Skip to content

Commit 7d151c2

Browse files
committed
address so missed duplication
2 parents 9807eb8 + 932b02a commit 7d151c2

8 files changed

Lines changed: 163 additions & 211 deletions

File tree

code/missioneditor/sexp_tree_actions.cpp

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,117 @@ int SexpTreeActions::add_default_operator(int op_index, int argnum)
474474
return 0;
475475
}
476476

477+
int SexpTreeActions::insert_operator(int op, void* root_parent_handle)
478+
{
479+
Assertion(SCP_vector_inbounds(Operators, op), "Invalid operator index");
480+
Assertion(_model.item_index >= 0, "Invalid selected node index");
481+
482+
const int wrapped_node = _model.item_index;
483+
const int parent_node = _model.tree_nodes[wrapped_node].parent;
484+
const int node_flags = _model.tree_nodes[wrapped_node].flags;
485+
const void* wrapped_handle = _model.tree_nodes[wrapped_node].handle;
486+
487+
const int node = _model.allocate_node(parent_node, wrapped_node);
488+
_model.set_node(node, (SEXPT_OPERATOR | SEXPT_VALID), Operators[op].text.c_str());
489+
_model.tree_nodes[node].flags = node_flags;
490+
491+
void* insert_parent = nullptr;
492+
if (parent_node >= 0) {
493+
insert_parent = _model.tree_nodes[parent_node].handle;
494+
} else {
495+
if (_model._interface && _model._interface->getFlags()[TreeFlags::LabeledRoot]) {
496+
insert_parent = root_parent_handle;
497+
_model._interface->onRootInserted(wrapped_node, node);
498+
} else {
499+
_model.root_item = node;
500+
}
501+
}
502+
503+
_model.tree_nodes[node].handle =
504+
_ui.ui_insert_item(Operators[op].text.c_str(), NodeImage::OPERATOR, insert_parent, const_cast<void*>(wrapped_handle));
505+
506+
_ui.ui_move_branch(wrapped_node, node);
507+
_model.item_index = node;
508+
for (int i = 1; i < Operators[op].min; i++) {
509+
add_default_operator(op, i);
510+
}
511+
512+
_ui.ui_expand_item(_model.tree_nodes[node].handle);
513+
if (_model.modified) {
514+
*_model.modified = 1;
515+
}
516+
517+
return node;
518+
}
519+
520+
int SexpTreeActions::add_or_replace_typed_data(int data_idx, bool replace, int add_count, int replace_count)
521+
{
522+
Assertion(_model.item_index >= 0, "Invalid item index");
523+
const int op_node = replace ? _model.tree_nodes[_model.item_index].parent : _model.item_index;
524+
Assertion(op_node >= 0, "Invalid operator node");
525+
526+
sexp_list_item* list = nullptr;
527+
if (_model.tree_nodes[op_node].type & SEXPT_CONTAINER_DATA) {
528+
if (replace && replace_count == 0) {
529+
list = _model._opf.get_container_modifiers(op_node);
530+
} else {
531+
list = _model._opf.get_container_multidim_modifiers(op_node);
532+
}
533+
} else {
534+
const int op = get_operator_index(_model.tree_nodes[op_node].text);
535+
Assertion(op >= 0, "Invalid operator index");
536+
const auto argcount = replace ? replace_count : add_count;
537+
const auto type = query_operator_argument_type(op, argcount);
538+
list = _model._opf.get_listing_opf(type, _model.item_index, argcount);
539+
}
540+
Assertion(list, "Failed to get listing OPF");
541+
542+
auto* ptr = list;
543+
while (data_idx) {
544+
data_idx--;
545+
ptr = ptr->next;
546+
Assertion(ptr, "Invalid SEXP list");
547+
}
548+
549+
Assertion((SEXPT_TYPE(ptr->type) != SEXPT_OPERATOR) && (ptr->op < 0), "Invalid SEXP type or operator");
550+
expand_operator(_model.item_index);
551+
int added_node = -1;
552+
if (replace) {
553+
replace_data(ptr->text.c_str(), ptr->type);
554+
} else {
555+
added_node = add_data(ptr->text.c_str(), ptr->type);
556+
}
557+
list->destroy();
558+
return added_node;
559+
}
560+
561+
void SexpTreeActions::replace_variable_with_type_validation(int var_idx, int current_node_type, bool allow_type_coercion)
562+
{
563+
Assertion(_model.item_index >= 0, "Invalid item index");
564+
Assertion((var_idx >= 0) && (var_idx < MAX_SEXP_VARIABLES), "Invalid variable index");
565+
Assertion((current_node_type & SEXPT_NUMBER) || (current_node_type & SEXPT_STRING), "Invalid node type");
566+
567+
int resolved_type = current_node_type;
568+
if (allow_type_coercion) {
569+
if (Sexp_variables[var_idx].type & SEXP_VARIABLE_NUMBER) {
570+
resolved_type = SEXPT_NUMBER;
571+
} else if (Sexp_variables[var_idx].type & SEXP_VARIABLE_STRING) {
572+
resolved_type = SEXPT_STRING;
573+
} else {
574+
Int3();
575+
}
576+
} else {
577+
if (resolved_type & SEXPT_NUMBER) {
578+
Assertion(Sexp_variables[var_idx].type & SEXP_VARIABLE_NUMBER, "Invalid variable type");
579+
}
580+
if (resolved_type & SEXPT_STRING) {
581+
Assertion(Sexp_variables[var_idx].type & SEXP_VARIABLE_STRING, "Invalid variable type");
582+
}
583+
}
584+
585+
replace_variable_data(var_idx, (resolved_type | SEXPT_VARIABLE));
586+
}
587+
477588
// -----------------------------------------------------------------------
478589
// Validation
479590
// -----------------------------------------------------------------------

