task editor
This commit is contained in:
@@ -94,6 +94,9 @@ void init(DrawData& drawData, ApplicationData& appData)
|
||||
iconFontPath.append("\\remixicon.ttf");
|
||||
io.Fonts->AddFontFromFileTTF(iconFontPath.c_str(), 14.0f, &icons_config, icons_ranges);
|
||||
|
||||
// style
|
||||
loadUiStyle();
|
||||
|
||||
// Start timer thread
|
||||
std::thread timerThread(updateTimer, std::ref(appData));
|
||||
timerThread.detach();
|
||||
@@ -108,6 +111,8 @@ void init(DrawData& drawData, ApplicationData& appData)
|
||||
|
||||
void draw(DrawData& drawData, ApplicationData& appData)
|
||||
{
|
||||
const float panelGap = 0.f;
|
||||
|
||||
justDocked = false;
|
||||
appData.hoverTargetType = HoverTargetType::HOVER_TARGET_NONE;
|
||||
|
||||
@@ -127,7 +132,7 @@ void draw(DrawData& drawData, ApplicationData& appData)
|
||||
ImGui::SetNextWindowPos(ImVec2(0, customYCursor));
|
||||
ImGui::SetNextWindowSize(ImVec2(viewportSize.x, 0));
|
||||
customYCursor += checklistWindow(appData, std::format(" {} Checklist", ICON_CHECK_FILL).c_str()).y;
|
||||
customYCursor += 5.;
|
||||
customYCursor += panelGap;
|
||||
|
||||
// Timer
|
||||
ImGui::SetNextWindowPos(ImVec2(0, customYCursor));
|
||||
@@ -138,13 +143,13 @@ void draw(DrawData& drawData, ApplicationData& appData)
|
||||
ImGui::SetNextWindowPos(ImVec2(viewportSize.x / 2.f, customYCursor));
|
||||
ImGui::SetNextWindowSize(ImVec2(viewportSize.x / 2.f, 0));
|
||||
customYCursor += baseStationWindow(appData).y;
|
||||
customYCursor += 5.;
|
||||
customYCursor += panelGap;
|
||||
|
||||
// Playback Devices
|
||||
ImGui::SetNextWindowPos(ImVec2(0, customYCursor));
|
||||
ImGui::SetNextWindowSize(ImVec2(viewportSize.x, 0));
|
||||
customYCursor += audioDeviceWindow(appData, appData.audioData->playbackDevices, std::format(" {} Playback", ICON_HEADPHONE_FILL).c_str()).y;
|
||||
customYCursor += 5.;
|
||||
customYCursor += panelGap;
|
||||
|
||||
// Recording devices
|
||||
ImGui::SetNextWindowPos(ImVec2(0, customYCursor));
|
||||
@@ -179,6 +184,12 @@ void cleanup(DrawData& drawData, ApplicationData& appData)
|
||||
cleanupShell(drawData);
|
||||
}
|
||||
|
||||
float getButtonWidth(const char* label)
|
||||
{
|
||||
ImVec2 labelSize = ImGui::CalcTextSize(label);
|
||||
return labelSize.x + ImGui::GetStyle().FramePadding.x * 2.f;
|
||||
}
|
||||
|
||||
ImVec2 menuBar(DrawData& drawData, ApplicationData& appData)
|
||||
{
|
||||
ImVec2 size{};
|
||||
@@ -219,7 +230,7 @@ ImVec2 menuBar(DrawData& drawData, ApplicationData& appData)
|
||||
{
|
||||
ImVec2 availableSpace = ImGui::GetContentRegionAvail();
|
||||
ImVec2 cursorPos = ImGui::GetCursorPos();
|
||||
ImGui::SetCursorPosX(cursorPos.x + availableSpace.x - 47.);
|
||||
ImGui::SetCursorPosX(cursorPos.x + availableSpace.x - getButtonWidth(ICON_SUBTRACT_FILL) * 2.f);
|
||||
|
||||
if (ImGui::SmallButton(ICON_SUBTRACT_FILL))
|
||||
{
|
||||
@@ -270,7 +281,7 @@ bool windowHeaderButton(const char* id)
|
||||
ImVec2 windowMax = ImGui::GetWindowContentRegionMax();
|
||||
ImGui::PopClipRect();
|
||||
|
||||
ImGui::SetCursorPos({ windowMax.x - 20.f, tempPos.y - 28.f });
|
||||
ImGui::SetCursorPos({ windowMax.x - getButtonWidth(ICON_CLOSE_FILL), tempPos.y - 30.f});
|
||||
bool result = ImGui::SmallButton(id);
|
||||
|
||||
ImGui::PushClipRect(tempRect.Min, tempRect.Max, false);
|
||||
@@ -441,11 +452,11 @@ ImVec2 timerWindow(DrawData& drawData, ApplicationData& appData)
|
||||
{
|
||||
if (timerData.timerHasNotified)
|
||||
{
|
||||
formatTime(timerData.timerStartTimestamp + std::chrono::seconds((int)appData.settings.timerDuration), timeStr, sizeof(timeStr));
|
||||
timerText = std::format("Ended at {}", timeStr);
|
||||
}
|
||||
else
|
||||
{
|
||||
formatTime(timerData.timerStartTimestamp + std::chrono::seconds((int)appData.settings.timerDuration), timeStr, sizeof(timeStr));
|
||||
timerText = std::format("Ended at {}", timeStr);
|
||||
}
|
||||
else
|
||||
{
|
||||
formatTime(appData.timerData.timerStartTimestamp + std::chrono::seconds((int)appData.settings.timerDuration), timeStr, sizeof(timeStr));
|
||||
timerText = std::format("Ends at {}", timeStr);
|
||||
}
|
||||
@@ -531,12 +542,18 @@ ImVec2 checklistWindow(ApplicationData& appData, const char* title)
|
||||
|
||||
std::vector<time_t>& taskDates = appData.settings.tasks[taskName];
|
||||
bool taskDone = std::any_of(taskDates.begin(), taskDates.end(), selectedDayMatcher);
|
||||
bool highlightButton = false;
|
||||
std::string hoverText = "";
|
||||
|
||||
if (taskDates.size() > 0)
|
||||
{
|
||||
time_t mostRecentDoneDate = *std::max_element(taskDates.begin(), taskDates.end());
|
||||
double timeDiffSeconds = difftime(today, getDayStartOf(mostRecentDoneDate));
|
||||
int timeDiffDays = timeDiffSeconds / (60 * 60 * 24);
|
||||
highlightButton = timeDiffDays > appData.checklistHighlightDurationDays;
|
||||
hoverText = std::format("{}", timeDiffDays);
|
||||
}
|
||||
|
||||
time_t mostRecentDoneDate = *std::max_element(taskDates.begin(), taskDates.end());
|
||||
double timeDiffSeconds = difftime(today, getDayStartOf(mostRecentDoneDate));
|
||||
int timeDiffDays = timeDiffSeconds / (60 * 60 * 24);
|
||||
|
||||
bool highlightButton = timeDiffDays > appData.checklistHighlightDurationDays;
|
||||
if (highlightButton)
|
||||
{
|
||||
ImGui::PushStyleColor(ImGuiCol_FrameBg, { .5f, .2f, .15f, 0.54f });
|
||||
@@ -545,7 +562,8 @@ ImVec2 checklistWindow(ApplicationData& appData, const char* title)
|
||||
}
|
||||
|
||||
ImVec2 beforeCheckbox = ImGui::GetCursorScreenPos();
|
||||
if (ImGui::Checkbox(taskName.c_str(), &taskDone))
|
||||
std::string checkboxText = std::format("{}##taskcheck{}", taskName.c_str(), taskName.c_str());
|
||||
if (ImGui::Checkbox(checkboxText.c_str(), &taskDone))
|
||||
{
|
||||
if (taskDone)
|
||||
{
|
||||
@@ -563,11 +581,10 @@ ImVec2 checklistWindow(ApplicationData& appData, const char* title)
|
||||
ImGui::PopStyleColor(3);
|
||||
|
||||
ImVec2 afterCheckbox = ImGui::GetCursorScreenPos();
|
||||
std::string dayText = std::format("{}", timeDiffDays);
|
||||
float textWidth = ImGui::CalcTextSize(dayText.c_str()).x;
|
||||
float textWidth = ImGui::CalcTextSize(hoverText.c_str()).x;
|
||||
ImGui::SetCursorScreenPos({ beforeCheckbox.x + ImGui::GetFrameHeight() / 2.f - textWidth / 2.f, beforeCheckbox.y });
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, { 1.f, 1.f, 1.f, 1.f });
|
||||
ImGui::Text(dayText.c_str());
|
||||
ImGui::Text(hoverText.c_str());
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::SetCursorScreenPos(afterCheckbox);
|
||||
}
|
||||
@@ -575,9 +592,37 @@ ImVec2 checklistWindow(ApplicationData& appData, const char* title)
|
||||
|
||||
if (ImGui::BeginPopup(SETTINGS_POPUP_NAME))
|
||||
{
|
||||
ImGui::Text("Task Highlight Duration");
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::PushItemWidth(75.f);
|
||||
ImGui::DragInt("Task highlight duration", &appData.checklistHighlightDurationDays, .05f, 1, 7, "%d days");
|
||||
ImGui::DragInt("##taskduration", &appData.checklistHighlightDurationDays, .05f, 1, 7, "%d days");
|
||||
ImGui::PopItemWidth();
|
||||
|
||||
ImGui::Text("Tasks");
|
||||
auto taskIterator = appData.settings.taskNames.begin();
|
||||
while (taskIterator != appData.settings.taskNames.end())
|
||||
{
|
||||
size_t taskIndex = taskIterator - appData.settings.taskNames.begin();
|
||||
std::string& taskName = *taskIterator;
|
||||
taskName.reserve(128);
|
||||
ImGui::InputText(std::format("##taskinput{}", taskIndex).c_str(), taskName.data(), taskName.capacity());
|
||||
ImGui::SameLine();
|
||||
if (ImGui::SmallButton(std::format("{}##deltask{}", ICON_CLOSE_FILL, taskIndex).c_str()))
|
||||
{
|
||||
taskIterator = appData.settings.taskNames.erase(taskIterator);
|
||||
}
|
||||
else
|
||||
{
|
||||
taskIterator++;
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::Button(ICON_ADD_FILL))
|
||||
{
|
||||
appData.settings.taskNames.push_back("");
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
@@ -587,8 +632,21 @@ ImVec2 checklistWindow(ApplicationData& appData, const char* title)
|
||||
return size;
|
||||
}
|
||||
|
||||
void startBaseStationProc(const char* args, DWORD flags = 0)
|
||||
void startBaseStationProc(ApplicationData& appData, const char* args, DWORD flags = 0)
|
||||
{
|
||||
if (appData.lighthouseProcActive) return;
|
||||
appData.lighthouseProcActive = true;
|
||||
|
||||
SECURITY_ATTRIBUTES saAttr;
|
||||
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||
saAttr.bInheritHandle = TRUE;
|
||||
saAttr.lpSecurityDescriptor = NULL;
|
||||
|
||||
HANDLE exeOutWrite;
|
||||
HANDLE exeOutRead;
|
||||
CreatePipe(&exeOutRead, &exeOutWrite, &saAttr, 0);
|
||||
SetHandleInformation(exeOutRead, HANDLE_FLAG_INHERIT, 0);
|
||||
|
||||
// additional information
|
||||
STARTUPINFOA si;
|
||||
PROCESS_INFORMATION pi;
|
||||
@@ -596,14 +654,33 @@ void startBaseStationProc(const char* args, DWORD flags = 0)
|
||||
// set the size of the structures
|
||||
ZeroMemory(&si, sizeof(si));
|
||||
si.cb = sizeof(si);
|
||||
si.hStdOutput = exeOutWrite;
|
||||
si.dwFlags = STARTF_USESTDHANDLES;
|
||||
ZeroMemory(&pi, sizeof(pi));
|
||||
|
||||
// start the program up
|
||||
CreateProcessA("lighthouse-v2-manager.exe", const_cast<LPSTR>(args), NULL, NULL, FALSE, flags, NULL, NULL, &si, &pi);
|
||||
CreateProcessA("lighthouse-v2-manager.exe", const_cast<LPSTR>(args), NULL, NULL, true, flags, NULL, NULL, &si, &pi);
|
||||
|
||||
WaitForSingleObject(pi.hProcess, INFINITE);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
constexpr size_t BUFFER_SIZE = 4096;
|
||||
char readBuffer[BUFFER_SIZE]{};
|
||||
DWORD readCount = 0;
|
||||
bool readSuccess = ReadFile(exeOutRead, readBuffer, BUFFER_SIZE, &readCount, NULL);
|
||||
if (!readSuccess || readCount == 0) break;
|
||||
|
||||
std::cout << readBuffer << std::endl;
|
||||
}
|
||||
|
||||
// Close process and thread handles.
|
||||
CloseHandle(pi.hProcess);
|
||||
CloseHandle(pi.hThread);
|
||||
CloseHandle(exeOutWrite);
|
||||
CloseHandle(exeOutRead);
|
||||
|
||||
appData.lighthouseProcActive = false;
|
||||
}
|
||||
|
||||
ImVec2 baseStationWindow(ApplicationData& appData)
|
||||
@@ -623,7 +700,7 @@ ImVec2 baseStationWindow(ApplicationData& appData)
|
||||
params.append(" ");
|
||||
params.append(mac.c_str());
|
||||
}
|
||||
startBaseStationProc(params.c_str(), appData.settings.baseStationShowConsole ? CREATE_NEW_CONSOLE : CREATE_NO_WINDOW);
|
||||
startBaseStationProc(appData, params.c_str(), appData.settings.baseStationShowConsole ? CREATE_NEW_CONSOLE : CREATE_NO_WINDOW);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Shutdown"))
|
||||
@@ -634,7 +711,7 @@ ImVec2 baseStationWindow(ApplicationData& appData)
|
||||
params.append(" ");
|
||||
params.append(mac.c_str());
|
||||
}
|
||||
startBaseStationProc(params.c_str(), appData.settings.baseStationShowConsole ? CREATE_NEW_CONSOLE : CREATE_NO_WINDOW);
|
||||
startBaseStationProc(appData, params.c_str(), appData.settings.baseStationShowConsole ? CREATE_NEW_CONSOLE : CREATE_NO_WINDOW);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -643,7 +720,7 @@ ImVec2 baseStationWindow(ApplicationData& appData)
|
||||
ImGui::Checkbox("Show Console", &appData.settings.baseStationShowConsole);
|
||||
if (ImGui::Button("Search"))
|
||||
{
|
||||
startBaseStationProc("discover");
|
||||
startBaseStationProc(appData, "discover");
|
||||
// TODO: parse stuff (annoying)
|
||||
}
|
||||
ImGui::Text(std::format("Known: {}", appData.settings.baseStationMacAdresses.size()).c_str());
|
||||
@@ -664,11 +741,12 @@ ImVec2 audioDeviceWindow(ApplicationData& appData, std::vector<AudioDevice>& dev
|
||||
ImGui::OpenPopup(SETTINGS_POPUP_NAME);
|
||||
}
|
||||
|
||||
if (ImGui::BeginTable("DeviceTable", 3, ImGuiTableFlags_Resizable | ImGuiTableFlags_Borders | ImGuiTableFlags_NoSavedSettings))
|
||||
if (ImGui::BeginTable("DeviceTable", 4, ImGuiTableFlags_Resizable | ImGuiTableFlags_Borders | ImGuiTableFlags_NoSavedSettings))
|
||||
{
|
||||
ImGui::TableSetupColumn("Devices", ImGuiTableColumnFlags_WidthStretch, 3.);
|
||||
ImGui::TableSetupColumn("Volume", ImGuiTableColumnFlags_WidthStretch, 1.);
|
||||
ImGui::TableSetupColumn("Defaults", ImGuiTableColumnFlags_WidthFixed, 55.);
|
||||
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, getButtonWidth(ICON_MUSIC_2_FILL));
|
||||
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, getButtonWidth(ICON_PHONE_FILL));
|
||||
ImGui::TableHeadersRow();
|
||||
|
||||
for (auto& dev : deviceList)
|
||||
@@ -756,22 +834,31 @@ ImVec2 audioDeviceWindow(ApplicationData& appData, std::vector<AudioDevice>& dev
|
||||
}
|
||||
|
||||
// Defaults
|
||||
const float circleSize = 5.f;
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
if (dev.state == DEVICE_STATE_ACTIVE)
|
||||
{
|
||||
if (dev.isDefaultConsole)
|
||||
{
|
||||
drawCircle(5, IM_COL32(50, 50, 222, 255));
|
||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + getButtonWidth(ICON_MUSIC_2_FILL) / 2.f - circleSize);
|
||||
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 4.f);
|
||||
drawCircle(circleSize, IM_COL32(50, 50, 222, 255));
|
||||
}
|
||||
if (customButton("bn_d_", deviceIdUtf8.c_str(), ICON_MUSIC_2_FILL, !dev.isDefaultConsole))
|
||||
{
|
||||
setDefaultAudioDevice(*appData.audioData, dev.id.c_str(), ERole::eConsole);
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
ImGui::TableNextColumn();
|
||||
if (dev.state == DEVICE_STATE_ACTIVE)
|
||||
{
|
||||
if (dev.isDefaultCommunication)
|
||||
{
|
||||
drawCircle(5, IM_COL32(222, 50, 50, 255));
|
||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + getButtonWidth(ICON_PHONE_FILL) / 2.f - circleSize);
|
||||
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 4.f);
|
||||
drawCircle(circleSize, IM_COL32(222, 50, 50, 255));
|
||||
}
|
||||
if (customButton("bn_c_", deviceIdUtf8.c_str(), ICON_PHONE_FILL, !dev.isDefaultCommunication))
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user