diff --git a/.gitmodules b/.gitmodules index 6ebb78be7..563136f32 100644 --- a/.gitmodules +++ b/.gitmodules @@ -28,3 +28,6 @@ [submodule "libs/google/benchmark"] path = libs/google/benchmark url = https://github.com/google/benchmark.git +[submodule "libs/glm"] + path = libs/glm + url = https://github.com/g-truc/glm.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 57259d693..29df578c5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,49 +2,485 @@ # prerequisites: cmake_minimum_required(VERSION 3.14 FATAL_ERROR) -set(CMAKE_OSX_DEPLOYMENT_TARGET "10.9" CACHE STRING "Minimum OS X deployment version") # must be declared BEFORE project - # 10.9 is earliest version supporting c++11 +set(CMAKE_OSX_DEPLOYMENT_TARGET "10.9" CACHE STRING "Minimum OS X deployment version") # must be declared BEFORE project +# 10.9 is earliest version supporting c++11 # project declaration -project( "Nodable" VERSION "0.9" ) +project("Nodable" VERSION "0.9") # options/variables -set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/) -set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/) -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/) -set(CMAKE_INSTALL_PREFIX "${CMAKE_CURRENT_LIST_DIR}/out/app") # ./out/ folder must not be changed, referenced in readme.md -set(NDBL_APP_NAME "Nodable") -set(NDBL_PACKAGE_DIR "${CMAKE_CURRENT_LIST_DIR}/out/package") # // -set(NDBL_CONFIGURED_DIR "${PROJECT_BINARY_DIR}/configured/ndbl") -set(NDBL_SKIP_TESTS OFF ) -option(NDBL_NO_POOL "Disable Pool (for benchmark only)" OFF ) +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/) +set(CMAKE_INSTALL_PREFIX "${CMAKE_CURRENT_LIST_DIR}/out/app") # ./out/ folder must not be changed, referenced in readme.md +set(NDBL_APP_NAME "Nodable") +set(NDBL_PACKAGE_DIR "${CMAKE_CURRENT_LIST_DIR}/out/package") # // +set(NDBL_CONFIGURED_DIR "${PROJECT_BINARY_DIR}/configured/ndbl") +set(NDBL_SKIP_TESTS OFF) +option(FW_NO_POOL "Disable Pool (for benchmark only)" OFF) # include *.cmake scripts include(scripts/cmake/log.cmake) include(scripts/cmake/compiler-config.cmake) include(scripts/cmake/set-build-ref-variable.cmake) -#include other CMakeLists.txt +# add subdirectories +#------------------- -if ( NOT NDBL_SKIP_TESTS) +# Libraries: we only add the libraries that have a CMakeList, otherwise we append sources directly. + +if (NOT NDBL_SKIP_TESTS) enable_testing() # https://stackoverflow.com/questions/12540970/how-to-make-gtest-build-mdd-instead-of-mtd-by-default-using-cmake set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) # we don't need mocks (for now) nor install option(BUILD_GMOCK OFF) option(INSTALL_GTEST OFF) -endif() - -add_subdirectory(libs lib) # libraries (SDL, lodepng, Dear ImGui, etc.) -add_subdirectory(src/fw/core) # core framework -add_subdirectory(src/fw/gui) # gui framework (ImGui based) -add_subdirectory(src/fw/gui-example) # gui example using framework-gui -add_subdirectory(src/nodable/core) # nodable core (static library) -add_subdirectory(src/nodable/cli) # nodable command line interface (terminal) -add_subdirectory(src/nodable/gui) # nodable gui (gui) -add_subdirectory(src/nodable/app) # nodable application - -# Packaging: + add_subdirectory(libs/googletest EXCLUDE_FROM_ALL) +endif () + +set(BENCHMARK_ENABLE_GTEST_TESTS OFF) +set(BENCHMARK_ENABLE_TESTING OFF) +add_subdirectory(libs/google/benchmark EXCLUDE_FROM_ALL) +set(GLM_EXT_INCLUDED ON) +add_subdirectory(libs/glm EXCLUDE_FROM_ALL) +add_subdirectory(libs/freetype EXCLUDE_FROM_ALL) +set(NFD_PORTAL ON) # use portal instead of gtk, read: https://github.com/btzy/nativefiledialog-extended#using-xdg-desktop-portal-on-linux +add_subdirectory(libs/nativefiledialog-extended EXCLUDE_FROM_ALL) # target is nfd +add_subdirectory(libs/gulrak/filesystem EXCLUDE_FROM_ALL) # cpp11 compatible filesystem library. +add_subdirectory(libs/Observe EXCLUDE_FROM_ALL) # EXCLUDE_FROM_ALL: we don't want to install it. +add_subdirectory(libs/SDL EXCLUDE_FROM_ALL) # SDL2 + +# 1) Nodable #=========== +ndbl_log("Looking for libraries ...") + +find_package(Threads REQUIRED) +if (NOT Threads_FOUND) + ndbl_err("Threads not found") +endif () + +find_package(OpenGL REQUIRED) +if (NOT OpenGL_FOUND) + ndbl_err("OpenGL not found") +endif () + +ndbl_log("Threads found: ${Threads_FOUND}") +ndbl_log("OpenGL found: ${OpenGL_FOUND}") + +# 1.1) Framework Core +#-------------------- + +add_library( + framework-core + STATIC + libs/whereami/src/whereami.c + src/fw/core/Color.h + src/fw/core/TIdentifier.h + src/fw/core/assertions.h + src/fw/core/async.cpp + src/fw/core/async.h + src/fw/core/format.cpp + src/fw/core/format.h + src/fw/core/geometry/Box2D.h + src/fw/core/geometry/Rect.h + src/fw/core/geometry/Space.h + src/fw/core/geometry/Vec2.h + src/fw/core/geometry/Vec4.h + src/fw/core/geometry/XForm2D.h + src/fw/core/hash.h + src/fw/core/log.cpp + src/fw/core/log.h + src/fw/core/math.h + src/fw/core/memory/Pool.cpp + src/fw/core/memory/Pool.h + src/fw/core/reflection/Operator.h + src/fw/core/reflection/Operator_t.h + src/fw/core/reflection/class.h + src/fw/core/reflection/enum.h + src/fw/core/reflection/func_type.cpp + src/fw/core/reflection/func_type.h + src/fw/core/reflection/invokable.h + src/fw/core/reflection/qword.cpp + src/fw/core/reflection/qword.h + src/fw/core/reflection/reflection + src/fw/core/reflection/registration.h + src/fw/core/reflection/type.cpp + src/fw/core/reflection/type.h + src/fw/core/reflection/type_register.cpp + src/fw/core/reflection/type_register.h + src/fw/core/reflection/union.h + src/fw/core/reflection/variant.cpp + src/fw/core/reflection/variant.h + src/fw/core/string.h + src/fw/core/system.cpp + src/fw/core/system.h + src/fw/core/types.h +) + +target_link_libraries( + framework-core + PUBLIC + ghc_filesystem # c++ compatible std::filesystem::path like API + Observe # event system using observer/observable pattern. + glm # math + Threads::Threads +) + +target_include_directories( + framework-core + PUBLIC + src/ + src/fw/ + libs/ + libs/Observe/include/ + libs/whereami/src/ +) + +add_executable( + test-framework-core + src/fw/core/reflection/reflection.specs.cpp + src/fw/core/memory/Pool.specs.cpp +) + +target_link_libraries(test-framework-core PRIVATE gtest_main gtest framework-core) +add_test(NAME test_framework_core COMMAND test-framework-core) + +add_executable(bench-fw-core-string src/fw/core/string.bench.cpp) +target_link_libraries(bench-fw-core-string PRIVATE benchmark::benchmark framework-core) + +add_executable(bench-fw-core-Pool src/fw/core/memory/Pool.bench.cpp) +target_link_libraries(bench-fw-core-Pool PRIVATE benchmark::benchmark framework-core) + +# 1.2) Framework GUI +#------------------- + +add_library( + framework-gui + STATIC + src/fw/gui/Action.cpp + src/fw/gui/ActionManager.cpp + src/fw/gui/ActionManagerView.cpp + src/fw/gui/App.cpp + src/fw/gui/AppView.cpp + src/fw/gui/EventManager.cpp + src/fw/gui/FontManager.cpp + src/fw/gui/ImGuiEx.cpp + src/fw/gui/ImGuiExConfig.h + src/fw/gui/TextureManager.cpp + src/fw/gui/View.cpp + ${ICONFONTCPPHEADERS} # Font Awesome + libs/imgui/imgui.cpp + libs/imgui/imgui_demo.cpp + libs/imgui/imgui_draw.cpp + libs/imgui/imgui_tables.cpp + libs/imgui/imgui_widgets.cpp + libs/imgui/misc/freetype/imgui_freetype.cpp + libs/imgui/backends/imgui_impl_opengl3.cpp # include backend as-is + libs/imgui/backends/imgui_impl_sdl.cpp # // + libs/ImGuiColorTextEdit/TextEditor.cpp + libs/gl3w/GL/gl3w.c # Open GL Wrangler + libs/gl3w/GL/gl3w.h + libs/gl3w/GL/gl3w.gcda + libs/gl3w/GL/gl3w.gcno + libs/lodepng/lodepng.cpp +) + +target_link_libraries( + framework-gui + PUBLIC + ${CMAKE_DL_LIBS} + OpenGL::GL + SDL2-static SDL2main + nfd # native file dialog - extended + freetype # because: https://github.com/ocornut/imgui/tree/master/misc/freetype + framework-core +) + +target_include_directories( + framework-gui + PRIVATE + src/fw/ + PUBLIC + libs/gl3w/ + libs/gl3w/GL/ + src/ + libs/imgui/ + libs/SDL/include/ + libs/gulrak/filesystem/include/ +) + +# link APPLE specific libraries +IF (APPLE) + ndbl_log("Looking for Apple specific libraries ...") + + find_library(CORE_FOUNDATION_FRAMEWORK CoreFoundation) + if (NOT CORE_FOUNDATION_FRAMEWORK) +ndbl_err("CoreFoundation not found") + endif () + + find_library(COCOA_FRAMEWORK Cocoa) + if (NOT COCOA_FRAMEWORK) +ndbl_err("Cocoa not found") + endif () + + ndbl_log("CORE_FOUNDATION_FRAMEWORK: ${CORE_FOUNDATION_FRAMEWORK}") + ndbl_log("COCOA_FRAMEWORK: ${COCOA_FRAMEWORK}") + + target_link_libraries( + framework-gui + PRIVATE + ${CORE_FOUNDATION_FRAMEWORK} + ${COCOA_FRAMEWORK}) +ENDIF () + +target_compile_definitions(framework-gui PUBLIC IMGUI_USER_CONFIG="${CMAKE_CURRENT_LIST_DIR}/src/fw/gui/ImGuiExConfig.h") # Override imconfig.h +set_target_properties(framework-gui PROPERTIES POSITION_INDEPENDENT_CODE FALSE) # required to run well on recent os (ex: ubuntu) +set_target_properties(framework-gui PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY "${BUILD_PATH}") # fix working directory for visual studio + +# define assets +set(FW_ASSETS +"assets/fonts/CenturyGothic.ttf" +"assets/fonts/fa-solid-900.ttf" +) + +# copy each file (will dirty the build when file changes) +foreach (ASSET ${FW_ASSETS}) + configure_file("${ASSET}" "${CMAKE_BINARY_DIR}/${ASSET}" COPYONLY) +endforeach () + +# 1.3) Framework GUI - Example application +#--------------------------------------- + +# add executable +add_executable(framework-gui-example WIN32 src/fw/gui-example/main.cpp) +target_link_libraries(framework-gui-example PRIVATE framework-gui) +set_target_properties(framework-gui-example PROPERTIES POSITION_INDEPENDENT_CODE FALSE) # required to run well on recent os (ex: ubuntu) +set_target_properties(framework-gui-example PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY "${BUILD_PATH}") # fix working directory for visual studio + +# Installation : +# install( TARGETS framework-gui-example RUNTIME PERMISSIONS OWNER_EXECUTE OWNER_READ OWNER_WRITE DESTINATION .) + +# 2.1) Nodable Core +#------------------ + +add_library( + nodable-core + STATIC + src/nodable/core/Component.cpp + src/nodable/core/ComponentBag.cpp + src/nodable/core/IfNode.cpp + src/nodable/core/DataAccess.cpp + src/nodable/core/DirectedEdge.cpp + src/nodable/core/ForLoopNode.cpp + src/nodable/core/Graph.cpp + src/nodable/core/GraphUtil.cpp + src/nodable/core/InvokableComponent.cpp + src/nodable/core/LiteralNode.cpp + src/nodable/core/Node.cpp + src/nodable/core/NodeFactory.cpp + src/nodable/core/Property.cpp + src/nodable/core/PropertyBag.cpp + src/nodable/core/Scope.cpp + src/nodable/core/Slot.cpp + src/nodable/core/SlotRef.cpp + src/nodable/core/Token.cpp + src/nodable/core/TokenRibbon.cpp + src/nodable/core/VariableNode.cpp + src/nodable/core/VirtualMachine.cpp + src/nodable/core/WhileLoopNode.cpp + src/nodable/core/assembly/Code.cpp + src/nodable/core/assembly/Compiler.cpp + src/nodable/core/assembly/Instruction.cpp + src/nodable/core/language/Nodlang.cpp + src/nodable/core/language/Nodlang_biology.cpp + src/nodable/core/language/Nodlang_math.cpp +) + +target_link_libraries( + nodable-core + PUBLIC + framework-core +) + +target_include_directories( + nodable-core + PUBLIC + src/nodable/ +) + +ndbl_log("Defining install ...") +set_target_properties(nodable-core PROPERTIES OUTPUT_NAME "core") + +ndbl_log("NDBL_SKIP_TESTS: ${NDBL_SKIP_TESTS}") + +if (NDBL_SKIP_TESTS) + return() +endif () + +add_executable( + test-nodable-core + src/nodable/core/Graph.specs.cpp + src/nodable/core/Node.specs.cpp + src/nodable/core/Property.specs.cpp + src/nodable/core/Slot.specs.cpp + src/nodable/core/Token.specs.cpp + src/nodable/core/language/Nodlang.specs.cpp + src/nodable/core/language/Nodlang.tokenize.specs.cpp + src/nodable/core/language/Nodlang.parse_function_call.specs.cpp + src/nodable/core/language/Nodlang.parse_token.specs.cpp + src/nodable/core/VirtualMachine.specs.cpp + src/nodable/core/language/Nodlang.parse_and_eval.specs.cpp +) +target_link_libraries(test-nodable-core PRIVATE gtest_main gtest nodable-core) +add_test(NAME test_nodable_core COMMAND test-nodable-core) + +# Benchmarks +add_executable(bench-nodable-core-Nodlang src/nodable/core/language/Nodlang.bench.cpp) +target_link_libraries(bench-nodable-core-Nodlang PRIVATE benchmark::benchmark nodable-core) + +# 2.1) Nodable CLI +#----------------- + +ndbl_log("Checking ...") +if (NOT NDBL_CONFIGURED_DIR) + ndbl_err("Variable NDBL_CONFIGURED_DIR must be set in main CMakeLists.txt") +endif () + +add_executable( + nodable-cli + src/nodable/cli/main.cpp + src/nodable/cli/CLI.cpp +) + +target_link_libraries(nodable-cli PRIVATE nodable-core) +set_target_properties(nodable-cli PROPERTIES POSITION_INDEPENDENT_CODE FALSE) # required to run well on recent os (ex: ubuntu) +set_target_properties(nodable-cli PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY "${BUILD_PATH}") # fix working directory for visual studio +set_target_properties(nodable-cli PROPERTIES OUTPUT_NAME "cli") + +# Installation : +install(TARGETS nodable-cli DESTINATION . RUNTIME PERMISSIONS OWNER_EXECUTE OWNER_READ OWNER_WRITE) + +# 2.1) Nodable GUI +#------------------ + +# checks +ndbl_log("Checking ...") +if (NOT NDBL_CONFIGURED_DIR) + ndbl_err("Variable NDBL_CONFIGURED_DIR must be set in main CMakeLists.txt") +endif () + +# defines +set(NDBL_APP_ASSETS_DIR assets) +set(NDBL_APP_ASSETS_ABSOLUTE_DIR "${CMAKE_CURRENT_LIST_DIR}/${NDBL_APP_ASSETS_DIR}") + +# log variables +ndbl_log(" - NDBL_CONFIGURED_DIR: ${NDBL_CONFIGURED_DIR}") +ndbl_log(" - NDBL_APP_ASSETS_DIR: ${NDBL_APP_ASSETS_DIR}") +ndbl_log(" - NDBL_APP_ASSETS_ABSOLUTE_DIR: ${NDBL_APP_ASSETS_ABSOLUTE_DIR}") + +# Configure files +configure_file( +src/nodable/gui/build_info.h.in +${NDBL_CONFIGURED_DIR}/gui/build_info.h +) + +add_library( + nodable-gui + STATIC + src/nodable/gui/Config.cpp + src/nodable/gui/GraphView.cpp + src/nodable/gui/History.cpp + src/nodable/gui/HybridFile.cpp + src/nodable/gui/HybridFileView.cpp + src/nodable/gui/Nodable.cpp + src/nodable/gui/NodableView.cpp + src/nodable/gui/NodeView.cpp + src/nodable/gui/NodeViewConstraint.cpp + src/nodable/gui/Physics.cpp + src/nodable/gui/PropertyView.cpp + src/nodable/gui/SlotView.cpp +) + +target_link_libraries( + nodable-gui + PUBLIC + nodable-core + framework-gui +) + +target_include_directories( + nodable-gui + PRIVATE + src/nodable/ + libs/ + ${PROJECT_BINARY_DIR}/configured/ndbl/gui/ + PUBLIC + src/ +) + +# define assets +set(ASSETS + assets/examples/arithmetic.cpp + assets/examples/for-loop.cpp + assets/examples/if-else.cpp + assets/examples/multi-instructions.cpp + assets/fonts/JetBrainsMono-Bold.ttf + assets/fonts/JetBrainsMono-Italic.ttf + assets/fonts/JetBrainsMono-Medium.ttf + assets/fonts/JetBrainsMono-Regular.ttf + assets/images/nodable-logo-xs.png +) + +# copy each file (will dirty the build when file changes) +foreach (ASSET ${ASSETS}) + configure_file("${ASSET}" "${CMAKE_BINARY_DIR}/${ASSET}" COPYONLY) +endforeach () + +ndbl_log("NDBL_SKIP_TESTS: ${NDBL_SKIP_TESTS}") + +if (NDBL_SKIP_TESTS) + return() +endif () + +add_executable(test-nodable-gui src/nodable/gui/Nodable.specs.cpp) +target_link_libraries(test-nodable-gui PRIVATE gtest_main gtest nodable-gui) + +# GUI tests does not work on every machine (only MacOS in software on GitHub Actions) +if ($ENV{JETBRAINS_IDE}) + ndbl_log("JETBRAINS_IDE is defined: Enable Nodable GUI tests (hardware rendering)") + add_test(NAME test_nodable_gui COMMAND test-nodable-gui) + add_definitions(-D NDBL_GUI_TEST_HUMAN_SPEED) +elseif (WIN32) + ndbl_log("Windows detected: Skip Nodable GUI tests") +elseif (APPLE) + ndbl_log("Apple detected: Enable Nodable GUI tests (software rendering)") + add_test(NAME test_nodable_gui COMMAND test-nodable-gui) +elseif (UNIX) # Should be tested after APPLE + ndbl_log("Linux detected: Skip Nodable GUI tests") +endif () + +# 2.1) Nodable App +#----------------- + +add_executable(nodable-app WIN32 src/nodable/app/main.cpp) +target_link_libraries(nodable-app PUBLIC nodable-gui) +set_target_properties(nodable-app PROPERTIES POSITION_INDEPENDENT_CODE FALSE) # required to run well on recent os (ex: ubuntu) +set_target_properties(nodable-app PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY "${BUILD_PATH}") # fix working directory for visual studio +set_target_properties(nodable-app PROPERTIES OUTPUT_NAME "nodable") + +set(README README.md) +set(LICENSE LICENSE) +configure_file("${README}" . COPYONLY) +configure_file("${LICENSE}" . COPYONLY) + +# Installation : +install(TARGETS nodable-app DESTINATION . RUNTIME PERMISSIONS OWNER_EXECUTE OWNER_READ OWNER_WRITE) +install(DIRECTORY assets DESTINATION .) +install(FILES ${LICENSE} ${README} DESTINATION .) + +# 3) Packaging: +#============== + include(scripts/cmake/cpack.cmake) diff --git a/src/nodable/gui/assets/examples/arithmetic.cpp b/assets/examples/arithmetic.cpp similarity index 100% rename from src/nodable/gui/assets/examples/arithmetic.cpp rename to assets/examples/arithmetic.cpp diff --git a/src/nodable/gui/assets/examples/for-loop.cpp b/assets/examples/for-loop.cpp similarity index 100% rename from src/nodable/gui/assets/examples/for-loop.cpp rename to assets/examples/for-loop.cpp diff --git a/src/nodable/gui/assets/examples/if-else.cpp b/assets/examples/if-else.cpp similarity index 100% rename from src/nodable/gui/assets/examples/if-else.cpp rename to assets/examples/if-else.cpp diff --git a/src/nodable/gui/assets/examples/multi-instructions.cpp b/assets/examples/multi-instructions.cpp similarity index 100% rename from src/nodable/gui/assets/examples/multi-instructions.cpp rename to assets/examples/multi-instructions.cpp diff --git a/src/fw/gui/assets/fonts/CenturyGothic.ttf b/assets/fonts/CenturyGothic.ttf similarity index 100% rename from src/fw/gui/assets/fonts/CenturyGothic.ttf rename to assets/fonts/CenturyGothic.ttf diff --git a/src/nodable/gui/assets/fonts/JetBrainsMono-Bold.ttf b/assets/fonts/JetBrainsMono-Bold.ttf similarity index 100% rename from src/nodable/gui/assets/fonts/JetBrainsMono-Bold.ttf rename to assets/fonts/JetBrainsMono-Bold.ttf diff --git a/src/nodable/gui/assets/fonts/JetBrainsMono-Italic.ttf b/assets/fonts/JetBrainsMono-Italic.ttf similarity index 100% rename from src/nodable/gui/assets/fonts/JetBrainsMono-Italic.ttf rename to assets/fonts/JetBrainsMono-Italic.ttf diff --git a/src/nodable/gui/assets/fonts/JetBrainsMono-Medium.ttf b/assets/fonts/JetBrainsMono-Medium.ttf similarity index 100% rename from src/nodable/gui/assets/fonts/JetBrainsMono-Medium.ttf rename to assets/fonts/JetBrainsMono-Medium.ttf diff --git a/src/nodable/gui/assets/fonts/JetBrainsMono-Regular.ttf b/assets/fonts/JetBrainsMono-Regular.ttf similarity index 100% rename from src/nodable/gui/assets/fonts/JetBrainsMono-Regular.ttf rename to assets/fonts/JetBrainsMono-Regular.ttf diff --git a/src/fw/gui/assets/fonts/fa-solid-900.ttf b/assets/fonts/fa-solid-900.ttf similarity index 100% rename from src/fw/gui/assets/fonts/fa-solid-900.ttf rename to assets/fonts/fa-solid-900.ttf diff --git a/src/nodable/gui/assets/images/nodable-logo-xs.png b/assets/images/nodable-logo-xs.png similarity index 100% rename from src/nodable/gui/assets/images/nodable-logo-xs.png rename to assets/images/nodable-logo-xs.png diff --git a/libs/CMakeLists.txt b/libs/CMakeLists.txt deleted file mode 100644 index bb819c8ae..000000000 --- a/libs/CMakeLists.txt +++ /dev/null @@ -1,149 +0,0 @@ -# -# Create a target per library to facilitate usage by nodable targets -#------------------------------------------------------------------- - -# google tests -#------------- -add_subdirectory(googletest EXCLUDE_FROM_ALL) - -# freetype -#------------------------------ -add_library(xxhash INTERFACE) -target_include_directories(xxhash INTERFACE ./) - -# google benchmark -#----------------- -# Did not find Google Test sources! Either pass correct path in -# GOOGLETEST_PATH, or enable BENCHMARK_DOWNLOAD_DEPENDENCIES, or disable -# BENCHMARK_USE_BUNDLED_GTEST, or disable BENCHMARK_ENABLE_GTEST_TESTS / -# BENCHMARK_ENABLE_TESTING. -set(BENCHMARK_ENABLE_GTEST_TESTS off) -set(BENCHMARK_ENABLE_TESTING off) -add_subdirectory(google/benchmark EXCLUDE_FROM_ALL) - -# freetype -#------------------------------ -add_subdirectory(freetype EXCLUDE_FROM_ALL) - -# native file dialog - extended -#------------------------------ -set(NFD_PORTAL ON) # use portal instead of gtk, read: https://github.com/btzy/nativefiledialog-extended#using-xdg-desktop-portal-on-linux -add_subdirectory(nativefiledialog-extended EXCLUDE_FROM_ALL) # target is nfd - -# filesystem (c++11 compatible) -#------------------------------ -add_subdirectory(gulrak/filesystem EXCLUDE_FROM_ALL) - -# Where am I -#------------ -add_library( - whereami - STATIC - whereami/src/whereami.c -) - -target_include_directories( - whereami - PUBLIC - whereami/src -) - -# imgui -#------ -add_library( - ImGui - STATIC - imgui/imgui.cpp - imgui/imgui_demo.cpp - imgui/imgui_draw.cpp - imgui/imgui_tables.cpp - imgui/imgui_widgets.cpp - imgui/misc/freetype/imgui_freetype.cpp - imgui/backends/imgui_impl_opengl3.cpp # include backend as-is - imgui/backends/imgui_impl_sdl.cpp # // - ) - -target_link_libraries( - ImGui - PUBLIC - freetype -) - -target_include_directories( - ImGui - PUBLIC - imgui/ - SDL/include/ -) - -# imgui color text edit -#---------------------- -add_library( - ImGuiColorTextEdit - STATIC - ImGuiColorTextEdit/TextEditor.cpp -) - -target_include_directories( - ImGuiColorTextEdit - PUBLIC - ImGuiColorTextEdit/ - imgui/ -) - -# gl3w -#----- -add_library( - gl3w - STATIC - ./gl3w/GL/gl3w.c - ./gl3w/GL/gl3w.h - ./gl3w/GL/gl3w.gcda - ./gl3w/GL/gl3w.gcno -) - -target_include_directories( - gl3w - PUBLIC - ./gl3w - ./gl3w/GL -) - -# lode_png -#--------- -add_library( - lodepng - STATIC - ./lodepng/lodepng.cpp - ./lodepng/lodepng.h - ) - -target_include_directories( - lodepng - PUBLIC - ./lodepng -) - -# IconFontCppHeaders -#--------- -add_library( - IconFontCppHeaders - INTERFACE -) -target_include_directories(IconFontCppHeaders INTERFACE ./) - -# Rapid JSON -#--------- -add_library( - rapidjson - INTERFACE -) -target_include_directories(rapidjson INTERFACE ./) - -# Observe -add_subdirectory( Observe EXCLUDE_FROM_ALL) # EXCLUDE_FROM_ALL: we don't want to install it. - -# SDL2 -#------ -add_subdirectory( SDL EXCLUDE_FROM_ALL) - diff --git a/libs/glm b/libs/glm new file mode 160000 index 000000000..0af55ccec --- /dev/null +++ b/libs/glm @@ -0,0 +1 @@ +Subproject commit 0af55ccecd98d4e5a8d1fad7de25ba429d60e863 diff --git a/libs/imgui b/libs/imgui index 8c011919b..bb3cf0b6c 160000 --- a/libs/imgui +++ b/libs/imgui @@ -1 +1 @@ -Subproject commit 8c011919bfde8a96e94272b793849191bdab8ff0 +Subproject commit bb3cf0b6c1638846fb5578e429c734d71cee5217 diff --git a/scripts/cmake/compiler-config.cmake b/scripts/cmake/compiler-config.cmake index c05a8445e..680b4c4d5 100644 --- a/scripts/cmake/compiler-config.cmake +++ b/scripts/cmake/compiler-config.cmake @@ -25,13 +25,14 @@ set(CMAKE_CXX_EXTENSIONS ON) # enable threads (we have some std::async in ndbl_app) set(THREADS_PREFER_PTHREAD_FLAG ON) -# define NDBL_DEBUG in DEBUG (there is no cross-compiler solution) +# define DEBUG in DEBUG (there is no cross-compiler solution) +set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DFW_DEBUG") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DNDBL_DEBUG") if(WIN32) add_compile_definitions(NOMINMAX) # avoid min/max macros causing conflicts with min/max functions endif() -if (NDBL_NO_POOL) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DNDBL_NO_POOL") +if (FW_NO_POOL) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DFW_NO_POOL") endif () diff --git a/src/fw/core/CMakeLists.txt b/src/fw/core/CMakeLists.txt index be7f62f8c..e69de29bb 100644 --- a/src/fw/core/CMakeLists.txt +++ b/src/fw/core/CMakeLists.txt @@ -1,60 +0,0 @@ -# WARNING: Do not use this CMakeLists.txt directly, take the one from base directory. -include(../../../scripts/cmake/log.cmake) -ndbl_log_title_header() - -# log options -add_library( - framework-core - STATIC - log.cpp - format.cpp - Pool.cpp - system.cpp - reflection/func_type.cpp - reflection/qword.cpp - reflection/type.cpp - reflection/type_register.cpp - reflection/variant.cpp async.cpp - ) - -target_link_libraries( - framework-core - PUBLIC # <-------------- Those will be accessible by other targets if they link headless - ghc_filesystem # c++ compatible std::filesystem::path like API - Observe # event system using observer/observable pattern. - rapidjson # read/write json - xxhash - PRIVATE - whereami # get absolute executable/dll directory path - -) - -target_include_directories( - framework-core - PUBLIC - ../ -) - - -# Headless tests (nodable-core) -#------------------------------ - -add_executable( - test-framework-core - reflection/reflection.specs.cpp - Pool.specs.cpp) -target_link_libraries( test-framework-core PRIVATE gtest_main gtest framework-core ) -add_test( NAME test_framework_core COMMAND test-framework-core ) - -# Benchmarks -#----------- - -# string -add_executable (bench-fw-core-string string.bench.cpp) -target_link_libraries(bench-fw-core-string PRIVATE benchmark::benchmark framework-core ) - -# Pool -add_executable (bench-fw-core-Pool Pool.bench.cpp) -target_link_libraries(bench-fw-core-Pool PRIVATE benchmark::benchmark framework-core ) - - diff --git a/src/fw/core/Color.h b/src/fw/core/Color.h new file mode 100644 index 000000000..16cf08f85 --- /dev/null +++ b/src/fw/core/Color.h @@ -0,0 +1,24 @@ +#pragma once +#include "geometry/Vec4.h" +#include "types.h" + +namespace fw +{ + class Color + { + public: + Vec4 value; + + Color( u8_t r, u8_t g, u8_t b, u8_t a = 255 ) + : value( + float( r ) / 255.f, + float( g ) / 255.f, + float( b ) / 255.f, + float( a ) / 255.f + ) + {} + + operator Vec4() const + { return value; } + }; +} \ No newline at end of file diff --git a/src/fw/core/Pool.cpp b/src/fw/core/Pool.cpp deleted file mode 100644 index 6e59eb61d..000000000 --- a/src/fw/core/Pool.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "Pool.h" - -fw::Pool* fw::Pool::s_current_pool = nullptr; \ No newline at end of file diff --git a/src/fw/core/TIdentifier.h b/src/fw/core/TIdentifier.h index bd883550e..57abf9890 100644 --- a/src/fw/core/TIdentifier.h +++ b/src/fw/core/TIdentifier.h @@ -8,7 +8,7 @@ namespace fw struct _invalid_id { static_assert( std::is_unsigned_v, "UnsignedT should be unsigned" ); -#if NDBL_NO_POOL +#if FW_NO_POOL static constexpr UnsignedT value = 0; // Is an address #else static constexpr UnsignedT value = ~UnsignedT(0); diff --git a/src/fw/core/format.cpp b/src/fw/core/format.cpp index ffe912c10..26ba0787b 100644 --- a/src/fw/core/format.cpp +++ b/src/fw/core/format.cpp @@ -42,7 +42,7 @@ void format::limit_trailing_zeros(std::string& str, int _trailing_max) } -fw::string32 format::time_point_to_string(const std::chrono::system_clock::time_point &time_point) +string32 format::time_point_to_string(const std::chrono::system_clock::time_point &time_point) { std::time_t time = std::chrono::system_clock::to_time_t(time_point); // The result of ctime and ctime_s is formatted like: "Www Mmm dd hh:mm:ss yyyy\n\0" (24 chars + end of line + end of string) diff --git a/src/fw/core/format.h b/src/fw/core/format.h index 3684a07df..18b3f9dbd 100644 --- a/src/fw/core/format.h +++ b/src/fw/core/format.h @@ -1,13 +1,14 @@ #pragma once -#include "./string.h" -#include "./types.h" #include #include #include #include #include +#include "./string.h" +#include "types.h" + namespace fw { namespace format diff --git a/src/fw/core/geometry/Box2D.h b/src/fw/core/geometry/Box2D.h new file mode 100644 index 000000000..7c1f955e2 --- /dev/null +++ b/src/fw/core/geometry/Box2D.h @@ -0,0 +1,61 @@ +#pragma once +#include "XForm2D.h" + +namespace fw +{ + class Box2D + { + public: + Box2D() + {}; + + Box2D(XForm2D _xform, Vec2 _size) + : m_xform(_xform) + , m_size(_size) + {} + + Box2D(const Rect& r) + : m_xform() + , m_size() + { + m_xform.pos(r.center()); + m_size = r.size(); + } + + XForm2D& xform() + { return m_xform; } + + const XForm2D& xform() const + { return m_xform; } + + void size(Vec2 s) + { m_size = s; } + + Vec2 size() const + { return m_size; } + + void pos(Vec2 v) + { m_xform.pos(v); } + + Vec2 pos() const + { return m_xform.pos(); } + + Rect rect() const // pivot as center + { + Vec2 half_size = m_size / 2.f; + Rect result{-half_size, half_size}; + result.translate(m_xform.pos()); + return result; + } + + glm::mat3 world_matrix() const + { return m_xform.world_matrix(); } + + glm::mat3 model_matrix() const + { return m_xform.model_matrix(); } + + private: + XForm2D m_xform; + Vec2 m_size; + }; +} \ No newline at end of file diff --git a/src/fw/core/geometry/Rect.h b/src/fw/core/geometry/Rect.h new file mode 100644 index 000000000..7069702f1 --- /dev/null +++ b/src/fw/core/geometry/Rect.h @@ -0,0 +1,119 @@ +#pragma once +#include "Vec2.h" +#include + +namespace fw +{ + class Rect + { + public: + Vec2 min; + Vec2 max; + + Rect() = default; + + Rect(Vec2 min, Vec2 max) + : min(min) + , max(max) + {} + + Rect(float w, float h) + : min() + , max(w, h) + {} + + Rect(const Rect& _rect) + : min(_rect.min) + , max(_rect.max) + {} + + template + Rect(const RectT& _rect) + : Rect(fw::Vec2{_rect.Min}, fw::Vec2{_rect.Max} ) + {} + + template + Rect& operator=(const RectT& _rect) + { *this = Rect{_rect}; return *this; } + + float height() const + { return max.y - min.y; } + + float width() const + { return max.x - min.x; } + + Vec2 center() const + { return min + size() / 2.f; } + + Vec2 tl() const // Top-Left corner + { return min; } + + Vec2 bl() const // Bottom-Left corner + { return { min.x, max.y }; } + + Vec2 br() const // Bottom-Right corner + { return max; } + + Vec2 tr() const // Top-Right corner + { return { max.x, min.y }; } + + Vec2 left() const + { return { min.x, center().y }; } + + Vec2 size() const + { return { width(), height()}; } + + void translate_x( float d ) + { + min.x += d; + max.x += d; + } + + void translate_y( float d ) + { + min.y += d; + max.y += d; + } + + void translate( Vec2 _delta ) + { + min += _delta; + max += _delta; + } + + void expand( Vec2 offset) // Expand rectangle on both x and y axis + { + min -= offset; + max += offset; + } + + static bool contains(const Rect& a, const Rect& b ) + { + return a.min.x <= b.min.x && a.min.y <= b.min.y + && a.max.x >= b.max.x && a.max.y >= b.max.y; + } + + static Rect bbox(const Rect& a, const Rect& b ) // Return a rectangle overlapping the two rectangles + { + return { + {glm::min( a.min.x, b.min.x ), glm::min( a.min.y, b.min.y )}, + {glm::max( a.max.x, b.max.x ), glm::max( a.max.y, b.max.y )} + }; + } + + static Rect bbox( std::vector rects ) // Return a rectangle overlapping all the rectangles. + { + if( rects.empty() ) + { + return {}; + } + Rect result = rects[0]; + for(auto it = rects.begin() +1; it != rects.end(); it++ ) + { + result = Rect::bbox( result, *it ); + } + return result; + } + }; + +} \ No newline at end of file diff --git a/src/fw/core/geometry/Space.h b/src/fw/core/geometry/Space.h new file mode 100644 index 000000000..8d9b3d01f --- /dev/null +++ b/src/fw/core/geometry/Space.h @@ -0,0 +1,11 @@ +#pragma once + +namespace fw +{ + // to distinguish the referential of a position + enum Space { + PARENT_SPACE, + WORLD_SPACE + }; + +} \ No newline at end of file diff --git a/src/fw/core/geometry/Vec2.h b/src/fw/core/geometry/Vec2.h new file mode 100644 index 000000000..9c56ab82c --- /dev/null +++ b/src/fw/core/geometry/Vec2.h @@ -0,0 +1,103 @@ +#pragma once + +#include +#include +#include +#include + +#include "fw/core/types.h" + +namespace fw +{ + class Vec2 + { + public: + float x{}; + float y{}; + + constexpr Vec2() = default; + constexpr Vec2( float x, float y ): x( x ), y( y ) {} + constexpr Vec2( const Vec2& v ): Vec2( v.x, v.y ) {} + constexpr Vec2( const glm::vec2& v ): Vec2( v.x, v.y ) {} + explicit constexpr Vec2( float scalar ): Vec2( scalar, scalar ) {} + + operator glm::vec2() const + { return { x, y }; } + + Vec2& operator +=( const Vec2 & other ) + { + x += other.x; + y += other.y; + return *this; + } + + Vec2& operator -=( const Vec2 & other ) + { + x -= other.x; + y -= other.y; + return *this; + } + + Vec2& operator *=( const Vec2 & other ) + { + x *= other.x; + y *= other.y; + return *this; + } + + Vec2& operator /=( const Vec2 & other ) + { + x /= other.x; + y /= other.y; + return *this; + } + + Vec2 operator +( const Vec2& other ) const + { return { x + other.x, y + other.y }; } + + Vec2 operator -( const Vec2& other ) const + { return { x - other.x, y - other.y }; } + + Vec2 operator *( const Vec2& other ) const + { return { x * other.x, y * other.y }; } + + Vec2 operator /( const Vec2& other ) const + { return { x / other.x, y / other.y }; } + + Vec2 operator +( float f ) const + { return *this + Vec2(f); } + + Vec2 operator -( float f ) const + { return *this - Vec2(f); } + + Vec2 operator -() const + { return *this * Vec2(-1.f); } + + Vec2 operator /( float f ) const + { return *this / Vec2(f); } + + Vec2 operator *( float f ) const + { return *this * Vec2(f); } + + void round() + { *this = Vec2::round(*this); } + + static float sqrlen(Vec2 v) + { return v.x*v.x+v.y*v.y; } + + static Vec2 scale( Vec2 v, float magnitude ) + { return v * Vec2(magnitude); } + + static Vec2 round( Vec2 _vec ) + { return glm::round( (glm::vec2) _vec ); } + + inline static Vec2 lerp( Vec2 _source, Vec2 _target, float _factor) + { return glm::mix((glm::vec2)_source, (glm::vec2)_target, glm::clamp(_factor, 0.0f, 1.0f)); } + + static Vec2 transform(Vec2 v, glm::mat3 m) + { + auto result = m * glm::vec3(v.x, v.y, 1.f); + return {result.x, result.y}; + } + }; +} \ No newline at end of file diff --git a/src/fw/core/geometry/Vec4.h b/src/fw/core/geometry/Vec4.h new file mode 100644 index 000000000..7b68346c7 --- /dev/null +++ b/src/fw/core/geometry/Vec4.h @@ -0,0 +1,30 @@ +#pragma once +#include +#include + +namespace fw +{ + class Vec4 + { + public: + float x{}; + float y{}; + float z{}; + float w{}; + + constexpr Vec4() = default; + constexpr Vec4(float x, float y, float z, float w = 0.0f) + : x(x), y(y), z(z), w(w) + {} + + constexpr Vec4(const glm::vec4& vec) + : Vec4(vec.x, vec.y, vec.z, vec.w) + {} + + operator glm::vec4() const + { return {x, y, z, w}; } + + inline static Vec4 lerp(Vec4 _source, Vec4 _target, float _factor) + { return glm::mix((glm::vec4)_source, (glm::vec4)_target, glm::clamp(_factor, 0.0f, 1.0f)); } + }; +} diff --git a/src/fw/core/geometry/XForm2D.h b/src/fw/core/geometry/XForm2D.h new file mode 100644 index 000000000..49db96844 --- /dev/null +++ b/src/fw/core/geometry/XForm2D.h @@ -0,0 +1,55 @@ +#pragma once +#include "Rect.h" +#include "Vec2.h" +#define GLM_ENABLE_EXPERIMENTAL +#include +#include +#undef GLM_ENABLE_EXPERIMENTAL + +namespace fw +{ + class XForm2D + { + public: + XForm2D(){}; + + void pos(Vec2 _pos) + { + assert(!std::isnan(_pos.x) && !std::isnan(_pos.y)); + m_pos = _pos; + m_matrix_are_dirty = true; + } + + Vec2 pos() const + { return m_pos; } + + glm::mat3 world_matrix() const + { const_cast(this)->update(); return m_world_mat; } + + glm::mat3 model_matrix() const + { const_cast(this)->update(); return m_local_mat; } + + static Vec2 translate( Vec2 p, XForm2D t ) + { + glm::vec2 result = t.world_matrix() * glm::vec3(p.x, p.y, 1.f); + return result; + } + + private: + bool m_matrix_are_dirty{true}; + glm::vec2 m_pos{0.f, 0.f}; + glm::mat3 m_world_mat{1.f}; + glm::mat3 m_local_mat{1.f}; + + void update() + { + if ( !m_matrix_are_dirty ) + return; + + glm::mat3 m = glm::translate( glm::mat3{}, m_pos); + m_local_mat = glm::inverse( m_world_mat ); + + m_matrix_are_dirty = false; + } + }; +} \ No newline at end of file diff --git a/src/fw/core/log.h b/src/fw/core/log.h index b0c0cccbc..ea32a183d 100644 --- a/src/fw/core/log.h +++ b/src/fw/core/log.h @@ -35,7 +35,7 @@ # define LOG_MESSAGE(...) fw::log::push_message( fw::log::Verbosity_Message, ##__VA_ARGS__ ); # define LOG_FLUSH() fw::log::flush(); -#if NDBL_DEBUG +#ifdef FW_DEBUG # define LOG_VERBOSE(...) fw::log::push_message( fw::log::Verbosity_Verbose, ##__VA_ARGS__ ); #else # define LOG_VERBOSE(...) diff --git a/src/fw/core/math.h b/src/fw/core/math.h index eae0e58a9..6dea6dcfe 100644 --- a/src/fw/core/math.h +++ b/src/fw/core/math.h @@ -1,39 +1,22 @@ #pragma once -#include -#include "types.h" +#include -namespace fw::math +namespace fw { - static float clamp(float _value, float _min, float _max) - { - if ( _value < _min ) return _min; - if ( _value > _max ) return _max; - return _value; - } - static float normalize(float _value, float _min, float _max) - { - return clamp(_value, _min, _max) / (_max - _min); - } + { return glm::clamp(_value, _min, _max) / (_max - _min); } /** * Interpolate linearly _source to _target with a _factor (in [0.0f, 1.0f] ) */ - static float lerp(float _source, float _target, float _factor) - { - return _source + (_target - _source ) * clamp(_factor, 0.0f, 1.0f); - } + inline static float lerp(float _source, float _target, float _factor) + { return glm::mix(_source, _target, glm::clamp(_factor, 0.0f, 1.0f)); } static i64_t signed_diff(u64_t _left, u64_t _right) { bool left_greater_than_right = _left > _right; u64_t abs_diff = left_greater_than_right ? (_left - _right) : (_right - _left); - FW_ASSERT( abs_diff <= std::numeric_limits::max() ); + assert( abs_diff <= std::numeric_limits::max() ); return left_greater_than_right ? (i64_t)abs_diff : -(i64_t)abs_diff; } - - static ImVec2 round(ImVec2 vec) - { - return {(float)(int)(vec.x), (float)(int)(vec.y)}; - } } diff --git a/src/fw/core/Pool.bench.cpp b/src/fw/core/memory/Pool.bench.cpp similarity index 100% rename from src/fw/core/Pool.bench.cpp rename to src/fw/core/memory/Pool.bench.cpp diff --git a/src/fw/core/memory/Pool.cpp b/src/fw/core/memory/Pool.cpp new file mode 100644 index 000000000..4b0ae7bce --- /dev/null +++ b/src/fw/core/memory/Pool.cpp @@ -0,0 +1,5 @@ +#include "Pool.h" + +using namespace fw; + +Pool* Pool::s_current_pool = nullptr; \ No newline at end of file diff --git a/src/fw/core/Pool.h b/src/fw/core/memory/Pool.h similarity index 98% rename from src/fw/core/Pool.h rename to src/fw/core/memory/Pool.h index f5267837e..e0c000155 100644 --- a/src/fw/core/Pool.h +++ b/src/fw/core/memory/Pool.h @@ -1,6 +1,5 @@ #pragma once -#include "TIdentifier.h" -#include "assertions.h" + #include #include #include @@ -10,8 +9,11 @@ #include #include -#if NDBL_DEBUG -#include "reflection/type.h" +#include "fw/core/TIdentifier.h" +#include "fw/core/assertions.h" + +#ifdef FW_DEBUG +#include "fw/core/reflection/type.h" #endif #define POOL_REGISTRABLE( Class ) \ diff --git a/src/fw/core/Pool.inl b/src/fw/core/memory/Pool.inl similarity index 98% rename from src/fw/core/Pool.inl rename to src/fw/core/memory/Pool.inl index 03fcab166..3b0e948ff 100644 --- a/src/fw/core/Pool.inl +++ b/src/fw/core/memory/Pool.inl @@ -128,7 +128,7 @@ namespace fw inline Pool* Pool::get_pool() { -#ifdef NDBL_DEBUG +#ifdef FW_DEBUG FW_EXPECT(s_current_pool != nullptr, "No pool. Did you called Pool::init() ?") #endif return s_current_pool; @@ -153,7 +153,7 @@ namespace fw template inline T* Pool::get(PoolID _id) { -#if NDBL_NO_POOL +#if FW_NO_POOL return (T*)(u64_t)_id; #else return get( (u64_t)_id ); @@ -175,7 +175,7 @@ namespace fw template inline Type* PoolID::get() const // Return a pointer to the data from the Pool having an id == this->id { -#ifdef NDBL_NO_POOL +#ifdef FW_NO_POOL return (Type*)(u64_t)id; #else if( id ) return Pool::get_pool()->get( id.m_value ); @@ -213,7 +213,7 @@ namespace fw template inline PoolID Pool::create(Args... args) { -#ifdef NDBL_NO_POOL +#ifdef FW_NO_POOL T* instance = new T(args...); PoolID id{(u64_t)instance}; instance->poolid( id ); @@ -231,7 +231,7 @@ namespace fw template inline PoolID Pool::create() { -#ifdef NDBL_NO_POOL +#ifdef FW_NO_POOL T* instance = new T(); PoolID id{(u64_t)instance}; instance->poolid( id ); @@ -304,7 +304,7 @@ namespace fw template inline void Pool::destroy(PoolID _id ) { -#ifdef NDBL_NO_POOL +#ifdef FW_NO_POOL delete _id.get(); #else STATIC_ASSERT__IS_POOL_REGISTRABLE(T) diff --git a/src/fw/core/Pool.specs.cpp b/src/fw/core/memory/Pool.specs.cpp similarity index 99% rename from src/fw/core/Pool.specs.cpp rename to src/fw/core/memory/Pool.specs.cpp index 2e87f8614..71da65b2a 100644 --- a/src/fw/core/Pool.specs.cpp +++ b/src/fw/core/memory/Pool.specs.cpp @@ -1,6 +1,6 @@ -#include -#include "log.h" #include "Pool.h" +#include "fw/core/log.h" +#include using namespace fw; diff --git a/src/fw/core/reflection/invokable.h b/src/fw/core/reflection/invokable.h index 9b7ed78b1..8206d8111 100644 --- a/src/fw/core/reflection/invokable.h +++ b/src/fw/core/reflection/invokable.h @@ -4,9 +4,7 @@ #include #include /* va_list, va_start, va_arg, va_end */ #include - -#include "core/types.h" - +#include "fw/core/types.h" #include "variant.h" #include "type.h" #include "func_type.h" diff --git a/src/fw/core/reflection/qword.cpp b/src/fw/core/reflection/qword.cpp index 9314b2fb3..3a4379a1e 100644 --- a/src/fw/core/reflection/qword.cpp +++ b/src/fw/core/reflection/qword.cpp @@ -1,6 +1,6 @@ #include "qword.h" #include -#include "core/format.h" +#include "fw/core/format.h" using namespace fw; diff --git a/src/fw/core/reflection/qword.h b/src/fw/core/reflection/qword.h index dbc81cd46..9881ccbe3 100644 --- a/src/fw/core/reflection/qword.h +++ b/src/fw/core/reflection/qword.h @@ -3,8 +3,8 @@ #include #include // for memset -#include "core/assertions.h" -#include "core/types.h" +#include "fw/core/assertions.h" +#include "fw/core/types.h" #include "union.h" namespace fw diff --git a/src/fw/core/reflection/type.h b/src/fw/core/reflection/type.h index 88b9070bd..087fba22c 100644 --- a/src/fw/core/reflection/type.h +++ b/src/fw/core/reflection/type.h @@ -8,7 +8,7 @@ #include #include "type_register.h" -#include "core/assertions.h" +#include "fw/core/assertions.h" namespace fw { diff --git a/src/fw/core/reflection/type_register.cpp b/src/fw/core/reflection/type_register.cpp index 6c50f2a0b..0c7068f6b 100644 --- a/src/fw/core/reflection/type_register.cpp +++ b/src/fw/core/reflection/type_register.cpp @@ -1,7 +1,7 @@ #include "type_register.h" #include "type.h" -#include "core/log.h" -#include "core/assertions.h" +#include "fw/core/log.h" +#include "fw/core/assertions.h" using namespace fw; diff --git a/src/fw/core/reflection/variant.cpp b/src/fw/core/reflection/variant.cpp index 0bd47f8a7..2401d7152 100644 --- a/src/fw/core/reflection/variant.cpp +++ b/src/fw/core/reflection/variant.cpp @@ -1,5 +1,5 @@ #include "variant.h" -#include "core/format.h" +#include "fw/core/format.h" using namespace fw; diff --git a/src/fw/core/reflection/variant.h b/src/fw/core/reflection/variant.h index f5b3f94a4..e9b21d98e 100644 --- a/src/fw/core/reflection/variant.h +++ b/src/fw/core/reflection/variant.h @@ -4,11 +4,11 @@ #include #include // std::shared_ptr -#include "../types.h" -#include "../assertions.h" +#include "fw/core/assertions.h" +#include "fw/core/types.h" +#include "fw/core/memory/Pool.h" #include "qword.h" #include "type.h" -#include "core/Pool.h" namespace fw { diff --git a/src/fw/core/string.h b/src/fw/core/string.h index 6e9b5e45f..f4b44b36b 100644 --- a/src/fw/core/string.h +++ b/src/fw/core/string.h @@ -4,7 +4,7 @@ #include // for memcpy #include // for std::move #include // va_list, va_start, va_end - +#include #include "types.h" namespace fw diff --git a/src/fw/core/system.cpp b/src/fw/core/system.cpp index 5de0d1988..87f8f4a82 100644 --- a/src/fw/core/system.cpp +++ b/src/fw/core/system.cpp @@ -1,14 +1,14 @@ #include "system.h" -#include // to locate executable directory -#include // for ::system -#include // for std::thread +#include // to locate executable directory +#include // for ::system +#include // for std::thread #include "log.h" using namespace fw; -void fw::system::open_url_async(std::string _URL) +void system::open_url_async(std::string _URL) { auto open_url = [](std::string _URL) { @@ -37,7 +37,7 @@ void fw::system::open_url_async(std::string _URL) std::thread(open_url, _URL).detach(); } -ghc::filesystem::path fw::system::get_executable_directory() +ghc::filesystem::path system::get_executable_directory() { char* path = nullptr; int length, dirname_length; @@ -69,7 +69,7 @@ ghc::filesystem::path fw::system::get_executable_directory() return result; } -void fw::system::console::clear() /* cf: https://stackoverflow.com/questions/6486289/how-can-i-clear-console */ +void system::console::clear() /* cf: https://stackoverflow.com/questions/6486289/how-can-i-clear-console */ { #if defined _WIN32 const char* command = "cls"; diff --git a/src/fw/gui-example/AppExample.h b/src/fw/gui-example/AppExample.h index 1c124cea3..75dddd0d3 100644 --- a/src/fw/gui-example/AppExample.h +++ b/src/fw/gui-example/AppExample.h @@ -1,6 +1,6 @@ #pragma once #include "AppExampleView.h" -#include "gui/App.h" +#include "fw/gui/App.h" namespace fw { diff --git a/src/fw/gui-example/AppExampleView.h b/src/fw/gui-example/AppExampleView.h index 918c26b27..6b40d1b1a 100644 --- a/src/fw/gui-example/AppExampleView.h +++ b/src/fw/gui-example/AppExampleView.h @@ -1,5 +1,5 @@ #pragma once -#include "gui/App.h" +#include "fw/gui/App.h" namespace fw { diff --git a/src/fw/gui-example/CMakeLists.txt b/src/fw/gui-example/CMakeLists.txt deleted file mode 100644 index c3fc37cd5..000000000 --- a/src/fw/gui-example/CMakeLists.txt +++ /dev/null @@ -1,26 +0,0 @@ - -# WARNING: Do not use this CMakeLists.txt directly, take the one from base directory. - -ndbl_log_title_header() - -# add nodable executable -add_executable( - framework-gui-example - WIN32 - main.cpp - ) - -target_link_libraries( - framework-gui-example - PUBLIC - framework-gui - gl3w -) - -set_target_properties(framework-gui-example PROPERTIES POSITION_INDEPENDENT_CODE FALSE) # required to run well on recent os (ex: ubuntu) -set_target_properties(framework-gui-example PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY "${BUILD_PATH}") # fix working directory for visual studio - -# Installation : -#=============== - -# install( TARGETS framework-gui-example RUNTIME PERMISSIONS OWNER_EXECUTE OWNER_READ OWNER_WRITE DESTINATION .) diff --git a/src/fw/gui-example/main.cpp b/src/fw/gui-example/main.cpp index 9861a0da0..17d50ac8d 100644 --- a/src/fw/gui-example/main.cpp +++ b/src/fw/gui-example/main.cpp @@ -1,13 +1,15 @@ #include "AppExample.h" +using namespace fw; + int main(int argc, char *argv[]) { // Create a framework configuration, and override some fields ... - fw::Config conf; + Config conf; conf.app_window_label = "framework-example - (based on framework-gui library)"; // Instantiate the application using the predefined configuration - fw::AppExample app{conf}; + AppExample app{conf}; // Run the main loop until user closes the app or a crash happens... return app.main(argc, argv); diff --git a/src/fw/gui/Action.h b/src/fw/gui/Action.h index 9755a21af..1fe1f30f3 100644 --- a/src/fw/gui/Action.h +++ b/src/fw/gui/Action.h @@ -1,9 +1,11 @@ #pragma once -#include "Event.h" -#include "core/types.h" -#include + +#include #include +#include "fw/core/types.h" +#include "Event.h" + namespace fw { /** Data describing a shortcut (ex: "Reset": Ctrl + Alt + R) */ diff --git a/src/fw/gui/ActionManager.cpp b/src/fw/gui/ActionManager.cpp index 09c27314b..ff60237b4 100644 --- a/src/fw/gui/ActionManager.cpp +++ b/src/fw/gui/ActionManager.cpp @@ -1,12 +1,14 @@ #include "ActionManager.h" -#include "core/assertions.h" -#include "core/async.h" -#include "core/log.h" -#include "core/reflection/type.h" -#include + +#include #include #include +#include "fw/core/assertions.h" +#include "fw/core/async.h" +#include "fw/core/log.h" +#include "fw/core/reflection/type.h" + using namespace fw; ActionManager* ActionManager::s_instance = nullptr; diff --git a/src/fw/gui/ActionManager.h b/src/fw/gui/ActionManager.h index cce28a03c..fbf76d92e 100644 --- a/src/fw/gui/ActionManager.h +++ b/src/fw/gui/ActionManager.h @@ -6,10 +6,11 @@ #include #include +#include "fw/core/reflection/func_type.h" +#include "fw/core/types.h" + #include "Action.h" #include "Event.h" -#include "core/reflection/func_type.h" -#include "core/types.h" namespace fw { diff --git a/src/fw/gui/ActionManagerView.cpp b/src/fw/gui/ActionManagerView.cpp index 3fb5ec3db..045d82c23 100644 --- a/src/fw/gui/ActionManagerView.cpp +++ b/src/fw/gui/ActionManagerView.cpp @@ -1,6 +1,6 @@ #include "ActionManagerView.h" #include "ActionManager.h" -#include "imgui.h" +#include "ImGuiEx.h" using namespace fw; diff --git a/src/fw/gui/App.cpp b/src/fw/gui/App.cpp index 4bf1c7291..7fd8f0768 100644 --- a/src/fw/gui/App.cpp +++ b/src/fw/gui/App.cpp @@ -1,13 +1,13 @@ #include "App.h" -#include -#include -#include +#include "imgui/backends/imgui_impl_sdl.h" +#include "imgui/backends/imgui_impl_opengl3.h" +#include "nativefiledialog-extended/src/include/nfd.h" #include "gl3w/GL/gl3w.h" #include "lodepng/lodepng.h" - -#include "core/system.h" +#include "fw/core/system.h" #include "AppView.h" +#include "ImGuiEx.h" using namespace fw; @@ -93,9 +93,77 @@ bool App::init() // Override ImGui's default Style + // TODO: consider declaring new members in Config rather than modifying values from there. + // see colors[ImGuiCol_Button] LOG_VERBOSE("fw::App", "patch ImGui's style ...\n"); ImGuiStyle& style = ImGui::GetStyle(); - config.patch_imgui_style(style); + ImVec4 * colors = style.Colors; + colors[ImGuiCol_Text] = Vec4(0.20f, 0.20f, 0.20f, 1.00f); + colors[ImGuiCol_TextDisabled] = Vec4(0.21f, 0.21f, 0.21f, 1.00f); + colors[ImGuiCol_WindowBg] = Vec4(0.76f, 0.76f, 0.76f, 1.00f); + colors[ImGuiCol_DockingEmptyBg] = Vec4(0.64f, 0.24f, 0.24f, 1.00f); + colors[ImGuiCol_ChildBg] = Vec4(0.69f, 0.69f, 0.69f, 1.00f); + colors[ImGuiCol_PopupBg] = Vec4(0.66f, 0.66f, 0.66f, 1.00f); + colors[ImGuiCol_Border] = Vec4(0.70f, 0.70f, 0.70f, 1.00f); + colors[ImGuiCol_BorderShadow] = Vec4(0.30f, 0.30f, 0.30f, 0.50f); + colors[ImGuiCol_FrameBg] = Vec4(1.00f, 1.00f, 1.00f, 1.00f); + colors[ImGuiCol_FrameBgHovered] = Vec4(0.90f, 0.80f, 0.80f, 1.00f); + colors[ImGuiCol_FrameBgActive] = Vec4(0.90f, 0.65f, 0.65f, 1.00f); + colors[ImGuiCol_TitleBg] = Vec4(0.60f, 0.60f, 0.60f, 1.00f); + colors[ImGuiCol_TitleBgActive] = Vec4(0.60f, 0.60f, 0.60f, 1.00f); + colors[ImGuiCol_TitleBgCollapsed] = Vec4(0.49f, 0.63f, 0.69f, 1.00f); + colors[ImGuiCol_MenuBarBg] = Vec4(0.60f, 0.60f, 0.60f, 0.98f); + colors[ImGuiCol_ScrollbarBg] = Vec4(0.40f, 0.40f, 0.40f, 1.00f); + colors[ImGuiCol_ScrollbarGrab] = Vec4(0.61f, 0.61f, 0.62f, 1.00f); + colors[ImGuiCol_ScrollbarGrabHovered] = Vec4(0.70f, 0.70f, 0.70f, 1.00f); + colors[ImGuiCol_ScrollbarGrabActive] = Vec4(0.80f, 0.80f, 0.80f, 1.00f); + colors[ImGuiCol_CheckMark] = Vec4(0.31f, 0.23f, 0.14f, 1.00f); + colors[ImGuiCol_SliderGrab] = Vec4(0.71f, 0.46f, 0.22f, 0.63f); + colors[ImGuiCol_SliderGrabActive] = Vec4(0.71f, 0.46f, 0.22f, 1.00f); + colors[ImGuiCol_Button] = (ImVec4)config.button_color; + colors[ImGuiCol_ButtonHovered] = (ImVec4)config.button_hoveredColor; + colors[ImGuiCol_ButtonActive] = (ImVec4)config.button_activeColor; + colors[ImGuiCol_Header] = Vec4(0.70f, 0.70f, 0.70f, 1.00f); + colors[ImGuiCol_HeaderHovered] = Vec4(0.89f, 0.65f, 0.11f, 0.96f); + colors[ImGuiCol_HeaderActive] = Vec4(1.00f, 1.00f, 1.00f, 1.00f); + colors[ImGuiCol_Separator] = Vec4(0.43f, 0.43f, 0.50f, 0.50f); + colors[ImGuiCol_SeparatorHovered] = Vec4(0.71f, 0.71f, 0.71f, 0.78f); + colors[ImGuiCol_SeparatorActive] = Vec4(1.00f, 0.62f, 0.00f, 1.00f); + colors[ImGuiCol_ResizeGrip] = Vec4(1.00f, 1.00f, 1.00f, 0.30f); + colors[ImGuiCol_ResizeGripHovered] = Vec4(1.00f, 1.00f, 1.00f, 0.60f); + colors[ImGuiCol_ResizeGripActive] = Vec4(1.00f, 1.00f, 1.00f, 0.90f); + colors[ImGuiCol_Tab] = Vec4(0.58f, 0.54f, 0.50f, 0.86f); + colors[ImGuiCol_TabHovered] = Vec4(1.00f, 0.79f, 0.45f, 1.00f); + colors[ImGuiCol_TabActive] = Vec4(1.00f, 0.73f, 0.25f, 1.00f); + colors[ImGuiCol_TabUnfocused] = Vec4(0.53f, 0.53f, 0.53f, 0.97f); + colors[ImGuiCol_TabUnfocusedActive] = Vec4(0.79f, 0.79f, 0.79f, 1.00f); + colors[ImGuiCol_DockingPreview] = Vec4(1.00f, 0.70f, 0.09f, 0.70f); + colors[ImGuiCol_DockingEmptyBg] = Vec4(0.20f, 0.20f, 0.20f, 1.00f); + colors[ImGuiCol_PlotLines] = Vec4(1.00f, 1.00f, 1.00f, 1.00f); + colors[ImGuiCol_PlotLinesHovered] = Vec4(0.90f, 0.70f, 0.00f, 1.00f); + colors[ImGuiCol_PlotHistogram] = Vec4(0.90f, 0.70f, 0.00f, 1.00f); + colors[ImGuiCol_PlotHistogramHovered] = Vec4(1.00f, 0.60f, 0.00f, 1.00f); + colors[ImGuiCol_TextSelectedBg] = Vec4(0.00f, 0.00f, 1.00f, 0.35f); + colors[ImGuiCol_DragDropTarget] = Vec4(1.00f, 1.00f, 0.00f, 0.90f); + colors[ImGuiCol_NavHighlight] = Vec4(0.26f, 0.59f, 0.98f, 1.00f); + colors[ImGuiCol_NavWindowingHighlight] = Vec4(1.00f, 1.00f, 1.00f, 0.70f); + colors[ImGuiCol_NavWindowingDimBg] = Vec4(0.80f, 0.80f, 0.80f, 0.20f); + colors[ImGuiCol_ModalWindowDimBg] = Vec4(0.20f, 0.20f, 0.20f, 0.55f); + colors[ImGuiCol_TableBorderLight] = Vec4(0.20f, 0.20f, 0.20f, 0.80f); + colors[ImGuiCol_TableBorderStrong] = Vec4(0.20f, 0.20f, 0.20f, 0.90f); + colors[ImGuiCol_TableHeaderBg] = Vec4(0.20f, 0.20f, 0.20f, 0.60f); + colors[ImGuiCol_TableRowBg] = Vec4(0.20f, 0.20f, 0.20f, 0.40f); + colors[ImGuiCol_TableRowBgAlt] = Vec4(0.20f, 0.20f, 0.20f, 0.20f); + + style.WindowBorderSize = config.border_size; + style.FrameBorderSize = config.border_size; + style.FrameRounding = config.frame_rounding; + style.ChildRounding = config.frame_rounding; + style.WindowRounding = config.window_rounding; + style.AntiAliasedFill = config.antialiased; + style.AntiAliasedLines = config.antialiased; + style.WindowPadding = config.padding; + //style.ScaleAllSizes(1.25f); // load fonts @@ -183,7 +251,8 @@ void App::draw() SDL_GL_MakeCurrent(m_sdl_window, m_sdl_gl_context); ImGuiIO& io = ImGui::GetIO(); glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y); - glClearColor(config.background_color.Value.x, config.background_color.Value.y, config.background_color.Value.z, config.background_color.Value.w); + Vec4& color = config.background_color.value; + glClearColor( color.x, color.y, color.z, color.w); glClear(GL_COLOR_BUFFER_BIT); ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); diff --git a/src/fw/gui/App.h b/src/fw/gui/App.h index c3158eb12..42268b47b 100644 --- a/src/fw/gui/App.h +++ b/src/fw/gui/App.h @@ -6,7 +6,8 @@ #include #include -#include "core/types.h" +#include "fw/core/types.h" + #include "Config.h" #include "FontManager.h" #include "AppView.h" diff --git a/src/fw/gui/AppView.cpp b/src/fw/gui/AppView.cpp index ba2a7eea3..b36f3245f 100644 --- a/src/fw/gui/AppView.cpp +++ b/src/fw/gui/AppView.cpp @@ -2,8 +2,9 @@ #include -#include "core/log.h" -#include "core/system.h" +#include "fw/core/log.h" +#include "fw/core/system.h" + #include "EventManager.h" #include "App.h" #include "TextureManager.h" @@ -214,14 +215,14 @@ void AppView::draw_status_window() { if (ImGui::Begin(k_status_window_name)) { - if (!fw::log::get_messages().empty()) + if (!log::get_messages().empty()) { - const std::deque &messages = fw::log::get_messages(); + const std::deque &messages = log::get_messages(); auto it = messages.rend() - std::min(m_app->config.log_tooltip_max_count, messages.size()); while (it != messages.rend()) { auto &each_message = *it; - ImGui::TextColored(m_app->config.log_color[each_message.verbosity], "%s", each_message.text.c_str()); + ImGui::TextColored((ImVec4)m_app->config.log_color[each_message.verbosity], "%s", each_message.text.c_str()); ++it; } diff --git a/src/fw/gui/AppView.h b/src/fw/gui/AppView.h index eb12aee11..0c32216a3 100644 --- a/src/fw/gui/AppView.h +++ b/src/fw/gui/AppView.h @@ -1,13 +1,13 @@ #pragma once -#include -#include +#include #include #include #include #include -#include "core/types.h" +#include "fw/core/types.h" +#include "ImGuiEx.h" #include "EventManager.h" #include "View.h" #include "Config.h" @@ -20,7 +20,7 @@ namespace fw class History; struct Texture; class VirtualMachine; - struct Config; + struct FontManagerConfig; /* This class contain the basic setup for and OpenGL/SDL basic window. diff --git a/src/fw/gui/CMakeLists.txt b/src/fw/gui/CMakeLists.txt deleted file mode 100644 index 3448f6167..000000000 --- a/src/fw/gui/CMakeLists.txt +++ /dev/null @@ -1,87 +0,0 @@ - -# WARNING: Do not use this CMakeLists.txt directly, take the one from base directory. - -ndbl_log_title_header() - -# add imgui executable -add_library( - framework-gui - Action.cpp - ActionManager.cpp - ActionManagerView.cpp - App.cpp - AppView.cpp - EventManager.cpp - FontManager.cpp - ImGuiEx.cpp - TextureManager.cpp - View.cpp) - -ndbl_log("Looking for libraries ...") - -find_package(Threads REQUIRED) -if (NOT Threads_FOUND) - ndbl_err("Threads not found") -endif() - -find_package(OpenGL REQUIRED) -if (NOT OpenGL_FOUND) - ndbl_err("OpenGL not found") -endif() - -ndbl_log("Threads found: ${Threads_FOUND}") -ndbl_log("OpenGL found: ${OpenGL_FOUND}") - -target_link_libraries( - framework-gui - PUBLIC - ${CMAKE_DL_LIBS} - framework-core - IconFontCppHeaders # Font Awesome - ImGui - ImGuiColorTextEdit - OpenGL::GL gl3w # OpenGL and wrangler - SDL2-static SDL2main # SDL2 - Threads::Threads - lodepng - nfd # native file dialog - extended - freetype # because: https://github.com/ocornut/imgui/tree/master/misc/freetype -) - -# link APPLE specific libraries -IF (APPLE) - ndbl_log("Looking for Apple specific libraries ...") - - find_library(CORE_FOUNDATION_FRAMEWORK CoreFoundation) - if (NOT CORE_FOUNDATION_FRAMEWORK) - ndbl_err("CoreFoundation not found") - endif() - - find_library(COCOA_FRAMEWORK Cocoa) - if (NOT COCOA_FRAMEWORK) - ndbl_err("Cocoa not found") - endif() - - ndbl_log("CORE_FOUNDATION_FRAMEWORK: ${CORE_FOUNDATION_FRAMEWORK}") - ndbl_log("COCOA_FRAMEWORK: ${COCOA_FRAMEWORK}") - - target_link_libraries( - framework-gui - PRIVATE - ${CORE_FOUNDATION_FRAMEWORK} - ${COCOA_FRAMEWORK} ) -ENDIF() - -set_target_properties(framework-gui PROPERTIES POSITION_INDEPENDENT_CODE FALSE) # required to run well on recent os (ex: ubuntu) -set_target_properties(framework-gui PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY "${BUILD_PATH}") # fix working directory for visual studio - -# define assets -set(ASSETS - "assets/fonts/CenturyGothic.ttf" - "assets/fonts/fa-solid-900.ttf" - ) - -# copy each file (will dirty the build when file changes) -foreach(EACH_FILE ${ASSETS}) - configure_file("${EACH_FILE}" "${CMAKE_BINARY_DIR}/${EACH_FILE}" COPYONLY) -endforeach() \ No newline at end of file diff --git a/src/fw/gui/Config.h b/src/fw/gui/Config.h index a57401c18..237e6aaf5 100644 --- a/src/fw/gui/Config.h +++ b/src/fw/gui/Config.h @@ -1,14 +1,19 @@ #pragma once -#include + #include -#include "FontManager.h" + +#include "fw/core/Color.h" +#include "fw/core/geometry/Vec2.h" +#include "fw/core/geometry/Vec4.h" + +#include "FontManagerConfig.h" namespace fw { // Common configuration - struct Config { - + struct Config + { Config() = default; Config(const Config&) = delete; // disable copy @@ -18,10 +23,10 @@ namespace fw bool show_fps = false; bool delta_time_limit = true; u32_t delta_time_min = 1000 / 60; // in ms - ImColor background_color = ImColor(0.f,0.f,0.f); - ImVec4 button_activeColor = ImVec4(0.98f, 0.73f, 0.29f, 0.95f); // orange - ImVec4 button_hoveredColor = ImVec4(0.70f, 0.70f, 0.70f, 0.95f); // light grey - ImVec4 button_color = ImVec4(0.50f, 0.50f, 0.50f, 0.63f); // grey + Color background_color {0,0,0}; + Vec4 button_activeColor { 0.98f, 0.73f, 0.29f, 0.95f}; // orange + Vec4 button_hoveredColor { 0.70f, 0.70f, 0.70f, 0.95f}; // light grey + Vec4 button_color {0.50f, 0.50f, 0.50f, 0.63f}; // grey const char* splashscreen_window_label= "##Splashscreen"; bool splashscreen = true; // hide/show splashscreen bool imgui_demo = false; @@ -30,14 +35,14 @@ namespace fw float dockspace_right_ratio = 0.3f; size_t log_tooltip_max_count = 25; std::array< - ImVec4, - fw::log::Verbosity_COUNT> log_color { - ImVec4(0.5f, 0.0f, 0.0f, 1.0f), // red - ImVec4(0.5f, 0.0f, 0.5f, 1.0f), // violet - ImVec4(0.5f, 0.5f, 0.5f, 1.0f), // grey - ImVec4(0.0f, 0.5f, 0.0f, 1.0f) // green - }; - FontManager::Config font_manager{ + Vec4, + log::Verbosity_COUNT> log_color { + Vec4(0.5f, 0.0f, 0.0f, 1.0f), // red + Vec4(0.5f, 0.0f, 0.5f, 1.0f), // violet + Vec4(0.5f, 0.5f, 0.5f, 1.0f), // grey + Vec4(0.0f, 0.5f, 0.0f, 1.0f) // green + }; + FontManagerConfig font_manager{ {{ "default", // id "fonts/CenturyGothic.ttf", // path @@ -57,75 +62,10 @@ namespace fw }, 1.0f // subsampling }; - - void patch_imgui_style(ImGuiStyle& _style) const // Apply the configuration to an existing ImGuiStyle - { - ImVec4 * colors = _style.Colors; - colors[ImGuiCol_Text] = ImVec4(0.20f, 0.20f, 0.20f, 1.00f); - colors[ImGuiCol_TextDisabled] = ImVec4(0.21f, 0.21f, 0.21f, 1.00f); - colors[ImGuiCol_WindowBg] = ImVec4(0.76f, 0.76f, 0.76f, 1.00f); - colors[ImGuiCol_DockingEmptyBg] = ImVec4(0.64f, 0.24f, 0.24f, 1.00f); - colors[ImGuiCol_ChildBg] = ImVec4(0.69f, 0.69f, 0.69f, 1.00f); - colors[ImGuiCol_PopupBg] = ImVec4(0.66f, 0.66f, 0.66f, 1.00f); - colors[ImGuiCol_Border] = ImVec4(0.70f, 0.70f, 0.70f, 1.00f); - colors[ImGuiCol_BorderShadow] = ImVec4(0.30f, 0.30f, 0.30f, 0.50f); - colors[ImGuiCol_FrameBg] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f); - colors[ImGuiCol_FrameBgHovered] = ImVec4(0.90f, 0.80f, 0.80f, 1.00f); - colors[ImGuiCol_FrameBgActive] = ImVec4(0.90f, 0.65f, 0.65f, 1.00f); - colors[ImGuiCol_TitleBg] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f); - colors[ImGuiCol_TitleBgActive] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f); - colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.49f, 0.63f, 0.69f, 1.00f); - colors[ImGuiCol_MenuBarBg] = ImVec4(0.60f, 0.60f, 0.60f, 0.98f); - colors[ImGuiCol_ScrollbarBg] = ImVec4(0.40f, 0.40f, 0.40f, 1.00f); - colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.61f, 0.61f, 0.62f, 1.00f); - colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.70f, 0.70f, 0.70f, 1.00f); - colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.80f, 0.80f, 0.80f, 1.00f); - colors[ImGuiCol_CheckMark] = ImVec4(0.31f, 0.23f, 0.14f, 1.00f); - colors[ImGuiCol_SliderGrab] = ImVec4(0.71f, 0.46f, 0.22f, 0.63f); - colors[ImGuiCol_SliderGrabActive] = ImVec4(0.71f, 0.46f, 0.22f, 1.00f); - colors[ImGuiCol_Button] = button_color; - colors[ImGuiCol_ButtonHovered] = button_hoveredColor; - colors[ImGuiCol_ButtonActive] = button_activeColor; - colors[ImGuiCol_Header] = ImVec4(0.70f, 0.70f, 0.70f, 1.00f); - colors[ImGuiCol_HeaderHovered] = ImVec4(0.89f, 0.65f, 0.11f, 0.96f); - colors[ImGuiCol_HeaderActive] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f); - colors[ImGuiCol_Separator] = ImVec4(0.43f, 0.43f, 0.50f, 0.50f); - colors[ImGuiCol_SeparatorHovered] = ImVec4(0.71f, 0.71f, 0.71f, 0.78f); - colors[ImGuiCol_SeparatorActive] = ImVec4(1.00f, 0.62f, 0.00f, 1.00f); - colors[ImGuiCol_ResizeGrip] = ImVec4(1.00f, 1.00f, 1.00f, 0.30f); - colors[ImGuiCol_ResizeGripHovered] = ImVec4(1.00f, 1.00f, 1.00f, 0.60f); - colors[ImGuiCol_ResizeGripActive] = ImVec4(1.00f, 1.00f, 1.00f, 0.90f); - colors[ImGuiCol_Tab] = ImVec4(0.58f, 0.54f, 0.50f, 0.86f); - colors[ImGuiCol_TabHovered] = ImVec4(1.00f, 0.79f, 0.45f, 1.00f); - colors[ImGuiCol_TabActive] = ImVec4(1.00f, 0.73f, 0.25f, 1.00f); - colors[ImGuiCol_TabUnfocused] = ImVec4(0.53f, 0.53f, 0.53f, 0.97f); - colors[ImGuiCol_TabUnfocusedActive] = ImVec4(0.79f, 0.79f, 0.79f, 1.00f); - colors[ImGuiCol_DockingPreview] = ImVec4(1.00f, 0.70f, 0.09f, 0.70f); - colors[ImGuiCol_DockingEmptyBg] = ImVec4(0.20f, 0.20f, 0.20f, 1.00f); - colors[ImGuiCol_PlotLines] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f); - colors[ImGuiCol_PlotLinesHovered] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f); - colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f); - colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f); - colors[ImGuiCol_TextSelectedBg] = ImVec4(0.00f, 0.00f, 1.00f, 0.35f); - colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f); - colors[ImGuiCol_NavHighlight] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); - colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f); - colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.20f); - colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.55f); - colors[ImGuiCol_TableBorderLight] = ImVec4(0.20f, 0.20f, 0.20f, 0.80f); - colors[ImGuiCol_TableBorderStrong] = ImVec4(0.20f, 0.20f, 0.20f, 0.90f); - colors[ImGuiCol_TableHeaderBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.60f); - colors[ImGuiCol_TableRowBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.40f); - colors[ImGuiCol_TableRowBgAlt] = ImVec4(0.20f, 0.20f, 0.20f, 0.20f); - - _style.WindowBorderSize = 1.0f; - _style.FrameBorderSize = 1.0f; - _style.FrameRounding = 3.0f; - _style.ChildRounding = 3.0f; - _style.WindowRounding = 0.0f; - _style.AntiAliasedFill = true; - _style.AntiAliasedLines = true; - _style.WindowPadding = ImVec2(10.0f,10.0f); - } + Vec2 padding {10.0f,10.0f}; + bool antialiased {true}; + float window_rounding{0.f}; + float frame_rounding {3.f}; + float border_size {1.f}; }; } \ No newline at end of file diff --git a/src/fw/gui/Event.h b/src/fw/gui/Event.h index 94d0da27b..1952d934a 100644 --- a/src/fw/gui/Event.h +++ b/src/fw/gui/Event.h @@ -1,5 +1,5 @@ #pragma once -#include "core/types.h" +#include "fw/core/types.h" #include namespace fw diff --git a/src/fw/gui/EventManager.cpp b/src/fw/gui/EventManager.cpp index 3ef7d4e14..3afa37e8f 100644 --- a/src/fw/gui/EventManager.cpp +++ b/src/fw/gui/EventManager.cpp @@ -1,12 +1,14 @@ #include "EventManager.h" -#include "core/assertions.h" -#include "core/async.h" -#include "core/log.h" -#include "core/reflection/type.h" -#include + +#include #include #include +#include "fw/core/assertions.h" +#include "fw/core/async.h" +#include "fw/core/log.h" +#include "fw/core/reflection/type.h" + using namespace fw; EventManager* EventManager::s_instance = nullptr; @@ -57,7 +59,7 @@ IEvent* EventManager::dispatch( EventID _event_id ) void EventManager::dispatch_delayed(u64_t delay, IEvent* event) { - fw::async::get_instance().add_task( + async::get_instance().add_task( std::async(std::launch::async, [this, event, delay]() -> void { std::this_thread::sleep_for(std::chrono::milliseconds{delay}); dispatch(event); diff --git a/src/fw/gui/EventManager.h b/src/fw/gui/EventManager.h index 7f7a5c4a4..ecb8984a7 100644 --- a/src/fw/gui/EventManager.h +++ b/src/fw/gui/EventManager.h @@ -6,10 +6,11 @@ #include #include +#include "fw/core/reflection/func_type.h" +#include "fw/core/types.h" + #include "Action.h" #include "Event.h" -#include "core/reflection/func_type.h" -#include "core/types.h" namespace fw { diff --git a/src/fw/gui/FontManager.cpp b/src/fw/gui/FontManager.cpp index c364e7322..ec57b3f65 100644 --- a/src/fw/gui/FontManager.cpp +++ b/src/fw/gui/FontManager.cpp @@ -1,21 +1,20 @@ #include "FontManager.h" - -#include "core/assertions.h" -#include "core/log.h" - #include "App.h" using namespace fw; +FontManager::~FontManager() +{ LOG_VERBOSE("fw::FontManager", "Destructor " OK "\n"); } + void FontManager::init() { - for (const FontConf& each_font : m_config.text) + for (const FontConfig& each_font : m_config.text) { load_font(each_font); } // Assign text_fonts (user might want to change it later, but we need defaults) - for( int each_slot = 0; each_slot < fw::FontSlot_COUNT; ++each_slot ) + for( int each_slot = 0; each_slot < FontSlot_COUNT; ++each_slot ) { if(auto font = m_config.defaults[each_slot] ) { @@ -29,7 +28,7 @@ void FontManager::init() } } -ImFont* FontManager::load_font(const FontConf& text_font) +ImFont* FontManager::load_font(const FontConfig& text_font) { FW_EXPECT(m_loaded_fonts.find(text_font.id) == m_loaded_fonts.end(), "use of same key for different fonts is not allowed"); diff --git a/src/fw/gui/FontManager.h b/src/fw/gui/FontManager.h index 11219befc..1ac63381f 100644 --- a/src/fw/gui/FontManager.h +++ b/src/fw/gui/FontManager.h @@ -1,60 +1,27 @@ #pragma once -#include + #include #include #include -#include -#define IMGUI -#include - -#include "core/reflection/enum.h" -#include "core/log.h" - -namespace fw { - - enum FontSlot { - FontSlot_Paragraph, - FontSlot_Heading, - FontSlot_Code, - FontSlot_ToolBtn, - FontSlot_COUNT - }; +#include - R_ENUM(FontSlot) - R_ENUM_VALUE(FontSlot_Paragraph) - R_ENUM_VALUE(FontSlot_Heading) - R_ENUM_VALUE(FontSlot_Code) - R_ENUM_VALUE(FontSlot_ToolBtn) - R_ENUM_END - - struct FontConf // Struct to store text_font configuration - { - const char* id; // Font identifier - const char* path; // Font path relative to application folder - float size; // Font size in px - bool icons_enable; // If true, icons will be merged to the text_font - float icons_size; // If icons_enable is true, this will define icons size - }; +#include "FontManagerConfig.h" +#include "ImGuiEx.h" +namespace fw +{ class FontManager { public: - struct Config { - std::vector text; // text fonts - std::array defaults; // ids for font slots - FontConf icon; // icon font - float subsamples; - }; - - FontManager(Config& config): m_config(config), m_fonts(), m_loaded_fonts() {} + FontManager(const FontManagerConfig& config): m_config(config), m_fonts(), m_loaded_fonts() {} FontManager(const FontManager&) = delete; - ~FontManager() { LOG_VERBOSE("fw::FontManager", "Destructor " OK "\n"); }; + ~FontManager();; void init(); ImFont* get_font(FontSlot) const; ImFont* get_font(const char*) const; private: - ImFont* load_font(const FontConf&); - Config& m_config; + ImFont* load_font(const FontConfig&); + const FontManagerConfig& m_config; std::array m_fonts; // Required fonts std::map m_loaded_fonts; // Available fonts }; diff --git a/src/fw/gui/FontManagerConfig.h b/src/fw/gui/FontManagerConfig.h new file mode 100644 index 000000000..899362ee0 --- /dev/null +++ b/src/fw/gui/FontManagerConfig.h @@ -0,0 +1,38 @@ +#pragma once +#include "fw/core/reflection/reflection" + +namespace fw +{ + struct FontConfig // Struct to store text_font configuration + { + const char* id; // Font identifier + const char* path; // Font path relative to application folder + float size; // Font size in px + bool icons_enable; // If true, icons will be merged to the text_font + float icons_size; // If icons_enable is true, this will define icons size + }; + + enum FontSlot + { + FontSlot_Paragraph, + FontSlot_Heading, + FontSlot_Code, + FontSlot_ToolBtn, + FontSlot_COUNT + }; + + R_ENUM(FontSlot) + R_ENUM_VALUE(FontSlot_Paragraph) + R_ENUM_VALUE(FontSlot_Heading) + R_ENUM_VALUE(FontSlot_Code) + R_ENUM_VALUE(FontSlot_ToolBtn) + R_ENUM_END + + struct FontManagerConfig + { + std::vector text; // text fonts + std::array defaults; // ids for font slots + FontConfig icon; // icon font + float subsamples; + }; +} \ No newline at end of file diff --git a/src/fw/gui/ImGuiEx.cpp b/src/fw/gui/ImGuiEx.cpp index a28c3a1a5..fe184b9fd 100644 --- a/src/fw/gui/ImGuiEx.cpp +++ b/src/fw/gui/ImGuiEx.cpp @@ -3,47 +3,35 @@ #include #include -#include "core/log.h" -#include "core/assertions.h" +#include "fw/core/log.h" +#include "fw/core/assertions.h" #include "Texture.h" #include "EventManager.h" using namespace fw; -bool ImGuiEx::s_is_in_a_frame = false; -bool ImGuiEx::s_is_any_tooltip_open = false; -float ImGuiEx::s_tooltip_duration_default = 0.2f; -float ImGuiEx::s_tooltip_delay_default = 0.5f; -float ImGuiEx::s_tooltip_delay_elapsed = 0.0f; -bool ImGuiEx::debug = false; - -ImRect ImGuiEx::GetContentRegion(Space origin) +Rect ImGuiEx::GetContentRegion(Space origin) { + Rect region{ImGui::GetWindowContentRegionMin(), ImGui::GetWindowContentRegionMax()}; + switch (origin) { - case Space_Local: - return { - ImVec2(), - ImGui::GetWindowContentRegionMax() - ImGui::GetWindowContentRegionMin() - }; - case Space_Screen: { - ImRect rect{ - ImGui::GetWindowContentRegionMin(), - ImGui::GetWindowContentRegionMax() - }; - rect.Translate(ImGui::GetWindowPos()); - return rect; + case PARENT_SPACE: + return { Vec2(), region.size() }; + case WORLD_SPACE: { + region.translate(ImGui::GetWindowPos()); + return region; } default: FW_EXPECT(false,"OriginRef_ case not handled. Cannot compute GetContentRegion(..)") } } -void ImGuiEx::DrawRectShadow (ImVec2 _topLeftCorner, ImVec2 _bottomRightCorner, float _borderRadius, int _shadowRadius, ImVec2 _shadowOffset, ImColor _shadowColor) +void ImGuiEx::DrawRectShadow (Vec2 _topLeftCorner, Vec2 _bottomRightCorner, float _borderRadius, int _shadowRadius, Vec2 _shadowOffset, Vec4 _shadowColor) { - ImVec2 itemRectMin(_topLeftCorner.x + _shadowOffset.x, _topLeftCorner.y + _shadowOffset.y); - ImVec2 itemRectMax(_bottomRightCorner.x + _shadowOffset.x, _bottomRightCorner.y + _shadowOffset.y); - ImVec4 color = _shadowColor; + Vec2 itemRectMin(_topLeftCorner.x + _shadowOffset.x, _topLeftCorner.y + _shadowOffset.y); + Vec2 itemRectMax(_bottomRightCorner.x + _shadowOffset.x, _bottomRightCorner.y + _shadowOffset.y); + Vec4 color = _shadowColor; color.w /= _shadowRadius; auto borderRadius = _borderRadius; @@ -52,7 +40,7 @@ void ImGuiEx::DrawRectShadow (ImVec2 _topLeftCorner, ImVec2 _bottomRightCorner, { ImDrawList* draw_list = ImGui::GetWindowDrawList(); - draw_list->AddRectFilled(itemRectMin, itemRectMax, ImColor(color), borderRadius); + draw_list->AddRectFilled(itemRectMin, itemRectMax, ImColor(color)); itemRectMin.x -= 1.0f; itemRectMin.y -= 1.0f; @@ -64,11 +52,11 @@ void ImGuiEx::DrawRectShadow (ImVec2 _topLeftCorner, ImVec2 _bottomRightCorner, } } -void ImGuiEx::ShadowedText(ImVec2 _offset, ImColor _shadowColor, const char* _format, ...) +void ImGuiEx::ShadowedText(Vec2 _offset, Vec4 _shadowColor, const char* _format, ...) { // draw first the shadow auto p = ImGui::GetCursorPos(); - ImGui::SetCursorPos(ImVec2(p.x + _offset.x, p.y + _offset.y)); + ImGui::SetCursorPos(Vec2(p.x + _offset.x, p.y + _offset.y)); va_list args; va_start(args, _format); @@ -78,11 +66,11 @@ void ImGuiEx::ShadowedText(ImVec2 _offset, ImColor _shadowColor, const char* _fo va_end(args); } -void ImGuiEx::ColoredShadowedText(ImVec2 _offset, ImColor _textColor, ImColor _shadowColor, const char* _format, ...) +void ImGuiEx::ColoredShadowedText(Vec2 _offset, Vec4 _textColor, Vec4 _shadowColor, const char* _format, ...) { // draw first the shadow auto p = ImGui::GetCursorPos(); - ImGui::SetCursorPos(ImVec2(p.x + _offset.x, p.y + _offset.y)); + ImGui::SetCursorPos(Vec2(p.x + _offset.x, p.y + _offset.y)); va_list args; va_start(args, _format); @@ -94,41 +82,41 @@ void ImGuiEx::ColoredShadowedText(ImVec2 _offset, ImColor _textColor, ImColor _s void ImGuiEx::DrawWire( ImDrawList *draw_list, - ImVec2 pos0, - ImVec2 pos1, - ImVec2 norm0, - ImVec2 norm1, - ImColor color, - ImColor shadowColor, + Vec2 pos0, + Vec2 pos1, + Vec2 norm0, + Vec2 norm1, + Vec4 color, + Vec4 shadowColor, float thickness, float roundness) { // Compute tangents - ImVec2 roundedDist( + Vec2 roundedDist( std::abs( pos1.x - pos0.x ) * roundness, std::abs( pos1.y - pos0.y ) * roundness); - ImVec2 cp0_fill(pos0 + norm0 * roundedDist); - ImVec2 cp1_fill(pos1 + norm1 * roundedDist); + Vec2 cp0_fill(pos0 + norm0 * roundedDist); + Vec2 cp1_fill(pos1 + norm1 * roundedDist); - ImVec2 pos_shadow_offset(1.f, 1.f); - ImVec2 pos0_shadow(pos0 + pos_shadow_offset); - ImVec2 pos1_shadow(pos1 + pos_shadow_offset); - ImVec2 cp0_shadow(pos0_shadow + norm0 * roundedDist * 1.05f); - ImVec2 cp1_shadow(pos1_shadow + norm1 * roundedDist * 0.95f); + Vec2 pos_shadow_offset(1.f, 1.f); + Vec2 pos0_shadow(pos0 + pos_shadow_offset); + Vec2 pos1_shadow(pos1 + pos_shadow_offset); + Vec2 cp0_shadow(pos0_shadow + norm0 * roundedDist * 1.05f); + Vec2 cp1_shadow(pos1_shadow + norm1 * roundedDist * 0.95f); // shadow - draw_list->AddBezierCurve( pos0_shadow, cp0_shadow, cp1_shadow, pos1_shadow, shadowColor, thickness); + draw_list->AddBezierCurve( pos0_shadow, cp0_shadow, cp1_shadow, pos1_shadow, ImColor(shadowColor), thickness); // fill - draw_list->AddBezierCurve( pos0, cp0_fill, cp1_fill, pos1, color, thickness); + draw_list->AddBezierCurve( pos0, cp0_fill, cp1_fill, pos1, ImColor(color), thickness); } void ImGuiEx::DrawVerticalWire( ImDrawList *draw_list, - ImVec2 pos0, - ImVec2 pos1, - ImColor color, - ImColor shadowColor, + Vec2 pos0, + Vec2 pos1, + Vec4 color, + Vec4 shadowColor, float thickness, float roundness) { @@ -136,8 +124,8 @@ void ImGuiEx::DrawVerticalWire( draw_list, pos0, pos1, - ImVec2(0.0f, 1.0f), - ImVec2(0.0f, -1.0f), + Vec2(0.0f, 1.0f), + Vec2(0.0f, -1.0f), color, shadowColor, thickness, @@ -146,10 +134,10 @@ void ImGuiEx::DrawVerticalWire( void ImGuiEx::DrawHorizontalWire( ImDrawList *draw_list, - ImVec2 pos0, - ImVec2 pos1, - ImColor color, - ImColor shadowColor, + Vec2 pos0, + Vec2 pos1, + Vec4 color, + Vec4 shadowColor, float thickness, float roundness) { @@ -157,44 +145,34 @@ void ImGuiEx::DrawHorizontalWire( // Compute tangents float dist = std::max(std::abs(pos1.y - pos0.y), 200.0f); - ImVec2 cp0(pos0.x + dist * roundness , pos0.y ); - ImVec2 cp1(pos1.x - dist * roundness , pos1.y ); + Vec2 cp0(pos0.x + dist * roundness , pos0.y ); + Vec2 cp1(pos1.x - dist * roundness , pos1.y ); // draw bezier curve - ImVec2 shadowOffset(1.0f, 2.0f); + Vec2 shadowOffset(1.0f, 2.0f); draw_list->AddBezierCurve( pos0 + shadowOffset, cp0 + shadowOffset, cp1 + shadowOffset, pos1 + shadowOffset, - shadowColor, + ImColor(shadowColor), thickness); // shadow - draw_list->AddBezierCurve(pos0, cp0, cp1, pos1, color, thickness); // fill -} - -ImRect& ImGuiEx::EnlargeToInclude(ImRect& _rect, ImRect _other) -{ - if( _other.Min.x < _rect.Min.x) _rect.Min.x = _other.Min.x; - if( _other.Min.y < _rect.Min.y) _rect.Min.y = _other.Min.y; - if( _other.Max.x > _rect.Max.x) _rect.Max.x = _other.Max.x; - if( _other.Max.y > _rect.Max.y) _rect.Max.y = _other.Max.y; - - return _rect; + draw_list->AddBezierCurve(pos0, cp0, cp1, pos1, ImColor(color), thickness); // fill } bool ImGuiEx::BeginTooltip(float _delay, float _duration) { if ( !ImGui::IsItemHovered() ) return false; - FW_EXPECT(s_is_in_a_frame, "Did you forgot to call ImGuiEx::BeginFrame/EndFrame ?"); + FW_EXPECT( is_in_a_frame, "Did you forgot to call ImGuiEx::BeginFrame/EndFrame ?"); - s_is_any_tooltip_open = true; - s_tooltip_delay_elapsed += ImGui::GetIO().DeltaTime; + is_any_tooltip_open = true; + tooltip_delay_elapsed += ImGui::GetIO().DeltaTime; float fade = 0.f; - if (s_tooltip_delay_elapsed >= _delay ) + if ( tooltip_delay_elapsed >= _delay ) { - fade = (s_tooltip_delay_elapsed - _delay) / _duration; + fade = ( tooltip_delay_elapsed - _delay) / _duration; } ImGui::PushStyleVar(ImGuiStyleVar_Alpha, fade); @@ -211,20 +189,19 @@ void ImGuiEx::EndTooltip() void ImGuiEx::EndFrame() { - FW_EXPECT(s_is_in_a_frame, "ImGuiEx::BeginFrame/EndFrame mismatch"); - if( !s_is_any_tooltip_open ) + FW_EXPECT( is_in_a_frame, "ImGuiEx::BeginFrame/EndFrame mismatch"); + if( !is_any_tooltip_open ) { - s_tooltip_delay_elapsed = 0.f; + tooltip_delay_elapsed = 0.f; } - s_is_in_a_frame = false; + is_in_a_frame = false; } void ImGuiEx::BeginFrame() { - - FW_EXPECT(!s_is_in_a_frame, "ImGuiEx::BeginFrame/EndFrame mismatch"); - s_is_in_a_frame = true; - s_is_any_tooltip_open = false; + FW_EXPECT(!is_in_a_frame, "ImGuiEx::BeginFrame/EndFrame mismatch"); + is_in_a_frame = true; + is_any_tooltip_open = false; } void ImGuiEx::BulletTextWrapped(const char* str) @@ -233,32 +210,34 @@ void ImGuiEx::BulletTextWrapped(const char* str) ImGui::TextWrapped("%s", str); } -void ImGuiEx::DebugRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding, ImDrawFlags flags, float thickness) +void ImGuiEx::DebugRect(const Vec2& p_min, const Vec2& p_max, ImU32 col, float rounding, ImDrawFlags flags, float thickness) { +#ifdef FW_DEBUG if(!debug) return; ImDrawList* list = ImGui::GetForegroundDrawList(); list->AddRect(p_min, p_max, col, rounding, flags, thickness); +#endif } -void ImGuiEx::DebugCircle(const ImVec2& center, float radius, ImU32 col, int num_segments, float thickness) +void ImGuiEx::DebugCircle(const Vec2& center, float radius, ImU32 col, int num_segments, float thickness) { +#ifdef FW_DEBUG if(!debug) return; ImDrawList* list = ImGui::GetForegroundDrawList(); list->AddCircle(center, radius, col, num_segments, thickness); +#endif } -void ImGuiEx::DebugLine(const ImVec2& p1, const ImVec2& p2, ImU32 col, float thickness) +void ImGuiEx::DebugLine(const Vec2& p1, const Vec2& p2, ImU32 col, float thickness) { +#ifdef FW_DEBUG if(!debug) return; ImDrawList* list = ImGui::GetForegroundDrawList(); list->AddLine(p1, p2, col, thickness); +#endif } void ImGuiEx::Image(Texture* _texture) { - ImVec2 size{ - (float)_texture->width, - (float)_texture->height - }; - ImGui::Image((void *)(intptr_t)_texture->gl_handler, size); + ImGui::Image((ImTextureID)_texture->id(), _texture->size()); } diff --git a/src/fw/gui/ImGuiEx.h b/src/fw/gui/ImGuiEx.h index 2d29f8f9e..227bb4124 100644 --- a/src/fw/gui/ImGuiEx.h +++ b/src/fw/gui/ImGuiEx.h @@ -1,111 +1,99 @@ #pragma once #include +#include +#include +#include -#ifndef IMGUI_DEFINE_MATH_OPERATORS -#define IMGUI_DEFINE_MATH_OPERATORS -#endif +#include "fw/core/geometry/Rect.h" +#include "fw/core/geometry/Vec2.h" +#include "fw/core/geometry/Vec4.h" +#include "fw/core/geometry/Space.h" +#include "fw/core/types.h" #include "ActionManager.h" #include "EventManager.h" -#include "core/types.h" -#include -#include namespace fw { // forward declarations struct Texture; - // to distinguish the referential of a position - enum Space { - Space_Local, - Space_Screen - }; - - class ImGuiEx + namespace ImGuiEx { - public: - virtual ~ImGuiEx() = 0; - - template - static void DrawHelperEx(float _alpha, const char* _format, Args... args) - { - ImGui::PushStyleVar(ImGuiStyleVar_Alpha, _alpha); - ImGui::Text(ICON_FA_QUESTION_CIRCLE); - ImGui::PopStyleVar(); - - if( BeginTooltip() ) - { - ImGui::Text(_format, args...); - EndTooltip(); - } + constexpr float TOOLTIP_DURATION_DEFAULT = 0.2f; + constexpr float TOOLTIP_DELAY_DEFAULT = 0.5f; - } - - template - static void DrawHelper(const char* _format, Args... args) { DrawHelperEx(0.25f, _format, args...); } // simple "?" test with a tooltip. + static bool debug = false; // when true, all DebugXXX commands actually draw, otherwise it is skipped + static bool is_in_a_frame = false; + static bool is_any_tooltip_open = false; + static float tooltip_delay_elapsed = 0.0f; /** * Draw a rounded-rectangle shadow * TODO: use a low cost method, this one is drawing several rectangle with modulated opacity. */ - static void DrawRectShadow( - ImVec2 _topLeftCorner, - ImVec2 _bottomRightCorner, + extern void DrawRectShadow( + Vec2 _topLeftCorner, + Vec2 _bottomRightCorner, float _borderRadius = 0.0f, int _shadowRadius = 10, - ImVec2 _shadowOffset = ImVec2(), - ImColor _shadowColor = ImColor(0.0f, 0.0f, 0.0f)); + Vec2 _shadowOffset = Vec2(), + Vec4 _shadowColor = Vec4(0.0f, 0.0f, 0.0f, 1.f)); - static void ShadowedText( - ImVec2 _offset, - ImColor _shadowColor, + extern void ShadowedText( + Vec2 _offset, + Vec4 _shadowColor, const char *_format, ...); - static void ColoredShadowedText( - ImVec2 _offset, - ImColor _textColor, - ImColor _shadowColor, + extern void ColoredShadowedText( + Vec2 _offset, + Vec4 _textColor, + Vec4 _shadowColor, const char *_format, ...); - static void DrawWire( + extern void DrawWire( ImDrawList *draw_list, - ImVec2 pos0, - ImVec2 pos1, - ImVec2 norm0, - ImVec2 norm1, - ImColor color, - ImColor shadowColor, + Vec2 pos0, + Vec2 pos1, + Vec2 norm0, + Vec2 norm1, + Vec4 color, + Vec4 shadowColor, float thickness = 1.0f, float roundness = 0.5f); - static void DrawVerticalWire( + extern void DrawVerticalWire( ImDrawList *draw_list, - ImVec2 pos0, - ImVec2 pos1, - ImColor color, - ImColor shadowColor, + Vec2 pos0, + Vec2 pos1, + Vec4 color, + Vec4 shadowColor, float thickness = 1.0f, float roundness = 0.5f); - static void DrawHorizontalWire( + extern void DrawHorizontalWire( ImDrawList *draw_list, - ImVec2 pos0, - ImVec2 pos1, - ImColor color, - ImColor shadowColor, + Vec2 pos0, + Vec2 pos1, + Vec4 color, + Vec4 shadowColor, float thickness = 1.0f, float roundness = 0.5f); - static void BeginFrame(); - static void EndFrame(); - static bool BeginTooltip(float _delay = s_tooltip_delay_default - , float _duration = s_tooltip_duration_default); - static void EndTooltip(); - static ImRect& EnlargeToInclude(ImRect& _rect, ImRect _other); + extern void BeginFrame(); + extern void EndFrame(); + extern bool BeginTooltip(float _delay = TOOLTIP_DELAY_DEFAULT, float _duration = TOOLTIP_DURATION_DEFAULT ); + extern void EndTooltip(); + extern Rect& EnlargeToInclude(Rect& _rect, Rect _other); + extern void BulletTextWrapped(const char*); + extern Rect GetContentRegion(Space); + extern void DebugRect(const Vec2& p_min, const Vec2& p_max, ImU32 col, float rounding = 0.f, ImDrawFlags flags = 0, float thickness = 1.f); + extern void DebugCircle(const Vec2& center, float radius, ImU32 col, int num_segments = 0, float thickness = 1.0f); + extern void DebugLine(const Vec2& p1, const Vec2& p2, ImU32 col, float thickness = 1.0f); + extern void Image(fw::Texture* ); template static void MenuItem(bool selected = false, bool enable = true) // Shorthand to get a given action from the manager and draw a MenuItem from it. @@ -118,22 +106,26 @@ namespace fw } }; - static void BulletTextWrapped(const char*); - - static ImRect GetContentRegion(Space); + template + static void DrawHelperEx(float _alpha, const char* _format, Args... args) + { + ImGui::PushStyleVar(ImGuiStyleVar_Alpha, _alpha); + ImGui::Text(ICON_FA_QUESTION_CIRCLE); + ImGui::PopStyleVar(); - static bool debug; // when true, all DebugXXX commands actually draw, otherwise it is skipped - static void DebugRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding = 0.f, ImDrawFlags flags = 0, float thickness = 1.f); - static void DebugCircle(const ImVec2& center, float radius, ImU32 col, int num_segments = 0, float thickness = 1.0f); - static void DebugLine(const ImVec2& p1, const ImVec2& p2, ImU32 col, float thickness = 1.0f); + if( BeginTooltip() ) + { + ImGui::Text(_format, args...); + EndTooltip(); + } + } - static void Image(fw::Texture* ); - private: - static bool s_is_in_a_frame; - static bool s_is_any_tooltip_open; - static float s_tooltip_delay_default; - static float s_tooltip_duration_default; - static float s_tooltip_delay_elapsed; + template + static void DrawHelper(const char* _format, Args... args) + { DrawHelperEx(0.25f, _format, args...); } // simple "?" test with a tooltip. + inline ImRect toImGui(Rect r) { return { r.min, r.max }; }; + inline ImVec2 toImGui(Vec2 v) { return { v.x, v.y }; }; + inline ImVec4 toImGui(Vec4 v) { return { v.x, v.y, v.z, v.w }; }; }; } \ No newline at end of file diff --git a/src/fw/gui/ImGuiExConfig.h b/src/fw/gui/ImGuiExConfig.h new file mode 100644 index 000000000..24a1b8bac --- /dev/null +++ b/src/fw/gui/ImGuiExConfig.h @@ -0,0 +1,23 @@ +#pragma once + +#include "fw/core/geometry/Vec2.h" +#include "fw/core/geometry/Vec4.h" +#include "fw/core/geometry/Box2D.h" + +//---- Use stb_truetype to build and rasterize the font atlas (default) +// The only purpose of this define is if you want force compilation of the stb_truetype backend ALONG with the FreeType backend. +#define IMGUI_ENABLE_STB_TRUETYPE + +//---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4. +// This will be inlined as part of ImVec2 and ImVec4 class declarations. + +#define IM_VEC2_CLASS_EXTRA \ + ImVec2( const fw::Vec2& v ): ImVec2(v.x, v.y) {} \ + ImVec2( const float f): ImVec2(f, f) {} \ + operator fw::Vec2() const { return {x,y}; } + +#define IM_VEC4_CLASS_EXTRA \ + ImVec4(const fw::Vec4& v): ImVec4(v.x, v.y, v.z, v.w) {} \ + operator fw::Vec4() const { return {x,y,z,w}; } + +#define IMGUI_DEFINE_MATH_OPERATORS \ No newline at end of file diff --git a/src/fw/gui/Texture.h b/src/fw/gui/Texture.h index 32fabbc5c..499f97dcd 100644 --- a/src/fw/gui/Texture.h +++ b/src/fw/gui/Texture.h @@ -1,8 +1,10 @@ #pragma once -#include "core/types.h" #include "gl3w/GL/gl3w.h" +#include "fw/core/geometry/Vec2.h" +#include "fw/core/types.h" + namespace fw { struct Texture // Simple data structure to store OpenGL texture information @@ -21,5 +23,11 @@ namespace fw std::vector buffer; // Image buffer loaded into memory u32_t width; // in pixels u32_t height; // in pixels + + Vec2 size() const + { return { (float)width, (float)height }; } + + u64_t id() const + { return gl_handler; } }; } diff --git a/src/fw/gui/TextureManager.cpp b/src/fw/gui/TextureManager.cpp index 785627bc0..bdf399d26 100644 --- a/src/fw/gui/TextureManager.cpp +++ b/src/fw/gui/TextureManager.cpp @@ -1,17 +1,15 @@ #include "TextureManager.h" -#include "lodepng/lodepng.h" +#include +#include +#include +#include +#include +#include -#include "core/log.h" +#include "fw/core/log.h" #include "Texture.h" -//#include "gl3w/GL/gl3w.h" -//#include "gl3w/GL/glcorearb.h" -//#include "lodepng/lodepng.h" -//#include -//#include -//#include -//#include -//#include + using namespace fw; Texture* TextureManager::load(const std::string& path) diff --git a/src/fw/gui/View.cpp b/src/fw/gui/View.cpp index b19bb29c4..96620dd02 100644 --- a/src/fw/gui/View.cpp +++ b/src/fw/gui/View.cpp @@ -1,4 +1,5 @@ #include "View.h" +#include "ImGuiEx.h" using namespace fw; @@ -8,33 +9,53 @@ REGISTER } View::View() - : m_is_hovered(false) - , m_is_visible(true) - , m_screen_space_content_region(0.0f, 512.0f) // need to be != 0.0f (cf GraphNodeView frame_all) +: is_hovered(false) +, is_visible(true) +, parent_content_region() +, box() { } -void View::set_visible(bool _visibility) +void View::position( Vec2 _position, Space origin) { - m_is_visible = _visibility; + if ( origin == PARENT_SPACE ) + { + Vec2 parent_space_pos = Vec2::transform(_position, parent_content_region.world_matrix()); + return box.pos(parent_space_pos); + } + box.pos(_position); +} + +Vec2 View::position(Space origin) const +{ + if ( origin == PARENT_SPACE ) + { + return Vec2::transform(box.pos(), parent_content_region.model_matrix() ); + } + return box.pos(); } -bool View::is_visible() const +void View::translate( Vec2 _delta) { - return m_is_visible; + Vec2 new_pos = position( WORLD_SPACE ) + _delta; + position( new_pos, WORLD_SPACE ); } -bool View::is_hovered() const +bool View::draw() { - return m_is_hovered; + // Get the content region's top left corner + // This will be used later to convert coordinates between WORLD_SPACE and PARENT_SPACE + parent_content_region = ImGuiEx::GetContentRegion( WORLD_SPACE ); + + return onDraw(); } -void View::use_available_region(View* view, ImRect rect) +Rect View::rect(Space space) const { - if( rect.GetHeight() == 0 || rect.GetWidth() == 0) { - view->m_screen_space_content_region = fw::ImGuiEx::GetContentRegion(fw::Space_Screen); - view->m_local_space_content_region = fw::ImGuiEx::GetContentRegion(fw::Space_Local); - } else { - view->m_screen_space_content_region = rect; + Rect r = box.rect(); + if( space == PARENT_SPACE) + { + assert(false); } + return r; } diff --git a/src/fw/gui/View.h b/src/fw/gui/View.h index 5e46fb2df..c1b57f743 100644 --- a/src/fw/gui/View.h +++ b/src/fw/gui/View.h @@ -1,7 +1,10 @@ #pragma once -#include "ImGuiEx.h" -#include "../core/reflection/reflection" +#include "fw/core/geometry/Box2D.h" +#include "fw/core/geometry/Rect.h" +#include "fw/core/reflection/reflection" + +#include "ImGuiEx.h" // ImGui with extensions namespace fw { @@ -12,18 +15,20 @@ namespace fw class View { public: + bool is_visible; + bool is_hovered; + View(); virtual ~View() = default; - virtual bool draw() = 0; - void set_visible(bool _visibility); // show/hide view - bool is_visible()const; // check if visible - bool is_hovered()const; // check if hovered + bool draw(); + virtual bool onDraw() = 0; + fw::Vec2 position(Space) const; // Get position in a given Space + void position(Vec2 _delta, Space ); // Set position in a given Space + Rect rect(Space) const; // Get rectangle in a given Space + void translate(Vec2 _delta); protected: - static void use_available_region(View* , ImRect rect = ImRect()); // update m_xxx_space_content_region with available space or given rectangle - bool m_is_visible; - bool m_is_hovered; - ImRect m_screen_space_content_region; // view rectangle in screen space coordinates - ImRect m_local_space_content_region; // view rectangle in window space coordinates + Box2D parent_content_region; + Box2D box; // Screen space Box2D REFLECT_BASE_CLASS() }; } diff --git a/src/nodable/app/CMakeLists.txt b/src/nodable/app/CMakeLists.txt deleted file mode 100644 index 234e616f9..000000000 --- a/src/nodable/app/CMakeLists.txt +++ /dev/null @@ -1,34 +0,0 @@ - -# WARNING: Do not use this CMakeLists.txt directly, take the one from base directory. - -ndbl_log_title_header() - -# add nodable executable -add_executable( - nodable-app - WIN32 - main.cpp - ) - -target_link_libraries( - nodable-app - PUBLIC - nodable-gui -) - -set_target_properties(nodable-app PROPERTIES POSITION_INDEPENDENT_CODE FALSE) # required to run well on recent os (ex: ubuntu) -set_target_properties(nodable-app PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY "${BUILD_PATH}") # fix working directory for visual studio -set_target_properties(nodable-app PROPERTIES OUTPUT_NAME "nodable" ) - -set(README "${PROJECT_SOURCE_DIR}/README.md") -set(LICENSE "${PROJECT_SOURCE_DIR}/LICENSE") - -configure_file("${README}" . COPYONLY) -configure_file("${LICENSE}" . COPYONLY) - -# Installation : -#=============== - -install(TARGETS nodable-app DESTINATION . RUNTIME PERMISSIONS OWNER_EXECUTE OWNER_READ OWNER_WRITE ) -install(DIRECTORY "${CMAKE_BINARY_DIR}/assets" DESTINATION .) -install(FILES ${LICENSE} ${README} DESTINATION .) \ No newline at end of file diff --git a/src/nodable/app/main.cpp b/src/nodable/app/main.cpp index 632ea590e..329bdddfc 100644 --- a/src/nodable/app/main.cpp +++ b/src/nodable/app/main.cpp @@ -1,11 +1,14 @@ #include "nodable/gui/Nodable.h" +using namespace fw; +using namespace ndbl; + int main(int argc, char *argv[]) { #ifdef NDBL_DEBUG - fw::log::set_verbosity(fw::log::Verbosity_Warning); - fw::log::set_verbosity("Pool", fw::log::Verbosity_Verbose); + log::set_verbosity(log::Verbosity_Warning); + log::set_verbosity("Pool", log::Verbosity_Verbose); #endif - ndbl::Nodable app; // Instantiate app + Nodable app; // Instantiate app return app.main(argc, argv); // Run main loop } diff --git a/src/nodable/cli/CLI.cpp b/src/nodable/cli/CLI.cpp index 044166460..da5fb9693 100644 --- a/src/nodable/cli/CLI.cpp +++ b/src/nodable/cli/CLI.cpp @@ -8,10 +8,11 @@ #include "core/language/Nodlang.h" using namespace ndbl; +using namespace fw; REGISTER { - fw::registration::push_class("CLI") + registration::push_class("CLI") .add_method(&CLI::test_concat_str , "concat_str") .add_method(&CLI::test_return_str , "return_str") .add_method(&CLI::clear , "clear") @@ -32,7 +33,7 @@ CLI::CLI() , m_graph(&m_factory) { std::cout << R"(== Nodable command line interface ==)" << std::endl << - R"(Nodable Copyright (C) 2023 Bérenger DALLE-CORT. This program comes with ABSOLUTELY NO WARRANTY. )" + R"(Nodable Copyright (C) 2023-2024 Bérenger DALLE-CORT. This program comes with ABSOLUTELY NO WARRANTY. )" R"(This is free software, and you are welcome to redistribute it under certain conditions.)" << std::endl << R"(Feel lost? type "help".)" << std::endl; } @@ -47,8 +48,8 @@ CLI::~CLI() int CLI::main(int argc, char* argv[]) { - fw::log::set_verbosity(fw::log::Verbosity_Warning); - fw::Pool::init(); + log::set_verbosity(log::Verbosity_Warning); + Pool::init(); while (!should_stop()) { @@ -56,7 +57,7 @@ int CLI::main(int argc, char* argv[]) } m_graph.clear(); - fw::Pool::shutdown(); + Pool::shutdown(); LOG_FLUSH() return 0; } @@ -83,12 +84,12 @@ void CLI::update() } // Priority 1: call a static function immediately - const fw::type* cli_type = fw::type::get(); + const type* cli_type = type::get(); if( auto static_fct = cli_type->get_static(user_input) ) { try { - fw::variant result = static_fct->invoke(); + variant result = static_fct->invoke(); log_function_call(result, static_fct->get_type()); } catch (std::runtime_error e ) @@ -104,7 +105,7 @@ void CLI::update() try { // then we invoke it - fw::variant result = method->invoke((void*)this); + variant result = method->invoke((void*)this); log_function_call(result, method->get_type()); } catch (std::runtime_error e ) @@ -120,7 +121,7 @@ void CLI::update() m_language.parse(m_source_code, &m_graph) && compile() && run(); } -void CLI::log_function_call(const fw::variant &result, const fw::func_type *type) const +void CLI::log_function_call(const variant &result, const func_type *type) const { LOG_MESSAGE("CLI", "CLI::%s() done (result: %s)\n", @@ -177,7 +178,7 @@ bool CLI::compile() void CLI::set_verbose() { printf("Verbose mode ON\n"); - fw::log::set_verbosity(fw::log::Verbosity_Verbose); + log::set_verbosity(log::Verbosity_Verbose); } int CLI::print_program() @@ -207,7 +208,7 @@ bool CLI::run() if( m_virtual_machine.load_program(m_asm_code) ) { m_virtual_machine.run_program(); - fw::qword last_result = m_virtual_machine.get_last_result(); + qword last_result = m_virtual_machine.get_last_result(); printf( "bool: %s | int: %12f | double: %12d | hex: %12s\n" , (bool)last_result ? "true" : "false" @@ -229,7 +230,7 @@ void CLI::help() { std::vector command_names; - const fw::type* cli_type = fw::type::get(); + const type* cli_type = type::get(); for ( auto static_method_type : cli_type->get_static_methods() ) { @@ -253,7 +254,7 @@ void CLI::help() void CLI::clear() { m_source_code.clear(); - fw::system::console::clear(); + system::console::clear(); delete m_asm_code; m_graph.clear(); m_virtual_machine.release_program(); diff --git a/src/nodable/cli/CLI.h b/src/nodable/cli/CLI.h index da62002af..8d1e7a29f 100644 --- a/src/nodable/cli/CLI.h +++ b/src/nodable/cli/CLI.h @@ -4,11 +4,11 @@ #include "fw/core/reflection/reflection" -#include "core/language/Nodlang.h" -#include "core/NodeFactory.h" -#include "core/Graph.h" -#include "core/VirtualMachine.h" -#include "core/assembly/Compiler.h" +#include "nodable/core/language/Nodlang.h" +#include "nodable/core/NodeFactory.h" +#include "nodable/core/Graph.h" +#include "nodable/core/VirtualMachine.h" +#include "nodable/core/assembly/Compiler.h" namespace ndbl { diff --git a/src/nodable/cli/CMakeLists.txt b/src/nodable/cli/CMakeLists.txt deleted file mode 100644 index c97001324..000000000 --- a/src/nodable/cli/CMakeLists.txt +++ /dev/null @@ -1,40 +0,0 @@ - -# WARNING: Do not use this CMakeLists.txt directly, take the one from base directory. - -ndbl_log_title_header() - -# checks -ndbl_log("Checking ...") -if( NOT NDBL_CONFIGURED_DIR ) - ndbl_err("Variable NDBL_CONFIGURED_DIR must be set in main CMakeLists.txt") -endif() - -# add nodable executable -add_executable( - nodable-cli - main.cpp - CLI.cpp) - -find_package(Threads REQUIRED) -if (NOT Threads_FOUND) - ndbl_err("Threads not found") -endif() - -target_link_libraries( - nodable-cli - PRIVATE - nodable-core - Threads::Threads -) - -set_target_properties(nodable-cli PROPERTIES POSITION_INDEPENDENT_CODE FALSE) # required to run well on recent os (ex: ubuntu) -set_target_properties(nodable-cli PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY "${BUILD_PATH}") # fix working directory for visual studio -set_target_properties(nodable-cli PROPERTIES OUTPUT_NAME "cli" ) - -# AFTER BUILD: -#============= - -# Installation : -#=============== - -install( TARGETS nodable-cli DESTINATION bin RUNTIME PERMISSIONS OWNER_EXECUTE OWNER_READ OWNER_WRITE ) diff --git a/src/nodable/core/CMakeLists.txt b/src/nodable/core/CMakeLists.txt deleted file mode 100644 index b7e215dd9..000000000 --- a/src/nodable/core/CMakeLists.txt +++ /dev/null @@ -1,93 +0,0 @@ -# WARNING: Do not use this CMakeLists.txt directly, take the one from base directory. -include(../../../scripts/cmake/log.cmake) -ndbl_log_title_header() - -add_library( - nodable-core - STATIC - Component.cpp - ComponentBag.cpp - IfNode.cpp - DataAccess.cpp - DirectedEdge.cpp - ForLoopNode.cpp - Graph.cpp - GraphUtil.cpp - InvokableComponent.cpp - LiteralNode.cpp - Node.cpp - NodeFactory.cpp - Property.cpp - PropertyBag.cpp - Scope.cpp - Slot.cpp - SlotRef.cpp - Token.cpp - TokenRibbon.cpp - VariableNode.cpp - VirtualMachine.cpp - WhileLoopNode.cpp - assembly/Code.cpp - assembly/Compiler.cpp - assembly/Instruction.cpp - language/Nodlang.cpp - language/Nodlang_biology.cpp - language/Nodlang_math.cpp -) - -target_link_libraries( - nodable-core - PUBLIC # <-------------- Those will be accessible by other targets if they link nodable-core - framework-core -) - -target_include_directories( - nodable-core - PUBLIC - ../../../src - ../../nodable -) - -ndbl_log("Defining install ...") -set_target_properties(nodable-core PROPERTIES OUTPUT_NAME "core" ) - -#install( TARGETS nodable-core ARCHIVE DESTINATION "libs") -#install( DIRECTORY include DESTINATION "libs" FILES_MATCHING PATTERN "*.h") - -ndbl_log_title_header() - -# WARNING: Do not use this CMakeLists.txt directly, take the one from base directory. - -ndbl_log("NDBL_SKIP_TESTS: ${NDBL_SKIP_TESTS}") - -if ( NDBL_SKIP_TESTS ) - return() -endif() - -# Headless tests (nodable-core) -#------------------------------ - -add_executable( - test-nodable-core - Graph.specs.cpp - Node.specs.cpp - Property.specs.cpp - Slot.specs.cpp - Token.specs.cpp - language/Nodlang.specs.cpp - language/Nodlang.tokenize.specs.cpp - language/Nodlang.parse_function_call.specs.cpp - language/Nodlang.parse_token.specs.cpp - VirtualMachine.specs.cpp - language/Nodlang.parse_and_eval.specs.cpp - ) -target_link_libraries(test-nodable-core PRIVATE gtest_main gtest nodable-core ) -add_test( NAME test_nodable_core COMMAND test-nodable-core ) - -# Benchmarks -#----------- - -# Nodlang -add_executable( bench-nodable-core-Nodlang language/Nodlang.bench.cpp ) -target_link_libraries( bench-nodable-core-Nodlang PRIVATE benchmark::benchmark nodable-core framework-core ) - diff --git a/src/nodable/core/Component.cpp b/src/nodable/core/Component.cpp index b403ab3a7..52232c2ee 100644 --- a/src/nodable/core/Component.cpp +++ b/src/nodable/core/Component.cpp @@ -2,11 +2,11 @@ #include "Node.h" using namespace ndbl; -using fw::PoolID; +using namespace fw; REGISTER { - fw::registration::push_class("Component"); + registration::push_class("Component"); } Component::Component() diff --git a/src/nodable/core/Component.h b/src/nodable/core/Component.h index 7b410689c..24c51983a 100644 --- a/src/nodable/core/Component.h +++ b/src/nodable/core/Component.h @@ -1,7 +1,7 @@ #pragma once #include "fw/core/reflection/reflection" -#include "fw/core/Pool.h" +#include "fw/core/memory/Pool.h" namespace ndbl { diff --git a/src/nodable/core/ComponentBag.cpp b/src/nodable/core/ComponentBag.cpp index 00e819a15..cc0a1e414 100644 --- a/src/nodable/core/ComponentBag.cpp +++ b/src/nodable/core/ComponentBag.cpp @@ -8,7 +8,7 @@ void ComponentBag::add(PoolID id) { Component* component = id.get(); - const fw::type* type = component->get_type(); + const type* type = component->get_type(); std::type_index type_id = type->id(); m_components_by_type.emplace( type_id, id ); diff --git a/src/nodable/core/ComponentBag.h b/src/nodable/core/ComponentBag.h index 94894e8ba..d81a51909 100644 --- a/src/nodable/core/ComponentBag.h +++ b/src/nodable/core/ComponentBag.h @@ -1,6 +1,6 @@ #pragma once +#include "fw/core/memory/Pool.h" #include "fw/core/reflection/reflection" -#include "fw/core/Pool.h" #include namespace ndbl { diff --git a/src/nodable/core/DataAccess.cpp b/src/nodable/core/DataAccess.cpp index 8c99831b7..5722cdb86 100644 --- a/src/nodable/core/DataAccess.cpp +++ b/src/nodable/core/DataAccess.cpp @@ -7,14 +7,16 @@ #include #include "fw/core/assertions.h" -#include "fw/core/Pool.h" -#include "core/Node.h" +#include "fw/core/memory/Pool.h" + +#include "Node.h" using namespace ndbl; +using namespace fw; REGISTER { - fw::registration::push_class("DataAccess") + registration::push_class("DataAccess") .extends(); } @@ -30,7 +32,7 @@ bool DataAccess::update() writer.Key(property.get_name().c_str()); auto& value = *property.value(); - const fw::type* type = value.get_type(); + const type* type = value.get_type(); if (type->is() ) writer.String((const char*)value); else if (type->is() ) writer.Double((double)value); diff --git a/src/nodable/core/DataAccess.h b/src/nodable/core/DataAccess.h index 96c5a09fa..883d852d2 100644 --- a/src/nodable/core/DataAccess.h +++ b/src/nodable/core/DataAccess.h @@ -2,7 +2,7 @@ #include "fw/core/types.h" #include "fw/core/reflection/reflection" -#include "core/Component.h" +#include "Component.h" namespace ndbl { diff --git a/src/nodable/core/ForLoopNode.cpp b/src/nodable/core/ForLoopNode.cpp index 741cd4218..f181a6a3f 100644 --- a/src/nodable/core/ForLoopNode.cpp +++ b/src/nodable/core/ForLoopNode.cpp @@ -3,10 +3,11 @@ #include "GraphUtil.h" using namespace ndbl; +using namespace fw; REGISTER { - fw::registration::push_class("ForLoopNode") + registration::push_class("ForLoopNode") .extends() .extends(); } diff --git a/src/nodable/core/Graph.cpp b/src/nodable/core/Graph.cpp index ab3ef2b84..ce63f040f 100644 --- a/src/nodable/core/Graph.cpp +++ b/src/nodable/core/Graph.cpp @@ -13,6 +13,7 @@ #include "language/Nodlang.h" using namespace ndbl; +using namespace fw; Graph::Graph( const NodeFactory* _factory @@ -113,33 +114,33 @@ void Graph::ensure_has_root() } } -PoolID Graph::create_variable(const fw::type *_type, const std::string& _name, PoolID _scope) +PoolID Graph::create_variable(const type *_type, const std::string& _name, PoolID _scope) { PoolID node = m_factory->create_variable(_type, _name, _scope); add(node); return node; } -PoolID Graph::create_abstract_function(const fw::func_type* _invokable, bool _is_operator) +PoolID Graph::create_abstract_function(const func_type* _invokable, bool _is_operator) { PoolID node = m_factory->create_abstract_func(_invokable, _is_operator); add(node); return node; } -PoolID Graph::create_function(const fw::iinvokable* _invokable, bool _is_operator) +PoolID Graph::create_function(const iinvokable* _invokable, bool _is_operator) { PoolID node = m_factory->create_func(_invokable, _is_operator); add(node); return node; } -PoolID Graph::create_abstract_operator(const fw::func_type* _invokable) +PoolID Graph::create_abstract_operator(const func_type* _invokable) { return create_abstract_function(_invokable, true); } -PoolID Graph::create_operator(const fw::iinvokable* _invokable) +PoolID Graph::create_operator(const iinvokable* _invokable) { return create_function(_invokable, true); } @@ -168,7 +169,7 @@ void Graph::destroy(PoolID _id) }; // if it is a variable, we remove it from its scope - if ( auto* node_variable = fw::cast(node) ) + if ( auto* node_variable = cast(node) ) { if ( IScope* scope = node_variable->get_scope().get() ) { @@ -211,9 +212,9 @@ DirectedEdge* Graph::connect_or_merge(Slot&_out, Slot& _in ) FW_EXPECT( in_prop, "tail property must be defined" ) FW_EXPECT( out_prop, "head property must be defined" ) FW_EXPECT( in_prop != out_prop, "Can't connect same properties!" ) - const fw::type* out_type = out_prop->get_type(); - const fw::type* in_type = in_prop->get_type(); - FW_EXPECT( fw::type::is_implicitly_convertible( out_type, in_type ), "dependency type should be implicitly convertible to dependent type"); + const type* out_type = out_prop->get_type(); + const type* in_type = in_prop->get_type(); + FW_EXPECT( type::is_implicitly_convertible( out_type, in_type ), "dependency type should be implicitly convertible to dependent type"); // case 1: merge orphan slot if ( _out.get_node() == nullptr ) // if dependent is orphan @@ -505,14 +506,14 @@ PoolID Graph::create_node() return node; } -PoolID Graph::create_literal(const fw::type *_type) +PoolID Graph::create_literal(const type *_type) { PoolID node = m_factory->create_literal(_type); add(node); return node; } -PoolID Graph::create_node( NodeType _type, const fw::func_type* _signature ) +PoolID Graph::create_node( NodeType _type, const func_type* _signature ) { switch ( _type ) { @@ -550,7 +551,7 @@ PoolID Graph::create_node( NodeType _type, const fw::func_type* _signature } } -PoolID Graph::create_variable_decl(const fw::type* _type, const char* _name, PoolID _scope) +PoolID Graph::create_variable_decl(const type* _type, const char* _name, PoolID _scope) { if( !_scope) { diff --git a/src/nodable/core/Graph.specs.cpp b/src/nodable/core/Graph.specs.cpp index 7416d0e6d..bd0c35c3d 100644 --- a/src/nodable/core/Graph.specs.cpp +++ b/src/nodable/core/Graph.specs.cpp @@ -1,18 +1,17 @@ #include -#include "core/DirectedEdge.h" -#include "fixtures/core.h" #include "fw/core/reflection/func_type.h" -#include "nodable/core/Graph.h" -#include "nodable/core/InvokableComponent.h" -#include "nodable/core/Node.h" -#include "nodable/core/NodeFactory.h" -#include "nodable/core/Property.h" -#include "nodable/core/Scope.h" -#include "nodable/core/VariableNode.h" -#include "nodable/core/language/Nodlang.h" + +#include "Graph.h" +#include "InvokableComponent.h" +#include "Node.h" +#include "Scope.h" +#include "DirectedEdge.h" + +#include "fixtures/core.h" using namespace ndbl; +using namespace fw; typedef ::testing::Core Graph_; TEST_F(Graph_, connect) @@ -64,8 +63,8 @@ TEST_F(Graph_, clear) EXPECT_TRUE( graph.get_node_registry().empty() ); EXPECT_TRUE( graph.get_edge_registry().empty() ); - auto variable = graph.create_variable( fw::type::get(), "var", PoolID::null); - fw::func_type* fct_type = fw::func_type_builder::with_id("+"); + auto variable = graph.create_variable( type::get(), "var", PoolID::null); + func_type* fct_type = func_type_builder::with_id("+"); auto operator_fct = nodlang.find_operator_fct_exact(fct_type); EXPECT_TRUE(operator_fct.get() != nullptr); diff --git a/src/nodable/core/IScope.h b/src/nodable/core/IScope.h index 44a61704a..9642e9789 100644 --- a/src/nodable/core/IScope.h +++ b/src/nodable/core/IScope.h @@ -1,9 +1,9 @@ #pragma once #include +#include "fw/core/memory/Pool.h" #include "fw/core/reflection/reflection" #include "fw/core/types.h" -#include "fw/core/Pool.h" namespace ndbl { diff --git a/src/nodable/core/IfNode.cpp b/src/nodable/core/IfNode.cpp index 0603e37ba..267c701d6 100644 --- a/src/nodable/core/IfNode.cpp +++ b/src/nodable/core/IfNode.cpp @@ -2,11 +2,11 @@ #include "IfNode.h" using namespace ndbl; +using namespace fw; REGISTER { - using namespace ndbl; - fw::registration::push_class("IfNode") + registration::push_class("IfNode") .extends() .extends(); } diff --git a/src/nodable/core/InstructionNode.h b/src/nodable/core/InstructionNode.h index 005e14179..d50bced1e 100644 --- a/src/nodable/core/InstructionNode.h +++ b/src/nodable/core/InstructionNode.h @@ -4,9 +4,8 @@ #include #include "fw/core/types.h" -#include "core/Node.h" // base class -#include "core/Property.h" - +#include "Node.h" // base class +#include "Property.h" namespace ndbl { diff --git a/src/nodable/core/InvokableComponent.cpp b/src/nodable/core/InvokableComponent.cpp index 68054f40b..83ebe04d9 100644 --- a/src/nodable/core/InvokableComponent.cpp +++ b/src/nodable/core/InvokableComponent.cpp @@ -1,17 +1,17 @@ #include "InvokableComponent.h" #include "fw/core/log.h" +#include "fw/core/memory/Pool.h" #include "fw/core/reflection/func_type.h" -#include "fw/core/Pool.h" -#include "core/VariableNode.h" +#include "VariableNode.h" using namespace ndbl; -using fw::ID; +using namespace fw; REGISTER { - fw::registration::push_class("InvokableComponent").extends(); + registration::push_class("InvokableComponent").extends(); } InvokableComponent::InvokableComponent() @@ -21,7 +21,7 @@ InvokableComponent::InvokableComponent() , m_is_operator( false ) {} -InvokableComponent::InvokableComponent(const fw::func_type* _signature, bool _is_operator, const fw::iinvokable* _invokable) +InvokableComponent::InvokableComponent(const func_type* _signature, bool _is_operator, const iinvokable* _invokable) : Component() , m_signature( _signature ) , m_invokable( nullptr) @@ -45,7 +45,7 @@ bool InvokableComponent::update() // Gather the variants from argument slots // TODO: consider removing this dynamic allocation // we could simply dereference each Property within invoke() - std::vector variants; + std::vector variants; for(auto& slot: m_argument_slot ) { Property* property = slot->get_property(); @@ -60,7 +60,7 @@ bool InvokableComponent::update() } } FW_ASSERT( m_argument_slot.size() == variants.size()) - fw::variant result = m_invokable->invoke( variants ); + variant result = m_invokable->invoke( variants ); m_result_slot->get_property()->set( result); for( auto* variant : variants ) variant->flag_defined(true); } diff --git a/src/nodable/core/InvokableComponent.h b/src/nodable/core/InvokableComponent.h index 71ceae8ce..d0f74e121 100644 --- a/src/nodable/core/InvokableComponent.h +++ b/src/nodable/core/InvokableComponent.h @@ -4,10 +4,10 @@ #include "fw/core/types.h" #include "fw/core/reflection/reflection" -#include "core/DirectedEdge.h" -#include "core/Component.h" -#include "core/Property.h" -#include "core/Token.h" +#include "DirectedEdge.h" +#include "Component.h" +#include "Property.h" +#include "Token.h" namespace ndbl { diff --git a/src/nodable/core/LiteralNode.cpp b/src/nodable/core/LiteralNode.cpp index 8349b7cbe..0ceb108b1 100644 --- a/src/nodable/core/LiteralNode.cpp +++ b/src/nodable/core/LiteralNode.cpp @@ -1,13 +1,14 @@ #include "LiteralNode.h" using namespace ndbl; +using namespace fw; REGISTER { - fw::registration::push_class("LiteralNode").extends(); + registration::push_class("LiteralNode").extends(); } -LiteralNode::LiteralNode(const fw::type* _type) +LiteralNode::LiteralNode(const type* _type) : Node() , m_type( _type ) { diff --git a/src/nodable/core/LiteralNode.h b/src/nodable/core/LiteralNode.h index 9cc643a9e..9e4189134 100644 --- a/src/nodable/core/LiteralNode.h +++ b/src/nodable/core/LiteralNode.h @@ -1,7 +1,7 @@ #pragma once #include // std::shared_ptr #include "fw/core/reflection/reflection" -#include "core/Node.h" // Base class +#include "Node.h" // Base class namespace ndbl { diff --git a/src/nodable/core/Node.cpp b/src/nodable/core/Node.cpp index 430d25515..efd65e180 100644 --- a/src/nodable/core/Node.cpp +++ b/src/nodable/core/Node.cpp @@ -1,21 +1,20 @@ #include "Node.h" -#include "ForLoopNode.h" -#include "core/Scope.h" #include #include // for std::find +#include "ForLoopNode.h" +#include "Scope.h" #include "Graph.h" #include "GraphUtil.h" #include "InvokableComponent.h" using namespace ndbl; -using fw::Pool; +using namespace fw; REGISTER { - using namespace ndbl; - fw::registration::push_class("Node"); + registration::push_class("Node"); } Node::Node(std::string _label) @@ -68,7 +67,7 @@ size_t Node::adjacent_slot_count(SlotFlags _flags )const return filter_adjacent_slots( _flags ).size(); } -const fw::iinvokable* Node::get_connected_invokable(const char* property_name) const +const iinvokable* Node::get_connected_invokable(const char* property_name) const { const Slot& slot = *find_slot_by_property_name( property_name, SlotFlag_INPUT ); const SlotRef adjacent_slot = slot.first_adjacent(); @@ -203,11 +202,11 @@ std::vector> Node::filter_adjacent( SlotFlags _flags ) const return GraphUtil::get_adjacent_nodes(this, _flags); } -Slot* Node::find_slot_by_property_type(SlotFlags flags, const fw::type* _type) +Slot* Node::find_slot_by_property_type(SlotFlags flags, const type* _type) { for(Slot* slot : filter_slots( flags ) ) { - if( fw::type::is_implicitly_convertible( slot->get_property()->get_type(), _type ) ) + if( type::is_implicitly_convertible( slot->get_property()->get_type(), _type ) ) { return slot; } @@ -232,7 +231,7 @@ Slot & Node::get_nth_slot( u8_t _n, SlotFlags _flags ) FW_EXPECT(false, "Not found") } -ID Node::add_prop(const fw::type *_type, const char *_name, PropertyFlags _flags) +ID Node::add_prop(const type *_type, const char *_name, PropertyFlags _flags) { return props.add(_type, _name, _flags); } diff --git a/src/nodable/core/Node.h b/src/nodable/core/Node.h index c8c60bf11..e3c29293c 100644 --- a/src/nodable/core/Node.h +++ b/src/nodable/core/Node.h @@ -6,9 +6,9 @@ #include #include "fw/core/assertions.h" +#include "fw/core/memory/Pool.h" #include "fw/core/reflection/reflection" #include "fw/core/types.h" -#include "fw/core/Pool.h" #include "ComponentBag.h" #include "DirectedEdge.h" diff --git a/src/nodable/core/Node.specs.cpp b/src/nodable/core/Node.specs.cpp index 4be0a21c7..4c800e1c0 100644 --- a/src/nodable/core/Node.specs.cpp +++ b/src/nodable/core/Node.specs.cpp @@ -1,5 +1,5 @@ #include "nodable/core/Scope.h" -#include "core/fixtures/core.h" +#include "fixtures/core.h" #include using namespace ndbl; diff --git a/src/nodable/core/NodeFactory.cpp b/src/nodable/core/NodeFactory.cpp index 3e02f8277..65a95295b 100644 --- a/src/nodable/core/NodeFactory.cpp +++ b/src/nodable/core/NodeFactory.cpp @@ -15,15 +15,14 @@ #include "WhileLoopNode.h" using namespace ndbl; -using fw::Pool; - +using namespace fw; NodeFactory::NodeFactory() : m_post_process([](PoolID _node){}) , m_post_process_is_overrided(false) {} -PoolID NodeFactory::create_variable(const fw::type *_type, const std::string& _name, PoolID _scope) const +PoolID NodeFactory::create_variable(const type *_type, const std::string& _name, PoolID _scope) const { // create auto node = Pool::get_pool()->create(_type, _name.c_str()); @@ -42,7 +41,7 @@ PoolID NodeFactory::create_variable(const fw::type *_type, const s return node; } -PoolID NodeFactory::create_abstract_func(const fw::func_type* _signature, bool _is_operator) const +PoolID NodeFactory::create_abstract_func(const func_type* _signature, bool _is_operator) const { PoolID node = _create_abstract_func(_signature, _is_operator); add_invokable_component(node, _signature, nullptr, _is_operator ); @@ -50,7 +49,7 @@ PoolID NodeFactory::create_abstract_func(const fw::func_type* _signature, return node; } -PoolID NodeFactory::_create_abstract_func(const fw::func_type* _func_type, bool _is_operator) const +PoolID NodeFactory::_create_abstract_func(const func_type* _func_type, bool _is_operator) const { PoolID node = Pool::get_pool()->create(); node->init(); @@ -116,17 +115,17 @@ PoolID NodeFactory::_create_abstract_func(const fw::func_type* _func_type, return node; } -PoolID NodeFactory::create_func(const fw::iinvokable* _function, bool _is_operator) const +PoolID NodeFactory::create_func(const iinvokable* _function, bool _is_operator) const { // Create an abstract function node - const fw::func_type* type = _function->get_type(); + const func_type* type = _function->get_type(); PoolID node = _create_abstract_func(type, _is_operator); add_invokable_component(node, type, _function, _is_operator); m_post_process(node); return node; } -void NodeFactory::add_invokable_component(PoolID _node, const fw::func_type* _func_type, const fw::iinvokable *_invokable, bool _is_operator) const +void NodeFactory::add_invokable_component(PoolID _node, const func_type* _func_type, const iinvokable *_invokable, bool _is_operator) const { // Create an InvokableComponent with the function. PoolID component = Pool::get_pool()->create(_func_type, _is_operator, _invokable); @@ -221,7 +220,7 @@ PoolID NodeFactory::create_node() const return node; } -PoolID NodeFactory::create_literal(const fw::type *_type) const +PoolID NodeFactory::create_literal(const type *_type) const { PoolID node = Pool::get_pool()->create(_type); node->init(); diff --git a/src/nodable/core/NodeFactory.h b/src/nodable/core/NodeFactory.h index 4cfeb6b4b..d0074755c 100644 --- a/src/nodable/core/NodeFactory.h +++ b/src/nodable/core/NodeFactory.h @@ -1,13 +1,12 @@ #pragma once - #include // std::shared_ptr #include // std::function -#include "core/ForLoopNode.h" -#include "core/IfNode.h" -#include "core/WhileLoopNode.h" #include "fw/core/reflection/reflection" +#include "ForLoopNode.h" +#include "IfNode.h" +#include "WhileLoopNode.h" #include "IScope.h" namespace ndbl diff --git a/src/nodable/core/NodeUtils.h b/src/nodable/core/NodeUtils.h index c281a2c3c..4faf68d40 100644 --- a/src/nodable/core/NodeUtils.h +++ b/src/nodable/core/NodeUtils.h @@ -1,8 +1,8 @@ #pragma once -#include -#include -#include "fw/core/Pool.h" #include "Node.h" +#include "fw/core/memory/Pool.h" +#include +#include namespace ndbl { diff --git a/src/nodable/core/Property.cpp b/src/nodable/core/Property.cpp index 177314229..3b80539b7 100644 --- a/src/nodable/core/Property.cpp +++ b/src/nodable/core/Property.cpp @@ -2,9 +2,10 @@ #include "PropertyBag.h" #include "VariableNode.h" -#include "fw/core/Pool.h" +#include "fw/core/memory/Pool.h" using namespace ndbl; +using namespace fw; Property::Property() : m_name("Unknown") @@ -34,7 +35,7 @@ Property::Property(const std::string &s) {} -Property::Property(const fw::type* _type, PropertyFlags _flags) +Property::Property(const type* _type, PropertyFlags _flags) : Property() { // handle type @@ -55,9 +56,9 @@ void Property::digest(Property* _property) token = std::move( _property->token ); } -std::vector Property::get(std::vector _in_properties ) +std::vector Property::get(std::vector _in_properties ) { - std::vector result; + std::vector result; result.reserve(_in_properties.size()); for(Property* each_property : _in_properties) { @@ -78,7 +79,7 @@ bool Property::is_ref() const bool Property::is_type_null() const { - return get_type()->is(); + return get_type()->is(); } bool Property::has_flags( PropertyFlags _flags ) const diff --git a/src/nodable/core/Property.h b/src/nodable/core/Property.h index f2d08af03..63f31c51f 100644 --- a/src/nodable/core/Property.h +++ b/src/nodable/core/Property.h @@ -1,9 +1,9 @@ #pragma once -#include "fw/core/types.h" // for constants and forward declarations +#include "nodable/core/Token.h" +#include "fw/core/memory/Pool.h" #include "fw/core/reflection/variant.h" -#include "fw/core/Pool.h" -#include "core/Token.h" +#include "fw/core/types.h"// for constants and forward declarations #include #include diff --git a/src/nodable/core/Property.specs.cpp b/src/nodable/core/Property.specs.cpp index 50abf4c85..5dc99a1ec 100644 --- a/src/nodable/core/Property.specs.cpp +++ b/src/nodable/core/Property.specs.cpp @@ -1,6 +1,6 @@ -#include -#include "fw/core/Pool.h" #include "Property.h" +#include "fw/core/memory/Pool.h" +#include using namespace ndbl; using namespace fw; @@ -11,7 +11,7 @@ TEST(Property, Type_Boolean) property.set(true); EXPECT_TRUE((bool)*property); - EXPECT_EQ(property.get_type(), fw::type::get()); + EXPECT_EQ(property.get_type(), type::get()); property.set(false); EXPECT_FALSE((bool)*property); @@ -27,7 +27,7 @@ TEST(Property, Type_String) EXPECT_EQ((std::string)*property, str); EXPECT_TRUE(property.to()); - EXPECT_EQ(property.get_type(), fw::type::get()); + EXPECT_EQ(property.get_type(), type::get()); EXPECT_TRUE(property->is_defined()); } @@ -37,7 +37,7 @@ TEST(Property, Type_Double) property.set((double)50); EXPECT_EQ((double)50, (double)*property); - EXPECT_EQ(property.get_type(), fw::type::get()); + EXPECT_EQ(property.get_type(), type::get()); EXPECT_TRUE(property->is_defined()); } @@ -47,7 +47,7 @@ TEST(Property, Modify_by_reference_using_a_pointer) property.set(50.0); EXPECT_EQ((double)*property, 50.0); - EXPECT_EQ(property.get_type(), fw::type::get()); + EXPECT_EQ(property.get_type(), type::get()); EXPECT_TRUE(property->is_defined()); double& ref = (double&)*property; @@ -62,7 +62,7 @@ TEST(Property, Modify_by_reference_using_a_reference) Property property_2(50.0); EXPECT_EQ((double)*property_1, 50.0); - EXPECT_EQ(property_1.get_type(), fw::type::get()); + EXPECT_EQ(property_1.get_type(), type::get()); EXPECT_TRUE(property_1->is_defined()); auto add_right_to_left = [](double& a, double b) -> double { return a = a + b; }; diff --git a/src/nodable/core/PropertyBag.cpp b/src/nodable/core/PropertyBag.cpp index abffed89b..75a628140 100644 --- a/src/nodable/core/PropertyBag.cpp +++ b/src/nodable/core/PropertyBag.cpp @@ -2,18 +2,18 @@ #include "Node.h" using namespace ndbl; -using fw::ID; +using namespace fw; bool PropertyBag::has(const char* _name) const { return m_properties_by_name.find(_name) != m_properties_by_name.end(); } -ID PropertyBag::add(const fw::type* _type, const char* _name, PropertyFlags _flags ) +ID PropertyBag::add(const type* _type, const char* _name, PropertyFlags _flags ) { FW_ASSERT(!has(_name)); - ID id = (ID)m_properties.size(); // we cannot delete a property, so we can count on size() to get a unique id + auto id = (ID)m_properties.size(); // we cannot delete a property, so we can count on size() to get a unique id // create the property Property& new_property = m_properties.emplace_back(_type, _flags); @@ -26,22 +26,22 @@ ID PropertyBag::add(const fw::type* _type, const char* _name, Property return new_property.id; } -const Property* PropertyBag::find_first( PropertyFlags _flags, const fw::type *_type) const +const Property* PropertyBag::find_first( PropertyFlags _flags, const type *_type) const { return _find_first( _flags, _type ); } -Property* PropertyBag::find_first( PropertyFlags _flags, const fw::type *_type) +Property* PropertyBag::find_first( PropertyFlags _flags, const type *_type) { return const_cast( _find_first( _flags, _type ) ); } -const Property* PropertyBag::_find_first( PropertyFlags _flags, const fw::type *_type) const +const Property* PropertyBag::_find_first( PropertyFlags _flags, const type *_type) const { auto filter = [this, _flags, _type](const std::pair>& pair) -> bool { auto& property = m_properties[(u32_t)pair.second]; - return fw::type::is_implicitly_convertible( property.get_type(), _type) + return type::is_implicitly_convertible( property.get_type(), _type) && ( property.has_flags( _flags ) ); }; diff --git a/src/nodable/core/PropertyBag.h b/src/nodable/core/PropertyBag.h index b29cc8254..ff5a21de3 100644 --- a/src/nodable/core/PropertyBag.h +++ b/src/nodable/core/PropertyBag.h @@ -3,9 +3,9 @@ #include #include // std::shared_ptr +#include "fw/core/memory/Pool.h" #include "fw/core/reflection/reflection" #include "fw/core/types.h" -#include "fw/core/Pool.h" #include "constants.h" #include "Property.h" diff --git a/src/nodable/core/Scope.cpp b/src/nodable/core/Scope.cpp index dfc88db75..57908284a 100644 --- a/src/nodable/core/Scope.cpp +++ b/src/nodable/core/Scope.cpp @@ -4,7 +4,7 @@ #include // for std::find_if #include "fw/core/log.h" -#include "fw/core/Pool.h" +#include "fw/core/memory/Pool.h" #include "ForLoopNode.h" #include "IScope.h" @@ -12,11 +12,11 @@ #include "VariableNode.h" using namespace ndbl; -using fw::PoolID; +using namespace fw; REGISTER { - fw::registration::push_class("Scope"); + registration::push_class("Scope"); } Scope::Scope() diff --git a/src/nodable/core/Scope.h b/src/nodable/core/Scope.h index 6d110103c..7036a237b 100644 --- a/src/nodable/core/Scope.h +++ b/src/nodable/core/Scope.h @@ -1,7 +1,7 @@ #pragma once -#include "core/IScope.h" -#include "core/Token.h" +#include "IScope.h" +#include "Token.h" #include "Component.h" namespace ndbl diff --git a/src/nodable/core/Slot.h b/src/nodable/core/Slot.h index 60af759f8..01c037e7b 100644 --- a/src/nodable/core/Slot.h +++ b/src/nodable/core/Slot.h @@ -1,7 +1,7 @@ #pragma once #include "SlotFlag.h" +#include "fw/core/memory/Pool.h" #include "fw/core/types.h" -#include "fw/core/Pool.h" #include namespace ndbl diff --git a/src/nodable/core/SlotRef.h b/src/nodable/core/SlotRef.h index 21120034d..dbf4193ad 100644 --- a/src/nodable/core/SlotRef.h +++ b/src/nodable/core/SlotRef.h @@ -1,6 +1,6 @@ #pragma once #include "SlotFlag.h" -#include "fw/core/Pool.h" +#include "fw/core/memory/Pool.h" namespace ndbl { diff --git a/src/nodable/core/VariableNode.cpp b/src/nodable/core/VariableNode.cpp index de18962a3..9c01ea9b9 100644 --- a/src/nodable/core/VariableNode.cpp +++ b/src/nodable/core/VariableNode.cpp @@ -3,17 +3,18 @@ #include "Scope.h" using namespace ndbl; +using namespace fw; REGISTER { - fw::registration::push_class("VariableNode").extends(); + registration::push_class("VariableNode").extends(); } VariableNode::VariableNode() : Node("Variable") , m_is_declared(false) -, m_type(fw::type::any()) +, m_type(type::any()) { } @@ -44,12 +45,12 @@ PoolID VariableNode::get_scope() return scope_node ? scope_node->get_component() : PoolID{}; } -const fw::type *VariableNode::type() const +const type *VariableNode::type() const { return property()->get_type(); } -fw::variant* VariableNode::value() +variant* VariableNode::value() { return property()->value(); } diff --git a/src/nodable/core/VirtualMachine.cpp b/src/nodable/core/VirtualMachine.cpp index 3fe9e83ec..f4b12d1a2 100644 --- a/src/nodable/core/VirtualMachine.cpp +++ b/src/nodable/core/VirtualMachine.cpp @@ -17,25 +17,25 @@ void CPU::clear_registers() { for( size_t id = 0; id < std::size( m_register ); ++id ) { - write( (Register)id, fw::qword()); + write( (Register)id, qword()); } } -fw::qword CPU::read(Register _id)const +qword CPU::read(Register _id)const { LOG_VERBOSE("VM::CPU", "read register %s (value: %s)\n", assembly::to_string(_id), m_register[_id].to_string().c_str() ) return m_register[_id]; } -fw::qword& CPU::read_write(Register _id) +qword& CPU::read_write(Register _id) { LOG_VERBOSE("VM::CPU", "read_write register %s (value: %s)\n", assembly::to_string(_id), m_register[_id].to_string().c_str() ) return m_register[_id]; } -void CPU::write(Register _id, fw::qword _data) +void CPU::write(Register _id, qword _data) { - fw::qword& mem_dst = read_write(_id); + qword& mem_dst = read_write(_id); mem_dst = _data; LOG_VERBOSE("VM::CPU", "write register %s (value: %s)\n", assembly::to_string(_id), mem_dst.to_string().c_str()) } @@ -51,7 +51,7 @@ VirtualMachine::VirtualMachine() void VirtualMachine::advance_cursor(i64_t _amount) { - fw::qword eip = m_cpu.read(Register::eip); + qword eip = m_cpu.read(Register::eip); eip.u64 += _amount; m_cpu.write(Register::eip, eip ); } @@ -115,9 +115,9 @@ bool VirtualMachine::_stepOver() { case opcode::cmp: { - fw::qword left = m_cpu.read(static_cast(next_instr->cmp.left.u8)); // dereference registers, get their value - fw::qword right = m_cpu.read(static_cast(next_instr->cmp.right.u8)); - fw::qword result; + qword left = m_cpu.read(static_cast(next_instr->cmp.left.u8)); // dereference registers, get their value + qword right = m_cpu.read(static_cast(next_instr->cmp.right.u8)); + qword result; result.set(left.b == right.b); m_cpu.write(Register::rax, result); // boolean comparison advance_cursor(); @@ -127,7 +127,7 @@ bool VirtualMachine::_stepOver() case opcode::deref_qword: { - fw::qword& qword = *next_instr->uref.ptr; + qword& qword = *next_instr->uref.ptr; m_cpu.write(Register::rax, qword ); const type* ptr_type = next_instr->uref.type; @@ -231,7 +231,7 @@ bool VirtualMachine::_stepOver() } }; - if( auto variable = fw::cast(node)) + if( auto variable = cast(node)) { // If variable is not initialized, we compute its initial value from its inputs variant* variant = variable->value(); @@ -268,7 +268,7 @@ bool VirtualMachine::_stepOver() case opcode::jne: { - fw::qword rax = m_cpu.read(Register::rax); + qword rax = m_cpu.read(Register::rax); if ( rax.b ) { advance_cursor(); @@ -353,11 +353,11 @@ void VirtualMachine::debug_program() bool VirtualMachine::is_there_a_next_instr() const { - const fw::qword& eip = m_cpu.read(Register::eip); + const qword& eip = m_cpu.read(Register::eip); return eip.u64 < m_program_asm_code->size(); } -fw::qword VirtualMachine::get_last_result()const +qword VirtualMachine::get_last_result()const { return m_cpu.read(Register::rax); } @@ -381,7 +381,7 @@ bool VirtualMachine::load_program(const Code *_code) return m_program_asm_code && m_program_asm_code->size() != 0; } -fw::qword VirtualMachine::read_cpu_register(Register _register)const +qword VirtualMachine::read_cpu_register(Register _register)const { return m_cpu.read(_register); } diff --git a/src/nodable/core/WhileLoopNode.cpp b/src/nodable/core/WhileLoopNode.cpp index 2f29c42d5..a7c9a3ee3 100644 --- a/src/nodable/core/WhileLoopNode.cpp +++ b/src/nodable/core/WhileLoopNode.cpp @@ -1,10 +1,11 @@ #include "WhileLoopNode.h" using namespace ndbl; +using namespace fw; REGISTER { - fw::registration::push_class("WhileLoopNode") + registration::push_class("WhileLoopNode") .extends() .extends(); } diff --git a/src/nodable/core/assembly/Code.cpp b/src/nodable/core/assembly/Code.cpp index b01d142a4..26facd08f 100644 --- a/src/nodable/core/assembly/Code.cpp +++ b/src/nodable/core/assembly/Code.cpp @@ -3,6 +3,7 @@ #include "fw/core/format.h" using namespace ndbl; +using namespace fw; assembly::Code::~Code() { @@ -18,13 +19,13 @@ std::string assembly::Code::to_string(const Code* _code) { std::string result; - result.append( fw::format::title("Program begin") ); + result.append( format::title("Program begin") ); for( Instruction* each_instruction : _code->m_instructions ) { result.append(Instruction::to_string(*each_instruction) ); result.append("\n"); } - result.append( fw::format::title("Program end") ); + result.append( format::title("Program end") ); return result; } diff --git a/src/nodable/core/assembly/Compiler.cpp b/src/nodable/core/assembly/Compiler.cpp index fc32a240f..9a01851d0 100644 --- a/src/nodable/core/assembly/Compiler.cpp +++ b/src/nodable/core/assembly/Compiler.cpp @@ -1,25 +1,26 @@ #include "Compiler.h" + #include #include -#include "fw/core/log.h" -#include "fw/core/string.h" #include "fw/core/assertions.h" +#include "fw/core/log.h" #include "fw/core/math.h" +#include "fw/core/string.h" +#include "fw/core/memory/Pool.h" + +#include "nodable/core/ForLoopNode.h" +#include "nodable/core/Graph.h" +#include "nodable/core/IConditional.h" +#include "nodable/core/IfNode.h" +#include "nodable/core/InvokableComponent.h" +#include "nodable/core/LiteralNode.h" +#include "nodable/core/Scope.h" +#include "nodable/core/VariableNode.h" +#include "nodable/core/WhileLoopNode.h" -#include "core/ForLoopNode.h" -#include "core/Graph.h" -#include "core/IConditional.h" -#include "core/IfNode.h" -#include "core/InvokableComponent.h" -#include "core/LiteralNode.h" -#include "core/Scope.h" -#include "core/VariableNode.h" -#include "core/WhileLoopNode.h" - -#include "Register.h" #include "Instruction.h" -#include "core/Pool.h" +#include "Register.h" using namespace ndbl; using namespace ndbl::assembly; @@ -146,15 +147,15 @@ void assembly::Compiler::compile_node( const Node* _node ) if ( _node->get_type()->is_child_of()) { - if ( auto for_loop = fw::cast(_node)) + if ( auto for_loop = cast(_node)) { compile_for_loop(for_loop); } - else if ( auto while_loop = fw::cast(_node)) + else if ( auto while_loop = cast(_node)) { compile_while_loop(while_loop); } - else if ( auto cond_struct_node = fw::cast(_node) ) + else if ( auto cond_struct_node = cast(_node) ) { compile_conditional_struct(cond_struct_node); } @@ -185,8 +186,8 @@ void assembly::Compiler::compile_node( const Node* _node ) } // eval node - bool should_be_evaluated = _node->has_component() || fw::extends(_node) || - fw::extends(_node) ; + bool should_be_evaluated = _node->has_component() || extends(_node) || + extends(_node) ; if ( should_be_evaluated ) { Instruction *instr = m_temp_code->push_instr(Instruction_t::eval_node); @@ -231,7 +232,7 @@ void assembly::Compiler::compile_for_loop(const ForLoopNode* for_loop) // jump back to condition instruction auto loopJump = m_temp_code->push_instr( Instruction_t::jmp ); - loopJump->jmp.offset = math::signed_diff( conditionInstrLine, loopJump->line ); + loopJump->jmp.offset = signed_diff( conditionInstrLine, loopJump->line ); loopJump->m_comment = "jump back to \"for\""; } @@ -255,7 +256,7 @@ void assembly::Compiler::compile_while_loop(const WhileLoopNode* while_loop) // jump back to condition instruction auto loopJump = m_temp_code->push_instr( Instruction_t::jmp ); - loopJump->jmp.offset = math::signed_diff( conditionInstrLine, loopJump->line ); + loopJump->jmp.offset = signed_diff( conditionInstrLine, loopJump->line ); loopJump->m_comment = "jump back to \"while\""; } @@ -307,7 +308,7 @@ void assembly::Compiler::compile_conditional_struct(const IfNode* _cond_node) { if( false_scope->get_owner()->get_type()->is() ) { - auto* conditional_struct = fw::cast(false_scope->get_owner().get()); + auto* conditional_struct = cast(false_scope->get_owner().get()); compile_conditional_struct(conditional_struct); } else diff --git a/src/nodable/core/assembly/Compiler.h b/src/nodable/core/assembly/Compiler.h index bb3d5873c..bc9e02167 100644 --- a/src/nodable/core/assembly/Compiler.h +++ b/src/nodable/core/assembly/Compiler.h @@ -1,7 +1,7 @@ #pragma once -#include "Code.h" -#include "core/Graph.h" #include "fw/core/types.h" +#include "nodable/core/Graph.h" +#include "Code.h" namespace ndbl { diff --git a/src/nodable/core/assembly/Instruction.h b/src/nodable/core/assembly/Instruction.h index 05341ea5f..95f90e5f7 100644 --- a/src/nodable/core/assembly/Instruction.h +++ b/src/nodable/core/assembly/Instruction.h @@ -1,8 +1,8 @@ #pragma once -#include "fw/core/types.h" +#include "fw/core/memory/Pool.h" #include "fw/core/reflection/reflection" -#include "fw/core/Pool.h" +#include "fw/core/types.h" namespace ndbl { diff --git a/src/nodable/core/language/Nodlang.cpp b/src/nodable/core/language/Nodlang.cpp index cbd140d2c..0fb333cf4 100644 --- a/src/nodable/core/language/Nodlang.cpp +++ b/src/nodable/core/language/Nodlang.cpp @@ -20,20 +20,20 @@ #include "fw/core/format.h" #include "fw/core/log.h" #include "fw/core/hash.h" - -#include "core/DirectedEdge.h" -#include "core/ForLoopNode.h" -#include "core/Graph.h" -#include "core/IfNode.h" -#include "core/InvokableComponent.h" -#include "core/LiteralNode.h" -#include "core/Pool.h" -#include "core/Property.h" -#include "core/Scope.h" -#include "core/VariableNode.h" -#include "core/WhileLoopNode.h" -#include "core/language/Nodlang_biology.h" -#include "core/language/Nodlang_math.h" +#include "fw/core/memory/Pool.h" + +#include "nodable/core/DirectedEdge.h" +#include "nodable/core/ForLoopNode.h" +#include "nodable/core/Graph.h" +#include "nodable/core/IfNode.h" +#include "nodable/core/InvokableComponent.h" +#include "nodable/core/LiteralNode.h" +#include "nodable/core/Property.h" +#include "nodable/core/Scope.h" +#include "nodable/core/VariableNode.h" +#include "nodable/core/WhileLoopNode.h" +#include "nodable/core/language/Nodlang_biology.h" +#include "nodable/core/language/Nodlang_math.h" using namespace ndbl; using namespace fw; @@ -1531,7 +1531,7 @@ std::string &Nodlang::serialize_invokable(std::string &_out, const InvokableComp return _out; } -std::string &Nodlang::serialize_func_call(std::string &_out, const fw::func_type *_signature, const std::vector &inputs) const +std::string &Nodlang::serialize_func_call(std::string &_out, const func_type *_signature, const std::vector &inputs) const { _out.append(_signature->get_identifier()); serialize_token_t(_out, Token_t::parenthesis_open); @@ -1550,7 +1550,7 @@ std::string &Nodlang::serialize_func_call(std::string &_out, const fw::func_type return _out; } -std::string &Nodlang::serialize_func_sig(std::string &_out, const fw::func_type *_signature) const +std::string &Nodlang::serialize_func_sig(std::string &_out, const func_type *_signature) const { serialize_type(_out, _signature->get_return_type()); _out.append(" "); @@ -1577,7 +1577,7 @@ std::string &Nodlang::serialize_token_t(std::string &_out, const Token_t &_type) return _out.append(to_string(_type)); } -std::string &Nodlang::serialize_type(std::string &_out, const fw::type *_type) const +std::string &Nodlang::serialize_type(std::string &_out, const type *_type) const { return _out.append(to_string(_type)); } @@ -1620,7 +1620,7 @@ std::string& Nodlang::serialize_variable(std::string &_out, const VariableNode * return _out; } -std::string &Nodlang::serialize_variant(std::string &_out, const fw::variant *variant) const +std::string &Nodlang::serialize_variant(std::string &_out, const variant *variant) const { std::string variant_string = variant->to(); @@ -1659,7 +1659,7 @@ std::string &Nodlang::serialize_input(std::string& _out, const Slot& _slot, Seri } // If adjacent node is a variable, we only serialize its name (no need for recursion) - if ( auto* variable_node = fw::cast( adjacent_slot->get_node() ) ) + if ( auto* variable_node = cast( adjacent_slot->get_node() ) ) { _out.append( variable_node->name ); } @@ -1696,15 +1696,15 @@ std::string & Nodlang::serialize_node( std::string &_out, const PoolID(node ) ) + if ( auto* cond_struct = cast(node ) ) { serialize_cond_struct(_out, cond_struct); } - else if ( auto* for_loop = fw::cast(node ) ) + else if ( auto* for_loop = cast(node ) ) { serialize_for_loop(_out, for_loop); } - else if ( auto* while_loop = fw::cast(node ) ) + else if ( auto* while_loop = cast(node ) ) { serialize_while_loop(_out, while_loop); } @@ -1712,11 +1712,11 @@ std::string & Nodlang::serialize_node( std::string &_out, const PoolID(node ) ) + else if ( auto* literal = cast(node ) ) { serialize_property(_out, literal->value()); } - else if ( auto* variable = fw::cast(node ) ) + else if ( auto* variable = cast(node ) ) { serialize_variable(_out, variable); } @@ -1884,11 +1884,11 @@ std::shared_ptr Nodlang::find_function(const char* _signature_ return nullptr; } - auto hash = fw::hash::hash(_signature_hint); + auto hash = hash::hash(_signature_hint); return find_function( hash ); } -std::shared_ptr Nodlang::find_function(fw::hash::hash_t _hash) const +std::shared_ptr Nodlang::find_function(hash::hash_t _hash) const { auto found = m_functions_by_signature.find(_hash); if ( found != m_functions_by_signature.end()) @@ -2076,7 +2076,7 @@ std::string &Nodlang::to_string(std::string &_out, Token_t _token_t) const } } -std::string Nodlang::to_string(const fw::type *_type) const +std::string Nodlang::to_string(const type *_type) const { std::string result; return to_string(result, _type); diff --git a/src/nodable/core/language/Nodlang.h b/src/nodable/core/language/Nodlang.h index b3db583f1..0addb1c3c 100644 --- a/src/nodable/core/language/Nodlang.h +++ b/src/nodable/core/language/Nodlang.h @@ -6,13 +6,13 @@ #include #include -#include "core/VariableNode.h" #include "fw/core/reflection/reflection" #include "fw/core/system.h" #include "fw/core/hash.h" -#include "core/Token.h" -#include "core/TokenRibbon.h" +#include "nodable/core/VariableNode.h" +#include "nodable/core/Token.h" +#include "nodable/core/TokenRibbon.h" namespace ndbl{ diff --git a/src/nodable/core/language/Nodlang.parse_and_eval.specs.cpp b/src/nodable/core/language/Nodlang.parse_and_eval.specs.cpp index b8071ee16..0d98da78d 100644 --- a/src/nodable/core/language/Nodlang.parse_and_eval.specs.cpp +++ b/src/nodable/core/language/Nodlang.parse_and_eval.specs.cpp @@ -3,6 +3,7 @@ #include "fw/core/log.h" using namespace ndbl; +using namespace fw; typedef ::testing::Core Parse_and_eval; @@ -567,7 +568,7 @@ TEST_F(Parse_and_eval, parse_serialize_empty_program_with_space ) TEST_F(Parse_and_eval, parse_serialize_single_line_program_with_a_comment_before ) { - fw::log::set_verbosity("Parser", fw::log::Verbosity_Verbose); + log::set_verbosity("Parser", log::Verbosity_Verbose); std::string program = "// comment\n" "int a = 42;"; diff --git a/src/nodable/core/language/Nodlang_biology.cpp b/src/nodable/core/language/Nodlang_biology.cpp index e40a885e5..fbca6989a 100644 --- a/src/nodable/core/language/Nodlang_biology.cpp +++ b/src/nodable/core/language/Nodlang_biology.cpp @@ -2,6 +2,7 @@ #include "fw/core/reflection/reflection" using namespace ndbl; +using namespace fw; namespace // anonymous, only accessible from this file { @@ -51,7 +52,7 @@ namespace // anonymous, only accessible from this file REGISTER { - fw::registration::push_class("Nodlang_biology") + registration::push_class("Nodlang_biology") .add_method(&dna_to_protein, "dna_to_protein", "protein"); }; diff --git a/src/nodable/core/language/Nodlang_math.cpp b/src/nodable/core/language/Nodlang_math.cpp index 0b2632da0..37797caaa 100644 --- a/src/nodable/core/language/Nodlang_math.cpp +++ b/src/nodable/core/language/Nodlang_math.cpp @@ -8,6 +8,7 @@ #include "fw/core/types.h" using namespace ndbl; +using namespace fw; namespace // anonymous, accessible only in that file { @@ -22,7 +23,7 @@ namespace // anonymous, accessible only in that file double _secondDegreePolynomial(double a, double x, double b, double y, double c) { return a * x * x + b * y + c;} double _sin(double n) { return sin(n); } std::string _to_string(bool b) { return b ? "true" : "false"; } - std::string _to_string(double n) { return fw::format::number(n); } + std::string _to_string(double n) { return format::number(n); } std::string _to_string(i32_t i) { return std::to_string(i); } std::string _to_string(std::string s) { return s; } template @@ -34,7 +35,7 @@ namespace // anonymous, accessible only in that file template T _plus(T a, T b){ return a + T(b); } template<> - std::string _plus(std::string left, double right) { return left + fw::format::number(right); } + std::string _plus(std::string left, double right) { return left + format::number(right); } template<> std::string _plus(std::string left, i32_t right) { return left + std::to_string(right); } template @@ -73,7 +74,7 @@ namespace // anonymous, accessible only in that file REGISTER { - fw::registration::push_class("Nodlang_math") + registration::push_class("Nodlang_math") .add_method (&_plus, "+", "plus") .add_method(&_plus, "+", "plus") .add_method (&_plus, "+", "plus") diff --git a/src/nodable/gui/Action.h b/src/nodable/gui/Action.h index 7c9dc85f6..8f4dcf520 100644 --- a/src/nodable/gui/Action.h +++ b/src/nodable/gui/Action.h @@ -1,8 +1,9 @@ #pragma once -#include "Event.h" -#include "core/Graph.h" + #include "fw/core/reflection/func_type.h" #include "fw/gui/Action.h" +#include "nodable/core/Graph.h" +#include "Event.h" namespace ndbl { diff --git a/src/nodable/gui/CMakeLists.txt b/src/nodable/gui/CMakeLists.txt deleted file mode 100644 index 528552ca1..000000000 --- a/src/nodable/gui/CMakeLists.txt +++ /dev/null @@ -1,104 +0,0 @@ - -# WARNING: Do not use this CMakeLists.txt directly, take the one from base directory. - -ndbl_log_title_header() - -# checks -ndbl_log("Checking ...") -if( NOT NDBL_CONFIGURED_DIR ) - ndbl_err("Variable NDBL_CONFIGURED_DIR must be set in main CMakeLists.txt") -endif() - -# defines -set(NDBL_APP_ASSETS_DIR ../../../assets) -set(NDBL_APP_ASSETS_ABSOLUTE_DIR "${CMAKE_CURRENT_LIST_DIR}/${NDBL_APP_ASSETS_DIR}") - -# log variables -ndbl_log(" - NDBL_CONFIGURED_DIR: ${NDBL_CONFIGURED_DIR}") -ndbl_log(" - NDBL_APP_ASSETS_DIR: ${NDBL_APP_ASSETS_DIR}") -ndbl_log(" - NDBL_APP_ASSETS_ABSOLUTE_DIR: ${NDBL_APP_ASSETS_ABSOLUTE_DIR}") - -# Configure files -configure_file("build_info.h.in" "${NDBL_CONFIGURED_DIR}/gui/build_info.h" ) - -add_library( - nodable-gui - Config.cpp - GraphView.cpp - History.cpp - HybridFile.cpp - HybridFileView.cpp - Nodable.cpp - NodableView.cpp - NodeView.cpp - NodeViewConstraint.cpp - Physics.cpp - PropertyView.cpp - SlotView.cpp) - -target_link_libraries( - nodable-gui - PUBLIC - gl3w - framework-gui - nodable-core - PRIVATE - ImGuiColorTextEdit -) - -target_include_directories( - nodable-gui - PUBLIC - ${PROJECT_BINARY_DIR}/configured/ndbl/gui/ -) - -# define assets -set(ASSETS - "assets/examples/arithmetic.cpp" - "assets/examples/for-loop.cpp" - "assets/examples/if-else.cpp" - "assets/examples/multi-instructions.cpp" - "assets/fonts/JetBrainsMono-Bold.ttf" - "assets/fonts/JetBrainsMono-Italic.ttf" - "assets/fonts/JetBrainsMono-Medium.ttf" - "assets/fonts/JetBrainsMono-Regular.ttf" - "assets/images/nodable-logo-xs.png" - ) - -# copy each file (will dirty the build when file changes) -foreach(EACH_FILE ${ASSETS}) - configure_file("${EACH_FILE}" "${CMAKE_BINARY_DIR}/${EACH_FILE}" COPYONLY) -endforeach() - -ndbl_log_title_header() - -# WARNING: Do not use this CMakeLists.txt directly, take the one from base directory. - -ndbl_log("NDBL_SKIP_TESTS: ${NDBL_SKIP_TESTS}") - -if ( NDBL_SKIP_TESTS ) - return() -endif() - -# GUI tests (nodable-gui) -#------------------------ - -add_executable( test-nodable-gui Nodable.specs.cpp ) -target_link_libraries( test-nodable-gui PRIVATE gtest_main gtest nodable-gui ) - -# Add test executables -#--------------------- - -# GUI tests does not work on every machine (only MacOS in software on GitHub Actions) -if( $ENV{JETBRAINS_IDE} ) - ndbl_log("JETBRAINS_IDE is defined: Enable Nodable GUI tests (hardware rendering)") - add_test(NAME test_nodable_gui COMMAND test-nodable-gui ) - add_definitions(-D NDBL_GUI_TEST_HUMAN_SPEED ) -elseif(WIN32) - ndbl_log("Windows detected: Skip Nodable GUI tests") -elseif(APPLE) - ndbl_log("Apple detected: Enable Nodable GUI tests (software rendering)") - add_test( NAME test_nodable_gui COMMAND test-nodable-gui ) -elseif(UNIX) # Should be tested after APPLE - ndbl_log("Linux detected: Skip Nodable GUI tests") -endif() diff --git a/src/nodable/gui/Config.cpp b/src/nodable/gui/Config.cpp index 0415fca86..7972419e3 100644 --- a/src/nodable/gui/Config.cpp +++ b/src/nodable/gui/Config.cpp @@ -42,19 +42,19 @@ void ndbl::Config::reset_default() ui_node_instructionBorderRatio = 2.0f; ui_node_padding = { 8.0f, 4.0f, 4.0f, 4.0f }; ui_node_propertyslot_radius = 4.0f; - ui_node_invokableColor = ImColor(255, 199, 115); // light orange - ui_node_variableColor = ImColor( 171, 190, 255); // blue - ui_node_instructionColor = ImVec4(0.7f, 0.9f, 0.7f, 1.0f); // green - ui_node_literalColor = ImVec4(0.75f, 0.75f, 0.75f, 1.0f); // light grey - ui_node_condStructColor = ImVec4(1.f, 1.f, 1.f, 1.0f); // white - ui_node_fillColor = ImVec4(0.7f, 0.9f, 0.7f, 1.0f); // green - ui_node_highlightedColor = ImVec4(1.0f, 1.0f, 1.0f, 1.0f); - ui_node_slot_border_color = ImVec4(0.2f, 0.2f, 0.2f, 1.0f); - ui_node_borderColor = ImVec4(1.0f, 1.0f, 1.0f, 0.8f); - ui_node_borderHighlightedColor = ImVec4(1.0f, 1.0f, 1.0f, 0.8f); - ui_node_shadowColor = ImVec4(0.0f, 0.0f, 0.0f, 0.2f); - ui_node_slot_hovered_color = ImColor(200, 200, 200); - ui_node_slot_color = ImColor(127, 127, 127); + ui_node_invokableColor = Color(255, 199, 115); // light orange + ui_node_variableColor = Color( 171, 190, 255); // blue + ui_node_instructionColor = Vec4(0.7f, 0.9f, 0.7f, 1.0f); // green + ui_node_literalColor = Vec4(0.75f, 0.75f, 0.75f, 1.0f); // light grey + ui_node_condStructColor = Vec4(1.f, 1.f, 1.f, 1.0f); // white + ui_node_fillColor = Vec4(0.7f, 0.9f, 0.7f, 1.0f); // green + ui_node_highlightedColor = Vec4(1.0f, 1.0f, 1.0f, 1.0f); + ui_node_slot_border_color = Vec4(0.2f, 0.2f, 0.2f, 1.0f); + ui_node_borderColor = Vec4(1.0f, 1.0f, 1.0f, 0.8f); + ui_node_borderHighlightedColor = Vec4(1.0f, 1.0f, 1.0f, 0.8f); + ui_node_shadowColor = Vec4(0.0f, 0.0f, 0.0f, 0.2f); + ui_node_slot_hovered_color = Color(200, 200, 200); + ui_node_slot_color = Color(127, 127, 127); ui_node_spacing = 30.0f; ui_node_speed = 20.0f; ui_node_animation_subsample_count = 4; // 60fps * 4 gives virtually 240Fps for the animations @@ -66,16 +66,16 @@ void ndbl::Config::reset_default() ui_wire_bezier_roundness = {0.25f, 2.0f}; ui_wire_bezier_thickness = 2.0f; ui_wire_bezier_fade_length_minmax = {300.0f, 1000.0f}; - ui_wire_color = ImVec4(1.0f, 1.0f, 1.0f, 1.0f); + ui_wire_color = Vec4(1.0f, 1.0f, 1.0f, 1.0f); ui_wire_shadowColor = ui_node_shadowColor; // code flow - ui_codeflow_color = ImColor(150, 170, 140); // slightly green - ui_codeflow_shadowColor = ImColor(0, 0, 0, 64); + ui_codeflow_color = Color(150, 170, 140); // slightly green + ui_codeflow_shadowColor = Color(0, 0, 0, 64); ui_codeflow_thickness_ratio = 0.45f; // relative to ui_node_slot_size.x // buttons - ui_toolButton_size = ImVec2(0.0f, 25.0f); + ui_toolButton_size = Vec2(0.0f, 25.0f); // history ui_history_btn_spacing = 1.f; @@ -85,9 +85,9 @@ void ndbl::Config::reset_default() // overlay ui_overlay_margin = 10.0f; ui_overlay_indent = 5.0f; - ui_overlay_window_bg_golor = ImVec4(0.9f,0.9f,0.9f,0.2f); - ui_overlay_border_color = ImVec4(0,0,0,0); - ui_overlay_text_color = ImVec4(0,0,0,0.5f); + ui_overlay_window_bg_golor = Vec4(0.9f,0.9f,0.9f,0.2f); + ui_overlay_border_color = Vec4(0,0,0,0); + ui_overlay_text_color = Vec4(0,0,0,0.5f); // Window names ui_file_info_window_label = "File"; @@ -100,8 +100,8 @@ void ndbl::Config::reset_default() ui_virtual_machine_window_label = "VM"; // Graph - ui_graph_grid_color_major = ImColor(0, 0, 0, 42); - ui_graph_grid_color_minor = ImColor(0, 0, 0, 17); + ui_graph_grid_color_major = Color(0, 0, 0, 42); + ui_graph_grid_color_minor = Color(0, 0, 0, 17); ui_graph_grid_subdivs = 4; ui_graph_grid_size = 100.0f; diff --git a/src/nodable/gui/Config.h b/src/nodable/gui/Config.h index 87535f995..2883d1849 100644 --- a/src/nodable/gui/Config.h +++ b/src/nodable/gui/Config.h @@ -3,8 +3,8 @@ #include #include #include -#include +#include "fw/gui/ImGuiEx.h" #include "fw/core/reflection/reflection" #include "fw/core/types.h" #include "fw/gui/Config.h" @@ -22,49 +22,49 @@ namespace ndbl { void reset_default(); TextEditor::Palette ui_text_textEditorPalette{}; - ImVec2 ui_wire_bezier_roundness; // {min, max} + fw::Vec2 ui_wire_bezier_roundness; // {min, max} float ui_wire_bezier_thickness; - ImVec2 ui_wire_bezier_fade_length_minmax; - ImVec4 ui_wire_color; - ImVec4 ui_wire_shadowColor; + fw::Vec2 ui_wire_bezier_fade_length_minmax; + fw::Vec4 ui_wire_color; + fw::Vec4 ui_wire_shadowColor; float ui_node_propertyslot_radius; - ImVec4 ui_node_padding; // left, top, right, bottom + fw::Vec4 ui_node_padding; // left, top, right, bottom float ui_node_borderWidth; float ui_node_instructionBorderRatio; // ratio to apply to borderWidth - ImVec4 ui_node_variableColor; - ImVec4 ui_node_invokableColor; - ImVec4 ui_node_instructionColor; - ImVec4 ui_node_literalColor; - ImVec4 ui_node_condStructColor; - ImVec4 ui_node_shadowColor; - ImVec4 ui_node_borderColor; - ImVec4 ui_node_borderHighlightedColor; - ImVec4 ui_node_slot_border_color; - ImVec4 ui_node_highlightedColor; - ImVec4 ui_node_fillColor; - ImVec4 ui_node_slot_color; - ImVec4 ui_node_slot_hovered_color; + fw::Vec4 ui_node_variableColor; + fw::Vec4 ui_node_invokableColor; + fw::Vec4 ui_node_instructionColor; + fw::Vec4 ui_node_literalColor; + fw::Vec4 ui_node_condStructColor; + fw::Vec4 ui_node_shadowColor; + fw::Vec4 ui_node_borderColor; + fw::Vec4 ui_node_borderHighlightedColor; + fw::Vec4 ui_node_slot_border_color; + fw::Vec4 ui_node_highlightedColor; + fw::Vec4 ui_node_fillColor; + fw::Vec4 ui_node_slot_color; + fw::Vec4 ui_node_slot_hovered_color; float ui_node_spacing; float ui_node_speed; u8_t ui_node_animation_subsample_count; - ImVec2 ui_node_slot_size; - float ui_node_slot_gap; + fw::Vec2 ui_node_slot_size; + float ui_node_slot_gap; float ui_node_slot_border_radius; - ImVec4 ui_codeflow_color; - ImVec4 ui_codeflow_shadowColor; + fw::Vec4 ui_codeflow_color; + fw::Vec4 ui_codeflow_shadowColor; float ui_codeflow_thickness_ratio; - ImVec2 ui_toolButton_size; + fw::Vec2 ui_toolButton_size; float ui_history_btn_spacing; float ui_history_btn_height; float ui_history_btn_width_max; const char* ui_splashscreen_imagePath; float ui_overlay_margin; float ui_overlay_indent; - ImVec4 ui_overlay_window_bg_golor; - ImVec4 ui_overlay_border_color; - ImVec4 ui_overlay_text_color; - ImVec4 ui_graph_grid_color_major; - ImVec4 ui_graph_grid_color_minor; + fw::Vec4 ui_overlay_window_bg_golor; + fw::Vec4 ui_overlay_border_color; + fw::Vec4 ui_overlay_text_color; + fw::Vec4 ui_graph_grid_color_major; + fw::Vec4 ui_graph_grid_color_minor; i32_t ui_graph_grid_subdivs; i32_t ui_graph_grid_size; const char* ui_file_info_window_label; diff --git a/src/nodable/gui/Event.h b/src/nodable/gui/Event.h index 91bd6acca..823927846 100644 --- a/src/nodable/gui/Event.h +++ b/src/nodable/gui/Event.h @@ -1,13 +1,15 @@ #pragma once #include +#include "fw/core/memory/Pool.h" +#include "fw/gui/EventManager.h" + +#include "nodable/core/Graph.h" +#include "nodable/core/SlotRef.h" + #include "Event.h" #include "FrameMode.h" #include "SlotView.h" -#include "core/Graph.h" -#include "fw/core/Pool.h" -#include "fw/gui/EventManager.h" -#include "nodable/core/SlotRef.h" namespace ndbl { @@ -87,7 +89,7 @@ namespace ndbl const fw::func_type* node_signature; // The signature of the node that must be created SlotView* dragged_slot = nullptr; // The slot view being dragged. Graph* graph = nullptr; // The graph to create the node into - ImVec2 node_view_local_pos; // The desired position for the new node view + fw::Vec2 node_view_local_pos; // The desired position for the new node view explicit EventPayload_CreateNode(NodeType node_type ) : node_type(node_type) diff --git a/src/nodable/gui/GraphView.cpp b/src/nodable/gui/GraphView.cpp index f225bdc97..3df43df75 100644 --- a/src/nodable/gui/GraphView.cpp +++ b/src/nodable/gui/GraphView.cpp @@ -4,9 +4,10 @@ #include // std::shared_ptr #include #include -#include "core/types.h" +#include "fw/core/types.h" #include "fw/core/log.h" #include "fw/core/system.h" +#include "fw/gui/ImGuiEx.h" #include "Action.h" #include "Condition.h" @@ -36,17 +37,17 @@ const char* k_context_menu_popup = "GraphView.CreateNodeContextMenu"; REGISTER { - fw::registration::push_class("GraphView").extends(); + registration::push_class("GraphView").extends(); } GraphView::GraphView(Graph* graph) - : fw::View() + : View() , m_graph(graph) , m_create_node_context_menu() { } -bool GraphView::draw() +bool GraphView::onDraw() { bool changed = false; bool pixel_perfect = true; @@ -92,15 +93,15 @@ bool GraphView::draw() Node* each_successor_node = adjacent_slot->get_node(); NodeView* each_successor_view = NodeView::substitute_with_parent_if_not_visible( each_successor_node->get_component().get() ); - if ( each_successor_view && each_view->is_visible() && each_successor_view->is_visible() ) + if ( each_successor_view && each_view->is_visible && each_successor_view->is_visible ) { - ImRect start = each_view->get_slot_rect( *slot, app.config, slot_index ); - ImRect end = each_successor_view->get_slot_rect( *adjacent_slot, app.config, 0 );// there is only 1 previous slot + Rect start = each_view->get_slot_rect( *slot, app.config, slot_index ); + Rect end = each_successor_view->get_slot_rect( *adjacent_slot, app.config, 0 );// there is only 1 previous slot - fw::ImGuiEx::DrawVerticalWire( + ImGuiEx::DrawVerticalWire( ImGui::GetWindowDrawList(), - start.GetCenter(), - end.GetCenter(), + start.center(), + end.center(), app.config.ui_codeflow_color, // color app.config.ui_codeflow_shadowColor,// shadowColor, line_width, @@ -120,15 +121,17 @@ bool GraphView::draw() if ( _dragged_slot ) { // When dragging, edge follows mouse cursor. Otherwise, it sticks the contextual menu. - ImVec2 edge_end = m_create_node_context_menu.dragged_slot ? m_create_node_context_menu.opened_at_screen_pos : ImGui::GetMousePos(); + Vec2 edge_end = m_create_node_context_menu.dragged_slot + ? m_create_node_context_menu.opened_at_screen_pos + : (Vec2)ImGui::GetMousePos(); if ( _dragged_slot->slot().type() == SlotFlag_TYPE_CODEFLOW ) { // Thick line - fw::ImGuiEx::DrawVerticalWire( + ImGuiEx::DrawVerticalWire( ImGui::GetWindowDrawList(), - _dragged_slot->rect(app.config).GetCenter(), - hovered_slot ? hovered_slot->rect(app.config).GetCenter(): edge_end, + _dragged_slot->get_rect( app.config ).center(), + hovered_slot ? hovered_slot->get_rect( app.config ).center(): edge_end, app.config.ui_codeflow_color, app.config.ui_codeflow_shadowColor, app.config.ui_node_slot_size.x * app.config.ui_codeflow_thickness_ratio, @@ -167,19 +170,19 @@ bool GraphView::draw() NodeView* node_view = slot->node->get_component().get(); NodeView* adjacent_node_view = adjacent_slot->node->get_component().get(); - if ( !node_view->is_visible() || !adjacent_node_view->is_visible()) + if ( !node_view->is_visible || !adjacent_node_view->is_visible) { continue; } - ImVec2 slot_pos = node_view->get_slot_pos( *slot ); - ImVec2 slot_norm = node_view->get_slot_normal( *slot ); - ImVec2 adjacent_slot_pos = adjacent_node_view->get_slot_pos( *adjacent_slot ); - ImVec2 adjacent_slot_norm = adjacent_node_view->get_slot_normal( *adjacent_slot ); + Vec2 slot_pos = node_view->get_slot_pos( *slot ); + Vec2 slot_norm = node_view->get_slot_normal( *slot ); + Vec2 adjacent_slot_pos = adjacent_node_view->get_slot_pos( *adjacent_slot ); + Vec2 adjacent_slot_norm = adjacent_node_view->get_slot_normal( *adjacent_slot ); // do not draw long lines between a variable value - ImVec4 line_color = app.config.ui_wire_color; - ImVec4 shadow_color = app.config.ui_wire_shadowColor; + Vec4 line_color = app.config.ui_wire_color; + Vec4 shadow_color = app.config.ui_wire_shadowColor; if ( NodeView::is_selected( node_view->poolid() ) || NodeView::is_selected( adjacent_node_view->poolid() ) ) @@ -193,14 +196,14 @@ bool GraphView::draw() else { // transparent depending on wire length - ImVec2 delta = slot_pos - adjacent_slot_pos; + Vec2 delta = slot_pos - adjacent_slot_pos; float dist = std::sqrt(delta.x * delta.x + delta.y * delta.y); if (dist > app.config.ui_wire_bezier_fade_length_minmax.x ) { float factor = ( dist - app.config.ui_wire_bezier_fade_length_minmax.x ) / ( app.config.ui_wire_bezier_fade_length_minmax.y - app.config.ui_wire_bezier_fade_length_minmax.x ); - line_color = ImLerp(line_color, ImColor(0, 0, 0, 0), factor); - shadow_color = ImLerp(shadow_color, ImColor(0, 0, 0, 0), factor); + line_color = Vec4::lerp(line_color, Vec4(0, 0, 0, 0), factor); + shadow_color = Vec4::lerp(shadow_color, Vec4(0, 0, 0, 0), factor); } } @@ -208,12 +211,12 @@ bool GraphView::draw() if (line_color.w != 0.f) { float thickness = app.config.ui_wire_bezier_thickness; - ImVec2 delta = adjacent_slot_pos - slot_pos; - float roundness = fw::math::lerp( + Vec2 delta = adjacent_slot_pos - slot_pos; + float roundness = lerp( app.config.ui_wire_bezier_roundness.x, // min app.config.ui_wire_bezier_roundness.y, // max - 1.0f - fw::math::normalize( ImLengthSqr(delta), 100.0f, 10000.0f ) - + 1.0f - fw::math::normalize( abs(delta.y), 0.0f, 200.0f) + 1.0f - normalize( ImLengthSqr(delta), 100.0f, 10000.0f ) + + 1.0f - normalize( abs(delta.y), 0.0f, 200.0f) ); if ( slot->has_flags(SlotFlag_TYPE_CODEFLOW) ) @@ -222,7 +225,7 @@ bool GraphView::draw() // roundness *= 0.25f; } - fw::ImGuiEx::DrawWire(draw_list, + ImGuiEx::DrawWire(draw_list, slot_pos, adjacent_slot_pos, slot_norm, adjacent_slot_norm, line_color, shadow_color, thickness, roundness); @@ -235,10 +238,9 @@ bool GraphView::draw() */ for ( NodeView* each_node_view : NodeUtils::get_components( m_graph->get_node_registry() ) ) { - if (each_node_view->is_visible()) + if (each_node_view->is_visible) { each_node_view->enable_edition(enable_edition); - View::use_available_region(each_node_view); changed |= each_node_view->draw(); if( app.virtual_machine.is_debugging() && app.virtual_machine.is_next_node( each_node_view->get_owner() ) ) @@ -249,14 +251,14 @@ bool GraphView::draw() // dragging if (NodeView::get_dragged() == each_node_view->poolid() && ImGui::IsMouseDragging(0)) { - ImVec2 mouse_drag_delta = ImGui::GetMouseDragDelta(); + Vec2 mouse_drag_delta = ImGui::GetMouseDragDelta(); each_node_view->translate(mouse_drag_delta, true); ImGui::ResetMouseDragDelta(); each_node_view->pinned( true ); } is_any_node_dragged |= NodeView::get_dragged() == each_node_view->poolid(); - is_any_node_hovered |= each_node_view->is_hovered(); + is_any_node_hovered |= each_node_view->is_hovered; } } } @@ -269,21 +271,20 @@ bool GraphView::draw() const Node* node = app.virtual_machine.get_next_node(); if( NodeView* view = node->get_component().get() ) { - ImVec2 vm_cursor_pos = view->get_position(fw::Space_Screen, pixel_perfect); - vm_cursor_pos.x -= view->get_size().x * 0.5f; - + Vec2 left = view->rect( WORLD_SPACE ).left(); + Vec2 vm_cursor_pos = Vec2::round( left ); draw_list->AddCircleFilled( vm_cursor_pos, 5.0f, ImColor(255,0,0) ); - ImVec2 linePos = vm_cursor_pos + ImVec2(- 10.0f, 0.5f); - linePos += ImVec2(sin(float(app.elapsed_time()) * 12.0f ) * 4.0f, 0.f ); // wave + Vec2 linePos = vm_cursor_pos + Vec2(- 10.0f, 0.5f); + linePos += Vec2(sin(float(app.elapsed_time()) * 12.0f ) * 4.0f, 0.f ); // wave float size = 20.0f; float width = 2.0f; ImColor color = ImColor(255,255,255); // arrow -> - draw_list->AddLine( linePos - ImVec2(1.f, 0.0f), linePos - ImVec2(size, 0.0f), color, width); - draw_list->AddLine( linePos, linePos - ImVec2(size * 0.5f, -size * 0.5f), color, width); - draw_list->AddLine( linePos, linePos - ImVec2(size * 0.5f, size * 0.5f) , color, width); + draw_list->AddLine( linePos - Vec2(1.f, 0.0f), linePos - Vec2(size, 0.0f), color, width); + draw_list->AddLine( linePos, linePos - Vec2(size * 0.5f, -size * 0.5f), color, width); + draw_list->AddLine( linePos, linePos - Vec2(size * 0.5f, size * 0.5f) , color, width); } } @@ -300,7 +301,7 @@ bool GraphView::draw() */ if (ImGui::IsMouseDragging(0) && ImGui::IsWindowFocused() && !is_any_node_dragged ) { - translate_view(ImGui::GetMouseDragDelta()); + pan( ImGui::GetMouseDragDelta() ); ImGui::ResetMouseDragDelta(); } @@ -319,7 +320,7 @@ bool GraphView::draw() if ( ImGui::BeginPopup(k_context_menu_popup) ) { // Title : - fw::ImGuiEx::ColoredShadowedText( ImVec2( 1, 1 ), ImColor( 0.00f, 0.00f, 0.00f, 1.00f ), ImColor( 1.00f, 1.00f, 1.00f, 0.50f ), "Create new node :" ); + ImGuiEx::ColoredShadowedText( Vec2( 1, 1 ), Color( 0.00f, 0.00f, 0.00f, 1.00f ), Color( 1.00f, 1.00f, 1.00f, 0.50f ), "Create new node :" ); ImGui::Separator(); /* * In case user has created a new node we need to connect it to the m_graph depending @@ -350,29 +351,32 @@ bool GraphView::draw() void GraphView::draw_grid( ImDrawList* draw_list, const Config& config ) const { + Rect area = ImGuiEx::GetContentRegion(WORLD_SPACE); const int grid_size = config.ui_graph_grid_size; const int grid_subdiv_size = config.ui_graph_grid_size / config.ui_graph_grid_subdivs; - const int vertical_line_count = int( m_screen_space_content_region.GetSize().x) / grid_subdiv_size; - const int horizontal_line_count = int( m_screen_space_content_region.GetSize().y) / grid_subdiv_size; - ImColor grid_color = config.ui_graph_grid_color_major; - ImColor grid_color_light = config.ui_graph_grid_color_minor; + const int vertical_line_count = int( area.size().x) / grid_subdiv_size; + const int horizontal_line_count = int( area.size().y) / grid_subdiv_size; + Vec4 grid_color = config.ui_graph_grid_color_major; + Vec4 grid_color_light = config.ui_graph_grid_color_minor; for(int coord = 0; coord <= vertical_line_count; ++coord) { - float pos = m_screen_space_content_region.GetTL().x + float(coord) * float(grid_subdiv_size); - const ImVec2 line_start{pos, m_screen_space_content_region.GetTL().y}; - const ImVec2 line_end{pos, m_screen_space_content_region.GetBL().y}; + float pos = area.tl().x + float(coord) * float(grid_subdiv_size); + const Vec2 line_start{pos, area.tl().y}; + const Vec2 line_end{pos, area.bl().y}; bool is_major = coord % config.ui_graph_grid_subdivs == 0; - draw_list->AddLine(line_start, line_end, is_major ? grid_color : grid_color_light); + ImColor color{ is_major ? grid_color : grid_color_light }; + draw_list->AddLine(line_start, line_end, color); } for(int coord = 0; coord <= horizontal_line_count; ++coord) { - float pos = m_screen_space_content_region.GetTL().y + float(coord) * float(grid_subdiv_size); - const ImVec2 line_start{ m_screen_space_content_region.GetTL().x, pos}; - const ImVec2 line_end{ m_screen_space_content_region.GetBR().x, pos}; + float pos = area.tl().y + float(coord) * float(grid_subdiv_size); + const Vec2 line_start{ area.tl().x, pos}; + const Vec2 line_end{ area.br().x, pos}; bool is_major = coord % config.ui_graph_grid_subdivs == 0; - draw_list->AddLine(line_start, line_end, is_major ? grid_color : grid_color_light); + ImColor color{is_major ? grid_color : grid_color_light}; + draw_list->AddLine(line_start, line_end, color); } } @@ -441,45 +445,43 @@ void GraphView::frame_views(const std::vector& _views, bool _align_to LOG_VERBOSE("GraphView", "Unable to frame views vector. Reason: is empty.\n") return; } - ImRect screen = m_screen_space_content_region; + Rect frame = parent_content_region.rect(); // get selection rectangle - ImRect nodes_screen_rect = NodeView::get_rect(_views); - nodes_screen_rect.Translate(screen.Min); // convert to screen space + Rect selection = NodeView::get_rect(_views, WORLD_SPACE); // debug - fw::ImGuiEx::DebugRect(nodes_screen_rect.Min, nodes_screen_rect.Max, IM_COL32(0, 255, 0, 127 ), 5.0f ); - fw::ImGuiEx::DebugRect(screen.Min, screen.Max, IM_COL32( 255, 255, 0, 127 ), 5.0f ); + ImGuiEx::DebugRect( selection.min, selection.max, IM_COL32(0, 255, 0, 127 ), 5.0f ); + ImGuiEx::DebugRect( frame.min, frame.max, IM_COL32( 255, 255, 0, 127 ), 5.0f ); // align - ImVec2 translate_vec; + Vec2 move; if (_align_top_left_corner) { // Align with the top-left corner - nodes_screen_rect.Expand(20.0f); // add a padding to avoid alignment too close from the border - translate_vec = screen.GetTL() - nodes_screen_rect.GetTL(); + selection.expand( Vec2( 20.0f ) ); // add a padding to avoid alignment too close from the border + move = frame.tl() - selection.tl(); } else { - // Align the center of the node rectangle with the screen center - translate_vec = screen.GetCenter() - nodes_screen_rect.GetCenter(); + // Align the center of the node rectangle with the frame center + move = frame.center() - selection.center(); } // apply the translation // TODO: Instead of applying a translation to all views, we could translate a Camera. - // See if we can use matrices in the shaders of ImGui... - auto all_views = NodeUtils::get_components( m_graph->get_node_registry() ); - translate_all(translate_vec, all_views); + auto node_views = NodeUtils::get_components( m_graph->get_node_registry() ); + translate_all( node_views, move, NodeViewFlag_NONE); // debug - fw::ImGuiEx::DebugLine(nodes_screen_rect.GetCenter(), nodes_screen_rect.GetCenter() + translate_vec, IM_COL32(255, 0, 0, 255 ), 20.0f); + ImGuiEx::DebugLine( selection.center(), selection.center() + move, IM_COL32(255, 0, 0, 255 ), 20.0f); } -void GraphView::translate_all(ImVec2 delta, const std::vector& _views) +void GraphView::translate_all(const std::vector& _views, Vec2 delta, NodeViewFlags flags ) { for (auto node_view : _views ) { - node_view->translate(delta); + node_view->translate(delta, flags); } } @@ -489,10 +491,10 @@ void GraphView::unfold() update( config.graph_unfold_dt, config.graph_unfold_iterations ); } -void GraphView::translate_view(ImVec2 delta) +void GraphView::pan( Vec2 delta) { auto views = NodeUtils::get_components( m_graph->get_node_registry() ); - translate_all(delta, views); + translate_all(views, delta, NodeViewFlag_NONE); // TODO: implement a better solution, storing an offset. And then substract it in draw(); // m_view_origin += delta; @@ -505,7 +507,7 @@ void GraphView::add_action_to_context_menu( Action_CreateNode* _action ) void GraphView::frame( FrameMode mode ) { - // TODO: use an ImRect instead of a FrameMode enum, it will be easier to handle undo/redo + // TODO: use an rect instead of a FrameMode enum, it will be easier to handle undo/redo if ( mode == FRAME_ALL ) { return frame_all_node_views(); @@ -662,7 +664,7 @@ void CreateNodeContextMenu::reset_state( SlotView* _dragged_slot ) { must_be_reset_flag = true; search_input[0] = '\0'; - opened_at_pos = ImGui::GetMousePos() - ImGui::GetCursorScreenPos(); + opened_at_pos = (Vec2)(ImGui::GetMousePos() - ImGui::GetCursorScreenPos()); opened_at_screen_pos = ImGui::GetMousePos(); dragged_slot = _dragged_slot; diff --git a/src/nodable/gui/GraphView.h b/src/nodable/gui/GraphView.h index c211d014d..00eb2caf6 100644 --- a/src/nodable/gui/GraphView.h +++ b/src/nodable/gui/GraphView.h @@ -7,14 +7,15 @@ #include "fw/gui/View.h" // base class #include "fw/core/reflection/reflection" -#include "core/Component.h" // base class -#include "core/IScope.h" +#include "nodable/core/Component.h" // base class +#include "nodable/core/IScope.h" +#include "nodable/core/Scope.h" #include "Action.h" #include "Config.h" +#include "NodeView.h" #include "NodeViewConstraint.h" #include "SlotView.h" -#include "core/Scope.h" #include "types.h" namespace ndbl @@ -26,8 +27,8 @@ namespace ndbl struct CreateNodeContextMenu { bool must_be_reset_flag = false; - ImVec2 opened_at_pos = ImVec2(-1,-1); // relative - ImVec2 opened_at_screen_pos = ImVec2(-1,-1); // absolute (screen space) + fw::Vec2 opened_at_pos = fw::Vec2(-1,-1); // relative + fw::Vec2 opened_at_screen_pos = fw::Vec2(-1,-1); // absolute (screen space) SlotView* dragged_slot = nullptr; // The slot being dragged when the context menu opened. char search_input[255] = "\0"; // The search input entered by the user. std::vector items; // All the available items @@ -46,24 +47,23 @@ namespace ndbl GraphView(Graph* graph); ~GraphView() override = default; - bool draw() override; + bool onDraw() override; bool update(); bool update(float /* delta_time */); bool update(float /* delta_time */, i16_t /* subsample_count */); void frame_all_node_views(); void frame_selected_node_views(); - void translate_all(ImVec2 /* delta */, const std::vector&); + void translate_all(const std::vector&, fw::Vec2 delta, NodeViewFlags); void unfold(); // unfold the graph until it is stabilized void add_action_to_context_menu( Action_CreateNode* _action); - void frame( FrameMode mode ); + void frame( FrameMode mode ); private: void draw_grid( ImDrawList*, const Config& ) const; void frame_views(const std::vector &_views, bool _align_top_left_corner); - void translate_view(ImVec2 vec2); + void pan(fw::Vec2); // translate content Graph* m_graph; - ImVec2 m_view_origin; CreateNodeContextMenu m_create_node_context_menu; REFLECT_DERIVED_CLASS() diff --git a/src/nodable/gui/History.h b/src/nodable/gui/History.h index 2acccd614..6f8df7dc9 100644 --- a/src/nodable/gui/History.h +++ b/src/nodable/gui/History.h @@ -4,17 +4,16 @@ #include #include #include -#include - +#include "fw/gui/ImGuiEx.h" #include "fw/core/log.h" #include "fw/core/reflection/reflection" -#include "core/Component.h" -#include "core/Graph.h" -#include "core/Property.h" +#include "nodable/core/Component.h" +#include "nodable/core/Graph.h" +#include "nodable/core/Property.h" -#include "Command.h" -#include "types.h" +#include "nodable/gui/Command.h" +#include "nodable/gui/types.h" namespace ndbl { diff --git a/src/nodable/gui/HybridFile.cpp b/src/nodable/gui/HybridFile.cpp index fc1b83702..5b82bd7ce 100644 --- a/src/nodable/gui/HybridFile.cpp +++ b/src/nodable/gui/HybridFile.cpp @@ -3,14 +3,14 @@ #include #include -#include "core/InvokableComponent.h" -#include "core/LiteralNode.h" +#include "nodable/core/NodeUtils.h" +#include "nodable/core/InvokableComponent.h" +#include "nodable/core/LiteralNode.h" #include "GraphView.h" #include "History.h" #include "Nodable.h" #include "NodeView.h" #include "Physics.h" -#include "core/NodeUtils.h" using namespace ndbl; using namespace fw; diff --git a/src/nodable/gui/HybridFile.h b/src/nodable/gui/HybridFile.h index 7ca9182da..4b9698071 100644 --- a/src/nodable/gui/HybridFile.h +++ b/src/nodable/gui/HybridFile.h @@ -1,7 +1,5 @@ #pragma once -#include // for coordinates -#include #include #include #include @@ -11,11 +9,11 @@ #include "fw/core/reflection/reflection" #include "fw/core/log.h" -#include "core/NodeFactory.h" -#include "HybridFileView.h" -#include "History.h" -#include "Nodable.h" -#include "types.h" +#include "nodable/core/NodeFactory.h" +#include "nodable/gui/HybridFileView.h" +#include "nodable/gui/History.h" +#include "nodable/gui/Nodable.h" +#include "nodable/gui/types.h" namespace ndbl { diff --git a/src/nodable/gui/HybridFileView.cpp b/src/nodable/gui/HybridFileView.cpp index 179878d52..7ca350679 100644 --- a/src/nodable/gui/HybridFileView.cpp +++ b/src/nodable/gui/HybridFileView.cpp @@ -1,10 +1,10 @@ #include "HybridFileView.h" -#include "core/Graph.h" -#include "core/Node.h" -#include "core/VirtualMachine.h" -#include "core/language/Nodlang.h" -#include "core/NodeUtils.h" +#include "nodable/core/Graph.h" +#include "nodable/core/Node.h" +#include "nodable/core/VirtualMachine.h" +#include "nodable/core/language/Nodlang.h" +#include "nodable/core/NodeUtils.h" #include "commands/Cmd_ReplaceText.h" #include "commands/Cmd_WrappedTextEditorUndoRecord.h" @@ -18,7 +18,7 @@ using namespace ndbl; using namespace fw; HybridFileView::HybridFileView(HybridFile& _file) - : fw::View() + : View() , m_text_editor() , m_focused_text_changed(false) , m_is_graph_dirty(false) @@ -48,10 +48,10 @@ HybridFileView::HybridFileView(HybridFile& _file) // make sure views are outside viewable rectangle (to avoid flickering) auto views = NodeUtils::get_components( _graph->get_node_registry() ); - graph_view->translate_all( ImVec2(-1000.f, -1000.0f) , views); + graph_view->translate_all(views, Vec2(-1000.f, -1000.0f), NodeViewFlag_NONE); // frame all (33ms delayed) - fw::EventManager::get_instance().dispatch_delayed( 33, {FRAME_ALL} ); + EventManager::get_instance().dispatch_delayed( 33, {FRAME_ALL} ); } } }); @@ -65,13 +65,13 @@ void HybridFileView::init() m_text_editor.SetPalette(Nodable::get_instance().config.ui_text_textEditorPalette); } -bool HybridFileView::draw() +bool HybridFileView::onDraw() { - const ImVec2 margin(10.0f, 0.0f); + const Vec2 margin(10.0f, 0.0f); const Nodable &app = Nodable::get_instance(); - ImVec2 region_available = ImGui::GetContentRegionAvail() - margin; - ImVec2 text_editor_size = ImVec2(m_child1_size, region_available.y); - ImVec2 graph_editor_size = ImVec2(m_child2_size, region_available.y); + Vec2 region_available = (Vec2)ImGui::GetContentRegionAvail() - margin; + Vec2 text_editor_size {m_child1_size, region_available.y}; + Vec2 graph_editor_size{m_child2_size, region_available.y}; // Splitter //--------- @@ -83,17 +83,17 @@ bool HybridFileView::draw() m_child2_size *= ratio; } - ImRect splitter_rect{ - ImGui::GetCursorScreenPos(), - ImGui::GetCursorScreenPos() + ImVec2(4.0f, region_available.y) + Rect splitter_rect{ + ImGui::GetCursorScreenPos(), + (Vec2)ImGui::GetCursorScreenPos() + Vec2(4.0f, region_available.y) }; - splitter_rect.TranslateX(m_child1_size + 2.0f); - ImGui::SplitterBehavior(splitter_rect, ImGui::GetID("file_splitter"), ImGuiAxis_X, &m_child1_size, &m_child2_size, 20.0f, 20.0f); + splitter_rect.translate_x( m_child1_size + 2.0f ); + ImGui::SplitterBehavior(ImGuiEx::toImGui(splitter_rect), ImGui::GetID("file_splitter"), ImGuiAxis_X, &m_child1_size, &m_child2_size, 20.0f, 20.0f); // TEXT EDITOR //------------ - ImVec2 text_editor_top_left_corner = ImGui::GetCursorPos(); + Vec2 text_editor_top_left_corner = ImGui::GetCursorPos(); ImGui::BeginChild("text_editor", text_editor_size, false); { auto old_cursor_position = m_text_editor.GetCursorPosition(); @@ -131,10 +131,10 @@ bool HybridFileView::draw() m_text_editor.Render("Text Editor Plugin", ImGui::GetContentRegionAvail()); // overlay - ImRect overlay_rect = fw::ImGuiEx::GetContentRegion(fw::Space_Screen); - overlay_rect.Expand(ImVec2(-2.f * app.config.ui_overlay_margin)); // margin - draw_overlay(m_text_overlay_window_name.c_str(), m_overlay_data[OverlayType_TEXT], overlay_rect, ImVec2(0, 1)); - fw::ImGuiEx::DebugRect( overlay_rect.Min, overlay_rect.Max, IM_COL32( 255, 255, 0, 127 ) ); + Rect overlay_rect = ImGuiEx::GetContentRegion( WORLD_SPACE ); + overlay_rect.expand( Vec2( -2.f * app.config.ui_overlay_margin ) ); // margin + draw_overlay(m_text_overlay_window_name.c_str(), m_overlay_data[OverlayType_TEXT], overlay_rect, Vec2(0, 1)); + ImGuiEx::DebugRect( overlay_rect.min, overlay_rect.max, IM_COL32( 255, 255, 0, 127 ) ); if (app.config.experimental_hybrid_history) { @@ -169,24 +169,24 @@ bool HybridFileView::draw() LOG_VERBOSE("FileView", "graph_node_view->update()\n"); ImGuiWindowFlags flags = (ImGuiWindowFlags_)(ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); graph_view->update(); - ImVec2 graph_editor_top_left_corner = ImGui::GetCursorPos(); + Vec2 graph_editor_top_left_corner = ImGui::GetCursorPos(); ImGui::BeginChild("graph", graph_editor_size, false, flags); { // Draw graph - View::use_available_region(graph_view); m_is_graph_dirty = graph_view->draw(); // Draw overlay: shortcuts - ImRect overlay_rect = fw::ImGuiEx::GetContentRegion(fw::Space_Screen); - overlay_rect.Expand(ImVec2(-2.0f * app.config.ui_overlay_margin)); // margin - draw_overlay(m_graph_overlay_window_name.c_str(), m_overlay_data[OverlayType_GRAPH], overlay_rect, ImVec2(1, 1)); - fw::ImGuiEx::DebugRect( overlay_rect.Min, overlay_rect.Max, IM_COL32( 255, 255, 0, 127 ) ); + Rect overlay_rect = ImGuiEx::GetContentRegion( WORLD_SPACE ); + overlay_rect.expand( Vec2( -2.0f * app.config.ui_overlay_margin ) ); // margin + draw_overlay(m_graph_overlay_window_name.c_str(), m_overlay_data[OverlayType_GRAPH], overlay_rect, Vec2(1, 1)); + ImGuiEx::DebugRect( overlay_rect.min, overlay_rect.max, IM_COL32( 255, 255, 0, 127 ) ); // Draw overlay: isolation mode ON/OFF if( app.config.isolate_selection ) { - ImGui::SetCursorPos(graph_editor_top_left_corner + app.config.ui_overlay_margin); + Vec2 cursor_pos = graph_editor_top_left_corner + Vec2(app.config.ui_overlay_margin); + ImGui::SetCursorPos(cursor_pos); ImGui::Text("Isolation mode ON"); } } @@ -310,7 +310,7 @@ void HybridFileView::experimental_clipboard_auto_paste(bool _enable) } } -void HybridFileView::draw_overlay(const char* title, const std::vector& overlay_data, ImRect rect, ImVec2 position) +void HybridFileView::draw_overlay(const char* title, const std::vector& overlay_data, Rect rect, Vec2 position) { if( overlay_data.empty() ) return; @@ -318,8 +318,9 @@ void HybridFileView::draw_overlay(const char* title, const std::vector #include #include "fw/core/reflection/reflection" @@ -43,7 +42,7 @@ namespace ndbl ~HybridFileView() override = default; void init(); - bool draw() override; + bool onDraw() override; bool changed() const { return m_focused_text_changed || m_is_graph_dirty; } bool focused_text_changed() const { return m_focused_text_changed; } bool is_graph_dirty() const { return m_is_graph_dirty; } @@ -63,7 +62,7 @@ namespace ndbl void clear_overlay(); void push_overlay(OverlayData, OverlayType) ; void refresh_overlay(Condition condition); - void draw_overlay(const char* title, const std::vector& overlay_data, ImRect rect, ImVec2 position); + void draw_overlay(const char* title, const std::vector& overlay_data, fw::Rect rect, fw::Vec2 position); size_t size() const; private: diff --git a/src/nodable/gui/Nodable.cpp b/src/nodable/gui/Nodable.cpp index 874827819..6f9689127 100644 --- a/src/nodable/gui/Nodable.cpp +++ b/src/nodable/gui/Nodable.cpp @@ -26,17 +26,16 @@ using namespace ndbl; using namespace fw; -using fw::View; Nodable *Nodable::s_instance = nullptr; template -static fw::func_type* create_variable_node_signature() -{ return fw::func_type_builder::with_id("variable"); } +static func_type* create_variable_node_signature() +{ return func_type_builder::with_id("variable"); } template -static fw::func_type* create_literal_node_signature() -{ return fw::func_type_builder::with_id("literal"); } +static func_type* create_literal_node_signature() +{ return func_type_builder::with_id("literal"); } Nodable::Nodable() : App(config.common, new NodableView(this) ) @@ -45,7 +44,7 @@ Nodable::Nodable() { LOG_VERBOSE("ndbl::App", "Constructor ...\n"); - fw::type_register::log_statistics(); + type_register::log_statistics(); // set this instance as s_instance to access it via App::get_instance() FW_EXPECT(s_instance == nullptr, "Can't create two concurrent App. Delete first instance."); @@ -65,8 +64,8 @@ Nodable::Nodable() node->add_component( physics_id ); // Set fill_color - ImVec4* fill_color; - if ( fw::extends( node.get() ) ) + Vec4* fill_color; + if ( extends( node.get() ) ) { fill_color = &config.ui_node_variableColor; } @@ -78,11 +77,11 @@ Nodable::Nodable() { fill_color = &config.ui_node_instructionColor; } - else if ( fw::extends( node.get() ) ) + else if ( extends( node.get() ) ) { fill_color = &config.ui_node_literalColor; } - else if ( fw::extends( node.get() ) ) + else if ( extends( node.get() ) ) { fill_color = &config.ui_node_condStructColor; } @@ -107,7 +106,7 @@ bool Nodable::on_init() { LOG_VERBOSE("ndbl::App", "on_init ...\n"); - fw::Pool::init(); + Pool::init(); // Bind commands to shortcuts action_manager.new_action( "Delete", Shortcut{ SDLK_DELETE, KMOD_NONE } ); @@ -153,7 +152,7 @@ bool Nodable::on_init() const Nodlang& language = Nodlang::get_instance(); for ( auto& each_fct: language.get_api() ) { - const fw::func_type* func_type = each_fct->get_type(); + const func_type* func_type = each_fct->get_type(); std::string label; language.serialize_func_sig( label, func_type ); action_manager.new_action( label.c_str(), Shortcut{}, EventPayload_CreateNode{ NodeType_INVOKABLE, func_type } ); @@ -202,33 +201,33 @@ void Nodable::on_update() break; } - case fw::EventID_REQUEST_EXIT: + case EventID_REQUEST_EXIT: { should_stop = true; break; } - case fw::EventID_FILE_CLOSE: + case EventID_FILE_CLOSE: { if(current_file) close_file(current_file); break; } - case fw::EventID_UNDO: + case EventID_UNDO: { if(curr_file_history) curr_file_history->undo(); break; } - case fw::EventID_REDO: + case EventID_REDO: { if(curr_file_history) curr_file_history->redo(); break; } - case fw::EventID_FILE_BROWSE: + case EventID_FILE_BROWSE: { std::string path; - if( m_view->pick_file_path(path, fw::AppView::DIALOG_Browse)) + if( m_view->pick_file_path(path, AppView::DIALOG_Browse)) { open_file(path); break; @@ -238,18 +237,18 @@ void Nodable::on_update() } - case fw::EventID_FILE_NEW: + case EventID_FILE_NEW: { new_file(); break; } - case fw::EventID_FILE_SAVE_AS: + case EventID_FILE_SAVE_AS: { if (current_file) { std::string path; - if( m_view->pick_file_path(path, fw::AppView::DIALOG_SaveAs)) + if( m_view->pick_file_path(path, AppView::DIALOG_SaveAs)) { save_file_as(path); break; @@ -258,7 +257,7 @@ void Nodable::on_update() break; } - case fw::EventID_FILE_SAVE: + case EventID_FILE_SAVE: { if (current_file) { @@ -269,7 +268,7 @@ void Nodable::on_update() else { std::string path; - if( m_view->pick_file_path(path, fw::AppView::DIALOG_SaveAs)) + if( m_view->pick_file_path(path, AppView::DIALOG_SaveAs)) { save_file_as(path); } @@ -465,7 +464,7 @@ void Nodable::on_update() // set new_node's view position, select it if ( auto view = new_node_id->get_component() ) { - view->set_position( _event->data.node_view_local_pos, fw::Space_Local ); + view->position( _event->data.node_view_local_pos, PARENT_SPACE ); NodeView::set_selected( view ); } break; @@ -490,14 +489,14 @@ bool Nodable::on_shutdown() } LOG_VERBOSE("ndbl::App", "on_shutdown " OK "\n"); - fw::Pool::shutdown(); + Pool::shutdown(); return true; } HybridFile *Nodable::open_file(const ghc::filesystem::path& _path) { - auto file = new HybridFile(fw::App::asset_path(_path) ); + auto file = new HybridFile(App::asset_path(_path) ); if ( !file->load() ) { @@ -515,7 +514,7 @@ HybridFile *Nodable::add_file(HybridFile* _file) FW_EXPECT(_file, "File is nullptr"); m_loaded_files.push_back( _file ); current_file = _file; - event_manager.dispatch( fw::EventID_FILE_OPENED ); + event_manager.dispatch( EventID_FILE_OPENED ); return _file; } @@ -533,7 +532,7 @@ void Nodable::save_file(HybridFile* _file) const void Nodable::save_file_as(const ghc::filesystem::path& _path) const { - ghc::filesystem::path absolute_path = fw::App::asset_path(_path); + ghc::filesystem::path absolute_path = App::asset_path(_path); current_file->path = absolute_path.string(); current_file->name = absolute_path.filename().string(); if( !current_file->write_to_disk() ) diff --git a/src/nodable/gui/Nodable.h b/src/nodable/gui/Nodable.h index 3c353f751..02d96e2c0 100644 --- a/src/nodable/gui/Nodable.h +++ b/src/nodable/gui/Nodable.h @@ -7,9 +7,9 @@ #include "fw/core/reflection/reflection" #include "fw/gui/App.h" -#include "core/VirtualMachine.h" -#include "core/NodeFactory.h" -#include "core/language/Nodlang.h" +#include "nodable/core/VirtualMachine.h" +#include "nodable/core/NodeFactory.h" +#include "nodable/core/language/Nodlang.h" #include "NodableView.h" #include "Config.h" diff --git a/src/nodable/gui/NodableView.cpp b/src/nodable/gui/NodableView.cpp index 918b385f0..b920af1fb 100644 --- a/src/nodable/gui/NodableView.cpp +++ b/src/nodable/gui/NodableView.cpp @@ -24,7 +24,7 @@ using namespace ndbl::assembly; using namespace fw; NodableView::NodableView(Nodable * _app) - : fw::AppView(_app) + : AppView(_app) , m_logo(nullptr) , m_is_history_dragged(false) , m_show_properties_editor(false) @@ -46,7 +46,7 @@ void NodableView::on_init() LOG_VERBOSE("ndbl::NodableView", "on_init ...\n"); // Load splashscreen image - ghc::filesystem::path path = fw::App::asset_path(m_app->config.ui_splashscreen_imagePath); + ghc::filesystem::path path = App::asset_path(m_app->config.ui_splashscreen_imagePath); m_logo = m_app->texture_manager.load(path.string()); LOG_VERBOSE("ndbl::NodableView", "on_init " OK "\n"); @@ -57,7 +57,7 @@ void NodableView::on_draw() bool redock_all = true; HybridFile* current_file = m_app->current_file; - fw::EventManager& event_manager = m_app->event_manager; + EventManager& event_manager = m_app->event_manager; Config& config = m_app->config; VirtualMachine& virtual_machine = m_app->virtual_machine; @@ -82,7 +82,7 @@ void NodableView::on_draw() current_file->view.experimental_clipboard_auto_paste(!auto_paste); } - fw::ImGuiEx::MenuItem(); + ImGuiEx::MenuItem(); ImGui::EndMenu(); } @@ -103,8 +103,8 @@ void NodableView::on_draw() event_manager.dispatch( EventID_DELETE_NODE ); } - fw::ImGuiEx::MenuItem( false, has_selection ); - fw::ImGuiEx::MenuItem( false,has_selection ); + ImGuiEx::MenuItem( false, has_selection ); + ImGuiEx::MenuItem( false,has_selection ); if (ImGui::MenuItem("Expand/Collapse recursive", nullptr, false, has_selection)) { @@ -148,7 +148,7 @@ void NodableView::on_draw() ImGui::Separator(); - fw::ImGuiEx::MenuItem(config.isolate_selection ); + ImGuiEx::MenuItem(config.isolate_selection ); ImGui::EndMenu(); } @@ -184,7 +184,7 @@ void NodableView::on_draw() if ( ImGui::MenuItem("Show debug info", "", m_app->config.common.debug ) ) { m_app->config.common.debug = !m_app->config.common.debug; - fw::ImGuiEx::debug = m_app->config.common.debug; + ImGuiEx::debug = m_app->config.common.debug; } if ( ImGui::MenuItem("Show FPS", "", m_app->config.common.show_fps ) ) { @@ -199,18 +199,18 @@ void NodableView::on_draw() if (ImGui::BeginMenu("Verbosity")) { - auto menu_item_verbosity = [](fw::log::Verbosity _verbosity, const char *_label) { - if (ImGui::MenuItem(_label, "", fw::log::get_verbosity() == _verbosity)) { - fw::log::set_verbosity(_verbosity); + auto menu_item_verbosity = [](log::Verbosity _verbosity, const char *_label) { + if (ImGui::MenuItem(_label, "", log::get_verbosity() == _verbosity)) { + log::set_verbosity(_verbosity); } }; #ifndef LOG_DISABLE_VERBOSE - menu_item_verbosity(fw::log::Verbosity_Verbose, "Verbose"); + menu_item_verbosity(log::Verbosity_Verbose, "Verbose"); #endif - menu_item_verbosity(fw::log::Verbosity_Message, "Message (default)"); - menu_item_verbosity(fw::log::Verbosity_Warning, "Warning"); - menu_item_verbosity(fw::log::Verbosity_Error, "Error"); + menu_item_verbosity(log::Verbosity_Message, "Message (default)"); + menu_item_verbosity(log::Verbosity_Warning, "Warning"); + menu_item_verbosity(log::Verbosity_Error, "Error"); ImGui::EndMenu(); } @@ -224,11 +224,11 @@ void NodableView::on_draw() if (ImGui::BeginMenu("An issue ?")) { if (ImGui::MenuItem("Report on Github.com")) { - fw::system::open_url_async("https://github.com/berdal84/Nodable/issues"); + system::open_url_async("https://github.com/berdal84/Nodable/issues"); } if (ImGui::MenuItem("Report by email")) { - fw::system::open_url_async("mail:berenger@dalle-cort.fr"); + system::open_url_async("mail:berenger@dalle-cort.fr"); } ImGui::EndMenu(); @@ -240,11 +240,11 @@ void NodableView::on_draw() } if (ImGui::MenuItem("Browse source code")) { - fw::system::open_url_async("https://www.github.com/berdal84/nodable"); + system::open_url_async("https://www.github.com/berdal84/nodable"); } if (ImGui::MenuItem("Credits")) { - fw::system::open_url_async("https://github.com/berdal84/nodable#credits-"); + system::open_url_async("https://github.com/berdal84/nodable#credits-"); } ImGui::EndMenu(); @@ -262,14 +262,14 @@ void NodableView::on_draw() { if( !m_app->config.common.splashscreen ) { - draw_startup_window( get_dockspace(fw::AppView::Dockspace_ROOT)); + draw_startup_window( get_dockspace(AppView::Dockspace_ROOT)); } } else { draw_toolbar_window(); - auto ds_root = get_dockspace(fw::AppView::Dockspace_ROOT); + auto ds_root = get_dockspace(AppView::Dockspace_ROOT); for (HybridFile *each_file: m_app->get_files()) { draw_file_window(ds_root, redock_all, each_file); @@ -287,8 +287,8 @@ void NodableView::on_draw() void NodableView::draw_help_window() const { if (ImGui::Begin(m_app->config.ui_help_window_label)) { - fw::FontManager& font_manager = m_app->font_manager; - ImGui::PushFont(font_manager.get_font(fw::FontSlot_Heading)); + FontManager& font_manager = m_app->font_manager; + ImGui::PushFont(font_manager.get_font(FontSlot_Heading)); ImGui::Text("Welcome to Nodable!"); ImGui::PopFont(); ImGui::NewLine(); @@ -298,24 +298,24 @@ void NodableView::draw_help_window() const { "Nodable allows you to edit a program using both text and graph paradigms." "More precisely, it means:" ); - fw::ImGuiEx::BulletTextWrapped("any change on the text will affect the graph"); - fw::ImGuiEx::BulletTextWrapped("any change (structure or values) on the graph will affect the text"); - fw::ImGuiEx::BulletTextWrapped( + ImGuiEx::BulletTextWrapped("any change on the text will affect the graph"); + ImGuiEx::BulletTextWrapped("any change (structure or values) on the graph will affect the text"); + ImGuiEx::BulletTextWrapped( "but keep in mind the state is the text, any change not affecting the text (such as node positions or orphan nodes) will be lost."); ImGui::NewLine(); - ImGui::PushFont(font_manager.get_font(fw::FontSlot_Heading)); + ImGui::PushFont(font_manager.get_font(FontSlot_Heading)); ImGui::Text("Quick start"); ImGui::PopFont(); ImGui::NewLine(); ImGui::TextWrapped("Nodable UI is designed as following:\n"); - fw::ImGuiEx::BulletTextWrapped("On the left side a (light) text editor allows to edit source code.\n"); - fw::ImGuiEx::BulletTextWrapped( + ImGuiEx::BulletTextWrapped("On the left side a (light) text editor allows to edit source code.\n"); + ImGuiEx::BulletTextWrapped( "At the center, there is the graph editor where you can create/delete/connect nodes\n"); - fw::ImGuiEx::BulletTextWrapped( + ImGuiEx::BulletTextWrapped( "On the right side (this side) you will find many tabs to manage additional config such as node properties, virtual machine or app properties\n"); - fw::ImGuiEx::BulletTextWrapped("At the top, between the menu and the editors, there is a tool bar." + ImGuiEx::BulletTextWrapped("At the top, between the menu and the editors, there is a tool bar." " There, few buttons will serve to compile, run and debug your program."); - fw::ImGuiEx::BulletTextWrapped("And at the bottom, below the editors, there is a status bar." + ImGuiEx::BulletTextWrapped("And at the bottom, below the editors, there is a status bar." " This bar will display important messages, warning, and errors. You can expand it to get older messages."); } ImGui::End(); @@ -370,7 +370,7 @@ void NodableView::draw_virtual_machine_window() { ImGui::Text("Virtual Machine:"); ImGui::SameLine(); - fw::ImGuiEx::DrawHelper("%s", "The virtual machine - or interpreter - is a sort of implementation of \n" + ImGuiEx::DrawHelper("%s", "The virtual machine - or interpreter - is a sort of implementation of \n" "an imaginary hardware able to run a set of simple instructions."); ImGui::Separator(); @@ -381,10 +381,10 @@ void NodableView::draw_virtual_machine_window() { ImGui::Indent(); ImGui::Text("State: %s", vm.is_program_running() ? "running" : "stopped"); ImGui::SameLine(); - fw::ImGuiEx::DrawHelper("%s", "When virtual machine is running, you cannot edit the code or the graph."); + ImGuiEx::DrawHelper("%s", "When virtual machine is running, you cannot edit the code or the graph."); ImGui::Text("Debug: %s", vm.is_debugging() ? "ON" : "OFF"); ImGui::SameLine(); - fw::ImGuiEx::DrawHelper("%s", "When debugging is ON, you can run a program step by step."); + ImGuiEx::DrawHelper("%s", "When debugging is ON, you can run a program step by step."); ImGui::Text("Has program: %s", code ? "YES" : "NO"); if (code) { ImGui::Text("Program over: %s", !vm.is_there_a_next_instr() ? "YES" : "NO"); @@ -396,7 +396,7 @@ void NodableView::draw_virtual_machine_window() { ImGui::Separator(); ImGui::Text("CPU:"); ImGui::SameLine(); - fw::ImGuiEx::DrawHelper("%s", "This is the virtual machine's CPU" + ImGuiEx::DrawHelper("%s", "This is the virtual machine's CPU" "\nIt contains few registers to store temporary values " "\nlike instruction pointer, last node's value or last comparison result"); ImGui::Indent(); @@ -415,13 +415,13 @@ void NodableView::draw_virtual_machine_window() { draw_register_value(Register::rax); ImGui::SameLine(); - fw::ImGuiEx::DrawHelper("%s", "primary accumulator"); + ImGuiEx::DrawHelper("%s", "primary accumulator"); draw_register_value(Register::rdx); ImGui::SameLine(); - fw::ImGuiEx::DrawHelper("%s", "base register"); + ImGuiEx::DrawHelper("%s", "base register"); draw_register_value(Register::eip); ImGui::SameLine(); - fw::ImGuiEx::DrawHelper("%s", "instruction pointer"); + ImGuiEx::DrawHelper("%s", "instruction pointer"); ImGui::Unindent(); } @@ -431,19 +431,19 @@ void NodableView::draw_virtual_machine_window() { ImGui::Separator(); ImGui::Text("Memory:"); ImGui::SameLine(); - fw::ImGuiEx::DrawHelper("%s", "Virtual Machine Memory."); + ImGuiEx::DrawHelper("%s", "Virtual Machine Memory."); ImGui::Separator(); { ImGui::Indent(); ImGui::Text("Bytecode:"); ImGui::SameLine(); - fw::ImGuiEx::DrawHelper("%s", "The bytecode is the result of the Compilation process." + ImGuiEx::DrawHelper("%s", "The bytecode is the result of the Compilation process." "\nAfter source code has been parsed to a syntax tree, " "\nthe tree (or graph) is converted by the Compiler to an Assembly-like code."); ImGui::Checkbox("Auto-scroll ?", &m_scroll_to_curr_instr); ImGui::SameLine(); - fw::ImGuiEx::DrawHelper("%s", "to scroll automatically to the current instruction"); + ImGuiEx::DrawHelper("%s", "to scroll automatically to the current instruction"); ImGui::Separator(); { ImGui::BeginChild("AssemblyCodeChild", ImGui::GetContentRegionAvail(), true); @@ -458,7 +458,7 @@ void NodableView::draw_virtual_machine_window() { } ImGui::TextColored(ImColor(200, 0, 0), ">%s", str.c_str()); ImGui::SameLine(); - fw::ImGuiEx::DrawHelper("%s", "This is the next instruction to evaluate"); + ImGuiEx::DrawHelper("%s", "This is the next instruction to evaluate"); } else { ImGui::Text(" %s", str.c_str()); } @@ -466,7 +466,7 @@ void NodableView::draw_virtual_machine_window() { } else { ImGui::TextWrapped("Nothing loaded, try to compile, run or debug."); ImGui::SameLine(); - fw::ImGuiEx::DrawHelper("%s", "To see a compiled program here you need first to:" + ImGuiEx::DrawHelper("%s", "To see a compiled program here you need first to:" "\n- Select a piece of code in the text editor" "\n- Click on \"Compile\" button." "\n- Ensure there is no errors in the status bar (bottom)."); @@ -485,8 +485,8 @@ void NodableView::draw_startup_window(ImGuiID dockspace_id) { ImGui::Begin(m_app->config.ui_startup_window_label); { - fw::FontManager& font_manager = m_app->font_manager; - fw::EventManager& event_manager = m_app->event_manager; + FontManager& font_manager = m_app->font_manager; + EventManager& event_manager = m_app->event_manager; ImGui::PopStyleColor(); ImVec2 center_area(500.0f, 250.0f); @@ -499,15 +499,15 @@ void NodableView::draw_startup_window(ImGuiID dockspace_id) { { ImGui::Indent(center_area.x * 0.05f); - ImGui::PushFont(font_manager.get_font(fw::FontSlot_ToolBtn)); + ImGui::PushFont(font_manager.get_font(FontSlot_ToolBtn)); ImGui::NewLine(); ImVec2 btn_size(center_area.x * 0.44f, 40.0f); if (ImGui::Button(ICON_FA_FILE" New File", btn_size)) - event_manager.dispatch( fw::EventID_FILE_NEW ); + event_manager.dispatch( EventID_FILE_NEW ); ImGui::SameLine(); if (ImGui::Button(ICON_FA_FOLDER_OPEN" Open ...", btn_size)) - event_manager.dispatch( fw::EventID_FILE_BROWSE ); + event_manager.dispatch( EventID_FILE_BROWSE ); ImGui::NewLine(); ImGui::Separator(); @@ -530,7 +530,7 @@ void NodableView::draw_startup_window(ImGuiID dockspace_id) { if (i++ % 2) ImGui::SameLine(); if (ImGui::Button(label.c_str(), small_btn_size)) { - m_app->open_file( fw::App::asset_path(path.c_str()) ); + m_app->open_file( App::asset_path(path.c_str()) ); } } @@ -577,8 +577,8 @@ void NodableView::draw_file_window(ImGuiID dockspace_id, bool redock_all, Hybrid // File View in the middle ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(0, 0, 0, 0.35f)); - ImGui::PushFont(m_app->font_manager.get_font(fw::FontSlot_Code)); - const ImVec2 &size = ImGui::GetContentRegionAvail(); + ImGui::PushFont(m_app->font_manager.get_font(FontSlot_Code)); + const ImVec2 size = ImGui::GetContentRegionAvail(); ImGui::BeginChild("FileView", size, false, 0); { @@ -681,7 +681,7 @@ void NodableView::draw_config_window() { if ( m_app->config.common.debug && ImGui::CollapsingHeader("Pool")) { ImGui::Text("Pool stats:"); - auto pool = fw::Pool::get_pool(); + auto pool = Pool::get_pool(); ImGui::Text(" - Node.................... %8zu", pool->get_all().size() ); ImGui::Text(" - NodeView................ %8zu", pool->get_all().size() ); ImGui::Text(" - Physics................. %8zu", pool->get_all().size() ); @@ -699,9 +699,9 @@ void NodableView::draw_splashscreen() // Image ImGui::SameLine((ImGui::GetContentRegionAvail().x - m_logo->width) * 0.5f); // center img - fw::ImGuiEx::Image(m_logo); + ImGuiEx::Image(m_logo); - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(50.0f, 30.0f)); + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, {50.0f, 30.0f}); // disclaimer ImGui::TextWrapped( @@ -742,7 +742,7 @@ void NodableView::draw_history_bar(History *currentFileHistory) { float avail_width = ImGui::GetContentRegionAvail().x; float btn_width = fmin(btn_width_max, avail_width / float(historySize + 1) - btn_spacing); - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(btn_spacing, 0)); + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, { btn_spacing, 0}); for (int cmd_pos = history_range.first; cmd_pos <= history_range.second; cmd_pos++) { ImGui::SameLine(); @@ -752,11 +752,11 @@ void NodableView::draw_history_bar(History *currentFileHistory) { // Draw an highlighted button for the current history position if (cmd_pos == 0) { ImGui::PushStyleColor(ImGuiCol_Button, ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered)); - ImGui::Button(label.c_str(), ImVec2(btn_width, btn_height)); + ImGui::Button(label.c_str(), {btn_width, btn_height}); ImGui::PopStyleColor(); } else // or a simple one for other history positions { - ImGui::Button(label.c_str(), ImVec2(btn_width, btn_height)); + ImGui::Button(label.c_str(), {btn_width, btn_height}); } // Hovered item @@ -768,9 +768,9 @@ void NodableView::draw_history_bar(History *currentFileHistory) { // Draw command description ImGui::PushStyleVar(ImGuiStyleVar_Alpha, float(0.8)); - if (fw::ImGuiEx::BeginTooltip()) { + if (ImGuiEx::BeginTooltip()) { ImGui::Text("%s", currentFileHistory->get_cmd_description_at(cmd_pos).c_str()); - fw::ImGuiEx::EndTooltip(); + ImGuiEx::EndTooltip(); } ImGui::PopStyleVar(); } @@ -791,7 +791,7 @@ void NodableView::draw_history_bar(History *currentFileHistory) { void NodableView::draw_toolbar_window() { ImGuiWindowFlags flags = ImGuiWindowFlags_NoScrollbar; - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(5.0f, 5.0f)); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, {5.0f, 5.0f}); Config& config = m_app->config; if (ImGui::Begin(config.ui_toolbar_window_label, NULL, flags )) { @@ -800,9 +800,9 @@ void NodableView::draw_toolbar_window() { bool running = vm.is_program_running(); bool debugging = vm.is_debugging(); bool stopped = vm.is_program_stopped(); - ImVec2 button_size = config.ui_toolButton_size; + auto button_size = config.ui_toolButton_size; - ImGui::PushFont(m_app->font_manager.get_font(fw::FontSlot_ToolBtn)); + ImGui::PushFont(m_app->font_manager.get_font(FontSlot_ToolBtn)); ImGui::BeginGroup(); // compile @@ -866,11 +866,11 @@ void NodableView::on_reset_layout() // Dock windows to specific dockspace const Config& config = m_app->config; - dock_window(config.ui_help_window_label , fw::AppView::Dockspace_RIGHT); - dock_window(config.ui_config_window_label , fw::AppView::Dockspace_RIGHT); - dock_window(config.ui_file_info_window_label , fw::AppView::Dockspace_RIGHT); - dock_window(config.ui_node_properties_window_label , fw::AppView::Dockspace_RIGHT); - dock_window(config.ui_virtual_machine_window_label , fw::AppView::Dockspace_RIGHT); - dock_window(config.ui_imgui_config_window_label , fw::AppView::Dockspace_RIGHT); - dock_window(config.ui_toolbar_window_label , fw::AppView::Dockspace_TOP); + dock_window(config.ui_help_window_label , AppView::Dockspace_RIGHT); + dock_window(config.ui_config_window_label , AppView::Dockspace_RIGHT); + dock_window(config.ui_file_info_window_label , AppView::Dockspace_RIGHT); + dock_window(config.ui_node_properties_window_label , AppView::Dockspace_RIGHT); + dock_window(config.ui_virtual_machine_window_label , AppView::Dockspace_RIGHT); + dock_window(config.ui_imgui_config_window_label , AppView::Dockspace_RIGHT); + dock_window(config.ui_toolbar_window_label , AppView::Dockspace_TOP); } diff --git a/src/nodable/gui/NodeView.cpp b/src/nodable/gui/NodeView.cpp index 7ac5bdd06..a43273333 100644 --- a/src/nodable/gui/NodeView.cpp +++ b/src/nodable/gui/NodeView.cpp @@ -1,5 +1,14 @@ #include "NodeView.h" +#include // for std::max +#include // for sinus +#include + +#include "fw/core/math.h" +#include "nodable/core/GraphUtil.h" +#include "nodable/core/InvokableComponent.h" +#include "nodable/core/LiteralNode.h" + #include "Config.h" #include "Event.h" #include "Nodable.h" @@ -7,46 +16,32 @@ #include "Physics.h" #include "PropertyView.h" #include "SlotView.h" -#include "core/Graph.h" -#include "core/GraphUtil.h" -#include "core/InvokableComponent.h" -#include "core/LiteralNode.h" -#include "core/Pool.h" -#include "core/Scope.h" -#include "core/VariableNode.h" -#include "core/language/Nodlang.h" -#include "fw/core/math.h" -#include "fw/core/reflection/registration.h" -#include // for std::max -#include // for sinus -#include - -constexpr ImVec2 NODE_VIEW_DEFAULT_SIZE(10.0f, 35.0f); using namespace ndbl; using namespace fw; REGISTER { - fw::registration::push_class("NodeView") + registration::push_class("NodeView") .extends() - .extends(); + .extends(); } +constexpr Vec2 DEFAULT_SIZE{10.0f, 35.0f}; +constexpr Vec2 DEFAULT_POS{500.0f, -1.0f}; + PoolID NodeView::s_selected; PoolID NodeView::s_dragged; // TODO: move those values into the configuration NodeViewDetail NodeView::s_view_detail = NodeViewDetail::Default; const float NodeView::s_property_input_size_min = 10.0f; -const ImVec2 NodeView::s_property_input_toggle_button_size(10.0, 25.0f); +const Vec2 NodeView::s_property_input_toggle_button_size(10.0, 25.0f); NodeView::NodeView() : Component() - , fw::View() + , View() , m_colors({}) - , m_position(500.0f, -1.0f) - , m_size(NODE_VIEW_DEFAULT_SIZE) , m_opacity(1.0f) , m_expanded(true) , m_pinned(false) @@ -54,6 +49,8 @@ NodeView::NodeView() , m_edition_enable(true) , m_property_views() { + box.pos(DEFAULT_POS); + box.size(DEFAULT_SIZE); } NodeView::~NodeView() @@ -112,13 +109,13 @@ void NodeView::set_owner(PoolID node) // Create a SlotView per slot for(Slot& slot : m_owner->slots() ) { - ImVec2 alignment; + Vec2 alignment; switch ( slot.static_flags() ) // type and order flags only { case SlotFlag_INPUT: alignment.y = -0.5f; break; case SlotFlag_PREV: alignment = { -0.5f, -0.5f}; break; - case SlotFlag_OUTPUT: alignment = slot.get_property()->is_this() ? ImVec2{-0.5f, 0.0f} - : ImVec2{ 0.0f, 0.5f}; break; + case SlotFlag_OUTPUT: alignment = slot.get_property()->is_this() ? Vec2{-0.5f, 0.0f} + : Vec2{ 0.0f, 0.5f}; break; case SlotFlag_NEXT: alignment = { -0.5f, 0.5f}; break; case SlotFlag_CHILD: case SlotFlag_PARENT: break; // won't be displayed, let's keep default alignment (0,0) @@ -146,7 +143,7 @@ void NodeView::update_labels_from_name(const Node* _node) m_label.clear(); m_short_label.clear(); - if ( auto* variable = fw::cast(_node) ) + if ( auto* variable = cast(_node) ) { m_label += variable->type()->get_name(); m_label += " "; @@ -161,7 +158,7 @@ void NodeView::update_labels_from_name(const Node* _node) void NodeView::set_selected(PoolID new_selection) { - fw::EventManager& event_manager = fw::EventManager::get_instance(); + EventManager& event_manager = EventManager::get_instance(); if( s_selected == new_selection ) return; @@ -196,40 +193,19 @@ const PropertyView* NodeView::get_property_view( ID _id )const return &m_property_views.at((u32_t)_id); } -void NodeView::set_position(ImVec2 _position, fw::Space origin) +void NodeView::translate( Vec2 _delta, NodeViewFlags flags) { - switch (origin) - { - case fw::Space_Local: m_position = _position; break; - case fw::Space_Screen: m_position = _position - m_screen_space_content_region.GetTL(); break; - default: - FW_EXPECT(false, "OriginRef_ case not handled, cannot compute perform set_position(...)") - } -} - -ImVec2 NodeView::get_position(fw::Space origin, bool round) const -{ - // compute position depending on space - ImVec2 result = m_position; - if (origin == fw::Space_Screen) result += m_screen_space_content_region.GetTL(); - - // return rounded or not if needed - if(round) return fw::math::round(result); - return result; -} - -void NodeView::translate(ImVec2 _delta, bool _recurse) -{ - ImVec2 current_local_position = get_position(fw::Space_Local); - set_position( current_local_position + _delta, fw::Space_Local); + View::translate(_delta); - if ( !_recurse ) return; + if ( !(flags & NodeViewFlag_RECURSIVELY) ) return; for(auto each_input: get_adjacent(SlotFlag_INPUT) ) { - if ( each_input && !each_input->m_pinned && each_input->m_owner->should_be_constrain_to_follow_output( this->m_owner ) ) + if( !each_input ) continue; + if( each_input->m_pinned && flags & NodeViewFlag_IGNORE_PINNED ) continue; + if( each_input->m_owner->should_be_constrain_to_follow_output( this->m_owner ) ) { - each_input->translate(_delta, true); + each_input->translate(_delta, flags); } } } @@ -261,11 +237,14 @@ void NodeView::arrange_recursively(bool _smoothly) bool NodeView::update(float _deltaTime) { - if(m_opacity != 1.0f) fw::math::lerp(m_opacity, 1.0f, 10.0f * _deltaTime); + if(m_opacity != 1.0f) + { + lerp(m_opacity, 1.0f, 10.0f * _deltaTime); + } return true; } -bool NodeView::draw() +bool NodeView::onDraw() { bool changed = false; Node* node = m_owner.get(); @@ -277,11 +256,10 @@ bool NodeView::draw() // Draw Node slots (in background) bool is_slot_hovered = false; { - ImColor color = config.ui_node_slot_color; - ImColor border_color = config.ui_node_slot_border_color; - float border_radius = config.ui_node_slot_border_radius; - ImColor hover_color = config.ui_node_slot_hovered_color; - ImRect node_view_rect = get_screen_rect(); + Vec4 color = config.ui_node_slot_color; + Vec4 border_color = config.ui_node_slot_border_color; + float border_radius = config.ui_node_slot_border_radius; + Vec4 hover_color = config.ui_node_slot_hovered_color; std::unordered_map count_by_flags{{SlotFlag_NEXT, 0}, {SlotFlag_PREV, 0}}; for ( SlotView& slot_view : m_slot_views ) @@ -289,7 +267,7 @@ bool NodeView::draw() if( slot_view.slot().capacity() && slot_view.slot().type() == SlotFlag_TYPE_CODEFLOW && (node->is_instruction() || node->can_be_instruction() ) ) { int& count = count_by_flags[slot_view.slot().static_flags()]; - ImRect rect = get_slot_rect( slot_view, config, count ); + Rect rect = get_slot_rect( slot_view, config, count ); SlotView::draw_slot_rectangle( draw_list, slot_view, rect, color, border_color, hover_color, border_radius, m_edition_enable); is_slot_hovered |= ImGui::IsItemHovered(); count++; @@ -300,33 +278,45 @@ bool NodeView::draw() // Begin the window //----------------- ImGui::PushStyleVar(ImGuiStyleVar_Alpha, m_opacity); - const auto halfSize = m_size / 2.0; - ImVec2 node_screen_center_pos = get_position(fw::Space_Screen, true); - const ImVec2 &node_top_left_corner = node_screen_center_pos - halfSize; - ImGui::SetCursorScreenPos(node_top_left_corner); // start from th top left corner + Rect screen_rect = rect( WORLD_SPACE ); + ImGui::SetCursorScreenPos(screen_rect.tl() ); // start from th top left corner ImGui::PushID(this); // Draw the background of the Group + Vec4 border_color = config.ui_node_borderColor; + if ( is_selected( m_id ) ) + { + border_color = config.ui_node_borderHighlightedColor; + } + else if (node->is_instruction()) + { + border_color = config.ui_node_instructionColor; + } + + float border_width = config.ui_node_borderWidth; + if( node->is_instruction() ) + { + border_width *= config.ui_node_instructionBorderRatio; + } + DrawNodeRect( - node_top_left_corner, node_top_left_corner + m_size, + screen_rect, get_color( Color_FILL ), config.ui_node_borderColor, config.ui_node_shadowColor, - is_selected( m_id ) ? config.ui_node_borderHighlightedColor - : node->is_instruction() ? config.ui_node_instructionColor - : config.ui_node_borderColor, + border_color, is_selected( m_id ), 5.0f, - config.ui_node_borderWidth * ( node->is_instruction() ? config.ui_node_instructionBorderRatio : 1.0f) ); + border_width ); // Add an invisible just on top of the background to detect mouse hovering - ImGui::SetCursorScreenPos(node_top_left_corner); - ImGui::InvisibleButton("node", m_size); + ImGui::SetCursorScreenPos(screen_rect.tl() ); + ImGui::InvisibleButton("node", box.size()); ImGui::SetItemAllowOverlap(); - ImVec2 new_screen_pos = node_top_left_corner - + ImVec2{config.ui_node_padding.x, config.ui_node_padding.y} // left and top padding. - + ImVec2{config.ui_node_propertyslot_radius, 0.0f}; // space for "this" left slot + Vec2 new_screen_pos = screen_rect.tl() + + Vec2{config.ui_node_padding.x, config.ui_node_padding.y} // left and top padding. + + Vec2{config.ui_node_propertyslot_radius, 0.0f}; // space for "this" left slot ImGui::SetCursorScreenPos(new_screen_pos); bool is_node_hovered = ImGui::IsItemHovered(); @@ -342,7 +332,7 @@ bool NodeView::draw() //abel.insert(0, "<<"); label.append(" " ICON_FA_OBJECT_GROUP); } - fw::ImGuiEx::ShadowedText(ImVec2(1.0f), config.ui_node_borderHighlightedColor, label.c_str()); // text with a lighter shadow (encrust effect) + ImGuiEx::ShadowedText( Vec2(1.0f), config.ui_node_borderHighlightedColor, label.c_str()); // text with a lighter shadow (encrust effect) ImGui::SameLine(); @@ -359,28 +349,31 @@ bool NodeView::draw() ImGui::EndGroup(); ImGui::SameLine(); ImGui::EndGroup(); - ImVec2 new_size = ImGui::GetItemRectMax() - + ImVec2{config.ui_node_padding.z, config.ui_node_padding.w} // right and bottom padding - - node_top_left_corner; // Ends the Window //---------------- - m_size.x = std::max( 1.0f, std::ceil(new_size.x)); - m_size.y = std::max( 1.0f, std::ceil(new_size.y)); + // Update box's size according to item's rect + Vec2 new_size = ImGui::GetItemRectMax(); + new_size += Vec2{config.ui_node_padding.z, config.ui_node_padding.w}; // right and bottom padding + new_size -= screen_rect.tl(); + new_size.x = std::max( 1.0f, new_size.x ); + new_size.y = std::max( 1.0f, new_size.y ); + + box.size( Vec2::round(new_size) ); // Draw Property in/out slots { - float radius = config.ui_node_propertyslot_radius; - ImColor color = config.ui_node_slot_color; - ImColor borderCol = config.ui_node_slot_border_color; - ImColor hoverCol = config.ui_node_slot_hovered_color; + float radius = config.ui_node_propertyslot_radius; + Vec4 color = config.ui_node_slot_color; + Vec4 borderCol = config.ui_node_slot_border_color; + Vec4 hoverCol = config.ui_node_slot_hovered_color; for( auto& slot_view: m_slot_views ) { if( slot_view.slot().has_flags(SlotFlag_TYPE_VALUE) ) { - ImVec2 screen_pos = get_slot_pos(slot_view.slot()); + Vec2 screen_pos = get_slot_pos(slot_view.slot()); SlotView::draw_slot_circle( draw_list, slot_view, screen_pos, radius, color, borderCol, hoverCol, m_edition_enable ); is_slot_hovered |= ImGui::IsItemHovered(); } @@ -447,28 +440,44 @@ bool NodeView::draw() m_owner->dirty |= changed; - m_is_hovered = is_node_hovered || is_slot_hovered; + is_hovered = is_node_hovered || is_slot_hovered; return changed; } -void NodeView::DrawNodeRect( ImVec2 rect_min, ImVec2 rect_max, ImColor color, ImColor border_highlight_col, ImColor shadow_col, ImColor border_col, bool selected, float border_radius, float border_width ) +void NodeView::DrawNodeRect( + Rect rect, + Vec4 color, + Vec4 border_highlight_col, + Vec4 shadow_col, + Vec4 border_col, + bool selected, + float border_radius, + float border_width +) { ImDrawList* draw_list = ImGui::GetWindowDrawList(); // Draw the rectangle under everything - fw::ImGuiEx::DrawRectShadow(rect_min, rect_max, border_radius, 4, ImVec2(1.0f), shadow_col); + ImGuiEx::DrawRectShadow(rect.min, rect.max, border_radius, 4, Vec2(1.0f), shadow_col); ImDrawFlags flags = ImDrawFlags_RoundCornersAll; - draw_list->AddRectFilled(rect_min, rect_max, color, border_radius, flags); - draw_list->AddRect(rect_min + ImVec2(1.0f), rect_max, border_highlight_col, border_radius, flags, border_width); - draw_list->AddRect(rect_min, rect_max, border_col, border_radius, flags, border_width); + draw_list->AddRectFilled(rect.min, rect.max, ImColor(color), border_radius, flags); + draw_list->AddRect(rect.min + Vec2(1.0f), rect.max, ImColor(border_highlight_col), border_radius, flags, border_width); + draw_list->AddRect(rect.min, rect.max, ImColor(border_col), border_radius, flags, border_width); // Draw an additional blinking rectangle when selected if (selected) { auto alpha = sin(ImGui::GetTime() * 10.0F) * 0.25F + 0.5F; float offset = 4.0f; - draw_list->AddRect(rect_min - ImVec2(offset), rect_max + ImVec2(offset), ImColor(1.0f, 1.0f, 1.0f, float(alpha) ), border_radius + offset, ~0, offset / 2.0f); + draw_list->AddRect( + rect.min - Vec2(offset), + rect.max + Vec2(offset), + ImColor(1.0f, 1.0f, 1.0f, float(alpha) ), + border_radius + offset, + ~0, + offset / 2.0f + ); } } @@ -477,7 +486,7 @@ bool NodeView::_draw_property_view(PropertyView* _view) bool changed = false; Property* property = _view->get_property(); bool is_defined = property->value()->is_defined(); - const fw::type* owner_type = m_owner->get_type(); + const type* owner_type = m_owner->get_type(); VariableNode* connected_variable = _view->get_connected_variable(); /* @@ -534,7 +543,7 @@ bool NodeView::_draw_property_view(PropertyView* _view) } } - if ( fw::ImGuiEx::BeginTooltip() ) + if ( ImGuiEx::BeginTooltip() ) { ImGui::Text("%s %s\n", property->get_type()->get_name(), property->get_name().c_str()); @@ -550,16 +559,16 @@ bool NodeView::_draw_property_view(PropertyView* _view) ImGui::Text("source: \"%s\"", source_code.c_str()); - fw::ImGuiEx::EndTooltip(); + ImGuiEx::EndTooltip(); } // memorize property view rect (screen space) // enlarge rect to fit node_view top/bottom _view->screen_rect = { - ImVec2{ImGui::GetItemRectMin().x, get_screen_rect().Min.y} , - ImVec2{ImGui::GetItemRectMax().x, get_screen_rect().Max.y} + Vec2{ImGui::GetItemRectMin().x, rect( WORLD_SPACE ).min.y} , + Vec2{ImGui::GetItemRectMax().x, rect( WORLD_SPACE ).max.y} }; - fw::ImGuiEx::DebugCircle( _view->screen_rect.GetCenter(), 2.5f, ImColor(0,0,0)); + ImGuiEx::DebugCircle( _view->screen_rect.center(), 2.5f, ImColor(0,0,0)); return changed; } @@ -587,7 +596,7 @@ bool NodeView::draw_property_view(PropertyView* _view, const char* _override_lab char str[255]; snprintf(str, 255, "%s", variable->name.c_str() ); - ImGui::PushStyleColor(ImGuiCol_FrameBg, (ImVec4) variable->get_component()->get_color(Color_FILL) ); + ImGui::PushStyleColor(ImGuiCol_FrameBg, variable->get_component()->get_color(Color_FILL) ); ImGui::InputText(label.c_str(), str, 255, input_text_flags ); ImGui::PopStyleColor(); @@ -599,7 +608,7 @@ bool NodeView::draw_property_view(PropertyView* _view, const char* _override_lab else { /* Draw the property */ - const fw::type* property_type = property->get_type(); + const type* property_type = property->get_type(); bool read_only = _view->has_input_connected(); if( property_type->is() ) @@ -653,9 +662,9 @@ bool NodeView::draw_property_view(PropertyView* _view, const char* _override_lab return changed; } -bool NodeView::is_inside(NodeView* _nodeView, ImRect _rect) +bool NodeView::is_inside(NodeView* _nodeView, Rect _rect, Space _space) { - return _rect.Contains(_nodeView->get_rect()); + return Rect::contains(_rect, _nodeView->rect(_space) ); } void NodeView::draw_as_properties_panel(NodeView *_view, bool *_show_advanced) @@ -675,7 +684,7 @@ void NodeView::draw_as_properties_panel(NodeView *_view, bool *_show_advanced) ImGui::SameLine(); ImGui::Text("(?)"); - if ( fw::ImGuiEx::BeginTooltip() ) + if ( ImGuiEx::BeginTooltip() ) { const auto variant = property->value(); ImGui::Text("initialized: %s,\n" @@ -686,7 +695,7 @@ void NodeView::draw_as_properties_panel(NodeView *_view, bool *_show_advanced) variant->is_defined() ? "true" : "false", property->token.json().c_str() ); - fw::ImGuiEx::EndTooltip(); + ImGuiEx::EndTooltip(); } // input ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); @@ -851,29 +860,27 @@ void NodeView::draw_as_properties_panel(NodeView *_view, bool *_show_advanced) ImGui::Separator(); } -void NodeView::constraint_to_rect(NodeView* _view, ImRect _rect) +void NodeView::constraint_to_rect(NodeView* _view, Rect _rect) { - if ( !NodeView::is_inside(_view, _rect)) { - - _rect.Expand(ImVec2(-2, -2)); // shrink + if ( !NodeView::is_inside(_view, _rect, WORLD_SPACE )) { - auto nodeRect = _view->get_rect(); + _rect.expand( Vec2( -2, -2 ) ); // shrink - auto newPos = _view->get_position(fw::Space_Local, true); + auto nodeRect = _view->rect( WORLD_SPACE ); - auto left = _rect.Min.x - nodeRect.Min.x; - auto right = _rect.Max.x - nodeRect.Max.x; - auto up = _rect.Min.y - nodeRect.Min.y; - auto down = _rect.Max.y - nodeRect.Max.y; + auto left = _rect.min.x - nodeRect.min.x; + auto right = _rect.max.x - nodeRect.max.x; + auto up = _rect.min.y - nodeRect.min.y; + auto down = _rect.max.y - nodeRect.max.y; - if ( left > 0 ) nodeRect.TranslateX(left); - else if ( right < 0 ) nodeRect.TranslateX(right); + if ( left > 0 ) nodeRect.translate_x( left ); + else if ( right < 0 ) nodeRect.translate_x( right ); - if ( up > 0 ) nodeRect.TranslateY(up); - else if ( down < 0 ) nodeRect.TranslateY(down); + if ( up > 0 ) nodeRect.translate_y( up ); + else if ( down < 0 )nodeRect.translate_y( down ); - _view->set_position(nodeRect.GetCenter(), fw::Space_Local); + _view->position( nodeRect.center(), PARENT_SPACE ); } } @@ -891,81 +898,79 @@ void NodeView::set_view_detail(NodeViewDetail _viewDetail) } } -ImRect NodeView::get_rect(bool _recursively, bool _ignorePinned, bool _ignoreMultiConstrained, bool _ignoreSelf) const +Rect NodeView::get_rect(Space space, NodeViewFlags flags) const { - if( !_recursively) - { - ImVec2 local_position = get_position(fw::Space_Local); - ImRect rect{local_position, local_position}; - rect.Expand(m_size * 0.5f); + const bool recursively = flags & NodeViewFlag_RECURSIVELY; + const bool ignore_self = flags & NodeViewFlag_IGNORE_SELF; + const bool ignore_pinned = flags & NodeViewFlag_IGNORE_PINNED; - return rect; + if( !recursively ) + { + return View::rect(space); } - ImRect result_rect( ImVec2(std::numeric_limits::max()), ImVec2(-std::numeric_limits::max()) ); + std::vector rects; - if ( !_ignoreSelf && m_is_visible ) + if ( !ignore_self && is_visible ) { - ImRect self_rect = get_rect(false); - fw::ImGuiEx::EnlargeToInclude(result_rect, self_rect); + rects.push_back( View::rect(space) ); } - auto enlarge_to_fit_all = [&](PoolID view_id) + auto push_view_rect = [&](PoolID view_id) { NodeView* view = view_id.get(); if( !view) return; - - if ( view->m_is_visible && !(view->m_pinned && _ignorePinned) && view->m_owner->should_be_constrain_to_follow_output( this->m_owner ) ) + if( !view->is_visible ) return; + if( view->m_pinned && ignore_pinned ) return; + if( view->m_owner->should_be_constrain_to_follow_output( this->m_owner ) ) { - ImRect child_rect = view->get_rect(true, _ignorePinned, _ignoreMultiConstrained); - fw::ImGuiEx::EnlargeToInclude(result_rect, child_rect); + Rect rect = view->get_rect(space, flags); + rects.push_back( rect ); } }; auto children = get_adjacent(SlotFlag_CHILD); - std::for_each( children.begin(), children.end(), enlarge_to_fit_all); + std::for_each( children.begin(), children.end(), push_view_rect ); auto inputs = get_adjacent(SlotFlag_INPUT); - std::for_each( inputs.begin() , inputs.end() , enlarge_to_fit_all); + std::for_each( inputs.begin() , inputs.end() , push_view_rect ); + + Rect result = Rect::bbox(rects); #ifdef NDBL_DEBUG - ImRect screen_rect = result_rect; - screen_rect.Translate( get_position(Space_Screen) - get_position(Space_Local) ); - fw::ImGuiEx::DebugRect(screen_rect.Min, screen_rect.Max, IM_COL32( 0, 255, 0, 60 ), 2 ); + Rect screen_rect = result; + screen_rect.translate( position(space) - position(PARENT_SPACE) ); + ImGuiEx::DebugRect(screen_rect.min, screen_rect.max, IM_COL32( 0, 255, 0, 60 ), 2 ); #endif - return result_rect; + return result; } -void NodeView::translate_to(ImVec2 desiredPos, float _factor, bool _recurse) +Rect NodeView::get_rect( + const std::vector &_views, + Space space, + NodeViewFlags flags +) { - ImVec2 delta(desiredPos - m_position); + std::vector rects; - bool isDeltaTooSmall = delta.x * delta.x + delta.y * delta.y < 0.01f; - if (!isDeltaTooSmall) + for (auto eachView : _views) { - auto factor = std::min(1.0f, _factor); - translate(delta * factor, _recurse); + Rect rect = eachView->get_rect(space, flags); + rects.push_back( rect ); } + + return Rect::bbox( rects ); } -ImRect NodeView::get_rect( - const std::vector &_views, - bool _recursive, - bool _ignorePinned, - bool _ignoreMultiConstrained) +std::vector NodeView::get_rects(const std::vector& _in_views, Space space, NodeViewFlags flags) { - ImRect rect(ImVec2(std::numeric_limits::max()), ImVec2(-std::numeric_limits::max()) ); - - for (auto eachView : _views) + std::vector rects; + for (auto each_target : _in_views ) { - if ( eachView->m_is_visible ) - { - auto each_rect = eachView->get_rect(_recursive, _ignorePinned, _ignoreMultiConstrained); - fw::ImGuiEx::EnlargeToInclude(rect, each_rect); - } + rects.push_back( each_target->get_rect(space, flags )); } - return rect; + return std::move( rects ); } void NodeView::set_expanded_rec(bool _expanded) @@ -1006,7 +1011,7 @@ void NodeView::set_adjacent_visible(SlotFlags flags, bool _visible, bool _recurs each_child_view->set_children_visible(_visible, true); each_child_view->set_inputs_visible(_visible, true); } - each_child_view->set_visible(_visible); + each_child_view->is_visible = _visible; } } } @@ -1023,7 +1028,7 @@ NodeView* NodeView::substitute_with_parent_if_not_visible(NodeView* _view, bool return _view; } - if( _view->is_visible() ) + if( _view->is_visible ) { return _view; } @@ -1068,12 +1073,6 @@ void NodeView::expand_toggle_rec() return set_expanded_rec(!m_expanded); } -ImRect NodeView::get_screen_rect() const -{ - ImVec2 half_size = m_size / 2.0f; - ImVec2 screen_pos = get_position(fw::Space_Screen, false); - return {screen_pos - half_size, screen_pos + half_size}; -} bool NodeView::is_any_selected() { @@ -1085,42 +1084,42 @@ bool NodeView::is_dragged() const return s_dragged == m_id; } -ImVec2 NodeView::get_slot_normal( const Slot& slot ) const +Vec2 NodeView::get_slot_normal( const Slot& slot ) const { // Alignment is usually not a corner, so we don't need to normalize. return m_slot_views[(u8_t)slot.id].alignment(); } -ImVec2 NodeView::get_slot_pos( const Slot& slot ) +Vec2 NodeView::get_slot_pos( const Slot& slot ) { // TODO: use 3x3 matrices to simplify code if( slot.type() == SlotFlag_TYPE_VALUE && slot.get_property()->is_this() ) { - return get_screen_rect().GetCenter() - + get_screen_rect().GetSize() * m_slot_views[(u8_t)slot.id].alignment(); + Rect r = rect( WORLD_SPACE ); + return r.center() + r.size() * m_slot_views[(u8_t)slot.id].alignment(); } - ImRect property_rect = m_property_views.at( (u32_t)slot.property ).screen_rect; - return property_rect.GetCenter() - + property_rect.GetSize() * m_slot_views[(u8_t)slot.id].alignment(); + Rect property_rect = m_property_views.at( (u32_t)slot.property ).screen_rect; + return property_rect.center() + + property_rect.size() * m_slot_views[(u8_t)slot.id].alignment(); } -ImRect NodeView::get_slot_rect( const Slot& _slot, const Config& _config, i8_t _count ) const +Rect NodeView::get_slot_rect( const Slot& _slot, const Config& _config, i8_t _count ) const { return get_slot_rect( m_slot_views[_slot.id.m_value], _config, _count ); } -ImRect NodeView::get_slot_rect( const SlotView& _slot_view, const Config& _config, i8_t _pos ) const +Rect NodeView::get_slot_rect( const SlotView& _slot_view, const Config& _config, i8_t _pos ) const { - ImRect rect({0.0f, 0.0f }, _config.ui_node_slot_size); - rect.TranslateY( -rect.GetSize().y * 0.5f ); // Center vertically - rect.TranslateX( _config.ui_node_slot_size.x * float(_pos) // x offset - + _config.ui_node_slot_gap * float(1+_pos) ); // x gap - rect.TranslateY( _slot_view.alignment().y * rect.GetSize().y ); // align top/bottom - ImRect view_rect = get_screen_rect(); - rect.Translate(_slot_view.alignment() * view_rect.GetSize() + view_rect.GetCenter()); // align slot with nodeview - - return rect; + Rect result({0.0f, 0.0f }, _config.ui_node_slot_size); + result.translate_y( -result.size().y * 0.5f ); // Center vertically + result.translate_x( _config.ui_node_slot_size.x * float( _pos ) // x offset + + _config.ui_node_slot_gap * float( 1 + _pos ) ); // x gap + result.translate_y( _slot_view.alignment().y * result.size().y ); // align top/bottom + Rect view_rect = rect( WORLD_SPACE ); + result.translate( _slot_view.alignment() * view_rect.size() + view_rect.center() ); // align slot with nodeview + + return result; } std::vector> NodeView::get_adjacent(SlotFlags flags) const @@ -1128,18 +1127,18 @@ std::vector> NodeView::get_adjacent(SlotFlags flags) const return GraphUtil::adjacent_components(m_owner.get(), flags); } -void NodeView::set_color( const ImVec4* _color, ColorType _type ) +void NodeView::set_color( const Vec4* _color, ColorType _type ) { m_colors[_type] = _color; } -ImColor NodeView::get_color( ColorType _type ) const +Vec4 NodeView::get_color( ColorType _type ) const { - return ImColor(*m_colors[_type]); + return *m_colors[_type]; } bool NodeView::none_is_visible( std::vector _views ) { - auto is_visible = [](const NodeView* view) { return view->is_visible(); }; + auto is_visible = [](const NodeView* view) { return view->is_visible; }; return std::find_if(_views.begin(), _views.end(), is_visible) == _views.end(); } diff --git a/src/nodable/gui/NodeView.h b/src/nodable/gui/NodeView.h index 147c8a3b3..4da3bf8bc 100644 --- a/src/nodable/gui/NodeView.h +++ b/src/nodable/gui/NodeView.h @@ -7,13 +7,14 @@ #include #include -#include "fw/gui/ImGuiEx.h" -#include "fw/gui/View.h" -#include "core/Component.h" // base class -#include "core/Property.h" #include "Config.h" #include "PropertyView.h" #include "SlotView.h" +#include "nodable/core/Component.h"// base class +#include "nodable/core/Property.h" +#include "fw/core/geometry/Box2D.h" +#include "fw/gui/ImGuiEx.h" +#include "fw/gui/View.h" #include "types.h" namespace ndbl @@ -44,6 +45,17 @@ namespace ndbl Color_COUNT }; + typedef int NodeViewFlags; + enum NodeViewFlag_ + { + NodeViewFlag_NONE = 0, + NodeViewFlag_RECURSIVELY = 1 << 0, + NodeViewFlag_IGNORE_PINNED = 1 << 1, + NodeViewFlag_IGNORE_MULTICONSTRAINED = 1 << 2, + NodeViewFlag_IGNORE_SELF = 1 << 3, + NodeViewFlag_IGNORE_HIDDEN = 1 << 4 + }; + /** * This class implement a view for Nodes using ImGui. */ @@ -58,19 +70,15 @@ namespace ndbl std::vector> get_adjacent(SlotFlags) const; void pinned(bool b) { m_pinned = b; } bool pinned() const { return m_pinned; } - bool draw()override; + bool onDraw()override; void set_owner(PoolID)override; bool update(float); - ImVec2 get_position() const { return m_position; }; - ImVec2 get_position(fw::Space, bool round = false) const; - void set_position(ImVec2, fw::Space); - void translate(ImVec2, bool _recurse = false); - void translate_to(ImVec2 desiredPos, float _factor, bool _recurse = false); + void translate(fw::Vec2, NodeViewFlags flags ); void arrange_recursively(bool _smoothly = true); std::string get_label(); - ImRect get_rect(bool _recursively = false, bool _ignorePinned = true, bool _ignoreMultiConstrained = true, bool _ignoreSelf = false) const; + fw::Rect get_rect(fw::Space, NodeViewFlags = NodeViewFlag_IGNORE_PINNED | NodeViewFlag_IGNORE_MULTICONSTRAINED) const; const PropertyView* get_property_view( ID _id )const; - inline ImVec2 get_size() const { return m_size; } + inline fw::Vec2 get_size() const { return box.size(); } bool is_dragged()const; bool is_expanded()const { return m_expanded; } void set_expanded_rec(bool _expanded); @@ -80,19 +88,15 @@ namespace ndbl void expand_toggle(); void expand_toggle_rec(); void enable_edition(bool _enable = true) { m_edition_enable = _enable; } - ImRect get_screen_rect() const; - static ImRect get_rect( - const std::vector &_views, - bool _recursive = false, - bool _ignorePinned = true, - bool _ignoreMultiConstrained = true); // rectangle is in local space + static fw::Rect get_rect(const std::vector &_views, fw::Space, NodeViewFlags = NodeViewFlag_NONE ); + static std::vector get_rects( const std::vector& _in_views, fw::Space space, NodeViewFlags flags = NodeViewFlag_NONE ); static void set_selected(PoolID); static PoolID get_selected(); static bool is_selected(PoolID); static bool is_any_dragged(); static bool is_any_selected(); - static bool is_inside(NodeView*, ImRect); - static void constraint_to_rect(NodeView*, ImRect); + static bool is_inside(NodeView*, fw::Rect, fw::Space); + static void constraint_to_rect(NodeView*, fw::Rect ); static PoolID get_dragged(); static bool draw_property_view(PropertyView*, const char* _override_label); static void draw_as_properties_panel(NodeView* _view, bool *_nodes ); @@ -100,41 +104,48 @@ namespace ndbl static NodeViewDetail get_view_detail() { return s_view_detail; } static NodeView* substitute_with_parent_if_not_visible(NodeView* _view, bool _recursive = true); static std::vector substitute_with_parent_if_not_visible(const std::vector& _in, bool _recurse = true ); - ImVec2 get_slot_pos( const Slot& ); - ImRect get_slot_rect( const Slot& _slot, const Config& _config, i8_t _count ) const; - ImRect get_slot_rect( const SlotView &_slot_view, const Config &_config, i8_t _pos ) const; - ImVec2 get_slot_normal( const Slot& slot) const; - void set_color( const ImVec4* _color, ColorType _type = Color_FILL ); - ImColor get_color(ColorType _type) const; + fw::Vec2 get_slot_pos( const Slot& ); + fw::Rect get_slot_rect( const Slot& _slot, const Config& _config, i8_t _count ) const; + fw::Rect get_slot_rect( const SlotView &_slot_view, const Config &_config, i8_t _pos ) const; + fw::Vec2 get_slot_normal( const Slot& slot) const; + void set_color( const fw::Vec4* _color, ColorType _type = Color_FILL ); + fw::Vec4 get_color(ColorType _type) const; + static bool none_is_visible( std::vector vector1 ); private: - void set_adjacent_visible(SlotFlags flags, bool _visible, bool _recursive); bool _draw_property_view(PropertyView* _view); void update_labels_from_name(const Node *_node); - static void DrawNodeRect( ImVec2 rect_min, ImVec2 rect_max, ImColor color, ImColor border_highlight_col, ImColor shadow_col, ImColor border_col, bool selected, float border_radius, float border_width ); + static void DrawNodeRect( + fw::Rect rect, + fw::Vec4 color, + fw::Vec4 border_highlight_col, + fw::Vec4 shadow_col, + fw::Vec4 border_col, + bool selected, + float border_radius, + float border_width + ); std::string m_label; std::string m_short_label; bool m_edition_enable; bool m_expanded; - ImVec2 m_position; // local position (not affected by scroll) - ImVec2 m_size; bool m_pinned; - float m_opacity; - std::array m_colors; - std::vector m_slot_views; - std::vector m_property_views; - PropertyView* m_property_view_this; - std::vector m_property_views_with_input_only; - std::vector m_property_views_with_output_or_inout; - static PoolID s_selected; - static PoolID s_dragged; - static const float s_property_input_size_min; - static const ImVec2 s_property_input_toggle_button_size; - static NodeViewDetail s_view_detail; + float m_opacity; + std::array m_colors; + std::vector m_slot_views; + std::vector m_property_views; + PropertyView* m_property_view_this; + std::vector m_property_views_with_input_only; + std::vector m_property_views_with_output_or_inout; + static PoolID s_selected; + static PoolID s_dragged; + static const float s_property_input_size_min; + static const fw::Vec2 s_property_input_toggle_button_size; - REFLECT_DERIVED_CLASS() + static NodeViewDetail s_view_detail; + REFLECT_DERIVED_CLASS() }; } diff --git a/src/nodable/gui/NodeViewConstraint.cpp b/src/nodable/gui/NodeViewConstraint.cpp index bdd86133d..547640777 100644 --- a/src/nodable/gui/NodeViewConstraint.cpp +++ b/src/nodable/gui/NodeViewConstraint.cpp @@ -1,12 +1,9 @@ #include "NodeViewConstraint.h" - #include - -#include "core/ForLoopNode.h" - -#include "Nodable.h" -#include "NodeView.h" -#include "Physics.h" +#include "nodable/core/ForLoopNode.h" +#include "nodable/gui/Nodable.h" +#include "nodable/gui/NodeView.h" +#include "nodable/gui/Physics.h" using namespace ndbl; using namespace fw; @@ -19,22 +16,6 @@ NodeViewConstraint::NodeViewConstraint(const char* _name, ConstrainFlags _flags) { } -/** TODO: move this in a class (not NodeViewConstrain) */ -std::vector get_rect(const std::vector& _in_views) -{ - std::vector _out; - for (auto each_target : _in_views ) - { - ImRect rect; - if( !(each_target->pinned() || !each_target->is_visible()) ) - { - rect = each_target->get_rect( true ); - } - _out.push_back(rect); - } - return std::move(_out); -} - void NodeViewConstraint::apply(float _dt) { // Check if this constrain should apply @@ -64,9 +45,21 @@ void NodeViewConstraint::apply(float _dt) NodeView* driver = clean_drivers[0]; const bool align_bbox_bottom = m_flags & ConstrainFlag_ALIGN_BBOX_BOTTOM; const float y_direction = align_bbox_bottom ? 1.0f : -1.0f; - ImVec2 virtual_cursor = driver->get_position(fw::Space_Local); + Vec2 virtual_cursor = driver->position( WORLD_SPACE ); const Node& driver_owner = *driver->get_owner(); - auto target_rects = get_rect( clean_targets ); + NodeViewFlags flags = NodeViewFlag_IGNORE_PINNED; + auto target_rects = NodeView::get_rects( clean_targets, WORLD_SPACE, flags ); + +#ifdef NDBL_DEBUG + if( config.common.debug ) + { + for(Rect r : target_rects) + { + r.expand(Vec2(4.f)); + ImGuiEx::DebugRect(r.min, r.max, ImColor(255,127,127), 4.f); + } + } +#endif // Determine horizontal alignment //------------------------------- @@ -98,7 +91,7 @@ void NodeViewConstraint::apply(float _dt) case Align_CENTER: { float size_x_total = 0.0f; - std::for_each( target_rects.begin(), target_rects.end(),[&](auto each ) { size_x_total += each.GetSize().x; }); + std::for_each( target_rects.begin(), target_rects.end(),[&](auto each ) { size_x_total += each.size().x; }); virtual_cursor.x -= size_x_total / 2.0f; } } @@ -112,19 +105,19 @@ void NodeViewConstraint::apply(float _dt) const Node& target_owner = *each_target->get_owner(); // Guards - if ( !each_target->is_visible() ) continue; + if ( !each_target->is_visible ) continue; if ( each_target->pinned() ) continue; if ( !target_owner.should_be_constrain_to_follow_output( driver_owner.poolid() ) && !align_bbox_bottom ) continue; // Compute new position for this input view - ImRect& target_rect = target_rects[target_index]; + Rect& target_rect = target_rects[target_index]; - ImVec2 relative_pos( - target_rect.GetWidth() / 2.0f, - y_direction * (target_rect.GetHeight() / 2.0f + config.ui_node_spacing) + Vec2 relative_pos( + target_rect.width() / 2.0f, + y_direction * ( target_rect.height() / 2.0f + config.ui_node_spacing) ); - if ( align_bbox_bottom ) relative_pos += y_direction * config.ui_node_spacing; + if ( align_bbox_bottom ) relative_pos.y += y_direction * config.ui_node_spacing; // Add a vertical space to avoid having too much wires aligned on x-axis // useful for "for" nodes. @@ -135,9 +128,8 @@ void NodeViewConstraint::apply(float _dt) } auto target_physics = target_owner.get_component(); - target_physics->add_force_to_translate_to( virtual_cursor + relative_pos + m_offset, config.ui_node_speed, true); - virtual_cursor.x += target_rect.GetWidth() + config.ui_node_spacing; - + target_physics->translate_to( WORLD_SPACE, virtual_cursor + relative_pos + m_offset, config.ui_node_speed, true ); + virtual_cursor.x += target_rect.width() + config.ui_node_spacing; } break; } @@ -145,7 +137,7 @@ void NodeViewConstraint::apply(float _dt) case ConstrainFlag_LAYOUT_DEFAULT: { NodeView* target = clean_targets[0]; - if (!target->pinned() && target->is_visible() ) + if (!target->pinned() && target->is_visible ) { Physics& target_physics = *target->get_owner()->get_component(); @@ -158,29 +150,34 @@ void NodeViewConstraint::apply(float _dt) */ // compute - auto drivers_rect = NodeView::get_rect(clean_drivers, false); - - auto target_rect = target->get_rect(true, true); - ImVec2 target_driver_offset = drivers_rect.Max.y - target_rect.Min.y; - ImVec2 new_pos; - ImVec2 target_position = target->get_position(fw::Space_Local); - new_pos.x = drivers_rect.GetTL().x + target->get_size().x * 0.5f ; - new_pos.y = target_position.y + target_driver_offset.y + config.ui_node_spacing; + auto drivers_rect = NodeView::get_rect(clean_drivers, WORLD_SPACE); + + NodeViewFlags flags = NodeViewFlag_RECURSIVELY + | NodeViewFlag_IGNORE_PINNED + | NodeViewFlag_IGNORE_MULTICONSTRAINED; + auto target_rect = target->get_rect(WORLD_SPACE, flags); + float target_driver_offset = drivers_rect.max.y - target_rect.min.y; + Vec2 new_pos; + Vec2 target_position = target->position( WORLD_SPACE ); + new_pos.x = drivers_rect.tl().x + target->get_size().x * 0.5f ; + new_pos.y = target_position.y + target_driver_offset + config.ui_node_spacing; // apply - target_physics.add_force_to_translate_to(new_pos + m_offset, config.ui_node_speed, true); + target_physics.translate_to( WORLD_SPACE, new_pos + m_offset, config.ui_node_speed, true ); } else { /* * Align first target's bbox border left with all driver's bbox border right */ - ImRect drivers_bbox = NodeView::get_rect(clean_drivers, true); - ImVec2 new_position(drivers_bbox.GetCenter() - - ImVec2(drivers_bbox.GetSize().x * 0.5f - + config.ui_node_spacing - + target->get_rect().GetSize().x * 0.5f, 0 )); - target_physics.add_force_to_translate_to(new_position + m_offset, config.ui_node_speed); + NodeViewFlags flags = NodeViewFlag_RECURSIVELY + | NodeViewFlag_IGNORE_PINNED + | NodeViewFlag_IGNORE_MULTICONSTRAINED; + Rect drivers_bbox = NodeView::get_rect(clean_drivers, WORLD_SPACE, flags); + Vec2 new_position = drivers_bbox.left(); + new_position.x += config.ui_node_spacing; + new_position.x += target->rect( WORLD_SPACE ).size().x * 0.5f; + target_physics.translate_to( WORLD_SPACE, new_position + m_offset, config.ui_node_speed ); } } } @@ -189,19 +186,23 @@ void NodeViewConstraint::apply(float _dt) void NodeViewConstraint::draw_debug_lines(const std::vector& _drivers,const std::vector& _targets ) { - if( ImGuiEx::debug ) +#ifdef NDBL_DEBUG + if( ImGuiEx::debug && NodeView::is_selected(_drivers[0]->poolid()) ) { for (auto each_target: _targets ) { for (auto each_driver: _drivers ) { ImGuiEx::DebugLine( - each_driver->get_position( Space_Screen), - each_target->get_position( Space_Screen), - IM_COL32(0, 0, 255, 30), 1.0f); + each_driver->position( WORLD_SPACE ), + each_target->position( WORLD_SPACE ), + IM_COL32(0, 0, 255, 30), + 1.0f + ); } } } +#endif } void NodeViewConstraint::add_target(PoolID _target) diff --git a/src/nodable/gui/NodeViewConstraint.h b/src/nodable/gui/NodeViewConstraint.h index 0394a7d2e..01962d655 100644 --- a/src/nodable/gui/NodeViewConstraint.h +++ b/src/nodable/gui/NodeViewConstraint.h @@ -1,9 +1,9 @@ #pragma once +#include "fw/core/geometry/Vec2.h" +#include "fw/core/memory/Pool.h" +#include "fw/core/reflection/reflection" #include -#include "imgui.h" -#include "core/reflection/reflection" -#include "core/Pool.h" namespace ndbl { @@ -64,7 +64,7 @@ namespace ndbl { void add_drivers(const std::vector>&); void draw_view(); - ImVec2 m_offset; // offset applied to the constraint + fw::Vec2 m_offset; // offset applied to the constraint static const Filter no_target_expanded; static const Filter drivers_are_expanded; diff --git a/src/nodable/gui/Physics.cpp b/src/nodable/gui/Physics.cpp index a02dd3d5c..3f391381d 100644 --- a/src/nodable/gui/Physics.cpp +++ b/src/nodable/gui/Physics.cpp @@ -1,18 +1,20 @@ #include "Physics.h" + +#include "fw/core/math.h" +#include "nodable/core/ForLoopNode.h" +#include "nodable/core/GraphUtil.h" +#include "nodable/core/IConditional.h" +#include "nodable/core/Node.h" +#include "nodable/core/NodeUtils.h" + #include "NodeView.h" -#include "core/ForLoopNode.h" -#include "core/GraphUtil.h" -#include "core/IConditional.h" -#include "core/Node.h" -#include "core/NodeUtils.h" -#include "core/math.h" using namespace ndbl; using namespace fw; REGISTER { - fw::registration::push_class("Physics") + registration::push_class("Physics") .extends(); }; @@ -47,14 +49,15 @@ void Physics::apply_constraints(float _dt) } } -void Physics::add_force_to_translate_to(ImVec2 desiredPos, float _factor, bool _recurse) +void Physics::translate_to( fw::Space space, fw::Vec2 target_pos, float _factor, bool _recurse) { - ImVec2 delta(desiredPos - m_view->get_position()); + Vec2 delta( target_pos - m_view->position(space)); auto factor = std::max(0.0f, _factor); - add_force(delta * factor, _recurse); + auto force = Vec2::scale(delta, factor); + add_force( force, _recurse); } -void Physics::add_force(ImVec2 force, bool _recurse) +void Physics::add_force( Vec2 force, bool _recurse) { m_forces_sum += force; @@ -76,16 +79,16 @@ void Physics::add_force(ImVec2 force, bool _recurse) void Physics::apply_forces(float _dt, bool _recurse) { - float magnitude = std::sqrt(m_forces_sum.x * m_forces_sum.x + m_forces_sum.y * m_forces_sum.y ); - - constexpr float magnitude_max = 1000.0f; - const float friction = fw::math::lerp (0.0f, 0.5f, magnitude / magnitude_max); - const ImVec2 avg_forces_sum = (m_forces_sum + m_last_frame_forces_sum) * 0.5f; + float magnitude_max = 1000.0f; + float magnitude = std::sqrt(m_forces_sum.x * m_forces_sum.x + m_forces_sum.y * m_forces_sum.y ); + float friction = lerp(0.0f, 0.5f, magnitude / magnitude_max); + Vec2 avg_forces_sum = Vec2::scale(m_forces_sum + m_last_frame_forces_sum, 0.5f); + Vec2 delta = Vec2::scale(avg_forces_sum, (1.0f - friction) * _dt); - m_view->translate( avg_forces_sum * ( 1.0f - friction) * _dt , _recurse); + m_view->translate( delta , _recurse); m_last_frame_forces_sum = avg_forces_sum; - m_forces_sum = ImVec2(); + m_forces_sum = Vec2(); } void Physics::create_constraints(const std::vector>& nodes) @@ -97,7 +100,7 @@ void Physics::create_constraints(const std::vector>& nodes) auto each_physics = each_node->get_component(); if ( each_view ) { - const fw::type* node_type = each_node->get_type(); + const type* node_type = each_node->get_type(); // Follow predecessor Node(s), except if first predecessor is a Conditional //------------------------------------------------------------------------- diff --git a/src/nodable/gui/Physics.h b/src/nodable/gui/Physics.h index 993fb2411..99984887e 100644 --- a/src/nodable/gui/Physics.h +++ b/src/nodable/gui/Physics.h @@ -1,7 +1,10 @@ #pragma once -#include "imgui.h" -#include "core/Component.h" -#include "NodeViewConstraint.h" + +#include "fw/core/geometry/Space.h" +#include "fw/core/geometry/XForm2D.h" +#include "nodable/core/Component.h" +#include "nodable/gui/NodeViewConstraint.h" + namespace ndbl { // forward declarations @@ -21,15 +24,15 @@ namespace ndbl void add_constraint(NodeViewConstraint&); void apply_constraints(float _dt); void clear_constraints(); - void add_force_to_translate_to(ImVec2 desiredPos, float _factor, bool _recurse = false); - void add_force(ImVec2 force, bool _recurse = false); + void translate_to(fw::Space, fw::Vec2 target_pos, float _factor, bool _recurse = false ); + void add_force(fw::Vec2 force, bool _recurse = false); void apply_forces(float _dt, bool _recurse); static void create_constraints(const std::vector>&); static void destroy_constraints(std::vector &physics_components); private: PoolID m_view; - ImVec2 m_forces_sum; - ImVec2 m_last_frame_forces_sum; + fw::Vec2 m_forces_sum; + fw::Vec2 m_last_frame_forces_sum; REFLECT_DERIVED_CLASS() }; diff --git a/src/nodable/gui/PropertyView.cpp b/src/nodable/gui/PropertyView.cpp index 45f843855..2a702ef9a 100644 --- a/src/nodable/gui/PropertyView.cpp +++ b/src/nodable/gui/PropertyView.cpp @@ -1,8 +1,9 @@ #include "PropertyView.h" + +#include "nodable/core/language/Nodlang.h" +#include "nodable/core/Node.h" #include "NodeView.h" #include "SlotView.h" -#include "core/language/Nodlang.h" -#include "nodable/core/Node.h" using namespace ndbl; using namespace fw; @@ -63,5 +64,5 @@ VariableNode* PropertyView::get_connected_variable() const return nullptr; } - return fw::cast( adjacent_slot->node.get() ); + return cast( adjacent_slot->node.get() ); } \ No newline at end of file diff --git a/src/nodable/gui/PropertyView.h b/src/nodable/gui/PropertyView.h index d5fa5ceaa..1d33b1a74 100644 --- a/src/nodable/gui/PropertyView.h +++ b/src/nodable/gui/PropertyView.h @@ -1,14 +1,15 @@ #pragma once -#include "core/Node.h" -#include "core/VariableNode.h" -#include "fw/core/Pool.h" -#include "imgui.h" -#include "imgui_internal.h" #include -namespace ndbl { +#include "fw/core/geometry/Rect.h" +#include "fw/core/memory/Pool.h" +#include "nodable/core/Node.h" +#include "nodable/core/VariableNode.h" + +namespace ndbl +{ // forward declarations class Property; class NodeView; @@ -23,7 +24,7 @@ namespace ndbl { public: ID property_id; PoolID node_view; - ImRect screen_rect; + fw::Rect screen_rect; bool show_input; bool touched; diff --git a/src/nodable/gui/SlotView.cpp b/src/nodable/gui/SlotView.cpp index 738364f18..1fc381b5b 100644 --- a/src/nodable/gui/SlotView.cpp +++ b/src/nodable/gui/SlotView.cpp @@ -4,12 +4,13 @@ #include "Nodable.h" using namespace ndbl; +using namespace fw; SlotView *SlotView::s_focused = nullptr; SlotView *SlotView::s_dragged = nullptr; SlotView *SlotView::s_hovered = nullptr; -SlotView::SlotView( Slot &_slot, ImVec2 _alignment ) +SlotView::SlotView(Slot &_slot, Vec2 _alignment ) : m_slot(_slot) , m_alignment(_alignment) { @@ -18,30 +19,31 @@ SlotView::SlotView( Slot &_slot, ImVec2 _alignment ) void SlotView::draw_slot_circle( ImDrawList* _draw_list, SlotView& _view, - ImVec2 _position, + Vec2 _position, float _radius, - const ImColor& _color, - const ImColor& _border_color, - const ImColor& _hover_color, + Vec4 _color, + Vec4 _border_color, + Vec4 _hover_color, bool _readonly) { constexpr float INVISIBLE_BUTTON_SIZE_RATIO = 1.2f; // 120% // draw //----- - ImGui::SetCursorScreenPos( _position - ImVec2(_radius * INVISIBLE_BUTTON_SIZE_RATIO )); + Vec2 cursor_pos{_position - Vec2( _radius * INVISIBLE_BUTTON_SIZE_RATIO)}; + ImGui::SetCursorScreenPos( cursor_pos); // draw a larger invisible button on top of the circle to facilitate click/drag ImGui::PushID((u8_t)_view.m_slot.id); - ImGui::InvisibleButton("###", ImVec2(_radius * 2.0f * INVISIBLE_BUTTON_SIZE_RATIO, _radius * 2.0f * INVISIBLE_BUTTON_SIZE_RATIO )); + ImGui::InvisibleButton("###", Vec2(_radius * 2.0f * INVISIBLE_BUTTON_SIZE_RATIO, _radius * 2.0f * INVISIBLE_BUTTON_SIZE_RATIO )); ImGui::PopID(); bool is_hovered = ImGui::IsItemHovered(ImGuiHoveredFlags_RectOnly); // draw the circle - _draw_list->AddCircleFilled( _position, _radius, is_hovered ? _hover_color : _color); - _draw_list->AddCircle( _position, _radius, _border_color ); - fw::ImGuiEx::DebugCircle( _position, _radius, _border_color, ImColor(255, 0, 0, 0)); + _draw_list->AddCircleFilled( _position, _radius, ImColor(is_hovered ? _hover_color : _color)); + _draw_list->AddCircle( _position, _radius, ImColor(_border_color) ); + ImGuiEx::DebugCircle( _position, _radius, ImColor(_border_color)); behavior(_view, _readonly); } @@ -49,14 +51,14 @@ void SlotView::draw_slot_circle( void SlotView::draw_slot_rectangle( ImDrawList* _draw_list, SlotView& _view, - ImRect _rect, - const ImColor& _color, - const ImColor& _border_color, - const ImColor& _hover_color, + Rect _rect, + Vec4 _color, + Vec4 _border_color, + Vec4 _hover_color, float _border_radius, bool _readonly) { - ImVec2 rect_size = _rect.GetSize(); + Vec2 rect_size = _rect.size(); // Return early if rectangle cannot be draw. // TODO: Find why size can be zero more (more surprisingly) nan. @@ -64,15 +66,15 @@ void SlotView::draw_slot_rectangle( ImDrawCornerFlags corner_flags = _view.m_slot.has_flags(SlotFlag_ORDER_FIRST) ? ImDrawCornerFlags_Bot : ImDrawCornerFlags_Top; - ImGui::SetCursorScreenPos( _rect.GetTL()); + ImGui::SetCursorScreenPos( _rect.tl()); ImGui::PushID((u8_t)_view.m_slot.id); - ImGui::InvisibleButton("###", _rect.GetSize()); + ImGui::InvisibleButton("###", _rect.size()); ImGui::PopID(); - ImColor fill_color = ImGui::IsItemHovered(ImGuiHoveredFlags_RectOnly) ? _hover_color : _color; - _draw_list->AddRectFilled( _rect.Min, _rect.Max, fill_color, _border_radius, corner_flags ); - _draw_list->AddRect( _rect.Min, _rect.Max, _border_color, _border_radius, corner_flags ); - fw::ImGuiEx::DebugRect( _rect.Min, _rect.Max, ImColor(255,0, 0, 127), 0.0f ); + Vec4 fill_color = ImGui::IsItemHovered(ImGuiHoveredFlags_RectOnly) ? _hover_color : _color; + _draw_list->AddRectFilled( _rect.min, _rect.max, ImColor(fill_color), _border_radius, corner_flags ); + _draw_list->AddRect( _rect.min, _rect.max, ImColor(_border_color), _border_radius, corner_flags ); + ImGuiEx::DebugRect( _rect.min, _rect.max, ImColor(255,0, 0, 127), 0.0f ); behavior(_view, _readonly); } @@ -85,7 +87,7 @@ void SlotView::behavior(SlotView& _view, bool _readonly) { if ( ImGui::MenuItem(ICON_FA_TRASH " Disconnect")) { - auto& event_manager = fw::EventManager::get_instance(); + auto& event_manager = EventManager::get_instance(); event_manager.dispatch({ _view.slot() }); } @@ -97,10 +99,10 @@ void SlotView::behavior(SlotView& _view, bool _readonly) if ( ImGui::IsItemHovered(ImGuiHoveredFlags_RectOnly) ) { SlotView::reset_hovered(&_view); - if( fw::ImGuiEx::BeginTooltip() ) + if( ImGuiEx::BeginTooltip() ) { ImGui::Text("%s", SlotView::get_tooltip(_view).c_str() ); - fw::ImGuiEx::EndTooltip(); + ImGuiEx::EndTooltip(); } if ( ImGui::IsMouseDown(0) && !is_dragging() && !NodeView::is_any_dragged()) @@ -128,12 +130,12 @@ PoolID SlotView::get_node()const return m_slot.node; } -ImVec2 SlotView::position()const +Vec2 SlotView::position()const { return m_slot.node->get_component()->get_slot_pos( m_slot ); } -ImRect SlotView::rect(Config& config)const +Rect SlotView::get_rect(Config& config)const { return m_slot.node->get_component()->get_slot_rect( *this, config, 0 ); } @@ -146,7 +148,7 @@ void SlotView::drop_behavior(bool &require_new_node, bool _enable_edition) { if ( s_hovered ) { - auto& event_manager = fw::EventManager::get_instance(); + auto& event_manager = EventManager::get_instance(); event_manager.dispatch({ s_dragged->m_slot, s_hovered->m_slot}); reset_hovered(); @@ -164,13 +166,13 @@ void SlotView::drop_behavior(bool &require_new_node, bool _enable_edition) } } -const fw::type* SlotView::get_property_type()const +const type* SlotView::get_property_type()const { Property* property = get_property(); return property ? property->get_type() : nullptr; } -ImVec2 SlotView::alignment() const +Vec2 SlotView::alignment() const { return m_alignment; } diff --git a/src/nodable/gui/SlotView.h b/src/nodable/gui/SlotView.h index 88e4be1b6..9f91bcfbf 100644 --- a/src/nodable/gui/SlotView.h +++ b/src/nodable/gui/SlotView.h @@ -1,10 +1,13 @@ #pragma once -#include "Config.h" -#include "core/Slot.h" -#include "core/reflection/type.h" + +#include + +#include "fw/core/reflection/type.h" #include "fw/gui/ImGuiEx.h" -#include "observe/event.h" + +#include "nodable/core/Slot.h" #include "types.h" +#include "Config.h" namespace ndbl { @@ -20,16 +23,16 @@ namespace ndbl class SlotView { public: - SlotView( Slot& _slot, ImVec2 _alignment ); + SlotView( Slot& _slot, fw::Vec2 _alignment ); Property* get_property()const; const fw::type* get_property_type()const; bool has_node_connected() const; - ImVec2 alignment() const; + fw::Vec2 alignment() const; Slot& slot()const; PoolID get_node()const; - ImVec2 position()const; - ImRect rect(Config& config)const; + fw::Vec2 position()const; + fw::Rect get_rect(Config& config)const; PoolID adjacent_node() const; bool is_this() const; bool allows(SlotFlag) const; @@ -42,12 +45,12 @@ namespace ndbl static void reset_focused(SlotView * slot = nullptr) { s_focused = slot; } static void reset_hovered(SlotView * slot = nullptr) { s_hovered = slot; } static void behavior(SlotView&, bool _readonly); - static void draw_slot_circle( ImDrawList* _draw_list, SlotView& _view, ImVec2 _position, float _radius, const ImColor &_color, const ImColor &_border_color, const ImColor &_hover_color, bool _readonly ); - static void draw_slot_rectangle(ImDrawList* _draw_list, SlotView& _view, ImRect _rect, const ImColor& _color, const ImColor& _border_color, const ImColor& _hover_color, float _border_radius, bool _readonly); + static void draw_slot_circle( ImDrawList* _draw_list, SlotView& _view, fw::Vec2 _position, float _radius, fw::Vec4 _color, fw::Vec4 _border_color, fw::Vec4 _hover_color, bool _readonly ); + static void draw_slot_rectangle(ImDrawList* _draw_list, SlotView& _view, fw::Rect _rect, fw::Vec4 _color, fw::Vec4 _border_color, fw::Vec4 _hover_color, float _border_radius, bool _readonly); private: Slot& m_slot; - ImVec2 m_alignment; + fw::Vec2 m_alignment; static SlotView* s_focused; static SlotView* s_dragged; static SlotView* s_hovered; diff --git a/src/nodable/gui/commands/Cmd_ReplaceText.h b/src/nodable/gui/commands/Cmd_ReplaceText.h index 5ee3f7935..2cdcef469 100644 --- a/src/nodable/gui/commands/Cmd_ReplaceText.h +++ b/src/nodable/gui/commands/Cmd_ReplaceText.h @@ -1,7 +1,7 @@ #pragma once -#include "gui/Command.h" #include -#include +#include "fw/gui/ImGuiEx.h" +#include "nodable/gui/Command.h" namespace ndbl { diff --git a/src/nodable/gui/commands/Cmd_WrappedTextEditorUndoRecord.h b/src/nodable/gui/commands/Cmd_WrappedTextEditorUndoRecord.h index cff961589..ab4bcc80b 100644 --- a/src/nodable/gui/commands/Cmd_WrappedTextEditorUndoRecord.h +++ b/src/nodable/gui/commands/Cmd_WrappedTextEditorUndoRecord.h @@ -1,5 +1,6 @@ #pragma once -#include "gui/Command.h" +#include "fw/gui/ImGuiEx.h" +#include "nodable/gui/Command.h" namespace ndbl {