Compare commits
5 Commits
c91bc60cb9
...
6e0cc49826
Author | SHA1 | Date | |
---|---|---|---|
![]() |
6e0cc49826 | ||
![]() |
f8341ff8f2 | ||
![]() |
0858e70121 | ||
![]() |
0f5c1da12f | ||
![]() |
3e73cd63bb |
@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.24)
|
|||||||
|
|
||||||
project(RaylibDmx)
|
project(RaylibDmx)
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 26)
|
set(CMAKE_CXX_STANDARD 23)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
# nvim/fleet users (ONLY WORKS WITH MINGW/NINJA BUILDERS)
|
# nvim/fleet users (ONLY WORKS WITH MINGW/NINJA BUILDERS)
|
||||||
@ -64,19 +64,22 @@ FetchContent_Declare(
|
|||||||
)
|
)
|
||||||
FetchContent_MakeAvailable(rlimgui)
|
FetchContent_MakeAvailable(rlimgui)
|
||||||
|
|
||||||
file(GLOB_RECURSE SOURCES "src/*.cpp")
|
# Add source files
|
||||||
add_executable(${PROJECT_NAME} ${SOURCES})
|
file(GLOB_RECURSE PROJECT_SOURCES CONFIGURE_DEPENDS "${CMAKE_CURRENT_LIST_DIR}/src/*.cpp")
|
||||||
|
set(PROJECT_INCLUDE "${CMAKE_CURRENT_LIST_DIR}/src")
|
||||||
|
|
||||||
target_link_libraries(${PROJECT_NAME} raylib)
|
# Declare the executable
|
||||||
|
add_executable(${PROJECT_NAME})
|
||||||
|
target_sources(${PROJECT_NAME} PRIVATE ${PROJECT_SOURCES})
|
||||||
|
target_include_directories(${PROJECT_NAME} PRIVATE ${PROJECT_INCLUDE})
|
||||||
|
|
||||||
set(RLIMGUI_SOURCES
|
# Link with Raylib
|
||||||
${rlimgui_SOURCE_DIR}/rlImGui.cpp
|
target_link_libraries(${PROJECT_NAME} PRIVATE raylib)
|
||||||
)
|
|
||||||
|
|
||||||
# Create rlImGui lib
|
# Create rlImGui library
|
||||||
add_library(rlImGui STATIC ${RLIMGUI_SOURCES})
|
add_library(rlImGui STATIC ${rlimgui_SOURCE_DIR}/rlImGui.cpp)
|
||||||
target_include_directories(rlImGui PUBLIC ${rlimgui_SOURCE_DIR} ${imgui_SOURCE_DIR})
|
target_include_directories(rlImGui PUBLIC ${rlimgui_SOURCE_DIR} ${imgui_SOURCE_DIR})
|
||||||
target_link_libraries(rlImGui raylib ImGui)
|
target_link_libraries(rlImGui PRIVATE raylib ImGui)
|
||||||
|
|
||||||
# Link ImGui and rlImGui
|
# Link ImGui and rlImGui with the executable
|
||||||
target_link_libraries(${PROJECT_NAME} ImGui rlImGui)
|
target_link_libraries(${PROJECT_NAME} PRIVATE ImGui rlImGui)
|
||||||
|
27
src/BasicLogger.cpp
Normal file
27
src/BasicLogger.cpp
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
//
|
||||||
|
// Created by illyum on 8/15/2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "BasicLogger.h"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
// Set default verbosity
|
||||||
|
LogPriority BasicLogger::verbosity = TraceP;
|
||||||
|
|
||||||
|
void BasicLogger::Log(LogPriority priority, const char *message) {
|
||||||
|
if (priority >= verbosity) {
|
||||||
|
switch (priority) {
|
||||||
|
case TraceP: std::cout << "Trace: \t"; break;
|
||||||
|
case DebugP: std::cout << "Debug: \t"; break;
|
||||||
|
case InfoP: std::cout << "Info: \t"; break;
|
||||||
|
case WarnP: std::cout << "Warn: \t"; break;
|
||||||
|
case ErrorP: std::cout << "Error: \t"; break;
|
||||||
|
case FatalP: std::cout << "Fatal: \t"; break;
|
||||||
|
}
|
||||||
|
std::cout << message << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BasicLogger::SetVerbosity(LogPriority new_priority) {
|
||||||
|
verbosity = new_priority;
|
||||||
|
}
|
22
src/BasicLogger.h
Normal file
22
src/BasicLogger.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
//
|
||||||
|
// Created by illyum on 8/15/2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef BASICLOGGER_H
|
||||||
|
#define BASICLOGGER_H
|
||||||
|
|
||||||
|
|
||||||
|
enum LogPriority {
|
||||||
|
TraceP, DebugP, InfoP, WarnP, ErrorP, FatalP
|
||||||
|
};
|
||||||
|
|
||||||
|
class BasicLogger {
|
||||||
|
private:
|
||||||
|
static LogPriority verbosity;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static void Log(LogPriority priority, const char *message);
|
||||||
|
static void SetVerbosity(LogPriority new_priority);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //BASICLOGGER_H
|
11
src/DmxWriter.cpp
Normal file
11
src/DmxWriter.cpp
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
//
|
||||||
|
// Created by illyum on 8/16/2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "DmxWriter.h"
|
||||||
|
|
||||||
|
DmxWriter::DmxWriter(DMXEngine& engine) : dmxEngine(engine) {}
|
||||||
|
|
||||||
|
void DmxWriter::setChannel(int channel, unsigned char value) {
|
||||||
|
dmxEngine.setChannelValue(channel, value);
|
||||||
|
}
|
19
src/DmxWriter.h
Normal file
19
src/DmxWriter.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
//
|
||||||
|
// Created by illyum on 8/16/2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef DMXWRITER_H
|
||||||
|
#define DMXWRITER_H
|
||||||
|
|
||||||
|
#include "dmx.h"
|
||||||
|
|
||||||
|
class DmxWriter {
|
||||||
|
public:
|
||||||
|
DmxWriter(DMXEngine& engine);
|
||||||
|
void setChannel(int channel, unsigned char value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
DMXEngine& dmxEngine;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // DMXWRITER_H
|
114
src/dmx.cpp
114
src/dmx.cpp
@ -1,3 +1,117 @@
|
|||||||
//
|
//
|
||||||
// Created by illyum on 8/15/2024.
|
// Created by illyum on 8/15/2024.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#include "dmx.h"
|
||||||
|
#include <iostream>
|
||||||
|
#include <chrono>
|
||||||
|
#include <thread>
|
||||||
|
#include "windows.h"
|
||||||
|
|
||||||
|
DMXEngine::DMXEngine(const char* portName, int baudRate, int dataSize)
|
||||||
|
: running(false), buffer(dataSize, 0) {
|
||||||
|
hSerial = CreateFileA(portName, GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
||||||
|
if (hSerial == INVALID_HANDLE_VALUE) {
|
||||||
|
std::cerr << "Error opening " << portName << " port" << std::endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
configurePort();
|
||||||
|
}
|
||||||
|
|
||||||
|
DMXEngine::~DMXEngine() {
|
||||||
|
if (running) {
|
||||||
|
stop();
|
||||||
|
}
|
||||||
|
CloseHandle(hSerial);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DMXEngine::configurePort() {
|
||||||
|
DCB dcbSerialParams = { 0 };
|
||||||
|
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
|
||||||
|
if (!GetCommState(hSerial, &dcbSerialParams)) {
|
||||||
|
std::cerr << "Error getting COM port state" << std::endl;
|
||||||
|
CloseHandle(hSerial);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
dcbSerialParams.BaudRate = 250000;
|
||||||
|
dcbSerialParams.ByteSize = 8;
|
||||||
|
dcbSerialParams.StopBits = TWOSTOPBITS;
|
||||||
|
dcbSerialParams.Parity = NOPARITY;
|
||||||
|
|
||||||
|
if (!SetCommState(hSerial, &dcbSerialParams)) {
|
||||||
|
std::cerr << "Error setting COM port state" << std::endl;
|
||||||
|
CloseHandle(hSerial);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
COMMTIMEOUTS timeouts = { 0 };
|
||||||
|
timeouts.ReadIntervalTimeout = 50;
|
||||||
|
timeouts.ReadTotalTimeoutConstant = 50;
|
||||||
|
timeouts.ReadTotalTimeoutMultiplier = 10;
|
||||||
|
timeouts.WriteTotalTimeoutConstant = 50;
|
||||||
|
timeouts.WriteTotalTimeoutMultiplier = 10;
|
||||||
|
|
||||||
|
if (!SetCommTimeouts(hSerial, &timeouts)) {
|
||||||
|
std::cerr << "Error setting COM port timeouts" << std::endl;
|
||||||
|
CloseHandle(hSerial);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DMXEngine::start() {
|
||||||
|
running = true;
|
||||||
|
dmxThread = std::thread(dmxThreadFunc, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DMXEngine::stop() {
|
||||||
|
running = false;
|
||||||
|
if (dmxThread.joinable()) {
|
||||||
|
dmxThread.join();
|
||||||
|
}
|
||||||
|
|
||||||
|
DMXEngine::dumpZeros();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DMXEngine::setChannelValue(int channel, unsigned char value) {
|
||||||
|
if (channel >= 0 && channel < buffer.size()) {
|
||||||
|
buffer[channel] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DMXEngine::sendDMXData() {
|
||||||
|
while (running) {
|
||||||
|
// Break condition
|
||||||
|
EscapeCommFunction(hSerial, SETBREAK);
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||||
|
EscapeCommFunction(hSerial, CLRBREAK);
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // MAB
|
||||||
|
|
||||||
|
DWORD bytesWritten;
|
||||||
|
unsigned char startCode = 0;
|
||||||
|
WriteFile(hSerial, &startCode, 1, &bytesWritten, NULL);
|
||||||
|
WriteFile(hSerial, buffer.data(), buffer.size(), &bytesWritten, NULL);
|
||||||
|
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(25));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DMXEngine::dumpZeros() {
|
||||||
|
std::fill(buffer.begin(), buffer.end(), 0);
|
||||||
|
|
||||||
|
EscapeCommFunction(hSerial, SETBREAK);
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||||
|
EscapeCommFunction(hSerial, CLRBREAK);
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // MAB
|
||||||
|
|
||||||
|
DWORD bytesWritten;
|
||||||
|
unsigned char startCode = 0;
|
||||||
|
WriteFile(hSerial, &startCode, 1, &bytesWritten, NULL);
|
||||||
|
WriteFile(hSerial, buffer.data(), buffer.size(), &bytesWritten, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DMXEngine::dmxThreadFunc(DMXEngine* engine) {
|
||||||
|
engine->sendDMXData();
|
||||||
|
}
|
||||||
|
37
src/dmx.h
37
src/dmx.h
@ -2,7 +2,38 @@
|
|||||||
// Created by illyum on 8/15/2024.
|
// Created by illyum on 8/15/2024.
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef RAYLIBDMX_DMX_H
|
#ifndef DMX_H
|
||||||
#define RAYLIBDMX_DMX_H
|
#define DMX_H
|
||||||
|
|
||||||
#endif //RAYLIBDMX_DMX_H
|
#include <vector>
|
||||||
|
#include <tuple>
|
||||||
|
#include <atomic>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
struct DMXFixture {
|
||||||
|
unsigned char r, g, b;
|
||||||
|
int channel;
|
||||||
|
};
|
||||||
|
|
||||||
|
class DMXEngine {
|
||||||
|
public:
|
||||||
|
explicit DMXEngine(const char* portName, int baudRate = 250000, int dataSize = 512);
|
||||||
|
~DMXEngine();
|
||||||
|
|
||||||
|
void start();
|
||||||
|
void stop();
|
||||||
|
void setChannelValue(int channel, unsigned char value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void sendDMXData();
|
||||||
|
void dumpZeros();
|
||||||
|
void configurePort();
|
||||||
|
static void dmxThreadFunc(DMXEngine* engine);
|
||||||
|
|
||||||
|
void* hSerial;
|
||||||
|
std::atomic<bool> running;
|
||||||
|
std::vector<unsigned char> buffer;
|
||||||
|
std::thread dmxThread;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // DMX_H
|
||||||
|
77
src/main.cpp
77
src/main.cpp
@ -2,20 +2,35 @@
|
|||||||
#include "rlImGui.h"
|
#include "rlImGui.h"
|
||||||
#include "panel.h"
|
#include "panel.h"
|
||||||
#include "imgui.h"
|
#include "imgui.h"
|
||||||
|
#include "dmx.h"
|
||||||
|
#include "DmxWriter.h"
|
||||||
|
#include "BasicLogger.h"
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <ctime>
|
||||||
|
|
||||||
|
void DrawImGui();
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
DMXEngine dmxEngine("\\\\.\\COM3");
|
||||||
|
dmxEngine.start();
|
||||||
|
DmxWriter dmxWriter(dmxEngine);
|
||||||
|
|
||||||
|
// Initialize random seed
|
||||||
|
srand(static_cast<unsigned int>(time(0)));
|
||||||
|
|
||||||
const int screenWidth = 1920;
|
const int screenWidth = 1920;
|
||||||
const int screenHeight = 1080;
|
const int screenHeight = 1080;
|
||||||
|
|
||||||
InitWindow(screenWidth, screenHeight, "DMX Raylib UI");
|
InitWindow(screenWidth, screenHeight, "DMX Raylib UI");
|
||||||
SetTargetFPS(60);
|
SetTargetFPS(165);
|
||||||
|
|
||||||
rlImGuiSetup(true); // Use true for dark theme, false for light theme
|
rlImGuiSetup(true);
|
||||||
|
|
||||||
Panel timelinePanel = {{0, 0, screenWidth * 0.75f, screenHeight * 0.6f}, "Timeline", LIGHTGRAY, DARKGRAY, true};
|
Panel timelinePanel = {{0, 0, screenWidth * 0.75f, screenHeight * 0.6f}, "Timeline", LIGHTGRAY, DARKGRAY, true};
|
||||||
Panel propertiesPanel = {{screenWidth * 0.75f, 0, screenWidth * 0.25f, screenHeight}, "Properties", LIGHTGRAY, DARKGRAY, true};
|
Panel propertiesPanel = {{screenWidth * 0.75f, 0, screenWidth * 0.25f, screenHeight}, "Properties", LIGHTGRAY, DARKGRAY, true};
|
||||||
|
|
||||||
|
std::string randomColors;
|
||||||
|
|
||||||
while (!WindowShouldClose()) {
|
while (!WindowShouldClose()) {
|
||||||
timelinePanel.Update();
|
timelinePanel.Update();
|
||||||
propertiesPanel.Update();
|
propertiesPanel.Update();
|
||||||
@ -23,20 +38,68 @@ int main() {
|
|||||||
BeginDrawing();
|
BeginDrawing();
|
||||||
ClearBackground(RAYWHITE);
|
ClearBackground(RAYWHITE);
|
||||||
|
|
||||||
rlImGuiBegin();
|
|
||||||
bool open = true;
|
|
||||||
ImGui::ShowDemoWindow(&open);
|
|
||||||
rlImGuiEnd();
|
|
||||||
|
|
||||||
if (timelinePanel.isVisible) timelinePanel.Draw();
|
if (timelinePanel.isVisible) timelinePanel.Draw();
|
||||||
if (propertiesPanel.isVisible) propertiesPanel.Draw();
|
if (propertiesPanel.isVisible) propertiesPanel.Draw();
|
||||||
|
|
||||||
|
rlImGuiBegin();
|
||||||
|
|
||||||
|
ImGui::Begin("Random Color Clicker");
|
||||||
|
if (ImGui::Button("Random Color!")) {
|
||||||
|
unsigned char r = static_cast<unsigned char>(rand() % 256);
|
||||||
|
unsigned char g = static_cast<unsigned char>(rand() % 256);
|
||||||
|
unsigned char b = static_cast<unsigned char>(rand() % 256);
|
||||||
|
|
||||||
|
dmxWriter.setChannel(0, r);
|
||||||
|
dmxWriter.setChannel(1, g);
|
||||||
|
dmxWriter.setChannel(2, b);
|
||||||
|
|
||||||
|
randomColors = "Sent DMX Color - R: " + std::to_string(r) +
|
||||||
|
", G: " + std::to_string(g) +
|
||||||
|
", B: " + std::to_string(b);
|
||||||
|
}
|
||||||
|
ImGui::Text("%s", randomColors.c_str());
|
||||||
|
|
||||||
|
// End the window
|
||||||
|
ImGui::End();
|
||||||
|
|
||||||
|
rlImGuiEnd();
|
||||||
|
|
||||||
|
// Draw FPS on the screen
|
||||||
DrawFPS(3, screenHeight - 20);
|
DrawFPS(3, screenHeight - 20);
|
||||||
EndDrawing();
|
EndDrawing();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BasicLogger::Log(DebugP, "Stopping DMX Engine...");
|
||||||
|
dmxEngine.stop();
|
||||||
|
|
||||||
|
BasicLogger::Log(DebugP, "Shutting down rlImGui...");
|
||||||
rlImGuiShutdown();
|
rlImGuiShutdown();
|
||||||
|
|
||||||
|
BasicLogger::Log(DebugP, "Closing Window...");
|
||||||
CloseWindow();
|
CloseWindow();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DrawImGui() {
|
||||||
|
rlImGuiBegin();
|
||||||
|
|
||||||
|
// Begin a new window with a title
|
||||||
|
ImGui::Begin("My Custom Window");
|
||||||
|
|
||||||
|
// Add a button with a label
|
||||||
|
if (ImGui::Button("Click Me"))
|
||||||
|
{
|
||||||
|
// Action to be performed when the button is clicked
|
||||||
|
ImGui::Text("Button Clicked!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// End the window
|
||||||
|
ImGui::End();
|
||||||
|
|
||||||
|
// bool open = true;
|
||||||
|
// ImGui::ShowDemoWindow(&open);
|
||||||
|
|
||||||
|
rlImGuiEnd();
|
||||||
|
}
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by illyum on 8/15/2024.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef RAYLIBDMX_WINAPI_WRAPPER_H
|
|
||||||
#define RAYLIBDMX_WINAPI_WRAPPER_H
|
|
||||||
|
|
||||||
#endif //RAYLIBDMX_WINAPI_WRAPPER_H
|
|
Loading…
x
Reference in New Issue
Block a user