Skip to content

Commit 839b753

Browse files
committed
feat: implement variables viewport UI and backend logic for smartprop editor
1 parent 725d67b commit 839b753

8 files changed

Lines changed: 634 additions & 97 deletions

File tree

src/editors/smartprop_editor/document.py

Lines changed: 126 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1088,9 +1088,26 @@ def _populate_variables(self, data):
10881088
for item in data:
10891089
var_class = (item.get("_class", "")).replace(variable_prefix, "")
10901090
var_name = item.get("m_VariableName", None)
1091-
var_display_name = item.get("m_DisplayName", None)
1092-
if var_display_name is None:
1093-
var_display_name = item.get("m_ParameterName", None)
1091+
1092+
cat_name = item.get("m_Hammer5ToolsCategoryName")
1093+
import re
1094+
is_category = False
1095+
is_start = False
1096+
if var_name:
1097+
if re.match(r"hammer5tools_category_([a-z0-9]+)_(start|end)", var_name) or re.match(r"hammer5tools_category_(.*)_category_(.*)_(start|end)", var_name):
1098+
is_category = True
1099+
is_start = var_name.endswith('_start')
1100+
1101+
if is_category and cat_name is not None:
1102+
if is_start:
1103+
var_display_name = f" ----===={cat_name}===------"
1104+
else:
1105+
var_display_name = " "
1106+
else:
1107+
var_display_name = item.get("m_DisplayName", None)
1108+
if var_display_name is None:
1109+
var_display_name = item.get("m_ParameterName", None)
1110+
10941111
var_visible_in_editor = bool(item.get("m_bExposeAsParameter", None))
10951112
var_value = {
10961113
"default": item.get("m_DefaultValue", None),
@@ -1120,13 +1137,20 @@ def _populate_variables(self, data):
11201137
break
11211138

11221139
if not variable_exists:
1123-
self.add_variable(
1124-
name=var_name,
1125-
var_value=var_value,
1126-
var_visible_in_editor=var_visible_in_editor,
1127-
var_class=var_class,
1128-
var_display_name=var_display_name
1129-
)
1140+
if is_category:
1141+
self.add_category(
1142+
name=var_name,
1143+
var_visible_in_editor=var_visible_in_editor,
1144+
var_display_name=var_display_name
1145+
)
1146+
else:
1147+
self.add_variable(
1148+
name=var_name,
1149+
var_value=var_value,
1150+
var_visible_in_editor=var_visible_in_editor,
1151+
var_class=var_class,
1152+
var_display_name=var_display_name
1153+
)
11301154

11311155
def add_an_element(self):
11321156
self.popup_menu = PopupMenu(elements_list, add_once=False, window_name="SPE_elements")
@@ -1310,44 +1334,75 @@ def open_file(self, filename):
13101334

13111335
# Rebuild variables
13121336
if isinstance(variables, list):
1337+
import re
13131338
for item in variables:
13141339
var_class = (item["_class"]).replace(variable_prefix, "")
13151340
var_name = item.get("m_VariableName", None)
1316-
var_display_name = item.get("m_DisplayName", None)
1317-
if var_display_name is None:
1318-
var_display_name = item.get("m_ParameterName", None)
13191341
var_visible_in_editor = bool(item.get("m_bExposeAsParameter", None))
13201342

1321-
var_value = {
1322-
"default": item.get("m_DefaultValue", None),
1323-
"model": item.get("m_sModelName", None),
1324-
"m_nElementID": item.get("m_nElementID", None),
1325-
'm_HideExpression': item.get("m_HideExpression", None)
1326-
}
1327-
element_id = var_value['m_nElementID']
1328-
if element_id is not None:
1329-
self.element_id_generator.add_id(element_id)
1330-
else:
1331-
var_value = self.element_id_generator.update_value(var_value)
1332-
if var_class == "Float":
1333-
var_value.update({
1334-
"min": item.get("m_flParamaterMinValue", None),
1335-
"max": item.get("m_flParamaterMaxValue", None)
1336-
})
1337-
elif var_class == "Int":
1338-
var_value.update({
1339-
"min": item.get("m_nParamaterMinValue", None),
1340-
"max": item.get("m_nParamaterMaxValue", None)
1341-
})
1343+
# Detect category markers
1344+
is_category = False
1345+
is_start = False
1346+
if var_name:
1347+
if re.match(r"hammer5tools_category_([a-z0-9]+)_(start|end)", var_name) or re.match(r"hammer5tools_category_(.*)_category_(.*)_(start|end)", var_name):
1348+
is_category = True
1349+
is_start = var_name.endswith('_start')
1350+
1351+
if is_category:
1352+
cat_name = item.get("m_Hammer5ToolsCategoryName")
1353+
if cat_name is not None:
1354+
if is_start:
1355+
var_display_name = f" ----===={cat_name}===------"
1356+
else:
1357+
var_display_name = " "
1358+
else:
1359+
var_display_name = item.get("m_ParameterName", None)
1360+
1361+
# Still register element ID
1362+
element_id = item.get("m_nElementID", None)
1363+
if element_id is not None:
1364+
self.element_id_generator.add_id(element_id)
1365+
1366+
self.add_category(
1367+
name=var_name,
1368+
var_visible_in_editor=var_visible_in_editor,
1369+
var_display_name=var_display_name
1370+
)
13421371
else:
1343-
var_value.update({"min": None, "max": None})
1344-
self.add_variable(
1345-
name=var_name,
1346-
var_value=var_value,
1347-
var_visible_in_editor=var_visible_in_editor,
1348-
var_class=var_class,
1349-
var_display_name=var_display_name
1350-
)
1372+
var_display_name = item.get("m_DisplayName", None)
1373+
if var_display_name is None:
1374+
var_display_name = item.get("m_ParameterName", None)
1375+
1376+
var_value = {
1377+
"default": item.get("m_DefaultValue", None),
1378+
"model": item.get("m_sModelName", None),
1379+
"m_nElementID": item.get("m_nElementID", None),
1380+
'm_HideExpression': item.get("m_HideExpression", None)
1381+
}
1382+
element_id = var_value['m_nElementID']
1383+
if element_id is not None:
1384+
self.element_id_generator.add_id(element_id)
1385+
else:
1386+
var_value = self.element_id_generator.update_value(var_value)
1387+
if var_class == "Float":
1388+
var_value.update({
1389+
"min": item.get("m_flParamaterMinValue", None),
1390+
"max": item.get("m_flParamaterMaxValue", None)
1391+
})
1392+
elif var_class == "Int":
1393+
var_value.update({
1394+
"min": item.get("m_nParamaterMinValue", None),
1395+
"max": item.get("m_nParamaterMaxValue", None)
1396+
})
1397+
else:
1398+
var_value.update({"min": None, "max": None})
1399+
self.add_variable(
1400+
name=var_name,
1401+
var_value=var_value,
1402+
var_visible_in_editor=var_visible_in_editor,
1403+
var_class=var_class,
1404+
var_display_name=var_display_name
1405+
)
13511406

13521407
self._modified = False
13531408
finally:
@@ -1488,6 +1543,12 @@ def add_variable(
14881543
self._modified = True
14891544
self._edited.emit()
14901545

1546+
def add_category(self, name, var_visible_in_editor, var_display_name, index: int = None, expanded: bool = True):
1547+
self.variable_viewport.add_category(name, var_visible_in_editor, var_display_name, index, expanded)
1548+
if not self._restoring_state:
1549+
self._modified = True
1550+
self._edited.emit()
1551+
14911552
def duplicate_variable(self, __data, __index):
14921553
self.variable_viewport.duplicate_variable(__data, __index)
14931554

@@ -2115,14 +2176,29 @@ def _restore_variables(self, state):
21152176
self._restoring_state = True
21162177
try:
21172178
for var_data in state:
2118-
self.add_variable(
2119-
name=var_data['name'],
2120-
var_class=var_data['var_class'],
2121-
var_value=var_data['var_value'],
2122-
var_visible_in_editor=var_data['var_visible_in_editor'],
2123-
var_display_name=var_data['var_display_name'],
2124-
expanded=var_data.get('expanded', False),
2125-
)
2179+
name = var_data['name']
2180+
import re
2181+
is_category = False
2182+
if name:
2183+
if re.match(r"hammer5tools_category_([a-z0-9]+)_(start|end)", name) or re.match(r"hammer5tools_category_(.*)_category_(.*)_(start|end)", name):
2184+
is_category = True
2185+
2186+
if is_category:
2187+
self.add_category(
2188+
name=name,
2189+
var_visible_in_editor=var_data['var_visible_in_editor'],
2190+
var_display_name=var_data['var_display_name'],
2191+
expanded=var_data.get('expanded', True)
2192+
)
2193+
else:
2194+
self.add_variable(
2195+
name=name,
2196+
var_class=var_data['var_class'],
2197+
var_value=var_data['var_value'],
2198+
var_visible_in_editor=var_data['var_visible_in_editor'],
2199+
var_display_name=var_data['var_display_name'],
2200+
expanded=var_data.get('expanded', False),
2201+
)
21262202
finally:
21272203
self._restoring_state = False
21282204
self._modified = True

src/editors/smartprop_editor/property_frame.py

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -932,27 +932,14 @@ def mousePressEvent(self, event):
932932
if prefix and name:
933933
self.clicked.emit(f"{prefix}_{name}")
934934

935+
mousePressEvent = PropertyMethods.mousePressEvent
935936
mouseMoveEvent = PropertyMethods.mouseMoveEvent
936937
dragEnterEvent = PropertyMethods.dragEnterEvent
937938
dragMoveEvent = PropertyMethods.dragMoveEvent
938939
dragLeaveEvent = PropertyMethods.dragLeaveEvent
939940

940941
def dropEvent(self, event):
941-
if event.source() == self:
942-
return
943-
944-
mime_data = event.mimeData()
945-
if mime_data.hasText():
946-
if event.source() != self:
947-
source_index = self.widget_list.layout().indexOf(event.source())
948-
target_index = self.widget_list.layout().indexOf(self)
949-
if source_index != -1 and target_index != -1:
950-
if source_index < self.widget_list.layout().count():
951-
source_widget = self.widget_list.layout().takeAt(source_index).widget()
952-
if source_widget:
953-
self.widget_list.layout().insertWidget(target_index, source_widget)
954-
self.edited.emit()
955-
event.accept()
942+
PropertyMethods.dropEvent(self, event)
956943

957944
def show_context_menu(self):
958945
context_menu = QMenu()

src/editors/smartprop_editor/ui_variables_viewport.py

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,46 @@ def setupUi(self, Form):
107107

108108
self.horizontalLayout.addWidget(self.paste_variable_button)
109109

110+
self.add_new_category_button = QToolButton(self.frame)
111+
self.add_new_category_button.setObjectName(u"add_new_category_button")
112+
self.add_new_category_button.setMaximumSize(QSize(28, 28))
113+
self.add_new_category_button.setStyleSheet(u"\n"
114+
" /* QPushButton default and hover styles */\n"
115+
" QToolButton {\n"
116+
"\n"
117+
" font: 580 9pt \"Segoe UI\";\n"
118+
"\n"
119+
"\n"
120+
" border: 2px solid black;\n"
121+
" border-radius: 2px;\n"
122+
" border-color: rgba(80, 80, 80, 255);\n"
123+
" height:22px;\n"
124+
" padding-top: 2px;\n"
125+
" padding-bottom:2px;\n"
126+
" padding-left: 4px;\n"
127+
" padding-right: 4px;\n"
128+
" color: #E3E3E3;\n"
129+
" background-color: #1C1C1C;\n"
130+
" }\n"
131+
" QToolButton:hover {\n"
132+
" background-color: #414956;\n"
133+
" color: white;\n"
134+
" }\n"
135+
" QToolButton:pressed {\n"
136+
" background-color: red;\n"
137+
" background-color: #1C1C1C;\n"
138+
" margin: 1 px;\n"
139+
" margin-left: 2px;\n"
140+
" margin-right: 2px;\n"
141+
"\n"
142+
" }")
143+
icon1 = QIcon()
144+
icon1.addFile(u":/icons/create_new_folder_24dp_9D9D9D_FILL0_wght400_GRAD0_opsz24.svg", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
145+
self.add_new_category_button.setIcon(icon1)
146+
self.add_new_category_button.setIconSize(QSize(20, 20))
147+
148+
self.horizontalLayout.addWidget(self.add_new_category_button)
149+
110150
self.add_new_variable_button = QToolButton(self.frame)
111151
self.add_new_variable_button.setObjectName(u"add_new_variable_button")
112152
self.add_new_variable_button.setMaximumSize(QSize(28, 28))
@@ -140,9 +180,9 @@ def setupUi(self, Form):
140180
" margin-right: 2px;\n"
141181
"\n"
142182
" }")
143-
icon1 = QIcon()
144-
icon1.addFile(u":/icons/add_24dp_9D9D9D_FILL0_wght400_GRAD0_opsz24.svg", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
145-
self.add_new_variable_button.setIcon(icon1)
183+
icon2 = QIcon()
184+
icon2.addFile(u":/icons/add_24dp_9D9D9D_FILL0_wght400_GRAD0_opsz24.svg", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
185+
self.add_new_variable_button.setIcon(icon2)
146186
self.add_new_variable_button.setIconSize(QSize(20, 20))
147187

148188
self.horizontalLayout.addWidget(self.add_new_variable_button)
@@ -329,6 +369,10 @@ def retranslateUi(self, Form):
329369
self.paste_variable_button.setToolTip(QCoreApplication.translate("Form", u"<html><head/><body><p>Paste variable</p></body></html>", None))
330370
#endif // QT_CONFIG(tooltip)
331371
self.paste_variable_button.setText(QCoreApplication.translate("Form", u"...", None))
372+
#if QT_CONFIG(tooltip)
373+
self.add_new_category_button.setToolTip(QCoreApplication.translate("Form", u"<html><head/><body><p>Create category</p></body></html>", None))
374+
#endif // QT_CONFIG(tooltip)
375+
self.add_new_category_button.setText(QCoreApplication.translate("Form", u"...", None))
332376
#if QT_CONFIG(tooltip)
333377
self.add_new_variable_button.setToolTip(QCoreApplication.translate("Form", u"<html><head/><body><p>Create variable</p></body></html>", None))
334378
#endif // QT_CONFIG(tooltip)

0 commit comments

Comments
 (0)