diff --git a/.gitignore b/.gitignore index c2a51f45..a2d21835 100644 --- a/.gitignore +++ b/.gitignore @@ -33,6 +33,7 @@ CMakeUserPresets.json *.swo *~ .DS_Store +src/ios/yaze_ios.xcodeproj/ # Test outputs test_screenshots/ diff --git a/CMakeLists.txt b/CMakeLists.txt index b30b9dd9..2c1bc45c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,7 @@ else() set(YAZE_VERSION_SUFFIX "-alpha") endif() -if(CMAKE_SYSTEM_NAME MATCHES "Darwin") +if(APPLE) project(yaze VERSION ${YAZE_VERSION} DESCRIPTION "Yet Another Zelda3 Editor" LANGUAGES CXX C OBJC OBJCXX) @@ -33,6 +33,13 @@ else() LANGUAGES CXX C) endif() +# Set language standards early so dependencies (e.g., Abseil) build with them. +set(CMAKE_CXX_STANDARD 23) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) +set(CMAKE_C_STANDARD 99) +set(CMAKE_C_STANDARD_REQUIRED ON) + # Include build options first include(cmake/options.cmake) @@ -64,6 +71,19 @@ set(CMAKE_WARN_DEPRECATED OFF CACHE BOOL "Suppress deprecation warnings") # Add cmake directory to module path set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) +# Platform detection +if(APPLE) + if(CMAKE_SYSTEM_NAME STREQUAL "iOS") + set(YAZE_PLATFORM_IOS ON) + else() + set(YAZE_PLATFORM_MACOS ON) + endif() +elseif(CMAKE_SYSTEM_NAME MATCHES "Linux") + set(YAZE_PLATFORM_LINUX ON) +elseif(CMAKE_SYSTEM_NAME MATCHES "Windows") + set(YAZE_PLATFORM_WINDOWS ON) +endif() + # Include utility functions include(cmake/utils.cmake) @@ -82,15 +102,6 @@ set(YAZE_TEST_ROM_PATH "" CACHE STRING "Legacy path to test ROM file (vanilla)") # Export compile commands for clangd/LSP set(CMAKE_EXPORT_COMPILE_COMMANDS ON) -# Platform detection -if(CMAKE_SYSTEM_NAME MATCHES "Darwin") - set(YAZE_PLATFORM_MACOS ON) -elseif(CMAKE_SYSTEM_NAME MATCHES "Linux") - set(YAZE_PLATFORM_LINUX ON) -elseif(CMAKE_SYSTEM_NAME MATCHES "Windows") - set(YAZE_PLATFORM_WINDOWS ON) -endif() - # Setup compiler flags and common interface target yaze_add_compiler_flags() @@ -169,7 +180,9 @@ if(CLANG_FORMAT) endif() # Packaging configuration -include(cmake/packaging/cpack.cmake) +if(NOT YAZE_PLATFORM_IOS) + include(cmake/packaging/cpack.cmake) +endif() add_custom_target(build_cleaner COMMAND ${CMAKE_COMMAND} -E echo "Running scripts/build_cleaner.py --dry-run" diff --git a/CMakePresets.json b/CMakePresets.json index 3b04d8ce..cea0b96b 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -231,6 +231,18 @@ "name": "mac-sdl3", "configurePreset": "mac-sdl3" }, + { + "displayName": "iOS Debug Build (device)", + "jobs": 12, + "name": "ios-debug", + "configurePreset": "ios-debug" + }, + { + "displayName": "iOS Release Build (device)", + "jobs": 12, + "name": "ios-release", + "configurePreset": "ios-release" + }, { "displayName": "Windows SDL3 Build", "configuration": "Debug", @@ -515,6 +527,60 @@ }, "description": "Base macOS preset with Homebrew toolchain visibility" }, + { + "name": "ios-base", + "generator": "Ninja", + "binaryDir": "${sourceDir}/build-ios", + "hidden": true, + "condition": { + "type": "equals", + "rhs": "Darwin", + "lhs": "${hostSystemName}" + }, + "cacheVariables": { + "CMAKE_SYSTEM_NAME": "iOS", + "CMAKE_OSX_SYSROOT": "iphoneos", + "CMAKE_OSX_ARCHITECTURES": "arm64", + "CMAKE_OSX_DEPLOYMENT_TARGET": "17.0", + "CMAKE_EXPORT_COMPILE_COMMANDS": "ON", + "YAZE_IOS_SDK": "iphoneos", + "YAZE_BUILD_GUI": "OFF", + "YAZE_BUILD_CLI": "OFF", + "YAZE_BUILD_Z3ED": "OFF", + "YAZE_BUILD_TESTS": "OFF", + "YAZE_BUILD_TOOLS": "OFF", + "YAZE_BUILD_LAB": "OFF", + "YAZE_BUILD_EMU": "ON", + "YAZE_BUILD_LIB": "ON", + "YAZE_ENABLE_GRPC": "OFF", + "YAZE_ENABLE_REMOTE_AUTOMATION": "OFF", + "YAZE_ENABLE_AI": "OFF", + "YAZE_ENABLE_AI_RUNTIME": "OFF", + "YAZE_ENABLE_HTTP_API": "OFF", + "YAZE_BUILD_AGENT_UI": "OFF", + "YAZE_ENABLE_AGENT_CLI": "OFF", + "YAZE_ENABLE_OPENCV": "OFF", + "YAZE_ENABLE_JSON": "ON", + "YAZE_USE_SYSTEM_DEPS": "OFF" + }, + "description": "Base iOS preset for building static libs" + }, + { + "inherits": "ios-base", + "name": "ios-debug", + "displayName": "iOS Debug (device)", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug" + } + }, + { + "inherits": "ios-base", + "name": "ios-release", + "displayName": "iOS Release (device)", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Release" + } + }, { "inherits": "base", "cacheVariables": { @@ -1332,4 +1398,4 @@ "description": "Optimized build for fast test iteration (~2-3x faster than Debug)" } ] -} \ No newline at end of file +} diff --git a/cmake/asar.cmake b/cmake/asar.cmake index 37d0574c..5dc2211d 100644 --- a/cmake/asar.cmake +++ b/cmake/asar.cmake @@ -44,11 +44,16 @@ if(TARGET asar-static) linux stricmp=strcasecmp ) - elseif(APPLE) + elseif(YAZE_PLATFORM_MACOS) target_compile_definitions(asar-static PRIVATE MACOS stricmp=strcasecmp ) + elseif(YAZE_PLATFORM_IOS) + target_compile_definitions(asar-static PRIVATE + YAZE_IOS + stricmp=strcasecmp + ) endif() # Add include directories diff --git a/cmake/dependencies/httplib.cmake b/cmake/dependencies/httplib.cmake index acc5fa2d..e7500e7a 100644 --- a/cmake/dependencies/httplib.cmake +++ b/cmake/dependencies/httplib.cmake @@ -10,6 +10,29 @@ include(cmake/dependencies.lock) message(STATUS "Setting up cpp-httplib ${HTTPLIB_VERSION}") +if(YAZE_PLATFORM_IOS) + CPMAddPackage( + NAME httplib + VERSION ${HTTPLIB_VERSION} + GITHUB_REPOSITORY yhirose/cpp-httplib + GIT_TAG v${HTTPLIB_VERSION} + DOWNLOAD_ONLY YES + ) + + if(NOT TARGET httplib) + add_library(httplib INTERFACE) + target_include_directories(httplib INTERFACE ${httplib_SOURCE_DIR}) + endif() + if(NOT TARGET httplib::httplib) + add_library(httplib::httplib ALIAS httplib) + endif() + + set(YAZE_HTTPLIB_TARGETS httplib::httplib) + set(YAZE_HTTPLIB_TARGETS httplib::httplib CACHE INTERNAL "cpp-httplib targets") + message(STATUS "cpp-httplib configured as header-only for iOS") + return() +endif() + set(_YAZE_USE_SYSTEM_HTTPLIB ${YAZE_USE_SYSTEM_DEPS}) # Try to use system packages first diff --git a/cmake/dependencies/imgui.cmake b/cmake/dependencies/imgui.cmake index ed278a22..cc15868e 100644 --- a/cmake/dependencies/imgui.cmake +++ b/cmake/dependencies/imgui.cmake @@ -21,6 +21,12 @@ else() message(STATUS "Using ImGui SDL2 backend") endif() +if(YAZE_PLATFORM_IOS) + list(APPEND IMGUI_BACKEND_SOURCES + ${IMGUI_DIR}/backends/imgui_impl_metal.mm + ) +endif() + # Create ImGui library with core files from bundled source add_library(ImGui STATIC ${IMGUI_DIR}/imgui.cpp diff --git a/cmake/dependencies/sdl2.cmake b/cmake/dependencies/sdl2.cmake index ed0aca13..61dc8b2c 100644 --- a/cmake/dependencies/sdl2.cmake +++ b/cmake/dependencies/sdl2.cmake @@ -74,7 +74,7 @@ if(NOT TARGET yaze_sdl2) target_link_libraries(yaze_sdl2 INTERFACE SDL2::SDL2-static) # For local Homebrew SDL2, also add include path explicitly # SDL headers are in the SDL2 subdirectory - if(APPLE AND EXISTS "/opt/homebrew/opt/sdl2/include/SDL2") + if(YAZE_PLATFORM_MACOS AND EXISTS "/opt/homebrew/opt/sdl2/include/SDL2") target_include_directories(yaze_sdl2 INTERFACE /opt/homebrew/opt/sdl2/include/SDL2) message(STATUS "Added Homebrew SDL2 include path: /opt/homebrew/opt/sdl2/include/SDL2") endif() @@ -94,7 +94,7 @@ if(WIN32) wbemuuid ) target_compile_definitions(yaze_sdl2 INTERFACE SDL_MAIN_HANDLED) -elseif(APPLE) +elseif(YAZE_PLATFORM_MACOS) target_link_libraries(yaze_sdl2 INTERFACE "-framework Cocoa" "-framework IOKit" @@ -102,6 +102,20 @@ elseif(APPLE) "-framework ForceFeedback" ) target_compile_definitions(yaze_sdl2 INTERFACE SDL_MAIN_HANDLED) +elseif(YAZE_PLATFORM_IOS) + target_link_libraries(yaze_sdl2 INTERFACE + "-framework UIKit" + "-framework Foundation" + "-framework CoreGraphics" + "-framework CoreVideo" + "-framework CoreMotion" + "-framework QuartzCore" + "-framework AVFoundation" + "-framework AudioToolbox" + "-framework Metal" + "-framework GameController" + ) + target_compile_definitions(yaze_sdl2 INTERFACE SDL_MAIN_HANDLED) elseif(UNIX) find_package(PkgConfig REQUIRED) pkg_check_modules(GTK3 REQUIRED gtk+-3.0) diff --git a/cmake/dependencies/sdl3.cmake b/cmake/dependencies/sdl3.cmake index d5b2cd77..9b0f63af 100644 --- a/cmake/dependencies/sdl3.cmake +++ b/cmake/dependencies/sdl3.cmake @@ -63,7 +63,7 @@ if(NOT TARGET yaze_sdl3) message(STATUS "Using SDL3::SDL3-static target") target_link_libraries(yaze_sdl3 INTERFACE SDL3::SDL3-static) # For local Homebrew SDL3, also add include path explicitly - if(APPLE AND EXISTS "/opt/homebrew/opt/sdl3/include/SDL3") + if(YAZE_PLATFORM_MACOS AND EXISTS "/opt/homebrew/opt/sdl3/include/SDL3") target_include_directories(yaze_sdl3 INTERFACE /opt/homebrew/opt/sdl3/include/SDL3) message(STATUS "Added Homebrew SDL3 include path: /opt/homebrew/opt/sdl3/include/SDL3") endif() @@ -83,7 +83,7 @@ if(WIN32) wbemuuid ) target_compile_definitions(yaze_sdl3 INTERFACE SDL_MAIN_HANDLED) -elseif(APPLE) +elseif(YAZE_PLATFORM_MACOS) target_link_libraries(yaze_sdl3 INTERFACE "-framework Cocoa" "-framework IOKit" @@ -93,6 +93,20 @@ elseif(APPLE) "-framework GameController" ) target_compile_definitions(yaze_sdl3 INTERFACE SDL_MAIN_HANDLED) +elseif(YAZE_PLATFORM_IOS) + target_link_libraries(yaze_sdl3 INTERFACE + "-framework UIKit" + "-framework Foundation" + "-framework CoreGraphics" + "-framework CoreVideo" + "-framework CoreMotion" + "-framework QuartzCore" + "-framework AVFoundation" + "-framework AudioToolbox" + "-framework Metal" + "-framework GameController" + ) + target_compile_definitions(yaze_sdl3 INTERFACE SDL_MAIN_HANDLED) elseif(UNIX) find_package(PkgConfig REQUIRED) pkg_check_modules(GTK3 REQUIRED gtk+-3.0) @@ -107,4 +121,4 @@ set(YAZE_SDL3_TARGETS yaze_sdl3) # Set a flag to indicate SDL3 is being used set(YAZE_SDL2_TARGETS ${YAZE_SDL3_TARGETS}) # For compatibility with existing code -message(STATUS "SDL3 setup complete - YAZE_SDL3_TARGETS = ${YAZE_SDL3_TARGETS}") \ No newline at end of file +message(STATUS "SDL3 setup complete - YAZE_SDL3_TARGETS = ${YAZE_SDL3_TARGETS}") diff --git a/cmake/utils.cmake b/cmake/utils.cmake index f50baa44..a30a4570 100644 --- a/cmake/utils.cmake +++ b/cmake/utils.cmake @@ -34,6 +34,8 @@ function(yaze_add_compiler_flags) target_compile_definitions(yaze_common INTERFACE linux stricmp=strcasecmp) elseif(YAZE_PLATFORM_MACOS) target_compile_definitions(yaze_common INTERFACE MACOS) + elseif(YAZE_PLATFORM_IOS) + target_compile_definitions(yaze_common INTERFACE YAZE_IOS) elseif(YAZE_PLATFORM_WINDOWS) target_compile_definitions(yaze_common INTERFACE WINDOWS) endif() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 27423284..00a9bf92 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -22,22 +22,25 @@ set( app/emu/debug/step_controller.cc app/emu/debug/symbol_provider.cc app/emu/debug/watchpoint_manager.cc - app/emu/emu.cc app/emu/emulator.cc app/emu/input/input_backend.cc app/emu/input/input_manager.cc app/emu/memory/dma.cc app/emu/memory/memory.cc app/emu/snes.cc - app/emu/ui/debugger_ui.cc - app/emu/ui/emulator_ui.cc - app/emu/ui/input_handler.cc app/emu/video/ppu.cc app/emu/render/render_context.cc app/emu/render/emulator_render_service.cc app/emu/render/save_state_manager.cc ) +set( + YAZE_EMU_GUI_SRC + app/emu/ui/debugger_ui.cc + app/emu/ui/emulator_ui.cc + app/emu/ui/input_handler.cc +) + # Add SDL3-specific backends when SDL3 is enabled if(YAZE_USE_SDL3) list(APPEND YAZE_APP_EMU_SRC app/emu/input/sdl3_input_backend.cc) @@ -153,3 +156,92 @@ if (YAZE_BUILD_LIB) ImGui ) endif() + +if(YAZE_PLATFORM_IOS) + if(NOT DEFINED YAZE_IOS_SDK) + set(YAZE_IOS_SDK "iphoneos" CACHE STRING "iOS SDK name for xcrun/libtool") + endif() + + set(YAZE_IOS_BUNDLE_OUTPUT "${CMAKE_BINARY_DIR}/ios/libyaze_ios_bundle.a") + set(YAZE_IOS_BUNDLE_TARGETS + yaze_app_core_lib + yaze_editor + yaze_editor_system_panels + yaze_editor_system_session + yaze_editor_system_shortcuts + yaze_emulator + yaze_emulator_ui + yaze_gui_core + yaze_canvas + yaze_gui_widgets + yaze_gui_automation + yaze_gui_app + yaze_net + yaze_gfx_types + yaze_gfx_backend + yaze_gfx_resource + yaze_gfx_render + yaze_gfx_debug + yaze_gfx_core + yaze_gfx_util + yaze_zelda3 + yaze_rom + yaze_core_lib + yaze_util + ImGui + ) + + if(TARGET ImPlot) + list(APPEND YAZE_IOS_BUNDLE_TARGETS ImPlot) + endif() + + if(TARGET yaze_test_support) + list(APPEND YAZE_IOS_BUNDLE_TARGETS yaze_test_support) + endif() + + if(TARGET asar-static) + list(APPEND YAZE_IOS_BUNDLE_TARGETS asar-static) + endif() + + if(TARGET SDL2-static) + list(APPEND YAZE_IOS_BUNDLE_TARGETS SDL2-static) + elseif(TARGET SDL2::SDL2-static) + list(APPEND YAZE_IOS_BUNDLE_TARGETS SDL2::SDL2-static) + elseif(TARGET SDL2::SDL2) + list(APPEND YAZE_IOS_BUNDLE_TARGETS SDL2::SDL2) + endif() + + list(REMOVE_DUPLICATES YAZE_IOS_BUNDLE_TARGETS) + + set(YAZE_IOS_BUNDLE_INPUTS "") + foreach(target IN LISTS YAZE_IOS_BUNDLE_TARGETS) + if(TARGET ${target}) + get_target_property(_target_type ${target} TYPE) + if(NOT _target_type STREQUAL "INTERFACE_LIBRARY") + list(APPEND YAZE_IOS_BUNDLE_INPUTS "$") + endif() + endif() + endforeach() + + file(GLOB_RECURSE YAZE_IOS_ABSL_LIBS CONFIGURE_DEPENDS + "${CMAKE_BINARY_DIR}/_deps/absl-build/absl/*/libabsl_*.a" + ) + if(YAZE_IOS_ABSL_LIBS) + list(REMOVE_DUPLICATES YAZE_IOS_ABSL_LIBS) + list(APPEND YAZE_IOS_BUNDLE_INPUTS ${YAZE_IOS_ABSL_LIBS}) + endif() + + list(REMOVE_DUPLICATES YAZE_IOS_BUNDLE_INPUTS) + + if(YAZE_IOS_BUNDLE_INPUTS) + add_custom_command( + OUTPUT ${YAZE_IOS_BUNDLE_OUTPUT} + COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/ios + COMMAND xcrun --sdk ${YAZE_IOS_SDK} libtool -static -o ${YAZE_IOS_BUNDLE_OUTPUT} ${YAZE_IOS_BUNDLE_INPUTS} + DEPENDS ${YAZE_IOS_BUNDLE_TARGETS} ${YAZE_IOS_ABSL_LIBS} + COMMAND_EXPAND_LISTS + COMMENT "Bundling yaze iOS static libraries" + ) + add_custom_target(yaze_ios_bundle ALL DEPENDS ${YAZE_IOS_BUNDLE_OUTPUT}) + endif() +endif() diff --git a/src/app/app.cmake b/src/app/app.cmake index 6b113626..b698c61f 100644 --- a/src/app/app.cmake +++ b/src/app/app.cmake @@ -32,7 +32,7 @@ if(EMSCRIPTEN) list(APPEND YAZE_APP_EXECUTABLE_SRC web/debug/yaze_debug_inspector.cc) endif() -if (APPLE) +if (YAZE_PLATFORM_MACOS) list(APPEND YAZE_APP_EXECUTABLE_SRC app/platform/app_delegate.mm) add_executable(yaze MACOSX_BUNDLE ${YAZE_APP_EXECUTABLE_SRC} ${YAZE_RESOURCE_FILES}) @@ -79,7 +79,9 @@ endif() target_link_libraries(yaze PRIVATE yaze_editor yaze_emulator + yaze_emulator_ui yaze_agent + yaze_grpc_support absl::failure_signal_handler absl::flags absl::flags_parse @@ -103,7 +105,7 @@ if(WIN32) endif() endif() -if(APPLE) +if(YAZE_PLATFORM_MACOS) target_link_libraries(yaze PUBLIC "-framework Cocoa") endif() diff --git a/src/app/app_core.cmake b/src/app/app_core.cmake index 804f1a27..46f12843 100644 --- a/src/app/app_core.cmake +++ b/src/app/app_core.cmake @@ -19,6 +19,13 @@ set( app/platform/window_backend_factory.cc ) +if(YAZE_PLATFORM_IOS) + list(APPEND YAZE_APP_CORE_SRC + app/application.cc + app/controller.cc + ) +endif() + # Window backend: SDL2 or SDL3 (mutually exclusive) if(YAZE_USE_SDL3) list(APPEND YAZE_APP_CORE_SRC @@ -91,6 +98,9 @@ if(APPLE) set(YAZE_APPLE_OBJCXX_SRC app/platform/file_dialog.mm app/platform/font_loader.mm + app/platform/ios/ios_host.mm + app/platform/ios/ios_platform_state.mm + app/platform/ios/ios_window_backend.mm ) add_library(yaze_app_objcxx OBJECT ${YAZE_APPLE_OBJCXX_SRC}) @@ -116,13 +126,19 @@ if(APPLE) endif() target_link_libraries(yaze_app_objcxx PUBLIC ${ABSL_TARGETS} yaze_util ${YAZE_SDL2_TARGETS}) - target_compile_definitions(yaze_app_objcxx PUBLIC MACOS) - - find_library(COCOA_LIBRARY Cocoa) - if(NOT COCOA_LIBRARY) - message(FATAL_ERROR "Cocoa not found") + if(YAZE_PLATFORM_MACOS) + target_compile_definitions(yaze_app_objcxx PUBLIC MACOS) + elseif(YAZE_PLATFORM_IOS) + target_compile_definitions(yaze_app_objcxx PUBLIC YAZE_IOS) + endif() + + if(YAZE_PLATFORM_MACOS) + find_library(COCOA_LIBRARY Cocoa) + if(NOT COCOA_LIBRARY) + message(FATAL_ERROR "Cocoa not found") + endif() + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -framework ServiceManagement -framework Foundation -framework Cocoa") endif() - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -framework ServiceManagement -framework Foundation -framework Cocoa") endif() # Create the application core library @@ -176,14 +192,14 @@ endif() # gRPC Services (Optional) if(YAZE_WITH_GRPC) target_compile_definitions(yaze_app_core_lib PRIVATE YAZE_WITH_JSON) - # Link to consolidated gRPC support library - target_link_libraries(yaze_app_core_lib PUBLIC yaze_grpc_support) + # Note: Linking to yaze_grpc_support is moved to executable level to avoid cycle: + # yaze_grpc_support -> yaze_emulator -> yaze_app_core_lib -> yaze_grpc_support message(STATUS " - gRPC ROM service + canvas automation enabled") endif() # Platform-specific libraries -if(APPLE) +if(YAZE_PLATFORM_MACOS) target_link_libraries(yaze_app_core_lib PUBLIC ${COCOA_LIBRARY}) endif() @@ -196,8 +212,10 @@ set_target_properties(yaze_app_core_lib PROPERTIES # Platform-specific compile definitions if(UNIX AND NOT APPLE) target_compile_definitions(yaze_app_core_lib PRIVATE linux stricmp=strcasecmp) -elseif(APPLE) +elseif(YAZE_PLATFORM_MACOS) target_compile_definitions(yaze_app_core_lib PRIVATE MACOS) +elseif(YAZE_PLATFORM_IOS) + target_compile_definitions(yaze_app_core_lib PRIVATE YAZE_IOS) elseif(WIN32) target_compile_definitions(yaze_app_core_lib PRIVATE WINDOWS) endif() diff --git a/src/app/editor/editor_library.cmake b/src/app/editor/editor_library.cmake index e4343cec..27915691 100644 --- a/src/app/editor/editor_library.cmake +++ b/src/app/editor/editor_library.cmake @@ -293,8 +293,10 @@ set_target_properties(yaze_editor PROPERTIES # Platform-specific compile definitions if(UNIX AND NOT APPLE) target_compile_definitions(yaze_editor PRIVATE linux stricmp=strcasecmp) -elseif(APPLE) +elseif(YAZE_PLATFORM_MACOS) target_compile_definitions(yaze_editor PRIVATE MACOS) +elseif(YAZE_PLATFORM_IOS) + target_compile_definitions(yaze_editor PRIVATE YAZE_IOS) elseif(WIN32) target_compile_definitions(yaze_editor PRIVATE WINDOWS) endif() diff --git a/src/app/emu/audio/audio_backend.cc b/src/app/emu/audio/audio_backend.cc index 60eddd4a..f56ea239 100644 --- a/src/app/emu/audio/audio_backend.cc +++ b/src/app/emu/audio/audio_backend.cc @@ -4,6 +4,10 @@ #include "app/platform/sdl_compat.h" +#if defined(__APPLE__) +#include +#endif + #include #include @@ -109,6 +113,9 @@ bool SDL2AudioBackend::Initialize(const AudioConfig& config) { // but the hardware actually runs at 48000Hz, causing pitch/speed issues. // SDL will handle internal resampling if the hardware doesn't support 48000Hz. int allowed_changes = SDL_AUDIO_ALLOW_FORMAT_CHANGE | SDL_AUDIO_ALLOW_CHANNELS_CHANGE; +#if defined(__APPLE__) && (TARGET_OS_IPHONE == 1 || TARGET_IPHONE_SIMULATOR == 1) + SDL_SetHint(SDL_HINT_AUDIO_CATEGORY, "ambient"); +#endif device_id_ = SDL_OpenAudioDevice(nullptr, 0, &want, &have, allowed_changes); if (device_id_ == 0) { diff --git a/src/app/emu/emu.cmake b/src/app/emu/emu.cmake index 85ff5ba1..23bba4ed 100644 --- a/src/app/emu/emu.cmake +++ b/src/app/emu/emu.cmake @@ -3,8 +3,8 @@ # because it's used by the main yaze app and test suites. # This file only controls the STANDALONE emulator executable. -if(YAZE_BUILD_EMU AND NOT YAZE_MINIMAL_BUILD) - if(APPLE) +if(YAZE_BUILD_EMU AND NOT YAZE_MINIMAL_BUILD AND NOT YAZE_PLATFORM_IOS) + if(YAZE_PLATFORM_MACOS) # Note: controller.cc is included here (not via library) because it depends on # yaze_editor and yaze_gui. Including it in yaze_app_core_lib would create a cycle: # yaze_agent -> yaze_app_core_lib -> yaze_editor -> yaze_agent @@ -25,6 +25,7 @@ if(YAZE_BUILD_EMU AND NOT YAZE_MINIMAL_BUILD) target_link_libraries(yaze_emu PRIVATE yaze_editor yaze_emulator + yaze_emulator_ui yaze_agent absl::flags absl::flags_parse @@ -68,6 +69,6 @@ if(YAZE_BUILD_EMU AND NOT YAZE_MINIMAL_BUILD) message(STATUS "✓ yaze_emu_test: Headless emulator test harness configured") message(STATUS "✓ yaze_emu: Standalone emulator executable configured") else() - message(STATUS "○ Standalone emulator builds disabled (YAZE_BUILD_EMU=OFF or YAZE_MINIMAL_BUILD=ON)") + message(STATUS "○ Standalone emulator builds disabled (YAZE_BUILD_EMU=OFF, YAZE_MINIMAL_BUILD=ON, or iOS)") message(STATUS " Note: yaze_emulator library still available for main app and tests") endif() diff --git a/src/app/emu/emu_library.cmake b/src/app/emu/emu_library.cmake index 82254faf..26dabbb7 100644 --- a/src/app/emu/emu_library.cmake +++ b/src/app/emu/emu_library.cmake @@ -36,7 +36,33 @@ endif() target_link_libraries(yaze_emulator PUBLIC yaze_util yaze_common + ${ABSL_TARGETS} + ${SDL_TARGETS} +) + +if(YAZE_ENABLE_JSON AND TARGET nlohmann_json::nlohmann_json) + target_link_libraries(yaze_emulator PUBLIC nlohmann_json::nlohmann_json) +endif() + +# Emulator UI library (depends on app core and GUI) +add_library(yaze_emulator_ui STATIC ${YAZE_EMU_GUI_SRC}) + +target_precompile_headers(yaze_emulator_ui PRIVATE + "$<$:${CMAKE_SOURCE_DIR}/src/yaze_pch.h>" +) + +target_include_directories(yaze_emulator_ui PUBLIC + ${CMAKE_SOURCE_DIR}/src + ${CMAKE_SOURCE_DIR}/src/app + ${CMAKE_SOURCE_DIR}/incl + ${SDL2_INCLUDE_DIR} + ${PROJECT_BINARY_DIR} +) + +target_link_libraries(yaze_emulator_ui PUBLIC + yaze_emulator yaze_app_core_lib + yaze_gui ${ABSL_TARGETS} ${SDL_TARGETS} ) @@ -47,11 +73,19 @@ set_target_properties(yaze_emulator PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" ) +set_target_properties(yaze_emulator_ui PROPERTIES + POSITION_INDEPENDENT_CODE ON + ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" + LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" +) + # Platform-specific compile definitions if(UNIX AND NOT APPLE) target_compile_definitions(yaze_emulator PRIVATE linux stricmp=strcasecmp) -elseif(APPLE) +elseif(YAZE_PLATFORM_MACOS) target_compile_definitions(yaze_emulator PRIVATE MACOS) +elseif(YAZE_PLATFORM_IOS) + target_compile_definitions(yaze_emulator PRIVATE YAZE_IOS) elseif(WIN32) target_compile_definitions(yaze_emulator PRIVATE WINDOWS) endif() diff --git a/src/app/emu/render/save_state_manager.cc b/src/app/emu/render/save_state_manager.cc index 1fd87221..e2235e5f 100644 --- a/src/app/emu/render/save_state_manager.cc +++ b/src/app/emu/render/save_state_manager.cc @@ -11,6 +11,7 @@ #include "app/emu/snes.h" #include "rom/rom.h" +#include "util/platform_paths.h" namespace { @@ -70,9 +71,11 @@ absl::Status SaveStateManager::Initialize() { rom_checksum_ = CalculateRomChecksum(); printf("[StateManager] ROM checksum: 0x%08X\n", rom_checksum_); - // Use ~/.yaze/states/ directory for state files - if (const char* home = std::getenv("HOME")) { - state_directory_ = std::string(home) + "/.yaze/states"; + // Use app data directory for state files (sandbox-safe on iOS). + auto state_dir_status = + yaze::util::PlatformPaths::GetAppDataSubdirectory("states"); + if (state_dir_status.ok()) { + state_directory_ = state_dir_status->string(); } else { state_directory_ = "./states"; } diff --git a/src/app/emu/ui/emulator_ui.cc b/src/app/emu/ui/emulator_ui.cc index 53c318bb..c414146c 100644 --- a/src/app/emu/ui/emulator_ui.cc +++ b/src/app/emu/ui/emulator_ui.cc @@ -116,7 +116,8 @@ void RenderNavBar(Emulator* emu) { // Load ROM button if (ImGui::Button(ICON_MD_FOLDER_OPEN " Load ROM", ImVec2(110, kButtonHeight))) { - std::string rom_path = util::FileDialogWrapper::ShowOpenFileDialog(); + std::string rom_path = util::FileDialogWrapper::ShowOpenFileDialog( + util::MakeRomFileDialogOptions(false)); if (!rom_path.empty()) { // Check if it's a valid ROM file extension std::string ext = util::GetFileExtension(rom_path); diff --git a/src/app/gfx/backend/metal_renderer.h b/src/app/gfx/backend/metal_renderer.h new file mode 100644 index 00000000..5fada8f3 --- /dev/null +++ b/src/app/gfx/backend/metal_renderer.h @@ -0,0 +1,42 @@ +#pragma once + +#include "app/gfx/backend/irenderer.h" + +namespace yaze { +namespace gfx { + +class MetalRenderer final : public IRenderer { + public: + MetalRenderer() = default; + ~MetalRenderer() override; + + bool Initialize(SDL_Window* window) override; + void Shutdown() override; + + TextureHandle CreateTexture(int width, int height) override; + TextureHandle CreateTextureWithFormat(int width, int height, uint32_t format, + int access) override; + void UpdateTexture(TextureHandle texture, const Bitmap& bitmap) override; + void DestroyTexture(TextureHandle texture) override; + bool LockTexture(TextureHandle texture, SDL_Rect* rect, void** pixels, + int* pitch) override; + void UnlockTexture(TextureHandle texture) override; + + void Clear() override; + void Present() override; + void RenderCopy(TextureHandle texture, const SDL_Rect* srcrect, + const SDL_Rect* dstrect) override; + void SetRenderTarget(TextureHandle texture) override; + void SetDrawColor(SDL_Color color) override; + void* GetBackendRenderer() override; + + void SetMetalView(void* view); + + private: + void* metal_view_ = nullptr; + void* command_queue_ = nullptr; + TextureHandle render_target_ = nullptr; +}; + +} // namespace gfx +} // namespace yaze diff --git a/src/app/gfx/backend/metal_renderer.mm b/src/app/gfx/backend/metal_renderer.mm new file mode 100644 index 00000000..286c83d7 --- /dev/null +++ b/src/app/gfx/backend/metal_renderer.mm @@ -0,0 +1,243 @@ +#include "app/gfx/backend/metal_renderer.h" + +#if defined(__APPLE__) +#include +#import +#endif + +#if defined(__APPLE__) && (TARGET_OS_IPHONE == 1 || TARGET_IPHONE_SIMULATOR == 1) +#import +#import +#endif + +#include "app/gfx/core/bitmap.h" +#include "app/platform/sdl_compat.h" +#include "util/log.h" +#include "util/sdl_deleter.h" +#include + +namespace yaze { +namespace gfx { + +MetalRenderer::~MetalRenderer() { + Shutdown(); +} + +bool MetalRenderer::Initialize(SDL_Window* window) { + (void)window; +#if defined(__APPLE__) && (TARGET_OS_IPHONE == 1 || TARGET_IPHONE_SIMULATOR == 1) + if (!metal_view_) { + LOG_WARN("MetalRenderer", "Metal view not attached"); + return false; + } + auto* view = static_cast(metal_view_); + id device = view.device; + if (!device) { + device = MTLCreateSystemDefaultDevice(); + view.device = device; + } + if (!device) { + LOG_WARN("MetalRenderer", "Failed to create Metal device"); + return false; + } + if (!command_queue_) { + id queue = [device newCommandQueue]; + command_queue_ = (__bridge_retained void*)queue; + } + return true; +#else + return false; +#endif +} + +void MetalRenderer::Shutdown() { + if (command_queue_) { + CFRelease(command_queue_); + command_queue_ = nullptr; + } + render_target_ = nullptr; +} + +TextureHandle MetalRenderer::CreateTexture(int width, int height) { +#if defined(__APPLE__) && (TARGET_OS_IPHONE == 1 || TARGET_IPHONE_SIMULATOR == 1) + if (!metal_view_) { + return nullptr; + } + + auto* view = static_cast(metal_view_); + id device = view.device; + if (!device) { + device = MTLCreateSystemDefaultDevice(); + view.device = device; + } + if (!device) { + return nullptr; + } + + MTLTextureDescriptor* descriptor = + [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatRGBA8Unorm + width:width + height:height + mipmapped:NO]; + descriptor.usage = MTLTextureUsageShaderRead | MTLTextureUsageRenderTarget; + descriptor.storageMode = MTLStorageModeShared; + + id texture = [device newTextureWithDescriptor:descriptor]; + return texture ? (__bridge_retained void*)texture : nullptr; +#else + (void)width; + (void)height; + return nullptr; +#endif +} + +TextureHandle MetalRenderer::CreateTextureWithFormat(int width, int height, + uint32_t format, + int access) { + (void)format; + (void)access; + return CreateTexture(width, height); +} + +void MetalRenderer::UpdateTexture(TextureHandle texture, const Bitmap& bitmap) { +#if defined(__APPLE__) && (TARGET_OS_IPHONE == 1 || TARGET_IPHONE_SIMULATOR == 1) + if (!texture) { + return; + } + + SDL_Surface* surface = bitmap.surface(); + if (!surface || !surface->pixels || surface->w <= 0 || surface->h <= 0) { + return; + } + + auto converted_surface = + std::unique_ptr( + platform::ConvertSurfaceFormat(surface, SDL_PIXELFORMAT_RGBA8888)); + if (!converted_surface || !converted_surface->pixels) { + return; + } + + id metal_texture = (__bridge id)texture; + MTLRegion region = { + {0, 0, 0}, + {static_cast(converted_surface->w), + static_cast(converted_surface->h), + 1}}; + [metal_texture replaceRegion:region + mipmapLevel:0 + withBytes:converted_surface->pixels + bytesPerRow:converted_surface->pitch]; +#else + (void)texture; + (void)bitmap; +#endif +} + +void MetalRenderer::DestroyTexture(TextureHandle texture) { + if (!texture) { + return; + } + if (render_target_ == texture) { + render_target_ = nullptr; + } +#if defined(__APPLE__) && (TARGET_OS_IPHONE == 1 || TARGET_IPHONE_SIMULATOR == 1) + CFRelease(texture); +#else + (void)texture; +#endif +} + +bool MetalRenderer::LockTexture(TextureHandle texture, SDL_Rect* rect, + void** pixels, int* pitch) { + (void)texture; + (void)rect; + (void)pixels; + (void)pitch; + return false; +} + +void MetalRenderer::UnlockTexture(TextureHandle texture) { + (void)texture; +} + +void MetalRenderer::Clear() { +} + +void MetalRenderer::Present() { +} + +void MetalRenderer::RenderCopy(TextureHandle texture, const SDL_Rect* srcrect, + const SDL_Rect* dstrect) { +#if defined(__APPLE__) && (TARGET_OS_IPHONE == 1 || TARGET_IPHONE_SIMULATOR == 1) + if (!texture || !render_target_ || !command_queue_) { + return; + } + + id source = (__bridge id)texture; + id dest = (__bridge id)render_target_; + + int src_x = srcrect ? srcrect->x : 0; + int src_y = srcrect ? srcrect->y : 0; + int src_w = srcrect ? srcrect->w : static_cast(source.width); + int src_h = srcrect ? srcrect->h : static_cast(source.height); + + int dst_x = dstrect ? dstrect->x : 0; + int dst_y = dstrect ? dstrect->y : 0; + + src_w = std::min(src_w, static_cast(source.width) - src_x); + src_h = std::min(src_h, static_cast(source.height) - src_y); + + if (src_w <= 0 || src_h <= 0) { + return; + } + + MTLOrigin src_origin = {static_cast(src_x), + static_cast(src_y), + 0}; + MTLSize src_size = {static_cast(src_w), + static_cast(src_h), + 1}; + MTLOrigin dst_origin = {static_cast(dst_x), + static_cast(dst_y), + 0}; + + id queue = (__bridge id)command_queue_; + id command_buffer = [queue commandBuffer]; + id blit = [command_buffer blitCommandEncoder]; + [blit copyFromTexture:source + sourceSlice:0 + sourceLevel:0 + sourceOrigin:src_origin + sourceSize:src_size + toTexture:dest + destinationSlice:0 + destinationLevel:0 + destinationOrigin:dst_origin]; + [blit endEncoding]; + [command_buffer commit]; + [command_buffer waitUntilCompleted]; +#else + (void)texture; + (void)srcrect; + (void)dstrect; +#endif +} + +void MetalRenderer::SetRenderTarget(TextureHandle texture) { + render_target_ = texture; +} + +void MetalRenderer::SetDrawColor(SDL_Color color) { + (void)color; +} + +void* MetalRenderer::GetBackendRenderer() { + return command_queue_; +} + +void MetalRenderer::SetMetalView(void* view) { + metal_view_ = view; +} + +} // namespace gfx +} // namespace yaze diff --git a/src/app/gfx/backend/renderer_factory.h b/src/app/gfx/backend/renderer_factory.h index 9673bab1..5be0757f 100644 --- a/src/app/gfx/backend/renderer_factory.h +++ b/src/app/gfx/backend/renderer_factory.h @@ -3,6 +3,10 @@ #include +#if defined(__APPLE__) +#include +#endif + #include "app/gfx/backend/irenderer.h" #include "app/gfx/backend/sdl2_renderer.h" @@ -10,6 +14,10 @@ #include "app/gfx/backend/sdl3_renderer.h" #endif +#if defined(__APPLE__) +#include "app/gfx/backend/metal_renderer.h" +#endif + namespace yaze { namespace gfx { @@ -20,6 +28,7 @@ namespace gfx { enum class RendererBackendType { SDL2, ///< SDL2 renderer backend SDL3, ///< SDL3 renderer backend + Metal, ///< Metal renderer backend (Apple platforms) kDefault, ///< Use the default backend based on build configuration kAutoDetect ///< Automatically select the best available backend }; @@ -71,11 +80,20 @@ class RendererFactory { return std::make_unique(); #endif + case RendererBackendType::Metal: +#if defined(__APPLE__) + return std::make_unique(); +#else + return nullptr; +#endif + case RendererBackendType::kDefault: case RendererBackendType::kAutoDetect: default: // Use the default backend based on build configuration -#ifdef YAZE_USE_SDL3 +#if defined(__APPLE__) && (TARGET_OS_IPHONE == 1 || TARGET_IPHONE_SIMULATOR == 1) + return std::make_unique(); +#elif defined(YAZE_USE_SDL3) return std::make_unique(); #else return std::make_unique(); @@ -102,6 +120,13 @@ class RendererFactory { return false; #endif + case RendererBackendType::Metal: +#if defined(__APPLE__) + return true; +#else + return false; +#endif + case RendererBackendType::kDefault: case RendererBackendType::kAutoDetect: // Default/auto-detect is always available @@ -124,6 +149,8 @@ class RendererFactory { return "SDL2"; case RendererBackendType::SDL3: return "SDL3"; + case RendererBackendType::Metal: + return "Metal"; case RendererBackendType::kDefault: return "Default"; case RendererBackendType::kAutoDetect: @@ -139,7 +166,9 @@ class RendererFactory { * @return The default backend type based on build configuration. */ static RendererBackendType GetDefaultBackendType() { -#ifdef YAZE_USE_SDL3 +#if defined(__APPLE__) && (TARGET_OS_IPHONE == 1 || TARGET_IPHONE_SIMULATOR == 1) + return RendererBackendType::Metal; +#elif defined(YAZE_USE_SDL3) return RendererBackendType::SDL3; #else return RendererBackendType::SDL2; diff --git a/src/app/gfx/gfx_library.cmake b/src/app/gfx/gfx_library.cmake index d8aa425e..f4df5b16 100644 --- a/src/app/gfx/gfx_library.cmake +++ b/src/app/gfx/gfx_library.cmake @@ -34,8 +34,10 @@ macro(configure_gfx_library name) ) if(UNIX AND NOT APPLE) target_compile_definitions(${name} PRIVATE linux stricmp=strcasecmp) - elseif(APPLE) + elseif(YAZE_PLATFORM_MACOS) target_compile_definitions(${name} PRIVATE MACOS) + elseif(YAZE_PLATFORM_IOS) + target_compile_definitions(${name} PRIVATE YAZE_IOS) elseif(WIN32) target_compile_definitions(${name} PRIVATE WINDOWS) endif() @@ -65,6 +67,12 @@ else() ) endif() +if(APPLE) + list(APPEND GFX_BACKEND_SRC + app/gfx/backend/metal_renderer.mm + ) +endif() + # build_cleaner:auto-maintain set(GFX_RESOURCE_SRC app/gfx/resource/memory_pool.cc diff --git a/src/app/gui/gui_library.cmake b/src/app/gui/gui_library.cmake index ced6cef7..299631f1 100644 --- a/src/app/gui/gui_library.cmake +++ b/src/app/gui/gui_library.cmake @@ -128,8 +128,10 @@ foreach(LIB ${GUI_SUB_LIBS}) ) if(UNIX AND NOT APPLE) target_compile_definitions(${LIB} PRIVATE linux stricmp=strcasecmp) - elseif(APPLE) + elseif(YAZE_PLATFORM_MACOS) target_compile_definitions(${LIB} PRIVATE MACOS) + elseif(YAZE_PLATFORM_IOS) + target_compile_definitions(${LIB} PRIVATE YAZE_IOS) elseif(WIN32) target_compile_definitions(${LIB} PRIVATE WINDOWS) endif() diff --git a/src/app/platform/asset_loader.cc b/src/app/platform/asset_loader.cc index 1dc9d832..bac91b0a 100644 --- a/src/app/platform/asset_loader.cc +++ b/src/app/platform/asset_loader.cc @@ -3,6 +3,10 @@ #include #include +#ifdef __APPLE__ +#include +#endif + #include "absl/strings/str_format.h" #include "util/file_util.h" @@ -16,6 +20,12 @@ std::vector AssetLoader::GetSearchPaths( // macOS bundle resource paths std::string bundle_root = yaze::util::GetBundleResourcePath(); +#if TARGET_OS_IOS == 1 + // iOS app bundle resources live at the root. + search_paths.push_back(std::filesystem::path(bundle_root) / "assets" / + relative_path); + search_paths.push_back(std::filesystem::path(bundle_root) / relative_path); +#else // Try Contents/Resources first (standard bundle location) search_paths.push_back(std::filesystem::path(bundle_root) / "Contents" / "Resources" / relative_path); @@ -29,6 +39,7 @@ std::vector AssetLoader::GetSearchPaths( ".." / "assets" / relative_path); search_paths.push_back(std::filesystem::path(bundle_root) / ".." / ".." / ".." / ".." / "assets" / relative_path); +#endif #endif // Standard relative paths (works for all platforms) diff --git a/src/app/platform/file_dialog.mm b/src/app/platform/file_dialog.mm index bf7c7f17..e02d173b 100644 --- a/src/app/platform/file_dialog.mm +++ b/src/app/platform/file_dialog.mm @@ -1,10 +1,13 @@ #include "util/file_util.h" +#include #include +#include #include #include #include "core/features.h" +#include "util/platform_paths.h" #if defined(YAZE_ENABLE_NFD) && YAZE_ENABLE_NFD #include @@ -19,45 +22,276 @@ #if TARGET_IPHONE_SIMULATOR == 1 || TARGET_OS_IPHONE == 1 /* iOS in Xcode simulator */ +#import #import #import #include "app/platform/app_delegate.h" -namespace { -static std::string selectedFile; +@interface AppDelegate : UIResponder +@end -void ShowOpenFileDialogImpl(void (^completionHandler)(std::string)) { - AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate; - [appDelegate PresentDocumentPickerWithCompletionHandler:^(NSString *filePath) { - selectedFile = std::string([filePath UTF8String]); - completionHandler(selectedFile); - }]; +@interface AppDelegate (FileDialog) +- (void)PresentDocumentPickerWithCompletionHandler: + (void (^)(NSString *selectedFile))completionHandler + allowedTypes:(NSArray *)allowedTypes; +@end + +namespace { +std::string TrimCopy(const std::string& input) { + const auto start = input.find_first_not_of(" \t\n\r"); + if (start == std::string::npos) { + return ""; + } + const auto end = input.find_last_not_of(" \t\n\r"); + return input.substr(start, end - start + 1); } -std::string ShowOpenFileDialogSync() { - __block std::string result; +std::vector SplitFilterSpec(const std::string& spec) { + std::vector tokens; + std::string current; + for (char ch : spec) { + if (ch == ',') { + std::string trimmed = TrimCopy(current); + if (!trimmed.empty() && trimmed[0] == '.') { + trimmed.erase(0, 1); + } + if (!trimmed.empty()) { + tokens.push_back(trimmed); + } + current.clear(); + } else { + current.push_back(ch); + } + } + std::string trimmed = TrimCopy(current); + if (!trimmed.empty() && trimmed[0] == '.') { + trimmed.erase(0, 1); + } + if (!trimmed.empty()) { + tokens.push_back(trimmed); + } + return tokens; +} - ShowOpenFileDialogImpl(^(std::string filePath) { - result = filePath; - }); +NSArray* BuildAllowedTypes(const yaze::util::FileDialogOptions& options) { + if (options.filters.empty()) { + return @[ UTTypeData ]; + } + + bool allow_all = false; + NSMutableArray* types = [NSMutableArray array]; + + for (const auto& filter : options.filters) { + const std::string spec = TrimCopy(filter.spec); + if (spec.empty() || spec == "*") { + allow_all = true; + continue; + } + + for (const auto& token : SplitFilterSpec(spec)) { + if (token == "*") { + allow_all = true; + continue; + } + + NSString* ext = [NSString stringWithUTF8String:token.c_str()]; + UTType* type = [UTType typeWithFilenameExtension:ext]; + if (!type) { + NSString* identifier = [NSString stringWithUTF8String:token.c_str()]; + type = [UTType typeWithIdentifier:identifier]; + } + if (type) { + [types addObject:type]; + } + } + } + + if (allow_all || [types count] == 0) { + return @[ UTTypeData ]; + } + + return types; +} + +std::filesystem::path ResolveDocumentsPath() { + auto docs_result = yaze::util::PlatformPaths::GetUserDocumentsDirectory(); + if (docs_result.ok()) { + return *docs_result; + } + auto temp_result = yaze::util::PlatformPaths::GetTempDirectory(); + if (temp_result.ok()) { + return *temp_result; + } + std::error_code ec; + auto cwd = std::filesystem::current_path(ec); + if (!ec) { + return cwd; + } + return std::filesystem::path("."); +} + +std::string NormalizeExtension(const std::string& ext) { + if (ext.empty()) { + return ""; + } + if (ext.front() == '.') { + return ext; + } + return "." + ext; +} + +std::string BuildSaveFilename(const std::string& default_name, + const std::string& default_extension) { + std::string name = default_name.empty() ? "yaze_output" : default_name; + const std::string normalized_ext = NormalizeExtension(default_extension); + if (!normalized_ext.empty()) { + auto dot_pos = name.find_last_of('.'); + if (dot_pos == std::string::npos || dot_pos == 0) { + name += normalized_ext; + } + } + return name; +} + +void ShowOpenFileDialogImpl(NSArray* allowed_types, + void (^completionHandler)(std::string)) { + AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate; + if (!appDelegate) { + completionHandler(""); + return; + } + [appDelegate PresentDocumentPickerWithCompletionHandler:^(NSString *filePath) { + completionHandler(std::string([filePath UTF8String])); + } + allowedTypes:allowed_types]; +} + +std::string ShowOpenFileDialogSync( + const yaze::util::FileDialogOptions& options) { + __block std::string result; + __block bool done = false; + NSArray* allowed_types = BuildAllowedTypes(options); + + auto present_picker = ^{ + ShowOpenFileDialogImpl(allowed_types, ^(std::string filePath) { + result = filePath; + done = true; + }); + }; + + if ([NSThread isMainThread]) { + present_picker(); + // Run a nested loop to keep UI responsive while waiting on selection. + while (!done) { + [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode + beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.01]]; + } + } else { + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + dispatch_async(dispatch_get_main_queue(), ^{ + ShowOpenFileDialogImpl(allowed_types, ^(std::string filePath) { + result = filePath; + dispatch_semaphore_signal(semaphore); + }); + }); + dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); + } return result; } } // namespace -std::string yaze::util::FileDialogWrapper::ShowOpenFileDialog() { return ShowOpenFileDialogSync(); } +std::string yaze::util::FileDialogWrapper::ShowOpenFileDialog( + const FileDialogOptions& options) { + return ShowOpenFileDialogSync(options); +} -std::string yaze::util::FileDialogWrapper::ShowOpenFolderDialog() { return ""; } +std::string yaze::util::FileDialogWrapper::ShowOpenFileDialog() { + return ShowOpenFileDialog(FileDialogOptions{}); +} + +std::string yaze::util::FileDialogWrapper::ShowOpenFileDialogNFD() { + return ShowOpenFileDialog(FileDialogOptions{}); +} + +std::string yaze::util::FileDialogWrapper::ShowOpenFileDialogBespoke() { + return ShowOpenFileDialog(FileDialogOptions{}); +} + +void yaze::util::FileDialogWrapper::ShowOpenFileDialogAsync( + const FileDialogOptions& options, + std::function callback) { + if (!callback) { + return; + } + NSArray* allowed_types = BuildAllowedTypes(options); + auto callback_ptr = + std::make_shared>( + std::move(callback)); + + auto present_picker = ^{ + ShowOpenFileDialogImpl(allowed_types, ^(std::string filePath) { + (*callback_ptr)(filePath); + }); + }; + + if ([NSThread isMainThread]) { + present_picker(); + } else { + dispatch_async(dispatch_get_main_queue(), present_picker); + } +} + +std::string yaze::util::FileDialogWrapper::ShowOpenFolderDialog() { + return ResolveDocumentsPath().string(); +} + +std::string yaze::util::FileDialogWrapper::ShowSaveFileDialog( + const std::string& default_name, const std::string& default_extension) { + const auto base_dir = ResolveDocumentsPath(); + const std::string filename = BuildSaveFilename(default_name, default_extension); + return (base_dir / filename).string(); +} + +std::string yaze::util::FileDialogWrapper::ShowSaveFileDialogNFD( + const std::string& default_name, const std::string& default_extension) { + return ShowSaveFileDialog(default_name, default_extension); +} + +std::string yaze::util::FileDialogWrapper::ShowSaveFileDialogBespoke( + const std::string& default_name, const std::string& default_extension) { + return ShowSaveFileDialog(default_name, default_extension); +} std::vector yaze::util::FileDialogWrapper::GetFilesInFolder( const std::string &folder) { - return {}; + std::vector files; + std::error_code ec; + for (const auto& entry : std::filesystem::directory_iterator(folder, ec)) { + if (ec) { + break; + } + if (entry.is_regular_file()) { + files.push_back(entry.path().string()); + } + } + return files; } std::vector yaze::util::FileDialogWrapper::GetSubdirectoriesInFolder( const std::string &folder) { - return {}; + std::vector directories; + std::error_code ec; + for (const auto& entry : std::filesystem::directory_iterator(folder, ec)) { + if (ec) { + break; + } + if (entry.is_directory()) { + directories.push_back(entry.path().string()); + } + } + return directories; } std::string yaze::util::GetBundleResourcePath() { @@ -73,11 +307,91 @@ std::string yaze::util::GetBundleResourcePath() { #import #import -std::string yaze::util::FileDialogWrapper::ShowOpenFileDialogBespoke() { +namespace { +std::string TrimCopy(const std::string& input) { + const auto start = input.find_first_not_of(" \t\n\r"); + if (start == std::string::npos) { + return ""; + } + const auto end = input.find_last_not_of(" \t\n\r"); + return input.substr(start, end - start + 1); +} + +std::vector SplitFilterSpec(const std::string& spec) { + std::vector tokens; + std::string current; + for (char ch : spec) { + if (ch == ',') { + std::string trimmed = TrimCopy(current); + if (!trimmed.empty() && trimmed[0] == '.') { + trimmed.erase(0, 1); + } + if (!trimmed.empty()) { + tokens.push_back(trimmed); + } + current.clear(); + } else { + current.push_back(ch); + } + } + std::string trimmed = TrimCopy(current); + if (!trimmed.empty() && trimmed[0] == '.') { + trimmed.erase(0, 1); + } + if (!trimmed.empty()) { + tokens.push_back(trimmed); + } + return tokens; +} + +std::vector CollectExtensions( + const yaze::util::FileDialogOptions& options, bool* allow_all) { + std::vector extensions; + if (!allow_all) { + return extensions; + } + *allow_all = false; + + for (const auto& filter : options.filters) { + const std::string spec = TrimCopy(filter.spec); + if (spec.empty() || spec == "*") { + *allow_all = true; + continue; + } + + for (const auto& token : SplitFilterSpec(spec)) { + if (token == "*") { + *allow_all = true; + } else { + extensions.push_back(token); + } + } + } + + return extensions; +} + +std::string ShowOpenFileDialogBespokeWithOptions( + const yaze::util::FileDialogOptions& options) { NSOpenPanel* openPanel = [NSOpenPanel openPanel]; [openPanel setCanChooseFiles:YES]; [openPanel setCanChooseDirectories:NO]; [openPanel setAllowsMultipleSelection:NO]; + + bool allow_all = false; + std::vector extensions = CollectExtensions(options, &allow_all); + if (allow_all || extensions.empty()) { + [openPanel setAllowedFileTypes:nil]; + } else { + NSMutableArray* allowed_types = [NSMutableArray array]; + for (const auto& extension : extensions) { + NSString* ext = [NSString stringWithUTF8String:extension.c_str()]; + if (ext) { + [allowed_types addObject:ext]; + } + } + [openPanel setAllowedFileTypes:allowed_types]; + } if ([openPanel runModal] == NSModalResponseOK) { NSURL* url = [[openPanel URLs] objectAtIndex:0]; @@ -88,6 +402,70 @@ std::string yaze::util::FileDialogWrapper::ShowOpenFileDialogBespoke() { return ""; } +std::string ShowOpenFileDialogNFDWithOptions( + const yaze::util::FileDialogOptions& options) { +#if defined(YAZE_ENABLE_NFD) && YAZE_ENABLE_NFD + NFD_Init(); + nfdu8char_t* out_path = NULL; + const nfdu8filteritem_t* filter_list = nullptr; + size_t filter_count = 0; + std::vector filter_items; + std::vector filter_names; + std::vector filter_specs; + + if (!options.filters.empty()) { + filter_items.reserve(options.filters.size()); + filter_names.reserve(options.filters.size()); + filter_specs.reserve(options.filters.size()); + + for (const auto& filter : options.filters) { + std::string label = filter.label.empty() ? "Files" : filter.label; + std::string spec = filter.spec.empty() ? "*" : filter.spec; + filter_names.push_back(label); + filter_specs.push_back(spec); + filter_items.push_back( + {filter_names.back().c_str(), filter_specs.back().c_str()}); + } + + filter_list = filter_items.data(); + filter_count = filter_items.size(); + } + + nfdopendialogu8args_t args = {0}; + args.filterList = filter_list; + args.filterCount = filter_count; + + nfdresult_t result = NFD_OpenDialogU8_With(&out_path, &args); + if (result == NFD_OKAY) { + std::string file_path(out_path); + NFD_FreePath(out_path); + NFD_Quit(); + return file_path; + } else if (result == NFD_CANCEL) { + NFD_Quit(); + return ""; + } + NFD_Quit(); + return ""; +#else + return ShowOpenFileDialogBespokeWithOptions(options); +#endif +} +} // namespace + +std::string yaze::util::FileDialogWrapper::ShowOpenFileDialogBespoke() { + return ShowOpenFileDialogBespokeWithOptions(FileDialogOptions{}); +} + +void yaze::util::FileDialogWrapper::ShowOpenFileDialogAsync( + const FileDialogOptions& options, + std::function callback) { + if (!callback) { + return; + } + callback(ShowOpenFileDialog(options)); +} + std::string yaze::util::FileDialogWrapper::ShowSaveFileDialogBespoke(const std::string& default_name, const std::string& default_extension) { NSSavePanel* savePanel = [NSSavePanel savePanel]; @@ -111,12 +489,16 @@ std::string yaze::util::FileDialogWrapper::ShowSaveFileDialogBespoke(const std:: } // Global feature flag-based dispatch methods -std::string yaze::util::FileDialogWrapper::ShowOpenFileDialog() { +std::string yaze::util::FileDialogWrapper::ShowOpenFileDialog( + const FileDialogOptions& options) { if (core::FeatureFlags::get().kUseNativeFileDialog) { - return ShowOpenFileDialogNFD(); - } else { - return ShowOpenFileDialogBespoke(); + return ShowOpenFileDialogNFDWithOptions(options); } + return ShowOpenFileDialogBespokeWithOptions(options); +} + +std::string yaze::util::FileDialogWrapper::ShowOpenFileDialog() { + return ShowOpenFileDialog(FileDialogOptions{}); } std::string yaze::util::FileDialogWrapper::ShowOpenFolderDialog() { @@ -138,30 +520,7 @@ std::string yaze::util::FileDialogWrapper::ShowSaveFileDialog(const std::string& // NFD implementation for macOS (fallback to bespoke if NFD not available) std::string yaze::util::FileDialogWrapper::ShowOpenFileDialogNFD() { -#if defined(YAZE_ENABLE_NFD) && YAZE_ENABLE_NFD - NFD_Init(); - nfdu8char_t *out_path = NULL; - nfdu8filteritem_t filters[1] = {{"Rom File", "sfc,smc"}}; - nfdopendialogu8args_t args = {0}; - args.filterList = filters; - args.filterCount = 1; - - nfdresult_t result = NFD_OpenDialogU8_With(&out_path, &args); - if (result == NFD_OKAY) { - std::string file_path(out_path); - NFD_FreePath(out_path); - NFD_Quit(); - return file_path; - } else if (result == NFD_CANCEL) { - NFD_Quit(); - return ""; - } - NFD_Quit(); - return ""; -#else - // NFD not compiled in, use bespoke - return ShowOpenFileDialogBespoke(); -#endif + return ShowOpenFileDialogNFDWithOptions(FileDialogOptions{}); } std::string yaze::util::FileDialogWrapper::ShowOpenFolderDialogNFD() { @@ -300,4 +659,4 @@ std::string yaze::util::GetBundleResourcePath() { // Unsupported platform #endif // TARGET_OS_MAC -#endif // __APPLE__ && __MACH__ \ No newline at end of file +#endif // __APPLE__ && __MACH__ diff --git a/src/app/platform/file_dialog_nfd.cc b/src/app/platform/file_dialog_nfd.cc index 8b4fe1db..5c137a3a 100644 --- a/src/app/platform/file_dialog_nfd.cc +++ b/src/app/platform/file_dialog_nfd.cc @@ -11,11 +11,35 @@ namespace yaze { namespace util { -std::string FileDialogWrapper::ShowOpenFileDialog() { +std::string FileDialogWrapper::ShowOpenFileDialog( + const FileDialogOptions& options) { nfdchar_t* outPath = nullptr; - nfdfilteritem_t filterItem[2] = {{"ROM Files", "sfc,smc"}, - {"All Files", "*"}}; - nfdresult_t result = NFD_OpenDialog(&outPath, filterItem, 2, nullptr); + const nfdfilteritem_t* filter_list = nullptr; + size_t filter_count = 0; + std::vector filter_items; + std::vector filter_names; + std::vector filter_specs; + + if (!options.filters.empty()) { + filter_items.reserve(options.filters.size()); + filter_names.reserve(options.filters.size()); + filter_specs.reserve(options.filters.size()); + + for (const auto& filter : options.filters) { + std::string label = filter.label.empty() ? "Files" : filter.label; + std::string spec = filter.spec.empty() ? "*" : filter.spec; + filter_names.push_back(label); + filter_specs.push_back(spec); + filter_items.push_back( + {filter_names.back().c_str(), filter_specs.back().c_str()}); + } + + filter_list = filter_items.data(); + filter_count = filter_items.size(); + } + + nfdresult_t result = + NFD_OpenDialog(&outPath, filter_list, filter_count, nullptr); if (result == NFD_OKAY) { std::string path(outPath); @@ -26,6 +50,19 @@ std::string FileDialogWrapper::ShowOpenFileDialog() { return ""; } +std::string FileDialogWrapper::ShowOpenFileDialog() { + return ShowOpenFileDialog(FileDialogOptions{}); +} + +void FileDialogWrapper::ShowOpenFileDialogAsync( + const FileDialogOptions& options, + std::function callback) { + if (!callback) { + return; + } + callback(ShowOpenFileDialog(options)); +} + std::string FileDialogWrapper::ShowOpenFolderDialog() { nfdchar_t* outPath = nullptr; nfdresult_t result = NFD_PickFolder(&outPath, nullptr); diff --git a/src/app/platform/file_dialog_web.cc b/src/app/platform/file_dialog_web.cc index 7bdf4922..c5efe8a2 100644 --- a/src/app/platform/file_dialog_web.cc +++ b/src/app/platform/file_dialog_web.cc @@ -13,6 +13,12 @@ namespace util { // Web implementation of FileDialogWrapper // Triggers the existing file input element in the HTML +std::string FileDialogWrapper::ShowOpenFileDialog( + const FileDialogOptions& options) { + (void)options; + return ShowOpenFileDialog(); +} + std::string FileDialogWrapper::ShowOpenFileDialog() { #ifdef __EMSCRIPTEN__ // Trigger the existing file input element @@ -33,6 +39,15 @@ std::string FileDialogWrapper::ShowOpenFileDialog() { #endif } +void FileDialogWrapper::ShowOpenFileDialogAsync( + const FileDialogOptions& options, + std::function callback) { + if (!callback) { + return; + } + callback(ShowOpenFileDialog(options)); +} + std::string FileDialogWrapper::ShowOpenFolderDialog() { // Folder picking not supported on web in the same way return ""; @@ -57,4 +72,3 @@ std::vector FileDialogWrapper::GetFilesInFolder( } // namespace util } // namespace yaze - diff --git a/src/app/platform/font_loader.cc b/src/app/platform/font_loader.cc index 655a404f..ab3cc442 100644 --- a/src/app/platform/font_loader.cc +++ b/src/app/platform/font_loader.cc @@ -31,8 +31,17 @@ namespace { std::string SetFontPath(const std::string& font_path) { #ifdef __APPLE__ #if TARGET_OS_IOS == 1 - const std::string kBundlePath = util::GetBundleResourcePath(); - return kBundlePath + font_path; + const std::string bundle_root = util::GetBundleResourcePath(); + std::string bundle_path = + absl::StrCat(bundle_root, "assets/font/", font_path); + if (std::filesystem::exists(bundle_path)) { + return bundle_path; + } + bundle_path = absl::StrCat(bundle_root, font_path); + if (std::filesystem::exists(bundle_path)) { + return bundle_path; + } + return absl::StrCat("assets/font/", font_path); #else std::string bundle_path = absl::StrCat( util::GetBundleResourcePath(), "Contents/Resources/font/", font_path); diff --git a/src/app/platform/ios/ios_host.h b/src/app/platform/ios/ios_host.h new file mode 100644 index 00000000..5aa4539f --- /dev/null +++ b/src/app/platform/ios/ios_host.h @@ -0,0 +1,35 @@ +#pragma once + +#include + +#include "absl/status/status.h" +#include "app/application.h" + +namespace yaze { +namespace ios { + +struct IOSHostConfig { + AppConfig app_config; + bool auto_start = true; +}; + +class IOSHost { + public: + IOSHost() = default; + ~IOSHost(); + + absl::Status Initialize(const IOSHostConfig& config); + void Tick(); + void Shutdown(); + + void SetMetalView(void* view); + void* GetMetalView() const; + + private: + IOSHostConfig config_{}; + void* metal_view_ = nullptr; + bool initialized_ = false; +}; + +} // namespace ios +} // namespace yaze diff --git a/src/app/platform/ios/ios_host.mm b/src/app/platform/ios/ios_host.mm new file mode 100644 index 00000000..e6c4cd42 --- /dev/null +++ b/src/app/platform/ios/ios_host.mm @@ -0,0 +1,61 @@ +#include "app/platform/ios/ios_host.h" + +#if defined(__APPLE__) +#include +#endif + +#if defined(__APPLE__) && (TARGET_OS_IPHONE == 1 || TARGET_IPHONE_SIMULATOR == 1) +#import +#endif + +#include "app/platform/ios/ios_platform_state.h" +#include "util/log.h" + +namespace yaze::ios { + +IOSHost::~IOSHost() { + Shutdown(); +} + +absl::Status IOSHost::Initialize(const IOSHostConfig& config) { + config_ = config; + +#if defined(__APPLE__) && (TARGET_OS_IPHONE == 1 || TARGET_IPHONE_SIMULATOR == 1) + if (!metal_view_) { + return absl::FailedPreconditionError("Metal view not attached"); + } + + Application::Instance().Initialize(config_.app_config); + initialized_ = true; + LOG_INFO("IOSHost", "Initialized iOS host (stub)"); + return absl::OkStatus(); +#else + return absl::FailedPreconditionError("IOSHost only available on iOS"); +#endif +} + +void IOSHost::Tick() { + if (!initialized_) { + return; + } + Application::Instance().Tick(); +} + +void IOSHost::Shutdown() { + if (!initialized_) { + return; + } + Application::Instance().Shutdown(); + initialized_ = false; +} + +void IOSHost::SetMetalView(void* view) { + metal_view_ = view; + platform::ios::SetMetalView(view); +} + +void* IOSHost::GetMetalView() const { + return metal_view_; +} + +} // namespace yaze::ios diff --git a/src/app/platform/ios/ios_platform_state.h b/src/app/platform/ios/ios_platform_state.h new file mode 100644 index 00000000..e68d6fa4 --- /dev/null +++ b/src/app/platform/ios/ios_platform_state.h @@ -0,0 +1,22 @@ +#pragma once + +namespace yaze { +namespace platform { +namespace ios { + +struct SafeAreaInsets { + float left = 0.0f; + float right = 0.0f; + float top = 0.0f; + float bottom = 0.0f; +}; + +void SetMetalView(void* view); +void* GetMetalView(); + +void SetSafeAreaInsets(float left, float right, float top, float bottom); +SafeAreaInsets GetSafeAreaInsets(); + +} // namespace ios +} // namespace platform +} // namespace yaze diff --git a/src/app/platform/ios/ios_platform_state.mm b/src/app/platform/ios/ios_platform_state.mm new file mode 100644 index 00000000..3e7224ad --- /dev/null +++ b/src/app/platform/ios/ios_platform_state.mm @@ -0,0 +1,30 @@ +#include "app/platform/ios/ios_platform_state.h" + +namespace yaze { +namespace platform { +namespace ios { + +namespace { +void* g_metal_view = nullptr; +SafeAreaInsets g_safe_area_insets = {}; +} // namespace + +void SetMetalView(void* view) { + g_metal_view = view; +} + +void* GetMetalView() { + return g_metal_view; +} + +void SetSafeAreaInsets(float left, float right, float top, float bottom) { + g_safe_area_insets = {left, right, top, bottom}; +} + +SafeAreaInsets GetSafeAreaInsets() { + return g_safe_area_insets; +} + +} // namespace ios +} // namespace platform +} // namespace yaze diff --git a/src/app/platform/ios/ios_window_backend.h b/src/app/platform/ios/ios_window_backend.h new file mode 100644 index 00000000..e34ee7f3 --- /dev/null +++ b/src/app/platform/ios/ios_window_backend.h @@ -0,0 +1,56 @@ +#pragma once + +#include +#include + +#include "absl/status/status.h" +#include "app/platform/iwindow.h" + +namespace yaze { +namespace platform { + +class IOSWindowBackend final : public IWindowBackend { + public: + IOSWindowBackend() = default; + ~IOSWindowBackend() override = default; + + absl::Status Initialize(const WindowConfig& config) override; + absl::Status Shutdown() override; + bool IsInitialized() const override; + + bool PollEvent(WindowEvent& out_event) override; + void ProcessNativeEvent(void* native_event) override; + + WindowStatus GetStatus() const override; + bool IsActive() const override; + void SetActive(bool active) override; + void GetSize(int* width, int* height) const override; + void SetSize(int width, int height) override; + std::string GetTitle() const override; + void SetTitle(const std::string& title) override; + + bool InitializeRenderer(gfx::IRenderer* renderer) override; + SDL_Window* GetNativeWindow() override; + + absl::Status InitializeImGui(gfx::IRenderer* renderer) override; + void ShutdownImGui() override; + void NewImGuiFrame() override; + void RenderImGui(gfx::IRenderer* renderer) override; + + uint32_t GetAudioDevice() const override; + std::shared_ptr GetAudioBuffer() const override; + + std::string GetBackendName() const override; + int GetSDLVersion() const override; + + private: + bool initialized_ = false; + bool imgui_initialized_ = false; + WindowStatus status_{}; + std::string title_; + void* metal_view_ = nullptr; + void* command_queue_ = nullptr; +}; + +} // namespace platform +} // namespace yaze diff --git a/src/app/platform/ios/ios_window_backend.mm b/src/app/platform/ios/ios_window_backend.mm new file mode 100644 index 00000000..63aabc27 --- /dev/null +++ b/src/app/platform/ios/ios_window_backend.mm @@ -0,0 +1,351 @@ +#include "app/platform/ios/ios_window_backend.h" + +#if defined(__APPLE__) +#include +#endif + +#if defined(__APPLE__) && (TARGET_OS_IPHONE == 1 || TARGET_IPHONE_SIMULATOR == 1) +#import +#import +#import +#import +#endif + +#include + +#include "app/gfx/backend/metal_renderer.h" +#include "app/gui/core/style.h" +#include "app/platform/font_loader.h" +#include "app/platform/ios/ios_platform_state.h" +#include "imgui/backends/imgui_impl_metal.h" +#include "imgui/imgui.h" +#include "util/log.h" + +namespace yaze { +namespace platform { + +namespace { +#if defined(__APPLE__) && (TARGET_OS_IPHONE == 1 || TARGET_IPHONE_SIMULATOR == 1) +UIEdgeInsets GetSafeAreaInsets(MTKView* view) { + if (!view) { + return UIEdgeInsetsZero; + } + if (@available(iOS 11.0, *)) { + return view.safeAreaInsets; + } + return UIEdgeInsetsZero; +} + +void ApplyTouchStyle(MTKView* view) { + ImGuiStyle& style = ImGui::GetStyle(); + const float frame_height = ImGui::GetFrameHeight(); + const float target_height = std::max(44.0f, frame_height); + const float touch_extra = + std::clamp((target_height - frame_height) * 0.5f, 0.0f, 16.0f); + style.TouchExtraPadding = ImVec2(touch_extra, touch_extra); + + const float font_size = ImGui::GetFontSize(); + if (font_size > 0.0f) { + style.ScrollbarSize = std::max(style.ScrollbarSize, font_size * 1.1f); + style.GrabMinSize = std::max(style.GrabMinSize, font_size * 0.9f); + style.FramePadding.x = std::max(style.FramePadding.x, font_size * 0.55f); + style.FramePadding.y = std::max(style.FramePadding.y, font_size * 0.35f); + style.ItemSpacing.x = std::max(style.ItemSpacing.x, font_size * 0.45f); + style.ItemSpacing.y = std::max(style.ItemSpacing.y, font_size * 0.35f); + } + + const UIEdgeInsets insets = GetSafeAreaInsets(view); + const float safe_x = std::max(insets.left, insets.right); + const float safe_y = std::max(insets.top, insets.bottom); + style.DisplaySafeAreaPadding = ImVec2(safe_x, safe_y); + ios::SetSafeAreaInsets(insets.left, insets.right, insets.top, + insets.bottom); +} +#endif +} // namespace + +absl::Status IOSWindowBackend::Initialize(const WindowConfig& config) { +#if defined(__APPLE__) && (TARGET_OS_IPHONE == 1 || TARGET_IPHONE_SIMULATOR == 1) + metal_view_ = ios::GetMetalView(); + if (!metal_view_) { + return absl::FailedPreconditionError("Metal view not set"); + } + + title_ = config.title; + status_.is_active = true; + status_.is_focused = true; + status_.is_fullscreen = config.fullscreen; + + auto* view = static_cast(metal_view_); + status_.width = static_cast(view.bounds.size.width); + status_.height = static_cast(view.bounds.size.height); + + initialized_ = true; + return absl::OkStatus(); +#else + (void)config; + return absl::FailedPreconditionError( + "IOSWindowBackend is only available on iOS"); +#endif +} + +absl::Status IOSWindowBackend::Shutdown() { + ShutdownImGui(); + +#if defined(__APPLE__) && (TARGET_OS_IPHONE == 1 || TARGET_IPHONE_SIMULATOR == 1) + if (command_queue_) { + CFRelease(command_queue_); + command_queue_ = nullptr; + } +#endif + + metal_view_ = nullptr; + initialized_ = false; + return absl::OkStatus(); +} + +bool IOSWindowBackend::IsInitialized() const { + return initialized_; +} + +bool IOSWindowBackend::PollEvent(WindowEvent& out_event) { + out_event = WindowEvent{}; + return false; +} + +void IOSWindowBackend::ProcessNativeEvent(void* native_event) { + (void)native_event; +} + +WindowStatus IOSWindowBackend::GetStatus() const { + WindowStatus status = status_; +#if defined(__APPLE__) && (TARGET_OS_IPHONE == 1 || TARGET_IPHONE_SIMULATOR == 1) + if (metal_view_) { + auto* view = static_cast(metal_view_); + status.width = static_cast(view.bounds.size.width); + status.height = static_cast(view.bounds.size.height); + } +#endif + return status; +} + +bool IOSWindowBackend::IsActive() const { + return status_.is_active; +} + +void IOSWindowBackend::SetActive(bool active) { + status_.is_active = active; +} + +void IOSWindowBackend::GetSize(int* width, int* height) const { +#if defined(__APPLE__) && (TARGET_OS_IPHONE == 1 || TARGET_IPHONE_SIMULATOR == 1) + if (metal_view_) { + auto* view = static_cast(metal_view_); + if (width) { + *width = static_cast(view.bounds.size.width); + } + if (height) { + *height = static_cast(view.bounds.size.height); + } + return; + } +#endif + + if (width) { + *width = 0; + } + if (height) { + *height = 0; + } +} + +void IOSWindowBackend::SetSize(int width, int height) { +#if defined(__APPLE__) && (TARGET_OS_IPHONE == 1 || TARGET_IPHONE_SIMULATOR == 1) + if (metal_view_) { + auto* view = static_cast(metal_view_); + view.drawableSize = CGSizeMake(width, height); + } +#else + (void)width; + (void)height; +#endif +} + +std::string IOSWindowBackend::GetTitle() const { + return title_; +} + +void IOSWindowBackend::SetTitle(const std::string& title) { + title_ = title; +} + +bool IOSWindowBackend::InitializeRenderer(gfx::IRenderer* renderer) { + if (!renderer || !metal_view_) { + return false; + } + + if (renderer->GetBackendRenderer()) { + return true; + } + + auto* metal_renderer = dynamic_cast(renderer); + if (metal_renderer) { + metal_renderer->SetMetalView(metal_view_); + } else { + LOG_WARN("IOSWindowBackend", "Non-Metal renderer selected on iOS"); + } + + return renderer->Initialize(nullptr); +} + +SDL_Window* IOSWindowBackend::GetNativeWindow() { + return nullptr; +} + +absl::Status IOSWindowBackend::InitializeImGui(gfx::IRenderer* renderer) { + if (imgui_initialized_) { + return absl::OkStatus(); + } + + if (!renderer) { + return absl::InvalidArgumentError("Renderer is null"); + } + +#if defined(__APPLE__) && (TARGET_OS_IPHONE == 1 || TARGET_IPHONE_SIMULATOR == 1) + if (!metal_view_) { + return absl::FailedPreconditionError("Metal view not set"); + } + + auto* view = static_cast(metal_view_); + id device = view.device; + if (!device) { + device = MTLCreateSystemDefaultDevice(); + view.device = device; + } + + if (!device) { + return absl::InternalError("Failed to create Metal device"); + } + + IMGUI_CHECKVERSION(); + ImGui::CreateContext(); + + ImGuiIO& io = ImGui::GetIO(); + io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; + io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; + io.ConfigFlags |= ImGuiConfigFlags_IsTouchScreen; + + if (!ImGui_ImplMetal_Init(device)) { + return absl::InternalError("ImGui_ImplMetal_Init failed"); + } + + auto font_status = LoadPackageFonts(); + if (!font_status.ok()) { + ImGui_ImplMetal_Shutdown(); + ImGui::DestroyContext(); + return font_status; + } + gui::ColorsYaze(); +#if defined(__APPLE__) && (TARGET_OS_IPHONE == 1 || TARGET_IPHONE_SIMULATOR == 1) + ApplyTouchStyle(view); +#endif + + if (!command_queue_) { + id queue = [device newCommandQueue]; + command_queue_ = (__bridge_retained void*)queue; + } + + imgui_initialized_ = true; + LOG_INFO("IOSWindowBackend", "ImGui initialized with Metal backend"); + return absl::OkStatus(); +#else + return absl::FailedPreconditionError( + "IOSWindowBackend is only available on iOS"); +#endif +} + +void IOSWindowBackend::ShutdownImGui() { + if (!imgui_initialized_) { + return; + } + + ImGui_ImplMetal_Shutdown(); + ImGui::DestroyContext(); + + imgui_initialized_ = false; +} + +void IOSWindowBackend::NewImGuiFrame() { + if (!imgui_initialized_) { + return; + } + +#if defined(__APPLE__) && (TARGET_OS_IPHONE == 1 || TARGET_IPHONE_SIMULATOR == 1) + auto* view = static_cast(metal_view_); + if (!view) { + return; + } + + ApplyTouchStyle(view); + + auto* render_pass = view.currentRenderPassDescriptor; + if (!render_pass) { + return; + } + + ImGui_ImplMetal_NewFrame(render_pass); +#endif +} + +void IOSWindowBackend::RenderImGui(gfx::IRenderer* renderer) { + if (!imgui_initialized_) { + return; + } + + ImGui::Render(); + +#if defined(__APPLE__) && (TARGET_OS_IPHONE == 1 || TARGET_IPHONE_SIMULATOR == 1) + (void)renderer; + auto* view = static_cast(metal_view_); + if (!view || !view.currentDrawable) { + return; + } + + auto* render_pass = view.currentRenderPassDescriptor; + if (!render_pass || !command_queue_) { + return; + } + + id queue = + (__bridge id)command_queue_; + id command_buffer = [queue commandBuffer]; + id encoder = + [command_buffer renderCommandEncoderWithDescriptor:render_pass]; + + ImGui_ImplMetal_RenderDrawData(ImGui::GetDrawData(), command_buffer, encoder); + [encoder endEncoding]; + [command_buffer presentDrawable:view.currentDrawable]; + [command_buffer commit]; +#else + (void)renderer; +#endif +} + +uint32_t IOSWindowBackend::GetAudioDevice() const { + return 0; +} + +std::shared_ptr IOSWindowBackend::GetAudioBuffer() const { + return nullptr; +} + +std::string IOSWindowBackend::GetBackendName() const { + return "iOS-Metal"; +} + +int IOSWindowBackend::GetSDLVersion() const { + return 0; +} + +} // namespace platform +} // namespace yaze diff --git a/src/app/platform/iwindow.h b/src/app/platform/iwindow.h index 88dce5d3..d5393214 100644 --- a/src/app/platform/iwindow.h +++ b/src/app/platform/iwindow.h @@ -272,6 +272,7 @@ class IWindowBackend { enum class WindowBackendType { SDL2, SDL3, + IOS, Auto // Automatically select based on availability }; diff --git a/src/app/platform/view_controller.h b/src/app/platform/view_controller.h index 27e76646..c6da98b2 100644 --- a/src/app/platform/view_controller.h +++ b/src/app/platform/view_controller.h @@ -12,7 +12,7 @@ #endif #else #ifdef __OBJC__ -@interface AppViewController : UIViewController +@interface AppViewController : UIViewController @property(nonatomic) yaze::Controller *controller; @property(nonatomic) UIHoverGestureRecognizer *hoverGestureRecognizer; @property(nonatomic) UIPinchGestureRecognizer *pinchRecognizer; diff --git a/src/app/platform/window_backend_factory.cc b/src/app/platform/window_backend_factory.cc index d4b89d6e..7b365659 100644 --- a/src/app/platform/window_backend_factory.cc +++ b/src/app/platform/window_backend_factory.cc @@ -5,6 +5,14 @@ #include "app/platform/sdl2_window_backend.h" #include "util/log.h" +#if defined(__APPLE__) +#include +#endif + +#if defined(__APPLE__) && (TARGET_OS_IPHONE == 1 || TARGET_IPHONE_SIMULATOR == 1) +#include "app/platform/ios/ios_window_backend.h" +#endif + #ifdef YAZE_USE_SDL3 #include "app/platform/sdl3_window_backend.h" #endif @@ -33,6 +41,15 @@ std::unique_ptr WindowBackendFactory::Create( return std::make_unique(); #endif + case WindowBackendType::IOS: +#if defined(__APPLE__) && (TARGET_OS_IPHONE == 1 || TARGET_IPHONE_SIMULATOR == 1) + return std::make_unique(); +#else + LOG_WARN("WindowBackendFactory", + "iOS backend requested on non-iOS platform"); + return nullptr; +#endif + case WindowBackendType::Auto: default: return Create(GetDefaultType()); @@ -40,6 +57,9 @@ std::unique_ptr WindowBackendFactory::Create( } WindowBackendType WindowBackendFactory::GetDefaultType() { +#if defined(__APPLE__) && (TARGET_OS_IPHONE == 1 || TARGET_IPHONE_SIMULATOR == 1) + return WindowBackendType::IOS; +#endif #ifdef YAZE_USE_SDL3 return WindowBackendType::SDL3; #else @@ -66,6 +86,13 @@ bool WindowBackendFactory::IsAvailable(WindowBackendType type) { case WindowBackendType::Auto: return true; // Auto always available + case WindowBackendType::IOS: +#if defined(__APPLE__) && (TARGET_OS_IPHONE == 1 || TARGET_IPHONE_SIMULATOR == 1) + return true; +#else + return false; +#endif + default: return false; } diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 8ac844a5..2da211a2 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -76,8 +76,10 @@ set_target_properties(yaze_core_lib PROPERTIES # Platform-specific compile definitions if(UNIX AND NOT APPLE) target_compile_definitions(yaze_core_lib PRIVATE linux stricmp=strcasecmp) -elseif(APPLE) +elseif(YAZE_PLATFORM_MACOS) target_compile_definitions(yaze_core_lib PRIVATE MACOS) +elseif(YAZE_PLATFORM_IOS) + target_compile_definitions(yaze_core_lib PRIVATE YAZE_IOS) elseif(WIN32) target_compile_definitions(yaze_core_lib PRIVATE WINDOWS) endif() diff --git a/src/core/version_manager.cc b/src/core/version_manager.cc index c71f6d0e..fe2fdd78 100644 --- a/src/core/version_manager.cc +++ b/src/core/version_manager.cc @@ -182,6 +182,11 @@ absl::Status VersionManager::BackupRomArtifact(const std::string& timestamp_str) // ============================================================================ absl::Status VersionManager::RunCommand(const std::string& cmd) { +#if defined(YAZE_IOS) + (void)cmd; + return absl::FailedPreconditionError( + "Command execution is not available on iOS"); +#else // Execute command in project root std::string full_cmd; @@ -197,9 +202,15 @@ absl::Status VersionManager::RunCommand(const std::string& cmd) { return absl::InternalError(absl::StrFormat("Command failed: %s (Exit code %d)", cmd, ret)); } return absl::OkStatus(); +#endif } absl::StatusOr VersionManager::RunCommandOutput(const std::string& cmd) const { +#if defined(YAZE_IOS) + (void)cmd; + return absl::FailedPreconditionError( + "Command execution is not available on iOS"); +#else std::string full_cmd; fs::path project_dir = fs::path(project_->filepath).parent_path(); if (!project_dir.empty()) { @@ -218,6 +229,7 @@ absl::StatusOr VersionManager::RunCommandOutput(const std::string& result += buffer.data(); } return result; +#endif } } // namespace core diff --git a/src/ios/iOS/Info-iOS.plist b/src/ios/iOS/Info-iOS.plist index 2d98d3c6..d9bf93ef 100644 --- a/src/ios/iOS/Info-iOS.plist +++ b/src/ios/iOS/Info-iOS.plist @@ -23,7 +23,7 @@ Default LSItemContentTypes - halext.sfc + org.halext.sfc @@ -43,6 +43,10 @@ 1 LSRequiresIPhoneOS + LSSupportsOpeningDocumentsInPlace + + UIFileSharingEnabled + UILaunchStoryboardName LaunchScreen UIRequiredDeviceCapabilities @@ -52,6 +56,25 @@ UIRequiresFullScreen + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + UIWindowSceneSessionRoleApplication + + + UISceneConfigurationName + Default Configuration + UISceneDelegateClassName + SceneDelegate + UISceneClassName + UIWindowScene + + + + UIStatusBarHidden UIStatusBarStyle @@ -88,6 +111,7 @@ public.filename-extension sfc + smc @@ -110,6 +134,7 @@ public.filename-extension sfc + smc public.mime-type diff --git a/src/ios/main.mm b/src/ios/main.mm index ed6e018e..648630aa 100644 --- a/src/ios/main.mm +++ b/src/ios/main.mm @@ -35,6 +35,7 @@ #include "app/application.h" #include "app/platform/app_delegate.h" #include "app/platform/font_loader.h" +#include "app/platform/ios/ios_host.h" #include "app/platform/window.h" #include "rom/rom.h" @@ -49,11 +50,19 @@ #include "imgui/backends/imgui_impl_sdlrenderer2.h" #include "imgui/imgui.h" +namespace { +yaze::ios::IOSHost g_ios_host; +} // namespace + // ---------------------------------------------------------------------------- // AppViewController // ---------------------------------------------------------------------------- -@implementation AppViewController +@implementation AppViewController { + yaze::AppConfig app_config_; + bool host_initialized_; + UITouch *primary_touch_; +} - (instancetype)initWithNibName:(nullable NSString *)nibNameOrNil bundle:(nullable NSBundle *)nibBundleOrNil { @@ -69,6 +78,12 @@ // Initialize SDL for iOS SDL_SetMainReady(); +#if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR + SDL_SetHint(SDL_HINT_AUDIO_CATEGORY, "ambient"); + if (SDL_Init(SDL_INIT_AUDIO | SDL_INIT_TIMER) != 0) { + NSLog(@"SDL_Init failed: %s", SDL_GetError()); + } +#endif #if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR SDL_iOSSetEventPump(SDL_TRUE); #endif @@ -104,33 +119,34 @@ // Initialize Application singleton yaze::AppConfig config; config.rom_file = rom_filename; - yaze::Application::Instance().Initialize(config); - - // Keep local reference to controller for property compatibility - self.controller = yaze::Application::Instance().GetController(); - - if (!self.controller) { - NSLog(@"Failed to initialize application controller"); - abort(); - } + app_config_ = config; + host_initialized_ = false; // Setup gesture recognizers _hoverGestureRecognizer = [[UIHoverGestureRecognizer alloc] initWithTarget:self action:@selector(HoverGesture:)]; + _hoverGestureRecognizer.cancelsTouchesInView = NO; + _hoverGestureRecognizer.delegate = self; [self.view addGestureRecognizer:_hoverGestureRecognizer]; _pinchRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(HandlePinch:)]; + _pinchRecognizer.cancelsTouchesInView = NO; + _pinchRecognizer.delegate = self; [self.view addGestureRecognizer:_pinchRecognizer]; _longPressRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPress:)]; + _longPressRecognizer.cancelsTouchesInView = NO; + _longPressRecognizer.delegate = self; [self.view addGestureRecognizer:_longPressRecognizer]; _swipeRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(HandleSwipe:)]; _swipeRecognizer.direction = UISwipeGestureRecognizerDirectionRight | UISwipeGestureRecognizerDirectionLeft; + _swipeRecognizer.cancelsTouchesInView = NO; + _swipeRecognizer.delegate = self; [self.view addGestureRecognizer:_swipeRecognizer]; return self; @@ -147,13 +163,36 @@ - (void)viewDidLoad { [super viewDidLoad]; + self.view.multipleTouchEnabled = YES; + self.mtkView.device = self.device; self.mtkView.delegate = self; + + if (!host_initialized_) { + g_ios_host.SetMetalView((__bridge void *)self.view); + yaze::ios::IOSHostConfig host_config; + host_config.app_config = app_config_; + auto status = g_ios_host.Initialize(host_config); + if (!status.ok()) { + NSLog(@"Failed to initialize iOS host: %s", + std::string(status.message()).c_str()); + abort(); + } + + self.controller = yaze::Application::Instance().GetController(); + if (!self.controller) { + NSLog(@"Failed to initialize application controller"); + abort(); + } + host_initialized_ = true; + } } - (void)drawInMTKView:(MTKView *)view { auto& app = yaze::Application::Instance(); - if (!app.IsReady() || !app.GetController()->IsActive()) return; + if (!host_initialized_ || !app.IsReady() || !app.GetController()->IsActive()) { + return; + } // Update ImGui display size for iOS before Tick // Note: Tick() calls OnInput() then OnLoad() (NewFrame) then DoRender() @@ -167,7 +206,7 @@ CGFloat framebufferScale = view.window.screen.scale ?: UIScreen.mainScreen.scale; io.DisplayFramebufferScale = ImVec2(framebufferScale, framebufferScale); - app.Tick(); + g_ios_host.Tick(); } - (void)mtkView:(MTKView *)view drawableSizeWillChange:(CGSize)size { @@ -185,20 +224,36 @@ // when there are multiple active touches. But for demo purposes, single-touch // interaction actually works surprisingly well. - (void)UpdateIOWithTouchEvent:(UIEvent *)event { - UITouch *anyTouch = event.allTouches.anyObject; - CGPoint touchLocation = [anyTouch locationInView:self.view]; ImGuiIO &io = ImGui::GetIO(); io.AddMouseSourceEvent(ImGuiMouseSource_TouchScreen); - io.AddMousePosEvent(touchLocation.x, touchLocation.y); - BOOL hasActiveTouch = NO; - for (UITouch *touch in event.allTouches) { - if (touch.phase != UITouchPhaseEnded && touch.phase != UITouchPhaseCancelled) { - hasActiveTouch = YES; - break; + UITouch *active_touch = nil; + if (primary_touch_ && [event.allTouches containsObject:primary_touch_]) { + if (primary_touch_.phase != UITouchPhaseEnded && + primary_touch_.phase != UITouchPhaseCancelled) { + active_touch = primary_touch_; } } - io.AddMouseButtonEvent(0, hasActiveTouch); + + if (!active_touch) { + for (UITouch *touch in event.allTouches) { + if (touch.phase != UITouchPhaseEnded && + touch.phase != UITouchPhaseCancelled) { + active_touch = touch; + break; + } + } + } + + if (active_touch) { + primary_touch_ = active_touch; + CGPoint touchLocation = [active_touch locationInView:self.view]; + io.AddMousePosEvent(touchLocation.x, touchLocation.y); + io.AddMouseButtonEvent(0, true); + } else { + primary_touch_ = nil; + io.AddMouseButtonEvent(0, false); + } } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { @@ -256,10 +311,47 @@ [gestureRecognizer locationInView:self.view].y); } +- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer + shouldRecognizeSimultaneouslyWithGestureRecognizer: + (UIGestureRecognizer *)otherGestureRecognizer { + (void)gestureRecognizer; + (void)otherGestureRecognizer; + return YES; +} + #endif @end +// ---------------------------------------------------------------------------- +// SceneDelegate (UIScene lifecycle) +// ---------------------------------------------------------------------------- + +#if !TARGET_OS_OSX + +@interface SceneDelegate : UIResponder +@property(nonatomic, strong) UIWindow *window; +@end + +@implementation SceneDelegate + +- (void)scene:(UIScene *)scene + willConnectToSession:(UISceneSession *)session + options:(UISceneConnectionOptions *)connectionOptions { + if (![scene isKindOfClass:[UIWindowScene class]]) { + return; + } + UIWindowScene *windowScene = (UIWindowScene *)scene; + UIViewController *rootViewController = [[AppViewController alloc] init]; + self.window = [[UIWindow alloc] initWithWindowScene:windowScene]; + self.window.rootViewController = rootViewController; + [self.window makeKeyAndVisible]; +} + +@end + +#endif + // ---------------------------------------------------------------------------- // AppDelegate // ---------------------------------------------------------------------------- @@ -297,10 +389,19 @@ #else +@interface AppDelegate : UIResponder +@property(nonatomic, strong) UIWindow *window; +@property(nonatomic, copy) void (^completionHandler)(NSString *selectedFile); +@property(nonatomic, strong) UIDocumentPickerViewController *documentPicker; +@end + @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + if (@available(iOS 13.0, *)) { + return YES; + } UIViewController *rootViewController = [[AppViewController alloc] init]; self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds]; self.window.rootViewController = rootViewController; @@ -308,16 +409,66 @@ return YES; } +- (UISceneConfiguration *)application:(UIApplication *)application + configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession + options:(UISceneConnectionOptions *)options { + if (@available(iOS 13.0, *)) { + UISceneConfiguration *configuration = + [[UISceneConfiguration alloc] initWithName:@"Default Configuration" + sessionRole:connectingSceneSession.role]; + configuration.delegateClass = [SceneDelegate class]; + configuration.sceneClass = [UIWindowScene class]; + return configuration; + } + return nil; +} + - (void)applicationWillTerminate:(UIApplication *)application { - yaze::Application::Instance().Shutdown(); + g_ios_host.Shutdown(); +} + +- (UIViewController *)RootViewControllerForPresenting { + if (@available(iOS 13.0, *)) { + for (UIScene *scene in UIApplication.sharedApplication.connectedScenes) { + if (scene.activationState != UISceneActivationStateForegroundActive) { + continue; + } + if (![scene isKindOfClass:[UIWindowScene class]]) { + continue; + } + UIWindowScene *windowScene = (UIWindowScene *)scene; + for (UIWindow *window in windowScene.windows) { + if (window.isKeyWindow && window.rootViewController) { + return window.rootViewController; + } + } + if (windowScene.windows.count > 0 && + windowScene.windows.firstObject.rootViewController) { + return windowScene.windows.firstObject.rootViewController; + } + } + } + + return self.window.rootViewController; } - (void)PresentDocumentPickerWithCompletionHandler: - (void (^)(NSString *selectedFile))completionHandler { + (void (^)(NSString *selectedFile))completionHandler + allowedTypes:(NSArray *)allowedTypes { self.completionHandler = completionHandler; - NSArray *documentTypes = @[ [UTType typeWithIdentifier:@"org.halext.sfc"] ]; - UIViewController *rootViewController = self.window.rootViewController; + NSArray* documentTypes = allowedTypes; + if (!documentTypes || documentTypes.count == 0) { + documentTypes = @[ UTTypeData ]; + } + UIViewController *rootViewController = [self RootViewControllerForPresenting]; + if (!rootViewController) { + if (self.completionHandler) { + self.completionHandler(@""); + } + self.completionHandler = nil; + return; + } _documentPicker = [[UIDocumentPickerViewController alloc] initForOpeningContentTypes:documentTypes]; _documentPicker.delegate = self; @@ -332,8 +483,6 @@ if (self.completionHandler) { if (selectedFileURL) { - self.completionHandler(selectedFileURL.path); - // Create a temporary file path NSString *tempDir = NSTemporaryDirectory(); NSString *fileName = [selectedFileURL lastPathComponent]; @@ -350,13 +499,11 @@ if (success) { std::string cppPath = std::string([tempPath UTF8String]); - NSLog(@"ROM copied to temporary path: %s", cppPath.c_str()); - - // Load ROM using modern API via Application singleton - // This triggers the full editor loading pipeline (sessions, startup actions, etc.) - yaze::Application::Instance().LoadRom(cppPath); + NSLog(@"File copied to temporary path: %s", cppPath.c_str()); + self.completionHandler(tempPath); } else { NSLog(@"Failed to copy ROM to temp directory: %@", error); + self.completionHandler(@""); } } else { self.completionHandler(@""); diff --git a/src/ios/project.yml b/src/ios/project.yml new file mode 100644 index 00000000..1558e269 --- /dev/null +++ b/src/ios/project.yml @@ -0,0 +1,77 @@ +name: yaze_ios +options: + bundleIdPrefix: org.halext + createIntermediateGroups: true + deploymentTarget: + iOS: "17.0" +settings: + base: + PRODUCT_NAME: yaze + PRODUCT_BUNDLE_IDENTIFIER: org.halext.yaze-ios + INFOPLIST_FILE: iOS/Info-iOS.plist + CLANG_CXX_LANGUAGE_STANDARD: c++20 + GCC_C_LANGUAGE_STANDARD: c17 + TARGETED_DEVICE_FAMILY: "1,2" + ENABLE_USER_SCRIPT_SANDBOXING: NO + HEADER_SEARCH_PATHS: + - "$(SRCROOT)/../../src" + - "$(SRCROOT)/../../incl" + - "$(SRCROOT)/../../ext" + - "$(SRCROOT)/../../ext/imgui" + - "$(SRCROOT)/../../build-ios" + - "$(SRCROOT)/../../build-ios/_deps/absl-src" + - "$(SRCROOT)/../../build-ios/_deps/nlohmann_json-src/include" + SYSTEM_HEADER_SEARCH_PATHS: + - "$(SRCROOT)/../../build-ios/_deps/SDL2-src/include" + - "$(SRCROOT)/../../build-ios/_deps/sdl2-src/include" + - "$(SRCROOT)/../../ext/SDL/include" + - "$(SRCROOT)/../../incl" + LIBRARY_SEARCH_PATHS: + - "$(SRCROOT)/../../build-ios/ios" + OTHER_LDFLAGS: + - "-ObjC" + - "-force_load" + - "$(SRCROOT)/../../build-ios/ios/libyaze_ios_bundle.a" +targets: + yaze_ios: + type: application + platform: iOS + deploymentTarget: "17.0" + sources: + - path: main.mm + - path: Media.xcassets + - path: iOS/LaunchScreen.storyboard + resources: + - path: ../../assets + settings: + base: + ASSETCATALOG_COMPILER_APPICON_NAME: yaze + postBuildScripts: + - name: Copy assets + script: | + set -e + ASSET_SRC="${SRCROOT}/../../assets" + ASSET_DST="${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/assets" + if [ ! -d "${ASSET_SRC}" ]; then + echo "Assets source missing: ${ASSET_SRC}" >&2 + exit 1 + fi + /usr/bin/ditto "${ASSET_SRC}" "${ASSET_DST}" + dependencies: + - sdk: UIKit.framework + - sdk: Foundation.framework + - sdk: CoreBluetooth.framework + - sdk: CoreHaptics.framework + - sdk: Metal.framework + - sdk: MetalKit.framework + - sdk: ModelIO.framework + - sdk: CoreGraphics.framework + - sdk: CoreVideo.framework + - sdk: CoreMotion.framework + - sdk: OpenGLES.framework + - sdk: QuartzCore.framework + - sdk: AVFoundation.framework + - sdk: AudioToolbox.framework + - sdk: GameController.framework + - sdk: UniformTypeIdentifiers.framework + - sdk: CoreText.framework diff --git a/src/ios/yaze.xcodeproj/project.pbxproj b/src/ios/yaze.xcodeproj/project.pbxproj index ff6e3939..f32036a1 100644 --- a/src/ios/yaze.xcodeproj/project.pbxproj +++ b/src/ios/yaze.xcodeproj/project.pbxproj @@ -10,7 +10,10 @@ 05318E0F274C397200A8DE2E /* GameController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 05318E0E274C397200A8DE2E /* GameController.framework */; }; 07A82ED82139413D0078D120 /* imgui_widgets.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07A82ED72139413C0078D120 /* imgui_widgets.cpp */; }; 07A82ED92139418F0078D120 /* imgui_widgets.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07A82ED72139413C0078D120 /* imgui_widgets.cpp */; }; + 2C9383FF416B47B6B4ED5B3B /* ios_host.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4CBB29F4B39241868684DD52 /* ios_host.mm */; }; + 3D7E0DFF523646C292410DF5 /* ios_platform_state.mm in Sources */ = {isa = PBXBuildFile; fileRef = 104B9B65C53C4E71B4C15762 /* ios_platform_state.mm */; }; 5079822E257677DB0038A28D /* imgui_tables.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5079822D257677DB0038A28D /* imgui_tables.cpp */; }; + 694B819145E646BC8601D320 /* metal_renderer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2DD3040220B14DA7AE5C9126 /* metal_renderer.mm */; }; 8309BD8F253CCAAA0045E2A1 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8309BD8E253CCAAA0045E2A1 /* UIKit.framework */; }; 8309BDA5253CCC070045E2A1 /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8309BDA0253CCBC10045E2A1 /* main.mm */; }; 8309BDA8253CCC080045E2A1 /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8309BDA0253CCBC10045E2A1 /* main.mm */; }; @@ -28,6 +31,10 @@ 83BBEA0820EB54E700295997 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83BBEA0220EB54E700295997 /* imgui_demo.cpp */; }; 83BBEA0920EB54E700295997 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83BBEA0320EB54E700295997 /* imgui.cpp */; }; 83BBEA0A20EB54E700295997 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83BBEA0320EB54E700295997 /* imgui.cpp */; }; + 95413E18FB9F4DDF9CE960C2 /* metal_renderer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2DD3040220B14DA7AE5C9126 /* metal_renderer.mm */; }; + C29B39EDC05548EB9CC18619 /* ios_window_backend.mm in Sources */ = {isa = PBXBuildFile; fileRef = E7546FEBFDF44B59A7DADD23 /* ios_window_backend.mm */; }; + CE0FA109BFE4477C9D65C7CD /* ModelIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83BBE9EE20EB471C00295997 /* ModelIO.framework */; }; + DCB32DF154774924A7112F61 /* ModelIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83BBE9EE20EB471C00295997 /* ModelIO.framework */; }; E318D8FB2C59C08300091322 /* app_delegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = E318D8482C59C08300091322 /* app_delegate.mm */; }; E318D8FC2C59C08300091322 /* app_delegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = E318D8482C59C08300091322 /* app_delegate.mm */; }; E318D9012C59C08300091322 /* file_dialog.mm in Sources */ = {isa = PBXBuildFile; fileRef = E318D84D2C59C08300091322 /* file_dialog.mm */; }; @@ -36,8 +43,8 @@ E318D9042C59C08300091322 /* font_loader.cc in Sources */ = {isa = PBXBuildFile; fileRef = E318D84E2C59C08300091322 /* font_loader.cc */; }; E318D9052C59C08300091322 /* font_loader.mm in Sources */ = {isa = PBXBuildFile; fileRef = E318D8502C59C08300091322 /* font_loader.mm */; }; E318D9062C59C08300091322 /* font_loader.mm in Sources */ = {isa = PBXBuildFile; fileRef = E318D8502C59C08300091322 /* font_loader.mm */; }; - E318D9092C59C08300091322 /* controller.cc in Sources */ = {isa = PBXBuildFile; fileRef = E318D8552C59C08300091322 /* controller.cc */; }; - E318D90A2C59C08300091322 /* controller.cc in Sources */ = {isa = PBXBuildFile; fileRef = E318D8552C59C08300091322 /* controller.cc */; }; + E318D9092C59C08300091322 /* ../controller.cc in Sources */ = {isa = PBXBuildFile; fileRef = E318D8552C59C08300091322 /* ../controller.cc */; }; + E318D90A2C59C08300091322 /* ../controller.cc in Sources */ = {isa = PBXBuildFile; fileRef = E318D8552C59C08300091322 /* ../controller.cc */; }; E318D90D2C59C08300091322 /* assembly_editor.cc in Sources */ = {isa = PBXBuildFile; fileRef = E318D85C2C59C08300091322 /* assembly_editor.cc */; }; E318D90E2C59C08300091322 /* assembly_editor.cc in Sources */ = {isa = PBXBuildFile; fileRef = E318D85C2C59C08300091322 /* assembly_editor.cc */; }; E318D90F2C59C08300091322 /* dungeon_editor.cc in Sources */ = {isa = PBXBuildFile; fileRef = E318D8602C59C08300091322 /* dungeon_editor.cc */; }; @@ -559,8 +566,8 @@ E318E2042C5A4FC200091322 /* per_thread_sem_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = E318DC372C5A4FBD00091322 /* per_thread_sem_test.cc */; }; E318E2052C5A4FC200091322 /* per_thread_sem.cc in Sources */ = {isa = PBXBuildFile; fileRef = E318DC382C5A4FBD00091322 /* per_thread_sem.cc */; }; E318E2062C5A4FC200091322 /* per_thread_sem.cc in Sources */ = {isa = PBXBuildFile; fileRef = E318DC382C5A4FBD00091322 /* per_thread_sem.cc */; }; - E318E2072C5A4FC200091322 /* waiter.cc in Sources */ = {isa = PBXBuildFile; fileRef = E318DC3B2C5A4FBD00091322 /* waiter.cc */; }; - E318E2082C5A4FC200091322 /* waiter.cc in Sources */ = {isa = PBXBuildFile; fileRef = E318DC3B2C5A4FBD00091322 /* waiter.cc */; }; + E318E2072C5A4FC200091322 /* waiter_base.cc in Sources */ = {isa = PBXBuildFile; fileRef = E318DC3B2C5A4FBD00091322 /* waiter_base.cc */; }; + E318E2082C5A4FC200091322 /* waiter_base.cc in Sources */ = {isa = PBXBuildFile; fileRef = E318DC3B2C5A4FBD00091322 /* waiter_base.cc */; }; E318E20A2C5A4FC200091322 /* barrier_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = E318DC3E2C5A4FBD00091322 /* barrier_test.cc */; }; E318E20B2C5A4FC200091322 /* barrier.cc in Sources */ = {isa = PBXBuildFile; fileRef = E318DC3F2C5A4FBD00091322 /* barrier.cc */; }; E318E20C2C5A4FC200091322 /* barrier.cc in Sources */ = {isa = PBXBuildFile; fileRef = E318DC3F2C5A4FBD00091322 /* barrier.cc */; }; @@ -642,7 +649,6 @@ E318E7382C5A4FC900091322 /* variant_exception_safety_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = E318DF192C5A4FBD00091322 /* variant_exception_safety_test.cc */; }; E318E73A2C5A4FC900091322 /* variant_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = E318DF1A2C5A4FBD00091322 /* variant_test.cc */; }; E318E7402C5A4FCA00091322 /* utility_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = E318DF202C5A4FBD00091322 /* utility_test.cc */; }; - E318E7422C5A4FCA00091322 /* abseil.podspec.gen.py in Resources */ = {isa = PBXBuildFile; fileRef = E318DF232C5A4FBD00091322 /* abseil.podspec.gen.py */; }; E318E7932C5A542700091322 /* distribution_test_util.cc in Sources */ = {isa = PBXBuildFile; fileRef = E318DB1F2C5A4FBD00091322 /* distribution_test_util.cc */; }; E318E7942C5A542700091322 /* distribution_test_util.h in Sources */ = {isa = PBXBuildFile; fileRef = E318DB202C5A4FBD00091322 /* distribution_test_util.h */; }; E318E7AD2C5A548C00091322 /* png.c in Sources */ = {isa = PBXBuildFile; fileRef = E318E7952C5A548C00091322 /* png.c */; }; @@ -682,15 +688,14 @@ E318E7D32C5A55AE00091322 /* palette_neon_intrinsics.c in Sources */ = {isa = PBXBuildFile; fileRef = E318E7CE2C5A55AE00091322 /* palette_neon_intrinsics.c */; }; E318E7D42C5A55AE00091322 /* filter_neon_intrinsics.c in Sources */ = {isa = PBXBuildFile; fileRef = E318E7CF2C5A55AE00091322 /* filter_neon_intrinsics.c */; }; E318E7D52C5A55AE00091322 /* filter_neon_intrinsics.c in Sources */ = {isa = PBXBuildFile; fileRef = E318E7CF2C5A55AE00091322 /* filter_neon_intrinsics.c */; }; - E318E7D72C5A55C300091322 /* arm_init.c in Sources */ = {isa = PBXBuildFile; fileRef = E318E7D62C5A55C300091322 /* arm_init.c */; }; - E318E7D82C5A55C300091322 /* arm_init.c in Sources */ = {isa = PBXBuildFile; fileRef = E318E7D62C5A55C300091322 /* arm_init.c */; }; + E318E7D72C5A55C300091322 /* arm/arm_init.c in Sources */ = {isa = PBXBuildFile; fileRef = E318E7D62C5A55C300091322 /* arm/arm_init.c */; }; + E318E7D82C5A55C300091322 /* arm/arm_init.c in Sources */ = {isa = PBXBuildFile; fileRef = E318E7D62C5A55C300091322 /* arm/arm_init.c */; }; E318E7E82C5A688A00091322 /* DroidSans.ttf in Resources */ = {isa = PBXBuildFile; fileRef = E318E7DB2C5A688A00091322 /* DroidSans.ttf */; }; E318E7EA2C5A688A00091322 /* IBMPlexSansJP-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = E318E7DC2C5A688A00091322 /* IBMPlexSansJP-Bold.ttf */; }; E318E7EC2C5A688A00091322 /* Karla-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = E318E7DD2C5A688A00091322 /* Karla-Regular.ttf */; }; E318E7EE2C5A688A00091322 /* MaterialIcons-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = E318E7DE2C5A688A00091322 /* MaterialIcons-Regular.ttf */; }; E318E7F02C5A688A00091322 /* NotoSansJP.ttf in Resources */ = {isa = PBXBuildFile; fileRef = E318E7DF2C5A688A00091322 /* NotoSansJP.ttf */; }; E318E7F22C5A688A00091322 /* Roboto-Medium.ttf in Resources */ = {isa = PBXBuildFile; fileRef = E318E7E02C5A688A00091322 /* Roboto-Medium.ttf */; }; - E318E7F62C5A688A00091322 /* ow_toolset.zeml in Resources */ = {isa = PBXBuildFile; fileRef = E318E7E32C5A688A00091322 /* ow_toolset.zeml */; }; E318E8342C5BD8C100091322 /* UniformTypeIdentifiers.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E318E8332C5BD8C000091322 /* UniformTypeIdentifiers.framework */; }; E318E86A2C5D74C500091322 /* SDL2.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E318E8592C5D74B700091322 /* SDL2.framework */; }; E318E86B2C5D74C500091322 /* SDL2.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = E318E8592C5D74B700091322 /* SDL2.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; @@ -701,7 +706,6 @@ E318E8712C5D757800091322 /* MaterialIcons-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = E318E7DE2C5A688A00091322 /* MaterialIcons-Regular.ttf */; }; E318E8722C5D757800091322 /* NotoSansJP.ttf in Resources */ = {isa = PBXBuildFile; fileRef = E318E7DF2C5A688A00091322 /* NotoSansJP.ttf */; }; E318E8732C5D757800091322 /* Roboto-Medium.ttf in Resources */ = {isa = PBXBuildFile; fileRef = E318E7E02C5A688A00091322 /* Roboto-Medium.ttf */; }; - E318E8752C5D757800091322 /* ow_toolset.zeml in Resources */ = {isa = PBXBuildFile; fileRef = E318E7E32C5A688A00091322 /* ow_toolset.zeml */; }; E318E8772C5D949200091322 /* yaze.png in Resources */ = {isa = PBXBuildFile; fileRef = E318E8762C5D949200091322 /* yaze.png */; }; E318E8792C5D958400091322 /* Media.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E318E8782C5D958400091322 /* Media.xcassets */; }; E318E87A2C605D5700091322 /* SDL2.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E318E8572C5D74B700091322 /* SDL2.framework */; }; @@ -711,8 +715,8 @@ E346FD782E82E3D60044283C /* tile16_editor.cc in Sources */ = {isa = PBXBuildFile; fileRef = E346FD772E82E3D60044283C /* tile16_editor.cc */; }; E346FD792E82E3D60044283C /* tile16_editor.cc in Sources */ = {isa = PBXBuildFile; fileRef = E346FD772E82E3D60044283C /* tile16_editor.cc */; }; E34C789C2C5882A100A6C275 /* imgui_tables.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5079822D257677DB0038A28D /* imgui_tables.cpp */; }; - E36971DA2CE189EA00DEF2F6 /* project.cc in Sources */ = {isa = PBXBuildFile; fileRef = E36971D92CE189EA00DEF2F6 /* project.cc */; }; - E36971DB2CE189EA00DEF2F6 /* project.cc in Sources */ = {isa = PBXBuildFile; fileRef = E36971D92CE189EA00DEF2F6 /* project.cc */; }; + E36971DA2CE189EA00DEF2F6 /* ../../core/project.cc in Sources */ = {isa = PBXBuildFile; fileRef = E36971D92CE189EA00DEF2F6 /* ../../core/project.cc */; }; + E36971DB2CE189EA00DEF2F6 /* ../../core/project.cc in Sources */ = {isa = PBXBuildFile; fileRef = E36971D92CE189EA00DEF2F6 /* ../../core/project.cc */; }; E37323B62D6A0BC800059101 /* text_editor.cc in Sources */ = {isa = PBXBuildFile; fileRef = E37323B52D6A0BC800059101 /* text_editor.cc */; }; E37323B82D6A0BE800059101 /* file_dialog.cc in Sources */ = {isa = PBXBuildFile; fileRef = E37323B72D6A0BE800059101 /* file_dialog.cc */; }; E37323B92D6A0BE800059101 /* file_dialog.cc in Sources */ = {isa = PBXBuildFile; fileRef = E37323B72D6A0BE800059101 /* file_dialog.cc */; }; @@ -726,7 +730,7 @@ E37323CD2D6A0C4800059101 /* hyrule_magic.cc in Sources */ = {isa = PBXBuildFile; fileRef = E37323CB2D6A0C4800059101 /* hyrule_magic.cc */; }; E384E2D62C76C6E800147029 /* message_data.cc in Sources */ = {isa = PBXBuildFile; fileRef = E384E2D52C76C6C800147029 /* message_data.cc */; }; E38A97F72C6C4CE3005FB662 /* extension_manager.cc in Sources */ = {isa = PBXBuildFile; fileRef = E38A97F22C6C4CE3005FB662 /* extension_manager.cc */; }; - E38A97F82C6C4CE3005FB662 /* settings_editor.cc in Sources */ = {isa = PBXBuildFile; fileRef = E38A97F42C6C4CE3005FB662 /* settings_editor.cc */; }; + E38A97F82C6C4CE3005FB662 /* settings_panel.cc in Sources */ = {isa = PBXBuildFile; fileRef = E38A97F42C6C4CE3005FB662 /* settings_panel.cc */; }; E3A5CEE52CF61F1200259DE8 /* main.cc in Sources */ = {isa = PBXBuildFile; fileRef = E3A5CEE32CF61F1200259DE8 /* main.cc */; }; E3B864952C8214B500122951 /* asset_browser.cc in Sources */ = {isa = PBXBuildFile; fileRef = E3B864902C82144A00122951 /* asset_browser.cc */; }; E3BE450D2E90A64D0075AC22 /* graphics_optimizer.cc in Sources */ = {isa = PBXBuildFile; fileRef = E3BE45042E90A64D0075AC22 /* graphics_optimizer.cc */; }; @@ -759,7 +763,7 @@ E3BE45482E90A6690075AC22 /* background_renderer.cc in Sources */ = {isa = PBXBuildFile; fileRef = E3BE45202E90A6690075AC22 /* background_renderer.cc */; }; E3BE45492E90A6690075AC22 /* text_editor.cc in Sources */ = {isa = PBXBuildFile; fileRef = E3BE45392E90A6690075AC22 /* text_editor.cc */; }; E3BE454A2E90A6690075AC22 /* canvas_performance/performance_integration.cc in Sources */ = {isa = PBXBuildFile; fileRef = E3BE452B2E90A6690075AC22 /* canvas_performance/performance_integration.cc */; }; - E3BE454B2E90A6690075AC22 /* widget_id_registry.cc in Sources */ = {isa = PBXBuildFile; fileRef = E3BE453E2E90A6690075AC22 /* widget_id_registry.cc */; }; + E3BE454B2E90A6690075AC22 /* automation/widget_id_registry.cc in Sources */ = {isa = PBXBuildFile; fileRef = E3BE453E2E90A6690075AC22 /* automation/widget_id_registry.cc */; }; E3BE454C2E90A6690075AC22 /* canvas_context_menu.cc in Sources */ = {isa = PBXBuildFile; fileRef = E3BE45252E90A6690075AC22 /* canvas_context_menu.cc */; }; E3BE454D2E90A6690075AC22 /* canvas.cmake in Resources */ = {isa = PBXBuildFile; fileRef = E3BE45232E90A6690075AC22 /* canvas.cmake */; }; E3BE454E2E90A6690075AC22 /* canvas.cmake in Resources */ = {isa = PBXBuildFile; fileRef = E3BE45232E90A6690075AC22 /* canvas.cmake */; }; @@ -775,14 +779,14 @@ E3BE45582E90A6690075AC22 /* background_renderer.cc in Sources */ = {isa = PBXBuildFile; fileRef = E3BE45202E90A6690075AC22 /* background_renderer.cc */; }; E3BE45592E90A6690075AC22 /* text_editor.cc in Sources */ = {isa = PBXBuildFile; fileRef = E3BE45392E90A6690075AC22 /* text_editor.cc */; }; E3BE455A2E90A6690075AC22 /* canvas_performance/performance_integration.cc in Sources */ = {isa = PBXBuildFile; fileRef = E3BE452B2E90A6690075AC22 /* canvas_performance/performance_integration.cc */; }; - E3BE455B2E90A6690075AC22 /* widget_id_registry.cc in Sources */ = {isa = PBXBuildFile; fileRef = E3BE453E2E90A6690075AC22 /* widget_id_registry.cc */; }; + E3BE455B2E90A6690075AC22 /* automation/widget_id_registry.cc in Sources */ = {isa = PBXBuildFile; fileRef = E3BE453E2E90A6690075AC22 /* automation/widget_id_registry.cc */; }; E3BE455C2E90A6690075AC22 /* canvas_context_menu.cc in Sources */ = {isa = PBXBuildFile; fileRef = E3BE45252E90A6690075AC22 /* canvas_context_menu.cc */; }; - E3BE45642E90A6E20075AC22 /* window.cc in Sources */ = {isa = PBXBuildFile; fileRef = E3BE45632E90A6E20075AC22 /* window.cc */; }; - E3BE45652E90A6E20075AC22 /* widget_state_capture.cc in Sources */ = {isa = PBXBuildFile; fileRef = E3BE45612E90A6E20075AC22 /* widget_state_capture.cc */; }; - E3BE45662E90A6E20075AC22 /* asar_wrapper.cc in Sources */ = {isa = PBXBuildFile; fileRef = E3BE455E2E90A6E20075AC22 /* asar_wrapper.cc */; }; - E3BE45672E90A6E20075AC22 /* window.cc in Sources */ = {isa = PBXBuildFile; fileRef = E3BE45632E90A6E20075AC22 /* window.cc */; }; - E3BE45682E90A6E20075AC22 /* widget_state_capture.cc in Sources */ = {isa = PBXBuildFile; fileRef = E3BE45612E90A6E20075AC22 /* widget_state_capture.cc */; }; - E3BE45692E90A6E20075AC22 /* asar_wrapper.cc in Sources */ = {isa = PBXBuildFile; fileRef = E3BE455E2E90A6E20075AC22 /* asar_wrapper.cc */; }; + E3BE45642E90A6E20075AC22 /* ../platform/window.cc in Sources */ = {isa = PBXBuildFile; fileRef = E3BE45632E90A6E20075AC22 /* ../platform/window.cc */; }; + E3BE45652E90A6E20075AC22 /* ../gui/automation/widget_state_capture.cc in Sources */ = {isa = PBXBuildFile; fileRef = E3BE45612E90A6E20075AC22 /* ../gui/automation/widget_state_capture.cc */; }; + E3BE45662E90A6E20075AC22 /* ../../core/asar_wrapper.cc in Sources */ = {isa = PBXBuildFile; fileRef = E3BE455E2E90A6E20075AC22 /* ../../core/asar_wrapper.cc */; }; + E3BE45672E90A6E20075AC22 /* ../platform/window.cc in Sources */ = {isa = PBXBuildFile; fileRef = E3BE45632E90A6E20075AC22 /* ../platform/window.cc */; }; + E3BE45682E90A6E20075AC22 /* ../gui/automation/widget_state_capture.cc in Sources */ = {isa = PBXBuildFile; fileRef = E3BE45612E90A6E20075AC22 /* ../gui/automation/widget_state_capture.cc */; }; + E3BE45692E90A6E20075AC22 /* ../../core/asar_wrapper.cc in Sources */ = {isa = PBXBuildFile; fileRef = E3BE455E2E90A6E20075AC22 /* ../../core/asar_wrapper.cc */; }; E3BE45732E90A6FB0075AC22 /* test_manager.cc in Sources */ = {isa = PBXBuildFile; fileRef = E3BE456F2E90A6FB0075AC22 /* test_manager.cc */; }; E3BE45742E90A6FB0075AC22 /* test.cmake in Resources */ = {isa = PBXBuildFile; fileRef = E3BE456D2E90A6FB0075AC22 /* test.cmake */; }; E3BE45752E90A6FB0075AC22 /* test.cmake in Resources */ = {isa = PBXBuildFile; fileRef = E3BE456D2E90A6FB0075AC22 /* test.cmake */; }; @@ -803,7 +807,6 @@ E3BE45932E90A7EB0075AC22 /* overworld_editor_manager.cc in Sources */ = {isa = PBXBuildFile; fileRef = E3BE458B2E90A7EA0075AC22 /* overworld_editor_manager.cc */; }; E3BE45A62E90A9D70075AC22 /* dungeon_canvas_viewer.cc in Sources */ = {isa = PBXBuildFile; fileRef = E3BE45972E90A9D70075AC22 /* dungeon_canvas_viewer.cc */; }; E3BE45A72E90A9D70075AC22 /* dungeon_object_selector.cc in Sources */ = {isa = PBXBuildFile; fileRef = E3BE459B2E90A9D70075AC22 /* dungeon_object_selector.cc */; }; - E3BE45A82E90A9D70075AC22 /* dungeon_renderer.cc in Sources */ = {isa = PBXBuildFile; fileRef = E3BE459D2E90A9D70075AC22 /* dungeon_renderer.cc */; }; E3BE45A92E90A9D70075AC22 /* dungeon_room_loader.cc in Sources */ = {isa = PBXBuildFile; fileRef = E3BE459F2E90A9D70075AC22 /* dungeon_room_loader.cc */; }; E3BE45AA2E90A9D70075AC22 /* dungeon_object_interaction.cc in Sources */ = {isa = PBXBuildFile; fileRef = E3BE45992E90A9D70075AC22 /* dungeon_object_interaction.cc */; }; E3BE45AB2E90A9D70075AC22 /* dungeon_toolset.cc in Sources */ = {isa = PBXBuildFile; fileRef = E3BE45A32E90A9D70075AC22 /* dungeon_toolset.cc */; }; @@ -811,7 +814,6 @@ E3BE45AD2E90A9D70075AC22 /* dungeon_usage_tracker.cc in Sources */ = {isa = PBXBuildFile; fileRef = E3BE45A52E90A9D70075AC22 /* dungeon_usage_tracker.cc */; }; E3BE45AE2E90A9D70075AC22 /* dungeon_canvas_viewer.cc in Sources */ = {isa = PBXBuildFile; fileRef = E3BE45972E90A9D70075AC22 /* dungeon_canvas_viewer.cc */; }; E3BE45AF2E90A9D70075AC22 /* dungeon_object_selector.cc in Sources */ = {isa = PBXBuildFile; fileRef = E3BE459B2E90A9D70075AC22 /* dungeon_object_selector.cc */; }; - E3BE45B02E90A9D70075AC22 /* dungeon_renderer.cc in Sources */ = {isa = PBXBuildFile; fileRef = E3BE459D2E90A9D70075AC22 /* dungeon_renderer.cc */; }; E3BE45B12E90A9D70075AC22 /* dungeon_room_loader.cc in Sources */ = {isa = PBXBuildFile; fileRef = E3BE459F2E90A9D70075AC22 /* dungeon_room_loader.cc */; }; E3BE45B22E90A9D70075AC22 /* dungeon_object_interaction.cc in Sources */ = {isa = PBXBuildFile; fileRef = E3BE45992E90A9D70075AC22 /* dungeon_object_interaction.cc */; }; E3BE45B32E90A9D70075AC22 /* dungeon_toolset.cc in Sources */ = {isa = PBXBuildFile; fileRef = E3BE45A32E90A9D70075AC22 /* dungeon_toolset.cc */; }; @@ -907,6 +909,13 @@ remoteGlobalIDString = E2D187CF28A5673500D2B4F1; remoteInfo = "xcFramework-iOS"; }; + E3C0D1A12F2B1C8A00000001 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = E318E8492C5D74B700091322 /* SDL.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = A7D88A1423E2437C00DCD162; + remoteInfo = "Framework-iOS"; + }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -938,20 +947,25 @@ 05318E0E274C397200A8DE2E /* GameController.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameController.framework; path = System/Library/Frameworks/GameController.framework; sourceTree = SDKROOT; }; 07A82ED62139413C0078D120 /* imgui_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui_internal.h; path = ../../yaze/ext/imgui/imgui_internal.h; sourceTree = ""; }; 07A82ED72139413C0078D120 /* imgui_widgets.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_widgets.cpp; path = /Users/scawful/Code/yaze/ext/imgui/imgui_widgets.cpp; sourceTree = ""; }; + 104B9B65C53C4E71B4C15762 /* ios_platform_state.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ios_platform_state.mm; path = ../app/platform/ios/ios_platform_state.mm; sourceTree = SOURCE_ROOT; }; + 2DD3040220B14DA7AE5C9126 /* metal_renderer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = metal_renderer.mm; path = ../app/gfx/backend/metal_renderer.mm; sourceTree = SOURCE_ROOT; }; + 33E38666249F4B68BD81E8FD /* ios_host.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ios_host.h; path = ../app/platform/ios/ios_host.h; sourceTree = SOURCE_ROOT; }; + 4CBB29F4B39241868684DD52 /* ios_host.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ios_host.mm; path = ../app/platform/ios/ios_host.mm; sourceTree = SOURCE_ROOT; }; 5079822D257677DB0038A28D /* imgui_tables.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_tables.cpp; path = /Users/scawful/Code/yaze/ext/imgui/imgui_tables.cpp; sourceTree = ""; }; + 75242C7D5025428685194503 /* ios_platform_state.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ios_platform_state.h; path = ../app/platform/ios/ios_platform_state.h; sourceTree = SOURCE_ROOT; }; 8307E7C420E9F9C900473790 /* yaze.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = yaze.app; sourceTree = BUILT_PRODUCTS_DIR; }; 8307E7DA20E9F9C900473790 /* yaze.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = yaze.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 8309BD8E253CCAAA0045E2A1 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; + 8309BD8E253CCAAA0045E2A1 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 8309BDA0253CCBC10045E2A1 /* main.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; sourceTree = ""; }; - 8309BDB5253CCC9D0045E2A1 /* imgui_impl_metal.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = imgui_impl_metal.mm; path = "/Users/scawful/Code/xcode/metal-ios/imgui_impl_metal.mm"; sourceTree = ""; }; + 8309BDB5253CCC9D0045E2A1 /* imgui_impl_metal.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = imgui_impl_metal.mm; path = ../../ext/imgui/backends/imgui_impl_metal.mm; sourceTree = SOURCE_ROOT; }; 8309BDC5253CCCFE0045E2A1 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; 8309BDF7253CDAAE0045E2A1 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = ""; }; 8309BDF8253CDAAE0045E2A1 /* Info-iOS.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Info-iOS.plist"; sourceTree = ""; }; 8309BDFA253CDAAE0045E2A1 /* MainMenu.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = MainMenu.storyboard; sourceTree = ""; }; 8309BDFB253CDAAE0045E2A1 /* Info-macOS.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Info-macOS.plist"; sourceTree = ""; }; - 83BBE9E420EB46B900295997 /* Metal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Metal.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.4.sdk/System/Library/Frameworks/Metal.framework; sourceTree = DEVELOPER_DIR; }; - 83BBE9E620EB46BD00295997 /* MetalKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MetalKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.4.sdk/System/Library/Frameworks/MetalKit.framework; sourceTree = DEVELOPER_DIR; }; - 83BBE9E820EB46C100295997 /* ModelIO.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ModelIO.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.4.sdk/System/Library/Frameworks/ModelIO.framework; sourceTree = DEVELOPER_DIR; }; + 83BBE9E420EB46B900295997 /* Metal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Metal.framework; path = System/Library/Frameworks/Metal.framework; sourceTree = SDKROOT; }; + 83BBE9E620EB46BD00295997 /* MetalKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MetalKit.framework; path = System/Library/Frameworks/MetalKit.framework; sourceTree = SDKROOT; }; + 83BBE9E820EB46C100295997 /* ModelIO.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ModelIO.framework; path = System/Library/Frameworks/ModelIO.framework; sourceTree = SDKROOT; }; 83BBE9EA20EB471700295997 /* MetalKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MetalKit.framework; path = System/Library/Frameworks/MetalKit.framework; sourceTree = SDKROOT; }; 83BBE9EB20EB471700295997 /* Metal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Metal.framework; path = System/Library/Frameworks/Metal.framework; sourceTree = SDKROOT; }; 83BBE9EE20EB471C00295997 /* ModelIO.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ModelIO.framework; path = System/Library/Frameworks/ModelIO.framework; sourceTree = SDKROOT; }; @@ -959,6 +973,8 @@ 83BBEA0220EB54E700295997 /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = /Users/scawful/Code/yaze/ext/imgui/imgui_demo.cpp; sourceTree = ""; }; 83BBEA0320EB54E700295997 /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = /Users/scawful/Code/yaze/ext/imgui/imgui.cpp; sourceTree = ""; }; 83BBEA0420EB54E700295997 /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imconfig.h; sourceTree = ""; }; + C655B969EA0646E8AC97C6FA /* metal_renderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = metal_renderer.h; path = ../app/gfx/backend/metal_renderer.h; sourceTree = SOURCE_ROOT; }; + D329B1DE46A74E5783838504 /* ios_window_backend.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ios_window_backend.h; path = ../app/platform/ios/ios_window_backend.h; sourceTree = SOURCE_ROOT; }; E318D8472C59C08300091322 /* app_delegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = app_delegate.h; sourceTree = ""; }; E318D8482C59C08300091322 /* app_delegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = app_delegate.mm; sourceTree = ""; }; E318D84C2C59C08300091322 /* file_dialog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = file_dialog.h; sourceTree = ""; }; @@ -966,9 +982,9 @@ E318D84E2C59C08300091322 /* font_loader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = font_loader.cc; sourceTree = ""; }; E318D84F2C59C08300091322 /* font_loader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = font_loader.h; sourceTree = ""; }; E318D8502C59C08300091322 /* font_loader.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = font_loader.mm; sourceTree = ""; }; - E318D8552C59C08300091322 /* controller.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = controller.cc; sourceTree = ""; }; - E318D8562C59C08300091322 /* controller.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = controller.h; sourceTree = ""; }; - E318D8592C59C08300091322 /* project.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = project.h; sourceTree = ""; }; + E318D8552C59C08300091322 /* ../controller.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ../controller.cc; sourceTree = ""; }; + E318D8562C59C08300091322 /* ../controller.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ../controller.h; sourceTree = ""; }; + E318D8592C59C08300091322 /* ../../core/project.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ../../core/project.h; sourceTree = ""; }; E318D85C2C59C08300091322 /* assembly_editor.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = assembly_editor.cc; sourceTree = ""; }; E318D85D2C59C08300091322 /* assembly_editor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = assembly_editor.h; sourceTree = ""; }; E318D85E2C59C08300091322 /* memory_editor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = memory_editor.h; sourceTree = ""; }; @@ -1025,23 +1041,23 @@ E318D8B92C59C08300091322 /* bitmap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bitmap.h; sourceTree = ""; }; E318D8BA2C59C08300091322 /* compression.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = compression.cc; sourceTree = ""; }; E318D8BB2C59C08300091322 /* compression.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = compression.h; sourceTree = ""; }; - E318D8BC2C59C08300091322 /* scad_format.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = scad_format.cc; sourceTree = ""; }; - E318D8BD2C59C08300091322 /* scad_format.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = scad_format.h; sourceTree = ""; }; - E318D8BE2C59C08300091322 /* snes_color.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = snes_color.cc; sourceTree = ""; }; - E318D8BF2C59C08300091322 /* snes_color.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = snes_color.h; sourceTree = ""; }; - E318D8C02C59C08300091322 /* snes_palette.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = snes_palette.cc; sourceTree = ""; }; - E318D8C12C59C08300091322 /* snes_palette.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = snes_palette.h; sourceTree = ""; }; - E318D8C22C59C08300091322 /* snes_tile.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = snes_tile.cc; sourceTree = ""; }; - E318D8C32C59C08300091322 /* snes_tile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = snes_tile.h; sourceTree = ""; }; - E318D8C92C59C08300091322 /* canvas.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = canvas.cc; sourceTree = ""; }; - E318D8CA2C59C08300091322 /* canvas.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = canvas.h; sourceTree = ""; }; - E318D8CB2C59C08300091322 /* color.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = color.cc; sourceTree = ""; }; - E318D8CC2C59C08300091322 /* color.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = color.h; sourceTree = ""; }; - E318D8CD2C59C08300091322 /* icons.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = icons.h; sourceTree = ""; }; - E318D8CE2C59C08300091322 /* input.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = input.cc; sourceTree = ""; }; - E318D8CF2C59C08300091322 /* input.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = input.h; sourceTree = ""; }; - E318D8D02C59C08300091322 /* style.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = style.cc; sourceTree = ""; }; - E318D8D12C59C08300091322 /* style.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = style.h; sourceTree = ""; }; + E318D8BC2C59C08300091322 /* scad_format.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = util/scad_format.cc; sourceTree = ""; }; + E318D8BD2C59C08300091322 /* scad_format.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = util/scad_format.h; sourceTree = ""; }; + E318D8BE2C59C08300091322 /* snes_color.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = types/snes_color.cc; sourceTree = ""; }; + E318D8BF2C59C08300091322 /* snes_color.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = types/snes_color.h; sourceTree = ""; }; + E318D8C02C59C08300091322 /* snes_palette.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = types/snes_palette.cc; sourceTree = ""; }; + E318D8C12C59C08300091322 /* snes_palette.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = types/snes_palette.h; sourceTree = ""; }; + E318D8C22C59C08300091322 /* snes_tile.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = types/snes_tile.cc; sourceTree = ""; }; + E318D8C32C59C08300091322 /* snes_tile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = types/snes_tile.h; sourceTree = ""; }; + E318D8C92C59C08300091322 /* canvas.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = canvas/canvas.cc; sourceTree = ""; }; + E318D8CA2C59C08300091322 /* canvas.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = canvas/canvas.h; sourceTree = ""; }; + E318D8CB2C59C08300091322 /* color.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = core/color.cc; sourceTree = ""; }; + E318D8CC2C59C08300091322 /* color.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = core/color.h; sourceTree = ""; }; + E318D8CD2C59C08300091322 /* icons.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = core/icons.h; sourceTree = ""; }; + E318D8CE2C59C08300091322 /* input.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = core/input.cc; sourceTree = ""; }; + E318D8CF2C59C08300091322 /* input.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = core/input.h; sourceTree = ""; }; + E318D8D02C59C08300091322 /* style.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = core/style.cc; sourceTree = ""; }; + E318D8D12C59C08300091322 /* style.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = core/style.h; sourceTree = ""; }; E318D8D62C59C08300091322 /* object_renderer.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = object_renderer.cc; sourceTree = ""; }; E318D8D72C59C08300091322 /* object_renderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = object_renderer.h; sourceTree = ""; }; E318D8D82C59C08300091322 /* room_entrance.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = room_entrance.h; sourceTree = ""; }; @@ -1064,13 +1080,12 @@ E318D8EE2C59C08300091322 /* sprite.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sprite.cc; sourceTree = ""; }; E318D8EF2C59C08300091322 /* sprite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sprite.h; sourceTree = ""; }; E318D8F22C59C08300091322 /* common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = common.h; sourceTree = ""; }; - E318D8F62C59C08300091322 /* rom.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = rom.cc; sourceTree = ""; }; - E318D8F72C59C08300091322 /* rom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rom.h; sourceTree = ""; }; + E318D8F62C59C08300091322 /* rom.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ../rom/rom.cc; sourceTree = ""; }; + E318D8F72C59C08300091322 /* rom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ../rom/rom.h; sourceTree = ""; }; E318D9942C59CDF800091322 /* imgui_impl_sdl2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_impl_sdl2.cpp; path = ../../yaze/ext/imgui/backends/imgui_impl_sdl2.cpp; sourceTree = ""; }; E318D9972C59D0C400091322 /* imgui_impl_sdlrenderer2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_impl_sdlrenderer2.cpp; path = ../../yaze/ext/imgui/backends/imgui_impl_sdlrenderer2.cpp; sourceTree = ""; }; E318D99B2C59D0E500091322 /* imgui_stdlib.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_stdlib.cpp; path = ../../yaze/ext/imgui/misc/cpp/imgui_stdlib.cpp; sourceTree = ""; }; E318D99C2C59D0E500091322 /* imgui_stdlib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui_stdlib.h; path = ../../yaze/ext/imgui/misc/cpp/imgui_stdlib.h; sourceTree = ""; }; - E318D9A02C59DFD200091322 /* libpng16.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libpng16.a; path = "../../../opt/anaconda3/pkgs/libpng-1.6.37-ha441bb4_0/lib/libpng16.a"; sourceTree = ""; }; E318D9A32C5A4FBD00091322 /* algorithm_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = algorithm_test.cc; sourceTree = ""; }; E318D9A42C5A4FBD00091322 /* algorithm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = algorithm.h; sourceTree = ""; }; E318D9A52C5A4FBD00091322 /* BUILD.bazel */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = BUILD.bazel; sourceTree = ""; }; @@ -1690,7 +1705,7 @@ E318DC382C5A4FBD00091322 /* per_thread_sem.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = per_thread_sem.cc; sourceTree = ""; }; E318DC392C5A4FBD00091322 /* per_thread_sem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = per_thread_sem.h; sourceTree = ""; }; E318DC3A2C5A4FBD00091322 /* thread_pool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = thread_pool.h; sourceTree = ""; }; - E318DC3B2C5A4FBD00091322 /* waiter.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = waiter.cc; sourceTree = ""; }; + E318DC3B2C5A4FBD00091322 /* waiter_base.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = waiter_base.cc; sourceTree = ""; }; E318DC3C2C5A4FBD00091322 /* waiter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = waiter.h; sourceTree = ""; }; E318DC3E2C5A4FBD00091322 /* barrier_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = barrier_test.cc; sourceTree = ""; }; E318DC3F2C5A4FBD00091322 /* barrier.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = barrier.cc; sourceTree = ""; }; @@ -2398,7 +2413,6 @@ E318DF1F2C5A4FBD00091322 /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = ""; }; E318DF202C5A4FBD00091322 /* utility_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = utility_test.cc; sourceTree = ""; }; E318DF212C5A4FBD00091322 /* utility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = utility.h; sourceTree = ""; }; - E318DF232C5A4FBD00091322 /* abseil.podspec.gen.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = abseil.podspec.gen.py; sourceTree = ""; }; E318DF242C5A4FBD00091322 /* BUILD.bazel */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = BUILD.bazel; sourceTree = ""; }; E318DF252C5A4FBD00091322 /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = ""; }; E318E7952C5A548C00091322 /* png.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = png.c; sourceTree = ""; }; @@ -2424,10 +2438,10 @@ E318E7A92C5A548C00091322 /* pngwrite.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pngwrite.c; sourceTree = ""; }; E318E7AA2C5A548C00091322 /* pngwtran.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pngwtran.c; sourceTree = ""; }; E318E7AB2C5A548C00091322 /* pngwutil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pngwutil.c; sourceTree = ""; }; - E318E7CD2C5A55AE00091322 /* filter_neon.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; name = filter_neon.S; path = ../arm/filter_neon.S; sourceTree = ""; }; - E318E7CE2C5A55AE00091322 /* palette_neon_intrinsics.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = palette_neon_intrinsics.c; path = ../arm/palette_neon_intrinsics.c; sourceTree = ""; }; - E318E7CF2C5A55AE00091322 /* filter_neon_intrinsics.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = filter_neon_intrinsics.c; path = ../arm/filter_neon_intrinsics.c; sourceTree = ""; }; - E318E7D62C5A55C300091322 /* arm_init.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = arm_init.c; sourceTree = ""; }; + E318E7CD2C5A55AE00091322 /* filter_neon.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; name = filter_neon.S; path = arm/filter_neon.S; sourceTree = ""; }; + E318E7CE2C5A55AE00091322 /* palette_neon_intrinsics.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = palette_neon_intrinsics.c; path = arm/palette_neon_intrinsics.c; sourceTree = ""; }; + E318E7CF2C5A55AE00091322 /* filter_neon_intrinsics.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = filter_neon_intrinsics.c; path = arm/filter_neon_intrinsics.c; sourceTree = ""; }; + E318E7D62C5A55C300091322 /* arm/arm_init.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = arm/arm_init.c; sourceTree = ""; }; E318E7DA2C5A688A00091322 /* Cousine-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Cousine-Regular.ttf"; sourceTree = ""; }; E318E7DB2C5A688A00091322 /* DroidSans.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = DroidSans.ttf; sourceTree = ""; }; E318E7DC2C5A688A00091322 /* IBMPlexSansJP-Bold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "IBMPlexSansJP-Bold.ttf"; sourceTree = ""; }; @@ -2435,8 +2449,6 @@ E318E7DE2C5A688A00091322 /* MaterialIcons-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "MaterialIcons-Regular.ttf"; sourceTree = ""; }; E318E7DF2C5A688A00091322 /* NotoSansJP.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = NotoSansJP.ttf; sourceTree = ""; }; E318E7E02C5A688A00091322 /* Roboto-Medium.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Roboto-Medium.ttf"; sourceTree = ""; }; - E318E7E32C5A688A00091322 /* ow_toolset.zeml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ow_toolset.zeml; sourceTree = ""; }; - E318E8092C5B24CD00091322 /* ow_toolset.zeml */ = {isa = PBXFileReference; lastKnownFileType = text; path = ow_toolset.zeml; sourceTree = ""; }; E318E80A2C5B24CD00091322 /* overworld.zeml */ = {isa = PBXFileReference; lastKnownFileType = text; path = overworld.zeml; sourceTree = ""; }; E318E80C2C5B24CD00091322 /* Cousine-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Cousine-Regular.ttf"; sourceTree = ""; }; E318E80D2C5B24CD00091322 /* Karla-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Karla-Regular.ttf"; sourceTree = ""; }; @@ -2446,16 +2458,16 @@ E318E8112C5B24CD00091322 /* MaterialIcons-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "MaterialIcons-Regular.ttf"; sourceTree = ""; }; E318E8122C5B24CD00091322 /* NotoSansJP.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = NotoSansJP.ttf; sourceTree = ""; }; E318E8332C5BD8C000091322 /* UniformTypeIdentifiers.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UniformTypeIdentifiers.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS17.5.sdk/System/Library/Frameworks/UniformTypeIdentifiers.framework; sourceTree = DEVELOPER_DIR; }; - E318E8492C5D74B700091322 /* SDL.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = SDL.xcodeproj; path = ../lib/SDL/Xcode/SDL/SDL.xcodeproj; sourceTree = ""; }; + E318E8492C5D74B700091322 /* SDL.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = SDL.xcodeproj; path = ../../ext/SDL/Xcode/SDL/SDL.xcodeproj; sourceTree = ""; }; E318E8762C5D949200091322 /* yaze.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = yaze.png; sourceTree = ""; }; E318E8782C5D958400091322 /* Media.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Media.xcassets; sourceTree = ""; }; E318E87E2C609B3500091322 /* PencilKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PencilKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS17.5.sdk/System/Library/Frameworks/PencilKit.framework; sourceTree = DEVELOPER_DIR; }; E32BC4CA2CA4D7BC001F57A8 /* command_manager.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = command_manager.cc; sourceTree = ""; }; E346FD762E82E3D60044283C /* tile16_editor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = tile16_editor.h; sourceTree = ""; }; E346FD772E82E3D60044283C /* tile16_editor.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = tile16_editor.cc; sourceTree = ""; }; - E36971D92CE189EA00DEF2F6 /* project.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = project.cc; sourceTree = ""; }; - E37323B42D6A0BC800059101 /* text_editor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = text_editor.h; sourceTree = ""; }; - E37323B52D6A0BC800059101 /* text_editor.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = text_editor.cc; sourceTree = ""; }; + E36971D92CE189EA00DEF2F6 /* ../../core/project.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ../../core/project.cc; sourceTree = ""; }; + E37323B42D6A0BC800059101 /* text_editor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ../widgets/text_editor.h; sourceTree = ""; }; + E37323B52D6A0BC800059101 /* text_editor.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ../widgets/text_editor.cc; sourceTree = ""; }; E37323B72D6A0BE800059101 /* file_dialog.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = file_dialog.cc; sourceTree = ""; }; E37323BA2D6A0C1E00059101 /* bps.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = bps.h; sourceTree = ""; }; E37323BB2D6A0C1E00059101 /* bps.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = bps.cc; sourceTree = ""; }; @@ -2473,12 +2485,12 @@ E38A97F12C6C4CE3005FB662 /* command_manager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = command_manager.h; sourceTree = ""; }; E38A97F22C6C4CE3005FB662 /* extension_manager.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = extension_manager.cc; sourceTree = ""; }; E38A97F32C6C4CE3005FB662 /* extension_manager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = extension_manager.h; sourceTree = ""; }; - E38A97F42C6C4CE3005FB662 /* settings_editor.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = settings_editor.cc; sourceTree = ""; }; - E38A97F52C6C4CE3005FB662 /* settings_editor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = settings_editor.h; sourceTree = ""; }; + E38A97F42C6C4CE3005FB662 /* settings_panel.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ../ui/settings_panel.cc; sourceTree = ""; }; + E38A97F52C6C4CE3005FB662 /* settings_panel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ../ui/settings_panel.h; sourceTree = ""; }; E3A5CEE32CF61F1200259DE8 /* main.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = main.cc; sourceTree = ""; }; E3A5CEE82CF61F3100259DE8 /* editor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = editor.h; sourceTree = ""; }; - E3B8648F2C82144A00122951 /* asset_browser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = asset_browser.h; sourceTree = ""; }; - E3B864902C82144A00122951 /* asset_browser.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = asset_browser.cc; sourceTree = ""; }; + E3B8648F2C82144A00122951 /* asset_browser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ../widgets/asset_browser.h; sourceTree = ""; }; + E3B864902C82144A00122951 /* asset_browser.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ../widgets/asset_browser.cc; sourceTree = ""; }; E3BE44FB2E90A64D0075AC22 /* arena.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = arena.h; sourceTree = ""; }; E3BE44FC2E90A64D0075AC22 /* arena.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = arena.cc; sourceTree = ""; }; E3BE44FD2E90A64D0075AC22 /* atlas_renderer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = atlas_renderer.h; sourceTree = ""; }; @@ -2491,12 +2503,12 @@ E3BE45042E90A64D0075AC22 /* graphics_optimizer.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = graphics_optimizer.cc; sourceTree = ""; }; E3BE45052E90A64D0075AC22 /* memory_pool.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = memory_pool.h; sourceTree = ""; }; E3BE45062E90A64D0075AC22 /* memory_pool.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = memory_pool.cc; sourceTree = ""; }; - E3BE45072E90A64D0075AC22 /* performance/performance_dashboard.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = performance/performance_dashboard.h; sourceTree = ""; }; - E3BE45082E90A64D0075AC22 /* performance/performance_dashboard.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = performance/performance_dashboard.cc; sourceTree = ""; }; - E3BE45092E90A64D0075AC22 /* performance/performance_profiler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = performance/performance_profiler.h; sourceTree = ""; }; - E3BE450A2E90A64D0075AC22 /* performance/performance_profiler.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = performance/performance_profiler.cc; sourceTree = ""; }; - E3BE450B2E90A64D0075AC22 /* tilemap.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = tilemap.h; sourceTree = ""; }; - E3BE450C2E90A64D0075AC22 /* tilemap.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = tilemap.cc; sourceTree = ""; }; + E3BE45072E90A64D0075AC22 /* performance/performance_dashboard.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = debug/performance/performance_dashboard.h; sourceTree = ""; }; + E3BE45082E90A64D0075AC22 /* performance/performance_dashboard.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = debug/performance/performance_dashboard.cc; sourceTree = ""; }; + E3BE45092E90A64D0075AC22 /* performance/performance_profiler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = debug/performance/performance_profiler.h; sourceTree = ""; }; + E3BE450A2E90A64D0075AC22 /* performance/performance_profiler.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = debug/performance/performance_profiler.cc; sourceTree = ""; }; + E3BE450B2E90A64D0075AC22 /* tilemap.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = render/tilemap.h; sourceTree = ""; }; + E3BE450C2E90A64D0075AC22 /* tilemap.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = render/tilemap.cc; sourceTree = ""; }; E3BE451F2E90A6690075AC22 /* background_renderer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = background_renderer.h; sourceTree = ""; }; E3BE45202E90A6690075AC22 /* background_renderer.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = background_renderer.cc; sourceTree = ""; }; E3BE45212E90A6690075AC22 /* bpp_format_ui.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = bpp_format_ui.h; sourceTree = ""; }; @@ -2508,8 +2520,8 @@ E3BE45272E90A6690075AC22 /* canvas_interaction_handler.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = canvas_interaction_handler.cc; sourceTree = ""; }; E3BE45282E90A6690075AC22 /* canvas_modals.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = canvas_modals.h; sourceTree = ""; }; E3BE45292E90A6690075AC22 /* canvas_modals.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = canvas_modals.cc; sourceTree = ""; }; - E3BE452A2E90A6690075AC22 /* canvas_performance/performance_integration.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = canvas_performance/performance_integration.h; sourceTree = ""; }; - E3BE452B2E90A6690075AC22 /* canvas_performance/performance_integration.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = canvas_performance/performance_integration.cc; sourceTree = ""; }; + E3BE452A2E90A6690075AC22 /* canvas_performance_integration.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = canvas_performance_integration.h; sourceTree = ""; }; + E3BE452B2E90A6690075AC22 /* canvas_performance_integration.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = canvas_performance_integration.cc; sourceTree = ""; }; E3BE452C2E90A6690075AC22 /* canvas_usage_tracker.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = canvas_usage_tracker.h; sourceTree = ""; }; E3BE452D2E90A6690075AC22 /* canvas_usage_tracker.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = canvas_usage_tracker.cc; sourceTree = ""; }; E3BE452E2E90A6690075AC22 /* canvas_utils_moved.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = canvas_utils_moved.h; sourceTree = ""; }; @@ -2518,22 +2530,22 @@ E3BE45322E90A6690075AC22 /* canvas_utils.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = canvas_utils.cc; sourceTree = ""; }; E3BE45332E90A6690075AC22 /* enhanced_palette_editor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = enhanced_palette_editor.h; sourceTree = ""; }; E3BE45342E90A6690075AC22 /* enhanced_palette_editor.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = enhanced_palette_editor.cc; sourceTree = ""; }; - E3BE45352E90A6690075AC22 /* asset_browser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = asset_browser.h; sourceTree = ""; }; - E3BE45362E90A6690075AC22 /* asset_browser.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = asset_browser.cc; sourceTree = ""; }; + E3BE45352E90A6690075AC22 /* asset_browser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ../widgets/asset_browser.h; sourceTree = ""; }; + E3BE45362E90A6690075AC22 /* asset_browser.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ../widgets/asset_browser.cc; sourceTree = ""; }; E3BE45372E90A6690075AC22 /* component.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = component.h; sourceTree = ""; }; - E3BE45382E90A6690075AC22 /* text_editor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = text_editor.h; sourceTree = ""; }; - E3BE45392E90A6690075AC22 /* text_editor.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = text_editor.cc; sourceTree = ""; }; - E3BE453B2E90A6690075AC22 /* theme_manager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = theme_manager.h; sourceTree = ""; }; - E3BE453C2E90A6690075AC22 /* theme_manager.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = theme_manager.cc; sourceTree = ""; }; - E3BE453D2E90A6690075AC22 /* widget_id_registry.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = widget_id_registry.h; sourceTree = ""; }; - E3BE453E2E90A6690075AC22 /* widget_id_registry.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = widget_id_registry.cc; sourceTree = ""; }; - E3BE455D2E90A6E20075AC22 /* asar_wrapper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = asar_wrapper.h; sourceTree = ""; }; - E3BE455E2E90A6E20075AC22 /* asar_wrapper.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = asar_wrapper.cc; sourceTree = ""; }; - E3BE455F2E90A6E20075AC22 /* features.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = features.h; sourceTree = ""; }; - E3BE45602E90A6E20075AC22 /* widget_state_capture.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = widget_state_capture.h; sourceTree = ""; }; - E3BE45612E90A6E20075AC22 /* widget_state_capture.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = widget_state_capture.cc; sourceTree = ""; }; - E3BE45622E90A6E20075AC22 /* window.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = window.h; sourceTree = ""; }; - E3BE45632E90A6E20075AC22 /* window.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = window.cc; sourceTree = ""; }; + E3BE45382E90A6690075AC22 /* text_editor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ../widgets/text_editor.h; sourceTree = ""; }; + E3BE45392E90A6690075AC22 /* text_editor.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ../widgets/text_editor.cc; sourceTree = ""; }; + E3BE453B2E90A6690075AC22 /* theme_manager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = core/theme_manager.h; sourceTree = ""; }; + E3BE453C2E90A6690075AC22 /* theme_manager.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = core/theme_manager.cc; sourceTree = ""; }; + E3BE453D2E90A6690075AC22 /* automation/widget_id_registry.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = automation/widget_id_registry.h; sourceTree = ""; }; + E3BE453E2E90A6690075AC22 /* automation/widget_id_registry.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = automation/widget_id_registry.cc; sourceTree = ""; }; + E3BE455D2E90A6E20075AC22 /* ../../core/asar_wrapper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ../../core/asar_wrapper.h; sourceTree = ""; }; + E3BE455E2E90A6E20075AC22 /* ../../core/asar_wrapper.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ../../core/asar_wrapper.cc; sourceTree = ""; }; + E3BE455F2E90A6E20075AC22 /* ../../core/features.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ../../core/features.h; sourceTree = ""; }; + E3BE45602E90A6E20075AC22 /* ../gui/automation/widget_state_capture.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ../gui/automation/widget_state_capture.h; sourceTree = ""; }; + E3BE45612E90A6E20075AC22 /* ../gui/automation/widget_state_capture.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ../gui/automation/widget_state_capture.cc; sourceTree = ""; }; + E3BE45622E90A6E20075AC22 /* ../platform/window.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ../platform/window.h; sourceTree = ""; }; + E3BE45632E90A6E20075AC22 /* ../platform/window.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ../platform/window.cc; sourceTree = ""; }; E3BE456A2E90A6FB0075AC22 /* e2e_test_suite.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = e2e_test_suite.h; sourceTree = ""; }; E3BE456B2E90A6FB0075AC22 /* integrated_test_suite.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = integrated_test_suite.h; sourceTree = ""; }; E3BE456C2E90A6FB0075AC22 /* rom_dependent_test_suite.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = rom_dependent_test_suite.h; sourceTree = ""; }; @@ -2565,8 +2577,6 @@ E3BE45992E90A9D70075AC22 /* dungeon_object_interaction.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = dungeon_object_interaction.cc; sourceTree = ""; }; E3BE459A2E90A9D70075AC22 /* dungeon_object_selector.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dungeon_object_selector.h; sourceTree = ""; }; E3BE459B2E90A9D70075AC22 /* dungeon_object_selector.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = dungeon_object_selector.cc; sourceTree = ""; }; - E3BE459C2E90A9D70075AC22 /* dungeon_renderer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dungeon_renderer.h; sourceTree = ""; }; - E3BE459D2E90A9D70075AC22 /* dungeon_renderer.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = dungeon_renderer.cc; sourceTree = ""; }; E3BE459E2E90A9D70075AC22 /* dungeon_room_loader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dungeon_room_loader.h; sourceTree = ""; }; E3BE459F2E90A9D70075AC22 /* dungeon_room_loader.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = dungeon_room_loader.cc; sourceTree = ""; }; E3BE45A02E90A9D70075AC22 /* dungeon_room_selector.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dungeon_room_selector.h; sourceTree = ""; }; @@ -2578,8 +2588,8 @@ E3BE45B62E90A9E80075AC22 /* agent_chat_widget.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = agent_chat_widget.h; sourceTree = ""; }; E3BE45B72E90A9E80075AC22 /* agent_chat_widget.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = agent_chat_widget.cc; sourceTree = ""; }; E3BE45B82E90A9E80075AC22 /* history_manager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = history_manager.h; sourceTree = ""; }; - E3BE45B92E90A9E80075AC22 /* popup_manager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = popup_manager.h; sourceTree = ""; }; - E3BE45BA2E90A9E80075AC22 /* popup_manager.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = popup_manager.cc; sourceTree = ""; }; + E3BE45B92E90A9E80075AC22 /* popup_manager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ../ui/popup_manager.h; sourceTree = ""; }; + E3BE45BA2E90A9E80075AC22 /* popup_manager.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ../ui/popup_manager.cc; sourceTree = ""; }; E3BE45BB2E90A9E80075AC22 /* proposal_drawer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = proposal_drawer.h; sourceTree = ""; }; E3BE45BC2E90A9E80075AC22 /* proposal_drawer.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = proposal_drawer.cc; sourceTree = ""; }; E3BE45BD2E90A9E80075AC22 /* shortcut_manager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = shortcut_manager.h; sourceTree = ""; }; @@ -2592,6 +2602,7 @@ E3BE958C2C68379B008DD1E7 /* editor_manager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = editor_manager.h; sourceTree = ""; }; E3BE958E2C6837C8008DD1E7 /* overworld_editor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = overworld_editor.h; sourceTree = ""; }; E3BE958F2C6837C8008DD1E7 /* overworld_editor.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = overworld_editor.cc; sourceTree = ""; }; + E7546FEBFDF44B59A7DADD23 /* ios_window_backend.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ios_window_backend.mm; path = ../app/platform/ios/ios_window_backend.mm; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -2603,6 +2614,7 @@ 8309BD8F253CCAAA0045E2A1 /* UIKit.framework in Frameworks */, E318E87F2C609B3500091322 /* PencilKit.framework in Frameworks */, 83BBE9E720EB46BD00295997 /* MetalKit.framework in Frameworks */, + DCB32DF154774924A7112F61 /* ModelIO.framework in Frameworks */, 83BBE9E520EB46B900295997 /* Metal.framework in Frameworks */, E318E8342C5BD8C100091322 /* UniformTypeIdentifiers.framework in Frameworks */, ); @@ -2615,6 +2627,7 @@ E318E87A2C605D5700091322 /* SDL2.framework in Frameworks */, 8309BDC6253CCCFE0045E2A1 /* AppKit.framework in Frameworks */, 83BBE9EC20EB471700295997 /* MetalKit.framework in Frameworks */, + CE0FA109BFE4477C9D65C7CD /* ModelIO.framework in Frameworks */, 05318E0F274C397200A8DE2E /* GameController.framework in Frameworks */, 83BBE9ED20EB471700295997 /* Metal.framework in Frameworks */, ); @@ -2682,7 +2695,6 @@ children = ( E318E87E2C609B3500091322 /* PencilKit.framework */, E318E8332C5BD8C000091322 /* UniformTypeIdentifiers.framework */, - E318D9A02C59DFD200091322 /* libpng16.a */, 05318E0E274C397200A8DE2E /* GameController.framework */, 8309BDC5253CCCFE0045E2A1 /* AppKit.framework */, 8309BD8E253CCAAA0045E2A1 /* UIKit.framework */, @@ -2713,10 +2725,10 @@ 07A82ED72139413C0078D120 /* imgui_widgets.cpp */, ); name = imgui; - path = "/Users/scawful/Code/xcode/metal-ios"; - sourceTree = ""; + path = ../../ext/imgui; + sourceTree = ""; }; - E318D8512C59C08300091322 /* platform */ = { + E318D8512C59C08300091322 /* ../platform */ = { isa = PBXGroup; children = ( E3BE45772E90A7BE0075AC22 /* sdl_deleter.h */, @@ -2729,25 +2741,31 @@ E318D84E2C59C08300091322 /* font_loader.cc */, E318D84F2C59C08300091322 /* font_loader.h */, E318D8502C59C08300091322 /* font_loader.mm */, + 33E38666249F4B68BD81E8FD /* ios_host.h */, + 4CBB29F4B39241868684DD52 /* ios_host.mm */, + 75242C7D5025428685194503 /* ios_platform_state.h */, + 104B9B65C53C4E71B4C15762 /* ios_platform_state.mm */, + D329B1DE46A74E5783838504 /* ios_window_backend.h */, + E7546FEBFDF44B59A7DADD23 /* ios_window_backend.mm */, ); - path = platform; + path = ../platform; sourceTree = ""; }; E318D85B2C59C08300091322 /* core */ = { isa = PBXGroup; children = ( - E3BE455D2E90A6E20075AC22 /* asar_wrapper.h */, - E3BE455E2E90A6E20075AC22 /* asar_wrapper.cc */, - E3BE455F2E90A6E20075AC22 /* features.h */, - E3BE45602E90A6E20075AC22 /* widget_state_capture.h */, - E3BE45612E90A6E20075AC22 /* widget_state_capture.cc */, - E3BE45622E90A6E20075AC22 /* window.h */, - E3BE45632E90A6E20075AC22 /* window.cc */, - E318D8512C59C08300091322 /* platform */, - E318D8552C59C08300091322 /* controller.cc */, - E318D8562C59C08300091322 /* controller.h */, - E36971D92CE189EA00DEF2F6 /* project.cc */, - E318D8592C59C08300091322 /* project.h */, + E3BE455D2E90A6E20075AC22 /* ../../core/asar_wrapper.h */, + E3BE455E2E90A6E20075AC22 /* ../../core/asar_wrapper.cc */, + E3BE455F2E90A6E20075AC22 /* ../../core/features.h */, + E3BE45602E90A6E20075AC22 /* ../gui/automation/widget_state_capture.h */, + E3BE45612E90A6E20075AC22 /* ../gui/automation/widget_state_capture.cc */, + E3BE45622E90A6E20075AC22 /* ../platform/window.h */, + E3BE45632E90A6E20075AC22 /* ../platform/window.cc */, + E318D8512C59C08300091322 /* ../platform */, + E318D8552C59C08300091322 /* ../controller.cc */, + E318D8562C59C08300091322 /* ../controller.h */, + E36971D92CE189EA00DEF2F6 /* ../../core/project.cc */, + E318D8592C59C08300091322 /* ../../core/project.h */, ); path = core; sourceTree = ""; @@ -2771,8 +2789,6 @@ E3BE45992E90A9D70075AC22 /* dungeon_object_interaction.cc */, E3BE459A2E90A9D70075AC22 /* dungeon_object_selector.h */, E3BE459B2E90A9D70075AC22 /* dungeon_object_selector.cc */, - E3BE459C2E90A9D70075AC22 /* dungeon_renderer.h */, - E3BE459D2E90A9D70075AC22 /* dungeon_renderer.cc */, E3BE459E2E90A9D70075AC22 /* dungeon_room_loader.h */, E3BE459F2E90A9D70075AC22 /* dungeon_room_loader.cc */, E3BE45A02E90A9D70075AC22 /* dungeon_room_selector.h */, @@ -2962,6 +2978,8 @@ E3BE44FC2E90A64D0075AC22 /* arena.cc */, E3BE44FD2E90A64D0075AC22 /* atlas_renderer.h */, E3BE44FE2E90A64D0075AC22 /* atlas_renderer.cc */, + C655B969EA0646E8AC97C6FA /* metal_renderer.h */, + 2DD3040220B14DA7AE5C9126 /* metal_renderer.mm */, E3BE44FF2E90A64D0075AC22 /* background_buffer.h */, E3BE45002E90A64D0075AC22 /* background_buffer.cc */, E3BE45012E90A64D0075AC22 /* bpp_format_manager.h */, @@ -3007,8 +3025,8 @@ E3BE453A2E90A6690075AC22 /* modules */, E3BE453B2E90A6690075AC22 /* theme_manager.h */, E3BE453C2E90A6690075AC22 /* theme_manager.cc */, - E3BE453D2E90A6690075AC22 /* widget_id_registry.h */, - E3BE453E2E90A6690075AC22 /* widget_id_registry.cc */, + E3BE453D2E90A6690075AC22 /* automation/widget_id_registry.h */, + E3BE453E2E90A6690075AC22 /* automation/widget_id_registry.cc */, E3B864942C82146700122951 /* modules */, E318D8C92C59C08300091322 /* canvas.cc */, E318D8CA2C59C08300091322 /* canvas.h */, @@ -3088,7 +3106,7 @@ path = sprite; sourceTree = ""; }; - E318D8F32C59C08300091322 /* zelda3 */ = { + E318D8F32C59C08300091322 /* ../zelda3 */ = { isa = PBXGroup; children = ( E318D8DE2C59C08300091322 /* dungeon */, @@ -3100,7 +3118,7 @@ E37323CB2D6A0C4800059101 /* hyrule_magic.cc */, E37323CA2D6A0C4800059101 /* hyrule_magic.h */, ); - path = zelda3; + path = ../zelda3; sourceTree = ""; }; E318D8FA2C59C08300091322 /* app */ = { @@ -3112,7 +3130,7 @@ E3BE45722E90A6FB0075AC22 /* test */, E318D8C62C59C08300091322 /* gfx */, E318D8D42C59C08300091322 /* gui */, - E318D8F32C59C08300091322 /* zelda3 */, + E318D8F32C59C08300091322 /* ../zelda3 */, E318D8F62C59C08300091322 /* rom.cc */, E318D8F72C59C08300091322 /* rom.h */, E3A5CEE32CF61F1200259DE8 /* main.cc */, @@ -4095,7 +4113,7 @@ E318DC382C5A4FBD00091322 /* per_thread_sem.cc */, E318DC392C5A4FBD00091322 /* per_thread_sem.h */, E318DC3A2C5A4FBD00091322 /* thread_pool.h */, - E318DC3B2C5A4FBD00091322 /* waiter.cc */, + E318DC3B2C5A4FBD00091322 /* waiter_base.cc */, E318DC3C2C5A4FBD00091322 /* waiter.h */, ); path = internal; @@ -5109,19 +5127,18 @@ E318DEF82C5A4FBD00091322 /* time */, E318DF1C2C5A4FBD00091322 /* types */, E318DF222C5A4FBD00091322 /* utility */, - E318DF232C5A4FBD00091322 /* abseil.podspec.gen.py */, E318DF242C5A4FBD00091322 /* BUILD.bazel */, E318DF252C5A4FBD00091322 /* CMakeLists.txt */, ); name = absl; - path = "../lib/abseil-cpp/absl"; + path = "../../build/_deps/absl-src/absl"; sourceTree = ""; }; E318E7AC2C5A548C00091322 /* png */ = { isa = PBXGroup; children = ( E318E8072C5B24CC00091322 /* assets */, - E318E7D62C5A55C300091322 /* arm_init.c */, + E318E7D62C5A55C300091322 /* arm/arm_init.c */, E318E7CF2C5A55AE00091322 /* filter_neon_intrinsics.c */, E318E7CD2C5A55AE00091322 /* filter_neon.S */, E318E7CE2C5A55AE00091322 /* palette_neon_intrinsics.c */, @@ -5150,7 +5167,7 @@ E318E7AB2C5A548C00091322 /* pngwutil.c */, ); name = png; - path = ../../../lpng1643/png; + path = ../lib/libpng; sourceTree = ""; }; E318E7D92C5A687600091322 /* assets */ = { @@ -5181,7 +5198,6 @@ E318E7E42C5A688A00091322 /* layouts */ = { isa = PBXGroup; children = ( - E318E7E32C5A688A00091322 /* ow_toolset.zeml */, ); path = layouts; sourceTree = ""; @@ -5199,7 +5215,6 @@ isa = PBXGroup; children = ( E318E80A2C5B24CD00091322 /* overworld.zeml */, - E318E8092C5B24CD00091322 /* ow_toolset.zeml */, ); path = layouts; sourceTree = ""; @@ -5270,8 +5285,8 @@ E38A97F12C6C4CE3005FB662 /* command_manager.h */, E38A97F22C6C4CE3005FB662 /* extension_manager.cc */, E38A97F32C6C4CE3005FB662 /* extension_manager.h */, - E38A97F42C6C4CE3005FB662 /* settings_editor.cc */, - E38A97F52C6C4CE3005FB662 /* settings_editor.h */, + E38A97F42C6C4CE3005FB662 /* settings_panel.cc */, + E38A97F52C6C4CE3005FB662 /* settings_panel.h */, ); path = system; sourceTree = ""; @@ -5297,8 +5312,8 @@ E3BE45272E90A6690075AC22 /* canvas_interaction_handler.cc */, E3BE45282E90A6690075AC22 /* canvas_modals.h */, E3BE45292E90A6690075AC22 /* canvas_modals.cc */, - E3BE452A2E90A6690075AC22 /* canvas_performance/performance_integration.h */, - E3BE452B2E90A6690075AC22 /* canvas_performance/performance_integration.cc */, + E3BE452A2E90A6690075AC22 /* canvas_performance_integration.h */, + E3BE452B2E90A6690075AC22 /* canvas_performance_integration.cc */, E3BE452C2E90A6690075AC22 /* canvas_usage_tracker.h */, E3BE452D2E90A6690075AC22 /* canvas_usage_tracker.cc */, E3BE452E2E90A6690075AC22 /* canvas_utils_moved.h */, @@ -5349,6 +5364,7 @@ buildRules = ( ); dependencies = ( + E3C0D1A12F2B1C8A00000002 /* PBXTargetDependency */, ); name = yaze_ios; productName = "imguiex iOS"; @@ -5515,7 +5531,6 @@ E318E8722C5D757800091322 /* NotoSansJP.ttf in Resources */, E318E8772C5D949200091322 /* yaze.png in Resources */, E318E8732C5D757800091322 /* Roboto-Medium.ttf in Resources */, - E318E8752C5D757800091322 /* ow_toolset.zeml in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -5527,13 +5542,11 @@ E318E7E82C5A688A00091322 /* DroidSans.ttf in Resources */, E318E7EA2C5A688A00091322 /* IBMPlexSansJP-Bold.ttf in Resources */, 8309BE04253CDAB60045E2A1 /* MainMenu.storyboard in Resources */, - E318E7422C5A4FCA00091322 /* abseil.podspec.gen.py in Resources */, E3BE45752E90A6FB0075AC22 /* test.cmake in Resources */, E3BE454E2E90A6690075AC22 /* canvas.cmake in Resources */, E318E7EE2C5A688A00091322 /* MaterialIcons-Regular.ttf in Resources */, E318E7F22C5A688A00091322 /* Roboto-Medium.ttf in Resources */, E318E7EC2C5A688A00091322 /* Karla-Regular.ttf in Resources */, - E318E7F62C5A688A00091322 /* ow_toolset.zeml in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -5553,6 +5566,10 @@ E318E1492C5A4FC100091322 /* float_conversion.cc in Sources */, E318E2012C5A4FC200091322 /* graphcycles.cc in Sources */, E318D9012C59C08300091322 /* file_dialog.mm in Sources */, + 2C9383FF416B47B6B4ED5B3B /* ios_host.mm in Sources */, + 3D7E0DFF523646C292410DF5 /* ios_platform_state.mm in Sources */, + C29B39EDC05548EB9CC18619 /* ios_window_backend.mm in Sources */, + 694B819145E646BC8601D320 /* metal_renderer.mm in Sources */, E318D9752C59C08300091322 /* tracker.cc in Sources */, 8309BDBB253CCCAD0045E2A1 /* imgui_impl_metal.mm in Sources */, E318E0012C5A4FBF00091322 /* stacktrace_powerpc-inl.inc in Sources */, @@ -5625,9 +5642,9 @@ E318E7C32C5A548C00091322 /* pngtrans.c in Sources */, E318E7B32C5A548C00091322 /* pngmem.c in Sources */, E318E02D2C5A4FBF00091322 /* commandlineflag.cc in Sources */, - E3BE45642E90A6E20075AC22 /* window.cc in Sources */, - E3BE45652E90A6E20075AC22 /* widget_state_capture.cc in Sources */, - E3BE45662E90A6E20075AC22 /* asar_wrapper.cc in Sources */, + E3BE45642E90A6E20075AC22 /* ../platform/window.cc in Sources */, + E3BE45652E90A6E20075AC22 /* ../gui/automation/widget_state_capture.cc in Sources */, + E3BE45662E90A6E20075AC22 /* ../../core/asar_wrapper.cc in Sources */, E318D97D2C59C08300091322 /* title_screen.cc in Sources */, E318DF512C5A4FBE00091322 /* spinlock_linux.inc in Sources */, E318E7D22C5A55AE00091322 /* palette_neon_intrinsics.c in Sources */, @@ -5641,7 +5658,7 @@ E37323C72D6A0C1E00059101 /* bps.cc in Sources */, E37323C82D6A0C1E00059101 /* flag.cc in Sources */, E37323C92D6A0C1E00059101 /* hex.cc in Sources */, - E318E2072C5A4FC200091322 /* waiter.cc in Sources */, + E318E2072C5A4FC200091322 /* waiter_base.cc in Sources */, E318E09F2C5A4FC000091322 /* int128_have_intrinsic.inc in Sources */, E318DF5F2C5A4FBE00091322 /* strerror.cc in Sources */, E318E1592C5A4FC100091322 /* charconv_bigint.cc in Sources */, @@ -5675,7 +5692,7 @@ E318DFFB2C5A4FBF00091322 /* stacktrace_arm-inl.inc in Sources */, E318E2292C5A4FC200091322 /* time_zone_fixed.cc in Sources */, E318E12F2C5A4FC100091322 /* status_payload_printer.cc in Sources */, - E36971DB2CE189EA00DEF2F6 /* project.cc in Sources */, + E36971DB2CE189EA00DEF2F6 /* ../../core/project.cc in Sources */, E318E1792C5A4FC100091322 /* cordz_functions.cc in Sources */, E318E0212C5A4FBF00091322 /* symbolize_elf.inc in Sources */, E318D94B2C59C08300091322 /* ppu.cc in Sources */, @@ -5741,7 +5758,7 @@ E3BE45482E90A6690075AC22 /* background_renderer.cc in Sources */, E3BE45492E90A6690075AC22 /* text_editor.cc in Sources */, E3BE454A2E90A6690075AC22 /* canvas_performance/performance_integration.cc in Sources */, - E3BE454B2E90A6690075AC22 /* widget_id_registry.cc in Sources */, + E3BE454B2E90A6690075AC22 /* automation/widget_id_registry.cc in Sources */, E3BE454C2E90A6690075AC22 /* canvas_context_menu.cc in Sources */, E318D9392C59C08300091322 /* dsp.cc in Sources */, E318D9632C59C08300091322 /* canvas.cc in Sources */, @@ -5749,7 +5766,7 @@ E318E1092C5A4FC100091322 /* discrete_distribution.cc in Sources */, E318D9572C59C08300091322 /* scad_format.cc in Sources */, E318E0E32C5A4FC000091322 /* randen_hwaes.cc in Sources */, - E318D9092C59C08300091322 /* controller.cc in Sources */, + E318D9092C59C08300091322 /* ../controller.cc in Sources */, E318D9372C59C08300091322 /* apu.cc in Sources */, E318E22D2C5A4FC300091322 /* time_zone_format.cc in Sources */, E318E6FF2C5A4FC900091322 /* civil_time.cc in Sources */, @@ -5778,7 +5795,7 @@ E318E7BB2C5A548C00091322 /* pngrtran.c in Sources */, E318D9352C59C08300091322 /* instructions.cc in Sources */, E318E0ED2C5A4FC000091322 /* randen.cc in Sources */, - E38A97F82C6C4CE3005FB662 /* settings_editor.cc in Sources */, + E38A97F82C6C4CE3005FB662 /* settings_panel.cc in Sources */, E318E7052C5A4FC900091322 /* clock.cc in Sources */, E318DFA72C5A4FBE00091322 /* hashtablez_sampler.cc in Sources */, E318E1F92C5A4FC200091322 /* substitute.cc in Sources */, @@ -5794,7 +5811,7 @@ E318E0292C5A4FBF00091322 /* symbolize_win32.inc in Sources */, E318E0392C5A4FBF00091322 /* program_name.cc in Sources */, E318E0572C5A4FBF00091322 /* marshalling.cc in Sources */, - E318E7D72C5A55C300091322 /* arm_init.c in Sources */, + E318E7D72C5A55C300091322 /* arm/arm_init.c in Sources */, E346FD782E82E3D60044283C /* tile16_editor.cc in Sources */, E318E21D2C5A4FC200091322 /* mutex.cc in Sources */, E318E7B72C5A548C00091322 /* pngread.c in Sources */, @@ -5805,7 +5822,6 @@ E318E1B32C5A4FC200091322 /* charconv.cc in Sources */, E3BE45A62E90A9D70075AC22 /* dungeon_canvas_viewer.cc in Sources */, E3BE45A72E90A9D70075AC22 /* dungeon_object_selector.cc in Sources */, - E3BE45A82E90A9D70075AC22 /* dungeon_renderer.cc in Sources */, E3BE45A92E90A9D70075AC22 /* dungeon_room_loader.cc in Sources */, E3BE45AA2E90A9D70075AC22 /* dungeon_object_interaction.cc in Sources */, E3BE45AB2E90A9D70075AC22 /* dungeon_toolset.cc in Sources */, @@ -5864,7 +5880,7 @@ E318E1AA2C5A4FC200091322 /* ascii_test.cc in Sources */, E318E1E02C5A4FC200091322 /* str_join_benchmark.cc in Sources */, E318E7182C5A4FC900091322 /* time_test.cc in Sources */, - E318E2082C5A4FC200091322 /* waiter.cc in Sources */, + E318E2082C5A4FC200091322 /* waiter_base.cc in Sources */, E318E15E2C5A4FC100091322 /* charconv_parse.cc in Sources */, E318E04C2C5A4FBF00091322 /* flag_benchmark.cc in Sources */, E318E1A62C5A4FC200091322 /* utf8.cc in Sources */, @@ -5885,7 +5901,6 @@ E318E7222C5A4FC900091322 /* any_test.cc in Sources */, E3BE45AE2E90A9D70075AC22 /* dungeon_canvas_viewer.cc in Sources */, E3BE45AF2E90A9D70075AC22 /* dungeon_object_selector.cc in Sources */, - E3BE45B02E90A9D70075AC22 /* dungeon_renderer.cc in Sources */, E3BE45B12E90A9D70075AC22 /* dungeon_room_loader.cc in Sources */, E3BE45B22E90A9D70075AC22 /* dungeon_object_interaction.cc in Sources */, E3BE45B32E90A9D70075AC22 /* dungeon_toolset.cc in Sources */, @@ -5893,6 +5908,7 @@ E3BE45B52E90A9D70075AC22 /* dungeon_usage_tracker.cc in Sources */, E318E1FC2C5A4FC200091322 /* create_thread_identity.cc in Sources */, 8309BDBE253CCCB60045E2A1 /* imgui_impl_metal.mm in Sources */, + 95413E18FB9F4DDF9CE960C2 /* metal_renderer.mm in Sources */, E318DF3A2C5A4FBE00091322 /* endian_test.cc in Sources */, E318D91E2C59C08300091322 /* message_editor.cc in Sources */, E318E7042C5A4FC900091322 /* clock_test.cc in Sources */, @@ -5976,7 +5992,7 @@ E318DF402C5A4FBE00091322 /* fast_type_id_test.cc in Sources */, E318E16A2C5A4FC100091322 /* cord_rep_btree_reader.cc in Sources */, E318E11A2C5A4FC100091322 /* mock_distributions_test.cc in Sources */, - E36971DA2CE189EA00DEF2F6 /* project.cc in Sources */, + E36971DA2CE189EA00DEF2F6 /* ../../core/project.cc in Sources */, E318E0602C5A4FBF00091322 /* reflection.cc in Sources */, E318DF882C5A4FBE00091322 /* log_severity.cc in Sources */, E318DF302C5A4FBD00091322 /* equal_benchmark.cc in Sources */, @@ -5986,7 +6002,7 @@ E318E7B62C5A548C00091322 /* pngpread.c in Sources */, E318D9582C59C08300091322 /* scad_format.cc in Sources */, E318DFF02C5A4FBF00091322 /* demangle.cc in Sources */, - E318D90A2C59C08300091322 /* controller.cc in Sources */, + E318D90A2C59C08300091322 /* ../controller.cc in Sources */, E318E1B82C5A4FC200091322 /* cord_analysis.cc in Sources */, E318E1BA2C5A4FC200091322 /* cord_buffer_test.cc in Sources */, E318DFEE2C5A4FBF00091322 /* demangle_test.cc in Sources */, @@ -6042,7 +6058,7 @@ E318D9482C59C08300091322 /* dma.cc in Sources */, E318E16E2C5A4FC100091322 /* cord_rep_btree.cc in Sources */, E318E0D82C5A4FC000091322 /* pool_urbg_test.cc in Sources */, - E318E7D82C5A55C300091322 /* arm_init.c in Sources */, + E318E7D82C5A55C300091322 /* arm/arm_init.c in Sources */, E318E0782C5A4FC000091322 /* hash.cc in Sources */, E318E11C2C5A4FC100091322 /* mocking_bit_gen_test.cc in Sources */, E318E18E2C5A4FC100091322 /* escaping.cc in Sources */, @@ -6200,7 +6216,7 @@ E3BE45582E90A6690075AC22 /* background_renderer.cc in Sources */, E3BE45592E90A6690075AC22 /* text_editor.cc in Sources */, E3BE455A2E90A6690075AC22 /* canvas_performance/performance_integration.cc in Sources */, - E3BE455B2E90A6690075AC22 /* widget_id_registry.cc in Sources */, + E3BE455B2E90A6690075AC22 /* automation/widget_id_registry.cc in Sources */, E3BE455C2E90A6690075AC22 /* canvas_context_menu.cc in Sources */, E318D93C2C59C08300091322 /* spc700.cc in Sources */, E318E2322C5A4FC300091322 /* time_zone_impl.cc in Sources */, @@ -6299,9 +6315,9 @@ E318E1262C5A4FC100091322 /* uniform_int_distribution_test.cc in Sources */, E318E1562C5A4FC100091322 /* char_map_test.cc in Sources */, E318E03A2C5A4FBF00091322 /* program_name.cc in Sources */, - E3BE45672E90A6E20075AC22 /* window.cc in Sources */, - E3BE45682E90A6E20075AC22 /* widget_state_capture.cc in Sources */, - E3BE45692E90A6E20075AC22 /* asar_wrapper.cc in Sources */, + E3BE45672E90A6E20075AC22 /* ../platform/window.cc in Sources */, + E3BE45682E90A6E20075AC22 /* ../gui/automation/widget_state_capture.cc in Sources */, + E3BE45692E90A6E20075AC22 /* ../../core/asar_wrapper.cc in Sources */, E318E1842C5A4FC100091322 /* cordz_info.cc in Sources */, E318E7BC2C5A548C00091322 /* pngrtran.c in Sources */, E318E1802C5A4FC100091322 /* cordz_info_statistics_test.cc in Sources */, @@ -6340,6 +6356,14 @@ }; /* End PBXSourcesBuildPhase section */ +/* Begin PBXTargetDependency section */ + E3C0D1A12F2B1C8A00000002 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "Framework-iOS"; + targetProxy = E3C0D1A12F2B1C8A00000001 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + /* Begin XCBuildConfiguration section */ 8307E7EE20E9F9C900473790 /* Debug */ = { isa = XCBuildConfiguration; @@ -6486,7 +6510,17 @@ "@executable_path/Frameworks", ); MARKETING_VERSION = 0.2.0; - OTHER_LDFLAGS = ""; + OTHER_LDFLAGS = ( + "$(inherited)", + "-framework", + UIKit, + "-framework", + Metal, + "-framework", + MetalKit, + "-framework", + ModelIO, + ); PRODUCT_BUNDLE_IDENTIFIER = "org.halext.yaze-ios"; PRODUCT_NAME = yaze; SDKROOT = iphoneos; @@ -6494,18 +6528,21 @@ SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; SYSTEM_HEADER_SEARCH_PATHS = ( - "\"$(SRCROOT)/../lib/SDL/include\"", - /Users/scawful/Code/lpng1643, + "\"$(SRCROOT)/../../ext/SDL/include\"", + "\"$(SRCROOT)/../lib/libpng\"", "\"$(SRCROOT)/../../incl\"", + "\"$(SRCROOT)/../../build/_deps/nlohmann_json-src/include\"", ); TARGETED_DEVICE_FAMILY = "1,2"; USER_HEADER_SEARCH_PATHS = ( "\"$(SRCROOT)/../app\"", - "\"$(SRCROOT)/../lib/abseil-cpp\"", + "\"$(SRCROOT)/../../build/_deps/absl-src\"", + "\"$(SRCROOT)/../../build/_deps/nlohmann_json-src/include\"", "\"$(SRCROOT)/../\"", "\"$(SRCROOT)/../lib\"", - "\"$(SRCROOT)/../lib/abseil-cpp\"", - "\"$(SRCROOT)/../lib/imgui\"", + "\"$(SRCROOT)/../../build/_deps/absl-src\"", + "\"$(SRCROOT)/../../ext\"", + "\"$(SRCROOT)/../../ext/imgui\"", "\"/Users/scawful/Code/yaze/build\"", ); }; @@ -6534,25 +6571,38 @@ "@executable_path/Frameworks", ); MARKETING_VERSION = 0.2.0; - OTHER_LDFLAGS = ""; + OTHER_LDFLAGS = ( + "$(inherited)", + "-framework", + UIKit, + "-framework", + Metal, + "-framework", + MetalKit, + "-framework", + ModelIO, + ); PRODUCT_BUNDLE_IDENTIFIER = "org.halext.yaze-ios"; PRODUCT_NAME = yaze; SDKROOT = iphoneos; SWIFT_OBJC_BRIDGING_HEADER = "iOS/yaze_ios-Bridging-Header.h"; SWIFT_VERSION = 5.0; SYSTEM_HEADER_SEARCH_PATHS = ( - "\"$(SRCROOT)/../lib/SDL/include\"", - /Users/scawful/Code/lpng1643, + "\"$(SRCROOT)/../../ext/SDL/include\"", + "\"$(SRCROOT)/../lib/libpng\"", "\"$(SRCROOT)/../../incl\"", + "\"$(SRCROOT)/../../build/_deps/nlohmann_json-src/include\"", ); TARGETED_DEVICE_FAMILY = "1,2"; USER_HEADER_SEARCH_PATHS = ( "\"$(SRCROOT)/../app\"", - "\"$(SRCROOT)/../lib/abseil-cpp\"", + "\"$(SRCROOT)/../../build/_deps/absl-src\"", + "\"$(SRCROOT)/../../build/_deps/nlohmann_json-src/include\"", "\"$(SRCROOT)/../\"", "\"$(SRCROOT)/../lib\"", - "\"$(SRCROOT)/../lib/abseil-cpp\"", - "\"$(SRCROOT)/../lib/imgui\"", + "\"$(SRCROOT)/../../build/_deps/absl-src\"", + "\"$(SRCROOT)/../../ext\"", + "\"$(SRCROOT)/../../ext/imgui\"", "\"/Users/scawful/Code/yaze/build\"", ); VALIDATE_PRODUCT = YES; diff --git a/src/util/file_util.cc b/src/util/file_util.cc index 56fb35b2..534eb3f0 100644 --- a/src/util/file_util.cc +++ b/src/util/file_util.cc @@ -71,7 +71,10 @@ std::string GetResourcePath(const std::string& resource_path) { #ifdef __APPLE__ #if TARGET_OS_IOS == 1 const std::string kBundlePath = GetBundleResourcePath(); - return kBundlePath + resource_path; + if (resource_path.rfind("assets/", 0) == 0) { + return kBundlePath + resource_path; + } + return kBundlePath + "assets/" + resource_path; #else return GetBundleResourcePath() + "Contents/Resources/" + resource_path; #endif @@ -81,9 +84,18 @@ std::string GetResourcePath(const std::string& resource_path) { #endif } +FileDialogOptions MakeRomFileDialogOptions(bool include_all_files) { + FileDialogOptions options; + options.filters.push_back({"ROM Files", "sfc,smc"}); + if (include_all_files) { + options.filters.push_back({"All Files", "*"}); + } + return options; +} + // Note: FileDialogWrapper implementations are in // src/app/platform/file_dialog.mm (platform-specific implementations to avoid // duplicate symbols) } // namespace util -} // namespace yaze \ No newline at end of file +} // namespace yaze diff --git a/src/util/file_util.h b/src/util/file_util.h index 54eb1552..8e14660a 100644 --- a/src/util/file_util.h +++ b/src/util/file_util.h @@ -1,12 +1,22 @@ #ifndef YAZE_UTIL_FILE_UTIL_H_ #define YAZE_UTIL_FILE_UTIL_H_ +#include #include #include namespace yaze { namespace util { +struct FileDialogFilter { + std::string label; + std::string spec; // Comma-delimited extensions (e.g., "sfc,smc") or "*". +}; + +struct FileDialogOptions { + std::vector filters; +}; + class FileDialogWrapper { public: /** @@ -14,6 +24,10 @@ class FileDialogWrapper { * filepath. Uses global feature flag to choose implementation. */ static std::string ShowOpenFileDialog(); + static std::string ShowOpenFileDialog(const FileDialogOptions& options); + static void ShowOpenFileDialogAsync( + const FileDialogOptions& options, + std::function callback); /** * @brief ShowOpenFolderDialog opens a file dialog and returns the selected @@ -46,6 +60,8 @@ class FileDialogWrapper { const std::string& folder_path); }; +FileDialogOptions MakeRomFileDialogOptions(bool include_all_files = true); + /** * @brief GetBundleResourcePath returns the path to the bundle resource * directory. Specific to MacOS. diff --git a/src/util/platform_paths.cc b/src/util/platform_paths.cc index 2003f0ba..641f21fb 100644 --- a/src/util/platform_paths.cc +++ b/src/util/platform_paths.cc @@ -14,10 +14,15 @@ #include // For PATH_MAX #ifdef __APPLE__ +#include #include // For _NSGetExecutablePath #endif #endif +#if defined(__APPLE__) && defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE +#define YAZE_APPLE_MOBILE 1 +#endif + namespace yaze { namespace util { @@ -76,7 +81,28 @@ std::filesystem::path PlatformPaths::GetHomeDirectory() { } absl::StatusOr PlatformPaths::GetAppDataDirectory() { -#ifdef _WIN32 +#if defined(YAZE_IOS) || defined(YAZE_APPLE_MOBILE) + std::filesystem::path home = GetHomeDirectory(); + if (home.empty() || home == ".") { + std::error_code ec; + auto temp = std::filesystem::temp_directory_path(ec); + if (!ec) { + home = temp; + } + } + + std::filesystem::path app_data = + home / "Library" / "Application Support" / "yaze"; + auto status = EnsureDirectoryExists(app_data); + if (!status.ok()) { + app_data = home / "Documents" / "yaze"; + status = EnsureDirectoryExists(app_data); + if (!status.ok()) { + return status; + } + } + return app_data; +#elif defined(_WIN32) wchar_t path[MAX_PATH]; if (SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, 0, path))) { std::filesystem::path app_data = std::filesystem::path(path) / "yaze"; @@ -127,7 +153,19 @@ absl::StatusOr PlatformPaths::GetConfigDirectory() { } absl::StatusOr PlatformPaths::GetUserDocumentsDirectory() { -#ifdef _WIN32 +#if defined(YAZE_IOS) || defined(YAZE_APPLE_MOBILE) + std::filesystem::path home = GetHomeDirectory(); + std::filesystem::path docs_dir = home / "Documents" / "Yaze"; + auto status = EnsureDirectoryExists(docs_dir); + if (!status.ok()) { + docs_dir = home / "Yaze"; + status = EnsureDirectoryExists(docs_dir); + if (!status.ok()) { + return status; + } + } + return docs_dir; +#elif defined(_WIN32) wchar_t path[MAX_PATH]; if (SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_PERSONAL, NULL, 0, path))) { std::filesystem::path docs_dir = std::filesystem::path(path) / "Yaze"; diff --git a/src/util/util.cmake b/src/util/util.cmake index 137e8ff1..b5fd3e50 100644 --- a/src/util/util.cmake +++ b/src/util/util.cmake @@ -129,8 +129,10 @@ if(UNIX AND NOT APPLE) if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9.0) target_link_libraries(yaze_util PUBLIC stdc++fs) endif() -elseif(APPLE) +elseif(YAZE_PLATFORM_MACOS) target_compile_definitions(yaze_util PRIVATE MACOS) +elseif(YAZE_PLATFORM_IOS) + target_compile_definitions(yaze_util PRIVATE YAZE_IOS) elseif(WIN32) target_compile_definitions(yaze_util PRIVATE WINDOWS) diff --git a/src/zelda3/zelda3_library.cmake b/src/zelda3/zelda3_library.cmake index f45e21dc..f1d96432 100644 --- a/src/zelda3/zelda3_library.cmake +++ b/src/zelda3/zelda3_library.cmake @@ -99,8 +99,10 @@ set_target_properties(yaze_zelda3 PROPERTIES # Platform-specific compile definitions if(UNIX AND NOT APPLE) target_compile_definitions(yaze_zelda3 PRIVATE linux stricmp=strcasecmp) -elseif(APPLE) +elseif(YAZE_PLATFORM_MACOS) target_compile_definitions(yaze_zelda3 PRIVATE MACOS) +elseif(YAZE_PLATFORM_IOS) + target_compile_definitions(yaze_zelda3 PRIVATE YAZE_IOS) elseif(WIN32) target_compile_definitions(yaze_zelda3 PRIVATE WINDOWS) endif()