Ember
Loading...
Searching...
No Matches
PropertiesTab.cpp
Go to the documentation of this file.
1#include "Tabs/PropertiesTab.h"
2#include "App/MainFrame.h"
4#include "Utils/Logger.h"
5
7 EVT_PG_CHANGED(wxID_ANY, PropertiesTab::OnPropertyChanged)
8 EVT_PG_CHANGING(wxID_ANY, PropertiesTab::OnPropertyChanging) wxEND_EVENT_TABLE()
9
10 PropertiesTab::PropertiesTab(wxWindow *parent, MainFrame *mainFrame)
11 : PropertiesTabBase(parent), m_node(nullptr), m_mainFrame(mainFrame) {
12 SetSelectionHighlightColor(EmberForge::AppPreferencesManager::GetAccentColor());
13 InitLayout();
14}
15
17 if (m_mainFrame) {
18 m_mainFrame->OnPropertiesTabClosed();
19 }
20}
21
23
24void PropertiesTab::CreateContentLayout(wxPanel *contentPanel) {
25 SetupPropertyGrid(contentPanel);
26
27 wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL);
28 sizer->Add(m_propertyGrid, 1, wxEXPAND | wxALL, 5);
29 contentPanel->SetSizer(sizer);
30}
31
33 m_node = node;
34 m_selectedNode = nullptr;
35
36 if (node) {
37 LOG_INFO("Properties",
38 wxString::Format("Selected node: %s (ID: %zu)", node->GetName(), node->GetId()).ToStdString());
39 m_propertyGrid->Clear();
41 m_propertyGrid->Refresh();
42 m_stack->ChangeSelection(1);
43 } else {
45 }
46}
47
49 if (!m_node || !m_propertyGrid)
50 return;
51
52 // Basic properties category
53 m_propertyGrid->Append(new wxPropertyCategory("Basic Properties"));
54
55 auto nameProp = new wxStringProperty("Name", "name", m_node->GetName());
56 nameProp->SetClientData(reinterpret_cast<void *>(PROP_NODE_NAME));
57 m_propertyGrid->Append(nameProp);
58
59 auto idProp = new wxUIntProperty("ID", "id", static_cast<unsigned int>(m_node->GetId()));
60 idProp->SetClientData(reinterpret_cast<void *>(PROP_NODE_ID));
61 idProp->ChangeFlag(wxPGPropertyFlags::ReadOnly, true);
62 m_propertyGrid->Append(idProp);
63
64 auto typeProp = new wxStringProperty("Type", "type", GetNodeTypeDisplayName(m_node->GetType()));
65 typeProp->SetClientData(reinterpret_cast<void *>(PROP_NODE_TYPE));
66 typeProp->ChangeFlag(wxPGPropertyFlags::ReadOnly, true);
67 m_propertyGrid->Append(typeProp);
68
72}
73
75 if (!m_node)
76 return;
77
78 m_propertyGrid->Append(new wxPropertyCategory("Visual Properties"));
79
80 auto childrenVisibleProp = new wxBoolProperty("Children Visible", "children_visible", m_node->AreChildrenVisible());
81 childrenVisibleProp->SetClientData(reinterpret_cast<void *>(PROP_NODE_CHILDREN_VISIBLE));
82 m_propertyGrid->Append(childrenVisibleProp);
83}
84
85bool PropertiesTab::IsPortValue(const std::string &value) {
86 if (value.size() < 3)
87 return false;
88 if (value.front() == '{' && value.back() == '}')
89 return true;
90 if (value.size() >= 4 && value[0] == '$' && value[1] == '{' && value.back() == '}')
91 return true;
92 return false;
93}
94
96 if (!m_node)
97 return;
98
99 const auto &attributes = m_node->GetAllAttributes();
100 bool headerAdded = false;
101 int propId = PROP_CUSTOM_ATTRIBUTES_START;
102
103 for (const auto &pair : attributes) {
104 if (!IsPortValue(pair.second))
105 continue;
106
107 if (!headerAdded) {
108 m_propertyGrid->Append(new wxPropertyCategory("Ports"));
109 headerAdded = true;
110 }
111
112 auto portProp = new wxStringProperty(pair.first, wxString::Format("attr_%s", pair.first), pair.second);
113 portProp->SetClientData(reinterpret_cast<void *>(propId++));
114 m_propertyGrid->Append(portProp);
115 }
116}
117
119 if (!m_node)
120 return;
121
122 const auto &attributes = m_node->GetAllAttributes();
123 bool headerAdded = false;
124 int propId = PROP_CUSTOM_ATTRIBUTES_START + 500;
125
126 for (const auto &pair : attributes) {
127 if (IsPortValue(pair.second))
128 continue;
129
130 if (!headerAdded) {
131 m_propertyGrid->Append(new wxPropertyCategory("Attributes"));
132 headerAdded = true;
133 }
134
135 auto attrProp = new wxStringProperty(pair.first, wxString::Format("attr_%s", pair.first), pair.second);
136 attrProp->SetClientData(reinterpret_cast<void *>(propId++));
137 m_propertyGrid->Append(attrProp);
138 }
139}
140
142 switch (type) {
144 return "Control";
146 return "Action";
148 return "Condition";
150 return "Decorator";
152 return "BehaviorTree";
154 return "None";
155 default:
156 return "Unknown";
157 }
158}
159
160void PropertiesTab::OnPropertyChanged(wxPropertyGridEvent &event) {
161 if (!m_node)
162 return;
163
164 wxPGProperty *prop = event.GetProperty();
165 if (!prop)
166 return;
167
168 int propId = reinterpret_cast<intptr_t>(prop->GetClientData());
169 wxVariant value = prop->GetValue();
170
171 LOG_INFO("Properties",
172 wxString::Format("Property changed: %s = %s", prop->GetName(), value.GetString()).ToStdString());
173
174 switch (propId) {
175 case PROP_NODE_NAME:
176 m_node->SetName(value.GetString().ToStdString());
177 break;
178
180 m_node->SetChildrenVisible(value.GetBool());
181 break;
182
183 default:
184 if (propId >= PROP_CUSTOM_ATTRIBUTES_START) {
185 wxString attrName = prop->GetName();
186 m_node->SetAttribute(attrName.ToStdString(), value.GetString().ToStdString());
187 }
188 break;
189 }
190}
191
192void PropertiesTab::OnPropertyChanging(wxPropertyGridEvent &event) {
193 wxPGProperty *prop = event.GetProperty();
194 if (!prop)
195 return;
196}
BehaviorTreeProjectDialog::OnProjectNameChanged BehaviorTreeProjectDialog::OnRemoveFiles wxEND_EVENT_TABLE() BehaviorTreeProjectDialog
wxBEGIN_EVENT_TABLE(PropertiesTab, EmberUI::PropertiesTabBase) EVT_PG_CHANGING(wxID_ANY
#define LOG_INFO(category, message)
Definition Logger.h:114
Represents a node in a behavior tree structure.
Definition Node.h:20
Type
Node types for behavior tree classification.
Definition Node.h:25
size_t GetId() const
Definition Node.h:80
const String & GetName() const
Definition Node.h:81
static wxColour GetAccentColor()
Get the accent color as a wxColour for UI elements.
Shared base class for property editors (wxPanel, ITab).
void SetupPropertyGrid(wxPanel *parent)
Creates and configures the property grid in the given parent.
EmberCore::ITreeNode * m_selectedNode
void ClearSelection()
Clears the current selection.
Main application window for EmberForge.
Definition MainFrame.h:67
MainFrame * m_mainFrame
void OnClosed() override
Called when the tab is closed.
void SetSelectedNode(EmberCore::Node *node)
void CreateContentLayout(wxPanel *contentPanel) override
Pure virtual: subclasses create their content layout in contentPanel.
void OnPropertyChanged(wxPropertyGridEvent &event)
void AddVisualProperties()
wxString GetNodeTypeDisplayName(EmberCore::Node::Type type) const
static bool IsPortValue(const std::string &value)
void PopulateProperties() override
Pure virtual: subclasses populate the property grid from m_selectedNode.
void OnPropertyChanging(wxPropertyGridEvent &event)
void AddNodeCustomAttributes()
void AddNodePortAttributes()
@ PROP_CUSTOM_ATTRIBUTES_START
void OnNodeCleared() override
Called when selection is cleared; subclasses may override.
EmberCore::Node * m_node