Add bpm light changer
This commit is contained in:
parent
9b738c359d
commit
332d3e3b33
@ -15,7 +15,7 @@ set(CMAKE_CXX_STANDARD 23)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||
set(FETCHCONTENT_QUIET OFF)
|
||||
|
||||
add_executable(${PROJECT_NAME} main.cpp tinyfiledialogs.c)
|
||||
add_executable(${PROJECT_NAME} main.cpp tinyfiledialogs.c timeline.cpp)
|
||||
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
|
79
ImSequencer.h
Normal file
79
ImSequencer.h
Normal file
@ -0,0 +1,79 @@
|
||||
// https://github.com/CedricGuillemet/ImGuizmo
|
||||
// v 1.89 WIP
|
||||
//
|
||||
// The MIT License(MIT)
|
||||
//
|
||||
// Copyright(c) 2021 Cedric Guillemet
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files(the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions :
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
struct ImDrawList;
|
||||
struct ImRect;
|
||||
namespace ImSequencer
|
||||
{
|
||||
enum SEQUENCER_OPTIONS
|
||||
{
|
||||
SEQUENCER_EDIT_NONE = 0,
|
||||
SEQUENCER_EDIT_STARTEND = 1 << 1,
|
||||
SEQUENCER_CHANGE_FRAME = 1 << 3,
|
||||
SEQUENCER_ADD = 1 << 4,
|
||||
SEQUENCER_DEL = 1 << 5,
|
||||
SEQUENCER_COPYPASTE = 1 << 6,
|
||||
SEQUENCER_EDIT_ALL = SEQUENCER_EDIT_STARTEND | SEQUENCER_CHANGE_FRAME
|
||||
};
|
||||
|
||||
struct SequenceInterface
|
||||
{
|
||||
bool focused = false;
|
||||
virtual int GetFrameMin() const = 0;
|
||||
virtual int GetFrameMax() const = 0;
|
||||
virtual int GetItemCount() const = 0;
|
||||
|
||||
virtual void BeginEdit(int /*index*/) {}
|
||||
virtual void EndEdit() {}
|
||||
virtual int GetItemTypeCount() const { return 0; }
|
||||
virtual const char* GetItemTypeName(int /*typeIndex*/) const { return ""; }
|
||||
virtual const char* GetItemLabel(int /*index*/) const { return ""; }
|
||||
virtual const char* GetCollapseFmt() const { return "%d Frames / %d entries"; }
|
||||
|
||||
virtual void Get(int index, int** start, int** end, int* type, unsigned int* color) = 0;
|
||||
virtual void Add(int /*type*/) {}
|
||||
virtual void Del(int /*index*/) {}
|
||||
virtual void Duplicate(int /*index*/) {}
|
||||
|
||||
virtual void Copy() {}
|
||||
virtual void Paste() {}
|
||||
|
||||
virtual size_t GetCustomHeight(int /*index*/) { return 0; }
|
||||
virtual void DoubleClick(int /*index*/) {}
|
||||
virtual void CustomDraw(int /*index*/, ImDrawList* /*draw_list*/, const ImRect& /*rc*/, const ImRect& /*legendRect*/, const ImRect& /*clippingRect*/, const ImRect& /*legendClippingRect*/) {}
|
||||
virtual void CustomDrawCompact(int /*index*/, ImDrawList* /*draw_list*/, const ImRect& /*rc*/, const ImRect& /*clippingRect*/) {}
|
||||
|
||||
virtual ~SequenceInterface() = default;
|
||||
};
|
||||
|
||||
|
||||
// return true if selection is made
|
||||
bool Sequencer(SequenceInterface* sequence, int* currentFrame, bool* expanded, int* selectedEntry, int* firstFrame, int sequenceOptions);
|
||||
|
||||
}
|
148
main.cpp
148
main.cpp
@ -21,6 +21,7 @@ void sendDMXData(HANDLE hSerial, unsigned char* data, int length);
|
||||
void setupImGui(GLFWwindow* window);
|
||||
void renderImGui();
|
||||
void renderImGuiBpm();
|
||||
void renderTestImGui();
|
||||
|
||||
|
||||
// ui timeline stuff
|
||||
@ -34,6 +35,9 @@ float bpm = 120.0f; // Default BPM
|
||||
float zoom_level = 1.0f; // Zoom level
|
||||
float pan_offset = 0.0f; // Pan offset
|
||||
|
||||
// Calculate time per beat based on BPM
|
||||
float beat_interval = 60.0f / bpm;
|
||||
|
||||
// audio stuff
|
||||
ma_sound sound;
|
||||
ma_engine engine;
|
||||
@ -120,8 +124,10 @@ int main() {
|
||||
ImGui_ImplGlfw_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
renderImGui();
|
||||
renderImGuiBpm();
|
||||
// renderImGui();
|
||||
// renderImGuiBpm();
|
||||
|
||||
renderTestImGui();
|
||||
|
||||
ImGui::Render();
|
||||
|
||||
@ -346,9 +352,6 @@ void setupImGui(GLFWwindow* window) {
|
||||
}
|
||||
|
||||
void renderImGui() {
|
||||
// Calculate time per beat based on BPM
|
||||
float beat_interval = 60.0f / bpm;
|
||||
|
||||
// Temporary variables to hold the slider values
|
||||
int channel1 = buffer[0];
|
||||
int channel2 = buffer[1];
|
||||
@ -671,3 +674,138 @@ void renderImGuiBpm() {
|
||||
ImGui::End();
|
||||
|
||||
}
|
||||
|
||||
void renderTestImGui() {
|
||||
ImGui::Begin("Timeline");
|
||||
|
||||
|
||||
|
||||
// Time Slider (Timeline Position)
|
||||
ImGui::SliderFloat("Timeline Position", &timeline_position, 0.0f, timeline_duration, "%.2f sec");
|
||||
|
||||
// Custom timeline rendering with grid lines
|
||||
ImGui::Text("Timeline");
|
||||
ImGui::PushID("CustomTimeline");
|
||||
ImGui::BeginChild("##Timeline", ImVec2(ImGui::GetContentRegionAvail().x, 150), true);
|
||||
|
||||
// Draw grid lines for beats
|
||||
ImDrawList* draw_list = ImGui::GetWindowDrawList();
|
||||
ImVec2 cursor_pos = ImGui::GetCursorScreenPos();
|
||||
float timeline_width = ImGui::GetContentRegionAvail().x;
|
||||
|
||||
// Draw the audio waveform if loaded
|
||||
if (audioDataLoaded && !downsampledAudioSamples.empty()) {
|
||||
float timelineHeight = 100.0f; // Total height of the timeline
|
||||
float waveformHeight = timelineHeight / 2.0f; // Waveform takes half the height of the timeline
|
||||
float yOffset = cursor_pos.y + timelineHeight / 2.0f; // Center the waveform vertically
|
||||
|
||||
int sampleCount = static_cast<int>(downsampledAudioSamples.size()) / 2;
|
||||
|
||||
// Adjust the scaling to fit the timeline duration
|
||||
float pixelsPerSample = (timeline_width * zoom_level) / timeline_duration;
|
||||
|
||||
for (int i = 0; i < sampleCount - 1; ++i) {
|
||||
float x1 = cursor_pos.x + i * pixelsPerSample;
|
||||
float x2 = cursor_pos.x + (i + 1) * pixelsPerSample;
|
||||
|
||||
float y1_max = yOffset - (downsampledAudioSamples[i * 2] * waveformHeight);
|
||||
float y1_min = yOffset - (downsampledAudioSamples[i * 2 + 1] * waveformHeight);
|
||||
float y2_max = yOffset - (downsampledAudioSamples[(i + 1) * 2] * waveformHeight);
|
||||
float y2_min = yOffset - (downsampledAudioSamples[(i + 1) * 2 + 1] * waveformHeight);
|
||||
|
||||
draw_list->AddLine(ImVec2(x1, y1_max), ImVec2(x2, y2_max), IM_COL32(0, 255, 0, 255), 1.0f);
|
||||
draw_list->AddLine(ImVec2(x1, y1_min), ImVec2(x2, y2_min), IM_COL32(0, 255, 0, 255), 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i <= static_cast<int>(timeline_duration / beat_interval); ++i) {
|
||||
float beat_position = i * beat_interval * zoom_level - pan_offset;
|
||||
float x_position = cursor_pos.x + (beat_position / timeline_duration) * timeline_width;
|
||||
|
||||
if (x_position >= cursor_pos.x && x_position <= cursor_pos.x + timeline_width) {
|
||||
// Draw major beat line
|
||||
if (i % 4 == 0) {
|
||||
draw_list->AddLine(ImVec2(x_position, cursor_pos.y), ImVec2(x_position, cursor_pos.y + 100), IM_COL32(255, 0, 0, 255), 2.0f);
|
||||
}
|
||||
else {
|
||||
// Draw minor beat line
|
||||
draw_list->AddLine(ImVec2(x_position, cursor_pos.y), ImVec2(x_position, cursor_pos.y + 100), IM_COL32(255, 255, 255, 255), 1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Draw the current timeline position marker
|
||||
float position_marker = (timeline_position * zoom_level - pan_offset) / timeline_duration * timeline_width;
|
||||
draw_list->AddLine(ImVec2(cursor_pos.x + position_marker, cursor_pos.y), ImVec2(cursor_pos.x + position_marker, cursor_pos.y + 100), IM_COL32(0, 0, 255, 255), 2.0f);
|
||||
|
||||
// Allow adding markers with snapping to grid
|
||||
if (ImGui::Button("Add Marker")) {
|
||||
float snap_position = std::round(timeline_position / beat_interval) * beat_interval;
|
||||
markers.emplace_back(snap_position / timeline_duration, buffer[0], buffer[1], buffer[2]);
|
||||
}
|
||||
|
||||
// Add Random Marker button
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Add Random Marker")) {
|
||||
float snap_position = std::round(timeline_position / beat_interval) * beat_interval;
|
||||
|
||||
// Generate random colors
|
||||
unsigned char r = rand() % 256;
|
||||
unsigned char g = rand() % 256;
|
||||
unsigned char b = rand() % 256;
|
||||
|
||||
// Add the marker with random colors
|
||||
markers.emplace_back(snap_position / timeline_duration, r, g, b);
|
||||
}
|
||||
|
||||
// Draw markers on the timeline
|
||||
for (const auto& marker : markers) {
|
||||
float marker_position = std::get<0>(marker) * timeline_duration * zoom_level - pan_offset;
|
||||
float x_position = cursor_pos.x + (marker_position / timeline_duration) * timeline_width;
|
||||
|
||||
if (x_position >= cursor_pos.x && x_position <= cursor_pos.x + timeline_width) {
|
||||
draw_list->AddRectFilled(ImVec2(x_position - 2.0f, cursor_pos.y), ImVec2(x_position + 2.0f, cursor_pos.y + 100), IM_COL32(0, 255, 0, 255));
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndChild();
|
||||
ImGui::PopID();
|
||||
|
||||
// Playback logic: Update timeline position based on playback time
|
||||
if (is_playing) {
|
||||
current_time = static_cast<float>(glfwGetTime()) - playback_start_time;
|
||||
timeline_position = current_time;
|
||||
|
||||
for (const auto& marker : markers) {
|
||||
float marker_time = std::get<0>(marker) * timeline_duration;
|
||||
if (current_time >= marker_time && current_time < marker_time + 0.025f) {
|
||||
buffer[0] = std::get<1>(marker);
|
||||
buffer[1] = std::get<2>(marker);
|
||||
buffer[2] = std::get<3>(marker);
|
||||
}
|
||||
}
|
||||
|
||||
if (timeline_position >= timeline_duration) {
|
||||
is_playing = false;
|
||||
timeline_position = timeline_duration;
|
||||
if (audioLoaded) {
|
||||
ma_sound_stop(&sound);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Display added markers with their RGB values and time
|
||||
for (const auto& marker : markers) {
|
||||
float marker_time = std::get<0>(marker) * timeline_duration;
|
||||
ImGui::Text("Marker at %.2f sec: R=%d, G=%d, B=%d",
|
||||
marker_time,
|
||||
std::get<1>(marker),
|
||||
std::get<2>(marker),
|
||||
std::get<3>(marker));
|
||||
}
|
||||
|
||||
|
||||
|
||||
ImGui::End();
|
||||
}
|
33
notes.md
Normal file
33
notes.md
Normal file
@ -0,0 +1,33 @@
|
||||
https://github.com/epezent/implot
|
||||
licences for tinyfiledialog and miniaudio
|
||||
|
||||
Might need drigers?
|
||||
https://ftdichip.com/drivers/
|
||||
|
||||
On windows you can find the com port stuff using the `mode` command:
|
||||
```
|
||||
C:\Users\illyum>mode
|
||||
|
||||
Status for device COM3:
|
||||
-----------------------
|
||||
Baud: 1200
|
||||
Parity: None
|
||||
Data Bits: 7
|
||||
Stop Bits: 1
|
||||
Timeout: OFF
|
||||
XON/XOFF: OFF
|
||||
CTS handshaking: OFF
|
||||
DSR handshaking: OFF
|
||||
DSR sensitivity: OFF
|
||||
DTR circuit: ON
|
||||
RTS circuit: ON
|
||||
|
||||
|
||||
Status for device CON:
|
||||
----------------------
|
||||
Lines: 9001
|
||||
Columns: 135
|
||||
Keyboard rate: 31
|
||||
Keyboard delay: 1
|
||||
Code page: 437
|
||||
```
|
Loading…
x
Reference in New Issue
Block a user