From 3817dff0f807e8974422a8cfab04e774af1e5051 Mon Sep 17 00:00:00 2001 From: Benjamin Biglari Date: Sat, 25 Jul 2026 00:45:40 +0200 Subject: [PATCH] fixes needed to build VisualNodeSystemTest use cross platform method to set compile definitions moved BaseArithmeticOperatorNode::PerformOperation specializations out of class, to fix build error moved BaseArithmeticOperatorNode::Execute to cpp file to fix build error "specialization after instantiation" redefinition of RecordID in VisualNodeSystem fixed by renaming variable --- CMakeLists.txt | 10 +- .../Arithmetic/BaseArithmeticOperatorNode.cpp | 91 ++++++- .../Arithmetic/BaseArithmeticOperatorNode.h | 241 ++++++------------ VisualNodeSystem.cpp | 6 +- 4 files changed, 177 insertions(+), 171 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5d36c44..8c1d00d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -101,7 +101,6 @@ set(VariablesNodes_SOURCE_FILES) set(ControlFlowNodes_SOURCE_FILES) if(VISUAL_NODE_SYSTEM_BUILD_EXECUTION_FLOW_NODES) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /DVISUAL_NODE_SYSTEM_BUILD_EXECUTION_FLOW_NODES") # *************** EXECUTION_FLOW_NODES *************** list(APPEND BaseExecutionFlowNodes_SOURCE_FILES @@ -280,7 +279,10 @@ else() add_library(VisualNodeSystem STATIC ${ALL_SOURCE_FILES}) endif() -target_include_directories(VisualNodeSystem PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/ThirdParty/jsoncpp) +if(VISUAL_NODE_SYSTEM_BUILD_EXECUTION_FLOW_NODES) + #NOTE use cross platform method to set compile definitions + target_compile_definitions(VisualNodeSystem PRIVATE VISUAL_NODE_SYSTEM_BUILD_EXECUTION_FLOW_NODES) +endif() source_group("Source Files" FILES ${VisualNodeSystem_SRC}) source_group("Source Files/SubSystems/VisualNodeArea/" FILES ${VisualNodeArea_SRC}) @@ -301,6 +303,7 @@ endif() source_group("Source Files/ThirdParty/jsoncpp" FILES ${jsoncpp_SRC}) set(VISUAL_NODE_SYSTEM_THIRDPARTY_DIR ${CMAKE_CURRENT_SOURCE_DIR}/ThirdParty) +set(VISUAL_NODE_SYSTEM_THIRDPARTY_JSONCPP_DIR ${CMAKE_CURRENT_SOURCE_DIR}/ThirdParty/jsoncpp) # set the startup project set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT VisualNodeSystem) @@ -336,6 +339,7 @@ endif() include_directories( ${DEAR_IMGUI_INCLUDE_DIR} ${VISUAL_NODE_SYSTEM_THIRDPARTY_DIR} + ${VISUAL_NODE_SYSTEM_THIRDPARTY_JSONCPP_DIR} ) set(VISUAL_NODE_SYSTEM_THIRDPARTY_DIR ${CMAKE_CURRENT_SOURCE_DIR}/ThirdParty PARENT_SCOPE) @@ -353,4 +357,4 @@ add_custom_target(VisualNodeSystemPreBuild ${CMAKE_CURRENT_SOURCE_DIR}/VersionInfo/VISUAL_NODE_SYSTEM_Version.h ) -add_dependencies(VisualNodeSystem VisualNodeSystemPreBuild) \ No newline at end of file +add_dependencies(VisualNodeSystem VisualNodeSystemPreBuild) diff --git a/StandardNodes/ExecutionFlowNodes/OperatorNodes/Arithmetic/BaseArithmeticOperatorNode.cpp b/StandardNodes/ExecutionFlowNodes/OperatorNodes/Arithmetic/BaseArithmeticOperatorNode.cpp index c60f09f..8183518 100644 --- a/StandardNodes/ExecutionFlowNodes/OperatorNodes/Arithmetic/BaseArithmeticOperatorNode.cpp +++ b/StandardNodes/ExecutionFlowNodes/OperatorNodes/Arithmetic/BaseArithmeticOperatorNode.cpp @@ -167,4 +167,93 @@ bool BaseArithmeticOperatorNode::CanConnect(NodeSocket* OwnSocket, NodeSocket* C } return true; -} \ No newline at end of file +} + +void BaseArithmeticOperatorNode::Execute() +{ + // Both A and B input sockets are required to perform the operation. + if (Input.size() <= 2) + return; + + std::string CurrentMode = GetActiveINDataType(); + if (CurrentMode.empty()) + return; + + // If we don't have both A and B inputs connected, we can't do anything. + if (Input[1]->GetConnectedSockets().empty() && + Input[2]->GetConnectedSockets().empty()) + return; + + void* AData = nullptr; + if (!Input[1]->GetConnectedSockets().empty()) + AData = Input[1]->GetConnectedSockets()[0]->GetData(); + + void* BData = nullptr; + if (!Input[2]->GetConnectedSockets().empty()) + BData = Input[2]->GetConnectedSockets()[0]->GetData(); + + if (AData == nullptr && BData == nullptr) + return; + + // Call the appropriate operation method based on the data type. + if (CurrentMode == "INT") + { + int A = 0; + if (AData != nullptr) + A = *reinterpret_cast(AData); + + int B = 0; + if (BData != nullptr) + B = *reinterpret_cast(BData); + + LocalIntegerData = PerformOperation(A, B); + } + else if (CurrentMode == "FLOAT") + { + float A = 0.0f; + if (AData != nullptr) + A = *reinterpret_cast(AData); + + float B = 0.0f; + if (BData != nullptr) + B = *reinterpret_cast(BData); + + LocalFloatData = PerformOperation(A, B); + } + else if (CurrentMode == "VEC2") + { + glm::vec2 A = glm::vec2(0.0f); + if (AData != nullptr) + A = *reinterpret_cast(AData); + + glm::vec2 B = glm::vec2(0.0f); + if (BData != nullptr) + B = *reinterpret_cast(BData); + + LocalVec2Data = PerformOperation(A, B); + } + else if (CurrentMode == "VEC3") + { + glm::vec3 A = glm::vec3(0.0f); + if (AData != nullptr) + A = *reinterpret_cast(AData); + + glm::vec3 B = glm::vec3(0.0f); + if (BData != nullptr) + B = *reinterpret_cast(BData); + + LocalVec3Data = PerformOperation(A, B); + } + else if (CurrentMode == "VEC4") + { + glm::vec4 A = glm::vec4(0.0f); + if (AData != nullptr) + A = *reinterpret_cast(AData); + + glm::vec4 B = glm::vec4(0.0f); + if (BData != nullptr) + B = *reinterpret_cast(BData); + + LocalVec4Data = PerformOperation(A, B); + } +} diff --git a/StandardNodes/ExecutionFlowNodes/OperatorNodes/Arithmetic/BaseArithmeticOperatorNode.h b/StandardNodes/ExecutionFlowNodes/OperatorNodes/Arithmetic/BaseArithmeticOperatorNode.h index 9aa404b..7d96a80 100644 --- a/StandardNodes/ExecutionFlowNodes/OperatorNodes/Arithmetic/BaseArithmeticOperatorNode.h +++ b/StandardNodes/ExecutionFlowNodes/OperatorNodes/Arithmetic/BaseArithmeticOperatorNode.h @@ -59,169 +59,7 @@ class BaseArithmeticOperatorNode : public BaseExecutionFlowNode } } - // Specialization for integer type. - template <> - int PerformOperation(const int& A, const int& B) - { - switch (OperatorType) - { - case ArithmeticOperationType::ADD: - return A + B; - case ArithmeticOperationType::SUBTRACT: - return A - B; - case ArithmeticOperationType::MULTIPLY: - return A * B; - case ArithmeticOperationType::DIVIDE: - { - if (B == 0) - return A; - if (A == INT_MIN && B == -1) - return INT_MAX; // INT_MIN / -1 overflows int; saturate like the POWER case. - return A / B; - } - case ArithmeticOperationType::MODULUS: - { - if (B == 0) - return A; - if (A == INT_MIN && B == -1) - return 0; // INT_MIN % -1 is mathematically 0. - return A % B; - } - case ArithmeticOperationType::POWER: - { - const double Result = std::pow(static_cast(A), static_cast(B)); - - if (!std::isfinite(Result)) - return 0; - - if (Result >= static_cast(INT_MAX)) - return INT_MAX; - - if (Result <= static_cast(INT_MIN)) - return INT_MIN; - - return static_cast(Result); - } - default: - return A; - } - } - - // Specialization for floating-point type - template <> - float PerformOperation(const float& A, const float& B) - { - switch (OperatorType) - { - case ArithmeticOperationType::ADD: - return A + B; - case ArithmeticOperationType::SUBTRACT: - return A - B; - case ArithmeticOperationType::MULTIPLY: - return A * B; - case ArithmeticOperationType::DIVIDE: - if (B == 0.0f) - return A; - return A / B; - case ArithmeticOperationType::POWER: - return std::pow(A, B); - case ArithmeticOperationType::MODULUS: - if (B == 0.0f) - return A; - return std::fmod(A, B); - default: - return A; - } - } - - void Execute() - { - // Both A and B input sockets are required to perform the operation. - if (Input.size() <= 2) - return; - - std::string CurrentMode = GetActiveINDataType(); - if (CurrentMode.empty()) - return; - - // If we don't have both A and B inputs connected, we can't do anything. - if (Input[1]->GetConnectedSockets().empty() && - Input[2]->GetConnectedSockets().empty()) - return; - - void* AData = nullptr; - if (!Input[1]->GetConnectedSockets().empty()) - AData = Input[1]->GetConnectedSockets()[0]->GetData(); - - void* BData = nullptr; - if (!Input[2]->GetConnectedSockets().empty()) - BData = Input[2]->GetConnectedSockets()[0]->GetData(); - - if (AData == nullptr && BData == nullptr) - return; - - // Call the appropriate operation method based on the data type. - if (CurrentMode == "INT") - { - int A = 0; - if (AData != nullptr) - A = *reinterpret_cast(AData); - - int B = 0; - if (BData != nullptr) - B = *reinterpret_cast(BData); - - LocalIntegerData = PerformOperation(A, B); - } - else if (CurrentMode == "FLOAT") - { - float A = 0.0f; - if (AData != nullptr) - A = *reinterpret_cast(AData); - - float B = 0.0f; - if (BData != nullptr) - B = *reinterpret_cast(BData); - - LocalFloatData = PerformOperation(A, B); - } - else if (CurrentMode == "VEC2") - { - glm::vec2 A = glm::vec2(0.0f); - if (AData != nullptr) - A = *reinterpret_cast(AData); - - glm::vec2 B = glm::vec2(0.0f); - if (BData != nullptr) - B = *reinterpret_cast(BData); - - LocalVec2Data = PerformOperation(A, B); - } - else if (CurrentMode == "VEC3") - { - glm::vec3 A = glm::vec3(0.0f); - if (AData != nullptr) - A = *reinterpret_cast(AData); - - glm::vec3 B = glm::vec3(0.0f); - if (BData != nullptr) - B = *reinterpret_cast(BData); - - LocalVec3Data = PerformOperation(A, B); - } - else if (CurrentMode == "VEC4") - { - glm::vec4 A = glm::vec4(0.0f); - if (AData != nullptr) - A = *reinterpret_cast(AData); - - glm::vec4 B = glm::vec4(0.0f); - if (BData != nullptr) - B = *reinterpret_cast(BData); - - LocalVec4Data = PerformOperation(A, B); - } - } + void Execute(); std::function ResultDataGetter = [this]() -> void* { std::string CurrentMode = GetActiveINDataType(); @@ -263,4 +101,79 @@ class BaseArithmeticOperatorNode : public BaseExecutionFlowNode void Draw(); std::string GetActiveINDataType(); -}; \ No newline at end of file +}; + +// Specialization for integer type. +template <> +inline int BaseArithmeticOperatorNode::PerformOperation(const int& A, const int& B) +{ + switch (OperatorType) + { + case ArithmeticOperationType::ADD: + return A + B; + case ArithmeticOperationType::SUBTRACT: + return A - B; + case ArithmeticOperationType::MULTIPLY: + return A * B; + case ArithmeticOperationType::DIVIDE: + { + if (B == 0) + return A; + if (A == INT_MIN && B == -1) + return INT_MAX; // INT_MIN / -1 overflows int; saturate like the POWER case. + return A / B; + } + case ArithmeticOperationType::MODULUS: + { + if (B == 0) + return A; + if (A == INT_MIN && B == -1) + return 0; // INT_MIN % -1 is mathematically 0. + return A % B; + } + case ArithmeticOperationType::POWER: + { + const double Result = std::pow(static_cast(A), static_cast(B)); + + if (!std::isfinite(Result)) + return 0; + + if (Result >= static_cast(INT_MAX)) + return INT_MAX; + + if (Result <= static_cast(INT_MIN)) + return INT_MIN; + + return static_cast(Result); + } + default: + return A; + } +} + +// Specialization for floating-point type +template <> +inline float BaseArithmeticOperatorNode::PerformOperation(const float& A, const float& B) +{ + switch (OperatorType) + { + case ArithmeticOperationType::ADD: + return A + B; + case ArithmeticOperationType::SUBTRACT: + return A - B; + case ArithmeticOperationType::MULTIPLY: + return A * B; + case ArithmeticOperationType::DIVIDE: + if (B == 0.0f) + return A; + return A / B; + case ArithmeticOperationType::POWER: + return std::pow(A, B); + case ArithmeticOperationType::MODULUS: + if (B == 0.0f) + return A; + return std::fmod(A, B); + default: + return A; + } +} diff --git a/VisualNodeSystem.cpp b/VisualNodeSystem.cpp index 7816b92..69d11da 100644 --- a/VisualNodeSystem.cpp +++ b/VisualNodeSystem.cpp @@ -1211,7 +1211,7 @@ bool NodeSystem::UnlinkNodeAreas(const std::string& FirstAreaID, const std::stri continue; NodeAreaLinkRecord Record = LinkRecordIterator->second; - std::string RecordID = LinkRecordIterator->first; + std::string RecordIDLocal = LinkRecordIterator->first; NodeArea* InArea = GetNodeAreaByID(Record.InAreaID); if (InArea != nullptr) { @@ -1220,7 +1220,7 @@ bool NodeSystem::UnlinkNodeAreas(const std::string& FirstAreaID, const std::stri InArea->Delete(InNode); } - DeleteLinkRecord(RecordID); + DeleteLinkRecord(RecordIDLocal); } return !RecordIDsToRemove.empty(); @@ -2542,4 +2542,4 @@ std::vector NodeSystem::DeduplicateIDList(const std::vector SeenIDs(ListOfIDs.begin(), ListOfIDs.end()); return std::vector(SeenIDs.begin(), SeenIDs.end()); -} \ No newline at end of file +}