356 lines
11 KiB
C++
356 lines
11 KiB
C++
#define IMGUI_DEFINE_MATH_OPERATORS
|
|
#include "parameter_edit_dialog.h"
|
|
#include "../app.h"
|
|
#include "../types.h"
|
|
#include "parameter_node.h"
|
|
#include <imgui.h>
|
|
#include <imgui_node_editor.h>
|
|
|
|
namespace ed = ax::NodeEditor;
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Parameter Edit Dialog
|
|
//------------------------------------------------------------------------------
|
|
static bool s_ParameterEditDialogOpen = false;
|
|
static Node* s_EditingParameterNode = nullptr;
|
|
static App* s_EditingParameterApp = nullptr;
|
|
|
|
void OpenParameterEditDialog(Node* node, App* app)
|
|
{
|
|
s_EditingParameterNode = node;
|
|
s_EditingParameterApp = app;
|
|
s_ParameterEditDialogOpen = true;
|
|
}
|
|
|
|
void RenderParameterEditDialog()
|
|
{
|
|
if (!s_ParameterEditDialogOpen || !s_EditingParameterNode || !s_EditingParameterApp)
|
|
return;
|
|
|
|
// Suspend node editor and disable shortcuts to prevent input conflicts
|
|
ed::Suspend();
|
|
ed::EnableShortcuts(false);
|
|
|
|
// Center modal window
|
|
ImVec2 center = ImGui::GetMainViewport()->GetCenter();
|
|
ImGui::SetNextWindowPos(center, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
|
|
ImGui::SetNextWindowSize(ImVec2(400, 0), ImGuiCond_Appearing);
|
|
|
|
// Open popup if not already open
|
|
if (!ImGui::IsPopupOpen("Edit Parameter", ImGuiPopupFlags_AnyPopupId))
|
|
ImGui::OpenPopup("Edit Parameter");
|
|
|
|
// Use proper modal flags
|
|
bool isOpen = s_ParameterEditDialogOpen;
|
|
if (!ImGui::BeginPopupModal("Edit Parameter", &isOpen, ImGuiWindowFlags_AlwaysAutoResize))
|
|
{
|
|
if (!isOpen)
|
|
s_ParameterEditDialogOpen = false;
|
|
ed::EnableShortcuts(true);
|
|
ed::Resume();
|
|
return;
|
|
}
|
|
|
|
// Update our state if popup was closed via X button
|
|
if (!isOpen)
|
|
{
|
|
s_ParameterEditDialogOpen = false;
|
|
ImGui::EndPopup();
|
|
ed::EnableShortcuts(true);
|
|
ed::Resume();
|
|
return;
|
|
}
|
|
|
|
// Handle ESC to close (only if not typing in an input field)
|
|
if (!ImGui::IsAnyItemActive() && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Escape)))
|
|
{
|
|
s_ParameterEditDialogOpen = false;
|
|
ImGui::CloseCurrentPopup();
|
|
ImGui::EndPopup();
|
|
ed::EnableShortcuts(true);
|
|
ed::Resume();
|
|
return;
|
|
}
|
|
|
|
if (s_EditingParameterNode->Type != NodeType::Parameter || !s_EditingParameterNode->ParameterInstance)
|
|
{
|
|
ImGui::Text("Error: Not a parameter node");
|
|
if (ImGui::Button("Close"))
|
|
{
|
|
s_ParameterEditDialogOpen = false;
|
|
ImGui::CloseCurrentPopup();
|
|
}
|
|
ImGui::EndPopup();
|
|
ed::EnableShortcuts(true);
|
|
ed::Resume();
|
|
return;
|
|
}
|
|
|
|
auto* paramInstance = s_EditingParameterNode->ParameterInstance;
|
|
|
|
// Parameter Name
|
|
ImGui::Text("Parameter Name:");
|
|
ImGui::SameLine();
|
|
ImGui::PushItemWidth(200.0f);
|
|
static std::map<int, std::string> nameBuffers;
|
|
int nodeId = s_EditingParameterNode->ID.Get();
|
|
if (nameBuffers.find(nodeId) == nameBuffers.end())
|
|
{
|
|
nameBuffers[nodeId] = s_EditingParameterNode->Name;
|
|
}
|
|
|
|
char nameBuffer[128];
|
|
strncpy(nameBuffer, nameBuffers[nodeId].c_str(), 127);
|
|
nameBuffer[127] = '\0';
|
|
|
|
if (ImGui::InputText("##param_name", nameBuffer, 128))
|
|
{
|
|
nameBuffers[nodeId] = nameBuffer;
|
|
s_EditingParameterNode->Name = nameBuffer;
|
|
paramInstance->SetName(nameBuffer);
|
|
|
|
// Sync to source or shortcuts
|
|
if (paramInstance->IsSource())
|
|
paramInstance->SyncNameToAllShortcuts(*s_EditingParameterNode, s_EditingParameterApp);
|
|
else if (paramInstance->GetSourceID() > 0)
|
|
paramInstance->SyncNameToSource(s_EditingParameterApp);
|
|
}
|
|
ImGui::PopItemWidth();
|
|
|
|
ImGui::Separator();
|
|
ImGui::Spacing();
|
|
|
|
// Parameter Type (editable combo)
|
|
ImGui::Text("Type:");
|
|
ImGui::SameLine();
|
|
ImGui::PushItemWidth(150.0f);
|
|
|
|
static std::map<int, int> typeIndices; // Per-node type index
|
|
|
|
const char* typeItems[] = { "Bool", "Int", "Float", "String" };
|
|
PinType typeValues[] = { PinType::Bool, PinType::Int, PinType::Float, PinType::String };
|
|
const int typeCount = 4;
|
|
|
|
// Initialize type index if needed
|
|
if (typeIndices.find(nodeId) == typeIndices.end())
|
|
{
|
|
// Find current type in the array
|
|
for (int i = 0; i < typeCount; i++)
|
|
{
|
|
if (typeValues[i] == s_EditingParameterNode->ParameterType)
|
|
{
|
|
typeIndices[nodeId] = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
int currentTypeIndex = typeIndices[nodeId];
|
|
if (ImGui::Combo("##param_type_combo", ¤tTypeIndex, typeItems, typeCount))
|
|
{
|
|
typeIndices[nodeId] = currentTypeIndex;
|
|
PinType newType = typeValues[currentTypeIndex];
|
|
|
|
// Update parameter type
|
|
s_EditingParameterNode->ParameterType = newType;
|
|
paramInstance->SetType(newType);
|
|
|
|
// Clear all input pins and rebuild
|
|
s_EditingParameterNode->Inputs.clear();
|
|
s_EditingParameterNode->Outputs.clear();
|
|
paramInstance->Build(*s_EditingParameterNode, s_EditingParameterApp);
|
|
|
|
// Initialize default value for the new type
|
|
switch (newType)
|
|
{
|
|
case PinType::Bool:
|
|
s_EditingParameterNode->BoolValue = false;
|
|
paramInstance->SetBool(false);
|
|
break;
|
|
case PinType::Int:
|
|
s_EditingParameterNode->IntValue = 0;
|
|
paramInstance->SetInt(0);
|
|
break;
|
|
case PinType::Float:
|
|
s_EditingParameterNode->FloatValue = 0.0f;
|
|
paramInstance->SetFloat(0.0f);
|
|
break;
|
|
case PinType::String:
|
|
s_EditingParameterNode->StringValue = "";
|
|
paramInstance->SetString("");
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
ImGui::PopItemWidth();
|
|
|
|
ImGui::Separator();
|
|
ImGui::Spacing();
|
|
|
|
// Value Editor
|
|
ImGui::Text("Value:");
|
|
ImGui::PushItemWidth(200.0f);
|
|
|
|
bool valueChanged = false;
|
|
switch (s_EditingParameterNode->ParameterType)
|
|
{
|
|
case PinType::Bool:
|
|
if (ImGui::Checkbox("##value", &s_EditingParameterNode->BoolValue))
|
|
{
|
|
paramInstance->SetBool(s_EditingParameterNode->BoolValue);
|
|
valueChanged = true;
|
|
}
|
|
break;
|
|
|
|
case PinType::Int:
|
|
if (ImGui::DragInt("##value", &s_EditingParameterNode->IntValue, 1.0f))
|
|
{
|
|
paramInstance->SetInt(s_EditingParameterNode->IntValue);
|
|
valueChanged = true;
|
|
}
|
|
break;
|
|
|
|
case PinType::Float:
|
|
if (ImGui::DragFloat("##value", &s_EditingParameterNode->FloatValue, 0.01f))
|
|
{
|
|
paramInstance->SetFloat(s_EditingParameterNode->FloatValue);
|
|
valueChanged = true;
|
|
}
|
|
break;
|
|
|
|
case PinType::String:
|
|
{
|
|
static std::map<int, std::string> stringBuffers;
|
|
if (stringBuffers.find(nodeId) == stringBuffers.end())
|
|
{
|
|
stringBuffers[nodeId] = s_EditingParameterNode->StringValue;
|
|
}
|
|
|
|
char strBuffer[256];
|
|
strncpy(strBuffer, stringBuffers[nodeId].c_str(), 255);
|
|
strBuffer[255] = '\0';
|
|
|
|
if (ImGui::InputText("##value", strBuffer, 256))
|
|
{
|
|
stringBuffers[nodeId] = strBuffer;
|
|
s_EditingParameterNode->StringValue = strBuffer;
|
|
paramInstance->SetString(strBuffer);
|
|
valueChanged = true;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
ImGui::Text("Unknown type");
|
|
break;
|
|
}
|
|
|
|
// Sync value if changed
|
|
if (valueChanged)
|
|
{
|
|
if (paramInstance->IsSource())
|
|
paramInstance->SyncValueToAllShortcuts(*s_EditingParameterNode, s_EditingParameterApp);
|
|
else if (paramInstance->GetSourceID() > 0)
|
|
paramInstance->SyncValueToSource(s_EditingParameterApp);
|
|
}
|
|
|
|
ImGui::PopItemWidth();
|
|
|
|
ImGui::Separator();
|
|
ImGui::Spacing();
|
|
|
|
// Display Mode
|
|
ImGui::Text("Display Mode:");
|
|
auto currentMode = paramInstance->GetDisplayMode();
|
|
const char* modeNames[] = {"Name Only", "Name + Value", "Small Box", "Minimal", "Minimal Links"};
|
|
int currentModeIndex = static_cast<int>(currentMode);
|
|
|
|
ImGui::PushItemWidth(200.0f);
|
|
if (ImGui::Combo("##display_mode", ¤tModeIndex, modeNames, 5))
|
|
{
|
|
paramInstance->SetDisplayMode(static_cast<ParameterDisplayMode>(currentModeIndex));
|
|
// Notify editor that display mode changed
|
|
ed::NotifyBlockDisplayModeChanged(s_EditingParameterNode->ID);
|
|
}
|
|
ImGui::PopItemWidth();
|
|
|
|
ImGui::Separator();
|
|
ImGui::Spacing();
|
|
|
|
// Source/Shortcut Settings
|
|
ImGui::Text("Source/Shortcut:");
|
|
|
|
// Only allow marking as source if not already a shortcut
|
|
if (paramInstance->GetSourceID() == 0)
|
|
{
|
|
bool isSource = paramInstance->IsSource();
|
|
if (ImGui::Checkbox("Mark as Source", &isSource))
|
|
{
|
|
paramInstance->SetIsSource(isSource);
|
|
if (!isSource)
|
|
{
|
|
paramInstance->SetSourceID(0);
|
|
}
|
|
}
|
|
|
|
if (ImGui::IsItemHovered())
|
|
ImGui::SetTooltip("Source parameters can have shortcuts created from them");
|
|
}
|
|
else
|
|
{
|
|
// This is a shortcut - show source info
|
|
ImGui::TextDisabled("This is a shortcut to source: %d", paramInstance->GetSourceID());
|
|
if (ImGui::Button("Clear Shortcut Reference"))
|
|
{
|
|
paramInstance->SetSourceID(0);
|
|
paramInstance->SetIsSource(false);
|
|
}
|
|
}
|
|
|
|
ImGui::Separator();
|
|
ImGui::Spacing();
|
|
|
|
// Buttons
|
|
bool confirmPressed = false;
|
|
if (ImGui::Button("Confirm (Enter)", ImVec2(120, 0)))
|
|
{
|
|
confirmPressed = true;
|
|
}
|
|
ImGui::SameLine();
|
|
if (ImGui::Button("Cancel (Esc)", ImVec2(120, 0)))
|
|
{
|
|
s_ParameterEditDialogOpen = false;
|
|
ImGui::CloseCurrentPopup();
|
|
}
|
|
|
|
// Handle Enter key to confirm (only if not typing in an input field)
|
|
if (!ImGui::IsAnyItemActive() && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Enter)))
|
|
{
|
|
confirmPressed = true;
|
|
}
|
|
|
|
if (confirmPressed)
|
|
{
|
|
// Save graph
|
|
auto* activeContainer = s_EditingParameterApp->GetActiveRootContainer();
|
|
if (activeContainer)
|
|
{
|
|
s_EditingParameterApp->SaveGraph(s_EditingParameterApp->m_GraphFilename, activeContainer);
|
|
}
|
|
s_ParameterEditDialogOpen = false;
|
|
ImGui::CloseCurrentPopup();
|
|
}
|
|
|
|
ImGui::EndPopup();
|
|
|
|
// Resume node editor and re-enable shortcuts
|
|
ed::EnableShortcuts(true);
|
|
ed::Resume();
|
|
}
|
|
|
|
bool IsParameterEditDialogOpen()
|
|
{
|
|
return s_ParameterEditDialogOpen;
|
|
}
|
|
|