diff --git a/.github/workflows/build.ps1 b/.github/workflows/build.ps1 index c10723e4..3eec5ab6 100644 --- a/.github/workflows/build.ps1 +++ b/.github/workflows/build.ps1 @@ -113,7 +113,7 @@ cmd.exe /c "call $vcpkgRoot\bootstrap-vcpkg.bat" vcpkg integrate install # Start the build -cmake --preset "${env:_RELEASE_CONFIGURATION}" +cmake --preset "${env:_RELEASE_CONFIGURATION}" -DCI_BUILD=ON cmake --build --preset "${env:_RELEASE_CONFIGURATION}" # Start the packaging diff --git a/.github/workflows/main-1.0.0.yaml b/.github/workflows/main-1.0.0.yaml index 1d535175..6331c97b 100644 --- a/.github/workflows/main-1.0.0.yaml +++ b/.github/workflows/main-1.0.0.yaml @@ -54,6 +54,11 @@ jobs: env: _BUILD_VERSION: "1.0.5.${{ github.run_number }}" GITHUB_PACKAGES_PAT: ${{ secrets.GITHUB_TOKEN }} + - name: Test + working-directory: ${{github.workspace}}\.build + # Execute tests defined by the CMake configuration. + # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail + run: ctest -C Release --output-on-failure - name: Upload vcpkg build logs if: failure() uses: actions/upload-artifact@v4 diff --git a/.github/workflows/ubuntu.yaml b/.github/workflows/ubuntu.yaml index a660fc0f..777792da 100644 --- a/.github/workflows/ubuntu.yaml +++ b/.github/workflows/ubuntu.yaml @@ -81,7 +81,7 @@ jobs: - name: Configure CMake # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type - run: cmake -B ${{github.workspace}}/build -G Ninja -DCMAKE_TOOLCHAIN_FILE=${{github.workspace}}/vcpkg/scripts/buildsystems/vcpkg.cmake -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} + run: cmake -B ${{github.workspace}}/build -G Ninja -DCMAKE_TOOLCHAIN_FILE=${{github.workspace}}/vcpkg/scripts/buildsystems/vcpkg.cmake -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCI_BUILD=ON - name: Build # Build your program with the given configuration diff --git a/CMakeLists.txt b/CMakeLists.txt index 56db4e8e..ef0119f3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,6 +13,18 @@ set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /NODEFAULTLIB:MSVCRT /NODEFAULTLIB:MSVCRTD /DEBUG:FULL /FORCE:MULTIPLE /IGNORE:4006,4075,4099,4217" ) +option(CI_BUILD "Set to ON when building on CI" OFF) +if(NOT CI_BUILD AND DEFINED ENV{CI_BUILD} AND "$ENV{CI_BUILD}" STREQUAL "ON") + set(CI_BUILD ON) +endif() +# Construct path depending on CI mode +if (CI_BUILD) + set(DEFAULT_CONFIG_ROOT_PATH "res") +else() + # Use full path when developing locally + set(DEFAULT_CONFIG_ROOT_PATH "${CMAKE_SOURCE_DIR}/res") +endif() + if(CMAKE_BUILD_TYPE MATCHES Debug) set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreadedDebug") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /NODEFAULTLIB:LIBCMT") diff --git a/res/field-map-editor.toml b/res/field-map-editor.toml new file mode 100644 index 00000000..809c3773 --- /dev/null +++ b/res/field-map-editor.toml @@ -0,0 +1,216 @@ +BackgroundCheckerboardScale = 4 +BackgroundColor = 4294967295 +BackgroundColor2 = 4294967295 +BackgroundSettings = 0 +BatchForceLoading = true +BatchGenerateColorfulMask = true +BatchGenerateWhiteOnBlackMask = false +BatchInputLoadMap = 0 +BatchInputMapPath = '' +BatchInputMapRootPathType = 0 +BatchInputPath = 'C:\Users\pcvii\Downloads' +BatchInputRootPathType = 0 +BatchInputType = 0 +BatchMapListEnabled = '000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' +BatchOutputPath = '' +BatchOutputRootPathType = 2 +BatchOutputSaveMap = false +BatchOutputType = 0 +BatchQueue = [] +BatchQueueEnabled = false +BatchUpdateDelay = 0.029999999329447746 +BatchUpdateDelayEnabled = false +Bpp = 0 +CacheDeswizzlePathsEnabled = '0000000000000' +CacheFullFileNamePathsEnabled = '0000000000000' +CacheMapPathsEnabled = '1000000000000' +CacheSwizzleAsOneImagePathsEnabled = '0000000000000' +CacheSwizzlePathsEnabled = '0000010000000' +CacheTextureAndMapPaths = [ + 'D:/SteamLibrary/steamapps/common/FINAL FANTASY VIII', + 'D:/SteamLibrary/steamapps/common/FINAL FANTASY VIII/deswizzle/mods/Textures/field/mapdata/bd/bdifrit1', + 'D:/SteamLibrary/steamapps/common/FINAL FANTASY VIII/mods/Textures', + 'D:/SteamLibrary/steamapps/common/FINAL FANTASY VIII/mods/Textures/field/mapdata/', + 'D:/SteamLibrary/steamapps/common/FINAL FANTASY VIII Remastered', + 'D:/SteamLibrary/steamapps/common/FINAL FANTASY VIII Remastered/DEMASTER_EXP/textures/field_bg', + 'D:/games/ff82000', + 'D:/games/ff82000/mods/Textures', + 'D:/games/ff82000/mods/Textures/field/mapdata/', + 'd:/games/ff82000', + 'd:/games/ff82000/mods/Textures', + 'd:/games/ff82000/mods/Textures/field/mapdata/', + 'e:/' +] +CompactOnLoad = 4 +CompactOnLoadEnabled = false +Coo = 0 +CurrentPattern = 0 +CurrentPatternIndex = 0 +DeswizzlePath = 'D:/SteamLibrary/steamapps/common/FINAL FANTASY VIII/deswizzle/mods/Textures/field/mapdata/bd/bdifrit1' +DisplayBatchWindow = true +DisplayControlPanelWindow = true +DisplayCustomPathsWindow = true +DisplayDrawWindow = true +DisplayFieldFileWindow = true +DisplayFiltersWindow = true +DisplayHistoryWindow = false +DisplayImageCompareWindow = true +DisplayImportImage = false +DisplayKeyboardShortcutsWindow = false +DisplayTexturesWindow = true +DrawDisableBlending = false +DrawGrid = true +DrawMode = 1 +DrawPalette = false +DrawPupuMask = false +DrawSwizzle = true +DrawTexturePageGrid = false +DrawTileConflictRects = false +ExternalTexturesAndMapsDirectoryPaths = [ 'D:/SteamLibrary/steamapps/common/FINAL FANTASY VIII/deswizzle/mods/Textures/field/mapdata/bd/bdifrit1' ] +FF8DirectoryPaths = [ + 'D:/SteamLibrary/steamapps/common/FINAL FANTASY VIII', + 'D:/SteamLibrary/steamapps/common/FINAL FANTASY VIII Remastered', + 'D:/games/ff82000', + 'd:/games/ff82000', + 'e:/' +] +FF8Path = 'D:/SteamLibrary/steamapps/common/FINAL FANTASY VIII' +ForceReloadingOfTextures = false +ForceRenderingOfMap = false +FullFileNamePath = 'D:/SteamLibrary/steamapps/common/FINAL FANTASY VIII' +ImageCompareWindowPath1 = '' +ImageCompareWindowPath2 = '' +ImportImageGrid = false +ImportLoadImageDirectory = '' +ImportSelectedTile = 0 +OutputDeswizzlePattern = '{selected_path}\deswizzle\{ffnx_multi_texture}' +OutputFullFileNamePattern = '{selected_path}\full_filename\{ffnx_multi_texture_full}' +OutputImagePath = 'D:/SteamLibrary/steamapps/common/FINAL FANTASY VIII' +OutputMapPath = 'D:/SteamLibrary/steamapps/common/FINAL FANTASY VIII' +OutputMapPatternForDeswizzle = '{selected_path}\deswizzle\{ffnx_map}' +OutputMapPatternForFullFileName = '{selected_path}\full_filename\{ffnx_map}' +OutputMapPatternForSwizzle = '{selected_path}\{ffnx_map}' +OutputMimPath = 'D:/SteamLibrary/steamapps/common/FINAL FANTASY VIII' +OutputSwizzleAsOneImagePattern = '{selected_path}\{ffnx_single_texture}' +OutputSwizzlePattern = '{selected_path}\{ffnx_multi_texture}' +OutputTomlPattern = '{{current_toml_path}?:{current_path}\res\deswizzle.toml:?}' +Palette = 0 +PathPatternsWithFullFileName = [ + '{selected_path}/{full_filename}', + '{selected_path}/{field_name}/{full_filename}', + '{selected_path}/{field_prefix}/{field_name}/{full_filename}' +] +PathPatternsWithPalette = [ + '{selected_path}/{field_name}{_{2_letter_lang}}_0{palette}{ext}', + '{selected_path}/{field_name}/{field_name}{_{2_letter_lang}}_0{palette}{ext}', + '{selected_path}/{field_prefix}/{field_name}/{field_name}{_{2_letter_lang}}_0{palette}{ext}', + '{selected_path}/{field_name}_0{palette}{ext}', + '{selected_path}/{field_name}/{field_name}_0{palette}{ext}', + '{selected_path}/{field_prefix}/{field_name}/{field_name}_0{palette}{ext}', + '{selected_path}/{field_name}{_{2_letter_lang}}_{palette}{ext}', + '{selected_path}/{field_name}/{field_name}{_{2_letter_lang}}_{palette}{ext}', + '{selected_path}/{field_prefix}/{field_name}/{field_name}{_{2_letter_lang}}_{palette}{ext}', + '{selected_path}/{field_name}_{palette}{ext}', + '{selected_path}/{field_name}/{field_name}_{palette}{ext}', + '{selected_path}/{field_prefix}/{field_name}/{field_name}_{palette}{ext}' +] +PathPatternsWithPaletteAndTexturePage = [ + '{selected_path}/{field_name}{_{2_letter_lang}}_0{texture_page}_0{palette}{ext}', + '{selected_path}/{field_name}/{field_name}{_{2_letter_lang}}_0{texture_page}_0{palette}{ext}', + '{selected_path}/{field_prefix}/{field_name}/{field_name}{_{2_letter_lang}}_0{texture_page}_0{palette}{ext}', + '{selected_path}/{field_name}_0{texture_page}_0{palette}{ext}', + '{selected_path}/{field_name}/{field_name}_0{texture_page}_0{palette}{ext}', + '{selected_path}/{field_prefix}/{field_name}/{field_name}_0{texture_page}_0{palette}{ext}', + '{selected_path}/{field_name}{_{2_letter_lang}}_{texture_page}_{palette}{ext}', + '{selected_path}/{field_name}/{field_name}{_{2_letter_lang}}_{texture_page}_{palette}{ext}', + '{selected_path}/{field_prefix}/{field_name}/{field_name}{_{2_letter_lang}}_{texture_page}_{palette}{ext}', + '{selected_path}/{field_name}_{texture_page}_{palette}{ext}', + '{selected_path}/{field_name}/{field_name}_{texture_page}_{palette}{ext}', + '{selected_path}/{field_prefix}/{field_name}/{field_name}_{texture_page}_{palette}{ext}' +] +PathPatternsWithPupuID = [ + '{selected_path}/{field_name}{_{2_letter_lang}}_{pupu_id}{ext}', + '{selected_path}/{field_name}/{field_name}{_{2_letter_lang}}_{pupu_id}{ext}', + '{selected_path}/{field_prefix}/{field_name}/{field_name}{_{2_letter_lang}}_{pupu_id}{ext}', + '{selected_path}/{field_name}_{pupu_id}{ext}', + '{selected_path}/{field_name}/{field_name}_{pupu_id}{ext}', + '{selected_path}/{field_prefix}/{field_name}/{field_name}_{pupu_id}{ext}' +] +PathPatternsWithTexturePage = [ + '{selected_path}/{field_name}{_{2_letter_lang}}_0{texture_page}{ext}', + '{selected_path}/{field_name}/{field_name}{_{2_letter_lang}}_0{texture_page}{ext}', + '{selected_path}/{field_prefix}/{field_name}/{field_name}{_{2_letter_lang}}_0{texture_page}{ext}', + '{selected_path}/{field_name}_0{texture_page}{ext}', + '{selected_path}/{field_name}/{field_name}_0{texture_page}{ext}', + '{selected_path}/{field_prefix}/{field_name}/{field_name}_0{texture_page}{ext}', + '{selected_path}/{field_name}{_{2_letter_lang}}_{texture_page}{ext}', + '{selected_path}/{field_name}/{field_name}{_{2_letter_lang}}_{texture_page}{ext}', + '{selected_path}/{field_prefix}/{field_name}/{field_name}{_{2_letter_lang}}_{texture_page}{ext}', + '{selected_path}/{field_name}_{texture_page}{ext}', + '{selected_path}/{field_name}/{field_name}_{texture_page}{ext}', + '{selected_path}/{field_prefix}/{field_name}/{field_name}_{texture_page}{ext}' +] +PatternsBase = [ + '{selected_path}/{field_name}{_{2_letter_lang}}{ext}', + '{selected_path}/{field_name}/{field_name}{_{2_letter_lang}}{ext}', + '{selected_path}/{field_prefix}/{field_name}/{field_name}{_{2_letter_lang}}{ext}', + '{selected_path}/{field_name}{ext}', + '{selected_path}/{field_name}/{field_name}{ext}', + '{selected_path}/{field_prefix}/{field_name}/{field_name}{ext}', + '{selected_path}/{demaster}', + '{selected_path}/{ffnx_multi_texture}', + '{selected_path}/{ffnx_single_texture}', + '{selected_path}/{ffnx_map}' +] +PatternsCommonPrefixes = [ + '{selected_path}', + '{selected_path}/{ffnx_mod_path}/field/mapdata/', + '{selected_path}/mods/Textures', + '{selected_path}/{demaster_mod_path}/textures/field_bg', + '{selected_path}/field_bg', + '{selected_path}/textures/fields', + '{selected_path}/textures', + '{selected_path}/ff8/Data/{3_letter_lang}/field/mapdata', + '{selected_path}/ff8/Data/{3_letter_lang}/FIELD/mapdata', + '{selected_path}/ff8/Data/{eng}/field/mapdata', + '{selected_path}/ff8/Data/{eng}/FIELD/mapdata', + '{selected_path}/ff8/Data/{fre}/field/mapdata', + '{selected_path}/ff8/Data/{fre}/FIELD/mapdata', + '{selected_path}/ff8/Data/{ger}/field/mapdata', + '{selected_path}/ff8/Data/{ger}/FIELD/mapdata', + '{selected_path}/ff8/Data/{ita}/field/mapdata', + '{selected_path}/ff8/Data/{ita}/FIELD/mapdata', + '{selected_path}/ff8/Data/{spa}/field/mapdata', + '{selected_path}/ff8/Data/{spa}/FIELD/mapdata', + '{selected_path}/ff8/Data/{jp}/field/mapdata', + '{selected_path}/ff8/Data/{jp}/FIELD/mapdata', + '{selected_path}/ff8/Data/{x}/field/mapdata', + '{selected_path}/ff8/Data/{x}/FIELD/mapdata' +] +PatternsCommonPrefixesForMaps = [ '{selected_path}/{ffnx_direct_mode_path}/field/mapdata/' ] +RenderImportedImage = false +StarterField = 'bdin1' +SwizzleAsOneImagePath = 'D:/SteamLibrary/steamapps/common/FINAL FANTASY VIII' +SwizzlePath = 'C:/Users/pcvii/Downloads/bdifrit1' +TOMLFailOverForEditor = 1 +TileSizeValue = 0 +TomlPath = '' +TomlPaths = [] +WindowHeight = 720 +WindowWidth = 1280 +batch_compact_enabled = false +batch_compact_type = 0 +batch_flatten_enabled = false +batch_flatten_type = 0 +filter_deswizzle = 'D:/SteamLibrary/steamapps/common/FINAL FANTASY VIII' +filter_deswizzle_enabled = false +filter_full_filename = 'D:/SteamLibrary/steamapps/common/FINAL FANTASY VIII' +filter_map = 'D:/SteamLibrary/steamapps/common/FINAL FANTASY VIII' +filter_multi_layer_id = [ 0 ] +filter_multi_layer_id_enabled = false +filter_multi_z = [] +filter_multi_z_enabled = false +filter_swizzle = 'D:/SteamLibrary/steamapps/common/FINAL FANTASY VIII Remastered/DEMASTER_EXP/textures/field_bg' +filter_swizzle_as_one_image = 'D:/SteamLibrary/steamapps/common/FINAL FANTASY VIII' +filter_swizzle_as_one_image_enabled = false +filter_swizzle_enabled = true \ No newline at end of file diff --git a/res/field-map-editor_experimental.toml b/res/field-map-editor_experimental.toml new file mode 100644 index 00000000..25602987 --- /dev/null +++ b/res/field-map-editor_experimental.toml @@ -0,0 +1,12 @@ +FF8_menu = [ false, true, true ] +coo_index = 0 +coo_string = 'English' +ff8_directory_paths = [ + 'D:\SteamLibrary\steamapps\common\FINAL FANTASY VIII', + 'D:\SteamLibrary\steamapps\common\FINAL FANTASY VIII Remastered', + 'D:\games\ff82000', + 'd:\games\ff82000', + 'd:\tim', + 'e:\' +] +upscale_paths_vector = [ 'D:\Angelwing-Ultima_Remastered_v1-0-a\field_bg' ] \ No newline at end of file diff --git a/res/field-map-editor_experimental_imgui.ini b/res/field-map-editor_experimental_imgui.ini new file mode 100644 index 00000000..c94d131f --- /dev/null +++ b/res/field-map-editor_experimental_imgui.ini @@ -0,0 +1,79 @@ +[Window][DockSpace Demo] +Pos=0,19 +Size=1280,701 +Collapsed=0 + +[Window][Debug##Default] +Pos=60,60 +Size=400,400 +Collapsed=0 + +[Window][FPS] +Pos=954,672 +Size=326,48 +Collapsed=0 +DockId=0x00000006,0 + +[Window][Map Filters] +Pos=954,19 +Size=326,293 +Collapsed=0 +DockId=0x00000003,0 + +[Window][FF8 Controls] +Pos=954,314 +Size=326,178 +Collapsed=0 +DockId=0x00000007,0 + +[Window][Preview] +Pos=954,494 +Size=326,176 +Collapsed=0 +DockId=0x00000008,0 + +[Window][Tile Display Window] +Pos=0,372 +Size=952,348 +Collapsed=0 +DockId=0x0000000A,1 + +[Window][Map (Swizzle) - Controls] +Pos=0,372 +Size=952,348 +Collapsed=0 +DockId=0x0000000A,0 + +[Window][Map (Swizzle)] +Pos=0,19 +Size=363,351 +Collapsed=0 +DockId=0x0000000B,0 + +[Window][Map (Deswizzle)] +Pos=365,19 +Size=587,351 +Collapsed=0 +DockId=0x0000000C,0 + +[Window][Map (Deswizzle) - Controls] +Pos=0,372 +Size=952,348 +Collapsed=0 +DockId=0x0000000A,2 + +[Docking][Data] +DockSpace ID=0xC0DFADC4 Window=0xD0388BC8 Pos=190,232 Size=1280,701 Split=X + DockNode ID=0x00000001 Parent=0xC0DFADC4 SizeRef=1592,701 Split=Y Selected=0xB5DA26E3 + DockNode ID=0x00000009 Parent=0x00000001 SizeRef=1115,351 Split=X Selected=0xC3155CEC + DockNode ID=0x0000000B Parent=0x00000009 SizeRef=1003,351 CentralNode=1 Selected=0xC3155CEC + DockNode ID=0x0000000C Parent=0x00000009 SizeRef=587,351 Selected=0xAB7CAA7F + DockNode ID=0x0000000A Parent=0x00000001 SizeRef=1115,348 Selected=0xB5DA26E3 + DockNode ID=0x00000002 Parent=0xC0DFADC4 SizeRef=326,701 Split=Y Selected=0xE20875FD + DockNode ID=0x00000005 Parent=0x00000002 SizeRef=163,651 Split=Y Selected=0xE20875FD + DockNode ID=0x00000003 Parent=0x00000005 SizeRef=163,293 Selected=0xE20875FD + DockNode ID=0x00000004 Parent=0x00000005 SizeRef=163,356 Split=Y Selected=0x2E31F56F + DockNode ID=0x00000007 Parent=0x00000004 SizeRef=163,178 Selected=0x2E31F56F + DockNode ID=0x00000008 Parent=0x00000004 SizeRef=163,176 Selected=0xE41466B5 + DockNode ID=0x00000006 Parent=0x00000002 SizeRef=163,48 Selected=0x5ACCD6C9 + diff --git a/res/field-map-editor_imgui.ini b/res/field-map-editor_imgui.ini new file mode 100644 index 00000000..64a18db0 --- /dev/null +++ b/res/field-map-editor_imgui.ini @@ -0,0 +1,103 @@ +[Window][##FieldMapEditor] +Pos=0,19 +Size=1920,1038 +Collapsed=0 + +[Window][Control Panel] +Pos=1417,19 +Size=503,1038 +Collapsed=0 +DockId=0x00000003,0 + +[Window][Debug##Default] +Pos=60,60 +Size=400,400 +Collapsed=0 + +[Window][Draw] +Pos=0,19 +Size=1415,1038 +Collapsed=0 +DockId=0x00000001,0 + +[Window][History] +Pos=1417,820 +Size=503,237 +Collapsed=0 +DockId=0x00000004,0 + +[Window][Image Comparison Tool] +Pos=0,19 +Size=1415,1038 +Collapsed=0 +DockId=0x00000001,1 + +[Window][Field File Window] +Pos=0,19 +Size=1415,1038 +Collapsed=0 +DockId=0x00000001,2 + +[Window][Batch Operation] +Pos=0,19 +Size=1415,1038 +Collapsed=0 +DockId=0x00000001,3 + +[Window][Textures] +Pos=0,19 +Size=1415,1038 +Collapsed=0 +DockId=0x00000001,4 + +[Window][Custom Paths Window] +Pos=0,19 +Size=1415,1038 +Collapsed=0 +DockId=0x00000001,5 + +[Window][deswizzle.toml Editor] +Pos=0,19 +Size=1415,1038 +Collapsed=0 +DockId=0x00000001,6 + +[Window][Dear ImGui Demo] +Pos=0,19 +Size=983,701 +Collapsed=0 +DockId=0x00000001,7 + +[Window][Choose directory to save textures to...##filebrowser_863293925200] +Pos=290,135 +Size=700,450 +Collapsed=0 + +[Window][Choose directory to load textures from...##filebrowser_655527044736] +Pos=290,135 +Size=700,450 +Collapsed=0 + +[Window][Choose directory to load textures from##filebrowser_1006993339352] +Pos=610,303 +Size=700,450 +Collapsed=0 + +[Window][Choose directory to load textures from##filebrowser_487196785224] +Pos=-255,-138 +Size=700,450 +Collapsed=0 + +[Window][Logging Window] +Pos=0,19 +Size=1415,1038 +Collapsed=0 +DockId=0x00000001,7 + +[Docking][Data] +DockSpace ID=0xA2843463 Window=0xB411673B Pos=0,42 Size=1920,1038 Split=X + DockNode ID=0x00000001 Parent=0xA2843463 SizeRef=1415,701 CentralNode=1 Selected=0xD2549B58 + DockNode ID=0x00000002 Parent=0xA2843463 SizeRef=503,701 Split=Y Selected=0xF930105C + DockNode ID=0x00000003 Parent=0x00000002 SizeRef=295,539 Selected=0xF930105C + DockNode ID=0x00000004 Parent=0x00000002 SizeRef=295,160 Selected=0x344D3274 + diff --git a/src/opengl/CMakeLists.txt b/src/opengl/CMakeLists.txt index 18325316..7ef50225 100644 --- a/src/opengl/CMakeLists.txt +++ b/src/opengl/CMakeLists.txt @@ -1,4 +1,6 @@ add_subdirectory(stbi) +add_subdirectory(ff_8) add_subdirectory(glengine) +add_subdirectory(imgui_utils) add_subdirectory(experimental) add_subdirectory(main) diff --git a/src/opengl/experimental/Application.cpp b/src/opengl/experimental/Application.cpp index 0eb5fd92..9ebc6928 100644 --- a/src/opengl/experimental/Application.cpp +++ b/src/opengl/experimental/Application.cpp @@ -69,7 +69,7 @@ Application::Application( // { // return; // } - spdlog::debug( + spdlog::trace( "event::{}\t{}\t{}", e.name(), e.category_name(), e.data()); } })) { diff --git a/src/opengl/experimental/CMakeLists.txt b/src/opengl/experimental/CMakeLists.txt index 9d3f9fba..98af0210 100644 --- a/src/opengl/experimental/CMakeLists.txt +++ b/src/opengl/experimental/CMakeLists.txt @@ -28,13 +28,7 @@ add_executable( ff8/MapHistory.cpp ff8/MapTileAdjustments.hpp ff8/SimilarAdjustments.cpp - ff8/Configuration.cpp ff8/MenuSaveToggles.hpp - ff8/PupuID.hpp - ImGuiDisabled.cpp - ImGuiPushItemWidth.cpp - ImGuiPushID.cpp - ImGuiPushStyleVar.cpp ImGuiViewPortWindow.cpp main.cpp Menu.cpp @@ -47,16 +41,17 @@ add_executable( test/TestBatchRenderingTexture2DDynamic.cpp test/TestMenu.cpp test/TestTexture2D.cpp - ff8/UniquifyPupu.hpp Window.cpp) target_link_libraries( ${PROJECT_NAME}_EXPERIMENTAL + PRIVATE ${PROJECT_NAME}_ff_8 PRIVATE glengine PRIVATE project_warnings PRIVATE Threads::Threads PRIVATE OpenVIII_CPP_WIP_VIIIGraphics PRIVATE OpenVIII_CPP_WIP_VIIIArchive PRIVATE OpenVIII_CPP_WIP_VIIIPaths + PRIVATE ${PROJECT_NAME}_imgui_utils PRIVATE imgui::imgui PRIVATE GLEW::GLEW PRIVATE glfw @@ -75,8 +70,6 @@ add_custom_command( $/res VERBATIM) -target_compile_definitions(${PROJECT_NAME}_EXPERIMENTAL - PUBLIC TOML_EXCEPTIONS=0) if(MSVC) target_compile_definitions( ${PROJECT_NAME}_EXPERIMENTAL PUBLIC _CRT_SECURE_NO_WARNINGS) # required by @@ -92,6 +85,15 @@ string(TOLOWER "${PROJECT_NAME}_EXPERIMENTAL" experimental_exec) set_target_properties(${PROJECT_NAME}_EXPERIMENTAL PROPERTIES OUTPUT_NAME "${experimental_exec}" ) + + +target_compile_definitions( + ${PROJECT_NAME}_EXPERIMENTAL + PUBLIC NOMINMAX # imgui uses unguarded min and max. + PUBLIC DEFAULT_CONFIG_PATH="${DEFAULT_CONFIG_ROOT_PATH}/${experimental_exec}.toml" + PUBLIC DEFAULT_IMGUI_INI_PATH="${DEFAULT_CONFIG_ROOT_PATH}/${experimental_exec}_imgui.ini" + PUBLIC DEFAULT_LOG_PATH="${DEFAULT_CONFIG_ROOT_PATH}/${experimental_exec}.log" + ) if(supported) message(STATUS "IPO / LTO enabled") set_target_properties(${PROJECT_NAME}_EXPERIMENTAL diff --git a/src/opengl/experimental/ImGuiDisabled.cpp b/src/opengl/experimental/ImGuiDisabled.cpp deleted file mode 100644 index f5573d66..00000000 --- a/src/opengl/experimental/ImGuiDisabled.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// -// Created by pcvii on 1/25/2022. -// - -#include "ImGuiDisabled.hpp" diff --git a/src/opengl/experimental/ImGuiDisabled.hpp b/src/opengl/experimental/ImGuiDisabled.hpp deleted file mode 100644 index eb1201ae..00000000 --- a/src/opengl/experimental/ImGuiDisabled.hpp +++ /dev/null @@ -1,18 +0,0 @@ -// -// Created by pcvii on 1/25/2022. -// - -#ifndef FIELD_MAP_EDITOR_IMGUIDISABLED_HPP -#define FIELD_MAP_EDITOR_IMGUIDISABLED_HPP -#include -#include -namespace glengine -{ -[[nodiscard]] inline auto ImGuiDisabled(bool disabled) noexcept -{ - - ImGui::BeginDisabled(disabled); - return ScopeGuard{ &ImGui::EndDisabled }; -} -}// namespace glengine -#endif// FIELD_MAP_EDITOR_IMGUIDISABLED_HPP diff --git a/src/opengl/experimental/ImGuiPushID.cpp b/src/opengl/experimental/ImGuiPushID.cpp deleted file mode 100644 index 41934b81..00000000 --- a/src/opengl/experimental/ImGuiPushID.cpp +++ /dev/null @@ -1,9 +0,0 @@ -// -// Created by pcvii on 1/18/2022. -// -#include "ImGuiPushID.hpp" - -void glengine::ImGuiPushIdImpl::reset() const noexcept -{ - s_id = {}; -} diff --git a/src/opengl/experimental/ImGuiPushID.hpp b/src/opengl/experimental/ImGuiPushID.hpp deleted file mode 100644 index 13f9b139..00000000 --- a/src/opengl/experimental/ImGuiPushID.hpp +++ /dev/null @@ -1,38 +0,0 @@ -// -// Created by pcvii on 1/18/2022. -// - -#ifndef FIELD_MAP_EDITOR_IMGUIPUSHID_HPP -#define FIELD_MAP_EDITOR_IMGUIPUSHID_HPP -#include -#include -namespace glengine -{ -/** - * Wrapper for ImGui::PushID(int) that increments an int and returns a scope - * guarded ImGui::PopID() that will automatically Pop when the scope ends. - */ -class [[nodiscard]] ImGuiPushIdImpl -{ - public: - /** - * ImGui::PushID(int) and increment int. - * @return ImGui::PopID() wrapped in a scope guard. - */ - [[nodiscard]] auto operator()() const noexcept - { - ImGui::PushID(++s_id); - return ScopeGuard{ &ImGui::PopID }; - } - /** - * reset() must be called once per frame usually at the beginning or the - * end. It resets an int to 0. - */ - void reset() const noexcept; - - private: - inline static constinit int s_id = {}; -}; -static constexpr inline ImGuiPushIdImpl ImGuiPushId = {}; -}// namespace glengine -#endif// FIELD_MAP_EDITOR_IMGUIPUSHID_HPP diff --git a/src/opengl/experimental/ImGuiPushItemWidth.cpp b/src/opengl/experimental/ImGuiPushItemWidth.cpp deleted file mode 100644 index da458627..00000000 --- a/src/opengl/experimental/ImGuiPushItemWidth.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// -// Created by pcvii on 1/25/2022. -// - -#include "ImGuiPushItemWidth.hpp" diff --git a/src/opengl/experimental/ImGuiPushStyleVar.cpp b/src/opengl/experimental/ImGuiPushStyleVar.cpp deleted file mode 100644 index 7098ae14..00000000 --- a/src/opengl/experimental/ImGuiPushStyleVar.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// -// Created by pcvii on 5/25/2022. -// - -#include "ImGuiPushStyleVar.hpp" diff --git a/src/opengl/experimental/ImGuiViewPortWindow.cpp b/src/opengl/experimental/ImGuiViewPortWindow.cpp index 0d41bcd6..ac9106ac 100644 --- a/src/opengl/experimental/ImGuiViewPortWindow.cpp +++ b/src/opengl/experimental/ImGuiViewPortWindow.cpp @@ -141,14 +141,14 @@ inline namespace impl void ImGuiViewPortWindow::on_im_gui_update() const { { - const auto push_id = ImGuiPushId(); + const auto push_id = imgui_utils::ImGuiPushId(); if (ImGui::Checkbox("Enable Debug Text", &m_debug_text)) { // changed } } { - const auto pop_id = glengine::ImGuiPushId(); + const auto pop_id = imgui_utils::ImGuiPushId(); if (ImGui::ColorEdit3("Clear Color", &m_background_color.r)) { m_clear_impl.Color(m_background_color); diff --git a/src/opengl/experimental/ImGuiViewPortWindow.hpp b/src/opengl/experimental/ImGuiViewPortWindow.hpp index 79a82c0f..79e5b729 100644 --- a/src/opengl/experimental/ImGuiViewPortWindow.hpp +++ b/src/opengl/experimental/ImGuiViewPortWindow.hpp @@ -4,13 +4,13 @@ #ifndef FIELD_MAP_EDITOR_IMGUIVIEWPORTWINDOW_HPP #define FIELD_MAP_EDITOR_IMGUIVIEWPORTWINDOW_HPP -#include "ImGuiPushID.hpp" -#include "ImGuiPushStyleVar.hpp" #include "OrthographicCameraController.hpp" #include #include #include #include +#include +#include namespace glengine { inline namespace impl @@ -27,10 +27,10 @@ inline namespace impl void on_render(const std::invocable auto &&callable) const { - const auto pop_style = ImGuiPushStyleVar( + const auto pop_style = imgui_utils::ImGuiPushStyleVar( ImGuiStyleVar_WindowPadding, ImVec2(0.F, 0.F)); { - const auto pop_id_0 = ImGuiPushId(); + const auto pop_id_0 = imgui_utils::ImGuiPushId(); const auto pop_end = ScopeGuard([]() { ImGui::End(); }); if (!ImGui::Begin(m_title)) { @@ -45,7 +45,7 @@ inline namespace impl = ImGui::IsWindowFocused(); // Using a Child allow to fill all the space of the // window. It also allows customization - const auto pop_id_1 = ImGuiPushId(); + const auto pop_id_1 = imgui_utils::ImGuiPushId(); ImGui::BeginChild(m_title); const auto pop_child = ScopeGuard([]() { ImGui::EndChild(); }); diff --git a/src/opengl/experimental/Menu.cpp b/src/opengl/experimental/Menu.cpp index c5349c97..19c39928 100644 --- a/src/opengl/experimental/Menu.cpp +++ b/src/opengl/experimental/Menu.cpp @@ -2,7 +2,7 @@ // Created by pcvii on 11/29/2021. // #include "Menu.hpp" -#include "ImGuiIndent.hpp" +#include namespace glengine { static_assert(Renderable); diff --git a/src/opengl/experimental/Window.cpp b/src/opengl/experimental/Window.cpp index 66d93f34..72f5cf93 100644 --- a/src/opengl/experimental/Window.cpp +++ b/src/opengl/experimental/Window.cpp @@ -1,12 +1,17 @@ // // Created by pcvii on 12/6/2021. // + +#ifndef DEFAULT_IMGUI_INI_PATH +#define DEFAULT_IMGUI_INI_PATH "imgui.ini"// fallback, just in case +#endif #include "Window.hpp" -#include "ImGuiPushID.hpp" +#include #include #include #include #include +#include #include namespace glengine @@ -22,7 +27,7 @@ void Window::begin_frame() const ImGui_ImplOpenGL3_NewFrame(); ImGui_ImplGlfw_NewFrame(); ImGui::NewFrame(); - glengine::ImGuiPushId.reset(); + imgui_utils::ImGuiPushId.reset(); } void Window::render_dockspace() const { @@ -224,13 +229,38 @@ void Window::init_im_gui(const char *const glsl_version) const // Setup Dear ImGui context IMGUI_CHECKVERSION(); ImGui::CreateContext(); - ImGuiIO &io = ImGui::GetIO(); - std::error_code error_code = {}; - static const auto path - = (std::filesystem::current_path(error_code) / "res" - / "field-map-editor-experimental_imgui.ini") - .string(); - io.IniFilename = path.c_str(); + ImGuiIO &imgui_io = ImGui::GetIO(); + imgui_io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; + imgui_io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; + // events don't work with viewports + std::error_code error_code = {}; + auto temp_path = std::filesystem::path(DEFAULT_IMGUI_INI_PATH); + static std::string path; + try + { + if (temp_path.is_relative()) + { + temp_path + = (std::filesystem::current_path(error_code) / path); + } + temp_path.make_preferred(); + path = temp_path.string(); + imgui_io.IniFilename = path.c_str(); + spdlog::info("ImGui ini path: {}", imgui_io.IniFilename); + ImGui::LoadIniSettingsFromDisk(imgui_io.IniFilename); + } + catch (const std::filesystem::filesystem_error &e) + { + spdlog::error( + "Filesystem error while constructing config path: {}", + e.what()); + } + catch (const std::exception &e) + { + spdlog::error( + "Unexpected error while constructing config path: {}", + e.what()); + } if (error_code) { spdlog::warn( @@ -245,10 +275,6 @@ void Window::init_im_gui(const char *const glsl_version) const // io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable // Keyboard Controls io.ConfigFlags |= // ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls - io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; - // io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;// events don't - // work - // with viewports // Setup Dear ImGui style ImGui::StyleColorsDark(); diff --git a/src/opengl/experimental/ff8/BPPs.cpp b/src/opengl/experimental/ff8/BPPs.cpp index 3b6e1145..c3eaf037 100644 --- a/src/opengl/experimental/ff8/BPPs.cpp +++ b/src/opengl/experimental/ff8/BPPs.cpp @@ -2,10 +2,10 @@ // Created by pcvii on 12/1/2021. // #include "BPPs.hpp" -#include +#include bool ff_8::Bpps::on_im_gui_update() const { - return glengine::GenericCombo("BPP", m_current, m_strings); + return imgui_utils::GenericCombo("BPP", m_current, m_strings); } const open_viii::graphics::BPPT *ff_8::Bpps::operator->() const { diff --git a/src/opengl/experimental/ff8/Configuration.cpp b/src/opengl/experimental/ff8/Configuration.cpp deleted file mode 100644 index 15d8a0bb..00000000 --- a/src/opengl/experimental/ff8/Configuration.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// -// Created by pcvii on 9/5/2022. -// - -#include "Configuration.hpp" diff --git a/src/opengl/experimental/ff8/Configuration.hpp b/src/opengl/experimental/ff8/Configuration.hpp deleted file mode 100644 index 3228f5b1..00000000 --- a/src/opengl/experimental/ff8/Configuration.hpp +++ /dev/null @@ -1,81 +0,0 @@ -// -// Created by pcvii on 9/5/2022. -// - -#ifndef FIELD_MAP_EDITOR_CONFIGURATION_HPP -#define FIELD_MAP_EDITOR_CONFIGURATION_HPP -#include -#include -#include -#include -class Configuration -{ - public: - Configuration() - : m_table( - []() - { - toml::parse_result result = toml::parse_file(m_path.string()); - if (!result) - { - spdlog::warn( - "TOML Parsing failed: {}\n\t{}", - result.error().description(), - m_path.string()); - return toml::table{}; - } - return std::move(result).table(); - }()) - { - } - toml::table *operator->() & - { - return &m_table; - } - toml::table *operator->() && = delete; - const toml::table *operator->() const && - { - return &m_table; - } - const toml::table *operator->() const & - { - return &m_table; - } - auto operator[](std::string_view i) const - { - return m_table[i]; - } - - void save() const - { - std::error_code error_code{}; - std::filesystem::create_directories(m_path.parent_path(), error_code); - if (error_code) - { - spdlog::error( - "{}:{} - {}: {} - path: {}", - __FILE__, - __LINE__, - error_code.value(), - error_code.message(), - m_path.parent_path().string()); - error_code.clear(); - } - auto fs = std::ofstream( - m_path, std::ios::out | std::ios::binary | std::ios::trunc); - if (!fs) - { - spdlog::error( - "ofstream: failed to open \"{}\" for writing", - m_path.string()); - return; - } - fs << m_table; - } - - private: - static inline const auto m_path - = std::filesystem::current_path() / "res" / "ff8_config.toml"; - toml::table m_table{}; -}; -#endif// FIELD_MAP_EDITOR_CONFIGURATION_HPP diff --git a/src/opengl/experimental/ff8/Coos.cpp b/src/opengl/experimental/ff8/Coos.cpp index 347bc7f9..10568d93 100644 --- a/src/opengl/experimental/ff8/Coos.cpp +++ b/src/opengl/experimental/ff8/Coos.cpp @@ -3,14 +3,14 @@ // #include "Coos.hpp" -#include +#include static constexpr auto coo_index = std::string_view("coo_index"); static constexpr auto coo_string = std::string_view("coo_string"); bool ff_8::Coos::on_im_gui_update() const { - if (glengine::GenericCombo("Language", m_current, m_coos)) + if (imgui_utils::GenericCombo("Language", m_current, m_coos)) { - auto config = Configuration{}; + auto config = ff_8::Configuration{}; config->insert_or_assign(coo_index, m_current); config->insert_or_assign(coo_string, std::string_view{ *this }); config.save(); @@ -27,6 +27,6 @@ ff_8::Coos::operator std::string_view() const return m_coos.at(static_cast(m_current)); } ff_8::Coos::Coos() - : m_current(Configuration{}[coo_index].value_or(int{})) + : m_current(ff_8::Configuration{}[coo_index].value_or(int{})) { } diff --git a/src/opengl/experimental/ff8/Coos.hpp b/src/opengl/experimental/ff8/Coos.hpp index c871183f..1a6bbe94 100644 --- a/src/opengl/experimental/ff8/Coos.hpp +++ b/src/opengl/experimental/ff8/Coos.hpp @@ -4,7 +4,7 @@ #ifndef FIELD_MAP_EDITOR_COOS_HPP #define FIELD_MAP_EDITOR_COOS_HPP -#include "Configuration.hpp" +#include #include #include #include @@ -23,8 +23,9 @@ class Coos [[nodiscard]] operator std::string_view() const; private: - static constexpr auto m_coos = open_viii::LangCommon::to_string_array(); - mutable int m_current{}; + static constexpr auto m_coos + = open_viii::LangCommon::to_string_array_full(); + mutable int m_current{}; }; static_assert(glengine::Renderable); }// namespace ff_8 diff --git a/src/opengl/experimental/ff8/Fields.cpp b/src/opengl/experimental/ff8/Fields.cpp index a380db5b..f1ec7980 100644 --- a/src/opengl/experimental/ff8/Fields.cpp +++ b/src/opengl/experimental/ff8/Fields.cpp @@ -3,9 +3,9 @@ // #include "Fields.hpp" -#include "Configuration.hpp" +#include #include -#include +#include namespace ff_8 { @@ -117,12 +117,12 @@ bool Fields::on_archive_change() const bool Fields::on_field_change() const { - if (glengine::GenericCombo("Field", m_current_index, m_map_data)) + if (imgui_utils::GenericCombo("Field", m_current_index, m_map_data)) { m_field = load_field(); if (std::cmp_less(m_current_index, std::ranges::size(m_map_data))) { - auto config = Configuration{}; + auto config = ff_8::Configuration{}; config->insert_or_assign(fields_index, m_current_index); config->insert_or_assign( @@ -181,7 +181,7 @@ std::string_view Fields::map_name() const return tmp; } Fields::Fields() - : m_current_index(Configuration{}[fields_index].value_or(int{})) + : m_current_index(ff_8::Configuration{}[fields_index].value_or(int{})) , m_map_data(m_archive.fields().map_data()) , m_field(load_field()) { diff --git a/src/opengl/experimental/ff8/Map.hpp b/src/opengl/experimental/ff8/Map.hpp index f1e2a734..980abd7a 100644 --- a/src/opengl/experimental/ff8/Map.hpp +++ b/src/opengl/experimental/ff8/Map.hpp @@ -8,9 +8,6 @@ #include "Changed.hpp" #include "FF8LoadTextures.hpp" #include "Fields.hpp" -#include "ImGuiDisabled.hpp" -#include "ImGuiIndent.hpp" -#include "ImGuiPushID.hpp" #include "ImGuiTileDisplayWindow.hpp" #include "ImGuiViewPortWindow.hpp" #include "MapBlends.hpp" @@ -21,10 +18,10 @@ #include "MouseToTilePos.h" #include "OrthographicCameraController.hpp" #include "SimilarAdjustments.hpp" -#include "tile_operations.hpp" #include "TransformedSortedUniqueCopy.hpp" #include "UniqueTileValues.hpp" #include "Window.hpp" +#include #include #include #include @@ -34,9 +31,12 @@ #include #include #include -#include #include #include +#include +#include +#include +#include #include #include namespace ff_8 @@ -69,41 +69,41 @@ class [[nodiscard]] MoveTiles std::vector> operations{}; if constexpr (std::is_same_v< typename TileFunctions::X, - tile_operations::X>) + TileOperations::X>) { operations.push_back( - tile_operations::TranslateWithX{ m_released.x, m_pressed.x }); + TileOperations::X::TranslateWith{ m_released.x, m_pressed.x }); } if constexpr (std::is_same_v< typename TileFunctions::Y, - tile_operations::Y>) + TileOperations::Y>) { operations.push_back( - tile_operations::TranslateWithY{ m_released.y, m_pressed.y }); + TileOperations::Y::TranslateWith{ m_released.y, m_pressed.y }); } if constexpr (std::is_same_v< typename TileFunctions::X, - tile_operations::SourceX>) + TileOperations::SourceX>) { operations.push_back( - tile_operations::TranslateWithSourceX{ m_released.x, - m_pressed.x }); + TileOperations::SourceX::TranslateWith{ m_released.x, + m_pressed.x }); } if constexpr (std::is_same_v< typename TileFunctions::Y, - tile_operations::SourceY>) + TileOperations::SourceY>) { operations.push_back( - tile_operations::TranslateWithSourceY{ m_released.y, - m_pressed.y }); + TileOperations::SourceY::TranslateWith{ m_released.y, + m_pressed.y }); } - + //@todo I donno what this if constexpr is doing. if constexpr (std::is_same_v< typename TileFunctions::TexturePage, - tile_operations::TextureId>) + TileOperations::TextureId>) { operations.push_back( - tile_operations::WithTextureId{ m_released.z }); + TileOperations::TextureId::With{ m_released.z }); } GetMapHistory()->copy_working_perform_operation( m_indexes, @@ -261,7 +261,7 @@ class Map = ConvertGliDtoImTextureId( sub_texture.id()); const auto uv = sub_texture.im_gui_uv(); - const auto id_pop = glengine::ImGuiPushId(); + const auto id_pop = imgui_utils::ImGuiPushId(); const auto color = ImVec4(0.F, 0.F, 0.F, 0.F); last_pos = ImGui::GetCursorPos(); text_width = ImGui::GetItemRectMax().x; @@ -291,7 +291,7 @@ class Map { auto &local_tile_button_state = *tile_button_state; using namespace open_viii::graphics::background; - const auto id_pop_2 = glengine::ImGuiPushId(); + const auto id_pop_2 = imgui_utils::ImGuiPushId(); const auto sub_texture = tile_to_sub_texture(tile); const auto increment = glengine::ScopeGuard([&]() { ++i; }); @@ -414,9 +414,9 @@ class Map } void on_im_gui_update() const { - const auto pop_id = glengine::ImGuiPushId(); + const auto pop_id = imgui_utils::ImGuiPushId(); { - const auto disable = glengine::ImGuiDisabled( + const auto disable = imgui_utils::ImGuiDisabled( std::ranges::empty(GetMapHistory().path) || std::ranges::empty(GetMim().path)); @@ -794,7 +794,7 @@ class Map { auto f_tiles = tiles - | std::views::filter(tile_operations::NotInvalidTile{}) + | std::views::filter(TileOperations::NotInvalidTile{}) | std::views::filter( []([[maybe_unused]] const auto &tile) -> bool { @@ -814,7 +814,7 @@ class Map std::ranges::transform( f_tiles, std::back_inserter(unique_z), - tile_operations::Z{}); + TileOperations::Z{}); std::ranges::sort(unique_z); auto [begin, end] = std::ranges::unique(unique_z); unique_z.erase(begin, end); @@ -825,7 +825,7 @@ class Map { auto f_tiles_reverse_filter_z = f_tiles | std::views::reverse - | std::views::filter(tile_operations::ZMatch{ z }); + | std::views::filter(TileOperations::Z::Match{ z }); for (const auto &tile : f_tiles_reverse_filter_z) { if (!lambda(tile)) @@ -1060,7 +1060,7 @@ class Map { auto f_tiles = tiles - | std::views::filter(tile_operations::NotInvalidTile{}); + | std::views::filter(TileOperations::NotInvalidTile{}); return static_cast(std::ranges::count_if( f_tiles, [](auto &&) { return true; })); }); @@ -1074,7 +1074,7 @@ class Map { auto f_tiles = tiles - | std::views::filter(tile_operations::NotInvalidTile{}) + | std::views::filter(TileOperations::NotInvalidTile{}) | std::views::filter(filter); bool changed = false; VisitState visit_state = {}; diff --git a/src/opengl/experimental/ff8/MapBlends.hpp b/src/opengl/experimental/ff8/MapBlends.hpp index c983527e..13c7df09 100644 --- a/src/opengl/experimental/ff8/MapBlends.hpp +++ b/src/opengl/experimental/ff8/MapBlends.hpp @@ -4,10 +4,10 @@ #ifndef FIELD_MAP_EDITOR_MAPBLENDS_HPP #define FIELD_MAP_EDITOR_MAPBLENDS_HPP -#include "ImGuiIndent.hpp" #include #include #include +#include class MapBlends { public: @@ -16,13 +16,13 @@ class MapBlends bool changed = false; if (ImGui::CollapsingHeader("Add Blend")) { - const auto un_indent = glengine::ImGuiIndent(); + const auto un_indent = imgui_utils::ImGuiIndent(); if (ImGui::Checkbox( "Percent Blends (50%,25%)", &m_enable_percent_blend)) { changed = true; } - const auto pop = glengine::ImGuiPushId(); + const auto pop = imgui_utils::ImGuiPushId(); if (blend_combos( m_add_parameter_selections, m_add_equation_selections)) { @@ -31,8 +31,8 @@ class MapBlends } if (ImGui::CollapsingHeader("Subtract Blend")) { - const auto un_indent = glengine::ImGuiIndent(); - const auto pop = glengine::ImGuiPushId(); + const auto un_indent = imgui_utils::ImGuiIndent(); + const auto pop = imgui_utils::ImGuiPushId(); if (blend_combos( m_subtract_parameter_selections, m_subtract_equation_selections)) diff --git a/src/opengl/experimental/ff8/MapDeswizzle.hpp b/src/opengl/experimental/ff8/MapDeswizzle.hpp index a9c6edcf..c18640d4 100644 --- a/src/opengl/experimental/ff8/MapDeswizzle.hpp +++ b/src/opengl/experimental/ff8/MapDeswizzle.hpp @@ -5,14 +5,14 @@ #ifndef FIELD_MAP_EDITOR_MAPDESWIZZLE_HPP #define FIELD_MAP_EDITOR_MAPDESWIZZLE_HPP #include "Map.hpp" -#include "tile_operations.hpp" +#include namespace ff_8 { struct TileFunctionsDeswizzle { - using X = tile_operations::X; - using Y = tile_operations::Y; - using TexturePage = tile_operations::TextureIdDefaultValue; + using X = TileOperations::X; + using Y = TileOperations::Y; + using TexturePage = TileOperations::TextureId::DefaultValue; using UseTexturePage = std::true_type; using UseBlending = std::true_type; static constexpr const char *const label = "Map (Deswizzle)"; diff --git a/src/opengl/experimental/ff8/MapDims.hpp b/src/opengl/experimental/ff8/MapDims.hpp index becc0269..63b75022 100644 --- a/src/opengl/experimental/ff8/MapDims.hpp +++ b/src/opengl/experimental/ff8/MapDims.hpp @@ -4,7 +4,7 @@ #ifndef FIELD_MAP_EDITOR_MAPDIMS_HPP #define FIELD_MAP_EDITOR_MAPDIMS_HPP -#include "tile_operations.hpp" +#include #include namespace ff_8 { @@ -54,7 +54,7 @@ class MapDims { auto f_tiles = tiles | std::views::filter( - tile_operations::NotInvalidTile{}); + TileOperations::NotInvalidTile{}); get_x(f_tiles); get_y(f_tiles); get_true_x(f_tiles); @@ -121,7 +121,7 @@ class MapDims template void get_true_x(TilesR &&f_tiles) { - static constexpr tile_operations::X true_x = {}; + static constexpr TileOperations::X true_x = {}; const auto [true_i_min_x, true_i_max_x] = std::ranges::minmax_element(f_tiles, {}, true_x); if (true_i_min_x == true_i_max_x) @@ -134,7 +134,7 @@ class MapDims template void get_true_y(TilesR &&f_tiles) { - static constexpr tile_operations::Y true_y = {}; + static constexpr TileOperations::Y true_y = {}; const auto [true_i_min_y, true_i_max_y] = std::ranges::minmax_element(f_tiles, {}, true_y); if (true_i_min_y == true_i_max_y) diff --git a/src/opengl/experimental/ff8/MapFilters.hpp b/src/opengl/experimental/ff8/MapFilters.hpp index 9724ff80..398b8ae8 100644 --- a/src/opengl/experimental/ff8/MapFilters.hpp +++ b/src/opengl/experimental/ff8/MapFilters.hpp @@ -5,9 +5,9 @@ #ifndef FIELD_MAP_EDITOR_MAPFILTERS_HPP #define FIELD_MAP_EDITOR_MAPFILTERS_HPP #include "UniqueTileValues.hpp" -#include -#include -#include +#include +#include +#include namespace ff_8 { class MapFilters @@ -55,13 +55,14 @@ class MapFilters { bool ret_changed = false; { - const auto push_id = glengine::ImGuiPushId(); - const auto filter_disable = glengine::ImGuiDisabled(m_disabled); + const auto push_id = imgui_utils::ImGuiPushId(); + const auto filter_disable + = imgui_utils::ImGuiDisabled(m_disabled); auto const window_end = glengine::ScopeGuard{ []() { ImGui::End(); } }; if (ImGui::Begin("Map Filters")) { - const auto un_indent_0 = glengine::ImGuiIndent(); + const auto un_indent_0 = imgui_utils::ImGuiIndent(); static const auto common = []( const char *label, @@ -84,10 +85,11 @@ class MapFilters assert( std::ranges::size(possible_value_range) >= std::ranges::size(used_value_range)); - const auto push_id_0 = glengine::ImGuiPushId(); + const auto push_id_0 = imgui_utils::ImGuiPushId(); if (ImGui::CollapsingHeader(label)) { - const auto un_indent_1 = glengine::ImGuiIndent(); + const auto un_indent_1 + = imgui_utils::ImGuiIndent(); auto boolptr = std::ranges::begin(bool_range); const auto boolsent @@ -108,11 +110,11 @@ class MapFilters used_value_range, *current_value); const auto disabled - = glengine::ImGuiDisabled( + = imgui_utils ::ImGuiDisabled( found == std::ranges::end(used_value_range)); - const auto pop = glengine::ImGuiPushId(); + const auto pop = imgui_utils::ImGuiPushId(); const auto string = fmt::format("{:>4}", *current_string); auto size @@ -126,7 +128,7 @@ class MapFilters ImGui::SameLine(); { const auto push_id_1 - = glengine::ImGuiPushId(); + = imgui_utils::ImGuiPushId(); if (ImGui::Selectable( string.c_str(), static_cast(*boolptr), @@ -143,10 +145,10 @@ class MapFilters } ImGui::Dummy(ImVec2(2.F, 2.F)); { - const auto pop = glengine::ImGuiPushId(); + const auto pop = imgui_utils::ImGuiPushId(); { const auto push_id_2 - = glengine::ImGuiPushId(); + = imgui_utils::ImGuiPushId(); if (ImGui::Button("All")) { std::ranges::fill( @@ -161,10 +163,10 @@ class MapFilters ImGui::Dummy(ImVec2(2.F, 2.F)); ImGui::SameLine(); { - const auto pop = glengine::ImGuiPushId(); + const auto pop = imgui_utils::ImGuiPushId(); { const auto push_id_3 - = glengine::ImGuiPushId(); + = imgui_utils::ImGuiPushId(); if (ImGui::Button("None")) { std::ranges::fill( diff --git a/src/opengl/experimental/ff8/MapHistory.hpp b/src/opengl/experimental/ff8/MapHistory.hpp index ad6a05ff..502a21ca 100644 --- a/src/opengl/experimental/ff8/MapHistory.hpp +++ b/src/opengl/experimental/ff8/MapHistory.hpp @@ -6,7 +6,7 @@ #define FIELD_MAP_EDITOR_MAPHISTORY_HPP #include "MouseToTilePos.h" #include "SimilarAdjustments.hpp" -#include "UniquifyPupu.hpp" +#include #include #include namespace ff_8 diff --git a/src/opengl/experimental/ff8/MapSwizzle.hpp b/src/opengl/experimental/ff8/MapSwizzle.hpp index 354e3f4f..f8821a9a 100644 --- a/src/opengl/experimental/ff8/MapSwizzle.hpp +++ b/src/opengl/experimental/ff8/MapSwizzle.hpp @@ -5,14 +5,14 @@ #ifndef FIELD_MAP_EDITOR_MAPSWIZZLE_HPP #define FIELD_MAP_EDITOR_MAPSWIZZLE_HPP #include "Map.hpp" -#include "tile_operations.hpp" +#include namespace ff_8 { struct TileFunctionsSwizzle { - using X = tile_operations::SourceX; - using Y = tile_operations::SourceY; - using TexturePage = tile_operations::TextureId; + using X = TileOperations::SourceX; + using Y = TileOperations::SourceY; + using TexturePage = TileOperations::TextureId; using UseTexturePage = std::false_type; using UseBlending = std::false_type; static constexpr const char *const label = "Map (Swizzle)"; diff --git a/src/opengl/experimental/ff8/MapTileAdjustments.hpp b/src/opengl/experimental/ff8/MapTileAdjustments.hpp index db09afd4..e48f496d 100644 --- a/src/opengl/experimental/ff8/MapTileAdjustments.hpp +++ b/src/opengl/experimental/ff8/MapTileAdjustments.hpp @@ -7,12 +7,12 @@ #include "MapDims.hpp" #include "MapFilters.hpp" #include "SimilarAdjustments.hpp" -#include "tile_operations.hpp" #include "VisitState.hpp" -#include +#include #include -#include -#include +#include +#include +#include namespace ff_8 { template @@ -42,7 +42,7 @@ class MapTileAdjustments ImGui::SameLine(); { const auto disabled - = glengine::ImGuiDisabled(!m_map_history.undo_enabled()); + = imgui_utils::ImGuiDisabled(!m_map_history.undo_enabled()); if (ImGui::Button("Undo")) { visit_state = VisitState::Undo; @@ -111,7 +111,7 @@ class MapTileAdjustments const TileT &tile, bool &changed) const { - using namespace tile_operations; + bool draw = tile.draw(); if (ImGui::Checkbox("draw?", &draw)) { @@ -126,8 +126,9 @@ class MapTileAdjustments m_matching, [&](TileT &new_tile) { - new_tile - = new_tile.with_draw(static_cast>(draw)); + new_tile = new_tile.with_draw( + static_cast>( + draw)); }); } } @@ -202,7 +203,7 @@ class MapTileAdjustments checkbox_tool_tip("##matching bpp", "Matching BPP", m_matching.depth); const float width = ImGui::CalcItemWidth(); const auto pop_width - = glengine::ImGuiPushItemWidth(width - checkbox_width); + = imgui_utils::ImGuiPushItemWidth(width - checkbox_width); if (ImGui::Combo( "BPP", ¤t_bpp_selection, bpp_options.data(), 3)) { @@ -257,8 +258,8 @@ class MapTileAdjustments int step = 1, std::optional override_max = std::nullopt) const { - const auto pop_width = glengine::ImGuiPushItemWidth(width); - const auto pop_id = glengine::ImGuiPushId(); + const auto pop_width = imgui_utils::ImGuiPushItemWidth(width); + const auto pop_id = imgui_utils::ImGuiPushId(); if constexpr (!GroupT::read_only) { assert(step > 0); @@ -272,8 +273,9 @@ class MapTileAdjustments {}, ImGuiSliderFlags_AlwaysClamp)) { - group.current = static_cast( - current_int * step); + group.current + = static_cast( + current_int * step); return true; } } @@ -291,7 +293,7 @@ class MapTileAdjustments bool &changed, const int current_bpp_selection) const { - using namespace tile_operations; + const float checkbox_width = get_checkbox_width(3U); const std::pair item_width = generate_inner_width(2, checkbox_width); @@ -301,7 +303,7 @@ class MapTileAdjustments m_matching.source_xy); checkbox_tool_tip( "##matching source_x", "Matching Source X", m_matching.source_x); - auto x = SourceXGroup(tile); + auto x = TileOperations::SourceX::Group(tile); if (generic_slider_int( x, item_width.first, @@ -310,20 +312,20 @@ class MapTileAdjustments std::pow(2, (2 - current_bpp_selection) + 2) - 1)))) { changed = true; - const auto op = [&](TileT &new_tile) - { new_tile = new_tile.with_source_x(x.current); }; + const auto op = [current = x.current](TileT &new_tile) + { new_tile = new_tile.with_source_x(current); }; m_map_history.copy_working_perform_operation( tile, m_matching, op); } ImGui::SameLine(0, ImGui::GetStyle().ItemInnerSpacing.x); checkbox_tool_tip( "##matching source_y", "Matching Source Y", m_matching.source_y); - auto y = SourceYGroup(tile); + auto y = TileOperations::SourceY::Group(tile); if (generic_slider_int(y, item_width.second, tile.height())) { changed = true; - const auto op = [&](TileT &new_tile) - { new_tile = new_tile.with_source_y(y.current); }; + const auto op = [current = y.current](TileT &new_tile) + { new_tile = new_tile.with_source_y(current); }; m_map_history.copy_working_perform_operation( tile, m_matching, op); } @@ -345,7 +347,7 @@ class MapTileAdjustments const TileT &tile, bool &changed) const { - using namespace tile_operations; + const float checkbox_width = get_checkbox_width(5U); const std::pair item_width = generate_inner_width(3, checkbox_width); @@ -359,41 +361,41 @@ class MapTileAdjustments m_matching.xy); checkbox_tool_tip( "##matching x", "Matching Destination X", m_matching.x); - auto x = XGroup{ tile }; + auto x = TileOperations::X::Group{ tile }; if (generic_slider_int(x, item_width.first, tile.width())) { changed = true; m_map_history.copy_working_perform_operation( tile, m_matching, - [&](TileT &new_tile) - { new_tile = new_tile.with_x(x.current); }); + [current = x.current](TileT &new_tile) + { new_tile = new_tile.with_x(current); }); } ImGui::SameLine(0, ImGui::GetStyle().ItemInnerSpacing.x); checkbox_tool_tip( "##matching y", "Matching Destination Y", m_matching.y); - auto y = YGroup{ tile }; + auto y = TileOperations::Y::Group{ tile }; if (generic_slider_int(y, item_width.first, tile.width())) { changed = true; m_map_history.copy_working_perform_operation( tile, m_matching, - [&](TileT &new_tile) - { new_tile = new_tile.with_y(y.current); }); + [current = y.current](TileT &new_tile) + { new_tile = new_tile.with_y(current); }); } ImGui::SameLine(0, ImGui::GetStyle().ItemInnerSpacing.x); checkbox_tool_tip( "##matching z", "Matching Destination Z", m_matching.z); - auto z = ZGroup{ tile }; + auto z = TileOperations::Z::Group{ tile }; if (generic_slider_int(z, item_width.second, tile.width())) { changed = true; m_map_history.copy_working_perform_operation( tile, m_matching, - [&](TileT &new_tile) - { new_tile = new_tile.with_z(z.current); }); + [current = z.current](TileT &new_tile) + { new_tile = new_tile.with_z(current); }); m_filters.unique_tile_values().refresh_z(m_map_history); } ImGui::SameLine(0, ImGui::GetStyle().ItemInnerSpacing.x); @@ -408,9 +410,9 @@ class MapTileAdjustments const TileT &tile, bool &changed) const { - using namespace tile_operations; - const auto disabled - = glengine::ImGuiDisabled(!has_with_blend_mode); + + const auto disabled = imgui_utils::ImGuiDisabled( + !TileOperations::BlendMode::has_setter); const auto blend_mode = tile.blend_mode(); int current_blend_mode_selection = static_cast(blend_mode); const std::array blend_mode_str = { @@ -421,13 +423,13 @@ class MapTileAdjustments "##matching blend mode", "Matching Blend Mode", m_matching.blend_mode); - if (glengine::GenericCombo( + if (imgui_utils::GenericCombo( "Blend Mode", current_blend_mode_selection, blend_mode_str, checkbox_width)) { - if constexpr (has_with_blend_mode) + if constexpr (TileOperations::BlendMode::has_setter) { changed = true; m_map_history.copy_working_perform_operation( @@ -435,9 +437,11 @@ class MapTileAdjustments m_matching, [&](TileT &new_tile) { - new_tile = new_tile.with_blend_mode( - static_cast>( - current_blend_mode_selection)); + const auto blendmode_f + = TileOperations::BlendMode::With{ + current_blend_mode_selection + }; + new_tile = blendmode_f(new_tile); }); m_filters.unique_tile_values().refresh_blend_mode( m_map_history); @@ -449,22 +453,22 @@ class MapTileAdjustments const TileT &tile, bool &changed) const { - using namespace tile_operations; + using namespace open_viii::graphics::background; int layer_id = tile.layer_id(); const auto disabled - = glengine::ImGuiDisabled(!has_with_layer_id); + = imgui_utils::ImGuiDisabled(!has_with_layer_id); const float checkbox_width = get_checkbox_width(1U); const float width = ImGui::CalcItemWidth(); const auto pop_width - = glengine::ImGuiPushItemWidth(width - checkbox_width); + = imgui_utils::ImGuiPushItemWidth(width - checkbox_width); checkbox_tool_tip( "##matching layer_id", "Matching Layer ID", m_matching.layer_id); if (ImGui::SliderInt( "Layer ID", &layer_id, - LayerIdT{}, - LayerIdT{ 0b0111'1111U }, + TileOperations::LayerId::value_type{}, + TileOperations::LayerId::value_type{ 0b0111'1111U }, {}, ImGuiSliderFlags_AlwaysClamp)) { @@ -477,7 +481,9 @@ class MapTileAdjustments [&](TileT &new_tile) { new_tile = new_tile.with_layer_id( - static_cast>(layer_id)); + static_cast< + TileOperations::LayerId::value_type>( + layer_id)); }); m_filters.unique_tile_values().refresh_layer_id( m_map_history); @@ -489,12 +495,12 @@ class MapTileAdjustments const TileT &tile, bool &changed) const { - using namespace tile_operations; + int texture_page_id = static_cast(tile.texture_id()); const float checkbox_width = get_checkbox_width(1U); const float width = ImGui::CalcItemWidth(); const auto pop_width - = glengine::ImGuiPushItemWidth(width - checkbox_width); + = imgui_utils::ImGuiPushItemWidth(width - checkbox_width); checkbox_tool_tip( "##matching texture_page_id", "Matching Texture Page ID", @@ -502,8 +508,8 @@ class MapTileAdjustments if (ImGui::SliderInt( "Texture Page ID", &texture_page_id, - TextureIdT{}, - TextureIdT{ + TileOperations::TextureId::value_type{}, + TileOperations::TextureId::value_type{ 12U },// 15 is max val but 12 or 11 is max used {}, ImGuiSliderFlags_AlwaysClamp)) @@ -515,7 +521,9 @@ class MapTileAdjustments [&](TileT &new_tile) { new_tile = new_tile.with_texture_id( - static_cast>(texture_page_id)); + static_cast< + TileOperations::TextureId::value_type>( + texture_page_id)); }); m_filters.unique_tile_values().refresh_texture_page_id( m_map_history); @@ -526,11 +534,11 @@ class MapTileAdjustments const TileT &tile, bool &changed) const { - using namespace tile_operations; + const float checkbox_width = get_checkbox_width(1U); const float width = ImGui::CalcItemWidth(); const auto pop_width - = glengine::ImGuiPushItemWidth(width - checkbox_width); + = imgui_utils::ImGuiPushItemWidth(width - checkbox_width); checkbox_tool_tip( "##matching palette_id", "Matching Palette ID", @@ -539,8 +547,8 @@ class MapTileAdjustments if (ImGui::SliderInt( "Palette ID", &palette_id, - PaletteIdT{}, - PaletteIdT{ 0b1111U }, + TileOperations::PaletteId::value_type{}, + TileOperations::PaletteId::value_type{ 0b1111U }, {}, ImGuiSliderFlags_AlwaysClamp)) @@ -552,7 +560,9 @@ class MapTileAdjustments [&](TileT &new_tile) { new_tile = new_tile.with_palette_id( - static_cast>(palette_id)); + static_cast< + TileOperations::PaletteId::value_type>( + palette_id)); }); m_filters.unique_tile_values().refresh_palette_id(m_map_history); } @@ -562,19 +572,19 @@ class MapTileAdjustments const TileT &tile, bool &changed) const { - using namespace tile_operations; + int blend = tile.blend(); const float checkbox_width = get_checkbox_width(1U); const float width = ImGui::CalcItemWidth(); checkbox_tool_tip( "##matching blend other", "Matching Blend Other", m_matching.blend); const auto pop_width - = glengine::ImGuiPushItemWidth(width - checkbox_width); + = imgui_utils::ImGuiPushItemWidth(width - checkbox_width); if (ImGui::SliderInt( "Blend Other", &blend, - BlendT{}, - BlendT{ 0b0011U }, + TileOperations::Blend::value_type{}, + TileOperations::Blend::value_type{ 0b0011U }, {}, ImGuiSliderFlags_AlwaysClamp)) { @@ -585,7 +595,8 @@ class MapTileAdjustments [&](TileT &new_tile) { new_tile = new_tile.with_blend( - static_cast>(blend)); + static_cast>( + blend)); }); m_filters.unique_tile_values().refresh_blend_other( m_map_history); @@ -596,7 +607,7 @@ class MapTileAdjustments const TileT &tile, bool &changed) const { - using namespace tile_operations; + using namespace open_viii::graphics::background; int animation_id = tile.animation_id(); int animation_state = tile.animation_state(); @@ -609,14 +620,16 @@ class MapTileAdjustments = generate_inner_width(2, checkbox_width); { const auto disabled - = glengine::ImGuiDisabled(!has_with_animation_id); + = imgui_utils::ImGuiDisabled(!has_with_animation_id); const auto pop_width - = glengine::ImGuiPushItemWidth(item_width.first); + = imgui_utils::ImGuiPushItemWidth(item_width.first); if (ImGui::SliderInt( "##Animation ID", &animation_id, - std::numeric_limits>::min(), - std::numeric_limits>::max(), + std::numeric_limits< + TileOperations::AnimationId::value_type>::min(), + std::numeric_limits< + TileOperations::AnimationId::value_type>::max(), {}, ImGuiSliderFlags_AlwaysClamp)) { @@ -629,7 +642,8 @@ class MapTileAdjustments [&](TileT &new_tile) { new_tile = new_tile.with_animation_id( - static_cast>( + static_cast>( animation_id)); }); m_filters.unique_tile_values().refresh_animation_id( @@ -644,14 +658,16 @@ class MapTileAdjustments m_matching.animation_state); { const auto disabled - = glengine::ImGuiDisabled(!has_with_animation_state); + = imgui_utils::ImGuiDisabled(!has_with_animation_state); const auto pop_width - = glengine::ImGuiPushItemWidth(item_width.second); + = imgui_utils::ImGuiPushItemWidth(item_width.second); if (ImGui::SliderInt( "##Animation State", &animation_state, - std::numeric_limits>::min(), - std::numeric_limits>::max(), + std::numeric_limits>::min(), + std::numeric_limits>::max(), {}, ImGuiSliderFlags_AlwaysClamp)) { @@ -664,7 +680,8 @@ class MapTileAdjustments [&](TileT &new_tile) { new_tile = new_tile.with_animation_state( - static_cast>( + static_cast>( animation_state)); }); m_filters.unique_tile_values().refresh_animation_frame( diff --git a/src/opengl/experimental/ff8/MapUpscaleDeswizzle.hpp b/src/opengl/experimental/ff8/MapUpscaleDeswizzle.hpp index a15307ab..26452088 100644 --- a/src/opengl/experimental/ff8/MapUpscaleDeswizzle.hpp +++ b/src/opengl/experimental/ff8/MapUpscaleDeswizzle.hpp @@ -5,14 +5,14 @@ #ifndef FIELD_MAP_EDITOR_MAPUPSCALEDESWIZZLE_HPP #define FIELD_MAP_EDITOR_MAPUPSCALEDESWIZZLE_HPP #include "Map.hpp" -#include "tile_operations.hpp" +#include namespace ff_8 { struct TileFunctionsUpscaleDeswizzle { - using X = tile_operations::X; - using Y = tile_operations::Y; - using TexturePage = tile_operations::TextureIdDefaultValue; + using X = TileOperations::X; + using Y = TileOperations::Y; + using TexturePage = TileOperations::TextureId::DefaultValue; using UseTexturePage = std::true_type; using UseBlending = std::true_type; static constexpr const char *const label = "Map (Swizzle Deswizzle)"; diff --git a/src/opengl/experimental/ff8/MapUpscaleSwizzle.hpp b/src/opengl/experimental/ff8/MapUpscaleSwizzle.hpp index 7ee827e9..31d9baab 100644 --- a/src/opengl/experimental/ff8/MapUpscaleSwizzle.hpp +++ b/src/opengl/experimental/ff8/MapUpscaleSwizzle.hpp @@ -5,14 +5,14 @@ #ifndef FIELD_MAP_EDITOR_MAPUPSCALESWIZZLE_HPP #define FIELD_MAP_EDITOR_MAPUPSCALESWIZZLE_HPP #include "Map.hpp" -#include "tile_operations.hpp" +#include namespace ff_8 { struct TileFunctionsUpscaleSwizzle { - using X = tile_operations::SourceX; - using Y = tile_operations::SourceY; - using TexturePage = tile_operations::TextureId; + using X = TileOperations::SourceX; + using Y = TileOperations::SourceY; + using TexturePage = TileOperations::TextureId; using UseTexturePage = std::false_type; using UseBlending = std::false_type; static constexpr const char *const label = "Map (Swizzle Swizzle)"; diff --git a/src/opengl/experimental/ff8/MenuSaveToggles.hpp b/src/opengl/experimental/ff8/MenuSaveToggles.hpp index 27b6af08..8b24a727 100644 --- a/src/opengl/experimental/ff8/MenuSaveToggles.hpp +++ b/src/opengl/experimental/ff8/MenuSaveToggles.hpp @@ -4,13 +4,13 @@ #ifndef FIELD_MAP_EDITOR_MENUSAVETOGGLES_HPP #define FIELD_MAP_EDITOR_MENUSAVETOGGLES_HPP -#include "Configuration.hpp" #include "Menu.hpp" +#include #include #include static inline void MenuSaveToggles( const glengine::Menu &menu, - Configuration &config) + ff_8::Configuration &config) { const auto string = fmt::format("{}_menu", menu.title()); toml::array array{}; @@ -25,12 +25,12 @@ static inline void MenuSaveToggles( } static inline void MenuSaveToggles(const glengine::Menu &menu) { - Configuration config{}; + ff_8::Configuration config{}; MenuSaveToggles(menu, config); } static inline void MenuLoadToggles( - glengine::Menu &menu, - Configuration &config) + glengine::Menu &menu, + ff_8::Configuration &config) { const auto string = fmt::format("{}_menu", menu.title()); if (config->contains(string)) @@ -50,7 +50,7 @@ static inline void MenuLoadToggles( } static inline void MenuLoadToggles(glengine::Menu &menu) { - Configuration config{}; + ff_8::Configuration config{}; MenuLoadToggles(menu, config); } diff --git a/src/opengl/experimental/ff8/Mim.cpp b/src/opengl/experimental/ff8/Mim.cpp index dc537dcc..80815589 100644 --- a/src/opengl/experimental/ff8/Mim.cpp +++ b/src/opengl/experimental/ff8/Mim.cpp @@ -4,7 +4,6 @@ #include "Mim.hpp" #include "Application.hpp" -#include "ImGuiDisabled.hpp" #include "ImGuiTileDisplayWindow.hpp" #include "OrthographicCameraController.hpp" #include @@ -12,6 +11,7 @@ #include #include #include +#include namespace ff_8 { static const Bpps Bpp = {}; @@ -74,10 +74,10 @@ void ff_8::Mim::on_render() const } void ff_8::Mim::on_im_gui_update() const { - const auto pop_id = glengine::ImGuiPushId(); + const auto pop_id = imgui_utils::ImGuiPushId(); const auto &local_texture = current_texture(); { - const auto disable = glengine::ImGuiDisabled( + const auto disable = imgui_utils ::ImGuiDisabled( local_texture.height() == 0 || local_texture.width() == 0); diff --git a/src/opengl/experimental/ff8/MouseToTilePos.h b/src/opengl/experimental/ff8/MouseToTilePos.h index c5f6ad0d..c60e2036 100644 --- a/src/opengl/experimental/ff8/MouseToTilePos.h +++ b/src/opengl/experimental/ff8/MouseToTilePos.h @@ -5,7 +5,7 @@ #ifndef FIELD_MAP_EDITOR_MOUSETOTILEPOS_H #define FIELD_MAP_EDITOR_MOUSETOTILEPOS_H #include "MapDims.hpp" -#include "tile_operations.hpp" +#include namespace ff_8 { class MouseToTilePos @@ -33,7 +33,7 @@ class MouseToTilePos { static constexpr bool has_texture_page = std::is_same_v< typename TileFunctions::TexturePage, - tile_operations::TextureId>; + TileOperations::TextureId>; texture_page = [&]() -> std::uint8_t { if constexpr (has_texture_page) diff --git a/src/opengl/experimental/ff8/Palettes.cpp b/src/opengl/experimental/ff8/Palettes.cpp index 1760720e..86802772 100644 --- a/src/opengl/experimental/ff8/Palettes.cpp +++ b/src/opengl/experimental/ff8/Palettes.cpp @@ -3,10 +3,10 @@ // #include "Palettes.hpp" #include "imgui.h" -#include +#include bool ff_8::Palettes::on_im_gui_update() const { - return glengine::GenericCombo("Palette", m_current, m_strings); + return imgui_utils::GenericCombo("Palette", m_current, m_strings); } ff_8::Palettes::operator std::uint8_t() const { diff --git a/src/opengl/experimental/ff8/Paths.cpp b/src/opengl/experimental/ff8/Paths.cpp index 9110c00e..6712f62f 100644 --- a/src/opengl/experimental/ff8/Paths.cpp +++ b/src/opengl/experimental/ff8/Paths.cpp @@ -2,8 +2,8 @@ // Created by pcvii on 11/30/2021. // #include "Paths.hpp" -#include "Configuration.hpp" -#include +#include +#include #include static constexpr auto ff8_directory_paths = std::string_view{ "ff8_directory_paths" }; @@ -11,7 +11,7 @@ static constexpr auto ff8_directory_path_index = std::string_view{ "ff8_directory_path_index" }; bool ff_8::Paths::on_im_gui_update() const { - if (glengine::GenericCombo( + if (imgui_utils::GenericCombo( "Path", m_current, m_paths @@ -22,7 +22,7 @@ bool ff_8::Paths::on_im_gui_update() const }))// todo filter by if is directory check ) { - auto config = Configuration{}; + auto config = ff_8::Configuration{}; config->insert_or_assign(ff8_directory_path_index, m_current); config.save(); return true; @@ -39,7 +39,7 @@ const std::string &ff_8::Paths::string() const const static auto empty = std::string(""); return empty; } -ff_8::Paths::Paths(Configuration config) +ff_8::Paths::Paths(ff_8::Configuration config) : m_paths( [&]() { @@ -68,6 +68,6 @@ ff_8::Paths::operator std::filesystem::path() const return string(); } ff_8::Paths::Paths() - : Paths(Configuration{}) + : Paths(ff_8::Configuration{}) { } diff --git a/src/opengl/experimental/ff8/Paths.hpp b/src/opengl/experimental/ff8/Paths.hpp index adff670b..bd995b76 100644 --- a/src/opengl/experimental/ff8/Paths.hpp +++ b/src/opengl/experimental/ff8/Paths.hpp @@ -4,7 +4,7 @@ #ifndef FIELD_MAP_EDITOR_PATHS_HPP #define FIELD_MAP_EDITOR_PATHS_HPP -#include "Configuration.hpp" +#include #include #include #include @@ -21,7 +21,7 @@ class Paths void on_event(const glengine::event::Item &) const {} [[nodiscard]] operator std::filesystem::path() const; Paths(); - explicit Paths(Configuration); + explicit Paths(ff_8::Configuration); private: [[nodiscard]] const std::string &string() const; diff --git a/src/opengl/experimental/ff8/PupuID.hpp b/src/opengl/experimental/ff8/PupuID.hpp deleted file mode 100644 index a25fbaaa..00000000 --- a/src/opengl/experimental/ff8/PupuID.hpp +++ /dev/null @@ -1,127 +0,0 @@ -// -// Created by pcvii on 10/19/2021. -// - -#ifndef FIELD_MAP_EDITOR_PUPUID_HPP -#define FIELD_MAP_EDITOR_PUPUID_HPP -#include "open_viii/graphics/background/Map.hpp" -#include -#include -struct PupuID -{ - constexpr PupuID() = default; - constexpr explicit PupuID(std::uint32_t raw) - : m_raw(raw) - { - } - // layer is 7 bits - static constexpr std::uint32_t layer_offset = 24U; - // blend is only 0,1,2,3,4. So 3 bits - static constexpr std::uint32_t blend_offset = 20U; - // animation id and state is 8 bits - static constexpr std::uint32_t animation_offset = 12U; - static constexpr std::uint32_t animation_state_offset = 4U; - // leaves 3 bits for offset markers and 3 bits for offset increment - constexpr PupuID( - const open_viii::graphics::background::is_tile auto &tile, - std::uint8_t offset = 0U) - : PupuID( - std::uint32_t{ - ((static_cast(tile.layer_id()) & 0x7FU) - << layer_offset) - | ((static_cast(tile.blend_mode()) & 0x07U) << blend_offset) - | static_cast( - tile.animation_id() << animation_offset) - | static_cast( - tile.animation_state() << animation_state_offset) - | static_cast(offset & 0xF) }) - { - if (tile.x() % 16 != 0) - { - m_raw |= 0x8000'0000U; - } - if (tile.y() % 16 != 0) - { - m_raw |= 0x0080'0000U; - } - } - constexpr auto &operator+=(std::uint32_t right) - { - m_raw += right; - return *this; - } - [[nodiscard]] constexpr auto operator+(std::uint32_t right) const - { - auto cpy = *this; - cpy += right; - return cpy; - } - constexpr auto &operator|=(std::uint32_t right) - { - m_raw |= right; - return *this; - } - [[nodiscard]] constexpr auto operator|(std::uint32_t right) const - { - auto cpy = *this; - cpy |= right; - return cpy; - } - constexpr auto &operator+=(PupuID right) - { - m_raw += right.raw(); - return *this; - } - [[nodiscard]] constexpr auto operator+(PupuID right) const - { - auto cpy = *this; - cpy += right.raw(); - return cpy; - } - [[nodiscard]] constexpr std::uint32_t raw() const - { - return m_raw; - } - [[nodiscard]] bool constexpr same_base(PupuID right) const - { - constexpr auto mask = 0xFFFF'FFF0U; - return (m_raw & mask) == (right.raw() & mask); - } - - constexpr auto operator<=>(const PupuID &) const = default; - - private: - std::uint32_t m_raw{}; -}; -// PupuID = uint32_t(0U + (tile.layer_id() << -// 24U)+(static_cast(tile.blend_mode()) << 20U) + -// (tile.animation_id() <<12U)+ (tile.animation_state()<<4U)) - -// std::transform(Sprites.cbegin(), Sprites.cend() - 1, Sprites.cbegin() + 1, -// Sprites.begin()+1, [](const Sprite& first, Sprite second) { -// static constexpr auto mask = 0xFFFFFFF0U; -// if ((first.ID & mask) == (second.ID & mask)) -// { -// second.ID = first.ID + 1; -// } -// return second; -// }); - -// IDs.reserve(Sprites.size()); -// std::transform(Sprites.cbegin(), Sprites.cend(), std::back_inserter(IDs), -// [](const Sprite& sprite) {return sprite.ID; }); std::sort(IDs.begin(), -// IDs.end()); auto it = std::unique(IDs.begin(), IDs.end()); IDs.erase(it, -// IDs.end()); -template<> -struct fmt::formatter : fmt::formatter -{ - // Formats value using the parsed format specification stored in this - // formatter and writes the output to ctx.out(). - auto format( - const PupuID &value, - format_context &ctx) const -> format_context::iterator - { - return fmt::format_to(ctx.out(), "{:08X}", value.raw()); - } -}; -#endif// FIELD_MAP_EDITOR_PUPUID_HPP diff --git a/src/opengl/experimental/ff8/SimilarAdjustments.hpp b/src/opengl/experimental/ff8/SimilarAdjustments.hpp index fddbed9d..9b4109df 100644 --- a/src/opengl/experimental/ff8/SimilarAdjustments.hpp +++ b/src/opengl/experimental/ff8/SimilarAdjustments.hpp @@ -4,7 +4,7 @@ #ifndef FIELD_MAP_EDITOR_SIMILARADJUSTMENTS_HPP #define FIELD_MAP_EDITOR_SIMILARADJUSTMENTS_HPP -#include "tile_operations.hpp" +#include namespace ff_8 { struct SimilarAdjustments @@ -29,29 +29,33 @@ struct SimilarAdjustments template auto operator()(const TileT &tile) const { - using namespace tile_operations; - static constexpr auto xy_f = XY{}; - static constexpr auto z_f = Z{}; + + static constexpr auto xy_f = TileOperations::XY{}; + static constexpr auto z_f = TileOperations::Z{}; return [=, this](const TileT &other_tile) -> bool { const auto compare = [&](bool toggle, auto &&op) -> bool { return !toggle || op(tile) == op(other_tile); }; return std::ranges::all_of( std::array{ - compare(x, X{}), compare(y, Y{}), compare(xy, xy_f), + compare(x, TileOperations::X{}), + compare(y, TileOperations::Y{}), compare(xy, xy_f), compare(z, z_f), compare( xyz, [](const TileT &t) { return std::make_pair(xy_f(t), z_f(t)); }), - compare(source_x, SourceX{}), compare(source_y, SourceY{}), - compare(source_xy, SourceXY{}), - compare(texture_id, TextureId{}), - compare(blend_mode, BlendMode{}), compare(blend, Blend{}), - compare(draw, Draw{}), compare(depth, Depth{}), - compare(layer_id, LayerId{}), - compare(palette_id, PaletteId{}), - compare(animation_id, AnimationId{}), - compare(animation_state, AnimationState{}) }, + compare(source_x, TileOperations::SourceX{}), + compare(source_y, TileOperations::SourceY{}), + compare(source_xy, TileOperations::SourceXY{}), + compare(texture_id, TileOperations::TextureId{}), + compare(blend_mode, TileOperations::BlendMode{}), + compare(blend, TileOperations::Blend{}), + compare(draw, TileOperations::Draw{}), + compare(depth, TileOperations::Depth{}), + compare(layer_id, TileOperations::LayerId{}), + compare(palette_id, TileOperations::PaletteId{}), + compare(animation_id, TileOperations::AnimationId{}), + compare(animation_state, TileOperations::AnimationState{}) }, std::identity{}); }; } diff --git a/src/opengl/experimental/ff8/UniqueTileValues.hpp b/src/opengl/experimental/ff8/UniqueTileValues.hpp index e9f8462c..8428dd69 100644 --- a/src/opengl/experimental/ff8/UniqueTileValues.hpp +++ b/src/opengl/experimental/ff8/UniqueTileValues.hpp @@ -5,9 +5,9 @@ #ifndef FIELD_MAP_EDITOR_UNIQUETILEVALUES_HPP #define FIELD_MAP_EDITOR_UNIQUETILEVALUES_HPP #include "MapHistory.hpp" -#include "tile_operations.hpp" #include "TransformedSortedUniqueCopy.hpp" #include "UniqueValues.hpp" +#include #include namespace ff_8 { @@ -17,11 +17,12 @@ struct UniqueTileValues using MapT = MapHistory; static auto filtered(const auto &tiles) { - return tiles | std::views::filter(tile_operations::NotInvalidTile{}); + return tiles | std::views::filter(TileOperations::NotInvalidTile{}); }; + template static auto visit( - const MapT &map, - auto &&transform) + const MapT &map, + TransformT &&transform) { return map.front().visit_tiles( [&](const auto &f_tiles) @@ -30,7 +31,7 @@ struct UniqueTileValues [&](const auto &b_tiles) { return TransformedSortedUniqueCopy( - std::forward(transform), + std::forward(transform), {}, {}, {}, @@ -63,41 +64,41 @@ struct UniqueTileValues } static auto gen_z(const MapT &map) { - return visit(map, tile_operations::Z{}); + return visit(map, TileOperations::Z{}); } static auto gen_layer_id(const MapT &map) { - return visit(map, tile_operations::LayerId{}); + return visit(map, TileOperations::LayerId{}); } static auto gen_palette_id(const MapT &map) { - return visit(map, tile_operations::PaletteId{}); + return visit(map, TileOperations::PaletteId{}); } static auto gen_texture_page_id(const MapT &map) { - return visit(map, tile_operations::TextureId{}); + return visit(map, TileOperations::TextureId{}); } static auto gen_animation_id(const MapT &map) { - return visit(map, tile_operations::AnimationId{}); + return visit(map, TileOperations::AnimationId{}); } static auto gen_animation_frame(const MapT &map) { - return visit(map, tile_operations::AnimationState{}); + return visit(map, TileOperations::AnimationState{}); } static auto gen_blend_other(const MapT &map) { - return visit(map, tile_operations::Blend{}); + return visit(map, TileOperations::Blend{}); } static auto gen_blend_mode(const MapT &map) { return UniqueValues( - visit(map, tile_operations::BlendMode{}), blendmode_to_string); + visit(map, TileOperations::BlendMode{}), blendmode_to_string); } static auto gen_bpp(const MapT &map) { return UniqueValues( - visit(map, tile_operations::Depth{}), bpp_to_string); + visit(map, TileOperations::Depth{}), bpp_to_string); } static void refresh( const MapT &map, diff --git a/src/opengl/experimental/ff8/UniquifyPupu.hpp b/src/opengl/experimental/ff8/UniquifyPupu.hpp deleted file mode 100644 index 24966c5c..00000000 --- a/src/opengl/experimental/ff8/UniquifyPupu.hpp +++ /dev/null @@ -1,58 +0,0 @@ -// -// Created by pcvii on 9/6/2022. -// - -#ifndef FIELD_MAP_EDITOR_UNIQUIFYPUPU_HPP -#define FIELD_MAP_EDITOR_UNIQUIFYPUPU_HPP -#include "PupuID.hpp" -#include - -class UniquifyPupu -{ - public: - struct PupuKey - { - PupuID pupu_id = {}; - std::int16_t x = {}; - std::int16_t y = {}; - auto operator<=>(const PupuKey &) const = default; - }; - std::map m_pupu_map = {}; - - PupuID operator()( - const open_viii::graphics::background::is_tile auto &tile_const) - { - const auto tile_size = 16; - const auto x_position - = static_cast(tile_const.x() / tile_size); - const auto y_position - = static_cast(tile_const.y() / tile_size); - auto input_value - = PupuKey{ PupuID(tile_const), x_position, y_position }; - auto insert_key = [&](PupuKey key) -> PupuID - { - if (m_pupu_map.contains(key)) - { - ++(m_pupu_map.at(key)); - return key.pupu_id + m_pupu_map.at(key); - } - else - { - m_pupu_map.emplace(key, std::uint8_t{}); - return key.pupu_id + m_pupu_map.at(key); - } - }; - return insert_key(input_value); - } - // operator UniqueValues() const - // { - // std::vector values{}; - // std::ranges::transform(m_pupu_map, - // std::back_insert_iterator(values),[](auto && key_value)->PupuID{ - // const auto & [key,value] = key_value; - // return key.pupu_id; - // }); - // UniqueValues{std::move(values)}; - // } -}; -#endif// FIELD_MAP_EDITOR_UNIQUIFYPUPU_HPP diff --git a/src/opengl/experimental/ff8/Upscales.cpp b/src/opengl/experimental/ff8/Upscales.cpp index 83421118..22c05209 100644 --- a/src/opengl/experimental/ff8/Upscales.cpp +++ b/src/opengl/experimental/ff8/Upscales.cpp @@ -3,7 +3,7 @@ // #include "Upscales.hpp" -#include +#include #include static constexpr auto swizzle_paths_index = std::string_view("swizzle_paths_index"); @@ -11,14 +11,14 @@ static constexpr auto upscale_paths_vector = std::string_view("upscale_paths_vector"); bool ff_8::Upscales::on_im_gui_update() const { - if (glengine::GenericCombo( + if (imgui_utils::GenericCombo( "Swizzle Path", m_current, m_paths | std::ranges::views::transform( [](auto &&value) -> decltype(auto) { return value.template ref(); }))) { - auto config = Configuration{}; + auto config = ff_8::Configuration{}; config->insert_or_assign(swizzle_paths_index, m_current); config.save(); return true; @@ -137,10 +137,10 @@ static std::vector get_default_paths() return paths; } ff_8::Upscales::Upscales() - : Upscales(Configuration{}) + : Upscales(ff_8::Configuration{}) { } -ff_8::Upscales::Upscales(Configuration config) +ff_8::Upscales::Upscales(ff_8::Configuration config) : m_current(config[swizzle_paths_index].value_or(int{})) , m_paths( [&]() -> toml::array diff --git a/src/opengl/experimental/ff8/Upscales.hpp b/src/opengl/experimental/ff8/Upscales.hpp index 87e381e2..9aca6e6b 100644 --- a/src/opengl/experimental/ff8/Upscales.hpp +++ b/src/opengl/experimental/ff8/Upscales.hpp @@ -4,7 +4,7 @@ #ifndef FIELD_MAP_EDITOR_UPSCALES_HPP #define FIELD_MAP_EDITOR_UPSCALES_HPP -#include "Configuration.hpp" +#include #include #include namespace ff_8 @@ -18,7 +18,7 @@ class Upscales void on_event(const glengine::event::Item &) const {} operator std::filesystem::path() const; Upscales(); - Upscales(Configuration); + Upscales(ff_8::Configuration); private: [[nodiscard]] const std::string &string() const; diff --git a/src/opengl/experimental/ff8/tile_operations.hpp b/src/opengl/experimental/ff8/tile_operations.hpp deleted file mode 100644 index 4d200cd4..00000000 --- a/src/opengl/experimental/ff8/tile_operations.hpp +++ /dev/null @@ -1,253 +0,0 @@ -// -// Created by pcvii on 6/14/2022. -// - -#ifndef FIELD_MAP_EDITOR_TILE_OPERATIONS_HPP -#define FIELD_MAP_EDITOR_TILE_OPERATIONS_HPP -#include -#include -namespace ff_8 -{ -namespace tile_operations -{ - template - static constexpr TileT MaxTile = []() - { - std::array tmp{}; - // std::fill(tmp.begin(), tmp.end(), 0xFFU); - tmp.fill(0xFFU); - return std::bit_cast(tmp); - }(); -#define TILE_OPERATION(STRING, FUNCTION) \ - template \ - using STRING##T = typename std::remove_cvref_t< \ - std::invoke_result_t>; \ - struct STRING \ - { \ - template \ - constexpr STRING##T \ - operator()(const TileT &tile) const noexcept \ - { \ - return tile.FUNCTION(); \ - } \ - }; \ - template \ - struct STRING##Match \ - { \ - template \ - constexpr STRING##Match(TileT tile) \ - : STRING##Match(tile.FUNCTION()) \ - { \ - } \ - constexpr STRING##Match(ValueT value) \ - requires(!open_viii::graphics::background::is_tile) \ - : m_value(std::move(value)) \ - { \ - } \ - template \ - constexpr bool operator()(const TileT &tile) const noexcept \ - { \ - return static_cast>(m_value) \ - == tile.FUNCTION(); \ - } \ - auto operator<=>(const STRING##Match &) const = default; \ - std::strong_ordering operator<=>(const ValueT &that) const \ - { \ - return m_value <=> that; \ - } \ - template \ - std::strong_ordering operator<=>(const TileT &tile) const \ - { \ - return static_cast>(m_value) \ - <=> tile.FUNCTION(); \ - } \ - \ - private: \ - ValueT m_value = {}; \ - }; \ - struct STRING##DefaultValue \ - { \ - template \ - constexpr STRING##T operator()(const T &) const noexcept \ - { \ - return {}; \ - } \ - }; \ - template \ - concept has_with_##FUNCTION \ - = requires(std::remove_cvref_t t, STRING##T v) { \ - t = t.with_##FUNCTION(v); \ - }; \ - template \ - struct With##STRING \ - { \ - constexpr With##STRING(ValueT value) \ - : m_value(std::move(value)) \ - { \ - } \ - template \ - requires(has_with_##FUNCTION) \ - [[nodiscard]] constexpr TileT \ - operator()(const TileT &tile) const noexcept \ - { \ - spdlog::debug( \ - "Used with_" #FUNCTION " to assign: {}", m_value); \ - return tile.with_##FUNCTION( \ - static_cast>(m_value)); \ - } \ - \ - template \ - requires(!has_with_##FUNCTION) \ - constexpr decltype(auto) \ - operator()(const TileT &tile) const noexcept \ - { /*donno why I can not forward or move when not has_with*/ \ - spdlog::debug("Has no with_" #FUNCTION); \ - return tile; \ - } \ - \ - private: \ - ValueT m_value = {}; \ - }; \ - template \ - struct TranslateWith##STRING \ - { \ - constexpr TranslateWith##STRING( \ - ValueT to, \ - ValueT from) \ - : m_to(std::move(to)) \ - , m_from(std::move(from)) \ - { \ - } \ - template \ - requires(has_with_##FUNCTION) \ - [[nodiscard]] constexpr TileT \ - operator()(const TileT &tile) const noexcept \ - { \ - const auto current = m_to + tile.FUNCTION() - m_from; \ - spdlog::debug( \ - "Used with_" #FUNCTION " to assign: {}", current); \ - return tile.with_##FUNCTION( \ - static_cast>(current)); \ - } \ - \ - template \ - requires(!has_with_##FUNCTION) \ - constexpr decltype(auto) \ - operator()(const TileT &tile) const noexcept \ - { /*donno why I can not forward or move when not has_with*/ \ - spdlog::debug("Has no with_" #FUNCTION); \ - return tile; \ - } \ - \ - private: \ - ValueT m_to = {}; \ - ValueT m_from = {}; /*used to calc offset using original*/ \ - }; \ - template \ - struct STRING##Group \ - { \ - using value_type = STRING##T; \ - using get = STRING; \ - using get_default = STRING##DefaultValue; \ - constexpr STRING##Group() = default; \ - constexpr STRING##Group(value_type value) \ - : current(std::move(value)) \ - { \ - } \ - constexpr STRING##Group(TileT tile) \ - : current(get{}(tile)) \ - { \ - } \ - static constexpr value_type min_value = []() -> value_type \ - { \ - if constexpr (std::signed_integral) \ - { \ - return (std::numeric_limits::min)(); \ - } \ - else \ - { \ - const auto get_f = get{}; \ - return get_f(TileT{}); \ - } \ - }(); \ - static constexpr value_type max_value = []() -> value_type \ - { \ - if constexpr (std::signed_integral) \ - { \ - return (std::numeric_limits::max)(); \ - } \ - else \ - { \ - const auto get_f = get{}; \ - return get_f(MaxTile); \ - } \ - }(); \ - value_type current = {}; \ - constexpr static bool read_only = !has_with_##FUNCTION; \ - using transform_with = With##STRING; \ - using match_with = STRING##Match; \ - } - - TILE_OPERATION( - X, - x); - TILE_OPERATION( - Y, - y); - TILE_OPERATION( - XY, - xy); - TILE_OPERATION( - Z, - z); - TILE_OPERATION( - SourceX, - source_x); - TILE_OPERATION( - SourceY, - source_y); - TILE_OPERATION( - SourceXY, - source_xy); - TILE_OPERATION( - TextureId, - texture_id); - TILE_OPERATION( - BlendMode, - blend_mode); - TILE_OPERATION( - Blend, - blend); - TILE_OPERATION( - Draw, - draw); - TILE_OPERATION( - Depth, - depth); - TILE_OPERATION( - LayerId, - layer_id); - TILE_OPERATION( - PaletteId, - palette_id); - TILE_OPERATION( - AnimationId, - animation_id); - TILE_OPERATION( - AnimationState, - animation_state); -#undef TILE_OPERATION - struct NotInvalidTile - { - template - constexpr bool operator()(const T &tile) const noexcept - { - return (std::cmp_not_equal(tile.x(), s_end_x)); - } - - private: - static constexpr std::uint16_t s_end_x = { 0x7FFFU }; - }; -}// namespace tile_operations -}// namespace ff_8 -#endif// FIELD_MAP_EDITOR_TILE_OPERATIONS_HPP diff --git a/src/opengl/experimental/main.cpp b/src/opengl/experimental/main.cpp index 2f2fe0eb..dcd7df30 100644 --- a/src/opengl/experimental/main.cpp +++ b/src/opengl/experimental/main.cpp @@ -1,10 +1,98 @@ // #include +#ifndef DEFAULT_LOG_PATH +#define DEFAULT_LOG_PATH "res/field-map-editor.log"// fallback, just in case +#endif #include "Application.hpp" -int main() +#include + +#ifdef _WIN32 +#include + +int main( + int argc, + char **argv);// your existing main + +int WINAPI WinMain( + [[maybe_unused]] HINSTANCE hInstance, + [[maybe_unused]] HINSTANCE hPrevInstance, + [[maybe_unused]] LPSTR lpCmdLine, + [[maybe_unused]] int nCmdShow) +{ + // Convert lpCmdLine to argc/argv if needed, or just call main(0,nullptr) + return main(__argc, __argv); +} +#endif + + +int main( + [[maybe_unused]] int argc, + [[maybe_unused]] char **argv) { // todo attach this scope gaurd to the api somewhere // anything created in the window must be destroyed before the window. - spdlog::set_level(spdlog::level::debug);// Set global log level to debug + std::error_code error_code = {}; + + auto temp_path = std::filesystem::path(DEFAULT_LOG_PATH); + std::string path; + try + { + if (temp_path.is_relative()) + { + temp_path = (std::filesystem::current_path(error_code) / path); + } + temp_path.make_preferred(); + spdlog::info("log path: {}", temp_path); + path = temp_path.string(); + } + catch (const std::filesystem::filesystem_error &e) + { + spdlog::error( + "Filesystem error while constructing config path: {}", e.what()); + } + catch (const std::exception &e) + { + spdlog::error( + "Unexpected error while constructing config path: {}", e.what()); + } + if (error_code) + { + spdlog::warn( + "{}:{} - {}: {} path: \"{}\"", + __FILE__, + __LINE__, + error_code.value(), + error_code.message(), + path); + error_code.clear(); + } + + try + { + // Create file logger and set as default + auto file_logger = spdlog::basic_logger_mt("file_logger", path, true); + + // Remove logger name from output pattern + file_logger->set_pattern(R"([%Y-%m-%d %H:%M:%S.%e] [%^%l%$] %v)"); + + spdlog::set_default_logger(file_logger); + + // Set log level based on build type + // #ifndef NDEBUG + spdlog::set_level(spdlog::level::debug);// Debug build + // #else + // spdlog::set_level(spdlog::level::info);// Release build + // #endif + + // Optional: control flush policy + spdlog::flush_on(spdlog::level::info); + + // Now log anywhere + spdlog::info("App started"); + } + catch (const spdlog::spdlog_ex &ex) + { + std::cerr << "Log init failed: " << ex.what() << std::endl; + } const auto end = glengine::ScopeGuard{ []() { ImGui::DestroyContext(nullptr); diff --git a/src/opengl/experimental/test/TestBatchQuads.cpp b/src/opengl/experimental/test/TestBatchQuads.cpp index f733950b..0266c678 100644 --- a/src/opengl/experimental/test/TestBatchQuads.cpp +++ b/src/opengl/experimental/test/TestBatchQuads.cpp @@ -4,9 +4,9 @@ #include "TestBatchQuads.hpp" #include "Application.hpp" -#include "ImGuiPushID.hpp" #include #include +#include static constinit bool FitWidth = true; static constinit bool FitHeight = true; @@ -95,13 +95,13 @@ void test::TestBatchQuads::on_im_gui_update() const const float window_height = window_width / m_imgui_viewport_window.view_port_aspect_ratio(); { - const auto pop = glengine::ImGuiPushId(); + const auto pop = imgui_utils::ImGuiPushId(); ImGui::Checkbox("fit Height", &FitHeight); ImGui::Checkbox("fit Width", &FitWidth); } { - const auto pop = glengine::ImGuiPushId(); + const auto pop = imgui_utils::ImGuiPushId(); if (ImGui::SliderFloat2( "View Offset", &view_offset.x, -window_width, window_width)) { @@ -110,7 +110,7 @@ void test::TestBatchQuads::on_im_gui_update() const } } { - const auto pop_3 = glengine::ImGuiPushId(); + const auto pop_3 = imgui_utils::ImGuiPushId(); if (ImGui::SliderInt2("Quad (X, Y)", std::data(m_count), 0, 256)) { } diff --git a/src/opengl/experimental/test/TestBatchRenderer.cpp b/src/opengl/experimental/test/TestBatchRenderer.cpp index 094e845d..0db86976 100644 --- a/src/opengl/experimental/test/TestBatchRenderer.cpp +++ b/src/opengl/experimental/test/TestBatchRenderer.cpp @@ -3,7 +3,7 @@ // #include "TestBatchRenderer.hpp" #include "Application.hpp" -#include "ImGuiPushID.hpp" +#include static constinit bool FitWidth = true; static constinit bool FitHeight = true; static constinit bool Preview = false; @@ -86,13 +86,13 @@ void test::TestBatchRenderer::on_im_gui_update() const float window_height = window_width / m_imgui_viewport_window.view_port_aspect_ratio(); { - const auto pop = glengine::ImGuiPushId(); + const auto pop = imgui_utils::ImGuiPushId(); ImGui::Checkbox("fit Height", &FitHeight); ImGui::Checkbox("fit Width", &FitWidth); } { - const auto pop = glengine::ImGuiPushId(); + const auto pop = imgui_utils::ImGuiPushId(); if (ImGui::SliderFloat2( "View Offset", &view_offset.x, -window_width, window_width)) { @@ -102,7 +102,7 @@ void test::TestBatchRenderer::on_im_gui_update() const } { - const auto pop = glengine::ImGuiPushId(); + const auto pop = imgui_utils::ImGuiPushId(); if (ImGui::SliderInt2( "Quad Axis Count (X, Y)", std::data(m_count), 0, 256)) { diff --git a/src/opengl/experimental/test/TestBatchRendering.cpp b/src/opengl/experimental/test/TestBatchRendering.cpp index bde8f7fc..6e1570ed 100644 --- a/src/opengl/experimental/test/TestBatchRendering.cpp +++ b/src/opengl/experimental/test/TestBatchRendering.cpp @@ -3,8 +3,8 @@ // #include "TestBatchRendering.hpp" #include "Application.hpp" -#include "ImGuiPushID.hpp" #include +#include static constinit bool Preview = false; static_assert(glengine::Renderable); void test::TestBatchRendering::on_im_gui_update() const @@ -16,7 +16,7 @@ void test::TestBatchRendering::on_im_gui_update() const constexpr float clamp_width = window_width / 2.F - 1.F; const float clamp_height = window_height / 2.F - 1.F; { - const auto pop = glengine::ImGuiPushId(); + const auto pop = imgui_utils::ImGuiPushId(); if (ImGui::SliderFloat2( "View Offset", &view_offset.x, -clamp_width, clamp_width)) { diff --git a/src/opengl/experimental/test/TestBatchRenderingTexture2D.cpp b/src/opengl/experimental/test/TestBatchRenderingTexture2D.cpp index 2a058e52..51d480ca 100644 --- a/src/opengl/experimental/test/TestBatchRenderingTexture2D.cpp +++ b/src/opengl/experimental/test/TestBatchRenderingTexture2D.cpp @@ -3,8 +3,8 @@ // #include "TestBatchRenderingTexture2D.hpp" #include "Application.hpp" -#include "ImGuiPushID.hpp" #include +#include static constinit bool FitWidth = true; static constinit bool FitHeight = true; static constinit bool Preview = false; @@ -72,13 +72,13 @@ void test::TestBatchRenderingTexture2D::on_im_gui_update() const constexpr float clamp_width = window_width / 2.F - 1.F; const float clamp_height = window_height / 2.F - 1.F; { - const auto pop = glengine::ImGuiPushId(); + const auto pop = imgui_utils::ImGuiPushId(); ImGui::Checkbox("fit Height", &FitHeight); ImGui::Checkbox("fit Width", &FitWidth); } { - const auto pop = glengine::ImGuiPushId(); + const auto pop = imgui_utils::ImGuiPushId(); if (ImGui::SliderFloat3( "View Offset", &view_offset.x, -clamp_width, clamp_width)) { diff --git a/src/opengl/experimental/test/TestBatchRenderingTexture2DDynamic.cpp b/src/opengl/experimental/test/TestBatchRenderingTexture2DDynamic.cpp index 3861211a..d78f0d00 100644 --- a/src/opengl/experimental/test/TestBatchRenderingTexture2DDynamic.cpp +++ b/src/opengl/experimental/test/TestBatchRenderingTexture2DDynamic.cpp @@ -3,9 +3,9 @@ // #include "TestBatchRenderingTexture2DDynamic.hpp" #include "Application.hpp" -#include "ImGuiPushID.hpp" #include #include +#include static constinit bool FitWidth = true; static constinit bool FitHeight = true; static constinit bool Preview = false; @@ -68,13 +68,13 @@ void test::TestBatchRenderingTexture2DDynamic::on_im_gui_update() const const float clamp_width = window_width / 2.F - 1.F; const float clamp_height = window_height / 2.F - 1.F; { - const auto pop = glengine::ImGuiPushId(); + const auto pop = imgui_utils::ImGuiPushId(); ImGui::Checkbox("fit Height", &FitHeight); ImGui::Checkbox("fit Width", &FitWidth); } { - const auto pop = glengine::ImGuiPushId(); + const auto pop = imgui_utils::ImGuiPushId(); if (ImGui::SliderFloat2( "View Offset", &view_offset.x, -clamp_width, clamp_width)) { @@ -83,7 +83,7 @@ void test::TestBatchRenderingTexture2DDynamic::on_im_gui_update() const } } { - const auto pop_2 = glengine::ImGuiPushId(); + const auto pop_2 = imgui_utils::ImGuiPushId(); if (ImGui::SliderFloat2( "Model Offset 1", &model_offset_1.x, -clamp_width, clamp_width)) { @@ -92,7 +92,7 @@ void test::TestBatchRenderingTexture2DDynamic::on_im_gui_update() const } } { - const auto pop_3 = glengine::ImGuiPushId(); + const auto pop_3 = imgui_utils::ImGuiPushId(); if (ImGui::SliderFloat2( "Model Offset 2", &model_offset_2.x, -clamp_width, clamp_width)) { @@ -101,7 +101,7 @@ void test::TestBatchRenderingTexture2DDynamic::on_im_gui_update() const } } { - const auto pop_4 = glengine::ImGuiPushId(); + const auto pop_4 = imgui_utils::ImGuiPushId(); if (ImGui::SliderFloat2( "Model Offset 3", &model_offset_3.x, -clamp_width, clamp_width)) { diff --git a/src/opengl/experimental/test/TestTexture2D.cpp b/src/opengl/experimental/test/TestTexture2D.cpp index 2ae91d81..f808849e 100644 --- a/src/opengl/experimental/test/TestTexture2D.cpp +++ b/src/opengl/experimental/test/TestTexture2D.cpp @@ -3,10 +3,10 @@ // #include "TestTexture2D.hpp" #include "Application.hpp" -#include "ImGuiPushID.hpp" #include #include #include +#include static_assert(glengine::Renderable); static constinit bool Preview = { false }; test::TestTexture2D::TestTexture2D() @@ -44,7 +44,7 @@ void test::TestTexture2D::on_im_gui_update() const constexpr float clamp_width = window_width / 2.F - 1.F; const float clamp_height = window_height / 2.F - 1.F; { - const auto pop = glengine::ImGuiPushId(); + const auto pop = imgui_utils::ImGuiPushId(); // glfwGetFramebufferSize(window, &window_width, &window_height); if (ImGui::SliderFloat2( @@ -55,7 +55,7 @@ void test::TestTexture2D::on_im_gui_update() const } } { - const auto pop_2 = glengine::ImGuiPushId(); + const auto pop_2 = imgui_utils::ImGuiPushId(); if (ImGui::SliderFloat2( "Model Offset 1", &model_offset.x, -clamp_width, clamp_width)) { @@ -64,7 +64,7 @@ void test::TestTexture2D::on_im_gui_update() const } } { - const auto pop_3 = glengine::ImGuiPushId(); + const auto pop_3 = imgui_utils::ImGuiPushId(); if (ImGui::SliderFloat2( "Model Offset 1", &model_2_offset.x, -clamp_width, clamp_width)) { diff --git a/src/opengl/ff_8/CMakeLists.txt b/src/opengl/ff_8/CMakeLists.txt new file mode 100644 index 00000000..b158f417 --- /dev/null +++ b/src/opengl/ff_8/CMakeLists.txt @@ -0,0 +1,83 @@ +cmake_minimum_required(VERSION 3.18) +include(${CMAKE_SOURCE_DIR}/cmake/OpenVIII_CPP_WIP.cmake) +include(CheckIPOSupported) +check_ipo_supported(RESULT supported OUTPUT error) +find_package(tomlplusplus CONFIG REQUIRED) +find_package(Threads REQUIRED) +find_package(fmt REQUIRED) +find_package(spdlog REQUIRED) +add_library( + ${PROJECT_NAME}_ff_8 STATIC + ff_8/ArchivesGroup.cpp + ff_8/Configuration.cpp + ff_8/MapGroup.cpp + ff_8/MapHistory.cpp + ff_8/MapOperations.cpp + ff_8/PupuID.cpp + ff_8/SafeDir.cpp + ff_8/UniquifyPupu.cpp + ff_8/Utilities.cpp + ) + +if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + target_link_libraries(${PROJECT_NAME}_ff_8 PUBLIC stdc++exp) +endif() +target_compile_features( + ${PROJECT_NAME}_ff_8 + PUBLIC cxx_std_23 + PUBLIC cxx_std_20) +target_link_libraries( + ${PROJECT_NAME}_ff_8 + PUBLIC project_warnings + PUBLIC spdlog::spdlog + PUBLIC OpenVIII_CPP_WIP_VIIIPaths + PUBLIC OpenVIII_CPP_WIP_VIIIArchive + PUBLIC OpenVIII_CPP_WIP_VIIIGraphics + #PUBLIC tomlplusplus::tomlplusplus + PUBLIC Threads::Threads) +target_include_directories(${PROJECT_NAME}_ff_8 PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) + +if(MSVC) + target_compile_definitions(${PROJECT_NAME}_ff_8 PUBLIC _CRT_SECURE_NO_WARNINGS + )# required by libpng + target_compile_options(${PROJECT_NAME}_ff_8 + PUBLIC "/bigobj" + PUBLIC "/Qpar" + PUBLIC "/MP" + ) + # target_link_options(${PROJECT_NAME}_ff_8 PUBLIC "/PROFILE") +elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + target_compile_options(${PROJECT_NAME}_ff_8 PUBLIC "-fconcepts-diagnostics-depth=2") +elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + target_compile_options( + ${PROJECT_NAME}_ff_8 + PUBLIC "-stdlib=libc++" + # PUBLIC "-march=native" + PUBLIC "-fexperimental-library" # new in clang15 for things like std::ranges + # and std::format + ) + target_link_options( + ${PROJECT_NAME}_ff_8 + PUBLIC + "-stdlib=libc++" + # PUBLIC "-fuse-ld=lld" PUBLIC "-Wl" + PUBLIC + "-fexperimental-library" # new in clang15 for things like std::ranges and + # std::format + PUBLIC + "-v") # ,--gdb-index +endif() + +target_compile_definitions( + ${PROJECT_NAME}_ff_8 + PUBLIC NOMINMAX # imgui uses unguarded min and max. + PUBLIC TOML_EXCEPTIONS=0 + PUBLIC TOML_HEADER_ONLY=1 +) + +if(supported) + message(STATUS "IPO / LTO enabled") + set_target_properties(${PROJECT_NAME}_ff_8 PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE) +else() + message(STATUS "IPO / LTO not supported: <${error}>") +endif() diff --git a/src/opengl/main/archives_group.cpp b/src/opengl/ff_8/ff_8/ArchivesGroup.cpp similarity index 73% rename from src/opengl/main/archives_group.cpp rename to src/opengl/ff_8/ff_8/ArchivesGroup.cpp index c9833131..4b8dcec9 100644 --- a/src/opengl/main/archives_group.cpp +++ b/src/opengl/ff_8/ff_8/ArchivesGroup.cpp @@ -1,10 +1,12 @@ -#include "archives_group.hpp" +#include "ArchivesGroup.hpp" #include #include #include #include -open_viii::archive::Archives archives_group::get_archives() const +namespace ff_8 +{ +open_viii::archive::Archives ArchivesGroup::get_archives() const { // todo need a way to filter out versions of game that don't have a // language. @@ -24,11 +26,11 @@ open_viii::archive::Archives archives_group::get_archives() const m_failed = !fields(); return archives; } -const open_viii::archive::FIFLFS &archives_group::fields() const +const open_viii::archive::FIFLFS &ArchivesGroup::fields() const { return m_archives.get(); } -std::vector archives_group::get_map_list() const +std::vector ArchivesGroup::get_map_list() const { if (!m_failed) { @@ -36,7 +38,7 @@ std::vector archives_group::get_map_list() const } return {}; } -std::vector archives_group::get_map_data() const +std::vector ArchivesGroup::get_map_data() const { if (!m_failed) { @@ -45,7 +47,7 @@ std::vector archives_group::get_map_data() const return {}; } std::vector - archives_group::get_c_str(const std::vector &in_vector) + ArchivesGroup::get_c_str(const std::vector &in_vector) { std::vector ret{}; ret.reserve(in_vector.size()); @@ -56,34 +58,34 @@ std::vector return ret; } -const std::filesystem::path &archives_group::path() const noexcept +const std::filesystem::path &ArchivesGroup::path() const noexcept { return m_path; } -const open_viii::LangT &archives_group::coo() const noexcept +const open_viii::LangT &ArchivesGroup::coo() const noexcept { return m_coo; } -const open_viii::archive::Archives &archives_group::archives() const noexcept +const open_viii::archive::Archives &ArchivesGroup::archives() const noexcept { return m_archives; } -bool archives_group::failed() const noexcept +bool ArchivesGroup::failed() const noexcept { return m_failed; } const std::vector & - archives_group::map_data_from_maplist() const noexcept + ArchivesGroup::map_data_from_maplist() const noexcept { return m_maplist; } -const std::vector &archives_group::mapdata() const noexcept +const std::vector &ArchivesGroup::mapdata() const noexcept { return m_mapdata; } std::shared_ptr> - archives_group::field(const int current_map) const + ArchivesGroup::field(const int current_map) const { std::shared_ptr> archive{}; if (!m_mapdata.empty() && std::cmp_less(current_map, m_mapdata.size())) @@ -110,13 +112,13 @@ std::shared_ptr> } return archive; } -archives_group - archives_group::with_path(const std::filesystem::path &in_path) const +ArchivesGroup + ArchivesGroup::with_path(const std::filesystem::path &in_path) const { return { m_coo, in_path }; } -int archives_group::find_field(std::string_view needle) const +int ArchivesGroup::find_field(std::string_view needle) const { const auto first = m_mapdata.cbegin(); const auto last = m_mapdata.cend(); @@ -131,3 +133,4 @@ int archives_group::find_field(std::string_view needle) const } return -1; } +}// namespace ff_8 \ No newline at end of file diff --git a/src/opengl/main/archives_group.hpp b/src/opengl/ff_8/ff_8/ArchivesGroup.hpp similarity index 81% rename from src/opengl/main/archives_group.hpp rename to src/opengl/ff_8/ff_8/ArchivesGroup.hpp index 446191bc..9ee6a583 100644 --- a/src/opengl/main/archives_group.hpp +++ b/src/opengl/ff_8/ff_8/ArchivesGroup.hpp @@ -1,13 +1,13 @@ // // Created by pcvii on 9/5/2021. -// -#ifndef FIELD_MAP_EDITOR_ARCHIVES_GROUP_HPP -#define FIELD_MAP_EDITOR_ARCHIVES_GROUP_HPP -#include "map_sprite.hpp" -#include "mim_sprite.hpp" -#include "open_viii/archive/Archives.hpp" -struct archives_group +#ifndef E9C12B82_BF66_405D_B9CA_BB704F701019 +#define E9C12B82_BF66_405D_B9CA_BB704F701019 +#include "Formatters.hpp" +#include +namespace ff_8 +{ +struct ArchivesGroup { private: open_viii::LangT m_coo = {}; @@ -25,8 +25,8 @@ struct archives_group public: [[nodiscard]] static std::vector get_c_str(const std::vector &in_vector); - archives_group() = default; - [[maybe_unused]] archives_group( + ArchivesGroup() = default; + [[maybe_unused]] ArchivesGroup( const open_viii::LangT in_coo, const std::filesystem::path &in_path) : m_coo(in_coo) @@ -38,11 +38,11 @@ struct archives_group { } /** - * Creates a new archives_group pointing to the provided path. + * Creates a new ArchivesGroup pointing to the provided path. * @param in_path new path. - * @return new archives_group + * @return new ArchivesGroup */ - [[nodiscard]] archives_group + [[nodiscard]] ArchivesGroup with_path(const std::filesystem::path &in_path) const; [[maybe_unused]] [[nodiscard]] const open_viii::LangT & coo() const noexcept; @@ -62,4 +62,5 @@ struct archives_group field(int current_map) const; [[nodiscard]] int find_field(std::string_view needle) const; }; -#endif// FIELD_MAP_EDITOR_ARCHIVES_GROUP_HPP +}// namespace ff_8 +#endif /* E9C12B82_BF66_405D_B9CA_BB704F701019 */ diff --git a/src/opengl/ff_8/ff_8/Colors.hpp b/src/opengl/ff_8/ff_8/Colors.hpp new file mode 100644 index 00000000..643cff74 --- /dev/null +++ b/src/opengl/ff_8/ff_8/Colors.hpp @@ -0,0 +1,524 @@ +#ifndef B8D7F206_870F_4BEB_9A0E_17FA763286F1 +#define B8D7F206_870F_4BEB_9A0E_17FA763286F1 +#include // std::clamp +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace ff_8 +{ +// ---------------------------------------------------------------------- +// Color – the only type that lives in ff_8 +// ---------------------------------------------------------------------- +struct [[nodiscard]] Color +{ + std::uint8_t r = {}; + std::uint8_t g = {}; + std::uint8_t b = {}; + std::uint8_t a = (std::numeric_limits::max)(); + + // ----- ctors / assignment ----------------------------------------- + constexpr Color() noexcept = default; + constexpr Color(const Color &) noexcept = default; + constexpr Color(Color &&) noexcept = default; + constexpr Color &operator=(const Color &) noexcept = default; + constexpr Color &operator=(Color &&) noexcept = default; + + // ----- max / min helpers ----------------------------------------- + template + static constexpr auto max_f + = static_cast((std::numeric_limits::max)()); + template + static constexpr auto min_f + = static_cast((std::numeric_limits::min)()); + template + static constexpr auto max_i + = static_cast((std::numeric_limits::max)()); + + // ----- integral constructors -------------------------------------- + template + constexpr Color( + I in_r, + I in_g, + I in_b, + I in_a) noexcept + { +#if defined(__cpp_lib_saturation_arithmetic) \ + && __cpp_lib_saturation_arithmetic >= 202311L + r = std::saturate_cast(in_r); + g = std::saturate_cast(in_g); + b = std::saturate_cast(in_b); + a = std::saturate_cast(in_a); +#else + r = static_cast(in_r); + g = static_cast(in_g); + b = static_cast(in_b); + a = static_cast(in_a); +#endif + } + + template + constexpr Color( + I in_r, + I in_g, + I in_b) noexcept + : Color( + in_r, + in_g, + in_b, + max_i) + { + } + + // ----- floating-point constructors -------------------------------- + template + constexpr Color( + F in_r, + F in_g, + F in_b, + F in_a) noexcept + { +#if defined(__cpp_lib_saturation_arithmetic) \ + && __cpp_lib_saturation_arithmetic >= 202311L + r = std::saturate_cast(in_r * max_f); + g = std::saturate_cast(in_g * max_f); + b = std::saturate_cast(in_b * max_f); + a = std::saturate_cast(in_a * max_f); +#else + r = static_cast(in_r * max_f); + g = static_cast(in_g * max_f); + b = static_cast(in_b * max_f); + a = static_cast(in_a * max_f); +#endif + } + + template + constexpr Color( + F in_r, + F in_g, + F in_b) noexcept + : Color( + in_r, + in_g, + in_b, + F{ 1 }) + { + } + + + // ----- generic constructor --------------------------------------- + + template + requires( + requires(T v) { + v.x; + v.y; + v.z; + } ||// has x,y,z + requires(T v) { + v.r; + v.g; + v.b; + }// or has r,g,b + ) + explicit constexpr Color(const T &v) noexcept + { + if constexpr (requires { + v.x; + v.y; + v.z; + }) + { + // Try to detect float vs integer range + using value_type = std::remove_cvref_t; + if constexpr (std::floating_point) + { +#if defined(__cpp_lib_saturation_arithmetic) \ + && __cpp_lib_saturation_arithmetic >= 202311L + r = std::saturate_cast( + v.x * max_f); + g = std::saturate_cast( + v.y * max_f); + b = std::saturate_cast( + v.z * max_f); + + if constexpr (requires { v.w; }) + { + a = std::saturate_cast( + v.w * max_f); + } + else + { + a = 255; + } +#else + r = static_cast(v.x * max_f); + g = static_cast(v.y * max_f); + b = static_cast(v.z * max_f); + + if constexpr (requires { v.w; }) + { + a = static_cast(v.w * max_f); + } + else + { + a = 255; + } +#endif + } + else + { +#if defined(__cpp_lib_saturation_arithmetic) \ + && __cpp_lib_saturation_arithmetic >= 202311L + r = std::saturate_cast(v.x); + g = std::saturate_cast(v.y); + b = std::saturate_cast(v.z); + if constexpr (requires { v.w; }) + { + a = std::saturate_cast(v.w); + } + else + { + a = 255; + } +#else + r = static_cast(v.x); + g = static_cast(v.y); + b = static_cast(v.z); + + if constexpr (requires { v.w; }) + { + a = static_cast(v.w); + } + + else + { + a = 255; + } + +#endif + } + } + else if constexpr (requires { + v.r; + v.g; + v.b; + }) + { + // Try to detect float vs integer range + using value_type = std::remove_cvref_t; + if constexpr (std::floating_point) + +#if defined(__cpp_lib_saturation_arithmetic) \ + && __cpp_lib_saturation_arithmetic >= 202311L + r = std::saturate_cast( + v.r * max_f); + g = std::saturate_cast(v.g * max_f); + b = std::saturate_cast(v.b * max_f); + + if constexpr (requires { v.a; }) + { + a = std::saturate_cast( + v.a * max_f); + } + else + { + a = 255; + } +#else + r = static_cast(v.r * max_f); + g = static_cast(v.g * max_f); + b = static_cast(v.b * max_f); + + if constexpr (requires { v.a; }) + { + a = static_cast(v.a * max_f); + } + else + { + a = 255; + } +#endif + } + else + { +#if defined(__cpp_lib_saturation_arithmetic) \ + && __cpp_lib_saturation_arithmetic >= 202311L + r = std::saturate_cast(v.r); + g = std::saturate_cast(v.g); + b = std::saturate_cast(v.b); + if constexpr (requires { v.a; }) + { + a = std::saturate_cast(v.a); + } + else + { + a = 255; + } +#else + r = static_cast(v.r); + g = static_cast(v.g); + b = static_cast(v.b); + + if constexpr (requires { v.a; }) + { + a = static_cast(v.a); + } + + else + { + a = 255; + } + +#endif + } + } + + + // ----- utility ---------------------------------------------------- + [[nodiscard]] double difference(const Color &o) const + { + int dr = static_cast(r) - static_cast(o.r); + int dg = static_cast(g) - static_cast(o.g); + int db = static_cast(b) - static_cast(o.b); + int da = static_cast(a) - static_cast(o.a); + return std::sqrt(dr * dr + dg * dg + db * db + da * da); + } + + constexpr auto operator<=>(const Color &) const = default; + + [[nodiscard]] constexpr Color fade(float f) const noexcept + { + const float factor = 1.0f + f; + return { static_cast( + std::clamp(static_cast(r) * factor, 0.f, 255.f)), + static_cast( + std::clamp(static_cast(g) * factor, 0.f, 255.f)), + static_cast( + std::clamp(static_cast(b) * factor, 0.f, 255.f)), + a }; + } + + [[nodiscard]] constexpr Color fade_alpha(float f) const noexcept + { + const float factor = 1.0f + f; + return { r, g, b, + static_cast( + std::clamp(static_cast(a) * factor, 0.f, 255.f)) }; + } + + [[nodiscard]] constexpr Color opaque() const noexcept + { + return { r, g, b }; + } + + // ----- conversion to uint32_t (IM_COL32) – always available ---------- + [[nodiscard]] explicit constexpr operator std::uint32_t() const noexcept + { + return (static_cast(a) << 24) + | (static_cast(b) << 16) + | (static_cast(g) << 8) + | (static_cast(r)); + } +}; + + +// ---------------------------------------------------------------------- +// Color constants +// ---------------------------------------------------------------------- +namespace Colors +{ + static constexpr Color Red = { 255, 0, 0 }; + static constexpr Color Green = { 0, 255, 0 }; + static constexpr Color Blue = { 0, 0, 255 }; + static constexpr Color White = { 255, 255, 255 }; + static constexpr Color Black = { 0, 0, 0 }; + static constexpr Color Transparent = { 0, 0, 0, 0 }; + static constexpr Color Yellow = { 255, 255, 0 }; + static constexpr Color Cyan = { 0, 255, 255 }; + static constexpr Color Magenta = { 255, 0, 255 }; + static constexpr Color Gray = { 128, 128, 128 }; + static constexpr Color LightGray = { 192, 192, 192 }; + static constexpr Color DarkGray = { 64, 64, 64 }; + static constexpr Color Orange = { 255, 165, 0 }; + static constexpr Color Peach = { 255, 153, 102 }; + static constexpr Color Purple = { 128, 0, 128 }; + static constexpr Color Pink = { 255, 192, 203 }; + static constexpr Color Brown = { 78, 39, 5 }; + + + static constexpr auto ColorValues + = std::array{ Red, Green, Blue, White, Black, Transparent, + Yellow, Cyan, Magenta, Gray, LightGray, DarkGray, + Orange, Peach, Purple, Pink, Brown }; + + static constexpr auto ColorNames + = std::array{ + "Red", "Green", "Blue", "White", "Black", "Transparent", + "Yellow", "Cyan", "Magenta", "Gray", "LightGray", "DarkGray", + "Orange", "Peach", "Purple", "Pink", "Brown" + }; + + // (All the button / table Colors from the original file – unchanged) + + // Green tint + static constexpr Color ButtonGreen = Color{ 0.26f, 0.98f, 0.26f, 0.40f }; + static constexpr Color ButtonGreenHovered + = Color{ 0.26f, 0.98f, 0.26f, 1.00f }; + static constexpr Color ButtonGreenActive + = Color{ 0.06f, 0.53f, 0.06f, 1.00f }; + + // Red tint + static constexpr Color ButtonRed = Color{ 0.98f, 0.26f, 0.26f, 0.40f }; + static constexpr Color ButtonRedHovered + = Color{ 0.98f, 0.26f, 0.26f, 1.00f }; + static constexpr Color ButtonRedActive + = Color{ 0.53f, 0.06f, 0.06f, 1.00f }; + + // Dark Blue tint + static constexpr Color ButtonDarkBlue + = Color{ 0.26f, 0.26f, 0.59f, 0.40f }; + static constexpr Color ButtonDarkBlueHovered + = Color{ 0.26f, 0.26f, 0.59f, 1.00f }; + static constexpr Color ButtonDarkBlueActive + = Color{ 0.06f, 0.06f, 0.53f, 1.00f }; + + // Yellow tint + static constexpr Color ButtonYellow = Color{ 0.98f, 0.98f, 0.26f, 0.40f }; + static constexpr Color ButtonYellowHovered + = Color{ 0.98f, 0.98f, 0.26f, 1.00f }; + static constexpr Color ButtonYellowActive + = Color{ 0.53f, 0.53f, 0.06f, 1.00f }; + + // Orange tint + static constexpr Color ButtonOrange = Color{ 0.98f, 0.59f, 0.26f, 0.40f }; + static constexpr Color ButtonOrangeHovered + = Color{ 0.98f, 0.59f, 0.26f, 1.00f }; + static constexpr Color ButtonOrangeActive + = Color{ 0.53f, 0.26f, 0.06f, 1.00f }; + + // Pink tint + static constexpr Color ButtonPink = Color{ 0.98f, 0.26f, 0.59f, 0.40f }; + static constexpr Color ButtonPinkHovered + = Color{ 0.98f, 0.26f, 0.59f, 1.00f }; + static constexpr Color ButtonPinkActive + = Color{ 0.53f, 0.06f, 0.29f, 1.00f }; + + // Tan tint + static constexpr Color ButtonTan = Color{ 0.98f, 0.84f, 0.57f, 0.40f }; + static constexpr Color ButtonTanHovered + = Color{ 0.98f, 0.84f, 0.57f, 1.00f }; + static constexpr Color ButtonTanActive + = Color{ 0.53f, 0.48f, 0.29f, 1.00f }; + + // tableColors + static constexpr Color TableDarkRed = Color{ 120, 40, 40 }; + static constexpr Color TableLightDarkRed = Color{ 160, 60, 60 }; + static constexpr Color TableDarkRedHovered = TableLightDarkRed.fade(0.4F); + static constexpr Color TableDarkRedActive = Color{ 100, 20, 20 }; + + static constexpr Color TableDarkGray = Color{ 80, 80, 80 }; + static constexpr Color TableLightDarkGray = Color{ 100, 100, 100 }; + static constexpr Color TableDarkGrayHovered + = TableLightDarkGray.fade(0.4F); + static constexpr Color TableDarkGrayActive = Color{ 50, 50, 50 }; + + static constexpr Color TableDarkBlue = Color{ 40, 60, 120 }; + static constexpr Color TableLightDarkBlue = Color{ 60, 90, 160 }; + static constexpr Color TableDarkBlueHovered + = TableLightDarkBlue.fade(0.4F); + static constexpr Color TableDarkBlueActive = Color{ 20, 40, 100 }; + + static constexpr Color TableDarkGreen = Color{ 40, 120, 60 }; + static constexpr Color TableLightDarkGreen = Color{ 60, 160, 90 }; + static constexpr Color TableDarkGreenHovered + = TableLightDarkGreen.fade(0.4F); + static constexpr Color TableDarkGreenActive = Color{ 20, 100, 40 }; + + static constexpr Color TableDarkPurple = Color{ 80, 40, 120 }; + static constexpr Color TableLightDarkPurple = Color{ 110, 60, 160 }; + static constexpr Color TableDarkPurpleHovered + = TableLightDarkPurple.fade(0.4F); + static constexpr Color TableDarkPurpleActive = Color{ 50, 20, 100 }; + + static constexpr Color TableDarkTeal = Color{ 40, 100, 100 }; + static constexpr Color TableLightDarkTeal = Color{ 60, 140, 140 }; + static constexpr Color TableDarkTealHovered + = TableLightDarkTeal.fade(0.4F); + static constexpr Color TableDarkTealActive = Color{ 20, 80, 80 }; + + static constexpr Color TableDarkOrange = Color{ 120, 80, 40 }; + static constexpr Color TableLightDarkOrange = Color{ 160, 110, 60 }; + static constexpr Color TableDarkOrangeHovered + = TableLightDarkOrange.fade(0.4F); + static constexpr Color TableDarkOrangeActive = Color{ 100, 50, 20 }; + + + // HSV → RGB conversion (GLM-free) + [[nodiscard]] static inline std::array< + float, + 3> + HSV2RGB( + const std::array< + float, + 3> &c) + { + constexpr float Kx = 1.0f; + constexpr float Ky = 2.0f / 3.0f; + constexpr float Kz = 1.0f / 3.0f; + constexpr float Kw = 3.0f; + + auto fract = [](float x) { return x - std::floor(x); }; + auto clamp = [](float v, float lo, float hi) + { return std::max(lo, std::min(v, hi)); }; + + float px = std::fabs(fract(c[0] + Kx) * 6.0f - Kw); + float py = std::fabs(fract(c[0] + Ky) * 6.0f - Kw); + float pz = std::fabs(fract(c[0] + Kz) * 6.0f - Kw); + + float mix_x = Kx + (clamp(px - Kx, 0.0f, 1.0f) - Kx) * c[1]; + float mix_y = Kx + (clamp(py - Kx, 0.0f, 1.0f) - Kx) * c[1]; + float mix_z = Kx + (clamp(pz - Kx, 0.0f, 1.0f) - Kx) * c[1]; + + return { c[2] * mix_x, c[2] * mix_y, c[2] * mix_z }; + } + + // Final function returning ff_8::Color + [[nodiscard]] static inline ff_8::Color EncodeUintToColor(unsigned int id) + { + constexpr float GOLDEN_RATIO = 0.61803398875f; + constexpr float SATURATION = 0.8f; + constexpr float VALUE = 0.9f; + + float hue = std::fmod(static_cast(id) * GOLDEN_RATIO, 1.0f); + if (hue < 0.0f) + hue += 1.0f; + + auto temp_color = HSV2RGB({ hue, SATURATION, VALUE }); + return ff_8::Color(temp_color[0], temp_color[1], temp_color[2], 1.0f); + } +};// namespace Colors + +// ---------------------------------------------------------------------- +// BackgroundSettings – unchanged +// ---------------------------------------------------------------------- +enum class BackgroundSettings : std::uint8_t +{ + Default = 0, + OneColor = Default, + TwoColors = 1 << 0, + Checkerboard = Default, + Solid = 1 << 1, +}; + +// (All the bitwise helpers, ValidateBackgroundSettings, HasFlag, SetFlag …) +// – copy-paste from your original file, they only need the enum. +}// namespace ff_8 +#endif /* B8D7F206_870F_4BEB_9A0E_17FA763286F1 */ diff --git a/src/opengl/ff_8/ff_8/CompactTypeT.hpp b/src/opengl/ff_8/ff_8/CompactTypeT.hpp new file mode 100644 index 00000000..f7dd7a49 --- /dev/null +++ b/src/opengl/ff_8/ff_8/CompactTypeT.hpp @@ -0,0 +1,49 @@ +#ifndef F9B6101F_23D3_4195_B3F1_1697180FC40A +#define F9B6101F_23D3_4195_B3F1_1697180FC40A +#include +#include +#include +namespace ff_8 +{ +enum struct CompactTypeT : std::uint8_t +{ + rows, + all, + move_only_conflicts, + map_order, + map_order_ffnx +}; +} + +template<> +struct fmt::formatter : fmt::formatter +{// parse is inherited from formatter. + template + constexpr auto format( + ff_8::CompactTypeT in_compact_type, + FormatContext &ctx) const + { + using namespace std::string_view_literals; + std::string_view name = {}; + switch (in_compact_type) + { + case ff_8::CompactTypeT::map_order_ffnx: + name = "map order ffnx"sv; + break; + case ff_8::CompactTypeT::map_order: + name = "map order"sv; + break; + case ff_8::CompactTypeT::move_only_conflicts: + name = "move only conflicts"sv; + break; + case ff_8::CompactTypeT::rows: + name = "rows"sv; + break; + case ff_8::CompactTypeT::all: + name = "all"sv; + break; + } + return fmt::formatter::format(name, ctx); + } +}; +#endif /* F9B6101F_23D3_4195_B3F1_1697180FC40A */ diff --git a/src/opengl/main/Configuration.cpp b/src/opengl/ff_8/ff_8/Configuration.cpp similarity index 55% rename from src/opengl/main/Configuration.cpp rename to src/opengl/ff_8/ff_8/Configuration.cpp index 2ecfb525..f623c8d1 100644 --- a/src/opengl/main/Configuration.cpp +++ b/src/opengl/ff_8/ff_8/Configuration.cpp @@ -2,13 +2,12 @@ // Created by pcvii on 9/5/2022. // -#include "Configuration.hpp" -#include "safedir.hpp" -#include +#include "SafeDir.hpp" +#include #include #include -fme::Configuration::Configuration(std::filesystem::path in_path) +ff_8::Configuration::Configuration(std::filesystem::path in_path) : m_path(std::move(in_path)) , m_table( [&]() @@ -36,73 +35,43 @@ fme::Configuration::Configuration(std::filesystem::path in_path) { } -fme::Configuration::Configuration() - : fme::Configuration( - []() -> const std::filesystem::path & - { - static std::filesystem::path path;// path is cached across calls - static bool initialized = false; - - if (!initialized) - { - std::error_code error_code{}; - path = std::filesystem::current_path(error_code) / "res" - / "field-map-editor.toml"; - if (error_code) - { - spdlog::warn( - "{}:{} - {}: {} path: \"{}\"", - __FILE__, - __LINE__, - error_code.value(), - error_code.message(), - path.string()); - } - initialized = true; - } - return path; - }()) -{ -} - - -fme::Configuration::operator toml::table &() & +ff_8::Configuration::operator toml::table &() & { return *m_table; } -fme::Configuration::operator const toml::table &() const & +ff_8::Configuration::operator const toml::table &() const & { return *m_table; } -toml::table &fme::Configuration::operator*() & +toml::table &ff_8::Configuration::operator*() & { return *m_table; } -toml::table const &fme::Configuration::operator*() const & +toml::table const &ff_8::Configuration::operator*() const & { return *m_table; } -toml::table *fme::Configuration::operator->() & +toml::table *ff_8::Configuration::operator->() & { return m_table; } -const toml::table *fme::Configuration::operator->() const && +const toml::table *ff_8::Configuration::operator->() const && { return m_table; } -const toml::table *fme::Configuration::operator->() const & +const toml::table *ff_8::Configuration::operator->() const & { return m_table; } toml::node_view - fme::Configuration::operator[](std::string_view i) const + ff_8::Configuration::operator[](std::string_view i) const { return std::as_const(*m_table)[i]; } -toml::node_view fme::Configuration::operator()( +toml::node_view ff_8::Configuration::operator()( std::string_view root, std::string_view child) const { @@ -113,18 +82,17 @@ toml::node_view fme::Configuration::operator()( return root_node[child]; } -void fme::Configuration::save(const bool remove_from_cache) const +void ff_8::Configuration::save(const bool remove_from_cache) const { - const auto pop_erase = glengine::ScopeGuard( - [&]() - { - if (remove_from_cache) - { - s_tables.erase(m_path); - m_table = nullptr; - m_path = std::filesystem::path{}; - } - }); + const auto erase = [&]() + { + if (remove_from_cache) + { + s_tables.erase(m_path); + m_table = nullptr; + m_path = std::filesystem::path{}; + } + }; std::error_code error_code = {}; (void)std::filesystem::create_directories( @@ -144,13 +112,15 @@ void fme::Configuration::save(const bool remove_from_cache) const { spdlog::error( "ofstream: failed to open \"{}\" for writing", m_path.string()); + erase(); return; } fs << *m_table; spdlog::info("ofstream: saved config \"{}\"", m_path.string()); + erase(); } -bool fme::Configuration::reload() +bool ff_8::Configuration::reload() { toml::parse_result result = toml::parse_file(m_path.string()); if (!result) diff --git a/src/opengl/main/Configuration.hpp b/src/opengl/ff_8/ff_8/Configuration.hpp similarity index 85% rename from src/opengl/main/Configuration.hpp rename to src/opengl/ff_8/ff_8/Configuration.hpp index 79200695..f93fae4c 100644 --- a/src/opengl/main/Configuration.hpp +++ b/src/opengl/ff_8/ff_8/Configuration.hpp @@ -4,12 +4,15 @@ #ifndef FIELD_MAP_EDITOR_CONFIGURATION_HPP #define FIELD_MAP_EDITOR_CONFIGURATION_HPP +#ifndef DEFAULT_CONFIG_PATH +#define DEFAULT_CONFIG_PATH "res/field-map-editor.toml"// fallback, just in case +#endif #include #include #include #include #include -namespace fme +namespace ff_8 { /** * @brief Manages the configuration settings for the application, using a TOML @@ -30,8 +33,6 @@ class Configuration * `field-map-editor.toml` relative to the current working directory. */ Configuration(); - - Configuration(std::filesystem::path); operator toml::table &() &; @@ -83,8 +84,8 @@ class Configuration * `m_path`. * * @param remove_from_cache If true, the TOML table will also be removed - * from the in-memory cache after saving. This can be useful if you want to - * force a reload the next time the configuration is accessed. + * from the in-memory cache after saving. This can be useful if you want + * to force a reload the next time the configuration is accessed. */ void save(const bool remove_from_cache = false) const; @@ -109,8 +110,8 @@ class Configuration * * @note For `bool`, both TOML arrays of booleans and strings of * `'0'`/`'1'` are supported. - * @note For `std::filesystem::path`, values are expected as UTF-8 strings - * and backslashes are converted to slashes. + * @note For `std::filesystem::path`, values are expected as UTF-8 + * strings and backslashes are converted to slashes. * @note For all other types (including `std::string`), values are parsed * as `InputT` and optionally cast to `OutputT`. * @note This function requires that `InputT` is statically castable to @@ -224,11 +225,11 @@ class Configuration * casted conversion from `InputT` to `OutputT`. * * @tparam InputT The type of each element in the input vector. - * @tparam OutputT The type to be written into the TOML array. Defaults to - * `InputT`. + * @tparam OutputT The type to be written into the TOML array. Defaults + * to `InputT`. * - * @param table The TOML table where the key/value pair will be inserted or - * updated. + * @param table The TOML table where the key/value pair will be inserted + * or updated. * @param key The TOML key under which to store the array. * @param input The vector of input values to convert and write to the * configuration. @@ -313,5 +314,65 @@ class Configuration mutable toml::table *m_table = {}; }; -}// namespace fme +static inline const std::filesystem::path CURRENT_CONFIG_PATH + = []() -> const std::filesystem::path +{ + std::filesystem::path path;// path is cached across calls + + + std::error_code error_code{}; + + + try + { + path = std::filesystem::path(DEFAULT_CONFIG_PATH); + + if (path.is_relative()) + { + auto current = std::filesystem::current_path(error_code); + if (error_code) + { + spdlog::warn( + "Warning: failed to get current path: {}", + error_code.message()); + return path;// fallback to relative path + } + path = current / path; + } + path.make_preferred(); + } + catch (const std::filesystem::filesystem_error &e) + { + spdlog::error( + "Filesystem error while constructing config path: " + "{}", + e.what()); + } + catch (const std::exception &e) + { + spdlog::error( + "Unexpected error while constructing config path: " + "{}", + e.what()); + } + if (error_code) + { + spdlog::warn( + "{}:{} - {}: {} path: \"{}\"", + __FILE__, + __LINE__, + error_code.value(), + error_code.message(), + path.string()); + } + + + return path; +}(); +inline Configuration::Configuration() + : Configuration(CURRENT_CONFIG_PATH) +{ +} + +}// namespace ff_8 #endif// FIELD_MAP_EDITOR_CONFIGURATION_HPP diff --git a/src/opengl/ff_8/ff_8/DrawBitT.hpp b/src/opengl/ff_8/ff_8/DrawBitT.hpp new file mode 100644 index 00000000..9474318b --- /dev/null +++ b/src/opengl/ff_8/ff_8/DrawBitT.hpp @@ -0,0 +1,71 @@ +// +// Created by pcvii on 1/1/2025. +// + +#ifndef FIELD_MAP_EDITOR_DRAW_BIT_T_HPP +#define FIELD_MAP_EDITOR_DRAW_BIT_T_HPP +#include +#include +#include +namespace ff_8 +{ +enum struct DrawBitT +{ + all = 0, + disabled = 1, + enabled = 2, +}; + +static inline constexpr bool operator==( + DrawBitT left, + bool right) noexcept +{ + return (std::to_underlying(left) == std::to_underlying(DrawBitT::all)) + || (std::to_underlying(left) == std::to_underlying(DrawBitT::disabled) && !right) + || (std::to_underlying(left) == std::to_underlying(DrawBitT::enabled) && right); +} +static inline constexpr bool operator==( + bool left, + DrawBitT right) noexcept +{ + return operator==(right, left); +} +static inline constexpr bool operator==( + DrawBitT lhs, + DrawBitT rhs) noexcept +{ + return std::to_underlying(lhs) == std::to_underlying(DrawBitT::all) + || std::to_underlying(rhs) == std::to_underlying(DrawBitT::all) + || std::to_underlying(lhs) == std::to_underlying(rhs); +} + +};// namespace ff_8 + +template<> +struct fmt::formatter : fmt::formatter +{ + // parse is inherited from formatter. + template + constexpr auto format( + ff_8::DrawBitT draw_bit_t, + FormatContext &ctx) const + { + using namespace open_viii::graphics::background; + using namespace std::string_view_literals; + std::string_view name = {}; + switch (draw_bit_t) + { + case ff_8::DrawBitT::all: + name = "all"sv; + break; + case ff_8::DrawBitT::disabled: + name = "disabled"sv; + break; + case ff_8::DrawBitT::enabled: + name = "enabled"sv; + break; + } + return fmt::formatter::format(name, ctx); + } +}; +#endif \ No newline at end of file diff --git a/src/opengl/main/filter.hpp b/src/opengl/ff_8/ff_8/Filter.hpp similarity index 84% rename from src/opengl/main/filter.hpp rename to src/opengl/ff_8/ff_8/Filter.hpp index 29737f4e..089dc2da 100644 --- a/src/opengl/main/filter.hpp +++ b/src/opengl/ff_8/ff_8/Filter.hpp @@ -4,17 +4,18 @@ #ifndef FIELD_MAP_EDITOR_FILTER_HPP #define FIELD_MAP_EDITOR_FILTER_HPP -#include "Configuration.hpp" -#include "draw_bit_t.hpp" -#include "formatters.hpp" -#include "gui/colors.hpp" -#include "gui/compact_type.hpp" +#include "CompactTypeT.hpp" +#include "FlattenTypeT.hpp" +#include "Formatters.hpp" #include "open_viii/graphics/background/BlendModeT.hpp" #include "open_viii/graphics/BPPT.hpp" -#include "PupuID.hpp" -#include "tile_operations.hpp" -#include "utilities.hpp" #include +#include +#include +#include +#include +#include +#include #include #include #include @@ -203,13 +204,13 @@ struct ConfigKeys template<> struct ConfigKeys { - using value_type = draw_bitT; - static constexpr draw_bitT to_draw_bitT(bool in) + using value_type = DrawBitT; + static constexpr DrawBitT to_DrawBitT(bool in) { - return in ? draw_bitT::enabled : draw_bitT::disabled; + return in ? DrawBitT::enabled : DrawBitT::disabled; } using operation_type - = decltype([](auto &&...args) { return to_draw_bitT(ff_8::tile_operations::Draw{}(std::forward(args)...)); }); + = decltype([](auto &&...args) { return to_DrawBitT(ff_8::TileOperations::Draw{}(std::forward(args)...)); }); static constexpr std::string_view key_name = "filter_draw"; static constexpr std::string_view enabled_key_name = "filter_draw_enabled"; }; @@ -218,8 +219,8 @@ template<> struct ConfigKeys { using TileT = open_viii::graphics::background::Tile1; - using value_type = ff_8::tile_operations::ZT; - using operation_type = ff_8::tile_operations::Z; + using value_type = ff_8::TileOperations::Z::value_type; + using operation_type = ff_8::TileOperations::Z; static constexpr std::string_view key_name = "filter_z"; static constexpr std::string_view enabled_key_name = "filter_z_enabled"; }; @@ -228,9 +229,9 @@ struct ConfigKeys template<> struct ConfigKeys { - using TileT = open_viii::graphics::background::Tile1; - using value_type = std::vector>; - using operation_type = ff_8::tile_operations::Z; + using TileT = open_viii::graphics::background::Tile1; + using value_type = std::vector>; + using operation_type = ff_8::TileOperations::Z; static constexpr std::string_view key_name = "filter_multi_z"; static constexpr std::string_view enabled_key_name = "filter_multi_z_enabled"; @@ -240,8 +241,8 @@ template<> struct ConfigKeys { using TileT = open_viii::graphics::background::Tile1; - using value_type = ff_8::tile_operations::PaletteIdT; - using operation_type = ff_8::tile_operations::PaletteId; + using value_type = ff_8::TileOperations::PaletteId::value_type; + using operation_type = ff_8::TileOperations::PaletteId; static constexpr std::string_view key_name = "filter_palette"; static constexpr std::string_view enabled_key_name = "filter_palette_enabled"; @@ -250,9 +251,10 @@ struct ConfigKeys template<> struct ConfigKeys { - using TileT = open_viii::graphics::background::Tile1; - using value_type = std::vector>; - using operation_type = ff_8::tile_operations::PaletteId; + using TileT = open_viii::graphics::background::Tile1; + using value_type + = std::vector>; + using operation_type = ff_8::TileOperations::PaletteId; static constexpr std::string_view key_name = "filter_multi_palette"; static constexpr std::string_view enabled_key_name = "filter_multi_palette_enabled"; @@ -261,9 +263,9 @@ struct ConfigKeys template<> struct ConfigKeys { - using TileT = open_viii::graphics::background::Tile1; - using value_type = ff_8::tile_operations::AnimationIdT; - using operation_type = ff_8::tile_operations::AnimationId; + using TileT = open_viii::graphics::background::Tile1; + using value_type = ff_8::TileOperations::AnimationId::value_type; + using operation_type = ff_8::TileOperations::AnimationId; static constexpr std::string_view key_name = "filter_animation_id"; static constexpr std::string_view enabled_key_name = "filter_animation_id_enabled"; @@ -272,9 +274,10 @@ struct ConfigKeys template<> struct ConfigKeys { - using TileT = open_viii::graphics::background::Tile1; - using value_type = std::vector>; - using operation_type = ff_8::tile_operations::AnimationId; + using TileT = open_viii::graphics::background::Tile1; + using value_type + = std::vector>; + using operation_type = ff_8::TileOperations::AnimationId; static constexpr std::string_view key_name = "filter_multi_animation_id"; static constexpr std::string_view enabled_key_name = "filter_multi_animation_id_enabled"; @@ -283,9 +286,9 @@ struct ConfigKeys template<> struct ConfigKeys { - using TileT = open_viii::graphics::background::Tile1; - using value_type = ff_8::tile_operations::AnimationStateT; - using operation_type = ff_8::tile_operations::AnimationState; + using TileT = open_viii::graphics::background::Tile1; + using value_type = ff_8::TileOperations::AnimationState::value_type; + using operation_type = ff_8::TileOperations::AnimationState; static constexpr std::string_view key_name = "filter_animation_frame"; static constexpr std::string_view enabled_key_name = "filter_animation_frame_enabled"; @@ -297,8 +300,8 @@ struct ConfigKeys { using TileT = open_viii::graphics::background::Tile1; using value_type - = std::vector>; - using operation_type = ff_8::tile_operations::AnimationState; + = std::vector>; + using operation_type = ff_8::TileOperations::AnimationState; static constexpr std::string_view key_name = "filter_multi_animation_frame"; static constexpr std::string_view enabled_key_name @@ -309,8 +312,8 @@ template<> struct ConfigKeys { using TileT = open_viii::graphics::background::Tile1; - using value_type = ff_8::tile_operations::LayerIdT; - using operation_type = ff_8::tile_operations::LayerId; + using value_type = ff_8::TileOperations::LayerId::value_type; + using operation_type = ff_8::TileOperations::LayerId; static constexpr std::string_view key_name = "filter_layer_id"; static constexpr std::string_view enabled_key_name = "filter_layer_id_enabled"; @@ -320,9 +323,10 @@ struct ConfigKeys template<> struct ConfigKeys { - using TileT = open_viii::graphics::background::Tile1; - using value_type = std::vector>; - using operation_type = ff_8::tile_operations::LayerId; + using TileT = open_viii::graphics::background::Tile1; + using value_type + = std::vector>; + using operation_type = ff_8::TileOperations::LayerId; static constexpr std::string_view key_name = "filter_multi_layer_id"; static constexpr std::string_view enabled_key_name = "filter_multi_layer_id_enabled"; @@ -332,8 +336,8 @@ template<> struct ConfigKeys { using TileT = open_viii::graphics::background::Tile1; - using value_type = ff_8::tile_operations::TextureIdT; - using operation_type = ff_8::tile_operations::TextureId; + using value_type = ff_8::TileOperations::TextureId::value_type; + using operation_type = ff_8::TileOperations::TextureId; static constexpr std::string_view key_name = "filter_texture_page_id"; static constexpr std::string_view enabled_key_name = "filter_texture_page_id_enabled"; @@ -342,9 +346,10 @@ struct ConfigKeys template<> struct ConfigKeys { - using TileT = open_viii::graphics::background::Tile1; - using value_type = std::vector>; - using operation_type = ff_8::tile_operations::TextureId; + using TileT = open_viii::graphics::background::Tile1; + using value_type + = std::vector>; + using operation_type = ff_8::TileOperations::TextureId; static constexpr std::string_view key_name = "filter_multi_texture_page_id"; static constexpr std::string_view enabled_key_name @@ -355,8 +360,8 @@ template<> struct ConfigKeys { using TileT = open_viii::graphics::background::Tile1; - using value_type = ff_8::tile_operations::BlendModeT; - using operation_type = ff_8::tile_operations::BlendMode; + using value_type = ff_8::TileOperations::BlendMode::value_type; + using operation_type = ff_8::TileOperations::BlendMode; static constexpr std::string_view key_name = "filter_blend_mode"; static constexpr std::string_view enabled_key_name = "filter_blend_mode_enabled"; @@ -365,9 +370,10 @@ struct ConfigKeys template<> struct ConfigKeys { - using TileT = open_viii::graphics::background::Tile1; - using value_type = std::vector>; - using operation_type = ff_8::tile_operations::BlendMode; + using TileT = open_viii::graphics::background::Tile1; + using value_type + = std::vector>; + using operation_type = ff_8::TileOperations::BlendMode; static constexpr std::string_view enabled_key_name = "filter_multi_blend_mode_enabled"; static constexpr std::string_view key_name = "filter_multi_blend_mode"; @@ -377,8 +383,8 @@ template<> struct ConfigKeys { using TileT = open_viii::graphics::background::Tile1; - using value_type = ff_8::tile_operations::BlendT; - using operation_type = ff_8::tile_operations::Blend; + using value_type = ff_8::TileOperations::Blend::value_type; + using operation_type = ff_8::TileOperations::Blend; static constexpr std::string_view key_name = "filter_blend_other"; static constexpr std::string_view enabled_key_name = "filter_blend_other_enabled"; @@ -388,9 +394,10 @@ struct ConfigKeys template<> struct ConfigKeys { - using TileT = open_viii::graphics::background::Tile1; - using value_type = std::vector>; - using operation_type = ff_8::tile_operations::Blend; + using TileT = open_viii::graphics::background::Tile1; + using value_type + = std::vector>; + using operation_type = ff_8::TileOperations::Blend; static constexpr std::string_view key_name = "filter_multi_blend_other"; static constexpr std::string_view enabled_key_name = "filter_multi_blend_other_enabled"; @@ -400,8 +407,8 @@ template<> struct ConfigKeys { using TileT = open_viii::graphics::background::Tile1; - using value_type = ff_8::tile_operations::DepthT; - using operation_type = ff_8::tile_operations::Depth; + using value_type = ff_8::TileOperations::Depth::value_type; + using operation_type = ff_8::TileOperations::Depth; static constexpr std::string_view key_name = "filter_bpp"; static constexpr std::string_view enabled_key_name = "filter_bpp_enabled"; }; @@ -409,9 +416,10 @@ struct ConfigKeys template<> struct ConfigKeys { - using TileT = open_viii::graphics::background::Tile1; - using value_type = std::vector>; - using operation_type = ff_8::tile_operations::Depth; + using TileT = open_viii::graphics::background::Tile1; + using value_type + = std::vector>; + using operation_type = ff_8::TileOperations::Depth; static constexpr std::string_view key_name = "filter_multi_bpp"; static constexpr std::string_view enabled_key_name = "filter_multi_bpp_enabled"; @@ -420,7 +428,7 @@ struct ConfigKeys template<> struct ConfigKeys { - using value_type = fme::compact_type; + using value_type = ff_8::CompactTypeT; static constexpr std::string_view key_name = "batch_compact_type"; static constexpr std::string_view enabled_key_name = "batch_compact_enabled"; @@ -429,7 +437,7 @@ struct ConfigKeys template<> struct ConfigKeys { - using value_type = fme::flatten_type; + using value_type = FlattenTypeT; static constexpr std::string_view key_name = "batch_flatten_type"; static constexpr std::string_view enabled_key_name = "batch_flatten_enabled"; @@ -438,7 +446,7 @@ struct ConfigKeys template<> struct ConfigKeys { - using value_type = fme::compact_type; + using value_type = CompactTypeT; static constexpr std::string_view key_name = "CompactOnLoad"; static constexpr std::string_view enabled_key_name = "CompactOnLoadEnabled"; @@ -447,7 +455,7 @@ struct ConfigKeys template<> struct ConfigKeys { - using value_type = fme::flatten_type; + using value_type = ff_8::FlattenTypeT; static constexpr std::string_view key_name = "FlattenOnLoad"; static constexpr std::string_view enabled_key_name = "FlattenOnLoadEnabled"; @@ -477,9 +485,9 @@ struct FilterLoadStrategy { value = config[id].value_or(value.u8string()); } - else if constexpr (std::convertible_to) + else if constexpr (std::convertible_to) { - value = std::bit_cast( + value = std::bit_cast( config[id].value_or(std::bit_cast(value))); } else if constexpr (requires { std::declval().raw(); }) @@ -496,7 +504,7 @@ struct FilterLoadStrategy if constexpr (std::is_enum_v< glengine::vector_elem_type_t>) { - (void)fme::Configuration::load_array< + (void)ff_8::Configuration::load_array< glengine::vector_elem_type_t, std::underlying_type_t< glengine::vector_elem_type_t>>( @@ -506,7 +514,7 @@ struct FilterLoadStrategy glengine::vector_elem_type_t, open_viii::graphics::BPPT>) { - (void)fme::Configuration::load_array< + (void)ff_8::Configuration::load_array< glengine::vector_elem_type_t, std::uint8_t>(config, id, value); } @@ -514,13 +522,13 @@ struct FilterLoadStrategy glengine::vector_elem_type_t, PupuID>) { - (void)fme::Configuration::load_array< + (void)ff_8::Configuration::load_array< glengine::vector_elem_type_t, std::uint32_t>(config, id, value); } else { - (void)fme::Configuration::load_array< + (void)ff_8::Configuration::load_array< glengine::vector_elem_type_t>(config, id, value); } } @@ -574,7 +582,7 @@ struct FilterUpdateStrategy std::filesystem::path(str_val).string()); config.insert_or_assign(id, str_val); } - else if constexpr (std::convertible_to) + else if constexpr (std::convertible_to) { spdlog::debug("selection<{}>: {}", id, value); config.insert_or_assign(id, std::bit_cast(value)); @@ -594,7 +602,7 @@ struct FilterUpdateStrategy if constexpr (std::is_enum_v< glengine::vector_elem_type_t>) { - fme::Configuration::update_array< + ff_8::Configuration::update_array< glengine::vector_elem_type_t, std::underlying_type_t< glengine::vector_elem_type_t>>( @@ -604,7 +612,7 @@ struct FilterUpdateStrategy glengine::vector_elem_type_t, open_viii::graphics::BPPT>) { - fme::Configuration::update_array< + ff_8::Configuration::update_array< glengine::vector_elem_type_t, std::uint8_t>(config, id, value); } @@ -612,13 +620,13 @@ struct FilterUpdateStrategy glengine::vector_elem_type_t, PupuID>) { - fme::Configuration::update_array< + ff_8::Configuration::update_array< glengine::vector_elem_type_t, std::uint32_t>(config, id, value); } else { - fme::Configuration::update_array< + ff_8::Configuration::update_array< glengine::vector_elem_type_t>(config, id, value); } spdlog::trace("selection<{}>", id); @@ -649,7 +657,7 @@ concept HasOperationType template -struct filter +struct Filter { public: using value_type = ConfigKeys::value_type; @@ -660,17 +668,17 @@ struct filter FilterSettings m_settings = {}; public: - filter( + Filter( value_type value, FilterSettings settings)// FilterSettings::Default : m_value(std::move(value)) , m_settings(settings) { } - filter( - bool load_config, - const fme::Configuration &config) - : filter( + Filter( + bool load_config, + const ff_8::Configuration &config) + : Filter( FilterLoadStrategy::load_value( load_config, config, @@ -682,16 +690,16 @@ struct filter { } - filter(FilterSettings settings) - : filter( + Filter(FilterSettings settings) + : Filter( HasFlag( settings, FilterSettings::Config_Enabled), - fme::Configuration{}) + ff_8::Configuration{}) { } - filter &reload(const toml::table &table) + Filter &reload(const toml::table &table) { m_value = FilterLoadStrategy::load_value( table, ConfigKeys::key_name); @@ -700,17 +708,17 @@ struct filter return *this; } - filter &reload() + Filter &reload() { if (HasFlag(m_settings, FilterSettings::Config_Enabled)) { - fme::Configuration config{}; + ff_8::Configuration config{}; return reload(config); } return *this; } - filter &combine(const toml::table &table) + Filter &combine(const toml::table &table) { // Load temporary values const auto tmp_settings @@ -746,7 +754,7 @@ struct filter template - const filter &update([[maybe_unused]] U &&value) const + const Filter &update([[maybe_unused]] U &&value) const requires(std::same_as< std::remove_cvref_t, toml::table>) @@ -770,7 +778,7 @@ struct filter requires std::same_as< std::remove_cvref_t, toml::table> - filter &update(U &&value) + Filter &update(U &&value) { if (enabled()) { @@ -797,7 +805,7 @@ struct filter && std::indirectly_movable< std::ranges::iterator_t>, std::back_insert_iterator>) - filter &update(U &&value) + Filter &update(U &&value) { if (!std::ranges::equal(m_value, value)) { @@ -808,7 +816,7 @@ struct filter if (HasFlag(m_settings, FilterSettings::Config_Enabled)) { - fme::Configuration config{}; + ff_8::Configuration config{}; FilterUpdateStrategy::update_value( *config, ConfigKeys::key_name, m_value); config.save(); @@ -826,7 +834,7 @@ struct filter value_type &, U>) - filter &update(U &&value) + Filter &update(U &&value) { const bool not_same = [&]() { @@ -848,7 +856,7 @@ struct filter if (HasFlag(m_settings, FilterSettings::Config_Enabled)) { - fme::Configuration config{}; + ff_8::Configuration config{}; FilterUpdateStrategy::update_value( config, ConfigKeys::key_name, m_value); config.save(); @@ -868,7 +876,7 @@ struct filter { return HasFlag(m_settings, FilterSettings::Toggle_Enabled); } - filter &enable() + Filter &enable() { if (HasFlag(m_settings, FilterSettings::Toggle_Enabled)) { @@ -882,7 +890,7 @@ struct filter { if (HasFlag(m_settings, FilterSettings::Config_Enabled)) { - fme::Configuration config{}; + ff_8::Configuration config{}; FilterUpdateStrategy::update_settings( config, ConfigKeys::enabled_key_name, m_settings); config.save(); @@ -890,7 +898,7 @@ struct filter } return *this; } - filter &disable() + Filter &disable() { if (!HasFlag(m_settings, FilterSettings::Toggle_Enabled)) { @@ -904,7 +912,7 @@ struct filter { if (HasFlag(m_settings, FilterSettings::Config_Enabled)) { - fme::Configuration config{}; + ff_8::Configuration config{}; FilterUpdateStrategy::update_settings( config, ConfigKeys::enabled_key_name, m_settings); config.save(); @@ -944,7 +952,7 @@ struct filter }; template requires(HasOperationType) -struct filter +struct Filter { public: using value_type = ConfigKeys::value_type; @@ -957,17 +965,17 @@ struct filter static const inline operation_type s_operation = {}; public: - filter( + Filter( value_type value, FilterSettings settings)// FilterSettings::Default : m_value(std::move(value)) , m_settings(settings) { } - filter( - bool load_config, - const fme::Configuration &config) - : filter( + Filter( + bool load_config, + const ff_8::Configuration &config) + : Filter( FilterLoadStrategy::load_value( load_config, config, @@ -978,16 +986,16 @@ struct filter ConfigKeys::enabled_key_name)) { } - filter(FilterSettings settings) - : filter( + Filter(FilterSettings settings) + : Filter( HasFlag( settings, FilterSettings::Config_Enabled), - fme::Configuration{}) + ff_8::Configuration{}) { } - filter &reload(const toml::table &table) + Filter &reload(const toml::table &table) { m_value = FilterLoadStrategy::load_value( table, ConfigKeys::key_name); @@ -997,7 +1005,7 @@ struct filter } - filter &combine(const toml::table &table) + Filter &combine(const toml::table &table) { // Load temporary values const auto tmp_settings @@ -1031,17 +1039,17 @@ struct filter return *this; } - filter &reload() + Filter &reload() { if (HasFlag(m_settings, FilterSettings::Config_Enabled)) { - fme::Configuration config{}; + ff_8::Configuration config{}; return reload(config); } return *this; } template - const filter &update([[maybe_unused]] U &&value) const + const Filter &update([[maybe_unused]] U &&value) const requires(std::same_as< std::remove_cvref_t, toml::table>) @@ -1061,7 +1069,7 @@ struct filter return *this; } template - filter &update(U &&value) + Filter &update(U &&value) requires open_viii::graphics::background::is_tile< std::remove_cvref_t> { @@ -1072,7 +1080,7 @@ struct filter requires std::same_as< std::remove_cvref_t, toml::table> - filter &update(U &&value) + Filter &update(U &&value) { if (enabled()) { @@ -1099,7 +1107,7 @@ struct filter && std::indirectly_movable< std::ranges::iterator_t>, std::back_insert_iterator>) - filter &update(U &&value) + Filter &update(U &&value) { if (!std::ranges::equal(m_value, value)) { @@ -1110,7 +1118,7 @@ struct filter if (HasFlag(m_settings, FilterSettings::Config_Enabled)) { - fme::Configuration config{}; + ff_8::Configuration config{}; FilterUpdateStrategy::update_value( *config, ConfigKeys::key_name, m_value); config.save(); @@ -1128,7 +1136,7 @@ struct filter value_type &, U>) - filter &update(U &&value) + Filter &update(U &&value) { const bool not_same = [&]() { @@ -1150,7 +1158,7 @@ struct filter if (HasFlag(m_settings, FilterSettings::Config_Enabled)) { - fme::Configuration config{}; + ff_8::Configuration config{}; FilterUpdateStrategy::update_value( config, ConfigKeys::key_name, m_value); config.save(); @@ -1171,7 +1179,7 @@ struct filter { return HasFlag(m_settings, FilterSettings::Toggle_Enabled); } - filter &enable() + Filter &enable() { SetFlag(m_settings, FilterSettings::Toggle_Enabled, true); if constexpr (std::same_as< @@ -1181,7 +1189,7 @@ struct filter { if (HasFlag(m_settings, FilterSettings::Config_Enabled)) { - fme::Configuration config{}; + ff_8::Configuration config{}; FilterUpdateStrategy::update_settings( config, ConfigKeys::enabled_key_name, m_settings); config.save(); @@ -1189,7 +1197,7 @@ struct filter } return *this; } - filter &disable() + Filter &disable() { SetFlag(m_settings, FilterSettings::Toggle_Enabled, false); if constexpr (std::same_as< @@ -1199,7 +1207,7 @@ struct filter { if (HasFlag(m_settings, FilterSettings::Config_Enabled)) { - fme::Configuration config{}; + ff_8::Configuration config{}; FilterUpdateStrategy::update_settings( config, ConfigKeys::enabled_key_name, m_settings); config.save(); @@ -1286,13 +1294,13 @@ concept IsEitherFilter = IsFilterOld || IsFilter; using FilterVariant = decltype([] { return [](std::index_sequence) - -> std::variant(Is)>...> + -> std::variant(Is)>...> { return std::monostate{}; // default-constructed variant }(std::make_index_sequence(FilterTag::All)>{}); }()); -struct filters +struct Filters { using TileT = open_viii::graphics::background::Tile1; @@ -1303,30 +1311,30 @@ struct filters FiltersArrayT m_filters_array; FiltersArrayT load_filters_array( - const bool load_config, - const fme::Configuration &config) + const bool load_config, + const ff_8::Configuration &config) { FiltersArrayT result{}; - fme::for_each_enum( + ff_8::for_each_enum( [&]() { result[std::to_underlying(Key)] - = FilterVariant{ std::in_place_type>, + = FilterVariant{ std::in_place_type>, load_config, config }; }); return result; } - filters(const filters &) = default; - filters &operator=(const filters &) = default; + Filters(const Filters &) = default; + Filters &operator=(const Filters &) = default; - filters(filters &&) noexcept = default; - filters &operator=(filters &&) noexcept = default; + Filters(Filters &&) noexcept = default; + Filters &operator=(Filters &&) noexcept = default; - filters( - bool load_config, - fme::Configuration const config = {}) + Filters( + bool load_config, + ff_8::Configuration const config = {}) : m_filters_array(load_filters_array( load_config, config)) @@ -1336,7 +1344,7 @@ struct filters template requires(FiltersSizeT > static_cast(Tag)) - filter &get() + Filter &get() { static constexpr std::size_t index = static_cast(Tag); // using ValueT = typename ConfigKeys::value_type; @@ -1360,13 +1368,13 @@ struct filters } } - return std::get>(m_filters_array[index]); + return std::get>(m_filters_array[index]); } template requires(FiltersSizeT > static_cast(Tag)) - const filter &get() const + const Filter &get() const { static constexpr std::size_t index = static_cast(Tag); // using ValueT = typename ConfigKeys::value_type; @@ -1389,7 +1397,7 @@ struct filters } } - return std::get>(m_filters_array[index]); + return std::get>(m_filters_array[index]); } @@ -1418,7 +1426,7 @@ struct filters && !std::same_as< std::remove_cvref_t, toml::table>) - filter &update(TypeT &&input) + Filter &update(TypeT &&input) { return get().update(std::forward(input)); } @@ -1435,21 +1443,21 @@ struct filters template requires(FiltersSizeT > static_cast(Tag)) - filter &enable() + Filter &enable() { return get().enable(); } template requires(FiltersSizeT > static_cast(Tag)) - filter &disable() + Filter &disable() { return get().disable(); } void reload(const toml::table &table) { - fme::for_each_enum( + ff_8::for_each_enum( [&]() { using ValueT = typename ConfigKeys::value_type; @@ -1461,7 +1469,7 @@ struct filters void combine(const toml::table &table) { - fme::for_each_enum( + ff_8::for_each_enum( [&]() { using ValueT = typename ConfigKeys::value_type; @@ -1473,7 +1481,7 @@ struct filters void update_table(toml::table &table) { - fme::for_each_enum( + ff_8::for_each_enum( [&]() { using ValueT = typename ConfigKeys::value_type; @@ -1487,7 +1495,7 @@ struct filters { std::bitset(FilterTag::All)> results; - fme::for_each_enum( + ff_8::for_each_enum( [&]() { if constexpr (HasOperationType) @@ -1503,15 +1511,15 @@ struct filters return results.all(); } }; -namespace tile_operations +namespace TileOperations { template bool fail_any_filters( - const ff_8::filters &filters, + const ff_8::Filters &Filters, const tileT &tile) { - return !std::invoke(filters, tile); + return !std::invoke(Filters, tile); } -}// namespace tile_operations +}// namespace TileOperations }// namespace ff_8 #endif// FIELD_MAP_EDITOR_FILTER_HPP diff --git a/src/opengl/ff_8/ff_8/FlattenTypeT.hpp b/src/opengl/ff_8/ff_8/FlattenTypeT.hpp new file mode 100644 index 00000000..f5bcbdc1 --- /dev/null +++ b/src/opengl/ff_8/ff_8/FlattenTypeT.hpp @@ -0,0 +1,42 @@ +#ifndef A2A1F775_0956_4BD9_91AA_C281C4D68D79 +#define A2A1F775_0956_4BD9_91AA_C281C4D68D79 +#include +#include +#include +namespace ff_8 +{ +enum struct FlattenTypeT : std::uint8_t +{ + bpp, + palette, + both, +}; +} + +template<> +struct fmt::formatter : fmt::formatter +{ + // parse is inherited from formatter. + template + constexpr auto format( + ff_8::FlattenTypeT in_flatten_type, + FormatContext &ctx) const + { + using namespace std::string_view_literals; + std::string_view name = {}; + switch (in_flatten_type) + { + case ff_8::FlattenTypeT::bpp: + name = "bpp"sv; + break; + case ff_8::FlattenTypeT::palette: + name = "palette"sv; + break; + case ff_8::FlattenTypeT::both: + name = "both"sv; + break; + } + return fmt::formatter::format(name, ctx); + } +}; +#endif /* A2A1F775_0956_4BD9_91AA_C281C4D68D79 */ diff --git a/src/opengl/ff_8/ff_8/Formatters.hpp b/src/opengl/ff_8/ff_8/Formatters.hpp new file mode 100644 index 00000000..c08c37bc --- /dev/null +++ b/src/opengl/ff_8/ff_8/Formatters.hpp @@ -0,0 +1,713 @@ +#ifndef ECF4A438_F519_4336_8557_5AD27FA11B10 +#define ECF4A438_F519_4336_8557_5AD27FA11B10 + + +#include "NormalizedSourceTile.hpp" +// #include "tile_sizes.hpp" +#include "Colors.hpp" +#include "CompactTypeT.hpp" +#include "DrawBitT.hpp" +#include "FlattenTypeT.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace ff_8 +{ +template +static constexpr auto to_hex(const tileT &tile) +{ + constexpr auto to_hex_operation + = [](const std::uint8_t input_byte, const auto operation) -> char + { + constexpr std::uint8_t number_of_values_in_nibble = 16U; + constexpr char threshold_of_A_to_F = 10; + char const half_transformed_char = static_cast( + operation(input_byte, number_of_values_in_nibble)); + return static_cast( + (half_transformed_char < threshold_of_A_to_F + ? half_transformed_char + '0' + : half_transformed_char - threshold_of_A_to_F + 'A')); + }; + const auto raw_bytes + = std::bit_cast>(tile); + std::array raw_hex{}; + raw_hex.back() = '\0'; + auto rhi = raw_hex.begin(); + for (const std::uint8_t current_byte : raw_bytes) + { + *rhi = to_hex_operation(current_byte, std::divides{}); + std::advance(rhi, 1); + *rhi = to_hex_operation(current_byte, std::modulus{}); + std::advance(rhi, 1); + } + return raw_hex; +} +}// namespace ff_8 + +// template<> +// struct fmt::formatter : fmt::formatter +// { +// // tile_sizes::default_size, tile_sizes::x_2_size, tile_sizes::x_4_size, +// // tile_sizes::x_8_size, tile_sizes::x_16_size +// // parse is inherited from formatter. +// template +// constexpr auto format( +// tile_sizes tile_sizes_t, +// FormatContext &ctx) const +// { +// using namespace open_viii::graphics::background; +// using namespace std::string_view_literals; +// std::string_view name = {}; +// switch (tile_sizes_t) +// { +// case tile_sizes::default_size: +// name = "1x 16 px"sv; +// break; +// case tile_sizes::x_2_size: +// name = "2x 32 px"sv; +// break; +// case tile_sizes::x_4_size: +// name = "4x 64 px"sv; +// break; +// case tile_sizes::x_8_size: +// name = "8x 128 px"sv; +// break; +// case tile_sizes::x_16_size: +// name = "16x 256 px"sv; +// break; +// } +// return fmt::formatter::format(name, ctx); +// } +// }; + + +template<> +struct fmt::formatter + : fmt::formatter +{ + // parse is inherited from formatter. + template + constexpr auto format( + open_viii::graphics::background::BlendModeT blend_mode_t, + FormatContext &ctx) const + { + using namespace open_viii::graphics::background; + using namespace std::string_view_literals; + std::string_view name = {}; + switch (blend_mode_t) + { + case BlendModeT::add: + name = "add"sv; + break; + case BlendModeT::half_add: + name = "half add"sv; + break; + case BlendModeT::none: + name = "none"sv; + break; + case BlendModeT::quarter_add: + name = "quarter add"sv; + break; + case BlendModeT::subtract: + name = "subtract"sv; + break; + } + return fmt::formatter::format(name, ctx); + } +}; + + +// template<> +// struct fmt::formatter : fmt::formatter +// { +// // parse is inherited from formatter. +// template +// constexpr auto format( +// draw_mode draw_mode_t, +// FormatContext &ctx) const +// { +// using namespace open_viii::graphics::background; +// using namespace std::string_view_literals; +// std::string_view name = {}; +// switch (draw_mode_t) +// { +// case draw_mode::draw_mim: +// name = open_viii::graphics::background::Mim::EXT; +// break; +// case draw_mode::draw_map: +// name = open_viii::graphics::background::Map::EXT; +// break; +// } +// return fmt::formatter::format(name, ctx); +// } +// }; + +// template<> +// struct fmt::formatter : fmt::formatter +// { +// // parse is inherited from formatter. +// template +// constexpr auto format( +// fme::FailOverLevels level, +// FormatContext &ctx) const +// { +// using namespace std::string_view_literals; +// std::string_view name = {}; +// switch (level) +// { +// case fme::FailOverLevels::EN: +// name = open_viii::LangCommon::ENFULL; +// break; +// case fme::FailOverLevels::FR: +// name = open_viii::LangCommon::FRFULL; +// break; +// case fme::FailOverLevels::DE: +// name = open_viii::LangCommon::DEFULL; +// break; +// case fme::FailOverLevels::IT: +// name = open_viii::LangCommon::ITFULL; +// break; +// case fme::FailOverLevels::ES: +// name = open_viii::LangCommon::ESFULL; +// break; +// case fme::FailOverLevels::JP: +// name = open_viii::LangCommon::JPFULL; +// break; +// case fme::FailOverLevels::Generic: +// name = "Generic"sv; +// break; +// case fme::FailOverLevels::All: +// name = "All"sv; +// break; +// case fme::FailOverLevels::Loaded: +// name = "Loaded"sv; +// break; +// } +// return fmt::formatter::format(name, ctx); +// } +// }; + +template<> +struct fmt::formatter : fmt::formatter +{ + // parse is inherited from formatter. + template + constexpr auto format( + open_viii::LangT lang_t, + FormatContext &ctx) const + { + using namespace open_viii::graphics::background; + using namespace std::string_view_literals; + std::string_view name = {}; + switch (lang_t) + { + case open_viii::LangT::en: + name = open_viii::LangCommon::ENFULL; + break; + case open_viii::LangT::fr: + name = open_viii::LangCommon::FRFULL; + break; + case open_viii::LangT::de: + name = open_viii::LangCommon::DEFULL; + break; + case open_viii::LangT::it: + name = open_viii::LangCommon::ITFULL; + break; + case open_viii::LangT::es: + name = open_viii::LangCommon::ESFULL; + break; + case open_viii::LangT::jp: + name = open_viii::LangCommon::JPFULL; + break; + case open_viii::LangT::end: + case open_viii::LangT::generic: + name = "Generic"sv; + break; + } + return fmt::formatter::format(name, ctx); + } +}; + +template +struct fmt::formatter> : fmt::formatter +{ + // parse is inherited from formatter>. + template + constexpr auto format( + open_viii::graphics::Point point, + FormatContext &ctx) const + { + fmt::format_to(ctx.out(), "{}", '('); + fmt::formatter::format(point.x(), ctx); + fmt::format_to(ctx.out(), "{}", ", "); + fmt::formatter::format(point.y(), ctx); + return fmt::format_to(ctx.out(), "{}", ')'); + } +}; + +// template<> +// struct fmt::formatter +// { +// // parse is default; no custom format parsing needed +// template +// constexpr auto parse(ParseContext &ctx) +// { +// return ctx.begin(); +// } + +// template +// auto format( +// fme::BackgroundSettings bs, +// FormatContext &ctx) const +// { +// using enum fme::BackgroundSettings; + +// if (bs == Default) +// { +// return fmt::format_to( +// ctx.out(), "Default (OneColor | Checkerboard)"); +// } + +// bool first = true; + +// const auto write_part = [&](std::string_view part) +// { +// if (!first) +// fmt::format_to(ctx.out(), " | "); +// fmt::format_to(ctx.out(), "{}", part); +// first = false; +// }; + +// if (HasFlag(bs, TwoColors)) +// write_part("TwoColors"); +// else +// write_part("OneColor"); + +// if (HasFlag(bs, Solid)) +// write_part("Solid"); +// else +// write_part("Checkerboard"); + +// return ctx.out(); +// } +// }; + +template +struct fmt::formatter> + : fmt::formatter> +{ + // parse is inherited from formatter>. + template + constexpr auto format( + open_viii::graphics::Rectangle rectangle, + FormatContext &ctx) const + { + fmt::formatter>::format( + open_viii::graphics::Point{ rectangle.x(), rectangle.y() }, + ctx); + fmt::format_to(ctx.out(), "{}", ' '); + return fmt::formatter>::format( + open_viii::graphics::Point{ rectangle.width(), + rectangle.height() }, + ctx); + } +}; + +template<> +struct fmt::formatter : fmt::formatter +{ + // parse is inherited from formatter. + template + constexpr auto format( + open_viii::graphics::BPPT bppt, + FormatContext &ctx) const + { + using namespace open_viii::graphics; + using namespace std::string_view_literals; + + if (bppt.bpp8()) + { + return fmt::formatter::format(BPPT::BPP8, ctx); + } + if (bppt.bpp16()) + { + return fmt::formatter::format(BPPT::BPP16, ctx); + } + if (bppt.bpp24()) + { + return fmt::formatter::format(BPPT::BPP24, ctx); + } + return fmt::formatter::format(BPPT::BPP4, ctx); + } +}; + + +template +struct fmt::formatter : fmt::formatter +{ + // parse is inherited from formatter. + template + constexpr auto format( + const tileT &tile, + FormatContext &ctx) const + { + using namespace std::string_view_literals; + const auto array = ff_8::to_hex(tile); + const auto hexview = std::string_view(array.data(), array.size() - 1); + return fmt::format_to( + ctx.out(), + "{}: {}\n" + "{}: {}\n" + "{}: {}\n" + "{}: {}\n" + "{}: {}\n" + "{}: {}\n" + "{}: {}\n" + "{}: {}\n" + "{}: {}\n" + "{}: {}\n" + "{}: {}\n" + "{}: {}\n" + "{}: {}", + "Hex"sv, + hexview, + "Source"sv, + tile.source_rectangle(), + "Destination"sv, + tile.output_rectangle(), + "Z"sv, + tile.z(), + "BPP"sv, + tile.depth(), + "Palette"sv, + tile.palette_id(), + "Texture Page"sv, + tile.texture_id(), + "Layer ID"sv, + tile.layer_id(), + "Blend Mode"sv, + tile.blend_mode(), + "Blend Other"sv, + tile.blend(), + "Animation ID"sv, + tile.animation_id(), + "Animation State"sv, + tile.animation_state(), + "Draw"sv, + tile.draw()); + } +}; + +template<> +struct fmt::formatter + : fmt::formatter +{ + // parse is inherited from formatter. + template + constexpr auto format( + const open_viii::graphics::background::NormalizedSourceTile &tile, + FormatContext &ctx) const + { + using namespace std::string_view_literals; + const auto array = ff_8::to_hex(tile); + const auto hexview = std::string_view(array.data(), array.size() - 1); + return fmt::format_to( + ctx.out(), + "{}: {}\n" + "{}: {}\n" + "{}: {}\n" + "{}: {}\n" + "{}: {}\n" + "{}: {}\n" + "{}: {}\n" + "{}: {}\n" + "{}: {}\n" + "{}: {}\n" + "{}: {}\n" + "{}: {}", + "Hex"sv, + hexview, + "Source"sv, + tile.m_source_xy, + "BPP"sv, + tile.m_tex_id_buffer.depth(), + "Palette"sv, + tile.m_palette_id.id(), + "Texture Page"sv, + tile.m_tex_id_buffer.id(), + "Layer ID"sv, + tile.m_layer_id.id(), + "Blend Mode"sv, + tile.m_blend_mode, + "Blend Other"sv, + tile.m_tex_id_buffer.blend(), + "Animation ID"sv, + tile.m_animation_id, + "Animation State"sv, + tile.m_animation_state, + "Draw"sv, + tile.m_tex_id_buffer.draw); + } +}; + +template +concept tile_range = std::ranges::range + && open_viii::graphics::background::is_tile< + std::ranges::range_value_t>; + +template +struct fmt::is_range : std::false_type +{ +}; + + +// Specialization for ranges of tiles +template +struct fmt::formatter : fmt::formatter +{ + // parse is inherited from formatter. + template + constexpr auto format( + const TileRange &tiles, + FormatContext &ctx) const + { + const auto count = std::ranges::distance(tiles); + + + return fmt::format_to(ctx.out(), "Total Tiles: {}\n", count); + } +}; + +template<> +struct fmt::formatter +{ + // Parses format specs; in this case, we don't support any custom + // formatting + constexpr auto parse(format_parse_context &ctx) + { + return ctx.begin();// no custom formatting, so just return the end + } + + // Formats the color as "(r,g,b,a)" + template + auto format( + const ff_8::Color &c, + FormatContext &ctx) const + { + return fmt::format_to( + ctx.out(), "({:>3},{:>3},{:>3},{:>3})", c.r, c.g, c.b, c.a); + } +}; + +// template<> +// struct fmt::formatter : +// fmt::formatter +// { +// // parse is inherited from formatter. +// template +// constexpr auto format( +// fme::root_path_types in_root_path_types, +// FormatContext &ctx) const +// { +// using namespace std::string_view_literals; +// std::string_view name = {}; +// switch (in_root_path_types) +// { +// case fme::root_path_types::selected_path: +// name = fme::gui_labels::selected_path; +// break; +// case fme::root_path_types::ff8_path: +// name = fme::gui_labels::ff8_path; +// break; +// case fme::root_path_types::current_path: +// name = fme::gui_labels::current_path; +// break; +// } +// return fmt::formatter::format(name, ctx); +// } +// }; + +// template<> +// struct fmt::formatter : +// fmt::formatter +// { +// // parse is inherited from formatter. +// template +// constexpr auto format( +// fme::PatternSelector pattern_selector, +// FormatContext &ctx) const +// { +// using namespace std::string_view_literals; +// std::string_view name = {}; +// switch (pattern_selector) +// { +// case fme::PatternSelector::OutputSwizzlePattern: +// name = "Output swizzle pattern"sv; +// break; +// case fme::PatternSelector::OutputSwizzleAsOneImagePattern: +// name = "Output Swizzle as One Image Pattern"sv; +// break; +// case fme::PatternSelector::OutputDeswizzlePattern: +// name = "Output deswizzle pattern"sv; +// break; +// case fme::PatternSelector::OutputFullFileNamePattern: +// name = "Output Full Filename Pattern (.toml)"sv; +// break; +// case fme::PatternSelector::OutputTomlPattern: +// name = "Output '.toml' Pattern"sv; +// break; +// case fme::PatternSelector::OutputMapPatternForSwizzle: +// name = "Output map pattern for swizzle"sv; +// break; +// case fme::PatternSelector::OutputMapPatternForDeswizzle: +// name = "Output map pattern for deswizzle"sv; +// break; +// case fme::PatternSelector::OutputMapPatternForFullFileName: +// name = "Output map pattern for Full Filename (.toml)"sv; +// break; +// case fme::PatternSelector::PatternsCommonPrefixes: +// name = "Path Patterns Common Swizzle"sv; +// break; +// case fme::PatternSelector::PatternsCommonPrefixesForMaps: +// name = "Path Patterns Common Swizzle For Maps"sv; +// break; +// case fme::PatternSelector::PatternsBase: +// name = "Path Patterns No Palette And Texture Page"sv; +// break; +// case +// fme::PatternSelector::PathPatternsWithPaletteAndTexturePage: +// name = "Path Patterns With Palette And Texture Page"sv; +// break; +// case fme::PatternSelector::PathPatternsWithPalette: +// name = "Path Patterns With Palette"sv; +// break; +// case fme::PatternSelector::PathPatternsWithTexturePage: +// name = "Path Patterns With Texture Page"sv; +// break; +// case fme::PatternSelector::PathPatternsWithPupuID: +// name = "Path Patterns With PupuID"sv; +// break; +// case fme::PatternSelector::PathPatternsWithFullFileName: +// name = "Path Patterns With Full Filename (.toml)"sv; +// break; +// case fme::PatternSelector::End: +// name = "End"; +// break; +// } +// return fmt::formatter::format(name, ctx); +// } +// }; + + +// template<> +// struct fmt::formatter : fmt::formatter +// { +// // parse is inherited from formatter. +// template +// constexpr auto format( +// fme::input_types in_input_type, +// FormatContext &ctx) const +// { +// using namespace std::string_view_literals; +// std::string_view name = {}; +// switch (in_input_type) +// { +// case fme::input_types::mim: +// name = fme::gui_labels::mim; +// break; +// case fme::input_types::deswizzle: +// name = fme::gui_labels::deswizzle; +// break; +// case fme::input_types::swizzle: +// name = fme::gui_labels::swizzle; +// break; +// case fme::input_types::swizzle_as_one_image: +// name = fme::gui_labels::swizzle_as_one_image; +// break; +// // case fme::input_types::deswizzle_generate_toml: +// // name = fme::gui_labels::deswizzle_generate_toml; +// // break; +// case fme::input_types::deswizzle_full_filename: +// name = fme::gui_labels::deswizzle_full_filename_input; +// break; +// } +// return fmt::formatter::format(name, ctx); +// } +// }; + +// template<> +// struct fmt::formatter : +// fmt::formatter +// { +// // parse is inherited from formatter. +// template +// constexpr auto format( +// fme::input_map_types in_input_type, +// FormatContext &ctx) const +// { +// using namespace std::string_view_literals; +// std::string_view name = {}; +// switch (in_input_type) +// { +// case fme::input_map_types::native: +// name = fme::gui_labels::input_map_short_strings +// [std::to_underlying(fme::input_map_types::native)]; +// break; +// case fme::input_map_types::loaded_same_input_path: +// name = fme::gui_labels::input_map_short_strings +// [std::to_underlying( +// fme::input_map_types::loaded_same_input_path)]; +// break; +// case fme::input_map_types::loaded_different_input_path: +// name = fme::gui_labels::input_map_short_strings +// [std::to_underlying( +// fme::input_map_types::loaded_different_input_path)]; +// break; +// } +// return fmt::formatter::format(name, ctx); +// } +// }; + +// template<> +// struct fmt::formatter : fmt::formatter +// {// parse is inherited from formatter. +// template +// constexpr auto format( +// fme::output_types in_output_type, +// FormatContext &ctx) const +// { +// using namespace std::string_view_literals; +// std::string_view name = {}; +// switch (in_output_type) +// { +// case fme::output_types::deswizzle: +// name = fme::gui_labels::deswizzle; +// break; +// case fme::output_types::swizzle: +// name = fme::gui_labels::swizzle; +// break; +// case fme::output_types::swizzle_as_one_image: +// name = fme::gui_labels::swizzle_as_one_image; +// break; +// case fme::output_types::deswizzle_generate_toml: +// name = fme::gui_labels::deswizzle_generate_toml; +// break; +// case fme::output_types::deswizzle_full_filename: +// name = fme::gui_labels::deswizzle_full_filename; +// break; +// case fme::output_types::csv: +// name = ".csv"; +// break; +// } +// return fmt::formatter::format(name, ctx); +// } +// }; + +#endif /* ECF4A438_F519_4336_8557_5AD27FA11B10 */ diff --git a/src/opengl/main/map_group.cpp b/src/opengl/ff_8/ff_8/MapGroup.cpp similarity index 66% rename from src/opengl/main/map_group.cpp rename to src/opengl/ff_8/ff_8/MapGroup.cpp index 71d47763..344c775e 100644 --- a/src/opengl/main/map_group.cpp +++ b/src/opengl/ff_8/ff_8/MapGroup.cpp @@ -2,7 +2,7 @@ // Created by pcvii on 2/28/2023. // -#include "map_group.hpp" +#include "MapGroup.hpp" #include "open_viii/strings/LangCommon.hpp" #include static std::string str_to_lower(std::string input) @@ -19,9 +19,9 @@ static std::string str_to_lower(std::string input) namespace ff_8 { -static map_group::Mim load_mim( - const map_group::WeakField &weak_field, - const map_group::Coo coo) +static MapGroup::Mim load_mim( + const MapGroup::WeakField &weak_field, + const MapGroup::Coo coo) { const auto field = weak_field.lock(); if (!field) @@ -30,7 +30,7 @@ static map_group::Mim load_mim( return {}; } auto lang_name = fmt::format( - "_{}{}", open_viii::LangCommon::to_string(coo), map_group::Mim::EXT); + "_{}{}", open_viii::LangCommon::to_string(coo), MapGroup::Mim::EXT); auto long_lang_name = fmt::format( "{}_{}{}", field->get_base_name(), @@ -42,15 +42,15 @@ static map_group::Mim load_mim( open_viii::graphics::background::Mim::EXT); return { field->get_entry_data( { std::string_view(long_lang_name), std::string_view(long_name), - std::string_view(lang_name), map_group::Mim::EXT }), + std::string_view(lang_name), MapGroup::Mim::EXT }), str_to_lower(std::string{ field->get_base_name() }) }; } -static map_group::MapHistory load_map_history( - const map_group::WeakField &weak_field, - std::optional &coo, - const map_group::SharedMim &mim, - std::string *out_path, - bool shift = true) +static MapGroup::MapHistory load_map_history( + const MapGroup::WeakField &weak_field, + std::optional &coo, + const MapGroup::SharedMim &mim, + std::string *out_path, + bool shift = true) { const auto field = weak_field.lock(); if (!field) @@ -58,14 +58,14 @@ static map_group::MapHistory load_map_history( spdlog::error("Failed to lock weak_field: shared_ptr is expired."); return {}; } - return map_group::MapHistory{ load_map(field, coo, mim, out_path, shift) }; + return MapGroup::MapHistory{ load_map(field, coo, mim, out_path, shift) }; } -map_group::Map load_map( - const map_group::WeakField &weak_field, - std::optional &coo, - const map_group::SharedMim &mim, - std::string *out_path, - bool shift) +MapGroup::Map load_map( + const MapGroup::WeakField &weak_field, + std::optional &coo, + const MapGroup::SharedMim &mim, + std::string *out_path, + bool shift) { const auto field = weak_field.lock(); if (!field) @@ -75,11 +75,11 @@ map_group::Map load_map( } if (!coo) { - coo = map_group::Coo::generic; + coo = MapGroup::Coo::generic; } size_t out_path_pos = {}; auto lang_name = fmt::format( - "_{}{}", open_viii::LangCommon::to_string(*coo), map_group::Map::EXT); + "_{}{}", open_viii::LangCommon::to_string(*coo), MapGroup::Map::EXT); auto long_lang_name = fmt::format( "{}_{}{}", field->get_base_name(), @@ -89,11 +89,11 @@ map_group::Map load_map( "{}{}", field->get_base_name(), open_viii::graphics::background::Map::EXT); - auto map = map_group::Map{ + auto map = MapGroup::Map{ mim->mim_type(), field->get_entry_data( { std::string_view(long_lang_name), std::string_view(long_name), - std::string_view(lang_name), map_group::Map::EXT }, + std::string_view(lang_name), MapGroup::Map::EXT }, out_path, &out_path_pos), shift @@ -104,13 +104,13 @@ map_group::Map load_map( } return map; } -map_group::map_group( - map_group::WeakField in_field, - map_group::OptCoo in_coo = std::nullopt) +MapGroup::MapGroup( + MapGroup::WeakField in_field, + MapGroup::OptCoo in_coo = std::nullopt) : field{ std::move(in_field) } , mim{ std::make_shared(load_mim( field, - in_coo ? *in_coo : map_group::Coo::generic)) } + in_coo ? *in_coo : MapGroup::Coo::generic)) } , map_path{} , opt_coo{ in_coo } , maps{ load_map_history( diff --git a/src/opengl/main/map_group.hpp b/src/opengl/ff_8/ff_8/MapGroup.hpp similarity index 81% rename from src/opengl/main/map_group.hpp rename to src/opengl/ff_8/ff_8/MapGroup.hpp index 2ace5f1c..bcd30b2c 100644 --- a/src/opengl/main/map_group.hpp +++ b/src/opengl/ff_8/ff_8/MapGroup.hpp @@ -12,7 +12,7 @@ #include namespace ff_8 { -struct map_group +struct MapGroup { // required to initialize using Field = open_viii::archive::FIFLFS; @@ -26,8 +26,8 @@ struct map_group using Coo = open_viii::LangT; using OptCoo = std::optional; static constexpr auto TILE_SIZE = 16U; - map_group() = default; - map_group( + MapGroup() = default; + MapGroup( WeakField, OptCoo); WeakField field{}; @@ -37,11 +37,11 @@ struct map_group OptCoo opt_coo{}; MapHistory maps{}; }; -map_group::Map load_map( - const map_group::WeakField &field, - std::optional &coo, - const map_group::SharedMim &mim, - std::string *out_path, - bool shift); +MapGroup::Map load_map( + const MapGroup::WeakField &field, + std::optional &coo, + const MapGroup::SharedMim &mim, + std::string *out_path, + bool shift); }// namespace ff_8 #endif// FIELD_MAP_EDITOR_MAP_GROUP_HPP diff --git a/src/opengl/main/MapHistory.cpp b/src/opengl/ff_8/ff_8/MapHistory.cpp similarity index 93% rename from src/opengl/main/MapHistory.cpp rename to src/opengl/ff_8/ff_8/MapHistory.cpp index 881bcd92..9cc964c8 100644 --- a/src/opengl/main/MapHistory.cpp +++ b/src/opengl/ff_8/ff_8/MapHistory.cpp @@ -3,7 +3,6 @@ // #include "MapHistory.hpp" -#include "gui/colors.hpp" using namespace open_viii::graphics::background; using map_t = Map; @@ -36,7 +35,7 @@ namespace ff_8 * * The `PupuID` is designed to wrap around the unsigned 64-bit integer, allowing * you to reverse the ID back to the original values, much like - * `source_tile_conflicts` handles the swizzle or input locations. + * `SourceTileConflicts` handles the swizzle or input locations. * * The generated `PupuID`s can be used to: * - Dump unswizzled images with unique filenames containing the raw hex value @@ -105,19 +104,19 @@ static std::vector make_unique_pupu(const std::vector &input) * * This function identifies and tracks conflicts between tiles in the provided * map. A conflict is defined as multiple tiles occupying the same grid - * location. The result is a `source_tile_conflicts` object, which stores + * location. The result is a `SourceTileConflicts` object, which stores * information about conflicting tiles and their locations. * * @param map The map containing the tiles to process. - * @return A `source_tile_conflicts` object representing the tile conflicts in + * @return A `SourceTileConflicts` object representing the tile conflicts in * the map. */ -[[nodiscard]] static source_tile_conflicts calculate_conflicts(const map_t &map) +[[nodiscard]] static SourceTileConflicts calculate_conflicts(const map_t &map) { return map.visit_tiles( [](const auto &tiles) { - source_tile_conflicts stc{}; + SourceTileConflicts stc{}; std::ranges::for_each( tiles | Map::filter_view_invalid(), [&](const auto &tile) @@ -149,7 +148,7 @@ static std::vector make_unique_pupu(const std::vector &input) * counted. The range can be any iterable sequence of indices that corresponds * to the tiles within the map. * - * @return A map of `normalized_source_tile` to `std::uint8_t` where the key is + * @return A map of `NormalizedSourceTile` to `std::uint8_t` where the key is * the normalized tile and the value is the count of its occurrences within the * specified range of tile indices. * @@ -158,7 +157,7 @@ static std::vector make_unique_pupu(const std::vector &input) * given range. */ [[nodiscard]] static std::map< - normalized_source_tile, + NormalizedSourceTile, std::uint8_t> populate_similar_tile_count( const map_t &map, @@ -168,7 +167,7 @@ static std::vector make_unique_pupu(const std::vector &input) return map.visit_tiles( [&](const auto &tiles) { - std::map ret = {}; + std::map ret = {}; const auto to_tile = [&](const auto index) { assert( @@ -195,7 +194,7 @@ static std::vector make_unique_pupu(const std::vector &input) * * This function processes a range of tile indices within the map and counts the * frequency of normalized animated tiles. The result is a map where each key is - * a `normalized_source_animated_tile`, and the corresponding value represents + * a `NormalizedSourceAnimatedTile`, and the corresponding value represents * the count of its occurrences in the specified range. * * This function is useful for identifying frequently used animated tiles within @@ -207,7 +206,7 @@ static std::vector make_unique_pupu(const std::vector &input) * to be counted. The range can be any iterable sequence of indices * corresponding to tiles in the map. * - * @return A map of `normalized_source_animated_tile` to `std::uint8_t` where + * @return A map of `NormalizedSourceAnimatedTile` to `std::uint8_t` where * the key is the normalized animated tile and the value is the count of its * occurrences within the specified range of tile indices. * @@ -216,7 +215,7 @@ static std::vector make_unique_pupu(const std::vector &input) * indices into tiles and count their occurrences. */ [[nodiscard]] static std::map< - normalized_source_animated_tile, + NormalizedSourceAnimatedTile, std::uint8_t> populate_animation_tile_count( const map_t &map, @@ -226,7 +225,7 @@ static std::vector make_unique_pupu(const std::vector &input) return map.visit_tiles( [&](const auto &tiles) { - std::map ret = {}; + std::map ret = {}; const auto to_tile = [&](const auto index) { assert( @@ -261,11 +260,11 @@ static std::vector make_unique_pupu(const std::vector &input) // counts. // * @return A map of normalized source animated tiles to their total counts. // */ -// [[nodiscard]] static std::map +// [[nodiscard]] static std::map // populate_animation_tile_count(const ff_8::MapHistory::nst_map // &similar_tiles) // { -// std::map ret = {}; +// std::map ret = {}; // for (const auto &[tile, count] : similar_tiles) // { // ret[tile] += count; @@ -332,13 +331,13 @@ static void disambiguate_normalized_tiles( } -static std::vector create_colors_from_indexes(std::size_t count) +static std::vector create_colors_from_indexes(std::size_t count) { return std::views::iota(0u, static_cast(count)) | std::views::transform( [&](const auto index) { - return fme::colors::encode_uint_to_rgba( + return ff_8::Colors::EncodeUintToColor( static_cast(index)); }) | std::ranges::to(); @@ -458,26 +457,26 @@ const std::vector & } -const std::vector & +const std::vector & ff_8::MapHistory::original_unique_pupu_color() const noexcept { return m_original_unique_pupu_color; } -const std::vector & +const std::vector & ff_8::MapHistory::working_unique_pupu_color() const noexcept { return m_working_unique_pupu_color; } -const ff_8::source_tile_conflicts & +const ff_8::SourceTileConflicts & ff_8::MapHistory::original_conflicts() const noexcept { return m_original_conflicts; } -const ff_8::source_tile_conflicts & +const ff_8::SourceTileConflicts & ff_8::MapHistory::working_conflicts() const noexcept { return m_working_conflicts; @@ -532,7 +531,7 @@ map_t &ff_8::MapHistory::copy_original(std::string description) { return original_mutable(); } - (void)debug_count_print(); + // (void)debug_count_print(); clear_redo(); m_undo_original_or_working.push_back(pushed::original); m_undo_history.push_back(original()); @@ -547,7 +546,7 @@ map_t &ff_8::MapHistory::copy_working(std::string description) { return working(); } - (void)debug_count_print(); + // (void)debug_count_print(); clear_redo(); m_undo_original_or_working.push_back(pushed::working); m_undo_history.push_back(working()); @@ -560,10 +559,9 @@ map_t &ff_8::MapHistory::begin_multi_frame_working(std::string description) { if (!m_in_multi_frame_operation) { - const auto pop_set - = glengine::ScopeGuard{ [this] - { m_in_multi_frame_operation = true; } }; - return copy_working(std::move(description)); + map_t &temp = copy_working(std::move(description)); + m_in_multi_frame_operation = true; + return temp; } return working(); } @@ -603,7 +601,7 @@ bool ff_8::MapHistory::remove_duplicate() const map_t &ff_8::MapHistory::first_to_original(std::string description) { - (void)debug_count_print(); + // (void)debug_count_print(); clear_redo(); m_undo_history.push_back(original()); m_undo_original_or_working.push_back(pushed::original); @@ -615,7 +613,7 @@ const map_t &ff_8::MapHistory::first_to_original(std::string description) const map_t &ff_8::MapHistory::first_to_working(std::string description) { - (void)debug_count_print(); + // (void)debug_count_print(); clear_redo(); m_undo_history.push_back(working()); m_undo_original_or_working.push_back(pushed::working); @@ -627,7 +625,7 @@ const map_t &ff_8::MapHistory::first_to_working(std::string description) const map_t &ff_8::MapHistory::copy_working_to_original(std::string description) { - (void)debug_count_print(); + // (void)debug_count_print(); clear_redo(); m_undo_history.push_back(original()); m_undo_original_or_working.push_back(pushed::original); @@ -640,7 +638,7 @@ const map_t &ff_8::MapHistory::copy_working_to_original(std::string description) bool ff_8::MapHistory::redo() { - const auto count = debug_count_print(); + // const auto count = debug_count_print(); if (!redo_enabled()) { return false; @@ -669,7 +667,7 @@ bool ff_8::MapHistory::redo() bool ff_8::MapHistory::undo(bool skip_redo) { - const auto count = debug_count_print(); + // const auto count = debug_count_print(); if (!undo_enabled()) { return false; diff --git a/src/opengl/main/MapHistory.hpp b/src/opengl/ff_8/ff_8/MapHistory.hpp similarity index 90% rename from src/opengl/main/MapHistory.hpp rename to src/opengl/ff_8/ff_8/MapHistory.hpp index c207fbcc..9896725b 100644 --- a/src/opengl/main/MapHistory.hpp +++ b/src/opengl/ff_8/ff_8/MapHistory.hpp @@ -4,12 +4,11 @@ #ifndef FIELD_MAP_EDITOR_MAPHISTORY_HPP #define FIELD_MAP_EDITOR_MAPHISTORY_HPP -#include "normalized_source_tile.hpp" +#include "Colors.hpp" +#include "NormalizedSourceTile.hpp" #include "PupuID.hpp" -#include "source_tile_conflicts.hpp" +#include "SourceTileConflicts.hpp" #include "UniquifyPupu.hpp" -#include -#include #include #include #include @@ -50,11 +49,10 @@ class [[nodiscard]] MapHistory * @brief Alias for the `Map` type from `open_viii::graphics::background`. */ using map_t = open_viii::graphics::background::Map; - using nst_map = std::map< - open_viii::graphics::background::normalized_source_tile, - std::uint8_t>; + using nst_map = std:: + map; using nsat_map = std::map< - open_viii::graphics::background::normalized_source_animated_tile, + open_viii::graphics::background::NormalizedSourceAnimatedTile, std::uint8_t>; private: @@ -66,7 +64,7 @@ class [[nodiscard]] MapHistory * until `end_multi_frame_working` is called, which sets it back to * `false`. */ - mutable bool m_in_multi_frame_operation = { false }; + mutable bool m_in_multi_frame_operation = { false }; /** * @brief Indicates whether the original state has been changed. * @@ -79,7 +77,7 @@ class [[nodiscard]] MapHistory * @note This flag is used to track modifications to the original tile * data. */ - mutable bool m_original_changed = { false }; + mutable bool m_original_changed = { false }; /** * @brief Indicates whether the working state has been changed. @@ -92,67 +90,67 @@ class [[nodiscard]] MapHistory * * @note This flag is used to track modifications to the working tile data. */ - mutable bool m_working_changed = { false }; + mutable bool m_working_changed = { false }; // Current states /** * @brief The active original map state. */ - map_t m_original = {}; + map_t m_original = {}; /** * @brief The active working map state. */ - map_t m_working = {}; + map_t m_working = {}; // Corresponding PupuIDs /** * @brief PupuID list corresponding to the original map state. */ - mutable std::vector m_original_pupu = {}; + mutable std::vector m_original_pupu = {}; /** * @brief PupuID list corresponding to the working map state. */ - mutable std::vector m_working_pupu = {}; + mutable std::vector m_working_pupu = {}; // Corresponding PupuIDs /** * @brief Unique PupuID list corresponding to the original map state. */ - mutable std::vector m_original_unique_pupu = {}; + mutable std::vector m_original_unique_pupu = {}; /** * @brief Unique PupuID list corresponding to the working map state. */ - mutable std::vector m_working_unique_pupu = {}; + mutable std::vector m_working_unique_pupu = {}; /** * @brief Unique PupuID color list corresponding to the original map state. */ - mutable std::vector m_original_unique_pupu_color = {}; + mutable std::vector m_original_unique_pupu_color = {}; /** * @brief Unique PupuID color list corresponding to the working map state. */ - mutable std::vector m_working_unique_pupu_color = {}; + mutable std::vector m_working_unique_pupu_color = {}; // Corresponding Source Conflicts /** * @brief Source Conflict list corresponding to the original map state. */ - mutable source_tile_conflicts m_original_conflicts = {}; + mutable SourceTileConflicts m_original_conflicts = {}; /** * @brief Source Conflict list corresponding to the working map state. */ - mutable source_tile_conflicts m_working_conflicts = {}; + mutable SourceTileConflicts m_working_conflicts = {}; /** @@ -162,67 +160,69 @@ class [[nodiscard]] MapHistory * one location. Mostly just to high light it differently. Or provide a * user with information. */ - mutable nst_map m_working_similar_counts = {}; + mutable nst_map m_working_similar_counts = {}; - mutable nsat_map m_working_animation_counts = {}; + mutable nsat_map m_working_animation_counts = {}; // Consolidated history and tracking /** * @brief Unified undo history for both original and working states. */ - std::vector m_undo_history = {}; + std::vector m_undo_history = {}; /** * @brief Tracks whether a history entry belongs to the original or working * state. */ - std::vector m_undo_original_or_working = {}; + std::vector m_undo_original_or_working = {}; // Redo history and tracking /** * @brief Unified redo history for both original and working states. */ - std::vector m_redo_history = {}; + std::vector m_redo_history = {}; /** * @brief Tracks redo states for original or working states. */ - std::vector m_redo_original_or_working = {}; + std::vector m_redo_original_or_working = {}; // New vectors for tracking descriptions of changes /** * @brief Descriptions of undo changes corresponding to * `m_undo_original_or_working`. */ - std::vector m_undo_change_descriptions = {}; + std::vector m_undo_change_descriptions = {}; /** * @brief Descriptions of redo changes corresponding to * `m_redo_original_or_working`. */ - std::vector m_redo_change_descriptions = {}; - - /** - * @brief Debug utility to print the current map history count. - * - * Outputs the count of maps in history along with the file name and line - * number for debugging purposes. - * - * @return A `glengine::ScopeGuard` object that automatically logs debug - * information when it goes out of scope. - */ - auto debug_count_print() const - { - return glengine::ScopeGuard( - [&]() - { - spdlog::debug( - "Map History Count: {}\n\t{}:{}", - count() + 2U, - __FILE__, - __LINE__); - }); - } + std::vector m_redo_change_descriptions = {}; + + // /** + // * @brief Debug utility to print the current map history count. + // * + // * Outputs the count of maps in history along with the file name and + // line + // * number for debugging purposes. + // * + // * @return A `glengine::ScopeGuard` object that automatically logs + // debug + // * information when it goes out of scope. + // */ + // auto debug_count_print() const + // { + // return glengine::ScopeGuard( + // [&]() + // { + // spdlog::debug( + // "Map History Count: {}\n\t{}:{}", + // count() + 2U, + // __FILE__, + // __LINE__); + // }); + // } /** * @brief Retrieve and process a tile from the original map at a specific @@ -674,7 +674,7 @@ class [[nodiscard]] MapHistory /** * @brief Retrieves the unique colors associated with the original PupuIDs. * - * This function provides a constant reference to a vector of `glm::vec4` + * This function provides a constant reference to a vector of `ff_8::Color` * color values corresponding to the unique PupuIDs from the original state * of the map. * @@ -684,18 +684,19 @@ class [[nodiscard]] MapHistory * targets. The colors are also cached in memory to allow reverse lookup * from a color back to its associated PupuID. * - * @return A constant reference to a vector of `glm::vec4` values, one per - * unique original PupuID. + * @return A constant reference to a vector of `ff_8::Color` values, one + * per unique original PupuID. * @note The returned colors are guaranteed to be unique for each PupuID. * @warning Assertions may be added in the future to validate the * uniqueness of the mapping. */ - const std::vector &original_unique_pupu_color() const noexcept; + const std::vector & + original_unique_pupu_color() const noexcept; /** * @brief Retrieves the unique colors associated with the working PupuIDs. * - * This function provides a constant reference to a vector of `glm::vec4` + * This function provides a constant reference to a vector of `ff_8::Color` * color values corresponding to the unique PupuIDs from the working state * of the map. * @@ -705,19 +706,19 @@ class [[nodiscard]] MapHistory * targets. The colors are also cached in memory to allow reverse lookup * from a color back to its associated PupuID. * - * @return A constant reference to a vector of `glm::vec4` values, one per - * unique working PupuID. + * @return A constant reference to a vector of `ff_8::Color` values, one + * per unique working PupuID. * @note The returned colors are guaranteed to be unique for each PupuID. * @warning Assertions may be added in the future to validate the * uniqueness of the mapping. */ - const std::vector &working_unique_pupu_color() const noexcept; + const std::vector &working_unique_pupu_color() const noexcept; /** * @brief Retrieves the PupuID associated with a given working color. * - * This function performs a reverse lookup from a `glm::vec4` color value + * This function performs a reverse lookup from a `ff_8::Color` color value * to its corresponding `PupuID` in the working map state. * * Colors are generated uniquely for each `PupuID` to support rendering @@ -737,7 +738,7 @@ class [[nodiscard]] MapHistory * the lookup will fail. */ std::optional - working_color_to_pupu_id(const glm::vec4 &in_color) const noexcept + working_color_to_pupu_id(const ff_8::Color &in_color) const noexcept { auto color_and_ids = std::views::zip( working_unique_pupu_color(), working_unique_pupu()); @@ -760,14 +761,14 @@ class [[nodiscard]] MapHistory * @brief Retrieves the current (working) tile conflicts. * * This function returns a constant reference to the current - * `source_tile_conflicts` object, which holds the conflicts between tiles + * `SourceTileConflicts` object, which holds the conflicts between tiles * in their current (working) state. The working conflicts represent the * tile data that is actively being used or modified. * - * @return A constant reference to the current `source_tile_conflicts` + * @return A constant reference to the current `SourceTileConflicts` * object. */ - [[nodiscard]] const source_tile_conflicts & + [[nodiscard]] const SourceTileConflicts & working_conflicts() const noexcept; @@ -777,7 +778,7 @@ class [[nodiscard]] MapHistory * * This getter provides access to the `m_working_similar_counts` map, which * contains the frequency of normalized tiles in the working map state. The - * map is of type `std::map`, where + * map is of type `std::map`, where * the key represents a normalized tile and the value represents how many * times it appears. * @@ -796,14 +797,14 @@ class [[nodiscard]] MapHistory * @brief Retrieves the original tile conflicts. * * This function returns a constant reference to the original - * `source_tile_conflicts` object, which holds the conflicts between tiles + * `SourceTileConflicts` object, which holds the conflicts between tiles * in their initial, unmodified state. The original conflicts are typically * used to compare against the working conflicts or as a reference. * - * @return A constant reference to the original `source_tile_conflicts` + * @return A constant reference to the original `SourceTileConflicts` * object. */ - [[nodiscard]] const source_tile_conflicts & + [[nodiscard]] const SourceTileConflicts & original_conflicts() const noexcept; diff --git a/src/opengl/ff_8/ff_8/MapOperations.cpp b/src/opengl/ff_8/ff_8/MapOperations.cpp new file mode 100644 index 00000000..424fac87 --- /dev/null +++ b/src/opengl/ff_8/ff_8/MapOperations.cpp @@ -0,0 +1,24 @@ +#include "MapOperations.hpp" + +namespace ff_8 +{ +TileInputFunctionVariant MakeTileInputFunction(TileInputStrategy s) +{ + std::size_t i = static_cast(s); + + if (i >= MapOperationSettings::input_values.size()) [[unlikely]] + return {};// monostate + + return MapOperationSettings::input_values[i]; +} + +TileOutputFunctionVariant MakeTileOutputFunction(TileOutputStrategy s) +{ + std::size_t i = static_cast(s); + + if (i >= MapOperationSettings::output_values.size()) [[unlikely]] + return {};// monostate + + return MapOperationSettings::output_values[i]; +} +}// namespace ff_8 \ No newline at end of file diff --git a/src/opengl/ff_8/ff_8/MapOperations.hpp b/src/opengl/ff_8/ff_8/MapOperations.hpp new file mode 100644 index 00000000..ba9960f6 --- /dev/null +++ b/src/opengl/ff_8/ff_8/MapOperations.hpp @@ -0,0 +1,341 @@ +#ifndef B2E1701E_178B_463A_A598_6CB97968CE39 +#define B2E1701E_178B_463A_A598_6CB97968CE39 +#include +namespace ff_8 +{ +enum struct TileInputStrategy : std::uint8_t +{ + None, + MimSwizzle, + ExternalSwizzle, + ExternalDeswizzle, + ExternalSwizzleAsOneImage, + All +}; + +enum struct TileOutputStrategy : std::uint8_t +{ + None, + Swizzle, + Deswizzle, + SwizzleAsOneImage, + All +}; + +template +struct TileInputFunction +{ +}; + +template +struct TileOutputFunction +{ +}; + +template<> +struct TileInputFunction +{ + using X = TileOperations::SourceX; + using Y = TileOperations::SourceY; + using TexturePage = TileOperations::TextureId; + using UseTexturePage = std::true_type; + using Lossless = std::true_type; + using External = std::false_type; + using StrategyType = TileInputStrategy; + static constexpr TileInputStrategy strategy + = TileInputStrategy::MimSwizzle; + static constexpr std::string_view label = "Input (MIM Swizzle)"; + static constexpr std::string_view description + = "Inputs all tiles from a MIM swizzled image file. This uses the " + "original game files so it is the most accurate representation of the " + "image."; +}; + +template<> +struct TileInputFunction +{ + using X = TileOperations::SourceX; + using Y = TileOperations::SourceY; + using TexturePage = TileOperations::TextureId; + using UseTexturePage = std::true_type; + using Lossless = std::false_type; + using External = std::true_type; + using StrategyType = TileInputStrategy; + static constexpr TileInputStrategy strategy + = TileInputStrategy::ExternalSwizzle; + static constexpr std::string_view label = "Input (External Swizzle)"; + static constexpr std::string_view description + = "Inputs all tiles from multiple swizzled image files. This is lossy " + "because tiles may overlap. Due to palettes or bits per pixel " + "settings. Meaning you might not get the same image in as you put " + "out."; +}; + +template<> +struct TileInputFunction +{ + using X = TileOperations::X; + using Y = TileOperations::Y; + using TexturePage = TileOperations::TextureId::DefaultValue; + using UseTexturePage = std::false_type; + using Lossless = std::true_type; + using External = std::true_type; + using StrategyType = TileInputStrategy; + static constexpr TileInputStrategy strategy + = TileInputStrategy::ExternalDeswizzle; + static constexpr std::string_view label = "Input (External Deswizzle)"; + static constexpr std::string_view description + = "Inputs all tiles from multiple deswizzled image files. Pupu ID is " + "used in the filename to determine which tile in each file. This " + "prevents data loss due to overlapping tiles."; +}; + +template<> +struct TileInputFunction +{ + using X = TileOperations::SwizzleAsOneImage::X; + using Y = TileOperations::SwizzleAsOneImage::Y; + using TexturePage = TileOperations::SwizzleAsOneImage::TextureId; + using UseTexturePage = std::true_type; + using Lossless = std::true_type; + using External = std::true_type; + using StrategyType = TileInputStrategy; + static constexpr TileInputStrategy strategy + = TileInputStrategy::ExternalSwizzleAsOneImage; + static constexpr std::string_view label + = "Input (External Swizzle As One Image)"; + static constexpr std::string_view description + = "Inputs all tiles from a single swizzled image file. The tiles come " + "in sequential order, so the texture page and source coordinates are " + "calculated based on the tile index.This prevents data loss due to " + "overlapping tiles."; +}; + +template<> +struct TileOutputFunction +{ + using X = TileOperations::SourceX; + using Y = TileOperations::SourceY; + using TexturePage = TileOperations::TextureId; + using UseTexturePage = std::true_type; + using UseBlendingOnRender = std::false_type; + using Lossless = std::false_type; + using StrategyType = TileOutputStrategy; + static constexpr TileOutputStrategy strategy = TileOutputStrategy::Swizzle; + static constexpr std::string_view label = "Output (Swizzle)"; + static constexpr std::string_view description + = "Standard swizzle output used by MIM. May lose data when multiple " + "tiles share the same texture page and source coordinates but have " + "different palettes or blending settings."; +}; + +template<> +struct TileOutputFunction +{ + using X = TileOperations::X; + using Y = TileOperations::Y; + using TexturePage = TileOperations::TextureId::DefaultValue; + using UseTexturePage = std::false_type; + using UseBlendingOnRender = std::true_type; + using Lossless = std::true_type; + using StrategyType = TileOutputStrategy; + static constexpr TileOutputStrategy strategy + = TileOutputStrategy::Deswizzle; + static constexpr std::string_view label = "Output (Deswizzle)"; + static constexpr std::string_view description + = "Uses Pupu ID to break up the unscrambled image into seperate files. " + "This avoid losing data. Pupu ID is generated automatically during " + "the loading of the tiles. It uses various unique properties of the " + "tile to generate a unique ID where tiles aren't overlapping."; +}; + +template<> +struct TileOutputFunction +{ + using X = TileOperations::SwizzleAsOneImage::X; + using Y = TileOperations::SwizzleAsOneImage::Y; + using TexturePage = TileOperations::SwizzleAsOneImage::TextureId; + using UseTexturePage = std::true_type; + using UseBlendingOnRender = std::false_type; + using Lossless = std::true_type; + using StrategyType = TileOutputStrategy; + static constexpr TileOutputStrategy strategy + = TileOutputStrategy::SwizzleAsOneImage; + static constexpr std::string_view label = "Output (Swizzle As One Image)"; + static constexpr std::string_view description + = "Outputs all tiles into a single swizzled image file. This also " + "reorderes the tiles to be in sequential order. This will prevent " + "data loss. Because it's impossible for the tiles to overlap " + "when using this method."; +}; + +template +struct TileFunction +{ + using S = std::remove_cvref_t; + // ------------------------- + // Type aliases for compile-time use + // ------------------------- + using XType = typename S::X; + using YType = typename S::Y; + using TexturePageType = typename S::TexturePage; + using StrategyType = typename S::StrategyType; + static constexpr StrategyType strategy = S::strategy; + + constexpr operator StrategyType() const + { + return strategy; + } + + // Mandatory trait: + // UseTexturePage indicates if the texture page is used in this operation. + // Texture Page shifts everything by 256 pixels in X direction. Depending + // on the bits per pixel. Higher bpp uses shortened texture pages: 4bpp = + // 256, 8bpp = 128, 16bpp = 64. Though for output we just use full 256 + // pixel pages. + static constexpr bool UseTexturePage = S::UseTexturePage::value; + + // Mandatory trait: + // Lossless indicates if the operation is lossless or lossy. + static constexpr bool Lossless = S::Lossless::value; + + static constexpr std::string_view label = S::label; + static constexpr std::string_view description = S::description; + + + // Optional trait: + // External (input-only trait) indicates if the tile data comes from + // external files and not the original MIM files. + static constexpr bool External = [] + { + if constexpr (requires { typename S::External; }) + { + return S::External::value; + } + else + { + return false; + } + }(); + + // Optional trait: + // UseBlendingOnRender (output-only trait) forced to false for outputting + // to files. But when true and rendering to screen its used for a default. + // That can be toggled on and off. When false it cannot be toggled. + static constexpr bool UseBlendingOnRender = [] + { + if constexpr (requires { typename S::UseBlendingOnRender; }) + { + return S::UseBlendingOnRender::value; + } + else + { + return false; + } + }(); + + [[nodiscard]] auto set_map(const open_viii::graphics::background::Map &m) + { + // set the map for the operations and return all the guards in a tuple + // so they reset on destruction. + return std::tuple{ X(m), Y(m), TexturePage(m) }; + } + + // X cordinate getter, use X(tile) to get value + XType X{}; + // Y cordinate getter, use Y(tile) to get value + YType Y{}; + // Texture page getter, use TexturePage(tile) to get value + TexturePageType TexturePage{}; +}; + + +using TileInputFunctionVariant = decltype([] { + return [](std::index_sequence) + -> std::variant(Is + 1)>>...> + { + return std::monostate{}; // default-constructed variant + }(std::make_index_sequence(TileInputStrategy::All) - 1>{}); +}()); + +using TileOutputFunctionVariant = decltype([] { + return [](std::index_sequence) + -> std::variant(Is + 1)>>...> + { + return std::monostate{}; // default-constructed variant + }(std::make_index_sequence(TileOutputStrategy::All) - 1>{}); +}()); + + +namespace MapOperationSettings +{ + template + inline consteval std::array< + std::string_view, + std::variant_size_v> + all_labels() + { + return [](std::index_sequence) + { + return std::array{ ( + [] + { + using T = std::variant_alternative_t; + if constexpr (std::is_same_v) + return std::string_view{ "" }; + else + return T::label; + }())... }; + }(std::make_index_sequence>{}); + } + + template + inline consteval std::array< + std::string_view, + std::variant_size_v> + all_descriptions() + { + return [](std::index_sequence) + { + return std::array{ ( + [] + { + using T = std::variant_alternative_t; + if constexpr (std::is_same_v) + return std::string_view{ "" }; + else + return T::description; + }())... }; + }(std::make_index_sequence>{}); + } + + template + inline consteval std::array< + Variant, + std::variant_size_v> + all_values() + { + return [](std::index_sequence) + { + return std::array{ Variant{ + std::variant_alternative_t{} }... }; + }(std::make_index_sequence>{}); + } + inline constexpr auto input_labels + = all_labels(); + inline constexpr auto input_descriptions + = all_descriptions(); + inline constexpr auto input_values + = all_values(); + inline constexpr auto output_labels + = all_labels(); + inline constexpr auto output_descriptions + = all_descriptions(); + inline constexpr auto output_values + = all_values(); +}// namespace MapOperationSettings + +TileInputFunctionVariant MakeTileInputFunction(TileInputStrategy s); +TileOutputFunctionVariant MakeTileOutputFunction(TileOutputStrategy s); +}// namespace ff_8 +#endif /* B2E1701E_178B_463A_A598_6CB97968CE39 */ diff --git a/src/opengl/main/normalized_source_tile.hpp b/src/opengl/ff_8/ff_8/NormalizedSourceTile.hpp similarity index 85% rename from src/opengl/main/normalized_source_tile.hpp rename to src/opengl/ff_8/ff_8/NormalizedSourceTile.hpp index 70d0030c..f871cd8c 100644 --- a/src/opengl/main/normalized_source_tile.hpp +++ b/src/opengl/ff_8/ff_8/NormalizedSourceTile.hpp @@ -12,10 +12,10 @@ namespace open_viii::graphics::background * - **Destination X, Y, Z**: These are excluded since similar/duplicate tiles * do not rely on specific destination coordinates. */ -struct normalized_source_tile +struct NormalizedSourceTile { public: - using impl_type = normalized_source_tile; + using impl_type = NormalizedSourceTile; TexIdBuffer m_tex_id_buffer = {};///< Buffer holding texture ID, blending, depth, and draw flags. PaletteID m_palette_id @@ -32,10 +32,10 @@ struct normalized_source_tile /// @brief Default constructor. - constexpr normalized_source_tile() = default; + constexpr NormalizedSourceTile() = default; /// @brief Compares two tiles for equality or ordering. - constexpr auto operator<=>(const normalized_source_tile &) const = default; + constexpr auto operator<=>(const NormalizedSourceTile &) const = default; /** * @brief Constructs a normalized tile from a generic tile object. @@ -44,7 +44,7 @@ struct normalized_source_tile * properties like texture ID, source position, etc. * @param tile The tile object to initialize this normalized tile from. */ - constexpr normalized_source_tile(const is_tile auto &tile) + constexpr NormalizedSourceTile(const is_tile auto &tile) { m_tex_id_buffer = m_tex_id_buffer.with_id(tile.texture_id()) .with_blend(tile.blend()) @@ -74,7 +74,7 @@ struct normalized_source_tile * @param tile The tile object to assign from. * @return Reference to the updated normalized tile. */ - constexpr normalized_source_tile &operator=(const is_tile auto &tile) + constexpr NormalizedSourceTile &operator=(const is_tile auto &tile) { m_tex_id_buffer = m_tex_id_buffer.with_id(tile.texture_id()) .with_blend(tile.blend()) @@ -98,17 +98,16 @@ struct normalized_source_tile } /// @brief Default copy constructor. - normalized_source_tile(const normalized_source_tile &) = default; + NormalizedSourceTile(const NormalizedSourceTile &) = default; /// @brief Default copy assignment operator. - normalized_source_tile &operator=(const normalized_source_tile &) - = default; + NormalizedSourceTile &operator=(const NormalizedSourceTile &) = default; /// @brief Default move constructor. - normalized_source_tile(normalized_source_tile &&) noexcept = default; + NormalizedSourceTile(NormalizedSourceTile &&) noexcept = default; /// @brief Default move assignment operator. - normalized_source_tile &operator=(normalized_source_tile &&) noexcept + NormalizedSourceTile &operator=(NormalizedSourceTile &&) noexcept = default; }; @@ -130,7 +129,7 @@ struct normalized_source_tile * palette is set to a unused (maximum value) because some animations have * frames with different palettes. */ -struct normalized_source_animated_tile +struct NormalizedSourceAnimatedTile { public: TexIdBuffer m_tex_id_buffer = {};///< Buffer holding texture ID, depth, and @@ -145,22 +144,21 @@ struct normalized_source_animated_tile ///< no animation). /// @brief Default constructor. - constexpr normalized_source_animated_tile() = default; + constexpr NormalizedSourceAnimatedTile() = default; /// @brief Compares two animated tiles for equality or ordering. - constexpr auto operator<=>(const normalized_source_animated_tile &) const + constexpr auto operator<=>(const NormalizedSourceAnimatedTile &) const = default; /** * @brief Constructs a normalized animated tile from a - * `normalized_source_tile`. + * `NormalizedSourceTile`. * * @param tile The source tile to initialize this animated tile from. */ - constexpr normalized_source_animated_tile( - const normalized_source_tile &tile) + constexpr NormalizedSourceAnimatedTile(const NormalizedSourceTile &tile) : m_tex_id_buffer(tile.m_tex_id_buffer.with_blend(0)) , m_palette_id( tile.m_animation_id != (std::numeric_limits::max)() @@ -179,7 +177,7 @@ struct normalized_source_animated_tile * properties like texture ID, source position, etc. * @param tile The tile object to initialize this animated tile from. */ - constexpr normalized_source_animated_tile(const is_tile auto &tile) + constexpr NormalizedSourceAnimatedTile(const is_tile auto &tile) : m_tex_id_buffer{ TexIdBuffer{} .with_id(tile.texture_id()) .with_depth(tile.depth()) @@ -204,14 +202,14 @@ struct normalized_source_animated_tile } /** - * @brief Assigns values from a `normalized_source_tile` to this animated + * @brief Assigns values from a `NormalizedSourceTile` to this animated * tile. * * @param tile The source tile to assign from. * @return Reference to the updated animated tile. */ - constexpr normalized_source_animated_tile & - operator=(const normalized_source_tile &tile) + constexpr NormalizedSourceAnimatedTile & + operator=(const NormalizedSourceTile &tile) { m_tex_id_buffer = tile.m_tex_id_buffer.with_blend(0); m_palette_id @@ -232,8 +230,7 @@ struct normalized_source_animated_tile * @param tile The tile object to assign from. * @return Reference to the updated animated tile. */ - constexpr normalized_source_animated_tile & - operator=(const is_tile auto &tile) + constexpr NormalizedSourceAnimatedTile &operator=(const is_tile auto &tile) { m_tex_id_buffer = TexIdBuffer{} .with_id(tile.texture_id()) @@ -259,23 +256,23 @@ struct normalized_source_animated_tile } /// @brief Default copy constructor. - constexpr normalized_source_animated_tile( - const normalized_source_animated_tile &) + constexpr NormalizedSourceAnimatedTile( + const NormalizedSourceAnimatedTile &) = default; /// @brief Default copy assignment operator. - constexpr normalized_source_animated_tile & - operator=(const normalized_source_animated_tile &) + constexpr NormalizedSourceAnimatedTile & + operator=(const NormalizedSourceAnimatedTile &) = default; /// @brief Default move constructor. - constexpr normalized_source_animated_tile( - normalized_source_animated_tile &&) noexcept + constexpr NormalizedSourceAnimatedTile( + NormalizedSourceAnimatedTile &&) noexcept = default; /// @brief Default move assignment operator. - constexpr normalized_source_animated_tile & - operator=(normalized_source_animated_tile &&) noexcept + constexpr NormalizedSourceAnimatedTile & + operator=(NormalizedSourceAnimatedTile &&) noexcept = default; }; }// namespace open_viii::graphics::background diff --git a/src/opengl/main/PupuID.cpp b/src/opengl/ff_8/ff_8/PupuID.cpp similarity index 98% rename from src/opengl/main/PupuID.cpp rename to src/opengl/ff_8/ff_8/PupuID.cpp index 9ea60a2e..b29a14d3 100644 --- a/src/opengl/main/PupuID.cpp +++ b/src/opengl/ff_8/ff_8/PupuID.cpp @@ -1,5 +1,5 @@ -#include "PupuID.hpp" -#include "formatters.hpp" +#include "Formatters.hpp" +#include using namespace open_viii::graphics::background; namespace ff_8 { diff --git a/src/opengl/main/PupuID.hpp b/src/opengl/ff_8/ff_8/PupuID.hpp similarity index 99% rename from src/opengl/main/PupuID.hpp rename to src/opengl/ff_8/ff_8/PupuID.hpp index 329b4ab9..5adc8e46 100644 --- a/src/opengl/main/PupuID.hpp +++ b/src/opengl/ff_8/ff_8/PupuID.hpp @@ -7,6 +7,7 @@ #include "open_viii/graphics/background/Map.hpp" #include #include +#include namespace ff_8 { struct PupuID diff --git a/src/opengl/ff_8/ff_8/SafeDir.cpp b/src/opengl/ff_8/ff_8/SafeDir.cpp new file mode 100644 index 00000000..0f2cdd41 --- /dev/null +++ b/src/opengl/ff_8/ff_8/SafeDir.cpp @@ -0,0 +1,123 @@ +// +// Created by pcvii on 12/14/2022. +// + +#include "SafeDir.hpp" + +namespace ff_8 +{ +SafeDir::SafeDir(const std::filesystem::path &path) + : m_path(path) +{ + std::error_code ec{}; + m_status = std::filesystem::status(m_path, ec); + if (ec) + { + debug(ec, __FILE__, __LINE__); + return; + } +} + +SafeDir::operator const std::filesystem::path &() const +{ + return m_path; +} + +bool SafeDir::is_exists() const noexcept +{ + return std::filesystem::exists(m_status); +} + +bool SafeDir::is_dir() const noexcept +{ + return std::filesystem::is_directory(m_status); +} + +bool SafeDir::is_file() const noexcept +{ + return std::filesystem::is_regular_file(m_status); +} + +bool SafeDir::is_symlink() const noexcept +{ + return std::filesystem::is_symlink(m_status); +} + +bool SafeDir::is_block() const noexcept +{ + return std::filesystem::is_block_file(m_status); +} + +bool SafeDir::is_char() const noexcept +{ + return std::filesystem::is_character_file(m_status); +} + +bool SafeDir::is_fifo() const noexcept +{ + return std::filesystem::is_fifo(m_status); +} + +bool SafeDir::is_socket() const noexcept +{ + return std::filesystem::is_socket(m_status); +} + +bool SafeDir::is_other() const noexcept +{ + return std::filesystem::is_other(m_status); +} + +std::filesystem::perms SafeDir::permissions() const noexcept +{ + return m_status.permissions(); +} + +const std::filesystem::path &SafeDir::path() const noexcept +{ + return m_path; +} + +std::filesystem::path SafeDir::case_insensitive_exists() const +{ + std::error_code ec{}; + for (const auto &entry : + std::filesystem::directory_iterator(m_path.parent_path(), ec)) + { + bool size_match = entry.path().filename().string().size() + == m_path.filename().string().size(); + if ( + size_match + && open_viii::tools::i_equals( + entry.path().filename().string(), m_path.filename().string())) + { + return entry.path(); + } + } + if (ec) + { + debug(ec, __FILE__, __LINE__); + } + return {}; +} +void SafeDir::debug( + std::error_code &ec, + std::string_view file, + int line) const +{ + if (ec == std::errc::no_such_file_or_directory) + { + // Not found - common, safe to ignore + return; + } + spdlog::info( + "{}:{} - {}: {} path: \"{}\"", + file, + line, + ec.value(), + ec.message(), + m_path.string()); + ec.clear(); +} + +}// namespace ff_8 \ No newline at end of file diff --git a/src/opengl/ff_8/ff_8/SafeDir.hpp b/src/opengl/ff_8/ff_8/SafeDir.hpp new file mode 100644 index 00000000..2e8d9206 --- /dev/null +++ b/src/opengl/ff_8/ff_8/SafeDir.hpp @@ -0,0 +1,40 @@ +// +// Created by pcvii on 12/14/2022. +// + +#ifndef FIELD_MAP_EDITOR_SAFEDIR_HPP +#define FIELD_MAP_EDITOR_SAFEDIR_HPP +#include +#include +#include +#include +namespace ff_8 +{ +class SafeDir +{ + public: + SafeDir(const std::filesystem::path &path); + explicit operator const std::filesystem::path &() const; + bool is_exists() const noexcept; + bool is_dir() const noexcept; + std::filesystem::path case_insensitive_exists() const; + bool is_file() const noexcept; + bool is_symlink() const noexcept; + bool is_block() const noexcept; + bool is_char() const noexcept; + bool is_fifo() const noexcept; + bool is_socket() const noexcept; + bool is_other() const noexcept; + std::filesystem::perms permissions() const noexcept; + const std::filesystem::path &path() const noexcept; + + private: + void debug( + std::error_code &ec, + std::string_view file, + int line) const; + const std::filesystem::path &m_path = {}; + std::filesystem::file_status m_status = {}; +}; +}// namespace ff_8 +#endif// FIELD_MAP_EDITOR_SAFEDIR_HPP diff --git a/src/opengl/main/source_tile_conflicts.hpp b/src/opengl/ff_8/ff_8/SourceTileConflicts.hpp similarity index 98% rename from src/opengl/main/source_tile_conflicts.hpp rename to src/opengl/ff_8/ff_8/SourceTileConflicts.hpp index 4a69cd10..0b2dbbdc 100644 --- a/src/opengl/main/source_tile_conflicts.hpp +++ b/src/opengl/ff_8/ff_8/SourceTileConflicts.hpp @@ -24,7 +24,7 @@ namespace ff_8 /** * @brief A class for tracking and resolving conflicts between source tiles. * - * The `source_tile_conflicts` class is used to manage and analyze conflicts + * The `SourceTileConflicts` class is used to manage and analyze conflicts * between tiles in a grid. It provides methods to: * - Track the number of tiles at each location. * - Identify locations with conflicts (multiple tiles in the same spot). @@ -36,7 +36,7 @@ namespace ff_8 * * @note The class is marked `final` to prevent inheritance. */ -class [[nodiscard]] source_tile_conflicts final +class [[nodiscard]] SourceTileConflicts final { public: /** @@ -398,17 +398,17 @@ class [[nodiscard]] source_tile_conflicts final } // /** - // * @brief Compares two `source_tile_conflicts` objects for ordering and + // * @brief Compares two `SourceTileConflicts` objects for ordering and // equality. // * // * This operator provides default comparison behavior using the // three-way comparison operator. // * - // * @param other The other `source_tile_conflicts` object to compare. + // * @param other The other `SourceTileConflicts` object to compare. // * @return A `std::strong_ordering` indicating the result of the // comparison. // */ - // constexpr auto operator<=>(const source_tile_conflicts &) + // constexpr auto operator<=>(const SourceTileConflicts &) // const noexcept = default; diff --git a/src/opengl/ff_8/ff_8/TileOperations.hpp b/src/opengl/ff_8/ff_8/TileOperations.hpp new file mode 100644 index 00000000..52deee63 --- /dev/null +++ b/src/opengl/ff_8/ff_8/TileOperations.hpp @@ -0,0 +1,672 @@ +#ifndef DC423E74_7AF3_459A_A708_F6C46A9776EA +#define DC423E74_7AF3_459A_A708_F6C46A9776EA +#include "Formatters.hpp" +#include +#include +#include +#include +#include +#include +#include +#include + +namespace ff_8::TileOperations +{ + +template +static constexpr TileT MaxTile = []() +{ + std::array tmp{}; + tmp.fill(std::numeric_limits::max()); + return std::bit_cast(tmp); +}(); + +// === TileOperation Base === +template +struct TileOperation +{ + using get_fn_t = decltype(GetFn); + using set_fn_t = decltype(SetFn); + + // Deduce value_type from any tile type + template + using value_type = std::invoke_result_t; + + // noop set_map + [[nodiscard]] std::monostate + set_map(const open_viii::graphics::background::Map & /*m*/) + { + return {}; + } + + template + struct nested_type + { + using local_value_type = ValueT; + }; + + // Partial specialization for value_type + template + struct nested_type + { + using local_value_type = value_type; + }; + + template + using nested_type_t = nested_type::local_value_type; + + // === Get === + template + [[nodiscard]] constexpr value_type + operator()(const TileT &tile) const noexcept + { + return GetFn(tile); + } + + // === DefaultValue === + struct DefaultValue + { + template + [[nodiscard]] constexpr value_type + operator()(const TileT &) const noexcept + { + return {}; + } + }; + + // === Match === + + template + struct Match + { + + using ValueT = nested_type_t; + ValueT m_value{}; + + constexpr explicit Match(const InputT &tile) + requires(open_viii::graphics::background::is_tile) + : m_value(GetFn(tile)) + { + } + + constexpr explicit Match(InputT v) + requires(!open_viii::graphics::background::is_tile) + : m_value(std::move(v)) + { + } + + + template + [[nodiscard]] constexpr bool + operator()(const TileT &tile) const noexcept + { + return GetFn(tile) == m_value; + } + + [[nodiscard]] constexpr auto operator<=>(const Match &) const + = default; + + template + requires std::equality_comparable_with< + ValueT, + T> + [[nodiscard]] constexpr bool operator==(const T &v) const + { + return m_value == v; + } + + template + requires std::three_way_comparable_with< + ValueT, + T> + [[nodiscard]] constexpr auto operator<=>(const T &v) const + { + return m_value <=> v; + } + + template + [[nodiscard]] constexpr bool operator==(const TileT &tile) const + { + return GetFn(tile) == m_value; + } + template + [[nodiscard]] constexpr auto operator<=>(const TileT &tile) const + { + return m_value <=> GetFn(tile); + } + }; + + // === With === + template + struct With + { + using ValueT = nested_type_t; + ValueT m_value{}; + + + constexpr explicit With(const InputT &tile) + requires(open_viii::graphics::background::is_tile) + : m_value(GetFn(tile)) + { + } + + constexpr explicit With(InputT v) + requires(!open_viii::graphics::background::is_tile) + : m_value(std::move(v)) + { + } + + template + [[nodiscard]] constexpr TileT + operator()(const TileT &tile) const noexcept + requires(!std::is_same_v< + set_fn_t, + std::nullptr_t>) + { + spdlog::trace( + "with_... used: {}", static_cast>(m_value)); + return SetFn(tile, static_cast>(m_value)); + } + + template + [[nodiscard]] constexpr TileT + operator()(const TileT &tile) const noexcept + requires(std::is_same_v< + set_fn_t, + std::nullptr_t>) + { + spdlog::debug("no with_... available"); + return tile; + } + + template + friend constexpr TileT operator|( + const TileT &tile, + const With &op) + { + return op(tile); + } + }; + + // === TranslateWith === + template + struct TranslateWith + { + using ValueT = nested_type_t; + ValueT m_from{}; + ValueT m_to{}; + + template + constexpr explicit TranslateWith( + const InputT &tile, + V &&to) + requires(open_viii::graphics::background::is_tile) + : m_from(GetFn(tile)) + , m_to(std::forward_like(static_cast(to))) + { + } + + constexpr explicit TranslateWith( + InputT from, + InputT to) + requires(!open_viii::graphics::background::is_tile) + : m_from(std::move(from)) + , m_to(std::move(to)) + { + } + + template + [[nodiscard]] constexpr TileT + operator()(const TileT &tile) const noexcept + requires(!std::is_same_v< + set_fn_t, + std::nullptr_t>) + { + if constexpr (requires(ValueT a, ValueT b) { + { a + b } -> std::convertible_to; + { a - b } -> std::convertible_to; + }) + { + const auto current = m_to + GetFn(tile) - m_from; + spdlog::trace( + "translate with_...: {} -> {}", current, current); + return SetFn(tile, static_cast>(current)); + } + else + { + spdlog::debug( + "translate skipped for type without + or - support"); + return tile; + } + } + + template + [[nodiscard]] constexpr TileT + operator()(const TileT &tile) const noexcept + requires(std::is_same_v< + set_fn_t, + std::nullptr_t>) + { + spdlog::debug("no translate with_... available"); + return tile; + } + + template + friend constexpr TileT operator|( + const TileT &tile, + const TranslateWith &op) + { + return op(tile); + } + }; + + // === Group (UI State) === + template + struct Group + { + using local_value_type = value_type; + local_value_type current{}; + + static constexpr local_value_type min_value = []() + { + if constexpr (std::signed_integral) + { + return std::numeric_limits::min(); + } + else + { + return GetFn(TileT{}); + } + }(); + + static constexpr local_value_type max_value = []() + { + if constexpr (std::signed_integral) + { + return std::numeric_limits::max(); + } + else + { + return GetFn(MaxTile); + } + }(); + + static constexpr bool read_only + = std::is_same_v; + + constexpr Group() = default; + constexpr explicit Group(local_value_type v) + : current(std::move(v)) + { + } + constexpr explicit Group(const TileT &tile) + : current(GetFn(tile)) + { + } + + using transform_with = With; + using match_with = Match; + }; + + // === Concepts === + template + static constexpr bool has_setter + = !std::is_same_v; + + // === Deduction Guides === + template + Match(T) -> Match; + + template< + typename U, + open_viii::graphics::background::is_tile T> + requires std::constructible_from< + value_type, + U> + Match(U) -> Match; + + template< + typename U, + open_viii::graphics::background::is_tile T> + requires std::constructible_from< + value_type, + U> + With(U) -> With; +}; + + +// Define operations +using X = TileOperation< + [](auto &&t) { return t.x(); }, + [](auto &&t, auto v) { return t.with_x(v); }>; + +using Y = TileOperation< + [](auto &&t) { return t.y(); }, + [](auto &&t, auto v) { return t.with_y(v); }>; + +using XY = TileOperation< + [](auto &&t) { return t.xy(); }, + [](auto &&t, auto v) { return t.with_xy(v); }>; + +using Z = TileOperation< + [](auto &&t) { return t.z(); }, + [](auto &&t, auto v) { return t.with_z(v); }>; + +using SourceX = TileOperation< + [](auto &&t) { return t.source_x(); }, + [](auto &&t, auto v) { return t.with_source_x(v); }>; + +using SourceY = TileOperation< + [](auto &&t) { return t.source_y(); }, + [](auto &&t, auto v) { return t.with_source_y(v); }>; + +using SourceXY = TileOperation< + [](auto &&t) { return t.source_xy(); }, + [](auto &&t, auto v) { return t.with_source_xy(v); }>; + +using TextureId = TileOperation< + [](auto &&t) { return t.texture_id(); }, + [](auto &&t, auto v) { return t.with_texture_id(v); }>; + +using BlendMode = TileOperation< + [](auto &&t) { return t.blend_mode(); }, + [](open_viii::graphics::background::is_tile auto &&t, auto v) + { + if constexpr (requires { t.with_blend_mode(v); }) + { + return t.with_blend_mode(v); + } + else + { + return std::forward(t); + } + }>; + +using Blend = TileOperation< + [](auto &&t) { return t.blend(); }, + [](auto &&t, auto v) { return t.with_blend(v); }>; + +using Draw = TileOperation< + [](auto &&t) { return t.draw(); }, + [](auto &&t, auto v) { return t.with_draw(v); }>; + +using Depth = TileOperation< + [](auto &&t) { return t.depth(); }, + [](auto &&t, auto v) { return t.with_depth(v); }>; + +using LayerId = TileOperation< + [](auto &&t) { return t.layer_id(); }, + [](open_viii::graphics::background::is_tile auto &&t, auto v) + { + if constexpr (requires { t.with_layer_id(v); }) + { + return t.with_layer_id(v); + } + else + { + return std::forward(t); + } + }>; + +using PaletteId = TileOperation< + [](auto &&t) { return t.palette_id(); }, + [](auto &&t, auto v) { return t.with_palette_id(v); }>; + +using AnimationId = TileOperation< + [](auto &&t) { return t.animation_id(); }, + [](open_viii::graphics::background::is_tile auto &&t, auto v) + { + if constexpr (requires { t.with_animation_id(v); }) + { + return t.with_animation_id(v); + } + else + { + return std::forward(t); + } + }>; + +using AnimationState = TileOperation< + [](auto &&t) { return t.animation_state(); }, + [](open_viii::graphics::background::is_tile auto &&t, auto v) + { + if constexpr (requires { t.with_animation_state(v); }) + { + return t.with_animation_state(v); + } + else + { + return std::forward(t); + } + }>; + +struct NotInvalidTile +{ + template + constexpr bool operator()(const T &tile) const noexcept + { + return std::cmp_not_equal(tile.x(), 0x7FFFU); + } +}; +namespace SwizzleAsOneImage +{ + struct Base + { + static constexpr int TILE_SIZE = 16; + static constexpr int TEXTURE_PAGE_WIDTH = 256; + const open_viii::graphics::background::Map *map = nullptr; + + static int tiles_per_row(std::size_t size) + { + if (size > TILE_SIZE) + { + return static_cast(size) / TILE_SIZE + + ((static_cast(size) % TILE_SIZE) != 0 ? 1 : 0); + } + return TILE_SIZE; + } + + template + static std::optional index_of( + const TileVec &tiles, + const auto &tile) + { + auto it = std::ranges::find_if( + tiles, + [&](const auto &t) + { return std::addressof(t) == std::addressof(tile); }); + + if (tiles.end() == it) + { + return std::nullopt; + } + return static_cast( + std::distance(std::begin(tiles), it)); + } + + struct index_and_size + { + std::size_t index{}; + std::size_t size{}; + }; + + struct guard + { + const open_viii::graphics::background::Map **map_ptr = nullptr; + explicit guard(const open_viii::graphics::background::Map *&map) + : map_ptr(&map) + { + } + ~guard() + { + if (map_ptr && *map_ptr) + { + *map_ptr = nullptr; + } + } + // Movable + guard(guard &&other) noexcept + : map_ptr(other.map_ptr) + { + other.map_ptr = nullptr; + } + guard &operator=(guard &&other) noexcept + { + if (this != &other) + { + map_ptr = other.map_ptr; + other.map_ptr = nullptr; + } + return *this; + } + }; + + [[nodiscard]] guard + set_map(const open_viii::graphics::background::Map &m) + { + map = &m; + return guard{ map }; + } + + protected: + template + std::expected< + index_and_size, + std::string> + get_index_and_size(const TileT &tile) const + { + if (!map) + { + return std::unexpected("SwizzleAsOneImage: map not set"); + } + + + return map->visit_tiles( + [&](auto &&tiles) -> std::expected + { + using VecT = std::remove_cvref_t; + using ElemT = typename VecT::value_type; + + if constexpr (std::is_same_v) + { + std::optional index{}; + std::size_t total_size{}; + + auto filtered + = tiles | std::views::filter(NotInvalidTile{}); + total_size = static_cast( + std::ranges::distance(filtered)); + index = index_of(tiles, tile); + + if (!index.has_value()) + { + return std::unexpected( + "SwizzleAsOneImage: Tile not found in map"); + } + + return std::expected{ + std::in_place, *index, total_size + }; + } + else + { + return std::unexpected( + "SwizzleAsOneImage: Tile type mismatch"); + } + }); + } + }; + + struct X : Base + { + using Base::Base;// inherit constructor + + template + auto operator()(const TileT &tile) const + { + const auto result = get_index_and_size(tile); + if (!result) + { + spdlog::error( + "[{}:{}] SwizzleAsOneImage::X: {}", + __FILE__, + __LINE__, + result.error()); + return ff_8::TileOperations::SourceX::value_type{}; + } + + const auto &[index, total_size] = *result; + + assert(index < total_size && "Index out of range"); + + const int tpr = tiles_per_row(total_size); + const int x = (static_cast(index) % tpr) * TILE_SIZE; + assert(x >= 0 && "X coordinate negative"); + const int tp = x / TEXTURE_PAGE_WIDTH; + assert(tp >= 0 && "Texture page negative"); + const int src_x = x - tp * TEXTURE_PAGE_WIDTH; + + return static_cast< + ff_8::TileOperations::SourceX::value_type>(src_x); + } + }; + + struct Y : Base + { + using Base::Base; + + template + auto operator()(const TileT &tile) const + { + const auto result = get_index_and_size(tile); + if (!result) + { + spdlog::error( + "[{}:{}] SwizzleAsOneImage::Y: {}", + __FILE__, + __LINE__, + result.error()); + return ff_8::TileOperations::SourceY::value_type{}; + } + + const auto &[index, total_size] = *result; + + const int tpr = tiles_per_row(total_size); + const int y = (static_cast(index) / tpr) * TILE_SIZE; + + return static_cast< + ff_8::TileOperations::SourceY::value_type>(y); + } + }; + + struct TextureId : Base + { + using Base::Base; + + template + std::uint8_t operator()(const TileT &tile) const + { + auto result = get_index_and_size(tile); + if (!result) + { + spdlog::error( + "[{}:{}] SwizzleAsOneImage::TextureId: {}", + __FILE__, + __LINE__, + result.error()); + return {}; + } + + const auto &[index, total_size] = *result; + + const int tpr = tiles_per_row(total_size); + const int x = (static_cast(index) % tpr) * TILE_SIZE; + const int tp = x / TEXTURE_PAGE_WIDTH; + + return static_cast(tp); + } + }; +}// namespace SwizzleAsOneImage + +}// namespace ff_8::TileOperations +#endif /* DC423E74_7AF3_459A_A708_F6C46A9776EA */ \ No newline at end of file diff --git a/src/opengl/main/unique_values.hpp b/src/opengl/ff_8/ff_8/UniqueValues.hpp similarity index 75% rename from src/opengl/main/unique_values.hpp rename to src/opengl/ff_8/ff_8/UniqueValues.hpp index 2393a140..8456e64e 100644 --- a/src/opengl/main/unique_values.hpp +++ b/src/opengl/ff_8/ff_8/UniqueValues.hpp @@ -4,16 +4,16 @@ #ifndef FIELD_MAP_EDITOR_UNIQUE_VALUES_HPP #define FIELD_MAP_EDITOR_UNIQUE_VALUES_HPP -#include "formatters.hpp" -#include "open_viii/graphics/background/BlendModeT.hpp" -#include "open_viii/graphics/BPPT.hpp" +#include "Formatters.hpp" #include "PupuID.hpp" -#include "tile_operations.hpp" +#include "TileOperations.hpp" #include "UniquifyPupu.hpp" #include #include #include #include +#include +#include #include #include #include @@ -21,7 +21,7 @@ namespace ff_8 { template -struct unique_values_and_strings +struct UniqueValues { private: static constexpr auto default_filter_lambda = [](auto &&) { return true; }; @@ -29,15 +29,15 @@ struct unique_values_and_strings = [](auto &&, auto &&ret) { return std::forward(ret); }; public: - using value_type = T; - unique_values_and_strings() = default; + using value_type = T; + UniqueValues() = default; template< std::ranges::range tilesT, typename lambdaT, typename sortT = std::less<>, typename filterT = decltype(default_filter_lambda), typename secondT = decltype(kite)> - explicit unique_values_and_strings( + explicit UniqueValues( const tilesT &tiles, lambdaT &&lambda, sortT &&sort = {}, @@ -53,7 +53,7 @@ struct unique_values_and_strings , m_strings(get_strings(m_values)) { } - explicit unique_values_and_strings( + explicit UniqueValues( std::vector in_values, std::vector in_strings) : m_values(std::move(in_values)) @@ -153,39 +153,40 @@ struct all_unique_values_and_strings explicit all_unique_values_and_strings(const tilesT &tiles) : m_z( tiles, - ff_8::tile_operations::Z{}, + ff_8::TileOperations::Z{}, std::greater<>{}) , m_layer_id( tiles, - ff_8::tile_operations::LayerId{}) + ff_8::TileOperations::LayerId{}) , m_texture_page_id( tiles, - ff_8::tile_operations::TextureId{}) + ff_8::TileOperations::TextureId{}) , m_animation_id( tiles, - ff_8::tile_operations::AnimationId{}) + ff_8::TileOperations::AnimationId{}) , m_blend_other( tiles, - ff_8::tile_operations::Blend{}) + ff_8::TileOperations::Blend{}) , m_blend_mode( tiles, - ff_8::tile_operations::BlendMode{}) + ff_8::TileOperations::BlendMode{}) , m_bpp( tiles, - ff_8::tile_operations::Depth{}) + ff_8::TileOperations::Depth{}) , m_animation_frame( get_map< std::uint8_t, std::uint8_t>( tiles, m_animation_id, - ff_8::tile_operations::AnimationState{}, + ff_8::TileOperations::AnimationState{}, {}, []( const auto key, const auto &tile) -> bool { - return ff_8::tile_operations::AnimationIdMatch{ key } == tile; + return ff_8::TileOperations::AnimationId::Match{ key } + == tile; })) , m_palette( get_map< @@ -193,12 +194,12 @@ struct all_unique_values_and_strings open_viii::graphics::BPPT>( tiles, m_bpp, - ff_8::tile_operations::PaletteId{}, + ff_8::TileOperations::PaletteId{}, {}, []( const auto key, const auto &tile) -> bool - { return ff_8::tile_operations::DepthMatch{ tile } == key; })) + { return ff_8::TileOperations::Depth::Match{ tile } == key; })) { } [[nodiscard]] const auto &z() const @@ -239,19 +240,17 @@ struct all_unique_values_and_strings } private: - unique_values_and_strings m_z = {}; - unique_values_and_strings m_layer_id = {}; - unique_values_and_strings m_texture_page_id = {}; - unique_values_and_strings m_animation_id = {}; - unique_values_and_strings m_blend_other = {}; - unique_values_and_strings - m_blend_mode = {}; - unique_values_and_strings m_bpp = {}; - std::map> - m_animation_frame = {}; - std:: - map> - m_palette = {}; + UniqueValues m_z = {}; + UniqueValues m_layer_id = {}; + UniqueValues m_texture_page_id = {}; + UniqueValues m_animation_id = {}; + UniqueValues m_blend_other = {}; + UniqueValues m_blend_mode + = {}; + UniqueValues m_bpp = {}; + std::map> m_animation_frame = {}; + std::map> m_palette + = {}; static constexpr auto default_filter_lambda = [](auto &&) { return true; }; template< @@ -263,20 +262,20 @@ struct all_unique_values_and_strings typename filterT = decltype(default_filter_lambda)> static std::map< keyT, - unique_values_and_strings> + UniqueValues> get_map( - const tilesT &tiles, - const unique_values_and_strings &keys, - lambdaT &&lambda, - sortT &&sort = {}, - filterT &&filter = {}) + const tilesT &tiles, + const UniqueValues &keys, + lambdaT &&lambda, + sortT &&sort = {}, + filterT &&filter = {}) { - std::map> ret = {}; + std::map> ret = {}; for (const auto &key : keys.values()) { ret.emplace( key, - unique_values_and_strings( + UniqueValues( tiles, lambda, sort, diff --git a/src/opengl/main/UniquifyPupu.cpp b/src/opengl/ff_8/ff_8/UniquifyPupu.cpp similarity index 100% rename from src/opengl/main/UniquifyPupu.cpp rename to src/opengl/ff_8/ff_8/UniquifyPupu.cpp diff --git a/src/opengl/main/UniquifyPupu.hpp b/src/opengl/ff_8/ff_8/UniquifyPupu.hpp similarity index 100% rename from src/opengl/main/UniquifyPupu.hpp rename to src/opengl/ff_8/ff_8/UniquifyPupu.hpp diff --git a/src/opengl/main/utilities.cpp b/src/opengl/ff_8/ff_8/Utilities.cpp similarity index 97% rename from src/opengl/main/utilities.cpp rename to src/opengl/ff_8/ff_8/Utilities.cpp index 009f2821..80dcc101 100644 --- a/src/opengl/main/utilities.cpp +++ b/src/opengl/ff_8/ff_8/Utilities.cpp @@ -1,8 +1,8 @@ -#include "utilities.hpp" +#include "Utilities.hpp" #include #include #include -namespace fme +namespace ff_8 { // Explicit instantiation for specific types template bool sort_and_remove_duplicates( @@ -81,4 +81,4 @@ bool has_balanced_braces([[maybe_unused]] const std::u8string_view s) return true; } -}// namespace fme +}// namespace ff_8 diff --git a/src/opengl/main/utilities.hpp b/src/opengl/ff_8/ff_8/Utilities.hpp similarity index 91% rename from src/opengl/main/utilities.hpp rename to src/opengl/ff_8/ff_8/Utilities.hpp index 0a82f762..1c541b65 100644 --- a/src/opengl/main/utilities.hpp +++ b/src/opengl/ff_8/ff_8/Utilities.hpp @@ -9,8 +9,39 @@ #include #include -namespace fme +namespace ff_8 { +template +concept is_enum = std::is_enum_v; +template +concept is_enum_or_integral = is_enum || std::integral; +template< + is_enum_or_integral number_type, + is_enum_or_integral... rest_number_type> +inline static constexpr number_type bitwise_or( + number_type first, + rest_number_type... rest) +{ + return static_cast( + static_cast(first) + | (static_cast(rest) | ...)); +} +template< + is_enum_or_integral number_type, + is_enum_or_integral... rest_number_type> +inline static constexpr number_type bitwise_and( + number_type start, + rest_number_type... rest) +{ + return static_cast( + static_cast(start) + & (static_cast(rest) & ...)); +} +template +inline static constexpr number_type bitwise_not(number_type value) +{ + return static_cast(~static_cast(value)); +} template< std::size_t N, typename F> @@ -154,8 +185,6 @@ constexpr inline bool remove_empty_values(R &...ranges) return false; } -#include - template inline bool remove_nonexistent_paths( const bool remove_on_error, @@ -332,6 +361,6 @@ constexpr inline auto generate_combinations(const rangeT &pupu_ids) return CombinationRange{ generate_combinations_64bit(pupu_ids) }; } -}// namespace fme +}// namespace ff_8 #endif /* B24A24CC_B3E6_4D3F_AFB1_C86F174A1902 */ diff --git a/src/opengl/glengine/glengine/BlendModeGeneric.hpp b/src/opengl/glengine/glengine/BlendModeGeneric.hpp index a5971fca..aa36b510 100644 --- a/src/opengl/glengine/glengine/BlendModeGeneric.hpp +++ b/src/opengl/glengine/glengine/BlendModeGeneric.hpp @@ -4,7 +4,7 @@ #ifndef FIELD_MAP_EDITOR_BLENDMODEGENERIC_HPP #define FIELD_MAP_EDITOR_BLENDMODEGENERIC_HPP -#include +#include namespace glengine { template @@ -78,7 +78,7 @@ class BlendModeGenerics bool changed = false; for (std::size_t i = 0U; i != std::ranges::size(labels); ++i) { - if (glengine::GenericCombo( + if (imgui_utils::GenericCombo( labels[i].data(), m_selections[i], UsedSelectionsT::selection_strings)) diff --git a/src/opengl/glengine/glengine/Layer/LayerItem.cpp b/src/opengl/glengine/glengine/Layer/LayerItem.cpp index 0cfa771f..130d0f44 100644 --- a/src/opengl/glengine/glengine/Layer/LayerItem.cpp +++ b/src/opengl/glengine/glengine/Layer/LayerItem.cpp @@ -25,6 +25,34 @@ void Layer::Item::on_im_gui_update() const return m_impl->on_im_gui_update(); } } +void Layer::Item::on_im_gui_file_menu() const +{ + if (m_impl) + { + return m_impl->on_im_gui_file_menu(); + } +} +void Layer::Item::on_im_gui_edit_menu() const +{ + if (m_impl) + { + return m_impl->on_im_gui_edit_menu(); + } +} +void Layer::Item::on_im_gui_window_menu() const +{ + if (m_impl) + { + return m_impl->on_im_gui_window_menu(); + } +} +void Layer::Item::on_im_gui_help_menu() const +{ + if (m_impl) + { + return m_impl->on_im_gui_help_menu(); + } +} void Layer::Item::on_event(const event::Item &e) const { if (m_impl) diff --git a/src/opengl/glengine/glengine/Layer/LayerItem.hpp b/src/opengl/glengine/glengine/Layer/LayerItem.hpp index eb4dcd61..baf48a17 100644 --- a/src/opengl/glengine/glengine/Layer/LayerItem.hpp +++ b/src/opengl/glengine/glengine/Layer/LayerItem.hpp @@ -29,44 +29,79 @@ namespace Layer virtual void on_update(float) const = 0; virtual void on_render() const = 0; virtual void on_im_gui_update() const = 0; + virtual void on_im_gui_file_menu() const = 0; + virtual void on_im_gui_edit_menu() const = 0; + virtual void on_im_gui_window_menu() const = 0; + virtual void on_im_gui_help_menu() const = 0; virtual void on_event(const event::Item &) const = 0; }; template class ItemModel final : public ItemConcept { public: - ItemModel(renderableT t) - : m_renderable(std::move(t)) + template + ItemModel(Args &&...args) + : m_renderable(std::forward(args)...) { } void on_update(float ts) const final { - return m_renderable.on_update(ts); + (void)OnUpdate(m_renderable, ts); } void on_render() const final { - return m_renderable.on_render(); + (void)OnRender(m_renderable); } void on_im_gui_update() const final { - return m_renderable.on_im_gui_update(); + (void)OnImGuiUpdate(m_renderable); + } + void on_im_gui_file_menu() const final + { + (void)OnImGuiFileMenu(m_renderable); + } + void on_im_gui_edit_menu() const final + { + (void)OnImGuiEditMenu(m_renderable); + } + void on_im_gui_window_menu() const final + { + (void)OnImGuiWindowMenu(m_renderable); + } + void on_im_gui_help_menu() const final + { + (void)OnImGuiHelpMenu(m_renderable); } void on_event(const event::Item &e) const final { - return m_renderable.on_event(e); + (void)OnEvent(m_renderable, e); } ItemModel() = default; + auto *get() + { + return &m_renderable; + } + + const auto *get() const + { + return &m_renderable; + } + private: renderableT m_renderable; }; - mutable std::unique_ptr m_impl{ nullptr }; + mutable std::unique_ptr m_impl{ nullptr }; public: void on_update(float) const; void on_render() const; void on_im_gui_update() const; + void on_im_gui_file_menu() const; + void on_im_gui_edit_menu() const; + void on_im_gui_window_menu() const; + void on_im_gui_help_menu() const; void on_event(const event::Item &e) const; Item() : m_impl(nullptr) @@ -76,7 +111,7 @@ namespace Layer typename T, typename... argsT> Item( - std::in_place_type_t, + const std::in_place_type_t &, argsT &&...args) : m_impl( std::make_unique>>( @@ -95,8 +130,21 @@ namespace Layer Item &operator=(const Item &other) = delete; Item(Item &&other) noexcept = default; Item &operator=(Item &&other) noexcept = default; - operator bool() const; + template + T *get() + { + if (auto ptr = dynamic_cast *>(m_impl.get())) + return ptr->get(); + return nullptr; + } + template + const T *get() const + { + if (auto ptr = dynamic_cast *>(m_impl.get())) + return ptr->get(); + return nullptr; + } }; }// namespace Layer }// namespace glengine diff --git a/src/opengl/glengine/glengine/Layer/LayerStack.cpp b/src/opengl/glengine/glengine/Layer/LayerStack.cpp index 9c82745d..2383d795 100644 --- a/src/opengl/glengine/glengine/Layer/LayerStack.cpp +++ b/src/opengl/glengine/glengine/Layer/LayerStack.cpp @@ -19,6 +19,34 @@ void Layer::Stack::on_im_gui_update() const layer.on_im_gui_update(); } } +void Layer::Stack::on_im_gui_file_menu() const +{ + for (const Item &layer : m_layers) + { + layer.on_im_gui_file_menu(); + } +} +void Layer::Stack::on_im_gui_edit_menu() const +{ + for (const Item &layer : m_layers) + { + layer.on_im_gui_edit_menu(); + } +} +void Layer::Stack::on_im_gui_window_menu() const +{ + for (const Item &layer : m_layers) + { + layer.on_im_gui_window_menu(); + } +} +void Layer::Stack::on_im_gui_help_menu() const +{ + for (const Item &layer : m_layers) + { + layer.on_im_gui_help_menu(); + } +} void Layer::Stack::on_update(float delta_time) const { for (const Item &layer : m_layers) diff --git a/src/opengl/glengine/glengine/Layer/LayerStack.hpp b/src/opengl/glengine/glengine/Layer/LayerStack.hpp index 698d650c..8eaa3459 100644 --- a/src/opengl/glengine/glengine/Layer/LayerStack.hpp +++ b/src/opengl/glengine/glengine/Layer/LayerStack.hpp @@ -31,17 +31,54 @@ namespace Layer void on_update(float) const; void on_render() const; void on_im_gui_update() const; + void on_im_gui_file_menu() const; + void on_im_gui_edit_menu() const; + void on_im_gui_window_menu() const; + void on_im_gui_help_menu() const; void on_event(const event::Item &) const; - template - void emplace_layers(T &&...args) const + // emplace_front for layers + template< + RenderableOrInplaceRenderable FirstT, + typename... T> + void emplace_layers( + FirstT &&first, + T &&...args) const { - end_of_layers - = m_layers.emplace(end_of_layers, std::forward(args)...); + end_of_layers = m_layers.emplace( + end_of_layers, + std::forward(first), + std::forward(args)...); } - template - void emplace_overlays(T &&...args) const + // emplace_back for overlays + + template< + RenderableOrInplaceRenderable FirstT, + typename... T> + void emplace_overlays( + FirstT &&first, + T &&...args) const + { + m_layers.emplace_back( + std::forward(first), std::forward(args)...); + end_of_layers = std::ranges::begin(m_layers); + } + + template + T *get() + { + for (auto &item : m_layers) + if (auto ptr = item.get()) + return ptr; + return nullptr; + } + + template + const T *get() const { - m_layers.emplace_back(std::forward(args)...); + for (auto &item : m_layers) + if (auto ptr = item.get()) + return ptr; + return nullptr; } private: diff --git a/src/opengl/glengine/glengine/Renderable.hpp b/src/opengl/glengine/glengine/Renderable.hpp index 4b6b541a..38729b63 100644 --- a/src/opengl/glengine/glengine/Renderable.hpp +++ b/src/opengl/glengine/glengine/Renderable.hpp @@ -4,6 +4,7 @@ #ifndef FIELD_MAP_EDITOR_RENDERABLE_HPP #define FIELD_MAP_EDITOR_RENDERABLE_HPP +#include "concepts.hpp" namespace glengine { namespace event @@ -11,63 +12,144 @@ namespace event class Item; } template -concept Renderable = - std::default_initializable && std::movable &&( - requires(const T &t, const event::Item & e) - { - { - t.on_im_gui_update() - } -> std::same_as; - { - t.on_update(float{}) - } -> Void; - { - t.on_render() - } -> Void; - { - t.on_event(e) - } -> Void; - } || - requires(const T &t, const event::Item & e) - { - { - t.on_im_gui_update() - } -> Void; - { - t.on_update(float{}) - } -> Void; - { - t.on_render() - } -> Void; - { - t.on_event(e) - } -> Void; - }); +concept HasOnUpdate = requires(const T &t, float ts) { + { t.on_update(ts) } -> Void; +}; + +template +concept HasOnRender = requires(const T &t) { + { t.on_render() } -> Void; +}; + +template +concept HasOnEvent = requires(const T &t, const event::Item &e) { + { t.on_event(e) } -> Void; +}; + + +template +concept HasOnImGuiUpdate = requires(const T &t) { + { t.on_im_gui_update() } -> std::same_as; +} || requires(const T &t) { + { t.on_im_gui_update() } -> Void; +}; + +template +concept HasOnImGuiFileMenu = requires(const T &t) { + { t.on_im_gui_file_menu() } -> std::same_as; +} || requires(const T &t) { + { t.on_im_gui_file_menu() } -> Void; +}; + +template +concept HasOnImGuiEditMenu = requires(const T &t) { + { t.on_im_gui_edit_menu() } -> std::same_as; +} || requires(const T &t) { + { t.on_im_gui_edit_menu() } -> Void; +}; + +template +concept HasOnImGuiWindowMenu = requires(const T &t) { + { t.on_im_gui_window_menu() } -> std::same_as; +} || requires(const T &t) { + { t.on_im_gui_window_menu() } -> Void; +}; + +template +concept HasOnImGuiHelpMenu = requires(const T &t) { + { t.on_im_gui_help_menu() } -> std::same_as; +} || requires(const T &t) { + { t.on_im_gui_help_menu() } -> Void; +}; + +template +concept Renderable + = std::movable + && (HasOnUpdate || HasOnRender || HasOnEvent || HasOnImGuiUpdate || HasOnImGuiFileMenu || HasOnImGuiEditMenu || HasOnImGuiWindowMenu || HasOnImGuiHelpMenu); + +template +struct inplace_type_extract +{ + using type = void; +}; + +template +struct inplace_type_extract> +{ + using type = U; +}; + +template +concept RenderableOrInplaceRenderable + = (std::is_void_v>::type> + && glengine::Renderable>) + || (requires { + typename inplace_type_extract>::type; + } && glengine::Renderable>::type>>); +// std::default_initializable && +// I donno if I really need this. + // free function overloads for the member functions. template inline auto OnImGuiUpdate(const T &t) { - return t.on_im_gui_update(); + if constexpr (HasOnImGuiUpdate) + return t.on_im_gui_update(); } + template inline auto OnUpdate( - const T &t, - const float ts) + const T &t, + float ts) { - return t.on_update(ts); + if constexpr (HasOnUpdate) + return t.on_update(ts); } + template inline auto OnRender(const T &t) { - return t.on_render(); + if constexpr (HasOnRender) + return t.on_render(); } + template inline auto OnEvent( const T &t, const event::Item &e) { - return t.on_event(e); + if constexpr (HasOnEvent) + return t.on_event(e); +} + +template +inline auto OnImGuiFileMenu(const T &t) +{ + if constexpr (HasOnImGuiFileMenu) + return t.on_im_gui_file_menu(); +} + +template +inline auto OnImGuiEditMenu(const T &t) +{ + if constexpr (HasOnImGuiEditMenu) + return t.on_im_gui_edit_menu(); +} + +template +inline auto OnImGuiWindowMenu(const T &t) +{ + if constexpr (HasOnImGuiWindowMenu) + return t.on_im_gui_window_menu(); } + +template +inline auto OnImGuiHelpMenu(const T &t) +{ + if constexpr (HasOnImGuiHelpMenu) + return t.on_im_gui_help_menu(); +} + }// namespace glengine #endif// FIELD_MAP_EDITOR_RENDERABLE_HPP diff --git a/src/opengl/imgui_utils/CMakeLists.txt b/src/opengl/imgui_utils/CMakeLists.txt new file mode 100644 index 00000000..6100d3ee --- /dev/null +++ b/src/opengl/imgui_utils/CMakeLists.txt @@ -0,0 +1,80 @@ +cmake_minimum_required(VERSION 3.18) +include(${CMAKE_SOURCE_DIR}/cmake/OpenVIII_CPP_WIP.cmake) +include(CheckIPOSupported) +check_ipo_supported(RESULT supported OUTPUT error) +find_package(tomlplusplus CONFIG REQUIRED) +find_package(Threads REQUIRED) +find_package(fmt REQUIRED) +find_package(spdlog REQUIRED) +find_package(imgui CONFIG REQUIRED) +find_package(clip CONFIG REQUIRED) +add_library( + ${PROJECT_NAME}_imgui_utils STATIC + #... tbd + imgui_utils/ImGuiPushID.cpp + ) + +if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + target_link_libraries(${PROJECT_NAME}_imgui_utils PUBLIC stdc++exp) +endif() +target_compile_features( + ${PROJECT_NAME}_imgui_utils + PUBLIC cxx_std_23 + PUBLIC cxx_std_20) +target_link_libraries( + ${PROJECT_NAME}_imgui_utils + PUBLIC project_warnings + PUBLIC imgui_filebrowser + PUBLIC imgui::imgui + PUBLIC clip::clip + PUBLIC ImGuizmo + PUBLIC glengine + PUBLIC spdlog::spdlog + #PUBLIC tomlplusplus::tomlplusplus + PUBLIC Threads::Threads) +target_include_directories(${PROJECT_NAME}_imgui_utils PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) + +if(MSVC) + target_compile_definitions(${PROJECT_NAME}_imgui_utils PUBLIC _CRT_SECURE_NO_WARNINGS + )# required by libpng + target_compile_options(${PROJECT_NAME}_imgui_utils + PUBLIC "/bigobj" + PUBLIC "/Qpar" + PUBLIC "/MP" + ) + # target_link_options(${PROJECT_NAME}_imgui_utils PUBLIC "/PROFILE") +elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + target_compile_options(${PROJECT_NAME}_imgui_utils PUBLIC "-fconcepts-diagnostics-depth=2") +elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + target_compile_options( + ${PROJECT_NAME}_imgui_utils + PUBLIC "-stdlib=libc++" + # PUBLIC "-march=native" + PUBLIC "-fexperimental-library" # new in clang15 for things like std::ranges + # and std::format + ) + target_link_options( + ${PROJECT_NAME}_imgui_utils + PUBLIC + "-stdlib=libc++" + # PUBLIC "-fuse-ld=lld" PUBLIC "-Wl" + PUBLIC + "-fexperimental-library" # new in clang15 for things like std::ranges and + # std::format + PUBLIC + "-v") # ,--gdb-index +endif() + +target_compile_definitions( + ${PROJECT_NAME}_imgui_utils + PUBLIC NOMINMAX # imgui uses unguarded min and max. + PUBLIC TOML_EXCEPTIONS=0 + PUBLIC TOML_HEADER_ONLY=1 +) + +if(supported) + message(STATUS "IPO / LTO enabled") + set_target_properties(${PROJECT_NAME}_imgui_utils PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE) +else() + message(STATUS "IPO / LTO not supported: <${error}>") +endif() diff --git a/src/opengl/glengine/glengine/GenericCombo.hpp b/src/opengl/imgui_utils/imgui_utils/GenericCombo.hpp similarity index 75% rename from src/opengl/glengine/glengine/GenericCombo.hpp rename to src/opengl/imgui_utils/imgui_utils/GenericCombo.hpp index 3b7275d5..a4767518 100644 --- a/src/opengl/glengine/glengine/GenericCombo.hpp +++ b/src/opengl/imgui_utils/imgui_utils/GenericCombo.hpp @@ -8,8 +8,10 @@ #include "ImGuiDisabled.hpp" #include "ImGuiPushID.hpp" #include "ImGuiPushItemWidth.hpp" +#include +#include #include -namespace glengine +namespace imgui_utils { template @@ -31,13 +33,13 @@ template const ImGuiStyle &style = ImGui::GetStyle(); const float spacing = style.ItemInnerSpacing.x; { - const auto pop_0 = glengine::ImGuiPushId(); + const auto pop_0 = imgui_utils::ImGuiPushId(); const float width = ImGui::CalcItemWidth() - sub_width; const float button_size = ImGui::GetFrameHeight(); - const auto pop_width = glengine::ImGuiPushItemWidth( + const auto pop_width = imgui_utils::ImGuiPushItemWidth( width - spacing * 2.0f - button_size * 2.0f); const auto disabled - = glengine::ImGuiDisabled(std::ranges::empty(data)); + = imgui_utils::ImGuiDisabled(std::ranges::empty(data)); static constexpr auto c_str = [](auto &&v) { @@ -77,8 +79,24 @@ template const auto end = glengine::ScopeGuard{ &ImGui::EndCombo }; for (int i{}; const auto &map : data) { + if (c_str(map) == nullptr) + { + spdlog::warn( + "GenericCombo: encountered null c_str entry, " + "skipping, at index: {}", + i); + continue; + } + if (std::ranges::empty(map)) + { + spdlog::warn( + "GenericCombo: encountered empty string entry, " + "skipping, at index: {}", + i); + continue; + } const bool is_selected = i == current_index; - const auto pop_1 = glengine::ImGuiPushId(); + const auto pop_1 = imgui_utils::ImGuiPushId(); if (ImGui::Selectable(c_str(map), is_selected)) { current_index = i; @@ -93,9 +111,9 @@ template } } { - const auto pop = glengine::ImGuiPushId(); + const auto pop = imgui_utils::ImGuiPushId(); ImGui::SameLine(0, spacing); - const auto disabled = glengine::ImGuiDisabled( + const auto disabled = imgui_utils::ImGuiDisabled( std::cmp_less_equal(current_index, 0) || std::cmp_greater_equal( current_index - 1, std::ranges::size(data))); @@ -106,9 +124,9 @@ template } } { - const auto pop = glengine::ImGuiPushId(); + const auto pop = imgui_utils::ImGuiPushId(); ImGui::SameLine(0, spacing); - const auto disabled = glengine::ImGuiDisabled( + const auto disabled = imgui_utils::ImGuiDisabled( std::cmp_greater_equal(current_index + 1, std::ranges::size(data))); if (ImGui::ArrowButton("##r", ImGuiDir_Right)) { @@ -120,5 +138,5 @@ template ImGui::Text("%s", label); return changed; } -}// namespace glengine +}// namespace imgui_utils #endif// FIELD_MAP_EDITOR_GENERICCOMBO_HPP diff --git a/src/opengl/main/gui/ImGuiDisabled.hpp b/src/opengl/imgui_utils/imgui_utils/ImGuiDisabled.hpp similarity index 89% rename from src/opengl/main/gui/ImGuiDisabled.hpp rename to src/opengl/imgui_utils/imgui_utils/ImGuiDisabled.hpp index bafe3fe5..6c93c8eb 100644 --- a/src/opengl/main/gui/ImGuiDisabled.hpp +++ b/src/opengl/imgui_utils/imgui_utils/ImGuiDisabled.hpp @@ -4,7 +4,7 @@ #define B99BEDA4_8B05_47FE_B03E_4AC0C8FF90EE #include #include -namespace fme +namespace imgui_utils { [[nodiscard]] inline auto ImGuiDisabled(bool disabled) noexcept { @@ -12,5 +12,5 @@ namespace fme ImGui::BeginDisabled(disabled); return glengine::ScopeGuard{ &ImGui::EndDisabled }; } -}// namespace fme +}// namespace imgui_utils #endif /* B99BEDA4_8B05_47FE_B03E_4AC0C8FF90EE */ diff --git a/src/opengl/experimental/ImGuiIndent.hpp b/src/opengl/imgui_utils/imgui_utils/ImGuiIndent.hpp similarity index 89% rename from src/opengl/experimental/ImGuiIndent.hpp rename to src/opengl/imgui_utils/imgui_utils/ImGuiIndent.hpp index 61d3d2e0..e63594b8 100644 --- a/src/opengl/experimental/ImGuiIndent.hpp +++ b/src/opengl/imgui_utils/imgui_utils/ImGuiIndent.hpp @@ -6,7 +6,7 @@ #define FIELD_MAP_EDITOR_IMGUIINDENT_HPP #include #include -namespace glengine +namespace imgui_utils { [[nodiscard]] inline auto ImGuiIndent(float width = 0.F) noexcept @@ -14,5 +14,5 @@ namespace glengine ImGui::Indent(width); return glengine::ScopeGuard{ [=]() { ImGui::Unindent(width); } }; } -}// namespace glengine +}// namespace imgui_utils #endif// FIELD_MAP_EDITOR_IMGUIINDENT_HPP diff --git a/src/opengl/imgui_utils/imgui_utils/ImGuiPushID.cpp b/src/opengl/imgui_utils/imgui_utils/ImGuiPushID.cpp new file mode 100644 index 00000000..70947a36 --- /dev/null +++ b/src/opengl/imgui_utils/imgui_utils/ImGuiPushID.cpp @@ -0,0 +1,26 @@ +// +// Created by pcvii on 1/18/2022. +// +#include "ImGuiPushID.hpp" + +[[nodiscard]] static int &get_imgui_id() +{ + static int imgui_id = {}; + return imgui_id; +} +void imgui_utils::impl::ImGuiPushId::reset() const noexcept +{ + get_imgui_id() = {}; +} + +int imgui_utils::impl::ImGuiPushId::id() const noexcept +{ + return get_imgui_id(); +} + +glengine::ScopeGuard + imgui_utils::impl::ImGuiPushId::operator()() const noexcept +{ + ImGui::PushID(++get_imgui_id()); + return glengine::ScopeGuard{ &ImGui::PopID }; +} diff --git a/src/opengl/imgui_utils/imgui_utils/ImGuiPushID.hpp b/src/opengl/imgui_utils/imgui_utils/ImGuiPushID.hpp new file mode 100644 index 00000000..993b607e --- /dev/null +++ b/src/opengl/imgui_utils/imgui_utils/ImGuiPushID.hpp @@ -0,0 +1,39 @@ +// +// Created by pcvii on 1/18/2022. +// + +#ifndef FIELD_MAP_EDITOR_IMGUIPUSHID_HPP +#define FIELD_MAP_EDITOR_IMGUIPUSHID_HPP +#include +#include +namespace imgui_utils +{ +namespace impl +{ + /** + * Wrapper for ImGui::PushID(int) that increments an int and returns a + * scope guarded ImGui::PopID() that will automatically Pop when the scope + * ends. + */ + class [[nodiscard]] ImGuiPushId final + { + public: + /** + * ImGui::PushID(int) and increment int. + * @return ImGui::PopID() wrapped in a scope guard. + */ + [[nodiscard]] glengine::ScopeGuard + operator()() const noexcept; + /** + * reset() must be called once per frame usually at the beginning or + * the end. It resets an int to 0. + */ + void reset() const noexcept; + + int id() const noexcept; + }; +}// namespace impl +static constexpr inline impl::ImGuiPushId ImGuiPushId = {}; + +}// namespace imgui_utils +#endif// FIELD_MAP_EDITOR_IMGUIPUSHID_HPP diff --git a/src/opengl/experimental/ImGuiPushItemWidth.hpp b/src/opengl/imgui_utils/imgui_utils/ImGuiPushItemWidth.hpp similarity index 77% rename from src/opengl/experimental/ImGuiPushItemWidth.hpp rename to src/opengl/imgui_utils/imgui_utils/ImGuiPushItemWidth.hpp index 04cd16bf..b77ff82f 100644 --- a/src/opengl/experimental/ImGuiPushItemWidth.hpp +++ b/src/opengl/imgui_utils/imgui_utils/ImGuiPushItemWidth.hpp @@ -6,12 +6,12 @@ #define FIELD_MAP_EDITOR_IMGUIPUSHITEMWIDTH_HPP #include #include -namespace glengine +namespace imgui_utils { [[nodiscard]] inline auto ImGuiPushItemWidth(float item_width) noexcept { ImGui::PushItemWidth(item_width); - return ScopeGuard{ &ImGui::PopItemWidth }; + return glengine::ScopeGuard{ &ImGui::PopItemWidth }; } -}// namespace glengine +}// namespace imgui_utils #endif// FIELD_MAP_EDITOR_IMGUIPUSHITEMWIDTH_HPP diff --git a/src/opengl/experimental/ImGuiPushStyleVar.hpp b/src/opengl/imgui_utils/imgui_utils/ImGuiPushStyleVar.hpp similarity index 75% rename from src/opengl/experimental/ImGuiPushStyleVar.hpp rename to src/opengl/imgui_utils/imgui_utils/ImGuiPushStyleVar.hpp index 2cbeab19..257e2ade 100644 --- a/src/opengl/experimental/ImGuiPushStyleVar.hpp +++ b/src/opengl/imgui_utils/imgui_utils/ImGuiPushStyleVar.hpp @@ -6,7 +6,7 @@ #define FIELD_MAP_EDITOR_IMGUIPUSHSTYLEVAR_HPP #include #include -namespace glengine +namespace imgui_utils { [[maybe_unused]] [[nodiscard]] inline auto ImGuiPushStyleVar( @@ -14,15 +14,15 @@ namespace glengine float val) noexcept { ImGui::PushStyleVar(style, val); - return ScopeGuard{ []() { ImGui::PopStyleVar(); } }; + return glengine::ScopeGuard{ []() { ImGui::PopStyleVar(); } }; } [[maybe_unused]] [[nodiscard]] inline auto ImGuiPushStyleVar( ImGuiStyleVar style, const ImVec2 &val) noexcept { ImGui::PushStyleVar(style, val); - return ScopeGuard{ []() { ImGui::PopStyleVar(); } }; + return glengine::ScopeGuard{ []() { ImGui::PopStyleVar(); } }; } -}// namespace glengine +}// namespace imgui_utils #endif// FIELD_MAP_EDITOR_IMGUIPUSHSTYLEVAR_HPP diff --git a/src/opengl/main/CMakeLists.txt b/src/opengl/main/CMakeLists.txt index b32c7d5f..2e093c9a 100644 --- a/src/opengl/main/CMakeLists.txt +++ b/src/opengl/main/CMakeLists.txt @@ -34,33 +34,24 @@ set(MAIN_SOURCES gui/keyboard_shortcuts_window.cpp gui/image_compare_window.cpp gui/import.cpp + gui/LoggingWindow.cpp gui/main_menu_paths.cpp gui/mouse_positions.cpp - gui/push_pop_id.cpp gui/Selections.cpp gui/textures_window.cpp gui/tool_tip.cpp - archives_group.cpp - Configuration.cpp formatters.cpp future_operations.cpp generic_combo.cpp main.cpp - map_group.cpp map_operation.cpp - MapHistory.cpp map_sprite.cpp mim_sprite.cpp open_file_explorer.cpp path_search.cpp - PupuID.cpp - safedir.cpp save_image_pbo.cpp - source_tile_conflicts.cpp tile_sizes.cpp - unique_values.cpp - UniquifyPupu.cpp - utilities.cpp) +) if(WIN32 AND NOT CMAKE_BUILD_TYPE STREQUAL "Debug") add_executable(${PROJECT_NAME}_MAIN WIN32 ${MAIN_SOURCES}) @@ -69,7 +60,6 @@ else() endif() # set_property(TARGET ${PROJECT_NAME}_MAIN PROPERTY CXX_STANDARD 20) -find_package(tomlplusplus CONFIG REQUIRED) find_package(spdlog REQUIRED) find_package(GLEW REQUIRED) find_package(glfw3 CONFIG REQUIRED) @@ -84,9 +74,15 @@ target_include_directories(${PROJECT_NAME}_MAIN_COMMON INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) string(TOLOWER "${PROJECT_NAME}" main_exec) - set_target_properties(${PROJECT_NAME}_MAIN PROPERTIES OUTPUT_NAME "${main_exec}") +target_compile_definitions( + ${PROJECT_NAME}_MAIN + PUBLIC NOMINMAX # imgui uses unguarded min and max. + PUBLIC DEFAULT_CONFIG_PATH="${DEFAULT_CONFIG_ROOT_PATH}/${main_exec}.toml" + PUBLIC DEFAULT_IMGUI_INI_PATH="${DEFAULT_CONFIG_ROOT_PATH}/${main_exec}_imgui.ini" + PUBLIC DEFAULT_LOG_PATH="${DEFAULT_CONFIG_ROOT_PATH}/${main_exec}.log" + ) target_link_libraries( ${PROJECT_NAME}_MAIN PRIVATE project_warnings @@ -96,6 +92,8 @@ target_link_libraries( PRIVATE glfw PRIVATE OpenGL::GL PRIVATE glengine + PRIVATE ${PROJECT_NAME}_ff_8 + PRIVATE ${PROJECT_NAME}_imgui_utils PRIVATE OpenVIII_CPP_WIP_VIIIPaths PRIVATE OpenVIII_CPP_WIP_VIIIArchive PRIVATE OpenVIII_CPP_WIP_VIIIGraphics @@ -108,10 +106,6 @@ target_link_libraries( PRIVATE clip::clip PRIVATE ${PROJECT_NAME}_MAIN_COMMON) -target_compile_definitions( - ${PROJECT_NAME}_MAIN - PUBLIC NOMINMAX # imgui uses unguarded min and max. - PUBLIC TOML_EXCEPTIONS=0) target_compile_features( ${PROJECT_NAME}_MAIN diff --git a/src/opengl/main/draw_bit_t.hpp b/src/opengl/main/draw_bit_t.hpp deleted file mode 100644 index f0e825cc..00000000 --- a/src/opengl/main/draw_bit_t.hpp +++ /dev/null @@ -1,41 +0,0 @@ -// -// Created by pcvii on 1/1/2025. -// - -#ifndef FIELD_MAP_EDITOR_DRAW_BIT_T_HPP -#define FIELD_MAP_EDITOR_DRAW_BIT_T_HPP -#include -namespace ff_8 -{ -enum struct draw_bitT -{ - all = 0, - disabled = 1, - enabled = 2, -}; - -static inline constexpr bool operator==( - draw_bitT left, - bool right) noexcept -{ - return (std::to_underlying(left) == std::to_underlying(draw_bitT::all)) - || (std::to_underlying(left) == std::to_underlying(draw_bitT::disabled) && !right) - || (std::to_underlying(left) == std::to_underlying(draw_bitT::enabled) && right); -} -static inline constexpr bool operator==( - bool left, - draw_bitT right) noexcept -{ - return operator==(right, left); -} -static inline constexpr bool operator==( - draw_bitT lhs, - draw_bitT rhs) noexcept -{ - return std::to_underlying(lhs) == std::to_underlying(draw_bitT::all) - || std::to_underlying(rhs) == std::to_underlying(draw_bitT::all) - || std::to_underlying(lhs) == std::to_underlying(rhs); -} - -};// namespace ff_8 -#endif \ No newline at end of file diff --git a/src/opengl/main/formatters.hpp b/src/opengl/main/formatters.hpp index a2ef6474..110ec830 100644 --- a/src/opengl/main/formatters.hpp +++ b/src/opengl/main/formatters.hpp @@ -4,13 +4,12 @@ #ifndef FIELD_MAP_EDITOR_FORMATTERS_HPP #define FIELD_MAP_EDITOR_FORMATTERS_HPP -#include "draw_bit_t.hpp" -#include "gui/colors.hpp" +#include "gui/BackgroundSettings.hpp" #include "gui/compact_type.hpp" #include "gui/draw_mode.hpp" #include "gui/gui_labels.hpp" -#include "normalized_source_tile.hpp" #include "tile_sizes.hpp" +#include #include #include #include @@ -21,139 +20,88 @@ #include #include -namespace ff_8 -{ -template -static constexpr auto to_hex(const tileT &tile) -{ - constexpr auto to_hex_operation - = [](const std::uint8_t input_byte, const auto operation) -> char - { - constexpr std::uint8_t number_of_values_in_nibble = 16U; - constexpr char threshold_of_A_to_F = 10; - char const half_transformed_char = static_cast( - operation(input_byte, number_of_values_in_nibble)); - return static_cast( - (half_transformed_char < threshold_of_A_to_F - ? half_transformed_char + '0' - : half_transformed_char - threshold_of_A_to_F + 'A')); - }; - const auto raw_bytes - = std::bit_cast>(tile); - std::array raw_hex{}; - raw_hex.back() = '\0'; - auto rhi = raw_hex.begin(); - for (const std::uint8_t current_byte : raw_bytes) - { - *rhi = to_hex_operation(current_byte, std::divides{}); - std::advance(rhi, 1); - *rhi = to_hex_operation(current_byte, std::modulus{}); - std::advance(rhi, 1); - } - return raw_hex; -} -}// namespace ff_8 template<> -struct fmt::formatter : fmt::formatter +struct fmt::formatter + : fmt::formatter { - // tile_sizes::default_size, tile_sizes::x_2_size, tile_sizes::x_4_size, - // tile_sizes::x_8_size, tile_sizes::x_16_size // parse is inherited from formatter. template constexpr auto format( - tile_sizes tile_sizes_t, - FormatContext &ctx) const + spdlog::level::level_enum level_t, + FormatContext &ctx) const { using namespace open_viii::graphics::background; using namespace std::string_view_literals; std::string_view name = {}; - switch (tile_sizes_t) + switch (level_t) { - case tile_sizes::default_size: - name = "1x 16 px"sv; + case spdlog::level::trace: + name = "Trace"sv; break; - case tile_sizes::x_2_size: - name = "2x 32 px"sv; + case spdlog::level::debug: + name = "Debug"sv; break; - case tile_sizes::x_4_size: - name = "4x 64 px"sv; + case spdlog::level::info: + name = "Info"sv; break; - case tile_sizes::x_8_size: - name = "8x 128 px"sv; + case spdlog::level::warn: + name = "Warn"sv; break; - case tile_sizes::x_16_size: - name = "16x 256 px"sv; + case spdlog::level::err: + name = "Error"sv; break; - } - return fmt::formatter::format(name, ctx); - } -}; - -template<> -struct fmt::formatter : fmt::formatter -{ - // parse is inherited from formatter. - template - constexpr auto format( - ff_8::draw_bitT draw_bit_t, - FormatContext &ctx) const - { - using namespace open_viii::graphics::background; - using namespace std::string_view_literals; - std::string_view name = {}; - switch (draw_bit_t) - { - case ff_8::draw_bitT::all: - name = "all"sv; + case spdlog::level::critical: + name = "Critical"sv; break; - case ff_8::draw_bitT::disabled: - name = "disabled"sv; + case spdlog::level::off: + name = "Off"sv; break; - case ff_8::draw_bitT::enabled: - name = "enabled"sv; + default: + name = "Unknown"sv; break; } return fmt::formatter::format(name, ctx); } }; + template<> -struct fmt::formatter - : fmt::formatter +struct fmt::formatter : fmt::formatter { - // parse is inherited from formatter. + // tile_sizes::default_size, tile_sizes::x_2_size, tile_sizes::x_4_size, + // tile_sizes::x_8_size, tile_sizes::x_16_size + // parse is inherited from formatter. template constexpr auto format( - open_viii::graphics::background::BlendModeT blend_mode_t, - FormatContext &ctx) const + tile_sizes tile_sizes_t, + FormatContext &ctx) const { using namespace open_viii::graphics::background; using namespace std::string_view_literals; std::string_view name = {}; - switch (blend_mode_t) + switch (tile_sizes_t) { - case BlendModeT::add: - name = "add"sv; + case tile_sizes::default_size: + name = "1x 16 px"sv; break; - case BlendModeT::half_add: - name = "half add"sv; + case tile_sizes::x_2_size: + name = "2x 32 px"sv; break; - case BlendModeT::none: - name = "none"sv; + case tile_sizes::x_4_size: + name = "4x 64 px"sv; break; - case BlendModeT::quarter_add: - name = "quarter add"sv; + case tile_sizes::x_8_size: + name = "8x 128 px"sv; break; - case BlendModeT::subtract: - name = "subtract"sv; + case tile_sizes::x_16_size: + name = "16x 256 px"sv; break; } return fmt::formatter::format(name, ctx); } }; - template<> struct fmt::formatter : fmt::formatter { @@ -224,63 +172,6 @@ struct fmt::formatter : fmt::formatter } }; -template<> -struct fmt::formatter : fmt::formatter -{ - // parse is inherited from formatter. - template - constexpr auto format( - open_viii::LangT lang_t, - FormatContext &ctx) const - { - using namespace open_viii::graphics::background; - using namespace std::string_view_literals; - std::string_view name = {}; - switch (lang_t) - { - case open_viii::LangT::en: - name = open_viii::LangCommon::ENFULL; - break; - case open_viii::LangT::fr: - name = open_viii::LangCommon::FRFULL; - break; - case open_viii::LangT::de: - name = open_viii::LangCommon::DEFULL; - break; - case open_viii::LangT::it: - name = open_viii::LangCommon::ITFULL; - break; - case open_viii::LangT::es: - name = open_viii::LangCommon::ESFULL; - break; - case open_viii::LangT::jp: - name = open_viii::LangCommon::JPFULL; - break; - case open_viii::LangT::end: - case open_viii::LangT::generic: - name = "Generic"sv; - break; - } - return fmt::formatter::format(name, ctx); - } -}; - -template -struct fmt::formatter> : fmt::formatter -{ - // parse is inherited from formatter>. - template - constexpr auto format( - open_viii::graphics::Point point, - FormatContext &ctx) const - { - fmt::format_to(ctx.out(), "{}", '('); - fmt::formatter::format(point.x(), ctx); - fmt::format_to(ctx.out(), "{}", ", "); - fmt::formatter::format(point.y(), ctx); - return fmt::format_to(ctx.out(), "{}", ')'); - } -}; template<> struct fmt::formatter @@ -329,210 +220,27 @@ struct fmt::formatter } }; -template -struct fmt::formatter> - : fmt::formatter> -{ - // parse is inherited from formatter>. - template - constexpr auto format( - open_viii::graphics::Rectangle rectangle, - FormatContext &ctx) const - { - fmt::formatter>::format( - open_viii::graphics::Point{ rectangle.x(), rectangle.y() }, - ctx); - fmt::format_to(ctx.out(), "{}", ' '); - return fmt::formatter>::format( - open_viii::graphics::Point{ rectangle.width(), - rectangle.height() }, - ctx); - } -}; - -template<> -struct fmt::formatter : fmt::formatter -{ - // parse is inherited from formatter. - template - constexpr auto format( - open_viii::graphics::BPPT bppt, - FormatContext &ctx) const - { - using namespace open_viii::graphics; - using namespace std::string_view_literals; - - if (bppt.bpp8()) - { - return fmt::formatter::format(BPPT::BPP8, ctx); - } - if (bppt.bpp16()) - { - return fmt::formatter::format(BPPT::BPP16, ctx); - } - if (bppt.bpp24()) - { - return fmt::formatter::format(BPPT::BPP24, ctx); - } - return fmt::formatter::format(BPPT::BPP4, ctx); - } -}; - - -template -struct fmt::formatter : fmt::formatter -{ - // parse is inherited from formatter. - template - constexpr auto format( - const tileT &tile, - FormatContext &ctx) const - { - const auto array = ff_8::to_hex(tile); - const auto hexview = std::string_view(array.data(), array.size() - 1); - return fmt::format_to( - ctx.out(), - "{}: {}\n" - "{}: {}\n" - "{}: {}\n" - "{}: {}\n" - "{}: {}\n" - "{}: {}\n" - "{}: {}\n" - "{}: {}\n" - "{}: {}\n" - "{}: {}\n" - "{}: {}\n" - "{}: {}\n" - "{}: {}", - fme::gui_labels::hex, - hexview, - fme::gui_labels::source, - tile.source_rectangle(), - fme::gui_labels::destination, - tile.output_rectangle(), - fme::gui_labels::z, - tile.z(), - fme::gui_labels::bpp, - tile.depth(), - fme::gui_labels::palette, - tile.palette_id(), - fme::gui_labels::texture_page, - tile.texture_id(), - fme::gui_labels::layer_id, - tile.layer_id(), - fme::gui_labels::blend_mode, - tile.blend_mode(), - fme::gui_labels::blend_other, - tile.blend(), - fme::gui_labels::animation_id, - tile.animation_id(), - fme::gui_labels::animation_state, - tile.animation_state(), - fme::gui_labels::draw, - tile.draw()); - } -}; - -template<> -struct fmt::formatter - : fmt::formatter -{ - // parse is inherited from formatter. - template - constexpr auto format( - const open_viii::graphics::background::normalized_source_tile &tile, - FormatContext &ctx) const - { - const auto array = ff_8::to_hex(tile); - const auto hexview = std::string_view(array.data(), array.size() - 1); - return fmt::format_to( - ctx.out(), - "{}: {}\n" - "{}: {}\n" - "{}: {}\n" - "{}: {}\n" - "{}: {}\n" - "{}: {}\n" - "{}: {}\n" - "{}: {}\n" - "{}: {}\n" - "{}: {}\n" - "{}: {}\n" - "{}: {}", - fme::gui_labels::hex, - hexview, - fme::gui_labels::source, - tile.m_source_xy, - fme::gui_labels::bpp, - tile.m_tex_id_buffer.depth(), - fme::gui_labels::palette, - tile.m_palette_id.id(), - fme::gui_labels::texture_page, - tile.m_tex_id_buffer.id(), - fme::gui_labels::layer_id, - tile.m_layer_id.id(), - fme::gui_labels::blend_mode, - tile.m_blend_mode, - fme::gui_labels::blend_other, - tile.m_tex_id_buffer.blend(), - fme::gui_labels::animation_id, - tile.m_animation_id, - fme::gui_labels::animation_state, - tile.m_animation_state, - fme::gui_labels::draw, - tile.m_tex_id_buffer.draw); - } -}; - -template -concept tile_range = std::ranges::range - && open_viii::graphics::background::is_tile< - std::ranges::range_value_t>; - -template -struct fmt::is_range : std::false_type -{ -}; - - -// Specialization for ranges of tiles -template -struct fmt::formatter : fmt::formatter -{ - // parse is inherited from formatter. - template - constexpr auto format( - const TileRange &tiles, - FormatContext &ctx) const - { - const auto count = std::ranges::distance(tiles); - - - return fmt::format_to(ctx.out(), "Total Tiles: {}\n", count); - } -}; - -template<> -struct fmt::formatter -{ - // Parses format specs; in this case, we don't support any custom - // formatting - constexpr auto parse(format_parse_context &ctx) - { - return ctx.begin();// no custom formatting, so just return the end - } - // Formats the color as "(r,g,b,a)" - template - auto format( - const fme::color &c, - FormatContext &ctx) const - { - return fmt::format_to( - ctx.out(), "({:>3},{:>3},{:>3},{:>3})", c.r, c.g, c.b, c.a); - } -}; +// template<> +// struct fmt::formatter +// { +// // Parses format specs; in this case, we don't support any custom +// // formatting +// constexpr auto parse(format_parse_context &ctx) +// { +// return ctx.begin();// no custom formatting, so just return the end +// } + +// // Formats the color as "(r,g,b,a)" +// template +// auto format( +// const fme::color &c, +// FormatContext &ctx) const +// { +// return fmt::format_to( +// ctx.out(), "({:>3},{:>3},{:>3},{:>3})", c.r, c.g, c.b, c.a); +// } +// }; template<> struct fmt::formatter : fmt::formatter @@ -631,38 +339,6 @@ struct fmt::formatter : fmt::formatter }; -template<> -struct fmt::formatter : fmt::formatter -{// parse is inherited from formatter. - template - constexpr auto format( - fme::compact_type in_compact_type, - FormatContext &ctx) const - { - using namespace std::string_view_literals; - std::string_view name = {}; - switch (in_compact_type) - { - case fme::compact_type::map_order_ffnx: - name = fme::gui_labels::compact_map_order_ffnx2; - break; - case fme::compact_type::map_order: - name = fme::gui_labels::map_order; - break; - case fme::compact_type::move_only_conflicts: - name = fme::gui_labels::move_conflicts; - break; - case fme::compact_type::rows: - name = fme::gui_labels::rows; - break; - case fme::compact_type::all: - name = fme::gui_labels::all; - break; - } - return fmt::formatter::format(name, ctx); - } -}; - template<> struct fmt::formatter : fmt::formatter { @@ -765,31 +441,4 @@ struct fmt::formatter : fmt::formatter return fmt::formatter::format(name, ctx); } }; - -template<> -struct fmt::formatter : fmt::formatter -{ - // parse is inherited from formatter. - template - constexpr auto format( - fme::flatten_type in_flatten_type, - FormatContext &ctx) const - { - using namespace std::string_view_literals; - std::string_view name = {}; - switch (in_flatten_type) - { - case fme::flatten_type::bpp: - name = fme::gui_labels::bpp; - break; - case fme::flatten_type::palette: - name = fme::gui_labels::palette; - break; - case fme::flatten_type::both: - name = fme::gui_labels::bpp_and_palette; - break; - } - return fmt::formatter::format(name, ctx); - } -}; #endif// FIELD_MAP_EDITOR_FORMATTERS_HPP diff --git a/src/opengl/main/future_operations.cpp b/src/opengl/main/future_operations.cpp index a63fe683..6feef495 100644 --- a/src/opengl/main/future_operations.cpp +++ b/src/opengl/main/future_operations.cpp @@ -141,7 +141,7 @@ std::future [](auto &&path) -> std::filesystem::path { return std::forward(path); }) | std::views::filter( - [](safedir path) + [](ff_8::SafeDir path) { return path.is_exists() && !path.is_dir(); }); if (filtered_paths.begin() == filtered_paths.end()) { diff --git a/src/opengl/main/future_operations.hpp b/src/opengl/main/future_operations.hpp index 7de58ec9..2f63928d 100644 --- a/src/opengl/main/future_operations.hpp +++ b/src/opengl/main/future_operations.hpp @@ -4,7 +4,7 @@ #ifndef FIELD_MAP_EDITOR_FUTURE_OPERATIONS_HPP #define FIELD_MAP_EDITOR_FUTURE_OPERATIONS_HPP -#include "safedir.hpp" +#include #include #include #include diff --git a/src/opengl/main/generic_combo.hpp b/src/opengl/main/generic_combo.hpp index 496e19e8..0e3b7c0f 100644 --- a/src/opengl/main/generic_combo.hpp +++ b/src/opengl/main/generic_combo.hpp @@ -4,19 +4,19 @@ #ifndef FIELD_MAP_EDITOR_GENERIC_COMBO_HPP #define FIELD_MAP_EDITOR_GENERIC_COMBO_HPP -#include "filter.hpp" #include "format_imgui_text.hpp" #include "gui/fa_icons.hpp" #include "gui/gui_labels.hpp" -#include "gui/push_pop_id.hpp" #include "gui/tool_tip.hpp" #include "open_file_explorer.hpp" -#include "unique_values.hpp" #include +#include +#include #include #include #include #include +#include #include #include #include @@ -162,7 +162,7 @@ class GenericComboWithFilter } void renderCheckBox() const { - const auto _ = PushPopID(); + const auto _ = imgui_utils::ImGuiPushId(); if (bool checked = filter_.get().enabled(); ImGui::Checkbox("", &checked)) { @@ -174,7 +174,7 @@ class GenericComboWithFilter void renderComboBox() const { - const auto _ = PushPopID(); + const auto _ = imgui_utils::ImGuiPushId(); const float button_size = ImGui::GetFrameHeight(); const float button_count = [&]() { @@ -218,7 +218,7 @@ class GenericComboWithFilter // want, outside or inside your objects const char *c_str_value = std::ranges::data(string); { - const auto pop_id = PushPopID(); + const auto pop_id = imgui_utils::ImGuiPushId(); const auto pop_column = glengine::ScopeGuard{ &ImGui::NextColumn }; if (ImGui::Selectable(c_str_value, is_selected)) @@ -270,7 +270,7 @@ class GenericComboWithFilter void renderLeftButton() const { - const auto _ = PushPopID(); + const auto _ = imgui_utils::ImGuiPushId(); ImGui::SameLine(0, spacing_); const auto check_valid = [&]() { @@ -295,7 +295,7 @@ class GenericComboWithFilter void renderRightButton() const { - const auto _ = PushPopID(); + const auto _ = imgui_utils::ImGuiPushId(); ImGui::SameLine(0, spacing_); const auto check_valid = [&]() { return (current_idx_ + 1 >= size_of_values()); }; @@ -323,7 +323,7 @@ class GenericComboWithFilter } ImGui::SameLine(0, spacing_); const float button_size = ImGui::GetFrameHeight(); - const auto _ = PushPopID(); + const auto _ = imgui_utils::ImGuiPushId(); if (ImGui::Button( ICON_FA_FOLDER_OPEN, ImVec2{ button_size, button_size })) { @@ -480,7 +480,7 @@ class GenericComboWithToggle void renderCheckBox() const { - const auto _ = PushPopID(); + const auto _ = imgui_utils::ImGuiPushId(); bool checked = enabled_.get(); if (ImGui::Checkbox("", &checked)) { @@ -492,7 +492,7 @@ class GenericComboWithToggle void renderComboBox() const { - const auto _ = PushPopID(); + const auto _ = imgui_utils::ImGuiPushId(); const float button_size = ImGui::GetFrameHeight(); const float button_count = [&]() { @@ -527,7 +527,7 @@ class GenericComboWithToggle = static_cast(index_raw); const bool is_selected = (index == current_idx_); const char *c_str_value = std::ranges::data(string); - const auto pop_id = PushPopID(); + const auto pop_id = imgui_utils::ImGuiPushId(); const auto pop_column = glengine::ScopeGuard{ &ImGui::NextColumn }; if (ImGui::Selectable(c_str_value, is_selected)) @@ -561,7 +561,7 @@ class GenericComboWithToggle void renderLeftButton() const { - const auto _ = PushPopID(); + const auto _ = imgui_utils::ImGuiPushId(); ImGui::SameLine(0, spacing_); const bool disabled = current_idx_ == 0; ImGui::BeginDisabled(disabled); @@ -576,7 +576,7 @@ class GenericComboWithToggle void renderRightButton() const { - const auto _ = PushPopID(); + const auto _ = imgui_utils::ImGuiPushId(); ImGui::SameLine(0, spacing_); const bool disabled = current_idx_ + 1 >= size_of_values(); ImGui::BeginDisabled(disabled); @@ -596,7 +596,7 @@ class GenericComboWithToggle ImGui::SameLine(0, spacing_); const float button_size = ImGui::GetFrameHeight(); - const auto _ = PushPopID(); + const auto _ = imgui_utils::ImGuiPushId(); if (ImGui::Button( ICON_FA_FOLDER_OPEN, ImVec2{ button_size, button_size })) { @@ -964,7 +964,7 @@ class GenericComboWithMultiFilter // } void renderCheckBox() const { - const auto _ = PushPopID(); + const auto _ = imgui_utils::ImGuiPushId(); bool disabled = std::ranges::none_of(current_idx_, std::identity{}); if (disabled && filter_.get().enabled()) { @@ -985,7 +985,7 @@ class GenericComboWithMultiFilter void renderComboBox() const { - const auto _ = PushPopID(); + const auto _ = imgui_utils::ImGuiPushId(); const float button_size = ImGui::GetFrameHeight(); const float button_count = [&]() { @@ -1038,7 +1038,7 @@ class GenericComboWithMultiFilter // want, outside or inside your objects const char *c_str_value = std::ranges::data(string); { - const auto pop_id = PushPopID(); + const auto pop_id = imgui_utils::ImGuiPushId(); const auto pop_column = glengine::ScopeGuard{ &ImGui::NextColumn }; if (ImGui::Selectable( @@ -1092,7 +1092,7 @@ class GenericComboWithMultiFilter ImGui::SameLine(0, spacing_); const float button_size = ImGui::GetFrameHeight(); - const auto _ = PushPopID(); + const auto _ = imgui_utils::ImGuiPushId(); if (ImGui::Button( ICON_FA_FOLDER_OPEN, ImVec2{ button_size, button_size })) @@ -1287,7 +1287,7 @@ class GenericComboWithFilterAndFixedToggles { return; } - const auto _ = PushPopID(); + const auto _ = imgui_utils::ImGuiPushId(); const auto ¤t_fixed_toggle = *getNext(fixed_toggles_.get(), current_idx_); ImGui::BeginDisabled( @@ -1304,7 +1304,7 @@ class GenericComboWithFilterAndFixedToggles void renderComboBox() const { - const auto _ = PushPopID();// RAII for ImGui ID stack + const auto _ = imgui_utils::ImGuiPushId();// RAII for ImGui ID stack const float button_size = ImGui::GetFrameHeight(); const float button_count = [&]() { @@ -1345,7 +1345,7 @@ class GenericComboWithFilterAndFixedToggles const auto index = static_cast(index_raw); const bool is_selected = current_idx_ == index; - const auto pop_id = PushPopID(); + const auto pop_id = imgui_utils::ImGuiPushId(); const auto pop_column = glengine::ScopeGuard{ &ImGui::NextColumn }; @@ -1406,7 +1406,7 @@ class GenericComboWithFilterAndFixedToggles void renderLeftButton() const { - const auto _ = PushPopID(); + const auto _ = imgui_utils::ImGuiPushId(); const auto check_valid = [&]() { @@ -1448,7 +1448,7 @@ class GenericComboWithFilterAndFixedToggles void renderRightButton() const { - const auto _ = PushPopID(); + const auto _ = imgui_utils::ImGuiPushId(); ImGui::SameLine(0, spacing_); const auto check_valid = [&]() { return (current_idx_ + 1 >= size_of_values()); }; @@ -1490,7 +1490,7 @@ class GenericComboWithFilterAndFixedToggles } ImGui::SameLine(0, spacing_); const float button_size = ImGui::GetFrameHeight(); - const auto _ = PushPopID(); + const auto _ = imgui_utils::ImGuiPushId(); if (ImGui::Button( ICON_FA_FOLDER_OPEN, ImVec2{ button_size, button_size })) { @@ -1518,7 +1518,7 @@ class GenericComboWithFilterAndFixedToggles ImGui::SetCursorScreenPos(ImGui::GetItemRectMin()); // Make invisible button the same size as the text - const auto _ = PushPopID(); + const auto _ = imgui_utils::ImGuiPushId(); ImGui::InvisibleButton("##hover_area", textSize); tool_tip(name_); @@ -1671,7 +1671,7 @@ class GenericCombo void renderComboBox() const { - const auto pop_id = PushPopID(); + const auto pop_id = imgui_utils::ImGuiPushId(); const float button_size = ImGui::GetFrameHeight(); const float button_count = [&]() { @@ -1737,7 +1737,7 @@ class GenericCombo } const char *c_str_value = std::ranges::data(string); { - const auto pop_id2 = PushPopID(); + const auto pop_id2 = imgui_utils::ImGuiPushId(); const auto pop_column = glengine::ScopeGuard{ &ImGui::NextColumn }; @@ -1781,7 +1781,7 @@ class GenericCombo void renderLeftButton() const { - const auto _ = PushPopID(); + const auto _ = imgui_utils::ImGuiPushId(); const auto pop_disabled = glengine::ScopeGuard{ &ImGui::EndDisabled }; ImGui::SameLine(0, spacing_); const auto check_valid = [&]() @@ -1813,7 +1813,7 @@ class GenericCombo void renderRightButton() const { - const auto pop_id_right = PushPopID(); + const auto pop_id_right = imgui_utils::ImGuiPushId(); ImGui::SameLine(0, spacing_); const auto check_valid = [&]() { return (current_idx_ + 1 >= size_of_values()); }; @@ -1840,7 +1840,7 @@ class GenericCombo } ImGui::SameLine(0, spacing_); const float button_size = ImGui::GetFrameHeight(); - const auto _ = PushPopID(); + const auto _ = imgui_utils::ImGuiPushId(); if (ImGui::Button( ICON_FA_FOLDER_OPEN, ImVec2{ button_size, button_size })) { diff --git a/src/opengl/main/gui/BackgroundSettings.hpp b/src/opengl/main/gui/BackgroundSettings.hpp new file mode 100644 index 00000000..161b7733 --- /dev/null +++ b/src/opengl/main/gui/BackgroundSettings.hpp @@ -0,0 +1,243 @@ +#ifndef A123DC46_3563_4C3C_8852_7D600E671125 +#define A123DC46_3563_4C3C_8852_7D600E671125 +#include "spdlog/spdlog.h" +namespace fme +{ + +enum class BackgroundSettings : uint8_t +{ + // Presets + Default = 0, + + // Color count bit + OneColor = Default, + TwoColors = 1 << 0, + + // Pattern bit + Checkerboard = Default, + Solid = 1 << 1, + + +}; + + +// Bitwise operators +inline constexpr BackgroundSettings operator|( + BackgroundSettings lhs, + BackgroundSettings rhs) +{ + return static_cast( + std::to_underlying(lhs) | std::to_underlying(rhs)); +} + +inline constexpr BackgroundSettings operator&( + BackgroundSettings lhs, + BackgroundSettings rhs) +{ + return static_cast( + std::to_underlying(lhs) & std::to_underlying(rhs)); +} + +inline constexpr BackgroundSettings &operator|=( + BackgroundSettings &lhs, + BackgroundSettings rhs) +{ + lhs = lhs | rhs; + return lhs; +} + +inline constexpr bool ValidateBackgroundSettings(BackgroundSettings setting) +{ + // Must only contain valid bits + if ( + std::to_underlying(setting) + & ~std::to_underlying( + BackgroundSettings::Solid | BackgroundSettings::TwoColors)) + { + if (!std::is_constant_evaluated()) + { + spdlog::debug( + "Invalid BackgroundSettings: contains unknown bits ({:#X})", + std::to_underlying(setting)); + } + return false; + } + + // Disallow Solid + TwoColors + if ( + (setting & (BackgroundSettings::Solid | BackgroundSettings::TwoColors)) + == (BackgroundSettings::Solid | BackgroundSettings::TwoColors)) + { + if (!std::is_constant_evaluated()) + { + spdlog::debug( + "Invalid BackgroundSettings: Solid and TwoColors cannot be " + "combined ({:#X})", + std::to_underlying(setting)); + } + return false; + } + + return true; +} + +inline constexpr bool HasFlag( + BackgroundSettings value, + BackgroundSettings flag) +{ + if (flag == BackgroundSettings::Default) + return value == BackgroundSettings::Default; + else + return (value & flag) != BackgroundSettings::Default; +} + + +static_assert(ValidateBackgroundSettings(BackgroundSettings::Default)); +static_assert(!ValidateBackgroundSettings( + BackgroundSettings::TwoColors | BackgroundSettings::Solid)); + +// Static asserts to validate HasFlag logic + +static_assert( + HasFlag( + BackgroundSettings::Default, + BackgroundSettings::Default), + "Default has Default"); +static_assert( + HasFlag( + BackgroundSettings::Default, + BackgroundSettings::OneColor), + "Default has OneColor (alias of Default)"); +static_assert( + !HasFlag( + BackgroundSettings::Default, + BackgroundSettings::TwoColors), + "Default does not have TwoColors"); +static_assert( + HasFlag( + BackgroundSettings::TwoColors, + BackgroundSettings::TwoColors), + "TwoColors has TwoColors"); +static_assert( + !HasFlag( + BackgroundSettings::TwoColors, + BackgroundSettings::Default), + "TwoColors does not have Default"); +static_assert( + !HasFlag( + BackgroundSettings::TwoColors, + BackgroundSettings::OneColor), + "TwoColors does not have OneColor (Default)"); +static_assert( + !HasFlag( + BackgroundSettings::OneColor, + BackgroundSettings::TwoColors), + "OneColor (Default) does not have TwoColors"); + +// Also test pattern bits +static_assert( + HasFlag( + BackgroundSettings::Default, + BackgroundSettings::Checkerboard), + "Default has Checkerboard"); +static_assert( + !HasFlag( + BackgroundSettings::Default, + BackgroundSettings::Solid), + "Default does not have Solid"); +static_assert( + HasFlag( + BackgroundSettings::Solid, + BackgroundSettings::Solid), + "Solid has Solid"); +static_assert( + !HasFlag( + BackgroundSettings::Solid, + BackgroundSettings::Checkerboard), + "Solid does not have Checkerboard"); + +constexpr void SetFlag( + BackgroundSettings ¤t, + BackgroundSettings flag, + bool enabled) +{ + if (flag == BackgroundSettings::Default) + { + // No operation if flag is Default + return; + } + + auto value = std::to_underlying(current); + auto flagBit = std::to_underlying(flag); + + if (enabled) + { + value |= flagBit;// Set the bit + } + else + { + value &= ~flagBit;// Clear the bit + } + + current = static_cast(value); + + return; +} + +[[nodiscard]] constexpr BackgroundSettings SetFlag( + BackgroundSettings &&initial, + BackgroundSettings flag, + bool enabled) +{ + SetFlag(initial, flag, enabled); + return initial; +} + +static_assert( + SetFlag( + BackgroundSettings::OneColor, + BackgroundSettings::TwoColors, + true) + == BackgroundSettings::TwoColors, + "Enable TwoColors failed"); +static_assert( + SetFlag( + BackgroundSettings::TwoColors, + BackgroundSettings::TwoColors, + false) + == BackgroundSettings::OneColor, + "Disable TwoColors failed"); + +static_assert( + SetFlag( + BackgroundSettings::Checkerboard, + BackgroundSettings::Solid, + true) + == BackgroundSettings::Solid, + "Enable Solid failed"); +static_assert( + SetFlag( + BackgroundSettings::Solid, + BackgroundSettings::Solid, + false) + == BackgroundSettings::Checkerboard, + "Disable Solid failed"); + +// Test no-op when flag == Default +static_assert( + SetFlag( + BackgroundSettings::Solid, + BackgroundSettings::Default, + true) + == BackgroundSettings::Solid, + "No-op with Default flag failed"); +static_assert( + SetFlag( + BackgroundSettings::TwoColors, + BackgroundSettings::Default, + false) + == BackgroundSettings::TwoColors, + "No-op with Default flag failed"); +}// namespace fme + +#endif /* A123DC46_3563_4C3C_8852_7D600E671125 */ diff --git a/src/opengl/main/gui/ColorConversions.hpp b/src/opengl/main/gui/ColorConversions.hpp new file mode 100644 index 00000000..7acd37a9 --- /dev/null +++ b/src/opengl/main/gui/ColorConversions.hpp @@ -0,0 +1,97 @@ +#ifndef B8F75462_5799_4CFA_80D6_4E3FE743A9D3 +#define B8F75462_5799_4CFA_80D6_4E3FE743A9D3 +#include +#include +#include +#include + +namespace ff_8::Colors +{ +// darkstyle imgui color blue tint + +static inline const ImGuiStyle DarkStyle = []() +{ + auto s = ImGuiStyle{}; + ImGui::StyleColorsDark(&s); + return s; +}(); +static inline const Color Button = Color{ DarkStyle.Colors[ImGuiCol_Button] }; +static inline const Color ButtonHovered + = Color{ DarkStyle.Colors[ImGuiCol_ButtonHovered] }; +static inline const Color ButtonActive + = Color{ DarkStyle.Colors[ImGuiCol_ButtonActive] }; + +[[nodiscard]] constexpr ImVec4 to_imvec4(const Color &c) noexcept +{ + constexpr float max_f + = static_cast(std::numeric_limits::max()); + return { static_cast(c.r) / max_f, static_cast(c.g) / max_f, + static_cast(c.b) / max_f, + static_cast(c.a) / max_f }; +} + +[[nodiscard]] constexpr ImColor to_imcolor(const Color &c) noexcept +{ + return ImColor( + static_cast(c.r), + static_cast(c.g), + static_cast(c.b), + static_cast(c.a)); +} + +[[nodiscard]] constexpr glm::vec4 to_vec4(const Color &c) noexcept +{ + constexpr float max_f + = static_cast(std::numeric_limits::max()); + return { static_cast(c.r) / max_f, static_cast(c.g) / max_f, + static_cast(c.b) / max_f, + static_cast(c.a) / max_f }; +} + +[[nodiscard]] constexpr ImU32 to_imU32(const Color &c) noexcept +{ + // ImGui’s packing order: 0xAABBGGRR + return IM_COL32(c.r, c.g, c.b, c.a); +} + +// Pipeable range adaptors +inline constexpr auto as_vec4 + = std::views::transform([](const Color &c) { return to_vec4(c); }); + +inline constexpr auto as_imvec4 + = std::views::transform([](const Color &c) { return to_imvec4(c); }); + +inline constexpr auto as_imcolor + = std::views::transform([](const Color &c) { return to_imcolor(c); }); + +// Constructors from ImGui / GLM types +[[nodiscard]] constexpr Color from_imvec4(const ImVec4 &v) noexcept +{ + constexpr float max_f + = static_cast(std::numeric_limits::max()); + return { static_cast(std::clamp(v.x, 0.0f, 1.0f) * max_f), + static_cast(std::clamp(v.y, 0.0f, 1.0f) * max_f), + static_cast(std::clamp(v.z, 0.0f, 1.0f) * max_f), + static_cast(std::clamp(v.w, 0.0f, 1.0f) * max_f) }; +} + +[[nodiscard]] constexpr Color from_vec4(const glm::vec4 &v) noexcept +{ + constexpr float max_f + = static_cast(std::numeric_limits::max()); + return { static_cast(std::clamp(v.r, 0.0f, 1.0f) * max_f), + static_cast(std::clamp(v.g, 0.0f, 1.0f) * max_f), + static_cast(std::clamp(v.b, 0.0f, 1.0f) * max_f), + static_cast(std::clamp(v.a, 0.0f, 1.0f) * max_f) }; +} + +[[nodiscard]] constexpr Color from_imcolor(const ImColor &c) noexcept +{ + // ImColor stores normalized floats in c.Value + const ImVec4 &v = c.Value; + return from_imvec4(v); +} + +}// namespace ff_8::Colors + +#endif /* B8F75462_5799_4CFA_80D6_4E3FE743A9D3 */ diff --git a/src/opengl/main/gui/LoggingWindow.cpp b/src/opengl/main/gui/LoggingWindow.cpp new file mode 100644 index 00000000..4e34c451 --- /dev/null +++ b/src/opengl/main/gui/LoggingWindow.cpp @@ -0,0 +1,104 @@ +#include "LoggingWindow.hpp" + + +fme::LoggingWindow::LoggingWindow( + std::shared_ptr memory_sink, + std::weak_ptr selections) + : m_memory_sink(std::move(memory_sink)) + , m_selections(std::move(selections)) +{ +} + +void fme::LoggingWindow::on_update(float ts) const +{ + m_refresh_timer -= ts; + if (m_refresh_timer <= 0.0f) + { + refresh_messages(); + m_refresh_timer = m_refresh_interval; + } +} + +void fme::LoggingWindow::on_im_gui_update() const +{ + + if (!m_memory_sink) + { + return; + } + if (!m_open) + { + return; + } + if (!ImGui::Begin("Logging Window", &m_open)) + { + ImGui::End(); + return; + } + + auto cmb = fme::GenericCombo( + "Log level", level_values, level_names, m_current_level); + if (cmb.render()) + { + // m_memory_sink->set_level(m_current_level); + spdlog::set_level(m_current_level); + } + + ImGui::Checkbox("Auto-scroll", &m_auto_scroll); + + ImGui::Separator(); + + draw_log_entries(); + + ImGui::End(); +} + +void fme::LoggingWindow::on_im_gui_window_menu() const +{ + ImGui::MenuItem("Log", nullptr, &m_open); +} + +void fme::LoggingWindow::refresh_messages() const +{ + if (!m_memory_sink) + return; + + m_messages = m_memory_sink->last_formatted(); +} + +void fme::LoggingWindow::draw_log_entries() const +{ + + if (!m_memory_sink) + return; + + ImGui::BeginChild( + "log_scroller", + ImVec2(0, 0), + false, + ImGuiWindowFlags_HorizontalScrollbar); + + ImGuiListClipper clipper; + clipper.Begin(static_cast(m_messages.size())); + + while (clipper.Step()) + { + const int start = clipper.DisplayStart; + const int count = clipper.DisplayEnd - clipper.DisplayStart; + + const std::span visible( + m_messages.data() + start, static_cast(count)); + + for (const auto &msg : visible) + { + ImGui::TextUnformatted(msg.c_str()); + } + } + + if (m_auto_scroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY()) + { + ImGui::SetScrollHereY(1.0f); + } + + ImGui::EndChild(); +} diff --git a/src/opengl/main/gui/LoggingWindow.hpp b/src/opengl/main/gui/LoggingWindow.hpp new file mode 100644 index 00000000..a24d4af3 --- /dev/null +++ b/src/opengl/main/gui/LoggingWindow.hpp @@ -0,0 +1,74 @@ +#ifndef A70191A7_A943_4FCE_9EB3_0E7324FBB417 +#define A70191A7_A943_4FCE_9EB3_0E7324FBB417 + +#include "formatters.hpp" +#include "Selections.hpp" +#include +#include +#include +#include +#include +#include +#include +#include + +namespace fme +{ + +class LoggingWindow +{ + public: + static const constexpr std::string_view level_names[] + = { "Trace", "Debug", "Info", "Warn", "Error", "Critical", "Off" }; + + static const constexpr spdlog::level::level_enum level_values[] + = { spdlog::level::trace, spdlog::level::debug, spdlog::level::info, + spdlog::level::warn, spdlog::level::err, spdlog::level::critical, + spdlog::level::off }; + using MemorySink = spdlog::sinks::ringbuffer_sink_mt; + + LoggingWindow( + std::shared_ptr memory_sink, + std::weak_ptr selections); + + // ------------------------------------------------------------ + // Renderable hooks + // ------------------------------------------------------------ + + void on_update(float ts) const; + + void on_im_gui_update() const; + + void on_im_gui_window_menu() const; + + private: + // ------------------------------------------------------------ + // Helpers + // ------------------------------------------------------------ + + void refresh_messages() const; + + void draw_log_entries() const; + + + private: + std::shared_ptr m_memory_sink; + std::weak_ptr m_selections; + + // Cached messages + mutable std::vector m_messages; + + // Refresh control + float m_refresh_interval = 0.25f;// seconds + mutable float m_refresh_timer = 0.0f; + + // UI state (mutable to allow const callbacks) + mutable bool m_open = true; + mutable bool m_auto_scroll = true; + + mutable spdlog::level::level_enum m_current_level = spdlog::level::debug; +}; +}// namespace fme + + +#endif /* A70191A7_A943_4FCE_9EB3_0E7324FBB417 */ diff --git a/src/opengl/main/gui/Selections.cpp b/src/opengl/main/gui/Selections.cpp index a75a1186..709b3cc5 100644 --- a/src/opengl/main/gui/Selections.cpp +++ b/src/opengl/main/gui/Selections.cpp @@ -3,10 +3,10 @@ // #include "Selections.hpp" #include "formatters.hpp" -#include "utilities.hpp" +#include #include -fme::Selections::Selections(const Configuration config) +fme::Selections::Selections(const ff_8::Configuration config) : m_selections_array(load_selections_array(config)) { sort_paths(); @@ -21,12 +21,12 @@ fme::Selections::Selections(const Configuration config) } } -std::optional fme::Selections::get_ffnx_config() const +std::optional fme::Selections::get_ffnx_config() const { return get_ffnx_config(get()); } -std::optional +std::optional fme::Selections::get_ffnx_config(const std::filesystem::path &ff8_path) const { const auto ffnx_settings_toml = ff8_path / "FFNx.toml"; @@ -71,14 +71,15 @@ void fme::Selections::sort_paths() bool changed = false; changed |= std::apply( - remove_empty_values())>...>, + ff_8::remove_empty_values< + std::remove_cvref_t())>...>, args); changed |= std::apply( - remove_nonexistent_paths< + ff_8::remove_nonexistent_paths< std::remove_cvref_t())>...>, args_with_bool); changed |= std::apply( - sort_and_remove_duplicates< + ff_8::sort_and_remove_duplicates< std::remove_cvref_t())>...>, args); diff --git a/src/opengl/main/gui/Selections.hpp b/src/opengl/main/gui/Selections.hpp index 22ab05b8..ba711f6f 100644 --- a/src/opengl/main/gui/Selections.hpp +++ b/src/opengl/main/gui/Selections.hpp @@ -3,14 +3,14 @@ // #ifndef FIELD_MAP_EDITOR_SELECTIONS_HPP #define FIELD_MAP_EDITOR_SELECTIONS_HPP -#include "colors.hpp" -#include "compact_type.hpp" -#include "Configuration.hpp" #include "draw_mode.hpp" -#include "filter.hpp" #include "formatters.hpp" #include "tile_sizes.hpp" -#include "utilities.hpp" +#include +#include +#include +#include +#include #include #include #include @@ -722,21 +722,21 @@ struct SelectionInfo template<> struct SelectionInfo { - using value_type = color; + using value_type = ff_8::Color; static constexpr std::string_view id = "BackgroundColor"; static inline value_type default_value() { - return fme::colors::White; + return ff_8::Colors::White; } }; template<> struct SelectionInfo { - using value_type = color; + using value_type = ff_8::Color; static constexpr std::string_view id = "BackgroundColor2"; static inline value_type default_value() { - return fme::colors::White; + return ff_8::Colors::White; } }; template<> @@ -865,7 +865,7 @@ struct SelectionInfo } static void post_load_operation([[maybe_unused]] const value_type &value) { - assert(has_balanced_braces(value)); + assert(ff_8::has_balanced_braces(value)); } }; template<> @@ -896,7 +896,7 @@ struct SelectionInfo } static void post_load_operation([[maybe_unused]] const value_type &value) { - assert(has_balanced_braces(value)); + assert(ff_8::has_balanced_braces(value)); } }; template<> @@ -927,7 +927,7 @@ struct SelectionInfo } static void post_load_operation([[maybe_unused]] const value_type &value) { - assert(has_balanced_braces(value)); + assert(ff_8::has_balanced_braces(value)); } }; template<> @@ -950,7 +950,7 @@ struct SelectionInfo } static void post_load_operation([[maybe_unused]] const value_type &value) { - assert(has_balanced_braces(value)); + assert(ff_8::has_balanced_braces(value)); } }; @@ -970,7 +970,7 @@ struct SelectionInfo } static void post_load_operation([[maybe_unused]] const value_type &value) { - assert(has_balanced_braces(value)); + assert(ff_8::has_balanced_braces(value)); } }; template<> @@ -999,7 +999,7 @@ struct SelectionInfo } static void post_load_operation([[maybe_unused]] const value_type &value) { - assert(has_balanced_braces(value)); + assert(ff_8::has_balanced_braces(value)); } }; template<> @@ -1047,7 +1047,7 @@ struct SelectionInfo } static void post_load_operation([[maybe_unused]] const value_type &value) { - assert(has_balanced_braces(value)); + assert(ff_8::has_balanced_braces(value)); } }; template<> @@ -1062,7 +1062,7 @@ struct SelectionInfo } static void post_load_operation([[maybe_unused]] const value_type &value) { - assert(has_balanced_braces(value)); + assert(ff_8::has_balanced_braces(value)); } }; template<> @@ -1077,7 +1077,7 @@ struct SelectionInfo } static void post_load_operation([[maybe_unused]] const value_type &value) { - assert(has_balanced_braces(value)); + assert(ff_8::has_balanced_braces(value)); } }; @@ -1095,7 +1095,7 @@ struct SelectionInfo // static void post_load_operation([[maybe_unused]] const value_type // &value) // { - // assert(has_balanced_braces(value)); + // assert(ff_8::has_balanced_braces(value)); // } }; @@ -1113,7 +1113,7 @@ struct SelectionInfo } static void post_load_operation([[maybe_unused]] const value_type &value) { - assert(has_balanced_braces(value)); + assert(ff_8::has_balanced_braces(value)); } }; template<> @@ -1269,9 +1269,9 @@ struct SelectionLoadStrategy { value = config[id].value_or(value.u8string()); } - else if constexpr (std::convertible_to) + else if constexpr (std::convertible_to) { - value = std::bit_cast( + value = std::bit_cast( config[id].value_or(std::bit_cast(value))); } else if constexpr (requires { std::declval().raw(); }) @@ -1288,7 +1288,7 @@ struct SelectionLoadStrategy if constexpr (std::is_enum_v< glengine::vector_elem_type_t>) { - return fme::Configuration::load_array< + return ff_8::Configuration::load_array< glengine::vector_elem_type_t, std::underlying_type_t< glengine::vector_elem_type_t>>( @@ -1298,13 +1298,13 @@ struct SelectionLoadStrategy glengine::vector_elem_type_t, ff_8::PupuID>) { - return fme::Configuration::load_array< + return ff_8::Configuration::load_array< glengine::vector_elem_type_t, std::uint32_t>(config, id, value); } else { - return fme::Configuration::load_array< + return ff_8::Configuration::load_array< glengine::vector_elem_type_t>(config, id, value); } } @@ -1450,7 +1450,7 @@ struct SelectionLoadStrategy::value_type> // For filters that are constructed with full context and do not support default // init template -struct SelectionLoadStrategy> +struct SelectionLoadStrategy> { // No loading: object is fully initialized elsewhere static bool load(auto &&...) noexcept @@ -1479,7 +1479,7 @@ struct SelectionUpdateStrategy std::filesystem::path(str_val).string()); config.insert_or_assign(id, str_val); } - else if constexpr (std::convertible_to) + else if constexpr (std::convertible_to) { spdlog::info("selection<{}>: {}", id, value); config.insert_or_assign(id, std::bit_cast(value)); @@ -1496,17 +1496,17 @@ struct SelectionUpdateStrategy } else if constexpr (std::same_as>) { - Configuration::update_array(config, id, value); + ff_8::Configuration::update_array(config, id, value); } else if constexpr (std::same_as>) { - Configuration::update_array(config, id, value); + ff_8::Configuration::update_array(config, id, value); } else if constexpr (std::same_as< ValueT, std::vector>) { - Configuration::update_array(config, id, value); + ff_8::Configuration::update_array(config, id, value); } else { @@ -1566,7 +1566,7 @@ struct SelectionUpdateStrategy::value_type> // Skip updating for filters — they update themselves template -struct SelectionUpdateStrategy> +struct SelectionUpdateStrategy> { static void update(auto &&...) noexcept { @@ -1581,7 +1581,7 @@ struct Selection using value_type = typename SelectionInfo::value_type; value_type value; - Selection([[maybe_unused]] const Configuration &config) + Selection([[maybe_unused]] const ff_8::Configuration &config) : Selection( config, std::nullopt) @@ -1589,8 +1589,8 @@ struct Selection } Selection( - [[maybe_unused]] const Configuration &config, - [[maybe_unused]] const std::optional &ffnx_config) + [[maybe_unused]] const ff_8::Configuration &config, + [[maybe_unused]] const std::optional &ffnx_config) : value( [&]() { @@ -1623,9 +1623,9 @@ struct Selection private: static constexpr value_type - get_default_value([[maybe_unused]] const Configuration *config) + get_default_value([[maybe_unused]] const ff_8::Configuration *config) { - if constexpr (requires(const Configuration &c) { + if constexpr (requires(const ff_8::Configuration &c) { SelectionInfo::default_value(c); }) { @@ -1663,7 +1663,7 @@ struct Selection } } - void fail_to_load([[maybe_unused]] const Configuration &config) + void fail_to_load([[maybe_unused]] const ff_8::Configuration &config) { if constexpr (requires { SelectionInfo::expensive_default_value(); @@ -1686,7 +1686,7 @@ struct Selection } } - void load(const Configuration &config) + void load(const ff_8::Configuration &config) { if (!SelectionLoadStrategy::load( config, SelectionInfo::id, value)) @@ -1705,8 +1705,8 @@ struct Selection // when we change directories we need to check for the ffnx config and // refresh the values from that config. go back to default value if // ffnx_config not there. - void - refresh([[maybe_unused]] const std::optional &ffnx_config) + void refresh( + [[maybe_unused]] const std::optional &ffnx_config) { if constexpr (SelectionUseFFNXConfig::value) { @@ -1723,7 +1723,7 @@ struct Selection // update skips over ffnx values as we're currently not writing to the // ffnx config file. - void update([[maybe_unused]] Configuration &config) const + void update([[maybe_unused]] ff_8::Configuration &config) const { if constexpr (!SelectionUseFFNXConfig::value) { @@ -1800,10 +1800,10 @@ struct Selections static inline constexpr std::array s_selections_id_array = load_selections_id_array(); - SelectionsArrayT load_selections_array(const Configuration &config) + SelectionsArrayT load_selections_array(const ff_8::Configuration &config) { // cache these values for use later on. - std::optional ffnx_config{}; + std::optional ffnx_config{}; std::optional ff8_path{}; return [&]( std::index_sequence) -> SelectionsArrayT @@ -1857,15 +1857,15 @@ struct Selections // */ // void refresh_ffnx_paths(const // std::filesystem::path &ff8_path); - std::optional get_ffnx_config() const; - std::optional + std::optional get_ffnx_config() const; + std::optional get_ffnx_config(const std::filesystem::path &ff8_path) const; public: /** * @brief Constructs a Selections object with default values. */ - Selections(const Configuration config = {}); + Selections(const ff_8::Configuration config = {}); template requires(SelectionsSizeT > static_cast(Key)) @@ -2007,7 +2007,7 @@ struct Selections } else { - const std::optional ffnx_config + const std::optional ffnx_config = get_ffnx_config(); ( [&] @@ -2045,7 +2045,7 @@ struct Selections } else { - Configuration config{}; + ff_8::Configuration config{}; ( [&] { @@ -2069,7 +2069,7 @@ struct Selections void reset_to_demaster() { - Configuration config{}; + ff_8::Configuration config{}; [&](std::index_sequence) { ( @@ -2089,7 +2089,7 @@ struct Selections void reset_to_ffnx() { - Configuration config{}; + ff_8::Configuration config{}; [&](std::index_sequence) { ( diff --git a/src/opengl/main/gui/batch.cpp b/src/opengl/main/gui/batch.cpp index e32cafcb..2a547d33 100644 --- a/src/opengl/main/gui/batch.cpp +++ b/src/opengl/main/gui/batch.cpp @@ -6,8 +6,9 @@ #include "as_string.hpp" #include "custom_paths_window.hpp" #include "open_file_explorer.hpp" -#include "push_pop_id.hpp" #include "tool_tip.hpp" +#include +#include #include #include namespace fme @@ -59,7 +60,7 @@ static bool safe_copy_string( std::ranges::begin(src), src_size, std::ranges::data(dst)); dst[static_cast(src_size)] = '\0'; - const auto tmp = safedir(std::ranges::data(dst)); + const auto tmp = ff_8::SafeDir(std::ranges::data(dst)); return tmp.is_dir() && tmp.is_exists(); } @@ -82,7 +83,7 @@ void fme::batch::draw_window() } }; const auto end = glengine::ScopeGuard(&ImGui::End); - if (!ImGui::Begin(gui_labels::batch_operation_window.data(), &visible)) + if (!ImGui::Begin(gui_labels::batch_operation.data(), &visible)) { return; } @@ -100,7 +101,7 @@ void fme::batch::draw_window() const std::filesystem::path config_path = config_path_values.replace_tags( selections->get(), selections); - auto config = Configuration(config_path); + auto config = ff_8::Configuration(config_path); config.save(); } spdlog::info("Batch operation completed."); @@ -297,7 +298,7 @@ void fme::batch::draw_queue() for (auto &&[index, pair] : queue | std::views::enumerate) { auto &&[name, settings, enabled] = pair; - const auto pop_id = PushPopID(); + const auto pop_id = imgui_utils::ImGuiPushId(); ImGui::TableNextRow(); ImGui::TableNextColumn(); if (ImGui::Checkbox( @@ -767,7 +768,7 @@ void fme::batch::combo_load_map() [](const auto &key) { return gui_labels::input_map_tooltips[std::to_underlying(key)]; }) | std::ranges::to(); - const auto pop_id = PushPopID(); + const auto pop_id = imgui_utils::ImGuiPushId(); const auto gcc = fme::GenericCombo( gui_labels::batch_load_map, values, strings, tooltips, selections->get()); @@ -848,7 +849,7 @@ void fme::batch::browse_input_path() { const float button_size = ImGui::GetFrameHeight(); const float button_width = button_size * 3.0F; - const auto pop_id = PushPopID(); + const auto pop_id = imgui_utils::ImGuiPushId(); const std::string &selected_string = get_selected_path( selections->get(), selections->get()); @@ -920,7 +921,7 @@ void fme::batch::browse_input_map_path() { const float button_size = ImGui::GetFrameHeight(); const float button_width = button_size * 3.0F; - const auto pop_id = PushPopID(); + const auto pop_id = imgui_utils::ImGuiPushId(); const std::string &selected_string = get_selected_path( selections->get(), selections->get()); @@ -987,7 +988,7 @@ void fme::batch::browse_output_path() { const float button_size = ImGui::GetFrameHeight(); const float button_width = button_size * 3.0F; - const auto pop_id = PushPopID(); + const auto pop_id = imgui_utils::ImGuiPushId(); const std::string &selected_string = get_selected_path( selections->get(), selections->get()); @@ -1136,17 +1137,18 @@ void fme::batch::combo_compact_type_ffnx() const auto tool_tip_pop = glengine::ScopeGuard{ [&]() { tool_tip(gui_labels::compact_tooltip); } }; - static constexpr auto values = std::array{ compact_type::map_order_ffnx }; - static const auto strings = values | std::views::transform(AsString{}) + static constexpr auto values + = std::array{ ff_8::CompactTypeT::map_order_ffnx }; + static const auto strings = values | std::views::transform(AsString{}) | std::ranges::to(); static constexpr auto tool_tips = std::array{ gui_labels::compact_map_order_ffnx_tooltip }; static auto filter = []() { - ff_8::filter tmp_filter{ + ff_8::Filter tmp_filter{ ff_8::FilterSettings::All_Disabled }; - tmp_filter.update(compact_type::map_order_ffnx).enable(); + tmp_filter.update(ff_8::CompactTypeT::map_order_ffnx).enable(); return tmp_filter; }(); @@ -1170,9 +1172,10 @@ void fme::batch::combo_compact_type() { tool_tip(gui_labels::compact_tooltip); } }; static const auto values - = std::array{ compact_type::rows, compact_type::all, - compact_type::move_only_conflicts, compact_type::map_order, - compact_type::map_order_ffnx }; + = std::array{ ff_8::CompactTypeT::rows, ff_8::CompactTypeT::all, + ff_8::CompactTypeT::move_only_conflicts, + ff_8::CompactTypeT::map_order, + ff_8::CompactTypeT::map_order_ffnx }; static const auto strings = values | std::views::transform(AsString{}) | std::ranges::to(); static const auto tool_tips @@ -1204,7 +1207,7 @@ void fme::batch::combo_flatten_type_bpp() const auto tool_tip_pop = glengine::ScopeGuard{ [&]() { tool_tip(gui_labels::flatten_tooltip); } }; - static constexpr auto values = std::array{ flatten_type::bpp }; + static constexpr auto values = std::array{ ff_8::FlattenTypeT::bpp }; static const auto strings = values | std::views::transform(AsString{}) | std::ranges::to(); static constexpr auto tool_tips @@ -1234,11 +1237,11 @@ void fme::batch::combo_flatten_type() { tool_tip(gui_labels::flatten_tooltip); } }; const bool all_or_only_palette = !selections->get() - || (selections->get() != compact_type::map_order) - || (selections->get() != compact_type::map_order_ffnx); + || (selections->get() != ff_8::CompactTypeT::map_order) + || (selections->get() != ff_8::CompactTypeT::map_order_ffnx); static constexpr auto values - = std::array{ flatten_type::bpp, flatten_type::palette, - flatten_type::both }; + = std::array{ ff_8::FlattenTypeT::bpp, ff_8::FlattenTypeT::palette, + ff_8::FlattenTypeT::both }; static const auto strings = values | std::views::transform(AsString{}) | std::ranges::to(); static constexpr auto tool_tips @@ -1246,7 +1249,7 @@ void fme::batch::combo_flatten_type() gui_labels::flatten_palette_tooltip, gui_labels::flatten_both_tooltip }; static constexpr auto values_only_palette - = std::array{ flatten_type::palette }; + = std::array{ ff_8::FlattenTypeT::palette }; static const auto strings_only_palette = values_only_palette | std::views::transform(AsString{}) | std::ranges::to(); @@ -1352,7 +1355,7 @@ bool fme::batch::draw_multi_column_list_box( = std::get<0>(zipped);// const auto& or auto& depending on the range auto &enable = std::get<1>(zipped);// mutable reference - const auto pop_id = PushPopID(); + const auto pop_id = imgui_utils::ImGuiPushId(); const auto pop_column = glengine::ScopeGuard{ &ImGui::NextColumn }; const auto selectable = [&]() { @@ -1398,7 +1401,7 @@ void fme::batch::button_start() spdlog::error("Failed to lock m_selections: shared_ptr is expired."); return; } - const auto pop_id_right = PushPopID(); + const auto pop_id_right = imgui_utils::ImGuiPushId(); const auto spacing = ImGui::GetStyle().ItemInnerSpacing.x; const auto end_function = glengine::ScopeGuard{ []() @@ -1435,7 +1438,7 @@ void fme::batch::button_start() const std::filesystem::path config_path = config_path_values.replace_tags( selections->get(), selections); - auto config = Configuration(config_path); + auto config = ff_8::Configuration(config_path); config->clear(); } m_fields_consumer = archives_group->fields(); @@ -1468,7 +1471,7 @@ void fme::batch::button_stop() spdlog::error("Failed to lock m_selections: shared_ptr is expired."); return; } - const auto pop_id_right = PushPopID(); + const auto pop_id_right = imgui_utils::ImGuiPushId(); const auto spacing = ImGui::GetStyle().ItemInnerSpacing.x; ImGui::SameLine(0, spacing); const auto end_function @@ -1526,7 +1529,7 @@ bool fme::batch::browse_path( const float spacing = style.ItemInnerSpacing.x; const float button_size = ImGui::GetFrameHeight(); const float button_width = button_size * 3.0F; - const auto pop_id = PushPopID(); + const auto pop_id = imgui_utils::ImGuiPushId(); // ImGui text box with browse button // Highlight text box red if the folder doesn't exist { @@ -1559,7 +1562,7 @@ bool fme::batch::browse_path( "##Empty", path_buffer.data(), path_buffer.size())) { // Check if the folder path exists when the text box changes - const auto tmp = safedir(path_buffer.data()); + const auto tmp = ff_8::SafeDir(path_buffer.data()); valid_path = tmp.is_exists() && tmp.is_dir(); changed = true; } @@ -1859,7 +1862,7 @@ void fme::batch::generate_map_sprite() assert(m_coo); // Initialize filters with default disabled state - ff_8::filters filters = { false }; + ff_8::Filters filters = { false }; // Enable specific filters depending on the input type const std::string &selected_string = get_selected_path( @@ -1906,7 +1909,7 @@ void fme::batch::generate_map_sprite() .enable(); filters .update( - compact_type::map_order_ffnx) + ff_8::CompactTypeT::map_order_ffnx) .enable(); break; } @@ -1950,7 +1953,7 @@ void fme::batch::generate_map_sprite() break; } } - ff_8::map_group map_group = { m_field, *m_coo }; + ff_8::MapGroup MapGroup = { m_field, *m_coo }; // Create the map sprite with appropriate settings if (m_coo.has_value() && m_coo.value() != open_viii::LangT::generic) { @@ -1963,11 +1966,11 @@ void fme::batch::generate_map_sprite() .force_loading = selections->get() }; if ( - map_group.opt_coo.has_value() - && map_group.opt_coo.value() != open_viii::LangT::generic) + MapGroup.opt_coo.has_value() + && MapGroup.opt_coo.value() != open_viii::LangT::generic) { // Both are non-generic and present → okay - m_map_sprite = map_sprite{ std::move(map_group), settings, + m_map_sprite = map_sprite{ std::move(MapGroup), settings, filters, m_selections }; return; } @@ -1982,11 +1985,11 @@ void fme::batch::generate_map_sprite() .force_loading = selections->get() }; if ( - !map_group.opt_coo.has_value() - || map_group.opt_coo.value() == open_viii::LangT::generic) + !MapGroup.opt_coo.has_value() + || MapGroup.opt_coo.value() == open_viii::LangT::generic) { // Both are generic or not set → okay - m_map_sprite = map_sprite{ std::move(map_group), settings, + m_map_sprite = map_sprite{ std::move(MapGroup), settings, filters, m_selections }; return; } @@ -2034,19 +2037,19 @@ void fme::batch::compact() // type switch (selections->get()) { - case compact_type::rows: + case ff_8::CompactTypeT::rows: m_map_sprite.compact_rows(); break; - case compact_type::all: + case ff_8::CompactTypeT::all: m_map_sprite.compact_all(); break; - case compact_type::move_only_conflicts: + case ff_8::CompactTypeT::move_only_conflicts: m_map_sprite.compact_move_conflicts_only(); break; - case compact_type::map_order: + case ff_8::CompactTypeT::map_order: m_map_sprite.compact_map_order(); break; - case compact_type::map_order_ffnx: + case ff_8::CompactTypeT::map_order_ffnx: m_map_sprite.compact_map_order_ffnx(); break; } @@ -2086,25 +2089,25 @@ void fme::batch::flatten() { switch (selections->get()) { - case flatten_type::bpp: + case ff_8::FlattenTypeT::bpp: // Only flatten BPP if compact type isn't using map order if ( !selections->get() - || (selections->get() != compact_type::map_order && selections->get() != compact_type::map_order_ffnx)) + || (selections->get() != ff_8::CompactTypeT::map_order && selections->get() != ff_8::CompactTypeT::map_order_ffnx)) { m_map_sprite.flatten_bpp(); } break; - case flatten_type::palette: + case ff_8::FlattenTypeT::palette: m_map_sprite.flatten_palette(); break; - case flatten_type::both: + case ff_8::FlattenTypeT::both: // Only flatten BPP if not using map order if ( !selections->get() - || (selections->get() != compact_type::map_order && selections->get() != compact_type::map_order_ffnx)) + || (selections->get() != ff_8::CompactTypeT::map_order && selections->get() != ff_8::CompactTypeT::map_order_ffnx)) { m_map_sprite.flatten_bpp(); } @@ -2116,9 +2119,9 @@ void fme::batch::flatten() // If the compact strategy is not map-order-based, re-apply compaction if ( selections->get() - != compact_type::map_order + != ff_8::CompactTypeT::map_order && selections->get() - != compact_type::map_order_ffnx) + != ff_8::CompactTypeT::map_order_ffnx) { compact(); } @@ -2338,7 +2341,7 @@ void fme::batch::open_directory_browser() const std::string &selected_path = m_directory_browser.GetDirectory().string(); // todo check if the directory is valid. - // const auto tmp = safedir(selected_path); + // const auto tmp = ff_8::SafeDir(selected_path); switch (m_directory_browser_mode) { case directory_mode::input_mode: @@ -2365,7 +2368,7 @@ void fme::batch::open_directory_browser() } } -fme::batch &fme::batch::operator=(std::weak_ptr new_group) +fme::batch &fme::batch::operator=(std::weak_ptr new_group) { const auto selections = m_selections.lock(); if (!selections) @@ -2437,8 +2440,8 @@ void fme::batch::stop() } fme::batch::batch( - std::weak_ptr existing_selections, - std::weak_ptr existing_group) + std::weak_ptr existing_selections, + std::weak_ptr existing_group) { operator=(std::move(existing_selections)); operator=(std::move(existing_group)); diff --git a/src/opengl/main/gui/batch.hpp b/src/opengl/main/gui/batch.hpp index 966a8662..f69d0c2a 100644 --- a/src/opengl/main/gui/batch.hpp +++ b/src/opengl/main/gui/batch.hpp @@ -4,16 +4,17 @@ #ifndef FIELD_MAP_EDITOR_BATCH_HPP #define FIELD_MAP_EDITOR_BATCH_HPP -#include "archives_group.hpp" #include "cstdint" #include "filebrowser.hpp" #include "format_imgui_text.hpp" #include "generic_combo.hpp" #include "gui_labels.hpp" +#include "map_sprite.hpp" #include "RangeConsumer.hpp" -#include "safedir.hpp" #include "Selections.hpp" #include +#include +#include #include #include namespace fme @@ -26,21 +27,21 @@ class batch input_map_mode, output_mode, }; - std::weak_ptr m_selections = {}; - std::weak_ptr m_archives_group = {}; - bool m_input_path_valid = { false }; - bool m_input_map_path_valid = { false }; - bool m_output_path_valid = { false }; - static constexpr std::size_t m_buffer_size = { 256U }; - std::array m_input_path = {}; - std::array m_input_map_path = {}; - std::array m_output_path = {}; - std::optional m_coo = {}; - std::string m_status = {}; - map_sprite m_map_sprite = {}; - std::uint8_t m_num_columns = { 5 }; - directory_mode m_directory_browser_mode = {}; - ImGui::FileBrowser m_directory_browser{ + std::weak_ptr m_selections = {}; + std::weak_ptr m_archives_group = {}; + bool m_input_path_valid = { false }; + bool m_input_map_path_valid = { false }; + bool m_output_path_valid = { false }; + static constexpr std::size_t m_buffer_size = { 256U }; + std::array m_input_path = {}; + std::array m_input_map_path = {}; + std::array m_output_path = {}; + std::optional m_coo = {}; + std::string m_status = {}; + map_sprite m_map_sprite = {}; + std::uint8_t m_num_columns = { 5 }; + directory_mode m_directory_browser_mode = {}; + ImGui::FileBrowser m_directory_browser{ ImGuiFileBrowserFlags_SelectDirectory | ImGuiFileBrowserFlags_CreateNewDir | ImGuiFileBrowserFlags_EditPathString @@ -116,11 +117,11 @@ class batch void update(float elapsed_time); batch() = default; explicit batch( - std::weak_ptr existing_selections, - std::weak_ptr existing_group); + std::weak_ptr existing_selections, + std::weak_ptr existing_group); bool in_progress() const; void stop(); - batch &operator=(std::weak_ptr new_group); + batch &operator=(std::weak_ptr new_group); batch &operator=(std::weak_ptr new_selections); void draw_window(); }; diff --git a/src/opengl/main/gui/collapsing_tile_info.cpp b/src/opengl/main/gui/collapsing_tile_info.cpp index e034244b..8244a7b0 100644 --- a/src/opengl/main/gui/collapsing_tile_info.cpp +++ b/src/opengl/main/gui/collapsing_tile_info.cpp @@ -1,10 +1,11 @@ #include "collapsing_tile_info.hpp" #include "format_imgui_text.hpp" +#include "gui/ColorConversions.hpp" #include "gui_labels.hpp" -#include "push_pop_id.hpp" #include "tool_tip.hpp" #include #include +#include #include #include namespace fme @@ -53,7 +54,7 @@ bool collapsing_tile_info( { return false; } - const auto pushpopid1 = PushPopID(); + const auto pushpopid1 = imgui_utils::ImGuiPushId(); ImVec2 const table_pos = ImGui::GetCursorScreenPos(); if (ImGui::BeginTable("table_tile_info", 2)) { @@ -119,7 +120,8 @@ bool collapsing_tile_info( if (changed) ImGui::PushStyleColor( - ImGuiCol_Text, ImVec4(colors::Peach)); + ImGuiCol_Text, + ff_8::Colors::to_imvec4(ff_8::Colors::Peach)); format_imgui_text("{}", new_val); diff --git a/src/opengl/main/gui/colors.hpp b/src/opengl/main/gui/colors.hpp deleted file mode 100644 index 81aa6384..00000000 --- a/src/opengl/main/gui/colors.hpp +++ /dev/null @@ -1,981 +0,0 @@ -#ifndef E9FF3A6F_3CCA_4C0B_86CF_665262267C20 -#define E9FF3A6F_3CCA_4C0B_86CF_665262267C20 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -namespace fme -{ -/** - * @brief Represents a color with RGBA components. - * - * This structure holds the red, green, blue, and alpha components of a color. - * The components are stored as 8-bit unsigned integers (0-255). - */ -struct [[nodiscard]] color -{ - std::uint8_t r = {};//!< Red component (0-255) - std::uint8_t g = {};//!< Green component (0-255) - std::uint8_t b = {};//!< Blue component (0-255) - std::uint8_t a = { - (std::numeric_limits::max)() - };//!< Alpha (opacity) component (0-255) - - /** - * @brief Default constructor. - * - * Initializes the color to fully opaque black. - */ - constexpr color() noexcept = default; - - /** - * @brief Copy constructor. - */ - constexpr color(const color &) noexcept = default; - - /** - * @brief Move constructor. - */ - constexpr color(color &&) noexcept = default; - - /** - * @brief Copy assignment operator. - */ - constexpr color &operator=(const color &) noexcept = default; - - /** - * @brief Move assignment operator. - */ - constexpr color &operator=(color &&) noexcept = default; - - /** - * @brief Maximum value for floating-point conversions. - * - * @tparam float_t A floating-point type. - */ - template - static constexpr auto max_f - = static_cast((std::numeric_limits::max)()); - - - /** - * @brief Minimum value for floating-point conversions. - * - * @tparam float_t A floating-point type. - */ - template - static constexpr auto min_f - = static_cast((std::numeric_limits::min)()); - - /** - * @brief Maximum value for integral conversions. - * - * @tparam int_t An integral type. - */ - template - static constexpr auto max_i - = static_cast((std::numeric_limits::max)()); - - /** - * @brief Constructs a color from an ImVec4 instance. - * - * @param c The ImVec4 object containing RGBA components. - */ - explicit constexpr color(const ImVec4 c) noexcept - : color( - c.x, - c.y, - c.z, - c.w) - { - } - - - /// Construct from glm::vec3 (assumes 0.0–1.0 range, opaque alpha) - explicit color(const glm::vec3 &v) - : r(static_cast( - glm::clamp( - v.r, - 0.0f, - 1.0f) - * max_f)) - , g(static_cast( - glm::clamp( - v.g, - 0.0f, - 1.0f) - * max_f)) - , b(static_cast( - glm::clamp( - v.b, - 0.0f, - 1.0f) - * max_f)) - , a((std::numeric_limits::max)()) - { - } - - /// Construct from glm::vec4 (assumes 0.0–1.0 range including alpha) - explicit color(const glm::vec4 &v) - : r(static_cast( - glm::clamp( - v.r, - 0.0f, - 1.0f) - * max_f)) - , g(static_cast( - glm::clamp( - v.g, - 0.0f, - 1.0f) - * max_f)) - , b(static_cast( - glm::clamp( - v.b, - 0.0f, - 1.0f) - * max_f)) - , a(static_cast( - glm::clamp( - v.a, - 0.0f, - 1.0f) - * max_f)) - { - } - - - explicit color(const glm::ivec4 &v) - : r(static_cast(v.x)) - , g(static_cast(v.y)) - , b(static_cast(v.z)) - , a(static_cast(v.w)) - { - } - - /** - * @brief Constructs a color from an ImColor instance. - * - * @param c The ImColor object containing RGBA components. - */ - explicit constexpr color(const ImColor &c) noexcept - : color(c.Value) - { - } - - - /** - * @brief Constructs a color from integral RGBA components. - * - * @tparam int_t An integral type. - * @param in_r Red component. - * @param in_g Green component. - * @param in_b Blue component. - * @param in_a Alpha (opacity) component. - */ - template - constexpr color( - int_t in_r, - int_t in_g, - int_t in_b, - int_t in_a) noexcept - { -#if defined(__cpp_lib_saturation_arithmetic) \ - && __cpp_lib_saturation_arithmetic >= 202311L - r = std::saturate_cast(in_r); - g = std::saturate_cast(in_g); - b = std::saturate_cast(in_b); - a = std::saturate_cast(in_a); -#else - r = static_cast(in_r); - g = static_cast(in_g); - b = static_cast(in_b); - a = static_cast(in_a); -#endif - } - - /** - * @brief Constructs a color from integral RGB components with default - * alpha. - * - * @tparam int_t An integral type. - * @param in_r Red component. - * @param in_g Green component. - * @param in_b Blue component. - */ - template - constexpr color( - int_t in_r, - int_t in_g, - int_t in_b) noexcept - : color( - in_r, - in_g, - in_b, - max_i) - { - } - - /** - * @brief Constructs a color from floating-point RGBA components. - * - * @tparam float_t A floating-point type. - * @param in_r Red component (0.0-1.0). - * @param in_g Green component (0.0-1.0). - * @param in_b Blue component (0.0-1.0). - * @param in_a Alpha (opacity) component (0.0-1.0). - */ - template - constexpr color( - float_t in_r, - float_t in_g, - float_t in_b, - float_t in_a) noexcept - { -#if defined(__cpp_lib_saturation_arithmetic) \ - && __cpp_lib_saturation_arithmetic >= 202311L - r = std::saturate_cast(in_r * max_f); - g = std::saturate_cast(in_g * max_f); - b = std::saturate_cast(in_b * max_f); - a = std::saturate_cast(in_a * max_f); -#else - r = static_cast(in_r * max_f); - g = static_cast(in_g * max_f); - b = static_cast(in_b * max_f); - a = static_cast(in_a * max_f); -#endif - } - - /** - * @brief Constructs a color from floating-point RGB components with - * default alpha. - * - * @tparam float_t A floating-point type. - * @param in_r Red component (0.0-1.0). - * @param in_g Green component (0.0-1.0). - * @param in_b Blue component (0.0-1.0). - */ - template - constexpr color( - float_t in_r, - float_t in_g, - float_t in_b) noexcept - : color( - in_r, - in_g, - in_b, - float_t{ 1 }) - { - } - - /** - * @brief Converts the color to a std::uint32_t. - * - * @return An std::uint32_t object representing the color. - */ - [[nodiscard]] explicit constexpr operator std::uint32_t() const noexcept - { - return IM_COL32(r, g, b, a);// std::bit_cast(*this); - } - - /** - * @brief Converts the color to an ImColor object. - * - * @return An ImColor object representing the color. - */ - [[nodiscard]] constexpr operator ImColor() const noexcept - { - return ImColor( - static_cast(r), - static_cast(g), - static_cast(b), - static_cast(a)); - } - - /** - * @brief Converts the color to an ImVec4 object. - * - * @return An ImVec4 object representing the color. - */ - [[nodiscard]] constexpr operator ImVec4() const noexcept - { - return { static_cast(r) / max_f, - static_cast(g) / max_f, - static_cast(b) / max_f, - static_cast(a) / max_f }; - } - - - /** - * @brief Converts the color to an ImVec4 object. - * - * @return An ImVec4 object representing the color. - */ - [[nodiscard]] constexpr operator glm::vec4() const noexcept - { - return { static_cast(r) / max_f, - static_cast(g) / max_f, - static_cast(b) / max_f, - static_cast(a) / max_f }; - } - - // Calculate difference with another color - [[nodiscard]] double difference(const color &other) const - { - int dr = static_cast(r) - static_cast(other.r); - int dg = static_cast(g) - static_cast(other.g); - int db = static_cast(b) - static_cast(other.b); - int da = static_cast(a) - static_cast(other.a); - - return std::sqrt(dr * dr + dg * dg + db * db + da * da); - } - - /** - * @brief Compares two colors for equality or ordering. - * - * @param other Another color to compare with. - * @return A strong ordering result. - */ - constexpr auto operator<=>(const color &) const = default; - - /** - * @brief Fades the color's RGB by a given value. - * - * If the value is positive, the color will become brighter. If negative, - * the color will become darker. - * - * @param fadeValue A float that determines the amount of fade. Positive - * values brighten the color, negative values darken it. - */ - [[nodiscard]] constexpr color fade(float fadeValue) const noexcept - { - // Clamp the fadeValue to avoid overflowing the color channels - const float factor = 1.0f + fadeValue;// The factor by which the color - // channels will be adjusted - return { static_cast( - std::clamp(r * factor, min_f, max_f)), - static_cast( - std::clamp(g * factor, min_f, max_f)), - static_cast( - std::clamp(b * factor, min_f, max_f)), - a }; - } - - /** - * @brief Fades the color's alpha by a given value. - * - * If the value is positive, the color will become less transparent. If - * negative, the color will become more transparent. - * - * @param fadeValue A float that determines the amount of fade. Positive - * values brighten the color, negative values darken it. - */ - [[nodiscard]] constexpr color fade_alpha(float fadeValue) const noexcept - { - // Clamp the fadeValue to avoid overflowing the color channels - const float factor = 1.0f + fadeValue;// The factor by which the color - // channels will be adjusted - return { r, g, b, - static_cast( - std::clamp(a * factor, min_f, max_f)) }; - } - - [[nodiscard]] constexpr color opaque() const noexcept - { - return { r, g, b }; - } -}; - -struct colors -{ - // Static asserts to verify invariants and assumptions - static_assert( - std::is_trivially_copyable_v, - "color must be trivially copyable."); - static_assert( - std::is_standard_layout_v, - "color must have a standard layout."); - static_assert( - sizeof(color) == 4, - "color must occupy exactly 4 bytes."); - static_assert( - std::is_nothrow_default_constructible_v, - "color must be nothrow default constructible."); - static_assert( - std::is_nothrow_copy_constructible_v, - "color must be nothrow copy constructible."); - static_assert( - std::is_nothrow_move_constructible_v, - "color must be nothrow move constructible."); - static_assert( - std::is_nothrow_copy_assignable_v, - "color must be nothrow copy assignable."); - static_assert( - std::is_nothrow_move_assignable_v, - "color must be nothrow move assignable."); - - // Static checks for default RGBA values - static_assert( - color{}.r == 0, - "Default red component of color must be 0."); - static_assert( - color{}.g == 0, - "Default green component of color must be 0."); - static_assert( - color{}.b == 0, - "Default blue component of color must be 0."); - static_assert( - color{}.a == std::numeric_limits::max(), - "Default alpha component of color must be fully opaque."); - - static_assert( - color{}.r == 0 && color{}.g == 0 && color{}.b == 0 && color{}.a == 255, - "Default constructor failed!"); - - static_assert( - color( - 255, - 128, - 64, - 32) - .r - == 255 - && color( - 255, - 128, - 64, - 32) - .g - == 128 - && color( - 255, - 128, - 64, - 32) - .b - == 64 - && color( - 255, - 128, - 64, - 32) - .a - == 32, - "Integral constructor failed!"); - - static_assert( - color( - 255, - 128, - 64) - .r - == 255 - && color( - 255, - 128, - 64) - .g - == 128 - && color( - 255, - 128, - 64) - .b - == 64 - && color( - 255, - 128, - 64) - .a - == 255, - "Integral constructor with default alpha failed!"); - - static_assert( - color( - 1.0f, - 0.5f, - 0.25f, - 0.125f) - .r - == 255 - && color( - 1.0f, - 0.5f, - 0.25f, - 0.125f) - .g - == 127 - && color( - 1.0f, - 0.5f, - 0.25f, - 0.125f) - .b - == 63 - && color( - 1.0f, - 0.5f, - 0.25f, - 0.125f) - .a - == 31, - "Floating-point constructor failed!"); - - static_assert( - color( - 1.0f, - 0.5f, - 0.25f) - .r - == 255 - && color( - 1.0f, - 0.5f, - 0.25f) - .g - == 127 - && color( - 1.0f, - 0.5f, - 0.25f) - .b - == 63 - && color( - 1.0f, - 0.5f, - 0.25f) - .a - == 255, - "Floating-point constructor with default alpha failed!"); - - static inline const ImGuiStyle DarkStyle = []() - { - auto s = ImGuiStyle{}; - ImGui::StyleColorsDark(&s); - return s; - }(); - - static constexpr color Red = { 255, 0, 0 }; //!< Fully red. - static constexpr color Green = { 0, 255, 0 }; //!< Fully green. - static constexpr color Blue = { 0, 0, 255 }; //!< Fully blue. - static constexpr color White = { 255, 255, 255 };//!< Fully white. - static constexpr color Black = { 0, 0, 0 }; //!< Fully black. - static constexpr color Transparent = { 0, 0, 0, 0 };//!< Fully transparent. - static constexpr color Yellow = { 255, 255, 0 }; //!< Fully yellow. - static constexpr color Cyan = { 0, 255, 255 }; //!< Fully cyan. - static constexpr color Magenta = { 255, 0, 255 }; //!< Fully magenta. - static constexpr color Gray = { 128, 128, 128 };//!< Neutral gray. - static constexpr color LightGray = { 192, 192, 192 };//!< Light gray. - static constexpr color DarkGray = { 64, 64, 64 }; //!< Dark gray. - static constexpr color Orange = { 255, 165, 0 }; //!< Orange color. - static constexpr color Peach - = { 255, 153, 102 };//!< Gentle, warm orange variant - static constexpr color Purple = { 128, 0, 128 }; //!< Purple color. - static constexpr color Pink = { 255, 192, 203 };//!< Pink color. - static constexpr color Brown = { 78, 39, 5 }; //!< Brown color. - - static constexpr auto ColorValues - = std::array{ Red, Green, Blue, White, Black, Transparent, - Yellow, Cyan, Magenta, Gray, LightGray, DarkGray, - Orange, Peach, Purple, Pink, Brown }; - - static constexpr auto ColorNames - = std::array{ - "Red", "Green", "Blue", "White", "Black", "Transparent", - "Yellow", "Cyan", "Magenta", "Gray", "LightGray", "DarkGray", - "Orange", "Peach", "Purple", "Pink", "Brown" - }; - - // darkstyle imgui color blue tint - static inline const color Button - = color{ DarkStyle.Colors[ImGuiCol_Button] }; - static inline const color ButtonHovered - = color{ DarkStyle.Colors[ImGuiCol_ButtonHovered] }; - static inline const color ButtonActive - = color{ DarkStyle.Colors[ImGuiCol_ButtonActive] }; - - // Green tint - static constexpr color ButtonGreen - = color{ ImVec4(0.26f, 0.98f, 0.26f, 0.40f) }; - static constexpr color ButtonGreenHovered - = color{ ImVec4(0.26f, 0.98f, 0.26f, 1.00f) }; - static constexpr color ButtonGreenActive - = color{ ImVec4(0.06f, 0.53f, 0.06f, 1.00f) }; - - // Red tint - static constexpr color ButtonRed - = color{ ImVec4(0.98f, 0.26f, 0.26f, 0.40f) }; - static constexpr color ButtonRedHovered - = color{ ImVec4(0.98f, 0.26f, 0.26f, 1.00f) }; - static constexpr color ButtonRedActive - = color{ ImVec4(0.53f, 0.06f, 0.06f, 1.00f) }; - - // Dark Blue tint - static constexpr color ButtonDarkBlue - = color{ ImVec4(0.26f, 0.26f, 0.59f, 0.40f) }; - static constexpr color ButtonDarkBlueHovered - = color{ ImVec4(0.26f, 0.26f, 0.59f, 1.00f) }; - static constexpr color ButtonDarkBlueActive - = color{ ImVec4(0.06f, 0.06f, 0.53f, 1.00f) }; - - // Yellow tint - static constexpr color ButtonYellow - = color{ ImVec4(0.98f, 0.98f, 0.26f, 0.40f) }; - static constexpr color ButtonYellowHovered - = color{ ImVec4(0.98f, 0.98f, 0.26f, 1.00f) }; - static constexpr color ButtonYellowActive - = color{ ImVec4(0.53f, 0.53f, 0.06f, 1.00f) }; - - // Orange tint - static constexpr color ButtonOrange - = color{ ImVec4(0.98f, 0.59f, 0.26f, 0.40f) }; - static constexpr color ButtonOrangeHovered - = color{ ImVec4(0.98f, 0.59f, 0.26f, 1.00f) }; - static constexpr color ButtonOrangeActive - = color{ ImVec4(0.53f, 0.26f, 0.06f, 1.00f) }; - - // Pink tint - static constexpr color ButtonPink - = color{ ImVec4(0.98f, 0.26f, 0.59f, 0.40f) }; - static constexpr color ButtonPinkHovered - = color{ ImVec4(0.98f, 0.26f, 0.59f, 1.00f) }; - static constexpr color ButtonPinkActive - = color{ ImVec4(0.53f, 0.06f, 0.29f, 1.00f) }; - - // Tan tint - static constexpr color ButtonTan - = color{ ImVec4(0.98f, 0.84f, 0.57f, 0.40f) }; - static constexpr color ButtonTanHovered - = color{ ImVec4(0.98f, 0.84f, 0.57f, 1.00f) }; - static constexpr color ButtonTanActive - = color{ ImVec4(0.53f, 0.48f, 0.29f, 1.00f) }; - - // tableColors - static constexpr color TableDarkRed = color{ 120, 40, 40 }; - static constexpr color TableLightDarkRed = color{ 160, 60, 60 }; - static constexpr color TableDarkRedHovered = TableLightDarkRed.fade(0.4F); - static constexpr color TableDarkRedActive = color{ 100, 20, 20 }; - - static constexpr color TableDarkGray = color{ 80, 80, 80 }; - static constexpr color TableLightDarkGray = color{ 100, 100, 100 }; - static constexpr color TableDarkGrayHovered - = TableLightDarkGray.fade(0.4F); - static constexpr color TableDarkGrayActive = color{ 50, 50, 50 }; - - static constexpr color TableDarkBlue = color{ 40, 60, 120 }; - static constexpr color TableLightDarkBlue = color{ 60, 90, 160 }; - static constexpr color TableDarkBlueHovered - = TableLightDarkBlue.fade(0.4F); - static constexpr color TableDarkBlueActive = color{ 20, 40, 100 }; - - static constexpr color TableDarkGreen = color{ 40, 120, 60 }; - static constexpr color TableLightDarkGreen = color{ 60, 160, 90 }; - static constexpr color TableDarkGreenHovered - = TableLightDarkGreen.fade(0.4F); - static constexpr color TableDarkGreenActive = color{ 20, 100, 40 }; - - static constexpr color TableDarkPurple = color{ 80, 40, 120 }; - static constexpr color TableLightDarkPurple = color{ 110, 60, 160 }; - static constexpr color TableDarkPurpleHovered - = TableLightDarkPurple.fade(0.4F); - static constexpr color TableDarkPurpleActive = color{ 50, 20, 100 }; - - static constexpr color TableDarkTeal = color{ 40, 100, 100 }; - static constexpr color TableLightDarkTeal = color{ 60, 140, 140 }; - static constexpr color TableDarkTealHovered - = TableLightDarkTeal.fade(0.4F); - static constexpr color TableDarkTealActive = color{ 20, 80, 80 }; - - static constexpr color TableDarkOrange = color{ 120, 80, 40 }; - static constexpr color TableLightDarkOrange = color{ 160, 110, 60 }; - static constexpr color TableDarkOrangeHovered - = TableLightDarkOrange.fade(0.4F); - static constexpr color TableDarkOrangeActive = color{ 100, 50, 20 }; - - - [[nodiscard]] static inline glm::vec3 hsv2rgb(const glm::vec3 &c) - { - static const glm::vec4 K - = glm::vec4(1.0f, 2.0f / 3.0f, 1.0f / 3.0f, 3.0f); - // Replace GLSL c.xxx + K.xyz with explicit vector construction - const glm::vec3 p = glm::abs( - glm::fract(glm::vec3(c.x) + glm::vec3(K.x, K.y, K.z)) * 6.0f - - glm::vec3(K.w)); - // Replace GLSL mix and clamp with GLM equivalents, ensuring correct - // argument types - return c.z - * glm::mix( - glm::vec3(K.x), - glm::clamp(p - glm::vec3(K.x), 0.0f, 1.0f), - c.y); - } - - [[nodiscard]] static inline glm::vec4 - encode_uint_to_rgba(const unsigned int id) - { - static constexpr float GOLDEN_RATIO = 0.61803398875f; - static constexpr float SATURATION = 0.8f; - static constexpr float VALUE = 0.9f; - const float hue = glm::fract(static_cast(id) * GOLDEN_RATIO); - const glm::vec3 temp_color = hsv2rgb( - glm::vec3( - hue, - SATURATION, - VALUE));// Explicitly round to integers for comparison - // glm::vec3 rounded_color = glm::floor(temp_color * - // 255.0f + 0.5f); - /// return glm::vec4(rounded_color / 255.0f, 1.0f);// Keep in [0,1] - /// for rendering - return glm::vec4(temp_color, 1.f); - } -}; - - -enum class BackgroundSettings : uint8_t -{ - // Presets - Default = 0, - - // Color count bit - OneColor = Default, - TwoColors = 1 << 0, - - // Pattern bit - Checkerboard = Default, - Solid = 1 << 1, - - -}; - - -// Bitwise operators -inline constexpr BackgroundSettings operator|( - BackgroundSettings lhs, - BackgroundSettings rhs) -{ - return static_cast( - std::to_underlying(lhs) | std::to_underlying(rhs)); -} - -inline constexpr BackgroundSettings operator&( - BackgroundSettings lhs, - BackgroundSettings rhs) -{ - return static_cast( - std::to_underlying(lhs) & std::to_underlying(rhs)); -} - -inline constexpr BackgroundSettings &operator|=( - BackgroundSettings &lhs, - BackgroundSettings rhs) -{ - lhs = lhs | rhs; - return lhs; -} - -inline constexpr bool ValidateBackgroundSettings(BackgroundSettings setting) -{ - // Must only contain valid bits - if ( - std::to_underlying(setting) - & ~std::to_underlying( - BackgroundSettings::Solid | BackgroundSettings::TwoColors)) - { - if (!std::is_constant_evaluated()) - { - spdlog::debug( - "Invalid BackgroundSettings: contains unknown bits ({:#X})", - std::to_underlying(setting)); - } - return false; - } - - // Disallow Solid + TwoColors - if ( - (setting & (BackgroundSettings::Solid | BackgroundSettings::TwoColors)) - == (BackgroundSettings::Solid | BackgroundSettings::TwoColors)) - { - if (!std::is_constant_evaluated()) - { - spdlog::debug( - "Invalid BackgroundSettings: Solid and TwoColors cannot be " - "combined ({:#X})", - std::to_underlying(setting)); - } - return false; - } - - return true; -} - -inline constexpr bool HasFlag( - BackgroundSettings value, - BackgroundSettings flag) -{ - if (flag == BackgroundSettings::Default) - return value == BackgroundSettings::Default; - else - return (value & flag) != BackgroundSettings::Default; -} - - -static_assert(ValidateBackgroundSettings(BackgroundSettings::Default)); -static_assert(!ValidateBackgroundSettings( - BackgroundSettings::TwoColors | BackgroundSettings::Solid)); - -// Static asserts to validate HasFlag logic - -static_assert( - HasFlag( - BackgroundSettings::Default, - BackgroundSettings::Default), - "Default has Default"); -static_assert( - HasFlag( - BackgroundSettings::Default, - BackgroundSettings::OneColor), - "Default has OneColor (alias of Default)"); -static_assert( - !HasFlag( - BackgroundSettings::Default, - BackgroundSettings::TwoColors), - "Default does not have TwoColors"); -static_assert( - HasFlag( - BackgroundSettings::TwoColors, - BackgroundSettings::TwoColors), - "TwoColors has TwoColors"); -static_assert( - !HasFlag( - BackgroundSettings::TwoColors, - BackgroundSettings::Default), - "TwoColors does not have Default"); -static_assert( - !HasFlag( - BackgroundSettings::TwoColors, - BackgroundSettings::OneColor), - "TwoColors does not have OneColor (Default)"); -static_assert( - !HasFlag( - BackgroundSettings::OneColor, - BackgroundSettings::TwoColors), - "OneColor (Default) does not have TwoColors"); - -// Also test pattern bits -static_assert( - HasFlag( - BackgroundSettings::Default, - BackgroundSettings::Checkerboard), - "Default has Checkerboard"); -static_assert( - !HasFlag( - BackgroundSettings::Default, - BackgroundSettings::Solid), - "Default does not have Solid"); -static_assert( - HasFlag( - BackgroundSettings::Solid, - BackgroundSettings::Solid), - "Solid has Solid"); -static_assert( - !HasFlag( - BackgroundSettings::Solid, - BackgroundSettings::Checkerboard), - "Solid does not have Checkerboard"); - -constexpr void SetFlag( - BackgroundSettings ¤t, - BackgroundSettings flag, - bool enabled) -{ - if (flag == BackgroundSettings::Default) - { - // No operation if flag is Default - return; - } - - auto value = std::to_underlying(current); - auto flagBit = std::to_underlying(flag); - - if (enabled) - { - value |= flagBit;// Set the bit - } - else - { - value &= ~flagBit;// Clear the bit - } - - current = static_cast(value); - - return; -} - -[[nodiscard]] constexpr BackgroundSettings SetFlag( - BackgroundSettings &&initial, - BackgroundSettings flag, - bool enabled) -{ - SetFlag(initial, flag, enabled); - return initial; -} - -static_assert( - SetFlag( - BackgroundSettings::OneColor, - BackgroundSettings::TwoColors, - true) - == BackgroundSettings::TwoColors, - "Enable TwoColors failed"); -static_assert( - SetFlag( - BackgroundSettings::TwoColors, - BackgroundSettings::TwoColors, - false) - == BackgroundSettings::OneColor, - "Disable TwoColors failed"); - -static_assert( - SetFlag( - BackgroundSettings::Checkerboard, - BackgroundSettings::Solid, - true) - == BackgroundSettings::Solid, - "Enable Solid failed"); -static_assert( - SetFlag( - BackgroundSettings::Solid, - BackgroundSettings::Solid, - false) - == BackgroundSettings::Checkerboard, - "Disable Solid failed"); - -// Test no-op when flag == Default -static_assert( - SetFlag( - BackgroundSettings::Solid, - BackgroundSettings::Default, - true) - == BackgroundSettings::Solid, - "No-op with Default flag failed"); -static_assert( - SetFlag( - BackgroundSettings::TwoColors, - BackgroundSettings::Default, - false) - == BackgroundSettings::TwoColors, - "No-op with Default flag failed"); - - -}// namespace fme - -#endif /* E9FF3A6F_3CCA_4C0B_86CF_665262267C20 */ diff --git a/src/opengl/main/gui/compact_type.hpp b/src/opengl/main/gui/compact_type.hpp index 1aa1af1d..1270408f 100644 --- a/src/opengl/main/gui/compact_type.hpp +++ b/src/opengl/main/gui/compact_type.hpp @@ -8,14 +8,6 @@ #include namespace fme { -enum struct compact_type : std::uint8_t -{ - rows, - all, - move_only_conflicts, - map_order, - map_order_ffnx -}; enum struct input_types : std::uint8_t { mim, @@ -82,12 +74,6 @@ enum struct output_types : std::uint8_t return std::nullopt;// input_types::mim has no mapping } } -enum struct flatten_type : std::uint8_t -{ - bpp, - palette, - both, -}; enum struct root_path_types : std::uint8_t { selected_path, diff --git a/src/opengl/main/gui/create_tile_button.cpp b/src/opengl/main/gui/create_tile_button.cpp index 51412d21..396d197f 100644 --- a/src/opengl/main/gui/create_tile_button.cpp +++ b/src/opengl/main/gui/create_tile_button.cpp @@ -1,4 +1,5 @@ #include "create_tile_button.hpp" +#include "gui/ColorConversions.hpp" using namespace open_viii::graphics::background; template [[nodiscard]] bool fme::create_tile_button( @@ -77,19 +78,23 @@ template int pop_var_count = {}; if (options.button_color.has_value()) { - ImGui::PushStyleColor(ImGuiCol_Button, options.button_color.value()); + ImGui::PushStyleColor( + ImGuiCol_Button, + ff_8::Colors::to_imvec4(options.button_color.value())); ++pop_count; } if (options.button_hover_color.has_value()) { ImGui::PushStyleColor( - ImGuiCol_ButtonHovered, options.button_hover_color.value()); + ImGuiCol_ButtonHovered, + ff_8::Colors::to_imvec4(options.button_hover_color.value())); ++pop_count; } if (options.button_active_color.has_value()) { ImGui::PushStyleColor( - ImGuiCol_ButtonActive, options.button_active_color.value()); + ImGuiCol_ButtonActive, + ff_8::Colors::to_imvec4(options.button_active_color.value())); ++pop_count; } if (options.padding_size.has_value()) @@ -108,7 +113,7 @@ template if (pop_var_count > 0) ImGui::PopStyleVar(pop_var_count); } }; - const auto pop_id = PushPopID(); + const auto pop_id = imgui_utils::ImGuiPushId(); return ImGui::ImageButton( "##tile_image_button", @@ -118,8 +123,8 @@ template : options.size), uv0, uv1, - ImVec4{ options.background_color }, - ImVec4{ options.tint_color }); + ff_8::Colors::to_imvec4(options.background_color), + ff_8::Colors::to_imvec4(options.tint_color)); } @@ -156,19 +161,22 @@ template [[nodiscard]] bool fme::create_tile_button( if (m_options.button_color.has_value()) { ImGui::PushStyleColor( - ImGuiCol_Button, m_options.button_color.value()); + ImGuiCol_Button, + ff_8::Colors::to_imvec4(m_options.button_color.value())); ++pop_count; } if (m_options.button_hover_color.has_value()) { ImGui::PushStyleColor( - ImGuiCol_ButtonHovered, m_options.button_hover_color.value()); + ImGuiCol_ButtonHovered, + ff_8::Colors::to_imvec4(m_options.button_hover_color.value())); ++pop_count; } if (m_options.button_active_color.has_value()) { ImGui::PushStyleColor( - ImGuiCol_ButtonActive, m_options.button_active_color.value()); + ImGuiCol_ButtonActive, + ff_8::Colors::to_imvec4(m_options.button_active_color.value())); ++pop_count; } if (m_options.padding_size.has_value()) @@ -187,7 +195,7 @@ template [[nodiscard]] bool fme::create_tile_button( if (pop_var_count > 0) ImGui::PopStyleVar(pop_var_count); } }; - const auto pop_id = PushPopID(); + const auto pop_id = imgui_utils::ImGuiPushId(); ImVec2 uv0 = ImVec2(0.0f, 0.0f); ImVec2 uv1 = ImVec2(1.0f, 1.0f); return ImGui::ImageButton( @@ -199,6 +207,6 @@ template [[nodiscard]] bool fme::create_tile_button( : m_options.size), uv0, uv1, - ImVec4{ m_options.background_color }, - ImVec4{ m_options.tint_color }); + ff_8::Colors::to_imvec4(m_options.background_color), + ff_8::Colors::to_imvec4(m_options.tint_color)); } \ No newline at end of file diff --git a/src/opengl/main/gui/create_tile_button.hpp b/src/opengl/main/gui/create_tile_button.hpp index d5108c9e..d7d9fec8 100644 --- a/src/opengl/main/gui/create_tile_button.hpp +++ b/src/opengl/main/gui/create_tile_button.hpp @@ -1,10 +1,10 @@ #ifndef DF4C3AF7_C3A6_4F62_8336_B0EF72752E11 #define DF4C3AF7_C3A6_4F62_8336_B0EF72752E11 -#include "colors.hpp" #include "map_sprite.hpp" -#include "push_pop_id.hpp" +#include #include #include +#include #include namespace fme { @@ -17,21 +17,21 @@ struct tile_button_options /** * @brief Size of the button in pixels. */ - ImVec2 size = {}; + ImVec2 size = {}; /** * @brief Background color of the button. * This is the color drawn before the image gets overlaid on top. * Defaults to `sf::Color::Transparent`. */ - fme::color background_color = { colors::Transparent }; + ff_8::Color background_color = { ff_8::Colors::Transparent }; /** * @brief Tint color applied to the button image. * This color is applied over the image itself, modifying its appearance. * Defaults to `sf::Color::White` (no tint). */ - fme::color tint_color = { colors::White }; + ff_8::Color tint_color = { ff_8::Colors::White }; /** * @brief Optional override for the default button color. @@ -40,7 +40,7 @@ struct tile_button_options * `ImGui::PushStyleColor(ImGuiCol_Button)`. If not set, the style's * default button color is used. */ - std::optional button_color = {}; + std::optional button_color = {}; /** * @brief Optional color for the button when hovered. @@ -49,7 +49,7 @@ struct tile_button_options * `ImGui::PushStyleColor(ImGuiCol_ButtonHovered)`. If not set, the style's * default hover color is used. */ - std::optional button_hover_color = {}; + std::optional button_hover_color = {}; /** * @brief Optional color for the button when active (pressed). @@ -58,7 +58,7 @@ struct tile_button_options * `ImGui::PushStyleColor(ImGuiCol_ButtonActive)`. If not set, the style's * default active color is used. */ - std::optional button_active_color = {}; + std::optional button_active_color = {}; /** * @brief Optional padding size around the image in pixels. @@ -68,7 +68,7 @@ struct tile_button_options * be applied using `ImGui::PushStyleVar(ImGuiStyleVar_FramePadding)`. If * not set, the style's default padding size is used. */ - std::optional padding_size = {}; + std::optional padding_size = {}; }; template @@ -85,7 +85,8 @@ struct [[nodiscard]] create_color_button public: create_color_button(tile_button_options options = {}) : m_options(std::move(options)) - , m_transparent_texture(static_cast(colors::Transparent)) + , m_transparent_texture( + static_cast(ff_8::Colors::Transparent)) { } bool operator()() const; diff --git a/src/opengl/main/gui/custom_paths_window.cpp b/src/opengl/main/gui/custom_paths_window.cpp index a022c6a4..23da8d9c 100644 --- a/src/opengl/main/gui/custom_paths_window.cpp +++ b/src/opengl/main/gui/custom_paths_window.cpp @@ -1,5 +1,6 @@ #include "custom_paths_window.hpp" #include "as_string.hpp" +#include "ColorConversions.hpp" #include "fa_icons.hpp" #include "formatters.hpp" #include @@ -147,7 +148,7 @@ static const auto trim = [](const std::string &str) -> std::string std::to_underlying(fme::PatternSelector::End)> result{}; - fme::for_each_enum< + ff_8::for_each_enum< fme::PatternSelector, std::to_underlying(fme::PatternSelector::End)>( [&]() @@ -265,7 +266,7 @@ fme::VectorOrString fme::custom_paths_window::vector_or_string() const bool found = false; - fme::for_each_enum< + ff_8::for_each_enum< fme::PatternSelector, std::to_underlying(fme::PatternSelector::End)>( [&]() @@ -300,7 +301,7 @@ std::string *fme::custom_paths_window::get_current_string_value_mutable() const return nullptr; } std::string *result = nullptr; - fme::for_each_enum< + ff_8::for_each_enum< fme::PatternSelector, std::to_underlying(fme::PatternSelector::End)>( [&]() @@ -345,7 +346,7 @@ std::vector * return nullptr; } std::vector *result = nullptr; - fme::for_each_enum< + ff_8::for_each_enum< fme::PatternSelector, std::to_underlying(fme::PatternSelector::End)>( [&]() @@ -486,7 +487,7 @@ void fme::custom_paths_window::save_pattern() const return; } bool found = false; - fme::for_each_enum< + ff_8::for_each_enum< fme::PatternSelector, std::to_underlying(fme::PatternSelector::End)>( [&]() @@ -597,14 +598,16 @@ bool fme::custom_paths_window::vector_pattern() const { ImGui::TableSetBgColor( ImGuiTableBgTarget_RowBg0, - ImU32{ colors::TableDarkTeal.fade(-0.4F) });// Dark red + ff_8::Colors::to_imU32( + ff_8::Colors::TableDarkTeal.fade(-0.4F)));// Dark red } else { ImGui::TableSetBgColor( ImGuiTableBgTarget_RowBg0, - ImU32{ colors::TableLightDarkTeal.fade( - -0.4F) });// Slightly lighter dark red + ff_8::Colors::to_imU32( + ff_8::Colors::TableLightDarkTeal.fade( + -0.4F)));// Slightly lighter dark red } bg_color = !bg_color; ImGui::TableNextColumn(); @@ -659,7 +662,7 @@ bool fme::custom_paths_window::vector_pattern() const selections->get() != static_cast(index)) { - const auto pop_id = PushPopID(); + const auto pop_id = imgui_utils::ImGuiPushId(); // Edit button if (ImGui::Button( fmt::format("{}##edit_{}", ICON_FA_PEN, index).c_str())) @@ -720,14 +723,16 @@ bool fme::custom_paths_window::vector_pattern() const { ImGui::TableSetBgColor( ImGuiTableBgTarget_RowBg0, - ImU32{ colors::TableDarkTeal.fade(-0.4F) });// Dark red + ff_8::Colors::to_imU32( + ff_8::Colors::TableDarkTeal.fade(-0.4F)));// Dark red } else { ImGui::TableSetBgColor( ImGuiTableBgTarget_RowBg0, - ImU32{ colors::TableLightDarkTeal.fade( - -0.4F) });// Slightly lighter dark red + ff_8::Colors::to_imU32( + ff_8::Colors::TableLightDarkTeal.fade( + -0.4F)));// Slightly lighter dark red } ImGui::TableNextColumn(); const char *add = "Add New Pattern"; @@ -893,20 +898,22 @@ bool fme::custom_paths_window::child_keys() const { ImGui::TableSetBgColor( ImGuiTableBgTarget_RowBg0, - ImU32{ - colors::TableDarkRed.fade(-0.4F) });// Dark red + ff_8::Colors::to_imU32( + ff_8::Colors::TableDarkRed.fade( + -0.4F)));// Dark red } else { ImGui::TableSetBgColor( ImGuiTableBgTarget_RowBg0, - ImU32{ colors::TableLightDarkRed.fade( - -0.4F) });// Slightly lighter dark red + ff_8::Colors::to_imU32( + ff_8::Colors::TableLightDarkRed.fade( + -0.4F)));// Slightly lighter dark red } bg_color = !bg_color; } ImGui::TableNextColumn(); - const auto pop_id = PushPopID(); + const auto pop_id = imgui_utils::ImGuiPushId(); std::string key_brackets = fmt::format("{{{}}}", key); if (ImGui::Selectable(key_brackets.data())) { @@ -1023,19 +1030,21 @@ bool fme::custom_paths_window::child_test_output() const { ImGui::TableSetBgColor( ImGuiTableBgTarget_RowBg0, - ImU32{ colors::TableDarkGreen.fade(-0.4F) });// Dark red + ff_8::Colors::to_imU32( + ff_8::Colors::TableDarkGreen.fade(-0.4F)));// Dark red } else { ImGui::TableSetBgColor( ImGuiTableBgTarget_RowBg0, - ImU32{ colors::TableLightDarkGreen.fade( - -0.4F) });// Slightly lighter dark red + ff_8::Colors::to_imU32( + ff_8::Colors::TableLightDarkGreen.fade( + -0.4F)));// Slightly lighter dark red } bg_color = !bg_color; } ImGui::TableNextColumn(); - const auto pop_id = PushPopID(); + const auto pop_id = imgui_utils::ImGuiPushId(); (void)ImGui::Selectable(test_str.data()); if (ImGui::BeginPopupContextItem())// <-- use last item id as popup id { diff --git a/src/opengl/main/gui/custom_paths_window.hpp b/src/opengl/main/gui/custom_paths_window.hpp index 38363085..f6e1f7d2 100644 --- a/src/opengl/main/gui/custom_paths_window.hpp +++ b/src/opengl/main/gui/custom_paths_window.hpp @@ -5,7 +5,6 @@ #include "generic_combo.hpp" #include "gui_labels.hpp" #include "key_value_data.hpp" -#include "push_pop_id.hpp" #include "Selections.hpp" #include "tool_tip.hpp" #include @@ -14,8 +13,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -329,5 +330,5 @@ struct custom_paths_window void render() const; }; }// namespace fme - +// static_assert(glengine::Renderable); #endif /* A68AC487_FAA2_4B0F_9C15_BB16CD240B56 */ diff --git a/src/opengl/main/gui/draw_window.cpp b/src/opengl/main/gui/draw_window.cpp index 92c9e5d4..413a88ba 100644 --- a/src/opengl/main/gui/draw_window.cpp +++ b/src/opengl/main/gui/draw_window.cpp @@ -1,11 +1,13 @@ #include "draw_window.hpp" +#include "gui/ColorConversions.hpp" #include "gui_labels.hpp" -#include "push_pop_id.hpp" #include "tool_tip.hpp" +#include #include #include // for glm::translate, glm::ortho, etc. #include // for glm::value_ptr #include +#include #include static ImVec2 operator+( const ImVec2 &a, @@ -34,7 +36,7 @@ void fme::draw_window::update(std::weak_ptr in_map_sprite) { m_map_sprite = std::move(in_map_sprite); } -void fme::draw_window::render() const +void fme::draw_window::on_im_gui_update() const { const auto selections = m_selections.lock(); @@ -74,8 +76,8 @@ void fme::draw_window::render() const const ImVec2 &window_pos, const ImVec2 &window_size, float tile_size, - color color1, - color color2) + ff_8::Color color1, + ff_8::Color color2) { if ( window_size.x < 1.f || window_size.y < 1.f @@ -119,15 +121,15 @@ void fme::draw_window::render() const // "resolution", glm::vec2{ m_checkerboard_framebuffer.width(), // m_checkerboard_framebuffer.height() }); m_checkerboard_batchrenderer.shader().set_uniform( - "color1", glm::vec4{ color1 }); + "color1", ff_8::Colors::to_vec4(color1)); m_checkerboard_batchrenderer.shader().set_uniform( - "color2", glm::vec4{ color2 }); + "color2", ff_8::Colors::to_vec4(color2)); m_checkerboard_batchrenderer.shader().set_uniform( "u_MVP", m_fixed_render_camera.view_projection_matrix()); m_checkerboard_batchrenderer.clear(); m_checkerboard_batchrenderer.draw_quad( glm::vec3{}, - fme::colors::White, + ff_8::Colors::to_vec4(ff_8::Colors::White), glm::vec2{ m_checkerboard_framebuffer.width(), m_checkerboard_framebuffer.height() }); m_checkerboard_batchrenderer.draw(); @@ -179,7 +181,7 @@ void fme::draw_window::render() const const auto pop_style0 = glengine::ScopeGuard([]() { ImGui::PopStyleVar(); }); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.F, 0.F)); - const auto pop_id0 = PushPopID(); + const auto pop_id0 = imgui_utils::ImGuiPushId(); const auto pop_end = glengine::ScopeGuard(&ImGui::End); // const auto pop_style1 = glengine::ScopeGuard([]() { // ImGui::PopStyleColor(); }); @@ -210,7 +212,7 @@ void fme::draw_window::render() const selections->get().fade(-0.2F), selections->get().fade(0.2F)); - const auto pop_id1 = PushPopID(); + const auto pop_id1 = imgui_utils::ImGuiPushId(); ImGui::GetWindowDrawList()->AddImage( glengine::ConvertGliDtoImTextureId( @@ -228,7 +230,7 @@ void fme::draw_window::render() const const auto pop_style0 = glengine::ScopeGuard([]() { ImGui::PopStyleVar(); }); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.F, 0.F)); - const auto pop_id0 = PushPopID(); + const auto pop_id0 = imgui_utils::ImGuiPushId(); const auto pop_end = glengine::ScopeGuard(&ImGui::End); // const auto pop_style1 = glengine::ScopeGuard([]() { // ImGui::PopStyleColor(); }); @@ -290,7 +292,7 @@ void fme::draw_window::render() const color1, color2); - const auto pop_id1 = PushPopID(); + const auto pop_id1 = imgui_utils::ImGuiPushId(); ImGui::GetWindowDrawList()->AddImage( glengine::ConvertGliDtoImTextureId( framebuffer.color_attachment_id( @@ -327,7 +329,7 @@ const fme::MousePositions &fme::draw_window::mouse_positions() const { return m_mouse_positions; } -void fme::draw_window::update_mouse_positions() +void fme::draw_window::on_update(float) const { m_mouse_positions.update(); } @@ -335,12 +337,12 @@ const std::vector &fme::draw_window::clicked_tile_indices() const { return m_clicked_tile_indices; } -void fme::draw_window::clear_clicked_tile_indices() const +void fme::draw_window::clear_clicked_tile_indices() { m_clicked_tile_indices.clear(); } -void fme::draw_window::remove_clicked_index(std::size_t in_index) const +void fme::draw_window::remove_clicked_index(std::size_t in_index) { const auto remove_result = std::ranges::remove_if( m_clicked_tile_indices, @@ -590,7 +592,7 @@ void fme::draw_window::draw_map_grid_for_conflict_tiles( = 16.0f * scale * static_cast(framebuffer.scale()); const auto [c, thickness] - = [&]() -> std::pair + = [&]() -> std::pair { const auto default_thickness = 3.F; const auto hover_thickeness = 4.5F; @@ -611,37 +613,44 @@ void fme::draw_window::draw_map_grid_for_conflict_tiles( { if (similar_over_1) { - return { colors::ButtonGreen.opaque() + return { ff_8::Colors::ButtonGreen + .opaque() .fade(-.2F), default_thickness }; } if (animation_over_1) { - return { colors::ButtonPink.opaque() + return { ff_8::Colors::ButtonPink + .opaque() .fade(-.2F), default_thickness }; } - return { colors::Button.opaque().fade( - -.2F), + return { ff_8::Colors::Button.opaque() + .fade(-.2F), default_thickness }; } if (m_mouse_positions.left) { if (similar_over_1) { - return { colors::ButtonGreenActive - .opaque() - .fade(-.2F), - default_thickness }; + return { + ff_8::Colors::ButtonGreenActive + .opaque() + .fade(-.2F), + default_thickness + }; } if (animation_over_1) { - return { colors::ButtonPinkActive - .opaque() - .fade(-.2F), - default_thickness }; + return { + ff_8::Colors::ButtonPinkActive + .opaque() + .fade(-.2F), + default_thickness + }; } - return { colors::ButtonActive.opaque() + return { ff_8::Colors::ButtonActive + .opaque() .fade(-.2F), default_thickness }; } @@ -671,16 +680,20 @@ void fme::draw_window::draw_map_grid_for_conflict_tiles( } if (similar_over_1) { - return { colors::ButtonGreenHovered.opaque(), - hover_thickeness }; + return { + ff_8::Colors::ButtonGreenHovered.opaque(), + hover_thickeness + }; } if (animation_over_1) { - return { colors::ButtonPinkHovered.opaque(), - hover_thickeness }; + return { + ff_8::Colors::ButtonPinkHovered.opaque(), + hover_thickeness + }; } - return { colors::ButtonHovered.opaque(), + return { ff_8::Colors::ButtonHovered.opaque(), hover_thickeness }; }(); @@ -1103,3 +1116,24 @@ void fme::draw_window::UseImGuizmo( t_map_sprite->end_multi_frame_working(std::move(history_entry)); } } + + +void fme::draw_window::on_im_gui_window_menu() const +{ + const auto selections = m_selections.lock(); + if (!selections) + { + spdlog::error( + "m_selections is no longer valid. File: {}, Line: {}", + __FILE__, + __LINE__); + return; + } + if (ImGui::MenuItem( + gui_labels::display_draw.data(), + "Control + D", + &selections->get())) + { + selections->update(); + } +} \ No newline at end of file diff --git a/src/opengl/main/gui/draw_window.hpp b/src/opengl/main/gui/draw_window.hpp index bd951d1a..e450747f 100644 --- a/src/opengl/main/gui/draw_window.hpp +++ b/src/opengl/main/gui/draw_window.hpp @@ -12,13 +12,15 @@ namespace fme { struct [[nodiscard]] draw_window { + draw_window() = default; + draw_window( - std::weak_ptr in_selections, - std::weak_ptr in_mim_sprite, - std::weak_ptr in_map_sprite) - : m_selections(std::move(in_selections)) - , m_mim_sprite(std::move(in_mim_sprite)) - , m_map_sprite(std::move(in_map_sprite)) + const std::shared_ptr &in_selections, + const std::shared_ptr &in_mim_sprite, + const std::shared_ptr &in_map_sprite) + : m_selections(in_selections) + , m_mim_sprite(in_mim_sprite) + , m_map_sprite(in_map_sprite) , m_checkerboard_batchrenderer{ 4, []() -> std::filesystem::path @@ -65,14 +67,16 @@ struct [[nodiscard]] draw_window void update(std::weak_ptr in_selections); void update(std::weak_ptr in_mim_sprite); void update(std::weak_ptr in_map_sprite); - void render() const; - void hovered_index(std::ptrdiff_t index); + + const std::vector &clicked_tile_indices() const; const std::vector &hovered_tiles_indices() const; const MousePositions &mouse_positions() const; - void update_mouse_positions(); - const std::vector &clicked_tile_indices() const; - void clear_clicked_tile_indices() const; - void remove_clicked_index(std::size_t) const; + void on_im_gui_update() const; + void on_update(float) const; + void on_im_gui_window_menu() const; + void hovered_index(std::ptrdiff_t index); + void clear_clicked_tile_indices(); + void remove_clicked_index(std::size_t); private: std::weak_ptr m_selections = {}; @@ -84,7 +88,7 @@ struct [[nodiscard]] draw_window mutable glengine::OrthographicCamera m_fixed_render_camera = {}; mutable std::vector m_clicked_tile_indices = {}; mutable std::vector m_hovered_tiles_indices = {}; - std::ptrdiff_t m_hovered_index = { -1 }; + mutable std::ptrdiff_t m_hovered_index = { -1 }; mutable glm::ivec2 m_location_backup = {}; mutable bool m_translation_in_progress = { false }; void update_hover_and_mouse_button_status_for_map( @@ -114,5 +118,8 @@ struct [[nodiscard]] draw_window const ImVec2 &screen_pos) const; }; }// namespace fme +static_assert( + glengine::Renderable, + "draw_window must satisfy Renderable concept"); #endif /* A047A03B_B70D_4490_89A6_07E5D157223D */ diff --git a/src/opengl/main/gui/field_file_window.hpp b/src/opengl/main/gui/field_file_window.hpp index e085407e..4be806fe 100644 --- a/src/opengl/main/gui/field_file_window.hpp +++ b/src/opengl/main/gui/field_file_window.hpp @@ -2,9 +2,9 @@ #define FFE291E8_6AE6_403A_A4F4_7173F0D98EE5 #include "format_imgui_text.hpp" #include "gui_labels.hpp" -#include "push_pop_id.hpp" #include "Selections.hpp" #include +#include #include namespace fme { @@ -89,7 +89,7 @@ struct field_file_window } for (const std::string_view path : paths) { - const auto pop_id = PushPopID(); + const auto pop_id = imgui_utils::ImGuiPushId(); (void)ImGui::Selectable(path.data()); if (ImGui::BeginPopupContextItem())// <-- use last item id as // popup id diff --git a/src/opengl/main/gui/filter_window.cpp b/src/opengl/main/gui/filter_window.cpp index 4972dd84..5fb9b840 100644 --- a/src/opengl/main/gui/filter_window.cpp +++ b/src/opengl/main/gui/filter_window.cpp @@ -1,10 +1,11 @@ #include "filter_window.hpp" #include "as_string.hpp" #include "generic_combo.hpp" -#include "gui/ImGuiDisabled.hpp" +#include "gui/ColorConversions.hpp" #include "gui_labels.hpp" -#include "push_pop_id.hpp" #include +#include +#include #include fme::filter_window::filter_window( @@ -107,7 +108,7 @@ bool fme::filter_window::shortcut(const ImGuiKeyChord key_chord) } return false; } -void fme::filter_window::render() const +void fme::filter_window::on_im_gui_update() const { m_changed = false; const auto lock_selections = m_selections.lock(); @@ -187,7 +188,7 @@ void fme::filter_window::render() const { touched_editor = true; } - ff_8::filter multi_pupu + ff_8::Filter multi_pupu = { ff_8::FilterSettings::All_Disabled }; multi_pupu.reload(*file_table); const auto optional_field_coo = [&]() @@ -396,7 +397,7 @@ toml::table *fme::filter_window::get_root_table( const key_value_data config_path_values = { .ext = ".toml" }; const std::filesystem::path config_path = config_path_values.replace_tags( lock_selections->get(), lock_selections); - auto config = Configuration(config_path); + auto config = ff_8::Configuration(config_path); return &(config.operator toml::table &()); } @@ -422,7 +423,7 @@ void fme::filter_window::root_table_to_imgui_tree( const auto label = std::string{ key }; if (val.is_table()) { - const auto pop_id = PushPopID(); + const auto pop_id = imgui_utils::ImGuiPushId(); // if skip_search we already found a match. if (!skip_search && !contains_key_recursive(val.as_table())) { @@ -845,7 +846,7 @@ void fme::filter_window::save_config( const key_value_data config_path_values = { .ext = ".toml" }; const std::filesystem::path config_path = config_path_values.replace_tags( lock_selections->get(), lock_selections); - auto config = Configuration(config_path); + auto config = ff_8::Configuration(config_path); config.save(); } @@ -1332,7 +1333,7 @@ void fme::filter_window::draw_thumbnail_label( ImGui::SetCursorScreenPos(ImVec2( text_start_pos.x + text_area_width + ImGui::GetStyle().FramePadding.x, text_start_pos.y)); - const auto pop_id = PushPopID(); + const auto pop_id = imgui_utils::ImGuiPushId(); if (ImGui::Button(ICON_FA_TRASH, button_size)) { m_remove_queue.push_back(file_name); @@ -1574,9 +1575,9 @@ void fme::filter_window::draw_filename_controls( ImGui::EndDisabled(); ImGui::SameLine(); { - const auto pop_id = PushPopID(); + const auto pop_id = imgui_utils::ImGuiPushId(); const bool has_prev = m_previous_file_name.has_value(); - const auto disabled = ImGuiDisabled(!has_prev); + const auto disabled = imgui_utils::ImGuiDisabled(!has_prev); const bool activate_prev = ImGui::ArrowButton("##l", ImGuiDir_Left) @@ -1592,9 +1593,9 @@ void fme::filter_window::draw_filename_controls( } ImGui::SameLine(); { - const auto pop_id = PushPopID(); + const auto pop_id = imgui_utils::ImGuiPushId(); const bool has_next = m_next_file_name.has_value(); - const auto disabled = ImGuiDisabled(!has_next); + const auto disabled = imgui_utils::ImGuiDisabled(!has_next); const bool activate_next = ImGui::ArrowButton("##l", ImGuiDir_Right) @@ -2079,8 +2080,8 @@ void fme::filter_window::combo_filtered_draw_bit( { using namespace std::string_view_literals; static constexpr auto values - = std::array{ ff_8::draw_bitT::all, ff_8::draw_bitT::enabled, - ff_8::draw_bitT::disabled }; + = std::array{ ff_8::DrawBitT::all, ff_8::DrawBitT::enabled, + ff_8::DrawBitT::disabled }; static const auto strings = values | std::views::transform(AsString{}) | std::ranges::to(); static constexpr auto tooltips @@ -2202,7 +2203,7 @@ void fme::filter_window::menu_filtered_palettes( [](const auto &pair) { return std::get<0>(pair); }); value_string_pairs.erase(unique_range.begin(), unique_range.end()); - const auto unique_palettes = ff_8::unique_values_and_strings( + const auto unique_palettes = ff_8::UniqueValues( value_string_pairs | std::views::transform([&](const auto &pair) { return std::get<0>(pair); }) @@ -2346,16 +2347,15 @@ void fme::filter_window::menu_filtered_animation_states( [](const auto &pair) { return std::get<0>(pair); }); value_string_pairs.erase(unique_range.begin(), unique_range.end()); - const auto unique_animation_state - = ff_8::unique_values_and_strings( - value_string_pairs - | std::views::transform([&](const auto &pair) - { return std::get<0>(pair); }) - | std::ranges::to(), - value_string_pairs - | std::views::transform([&](const auto &pair) - { return std::get<1>(pair); }) - | std::ranges::to()); + const auto unique_animation_state = ff_8::UniqueValues( + value_string_pairs + | std::views::transform([&](const auto &pair) + { return std::get<0>(pair); }) + | std::ranges::to(), + value_string_pairs + | std::views::transform([&](const auto &pair) + { return std::get<1>(pair); }) + | std::ranges::to()); GenericMenuWithMultiFilter( gui_labels::animation_state, @@ -2386,8 +2386,8 @@ struct map_draw_bit { private: static constexpr auto m_values - = std::array{ ff_8::draw_bitT::all, ff_8::draw_bitT::enabled, - ff_8::draw_bitT::disabled }; + = std::array{ ff_8::DrawBitT::all, ff_8::DrawBitT::enabled, + ff_8::DrawBitT::disabled }; static constexpr auto m_tooltips = std::array{ fme::gui_labels::draw_bit_all_tooltip, fme::gui_labels::draw_bit_enabled_tooltip, @@ -2447,7 +2447,7 @@ void fme::filter_window::draw_thumbnail( } else { - const auto pop_id = PushPopID(); + const auto pop_id = imgui_utils::ImGuiPushId(); ImVec2 padded_thumb_size = { m_thumb_size_width + ImGui::GetStyle().FramePadding.x * 2.0f, m_thumb_size_width * m_aspect_ratio @@ -2515,11 +2515,15 @@ void fme::filter_window::render_thumbnail_button( } }; if (selected) { - ImGui::PushStyleColor(ImGuiCol_Button, colors::ButtonGreen); ImGui::PushStyleColor( - ImGuiCol_ButtonHovered, colors::ButtonGreenHovered); + ImGuiCol_Button, + ff_8::Colors::to_imvec4(ff_8::Colors::ButtonGreen)); + ImGui::PushStyleColor( + ImGuiCol_ButtonHovered, + ff_8::Colors::to_imvec4(ff_8::Colors::ButtonGreenHovered)); ImGui::PushStyleColor( - ImGuiCol_ButtonActive, colors::ButtonGreenActive); + ImGuiCol_ButtonActive, + ff_8::Colors::to_imvec4(ff_8::Colors::ButtonGreenActive)); } if (ImGui::ImageButton(file_name.c_str(), tex_id, thumb_size)) @@ -2533,7 +2537,7 @@ void fme::filter_window::render_thumbnail_popup( const std::shared_ptr &lock_map_sprite, const std::string &file_name) const { - const auto pop_id = PushPopID(); + const auto pop_id = imgui_utils::ImGuiPushId(); if (!ImGui::BeginPopupContextItem( file_name.c_str()))// right-click menu for this button { @@ -2755,7 +2759,7 @@ void fme::filter_window::process_combine( { if (value.is_table()) { - ff_8::filter temp_filter + ff_8::Filter temp_filter = { ff_8::FilterSettings::All_Disabled }; toml::table &file_table = *value.as_table(); temp_filter.reload(file_table); @@ -2812,7 +2816,7 @@ void fme::filter_window::process_combine( continue; } - ff_8::filter temp_filter{ + ff_8::Filter temp_filter{ ff_8::FilterSettings::All_Disabled }; toml::table &file_table = *value.as_table(); diff --git a/src/opengl/main/gui/filter_window.hpp b/src/opengl/main/gui/filter_window.hpp index 7ed5713b..8ed8cba9 100644 --- a/src/opengl/main/gui/filter_window.hpp +++ b/src/opengl/main/gui/filter_window.hpp @@ -3,6 +3,7 @@ #include "map_sprite.hpp" #include "Selections.hpp" #include +#include #include namespace fme { @@ -30,7 +31,7 @@ struct filter_window std::weak_ptr); void collapsing_header_filters() const; [[nodiscard]] bool shortcut(const ImGuiKeyChord); - void render() const; + void on_im_gui_update() const; void menu() const; void update(std::weak_ptr); void update(std::weak_ptr); @@ -192,9 +193,9 @@ struct filter_window mutable float m_aspect_ratio = { 1.f }; float m_tool_button_size_width = { 152.f }; mutable float m_thumb_size_width = { 96.f }; - mutable ff_8::filter m_multi_select_filter + mutable ff_8::Filter m_multi_select_filter = { ff_8::FilterSettings::All_Disabled }; - mutable ff_8::filter + mutable ff_8::Filter m_excluded_animation_id_from_state = { ff_8::FilterSettings::All_Disabled }; mutable std::map m_select_for_fix_names = {}; diff --git a/src/opengl/main/gui/gui.cpp b/src/opengl/main/gui/gui.cpp index 8f119d90..84036d23 100644 --- a/src/opengl/main/gui/gui.cpp +++ b/src/opengl/main/gui/gui.cpp @@ -1,23 +1,26 @@ // // Created by pcvii on 9/7/2021. // +#ifndef DEFAULT_IMGUI_INI_PATH +#define DEFAULT_IMGUI_INI_PATH "imgui.ini"// fallback, just in case +#endif #include "gui.hpp" #include "collapsing_tile_info.hpp" -#include "colors.hpp" #include "EmptyStringIterator.hpp" +#include "gui/ColorConversions.hpp" +#include "gui/LoggingWindow.hpp" #include "gui_labels.hpp" -#include "imgui_color.hpp" #include "main_menu_paths.hpp" #include "open_file_explorer.hpp" #include "path_search.hpp" -#include "push_pop_id.hpp" -#include "safedir.hpp" #include "tool_tip.hpp" -#include "utilities.hpp" #include #include #include +#include +#include #include +#include #include #include #include @@ -241,18 +244,17 @@ void gui::start(GLFWwindow *const window) (void)icons_font(); do { - m_changed = false; - get_imgui_id() = {};// reset id counter + m_changed = false; + imgui_utils::ImGuiPushId.reset();// reset id counter m_elapsed_time = m_delta_clock; - consume_one_future(); - glfwPollEvents();// Input - - m_draw_window.update_mouse_positions(); + consume_one_future(); + glfwPollEvents();// Input handling ImGui_ImplGlfw_NewFrame(); ImGui_ImplOpenGL3_NewFrame(); ImGui::NewFrame(); ImGuizmo::BeginFrame(); + m_layers.on_update(m_elapsed_time); if (m_selections->get()) { @@ -275,7 +277,6 @@ void gui::start(GLFWwindow *const window) { m_batch_window.draw_window(); } - m_image_compare_window.render(); m_custom_paths_window.render(); m_field_file_window.render(); m_keyboard_shortcuts_window.render(); @@ -286,10 +287,8 @@ void gui::start(GLFWwindow *const window) } control_panel_window(); m_import.render(); - m_history_window.render(); m_textures_window.render(); - m_filter_window.render(); - m_draw_window.render(); + m_layers.on_im_gui_update(); // m_mouse_positions.cover.setColor(clear_color); // window.draw(m_mouse_positions.cover); ImGui::Render(); @@ -300,6 +299,7 @@ void gui::start(GLFWwindow *const window) // Clear and draw main viewport glengine::Renderer::Clear(); + m_layers.on_render(); ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); ImGuiIO &io = ImGui::GetIO(); @@ -359,7 +359,7 @@ void gui::render_dockspace() ImGui::SetNextWindowViewport(viewport->ID); ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0F); ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0F); - window_flags = bitwise_or( + window_flags = ff_8::bitwise_or( window_flags, ImGuiWindowFlags_NoTitleBar, ImGuiWindowFlags_NoCollapse, @@ -370,20 +370,21 @@ void gui::render_dockspace() } else { - dockspace_flags = bitwise_and( + dockspace_flags = ff_8::bitwise_and( dockspace_flags, - bitwise_not(ImGuiDockNodeFlags_PassthruCentralNode)); + ff_8::bitwise_not(ImGuiDockNodeFlags_PassthruCentralNode)); } // When using ImGuiDockNodeFlags_PassthruCentralNode, DockSpace() will // render our background and handle the pass-thru hole, so we ask Begin() // to not render a background. if ( - bitwise_and(dockspace_flags, ImGuiDockNodeFlags_PassthruCentralNode) + ff_8::bitwise_and( + dockspace_flags, ImGuiDockNodeFlags_PassthruCentralNode) != ImGuiDockNodeFlags{}) { window_flags - = bitwise_or(window_flags, ImGuiWindowFlags_NoBackground); + = ff_8::bitwise_or(window_flags, ImGuiWindowFlags_NoBackground); } // Important: note that we proceed even if Begin() returns false (aka @@ -416,17 +417,17 @@ void gui::render_dockspace() ImGui::PopStyleVar(2); } - dockspace_flags - = bitwise_or(dockspace_flags, ImGuiDockNodeFlags_PassthruCentralNode); - dockspace_flags - = bitwise_and(dockspace_flags, bitwise_not(ImGuiDockNodeFlags_NoResize)); + dockspace_flags = ff_8::bitwise_or( + dockspace_flags, ImGuiDockNodeFlags_PassthruCentralNode); + dockspace_flags = ff_8::bitwise_and( + dockspace_flags, ff_8::bitwise_not(ImGuiDockNodeFlags_NoResize)); // Submit the DockSpace ImGuiIO &imgui_io = ImGui::GetIO(); imgui_io.ConfigWindowsMoveFromTitleBarOnly = true; if ( - bitwise_and(imgui_io.ConfigFlags, ImGuiConfigFlags_DockingEnable) + ff_8::bitwise_and(imgui_io.ConfigFlags, ImGuiConfigFlags_DockingEnable) != ImGuiConfigFlags{}) { const ImGuiID dockspace_id = ImGui::GetID("MyDockSpace"); @@ -499,8 +500,12 @@ void gui::control_panel_window() } void gui::tile_conflicts_panel() { - m_draw_window.hovered_index( - -1);// reset to -1 and below we set to number if we're hovering. + if (auto *draw_window = m_layers.get(); draw_window) + { + draw_window->hovered_index(-1); + // reset to -1 and below we set to number if we're hovering. + } + if (!map_test()) { return; @@ -523,11 +528,12 @@ void gui::tile_conflicts_panel() const auto &animation_counts = m_map_sprite->working_animation_counts(); - const auto pop_table_id = PushPopID(); + const auto pop_table_id = imgui_utils::ImGuiPushId(); // Default hover options for ImGuiCol_ButtonHovered const auto options_hover = tile_button_options{ .size = { buttonWidth, buttonWidth }, - .button_color = colors::ButtonHovered }; + .button_color + = ff_8::Colors::ButtonHovered }; // Default regular options for ImGuiCol_Button const auto options_regular @@ -537,30 +543,32 @@ void gui::tile_conflicts_panel() // tint) const auto options_similar = tile_button_options{ .size = { buttonWidth, buttonWidth }, - .button_color = colors::ButtonGreen, - .button_hover_color = colors::ButtonGreenHovered, - .button_active_color = colors::ButtonGreenActive + .button_color = ff_8::Colors::ButtonGreen, + .button_hover_color = ff_8::Colors::ButtonGreenHovered, + .button_active_color = ff_8::Colors::ButtonGreenActive }; // New hover options for similar tiles (green hover) const auto options_similar_hover = tile_button_options{ - .size = { buttonWidth, buttonWidth }, - .button_color = colors::ButtonGreenHovered// Green hover tint + .size = { buttonWidth, buttonWidth }, + .button_color + = ff_8::Colors::ButtonGreenHovered// Green hover tint }; // New options for when the animation count is greater than 1 (pink // tint) const auto options_animation = tile_button_options{ .size = { buttonWidth, buttonWidth }, - .button_color = colors::ButtonPink, - .button_hover_color = colors::ButtonPinkHovered, - .button_active_color = colors::ButtonPinkActive + .button_color = ff_8::Colors::ButtonPink, + .button_hover_color = ff_8::Colors::ButtonPinkHovered, + .button_active_color = ff_8::Colors::ButtonPinkActive }; // New hover options for animation tiles (pink hover) const auto options_animation_hover = tile_button_options{ - .size = { buttonWidth, buttonWidth }, - .button_color = colors::ButtonPinkHovered// pink hover tint + .size = { buttonWidth, buttonWidth }, + .button_color + = ff_8::Colors::ButtonPinkHovered// pink hover tint }; format_imgui_text("{}", "Legend: "); @@ -598,7 +606,7 @@ void gui::tile_conflicts_panel() first_tile.source_x(), first_tile.source_x() + first_tile.texture_id() - * ff_8::source_tile_conflicts::GRID_SIZE, + * ff_8::SourceTileConflicts::GRID_SIZE, first_tile.source_y(), first_tile.texture_id()); } @@ -672,26 +680,31 @@ void gui::tile_conflicts_panel() { return options_hover; } - if ( - std::ranges::empty( - m_draw_window.hovered_tiles_indices()) - || std::ranges::find( - m_draw_window.hovered_tiles_indices(), - static_cast(index)) - == std::ranges::end( - m_draw_window.hovered_tiles_indices()) - || !m_draw_window.mouse_positions() - .mouse_enabled) + if (auto *draw_window + = m_layers.get(); + draw_window) { - if (similar_over_1) - { - return options_similar; - } - if (animation_over_1) + const auto &indices + = draw_window->hovered_tiles_indices(); + if ( + std::ranges::empty(indices) + || std::ranges::find( + indices, + static_cast(index)) + == std::ranges::end(indices) + || !draw_window->mouse_positions() + .mouse_enabled) { - return options_animation; + if (similar_over_1) + { + return options_similar; + } + if (animation_over_1) + { + return options_animation; + } + return options_regular; } - return options_regular; } if (similar_over_1) { @@ -708,7 +721,12 @@ void gui::tile_conflicts_panel() m_map_sprite, original_tile, options); if (ImGui::IsItemHovered()) { - m_draw_window.hovered_index(index); + if (auto *draw_window + = m_layers.get(); + draw_window) + { + draw_window->hovered_index(index); + } } // Ensure subsequent buttons are on the same row std::string strtooltip = fmt::format( @@ -730,14 +748,13 @@ void gui::tile_conflicts_panel() void gui::selected_tiles_panel() { - - if (!map_test()) { return; } - - if (std::ranges::empty(m_draw_window.clicked_tile_indices())) + auto *draw_window = m_layers.get(); + if ( + !draw_window || std::ranges::empty(draw_window->clicked_tile_indices())) { return; } @@ -749,7 +766,7 @@ void gui::selected_tiles_panel() m_map_sprite->const_visit_working_tiles( [&](const auto &working_tiles) { - for (const auto &i : m_draw_window.clicked_tile_indices()) + for (const auto &i : draw_window->clicked_tile_indices()) { if ( i < std::ranges::size(original_tiles) @@ -772,7 +789,7 @@ void gui::selected_tiles_panel() }); if (remove_index.has_value()) { - m_draw_window.remove_clicked_index(remove_index.value()); + draw_window->remove_clicked_index(remove_index.value()); } } void gui::control_panel_window_mim() @@ -804,7 +821,12 @@ void gui::control_panel_window_map() m_changed = m_import.checkbox_render_imported_image() || m_changed; checkbox_map_disable_blending(); compact_flatten_buttons(); - m_filter_window.collapsing_header_filters(); + + if (const auto *filter_window = m_layers.get(); + filter_window) + { + filter_window->collapsing_header_filters(); + } // if (m_changed) // { // scale_window(); @@ -1067,8 +1089,13 @@ void gui::consume_one_future() void gui::text_mouse_position() const { + auto *draw_window = m_layers.get(); + if (!draw_window) + { + return; + } // Display texture coordinates if they are set - if (!m_draw_window.mouse_positions().mouse_enabled) + if (!draw_window->mouse_positions().mouse_enabled) { format_imgui_text("{}", gui_labels::mouse_not_over); return; @@ -1078,21 +1105,21 @@ void gui::text_mouse_position() const format_imgui_text( "{}: ({:4}, {:3})", gui_labels::mouse_pos, - m_draw_window.mouse_positions().pixel.x, - m_draw_window.mouse_positions().pixel.y); + draw_window->mouse_positions().pixel.x, + draw_window->mouse_positions().pixel.y); ImGui::SameLine(); const int tile_size = 16; format_imgui_text( "{}: ({:2}, {:2})", gui_labels::tile_pos, - m_draw_window.mouse_positions().pixel.x / tile_size, - m_draw_window.mouse_positions().pixel.y / tile_size); + draw_window->mouse_positions().pixel.x / tile_size, + draw_window->mouse_positions().pixel.y / tile_size); if (m_selections->get()) { format_imgui_text( "{}: {:2}", gui_labels::page, - m_draw_window.mouse_positions().texture_page); + draw_window->mouse_positions().texture_page); } } } @@ -1107,8 +1134,13 @@ void gui::hovered_tiles_panel() m_map_sprite->const_visit_tiles_both( [&](const auto &working_tiles, const auto &original_tiles) { + auto *draw_window = m_layers.get(); + if (!draw_window) + { + return; + } const auto &hovered_tiles_indices - = m_draw_window.hovered_tiles_indices(); + = draw_window->hovered_tiles_indices(); format_imgui_text( "{} {:4}", gui_labels::number_of_tiles, @@ -1117,7 +1149,7 @@ void gui::hovered_tiles_panel() { return; } - if (!m_draw_window.mouse_positions().mouse_enabled) + if (!draw_window->mouse_positions().mouse_enabled) { return; } @@ -1162,32 +1194,32 @@ void gui::hovered_tiles_panel() && std::cmp_greater( similar_counts.at(working_tile), 1)) { - return colors::ButtonGreenHovered; + return ff_8::Colors::ButtonGreenHovered; } if ( animation_counts.contains(working_tile) && std::cmp_greater( animation_counts.at(working_tile), 1)) { - return colors::ButtonPinkHovered; + return ff_8::Colors::ButtonPinkHovered; } - return colors::ButtonHovered; + return ff_8::Colors::ButtonHovered; } if ( similar_counts.contains(working_tile) && std::cmp_greater(similar_counts.at(working_tile), 1)) { - return colors::ButtonGreen; + return ff_8::Colors::ButtonGreen; } if ( animation_counts.contains(working_tile) && std::cmp_greater( animation_counts.at(working_tile), 1)) { - return colors::ButtonPink; + return ff_8::Colors::ButtonPink; } - return colors::Button; + return ff_8::Colors::Button; }(); const auto options = tile_button_options{ .size = { buttonWidth, buttonWidth }, @@ -1374,7 +1406,12 @@ void gui::update_field() } // Clear clicked tile indices used for selection logic - m_draw_window.clear_clicked_tile_indices(); + auto *draw_window = m_layers.get(); + if (!draw_window) + { + return; + } + draw_window->clear_clicked_tile_indices(); } void gui::refresh_map_swizzle() @@ -1637,19 +1674,19 @@ void gui::windows_menu() } const auto end_menu = glengine::ScopeGuard(&ImGui::EndMenu); if (ImGui::MenuItem( - gui_labels::display_control_panel_window.data(), + gui_labels::display_control_panel.data(), "Control + P", &m_selections->get())) { m_selections->update(); } if (ImGui::MenuItem( - "ImGui Demo Window", std::nullptr_t{}, &toggle_imgui_demo_window)) + "ImGui Demo Window", nullptr, &toggle_imgui_demo_window)) { } ImGui::Separator(); if (ImGui::MenuItem( - gui_labels::display_field_file_window.data(), + gui_labels::display_field_file.data(), "Control + F", &m_selections->get())) { @@ -1660,7 +1697,7 @@ void gui::windows_menu() return; } if (ImGui::MenuItem( - gui_labels::batch_operation_window.data(), + gui_labels::display_batch_operation.data(), "Control + B", &m_selections->get())) { @@ -1672,14 +1709,6 @@ void gui::windows_menu() // { // m_selections->update(); // } - ImGui::Separator(); - if (ImGui::MenuItem( - gui_labels::display_history.data(), - "Control + H", - &m_selections->get())) - { - m_selections->update(); - } if (ImGui::MenuItem( "Display Textures", @@ -1689,25 +1718,10 @@ void gui::windows_menu() m_selections->update(); } - if (ImGui::MenuItem( - "Display Image Compare", - nullptr, - &m_selections->get())) - { - m_selections->update(); - } - - ImGui::Separator(); - if (ImGui::MenuItem( - gui_labels::display_draw_window.data(), - "Control + D", - &m_selections->get())) - { - m_selections->update(); - } + m_layers.on_im_gui_window_menu(); ImGui::Separator(); if (ImGui::MenuItem( - gui_labels::display_custom_paths_window.data(), + gui_labels::display_custom_paths.data(), "Control + U", &m_selections->get())) { @@ -2058,7 +2072,7 @@ void gui::edit_menu() float sz = ImGui::GetTextLineHeight(); auto zip_view = std::ranges::views::zip( - fme::colors::ColorValues, fme::colors::ColorNames); + ff_8::Colors::ColorValues, ff_8::Colors::ColorNames); constexpr int columns = 2; format_imgui_wrapped_text( "Hold Control to set Secondary Background Color"); @@ -2239,7 +2253,13 @@ void gui::edit_menu() }; if (map_test()) { - m_filter_window.menu(); + + if (const auto *filter_window + = m_layers.get(); + filter_window) + { + filter_window->menu(); + } } if (mim_test()) { @@ -2378,10 +2398,10 @@ void gui::file_menu() refresh_path(); } ImGui::TableNextColumn(); - const auto pop_id = PushPopID(); + const auto pop_id = imgui_utils::ImGuiPushId(); const float button_size = ImGui::GetFrameHeight(); - const auto _ = PushPopID(); + const auto _ = imgui_utils::ImGuiPushId(); if (ImGui::Button( ICON_FA_FOLDER_OPEN, ImVec2{ button_size, button_size })) @@ -2541,29 +2561,32 @@ void gui::file_menu() { ImGui::TableSetBgColor( ImGuiTableBgTarget_RowBg0, - ImU32{ colors::TableDarkGray.fade(-.6F).fade_alpha( - -.4F) }); + ImU32{ + ff_8::Colors::TableDarkGray.fade(-.6F).fade_alpha( + -.4F) }); } else { ImGui::TableSetBgColor( ImGuiTableBgTarget_RowBg0, - ImU32{ - colors::TableLightDarkGray.fade(-.6F).fade_alpha( - -.4F) }); + ImU32{ ff_8::Colors::TableLightDarkGray.fade(-.6F) + .fade_alpha(-.4F) }); } ImGui::TableNextColumn(); ImGui::PushStyleColor( - ImGuiCol_HeaderHovered, colors::ButtonHovered); + ImGuiCol_HeaderHovered, + ff_8::Colors::to_imvec4(ff_8::Colors::ButtonHovered)); ImGui::PushStyleColor( - ImGuiCol_HeaderActive, colors::ButtonActive); + ImGuiCol_HeaderActive, + ff_8::Colors::to_imvec4(ff_8::Colors::ButtonActive)); const bool checked = std::cmp_equal(m_field_index, index); if (checked) { ImGui::TableSetBgColor( ImGuiTableBgTarget_CellBg, - ImU32{ colors::Button });// Make the selected field - // stand out more. + ImU32{ + ff_8::Colors::Button });// Make the selected field + // stand out more. } if (ImGui::MenuItem( str.c_str(), @@ -2684,7 +2707,7 @@ void gui::file_menu() m_custom_paths_window.refresh(); } ImGui::TableNextColumn(); - const auto _ = PushPopID(); + const auto _ = imgui_utils::ImGuiPushId(); if (ImGui::Button( ICON_FA_TRASH, ImVec2{ button_size, button_size })) @@ -2838,7 +2861,7 @@ void gui::menu_swizzle_as_one_image_paths() { m_map_sprite->filter() .update( - compact_type::map_order_ffnx); + ff_8::CompactTypeT::map_order_ffnx); m_map_sprite->toggle_filter_compact_on_load_original(true); } else @@ -3071,7 +3094,7 @@ void gui::menu_map_paths() std::ptrdiff_t gui::add_delete_button(const std::ptrdiff_t index) { - const auto pop_id = PushPopID(); + const auto pop_id = imgui_utils::ImGuiPushId(); if (ImGui::Button(ICON_FA_TRASH)) { ImGui::CloseCurrentPopup(); @@ -3096,7 +3119,7 @@ std::ptrdiff_t gui::add_delete_button( if (it != std::ranges::end(transformed_paths)) { const auto &index = std::get<0>(*it); - const auto pop_id = PushPopID(); + const auto pop_id = imgui_utils::ImGuiPushId(); if (ImGui::Button(ICON_FA_TRASH)) { ImGui::CloseCurrentPopup(); @@ -3374,7 +3397,7 @@ void gui::directory_browser_display() { m_map_sprite->filter() .get() - .update(compact_type::map_order_ffnx); + .update(ff_8::CompactTypeT::map_order_ffnx); m_map_sprite->toggle_filter_compact_on_load_original( true); } @@ -3798,7 +3821,7 @@ void gui::refresh_draw_mode() break; case draw_mode::draw_map: *m_map_sprite = m_map_sprite->update( - ff_8::map_group(m_field, get_coo()), + ff_8::MapGroup(m_field, get_coo()), m_selections->get()); // m_draw_window.update(m_map_sprite); // m_import.update(m_map_sprite); @@ -3909,9 +3932,14 @@ void gui::bind_shortcuts() ImGui::Shortcut(escapeChord, flags) || ImGui::Shortcut(ImGuiMod_Ctrl | ImGuiMod_Shift | ImGuiKey_A, flags)) { - if (!m_filter_window.shortcut(escapeChord)) + if (auto *filter_window = m_layers.get(); + !filter_window || !filter_window->shortcut(escapeChord)) { - m_draw_window.clear_clicked_tile_indices(); + if (auto *draw_window = m_layers.get(); + draw_window) + { + draw_window->clear_clicked_tile_indices(); + } } } @@ -4019,7 +4047,8 @@ void gui::bind_shortcuts() else if (const ImGuiKeyChord selectAllChord = (ImGuiMod_Ctrl | ImGuiKey_A); ImGui::Shortcut(selectAllChord, flags)) { - if (!m_filter_window.shortcut(selectAllChord)) + if (auto *filter_window = m_layers.get(); + !filter_window || !filter_window->shortcut(selectAllChord)) { // select all action for draw window? seems a bit extreme } @@ -4028,7 +4057,8 @@ void gui::bind_shortcuts() else if (const ImGuiKeyChord invertChord = (ImGuiMod_Ctrl | ImGuiKey_I); ImGui::Shortcut(invertChord, flags)) { - if (!m_filter_window.shortcut(invertChord)) + if (auto *filter_window = m_layers.get(); + !filter_window || !filter_window->shortcut(invertChord)) { // todo fix imports in new branch. // m_selections->display_import_image_window ^= true; @@ -4110,7 +4140,7 @@ float gui::scaled_menubar_gap() const // scaled_gap), m_scale_width, std::round(img_height + // // scaled_gap)))); // } -archives_group gui::get_archives_group() const +ff_8::ArchivesGroup gui::get_archives_group() const { if (!std::ranges::empty(m_selections->get())) { @@ -4121,7 +4151,7 @@ archives_group gui::get_archives_group() const } void gui::update_path() { - m_archives_group = std::make_shared( + m_archives_group = std::make_shared( m_archives_group->with_path(m_selections->get())); m_batch_window = m_archives_group; m_custom_paths_window.refresh(); @@ -4137,7 +4167,11 @@ std::shared_ptr gui::get_mim_sprite() const get_coo(), m_selections->get()); } -gui::gui(GLFWwindow *const window) +gui::gui( + GLFWwindow *const window, + std::shared_ptr sink) + : m_window(std::move(window)) + , m_memory_sink(std::move(sink)) { // 0. Set the debug callback function glDebugMessageCallback(DebugCallback, nullptr); @@ -4148,16 +4182,37 @@ gui::gui(GLFWwindow *const window) IM_ASSERT(ImGui::GetCurrentContext() != nullptr); // 2. Configure ImGui (optional but common) - ImGuiIO &imgui_io = ImGui::GetIO(); - std::error_code error_code = {}; - static const auto path = (std::filesystem::current_path(error_code) / "res" - / "field-map-editor_imgui.ini") - .string(); + ImGuiIO &imgui_io = ImGui::GetIO(); imgui_io.ConfigFlags - = bitwise_or(imgui_io.ConfigFlags, ImGuiConfigFlags_DockingEnable); - imgui_io.ConfigFlags - = bitwise_or(imgui_io.ConfigFlags, ImGuiConfigFlags_ViewportsEnable); - imgui_io.IniFilename = path.c_str(); + = ff_8::bitwise_or(imgui_io.ConfigFlags, ImGuiConfigFlags_DockingEnable); + imgui_io.ConfigFlags = ff_8::bitwise_or( + imgui_io.ConfigFlags, ImGuiConfigFlags_ViewportsEnable); + std::error_code error_code = {}; + + auto temp_path = std::filesystem::path(DEFAULT_IMGUI_INI_PATH); + static std::string path; + try + { + if (temp_path.is_relative()) + { + temp_path = (std::filesystem::current_path(error_code) / path); + } + temp_path.make_preferred(); + path = temp_path.string(); + imgui_io.IniFilename = path.c_str(); + spdlog::info("ImGui ini path: {}", imgui_io.IniFilename); + ImGui::LoadIniSettingsFromDisk(imgui_io.IniFilename); + } + catch (const std::filesystem::filesystem_error &e) + { + spdlog::error( + "Filesystem error while constructing config path: {}", e.what()); + } + catch (const std::exception &e) + { + spdlog::error( + "Unexpected error while constructing config path: {}", e.what()); + } if (error_code) { spdlog::warn( @@ -4169,7 +4224,6 @@ gui::gui(GLFWwindow *const window) path); error_code.clear(); } - ImGui::LoadIniSettingsFromDisk(path.c_str()); // 3. Set ImGui style (optional) ImGui::StyleColorsDark();// or Light(), Classic() @@ -4187,75 +4241,89 @@ gui::gui(GLFWwindow *const window) // ImGuiIO::Fonts // 6. MISC - m_archives_group = std::make_shared(get_archives_group()); - m_batch_window = fme::batch{ m_selections, m_archives_group }; - m_field = init_field(); + m_archives_group + = std::make_shared(get_archives_group()); + m_batch_window = fme::batch{ m_selections, m_archives_group }; + m_field = init_field(); m_field_file_window.refresh(m_field); m_mim_sprite = get_mim_sprite(); m_map_sprite = get_map_sprite(); - m_draw_window.update(m_mim_sprite); - m_draw_window.update(m_map_sprite); - m_filter_window.update(m_map_sprite); + m_layers.emplace_layers( + std::in_place_type, + m_selections, + m_mim_sprite, + m_map_sprite); + m_layers.emplace_layers( + std::in_place_type, m_selections, m_map_sprite); + m_layers.emplace_layers( + std::in_place_type, m_selections); + m_layers.emplace_layers( + std::in_place_type, m_selections, m_map_sprite); + m_layers.emplace_layers( + std::in_place_type, m_memory_sink, m_selections); m_import.update(m_selections); - m_history_window.update(m_selections); m_textures_window.update(m_selections); m_import.update(m_map_sprite); - m_history_window.update(m_map_sprite); m_textures_window.update(m_map_sprite); - m_filter_window.register_change_field_callback( - [&](const std::string &in) - { - // Get a reference to the map data (field name list) - const auto &maps = m_archives_group->mapdata(); - - const auto it = std::ranges::find(maps, in); - if (it == maps.end()) + if (auto *filter_window = m_layers.get(); + filter_window) + { + filter_window->register_change_field_callback( + [&](const std::string &in) { - return; - } - m_field_index - = static_cast(std::ranges::distance(maps.begin(), it)); + // Get a reference to the map data (field name list) + const auto &maps = m_archives_group->mapdata(); - // Update the starter_field name based on the current field index - m_selections->get() = *it; + const auto it = std::ranges::find(maps, in); + if (it == maps.end()) + { + return; + } + m_field_index + = static_cast(std::ranges::distance(maps.begin(), it)); - // Save the selected field name to the configuration - m_selections->update(); + // Update the starter_field name based on the current field + // index + m_selections->get() = *it; - // Apply the updated field selection - update_field(); - }); + // Save the selected field name to the configuration + m_selections->update(); + // Apply the updated field selection + update_field(); + }); - m_filter_window.register_change_coo_callback( - [&](const std::string &in) - { - // Get a reference to the map data (field name list) - open_viii::LangT lang - = open_viii::LangCommon::from_string_3_char(in); - if (m_selections->get() != lang) + filter_window->register_change_coo_callback( + [&](const std::string &in) { - m_selections->get() = lang; - // hmm this refreshes the field too bah. So could have double - // work done in some cases. - refresh_coo(); - } - }); + // Get a reference to the map data (field name list) + open_viii::LangT lang + = open_viii::LangCommon::from_string_3_char(in); - m_filter_window.register_is_remaster_callback( - [this]() -> bool - { return m_field && m_field->is_remaster_from_fl_paths(); }); + if (m_selections->get() != lang) + { + m_selections->get() = lang; + // hmm this refreshes the field too bah. So could have + // double work done in some cases. + refresh_coo(); + } + }); - if (m_field) - { - m_future_of_future_paths_consumer - += generate_external_texture_paths(); - m_future_of_future_paths_consumer += generate_external_map_paths(); - m_future_of_future_paths_consumer += generate_sort_paths(); - } + filter_window->register_is_remaster_callback( + [this]() -> bool + { return m_field && m_field->is_remaster_from_fl_paths(); }); + if (m_field) + { + m_future_of_future_paths_consumer + += generate_external_texture_paths(); + m_future_of_future_paths_consumer + += generate_external_map_paths(); + m_future_of_future_paths_consumer += generate_sort_paths(); + } + } m_custom_paths_window.register_callback( [&](const ConfigKey key) { @@ -4340,8 +4408,8 @@ std::shared_ptr> gui::init_field() std::shared_ptr gui::get_map_sprite() const { - // map_sprite(ff_8::map_group map_group, bool draw_swizzle, - // ff_8::filters in_filters, bool force_disable_blends, bool + // map_sprite(ff_8::MapGroup MapGroup, bool draw_swizzle, + // ff_8::Filters in_filters, bool force_disable_blends, bool // require_coo); map_sprite_settings settings = { .draw_swizzle = m_selections->get(), @@ -4349,9 +4417,9 @@ std::shared_ptr gui::get_map_sprite() const .require_coo = false, }; return std::make_shared( - ff_8::map_group{ m_field, get_coo() }, + ff_8::MapGroup{ m_field, get_coo() }, settings, - ff_8::filters{ true }, + ff_8::Filters{ true }, m_selections); } @@ -4476,7 +4544,7 @@ void gui::combo_swizzle_as_one_image_path() m_map_sprite->filter().disable(); m_map_sprite->filter().disable(); m_map_sprite->filter().update( - compact_type::map_order_ffnx); + ff_8::CompactTypeT::map_order_ffnx); m_map_sprite->toggle_filter_compact_on_load_original(true); } else @@ -4693,7 +4761,7 @@ std::future> } bool gui::combo_swizzle_path( - ff_8::filter &filter) const + ff_8::Filter &filter) const { const auto strings = m_selections->get() @@ -4711,7 +4779,7 @@ bool gui::combo_swizzle_path( bool gui::combo_swizzle_as_one_image_path( - ff_8::filter &filter) const + ff_8::Filter &filter) const { const auto strings = m_selections->get() @@ -4728,7 +4796,7 @@ bool gui::combo_swizzle_as_one_image_path( } bool gui::combo_deswizzle_path( - ff_8::filter &filter) const + ff_8::Filter &filter) const { const auto strings = m_selections->get() @@ -4745,7 +4813,7 @@ bool gui::combo_deswizzle_path( } bool gui::combo_full_filename_path( - ff_8::filter &filter) const + ff_8::Filter &filter) const { const auto strings = m_selections->get() @@ -4762,7 +4830,7 @@ bool gui::combo_full_filename_path( return m_field && gcc.render(); } -bool gui::combo_map_path(ff_8::filter &filter) const +bool gui::combo_map_path(ff_8::Filter &filter) const { const auto strings = m_selections->get() diff --git a/src/opengl/main/gui/gui.hpp b/src/opengl/main/gui/gui.hpp index f8381650..bc6d7ecd 100644 --- a/src/opengl/main/gui/gui.hpp +++ b/src/opengl/main/gui/gui.hpp @@ -7,12 +7,8 @@ #include #include // clang-format on -#include "archives_group.hpp" #include "as_string.hpp" #include "batch.hpp" -#include "colors.hpp" -#include "compact_type.hpp" -#include "Configuration.hpp" #include "create_tile_button.hpp" #include "custom_paths_window.hpp" #include "draw_window.hpp" @@ -30,11 +26,17 @@ #include "map_directory_mode.hpp" #include "mouse_positions.hpp" #include "RangeConsumer.hpp" -#include "safedir.hpp" #include "Selections.hpp" +#include "spdlog/sinks/ringbuffer_sink.h" #include "textures_window.hpp" #include +#include +#include +#include +#include +#include #include +#include #include #include #include @@ -47,11 +49,15 @@ namespace fme struct gui { public: - gui(GLFWwindow *const window); + gui( + GLFWwindow *const window, + std::shared_ptr memory_sink); void start(GLFWwindow *const window); ~gui(); private: + GLFWwindow *const m_window; + std::shared_ptr m_memory_sink; using variant_tile_t = std::variant< open_viii::graphics::background::Tile1, open_viii::graphics::background::Tile2, @@ -71,27 +77,24 @@ struct gui // std::shared_ptr m_drag_sprite_shader // = {}; static constexpr std::int8_t tile_size_px = { 16 }; - static constexpr std::uint8_t tile_size_px_unsigned = { 16U }; - int m_field_index = {}; - float m_scale_width = {}; - glengine::TimeStep m_delta_clock = {}; - float m_elapsed_time = {};///< seconds - std::shared_ptr m_archives_group = {}; - batch m_batch_window = {}; + static constexpr std::uint8_t tile_size_px_unsigned = { 16U }; + int m_field_index = {}; + float m_scale_width = {}; + glengine::TimeStep m_delta_clock = {}; + float m_elapsed_time = {};///< seconds + std::shared_ptr m_archives_group = {}; + glengine::Layer::Stack m_layers = {}; + batch m_batch_window = {}; std::shared_ptr> m_field = {}; std::array xy = {}; std::shared_ptr m_mim_sprite = {}; std::shared_ptr m_map_sprite = {}; - filter_window m_filter_window = { m_selections, m_map_sprite }; - draw_window m_draw_window = { m_selections, m_mim_sprite, m_map_sprite }; custom_paths_window m_custom_paths_window = { m_selections }; field_file_window m_field_file_window = { m_field, m_selections }; keyboard_shortcuts_window m_keyboard_shortcuts_window = { m_selections }; - ImageCompareWindow m_image_compare_window = { m_selections }; float saved_window_width = {}; float saved_window_height = {}; fme::import m_import = {}; - fme::history_window m_history_window = {}; fme::textures_window m_textures_window = {}; // sf::RenderTexture m_shader_renderTexture = {}; @@ -126,14 +129,14 @@ struct gui create_color_button blue_color_button = {}; create_color_button green_color_button - = { { .button_color = colors::ButtonGreen, - .button_hover_color = colors::ButtonGreenHovered, - .button_active_color = colors::ButtonGreenActive } }; + = { { .button_color = ff_8::Colors::ButtonGreen, + .button_hover_color = ff_8::Colors::ButtonGreenHovered, + .button_active_color = ff_8::Colors::ButtonGreenActive } }; create_color_button pink_color_button - = { { .button_color = colors::ButtonPink, - .button_hover_color = colors::ButtonPinkHovered, - .button_active_color = colors::ButtonPinkActive } }; + = { { .button_color = ff_8::Colors::ButtonPink, + .button_hover_color = ff_8::Colors::ButtonPinkHovered, + .button_active_color = ff_8::Colors::ButtonPinkActive } }; static inline constinit bool toggle_imgui_demo_window = { false }; @@ -148,7 +151,7 @@ struct gui m_future_of_future_consumer = {}; // imgui doesn't support std::string or std::string_view or // std::filesystem::path, only const char * - archives_group get_archives_group() const; + ff_8::ArchivesGroup get_archives_group() const; void update_path(); void consume_one_future(); std::shared_ptr get_mim_sprite() const; @@ -192,18 +195,18 @@ struct gui void text_mouse_position() const; void combo_swizzle_path(); bool - combo_swizzle_path(ff_8::filter &filter) const; + combo_swizzle_path(ff_8::Filter &filter) const; void combo_swizzle_as_one_image_path(); bool combo_swizzle_as_one_image_path( - ff_8::filter &filter) const; + ff_8::Filter &filter) const; void combo_deswizzle_path(); bool combo_deswizzle_path( - ff_8::filter &filter) const; + ff_8::Filter &filter) const; void combo_full_filename_path(); bool combo_full_filename_path( - ff_8::filter &filter) const; + ff_8::Filter &filter) const; void combo_map_path(); - bool combo_map_path(ff_8::filter &filter) const; + bool combo_map_path(ff_8::Filter &filter) const; const open_viii::LangT &get_coo() const; file_dialog_mode m_file_dialog_mode = {}; map_directory_mode m_modified_directory_map = {}; @@ -211,7 +214,7 @@ struct gui std::filesystem::path m_loaded_deswizzle_texture_path{}; // void popup_batch_reswizzle(); void popup_batch_deswizzle(); // static void popup_batch_common_filter_start( - // ff_8::filter &filter, + // ff_8::Filter &filter, // std::string_view prefix, // std::string_view base_name); // void popup_batch_embed(); diff --git a/src/opengl/main/gui/gui_labels.hpp b/src/opengl/main/gui/gui_labels.hpp index 68fa0f8b..ccf0ebf6 100644 --- a/src/opengl/main/gui/gui_labels.hpp +++ b/src/opengl/main/gui/gui_labels.hpp @@ -47,8 +47,18 @@ struct gui_labels = { "Full Filename Path (.toml)" }; static constexpr std::string_view map_path = { ".map Path" }; static constexpr std::string_view processing = { "Processing" }; - static constexpr std::string_view display_history = { "History" }; static constexpr std::string_view history = { "History" }; + static constexpr std::string_view display_history = { "History" }; + static constexpr std::string_view display_image_compare + = { "Image Compare" }; + static constexpr std::string_view display_draw = { "Draw" }; + static constexpr std::string_view display_control_panel + = { "Control Panel" }; + static constexpr std::string_view display_custom_paths + = { "Custom Paths" }; + static constexpr std::string_view display_field_file = { "Field File" }; + static constexpr std::string_view display_batch_operation + = { "Batch Operation" }; static constexpr std::string_view animation_state = { "Animation State" }; static constexpr std::string_view z = { "Z" }; static constexpr std::string_view blend_other = { "Blend Other" }; @@ -159,9 +169,7 @@ struct gui_labels static constexpr std::string_view compact_flatten = { "Compact and Flatten" }; static constexpr std::string_view batch_operation = { "Batch Operation" }; - static constexpr std::string_view batch_operation_window - = { "Batch Swizzle/Deswizzle" }; - static constexpr std::string_view explore = { "Explore" }; + static constexpr std::string_view explore = { "Explore" }; static constexpr std::string_view forced_on_while_swizzled = { "Forced on while Swizzled..." }; @@ -185,10 +193,7 @@ struct gui_labels static constexpr std::string_view output_path = { "Output Path" }; static constexpr std::string_view select_none = { "Select None" }; static constexpr std::string_view select_all = { "Select All" }; - static constexpr std::string_view draw_window_title = { "Draw" }; - static constexpr std::string_view display_draw_window = { "Draw" }; - static constexpr std::string_view display_control_panel_window - = { "Control Panel" }; + static constexpr std::string_view draw_window_title = { "Draw" }; static constexpr std::string_view render_imported_image = { "Render Imported Image" }; static constexpr std::string_view mouse_not_over @@ -223,10 +228,6 @@ struct gui_labels = { "Generate Colorful Masks" }; static constexpr std::string_view BatchGenerateWhiteOnBlackMask = { "Generate White On Black Masks" }; - static constexpr std::string_view display_custom_paths_window - = { "Display Custom Paths Window" }; - static constexpr std::string_view display_field_file_window - = { "Display Field File Window" }; static constexpr std::string_view field_file_window = { "Field File Window" }; diff --git a/src/opengl/main/gui/history_window.cpp b/src/opengl/main/gui/history_window.cpp index 7c76a57a..f62c80ec 100644 --- a/src/opengl/main/gui/history_window.cpp +++ b/src/opengl/main/gui/history_window.cpp @@ -1,12 +1,11 @@ #include "history_window.hpp" -#include "colors.hpp" #include "format_imgui_text.hpp" +#include "gui/ColorConversions.hpp" #include "gui/gui_labels.hpp" -#include "gui/push_pop_id.hpp" #include "tool_tip.hpp" +#include - -void fme::history_window::render() const +void fme::history_window::on_im_gui_update() const { const auto selections = m_selections.lock(); if (!selections) @@ -84,15 +83,17 @@ void fme::history_window::draw_table() const { ImGui::TableSetBgColor( ImGuiTableBgTarget_RowBg0, - ImU32{ colors::TableDarkGray });// Dark gray + ff_8::Colors::to_imU32( + ff_8::Colors::TableDarkGray));// Dark gray } else { ImGui::TableSetBgColor( ImGuiTableBgTarget_RowBg0, - ImU32{ - colors::TableLightDarkGray });// Slightly lighter - // gray + ff_8::Colors::to_imU32( + ff_8::Colors::TableLightDarkGray));// Slightly + // lighter + // gray } ++i; @@ -116,11 +117,15 @@ void fme::history_window::draw_table() const } }; - const auto pop_id = PushPopID(); + const auto pop_id = imgui_utils::ImGuiPushId(); ImGui::PushStyleColor( - ImGuiCol_HeaderHovered, colors::TableDarkGrayHovered); + ImGuiCol_HeaderHovered, + ff_8::Colors::to_imvec4( + ff_8::Colors::TableDarkGrayHovered)); ImGui::PushStyleColor( - ImGuiCol_HeaderActive, colors::TableDarkGrayActive); + ImGuiCol_HeaderActive, + ff_8::Colors::to_imvec4( + ff_8::Colors::TableDarkGrayActive)); if (ImGui::Selectable( "##undo_history", false, @@ -175,15 +180,17 @@ void fme::history_window::draw_table() const { ImGui::TableSetBgColor( ImGuiTableBgTarget_RowBg0, - ImU32{ colors::TableDarkRed });// Dark red + ff_8::Colors::to_imU32( + ff_8::Colors::TableDarkRed));// Dark red } else { ImGui::TableSetBgColor( ImGuiTableBgTarget_RowBg0, - ImU32{ - colors::TableLightDarkRed });// Slightly lighter - // dark red + ff_8::Colors::to_imU32( + ff_8::Colors::TableLightDarkRed));// Slightly + // lighter dark + // red } ++i; @@ -206,12 +213,16 @@ void fme::history_window::draw_table() const format_imgui_text("{}", text); } }; - const auto pop_id = PushPopID(); + const auto pop_id = imgui_utils::ImGuiPushId(); ImGui::PushStyleColor( - ImGuiCol_HeaderHovered, colors::TableDarkRedHovered); + ImGuiCol_HeaderHovered, + ff_8::Colors::to_imvec4( + ff_8::Colors::TableDarkRedHovered)); ImGui::PushStyleColor( - ImGuiCol_HeaderActive, colors::TableDarkRedActive); + ImGuiCol_HeaderActive, + ff_8::Colors::to_imvec4( + ff_8::Colors::TableDarkRedActive)); if (ImGui::Selectable( "##redo history", false, @@ -239,6 +250,13 @@ void fme::history_window::draw_table() const } } } + +fme::history_window::history_window( + const std::shared_ptr &new_selections, + const std::shared_ptr &new_map_sprite) + : m_map_sprite{ new_map_sprite } + , m_selections{ new_selections } {}; + void fme::history_window::update( const std::shared_ptr &new_map_sprite) const { @@ -248,4 +266,23 @@ void fme::history_window::update( const std::shared_ptr &new_selections) const { m_selections = new_selections; +} +void fme::history_window::on_im_gui_window_menu() const +{ + const auto selections = m_selections.lock(); + if (!selections) + { + spdlog::error( + "m_selections is no longer valid. File: {}, Line: {}", + __FILE__, + __LINE__); + return; + } + if (ImGui::MenuItem( + gui_labels::display_history.data(), + "Control + H", + &selections->get())) + { + selections->update(); + } } \ No newline at end of file diff --git a/src/opengl/main/gui/history_window.hpp b/src/opengl/main/gui/history_window.hpp index 31496bdf..5b4a1072 100644 --- a/src/opengl/main/gui/history_window.hpp +++ b/src/opengl/main/gui/history_window.hpp @@ -14,10 +14,15 @@ class [[nodiscard]] history_window public: history_window() = default; - void render() const; + history_window( + const std::shared_ptr &new_selections, + const std::shared_ptr &new_map_sprite); + void on_im_gui_update() const; + void on_im_gui_window_menu() const; void update(const std::shared_ptr &new_map_sprite) const; void update(const std::shared_ptr &new_selections) const; }; }// namespace fme +static_assert(glengine::Renderable); #endif /* AB58D01A_1172_4330_A796_897047556559 */ diff --git a/src/opengl/main/gui/image_compare_window.cpp b/src/opengl/main/gui/image_compare_window.cpp index 7f1ffdc7..b9c842af 100644 --- a/src/opengl/main/gui/image_compare_window.cpp +++ b/src/opengl/main/gui/image_compare_window.cpp @@ -1,8 +1,8 @@ #include "image_compare_window.hpp" #include "format_imgui_text.hpp" -#include "safedir.hpp" #include "tool_tip.hpp" #include +#include #include #include #include @@ -56,7 +56,7 @@ static bool safe_copy_string( std::ranges::begin(src), src_size, std::ranges::data(dst)); dst[static_cast(src_size)] = '\0'; - const auto tmp = safedir(std::ranges::data(dst)); + const auto tmp = ff_8::SafeDir(std::ranges::data(dst)); return tmp.is_dir() && tmp.is_exists(); } ImageCompareWindow::DiffResult::operator toml::table() const @@ -90,7 +90,7 @@ ImageCompareWindow::ImageCompareWindow( } -void ImageCompareWindow::button_input_browse() +void ImageCompareWindow::button_input_browse() const { m_directory_browser.Open(); m_directory_browser.SetTitle("Path A"); @@ -102,7 +102,7 @@ void ImageCompareWindow::button_input_browse() m_directory_browser_mode = directory_mode::input_mode; }; -void ImageCompareWindow::button_output_browse() +void ImageCompareWindow::button_output_browse() const { m_directory_browser.Open(); m_directory_browser.SetTitle("Path B"); @@ -114,7 +114,7 @@ void ImageCompareWindow::button_output_browse() m_directory_browser_mode = directory_mode::output_mode; }; -void ImageCompareWindow::display_save_browser() +void ImageCompareWindow::display_save_browser() const { if (m_diff_results.empty()) @@ -165,7 +165,7 @@ void ImageCompareWindow::display_save_browser() } } -void ImageCompareWindow::open_directory_browser() +void ImageCompareWindow::open_directory_browser() const { m_directory_browser.Display(); if (!m_directory_browser.HasSelected()) @@ -183,7 +183,7 @@ void ImageCompareWindow::open_directory_browser() const std::string &selected_path = m_directory_browser.GetDirectory().string(); // todo check if the directory is valid. - // const auto tmp = safedir(selected_path); + // const auto tmp = ff_8::SafeDir(selected_path); switch (m_directory_browser_mode) { case directory_mode::input_mode: @@ -206,7 +206,7 @@ void ImageCompareWindow::open_directory_browser() } } -void ImageCompareWindow::render() +void ImageCompareWindow::on_im_gui_update() const { const auto selections = m_selections.lock(); if (!selections) @@ -246,7 +246,7 @@ void ImageCompareWindow::render() const float button_width = button_size * 3.0F; ImGui::BeginDisabled(!m_consumer.done() || !m_future_consumer.done()); { - const auto popid = PushPopID(); + const auto popid = imgui_utils::ImGuiPushId(); const float width = ImGui::CalcItemWidth(); ImGui::PushItemWidth(width - (spacing * 2.0F) - button_width * 2.0F); const auto pop_item_width @@ -274,7 +274,7 @@ void ImageCompareWindow::render() }); if (ImGui::InputText("##Path A", m_path1.data(), m_path1.size())) { - const auto tmp = safedir(m_path1.data()); + const auto tmp = ff_8::SafeDir(m_path1.data()); m_path1_valid = tmp.is_dir() && tmp.is_exists(); if (m_path1_valid) { @@ -303,7 +303,7 @@ void ImageCompareWindow::render() format_imgui_wrapped_text("{}", "Path A"); } { - const auto popid = PushPopID(); + const auto popid = imgui_utils::ImGuiPushId(); const float width = ImGui::CalcItemWidth(); ImGui::PushItemWidth(width - (spacing * 2.0F) - button_width * 2.0F); const auto pop_item_width @@ -331,7 +331,7 @@ void ImageCompareWindow::render() }); if (ImGui::InputText("##Path B", m_path2.data(), m_path2.size())) { - const auto tmp = safedir(m_path2.data()); + const auto tmp = ff_8::SafeDir(m_path2.data()); m_path2_valid = tmp.is_dir() && tmp.is_exists(); if (m_path2_valid) { @@ -415,7 +415,7 @@ void ImageCompareWindow::render() }); } -void ImageCompareWindow::diff_results_table() +void ImageCompareWindow::diff_results_table() const { if (m_diff_results.empty()) { @@ -528,7 +528,7 @@ void ImageCompareWindow::diff_results_table() format_imgui_text("{:0.2f}", difference_percentage * 100.0); ImGui::TableNextColumn();// Copy { - const auto pop_id_buttons = PushPopID(); + const auto pop_id_buttons = imgui_utils::ImGuiPushId(); if (ImGui::SmallButton(ICON_FA_COPY)) { ImGui::SetClipboardText(path1.string().c_str()); @@ -559,7 +559,7 @@ void ImageCompareWindow::diff_results_table() format_imgui_text("{:0.2f}", difference_percentage * 100.0); ImGui::TableNextColumn();// Copy { - const auto pop_id_buttons = PushPopID(); + const auto pop_id_buttons = imgui_utils::ImGuiPushId(); if (ImGui::SmallButton(ICON_FA_COPY)) { ImGui::SetClipboardText(path1.string().c_str()); @@ -578,7 +578,7 @@ void ImageCompareWindow::diff_results_table() } } -void ImageCompareWindow::handle_table_sorting() +void ImageCompareWindow::handle_table_sorting() const { if (!m_consumer.done() || !m_future_consumer.done()) { @@ -678,7 +678,7 @@ void ImageCompareWindow::handle_table_sorting() sort_specs->SpecsDirty = false; } -void ImageCompareWindow::CompareDirectoriesStart() +void ImageCompareWindow::CompareDirectoriesStart() const { if (!m_path1_valid || !m_path2_valid) { @@ -722,7 +722,7 @@ void ImageCompareWindow::CompareDirectoriesStart() } } -void ImageCompareWindow::CompareDirectoriesStep() +void ImageCompareWindow::CompareDirectoriesStep() const { if (m_consumer.done()) @@ -783,7 +783,7 @@ void ImageCompareWindow::CompareDirectoriesStep() } } -void ImageCompareWindow::export_button() +void ImageCompareWindow::export_button() const { if (ImGui::Button("Export Diff Results")) { @@ -795,7 +795,7 @@ void ImageCompareWindow::export_button() } } -void ImageCompareWindow::CompareDirectoriesStop() +void ImageCompareWindow::CompareDirectoriesStop() const { m_consumer.stop(); m_future_consumer.stop(); @@ -881,5 +881,23 @@ ImageCompareWindow::DiffResult ImageCompareWindow::CompareImage( / static_cast((std::max)(total_pixels1, total_pixels2)); return result; } - +void ImageCompareWindow::on_im_gui_window_menu() const +{ + const auto selections = m_selections.lock(); + if (!selections) + { + spdlog::error( + "m_selections is no longer valid. File: {}, Line: {}", + __FILE__, + __LINE__); + return; + } + if (ImGui::MenuItem( + gui_labels::display_image_compare.data(), + nullptr, + &selections->get())) + { + selections->update(); + } +} }// namespace fme diff --git a/src/opengl/main/gui/image_compare_window.hpp b/src/opengl/main/gui/image_compare_window.hpp index 7e9a0952..18eb233a 100644 --- a/src/opengl/main/gui/image_compare_window.hpp +++ b/src/opengl/main/gui/image_compare_window.hpp @@ -4,6 +4,7 @@ #include "RangeConsumer.hpp" #include "Selections.hpp" #include +#include #include #include #include @@ -27,48 +28,51 @@ class ImageCompareWindow [[nodiscard]] static toml::array to_toml_array(const std::span diffs) noexcept; + ImageCompareWindow() = default; ImageCompareWindow(const std::shared_ptr &selections); - void render(); - void export_button(); + void on_im_gui_update() const; + void on_im_gui_window_menu() const; private: - static constexpr const std::size_t PopThreshold = 1000U; enum struct directory_mode { input_mode, output_mode, }; - static const constexpr std::size_t max_path_length = { 1024U }; - std::array m_path1 = {}; - bool m_path1_valid = { false }; - std::array m_path2 = {}; - bool m_path2_valid = false; - std::weak_ptr m_selections = {}; - std::vector m_diff_results = {}; - std::unordered_set m_files_in_path2 = {}; + std::weak_ptr m_selections = {}; + static constexpr const std::size_t PopThreshold = { 1000U }; + static const constexpr std::size_t max_path_length = { 1024U }; + mutable std::array m_path1 = {}; + mutable bool m_path1_valid = { false }; + mutable std::array m_path2 = {}; + mutable bool m_path2_valid = { false }; + mutable std::vector m_diff_results = {}; + mutable std::unordered_set m_files_in_path2 = {}; - std::vector> - m_diff_result_futures = {}; - bool m_auto_scroll = true; - directory_mode m_directory_browser_mode = {}; - ImGui::FileBrowser m_directory_browser{ + mutable std::vector> + m_diff_result_futures = {}; + mutable bool m_auto_scroll = true; + mutable directory_mode m_directory_browser_mode = {}; + mutable ImGui::FileBrowser m_directory_browser{ ImGuiFileBrowserFlags_SelectDirectory | ImGuiFileBrowserFlags_CreateNewDir | ImGuiFileBrowserFlags_EditPathString | ImGuiFileBrowserFlags_SkipItemsCausingError }; - ImGui::FileBrowser m_save_dialog{ + mutable ImGui::FileBrowser m_save_dialog{ ImGuiFileBrowserFlags_EditPathString | ImGuiFileBrowserFlags_CreateNewDir | ImGuiFileBrowserFlags_EnterNewFilename | ImGuiFileBrowserFlags_SkipItemsCausingError }; - RangeConsumer m_consumer; - FutureConsumer>> - m_future_consumer; + mutable RangeConsumer + m_consumer; + mutable FutureConsumer< + std::vector>> + m_future_consumer; - std::filesystem::path m_save_directory = []() + mutable std::filesystem::path m_save_directory = []() { try { @@ -82,15 +86,16 @@ class ImageCompareWindow return std::filesystem::path{}; } }(); - void diff_results_table(); - void handle_table_sorting(); - void display_save_browser(); - void open_directory_browser(); - void button_input_browse(); - void button_output_browse(); - void CompareDirectoriesStart(); - void CompareDirectoriesStep(); - void CompareDirectoriesStop(); + void export_button() const; + void diff_results_table() const; + void handle_table_sorting() const; + void display_save_browser() const; + void open_directory_browser() const; + void button_input_browse() const; + void button_output_browse() const; + void CompareDirectoriesStart() const; + void CompareDirectoriesStep() const; + void CompareDirectoriesStop() const; static DiffResult CompareImage( std::filesystem::path fileA, std::filesystem::path fileB); @@ -99,4 +104,5 @@ class ImageCompareWindow std::filesystem::path fileB); }; }// namespace fme +static_assert(glengine::Renderable); #endif /* C126DFEB_2E60_4799_8C5D_8ECE89625649 */ diff --git a/src/opengl/main/gui/imgui_color.hpp b/src/opengl/main/gui/imgui_color.hpp deleted file mode 100644 index 545785f2..00000000 --- a/src/opengl/main/gui/imgui_color.hpp +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef CC65C6B1_E0C1_485A_BC29_965EB1AE26A7 -#define CC65C6B1_E0C1_485A_BC29_965EB1AE26A7 -#include -#include -#include -#include - -template -concept is_enum = std::is_enum_v; -template -concept is_enum_or_integral = is_enum || std::integral; -template< - is_enum_or_integral number_type, - is_enum_or_integral... rest_number_type> -inline static constexpr number_type bitwise_or( - number_type first, - rest_number_type... rest) -{ - return static_cast( - static_cast(first) - | (static_cast(rest) | ...)); -} -template< - is_enum_or_integral number_type, - is_enum_or_integral... rest_number_type> -inline static constexpr number_type bitwise_and( - number_type start, - rest_number_type... rest) -{ - return static_cast( - static_cast(start) - & (static_cast(rest) & ...)); -} -template -inline static constexpr number_type bitwise_not(number_type value) -{ - return static_cast(~static_cast(value)); -} -inline static constexpr ImU32 imgui_color32( - std::uint8_t red, - std::uint8_t green, - std::uint8_t blue, - std::uint8_t alpha) -{ - constexpr auto R_SHIFT = 0U; - constexpr auto G_SHIFT = 8U; - constexpr auto B_SHIFT = 16U; - constexpr auto A_SHIFT = 24U; - return bitwise_or( - ImU32{}, - alpha << A_SHIFT, - blue << B_SHIFT, - green << G_SHIFT, - red << R_SHIFT); -} -inline static constexpr ImU32 - imgui_color32(open_viii::struct_of_color32_byte auto color) -{ - return imgui_color32(color.r, color.g, color.b, color.a); -} -inline static constexpr ImU32 imgui_color32(open_viii::Color auto color) -{ - return imgui_color32(color.r(), color.b(), color.b(), color.a()); -} - -#endif /* CC65C6B1_E0C1_485A_BC29_965EB1AE26A7 */ diff --git a/src/opengl/main/gui/import.cpp b/src/opengl/main/gui/import.cpp index fd5b269a..3b5ececf 100644 --- a/src/opengl/main/gui/import.cpp +++ b/src/opengl/main/gui/import.cpp @@ -1,23 +1,23 @@ #include "import.hpp" -#include "archives_group.hpp" #include "as_string.hpp" #include "collapsing_tile_info.hpp" -#include "compact_type.hpp" -#include "Configuration.hpp" #include "create_tile_button.hpp" #include "cstdint" #include "filebrowser.hpp" -#include "filter.hpp" #include "format_imgui_text.hpp" #include "generic_combo.hpp" +#include "gui/ColorConversions.hpp" #include "gui_labels.hpp" -#include "imgui_color.hpp" -#include "push_pop_id.hpp" #include "RangeConsumer.hpp" -#include "safedir.hpp" #include "tool_tip.hpp" #include +#include +#include +#include +#include +#include #include +#include #include #include @@ -193,7 +193,7 @@ open_viii::graphics::background::Map::variant_tile & ImVec2 const combo_pos = ImGui::GetCursorScreenPos(); - const auto the_end_id_0 = PushPopID(); + const auto the_end_id_0 = imgui_utils::ImGuiPushId(); static bool was_hovered = false; ImGui::PushItemWidth( @@ -222,7 +222,7 @@ open_viii::graphics::background::Map::variant_tile & { const auto next_col_pop = glengine::ScopeGuard([]() { ImGui::NextColumn(); }); - const auto the_end_id_1 = PushPopID(); + const auto the_end_id_1 = imgui_utils::ImGuiPushId(); const auto iterate = glengine::ScopeGuard([&tile_id]() { ++tile_id; }); bool is_selected @@ -293,7 +293,7 @@ open_viii::graphics::background::Map::variant_tile & { { // Left - const auto pop_id_left = PushPopID(); + const auto pop_id_left = imgui_utils::ImGuiPushId(); ImGui::SameLine(0, spacing); const bool disabled = std::cmp_less_equal( @@ -314,7 +314,7 @@ open_viii::graphics::background::Map::variant_tile & } { // Right - const auto pop_id_right = PushPopID(); + const auto pop_id_right = imgui_utils::ImGuiPushId(); ImGui::SameLine(0, spacing); const bool disabled = std::cmp_greater_equal( selections->get() + 1, @@ -430,8 +430,9 @@ bool import::browse_for_image_display_preview() const float const scale = width / static_cast(size.x); const float height = static_cast(size.y) * scale; ImVec2 const cursor_screen_pos = ImGui::GetCursorScreenPos(); - const auto pop_id = PushPopID(); - const auto str_id = fmt::format("id2668{}", get_imgui_id()); + const auto pop_id = imgui_utils::ImGuiPushId(); + const auto str_id + = fmt::format("id2668{}", imgui_utils::ImGuiPushId.id()); ImGui::ImageButton( str_id.c_str(), glengine::ConvertGliDtoImTextureId( @@ -447,7 +448,7 @@ bool import::browse_for_image_display_preview() const { static constexpr float thickness = 2.0F; static const ImU32 color_32 - = static_cast(fme::colors::Red); + = ff_8::Colors::to_imU32(ff_8::Colors::Red); for (auto x_pos = static_cast( selections->get()); std::cmp_less(x_pos, size.x); @@ -675,10 +676,11 @@ void import::collapsing_header_generated_tiles() const / static_cast(texSize.x), static_cast(rect.y + rect.w) / static_cast(texSize.y) }; - const auto the_end_tile_table_tile = PushPopID(); - static constexpr float button_size = 32.F; + const auto the_end_tile_table_tile + = imgui_utils::ImGuiPushId(); + static constexpr float button_size = 32.F; - const auto str = fmt::format("tb{}", i++); + const auto str = fmt::format("tb{}", i++); ImGui::ImageButton( str.c_str(), glengine::ConvertGliDtoImTextureId( diff --git a/src/opengl/main/gui/keyboard_shortcuts_window.cpp b/src/opengl/main/gui/keyboard_shortcuts_window.cpp index efe4b7d0..9cb3f2c2 100644 --- a/src/opengl/main/gui/keyboard_shortcuts_window.cpp +++ b/src/opengl/main/gui/keyboard_shortcuts_window.cpp @@ -1,5 +1,6 @@ #include "keyboard_shortcuts_window.hpp" #include +#include fme::keyboard_shortcuts_window::keyboard_shortcuts_window( std::weak_ptr selections) : m_selections(selections) diff --git a/src/opengl/main/gui/main_menu_paths.hpp b/src/opengl/main/gui/main_menu_paths.hpp index ab969ad4..58fe6067 100644 --- a/src/opengl/main/gui/main_menu_paths.hpp +++ b/src/opengl/main/gui/main_menu_paths.hpp @@ -226,7 +226,8 @@ struct main_menu_paths 0, max_display_chars - display_text.size()); } - const auto pop_id_menu_item = PushPopID(); + const auto pop_id_menu_item + = imgui_utils::ImGuiPushId(); ImVec2 cursor_pos = ImGui::GetCursorScreenPos(); bool selected = ImGui::MenuItem( "##menu_item", nullptr, &is_checked); @@ -355,7 +356,7 @@ struct main_menu_paths const std::ptrdiff_t index, const std::ptrdiff_t delete_me) const { - const auto pop_id = PushPopID(); + const auto pop_id = imgui_utils::ImGuiPushId(); const float button_size = ImGui::GetFrameHeight(); ImGui::SameLine(); if (ImGui::Button(ICON_FA_TRASH, ImVec2{ button_size, button_size })) @@ -383,7 +384,7 @@ struct main_menu_paths if (it != std::ranges::end(transformed_paths)) { - const auto pop_id = PushPopID(); + const auto pop_id = imgui_utils::ImGuiPushId(); const float button_size = ImGui::GetFrameHeight(); ImGui::SameLine(); if (ImGui::Button( @@ -404,7 +405,7 @@ struct main_menu_paths void add_explore_button(const std::filesystem::path &path) const { const float button_size = ImGui::GetFrameHeight(); - const auto _ = PushPopID(); + const auto _ = imgui_utils::ImGuiPushId(); if (ImGui::Button( ICON_FA_FOLDER_OPEN, ImVec2{ button_size, button_size })) { diff --git a/src/opengl/main/gui/push_pop_id.cpp b/src/opengl/main/gui/push_pop_id.cpp deleted file mode 100644 index b7650c1a..00000000 --- a/src/opengl/main/gui/push_pop_id.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include "push_pop_id.hpp" -namespace fme -{ -[[nodiscard]] int &get_imgui_id() -{ - static int imgui_id = {}; - return imgui_id; -} - -[[nodiscard]] glengine::ScopeGuard PushPopID() -{ - ImGui::PushID(++get_imgui_id()); - return glengine::ScopeGuard{ &ImGui::PopID }; -} -}// namespace fme \ No newline at end of file diff --git a/src/opengl/main/gui/push_pop_id.hpp b/src/opengl/main/gui/push_pop_id.hpp deleted file mode 100644 index 2c6b77aa..00000000 --- a/src/opengl/main/gui/push_pop_id.hpp +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef F5DCBECE_9BF1_4228_BFAE_6AA9A57273F5 -#define F5DCBECE_9BF1_4228_BFAE_6AA9A57273F5 -#include -#include -namespace fme -{ -[[nodiscard]] int &get_imgui_id(); -[[nodiscard]] glengine::ScopeGuard PushPopID(); -}// namespace fme -#endif /* F5DCBECE_9BF1_4228_BFAE_6AA9A57273F5 */ diff --git a/src/opengl/main/gui/textures_window.cpp b/src/opengl/main/gui/textures_window.cpp index 8415f2ce..c80be4dc 100644 --- a/src/opengl/main/gui/textures_window.cpp +++ b/src/opengl/main/gui/textures_window.cpp @@ -103,7 +103,7 @@ void fme::textures_window::render() const std::string title = fmt::format("{}", index); render_thumbnail_button(title, texture, false, []() {}); // Right-click context menu - const auto pop_id = PushPopID(); + const auto pop_id = imgui_utils::ImGuiPushId(); if (!std::ranges::empty(texture.path())) { if (ImGui::BeginPopupContextItem( @@ -333,14 +333,18 @@ void fme::textures_window::render_thumbnail_button( } }; if (selected) { - ImGui::PushStyleColor(ImGuiCol_Button, colors::ButtonGreen); ImGui::PushStyleColor( - ImGuiCol_ButtonHovered, colors::ButtonGreenHovered); + ImGuiCol_Button, + ff_8::Colors::to_imvec4(ff_8::Colors::ButtonGreen)); ImGui::PushStyleColor( - ImGuiCol_ButtonActive, colors::ButtonGreenActive); + ImGuiCol_ButtonHovered, + ff_8::Colors::to_imvec4(ff_8::Colors::ButtonGreenHovered)); + ImGui::PushStyleColor( + ImGuiCol_ButtonActive, + ff_8::Colors::to_imvec4(ff_8::Colors::ButtonGreenActive)); } - const auto pop_id = PushPopID(); + const auto pop_id = imgui_utils::ImGuiPushId(); if (ImGui::ImageButton(file_name.c_str(), tex_id, thumb_size)) { std::invoke(on_click); @@ -371,14 +375,18 @@ void fme::textures_window::render_thumbnail_button( } }; if (selected) { - ImGui::PushStyleColor(ImGuiCol_Button, colors::ButtonGreen); ImGui::PushStyleColor( - ImGuiCol_ButtonHovered, colors::ButtonGreenHovered); + ImGuiCol_Button, + ff_8::Colors::to_imvec4(ff_8::Colors::ButtonGreen)); + ImGui::PushStyleColor( + ImGuiCol_ButtonHovered, + ff_8::Colors::to_imvec4(ff_8::Colors::ButtonGreenHovered)); ImGui::PushStyleColor( - ImGuiCol_ButtonActive, colors::ButtonGreenActive); + ImGuiCol_ButtonActive, + ff_8::Colors::to_imvec4(ff_8::Colors::ButtonGreenActive)); } - const auto pop_id = PushPopID(); + const auto pop_id = imgui_utils::ImGuiPushId(); if (ImGui::ImageButton(file_name.c_str(), tex_id, thumb_size)) { std::invoke(on_click); @@ -404,7 +412,7 @@ void fme::textures_window::draw_thumbnail_label( ImGui::SetCursorScreenPos(ImVec2( text_start_pos.x + text_area_width + ImGui::GetStyle().FramePadding.x, text_start_pos.y)); - const auto pop_id = PushPopID(); + const auto pop_id = imgui_utils::ImGuiPushId(); // if (ImGui::Button(ICON_FA_TRASH, button_size)) // { // m_remove_queue.push_back(file_name); diff --git a/src/opengl/main/gui/tool_tip.hpp b/src/opengl/main/gui/tool_tip.hpp index bd813e47..3fa597db 100644 --- a/src/opengl/main/gui/tool_tip.hpp +++ b/src/opengl/main/gui/tool_tip.hpp @@ -1,9 +1,9 @@ #ifndef B4F3B564_D2A3_4C2C_992A_95E9DAEA83EF #define B4F3B564_D2A3_4C2C_992A_95E9DAEA83EF #include "format_imgui_text.hpp" -#include "push_pop_id.hpp" #include #include +#include #include namespace fme { @@ -30,7 +30,7 @@ void tool_tip( return; } - // const auto pop_id = PushPopID(); + // const auto pop_id = imgui_utils::ImGuiPushId(); if (ImGui::BeginTooltip()) { const auto pop_tool_tip = glengine::ScopeGuard{ &ImGui::EndTooltip }; @@ -67,7 +67,7 @@ static inline void tool_tip( return; } - // const auto pop_id = PushPopID(); + // const auto pop_id = imgui_utils::ImGuiPushId(); if (ImGui::BeginTooltip()) { const auto pop_tool_tip = glengine::ScopeGuard{ &ImGui::EndTooltip }; diff --git a/src/opengl/main/main.cpp b/src/opengl/main/main.cpp index 8c64bc4f..dacee434 100644 --- a/src/opengl/main/main.cpp +++ b/src/opengl/main/main.cpp @@ -1,9 +1,12 @@ - +#ifndef DEFAULT_LOG_PATH +#define DEFAULT_LOG_PATH "res/field-map-editor.log"// fallback, just in case +#endif // clang-format off #include #include // clang-format on #include "gui/gui.hpp" +#include "spdlog/sinks/ringbuffer_sink.h" #include #include @@ -74,8 +77,8 @@ static void setWindowIcon(GLFWwindow *const window) static GLFWwindow *create_glfw_window() { using namespace fme; - const Configuration config = {}; - const int window_height + const ff_8::Configuration config = {}; + const int window_height = config[SelectionInfo::id].value_or( SelectionInfo::default_value()); const int window_width @@ -113,20 +116,63 @@ static GLFWwindow *create_glfw_window() glfwSwapInterval(1);// Enable vsync return window; } -int main( - [[maybe_unused]] int argc, - [[maybe_unused]] char **argv) + +static std::shared_ptr initialize_logger() { + + std::error_code error_code = {}; + + auto temp_path = std::filesystem::path(DEFAULT_LOG_PATH); + std::string path; + try + { + if (temp_path.is_relative()) + { + temp_path = (std::filesystem::current_path(error_code) / path); + } + temp_path.make_preferred(); + spdlog::info("log path: {}", temp_path); + path = temp_path.string(); + } + catch (const std::filesystem::filesystem_error &e) + { + spdlog::error( + "Filesystem error while constructing config path: {}", e.what()); + } + catch (const std::exception &e) + { + spdlog::error( + "Unexpected error while constructing config path: {}", e.what()); + } + if (error_code) + { + spdlog::warn( + "{}:{} - {}: {} path: \"{}\"", + __FILE__, + __LINE__, + error_code.value(), + error_code.message(), + path); + error_code.clear(); + } try { // Create file logger and set as default - auto file_logger = spdlog::basic_logger_mt( - "file_logger", "res/field_map_editor.log", true); + auto file_sink + = std::make_shared(path, true); + auto memory_sink + = std::make_shared(2000); + // Remove logger name from output pattern - file_logger->set_pattern(R"([%Y-%m-%d %H:%M:%S.%e] [%^%l%$] %v)"); + file_sink->set_pattern(R"([%Y-%m-%d %H:%M:%S.%e] [%^%l%$] %v)"); + memory_sink->set_pattern(R"([%H:%M:%S] [%^%l%$] %v)"); + - spdlog::set_default_logger(file_logger); + std::vector sinks{ file_sink, memory_sink }; + auto logger = std::make_shared( + "multi", sinks.begin(), sinks.end()); + spdlog::set_default_logger(logger); // Set log level based on build type // #ifndef NDEBUG @@ -140,12 +186,26 @@ int main( // Now log anywhere spdlog::info("App started"); + spdlog::info("Log file created at: {}", path); + return memory_sink; } catch (const spdlog::spdlog_ex &ex) { std::cerr << "Log init failed: " << ex.what() << std::endl; } - GLFWwindow *const window = create_glfw_window(); + catch (const std::exception &ex) + { + std::cerr << "Unexpected error: " << ex.what() << std::endl; + } + return nullptr; +} + +int main( + [[maybe_unused]] int argc, + [[maybe_unused]] char **argv) +{ + auto memory_sink = initialize_logger(); + GLFWwindow *const window = create_glfw_window(); if (!window) return 0; setWindowIcon(window); @@ -179,9 +239,8 @@ int main( // Enable debug output glengine::GlCall{}(glEnable, GL_DEBUG_OUTPUT); glengine::GlCall{}(glEnable, GL_DEBUG_OUTPUT_SYNCHRONOUS); - { - auto the_gui = fme::gui{ window }; + auto the_gui = fme::gui{ window, std::move(memory_sink) }; the_gui.start(window); } diff --git a/src/opengl/main/map_operation.cpp b/src/opengl/main/map_operation.cpp index 42a2d27b..b6e02a8f 100644 --- a/src/opengl/main/map_operation.cpp +++ b/src/opengl/main/map_operation.cpp @@ -4,16 +4,16 @@ #include "map_operation.hpp" #include "formatters.hpp" -#include "tile_operations.hpp" #include +#include #include #include #include #include namespace ff_8 { -static constexpr auto not_invalid = tile_operations::NotInvalidTile{}; -void flatten_bpp(map_group::Map &map) +static constexpr auto not_invalid = TileOperations::NotInvalidTile{}; +void flatten_bpp(MapGroup::Map &map) { map.visit_tiles( [](auto &tiles) @@ -32,7 +32,7 @@ void flatten_bpp(map_group::Map &map) }); }); } -void flatten_palette(map_group::Map &map) +void flatten_palette(MapGroup::Map &map) { map.visit_tiles( [](auto &tiles) @@ -50,7 +50,7 @@ void flatten_palette(map_group::Map &map) }); }); } -void compact_map_order_ffnx(map_group::Map &map) +void compact_map_order_ffnx(MapGroup::Map &map) { map.visit_tiles( [](auto &&tiles) @@ -64,10 +64,9 @@ void compact_map_order_ffnx(map_group::Map &map) const auto size_of_tiles = std::ranges::distance(filtered_tiles); using tile_t = std::remove_cvref_t< std::ranges::range_value_t>; - const auto with_depth_operation - = ff_8::tile_operations::WithDepth{ - open_viii::graphics::BPPT::BPP4_CONST() - }; + const auto with_depth_operation = ff_8::TileOperations::Depth::With{ + open_viii::graphics::BPPT::BPP4_CONST() + }; for (auto &&[tile_index, tile] : filtered_and_enumerated_tiles) { @@ -78,19 +77,20 @@ void compact_map_order_ffnx(map_group::Map &map) const auto new_pos = dest_coords_for_horizontal_tile_index_swizzle( tile_index, size_of_tiles); - const auto source_x - = static_cast>( - new_pos.source_xy.x); - const auto source_y - = static_cast>( - new_pos.source_xy.y); + const auto source_x = static_cast< + ff_8::TileOperations::SourceX::value_type>( + new_pos.source_xy.x); + const auto source_y = static_cast< + ff_8::TileOperations::SourceY::value_type>( + new_pos.source_xy.y); const auto with_texture_id_operation - = ff_8::tile_operations::WithTextureId{ + = ff_8::TileOperations::TextureId::With{ new_pos.texture_page }; const auto with_source_xy_operation - = ff_8::tile_operations::WithSourceXY{ - { source_x, source_y } + = ff_8::TileOperations::SourceXY::With{ + ff_8::TileOperations::SourceXY::value_type{ + source_x, source_y } }; tile = tile | with_depth_operation | with_source_xy_operation | with_texture_id_operation; @@ -99,14 +99,14 @@ void compact_map_order_ffnx(map_group::Map &map) } void compact_move_conflicts_only( - map_group::Map &map, - const source_tile_conflicts &conflicts) + MapGroup::Map &map, + const SourceTileConflicts &conflicts) { map.visit_tiles( [&conflicts](auto &&tiles) { - std::vector empty_locations + std::vector empty_locations = conflicts.range_of_empty_locations() | std::ranges::to(); auto range_of_conflicts = conflicts.range_of_conflicts(); @@ -114,10 +114,9 @@ void compact_move_conflicts_only( // std::views::filter(not_invalid); using tile_t = std::remove_cvref_t< std::ranges::range_value_t>; - const auto with_depth_operation - = ff_8::tile_operations::WithDepth{ - open_viii::graphics::BPPT::BPP4_CONST() - }; + const auto with_depth_operation = ff_8::TileOperations::Depth::With{ + open_viii::graphics::BPPT::BPP4_CONST() + }; for (const auto &indieces : range_of_conflicts) { @@ -139,20 +138,25 @@ void compact_move_conflicts_only( // filter out any locations you don't want here. const auto texture_page = static_cast< - ff_8::tile_operations::TextureIdT>( - location.t); - const auto source_x = static_cast< - ff_8::tile_operations::SourceXT>( - location.x); - const auto source_y = static_cast< - ff_8::tile_operations::SourceYT>( - location.y); + ff_8::TileOperations::TextureId::value_type< + tile_t>>(location.t); + const auto source_x + = static_cast>( + location.x); + const auto source_y + = static_cast>( + location.y); const auto with_texture_id_operation - = ff_8::tile_operations::WithTextureId< - tile_t>{ texture_page }; + = ff_8::TileOperations::TextureId::With{ + texture_page + }; const auto with_source_xy_operation - = ff_8::tile_operations::WithSourceXY{ - { source_x, source_y } + = ff_8::TileOperations::SourceXY::With{ + ff_8::TileOperations::SourceXY:: + value_type{ source_x, + source_y } }; tile = tile | with_depth_operation | with_source_xy_operation @@ -171,7 +175,7 @@ void compact_move_conflicts_only( } }); } -void compact_map_order(map_group::Map &map) +void compact_map_order(MapGroup::Map &map) { map.visit_tiles( [](auto &&tiles) @@ -179,32 +183,30 @@ void compact_map_order(map_group::Map &map) auto filtered_tiles = tiles | std::views::filter(not_invalid); using tile_t = std::remove_cvref_t< std::ranges::range_value_t>; - const auto with_depth_operation - = ff_8::tile_operations::WithDepth{ - open_viii::graphics::BPPT::BPP4_CONST() - }; + const auto with_depth_operation = ff_8::TileOperations::Depth::With{ + open_viii::graphics::BPPT::BPP4_CONST() + }; for (std::size_t tile_index = {}; tile_t &tile : filtered_tiles) { - const auto texture_page - = static_cast>( - tile_index / 256); + const auto texture_page = static_cast< + ff_8::TileOperations::TextureId::value_type>( + tile_index / 256); const auto file_tile_index = tile_index % 256; - const auto source_x - = static_cast>( - (file_tile_index % ff_8::map_group::TILE_SIZE) - * ff_8::map_group::TILE_SIZE); - const auto source_y - = static_cast>( - (file_tile_index / ff_8::map_group::TILE_SIZE) - * ff_8::map_group::TILE_SIZE); + const auto source_x = static_cast< + ff_8::TileOperations::SourceX::value_type>( + (file_tile_index % ff_8::MapGroup::TILE_SIZE) + * ff_8::MapGroup::TILE_SIZE); + const auto source_y = static_cast< + ff_8::TileOperations::SourceY::value_type>( + (file_tile_index / ff_8::MapGroup::TILE_SIZE) + * ff_8::MapGroup::TILE_SIZE); ++tile_index; const auto with_texture_id_operation - = ff_8::tile_operations::WithTextureId{ - texture_page - }; + = ff_8::TileOperations::TextureId::With{ texture_page }; const auto with_source_xy_operation - = ff_8::tile_operations::WithSourceXY{ - { source_x, source_y } + = ff_8::TileOperations::SourceXY::With{ + ff_8::TileOperations::SourceXY::value_type{ + source_x, source_y } }; tile = tile | with_depth_operation | with_source_xy_operation | with_texture_id_operation; @@ -255,7 +257,7 @@ template< typename key_lambdaT, typename weight_lambdaT> [[maybe_unused]] static void compact_generic( - map_group::Map &map, + MapGroup::Map &map, key_lambdaT &&key_lambda, weight_lambdaT &&weight_lambda, int passes = 2) @@ -279,11 +281,11 @@ template< const auto weight = weight_lambda(key, tps); if ( - std::cmp_greater_equal(col, ff_8::map_group::TILE_SIZE) + std::cmp_greater_equal(col, ff_8::MapGroup::TILE_SIZE) || std::cmp_greater_equal( - row_weight, ff_8::map_group::TILE_SIZE) + row_weight, ff_8::MapGroup::TILE_SIZE) || std::cmp_greater( - row_weight + weight, ff_8::map_group::TILE_SIZE)) + row_weight + weight, ff_8::MapGroup::TILE_SIZE)) { ++row; col = {}; @@ -291,7 +293,7 @@ template< } if (std::cmp_greater_equal( - row, ff_8::map_group::TILE_SIZE)) + row, ff_8::MapGroup::TILE_SIZE)) { ++page; row = {}; @@ -305,9 +307,9 @@ template< *tp = tp->with_source_xy( static_cast( - col * ff_8::map_group::TILE_SIZE), + col * ff_8::MapGroup::TILE_SIZE), static_cast( - row * ff_8::map_group::TILE_SIZE)) + row * ff_8::MapGroup::TILE_SIZE)) .with_texture_id( static_cast( page)); @@ -320,7 +322,7 @@ template< }); } -void compact_rows(map_group::Map &map) +void compact_rows(MapGroup::Map &map) { compact_generic( map, @@ -336,7 +338,7 @@ void compact_rows(map_group::Map &map) [](const auto &key, const auto &) { return static_cast(1U << (3U - std::get<2>(key))); }); } -void compact_all(map_group::Map &map) +void compact_all(MapGroup::Map &map) { compact_generic( map, @@ -355,12 +357,12 @@ void compact_all(map_group::Map &map) [[nodiscard]] std::vector find_intersecting_swizzle( - const map_group::Map &map, - const ff_8::filters &filters, - const glm::ivec2 &pixel_pos, - const std::uint8_t &texture_page, - bool skip_filters, - bool find_all) + const MapGroup::Map &map, + const ff_8::Filters &filters, + const glm::ivec2 &pixel_pos, + const std::uint8_t &texture_page, + bool skip_filters, + bool find_all) { return map.visit_tiles( [&](const auto &tiles) @@ -370,11 +372,11 @@ void compact_all(map_group::Map &map) }); } [[nodiscard]] std::vector find_intersecting_deswizzle( - const map_group::Map &map, - const ff_8::filters &filters, - const glm::ivec2 &pixel_pos, - bool skip_filters, - bool find_all) + const MapGroup::Map &map, + const ff_8::Filters &filters, + const glm::ivec2 &pixel_pos, + bool skip_filters, + bool find_all) { return map.visit_tiles( [&](const auto &tiles) @@ -394,10 +396,10 @@ QuadStrip get_triangle_strip( // source_position and destination_position are in TILE_SIZE cordinates. // TILE_SIZE default is 16x16. So we pass in the scaled up source_tile_size // and destination_tile_size and do the conversion. - constexpr static auto tile_size = static_cast(map_group::TILE_SIZE); + constexpr static auto tile_size = static_cast(MapGroup::TILE_SIZE); const glm::vec2 base_source = source_position / tile_size; - return { .uv_min - = (base_source * source_tile_size) / source_texture_size, + + return { .uv_min = (base_source * source_tile_size) / source_texture_size, .uv_max = ((base_source + glm::vec2(1)) * source_tile_size) / source_texture_size, .draw_pos @@ -405,8 +407,8 @@ QuadStrip get_triangle_strip( } bool test_if_map_same( const std::filesystem::path &saved_path, - const map_group::WeakField &weak_field, - const map_group::MimType &type) + const MapGroup::WeakField &weak_field, + const MapGroup::MimType &type) { bool return_value = false; const auto field = weak_field.lock(); @@ -415,12 +417,12 @@ bool test_if_map_same( spdlog::error("Failed to lock weak_field: shared_ptr is expired."); return return_value; } - const auto raw_map = map_group::Map{ + const auto raw_map = MapGroup::Map{ type, field->get_entry_data({ saved_path.filename().string() }), false }; auto saved_map - = map_group::Map{ type, open_viii::tools::read_entire_file(saved_path), - false }; + = MapGroup::Map{ type, open_viii::tools::read_entire_file(saved_path), + false }; raw_map.visit_tiles( [&](const auto &raw_tiles) @@ -492,9 +494,9 @@ bool test_if_map_same( } void save_modified_map( const std::filesystem::path &dest_path, - const map_group::Map &map_const, - const map_group::Map &map_changed, - const map_group::Map *const imported) + const MapGroup::Map &map_const, + const MapGroup::Map &map_changed, + const MapGroup::Map *const imported) { const auto path = dest_path.string(); spdlog::info("Saving modified map: {}", path); @@ -576,4 +578,4 @@ void save_modified_map( path, ""); } -}// namespace ff_8 +}// namespace ff_8 \ No newline at end of file diff --git a/src/opengl/main/map_operation.hpp b/src/opengl/main/map_operation.hpp index 6282faef..c97e6f8d 100644 --- a/src/opengl/main/map_operation.hpp +++ b/src/opengl/main/map_operation.hpp @@ -4,9 +4,9 @@ #ifndef FIELD_MAP_EDITOR_MAP_OPERATION_HPP #define FIELD_MAP_EDITOR_MAP_OPERATION_HPP -#include "filter.hpp" -#include "map_group.hpp" -#include "source_tile_conflicts.hpp" +#include +#include +#include #include namespace ff_8 { @@ -17,24 +17,24 @@ struct QuadStrip glm::vec2 draw_pos; }; -void flatten_bpp(map_group::Map &map); -void flatten_palette(map_group::Map &map); +void flatten_bpp(MapGroup::Map &map); +void flatten_palette(MapGroup::Map &map); void compact_move_conflicts_only( - map_group::Map &map, - const source_tile_conflicts &conflicts); -void compact_map_order(map_group::Map &map); -void compact_map_order_ffnx(map_group::Map &map); -void compact_rows(map_group::Map &map); -void compact_all(map_group::Map &map); + MapGroup::Map &map, + const SourceTileConflicts &conflicts); +void compact_map_order(MapGroup::Map &map); +void compact_map_order_ffnx(MapGroup::Map &map); +void compact_rows(MapGroup::Map &map); +void compact_all(MapGroup::Map &map); bool test_if_map_same( const std::filesystem::path &saved_path, - const map_group::WeakField &field, - const map_group::MimType &type); + const MapGroup::WeakField &field, + const MapGroup::MimType &type); void save_modified_map( const std::filesystem::path &dest_path, - const map_group::Map &map_const, - const map_group::Map &map_changed, - const map_group::Map *const imported = nullptr); + const MapGroup::Map &map_const, + const MapGroup::Map &map_changed, + const MapGroup::Map *const imported = nullptr); /** * @brief Computes a triangle strip (quad) with correct UV coordinates and draw @@ -90,20 +90,20 @@ void save_modified_map( return { tile_const.x(), tile_const.y() }; } -[[nodiscard]] static inline glm::ivec2 - dest_coords_for_default(open_viii::graphics::background::is_tile auto &&tile) +[[nodiscard]] static inline glm::ivec2 dest_coords_for_default( + const open_viii::graphics::background::is_tile auto &tile) { return { tile.x(), tile.y() }; } [[nodiscard]] static inline glm::uvec2 dest_coords_for_swizzle_disable_shift( - open_viii::graphics::background::is_tile auto &&tile) + const open_viii::graphics::background::is_tile auto &tile) { return { tile.source_x(), tile.source_y() }; } -[[nodiscard]] static inline glm::uvec2 - dest_coords_for_swizzle(open_viii::graphics::background::is_tile auto &&tile) +[[nodiscard]] static inline glm::uvec2 dest_coords_for_swizzle( + const open_viii::graphics::background::is_tile auto &tile) { using namespace open_viii::graphics::literals; using tile_type = std::remove_cvref_t; @@ -114,7 +114,7 @@ void save_modified_map( } [[nodiscard]] static inline glm::uvec2 source_coords_for_single_swizzle( - open_viii::graphics::background::is_tile auto &&tile) + const open_viii::graphics::background::is_tile auto &tile) { return dest_coords_for_swizzle(std::forward(tile)); } @@ -153,18 +153,18 @@ struct source_x_y_texture_page } [[nodiscard]] std::vector find_intersecting_swizzle( - const map_group::Map &map, - const ff_8::filters &filters, - const glm::ivec2 &pixel_pos, - const std::uint8_t &texture_page, - bool skip_filters, - bool find_all); + const MapGroup::Map &map, + const ff_8::Filters &filters, + const glm::ivec2 &pixel_pos, + const std::uint8_t &texture_page, + bool skip_filters, + bool find_all); [[nodiscard]] std::vector find_intersecting_deswizzle( - const map_group::Map &map, - const ff_8::filters &filters, - const glm::ivec2 &pixel_pos, - bool skip_filters, - bool find_all); + const MapGroup::Map &map, + const ff_8::Filters &filters, + const glm::ivec2 &pixel_pos, + bool skip_filters, + bool find_all); template< std::integral input_t, @@ -203,7 +203,7 @@ static inline void find_intersecting_get_indices( template [[nodiscard]] static inline std::vector find_intersecting_swizzle( const tilesT &tiles, - const ff_8::filters &filters, + const ff_8::Filters &filters, const glm::ivec2 &pixel_pos, const std::uint8_t &texture_page, bool skip_filters = false, @@ -222,7 +222,7 @@ template { if ( !skip_filters - && ff_8::tile_operations::fail_any_filters(filters, tile)) + && ff_8::TileOperations::fail_any_filters(filters, tile)) { return false; } @@ -233,14 +233,14 @@ template pixel_pos.x % max_texture_page_dim, tile.source_x(), tile.source_x() - + static_cast(ff_8::map_group::TILE_SIZE))) + + static_cast(ff_8::MapGroup::TILE_SIZE))) { if (find_intersecting_in_bounds( pixel_pos.y % max_texture_page_dim, tile.source_y(), tile.source_y() + static_cast( - ff_8::map_group::TILE_SIZE))) + ff_8::MapGroup::TILE_SIZE))) { return true; } @@ -286,7 +286,7 @@ template [[nodiscard]] static inline std::vector find_intersecting_deswizzle( const tilesT &tiles, - const ff_8::filters &filters, + const ff_8::Filters &filters, const glm::ivec2 &pixel_pos, bool skip_filters = false, bool find_all = false) @@ -303,20 +303,20 @@ template { if ( !skip_filters - && ff_8::tile_operations::fail_any_filters(filters, tile)) + && ff_8::TileOperations::fail_any_filters(filters, tile)) { return false; } if (find_intersecting_in_bounds( pixel_pos.x, tile.x(), - tile.x() + static_cast(ff_8::map_group::TILE_SIZE))) + tile.x() + static_cast(ff_8::MapGroup::TILE_SIZE))) { if (find_intersecting_in_bounds( pixel_pos.y, tile.y(), tile.y() - + static_cast(ff_8::map_group::TILE_SIZE))) + + static_cast(ff_8::MapGroup::TILE_SIZE))) { return true; } diff --git a/src/opengl/main/map_sprite.cpp b/src/opengl/main/map_sprite.cpp index 5e8bcf1a..347ed1c5 100644 --- a/src/opengl/main/map_sprite.cpp +++ b/src/opengl/main/map_sprite.cpp @@ -2,13 +2,14 @@ #include "append_inserter.hpp" #include "format_imgui_text.hpp" #include "future_operations.hpp" +#include "gui/ColorConversions.hpp" #include "gui/gui_labels.hpp" #include "map_operation.hpp" -#include "safedir.hpp" #include "save_image_pbo.hpp" -#include "utilities.hpp" #include #include +#include +#include #include #include #include @@ -32,16 +33,16 @@ namespace fme { map_sprite::map_sprite( - ff_8::map_group map_group, + ff_8::MapGroup MapGroup, map_sprite_settings settings, - ff_8::filters in_filters, + ff_8::Filters in_filters, std::weak_ptr selections, std::shared_ptr framebuffer) : m_map_group( !settings.require_coo - || (map_group.opt_coo && map_group.opt_coo.value() != open_viii::LangT::generic) - ? std::move(map_group) - : ff_8::map_group{}) + || (MapGroup.opt_coo && MapGroup.opt_coo.value() != open_viii::LangT::generic) + ? std::move(MapGroup) + : ff_8::MapGroup{}) , m_settings(settings) , m_filters(std::move(in_filters)) , m_selections(selections) @@ -120,19 +121,19 @@ void map_sprite::toggle_filter_compact_on_load_original( { switch (m_filters.value()) { - case compact_type::rows: + case ff_8::CompactTypeT::rows: compact_rows_original(skip_update); break; - case compact_type::all: + case ff_8::CompactTypeT::all: compact_all_original(skip_update); break; - case compact_type::move_only_conflicts: + case ff_8::CompactTypeT::move_only_conflicts: compact_move_conflicts_only_original(skip_update); break; - case compact_type::map_order: + case ff_8::CompactTypeT::map_order: compact_map_order_original(skip_update); break; - case compact_type::map_order_ffnx: + case ff_8::CompactTypeT::map_order_ffnx: compact_map_order_ffnx_original(skip_update); break; } @@ -160,26 +161,26 @@ void map_sprite::toggle_filter_flatten_on_load_original( { switch (m_filters.value()) { - case flatten_type::bpp: + case ff_8::FlattenTypeT::bpp: // Only flatten BPP if compact type isn't using map // order if ( !m_filters.enabled() - || (m_filters.value() != compact_type::map_order && m_filters.value() != compact_type::map_order_ffnx)) + || (m_filters.value() != ff_8::CompactTypeT::map_order && m_filters.value() != ff_8::CompactTypeT::map_order_ffnx)) { flatten_bpp_original(skip_update); } break; - case flatten_type::palette: + case ff_8::FlattenTypeT::palette: flatten_palette_original(skip_update); break; - case flatten_type::both: + case ff_8::FlattenTypeT::both: // Only flatten BPP if not using map order if ( !m_filters.enabled() - || (m_filters.value() != compact_type::map_order && m_filters.value() != compact_type::map_order_ffnx)) + || (m_filters.value() != ff_8::CompactTypeT::map_order && m_filters.value() != ff_8::CompactTypeT::map_order_ffnx)) { flatten_bpp_original(skip_update); } @@ -226,7 +227,7 @@ map_sprite::operator ff_8::path_search() const map_sprite map_sprite::with_coo(const open_viii::LangT coo) const { - return { ff_8::map_group{ m_map_group.field, coo }, m_settings, m_filters, + return { ff_8::MapGroup{ m_map_group.field, coo }, m_settings, m_filters, m_selections, m_render_framebuffer }; } @@ -234,11 +235,11 @@ map_sprite map_sprite::with_field( map_sprite::WeakField field, const open_viii::LangT coo) const { - return { ff_8::map_group{ std::move(field), coo }, m_settings, m_filters, + return { ff_8::MapGroup{ std::move(field), coo }, m_settings, m_filters, m_selections, m_render_framebuffer }; } -map_sprite map_sprite::with_filters(ff_8::filters filters) const +map_sprite map_sprite::with_filters(ff_8::Filters filters) const { return { m_map_group, m_settings, std::move(filters), m_selections, m_render_framebuffer }; @@ -1064,7 +1065,7 @@ void map_sprite::update_position( return; } - if (ff_8::tile_operations::fail_any_filters(m_filters, tile)) + if (ff_8::TileOperations::fail_any_filters(m_filters, tile)) { failures.emplace(DrawError::FilteredOut); return; @@ -1271,7 +1272,7 @@ void map_sprite::update_position( // return; // } // } - // if (ff_8::tile_operations::fail_any_filters(m_filters, tile)) + // if (ff_8::TileOperations::fail_any_filters(m_filters, tile)) // { // return; // } @@ -1383,7 +1384,7 @@ void map_sprite::clear_toml_cached_framebuffers() const const key_value_data config_path_values = { .ext = ".toml" }; const std::filesystem::path config_path = config_path_values.replace_tags( selections->get(), selections); - auto config = Configuration(config_path); + auto config = ff_8::Configuration(config_path); config.save(true); m_cache_framebuffer.clear(); m_cache_framebuffer_tooltips.clear(); @@ -1500,7 +1501,7 @@ void map_sprite::load_child_map_sprite_full_filename_texture() const .require_coo = m_settings.require_coo, .force_loading = true }; m_child_map_sprite = std::make_unique( - m_map_group, settings, ff_8::filters{ false }, m_selections); + m_map_group, settings, ff_8::Filters{ false }, m_selections); m_child_map_sprite->consume_now(true); // return;// return early here as the texture loading is placed // in @@ -1600,7 +1601,7 @@ std::tuple< glengine::PaletteBuffer, glengine::HistogramBuffer, glengine::DistanceBuffer> - map_sprite::initialize_buffers(const std::vector &palette) const + map_sprite::initialize_buffers(const std::vector &palette) const { std::tuple< glengine::PaletteBuffer, glengine::HistogramBuffer, @@ -1609,7 +1610,8 @@ std::tuple< glengine::HistogramBuffer{ std::ranges::size(palette) }, glengine::DistanceBuffer{ std::ranges::size(palette) } }; auto &[pb, hb, db] = ret; - pb.initialize(palette); + pb.initialize( + palette | ff_8::Colors::as_vec4 | std::ranges::to()); if (!pb.id()) spdlog::critical("PaletteBuffer initialization failed, aborting"); @@ -1705,7 +1707,7 @@ std::pair< const toml::table *file_table = get_deswizzle_combined_toml_table(filename); - ff_8::filter multi_pupu + ff_8::Filter multi_pupu = { ff_8::FilterSettings::All_Disabled }; multi_pupu.reload(*file_table); if (!multi_pupu.enabled()) @@ -1801,7 +1803,7 @@ std::pair< "Index {:>3}, Color {}, Pupu {}, Count {:>6}, " "Distance {}", index, - fme::color{ color }, + color, pupu, count, distance); @@ -2069,7 +2071,7 @@ bool map_sprite::fail() const } void map_sprite::save_map(const std::filesystem::path &dest_path) const { - ff_8::map_group::OptCoo coo + ff_8::MapGroup::OptCoo coo = m_map_group.opt_coo;// copy because coo is modified const auto map = ff_8::load_map( m_map_group.field, coo, m_map_group.mim, nullptr, false); @@ -2227,21 +2229,21 @@ ff_8::all_unique_values_and_strings { return ff_8::all_unique_values_and_strings(tiles); }); } -const ff_8::filters &map_sprite::filter() const +const ff_8::Filters &map_sprite::filter() const { return m_filters; } -ff_8::filters &map_sprite::filter() +ff_8::Filters &map_sprite::filter() { return m_filters; } map_sprite map_sprite::update( - ff_8::map_group map_group, - bool draw_swizzle) const + ff_8::MapGroup MapGroup, + bool draw_swizzle) const { auto settings = m_settings; settings.draw_swizzle = draw_swizzle; - return { std::move(map_group), settings, m_filters, m_selections }; + return { std::move(MapGroup), settings, m_filters, m_selections }; } const ff_8::all_unique_values_and_strings &map_sprite::uniques() const { @@ -2270,7 +2272,7 @@ const std::vector &map_sprite::working_unique_pupu() const } std::vector> map_sprite::working_unique_color_pupu() const { @@ -2290,7 +2292,7 @@ const std::vector &map_sprite::original_unique_pupu() const } -const ff_8::source_tile_conflicts &map_sprite::original_conflicts() const +const ff_8::SourceTileConflicts &map_sprite::original_conflicts() const { // side effect. we wait till conflicts is needed than we refresh it. m_map_group.maps.refresh_original_all(); @@ -2298,11 +2300,11 @@ const ff_8::source_tile_conflicts &map_sprite::original_conflicts() const { return m_map_group.maps.original_conflicts(); } - static const ff_8::source_tile_conflicts blank{}; + static const ff_8::SourceTileConflicts blank{}; return blank; } -const ff_8::source_tile_conflicts &map_sprite::working_conflicts() const +const ff_8::SourceTileConflicts &map_sprite::working_conflicts() const { // side effect. we wait till conflicts is needed than we refresh it. m_map_group.maps.refresh_working_all(); @@ -2310,7 +2312,7 @@ const ff_8::source_tile_conflicts &map_sprite::working_conflicts() const { return m_map_group.maps.working_conflicts(); } - static const ff_8::source_tile_conflicts blank{}; + static const ff_8::SourceTileConflicts blank{}; return blank; } @@ -2630,7 +2632,7 @@ const ff_8::MapHistory::nsat_map &map_sprite::working_animation_counts() const | std::ranges::views::join // Flatten the vectors into a single // range | std::ranges::to();// merge to vector; - sort_and_remove_duplicates(conflicting_palettes_flatten); + ff_8::sort_and_remove_duplicates(conflicting_palettes_flatten); // Prepare futures to track save operations. std::vector> future_of_futures = {}; @@ -3022,7 +3024,7 @@ void map_sprite::save_deswizzle_generate_toml( m_filters, m_settings //, m_render_framebuffer.mutable_scale() }; - backup.filters = ff_8::filters{ false }; + backup.filters = ff_8::Filters{ false }; backup.filters.value().get() = backup.filters.backup().get(); backup.filters.value().get() @@ -3116,8 +3118,8 @@ void map_sprite::save_deswizzle_generate_toml( = out_path.parent_path() / (out_path.stem().string() + "_mask" + out_path.extension().string()); spdlog::debug( "Queued image save: mask='{}'", mask_path.string()); - const auto colors_to_pupu = - [&]() -> std::vector> + const auto colors_to_pupu = [&]() + -> std::vector> { if (selections->get< ConfigKey::BatchGenerateWhiteOnBlackMask>()) @@ -3304,7 +3306,7 @@ void map_sprite::save_deswizzle_generate_toml( void map_sprite::cache_pupuids( const std::string &file_name_str, - const ff_8::filters &filters) const + const ff_8::Filters &filters) const { if ( filters.enabled() @@ -3406,7 +3408,7 @@ open_viii::LangT const std::filesystem::path config_path = config_path_values.replace_tags( selections->get(), selections); - auto config = Configuration(config_path); + auto config = ff_8::Configuration(config_path); toml::table &root_table = config; toml::table *field_table = nullptr; @@ -3471,7 +3473,7 @@ toml::table *map_sprite::get_deswizzle_combined_coo_table( const key_value_data config_path_values = { .ext = ".toml" }; const std::filesystem::path config_path = config_path_values.replace_tags( selections->get(), selections); - auto config = Configuration(config_path); + auto config = ff_8::Configuration(config_path); toml::table &root_table = config; const auto coo_opt = [&]() @@ -3803,14 +3805,14 @@ void map_sprite::refresh_tooltip(const std::string &file_name) void map_sprite::apply_multi_pupu_filter_deswizzle_combined_toml_table( const std::string &file_name_key, - const ff_8::filter &new_filter) + const ff_8::Filter &new_filter) { if (auto *table = get_deswizzle_combined_toml_table(file_name_key)) { if (new_filter.enabled()) { // Update in-memory filter state from the table - ff_8::filter copy_filter + ff_8::Filter copy_filter = { new_filter.value(), ff_8::FilterSettings::Toggle_Enabled }; copy_filter.combine(*table); @@ -3818,10 +3820,10 @@ void map_sprite::apply_multi_pupu_filter_deswizzle_combined_toml_table( } else { - ff_8::filter copy_filter + ff_8::Filter copy_filter = (ff_8::FilterSettings::Toggle_Enabled); copy_filter.reload(*table); - ff_8::filter::value_type tempvec + ff_8::Filter::value_type tempvec = {}; std::ranges::remove_copy_if( @@ -3855,7 +3857,7 @@ toml::table *map_sprite::add_combine_deswizzle_combined_toml_table( { return nullptr; } - ff_8::filters tmp_filters = { false }; + ff_8::Filters tmp_filters = { false }; for (const std::string &file_name_str : file_names) { if (auto it_base = coo_table->find(file_name_str); diff --git a/src/opengl/main/map_sprite.hpp b/src/opengl/main/map_sprite.hpp index c946beca..5a864e83 100644 --- a/src/opengl/main/map_sprite.hpp +++ b/src/opengl/main/map_sprite.hpp @@ -4,22 +4,19 @@ #ifndef FIELD_MAP_EDITOR_MAP_SPRITE_HPP #define FIELD_MAP_EDITOR_MAP_SPRITE_HPP -#include "filter.hpp" #include "gui/key_value_data.hpp" #include "gui/Selections.hpp" -#include "map_group.hpp" #include "map_operation.hpp" -#include "MapHistory.hpp" -#include "open_viii/archive/Archives.hpp" -#include "open_viii/graphics/background/Map.hpp" -#include "open_viii/graphics/background/Mim.hpp" #include "path_search.hpp" #include "RangeConsumer.hpp" #include "settings_backup.hpp" #include "tile_sizes.hpp" -#include "unique_values.hpp" #include #include +#include +#include +#include +#include #include #include #include @@ -30,6 +27,9 @@ #include #include #include +#include +#include +#include #include #include @@ -221,13 +221,13 @@ struct [[nodiscard]] map_sprite// final = {}; mutable std::map> m_cache_framebuffer_pupuids = {}; - mutable ff_8::map_group m_map_group = {}; + mutable ff_8::MapGroup m_map_group = {}; map_sprite_settings m_settings = {}; mutable std::unique_ptr m_child_map_sprite = { nullptr }; mutable std::map> m_child_textures_map = {}; - mutable ff_8::filters m_filters + mutable ff_8::Filters m_filters = { false };// default false should be override by gui to true. std::weak_ptr m_selections = {}; bool m_using_imported_texture = {}; @@ -326,7 +326,7 @@ struct [[nodiscard]] map_sprite// final glengine::PaletteBuffer, glengine::HistogramBuffer, glengine::DistanceBuffer> - initialize_buffers(const std::vector &palette) const; + initialize_buffers(const std::vector &palette) const; std::pair< std::vector, @@ -346,9 +346,9 @@ struct [[nodiscard]] map_sprite// final public: map_sprite() = default; map_sprite( - ff_8::map_group map_group, + ff_8::MapGroup MapGroup, map_sprite_settings settings, - ff_8::filters in_filters, + ff_8::Filters in_filters, std::weak_ptr selections, std::shared_ptr framebuffer = std::make_shared()); @@ -402,16 +402,15 @@ struct [[nodiscard]] map_sprite// final [[nodiscard]] const ff_8::all_unique_values_and_strings &uniques() const; [[nodiscard]] const std::vector &working_unique_pupu() const; [[nodiscard]] std::vector> working_unique_color_pupu() const; [[nodiscard]] const std::vector & original_unique_pupu() const; [[nodiscard]] const std::vector &original_pupu() const; [[nodiscard]] const std::vector &working_pupu() const; - [[nodiscard]] const ff_8::source_tile_conflicts & - original_conflicts() const; - [[nodiscard]] const ff_8::source_tile_conflicts &working_conflicts() const; + [[nodiscard]] const ff_8::SourceTileConflicts &original_conflicts() const; + [[nodiscard]] const ff_8::SourceTileConflicts &working_conflicts() const; [[nodiscard]] const ff_8::MapHistory::nst_map & working_similar_counts() const; [[nodiscard]] const ff_8::MapHistory::nsat_map & @@ -424,19 +423,19 @@ struct [[nodiscard]] map_sprite// final [[nodiscard]] map_sprite with_field( WeakField field, open_viii::LangT coo) const; - [[nodiscard]] map_sprite with_filters(ff_8::filters filters) const; + [[nodiscard]] map_sprite with_filters(ff_8::Filters filters) const; [[nodiscard]] bool empty() const; - [[nodiscard]] const ff_8::filters &filter() const; + [[nodiscard]] const ff_8::Filters &filter() const; [[nodiscard]] map_sprite update( - ff_8::map_group map_group, - bool draw_swizzle) const; + ff_8::MapGroup MapGroup, + bool draw_swizzle) const; [[nodiscard]] ff_8::all_unique_values_and_strings get_all_unique_values_and_strings() const; [[nodiscard]] glm::uvec2 get_tile_texture_size_for_import() const; [[nodiscard]] Rectangle get_canvas() const; [[nodiscard]] bool undo_enabled() const; [[nodiscard]] bool redo_enabled() const; - [[nodiscard]] ff_8::filters &filter(); + [[nodiscard]] ff_8::Filters &filter(); //[[nodiscard]] static sf::BlendMode set_blend_mode(const // BlendModeT &blend_mode, std::array &quad); [[nodiscard]] bool fallback_textures() const; @@ -489,7 +488,7 @@ struct [[nodiscard]] map_sprite// final const std::shared_ptr &selections); void cache_pupuids( const std::string &, - const ff_8::filters &) const; + const ff_8::Filters &) const; [[nodiscard]] const std::map< std::string, std::string> & @@ -529,7 +528,7 @@ struct [[nodiscard]] map_sprite// final void refresh_tooltip(const std::string &); void apply_multi_pupu_filter_deswizzle_combined_toml_table( const std::string &file_name_key, - const ff_8::filter &new_filter); + const ff_8::Filter &new_filter); [[nodiscard]] toml::table *add_combine_deswizzle_combined_toml_table( const std::vector &, const std::string &); @@ -906,12 +905,12 @@ struct [[nodiscard]] map_sprite// final auto find_conflicting_tiles(const TilesT &tiles) const { using TileT = std::ranges::range_value_t>; - using TextureIdT = ff_8::tile_operations::TextureIdT; - using PaletteIdT = ff_8::tile_operations::PaletteIdT; - static constexpr auto SourceX = ff_8::tile_operations::SourceX{}; - static constexpr auto SourceY = ff_8::tile_operations::SourceY{}; - static constexpr auto TextureId = ff_8::tile_operations::TextureId{}; - static constexpr auto PaletteId = ff_8::tile_operations::PaletteId{}; + using TextureIdT = ff_8::TileOperations::TextureId::value_type; + using PaletteIdT = ff_8::TileOperations::PaletteId::value_type; + static constexpr auto SourceX = ff_8::TileOperations::SourceX{}; + static constexpr auto SourceY = ff_8::TileOperations::SourceY{}; + static constexpr auto TextureId = ff_8::TileOperations::TextureId{}; + static constexpr auto PaletteId = ff_8::TileOperations::PaletteId{}; std::map> conflicts; // Process each pair of matching tiles and insert their palette IDs @@ -982,7 +981,7 @@ struct [[nodiscard]] map_sprite// final const glm::uvec2 &destination_tile_size, const glm::uvec2 &source_texture_size, const open_viii::graphics::background::is_tile auto &tile_const, - open_viii::graphics::background::is_tile auto &&tile) const + const open_viii::graphics::background::is_tile auto &tile) const { return get_triangle_strip( source_tile_size, @@ -997,7 +996,7 @@ struct [[nodiscard]] map_sprite// final const glm::uvec2 &destination_tile_size, const glm::uvec2 &source_texture_size, const open_viii::graphics::background::is_tile auto &tile_const, - open_viii::graphics::background::is_tile auto &&tile, + const open_viii::graphics::background::is_tile auto &tile, bool imported = false) const { const auto src = [this, &tile_const, &imported]() diff --git a/src/opengl/main/open_file_explorer.cpp b/src/opengl/main/open_file_explorer.cpp index 28d36e01..93a6eae6 100644 --- a/src/opengl/main/open_file_explorer.cpp +++ b/src/opengl/main/open_file_explorer.cpp @@ -3,7 +3,7 @@ // #include "open_file_explorer.hpp" -#include "safedir.hpp" +#include #if defined(_WIN32) #include @@ -47,7 +47,7 @@ void open_directory(const std::filesystem::path &path) } void open_file_explorer(const std::filesystem::path &path) { - const auto safe = safedir{ path }; + const auto safe = ff_8::SafeDir{ path }; if (!safe.is_exists()) { return; diff --git a/src/opengl/main/path_search.cpp b/src/opengl/main/path_search.cpp index 50bd0566..6cac0d83 100644 --- a/src/opengl/main/path_search.cpp +++ b/src/opengl/main/path_search.cpp @@ -1,5 +1,5 @@ #include "path_search.hpp" -#include "safedir.hpp" +#include #include namespace ff_8 { @@ -248,7 +248,7 @@ bool path_search::has_deswizzle_path( .pupu_id = pupu.raw() }, selections); // || - // safedir(cpm.replace_tags(get(), + // ff_8::SafeDir(cpm.replace_tags(get(), // selections, filter_path)).is_exists(); } @@ -279,7 +279,7 @@ bool path_search::has_full_filename_path( : std::nullopt }, selections); // || - // safedir(cpm.replace_tags(get(), + // ff_8::SafeDir(cpm.replace_tags(get(), // selections, filter_path)).is_exists(); } @@ -374,7 +374,7 @@ bool path_search::has_swizzle_path( .texture_page = texture_page }, selections); // || - // safedir(cpm.replace_tags(get(), + // ff_8::SafeDir(cpm.replace_tags(get(), // selections, filter_path)).is_exists(); } @@ -469,7 +469,7 @@ bool path_search::has_map_path( } auto temp = cpm.replace_tags(secondary_output_pattern, selections, filter_path); - const auto test = safedir{ temp }; + const auto test = ff_8::SafeDir{ temp }; return !test.is_dir() && test.is_exists(); } @@ -506,7 +506,7 @@ std::vector path_search::generate_paths( } auto temp = cpm.replace_tags(*output_pattern, selections, filter_path); - if (const auto test = safedir{ temp }; + if (const auto test = ff_8::SafeDir{ temp }; !test.is_dir() && test.is_exists()) { paths.push_back(std::move(temp)); @@ -729,7 +729,7 @@ std::vector path_search::get_paths( = [&](const std::string &pattern) -> std::filesystem::path { return data.replace_tags(pattern, selections, root); }; const auto filter_dir - = [](safedir path) { return path.is_exists() && path.is_dir(); }; + = [](ff_8::SafeDir path) { return path.is_exists() && path.is_dir(); }; return selections->get() @@ -754,7 +754,7 @@ std::vector path_search::get_map_paths( = [&](const std::string &pattern) -> std::filesystem::path { return data.replace_tags(pattern, selections, root); }; const auto filter_dir - = [](safedir path) { return path.is_exists() && path.is_dir(); }; + = [](ff_8::SafeDir path) { return path.is_exists() && path.is_dir(); }; auto transformed_paths diff --git a/src/opengl/main/path_search.hpp b/src/opengl/main/path_search.hpp index c2755491..783a87e0 100644 --- a/src/opengl/main/path_search.hpp +++ b/src/opengl/main/path_search.hpp @@ -2,8 +2,8 @@ #define D32D9952_25B7_4925_A5EB_B8672C65F70C #include "gui/key_value_data.hpp" #include "gui/Selections.hpp" -#include "PupuID.hpp" -#include "unique_values.hpp" +#include +#include #include #include #include @@ -24,10 +24,9 @@ struct path_search std::filesystem::path filters_map_value_string = {}; std::vector working_unique_pupu = {}; std::vector current_filenames = {}; - std:: - map> - bpp_palette = {}; - unique_values_and_strings texture_page_id = {}; + std::map> bpp_palette + = {}; + UniqueValues texture_page_id = {}; [[nodiscard]] std::vector diff --git a/src/opengl/main/safedir.cpp b/src/opengl/main/safedir.cpp deleted file mode 100644 index c3297769..00000000 --- a/src/opengl/main/safedir.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// -// Created by pcvii on 12/14/2022. -// - -#include "safedir.hpp" diff --git a/src/opengl/main/safedir.hpp b/src/opengl/main/safedir.hpp deleted file mode 100644 index 8019c0a9..00000000 --- a/src/opengl/main/safedir.hpp +++ /dev/null @@ -1,102 +0,0 @@ -// -// Created by pcvii on 12/14/2022. -// - -#ifndef FIELD_MAP_EDITOR_SAFEDIR_HPP -#define FIELD_MAP_EDITOR_SAFEDIR_HPP -#include -#include -#include -#include -class safedir -{ - public: - safedir(const std::filesystem::path &path) - : m_path(path) - { - std::error_code ec{}; - m_status = std::filesystem::status(m_path, ec); - if (ec) - { - debug(ec, __FILE__, __LINE__); - m_is_dir = false; - m_is_exist = false; - return; - } - m_is_dir = set_is_dir(); - m_is_exist = set_is_exists(); - } - // operator bool() const - // { - // return m_is_dir && m_is_exist; - // } - explicit operator const std::filesystem::path &() const - { - return m_path; - } - bool is_exists() const - { - return m_is_exist; - } - bool is_dir() const - { - return m_is_dir; - } - std::filesystem::path case_insensitive_exists() const - { - std::error_code ec{}; - for (const auto &entry : - std::filesystem::directory_iterator(m_path.parent_path(), ec)) - { - bool size_match = entry.path().filename().string().size() - == m_path.filename().string().size(); - if ( - size_match - && open_viii::tools::i_equals( - entry.path().filename().string(), - m_path.filename().string())) - { - return entry.path(); - } - } - if (ec) - { - debug(ec, __FILE__, __LINE__); - } - return {}; - } - - private: - bool set_is_exists() - { - return std::filesystem::exists(m_status); - } - bool set_is_dir() - { - return std::filesystem::is_directory(m_status); - } - void debug( - std::error_code &ec, - std::string_view file, - int line) const - { - if (ec == std::errc::no_such_file_or_directory) - { - // Not found - common, safe to ignore - return; - } - spdlog::info( - "{}:{} - {}: {} path: \"{}\"", - file, - line, - ec.value(), - ec.message(), - m_path.string()); - ec.clear(); - } - const std::filesystem::path &m_path = {}; - std::filesystem::file_status m_status = {}; - bool m_is_dir = { false }; - bool m_is_exist = { false }; -}; -#endif// FIELD_MAP_EDITOR_SAFEDIR_HPP diff --git a/src/opengl/main/save_image_pbo.cpp b/src/opengl/main/save_image_pbo.cpp index 8fb878ab..788cde8d 100644 --- a/src/opengl/main/save_image_pbo.cpp +++ b/src/opengl/main/save_image_pbo.cpp @@ -3,8 +3,8 @@ // #include "save_image_pbo.hpp" #include "formatters.hpp" -#include "PupuID.hpp" #include +#include #include #include #include @@ -47,7 +47,7 @@ std::future save_image_pbo( glengine::FrameBuffer in_fbo, const GLenum attachment, std::vector> in_color_ids) { // Backup currently bound framebuffer (restored by your helper) @@ -189,18 +189,17 @@ std::future save_image_pbo( } const auto span = std::span( - reinterpret_cast(pixels.get()), + reinterpret_cast(pixels.get()), static_cast(w * h)); // For each unique PupuID, create a vector of masks - std::map> masks; - std::set> logged_colors; - static std::map conv_cache; - std::map + std::map> masks; + std::set> logged_colors; + std::map best_id_cache;// memoizes best id for each pixel color for (const auto &[i, color_in] : span | std::views::enumerate) { - if (color_in == fme::colors::Transparent) + if (color_in == ff_8::Colors::Transparent) continue; const auto best_id = [&]() -> ff_8::PupuID @@ -214,25 +213,13 @@ std::future save_image_pbo( { auto it = std::ranges::min_element( color_ids, - [&](const auto &a, const auto &b) + [&](const ff_8::Color &a, const ff_8::Color &b) { - auto get_conv = [](const glm::vec4 &c) - { - auto nested_it = conv_cache.find(c); - if (nested_it != conv_cache.end()) - return nested_it->second; - fme::color conv - = static_cast(c); - conv_cache.emplace(c, conv); - return conv; - }; - - const auto conv_a = get_conv(std::get<0>(a)); - const auto conv_b = get_conv(std::get<0>(b)); - - return color_in.difference(conv_a) - < color_in.difference(conv_b); - }); + return color_in.difference(a) + < color_in.difference(b); + }, + [](const auto &tuple) + { return std::get<0>(tuple); }); if (it == color_ids.end()) { @@ -250,19 +237,19 @@ std::future save_image_pbo( } auto &mask = masks[best_id]; if (mask.empty()) - mask.resize(span.size(), fme::colors::Black); + mask.resize(span.size(), ff_8::Colors::Black); - mask[static_cast(i)] = fme::colors::White; + mask[static_cast(i)] = ff_8::Colors::White; auto it = std::ranges::find_if( color_ids, [&](const auto &tup) { return std::get<1>(tup) == best_id; }); - fme::color conv_color_best; + if (it != color_ids.end()) { - conv_color_best = conv_cache[std::get<0>(*it)]; + const ff_8::Color &conv_color_best = std::get<0>(*it); if ( color_in != conv_color_best && logged_colors.insert({ color_in, conv_color_best }) diff --git a/src/opengl/main/save_image_pbo.hpp b/src/opengl/main/save_image_pbo.hpp index 4372975d..d12024c1 100644 --- a/src/opengl/main/save_image_pbo.hpp +++ b/src/opengl/main/save_image_pbo.hpp @@ -5,7 +5,8 @@ #ifndef FIELD_MAP_EDITOR_SAVE_IMAGE_PBO_HPP #define FIELD_MAP_EDITOR_SAVE_IMAGE_PBO_HPP -#include "PupuID.hpp" +#include "gui/ColorConversions.hpp" +#include #include #include #include @@ -34,7 +35,7 @@ namespace fme glengine::FrameBuffer in_fbo, const GLenum attachment = GL_COLOR_ATTACHMENT0, std::vector> in_pupu_ids = {}); diff --git a/src/opengl/main/settings_backup.hpp b/src/opengl/main/settings_backup.hpp index 05de3509..0dc57189 100644 --- a/src/opengl/main/settings_backup.hpp +++ b/src/opengl/main/settings_backup.hpp @@ -4,8 +4,8 @@ #ifndef FIELD_MAP_EDITOR_SETTINGS_BACKUP_HPP #define FIELD_MAP_EDITOR_SETTINGS_BACKUP_HPP -#include "filter.hpp" #include +#include namespace fme { struct map_sprite_settings @@ -98,12 +98,12 @@ struct setting_backup struct settings_backup { public: - setting_backup filters; + setting_backup filters; setting_backup settings; // setting_backup scale; settings_backup( - ff_8::filters &in_filters, + ff_8::Filters &in_filters, map_sprite_settings &in_settings) : filters{ in_filters } , settings{ in_settings } diff --git a/src/opengl/main/source_tile_conflicts.cpp b/src/opengl/main/source_tile_conflicts.cpp deleted file mode 100644 index 12882c08..00000000 --- a/src/opengl/main/source_tile_conflicts.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "source_tile_conflicts.hpp" \ No newline at end of file diff --git a/src/opengl/main/tile_operations.hpp b/src/opengl/main/tile_operations.hpp deleted file mode 100644 index dd9b2a2e..00000000 --- a/src/opengl/main/tile_operations.hpp +++ /dev/null @@ -1,342 +0,0 @@ -// -// Created by pcvii on 6/14/2022. -// - -#ifndef FIELD_MAP_EDITOR_TILE_OPERATIONS_HPP -#define FIELD_MAP_EDITOR_TILE_OPERATIONS_HPP -#include -#include -namespace ff_8::tile_operations -{ -template -static constexpr TileT MaxTile = []() -{ - std::array tmp{}; - // std::fill(tmp.begin(), tmp.end(), 0xFFU); - tmp.fill((std::numeric_limits::max)()); - return std::bit_cast(tmp); -}(); -#define CONCAT(a, b) a##b -#define TILE_OPERATION(STRING, FUNCTION) \ - template \ - using CONCAT(STRING, T) = typename std::remove_cvref_t< \ - std::invoke_result_t>; \ - struct STRING \ - { \ - template \ - constexpr CONCAT( \ - STRING, \ - T) \ - operator()(const TileT &tile) const noexcept \ - { \ - return tile.FUNCTION(); \ - } \ - }; \ - template \ - struct CONCAT(STRING, Match) \ - { \ - template \ - constexpr explicit CONCAT( \ - STRING, \ - Match)(TileT tile) \ - : CONCAT( \ - STRING, \ - Match)(tile.FUNCTION()) \ - { \ - } \ - constexpr explicit CONCAT( \ - STRING, \ - Match)(ValueT value) \ - requires(!open_viii::graphics::background::is_tile) \ - : m_value(std::move(value)) \ - { \ - } \ - template \ - constexpr bool operator()(const TileT &tile) const noexcept \ - { \ - return static_cast < CONCAT(STRING, T) < TileT >> (m_value) \ - == tile.FUNCTION(); \ - } \ - auto operator<=>(const CONCAT( \ - STRING, \ - Match) &) const \ - = default; \ - bool operator==(const ValueT &that) const \ - { \ - return m_value == that; \ - } \ - std::strong_ordering operator<=>(const ValueT &that) const \ - { \ - return m_value <=> that; \ - } \ - template \ - bool operator==(const TileT &tile) const \ - { \ - return static_cast < CONCAT(STRING, T) < TileT >> (m_value) \ - == tile.FUNCTION(); \ - } \ - template \ - std::strong_ordering operator<=>(const TileT &tile) const \ - { \ - return static_cast < CONCAT(STRING, T) < TileT \ - >> (m_value) <=> tile.FUNCTION(); \ - } \ - \ - private: \ - ValueT m_value = {}; \ - }; \ - template \ - CONCAT(STRING, Match)(const TileT &)->CONCAT(STRING, Match) \ - < CONCAT(STRING, T) < TileT >> ; \ - struct CONCAT(STRING, DefaultValue) \ - { \ - template \ - constexpr CONCAT( \ - STRING, \ - T) \ - operator()(const T &) const noexcept \ - { \ - return {}; \ - } \ - }; \ - template \ - concept CONCAT(has_with_, FUNCTION) = requires( \ - std::remove_cvref_t tile, CONCAT(STRING, T) < TileT > value) { \ - tile = tile.CONCAT(with_, FUNCTION)(value); \ - }; \ - template \ - struct CONCAT(With, STRING) \ - { \ - constexpr explicit CONCAT( \ - With, \ - STRING)( \ - CONCAT( \ - STRING, \ - T) \ - < TileT > value) \ - : m_value(std::move(value)) \ - { \ - } \ - \ - [[nodiscard]] constexpr TileT \ - operator()(const TileT &tile) const noexcept \ - requires( \ - CONCAT( \ - has_with_, \ - FUNCTION) \ - < TileT >) \ - { \ - spdlog::trace( \ - "Used with_" #FUNCTION " to assign: {}", m_value); \ - return tile.CONCAT(with_, FUNCTION)( \ - static_cast < CONCAT(STRING, T) < TileT >> (m_value)); \ - } \ - constexpr decltype(auto) \ - operator()(const TileT &tile) const noexcept \ - requires( \ - !CONCAT( \ - has_with_, \ - FUNCTION) \ - < TileT >) \ - { /*donno why I can not forward or move when not has_with*/ \ - spdlog::debug("Has no with_" #FUNCTION); \ - return tile; \ - } \ - friend constexpr TileT operator|( \ - const TileT &tile, \ - const CONCAT( \ - With, \ - STRING) \ - & operation) \ - { \ - return operation.operator()(tile); \ - } \ - \ - private: \ - CONCAT( \ - STRING, \ - T) m_value \ - = {}; \ - }; \ - template \ - struct CONCAT(TranslateWith, STRING) \ - { \ - using ValueT = CONCAT( \ - STRING, \ - T); \ - constexpr explicit CONCAT( \ - TranslateWith, \ - STRING)( \ - const TileT &tile, \ - ValueT to_value) \ - : m_to(std::move(to_value)) \ - , m_from(tile.FUNCTION()) \ - { \ - } \ - constexpr explicit CONCAT( \ - TranslateWith, \ - STRING)( \ - ValueT from_value, \ - ValueT to_value) \ - : m_to(std::move(to_value)) \ - , m_from(std::move(from_value)) \ - { \ - } \ - \ - \ - [[nodiscard]] constexpr TileT \ - operator()(const TileT &tile) const noexcept \ - requires( \ - CONCAT( \ - has_with_, \ - FUNCTION) \ - < TileT >) \ - { \ - const auto current = m_to + tile.FUNCTION() - m_from; \ - spdlog::trace( \ - "Used with_" #FUNCTION " to assign: {}", current); \ - return tile.CONCAT(with_, FUNCTION)( \ - static_cast(current)); \ - } \ - \ - \ - constexpr decltype(auto) \ - operator()(const TileT &tile) const noexcept \ - requires( \ - !CONCAT( \ - has_with_, \ - FUNCTION) \ - < TileT >) \ - { /*donno why I can not forward or move when not has_with*/ \ - spdlog::debug("Has no with_" #FUNCTION); \ - return tile; \ - } \ - \ - private: \ - ValueT m_to = {}; \ - ValueT m_from = {}; /*used to calc offset using original*/ \ - }; \ - template \ - struct CONCAT(STRING, Group) \ - { \ - using value_type = CONCAT( \ - STRING, \ - T); \ - using get = STRING; \ - using get_default = CONCAT( \ - STRING, \ - DefaultValue); \ - constexpr CONCAT( \ - STRING, \ - Group)() \ - = default; \ - constexpr explicit CONCAT( \ - STRING, \ - Group)(value_type value) \ - : current(std::move(value)) \ - { \ - } \ - constexpr explicit CONCAT( \ - STRING, \ - Group)(TileT tile) \ - : current(get{}(tile)) \ - { \ - } \ - static constexpr value_type min_value = []() -> value_type \ - { \ - if constexpr (std::signed_integral) \ - { \ - return (std::numeric_limits::min)(); \ - } \ - else \ - { \ - const auto get_f = get{}; \ - return get_f(TileT{}); \ - } \ - }(); \ - static constexpr value_type max_value = []() -> value_type \ - { \ - if constexpr (std::signed_integral) \ - { \ - return (std::numeric_limits::max)(); \ - } \ - else \ - { \ - const auto get_f = get{}; \ - return get_f(MaxTile); \ - } \ - }(); \ - value_type current = {}; \ - constexpr static bool read_only \ - = !CONCAT(has_with_, FUNCTION); \ - using transform_with = CONCAT( \ - With, \ - STRING); \ - using match_with = CONCAT( \ - STRING, \ - Match); \ - } - -TILE_OPERATION( - X, - x); -TILE_OPERATION( - Y, - y); -TILE_OPERATION( - XY, - xy); -TILE_OPERATION( - Z, - z); -TILE_OPERATION( - SourceX, - source_x); -TILE_OPERATION( - SourceY, - source_y); -TILE_OPERATION( - SourceXY, - source_xy); -TILE_OPERATION( - TextureId, - texture_id); -TILE_OPERATION( - BlendMode, - blend_mode); -TILE_OPERATION( - Blend, - blend); -TILE_OPERATION( - Draw, - draw); -TILE_OPERATION( - Depth, - depth); -TILE_OPERATION( - LayerId, - layer_id); -TILE_OPERATION( - PaletteId, - palette_id); -TILE_OPERATION( - AnimationId, - animation_id); -TILE_OPERATION( - AnimationState, - animation_state); -#undef TILE_OPERATION -#undef CONCAT -struct NotInvalidTile -{ - template - constexpr bool operator()(const T &tile) const noexcept - { - return (std::cmp_not_equal(tile.x(), s_end_x)); - } - - private: - static constexpr std::uint16_t s_end_x = { 0x7FFFU }; -}; -}// namespace ff_8::tile_operations -#endif// FIELD_MAP_EDITOR_TILE_OPERATIONS_HPP diff --git a/src/opengl/main/unique_values.cpp b/src/opengl/main/unique_values.cpp deleted file mode 100644 index 6086902f..00000000 --- a/src/opengl/main/unique_values.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "unique_values.hpp" diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index a7b7bdac..ba66ddbe 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,3 +1,6 @@ +# -------------------------------------------------------------- +# Boost.UT – tests +# -------------------------------------------------------------- find_package(ut REQUIRED CONFIG) set(boost_namespace Boost) @@ -5,10 +8,14 @@ if(ut_VERSION VERSION_LESS "1.1.9") set(boost_namespace boost) endif() +# source_tile_conflicts_test ----------------------------------------------- + add_executable(${PROJECT_NAME}_UT_source_tile_conflicts_test UT_source_tile_conflicts_test.cpp) target_link_libraries(${PROJECT_NAME}_UT_source_tile_conflicts_test - PRIVATE "${boost_namespace}::ut") + PRIVATE "${boost_namespace}::ut" + PRIVATE ${PROJECT_NAME}_ff_8 +) target_compile_features( ${PROJECT_NAME}_UT_source_tile_conflicts_test PRIVATE cxx_std_23 @@ -25,3 +32,48 @@ target_compile_definitions( # Register the test with CTest add_test(NAME ${PROJECT_NAME}_UT_source_tile_conflicts_test COMMAND ${PROJECT_NAME}_UT_source_tile_conflicts_test) + +# MapOperationTest ----------------------------------------------------- + add_executable(${PROJECT_NAME}_UT_TileOperationsTest + UT_TileOperationsTest.cpp +) + +target_link_libraries(${PROJECT_NAME}_UT_TileOperationsTest + PRIVATE "${boost_namespace}::ut" + PRIVATE ${PROJECT_NAME}_ff_8 +) + +target_compile_features(${PROJECT_NAME}_UT_TileOperationsTest + PRIVATE cxx_std_23 +) + +add_test( + NAME ${PROJECT_NAME}_UT_TileOperationsTest + COMMAND ${PROJECT_NAME}_UT_TileOperationsTest +) + +# # optional – nicer ctest output +# set_tests_properties(${PROJECT_NAME}_UT_TileOperationsTest PROPERTIES +# FAIL_REGULAR_EXPRESSION "failed" +# PASS_REGULAR_EXPRESSION "[Aa]ll tests passed" +# ) + + +# MapOperations ----------------------------------------------------- + add_executable(${PROJECT_NAME}_UT_MapOperations + UT_MapOperations.cpp +) + +target_link_libraries(${PROJECT_NAME}_UT_MapOperations + PRIVATE "${boost_namespace}::ut" + PRIVATE ${PROJECT_NAME}_ff_8 +) + +target_compile_features(${PROJECT_NAME}_UT_MapOperations + PRIVATE cxx_std_23 +) + +add_test( + NAME ${PROJECT_NAME}_UT_MapOperations + COMMAND ${PROJECT_NAME}_UT_MapOperations +) \ No newline at end of file diff --git a/test/UT_MapOperations.cpp b/test/UT_MapOperations.cpp new file mode 100644 index 00000000..89f0acc9 --- /dev/null +++ b/test/UT_MapOperations.cpp @@ -0,0 +1,129 @@ +// UT_MapOperations.cpp — robust, zero-magic-number version +#include +#include +#include +#include +int main() +{ + using namespace boost::ut; + using namespace ff_8; + using namespace std::string_view_literals; + using namespace MapOperationSettings; + + + "MakeTileInputFunction returns correct type for each strategy"_test = [] + { + expect( + std::holds_alternative< + TileFunction>>( + MakeTileInputFunction(TileInputStrategy::MimSwizzle))); + + expect( + std::holds_alternative>>( + MakeTileInputFunction(TileInputStrategy::ExternalSwizzle))); + + expect( + std::holds_alternative>>( + MakeTileInputFunction(TileInputStrategy::ExternalDeswizzle))); + + expect( + std::holds_alternative>>( + MakeTileInputFunction( + TileInputStrategy::ExternalSwizzleAsOneImage))); + + // Invalid / All → monostate + expect( + std::holds_alternative( + MakeTileInputFunction(TileInputStrategy::All))); + expect( + std::holds_alternative( + MakeTileInputFunction(static_cast(99)))); + }; + + "MakeTileOutputFunction returns correct type"_test = [] + { + expect( + std::holds_alternative< + TileFunction>>( + MakeTileOutputFunction(TileOutputStrategy::Swizzle))); + + expect( + std::holds_alternative< + TileFunction>>( + MakeTileOutputFunction(TileOutputStrategy::Deswizzle))); + + expect( + std::holds_alternative>>( + MakeTileOutputFunction(TileOutputStrategy::SwizzleAsOneImage))); + }; + + "Traits are correct without assuming order"_test = [] + { + auto check_strategy = [](const auto &strategy) + { + using Func = std::remove_cvref_t; + + if constexpr (std::is_same_v) + { + return; + } + else + { + using ExpectedX = typename Func::XType; + using ExpectedY = typename Func::YType; + + // Example: ExternalSwizzleAsOneImage should use + // SwizzleAsOneImage ops + if constexpr ( + std::is_same_v< + Func, TileFunction>>) + { + expect( + std::is_same_v< + ExpectedX, TileOperations::SwizzleAsOneImage::X>); + expect( + std::is_same_v< + ExpectedY, TileOperations::SwizzleAsOneImage::Y>); + } + } + }; + + // Visit every valid input strategy + for (std::size_t i = 1; i < MapOperationSettings::input_values.size(); + ++i) + { + std::visit( + check_strategy, MapOperationSettings::input_values[i]); + } + }; + + // ================================================================== + // NEW: Exhaustive compile-time array correctness + // ================================================================== + + "MapOperationSettings arrays have exact expected size and content"_test + = [] + { + static_assert( + input_values.size() + == std::variant_size_v); + static_assert( + output_values.size() + == std::variant_size_v); + + expect(eq(input_labels.size(), input_values.size())); + expect(eq(input_descriptions.size(), input_values.size())); + expect(eq(output_labels.size(), output_values.size())); + expect(eq(output_descriptions.size(), output_values.size())); + + // First entry is always monostate → empty label + expect(eq(input_labels[0], ""sv)); + expect(eq(input_descriptions[0], ""sv)); + expect(std::holds_alternative(input_values[0])); + }; +} \ No newline at end of file diff --git a/test/UT_TileOperationsTest.cpp b/test/UT_TileOperationsTest.cpp new file mode 100644 index 00000000..4b154b7a --- /dev/null +++ b/test/UT_TileOperationsTest.cpp @@ -0,0 +1,391 @@ +#include +#include +#include + +#include + +std::size_t count_valid_tiles(const open_viii::graphics::background::Map &map) +{ + return map.visit_tiles([&](const auto &tiles) { return tiles.size(); }); +} + +namespace open_viii::graphics::background +{ + +std::ostream &operator<<( + std::ostream &os, + BlendModeT mode) +{ + switch (mode) + { + case BlendModeT::none: + return os << "none"; + case BlendModeT::add: + return os << "add"; + case BlendModeT::subtract: + return os << "subtract"; + case BlendModeT::half_add: + return os << "half_add"; + case BlendModeT::quarter_add: + return os << "quarter_add"; + // add all cases + default: + return os << "unknown(" << static_cast(mode) << ")"; + } +} + +}// namespace open_viii::graphics::background + +int main() +{ + using namespace boost::ut; + using namespace boost::ut::bdd; + using namespace open_viii::graphics::background; + using namespace ff_8::TileOperations; + + spdlog::set_level(spdlog::level::err); + + const auto test_tile = [](TileT tile) + { + // ----------------------------------------------------------------- + // Helper that runs the four sub-tests for a single TileOperation + // ----------------------------------------------------------------- + const auto check_op = [](const Op op, const auto &t) + { + using OpT = std::remove_cvref_t; + using Val = typename OpT::template value_type; + + Val new_val = static_cast(3);// something different + + // ----- GET ----- + expect(eq(op(t), op(t)));// sanity + expect(eq(op(t), op(t)));// (second call – no side-effect) + + // ----- WITH ----- + if constexpr (Op::template has_setter) + { + [[maybe_unused]] auto t2 = t | typename Op::With(new_val); + // expect(eq(op(t2), new_val)); + } + else + { + auto t2 = t | typename Op::With(new_val); + expect(eq(Op(t2), Op(t)));// unchanged on read-only + } + + // ----- MATCH ----- + expect(eq(typename Op::Match(t)(t), true)); + // expect(eq(Op::Match(new_val)(t), false)); + // expect(neq(op(t), new_val)); + + // ----- TRANSLATEWITH ----- + Val from = op(t); + Val to = static_cast(1); + if constexpr (Op::template has_setter) + { + [[maybe_unused]] auto t3 + = t | typename Op::TranslateWith(from, to); + // expect(neq(op(t3), to)); //sometimes eq sometimes + // neq + } + else + { + auto t3 = t | typename Op::TranslateWith(from, to); + expect(eq(Op(t3), Op(t)));// unchanged + } + + // ----- GROUP ----- + auto grp = typename Op::template Group(t); + expect(eq(grp.current, op(t))); + expect(eq(grp.read_only, !Op::template has_setter)); + }; + + // ----------------------------------------------------------------- + // Run the helper on **every** operation + // ----------------------------------------------------------------- + scenario("X") = [&] { check_op(X{}, tile); }; + scenario("Y") = [&] { check_op(Y{}, tile); }; + scenario("Z") = [&] { check_op(Z{}, tile); }; + scenario("SourceX") = [&] { check_op(SourceX{}, tile); }; + scenario("SourceY") = [&] { check_op(SourceY{}, tile); }; + scenario("TextureId") = [&] { check_op(TextureId{}, tile); }; + scenario("PaletteId") = [&] { check_op(PaletteId{}, tile); }; + scenario("Blend") = [&] { check_op(Blend{}, tile); }; + scenario("Depth") = [&] { check_op(Depth{}, tile); }; + scenario("Draw") = [&] { check_op(Draw{}, tile); }; + scenario("BlendMode") = [&] { check_op(BlendMode{}, tile); }; + scenario("LayerId") = [&] { check_op(LayerId{}, tile); }; + scenario("AnimationId") = [&] { check_op(AnimationId{}, tile); }; + scenario("AnimationState") + = [&] { check_op(AnimationState{}, tile); }; + + // ----------------------------------------------------------------- + // NotInvalidTile – still a separate filter + // ----------------------------------------------------------------- + expect(eq(NotInvalidTile{}(tile), true)); + expect(neq(tile.x(), 0x7FFF)); + }; + + // === Create test tiles with known values === + Tile1 t1{}; + t1 = t1.with_x(10) + .with_y(20) + .with_z(30) + .with_source_x(40) + .with_source_y(50) + .with_texture_id(1) + .with_palette_id(2) + .with_blend_mode(BlendModeT::add) + .with_layer_id(1) + .with_animation_id(4) + .with_animation_state(5); + + Tile2 t2{}; + t2 = t2.with_x(15) + .with_y(25) + .with_z(35) + .with_source_x(45) + .with_source_y(55) + .with_texture_id(3) + .with_palette_id(4) + .with_animation_id(6) + .with_animation_state(7); + + Tile3 t3{}; + t3 = t3.with_x(100) + .with_y(200) + .with_z(300) + .with_source_x(10) + .with_source_y(20) + .with_texture_id(5) + .with_palette_id(6); + + // === Run same test for all types === + "Uniform TileOperations on Tile1"_test = [&]() { test_tile(t1); }; + "Uniform TileOperations on Tile2"_test = [&]() { test_tile(t2); }; + "Uniform TileOperations on Tile3"_test = [&]() { test_tile(t3); }; + + "SwizzleAsOneImage operations (using variant constructor)"_test = [&] + { + using namespace open_viii::graphics::background; + using namespace SwizzleAsOneImage; + + // Helper to build a map from a sequence of tiles using the variant + // constructor + const auto make_map = [](auto &&...tiles_pack) + { + // Capture tiles in a vector first so we can return them by + // lambda + auto tile_vector + = std::vector...>{ + tiles_pack... + }; + + return Map( + [&, index = std::size_t{}]() mutable -> Map::variant_tile + { + if (index < tile_vector.size()) + { + return tile_vector[index++]; + } + index = {}; + return std::monostate{}; + }); + }; + + // Build a small map with known order: t1 (Tile1), t2 (Tile2), t3 + // (Tile3) Note: even though types differ, the constructor will reject + // mixed types! So we build three separate homogeneous maps instead. + + const Map map1 = make_map(t1);// only Tile1 + const Map map2 = make_map(t2);// only Tile2 + const Map map3 = make_map(t3);// only Tile3 + + // But for swizzle testing, we really want multiple tiles of the + // *same* type Let's create a realistic test map with 25 valid Tile1s + + + const Map big_map = []() -> Map + { + return Map( + [&, index = std::size_t{}]() mutable -> Map::variant_tile + { + if (index++ < 25) + { + return Tile1{}; + } + return std::monostate{}; + }); + }(); + + const Map bigger_map = []() -> Map + { + return Map( + [&, index = std::size_t{}]() mutable -> Map::variant_tile + { + if (index++ < 513) + { + return Tile1{}; + } + return std::monostate{}; + }); + }(); + + // Expected layout: + // 25 tiles → 25 × 16 = 400 px wide → 2 texture pages (256 + 144) + // tiles per row = ceil(400 / 16) = 25 + // But texture page width = 256 → 16 tiles fit in first page (0..15) + // So tile 16 → x = 0, texture page = 1 + + expect(eq(count_valid_tiles(big_map), 25u)) + << "Map should have 25 valid tiles"; + + SwizzleAsOneImage::X x_op; + SwizzleAsOneImage::Y y_op; + SwizzleAsOneImage::TextureId tp_op; + + + // SwizzleAsOneImage with column-major + max 16 rows + big_map.visit_tiles( + [&](const auto &tiles) + { + auto gx = x_op.set_map(big_map); + auto gy = y_op.set_map(big_map); + auto gtp = tp_op.set_map(big_map); + expect(eq(+x_op(tiles[0]), 0)) << "Tile 0 X "; + expect(eq(+y_op(tiles[0]), 0)) << "Tile 0 Y "; + expect(eq(+tp_op(tiles[0]), 0)) << "Tile 0 Texture Page "; + + expect(eq(+x_op(tiles[1]), 16)) << "Tile 1 X "; + expect(eq(+y_op(tiles[1]), 0)) << "Tile 1 Y "; + expect(eq(+tp_op(tiles[1]), 0)) << "Tile 1 Texture Page "; + + expect(eq(+x_op(tiles[2]), 0)) << "Tile 2 X "; + expect(eq(+y_op(tiles[2]), 16)) << "Tile 2 Y "; + expect(eq(+tp_op(tiles[2]), 0)) << "Tile 2 Texture Page "; + + expect(eq(+x_op(tiles[15]), 16)) << "Tile 15 X "; + expect(eq(+y_op(tiles[15]), 112)) << "Tile 15 Y "; + expect(eq(+tp_op(tiles[15]), 0)) << "Tile 15 Texture Page "; + + expect(eq(+x_op(tiles[16]), 0)) << "Tile 16 X "; + expect(eq(+y_op(tiles[16]), 128)) << "Tile 16 Y "; + expect(eq(+tp_op(tiles[16]), 0)) << "Tile 16 Texture Page "; + + expect(eq(+x_op(tiles[24]), 0)) << "Tile 24 X "; + expect(eq(+y_op(tiles[24]), 192)) << "Tile 24 Y "; + expect(eq(+tp_op(tiles[24]), 0)) << "Tile 24 Texture Page "; + }); + + // SwizzleAsOneImage with column-major + max 16 rows — now with + // bigger_map (513 tiles) + bigger_map.visit_tiles( + [&](const auto &tiles) + { + auto gx = x_op.set_map(bigger_map); + auto gy = y_op.set_map(bigger_map); + auto gtp = tp_op.set_map(bigger_map); + + // Tile 0: top-left of first page + expect(eq(+x_op(tiles[0]), 0)) << "BigMap Tile 0 X"; + expect(eq(+y_op(tiles[0]), 0)) << "BigMap Tile 0 Y"; + expect(eq(+tp_op(tiles[0]), 0)) + << "BigMap Tile 0 Texture Page"; + + // Tile 1: second column, same row + expect(eq(+x_op(tiles[1]), 16)) << "BigMap Tile 1 X"; + expect(eq(+y_op(tiles[1]), 0)) << "BigMap Tile 1 Y"; + expect(eq(+tp_op(tiles[1]), 0)) << "BigMap Tile 1 TP"; + + // Tile 31: last tile of first texture page (bottom-right of + // page 0) + expect(eq(+x_op(tiles[31]), 240)) + << "BigMap Tile 31 X (end of page 0)"; + expect(eq(+y_op(tiles[31]), 0)) << "BigMap Tile 31 Y (15*16)"; + expect(eq(+tp_op(tiles[31]), 1)) << "BigMap Tile 31 TP"; + + // Tile 32: first tile of second texture page + expect(eq(+x_op(tiles[32]), 0)) + << "BigMap Tile 32 X (start page 1)"; + expect(eq(+y_op(tiles[32]), 0)) << "BigMap Tile 32 Y"; + expect(eq(+tp_op(tiles[32]), 2)) + << "BigMap Tile 32 Texture Page"; + + // Tile 256: somewhere in the middle (page 8, first column) + expect(eq(+x_op(tiles[256]), 144)) << "BigMap Tile 256 X"; + expect(eq(+y_op(tiles[256]), 112)) << "BigMap Tile 256 Y"; + expect(eq(+tp_op(tiles[256]), 1)) + << "BigMap Tile 256 Texture Page (256/32 = 8)"; + + // Tile 511: very last tile of the 16th full page (page index + // 15) + expect(eq(+x_op(tiles[511]), 0)) << "BigMap Tile 511 X"; + expect(eq(+y_op(tiles[511]), 240)) << "BigMap Tile 511 Y"; + expect(eq(+tp_op(tiles[511]), 1)) + << "BigMap Tile 511 Texture Page (511/32 = 15 full pages)"; + + // Tile 512: the 513th tile → first (and only) tile on the 17th + // texture page + expect(eq(+x_op(tiles[512]), 16)) + << "BigMap Tile 512 X (new page, only tile)"; + expect(eq(+y_op(tiles[512]), 240)) << "BigMap Tile 512 Y"; + expect(eq(+tp_op(tiles[512]), 1)) + << "BigMap Tile 512 Texture Page (17th page, index 16)"; + + // Optional: double-check total number of tiles + expect(eq(tiles.size(), 513u)) << "BigMap total tile count"; + }); + + // Negative test: map not set → should log error and return 0 + big_map.visit_tiles( + [&](const auto &tiles) + { + SwizzleAsOneImage::X clean_op; + expect(eq(+clean_op(tiles[0]), 0)) + << "X without map should return 0"; + // Note: spdlog is set to err, so error should be printed + // if logging enabled + }); + + + // Test with empty map (no valid tiles) + big_map.visit_tiles( + [&](const auto &tiles) + { + const Map empty_map = Map( + []() -> Map::variant_tile { return std::monostate{}; }); + + SwizzleAsOneImage::X op; + auto guard = op.set_map(empty_map); + + // get_index_and_size should fail → return 0 + expect(eq(+op(tiles[0]), 0)) + << "Swizzle on empty map should return 0"; + }); + + + // // Test that mixed tile types are rejected at + // construction time + // static_assert(!std::is_constructible_v Map::variant_tile { + // static int i = 0; + // return i++ == 0 ? Map::variant_tile(Tile1{}) : + // Map::variant_tile(Tile2{}); + // })>); // Should not compile if mixed types were allowed — but + // we can't test compile-time here + + // So instead, runtime check: + // expect( + // throws( + // [] + // { + // Map bad_map( + // [index = std::size_t{}]() mutable -> Map::variant_tile + // { + // return (index++ == 0) ? Map::variant_tile(Tile1{}) + // : Map::variant_tile(Tile2{}); + // }); + // })) + // << "Map constructor should reject mixed tile types"; + }; +} \ No newline at end of file diff --git a/test/UT_source_tile_conflicts_test.cpp b/test/UT_source_tile_conflicts_test.cpp index 3b8460d0..dd88a96e 100644 --- a/test/UT_source_tile_conflicts_test.cpp +++ b/test/UT_source_tile_conflicts_test.cpp @@ -1,6 +1,6 @@ -#include "source_tile_conflicts.hpp" #include // single header +#include #include static constexpr auto sum(auto... args) { @@ -12,31 +12,31 @@ int main() static constexpr auto t_range = std::ranges::views::iota( std::uint8_t{}, - static_cast(ff_8::source_tile_conflicts::T_SIZE)); + static_cast(ff_8::SourceTileConflicts::T_SIZE)); static constexpr auto x_range = std::ranges::views::iota( std::uint8_t{}, - static_cast(ff_8::source_tile_conflicts::X_SIZE)) + static_cast(ff_8::SourceTileConflicts::X_SIZE)) | std::ranges::views::transform( [](const std::uint8_t i) { return static_cast( - i * ff_8::source_tile_conflicts::X_SIZE); + i * ff_8::SourceTileConflicts::X_SIZE); }); static constexpr auto y_range = std::ranges::views::iota( std::uint8_t{}, - static_cast(ff_8::source_tile_conflicts::Y_SIZE)) + static_cast(ff_8::SourceTileConflicts::Y_SIZE)) | std::ranges::views::transform( [](const std::uint8_t i) { return static_cast( - i * ff_8::source_tile_conflicts::Y_SIZE); + i * ff_8::SourceTileConflicts::Y_SIZE); }); // Test case to validate the reverse mapping test("Reverse index validation") = [&] { - const ff_8::source_tile_conflicts stc{}; + const ff_8::SourceTileConflicts stc{}; for (const auto t : t_range) { for (const auto y : y_range) @@ -44,11 +44,11 @@ int main() for (const auto x : x_range) { const auto index - = ff_8::source_tile_conflicts::calculate_index( + = ff_8::SourceTileConflicts::calculate_index( x, y, t); const auto l - = ff_8::source_tile_conflicts::reverse_index(index); + = ff_8::SourceTileConflicts::reverse_index(index); // Assert that input matches output expect(x == l.x) << "Mismatch in x: input " << +x @@ -58,14 +58,14 @@ int main() expect(t == l.t) << "Mismatch in t: input " << +t << ", output " << +l.t; expect( - index < ff_8::source_tile_conflicts::X_SIZE - * ff_8::source_tile_conflicts::Y_SIZE - * ff_8::source_tile_conflicts::T_SIZE) + index < ff_8::SourceTileConflicts::X_SIZE + * ff_8::SourceTileConflicts::Y_SIZE + * ff_8::SourceTileConflicts::T_SIZE) << "Index out of range: t=" << +t << ", y=" << +y << ", x=" << +x << ", index=" << +index << ", size=" - << ff_8::source_tile_conflicts::X_SIZE - * ff_8::source_tile_conflicts::Y_SIZE - * ff_8::source_tile_conflicts::T_SIZE; + << ff_8::SourceTileConflicts::X_SIZE + * ff_8::SourceTileConflicts::Y_SIZE + * ff_8::SourceTileConflicts::T_SIZE; if (x != l.x || y != l.y || t != l.t) {