7 #include <unordered_map>
42 using std::make_unique;
45 using std::unique_ptr;
46 using std::unordered_map;
80 TextEditorTabView::TextEditorTabView(
EditorView* editorView,
const string& tabId,
GUIScreenNode* screenNode,
const string& fileName)
88 auto fileNameLowerCase = StringTools::toLowerCase(
fileName);
90 fileNameLowerCase ==
"makefile" || StringTools::endsWith(fileNameLowerCase,
"/makefile")?
"makefile":
91 StringTools::substring(fileNameLowerCase, fileNameLowerCase.rfind(
'.') + 1, fileNameLowerCase.size());
92 engine = unique_ptr<Engine>(Engine::createOffScreenInstance(512, 512,
false,
false,
false));
93 engine->setSceneColor(
Color4(39.0f / 255.0f, 39.0f / 255.0f, 39.0f / 255.0f, 1.0f));
109 NodeMoveListener(
TextEditorTabView* textEditorTabView): textEditorTabView(textEditorTabView) {
112 if (node->
getId().find(
"_") != string::npos) {
122 auto xMax = nodeComputedConstraints.
left + nodeComputedConstraints.width;
123 auto yMax = nodeComputedConstraints.top + nodeComputedConstraints.height;
130 void onRelease(
GUINode* node,
int mouseX,
int mouseY) {
145 codeCompletion = unique_ptr<const TextFormatter::CodeCompletion>(TextFormatter::getInstance()->loadCodeCompletion(
extension));
150 class TextChangeListener:
public GUIStyledTextNodeController::ChangeListener {
152 TextChangeListener(
TextEditorTabView* textEditorTabView): textEditorTabView(textEditorTabView) {
155 virtual ~TextChangeListener() {
158 virtual void onRemoveText(
int idx,
int count)
override {
163 TextFormatter::getInstance()->format(textEditorTabView->
extension, textEditorTabView->
textNode, idx, idx +
count);
166 virtual void onInsertText(
int idx,
int count)
override {
171 TextFormatter::getInstance()->format(textEditorTabView->
extension, textEditorTabView->
textNode, idx, idx +
count);
184 class TextCodeCompletionListener:
public GUIStyledTextNodeController::CodeCompletionListener {
186 TextCodeCompletionListener(
TextEditorTabView* textEditorTabView): textEditorTabView(textEditorTabView) {
189 virtual ~TextCodeCompletionListener() {
192 virtual void onCodeCompletion(
int idx)
override {
199 string search = StringTools::substring(textEditorTabView->
textNode->
getText().
getString(), previousDelimiterPos == 0?0:previousDelimiterPos + 1, idx);
200 vector<CodeCompletionSymbol> codeCompletionSymbolCandidates;
201 #define MAX_ENTRIES 40
203 if (StringTools::startsWith(symbol.name, search) ==
true) {
204 if (symbol.overloadList.empty() ==
true) {
205 if (codeCompletionSymbolCandidates.size() ==
MAX_ENTRIES) {
206 codeCompletionSymbolCandidates.push_back(
217 codeCompletionSymbolCandidates.push_back(
220 .display = symbol.name,
228 for (
const auto& overload: symbol.overloadList) {
229 if (codeCompletionSymbolCandidates.size() ==
MAX_ENTRIES) {
230 codeCompletionSymbolCandidates.push_back(
242 for (
const auto& parameter: overload.parameters) {
243 if (parameters.empty() ==
false) parameters+=
", ";
244 parameters+= parameter;
246 codeCompletionSymbolCandidates.push_back(
249 .display = symbol.name +
"(" + parameters +
"): " + overload.returnValue,
251 .parameters = overload.parameters,
252 .returnValue = overload.returnValue
257 if (codeCompletionSymbolCandidates.size() ==
MAX_ENTRIES + 1)
break;
266 codeCompletionSymbolCandidates.begin(),
267 codeCompletionSymbolCandidates.begin() + (Math::min(codeCompletionSymbolCandidates.size(),
MAX_ENTRIES)),
269 return lhs.display < rhs.display;
275 for (
const auto& codeCompletionSymbolCandidate: codeCompletionSymbolCandidates) {
277 class OnCodeCompletionAction:
public virtual Action
281 void performAction()
override {
282 if (symbol.
name.empty() ==
true)
return;
288 if (withoutWhiteSpaceDelimiters.find(
' ') != string::npos) withoutWhiteSpaceDelimiters.erase(withoutWhiteSpaceDelimiters.find(
' '), 1);
289 if (withoutWhiteSpaceDelimiters.find(
'\t') != string::npos) withoutWhiteSpaceDelimiters.erase(withoutWhiteSpaceDelimiters.find(
'\t'), 1);
290 if (withoutWhiteSpaceDelimiters.find(
'\n') != string::npos) withoutWhiteSpaceDelimiters.erase(withoutWhiteSpaceDelimiters.find(
'\n'), 1);
293 string parameterString;
295 for (
const auto& parameter: symbol.
parameters) {
296 auto parameterTokenized = StringTools::tokenize(parameter,
" \t\n");
297 if (parameterString.empty() ==
false) parameterString+=
", ";
298 parameterString+= parameterTokenized[parameterTokenized.size() - 1];
300 parameterString =
"(" + parameterString +
")";
302 textEditorTabView->
textNode->
removeText(previousDelimiterPos == 0?0:previousDelimiterPos + 1, nextDelimiterPos - (previousDelimiterPos == 0?0:previousDelimiterPos + 1));
303 textEditorTabView->
textNode->
insertText(previousDelimiterPos == 0?0:previousDelimiterPos + 1, symbol.
name + parameterString);
304 TextFormatter::getInstance()->format(textEditorTabView->
extension, textEditorTabView->
textNode, previousDelimiterPos == 0?0:previousDelimiterPos + 1, (previousDelimiterPos == 0?0:previousDelimiterPos + 1) + symbol.
name.size() + parameterString.size());
316 if (codeCompletionSymbolCandidates.empty() ==
false) {
318 int left, top, width, height, offsetX, offsetY;
320 if (selectedTab !=
nullptr) {
321 textEditorTabView->
getEditorView()->
getViewPort(selectedTab->getFrameBufferNode(), left, top, width, height, offsetX, offsetY);
342 FileSystem::getStandardFileSystem()->setContentFromString(
353 auto scrollX = visualizationNode->getChildrenRenderOffsetX();
354 auto scrollY = visualizationNode->getChildrenRenderOffsetY();
355 for (
auto& event:
engine->getGUI()->getMouseEvents()) {
356 if (event.getButton() != GUIMouseEvent::MOUSEEVENT_BUTTON_LEFT)
continue;
357 if (event.getType() == GUIMouseEvent::MOUSEEVENT_RELEASED) {
361 event.setProcessed(
true);
365 if (event.getType() == GUIMouseEvent::MOUSEEVENT_DRAGGED) {
367 if (connection.srcNodeId.empty() ==
true) {
368 connection.x1 =
scrollX +
event.getX();
369 connection.y1 =
scrollY +
event.getY();
371 if (connection.dstNodeId.empty() ==
true) {
372 connection.x2 =
scrollX +
event.getX();
373 connection.y2 =
scrollY +
event.getY();
378 event.setProcessed(
true);
383 engine->getGUI()->handleEvents();
398 auto scrolled =
false;
399 auto scrollXNew = visualizationNode->getChildrenRenderOffsetX();
400 auto scrollYNew = visualizationNode->getChildrenRenderOffsetY();
402 if (Float::equals(scrollXNew,
scrollX) ==
false ||
403 Float::equals(scrollYNew,
scrollY) ==
false) {
410 if (scrolled ==
true ||
420 auto visualizationScrollArea = required_dynamic_cast<GUIParentNode*>(
screenNode->
getNodeById(
"visualization"));
421 auto visualizationWidth = visualizationScrollArea->getComputedConstraints().width;
422 auto visualizationHeight = visualizationScrollArea->getComputedConstraints().height;
423 auto visualizationScrollX =
static_cast<int>(
scrollX);
424 auto visualizationScrollY =
static_cast<int>(
scrollY);
428 canvas.
clear(0, 0, 0, 0);
430 for (
auto y = 0; y <
linesTexture->getHeight(); y+= 10) {
431 for (
auto x = 0; x <
linesTexture->getWidth(); x+= 10) {
432 canvas.
drawPixel(Math::absmod(x - visualizationScrollX,
linesTexture->getWidth()), Math::absmod(y - visualizationScrollY,
linesTexture->getHeight()), 125, 125, 125, 50);
437 auto x1 = connection.x1 - visualizationScrollX;
438 auto y1 = connection.y1 - visualizationScrollY;
439 auto x2 = connection.x2 - visualizationScrollX;
440 auto y2 = connection.y2 - visualizationScrollY;
442 if ((x1 < 0 && x2 < 0) ||
443 (x1 > visualizationWidth && x2 > visualizationWidth) ||
444 (y1 < 0 && y2 < 0) ||
445 (y1 > visualizationHeight && y2 > visualizationHeight))
continue;
447 auto straightLineLength = Math::min(
static_cast<float>(Math::abs(y2 - y1)), 50.0f);
449 Vector2 srcVector2(x1 + (x2 < x1?-straightLineLength:straightLineLength), y1);
450 Vector2 dstVector1(x1 + (x2 < x1?-straightLineLength:straightLineLength), y2 - (y2 < y1?-straightLineLength:straightLineLength));
452 vector<Vector2> controlPoints;
453 controlPoints.push_back(srcVector1);
454 controlPoints.push_back(srcVector2);
455 controlPoints.push_back(dstVector1);
456 controlPoints.push_back(dstVector2);
457 canvas.
drawBezier(controlPoints, connection.red, connection.green, connection.blue, connection.alpha);
466 engine->getGUI()->render();
477 Console::println(
"TextEditorTabView::initialize(): An error occurred: " +
string(exception.what()));
493 auto scrollX = visualizationNode->getChildrenRenderOffsetX();
494 auto scrollY = visualizationNode->getChildrenRenderOffsetY();
530 for (
const auto& [nodeId, node]:
nodes) {
537 Console::println(
"Node[" + to_string(i++) +
"]: " + node.id +
": " + node.value +
"(" + nodeType +
")");
544 Console::println(
"Connection[" + to_string(i++) +
"]");
545 string connectionType;
546 switch (connection.type) {
551 Console::println(
"\t" + connection.srcNodeId +
" --> " + connection.dstNodeId +
"(" + connectionType +
")");
559 "Generated Source Code:\n\n" +
568 auto flattenedId = to_string(
nodeIdx++);
572 nodes[flattenedId] = {
576 .returnValueType = method->getReturnValueType(),
581 auto nodeName = methodName;
582 auto nodeTypeColor = string(
"color.nodetype_method");
585 nodeName = methodOperatorMapIt->second;
586 nodeTypeColor =
"color.nodetype_math";
589 if (method ==
nullptr) {
590 nodeTypeColor =
"color.nodetype_function";
593 if (nodeName == flowControlNode) {
594 nodeTypeColor =
"color.nodetype_flowcontrol";
599 if (nodeName == mathNode || StringTools::startsWith(nodeName, mathNode +
".")) {
600 nodeTypeColor =
"color.nodetype_math";
607 string xml =
"<template src='resources/engine/gui/template_visualcode_node.xml' id='" + flattenedId +
"' left='" + to_string(x) +
"' top='" + to_string(y) +
"' node-name='" + GUIParser::escape(nodeName +
"(" + flattenedId +
")") +
"' node-type-color='{$" + GUIParser::escape(nodeTypeColor) +
"}' />";
611 Console::println(
"TextEditorTabView::createMiniScriptNodes(): method/function: " +
string(exception.what()));
615 auto nodeInputContainer = required_dynamic_cast<GUIParentNode*>(
screenNode->
getNodeById(flattenedId +
"_input_container"));
616 auto nodeOutputContainer = required_dynamic_cast<GUIParentNode*>(
screenNode->
getNodeById(flattenedId +
"_output_container"));
624 " id='" + flattenedId +
"_fi' " +
625 " src='resources/engine/gui/template_visualcode_input.xml' " +
626 " pin_type_connected='resources/engine/images/visualcode_flow_connected.png' " +
627 " pin_type_unconnected='resources/engine/images/visualcode_flow_unconnected.png' " +
631 GUIParser::parse(nodeInputContainer, xml);
633 required_dynamic_cast<GUIElementNode*>(
screenNode->
getNodeById(flattenedId +
"_fi_pin_type_panel"))->getActiveConditions().add(
"connected");
635 Console::println(
"TextEditorTabView::createMiniScriptNodes(): method/function: " +
string(exception.what()));
641 auto argumentIdx = 0;
642 if (method !=
nullptr) {
643 const auto& argumentTypes = method->getArgumentTypes();
644 for (argumentIdx = 0; argumentIdx < argumentTypes.size(); argumentIdx++) {
646 auto isLiteral =
true;
647 auto literal = string(
"");
648 auto argumentName = argumentTypes[argumentIdx].name;
649 if (argumentName.empty() ==
false) argumentName[0] = Character::toUpperCase(argumentName[0]);
654 " id='" + flattenedId +
"_a" + to_string(argumentIdx) +
"' " +
655 " src='resources/engine/gui/template_visualcode_input.xml' " +
656 " pin_type_connected='resources/engine/images/visualcode_value_connected.png' " +
657 " pin_type_unconnected='resources/engine/images/visualcode_value_unconnected.png' " +
659 " text='" + GUIParser::escape(argumentName) +
"' ";
660 if (isLiteral ==
true) {
661 xml+=
" input_text='" + GUIParser::escape(literal) +
"' ";
666 GUIParser::parse(nodeInputContainer, xml);
668 if (isLiteral ==
true) {
670 required_dynamic_cast<GUIElementNode*>(
screenNode->
getNodeById(flattenedId +
"_a" + to_string(argumentIdx) +
"_input_type_panel"))->getActiveConditions().add(
"input");
673 required_dynamic_cast<GUIElementNode*>(
screenNode->
getNodeById(flattenedId +
"_a" + to_string(argumentIdx) +
"_pin_type_panel"))->getActiveConditions().add(
"connected");
677 Console::println(
"TextEditorTabView::createMiniScriptNodes(): method/function: " +
string(exception.what()));
689 " id='" + flattenedId +
"_fo' " +
690 " src='resources/engine/gui/template_visualcode_output.xml' " +
691 " pin_type_connected='resources/engine/images/visualcode_flow_connected.png' " +
692 " pin_type_unconnected='resources/engine/images/visualcode_flow_unconnected.png' " +
696 GUIParser::parse(nodeOutputContainer, xml);
698 required_dynamic_cast<GUIElementNode*>(
screenNode->
getNodeById(flattenedId +
"_fo_pin_type_panel"))->getActiveConditions().add(
"connected");
700 Console::println(
"TextEditorTabView::createMiniScriptNodes(): method/function: " +
string(exception.what()));
704 if (method !=
nullptr && method->getReturnValueType() != MiniScript::ScriptVariableType::TYPE_NULL) {
710 " id='" + flattenedId +
"_r' " +
711 " src='resources/engine/gui/template_visualcode_output.xml' " +
712 " pin_type_connected='resources/engine/images/visualcode_value_connected.png' " +
713 " pin_type_unconnected='resources/engine/images/visualcode_value_unconnected.png' " +
720 GUIParser::parse(nodeOutputContainer, xml);
722 required_dynamic_cast<GUIElementNode*>(
screenNode->
getNodeById(flattenedId +
"_r_pin_type_panel"))->getActiveConditions().add(
"connected");
724 Console::println(
"TextEditorTabView::createMiniScriptNodes(): method/function: " +
string(exception.what()));
729 if (method ==
nullptr) {
735 " id='" + flattenedId +
"_r' " +
736 " src='resources/engine/gui/template_visualcode_output.xml' " +
737 " pin_type_connected='resources/engine/images/visualcode_value_connected.png' " +
738 " pin_type_unconnected='resources/engine/images/visualcode_value_unconnected.png' " +
739 " pin_color='{$color.pintype_undefined}' " +
740 " text='Return Value' " +
745 GUIParser::parse(nodeOutputContainer, xml);
747 required_dynamic_cast<GUIElementNode*>(
screenNode->
getNodeById(flattenedId +
"_r_pin_type_panel"))->getActiveConditions().add(
"connected");
749 Console::println(
"TextEditorTabView::createMiniScriptNodes(): method/function: " +
string(exception.what()));
759 node->getRequestsConstraints().left+= deltaX;
760 for (
auto argumentIdx = 0; argumentIdx < syntaxTreeNode.arguments.size(); argumentIdx++) {
762 auto isLiteral = syntaxTreeNode.arguments[argumentIdx].type == MiniScript::ScriptSyntaxTreeNode::SCRIPTSYNTAXTREENODE_LITERAL;
763 if (isLiteral ==
true)
continue;
765 addMiniScriptNodeDeltaX(idMapping,
id +
"." + to_string(argumentIdx), syntaxTreeNode.arguments[argumentIdx], deltaX);
769 void TextEditorTabView::createMiniScriptScriptNode(unordered_map<string, string>& idMapping,
const string&
id, MiniScript::Script::ScriptType scriptType,
const string& condition,
const string& readableName,
const MiniScript::ScriptSyntaxTreeNode* conditionSyntaxTreeNode,
int x,
int y,
int& width,
int& height) {
774 if (conditionSyntaxTreeNode->type != MiniScript::ScriptSyntaxTreeNode::SCRIPTSYNTAXTREENODE_NONE) {
778 auto childHeight = 0;
779 vector<string> leftNodeIds;
780 createMiniScriptNodes(idMapping,
id +
".c", 0, 1, conditionSyntaxTreeNode,
Node::NODETYPE_ARGUMENT, x, y, childWidth, childHeight, leftNodeIds, 1);
783 height+= childHeight;
796 nodes[flattenedId] = {
799 .value = conditionSyntaxTreeNode->value.getValueAsString(),
800 .returnValueType = MiniScript::ScriptVariableType::TYPE_NULL,
806 auto nodeName = readableName;
807 string nodeTypeColor = string(
"color.nodetype_condition");
810 string xml =
"<template src='resources/engine/gui/template_visualcode_node.xml' id='" + flattenedId +
"' left='" + to_string(x) +
"' top='" + to_string(y) +
"' node-name='" + GUIParser::escape(nodeName +
"(" + flattenedId +
")") +
"' node-type-color='{$" + GUIParser::escape(nodeTypeColor) +
"}' />";
814 Console::println(
"TextEditorTabView::createMiniScriptScriptNode(): method/function: " +
string(exception.what()));
818 auto nodeInputContainer = required_dynamic_cast<GUIParentNode*>(
screenNode->
getNodeById(
id +
"_input_container"));
822 auto isLiteral = conditionSyntaxTreeNode->type == MiniScript::ScriptSyntaxTreeNode::SCRIPTSYNTAXTREENODE_NONE;
823 auto literal = isLiteral ==
true?condition:string();
828 " id='" + flattenedId +
"_c' " +
829 " src='resources/engine/gui/template_visualcode_input.xml' " +
830 " pin_type_connected='resources/engine/images/visualcode_value_connected.png' " +
831 " pin_type_unconnected='resources/engine/images/visualcode_value_unconnected.png' " +
833 " text='" + GUIParser::escape(
"Cond") +
"' ";
834 if (isLiteral ==
true) {
835 xml+=
" input_text='" + GUIParser::escape(literal) +
"' ";
840 GUIParser::parse(nodeInputContainer, xml);
842 if (isLiteral ==
true) {
844 required_dynamic_cast<GUIElementNode*>(
screenNode->
getNodeById(flattenedId +
"_c_input_type_panel"))->getActiveConditions().add(
"input");
847 required_dynamic_cast<GUIElementNode*>(
screenNode->
getNodeById(flattenedId +
"_c_pin_type_panel"))->getActiveConditions().add(
"connected");
850 Console::println(
"TextEditorTabView::createMiniScriptScriptNode(): method/function: " +
string(exception.what()));
856 if (conditionSyntaxTreeNode->type != MiniScript::ScriptSyntaxTreeNode::SCRIPTSYNTAXTREENODE_NONE) {
858 string argumentInputNodeId = flattenedId +
"_c";
862 if (argumentInputNode ==
nullptr) {
863 Console::println(
"TextEditorTabView::createMiniScriptNodes(): missing argument input node: " + argumentInputNodeId);
865 if (argumentOutputNode ==
nullptr) {
866 Console::println(
"TextEditorTabView::createMiniScriptNodes(): missing argument output node: " + argumentOutputNodeId);
870 auto pinColor = string(
"color.pintype_boolean");
871 GUIColor color(GUIParser::getEngineThemeProperties()->get(pinColor,
"#ffffff"));
874 const auto& argumentInputNodeComputedConstraints = argumentInputNode->getComputedConstraints();
875 const auto& argumentOutputNodeComputedConstraints = argumentOutputNode->getComputedConstraints();
879 .srcNodeId = argumentInputNodeId,
880 .dstNodeId = argumentOutputNodeId,
881 .red =
static_cast<uint8_t
>(color.
getRed() * 255.0f),
882 .green =
static_cast<uint8_t
>(color.
getGreen() * 255.0f),
883 .blue =
static_cast<uint8_t
>(color.
getBlue() * 255.0f),
884 .alpha =
static_cast<uint8_t
>(color.
getAlpha() * 255.0f),
885 .x1 = argumentInputNodeComputedConstraints.left,
886 .y1 = argumentInputNodeComputedConstraints.top + argumentInputNodeComputedConstraints.height / 2,
887 .x2 = argumentOutputNodeComputedConstraints.left + argumentOutputNodeComputedConstraints.width,
888 .y2 = argumentOutputNodeComputedConstraints.top + argumentOutputNodeComputedConstraints.height / 2,
896 height = Math::max(height, 200);
899 void TextEditorTabView::createMiniScriptNodes(unordered_map<string, string>& idMapping,
const string&
id,
int syntaxTreeNodeIdx,
int syntaxTreeNodeCount,
const MiniScript::ScriptSyntaxTreeNode* syntaxTreeNode,
Node::NodeType nodeType,
int x,
int y,
int& width,
int& height, vector<string>& createdNodeIds,
int depth) {
901 int childMaxWidth = 0;
906 vector<string> leftNodeIds;
907 for (
auto argumentIdx = 0; argumentIdx < syntaxTreeNode->arguments.size(); argumentIdx++) {
909 auto isLiteral = syntaxTreeNode->arguments[argumentIdx].type == MiniScript::ScriptSyntaxTreeNode::SCRIPTSYNTAXTREENODE_LITERAL;
910 if (isLiteral ==
true)
continue;
913 auto childHeight = 0;
914 createMiniScriptNodes(idMapping,
id +
"." + to_string(argumentIdx), argumentIdx, syntaxTreeNode->arguments.size(), &syntaxTreeNode->arguments[argumentIdx],
Node::NODETYPE_ARGUMENT, x, y, childWidth, childHeight, leftNodeIds, depth + 1);
915 if (childWidth > childMaxWidth) childMaxWidth = childWidth;
917 height+= childHeight;
923 width+= childMaxWidth;
926 for (
const auto& nodeId: leftNodeIds) createdNodeIds.push_back(nodeId);
932 switch (syntaxTreeNode->type) {
933 case MiniScript::ScriptSyntaxTreeNode::SCRIPTSYNTAXTREENODE_EXECUTE_METHOD:
934 case MiniScript::ScriptSyntaxTreeNode::SCRIPTSYNTAXTREENODE_EXECUTE_FUNCTION:
937 createdNodeIds.push_back(flattenedId);
939 nodes[flattenedId] = {
942 .value = syntaxTreeNode->value.getValueAsString(),
943 .returnValueType = syntaxTreeNode->method !=
nullptr?syntaxTreeNode->method->getReturnValueType():MiniScript::ScriptVariableType::TYPE_NULL,
948 auto nodeName = syntaxTreeNode->value.getValueAsString();
949 auto nodeTypeColor = string(
"color.nodetype_method");
952 nodeName = methodOperatorMapIt->second;
953 nodeTypeColor =
"color.nodetype_math";
956 if (syntaxTreeNode->method ==
nullptr) {
957 nodeTypeColor =
"color.nodetype_function";
960 if (nodeName == flowControlNode) {
961 nodeTypeColor =
"color.nodetype_flowcontrol";
966 if (nodeName == mathNode || StringTools::startsWith(nodeName, mathNode +
".")) {
967 nodeTypeColor =
"color.nodetype_math";
974 string xml =
"<template src='resources/engine/gui/template_visualcode_node.xml' id='" + flattenedId +
"' left='" + to_string(x) +
"' top='" + to_string(y) +
"' node-name='" + GUIParser::escape(nodeName +
"(" + flattenedId +
")") +
"' node-type-color='{$" + GUIParser::escape(nodeTypeColor) +
"}' />";
978 Console::println(
"TextEditorTabView::createMiniScriptNodes(): method/function: " +
string(exception.what()));
982 auto nodeInputContainer = required_dynamic_cast<GUIParentNode*>(
screenNode->
getNodeById(flattenedId +
"_input_container"));
983 auto nodeOutputContainer = required_dynamic_cast<GUIParentNode*>(
screenNode->
getNodeById(flattenedId +
"_output_container"));
991 " id='" + flattenedId +
"_fi' " +
992 " src='resources/engine/gui/template_visualcode_input.xml' " +
993 " pin_type_connected='resources/engine/images/visualcode_flow_connected.png' " +
994 " pin_type_unconnected='resources/engine/images/visualcode_flow_unconnected.png' " +
998 GUIParser::parse(nodeInputContainer, xml);
1000 required_dynamic_cast<GUIElementNode*>(
screenNode->
getNodeById(flattenedId +
"_fi_pin_type_panel"))->getActiveConditions().add(
"connected");
1002 Console::println(
"TextEditorTabView::createMiniScriptNodes(): method/function: " +
string(exception.what()));
1008 auto argumentIdx = 0;
1009 if (syntaxTreeNode->method !=
nullptr) {
1010 const auto& argumentTypes = syntaxTreeNode->method->getArgumentTypes();
1011 for (argumentIdx = 0; argumentIdx < argumentTypes.size(); argumentIdx++) {
1013 auto isLiteral = argumentIdx < syntaxTreeNode->arguments.size()?syntaxTreeNode->arguments[argumentIdx].type == MiniScript::ScriptSyntaxTreeNode::SCRIPTSYNTAXTREENODE_LITERAL:
false;
1014 auto literal = isLiteral ==
true?syntaxTreeNode->arguments[argumentIdx].value.getValueAsString():string();
1015 auto argumentName = argumentTypes[argumentIdx].name;
1016 if (argumentName.empty() ==
false) argumentName[0] = Character::toUpperCase(argumentName[0]);
1021 " id='" + flattenedId +
"_a" + to_string(argumentIdx) +
"' " +
1022 " src='resources/engine/gui/template_visualcode_input.xml' " +
1023 " pin_type_connected='resources/engine/images/visualcode_value_connected.png' " +
1024 " pin_type_unconnected='resources/engine/images/visualcode_value_unconnected.png' " +
1026 " text='" + GUIParser::escape(argumentName) +
"' ";
1027 if (isLiteral ==
true) {
1028 xml+=
" input_text='" + GUIParser::escape(literal) +
"' ";
1033 GUIParser::parse(nodeInputContainer, xml);
1035 if (isLiteral ==
true) {
1037 required_dynamic_cast<GUIElementNode*>(
screenNode->
getNodeById(flattenedId +
"_a" + to_string(argumentIdx) +
"_input_type_panel"))->getActiveConditions().add(
"input");
1040 required_dynamic_cast<GUIElementNode*>(
screenNode->
getNodeById(flattenedId +
"_a" + to_string(argumentIdx) +
"_pin_type_panel"))->getActiveConditions().add(
"connected");
1044 Console::println(
"TextEditorTabView::createMiniScriptNodes(): method/function: " +
string(exception.what()));
1048 for (; argumentIdx < syntaxTreeNode->arguments.size(); argumentIdx++) {
1050 auto isLiteral = syntaxTreeNode->arguments[argumentIdx].type == MiniScript::ScriptSyntaxTreeNode::SCRIPTSYNTAXTREENODE_LITERAL;
1051 auto literal = isLiteral ==
true?syntaxTreeNode->arguments[argumentIdx].value.getValueAsString():string();
1056 " id='" + flattenedId +
"_a" + to_string(argumentIdx) +
"' " +
1057 " src='resources/engine/gui/template_visualcode_input.xml' " +
1058 " pin_type_connected='resources/engine/images/visualcode_value_connected.png' " +
1059 " pin_type_unconnected='resources/engine/images/visualcode_value_unconnected.png' " +
1060 " pin_color='{$color.pintype_undefined}' " +
1061 " text='Arg " + to_string(argumentIdx) +
"' ";
1062 if (isLiteral ==
true) {
1063 xml+=
" input_text='" + GUIParser::escape(literal) +
"' ";
1068 GUIParser::parse(nodeInputContainer, xml);
1070 if (isLiteral ==
true) {
1072 required_dynamic_cast<GUIElementNode*>(
screenNode->
getNodeById(flattenedId +
"_a" + to_string(argumentIdx) +
"_input_type_panel"))->getActiveConditions().add(
"input");
1075 required_dynamic_cast<GUIElementNode*>(
screenNode->
getNodeById(flattenedId +
"_a" + to_string(argumentIdx) +
"_pin_type_panel"))->getActiveConditions().add(
"connected");
1078 Console::println(
"TextEditorTabView::createMiniScriptNodes(): method/function: " +
string(exception.what()));
1089 " id='" + flattenedId +
"_fo' " +
1090 " src='resources/engine/gui/template_visualcode_output.xml' " +
1091 " pin_type_connected='resources/engine/images/visualcode_flow_connected.png' " +
1092 " pin_type_unconnected='resources/engine/images/visualcode_flow_unconnected.png' " +
1096 GUIParser::parse(nodeOutputContainer, xml);
1098 required_dynamic_cast<GUIElementNode*>(
screenNode->
getNodeById(flattenedId +
"_fo_pin_type_panel"))->getActiveConditions().add(
"connected");
1100 Console::println(
"TextEditorTabView::createMiniScriptNodes(): method/function: " +
string(exception.what()));
1104 if (syntaxTreeNode->method !=
nullptr && syntaxTreeNode->method->getReturnValueType() != MiniScript::ScriptVariableType::TYPE_NULL) {
1110 " id='" + flattenedId +
"_r' " +
1111 " src='resources/engine/gui/template_visualcode_output.xml' " +
1112 " pin_type_connected='resources/engine/images/visualcode_value_connected.png' " +
1113 " pin_type_unconnected='resources/engine/images/visualcode_value_unconnected.png' " +
1120 GUIParser::parse(nodeOutputContainer, xml);
1122 required_dynamic_cast<GUIElementNode*>(
screenNode->
getNodeById(flattenedId +
"_r_pin_type_panel"))->getActiveConditions().add(
"connected");
1124 Console::println(
"TextEditorTabView::createMiniScriptNodes(): method/function: " +
string(exception.what()));
1129 if (syntaxTreeNode->method ==
nullptr) {
1135 " id='" + flattenedId +
"_r' " +
1136 " src='resources/engine/gui/template_visualcode_output.xml' " +
1137 " pin_type_connected='resources/engine/images/visualcode_value_connected.png' " +
1138 " pin_type_unconnected='resources/engine/images/visualcode_value_unconnected.png' " +
1139 " pin_color='{$color.pintype_undefined}' " +
1140 " text='Return Value' " +
1145 GUIParser::parse(nodeOutputContainer, xml);
1147 required_dynamic_cast<GUIElementNode*>(
screenNode->
getNodeById(flattenedId +
"_r_pin_type_panel"))->getActiveConditions().add(
"connected");
1149 Console::println(
"TextEditorTabView::createMiniScriptNodes(): method/function: " +
string(exception.what()));
1154 case MiniScript::ScriptSyntaxTreeNode::SCRIPTSYNTAXTREENODE_LITERAL:
1163 auto rootDistanceMax = Integer::MAX_VALUE;
1164 auto nextLevelXBestFit = -1;
1165 for (
auto argumentIdx = 0; argumentIdx < syntaxTreeNode->arguments.size(); argumentIdx++) {
1167 auto isLiteral = syntaxTreeNode->arguments[argumentIdx].type == MiniScript::ScriptSyntaxTreeNode::SCRIPTSYNTAXTREENODE_LITERAL;
1168 if (isLiteral ==
true)
continue;
1171 auto nodeXPosition = nextLevelNode->getRequestsConstraints().left;
1172 auto rootDistance = Math::abs(x - nodeXPosition);
1173 if (rootDistance < rootDistanceMax) {
1174 rootDistanceMax = rootDistance;
1175 nextLevelXBestFit = nodeXPosition;
1178 for (
auto argumentIdx = 0; argumentIdx < syntaxTreeNode->arguments.size(); argumentIdx++) {
1180 auto isLiteral = syntaxTreeNode->arguments[argumentIdx].type == MiniScript::ScriptSyntaxTreeNode::SCRIPTSYNTAXTREENODE_LITERAL;
1181 if (isLiteral ==
true)
continue;
1184 auto nodeXPosition = nextLevelNode->getRequestsConstraints().left;
1185 auto deltaX = nextLevelXBestFit - nodeXPosition;
1186 if (deltaX == 0)
continue;
1187 addMiniScriptNodeDeltaX(idMapping,
id +
"." + to_string(argumentIdx), syntaxTreeNode->arguments[argumentIdx], deltaX);
1191 for (
auto argumentIdx = 0; argumentIdx < syntaxTreeNode->arguments.size(); argumentIdx++) {
1193 auto isLiteral = syntaxTreeNode->arguments[argumentIdx].type == MiniScript::ScriptSyntaxTreeNode::SCRIPTSYNTAXTREENODE_LITERAL;
1194 if (isLiteral ==
true)
continue;
1196 string argumentInputNodeId = flattenedId +
"_a" + to_string(argumentIdx);
1200 if (argumentInputNode ==
nullptr) {
1201 Console::println(
"TextEditorTabView::createMiniScriptNodes(): missing argument input node: " + argumentInputNodeId);
1204 if (argumentOutputNode ==
nullptr) {
1205 Console::println(
"TextEditorTabView::createMiniScriptNodes(): missing argument output node: " + argumentOutputNodeId);
1210 auto pinColor = string(
"color.pintype_undefined");
1211 if (syntaxTreeNode->method !=
nullptr) {
1212 const auto& argumentTypes = syntaxTreeNode->method->getArgumentTypes();
1214 if (argumentIdx < argumentTypes.size()) {
1218 if (pinColor ==
"color.pintype_undefined") {
1219 auto node =
getNodeById(flattenedId +
"." + to_string(argumentIdx));
1220 if (node !=
nullptr) {
1221 if (node->returnValueType != MiniScript::ScriptVariableType::TYPE_NULL) {
1227 GUIColor color(GUIParser::getEngineThemeProperties()->get(pinColor,
"#ffffff"));
1230 const auto& argumentInputNodeComputedConstraints = argumentInputNode->getComputedConstraints();
1231 const auto& argumentOutputNodeComputedConstraints = argumentOutputNode->getComputedConstraints();
1235 .srcNodeId = argumentInputNodeId,
1236 .dstNodeId = argumentOutputNodeId,
1237 .red =
static_cast<uint8_t
>(color.
getRed() * 255.0f),
1238 .green =
static_cast<uint8_t
>(color.
getGreen() * 255.0f),
1239 .blue =
static_cast<uint8_t
>(color.
getBlue() * 255.0f),
1240 .alpha =
static_cast<uint8_t
>(color.
getAlpha() * 255.0f),
1241 .x1 = argumentInputNodeComputedConstraints.left,
1242 .y1 = argumentInputNodeComputedConstraints.top + argumentInputNodeComputedConstraints.height / 2,
1243 .x2 = argumentOutputNodeComputedConstraints.left + argumentOutputNodeComputedConstraints.width,
1244 .y2 = argumentOutputNodeComputedConstraints.top + argumentOutputNodeComputedConstraints.height / 2,
1250 void TextEditorTabView::createMiniScriptBranchNodes(unordered_map<string, string>& idMapping,
const string&
id,
int syntaxTreeNodeIdx,
int syntaxTreeNodeCount,
const MiniScript::ScriptSyntaxTreeNode* syntaxTreeNode,
Node::NodeType nodeType,
const vector<MiniScriptBranch>& branches,
int x,
int y,
int& width,
int& height, vector<string>& createdNodeIds,
int depth) {
1259 vector<string> leftNodeIds;
1260 auto childMaxWidth = 0;
1261 for (
auto branchIdx = 0; branchIdx < branches.size(); branchIdx++) {
1263 if (branches[branchIdx].conditionSyntaxTree ==
nullptr)
break;
1265 if (branches[branchIdx].conditionSyntaxTree->type == MiniScript::ScriptSyntaxTreeNode::SCRIPTSYNTAXTREENODE_LITERAL)
continue;
1268 auto childWidth = 0;
1269 auto childHeight = 0;
1270 createMiniScriptNodes(idMapping,
id +
"." + to_string(branchIdx), branchIdx, branches.size(), branches[branchIdx].conditionSyntaxTree,
Node::NODETYPE_ARGUMENT, x, y, childWidth, childHeight, leftNodeIds, depth + 1);
1271 if (childWidth > childMaxWidth) childMaxWidth = childWidth;
1273 height+= childHeight;
1277 width+= childMaxWidth;
1281 for (
const auto& nodeId: leftNodeIds) createdNodeIds.push_back(nodeId);
1288 createdNodeIds.push_back(flattenedId);
1290 nodes[flattenedId] = {
1293 .value = syntaxTreeNode->value.getValueAsString(),
1294 .returnValueType = MiniScript::ScriptVariableType::TYPE_NULL,
1299 string nodeName = syntaxTreeNode->value.getValueAsString();
1300 string nodeTypeColor = string(
"color.nodetype_flowcontrol");
1303 string xml =
"<template src='resources/engine/gui/template_visualcode_node.xml' id='" + flattenedId +
"' left='" + to_string(x) +
"' top='" + to_string(y) +
"' node-name='" + GUIParser::escape(nodeName +
"(" + flattenedId +
")") +
"' node-type-color='{$" + GUIParser::escape(nodeTypeColor) +
"}' />";
1307 Console::println(
"TextEditorTabView::createMiniScriptIfBranchNodes(): method/function: " +
string(exception.what()));
1311 auto nodeInputContainer = required_dynamic_cast<GUIParentNode*>(
screenNode->
getNodeById(flattenedId +
"_input_container"));
1312 auto nodeOutputContainer = required_dynamic_cast<GUIParentNode*>(
screenNode->
getNodeById(flattenedId +
"_output_container"));
1320 " id='" + flattenedId +
"_fi' " +
1321 " src='resources/engine/gui/template_visualcode_input.xml' " +
1322 " pin_type_connected='resources/engine/images/visualcode_flow_connected.png' " +
1323 " pin_type_unconnected='resources/engine/images/visualcode_flow_unconnected.png' " +
1327 GUIParser::parse(nodeInputContainer, xml);
1329 required_dynamic_cast<GUIElementNode*>(
screenNode->
getNodeById(flattenedId +
"_fi_pin_type_panel"))->getActiveConditions().add(
"connected");
1331 Console::println(
"TextEditorTabView::createMiniScriptIfBranchNodes(): method/function: " +
string(exception.what()));
1341 " id='" + flattenedId +
"_fo' " +
1342 " src='resources/engine/gui/template_visualcode_output.xml' " +
1343 " pin_type_connected='resources/engine/images/visualcode_flow_connected.png' " +
1344 " pin_type_unconnected='resources/engine/images/visualcode_flow_unconnected.png' " +
1348 GUIParser::parse(nodeOutputContainer, xml);
1350 required_dynamic_cast<GUIElementNode*>(
screenNode->
getNodeById(flattenedId +
"_fo_pin_type_panel"))->getActiveConditions().add(
"connected");
1352 Console::println(
"TextEditorTabView::createMiniScriptIfBranchNodes(): method/function: " +
string(exception.what()));
1356 for (
auto branchIdx = 0; branchIdx < branches.size(); branchIdx++) {
1359 if (branches[branchIdx].conditionSyntaxTree !=
nullptr) {
1361 auto isLiteral = branches[branchIdx].conditionSyntaxTree->type == MiniScript::ScriptSyntaxTreeNode::SCRIPTSYNTAXTREENODE_LITERAL;
1362 auto literal = isLiteral ==
true?branches[branchIdx].conditionSyntaxTree->value.getValueAsString():string();
1367 " id='" + flattenedId +
"_c" + to_string(branchIdx) +
"' " +
1368 " src='resources/engine/gui/template_visualcode_input.xml' " +
1369 " pin_type_connected='resources/engine/images/visualcode_value_connected.png' " +
1370 " pin_type_unconnected='resources/engine/images/visualcode_value_unconnected.png' " +
1371 " pin_color='{$" + GUIParser::escape(
getScriptVariableTypePinColor(nodeName ==
"forTime"?MiniScript::ScriptVariableType::TYPE_INTEGER:MiniScript::ScriptVariableType::TYPE_BOOLEAN)) +
"}' " +
1372 " text='" + GUIParser::escape(nodeName ==
"forTime"?
"time":
"Cond " + to_string(branchIdx)) +
"' ";
1373 if (isLiteral ==
true) {
1374 xml+=
" input_text='" + GUIParser::escape(literal) +
"' ";
1379 GUIParser::parse(nodeInputContainer, xml);
1381 if (isLiteral ==
true) {
1383 required_dynamic_cast<GUIElementNode*>(
screenNode->
getNodeById(flattenedId +
"_c" + to_string(branchIdx) +
"_input_type_panel"))->getActiveConditions().add(
"input");
1386 required_dynamic_cast<GUIElementNode*>(
screenNode->
getNodeById(flattenedId +
"_c" + to_string(branchIdx) +
"_pin_type_panel"))->getActiveConditions().add(
"connected");
1389 Console::println(
"TextEditorTabView::createMiniScriptIfBranchNodes(): method/function: " +
string(exception.what()));
1399 " id='" + flattenedId +
"_b" + to_string(branchIdx) +
"' " +
1400 " src='resources/engine/gui/template_visualcode_output.xml' " +
1401 " pin_type_connected='resources/engine/images/visualcode_flow_connected.png' " +
1402 " pin_type_unconnected='resources/engine/images/visualcode_flow_unconnected.png' " +
1403 " text='Flow " + to_string(branchIdx) +
"' " +
1407 GUIParser::parse(nodeOutputContainer, xml);
1409 required_dynamic_cast<GUIElementNode*>(
screenNode->
getNodeById(flattenedId +
"_b" + to_string(branchIdx) +
"_pin_type_panel"))->getActiveConditions().add(
"connected");
1411 Console::println(
"TextEditorTabView::createMiniScriptIfBranchNodes(): method/function: " +
string(exception.what()));
1422 auto rootDistanceMax = Integer::MAX_VALUE;
1423 auto nextLevelXBestFit = -1;
1424 for (
auto branchIdx = 0; branchIdx < branches.size(); branchIdx++) {
1426 if (branches[branchIdx].conditionSyntaxTree ==
nullptr)
break;
1428 if (branches[branchIdx].conditionSyntaxTree->type == MiniScript::ScriptSyntaxTreeNode::SCRIPTSYNTAXTREENODE_LITERAL)
continue;
1431 auto nodeXPosition = nextLevelNode->getRequestsConstraints().left;
1432 auto rootDistance = Math::abs(x - nodeXPosition);
1433 if (rootDistance < rootDistanceMax) {
1434 rootDistanceMax = rootDistance;
1435 nextLevelXBestFit = nodeXPosition;
1438 for (
auto branchIdx = 0; branchIdx < branches.size(); branchIdx++) {
1440 if (branches[branchIdx].conditionSyntaxTree ==
nullptr)
break;
1442 if (branches[branchIdx].conditionSyntaxTree->type == MiniScript::ScriptSyntaxTreeNode::SCRIPTSYNTAXTREENODE_LITERAL)
continue;
1445 auto nodeXPosition = nextLevelNode->getRequestsConstraints().left;
1446 auto deltaX = nextLevelXBestFit - nodeXPosition;
1447 if (deltaX == 0)
continue;
1448 addMiniScriptNodeDeltaX(idMapping,
id +
"." + to_string(branchIdx), *branches[branchIdx].conditionSyntaxTree, deltaX);
1452 for (
auto branchIdx = 0; branchIdx < branches.size(); branchIdx++) {
1454 if (branches[branchIdx].conditionSyntaxTree ==
nullptr ||
1455 (branches[branchIdx].conditionSyntaxTree !=
nullptr && branches[branchIdx].conditionSyntaxTree->type == MiniScript::ScriptSyntaxTreeNode::SCRIPTSYNTAXTREENODE_LITERAL))
continue;
1457 string conditionInputNodeId = flattenedId +
"_c" + to_string(branchIdx);
1461 if (conditionInputNode ==
nullptr) {
1462 Console::println(
"TextEditorTabView::createMiniScriptIfBranchNodes(): missing condition input node: " + conditionInputNodeId);
1465 if (conditionOutputNode ==
nullptr) {
1466 Console::println(
"TextEditorTabView::createMiniScriptIfBranchNodes(): missing condition output node: " + conditionOutputNodeId);
1471 auto pinColor = string(
"color.pintype_boolean");
1472 GUIColor color(GUIParser::getEngineThemeProperties()->get(pinColor,
"#ffffff"));
1475 const auto& conditionInputNodeComputedConstraints = conditionInputNode->getComputedConstraints();
1476 const auto& conditionOutputNodeComputedConstraints = conditionOutputNode->getComputedConstraints();
1480 .srcNodeId = conditionInputNodeId,
1481 .dstNodeId = conditionOutputNodeId,
1482 .red =
static_cast<uint8_t
>(color.
getRed() * 255.0f),
1483 .green =
static_cast<uint8_t
>(color.
getGreen() * 255.0f),
1484 .blue =
static_cast<uint8_t
>(color.
getBlue() * 255.0f),
1485 .alpha =
static_cast<uint8_t
>(color.
getAlpha() * 255.0f),
1486 .x1 = conditionInputNodeComputedConstraints.left,
1487 .y1 = conditionInputNodeComputedConstraints.top + conditionInputNodeComputedConstraints.height / 2,
1488 .x2 = conditionOutputNodeComputedConstraints.left + conditionOutputNodeComputedConstraints.width,
1489 .y2 = conditionOutputNodeComputedConstraints.top + conditionOutputNodeComputedConstraints.height / 2,
1495 vector<string> rightNodeIds;
1496 auto branchWidthMax = 0;
1498 for (
auto branchIdx = 0; branchIdx < branches.size(); branchIdx++) {
1500 auto branchSyntaxTreeNodes = branches[branchIdx].syntaxTreeNodes;
1504 x = xInitial + width;
1505 auto branchHeightMax = 0;
1506 auto branchWidth = 0;
1507 auto branchNodesWidth = 0;
1508 auto branchNodesHeight = 0;
1509 for (
auto i = 0; i < branchSyntaxTreeNodes.size(); i++) {
1510 auto branchSyntaxTreeNode = branchSyntaxTreeNodes[i];
1513 auto branchNodeIdx = i;
1514 branchNodesWidth = 0;
1515 branchNodesHeight = 0;
1516 while (
handleMiniScriptBranch(idMapping,
id +
".b." + to_string(branchIdx) +
".", branchSyntaxTreeNodes, i, x, y, branchNodesWidth, branchNodesHeight, rightNodeIds) ==
true) {
1518 x+= branchNodesWidth + 100;
1520 branchWidth += branchNodesWidth + 100;
1521 branchHeightMax = Math::max(branchHeightMax, branchNodesHeight);
1523 auto nodeFlowInId =
getMiniScriptNodeFlattenedId(idMapping,
id +
".b." + to_string(branchIdx) +
"." + to_string(branchNodeIdx)) +
"_fi";
1524 auto nodeFlowOutId =
getMiniScriptNodeFlattenedId(idMapping,
id +
".b." + to_string(branchIdx) +
"." + to_string(branchNodeIdx)) +
"_fo";
1527 if (previousNodeFlowNode !=
nullptr && nodeFlowIn !=
nullptr) {
1529 const auto& nodeComputedConstraints = nodeFlowIn->getComputedConstraints();
1533 .srcNodeId = previousNodeFlowNode->
getId(),
1534 .dstNodeId = nodeFlowInId,
1539 .x1 = previousNodeComputedConstraints.left + previousNodeComputedConstraints.width,
1540 .y1 = previousNodeComputedConstraints.top + previousNodeComputedConstraints.height / 2,
1541 .x2 = nodeComputedConstraints.left,
1542 .y2 = nodeComputedConstraints.top + nodeComputedConstraints.height / 2,
1547 if (i >= branchSyntaxTreeNodes.size())
break;
1549 previousNodeFlowNode = nodeFlowOut;
1552 branchNodesWidth = 0;
1553 branchNodesHeight = 0;
1557 if (i >= branchSyntaxTreeNodes.size())
break;
1558 branchSyntaxTreeNode = branchSyntaxTreeNodes[i];
1561 branchNodesWidth = 0;
1562 branchNodesHeight = 0;
1563 createMiniScriptNodes(idMapping,
id +
".b." + to_string(branchIdx) +
"." + to_string(i), i + 1, branchSyntaxTreeNodes.size() + 1, branchSyntaxTreeNode,
Node::NODETYPE_FLOW, x, y, branchNodesWidth, branchNodesHeight, rightNodeIds);
1566 x+= branchNodesWidth + 100;
1568 branchWidth += branchNodesWidth + 100;
1569 branchHeightMax = Math::max(branchHeightMax, branchNodesHeight);
1576 if (previousNodeFlowNode !=
nullptr && nodeFlowIn !=
nullptr) {
1578 const auto& nodeComputedConstraints = nodeFlowIn->getComputedConstraints();
1582 .srcNodeId = previousNodeFlowNode->
getId(),
1583 .dstNodeId = nodeFlowInId,
1588 .x1 = previousNodeComputedConstraints.left + previousNodeComputedConstraints.width,
1589 .y1 = previousNodeComputedConstraints.top + previousNodeComputedConstraints.height / 2,
1590 .x2 = nodeComputedConstraints.left,
1591 .y2 = nodeComputedConstraints.top + nodeComputedConstraints.height / 2,
1596 previousNodeFlowNode = nodeFlowOut;
1599 if (branchSyntaxTreeNodes.empty() ==
false) branchWidth-= 100;
1600 branchWidthMax = Math::max(branchWidthMax, branchWidth);
1601 y+= branchHeightMax;
1604 width+= branchWidthMax;
1605 height = Math::max(height, y - yInitial);
1607 for (
const auto& nodeId: rightNodeIds) createdNodeIds.push_back(nodeId);
1610 auto leftTop = Integer::MAX_VALUE;
1611 auto leftBottom = Integer::MIN_VALUE;
1612 for (
const auto& leftNodeId: leftNodeIds) {
1614 auto nodeTop = node->getRequestsConstraints().top;
1615 auto nodeBottom = node->getRequestsConstraints().top + 200;
1616 leftTop = Math::min(leftTop, nodeTop);
1617 leftBottom = Math::max(leftBottom, nodeBottom);
1621 auto rightTop = Integer::MAX_VALUE;
1622 auto rightBottom = Integer::MIN_VALUE;
1623 for (
const auto& rightNodeId: rightNodeIds) {
1625 auto nodeTop = node->getRequestsConstraints().top;
1626 auto nodeBottom = node->getRequestsConstraints().top + 200;
1627 rightTop = Math::min(rightTop, nodeTop);
1628 rightBottom = Math::max(rightBottom, nodeBottom);
1632 auto leftHeight = leftBottom - leftTop;
1633 auto rightHeight = rightBottom - rightTop;
1634 if (leftNodeIds.empty() ==
false && rightNodeIds.empty() ==
false) {
1635 if (leftHeight == rightHeight) {
1638 if (leftHeight > rightHeight) {
1639 auto deltaY = (leftHeight - rightHeight) / 2;
1640 for (
const auto& rightNodeId: rightNodeIds) {
1642 node->getRequestsConstraints().top+= deltaY;
1646 node->getRequestsConstraints().top = yInitial + (leftHeight - 200) / 2;
1649 auto deltaY = (rightHeight - leftHeight) / 2;
1650 for (
const auto& leftNodeId: leftNodeIds) {
1652 node->getRequestsConstraints().top+= deltaY;
1656 node->getRequestsConstraints().top = yInitial + (rightHeight - 200) / 2;
1663 bool TextEditorTabView::handleMiniScriptBranch(unordered_map<string, string>& idMapping,
const string& idPrefix,
const vector<MiniScript::ScriptSyntaxTreeNode*>& syntaxTree,
int& i,
int x,
int y,
int& width,
int& height, vector<string>& createdNodeIds) {
1665 auto syntaxTreeNode = syntaxTree[i];
1666 auto syntaxTreeNodeIdx = i;
1668 if (syntaxTreeNode->type == MiniScript::ScriptSyntaxTreeNode::SCRIPTSYNTAXTREENODE_EXECUTE_METHOD &&
1669 (syntaxTreeNode->value.getValueAsString() ==
"if" ||
1670 syntaxTreeNode->value.getValueAsString() ==
"forCondition" ||
1671 syntaxTreeNode->value.getValueAsString() ==
"forTime")) {
1673 auto ifStatement = syntaxTreeNode->value.getValueAsString() ==
"if";
1674 auto stackDepth = 1;
1675 vector<MiniScriptBranch> branches;
1678 .name = syntaxTreeNode->value.getValueAsString(),
1679 .conditionSyntaxTree = syntaxTreeNode->arguments.empty() ==
false?&syntaxTreeNode->arguments[0]:
nullptr,
1680 .syntaxTreeNodes = {}
1683 for (i++; i < syntaxTree.size(); i++) {
1684 auto branchSyntaxTreeNode = syntaxTree[i];
1685 if (branchSyntaxTreeNode->type == MiniScript::ScriptSyntaxTreeNode::SCRIPTSYNTAXTREENODE_EXECUTE_METHOD &&
1686 (branchSyntaxTreeNode->value.getValueAsString() ==
"if" ||
1687 branchSyntaxTreeNode->value.getValueAsString() ==
"forCondition" ||
1688 branchSyntaxTreeNode->value.getValueAsString() ==
"forTime")) {
1690 branches[branches.size() - 1].syntaxTreeNodes.push_back(branchSyntaxTreeNode);
1692 if (ifStatement ==
true && stackDepth == 1 && branchSyntaxTreeNode->type == MiniScript::ScriptSyntaxTreeNode::SCRIPTSYNTAXTREENODE_EXECUTE_METHOD && branchSyntaxTreeNode->value.getValueAsString() ==
"elseif") {
1695 .name = branchSyntaxTreeNode->value.getValueAsString(),
1696 .conditionSyntaxTree = branchSyntaxTreeNode->arguments.empty() ==
false?&branchSyntaxTreeNode->arguments[0]:
nullptr,
1697 .syntaxTreeNodes = {}
1701 if (ifStatement ==
true && stackDepth == 1 && branchSyntaxTreeNode->type == MiniScript::ScriptSyntaxTreeNode::SCRIPTSYNTAXTREENODE_EXECUTE_METHOD && branchSyntaxTreeNode->value.getValueAsString() ==
"else") {
1704 .name = branchSyntaxTreeNode->value.getValueAsString(),
1705 .conditionSyntaxTree =
nullptr,
1706 .syntaxTreeNodes = {}
1710 if (branchSyntaxTreeNode->type == MiniScript::ScriptSyntaxTreeNode::SCRIPTSYNTAXTREENODE_EXECUTE_METHOD && branchSyntaxTreeNode->value.getValueAsString() ==
"end") {
1714 if (stackDepth == 0) {
1716 createMiniScriptBranchNodes(idMapping, idPrefix + to_string(syntaxTreeNodeIdx), syntaxTreeNodeIdx, syntaxTree.size(), syntaxTreeNode,
Node::NODETYPE_FLOW, branches, x, y, width, height, createdNodeIds);
1723 branches[branches.size() - 1].syntaxTreeNodes.push_back(branchSyntaxTreeNode);
1726 branches[branches.size() - 1].syntaxTreeNodes.push_back(branchSyntaxTreeNode);
1737 this->
nodes.clear();
1740 unordered_map<string, string> idMapping;
1751 for (
auto i = 0; i < syntaxTrees.size(); i++) {
1756 createMiniScriptScriptNode(idMapping, to_string(i), syntaxTrees[i].type, syntaxTrees[i].condition, syntaxTrees[i].name, &syntaxTrees[i].conditionSyntaxTree, x, y, width, height);
1760 yMax = Math::max(y + height, yMax);
1761 xMax = Math::max(x + width, xMax);
1774 vector<MiniScript::ScriptSyntaxTreeNode*> syntaxTreeNodes;
1775 for (
auto& syntaxTreeNode: syntaxTree) syntaxTreeNodes.push_back(&syntaxTreeNode);
1777 if (syntaxTreeNodes.empty() ==
false &&
1778 syntaxTreeNodes[syntaxTreeNodes.size() - 1]->type == MiniScript::ScriptSyntaxTreeNode::SCRIPTSYNTAXTREENODE_EXECUTE_METHOD &&
1779 syntaxTreeNodes[syntaxTreeNodes.size() - 1]->value.getValueAsString() ==
"end") {
1780 syntaxTreeNodes.erase(syntaxTreeNodes.begin() + syntaxTreeNodes.size() - 1);
1788 vector<string> createdNodeIds;
1789 GUINode* previousNodeFlowNode =
nullptr;
1790 for (
auto i = 0; i < syntaxTreeNodes.size(); i++) {
1791 auto syntaxTreeNode = syntaxTreeNodes[i];
1796 auto branchNodeIdx = i;
1797 while (
handleMiniScriptBranch(idMapping,
string(), syntaxTreeNodes, i, x, y, width, height, createdNodeIds) ==
true) {
1800 yMax = Math::max(y + height, yMax);
1806 if (previousNodeFlowNode !=
nullptr && nodeFlowIn !=
nullptr) {
1808 const auto& nodeComputedConstraints = nodeFlowIn->getComputedConstraints();
1812 .srcNodeId = previousNodeFlowNode->
getId(),
1813 .dstNodeId = nodeFlowInId,
1818 .x1 = previousNodeComputedConstraints.left + previousNodeComputedConstraints.width,
1819 .y1 = previousNodeComputedConstraints.top + previousNodeComputedConstraints.height / 2,
1820 .x2 = nodeComputedConstraints.left,
1821 .y2 = nodeComputedConstraints.top + nodeComputedConstraints.height / 2,
1826 if (i >= syntaxTreeNodes.size())
break;
1828 previousNodeFlowNode = nodeFlowOut;
1836 if (i >= syntaxTreeNodes.size())
break;
1837 syntaxTreeNode = syntaxTreeNodes[i];
1842 createMiniScriptNodes(idMapping, to_string(i), i, syntaxTreeNodes.size(), syntaxTreeNode,
Node::NODETYPE_FLOW, x, y, width, height, createdNodeIds);
1846 yMax = Math::max(y + height, yMax);
1853 if (previousNodeFlowNode !=
nullptr && nodeFlowIn !=
nullptr) {
1855 const auto& nodeComputedConstraints = nodeFlowIn->getComputedConstraints();
1859 .srcNodeId = previousNodeFlowNode->
getId(),
1860 .dstNodeId = nodeFlowInId,
1865 .x1 = previousNodeComputedConstraints.left + previousNodeComputedConstraints.width,
1866 .y1 = previousNodeComputedConstraints.top + previousNodeComputedConstraints.height / 2,
1867 .x2 = nodeComputedConstraints.left,
1868 .y2 = nodeComputedConstraints.top + nodeComputedConstraints.height / 2,
1873 previousNodeFlowNode = nodeFlowOut;
1897 if (srcNode ==
nullptr) {
1900 if (dstNode ==
nullptr) {
1904 const auto& dstNodeComputedConstraints = dstNode->getComputedConstraints();
1905 switch (connection.type) {
1907 connection.x1 = srcNodeComputedConstraints.left + srcNodeComputedConstraints.width;
1908 connection.y1 = srcNodeComputedConstraints.top + srcNodeComputedConstraints.height / 2;
1909 connection.x2 = dstNodeComputedConstraints.left;
1910 connection.y2 = dstNodeComputedConstraints.top + dstNodeComputedConstraints.height / 2;
1913 connection.x1 = srcNodeComputedConstraints.left;
1914 connection.y1 = srcNodeComputedConstraints.top + srcNodeComputedConstraints.height / 2;
1915 connection.x2 = dstNodeComputedConstraints.left + dstNodeComputedConstraints.width;
1916 connection.y2 = dstNodeComputedConstraints.top + dstNodeComputedConstraints.height / 2;
1924 auto textNodeController = required_dynamic_cast<GUIStyledTextNodeController*>(
textNode->
getController());
1925 return textNodeController->getIndex();
1928 bool TextEditorTabView::find(
const string& findString,
bool matchCase,
bool wholeWord,
bool selection,
bool firstSearch,
int& index) {
1930 return TextTools::find(
textNode, findString, matchCase, wholeWord, selection, firstSearch, index);
1936 return TextTools::count(
textNode, findString, matchCase, wholeWord, selection);
1939 bool TextEditorTabView::replace(
const string& findString,
const string& replaceString,
bool matchCase,
bool wholeWord,
bool selection,
int& index) {
1941 auto success = TextTools::replace(
textNode, findString, replaceString, matchCase, wholeWord, selection, index);
1947 auto success = TextTools::replaceAll(
textNode, findString, replaceString, matchCase, wholeWord, selection);
2000 while (node !=
nullptr) {
2004 if (nextNodeId.empty() ==
true)
break;
2012 for (
auto i = 0; i < depth; i++) spacePrefix+=
"\t";
2013 if (node->
value ==
"if") {
2015 for (
auto conditionIdx = 0; conditionIdx < 100; conditionIdx++) {
2020 auto conditionNode =
getNodeById(conditionNodeId);
2021 if (conditionNode !=
nullptr) {
2022 sourceCode+= spacePrefix;
2023 if (conditionIdx == 0) {
2026 sourceCode+=
"elseif ";
2033 if (branchNode !=
nullptr) {
2034 if (conditionNode ==
nullptr) {
2035 sourceCode+= spacePrefix;
2036 sourceCode+=
"else";
2040 if (conditionNode ==
nullptr) {
2041 sourceCode+= spacePrefix;
2046 if (conditionNode ==
nullptr && branchNode ==
nullptr) {
2047 sourceCode+= spacePrefix;
2053 sourceCode+= spacePrefix;
2054 sourceCode+= node->
value +
"(";
2056 string argumentsSourceCode;
2057 for (
auto argumentIdx = 0; argumentIdx < 100; argumentIdx++) {
2059 if (argumentNodeId.empty() ==
true) {
2063 if (literalInput !=
nullptr) {
2065 if (argumentsSourceCode.empty() ==
false) argumentsSourceCode+=
", ";
2067 MiniScript::ScriptVariable value;
2068 MiniScript::ScriptStatement scriptStatement(
2069 MiniScript::LINE_NONE,
2070 MiniScript::STATEMENTIDX_NONE,
2073 MiniScript::STATEMENTIDX_NONE
2075 value.setImplicitTypedValueFromStringView(literalInputValue,
textEditorTabController->getMiniScript(), scriptStatement);
2076 if (value.getType() == MiniScript::TYPE_STRING) {
2077 argumentsSourceCode+=
"\"" + StringTools::replace(literalInputValue,
"\"",
"\\\"") +
"\"";
2079 argumentsSourceCode+= literalInputValue;
2085 if (argumentNode ==
nullptr)
continue;
2087 if (argumentsSourceCode.empty() ==
false) argumentsSourceCode+=
", ";
2091 sourceCode+= argumentsSourceCode +
")";
2098 auto srcNodeMatch = connection.srcNodeId == nodeId || StringTools::startsWith(connection.srcNodeId, nodeId +
"_") ==
true;
2099 auto dstNodeMatch = connection.dstNodeId == nodeId || StringTools::startsWith(connection.dstNodeId, nodeId +
"_") ==
true;
2100 if (srcNodeMatch ==
true || dstNodeMatch ==
true) {
2108 auto nodeIt =
nodes.find(nodeId);
2109 if (nodeIt ==
nodes.end())
return;
2110 nodes.erase(nodeIt);
2122 Console::println(
"TextEditorTabView::createConnection(): " + guiNodeId);
2124 if (guiNodeId.find(
"_r_") != string::npos) {
2125 auto connectionNodeId = StringTools::substring(guiNodeId, 0, guiNodeId.find(
"_r_") + 2);
2126 auto nodeId = StringTools::substring(guiNodeId, 0, guiNodeId.find(
"_r_"));
2128 if (argumentOutputNode !=
nullptr) {
2130 const auto& argumentOutputNodeComputedConstraints = argumentOutputNode->getComputedConstraints();
2131 auto pinColor = string(
"color.pintype_undefined");
2132 GUIColor color(GUIParser::getEngineThemeProperties()->get(pinColor,
"#ffffff"));
2136 .srcNodeId = string(),
2137 .dstNodeId = connectionNodeId,
2138 .red =
static_cast<uint8_t
>(color.
getRed() * 255.0f),
2139 .green =
static_cast<uint8_t
>(color.
getGreen() * 255.0f),
2140 .blue =
static_cast<uint8_t
>(color.
getBlue() * 255.0f),
2141 .alpha =
static_cast<uint8_t
>(color.
getAlpha() * 255.0f),
2142 .x1 = argumentOutputNodeComputedConstraints.left + argumentOutputNodeComputedConstraints.width,
2143 .y1 = argumentOutputNodeComputedConstraints.top + argumentOutputNodeComputedConstraints.height / 2,
2144 .x2 = argumentOutputNodeComputedConstraints.left + argumentOutputNodeComputedConstraints.width,
2145 .y2 = argumentOutputNodeComputedConstraints.top + argumentOutputNodeComputedConstraints.height / 2,
2154 if (guiNodeId.find(
"_fo_") != string::npos) {
2155 auto connectionNodeId = StringTools::substring(guiNodeId, 0, guiNodeId.find(
"_fo_") + 3);
2157 if (flowOutputFlowNode !=
nullptr) {
2159 const auto& flowOutputNodeComputedConstraints = flowOutputFlowNode->getComputedConstraints();
2160 auto pinColor = string(
"color.pintype_undefined");
2161 GUIColor color(GUIParser::getEngineThemeProperties()->get(pinColor,
"#ffffff"));
2165 .srcNodeId = connectionNodeId,
2166 .dstNodeId = string(),
2171 .x1 = flowOutputNodeComputedConstraints.left + flowOutputNodeComputedConstraints.width,
2172 .y1 = flowOutputNodeComputedConstraints.top + flowOutputNodeComputedConstraints.height / 2,
2173 .x2 = flowOutputNodeComputedConstraints.left + flowOutputNodeComputedConstraints.width,
2174 .y2 = flowOutputNodeComputedConstraints.top + flowOutputNodeComputedConstraints.height / 2,
2183 if (guiNodeId.find(
"_fi_") != string::npos) {
2184 auto connectionNodeId = StringTools::substring(guiNodeId, 0, guiNodeId.find(
"_fi_") + 3);
2186 if (flowInputNode !=
nullptr) {
2188 const auto& flowInputNodeComputedConstraints = flowInputNode->getComputedConstraints();
2189 auto pinColor = string(
"color.pintype_undefined");
2190 GUIColor color(GUIParser::getEngineThemeProperties()->get(pinColor,
"#ffffff"));
2194 .srcNodeId = string(),
2195 .dstNodeId = connectionNodeId,
2200 .x1 = flowInputNodeComputedConstraints.left,
2201 .y1 = flowInputNodeComputedConstraints.top + flowInputNodeComputedConstraints.height / 2,
2202 .x2 = flowInputNodeComputedConstraints.left,
2203 .y2 = flowInputNodeComputedConstraints.top + flowInputNodeComputedConstraints.height / 2,
2212 if (guiNodeId.find(
"_a") != string::npos) {
2213 auto connectionNodeId = StringTools::substring(guiNodeId, 0, guiNodeId.find(
"_", guiNodeId.find(
"_a") + 2));
2215 if (argumentInputNode !=
nullptr) {
2217 const auto& argumentInputNodeComputedConstraints = argumentInputNode->getComputedConstraints();
2218 auto pinColor = string(
"color.pintype_undefined");
2219 GUIColor color(GUIParser::getEngineThemeProperties()->get(pinColor,
"#ffffff"));
2223 .srcNodeId = guiNodeId,
2224 .dstNodeId = string(),
2225 .red =
static_cast<uint8_t
>(color.
getRed() * 255.0f),
2226 .green =
static_cast<uint8_t
>(color.
getGreen() * 255.0f),
2227 .blue =
static_cast<uint8_t
>(color.
getBlue() * 255.0f),
2228 .alpha =
static_cast<uint8_t
>(color.
getAlpha() * 255.0f),
2229 .x1 = argumentInputNodeComputedConstraints.left,
2230 .y1 = argumentInputNodeComputedConstraints.top + argumentInputNodeComputedConstraints.height / 2,
2231 .x2 = argumentInputNodeComputedConstraints.left,
2232 .y2 = argumentInputNodeComputedConstraints.top + argumentInputNodeComputedConstraints.height / 2,
2246 unordered_set<string> nodeIds;
2248 for (
const auto& nodeId: nodeIds) {
2250 if (nodeId.find(
"_r_") != string::npos) {
2254 auto connectionNodeId = StringTools::substring(nodeId, 0, nodeId.find(
"_r_") + 2);
2256 if (argumentNode !=
nullptr) {
2262 const auto& argumentNodeComputedConstraints = argumentNode->getComputedConstraints();
2263 connection.dstNodeId = connectionNodeId;
2264 connection.x2 = argumentNodeComputedConstraints.left + argumentNodeComputedConstraints.width;
2265 connection.y2 = argumentNodeComputedConstraints.top + argumentNodeComputedConstraints.height / 2;
2273 if (nodeId.find(
"_fo_") != string::npos) {
2274 auto connectionNodeId = StringTools::substring(nodeId, 0, nodeId.find(
"_fo_") + 3);
2279 if (flowNode !=
nullptr) {
2285 const auto& flowNodeComputedConstraints = flowNode->getComputedConstraints();
2286 connection.srcNodeId = connectionNodeId;
2287 connection.x1 = flowNodeComputedConstraints.left;
2288 connection.y1 = flowNodeComputedConstraints.top + flowNodeComputedConstraints.height / 2;
2296 if (nodeId.find(
"_fi_") != string::npos) {
2297 auto connectionNodeId = StringTools::substring(nodeId, 0, nodeId.find(
"_fi_") + 3);
2302 if (flowNode !=
nullptr) {
2308 const auto& flowNodeComputedConstraints = flowNode->getComputedConstraints();
2309 connection.dstNodeId = connectionNodeId;
2310 connection.x2 = flowNodeComputedConstraints.left + flowNodeComputedConstraints.width;
2311 connection.y2 = flowNodeComputedConstraints.top + flowNodeComputedConstraints.height / 2;
2319 if (nodeId.find(
"_a") != string::npos) {
2320 auto connectionNodeId = StringTools::substring(nodeId, 0, nodeId.find(
"_", nodeId.find(
"_a") + 2));
2325 if (argumentNode !=
nullptr) {
2331 const auto& argumentNodeComputedConstraints = argumentNode->getComputedConstraints();
2332 connection.srcNodeId = connectionNodeId;
2333 connection.x1 = argumentNodeComputedConstraints.left;
2334 connection.y1 = argumentNodeComputedConstraints.top + argumentNodeComputedConstraints.height / 2;
2354 case TextEditorTabController::CONTEXTMENUTYPE_NODE:
2360 class OnNodeDeleteAction:
public virtual Action
2363 void performAction()
override {
2364 textEditorTabView->deleteNode(nodeId);
2366 OnNodeDeleteAction(
TextEditorTabView* textEditorTabView,
const string& nodeId): textEditorTabView(textEditorTabView), nodeId(nodeId) {
2380 case TextEditorTabController::CONTEXTMENUTYPE_CANVAS:
Color 4 definition class.
void drawPixel(int x, int y, uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha)
Draw pixel.
void drawBezier(const vector< Vector2 > &controlPoints, uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha)
Draw bezier curve.
void clear(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha)
Clear texture with given clear color.
GUINodeConditions & getActiveConditions()
void setTexture(Texture *texture)
Set texture.
void set(const string &condition)
Set condition.
virtual const MutableString & getValue()=0
float computeParentChildrenRenderOffsetXTotal()
GUINode_RequestedConstraints & getRequestsConstraints()
GUINodeController * getController()
float computeParentChildrenRenderOffsetYTotal()
GUINode_ComputedConstraints & getComputedConstraints()
GUI parent node base class thats supporting child nodes.
void clearSubNodes()
Clear sub nodes.
void determineNodesByCoordinate(const Vector2 &coordinate, unordered_set< string > &nodeIds) override
Determine nodes by coordinate.
GUI screen node that represents a screen that can be rendered via GUI system.
void addContextMenuRequestListener(GUIContextMenuRequestListener *listener)
Add context menu request listener.
void addMoveListener(GUIMoveListener *listener)
Add move listener.
void addTooltipRequestListener(GUITooltipRequestListener *listener)
Add tooltip request listener.
GUINode * forceInvalidateLayout(GUINode *node)
Actually do the invalidate layout.
void removeNodeById(const string &nodeId, bool resetScrollOffsets)
Remove GUI node by id.
GUINode * getInnerNodeById(const string &nodeId)
Get inner GUI node by id.
GUINode * getNodeById(const string &nodeId)
Get GUI node by id.
int getNextDelimiter(int index, const string &delimiters)
Get next delimiter.
void insertText(int32_t idx, int c)
Insert character c at idx.
int getPreviousDelimiter(int index, const string &delimiters)
Get previous delimiter.
void removeText(int32_t idx, int32_t count)
Remove characters at idx with given length.
const MutableString & getText() const
Vector2 class representing vector2 mathematical structure and operations with x, y components.
File system singleton class.
Text editor tab controller.
const array< string, 12 > mathNodes
void saveFile(const string &pathName, const string &fileName)
Save file.
void setupContextMenu()
Set up context menu.
static constexpr int MINISCRIPT_SCRIPTIDX_STRUCTURE
void setVisualEditor()
Set visual editor.
const string getConnectedBranchNodeId(const string &nodeId, int branchIdx)
Find branch node id.
void dispose() override
Disposes the view.
CreateConnectionMode createConnectionMode
const string getScriptVariableTypePinColor(EngineMiniScript::ScriptVariableType type)
Get script variable type pin color.
void finishCreateConnection(int mouseX, int mouseY)
Finish creating connection.
void display() override
Renders the view.
void reloadOutliner() override
Reload outliner.
unique_ptr< GUIStyledTextNodeController::CodeCompletionListener > textNodeCodeCompletionListener
@ CREATECONNECTIONMODE_NONE
@ CREATECONNECTIONMODE_FLOW_OUT
@ CREATECONNECTIONMODE_ARGUMENT_OUT
@ CREATECONNECTIONMODE_ARGUMENT_IN
@ CREATECONNECTIONMODE_FLOW_IN
const string getNextNodeId(const string &nodeId)
Find next node.
void createSourceCodeFromNodes(string &sourceCode, const Node *node, int depth=0)
Create source code from nodes.
bool replace(const string &findString, const string &replaceString, bool matchCase, bool wholeWord, bool selection, int &index)
Replace string.
void setCodeEditor()
Set code editor.
const string getStartNodeId()
unique_ptr< Engine > engine
void initialize() override
Initiates the view.
void deactivate() override
Deactivate.
static const string getCreateConnectionModeName(CreateConnectionMode createConnectionMode)
GUIParentNode * visualisationNode
Engine * getEngine() override
unique_ptr< GUIMoveListener > guiMoveListener
Node * getNodeById(const string &nodeId)
Get node by id.
void handleInputEvents() override
Handle input events that have not yet been processed.
void createSourceCodeFromNode(string &sourceCode, const Node *node, int depth=0)
Create source code from node.
void cancelFind()
Cancel find.
void onMethodSelection(const string &methodName)
void deleteConnection(const string &nodeId)
Delete connection.
bool handleMiniScriptBranch(unordered_map< string, string > &idMapping, const string &idPrefix, const vector< EngineMiniScript::ScriptSyntaxTreeNode * > &syntaxTree, int &i, int x, int y, int &width, int &height, vector< string > &createdNodeIds)
Handle EngineMiniScript branch.
const array< string, 6 > flowControlNodes
TabView::OutlinerState outlinerState
unique_ptr< const TextFormatter::CodeCompletion > codeCompletion
bool isCreatingConnection()
Returns if creating a connection currently.
unique_ptr< TextEditorTabController > textEditorTabController
GUIStyledTextNode * textNode
void createMiniScriptNode(const string &methodName, int x, int y)
Create EngineMiniScript node.
const string getMiniScriptNodeFlattenedId(unordered_map< string, string > &idMapping, const string &hierarchicalId)
Get EngineMiniScript node flattened id from hierarchical id.
void activate() override
Activate.
unordered_map< string, string > methodOperatorMap
int createConnectionsPasses
GUIScreenNode * screenNode
~TextEditorTabView()
Destructor.
void addMiniScriptNodeDeltaX(unordered_map< string, string > &idMapping, const string &id, const EngineMiniScript::ScriptSyntaxTreeNode &syntaxTreeNode, int deltaX)
Adds a delta X value to UI node with given id and all nodes down the statement syntax tree.
void createMiniScriptBranchNodes(unordered_map< string, string > &idMapping, const string &id, int syntaxTreeNodeIdx, int syntaxTreeNodeCount, const EngineMiniScript::ScriptSyntaxTreeNode *syntaxTreeNode, Node::NodeType nodeType, const vector< MiniScriptBranch > &branches, int x, int y, int &width, int &height, vector< string > &createdNodeIds, int depth=0)
Create UI nodes for branch nodes like if, elseif, else, end; forTime, end; forCondition,...
void createConnection(const string &guiNodeId)
Create connection with given start or end node id.
const string getConnectedConditionNodeId(const string &nodeId, int conditionIdx)
Find condition node id.
void deleteNode(const string &nodeId)
Delete node.
int count(const string &findString, bool matchCase, bool wholeWord, bool selection)
Count string.
unique_ptr< GUIStyledTextNodeController::ChangeListener > textNodeChangeListener
bool find(const string &findString, bool matchCase, bool wholeWord, bool selection, bool firstSearch, int &index)
Find string.
unordered_map< string, Node > nodes
void createMiniScriptConnections()
Create miniscript connections.
EditorView * getEditorView()
void selectAll()
Select all.
vector< Connection > connections
void updateMiniScriptSyntaxTree(int miniScriptScriptIdx)
Update miniscript syntax tree.
void updateRendering() override
Update rendering.
void createMiniScriptScriptNode(unordered_map< string, string > &idMapping, const string &id, EngineMiniScript::Script::ScriptType scriptType, const string &condition, const string &readableName, const EngineMiniScript::ScriptSyntaxTreeNode *conditionSyntaxTreeNode, int x, int y, int &width, int &height)
Create UI nodes for EngineMiniScript script node syntax tree, which matches a event or function in En...
const string getArgumentNodeId(const string &nodeId, int argumentIdx)
Create argument node id.
unique_ptr< DynamicColorTexture > linesTexture
void createMiniScriptNodes(unordered_map< string, string > &idMapping, const string &id, int syntaxTreeNodeIdx, int syntaxTreeNodeCount, const EngineMiniScript::ScriptSyntaxTreeNode *syntaxTreeNode, Node::NodeType nodeType, int x, int y, int &width, int &height, vector< string > &createdNodeIds, int depth=0)
Create UI nodes for given statement syntax tree, which matches a statement in miniscript.
bool replaceAll(const string &findString, const string &replaceString, bool matchCase, bool wholeWord, bool selection)
Replace all string.
const string getConnectedArgumentNodeId(const string &nodeId, int argumentIdx)
Find argument node id.
char getCharAt(int32_t idx) const
Get char at given binary index.
const string & getString() const
Properties class, which helps out with storeing or loading key value pairs from/to property files.
std::exception Exception
Exception base class.
GUI move listener interface.
vector< string > parameters
@ CONNECTIONTYPE_ARGUMENT