159 wxPanel *panel =
new wxPanel(notebook);
160 wxGridBagSizer *sizer =
new wxGridBagSizer(10, 10);
165 wxBoxSizer *labelSizer1 =
new wxBoxSizer(wxHORIZONTAL);
169 wxBitmap infoNormal(
GetResourcePath(
"buttons/info/Info_Normal_20.png"), wxBITMAP_TYPE_PNG);
170 wxBitmap infoHover(
GetResourcePath(
"buttons/info/Info_Hovered_20.png"), wxBITMAP_TYPE_PNG);
171 wxBitmap infoPressed(
GetResourcePath(
"buttons/info/Info_Pressed_20.png"), wxBITMAP_TYPE_PNG);
172 wxBitmap infoDisabled(
GetResourcePath(
"buttons/info/Info_Disabled_20.png"), wxBITMAP_TYPE_PNG);
174 wxBitmapButton *infoBtn1 =
new wxBitmapButton(panel, wxID_ANY, infoNormal, wxDefaultPosition, wxSize(40, 40),
175 wxBORDER_NONE | wxBU_EXACTFIT);
176 infoBtn1->SetBitmapHover(infoHover);
177 infoBtn1->SetBitmapPressed(infoPressed);
178 infoBtn1->SetBitmapDisabled(infoDisabled);
179 infoBtn1->SetToolTip(
"Click for detailed information");
180 infoBtn1->Bind(wxEVT_BUTTON, [
this](wxCommandEvent &) {
181 wxString helpText =
"ROOT ELEMENT NAME\n"
182 "===========================================================\n\n"
184 "The name of the top-level XML element that wraps all behavior trees.\n"
185 "This is the outermost container in your XML file.\n\n"
187 " - 'root' - BehaviorTree.CPP standard format\n"
188 " - 'BehaviorTrees' - Some Unity implementations\n"
189 " - 'TreeCollection' - Custom formats\n\n"
191 "This element MUST be present in your XML file as the outermost container.\n"
192 "All behavior tree definitions must be nested inside this root element.\n\n"
193 "EXAMPLE XML STRUCTURE:\n"
194 " <root main_tree_to_execute=\"MainTree\">\n"
195 " <BehaviorTree ID=\"MainTree\">\n"
197 " <Action ID=\"MoveForward\"/>\n"
201 "If your XML uses a different name (e.g., <Trees>), enter that name here.";
202 HelpDialog dlg(
this,
"Root Element Name - Help", helpText);
205 labelSizer1->Add(infoBtn1, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5);
206 labelSizer1->Add(
new wxStaticText(panel, wxID_ANY,
"Root Element Name:"), 0, wxALIGN_CENTER_VERTICAL);
207 sizer->Add(labelSizer1, wxGBPosition(row, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
210 m_rootElement->SetToolTip(
"Top-level XML element name (e.g., 'root')");
212 sizer->Add(
m_rootElement, wxGBPosition(row, 1), wxDefaultSpan, wxEXPAND);
216 wxBoxSizer *labelSizer2 =
new wxBoxSizer(wxHORIZONTAL);
218 wxBitmapButton *infoBtn2 =
new wxBitmapButton(panel, wxID_ANY, infoNormal, wxDefaultPosition, wxSize(40, 40),
219 wxBORDER_NONE | wxBU_EXACTFIT);
220 infoBtn2->SetBitmapHover(infoHover);
221 infoBtn2->SetBitmapPressed(infoPressed);
222 infoBtn2->SetBitmapDisabled(infoDisabled);
223 infoBtn2->SetToolTip(
"Click for detailed information");
224 infoBtn2->Bind(wxEVT_BUTTON, [
this](wxCommandEvent &) {
225 wxString helpText =
"MAIN TREE ATTRIBUTE\n"
226 "===========================================================\n\n"
228 "The attribute on the root element that specifies which behavior tree\n"
229 "should be executed first when your XML file contains multiple trees.\n\n"
231 " - 'main_tree_to_execute' - BehaviorTree.CPP standard\n"
232 " - 'entry_point' - Alternative naming convention\n"
233 " - 'start_tree' - Some custom implementations\n\n"
234 "WHY DO YOU NEED IT?\n"
235 "When your XML file contains multiple behavior tree definitions (main tree,\n"
236 "subtrees, utility trees), this attribute tells the system which one is the\n"
237 "primary entry point.\n\n"
239 " <root main_tree_to_execute=\"PlayerAI\">\n"
240 " <BehaviorTree ID=\"PlayerAI\">\n"
241 " <!-- This tree will be loaded first -->\n"
243 " <BehaviorTree ID=\"EnemyAI\">\n"
244 " <!-- This tree is available as a subtree -->\n"
247 "FALLBACK BEHAVIOR:\n"
248 "If this attribute is missing or empty, the parser will automatically\n"
249 "load the first behavior tree it finds in the file.";
250 HelpDialog dlg(
this,
"Main Tree Attribute - Help", helpText);
253 labelSizer2->Add(infoBtn2, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5);
254 labelSizer2->Add(
new wxStaticText(panel, wxID_ANY,
"Main Tree Attribute:"), 0, wxALIGN_CENTER_VERTICAL);
255 sizer->Add(labelSizer2, wxGBPosition(row, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
258 m_mainTreeAttr->SetToolTip(
"Attribute specifying entry point tree (e.g., 'main_tree_to_execute')");
260 sizer->Add(
m_mainTreeAttr, wxGBPosition(row, 1), wxDefaultSpan, wxEXPAND);
264 wxBoxSizer *caseSizer =
new wxBoxSizer(wxHORIZONTAL);
266 wxBitmapButton *infoBtn3 =
new wxBitmapButton(panel, wxID_ANY, infoNormal, wxDefaultPosition, wxSize(40, 40),
267 wxBORDER_NONE | wxBU_EXACTFIT);
268 infoBtn3->SetBitmapHover(infoHover);
269 infoBtn3->SetBitmapPressed(infoPressed);
270 infoBtn3->SetBitmapDisabled(infoDisabled);
271 infoBtn3->SetToolTip(
"Click for detailed information");
272 infoBtn3->Bind(wxEVT_BUTTON, [
this](wxCommandEvent &) {
273 wxString helpText =
"CASE SENSITIVE ELEMENT NAMES\n"
274 "===========================================================\n\n"
275 "Controls whether element and attribute names must match the exact\n"
276 "case specified in your configuration.\n\n"
277 "ENABLED (Recommended):\n"
278 " - <BehaviorTree> and <behaviortree> are treated as DIFFERENT\n"
279 " - More strict parsing - catches typos and inconsistencies\n"
280 " - Standard for most XML parsers and behavior tree formats\n"
281 " - Best for well-defined, consistent XML formats\n\n"
283 " - <BehaviorTree>, <behaviortree>, <BEHAVIORTREE> all treated as SAME\n"
284 " - More forgiving - useful for legacy/inconsistent XML files\n"
285 " - May hide formatting issues in your XML\n"
286 " - Use ONLY if your XML has inconsistent casing\n\n"
288 "If ENABLED and you configure 'BehaviorTree' as the tree element:\n"
289 " [YES] <BehaviorTree ID=\"Test\"> - ACCEPTED\n"
290 " [NO] <behaviortree ID=\"Test\"> - REJECTED (case mismatch)\n\n"
292 " [YES] <BehaviorTree ID=\"Test\"> - ACCEPTED\n"
293 " [YES] <behaviortree ID=\"Test\"> - ACCEPTED\n"
294 " [YES] <BEHAVIORTREE ID=\"Test\"> - ACCEPTED\n\n"
296 "Keep this ENABLED unless working with legacy files that have\n"
297 "inconsistent casing. Strict validation helps catch errors early!";
298 HelpDialog dlg(
this,
"Case Sensitive - Help", helpText);
301 caseSizer->Add(infoBtn3, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5);
302 m_caseSensitive =
new wxCheckBox(panel, wxID_ANY,
"Case Sensitive Element Names");
303 m_caseSensitive->SetToolTip(
"Element/attribute names must match exact case");
305 sizer->Add(caseSizer, wxGBPosition(row, 0), wxGBSpan(1, 2));
309 wxBoxSizer *unknownSizer =
new wxBoxSizer(wxHORIZONTAL);
311 wxBitmapButton *infoBtn4 =
new wxBitmapButton(panel, wxID_ANY, infoNormal, wxDefaultPosition, wxSize(40, 40),
312 wxBORDER_NONE | wxBU_EXACTFIT);
313 infoBtn4->SetBitmapHover(infoHover);
314 infoBtn4->SetBitmapPressed(infoPressed);
315 infoBtn4->SetBitmapDisabled(infoDisabled);
316 infoBtn4->SetToolTip(
"Click for detailed information");
317 infoBtn4->Bind(wxEVT_BUTTON, [
this](wxCommandEvent &) {
318 wxString helpText =
"ALLOW UNKNOWN ELEMENTS\n"
319 "===========================================================\n\n"
320 "Controls how the parser handles XML elements that are NOT defined\n"
321 "in your configuration.\n\n"
323 " - Unknown elements are SILENTLY IGNORED\n"
324 " - Parsing continues without warnings\n"
325 " - Useful for XML with documentation, metadata, or extensions\n"
326 " - More flexible for varying XML formats\n\n"
327 "DISABLED (Recommended):\n"
328 " - Unknown elements cause WARNING messages in the log\n"
329 " - Helps catch typos (e.g., 'Behaviortree' vs 'BehaviorTree')\n"
330 " - Stricter validation ensures XML matches expectations\n"
331 " - Better for catching configuration errors\n\n"
332 "EXAMPLE - XML with unknown elements:\n"
334 " <BehaviorTree ID=\"Test\">...</BehaviorTree>\n"
335 " <Documentation>Comment</Documentation> <- Unknown\n"
336 " <Metadata author=\"John\"/> <- Unknown\n"
338 "If ENABLED: Parser ignores <Documentation> and <Metadata>\n"
339 "If DISABLED: Parser logs warnings about unexpected elements\n\n"
341 "Keep DISABLED during development to catch errors.\n"
342 "Enable only if you need to parse XML with extra metadata.";
343 HelpDialog dlg(
this,
"Allow Unknown Elements - Help", helpText);
346 unknownSizer->Add(infoBtn4, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5);
350 sizer->Add(unknownSizer, wxGBPosition(row, 0), wxGBSpan(1, 2));
354 wxBoxSizer *labelSizer5 =
new wxBoxSizer(wxHORIZONTAL);
356 wxBitmapButton *infoBtn5 =
new wxBitmapButton(panel, wxID_ANY, infoNormal, wxDefaultPosition, wxSize(40, 40),
357 wxBORDER_NONE | wxBU_EXACTFIT);
358 infoBtn5->SetBitmapHover(infoHover);
359 infoBtn5->SetBitmapPressed(infoPressed);
360 infoBtn5->SetBitmapDisabled(infoDisabled);
361 infoBtn5->SetToolTip(
"Click for detailed information");
362 infoBtn5->Bind(wxEVT_BUTTON, [
this](wxCommandEvent &) {
363 wxString helpText =
"WHITESPACE HANDLING\n"
364 "===========================================================\n\n"
365 "Controls how whitespace (spaces, tabs, newlines) in attribute values\n"
366 "and text content is processed during parsing.\n\n"
369 " - Keeps ALL whitespace exactly as it appears\n"
370 " - ' Hello World ' stays as ' Hello World '\n"
371 " - Use if whitespace is meaningful in your data\n"
372 " - Rarely needed for behavior trees\n\n"
373 "TRIM (Recommended):\n"
374 " - Removes leading and trailing whitespace ONLY\n"
375 " - ' Hello World ' becomes 'Hello World'\n"
376 " - Internal spaces preserved: 'Hello World' stays 'Hello World'\n"
377 " - Best for most behavior tree formats\n"
378 " - Handles formatting inconsistencies gracefully\n\n"
380 " - Trims AND collapses multiple spaces to single space\n"
381 " - ' Hello World ' becomes 'Hello World'\n"
382 " - Useful for cleaning poorly formatted XML\n"
383 " - May affect intentional multi-spacing\n\n"
385 "Value: name=' Patrol Enemy '\n"
386 " - PRESERVE: ' Patrol Enemy '\n"
387 " - TRIM: 'Patrol Enemy'\n"
388 " - NORMALIZE: 'Patrol Enemy'\n\n"
389 "Value: name='Move To Target'\n"
390 " - PRESERVE: 'Move To Target'\n"
391 " - TRIM: 'Move To Target'\n"
392 " - NORMALIZE: 'Move To Target'\n\n"
394 "Use TRIM for clean, consistent parsing that handles\n"
395 "formatting variations without losing meaningful content.";
396 HelpDialog dlg(
this,
"Whitespace Handling - Help", helpText);
399 labelSizer5->Add(infoBtn5, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5);
400 labelSizer5->Add(
new wxStaticText(panel, wxID_ANY,
"Whitespace Handling:"), 0, wxALIGN_CENTER_VERTICAL);
401 sizer->Add(labelSizer5, wxGBPosition(row, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
403 wxArrayString whitespaceChoices;
404 whitespaceChoices.Add(
"Preserve");
405 whitespaceChoices.Add(
"Trim");
406 whitespaceChoices.Add(
"Normalize");
407 m_whitespaceHandling =
new wxChoice(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, whitespaceChoices);
414 wxBoxSizer *namingSizer =
new wxBoxSizer(wxHORIZONTAL);
416 wxBitmapButton *infoBtn6 =
new wxBitmapButton(panel, wxID_ANY, infoNormal, wxDefaultPosition, wxSize(40, 40),
417 wxBORDER_NONE | wxBU_EXACTFIT);
418 infoBtn6->SetBitmapHover(infoHover);
419 infoBtn6->SetBitmapPressed(infoPressed);
420 infoBtn6->SetBitmapDisabled(infoDisabled);
421 infoBtn6->SetToolTip(
"Click for detailed information");
422 infoBtn6->Bind(wxEVT_BUTTON, [
this](wxCommandEvent &) {
423 wxString helpText =
"NAMING CONVENTION\n"
424 "===========================================================\n\n"
425 "Controls how strictly element and attribute naming rules are enforced.\n"
426 "When you switch conventions, all fields are immediately re-validated\n"
427 "and invalid names are highlighted with a pulsing yellow background.\n\n"
428 "===========================================================\n\n"
430 " Allowed: Letters (a-z, A-Z) and underscores (_) ONLY\n"
431 " Not allowed: Numbers, hyphens, dots, or any special characters\n"
432 " Must start with: Letter or underscore\n"
434 " Use for: Maximum safety and consistency\n"
435 " Best for: Production environments, strict standards\n\n"
436 "===========================================================\n\n"
437 "BALANCED MODE (Recommended):\n"
438 " Allowed: Letters, underscores, digits (0-9), and hyphens (-)\n"
439 " Not allowed: Dots, spaces, or other special characters\n"
440 " Must start with: Letter or underscore (NOT a number)\n"
442 " Use for: Most projects - flexible yet safe\n"
443 " Best for: Standard behavior tree projects\n\n"
444 "===========================================================\n\n"
446 " Allowed: Most characters that don't break XML\n"
447 " Includes: Letters, digits, underscores, hyphens, dots, colons\n"
448 " Not allowed: <, >, &, quotes, spaces, brackets, and other\n"
449 " XML-breaking characters\n"
450 " Must start with: Letter, underscore, or colon\n"
452 " Use for: Legacy XML files, maximum compatibility\n"
453 " Best for: Working with existing/legacy systems\n\n"
454 "===========================================================\n\n"
456 "Name: 'MyAction' All modes accept\n"
457 "Name: 'My_Action' All modes accept\n"
458 "Name: 'My-Action' STRICT rejects | BALANCED/LOOSE accept\n"
459 "Name: 'MyAction123' STRICT rejects | BALANCED/LOOSE accept\n"
460 "Name: 'My.Action' STRICT/BALANCED reject | LOOSE accepts\n"
461 "Name: 'My:Action' STRICT/BALANCED reject | LOOSE accepts\n"
462 "Name: '123Action' STRICT/BALANCED reject | LOOSE rejects\n"
463 "Name: 'My Action' All modes reject (contains space)\n"
464 "Name: 'My<Action>' All modes reject (breaks XML)\n\n"
465 "===========================================================\n\n"
467 " - Switch between conventions to see which fields become invalid\n"
468 " - Invalid fields pulse with yellow highlighting\n"
469 " - Fix invalid names before saving your configuration\n\n"
471 "Start with BALANCED - it provides excellent validation while\n"
472 "supporting common naming patterns like 'Action-Name' and 'Node123'.\n"
473 "Use STRICT for maximum safety or LOOSE for legacy compatibility.";
474 HelpDialog dlg(
this,
"Naming Convention - Help", helpText);
477 namingSizer->Add(infoBtn6, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5);
478 namingSizer->Add(
new wxStaticText(panel, wxID_ANY,
"Naming Convention:"), 0, wxALIGN_CENTER_VERTICAL);
479 sizer->Add(namingSizer, wxGBPosition(row, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
482 wxBoxSizer *checkboxesSizer =
new wxBoxSizer(wxHORIZONTAL);
485 wxBoxSizer *strictSizer =
new wxBoxSizer(wxVERTICAL);
489 strictSizer->Add(
new wxStaticText(panel, wxID_ANY,
"Strict"), 0, wxALIGN_CENTER_HORIZONTAL | wxTOP, 2);
490 checkboxesSizer->Add(strictSizer, 0, wxRIGHT, 15);
493 wxBoxSizer *balancedSizer =
new wxBoxSizer(wxVERTICAL);
497 balancedSizer->Add(
new wxStaticText(panel, wxID_ANY,
"Balanced"), 0, wxALIGN_CENTER_HORIZONTAL | wxTOP, 2);
498 checkboxesSizer->Add(balancedSizer, 0, wxRIGHT, 15);
501 wxBoxSizer *looseSizer =
new wxBoxSizer(wxVERTICAL);
505 looseSizer->Add(
new wxStaticText(panel, wxID_ANY,
"Loose"), 0, wxALIGN_CENTER_HORIZONTAL | wxTOP, 2);
506 checkboxesSizer->Add(looseSizer, 0);
508 sizer->Add(checkboxesSizer, wxGBPosition(row, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
514 if (event.IsChecked()) {
521 if (event.IsChecked()) {
528 if (event.IsChecked()) {
535 sizer->AddGrowableCol(1);
536 panel->SetSizer(sizer);
541 wxPanel *panel =
new wxPanel(notebook);
542 wxGridBagSizer *sizer =
new wxGridBagSizer(5, 5);
545 wxBitmap infoNormal(
GetResourcePath(
"buttons/info/Info_Normal_20.png"), wxBITMAP_TYPE_PNG);
546 wxBitmap infoHover(
GetResourcePath(
"buttons/info/Info_Hovered_20.png"), wxBITMAP_TYPE_PNG);
547 wxBitmap infoPressed(
GetResourcePath(
"buttons/info/Info_Pressed_20.png"), wxBITMAP_TYPE_PNG);
548 wxBitmap infoDisabled(
GetResourcePath(
"buttons/info/Info_Disabled_20.png"), wxBITMAP_TYPE_PNG);
553 wxBoxSizer *labelSizer1 =
new wxBoxSizer(wxHORIZONTAL);
554 wxBitmapButton *infoBtn1 =
new wxBitmapButton(panel, wxID_ANY, infoNormal, wxDefaultPosition, wxSize(40, 40),
555 wxBORDER_NONE | wxBU_EXACTFIT);
556 infoBtn1->SetBitmapHover(infoHover);
557 infoBtn1->SetBitmapPressed(infoPressed);
558 infoBtn1->SetBitmapDisabled(infoDisabled);
559 infoBtn1->SetToolTip(
"Click for detailed information");
560 infoBtn1->Bind(wxEVT_BUTTON, [
this](wxCommandEvent &) {
561 wxString helpText =
"BEHAVIOR TREE ELEMENT\n"
562 "===========================================================\n\n"
564 "The XML element name that represents a behavior tree definition\n"
565 "in your XML file. This is the main container for each tree.\n\n"
567 " - 'BehaviorTree' - Standard BehaviorTree.CPP format\n"
568 " - 'Tree' - Simplified/custom format\n"
569 " - 'btree' - Alternative naming\n\n"
571 "The parser scans your XML looking for elements with this exact name.\n"
572 "Each matching element is treated as a separate behavior tree definition.\n\n"
575 " <BehaviorTree ID=\"MainTree\">\n"
577 " <Action name=\"DoSomething\"/>\n"
582 " - Name must match EXACTLY (case-sensitive if enabled)\n"
583 " - All your behavior trees must use this element name\n"
584 " - Typical values: 'BehaviorTree', 'Tree', or custom names";
585 HelpDialog dlg(
this,
"Behavior Tree Element - Help", helpText);
588 labelSizer1->Add(infoBtn1, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5);
589 labelSizer1->Add(
new wxStaticText(panel, wxID_ANY,
"Behavior Tree Element:"), 0, wxALIGN_CENTER_VERTICAL);
590 sizer->Add(labelSizer1, wxGBPosition(row, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
598 wxBoxSizer *labelSizer2 =
new wxBoxSizer(wxHORIZONTAL);
599 wxBitmapButton *infoBtn2 =
new wxBitmapButton(panel, wxID_ANY, infoNormal, wxDefaultPosition, wxSize(40, 40),
600 wxBORDER_NONE | wxBU_EXACTFIT);
601 infoBtn2->SetBitmapHover(infoHover);
602 infoBtn2->SetBitmapPressed(infoPressed);
603 infoBtn2->SetBitmapDisabled(infoDisabled);
604 infoBtn2->SetToolTip(
"Click for detailed information");
605 infoBtn2->Bind(wxEVT_BUTTON, [
this](wxCommandEvent &) {
606 wxString helpText =
"TREE ID ATTRIBUTE\n"
607 "===========================================================\n\n"
609 "The XML attribute name that contains the unique identifier for\n"
610 "each behavior tree in your file.\n\n"
612 " - 'ID' - Standard BehaviorTree.CPP format (most common)\n"
613 " - 'name' - Alternative naming convention\n"
614 " - 'id' - Lowercase variant\n"
615 " - 'tree_id' - Explicit naming\n\n"
616 "WHY DO YOU NEED IT?\n"
617 "The ID serves multiple critical purposes:\n"
618 " - Uniquely identifies each behavior tree\n"
619 " - Enables subtree references (one tree calling another)\n"
620 " - Supports multiple trees in a single XML file\n"
621 " - Used by the main tree attribute to specify entry point\n\n"
623 " <BehaviorTree ID=\"MainTree\">\n"
624 " <SubTree ID=\"PatrolBehavior\"/>\n"
626 " <BehaviorTree ID=\"PatrolBehavior\">\n"
627 " <!-- This tree can be called by MainTree -->\n"
628 " </BehaviorTree>\n\n"
630 " - Each tree MUST have a unique ID\n"
631 " - IDs are used for subtree references";
632 HelpDialog dlg(
this,
"Tree ID Attribute - Help", helpText);
635 labelSizer2->Add(infoBtn2, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5);
636 labelSizer2->Add(
new wxStaticText(panel, wxID_ANY,
"Tree ID Attribute:"), 0, wxALIGN_CENTER_VERTICAL);
637 sizer->Add(labelSizer2, wxGBPosition(row, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
639 m_treeIdAttr->SetToolTip(
"Attribute name for tree identifier (e.g., 'ID')");
641 sizer->Add(
m_treeIdAttr, wxGBPosition(row, 1), wxDefaultSpan, wxEXPAND);
645 wxBoxSizer *labelSizer3 =
new wxBoxSizer(wxHORIZONTAL);
646 wxBitmapButton *infoBtn3 =
new wxBitmapButton(panel, wxID_ANY, infoNormal, wxDefaultPosition, wxSize(40, 40),
647 wxBORDER_NONE | wxBU_EXACTFIT);
648 infoBtn3->SetBitmapHover(infoHover);
649 infoBtn3->SetBitmapPressed(infoPressed);
650 infoBtn3->SetBitmapDisabled(infoDisabled);
651 infoBtn3->SetToolTip(
"Click for detailed information");
652 infoBtn3->Bind(wxEVT_BUTTON, [
this](wxCommandEvent &) {
653 wxString helpText =
"ALLOW MULTIPLE TREES IN FILE\n"
654 "===========================================================\n\n"
655 "Controls whether your XML file can contain multiple behavior tree\n"
656 "definitions or just one.\n\n"
657 "ENABLED (Recommended):\n"
658 " - Multiple <BehaviorTree> elements can exist in one file\n"
659 " - Each tree MUST have a unique ID\n"
660 " - Perfect for organizing related trees together\n"
661 " - Enables subtree references within the same file\n"
662 " - Common in BehaviorTree.CPP and complex AI systems\n\n"
664 " - Only ONE <BehaviorTree> element allowed per file\n"
665 " - Simpler structure for basic projects\n"
666 " - Parser will REJECT files with multiple trees\n"
667 " - Forces one-tree-per-file organization\n\n"
668 "EXAMPLE (ENABLED):\n"
670 " <BehaviorTree ID=\"MainAI\">\n"
671 " <SubTree ID=\"Patrol\"/>\n"
673 " <BehaviorTree ID=\"Patrol\">\n"
674 " <!-- Subtree definition -->\n"
678 "Enable this for flexibility and better tree organization.";
679 HelpDialog dlg(
this,
"Allow Multiple Trees - Help", helpText);
682 labelSizer3->Add(infoBtn3, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5);
686 sizer->Add(labelSizer3, wxGBPosition(row, 0), wxGBSpan(1, 2));
690 wxBoxSizer *labelSizer4 =
new wxBoxSizer(wxHORIZONTAL);
691 wxBitmapButton *infoBtn4 =
new wxBitmapButton(panel, wxID_ANY, infoNormal, wxDefaultPosition, wxSize(40, 40),
692 wxBORDER_NONE | wxBU_EXACTFIT);
693 infoBtn4->SetBitmapHover(infoHover);
694 infoBtn4->SetBitmapPressed(infoPressed);
695 infoBtn4->SetBitmapDisabled(infoDisabled);
696 infoBtn4->SetToolTip(
"Click for detailed information");
697 infoBtn4->Bind(wxEVT_BUTTON, [
this](wxCommandEvent &) {
698 wxString helpText =
"SUBTREE ELEMENT\n"
699 "===========================================================\n\n"
701 "The XML element name that represents a subtree reference - a special\n"
702 "node that calls another behavior tree by its ID.\n\n"
704 " - 'SubTree' - Standard BehaviorTree.CPP format (recommended)\n"
705 " - 'CallTree' - Alternative naming\n"
706 " - 'TreeReference' - Explicit variant\n"
707 " - 'Include' - Some custom implementations\n\n"
709 "When the execution reaches a SubTree node, it:\n"
710 " 1. Pauses the current tree\n"
711 " 2. Executes the referenced tree completely\n"
712 " 3. Returns the referenced tree's result (SUCCESS/FAILURE)\n"
713 " 4. Continues with the current tree\n\n"
715 " <BehaviorTree ID=\"MainAI\">\n"
717 " <SubTree ID=\"PatrolBehavior\"/>\n"
718 " <Action name=\"Attack\"/>\n"
720 " </BehaviorTree>\n\n"
722 " - Reuse trees in multiple places\n"
723 " - Create modular, maintainable structures\n"
724 " - Break complex behaviors into components";
725 HelpDialog dlg(
this,
"SubTree Element - Help", helpText);
728 labelSizer4->Add(infoBtn4, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5);
729 labelSizer4->Add(
new wxStaticText(panel, wxID_ANY,
"SubTree Element:"), 0, wxALIGN_CENTER_VERTICAL);
730 sizer->Add(labelSizer4, wxGBPosition(row, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
732 m_subtreeElement->SetToolTip(
"Element name for subtree references (e.g., 'SubTree')");
734 sizer->Add(
m_subtreeElement, wxGBPosition(row, 1), wxDefaultSpan, wxEXPAND);
738 wxBoxSizer *labelSizer5 =
new wxBoxSizer(wxHORIZONTAL);
739 wxBitmapButton *infoBtn5 =
new wxBitmapButton(panel, wxID_ANY, infoNormal, wxDefaultPosition, wxSize(40, 40),
740 wxBORDER_NONE | wxBU_EXACTFIT);
741 infoBtn5->SetBitmapHover(infoHover);
742 infoBtn5->SetBitmapPressed(infoPressed);
743 infoBtn5->SetBitmapDisabled(infoDisabled);
744 infoBtn5->SetToolTip(
"Click for detailed information");
745 infoBtn5->Bind(wxEVT_BUTTON, [
this](wxCommandEvent &) {
746 wxString helpText =
"SUBTREE REFERENCE ATTRIBUTE\n"
747 "===========================================================\n\n"
749 "The XML attribute name on a SubTree node that contains the ID of\n"
750 "the behavior tree being referenced/called.\n\n"
752 " - 'ID' - Standard BehaviorTree.CPP format (most common)\n"
753 " - 'treeID' - Explicit variant\n"
754 " - 'ref' - Short form\n"
755 " - 'tree' - Simple naming\n\n"
757 "When the parser encounters a SubTree node:\n"
758 " 1. Reads this attribute to get the referenced tree ID\n"
759 " 2. Searches for a BehaviorTree with matching ID\n"
760 " 3. Links them together for execution\n"
761 " 4. Validates that the reference is valid\n\n"
763 " <BehaviorTree ID=\"MainAI\">\n"
764 " <SubTree ID=\"PatrolBehavior\"/>\n"
765 " ^^^^^^^^^^^^^^^^^^^^^\n"
766 " This attribute references another tree\n"
767 " </BehaviorTree>\n\n"
769 " - Should typically MATCH your Tree ID Attribute setting\n"
770 " - Referenced tree must exist in the same or loaded files\n"
771 " - Parser validates references during loading";
772 HelpDialog dlg(
this,
"SubTree Reference Attribute - Help", helpText);
775 labelSizer5->Add(infoBtn5, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5);
776 labelSizer5->Add(
new wxStaticText(panel, wxID_ANY,
"SubTree Reference Attribute:"), 0, wxALIGN_CENTER_VERTICAL);
777 sizer->Add(labelSizer5, wxGBPosition(row, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
779 m_subtreeRefAttr->SetToolTip(
"Attribute containing referenced tree ID (e.g., 'ID')");
781 sizer->Add(
m_subtreeRefAttr, wxGBPosition(row, 1), wxDefaultSpan, wxEXPAND);
785 wxBoxSizer *labelSizer6 =
new wxBoxSizer(wxHORIZONTAL);
786 wxBitmapButton *infoBtn6 =
new wxBitmapButton(panel, wxID_ANY, infoNormal, wxDefaultPosition, wxSize(40, 40),
787 wxBORDER_NONE | wxBU_EXACTFIT);
788 infoBtn6->SetBitmapHover(infoHover);
789 infoBtn6->SetBitmapPressed(infoPressed);
790 infoBtn6->SetBitmapDisabled(infoDisabled);
791 infoBtn6->SetToolTip(
"Click for detailed information");
792 infoBtn6->Bind(wxEVT_BUTTON, [
this](wxCommandEvent &) {
793 wxString helpText =
"VALIDATE TREE STRUCTURE\n"
794 "===========================================================\n\n"
795 "Enables comprehensive structural validation to ensure your behavior\n"
796 "trees follow proper hierarchical and semantic rules.\n\n"
797 "ENABLED (Recommended):\n"
798 " The parser performs these critical checks:\n"
799 " - Control nodes (Sequence, Selector, etc.) have at least one child\n"
800 " - Decorator nodes have EXACTLY one child\n"
801 " - Action/Condition nodes have NO children\n"
802 " - No circular subtree references (A->B->A)\n"
803 " - All node types are properly nested\n"
804 " - Tree structure matches behavior tree semantics\n\n"
806 " - No structural validation performed\n"
807 " - Faster parsing (minimal performance gain)\n"
808 " - MAY allow invalid trees that crash at runtime\n"
809 " - Use ONLY if you're 100% certain trees are valid\n\n"
810 "BENEFITS OF ENABLING:\n"
811 " - Catches errors EARLY during file loading\n"
812 " - Prevents mysterious runtime crashes\n"
813 " - Provides CLEAR, actionable error messages\n"
814 " - Saves debugging time\n\n"
816 "Keep this ENABLED, especially during development!";
817 HelpDialog dlg(
this,
"Validate Tree Structure - Help", helpText);
820 labelSizer6->Add(infoBtn6, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5);
824 sizer->Add(labelSizer6, wxGBPosition(row, 0), wxGBSpan(1, 2));
828 wxBoxSizer *labelSizer7 =
new wxBoxSizer(wxHORIZONTAL);
829 wxBitmapButton *infoBtn7 =
new wxBitmapButton(panel, wxID_ANY, infoNormal, wxDefaultPosition, wxSize(40, 40),
830 wxBORDER_NONE | wxBU_EXACTFIT);
831 infoBtn7->SetBitmapHover(infoHover);
832 infoBtn7->SetBitmapPressed(infoPressed);
833 infoBtn7->SetBitmapDisabled(infoDisabled);
834 infoBtn7->SetToolTip(
"Click for detailed information");
835 infoBtn7->Bind(wxEVT_BUTTON, [
this](wxCommandEvent &) {
836 wxString helpText =
"REQUIRE ROOT NODE\n"
837 "===========================================================\n\n"
838 "Determines whether each behavior tree must have at least one\n"
839 "root node (a direct child of the BehaviorTree element).\n\n"
840 "ENABLED (Recommended):\n"
841 " - Each tree MUST contain at least one root-level node\n"
842 " - Empty trees are REJECTED during parsing\n"
843 " - Ensures all trees are executable and meaningful\n"
844 " - Catches incomplete or placeholder trees\n"
845 " - Standard for production-ready behavior trees\n\n"
847 " - Empty trees are ALLOWED (no root node required)\n"
848 " - Useful for template/stub trees during development\n"
849 " - May allow non-functional tree structures\n"
850 " - Could lead to runtime issues if tree is called\n\n"
851 "EXAMPLE (VALID - with root):\n"
852 " <BehaviorTree ID=\"MainTree\">\n"
853 " <Sequence> <!-- ROOT NODE (direct child) -->\n"
854 " <Action name=\"DoSomething\"/>\n"
856 " </BehaviorTree>\n\n"
857 "EXAMPLE (INVALID - no root):\n"
858 " <BehaviorTree ID=\"EmptyTree\">\n"
859 " <!-- No nodes! -->\n"
860 " </BehaviorTree>\n\n"
862 "Keep ENABLED to ensure all trees are complete and executable!";
863 HelpDialog dlg(
this,
"Require Root Node - Help", helpText);
866 labelSizer7->Add(infoBtn7, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5);
870 sizer->Add(labelSizer7, wxGBPosition(row, 0), wxGBSpan(1, 2));
873 sizer->AddGrowableCol(1);
874 panel->SetSizer(sizer);
879 wxPanel *panel =
new wxPanel(notebook);
880 wxGridBagSizer *sizer =
new wxGridBagSizer(5, 5);
883 wxBitmap infoNormal(
GetResourcePath(
"buttons/info/Info_Normal_20.png"), wxBITMAP_TYPE_PNG);
884 wxBitmap infoHover(
GetResourcePath(
"buttons/info/Info_Hovered_20.png"), wxBITMAP_TYPE_PNG);
885 wxBitmap infoPressed(
GetResourcePath(
"buttons/info/Info_Pressed_20.png"), wxBITMAP_TYPE_PNG);
886 wxBitmap infoDisabled(
GetResourcePath(
"buttons/info/Info_Disabled_20.png"), wxBITMAP_TYPE_PNG);
891 wxBoxSizer *labelSizer1 =
new wxBoxSizer(wxHORIZONTAL);
892 wxBitmapButton *infoBtn1 =
new wxBitmapButton(panel, wxID_ANY, infoNormal, wxDefaultPosition, wxSize(40, 40),
893 wxBORDER_NONE | wxBU_EXACTFIT);
894 infoBtn1->SetBitmapHover(infoHover);
895 infoBtn1->SetBitmapPressed(infoPressed);
896 infoBtn1->SetBitmapDisabled(infoDisabled);
897 infoBtn1->SetToolTip(
"Click for detailed information");
898 infoBtn1->Bind(wxEVT_BUTTON, [
this](wxCommandEvent &) {
899 wxString helpText =
"CONTROL NODE ELEMENT\n"
900 "===========================================================\n\n"
902 "The XML element name that represents control flow nodes - nodes that\n"
903 "control the execution order and logic of their children.\n\n"
905 " - 'Control' - Generic control node element\n"
906 " - Leave empty to use specific names (Sequence, Selector, etc.)\n\n"
907 "CONTROL NODE TYPES:\n"
908 "Control nodes determine HOW and WHEN child nodes execute:\n"
909 " - Sequence: Execute children in order until one fails\n"
910 " - Selector/Fallback: Execute children until one succeeds\n"
911 " - Parallel: Execute multiple children simultaneously\n"
912 " - Random: Execute children in random order\n\n"
914 "If set to 'Control':\n"
915 " <Control type=\"Sequence\">\n"
916 " <Action name=\"Step1\"/>\n"
917 " <Action name=\"Step2\"/>\n"
919 "If left empty (common in BehaviorTree.CPP):\n"
920 " <Sequence> <!-- Direct element name -->\n"
921 " <Action name=\"Step1\"/>\n"
924 "For BehaviorTree.CPP compatibility, leave empty and use\n"
925 "specific element names like <Sequence>, <Selector>, etc.";
926 HelpDialog dlg(
this,
"Control Node Element - Help", helpText);
929 labelSizer1->Add(infoBtn1, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5);
930 labelSizer1->Add(
new wxStaticText(panel, wxID_ANY,
"Control Node Element:"), 0, wxALIGN_CENTER_VERTICAL);
931 sizer->Add(labelSizer1, wxGBPosition(row, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
933 m_controlElement->SetToolTip(
"Element name for control nodes (e.g., 'Control')");
935 sizer->Add(
m_controlElement, wxGBPosition(row, 1), wxDefaultSpan, wxEXPAND);
939 wxBoxSizer *labelSizer2 =
new wxBoxSizer(wxHORIZONTAL);
940 wxBitmapButton *infoBtn2 =
new wxBitmapButton(panel, wxID_ANY, infoNormal, wxDefaultPosition, wxSize(40, 40),
941 wxBORDER_NONE | wxBU_EXACTFIT);
942 infoBtn2->SetBitmapHover(infoHover);
943 infoBtn2->SetBitmapPressed(infoPressed);
944 infoBtn2->SetBitmapDisabled(infoDisabled);
945 infoBtn2->SetToolTip(
"Click for detailed information");
946 infoBtn2->Bind(wxEVT_BUTTON, [
this](wxCommandEvent &) {
947 wxString helpText =
"ACTION NODE ELEMENT\n"
948 "===========================================================\n\n"
950 "The XML element name that represents action nodes - nodes that\n"
951 "perform actual tasks or operations in your behavior tree.\n\n"
953 " - 'Action' - Standard BehaviorTree.CPP format\n"
954 " - 'Task' - Alternative naming\n"
955 " - 'Do' - Simple variant\n\n"
956 "WHAT ARE ACTION NODES?\n"
957 "Actions are the LEAF NODES that do the actual work:\n"
958 " - Move to a position\n"
959 " - Play an animation\n"
960 " - Attack an enemy\n"
961 " - Wait for a duration\n"
962 " - Set a variable\n\n"
964 " - Have NO children (leaf nodes)\n"
965 " - Return SUCCESS, FAILURE, or RUNNING\n"
966 " - Contain the actual executable logic\n"
967 " - May take parameters via attributes\n\n"
969 " <BehaviorTree ID=\"PatrolAI\">\n"
971 " <Action name=\"MoveToWaypoint\"/>\n"
972 " <Action name=\"Wait\" duration=\"2.0\"/>\n"
973 " <Action name=\"LookAround\"/>\n"
975 " </BehaviorTree>\n\n"
977 "Use 'Action' for standard BehaviorTree.CPP compatibility.";
978 HelpDialog dlg(
this,
"Action Node Element - Help", helpText);
981 labelSizer2->Add(infoBtn2, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5);
982 labelSizer2->Add(
new wxStaticText(panel, wxID_ANY,
"Action Node Element:"), 0, wxALIGN_CENTER_VERTICAL);
983 sizer->Add(labelSizer2, wxGBPosition(row, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
985 m_actionElement->SetToolTip(
"Element name for action nodes (e.g., 'Action')");
987 sizer->Add(
m_actionElement, wxGBPosition(row, 1), wxDefaultSpan, wxEXPAND);
991 wxBoxSizer *labelSizer3 =
new wxBoxSizer(wxHORIZONTAL);
992 wxBitmapButton *infoBtn3 =
new wxBitmapButton(panel, wxID_ANY, infoNormal, wxDefaultPosition, wxSize(40, 40),
993 wxBORDER_NONE | wxBU_EXACTFIT);
994 infoBtn3->SetBitmapHover(infoHover);
995 infoBtn3->SetBitmapPressed(infoPressed);
996 infoBtn3->SetBitmapDisabled(infoDisabled);
997 infoBtn3->SetToolTip(
"Click for detailed information");
998 infoBtn3->Bind(wxEVT_BUTTON, [
this](wxCommandEvent &) {
999 wxString helpText =
"CONDITION NODE ELEMENT\n"
1000 "===========================================================\n\n"
1002 "The XML element name that represents condition nodes - nodes that\n"
1003 "check/test a state and return SUCCESS or FAILURE immediately.\n\n"
1005 " - 'Condition' - Standard BehaviorTree.CPP format\n"
1006 " - 'Check' - Alternative naming\n"
1007 " - 'Test' - Some implementations\n\n"
1008 "WHAT ARE CONDITION NODES?\n"
1009 "Conditions are LEAF NODES that perform instant checks:\n"
1010 " - Is enemy in range?\n"
1011 " - Is health below 50%?\n"
1012 " - Is door open?\n"
1013 " - Has item in inventory?\n"
1014 " - Is time > X?\n\n"
1015 "KEY CHARACTERISTICS:\n"
1016 " - Have NO children (leaf nodes)\n"
1017 " - Execute INSTANTLY (never return RUNNING)\n"
1018 " - Return only SUCCESS or FAILURE\n"
1019 " - Used for decision-making logic\n"
1020 " - Often used with Selectors for branching\n\n"
1024 " <Condition name=\"IsEnemyClose\"/>\n"
1025 " <Action name=\"Attack\"/>\n"
1027 " <Action name=\"Patrol\"/>\n"
1030 "Use 'Condition' for standard BehaviorTree.CPP compatibility.";
1031 HelpDialog dlg(
this,
"Condition Node Element - Help", helpText);
1034 labelSizer3->Add(infoBtn3, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5);
1035 labelSizer3->Add(
new wxStaticText(panel, wxID_ANY,
"Condition Node Element:"), 0, wxALIGN_CENTER_VERTICAL);
1036 sizer->Add(labelSizer3, wxGBPosition(row, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
1038 m_conditionElement->SetToolTip(
"Element name for condition nodes (e.g., 'Condition')");
1044 wxBoxSizer *labelSizer4 =
new wxBoxSizer(wxHORIZONTAL);
1045 wxBitmapButton *infoBtn4 =
new wxBitmapButton(panel, wxID_ANY, infoNormal, wxDefaultPosition, wxSize(40, 40),
1046 wxBORDER_NONE | wxBU_EXACTFIT);
1047 infoBtn4->SetBitmapHover(infoHover);
1048 infoBtn4->SetBitmapPressed(infoPressed);
1049 infoBtn4->SetBitmapDisabled(infoDisabled);
1050 infoBtn4->SetToolTip(
"Click for detailed information");
1051 infoBtn4->Bind(wxEVT_BUTTON, [
this](wxCommandEvent &) {
1052 wxString helpText =
"DECORATOR NODE ELEMENT\n"
1053 "===========================================================\n\n"
1055 "The XML element name that represents decorator nodes - nodes that\n"
1056 "modify or enhance the behavior of EXACTLY ONE child node.\n\n"
1058 " - 'Decorator' - Generic decorator element\n"
1059 " - Leave empty to use specific names (Inverter, Retry, etc.)\n\n"
1060 "WHAT ARE DECORATOR NODES?\n"
1061 "Decorators WRAP a single child and modify its behavior:\n"
1062 " - Inverter: Flip SUCCESS <-> FAILURE\n"
1063 " - Retry: Repeat child until success (N times)\n"
1064 " - Repeat: Execute child multiple times\n"
1065 " - Force Success/Failure: Override child's result\n"
1066 " - Timeout: Fail child if it takes too long\n"
1067 " - Delay: Wait before executing child\n\n"
1068 "KEY CHARACTERISTICS:\n"
1069 " - Must have EXACTLY ONE child\n"
1070 " - Act as a wrapper/modifier\n"
1071 " - Don't change the tree structure\n"
1072 " - Commonly used for logic inversion and retries\n\n"
1075 " <Inverter> <!-- Decorator: flips result -->\n"
1076 " <Condition name=\"IsEnemyClose\"/>\n"
1078 " <Action name=\"Patrol\"/>\n"
1081 "Leave empty and use specific names like <Inverter>, <Retry>.";
1082 HelpDialog dlg(
this,
"Decorator Node Element - Help", helpText);
1085 labelSizer4->Add(infoBtn4, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5);
1086 labelSizer4->Add(
new wxStaticText(panel, wxID_ANY,
"Decorator Node Element:"), 0, wxALIGN_CENTER_VERTICAL);
1087 sizer->Add(labelSizer4, wxGBPosition(row, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
1089 m_decoratorElement->SetToolTip(
"Element name for decorator nodes (e.g., 'Decorator')");
1095 wxBoxSizer *labelSizer5 =
new wxBoxSizer(wxHORIZONTAL);
1096 wxBitmapButton *infoBtn5 =
new wxBitmapButton(panel, wxID_ANY, infoNormal, wxDefaultPosition, wxSize(40, 40),
1097 wxBORDER_NONE | wxBU_EXACTFIT);
1098 infoBtn5->SetBitmapHover(infoHover);
1099 infoBtn5->SetBitmapPressed(infoPressed);
1100 infoBtn5->SetBitmapDisabled(infoDisabled);
1101 infoBtn5->SetToolTip(
"Click for detailed information");
1102 infoBtn5->Bind(wxEVT_BUTTON, [
this](wxCommandEvent &) {
1103 wxString helpText =
"GENERIC NODE ELEMENT\n"
1104 "===========================================================\n\n"
1106 "A fallback element name used when a node doesn't match any\n"
1107 "of the specific node type elements (Control, Action, etc.).\n\n"
1109 " - 'Node' - Simple generic name\n"
1110 " - Leave empty if not needed\n\n"
1111 "WHEN IS IT USED?\n"
1112 "This acts as a catch-all for nodes that don't fit standard categories:\n"
1113 " - Custom node types specific to your implementation\n"
1114 " - Experimental or plugin nodes\n"
1115 " - Nodes that need runtime type determination\n\n"
1117 "Parser checks elements in this order:\n"
1118 " 1. Is it a Control node? (e.g., <Sequence>)\n"
1119 " 2. Is it an Action node? (e.g., <Action>)\n"
1120 " 3. Is it a Condition node? (e.g., <Condition>)\n"
1121 " 4. Is it a Decorator node? (e.g., <Inverter>)\n"
1122 " 5. Is it the Generic element? (e.g., <Node>)\n"
1123 " 6. Unknown element (error or ignored)\n\n"
1125 " <Node type=\"CustomPlugin\" name=\"SpecialBehavior\">\n"
1126 " <!-- Custom implementation -->\n"
1129 "Leave empty unless you have custom node types that don't\n"
1130 "fit the standard categories.";
1131 HelpDialog dlg(
this,
"Generic Node Element - Help", helpText);
1134 labelSizer5->Add(infoBtn5, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5);
1135 labelSizer5->Add(
new wxStaticText(panel, wxID_ANY,
"Generic Node Element:"), 0, wxALIGN_CENTER_VERTICAL);
1136 sizer->Add(labelSizer5, wxGBPosition(row, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
1144 wxBoxSizer *labelSizer6 =
new wxBoxSizer(wxHORIZONTAL);
1145 wxBitmapButton *infoBtn6 =
new wxBitmapButton(panel, wxID_ANY, infoNormal, wxDefaultPosition, wxSize(40, 40),
1146 wxBORDER_NONE | wxBU_EXACTFIT);
1147 infoBtn6->SetBitmapHover(infoHover);
1148 infoBtn6->SetBitmapPressed(infoPressed);
1149 infoBtn6->SetBitmapDisabled(infoDisabled);
1150 infoBtn6->SetToolTip(
"Click for detailed information");
1151 infoBtn6->Bind(wxEVT_BUTTON, [
this](wxCommandEvent &) {
1152 wxString helpText =
"NODE ID ATTRIBUTE\n"
1153 "===========================================================\n\n"
1155 "The XML attribute name that identifies the specific TYPE or\n"
1156 "CLASS of a node (e.g., 'Sequence', 'MoveToTarget', 'IsHealthLow').\n\n"
1158 " - 'ID' - BehaviorTree.CPP standard\n"
1159 " - 'type' - Alternative common usage\n"
1160 " - 'class' - Some implementations\n\n"
1161 "WHAT DOES IT CONTAIN?\n"
1162 "The ID typically specifies the node's TYPE/CLASS:\n"
1163 " - For Control: 'Sequence', 'Selector', 'Parallel'\n"
1164 " - For Action: 'MoveToTarget', 'Attack', 'PlayAnimation'\n"
1165 " - For Condition: 'IsHealthLow', 'IsEnemyNear'\n"
1166 " - For Decorator: 'Inverter', 'Retry', 'Timeout'\n\n"
1167 "EXAMPLE (using ID='type'):\n"
1168 " <Control ID=\"Sequence\">\n"
1169 " <Action ID=\"MoveToWaypoint\" target=\"wp1\"/>\n"
1170 " <Action ID=\"Wait\" duration=\"2.0\"/>\n"
1172 "vs EXAMPLE (element name is type):\n"
1174 " <MoveToWaypoint target=\"wp1\"/>\n"
1175 " <Wait duration=\"2.0\"/>\n"
1178 "Use 'ID' for BehaviorTree.CPP compatibility when using\n"
1179 "generic element names. Leave empty if using specific\n"
1180 "element names for each node type.";
1181 HelpDialog dlg(
this,
"Node ID Attribute - Help", helpText);
1184 labelSizer6->Add(infoBtn6, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5);
1185 labelSizer6->Add(
new wxStaticText(panel, wxID_ANY,
"Node ID Attribute:"), 0, wxALIGN_CENTER_VERTICAL);
1186 sizer->Add(labelSizer6, wxGBPosition(row, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
1188 m_nodeIdAttr->SetToolTip(
"Attribute name for node identifier/type (e.g., 'ID')");
1190 sizer->Add(
m_nodeIdAttr, wxGBPosition(row, 1), wxDefaultSpan, wxEXPAND);
1194 wxBoxSizer *labelSizer7 =
new wxBoxSizer(wxHORIZONTAL);
1195 wxBitmapButton *infoBtn7 =
new wxBitmapButton(panel, wxID_ANY, infoNormal, wxDefaultPosition, wxSize(40, 40),
1196 wxBORDER_NONE | wxBU_EXACTFIT);
1197 infoBtn7->SetBitmapHover(infoHover);
1198 infoBtn7->SetBitmapPressed(infoPressed);
1199 infoBtn7->SetBitmapDisabled(infoDisabled);
1200 infoBtn7->SetToolTip(
"Click for detailed information");
1201 infoBtn7->Bind(wxEVT_BUTTON, [
this](wxCommandEvent &) {
1202 wxString helpText =
"NODE NAME ATTRIBUTE\n"
1203 "===========================================================\n\n"
1205 "The XML attribute name that provides a human-readable display\n"
1206 "name or label for a node instance.\n\n"
1208 " - 'name' - Most common standard\n"
1209 " - 'label' - Alternative\n"
1210 " - 'displayName' - Explicit variant\n\n"
1211 "WHAT'S THE DIFFERENCE FROM NODE ID?\n"
1212 " - Node ID: The TYPE/CLASS of the node (e.g., 'MoveToTarget')\n"
1213 " - Node Name: A specific INSTANCE label (e.g., 'Move to Enemy')\n\n"
1215 " - Provide descriptive labels in visual editors\n"
1216 " - Make trees more readable in XML\n"
1217 " - Help with debugging and logging\n"
1218 " - Distinguish between multiple instances of same node type\n\n"
1220 " <Action ID=\"MoveToTarget\" name=\"Move to Waypoint 1\">\n"
1221 " ^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^\n"
1222 " Node type/class Human-readable name\n"
1224 " <Action ID=\"MoveToTarget\" name=\"Return to Base\">\n"
1225 " Same type Different instance name\n\n"
1226 "IN VISUAL EDITOR:\n"
1227 "The 'name' would be displayed on the node box, making the\n"
1228 "tree easier to understand at a glance.\n\n"
1230 "Use 'name' for standard compatibility and readability.";
1231 HelpDialog dlg(
this,
"Node Name Attribute - Help", helpText);
1234 labelSizer7->Add(infoBtn7, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5);
1235 labelSizer7->Add(
new wxStaticText(panel, wxID_ANY,
"Node Name Attribute:"), 0, wxALIGN_CENTER_VERTICAL);
1236 sizer->Add(labelSizer7, wxGBPosition(row, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
1238 m_nodeNameAttr->SetToolTip(
"Attribute name for node display name (e.g., 'name')");
1240 sizer->Add(
m_nodeNameAttr, wxGBPosition(row, 1), wxDefaultSpan, wxEXPAND);
1244 wxBoxSizer *labelSizer8 =
new wxBoxSizer(wxHORIZONTAL);
1245 wxBitmapButton *infoBtn8 =
new wxBitmapButton(panel, wxID_ANY, infoNormal, wxDefaultPosition, wxSize(40, 40),
1246 wxBORDER_NONE | wxBU_EXACTFIT);
1247 infoBtn8->SetBitmapHover(infoHover);
1248 infoBtn8->SetBitmapPressed(infoPressed);
1249 infoBtn8->SetBitmapDisabled(infoDisabled);
1250 infoBtn8->SetToolTip(
"Click for detailed information");
1251 infoBtn8->Bind(wxEVT_BUTTON, [
this](wxCommandEvent &) {
1252 wxString helpText =
"NODE TYPE ATTRIBUTE\n"
1253 "===========================================================\n\n"
1255 "An ALTERNATIVE attribute used for by-attribute node classification,\n"
1256 "where node category is specified via attribute instead of element name.\n\n"
1258 " - 'type' - Most common\n"
1259 " - 'category' - Alternative\n"
1260 " - 'nodeType' - Explicit variant\n\n"
1261 "WHEN IS THIS USED?\n"
1262 "Some XML formats use a SINGLE generic element with a type attribute\n"
1263 "instead of different elements for each node category:\n\n"
1264 "BY-ELEMENT APPROACH (most common):\n"
1266 " <Action name=\"Move\"/>\n"
1267 " <Condition name=\"IsClose\"/>\n"
1269 "BY-ATTRIBUTE APPROACH:\n"
1270 " <Node type=\"Sequence\">\n"
1271 " <Node type=\"Action\" name=\"Move\"/>\n"
1272 " <Node type=\"Condition\" name=\"IsClose\"/>\n"
1275 " This attribute specifies node category\n\n"
1276 "ATTRIBUTE VALUES:\n"
1277 " - 'Control', 'Action', 'Condition', 'Decorator'\n"
1278 " - Used by parser to classify nodes\n\n"
1280 "Only use this if your XML format uses by-attribute\n"
1281 "classification. Leave empty for standard element-based\n"
1282 "classification (BehaviorTree.CPP style).";
1283 HelpDialog dlg(
this,
"Node Type Attribute - Help", helpText);
1286 labelSizer8->Add(infoBtn8, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5);
1287 labelSizer8->Add(
new wxStaticText(panel, wxID_ANY,
"Node Type Attribute:"), 0, wxALIGN_CENTER_VERTICAL);
1288 sizer->Add(labelSizer8, wxGBPosition(row, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
1290 m_nodeTypeAttr->SetToolTip(
"Attribute name for node type (used in by-attribute classification)");
1292 sizer->Add(
m_nodeTypeAttr, wxGBPosition(row, 1), wxDefaultSpan, wxEXPAND);
1296 wxBoxSizer *labelSizer9 =
new wxBoxSizer(wxHORIZONTAL);
1297 wxBitmapButton *infoBtn9 =
new wxBitmapButton(panel, wxID_ANY, infoNormal, wxDefaultPosition, wxSize(40, 40),
1298 wxBORDER_NONE | wxBU_EXACTFIT);
1299 infoBtn9->SetBitmapHover(infoHover);
1300 infoBtn9->SetBitmapPressed(infoPressed);
1301 infoBtn9->SetBitmapDisabled(infoDisabled);
1302 infoBtn9->SetToolTip(
"Click for detailed information");
1303 infoBtn9->Bind(wxEVT_BUTTON, [
this](wxCommandEvent &) {
1304 wxString helpText =
"ALLOW CUSTOM ATTRIBUTES\n"
1305 "===========================================================\n\n"
1306 "Controls whether the parser preserves and stores custom/additional\n"
1307 "attributes found on nodes beyond the standard configuration attributes.\n\n"
1308 "ENABLED (Recommended):\n"
1309 " - ALL attributes on nodes are parsed and stored\n"
1310 " - Custom parameters are preserved for runtime use\n"
1311 " - Enables flexible node parameterization\n"
1312 " - Required for most practical behavior trees\n\n"
1314 " - Only recognized/standard attributes are stored\n"
1315 " - Custom attributes are IGNORED during parsing\n"
1316 " - Stricter validation, but less flexible\n"
1317 " - May lose important node parameters\n\n"
1318 "EXAMPLE (custom attributes in bold concept):\n"
1319 " <Action name=\"MoveToTarget\" \n"
1320 " speed=\"5.0\" <!-- Custom attribute -->\n"
1321 " target=\"enemy\" <!-- Custom attribute -->\n"
1322 " acceptableRadius=\"2.0\"> <!-- Custom -->\n\n"
1324 " - Actions/Conditions need parameters to work\n"
1325 " - Different node instances need different values\n"
1326 " - Runtime system reads these for behavior\n"
1327 " - Standard in BehaviorTree.CPP and most frameworks\n\n"
1329 "KEEP THIS ENABLED! Most behavior trees require custom\n"
1330 "attributes for node parameters, making trees functional\n"
1331 "and configurable.";
1332 HelpDialog dlg(
this,
"Allow Custom Attributes - Help", helpText);
1335 labelSizer9->Add(infoBtn9, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5);
1339 sizer->Add(labelSizer9, wxGBPosition(row, 0), wxGBSpan(1, 2));
1342 sizer->AddGrowableCol(1);
1343 panel->SetSizer(sizer);
1348 wxPanel *panel =
new wxPanel(notebook);
1349 wxBoxSizer *mainSizer =
new wxBoxSizer(wxVERTICAL);
1352 wxBitmap infoNormal(
GetResourcePath(
"buttons/info/Info_Normal_20.png"), wxBITMAP_TYPE_PNG);
1353 wxBitmap infoHover(
GetResourcePath(
"buttons/info/Info_Hovered_20.png"), wxBITMAP_TYPE_PNG);
1354 wxBitmap infoPressed(
GetResourcePath(
"buttons/info/Info_Pressed_20.png"), wxBITMAP_TYPE_PNG);
1355 wxBitmap infoDisabled(
GetResourcePath(
"buttons/info/Info_Disabled_20.png"), wxBITMAP_TYPE_PNG);
1358 wxBoxSizer *strategySizer =
new wxBoxSizer(wxHORIZONTAL);
1360 wxBitmapButton *infoBtn1 =
new wxBitmapButton(panel, wxID_ANY, infoNormal, wxDefaultPosition, wxSize(40, 40),
1361 wxBORDER_NONE | wxBU_EXACTFIT);
1362 infoBtn1->SetBitmapHover(infoHover);
1363 infoBtn1->SetBitmapPressed(infoPressed);
1364 infoBtn1->SetBitmapDisabled(infoDisabled);
1365 infoBtn1->SetToolTip(
"Click for detailed information");
1366 infoBtn1->Bind(wxEVT_BUTTON, [
this](wxCommandEvent &) {
1367 wxString helpText =
"CLASSIFICATION STRATEGY\n"
1368 "===========================================================\n\n"
1369 "Determines HOW the parser identifies what type of node it's dealing\n"
1370 "with when reading your XML.\n\n"
1371 "THREE STRATEGIES:\n\n"
1372 "1. BY ELEMENT NAME (Most Common)\n"
1373 " - Node type is determined by the XML element name itself\n"
1374 " - Different elements for different types\n"
1376 " <Sequence> <!-- Control node -->\n"
1377 " <Action name=\"Move\"/> <!-- Action node -->\n"
1378 " <Condition name=\"Check\"/> <!-- Condition node -->\n"
1380 " Pros: Clean, readable XML; standard in BehaviorTree.CPP\n"
1381 " Use when: You want clear, self-documenting trees\n\n"
1383 " - Single generic element with 'type' attribute\n"
1384 " - All nodes use the same element name\n"
1386 " <Node type=\"Sequence\">\n"
1387 " <Node type=\"Action\" name=\"Move\"/>\n"
1388 " <Node type=\"Condition\" name=\"Check\"/>\n"
1390 " Pros: Uniform structure; easier schema validation\n"
1391 " Use when: You need strict XML schema conformance\n\n"
1393 " - Mix of both approaches\n"
1394 " - Checks element name first, falls back to attribute\n"
1396 " <Sequence> <!-- By element name -->\n"
1397 " <Node type=\"Action\" name=\"Custom\"/> <!-- By attribute -->\n"
1398 " <Condition name=\"Check\"/> <!-- By element name -->\n"
1400 " Pros: Maximum flexibility; supports mixed formats\n"
1401 " Use when: Working with multiple XML formats\n\n"
1403 "Use 'By Element Name' for standard BehaviorTree.CPP compatibility\n"
1404 "and maximum readability.";
1405 HelpDialog dlg(
this,
"Classification Strategy - Help", helpText);
1408 strategySizer->Add(infoBtn1, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
1409 strategySizer->Add(
new wxStaticText(panel, wxID_ANY,
"Classification Strategy:"), 0,
1410 wxALIGN_CENTER_VERTICAL | wxALL, 5);
1411 wxArrayString strategyChoices;
1412 strategyChoices.Add(
"By Element Name");
1413 strategyChoices.Add(
"By Attribute");
1414 strategyChoices.Add(
"Hybrid");
1418 mainSizer->Add(strategySizer, 0, wxEXPAND);
1421 wxBoxSizer *listsHeaderSizer =
new wxBoxSizer(wxHORIZONTAL);
1424 wxBitmap infoNormal4(
GetResourcePath(
"buttons/info/Info_Normal_20.png"), wxBITMAP_TYPE_PNG);
1425 wxBitmap infoHover4(
GetResourcePath(
"buttons/info/Info_Hovered_20.png"), wxBITMAP_TYPE_PNG);
1426 wxBitmap infoPressed4(
GetResourcePath(
"buttons/info/Info_Pressed_20.png"), wxBITMAP_TYPE_PNG);
1427 wxBitmap infoDisabled4(
GetResourcePath(
"buttons/info/Info_Disabled_20.png"), wxBITMAP_TYPE_PNG);
1429 wxBitmapButton *infoBtn4 =
new wxBitmapButton(panel, wxID_ANY, infoNormal4, wxDefaultPosition, wxSize(40, 40),
1430 wxBORDER_NONE | wxBU_EXACTFIT);
1431 infoBtn4->SetBitmapHover(infoHover4);
1432 infoBtn4->SetBitmapPressed(infoPressed4);
1433 infoBtn4->SetBitmapDisabled(infoDisabled4);
1434 infoBtn4->SetToolTip(
"Click for detailed information");
1435 infoBtn4->Bind(wxEVT_BUTTON, [
this](wxCommandEvent &) {
1436 wxString helpText =
"NODE TYPE LISTS\n"
1437 "===========================================================\n\n"
1438 "These lists define the SPECIFIC NODE TYPES recognized in each\n"
1439 "category. Used for element-name and attribute-based classification.\n\n"
1441 "When the parser encounters a node, it checks if the node's name\n"
1442 "(element or attribute value) appears in one of these lists to\n"
1443 "determine its category.\n\n"
1444 "FOUR CATEGORIES:\n\n"
1445 "1. CONTROL TYPES (Required)\n"
1446 " Flow control nodes that manage child execution\n"
1447 " Common examples:\n"
1448 " - Sequence, Selector, Fallback\n"
1449 " - Parallel, ParallelSequence\n"
1450 " - ReactiveSequence, ReactiveFallback\n"
1451 " - IfThenElse, Switch, WhileDoElse\n"
1452 " These nodes MUST have at least one child\n\n"
1453 "2. DECORATOR TYPES (Required)\n"
1454 " Wrapper nodes that modify a single child's behavior\n"
1455 " Common examples:\n"
1456 " - Inverter, ForceSuccess, ForceFailure\n"
1457 " - Retry, Repeat, RepeatUntilSuccess\n"
1458 " - Timeout, Delay\n"
1459 " - KeepRunningUntilFailure\n"
1460 " These nodes MUST have exactly one child\n\n"
1461 "3. ACTION TYPES (Optional)\n"
1462 " Leaf nodes that perform tasks\n"
1463 " Common examples:\n"
1464 " - MoveToTarget, Attack, Wait\n"
1465 " - PlayAnimation, SetBlackboard\n"
1466 " - Custom action nodes\n"
1467 " Leave empty to allow any non-classified leaf as Action\n\n"
1468 "4. CONDITION TYPES (Optional)\n"
1469 " Leaf nodes that check state (instant, no RUNNING)\n"
1470 " Common examples:\n"
1471 " - IsHealthLow, IsEnemyInRange\n"
1472 " - CheckBlackboard, IsBoolTrue\n"
1473 " - Custom condition nodes\n"
1474 " Leave empty to allow any non-classified leaf as Condition\n\n"
1476 " 1. Click '+' button\n"
1477 " 2. Enter the exact node type name\n"
1478 " 3. Case-sensitive (usually)\n\n"
1479 "EXAMPLE CLASSIFICATION:\n"
1480 " Lists: Control=[Sequence, Selector], Decorator=[Inverter]\n"
1481 " XML: <Sequence> -> Control (in list)\n"
1482 " XML: <Inverter> -> Decorator (in list)\n"
1483 " XML: <CustomAction> -> Action (not in any list)\n\n"
1485 "Always define Control and Decorator types. Leave Action/Condition\n"
1486 "empty for maximum flexibility unless you need strict validation.";
1487 HelpDialog dlg(
this,
"Node Type Lists - Help", helpText);
1490 listsHeaderSizer->Add(infoBtn4, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
1491 wxStaticText *listsLabel =
new wxStaticText(panel, wxID_ANY,
"Node Type Recognition Lists:");
1492 wxFont font = listsLabel->GetFont();
1493 font.SetWeight(wxFONTWEIGHT_BOLD);
1494 listsLabel->SetFont(font);
1495 listsHeaderSizer->Add(listsLabel, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
1496 mainSizer->Add(listsHeaderSizer, 0, wxEXPAND);
1499 wxBoxSizer *listsGrid =
new wxBoxSizer(wxHORIZONTAL);
1502 wxStaticBoxSizer *controlBox =
new wxStaticBoxSizer(wxVERTICAL, panel,
"Control Types");
1505 wxBoxSizer *controlBtnSizer =
new wxBoxSizer(wxHORIZONTAL);
1510 controlBox->Add(controlBtnSizer, 0, wxEXPAND);
1511 listsGrid->Add(controlBox, 1, wxEXPAND | wxALL, 5);
1514 wxStaticBoxSizer *decoratorBox =
new wxStaticBoxSizer(wxVERTICAL, panel,
"Decorator Types");
1517 wxBoxSizer *decoratorBtnSizer =
new wxBoxSizer(wxHORIZONTAL);
1522 decoratorBox->Add(decoratorBtnSizer, 0, wxEXPAND);
1523 listsGrid->Add(decoratorBox, 1, wxEXPAND | wxALL, 5);
1525 mainSizer->Add(listsGrid, 1, wxEXPAND);
1528 wxBoxSizer *listsGrid2 =
new wxBoxSizer(wxHORIZONTAL);
1531 wxStaticBoxSizer *actionBox =
new wxStaticBoxSizer(wxVERTICAL, panel,
"Action Types (optional)");
1534 wxBoxSizer *actionBtnSizer =
new wxBoxSizer(wxHORIZONTAL);
1539 actionBox->Add(actionBtnSizer, 0, wxEXPAND);
1540 listsGrid2->Add(actionBox, 1, wxEXPAND | wxALL, 5);
1543 wxStaticBoxSizer *conditionBox =
new wxStaticBoxSizer(wxVERTICAL, panel,
"Condition Types (optional)");
1546 wxBoxSizer *conditionBtnSizer =
new wxBoxSizer(wxHORIZONTAL);
1551 conditionBox->Add(conditionBtnSizer, 0, wxEXPAND);
1552 listsGrid2->Add(conditionBox, 1, wxEXPAND | wxALL, 5);
1554 mainSizer->Add(listsGrid2, 1, wxEXPAND);
1557 wxBoxSizer *unknownSizer =
new wxBoxSizer(wxHORIZONTAL);
1560 wxBitmap infoNormal2(
GetResourcePath(
"buttons/info/Info_Normal_20.png"), wxBITMAP_TYPE_PNG);
1561 wxBitmap infoHover2(
GetResourcePath(
"buttons/info/Info_Hovered_20.png"), wxBITMAP_TYPE_PNG);
1562 wxBitmap infoPressed2(
GetResourcePath(
"buttons/info/Info_Pressed_20.png"), wxBITMAP_TYPE_PNG);
1563 wxBitmap infoDisabled2(
GetResourcePath(
"buttons/info/Info_Disabled_20.png"), wxBITMAP_TYPE_PNG);
1565 wxBitmapButton *infoBtn2 =
new wxBitmapButton(panel, wxID_ANY, infoNormal2, wxDefaultPosition, wxSize(40, 40),
1566 wxBORDER_NONE | wxBU_EXACTFIT);
1567 infoBtn2->SetBitmapHover(infoHover2);
1568 infoBtn2->SetBitmapPressed(infoPressed2);
1569 infoBtn2->SetBitmapDisabled(infoDisabled2);
1570 infoBtn2->SetToolTip(
"Click for detailed information");
1571 infoBtn2->Bind(wxEVT_BUTTON, [
this](wxCommandEvent &) {
1572 wxString helpText =
"UNKNOWN TYPE BEHAVIOR\n"
1573 "===========================================================\n\n"
1574 "Determines what happens when the parser encounters a node type\n"
1575 "that is NOT in your defined type lists (Control, Decorator, etc.).\n\n"
1576 "THREE OPTIONS:\n\n"
1577 "1. ERROR (Strict - Recommended for Development)\n"
1578 " - Parser STOPS and reports an error\n"
1579 " - File loading FAILS\n"
1580 " - Ensures all node types are explicitly defined\n"
1581 " Example: <UnknownNode/> causes parsing to fail\n"
1583 " - Developing new trees - catch typos early\n"
1584 " - Want strict validation\n"
1585 " - Need to ensure only known types are used\n\n"
1586 "2. WARNING (Permissive)\n"
1587 " - Parser CONTINUES but logs a warning\n"
1588 " - File loads successfully\n"
1589 " - Unknown node is treated as Generic Node\n"
1590 " Example: <UnknownNode/> becomes a generic node + warning\n"
1592 " - Working with mixed/evolving formats\n"
1593 " - Want to see what's unrecognized but still load\n"
1594 " - Debugging format compatibility\n\n"
1595 "3. GENERIC NODE (Silent Fallback)\n"
1596 " - Parser treats unknown types as generic nodes\n"
1597 " - NO warning or error\n"
1598 " - Maximum compatibility\n"
1599 " Example: <UnknownNode/> silently becomes generic node\n"
1601 " - Working with highly variable XML formats\n"
1602 " - Want maximum flexibility\n"
1603 " - Already validated your trees externally\n\n"
1605 "Use ERROR during development to catch typos and undefined types.\n"
1606 "Use WARNING in production if you need to support evolving formats.";
1607 HelpDialog dlg(
this,
"Unknown Type Behavior - Help", helpText);
1610 unknownSizer->Add(infoBtn2, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
1611 unknownSizer->Add(
new wxStaticText(panel, wxID_ANY,
"Unknown Type Behavior:"), 0, wxALIGN_CENTER_VERTICAL | wxALL,
1613 wxArrayString unknownChoices;
1614 unknownChoices.Add(
"Error");
1615 unknownChoices.Add(
"Warning");
1616 unknownChoices.Add(
"Generic Node");
1617 m_unknownBehavior =
new wxChoice(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, unknownChoices);
1620 mainSizer->Add(unknownSizer, 0, wxEXPAND);
1623 wxBoxSizer *typeAttrSizer =
new wxBoxSizer(wxHORIZONTAL);
1626 wxBitmap infoNormal3(
GetResourcePath(
"buttons/info/Info_Normal_20.png"), wxBITMAP_TYPE_PNG);
1627 wxBitmap infoHover3(
GetResourcePath(
"buttons/info/Info_Hovered_20.png"), wxBITMAP_TYPE_PNG);
1628 wxBitmap infoPressed3(
GetResourcePath(
"buttons/info/Info_Pressed_20.png"), wxBITMAP_TYPE_PNG);
1629 wxBitmap infoDisabled3(
GetResourcePath(
"buttons/info/Info_Disabled_20.png"), wxBITMAP_TYPE_PNG);
1631 wxBitmapButton *infoBtn3 =
new wxBitmapButton(panel, wxID_ANY, infoNormal3, wxDefaultPosition, wxSize(40, 40),
1632 wxBORDER_NONE | wxBU_EXACTFIT);
1633 infoBtn3->SetBitmapHover(infoHover3);
1634 infoBtn3->SetBitmapPressed(infoPressed3);
1635 infoBtn3->SetBitmapDisabled(infoDisabled3);
1636 infoBtn3->SetToolTip(
"Click for detailed information");
1637 infoBtn3->Bind(wxEVT_BUTTON, [
this](wxCommandEvent &) {
1638 wxString helpText =
"TYPE ATTRIBUTE NAME\n"
1639 "===========================================================\n\n"
1640 "The XML attribute name used for by-attribute node classification.\n"
1641 "Only relevant when using 'By Attribute' or 'Hybrid' strategy.\n\n"
1643 "When using attribute-based classification, this attribute specifies\n"
1644 "the node category (Control, Action, Condition, Decorator).\n\n"
1646 " - 'type' - Most common standard\n"
1647 " - 'nodeType' - Explicit variant\n"
1648 " - 'category' - Alternative naming\n\n"
1650 "BY ATTRIBUTE STRATEGY:\n"
1651 " <Node type=\"Sequence\"> <!-- 'type' is the attribute -->\n"
1652 " <Node type=\"Action\" name=\"Move\"/>\n"
1653 " <Node type=\"Condition\" name=\"Check\"/>\n"
1655 " The parser reads the 'type' attribute to determine:\n"
1656 " - 'Sequence' -> Control node (from Control Types list)\n"
1657 " - 'Action' -> Action node (from Action Types list)\n"
1658 " - 'Condition' -> Condition node (from Condition Types list)\n\n"
1659 "HYBRID STRATEGY:\n"
1660 " <Sequence> <!-- Element name = Control -->\n"
1661 " <Node type=\"Action\" name=\"Custom\"/> <!-- Attribute -->\n"
1662 " <Condition name=\"Check\"/> <!-- Element name -->\n"
1664 " Parser checks element name first, falls back to attribute.\n\n"
1665 "BY ELEMENT NAME STRATEGY:\n"
1666 " This setting is IGNORED (not used)\n\n"
1667 "CLASSIFICATION FLOW:\n"
1668 " 1. Read node's type attribute value\n"
1669 " 2. Check if value is in Control Types -> Control node\n"
1670 " 3. Check if value is in Decorator Types -> Decorator node\n"
1671 " 4. Check if value is in Action Types -> Action node\n"
1672 " 5. Check if value is in Condition Types -> Condition node\n"
1673 " 6. Not found -> Apply Unknown Type Behavior\n\n"
1675 "Use 'type' for standard compatibility. Leave empty if using\n"
1676 "'By Element Name' strategy exclusively.";
1677 HelpDialog dlg(
this,
"Type Attribute Name - Help", helpText);
1680 typeAttrSizer->Add(infoBtn3, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
1681 typeAttrSizer->Add(
new wxStaticText(panel, wxID_ANY,
"Type Attribute Name:"), 0, wxALIGN_CENTER_VERTICAL | wxALL,
1684 m_typeAttrName->SetToolTip(
"Attribute name used for by-attribute classification");
1687 mainSizer->Add(typeAttrSizer, 0, wxEXPAND);
1689 panel->SetSizer(mainSizer);
1694 wxPanel *panel =
new wxPanel(notebook);
1695 wxBoxSizer *mainSizer =
new wxBoxSizer(wxVERTICAL);
1698 wxBitmap infoNormal(
GetResourcePath(
"buttons/info/Info_Normal_20.png"), wxBITMAP_TYPE_PNG);
1699 wxBitmap infoHover(
GetResourcePath(
"buttons/info/Info_Hovered_20.png"), wxBITMAP_TYPE_PNG);
1700 wxBitmap infoPressed(
GetResourcePath(
"buttons/info/Info_Pressed_20.png"), wxBITMAP_TYPE_PNG);
1701 wxBitmap infoDisabled(
GetResourcePath(
"buttons/info/Info_Disabled_20.png"), wxBITMAP_TYPE_PNG);
1704 wxGridBagSizer *basicSizer =
new wxGridBagSizer(5, 5);
1708 wxBoxSizer *labelSizer1 =
new wxBoxSizer(wxHORIZONTAL);
1709 wxBitmapButton *infoBtn1 =
new wxBitmapButton(panel, wxID_ANY, infoNormal, wxDefaultPosition, wxSize(40, 40),
1710 wxBORDER_NONE | wxBU_EXACTFIT);
1711 infoBtn1->SetBitmapHover(infoHover);
1712 infoBtn1->SetBitmapPressed(infoPressed);
1713 infoBtn1->SetBitmapDisabled(infoDisabled);
1714 infoBtn1->SetToolTip(
"Click for detailed information");
1715 infoBtn1->Bind(wxEVT_BUTTON, [
this](wxCommandEvent &) {
1716 wxString helpText =
"BLACKBOARD ELEMENT\n"
1717 "===========================================================\n\n"
1719 "The XML element name that represents a blackboard definition - a\n"
1720 "shared data storage that behavior trees use to store and access variables.\n\n"
1722 " - 'BlackboardModel' - BehaviorTree.CPP standard\n"
1723 " - 'Blackboard' - Simplified variant\n"
1724 " - 'Variables' - Alternative naming\n\n"
1725 "WHAT IS A BLACKBOARD?\n"
1726 "A blackboard is a KEY-VALUE data store that:\n"
1727 " - Stores variables shared across the behavior tree\n"
1728 " - Provides data for condition checks and actions\n"
1729 " - Can be defined once and used by multiple trees\n"
1730 " - Supports typed data (int, float, string, bool, etc.)\n\n"
1733 " <BlackboardModel ID=\"PlayerBlackboard\">\n"
1734 " <Entry key=\"health\" type=\"int\" value=\"100\"/>\n"
1735 " <Entry key=\"target\" type=\"string\"/>\n"
1736 " <Entry key=\"isAggressive\" type=\"bool\" value=\"false\"/>\n"
1737 " </BlackboardModel>\n\n"
1738 " <BehaviorTree ID=\"MainAI\" blackboard=\"PlayerBlackboard\">\n"
1739 " <!-- Tree uses the blackboard -->\n"
1740 " </BehaviorTree>\n"
1742 "WHY USE BLACKBOARDS?\n"
1743 " - Share data between different parts of the tree\n"
1744 " - Parameterize behavior trees for reusability\n"
1745 " - Type-safe data access\n"
1746 " - Runtime variable inspection and debugging";
1747 HelpDialog dlg(
this,
"Blackboard Element - Help", helpText);
1750 labelSizer1->Add(infoBtn1, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5);
1751 labelSizer1->Add(
new wxStaticText(panel, wxID_ANY,
"Blackboard Element:"), 0, wxALIGN_CENTER_VERTICAL);
1752 basicSizer->Add(labelSizer1, wxGBPosition(row, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
1759 wxBoxSizer *labelSizer2 =
new wxBoxSizer(wxHORIZONTAL);
1760 wxBitmapButton *infoBtn2 =
new wxBitmapButton(panel, wxID_ANY, infoNormal, wxDefaultPosition, wxSize(40, 40),
1761 wxBORDER_NONE | wxBU_EXACTFIT);
1762 infoBtn2->SetBitmapHover(infoHover);
1763 infoBtn2->SetBitmapPressed(infoPressed);
1764 infoBtn2->SetBitmapDisabled(infoDisabled);
1765 infoBtn2->SetToolTip(
"Click for detailed information");
1766 infoBtn2->Bind(wxEVT_BUTTON, [
this](wxCommandEvent &) {
1767 wxString helpText =
"BLACKBOARD ID ATTRIBUTE\n"
1768 "===========================================================\n\n"
1770 "The XML attribute name that contains the unique identifier for\n"
1771 "each blackboard definition.\n\n"
1773 " - 'ID' - Standard naming (most common)\n"
1774 " - 'name' - Alternative\n"
1775 " - 'id' - Lowercase variant\n\n"
1776 "WHY IS IT NEEDED?\n"
1778 " - Multiple blackboard definitions in one file\n"
1779 " - Behavior trees to reference specific blackboards\n"
1780 " - Blackboard inheritance (one extends another)\n"
1781 " - Runtime blackboard lookup by name\n\n"
1783 " <BlackboardModel ID=\"BaseAI\">\n"
1784 " <Entry key=\"speed\" type=\"float\" value=\"5.0\"/>\n"
1785 " </BlackboardModel>\n\n"
1786 " <BlackboardModel ID=\"EnemyAI\" parent=\"BaseAI\">\n"
1787 " <Entry key=\"health\" type=\"int\" value=\"100\"/>\n"
1788 " <!-- Inherits 'speed' from BaseAI -->\n"
1789 " </BlackboardModel>\n\n"
1790 " <BehaviorTree ID=\"Enemy\" blackboard=\"EnemyAI\">\n"
1791 " ^^^^^^^^^^^^^^^^^^^\n"
1792 " References blackboard by ID\n"
1793 " </BehaviorTree>\n\n"
1795 "Use 'ID' for consistency with BehaviorTree.CPP standard.";
1796 HelpDialog dlg(
this,
"Blackboard ID Attribute - Help", helpText);
1799 labelSizer2->Add(infoBtn2, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5);
1800 labelSizer2->Add(
new wxStaticText(panel, wxID_ANY,
"Blackboard ID Attribute:"), 0, wxALIGN_CENTER_VERTICAL);
1801 basicSizer->Add(labelSizer2, wxGBPosition(row, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
1808 wxBoxSizer *labelSizer3 =
new wxBoxSizer(wxHORIZONTAL);
1809 wxBitmapButton *infoBtn3 =
new wxBitmapButton(panel, wxID_ANY, infoNormal, wxDefaultPosition, wxSize(40, 40),
1810 wxBORDER_NONE | wxBU_EXACTFIT);
1811 infoBtn3->SetBitmapHover(infoHover);
1812 infoBtn3->SetBitmapPressed(infoPressed);
1813 infoBtn3->SetBitmapDisabled(infoDisabled);
1814 infoBtn3->SetToolTip(
"Click for detailed information");
1815 infoBtn3->Bind(wxEVT_BUTTON, [
this](wxCommandEvent &) {
1816 wxString helpText =
"PARENT/INHERITANCE ATTRIBUTE\n"
1817 "===========================================================\n\n"
1819 "The XML attribute name that specifies a parent blackboard from\n"
1820 "which the current blackboard inherits entries.\n\n"
1822 " - 'parent' - Most common\n"
1823 " - 'extends' - Object-oriented terminology\n"
1824 " - 'inherits' - Explicit naming\n"
1825 " - 'base' - Alternative\n\n"
1826 "HOW INHERITANCE WORKS:\n"
1827 "A child blackboard:\n"
1828 " - Inherits ALL entries from its parent\n"
1829 " - Can add NEW entries not in the parent\n"
1830 " - Can OVERRIDE parent entries with different defaults\n"
1831 " - Cannot remove parent entries\n\n"
1833 " <BlackboardModel ID=\"BaseCharacter\">\n"
1834 " <Entry key=\"health\" type=\"int\" value=\"100\"/>\n"
1835 " <Entry key=\"speed\" type=\"float\" value=\"5.0\"/>\n"
1836 " </BlackboardModel>\n\n"
1837 " <BlackboardModel ID=\"Player\" parent=\"BaseCharacter\">\n"
1838 " <Entry key=\"mana\" type=\"int\" value=\"50\"/>\n"
1839 " <Entry key=\"speed\" type=\"float\" value=\"7.0\"/>\n"
1840 " <!-- Inherits: health=100 (from parent) -->\n"
1841 " <!-- Overrides: speed=7.0 (not 5.0) -->\n"
1842 " <!-- Adds: mana=50 (new entry) -->\n"
1843 " </BlackboardModel>\n\n"
1845 " - Reduce duplication in blackboard definitions\n"
1846 " - Create base templates for common variables\n"
1847 " - Organize related blackboards hierarchically";
1848 HelpDialog dlg(
this,
"Parent/Inheritance Attribute - Help", helpText);
1851 labelSizer3->Add(infoBtn3, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5);
1852 labelSizer3->Add(
new wxStaticText(panel, wxID_ANY,
"Parent/Inheritance Attribute:"), 0, wxALIGN_CENTER_VERTICAL);
1853 basicSizer->Add(labelSizer3, wxGBPosition(row, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
1860 wxBoxSizer *labelSizer4 =
new wxBoxSizer(wxHORIZONTAL);
1861 wxBitmapButton *infoBtn4 =
new wxBitmapButton(panel, wxID_ANY, infoNormal, wxDefaultPosition, wxSize(40, 40),
1862 wxBORDER_NONE | wxBU_EXACTFIT);
1863 infoBtn4->SetBitmapHover(infoHover);
1864 infoBtn4->SetBitmapPressed(infoPressed);
1865 infoBtn4->SetBitmapDisabled(infoDisabled);
1866 infoBtn4->SetToolTip(
"Click for detailed information");
1867 infoBtn4->Bind(wxEVT_BUTTON, [
this](wxCommandEvent &) {
1868 wxString helpText =
"ENTRY ELEMENT\n"
1869 "===========================================================\n\n"
1871 "The XML element name that represents a single variable/entry\n"
1872 "within a blackboard definition.\n\n"
1874 " - 'Entry' - BehaviorTree.CPP standard\n"
1875 " - 'Variable' - Descriptive alternative\n"
1876 " - 'Field' - Object-oriented terminology\n"
1877 " - 'Property' - Another variant\n\n"
1878 "WHAT IS AN ENTRY?\n"
1879 "Each entry represents ONE variable in the blackboard:\n"
1880 " - Has a KEY (variable name)\n"
1881 " - Has a TYPE (int, float, string, bool, etc.)\n"
1882 " - May have a DEFAULT VALUE\n"
1883 " - Can be read/written by nodes during execution\n\n"
1885 " <BlackboardModel ID=\"GameAI\">\n"
1886 " <Entry key=\"playerHealth\" type=\"int\" value=\"100\"/>\n"
1887 " <Entry key=\"targetPosition\" type=\"Vector3\"/>\n"
1888 " <Entry key=\"isAlerted\" type=\"bool\" value=\"false\"/>\n"
1889 " <Entry key=\"patrolSpeed\" type=\"float\" value=\"2.5\"/>\n"
1890 " <Entry key=\"weaponName\" type=\"string\" value=\"Sword\"/>\n"
1891 " </BlackboardModel>\n\n"
1892 "USAGE IN BEHAVIOR TREE:\n"
1893 " <Condition name=\"CheckHealth\">\n"
1894 " <input key=\"health\" blackboard_key=\"playerHealth\"/>\n"
1896 " <Action name=\"SetAlert\">\n"
1897 " <output key=\"isAlerted\" blackboard_key=\"isAlerted\" value=\"true\"/>\n"
1899 HelpDialog dlg(
this,
"Entry Element - Help", helpText);
1902 labelSizer4->Add(infoBtn4, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5);
1903 labelSizer4->Add(
new wxStaticText(panel, wxID_ANY,
"Entry Element:"), 0, wxALIGN_CENTER_VERTICAL);
1904 basicSizer->Add(labelSizer4, wxGBPosition(row, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
1907 basicSizer->Add(
m_entryElement, wxGBPosition(row, 1), wxDefaultSpan, wxEXPAND);
1911 wxBoxSizer *labelSizer5 =
new wxBoxSizer(wxHORIZONTAL);
1912 wxBitmapButton *infoBtn5 =
new wxBitmapButton(panel, wxID_ANY, infoNormal, wxDefaultPosition, wxSize(40, 40),
1913 wxBORDER_NONE | wxBU_EXACTFIT);
1914 infoBtn5->SetBitmapHover(infoHover);
1915 infoBtn5->SetBitmapPressed(infoPressed);
1916 infoBtn5->SetBitmapDisabled(infoDisabled);
1917 infoBtn5->SetToolTip(
"Click for detailed information");
1918 infoBtn5->Bind(wxEVT_BUTTON, [
this](wxCommandEvent &) {
1919 wxString helpText =
"ENTRY KEY ATTRIBUTE\n"
1920 "===========================================================\n\n"
1922 "The XML attribute name that contains the KEY (variable name)\n"
1923 "for a blackboard entry.\n\n"
1925 " - 'key' - BehaviorTree.CPP standard\n"
1926 " - 'name' - Alternative common usage\n"
1927 " - 'id' - Some implementations\n\n"
1929 "The key is the UNIQUE IDENTIFIER for a variable within a blackboard:\n"
1930 " - Acts as the variable name\n"
1931 " - Used to read/write the value at runtime\n"
1932 " - Must be unique within the blackboard\n"
1933 " - Case-sensitive (usually)\n\n"
1935 " <Entry key=\"playerHealth\" type=\"int\" value=\"100\"/>\n"
1936 " ^^^^^^^^^^^^^^^^^^^\n"
1937 " This is the key - the variable name\n\n"
1938 " <!-- In behavior tree nodes: -->\n"
1939 " <Condition name=\"IsHealthLow\">\n"
1940 " <input key=\"health\" blackboard_key=\"playerHealth\"/>\n"
1941 " ^^^^^^^^^^^^^^^^^\n"
1942 " References by key\n"
1944 "NAMING CONVENTIONS:\n"
1945 " - camelCase: playerHealth, maxSpeed, isActive\n"
1946 " - snake_case: player_health, max_speed, is_active\n"
1947 " - PascalCase: PlayerHealth, MaxSpeed, IsActive\n\n"
1949 "Use descriptive, consistent names following your project's\n"
1950 "naming convention. Common standard is camelCase.";
1951 HelpDialog dlg(
this,
"Entry Key Attribute - Help", helpText);
1954 labelSizer5->Add(infoBtn5, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5);
1955 labelSizer5->Add(
new wxStaticText(panel, wxID_ANY,
"Entry Key Attribute:"), 0, wxALIGN_CENTER_VERTICAL);
1956 basicSizer->Add(labelSizer5, wxGBPosition(row, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
1959 basicSizer->Add(
m_entryKeyAttr, wxGBPosition(row, 1), wxDefaultSpan, wxEXPAND);
1963 wxBoxSizer *labelSizer6 =
new wxBoxSizer(wxHORIZONTAL);
1964 wxBitmapButton *infoBtn6 =
new wxBitmapButton(panel, wxID_ANY, infoNormal, wxDefaultPosition, wxSize(40, 40),
1965 wxBORDER_NONE | wxBU_EXACTFIT);
1966 infoBtn6->SetBitmapHover(infoHover);
1967 infoBtn6->SetBitmapPressed(infoPressed);
1968 infoBtn6->SetBitmapDisabled(infoDisabled);
1969 infoBtn6->SetToolTip(
"Click for detailed information");
1970 infoBtn6->Bind(wxEVT_BUTTON, [
this](wxCommandEvent &) {
1971 wxString helpText =
"ENTRY TYPE ATTRIBUTE\n"
1972 "===========================================================\n\n"
1974 "The XML attribute name that specifies the DATA TYPE for a\n"
1975 "blackboard entry (int, float, string, bool, etc.).\n\n"
1977 " - 'type' - Most common standard\n"
1978 " - 'dataType' - Explicit variant\n"
1979 " - 'valueType' - Alternative\n\n"
1980 "SUPPORTED TYPES (typical):\n"
1982 " - 'int' / 'integer' - Whole numbers (e.g., 42, -10)\n"
1983 " - 'float' / 'double' - Decimals (e.g., 3.14, -2.5)\n"
1984 " - 'bool' / 'boolean' - true/false\n"
1985 " - 'string' - Text (e.g., \"Hello\", \"weapon_1\")\n\n"
1986 " ADVANCED (depends on implementation):\n"
1987 " - 'Vector2' / 'Vector3' - Position/direction\n"
1988 " - 'Pose' / 'Pose2D' - Position + rotation\n"
1989 " - 'array' - List of values\n"
1990 " - 'object' - Complex custom types\n\n"
1992 " <Entry key=\"health\" type=\"int\" value=\"100\"/>\n"
1993 " <Entry key=\"speed\" type=\"float\" value=\"5.5\"/>\n"
1994 " <Entry key=\"isAlive\" type=\"bool\" value=\"true\"/>\n"
1995 " <Entry key=\"name\" type=\"string\" value=\"Player\"/>\n"
1996 " <Entry key=\"position\" type=\"Vector3\"/>\n\n"
1997 "WHY TYPES MATTER:\n"
1998 " - Type safety: prevent wrong value assignments\n"
1999 " - Runtime validation\n"
2000 " - Editor support (proper UI widgets)\n"
2001 " - Performance optimization";
2002 HelpDialog dlg(
this,
"Entry Type Attribute - Help", helpText);
2005 labelSizer6->Add(infoBtn6, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5);
2006 labelSizer6->Add(
new wxStaticText(panel, wxID_ANY,
"Entry Type Attribute:"), 0, wxALIGN_CENTER_VERTICAL);
2007 basicSizer->Add(labelSizer6, wxGBPosition(row, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
2010 basicSizer->Add(
m_entryTypeAttr, wxGBPosition(row, 1), wxDefaultSpan, wxEXPAND);
2014 wxBoxSizer *labelSizer7 =
new wxBoxSizer(wxHORIZONTAL);
2015 wxBitmapButton *infoBtn7 =
new wxBitmapButton(panel, wxID_ANY, infoNormal, wxDefaultPosition, wxSize(40, 40),
2016 wxBORDER_NONE | wxBU_EXACTFIT);
2017 infoBtn7->SetBitmapHover(infoHover);
2018 infoBtn7->SetBitmapPressed(infoPressed);
2019 infoBtn7->SetBitmapDisabled(infoDisabled);
2020 infoBtn7->SetToolTip(
"Click for detailed information");
2021 infoBtn7->Bind(wxEVT_BUTTON, [
this](wxCommandEvent &) {
2022 wxString helpText =
"ENTRY VALUE ATTRIBUTE\n"
2023 "===========================================================\n\n"
2025 "The XML attribute name that contains the DEFAULT VALUE for a\n"
2026 "blackboard entry.\n\n"
2028 " - 'value' - Most common\n"
2029 " - 'default' - Explicit naming\n"
2030 " - 'defaultValue' - Verbose variant\n\n"
2031 "WHAT IS A DEFAULT VALUE?\n"
2032 "The default value is the INITIAL value assigned when:\n"
2033 " - A blackboard is first created/instantiated\n"
2034 " - A behavior tree starts executing\n"
2035 " - The blackboard is reset\n\n"
2036 "OPTIONAL vs REQUIRED:\n"
2037 " - Some entries HAVE defaults (value specified)\n"
2038 " - Some entries DON'T (must be set at runtime)\n\n"
2040 " <Entry key=\"health\" type=\"int\" value=\"100\"/>\n"
2042 " Starts with 100\n\n"
2043 " <Entry key=\"currentTarget\" type=\"string\"/>\n"
2044 " No default - must be set\n\n"
2045 " <Entry key=\"isAlerted\" type=\"bool\" value=\"false\"/>\n"
2046 " ^^^^^^^^^^^^^^^^\n"
2047 " Starts as false\n\n"
2048 "TYPE-SPECIFIC FORMATS:\n"
2049 " - int: \"42\", \"-10\", \"0\"\n"
2050 " - float: \"3.14\", \"-2.5\", \"0.0\"\n"
2051 " - bool: \"true\", \"false\" (case-insensitive)\n"
2052 " - string: \"PlayerName\", \"idle_animation\"\n"
2053 " - Vector3: \"1.0,2.0,3.0\" (comma-separated)\n\n"
2055 "Provide sensible defaults when possible to make trees\n"
2056 "more self-contained and easier to test.";
2057 HelpDialog dlg(
this,
"Entry Value Attribute - Help", helpText);
2060 labelSizer7->Add(infoBtn7, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5);
2061 labelSizer7->Add(
new wxStaticText(panel, wxID_ANY,
"Entry Value Attribute:"), 0, wxALIGN_CENTER_VERTICAL);
2062 basicSizer->Add(labelSizer7, wxGBPosition(row, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
2065 basicSizer->Add(
m_entryValueAttr, wxGBPosition(row, 1), wxDefaultSpan, wxEXPAND);
2068 basicSizer->AddGrowableCol(1);
2069 mainSizer->Add(basicSizer, 0, wxEXPAND | wxALL, 5);
2072 wxStaticBoxSizer *mappingsBox =
new wxStaticBoxSizer(wxVERTICAL, panel,
"Data Type Mappings");
2085 wxBoxSizer *mappingBtnSizer =
new wxBoxSizer(wxHORIZONTAL);
2090 mappingsBox->Add(mappingBtnSizer, 0);
2092 mainSizer->Add(mappingsBox, 1, wxEXPAND | wxALL, 5);
2098 panel->SetSizer(mainSizer);
2103 wxPanel *panel =
new wxPanel(notebook);
2104 wxBoxSizer *mainSizer =
new wxBoxSizer(wxVERTICAL);
2107 wxBitmap infoNormal(
GetResourcePath(
"buttons/info/Info_Normal_20.png"), wxBITMAP_TYPE_PNG);
2108 wxBitmap infoHover(
GetResourcePath(
"buttons/info/Info_Hovered_20.png"), wxBITMAP_TYPE_PNG);
2109 wxBitmap infoPressed(
GetResourcePath(
"buttons/info/Info_Pressed_20.png"), wxBITMAP_TYPE_PNG);
2110 wxBitmap infoDisabled(
GetResourcePath(
"buttons/info/Info_Disabled_20.png"), wxBITMAP_TYPE_PNG);
2113 wxGridBagSizer *sizer =
new wxGridBagSizer(5, 5);
2117 wxBoxSizer *labelSizer1 =
new wxBoxSizer(wxHORIZONTAL);
2118 wxBitmapButton *infoBtn1 =
new wxBitmapButton(panel, wxID_ANY, infoNormal, wxDefaultPosition, wxSize(40, 40),
2119 wxBORDER_NONE | wxBU_EXACTFIT);
2120 infoBtn1->SetBitmapHover(infoHover);
2121 infoBtn1->SetBitmapPressed(infoPressed);
2122 infoBtn1->SetBitmapDisabled(infoDisabled);
2123 infoBtn1->SetToolTip(
"Click for detailed information");
2124 infoBtn1->Bind(wxEVT_BUTTON, [
this](wxCommandEvent &) {
2125 wxString helpText =
"ENABLE PROGRESS REPORTING\n"
2126 "===========================================================\n\n"
2128 "Controls whether the parser reports progress updates during XML\n"
2129 "parsing operations, especially useful for large files.\n\n"
2131 " - Parser emits progress callbacks during parsing\n"
2132 " - UI can show loading bars or progress indicators\n"
2133 " - Helps prevent \"app not responding\" appearance\n"
2134 " - Useful for files > 1000 nodes\n"
2135 " - Small performance overhead (~2-5%)\n\n"
2137 " - No progress updates\n"
2138 " - Slightly faster parsing\n"
2139 " - Simpler implementation\n"
2140 " - Best for small/medium files\n\n"
2143 " - Loading very large behavior tree files\n"
2144 " - Need to show user feedback during loading\n"
2145 " - Parsing operations take > 1 second\n\n"
2147 " - Working with small files (< 100 nodes)\n"
2148 " - Maximum parsing speed is priority\n"
2149 " - No UI for displaying progress\n\n"
2151 "Enable for production applications to improve user experience\n"
2152 "when loading large behavior tree files.";
2153 HelpDialog dlg(
this,
"Progress Reporting - Help", helpText);
2156 labelSizer1->Add(infoBtn1, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5);
2160 sizer->Add(labelSizer1, wxGBPosition(row, 0), wxGBSpan(1, 2));
2164 wxBoxSizer *labelSizer2 =
new wxBoxSizer(wxHORIZONTAL);
2165 wxBitmap infoNormal2(
GetResourcePath(
"buttons/info/Info_Normal_20.png"), wxBITMAP_TYPE_PNG);
2166 wxBitmap infoHover2(
GetResourcePath(
"buttons/info/Info_Hovered_20.png"), wxBITMAP_TYPE_PNG);
2167 wxBitmap infoPressed2(
GetResourcePath(
"buttons/info/Info_Pressed_20.png"), wxBITMAP_TYPE_PNG);
2168 wxBitmap infoDisabled2(
GetResourcePath(
"buttons/info/Info_Disabled_20.png"), wxBITMAP_TYPE_PNG);
2169 wxBitmapButton *infoBtn2 =
new wxBitmapButton(panel, wxID_ANY, infoNormal2, wxDefaultPosition, wxSize(40, 40),
2170 wxBORDER_NONE | wxBU_EXACTFIT);
2171 infoBtn2->SetBitmapHover(infoHover2);
2172 infoBtn2->SetBitmapPressed(infoPressed2);
2173 infoBtn2->SetBitmapDisabled(infoDisabled2);
2174 infoBtn2->SetToolTip(
"Click for detailed information");
2175 infoBtn2->Bind(wxEVT_BUTTON, [
this](wxCommandEvent &) {
2176 wxString helpText =
"DETAILED ERROR MESSAGES\n"
2177 "===========================================================\n\n"
2178 "Controls the verbosity of error messages when parsing fails.\n\n"
2179 "ENABLED (Recommended for Development):\n"
2180 " - Full error descriptions with context\n"
2181 " - Shows exact line and column numbers\n"
2182 " - Includes surrounding XML context\n"
2183 " - Lists all violated validation rules\n"
2184 " - Suggests possible fixes\n\n"
2185 "Example detailed error:\n"
2186 " ERROR at line 42, column 15:\n"
2187 " Unknown element 'Sequenc' found.\n"
2188 " Context: <Sequenc name=\"Patrol\">\n"
2189 " Did you mean: 'Sequence'?\n"
2190 " Valid elements: Sequence, Selector, Parallel\n\n"
2191 "DISABLED (Production):\n"
2192 " - Brief error messages\n"
2193 " - Just error type and location\n"
2194 " - Less information leakage\n"
2195 " - Slightly faster\n\n"
2196 "Example simple error:\n"
2197 " Parse error at line 42: Unknown element\n\n"
2200 " - Developing behavior trees\n"
2201 " - Debugging XML format issues\n"
2202 " - Users need helpful error messages\n\n"
2204 " - Production/release builds\n"
2205 " - Security concerns about information disclosure\n"
2206 " - Minimal error output desired\n\n"
2208 "Keep ENABLED during development. Consider disabling for\n"
2209 "production if error details are security-sensitive.";
2210 HelpDialog dlg(
this,
"Detailed Error Messages - Help", helpText);
2213 labelSizer2->Add(infoBtn2, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5);
2214 m_detailedErrors =
new wxCheckBox(panel, wxID_ANY,
"Detailed Error Messages");
2215 m_detailedErrors->SetToolTip(
"Include detailed context in error messages");
2217 sizer->Add(labelSizer2, wxGBPosition(row, 0), wxGBSpan(1, 2));
2221 wxBoxSizer *labelSizer3 =
new wxBoxSizer(wxHORIZONTAL);
2222 wxBitmap infoNormal3(
GetResourcePath(
"buttons/info/Info_Normal_20.png"), wxBITMAP_TYPE_PNG);
2223 wxBitmap infoHover3(
GetResourcePath(
"buttons/info/Info_Hovered_20.png"), wxBITMAP_TYPE_PNG);
2224 wxBitmap infoPressed3(
GetResourcePath(
"buttons/info/Info_Pressed_20.png"), wxBITMAP_TYPE_PNG);
2225 wxBitmap infoDisabled3(
GetResourcePath(
"buttons/info/Info_Disabled_20.png"), wxBITMAP_TYPE_PNG);
2226 wxBitmapButton *infoBtn3 =
new wxBitmapButton(panel, wxID_ANY, infoNormal3, wxDefaultPosition, wxSize(40, 40),
2227 wxBORDER_NONE | wxBU_EXACTFIT);
2228 infoBtn3->SetBitmapHover(infoHover3);
2229 infoBtn3->SetBitmapPressed(infoPressed3);
2230 infoBtn3->SetBitmapDisabled(infoDisabled3);
2231 infoBtn3->SetToolTip(
"Click for detailed information");
2232 infoBtn3->Bind(wxEVT_BUTTON, [
this](wxCommandEvent &) {
2233 wxString helpText =
"TRACK LINE/COLUMN NUMBERS\n"
2234 "===========================================================\n\n"
2235 "Controls whether the parser maintains line and column position\n"
2236 "information for every parsed element.\n\n"
2238 " - Every node tracks its source location (line, column)\n"
2239 " - Error messages show EXACT locations\n"
2240 " - Enables \"jump to source\" in editors\n"
2241 " - Useful for debugging and validation\n"
2242 " - Small memory overhead per node (~8 bytes)\n"
2243 " - Minor performance impact (~5-10%)\n\n"
2245 " - No line/column tracking\n"
2246 " - Error messages less specific\n"
2247 " - Lower memory usage\n"
2248 " - Slightly faster parsing\n\n"
2249 "ERROR COMPARISON:\n\n"
2250 "With tracking enabled:\n"
2251 " ERROR at line 127, column 23:\n"
2252 " Invalid attribute 'tpye' on Action node.\n"
2253 " <Action tpye=\"Move\" target=\"enemy\"/>\n"
2255 "With tracking disabled:\n"
2256 " ERROR: Invalid attribute 'tpye' on Action node.\n"
2257 " (no location information available)\n\n"
2260 " - Developing/debugging trees\n"
2261 " - Need precise error locations\n"
2262 " - Integrating with XML editors\n\n"
2264 " - Memory is critical constraint\n"
2265 " - Maximum performance needed\n"
2266 " - Source locations not needed\n\n"
2268 "Keep ENABLED during development for better debugging.\n"
2269 "Consider disabling in memory-constrained environments.";
2270 HelpDialog dlg(
this,
"Track Line/Column Numbers - Help", helpText);
2273 labelSizer3->Add(infoBtn3, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5);
2274 m_trackLineColumn =
new wxCheckBox(panel, wxID_ANY,
"Track Line/Column Numbers");
2277 sizer->Add(labelSizer3, wxGBPosition(row, 0), wxGBSpan(1, 2));
2281 wxBoxSizer *labelSizer4 =
new wxBoxSizer(wxHORIZONTAL);
2282 wxBitmap infoNormal4(
GetResourcePath(
"buttons/info/Info_Normal_20.png"), wxBITMAP_TYPE_PNG);
2283 wxBitmap infoHover4(
GetResourcePath(
"buttons/info/Info_Hovered_20.png"), wxBITMAP_TYPE_PNG);
2284 wxBitmap infoPressed4(
GetResourcePath(
"buttons/info/Info_Pressed_20.png"), wxBITMAP_TYPE_PNG);
2285 wxBitmap infoDisabled4(
GetResourcePath(
"buttons/info/Info_Disabled_20.png"), wxBITMAP_TYPE_PNG);
2286 wxBitmapButton *infoBtn4 =
new wxBitmapButton(panel, wxID_ANY, infoNormal4, wxDefaultPosition, wxSize(40, 40),
2287 wxBORDER_NONE | wxBU_EXACTFIT);
2288 infoBtn4->SetBitmapHover(infoHover4);
2289 infoBtn4->SetBitmapPressed(infoPressed4);
2290 infoBtn4->SetBitmapDisabled(infoDisabled4);
2291 infoBtn4->SetToolTip(
"Click for detailed information");
2292 infoBtn4->Bind(wxEVT_BUTTON, [
this](wxCommandEvent &) {
2293 wxString helpText =
"SUBTREE EXPANSION\n"
2294 "===========================================================\n\n"
2295 "Controls WHEN subtree references are resolved and loaded during\n"
2296 "parsing. Affects memory usage and loading performance.\n\n"
2297 "THREE STRATEGIES:\n\n"
2298 "1. IMMEDIATE (Default - Recommended)\n"
2299 " - All subtrees loaded and expanded during initial parse\n"
2300 " - Complete tree structure available immediately\n"
2301 " - All errors detected at load time\n"
2302 " - Higher initial memory usage\n"
2303 " - Slightly longer initial load time\n"
2304 " Pros: Simple, predictable, catches all errors early\n"
2305 " Cons: Loads trees that may never be used\n\n"
2306 "2. LAZY (On-Demand Loading)\n"
2307 " - Subtrees loaded only when first accessed\n"
2308 " - Lower initial memory footprint\n"
2309 " - Faster initial load time\n"
2310 " - Subtree errors discovered at runtime\n"
2311 " - Small performance hit on first access\n"
2312 " Pros: Efficient for large tree collections\n"
2313 " Cons: Errors may appear during gameplay/execution\n\n"
2314 "3. MANUAL (Explicit Control)\n"
2315 " - No automatic expansion\n"
2316 " - Application controls when to load\n"
2317 " - Maximum flexibility\n"
2318 " - Requires explicit API calls\n"
2319 " Pros: Full control over loading\n"
2320 " Cons: More complex application code\n\n"
2322 "Tree with subtrees: Main -> Patrol -> GuardPoint\n\n"
2323 "IMMEDIATE: Main, Patrol, GuardPoint all loaded at once\n"
2324 "LAZY: Only Main loaded, Patrol/GuardPoint on first use\n"
2325 "MANUAL: Only Main loaded, app calls LoadSubtree() explicitly\n\n"
2327 "Use IMMEDIATE for most cases - simple and catches errors early.\n"
2328 "Use LAZY for very large tree collections (100+ trees).";
2329 HelpDialog dlg(
this,
"SubTree Expansion - Help", helpText);
2332 labelSizer4->Add(infoBtn4, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5);
2333 labelSizer4->Add(
new wxStaticText(panel, wxID_ANY,
"SubTree Expansion:"), 0, wxALIGN_CENTER_VERTICAL);
2334 sizer->Add(labelSizer4, wxGBPosition(row, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
2335 wxArrayString expansionChoices;
2336 expansionChoices.Add(
"Immediate");
2337 expansionChoices.Add(
"Lazy");
2338 expansionChoices.Add(
"Manual");
2339 m_subtreeExpansion =
new wxChoice(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, expansionChoices);
2346 wxBoxSizer *labelSizer5 =
new wxBoxSizer(wxHORIZONTAL);
2347 wxBitmap infoNormal5(
GetResourcePath(
"buttons/info/Info_Normal_20.png"), wxBITMAP_TYPE_PNG);
2348 wxBitmap infoHover5(
GetResourcePath(
"buttons/info/Info_Hovered_20.png"), wxBITMAP_TYPE_PNG);
2349 wxBitmap infoPressed5(
GetResourcePath(
"buttons/info/Info_Pressed_20.png"), wxBITMAP_TYPE_PNG);
2350 wxBitmap infoDisabled5(
GetResourcePath(
"buttons/info/Info_Disabled_20.png"), wxBITMAP_TYPE_PNG);
2351 wxBitmapButton *infoBtn5 =
new wxBitmapButton(panel, wxID_ANY, infoNormal5, wxDefaultPosition, wxSize(40, 40),
2352 wxBORDER_NONE | wxBU_EXACTFIT);
2353 infoBtn5->SetBitmapHover(infoHover5);
2354 infoBtn5->SetBitmapPressed(infoPressed5);
2355 infoBtn5->SetBitmapDisabled(infoDisabled5);
2356 infoBtn5->SetToolTip(
"Click for detailed information");
2357 infoBtn5->Bind(wxEVT_BUTTON, [
this](wxCommandEvent &) {
2358 wxString helpText =
"MAX RECURSION DEPTH\n"
2359 "===========================================================\n\n"
2360 "Maximum depth of nested subtree references allowed. Prevents\n"
2361 "infinite recursion from circular subtree references.\n\n"
2362 "WHAT IS RECURSION DEPTH?\n"
2363 "The number of levels of subtree-within-subtree nesting:\n\n"
2364 "Depth 1: MainTree -> SubTreeA (1 level)\n"
2365 "Depth 2: MainTree -> SubTreeA -> SubTreeB (2 levels)\n"
2366 "Depth 3: MainTree -> SubTreeA -> SubTreeB -> SubTreeC\n\n"
2367 "CIRCULAR REFERENCE PROTECTION:\n"
2368 "This limit prevents infinite loops from circular references:\n"
2369 " TreeA references TreeB\n"
2370 " TreeB references TreeA <- CIRCULAR!\n"
2371 "Without limit: Infinite expansion and stack overflow\n"
2372 "With limit: Stops after N levels with clear error\n\n"
2373 "VALUE GUIDELINES:\n\n"
2374 "Very Low (1-10):\n"
2375 " - Simple trees with few subtree levels\n"
2376 " - Strict control over complexity\n"
2377 " - Fast circular reference detection\n\n"
2378 "Medium (10-100): RECOMMENDED\n"
2379 " - Handles most reasonable tree structures\n"
2380 " - Default value: 100\n"
2381 " - Good balance of safety and flexibility\n\n"
2382 "High (100-1000):\n"
2383 " - Very complex nested structures\n"
2384 " - Larger memory usage\n"
2385 " - Slower to detect circular refs\n\n"
2387 "Max depth = 10, actual nesting = 12:\n"
2388 " ERROR: Max recursion depth (10) exceeded.\n"
2389 " Subtree expansion stopped at: TreeA -> TreeB -> ... (10 levels)\n"
2390 " Possible circular reference detected.\n\n"
2392 "Keep default 100 - catches circular refs while allowing\n"
2393 "complex legitimate nesting. Increase only if you have\n"
2394 "verified deeply nested structures.";
2395 HelpDialog dlg(
this,
"Max Recursion Depth - Help", helpText);
2398 labelSizer5->Add(infoBtn5, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5);
2399 labelSizer5->Add(
new wxStaticText(panel, wxID_ANY,
"Max Recursion Depth:"), 0, wxALIGN_CENTER_VERTICAL);
2400 sizer->Add(labelSizer5, wxGBPosition(row, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
2404 m_maxRecursionDepth->SetToolTip(
"Prevent infinite loops from circular subtree references");
2409 wxBoxSizer *labelSizer8 =
new wxBoxSizer(wxHORIZONTAL);
2410 wxBitmap infoNormal8(
GetResourcePath(
"buttons/info/Info_Normal_20.png"), wxBITMAP_TYPE_PNG);
2411 wxBitmap infoHover8(
GetResourcePath(
"buttons/info/Info_Hovered_20.png"), wxBITMAP_TYPE_PNG);
2412 wxBitmap infoPressed8(
GetResourcePath(
"buttons/info/Info_Pressed_20.png"), wxBITMAP_TYPE_PNG);
2413 wxBitmap infoDisabled8(
GetResourcePath(
"buttons/info/Info_Disabled_20.png"), wxBITMAP_TYPE_PNG);
2414 wxBitmapButton *infoBtn8 =
new wxBitmapButton(panel, wxID_ANY, infoNormal8, wxDefaultPosition, wxSize(40, 40),
2415 wxBORDER_NONE | wxBU_EXACTFIT);
2416 infoBtn8->SetBitmapHover(infoHover8);
2417 infoBtn8->SetBitmapPressed(infoPressed8);
2418 infoBtn8->SetBitmapDisabled(infoDisabled8);
2419 infoBtn8->SetToolTip(
"Click for detailed information");
2420 infoBtn8->Bind(wxEVT_BUTTON, [
this](wxCommandEvent &) {
2421 wxString helpText =
"XML NAMESPACE URI\n"
2422 "===========================================================\n\n"
2423 "Optional XML namespace for behavior tree elements.\n"
2424 "Used for XML schema validation and element disambiguation.\n\n"
2425 "WHAT IS AN XML NAMESPACE?\n"
2426 "A unique identifier (usually a URI) that prevents naming\n"
2427 "conflicts between XML vocabularies.\n\n"
2428 "EXAMPLE WITHOUT NAMESPACE:\n"
2430 " <BehaviorTree ID=\"AI\">\n"
2431 " <Sequence>...</Sequence>\n"
2432 " </BehaviorTree>\n"
2434 "EXAMPLE WITH NAMESPACE:\n"
2435 " <root xmlns:bt=\"http://behaviortree.dev/bt/1.0\">\n"
2436 " <bt:BehaviorTree ID=\"AI\">\n"
2437 " <bt:Sequence>...</bt:Sequence>\n"
2438 " </bt:BehaviorTree>\n"
2441 "Leave Empty (Most Common):\n"
2442 " - Simple XML files\n"
2443 " - No naming conflicts\n"
2445 " - Easier to read/write\n\n"
2446 "Specify Namespace When:\n"
2447 " - Mixing multiple XML vocabularies\n"
2448 " - Need formal XML schema validation\n"
2449 " - Working with XML tools that require it\n"
2450 " - Preventing element name collisions\n\n"
2451 "COMMON NAMESPACE FORMATS:\n"
2452 " - http://behaviortree.dev/bt/1.0\n"
2453 " - urn:behaviortree:schema:1.0\n"
2454 " - http://example.com/schemas/bt\n\n"
2455 "Note: The URI doesn't need to be a real web address.\n"
2456 "It's just a unique identifier.\n\n"
2458 "If specified, all behavior tree elements must use the\n"
2459 "namespace prefix in your XML files.\n\n"
2461 "Leave empty unless you have specific requirements for\n"
2462 "namespace-based XML validation or element disambiguation.";
2463 HelpDialog dlg(
this,
"XML Namespace - Help", helpText);
2466 labelSizer8->Add(infoBtn8, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5);
2467 labelSizer8->Add(
new wxStaticText(panel, wxID_ANY,
"XML Namespace URI:"), 0, wxALIGN_CENTER_VERTICAL);
2468 sizer->Add(labelSizer8, wxGBPosition(row, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
2470 m_xmlNamespace->SetToolTip(
"Optional namespace URI (e.g., http://behaviortree.dev/bt/1.0)");
2471 sizer->Add(
m_xmlNamespace, wxGBPosition(row, 1), wxDefaultSpan, wxEXPAND);
2475 wxBoxSizer *labelSizer9 =
new wxBoxSizer(wxHORIZONTAL);
2476 wxBitmap infoNormal9(
GetResourcePath(
"buttons/info/Info_Normal_20.png"), wxBITMAP_TYPE_PNG);
2477 wxBitmap infoHover9(
GetResourcePath(
"buttons/info/Info_Hovered_20.png"), wxBITMAP_TYPE_PNG);
2478 wxBitmap infoPressed9(
GetResourcePath(
"buttons/info/Info_Pressed_20.png"), wxBITMAP_TYPE_PNG);
2479 wxBitmap infoDisabled9(
GetResourcePath(
"buttons/info/Info_Disabled_20.png"), wxBITMAP_TYPE_PNG);
2480 wxBitmapButton *infoBtn9 =
new wxBitmapButton(panel, wxID_ANY, infoNormal9, wxDefaultPosition, wxSize(40, 40),
2481 wxBORDER_NONE | wxBU_EXACTFIT);
2482 infoBtn9->SetBitmapHover(infoHover9);
2483 infoBtn9->SetBitmapPressed(infoPressed9);
2484 infoBtn9->SetBitmapDisabled(infoDisabled9);
2485 infoBtn9->SetToolTip(
"Click for detailed information");
2486 infoBtn9->Bind(wxEVT_BUTTON, [
this](wxCommandEvent &) {
2487 wxString helpText =
"PRESERVE XML COMMENTS\n"
2488 "===========================================================\n\n"
2489 "Controls whether XML comments are kept in memory after parsing.\n\n"
2491 " - Comments stored in parsed tree structure\n"
2492 " - Can be accessed programmatically\n"
2493 " - Preserved when saving/exporting trees\n"
2494 " - Useful for round-trip editing\n"
2495 " - Small memory overhead\n\n"
2496 "DISABLED (Default):\n"
2497 " - Comments discarded during parsing\n"
2498 " - Lower memory usage\n"
2499 " - Slightly faster parsing\n"
2500 " - Lost if tree is saved back to XML\n\n"
2502 " <!-- This is a comment -->\n"
2503 " <!-- Comments can span\n"
2504 " multiple lines -->\n\n"
2506 " <BehaviorTree ID=\"AI\">\n"
2507 " <!-- This is the patrol sequence -->\n"
2509 " <Action name=\"Move\"/> <!-- Move forward -->\n"
2511 " </BehaviorTree>\n\n"
2514 " - Building XML editor/viewer\n"
2515 " - Need to preserve documentation\n"
2516 " - Round-trip editing (load -> modify -> save)\n"
2517 " - Comments contain important metadata\n\n"
2519 " - Only loading trees for execution\n"
2520 " - Memory is constrained\n"
2521 " - Comments are just temporary notes\n"
2522 " - Maximum parsing speed needed\n\n"
2524 "Enable if building an editor or if comments contain important\n"
2525 "information. Disable for runtime-only tree loading.";
2526 HelpDialog dlg(
this,
"Preserve Comments - Help", helpText);
2529 labelSizer9->Add(infoBtn9, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5);
2533 sizer->Add(labelSizer9, wxGBPosition(row, 0), wxGBSpan(1, 2));
2537 wxBoxSizer *labelSizer10 =
new wxBoxSizer(wxHORIZONTAL);
2538 wxBitmap infoNormal10(
GetResourcePath(
"buttons/info/Info_Normal_20.png"), wxBITMAP_TYPE_PNG);
2539 wxBitmap infoHover10(
GetResourcePath(
"buttons/info/Info_Hovered_20.png"), wxBITMAP_TYPE_PNG);
2540 wxBitmap infoPressed10(
GetResourcePath(
"buttons/info/Info_Pressed_20.png"), wxBITMAP_TYPE_PNG);
2541 wxBitmap infoDisabled10(
GetResourcePath(
"buttons/info/Info_Disabled_20.png"), wxBITMAP_TYPE_PNG);
2542 wxBitmapButton *infoBtn10 =
new wxBitmapButton(panel, wxID_ANY, infoNormal10, wxDefaultPosition, wxSize(40, 40),
2543 wxBORDER_NONE | wxBU_EXACTFIT);
2544 infoBtn10->SetBitmapHover(infoHover10);
2545 infoBtn10->SetBitmapPressed(infoPressed10);
2546 infoBtn10->SetBitmapDisabled(infoDisabled10);
2547 infoBtn10->SetToolTip(
"Click for detailed information");
2548 infoBtn10->Bind(wxEVT_BUTTON, [
this](wxCommandEvent &) {
2549 wxString helpText =
"PRESERVE ATTRIBUTE ORDER\n"
2550 "===========================================================\n\n"
2551 "Controls whether the order of XML attributes is maintained\n"
2552 "exactly as they appear in the source file.\n\n"
2554 " - Attributes stored in original order\n"
2555 " - When saved, attributes appear in same order\n"
2556 " - Useful for version control (minimal diffs)\n"
2557 " - Slight memory/performance overhead\n"
2558 " - Better for human-edited XML\n\n"
2559 "DISABLED (Default):\n"
2560 " - Attributes may be reordered internally\n"
2561 " - Typically alphabetical order\n"
2562 " - Slightly more efficient\n"
2563 " - Doesn't affect functionality\n"
2564 " - Standard XML behavior\n\n"
2565 "XML ATTRIBUTE ORDER:\n\n"
2567 " <Action name=\"Move\" speed=\"5.0\" target=\"enemy\"/>\n\n"
2568 "Preserved (enabled):\n"
2569 " <Action name=\"Move\" speed=\"5.0\" target=\"enemy\"/>\n"
2570 " (Exact same order)\n\n"
2571 "Not preserved (disabled):\n"
2572 " <Action name=\"Move\" speed=\"5.0\" target=\"enemy\"/>\n"
2573 " (May become: name, speed, target OR alphabetically)\n\n"
2575 "XML specification says attribute order is NOT significant.\n"
2576 "All XML parsers must work regardless of attribute order.\n\n"
2579 " - Using version control (Git, SVN)\n"
2580 " - Want minimal diffs between versions\n"
2581 " - Hand-editing XML files\n"
2582 " - Order has semantic meaning to humans\n\n"
2584 " - Pure runtime loading\n"
2585 " - No round-trip editing\n"
2586 " - Programmatically generated XML\n"
2587 " - Order doesn't matter\n\n"
2589 "Enable for editor applications and version-controlled files.\n"
2590 "Disable for runtime-only loading.";
2591 HelpDialog dlg(
this,
"Preserve Attribute Order - Help", helpText);
2594 labelSizer10->Add(infoBtn10, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5);
2598 sizer->Add(labelSizer10, wxGBPosition(row, 0), wxGBSpan(1, 2));
2601 sizer->AddGrowableCol(1);
2602 mainSizer->Add(sizer, 0, wxEXPAND | wxALL, 5);
2605 mainSizer->Add(
new wxStaticLine(panel), 0, wxEXPAND | wxLEFT | wxRIGHT | wxTOP, 5);
2615 wxBoxSizer *rulesLabelSizer =
new wxBoxSizer(wxHORIZONTAL);
2616 wxBitmap infoNormal11(
GetResourcePath(
"buttons/info/Info_Normal_20.png"), wxBITMAP_TYPE_PNG);
2617 wxBitmap infoHover11(
GetResourcePath(
"buttons/info/Info_Hovered_20.png"), wxBITMAP_TYPE_PNG);
2618 wxBitmap infoPressed11(
GetResourcePath(
"buttons/info/Info_Pressed_20.png"), wxBITMAP_TYPE_PNG);
2619 wxBitmap infoDisabled11(
GetResourcePath(
"buttons/info/Info_Disabled_20.png"), wxBITMAP_TYPE_PNG);
2620 wxBitmapButton *infoBtn11 =
new wxBitmapButton(panel, wxID_ANY, infoNormal11, wxDefaultPosition, wxSize(40, 40),
2621 wxBORDER_NONE | wxBU_EXACTFIT);
2622 infoBtn11->SetBitmapHover(infoHover11);
2623 infoBtn11->SetBitmapPressed(infoPressed11);
2624 infoBtn11->SetBitmapDisabled(infoDisabled11);
2625 infoBtn11->SetToolTip(
"Click for detailed information");
2626 infoBtn11->Bind(wxEVT_BUTTON, [
this](wxCommandEvent &) {
2627 wxString helpText =
"CUSTOM VALIDATION RULES\n"
2628 "===========================================================\n\n"
2629 "Define custom validation logic beyond standard XML schema validation.\n"
2630 "Specify rules using a simple scripting language or expressions.\n\n"
2631 "WHAT ARE VALIDATION RULES?\n"
2632 "Custom constraints that your behavior trees must satisfy:\n"
2633 " - Structural rules (e.g., Sequence must have 2+ children)\n"
2634 " - Naming conventions (e.g., Actions must start with verb)\n"
2635 " - Business logic (e.g., no more than 3 decorators deep)\n"
2636 " - Cross-tree references (e.g., all subtrees must exist)\n\n"
2638 "One rule per line. Each rule has:\n"
2639 " - Condition: When to check\n"
2640 " - Validation: What to verify\n"
2641 " - Message: Error to show if fails\n\n"
2642 "EXAMPLE RULES:\n\n"
2643 "1. Structural Rule:\n"
2644 " node.type == 'Sequence' && node.children.count < 2:\n"
2645 " 'Sequence nodes must have at least 2 children'\n\n"
2646 "2. Naming Convention:\n"
2647 " node.type == 'Action' && !node.name.startsWithVerb():\n"
2648 " 'Action names must start with a verb'\n\n"
2649 "3. Decorator Depth:\n"
2650 " node.type == 'Decorator' && node.depth > 3:\n"
2651 " 'Decorators cannot be nested more than 3 levels'\n\n"
2652 "4. Required Attributes:\n"
2653 " node.type == 'Action' && !node.hasAttribute('timeout'):\n"
2654 " 'All actions must specify a timeout'\n\n"
2655 "5. Subtree References:\n"
2656 " node.type == 'SubTree' && !subtreeExists(node.ID):\n"
2657 " 'Referenced subtree does not exist'\n\n"
2658 "AVAILABLE PROPERTIES:\n"
2659 " - node.type: Node type (Action, Sequence, etc.)\n"
2660 " - node.name: Node name/ID\n"
2661 " - node.children.count: Number of child nodes\n"
2662 " - node.depth: Nesting level\n"
2663 " - node.attributes: Map of attributes\n"
2664 " - tree.ID: Current tree identifier\n\n"
2665 "WHEN VALIDATION RUNS:\n"
2666 " - After parsing completes\n"
2667 " - Before tree is made available to application\n"
2668 " - All rules checked, multiple errors reported\n\n"
2670 "If any rule fails:\n"
2671 " - Clear error message shown\n"
2672 " - Parse operation fails\n"
2673 " - Tree not loaded into memory\n\n"
2675 " - Rules checked once at parse time\n"
2676 " - No runtime overhead\n"
2677 " - Complex rules may slow initial load\n\n"
2679 "Use for project-specific constraints that can't be expressed\n"
2680 "in XML schema. Keep rules simple and clear. Too many complex\n"
2681 "rules can make debugging difficult.";
2682 HelpDialog dlg(
this,
"Custom Validation Rules - Help", helpText);
2685 rulesLabelSizer->Add(infoBtn11, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5);
2686 rulesLabelSizer->Add(
new wxStaticText(panel, wxID_ANY,
"Custom Validation Rules: ( experimental )"), 0,
2687 wxALIGN_CENTER_VERTICAL);
2688 mainSizer->Add(rulesLabelSizer, 0, wxEXPAND | wxLEFT | wxRIGHT | wxTOP, 5);
2689 m_customValidation =
new wxTextCtrl(panel, wxID_ANY,
"", wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE);
2691 m_customValidation->SetToolTip(
"Define custom validation expressions (one rule per line)");
2695 panel->SetSizer(mainSizer);
3309 auto config = std::make_shared<EmberCore::ParserConfig>();
3312 auto &docConfig = config->GetDocumentConfig();
3313 docConfig.root_element =
m_rootElement->GetValue().ToStdString();
3314 docConfig.main_tree_attribute =
m_mainTreeAttr->GetValue().ToStdString();
3317 docConfig.whitespace_handling =
3333 auto &treeConfig = config->GetTreeConfig();
3335 treeConfig.tree_id_attribute =
m_treeIdAttr->GetValue().ToStdString();
3338 treeConfig.subtree_reference_attribute =
m_subtreeRefAttr->GetValue().ToStdString();
3343 auto &nodeConfig = config->GetNodeConfig();
3345 nodeConfig.action_element =
m_actionElement->GetValue().ToStdString();
3349 nodeConfig.node_id_attribute =
m_nodeIdAttr->GetValue().ToStdString();
3350 nodeConfig.node_name_attribute =
m_nodeNameAttr->GetValue().ToStdString();
3351 nodeConfig.node_type_attribute =
m_nodeTypeAttr->GetValue().ToStdString();
3355 auto &classConfig = config->GetClassificationConfig();
3356 classConfig.strategy =
3359 classConfig.control_types.clear();
3364 classConfig.decorator_types.clear();
3369 classConfig.action_types.clear();
3371 classConfig.action_types.push_back(
m_actionTypesList->GetString(i).ToStdString());
3374 classConfig.condition_types.clear();
3379 classConfig.unknown_behavior =
3381 classConfig.type_attribute_name =
m_typeAttrName->GetValue().ToStdString();
3384 auto &bbConfig = config->GetBlackboardConfig();
3388 bbConfig.entry_element =
m_entryElement->GetValue().ToStdString();
3389 bbConfig.entry_key_attribute =
m_entryKeyAttr->GetValue().ToStdString();
3390 bbConfig.entry_type_attribute =
m_entryTypeAttr->GetValue().ToStdString();
3391 bbConfig.entry_value_attribute =
m_entryValueAttr->GetValue().ToStdString();
3394 bbConfig.type_mappings.clear();
3398 if (!xmlType.empty() && !internalType.empty()) {
3399 bbConfig.type_mappings[xmlType] = internalType;
3404 auto &advConfig = config->GetAdvancedConfig();
3408 advConfig.subtree_expansion =
3411 advConfig.xml_namespace_uri =
m_xmlNamespace->GetValue().ToStdString();
3419 advConfig.custom_validation_rules =
"";