parameters
4
.gitignore
vendored
@ -8,7 +8,7 @@ bin
|
||||
*.VC.opendb
|
||||
*.user
|
||||
*.ini
|
||||
*.json
|
||||
docs/html
|
||||
docs/docbook
|
||||
build
|
||||
node_modules
|
||||
last-run.log
|
||||
@ -1,4 +0,0 @@
|
||||
./docs
|
||||
./scripts
|
||||
./tests
|
||||
./incoming
|
||||
25
Blueprints.json
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"selection": null,
|
||||
"view":
|
||||
{
|
||||
"scroll":
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"visible_rect":
|
||||
{
|
||||
"max":
|
||||
{
|
||||
"x": 1000,
|
||||
"y": 562
|
||||
},
|
||||
"min":
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0
|
||||
}
|
||||
},
|
||||
"zoom": 1
|
||||
}
|
||||
}
|
||||
4
BlueprintsGraph.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"app_links": null,
|
||||
"app_nodes": null
|
||||
}
|
||||
10
Blueprints_window.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"window": {
|
||||
"x": -1,
|
||||
"y": -1,
|
||||
"width": 1440,
|
||||
"height": 800,
|
||||
"monitor": 0,
|
||||
"maximized": false
|
||||
}
|
||||
}
|
||||
33
CMakeLists.txt
Normal file
@ -0,0 +1,33 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
project(NodeHub)
|
||||
|
||||
# ==============================================================================
|
||||
# Dependencies
|
||||
# ==============================================================================
|
||||
include(FetchContent)
|
||||
|
||||
# Google Test (for C++ unit tests)
|
||||
FetchContent_Declare(
|
||||
googletest
|
||||
URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip
|
||||
)
|
||||
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
||||
FetchContent_MakeAvailable(googletest)
|
||||
|
||||
# Protocol Buffers
|
||||
FetchContent_Declare(
|
||||
protobuf
|
||||
GIT_REPOSITORY https://github.com/protocolbuffers/protobuf.git
|
||||
GIT_TAG v21.9
|
||||
)
|
||||
FetchContent_MakeAvailable(protobuf)
|
||||
|
||||
# ==============================================================================
|
||||
# Add subdirectories
|
||||
# ==============================================================================
|
||||
add_subdirectory(applications/base)
|
||||
add_subdirectory(applications/nodehub)
|
||||
add_subdirectory(applications/protos)
|
||||
if (BUILD_TESTING)
|
||||
add_subdirectory(applications/tests)
|
||||
endif()
|
||||
2
Doxyfile
@ -1057,7 +1057,7 @@ EXCLUDE = ./build \
|
||||
./external/stb_image_latest \
|
||||
./misc \
|
||||
./NodeEditor/External \
|
||||
./examples/application
|
||||
./applications/
|
||||
|
||||
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
|
||||
# directories that are symbolic links (a Unix file system feature) are excluded
|
||||
|
||||
@ -1,31 +1,117 @@
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
# Set up vcpkg toolchain
|
||||
if(DEFINED CMAKE_TOOLCHAIN_FILE AND EXISTS "${CMAKE_TOOLCHAIN_FILE}")
|
||||
include(${CMAKE_TOOLCHAIN_FILE})
|
||||
endif()
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# ImGui Node Editor examples build configuration.
|
||||
# - `get_filename_component(... ABSOLUTE CACHE)` resolves the project root to
|
||||
# an absolute path and stores it in CMake's cache so re-configures reuse it.
|
||||
# - `USE_FOLDERS` enables logical IDE folders for generated projects.
|
||||
# - `BUILD_CONSOLE_VARIANTS` toggles additional Win32 console builds.
|
||||
# - `USE_CONSOLE_AS_STARTUP` selects which target Visual Studio launches.
|
||||
# - `EXAMPLES_NO_WARNING_FLAGS` holds warning overrides (set to `/W0` on MSVC).
|
||||
#------------------------------------------------------------------------------
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
# Root project that pulls in the node editor and builds the sample apps.
|
||||
project(imgui-node-editor)
|
||||
|
||||
# Enable testing capabilities with CTest
|
||||
enable_testing()
|
||||
|
||||
# Fetch Google Test framework
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
googletest
|
||||
URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip
|
||||
)
|
||||
|
||||
# Enforce the same compiler settings for gtest as for our project
|
||||
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
||||
|
||||
FetchContent_MakeAvailable(googletest)
|
||||
|
||||
# Option to enable/disable protobuf support (default: ON)
|
||||
option(ENABLE_PROTOBUF "Enable Protocol Buffers support" ON)
|
||||
|
||||
# Protocol Buffers support (optional, via vcpkg)
|
||||
if (ENABLE_PROTOBUF)
|
||||
# Try CONFIG mode first (modern protobuf CMake, works with vcpkg)
|
||||
find_package(protobuf CONFIG QUIET)
|
||||
if (protobuf_FOUND)
|
||||
message(STATUS "Protocol Buffers: ENABLED (found via CONFIG mode)")
|
||||
# Create an interface library to propagate protobuf settings
|
||||
add_library(protobuf_interface INTERFACE)
|
||||
target_link_libraries(protobuf_interface INTERFACE
|
||||
protobuf::libprotobuf
|
||||
protobuf::libprotoc
|
||||
)
|
||||
target_compile_definitions(protobuf_interface INTERFACE ENABLE_PROTOBUF=1)
|
||||
else()
|
||||
# Fallback to MODULE mode (legacy FindProtobuf)
|
||||
find_package(Protobuf QUIET)
|
||||
if (Protobuf_FOUND)
|
||||
message(STATUS "Protocol Buffers: ENABLED (found via MODULE mode)")
|
||||
# Create an interface library to propagate protobuf settings
|
||||
add_library(protobuf_interface INTERFACE)
|
||||
target_link_libraries(protobuf_interface INTERFACE ${Protobuf_LIBRARIES})
|
||||
target_include_directories(protobuf_interface INTERFACE ${Protobuf_INCLUDE_DIRS})
|
||||
target_compile_definitions(protobuf_interface INTERFACE ENABLE_PROTOBUF=1)
|
||||
else()
|
||||
message(WARNING "Protocol Buffers: ENABLED but not found. Install via 'vcpkg install protobuf[zlib] protobuf[zlib]:x64-windows' or set ENABLE_PROTOBUF=OFF")
|
||||
message(WARNING " To use vcpkg, configure CMake with: -DCMAKE_TOOLCHAIN_FILE=[path to vcpkg]/scripts/buildsystems/vcpkg.cmake")
|
||||
endif()
|
||||
endif()
|
||||
else()
|
||||
message(STATUS "Protocol Buffers: DISABLED")
|
||||
endif()
|
||||
|
||||
# Define IMGUI_NODE_EDITOR_ROOT_DIR pointing to project root directory
|
||||
get_filename_component(IMGUI_NODE_EDITOR_ROOT_DIR ${CMAKE_SOURCE_DIR}/.. ABSOLUTE CACHE)
|
||||
|
||||
# Define IMGUI_NODE_EDITOR_ROOT_DIR pointing to project root directory
|
||||
get_filename_component(ROOT_DIR ${CMAKE_SOURCE_DIR}/.. ABSOLUTE CACHE)
|
||||
|
||||
# Ensure IDE generators expose logical folder groupings instead of a flat list.
|
||||
# Enable solution folders in Visual Studio and Folders in Xcode
|
||||
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||
|
||||
# Extend the module search path so `find_package(imgui_node_editor)` locates the
|
||||
# custom `Findimgui_node_editor.cmake` bundled with this repository.
|
||||
# Point CMake where to look for module files.
|
||||
list(APPEND CMAKE_MODULE_PATH ${IMGUI_NODE_EDITOR_ROOT_DIR}/misc/cmake-modules)
|
||||
|
||||
# Central place to tweak warning configuration for all example targets.
|
||||
if (MSVC)
|
||||
set(EXAMPLES_NO_WARNING_FLAGS "/W0" CACHE STRING "Compiler warning overrides applied to all example targets" FORCE)
|
||||
elseif (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|AppleClang")
|
||||
set(EXAMPLES_NO_WARNING_FLAGS "-w" CACHE STRING "Compiler warning overrides applied to all example targets" FORCE)
|
||||
else()
|
||||
set(EXAMPLES_NO_WARNING_FLAGS "" CACHE STRING "Compiler warning overrides applied to all example targets" FORCE)
|
||||
endif()
|
||||
|
||||
# Examples use C++17 features (structured bindings, custom unordered_map hash).
|
||||
# Node editor use C++17 (required for structured bindings and unordered_map with custom hash)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED YES)
|
||||
|
||||
# Make it easy to toggle console builds without editing the file.
|
||||
# Option to also build console variants on Windows
|
||||
option(BUILD_CONSOLE_VARIANTS "Also build console variants of applications on Windows" ON)
|
||||
# option(BUILD_CONSOLE_VARIANTS "Also build console variants of applications on Windows" ON)
|
||||
|
||||
# Let developers choose which target Visual Studio launches by default.
|
||||
# Option to set console variant as default VS startup project
|
||||
option(USE_CONSOLE_AS_STARTUP "Set console variant as Visual Studio startup project" ON)
|
||||
# option(USE_CONSOLE_AS_STARTUP "Set console variant as Visual Studio startup project" ON)
|
||||
|
||||
|
||||
# Macro that will configure an example application
|
||||
macro(add_example_executable name)
|
||||
# Start a nested project for each example so properties such as versioning
|
||||
# remain isolated.
|
||||
project(${name})
|
||||
|
||||
# Collect all sources provided by the caller.
|
||||
set(_Example_Sources
|
||||
${ARGN}
|
||||
)
|
||||
@ -37,24 +123,26 @@ macro(add_example_executable name)
|
||||
# Group example sources under their tree
|
||||
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${ARGN})
|
||||
# Group entry_point.cpp separately since it's from application directory
|
||||
source_group("application" FILES ${APPLICATION_ENTRY_POINT_SOURCE})
|
||||
source_group("base" FILES ${APPLICATION_ENTRY_POINT_SOURCE})
|
||||
|
||||
file(GLOB _Example_CommonResources CONFIGURE_DEPENDS "${IMGUI_NODE_EDITOR_ROOT_DIR}/examples/data/*")
|
||||
file(GLOB _Nodehub_CommonResources CONFIGURE_DEPENDS "${IMGUI_NODE_EDITOR_ROOT_DIR}/applications/nodehub/data/*")
|
||||
file(GLOB _Example_CommonResources CONFIGURE_DEPENDS "${IMGUI_NODE_EDITOR_ROOT_DIR}/applications/base/data/*")
|
||||
file(GLOB _Example_Resources CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/data/*")
|
||||
#message(FATAL_ERROR "_Example_Resources = ${_Example_Resources}")
|
||||
|
||||
# Choose bundle/executable type depending on platform.
|
||||
set(_Example_Type)
|
||||
if (WIN32)
|
||||
set(_Example_Type WIN32)
|
||||
|
||||
set(ApplicationIcon ${IMGUI_NODE_EDITOR_ROOT_DIR}/examples/Application/Support/Icon.ico)
|
||||
set(ApplicationIcon ${IMGUI_NODE_EDITOR_ROOT_DIR}/applications/base/support/Icon.ico)
|
||||
file(TO_NATIVE_PATH "${ApplicationIcon}" ApplicationIcon)
|
||||
string(REPLACE "\\" "\\\\" ApplicationIcon "${ApplicationIcon}")
|
||||
configure_file(
|
||||
${IMGUI_NODE_EDITOR_ROOT_DIR}/examples/Application/Support/Resource.rc.in
|
||||
${IMGUI_NODE_EDITOR_ROOT_DIR}/applications/base/support/Resource.rc.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/Resource.rc
|
||||
)
|
||||
source_group(TREE "${IMGUI_NODE_EDITOR_ROOT_DIR}/examples" FILES ${_Example_CommonResources})
|
||||
source_group(TREE "${IMGUI_NODE_EDITOR_ROOT_DIR}/applications/base" FILES ${_Example_CommonResources})
|
||||
source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" FILES ${_Example_Resources})
|
||||
list(APPEND _Example_Resources
|
||||
${CMAKE_CURRENT_BINARY_DIR}/Resource.rc
|
||||
@ -67,7 +155,7 @@ macro(add_example_executable name)
|
||||
set_source_files_properties(${_Example_Resources} ${_Example_CommonResources} PROPERTIES
|
||||
MACOSX_PACKAGE_LOCATION "Resources/data"
|
||||
)
|
||||
set(_Example_Icon "${IMGUI_NODE_EDITOR_ROOT_DIR}/examples/application/support/Icon.icns")
|
||||
set(_Example_Icon "${IMGUI_NODE_EDITOR_ROOT_DIR}/applications/base/support/Icon.icns")
|
||||
list(APPEND _Example_Resources ${_Example_Icon})
|
||||
set_source_files_properties(${_Example_Icon} PROPERTIES
|
||||
MACOSX_PACKAGE_LOCATION "Resources"
|
||||
@ -76,6 +164,10 @@ macro(add_example_executable name)
|
||||
|
||||
add_executable(${name} ${_Example_Type} ${_Example_Sources} ${_Example_Resources} ${_Example_CommonResources})
|
||||
|
||||
if (EXAMPLES_NO_WARNING_FLAGS)
|
||||
target_compile_options(${name} PRIVATE ${EXAMPLES_NO_WARNING_FLAGS})
|
||||
endif()
|
||||
|
||||
# Add /FS flag for MSVC to prevent PDB locking issues during parallel builds
|
||||
if (WIN32 AND MSVC)
|
||||
target_compile_options(${name} PRIVATE /FS)
|
||||
@ -83,12 +175,17 @@ macro(add_example_executable name)
|
||||
|
||||
find_package(imgui REQUIRED)
|
||||
find_package(imgui_node_editor REQUIRED)
|
||||
target_link_libraries(${name} PRIVATE imgui imgui_node_editor application)
|
||||
target_link_libraries(${name} PRIVATE imgui imgui_node_editor base)
|
||||
|
||||
# Link protobuf if available
|
||||
if (ENABLE_PROTOBUF AND TARGET protobuf_interface)
|
||||
target_link_libraries(${name} PRIVATE protobuf_interface)
|
||||
endif()
|
||||
|
||||
set(_ExampleBinDir ${CMAKE_BINARY_DIR}/bin)
|
||||
|
||||
set_target_properties(${name} PROPERTIES
|
||||
FOLDER "examples"
|
||||
FOLDER "applications"
|
||||
RUNTIME_OUTPUT_DIRECTORY "${_ExampleBinDir}"
|
||||
RUNTIME_OUTPUT_DIRECTORY_DEBUG "${_ExampleBinDir}"
|
||||
RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO "${_ExampleBinDir}"
|
||||
@ -98,7 +195,7 @@ macro(add_example_executable name)
|
||||
RELWITHDEBINGO_POSTFIX _rd
|
||||
MINSIZEREL_POSTFIX _r
|
||||
VS_DEBUGGER_WORKING_DIRECTORY ${_ExampleBinDir}
|
||||
MACOSX_BUNDLE_INFO_PLIST "${IMGUI_NODE_EDITOR_ROOT_DIR}/examples/application/support/Info.plist.in"
|
||||
MACOSX_BUNDLE_INFO_PLIST "${IMGUI_NODE_EDITOR_ROOT_DIR}/applications/base/support/Info.plist.in"
|
||||
MACOSX_BUNDLE_BUNDLE_NAME "${PACKAGE_NAME}"
|
||||
MACOSX_BUNDLE_GUI_IDENTIFIER "com.sandbox.collisions"
|
||||
MACOSX_BUNDLE_LONG_VERSION_STRING "${PACKAGE_VERSION}"
|
||||
@ -106,6 +203,7 @@ macro(add_example_executable name)
|
||||
MACOSX_BUNDLE_ICON_FILE Icon.icns
|
||||
)
|
||||
|
||||
# Ensure the runtime data directory exists before copying anything in.
|
||||
add_custom_command(
|
||||
TARGET ${name}
|
||||
PRE_BUILD
|
||||
@ -113,7 +211,9 @@ macro(add_example_executable name)
|
||||
)
|
||||
|
||||
set(_ResourceRoot ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
foreach(_Resource ROOT "${IMGUI_NODE_EDITOR_ROOT_DIR}/examples/data" ${_Example_CommonResources} ROOT "${CMAKE_CURRENT_SOURCE_DIR}/data" ${_Example_Resources})
|
||||
# Copy both shared and example-specific data into the runtime folder while
|
||||
# preserving relative paths.
|
||||
foreach(_Resource ROOT "${IMGUI_NODE_EDITOR_ROOT_DIR}/applications/base/data" ${_Example_CommonResources} ROOT "${CMAKE_CURRENT_SOURCE_DIR}/data" ${_Example_Resources})
|
||||
if (_Resource STREQUAL ROOT)
|
||||
set(_ResourceRoot FALSE)
|
||||
continue()
|
||||
@ -144,6 +244,10 @@ macro(add_example_executable name)
|
||||
# Create console executable (without WIN32 flag)
|
||||
add_executable(${_ConsoleTargetName} ${_Example_Sources} ${_Example_Resources} ${_Example_CommonResources})
|
||||
|
||||
if (EXAMPLES_NO_WARNING_FLAGS)
|
||||
target_compile_options(${_ConsoleTargetName} PRIVATE ${EXAMPLES_NO_WARNING_FLAGS})
|
||||
endif()
|
||||
|
||||
# Define _CONSOLE to use main() instead of WinMain()
|
||||
target_compile_definitions(${_ConsoleTargetName} PRIVATE _CONSOLE)
|
||||
|
||||
@ -157,6 +261,11 @@ macro(add_example_executable name)
|
||||
find_package(imgui_node_editor REQUIRED)
|
||||
target_link_libraries(${_ConsoleTargetName} PRIVATE imgui imgui_node_editor application)
|
||||
|
||||
# Link protobuf if available
|
||||
if (ENABLE_PROTOBUF AND TARGET protobuf_interface)
|
||||
target_link_libraries(${_ConsoleTargetName} PRIVATE protobuf_interface)
|
||||
endif()
|
||||
|
||||
# Set the same properties as the GUI version
|
||||
set_target_properties(${_ConsoleTargetName} PROPERTIES
|
||||
FOLDER "examples"
|
||||
@ -178,7 +287,7 @@ macro(add_example_executable name)
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ARGS ${_ExampleBinDir}/data
|
||||
)
|
||||
|
||||
foreach(_Resource ROOT "${IMGUI_NODE_EDITOR_ROOT_DIR}/examples/data" ${_Example_CommonResources} ROOT "${CMAKE_CURRENT_SOURCE_DIR}/data" ${_Example_Resources})
|
||||
foreach(_Resource ROOT "${IMGUI_NODE_EDITOR_ROOT_DIR}/applications/base/data" ${_Example_CommonResources} ROOT "${CMAKE_CURRENT_SOURCE_DIR}/data" ${_Example_Resources})
|
||||
if (_Resource STREQUAL ROOT)
|
||||
set(_ResourceRoot FALSE)
|
||||
continue()
|
||||
@ -193,6 +302,7 @@ macro(add_example_executable name)
|
||||
|
||||
file(RELATIVE_PATH _RelResource ${_ResourceRoot} ${_Resource})
|
||||
|
||||
# Reuse the resource copying logic for the console binary.
|
||||
add_custom_command(
|
||||
TARGET ${_ConsoleTargetName}
|
||||
PRE_BUILD
|
||||
@ -203,14 +313,16 @@ macro(add_example_executable name)
|
||||
|
||||
endmacro()
|
||||
|
||||
add_subdirectory(application)
|
||||
add_subdirectory(blueprints-example)
|
||||
# Build the shared application support code and individual examples.
|
||||
add_subdirectory(base)
|
||||
add_subdirectory(nodehub)
|
||||
add_subdirectory(tests)
|
||||
|
||||
# Set the default Visual Studio startup project
|
||||
if (WIN32 AND BUILD_CONSOLE_VARIANTS AND USE_CONSOLE_AS_STARTUP)
|
||||
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT blueprints-example-console)
|
||||
message(STATUS "Visual Studio startup project: blueprints-example-console")
|
||||
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT nodehub-console)
|
||||
message(STATUS "Visual Studio startup project: nodehub-console")
|
||||
else()
|
||||
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT blueprints-example)
|
||||
message(STATUS "Visual Studio startup project: blueprints-example")
|
||||
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT nodehub)
|
||||
message(STATUS "Visual Studio startup project: nodehub")
|
||||
endif()
|
||||
@ -1,8 +1,9 @@
|
||||
project(application)
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
project(base)
|
||||
|
||||
set(_Application_Sources
|
||||
include/application.h
|
||||
source/application.cpp
|
||||
set(_base_Sources
|
||||
include/base.h
|
||||
source/base.cpp
|
||||
source/entry_point.cpp
|
||||
source/imgui_extra_keys.h
|
||||
source/config.h.in
|
||||
@ -18,23 +19,23 @@ set(_Application_Sources
|
||||
# entry_point.cpp is not included in the library because it has
|
||||
# conditional compilation for WinMain() vs main() based on _CONSOLE define.
|
||||
# It will be added directly to each executable target instead.
|
||||
set(APPLICATION_ENTRY_POINT_SOURCE
|
||||
set(base_ENTRY_POINT_SOURCE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/source/entry_point.cpp
|
||||
CACHE INTERNAL ""
|
||||
)
|
||||
|
||||
add_library(application STATIC)
|
||||
add_library(base STATIC)
|
||||
|
||||
target_include_directories(application PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
target_include_directories(base PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
|
||||
find_package(imgui REQUIRED)
|
||||
find_package(stb_image REQUIRED)
|
||||
find_package(ScopeGuard REQUIRED)
|
||||
target_link_libraries(application PUBLIC imgui)
|
||||
target_link_libraries(application PRIVATE stb_image ScopeGuard)
|
||||
target_link_libraries(base PUBLIC imgui)
|
||||
target_link_libraries(base PRIVATE stb_image ScopeGuard)
|
||||
|
||||
if (WIN32)
|
||||
list(APPEND _Application_Sources
|
||||
list(APPEND _base_Sources
|
||||
source/imgui_impl_dx11.cpp
|
||||
source/imgui_impl_dx11.h
|
||||
source/imgui_impl_win32.cpp
|
||||
@ -59,13 +60,13 @@ if (WIN32)
|
||||
INTERFACE_LINK_LIBRARIES "$<$<CONFIG:Debug>:dxerr>"
|
||||
)
|
||||
|
||||
target_link_libraries(application PRIVATE d3d11.lib d3dcompiler.lib d3dx11)
|
||||
target_link_libraries(base PRIVATE d3d11.lib d3dcompiler.lib d3dx11)
|
||||
else()
|
||||
find_package(OpenGL REQUIRED)
|
||||
find_package(glfw3 3 REQUIRED)
|
||||
|
||||
if (APPLE)
|
||||
target_link_libraries(application PRIVATE
|
||||
target_link_libraries(base PRIVATE
|
||||
"-framework CoreFoundation"
|
||||
"-framework Cocoa"
|
||||
"-framework IOKit"
|
||||
@ -77,9 +78,9 @@ endif()
|
||||
if (OpenGL_FOUND)
|
||||
set(HAVE_OPENGL YES)
|
||||
|
||||
target_include_directories(application PRIVATE ${OPENGL_INCLUDE_DIR})
|
||||
target_link_libraries(application PRIVATE ${OPENGL_gl_LIBRARY})
|
||||
list(APPEND _Application_Sources
|
||||
target_include_directories(base PRIVATE ${OPENGL_INCLUDE_DIR})
|
||||
target_link_libraries(base PRIVATE ${OPENGL_gl_LIBRARY})
|
||||
list(APPEND _base_Sources
|
||||
source/imgui_impl_opengl3.cpp
|
||||
source/imgui_impl_opengl3.h
|
||||
source/imgui_impl_opengl3_loader.h
|
||||
@ -89,11 +90,11 @@ endif()
|
||||
if (glfw3_FOUND)
|
||||
set(HAVE_GLFW3 YES)
|
||||
|
||||
list(APPEND _Application_Sources
|
||||
list(APPEND _base_Sources
|
||||
source/imgui_impl_glfw.cpp
|
||||
source/imgui_impl_glfw.h
|
||||
)
|
||||
target_link_libraries(application PRIVATE
|
||||
target_link_libraries(base PRIVATE
|
||||
glfw
|
||||
)
|
||||
endif()
|
||||
@ -103,16 +104,16 @@ configure_file(
|
||||
${CMAKE_CURRENT_BINARY_DIR}/source/config.h
|
||||
)
|
||||
|
||||
target_compile_definitions(application PRIVATE
|
||||
target_compile_definitions(base PRIVATE
|
||||
#BACKEND_CONFIG=IMGUI_GLFW
|
||||
#RENDERER_CONFIG=IMGUI_OGL3
|
||||
)
|
||||
|
||||
# Make config.h include directory PUBLIC since entry_point.cpp (which needs it) is now compiled in executables
|
||||
target_include_directories(application PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/source)
|
||||
target_include_directories(base PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/source)
|
||||
|
||||
source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" FILES ${_Application_Sources})
|
||||
source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" FILES ${_base_Sources})
|
||||
|
||||
target_sources(application PRIVATE ${_Application_Sources})
|
||||
target_sources(base PRIVATE ${_base_Sources})
|
||||
|
||||
set_property(TARGET application PROPERTY FOLDER "examples")
|
||||
set_property(TARGET base PROPERTY FOLDER "applications")
|
||||
33
applications/base/include/app-types.h
Normal file
@ -0,0 +1,33 @@
|
||||
#ifndef APP_TYPES_H
|
||||
#define APP_TYPES_H
|
||||
|
||||
# include <string>
|
||||
# include <memory>
|
||||
# include <map>
|
||||
# include <vector>
|
||||
#include <string>
|
||||
|
||||
struct ArgValue
|
||||
{
|
||||
enum class Type { Empty, Bool, Int, Double, String };
|
||||
|
||||
Type Type = Type::Empty;
|
||||
|
||||
bool Bool = false;
|
||||
long long Int = 0;
|
||||
double Double = 0.0;
|
||||
std::string String;
|
||||
|
||||
ArgValue() = default;
|
||||
ArgValue(bool value) : Type(Type::Bool), Bool(value) {}
|
||||
ArgValue(int value) : Type(Type::Int), Int(value) {}
|
||||
ArgValue(long long value) : Type(Type::Int), Int(value) {}
|
||||
ArgValue(float value) : Type(Type::Double), Double(value) {}
|
||||
ArgValue(double value) : Type(Type::Double), Double(value) {}
|
||||
ArgValue(const char* value) : Type(Type::String), String(value) {}
|
||||
ArgValue(std::string value) : Type(Type::String), String(std::move(value)) {}
|
||||
};
|
||||
|
||||
using ArgsMap = std::map<std::string, ArgValue>;
|
||||
|
||||
#endif
|
||||
@ -5,6 +5,9 @@
|
||||
# include <map>
|
||||
# include <vector>
|
||||
|
||||
# include "app-types.h"
|
||||
|
||||
|
||||
struct WindowState
|
||||
{
|
||||
int x = -1;
|
||||
@ -15,29 +18,6 @@ struct WindowState
|
||||
bool maximized = false;
|
||||
};
|
||||
|
||||
struct ArgValue
|
||||
{
|
||||
enum class Type { Empty, Bool, Int, Double, String };
|
||||
|
||||
Type Type = Type::Empty;
|
||||
|
||||
bool Bool = false;
|
||||
long long Int = 0;
|
||||
double Double = 0.0;
|
||||
std::string String;
|
||||
|
||||
ArgValue() = default;
|
||||
ArgValue(bool value) : Type(Type::Bool), Bool(value) {}
|
||||
ArgValue(int value) : Type(Type::Int), Int(value) {}
|
||||
ArgValue(long long value) : Type(Type::Int), Int(value) {}
|
||||
ArgValue(float value) : Type(Type::Double), Double(value) {}
|
||||
ArgValue(double value) : Type(Type::Double), Double(value) {}
|
||||
ArgValue(const char* value) : Type(Type::String), String(value) {}
|
||||
ArgValue(std::string value) : Type(Type::String), String(std::move(value)) {}
|
||||
};
|
||||
|
||||
using ArgsMap = std::map<std::string, ArgValue>;
|
||||
|
||||
struct Platform;
|
||||
struct Renderer;
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# include "application.h"
|
||||
# include "base.h"
|
||||
# include "setup.h"
|
||||
# include "platform.h"
|
||||
# include "renderer.h"
|
||||
@ -14,6 +14,71 @@
|
||||
# include <cstdio>
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
#ifdef _WIN32
|
||||
static inline std::string WideToUtf8(const wchar_t* wstr) {
|
||||
if (!wstr) return {};
|
||||
// Ask for required size (includes NUL)
|
||||
const int n = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, nullptr, 0, nullptr, nullptr);
|
||||
if (n <= 0) return {};
|
||||
std::string out;
|
||||
out.resize(n - 1); // we store without the trailing NUL
|
||||
|
||||
#if __cplusplus >= 201703L
|
||||
// C++17: string::data() is char*
|
||||
WideCharToMultiByte(CP_UTF8, 0, wstr, -1, out.data(), n, nullptr, nullptr);
|
||||
#else
|
||||
// C++11/14: use &out[0] to get char*
|
||||
WideCharToMultiByte(CP_UTF8, 0, wstr, -1, &out[0], n, nullptr, nullptr);
|
||||
#endif
|
||||
|
||||
// The call above wrote a NUL at the end because we passed length n.
|
||||
// Keep size at n-1 (already set via resize).
|
||||
return out;
|
||||
}
|
||||
|
||||
static std::string GetExecutableDir()
|
||||
{
|
||||
wchar_t exe_path_buffer[MAX_PATH] = { 0 };
|
||||
if (GetModuleFileNameW(NULL, exe_path_buffer, MAX_PATH) == 0)
|
||||
return "";
|
||||
|
||||
std::wstring exe_path(exe_path_buffer);
|
||||
size_t last_slash = exe_path.find_last_of(L"\\/");
|
||||
if (last_slash == std::wstring::npos)
|
||||
return "";
|
||||
|
||||
return WideToUtf8(exe_path.substr(0, last_slash).c_str());
|
||||
}
|
||||
#else
|
||||
static std::string GetExecutableDir()
|
||||
{
|
||||
// Implementation for other platforms (e.g., Linux, macOS) would go here.
|
||||
return "";
|
||||
}
|
||||
#endif
|
||||
|
||||
static std::string ResolveResourcePath(const std::string& relativePath)
|
||||
{
|
||||
static const std::string exeDir = GetExecutableDir();
|
||||
if (!exeDir.empty())
|
||||
{
|
||||
std::string exePath = exeDir + "/" + relativePath;
|
||||
std::ifstream f(exePath);
|
||||
if (f.good())
|
||||
{
|
||||
return exePath;
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback to CWD
|
||||
return relativePath;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
extern "C" {
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#define STB_IMAGE_STATIC
|
||||
@ -22,11 +87,7 @@ extern "C" {
|
||||
|
||||
|
||||
Application::Application(const char* name)
|
||||
: Application(name, {})
|
||||
{
|
||||
int d = 2;
|
||||
d++;
|
||||
}
|
||||
: Application(name, {}){}
|
||||
|
||||
Application::Application(const char* name, const ArgsMap& args)
|
||||
: m_Name(name)
|
||||
@ -170,8 +231,8 @@ void Application::RecreateFontAtlas()
|
||||
config.OversampleV = 4;
|
||||
config.PixelSnapH = false;
|
||||
|
||||
m_DefaultFont = io.Fonts->AddFontFromFileTTF("data/Play-Regular.ttf", 18.0f, &config);
|
||||
m_HeaderFont = io.Fonts->AddFontFromFileTTF("data/Cuprum-Bold.ttf", 20.0f, &config);
|
||||
m_DefaultFont = io.Fonts->AddFontFromFileTTF(ResolveResourcePath("data/Play-Regular.ttf").c_str(), 18.0f, &config);
|
||||
m_HeaderFont = io.Fonts->AddFontFromFileTTF(ResolveResourcePath("data/Cuprum-Bold.ttf").c_str(), 20.0f, &config);
|
||||
|
||||
io.Fonts->Build();
|
||||
}
|
||||
@ -273,7 +334,7 @@ ImFont* Application::HeaderFont() const
|
||||
ImTextureID Application::LoadTexture(const char* path)
|
||||
{
|
||||
int width = 0, height = 0, component = 0;
|
||||
if (auto data = stbi_load(path, &width, &height, &component, 4))
|
||||
if (auto data = stbi_load(ResolveResourcePath(path).c_str(), &width, &height, &component, 4))
|
||||
{
|
||||
auto texture = CreateTexture(data, width, height);
|
||||
stbi_image_free(data);
|
||||
4
applications/base/source/config.h
Normal file
@ -0,0 +1,4 @@
|
||||
# pragma once
|
||||
|
||||
# define HAVE_GLFW3 0
|
||||
# define HAVE_OPENGL 0
|
||||
@ -1,6 +1,6 @@
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
|
||||
# include "application.h"
|
||||
# include "base.h"
|
||||
# include "platform.h"
|
||||
# include <map>
|
||||
# include <vector>
|
||||
@ -44,7 +44,7 @@ public:
|
||||
|
||||
// Runtime execution options
|
||||
app.add_flag("--run", "Execute the graph runtime (used with --headless and --graph)");
|
||||
app.add_option("--log", "Logging options (all, blocks, links, none)")->capture_default_str();
|
||||
app.add_option("--log", "Path to log file (absolute or relative)")->capture_default_str();
|
||||
app.add_option("--log-level", "Minimum logging level (trace, debug, info, warn, error, critical, off)")->capture_default_str();
|
||||
|
||||
// Manual pre-check for help flag because allow_extras() interferes with normal help handling
|
||||
@ -68,9 +68,16 @@ public:
|
||||
|
||||
for (const CLI::Option* option : app.get_options())
|
||||
{
|
||||
if(option->count() > 0 && !option->get_lnames().empty() && !option->results().empty())
|
||||
if(option->count() > 0 && !option->get_lnames().empty())
|
||||
{
|
||||
(*args_map)[option->get_lnames()[0]] = ParseValue(option->results()[0]);
|
||||
if (!option->results().empty())
|
||||
{
|
||||
(*args_map)[option->get_lnames()[0]] = ParseValue(option->results()[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
(*args_map)[option->get_lnames()[0]] = ArgValue(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
|
||||
# if BACKEND(IMGUI_WIN32)
|
||||
|
||||
# include "application.h"
|
||||
# include "base.h"
|
||||
# include "renderer.h"
|
||||
|
||||
# define NOMINMAX
|
||||
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 5.4 KiB |
|
Before Width: | Height: | Size: 332 B After Width: | Height: | Size: 332 B |
|
Before Width: | Height: | Size: 168 B After Width: | Height: | Size: 168 B |
112
applications/nodehub/CMakeLists.txt
Normal file
@ -0,0 +1,112 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
add_example_executable(nodehub
|
||||
main.cpp
|
||||
types.h
|
||||
app.h
|
||||
app.cpp
|
||||
app-logic.cpp
|
||||
app-render.cpp
|
||||
app-screenshot.cpp
|
||||
app-runtime.cpp
|
||||
containers/container.h
|
||||
containers/container.cpp
|
||||
containers/root_container.h
|
||||
containers/root_container.cpp
|
||||
core/graph_state.h
|
||||
core/graph_state.cpp
|
||||
core/Object.h
|
||||
core/Object.cpp
|
||||
core/Parameter.h
|
||||
core/Parameter.cpp
|
||||
core/ParameterIn.h
|
||||
core/ParameterIn.cpp
|
||||
core/ParameterOut.h
|
||||
core/ParameterOut.cpp
|
||||
core/ParameterManager.h
|
||||
core/ParameterManager.cpp
|
||||
core/BaseManager.h
|
||||
core/BaseManager.cpp
|
||||
core/Context.h
|
||||
core/Context.cpp
|
||||
blocks/NodeEx.h
|
||||
blocks/NodeEx.cpp
|
||||
blocks/block.h
|
||||
blocks/block.cpp
|
||||
blocks/math_blocks.h
|
||||
blocks/math_blocks.cpp
|
||||
blocks/logic_blocks.h
|
||||
blocks/logic_blocks.cpp
|
||||
blocks/start_block.h
|
||||
blocks/start_block.cpp
|
||||
blocks/log_block.h
|
||||
blocks/log_block.cpp
|
||||
blocks/parameter_operation.h
|
||||
blocks/parameter_operation.cpp
|
||||
blocks/group_block.h
|
||||
blocks/group_block.cpp
|
||||
blocks/parameter_node.h
|
||||
blocks/parameter_node.cpp
|
||||
blocks/block_edit_dialog.h
|
||||
blocks/block_edit_dialog.cpp
|
||||
blocks/parameter_edit_dialog.h
|
||||
blocks/parameter_edit_dialog.cpp
|
||||
utilities/node_renderer_base.h
|
||||
utilities/pathfinding.h
|
||||
utilities/edge_editing.h
|
||||
utilities/pin_renderer.h
|
||||
utilities/style_manager.h
|
||||
utilities/uuid_generator.h
|
||||
utilities/uuid_id_manager.h
|
||||
utilities/node_renderer_base.cpp
|
||||
utilities/pathfinding.cpp
|
||||
utilities/edge_editing.cpp
|
||||
utilities/pin_renderer.cpp
|
||||
utilities/style_manager.cpp
|
||||
utilities/uuid_generator.cpp
|
||||
utilities/uuid_id_manager.cpp
|
||||
Logging.h
|
||||
Logging.cpp
|
||||
stats.cpp
|
||||
)
|
||||
|
||||
target_include_directories(nodehub PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../application/include")
|
||||
target_include_directories(nodehub PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../nodehub/core")
|
||||
target_include_directories(nodehub PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../nodehub/blocks")
|
||||
|
||||
# Add local spdlog include directory (we copied it into our project)
|
||||
target_include_directories(nodehub PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/external")
|
||||
target_compile_definitions(nodehub PRIVATE FMT_HEADER_ONLY=1)
|
||||
|
||||
# Add /utf-8 compiler flag for spdlog on MSVC
|
||||
if (MSVC)
|
||||
target_compile_options(nodehub PRIVATE /utf-8)
|
||||
endif()
|
||||
|
||||
# Link protobuf if available
|
||||
if (PROTOBUF_AVAILABLE AND TARGET protobuf_interface)
|
||||
target_link_libraries(nodehub PRIVATE protobuf_interface)
|
||||
endif()
|
||||
|
||||
# Also add to console variant if it exists
|
||||
if (WIN32 AND BUILD_CONSOLE_VARIANTS)
|
||||
target_include_directories(nodehub-console PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../application/include")
|
||||
target_include_directories(nodehub-console PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/external")
|
||||
target_compile_definitions(nodehub-console PRIVATE FMT_HEADER_ONLY=1)
|
||||
if (MSVC)
|
||||
target_compile_options(nodehub-console PRIVATE /utf-8)
|
||||
endif()
|
||||
# Link protobuf to console variant if available
|
||||
if (PROTOBUF_AVAILABLE AND TARGET protobuf_interface)
|
||||
target_link_libraries(nodehub-console PRIVATE protobuf_interface)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
file(GLOB NodeHubResources CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/data/*")
|
||||
add_custom_command(
|
||||
TARGET nodehub
|
||||
PRE_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/data"
|
||||
"$<TARGET_FILE_DIR:nodehub>/data"
|
||||
)
|
||||
14
applications/nodehub/all.h
Normal file
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
// v2
|
||||
#include "commons.h"
|
||||
#include "core/Object.h"
|
||||
#include "core/Parameter.h"
|
||||
|
||||
#include "utilities/uuid_generator.h"
|
||||
|
||||
|
||||
//legacy blocks - v1
|
||||
#include "blocks/block.h"
|
||||
#include "blocks/parameter_node.h"
|
||||
#include "blocks/parameter_operation.h"
|
||||
@ -482,19 +482,6 @@ void App::SaveGraph(const std::string& filename, RootContainer* container)
|
||||
continue;
|
||||
}
|
||||
|
||||
// Validate node pointer is not corrupted
|
||||
uintptr_t nodePtrValue = reinterpret_cast<uintptr_t>(nodePtr);
|
||||
if (nodePtrValue < 0x1000 ||
|
||||
nodePtrValue == 0xFFFFFFFFFFFFFFFFULL ||
|
||||
nodePtrValue == 0xDDDDDDDDDDDDDDDDULL ||
|
||||
nodePtrValue == 0xCDCDCDCDCDCDCDCDULL)
|
||||
{
|
||||
LOG_WARN("[SAVE] SaveGraph: Skipping corrupted node pointer: 0x{:016X}",
|
||||
static_cast<unsigned long long>(nodePtrValue));
|
||||
orphanedNodes.push_back(const_cast<Node*>(nodePtr));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Safe access to node type
|
||||
NodeType nodeType;
|
||||
try {
|
||||
@ -447,4 +447,5 @@ bool App::ExecuteRuntimeStep()
|
||||
|
||||
return didAnyWork;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -4,38 +4,6 @@
|
||||
#include <string>
|
||||
#include <ctime>
|
||||
|
||||
// Helper function to log to blueprints-log.md
|
||||
static void LogToFile(const char* fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
|
||||
// Always log to stdout/console
|
||||
vprintf(fmt, args);
|
||||
printf("\n");
|
||||
fflush(stdout);
|
||||
|
||||
// Log to blueprints-log.md (in the same directory as the executable)
|
||||
// The app runs from build/bin/, so just use relative path
|
||||
static FILE* logFile = nullptr;
|
||||
if (!logFile)
|
||||
{
|
||||
logFile = fopen("blueprints-log.md", "a");
|
||||
if (logFile)
|
||||
{
|
||||
fprintf(logFile, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (logFile)
|
||||
{
|
||||
vfprintf(logFile, fmt, args);
|
||||
fprintf(logFile, "\n");
|
||||
fflush(logFile);
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void App::TakeScreenshot(const char* filename)
|
||||
{
|
||||
@ -58,8 +26,6 @@ void App::TakeScreenshot(const char* filename)
|
||||
printf("App::TakeScreenshot - Using provided filename: %s\n", fname.c_str());
|
||||
}
|
||||
|
||||
LogToFile("Screenshot: Starting screenshot capture...");
|
||||
LogToFile("Screenshot: Using filename: %s", fname.c_str());
|
||||
|
||||
// Delegate to Application base class which calls the renderer
|
||||
bool success = Application::TakeScreenshot(fname.c_str());
|
||||
@ -71,13 +37,13 @@ void App::TakeScreenshot(const char* filename)
|
||||
{
|
||||
m_ScreenshotMessage = "Screenshot saved: " + fname;
|
||||
m_ScreenshotMessageTime = 5.0f;
|
||||
LogToFile("Screenshot: SUCCESS - Screenshot saved to: %s", fname.c_str());
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ScreenshotMessage = "Failed to save screenshot: " + fname;
|
||||
m_ScreenshotMessageTime = 5.0f;
|
||||
LogToFile("Screenshot: FAILED - Could not save screenshot");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,16 +1,39 @@
|
||||
#define IMGUI_DEFINE_MATH_OPERATORS
|
||||
#include "app.h"
|
||||
#include "nodes.h"
|
||||
#include "containers/root_container.h"
|
||||
#include "Logging.h"
|
||||
#include <imgui_node_editor.h>
|
||||
#include <imgui_node_editor_internal.h>
|
||||
|
||||
#include <app-types.h>
|
||||
|
||||
namespace ed = ax::NodeEditor;
|
||||
|
||||
ed::EditorContext* m_Editor = nullptr;
|
||||
|
||||
void App::OnStart()
|
||||
App::App(const char* name) : Application(name){
|
||||
m_Context = new NH_Context();
|
||||
initLogger();
|
||||
// m_Context->SetParameterManager(new NH_ParameterManager(m_Context));
|
||||
|
||||
}
|
||||
|
||||
App::App(const char* name, const ArgsMap& args) : Application(name, args){
|
||||
m_Context = new NH_Context();
|
||||
initLogger();
|
||||
}
|
||||
|
||||
App::App() : Application("Blueprints"){
|
||||
m_Context = new NH_Context();
|
||||
initLogger();
|
||||
}
|
||||
|
||||
NH_Context* App::GetContext()
|
||||
{
|
||||
return m_Context;
|
||||
}
|
||||
|
||||
void App::initLogger()
|
||||
{
|
||||
// Determine desired log level from CLI args
|
||||
std::string logLevelArg = "debug";
|
||||
@ -35,9 +58,10 @@ void App::OnStart()
|
||||
{
|
||||
LOG_WARN("Unknown log level '{}', defaulting to 'debug'", logLevelArg);
|
||||
}
|
||||
}
|
||||
|
||||
LOG_TRACE("[CHECKPOINT] OnStart: Beginning");
|
||||
|
||||
void App::OnStart()
|
||||
{
|
||||
// Get graph filename from CLI args (--graph), default to BlueprintsGraph.json
|
||||
// Supports both relative and absolute paths
|
||||
auto it = m_Args.find("graph");
|
||||
@ -51,7 +75,7 @@ void App::OnStart()
|
||||
LOG_INFO("Using default graph file: {}", m_GraphFilename);
|
||||
}
|
||||
|
||||
LOG_TRACE("[CHECKPOINT] OnStart: About to create root container");
|
||||
|
||||
|
||||
// Create default root container from graph filename
|
||||
AddRootContainer(m_GraphFilename);
|
||||
@ -196,7 +220,11 @@ void App::OnStart()
|
||||
|
||||
BuildNodes();
|
||||
|
||||
LOG_TRACE("[CHECKPOINT] OnStart: Nodes built, about to load textures");
|
||||
LOG_TRACE("[CHECKPOINT] OnStart: Nodes built, about to initialize context");
|
||||
|
||||
m_Context->init(this);
|
||||
|
||||
LOG_TRACE("[CHECKPOINT] OnStart: Context initialized, about to load textures");
|
||||
|
||||
m_HeaderBackground = LoadTexture("data/BlueprintBackground.png");
|
||||
m_SaveIcon = LoadTexture("data/ic_save_white_24dp.png");
|
||||
@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
#include <application.h>
|
||||
#include <base.h>
|
||||
#include "types.h"
|
||||
#include "blocks/parameter_node.h"
|
||||
#include "utilities/edge_editing.h"
|
||||
@ -11,11 +11,20 @@
|
||||
#include "core/graph_state.h"
|
||||
#include <map>
|
||||
|
||||
#include "app-types.h"
|
||||
|
||||
#include "core/Context.h"
|
||||
|
||||
namespace ed = ax::NodeEditor;
|
||||
|
||||
class App: public Application
|
||||
{
|
||||
public:
|
||||
|
||||
App();
|
||||
App(const char* name);
|
||||
App(const char* name, const ArgsMap& args);
|
||||
|
||||
using Application::Application;
|
||||
|
||||
// Application lifecycle
|
||||
@ -159,7 +168,10 @@ public:
|
||||
// Made public so blocks can access it for visualization
|
||||
std::map<ed::NodeId, float, NodeIdLess> m_RunningNodes; // Node ID -> expiration time
|
||||
|
||||
NH_Context* GetContext();
|
||||
|
||||
private:
|
||||
void initLogger();
|
||||
// Container management delegated to GraphState - see m_GraphState
|
||||
// Link highlighting for Run() visualization
|
||||
std::map<ed::LinkId, float, LinkIdLess> m_HighlightedLinks; // Link ID -> expiration time
|
||||
@ -184,5 +196,8 @@ private:
|
||||
Pin* m_NewLinkPin = nullptr;
|
||||
float m_LeftPaneWidth = 400.0f;
|
||||
float m_RightPaneWidth = 800.0f;
|
||||
|
||||
NH_Context *m_Context;
|
||||
|
||||
};
|
||||
|
||||
@ -1,14 +1,16 @@
|
||||
#define IMGUI_DEFINE_MATH_OPERATORS
|
||||
#include <crude_json.h>
|
||||
|
||||
#include "block.h"
|
||||
#include "../app.h"
|
||||
#include "../utilities/node_renderer_base.h"
|
||||
#include "../containers/container.h"
|
||||
#include "../../crude_json.h"
|
||||
#include "NodeEx.h"
|
||||
#include "constants.h"
|
||||
#include <imgui_node_editor.h>
|
||||
#include <imgui_internal.h>
|
||||
#include <set>
|
||||
#include "../Logging.h"
|
||||
|
||||
namespace ed = ax::NodeEditor;
|
||||
using namespace ax::NodeRendering;
|
||||
@ -41,7 +43,7 @@ static void RenderFlowPin(ImDrawList* drawList, const ImVec2& center, const ImVe
|
||||
void ParameterizedBlock::Render(Node& node, App* app, Pin* newLinkPin)
|
||||
{
|
||||
// Check if node is currently running (for red border visualization)
|
||||
float currentTime = ImGui::GetTime();
|
||||
double currentTime = (double)ImGui::GetTime();
|
||||
bool isRunning = false;
|
||||
auto runningIt = app->m_RunningNodes.find(node.ID);
|
||||
if (runningIt != app->m_RunningNodes.end())
|
||||
@ -234,7 +236,7 @@ void ParameterizedBlock::Render(Node& node, App* app, Pin* newLinkPin)
|
||||
// NodeStyleScope destructor handles cleanup automatically
|
||||
}
|
||||
|
||||
void ParameterizedBlock::AddInputParameter(App* app, Node& node, const char* name, PinType type)
|
||||
void ParameterizedBlock::AddInputParameter(App* app, Node& node, NH_CSTRING name, PinType type)
|
||||
{
|
||||
int pinId = app->GetNextId();
|
||||
m_InputParams.push_back(pinId);
|
||||
@ -242,7 +244,7 @@ void ParameterizedBlock::AddInputParameter(App* app, Node& node, const char* nam
|
||||
node.Inputs.emplace_back(pinId, name, type);
|
||||
}
|
||||
|
||||
void ParameterizedBlock::AddOutputParameter(App* app, Node& node, const char* name, PinType type)
|
||||
void ParameterizedBlock::AddOutputParameter(App* app, Node& node, NH_CSTRING name, PinType type)
|
||||
{
|
||||
int pinId = app->GetNextId();
|
||||
m_OutputParams.push_back(pinId);
|
||||
@ -250,19 +252,19 @@ void ParameterizedBlock::AddOutputParameter(App* app, Node& node, const char* na
|
||||
node.Outputs.emplace_back(pinId, name, type);
|
||||
}
|
||||
|
||||
void ParameterizedBlock::AddInput(App* app, Node& node, const char* name)
|
||||
void ParameterizedBlock::AddInput(App* app, Node& node, NH_CSTRING name)
|
||||
{
|
||||
int pinId = app->GetNextId();
|
||||
m_Inputs.push_back(pinId);
|
||||
const char* displayName = (name && *name) ? name : "";
|
||||
NH_CSTRING displayName = (name && *name) ? name : "";
|
||||
node.Inputs.emplace_back(pinId, displayName, PinType::Flow);
|
||||
}
|
||||
|
||||
void ParameterizedBlock::AddOutput(App* app, Node& node, const char* name)
|
||||
void ParameterizedBlock::AddOutput(App* app, Node& node, NH_CSTRING name)
|
||||
{
|
||||
int pinId = app->GetNextId();
|
||||
m_Outputs.push_back(pinId);
|
||||
const char* displayName = (name && *name) ? name : "";
|
||||
NH_CSTRING displayName = (name && *name) ? name : "";
|
||||
node.Outputs.emplace_back(pinId, displayName, PinType::Flow);
|
||||
}
|
||||
|
||||
@ -321,10 +323,7 @@ void ParameterizedBlock::OnMenu(Node& node, App* app)
|
||||
if (ImGui::MenuItem("Run (R)"))
|
||||
{
|
||||
int result = Run(node, app);
|
||||
printf("Block '%s' (ID: %d) Run() returned: %d\n",
|
||||
node.Name.c_str(), node.ID.Get(), result);
|
||||
ax::NodeEditor::AddInAppLog("Block '%s' (ID: %d) Run() returned: %d\n",
|
||||
node.Name.c_str(), node.ID.Get(), result);
|
||||
// LOG_INFO("Block '{}' (ID: {}) Run() returned: {}", node.Name.c_str(), node.ID.Get(), result);
|
||||
}
|
||||
}
|
||||
|
||||
@ -347,7 +346,7 @@ int ParameterizedBlock::GetInputParamValueInt(const Pin& pin, Node& node, App* a
|
||||
else if (sourcePin->Node->IsBlockBased())
|
||||
{
|
||||
// Source is a block output - read from UnconnectedParamValues
|
||||
int sourcePinId = sourcePin->ID.Get();
|
||||
const int sourcePinId = ToRuntimeId(sourcePin->ID);
|
||||
auto& sourceParamValues = sourcePin->Node->UnconnectedParamValues;
|
||||
if (sourceParamValues.find(sourcePinId) != sourceParamValues.end())
|
||||
{
|
||||
@ -362,7 +361,7 @@ int ParameterizedBlock::GetInputParamValueInt(const Pin& pin, Node& node, App* a
|
||||
}
|
||||
|
||||
// Not connected, use default value from UnconnectedParamValues
|
||||
int pinId = pin.ID.Get();
|
||||
const int pinId = ToRuntimeId(pin.ID);
|
||||
auto& paramValues = node.UnconnectedParamValues;
|
||||
if (paramValues.find(pinId) != paramValues.end())
|
||||
{
|
||||
@ -394,7 +393,7 @@ float ParameterizedBlock::GetInputParamValueFloat(const Pin& pin, Node& node, Ap
|
||||
else if (sourcePin->Node->IsBlockBased())
|
||||
{
|
||||
// Source is a block output - read from UnconnectedParamValues
|
||||
int sourcePinId = sourcePin->ID.Get();
|
||||
const int sourcePinId = ToRuntimeId(sourcePin->ID);
|
||||
auto& sourceParamValues = sourcePin->Node->UnconnectedParamValues;
|
||||
if (sourceParamValues.find(sourcePinId) != sourceParamValues.end())
|
||||
{
|
||||
@ -409,7 +408,7 @@ float ParameterizedBlock::GetInputParamValueFloat(const Pin& pin, Node& node, Ap
|
||||
}
|
||||
|
||||
// Not connected, use default value from UnconnectedParamValues
|
||||
int pinId = pin.ID.Get();
|
||||
const int pinId = ToRuntimeId(pin.ID);
|
||||
auto& paramValues = node.UnconnectedParamValues;
|
||||
if (paramValues.find(pinId) != paramValues.end())
|
||||
{
|
||||
@ -441,7 +440,7 @@ bool ParameterizedBlock::GetInputParamValueBool(const Pin& pin, Node& node, App*
|
||||
else if (sourcePin->Node->IsBlockBased())
|
||||
{
|
||||
// Source is a block output - read from UnconnectedParamValues
|
||||
int sourcePinId = sourcePin->ID.Get();
|
||||
const int sourcePinId = ToRuntimeId(sourcePin->ID);
|
||||
auto& sourceParamValues = sourcePin->Node->UnconnectedParamValues;
|
||||
if (sourceParamValues.find(sourcePinId) != sourceParamValues.end())
|
||||
{
|
||||
@ -456,7 +455,7 @@ bool ParameterizedBlock::GetInputParamValueBool(const Pin& pin, Node& node, App*
|
||||
}
|
||||
|
||||
// Not connected, use default value from UnconnectedParamValues
|
||||
int pinId = pin.ID.Get();
|
||||
const int pinId = ToRuntimeId(pin.ID);
|
||||
auto& paramValues = node.UnconnectedParamValues;
|
||||
if (paramValues.find(pinId) != paramValues.end())
|
||||
{
|
||||
@ -488,7 +487,7 @@ std::string ParameterizedBlock::GetInputParamValueString(const Pin& pin, Node& n
|
||||
else if (sourcePin->Node->IsBlockBased())
|
||||
{
|
||||
// Source is a block output - read from UnconnectedParamValues
|
||||
int sourcePinId = sourcePin->ID.Get();
|
||||
const int sourcePinId = ToRuntimeId(sourcePin->ID);
|
||||
auto& sourceParamValues = sourcePin->Node->UnconnectedParamValues;
|
||||
auto it = sourceParamValues.find(sourcePinId);
|
||||
if (it != sourceParamValues.end())
|
||||
@ -500,7 +499,7 @@ std::string ParameterizedBlock::GetInputParamValueString(const Pin& pin, Node& n
|
||||
}
|
||||
|
||||
// Not connected, use default value from UnconnectedParamValues
|
||||
int pinId = pin.ID.Get();
|
||||
const int pinId = ToRuntimeId(pin.ID);
|
||||
auto& paramValues = node.UnconnectedParamValues;
|
||||
auto it = paramValues.find(pinId);
|
||||
if (it != paramValues.end())
|
||||
@ -514,7 +513,7 @@ std::string ParameterizedBlock::GetInputParamValueString(const Pin& pin, Node& n
|
||||
void ParameterizedBlock::SetOutputParamValueInt(const Pin& pin, Node& node, App* app, int value)
|
||||
{
|
||||
// Store output value in node's UnconnectedParamValues (output pins can be read by connected nodes)
|
||||
int pinId = pin.ID.Get();
|
||||
const int pinId = ToRuntimeId(pin.ID);
|
||||
node.UnconnectedParamValues[pinId] = std::to_string(value);
|
||||
|
||||
// Propagate to ALL connected parameter nodes (iterate through all links from active container)
|
||||
@ -542,7 +541,7 @@ void ParameterizedBlock::SetOutputParamValueInt(const Pin& pin, Node& node, App*
|
||||
void ParameterizedBlock::SetOutputParamValueFloat(const Pin& pin, Node& node, App* app, float value)
|
||||
{
|
||||
// Store output value in node's UnconnectedParamValues
|
||||
int pinId = pin.ID.Get();
|
||||
const int pinId = ToRuntimeId(pin.ID);
|
||||
char buf[32];
|
||||
snprintf(buf, sizeof(buf), "%.6g", value);
|
||||
node.UnconnectedParamValues[pinId] = buf;
|
||||
@ -571,7 +570,7 @@ void ParameterizedBlock::SetOutputParamValueFloat(const Pin& pin, Node& node, Ap
|
||||
void ParameterizedBlock::SetOutputParamValueBool(const Pin& pin, Node& node, App* app, bool value)
|
||||
{
|
||||
// Store output value in node's UnconnectedParamValues
|
||||
int pinId = pin.ID.Get();
|
||||
const int pinId = ToRuntimeId(pin.ID);
|
||||
node.UnconnectedParamValues[pinId] = value ? "true" : "false";
|
||||
|
||||
// Propagate to ALL connected parameter nodes (iterate through all links from active container)
|
||||
@ -599,7 +598,7 @@ void ParameterizedBlock::SetOutputParamValueBool(const Pin& pin, Node& node, App
|
||||
void ParameterizedBlock::SetOutputParamValueString(const Pin& pin, Node& node, App* app, const std::string& value)
|
||||
{
|
||||
// Store output value in node's UnconnectedParamValues
|
||||
int pinId = pin.ID.Get();
|
||||
int pinId = ToRuntimeId(pin.ID);
|
||||
node.UnconnectedParamValues[pinId] = value;
|
||||
|
||||
// Propagate to ALL connected parameter nodes (iterate through all links from active container)
|
||||
@ -638,7 +637,7 @@ void ParameterizedBlock::SaveState(Node& node, crude_json::value& nodeData, cons
|
||||
if (pin.Type == PinType::Flow)
|
||||
continue;
|
||||
|
||||
int pinId = pin.ID.Get();
|
||||
const int pinId = ToRuntimeId(pin.ID);
|
||||
auto& paramValues = node.UnconnectedParamValues;
|
||||
auto it = paramValues.find(pinId);
|
||||
|
||||
@ -672,7 +671,7 @@ void ParameterizedBlock::SaveState(Node& node, crude_json::value& nodeData, cons
|
||||
if (pin.Type == PinType::Flow)
|
||||
continue;
|
||||
|
||||
int pinId = pin.ID.Get();
|
||||
const int pinId = ToRuntimeId(pin.ID);
|
||||
auto& paramValues = node.UnconnectedParamValues;
|
||||
auto it = paramValues.find(pinId);
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "../commons.h"
|
||||
|
||||
#include "../core/Object.h"
|
||||
#include "../utilities/node_renderer_base.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@ -9,75 +9,32 @@
|
||||
#include <functional>
|
||||
#include <imgui.h>
|
||||
|
||||
// Pin icon offset constants
|
||||
namespace BlockPinOffsets {
|
||||
// Y offset for input parameter pins (moves pins higher on top edge)
|
||||
static constexpr float INPUT_PARAM_Y = -8.0f;
|
||||
// Y offset for output parameter pins (moves pins lower on bottom edge)
|
||||
static constexpr float OUTPUT_PARAM_Y = 8; // Negated (12.0f)
|
||||
|
||||
// Parameter node specific output offset (can be different from general blocks)
|
||||
static constexpr float PARAM_NODE_OUTPUT_Y = 0.0f;
|
||||
|
||||
// Combined ImVec2 offsets for convenience
|
||||
static const ImVec2 INPUT_PARAM(0.0f, -15);
|
||||
static const ImVec2 OUTPUT_PARAM(0.0f, OUTPUT_PARAM_Y);
|
||||
static const ImVec2 PARAM_NODE_OUTPUT(0.0f, PARAM_NODE_OUTPUT_Y);
|
||||
|
||||
static const ImVec2 GROUP_INPUT_PARAM(0.0f, -15.0f);
|
||||
}
|
||||
|
||||
// Block style constants
|
||||
namespace BlockStyle {
|
||||
// Node appearance constants
|
||||
static constexpr float ROUNDING = 1.0f;
|
||||
static constexpr float BORDER_WIDTH = 1.0f;
|
||||
static constexpr float PADDING = 0.0f;
|
||||
|
||||
// Group block specific (more rounded, slightly thicker border)
|
||||
static constexpr float GROUP_ROUNDING = 1.0f;
|
||||
static constexpr float GROUP_BORDER_WIDTH = 1.0f;
|
||||
|
||||
// Parameter node constants (standardized across all display modes)
|
||||
static constexpr float PARAM_ROUNDING = 0.0f;
|
||||
static constexpr float PARAM_BORDER_WIDTH = 1.0f;
|
||||
static constexpr float PARAM_BORDER_WIDTH_SOURCE = 2.0f; // Thicker for source nodes
|
||||
static constexpr float PARAM_BORDER_WIDTH_NAME_AND_VALUE = 1.5f; // Slightly thicker for name+value mode
|
||||
static constexpr float PARAM_BORDER_WIDTH_SOURCE_NAME_AND_VALUE = 2.5f; // Source in name+value mode
|
||||
|
||||
// Parameter node padding (ImVec4 for per-edge control)
|
||||
static const ImVec4 PARAM_PADDING_NAME_ONLY(4.0f, 2.0f, 4.0f, 2.0f);
|
||||
static const ImVec4 PARAM_PADDING_NAME_AND_VALUE(8.0f, 4.0f, 8.0f, 4.0f);
|
||||
static const ImVec4 PARAM_PADDING_SMALL_BOX(2.0f, 2.0f, 2.0f, 2.0f);
|
||||
static const ImVec4 PARAM_PADDING_MINIMAL(4.0f, 4.0f, 4.0f, 4.0f);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Forward declarations
|
||||
class App;
|
||||
class Container;
|
||||
namespace crude_json { struct value; }
|
||||
|
||||
class Block
|
||||
class Block : public NH_Object
|
||||
{
|
||||
public:
|
||||
Block(int id, const char* name)
|
||||
: m_ID(id)
|
||||
, m_Name(name)
|
||||
Block(int id, NH_CSTRING name)
|
||||
: NH_Object(id, name)
|
||||
, m_Type(NodeType::Blueprint)
|
||||
, m_Color(ImColor(255, 255, 255))
|
||||
, m_bFlags(NHBEHAVIOR_NONE)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~Block() = default;
|
||||
|
||||
// Core identification
|
||||
int GetID() const { return m_ID; }
|
||||
const char* GetName() const { return m_Name.c_str(); }
|
||||
const char* GetTypeName() const { return m_TypeName.c_str(); }
|
||||
NH_BEHAVIOR_FLAGS GetFlags() const { return m_bFlags; }
|
||||
int GetID() const { return NH_Object::GetID(); }
|
||||
NH_CSTRING GetName() const { return NH_Object::GetName(); }
|
||||
NH_CSTRING GetTypeName() const { return NH_Object::GetTypeName(); }
|
||||
NH_BEHAVIOR_FLAGS GetFlags() const { return GetBehaviorFlags(); }
|
||||
void SetFlags(NH_BEHAVIOR_FLAGS flags) { SetBehaviorFlags(flags); }
|
||||
void AddFlags(NH_BEHAVIOR_FLAGS flags) { AddBehaviorFlags(flags); }
|
||||
void RemoveFlags(NH_BEHAVIOR_FLAGS flags) { RemoveBehaviorFlags(flags); }
|
||||
|
||||
// Node building (like NHBehavior's CreateInput/CreateOutput)
|
||||
virtual void Build(Node& node, App* app) = 0;
|
||||
@ -86,7 +43,7 @@ public:
|
||||
virtual void Render(Node& node, App* app, Pin* newLinkPin) = 0;
|
||||
|
||||
// Serialization support
|
||||
virtual const char* GetBlockType() const = 0; // Unique type identifier
|
||||
virtual NH_CSTRING GetBlockType() const = 0; // Unique type identifier
|
||||
|
||||
// State save/load callbacks (optional - subclasses can override to save/load custom state)
|
||||
// These are called from App::SaveGraph() / App::LoadGraph()
|
||||
@ -122,19 +79,15 @@ protected:
|
||||
// Activation state (stored per-block instance)
|
||||
std::vector<bool> m_OutputActive; // Output activation states
|
||||
std::vector<bool> m_InputActive; // Input activation states
|
||||
int m_ID;
|
||||
std::string m_Name;
|
||||
std::string m_TypeName;
|
||||
NodeType m_Type;
|
||||
ImColor m_Color;
|
||||
NH_BEHAVIOR_FLAGS m_bFlags; // Behavior flags
|
||||
};
|
||||
|
||||
// Extended block with parameters - like NHBehavior with params
|
||||
class ParameterizedBlock : public Block, public ax::NodeRendering::NodeRendererBase
|
||||
{
|
||||
public:
|
||||
ParameterizedBlock(int id, const char* name)
|
||||
ParameterizedBlock(int id, NH_CSTRING name)
|
||||
: Block(id, name)
|
||||
{
|
||||
}
|
||||
@ -142,12 +95,12 @@ public:
|
||||
virtual ~ParameterizedBlock() = default;
|
||||
|
||||
// Parameter creation helpers (like NHBehavior::CreateInputParameter)
|
||||
void AddInputParameter(App* app, Node& node, const char* name, PinType type);
|
||||
void AddOutputParameter(App* app, Node& node, const char* name, PinType type);
|
||||
void AddInputParameter(App* app, Node& node, NH_CSTRING name, PinType type);
|
||||
void AddOutputParameter(App* app, Node& node, NH_CSTRING name, PinType type);
|
||||
|
||||
// I/O creation (flow control)
|
||||
void AddInput(App* app, Node& node, const char* name);
|
||||
void AddOutput(App* app, Node& node, const char* name);
|
||||
void AddInput(App* app, Node& node, NH_CSTRING name);
|
||||
void AddOutput(App* app, Node& node, NH_CSTRING name);
|
||||
|
||||
int GetInputParameterCount() const override { return (int)m_InputParams.size(); }
|
||||
int GetOutputParameterCount() const override { return (int)m_OutputParams.size(); }
|
||||
@ -197,12 +150,12 @@ public:
|
||||
return instance;
|
||||
}
|
||||
|
||||
void RegisterBlock(const char* typeName, BlockFactory factory)
|
||||
void RegisterBlock(NH_CSTRING typeName, BlockFactory factory)
|
||||
{
|
||||
m_Factories[typeName] = factory;
|
||||
}
|
||||
|
||||
Block* CreateBlock(const char* typeName, int id)
|
||||
Block* CreateBlock(NH_CSTRING typeName, int id)
|
||||
{
|
||||
auto it = m_Factories.find(typeName);
|
||||
if (it != m_Factories.end())
|
||||
@ -106,7 +106,7 @@ void RenderBlockEditDialog()
|
||||
ImGui::SameLine();
|
||||
ImGui::PushItemWidth(200.0f);
|
||||
static std::map<int, std::string> nodeNameBuffers; // Per-node name buffers
|
||||
int nodeId = s_EditingNode->ID.Get();
|
||||
int nodeId = ToRuntimeId(s_EditingNode->ID);
|
||||
if (nodeNameBuffers.find(nodeId) == nodeNameBuffers.end())
|
||||
{
|
||||
nodeNameBuffers[nodeId] = s_EditingNode->Name;
|
||||
@ -159,7 +159,7 @@ void RenderBlockEditDialog()
|
||||
// Editable flow input name
|
||||
ImGui::PushItemWidth(150.0f);
|
||||
static std::map<int, std::string> flowInputNameBuffers;
|
||||
int pinId = pin.ID.Get();
|
||||
const int pinId = ToRuntimeId(pin.ID);
|
||||
if (flowInputNameBuffers.find(pinId) == flowInputNameBuffers.end())
|
||||
{
|
||||
flowInputNameBuffers[pinId] = pin.Name;
|
||||
@ -250,7 +250,7 @@ void RenderBlockEditDialog()
|
||||
// Editable parameter name
|
||||
ImGui::PushItemWidth(150.0f);
|
||||
static std::map<int, std::string> nameBuffers; // Per-pin name buffers
|
||||
int pinId = pin.ID.Get();
|
||||
const int pinId = ToRuntimeId(pin.ID);
|
||||
if (nameBuffers.find(pinId) == nameBuffers.end())
|
||||
{
|
||||
nameBuffers[pinId] = pin.Name;
|
||||
@ -411,7 +411,7 @@ void RenderBlockEditDialog()
|
||||
case PinType::String:
|
||||
{
|
||||
static std::map<int, std::string> stringBuffers; // Per-pin buffers
|
||||
int pinId = pin.ID.Get();
|
||||
const int pinId = ToRuntimeId(pin.ID);
|
||||
if (stringBuffers.find(pinId) == stringBuffers.end())
|
||||
{
|
||||
stringBuffers[pinId] = paramNode->StringValue;
|
||||
@ -455,7 +455,7 @@ void RenderBlockEditDialog()
|
||||
ImGui::PushItemWidth(150.0f);
|
||||
|
||||
// Get or create default value
|
||||
int pinId = pin.ID.Get();
|
||||
const int pinId = ToRuntimeId(pin.ID);
|
||||
auto& paramValues = s_EditingNode->UnconnectedParamValues;
|
||||
if (paramValues.find(pinId) == paramValues.end())
|
||||
{
|
||||
@ -586,7 +586,7 @@ void RenderBlockEditDialog()
|
||||
// Editable flow output name
|
||||
ImGui::PushItemWidth(150.0f);
|
||||
static std::map<int, std::string> flowOutputNameBuffers;
|
||||
int pinId = pin.ID.Get();
|
||||
const int pinId = ToRuntimeId(pin.ID);
|
||||
if (flowOutputNameBuffers.find(pinId) == flowOutputNameBuffers.end())
|
||||
{
|
||||
flowOutputNameBuffers[pinId] = pin.Name;
|
||||
@ -677,7 +677,7 @@ void RenderBlockEditDialog()
|
||||
// Editable parameter name
|
||||
ImGui::PushItemWidth(150.0f);
|
||||
static std::map<int, std::string> outputNameBuffers; // Per-pin name buffers for outputs
|
||||
int pinId = pin.ID.Get();
|
||||
const int pinId = ToRuntimeId(pin.ID);
|
||||
if (outputNameBuffers.find(pinId) == outputNameBuffers.end())
|
||||
{
|
||||
outputNameBuffers[pinId] = pin.Name;
|
||||
@ -708,7 +708,7 @@ void RenderBlockEditDialog()
|
||||
// Editable parameter type (combo) for outputs
|
||||
ImGui::PushItemWidth(100.0f);
|
||||
static std::map<int, int> outputTypeIndices; // Per-pin type index buffers for outputs
|
||||
int outputPinId = pin.ID.Get();
|
||||
const int outputPinId = ToRuntimeId(pin.ID);
|
||||
|
||||
const char* outputTypeItems[] = { "Bool", "Int", "Float", "String", "Object", "Function", "Delegate" };
|
||||
PinType outputTypeValues[] = { PinType::Bool, PinType::Int, PinType::Float, PinType::String, PinType::Object, PinType::Function, PinType::Delegate };
|
||||
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
// Forward declarations
|
||||
class Node;
|
||||
struct Node;
|
||||
class App;
|
||||
|
||||
void OpenBlockEditDialog(Node* node, App* app);
|
||||
@ -1,9 +1,9 @@
|
||||
#define IMGUI_DEFINE_MATH_OPERATORS
|
||||
#include <crude_json.h>
|
||||
#include "group_block.h"
|
||||
#include "../app.h"
|
||||
#include "block.h"
|
||||
#include "../utilities/node_renderer_base.h"
|
||||
#include "../../crude_json.h"
|
||||
#include "NodeEx.h"
|
||||
#include "constants.h"
|
||||
#include "../Logging.h"
|
||||
@ -317,7 +317,7 @@ void GroupBlock::RenderExpanded(Node& node, App* app, Pin* newLinkPin)
|
||||
static std::map<int, ImVec2> resizeStartSize;
|
||||
static std::map<int, ImVec2> resizeStartMouseCanvas;
|
||||
|
||||
int nodeId = node.ID.Get();
|
||||
const int nodeId = ToRuntimeId(node.ID);
|
||||
|
||||
if (ImGui::IsItemActive())
|
||||
{
|
||||
@ -377,12 +377,12 @@ void GroupBlock::RebuildPins(Node& node, App* app)
|
||||
for (const auto& input : node.Inputs)
|
||||
{
|
||||
if (input.UUID.IsValid())
|
||||
oldPinUuids[input.ID.Get()] = input.UUID;
|
||||
oldPinUuids[ToRuntimeId(input.ID)] = input.UUID;
|
||||
}
|
||||
for (const auto& output : node.Outputs)
|
||||
{
|
||||
if (output.UUID.IsValid())
|
||||
oldPinUuids[output.ID.Get()] = output.UUID;
|
||||
oldPinUuids[ToRuntimeId(output.ID)] = output.UUID;
|
||||
}
|
||||
|
||||
LOG_DEBUG("[GroupBlock::RebuildPins] Preserved {} pin UUIDs before rebuild", oldPinUuids.size());
|
||||
@ -399,7 +399,7 @@ void GroupBlock::RebuildPins(Node& node, App* app)
|
||||
// Restore or generate UUIDs for pins
|
||||
for (auto& input : node.Inputs)
|
||||
{
|
||||
int pinId = input.ID.Get();
|
||||
const int pinId = ToRuntimeId(input.ID);
|
||||
|
||||
// Try to restore old UUID if this pin ID existed before
|
||||
auto it = oldPinUuids.find(pinId);
|
||||
@ -425,7 +425,7 @@ void GroupBlock::RebuildPins(Node& node, App* app)
|
||||
|
||||
for (auto& output : node.Outputs)
|
||||
{
|
||||
int pinId = output.ID.Get();
|
||||
const int pinId = ToRuntimeId(output.ID);
|
||||
|
||||
// Try to restore old UUID if this pin ID existed before
|
||||
auto it = oldPinUuids.find(pinId);
|
||||
@ -863,7 +863,7 @@ void GroupBlock::LoadState(Node& node, const crude_json::value& nodeData, Contai
|
||||
RebuildPins(node, app);
|
||||
|
||||
LOG_DEBUG("[GroupBlock::LoadState] Rebuilt node {} with {} inputs, {} outputs",
|
||||
node.ID.Get(), node.Inputs.size(), node.Outputs.size());
|
||||
ToRuntimeId(node.ID), node.Inputs.size(), node.Outputs.size());
|
||||
|
||||
// Call base class to load parameter values (after rebuilding structure)
|
||||
ParameterizedBlock::LoadState(node, nodeData, container, app);
|
||||
@ -29,19 +29,19 @@ class GroupBlock : public ParameterizedBlock
|
||||
public:
|
||||
GroupBlock(int id) : ParameterizedBlock(id, "Group")
|
||||
{
|
||||
m_TypeName = "Group";
|
||||
SetTypeName("Group");
|
||||
m_Type = NodeType::Group;
|
||||
m_Color = ImColor(200, 150, 200); // Purple-ish color for groups
|
||||
m_bFlags = static_cast<NH_BEHAVIOR_FLAGS>(
|
||||
SetFlags(static_cast<NH_BEHAVIOR_FLAGS>(
|
||||
NHBEHAVIOR_SCRIPT | NHBEHAVIOR_VARIABLEINPUTS | NHBEHAVIOR_VARIABLEOUTPUTS |
|
||||
NHBEHAVIOR_VARIABLEPARAMETERINPUTS | NHBEHAVIOR_VARIABLEPARAMETEROUTPUTS);
|
||||
NHBEHAVIOR_VARIABLEPARAMETERINPUTS | NHBEHAVIOR_VARIABLEPARAMETEROUTPUTS));
|
||||
m_DisplayMode = GroupDisplayMode::Expanded; // Default to expanded
|
||||
m_CollapsedSize = ImVec2(150.0f, 80.0f); // Default collapsed size
|
||||
}
|
||||
|
||||
void Build(Node& node, App* app) override;
|
||||
int Run(Node& node, App* app) override;
|
||||
const char* GetBlockType() const override { return "Group"; }
|
||||
NH_CSTRING GetBlockType() const override { return "Group"; }
|
||||
|
||||
// Rendering (uses base class rendering like any other block)
|
||||
void Render(Node& node, App* app, Pin* newLinkPin) override;
|
||||
@ -1,11 +1,10 @@
|
||||
#include <crude_json.h>
|
||||
|
||||
#include "log_block.h"
|
||||
#include "../app.h"
|
||||
#include "../../crude_json.h"
|
||||
#include "../Logging.h"
|
||||
#include <fstream>
|
||||
#include <ctime>
|
||||
#include <sstream>
|
||||
#include <map>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <direct.h>
|
||||
@ -14,17 +14,17 @@ class LogBlock : public ParameterizedBlock
|
||||
public:
|
||||
LogBlock(int id) : ParameterizedBlock(id, "Log")
|
||||
{
|
||||
m_TypeName = "Log";
|
||||
SetTypeName("Log");
|
||||
m_Type = NodeType::Blueprint;
|
||||
m_Color = ImColor(255, 200, 100);
|
||||
m_bFlags = static_cast<NH_BEHAVIOR_FLAGS>(
|
||||
SetFlags(static_cast<NH_BEHAVIOR_FLAGS>(
|
||||
NHBEHAVIOR_SCRIPT |
|
||||
NHBEHAVIOR_VARIABLEINPUTS);
|
||||
NHBEHAVIOR_VARIABLEINPUTS));
|
||||
}
|
||||
|
||||
void Build(Node& node, App* app) override;
|
||||
int Run(Node& node, App* app) override;
|
||||
const char* GetBlockType() const override { return "Log"; }
|
||||
NH_CSTRING GetBlockType() const override { return "Log"; }
|
||||
|
||||
// State save/load to persist variable parameters
|
||||
void SaveState(Node& node, crude_json::value& nodeData, const Container* container, App* app) override;
|
||||
@ -56,7 +56,7 @@ private:
|
||||
|
||||
// Log settings
|
||||
template <typename... Args>
|
||||
void LogWithConfiguredLevel(const char* fmt, Args&&... args) const
|
||||
void LogWithConfiguredLevel(NH_CSTRING fmt, Args&&... args) const
|
||||
{
|
||||
if (m_LogLevel == spdlog::level::off || !g_logger)
|
||||
return;
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
#include "../app.h"
|
||||
#include "../Logging.h"
|
||||
#include "../../crude_json.h"
|
||||
#include <crude_json.h>
|
||||
#include <imgui.h>
|
||||
#include <map>
|
||||
#include <string>
|
||||
@ -32,7 +32,7 @@ LogicTestBlock::LogicTestBlock(int id)
|
||||
, m_FlowOutputIds({-1, -1})
|
||||
, m_ValueParamIds({-1, -1})
|
||||
{
|
||||
m_TypeName = "Logic.Test";
|
||||
SetTypeName("Logic.Test");
|
||||
m_Type = NodeType::Blueprint;
|
||||
m_Color = ImColor(230, 180, 95);
|
||||
}
|
||||
@ -130,7 +130,7 @@ int LogicTestBlock::Run(Node& node, App* app)
|
||||
|
||||
if (!valuePins[0] || !valuePins[1])
|
||||
{
|
||||
LOG_WARN("[Logic.Test] Missing parameter inputs on node {}", node.ID.Get());
|
||||
LOG_WARN("[Logic.Test] Missing parameter inputs on node {}", ToRuntimeId(node.ID));
|
||||
ActivateOutput(0, false);
|
||||
ActivateOutput(1, false);
|
||||
return E_OK;
|
||||
@ -171,7 +171,7 @@ int LogicTestBlock::Run(Node& node, App* app)
|
||||
}
|
||||
default:
|
||||
{
|
||||
LOG_WARN("[Logic.Test] Unsupported parameter type on node {}", node.ID.Get());
|
||||
LOG_WARN("[Logic.Test] Unsupported parameter type on node {}", ToRuntimeId(node.ID));
|
||||
comparisonResult = false;
|
||||
break;
|
||||
}
|
||||
@ -180,7 +180,7 @@ int LogicTestBlock::Run(Node& node, App* app)
|
||||
ActivateOutput(0, comparisonResult);
|
||||
ActivateOutput(1, !comparisonResult);
|
||||
|
||||
LOG_DEBUG("[Logic.Test] Node {} result={} (operator={})", node.ID.Get(), comparisonResult ? "true" : "false", ToString(m_Operator));
|
||||
LOG_DEBUG("[Logic.Test] Node {} result={} (operator={})", ToRuntimeId(node.ID), comparisonResult ? "true" : "false", ToString(m_Operator));
|
||||
|
||||
return E_OK;
|
||||
}
|
||||
@ -230,7 +230,7 @@ void LogicTestBlock::RebuildPins(Node& node, App* app)
|
||||
std::map<int, Uuid64> oldPinUuids;
|
||||
for (const auto& input : node.Inputs)
|
||||
{
|
||||
int pinId = input.ID.Get();
|
||||
const int pinId = ToRuntimeId(input.ID);
|
||||
if (input.UUID.IsValid())
|
||||
{
|
||||
oldPinUuids[pinId] = input.UUID;
|
||||
@ -240,7 +240,7 @@ void LogicTestBlock::RebuildPins(Node& node, App* app)
|
||||
{
|
||||
if (output.UUID.IsValid())
|
||||
{
|
||||
oldPinUuids[output.ID.Get()] = output.UUID;
|
||||
oldPinUuids[ToRuntimeId(output.ID)] = output.UUID;
|
||||
}
|
||||
}
|
||||
|
||||
@ -255,7 +255,7 @@ void LogicTestBlock::RebuildPins(Node& node, App* app)
|
||||
|
||||
for (auto& input : node.Inputs)
|
||||
{
|
||||
int pinId = input.ID.Get();
|
||||
const int pinId = ToRuntimeId(input.ID);
|
||||
auto it = oldPinUuids.find(pinId);
|
||||
if (it != oldPinUuids.end())
|
||||
{
|
||||
@ -273,7 +273,7 @@ void LogicTestBlock::RebuildPins(Node& node, App* app)
|
||||
|
||||
for (auto& output : node.Outputs)
|
||||
{
|
||||
int pinId = output.ID.Get();
|
||||
const int pinId = ToRuntimeId(output.ID);
|
||||
auto it = oldPinUuids.find(pinId);
|
||||
if (it != oldPinUuids.end())
|
||||
{
|
||||
@ -328,7 +328,7 @@ void LogicTestBlock::LoadState(Node& node, const crude_json::value& nodeData, Co
|
||||
|
||||
// If IDs were not saved (backward compatibility), capture current IDs from node
|
||||
if (m_FlowInputId < 0 && !node.Inputs.empty())
|
||||
m_FlowInputId = node.Inputs.front().ID.Get();
|
||||
m_FlowInputId = ToRuntimeId(node.Inputs.front().ID);
|
||||
|
||||
int paramCounter = 0;
|
||||
for (const auto& pin : node.Inputs)
|
||||
@ -338,7 +338,7 @@ void LogicTestBlock::LoadState(Node& node, const crude_json::value& nodeData, Co
|
||||
|
||||
int valueIndex = paramCounter;
|
||||
if (valueIndex < 2 && m_ValueParamIds[valueIndex] < 0)
|
||||
m_ValueParamIds[valueIndex] = pin.ID.Get();
|
||||
m_ValueParamIds[valueIndex] = ToRuntimeId(pin.ID);
|
||||
|
||||
++paramCounter;
|
||||
}
|
||||
@ -350,7 +350,7 @@ void LogicTestBlock::LoadState(Node& node, const crude_json::value& nodeData, Co
|
||||
continue;
|
||||
if (flowOutCounter < 2 && m_FlowOutputIds[flowOutCounter] < 0)
|
||||
{
|
||||
m_FlowOutputIds[flowOutCounter] = pin.ID.Get();
|
||||
m_FlowOutputIds[flowOutCounter] = ToRuntimeId(pin.ID);
|
||||
}
|
||||
++flowOutCounter;
|
||||
}
|
||||
@ -24,7 +24,7 @@ public:
|
||||
|
||||
void Build(Node& node, App* app) override;
|
||||
int Run(Node& node, App* app) override;
|
||||
const char* GetBlockType() const override { return "Logic.Test"; }
|
||||
NH_CSTRING GetBlockType() const override { return "Logic.Test"; }
|
||||
void SaveState(Node& node, crude_json::value& nodeData, const Container* container, App* app) override;
|
||||
void LoadState(Node& node, const crude_json::value& nodeData, Container* container, App* app) override;
|
||||
void OnMenu(Node& node, App* app) override;
|
||||
@ -9,14 +9,14 @@ class AddBlock : public ParameterizedBlock
|
||||
public:
|
||||
AddBlock(int id) : ParameterizedBlock(id, "Add")
|
||||
{
|
||||
m_TypeName = "Math.Add";
|
||||
SetTypeName("Math.Add");
|
||||
m_Type = NodeType::Blueprint;
|
||||
m_Color = ImColor(128, 195, 248);
|
||||
}
|
||||
|
||||
void Build(Node& node, App* app) override;
|
||||
int Run(Node& node, App* app) override;
|
||||
const char* GetBlockType() const override { return "Math.Add"; }
|
||||
NH_CSTRING GetBlockType() const override { return "Math.Add"; }
|
||||
};
|
||||
|
||||
class MultiplyBlock : public ParameterizedBlock
|
||||
@ -24,14 +24,14 @@ class MultiplyBlock : public ParameterizedBlock
|
||||
public:
|
||||
MultiplyBlock(int id) : ParameterizedBlock(id, "Multiply")
|
||||
{
|
||||
m_TypeName = "Math.Multiply";
|
||||
SetTypeName("Math.Multiply");
|
||||
m_Type = NodeType::Blueprint;
|
||||
m_Color = ImColor(128, 195, 248);
|
||||
}
|
||||
|
||||
void Build(Node& node, App* app) override;
|
||||
int Run(Node& node, App* app) override;
|
||||
const char* GetBlockType() const override { return "Math.Multiply"; }
|
||||
NH_CSTRING GetBlockType() const override { return "Math.Multiply"; }
|
||||
};
|
||||
|
||||
class CompareBlock : public ParameterizedBlock
|
||||
@ -39,13 +39,13 @@ class CompareBlock : public ParameterizedBlock
|
||||
public:
|
||||
CompareBlock(int id) : ParameterizedBlock(id, "Compare")
|
||||
{
|
||||
m_TypeName = "Math.Compare";
|
||||
SetTypeName("Math.Compare");
|
||||
m_Type = NodeType::Blueprint;
|
||||
m_Color = ImColor(128, 195, 248);
|
||||
}
|
||||
|
||||
void Build(Node& node, App* app) override;
|
||||
int Run(Node& node, App* app) override;
|
||||
const char* GetBlockType() const override { return "Math.Compare"; }
|
||||
NH_CSTRING GetBlockType() const override { return "Math.Compare"; }
|
||||
};
|
||||
|
||||
@ -1,10 +1,13 @@
|
||||
#define IMGUI_DEFINE_MATH_OPERATORS
|
||||
#include <crude_json.h>
|
||||
|
||||
#include "../all.h"
|
||||
|
||||
#include "parameter_node.h"
|
||||
#include "../app.h"
|
||||
#include "block.h" // For BlockStyle constants (legacy)
|
||||
#include "block.h"
|
||||
#include "../utilities/node_renderer_base.h"
|
||||
#include "../containers/container.h"
|
||||
#include "../../crude_json.h"
|
||||
#include "NodeEx.h"
|
||||
#include "constants.h"
|
||||
#include <imgui_internal.h>
|
||||
@ -251,7 +254,7 @@ int ParameterNode::RunInternal(Node& node, App* app, int depth)
|
||||
{
|
||||
// Source doesn't exist - orphaned shortcut, clear reference
|
||||
printf("[RUN] Parameter node %d: Source node %d not found, clearing shortcut reference\n",
|
||||
node.ID.Get(), m_SourceID);
|
||||
ToRuntimeId(node.ID), m_SourceID);
|
||||
m_SourceID = 0;
|
||||
m_IsSource = false;
|
||||
}
|
||||
@ -333,7 +336,7 @@ int ParameterNode::RunInternal(Node& node, App* app, int depth)
|
||||
{
|
||||
// Source is a block output - read value from block's output parameter
|
||||
// Block outputs store their values in UnconnectedParamValues
|
||||
int sourcePinId = sourcePin->ID.Get();
|
||||
const int sourcePinId = ToRuntimeId(sourcePin->ID);
|
||||
auto& paramValues = sourceNode->UnconnectedParamValues;
|
||||
|
||||
if (paramValues.find(sourcePinId) != paramValues.end())
|
||||
@ -998,10 +1001,6 @@ void ParameterNode::OnMenu(Node& node, App* app)
|
||||
if (ImGui::MenuItem("Run (R)"))
|
||||
{
|
||||
int result = Run(node, app);
|
||||
printf("Parameter '%s' (ID: %d) Run() returned: %d\n",
|
||||
node.Name.c_str(), node.ID.Get(), result);
|
||||
ax::NodeEditor::AddInAppLog("Parameter '%s' (ID: %d) Run() returned: %d\n",
|
||||
node.Name.c_str(), node.ID.Get(), result);
|
||||
}
|
||||
|
||||
// Source/Shortcut management
|
||||
@ -1125,8 +1124,6 @@ void ParameterNode::LoadState(Node& node, const crude_json::value& nodeData, Con
|
||||
else
|
||||
{
|
||||
// Source doesn't exist - orphaned shortcut, clear reference
|
||||
printf("[LOAD] Parameter node %d: Source node %d not found, clearing shortcut reference\n",
|
||||
node.ID.Get(), sourceId);
|
||||
m_SourceID = 0;
|
||||
m_IsSource = false;
|
||||
}
|
||||
@ -1198,14 +1195,14 @@ Node* ParameterNode::CreateShortcut(Node& sourceNode, App* app)
|
||||
ed::SetNodePosition(shortcutNode->ID, shortcutPos);
|
||||
|
||||
printf("[SHORTCUT] Created shortcut node %d for source %d at (%.1f, %.1f)\n",
|
||||
shortcutNode->ID.Get(), m_ID, shortcutPos.x, shortcutPos.y);
|
||||
ToRuntimeId(shortcutNode->ID), m_ID, shortcutPos.x, shortcutPos.y);
|
||||
|
||||
return shortcutNode;
|
||||
}
|
||||
|
||||
ParameterNode* ParameterRegistry::CreateParameter(PinType type, int id, const char* name)
|
||||
ParameterNode* ParameterRegistry::CreateParameter(PinType type, int id, NH_CSTRING name)
|
||||
{
|
||||
const char* defaultName = nullptr;
|
||||
NH_CSTRING defaultName = nullptr;
|
||||
switch (type)
|
||||
{
|
||||
case PinType::Bool: defaultName = "Bool"; break;
|
||||
@ -1,6 +1,8 @@
|
||||
#pragma once
|
||||
#include "../commons.h"
|
||||
#include "../types.h"
|
||||
#include "../utilities/node_renderer_base.h"
|
||||
#include "../core/Object.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@ -20,12 +22,11 @@ enum class ParameterDisplayMode
|
||||
};
|
||||
|
||||
// Base parameter node class
|
||||
class ParameterNode : public ax::NodeRendering::NodeRendererBase
|
||||
class ParameterNode : public NH_Object, public ax::NodeRendering::NodeRendererBase
|
||||
{
|
||||
public:
|
||||
ParameterNode(int id, const char* name, PinType type)
|
||||
: m_ID(id)
|
||||
, m_Name(name)
|
||||
ParameterNode(int id, NH_CSTRING name, PinType type)
|
||||
: NH_Object(id, name)
|
||||
, m_Type(type)
|
||||
, m_DisplayMode(ParameterDisplayMode::NameAndValue)
|
||||
, m_IsSource(false)
|
||||
@ -37,9 +38,9 @@ public:
|
||||
virtual ~ParameterNode() = default;
|
||||
|
||||
// Core properties
|
||||
int GetID() const { return m_ID; }
|
||||
const char* GetName() const { return m_Name.c_str(); }
|
||||
void SetName(const char* name) { m_Name = name; }
|
||||
int GetID() const { return NH_Object::GetID(); }
|
||||
NH_CSTRING GetName() const { return NH_Object::GetName(); }
|
||||
void SetName(NH_CSTRING name) { NH_Object::SetName(name); }
|
||||
PinType GetType() const { return m_Type; }
|
||||
void SetType(PinType type) { m_Type = type; InitializeDefaultValue(); }
|
||||
|
||||
@ -113,8 +114,6 @@ protected:
|
||||
void RenderMinimal(Node& node, App* app, Pin* newLinkPin);
|
||||
void RenderMinimalLinks(Node& node, App* app, Pin* newLinkPin);
|
||||
|
||||
int m_ID;
|
||||
std::string m_Name;
|
||||
PinType m_Type;
|
||||
ParameterDisplayMode m_DisplayMode;
|
||||
|
||||
@ -141,7 +140,7 @@ public:
|
||||
return instance;
|
||||
}
|
||||
|
||||
ParameterNode* CreateParameter(PinType type, int id, const char* name = nullptr);
|
||||
ParameterNode* CreateParameter(PinType type, int id, NH_CSTRING name = nullptr);
|
||||
|
||||
private:
|
||||
ParameterRegistry() = default;
|
||||
@ -3,7 +3,7 @@
|
||||
#include "../app.h"
|
||||
#include "../utilities/node_renderer_base.h"
|
||||
#include "NodeEx.h"
|
||||
#include "../../crude_json.h"
|
||||
#include <crude_json.h>
|
||||
#include <imgui.h>
|
||||
#include <imgui_node_editor.h>
|
||||
|
||||
@ -227,7 +227,7 @@ int ParameterOperationBlock::Run(Node& node, App* app)
|
||||
void ParameterOperationBlock::Render(Node& node, App* app, Pin* newLinkPin)
|
||||
{
|
||||
// Check if node is currently running (for red border visualization)
|
||||
float currentTime = ImGui::GetTime();
|
||||
double currentTime = (double)ImGui::GetTime();
|
||||
bool isRunning = false;
|
||||
auto runningIt = app->m_RunningNodes.find(node.ID);
|
||||
if (runningIt != app->m_RunningNodes.end())
|
||||
@ -47,10 +47,10 @@ class ParameterOperationBlock : public ParameterizedBlock
|
||||
public:
|
||||
ParameterOperationBlock(int id) : ParameterizedBlock(id, "ParamOp")
|
||||
{
|
||||
m_TypeName = "ParamOp";
|
||||
SetTypeName("ParamOp");
|
||||
m_Type = NodeType::Blueprint;
|
||||
m_Color = ImColor(180, 200, 180); // Light green
|
||||
m_bFlags = static_cast<NH_BEHAVIOR_FLAGS>(NHBEHAVIOR_SCRIPT);
|
||||
SetFlags(static_cast<NH_BEHAVIOR_FLAGS>(NHBEHAVIOR_SCRIPT));
|
||||
|
||||
// Default types
|
||||
m_InputAType = PinType::Int;
|
||||
@ -62,7 +62,7 @@ public:
|
||||
void Build(Node& node, App* app) override;
|
||||
int Run(Node& node, App* app) override;
|
||||
void Render(Node& node, App* app, Pin* newLinkPin) override;
|
||||
const char* GetBlockType() const override { return "ParamOp"; }
|
||||
NH_CSTRING GetBlockType() const override { return "ParamOp"; }
|
||||
|
||||
void OnMenu(Node& node, App* app) override;
|
||||
|
||||
@ -9,13 +9,13 @@ class StartBlock : public ParameterizedBlock
|
||||
public:
|
||||
StartBlock(int id) : ParameterizedBlock(id, "Start")
|
||||
{
|
||||
m_TypeName = "Start";
|
||||
SetTypeName("Start");
|
||||
m_Type = NodeType::Blueprint;
|
||||
m_Color = ImColor(100, 255, 100);
|
||||
}
|
||||
|
||||
void Build(Node& node, App* app) override;
|
||||
int Run(Node& node, App* app) override;
|
||||
const char* GetBlockType() const override { return "Start"; }
|
||||
NH_CSTRING GetBlockType() const override { return "Start"; }
|
||||
};
|
||||
|
||||
36
applications/nodehub/commons.h
Normal file
@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <functional>
|
||||
|
||||
#include "./enums.h"
|
||||
#include "./utilities/uuid_generator.h"
|
||||
|
||||
|
||||
#ifndef NH_CSTRING
|
||||
#define NH_CSTRING const char*
|
||||
#endif
|
||||
|
||||
typedef char* NH_STRING;
|
||||
typedef char NH_CHAR;
|
||||
typedef unsigned short* NH_USTRING;
|
||||
typedef unsigned short NH_UCHAR;
|
||||
|
||||
typedef int NH_BOOL;
|
||||
typedef unsigned char NH_BYTE;
|
||||
typedef unsigned int NH_DWORD;
|
||||
typedef unsigned short NH_WORD;
|
||||
|
||||
typedef int NH_ERROR;
|
||||
typedef int NH_PARAMETER_TYPE;
|
||||
typedef int NH_OPERATION_TYPE;
|
||||
typedef int NH_MESSAGE_TYPE;
|
||||
typedef int NH_ATTRIBUTE_TYPE;
|
||||
typedef int NH_ATTRIBUTE_CATEGORY;
|
||||
|
||||
typedef Uuid64 NH_GUID;
|
||||
typedef unsigned int NH_ID;
|
||||
typedef unsigned int NH_CLASS_ID;
|
||||
8
applications/nodehub/config.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef CONFIG_H
|
||||
#define CONFIG_H
|
||||
|
||||
#ifndef NH_GUI
|
||||
#define NH_GUI
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@ -181,7 +181,7 @@ void Container::RemoveNode(Node* node)
|
||||
|
||||
int nodeId = -1;
|
||||
try {
|
||||
nodeId = node->ID.Get();
|
||||
nodeId = ToRuntimeId(node->ID);
|
||||
} catch (...) {
|
||||
printf("[DELETE] Container::RemoveNode: Cannot access node ID (corrupted pointer %p)\n", (void*)node);
|
||||
fflush(stdout);
|
||||
@ -216,10 +216,12 @@ void Container::AddLink(Link* link)
|
||||
return;
|
||||
}
|
||||
|
||||
const int linkId = ToRuntimeId(link->ID);
|
||||
|
||||
if (ContainsLink(link->ID))
|
||||
{
|
||||
printf("[LINK_DRAG] Container::AddLink: Link ID %lld already exists in container, REJECTING!\n",
|
||||
(long long)link->ID.Get());
|
||||
static_cast<long long>(linkId));
|
||||
printf("[LINK_DRAG] Container::AddLink: Current link IDs in container: ");
|
||||
for (auto id : m_LinkIds)
|
||||
printf("%lld ", (long long)id.Get());
|
||||
@ -228,7 +230,7 @@ void Container::AddLink(Link* link)
|
||||
return;
|
||||
}
|
||||
|
||||
printf("[LINK_DRAG] Container::AddLink: Adding link ID=%lld to container\n", (long long)link->ID.Get());
|
||||
printf("[LINK_DRAG] Container::AddLink: Adding link ID=%lld to container\n", static_cast<long long>(linkId));
|
||||
fflush(stdout);
|
||||
|
||||
// Store ID - actual link is stored in RootContainer::m_Links
|
||||
@ -112,9 +112,6 @@ Pin* RootContainer::FindPin(ed::PinId id, App* app)
|
||||
// Ensure pin's Node pointer is correct (should be set by BuildNode after AddNode)
|
||||
if (pin.Node != &node)
|
||||
{
|
||||
printf("[FindPin] FIXING pin %d - Node pointer incorrect (was %p, setting to %p)\n",
|
||||
id.Get(), (void*)pin.Node, (void*)&node);
|
||||
fflush(stdout);
|
||||
pin.Node = &node; // Fix to point to actual node in container
|
||||
}
|
||||
return &pin;
|
||||
@ -7,7 +7,7 @@
|
||||
namespace ed = ax::NodeEditor;
|
||||
|
||||
class App;
|
||||
class Pin;
|
||||
struct Pin;
|
||||
|
||||
/**
|
||||
* RootContainer - Owns actual Node and Link objects for its graph
|
||||
1
applications/nodehub/core/BaseManager.cpp
Normal file
@ -0,0 +1 @@
|
||||
#include "BaseManager.h"
|
||||
33
applications/nodehub/core/BaseManager.h
Normal file
@ -0,0 +1,33 @@
|
||||
#ifndef NH_BASE_MANAGER_H
|
||||
#define NH_BASE_MANAGER_H
|
||||
|
||||
#include "../commons.h"
|
||||
#include "../types.h"
|
||||
|
||||
class NH_Context;
|
||||
|
||||
class NH_BaseManager {
|
||||
public:
|
||||
NH_BaseManager() {}
|
||||
virtual ~NH_BaseManager() = default;
|
||||
|
||||
virtual NH_ERROR OnInit() { return E_OK; }
|
||||
|
||||
NH_Context* GetContext() { return m_Context; }
|
||||
void SetContext(NH_Context* context) { m_Context = context; }
|
||||
|
||||
Uuid64 GetGuid() { return m_Guid; }
|
||||
std::string GetName() { return m_Name; }
|
||||
|
||||
void SetName(std::string name) { m_Name = name; }
|
||||
void SetGuid(Uuid64 guid) { m_Guid = guid; }
|
||||
|
||||
protected:
|
||||
NH_Context* m_Context;
|
||||
Uuid64 m_Guid;
|
||||
std::string m_Name;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
38
applications/nodehub/core/Context.cpp
Normal file
@ -0,0 +1,38 @@
|
||||
#include "Context.h"
|
||||
#include "../logging.h"
|
||||
#include "ParameterManager.h"
|
||||
#include "ParameterIn.h"
|
||||
#include "ParameterOut.h"
|
||||
#include "../utilities/uuid_generator.h"
|
||||
|
||||
NH_Context::NH_Context() : m_ParameterManager(nullptr), m_App(nullptr) {}
|
||||
|
||||
NH_Context::~NH_Context()
|
||||
{
|
||||
delete m_ParameterManager;
|
||||
}
|
||||
|
||||
NH_ERROR NH_Context::init(App *app)
|
||||
{
|
||||
m_App = app;
|
||||
m_ParameterManager = new NH_ParameterManager(this);
|
||||
m_ParameterManager->OnInit();
|
||||
LOG_INFO("Context initialized");
|
||||
return E_OK;
|
||||
}
|
||||
|
||||
NH_ParameterIn* NH_Context::CreateParameterIn(NH_CSTRING name, const Uuid64& guid)
|
||||
{
|
||||
// A proper implementation would use an object manager to handle IDs and memory.
|
||||
auto* param = new NH_ParameterIn(0, name);
|
||||
// TODO: Set the parameter type based on the GUID by looking it up in the ParameterManager.
|
||||
return param;
|
||||
}
|
||||
|
||||
NH_ParameterOut* NH_Context::CreateParameterOut(NH_CSTRING name, const Uuid64& guid)
|
||||
{
|
||||
// A proper implementation would use an object manager.
|
||||
auto* param = new NH_ParameterOut(0, name);
|
||||
// TODO: Set the parameter type based on the GUID.
|
||||
return param;
|
||||
}
|
||||
41
applications/nodehub/core/Context.h
Normal file
@ -0,0 +1,41 @@
|
||||
#ifndef NH_CONTEXT_H
|
||||
#define NH_CONTEXT_H
|
||||
|
||||
#include "../commons.h"
|
||||
#include "../types.h"
|
||||
|
||||
class App;
|
||||
class NH_ParameterManager;
|
||||
class NH_ParameterIn;
|
||||
class NH_ParameterOut;
|
||||
struct Uuid64;
|
||||
|
||||
class NH_Context {
|
||||
public:
|
||||
NH_Context();
|
||||
virtual ~NH_Context();
|
||||
|
||||
NH_ParameterManager* GetParameterManager() { return m_ParameterManager; }
|
||||
void SetParameterManager(NH_ParameterManager* parameterManager) { m_ParameterManager = parameterManager; }
|
||||
|
||||
App* GetApp() { return m_App; }
|
||||
void SetApp(App* app) { m_App = app; }
|
||||
|
||||
//-----------------------------------------
|
||||
// Lifecycle
|
||||
//-----------------------------------------
|
||||
NH_ERROR init(App *app);
|
||||
|
||||
// Object Management
|
||||
NH_ParameterIn* CreateParameterIn(NH_CSTRING name, const Uuid64& guid);
|
||||
NH_ParameterOut* CreateParameterOut(NH_CSTRING name, const Uuid64& guid);
|
||||
|
||||
protected:
|
||||
NH_ParameterManager* m_ParameterManager;
|
||||
|
||||
// legacy support
|
||||
App* m_App;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
1
applications/nodehub/core/Object.cpp
Normal file
@ -0,0 +1 @@
|
||||
#include "Object.h"
|
||||
111
applications/nodehub/core/Object.h
Normal file
@ -0,0 +1,111 @@
|
||||
#pragma once
|
||||
|
||||
#include "../commons.h"
|
||||
#include "../utilities/uuid_generator.h"
|
||||
#include <string>
|
||||
|
||||
class App;
|
||||
class Container;
|
||||
namespace crude_json { struct value; }
|
||||
|
||||
class NH_Object
|
||||
{
|
||||
public:
|
||||
NH_Object()
|
||||
: m_ID(0)
|
||||
, m_Name("")
|
||||
, m_TypeName("")
|
||||
, m_Parent(nullptr)
|
||||
, m_BehaviorFlags(NHBEHAVIOR_NONE)
|
||||
, m_ObjectFlags(NH_OBJECT_DYNAMIC)
|
||||
{}
|
||||
|
||||
NH_Object(int id, NH_CSTRING name, NH_CSTRING typeName = nullptr)
|
||||
: NH_Object()
|
||||
{
|
||||
m_ID = id;
|
||||
if (name)
|
||||
m_Name = name;
|
||||
if (typeName)
|
||||
m_TypeName = typeName;
|
||||
}
|
||||
virtual ~NH_Object() = default;
|
||||
|
||||
// Core identification
|
||||
int GetID() const { return m_ID; }
|
||||
void SetID(int id) { m_ID = id; }
|
||||
|
||||
NH_CSTRING GetName() const { return m_Name.c_str(); }
|
||||
const std::string& GetNameString() const { return m_Name; }
|
||||
void SetName(NH_CSTRING name)
|
||||
{
|
||||
m_Name = name ? name : "";
|
||||
}
|
||||
|
||||
NH_CSTRING GetTypeName() const { return m_TypeName.c_str(); }
|
||||
void SetTypeName(NH_CSTRING typeName)
|
||||
{
|
||||
m_TypeName = typeName ? typeName : "";
|
||||
}
|
||||
|
||||
NH_Object* GetParent() const { return m_Parent; }
|
||||
void SetParent(NH_Object* parent) { m_Parent = parent; }
|
||||
|
||||
// Behavior flags (Virtools-style)
|
||||
NH_BEHAVIOR_FLAGS GetBehaviorFlags() const { return m_BehaviorFlags; }
|
||||
void SetBehaviorFlags(NH_BEHAVIOR_FLAGS flags) { m_BehaviorFlags = flags; }
|
||||
void AddBehaviorFlags(NH_BEHAVIOR_FLAGS flags)
|
||||
{
|
||||
m_BehaviorFlags = static_cast<NH_BEHAVIOR_FLAGS>(
|
||||
static_cast<int>(m_BehaviorFlags) | static_cast<int>(flags));
|
||||
}
|
||||
|
||||
void RemoveBehaviorFlags(NH_BEHAVIOR_FLAGS flags)
|
||||
{
|
||||
m_BehaviorFlags = static_cast<NH_BEHAVIOR_FLAGS>(
|
||||
static_cast<int>(m_BehaviorFlags) & ~static_cast<int>(flags));
|
||||
}
|
||||
|
||||
// Object flags (base Virtools object flags)
|
||||
NH_OBJECT_FLAGS GetObjectFlags() const
|
||||
{
|
||||
return static_cast<NH_OBJECT_FLAGS>(m_ObjectFlags);
|
||||
}
|
||||
void SetObjectFlags(NH_OBJECT_FLAGS flags)
|
||||
{
|
||||
m_ObjectFlags = static_cast<NH_DWORD>(flags);
|
||||
}
|
||||
void AddObjectFlags(NH_OBJECT_FLAGS flags)
|
||||
{
|
||||
m_ObjectFlags |= static_cast<NH_DWORD>(flags);
|
||||
}
|
||||
void ClearObjectFlags(NH_OBJECT_FLAGS flags)
|
||||
{
|
||||
m_ObjectFlags &= ~static_cast<NH_DWORD>(flags);
|
||||
}
|
||||
|
||||
// Serialization hooks (mirror block/parameter APIs)
|
||||
virtual void SaveState(crude_json::value& data, const Container* container, App* app) {}
|
||||
virtual void LoadState(const crude_json::value& data, Container* container, App* app) {}
|
||||
|
||||
Uuid64 m_UUID;
|
||||
void SetUUID(Uuid64 uuid) { m_UUID = uuid; }
|
||||
Uuid64 GetUUID() const { return m_UUID; }
|
||||
|
||||
|
||||
NH_STRING GetClassName();
|
||||
// Class Registering
|
||||
static NH_STRING m_ClassName;
|
||||
|
||||
virtual NH_CLASS_ID GetClassID() { return NHCID_PARAMETER; }
|
||||
|
||||
protected:
|
||||
int m_ID;
|
||||
std::string m_Name;
|
||||
std::string m_TypeName;
|
||||
NH_Object* m_Parent;
|
||||
NH_BEHAVIOR_FLAGS m_BehaviorFlags;
|
||||
NH_DWORD m_ObjectFlags;
|
||||
NH_CLASS_ID m_ClassID;
|
||||
|
||||
};
|
||||
68
applications/nodehub/core/Parameter.cpp
Normal file
@ -0,0 +1,68 @@
|
||||
#include "Parameter.h"
|
||||
#include "Context.h"
|
||||
#include "ParameterManager.h"
|
||||
#include <cstring>
|
||||
|
||||
NH_Parameter::NH_Parameter(int id, NH_CSTRING name) : NH_Object(id, name) {
|
||||
m_Owner = nullptr;
|
||||
m_AllocatedSize = 0;
|
||||
m_Buffer = nullptr;
|
||||
m_ParamType = nullptr;
|
||||
}
|
||||
|
||||
NH_Parameter::~NH_Parameter() {
|
||||
if (m_Buffer) {
|
||||
delete[] m_Buffer;
|
||||
m_Buffer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
NH_ERROR NH_Parameter::GetValue(void *buf, NH_BOOL update) {
|
||||
if (!buf || !m_Buffer) return E_FAIL;
|
||||
memcpy(buf, m_Buffer, m_DataSize);
|
||||
return E_OK;
|
||||
}
|
||||
|
||||
NH_ERROR NH_Parameter::SetValue(const void *buf, int size) {
|
||||
if (!buf) return E_FAIL;
|
||||
|
||||
int dataSize = size;
|
||||
if (dataSize == 0 && m_ParamType) {
|
||||
dataSize = m_ParamType->DefaultSize;
|
||||
}
|
||||
|
||||
if (dataSize == 0) return E_FAIL;
|
||||
|
||||
if (m_AllocatedSize < dataSize) {
|
||||
if (m_Buffer) {
|
||||
delete[] m_Buffer;
|
||||
}
|
||||
m_Buffer = new NH_BYTE[dataSize];
|
||||
m_AllocatedSize = dataSize;
|
||||
}
|
||||
|
||||
memcpy(m_Buffer, buf, dataSize);
|
||||
m_DataSize = dataSize;
|
||||
|
||||
return E_OK;
|
||||
}
|
||||
|
||||
NH_ERROR NH_Parameter::CopyValue(NH_Parameter *param, NH_BOOL UpdateParam) {
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
void *NH_Parameter::GetReadDataPtr(NH_BOOL update) {
|
||||
return m_Buffer;
|
||||
}
|
||||
|
||||
void *NH_Parameter::GetWriteDataPtr() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
NH_ERROR NH_Parameter::SetStringValue(NH_STRING Value) {
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
int NH_Parameter::GetStringValue(NH_STRING Value, NH_BOOL update) {
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
59
applications/nodehub/core/Parameter.h
Normal file
@ -0,0 +1,59 @@
|
||||
#ifndef NH_PARAMETER_H
|
||||
#define NH_PARAMETER_H
|
||||
|
||||
#include "../commons.h"
|
||||
#include "../types.h"
|
||||
#include "./Object.h"
|
||||
|
||||
class NH_Parameter : public NH_Object {
|
||||
public:
|
||||
NH_Parameter(int id, NH_CSTRING name);
|
||||
virtual ~NH_Parameter();
|
||||
|
||||
NH_PARAMETER_TYPE GetType();
|
||||
void SetType(NH_PARAMETER_TYPE type);
|
||||
|
||||
NH_CLASS_ID GetParameterClassID();
|
||||
virtual NH_CLASS_ID GetClassID() { return NHCID_PARAMETER; }
|
||||
|
||||
void SetOwner(NH_Object *owner) { m_Owner = owner; }
|
||||
NH_Object *GetOwner() { return m_Owner; }
|
||||
|
||||
NH_ParameterTypeDesc *GetParameterType() { return m_ParamType; }
|
||||
|
||||
// Convertion from / to string
|
||||
virtual NH_ERROR SetStringValue(NH_STRING Value);
|
||||
virtual int GetStringValue(NH_STRING Value, NH_BOOL update = true);
|
||||
|
||||
//--------------------------------------------
|
||||
// Value
|
||||
|
||||
NH_Object *GetValueObject(NH_BOOL update = true);
|
||||
|
||||
virtual NH_ERROR GetValue(void *buf, NH_BOOL update = true);
|
||||
virtual NH_ERROR SetValue(const void *buf, int size = 0);
|
||||
virtual NH_ERROR CopyValue(NH_Parameter *param, NH_BOOL UpdateParam = true);
|
||||
|
||||
NH_BOOL IsCompatibleWith(NH_Parameter *param);
|
||||
//--------------------------------------------
|
||||
// Data pointer
|
||||
int GetDataSize();
|
||||
virtual void *GetReadDataPtr(NH_BOOL update = true);
|
||||
virtual void *GetWriteDataPtr();
|
||||
|
||||
protected:
|
||||
NH_Object *m_Owner;
|
||||
|
||||
union {
|
||||
int m_DataSize;
|
||||
int m_AllocatedSize;
|
||||
};
|
||||
union {
|
||||
NH_BYTE *m_Buffer;
|
||||
NH_DWORD m_Value;
|
||||
};
|
||||
|
||||
NH_ParameterTypeDesc *m_ParamType;
|
||||
};
|
||||
|
||||
#endif
|
||||
81
applications/nodehub/core/ParameterIn.cpp
Normal file
@ -0,0 +1,81 @@
|
||||
#include "./ParameterIn.h"
|
||||
#include "./Context.h"
|
||||
#include "ParameterManager.h"
|
||||
|
||||
NH_ParameterIn::NH_ParameterIn(int id, NH_CSTRING name) : NH_Parameter(id, name) {
|
||||
m_ObjectFlags &= ~NH_PARAMETERIN_SHARED;
|
||||
m_DirectSource = nullptr;
|
||||
}
|
||||
|
||||
NH_Parameter* NH_ParameterIn::GetRealSource() {
|
||||
if (m_ObjectFlags & NH_PARAMETERIN_SHARED) {
|
||||
if (m_SharedSource) return m_SharedSource->GetRealSource();
|
||||
} else {
|
||||
return m_DirectSource;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
NH_Parameter* NH_ParameterIn::GetDirectSource() {
|
||||
if (m_ObjectFlags & NH_PARAMETERIN_SHARED) return nullptr;
|
||||
return m_DirectSource;
|
||||
}
|
||||
|
||||
NH_ERROR NH_ParameterIn::SetDirectSource(NH_Parameter* param) {
|
||||
m_ObjectFlags &= ~NH_PARAMETERIN_SHARED;
|
||||
m_DirectSource = param;
|
||||
return E_OK;
|
||||
}
|
||||
|
||||
NH_ParameterIn* NH_ParameterIn::GetSharedSource() {
|
||||
if (!(m_ObjectFlags & NH_PARAMETERIN_SHARED)) return nullptr;
|
||||
return m_SharedSource;
|
||||
}
|
||||
|
||||
NH_ERROR NH_ParameterIn::ShareSourceWith(NH_ParameterIn* param) {
|
||||
m_ObjectFlags |= NH_PARAMETERIN_SHARED;
|
||||
m_SharedSource = param;
|
||||
return E_OK;
|
||||
}
|
||||
|
||||
NH_ERROR NH_ParameterIn::GetValue(void* buf, NH_BOOL update) {
|
||||
// Stub implementation
|
||||
NH_Parameter* src = GetRealSource();
|
||||
if (!src) return E_FAIL;
|
||||
return src->GetValue(buf, update);
|
||||
}
|
||||
|
||||
void* NH_ParameterIn::GetReadDataPtr(NH_BOOL update) {
|
||||
// Stub implementation
|
||||
NH_Parameter* src = GetRealSource();
|
||||
if (!src) return nullptr;
|
||||
return src->GetReadDataPtr(update);
|
||||
}
|
||||
|
||||
NH_ERROR NH_ParameterIn::SetValue(const void* buf, int size) {
|
||||
// Input parameters are read-only
|
||||
return E_ACCESSDENIED;
|
||||
}
|
||||
|
||||
void* NH_ParameterIn::GetWriteDataPtr() {
|
||||
// Input parameters are read-only
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
NH_ERROR NH_ParameterIn::CopyValue(NH_Parameter* param, NH_BOOL UpdateParam) {
|
||||
NH_Parameter* src = GetRealSource();
|
||||
if (!src || !param) return E_FAIL;
|
||||
return src->CopyValue(param, UpdateParam);
|
||||
}
|
||||
|
||||
NH_ERROR NH_ParameterIn::SetStringValue(NH_STRING Value) {
|
||||
NH_Parameter* src = GetRealSource();
|
||||
if (!src) return E_FAIL;
|
||||
return src->SetStringValue(Value);
|
||||
}
|
||||
|
||||
int NH_ParameterIn::GetStringValue(NH_STRING Value, NH_BOOL update) {
|
||||
NH_Parameter* src = GetRealSource();
|
||||
if (!src) return E_FAIL;
|
||||
return src->GetStringValue(Value, update);
|
||||
}
|
||||
45
applications/nodehub/core/ParameterIn.h
Normal file
@ -0,0 +1,45 @@
|
||||
#ifndef NH_PARAMETER_IN_H
|
||||
#define NH_PARAMETER_IN_H
|
||||
|
||||
#include "./Parameter.h"
|
||||
|
||||
// Forward declaration
|
||||
class NH_ParameterIn;
|
||||
|
||||
class NH_ParameterIn : public NH_Parameter {
|
||||
public:
|
||||
NH_ParameterIn(int id, NH_CSTRING name);
|
||||
virtual ~NH_ParameterIn() = default;
|
||||
|
||||
// Source management
|
||||
NH_Parameter *GetRealSource();
|
||||
|
||||
NH_Parameter *GetDirectSource();
|
||||
NH_ERROR SetDirectSource(NH_Parameter *param);
|
||||
|
||||
NH_ParameterIn *GetSharedSource();
|
||||
NH_ERROR ShareSourceWith(NH_ParameterIn *param);
|
||||
|
||||
// Overridden value accessors
|
||||
virtual NH_ERROR GetValue(void *buf, NH_BOOL update = true) override;
|
||||
virtual void *GetReadDataPtr(NH_BOOL update = true) override;
|
||||
|
||||
// Disable writing
|
||||
virtual NH_ERROR SetValue(const void *buf, int size = 0) override;
|
||||
virtual NH_ERROR CopyValue(NH_Parameter *param, NH_BOOL UpdateParam = true) override;
|
||||
virtual void *GetWriteDataPtr() override;
|
||||
|
||||
// String conversion
|
||||
virtual NH_ERROR SetStringValue(NH_STRING Value) override;
|
||||
virtual int GetStringValue(NH_STRING Value, NH_BOOL update = true) override;
|
||||
|
||||
virtual NH_CLASS_ID GetClassID() override { return NHCID_PARAMETERIN; }
|
||||
|
||||
protected:
|
||||
union {
|
||||
NH_Parameter *m_DirectSource;
|
||||
NH_ParameterIn *m_SharedSource;
|
||||
};
|
||||
};
|
||||
|
||||
#endif // NH_PARAMETER_IN_H
|
||||
64
applications/nodehub/core/ParameterManager.cpp
Normal file
@ -0,0 +1,64 @@
|
||||
#include "ParameterManager.h"
|
||||
#include <string>
|
||||
|
||||
NH_ParameterManager::NH_ParameterManager(NH_Context *context) : NH_BaseManager() {
|
||||
SetContext(context);
|
||||
}
|
||||
|
||||
NH_ERROR NH_ParameterManager::OnInit() {
|
||||
NH_ParameterTypeDesc pdesc;
|
||||
|
||||
// Float
|
||||
pdesc.Guid = NHP_GUID_FLOAT;
|
||||
pdesc.TypeName = "Float";
|
||||
pdesc.DefaultSize = sizeof(float);
|
||||
RegisterParameterType(&pdesc);
|
||||
|
||||
// Int
|
||||
pdesc.Guid = NHP_GUID_INT;
|
||||
pdesc.TypeName = "Int";
|
||||
pdesc.DefaultSize = sizeof(int);
|
||||
RegisterParameterType(&pdesc);
|
||||
|
||||
// Bool
|
||||
pdesc.Guid = NHP_GUID_BOOL;
|
||||
pdesc.TypeName = "Bool";
|
||||
pdesc.DefaultSize = sizeof(bool);
|
||||
RegisterParameterType(&pdesc);
|
||||
|
||||
// String
|
||||
pdesc.Guid = NHP_GUID_STRING;
|
||||
pdesc.TypeName = "String";
|
||||
pdesc.DefaultSize = sizeof(char*);
|
||||
RegisterParameterType(&pdesc);
|
||||
|
||||
// Vector
|
||||
pdesc.Guid = NHP_GUID_VECTOR;
|
||||
pdesc.TypeName = "Vector";
|
||||
pdesc.DefaultSize = sizeof(float) * 3;
|
||||
RegisterParameterType(&pdesc);
|
||||
|
||||
return E_OK;
|
||||
}
|
||||
|
||||
NH_ERROR
|
||||
NH_ParameterManager::RegisterParameterType(NH_ParameterTypeDesc *parameterType) {
|
||||
if (!parameterType)
|
||||
return E_FAIL;
|
||||
|
||||
// Check if GUID is valid
|
||||
if (!parameterType->Guid.IsValid())
|
||||
return E_FAIL;
|
||||
|
||||
// Check if GUID already exists
|
||||
if (m_ParameterGuids.find(parameterType->Guid) != m_ParameterGuids.end()) {
|
||||
return E_OK; // Or an error for duplicate
|
||||
}
|
||||
|
||||
m_ParameterTypes.push_back(*parameterType);
|
||||
int newIndex = m_ParameterTypes.size() - 1;
|
||||
m_ParameterTypes.back().Index = newIndex;
|
||||
m_ParameterGuids[parameterType->Guid] = newIndex;
|
||||
|
||||
return E_OK;
|
||||
}
|
||||
26
applications/nodehub/core/ParameterManager.h
Normal file
@ -0,0 +1,26 @@
|
||||
#ifndef NH_PARAMETER_MANAGER_H
|
||||
#define NH_PARAMETER_MANAGER_H
|
||||
|
||||
#include "../commons.h"
|
||||
#include "../enums.h"
|
||||
#include "../types.h"
|
||||
#include "./BaseManager.h"
|
||||
#include "./Parameter.h"
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
class NH_ParameterManager : public NH_BaseManager {
|
||||
public:
|
||||
NH_ParameterManager(NH_Context *context);
|
||||
virtual ~NH_ParameterManager() = default;
|
||||
|
||||
virtual NH_ERROR OnInit() override;
|
||||
|
||||
NH_ERROR RegisterParameterType(NH_ParameterTypeDesc *parameterType);
|
||||
|
||||
protected:
|
||||
std::vector<NH_ParameterTypeDesc> m_ParameterTypes;
|
||||
std::map<Uuid64, int> m_ParameterGuids;
|
||||
};
|
||||
|
||||
#endif
|
||||
39
applications/nodehub/core/ParameterOut.cpp
Normal file
@ -0,0 +1,39 @@
|
||||
#include "ParameterOut.h"
|
||||
|
||||
NH_ERROR NH_ParameterOut::GetValue(void* buf, NH_BOOL update) {
|
||||
return NH_Parameter::GetValue(buf, update);
|
||||
}
|
||||
|
||||
NH_ERROR NH_ParameterOut::SetValue(const void* buf, int size) {
|
||||
return NH_Parameter::SetValue(buf, size);
|
||||
}
|
||||
|
||||
NH_ERROR NH_ParameterOut::CopyValue(NH_Parameter* param, NH_BOOL UpdateParam) {
|
||||
return NH_Parameter::CopyValue(param, UpdateParam);
|
||||
}
|
||||
|
||||
void* NH_ParameterOut::GetReadDataPtr(NH_BOOL update) {
|
||||
return NH_Parameter::GetReadDataPtr(update);
|
||||
}
|
||||
|
||||
int NH_ParameterOut::GetStringValue(NH_STRING Value, NH_BOOL update) {
|
||||
return NH_Parameter::GetStringValue(Value, update);
|
||||
}
|
||||
|
||||
void NH_ParameterOut::DataChanged() {}
|
||||
|
||||
NH_ERROR NH_ParameterOut::AddDestination(NH_Parameter* param, NH_BOOL CheckType) {
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
void NH_ParameterOut::RemoveDestination(NH_Parameter* param) {}
|
||||
|
||||
int NH_ParameterOut::GetDestinationCount() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
NH_Parameter* NH_ParameterOut::GetDestination(int pos) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void NH_ParameterOut::RemoveAllDestinations() {}
|
||||
79
applications/nodehub/core/ParameterOut.h
Normal file
@ -0,0 +1,79 @@
|
||||
#ifndef NH_PARAMETER_OUT_H
|
||||
#define NH_PARAMETER_OUT_H
|
||||
|
||||
#include "../commons.h"
|
||||
#include "./Parameter.h"
|
||||
|
||||
/**************************************************************************
|
||||
Name: CKParameterOut
|
||||
|
||||
Summary: Output parameter providing a value
|
||||
|
||||
Remarks:
|
||||
{Image:ParameterOut}
|
||||
|
||||
+ The type of the parameter defines the type of the data provided. These
|
||||
types are maintained by the parameter manager. It defines the size of the buffer
|
||||
to use, and also decides what can be plugged onto the output parameter. To have
|
||||
the list and definition of predefined parameter types see CKParameterManager.
|
||||
|
||||
+ An output parameter may have destinations to which it pushes the data
|
||||
each time it is changed. These destinations are other output parameters, which
|
||||
for example provide their value out of the enclosing behavior, or local
|
||||
parameters which provide values to other parts of the graph of sub-behaviors.
|
||||
These destinations are managed using the AddDestination and related methods.
|
||||
When the data of the output parameter changes, it pushes the new value down to
|
||||
its destinations.
|
||||
|
||||
+ An output parameter will probably also be plugged into input
|
||||
parameters. These input parameters will pull the value from the output parameter
|
||||
when needed.
|
||||
|
||||
+ An output parameter usually knows how to write its data from and to a
|
||||
string. This is useful for display and debugging purposes. When you define a new
|
||||
type of parameter, you can specify the function that converts to and from
|
||||
strings.
|
||||
|
||||
+ An output parameter can also have an edition window. When you define a
|
||||
new type of parameter, you can specify the function that will create the edition
|
||||
window when needed by the interface.
|
||||
|
||||
+ A NH_ParameterOut is created with CKBehavior::CreateOutputParameter or
|
||||
CKContext::CreateCKParameterOut.
|
||||
|
||||
+ The class id of NH_ParameterOut is NHCID_PARAMETEROUT.
|
||||
|
||||
|
||||
See also: NH_ParameterIn, NH_ParameterOperation
|
||||
**********************************************************************************/
|
||||
|
||||
class NH_ParameterOut : public NH_Parameter {
|
||||
public:
|
||||
NH_ParameterOut(int id, NH_CSTRING name) : NH_Parameter(id, name) {}
|
||||
virtual ~NH_ParameterOut() = default;
|
||||
|
||||
virtual NH_CLASS_ID GetClassID() override { return NHCID_PARAMETEROUT; }
|
||||
|
||||
//--------------------------------------------
|
||||
// Value
|
||||
|
||||
virtual NH_ERROR GetValue(void *buf, NH_BOOL update = true);
|
||||
virtual NH_ERROR SetValue(const void *buf, int size = 0);
|
||||
virtual NH_ERROR CopyValue(NH_Parameter *param, NH_BOOL UpdateParam = true);
|
||||
virtual void *GetReadDataPtr(NH_BOOL update = true);
|
||||
virtual int GetStringValue(NH_STRING Value, NH_BOOL update = true);
|
||||
|
||||
// void CheckClass(CKParameterTypeDesc* iType);
|
||||
|
||||
//--------------------------------------------
|
||||
// Destinations
|
||||
|
||||
void DataChanged();
|
||||
NH_ERROR AddDestination(NH_Parameter *param, NH_BOOL CheckType = true);
|
||||
void RemoveDestination(NH_Parameter *param);
|
||||
int GetDestinationCount();
|
||||
NH_Parameter *GetDestination(int pos);
|
||||
void RemoveAllDestinations();
|
||||
};
|
||||
|
||||
#endif
|
||||
574
applications/nodehub/core/XClassArray.h
Normal file
@ -0,0 +1,574 @@
|
||||
/*************************************************************************/
|
||||
/* File : XClassArray.h */
|
||||
/* Author : Aymeric Bard */
|
||||
/* */
|
||||
/* Virtools SDK */
|
||||
/* Copyright (c) Virtools 2000, All Rights Reserved. */
|
||||
/*************************************************************************/
|
||||
#ifndef _XCLASSARRAY_H_
|
||||
#define _XCLASSARRAY_H_ "$Id:$"
|
||||
|
||||
#include "XUtil.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma warning(disable : 4786)
|
||||
#endif
|
||||
|
||||
/************************************************
|
||||
{filename:XClassArray}
|
||||
Name: XClassArray
|
||||
|
||||
Summary: Class representation of an array.
|
||||
|
||||
Remarks:
|
||||
This array is designed to hold structure or class
|
||||
which have something specific to do on the construction,
|
||||
deletion or recopy, like allocating/destroying pointers.
|
||||
|
||||
|
||||
|
||||
See Also : XArray, XSArray
|
||||
************************************************/
|
||||
template <class T>
|
||||
class XClassArray
|
||||
{
|
||||
public:
|
||||
typedef T* Iterator;
|
||||
|
||||
/************************************************
|
||||
Summary: Constructors.
|
||||
|
||||
Input Arguments:
|
||||
ss: Default number of reserved elements.
|
||||
a: An array to copy from.
|
||||
|
||||
************************************************/
|
||||
XClassArray(int ss=0)
|
||||
{
|
||||
// Allocated
|
||||
if(ss>0) {
|
||||
m_Begin = Allocate(ss);
|
||||
m_End = m_Begin;
|
||||
m_AllocatedEnd = m_Begin+ss;
|
||||
} else {
|
||||
m_AllocatedEnd = 0;
|
||||
m_Begin = m_End = 0;
|
||||
}
|
||||
}
|
||||
|
||||
XClassArray(const XClassArray<T>& a)
|
||||
{
|
||||
// the resize
|
||||
int size = a.Size();
|
||||
m_Begin = Allocate(size);
|
||||
m_End = m_Begin+size;
|
||||
m_AllocatedEnd = m_End;
|
||||
// The copy
|
||||
XCopy(m_Begin,a.m_Begin,a.m_End);
|
||||
}
|
||||
|
||||
/************************************************
|
||||
Summary: Destructor.
|
||||
|
||||
Remarks:
|
||||
Release the elements contained in the array. If
|
||||
you were storing pointers, you need first to iterate
|
||||
on the array and call delete on each pointer.
|
||||
************************************************/
|
||||
~XClassArray()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
/************************************************
|
||||
Summary: Affectation operator.
|
||||
|
||||
Remarks:
|
||||
The content of the array is enterely overwritten
|
||||
by the given array.
|
||||
************************************************/
|
||||
XClassArray<T>& operator = (const XClassArray<T>& a)
|
||||
{
|
||||
if(this != &a) {
|
||||
if (Allocated() >= a.Size()) { // No need to allocate
|
||||
// The copy
|
||||
XCopy(m_Begin,a.m_Begin,a.m_End);
|
||||
m_End = m_Begin + a.Size();
|
||||
} else {
|
||||
Free();
|
||||
// the resize
|
||||
int size = a.Size();
|
||||
m_Begin = Allocate(size);
|
||||
m_End = m_Begin+size;
|
||||
m_AllocatedEnd = m_End;
|
||||
// The copy
|
||||
XCopy(m_Begin,a.m_Begin,a.m_End);
|
||||
}
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/************************************************
|
||||
Summary: Removes all the elements from an array.
|
||||
|
||||
Remarks:
|
||||
There is no more space reserved after this call.
|
||||
************************************************/
|
||||
void Clear()
|
||||
{
|
||||
Free();
|
||||
m_Begin = 0;
|
||||
m_End = 0;
|
||||
m_AllocatedEnd = 0;
|
||||
}
|
||||
|
||||
/************************************************
|
||||
Summary: Reserves n elements for an array.
|
||||
|
||||
Remarks:
|
||||
The elements beyond the reserved limit are
|
||||
discarded.
|
||||
************************************************/
|
||||
void Reserve(int size)
|
||||
{
|
||||
// allocation of new size
|
||||
T* newdata = Allocate(size);
|
||||
|
||||
// Recopy of old elements
|
||||
T* last = XMin(m_Begin+size,m_End);
|
||||
XCopy(newdata,m_Begin,last);
|
||||
|
||||
// new Pointers
|
||||
Free();
|
||||
m_End = newdata+(last-m_Begin);
|
||||
m_Begin = newdata;
|
||||
m_AllocatedEnd = newdata+size;
|
||||
}
|
||||
|
||||
/************************************************
|
||||
Summary: Resizes th elements numbers of an array.
|
||||
|
||||
Remarks:
|
||||
If the size is greater than the reserved size,
|
||||
the array is reallocated at the exact needed size.
|
||||
If not, there is no reallocation at all. Resize(0)
|
||||
is faster than Clear() if you know you will probably
|
||||
push some more elements after.
|
||||
************************************************/
|
||||
void Resize(int size)
|
||||
{
|
||||
// we check if the array has enough capacity
|
||||
int oldsize = (m_AllocatedEnd-m_Begin);
|
||||
// If not, we allocate extra data
|
||||
if(size > oldsize) Reserve(size);
|
||||
// We set the end cursor
|
||||
m_End = m_Begin+size;
|
||||
}
|
||||
|
||||
/************************************************
|
||||
Summary: Inserts an element at the end of an array.
|
||||
|
||||
Input Arguments:
|
||||
o: object to insert.
|
||||
************************************************/
|
||||
void PushBack(const T& o)
|
||||
{
|
||||
XInsert(m_End,o);
|
||||
}
|
||||
|
||||
/************************************************
|
||||
Summary: Expands an array of e elements.
|
||||
|
||||
Input Arguments:
|
||||
e: size to expand.
|
||||
************************************************/
|
||||
void Expand(int e = 1)
|
||||
{
|
||||
// we check if the array has enough capacity
|
||||
|
||||
// If not, we allocate extra data
|
||||
while (Size()+e > Allocated()) {
|
||||
Reserve(Allocated()?Allocated()*2:2);
|
||||
}
|
||||
// We set the end cursor
|
||||
m_End += e;
|
||||
}
|
||||
|
||||
/************************************************
|
||||
Summary: Inserts an element at the start of an array.
|
||||
|
||||
Input Arguments:
|
||||
o: object to insert.
|
||||
************************************************/
|
||||
void PushFront(const T& o)
|
||||
{
|
||||
XInsert(m_Begin,o);
|
||||
}
|
||||
|
||||
/************************************************
|
||||
Summary: Inserts an element before another one.
|
||||
|
||||
Input Arguments:
|
||||
i: iterator on the element to insert before.
|
||||
pos: position to insert the object
|
||||
o: object to insert.
|
||||
|
||||
Remarks:
|
||||
The element to insert before is given as
|
||||
an iterator on it, i.e. a pointer on it in
|
||||
this case.
|
||||
************************************************/
|
||||
void Insert(T* i, const T& o)
|
||||
{
|
||||
// TODO : s'assurer que i est dans les limites...
|
||||
if(i<m_Begin || i>m_End) return;
|
||||
|
||||
// The Call
|
||||
XInsert(i,o);
|
||||
}
|
||||
void Insert(int pos, const T& o)
|
||||
{
|
||||
Insert(m_Begin+pos,o);
|
||||
}
|
||||
|
||||
/************************************************
|
||||
Summary: Removes the last element of an array.
|
||||
************************************************/
|
||||
void PopBack()
|
||||
{
|
||||
// we remove the last element only if it exists
|
||||
if(m_End > m_Begin) XRemove(m_End-1);
|
||||
}
|
||||
|
||||
/************************************************
|
||||
Summary: Removes the first element of an array.
|
||||
************************************************/
|
||||
void PopFront()
|
||||
{
|
||||
// we remove the first element only if it exists
|
||||
if(m_Begin != m_End) XRemove(m_Begin);
|
||||
}
|
||||
|
||||
/************************************************
|
||||
Summary: Removes an element.
|
||||
|
||||
Input Arguments:
|
||||
i: iterator on the element to remove.
|
||||
pos: position of the object to remove.
|
||||
|
||||
Return Value: an iterator on the next
|
||||
element after the element removed (to go on with
|
||||
an iteration).
|
||||
|
||||
Remarks:
|
||||
The elements are given by iterators on them,
|
||||
i.e. pointer on them in this case.
|
||||
************************************************/
|
||||
T* Remove(T* i)
|
||||
{
|
||||
// we ensure i is in boundary...
|
||||
if(i<m_Begin || i>=m_End) return 0;
|
||||
|
||||
// the Call
|
||||
return XRemove(i);
|
||||
}
|
||||
|
||||
|
||||
T* RemoveAt(int pos)
|
||||
{
|
||||
// we ensure i is in boundary...
|
||||
if (pos >= Size()) return NULL;
|
||||
|
||||
// the Call
|
||||
return XRemove(m_Begin+pos);
|
||||
}
|
||||
|
||||
void FastRemove(const T& o)
|
||||
{
|
||||
FastRemove(Find(o));
|
||||
}
|
||||
|
||||
void FastRemove(const Iterator& iT)
|
||||
{
|
||||
// we ensure i is in boundary...
|
||||
if(iT<m_Begin || iT>=m_End)
|
||||
return;
|
||||
|
||||
m_End--;
|
||||
if (iT < m_End)
|
||||
*iT = *m_End;
|
||||
}
|
||||
|
||||
/************************************************
|
||||
Summary: Access to an array element.
|
||||
|
||||
Input Arguments:
|
||||
i: index of the element to access.
|
||||
|
||||
Return Value: a reference on the object accessed.
|
||||
|
||||
Remarks:
|
||||
No test are provided on i.
|
||||
************************************************/
|
||||
T& operator [](int i) const
|
||||
{
|
||||
XASSERT(i>=0 && i<Size());
|
||||
return *(m_Begin+i);
|
||||
}
|
||||
|
||||
/************************************************
|
||||
Summary: Access to an array element.
|
||||
|
||||
Input Arguments:
|
||||
i: index of the element to access.
|
||||
|
||||
Return Value: a pointer on the object accessed.
|
||||
|
||||
Remarks:
|
||||
End() is returned if i is outside the array
|
||||
limits.
|
||||
************************************************/
|
||||
T* At(unsigned int i) const
|
||||
{
|
||||
if (i >= (unsigned int)Size()) return m_End;
|
||||
return m_Begin+i;
|
||||
}
|
||||
|
||||
/************************************************
|
||||
Summary: Swaps two items in array.
|
||||
|
||||
Input Arguments:
|
||||
pos1: position of first item to swap
|
||||
pos2: position of second item to swap.
|
||||
************************************************/
|
||||
void Swap(int pos1,int pos2)
|
||||
{
|
||||
char buffer[sizeof(T)];
|
||||
memcpy(buffer,m_Begin+pos1,sizeof(T));
|
||||
memcpy(m_Begin+pos1,m_Begin+pos2,sizeof(T));
|
||||
memcpy(m_Begin+pos2,buffer,sizeof(T));
|
||||
}
|
||||
|
||||
/************************************************
|
||||
Summary: Swaps two arrays.
|
||||
|
||||
Input Arguments:
|
||||
o: second array to swap.
|
||||
************************************************/
|
||||
void Swap(XClassArray<T>& a)
|
||||
{
|
||||
XSwap(m_Begin,a.m_Begin);
|
||||
XSwap(m_End,a.m_End);
|
||||
XSwap(m_AllocatedEnd,a.m_AllocatedEnd);
|
||||
}
|
||||
|
||||
/************************************************
|
||||
Summary: Returns the last element of an array.
|
||||
|
||||
Remarks:
|
||||
No test are provided to see if there is an
|
||||
element.
|
||||
************************************************/
|
||||
T& Back() {return *(End()-1);}
|
||||
|
||||
const T& Back() const {return *(End()-1);}
|
||||
|
||||
/************************************************
|
||||
Summary: Returns an iterator on the first element.
|
||||
|
||||
Example:
|
||||
Typically, an algorithm iterating on an array
|
||||
looks like:
|
||||
|
||||
for(T* t = a.Begin(); t != a.End(); ++t) {
|
||||
// do something with *t
|
||||
}
|
||||
|
||||
************************************************/
|
||||
T* Begin() const {return m_Begin;}
|
||||
|
||||
/************************************************
|
||||
Summary: Returns an iterator after the last element.
|
||||
************************************************/
|
||||
T* End() const {return m_End;}
|
||||
|
||||
/************************************************
|
||||
Summary: Returns the elements number.
|
||||
************************************************/
|
||||
int Size() const {return m_End-m_Begin;}
|
||||
|
||||
/************************************************
|
||||
Summary: Returns the elements allocated.
|
||||
************************************************/
|
||||
int Allocated() const {return m_AllocatedEnd-m_Begin;}
|
||||
|
||||
/************************************************
|
||||
Summary: Returns the occupied size in memory in bytes
|
||||
|
||||
Parameters:
|
||||
addstatic: TRUE if you want to add the size occupied
|
||||
by the class itself.
|
||||
************************************************/
|
||||
int GetMemoryOccupation(XBOOL addstatic=FALSE) const {
|
||||
return Allocated()*sizeof(T)+(addstatic?sizeof(*this):0);
|
||||
}
|
||||
|
||||
/************************************************
|
||||
Summary: Finds an element.
|
||||
|
||||
Input Arguments:
|
||||
o: element to find.
|
||||
|
||||
Return Value: a pointer on the first object found
|
||||
or End() if the object is not found.
|
||||
************************************************/
|
||||
T* Find(const T& o) const
|
||||
{
|
||||
// If the array is empty
|
||||
if(!(m_End - m_Begin)) return m_End;
|
||||
T* t = m_Begin;
|
||||
while(t < m_End && *t != o)
|
||||
++t;
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
/************************************************
|
||||
Summary: Returns the position of an element.
|
||||
|
||||
Input Arguments:
|
||||
o: element to find.
|
||||
|
||||
Return Value: position or -1 if not found.
|
||||
************************************************/
|
||||
int GetPosition(const T& o) const
|
||||
{
|
||||
T* t = Find(o);
|
||||
// If the element is not found
|
||||
if(t == m_End) return -1;
|
||||
// else return the position
|
||||
return t-m_Begin;
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
int XCompare(const void *elem1, const void *elem2 )
|
||||
{
|
||||
return *(T*)elem1 - *(T*)elem2;
|
||||
}
|
||||
|
||||
/************************************************
|
||||
Summary: Sorts an array with a quick sort.
|
||||
|
||||
Input Arguments:
|
||||
compare: The function comparing two elements.
|
||||
|
||||
Remarks:
|
||||
Two sorts algorithm are available : BubbleSort
|
||||
and (quick)Sort.
|
||||
************************************************/
|
||||
void Sort( VxSortFunc Fct = XCompare)
|
||||
{
|
||||
qsort(m_Begin,Size(),sizeof(T),Fct);
|
||||
}
|
||||
|
||||
protected:
|
||||
///
|
||||
// Methods
|
||||
|
||||
|
||||
void XCopy(T* dest, T* start, T* end)
|
||||
{
|
||||
while(start != end) {
|
||||
*dest = *start;
|
||||
start++;
|
||||
dest++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void XMove(T* dest, T* start, T* end)
|
||||
{
|
||||
if (dest>start)
|
||||
{
|
||||
dest += end-start;
|
||||
while(start != end) {
|
||||
--dest;
|
||||
--end;
|
||||
*dest = *end;
|
||||
}
|
||||
} else XCopy(dest,start,end);
|
||||
}
|
||||
|
||||
void XInsert(T* i, const T& o)
|
||||
{
|
||||
// Test For Reallocation
|
||||
if(m_End+1 > m_AllocatedEnd) {
|
||||
int newsize = (m_AllocatedEnd-m_Begin)*2;//+m_AllocationSize;
|
||||
if(!newsize) newsize = 1;
|
||||
T* newdata = Allocate(newsize);
|
||||
|
||||
// copy before insertion point
|
||||
XCopy(newdata,m_Begin,i);
|
||||
|
||||
// copy the new element
|
||||
T* insertionpoint = newdata+(i-m_Begin);
|
||||
*(insertionpoint) = o;
|
||||
|
||||
// copy after insertion point
|
||||
XCopy(insertionpoint+1,i,m_End);
|
||||
|
||||
// New Pointers
|
||||
m_End = newdata+(m_End-m_Begin);
|
||||
Free();
|
||||
m_Begin = newdata;
|
||||
m_AllocatedEnd = newdata+newsize;
|
||||
} else {
|
||||
// copy after insertion point
|
||||
XMove(i+1,i,m_End);
|
||||
// copy the new element
|
||||
*i = o;
|
||||
}
|
||||
m_End++;
|
||||
}
|
||||
|
||||
|
||||
T* XRemove(T* i)
|
||||
{
|
||||
// copy after insertion point
|
||||
XMove(i,i+1,m_End);
|
||||
m_End--;
|
||||
return i;
|
||||
}
|
||||
|
||||
///
|
||||
// Allocation and deallocation methods : to be override for alignement purposes
|
||||
|
||||
|
||||
T* Allocate(int size)
|
||||
{
|
||||
if(size) return new T[size];
|
||||
else return 0;
|
||||
}
|
||||
|
||||
|
||||
void Free()
|
||||
{
|
||||
delete [] m_Begin;
|
||||
}
|
||||
|
||||
///
|
||||
// Members
|
||||
|
||||
|
||||
T* m_Begin;
|
||||
|
||||
T* m_End;
|
||||
|
||||
T* m_AllocatedEnd;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||