code/missioneditor/sexp_tree_actions.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,16 @@ class SexpTreeActions {
7474
// Handles special cases: variable names, container names, modify-variable types.
7575
// Returns 0 on success, -1 if no default value available.
7676
int add_default_operator(int op_index, int argnum);
77+
// Insert an operator above the current node and move the current node under it.
78+
// root_parent_handle is only used for labeled-root trees, where roots are inserted
79+
// under a label item instead of as true tree roots.
80+
int insert_operator(int op, void* root_parent_handle = nullptr);
81+
// Resolve and apply a typed add/replace-data menu entry by index.
82+
// add_count and replace_count are the cached argument positions computed by menu state.
83+
int add_or_replace_typed_data(int data_idx, bool replace, int add_count, int replace_count);
84+
// Resolve variable type validation/coercion and replace current node with the variable.
85+
// current_node_type should be the selected node's SEXPT_NUMBER/SEXPT_STRING flags.
86+
void replace_variable_with_type_validation(int var_idx, int current_node_type, bool allow_type_coercion);
7787

7888
// --- Validation ---
7989

code/missioneditor/sexp_tree_model.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,8 @@ class ISexpTreeUI {
256256

257257
// Recursively add child tree items for all children of the given model node
258258
virtual void ui_add_children_visual(int parent_node_index) = 0;
259+
// Move an existing subtree so source_node becomes a child of parent_node
260+
virtual void ui_move_branch(int source_node, int parent_node) = 0;
259261
// Recursively expand the subtree rooted at the given handle
260262
virtual void ui_expand_branch(void* handle) = 0;
261263

code/missioneditor/sexp_tree_opf.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -199,9 +199,9 @@ sexp_list_item *SexpTreeOPF::get_listing_opf_prop()
199199
ptr = GET_FIRST(&obj_used_list);
200200
while (ptr != END_OF_LIST(&obj_used_list)) {
201201
if (ptr->type == OBJ_PROP) {
202-
auto prop = prop_id_lookup(ptr->instance);
203-
if (prop != nullptr) {
204-
head.add_data(prop->prop_name);
202+
auto p = prop_id_lookup(ptr->instance);
203+
if (p != nullptr) {
204+
head.add_data(p->prop_name);
205205
}
206206
}
207207

fred2/sexp_tree_view.cpp

Lines changed: 17 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,11 @@ void sexp_tree_view::ui_add_children_visual(int parent_node_index)
139139
}
140140
}
141141

142+
void sexp_tree_view::ui_move_branch(int source_node, int parent_node)
143+
{
144+
move_branch(source_node, parent_node);
145+
}
146+
142147
void sexp_tree_view::ui_expand_branch(void* handle)
143148
{
144149
expand_branch((HTREEITEM)handle);
@@ -752,9 +757,7 @@ void sexp_tree_view::end_operator_edit(bool confirm)
752757
// now it also handles messages from the operator combo box
753758
BOOL sexp_tree_view::OnCommand(WPARAM wParam, LPARAM lParam)
754759
{
755-
int i, z, id, data, node, op;
756-
sexp_list_item *list, *ptr;
757-
HTREEITEM h;
760+
int id, data, node, op;
758761

759762
if ((item_index >= 0) && (item_index < total_nodes) && !tree_nodes.empty())
760763
item_handle = tree_item_handle(tree_nodes[item_index]);
@@ -946,38 +949,11 @@ BOOL sexp_tree_view::OnCommand(WPARAM wParam, LPARAM lParam)
946949
// check if REPLACE_VARIABLE_MENU
947950
if ( (id >= ID_VARIABLE_MENU) && (id < ID_VARIABLE_MENU + 511)) {
948951

949-
Assertion(item_index >= 0, "Invalid item index");
950-
951-
// get index into list of type valid variables
952952
int var_idx = id - ID_VARIABLE_MENU;
953-
Assertion( (var_idx >= 0) && (var_idx < MAX_SEXP_VARIABLES), "Invalid variable index");
954-
955-
int type = get_type(item_handle);
956-
Assertion( (type & SEXPT_NUMBER) || (type & SEXPT_STRING), "Invalid variable type");
957-
958-
// don't do type check for modify-variable or OPF_CONTAINER_VALUE (can be either type)
959-
if (m_modify_variable || _model.query_node_argument_type(item_index) == OPF_CONTAINER_VALUE) {
960-
if (Sexp_variables[var_idx].type & SEXP_VARIABLE_NUMBER) {
961-
type = SEXPT_NUMBER;
962-
} else if (Sexp_variables[var_idx].type & SEXP_VARIABLE_STRING) {
963-
type = SEXPT_STRING;
964-
} else {
965-
Int3(); // unknown type
966-
}
967-
968-
} else {
969-
// verify type in tree is same as type in Sexp_variables array
970-
if (type & SEXPT_NUMBER) {
971-
Assertion(Sexp_variables[var_idx].type & SEXP_VARIABLE_NUMBER, "Invalid variable type");
972-
}
973-
974-
if (type & SEXPT_STRING) {
975-
Assertion((Sexp_variables[var_idx].type & SEXP_VARIABLE_STRING), "Invalid variable type");
976-
}
977-
}
978-
979-
// Replace data
980-
_actions.replace_variable_data(var_idx, (type | SEXPT_VARIABLE));
953+
const int type = get_type(item_handle);
954+
const bool allow_type_coercion =
955+
(m_modify_variable != 0) || (_model.query_node_argument_type(item_index) == OPF_CONTAINER_VALUE);
956+
_actions.replace_variable_with_type_validation(var_idx, type, allow_type_coercion);
981957

982958
return 1;
983959
}
@@ -988,30 +964,12 @@ BOOL sexp_tree_view::OnCommand(WPARAM wParam, LPARAM lParam)
988964
Assertion(item_index >= 0, "Invalid item index");
989965

990966
int type = 0;
991-
992-
if (tree_nodes[item_index].type & SEXPT_CONTAINER_DATA) {
993-
list = _model._opf.get_container_multidim_modifiers(item_index);
994-
} else {
967+
if (!(tree_nodes[item_index].type & SEXPT_CONTAINER_DATA)) {
995968
op = get_operator_index(tree_nodes[item_index].text);
996969
Assertion(op >= 0, "Invalid operator index");
997-
998970
type = query_operator_argument_type(op, m_add_count);
999-
list = _model._opf.get_listing_opf(type, item_index, m_add_count);
1000-
}
1001-
Assertion(list, "Invalid listing");
1002-
1003-
id -= ID_ADD_MENU;
1004-
ptr = list;
1005-
while (id) {
1006-
id--;
1007-
ptr = ptr->next;
1008-
Assertion(ptr, "Invalid list pointer");
1009971
}
1010-
1011-
Assertion((SEXPT_TYPE(ptr->type) != SEXPT_OPERATOR) && (ptr->op < 0), "Invalid list type");
1012-
_actions.expand_operator(item_index);
1013-
node = _actions.add_data(ptr->text.c_str(), ptr->type);
1014-
list->destroy();
972+
node = _actions.add_or_replace_typed_data(id - ID_ADD_MENU, false, m_add_count, m_replace_count);
1015973

1016974
// bolted-on ugly hack
1017975
if (type == OPF_VARIABLE_NAME) {
@@ -1037,32 +995,7 @@ BOOL sexp_tree_view::OnCommand(WPARAM wParam, LPARAM lParam)
1037995
}
1038996

1039997
if ((id >= ID_REPLACE_MENU) && (id < ID_REPLACE_MENU + 511)) {
1040-
Assertion(item_index >= 0, "Invalid item index");
1041-
Assertion(tree_nodes[item_index].parent >= 0, "Invalid parent index");
1042-
1043-
if (tree_nodes[item_index].type & SEXPT_MODIFIER) {
1044-
list = _model._opf.get_container_modifiers(tree_nodes[item_index].parent);
1045-
} else {
1046-
op = get_operator_index(tree_nodes[tree_nodes[item_index].parent].text);
1047-
Assertion(op >= 0, "Invalid operator index");
1048-
1049-
auto type = query_operator_argument_type(op, m_replace_count); // check argument type at this position
1050-
list = _model._opf.get_listing_opf(type, tree_nodes[item_index].parent, m_replace_count);
1051-
}
1052-
Assertion(list, "Invalid listing");
1053-
1054-
id -= ID_REPLACE_MENU;
1055-
ptr = list;
1056-
while (id) {
1057-
id--;
1058-
ptr = ptr->next;
1059-
Assertion(ptr, "Invalid list pointer");
1060-
}
1061-
1062-
Assertion((SEXPT_TYPE(ptr->type) != SEXPT_OPERATOR) && (ptr->op < 0), "Invalid list type");
1063-
_actions.expand_operator(item_index);
1064-
_actions.replace_data(ptr->text.c_str(), ptr->type);
1065-
list->destroy();
998+
_actions.add_or_replace_typed_data(id - ID_REPLACE_MENU, true, m_add_count, m_replace_count);
1066999
return 1;
10671000
}
10681001

@@ -1119,37 +1052,12 @@ BOOL sexp_tree_view::OnCommand(WPARAM wParam, LPARAM lParam)
11191052
}
11201053

11211054
if (id == (Operators[op].value | OP_INSERT_FLAG)) {
1122-
int flags;
1123-
1124-
z = tree_nodes[item_index].parent;
1125-
flags = tree_nodes[item_index].flags;
1126-
node = _model.allocate_node(z, item_index);
1127-
_model.set_node(node, (SEXPT_OPERATOR | SEXPT_VALID), Operators[op].text.c_str());
1128-
tree_nodes[node].flags = flags;
1129-
if (z >= 0)
1130-
h = tree_item_handle(tree_nodes[z]);
1131-
1132-
else {
1133-
h = GetParentItem(tree_item_handle(tree_nodes[item_index]));
1134-
if (_model._interface && _model._interface->getFlags()[TreeFlags::LabeledRoot]) {
1135-
_model._interface->onRootInserted(item_index, node);
1136-
SetItemData(h, node);
1137-
} else {
1138-
h = TVI_ROOT;
1139-
root_item = node;
1140-
}
1055+
HTREEITEM root_parent = GetParentItem(tree_item_handle(tree_nodes[item_index]));
1056+
node = _actions.insert_operator(op, root_parent);
1057+
if (_model._interface && _model._interface->getFlags()[TreeFlags::LabeledRoot] && root_parent) {
1058+
SetItemData(root_parent, node);
11411059
}
1142-
1143-
tree_nodes[node].handle = insert(Operators[op].text.c_str(), BITMAP_OPERATOR, BITMAP_OPERATOR, h, tree_item_handle(tree_nodes[item_index]));
1144-
item_handle = tree_item_handle(tree_nodes[node]);
1145-
move_branch(item_index, node);
1146-
11471060
item_index = node;
1148-
for (i=1; i<Operators[op].min; i++)
1149-
_actions.add_default_operator(op, i);
1150-
1151-
Expand(item_handle, TVE_EXPAND);
1152-
*modified = 1;
11531061
return 1;
11541062
}
11551063
}
@@ -1939,4 +1847,3 @@ void sexp_tree_view::OnKeyDown(NMHDR *pNMHDR, LRESULT *pResult)
19391847

19401848
*pResult = 0;
19411849
}
1942-

fred2/sexp_tree_view.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ class sexp_tree_view : public CTreeCtrl, public ISexpTreeUI
109109
void ui_notify_modified() override;
110110
void ui_update_help(void* handle) override;
111111
void ui_add_children_visual(int parent_node_index) override;
112+
void ui_move_branch(int source_node, int parent_node) override;
112113
void ui_expand_branch(void* handle) override;
113114

114115
// ClassWizard generated virtual function overrides

0 commit comments

Comments
 (0)