mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-07-04 19:25:43 -04:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 692c04e936 | |||
| e17d0f21fc | |||
| 91e77b1051 | |||
| 0b1a2c10b6 | |||
| e855e6471f | |||
| 848f635798 |
+9
-50
@@ -126,33 +126,6 @@ set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
|
|||||||
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||||
set_property(GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER "_cmake")
|
set_property(GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER "_cmake")
|
||||||
|
|
||||||
option(ENABLE_ASAN "Enable AddressSanitizer" OFF)
|
|
||||||
if (ENABLE_ASAN)
|
|
||||||
if (CMAKE_C_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC" AND
|
|
||||||
CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC")
|
|
||||||
add_compile_options($<$<COMPILE_LANGUAGE:C,CXX>:/fsanitize=address>)
|
|
||||||
add_link_options(/fsanitize=address /INCREMENTAL:NO)
|
|
||||||
set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "ProgramDatabase")
|
|
||||||
foreach (_lang C CXX)
|
|
||||||
foreach (_rtc_flag /RTC1 /RTCc /RTCs /RTCu)
|
|
||||||
string(REPLACE "${_rtc_flag}" "" CMAKE_${_lang}_FLAGS_DEBUG "${CMAKE_${_lang}_FLAGS_DEBUG}")
|
|
||||||
endforeach ()
|
|
||||||
endforeach ()
|
|
||||||
elseif (CMAKE_C_COMPILER_FRONTEND_VARIANT STREQUAL "GNU" AND
|
|
||||||
CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "GNU")
|
|
||||||
add_compile_options(
|
|
||||||
$<$<COMPILE_LANGUAGE:C,CXX,OBJC,OBJCXX>:-fsanitize=address>
|
|
||||||
$<$<COMPILE_LANGUAGE:C,CXX,OBJC,OBJCXX>:-fno-omit-frame-pointer>
|
|
||||||
)
|
|
||||||
add_link_options(-fsanitize=address)
|
|
||||||
else ()
|
|
||||||
message(FATAL_ERROR "ENABLE_ASAN requires GNU-like or MSVC-like C/C++ compiler frontends")
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
add_compile_definitions(NDEBUG_SANITIZER) # Avoids absl issue with SwissTable debug code
|
|
||||||
message(STATUS "dusklight: Enabled AddressSanitizer")
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
if (CMAKE_SYSTEM_NAME STREQUAL Linux)
|
if (CMAKE_SYSTEM_NAME STREQUAL Linux)
|
||||||
set(DAWN_USE_WAYLAND ON CACHE BOOL "Enable support for Wayland surface" FORCE)
|
set(DAWN_USE_WAYLAND ON CACHE BOOL "Enable support for Wayland surface" FORCE)
|
||||||
endif ()
|
endif ()
|
||||||
@@ -175,7 +148,6 @@ option(DUSK_SELECTED_OPT "If on, selected parts of the project will be compiled
|
|||||||
option(DUSK_MOVIE_SUPPORT "If on, compile against libjpeg-turbo to enable THP file decoding" ON)
|
option(DUSK_MOVIE_SUPPORT "If on, compile against libjpeg-turbo to enable THP file decoding" ON)
|
||||||
option(DUSK_ENABLE_UPDATE_CHECKER "Enable update checking support" ON)
|
option(DUSK_ENABLE_UPDATE_CHECKER "Enable update checking support" ON)
|
||||||
option(DUSK_ENABLE_SENTRY_NATIVE "Enable sentry-native crash reporting support" OFF)
|
option(DUSK_ENABLE_SENTRY_NATIVE "Enable sentry-native crash reporting support" OFF)
|
||||||
option(DUSK_PACKAGE_INSTALL "Install Dusklight with a Linux-native file structure" OFF)
|
|
||||||
option(DUSK_GFX_DEBUG_GROUPS "Report debug groups to the native graphics API" ${DUSK_GFX_DEBUG_GROUPS_DEFAULT})
|
option(DUSK_GFX_DEBUG_GROUPS "Report debug groups to the native graphics API" ${DUSK_GFX_DEBUG_GROUPS_DEFAULT})
|
||||||
set(DUSK_SENTRY_DSN "" CACHE STRING "Sentry DSN")
|
set(DUSK_SENTRY_DSN "" CACHE STRING "Sentry DSN")
|
||||||
set(DUSK_SENTRY_ENVIRONMENT "development" CACHE STRING "Sentry environment")
|
set(DUSK_SENTRY_ENVIRONMENT "development" CACHE STRING "Sentry environment")
|
||||||
@@ -284,6 +256,7 @@ elseif (MSVC)
|
|||||||
add_compile_options($<$<COMPILE_LANGUAGE:C,CXX>:/utf-8>)
|
add_compile_options($<$<COMPILE_LANGUAGE:C,CXX>:/utf-8>)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
|
||||||
include(FetchContent)
|
include(FetchContent)
|
||||||
|
|
||||||
# Declare all dependencies first so CMake can download them in parallel
|
# Declare all dependencies first so CMake can download them in parallel
|
||||||
@@ -291,13 +264,13 @@ message(STATUS "dusklight: Fetching cxxopts")
|
|||||||
FetchContent_Declare(cxxopts
|
FetchContent_Declare(cxxopts
|
||||||
URL https://github.com/jarro2783/cxxopts/archive/refs/tags/v3.3.1.tar.gz
|
URL https://github.com/jarro2783/cxxopts/archive/refs/tags/v3.3.1.tar.gz
|
||||||
URL_HASH SHA256=3bfc70542c521d4b55a46429d808178916a579b28d048bd8c727ee76c39e2072
|
URL_HASH SHA256=3bfc70542c521d4b55a46429d808178916a579b28d048bd8c727ee76c39e2072
|
||||||
DOWNLOAD_EXTRACT_TIMESTAMP FALSE
|
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
|
||||||
)
|
)
|
||||||
message(STATUS "dusklight: Fetching nlohmann/json")
|
message(STATUS "dusklight: Fetching nlohmann/json")
|
||||||
FetchContent_Declare(json
|
FetchContent_Declare(json
|
||||||
URL https://github.com/nlohmann/json/releases/download/v3.12.0/json.tar.xz
|
URL https://github.com/nlohmann/json/releases/download/v3.12.0/json.tar.xz
|
||||||
URL_HASH SHA256=42f6e95cad6ec532fd372391373363b62a14af6d771056dbfc86160e6dfff7aa
|
URL_HASH SHA256=42f6e95cad6ec532fd372391373363b62a14af6d771056dbfc86160e6dfff7aa
|
||||||
DOWNLOAD_EXTRACT_TIMESTAMP FALSE
|
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
|
||||||
)
|
)
|
||||||
FetchContent_MakeAvailable(cxxopts json)
|
FetchContent_MakeAvailable(cxxopts json)
|
||||||
|
|
||||||
@@ -378,7 +351,9 @@ set(GAME_INCLUDE_DIRS
|
|||||||
find_package(Threads REQUIRED)
|
find_package(Threads REQUIRED)
|
||||||
set(GAME_LIBS aurora::core aurora::gx aurora::gd aurora::si aurora::vi aurora::pad aurora::mtx aurora::os aurora::dvd
|
set(GAME_LIBS aurora::core aurora::gx aurora::gd aurora::si aurora::vi aurora::pad aurora::mtx aurora::os aurora::dvd
|
||||||
aurora::card freeverb cxxopts::cxxopts absl::flat_hash_map nlohmann_json::nlohmann_json TracyClient fmt::fmt
|
aurora::card freeverb cxxopts::cxxopts absl::flat_hash_map nlohmann_json::nlohmann_json TracyClient fmt::fmt
|
||||||
Threads::Threads zstd::libzstd)
|
Threads::Threads)
|
||||||
|
|
||||||
|
list(APPEND GAME_LIBS zstd::libzstd)
|
||||||
|
|
||||||
if (DUSK_ENABLE_SENTRY_NATIVE)
|
if (DUSK_ENABLE_SENTRY_NATIVE)
|
||||||
list(APPEND GAME_LIBS sentry)
|
list(APPEND GAME_LIBS sentry)
|
||||||
@@ -450,11 +425,6 @@ if(ANDROID)
|
|||||||
list(APPEND GAME_COMPILE_DEFS TARGET_ANDROID=1)
|
list(APPEND GAME_COMPILE_DEFS TARGET_ANDROID=1)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
if (DUSK_PACKAGE_INSTALL)
|
|
||||||
include(GNUInstallDirs)
|
|
||||||
list(APPEND GAME_COMPILE_DEFS DUSK_ASSET_DIR="${CMAKE_INSTALL_FULL_DATADIR}/dusklight/")
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
if (DUSK_GFX_DEBUG_GROUPS)
|
if (DUSK_GFX_DEBUG_GROUPS)
|
||||||
list(APPEND GAME_COMPILE_DEFS DUSK_GFX_DEBUG_GROUPS=1)
|
list(APPEND GAME_COMPILE_DEFS DUSK_GFX_DEBUG_GROUPS=1)
|
||||||
target_compile_definitions(aurora_gx PRIVATE AURORA_GFX_DEBUG_GROUPS)
|
target_compile_definitions(aurora_gx PRIVATE AURORA_GFX_DEBUG_GROUPS)
|
||||||
@@ -516,9 +486,6 @@ if(ANDROID)
|
|||||||
else ()
|
else ()
|
||||||
add_executable(dusklight ${DUSK_FILES})
|
add_executable(dusklight ${DUSK_FILES})
|
||||||
endif ()
|
endif ()
|
||||||
if (ENABLE_ASAN)
|
|
||||||
target_sources(dusklight PRIVATE src/dusk/asan_options.c)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
target_compile_definitions(dusklight PRIVATE ${GAME_COMPILE_DEFS})
|
target_compile_definitions(dusklight PRIVATE ${GAME_COMPILE_DEFS})
|
||||||
target_include_directories(dusklight PRIVATE ${GAME_INCLUDE_DIRS})
|
target_include_directories(dusklight PRIVATE ${GAME_INCLUDE_DIRS})
|
||||||
@@ -681,20 +648,12 @@ set(EXTRA_TARGETS "")
|
|||||||
if (TARGET crashpad_handler)
|
if (TARGET crashpad_handler)
|
||||||
list(APPEND EXTRA_TARGETS crashpad_handler)
|
list(APPEND EXTRA_TARGETS crashpad_handler)
|
||||||
endif ()
|
endif ()
|
||||||
if (DUSK_PACKAGE_INSTALL)
|
install(TARGETS ${BINARY_TARGETS} ${EXTRA_TARGETS} DESTINATION ${CMAKE_INSTALL_PREFIX})
|
||||||
install(TARGETS ${BINARY_TARGETS} ${EXTRA_TARGETS} DESTINATION ${CMAKE_INSTALL_BINDIR})
|
|
||||||
else()
|
|
||||||
install(TARGETS ${BINARY_TARGETS} ${EXTRA_TARGETS} DESTINATION ${CMAKE_INSTALL_PREFIX})
|
|
||||||
endif()
|
|
||||||
aurora_install_runtime_dlls(dusklight ${CMAKE_INSTALL_PREFIX})
|
aurora_install_runtime_dlls(dusklight ${CMAKE_INSTALL_PREFIX})
|
||||||
if (NOT APPLE)
|
if (NOT APPLE)
|
||||||
if (DUSK_PACKAGE_INSTALL)
|
install(DIRECTORY ${CMAKE_SOURCE_DIR}/res DESTINATION ${CMAKE_INSTALL_PREFIX})
|
||||||
install(DIRECTORY ${CMAKE_SOURCE_DIR}/res DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/dusklight)
|
|
||||||
else()
|
|
||||||
install(DIRECTORY ${CMAKE_SOURCE_DIR}/res DESTINATION ${CMAKE_INSTALL_PREFIX})
|
|
||||||
endif()
|
|
||||||
endif ()
|
endif ()
|
||||||
if (CMAKE_BUILD_TYPE STREQUAL Debug OR CMAKE_BUILD_TYPE STREQUAL RelWithDebInfo AND NOT DUSK_PACKAGE_INSTALL)
|
if (CMAKE_BUILD_TYPE STREQUAL Debug OR CMAKE_BUILD_TYPE STREQUAL RelWithDebInfo)
|
||||||
set(DEBUG_FILES_LIST "")
|
set(DEBUG_FILES_LIST "")
|
||||||
foreach (target IN LISTS BINARY_TARGETS EXTRA_TARGETS)
|
foreach (target IN LISTS BINARY_TARGETS EXTRA_TARGETS)
|
||||||
get_target_output_name(${target} output_name)
|
get_target_output_name(${target} output_name)
|
||||||
|
|||||||
+1
-75
@@ -52,16 +52,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "asan",
|
|
||||||
"hidden": true,
|
|
||||||
"cacheVariables": {
|
|
||||||
"ENABLE_ASAN": {
|
|
||||||
"type": "BOOL",
|
|
||||||
"value": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "linux-default",
|
"name": "linux-default",
|
||||||
"displayName": "Linux (default)",
|
"displayName": "Linux (default)",
|
||||||
@@ -93,15 +83,6 @@
|
|||||||
"linux-default"
|
"linux-default"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "linux-default-debug-asan",
|
|
||||||
"displayName": "Linux (default) Debug ASan",
|
|
||||||
"inherits": [
|
|
||||||
"debug",
|
|
||||||
"linux-default",
|
|
||||||
"asan"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "linux-default-relwithdebinfo",
|
"name": "linux-default-relwithdebinfo",
|
||||||
"displayName": "Linux (default) RelWithDebInfo",
|
"displayName": "Linux (default) RelWithDebInfo",
|
||||||
@@ -129,15 +110,6 @@
|
|||||||
"linux-clang"
|
"linux-clang"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "linux-clang-debug-asan",
|
|
||||||
"displayName": "Linux (Clang) Debug ASan",
|
|
||||||
"inherits": [
|
|
||||||
"debug",
|
|
||||||
"linux-clang",
|
|
||||||
"asan"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "linux-clang-relwithdebinfo",
|
"name": "linux-clang-relwithdebinfo",
|
||||||
"displayName": "Linux (Clang) RelWithDebInfo",
|
"displayName": "Linux (Clang) RelWithDebInfo",
|
||||||
@@ -158,11 +130,7 @@
|
|||||||
"cacheVariables": {
|
"cacheVariables": {
|
||||||
"CMAKE_C_COMPILER": "cl",
|
"CMAKE_C_COMPILER": "cl",
|
||||||
"CMAKE_CXX_COMPILER": "cl",
|
"CMAKE_CXX_COMPILER": "cl",
|
||||||
"CMAKE_INSTALL_PREFIX": "${sourceDir}/build/install",
|
"CMAKE_INSTALL_PREFIX": "${sourceDir}/build/install"
|
||||||
"CMAKE_DISABLE_FIND_PACKAGE_PkgConfig": {
|
|
||||||
"type": "BOOL",
|
|
||||||
"value": true
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"vendor": {
|
"vendor": {
|
||||||
"microsoft.com/VisualStudioSettings/CMake/1.0": {
|
"microsoft.com/VisualStudioSettings/CMake/1.0": {
|
||||||
@@ -180,15 +148,6 @@
|
|||||||
"windows-msvc"
|
"windows-msvc"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "windows-msvc-debug-asan",
|
|
||||||
"displayName": "Windows (MSVC) Debug ASan",
|
|
||||||
"inherits": [
|
|
||||||
"debug",
|
|
||||||
"windows-msvc",
|
|
||||||
"asan"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "windows-msvc-relwithdebinfo",
|
"name": "windows-msvc-relwithdebinfo",
|
||||||
"displayName": "Windows (MSVC) RelWithDebInfo",
|
"displayName": "Windows (MSVC) RelWithDebInfo",
|
||||||
@@ -280,15 +239,6 @@
|
|||||||
"macos-default"
|
"macos-default"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "macos-default-debug-asan",
|
|
||||||
"displayName": "macOS (default) Debug ASan",
|
|
||||||
"inherits": [
|
|
||||||
"debug",
|
|
||||||
"macos-default",
|
|
||||||
"asan"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "macos-default-relwithdebinfo",
|
"name": "macos-default-relwithdebinfo",
|
||||||
"displayName": "macOS (default) RelWithDebInfo",
|
"displayName": "macOS (default) RelWithDebInfo",
|
||||||
@@ -579,12 +529,6 @@
|
|||||||
"description": "Linux (default) debug build",
|
"description": "Linux (default) debug build",
|
||||||
"displayName": "Linux (default) Debug"
|
"displayName": "Linux (default) Debug"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "linux-default-debug-asan",
|
|
||||||
"configurePreset": "linux-default-debug-asan",
|
|
||||||
"description": "Linux (default) debug build with AddressSanitizer",
|
|
||||||
"displayName": "Linux (default) Debug ASan"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "linux-default-relwithdebinfo",
|
"name": "linux-default-relwithdebinfo",
|
||||||
"configurePreset": "linux-default-relwithdebinfo",
|
"configurePreset": "linux-default-relwithdebinfo",
|
||||||
@@ -597,12 +541,6 @@
|
|||||||
"description": "Linux (Clang) debug build",
|
"description": "Linux (Clang) debug build",
|
||||||
"displayName": "Linux (Clang) Debug"
|
"displayName": "Linux (Clang) Debug"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "linux-clang-debug-asan",
|
|
||||||
"configurePreset": "linux-clang-debug-asan",
|
|
||||||
"description": "Linux (Clang) debug build with AddressSanitizer",
|
|
||||||
"displayName": "Linux (Clang) Debug ASan"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "linux-clang-relwithdebinfo",
|
"name": "linux-clang-relwithdebinfo",
|
||||||
"configurePreset": "linux-clang-relwithdebinfo",
|
"configurePreset": "linux-clang-relwithdebinfo",
|
||||||
@@ -615,12 +553,6 @@
|
|||||||
"description": "macOS debug build",
|
"description": "macOS debug build",
|
||||||
"displayName": "macOS Debug"
|
"displayName": "macOS Debug"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "macos-default-debug-asan",
|
|
||||||
"configurePreset": "macos-default-debug-asan",
|
|
||||||
"description": "macOS debug build with AddressSanitizer",
|
|
||||||
"displayName": "macOS Debug ASan"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "macos-default-relwithdebinfo",
|
"name": "macos-default-relwithdebinfo",
|
||||||
"configurePreset": "macos-default-relwithdebinfo",
|
"configurePreset": "macos-default-relwithdebinfo",
|
||||||
@@ -678,12 +610,6 @@
|
|||||||
"description": "Windows (MSVC) debug build",
|
"description": "Windows (MSVC) debug build",
|
||||||
"displayName": "Windows (MSVC) Debug"
|
"displayName": "Windows (MSVC) Debug"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "windows-msvc-debug-asan",
|
|
||||||
"configurePreset": "windows-msvc-debug-asan",
|
|
||||||
"description": "Windows (MSVC) debug build with AddressSanitizer",
|
|
||||||
"displayName": "Windows (MSVC) Debug ASan"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "windows-msvc-relwithdebinfo",
|
"name": "windows-msvc-relwithdebinfo",
|
||||||
"configurePreset": "windows-msvc-relwithdebinfo",
|
"configurePreset": "windows-msvc-relwithdebinfo",
|
||||||
|
|||||||
@@ -180,7 +180,6 @@ cmake --build --preset macos-default-relwithdebinfo
|
|||||||
Alternate presets available:
|
Alternate presets available:
|
||||||
|
|
||||||
* `macos-default-debug`: Clang, Debug
|
* `macos-default-debug`: Clang, Debug
|
||||||
* `macos-default-debug-asan`: Clang, Debug, AddressSanitizer
|
|
||||||
|
|
||||||
**ninja (Linux)**
|
**ninja (Linux)**
|
||||||
|
|
||||||
@@ -192,10 +191,8 @@ cmake --build --preset linux-default-relwithdebinfo
|
|||||||
Alternate presets available:
|
Alternate presets available:
|
||||||
|
|
||||||
* `linux-default-debug`: GCC, Debug
|
* `linux-default-debug`: GCC, Debug
|
||||||
* `linux-default-debug-asan`: GCC, Debug, AddressSanitizer
|
|
||||||
* `linux-clang-relwithdebinfo`: Clang, RelWithDebInfo
|
* `linux-clang-relwithdebinfo`: Clang, RelWithDebInfo
|
||||||
* `linux-clang-debug`: Clang, Debug
|
* `linux-clang-debug`: Clang, Debug
|
||||||
* `linux-clang-debug-asan`: Clang, Debug, AddressSanitizer
|
|
||||||
|
|
||||||
**ninja (Windows)**
|
**ninja (Windows)**
|
||||||
|
|
||||||
@@ -207,7 +204,6 @@ cmake --build --preset windows-msvc-relwithdebinfo
|
|||||||
Alternate presets available:
|
Alternate presets available:
|
||||||
|
|
||||||
* `windows-msvc-debug`: MSVC, Debug
|
* `windows-msvc-debug`: MSVC, Debug
|
||||||
* `windows-msvc-debug-asan`: MSVC, Debug, AddressSanitizer
|
|
||||||
* `windows-clang-relwithdebinfo`: Clang-cl, RelWithDebInfo
|
* `windows-clang-relwithdebinfo`: Clang-cl, RelWithDebInfo
|
||||||
* `windows-clang-debug`: Clang-cl, Debug
|
* `windows-clang-debug`: Clang-cl, Debug
|
||||||
|
|
||||||
|
|||||||
Vendored
+1
-1
Submodule extern/aurora updated: 22351fb0b7...19479a53e4
+12
-23
@@ -244,7 +244,7 @@ set(DOLZEL_FILES
|
|||||||
src/CaptureScreen.cpp
|
src/CaptureScreen.cpp
|
||||||
)
|
)
|
||||||
if(DEBUG)
|
if(DEBUG)
|
||||||
list(APPEND DOLZEL_FILES src/d/d_event_debug.cpp)
|
list(APPEND DOLZEL_FILES src/d/d_event_debug.cpp)
|
||||||
endif(DEBUG)
|
endif(DEBUG)
|
||||||
|
|
||||||
set(Z2AUDIOLIB_FILES
|
set(Z2AUDIOLIB_FILES
|
||||||
@@ -1404,10 +1404,10 @@ set(REL_FILES
|
|||||||
)
|
)
|
||||||
|
|
||||||
set(DOLPHIN_FILES
|
set(DOLPHIN_FILES
|
||||||
libs/dolphin/src/gf/GFGeometry.cpp
|
libs/dolphin/src/gf/GFGeometry.cpp
|
||||||
libs/dolphin/src/gf/GFLight.cpp
|
libs/dolphin/src/gf/GFLight.cpp
|
||||||
libs/dolphin/src/gf/GFPixel.cpp
|
libs/dolphin/src/gf/GFPixel.cpp
|
||||||
libs/dolphin/src/gf/GFTev.cpp
|
libs/dolphin/src/gf/GFTev.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set(DUSK_FILES
|
set(DUSK_FILES
|
||||||
@@ -1418,11 +1418,7 @@ set(DUSK_FILES
|
|||||||
include/dusk/scope_guard.hpp
|
include/dusk/scope_guard.hpp
|
||||||
src/dusk/dvd_asset.cpp
|
src/dusk/dvd_asset.cpp
|
||||||
src/d/actor/d_a_alink_dusk.cpp
|
src/d/actor/d_a_alink_dusk.cpp
|
||||||
src/dusk/android_frame_rate.hpp
|
|
||||||
src/dusk/android_frame_rate.cpp
|
|
||||||
src/dusk/asserts.cpp
|
src/dusk/asserts.cpp
|
||||||
src/dusk/batch.cpp
|
|
||||||
src/dusk/batch.hpp
|
|
||||||
src/dusk/config.cpp
|
src/dusk/config.cpp
|
||||||
src/dusk/crash_handler.cpp
|
src/dusk/crash_handler.cpp
|
||||||
src/dusk/crash_reporting.cpp
|
src/dusk/crash_reporting.cpp
|
||||||
@@ -1433,14 +1429,15 @@ set(DUSK_FILES
|
|||||||
src/dusk/file_select.cpp
|
src/dusk/file_select.cpp
|
||||||
src/dusk/file_select.hpp
|
src/dusk/file_select.hpp
|
||||||
src/dusk/frame_interpolation.cpp
|
src/dusk/frame_interpolation.cpp
|
||||||
|
src/dusk/commands.cpp
|
||||||
|
src/dusk/commands.hpp
|
||||||
src/dusk/game_clock.cpp
|
src/dusk/game_clock.cpp
|
||||||
|
src/dusk/game_combos.cpp
|
||||||
src/dusk/globals.cpp
|
src/dusk/globals.cpp
|
||||||
src/dusk/gyro.cpp
|
src/dusk/gyro.cpp
|
||||||
include/dusk/menu_pointer.h
|
|
||||||
src/dusk/menu_pointer.cpp
|
|
||||||
src/dusk/mouse.cpp
|
src/dusk/mouse.cpp
|
||||||
src/dusk/gamepad_color.cpp
|
src/dusk/gamepad_color.cpp
|
||||||
src/dusk/autosave.cpp
|
src/dusk/autosave.cpp
|
||||||
src/dusk/http/http.hpp
|
src/dusk/http/http.hpp
|
||||||
src/dusk/io.cpp
|
src/dusk/io.cpp
|
||||||
src/dusk/layout.cpp
|
src/dusk/layout.cpp
|
||||||
@@ -1451,7 +1448,6 @@ set(DUSK_FILES
|
|||||||
src/dusk/stubs.cpp
|
src/dusk/stubs.cpp
|
||||||
include/dusk/texture_replacements.hpp
|
include/dusk/texture_replacements.hpp
|
||||||
src/dusk/texture_replacements.cpp
|
src/dusk/texture_replacements.cpp
|
||||||
src/dusk/touch_camera.cpp
|
|
||||||
src/dusk/update_check.cpp
|
src/dusk/update_check.cpp
|
||||||
src/dusk/update_check.hpp
|
src/dusk/update_check.hpp
|
||||||
#src/dusk/m_Do_ext_dusk.cpp
|
#src/dusk/m_Do_ext_dusk.cpp
|
||||||
@@ -1475,13 +1471,14 @@ set(DUSK_FILES
|
|||||||
src/dusk/imgui/ImGuiStateShare.cpp
|
src/dusk/imgui/ImGuiStateShare.cpp
|
||||||
src/dusk/ui/achievements.cpp
|
src/dusk/ui/achievements.cpp
|
||||||
src/dusk/ui/achievements.hpp
|
src/dusk/ui/achievements.hpp
|
||||||
|
src/dusk/ui/command_console.cpp
|
||||||
|
src/dusk/ui/command_console.hpp
|
||||||
src/dusk/ui/bool_button.cpp
|
src/dusk/ui/bool_button.cpp
|
||||||
src/dusk/ui/bool_button.hpp
|
src/dusk/ui/bool_button.hpp
|
||||||
src/dusk/ui/button.cpp
|
src/dusk/ui/button.cpp
|
||||||
src/dusk/ui/button.hpp
|
src/dusk/ui/button.hpp
|
||||||
src/dusk/ui/component.cpp
|
src/dusk/ui/component.cpp
|
||||||
src/dusk/ui/component.hpp
|
src/dusk/ui/component.hpp
|
||||||
src/dusk/ui/controls.hpp
|
|
||||||
src/dusk/ui/controller_config.cpp
|
src/dusk/ui/controller_config.cpp
|
||||||
src/dusk/ui/controller_config.hpp
|
src/dusk/ui/controller_config.hpp
|
||||||
src/dusk/ui/document.cpp
|
src/dusk/ui/document.cpp
|
||||||
@@ -1494,8 +1491,6 @@ set(DUSK_FILES
|
|||||||
src/dusk/ui/graphics_tuner.hpp
|
src/dusk/ui/graphics_tuner.hpp
|
||||||
src/dusk/ui/input.cpp
|
src/dusk/ui/input.cpp
|
||||||
src/dusk/ui/input.hpp
|
src/dusk/ui/input.hpp
|
||||||
src/dusk/ui/icon_provider.cpp
|
|
||||||
src/dusk/ui/icon_provider.hpp
|
|
||||||
src/dusk/ui/modal.cpp
|
src/dusk/ui/modal.cpp
|
||||||
src/dusk/ui/modal.hpp
|
src/dusk/ui/modal.hpp
|
||||||
src/dusk/ui/nav_types.hpp
|
src/dusk/ui/nav_types.hpp
|
||||||
@@ -1521,12 +1516,6 @@ set(DUSK_FILES
|
|||||||
src/dusk/ui/string_button.hpp
|
src/dusk/ui/string_button.hpp
|
||||||
src/dusk/ui/tab_bar.cpp
|
src/dusk/ui/tab_bar.cpp
|
||||||
src/dusk/ui/tab_bar.hpp
|
src/dusk/ui/tab_bar.hpp
|
||||||
src/dusk/ui/touch_controls_common.cpp
|
|
||||||
src/dusk/ui/touch_controls_common.hpp
|
|
||||||
src/dusk/ui/touch_controls.cpp
|
|
||||||
src/dusk/ui/touch_controls.hpp
|
|
||||||
src/dusk/ui/touch_controls_editor.cpp
|
|
||||||
src/dusk/ui/touch_controls_editor.hpp
|
|
||||||
src/dusk/ui/ui.cpp
|
src/dusk/ui/ui.cpp
|
||||||
src/dusk/ui/ui.hpp
|
src/dusk/ui/ui.hpp
|
||||||
src/dusk/ui/warp.cpp
|
src/dusk/ui/warp.cpp
|
||||||
|
|||||||
@@ -138,7 +138,7 @@
|
|||||||
NOD_PREBUILT = nod;
|
NOD_PREBUILT = nod;
|
||||||
CXXOPTS = pkgs.cxxopts.src;
|
CXXOPTS = pkgs.cxxopts.src;
|
||||||
JSON = pkgs.nlohmann_json.src;
|
JSON = pkgs.nlohmann_json.src;
|
||||||
XXHASH = pkgs.xxhash.src;
|
XXHASH = pkgs.xxHash.src;
|
||||||
ZSTD = pkgs.zstd.src;
|
ZSTD = pkgs.zstd.src;
|
||||||
FMT = pkgs.fetchzip {
|
FMT = pkgs.fetchzip {
|
||||||
url = "https://github.com/fmtlib/fmt/archive/refs/tags/11.1.4.tar.gz";
|
url = "https://github.com/fmtlib/fmt/archive/refs/tags/11.1.4.tar.gz";
|
||||||
@@ -194,7 +194,7 @@
|
|||||||
pkgs.zstd
|
pkgs.zstd
|
||||||
pkgs.cxxopts
|
pkgs.cxxopts
|
||||||
pkgs.nlohmann_json
|
pkgs.nlohmann_json
|
||||||
pkgs.xxhash
|
pkgs.xxHash
|
||||||
pkgs.abseil-cpp
|
pkgs.abseil-cpp
|
||||||
pkgs.zlib
|
pkgs.zlib
|
||||||
pkgs.libpng
|
pkgs.libpng
|
||||||
|
|||||||
@@ -4556,7 +4556,6 @@ public:
|
|||||||
void handleWolfHowl();
|
void handleWolfHowl();
|
||||||
void handleQuickTransform();
|
void handleQuickTransform();
|
||||||
bool checkAimContext();
|
bool checkAimContext();
|
||||||
bool checkAimInputContext();
|
|
||||||
|
|
||||||
void onIronBallChainInterpCallback();
|
void onIronBallChainInterpCallback();
|
||||||
|
|
||||||
|
|||||||
@@ -4,10 +4,6 @@
|
|||||||
#include "JSystem/J3DGraphBase/J3DPacket.h"
|
#include "JSystem/J3DGraphBase/J3DPacket.h"
|
||||||
#include "SSystem/SComponent/c_xyz.h"
|
#include "SSystem/SComponent/c_xyz.h"
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
#include "dusk/batch.hpp"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class cCcD_Obj;
|
class cCcD_Obj;
|
||||||
class dCcMassS_HitInf;
|
class dCcMassS_HitInf;
|
||||||
class fopAc_ac_c;
|
class fopAc_ac_c;
|
||||||
@@ -111,12 +107,6 @@ public:
|
|||||||
#if TARGET_PC
|
#if TARGET_PC
|
||||||
TGXTexObj mTexObj_l_J_Ohana00_64TEX;
|
TGXTexObj mTexObj_l_J_Ohana00_64TEX;
|
||||||
TGXTexObj mTexObj_l_J_Ohana01_64128_0419TEX;
|
TGXTexObj mTexObj_l_J_Ohana01_64128_0419TEX;
|
||||||
|
|
||||||
dusk::batch::LeafTemplate mTplHana00; // l_J_hana00DL
|
|
||||||
dusk::batch::LeafTemplate mTplHana00Cut; // l_J_hana00_cDL
|
|
||||||
dusk::batch::LeafTemplate mTplHana01; // l_J_hana01DL
|
|
||||||
dusk::batch::LeafTemplate mTplHana01Cut00; // l_J_hana01_c_00DL
|
|
||||||
dusk::batch::LeafTemplate mTplHana01Cut; // l_J_hana01_c_01DL
|
|
||||||
#endif
|
#endif
|
||||||
}; // Size: 0x12A54
|
}; // Size: 0x12A54
|
||||||
|
|
||||||
|
|||||||
@@ -4,10 +4,6 @@
|
|||||||
#include "JSystem/J3DGraphBase/J3DPacket.h"
|
#include "JSystem/J3DGraphBase/J3DPacket.h"
|
||||||
#include "SSystem/SComponent/c_xyz.h"
|
#include "SSystem/SComponent/c_xyz.h"
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
#include "../../../src/dusk/batch.hpp"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class cCcD_Obj;
|
class cCcD_Obj;
|
||||||
class csXyz;
|
class csXyz;
|
||||||
class dCcMassS_HitInf;
|
class dCcMassS_HitInf;
|
||||||
@@ -114,10 +110,6 @@ public:
|
|||||||
#if TARGET_PC
|
#if TARGET_PC
|
||||||
TGXTexObj mTexObj_l_M_Hijiki00TEX;
|
TGXTexObj mTexObj_l_M_Hijiki00TEX;
|
||||||
TGXTexObj mTexObj_l_M_kusa05_RGBATEX;
|
TGXTexObj mTexObj_l_M_kusa05_RGBATEX;
|
||||||
|
|
||||||
dusk::batch::LeafTemplate mTplKusa9q; // l_M_Kusa_9qDL
|
|
||||||
dusk::batch::LeafTemplate mTplKusa9qCut; // l_M_Kusa_9q_cDL
|
|
||||||
dusk::batch::LeafTemplate mTplTengusa; // l_M_TenGusaDL
|
|
||||||
#endif
|
#endif
|
||||||
}; // Size: 0x1D718
|
}; // Size: 0x1D718
|
||||||
|
|
||||||
|
|||||||
@@ -1037,7 +1037,7 @@ public:
|
|||||||
bool test1Camera(s32);
|
bool test1Camera(s32);
|
||||||
bool test2Camera(s32);
|
bool test2Camera(s32);
|
||||||
#if TARGET_PC
|
#if TARGET_PC
|
||||||
static bool isAimActive();
|
static bool canUseFreeCam();
|
||||||
bool freeCamera();
|
bool freeCamera();
|
||||||
bool executeDebugFlyCam();
|
bool executeDebugFlyCam();
|
||||||
void deactivateDebugFlyCam();
|
void deactivateDebugFlyCam();
|
||||||
|
|||||||
@@ -287,11 +287,6 @@ public:
|
|||||||
MEMCARDCHECKPROC_ERR_YESNO_CURSOR_MOVE_ANM,
|
MEMCARDCHECKPROC_ERR_YESNO_CURSOR_MOVE_ANM,
|
||||||
MEMCARDCHECKPROC_SAVEDATA_CLEAR,
|
MEMCARDCHECKPROC_SAVEDATA_CLEAR,
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
MEMCARDCHECKPROC_AUTO_MAKE_GAMEFILE,
|
|
||||||
MEMCARDCHECKPROC_AUTO_MAKE_GAMEFILE_ERR_WAIT,
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if PLATFORM_WII || PLATFORM_SHIELD
|
#if PLATFORM_WII || PLATFORM_SHIELD
|
||||||
MEMCARDCHECKPROC_NAND_STAT_CHECK,
|
MEMCARDCHECKPROC_NAND_STAT_CHECK,
|
||||||
MEMCARDCHECKPROC_GAMEFILE_INIT_SEL,
|
MEMCARDCHECKPROC_GAMEFILE_INIT_SEL,
|
||||||
@@ -416,10 +411,6 @@ public:
|
|||||||
bool yesnoWakuAlpahAnm(u8);
|
bool yesnoWakuAlpahAnm(u8);
|
||||||
#if TARGET_PC
|
#if TARGET_PC
|
||||||
void fileSelectWide();
|
void fileSelectWide();
|
||||||
bool pointerDataSelect();
|
|
||||||
bool pointerMenuSelect();
|
|
||||||
bool pointerCopyDataToSelect();
|
|
||||||
bool pointerYesNoSelect(bool errorSelect);
|
|
||||||
#endif
|
#endif
|
||||||
void _draw();
|
void _draw();
|
||||||
void errorMoveAnmInitSet(int, int);
|
void errorMoveAnmInitSet(int, int);
|
||||||
@@ -454,10 +445,6 @@ public:
|
|||||||
void MemCardMakeGameFile();
|
void MemCardMakeGameFile();
|
||||||
void MemCardMakeGameFileWait();
|
void MemCardMakeGameFileWait();
|
||||||
void MemCardMakeGameFileCheck();
|
void MemCardMakeGameFileCheck();
|
||||||
#if TARGET_PC
|
|
||||||
void MemCardAutoMakeGameFile();
|
|
||||||
void MemCardAutoMakeGameFileErrWait();
|
|
||||||
#endif
|
|
||||||
void MemCardMsgWindowInitOpen();
|
void MemCardMsgWindowInitOpen();
|
||||||
void MemCardMsgWindowOpen();
|
void MemCardMsgWindowOpen();
|
||||||
void MemCardMsgWindowClose();
|
void MemCardMsgWindowClose();
|
||||||
|
|||||||
@@ -157,9 +157,6 @@ public:
|
|||||||
int getDispType() const;
|
int getDispType() const;
|
||||||
void _move(f32, f32, int, f32);
|
void _move(f32, f32, int, f32);
|
||||||
void _draw();
|
void _draw();
|
||||||
#if TARGET_PC
|
|
||||||
bool refreshTextureSize();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
virtual ~dMap_c() {
|
virtual ~dMap_c() {
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
|
|||||||
@@ -74,8 +74,6 @@ public:
|
|||||||
|
|
||||||
#if TARGET_PC
|
#if TARGET_PC
|
||||||
void menuCollectWide();
|
void menuCollectWide();
|
||||||
bool pointerWait();
|
|
||||||
void pointerActivateCurrent();
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void _create();
|
void _create();
|
||||||
|
|||||||
@@ -51,10 +51,6 @@ public:
|
|||||||
void setBButtonString(u16);
|
void setBButtonString(u16);
|
||||||
void setHIO(bool);
|
void setHIO(bool);
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
bool pointerWait();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
virtual void draw() { _draw(); }
|
virtual void draw() { _draw(); }
|
||||||
virtual ~dMenu_Insect_c();
|
virtual ~dMenu_Insect_c();
|
||||||
|
|
||||||
|
|||||||
@@ -55,10 +55,6 @@ public:
|
|||||||
u8 getLetterNum();
|
u8 getLetterNum();
|
||||||
void setHIO(bool);
|
void setHIO(bool);
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
bool pointerWait();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
virtual void draw() { _draw(); }
|
virtual void draw() { _draw(); }
|
||||||
virtual ~dMenu_Letter_c();
|
virtual ~dMenu_Letter_c();
|
||||||
|
|
||||||
|
|||||||
@@ -80,9 +80,6 @@ public:
|
|||||||
void setBButtonString(u16);
|
void setBButtonString(u16);
|
||||||
bool isRumbleSupported();
|
bool isRumbleSupported();
|
||||||
bool dpdMenuMove();
|
bool dpdMenuMove();
|
||||||
#if TARGET_PC
|
|
||||||
bool pointerConfirmSelect();
|
|
||||||
#endif
|
|
||||||
void paneResize(u64);
|
void paneResize(u64);
|
||||||
void initialize();
|
void initialize();
|
||||||
void yesnoMenuMoveAnmInitSet(int, int);
|
void yesnoMenuMoveAnmInitSet(int, int);
|
||||||
|
|||||||
@@ -74,9 +74,6 @@ public:
|
|||||||
void clacEllipsePlotAverage(int, f32, f32);
|
void clacEllipsePlotAverage(int, f32, f32);
|
||||||
bool dpdMove();
|
bool dpdMove();
|
||||||
u8 openExplain(u8);
|
u8 openExplain(u8);
|
||||||
#if TARGET_PC
|
|
||||||
bool pointerMove();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
virtual void draw() { _draw(); }
|
virtual void draw() { _draw(); }
|
||||||
virtual ~dMenu_Ring_c();
|
virtual ~dMenu_Ring_c();
|
||||||
|
|||||||
@@ -266,8 +266,6 @@ public:
|
|||||||
|
|
||||||
#if TARGET_PC
|
#if TARGET_PC
|
||||||
void menuSaveWide();
|
void menuSaveWide();
|
||||||
bool pointerSaveSelect();
|
|
||||||
bool pointerYesNoSelect(bool errorSelect, u8 errParam = 0, u8 soundParam = 0);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void _draw2();
|
void _draw2();
|
||||||
|
|||||||
@@ -49,10 +49,6 @@ public:
|
|||||||
u8 getSkillNum();
|
u8 getSkillNum();
|
||||||
void setHIO(bool);
|
void setHIO(bool);
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
bool pointerWait();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
virtual void draw() { _draw(); }
|
virtual void draw() { _draw(); }
|
||||||
virtual ~dMenu_Skill_c();
|
virtual ~dMenu_Skill_c();
|
||||||
|
|
||||||
|
|||||||
@@ -49,10 +49,6 @@ public:
|
|||||||
void selectScale();
|
void selectScale();
|
||||||
void selectTrans();
|
void selectTrans();
|
||||||
void selectAnimeTransform(int);
|
void selectAnimeTransform(int);
|
||||||
#if TARGET_PC
|
|
||||||
bool pointerMove();
|
|
||||||
bool consumePointerClick();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void setOffsetX(f32 i_offsetX) { mOffsetX = i_offsetX; }
|
void setOffsetX(f32 i_offsetX) { mOffsetX = i_offsetX; }
|
||||||
bool isAnimeUpdate(int param_0) { return (field_0x114 & (u8)(1 << param_0)) ? TRUE : FALSE; }
|
bool isAnimeUpdate(int param_0) { return (field_0x114 & (u8)(1 << param_0)) ? TRUE : FALSE; }
|
||||||
|
|||||||
@@ -1351,6 +1351,9 @@ enum dStage_SaveTbl {
|
|||||||
|
|
||||||
const char* dStage_getName2(s16, s8);
|
const char* dStage_getName2(s16, s8);
|
||||||
dStage_objectNameInf* dStage_searchName(const char*);
|
dStage_objectNameInf* dStage_searchName(const char*);
|
||||||
|
#if TARGET_PC
|
||||||
|
dStage_objectNameInf* dStage_searchNameCI(const char*);
|
||||||
|
#endif
|
||||||
static int dStage_stageKeepTresureInit(dStage_dt_c*, void*, int, void*);
|
static int dStage_stageKeepTresureInit(dStage_dt_c*, void*, int, void*);
|
||||||
static int dStage_filiInfo2Init(dStage_dt_c*, void*, int, void*);
|
static int dStage_filiInfo2Init(dStage_dt_c*, void*, int, void*);
|
||||||
static int dStage_mapPathInitCommonLayer(dStage_dt_c*, void*, int, void*);
|
static int dStage_mapPathInitCommonLayer(dStage_dt_c*, void*, int, void*);
|
||||||
|
|||||||
@@ -9,8 +9,6 @@ namespace dusk {
|
|||||||
enum class ActionBinds {
|
enum class ActionBinds {
|
||||||
FIRST_PERSON_CAMERA,
|
FIRST_PERSON_CAMERA,
|
||||||
CALL_MIDNA,
|
CALL_MIDNA,
|
||||||
OPEN_MAP_SCREEN,
|
|
||||||
TOGGLE_MINIMAP,
|
|
||||||
OPEN_DUSKLIGHT_MENU,
|
OPEN_DUSKLIGHT_MENU,
|
||||||
TURBO_SPEED_BUTTON,
|
TURBO_SPEED_BUTTON,
|
||||||
COUNT,
|
COUNT,
|
||||||
@@ -34,12 +32,6 @@ bool isActionBound(ActionBinds action, u32 port);
|
|||||||
|
|
||||||
void updateActionBindings();
|
void updateActionBindings();
|
||||||
|
|
||||||
void setVirtualActionBind(ActionBinds action, u32 port, bool pressed, bool available = true);
|
|
||||||
|
|
||||||
void clearVirtualActionBind(ActionBinds action, u32 port);
|
|
||||||
|
|
||||||
void clearAllVirtualActionBinds();
|
|
||||||
|
|
||||||
bool getActionBindTrig(ActionBinds action, u32 port);
|
bool getActionBindTrig(ActionBinds action, u32 port);
|
||||||
|
|
||||||
bool getActionBindHold(ActionBinds action, u32 port);
|
bool getActionBindHold(ActionBinds action, u32 port);
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
#include "dolphin/types.h"
|
#include "dolphin/types.h"
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <limits>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -140,16 +139,11 @@ concept ConfigValueInteger =
|
|||||||
|| std::is_same_v<T, s64>
|
|| std::is_same_v<T, s64>
|
||||||
|| std::is_same_v<T, u64>;
|
|| std::is_same_v<T, u64>;
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct ConfigValueTraits {
|
|
||||||
static constexpr bool enabled = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Concept that defines the legal set of types that can be used for CVar values.
|
* \brief Concept that defines the legal set of types that can be used for CVar values.
|
||||||
*
|
*
|
||||||
* Valid types cannot be cv-qualified and must be basic primitive types (int, float, bool),
|
* Valid types cannot be cv-qualified and must be basic primitive types (int, float, bool),
|
||||||
* strings, enums of the basic primitives, or explicitly-enabled structured settings.
|
* strings, or enums of the basic primitives.
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
concept ConfigValue =
|
concept ConfigValue =
|
||||||
@@ -160,8 +154,7 @@ concept ConfigValue =
|
|||||||
|| std::is_same_v<T, f32>
|
|| std::is_same_v<T, f32>
|
||||||
|| std::is_same_v<T, f64>
|
|| std::is_same_v<T, f64>
|
||||||
|| std::is_same_v<T, std::string>
|
|| std::is_same_v<T, std::string>
|
||||||
|| (std::is_enum_v<T> && ConfigValueInteger<std::underlying_type_t<T>>)
|
|| (std::is_enum_v<T> && ConfigValueInteger<std::underlying_type_t<T>>));
|
||||||
|| ConfigValueTraits<T>::enabled);
|
|
||||||
|
|
||||||
template <ConfigValue T>
|
template <ConfigValue T>
|
||||||
const ConfigImplBase* GetConfigImpl();
|
const ConfigImplBase* GetConfigImpl();
|
||||||
|
|||||||
@@ -23,4 +23,8 @@ float sample_interpolation_step();
|
|||||||
|
|
||||||
float consume_interval(const void* consumer);
|
float consume_interval(const void* consumer);
|
||||||
|
|
||||||
|
// Runtime sim rate override (default 30 hz). Resets the frame timer.
|
||||||
|
void set_sim_rate(float hz);
|
||||||
|
float get_sim_rate();
|
||||||
|
|
||||||
} // namespace dusk::game_clock
|
} // namespace dusk::game_clock
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <dolphin/types.h>
|
||||||
|
|
||||||
|
namespace dusk {
|
||||||
|
|
||||||
|
struct GameCombo {
|
||||||
|
using ConditionFn = bool(*)();
|
||||||
|
using ActionFn = void(*)();
|
||||||
|
|
||||||
|
u32 holdMask; // all of these must be held (getHold)
|
||||||
|
u32 trigMask; // at least one must be newly triggered (getTrig); 0 = fires every frame while holdMask is held
|
||||||
|
bool strict; // if true: (held & ~trigMask) must equal holdMask exactly, no extra buttons held
|
||||||
|
ConditionFn condition; // extra game-state guard; nullptr = no extra check
|
||||||
|
ActionFn action; // runs when the combo is fired
|
||||||
|
u32 consumeMask; // buttons to clear after firing; 0 = pass-through
|
||||||
|
bool exclusive; // stop evaluating future combos if this fires
|
||||||
|
};
|
||||||
|
|
||||||
|
void processGameCombos();
|
||||||
|
|
||||||
|
} // namespace dusk
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "dolphin/types.h"
|
|
||||||
|
|
||||||
class CPaneMgr;
|
|
||||||
|
|
||||||
namespace dusk::menu_pointer {
|
|
||||||
|
|
||||||
enum class Context {
|
|
||||||
None,
|
|
||||||
FileSelect,
|
|
||||||
Save,
|
|
||||||
ItemWheel,
|
|
||||||
Collection,
|
|
||||||
Options,
|
|
||||||
Dialog,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class Phase {
|
|
||||||
Move,
|
|
||||||
Press,
|
|
||||||
Release,
|
|
||||||
Cancel,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct State {
|
|
||||||
f32 x = 0.0f;
|
|
||||||
f32 y = 0.0f;
|
|
||||||
bool valid = false;
|
|
||||||
bool down = false;
|
|
||||||
bool pressed = false;
|
|
||||||
bool released = false;
|
|
||||||
bool clicked = false;
|
|
||||||
bool touch = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
void begin_game_frame() noexcept;
|
|
||||||
void end_game_frame() noexcept;
|
|
||||||
void begin_context(Context context) noexcept;
|
|
||||||
bool handle_fallthrough_pointer(f32 x, f32 y, Phase phase, bool touch, s32 mouseButton = -1) noexcept;
|
|
||||||
|
|
||||||
bool active() noexcept;
|
|
||||||
bool enabled() noexcept;
|
|
||||||
bool mouse_capture_active() noexcept;
|
|
||||||
const State& state() noexcept;
|
|
||||||
bool consume_click() noexcept;
|
|
||||||
void set_dialog_choice(u8 choice, bool clicked) noexcept;
|
|
||||||
bool get_dialog_choice(u8& choice) noexcept;
|
|
||||||
bool consume_dialog_click(u8& choice) noexcept;
|
|
||||||
void defer_activation(Context context, u8 target) noexcept;
|
|
||||||
bool consume_deferred_activation(Context context, u8 target) noexcept;
|
|
||||||
void clear_deferred_activation(Context context) noexcept;
|
|
||||||
u32 suppressed_pad_buttons(u32 port) noexcept;
|
|
||||||
void finish_pad_suppression_read(u32 port) noexcept;
|
|
||||||
|
|
||||||
bool hit_rect(f32 left, f32 top, f32 right, f32 bottom, f32 padding = 0.0f) noexcept;
|
|
||||||
bool hit_pane(CPaneMgr* pane, f32 padding = 0.0f) noexcept;
|
|
||||||
bool hit_pane(J2DPane* pane, f32 padding = 0.0f) noexcept;
|
|
||||||
|
|
||||||
} // namespace dusk::menu_pointer
|
|
||||||
+18
-18
@@ -1,9 +1,9 @@
|
|||||||
#pragma once
|
#ifndef DUSK_CONFIG_H
|
||||||
|
#define DUSK_CONFIG_H
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
#include "dusk/config_var.hpp"
|
#include "dusk/config_var.hpp"
|
||||||
#include "dusk/ui/controls.hpp"
|
|
||||||
|
|
||||||
namespace dusk {
|
namespace dusk {
|
||||||
|
|
||||||
@@ -40,6 +40,11 @@ enum class DiscVerificationState : u8 {
|
|||||||
HashMismatch,
|
HashMismatch,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class GyroMode : u8 {
|
||||||
|
Sensor = 0,
|
||||||
|
Mouse = 1,
|
||||||
|
};
|
||||||
|
|
||||||
enum class FrameInterpMode : u8 {
|
enum class FrameInterpMode : u8 {
|
||||||
Off = 0,
|
Off = 0,
|
||||||
Capped = 1,
|
Capped = 1,
|
||||||
@@ -91,6 +96,12 @@ struct ConfigEnumRange<DiscVerificationState> {
|
|||||||
static constexpr auto max = DiscVerificationState::HashMismatch;
|
static constexpr auto max = DiscVerificationState::HashMismatch;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct ConfigEnumRange<GyroMode> {
|
||||||
|
static constexpr auto min = GyroMode::Sensor;
|
||||||
|
static constexpr auto max = GyroMode::Mouse;
|
||||||
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct ConfigEnumRange<FrameInterpMode> {
|
struct ConfigEnumRange<FrameInterpMode> {
|
||||||
static constexpr auto min = FrameInterpMode::Off;
|
static constexpr auto min = FrameInterpMode::Off;
|
||||||
@@ -108,11 +119,6 @@ struct ConfigEnumRange<MagicArmorMode> {
|
|||||||
static constexpr auto min = MagicArmorMode::NORMAL;
|
static constexpr auto min = MagicArmorMode::NORMAL;
|
||||||
static constexpr auto max = MagicArmorMode::COSMETIC;
|
static constexpr auto max = MagicArmorMode::COSMETIC;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
|
||||||
struct ConfigValueTraits<ui::ControlLayout> {
|
|
||||||
static constexpr bool enabled = true;
|
|
||||||
};
|
|
||||||
} // namespace config
|
} // namespace config
|
||||||
|
|
||||||
// Persistent user settings
|
// Persistent user settings
|
||||||
@@ -128,9 +134,6 @@ struct UserSettings {
|
|||||||
ConfigVar<bool> enableFpsOverlay;
|
ConfigVar<bool> enableFpsOverlay;
|
||||||
ConfigVar<int> fpsOverlayCorner;
|
ConfigVar<int> fpsOverlayCorner;
|
||||||
ConfigVar<int> maxFrameRate;
|
ConfigVar<int> maxFrameRate;
|
||||||
ConfigVar<bool> rememberWindowSize;
|
|
||||||
ConfigVar<int> lastWindowWidth;
|
|
||||||
ConfigVar<int> lastWindowHeight;
|
|
||||||
} video;
|
} video;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
@@ -215,9 +218,6 @@ struct UserSettings {
|
|||||||
ConfigVar<float> mouseCameraSensitivity;
|
ConfigVar<float> mouseCameraSensitivity;
|
||||||
ConfigVar<bool> invertMouseY;
|
ConfigVar<bool> invertMouseY;
|
||||||
ConfigVar<bool> freeCamera;
|
ConfigVar<bool> freeCamera;
|
||||||
ConfigVar<bool> enableTouchControls;
|
|
||||||
ConfigVar<bool> enableMenuPointer;
|
|
||||||
ConfigVar<ui::ControlLayout> touchControlsLayout;
|
|
||||||
ConfigVar<bool> invertCameraXAxis;
|
ConfigVar<bool> invertCameraXAxis;
|
||||||
ConfigVar<bool> invertCameraYAxis;
|
ConfigVar<bool> invertCameraYAxis;
|
||||||
ConfigVar<bool> invertFirstPersonXAxis;
|
ConfigVar<bool> invertFirstPersonXAxis;
|
||||||
@@ -226,8 +226,6 @@ struct UserSettings {
|
|||||||
ConfigVar<bool> invertAirSwimY;
|
ConfigVar<bool> invertAirSwimY;
|
||||||
ConfigVar<float> freeCameraXSensitivity;
|
ConfigVar<float> freeCameraXSensitivity;
|
||||||
ConfigVar<float> freeCameraYSensitivity;
|
ConfigVar<float> freeCameraYSensitivity;
|
||||||
ConfigVar<float> touchCameraXSensitivity;
|
|
||||||
ConfigVar<float> touchCameraYSensitivity;
|
|
||||||
ConfigVar<bool> debugFlyCam;
|
ConfigVar<bool> debugFlyCam;
|
||||||
ConfigVar<bool> debugFlyCamLockEvents;
|
ConfigVar<bool> debugFlyCamLockEvents;
|
||||||
ConfigVar<bool> allowBackgroundInput;
|
ConfigVar<bool> allowBackgroundInput;
|
||||||
@@ -268,6 +266,8 @@ struct UserSettings {
|
|||||||
ConfigVar<bool> removeQuestMapMarkers;
|
ConfigVar<bool> removeQuestMapMarkers;
|
||||||
ConfigVar<bool> showInputViewer;
|
ConfigVar<bool> showInputViewer;
|
||||||
ConfigVar<bool> showInputViewerGyro;
|
ConfigVar<bool> showInputViewerGyro;
|
||||||
|
ConfigVar<bool> enableMoveLinkCombo;
|
||||||
|
ConfigVar<bool> enableTeleportCombo;
|
||||||
} game;
|
} game;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
@@ -286,8 +286,6 @@ struct UserSettings {
|
|||||||
struct {
|
struct {
|
||||||
std::array<ActionBindConfigVar, 4> firstPersonCamera;
|
std::array<ActionBindConfigVar, 4> firstPersonCamera;
|
||||||
std::array<ActionBindConfigVar, 4> callMidna;
|
std::array<ActionBindConfigVar, 4> callMidna;
|
||||||
std::array<ActionBindConfigVar, 4> openMapScreen;
|
|
||||||
std::array<ActionBindConfigVar, 4> toggleMinimap;
|
|
||||||
std::array<ActionBindConfigVar, 4> openDusklightMenu;
|
std::array<ActionBindConfigVar, 4> openDusklightMenu;
|
||||||
std::array<ActionBindConfigVar, 4> turboSpeedButton;
|
std::array<ActionBindConfigVar, 4> turboSpeedButton;
|
||||||
} actionBindings;
|
} actionBindings;
|
||||||
@@ -319,4 +317,6 @@ struct TransientSettings {
|
|||||||
|
|
||||||
TransientSettings& getTransientSettings();
|
TransientSettings& getTransientSettings();
|
||||||
|
|
||||||
} // namespace dusk
|
}
|
||||||
|
|
||||||
|
#endif // DUSK_CONFIG_H
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
namespace dusk::touch_camera {
|
|
||||||
|
|
||||||
constexpr float YAW_DEGREES_PER_DP = 0.34f;
|
|
||||||
constexpr float PITCH_DEGREES_PER_DP = 0.22f;
|
|
||||||
|
|
||||||
void add_delta(float yaw_dp, float pitch_dp) noexcept;
|
|
||||||
bool consume_delta(float& yaw_dp, float& pitch_dp) noexcept;
|
|
||||||
void clear() noexcept;
|
|
||||||
|
|
||||||
} // namespace dusk::touch_camera
|
|
||||||
@@ -212,9 +212,6 @@ public:
|
|||||||
void setCornerColor(JUtility::TColor c0) {
|
void setCornerColor(JUtility::TColor c0) {
|
||||||
setCornerColor(c0, c0, c0, c0);
|
setCornerColor(c0, c0, c0, c0);
|
||||||
}
|
}
|
||||||
#if TARGET_PC
|
|
||||||
JUtility::TColor corner(size_t index) const { return mCornerColor[index]; }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/* 0x100 */ JUTTexture* mTexture[2];
|
/* 0x100 */ JUTTexture* mTexture[2];
|
||||||
|
|||||||
@@ -3,20 +3,6 @@
|
|||||||
|
|
||||||
#include <gx.h>
|
#include <gx.h>
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
#include <mtx.h>
|
|
||||||
|
|
||||||
struct ParticleDrawCtx {
|
|
||||||
bool batch; // off = immediate mode
|
|
||||||
bool useTexMtx; // UVs transformed by texMtx
|
|
||||||
bool useClr0; // prm color in GX_VA_CLR0
|
|
||||||
bool useClr1; // env color in GX_VA_CLR1
|
|
||||||
Mtx texMtx;
|
|
||||||
GXColor clr0;
|
|
||||||
GXColor clr1;
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct JPAEmitterWorkData;
|
struct JPAEmitterWorkData;
|
||||||
class JPABaseParticle;
|
class JPABaseParticle;
|
||||||
class JKRHeap;
|
class JKRHeap;
|
||||||
@@ -89,9 +75,6 @@ public:
|
|||||||
|
|
||||||
const GXTevColorArg* getTevColorArg() const { return st_ca[(pBsd->mFlags >> 0x0F) & 0x07]; }
|
const GXTevColorArg* getTevColorArg() const { return st_ca[(pBsd->mFlags >> 0x0F) & 0x07]; }
|
||||||
const GXTevAlphaArg* getTevAlphaArg() const { return st_aa[(pBsd->mFlags >> 0x12) & 0x01]; }
|
const GXTevAlphaArg* getTevAlphaArg() const { return st_aa[(pBsd->mFlags >> 0x12) & 0x01]; }
|
||||||
#if TARGET_PC
|
|
||||||
u32 getTevColorArgSel() const { return (pBsd->mFlags >> 0x0F) & 0x07; }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
u32 getType() const { return (pBsd->mFlags >> 0) & 0x0F; }
|
u32 getType() const { return (pBsd->mFlags >> 0) & 0x0F; }
|
||||||
u32 getDirType() const { return (pBsd->mFlags >> 4) & 0x07; }
|
u32 getDirType() const { return (pBsd->mFlags >> 4) & 0x07; }
|
||||||
@@ -203,34 +186,26 @@ void JPARegistPrm(JPAEmitterWorkData*);
|
|||||||
void JPARegistEnv(JPAEmitterWorkData*);
|
void JPARegistEnv(JPAEmitterWorkData*);
|
||||||
void JPARegistPrmEnv(JPAEmitterWorkData*);
|
void JPARegistPrmEnv(JPAEmitterWorkData*);
|
||||||
|
|
||||||
#if TARGET_PC
|
void JPADrawPoint(JPAEmitterWorkData*, JPABaseParticle*);
|
||||||
#define JPA_DRAW_PARTICLE_ARGS JPAEmitterWorkData*, JPABaseParticle*, ParticleDrawCtx*
|
void JPADrawLine(JPAEmitterWorkData*, JPABaseParticle*);
|
||||||
#else
|
void JPADrawRotBillboard(JPAEmitterWorkData*, JPABaseParticle*);
|
||||||
#define JPA_DRAW_PARTICLE_ARGS JPAEmitterWorkData*, JPABaseParticle*
|
void JPADrawBillboard(JPAEmitterWorkData*, JPABaseParticle*);
|
||||||
#endif
|
void JPADrawRotDirection(JPAEmitterWorkData*, JPABaseParticle*);
|
||||||
|
void JPADrawDirection(JPAEmitterWorkData*, JPABaseParticle*);
|
||||||
void JPADrawPoint(JPA_DRAW_PARTICLE_ARGS);
|
void JPADrawRotation(JPAEmitterWorkData*, JPABaseParticle*);
|
||||||
void JPADrawLine(JPA_DRAW_PARTICLE_ARGS);
|
void JPADrawDBillboard(JPAEmitterWorkData*, JPABaseParticle*);
|
||||||
void JPADrawRotBillboard(JPA_DRAW_PARTICLE_ARGS);
|
void JPADrawRotYBillboard(JPAEmitterWorkData*, JPABaseParticle*);
|
||||||
void JPADrawBillboard(JPA_DRAW_PARTICLE_ARGS);
|
void JPADrawYBillboard(JPAEmitterWorkData*, JPABaseParticle*);
|
||||||
void JPADrawRotDirection(JPA_DRAW_PARTICLE_ARGS);
|
void JPADrawParticleCallBack(JPAEmitterWorkData*, JPABaseParticle*);
|
||||||
void JPADrawDirection(JPA_DRAW_PARTICLE_ARGS);
|
void JPALoadTexAnm(JPAEmitterWorkData*, JPABaseParticle*);
|
||||||
void JPADrawRotation(JPA_DRAW_PARTICLE_ARGS);
|
void JPASetPointSize(JPAEmitterWorkData*, JPABaseParticle*);
|
||||||
void JPADrawDBillboard(JPA_DRAW_PARTICLE_ARGS);
|
void JPASetLineWidth(JPAEmitterWorkData*, JPABaseParticle*);
|
||||||
void JPADrawRotYBillboard(JPA_DRAW_PARTICLE_ARGS);
|
void JPALoadCalcTexCrdMtxAnm(JPAEmitterWorkData*, JPABaseParticle*);
|
||||||
void JPADrawYBillboard(JPA_DRAW_PARTICLE_ARGS);
|
void JPARegistAlpha(JPAEmitterWorkData*, JPABaseParticle*);
|
||||||
void JPADrawParticleCallBack(JPA_DRAW_PARTICLE_ARGS);
|
void JPARegistEnv(JPAEmitterWorkData*, JPABaseParticle*);
|
||||||
void JPALoadTexAnm(JPA_DRAW_PARTICLE_ARGS);
|
void JPARegistAlphaEnv(JPAEmitterWorkData*, JPABaseParticle*);
|
||||||
void JPASetPointSize(JPA_DRAW_PARTICLE_ARGS);
|
void JPARegistPrmAlpha(JPAEmitterWorkData*, JPABaseParticle*);
|
||||||
void JPASetLineWidth(JPA_DRAW_PARTICLE_ARGS);
|
void JPARegistPrmAlphaEnv(JPAEmitterWorkData*, JPABaseParticle*);
|
||||||
void JPALoadCalcTexCrdMtxAnm(JPA_DRAW_PARTICLE_ARGS);
|
|
||||||
void JPARegistAlpha(JPA_DRAW_PARTICLE_ARGS);
|
|
||||||
void JPARegistEnv(JPA_DRAW_PARTICLE_ARGS);
|
|
||||||
void JPARegistAlphaEnv(JPA_DRAW_PARTICLE_ARGS);
|
|
||||||
void JPARegistPrmAlpha(JPA_DRAW_PARTICLE_ARGS);
|
|
||||||
void JPARegistPrmAlphaEnv(JPA_DRAW_PARTICLE_ARGS);
|
|
||||||
|
|
||||||
#undef JPA_DRAW_PARTICLE_ARGS
|
|
||||||
|
|
||||||
#if TARGET_PC
|
#if TARGET_PC
|
||||||
void JPAInterpBillboard(JPAEmitterWorkData*, JPABaseParticle*);
|
void JPAInterpBillboard(JPAEmitterWorkData*, JPABaseParticle*);
|
||||||
|
|||||||
@@ -17,10 +17,6 @@ class JPADynamicsBlock;
|
|||||||
class JPAFieldBlock;
|
class JPAFieldBlock;
|
||||||
class JPAKeyBlock;
|
class JPAKeyBlock;
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
struct ParticleDrawCtx;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ingroup jsystem-jparticle
|
* @ingroup jsystem-jparticle
|
||||||
*
|
*
|
||||||
@@ -54,19 +50,13 @@ public:
|
|||||||
public:
|
public:
|
||||||
typedef void (*EmitterFunc)(JPAEmitterWorkData*);
|
typedef void (*EmitterFunc)(JPAEmitterWorkData*);
|
||||||
typedef void (*ParticleFunc)(JPAEmitterWorkData*, JPABaseParticle*);
|
typedef void (*ParticleFunc)(JPAEmitterWorkData*, JPABaseParticle*);
|
||||||
#if TARGET_PC
|
|
||||||
typedef void (*DrawParticleFunc)(JPAEmitterWorkData*, JPABaseParticle*,
|
|
||||||
ParticleDrawCtx*);
|
|
||||||
#else
|
|
||||||
typedef ParticleFunc DrawParticleFunc;
|
|
||||||
#endif
|
|
||||||
/* 0x00 */ EmitterFunc* mpCalcEmitterFuncList;
|
/* 0x00 */ EmitterFunc* mpCalcEmitterFuncList;
|
||||||
/* 0x04 */ EmitterFunc* mpDrawEmitterFuncList;
|
/* 0x04 */ EmitterFunc* mpDrawEmitterFuncList;
|
||||||
/* 0x08 */ EmitterFunc* mpDrawEmitterChildFuncList;
|
/* 0x08 */ EmitterFunc* mpDrawEmitterChildFuncList;
|
||||||
/* 0x0C */ ParticleFunc* mpCalcParticleFuncList;
|
/* 0x0C */ ParticleFunc* mpCalcParticleFuncList;
|
||||||
/* 0x10 */ DrawParticleFunc* mpDrawParticleFuncList;
|
/* 0x10 */ ParticleFunc* mpDrawParticleFuncList;
|
||||||
/* 0x14 */ ParticleFunc* mpCalcParticleChildFuncList;
|
/* 0x14 */ ParticleFunc* mpCalcParticleChildFuncList;
|
||||||
/* 0x18 */ DrawParticleFunc* mpDrawParticleChildFuncList;
|
/* 0x18 */ ParticleFunc* mpDrawParticleChildFuncList;
|
||||||
|
|
||||||
/* 0x1C */ JPABaseShape* pBsp;
|
/* 0x1C */ JPABaseShape* pBsp;
|
||||||
/* 0x20 */ JPAExtraShape* pEsp;
|
/* 0x20 */ JPAExtraShape* pEsp;
|
||||||
@@ -87,20 +77,6 @@ public:
|
|||||||
/* 0x45 */ u8 mpDrawParticleFuncListNum;
|
/* 0x45 */ u8 mpDrawParticleFuncListNum;
|
||||||
/* 0x46 */ u8 mpCalcParticleChildFuncListNum;
|
/* 0x46 */ u8 mpCalcParticleChildFuncListNum;
|
||||||
/* 0x47 */ u8 mpDrawParticleChildFuncListNum;
|
/* 0x47 */ u8 mpDrawParticleChildFuncListNum;
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
struct BatchInfo {
|
|
||||||
f32 vtxPos[8][3];
|
|
||||||
f32 vtxUv[8][2];
|
|
||||||
u8 vtxCount; // 4 (quad) or 8 (cross)
|
|
||||||
bool supported; // draw func list contains only batchable funcs
|
|
||||||
bool hasPtclColor; // per-particle JPARegist* func is present
|
|
||||||
bool hasPtclTexMtx; // JPALoadCalcTexCrdMtxAnm is present
|
|
||||||
};
|
|
||||||
BatchInfo mBatchInfo;
|
|
||||||
|
|
||||||
void initBatchInfo();
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* JPARESOURCE_H */
|
#endif /* JPARESOURCE_H */
|
||||||
|
|||||||
@@ -542,11 +542,8 @@ void J3DModel::viewCalc() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TARGET_PC
|
#ifdef TARGET_PC
|
||||||
Mtx* drawMtx = getDrawMtxPtr();
|
for (u16 i = 0; i < mModelData->getDrawMtxNum(); ++i) {
|
||||||
if (drawMtx != J3DMtxBuffer::sNoUseDrawMtxPtr) {
|
dusk::frame_interp::record_final_mtx(getDrawMtxPtr()[i]);
|
||||||
for (u16 i = 0; i < mModelData->getDrawMtxNum(); ++i) {
|
|
||||||
dusk::frame_interp::record_final_mtx(drawMtx[i]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -136,8 +136,8 @@ void J3DLoadCPCmd(u8 addr, u32 val) {
|
|||||||
#if TARGET_PC
|
#if TARGET_PC
|
||||||
static void J3DLoadArrayBasePtr(GXAttr attr, void* data, u32 size, bool le) {
|
static void J3DLoadArrayBasePtr(GXAttr attr, void* data, u32 size, bool le) {
|
||||||
u32 idx = (attr == GX_VA_NBT) ? 1 : (attr - GX_VA_POS);
|
u32 idx = (attr == GX_VA_NBT) ? 1 : (attr - GX_VA_POS);
|
||||||
GXCmd1u8(GX_AURORA);
|
GXCmd1u8(GX_LOAD_AURORA);
|
||||||
GXCmd1u16(GX_AURORA_LOAD_ARRAYBASE | idx);
|
GXCmd1u16(GX_LOAD_AURORA_ARRAYBASE | idx);
|
||||||
GXCmd1u64((u64)data);
|
GXCmd1u64((u64)data);
|
||||||
GXCmd1u32(size);
|
GXCmd1u32(size);
|
||||||
GXCmd1u8(le ? 1 : 0);
|
GXCmd1u8(le ? 1 : 0);
|
||||||
|
|||||||
@@ -7,11 +7,265 @@
|
|||||||
#include "JSystem/JKernel/JKRHeap.h"
|
#include "JSystem/JKernel/JKRHeap.h"
|
||||||
|
|
||||||
#if TARGET_PC
|
#if TARGET_PC
|
||||||
#include <aurora/dl.hpp>
|
#include <algorithm>
|
||||||
#include <tracy/Tracy.hpp>
|
#include <tracy/Tracy.hpp>
|
||||||
|
#include <vector>
|
||||||
|
#include "dusk/logging.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
u16 read_be16(const u8* data) {
|
||||||
|
return (u16(data[0]) << 8) | data[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
void append_be16(std::vector<u8>& out, u16 value) {
|
||||||
|
out.push_back(value >> 8);
|
||||||
|
out.push_back(value & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
void append_bytes(std::vector<u8>& out, const u8* data, u32 size) {
|
||||||
|
out.insert(out.end(), data, data + size);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_matrix_idx_attr(GXAttr attr) {
|
||||||
|
return attr >= GX_VA_PNMTXIDX && attr <= GX_VA_TEX7MTXIDX;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_draw_opcode(u8 opcode) {
|
||||||
|
return opcode == GX_QUADS || opcode == GX_TRIANGLES || opcode == GX_TRIANGLESTRIP ||
|
||||||
|
opcode == GX_TRIANGLEFAN || opcode == GX_LINES || opcode == GX_LINESTRIP ||
|
||||||
|
opcode == GX_POINTS;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_mergeable_draw_opcode(u8 opcode) {
|
||||||
|
return opcode == GX_QUADS || opcode == GX_TRIANGLES || opcode == GX_TRIANGLESTRIP ||
|
||||||
|
opcode == GX_TRIANGLEFAN;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool calc_vtx_stride(const GXVtxDescList* vtxDesc, u32& stride) {
|
||||||
|
stride = 0;
|
||||||
|
for (; vtxDesc->attr != GX_VA_NULL; vtxDesc++) {
|
||||||
|
switch (vtxDesc->type) {
|
||||||
|
case GX_NONE:
|
||||||
|
break;
|
||||||
|
case GX_DIRECT:
|
||||||
|
if (!is_matrix_idx_attr(vtxDesc->attr)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
stride += 1;
|
||||||
|
break;
|
||||||
|
case GX_INDEX8:
|
||||||
|
stride += 1;
|
||||||
|
break;
|
||||||
|
case GX_INDEX16:
|
||||||
|
stride += 2;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return stride != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool get_command_size(const u8* dlStart, u32 dlSize, u32 offset, u32 stride, u32& cmdSize) {
|
||||||
|
if (offset >= dlSize) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const u8 cmd = dlStart[offset];
|
||||||
|
const u8 opcode = cmd & GX_OPCODE_MASK;
|
||||||
|
switch (opcode) {
|
||||||
|
case GX_NOP:
|
||||||
|
case GX_CMD_INVL_VC:
|
||||||
|
cmdSize = 1;
|
||||||
|
return true;
|
||||||
|
case (GX_LOAD_BP_REG & GX_OPCODE_MASK):
|
||||||
|
cmdSize = 5;
|
||||||
|
return offset + cmdSize <= dlSize;
|
||||||
|
case GX_LOAD_CP_REG:
|
||||||
|
cmdSize = 6;
|
||||||
|
return offset + cmdSize <= dlSize;
|
||||||
|
case GX_LOAD_XF_REG: {
|
||||||
|
if (offset + 5 > dlSize) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const u16 count = read_be16(dlStart + offset + 1) + 1;
|
||||||
|
cmdSize = 5 + count * 4;
|
||||||
|
return offset + cmdSize <= dlSize;
|
||||||
|
}
|
||||||
|
case GX_LOAD_INDX_A:
|
||||||
|
case GX_LOAD_INDX_B:
|
||||||
|
case GX_LOAD_INDX_C:
|
||||||
|
case GX_LOAD_INDX_D:
|
||||||
|
cmdSize = 5;
|
||||||
|
return offset + cmdSize <= dlSize;
|
||||||
|
case GX_CMD_CALL_DL:
|
||||||
|
cmdSize = 9;
|
||||||
|
return offset + cmdSize <= dlSize;
|
||||||
|
default:
|
||||||
|
if (is_draw_opcode(opcode)) {
|
||||||
|
if (offset + 3 > dlSize) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const u16 vtxCount = read_be16(dlStart + offset + 1);
|
||||||
|
cmdSize = 3 + vtxCount * stride;
|
||||||
|
return offset + cmdSize <= dlSize;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MergeRun {
|
||||||
|
u8 cmd = 0;
|
||||||
|
u16 vtxCount = 0;
|
||||||
|
std::vector<u8> vertices;
|
||||||
|
};
|
||||||
|
|
||||||
|
void flush_merge_run(std::vector<u8>& out, MergeRun& run) {
|
||||||
|
if (run.vtxCount == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
out.push_back(run.cmd);
|
||||||
|
append_be16(out, run.vtxCount);
|
||||||
|
append_bytes(out, run.vertices.data(), run.vertices.size());
|
||||||
|
run.vertices.clear();
|
||||||
|
run.vtxCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void append_vertex(std::vector<u8>& out, const u8* vertices, u32 stride, u16 idx) {
|
||||||
|
append_bytes(out, vertices + idx * stride, stride);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool triangulate_draw(
|
||||||
|
std::vector<u8>& out, u8 opcode, const u8* vertices, u32 stride, u16 vtxCount) {
|
||||||
|
switch (opcode) {
|
||||||
|
case GX_TRIANGLES:
|
||||||
|
append_bytes(out, vertices, vtxCount * stride);
|
||||||
|
return true;
|
||||||
|
case GX_TRIANGLEFAN:
|
||||||
|
if (vtxCount < 3) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (u16 v = 2; v < vtxCount; v++) {
|
||||||
|
append_vertex(out, vertices, stride, 0);
|
||||||
|
append_vertex(out, vertices, stride, v - 1);
|
||||||
|
append_vertex(out, vertices, stride, v);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
case GX_TRIANGLESTRIP:
|
||||||
|
if (vtxCount < 3) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (u16 v = 2; v < vtxCount; v++) {
|
||||||
|
if ((v & 1) == 0) {
|
||||||
|
append_vertex(out, vertices, stride, v - 2);
|
||||||
|
append_vertex(out, vertices, stride, v - 1);
|
||||||
|
} else {
|
||||||
|
append_vertex(out, vertices, stride, v - 1);
|
||||||
|
append_vertex(out, vertices, stride, v - 2);
|
||||||
|
}
|
||||||
|
append_vertex(out, vertices, stride, v);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
case GX_QUADS:
|
||||||
|
if ((vtxCount & 3) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (u16 v = 0; v < vtxCount; v += 4) {
|
||||||
|
append_vertex(out, vertices, stride, v);
|
||||||
|
append_vertex(out, vertices, stride, v + 1);
|
||||||
|
append_vertex(out, vertices, stride, v + 2);
|
||||||
|
append_vertex(out, vertices, stride, v + 2);
|
||||||
|
append_vertex(out, vertices, stride, v + 3);
|
||||||
|
append_vertex(out, vertices, stride, v);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void append_triangles_to_run(
|
||||||
|
std::vector<u8>& out, MergeRun& run, u8 cmd, const std::vector<u8>& vertices, u32 stride) {
|
||||||
|
u32 offset = 0;
|
||||||
|
u32 remaining = vertices.size() / stride;
|
||||||
|
while (remaining != 0) {
|
||||||
|
if (run.vtxCount != 0 && run.cmd != cmd) {
|
||||||
|
flush_merge_run(out, run);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (run.vtxCount == 0) {
|
||||||
|
run.cmd = cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 available = 0xFFFF - run.vtxCount;
|
||||||
|
if (available == 0) {
|
||||||
|
flush_merge_run(out, run);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 toCopy = std::min(remaining, available);
|
||||||
|
append_bytes(run.vertices, vertices.data() + offset * stride, toCopy * stride);
|
||||||
|
run.vtxCount += toCopy;
|
||||||
|
offset += toCopy;
|
||||||
|
remaining -= toCopy;
|
||||||
|
|
||||||
|
if (run.vtxCount == 0xFFFF) {
|
||||||
|
flush_merge_run(out, run);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool optimize_display_list(const u8* dlStart, u32 dlSize, u32 stride, std::vector<u8>& out) {
|
||||||
|
MergeRun run;
|
||||||
|
out.reserve(dlSize);
|
||||||
|
|
||||||
|
for (u32 offset = 0; offset < dlSize;) {
|
||||||
|
u32 cmdSize = 0;
|
||||||
|
if (!get_command_size(dlStart, dlSize, offset, stride, cmdSize)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const u8 cmd = dlStart[offset];
|
||||||
|
const u8 opcode = cmd & GX_OPCODE_MASK;
|
||||||
|
if (opcode == GX_NOP) {
|
||||||
|
offset += cmdSize;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_draw_opcode(opcode)) {
|
||||||
|
flush_merge_run(out, run);
|
||||||
|
append_bytes(out, dlStart + offset, cmdSize);
|
||||||
|
offset += cmdSize;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_mergeable_draw_opcode(opcode)) {
|
||||||
|
flush_merge_run(out, run);
|
||||||
|
append_bytes(out, dlStart + offset, cmdSize);
|
||||||
|
offset += cmdSize;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const u16 vtxCount = read_be16(dlStart + offset + 1);
|
||||||
|
const u8* vertices = dlStart + offset + 3;
|
||||||
|
std::vector<u8> triangles;
|
||||||
|
if (!triangulate_draw(triangles, opcode, vertices, stride, vtxCount)) {
|
||||||
|
flush_merge_run(out, run);
|
||||||
|
append_bytes(out, dlStart + offset, cmdSize);
|
||||||
|
offset += cmdSize;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
append_triangles_to_run(out, run, (GX_TRIANGLES | (cmd & GX_VAT_MASK)), triangles, stride);
|
||||||
|
offset += cmdSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
flush_merge_run(out, run);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void set_display_list_copy(void*& displayList, u32& displayListSize, const u8* data, u32 size) {
|
void set_display_list_copy(void*& displayList, u32& displayListSize, const u8* data, u32 size) {
|
||||||
const u32 alignedSize = ALIGN_NEXT(size, 0x20);
|
const u32 alignedSize = ALIGN_NEXT(size, 0x20);
|
||||||
u8* newDL = JKR_NEW_ARRAY_ARGS(u8, alignedSize, 0x20);
|
u8* newDL = JKR_NEW_ARRAY_ARGS(u8, alignedSize, 0x20);
|
||||||
@@ -35,11 +289,20 @@ u32 J3DShapeDraw::countVertex(u32 stride) {
|
|||||||
u8* dlStart = (u8*)getDisplayList();
|
u8* dlStart = (u8*)getDisplayList();
|
||||||
|
|
||||||
#if TARGET_PC
|
#if TARGET_PC
|
||||||
aurora::gx::dl::Reader reader{dlStart, getDisplayListSize(), static_cast<u8>(stride)};
|
for (u32 offset = 0; offset < getDisplayListSize();) {
|
||||||
while (const auto cmd = reader.next()) {
|
u8 cmd = dlStart[offset];
|
||||||
if (cmd->kind != aurora::gx::dl::Command::Kind::Passthrough) {
|
u8 opcode = cmd & GX_OPCODE_MASK;
|
||||||
count += cmd->draw.vtxCount;
|
u32 cmdSize = 0;
|
||||||
|
if (!get_command_size(dlStart, getDisplayListSize(), offset, stride, cmdSize)) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
if (!is_draw_opcode(opcode)) {
|
||||||
|
offset += cmdSize;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int vtxNum = be16(*reinterpret_cast<u16*>(dlStart + offset + 1));
|
||||||
|
count += vtxNum;
|
||||||
|
offset += 3 + stride * vtxNum;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
for (u8* dl = dlStart; (dl - dlStart) < getDisplayListSize();) {
|
for (u8* dl = dlStart; (dl - dlStart) < getDisplayListSize();) {
|
||||||
@@ -57,53 +320,6 @@ u32 J3DShapeDraw::countVertex(u32 stride) {
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
void J3DShapeDraw::addTexMtxIndexInDL(u32 stride, u32 attrOffs, u32 valueBase) {
|
|
||||||
u32 byteNum = countVertex(stride);
|
|
||||||
u32 oldSize = mDisplayListSize;
|
|
||||||
u32 newSize = ALIGN_NEXT(oldSize + byteNum, 0x20);
|
|
||||||
u8* newDLStart = JKR_NEW_ARRAY_ARGS(u8, newSize, 0x20);
|
|
||||||
u8* oldDLStart = (u8*)mDisplayList;
|
|
||||||
u8* newDL = newDLStart;
|
|
||||||
|
|
||||||
aurora::gx::dl::Reader reader{oldDLStart, mDisplayListSize, static_cast<u8>(stride)};
|
|
||||||
while (const auto cmd = reader.next()) {
|
|
||||||
if (cmd->kind == aurora::gx::dl::Command::Kind::Passthrough) {
|
|
||||||
std::memcpy(newDL, cmd->data, cmd->size);
|
|
||||||
newDL += cmd->size;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto& draw = cmd->draw;
|
|
||||||
const u32 headerSize = draw.vertices - cmd->data;
|
|
||||||
std::memcpy(newDL, cmd->data, headerSize);
|
|
||||||
newDL += headerSize;
|
|
||||||
|
|
||||||
for (u32 i = 0; i < draw.vtxCount; i++) {
|
|
||||||
const u8* oldVtx = draw.vertices + stride * i;
|
|
||||||
u8 pnmtxidx = oldVtx[0];
|
|
||||||
std::memcpy(newDL, oldVtx, attrOffs);
|
|
||||||
newDL += attrOffs;
|
|
||||||
*newDL++ = valueBase + pnmtxidx;
|
|
||||||
std::memcpy(newDL, oldVtx + attrOffs, stride - attrOffs);
|
|
||||||
newDL += stride - attrOffs;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (reader.failed()) {
|
|
||||||
// preserve the remainder untouched
|
|
||||||
std::memcpy(newDL, oldDLStart + reader.pos(), mDisplayListSize - reader.pos());
|
|
||||||
newDL += mDisplayListSize - reader.pos();
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 realSize = ALIGN_NEXT((uintptr_t)newDL - (uintptr_t)newDLStart, 0x20);
|
|
||||||
for (; (newDL - newDLStart) < newSize; newDL++)
|
|
||||||
*newDL = 0;
|
|
||||||
|
|
||||||
mDisplayListSize = realSize;
|
|
||||||
mDisplayList = newDLStart;
|
|
||||||
DCStoreRange(newDLStart, mDisplayListSize);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
void J3DShapeDraw::addTexMtxIndexInDL(u32 stride, u32 attrOffs, u32 valueBase) {
|
void J3DShapeDraw::addTexMtxIndexInDL(u32 stride, u32 attrOffs, u32 valueBase) {
|
||||||
u32 byteNum = countVertex(stride);
|
u32 byteNum = countVertex(stride);
|
||||||
u32 oldSize = mDisplayListSize;
|
u32 oldSize = mDisplayListSize;
|
||||||
@@ -114,13 +330,32 @@ void J3DShapeDraw::addTexMtxIndexInDL(u32 stride, u32 attrOffs, u32 valueBase) {
|
|||||||
u8* newDL = newDLStart;
|
u8* newDL = newDLStart;
|
||||||
|
|
||||||
for (; (oldDL - oldDLStart) < mDisplayListSize;) {
|
for (; (oldDL - oldDLStart) < mDisplayListSize;) {
|
||||||
|
#if TARGET_PC
|
||||||
|
u32 oldOffset = oldDL - oldDLStart;
|
||||||
|
u32 cmdSize = 0;
|
||||||
|
if (!get_command_size(oldDLStart, mDisplayListSize, oldOffset, stride, cmdSize)) {
|
||||||
|
memcpy(newDL, oldDL, mDisplayListSize - oldOffset);
|
||||||
|
newDL += mDisplayListSize - oldOffset;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
// Copy command
|
// Copy command
|
||||||
u8 cmd = *(u8*)oldDL;
|
u8 cmd = *(u8*)oldDL;
|
||||||
oldDL++;
|
oldDL++;
|
||||||
*newDL++ = cmd;
|
*newDL++ = cmd;
|
||||||
|
|
||||||
|
#if TARGET_PC
|
||||||
|
u8 opcode = cmd & GX_OPCODE_MASK;
|
||||||
|
if (!is_draw_opcode(opcode)) {
|
||||||
|
memcpy(newDL, oldDL, cmdSize - 1);
|
||||||
|
oldDL += cmdSize - 1;
|
||||||
|
newDL += cmdSize - 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#else
|
||||||
if (cmd != GX_TRIANGLEFAN && cmd != GX_TRIANGLESTRIP)
|
if (cmd != GX_TRIANGLEFAN && cmd != GX_TRIANGLESTRIP)
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Copy count
|
// Copy count
|
||||||
int vtxNum = *(u16*)oldDL;
|
int vtxNum = *(u16*)oldDL;
|
||||||
@@ -149,7 +384,6 @@ void J3DShapeDraw::addTexMtxIndexInDL(u32 stride, u32 attrOffs, u32 valueBase) {
|
|||||||
mDisplayList = newDLStart;
|
mDisplayList = newDLStart;
|
||||||
DCStoreRange(newDLStart, mDisplayListSize);
|
DCStoreRange(newDLStart, mDisplayListSize);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
J3DShapeDraw::J3DShapeDraw(const u8* displayList, u32 displayListSize) {
|
J3DShapeDraw::J3DShapeDraw(const u8* displayList, u32 displayListSize) {
|
||||||
#if TARGET_PC
|
#if TARGET_PC
|
||||||
@@ -163,8 +397,12 @@ J3DShapeDraw::J3DShapeDraw(const u8* displayList, u32 displayListSize) {
|
|||||||
#if TARGET_PC
|
#if TARGET_PC
|
||||||
J3DShapeDraw::J3DShapeDraw(
|
J3DShapeDraw::J3DShapeDraw(
|
||||||
const u8* displayList, u32 displayListSize, const GXVtxDescList* vtxDesc) {
|
const u8* displayList, u32 displayListSize, const GXVtxDescList* vtxDesc) {
|
||||||
if (const auto optimized = aurora::gx::dl::optimize(displayList, displayListSize, vtxDesc)) {
|
u32 stride = 0;
|
||||||
set_display_list_copy(mDisplayList, mDisplayListSize, optimized->data(), optimized->size());
|
std::vector<u8> optimized;
|
||||||
|
if (calc_vtx_stride(vtxDesc, stride) &&
|
||||||
|
optimize_display_list(displayList, displayListSize, stride, optimized))
|
||||||
|
{
|
||||||
|
set_display_list_copy(mDisplayList, mDisplayListSize, optimized.data(), optimized.size());
|
||||||
} else {
|
} else {
|
||||||
set_display_list_copy(mDisplayList, mDisplayListSize, displayList, displayListSize);
|
set_display_list_copy(mDisplayList, mDisplayListSize, displayList, displayListSize);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,33 +14,6 @@
|
|||||||
#endif
|
#endif
|
||||||
#include "tracy/Tracy.hpp"
|
#include "tracy/Tracy.hpp"
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
#define JPA_DRAW_CTX_PARAM , ParticleDrawCtx* ctx
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
GXColor emitter_prm_color(JPAEmitterWorkData* work) {
|
|
||||||
JPABaseEmitter* emtr = work->mpEmtr;
|
|
||||||
GXColor prm = emtr->mPrmClr;
|
|
||||||
prm.r = COLOR_MULTI(prm.r, emtr->mGlobalPrmClr.r);
|
|
||||||
prm.g = COLOR_MULTI(prm.g, emtr->mGlobalPrmClr.g);
|
|
||||||
prm.b = COLOR_MULTI(prm.b, emtr->mGlobalPrmClr.b);
|
|
||||||
prm.a = COLOR_MULTI(prm.a, emtr->mGlobalPrmClr.a);
|
|
||||||
return prm;
|
|
||||||
}
|
|
||||||
|
|
||||||
GXColor emitter_env_color(JPAEmitterWorkData* work) {
|
|
||||||
JPABaseEmitter* emtr = work->mpEmtr;
|
|
||||||
GXColor env = emtr->mEnvClr;
|
|
||||||
env.r = COLOR_MULTI(env.r, emtr->mGlobalEnvClr.r);
|
|
||||||
env.g = COLOR_MULTI(env.g, emtr->mGlobalEnvClr.g);
|
|
||||||
env.b = COLOR_MULTI(env.b, emtr->mGlobalEnvClr.b);
|
|
||||||
return env;
|
|
||||||
}
|
|
||||||
} // namespace
|
|
||||||
#else
|
|
||||||
#define JPA_DRAW_CTX_PARAM
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void JPASetPointSize(JPAEmitterWorkData* work) {
|
void JPASetPointSize(JPAEmitterWorkData* work) {
|
||||||
GXSetPointSize((u8)(25.0f * work->mGlobalPtclScl.x), GX_TO_ONE);
|
GXSetPointSize((u8)(25.0f * work->mGlobalPtclScl.x), GX_TO_ONE);
|
||||||
}
|
}
|
||||||
@@ -49,16 +22,15 @@ void JPASetLineWidth(JPAEmitterWorkData* work) {
|
|||||||
GXSetLineWidth((u8)(25.0f * work->mGlobalPtclScl.x), GX_TO_ONE);
|
GXSetLineWidth((u8)(25.0f * work->mGlobalPtclScl.x), GX_TO_ONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JPASetPointSize(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
|
void JPASetPointSize(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
|
||||||
GXSetPointSize((u8)(ptcl->mParticleScaleX * (25.0f * work->mGlobalPtclScl.x)), GX_TO_ONE);
|
GXSetPointSize((u8)(ptcl->mParticleScaleX * (25.0f * work->mGlobalPtclScl.x)), GX_TO_ONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JPASetLineWidth(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
|
void JPASetLineWidth(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
|
||||||
GXSetLineWidth((u8)(ptcl->mParticleScaleX * (25.0f * work->mGlobalPtclScl.x)), GX_TO_ONE);
|
GXSetLineWidth((u8)(ptcl->mParticleScaleX * (25.0f * work->mGlobalPtclScl.x)), GX_TO_ONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JPARegistPrm(JPAEmitterWorkData* work) {
|
void JPARegistPrm(JPAEmitterWorkData* work) {
|
||||||
ZoneScoped;
|
|
||||||
JPABaseEmitter* emtr = work->mpEmtr;
|
JPABaseEmitter* emtr = work->mpEmtr;
|
||||||
GXColor prm = emtr->mPrmClr;
|
GXColor prm = emtr->mPrmClr;
|
||||||
prm.r = COLOR_MULTI(prm.r, emtr->mGlobalPrmClr.r);
|
prm.r = COLOR_MULTI(prm.r, emtr->mGlobalPrmClr.r);
|
||||||
@@ -69,7 +41,6 @@ void JPARegistPrm(JPAEmitterWorkData* work) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void JPARegistEnv(JPAEmitterWorkData* work) {
|
void JPARegistEnv(JPAEmitterWorkData* work) {
|
||||||
ZoneScoped;
|
|
||||||
JPABaseEmitter* emtr = work->mpEmtr;
|
JPABaseEmitter* emtr = work->mpEmtr;
|
||||||
GXColor env = emtr->mEnvClr;
|
GXColor env = emtr->mEnvClr;
|
||||||
env.r = COLOR_MULTI(env.r, emtr->mGlobalEnvClr.r);
|
env.r = COLOR_MULTI(env.r, emtr->mGlobalEnvClr.r);
|
||||||
@@ -79,7 +50,6 @@ void JPARegistEnv(JPAEmitterWorkData* work) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void JPARegistPrmEnv(JPAEmitterWorkData* work) {
|
void JPARegistPrmEnv(JPAEmitterWorkData* work) {
|
||||||
ZoneScoped;
|
|
||||||
JPABaseEmitter* emtr = work->mpEmtr;
|
JPABaseEmitter* emtr = work->mpEmtr;
|
||||||
GXColor prm = emtr->mPrmClr;
|
GXColor prm = emtr->mPrmClr;
|
||||||
GXColor env = emtr->mEnvClr;
|
GXColor env = emtr->mEnvClr;
|
||||||
@@ -94,8 +64,7 @@ void JPARegistPrmEnv(JPAEmitterWorkData* work) {
|
|||||||
GXSetTevColor(GX_TEVREG1, env);
|
GXSetTevColor(GX_TEVREG1, env);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JPARegistAlpha(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
|
void JPARegistAlpha(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
|
||||||
ZoneScoped;
|
|
||||||
JPABaseEmitter* emtr = work->mpEmtr;
|
JPABaseEmitter* emtr = work->mpEmtr;
|
||||||
GXColor prm = emtr->mPrmClr;
|
GXColor prm = emtr->mPrmClr;
|
||||||
prm.r = COLOR_MULTI(prm.r, emtr->mGlobalPrmClr.r);
|
prm.r = COLOR_MULTI(prm.r, emtr->mGlobalPrmClr.r);
|
||||||
@@ -103,19 +72,10 @@ void JPARegistAlpha(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX
|
|||||||
prm.b = COLOR_MULTI(prm.b, emtr->mGlobalPrmClr.b);
|
prm.b = COLOR_MULTI(prm.b, emtr->mGlobalPrmClr.b);
|
||||||
prm.a = COLOR_MULTI(prm.a, emtr->mGlobalPrmClr.a);
|
prm.a = COLOR_MULTI(prm.a, emtr->mGlobalPrmClr.a);
|
||||||
prm.a = COLOR_MULTI(prm.a, ptcl->mPrmColorAlphaAnm);
|
prm.a = COLOR_MULTI(prm.a, ptcl->mPrmColorAlphaAnm);
|
||||||
#if TARGET_PC
|
|
||||||
if (ctx->batch) {
|
|
||||||
ctx->clr0 = prm;
|
|
||||||
if (ctx->useClr1) {
|
|
||||||
ctx->clr1 = emitter_env_color(work);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
GXSetTevColor(GX_TEVREG0, prm);
|
GXSetTevColor(GX_TEVREG0, prm);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JPARegistPrmAlpha(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
|
void JPARegistPrmAlpha(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
|
||||||
ZoneScoped;
|
ZoneScoped;
|
||||||
JPABaseEmitter* emtr = work->mpEmtr;
|
JPABaseEmitter* emtr = work->mpEmtr;
|
||||||
GXColor prm = ptcl->mPrmClr;
|
GXColor prm = ptcl->mPrmClr;
|
||||||
@@ -124,19 +84,10 @@ void JPARegistPrmAlpha(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_
|
|||||||
prm.b = COLOR_MULTI(prm.b, emtr->mGlobalPrmClr.b);
|
prm.b = COLOR_MULTI(prm.b, emtr->mGlobalPrmClr.b);
|
||||||
prm.a = COLOR_MULTI(prm.a, emtr->mGlobalPrmClr.a);
|
prm.a = COLOR_MULTI(prm.a, emtr->mGlobalPrmClr.a);
|
||||||
prm.a = COLOR_MULTI(prm.a, ptcl->mPrmColorAlphaAnm);
|
prm.a = COLOR_MULTI(prm.a, ptcl->mPrmColorAlphaAnm);
|
||||||
#if TARGET_PC
|
|
||||||
if (ctx->batch) {
|
|
||||||
ctx->clr0 = prm;
|
|
||||||
if (ctx->useClr1) {
|
|
||||||
ctx->clr1 = emitter_env_color(work);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
GXSetTevColor(GX_TEVREG0, prm);
|
GXSetTevColor(GX_TEVREG0, prm);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JPARegistPrmAlphaEnv(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
|
void JPARegistPrmAlphaEnv(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
|
||||||
ZoneScoped;
|
ZoneScoped;
|
||||||
JPABaseEmitter* emtr = work->mpEmtr;
|
JPABaseEmitter* emtr = work->mpEmtr;
|
||||||
GXColor prm = ptcl->mPrmClr;
|
GXColor prm = ptcl->mPrmClr;
|
||||||
@@ -149,19 +100,11 @@ void JPARegistPrmAlphaEnv(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DR
|
|||||||
env.r = COLOR_MULTI(env.r, emtr->mGlobalEnvClr.r);
|
env.r = COLOR_MULTI(env.r, emtr->mGlobalEnvClr.r);
|
||||||
env.g = COLOR_MULTI(env.g, emtr->mGlobalEnvClr.g);
|
env.g = COLOR_MULTI(env.g, emtr->mGlobalEnvClr.g);
|
||||||
env.b = COLOR_MULTI(env.b, emtr->mGlobalEnvClr.b);
|
env.b = COLOR_MULTI(env.b, emtr->mGlobalEnvClr.b);
|
||||||
#if TARGET_PC
|
|
||||||
if (ctx->batch) {
|
|
||||||
ctx->clr0 = prm;
|
|
||||||
ctx->clr1 = env;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
GXSetTevColor(GX_TEVREG0, prm);
|
GXSetTevColor(GX_TEVREG0, prm);
|
||||||
GXSetTevColor(GX_TEVREG1, env);
|
GXSetTevColor(GX_TEVREG1, env);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JPARegistAlphaEnv(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
|
void JPARegistAlphaEnv(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
|
||||||
ZoneScoped;
|
|
||||||
JPABaseEmitter* emtr = work->mpEmtr;
|
JPABaseEmitter* emtr = work->mpEmtr;
|
||||||
GXColor prm = emtr->mPrmClr;
|
GXColor prm = emtr->mPrmClr;
|
||||||
GXColor env = ptcl->mEnvClr;
|
GXColor env = ptcl->mEnvClr;
|
||||||
@@ -173,31 +116,16 @@ void JPARegistAlphaEnv(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_
|
|||||||
env.r = COLOR_MULTI(env.r, emtr->mGlobalEnvClr.r);
|
env.r = COLOR_MULTI(env.r, emtr->mGlobalEnvClr.r);
|
||||||
env.g = COLOR_MULTI(env.g, emtr->mGlobalEnvClr.g);
|
env.g = COLOR_MULTI(env.g, emtr->mGlobalEnvClr.g);
|
||||||
env.b = COLOR_MULTI(env.b, emtr->mGlobalEnvClr.b);
|
env.b = COLOR_MULTI(env.b, emtr->mGlobalEnvClr.b);
|
||||||
#if TARGET_PC
|
|
||||||
if (ctx->batch) {
|
|
||||||
ctx->clr0 = prm;
|
|
||||||
ctx->clr1 = env;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
GXSetTevColor(GX_TEVREG0, prm);
|
GXSetTevColor(GX_TEVREG0, prm);
|
||||||
GXSetTevColor(GX_TEVREG1, env);
|
GXSetTevColor(GX_TEVREG1, env);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JPARegistEnv(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
|
void JPARegistEnv(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
|
||||||
ZoneScoped;
|
|
||||||
JPABaseEmitter* emtr = work->mpEmtr;
|
JPABaseEmitter* emtr = work->mpEmtr;
|
||||||
GXColor env = ptcl->mEnvClr;
|
GXColor env = ptcl->mEnvClr;
|
||||||
env.r = COLOR_MULTI(env.r, emtr->mGlobalEnvClr.r);
|
env.r = COLOR_MULTI(env.r, emtr->mGlobalEnvClr.r);
|
||||||
env.g = COLOR_MULTI(env.g, emtr->mGlobalEnvClr.g);
|
env.g = COLOR_MULTI(env.g, emtr->mGlobalEnvClr.g);
|
||||||
env.b = COLOR_MULTI(env.b, emtr->mGlobalEnvClr.b);
|
env.b = COLOR_MULTI(env.b, emtr->mGlobalEnvClr.b);
|
||||||
#if TARGET_PC
|
|
||||||
if (ctx->batch) {
|
|
||||||
ctx->clr0 = emitter_prm_color(work);
|
|
||||||
ctx->clr1 = env;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
GXSetTevColor(GX_TEVREG1, env);
|
GXSetTevColor(GX_TEVREG1, env);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -330,7 +258,7 @@ void JPAGenCalcTexCrdMtxAnm(JPAEmitterWorkData* work) {
|
|||||||
GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_TEXMTX0);
|
GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_TEXMTX0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JPALoadCalcTexCrdMtxAnm(JPAEmitterWorkData* work, JPABaseParticle* param_1 JPA_DRAW_CTX_PARAM) {
|
void JPALoadCalcTexCrdMtxAnm(JPAEmitterWorkData* work, JPABaseParticle* param_1) {
|
||||||
ZoneScoped;
|
ZoneScoped;
|
||||||
JPABaseShape* shape = work->mpRes->getBsp();
|
JPABaseShape* shape = work->mpRes->getBsp();
|
||||||
f32 dVar16 = param_1->mAge;
|
f32 dVar16 = param_1->mAge;
|
||||||
@@ -358,12 +286,6 @@ void JPALoadCalcTexCrdMtxAnm(JPAEmitterWorkData* work, JPABaseParticle* param_1
|
|||||||
local_108[2][1] = 0.0f;
|
local_108[2][1] = 0.0f;
|
||||||
local_108[2][2] = 1.0f;
|
local_108[2][2] = 1.0f;
|
||||||
local_108[2][3] = 0.0f;
|
local_108[2][3] = 0.0f;
|
||||||
#if TARGET_PC
|
|
||||||
if (ctx->batch) {
|
|
||||||
MTXCopy(local_108, ctx->texMtx);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
GXLoadTexMtxImm(local_108, 0x1e, GX_MTX2x4);
|
GXLoadTexMtxImm(local_108, 0x1e, GX_MTX2x4);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -377,7 +299,7 @@ void JPALoadTexAnm(JPAEmitterWorkData* work) {
|
|||||||
work->mpResMgr->load(work->mpRes->getTexIdx(work->mpEmtr->mTexAnmIdx), GX_TEXMAP0);
|
work->mpResMgr->load(work->mpRes->getTexIdx(work->mpEmtr->mTexAnmIdx), GX_TEXMAP0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JPALoadTexAnm(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
|
void JPALoadTexAnm(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
|
||||||
ZoneScoped;
|
ZoneScoped;
|
||||||
work->mpResMgr->load(work->mpRes->getTexIdx(ptcl->mTexAnmIdx), GX_TEXMAP0);
|
work->mpResMgr->load(work->mpRes->getTexIdx(ptcl->mTexAnmIdx), GX_TEXMAP0);
|
||||||
}
|
}
|
||||||
@@ -507,47 +429,6 @@ static projectionFunc p_prj[3] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#if TARGET_PC
|
#if TARGET_PC
|
||||||
static void emit_batch_quad(JPAEmitterWorkData* work, const ParticleDrawCtx* ctx,
|
|
||||||
const Mtx posMtx) {
|
|
||||||
const JPAResource::BatchInfo& info = work->mpRes->mBatchInfo;
|
|
||||||
|
|
||||||
for (int i = 0; i < info.vtxCount; i++) {
|
|
||||||
Vec localPos = {info.vtxPos[i][0], info.vtxPos[i][1], info.vtxPos[i][2]};
|
|
||||||
Vec drawPos;
|
|
||||||
MTXMultVec(posMtx, &localPos, &drawPos);
|
|
||||||
|
|
||||||
f32 texS = info.vtxUv[i][0];
|
|
||||||
f32 texT = info.vtxUv[i][1];
|
|
||||||
if (ctx->useTexMtx) {
|
|
||||||
f32 srcS = texS;
|
|
||||||
f32 srcT = texT;
|
|
||||||
texS = ctx->texMtx[0][0] * srcS + ctx->texMtx[0][1] * srcT + ctx->texMtx[0][3];
|
|
||||||
texT = ctx->texMtx[1][0] * srcS + ctx->texMtx[1][1] * srcT + ctx->texMtx[1][3];
|
|
||||||
}
|
|
||||||
|
|
||||||
GXPosition3f32(drawPos.x, drawPos.y, drawPos.z);
|
|
||||||
if (ctx->useClr0) {
|
|
||||||
GXColor4u8(ctx->clr0.r, ctx->clr0.g, ctx->clr0.b, ctx->clr0.a);
|
|
||||||
}
|
|
||||||
if (ctx->useClr1) {
|
|
||||||
GXColor4u8(ctx->clr1.r, ctx->clr1.g, ctx->clr1.b, ctx->clr1.a);
|
|
||||||
}
|
|
||||||
GXTexCoord2f32(texS, texT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void submit_particle_quad(
|
|
||||||
JPAEmitterWorkData* work, ParticleDrawCtx* ctx, const Mtx posMtx, const u8* dl, u32 dlSize) {
|
|
||||||
if (ctx->batch) {
|
|
||||||
emit_batch_quad(work, ctx, posMtx);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
GXLoadPosMtxImm(posMtx, GX_PNMTX0);
|
|
||||||
p_prj[work->mPrjType](work, posMtx);
|
|
||||||
GXCallDisplayList(dl, dlSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
void JPAInterpBillboard(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
|
void JPAInterpBillboard(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
|
||||||
Mtx ptclPosMtx;
|
Mtx ptclPosMtx;
|
||||||
MTXTrans(ptclPosMtx, ptcl->mPosition.x, ptcl->mPosition.y, ptcl->mPosition.z);
|
MTXTrans(ptclPosMtx, ptcl->mPosition.x, ptcl->mPosition.y, ptcl->mPosition.z);
|
||||||
@@ -567,7 +448,7 @@ void JPAInterpRotBillboard(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void JPADrawBillboard(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
|
void JPADrawBillboard(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
|
||||||
if (ptcl->checkStatus(JPAPtclStts_Invisible)) {
|
if (ptcl->checkStatus(JPAPtclStts_Invisible)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -592,16 +473,12 @@ void JPADrawBillboard(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_C
|
|||||||
posMtx[2][2] = 1.0f;
|
posMtx[2][2] = 1.0f;
|
||||||
posMtx[2][3] = pos.z;
|
posMtx[2][3] = pos.z;
|
||||||
posMtx[0][1] = posMtx[0][2] = posMtx[1][0] = posMtx[1][2] = posMtx[2][0] = posMtx[2][1] = 0.0f;
|
posMtx[0][1] = posMtx[0][2] = posMtx[1][0] = posMtx[1][2] = posMtx[2][0] = posMtx[2][1] = 0.0f;
|
||||||
#if TARGET_PC
|
|
||||||
submit_particle_quad(work, ctx, posMtx, jpa_dl, sizeof(jpa_dl));
|
|
||||||
#else
|
|
||||||
GXLoadPosMtxImm(posMtx, GX_PNMTX0);
|
GXLoadPosMtxImm(posMtx, GX_PNMTX0);
|
||||||
p_prj[work->mPrjType](work, posMtx);
|
p_prj[work->mPrjType](work, posMtx);
|
||||||
GXCallDisplayList(jpa_dl, sizeof(jpa_dl));
|
GXCallDisplayList(jpa_dl, sizeof(jpa_dl));
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void JPADrawRotBillboard(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
|
void JPADrawRotBillboard(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
|
||||||
if (ptcl->checkStatus(JPAPtclStts_Invisible)) {
|
if (ptcl->checkStatus(JPAPtclStts_Invisible)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -640,16 +517,12 @@ void JPADrawRotBillboard(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRA
|
|||||||
posMtx[2][2] = 1.0f;
|
posMtx[2][2] = 1.0f;
|
||||||
posMtx[2][3] = pos.z;
|
posMtx[2][3] = pos.z;
|
||||||
posMtx[0][2] = posMtx[1][2] = posMtx[2][0] = posMtx[2][1] = 0.0f;
|
posMtx[0][2] = posMtx[1][2] = posMtx[2][0] = posMtx[2][1] = 0.0f;
|
||||||
#if TARGET_PC
|
|
||||||
submit_particle_quad(work, ctx, posMtx, jpa_dl, sizeof(jpa_dl));
|
|
||||||
#else
|
|
||||||
GXLoadPosMtxImm(posMtx, GX_PNMTX0);
|
GXLoadPosMtxImm(posMtx, GX_PNMTX0);
|
||||||
p_prj[work->mPrjType](work, posMtx);
|
p_prj[work->mPrjType](work, posMtx);
|
||||||
GXCallDisplayList(jpa_dl, sizeof(jpa_dl));
|
GXCallDisplayList(jpa_dl, sizeof(jpa_dl));
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void JPADrawYBillboard(JPAEmitterWorkData* work, JPABaseParticle* param_1 JPA_DRAW_CTX_PARAM) {
|
void JPADrawYBillboard(JPAEmitterWorkData* work, JPABaseParticle* param_1) {
|
||||||
if (param_1->checkStatus(JPAPtclStts_Invisible)) {
|
if (param_1->checkStatus(JPAPtclStts_Invisible)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -669,16 +542,12 @@ void JPADrawYBillboard(JPAEmitterWorkData* work, JPABaseParticle* param_1 JPA_DR
|
|||||||
local_38[2][2] = work->mYBBCamMtx[2][2];
|
local_38[2][2] = work->mYBBCamMtx[2][2];
|
||||||
local_38[2][3] = local_48.z;
|
local_38[2][3] = local_48.z;
|
||||||
local_38[0][1] = local_38[0][2] = local_38[1][0] = local_38[2][0] = 0.0f;
|
local_38[0][1] = local_38[0][2] = local_38[1][0] = local_38[2][0] = 0.0f;
|
||||||
#if TARGET_PC
|
|
||||||
submit_particle_quad(work, ctx, local_38, jpa_dl, sizeof(jpa_dl));
|
|
||||||
#else
|
|
||||||
GXLoadPosMtxImm(local_38, GX_PNMTX0);
|
GXLoadPosMtxImm(local_38, GX_PNMTX0);
|
||||||
p_prj[work->mPrjType](work, local_38);
|
p_prj[work->mPrjType](work, local_38);
|
||||||
GXCallDisplayList(jpa_dl, sizeof(jpa_dl));
|
GXCallDisplayList(jpa_dl, sizeof(jpa_dl));
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void JPADrawRotYBillboard(JPAEmitterWorkData* work, JPABaseParticle* param_1 JPA_DRAW_CTX_PARAM) {
|
void JPADrawRotYBillboard(JPAEmitterWorkData* work, JPABaseParticle* param_1) {
|
||||||
if (param_1->checkStatus(JPAPtclStts_Invisible)) {
|
if (param_1->checkStatus(JPAPtclStts_Invisible)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -707,13 +576,9 @@ void JPADrawRotYBillboard(JPAEmitterWorkData* work, JPABaseParticle* param_1 JPA
|
|||||||
local_38[2][1] = local_94 * fVar1;
|
local_38[2][1] = local_94 * fVar1;
|
||||||
local_38[2][2] = local_90;
|
local_38[2][2] = local_90;
|
||||||
local_38[2][3] = local_48.z;
|
local_38[2][3] = local_48.z;
|
||||||
#if TARGET_PC
|
|
||||||
submit_particle_quad(work, ctx, local_38, jpa_dl, sizeof(jpa_dl));
|
|
||||||
#else
|
|
||||||
GXLoadPosMtxImm(local_38, GX_PNMTX0);
|
GXLoadPosMtxImm(local_38, GX_PNMTX0);
|
||||||
p_prj[work->mPrjType](work, local_38);
|
p_prj[work->mPrjType](work, local_38);
|
||||||
GXCallDisplayList(jpa_dl, sizeof(jpa_dl));
|
GXCallDisplayList(jpa_dl, sizeof(jpa_dl));
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void dirTypeVel(JPAEmitterWorkData const* work, JPABaseParticle const* param_1,
|
void dirTypeVel(JPAEmitterWorkData const* work, JPABaseParticle const* param_1,
|
||||||
@@ -876,88 +741,6 @@ static u8* p_dl[2] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#if TARGET_PC
|
#if TARGET_PC
|
||||||
static bool make_direction_mtx(JPAEmitterWorkData* work, JPABaseParticle* ptcl, Mtx posMtx) {
|
|
||||||
JGeometry::TVec3<f32> axisY;
|
|
||||||
JGeometry::TVec3<f32> axisZ;
|
|
||||||
JGeometry::TVec3<f32> baseAxis(ptcl->mBaseAxis);
|
|
||||||
p_direction[work->mDirType](work, ptcl, &axisY);
|
|
||||||
if (axisY.isZero()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
axisY.normalize();
|
|
||||||
axisZ.cross(baseAxis, axisY);
|
|
||||||
if (axisZ.isZero()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
axisZ.normalize();
|
|
||||||
baseAxis.cross(axisY, axisZ);
|
|
||||||
baseAxis.normalize();
|
|
||||||
ptcl->mBaseAxis.set(baseAxis);
|
|
||||||
|
|
||||||
f32 scaleX = work->mGlobalPtclScl.x * ptcl->mParticleScaleX;
|
|
||||||
f32 scaleY = work->mGlobalPtclScl.y * ptcl->mParticleScaleY;
|
|
||||||
posMtx[0][0] = baseAxis.x;
|
|
||||||
posMtx[0][1] = axisY.x;
|
|
||||||
posMtx[0][2] = axisZ.x;
|
|
||||||
posMtx[0][3] = ptcl->mPosition.x;
|
|
||||||
posMtx[1][0] = baseAxis.y;
|
|
||||||
posMtx[1][1] = axisY.y;
|
|
||||||
posMtx[1][2] = axisZ.y;
|
|
||||||
posMtx[1][3] = ptcl->mPosition.y;
|
|
||||||
posMtx[2][0] = baseAxis.z;
|
|
||||||
posMtx[2][1] = axisY.z;
|
|
||||||
posMtx[2][2] = axisZ.z;
|
|
||||||
posMtx[2][3] = ptcl->mPosition.z;
|
|
||||||
p_plane[work->mPlaneType](posMtx, scaleX, scaleY);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool make_rot_direction_mtx(JPAEmitterWorkData* work, JPABaseParticle* ptcl, Mtx posMtx) {
|
|
||||||
f32 sinRot = JMASSin(ptcl->mRotateAngle);
|
|
||||||
f32 cosRot = JMASCos(ptcl->mRotateAngle);
|
|
||||||
JGeometry::TVec3<f32> axisY;
|
|
||||||
JGeometry::TVec3<f32> axisZ;
|
|
||||||
JGeometry::TVec3<f32> baseAxis(ptcl->mBaseAxis);
|
|
||||||
p_direction[work->mDirType](work, ptcl, &axisY);
|
|
||||||
if (axisY.isZero()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
axisY.normalize();
|
|
||||||
axisZ.cross(baseAxis, axisY);
|
|
||||||
if (axisZ.isZero()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
axisZ.normalize();
|
|
||||||
baseAxis.cross(axisY, axisZ);
|
|
||||||
baseAxis.normalize();
|
|
||||||
ptcl->mBaseAxis.set(baseAxis);
|
|
||||||
|
|
||||||
f32 scaleX = work->mGlobalPtclScl.x * ptcl->mParticleScaleX;
|
|
||||||
f32 scaleY = work->mGlobalPtclScl.y * ptcl->mParticleScaleY;
|
|
||||||
Mtx rotMtx;
|
|
||||||
Mtx dirMtx;
|
|
||||||
p_rot[work->mRotType](sinRot, cosRot, rotMtx);
|
|
||||||
p_plane[work->mPlaneType](rotMtx, scaleX, scaleY);
|
|
||||||
dirMtx[0][0] = baseAxis.x;
|
|
||||||
dirMtx[0][1] = axisY.x;
|
|
||||||
dirMtx[0][2] = axisZ.x;
|
|
||||||
dirMtx[0][3] = ptcl->mPosition.x;
|
|
||||||
dirMtx[1][0] = baseAxis.y;
|
|
||||||
dirMtx[1][1] = axisY.y;
|
|
||||||
dirMtx[1][2] = axisZ.y;
|
|
||||||
dirMtx[1][3] = ptcl->mPosition.y;
|
|
||||||
dirMtx[2][0] = baseAxis.z;
|
|
||||||
dirMtx[2][1] = axisY.z;
|
|
||||||
dirMtx[2][2] = axisZ.z;
|
|
||||||
dirMtx[2][3] = ptcl->mPosition.z;
|
|
||||||
MTXConcat(dirMtx, rotMtx, posMtx);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void JPAInterpDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
|
void JPAInterpDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
|
||||||
JGeometry::TVec3<f32> axisY;
|
JGeometry::TVec3<f32> axisY;
|
||||||
JGeometry::TVec3<f32> axisZ;
|
JGeometry::TVec3<f32> axisZ;
|
||||||
@@ -1040,7 +823,7 @@ void JPAInterpRotDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void JPADrawDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
|
void JPADrawDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
|
||||||
if (ptcl->checkStatus(JPAPtclStts_Invisible)) {
|
if (ptcl->checkStatus(JPAPtclStts_Invisible)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1049,12 +832,8 @@ void JPADrawDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_C
|
|||||||
|
|
||||||
Mtx posMtx;
|
Mtx posMtx;
|
||||||
#if TARGET_PC
|
#if TARGET_PC
|
||||||
if (!dusk::frame_interp::lookup_replacement(ptcl, posMtx) &&
|
if (!dusk::frame_interp::lookup_replacement(ptcl, posMtx))
|
||||||
!make_direction_mtx(work, ptcl, posMtx))
|
#endif
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
{
|
{
|
||||||
JGeometry::TVec3<f32> axisY;
|
JGeometry::TVec3<f32> axisY;
|
||||||
JGeometry::TVec3<f32> axisZ;
|
JGeometry::TVec3<f32> axisZ;
|
||||||
@@ -1090,19 +869,14 @@ void JPADrawDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_C
|
|||||||
posMtx[2][3] = ptcl->mPosition.z;
|
posMtx[2][3] = ptcl->mPosition.z;
|
||||||
p_plane[work->mPlaneType](posMtx, scaleX, scaleY);
|
p_plane[work->mPlaneType](posMtx, scaleX, scaleY);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
MTXConcat(work->mPosCamMtx, posMtx, posMtx);
|
MTXConcat(work->mPosCamMtx, posMtx, posMtx);
|
||||||
#if TARGET_PC
|
|
||||||
submit_particle_quad(work, ctx, posMtx, p_dl[work->mDLType], sizeof(jpa_dl));
|
|
||||||
#else
|
|
||||||
GXLoadPosMtxImm(posMtx, GX_PNMTX0);
|
GXLoadPosMtxImm(posMtx, GX_PNMTX0);
|
||||||
p_prj[work->mPrjType](work, posMtx);
|
p_prj[work->mPrjType](work, posMtx);
|
||||||
GXCallDisplayList(p_dl[work->mDLType], sizeof(jpa_dl));
|
GXCallDisplayList(p_dl[work->mDLType], sizeof(jpa_dl));
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void JPADrawRotDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
|
void JPADrawRotDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
|
||||||
if (ptcl->checkStatus(JPAPtclStts_Invisible)) {
|
if (ptcl->checkStatus(JPAPtclStts_Invisible)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1112,12 +886,8 @@ void JPADrawRotDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRA
|
|||||||
Mtx mtx1;
|
Mtx mtx1;
|
||||||
Mtx mtx2;
|
Mtx mtx2;
|
||||||
#if TARGET_PC
|
#if TARGET_PC
|
||||||
if (!dusk::frame_interp::lookup_replacement(ptcl, mtx1) &&
|
if (!dusk::frame_interp::lookup_replacement(ptcl, mtx1))
|
||||||
!make_rot_direction_mtx(work, ptcl, mtx1))
|
#endif
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
{
|
{
|
||||||
f32 sinRot = JMASSin(ptcl->mRotateAngle);
|
f32 sinRot = JMASSin(ptcl->mRotateAngle);
|
||||||
f32 cosRot = JMASCos(ptcl->mRotateAngle);
|
f32 cosRot = JMASCos(ptcl->mRotateAngle);
|
||||||
@@ -1157,18 +927,13 @@ void JPADrawRotDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRA
|
|||||||
mtx2[2][3] = ptcl->mPosition.z;
|
mtx2[2][3] = ptcl->mPosition.z;
|
||||||
MTXConcat(mtx2, mtx1, mtx1);
|
MTXConcat(mtx2, mtx1, mtx1);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
MTXConcat(work->mPosCamMtx, mtx1, mtx2);
|
MTXConcat(work->mPosCamMtx, mtx1, mtx2);
|
||||||
#if TARGET_PC
|
|
||||||
submit_particle_quad(work, ctx, mtx2, p_dl[work->mDLType], sizeof(jpa_dl));
|
|
||||||
#else
|
|
||||||
GXLoadPosMtxImm(mtx2, GX_PNMTX0);
|
GXLoadPosMtxImm(mtx2, GX_PNMTX0);
|
||||||
p_prj[work->mPrjType](work, mtx2);
|
p_prj[work->mPrjType](work, mtx2);
|
||||||
GXCallDisplayList(p_dl[work->mDLType], sizeof(jpa_dl));
|
GXCallDisplayList(p_dl[work->mDLType], sizeof(jpa_dl));
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void JPADrawDBillboard(JPAEmitterWorkData* param_0, JPABaseParticle* param_1 JPA_DRAW_CTX_PARAM) {
|
void JPADrawDBillboard(JPAEmitterWorkData* param_0, JPABaseParticle* param_1) {
|
||||||
if (param_1->checkStatus(JPAPtclStts_Invisible)) {
|
if (param_1->checkStatus(JPAPtclStts_Invisible)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1205,7 +970,7 @@ void JPADrawDBillboard(JPAEmitterWorkData* param_0, JPABaseParticle* param_1 JPA
|
|||||||
GXCallDisplayList(jpa_dl, sizeof(jpa_dl));
|
GXCallDisplayList(jpa_dl, sizeof(jpa_dl));
|
||||||
}
|
}
|
||||||
|
|
||||||
void JPADrawRotation(JPAEmitterWorkData* param_0, JPABaseParticle* param_1 JPA_DRAW_CTX_PARAM) {
|
void JPADrawRotation(JPAEmitterWorkData* param_0, JPABaseParticle* param_1) {
|
||||||
if (param_1->checkStatus(JPAPtclStts_Invisible)) {
|
if (param_1->checkStatus(JPAPtclStts_Invisible)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1223,16 +988,12 @@ void JPADrawRotation(JPAEmitterWorkData* param_0, JPABaseParticle* param_1 JPA_D
|
|||||||
auStack_88[1][3] = param_1->mPosition.y;
|
auStack_88[1][3] = param_1->mPosition.y;
|
||||||
auStack_88[2][3] = param_1->mPosition.z;
|
auStack_88[2][3] = param_1->mPosition.z;
|
||||||
MTXConcat(param_0->mPosCamMtx, auStack_88, auStack_88);
|
MTXConcat(param_0->mPosCamMtx, auStack_88, auStack_88);
|
||||||
#if TARGET_PC
|
|
||||||
submit_particle_quad(param_0, ctx, auStack_88, p_dl[param_0->mDLType], sizeof(jpa_dl));
|
|
||||||
#else
|
|
||||||
GXLoadPosMtxImm(auStack_88, 0);
|
GXLoadPosMtxImm(auStack_88, 0);
|
||||||
p_prj[param_0->mPrjType](param_0, auStack_88);
|
p_prj[param_0->mPrjType](param_0, auStack_88);
|
||||||
GXCallDisplayList(p_dl[param_0->mDLType], sizeof(jpa_dl));
|
GXCallDisplayList(p_dl[param_0->mDLType], sizeof(jpa_dl));
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void JPADrawPoint(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
|
void JPADrawPoint(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
|
||||||
if (ptcl->checkStatus(JPAPtclStts_Invisible)) {
|
if (ptcl->checkStatus(JPAPtclStts_Invisible)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1249,7 +1010,7 @@ void JPADrawPoint(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_P
|
|||||||
GXSetVtxDesc(GX_VA_TEX0, GX_INDEX8);
|
GXSetVtxDesc(GX_VA_TEX0, GX_INDEX8);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JPADrawLine(JPAEmitterWorkData* param_0, JPABaseParticle* param_1 JPA_DRAW_CTX_PARAM) {
|
void JPADrawLine(JPAEmitterWorkData* param_0, JPABaseParticle* param_1) {
|
||||||
if (param_1->checkStatus(JPAPtclStts_Invisible)) {
|
if (param_1->checkStatus(JPAPtclStts_Invisible)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1325,7 +1086,7 @@ void JPADrawStripe(JPAEmitterWorkData* param_0) {
|
|||||||
GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
|
GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
|
||||||
GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
|
GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
|
||||||
GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT1, ptcl_num << 1);
|
GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT1, ptcl_num << 1);
|
||||||
for (JPANode<JPABaseParticle>* node = startNode; node != param_0->mpAlivePtcl->getEnd();
|
for (JPANode<JPABaseParticle>* node = startNode; node != param_0->mpAlivePtcl->getEnd();
|
||||||
node = node_func(node), coord += step) {
|
node = node_func(node), coord += step) {
|
||||||
param_0->mpCurNode = node;
|
param_0->mpCurNode = node;
|
||||||
JPABaseParticle* particle = node->getObject();
|
JPABaseParticle* particle = node->getObject();
|
||||||
@@ -1350,7 +1111,7 @@ void JPADrawStripe(JPAEmitterWorkData* param_0) {
|
|||||||
}
|
}
|
||||||
particle->mBaseAxis.cross(local_f8, local_104);
|
particle->mBaseAxis.cross(local_f8, local_104);
|
||||||
particle->mBaseAxis.normalize();
|
particle->mBaseAxis.normalize();
|
||||||
|
|
||||||
local_c8[0][0] = local_104.x;
|
local_c8[0][0] = local_104.x;
|
||||||
local_c8[0][1] = local_f8.x;
|
local_c8[0][1] = local_f8.x;
|
||||||
local_c8[0][2] = particle->mBaseAxis.x;
|
local_c8[0][2] = particle->mBaseAxis.x;
|
||||||
@@ -1416,7 +1177,7 @@ void JPADrawStripeX(JPAEmitterWorkData* param_0) {
|
|||||||
GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
|
GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
|
||||||
GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
|
GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
|
||||||
GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT1, ptcl_num << 1);
|
GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT1, ptcl_num << 1);
|
||||||
for (JPANode<JPABaseParticle>* node = startNode; node != param_0->mpAlivePtcl->getEnd();
|
for (JPANode<JPABaseParticle>* node = startNode; node != param_0->mpAlivePtcl->getEnd();
|
||||||
node = node_func(node), coord += step) {
|
node = node_func(node), coord += step) {
|
||||||
param_0->mpCurNode = node;
|
param_0->mpCurNode = node;
|
||||||
JPABaseParticle* particle = node->getObject();
|
JPABaseParticle* particle = node->getObject();
|
||||||
@@ -1441,7 +1202,7 @@ void JPADrawStripeX(JPAEmitterWorkData* param_0) {
|
|||||||
}
|
}
|
||||||
particle->mBaseAxis.cross(local_c0, local_cc);
|
particle->mBaseAxis.cross(local_c0, local_cc);
|
||||||
particle->mBaseAxis.normalize();
|
particle->mBaseAxis.normalize();
|
||||||
|
|
||||||
local_90[0][0] = local_cc.x;
|
local_90[0][0] = local_cc.x;
|
||||||
local_90[0][1] = local_c0.x;
|
local_90[0][1] = local_c0.x;
|
||||||
local_90[0][2] = particle->mBaseAxis.x;
|
local_90[0][2] = particle->mBaseAxis.x;
|
||||||
@@ -1466,7 +1227,7 @@ void JPADrawStripeX(JPAEmitterWorkData* param_0) {
|
|||||||
|
|
||||||
coord = start_coord;
|
coord = start_coord;
|
||||||
GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT1, ptcl_num << 1);
|
GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT1, ptcl_num << 1);
|
||||||
for (JPANode<JPABaseParticle>* node = startNode; node != param_0->mpAlivePtcl->getEnd();
|
for (JPANode<JPABaseParticle>* node = startNode; node != param_0->mpAlivePtcl->getEnd();
|
||||||
node = node_func(node), coord += step) {
|
node = node_func(node), coord += step) {
|
||||||
param_0->mpCurNode = node;
|
param_0->mpCurNode = node;
|
||||||
JPABaseParticle* particle = node->getObject();
|
JPABaseParticle* particle = node->getObject();
|
||||||
@@ -1491,7 +1252,7 @@ void JPADrawStripeX(JPAEmitterWorkData* param_0) {
|
|||||||
}
|
}
|
||||||
particle->mBaseAxis.cross(local_c0, local_cc);
|
particle->mBaseAxis.cross(local_c0, local_cc);
|
||||||
particle->mBaseAxis.normalize();
|
particle->mBaseAxis.normalize();
|
||||||
|
|
||||||
local_90[0][0] = local_cc.x;
|
local_90[0][0] = local_cc.x;
|
||||||
local_90[0][1] = local_c0.x;
|
local_90[0][1] = local_c0.x;
|
||||||
local_90[0][2] = particle->mBaseAxis.x;
|
local_90[0][2] = particle->mBaseAxis.x;
|
||||||
@@ -1528,7 +1289,7 @@ void JPADrawEmitterCallBackB(JPAEmitterWorkData* work) {
|
|||||||
emtr->mpEmtrCallBack->draw(emtr);
|
emtr->mpEmtrCallBack->draw(emtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JPADrawParticleCallBack(JPAEmitterWorkData* work, JPABaseParticle* ptcl JPA_DRAW_CTX_PARAM) {
|
void JPADrawParticleCallBack(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
|
||||||
JPABaseEmitter* emtr = work->mpEmtr;
|
JPABaseEmitter* emtr = work->mpEmtr;
|
||||||
if (emtr->mpPtclCallBack == NULL) {
|
if (emtr->mpPtclCallBack == NULL) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -18,21 +18,9 @@
|
|||||||
#include "global.h"
|
#include "global.h"
|
||||||
#include "tracy/Tracy.hpp"
|
#include "tracy/Tracy.hpp"
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
#define JPA_DRAW_CTX_ARG , &ctx
|
|
||||||
#else
|
|
||||||
#define JPA_DRAW_CTX_ARG
|
|
||||||
#endif
|
|
||||||
|
|
||||||
JPAResource::JPAResource() {
|
JPAResource::JPAResource() {
|
||||||
mpCalcEmitterFuncList = mpDrawEmitterFuncList = mpDrawEmitterChildFuncList = NULL;
|
mpCalcEmitterFuncList = mpDrawEmitterFuncList = mpDrawEmitterChildFuncList = NULL;
|
||||||
#if TARGET_PC
|
|
||||||
mpCalcParticleFuncList = mpCalcParticleChildFuncList = NULL;
|
|
||||||
mpDrawParticleFuncList = mpDrawParticleChildFuncList = NULL;
|
|
||||||
mBatchInfo = {};
|
|
||||||
#else
|
|
||||||
mpCalcParticleFuncList = mpDrawParticleFuncList = mpCalcParticleChildFuncList = mpDrawParticleChildFuncList = NULL;
|
mpCalcParticleFuncList = mpDrawParticleFuncList = mpCalcParticleChildFuncList = mpDrawParticleChildFuncList = NULL;
|
||||||
#endif
|
|
||||||
pBsp = NULL;
|
pBsp = NULL;
|
||||||
pEsp = NULL;
|
pEsp = NULL;
|
||||||
pCsp = NULL;
|
pCsp = NULL;
|
||||||
@@ -73,60 +61,6 @@ static u8 jpa_crd[32] ATTRIBUTE_ALIGN(32) = {
|
|||||||
0x00, 0x00, 0x01, 0x00, 0x01, 0x02, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02,
|
0x00, 0x00, 0x01, 0x00, 0x01, 0x02, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02,
|
||||||
};
|
};
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
void JPAResource::initBatchInfo() {
|
|
||||||
mBatchInfo = {};
|
|
||||||
|
|
||||||
bool hasDrawFunc = false;
|
|
||||||
for (int i = 0; i < mpDrawParticleFuncListNum; i++) {
|
|
||||||
DrawParticleFunc func = mpDrawParticleFuncList[i];
|
|
||||||
if (func == JPADrawBillboard || func == JPADrawRotBillboard ||
|
|
||||||
func == JPADrawYBillboard || func == JPADrawRotYBillboard ||
|
|
||||||
func == JPADrawDirection || func == JPADrawRotDirection || func == JPADrawRotation)
|
|
||||||
{
|
|
||||||
hasDrawFunc = true;
|
|
||||||
} else if (func == JPADrawParticleCallBack) {
|
|
||||||
// Batchable only for emitters without a particle callback; checked per draw
|
|
||||||
} else if (func == JPALoadCalcTexCrdMtxAnm) {
|
|
||||||
mBatchInfo.hasPtclTexMtx = true;
|
|
||||||
} else if (func == JPARegistAlpha || func == JPARegistPrmAlpha ||
|
|
||||||
func == JPARegistPrmAlphaEnv || func == JPARegistAlphaEnv ||
|
|
||||||
func == static_cast<DrawParticleFunc>(JPARegistEnv)) // overloaded
|
|
||||||
{
|
|
||||||
mBatchInfo.hasPtclColor = true;
|
|
||||||
} else {
|
|
||||||
// JPADrawPoint, JPADrawLine, JPADrawDBillboard, JPALoadTexAnm,
|
|
||||||
// JPASetPointSize, JPASetLineWidth
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!hasDrawFunc) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Template array offsets, same math as setPTev
|
|
||||||
int base_plane_type = (pBsp->getType() == 3 || pBsp->getType() == 7) ?
|
|
||||||
pBsp->getBasePlaneType() : 0;
|
|
||||||
int center_offset = pEsp != nullptr ? (pEsp->getScaleCenterX() + 3 * pEsp->getScaleCenterY()) * 0xC : 0x30;
|
|
||||||
const s8* pos = reinterpret_cast<const s8*>(jpa_pos) + center_offset + base_plane_type * 0x6C;
|
|
||||||
const s8* crd = reinterpret_cast<const s8*>(jpa_crd) + (pBsp->getTilingS() + 2 * pBsp->getTilingT()) * 8;
|
|
||||||
|
|
||||||
bool cross = pBsp->getType() == 4 || pBsp->getType() == 8;
|
|
||||||
mBatchInfo.vtxCount = cross ? 8 : 4;
|
|
||||||
for (int i = 0; i < mBatchInfo.vtxCount; i++) {
|
|
||||||
int posIdx = i < 4 ? i : 72 + (i - 4);
|
|
||||||
int crdIdx = i & 3;
|
|
||||||
mBatchInfo.vtxPos[i][0] = pos[posIdx * 3 + 0];
|
|
||||||
mBatchInfo.vtxPos[i][1] = pos[posIdx * 3 + 1];
|
|
||||||
mBatchInfo.vtxPos[i][2] = pos[posIdx * 3 + 2];
|
|
||||||
mBatchInfo.vtxUv[i][0] = crd[crdIdx * 2 + 0];
|
|
||||||
mBatchInfo.vtxUv[i][1] = crd[crdIdx * 2 + 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
mBatchInfo.supported = true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void JPAResource::init(JKRHeap* heap) {
|
void JPAResource::init(JKRHeap* heap) {
|
||||||
BOOL is_glbl_clr_anm = pBsp->isGlblClrAnm();
|
BOOL is_glbl_clr_anm = pBsp->isGlblClrAnm();
|
||||||
BOOL is_glbl_tex_anm = pBsp->isGlblTexAnm();
|
BOOL is_glbl_tex_anm = pBsp->isGlblTexAnm();
|
||||||
@@ -591,10 +525,7 @@ void JPAResource::init(JKRHeap* heap) {
|
|||||||
|
|
||||||
if (mpDrawParticleFuncListNum != 0) {
|
if (mpDrawParticleFuncListNum != 0) {
|
||||||
mpDrawParticleFuncList =
|
mpDrawParticleFuncList =
|
||||||
(DrawParticleFunc*)JKRAllocFromHeap(
|
(ParticleFunc*)JKRAllocFromHeap(heap, mpDrawParticleFuncListNum * sizeof(ParticleFunc), alignof(ParticleFunc));
|
||||||
heap,
|
|
||||||
mpDrawParticleFuncListNum * sizeof(DrawParticleFunc),
|
|
||||||
alignof(DrawParticleFunc));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func_no = 0;
|
func_no = 0;
|
||||||
@@ -704,10 +635,7 @@ void JPAResource::init(JKRHeap* heap) {
|
|||||||
|
|
||||||
if (mpDrawParticleChildFuncListNum != 0) {
|
if (mpDrawParticleChildFuncListNum != 0) {
|
||||||
mpDrawParticleChildFuncList =
|
mpDrawParticleChildFuncList =
|
||||||
(DrawParticleFunc*)JKRAllocFromHeap(
|
(ParticleFunc*)JKRAllocFromHeap(heap, mpDrawParticleChildFuncListNum * sizeof(ParticleFunc), sizeof(EmitterFunc));
|
||||||
heap,
|
|
||||||
mpDrawParticleChildFuncListNum * sizeof(DrawParticleFunc),
|
|
||||||
alignof(DrawParticleFunc));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func_no = 0;
|
func_no = 0;
|
||||||
@@ -771,10 +699,6 @@ void JPAResource::init(JKRHeap* heap) {
|
|||||||
mpDrawParticleChildFuncList[func_no] = &JPARegistPrmAlphaEnv;
|
mpDrawParticleChildFuncList[func_no] = &JPARegistPrmAlphaEnv;
|
||||||
func_no++;
|
func_no++;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
initBatchInfo();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool JPAResource::calc(JPAEmitterWorkData* work, JPABaseEmitter* emtr) {
|
bool JPAResource::calc(JPAEmitterWorkData* work, JPABaseEmitter* emtr) {
|
||||||
@@ -884,183 +808,6 @@ void JPAResource::draw(JPAEmitterWorkData* work, JPABaseEmitter* emtr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
static GXTevAlphaArg to_vtx_alpha_arg(GXTevAlphaArg arg) {
|
|
||||||
return arg == GX_CA_A0 ? GX_CA_RASA : arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void batch_set_tev_op(GXTevStageID stage) {
|
|
||||||
GXSetTevColorOp(stage, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
|
|
||||||
GXSetTevAlphaOp(stage, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void batch_setup_tev(JPAEmitterWorkData* work, bool useClr1) {
|
|
||||||
JPABaseShape* shape = work->mpRes->getBsp();
|
|
||||||
JPAExTexShape* ets = work->mpRes->getEts();
|
|
||||||
bool useIndirect = ets != nullptr && ets->isUseIndirect();
|
|
||||||
|
|
||||||
// JPAEmitterManager::draw configures both channels to pass vertex color through
|
|
||||||
GXSetNumChans(useClr1 ? 2 : 1);
|
|
||||||
|
|
||||||
const GXTevAlphaArg* alphaArg = shape->getTevAlphaArg();
|
|
||||||
GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);
|
|
||||||
GXSetTevAlphaIn(GX_TEVSTAGE0, to_vtx_alpha_arg(alphaArg[0]), to_vtx_alpha_arg(alphaArg[1]),
|
|
||||||
to_vtx_alpha_arg(alphaArg[2]), to_vtx_alpha_arg(alphaArg[3]));
|
|
||||||
batch_set_tev_op(GX_TEVSTAGE0);
|
|
||||||
if (!useIndirect) {
|
|
||||||
GXSetTevDirect(GX_TEVSTAGE0);
|
|
||||||
}
|
|
||||||
GXTevStageID nextStage = GX_TEVSTAGE1;
|
|
||||||
|
|
||||||
switch (shape->getTevColorArgSel()) {
|
|
||||||
case 0: // TEXC
|
|
||||||
GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_TEXC, GX_CC_ONE, GX_CC_ZERO);
|
|
||||||
break;
|
|
||||||
case 1: // C0 * TEXC
|
|
||||||
GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_RASC, GX_CC_TEXC, GX_CC_ZERO);
|
|
||||||
break;
|
|
||||||
case 2: // lerp(C0, 1, TEXC)
|
|
||||||
GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_RASC, GX_CC_ONE, GX_CC_TEXC, GX_CC_ZERO);
|
|
||||||
break;
|
|
||||||
case 3: // lerp(C1, C0, TEXC) = C0 * TEXC (stage 0) + C1 * (1 - TEXC) (stage 1)
|
|
||||||
GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_RASC, GX_CC_TEXC, GX_CC_ZERO);
|
|
||||||
GXSetTevOrder(nextStage, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR1A1);
|
|
||||||
GXSetTevColorIn(nextStage, GX_CC_RASC, GX_CC_ZERO, GX_CC_TEXC, GX_CC_CPREV);
|
|
||||||
GXSetTevAlphaIn(nextStage, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_APREV);
|
|
||||||
batch_set_tev_op(nextStage);
|
|
||||||
GXSetTevDirect(nextStage);
|
|
||||||
nextStage = static_cast<GXTevStageID>(nextStage + 1);
|
|
||||||
break;
|
|
||||||
case 4: // TEXC * C0 + C1: C0 * TEXC (stage 0), + C1 (stage 1)
|
|
||||||
GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_RASC, GX_CC_TEXC, GX_CC_ZERO);
|
|
||||||
GXSetTevOrder(nextStage, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR1A1);
|
|
||||||
GXSetTevColorIn(nextStage, GX_CC_CPREV, GX_CC_ZERO, GX_CC_ZERO, GX_CC_RASC);
|
|
||||||
GXSetTevAlphaIn(nextStage, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_APREV);
|
|
||||||
batch_set_tev_op(nextStage);
|
|
||||||
GXSetTevDirect(nextStage);
|
|
||||||
nextStage = static_cast<GXTevStageID>(nextStage + 1);
|
|
||||||
break;
|
|
||||||
case 5: // C0
|
|
||||||
GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_RASC);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ets != nullptr && ets->isUseSecTex()) {
|
|
||||||
// Mirrors setPTev's secondary texture stage, at the next free stage
|
|
||||||
GXTexCoordID texCoord = useIndirect ? GX_TEXCOORD2 : GX_TEXCOORD1;
|
|
||||||
GXSetTevOrder(nextStage, texCoord, GX_TEXMAP3, GX_COLOR_NULL);
|
|
||||||
GXSetTevColorIn(nextStage, GX_CC_ZERO, GX_CC_TEXC, GX_CC_CPREV, GX_CC_ZERO);
|
|
||||||
GXSetTevAlphaIn(nextStage, GX_CA_ZERO, GX_CA_TEXA, GX_CA_APREV, GX_CA_ZERO);
|
|
||||||
batch_set_tev_op(nextStage);
|
|
||||||
GXSetTevDirect(nextStage);
|
|
||||||
nextStage = static_cast<GXTevStageID>(nextStage + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
GXSetNumTevStages(nextStage);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void batch_setup_vtx_desc(bool useClr0, bool useClr1) {
|
|
||||||
static Mtx identityMtx = {
|
|
||||||
{1.0f, 0.0f, 0.0f, 0.0f},
|
|
||||||
{0.0f, 1.0f, 0.0f, 0.0f},
|
|
||||||
{0.0f, 0.0f, 1.0f, 0.0f},
|
|
||||||
};
|
|
||||||
|
|
||||||
GXLoadPosMtxImm(identityMtx, GX_PNMTX0);
|
|
||||||
GXSetCurrentMtx(GX_PNMTX0);
|
|
||||||
GXClearVtxDesc();
|
|
||||||
GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
|
|
||||||
if (useClr0) {
|
|
||||||
GXSetVtxDesc(GX_VA_CLR0, GX_DIRECT);
|
|
||||||
}
|
|
||||||
if (useClr1) {
|
|
||||||
GXSetVtxDesc(GX_VA_CLR1, GX_DIRECT);
|
|
||||||
}
|
|
||||||
GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
|
|
||||||
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
|
|
||||||
if (useClr0) {
|
|
||||||
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
|
|
||||||
}
|
|
||||||
if (useClr1) {
|
|
||||||
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_CLR1, GX_CLR_RGBA, GX_RGBA8, 0);
|
|
||||||
}
|
|
||||||
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void batch_restore_gx(JPAEmitterWorkData* work, bool changedTev, bool changedTexMtx) {
|
|
||||||
GXClearVtxDesc();
|
|
||||||
GXSetVtxDesc(GX_VA_POS, GX_INDEX8);
|
|
||||||
GXSetVtxDesc(GX_VA_TEX0, GX_INDEX8);
|
|
||||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_S8, 0);
|
|
||||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_S8, 0);
|
|
||||||
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
|
|
||||||
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
|
|
||||||
GXSetCurrentMtx(GX_PNMTX0);
|
|
||||||
|
|
||||||
if (changedTexMtx) {
|
|
||||||
GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_TEXMTX0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (changedTev) {
|
|
||||||
GXSetNumChans(0);
|
|
||||||
work->mpRes->getBsp()->setGX(work);
|
|
||||||
work->mpRes->setPTev();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool draw_particle_batch(JPAEmitterWorkData* work) {
|
|
||||||
ZoneScoped;
|
|
||||||
|
|
||||||
JPAResource* res = work->mpRes;
|
|
||||||
const JPAResource::BatchInfo& info = res->mBatchInfo;
|
|
||||||
if (!info.supported || work->mPrjType != 0 || work->mpEmtr->mpPtclCallBack != nullptr) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool useClr0 = false;
|
|
||||||
bool useClr1 = false;
|
|
||||||
if (info.hasPtclColor) {
|
|
||||||
u32 colorSel = res->getBsp()->getTevColorArgSel();
|
|
||||||
if (colorSel >= 6) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
useClr0 = true;
|
|
||||||
useClr1 = colorSel == 3 || colorSel == 4;
|
|
||||||
batch_setup_tev(work, useClr1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (info.hasPtclTexMtx) {
|
|
||||||
// UVs are CPU-transformed; drop the texgen
|
|
||||||
GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);
|
|
||||||
}
|
|
||||||
|
|
||||||
batch_setup_vtx_desc(useClr0, useClr1);
|
|
||||||
|
|
||||||
ParticleDrawCtx ctx{};
|
|
||||||
ctx.batch = true;
|
|
||||||
ctx.useTexMtx = info.hasPtclTexMtx;
|
|
||||||
ctx.useClr0 = useClr0;
|
|
||||||
ctx.useClr1 = useClr1;
|
|
||||||
|
|
||||||
bool fwdAhead = res->getBsp()->isDrawFwdAhead();
|
|
||||||
JPANode<JPABaseParticle>* node = fwdAhead ? work->mpEmtr->mAlivePtclBase.getLast() :
|
|
||||||
work->mpEmtr->mAlivePtclBase.getFirst();
|
|
||||||
|
|
||||||
GXBegin(GX_QUADS, GX_VTXFMT1, GX_AUTO);
|
|
||||||
while (node != work->mpEmtr->mAlivePtclBase.getEnd()) {
|
|
||||||
work->mpCurNode = node;
|
|
||||||
for (int i = res->mpDrawParticleFuncListNum - 1; i >= 0; i--) {
|
|
||||||
(*res->mpDrawParticleFuncList[i])(work, node->getObject(), &ctx);
|
|
||||||
}
|
|
||||||
node = fwdAhead ? node->getPrev() : node->getNext();
|
|
||||||
}
|
|
||||||
GXEnd();
|
|
||||||
|
|
||||||
batch_restore_gx(work, useClr0, info.hasPtclTexMtx);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void JPAResource::drawP(JPAEmitterWorkData* work) {
|
void JPAResource::drawP(JPAEmitterWorkData* work) {
|
||||||
ZoneScoped;
|
ZoneScoped;
|
||||||
work->mpEmtr->clearStatus(0x80);
|
work->mpEmtr->clearStatus(0x80);
|
||||||
@@ -1095,25 +842,13 @@ void JPAResource::drawP(JPAEmitterWorkData* work) {
|
|||||||
(*mpDrawEmitterFuncList[i])(work);
|
(*mpDrawEmitterFuncList[i])(work);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
if (draw_particle_batch(work)) {
|
|
||||||
GXSetMisc(GX_MT_XF_FLUSH, 0);
|
|
||||||
if (work->mpEmtr->mpEmtrCallBack != nullptr) {
|
|
||||||
work->mpEmtr->mpEmtrCallBack->drawAfter(work->mpEmtr);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ParticleDrawCtx ctx{}; // immediate mode
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (pBsp->isDrawFwdAhead()) {
|
if (pBsp->isDrawFwdAhead()) {
|
||||||
JPANode<JPABaseParticle>* node = work->mpEmtr->mAlivePtclBase.getLast();
|
JPANode<JPABaseParticle>* node = work->mpEmtr->mAlivePtclBase.getLast();
|
||||||
for (; node != work->mpEmtr->mAlivePtclBase.getEnd(); node = node->getPrev()) {
|
for (; node != work->mpEmtr->mAlivePtclBase.getEnd(); node = node->getPrev()) {
|
||||||
work->mpCurNode = node;
|
work->mpCurNode = node;
|
||||||
if (mpDrawParticleFuncList != NULL) {
|
if (mpDrawParticleFuncList != NULL) {
|
||||||
for (int i = mpDrawParticleFuncListNum - 1; i >= 0; i--) {
|
for (int i = mpDrawParticleFuncListNum - 1; i >= 0; i--) {
|
||||||
(*mpDrawParticleFuncList[i])(work, node->getObject() JPA_DRAW_CTX_ARG);
|
(*mpDrawParticleFuncList[i])(work, node->getObject());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1123,7 +858,7 @@ void JPAResource::drawP(JPAEmitterWorkData* work) {
|
|||||||
work->mpCurNode = node;
|
work->mpCurNode = node;
|
||||||
if (mpDrawParticleFuncList != NULL) {
|
if (mpDrawParticleFuncList != NULL) {
|
||||||
for (int i = mpDrawParticleFuncListNum - 1; i >= 0; i--) {
|
for (int i = mpDrawParticleFuncListNum - 1; i >= 0; i--) {
|
||||||
(*mpDrawParticleFuncList[i])(work, node->getObject() JPA_DRAW_CTX_ARG);
|
(*mpDrawParticleFuncList[i])(work, node->getObject());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1170,17 +905,13 @@ void JPAResource::drawC(JPAEmitterWorkData* work) {
|
|||||||
(*mpDrawEmitterChildFuncList[i])(work);
|
(*mpDrawEmitterChildFuncList[i])(work);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
ParticleDrawCtx ctx{}; // immediate mode
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (pBsp->isDrawFwdAhead()) {
|
if (pBsp->isDrawFwdAhead()) {
|
||||||
JPANode<JPABaseParticle>* node = work->mpEmtr->mAlivePtclChld.getLast();
|
JPANode<JPABaseParticle>* node = work->mpEmtr->mAlivePtclChld.getLast();
|
||||||
for (; node != work->mpEmtr->mAlivePtclChld.getEnd(); node = node->getPrev()) {
|
for (; node != work->mpEmtr->mAlivePtclChld.getEnd(); node = node->getPrev()) {
|
||||||
work->mpCurNode = node;
|
work->mpCurNode = node;
|
||||||
if (mpDrawParticleChildFuncList != NULL) {
|
if (mpDrawParticleChildFuncList != NULL) {
|
||||||
for (int i = mpDrawParticleChildFuncListNum - 1; i >= 0; i--) {
|
for (int i = mpDrawParticleChildFuncListNum - 1; i >= 0; i--) {
|
||||||
(*mpDrawParticleChildFuncList[i])(work, node->getObject() JPA_DRAW_CTX_ARG);
|
(*mpDrawParticleChildFuncList[i])(work, node->getObject());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1190,7 +921,7 @@ void JPAResource::drawC(JPAEmitterWorkData* work) {
|
|||||||
work->mpCurNode = node;
|
work->mpCurNode = node;
|
||||||
if (mpDrawParticleChildFuncList != NULL) {
|
if (mpDrawParticleChildFuncList != NULL) {
|
||||||
for (int i = mpDrawParticleChildFuncListNum - 1; i >= 0; i--) {
|
for (int i = mpDrawParticleChildFuncListNum - 1; i >= 0; i--) {
|
||||||
(*mpDrawParticleChildFuncList[i])(work, node->getObject() JPA_DRAW_CTX_ARG);
|
(*mpDrawParticleChildFuncList[i])(work, node->getObject());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import android.app.ActionBar;
|
|||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.ActivityNotFoundException;
|
import android.content.ActivityNotFoundException;
|
||||||
import android.content.ClipData;
|
import android.content.ClipData;
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
@@ -15,16 +14,12 @@ import android.provider.DocumentsContract;
|
|||||||
import android.provider.OpenableColumns;
|
import android.provider.OpenableColumns;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.Display;
|
|
||||||
import android.view.Surface;
|
|
||||||
import android.view.SurfaceHolder;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.Window;
|
import android.view.Window;
|
||||||
import android.view.WindowInsets;
|
import android.view.WindowInsets;
|
||||||
import android.view.WindowInsetsController;
|
import android.view.WindowInsetsController;
|
||||||
|
|
||||||
import org.libsdl.app.SDLActivity;
|
import org.libsdl.app.SDLActivity;
|
||||||
import org.libsdl.app.SDLSurface;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -32,7 +27,6 @@ import java.util.List;
|
|||||||
|
|
||||||
public class DuskActivity extends SDLActivity {
|
public class DuskActivity extends SDLActivity {
|
||||||
private static final String TAG = "DuskActivity";
|
private static final String TAG = "DuskActivity";
|
||||||
private static final float DEFAULT_SURFACE_FRAME_RATE = 60.0f;
|
|
||||||
private static final int FOLDER_DIALOG_REQUEST_CODE = 0x4455;
|
private static final int FOLDER_DIALOG_REQUEST_CODE = 0x4455;
|
||||||
private static final int MANAGE_STORAGE_REQUEST_CODE = 0x4456;
|
private static final int MANAGE_STORAGE_REQUEST_CODE = 0x4456;
|
||||||
private static final String EXTERNAL_STORAGE_AUTHORITY =
|
private static final String EXTERNAL_STORAGE_AUTHORITY =
|
||||||
@@ -94,11 +88,6 @@ public class DuskActivity extends SDLActivity {
|
|||||||
hideSystemBars();
|
hideSystemBars();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected SDLSurface createSDLSurface(Context context) {
|
|
||||||
return new DuskSurface(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onResume() {
|
protected void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
@@ -150,77 +139,6 @@ public class DuskActivity extends SDLActivity {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPreferredSurfaceFrameRate(float frameRate) {
|
|
||||||
runOnUiThread(() -> {
|
|
||||||
if (mSurface instanceof DuskSurface) {
|
|
||||||
((DuskSurface)mSurface).setPreferredFrameRate(frameRate);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class DuskSurface extends SDLSurface {
|
|
||||||
private float preferredFrameRate = DEFAULT_SURFACE_FRAME_RATE;
|
|
||||||
|
|
||||||
DuskSurface(Context context) {
|
|
||||||
super(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
|
|
||||||
super.surfaceChanged(holder, format, width, height);
|
|
||||||
setTargetFrameRate(holder);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setPreferredFrameRate(float frameRate) {
|
|
||||||
preferredFrameRate = frameRate;
|
|
||||||
setTargetFrameRate(getHolder());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setTargetFrameRate(SurfaceHolder holder) {
|
|
||||||
if (!mIsSurfaceReady || Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Surface surface = holder != null ? holder.getSurface() : getHolder().getSurface();
|
|
||||||
if (surface == null || !surface.isValid()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
float targetFrameRate = getMaxSupportedFrameRate();
|
|
||||||
if (preferredFrameRate > 0.0f) {
|
|
||||||
targetFrameRate = preferredFrameRate;
|
|
||||||
}
|
|
||||||
if (targetFrameRate <= 0.0f) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
surface.setFrameRate(
|
|
||||||
targetFrameRate, Surface.FRAME_RATE_COMPATIBILITY_DEFAULT);
|
|
||||||
Log.v(TAG, "Requested surface frame rate " + targetFrameRate + " fps");
|
|
||||||
} catch (RuntimeException e) {
|
|
||||||
Log.w(TAG, "Failed to request surface frame rate", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private float getMaxSupportedFrameRate() {
|
|
||||||
if (mDisplay == null) {
|
|
||||||
return 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
float maxFrameRate = mDisplay.getRefreshRate();
|
|
||||||
Display.Mode[] modes = mDisplay.getSupportedModes();
|
|
||||||
if (modes == null) {
|
|
||||||
return maxFrameRate;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Display.Mode mode : modes) {
|
|
||||||
maxFrameRate = Math.max(maxFrameRate, mode.getRefreshRate());
|
|
||||||
}
|
|
||||||
return maxFrameRate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String[] getArguments() {
|
protected String[] getArguments() {
|
||||||
Intent intent = getIntent();
|
Intent intent = getIntent();
|
||||||
|
|||||||
+35
-209
@@ -19,13 +19,9 @@ import android.os.*;
|
|||||||
|
|
||||||
import java.lang.Runnable;
|
import java.lang.Runnable;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
import java.util.regex.Matcher;
|
|
||||||
|
|
||||||
class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDevice {
|
class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDevice {
|
||||||
|
|
||||||
private static final String TAG = "hidapi";
|
private static final String TAG = "hidapi";
|
||||||
@@ -37,19 +33,10 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
|
|||||||
private boolean mIsConnected = false;
|
private boolean mIsConnected = false;
|
||||||
private boolean mIsChromebook = false;
|
private boolean mIsChromebook = false;
|
||||||
private boolean mIsReconnecting = false;
|
private boolean mIsReconnecting = false;
|
||||||
private boolean mHasEnabledNotifications = false;
|
|
||||||
private boolean mHasSeenInputUpdate = false;
|
|
||||||
private boolean mFrozen = false;
|
private boolean mFrozen = false;
|
||||||
private LinkedList<GattOperation> mOperations;
|
private LinkedList<GattOperation> mOperations;
|
||||||
GattOperation mCurrentOperation = null;
|
GattOperation mCurrentOperation = null;
|
||||||
private Handler mHandler;
|
private Handler mHandler;
|
||||||
private int mProductId = -1;
|
|
||||||
private int mReportId = 0;
|
|
||||||
private UUID mInputCharacteristic;
|
|
||||||
|
|
||||||
private static final int D0G_BLE2_PID = 0x1106;
|
|
||||||
private static final int TRITON_BLE_PID = 0x1303;
|
|
||||||
|
|
||||||
|
|
||||||
private static final int TRANSPORT_AUTO = 0;
|
private static final int TRANSPORT_AUTO = 0;
|
||||||
private static final int TRANSPORT_BREDR = 1;
|
private static final int TRANSPORT_BREDR = 1;
|
||||||
@@ -58,14 +45,10 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
|
|||||||
private static final int CHROMEBOOK_CONNECTION_CHECK_INTERVAL = 10000;
|
private static final int CHROMEBOOK_CONNECTION_CHECK_INTERVAL = 10000;
|
||||||
|
|
||||||
static final UUID steamControllerService = UUID.fromString("100F6C32-1735-4313-B402-38567131E5F3");
|
static final UUID steamControllerService = UUID.fromString("100F6C32-1735-4313-B402-38567131E5F3");
|
||||||
static final UUID inputCharacteristicD0G = UUID.fromString("100F6C33-1735-4313-B402-38567131E5F3");
|
static final UUID inputCharacteristic = UUID.fromString("100F6C33-1735-4313-B402-38567131E5F3");
|
||||||
static final UUID inputCharacteristicTriton_0x45 = UUID.fromString("100F6C7A-1735-4313-B402-38567131E5F3");
|
|
||||||
static final UUID inputCharacteristicTriton_0x47 = UUID.fromString("100F6C7C-1735-4313-B402-38567131E5F3");
|
|
||||||
static final UUID reportCharacteristic = UUID.fromString("100F6C34-1735-4313-B402-38567131E5F3");
|
static final UUID reportCharacteristic = UUID.fromString("100F6C34-1735-4313-B402-38567131E5F3");
|
||||||
static private final byte[] enterValveMode = new byte[] { (byte)0xC0, (byte)0x87, 0x03, 0x08, 0x07, 0x00 };
|
static private final byte[] enterValveMode = new byte[] { (byte)0xC0, (byte)0x87, 0x03, 0x08, 0x07, 0x00 };
|
||||||
|
|
||||||
private HashMap<Integer, BluetoothGattCharacteristic> mOutputReportChars = new HashMap<Integer, BluetoothGattCharacteristic>();
|
|
||||||
|
|
||||||
static class GattOperation {
|
static class GattOperation {
|
||||||
private enum Operation {
|
private enum Operation {
|
||||||
CHR_READ,
|
CHR_READ,
|
||||||
@@ -78,7 +61,6 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
|
|||||||
byte[] mValue;
|
byte[] mValue;
|
||||||
BluetoothGatt mGatt;
|
BluetoothGatt mGatt;
|
||||||
boolean mResult = true;
|
boolean mResult = true;
|
||||||
int mDelayMs = 0;
|
|
||||||
|
|
||||||
private GattOperation(BluetoothGatt gatt, GattOperation.Operation operation, UUID uuid) {
|
private GattOperation(BluetoothGatt gatt, GattOperation.Operation operation, UUID uuid) {
|
||||||
mGatt = gatt;
|
mGatt = gatt;
|
||||||
@@ -86,13 +68,6 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
|
|||||||
mUuid = uuid;
|
mUuid = uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
private GattOperation(BluetoothGatt gatt, GattOperation.Operation operation, UUID uuid, int delayMs) {
|
|
||||||
mGatt = gatt;
|
|
||||||
mOp = operation;
|
|
||||||
mUuid = uuid;
|
|
||||||
mDelayMs = delayMs;
|
|
||||||
}
|
|
||||||
|
|
||||||
private GattOperation(BluetoothGatt gatt, GattOperation.Operation operation, UUID uuid, byte[] value) {
|
private GattOperation(BluetoothGatt gatt, GattOperation.Operation operation, UUID uuid, byte[] value) {
|
||||||
mGatt = gatt;
|
mGatt = gatt;
|
||||||
mOp = operation;
|
mOp = operation;
|
||||||
@@ -100,14 +75,6 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
|
|||||||
mValue = value;
|
mValue = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private GattOperation(BluetoothGatt gatt, GattOperation.Operation operation, UUID uuid, byte[] value, int delayMs) {
|
|
||||||
mGatt = gatt;
|
|
||||||
mOp = operation;
|
|
||||||
mUuid = uuid;
|
|
||||||
mValue = value;
|
|
||||||
mDelayMs = delayMs;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void run() {
|
public void run() {
|
||||||
// This is executed in main thread
|
// This is executed in main thread
|
||||||
BluetoothGattCharacteristic chr;
|
BluetoothGattCharacteristic chr;
|
||||||
@@ -169,8 +136,6 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
|
|||||||
return mResult;
|
return mResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getDelayMs() { return mDelayMs; }
|
|
||||||
|
|
||||||
private BluetoothGattCharacteristic getCharacteristic(UUID uuid) {
|
private BluetoothGattCharacteristic getCharacteristic(UUID uuid) {
|
||||||
BluetoothGattService valveService = mGatt.getService(steamControllerService);
|
BluetoothGattService valveService = mGatt.getService(steamControllerService);
|
||||||
if (valveService == null)
|
if (valveService == null)
|
||||||
@@ -189,10 +154,6 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
|
|||||||
static public GattOperation enableNotification(BluetoothGatt gatt, UUID uuid) {
|
static public GattOperation enableNotification(BluetoothGatt gatt, UUID uuid) {
|
||||||
return new GattOperation(gatt, Operation.ENABLE_NOTIFICATION, uuid);
|
return new GattOperation(gatt, Operation.ENABLE_NOTIFICATION, uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
static public GattOperation enableNotification(BluetoothGatt gatt, UUID uuid, int delayMs) {
|
|
||||||
return new GattOperation(gatt, Operation.ENABLE_NOTIFICATION, uuid, delayMs);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HIDDeviceBLESteamController(HIDDeviceManager manager, BluetoothDevice device) {
|
HIDDeviceBLESteamController(HIDDeviceManager manager, BluetoothDevice device) {
|
||||||
@@ -205,8 +166,6 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
|
|||||||
mHandler = new Handler(Looper.getMainLooper());
|
mHandler = new Handler(Looper.getMainLooper());
|
||||||
|
|
||||||
mGatt = connectGatt();
|
mGatt = connectGatt();
|
||||||
mHasEnabledNotifications = false;
|
|
||||||
mHasSeenInputUpdate = false;
|
|
||||||
// final HIDDeviceBLESteamController finalThis = this;
|
// final HIDDeviceBLESteamController finalThis = this;
|
||||||
// mHandler.postDelayed(new Runnable() {
|
// mHandler.postDelayed(new Runnable() {
|
||||||
// @Override
|
// @Override
|
||||||
@@ -355,45 +314,8 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
|
|||||||
Log.v(TAG, "Found Valve steam controller service " + service.getUuid());
|
Log.v(TAG, "Found Valve steam controller service " + service.getUuid());
|
||||||
|
|
||||||
for (BluetoothGattCharacteristic chr : service.getCharacteristics()) {
|
for (BluetoothGattCharacteristic chr : service.getCharacteristics()) {
|
||||||
if (chr.getUuid().equals(inputCharacteristicTriton_0x45)) {
|
if (chr.getUuid().equals(inputCharacteristic)) {
|
||||||
Log.v(TAG, "Found Triton input characteristic 0x45");
|
Log.v(TAG, "Found input characteristic");
|
||||||
mProductId = TRITON_BLE_PID;
|
|
||||||
mReportId = 0x45;
|
|
||||||
mInputCharacteristic = chr.getUuid();
|
|
||||||
} else if (chr.getUuid().equals(inputCharacteristicTriton_0x47)) {
|
|
||||||
Log.v(TAG, "Found Triton input characteristic 0x47");
|
|
||||||
mProductId = TRITON_BLE_PID;
|
|
||||||
mReportId = 0x47;
|
|
||||||
mInputCharacteristic = chr.getUuid();
|
|
||||||
} else if (chr.getUuid().equals(inputCharacteristicD0G)) {
|
|
||||||
Log.v(TAG, "Found D0G input characteristic");
|
|
||||||
mProductId = D0G_BLE2_PID;
|
|
||||||
mReportId = 0x03;
|
|
||||||
mInputCharacteristic = chr.getUuid();
|
|
||||||
} else {
|
|
||||||
Pattern reportPattern = Pattern.compile("100F6C([0-9A-Z]{2})", Pattern.CASE_INSENSITIVE);
|
|
||||||
Matcher matcher = reportPattern.matcher(chr.getUuid().toString());
|
|
||||||
|
|
||||||
if (matcher.find()) {
|
|
||||||
try {
|
|
||||||
int reportId = Integer.parseInt(matcher.group(1), 16);
|
|
||||||
|
|
||||||
reportId -= 0x35;
|
|
||||||
if (reportId >= 0x80) {
|
|
||||||
// This is a Triton output report characteristic that we need to care about.
|
|
||||||
Log.v(TAG, "Found Triton output report 0x" + Integer.toString(reportId, 16));
|
|
||||||
mOutputReportChars.put(reportId, chr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (NumberFormatException nfe) {
|
|
||||||
Log.w(TAG, "Could not parse report characteristic " + chr.getUuid().toString() + ": " + nfe.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (BluetoothGattCharacteristic chr : service.getCharacteristics()) {
|
|
||||||
if (chr.getUuid().equals(mInputCharacteristic)) {
|
|
||||||
// Start notifications
|
// Start notifications
|
||||||
BluetoothGattDescriptor cccd = chr.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"));
|
BluetoothGattDescriptor cccd = chr.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"));
|
||||||
if (cccd != null) {
|
if (cccd != null) {
|
||||||
@@ -450,30 +372,21 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
|
|||||||
mCurrentOperation = mOperations.removeFirst();
|
mCurrentOperation = mOperations.removeFirst();
|
||||||
}
|
}
|
||||||
|
|
||||||
Runnable gattOperationRunnable = new Runnable() {
|
// Run in main thread
|
||||||
@Override
|
mHandler.post(new Runnable() {
|
||||||
public void run() {
|
@Override
|
||||||
synchronized (mOperations) {
|
public void run() {
|
||||||
if (mCurrentOperation == null) {
|
synchronized (mOperations) {
|
||||||
Log.e(TAG, "Current operation null in executor?");
|
if (mCurrentOperation == null) {
|
||||||
return;
|
Log.e(TAG, "Current operation null in executor?");
|
||||||
}
|
return;
|
||||||
|
|
||||||
mCurrentOperation.run();
|
|
||||||
// now wait for the GATT callback and when it comes, finish this operation
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mCurrentOperation.run();
|
||||||
|
// now wait for the GATT callback and when it comes, finish this operation
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
});
|
||||||
if (mCurrentOperation.getDelayMs() == 0) {
|
|
||||||
// Run in main thread
|
|
||||||
mHandler.post(gattOperationRunnable);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// If we have a delay on this operation, wait before we post it.
|
|
||||||
mHandler.postDelayed(gattOperationRunnable, mCurrentOperation.getDelayMs());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void queueGattOperation(GattOperation op) {
|
private void queueGattOperation(GattOperation op) {
|
||||||
@@ -484,39 +397,8 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void enableNotification(UUID chrUuid) {
|
private void enableNotification(UUID chrUuid) {
|
||||||
// Add a 500ms delay to notification write for Amazon Fire TV devices, as otherwise if we do this too quickly after connecting
|
GattOperation op = HIDDeviceBLESteamController.GattOperation.enableNotification(mGatt, chrUuid);
|
||||||
// it will return success and then silently drop the operation on the floor.
|
|
||||||
GattOperation op = HIDDeviceBLESteamController.GattOperation.enableNotification(mGatt, chrUuid, 500);
|
|
||||||
queueGattOperation(op);
|
queueGattOperation(op);
|
||||||
|
|
||||||
// Amazon Fire devices can also silently timeout on writeDescriptor, so
|
|
||||||
// set up a little delayed check that will attempt to write a second time.
|
|
||||||
//
|
|
||||||
// While this only seems to be needed on Amazon Fire TV devices at present, it
|
|
||||||
// doesn't hurt to have a retry on other devices as well.
|
|
||||||
//
|
|
||||||
final HIDDeviceBLESteamController finalThis = this;
|
|
||||||
final UUID finalUuid = chrUuid;
|
|
||||||
mHandler.postDelayed(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
if (!finalThis.mHasEnabledNotifications) {
|
|
||||||
|
|
||||||
if (finalThis.mHasSeenInputUpdate) {
|
|
||||||
// Amazon Five devices may have enabled notifications on the input characteristic and not given us a callback. If we've seen
|
|
||||||
// input reports, though, somewhat by definition notifications are enabled.
|
|
||||||
Log.w(TAG, "WriteDescriptor has never returned, but we've seen input reports. Moving on with controller initialization.");
|
|
||||||
finalThis.mHasEnabledNotifications = true;
|
|
||||||
finalThis.enableValveMode();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Give one more try.
|
|
||||||
GattOperation retry = HIDDeviceBLESteamController.GattOperation.enableNotification(finalThis.mGatt, finalUuid, 500);
|
|
||||||
finalThis.queueGattOperation(retry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, 1000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeCharacteristic(UUID uuid, byte[] value) {
|
void writeCharacteristic(UUID uuid, byte[] value) {
|
||||||
@@ -566,16 +448,8 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
|
|||||||
mIsConnected = false;
|
mIsConnected = false;
|
||||||
gatt.disconnect();
|
gatt.disconnect();
|
||||||
mGatt = connectGatt(false);
|
mGatt = connectGatt(false);
|
||||||
} else {
|
}
|
||||||
if (getProductId() == TRITON_BLE_PID) {
|
else {
|
||||||
// Android will not properly play well with Data Length Extensions without manually requesting a large MTU,
|
|
||||||
// and Triton controllers require DLE support.
|
|
||||||
//
|
|
||||||
// 517 is basically a "magic number" as far as Android's bluetooth code is concerned, so do not change
|
|
||||||
// this value. It is functionally "please enable data length extensions" on some Android builds.
|
|
||||||
mGatt.requestMtu(517);
|
|
||||||
}
|
|
||||||
|
|
||||||
probeService(this);
|
probeService(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -600,7 +474,7 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
|
|||||||
// Only register controller with the native side once it has been fully configured
|
// Only register controller with the native side once it has been fully configured
|
||||||
if (!isRegistered()) {
|
if (!isRegistered()) {
|
||||||
Log.v(TAG, "Registering Steam Controller with ID: " + getId());
|
Log.v(TAG, "Registering Steam Controller with ID: " + getId());
|
||||||
mManager.HIDDeviceConnected(getId(), getIdentifier(), getVendorId(), getProductId(), getSerialNumber(), getVersion(), getManufacturerName(), getProductName(), 0, 0, 0, 0, true, mReportId);
|
mManager.HIDDeviceConnected(getId(), getIdentifier(), getVendorId(), getProductId(), getSerialNumber(), getVersion(), getManufacturerName(), getProductName(), 0, 0, 0, 0, true);
|
||||||
setRegistered();
|
setRegistered();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -613,8 +487,7 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
|
|||||||
// Enable this for verbose logging of controller input reports
|
// Enable this for verbose logging of controller input reports
|
||||||
//Log.v(TAG, "onCharacteristicChanged uuid=" + characteristic.getUuid() + " data=" + HexDump.dumpHexString(characteristic.getValue()));
|
//Log.v(TAG, "onCharacteristicChanged uuid=" + characteristic.getUuid() + " data=" + HexDump.dumpHexString(characteristic.getValue()));
|
||||||
|
|
||||||
if (characteristic.getUuid().equals(mInputCharacteristic) && !mFrozen) {
|
if (characteristic.getUuid().equals(inputCharacteristic) && !mFrozen) {
|
||||||
mHasSeenInputUpdate = true;
|
|
||||||
mManager.HIDDeviceInputReport(getId(), characteristic.getValue());
|
mManager.HIDDeviceInputReport(getId(), characteristic.getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -624,36 +497,19 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
|
|||||||
//Log.v(TAG, "onDescriptorRead status=" + status);
|
//Log.v(TAG, "onDescriptorRead status=" + status);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void enableValveMode()
|
|
||||||
{
|
|
||||||
BluetoothGattService valveService = mGatt.getService(steamControllerService);
|
|
||||||
if (valveService == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
BluetoothGattCharacteristic reportChr = valveService.getCharacteristic(reportCharacteristic);
|
|
||||||
if (reportChr != null) {
|
|
||||||
if (getProductId() == TRITON_BLE_PID) {
|
|
||||||
// For Triton we just mark things registered.
|
|
||||||
Log.v(TAG, "Registering Triton Steam Controller with ID: " + getId());
|
|
||||||
mManager.HIDDeviceConnected(getId(), getIdentifier(), getVendorId(), getProductId(), getSerialNumber(), getVersion(), getManufacturerName(), getProductName(), 0, 0, 0, 0, true, mReportId);
|
|
||||||
setRegistered();
|
|
||||||
} else {
|
|
||||||
// For the original controller, we need to manually enter Valve mode.
|
|
||||||
Log.v(TAG, "Writing report characteristic to enter valve mode");
|
|
||||||
reportChr.setValue(enterValveMode);
|
|
||||||
mGatt.writeCharacteristic(reportChr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
|
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
|
||||||
BluetoothGattCharacteristic chr = descriptor.getCharacteristic();
|
BluetoothGattCharacteristic chr = descriptor.getCharacteristic();
|
||||||
//Log.v(TAG, "onDescriptorWrite status=" + status + " uuid=" + chr.getUuid() + " descriptor=" + descriptor.getUuid());
|
//Log.v(TAG, "onDescriptorWrite status=" + status + " uuid=" + chr.getUuid() + " descriptor=" + descriptor.getUuid());
|
||||||
|
|
||||||
if (chr.getUuid().equals(mInputCharacteristic)) {
|
if (chr.getUuid().equals(inputCharacteristic)) {
|
||||||
mHasEnabledNotifications = true;
|
boolean hasWrittenInputDescriptor = true;
|
||||||
enableValveMode();
|
BluetoothGattCharacteristic reportChr = chr.getService().getCharacteristic(reportCharacteristic);
|
||||||
|
if (reportChr != null) {
|
||||||
|
Log.v(TAG, "Writing report characteristic to enter valve mode");
|
||||||
|
reportChr.setValue(enterValveMode);
|
||||||
|
gatt.writeCharacteristic(reportChr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
finishCurrentGattOperation();
|
finishCurrentGattOperation();
|
||||||
@@ -692,20 +548,9 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getProductId() {
|
public int getProductId() {
|
||||||
if (mProductId > 0) {
|
// We don't have an easy way to query from the Bluetooth device, but we know what it is
|
||||||
// We've already set a product ID.
|
final int D0G_BLE2_PID = 0x1106;
|
||||||
return mProductId;
|
return D0G_BLE2_PID;
|
||||||
}
|
|
||||||
|
|
||||||
if (mDevice.getName().startsWith("Steam Ctrl")) {
|
|
||||||
// We're a newer Triton device
|
|
||||||
mProductId = TRITON_BLE_PID;
|
|
||||||
} else {
|
|
||||||
// We're an OG Steam Controller
|
|
||||||
mProductId = D0G_BLE2_PID;
|
|
||||||
}
|
|
||||||
|
|
||||||
return mProductId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -756,29 +601,10 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
|
|||||||
writeCharacteristic(reportCharacteristic, actual_report);
|
writeCharacteristic(reportCharacteristic, actual_report);
|
||||||
return report.length;
|
return report.length;
|
||||||
} else {
|
} else {
|
||||||
// If we're an original-recipe Steam Controller we just write to the characteristic directly.
|
//Log.v(TAG, "writeOutputReport " + HexDump.dumpHexString(report));
|
||||||
if (getProductId() == D0G_BLE2_PID) {
|
writeCharacteristic(reportCharacteristic, report);
|
||||||
//Log.v(TAG, "writeOutputReport " + HexDump.dumpHexString(report));
|
return report.length;
|
||||||
writeCharacteristic(reportCharacteristic, report);
|
|
||||||
return report.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we're a Triton, we need to find the correct report characteristic.
|
|
||||||
if (report.length > 0) {
|
|
||||||
int reportId = report[0] & 0xFF;
|
|
||||||
BluetoothGattCharacteristic targetedReportCharacteristic = mOutputReportChars.get(reportId);
|
|
||||||
if (targetedReportCharacteristic != null) {
|
|
||||||
byte[] actual_report = Arrays.copyOfRange(report, 1, report.length - 1);
|
|
||||||
//Log.v(TAG, "writeOutputReport 0x" + Integer.toString(reportId, 16) + " " + HexDump.dumpHexString(report));
|
|
||||||
writeCharacteristic(targetedReportCharacteristic.getUuid(), actual_report);
|
|
||||||
return report.length;
|
|
||||||
} else {
|
|
||||||
Log.w(TAG, "Got report write request for unknown report type 0x" + Integer.toString(reportId, 16));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -256,7 +256,6 @@ public class HIDDeviceManager {
|
|||||||
0x24c6, // PowerA
|
0x24c6, // PowerA
|
||||||
0x2c22, // Qanba
|
0x2c22, // Qanba
|
||||||
0x2dc8, // 8BitDo
|
0x2dc8, // 8BitDo
|
||||||
0x3537, // GameSir
|
|
||||||
0x37d7, // Flydigi
|
0x37d7, // Flydigi
|
||||||
0x9886, // ASTRO Gaming
|
0x9886, // ASTRO Gaming
|
||||||
};
|
};
|
||||||
@@ -361,7 +360,7 @@ public class HIDDeviceManager {
|
|||||||
HIDDeviceUSB device = new HIDDeviceUSB(this, usbDevice, interface_index);
|
HIDDeviceUSB device = new HIDDeviceUSB(this, usbDevice, interface_index);
|
||||||
int id = device.getId();
|
int id = device.getId();
|
||||||
mDevicesById.put(id, device);
|
mDevicesById.put(id, device);
|
||||||
HIDDeviceConnected(id, device.getIdentifier(), device.getVendorId(), device.getProductId(), device.getSerialNumber(), device.getVersion(), device.getManufacturerName(), device.getProductName(), usbInterface.getId(), usbInterface.getInterfaceClass(), usbInterface.getInterfaceSubclass(), usbInterface.getInterfaceProtocol(), false, 0);
|
HIDDeviceConnected(id, device.getIdentifier(), device.getVendorId(), device.getProductId(), device.getSerialNumber(), device.getVersion(), device.getManufacturerName(), device.getProductName(), usbInterface.getId(), usbInterface.getInterfaceClass(), usbInterface.getInterfaceSubclass(), usbInterface.getInterfaceProtocol(), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -530,13 +529,7 @@ public class HIDDeviceManager {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Steam Controllers will always support Bluetooth Low Energy
|
return bluetoothDevice.getName().equals("SteamController") && ((bluetoothDevice.getType() & BluetoothDevice.DEVICE_TYPE_LE) != 0);
|
||||||
if ((bluetoothDevice.getType() & BluetoothDevice.DEVICE_TYPE_LE) == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Match on the name either the original Steam Controller or the new second-generation one advertise with.
|
|
||||||
return bluetoothDevice.getName().equals("SteamController") || bluetoothDevice.getName().startsWith("Steam Ctrl");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void close() {
|
private void close() {
|
||||||
@@ -688,7 +681,7 @@ public class HIDDeviceManager {
|
|||||||
private native void HIDDeviceRegisterCallback();
|
private native void HIDDeviceRegisterCallback();
|
||||||
private native void HIDDeviceReleaseCallback();
|
private native void HIDDeviceReleaseCallback();
|
||||||
|
|
||||||
native void HIDDeviceConnected(int deviceID, String identifier, int vendorId, int productId, String serial_number, int release_number, String manufacturer_string, String product_string, int interface_number, int interface_class, int interface_subclass, int interface_protocol, boolean bBluetooth, int reportID);
|
native void HIDDeviceConnected(int deviceID, String identifier, int vendorId, int productId, String serial_number, int release_number, String manufacturer_string, String product_string, int interface_number, int interface_class, int interface_subclass, int interface_protocol, boolean bBluetooth);
|
||||||
native void HIDDeviceOpenPending(int deviceID);
|
native void HIDDeviceOpenPending(int deviceID);
|
||||||
native void HIDDeviceOpenResult(int deviceID, boolean opened);
|
native void HIDDeviceOpenResult(int deviceID, boolean opened);
|
||||||
native void HIDDeviceDisconnected(int deviceID);
|
native void HIDDeviceDisconnected(int deviceID);
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ class HIDDeviceUSB implements HIDDevice {
|
|||||||
protected InputThread mInputThread;
|
protected InputThread mInputThread;
|
||||||
protected boolean mRunning;
|
protected boolean mRunning;
|
||||||
protected boolean mFrozen;
|
protected boolean mFrozen;
|
||||||
protected boolean mClaimed;
|
|
||||||
|
|
||||||
public HIDDeviceUSB(HIDDeviceManager manager, UsbDevice usbDevice, int interface_index) {
|
public HIDDeviceUSB(HIDDeviceManager manager, UsbDevice usbDevice, int interface_index) {
|
||||||
mManager = manager;
|
mManager = manager;
|
||||||
@@ -30,7 +29,6 @@ class HIDDeviceUSB implements HIDDevice {
|
|||||||
mInterface = mDevice.getInterface(mInterfaceIndex).getId();
|
mInterface = mDevice.getInterface(mInterfaceIndex).getId();
|
||||||
mDeviceId = manager.getDeviceIDForIdentifier(getIdentifier());
|
mDeviceId = manager.getDeviceIDForIdentifier(getIdentifier());
|
||||||
mRunning = false;
|
mRunning = false;
|
||||||
mClaimed = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String getIdentifier() {
|
String getIdentifier() {
|
||||||
@@ -116,7 +114,6 @@ class HIDDeviceUSB implements HIDDevice {
|
|||||||
close();
|
close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
mClaimed = true;
|
|
||||||
|
|
||||||
// Find the endpoints
|
// Find the endpoints
|
||||||
for (int j = 0; j < iface.getEndpointCount(); j++) {
|
for (int j = 0; j < iface.getEndpointCount(); j++) {
|
||||||
@@ -135,12 +132,9 @@ class HIDDeviceUSB implements HIDDevice {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure the required endpoints were present. The original Steam Controller and the wireless dongle for it do NOT
|
// Make sure the required endpoints were present
|
||||||
// actually have -- or require -- output endpoints, so we need to accept only an input one for them or else we'll fall
|
if (mInputEndpoint == null || mOutputEndpoint == null) {
|
||||||
// back to the Android system gamepad functionality (and lose our paddles et al).
|
|
||||||
if (mInputEndpoint == null) {
|
|
||||||
Log.w(TAG, "Missing required endpoint on USB device " + getDeviceName());
|
Log.w(TAG, "Missing required endpoint on USB device " + getDeviceName());
|
||||||
mConnection.releaseInterface(iface);
|
|
||||||
close();
|
close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -160,11 +154,6 @@ class HIDDeviceUSB implements HIDDevice {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mClaimed) {
|
|
||||||
Log.w(TAG, "writeReport() called but some other process currently owns the USB device");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (feature) {
|
if (feature) {
|
||||||
int res = -1;
|
int res = -1;
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
@@ -196,11 +185,6 @@ class HIDDeviceUSB implements HIDDevice {
|
|||||||
}
|
}
|
||||||
return length;
|
return length;
|
||||||
} else {
|
} else {
|
||||||
if (mOutputEndpoint == null)
|
|
||||||
{
|
|
||||||
Log.e(TAG, "Tried to write an output report to an interface with no output endpoint!");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
int res = mConnection.bulkTransfer(mOutputEndpoint, report, report.length, 1000);
|
int res = mConnection.bulkTransfer(mOutputEndpoint, report, report.length, 1000);
|
||||||
if (res != report.length) {
|
if (res != report.length) {
|
||||||
Log.w(TAG, "writeOutputReport() returned " + res + " on device " + getDeviceName());
|
Log.w(TAG, "writeOutputReport() returned " + res + " on device " + getDeviceName());
|
||||||
@@ -221,12 +205,6 @@ class HIDDeviceUSB implements HIDDevice {
|
|||||||
Log.w(TAG, "readReport() called with no device connection");
|
Log.w(TAG, "readReport() called with no device connection");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!mClaimed) {
|
|
||||||
if (feature) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (report_number == 0x0) {
|
if (report_number == 0x0) {
|
||||||
/* Offset the return buffer by 1, so that the report ID
|
/* Offset the return buffer by 1, so that the report ID
|
||||||
@@ -280,13 +258,10 @@ class HIDDeviceUSB implements HIDDevice {
|
|||||||
mInputThread = null;
|
mInputThread = null;
|
||||||
}
|
}
|
||||||
if (mConnection != null) {
|
if (mConnection != null) {
|
||||||
if (mClaimed) {
|
UsbInterface iface = mDevice.getInterface(mInterfaceIndex);
|
||||||
UsbInterface iface = mDevice.getInterface(mInterfaceIndex);
|
mConnection.releaseInterface(iface);
|
||||||
mConnection.releaseInterface(iface);
|
|
||||||
}
|
|
||||||
mConnection.close();
|
mConnection.close();
|
||||||
mConnection = null;
|
mConnection = null;
|
||||||
mClaimed = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -299,22 +274,6 @@ class HIDDeviceUSB implements HIDDevice {
|
|||||||
@Override
|
@Override
|
||||||
public void setFrozen(boolean frozen) {
|
public void setFrozen(boolean frozen) {
|
||||||
mFrozen = frozen;
|
mFrozen = frozen;
|
||||||
|
|
||||||
/* If we have a valid device connection and the claim state doesn't match what we want, try to correct that. */
|
|
||||||
if (mConnection != null && mClaimed == mFrozen) {
|
|
||||||
UsbInterface iface = mDevice.getInterface(mInterfaceIndex);
|
|
||||||
if (frozen) {
|
|
||||||
mClaimed = !mConnection.releaseInterface(iface);
|
|
||||||
if (mClaimed) {
|
|
||||||
Log.e(TAG, "Tried to release claim on USB device, but failed!");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
mClaimed = mConnection.claimInterface(iface, true);
|
|
||||||
if (!mClaimed) {
|
|
||||||
Log.e(TAG, "Tried to regain claim on USB device, but failed!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected class InputThread extends Thread {
|
protected class InputThread extends Thread {
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
|||||||
private static final String TAG = "SDL";
|
private static final String TAG = "SDL";
|
||||||
private static final int SDL_MAJOR_VERSION = 3;
|
private static final int SDL_MAJOR_VERSION = 3;
|
||||||
private static final int SDL_MINOR_VERSION = 4;
|
private static final int SDL_MINOR_VERSION = 4;
|
||||||
private static final int SDL_MICRO_VERSION = 10;
|
private static final int SDL_MICRO_VERSION = 8;
|
||||||
/*
|
/*
|
||||||
// Display InputType.SOURCE/CLASS of events and devices
|
// Display InputType.SOURCE/CLASS of events and devices
|
||||||
//
|
//
|
||||||
@@ -530,8 +530,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
|||||||
|
|
||||||
if (mHIDDeviceManager != null) {
|
if (mHIDDeviceManager != null) {
|
||||||
mHIDDeviceManager.setFrozen(true);
|
mHIDDeviceManager.setFrozen(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mHasMultiWindow) {
|
if (!mHasMultiWindow) {
|
||||||
pauseNativeThread();
|
pauseNativeThread();
|
||||||
}
|
}
|
||||||
@@ -544,8 +543,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
|||||||
|
|
||||||
if (mHIDDeviceManager != null) {
|
if (mHIDDeviceManager != null) {
|
||||||
mHIDDeviceManager.setFrozen(false);
|
mHIDDeviceManager.setFrozen(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mHasMultiWindow) {
|
if (!mHasMultiWindow) {
|
||||||
resumeNativeThread();
|
resumeNativeThread();
|
||||||
}
|
}
|
||||||
@@ -618,14 +616,6 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
|||||||
super.onWindowFocusChanged(hasFocus);
|
super.onWindowFocusChanged(hasFocus);
|
||||||
Log.v(TAG, "onWindowFocusChanged(): " + hasFocus);
|
Log.v(TAG, "onWindowFocusChanged(): " + hasFocus);
|
||||||
|
|
||||||
// If we are gaining focus, we can always try to restore our USB devices. If we are losing focus,
|
|
||||||
// only try to relinquish them if we don't have background events allowed (for multi-window Android setups).
|
|
||||||
if (hasFocus || !SDLActivity.nativeGetHintBoolean("SDL_JOYSTICK_ALLOW_BACKGROUND_EVENTS", false)) {
|
|
||||||
if (mHIDDeviceManager != null) {
|
|
||||||
mHIDDeviceManager.setFrozen(!hasFocus);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SDLActivity.mBrokenLibraries) {
|
if (SDLActivity.mBrokenLibraries) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1491,11 +1481,11 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
|||||||
if (SDLControllerManager.isDeviceSDLJoystick(deviceId)) {
|
if (SDLControllerManager.isDeviceSDLJoystick(deviceId)) {
|
||||||
// Note that we process events with specific key codes here
|
// Note that we process events with specific key codes here
|
||||||
if (event.getAction() == KeyEvent.ACTION_DOWN) {
|
if (event.getAction() == KeyEvent.ACTION_DOWN) {
|
||||||
if (SDLControllerManager.onNativePadDown(deviceId, keyCode, event.getScanCode())) {
|
if (SDLControllerManager.onNativePadDown(deviceId, keyCode)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else if (event.getAction() == KeyEvent.ACTION_UP) {
|
} else if (event.getAction() == KeyEvent.ACTION_UP) {
|
||||||
if (SDLControllerManager.onNativePadUp(deviceId, keyCode, event.getScanCode())) {
|
if (SDLControllerManager.onNativePadUp(deviceId, keyCode)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1973,7 +1963,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
|||||||
Intent i = new Intent(Intent.ACTION_VIEW);
|
Intent i = new Intent(Intent.ACTION_VIEW);
|
||||||
i.setData(Uri.parse(url));
|
i.setData(Uri.parse(url));
|
||||||
|
|
||||||
int flags = Intent.FLAG_ACTIVITY_NO_HISTORY
|
int flags = Intent.FLAG_ACTIVITY_NO_HISTORY
|
||||||
| Intent.FLAG_ACTIVITY_MULTIPLE_TASK
|
| Intent.FLAG_ACTIVITY_MULTIPLE_TASK
|
||||||
| Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
|
| Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
|
||||||
i.addFlags(flags);
|
i.addFlags(flags);
|
||||||
@@ -2237,4 +2227,3 @@ class SDLClipboardHandler implements
|
|||||||
SDLActivity.onNativeClipboardChanged();
|
SDLActivity.onNativeClipboardChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,10 +10,6 @@ import android.hardware.lights.Light;
|
|||||||
import android.hardware.lights.LightsRequest;
|
import android.hardware.lights.LightsRequest;
|
||||||
import android.hardware.lights.LightsManager;
|
import android.hardware.lights.LightsManager;
|
||||||
import android.hardware.lights.LightState;
|
import android.hardware.lights.LightState;
|
||||||
import android.hardware.Sensor;
|
|
||||||
import android.hardware.SensorEvent;
|
|
||||||
import android.hardware.SensorEventListener;
|
|
||||||
import android.hardware.SensorManager;
|
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.VibrationEffect;
|
import android.os.VibrationEffect;
|
||||||
@@ -34,18 +30,16 @@ public class SDLControllerManager
|
|||||||
static native void nativeAddJoystick(int device_id, String name, String desc,
|
static native void nativeAddJoystick(int device_id, String name, String desc,
|
||||||
int vendor_id, int product_id,
|
int vendor_id, int product_id,
|
||||||
int button_mask,
|
int button_mask,
|
||||||
int naxes, int axis_mask, int nhats, boolean can_rumble, boolean has_rgb_led,
|
int naxes, int axis_mask, int nhats, boolean can_rumble, boolean has_rgb_led);
|
||||||
boolean has_accelerometer, boolean has_gyroscope);
|
|
||||||
static native void nativeRemoveJoystick(int device_id);
|
static native void nativeRemoveJoystick(int device_id);
|
||||||
static native void nativeAddHaptic(int device_id, String name);
|
static native void nativeAddHaptic(int device_id, String name);
|
||||||
static native void nativeRemoveHaptic(int device_id);
|
static native void nativeRemoveHaptic(int device_id);
|
||||||
static public native boolean onNativePadDown(int device_id, int keycode, int scancode);
|
static public native boolean onNativePadDown(int device_id, int keycode);
|
||||||
static public native boolean onNativePadUp(int device_id, int keycode, int scancode);
|
static public native boolean onNativePadUp(int device_id, int keycode);
|
||||||
static native void onNativeJoy(int device_id, int axis,
|
static native void onNativeJoy(int device_id, int axis,
|
||||||
float value);
|
float value);
|
||||||
static native void onNativeHat(int device_id, int hat_id,
|
static native void onNativeHat(int device_id, int hat_id,
|
||||||
int x, int y);
|
int x, int y);
|
||||||
static native void onNativeJoySensor(int device_id, int sensor_type, long sensor_timestamp, float x, float y, float z);
|
|
||||||
|
|
||||||
protected static SDLJoystickHandler mJoystickHandler;
|
protected static SDLJoystickHandler mJoystickHandler;
|
||||||
protected static SDLHapticHandler mHapticHandler;
|
protected static SDLHapticHandler mHapticHandler;
|
||||||
@@ -87,13 +81,6 @@ public class SDLControllerManager
|
|||||||
mJoystickHandler.setLED(device_id, red, green, blue);
|
mJoystickHandler.setLED(device_id, red, green, blue);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called by SDL using JNI.
|
|
||||||
*/
|
|
||||||
static void joystickSetSensorsEnabled(int device_id, boolean enabled) {
|
|
||||||
mJoystickHandler.setSensorsEnabled(device_id, enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is called by SDL using JNI.
|
* This method is called by SDL using JNI.
|
||||||
*/
|
*/
|
||||||
@@ -166,10 +153,6 @@ class SDLJoystickHandler {
|
|||||||
ArrayList<InputDevice.MotionRange> hats;
|
ArrayList<InputDevice.MotionRange> hats;
|
||||||
ArrayList<Light> lights;
|
ArrayList<Light> lights;
|
||||||
LightsManager.LightsSession lightsSession;
|
LightsManager.LightsSession lightsSession;
|
||||||
SensorManager sensorManager;
|
|
||||||
SDLJoySensorListener sensorListener;
|
|
||||||
Sensor accelerometerSensor;
|
|
||||||
Sensor gyroscopeSensor;
|
|
||||||
}
|
}
|
||||||
static class RangeComparator implements Comparator<InputDevice.MotionRange> {
|
static class RangeComparator implements Comparator<InputDevice.MotionRange> {
|
||||||
@Override
|
@Override
|
||||||
@@ -242,13 +225,12 @@ class SDLJoystickHandler {
|
|||||||
joystick.desc = getJoystickDescriptor(joystickDevice);
|
joystick.desc = getJoystickDescriptor(joystickDevice);
|
||||||
joystick.axes = new ArrayList<InputDevice.MotionRange>();
|
joystick.axes = new ArrayList<InputDevice.MotionRange>();
|
||||||
joystick.hats = new ArrayList<InputDevice.MotionRange>();
|
joystick.hats = new ArrayList<InputDevice.MotionRange>();
|
||||||
java.util.Set<Integer> axisStrsSet = new java.util.HashSet<Integer>();
|
|
||||||
joystick.lights = new ArrayList<Light>();
|
joystick.lights = new ArrayList<Light>();
|
||||||
|
|
||||||
List<InputDevice.MotionRange> ranges = joystickDevice.getMotionRanges();
|
List<InputDevice.MotionRange> ranges = joystickDevice.getMotionRanges();
|
||||||
Collections.sort(ranges, new RangeComparator());
|
Collections.sort(ranges, new RangeComparator());
|
||||||
for (InputDevice.MotionRange range : ranges) {
|
for (InputDevice.MotionRange range : ranges) {
|
||||||
if (((range.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) && axisStrsSet.add(range.getAxis())) {
|
if ((range.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) {
|
||||||
if (range.getAxis() == MotionEvent.AXIS_HAT_X || range.getAxis() == MotionEvent.AXIS_HAT_Y) {
|
if (range.getAxis() == MotionEvent.AXIS_HAT_X || range.getAxis() == MotionEvent.AXIS_HAT_Y) {
|
||||||
joystick.hats.add(range);
|
joystick.hats.add(range);
|
||||||
} else {
|
} else {
|
||||||
@@ -259,8 +241,6 @@ class SDLJoystickHandler {
|
|||||||
|
|
||||||
boolean can_rumble = false;
|
boolean can_rumble = false;
|
||||||
boolean has_rgb_led = false;
|
boolean has_rgb_led = false;
|
||||||
boolean has_accelerometer = false;
|
|
||||||
boolean has_gyroscope = false;
|
|
||||||
if (Build.VERSION.SDK_INT >= 31 /* Android 12.0 (S) */) {
|
if (Build.VERSION.SDK_INT >= 31 /* Android 12.0 (S) */) {
|
||||||
VibratorManager vibratorManager = joystickDevice.getVibratorManager();
|
VibratorManager vibratorManager = joystickDevice.getVibratorManager();
|
||||||
int[] vibrators = vibratorManager.getVibratorIds();
|
int[] vibrators = vibratorManager.getVibratorIds();
|
||||||
@@ -278,26 +258,12 @@ class SDLJoystickHandler {
|
|||||||
joystick.lightsSession = lightsManager.openSession();
|
joystick.lightsSession = lightsManager.openSession();
|
||||||
has_rgb_led = true;
|
has_rgb_led = true;
|
||||||
}
|
}
|
||||||
SensorManager sensorManager = joystickDevice.getSensorManager();
|
|
||||||
if (sensorManager != null) {
|
|
||||||
joystick.sensorManager = sensorManager;
|
|
||||||
joystick.sensorListener = new SDLJoySensorListener(joystick.device_id);
|
|
||||||
joystick.accelerometerSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
|
|
||||||
if (joystick.accelerometerSensor != null) {
|
|
||||||
has_accelerometer = true;
|
|
||||||
}
|
|
||||||
joystick.gyroscopeSensor = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
|
|
||||||
if (joystick.gyroscopeSensor != null) {
|
|
||||||
has_gyroscope = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mJoysticks.add(joystick);
|
mJoysticks.add(joystick);
|
||||||
SDLControllerManager.nativeAddJoystick(joystick.device_id, joystick.name, joystick.desc,
|
SDLControllerManager.nativeAddJoystick(joystick.device_id, joystick.name, joystick.desc,
|
||||||
getVendorId(joystickDevice), getProductId(joystickDevice),
|
getVendorId(joystickDevice), getProductId(joystickDevice),
|
||||||
getButtonMask(joystickDevice), joystick.axes.size(), getAxisMask(joystick.axes), joystick.hats.size()/2, can_rumble, has_rgb_led,
|
getButtonMask(joystickDevice), joystick.axes.size(), getAxisMask(joystick.axes), joystick.hats.size()/2, can_rumble, has_rgb_led);
|
||||||
has_accelerometer, has_gyroscope);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -542,31 +508,6 @@ class SDLJoystickHandler {
|
|||||||
}
|
}
|
||||||
joystick.lightsSession.requestLights(lightsRequest.build());
|
joystick.lightsSession.requestLights(lightsRequest.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
void setSensorsEnabled(int device_id, boolean enabled) {
|
|
||||||
if (Build.VERSION.SDK_INT < 31 /* Android 12.0 (S) */) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
SDLJoystick joystick = getJoystick(device_id);
|
|
||||||
if (joystick == null || joystick.sensorManager == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (enabled) {
|
|
||||||
if (joystick.accelerometerSensor != null) {
|
|
||||||
SDLSensorManager.registerListener(joystick.sensorManager, joystick.sensorListener, joystick.accelerometerSensor, SensorManager.SENSOR_DELAY_GAME);
|
|
||||||
}
|
|
||||||
if (joystick.gyroscopeSensor != null) {
|
|
||||||
SDLSensorManager.registerListener(joystick.sensorManager, joystick.sensorListener, joystick.gyroscopeSensor, SensorManager.SENSOR_DELAY_GAME);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (joystick.accelerometerSensor != null) {
|
|
||||||
SDLSensorManager.unregisterListener(joystick.sensorManager, joystick.sensorListener, joystick.accelerometerSensor);
|
|
||||||
}
|
|
||||||
if (joystick.gyroscopeSensor != null) {
|
|
||||||
SDLSensorManager.unregisterListener(joystick.sensorManager, joystick.sensorListener, joystick.gyroscopeSensor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class SDLHapticHandler_API31 extends SDLHapticHandler {
|
class SDLHapticHandler_API31 extends SDLHapticHandler {
|
||||||
@@ -992,19 +933,3 @@ class SDLGenericMotionListener_API29 extends SDLGenericMotionListener_API26 {
|
|||||||
return penDevice.isExternal() ? SDL_PEN_DEVICE_TYPE_INDIRECT : SDL_PEN_DEVICE_TYPE_DIRECT;
|
return penDevice.isExternal() ? SDL_PEN_DEVICE_TYPE_INDIRECT : SDL_PEN_DEVICE_TYPE_DIRECT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SDLJoySensorListener implements SensorEventListener {
|
|
||||||
int device_id;
|
|
||||||
|
|
||||||
public SDLJoySensorListener(int device_id) {
|
|
||||||
this.device_id = device_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onAccuracyChanged(Sensor sensor, int accuracy) {}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onSensorChanged(SensorEvent event) {
|
|
||||||
SDLControllerManager.onNativeJoySensor(device_id, event.sensor.getType(), event.timestamp, event.values[0], event.values[1], event.values[2]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
package org.libsdl.app;
|
|
||||||
|
|
||||||
import android.hardware.Sensor;
|
|
||||||
import android.hardware.SensorEventListener;
|
|
||||||
import android.hardware.SensorManager;
|
|
||||||
|
|
||||||
// This class coordinates synchronized access to sensor manager registration
|
|
||||||
//
|
|
||||||
// This prevents a java.util.ConcurrentModificationException exception on
|
|
||||||
// Android 16, specifically on the Samsung Tab S9 Ultra.
|
|
||||||
|
|
||||||
class SDLSensorManager
|
|
||||||
{
|
|
||||||
static private SDLSensorManager mManager = new SDLSensorManager();
|
|
||||||
|
|
||||||
public static void registerListener(SensorManager manager, SensorEventListener listener, Sensor sensor, int samplingPeriodUs) {
|
|
||||||
mManager.RegisterListener(manager, listener, sensor, samplingPeriodUs);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void unregisterListener(SensorManager manager, SensorEventListener listener, Sensor sensor) {
|
|
||||||
mManager.UnregisterListener(manager, listener, sensor);
|
|
||||||
}
|
|
||||||
|
|
||||||
private synchronized void RegisterListener(SensorManager manager, SensorEventListener listener, Sensor sensor, int samplingPeriodUs) {
|
|
||||||
manager.registerListener(listener, sensor, samplingPeriodUs, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
private synchronized void UnregisterListener(SensorManager manager, SensorEventListener listener, Sensor sensor) {
|
|
||||||
manager.unregisterListener(listener, sensor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -47,9 +47,6 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
|
|||||||
// Is SurfaceView ready for rendering
|
// Is SurfaceView ready for rendering
|
||||||
protected boolean mIsSurfaceReady;
|
protected boolean mIsSurfaceReady;
|
||||||
|
|
||||||
// Is on-screen keyboard visible
|
|
||||||
protected boolean mKeyboardVisible;
|
|
||||||
|
|
||||||
// Pinch events
|
// Pinch events
|
||||||
private final ScaleGestureDetector scaleGestureDetector;
|
private final ScaleGestureDetector scaleGestureDetector;
|
||||||
|
|
||||||
@@ -216,18 +213,6 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
|
|||||||
WindowInsets.Type.displayCutout());
|
WindowInsets.Type.displayCutout());
|
||||||
|
|
||||||
SDLActivity.onNativeInsetsChanged(combined.left, combined.right, combined.top, combined.bottom);
|
SDLActivity.onNativeInsetsChanged(combined.left, combined.right, combined.top, combined.bottom);
|
||||||
|
|
||||||
if (insets.isVisible(WindowInsets.Type.ime())) {
|
|
||||||
if (!mKeyboardVisible) {
|
|
||||||
mKeyboardVisible = true;
|
|
||||||
SDLActivity.onNativeScreenKeyboardShown();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (mKeyboardVisible) {
|
|
||||||
mKeyboardVisible = false;
|
|
||||||
SDLActivity.onNativeScreenKeyboardHidden();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pass these to any child views in case they need them
|
// Pass these to any child views in case they need them
|
||||||
@@ -333,11 +318,11 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
|
|||||||
protected void enableSensor(int sensortype, boolean enabled) {
|
protected void enableSensor(int sensortype, boolean enabled) {
|
||||||
// TODO: This uses getDefaultSensor - what if we have >1 accels?
|
// TODO: This uses getDefaultSensor - what if we have >1 accels?
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
SDLSensorManager.registerListener(mSensorManager, this,
|
mSensorManager.registerListener(this,
|
||||||
mSensorManager.getDefaultSensor(sensortype),
|
mSensorManager.getDefaultSensor(sensortype),
|
||||||
SensorManager.SENSOR_DELAY_GAME);
|
SensorManager.SENSOR_DELAY_GAME, null);
|
||||||
} else {
|
} else {
|
||||||
SDLSensorManager.unregisterListener(mSensorManager, this,
|
mSensorManager.unregisterListener(this,
|
||||||
mSensorManager.getDefaultSensor(sensortype));
|
mSensorManager.getDefaultSensor(sensortype));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
*, *:before, *:after {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
overflow: visible;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
console {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 10dp;
|
||||||
|
left: 10dp;
|
||||||
|
width: 50%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
background-color: rgba(0, 0, 0, 60%);
|
||||||
|
pointer-events: auto;
|
||||||
|
font-family: "Noto Mono";
|
||||||
|
font-size: 14dp;
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
output {
|
||||||
|
display: block;
|
||||||
|
overflow: hidden;
|
||||||
|
max-height: 480dp;
|
||||||
|
padding: 4dp 8dp;
|
||||||
|
line-height: 1.4em;
|
||||||
|
}
|
||||||
|
|
||||||
|
output[open] {
|
||||||
|
height: 480dp;
|
||||||
|
max-height: 480dp;
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
line {
|
||||||
|
display: block;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
line.cmd {
|
||||||
|
color: #FFD966;
|
||||||
|
}
|
||||||
|
|
||||||
|
console input {
|
||||||
|
display: none;
|
||||||
|
width: 100%;
|
||||||
|
background-color: rgba(0, 0, 0, 40%);
|
||||||
|
border: 0dp;
|
||||||
|
border-top: 1dp rgba(255, 255, 255, 20%);
|
||||||
|
color: #FFFFFF;
|
||||||
|
font-family: "Noto Mono";
|
||||||
|
font-size: 14dp;
|
||||||
|
padding: 4dp 8dp;
|
||||||
|
}
|
||||||
|
|
||||||
|
console[open] input {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
@@ -16,7 +16,7 @@ body {
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
z-index: 2;
|
z-index: 1;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,339 +0,0 @@
|
|||||||
*, *:before, *:after {
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
overflow: hidden;
|
|
||||||
font-family: "Fira Sans Condensed";
|
|
||||||
font-weight: bold;
|
|
||||||
color: rgba(248, 244, 232, 90%);
|
|
||||||
z-index: 1;
|
|
||||||
filter: opacity(0);
|
|
||||||
transition: filter 0.2s linear-in-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
body[open] {
|
|
||||||
filter: opacity(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
body:not([open]) {
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
decorator: none;
|
|
||||||
padding: 0;
|
|
||||||
border: 1dp rgba(255, 255, 255, 22%);
|
|
||||||
background-color: rgba(22, 24, 28, 48%);
|
|
||||||
color: rgba(248, 244, 232, 90%);
|
|
||||||
text-align: center;
|
|
||||||
/* backdrop-filter: blur(7dp); */
|
|
||||||
/* box-shadow: 0 6dp 18dp rgba(0, 0, 0, 28%); */
|
|
||||||
transform-origin: center;
|
|
||||||
transition: background-color border-color filter transform 0.08s linear-in-out,
|
|
||||||
opacity 0.2s linear-in-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
button.pressed,
|
|
||||||
button.active {
|
|
||||||
background-color: rgba(63, 78, 90, 68%);
|
|
||||||
border-color: rgba(255, 255, 255, 48%);
|
|
||||||
filter: brightness(1.18);
|
|
||||||
}
|
|
||||||
|
|
||||||
button:hidden {
|
|
||||||
opacity: 0;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
button span {
|
|
||||||
display: block;
|
|
||||||
line-height: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
button icon {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
button icon glyph {
|
|
||||||
display: block;
|
|
||||||
font-family: "Material Symbols Rounded";
|
|
||||||
font-weight: normal;
|
|
||||||
font-size: 24dp;
|
|
||||||
line-height: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.midna-icon,
|
|
||||||
.item-icon,
|
|
||||||
.item-count,
|
|
||||||
.oil-meter {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.midna-icon.visible,
|
|
||||||
.item-icon.visible,
|
|
||||||
.item-count.visible,
|
|
||||||
.oil-meter.visible {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.control {
|
|
||||||
position: absolute;
|
|
||||||
}
|
|
||||||
|
|
||||||
.trigger-l.active {
|
|
||||||
background-color: rgba(57, 116, 133, 74%);
|
|
||||||
border-color: rgba(128, 222, 234, 72%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.trigger,
|
|
||||||
.skip {
|
|
||||||
border-radius: 23dp;
|
|
||||||
}
|
|
||||||
|
|
||||||
.trigger {
|
|
||||||
font-size: 22dp;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button-z {
|
|
||||||
background-color: rgba(118, 79, 158, 58%);
|
|
||||||
border-color: rgba(203, 170, 255, 36%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.midna-icon {
|
|
||||||
position: absolute;
|
|
||||||
left: 9dp;
|
|
||||||
top: -1dp;
|
|
||||||
height: 48dp;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button-z.has-icon span,
|
|
||||||
.face.has-item span {
|
|
||||||
position: absolute;
|
|
||||||
font-size: 13dp;
|
|
||||||
line-height: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button-z.has-icon span {
|
|
||||||
right: 9dp;
|
|
||||||
bottom: 7dp;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button-z.pressed {
|
|
||||||
background-color: rgba(139, 91, 187, 82%);
|
|
||||||
border-color: rgba(220, 194, 255, 70%);
|
|
||||||
}
|
|
||||||
|
|
||||||
action-bar {
|
|
||||||
position: absolute;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
border: 1dp rgba(255, 255, 255, 22%);
|
|
||||||
border-radius: 23dp;
|
|
||||||
background-color: rgba(22, 24, 28, 48%);
|
|
||||||
/* backdrop-filter: blur(7dp); */
|
|
||||||
/* box-shadow: 0 -6dp 18dp rgba(0, 0, 0, 28%); */
|
|
||||||
overflow: hidden;
|
|
||||||
opacity: 1;
|
|
||||||
transform-origin: center;
|
|
||||||
transition: opacity 0.2s linear-in-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
action-bar:hidden,
|
|
||||||
action-bar:hidden button,
|
|
||||||
action-bar:hidden separator {
|
|
||||||
opacity: 0;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.utility {
|
|
||||||
position: relative;
|
|
||||||
flex: 1 1 auto;
|
|
||||||
width: 56dp;
|
|
||||||
height: 44dp;
|
|
||||||
margin: 0;
|
|
||||||
border-width: 0dp;
|
|
||||||
border-radius: 0;
|
|
||||||
background-color: transparent;
|
|
||||||
box-shadow: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.utility,
|
|
||||||
.skip {
|
|
||||||
opacity: 0.55;
|
|
||||||
}
|
|
||||||
|
|
||||||
.utility.pressed {
|
|
||||||
background-color: rgba(63, 78, 90, 68%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.utility.pressed,
|
|
||||||
.skip.pressed {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.skip {
|
|
||||||
z-index: 1;
|
|
||||||
border-color: rgba(255, 255, 255, 36%);
|
|
||||||
}
|
|
||||||
|
|
||||||
separator {
|
|
||||||
display: block;
|
|
||||||
flex: 0 0 1dp;
|
|
||||||
width: 1dp;
|
|
||||||
height: 24dp;
|
|
||||||
background-color: rgba(255, 255, 255, 18%);
|
|
||||||
opacity: 1;
|
|
||||||
transition: opacity 0.2s linear-in-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
.face {
|
|
||||||
position: absolute;
|
|
||||||
border-radius: 29dp;
|
|
||||||
font-size: 24dp;
|
|
||||||
overflow: visible;
|
|
||||||
}
|
|
||||||
|
|
||||||
.item-icon {
|
|
||||||
width: auto;
|
|
||||||
height: auto;
|
|
||||||
max-width: 76%;
|
|
||||||
max-height: 76%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.item-count {
|
|
||||||
position: absolute;
|
|
||||||
left: 6dp;
|
|
||||||
bottom: 5dp;
|
|
||||||
min-width: 17dp;
|
|
||||||
height: 15dp;
|
|
||||||
padding: 1dp 3dp;
|
|
||||||
border-radius: 7dp;
|
|
||||||
background-color: rgba(0, 0, 0, 52%);
|
|
||||||
color: rgba(255, 255, 255, 92%);
|
|
||||||
font-size: 12dp;
|
|
||||||
line-height: 13dp;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.oil-meter {
|
|
||||||
position: absolute;
|
|
||||||
left: 12dp;
|
|
||||||
bottom: -5dp;
|
|
||||||
width: 34dp;
|
|
||||||
height: 8dp;
|
|
||||||
padding: 2dp;
|
|
||||||
border: 1dp rgba(42, 32, 18, 82%);
|
|
||||||
border-radius: 4dp;
|
|
||||||
background-color: rgba(18, 14, 10, 70%);
|
|
||||||
/* box-shadow: 0 2dp 6dp rgba(0, 0, 0, 35%); */
|
|
||||||
}
|
|
||||||
|
|
||||||
oil-fill {
|
|
||||||
display: block;
|
|
||||||
width: 0%;
|
|
||||||
height: 100%;
|
|
||||||
border-radius: 2dp;
|
|
||||||
background-color: rgb(255, 232, 74);
|
|
||||||
}
|
|
||||||
|
|
||||||
.face.has-item span {
|
|
||||||
right: 6dp;
|
|
||||||
bottom: 6dp;
|
|
||||||
color: rgba(255, 255, 255, 88%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.face.a {
|
|
||||||
border-radius: 37dp;
|
|
||||||
font-size: 31dp;
|
|
||||||
background-color: rgba(34, 112, 123, 62%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.face.b {
|
|
||||||
background-color: rgba(161, 61, 66, 58%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.face.x {
|
|
||||||
background-color: rgba(83, 115, 151, 56%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.face.y {
|
|
||||||
background-color: rgba(113, 91, 150, 54%);
|
|
||||||
}
|
|
||||||
|
|
||||||
button.control.docked-top,
|
|
||||||
action-bar.docked-top {
|
|
||||||
border-top-width: 0dp;
|
|
||||||
border-top-left-radius: 0dp;
|
|
||||||
border-top-right-radius: 0dp;
|
|
||||||
}
|
|
||||||
|
|
||||||
button.control.docked-bottom,
|
|
||||||
action-bar.docked-bottom {
|
|
||||||
border-bottom-width: 0dp;
|
|
||||||
border-bottom-left-radius: 0dp;
|
|
||||||
border-bottom-right-radius: 0dp;
|
|
||||||
}
|
|
||||||
|
|
||||||
button.control.docked-left,
|
|
||||||
action-bar.docked-left {
|
|
||||||
border-left-width: 0dp;
|
|
||||||
border-top-left-radius: 0dp;
|
|
||||||
border-bottom-left-radius: 0dp;
|
|
||||||
}
|
|
||||||
|
|
||||||
button.control.docked-right,
|
|
||||||
action-bar.docked-right {
|
|
||||||
border-right-width: 0dp;
|
|
||||||
border-top-right-radius: 0dp;
|
|
||||||
border-bottom-right-radius: 0dp;
|
|
||||||
}
|
|
||||||
|
|
||||||
touch-stick {
|
|
||||||
display: block;
|
|
||||||
position: absolute;
|
|
||||||
width: 124dp;
|
|
||||||
height: 124dp;
|
|
||||||
border-radius: 62dp;
|
|
||||||
background-color: rgba(18, 20, 24, 35%);
|
|
||||||
border: 1dp rgba(255, 255, 255, 20%);
|
|
||||||
/* backdrop-filter: blur(7dp); */
|
|
||||||
/* box-shadow: 0 8dp 24dp rgba(0, 0, 0, 24%); */
|
|
||||||
opacity: 0;
|
|
||||||
pointer-events: none;
|
|
||||||
transition: opacity 0.18s linear-in-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
touch-stick.active {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
stick-ring {
|
|
||||||
position: absolute;
|
|
||||||
left: 18dp;
|
|
||||||
top: 18dp;
|
|
||||||
width: 88dp;
|
|
||||||
height: 88dp;
|
|
||||||
border-radius: 44dp;
|
|
||||||
border: 1dp rgba(255, 255, 255, 18%);
|
|
||||||
}
|
|
||||||
|
|
||||||
stick-knob {
|
|
||||||
position: absolute;
|
|
||||||
width: 48dp;
|
|
||||||
height: 48dp;
|
|
||||||
border-radius: 24dp;
|
|
||||||
background-color: rgba(238, 236, 226, 55%);
|
|
||||||
border: 1dp rgba(255, 255, 255, 45%);
|
|
||||||
}
|
|
||||||
@@ -1,138 +0,0 @@
|
|||||||
body.touch-editor {
|
|
||||||
background-color: rgba(4, 6, 8, 34%);
|
|
||||||
z-index: 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.touch-editor .control,
|
|
||||||
body.touch-editor action-bar {
|
|
||||||
opacity: 0.88;
|
|
||||||
cursor: move;
|
|
||||||
pointer-events: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.touch-editor .control:hover,
|
|
||||||
body.touch-editor action-bar:hover,
|
|
||||||
body.touch-editor .control.editor-selected,
|
|
||||||
body.touch-editor action-bar.editor-selected {
|
|
||||||
border-color: rgba(255, 232, 128, 80%);
|
|
||||||
filter: brightness(1.15);
|
|
||||||
}
|
|
||||||
|
|
||||||
body.touch-editor action-bar button,
|
|
||||||
body.touch-editor action-bar separator {
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
selection-frame {
|
|
||||||
display: none;
|
|
||||||
position: absolute;
|
|
||||||
z-index: 20;
|
|
||||||
border: 2dp rgba(255, 232, 128, 88%);
|
|
||||||
background-color: rgba(255, 232, 128, 7%);
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
selection-frame.visible {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
resize-handle {
|
|
||||||
display: block;
|
|
||||||
position: absolute;
|
|
||||||
width: 22dp;
|
|
||||||
height: 22dp;
|
|
||||||
border: 2dp rgba(255, 244, 190, 96%);
|
|
||||||
border-radius: 11dp;
|
|
||||||
background-color: rgba(34, 37, 42, 86%);
|
|
||||||
pointer-events: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
resize-handle.left {
|
|
||||||
left: -12dp;
|
|
||||||
}
|
|
||||||
|
|
||||||
resize-handle.right {
|
|
||||||
right: -12dp;
|
|
||||||
}
|
|
||||||
|
|
||||||
resize-handle.top {
|
|
||||||
top: -12dp;
|
|
||||||
}
|
|
||||||
|
|
||||||
resize-handle.bottom {
|
|
||||||
bottom: -12dp;
|
|
||||||
}
|
|
||||||
|
|
||||||
resize-handle.horizontal {
|
|
||||||
top: 50%;
|
|
||||||
margin-top: -11dp;
|
|
||||||
}
|
|
||||||
|
|
||||||
resize-handle.vertical {
|
|
||||||
left: 50%;
|
|
||||||
margin-left: -11dp;
|
|
||||||
}
|
|
||||||
|
|
||||||
resize-handle.corner.left {
|
|
||||||
left: -12dp;
|
|
||||||
}
|
|
||||||
|
|
||||||
resize-handle.corner.right {
|
|
||||||
right: -12dp;
|
|
||||||
}
|
|
||||||
|
|
||||||
resize-handle.corner.top {
|
|
||||||
top: -12dp;
|
|
||||||
}
|
|
||||||
|
|
||||||
resize-handle.corner.bottom {
|
|
||||||
bottom: -12dp;
|
|
||||||
}
|
|
||||||
|
|
||||||
editor-toolbar {
|
|
||||||
display: flex;
|
|
||||||
position: absolute;
|
|
||||||
left: 24dp;
|
|
||||||
right: 24dp;
|
|
||||||
top: 50%;
|
|
||||||
z-index: 30;
|
|
||||||
height: 48dp;
|
|
||||||
margin-top: -24dp;
|
|
||||||
gap: 8dp;
|
|
||||||
justify-content: center;
|
|
||||||
pointer-events: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
editor-toolbar button.editor-command {
|
|
||||||
flex: 0 1 150dp;
|
|
||||||
min-width: 96dp;
|
|
||||||
height: 48dp;
|
|
||||||
padding: 0 14dp;
|
|
||||||
border-radius: 8dp;
|
|
||||||
border: 1dp rgba(255, 255, 255, 26%);
|
|
||||||
background-color: rgba(17, 19, 24, 88%);
|
|
||||||
color: rgba(255, 250, 232, 94%);
|
|
||||||
font-family: "Fira Sans";
|
|
||||||
font-size: 18dp;
|
|
||||||
line-height: 48dp;
|
|
||||||
opacity: 1;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
editor-toolbar button.editor-command span {
|
|
||||||
display: block;
|
|
||||||
width: 100%;
|
|
||||||
line-height: 48dp;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
editor-toolbar button.editor-command.primary {
|
|
||||||
border-color: rgba(255, 232, 128, 70%);
|
|
||||||
background-color: rgba(96, 82, 38, 90%);
|
|
||||||
}
|
|
||||||
|
|
||||||
editor-toolbar button.editor-command:hover,
|
|
||||||
editor-toolbar button.editor-command:focus-visible {
|
|
||||||
border-color: rgba(255, 244, 190, 92%);
|
|
||||||
background-color: rgba(78, 85, 96, 92%);
|
|
||||||
}
|
|
||||||
@@ -175,13 +175,3 @@ bool daAlink_c::checkAimContext() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool daAlink_c::checkAimInputContext() {
|
|
||||||
switch (mProcID) {
|
|
||||||
case PROC_HOOKSHOT_ROOF_WAIT:
|
|
||||||
case PROC_HOOKSHOT_WALL_WAIT:
|
|
||||||
return false;
|
|
||||||
default:
|
|
||||||
return checkAimContext();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -14,7 +14,6 @@
|
|||||||
#include "dusk/action_bindings.h"
|
#include "dusk/action_bindings.h"
|
||||||
#include "dusk/gyro.h"
|
#include "dusk/gyro.h"
|
||||||
#include "dusk/mouse.h"
|
#include "dusk/mouse.h"
|
||||||
#include "dusk/touch_camera.h"
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool daAlink_c::checkNoSubjectModeCamera() {
|
bool daAlink_c::checkNoSubjectModeCamera() {
|
||||||
@@ -123,7 +122,7 @@ BOOL daAlink_c::setBodyAngleToCamera() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if TARGET_PC
|
#if TARGET_PC
|
||||||
if (dusk::getSettings().game.enableMouseAim && checkAimInputContext()) {
|
if (dusk::getSettings().game.enableMouseAim && checkAimContext()) {
|
||||||
sp8 = mBodyAngle.x;
|
sp8 = mBodyAngle.x;
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
@@ -142,7 +141,7 @@ BOOL daAlink_c::setBodyAngleToCamera() {
|
|||||||
#if TARGET_PC
|
#if TARGET_PC
|
||||||
if ((dusk::getSettings().game.enableGyroAim ||
|
if ((dusk::getSettings().game.enableGyroAim ||
|
||||||
dusk::getSettings().game.enableMouseAim) &&
|
dusk::getSettings().game.enableMouseAim) &&
|
||||||
checkAimInputContext())
|
checkAimContext())
|
||||||
{
|
{
|
||||||
f32 gyro_scale = 1.0f;
|
f32 gyro_scale = 1.0f;
|
||||||
if (checkWolfEyeUp()) {
|
if (checkWolfEyeUp()) {
|
||||||
@@ -173,32 +172,6 @@ BOOL daAlink_c::setBodyAngleToCamera() {
|
|||||||
sp8 = mBodyAngle.x;
|
sp8 = mBodyAngle.x;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dusk::getSettings().game.enableTouchControls && checkAimInputContext()) {
|
|
||||||
f32 touchYawDp = 0.0f;
|
|
||||||
f32 touchPitchDp = 0.0f;
|
|
||||||
if (dusk::touch_camera::consume_delta(touchYawDp, touchPitchDp)) {
|
|
||||||
f32 scale = 1.0f;
|
|
||||||
if (checkWolfEyeUp()) {
|
|
||||||
scale *= 0.6f;
|
|
||||||
}
|
|
||||||
if (dComIfGp_checkPlayerStatus0(0, 0x200000)) {
|
|
||||||
scale /= dComIfGp_getCameraZoomScale(field_0x317c);
|
|
||||||
}
|
|
||||||
|
|
||||||
const f32 yawDeg = -touchYawDp * dusk::touch_camera::YAW_DEGREES_PER_DP * scale *
|
|
||||||
dusk::getSettings().game.touchCameraXSensitivity;
|
|
||||||
const f32 pitchDeg = touchPitchDp * dusk::touch_camera::PITCH_DEGREES_PER_DP *
|
|
||||||
scale * dusk::getSettings().game.touchCameraYSensitivity;
|
|
||||||
|
|
||||||
shape_angle.y = shape_angle.y + cM_deg2s(yawDeg);
|
|
||||||
sp8 = sp8 + cM_deg2s(pitchDeg);
|
|
||||||
|
|
||||||
if (checkNotItemSinkLimit() && sp8 > 0 && sp8 > mBodyAngle.x) {
|
|
||||||
sp8 = mBodyAngle.x;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (checkNotItemSinkLimit() && sp8 > 0) {
|
if (checkNotItemSinkLimit() && sp8 > 0) {
|
||||||
|
|||||||
@@ -6882,16 +6882,6 @@ static int daNpc_Ks_Delete(npc_ks_class* i_this) {
|
|||||||
i_this->model->stopZelAnime();
|
i_this->model->stopZelAnime();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
if (leader == i_this) {
|
|
||||||
leader = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (saru_p[i_this->set_id] == i_this) {
|
|
||||||
saru_p[i_this->set_id] = NULL;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,12 +15,6 @@ const u16 l_J_Ohana00_64TEX__height = 63;
|
|||||||
using GameVersion = dusk::version::GameVersion;
|
using GameVersion = dusk::version::GameVersion;
|
||||||
static u8* l_J_Ohana00_64TEX_get() { static u8 buf[0x800]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", {{GameVersion::GcnUsa, 0x9060}, {GameVersion::GcnPal, 0x9060}}, 0x800), true); return buf; }
|
static u8* l_J_Ohana00_64TEX_get() { static u8 buf[0x800]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", {{GameVersion::GcnUsa, 0x9060}, {GameVersion::GcnPal, 0x9060}}, 0x800), true); return buf; }
|
||||||
#define l_J_Ohana00_64TEX (l_J_Ohana00_64TEX_get())
|
#define l_J_Ohana00_64TEX (l_J_Ohana00_64TEX_get())
|
||||||
|
|
||||||
// from d_grass.inc
|
|
||||||
static MtxP get_model_mtx(Mtx modelMtx, Mtx storage);
|
|
||||||
static void transform_positions(
|
|
||||||
const dusk::batch::LeafTemplate& tpl, const Vec* posArray, const Mtx mtx, Vec* xfPos);
|
|
||||||
static void split_batch(u32& emitted, u32 vtxCount);
|
|
||||||
#else
|
#else
|
||||||
#include "assets/l_J_Ohana00_64TEX.h"
|
#include "assets/l_J_Ohana00_64TEX.h"
|
||||||
#endif
|
#endif
|
||||||
@@ -594,12 +588,6 @@ dFlower_packet_c::dFlower_packet_c() {
|
|||||||
GXInitTexObj(&mTexObj_l_J_Ohana01_64128_0419TEX, l_J_Ohana01_64128_0419TEX,
|
GXInitTexObj(&mTexObj_l_J_Ohana01_64128_0419TEX, l_J_Ohana01_64128_0419TEX,
|
||||||
l_J_Ohana01_64128_0419TEX__width + 1, l_J_Ohana01_64128_0419TEX__height + 1, GX_TF_CMPR, GX_MIRROR, GX_MIRROR, GX_FALSE
|
l_J_Ohana01_64128_0419TEX__width + 1, l_J_Ohana01_64128_0419TEX__height + 1, GX_TF_CMPR, GX_MIRROR, GX_MIRROR, GX_FALSE
|
||||||
);
|
);
|
||||||
|
|
||||||
dusk::batch::decode_leaf_template(l_J_hana00DL, 0x140, mTplHana00);
|
|
||||||
dusk::batch::decode_leaf_template(l_J_hana00_cDL, 0xC0, mTplHana00Cut);
|
|
||||||
dusk::batch::decode_leaf_template(l_J_hana01DL, 0x120, mTplHana01);
|
|
||||||
dusk::batch::decode_leaf_template(l_J_hana01_c_00DL, 0xC0, mTplHana01Cut00);
|
|
||||||
dusk::batch::decode_leaf_template(l_J_hana01_c_01DL, 0x120, mTplHana01Cut);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
m_deleteRoom = &dFlower_packet_c::deleteRoom;
|
m_deleteRoom = &dFlower_packet_c::deleteRoom;
|
||||||
@@ -609,371 +597,6 @@ dFlower_packet_c::dFlower_packet_c() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
static void batch_setup_tev(u32 lightMask) {
|
|
||||||
GXSetCullMode(GX_CULL_NONE);
|
|
||||||
|
|
||||||
GXSetNumChans(2);
|
|
||||||
GXSetChanCtrl(GX_COLOR0, GX_FALSE, GX_SRC_REG, GX_SRC_VTX, 0, GX_DF_NONE, GX_AF_NONE);
|
|
||||||
GXSetChanCtrl(GX_COLOR1, GX_TRUE, GX_SRC_VTX, GX_SRC_REG, lightMask, GX_DF_CLAMP, GX_AF_SPOT);
|
|
||||||
|
|
||||||
GXSetNumTevStages(3);
|
|
||||||
|
|
||||||
GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR1A1);
|
|
||||||
GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_RASC);
|
|
||||||
GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
|
|
||||||
GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO);
|
|
||||||
GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
|
|
||||||
|
|
||||||
GXSetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
|
|
||||||
GXSetTevColorIn(GX_TEVSTAGE1, GX_CC_ZERO, GX_CC_CPREV, GX_CC_RASC, GX_CC_ZERO);
|
|
||||||
GXSetTevColorOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
|
|
||||||
GXSetTevAlphaIn(GX_TEVSTAGE1, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO);
|
|
||||||
GXSetTevAlphaOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
|
|
||||||
|
|
||||||
GXSetTevOrder(GX_TEVSTAGE2, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL);
|
|
||||||
GXSetTevColorIn(GX_TEVSTAGE2, GX_CC_ZERO, GX_CC_TEXC, GX_CC_CPREV, GX_CC_C0);
|
|
||||||
GXSetTevColorOp(GX_TEVSTAGE2, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_4, GX_TRUE, GX_TEVPREV);
|
|
||||||
GXSetTevAlphaIn(GX_TEVSTAGE2, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_TEXA);
|
|
||||||
GXSetTevAlphaOp(GX_TEVSTAGE2, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
|
|
||||||
}
|
|
||||||
|
|
||||||
static GXColor hana00_amb_color(const dFlower_data_c* flower, const dKy_tevstr_c* tevstr) {
|
|
||||||
GXColor amb = {0, 0, 0, 0xFF};
|
|
||||||
if (DEBUG && g_kankyoHIO.navy.grass_adjust_ON != 0) {
|
|
||||||
amb.r = g_kankyoHIO.navy.grass_ambcol.r * 2;
|
|
||||||
amb.g = g_kankyoHIO.navy.grass_ambcol.g * 2;
|
|
||||||
amb.b = g_kankyoHIO.navy.grass_ambcol.b * 2;
|
|
||||||
} else {
|
|
||||||
amb.r = (flower->field_0x04 & 0x1F) * 2;
|
|
||||||
amb.g = ((flower->field_0x04 >> 5) & 0x1F) * 2;
|
|
||||||
amb.b = ((flower->field_0x04 >> 0xA) & 0x1F) * 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (daPy_py_c::checkNowWolfPowerUp()) {
|
|
||||||
f32 ambRate = g_env_light.bg_amb_col[0].r / 255.0f;
|
|
||||||
f32 col = (((flower->field_0x04 & 0x1F) * 2 + 0x10));
|
|
||||||
amb.r = col * (ambRate * 4.0f);
|
|
||||||
|
|
||||||
ambRate = g_env_light.bg_amb_col[0].g / 255.0f;
|
|
||||||
f32 col2 = (((flower->field_0x04 >> 5) & 0x1F) * 2 + 0x10);
|
|
||||||
amb.g = col2 * (4.0f * ambRate);
|
|
||||||
|
|
||||||
ambRate = g_env_light.bg_amb_col[0].b / 255.0f;
|
|
||||||
f32 col3 = (((flower->field_0x04 >> 10) & 0x1F) * 2 + 0x10);
|
|
||||||
amb.b = col3 * (4.0f * ambRate);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (amb.r == 0x3E) {
|
|
||||||
amb.r = tevstr->AmbCol.r;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (amb.g == 0x3E) {
|
|
||||||
amb.g = tevstr->AmbCol.g;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (amb.b == 0x3E) {
|
|
||||||
amb.b = tevstr->AmbCol.b;
|
|
||||||
}
|
|
||||||
|
|
||||||
return amb;
|
|
||||||
}
|
|
||||||
|
|
||||||
static GXColor hana01_amb_color(int idx, const dKy_tevstr_c* tevstr) {
|
|
||||||
f32 rRate = tevstr->AmbCol.r * 0.03125f;
|
|
||||||
if (rRate > 1.0f) {
|
|
||||||
rRate = 1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
f32 gRate = tevstr->AmbCol.g * 0.03125f;
|
|
||||||
if (gRate > 1.0f) {
|
|
||||||
gRate = 1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
f32 bRate = tevstr->AmbCol.b * 0.03125f;
|
|
||||||
if (bRate > 1.0f) {
|
|
||||||
bRate = 1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
GXColor amb = {1, 1, 1, 1};
|
|
||||||
|
|
||||||
GXColor sub;
|
|
||||||
sub.r = -0.4f * tevstr->AmbCol.r * rRate;
|
|
||||||
sub.g = -0.4f * tevstr->AmbCol.g * gRate;
|
|
||||||
sub.b = -0.4f * tevstr->AmbCol.b * bRate;
|
|
||||||
|
|
||||||
switch (idx & 7) {
|
|
||||||
case 0:
|
|
||||||
amb.r = tevstr->AmbCol.r + sub.r;
|
|
||||||
amb.g = tevstr->AmbCol.g;
|
|
||||||
amb.b = tevstr->AmbCol.b;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
amb.r = tevstr->AmbCol.r;
|
|
||||||
amb.g = tevstr->AmbCol.g + sub.g;
|
|
||||||
amb.b = tevstr->AmbCol.b;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
amb.r = tevstr->AmbCol.r;
|
|
||||||
amb.g = tevstr->AmbCol.g;
|
|
||||||
amb.b = tevstr->AmbCol.b + sub.b;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
amb.r = tevstr->AmbCol.r + sub.r;
|
|
||||||
amb.g = tevstr->AmbCol.g + sub.g;
|
|
||||||
amb.b = tevstr->AmbCol.b;
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
amb.r = tevstr->AmbCol.r;
|
|
||||||
amb.g = tevstr->AmbCol.g + sub.g;
|
|
||||||
amb.b = tevstr->AmbCol.b + sub.b;
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
amb.r = tevstr->AmbCol.r + sub.r;
|
|
||||||
amb.g = tevstr->AmbCol.g;
|
|
||||||
amb.b = tevstr->AmbCol.b + sub.b;
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
amb.r = tevstr->AmbCol.r + sub.r;
|
|
||||||
amb.g = tevstr->AmbCol.g + sub.g;
|
|
||||||
amb.b = tevstr->AmbCol.b + sub.b;
|
|
||||||
break;
|
|
||||||
case 7:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (daPy_py_c::checkNowWolfPowerUp()) {
|
|
||||||
f32 ambRate = g_env_light.bg_amb_col[0].r / 255.0f;
|
|
||||||
amb.r = (amb.r + 8) * (6.0f * ambRate);
|
|
||||||
|
|
||||||
ambRate = g_env_light.bg_amb_col[0].g / 255.0f;
|
|
||||||
amb.g = (amb.g + 8) * (6.0f * ambRate);
|
|
||||||
|
|
||||||
ambRate = g_env_light.bg_amb_col[0].b / 255.0f;
|
|
||||||
amb.b = (amb.b + 8) * (6.0f * ambRate);
|
|
||||||
}
|
|
||||||
|
|
||||||
amb.a = 0xFF;
|
|
||||||
return amb;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void flower_emit(const dusk::batch::LeafTemplate& tpl, const Vec* xformedPos, GXColor amb) {
|
|
||||||
for (u32 i = 0; i < tpl.vtxCount; i++) {
|
|
||||||
const dusk::batch::LeafTemplate::Vtx& v = tpl.vtx[i];
|
|
||||||
const Vec& p = xformedPos[v.pos];
|
|
||||||
GXPosition3f32(p.x, p.y, p.z);
|
|
||||||
GXNormal1x8(v.nrm);
|
|
||||||
GXColor1x8(v.clr);
|
|
||||||
GXColor4u8(amb.r, amb.g, amb.b, amb.a);
|
|
||||||
GXTexCoord1x8(v.tex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void dFlower_packet_c::draw() {
|
|
||||||
ZoneScoped;
|
|
||||||
dScnKy_env_light_c* kankyo = dKy_getEnvlight();
|
|
||||||
j3dSys.reinitGX();
|
|
||||||
|
|
||||||
GXSetNumIndStages(0);
|
|
||||||
dKy_setLight_again();
|
|
||||||
GXClearVtxDesc();
|
|
||||||
GXSetVtxDesc(GX_VA_POS, GX_INDEX8);
|
|
||||||
GXSetVtxDesc(GX_VA_NRM, GX_INDEX8);
|
|
||||||
GXSetVtxDesc(GX_VA_CLR0, GX_INDEX8);
|
|
||||||
GXSetVtxDesc(GX_VA_TEX0, GX_INDEX8);
|
|
||||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
|
|
||||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0);
|
|
||||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
|
|
||||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
|
|
||||||
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
|
|
||||||
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0);
|
|
||||||
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
|
|
||||||
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_CLR1, GX_CLR_RGBA, GX_RGBA8, 0);
|
|
||||||
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
|
|
||||||
GXSETARRAY(GX_VA_POS, &l_flowerPos, sizeof(l_flowerPos), sizeof(Vec), true);
|
|
||||||
GXSETARRAY(GX_VA_NRM, &l_flowerNormal, sizeof(l_flowerNormal), sizeof(Vec), true);
|
|
||||||
GXSETARRAY(GX_VA_CLR0, &l_flowerColor, sizeof(l_flowerColor), sizeof(GXColor), true);
|
|
||||||
GXSETARRAY(GX_VA_TEX0, &l_flowerTexCoord, sizeof(l_flowerTexCoord), 8, true);
|
|
||||||
|
|
||||||
static GXVtxDescList vtxDescList[] = {
|
|
||||||
{GX_VA_POS, GX_DIRECT},
|
|
||||||
{GX_VA_NRM, GX_INDEX8},
|
|
||||||
{GX_VA_CLR0, GX_INDEX8},
|
|
||||||
{GX_VA_CLR1, GX_DIRECT},
|
|
||||||
{GX_VA_TEX0, GX_INDEX8},
|
|
||||||
{GX_VA_NULL, GX_NONE},
|
|
||||||
};
|
|
||||||
static Vec xfPos[256];
|
|
||||||
Mtx identity;
|
|
||||||
MTXIdentity(identity);
|
|
||||||
|
|
||||||
// --- hana00 ---
|
|
||||||
for (int i = 0; i < 64; i++) {
|
|
||||||
dFlower_data_c* first = m_room[i].getData();
|
|
||||||
if (first == nullptr || !dComIfGp_roomControl_checkStatusFlag(i, 0x10)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
dKy_tevstr_c* tevstr = dComIfGp_roomControl_getTevStr(i);
|
|
||||||
int lightCount = 6;
|
|
||||||
|
|
||||||
if (dComIfGp_roomControl_getStatusRoomDt(i) != nullptr) {
|
|
||||||
lightCount = dComIfGp_roomControl_getStatusRoomDt(i)->getLightVecInfoNum();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dKy_SunMoon_Light_Check() && lightCount < 2) {
|
|
||||||
lightCount = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int j = 0; j < 6; j++) {
|
|
||||||
if (kankyo->field_0x0c18[j].field_0x26 == 1) {
|
|
||||||
lightCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lightCount <= 2) {
|
|
||||||
GXCallDisplayList(l_matLight4DL, 0x80);
|
|
||||||
} else {
|
|
||||||
GXCallDisplayList(l_matDL, 0x80);
|
|
||||||
}
|
|
||||||
|
|
||||||
GXSetTevColorS10(GX_TEVREG0, {0, 0, 0, 0});
|
|
||||||
dKy_Global_amb_set(tevstr);
|
|
||||||
dKy_GxFog_tevstr_set(tevstr);
|
|
||||||
dKy_setLight_nowroom_grass(tevstr->room_no, 1.0f);
|
|
||||||
|
|
||||||
GXLoadTexObj(&mTexObj_l_J_Ohana00_64TEX, GX_TEXMAP0);
|
|
||||||
batch_setup_tev(lightCount <= 2 ? (GX_LIGHT1 | GX_LIGHT2 | GX_LIGHT3 | GX_LIGHT4) :
|
|
||||||
(GX_LIGHT1 | GX_LIGHT2 | GX_LIGHT3 | GX_LIGHT4 |
|
|
||||||
GX_LIGHT5 | GX_LIGHT6 | GX_LIGHT7));
|
|
||||||
GXSetVtxDescv(vtxDescList);
|
|
||||||
GXLoadPosMtxImm(identity, GX_PNMTX0);
|
|
||||||
GXLoadNrmMtxImm(j3dSys.getViewMtx(), 0);
|
|
||||||
|
|
||||||
for (int bucket = 0; bucket < 2; bucket++) {
|
|
||||||
const bool cut = bucket != 0;
|
|
||||||
const dusk::batch::LeafTemplate& tpl = cut ? mTplHana00Cut : mTplHana00;
|
|
||||||
|
|
||||||
bool open = false;
|
|
||||||
u32 emitted = 0;
|
|
||||||
for (dFlower_data_c* flower = first; flower != nullptr; flower = flower->mp_next) {
|
|
||||||
if (cLib_checkBit<u8>(flower->m_state, 4) ||
|
|
||||||
cLib_checkBit<u8>(flower->m_state, 0x40))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if ((cLib_checkBit<u8>(flower->m_state, 8) != 0) != cut) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!open) {
|
|
||||||
GXBegin(GX_TRIANGLES, GX_VTXFMT1, GX_AUTO);
|
|
||||||
open = true;
|
|
||||||
}
|
|
||||||
split_batch(emitted, tpl.vtxCount);
|
|
||||||
|
|
||||||
Mtx interpMtx;
|
|
||||||
MtxP mtx = get_model_mtx(flower->m_modelMtx, interpMtx);
|
|
||||||
transform_positions(tpl, reinterpret_cast<Vec*>(l_flowerPos), mtx, xfPos);
|
|
||||||
flower_emit(tpl, xfPos, hana00_amb_color(flower, tevstr));
|
|
||||||
}
|
|
||||||
if (open) {
|
|
||||||
GXEnd();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- hana01 ---
|
|
||||||
GXSETARRAY(GX_VA_POS, mp_pos, sizeof(l_flowerPos2), sizeof(Vec), true);
|
|
||||||
GXSETARRAY(GX_VA_NRM, &l_flowerNormal2, sizeof(l_flowerNormal2), sizeof(Vec), true);
|
|
||||||
GXSETARRAY(GX_VA_CLR0, mp_colors, sizeof(l_flowerColor2), sizeof(GXColor), true);
|
|
||||||
GXSETARRAY(GX_VA_TEX0, mp_texCoords, sizeof(l_flowerTexCoord2), 8, true);
|
|
||||||
|
|
||||||
for (int i = 0; i < 64; i++) {
|
|
||||||
dFlower_data_c* first = m_room[i].getData();
|
|
||||||
if (first == NULL) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
dKy_tevstr_c* tevstr = dComIfGp_roomControl_getTevStr(i);
|
|
||||||
int lightCount = 6;
|
|
||||||
|
|
||||||
if (dComIfGp_roomControl_getStatusRoomDt(i) != NULL) {
|
|
||||||
lightCount = dComIfGp_roomControl_getStatusRoomDt(i)->getLightVecInfoNum();
|
|
||||||
}
|
|
||||||
|
|
||||||
#if DEBUG
|
|
||||||
if (g_kankyoHIO.light.m_HOSTIO_setting != 0) {
|
|
||||||
lightCount = g_kankyoHIO.dungeonLight.usedLights;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (dKy_SunMoon_Light_Check() == TRUE && lightCount < 2) {
|
|
||||||
lightCount = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lightCount <= 2) {
|
|
||||||
GXCallDisplayList(mp_mat2Light4DL, m_mat2Light4DL_size);
|
|
||||||
} else {
|
|
||||||
GXCallDisplayList(mp_mat2DL, m_mat2DL_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
GXSetTevColorS10(GX_TEVREG0, {0, 0, 0, 0});
|
|
||||||
dKy_Global_amb_set(tevstr);
|
|
||||||
dKy_GxFog_tevstr_set(tevstr);
|
|
||||||
dKy_setLight_nowroom_grass(tevstr->room_no, 1.0f);
|
|
||||||
|
|
||||||
GXLoadTexObj(&mTexObj_l_J_Ohana01_64128_0419TEX, GX_TEXMAP0);
|
|
||||||
batch_setup_tev(lightCount <= 2 ? (GX_LIGHT1 | GX_LIGHT2 | GX_LIGHT3 | GX_LIGHT4) :
|
|
||||||
(GX_LIGHT1 | GX_LIGHT2 | GX_LIGHT3 | GX_LIGHT4 |
|
|
||||||
GX_LIGHT5 | GX_LIGHT6 | GX_LIGHT7));
|
|
||||||
GXSetVtxDescv(vtxDescList);
|
|
||||||
GXLoadPosMtxImm(identity, GX_PNMTX0);
|
|
||||||
GXLoadNrmMtxImm(j3dSys.getViewMtx(), 0);
|
|
||||||
|
|
||||||
const dusk::batch::LeafTemplate* const buckets[3] = {
|
|
||||||
&mTplHana01, &mTplHana01Cut00, &mTplHana01Cut};
|
|
||||||
for (int bucket = 0; bucket < 3; bucket++) {
|
|
||||||
const dusk::batch::LeafTemplate& tpl = *buckets[bucket];
|
|
||||||
|
|
||||||
bool open = false;
|
|
||||||
u32 emitted = 0;
|
|
||||||
int idx = 0;
|
|
||||||
for (dFlower_data_c* flower = first; flower != NULL; flower = flower->mp_next, idx++) {
|
|
||||||
if (cLib_checkBit<u8>(flower->m_state, 4) ||
|
|
||||||
!cLib_checkBit<u8>(flower->m_state, 0x40))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const int flowerBucket = cLib_checkBit<u8>(flower->m_state, 8) ? 2 :
|
|
||||||
cLib_checkBit<u8>(flower->m_state, 0x10) ? 1 :
|
|
||||||
0;
|
|
||||||
if (flowerBucket != bucket) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!open) {
|
|
||||||
GXBegin(GX_TRIANGLES, GX_VTXFMT1, GX_AUTO);
|
|
||||||
open = true;
|
|
||||||
}
|
|
||||||
split_batch(emitted, tpl.vtxCount);
|
|
||||||
|
|
||||||
Mtx interpMtx;
|
|
||||||
MtxP mtx = get_model_mtx(flower->m_modelMtx, interpMtx);
|
|
||||||
transform_positions(tpl, mp_pos, mtx, xfPos);
|
|
||||||
flower_emit(tpl, xfPos, hana01_amb_color(idx, tevstr));
|
|
||||||
}
|
|
||||||
if (open) {
|
|
||||||
GXEnd();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GXSetNumTevStages(1);
|
|
||||||
GXSetNumChans(1);
|
|
||||||
J3DShape::resetVcdVatCache();
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
void dFlower_packet_c::draw() {
|
void dFlower_packet_c::draw() {
|
||||||
ZoneScoped;
|
ZoneScoped;
|
||||||
dScnKy_env_light_c* kankyo = dKy_getEnvlight();
|
dScnKy_env_light_c* kankyo = dKy_getEnvlight();
|
||||||
@@ -1263,7 +886,6 @@ void dFlower_packet_c::draw() {
|
|||||||
|
|
||||||
J3DShape::resetVcdVatCache();
|
J3DShape::resetVcdVatCache();
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
void dFlower_packet_c::calc() {
|
void dFlower_packet_c::calc() {
|
||||||
dFlower_anm_c* anm_p = getAnm();
|
dFlower_anm_c* anm_p = getAnm();
|
||||||
|
|||||||
@@ -512,366 +512,11 @@ dGrass_packet_c::dGrass_packet_c() {
|
|||||||
m_Mkusa_9q_cDL_size = 0xC0;
|
m_Mkusa_9q_cDL_size = 0xC0;
|
||||||
field_0x1d714 = 0;
|
field_0x1d714 = 0;
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
dusk::batch::decode_leaf_template(mp_Mkusa_9q_DL, m_Mkusa_9q_DL_size, mTplKusa9q);
|
|
||||||
dusk::batch::decode_leaf_template(mp_Mkusa_9q_cDL, m_Mkusa_9q_cDL_size, mTplKusa9qCut);
|
|
||||||
dusk::batch::decode_leaf_template(l_M_TenGusaDL, 0xC0, mTplTengusa);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
OS_REPORT("草群メモリ=%fK\n", 117.7734375f);
|
OS_REPORT("草群メモリ=%fK\n", 117.7734375f);
|
||||||
|
|
||||||
m_deleteRoom = &dGrass_packet_c::deleteRoom;
|
m_deleteRoom = &dGrass_packet_c::deleteRoom;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
static MtxP get_model_mtx(Mtx modelMtx, Mtx storage) {
|
|
||||||
if (dusk::frame_interp::lookup_replacement(modelMtx, storage)) {
|
|
||||||
cMtx_concat(j3dSys.getViewMtx(), storage, storage);
|
|
||||||
return storage;
|
|
||||||
}
|
|
||||||
return modelMtx;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void transform_positions(
|
|
||||||
const dusk::batch::LeafTemplate& tpl, const Vec* posArray, const Mtx mtx, Vec* xfPos) {
|
|
||||||
for (u32 i = 0; i < tpl.posRefCount; i++) {
|
|
||||||
const u8 idx = tpl.posRefs[i];
|
|
||||||
MTXMultVec(mtx, &posArray[idx], &xfPos[idx]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void split_batch(u32& emitted, u32 vtxCount) {
|
|
||||||
if (emitted + vtxCount > 0xFFFF) {
|
|
||||||
GXEnd();
|
|
||||||
GXBegin(GX_TRIANGLES, GX_VTXFMT1, GX_AUTO);
|
|
||||||
emitted = 0;
|
|
||||||
}
|
|
||||||
emitted += vtxCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
static GXColor blade_amb_color(const dGrass_data_c* blade, const dKy_tevstr_c* tevstr) {
|
|
||||||
GXColor amb;
|
|
||||||
amb.a = 0;
|
|
||||||
|
|
||||||
#if DEBUG
|
|
||||||
if (g_kankyoHIO.navy.grass_adjust_ON) {
|
|
||||||
amb.r = g_kankyoHIO.navy.grass_ambcol.r * 2;
|
|
||||||
amb.g = g_kankyoHIO.navy.grass_ambcol.g * 2;
|
|
||||||
amb.b = g_kankyoHIO.navy.grass_ambcol.b * 2;
|
|
||||||
return amb;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
amb.r = (blade->m_addCol & 0x1F) * 2;
|
|
||||||
amb.g = ((blade->m_addCol >> 5) & 0x1F) * 2;
|
|
||||||
amb.b = ((blade->m_addCol >> 0xA) & 0x1F) * 2;
|
|
||||||
|
|
||||||
if (daPy_py_c::checkNowWolfPowerUp()) {
|
|
||||||
f32 ambRate = g_env_light.bg_amb_col[0].r / 255.0f;
|
|
||||||
f32 col = (((blade->m_addCol & 0x1F) * 2 + 0x10));
|
|
||||||
amb.r = col * (ambRate * 4.0f);
|
|
||||||
|
|
||||||
ambRate = g_env_light.bg_amb_col[0].g / 255.0f;
|
|
||||||
f32 col2 = (((blade->m_addCol >> 5) & 0x1F) * 2 + 0x10);
|
|
||||||
amb.g = col2 * (4.0f * ambRate);
|
|
||||||
|
|
||||||
ambRate = g_env_light.bg_amb_col[0].b / 255.0f;
|
|
||||||
f32 col3 = (((blade->m_addCol >> 10) & 0x1F) * 2 + 0x10);
|
|
||||||
amb.b = col3 * (4.0f * ambRate);
|
|
||||||
}
|
|
||||||
|
|
||||||
f32 roomAmbScale = 1.0f - (static_cast<int>(blade->m_pos.x) & 0xFF) * 0.001953125f;
|
|
||||||
f32 colScale = 1.1f - (static_cast<u8>(static_cast<int>(blade->m_pos.x)) & 0xFF) / 2000.0f;
|
|
||||||
colScale -= (static_cast<int>(blade->m_pos.z) & 0xFF) / 2000.0f;
|
|
||||||
|
|
||||||
if (colScale > 1.0f) {
|
|
||||||
colScale = 1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (amb.r == 0x3E) {
|
|
||||||
amb.r = tevstr->AmbCol.r * roomAmbScale;
|
|
||||||
} else {
|
|
||||||
amb.r = amb.r * colScale;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (amb.g == 0x3E) {
|
|
||||||
amb.g = tevstr->AmbCol.g * roomAmbScale;
|
|
||||||
} else {
|
|
||||||
amb.g = amb.g * colScale;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (amb.b == 0x3E) {
|
|
||||||
amb.b = tevstr->AmbCol.b * roomAmbScale;
|
|
||||||
} else {
|
|
||||||
amb.b = amb.b * colScale;
|
|
||||||
}
|
|
||||||
|
|
||||||
return amb;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void blade_emit(const dusk::batch::LeafTemplate& tpl, const Vec* xformedPos,
|
|
||||||
const GXColor* colors, GXColor amb) {
|
|
||||||
for (u32 i = 0; i < tpl.vtxCount; i++) {
|
|
||||||
const dusk::batch::LeafTemplate::Vtx& v = tpl.vtx[i];
|
|
||||||
const Vec& p = xformedPos[v.pos];
|
|
||||||
GXPosition3f32(p.x, p.y, p.z);
|
|
||||||
GXNormal1x8(v.nrm);
|
|
||||||
GXColor4u8(amb.r, amb.g, amb.b, colors[v.clr].a);
|
|
||||||
GXTexCoord1x8(v.tex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void dGrass_packet_c::draw() {
|
|
||||||
ZoneScoped;
|
|
||||||
dScnKy_env_light_c* kankyo = dKy_getEnvlight();
|
|
||||||
|
|
||||||
j3dSys.reinitGX();
|
|
||||||
GXSetNumIndStages(0);
|
|
||||||
dKy_setLight_again();
|
|
||||||
GXClearVtxDesc();
|
|
||||||
|
|
||||||
static GXVtxDescList l_vtxDescList[] = {
|
|
||||||
{GX_VA_POS, GX_INDEX8},
|
|
||||||
{GX_VA_NRM, GX_INDEX8},
|
|
||||||
{GX_VA_CLR0, GX_INDEX8},
|
|
||||||
{GX_VA_TEX0, GX_INDEX8},
|
|
||||||
{GX_VA_NULL, GX_NONE},
|
|
||||||
};
|
|
||||||
|
|
||||||
static GXVtxDescList l_batchVtxDescList[] = {
|
|
||||||
{GX_VA_POS, GX_DIRECT},
|
|
||||||
{GX_VA_NRM, GX_INDEX8},
|
|
||||||
{GX_VA_CLR0, GX_DIRECT},
|
|
||||||
{GX_VA_TEX0, GX_INDEX8},
|
|
||||||
{GX_VA_NULL, GX_NONE},
|
|
||||||
};
|
|
||||||
|
|
||||||
GXSetVtxDescv(l_vtxDescList);
|
|
||||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
|
|
||||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0);
|
|
||||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
|
|
||||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
|
|
||||||
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
|
|
||||||
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0);
|
|
||||||
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
|
|
||||||
GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
|
|
||||||
GXSETARRAY(GX_VA_POS, mp_pos, sizeof(l_pos), sizeof(Vec), true);
|
|
||||||
GXSETARRAY(GX_VA_NRM, mp_normal, sizeof(l_normal), sizeof(Vec), true);
|
|
||||||
GXSETARRAY(GX_VA_CLR0, mp_colors, sizeof(l_color), sizeof(GXColor), true);
|
|
||||||
GXSETARRAY(GX_VA_TEX0, mp_texCoords, sizeof(l_texCoord), 8, true);
|
|
||||||
|
|
||||||
GXColorS10 reg1 = {0, 0, 0, 0};
|
|
||||||
|
|
||||||
// daytime "shine" alpha curve (TEVREG1 alpha)
|
|
||||||
f32 daytime = g_env_light.getDaytime();
|
|
||||||
f32 ratio;
|
|
||||||
f32 shine;
|
|
||||||
if (daytime >= 90.0f && daytime < 135.0f) {
|
|
||||||
ratio = 1.0f - (0.022222223f * (135.0f - daytime));
|
|
||||||
shine = 100.0f - (18.0f * ratio);
|
|
||||||
} else if (daytime >= 135.0f && daytime < 225.0f) {
|
|
||||||
ratio = 1.0f - (0.011111111f * (225.0f - daytime));
|
|
||||||
shine = 82.0f - (25.0f * ratio);
|
|
||||||
} else if (daytime >= 225.0f && daytime < 270.0f) {
|
|
||||||
ratio = 1.0f - (0.022222223f * (270.0f - daytime));
|
|
||||||
shine = 57.0f - (-25.0f * ratio);
|
|
||||||
} else if (daytime >= 270.0f && daytime < 315.0f) {
|
|
||||||
ratio = (1.0f - (0.022222223f * (315.0f - daytime)));
|
|
||||||
shine = 82.0f - (-18.0f * ratio);
|
|
||||||
} else {
|
|
||||||
shine = 100.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if DEBUG
|
|
||||||
if (g_kankyoHIO.navy.grass_shine_value != 0.0f) {
|
|
||||||
shine = g_kankyoHIO.navy.grass_shine_value;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static Vec xfPos[256];
|
|
||||||
Mtx identity;
|
|
||||||
PSMTXIdentity(identity);
|
|
||||||
|
|
||||||
for (int i = 0; i < 64; i++) {
|
|
||||||
dGrass_data_c* first = m_room[i].getData();
|
|
||||||
if (first == NULL || !dComIfGp_roomControl_checkStatusFlag(i, 0x10)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
int lightCount = 6;
|
|
||||||
dKy_tevstr_c* tevstr = dComIfGp_roomControl_getTevStr(i);
|
|
||||||
|
|
||||||
f32 lightInf = g_env_light.grass_light_inf_rate * g_env_light.bg_light_influence;
|
|
||||||
lightInf += 0.5f * (1.0f - lightInf);
|
|
||||||
|
|
||||||
J3DLightInfo* lightInfo = tevstr->mLights[0].getLightInfo();
|
|
||||||
reg1.r = lightInfo->mColor.r * lightInf;
|
|
||||||
reg1.g = lightInfo->mColor.g * lightInf;
|
|
||||||
reg1.b = lightInfo->mColor.b * lightInf;
|
|
||||||
reg1.a = shine;
|
|
||||||
if (memcmp(dComIfGp_getStartStageName(), "D_MN01", 6) == 0) {
|
|
||||||
reg1.r = 0;
|
|
||||||
reg1.g = 0x1E;
|
|
||||||
reg1.b = 5;
|
|
||||||
reg1.a = 0x50;
|
|
||||||
}
|
|
||||||
GFSetTevColorS10(GX_TEVREG1, reg1);
|
|
||||||
|
|
||||||
if (dComIfGp_roomControl_getStatusRoomDt(i) != nullptr) {
|
|
||||||
lightCount = dComIfGp_roomControl_getStatusRoomDt(i)->getLightVecInfoNum();
|
|
||||||
}
|
|
||||||
|
|
||||||
#if DEBUG
|
|
||||||
if (g_kankyoHIO.light.m_HOSTIO_setting != 0) {
|
|
||||||
lightCount = g_kankyoHIO.dungeonLight.usedLights;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (dKy_SunMoon_Light_Check() == TRUE && lightCount < 2) {
|
|
||||||
lightCount = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int j = 0; j < 6; j++) {
|
|
||||||
if (kankyo->field_0x0c18[j].field_0x26 == 1) {
|
|
||||||
lightCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// room-level setup
|
|
||||||
if (first->field_0x05 <= 3 || first->field_0x05 >= 10) {
|
|
||||||
GXLoadTexObj(&mTexObj_l_M_kusa05_RGBATEX, GX_TEXMAP0);
|
|
||||||
if (lightCount <= 3) {
|
|
||||||
GXCallDisplayList(mp_kusa9q_14_DL, m_kusa9q_DL_14_size);
|
|
||||||
} else {
|
|
||||||
GXCallDisplayList(mp_kusa9q_DL, m_kusa9q_DL_size);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
GXLoadTexObj(&mTexObj_l_M_Hijiki00TEX, GX_TEXMAP0);
|
|
||||||
GXCallDisplayList(l_Tengusa_matDL, 0xA0);
|
|
||||||
}
|
|
||||||
|
|
||||||
GFSetTevColorS10(GX_TEVREG2, {0, 0, 0, 0});
|
|
||||||
|
|
||||||
dKy_Global_amb_set(tevstr);
|
|
||||||
dKy_GfFog_tevstr_set(tevstr);
|
|
||||||
dKy_setLight_nowroom_grass(tevstr->room_no, 0.0f);
|
|
||||||
|
|
||||||
GXSetVtxDescv(l_batchVtxDescList);
|
|
||||||
GXLoadPosMtxImm(identity, GX_PNMTX0);
|
|
||||||
GXLoadNrmMtxImm(j3dSys.getViewMtx(), 0);
|
|
||||||
|
|
||||||
// buckets: (kusa05 vs tengusa) x (standing vs cut)
|
|
||||||
bool hasRegrowing = false;
|
|
||||||
for (int bucket = 0; bucket < 4; bucket++) {
|
|
||||||
const bool kusaTex = bucket < 2;
|
|
||||||
const bool cut = (bucket & 1) != 0;
|
|
||||||
const dusk::batch::LeafTemplate& tpl =
|
|
||||||
cut ? mTplKusa9qCut : (kusaTex ? mTplKusa9q : mTplTengusa);
|
|
||||||
|
|
||||||
bool open = false;
|
|
||||||
u32 emitted = 0;
|
|
||||||
for (dGrass_data_c* blade = first; blade != NULL; blade = blade->mp_next) {
|
|
||||||
if (cLib_checkBit<u8>(blade->field_0x01, 2)) {
|
|
||||||
continue; // clipped
|
|
||||||
}
|
|
||||||
if (blade->field_0x02 < -1) {
|
|
||||||
hasRegrowing = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const bool bladeKusaTex = blade->field_0x05 <= 3 || blade->field_0x05 >= 10;
|
|
||||||
if (bladeKusaTex != kusaTex || (blade->field_0x02 < 0) != cut) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!open) {
|
|
||||||
if (kusaTex) {
|
|
||||||
GXLoadTexObj(&mTexObj_l_M_kusa05_RGBATEX, GX_TEXMAP0);
|
|
||||||
if (lightCount <= 2) {
|
|
||||||
GXCallDisplayList(mp_kusa9q_14_DL, m_kusa9q_DL_14_size);
|
|
||||||
} else {
|
|
||||||
GXCallDisplayList(mp_kusa9q_DL, m_kusa9q_DL_size);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
GXLoadTexObj(&mTexObj_l_M_Hijiki00TEX, GX_TEXMAP0);
|
|
||||||
GXCallDisplayList(l_Tengusa_matDL, 0xA0);
|
|
||||||
}
|
|
||||||
// change amb_src to GX_SRC_VTX
|
|
||||||
const u32 lightMask =
|
|
||||||
(kusaTex && lightCount <= 2)
|
|
||||||
? (GX_LIGHT1 | GX_LIGHT2 | GX_LIGHT3 | GX_LIGHT4)
|
|
||||||
: (GX_LIGHT1 | GX_LIGHT2 | GX_LIGHT3 | GX_LIGHT4 | GX_LIGHT5 |
|
|
||||||
GX_LIGHT6 | GX_LIGHT7);
|
|
||||||
GXSetChanCtrl(GX_COLOR0, GX_TRUE, GX_SRC_VTX, GX_SRC_REG, lightMask,
|
|
||||||
GX_DF_CLAMP, GX_AF_SPOT);
|
|
||||||
reg1.a = cut ? 0 : shine;
|
|
||||||
GFSetTevColorS10(GX_TEVREG1, reg1);
|
|
||||||
GXBegin(GX_TRIANGLES, GX_VTXFMT1, GX_AUTO);
|
|
||||||
open = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
split_batch(emitted, tpl.vtxCount);
|
|
||||||
|
|
||||||
Mtx interpMtx;
|
|
||||||
MtxP mtx = get_model_mtx(blade->m_modelMtx, interpMtx);
|
|
||||||
transform_positions(tpl, mp_pos, mtx, xfPos);
|
|
||||||
blade_emit(tpl, xfPos, mp_colors, blade_amb_color(blade, tevstr));
|
|
||||||
}
|
|
||||||
if (open) {
|
|
||||||
GXEnd();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// regrowing blades have per-blade TEVREG2 alpha
|
|
||||||
// draw them with the original immediate path
|
|
||||||
if (hasRegrowing) {
|
|
||||||
GXSetVtxDescv(l_vtxDescList);
|
|
||||||
for (dGrass_data_c* blade = first; blade != NULL; blade = blade->mp_next) {
|
|
||||||
if (blade->field_0x02 >= -1 || cLib_checkBit<u8>(blade->field_0x01, 2)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const bool kusaTex = blade->field_0x05 <= 3 || blade->field_0x05 >= 10;
|
|
||||||
if (kusaTex) {
|
|
||||||
GXLoadTexObj(&mTexObj_l_M_kusa05_RGBATEX, GX_TEXMAP0);
|
|
||||||
if (lightCount <= 2) {
|
|
||||||
GXCallDisplayList(mp_kusa9q_14_DL, m_kusa9q_DL_14_size);
|
|
||||||
} else {
|
|
||||||
GXCallDisplayList(mp_kusa9q_DL, m_kusa9q_DL_size);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
GXLoadTexObj(&mTexObj_l_M_Hijiki00TEX, GX_TEXMAP0);
|
|
||||||
GXCallDisplayList(l_Tengusa_matDL, 0xA0);
|
|
||||||
}
|
|
||||||
|
|
||||||
reg1.a = 0;
|
|
||||||
GFSetTevColorS10(GX_TEVREG1, reg1);
|
|
||||||
GXSetChanAmbColor(GX_COLOR0A0, blade_amb_color(blade, tevstr));
|
|
||||||
|
|
||||||
Mtx modelMtx;
|
|
||||||
GXLoadPosMtxImm(get_model_mtx(blade->m_modelMtx, modelMtx), GX_PNMTX0);
|
|
||||||
GXLoadNrmMtxImm(j3dSys.getViewMtx(), 0);
|
|
||||||
|
|
||||||
GFSetTevColorS10(GX_TEVREG2,
|
|
||||||
{0, 0, 0, static_cast<s16>(-0x100 - (blade->field_0x02 << 8) / 40)});
|
|
||||||
|
|
||||||
if (blade->field_0x02 != -2) {
|
|
||||||
if (kusaTex) {
|
|
||||||
GXCallDisplayList(mp_Mkusa_9q_DL, m_Mkusa_9q_DL_size);
|
|
||||||
} else {
|
|
||||||
GXCallDisplayList(l_M_TenGusaDL, 0xC0);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
GXCallDisplayList(mp_Mkusa_9q_cDL, m_Mkusa_9q_cDL_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
GFSetTevColorS10(GX_TEVREG2, {0, 0, 0, 0});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
J3DShape::resetVcdVatCache();
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
void dGrass_packet_c::draw() {
|
void dGrass_packet_c::draw() {
|
||||||
ZoneScoped;
|
ZoneScoped;
|
||||||
dScnKy_env_light_c* kankyo = dKy_getEnvlight();
|
dScnKy_env_light_c* kankyo = dKy_getEnvlight();
|
||||||
@@ -1166,7 +811,6 @@ void dGrass_packet_c::draw() {
|
|||||||
|
|
||||||
J3DShape::resetVcdVatCache();
|
J3DShape::resetVcdVatCache();
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
void dGrass_packet_c::calc() {
|
void dGrass_packet_c::calc() {
|
||||||
cXyz* temp_r29 = dKyw_get_wind_vec();
|
cXyz* temp_r29 = dKyw_get_wind_vec();
|
||||||
|
|||||||
+7
-42
@@ -34,7 +34,6 @@
|
|||||||
#include "dusk/action_bindings.h"
|
#include "dusk/action_bindings.h"
|
||||||
#include "dusk/mouse.h"
|
#include "dusk/mouse.h"
|
||||||
#include "dusk/settings.h"
|
#include "dusk/settings.h"
|
||||||
#include "dusk/touch_camera.h"
|
|
||||||
#include "imgui.h"
|
#include "imgui.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -7500,15 +7499,6 @@ static constexpr s16 FLYCAM_ROLL_SPEED = 256;
|
|||||||
static ImVec2 sFlyCamLastMousePos = {-1.f, -1.f};
|
static ImVec2 sFlyCamLastMousePos = {-1.f, -1.f};
|
||||||
|
|
||||||
#if TARGET_PC
|
#if TARGET_PC
|
||||||
static constexpr f32 TOUCH_CAMERA_CSTICK_EXIT_THRESHOLD = 0.05f;
|
|
||||||
static bool sTouchFreeCameraActive = false;
|
|
||||||
|
|
||||||
bool dCamera_c::isAimActive() {
|
|
||||||
auto* link = daAlink_getAlinkActorClass();
|
|
||||||
return link != nullptr && link->checkAimInputContext() &&
|
|
||||||
dComIfGp_checkCameraAttentionStatus(link->field_0x317c, 0x10);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool dCamera_c::executeDebugFlyCam() {
|
bool dCamera_c::executeDebugFlyCam() {
|
||||||
if (!dusk::getSettings().game.debugFlyCam) {
|
if (!dusk::getSettings().game.debugFlyCam) {
|
||||||
if (mDebugFlyCam.initialized) {
|
if (mDebugFlyCam.initialized) {
|
||||||
@@ -7650,30 +7640,16 @@ void dCamera_c::deactivateDebugFlyCam() {
|
|||||||
mDebugFlyCam.initialized = false;
|
mDebugFlyCam.initialized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool dCamera_c::freeCamera() {
|
bool dCamera_c::canUseFreeCam() {
|
||||||
f32 touchYawDp = 0.0f;
|
return dusk::getSettings().game.freeCamera || dusk::getSettings().game.enableMouseCamera;
|
||||||
f32 touchPitchDp = 0.0f;
|
}
|
||||||
bool touchCameraMoved = false;
|
|
||||||
const bool touchControlsEnabled = dusk::getSettings().game.enableTouchControls;
|
|
||||||
if (touchControlsEnabled && !isAimActive()) {
|
|
||||||
touchCameraMoved = dusk::touch_camera::consume_delta(touchYawDp, touchPitchDp);
|
|
||||||
}
|
|
||||||
if (!touchControlsEnabled ||
|
|
||||||
mPadInfo.mCStick.mLastValue > TOUCH_CAMERA_CSTICK_EXIT_THRESHOLD)
|
|
||||||
{
|
|
||||||
sTouchFreeCameraActive = false;
|
|
||||||
}
|
|
||||||
if (touchCameraMoved) {
|
|
||||||
sTouchFreeCameraActive = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const bool useFreeCamera = dusk::getSettings().game.freeCamera ||
|
bool dCamera_c::freeCamera() {
|
||||||
dusk::getSettings().game.enableMouseCamera || sTouchFreeCameraActive;
|
if (canUseFreeCam() && mGear == 1) {
|
||||||
if (useFreeCamera && mGear == 1) {
|
|
||||||
mGear = 0;
|
mGear = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!useFreeCamera || mCamStyle == 70)
|
if (!canUseFreeCam() || mCamStyle == 70)
|
||||||
{
|
{
|
||||||
mCamParam.mManualMode = 0;
|
mCamParam.mManualMode = 0;
|
||||||
return false;
|
return false;
|
||||||
@@ -7684,17 +7660,6 @@ bool dCamera_c::freeCamera() {
|
|||||||
mCamParam.freeYAngle = mViewCache.mDirection.mInclination.Degree();
|
mCamParam.freeYAngle = mViewCache.mDirection.mInclination.Degree();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (touchCameraMoved) {
|
|
||||||
mCamParam.mManualMode = 1;
|
|
||||||
const f32 yawInput = dusk::getSettings().game.invertCameraXAxis ? -touchYawDp : touchYawDp;
|
|
||||||
const f32 pitchInput =
|
|
||||||
touchPitchDp * (dusk::getSettings().game.invertCameraYAxis ? -1.0f : 1.0f);
|
|
||||||
mCamParam.freeXAngle += yawInput * dusk::getSettings().game.touchCameraXSensitivity *
|
|
||||||
dusk::touch_camera::YAW_DEGREES_PER_DP;
|
|
||||||
mCamParam.freeYAngle += pitchInput * dusk::getSettings().game.touchCameraYSensitivity *
|
|
||||||
dusk::touch_camera::PITCH_DEGREES_PER_DP;
|
|
||||||
}
|
|
||||||
|
|
||||||
cXyz camMovement = {mPadInfo.mCStick.mLastPosX, mPadInfo.mCStick.mLastPosY, 0.0f};
|
cXyz camMovement = {mPadInfo.mCStick.mLastPosX, mPadInfo.mCStick.mLastPosY, 0.0f};
|
||||||
f32 magnitude = sqrt(mPadInfo.mCStick.mLastPosX * mPadInfo.mCStick.mLastPosX + mPadInfo.mCStick.mLastPosY * mPadInfo.mCStick.mLastPosY);
|
f32 magnitude = sqrt(mPadInfo.mCStick.mLastPosX * mPadInfo.mCStick.mLastPosX + mPadInfo.mCStick.mLastPosY * mPadInfo.mCStick.mLastPosY);
|
||||||
|
|
||||||
@@ -11394,7 +11359,7 @@ static int camera_execute(camera_process_class* i_this) {
|
|||||||
const auto target = get_target_trim_height(i_this);
|
const auto target = get_target_trim_height(i_this);
|
||||||
const auto step = dusk::frame_interp::get_interpolation_step();
|
const auto step = dusk::frame_interp::get_interpolation_step();
|
||||||
const auto cur = camera->TrimHeight();
|
const auto cur = camera->TrimHeight();
|
||||||
const auto prev = (4.0f * cur - target) / 3.0f;
|
const auto prev = (4.0f * cur - target) / 3.0f;
|
||||||
const auto trim_height = prev + (cur - prev) * step;
|
const auto trim_height = prev + (cur - prev) * step;
|
||||||
|
|
||||||
widezoom_correction(i_this, trim_height);
|
widezoom_correction(i_this, trim_height);
|
||||||
|
|||||||
@@ -23,22 +23,8 @@
|
|||||||
#include "m_Do/m_Do_graphic.h"
|
#include "m_Do/m_Do_graphic.h"
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
#include "dusk/menu_pointer.h"
|
|
||||||
#include "dusk/string.hpp"
|
#include "dusk/string.hpp"
|
||||||
|
|
||||||
namespace {
|
|
||||||
constexpr u8 pointer_target(u8 group, u8 index) noexcept {
|
|
||||||
return static_cast<u8>((group << 4) | (index & 0x0F));
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr u8 s_pointerDataSelectTarget = 0;
|
|
||||||
constexpr u8 s_pointerMenuSelectTarget = 1;
|
|
||||||
constexpr u8 s_pointerCopySelectTarget = 2;
|
|
||||||
constexpr u8 s_pointerYesNoSelectTarget = 3;
|
|
||||||
} // namespace
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static s32 SelStartFrameTbl[3] = {
|
static s32 SelStartFrameTbl[3] = {
|
||||||
59,
|
59,
|
||||||
99,
|
99,
|
||||||
@@ -770,143 +756,8 @@ void dFile_select_c::dataSelectInit() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
bool dFile_select_c::pointerDataSelect() {
|
|
||||||
dusk::menu_pointer::begin_context(dusk::menu_pointer::Context::FileSelect);
|
|
||||||
for (u8 i = 0; i < 3; ++i) {
|
|
||||||
if (!dusk::menu_pointer::hit_pane(mSelFilePanes[i], 8.0f)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const bool clicked = dusk::menu_pointer::consume_click();
|
|
||||||
if (mSelectNum != i) {
|
|
||||||
mDoAud_seStart(Z2SE_FILE_SELECT_CURSOR, NULL, 0, 0);
|
|
||||||
mLastSelectNum = mSelectNum;
|
|
||||||
mSelectNum = i;
|
|
||||||
if (clicked) {
|
|
||||||
dusk::menu_pointer::defer_activation(
|
|
||||||
dusk::menu_pointer::Context::FileSelect,
|
|
||||||
pointer_target(s_pointerDataSelectTarget, i));
|
|
||||||
}
|
|
||||||
dataSelectAnmSet();
|
|
||||||
mDataSelProc = DATASELPROC_DATA_SELECT_MOVE_ANIME;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (clicked) {
|
|
||||||
dataSelectStart();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool dFile_select_c::pointerMenuSelect() {
|
|
||||||
dusk::menu_pointer::begin_context(dusk::menu_pointer::Context::FileSelect);
|
|
||||||
for (u8 i = 0; i < 3; ++i) {
|
|
||||||
if (!dusk::menu_pointer::hit_pane(m3mSelPane[i], 8.0f)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const bool clicked = dusk::menu_pointer::consume_click();
|
|
||||||
if (!mIsDataNew[mSelectNum] && mSelectMenuNum != i) {
|
|
||||||
mDoAud_seStart(Z2SE_SY_MENU_CURSOR_COMMON, NULL, 0, 0);
|
|
||||||
mLastSelectMenuNum = mSelectMenuNum;
|
|
||||||
mSelectMenuNum = i;
|
|
||||||
if (clicked) {
|
|
||||||
dusk::menu_pointer::defer_activation(
|
|
||||||
dusk::menu_pointer::Context::FileSelect,
|
|
||||||
pointer_target(s_pointerMenuSelectTarget, i));
|
|
||||||
}
|
|
||||||
menuSelectAnmSet();
|
|
||||||
mDataSelProc = DATASELPROC_MENU_SELECT_MOVE_ANM;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (clicked) {
|
|
||||||
menuSelectStart();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool dFile_select_c::pointerCopyDataToSelect() {
|
|
||||||
dusk::menu_pointer::begin_context(dusk::menu_pointer::Context::FileSelect);
|
|
||||||
for (u8 i = 0; i < 2; ++i) {
|
|
||||||
if (!dusk::menu_pointer::hit_pane(mCpSelPane[i], 8.0f)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const bool clicked = dusk::menu_pointer::consume_click();
|
|
||||||
if (field_0x026b != i) {
|
|
||||||
mDoAud_seStart(Z2SE_FILE_SELECT_CURSOR, NULL, 0, 0);
|
|
||||||
field_0x026c = field_0x026b;
|
|
||||||
field_0x026b = i;
|
|
||||||
if (clicked) {
|
|
||||||
dusk::menu_pointer::defer_activation(
|
|
||||||
dusk::menu_pointer::Context::FileSelect,
|
|
||||||
pointer_target(s_pointerCopySelectTarget, i));
|
|
||||||
}
|
|
||||||
copyDataToSelectMoveAnmSet();
|
|
||||||
mDataSelProc = DATASELPROC_COPY_DATA_TO_SELECT_MOVE_ANM;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (clicked) {
|
|
||||||
copyDataToSelectStart();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool dFile_select_c::pointerYesNoSelect(bool errorSelect) {
|
|
||||||
dusk::menu_pointer::begin_context(dusk::menu_pointer::Context::FileSelect);
|
|
||||||
for (u8 i = 0; i < 2; ++i) {
|
|
||||||
if (!dusk::menu_pointer::hit_pane(mYnSelPane[i], 8.0f)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const bool clicked =
|
|
||||||
(!errorSelect || field_0x0268 == i) && dusk::menu_pointer::consume_click();
|
|
||||||
if (field_0x0268 != i) {
|
|
||||||
field_0x0269 = field_0x0268;
|
|
||||||
field_0x0268 = i;
|
|
||||||
if (errorSelect) {
|
|
||||||
errCurMove(0);
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
mDoAud_seStart(Z2SE_SY_MENU_CURSOR_COMMON, NULL, 0, 0);
|
|
||||||
if (clicked) {
|
|
||||||
dusk::menu_pointer::defer_activation(
|
|
||||||
dusk::menu_pointer::Context::FileSelect,
|
|
||||||
pointer_target(s_pointerYesNoSelectTarget, i));
|
|
||||||
}
|
|
||||||
yesnoSelectAnmSet();
|
|
||||||
mDataSelProc = DATASELPROC_YES_NO_CURSOR_MOVE_ANM;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (clicked) {
|
|
||||||
if (errorSelect) {
|
|
||||||
if (field_0x0268 != 0) {
|
|
||||||
mDoAud_seStart(Z2SE_SY_CURSOR_OK, 0, 0, 0);
|
|
||||||
} else {
|
|
||||||
mDoAud_seStart(Z2SE_SY_CURSOR_CANCEL, 0, 0, 0);
|
|
||||||
}
|
|
||||||
mSelIcon->setAlphaRate(0.0f);
|
|
||||||
} else {
|
|
||||||
yesNoSelectStart();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// handles switching between quest logs
|
// handles switching between quest logs
|
||||||
void dFile_select_c::dataSelect() {
|
void dFile_select_c::dataSelect() {
|
||||||
#if TARGET_PC
|
|
||||||
if (pointerDataSelect()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
stick->checkTrigger();
|
stick->checkTrigger();
|
||||||
|
|
||||||
// If A or Start was pressed
|
// If A or Start was pressed
|
||||||
@@ -950,9 +801,6 @@ static u16 msgTbl[3] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void dFile_select_c::dataSelectStart() {
|
void dFile_select_c::dataSelectStart() {
|
||||||
#if TARGET_PC
|
|
||||||
dusk::menu_pointer::clear_deferred_activation(dusk::menu_pointer::Context::FileSelect);
|
|
||||||
#endif
|
|
||||||
mSelIcon->setAlphaRate(0.0f);
|
mSelIcon->setAlphaRate(0.0f);
|
||||||
|
|
||||||
if (mIsNoData[mSelectNum]) {
|
if (mIsNoData[mSelectNum]) {
|
||||||
@@ -1101,16 +949,6 @@ void dFile_select_c::dataSelectAnmSet() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void dFile_select_c::dataSelectMoveAnime() {
|
void dFile_select_c::dataSelectMoveAnime() {
|
||||||
#if TARGET_PC
|
|
||||||
dusk::menu_pointer::begin_context(dusk::menu_pointer::Context::FileSelect);
|
|
||||||
if (mSelectNum != 0xFF && dusk::menu_pointer::hit_pane(mSelFilePanes[mSelectNum], 8.0f) &&
|
|
||||||
dusk::menu_pointer::consume_click())
|
|
||||||
{
|
|
||||||
dusk::menu_pointer::defer_activation(
|
|
||||||
dusk::menu_pointer::Context::FileSelect,
|
|
||||||
pointer_target(s_pointerDataSelectTarget, mSelectNum));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
bool iVar7 = true;
|
bool iVar7 = true;
|
||||||
bool iVar6 = true;
|
bool iVar6 = true;
|
||||||
bool bVar1 = true;
|
bool bVar1 = true;
|
||||||
@@ -1159,14 +997,6 @@ void dFile_select_c::dataSelectMoveAnime() {
|
|||||||
mSelFilePanes[mLastSelectNum]->getPanePtr()->setAnimation((J2DAnmTransform*)NULL);
|
mSelFilePanes[mLastSelectNum]->getPanePtr()->setAnimation((J2DAnmTransform*)NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
if (dusk::menu_pointer::consume_deferred_activation(
|
|
||||||
dusk::menu_pointer::Context::FileSelect,
|
|
||||||
pointer_target(s_pointerDataSelectTarget, mSelectNum))) {
|
|
||||||
dataSelectStart();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
mDataSelProc = DATASELPROC_DATA_SELECT;
|
mDataSelProc = DATASELPROC_DATA_SELECT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1331,12 +1161,6 @@ void dFile_select_c::selectDataOpenEraseMove() {
|
|||||||
|
|
||||||
// Handles selecting between copy / start / delete menus in quest log
|
// Handles selecting between copy / start / delete menus in quest log
|
||||||
void dFile_select_c::menuSelect() {
|
void dFile_select_c::menuSelect() {
|
||||||
#if TARGET_PC
|
|
||||||
if (pointerMenuSelect()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
stick->checkTrigger();
|
stick->checkTrigger();
|
||||||
|
|
||||||
// if a was pressed, do the menu selection process
|
// if a was pressed, do the menu selection process
|
||||||
@@ -1367,9 +1191,6 @@ void dFile_select_c::menuSelect() {
|
|||||||
|
|
||||||
// Handles copy / start / delete actions depending on which menu is selected from menuSelect
|
// Handles copy / start / delete actions depending on which menu is selected from menuSelect
|
||||||
void dFile_select_c::menuSelectStart() {
|
void dFile_select_c::menuSelectStart() {
|
||||||
#if TARGET_PC
|
|
||||||
dusk::menu_pointer::clear_deferred_activation(dusk::menu_pointer::Context::FileSelect);
|
|
||||||
#endif
|
|
||||||
#if TARGET_PC
|
#if TARGET_PC
|
||||||
if (!dusk::getSettings().game.hideTvSettingsScreen || mSelectMenuNum != 1) {
|
if (!dusk::getSettings().game.hideTvSettingsScreen || mSelectMenuNum != 1) {
|
||||||
mDoAud_seStart(Z2SE_SY_CURSOR_OK, NULL, 0, 0);
|
mDoAud_seStart(Z2SE_SY_CURSOR_OK, NULL, 0, 0);
|
||||||
@@ -1491,17 +1312,6 @@ void dFile_select_c::menuSelectAnmSet() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void dFile_select_c::menuSelectMoveAnm() {
|
void dFile_select_c::menuSelectMoveAnm() {
|
||||||
#if TARGET_PC
|
|
||||||
dusk::menu_pointer::begin_context(dusk::menu_pointer::Context::FileSelect);
|
|
||||||
if (mSelectMenuNum != 0xFF &&
|
|
||||||
dusk::menu_pointer::hit_pane(m3mSelPane[mSelectMenuNum], 8.0f) &&
|
|
||||||
dusk::menu_pointer::consume_click())
|
|
||||||
{
|
|
||||||
dusk::menu_pointer::defer_activation(
|
|
||||||
dusk::menu_pointer::Context::FileSelect,
|
|
||||||
pointer_target(s_pointerMenuSelectTarget, mSelectMenuNum));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
bool tmp1 = true;
|
bool tmp1 = true;
|
||||||
|
|
||||||
if (mSelectMenuNum != 0xFF &&
|
if (mSelectMenuNum != 0xFF &&
|
||||||
@@ -1559,14 +1369,6 @@ void dFile_select_c::menuSelectMoveAnm() {
|
|||||||
m3mSelPane[mLastSelectMenuNum]->getPanePtr()->setAnimation((J2DAnmTransform*)NULL);
|
m3mSelPane[mLastSelectMenuNum]->getPanePtr()->setAnimation((J2DAnmTransform*)NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
if (dusk::menu_pointer::consume_deferred_activation(
|
|
||||||
dusk::menu_pointer::Context::FileSelect,
|
|
||||||
pointer_target(s_pointerMenuSelectTarget, mSelectMenuNum))) {
|
|
||||||
menuSelectStart();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
mDataSelProc = DATASELPROC_MENU_SELECT;
|
mDataSelProc = DATASELPROC_MENU_SELECT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1896,12 +1698,6 @@ void dFile_select_c::setSaveDataForCopySel() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void dFile_select_c::copyDataToSelect() {
|
void dFile_select_c::copyDataToSelect() {
|
||||||
#if TARGET_PC
|
|
||||||
if (pointerCopyDataToSelect()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
stick->checkTrigger();
|
stick->checkTrigger();
|
||||||
|
|
||||||
if (mDoCPd_c::getTrigA(PAD_1)) {
|
if (mDoCPd_c::getTrigA(PAD_1)) {
|
||||||
@@ -1926,9 +1722,6 @@ void dFile_select_c::copyDataToSelect() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void dFile_select_c::copyDataToSelectStart() {
|
void dFile_select_c::copyDataToSelectStart() {
|
||||||
#if TARGET_PC
|
|
||||||
dusk::menu_pointer::clear_deferred_activation(dusk::menu_pointer::Context::FileSelect);
|
|
||||||
#endif
|
|
||||||
mDoAud_seStart(Z2SE_SY_CURSOR_OK, NULL, 0, 0);
|
mDoAud_seStart(Z2SE_SY_CURSOR_OK, NULL, 0, 0);
|
||||||
|
|
||||||
mCpDataToNum = getCptoNum(field_0x026b);
|
mCpDataToNum = getCptoNum(field_0x026b);
|
||||||
@@ -1994,17 +1787,6 @@ void dFile_select_c::copyDataToSelectMoveAnmSet() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void dFile_select_c::copyDataToSelectMoveAnm() {
|
void dFile_select_c::copyDataToSelectMoveAnm() {
|
||||||
#if TARGET_PC
|
|
||||||
dusk::menu_pointer::begin_context(dusk::menu_pointer::Context::FileSelect);
|
|
||||||
if (field_0x026b != 0xFF &&
|
|
||||||
dusk::menu_pointer::hit_pane(mCpSelPane[field_0x026b], 8.0f) &&
|
|
||||||
dusk::menu_pointer::consume_click())
|
|
||||||
{
|
|
||||||
dusk::menu_pointer::defer_activation(
|
|
||||||
dusk::menu_pointer::Context::FileSelect,
|
|
||||||
pointer_target(s_pointerCopySelectTarget, field_0x026b));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
bool iVar7 = true;
|
bool iVar7 = true;
|
||||||
bool iVar6 = true;
|
bool iVar6 = true;
|
||||||
bool bVar1 = true;
|
bool bVar1 = true;
|
||||||
@@ -2054,14 +1836,6 @@ void dFile_select_c::copyDataToSelectMoveAnm() {
|
|||||||
mSelIcon2->setAlphaRate(1.0f);
|
mSelIcon2->setAlphaRate(1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
if (dusk::menu_pointer::consume_deferred_activation(
|
|
||||||
dusk::menu_pointer::Context::FileSelect,
|
|
||||||
pointer_target(s_pointerCopySelectTarget, field_0x026b))) {
|
|
||||||
copyDataToSelectStart();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
mDataSelProc = DATASELPROC_COPY_DATA_TO_SELECT;
|
mDataSelProc = DATASELPROC_COPY_DATA_TO_SELECT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2331,12 +2105,6 @@ void dFile_select_c::yesnoCursorShow() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void dFile_select_c::YesNoSelect() {
|
void dFile_select_c::YesNoSelect() {
|
||||||
#if TARGET_PC
|
|
||||||
if (pointerYesNoSelect(false)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
stick->checkTrigger();
|
stick->checkTrigger();
|
||||||
|
|
||||||
if (mDoCPd_c::getTrigA(PAD_1)) {
|
if (mDoCPd_c::getTrigA(PAD_1)) {
|
||||||
@@ -2361,9 +2129,6 @@ void dFile_select_c::YesNoSelect() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void dFile_select_c::yesNoSelectStart() {
|
void dFile_select_c::yesNoSelectStart() {
|
||||||
#if TARGET_PC
|
|
||||||
dusk::menu_pointer::clear_deferred_activation(dusk::menu_pointer::Context::FileSelect);
|
|
||||||
#endif
|
|
||||||
if (field_0x0268 != 0) {
|
if (field_0x0268 != 0) {
|
||||||
mDoAud_seStart(Z2SE_SY_CURSOR_OK, NULL, 0, 0);
|
mDoAud_seStart(Z2SE_SY_CURSOR_OK, NULL, 0, 0);
|
||||||
field_0x03b1 = 1;
|
field_0x03b1 = 1;
|
||||||
@@ -2519,29 +2284,10 @@ void dFile_select_c::YesNoCancelMove() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void dFile_select_c::yesNoCursorMoveAnm() {
|
void dFile_select_c::yesNoCursorMoveAnm() {
|
||||||
#if TARGET_PC
|
|
||||||
dusk::menu_pointer::begin_context(dusk::menu_pointer::Context::FileSelect);
|
|
||||||
if (field_0x0268 != 0xFF &&
|
|
||||||
dusk::menu_pointer::hit_pane(mYnSelPane[field_0x0268], 8.0f) &&
|
|
||||||
dusk::menu_pointer::consume_click())
|
|
||||||
{
|
|
||||||
dusk::menu_pointer::defer_activation(
|
|
||||||
dusk::menu_pointer::Context::FileSelect,
|
|
||||||
pointer_target(s_pointerYesNoSelectTarget, field_0x0268));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
bool isYnSelMove = yesnoSelectMoveAnm();
|
bool isYnSelMove = yesnoSelectMoveAnm();
|
||||||
bool isYnWakuAlpha = yesnoWakuAlpahAnm(field_0x0269);
|
bool isYnWakuAlpha = yesnoWakuAlpahAnm(field_0x0269);
|
||||||
if (isYnSelMove == true && isYnWakuAlpha == true) {
|
if (isYnSelMove == true && isYnWakuAlpha == true) {
|
||||||
yesnoCursorShow();
|
yesnoCursorShow();
|
||||||
#if TARGET_PC
|
|
||||||
if (dusk::menu_pointer::consume_deferred_activation(
|
|
||||||
dusk::menu_pointer::Context::FileSelect,
|
|
||||||
pointer_target(s_pointerYesNoSelectTarget, field_0x0268))) {
|
|
||||||
yesNoSelectStart();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
mDataSelProc = DATASELPROC_YES_NO_SELECT;
|
mDataSelProc = DATASELPROC_YES_NO_SELECT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4492,11 +4238,6 @@ static MemCardCheckFuncT MemCardCheckProc[] = {
|
|||||||
&dFile_select_c::MemCardErrYesNoCursorMoveAnm,
|
&dFile_select_c::MemCardErrYesNoCursorMoveAnm,
|
||||||
&dFile_select_c::MemCardSaveDataClear,
|
&dFile_select_c::MemCardSaveDataClear,
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
&dFile_select_c::MemCardAutoMakeGameFile,
|
|
||||||
&dFile_select_c::MemCardAutoMakeGameFileErrWait,
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if PLATFORM_WII || PLATFORM_SHIELD
|
#if PLATFORM_WII || PLATFORM_SHIELD
|
||||||
&dFile_select_c::nandStatCheck,
|
&dFile_select_c::nandStatCheck,
|
||||||
&dFile_select_c::gameFileInitSel,
|
&dFile_select_c::gameFileInitSel,
|
||||||
@@ -4580,33 +4321,11 @@ void dFile_select_c::MemCardStatCheck() {
|
|||||||
mDoMemCd_Load();
|
mDoMemCd_Load();
|
||||||
mCardCheckProc = MEMCARDCHECKPROC_LOAD_WAIT;
|
mCardCheckProc = MEMCARDCHECKPROC_LOAD_WAIT;
|
||||||
break;
|
break;
|
||||||
#if TARGET_PC
|
|
||||||
case 1: { // no save file
|
|
||||||
if (dusk::getSettings().game.instantSaves) {
|
|
||||||
field_0x03b1 = 1;
|
|
||||||
setInitSaveData();
|
|
||||||
dataSave();
|
|
||||||
mCardCheckProc = MEMCARDCHECKPROC_AUTO_MAKE_GAMEFILE;
|
|
||||||
} else {
|
|
||||||
errDispInitSet(22, 0);
|
|
||||||
field_0x0280 = true;
|
|
||||||
mNextCardCheckProc = MEMCARDCHECKPROC_MAKE_GAMEFILE_SEL;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 4: // card is writing
|
|
||||||
if (dusk::getSettings().game.instantSaves) {
|
|
||||||
field_0x03b1 = 1;
|
|
||||||
mCardCheckProc = MEMCARDCHECKPROC_AUTO_MAKE_GAMEFILE;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
#else
|
|
||||||
case 1:
|
case 1:
|
||||||
errDispInitSet(22, 0);
|
errDispInitSet(22, 0);
|
||||||
field_0x0280 = true;
|
field_0x0280 = true;
|
||||||
mNextCardCheckProc = MEMCARDCHECKPROC_MAKE_GAMEFILE_SEL;
|
mNextCardCheckProc = MEMCARDCHECKPROC_MAKE_GAMEFILE_SEL;
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
switch (status) {
|
switch (status) {
|
||||||
@@ -5312,33 +5031,6 @@ void dFile_select_c::MemCardMakeGameFileCheck() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
void dFile_select_c::MemCardAutoMakeGameFile() {
|
|
||||||
field_0x03b4 = mDoMemCd_SaveSync();
|
|
||||||
if (field_0x03b4 == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
field_0x03b1 = 0;
|
|
||||||
if (field_0x03b4 == 1) {
|
|
||||||
mDoMemCd_Load();
|
|
||||||
mCardCheckProc = MEMCARDCHECKPROC_LOAD_WAIT;
|
|
||||||
} else {
|
|
||||||
errDispInitSet(0x1A, 0);
|
|
||||||
field_0x0280 = false;
|
|
||||||
mWindowCloseMsgDispCb = NULL;
|
|
||||||
mKeyWaitMsgDispCb = NULL;
|
|
||||||
mNextCardCheckProc = MEMCARDCHECKPROC_AUTO_MAKE_GAMEFILE_ERR_WAIT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void dFile_select_c::MemCardAutoMakeGameFileErrWait() {
|
|
||||||
mNextCardCheckProc = MEMCARDCHECKPROC_STAT_CHECK;
|
|
||||||
mKeyWaitCardCheckProc = MEMCARDCHECKPROC_MSG_WINDOW_CLOSE;
|
|
||||||
mCardCheckProc = MEMCARDCHECKPROC_ERRMSG_WAIT_KEY;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if PLATFORM_WII || PLATFORM_SHIELD
|
#if PLATFORM_WII || PLATFORM_SHIELD
|
||||||
void dFile_select_c::gameFileInitSel() {
|
void dFile_select_c::gameFileInitSel() {
|
||||||
if (errYesNoSelect() != 0) {
|
if (errYesNoSelect() != 0) {
|
||||||
@@ -5492,12 +5184,6 @@ void dFile_select_c::MemCardMsgWindowClose() {
|
|||||||
|
|
||||||
bool dFile_select_c::errYesNoSelect() {
|
bool dFile_select_c::errYesNoSelect() {
|
||||||
bool rv = false;
|
bool rv = false;
|
||||||
#if TARGET_PC
|
|
||||||
if (pointerYesNoSelect(true)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
stick->checkTrigger();
|
stick->checkTrigger();
|
||||||
|
|
||||||
if (mDoCPd_c::getTrigA(PAD_1)) {
|
if (mDoCPd_c::getTrigA(PAD_1)) {
|
||||||
|
|||||||
@@ -1213,10 +1213,6 @@ void dMap_c::changeTextureSize(int param_1, int param_2, int param_3) {
|
|||||||
JUT_ASSERT(2672, mImage_p != NULL);
|
JUT_ASSERT(2672, mImage_p != NULL);
|
||||||
JUT_ASSERT(2673, mResTIMG != NULL);
|
JUT_ASSERT(2673, mResTIMG != NULL);
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
GXDestroyCopyTex(mImage_p);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
mTexSizeX = param_1 >> param_3;
|
mTexSizeX = param_1 >> param_3;
|
||||||
mTexSizeY = param_2 >> param_3;
|
mTexSizeY = param_2 >> param_3;
|
||||||
|
|
||||||
@@ -1230,24 +1226,6 @@ void dMap_c::changeTextureSize(int param_1, int param_2, int param_3) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
bool dMap_c::refreshTextureSize() {
|
|
||||||
JUT_ASSERT(2688, mImage_p != NULL);
|
|
||||||
JUT_ASSERT(2689, mResTIMG != NULL);
|
|
||||||
|
|
||||||
const u16 oldWidth = mResTIMG->width;
|
|
||||||
const u16 oldHeight = mResTIMG->height;
|
|
||||||
makeResTIMG(mResTIMG, mTexSizeX, mTexSizeY, mImage_p, (u8*)m_res, 0x33);
|
|
||||||
|
|
||||||
if (mResTIMG->width == oldWidth && mResTIMG->height == oldHeight) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
GXDestroyCopyTex(mImage_p);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void dMap_c::_remove() {
|
void dMap_c::_remove() {
|
||||||
if (mImage_p != NULL) {
|
if (mImage_p != NULL) {
|
||||||
#if TARGET_PC
|
#if TARGET_PC
|
||||||
|
|||||||
+18
-49
@@ -15,51 +15,16 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
#ifdef TARGET_PC
|
#ifdef TARGET_PC
|
||||||
#include "dusk/settings.h"
|
|
||||||
#include "m_Do/m_Do_graphic.h"
|
|
||||||
#include <dolphin/gx/GXAurora.h>
|
|
||||||
#include <aurora/math.hpp>
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <array>
|
|
||||||
#include <cmath>
|
|
||||||
#include <functional>
|
|
||||||
#include <limits>
|
|
||||||
#include <numbers>
|
|
||||||
#include <span>
|
#include <span>
|
||||||
|
#include <numbers>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
constexpr u16 kMapIconResolutionMultiplier = 4;
|
constexpr u16 kMapResolutionMultiplier = 4;
|
||||||
constexpr u16 kMapImageSide = 16 * kMapIconResolutionMultiplier;
|
constexpr u16 kMapImageSide = 16 * kMapResolutionMultiplier;
|
||||||
constexpr u32 kMapImageTotalPixels = kMapImageSide * kMapImageSide;
|
constexpr u32 kMapImageTotalPixels = kMapImageSide * kMapImageSide;
|
||||||
|
|
||||||
typedef std::function<u8(size_t, size_t)> PaintI8Fn;
|
typedef std::function<u8(size_t, size_t)> PaintI8Fn;
|
||||||
|
|
||||||
u16 scaled_map_axis(u16 value, f32 scale) {
|
|
||||||
const auto scaledValue =
|
|
||||||
static_cast<u32>(std::max(1.0f, std::round(static_cast<f32>(value) * scale)));
|
|
||||||
return static_cast<u16>(std::min<u32>(scaledValue, std::numeric_limits<u16>::max()));
|
|
||||||
}
|
|
||||||
|
|
||||||
aurora::Vec2<u16> map_render_size_for(u16 width, u16 height) {
|
|
||||||
if (width == 0 || height == 0) {
|
|
||||||
return {width, height};
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 renderWidth = 0;
|
|
||||||
u32 renderHeight = 0;
|
|
||||||
AuroraGetRenderSize(&renderWidth, &renderHeight);
|
|
||||||
|
|
||||||
const f32 logicalWidth = std::max(mDoGph_gInf_c::getWidthF(), 1.0f);
|
|
||||||
const f32 logicalHeight = std::max(mDoGph_gInf_c::getHeightF(), 1.0f);
|
|
||||||
const f32 irScaleX = renderWidth > 0 ? static_cast<f32>(renderWidth) / logicalWidth : 1.0f;
|
|
||||||
const f32 irScaleY = renderHeight > 0 ? static_cast<f32>(renderHeight) / logicalHeight : 1.0f;
|
|
||||||
const f32 hudScale = std::clamp(dusk::getSettings().game.hudScale.getValue(), 0.5f, 2.0f);
|
|
||||||
return {
|
|
||||||
scaled_map_axis(width, irScaleX * hudScale),
|
|
||||||
scaled_map_axis(height, irScaleY * hudScale),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
void paint_i8(std::span<u8> dst, size_t width, PaintI8Fn paint) {
|
void paint_i8(std::span<u8> dst, size_t width, PaintI8Fn paint) {
|
||||||
const auto blocksAcross = width >> 3;
|
const auto blocksAcross = width >> 3;
|
||||||
|
|
||||||
@@ -513,9 +478,9 @@ void dRenderingMap_c::makeResTIMG(ResTIMG* p_image, u16 width, u16 height, u8* p
|
|||||||
p_image->format = GX_TF_C8;
|
p_image->format = GX_TF_C8;
|
||||||
p_image->alphaEnabled = 2;
|
p_image->alphaEnabled = 2;
|
||||||
#ifdef TARGET_PC
|
#ifdef TARGET_PC
|
||||||
const auto [rw, rh] = map_render_size_for(width, height);
|
// Increase map render resolution
|
||||||
p_image->width = rw;
|
p_image->width = width * kMapResolutionMultiplier;
|
||||||
p_image->height = rh;
|
p_image->height = height * kMapResolutionMultiplier;
|
||||||
#else
|
#else
|
||||||
p_image->width = width;
|
p_image->width = width;
|
||||||
p_image->height = height;
|
p_image->height = height;
|
||||||
@@ -598,14 +563,16 @@ void dRenderingFDAmap_c::drawBack() const {
|
|||||||
|
|
||||||
void dRenderingFDAmap_c::preRenderingMap() {
|
void dRenderingFDAmap_c::preRenderingMap() {
|
||||||
#ifdef TARGET_PC
|
#ifdef TARGET_PC
|
||||||
const auto [rw, rh] = map_render_size_for(mTexWidth, mTexHeight);
|
// Increase map render resolution
|
||||||
GXCreateFrameBuffer(rw, rh);
|
const u16 w = mTexWidth * kMapResolutionMultiplier;
|
||||||
|
const u16 h = mTexHeight * kMapResolutionMultiplier;
|
||||||
|
GXCreateFrameBuffer(w, h);
|
||||||
// Set logical viewport dimensions
|
// Set logical viewport dimensions
|
||||||
GXSetViewport(0.0f, 0.0f, mTexWidth, mTexHeight, 0.0f, 1.0f);
|
GXSetViewport(0.0f, 0.0f, mTexWidth, mTexHeight, 0.0f, 1.0f);
|
||||||
GXSetScissor(0, 0, mTexWidth, mTexHeight);
|
GXSetScissor(0, 0, mTexWidth, mTexHeight);
|
||||||
// Set render viewport dimensions
|
// Set render viewport dimensions
|
||||||
GXSetViewportRender(0.0f, 0.0f, rw, rh, 0.0f, 1.0f);
|
GXSetViewportRender(0.0f, 0.0f, w, h, 0.0f, 1.0f);
|
||||||
GXSetScissorRender(0, 0, rw, rh);
|
GXSetScissorRender(0, 0, w, h);
|
||||||
#else
|
#else
|
||||||
GXSetViewport(0.0f, 0.0f, mTexWidth, mTexHeight, 0.0f, 1.0f);
|
GXSetViewport(0.0f, 0.0f, mTexWidth, mTexHeight, 0.0f, 1.0f);
|
||||||
GXSetScissor(0, 0, mTexWidth, mTexHeight);
|
GXSetScissor(0, 0, mTexWidth, mTexHeight);
|
||||||
@@ -643,9 +610,11 @@ void dRenderingFDAmap_c::preRenderingMap() {
|
|||||||
void dRenderingFDAmap_c::postRenderingMap() {
|
void dRenderingFDAmap_c::postRenderingMap() {
|
||||||
GXSetCopyFilter(GX_FALSE, NULL, GX_FALSE, NULL);
|
GXSetCopyFilter(GX_FALSE, NULL, GX_FALSE, NULL);
|
||||||
#ifdef TARGET_PC
|
#ifdef TARGET_PC
|
||||||
const auto [rw, rh] = map_render_size_for(mTexWidth, mTexHeight);
|
// Increase map render resolution
|
||||||
GXSetTexCopySrc(0, 0, rw, rh);
|
const u16 w = mTexWidth * kMapResolutionMultiplier;
|
||||||
GXSetTexCopyDst(rw, rh, GX_CTF_R8, GX_FALSE);
|
const u16 h = mTexHeight * kMapResolutionMultiplier;
|
||||||
|
GXSetTexCopySrc(0, 0, w, h);
|
||||||
|
GXSetTexCopyDst(w, h, GX_CTF_R8, GX_FALSE);
|
||||||
GXCopyTex(field_0x4, GX_TRUE);
|
GXCopyTex(field_0x4, GX_TRUE);
|
||||||
GXRestoreFrameBuffer();
|
GXRestoreFrameBuffer();
|
||||||
#else
|
#else
|
||||||
|
|||||||
@@ -36,10 +36,6 @@
|
|||||||
#include "d/d_menu_window.h"
|
#include "d/d_menu_window.h"
|
||||||
#include "JSystem/J3DGraphBase/J3DMaterial.h"
|
#include "JSystem/J3DGraphBase/J3DMaterial.h"
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
#include "dusk/menu_pointer.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef void (dMenu_Collect2D_c::*initFunc)();
|
typedef void (dMenu_Collect2D_c::*initFunc)();
|
||||||
static DUSK_CONSTEXPR initFunc init[] = {
|
static DUSK_CONSTEXPR initFunc init[] = {
|
||||||
&dMenu_Collect2D_c::wait_init, &dMenu_Collect2D_c::save_open_init,
|
&dMenu_Collect2D_c::wait_init, &dMenu_Collect2D_c::save_open_init,
|
||||||
@@ -1790,12 +1786,6 @@ void dMenu_Collect2D_c::wait_init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void dMenu_Collect2D_c::wait_proc() {
|
void dMenu_Collect2D_c::wait_proc() {
|
||||||
#if TARGET_PC
|
|
||||||
if (pointerWait()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (dMw_A_TRIGGER()) {
|
if (dMw_A_TRIGGER()) {
|
||||||
if (mCursorX == 0 && mCursorY == 5) {
|
if (mCursorX == 0 && mCursorY == 5) {
|
||||||
if (mDoGph_gInf_c::getFader()->mStatus == 1) {
|
if (mDoGph_gInf_c::getFader()->mStatus == 1) {
|
||||||
@@ -1897,87 +1887,6 @@ void dMenu_Collect2D_c::wait_proc() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
void dMenu_Collect2D_c::pointerActivateCurrent() {
|
|
||||||
if (mCursorX == 0 && mCursorY == 5) {
|
|
||||||
if (mDoGph_gInf_c::getFader()->mStatus == 1) {
|
|
||||||
mSubWindowOpenCheck = 1;
|
|
||||||
Z2GetAudioMgr()->seStart(Z2SE_SY_MENU_CHANGE_WINDOW, NULL, 0, 0, 1.0f, 1.0f, -1.0f,
|
|
||||||
-1.0f, 0);
|
|
||||||
dMeter2Info_set2DVibrationM();
|
|
||||||
}
|
|
||||||
} else if (mCursorX == 1 && mCursorY == 5) {
|
|
||||||
if (mDoGph_gInf_c::getFader()->mStatus == 1) {
|
|
||||||
mSubWindowOpenCheck = 2;
|
|
||||||
Z2GetAudioMgr()->seStart(Z2SE_SY_MENU_CHANGE_WINDOW, NULL, 0, 0, 1.0f, 1.0f, -1.0f,
|
|
||||||
-1.0f, 0);
|
|
||||||
dMeter2Info_set2DVibrationM();
|
|
||||||
}
|
|
||||||
} else if (mCursorX == 3 && mCursorY == 4) {
|
|
||||||
if (field_0x22d[3][4] != 0 && mDoGph_gInf_c::getFader()->mStatus == 1) {
|
|
||||||
mSubWindowOpenCheck = 3;
|
|
||||||
dMeter2Info_set2DVibration();
|
|
||||||
}
|
|
||||||
} else if (mCursorX == 2 && mCursorY == 4) {
|
|
||||||
if (isFishIconVisible() && mDoGph_gInf_c::getFader()->mStatus == 1) {
|
|
||||||
mSubWindowOpenCheck = 4;
|
|
||||||
dMeter2Info_set2DVibration();
|
|
||||||
}
|
|
||||||
} else if (mCursorX == 3 && mCursorY == 3) {
|
|
||||||
if (isSkillIconVisible() && mDoGph_gInf_c::getFader()->mStatus == 1) {
|
|
||||||
mSubWindowOpenCheck = 5;
|
|
||||||
dMeter2Info_set2DVibration();
|
|
||||||
}
|
|
||||||
} else if (mCursorX == 2 && mCursorY == 3) {
|
|
||||||
if (isInsectIconVisible() && mDoGph_gInf_c::getFader()->mStatus == 1) {
|
|
||||||
mSubWindowOpenCheck = 6;
|
|
||||||
dMeter2Info_set2DVibration();
|
|
||||||
}
|
|
||||||
} else if (field_0x22d[mCursorX][mCursorY] != 0 && !mIsWolf) {
|
|
||||||
if ((mCursorX >= 3 && mCursorX <= 4) || (mCursorX == 5 && mCursorY == 2)) {
|
|
||||||
u8 cursorY = mCursorY;
|
|
||||||
if (cursorY == 0) {
|
|
||||||
if (daPy_getPlayerActorClass()->getSwordChangeWaitTimer() == 0) {
|
|
||||||
changeSword();
|
|
||||||
}
|
|
||||||
} else if (cursorY == 1) {
|
|
||||||
if (daPy_getPlayerActorClass()->getShieldChangeWaitTimer() == 0) {
|
|
||||||
changeShield();
|
|
||||||
}
|
|
||||||
} else if (cursorY == 2 &&
|
|
||||||
daPy_getPlayerActorClass()->getClothesChangeWaitTimer() == 0)
|
|
||||||
{
|
|
||||||
changeClothe();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool dMenu_Collect2D_c::pointerWait() {
|
|
||||||
dusk::menu_pointer::begin_context(dusk::menu_pointer::Context::Collection);
|
|
||||||
for (u8 y = 0; y < 6; ++y) {
|
|
||||||
for (u8 x = 0; x < 7; ++x) {
|
|
||||||
if (getItemTag(x, y, true) == 0 || !dusk::menu_pointer::hit_pane(mpSelPm[x][y], 8.0f)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (mCursorX != x || mCursorY != y) {
|
|
||||||
mDoAud_seStart(Z2SE_SY_MENU_CURSOR_COMMON, NULL, 0, 0);
|
|
||||||
mCursorX = x;
|
|
||||||
mCursorY = y;
|
|
||||||
cursorPosSet();
|
|
||||||
setItemNameString(mCursorX, mCursorY);
|
|
||||||
}
|
|
||||||
if (dusk::menu_pointer::consume_click()) {
|
|
||||||
pointerActivateCurrent();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
void dMenu_Collect2D_c::save_open_init() {
|
void dMenu_Collect2D_c::save_open_init() {
|
||||||
JKRHeap* heap = mDoExt_setCurrentHeap(mpSubHeap);
|
JKRHeap* heap = mDoExt_setCurrentHeap(mpSubHeap);
|
||||||
|
|||||||
@@ -17,10 +17,7 @@
|
|||||||
#include "d/d_msg_scrn_explain.h"
|
#include "d/d_msg_scrn_explain.h"
|
||||||
#include "m_Do/m_Do_graphic.h"
|
#include "m_Do/m_Do_graphic.h"
|
||||||
#include "d/actor/d_a_midna.h"
|
#include "d/actor/d_a_midna.h"
|
||||||
#if TARGET_PC
|
|
||||||
#include "dusk/frame_interpolation.h"
|
#include "dusk/frame_interpolation.h"
|
||||||
#include "dusk/ui/touch_controls.hpp"
|
|
||||||
#endif
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
#if TARGET_PC
|
#if TARGET_PC
|
||||||
@@ -2512,10 +2509,6 @@ dMenu_Fmap2DTop_c::dMenu_Fmap2DTop_c(JKRExpHeap* i_heap, STControl* i_stick) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dMenu_Fmap2DTop_c::~dMenu_Fmap2DTop_c() {
|
dMenu_Fmap2DTop_c::~dMenu_Fmap2DTop_c() {
|
||||||
#if TARGET_PC
|
|
||||||
dusk::ui::set_control_override(dusk::ui::Control::Z, dusk::ui::ControlOverride::Default);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
deleteExplain();
|
deleteExplain();
|
||||||
JKR_DELETE(mpTitleScreen);
|
JKR_DELETE(mpTitleScreen);
|
||||||
mpTitleScreen = NULL;
|
mpTitleScreen = NULL;
|
||||||
@@ -2789,12 +2782,6 @@ void dMenu_Fmap2DTop_c::setZButtonString(u32 param_0, u8 i_alpha) {
|
|||||||
param_0 = 0x533;
|
param_0 = 0x533;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
dusk::ui::set_control_override(dusk::ui::Control::Z,
|
|
||||||
param_0 != 0 && isWarpAccept() ? dusk::ui::ControlOverride::Action :
|
|
||||||
dusk::ui::ControlOverride::Default);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if VERSION == VERSION_GCN_JPN
|
#if VERSION == VERSION_GCN_JPN
|
||||||
static const u64 cont_zt[5] = {MULTI_CHAR('cont_zt'), MULTI_CHAR('cont_zt1'), MULTI_CHAR('cont_zt2'), MULTI_CHAR('cont_zt3'), MULTI_CHAR('cont_zt4')};
|
static const u64 cont_zt[5] = {MULTI_CHAR('cont_zt'), MULTI_CHAR('cont_zt1'), MULTI_CHAR('cont_zt2'), MULTI_CHAR('cont_zt3'), MULTI_CHAR('cont_zt4')};
|
||||||
#define setZButtonString_font_zt cont_zt
|
#define setZButtonString_font_zt cont_zt
|
||||||
|
|||||||
@@ -22,10 +22,6 @@
|
|||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
#include "dusk/menu_pointer.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef void (dMenu_Insect_c::*initFunc)();
|
typedef void (dMenu_Insect_c::*initFunc)();
|
||||||
static initFunc map_init_process[] = {
|
static initFunc map_init_process[] = {
|
||||||
&dMenu_Insect_c::wait_init, &dMenu_Insect_c::explain_open_init,
|
&dMenu_Insect_c::wait_init, &dMenu_Insect_c::explain_open_init,
|
||||||
@@ -284,12 +280,6 @@ void dMenu_Insect_c::wait_init() {
|
|||||||
|
|
||||||
void dMenu_Insect_c::wait_move() {
|
void dMenu_Insect_c::wait_move() {
|
||||||
if (mDoGph_gInf_c::getFader()->getStatus() == 1) {
|
if (mDoGph_gInf_c::getFader()->getStatus() == 1) {
|
||||||
#if TARGET_PC
|
|
||||||
if (pointerWait()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (mDoCPd_c::getTrigB(PAD_1) || field_0xf7 == 0) {
|
if (mDoCPd_c::getTrigB(PAD_1) || field_0xf7 == 0) {
|
||||||
if (mDoCPd_c::getTrigB(PAD_1) && field_0xf6 == 1) {
|
if (mDoCPd_c::getTrigB(PAD_1) && field_0xf6 == 1) {
|
||||||
dMeter2Info_setInsectSelectType(0);
|
dMeter2Info_setInsectSelectType(0);
|
||||||
@@ -311,39 +301,6 @@ void dMenu_Insect_c::wait_move() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
bool dMenu_Insect_c::pointerWait() {
|
|
||||||
dusk::menu_pointer::begin_context(dusk::menu_pointer::Context::Collection);
|
|
||||||
for (u8 y = 0; y < 4; ++y) {
|
|
||||||
for (u8 x = 0; x < 6; ++x) {
|
|
||||||
const int index = x + y * 6;
|
|
||||||
if (!isGetInsect(x, y) || !dusk::menu_pointer::hit_pane(mpINSParent[index], 8.0f)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (field_0xf4 != x || field_0xf5 != y) {
|
|
||||||
field_0xf4 = x;
|
|
||||||
field_0xf5 = y;
|
|
||||||
setCursorPos();
|
|
||||||
setAButtonString(0x368);
|
|
||||||
Z2GetAudioMgr()->seStart(Z2SE_SY_CURSOR_ITEM, NULL, 0, 0, 1.0f, 1.0f, -1.0f,
|
|
||||||
-1.0f, 0);
|
|
||||||
}
|
|
||||||
if (dusk::menu_pointer::consume_click()) {
|
|
||||||
field_0xf3 = 1;
|
|
||||||
Z2GetAudioMgr()->seStart(Z2SE_SY_EXP_WIN_OPEN, NULL, 0, 0, 1.0f, 1.0f, -1.0f,
|
|
||||||
-1.0f, 0);
|
|
||||||
dMeter2Info_set2DVibration();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void dMenu_Insect_c::explain_open_init() {
|
void dMenu_Insect_c::explain_open_init() {
|
||||||
char local_78[32];
|
char local_78[32];
|
||||||
char local_98[32];
|
char local_98[32];
|
||||||
|
|||||||
@@ -19,15 +19,6 @@
|
|||||||
|
|
||||||
#ifdef TARGET_PC
|
#ifdef TARGET_PC
|
||||||
#include "dusk/achievements.h"
|
#include "dusk/achievements.h"
|
||||||
#include "dusk/menu_pointer.h"
|
|
||||||
#include "dusk/ui/touch_controls.hpp"
|
|
||||||
|
|
||||||
static void enable_turn_page_controls(bool enabled) {
|
|
||||||
const auto controlOverride =
|
|
||||||
enabled ? dusk::ui::ControlOverride::Action : dusk::ui::ControlOverride::Default;
|
|
||||||
dusk::ui::set_control_override(dusk::ui::Control::L, controlOverride);
|
|
||||||
dusk::ui::set_control_override(dusk::ui::Control::R, controlOverride);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if VERSION == VERSION_GCN_JPN
|
#if VERSION == VERSION_GCN_JPN
|
||||||
@@ -91,10 +82,6 @@ dMenu_Letter_c::dMenu_Letter_c(JKRExpHeap* i_heap, STControl* i_stick, CSTContro
|
|||||||
|
|
||||||
|
|
||||||
dMenu_Letter_c::~dMenu_Letter_c() {
|
dMenu_Letter_c::~dMenu_Letter_c() {
|
||||||
#if TARGET_PC
|
|
||||||
enable_turn_page_controls(false);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
JKR_DELETE(mpDrawCursor);
|
JKR_DELETE(mpDrawCursor);
|
||||||
mpDrawCursor = NULL;
|
mpDrawCursor = NULL;
|
||||||
|
|
||||||
@@ -370,10 +357,6 @@ int dMenu_Letter_c::_open() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int dMenu_Letter_c::_close() {
|
int dMenu_Letter_c::_close() {
|
||||||
#if TARGET_PC
|
|
||||||
enable_turn_page_controls(false);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
s16 closeWindowFrame =
|
s16 closeWindowFrame =
|
||||||
g_drawHIO.mLetterSelectScreen.mCloseFrame[dMeter_drawLetterHIO_c::WINDOW_FRAME];
|
g_drawHIO.mLetterSelectScreen.mCloseFrame[dMeter_drawLetterHIO_c::WINDOW_FRAME];
|
||||||
field_0x368 = 0;
|
field_0x368 = 0;
|
||||||
@@ -403,10 +386,6 @@ int dMenu_Letter_c::_close() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void dMenu_Letter_c::wait_init() {
|
void dMenu_Letter_c::wait_init() {
|
||||||
#if TARGET_PC
|
|
||||||
enable_turn_page_controls(field_0x374 > 1);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
setAButtonString(0x40c);
|
setAButtonString(0x40c);
|
||||||
setBButtonString(0x3f9);
|
setBButtonString(0x3f9);
|
||||||
}
|
}
|
||||||
@@ -414,12 +393,6 @@ void dMenu_Letter_c::wait_init() {
|
|||||||
void dMenu_Letter_c::wait_move() {
|
void dMenu_Letter_c::wait_move() {
|
||||||
u8 oldIndex = mIndex;
|
u8 oldIndex = mIndex;
|
||||||
if (mDoGph_gInf_c::getFader()->getStatus() == 1) {
|
if (mDoGph_gInf_c::getFader()->getStatus() == 1) {
|
||||||
#if TARGET_PC
|
|
||||||
if (pointerWait()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (mDoCPd_c::getTrigB(PAD_1) != 0) {
|
if (mDoCPd_c::getTrigB(PAD_1) != 0) {
|
||||||
mpDrawCursor->offPlayAnime(0);
|
mpDrawCursor->offPlayAnime(0);
|
||||||
mStatus = 3;
|
mStatus = 3;
|
||||||
@@ -475,40 +448,8 @@ void dMenu_Letter_c::wait_move() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
bool dMenu_Letter_c::pointerWait() {
|
|
||||||
dusk::menu_pointer::begin_context(dusk::menu_pointer::Context::Collection);
|
|
||||||
for (u8 i = 0; i < field_0x373; ++i) {
|
|
||||||
if (!dusk::menu_pointer::hit_pane(mpLetterParent[i], 8.0f)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mIndex != i) {
|
|
||||||
mIndex = i;
|
|
||||||
changeActiveColor();
|
|
||||||
Z2GetAudioMgr()->seStart(Z2SE_SY_CURSOR_ITEM, NULL, 0, 0, 1.0f, 1.0f, -1.0f,
|
|
||||||
-1.0f, 0);
|
|
||||||
}
|
|
||||||
if (dusk::menu_pointer::consume_click()) {
|
|
||||||
mProcess = 3;
|
|
||||||
Z2GetAudioMgr()->seStart(Z2SE_SY_LETTER_OPEN, NULL, 0, 0, 1.0f, 1.0f, -1.0f,
|
|
||||||
-1.0f, 0);
|
|
||||||
dMeter2Info_set2DVibration();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
void dMenu_Letter_c::slide_right_init() {
|
void dMenu_Letter_c::slide_right_init() {
|
||||||
#if TARGET_PC
|
|
||||||
enable_turn_page_controls(false);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
field_0x358 = -field_0x1ec->getWidth() * mDoGph_gInf_c::getInvScale();
|
field_0x358 = -field_0x1ec->getWidth() * mDoGph_gInf_c::getInvScale();
|
||||||
field_0x35c = field_0x1ec->getWidth() IF_NOT_DUSK(* mDoGph_gInf_c::getInvScale());
|
field_0x35c = field_0x1ec->getWidth() IF_NOT_DUSK(* mDoGph_gInf_c::getInvScale());
|
||||||
changePageLight();
|
changePageLight();
|
||||||
@@ -526,10 +467,6 @@ void dMenu_Letter_c::slide_right_move() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void dMenu_Letter_c::slide_left_init() {
|
void dMenu_Letter_c::slide_left_init() {
|
||||||
#if TARGET_PC
|
|
||||||
enable_turn_page_controls(false);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
field_0x358 = field_0x1ec->getWidth() * mDoGph_gInf_c::getInvScale();
|
field_0x358 = field_0x1ec->getWidth() * mDoGph_gInf_c::getInvScale();
|
||||||
field_0x35c = -field_0x1ec->getWidth() IF_NOT_DUSK(* mDoGph_gInf_c::getInvScale());
|
field_0x35c = -field_0x1ec->getWidth() IF_NOT_DUSK(* mDoGph_gInf_c::getInvScale());
|
||||||
changePageLight();
|
changePageLight();
|
||||||
@@ -547,10 +484,6 @@ void dMenu_Letter_c::slide_left_move() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void dMenu_Letter_c::read_open_init() {
|
void dMenu_Letter_c::read_open_init() {
|
||||||
#if TARGET_PC
|
|
||||||
enable_turn_page_controls(false);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
field_0x36a = 0;
|
field_0x36a = 0;
|
||||||
u8 idx = field_0x3ac[field_0x36f * 6 + mIndex] - 1;
|
u8 idx = field_0x3ac[field_0x36f * 6 + mIndex] - 1;
|
||||||
field_0x3e3 = 1;
|
field_0x3e3 = 1;
|
||||||
|
|||||||
@@ -26,11 +26,6 @@
|
|||||||
|
|
||||||
#include "JSystem/JAudio2/JASDriverIF.h"
|
#include "JSystem/JAudio2/JASDriverIF.h"
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
#include "dusk/menu_pointer.h"
|
|
||||||
#include "dusk/ui/touch_controls.hpp"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef void (dMenu_Option_c::*initFunc)();
|
typedef void (dMenu_Option_c::*initFunc)();
|
||||||
static initFunc init[] = {
|
static initFunc init[] = {
|
||||||
&dMenu_Option_c::atten_init,
|
&dMenu_Option_c::atten_init,
|
||||||
@@ -298,10 +293,6 @@ void dMenu_Option_c::_create() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void dMenu_Option_c::_delete() {
|
void dMenu_Option_c::_delete() {
|
||||||
#if TARGET_PC
|
|
||||||
dusk::ui::set_control_override(dusk::ui::Control::Z, dusk::ui::ControlOverride::Default);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
JKR_DELETE(mpString);
|
JKR_DELETE(mpString);
|
||||||
mpString = NULL;
|
mpString = NULL;
|
||||||
|
|
||||||
@@ -527,15 +518,6 @@ void dMenu_Option_c::_move() {
|
|||||||
(this->*init[field_0x3ef])();
|
(this->*init[field_0x3ef])();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
if (field_0x3f4 == 5 && field_0x3ef != SelectType3 && field_0x3f3 == 5 &&
|
|
||||||
field_0x3ef != SelectType4 && field_0x3ef != SelectType5 && field_0x3ef != SelectType6 &&
|
|
||||||
field_0x3ef != SelectType7 && pointerConfirmSelect())
|
|
||||||
{
|
|
||||||
goto skip;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
skip:
|
skip:
|
||||||
u8 oldValue = field_0x3ef;
|
u8 oldValue = field_0x3ef;
|
||||||
@@ -1092,34 +1074,6 @@ void dMenu_Option_c::confirm_move_move() {
|
|||||||
bool leftTrigger = checkLeftTrigger();
|
bool leftTrigger = checkLeftTrigger();
|
||||||
bool rightTrigger = checkRightTrigger();
|
bool rightTrigger = checkRightTrigger();
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
dusk::menu_pointer::begin_context(dusk::menu_pointer::Context::Options);
|
|
||||||
for (u8 i = 0; i < 2; ++i) {
|
|
||||||
if (!dusk::menu_pointer::hit_pane(mpYesNoSelBase_c[i], 8.0f)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (field_0x3f9 != i) {
|
|
||||||
Z2GetAudioMgr()->seStart(Z2SE_SY_MENU_CURSOR_COMMON, NULL, 0, 0, 1.0f, 1.0f, -1.0f,
|
|
||||||
-1.0f, 0);
|
|
||||||
field_0x3fa = field_0x3f9;
|
|
||||||
field_0x3f9 = i;
|
|
||||||
yesnoSelectAnmSet();
|
|
||||||
field_0x3ef = SelectType6;
|
|
||||||
mpWarning->_move();
|
|
||||||
setAnimation();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (dusk::menu_pointer::consume_click()) {
|
|
||||||
yesNoSelectStart();
|
|
||||||
field_0x3ef = SelectType7;
|
|
||||||
dMeter2Info_set2DVibrationM();
|
|
||||||
mpWarning->_move();
|
|
||||||
setAnimation();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (mDoCPd_c::getTrigA(PAD_1) != 0) {
|
if (mDoCPd_c::getTrigA(PAD_1) != 0) {
|
||||||
yesNoSelectStart();
|
yesNoSelectStart();
|
||||||
field_0x3ef = SelectType7;
|
field_0x3ef = SelectType7;
|
||||||
@@ -2109,11 +2063,6 @@ void dMenu_Option_c::cursorAnime(f32 i_cursorValue) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void dMenu_Option_c::setZButtonString(u16 i_stringID) {
|
void dMenu_Option_c::setZButtonString(u16 i_stringID) {
|
||||||
#if TARGET_PC
|
|
||||||
dusk::ui::set_control_override(dusk::ui::Control::Z,
|
|
||||||
i_stringID != 0 ? dusk::ui::ControlOverride::Action : dusk::ui::ControlOverride::Default);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (i_stringID == 0) {
|
if (i_stringID == 0) {
|
||||||
for (int i = 0; i < 3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
if (mpZButtonText[i] != NULL) {
|
if (mpZButtonText[i] != NULL) {
|
||||||
@@ -2193,88 +2142,7 @@ bool dMenu_Option_c::isRumbleSupported() {
|
|||||||
return JUTGamePad::sRumbleSupported >> 0x1f;
|
return JUTGamePad::sRumbleSupported >> 0x1f;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
bool dMenu_Option_c::pointerConfirmSelect() {
|
|
||||||
dusk::menu_pointer::begin_context(dusk::menu_pointer::Context::Options);
|
|
||||||
if (!dusk::menu_pointer::state().clicked) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (u8 i = 0; i < SelectType3; ++i) {
|
|
||||||
if (dusk::menu_pointer::hit_pane(mpMenuPane[i], 8.0f)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!dusk::menu_pointer::consume_click()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
field_0x3f7 = 1;
|
|
||||||
field_0x3f5 = field_0x3ef;
|
|
||||||
field_0x3ef = SelectType4;
|
|
||||||
dMeter2Info_set2DVibration();
|
|
||||||
(this->*init[field_0x3ef])();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool dMenu_Option_c::dpdMenuMove() {
|
bool dMenu_Option_c::dpdMenuMove() {
|
||||||
#if TARGET_PC
|
|
||||||
dusk::menu_pointer::begin_context(dusk::menu_pointer::Context::Options);
|
|
||||||
for (u8 i = 0; i < SelectType3; ++i) {
|
|
||||||
if (!dusk::menu_pointer::hit_pane(mpMenuPane[i], 8.0f)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (getSelectType() != i) {
|
|
||||||
field_0x3ef = i;
|
|
||||||
setCursorPos(i);
|
|
||||||
Z2GetAudioMgr()->seStart(Z2SE_SY_CURSOR_OPTION, NULL, 0, 0, 1.0f, 1.0f, -1.0f,
|
|
||||||
-1.0f, 0);
|
|
||||||
}
|
|
||||||
if (!dusk::menu_pointer::consume_click()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (i) {
|
|
||||||
case SelectType0:
|
|
||||||
field_0x3e4 ^= 1;
|
|
||||||
field_0x3da = 5;
|
|
||||||
field_0x3ef = SelectType3;
|
|
||||||
field_0x3f5 = SelectType0;
|
|
||||||
Z2GetAudioMgr()->seStart(Z2SE_SY_OPTION_SWITCH, NULL, 0, 0, 1.0f, 1.0f, -1.0f,
|
|
||||||
-1.0f, 0);
|
|
||||||
return true;
|
|
||||||
case SelectType1:
|
|
||||||
if (isRumbleSupported()) {
|
|
||||||
field_0x3ea ^= 1;
|
|
||||||
if (field_0x3ea != 0) {
|
|
||||||
mDoCPd_c::startMotorWave(0, &field_0x3e0, JUTGamePad::CRumble::VAL_0, 0x3c);
|
|
||||||
}
|
|
||||||
field_0x3da = 5;
|
|
||||||
field_0x3ef = SelectType3;
|
|
||||||
field_0x3f5 = SelectType1;
|
|
||||||
Z2GetAudioMgr()->seStart(Z2SE_SY_OPTION_SWITCH, NULL, 0, 0, 1.0f, 1.0f, -1.0f,
|
|
||||||
-1.0f, 0);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
case SelectType2:
|
|
||||||
if (field_0x3e9 == 0) {
|
|
||||||
field_0x3e9 = 2;
|
|
||||||
} else {
|
|
||||||
field_0x3e9--;
|
|
||||||
}
|
|
||||||
field_0x3da = 5;
|
|
||||||
mDoAud_setOutputMode(dMo_soundMode[field_0x3e9]);
|
|
||||||
setSoundMode(dMo_soundMode[field_0x3e9]);
|
|
||||||
field_0x3ef = SelectType3;
|
|
||||||
field_0x3f5 = SelectType2;
|
|
||||||
Z2GetAudioMgr()->seStart(Z2SE_SY_OPTION_SWITCH, NULL, 0, 0, 1.0f, 1.0f, -1.0f,
|
|
||||||
-1.0f, 0);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,9 +31,7 @@
|
|||||||
|
|
||||||
#if TARGET_PC
|
#if TARGET_PC
|
||||||
#include "dusk/game_clock.h"
|
#include "dusk/game_clock.h"
|
||||||
#include "dusk/menu_pointer.h"
|
|
||||||
#include "dusk/settings.h"
|
#include "dusk/settings.h"
|
||||||
#include "dusk/ui/touch_controls.hpp"
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef void (dMenu_Ring_c::*initFunc)();
|
typedef void (dMenu_Ring_c::*initFunc)();
|
||||||
@@ -616,9 +614,6 @@ void dMenu_Ring_c::_delete() {
|
|||||||
* initializes a new process if mStatus changes
|
* initializes a new process if mStatus changes
|
||||||
*/
|
*/
|
||||||
void dMenu_Ring_c::_move() {
|
void dMenu_Ring_c::_move() {
|
||||||
#if TARGET_PC
|
|
||||||
dusk::menu_pointer::begin_context(dusk::menu_pointer::Context::ItemWheel);
|
|
||||||
#endif
|
|
||||||
mRingRadiusH = g_ringHIO.mRingRadiusH;
|
mRingRadiusH = g_ringHIO.mRingRadiusH;
|
||||||
mRingRadiusV = g_ringHIO.mRingRadiusV;
|
mRingRadiusV = g_ringHIO.mRingRadiusV;
|
||||||
mOldStatus = mStatus; // Save current status for check
|
mOldStatus = mStatus; // Save current status for check
|
||||||
@@ -1522,11 +1517,6 @@ void dMenu_Ring_c::stick_wait_proc() {
|
|||||||
setDoStatus(0);
|
setDoStatus(0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#if TARGET_PC
|
|
||||||
if (pointerMove()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (dMw_A_TRIGGER() && !dMeter2Info_isTouchKeyCheck(0xe)) {
|
if (dMw_A_TRIGGER() && !dMeter2Info_isTouchKeyCheck(0xe)) {
|
||||||
Z2GetAudioMgr()->seStart(Z2SE_SYS_ERROR, NULL, 0, 0, 1.0f, 1.0f, -1.0f, -1.0f, 0);
|
Z2GetAudioMgr()->seStart(Z2SE_SYS_ERROR, NULL, 0, 0, 1.0f, 1.0f, -1.0f, -1.0f, 0);
|
||||||
}
|
}
|
||||||
@@ -1538,49 +1528,6 @@ void dMenu_Ring_c::stick_wait_proc() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
bool dMenu_Ring_c::pointerMove() {
|
|
||||||
dusk::menu_pointer::begin_context(dusk::menu_pointer::Context::ItemWheel);
|
|
||||||
const auto& pointer = dusk::menu_pointer::state();
|
|
||||||
if (!pointer.valid || mItemsTotal == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int hoveredSlot = -1;
|
|
||||||
f32 bestDistance = 42.0f;
|
|
||||||
for (u8 i = 0; i < mItemsTotal; ++i) {
|
|
||||||
const f32 x = mItemSlotPosX[i] + mCenterPosX;
|
|
||||||
const f32 y = mItemSlotPosY[i] + mCenterPosY;
|
|
||||||
const f32 distance = calcDistance(pointer.x, pointer.y, x, y);
|
|
||||||
if (distance < bestDistance) {
|
|
||||||
bestDistance = distance;
|
|
||||||
hoveredSlot = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hoveredSlot < 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mCurrentSlot != hoveredSlot) {
|
|
||||||
mDirectSelectCursorPos.x = mItemSlotPosX[mCurrentSlot];
|
|
||||||
mDirectSelectCursorPos.z = mItemSlotPosY[mCurrentSlot];
|
|
||||||
mCurrentSlot = hoveredSlot;
|
|
||||||
mDirectSelectActive = true;
|
|
||||||
field_0x670 = field_0x63e[mCurrentSlot];
|
|
||||||
setStatus(STATUS_MOVE);
|
|
||||||
field_0x6b2 = 0;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dusk::menu_pointer::consume_click()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void dMenu_Ring_c::stick_move_init() {
|
void dMenu_Ring_c::stick_move_init() {
|
||||||
if (mCursorSpeed == 0) {
|
if (mCursorSpeed == 0) {
|
||||||
mCursorSpeed = g_ringHIO.mCursorInitSpeed;
|
mCursorSpeed = g_ringHIO.mCursorInitSpeed;
|
||||||
@@ -1725,40 +1672,12 @@ void dMenu_Ring_c::drawSelectItem() {
|
|||||||
#else
|
#else
|
||||||
if (field_0x674[i] < 10) {
|
if (field_0x674[i] < 10) {
|
||||||
#endif
|
#endif
|
||||||
#if TARGET_PC
|
|
||||||
f32 initSizeX;
|
|
||||||
f32 initSizeY;
|
|
||||||
f32 initScaleX;
|
|
||||||
f32 initScaleY;
|
|
||||||
Vec pos;
|
|
||||||
dusk::ui::EquipTarget touchTarget;
|
|
||||||
if (dusk::ui::get_equip_target(i, touchTarget)) {
|
|
||||||
initSizeX = touchTarget.width;
|
|
||||||
initSizeY = touchTarget.height;
|
|
||||||
initScaleX = 1.0f;
|
|
||||||
initScaleY = 1.0f;
|
|
||||||
pos.x = touchTarget.left;
|
|
||||||
pos.y = touchTarget.top;
|
|
||||||
pos.z = 0.0f;
|
|
||||||
} else {
|
|
||||||
CPaneMgr* meterItemPane = dMeter2Info_getMeterItemPanePtr(i);
|
|
||||||
if (meterItemPane == NULL) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
initSizeX = meterItemPane->getInitSizeX() * 1.7f;
|
|
||||||
initSizeY = meterItemPane->getInitSizeY() * 1.7f;
|
|
||||||
initScaleX = meterItemPane->getInitScaleX();
|
|
||||||
initScaleY = meterItemPane->getInitScaleY();
|
|
||||||
pos = meterItemPane->getGlobalVtxCenter(meterItemPane->mPane, true, 0);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
f32 initSizeX = dMeter2Info_getMeterItemPanePtr(i)->getInitSizeX() * 1.7f;
|
f32 initSizeX = dMeter2Info_getMeterItemPanePtr(i)->getInitSizeX() * 1.7f;
|
||||||
f32 initSizeY = dMeter2Info_getMeterItemPanePtr(i)->getInitSizeY() * 1.7f;
|
f32 initSizeY = dMeter2Info_getMeterItemPanePtr(i)->getInitSizeY() * 1.7f;
|
||||||
f32 initScaleX = dMeter2Info_getMeterItemPanePtr(i)->getInitScaleX();
|
f32 initScaleX = dMeter2Info_getMeterItemPanePtr(i)->getInitScaleX();
|
||||||
f32 initScaleY = dMeter2Info_getMeterItemPanePtr(i)->getInitScaleY();
|
f32 initScaleY = dMeter2Info_getMeterItemPanePtr(i)->getInitScaleY();
|
||||||
Vec pos = dMeter2Info_getMeterItemPanePtr(i)->getGlobalVtxCenter(
|
Vec pos = dMeter2Info_getMeterItemPanePtr(i)->getGlobalVtxCenter(
|
||||||
dMeter2Info_getMeterItemPanePtr(i)->mPane, true, 0);
|
dMeter2Info_getMeterItemPanePtr(i)->mPane, true, 0);
|
||||||
#endif
|
|
||||||
|
|
||||||
#if TARGET_PC
|
#if TARGET_PC
|
||||||
f32 fVar14 = 0.1f + 0.8f * u;
|
f32 fVar14 = 0.1f + 0.8f * u;
|
||||||
|
|||||||
+2
-153
@@ -18,15 +18,11 @@
|
|||||||
#include "m_Do/m_Do_controller_pad.h"
|
#include "m_Do/m_Do_controller_pad.h"
|
||||||
#include "m_Do/m_Do_graphic.h"
|
#include "m_Do/m_Do_graphic.h"
|
||||||
#include "d/d_msg_scrn_explain.h"
|
#include "d/d_msg_scrn_explain.h"
|
||||||
|
#include "dusk/frame_interpolation.h"
|
||||||
|
#include "dusk/settings.h"
|
||||||
#include "JSystem/J2DGraph/J2DAnmLoader.h"
|
#include "JSystem/J2DGraph/J2DAnmLoader.h"
|
||||||
#include "f_op/f_op_msg_mng.h"
|
#include "f_op/f_op_msg_mng.h"
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
#include "dusk/frame_interpolation.h"
|
|
||||||
#include "dusk/menu_pointer.h"
|
|
||||||
#include "dusk/settings.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static int SelStartFrameTbl[3] = {
|
static int SelStartFrameTbl[3] = {
|
||||||
59,
|
59,
|
||||||
99,
|
99,
|
||||||
@@ -58,17 +54,6 @@ static int YnSelStartFrameTbl[2][2] = {
|
|||||||
|
|
||||||
static int YnSelEndFrameTbl[2][2] = {{2138, 3171}, {2150, 3181}};
|
static int YnSelEndFrameTbl[2][2] = {{2138, 3171}, {2150, 3181}};
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
namespace {
|
|
||||||
constexpr u8 pointer_target(u8 group, u8 index) noexcept {
|
|
||||||
return static_cast<u8>((group << 4) | (index & 0x0F));
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr u8 s_pointerSaveSelectTarget = 0;
|
|
||||||
constexpr u8 s_pointerYesNoSelectTarget = 1;
|
|
||||||
} // namespace
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static dMs_HIO_c g_msHIO;
|
static dMs_HIO_c g_msHIO;
|
||||||
|
|
||||||
dMs_HIO_c::dMs_HIO_c() {
|
dMs_HIO_c::dMs_HIO_c() {
|
||||||
@@ -1781,12 +1766,6 @@ void dMenu_save_c::openSaveSelect3() {
|
|||||||
|
|
||||||
void dMenu_save_c::saveSelect() {
|
void dMenu_save_c::saveSelect() {
|
||||||
if (!mDoRst::isReset()) {
|
if (!mDoRst::isReset()) {
|
||||||
#if TARGET_PC
|
|
||||||
if (pointerSaveSelect()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
stick->checkTrigger();
|
stick->checkTrigger();
|
||||||
|
|
||||||
if (mDoCPd_c::getTrigA(PAD_1)) {
|
if (mDoCPd_c::getTrigA(PAD_1)) {
|
||||||
@@ -1813,84 +1792,7 @@ void dMenu_save_c::saveSelect() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
bool dMenu_save_c::pointerSaveSelect() {
|
|
||||||
dusk::menu_pointer::begin_context(dusk::menu_pointer::Context::Save);
|
|
||||||
for (u8 i = 0; i < 3; ++i) {
|
|
||||||
if (!dusk::menu_pointer::hit_pane(mpSelData[i], 8.0f)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const bool clicked = dusk::menu_pointer::consume_click();
|
|
||||||
if (mSelectedFile != i) {
|
|
||||||
mDoAud_seStart(Z2SE_FILE_SELECT_CURSOR, NULL, 0, 0);
|
|
||||||
mLastSelFile = mSelectedFile;
|
|
||||||
mSelectedFile = i;
|
|
||||||
if (clicked) {
|
|
||||||
dusk::menu_pointer::defer_activation(
|
|
||||||
dusk::menu_pointer::Context::Save,
|
|
||||||
pointer_target(s_pointerSaveSelectTarget, i));
|
|
||||||
}
|
|
||||||
dataSelectAnmSet();
|
|
||||||
mMenuProc = PROC_SAVE_SELECT_MOVE_ANM;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (clicked) {
|
|
||||||
saveSelectStart();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool dMenu_save_c::pointerYesNoSelect(bool errorSelect, u8 errParam, u8 soundParam) {
|
|
||||||
dusk::menu_pointer::begin_context(dusk::menu_pointer::Context::Save);
|
|
||||||
for (u8 i = 0; i < 2; ++i) {
|
|
||||||
if (!dusk::menu_pointer::hit_pane(mpNoYes[i], 8.0f)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const bool clicked =
|
|
||||||
(!errorSelect || mYesNoCursor == i) && dusk::menu_pointer::consume_click();
|
|
||||||
if (mYesNoCursor != i) {
|
|
||||||
if (errorSelect) {
|
|
||||||
errCurMove(errParam, soundParam);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
mDoAud_seStart(Z2SE_SY_MENU_CURSOR_COMMON, NULL, 0, 0);
|
|
||||||
mYesNoPrevCursor = mYesNoCursor;
|
|
||||||
mYesNoCursor = i;
|
|
||||||
if (clicked) {
|
|
||||||
dusk::menu_pointer::defer_activation(
|
|
||||||
dusk::menu_pointer::Context::Save,
|
|
||||||
pointer_target(s_pointerYesNoSelectTarget, i));
|
|
||||||
}
|
|
||||||
yesnoSelectAnmSet(0);
|
|
||||||
mMenuProc = PROC_YES_NO_CURSOR_MOVE_ANM;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (clicked) {
|
|
||||||
if (errorSelect) {
|
|
||||||
if (mYesNoCursor != CURSOR_NO) {
|
|
||||||
if (soundParam == 0) {
|
|
||||||
mDoAud_seStart(Z2SE_SY_CURSOR_OK, NULL, 0, 0);
|
|
||||||
}
|
|
||||||
} else if (soundParam == 0) {
|
|
||||||
mDoAud_seStart(Z2SE_SY_CURSOR_CANCEL, NULL, 0, 0);
|
|
||||||
}
|
|
||||||
mSelIcon->setAlphaRate(0.0f);
|
|
||||||
} else {
|
|
||||||
yesnoSelectStart();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void dMenu_save_c::saveSelectStart() {
|
void dMenu_save_c::saveSelectStart() {
|
||||||
#if TARGET_PC
|
|
||||||
dusk::menu_pointer::clear_deferred_activation(dusk::menu_pointer::Context::Save);
|
|
||||||
#endif
|
|
||||||
mDoAud_seStart(Z2SE_SY_CURSOR_OK, NULL, 0, 0);
|
mDoAud_seStart(Z2SE_SY_CURSOR_OK, NULL, 0, 0);
|
||||||
selectDataMoveAnmInitSet(SelOpenStartFrameTbl[mSelectedFile],
|
selectDataMoveAnmInitSet(SelOpenStartFrameTbl[mSelectedFile],
|
||||||
SelOpenEndFrameTbl[mSelectedFile]);
|
SelOpenEndFrameTbl[mSelectedFile]);
|
||||||
@@ -1949,17 +1851,6 @@ void dMenu_save_c::dataSelectAnmSet() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void dMenu_save_c::saveSelectMoveAnime() {
|
void dMenu_save_c::saveSelectMoveAnime() {
|
||||||
#if TARGET_PC
|
|
||||||
dusk::menu_pointer::begin_context(dusk::menu_pointer::Context::Save);
|
|
||||||
if (mSelectedFile != 0xFF &&
|
|
||||||
dusk::menu_pointer::hit_pane(mpSelData[mSelectedFile], 8.0f) &&
|
|
||||||
dusk::menu_pointer::consume_click())
|
|
||||||
{
|
|
||||||
dusk::menu_pointer::defer_activation(
|
|
||||||
dusk::menu_pointer::Context::Save,
|
|
||||||
pointer_target(s_pointerSaveSelectTarget, mSelectedFile));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
bool bookWakuAnmComplete = true;
|
bool bookWakuAnmComplete = true;
|
||||||
bool selWakuAnmComplete = true;
|
bool selWakuAnmComplete = true;
|
||||||
bool var_r29 = true;
|
bool var_r29 = true;
|
||||||
@@ -2009,26 +1900,12 @@ void dMenu_save_c::saveSelectMoveAnime() {
|
|||||||
if (mLastSelFile != 0xFF) {
|
if (mLastSelFile != 0xFF) {
|
||||||
mpSelData[mLastSelFile]->getPanePtr()->setAnimation((J2DAnmTransformKey*)NULL);
|
mpSelData[mLastSelFile]->getPanePtr()->setAnimation((J2DAnmTransformKey*)NULL);
|
||||||
}
|
}
|
||||||
#if TARGET_PC
|
|
||||||
if (dusk::menu_pointer::consume_deferred_activation(
|
|
||||||
dusk::menu_pointer::Context::Save,
|
|
||||||
pointer_target(s_pointerSaveSelectTarget, mSelectedFile))) {
|
|
||||||
saveSelectStart();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
mMenuProc = PROC_SAVE_SELECT;
|
mMenuProc = PROC_SAVE_SELECT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void dMenu_save_c::saveYesNoSelect() {
|
void dMenu_save_c::saveYesNoSelect() {
|
||||||
if (!mDoRst::isReset()) {
|
if (!mDoRst::isReset()) {
|
||||||
#if TARGET_PC
|
|
||||||
if (pointerYesNoSelect(false)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
stick->checkTrigger();
|
stick->checkTrigger();
|
||||||
|
|
||||||
if (mDoCPd_c::getTrigA(PAD_1)) {
|
if (mDoCPd_c::getTrigA(PAD_1)) {
|
||||||
@@ -2056,9 +1933,6 @@ void dMenu_save_c::saveYesNoSelect() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void dMenu_save_c::yesnoSelectStart() {
|
void dMenu_save_c::yesnoSelectStart() {
|
||||||
#if TARGET_PC
|
|
||||||
dusk::menu_pointer::clear_deferred_activation(dusk::menu_pointer::Context::Save);
|
|
||||||
#endif
|
|
||||||
if (mYesNoCursor != CURSOR_NO) {
|
if (mYesNoCursor != CURSOR_NO) {
|
||||||
mDoAud_seStart(Z2SE_SY_CURSOR_OK, NULL, 0, 0);
|
mDoAud_seStart(Z2SE_SY_CURSOR_OK, NULL, 0, 0);
|
||||||
mSelIcon->setAlphaRate(0.0f);
|
mSelIcon->setAlphaRate(0.0f);
|
||||||
@@ -2127,30 +2001,11 @@ void dMenu_save_c::yesnoSelectAnmSet(u8 param_0) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void dMenu_save_c::yesNoCursorMoveAnm() {
|
void dMenu_save_c::yesNoCursorMoveAnm() {
|
||||||
#if TARGET_PC
|
|
||||||
dusk::menu_pointer::begin_context(dusk::menu_pointer::Context::Save);
|
|
||||||
if (mYesNoCursor != 0xFF &&
|
|
||||||
dusk::menu_pointer::hit_pane(mpNoYes[mYesNoCursor], 8.0f) &&
|
|
||||||
dusk::menu_pointer::consume_click())
|
|
||||||
{
|
|
||||||
dusk::menu_pointer::defer_activation(
|
|
||||||
dusk::menu_pointer::Context::Save,
|
|
||||||
pointer_target(s_pointerYesNoSelectTarget, mYesNoCursor));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
bool selAnmComplete = yesnoSelectMoveAnm(0);
|
bool selAnmComplete = yesnoSelectMoveAnm(0);
|
||||||
bool wakuAnmComplete = yesnoWakuAlpahAnm(mYesNoPrevCursor);
|
bool wakuAnmComplete = yesnoWakuAlpahAnm(mYesNoPrevCursor);
|
||||||
|
|
||||||
if (selAnmComplete == true && wakuAnmComplete == true) {
|
if (selAnmComplete == true && wakuAnmComplete == true) {
|
||||||
yesnoCursorShow();
|
yesnoCursorShow();
|
||||||
#if TARGET_PC
|
|
||||||
if (dusk::menu_pointer::consume_deferred_activation(
|
|
||||||
dusk::menu_pointer::Context::Save,
|
|
||||||
pointer_target(s_pointerYesNoSelectTarget, mYesNoCursor))) {
|
|
||||||
yesnoSelectStart();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
mMenuProc = PROC_SAVE_YES_NO_SELECT;
|
mMenuProc = PROC_SAVE_YES_NO_SELECT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2326,12 +2181,6 @@ bool dMenu_save_c::errYesNoSelect(u8 param_0, u8 param_1) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
if (pointerYesNoSelect(true, param_0, param_1)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
stick->checkTrigger();
|
stick->checkTrigger();
|
||||||
|
|
||||||
if (mDoCPd_c::getTrigA(PAD_1)) {
|
if (mDoCPd_c::getTrigA(PAD_1)) {
|
||||||
|
|||||||
@@ -18,10 +18,6 @@
|
|||||||
#include "m_Do/m_Do_graphic.h"
|
#include "m_Do/m_Do_graphic.h"
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
#include "dusk/menu_pointer.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef void (dMenu_Skill_c::*initFunc)();
|
typedef void (dMenu_Skill_c::*initFunc)();
|
||||||
static initFunc map_init_process[] = {
|
static initFunc map_init_process[] = {
|
||||||
&dMenu_Skill_c::wait_init,
|
&dMenu_Skill_c::wait_init,
|
||||||
@@ -279,12 +275,6 @@ void dMenu_Skill_c::wait_init() {
|
|||||||
void dMenu_Skill_c::wait_move() {
|
void dMenu_Skill_c::wait_move() {
|
||||||
u8 oldIndex = mIndex;
|
u8 oldIndex = mIndex;
|
||||||
if (mDoGph_gInf_c::getFader()->getStatus() == 1) {
|
if (mDoGph_gInf_c::getFader()->getStatus() == 1) {
|
||||||
#if TARGET_PC
|
|
||||||
if (pointerWait()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (mDoCPd_c::getTrigB(PAD_1) != 0) {
|
if (mDoCPd_c::getTrigB(PAD_1) != 0) {
|
||||||
mpDrawCursor->offPlayAnime(0);
|
mpDrawCursor->offPlayAnime(0);
|
||||||
mStatus = 3;
|
mStatus = 3;
|
||||||
@@ -309,34 +299,6 @@ void dMenu_Skill_c::wait_move() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
bool dMenu_Skill_c::pointerWait() {
|
|
||||||
dusk::menu_pointer::begin_context(dusk::menu_pointer::Context::Collection);
|
|
||||||
for (u8 i = 0; i < mSkillNum; ++i) {
|
|
||||||
if (!dusk::menu_pointer::hit_pane(mpLetterParent[i], 8.0f)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mIndex != i) {
|
|
||||||
mIndex = i;
|
|
||||||
changeActiveColor();
|
|
||||||
Z2GetAudioMgr()->seStart(Z2SE_SY_CURSOR_ITEM, NULL, 0, 0, 1.0f, 1.0f, -1.0f,
|
|
||||||
-1.0f, 0);
|
|
||||||
}
|
|
||||||
if (dusk::menu_pointer::consume_click()) {
|
|
||||||
mProcess = PROC_WAIT_MOVE;
|
|
||||||
Z2GetAudioMgr()->seStart(Z2SE_SY_EXP_WIN_OPEN, NULL, 0, 0, 1.0f, 1.0f, -1.0f,
|
|
||||||
-1.0f, 0);
|
|
||||||
dMeter2Info_set2DVibration();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void dMenu_Skill_c::read_open_init() {
|
void dMenu_Skill_c::read_open_init() {
|
||||||
static const u32 i_id[7] = {
|
static const u32 i_id[7] = {
|
||||||
1716, 1715, 1717, 1718, 1719, 1720, 1721,
|
1716, 1715, 1717, 1718, 1719, 1720, 1721,
|
||||||
|
|||||||
+2
-17
@@ -663,15 +663,8 @@ void dMeter2_c::moveLife() {
|
|||||||
draw_life = true;
|
draw_life = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TARGET_PC
|
if (mLifeGaugeScale != g_drawHIO.mLifeParentScale) {
|
||||||
const f32 lifeGaugeScale =
|
mLifeGaugeScale = g_drawHIO.mLifeParentScale;
|
||||||
g_drawHIO.mLifeParentScale *
|
|
||||||
std::clamp(dusk::getSettings().game.hudScale.getValue(), 0.5f, 2.0f);
|
|
||||||
#else
|
|
||||||
const f32 lifeGaugeScale = g_drawHIO.mLifeParentScale;
|
|
||||||
#endif
|
|
||||||
if (mLifeGaugeScale != lifeGaugeScale) {
|
|
||||||
mLifeGaugeScale = lifeGaugeScale;
|
|
||||||
draw_life = true;
|
draw_life = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2973,15 +2966,7 @@ void dMeter2_c::alphaAnimeButtonCross() {
|
|||||||
field_0x190++;
|
field_0x190++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
#if TARGET_PC
|
|
||||||
if (dusk::getSettings().game.enableTouchControls) {
|
|
||||||
mpMeterDraw->setAlphaButtonCrossAnimeMin();
|
|
||||||
} else {
|
|
||||||
mpMeterDraw->setAlphaButtonCrossAnimeMax();
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
mpMeterDraw->setAlphaButtonCrossAnimeMax();
|
mpMeterDraw->setAlphaButtonCrossAnimeMax();
|
||||||
#endif
|
|
||||||
|
|
||||||
if (field_0x190 < 5) {
|
if (field_0x190 < 5) {
|
||||||
field_0x190++;
|
field_0x190++;
|
||||||
|
|||||||
@@ -25,7 +25,6 @@
|
|||||||
|
|
||||||
#if TARGET_PC
|
#if TARGET_PC
|
||||||
#include "dusk/settings.h"
|
#include "dusk/settings.h"
|
||||||
#include "dusk/ui/icon_provider.hpp"
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@@ -654,22 +653,10 @@ void dMeter2Draw_c::draw() {
|
|||||||
J2DGrafContext* graf_ctx = dComIfGp_getCurrentGrafPort();
|
J2DGrafContext* graf_ctx = dComIfGp_getCurrentGrafPort();
|
||||||
graf_ctx->setup2D();
|
graf_ctx->setup2D();
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
const bool touchControlsEnabled = dusk::getSettings().game.enableTouchControls;
|
|
||||||
if (touchControlsEnabled) {
|
|
||||||
mpButtonParent->hide();
|
|
||||||
} else {
|
|
||||||
mpButtonParent->show();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
mpScreen->draw(0.0f, 0.0f, graf_ctx);
|
mpScreen->draw(0.0f, 0.0f, graf_ctx);
|
||||||
drawKanteraScreen(1);
|
drawKanteraScreen(1);
|
||||||
drawKanteraScreen(2);
|
drawKanteraScreen(2);
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
if (!touchControlsEnabled) {
|
|
||||||
#endif
|
|
||||||
for (int i = 0; i < 2; i++) {
|
for (int i = 0; i < 2; i++) {
|
||||||
if (mpItemXY[i] != NULL) {
|
if (mpItemXY[i] != NULL) {
|
||||||
for (int j = 0; j < 3; j++) {
|
for (int j = 0; j < 3; j++) {
|
||||||
@@ -718,9 +705,6 @@ void dMeter2Draw_c::draw() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if TARGET_PC
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (mpLightDropParent->getAlphaRate() != 0.0f) {
|
if (mpLightDropParent->getAlphaRate() != 0.0f) {
|
||||||
f32 var_f28 = g_drawHIO.mLightDrop.mPikariScaleNormal;
|
f32 var_f28 = g_drawHIO.mLightDrop.mPikariScaleNormal;
|
||||||
@@ -803,11 +787,7 @@ void dMeter2Draw_c::draw() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
if (!touchControlsEnabled && field_0x738 > 0.0f) {
|
|
||||||
#else
|
|
||||||
if (field_0x738 > 0.0f) {
|
if (field_0x738 > 0.0f) {
|
||||||
#endif
|
|
||||||
drawPikari(mpButtonMidona, &field_0x738, g_drawHIO.mMidnaIconPikariScale,
|
drawPikari(mpButtonMidona, &field_0x738, g_drawHIO.mMidnaIconPikariScale,
|
||||||
g_drawHIO.mMidnaIconPikariFrontOuter, g_drawHIO.mMidnaIconPikariFrontInner,
|
g_drawHIO.mMidnaIconPikariFrontOuter, g_drawHIO.mMidnaIconPikariFrontInner,
|
||||||
g_drawHIO.mMidnaIconPikariBackOuter, g_drawHIO.mMidnaIconPikariBackInner,
|
g_drawHIO.mMidnaIconPikariBackOuter, g_drawHIO.mMidnaIconPikariBackInner,
|
||||||
@@ -2472,11 +2452,6 @@ void dMeter2Draw_c::drawButtonB(u8 i_action, bool param_1, f32 i_posX, f32 i_pos
|
|||||||
SAFE_STRCPY(static_cast<J2DTextBox*>(mpBText[i]->getPanePtr())->getStringPtr(), mp_string);
|
SAFE_STRCPY(static_cast<J2DTextBox*>(mpBText[i]->getPanePtr())->getStringPtr(), mp_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
if (dusk::getSettings().game.enableTouchControls) {
|
|
||||||
mpScreen->search(MULTI_CHAR('item_b_n'))->hide();
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
if (i_action == 0x26 || i_action == 0x2E) {
|
if (i_action == 0x26 || i_action == 0x2E) {
|
||||||
mpScreen->search(MULTI_CHAR('item_b_n'))->show();
|
mpScreen->search(MULTI_CHAR('item_b_n'))->show();
|
||||||
var_r31 = 1;
|
var_r31 = 1;
|
||||||
@@ -2754,12 +2729,6 @@ void dMeter2Draw_c::drawButtonXY(int i_no, u8 i_itemNo, u8 i_action, bool param_
|
|||||||
mpTextXY[i_no]->scale(g_drawHIO.mButtonXYTextScale, g_drawHIO.mButtonXYTextScale);
|
mpTextXY[i_no]->scale(g_drawHIO.mButtonXYTextScale, g_drawHIO.mButtonXYTextScale);
|
||||||
mpTextXY[i_no]->paneTrans(g_drawHIO.mButtonXYTextPosX, g_drawHIO.mButtonXYTextPosY);
|
mpTextXY[i_no]->paneTrans(g_drawHIO.mButtonXYTextPosX, g_drawHIO.mButtonXYTextPosY);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
if (dusk::getSettings().game.enableTouchControls) {
|
|
||||||
mpScreen->search(tag[i_no])->hide();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3325,10 +3294,6 @@ void dMeter2Draw_c::setButtonIconMidonaAlpha(u32 param_0) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mpButtonXY[2]->setAlpha(255.0f * field_0x724 * temp_f30_2);
|
mpButtonXY[2]->setAlpha(255.0f * field_0x724 * temp_f30_2);
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
dusk::ui::update_midna_icon_texture(mpButtonMidona != NULL ? mpButtonMidona->getPanePtr() : NULL);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void dMeter2Draw_c::setButtonIconAlpha(int i_no, u8 unused0, u32 unused1, bool unused2) {
|
void dMeter2Draw_c::setButtonIconAlpha(int i_no, u8 unused0, u32 unused1, bool unused2) {
|
||||||
|
|||||||
+2
-57
@@ -22,10 +22,6 @@
|
|||||||
#endif
|
#endif
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
#include "dusk/action_bindings.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (PLATFORM_WII || PLATFORM_SHIELD)
|
#if (PLATFORM_WII || PLATFORM_SHIELD)
|
||||||
dMeter_map_HIO_c g_meter_mapHIO;
|
dMeter_map_HIO_c g_meter_mapHIO;
|
||||||
#endif
|
#endif
|
||||||
@@ -543,12 +539,6 @@ void dMeterMap_c::_move(u32 param_0) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
if (mMap->refreshTextureSize()) {
|
|
||||||
mMapJ2DPicture->changeTexture(mMap->getResTIMGPointer(), 0);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int stayNo = dComIfGp_roomControl_getStayNo();
|
int stayNo = dComIfGp_roomControl_getStayNo();
|
||||||
|
|
||||||
field_0x14 = param_0;
|
field_0x14 = param_0;
|
||||||
@@ -742,38 +732,7 @@ void dMeterMap_c::ctrlShowMap() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} else if (!mDoCPd_c::getTrigUp(PAD_1) && !mDoCPd_c::getTrigDown(PAD_1)) {
|
||||||
#if TARGET_PC
|
|
||||||
else if (!isEventRunCheck() &&
|
|
||||||
(dMeter2Info_getMapStatus() == 0 || dMeter2Info_getMapStatus() == 1) &&
|
|
||||||
!dMeter2Info_isSub2DStatus(1) && (isFmapScreen() || isDmapScreen()) &&
|
|
||||||
dusk::getActionBindTrig(dusk::ActionBinds::OPEN_MAP_SCREEN, PAD_1))
|
|
||||||
{
|
|
||||||
dMeter2Info_setMapStatus(2);
|
|
||||||
dMeter2Info_setMapKeyDirection(0x400);
|
|
||||||
Z2GetAudioMgr()->seStart(Z2SE_SY_MAP_OPEN_S, NULL, 0, 0, 1.0f, 1.0f, -1.0f,
|
|
||||||
-1.0f, 0);
|
|
||||||
dMeter2Info_set2DVibration();
|
|
||||||
} else if (!isEventRunCheck() &&
|
|
||||||
(dMeter2Info_getMapStatus() == 0 || dMeter2Info_getMapStatus() == 1) &&
|
|
||||||
isEnableDispMapAndMapDispSizeTypeNo() &&
|
|
||||||
dusk::getActionBindTrig(dusk::ActionBinds::TOGGLE_MINIMAP, PAD_1))
|
|
||||||
{
|
|
||||||
if (isDispPosInsideFlg()) {
|
|
||||||
setDispPosOutsideFlg_SE_On();
|
|
||||||
Z2GetAudioMgr()->seStart(Z2SE_SY_MAP_CLOSE_S, NULL, 0, 0, 1.0f, 1.0f, -1.0f,
|
|
||||||
-1.0f, 0);
|
|
||||||
dMeter2Info_setMapStatus(0);
|
|
||||||
} else {
|
|
||||||
setDispPosInsideFlg_SE_On();
|
|
||||||
Z2GetAudioMgr()->seStart(Z2SE_SY_MAP_OPEN_S, NULL, 0, 0, 1.0f, 1.0f, -1.0f,
|
|
||||||
-1.0f, 0);
|
|
||||||
dMeter2Info_set2DVibration();
|
|
||||||
dMeter2Info_setMapStatus(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
else if (!mDoCPd_c::getTrigUp(PAD_1) && !mDoCPd_c::getTrigDown(PAD_1)) {
|
|
||||||
keyCheck();
|
keyCheck();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -868,21 +827,7 @@ void dMeterMap_c::meter_map_move(u32 param_0) {
|
|||||||
dMeter2Info_set2DVibration();
|
dMeter2Info_set2DVibration();
|
||||||
}
|
}
|
||||||
dMeter2Info_resetPauseStatus();
|
dMeter2Info_resetPauseStatus();
|
||||||
}
|
} else if (
|
||||||
#if TARGET_PC
|
|
||||||
else if (!dComIfGp_event_runCheck() && !dMsgObject_isTalkNowCheck() &&
|
|
||||||
(dMeter2Info_getMapStatus() == 0 || dMeter2Info_getMapStatus() == 1) &&
|
|
||||||
!dMeter2Info_isSub2DStatus(1) && (isFmapScreen() || isDmapScreen()) &&
|
|
||||||
dusk::getActionBindTrig(dusk::ActionBinds::OPEN_MAP_SCREEN, PAD_1))
|
|
||||||
{
|
|
||||||
dMeter2Info_setMapStatus(2);
|
|
||||||
dMeter2Info_setMapKeyDirection(0x400);
|
|
||||||
Z2GetAudioMgr()->seStart(Z2SE_SY_MAP_OPEN_S, NULL, 0, 0, 1.0f, 1.0f, -1.0f,
|
|
||||||
-1.0f, 0);
|
|
||||||
dMeter2Info_set2DVibration();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
else if (
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
dMw_RIGHT_TRIGGER() &&
|
dMw_RIGHT_TRIGGER() &&
|
||||||
#else
|
#else
|
||||||
|
|||||||
@@ -13,7 +13,6 @@
|
|||||||
#include "JSystem/JUtility/JUTFont.h"
|
#include "JSystem/JUtility/JUTFont.h"
|
||||||
|
|
||||||
#if TARGET_PC
|
#if TARGET_PC
|
||||||
#include "dusk/menu_pointer.h"
|
|
||||||
#include "dusk/scope_guard.hpp"
|
#include "dusk/scope_guard.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -576,20 +575,6 @@ void jmessage_tReference::pageSend() {
|
|||||||
|
|
||||||
void jmessage_tReference::selectMessage() {
|
void jmessage_tReference::selectMessage() {
|
||||||
if (mSelectNum != 0) {
|
if (mSelectNum != 0) {
|
||||||
#if TARGET_PC
|
|
||||||
u8 pointerChoice = 0xFF;
|
|
||||||
if (dusk::menu_pointer::get_dialog_choice(pointerChoice) && pointerChoice < mSelectNum &&
|
|
||||||
pointerChoice != mSelectPos)
|
|
||||||
{
|
|
||||||
mSelectPos = pointerChoice;
|
|
||||||
if (mSelectType != 0) {
|
|
||||||
getObjectPtr()->getSequenceProcessor()->calcStringLength();
|
|
||||||
}
|
|
||||||
Z2GetAudioMgr()->seStart(Z2SE_SY_TALK_CURSOR, NULL, 0, 0, 1.0f, 1.0f, -1.0f,
|
|
||||||
-1.0f, 0);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
mpStick->checkTrigger();
|
mpStick->checkTrigger();
|
||||||
|
|
||||||
if (mSelectType == 0) {
|
if (mSelectType == 0) {
|
||||||
|
|||||||
+2
-18
@@ -26,13 +26,12 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
#include "JSystem/JKernel/JKRExpHeap.h"
|
#include "JSystem/JKernel/JKRExpHeap.h"
|
||||||
|
#include "dusk/version.hpp"
|
||||||
#include "m_Do/m_Do_controller_pad.h"
|
#include "m_Do/m_Do_controller_pad.h"
|
||||||
#include "m_Do/m_Do_lib.h"
|
#include "m_Do/m_Do_lib.h"
|
||||||
|
|
||||||
#if TARGET_PC
|
#if TARGET_PC
|
||||||
#include "dusk/menu_pointer.h"
|
|
||||||
#include "dusk/settings.h"
|
#include "dusk/settings.h"
|
||||||
#include "dusk/version.hpp"
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@@ -1124,20 +1123,7 @@ void dMsgObject_c::selectProc() {
|
|||||||
dComIfGp_setAStatusForce(0x2a, 0);
|
dComIfGp_setAStatusForce(0x2a, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if TARGET_PC
|
if (mDoCPd_c::getTrigA(0)) {
|
||||||
jmessage_tReference* pRef = (jmessage_tReference*)mpRenProc->getReference();
|
|
||||||
u8 pointerChoice = 0xFF;
|
|
||||||
bool pointerConfirm = dusk::menu_pointer::consume_dialog_click(pointerChoice) &&
|
|
||||||
pointerChoice < pRef->getSelectNum();
|
|
||||||
if (pointerConfirm) {
|
|
||||||
pRef->setSelectPos(pointerChoice);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (mDoCPd_c::getTrigA(0)
|
|
||||||
#if TARGET_PC
|
|
||||||
|| pointerConfirm
|
|
||||||
#endif
|
|
||||||
) {
|
|
||||||
if (getSelectCursorPosLocal() != 0xff) {
|
if (getSelectCursorPosLocal() != 0xff) {
|
||||||
field_0x1a3 = 1;
|
field_0x1a3 = 1;
|
||||||
}
|
}
|
||||||
@@ -1159,9 +1145,7 @@ void dMsgObject_c::selectProc() {
|
|||||||
}
|
}
|
||||||
field_0x1a3 = 2;
|
field_0x1a3 = 2;
|
||||||
}
|
}
|
||||||
#ifndef TARGET_PC
|
|
||||||
jmessage_tReference* pRef = (jmessage_tReference*)mpRenProc->getReference();
|
jmessage_tReference* pRef = (jmessage_tReference*)mpRenProc->getReference();
|
||||||
#endif
|
|
||||||
if (getStatusLocal() == 8) {
|
if (getStatusLocal() == 8) {
|
||||||
if (isMidonaMessage() && field_0x1a3 != 0) {
|
if (isMidonaMessage() && field_0x1a3 != 0) {
|
||||||
if (field_0x1a3 == 2 && getSelectCancelPos() == 3) {
|
if (field_0x1a3 == 2 && getSelectCancelPos() == 3) {
|
||||||
|
|||||||
@@ -16,17 +16,6 @@
|
|||||||
#include "d/d_msg_object.h"
|
#include "d/d_msg_object.h"
|
||||||
#include "d/d_pane_class.h"
|
#include "d/d_pane_class.h"
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
#include "dusk/menu_pointer.h"
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
bool hit_choice_pane(CPaneMgr* pane, f32 padding) {
|
|
||||||
return pane != NULL && pane->getPanePtr() != NULL && pane->getPanePtr()->isVisible() &&
|
|
||||||
dusk::menu_pointer::hit_pane(pane, padding);
|
|
||||||
}
|
|
||||||
} // namespace
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef void (dMsgScrn3Select_c::*processFn)();
|
typedef void (dMsgScrn3Select_c::*processFn)();
|
||||||
processFn process[] = {
|
processFn process[] = {
|
||||||
&dMsgScrn3Select_c::open1Proc, &dMsgScrn3Select_c::open2Proc, &dMsgScrn3Select_c::waitProc,
|
&dMsgScrn3Select_c::open1Proc, &dMsgScrn3Select_c::open2Proc, &dMsgScrn3Select_c::waitProc,
|
||||||
@@ -481,9 +470,6 @@ bool dMsgScrn3Select_c::selAnimeMove(u8 i_selNum, u8 param_1, bool param_2) {
|
|||||||
mSelNum = i_selNum;
|
mSelNum = i_selNum;
|
||||||
field_0x114 = 0;
|
field_0x114 = 0;
|
||||||
field_0x108 = param_2;
|
field_0x108 = param_2;
|
||||||
#if TARGET_PC
|
|
||||||
pointerMove();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
(this->*process[mProcess])();
|
(this->*process[mProcess])();
|
||||||
|
|
||||||
@@ -532,47 +518,6 @@ bool dMsgScrn3Select_c::selAnimeMove(u8 i_selNum, u8 param_1, bool param_2) {
|
|||||||
return mProcess == PROC_SELECT_e ? TRUE : FALSE;
|
return mProcess == PROC_SELECT_e ? TRUE : FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TARGET_PC
|
|
||||||
bool dMsgScrn3Select_c::pointerMove() {
|
|
||||||
dusk::menu_pointer::begin_context(dusk::menu_pointer::Context::Dialog);
|
|
||||||
mDPDPoint = 0xFF;
|
|
||||||
|
|
||||||
const u8 firstPane = mSelNum == 2 ? 1 : 0;
|
|
||||||
for (u8 choice = 0; choice < mSelNum; ++choice) {
|
|
||||||
const u8 paneIndex = firstPane + choice;
|
|
||||||
if (paneIndex >= 3) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: this sucks and should be replaced with Wii mpTouchArea
|
|
||||||
bool hit = hit_choice_pane(mpSel_c[paneIndex], 8.0f) ||
|
|
||||||
hit_choice_pane(mpTmSel_c[paneIndex], 24.0f) ||
|
|
||||||
hit_choice_pane(mpTmrSel_c[paneIndex], 24.0f) ||
|
|
||||||
hit_choice_pane(mpKahen_c[paneIndex], 8.0f) ||
|
|
||||||
hit_choice_pane(mpCursor_c[paneIndex], 8.0f);
|
|
||||||
for (int i = 0; i < 5 && !hit; ++i) {
|
|
||||||
hit = hit_choice_pane(mpSelCldw_c[i][paneIndex], 8.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!hit) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
mDPDPoint = choice;
|
|
||||||
field_0x110 = paneIndex;
|
|
||||||
dusk::menu_pointer::set_dialog_choice(choice, dusk::menu_pointer::state().clicked);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool dMsgScrn3Select_c::consumePointerClick() {
|
|
||||||
u8 choice = 0xFF;
|
|
||||||
return dusk::menu_pointer::consume_dialog_click(choice);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool dMsgScrn3Select_c::selAnimeEnd() {
|
bool dMsgScrn3Select_c::selAnimeEnd() {
|
||||||
if (mProcess == PROC_MAX_e) {
|
if (mProcess == PROC_MAX_e) {
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -643,10 +643,6 @@ f32 dMsgScrnExplain_c::getAlphaRatio() {
|
|||||||
bool dMsgScrnExplain_c::checkTriggerA() {
|
bool dMsgScrnExplain_c::checkTriggerA() {
|
||||||
if (mDoCPd_c::getTrigA(PAD_1)) {
|
if (mDoCPd_c::getTrigA(PAD_1)) {
|
||||||
return true;
|
return true;
|
||||||
#if TARGET_PC
|
|
||||||
} else if (mpSelect_c != NULL && mpSelect_c->consumePointerClick()) {
|
|
||||||
return true;
|
|
||||||
#endif
|
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1536,6 +1536,27 @@ dStage_objectNameInf* dStage_searchName(char const* objName) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if TARGET_PC
|
||||||
|
dStage_objectNameInf* dStage_searchNameCI(char const* objName) {
|
||||||
|
dStage_objectNameInf* obj = l_objectName;
|
||||||
|
|
||||||
|
for (u32 i = 0; i < ARRAY_SIZEU(l_objectName); i++) {
|
||||||
|
const char* a = obj->name;
|
||||||
|
const char* b = objName;
|
||||||
|
while (*a && *b && tolower((unsigned char)*a) == tolower((unsigned char)*b)) {
|
||||||
|
++a;
|
||||||
|
++b;
|
||||||
|
}
|
||||||
|
if (*a == '\0' && *b == '\0') {
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
obj++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
const char* dStage_getName(s16 procName, s8 argument) {
|
const char* dStage_getName(s16 procName, s8 argument) {
|
||||||
static char tmp_name[dStage_NAME_LENGTH];
|
static char tmp_name[dStage_NAME_LENGTH];
|
||||||
|
|
||||||
|
|||||||
+13
-15
@@ -181,24 +181,22 @@ void OSWaitCond(OSCond* cond, OSMutex* mutex) {
|
|||||||
mutex->count = 0;
|
mutex->count = 0;
|
||||||
mutex->thread = nullptr;
|
mutex->thread = nullptr;
|
||||||
|
|
||||||
// Keep one recursion level held so cv.wait() is what releases the mutex;
|
// Unlock the recursive mutex the same number of times it was locked
|
||||||
// fully unlocking before the wait opens a window where a signal is lost.
|
for (s32 i = 0; i < savedCount; i++) {
|
||||||
if (savedCount >= 1) {
|
mutexData.nativeMutex.unlock();
|
||||||
for (s32 i = 1; i < savedCount; i++) {
|
}
|
||||||
mutexData.nativeMutex.unlock();
|
|
||||||
}
|
// Wait on the condition variable
|
||||||
std::unique_lock lock(mutexData.nativeMutex, std::adopt_lock);
|
{
|
||||||
condData.cv.wait(lock);
|
std::unique_lock<std::recursive_mutex> lock(mutexData.nativeMutex);
|
||||||
lock.release();
|
|
||||||
for (s32 i = 1; i < savedCount; i++) {
|
|
||||||
mutexData.nativeMutex.lock();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Mutex wasn't held on entry (contract violation); wait anyway.
|
|
||||||
std::unique_lock lock(mutexData.nativeMutex);
|
|
||||||
condData.cv.wait(lock);
|
condData.cv.wait(lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Re-lock the recursive mutex the same number of times
|
||||||
|
for (s32 i = 0; i < savedCount; i++) {
|
||||||
|
mutexData.nativeMutex.lock();
|
||||||
|
}
|
||||||
|
|
||||||
// Restore GC mutex state
|
// Restore GC mutex state
|
||||||
mutex->thread = currentThread;
|
mutex->thread = currentThread;
|
||||||
mutex->count = savedCount;
|
mutex->count = savedCount;
|
||||||
|
|||||||
@@ -8,19 +8,10 @@ namespace dusk {
|
|||||||
|
|
||||||
static std::array<std::array<ActionBindPressData, static_cast<int>(ActionBinds::COUNT)>, PAD_CHANMAX> actionPressData{};
|
static std::array<std::array<ActionBindPressData, static_cast<int>(ActionBinds::COUNT)>, PAD_CHANMAX> actionPressData{};
|
||||||
|
|
||||||
struct VirtualActionBindData {
|
|
||||||
bool pressed = false;
|
|
||||||
bool available = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
static std::array<std::array<VirtualActionBindData, static_cast<int>(ActionBinds::COUNT)>, PAD_CHANMAX> virtualActionData{};
|
|
||||||
|
|
||||||
ActionBindsMap& getActionBinds() {
|
ActionBindsMap& getActionBinds() {
|
||||||
static ActionBindsMap actionBinds = {
|
static ActionBindsMap actionBinds = {
|
||||||
{ActionBinds::FIRST_PERSON_CAMERA, {&getSettings().actionBindings.firstPersonCamera, "First Person Camera"}},
|
{ActionBinds::FIRST_PERSON_CAMERA, {&getSettings().actionBindings.firstPersonCamera, "First Person Camera"}},
|
||||||
{ActionBinds::CALL_MIDNA, {&getSettings().actionBindings.callMidna, "Call Midna"}},
|
{ActionBinds::CALL_MIDNA, {&getSettings().actionBindings.callMidna, "Call Midna"}},
|
||||||
{ActionBinds::OPEN_MAP_SCREEN, {&getSettings().actionBindings.openMapScreen, "Open Map Screen"}},
|
|
||||||
{ActionBinds::TOGGLE_MINIMAP, {&getSettings().actionBindings.toggleMinimap, "Toggle Minimap"}},
|
|
||||||
{ActionBinds::OPEN_DUSKLIGHT_MENU, {&getSettings().actionBindings.openDusklightMenu, "Open Dusklight Menu"}},
|
{ActionBinds::OPEN_DUSKLIGHT_MENU, {&getSettings().actionBindings.openDusklightMenu, "Open Dusklight Menu"}},
|
||||||
{ActionBinds::TURBO_SPEED_BUTTON, {&getSettings().actionBindings.turboSpeedButton, "Turbo Speed Button"}},
|
{ActionBinds::TURBO_SPEED_BUTTON, {&getSettings().actionBindings.turboSpeedButton, "Turbo Speed Button"}},
|
||||||
};
|
};
|
||||||
@@ -34,10 +25,6 @@ bool isActionBound(ActionBinds action, u32 port) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (port < PAD_CHANMAX && virtualActionData[port][static_cast<int>(action)].available) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return getActionBindButton(action, port) != PAD_NATIVE_BUTTON_INVALID;
|
return getActionBindButton(action, port) != PAD_NATIVE_BUTTON_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,71 +41,43 @@ void updateActionBindings() {
|
|||||||
// If the action isn't bound, or if documents are visible and the action isn't
|
// If the action isn't bound, or if documents are visible and the action isn't
|
||||||
// opening the dusklight menu, don't update. Otherwise, we may accidentally
|
// opening the dusklight menu, don't update. Otherwise, we may accidentally
|
||||||
// perform actions while the dusklight menu is open.
|
// perform actions while the dusklight menu is open.
|
||||||
const int button = boundAction.configVars->at(port);
|
if (!isActionBound(action, port) ||
|
||||||
const bool virtualAvailable = virtualActionData[port][static_cast<int>(action)].available;
|
|
||||||
if ((button == PAD_NATIVE_BUTTON_INVALID && !virtualAvailable) ||
|
|
||||||
(ui::any_document_visible() && action != ActionBinds::OPEN_DUSKLIGHT_MENU)) {
|
(ui::any_document_visible() && action != ActionBinds::OPEN_DUSKLIGHT_MENU)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (button != PAD_NATIVE_BUTTON_INVALID) {
|
int button = boundAction.configVars->at(port);
|
||||||
// If keyboard is active for this port
|
|
||||||
u32 count = 0;
|
// If keyboard is active for this port
|
||||||
if (PADGetKeyButtonBindings(port, &count) != nullptr) {
|
u32 count = 0;
|
||||||
int numKeys = 0;
|
if (PADGetKeyButtonBindings(port, &count) != nullptr) {
|
||||||
const bool* kbState = SDL_GetKeyboardState(&numKeys);
|
int numKeys = 0;
|
||||||
if (kbState[button]) {
|
const bool* kbState = SDL_GetKeyboardState(&numKeys);
|
||||||
|
if (kbState[button]) {
|
||||||
|
actionPressData[port][static_cast<int>(action)].pressedCurFrame = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// If controller is active
|
||||||
|
auto controller = aurora::input::get_controller_for_player(port);
|
||||||
|
if (controller) {
|
||||||
|
if (SDL_GetGamepadButton(controller->m_controller, static_cast<SDL_GamepadButton>(button))) {
|
||||||
actionPressData[port][static_cast<int>(action)].pressedCurFrame = true;
|
actionPressData[port][static_cast<int>(action)].pressedCurFrame = true;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// If controller is active
|
|
||||||
auto controller = aurora::input::get_controller_for_player(port);
|
|
||||||
if (controller) {
|
|
||||||
if (SDL_GetGamepadButton(controller->m_controller, static_cast<SDL_GamepadButton>(button))) {
|
|
||||||
actionPressData[port][static_cast<int>(action)].pressedCurFrame = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& [action, _] : getActionBinds()) {
|
|
||||||
const auto& virtualAction = virtualActionData[port][static_cast<int>(action)];
|
|
||||||
if (virtualAction.available && virtualAction.pressed && !ui::any_document_visible()) {
|
|
||||||
actionPressData[port][static_cast<int>(action)].pressedCurFrame = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setVirtualActionBind(ActionBinds action, u32 port, bool pressed, bool available) {
|
|
||||||
if (port >= PAD_CHANMAX) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
virtualActionData[port][static_cast<int>(action)] = {
|
|
||||||
.pressed = pressed,
|
|
||||||
.available = available,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
void clearVirtualActionBind(ActionBinds action, u32 port) {
|
|
||||||
if (port >= PAD_CHANMAX) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
virtualActionData[port][static_cast<int>(action)] = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
void clearAllVirtualActionBinds() {
|
|
||||||
virtualActionData = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
bool getActionBindTrig(ActionBinds action, u32 port) {
|
bool getActionBindTrig(ActionBinds action, u32 port) {
|
||||||
return actionPressData[port][static_cast<int>(action)].pressedCurFrame &&
|
return isActionBound(action, port) &&
|
||||||
|
actionPressData[port][static_cast<int>(action)].pressedCurFrame &&
|
||||||
!actionPressData[port][static_cast<int>(action)].pressedPrevFrame;
|
!actionPressData[port][static_cast<int>(action)].pressedPrevFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool getActionBindHold(ActionBinds action, u32 port) {
|
bool getActionBindHold(ActionBinds action, u32 port) {
|
||||||
return actionPressData[port][static_cast<int>(action)].pressedCurFrame &&
|
return isActionBound(action, port) &&
|
||||||
|
actionPressData[port][static_cast<int>(action)].pressedCurFrame &&
|
||||||
actionPressData[port][static_cast<int>(action)].pressedPrevFrame;
|
actionPressData[port][static_cast<int>(action)].pressedPrevFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,74 +0,0 @@
|
|||||||
#include "dusk/android_frame_rate.hpp"
|
|
||||||
|
|
||||||
#if defined(TARGET_ANDROID) || defined(__ANDROID__) || defined(ANDROID)
|
|
||||||
#include "dusk/settings.h"
|
|
||||||
|
|
||||||
#include <SDL3/SDL_system.h>
|
|
||||||
#include <jni.h>
|
|
||||||
|
|
||||||
namespace dusk::android {
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
float preferred_surface_frame_rate() {
|
|
||||||
switch (getSettings().game.enableFrameInterpolation.getValue()) {
|
|
||||||
case FrameInterpMode::Off:
|
|
||||||
return 30.0f;
|
|
||||||
case FrameInterpMode::Unlimited:
|
|
||||||
default:
|
|
||||||
return 0.0f;
|
|
||||||
case FrameInterpMode::Capped:
|
|
||||||
return static_cast<float>(getSettings().video.maxFrameRate.getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool clear_pending_exception(JNIEnv* env) {
|
|
||||||
if (env == nullptr || !env->ExceptionCheck()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
env->ExceptionClear();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
void update_surface_frame_rate() {
|
|
||||||
auto* env = static_cast<JNIEnv*>(SDL_GetAndroidJNIEnv());
|
|
||||||
if (env == nullptr) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
jobject activity = static_cast<jobject>(SDL_GetAndroidActivity());
|
|
||||||
if (activity == nullptr || clear_pending_exception(env)) {
|
|
||||||
if (activity != nullptr) {
|
|
||||||
env->DeleteLocalRef(activity);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
jclass activityClass = env->GetObjectClass(activity);
|
|
||||||
if (activityClass == nullptr || clear_pending_exception(env)) {
|
|
||||||
env->DeleteLocalRef(activity);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
jmethodID setPreferredFrameRate =
|
|
||||||
env->GetMethodID(activityClass, "setPreferredSurfaceFrameRate", "(F)V");
|
|
||||||
env->DeleteLocalRef(activityClass);
|
|
||||||
if (setPreferredFrameRate == nullptr || clear_pending_exception(env)) {
|
|
||||||
env->DeleteLocalRef(activity);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
jvalue args[1]{};
|
|
||||||
args[0].f = preferred_surface_frame_rate();
|
|
||||||
env->CallVoidMethodA(activity, setPreferredFrameRate, args);
|
|
||||||
env->DeleteLocalRef(activity);
|
|
||||||
clear_pending_exception(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace dusk::android
|
|
||||||
#else
|
|
||||||
namespace dusk::android {
|
|
||||||
void update_surface_frame_rate() {}
|
|
||||||
} // namespace dusk::android
|
|
||||||
#endif
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
namespace dusk::android {
|
|
||||||
|
|
||||||
void update_surface_frame_rate();
|
|
||||||
|
|
||||||
} // namespace dusk::android
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
const char* __asan_default_options(void) {
|
|
||||||
return "abort_on_error=1:symbolize=1:intercept_memcmp=0:detect_leaks=0";
|
|
||||||
}
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
#include "dusk/batch.hpp"
|
|
||||||
#include "dusk/logging.h"
|
|
||||||
|
|
||||||
#include <aurora/dl.hpp>
|
|
||||||
#include <dolphin/gx/GXEnum.h>
|
|
||||||
|
|
||||||
namespace dusk::batch {
|
|
||||||
|
|
||||||
void decode_leaf_template(const u8* dl, u32 size, LeafTemplate& out) {
|
|
||||||
out.vtxCount = 0;
|
|
||||||
out.posRefCount = 0;
|
|
||||||
bool posSeen[256] = {};
|
|
||||||
|
|
||||||
static constexpr GXVtxDescList kLeafDesc[] = {
|
|
||||||
{GX_VA_POS, GX_INDEX8},
|
|
||||||
{GX_VA_NRM, GX_INDEX8},
|
|
||||||
{GX_VA_CLR0, GX_INDEX8},
|
|
||||||
{GX_VA_TEX0, GX_INDEX8},
|
|
||||||
{GX_VA_NULL, GX_NONE},
|
|
||||||
};
|
|
||||||
|
|
||||||
aurora::gx::dl::Reader reader{dl, size, kLeafDesc};
|
|
||||||
while (const auto cmd = reader.next()) {
|
|
||||||
if (cmd->kind == aurora::gx::dl::Command::Kind::Passthrough) {
|
|
||||||
if (cmd->data[0] != GX_NOP) {
|
|
||||||
DuskLog.fatal("decode_leaf_template: unexpected opcode {:#x}", cmd->data[0]);
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (cmd->kind != aurora::gx::dl::Command::Kind::Draw) {
|
|
||||||
DuskLog.fatal("decode_leaf_template: unexpected pre-optimized draw");
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto& draw = cmd->draw;
|
|
||||||
bool overflow = false;
|
|
||||||
const bool expanded =
|
|
||||||
aurora::gx::dl::expand_triangles(draw.prim, draw.vtxCount, [&](u16 i0, u16 i1, u16 i2) {
|
|
||||||
if (overflow || out.vtxCount + 3 > LeafTemplate::kMaxVtx) {
|
|
||||||
overflow = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (const u16 elem : {i0, i1, i2}) {
|
|
||||||
LeafTemplate::Vtx& v = out.vtx[out.vtxCount++];
|
|
||||||
v.pos = draw.attr_idx(elem, GX_VA_POS);
|
|
||||||
v.nrm = draw.attr_idx(elem, GX_VA_NRM);
|
|
||||||
v.clr = draw.attr_idx(elem, GX_VA_CLR0);
|
|
||||||
v.tex = draw.attr_idx(elem, GX_VA_TEX0);
|
|
||||||
if (!posSeen[v.pos]) {
|
|
||||||
posSeen[v.pos] = true;
|
|
||||||
if (out.posRefCount >= LeafTemplate::kMaxPosRefs) {
|
|
||||||
overflow = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
out.posRefs[out.posRefCount++] = v.pos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (!expanded) {
|
|
||||||
DuskLog.fatal("decode_leaf_template: untriangulable draw (prim {:#x}, {} verts)",
|
|
||||||
static_cast<u32>(draw.prim), draw.vtxCount);
|
|
||||||
}
|
|
||||||
if (overflow) {
|
|
||||||
DuskLog.fatal("decode_leaf_template: template overflow ({} verts, {} positions)",
|
|
||||||
out.vtxCount, out.posRefCount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (reader.failed()) {
|
|
||||||
DuskLog.fatal("decode_leaf_template: failed to walk display list");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace dusk::batch
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <dolphin/types.h>
|
|
||||||
|
|
||||||
namespace dusk::batch {
|
|
||||||
|
|
||||||
struct LeafTemplate {
|
|
||||||
static constexpr u32 kMaxVtx = 192;
|
|
||||||
static constexpr u32 kMaxPosRefs = 64;
|
|
||||||
|
|
||||||
struct Vtx {
|
|
||||||
u8 pos;
|
|
||||||
u8 nrm;
|
|
||||||
u8 clr;
|
|
||||||
u8 tex;
|
|
||||||
};
|
|
||||||
Vtx vtx[kMaxVtx];
|
|
||||||
u16 vtxCount = 0;
|
|
||||||
u8 posRefs[kMaxPosRefs];
|
|
||||||
u8 posRefCount = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
void decode_leaf_template(const u8* dl, u32 size, LeafTemplate& out);
|
|
||||||
|
|
||||||
} // namespace dusk
|
|
||||||
@@ -0,0 +1,617 @@
|
|||||||
|
#include "commands.hpp"
|
||||||
|
|
||||||
|
#include "JSystem/JUtility/JUTGamePad.h"
|
||||||
|
#include "SSystem/SComponent/c_sxyz.h"
|
||||||
|
#include "SSystem/SComponent/c_xyz.h"
|
||||||
|
#include "c/c_damagereaction.h"
|
||||||
|
#include "d/actor/d_a_alink.h"
|
||||||
|
#include "d/d_com_inf_game.h"
|
||||||
|
#include "d/d_kankyo.h"
|
||||||
|
#include "d/d_stage.h"
|
||||||
|
#include "dusk/game_clock.h"
|
||||||
|
#include "f_op/f_op_actor_mng.h"
|
||||||
|
#include "f_pc/f_pc_layer.h"
|
||||||
|
#include "f_pc/f_pc_layer_iter.h"
|
||||||
|
#include "f_pc/f_pc_manager.h"
|
||||||
|
#include "f_pc/f_pc_node.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <optional>
|
||||||
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "fmt/format.h"
|
||||||
|
|
||||||
|
namespace dusk {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
static constexpr int kMaxHistory = 64;
|
||||||
|
|
||||||
|
static std::vector<std::string> SplitArgs(std::string_view input) {
|
||||||
|
std::vector<std::string> args;
|
||||||
|
std::string cur;
|
||||||
|
for (char c : input) {
|
||||||
|
if (c == ' ' || c == '\t') {
|
||||||
|
if (!cur.empty()) {
|
||||||
|
args.push_back(std::move(cur));
|
||||||
|
cur.clear();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cur += c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!cur.empty()) {
|
||||||
|
args.push_back(std::move(cur));
|
||||||
|
}
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::optional<long> ParseLong(const std::string& s) {
|
||||||
|
if (s.empty()) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
char* end = nullptr;
|
||||||
|
const long v = std::strtol(s.c_str(), &end, 0);
|
||||||
|
return (end != s.c_str() && *end == '\0') ? std::optional<long>{v} : std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::optional<float> ParseFloat(const std::string& s) {
|
||||||
|
if (s.empty()) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
char* end = nullptr;
|
||||||
|
const float v = std::strtof(s.c_str(), &end);
|
||||||
|
return (end != s.c_str() && *end == '\0') ? std::optional<float>{v} : std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* ActorShortName(s16 profname) {
|
||||||
|
const char* n = dStage_getName(profname, -1);
|
||||||
|
return n ? n : "?";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resolves @found / @link / @<id> to a process pointer, outputting an error on failure
|
||||||
|
static base_process_class* ParseProcArg(
|
||||||
|
const std::string& s, unsigned int foundProcId, const CommandOutput& output) {
|
||||||
|
if (s.empty() || s[0] != '@') {
|
||||||
|
output("Error: proc reference must start with @");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
const std::string inner = s.substr(1);
|
||||||
|
unsigned int id;
|
||||||
|
if (inner == "found") {
|
||||||
|
if (foundProcId == 0) {
|
||||||
|
output("Error: @found is not set");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
id = foundProcId;
|
||||||
|
} else if (inner == "link") {
|
||||||
|
auto* player = dComIfGp_getPlayer(0);
|
||||||
|
if (player == nullptr) {
|
||||||
|
output("Error: player not available");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
id = (unsigned int)fpcM_GetID(player);
|
||||||
|
} else {
|
||||||
|
const auto v = ParseLong(inner);
|
||||||
|
if (!v) {
|
||||||
|
output("Error: invalid proc ID");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
id = (unsigned int)*v;
|
||||||
|
}
|
||||||
|
auto* proc = fpcM_SearchByID(id);
|
||||||
|
if (proc == nullptr) {
|
||||||
|
output(fmt::format(FMT_STRING("Error: proc {} not found"), id));
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return proc;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Like ParseProcArg but ensures the proc is an actor
|
||||||
|
static fopAc_ac_c* ParseActorArg(
|
||||||
|
const std::string& s, unsigned int foundProcId, const CommandOutput& output) {
|
||||||
|
auto* proc = ParseProcArg(s, foundProcId, output);
|
||||||
|
if (proc == nullptr) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
if (!fopAcM_IsActor(proc)) {
|
||||||
|
output("Error: proc is not an actor");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return static_cast<fopAc_ac_c*>(proc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::optional<s16> ParseActorId(const std::string& s) {
|
||||||
|
if (const auto v = ParseLong(s)) {
|
||||||
|
return (s16)*v;
|
||||||
|
}
|
||||||
|
const auto* entry = dStage_searchNameCI(s.c_str());
|
||||||
|
return entry ? std::optional<s16>{entry->procname} : std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::optional<cXyz> ParseXYZ(const std::vector<std::string>& args, size_t i) {
|
||||||
|
const auto x = ParseFloat(args[i]), y = ParseFloat(args[i + 1]), z = ParseFloat(args[i + 2]);
|
||||||
|
return (x && y && z) ? std::optional<cXyz>{cXyz(*x, *y, *z)} : std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool TryAngle(
|
||||||
|
s16& out, const std::vector<std::string>& args, size_t i, const CommandOutput& output) {
|
||||||
|
if (args.size() <= i) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
const auto a = ParseLong(args[i]);
|
||||||
|
if (!a) {
|
||||||
|
output("Error: invalid angle");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
out = (s16)*a;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string actorLine(const base_process_class* proc) {
|
||||||
|
const auto* ac = static_cast<const fopAc_ac_c*>(proc);
|
||||||
|
return fmt::format(FMT_STRING("procId={} 0x{:04X} ({}) @ ({:.2f}, {:.2f}, {:.2f}) room={}"),
|
||||||
|
(unsigned int)proc->id, (unsigned int)(u16)proc->profname, ActorShortName(proc->profname),
|
||||||
|
ac->current.pos.x, ac->current.pos.y, ac->current.pos.z, (int)ac->current.roomNo);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void recurseLayer(void* p, int (*callback)(void*, void*), void* ctx) {
|
||||||
|
auto* proc = static_cast<base_process_class*>(p);
|
||||||
|
if (fpcBs_Is_JustOfType(g_fpcNd_type, proc->subtype)) {
|
||||||
|
fpcLyIt_OnlyHere(&static_cast<process_node_class*>(p)->layer, callback, ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ListContext {
|
||||||
|
s16 targetId;
|
||||||
|
std::vector<std::string>* output;
|
||||||
|
};
|
||||||
|
struct FindContext {
|
||||||
|
s16 targetId;
|
||||||
|
std::vector<base_process_class*> matches;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int ListActorCallback(void* p, void* ctx) {
|
||||||
|
auto* proc = static_cast<base_process_class*>(p);
|
||||||
|
auto* context = static_cast<ListContext*>(ctx);
|
||||||
|
if (fopAcM_IsActor(proc) && (context->targetId < 0 || proc->profname == context->targetId)) {
|
||||||
|
context->output->push_back(" " + actorLine(proc));
|
||||||
|
}
|
||||||
|
recurseLayer(p, ListActorCallback, ctx);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int FindActorCallback(void* p, void* ctx) {
|
||||||
|
auto* proc = static_cast<base_process_class*>(p);
|
||||||
|
auto* context = static_cast<FindContext*>(ctx);
|
||||||
|
if (fopAcM_IsActor(proc) && proc->profname == context->targetId) {
|
||||||
|
context->matches.push_back(proc);
|
||||||
|
}
|
||||||
|
recurseLayer(p, FindActorCallback, ctx);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void runCommand(std::string_view cmdLine, CommandState& state, const CommandOutput& output) {
|
||||||
|
output(fmt::format(FMT_STRING("> {}"), cmdLine));
|
||||||
|
|
||||||
|
if (!cmdLine.empty()) {
|
||||||
|
if (state.history.empty() || state.history.back() != cmdLine) {
|
||||||
|
state.history.push_back(std::string(cmdLine));
|
||||||
|
if ((int)state.history.size() > kMaxHistory) {
|
||||||
|
state.history.erase(state.history.begin());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto args = SplitArgs(cmdLine);
|
||||||
|
if (args.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto& cmd = args[0];
|
||||||
|
|
||||||
|
auto requirePlayer = [&]() -> daAlink_c* {
|
||||||
|
auto* p = (daAlink_c*)dComIfGp_getPlayer(0);
|
||||||
|
if (p == nullptr) {
|
||||||
|
output("Error: player not available");
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (cmd == "tp") {
|
||||||
|
auto* player = requirePlayer();
|
||||||
|
if (player == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.size() >= 2 && args[1].starts_with('@')) {
|
||||||
|
auto* ac = ParseActorArg(args[1], state.foundProcId, output);
|
||||||
|
if (ac == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.size() >= 3 && args[2].starts_with('@')) {
|
||||||
|
auto* destAc = ParseActorArg(args[2], state.foundProcId, output);
|
||||||
|
if (destAc == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const cXyz destPos = destAc->current.pos;
|
||||||
|
ac->current.pos = destPos;
|
||||||
|
output(fmt::format(FMT_STRING("Moved actor {} to ({:.2f}, {:.2f}, {:.2f})"), ac->id,
|
||||||
|
destPos.x, destPos.y, destPos.z));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.size() >= 5) {
|
||||||
|
const auto pos = ParseXYZ(args, 2);
|
||||||
|
if (!pos) {
|
||||||
|
output("Error: invalid coordinates");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ac->current.pos = *pos;
|
||||||
|
if (!TryAngle(ac->shape_angle.y, args, 5, output)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
output(fmt::format(FMT_STRING("Moved actor {} to ({:.2f}, {:.2f}, {:.2f})"), ac->id,
|
||||||
|
pos->x, pos->y, pos->z));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
player->current.pos = ac->current.pos;
|
||||||
|
output(fmt::format(FMT_STRING("Teleported to actor {} ({:.2f}, {:.2f}, {:.2f})"),
|
||||||
|
ac->id, ac->current.pos.x, ac->current.pos.y, ac->current.pos.z));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.size() < 4) {
|
||||||
|
output("Usage: tp <x> <y> <z> [angle] | tp @<procId> [<x> <y> <z> [angle] | @link]");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto pos = ParseXYZ(args, 1);
|
||||||
|
if (!pos) {
|
||||||
|
output("Error: invalid coordinates");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
player->current.pos = *pos;
|
||||||
|
if (!TryAngle(player->shape_angle.y, args, 4, output)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
output(fmt::format(
|
||||||
|
FMT_STRING("Teleported to ({:.2f}, {:.2f}, {:.2f})"), pos->x, pos->y, pos->z));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd == "spawn") {
|
||||||
|
if (args.size() < 2) {
|
||||||
|
output("Usage: spawn <actorId> [params] [x y z] [angle]");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto* player = requirePlayer();
|
||||||
|
if (player == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto actorId = ParseActorId(args[1]);
|
||||||
|
if (!actorId) {
|
||||||
|
output("Error: unknown actor ID or name");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
long paramsL = -1;
|
||||||
|
if (args.size() >= 3) {
|
||||||
|
const auto p = ParseLong(args[2]);
|
||||||
|
if (!p) {
|
||||||
|
output("Error: invalid params");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
paramsL = *p;
|
||||||
|
}
|
||||||
|
|
||||||
|
cXyz pos = player->current.pos;
|
||||||
|
if (args.size() >= 6) {
|
||||||
|
const auto spawnPos = ParseXYZ(args, 3);
|
||||||
|
if (!spawnPos) {
|
||||||
|
output("Error: invalid spawn coordinates");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pos = *spawnPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
s16 angleY = 0;
|
||||||
|
if (!TryAngle(angleY, args, 6, output)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
csXyz angle;
|
||||||
|
angle.set(0, angleY, 0);
|
||||||
|
cXyz scale(1.0f, 1.0f, 1.0f);
|
||||||
|
|
||||||
|
layer_class* savedLayer = fpcLy_CurrentLayer();
|
||||||
|
base_process_class* playScene = fpcM_SearchByName(fpcNm_PLAY_SCENE_e);
|
||||||
|
if (playScene != nullptr) {
|
||||||
|
fpcLy_SetCurrentLayer(&((process_node_class*)playScene)->layer);
|
||||||
|
}
|
||||||
|
unsigned int result = fopAcM_create(
|
||||||
|
*actorId, (u32)paramsL, &pos, player->current.roomNo, &angle, &scale, (s8)-1);
|
||||||
|
fpcLy_SetCurrentLayer(savedLayer);
|
||||||
|
|
||||||
|
output(result != 0 ? fmt::format(FMT_STRING("Spawned actorId=0x{:04X} procId={}"),
|
||||||
|
(unsigned int)(u16)*actorId, result) :
|
||||||
|
fmt::format(FMT_STRING("Failed to spawn actorId=0x{:04X}"),
|
||||||
|
(unsigned int)(u16)*actorId));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd == "reset") {
|
||||||
|
JUTGamePad::C3ButtonReset::sResetSwitchPushing = true;
|
||||||
|
output("Soft reset triggered");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd == "warp") {
|
||||||
|
if (args.size() < 4) {
|
||||||
|
output("Usage: warp <stageName> <point> <roomNo> [layer=-1]");
|
||||||
|
output(" e.g. warp F_SP121 0 0");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto pointL = ParseLong(args[2]), roomL = ParseLong(args[3]);
|
||||||
|
if (!pointL || !roomL) {
|
||||||
|
output("Error: invalid point or room number");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
long layerL = -1;
|
||||||
|
if (args.size() >= 5) {
|
||||||
|
const auto l = ParseLong(args[4]);
|
||||||
|
if (!l) {
|
||||||
|
output("Error: invalid layer");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
layerL = *l;
|
||||||
|
}
|
||||||
|
state.lastWarpStage = args[1];
|
||||||
|
dComIfGp_setNextStage(state.lastWarpStage.c_str(), (s16)*pointL, (s8)*roomL, (s8)layerL);
|
||||||
|
output(fmt::format(FMT_STRING("Warping to {} point={} room={} layer={}"), args[1],
|
||||||
|
(int)(s16)*pointL, (int)(s8)*roomL, (int)(s8)layerL));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd == "list") {
|
||||||
|
s16 targetId = -1;
|
||||||
|
if (args.size() >= 2) {
|
||||||
|
const auto id = ParseActorId(args[1]);
|
||||||
|
if (!id) {
|
||||||
|
output("Error: unknown actor ID or name");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
targetId = *id;
|
||||||
|
}
|
||||||
|
std::vector<std::string> results;
|
||||||
|
ListContext ctx{targetId, &results};
|
||||||
|
fpcLyIt_OnlyHere(fpcLy_RootLayer(), ListActorCallback, &ctx);
|
||||||
|
output(results.empty() ? "No matching actors found" :
|
||||||
|
fmt::format(FMT_STRING("Found {} actor(s):"), results.size()));
|
||||||
|
for (const auto& r : results) {
|
||||||
|
output(r);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd == "killall") {
|
||||||
|
if (args.size() < 2) {
|
||||||
|
output("Usage: killall <actorId|name>");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto targetId = ParseActorId(args[1]);
|
||||||
|
if (!targetId) {
|
||||||
|
output("Error: unknown actor ID or name");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
FindContext ctx{*targetId, {}};
|
||||||
|
fpcLyIt_OnlyHere(fpcLy_RootLayer(), FindActorCallback, &ctx);
|
||||||
|
for (auto* proc : ctx.matches) {
|
||||||
|
fpcM_Delete(proc);
|
||||||
|
}
|
||||||
|
output(fmt::format(FMT_STRING("Deleted {} actor(s) of type {} ({})"),
|
||||||
|
(int)ctx.matches.size(), (unsigned int)(u16)*targetId, ActorShortName(*targetId)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd == "heal") {
|
||||||
|
auto* player = requirePlayer();
|
||||||
|
if (player == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const u16 maxLife = dComIfGs_getMaxLife() / 5 * 4;
|
||||||
|
u16 newLife = maxLife;
|
||||||
|
if (args.size() >= 2) {
|
||||||
|
const auto amount = ParseLong(args[1]);
|
||||||
|
if (!amount) {
|
||||||
|
output("Error: invalid amount");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
newLife =
|
||||||
|
(u16)std::max(0L, std::min((long)maxLife, (long)dComIfGs_getLife() + *amount));
|
||||||
|
}
|
||||||
|
dComIfGs_setLife(newLife);
|
||||||
|
output(fmt::format(FMT_STRING("Health: {}/{}"), (int)newLife, (int)maxLife));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd == "kill") {
|
||||||
|
if (args.size() >= 2) {
|
||||||
|
auto* proc = ParseProcArg(args[1], state.foundProcId, output);
|
||||||
|
if (proc == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fpcM_Delete(proc);
|
||||||
|
output(fmt::format(FMT_STRING("Deleted proc {}"), proc->id));
|
||||||
|
} else {
|
||||||
|
auto* player = requirePlayer();
|
||||||
|
if (player == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dComIfGs_setLife(0);
|
||||||
|
output("Set Link's health to 0");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd == "rate") {
|
||||||
|
if (args.size() >= 2) {
|
||||||
|
const auto hz = ParseLong(args[1]);
|
||||||
|
if (!hz || *hz <= 0) {
|
||||||
|
output("Error: rate must be a positive integer");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dusk::game_clock::set_sim_rate((float)*hz);
|
||||||
|
}
|
||||||
|
output(fmt::format(FMT_STRING("Sim rate: {} hz"), (int)dusk::game_clock::get_sim_rate()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd == "ebf") {
|
||||||
|
if (args.size() >= 2) {
|
||||||
|
const auto val = ParseLong(args[1]);
|
||||||
|
if (!val || *val < 0 || *val > 255) {
|
||||||
|
output("Error: value must be 0-255");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cDmr_SkipInfo = (u8)*val;
|
||||||
|
}
|
||||||
|
output(fmt::format(FMT_STRING("EBF = {}"), (int)cDmr_SkipInfo));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd == "time") {
|
||||||
|
if (args.size() >= 2) {
|
||||||
|
const auto t = ParseFloat(args[1]);
|
||||||
|
if (!t || *t < 0.0f || *t > 360.0f) {
|
||||||
|
output("Error: time must be a float between 0 and 360");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dKy_instant_timechg(*t);
|
||||||
|
}
|
||||||
|
output(fmt::format(FMT_STRING("Time: {:.2f} ({}:{:02d})"), dComIfGs_getTime(),
|
||||||
|
dKy_getdaytime_hour(), dKy_getdaytime_minute()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd == "rupees") {
|
||||||
|
const u16 maxRupees = dComIfGs_getRupeeMax();
|
||||||
|
if (args.size() >= 2) {
|
||||||
|
const auto amount = ParseLong(args[1]);
|
||||||
|
if (!amount) {
|
||||||
|
output("Error: invalid amount");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dComIfGs_setRupee((u16)std::max(0L, std::min((long)maxRupees, *amount)));
|
||||||
|
}
|
||||||
|
output(fmt::format(FMT_STRING("Rupees: {}/{}"), (int)dComIfGs_getRupee(), (int)maxRupees));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd == "find") {
|
||||||
|
if (args.size() < 2) {
|
||||||
|
if (state.foundProcId == 0) {
|
||||||
|
output("@found is not set");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto* proc = fpcM_SearchByID(state.foundProcId);
|
||||||
|
output(proc != nullptr && fopAcM_IsActor(proc) ?
|
||||||
|
"@found = " + actorLine(proc) :
|
||||||
|
fmt::format(FMT_STRING("@found = {} (no longer exists)"),
|
||||||
|
(unsigned int)state.foundProcId));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto targetId = ParseActorId(args[1]);
|
||||||
|
if (!targetId) {
|
||||||
|
output("Error: unknown actor ID or name");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int targetN = 1;
|
||||||
|
if (args.size() >= 3) {
|
||||||
|
const auto n = ParseLong(args[2]);
|
||||||
|
if (!n || *n < 1) {
|
||||||
|
output("Error: index must be >= 1");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
targetN = (int)*n;
|
||||||
|
}
|
||||||
|
|
||||||
|
FindContext ctx{*targetId, {}};
|
||||||
|
fpcLyIt_OnlyHere(fpcLy_RootLayer(), FindActorCallback, &ctx);
|
||||||
|
|
||||||
|
if (ctx.matches.empty()) {
|
||||||
|
output(fmt::format(FMT_STRING("No actors found for '{}'"), args[1]));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::sort(ctx.matches.begin(), ctx.matches.end(),
|
||||||
|
[](const base_process_class* a, const base_process_class* b) { return a->id < b->id; });
|
||||||
|
|
||||||
|
if (targetN > (int)ctx.matches.size()) {
|
||||||
|
output(fmt::format(
|
||||||
|
FMT_STRING("Error: only {} actor(s) of that type exist"), (int)ctx.matches.size()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* picked = ctx.matches[(size_t)(targetN - 1)];
|
||||||
|
state.foundProcId = picked->id;
|
||||||
|
output(fmt::format(
|
||||||
|
FMT_STRING("@found [{}/{}] {}"), targetN, (int)ctx.matches.size(), actorLine(picked)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd == "transform") {
|
||||||
|
auto* player = requirePlayer();
|
||||||
|
if (player == nullptr) { return; }
|
||||||
|
player->procCoMetamorphoseInit();
|
||||||
|
output("Transforming");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd == "pos") {
|
||||||
|
auto* player = requirePlayer();
|
||||||
|
if (player == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
output(fmt::format(FMT_STRING("pos: {:.4f} {:.4f} {:.4f}"), player->current.pos.x,
|
||||||
|
player->current.pos.y, player->current.pos.z));
|
||||||
|
output(
|
||||||
|
fmt::format(FMT_STRING("stage: {} room: {} entry: {}"), dComIfGp_getStartStageName(),
|
||||||
|
(int)player->current.roomNo, (int)dComIfGp_getStartStagePoint()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd == "help") {
|
||||||
|
output("@<ref> = @<procId> | @found | @link");
|
||||||
|
output("");
|
||||||
|
output("ebf [0-255] Get or set cDmr_SkipInfo");
|
||||||
|
output("find <id|name> [n=1] Store nth actor as @found");
|
||||||
|
output("heal [amount] Heal to max, or by relative amount");
|
||||||
|
output("kill Set Link health to 0");
|
||||||
|
output("kill @<ref> Delete proc");
|
||||||
|
output("killall <id|name> Delete all actors of a type");
|
||||||
|
output("list [id|name] List actors in scene");
|
||||||
|
output("pos Print player position and stage");
|
||||||
|
output("rate [hz] Get or set sim rate (1-1000, default 30)");
|
||||||
|
output("reset Soft reset");
|
||||||
|
output("rupees [amount] Get or set rupee count");
|
||||||
|
output("spawn <id|name> [params] [x y z] [angle] Spawn actor");
|
||||||
|
output("time [0-360] Get or set time of day");
|
||||||
|
output("tp <x> <y> <z> [angle] Teleport Link to coords");
|
||||||
|
output("tp @<ref> Teleport Link to actor");
|
||||||
|
output("tp @<ref> <x> <y> <z> [angle] Move actor to coords");
|
||||||
|
output("tp @<ref> @<ref> Move actor to actor");
|
||||||
|
output("transform Force transform");
|
||||||
|
output("warp <stage> <point> <room> [layer] Warp to stage");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
output(fmt::format(FMT_STRING("Unknown command '{}' (try 'help')"), cmd));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace dusk
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace dusk {
|
||||||
|
|
||||||
|
using CommandOutput = std::function<void(std::string)>;
|
||||||
|
|
||||||
|
struct CommandState {
|
||||||
|
std::vector<std::string> history;
|
||||||
|
unsigned int foundProcId = 0;
|
||||||
|
std::string lastWarpStage;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Execute a single command line. Calls output() for every line of response.
|
||||||
|
// Manages history internally; callers need only hold a CommandState.
|
||||||
|
void runCommand(std::string_view cmdLine, CommandState& state, const CommandOutput& output);
|
||||||
|
|
||||||
|
} // namespace dusk
|
||||||
+51
-223
@@ -1,23 +1,19 @@
|
|||||||
#include "dusk/config.hpp"
|
#include "dusk/config.hpp"
|
||||||
#include "absl/container/flat_hash_map.h"
|
|
||||||
#include "fmt/format.h"
|
#include "fmt/format.h"
|
||||||
#include "nlohmann/json.hpp"
|
#include "nlohmann/json.hpp"
|
||||||
|
#include "absl/container/flat_hash_map.h"
|
||||||
|
|
||||||
#include "aurora/lib/logging.hpp"
|
#include "aurora/lib/logging.hpp"
|
||||||
#include "dusk/io.hpp"
|
#include "dusk/io.hpp"
|
||||||
#include "dusk/settings.h"
|
#include "dusk/settings.h"
|
||||||
|
|
||||||
#include <cmath>
|
|
||||||
#include <filesystem>
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <optional>
|
#include <filesystem>
|
||||||
#include <string>
|
|
||||||
#include <string_view>
|
|
||||||
#include <system_error>
|
#include <system_error>
|
||||||
#include <utility>
|
#include <string>
|
||||||
|
|
||||||
#include "dusk/action_bindings.h"
|
|
||||||
#include "dusk/main.h"
|
#include "dusk/main.h"
|
||||||
|
#include "dusk/action_bindings.h"
|
||||||
|
|
||||||
using namespace dusk::config;
|
using namespace dusk::config;
|
||||||
|
|
||||||
@@ -30,104 +26,6 @@ aurora::Module DuskConfigLog("dusk::config");
|
|||||||
static absl::flat_hash_map<std::string_view, ConfigVarBase*> RegisteredConfigVars;
|
static absl::flat_hash_map<std::string_view, ConfigVarBase*> RegisteredConfigVars;
|
||||||
static bool RegistrationDone = false;
|
static bool RegistrationDone = false;
|
||||||
|
|
||||||
static std::optional<dusk::ui::ControlAnchor> parse_control_anchor(std::string_view value) {
|
|
||||||
if (value == "none") {
|
|
||||||
return dusk::ui::ControlAnchor::None;
|
|
||||||
}
|
|
||||||
if (value == "top") {
|
|
||||||
return dusk::ui::ControlAnchor::Top;
|
|
||||||
}
|
|
||||||
if (value == "left") {
|
|
||||||
return dusk::ui::ControlAnchor::Left;
|
|
||||||
}
|
|
||||||
if (value == "bottom") {
|
|
||||||
return dusk::ui::ControlAnchor::Bottom;
|
|
||||||
}
|
|
||||||
if (value == "right") {
|
|
||||||
return dusk::ui::ControlAnchor::Right;
|
|
||||||
}
|
|
||||||
if (value == "topLeft") {
|
|
||||||
return dusk::ui::ControlAnchor::TopLeft;
|
|
||||||
}
|
|
||||||
if (value == "topRight") {
|
|
||||||
return dusk::ui::ControlAnchor::TopRight;
|
|
||||||
}
|
|
||||||
if (value == "bottomLeft") {
|
|
||||||
return dusk::ui::ControlAnchor::BottomLeft;
|
|
||||||
}
|
|
||||||
if (value == "bottomRight") {
|
|
||||||
return dusk::ui::ControlAnchor::BottomRight;
|
|
||||||
}
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char* control_anchor_value(dusk::ui::ControlAnchor anchor) {
|
|
||||||
switch (anchor) {
|
|
||||||
case dusk::ui::ControlAnchor::None:
|
|
||||||
return "none";
|
|
||||||
case dusk::ui::ControlAnchor::Top:
|
|
||||||
return "top";
|
|
||||||
case dusk::ui::ControlAnchor::Left:
|
|
||||||
return "left";
|
|
||||||
case dusk::ui::ControlAnchor::Bottom:
|
|
||||||
return "bottom";
|
|
||||||
case dusk::ui::ControlAnchor::Right:
|
|
||||||
return "right";
|
|
||||||
case dusk::ui::ControlAnchor::TopLeft:
|
|
||||||
return "topLeft";
|
|
||||||
case dusk::ui::ControlAnchor::TopRight:
|
|
||||||
return "topRight";
|
|
||||||
case dusk::ui::ControlAnchor::BottomLeft:
|
|
||||||
return "bottomLeft";
|
|
||||||
case dusk::ui::ControlAnchor::BottomRight:
|
|
||||||
return "bottomRight";
|
|
||||||
}
|
|
||||||
return "none";
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::optional<float> json_finite_float(const json& object, const char* key) {
|
|
||||||
const auto iter = object.find(key);
|
|
||||||
if (iter == object.end() || !iter->is_number()) {
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
const float value = iter->get<float>();
|
|
||||||
if (!std::isfinite(value)) {
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::optional<dusk::ui::ControlProps> parse_control_props(const json& value) {
|
|
||||||
if (!value.is_object()) {
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto x = json_finite_float(value, "x");
|
|
||||||
const auto y = json_finite_float(value, "y");
|
|
||||||
const auto w = json_finite_float(value, "w");
|
|
||||||
const auto h = json_finite_float(value, "h");
|
|
||||||
const auto scale = json_finite_float(value, "scale");
|
|
||||||
const auto anchorIter = value.find("anchor");
|
|
||||||
if (!x || !y || !w || !h || !scale || anchorIter == value.end() || !anchorIter->is_string()) {
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto anchor = parse_control_anchor(anchorIter->get<std::string>());
|
|
||||||
if (!anchor || *w <= 0.0f || *h <= 0.0f || *scale <= 0.0f) {
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
return dusk::ui::ControlProps{
|
|
||||||
.x = *x,
|
|
||||||
.y = *y,
|
|
||||||
.w = *w,
|
|
||||||
.h = *h,
|
|
||||||
.scale = *scale,
|
|
||||||
.anchor = *anchor,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::filesystem::path GetConfigJsonPath() {
|
static std::filesystem::path GetConfigJsonPath() {
|
||||||
return dusk::ConfigPath / ConfigFileName;
|
return dusk::ConfigPath / ConfigFileName;
|
||||||
}
|
}
|
||||||
@@ -148,8 +46,8 @@ static void ReplaceFile(const std::filesystem::path& source, const std::filesyst
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigVarBase::ConfigVarBase(const char* name, const ConfigImplBase* impl)
|
ConfigVarBase::ConfigVarBase(const char* name, const ConfigImplBase* impl) : name(name), registered(false), layer(ConfigVarLayer::Default), impl(impl) {
|
||||||
: name(name), registered(false), layer(ConfigVarLayer::Default), impl(impl) {}
|
}
|
||||||
|
|
||||||
const char* ConfigVarBase::getName() const noexcept {
|
const char* ConfigVarBase::getName() const noexcept {
|
||||||
return name;
|
return name;
|
||||||
@@ -174,13 +72,11 @@ static T sanitizeEnumValue(const ConfigVar<T>& cVar, T value) {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <ConfigValue T>
|
template<ConfigValue T>
|
||||||
void ConfigImpl<T>::loadFromJson(ConfigVar<T>& cVar, const json& jsonValue) {
|
void ConfigImpl<T>::loadFromJson(ConfigVar<T>& cVar, const json& jsonValue) {
|
||||||
if constexpr (std::is_enum_v<T>) {
|
if constexpr (std::is_enum_v<T>) {
|
||||||
if (jsonValue.is_boolean()) {
|
if (jsonValue.is_boolean()) {
|
||||||
DuskConfigLog.error("Doing default migration of CVar {} from bool, enum values may not "
|
DuskConfigLog.error("Doing default migration of CVar {} from bool, enum values may not be what is expected!", cVar.getName());
|
||||||
"be what is expected!",
|
|
||||||
cVar.getName());
|
|
||||||
|
|
||||||
using Underlying = std::underlying_type_t<T>;
|
using Underlying = std::underlying_type_t<T>;
|
||||||
const bool b = jsonValue.get<bool>();
|
const bool b = jsonValue.get<bool>();
|
||||||
@@ -195,14 +91,13 @@ void ConfigImpl<T>::loadFromJson(ConfigVar<T>& cVar, const json& jsonValue) {
|
|||||||
cVar.setValue(sanitizeEnumValue(cVar, jsonValue.get<T>()), false);
|
cVar.setValue(sanitizeEnumValue(cVar, jsonValue.get<T>()), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <ConfigValue T>
|
template<ConfigValue T>
|
||||||
nlohmann::json ConfigImpl<T>::dumpToJson(const ConfigVar<T>& cVar) {
|
nlohmann::json ConfigImpl<T>::dumpToJson(const ConfigVar<T>& cVar) {
|
||||||
return cVar.getValueForSave();
|
return cVar.getValueForSave();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <ConfigValue T>
|
template<ConfigValue T> requires std::is_integral_v<T> && std::is_signed_v<T>
|
||||||
requires std::is_integral_v<T>&& std::is_signed_v<T> static void loadFromArgImpl(
|
static void loadFromArgImpl(ConfigVar<T>& cVar, const std::string_view stringValue) {
|
||||||
ConfigVar<T>& cVar, const std::string_view stringValue) {
|
|
||||||
const std::string str(stringValue);
|
const std::string str(stringValue);
|
||||||
const auto result = std::stoll(str);
|
const auto result = std::stoll(str);
|
||||||
if (result >= std::numeric_limits<T>::min() && result <= std::numeric_limits<T>::max()) {
|
if (result >= std::numeric_limits<T>::min() && result <= std::numeric_limits<T>::max()) {
|
||||||
@@ -212,9 +107,8 @@ requires std::is_integral_v<T>&& std::is_signed_v<T> static void loadFromArgImpl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <ConfigValue T>
|
template<ConfigValue T> requires std::is_integral_v<T> && std::is_unsigned_v<T>
|
||||||
requires std::is_integral_v<T>&& std::is_unsigned_v<T> static void loadFromArgImpl(
|
static void loadFromArgImpl(ConfigVar<T>& cVar, const std::string_view stringValue) {
|
||||||
ConfigVar<T>& cVar, const std::string_view stringValue) {
|
|
||||||
const std::string str(stringValue);
|
const std::string str(stringValue);
|
||||||
const auto result = std::stoull(str);
|
const auto result = std::stoull(str);
|
||||||
if (result <= std::numeric_limits<T>::max()) {
|
if (result <= std::numeric_limits<T>::max()) {
|
||||||
@@ -240,17 +134,14 @@ static void loadFromArgImpl(ConfigVar<std::string>& cVar, const std::string_view
|
|||||||
cVar.setOverrideValue(std::string(stringValue));
|
cVar.setOverrideValue(std::string(stringValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <ConfigValue T>
|
template<ConfigValue T> requires std::is_enum_v<T>
|
||||||
requires std::is_enum_v<T> static void loadFromArgImpl(
|
static void loadFromArgImpl(ConfigVar<T>& cVar, const std::string_view stringValue) {
|
||||||
ConfigVar<T>& cVar, const std::string_view stringValue) {
|
|
||||||
using Underlying = std::underlying_type_t<T>;
|
using Underlying = std::underlying_type_t<T>;
|
||||||
const std::string str(stringValue);
|
const std::string str(stringValue);
|
||||||
|
|
||||||
if constexpr (std::is_signed_v<Underlying>) {
|
if constexpr (std::is_signed_v<Underlying>) {
|
||||||
const auto result = std::stoll(str);
|
const auto result = std::stoll(str);
|
||||||
if (result >= std::numeric_limits<Underlying>::min() &&
|
if (result >= std::numeric_limits<Underlying>::min() && result <= std::numeric_limits<Underlying>::max()) {
|
||||||
result <= std::numeric_limits<Underlying>::max())
|
|
||||||
{
|
|
||||||
cVar.setOverrideValue(sanitizeEnumValue(cVar, static_cast<T>(result)));
|
cVar.setOverrideValue(sanitizeEnumValue(cVar, static_cast<T>(result)));
|
||||||
} else {
|
} else {
|
||||||
throw std::out_of_range("Value is too large");
|
throw std::out_of_range("Value is too large");
|
||||||
@@ -265,20 +156,16 @@ requires std::is_enum_v<T> static void loadFromArgImpl(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <ConfigValue T>
|
template<ConfigValue T>
|
||||||
void ConfigImpl<T>::loadFromArg(ConfigVar<T>& cVar, const std::string_view stringValue) {
|
void ConfigImpl<T>::loadFromArg(ConfigVar<T>& cVar, const std::string_view stringValue) {
|
||||||
loadFromArgImpl(cVar, stringValue);
|
loadFromArgImpl(cVar, stringValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template<>
|
||||||
void ConfigImpl<bool>::loadFromArg(ConfigVar<bool>& cVar, const std::string_view stringValue) {
|
void ConfigImpl<bool>::loadFromArg(ConfigVar<bool>& cVar, const std::string_view stringValue) {
|
||||||
if (stringValue == "1" || stringValue == "TRUE" || stringValue == "true" ||
|
if (stringValue == "1" || stringValue == "TRUE" || stringValue == "true" || stringValue == "True") {
|
||||||
stringValue == "True")
|
|
||||||
{
|
|
||||||
cVar.setOverrideValue(true);
|
cVar.setOverrideValue(true);
|
||||||
} else if (stringValue == "0" || stringValue == "FALSE" || stringValue == "false" ||
|
} else if (stringValue == "0" || stringValue == "FALSE" || stringValue == "false" || stringValue == "False") {
|
||||||
stringValue == "False")
|
|
||||||
{
|
|
||||||
cVar.setOverrideValue(false);
|
cVar.setOverrideValue(false);
|
||||||
} else {
|
} else {
|
||||||
throw InvalidConfigError("Value cannot be parsed as boolean");
|
throw InvalidConfigError("Value cannot be parsed as boolean");
|
||||||
@@ -287,103 +174,42 @@ void ConfigImpl<bool>::loadFromArg(ConfigVar<bool>& cVar, const std::string_view
|
|||||||
|
|
||||||
// My IDE is convinced this namespace is necessary. It shouldn't be AFAICT?
|
// My IDE is convinced this namespace is necessary. It shouldn't be AFAICT?
|
||||||
namespace dusk::config {
|
namespace dusk::config {
|
||||||
template class ConfigImpl<bool>;
|
template class ConfigImpl<bool>;
|
||||||
template class ConfigImpl<s8>;
|
template class ConfigImpl<s8>;
|
||||||
template class ConfigImpl<u8>;
|
template class ConfigImpl<u8>;
|
||||||
template class ConfigImpl<s16>;
|
template class ConfigImpl<s16>;
|
||||||
template class ConfigImpl<u16>;
|
template class ConfigImpl<u16>;
|
||||||
template class ConfigImpl<s32>;
|
template class ConfigImpl<s32>;
|
||||||
template class ConfigImpl<u32>;
|
template class ConfigImpl<u32>;
|
||||||
template class ConfigImpl<s64>;
|
template class ConfigImpl<s64>;
|
||||||
template class ConfigImpl<u64>;
|
template class ConfigImpl<u64>;
|
||||||
template class ConfigImpl<f32>;
|
template class ConfigImpl<f32>;
|
||||||
template class ConfigImpl<f64>;
|
template class ConfigImpl<f64>;
|
||||||
template class ConfigImpl<std::string>;
|
template class ConfigImpl<std::string>;
|
||||||
template class ConfigImpl<dusk::BloomMode>;
|
template class ConfigImpl<dusk::BloomMode>;
|
||||||
template class ConfigImpl<dusk::DepthOfFieldMode>;
|
template class ConfigImpl<dusk::DepthOfFieldMode>;
|
||||||
template class ConfigImpl<dusk::DiscVerificationState>;
|
template class ConfigImpl<dusk::DiscVerificationState>;
|
||||||
template class ConfigImpl<dusk::GameLanguage>;
|
template class ConfigImpl<dusk::GameLanguage>;
|
||||||
|
template class ConfigImpl<dusk::GyroMode>;
|
||||||
|
|
||||||
template <>
|
template<> void ConfigImpl<FrameInterpMode>::loadFromJson(ConfigVar<FrameInterpMode>& cVar, const json& jsonValue) {
|
||||||
void ConfigImpl<FrameInterpMode>::loadFromJson(
|
if (jsonValue.is_boolean()) {
|
||||||
ConfigVar<FrameInterpMode>& cVar, const json& jsonValue) {
|
const bool b = jsonValue.get<bool>();
|
||||||
if (jsonValue.is_boolean()) {
|
|
||||||
const bool b = jsonValue.get<bool>();
|
|
||||||
|
|
||||||
const FrameInterpMode mode = b ? FrameInterpMode::Unlimited : FrameInterpMode::Off;
|
const FrameInterpMode mode = b ? FrameInterpMode::Unlimited : FrameInterpMode::Off;
|
||||||
|
|
||||||
cVar.setValue(sanitizeEnumValue(cVar, mode), false);
|
cVar.setValue(sanitizeEnumValue(cVar, mode), false);
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
cVar.setValue(sanitizeEnumValue(cVar, jsonValue.get<FrameInterpMode>()), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
void ConfigImpl<ui::ControlLayout>::loadFromJson(
|
|
||||||
ConfigVar<ui::ControlLayout>& cVar, const json& jsonValue) {
|
|
||||||
if (!jsonValue.is_object()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const int version = jsonValue.value("version", 0);
|
|
||||||
if (version != ui::ControlLayout::Version) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto controlsIter = jsonValue.find("controls");
|
|
||||||
if (controlsIter == jsonValue.end() || !controlsIter->is_object()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ui::ControlLayout layout{.version = version};
|
|
||||||
for (const auto& control : controlsIter->items()) {
|
|
||||||
if (!ui::is_control_layout_id(control.key())) {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (const auto props = parse_control_props(control.value())) {
|
cVar.setValue(sanitizeEnumValue(cVar, jsonValue.get<FrameInterpMode>()), false);
|
||||||
layout.controls[control.key()] = *props;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
template class ConfigImpl<dusk::FrameInterpMode>;
|
||||||
cVar.setValue(std::move(layout), false);
|
template class ConfigImpl<dusk::MenuScaling>;
|
||||||
|
template class ConfigImpl<dusk::Resampler>;
|
||||||
|
template class ConfigImpl<dusk::MagicArmorMode>;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
|
||||||
void ConfigImpl<ui::ControlLayout>::loadFromArg(
|
|
||||||
ConfigVar<ui::ControlLayout>&, const std::string_view) {
|
|
||||||
throw InvalidConfigError("Touch control layout cannot be parsed from launch arguments");
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
nlohmann::json ConfigImpl<ui::ControlLayout>::dumpToJson(const ConfigVar<ui::ControlLayout>& cVar) {
|
|
||||||
const auto& layout = cVar.getValueForSave();
|
|
||||||
json controls = json::object();
|
|
||||||
for (const auto& [id, props] : layout.controls) {
|
|
||||||
controls[id] = {
|
|
||||||
{"x", props.x},
|
|
||||||
{"y", props.y},
|
|
||||||
{"w", props.w},
|
|
||||||
{"h", props.h},
|
|
||||||
{"scale", props.scale},
|
|
||||||
{"anchor", control_anchor_value(props.anchor)},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
{"version", ui::ControlLayout::Version},
|
|
||||||
{"controls", std::move(controls)},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
template class ConfigImpl<dusk::FrameInterpMode>;
|
|
||||||
template class ConfigImpl<dusk::MenuScaling>;
|
|
||||||
template class ConfigImpl<dusk::Resampler>;
|
|
||||||
template class ConfigImpl<dusk::MagicArmorMode>;
|
|
||||||
template class ConfigImpl<dusk::ui::ControlLayout>;
|
|
||||||
} // namespace dusk::config
|
|
||||||
|
|
||||||
void dusk::config::Register(ConfigVarBase& configVar) {
|
void dusk::config::Register(ConfigVarBase& configVar) {
|
||||||
const auto& name = configVar.getName();
|
const auto& name = configVar.getName();
|
||||||
if (RegistrationDone) {
|
if (RegistrationDone) {
|
||||||
@@ -472,7 +298,9 @@ void dusk::config::Save() {
|
|||||||
}
|
}
|
||||||
const auto configPathString = io::fs_path_to_string(configJsonPath);
|
const auto configPathString = io::fs_path_to_string(configJsonPath);
|
||||||
|
|
||||||
DuskConfigLog.info("Saving config to '{}'", configPathString);
|
DuskConfigLog.info(
|
||||||
|
"Saving config to '{}'",
|
||||||
|
configPathString);
|
||||||
|
|
||||||
json j;
|
json j;
|
||||||
|
|
||||||
|
|||||||
+20
-9
@@ -16,8 +16,9 @@ clock::time_point s_current_snapshot_time{};
|
|||||||
|
|
||||||
std::unordered_map<uintptr_t, clock::time_point> s_interval_last_sample;
|
std::unordered_map<uintptr_t, clock::time_point> s_interval_last_sample;
|
||||||
|
|
||||||
constexpr clock::duration kSimPeriodDuration =
|
float s_sim_rate_hz = 30.0f;
|
||||||
std::chrono::duration_cast<clock::duration>(std::chrono::duration<float>(sim_pace()));
|
clock::duration s_sim_period_duration = std::chrono::duration_cast<clock::duration>(std::chrono::duration<float>(sim_pace()));
|
||||||
|
|
||||||
constexpr clock::duration kAbnormalGapResetThreshold = std::chrono::milliseconds(250);
|
constexpr clock::duration kAbnormalGapResetThreshold = std::chrono::milliseconds(250);
|
||||||
constexpr int kMaxSimTicksPerFrame = 2;
|
constexpr int kMaxSimTicksPerFrame = 2;
|
||||||
|
|
||||||
@@ -32,7 +33,17 @@ void ensure_initialized() {
|
|||||||
|
|
||||||
void reset_frame_timer() {
|
void reset_frame_timer() {
|
||||||
s_previous_sample = clock::now();
|
s_previous_sample = clock::now();
|
||||||
s_current_snapshot_time = s_previous_sample - kSimPeriodDuration;
|
s_current_snapshot_time = s_previous_sample - s_sim_period_duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_sim_rate(float hz) {
|
||||||
|
s_sim_rate_hz = std::max(1.0f, std::min(hz, 1000.0f));
|
||||||
|
s_sim_period_duration = std::chrono::duration_cast<clock::duration>(std::chrono::duration<float>(1.0f / s_sim_rate_hz));
|
||||||
|
reset_frame_timer();
|
||||||
|
}
|
||||||
|
|
||||||
|
float get_sim_rate() {
|
||||||
|
return s_sim_rate_hz;
|
||||||
}
|
}
|
||||||
|
|
||||||
MainLoopPacer advance_main_loop() {
|
MainLoopPacer advance_main_loop() {
|
||||||
@@ -45,12 +56,12 @@ MainLoopPacer advance_main_loop() {
|
|||||||
|
|
||||||
MainLoopPacer out{};
|
MainLoopPacer out{};
|
||||||
out.presentation_dt_seconds = presentation_dt;
|
out.presentation_dt_seconds = presentation_dt;
|
||||||
|
out.sim_pace = 1.0f / s_sim_rate_hz;
|
||||||
|
|
||||||
const bool should_interpolate = dusk::getSettings().game.enableFrameInterpolation.getValue() !=
|
const bool should_interpolate = dusk::getSettings().game.enableFrameInterpolation.getValue() !=
|
||||||
dusk::FrameInterpMode::Off &&
|
dusk::FrameInterpMode::Off &&
|
||||||
!dusk::getTransientSettings().skipFrameRateLimit;
|
!dusk::getTransientSettings().skipFrameRateLimit;
|
||||||
out.is_interpolating = should_interpolate;
|
out.is_interpolating = should_interpolate;
|
||||||
out.sim_pace = sim_pace();
|
|
||||||
|
|
||||||
if (!should_interpolate) {
|
if (!should_interpolate) {
|
||||||
s_current_snapshot_time = now;
|
s_current_snapshot_time = now;
|
||||||
@@ -59,16 +70,16 @@ MainLoopPacer advance_main_loop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (frame_gap > kAbnormalGapResetThreshold) {
|
if (frame_gap > kAbnormalGapResetThreshold) {
|
||||||
s_current_snapshot_time = now - kSimPeriodDuration;
|
s_current_snapshot_time = now - s_sim_period_duration;
|
||||||
out.sim_ticks_to_run = 0;
|
out.sim_ticks_to_run = 0;
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sim_ticks_to_run = 0;
|
int sim_ticks_to_run = 0;
|
||||||
clock::time_point projected_snapshot_time = s_current_snapshot_time;
|
clock::time_point projected_snapshot_time = s_current_snapshot_time;
|
||||||
const clock::time_point render_time = now - kSimPeriodDuration;
|
const clock::time_point render_time = now - s_sim_period_duration;
|
||||||
while (sim_ticks_to_run < kMaxSimTicksPerFrame && projected_snapshot_time < render_time) {
|
while (sim_ticks_to_run < kMaxSimTicksPerFrame && projected_snapshot_time < render_time) {
|
||||||
projected_snapshot_time += kSimPeriodDuration;
|
projected_snapshot_time += s_sim_period_duration;
|
||||||
sim_ticks_to_run++;
|
sim_ticks_to_run++;
|
||||||
}
|
}
|
||||||
out.sim_ticks_to_run = sim_ticks_to_run;
|
out.sim_ticks_to_run = sim_ticks_to_run;
|
||||||
@@ -77,13 +88,13 @@ MainLoopPacer advance_main_loop() {
|
|||||||
|
|
||||||
void commit_sim_tick() {
|
void commit_sim_tick() {
|
||||||
ensure_initialized();
|
ensure_initialized();
|
||||||
s_current_snapshot_time += kSimPeriodDuration;
|
s_current_snapshot_time += s_sim_period_duration;
|
||||||
}
|
}
|
||||||
|
|
||||||
float sample_interpolation_step() {
|
float sample_interpolation_step() {
|
||||||
ensure_initialized();
|
ensure_initialized();
|
||||||
const float step =
|
const float step =
|
||||||
std::chrono::duration<float>(clock::now() - s_current_snapshot_time).count() / sim_pace();
|
std::chrono::duration<float>(clock::now() - s_current_snapshot_time).count() / (1.0f / s_sim_rate_hz);
|
||||||
return std::clamp(step, 0.0f, 1.0f);
|
return std::clamp(step, 0.0f, 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,136 @@
|
|||||||
|
#include "dusk/game_combos.h"
|
||||||
|
|
||||||
|
#include "SSystem/SComponent/c_API_controller_pad.h"
|
||||||
|
#include "SSystem/SComponent/c_xyz.h"
|
||||||
|
#include "d/actor/d_a_alink.h"
|
||||||
|
#include "d/d_com_inf_game.h"
|
||||||
|
#include "dusk/settings.h"
|
||||||
|
#include "m_Do/m_Do_controller_pad.h"
|
||||||
|
|
||||||
|
namespace dusk {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
cXyz s_savedTeleportPos{};
|
||||||
|
s16 s_savedTeleportAngle = 0;
|
||||||
|
bool s_hasTeleportPos = false;
|
||||||
|
|
||||||
|
static daAlink_c* getPlayer() {
|
||||||
|
return (daAlink_c*)dComIfGp_getPlayer(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void consumeButtons(u32 mask) {
|
||||||
|
mDoCPd_c::getCpadInfo(PAD_1).mPressedButtonFlags &= ~mask;
|
||||||
|
mDoCPd_c::getCpadInfo(PAD_1).mButtonFlags &= ~mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Table: holdMask, trigMask, strict, condition, action, consumeMask, exclusive
|
||||||
|
static const GameCombo kCombos[] = {
|
||||||
|
// Move Link (L+R+Y), pass-through, non-exclusive
|
||||||
|
{
|
||||||
|
PAD_TRIGGER_R | PAD_TRIGGER_L,
|
||||||
|
PAD_BUTTON_Y,
|
||||||
|
false,
|
||||||
|
[] { return (bool)getSettings().game.enableMoveLinkCombo; },
|
||||||
|
[] { getTransientSettings().moveLinkActive = !getTransientSettings().moveLinkActive; },
|
||||||
|
0,
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
// Quick Transform (R+Y, strictly only R held)
|
||||||
|
{
|
||||||
|
PAD_TRIGGER_R,
|
||||||
|
PAD_BUTTON_Y,
|
||||||
|
true,
|
||||||
|
[] { return getPlayer() != nullptr; },
|
||||||
|
[] { getPlayer()->handleQuickTransform(); },
|
||||||
|
PAD_BUTTON_Y,
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
// Wolf Howl (R+X)
|
||||||
|
{
|
||||||
|
PAD_TRIGGER_R,
|
||||||
|
PAD_BUTTON_X,
|
||||||
|
false,
|
||||||
|
[] { return getPlayer() != nullptr; },
|
||||||
|
[] { getPlayer()->handleWolfHowl(); },
|
||||||
|
PAD_BUTTON_X,
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
// Teleport save (R+D-pad Up), consumes D-pad Up, exclusive
|
||||||
|
{
|
||||||
|
PAD_TRIGGER_R,
|
||||||
|
PAD_BUTTON_UP,
|
||||||
|
false,
|
||||||
|
[] { return getSettings().game.enableTeleportCombo && getPlayer() != nullptr; },
|
||||||
|
[] {
|
||||||
|
auto* p = getPlayer();
|
||||||
|
s_savedTeleportPos = p->current.pos;
|
||||||
|
s_savedTeleportAngle = p->shape_angle.y;
|
||||||
|
s_hasTeleportPos = true;
|
||||||
|
},
|
||||||
|
PAD_BUTTON_UP,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
// Teleport load (R+D-pad Down), consumes D-pad Down, exclusive
|
||||||
|
{
|
||||||
|
PAD_TRIGGER_R,
|
||||||
|
PAD_BUTTON_DOWN,
|
||||||
|
false,
|
||||||
|
[] {
|
||||||
|
return getSettings().game.enableTeleportCombo && s_hasTeleportPos &&
|
||||||
|
getPlayer() != nullptr;
|
||||||
|
},
|
||||||
|
[] {
|
||||||
|
auto* p = getPlayer();
|
||||||
|
p->current.pos = s_savedTeleportPos;
|
||||||
|
p->shape_angle.y = s_savedTeleportAngle;
|
||||||
|
p->mNormalSpeed = 0.0f;
|
||||||
|
},
|
||||||
|
PAD_BUTTON_DOWN,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
// Moon Jump (R+A, hold), continuous, pass-through, non-exclusive
|
||||||
|
{
|
||||||
|
PAD_TRIGGER_R | PAD_BUTTON_A,
|
||||||
|
0,
|
||||||
|
false,
|
||||||
|
[] { return getSettings().game.moonJump && getPlayer() != nullptr; },
|
||||||
|
[] { getPlayer()->speed.y = 56.0f; },
|
||||||
|
0,
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void processGameCombos() {
|
||||||
|
if (!getSettings().game.enableMoveLinkCombo) {
|
||||||
|
getTransientSettings().moveLinkActive = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const u32 held = mDoCPd_c::getHold(PAD_1);
|
||||||
|
const u32 trig = mDoCPd_c::getTrig(PAD_1);
|
||||||
|
|
||||||
|
for (const auto& combo : kCombos) {
|
||||||
|
if ((held & combo.holdMask) != combo.holdMask) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (combo.strict && (held & ~combo.trigMask) != combo.holdMask) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (combo.trigMask != 0 && !(trig & combo.trigMask)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (combo.condition != nullptr && !combo.condition()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
combo.action();
|
||||||
|
if (combo.consumeMask != 0) {
|
||||||
|
consumeButtons(combo.consumeMask);
|
||||||
|
}
|
||||||
|
if (combo.exclusive) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace dusk
|
||||||
+10
-1
@@ -70,7 +70,16 @@ bool rollgoal_gyro_enabled() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool queryGyroAimContext() {
|
bool queryGyroAimContext() {
|
||||||
return getSettings().game.enableGyroAim.getValue() && dCamera_c::isAimActive();
|
if (!static_cast<bool>(getSettings().game.enableGyroAim)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
daAlink_c* link = daAlink_getAlinkActorClass();
|
||||||
|
if (link == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return link->checkAimContext() && dComIfGp_checkCameraAttentionStatus(link->field_0x317c, 0x10);
|
||||||
}
|
}
|
||||||
|
|
||||||
void read(float dt) {
|
void read(float dt) {
|
||||||
|
|||||||
@@ -238,12 +238,6 @@ namespace dusk {
|
|||||||
getTransientSettings().skipFrameRateLimit = getSettings().game.enableTurboKeybind &&
|
getTransientSettings().skipFrameRateLimit = getSettings().game.enableTurboKeybind &&
|
||||||
(ImGui::IsKeyDown(ImGuiKey_Tab) || getActionBindHoldAnyPort(ActionBinds::TURBO_SPEED_BUTTON));
|
(ImGui::IsKeyDown(ImGuiKey_Tab) || getActionBindHoldAnyPort(ActionBinds::TURBO_SPEED_BUTTON));
|
||||||
|
|
||||||
if (dusk::frame_interp::get_ui_tick_pending() && mDoMain::developmentMode == 1 && (mDoCPd_c::getHold(PAD_1) & (PAD_TRIGGER_R | PAD_TRIGGER_L)) == (PAD_TRIGGER_R | PAD_TRIGGER_L) && mDoCPd_c::getTrigY(PAD_1)) {
|
|
||||||
getTransientSettings().moveLinkActive = !getTransientSettings().moveLinkActive;
|
|
||||||
}
|
|
||||||
if (mDoMain::developmentMode != 1) {
|
|
||||||
getTransientSettings().moveLinkActive = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImGuiConsole::PreDraw() {
|
void ImGuiConsole::PreDraw() {
|
||||||
|
|||||||
@@ -20,11 +20,7 @@
|
|||||||
namespace dusk {
|
namespace dusk {
|
||||||
namespace {
|
namespace {
|
||||||
std::string GetAssetPath(const char* assetName) {
|
std::string GetAssetPath(const char* assetName) {
|
||||||
#ifdef DUSK_ASSET_DIR
|
|
||||||
const char* basePath = DUSK_ASSET_DIR;
|
|
||||||
#else
|
|
||||||
const char* basePath = SDL_GetBasePath();
|
const char* basePath = SDL_GetBasePath();
|
||||||
#endif
|
|
||||||
if (basePath != nullptr && basePath[0] != '\0') {
|
if (basePath != nullptr && basePath[0] != '\0') {
|
||||||
return std::string(basePath) + "res/" + assetName;
|
return std::string(basePath) + "res/" + assetName;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,12 @@
|
|||||||
#include "dusk/logging.h"
|
#include "dusk/logging.h"
|
||||||
#include <algorithm>
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <cctype>
|
|
||||||
#include <cstdint>
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "dusk/io.hpp"
|
#include "dusk/io.hpp"
|
||||||
#include "tracy/Tracy.hpp"
|
#include "tracy/Tracy.hpp"
|
||||||
@@ -48,9 +44,6 @@ namespace {
|
|||||||
// We use this to check if the LogState is destroyed before attempting to acquire it.
|
// We use this to check if the LogState is destroyed before attempting to acquire it.
|
||||||
std::atomic g_logStateAlive(true);
|
std::atomic g_logStateAlive(true);
|
||||||
std::atomic<int> g_logFd(-1);
|
std::atomic<int> g_logFd(-1);
|
||||||
constexpr size_t MaxRetainedLogCount = 10;
|
|
||||||
constexpr size_t MaxRetainedOldLogCount = MaxRetainedLogCount - 1;
|
|
||||||
constexpr uintmax_t MaxRetainedOldLogBytes = 100ull * 1024ull * 1024ull;
|
|
||||||
|
|
||||||
struct LogState {
|
struct LogState {
|
||||||
std::mutex mutex;
|
std::mutex mutex;
|
||||||
@@ -98,121 +91,6 @@ FILE* LogStreamForLevel(AuroraLogLevel level) {
|
|||||||
return level >= LOG_ERROR ? stderr : stdout;
|
return level >= LOG_ERROR ? stderr : stdout;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct LogFileCandidate {
|
|
||||||
std::filesystem::path path;
|
|
||||||
std::string filename;
|
|
||||||
uintmax_t size;
|
|
||||||
};
|
|
||||||
|
|
||||||
void warn_log_cleanup_failure(
|
|
||||||
const char* action, const std::filesystem::path& path, const std::error_code& ec) {
|
|
||||||
std::fprintf(stderr, "[WARNING | dusk] Failed to %s '%s': %s\n", action,
|
|
||||||
dusk::io::fs_path_to_string(path).c_str(), ec.message().c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_digit_at(const std::string_view value, size_t index) {
|
|
||||||
return std::isdigit(static_cast<unsigned char>(value[index])) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_generated_log_file_name(const std::filesystem::path& path) {
|
|
||||||
const std::string filename = path.filename().string();
|
|
||||||
constexpr std::string_view currentPrefix = "dusklight-"sv;
|
|
||||||
constexpr std::string_view legacyPrefix = "dusk-"sv;
|
|
||||||
constexpr std::string_view suffix = ".log"sv;
|
|
||||||
size_t timestampOffset = 0;
|
|
||||||
|
|
||||||
if (filename.starts_with(currentPrefix)) {
|
|
||||||
timestampOffset = currentPrefix.size();
|
|
||||||
} else if (filename.starts_with(legacyPrefix)) {
|
|
||||||
timestampOffset = legacyPrefix.size();
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filename.size() != timestampOffset + 19 || !filename.ends_with(suffix) ||
|
|
||||||
filename[timestampOffset + 8] != '-') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = timestampOffset; i < timestampOffset + 8; ++i) {
|
|
||||||
if (!is_digit_at(filename, i)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (size_t i = timestampOffset + 9; i < timestampOffset + 15; ++i) {
|
|
||||||
if (!is_digit_at(filename, i)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void delete_log_file(const std::filesystem::path& path) {
|
|
||||||
std::error_code ec;
|
|
||||||
std::filesystem::remove(path, ec);
|
|
||||||
if (ec) {
|
|
||||||
warn_log_cleanup_failure("remove old log file", path, ec);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void prune_old_log_files(const std::filesystem::path& logsDir) {
|
|
||||||
std::error_code ec;
|
|
||||||
std::filesystem::directory_iterator entries{logsDir, ec};
|
|
||||||
if (ec) {
|
|
||||||
warn_log_cleanup_failure("inspect log directory", logsDir, ec);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<LogFileCandidate> candidates;
|
|
||||||
for (const auto& entry : entries) {
|
|
||||||
const std::filesystem::path path = entry.path();
|
|
||||||
if (!is_generated_log_file_name(path)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
ec.clear();
|
|
||||||
const auto status = entry.symlink_status(ec);
|
|
||||||
if (ec) {
|
|
||||||
warn_log_cleanup_failure("inspect log file", path, ec);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!std::filesystem::is_regular_file(status)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
ec.clear();
|
|
||||||
const uintmax_t size = entry.file_size(ec);
|
|
||||||
if (ec) {
|
|
||||||
warn_log_cleanup_failure("inspect size of log file", path, ec);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
candidates.push_back({path, path.filename().string(), size});
|
|
||||||
}
|
|
||||||
|
|
||||||
std::sort(candidates.begin(), candidates.end(),
|
|
||||||
[](const LogFileCandidate& a, const LogFileCandidate& b) {
|
|
||||||
return a.filename > b.filename;
|
|
||||||
});
|
|
||||||
|
|
||||||
const size_t retainedCount = std::min(candidates.size(), MaxRetainedOldLogCount);
|
|
||||||
uintmax_t retainedBytes = 0;
|
|
||||||
for (size_t i = 0; i < retainedCount; ++i) {
|
|
||||||
retainedBytes += candidates[i].size;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t retainedAfterSizeLimit = retainedCount;
|
|
||||||
while (retainedAfterSizeLimit > 0 && retainedBytes > MaxRetainedOldLogBytes) {
|
|
||||||
--retainedAfterSizeLimit;
|
|
||||||
retainedBytes -= candidates[retainedAfterSizeLimit].size;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = retainedAfterSizeLimit; i < candidates.size(); ++i) {
|
|
||||||
delete_log_file(candidates[i].path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string MakeTimestampedLogName() {
|
std::string MakeTimestampedLogName() {
|
||||||
const auto now = std::chrono::system_clock::now();
|
const auto now = std::chrono::system_clock::now();
|
||||||
const std::time_t nowTime = std::chrono::system_clock::to_time_t(now);
|
const std::time_t nowTime = std::chrono::system_clock::to_time_t(now);
|
||||||
@@ -352,7 +230,6 @@ void dusk::InitializeFileLogging(const std::filesystem::path& configDir, AuroraL
|
|||||||
io::fs_path_to_string(logsDir).c_str(), ec.message().c_str());
|
io::fs_path_to_string(logsDir).c_str(), ec.message().c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
prune_old_log_files(logsDir);
|
|
||||||
|
|
||||||
const std::filesystem::path logPath = logsDir / MakeTimestampedLogName();
|
const std::filesystem::path logPath = logsDir / MakeTimestampedLogName();
|
||||||
g_logState.file = io::FileStream::Create(logPath).ToInner();
|
g_logState.file = io::FileStream::Create(logPath).ToInner();
|
||||||
|
|||||||
@@ -1,386 +0,0 @@
|
|||||||
#include "dusk/menu_pointer.h"
|
|
||||||
|
|
||||||
#include "m_Do/m_Do_graphic.h"
|
|
||||||
#include "d/d_pane_class.h"
|
|
||||||
#include "dusk/settings.h"
|
|
||||||
|
|
||||||
#include <aurora/rmlui.hpp>
|
|
||||||
#include <dolphin/pad.h>
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
namespace dusk::menu_pointer {
|
|
||||||
namespace {
|
|
||||||
State s_state;
|
|
||||||
bool s_clickConsumed = false;
|
|
||||||
Context s_lastContext = Context::None;
|
|
||||||
Context s_currentContext = Context::None;
|
|
||||||
u8 s_lastDialogChoice = 0xFF;
|
|
||||||
u8 s_currentDialogChoice = 0xFF;
|
|
||||||
bool s_lastDialogChoiceValid = false;
|
|
||||||
bool s_currentDialogChoiceValid = false;
|
|
||||||
bool s_lastDialogClicked = false;
|
|
||||||
bool s_currentDialogClicked = false;
|
|
||||||
bool s_mouseActive = false;
|
|
||||||
bool s_mouseButtonCaptured = false;
|
|
||||||
s32 s_mouseButton = -1;
|
|
||||||
u32 s_suppressedPadHoldMask = 0;
|
|
||||||
u32 s_suppressedPadNextReadMask = 0;
|
|
||||||
Context s_deferredActivationContext = Context::None;
|
|
||||||
u8 s_deferredActivationTarget = 0xFF;
|
|
||||||
|
|
||||||
s32 scancode_from_rml_button(s32 button) noexcept {
|
|
||||||
switch (button) {
|
|
||||||
case 0:
|
|
||||||
return PAD_KEY_MOUSE_LEFT;
|
|
||||||
case 1:
|
|
||||||
return PAD_KEY_MOUSE_RIGHT;
|
|
||||||
case 2:
|
|
||||||
return PAD_KEY_MOUSE_MIDDLE;
|
|
||||||
default:
|
|
||||||
return PAD_KEY_INVALID;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_mouse_scancode(s32 scancode) noexcept {
|
|
||||||
return scancode >= PAD_KEY_MOUSE_X2 && scancode <= PAD_KEY_MOUSE_LEFT;
|
|
||||||
}
|
|
||||||
|
|
||||||
PADButton pad_button_for_scancode(u32 port, s32 scancode) noexcept {
|
|
||||||
u32 count = 0;
|
|
||||||
PADKeyButtonBinding* bindings = PADGetKeyButtonBindings(port, &count);
|
|
||||||
if (bindings == nullptr) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (u32 i = 0; i < count; ++i) {
|
|
||||||
if (bindings[i].scancode == scancode) {
|
|
||||||
return bindings[i].padButton;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
s32 menu_confirm_mouse_scancode() noexcept {
|
|
||||||
constexpr u32 port = PAD_CHAN0;
|
|
||||||
u32 count = 0;
|
|
||||||
PADKeyButtonBinding* bindings = PADGetKeyButtonBindings(port, &count);
|
|
||||||
if (bindings == nullptr) {
|
|
||||||
return PAD_KEY_MOUSE_LEFT;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (u32 i = 0; i < count; ++i) {
|
|
||||||
if (bindings[i].padButton == PAD_BUTTON_A && is_mouse_scancode(bindings[i].scancode)) {
|
|
||||||
return bindings[i].scancode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return pad_button_for_scancode(port, PAD_KEY_MOUSE_LEFT) != 0 ? PAD_KEY_INVALID :
|
|
||||||
PAD_KEY_MOUSE_LEFT;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool mouse_button_is_menu_confirm(s32 button) noexcept {
|
|
||||||
const s32 scancode = scancode_from_rml_button(button);
|
|
||||||
return scancode != PAD_KEY_INVALID && scancode == menu_confirm_mouse_scancode();
|
|
||||||
}
|
|
||||||
|
|
||||||
void suppress_pad_for_mouse_button(s32 button, bool held) noexcept {
|
|
||||||
const s32 scancode = scancode_from_rml_button(button);
|
|
||||||
if (scancode == PAD_KEY_INVALID) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const PADButton padButton = pad_button_for_scancode(PAD_CHAN0, scancode);
|
|
||||||
if (padButton == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
s_suppressedPadNextReadMask |= padButton;
|
|
||||||
if (held) {
|
|
||||||
s_suppressedPadHoldMask |= padButton;
|
|
||||||
} else {
|
|
||||||
s_suppressedPadHoldMask &= ~padButton;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_position_from_rml(f32 x, f32 y) noexcept {
|
|
||||||
auto* context = aurora::rmlui::get_context();
|
|
||||||
if (context == nullptr) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto dimensions = context->GetDimensions();
|
|
||||||
const f32 width = std::max(static_cast<f32>(dimensions.x), 1.0f);
|
|
||||||
const f32 height = std::max(static_cast<f32>(dimensions.y), 1.0f);
|
|
||||||
|
|
||||||
s_state.x = mDoGph_gInf_c::getMinXF() + x / width * mDoGph_gInf_c::getWidthF();
|
|
||||||
s_state.y = mDoGph_gInf_c::getMinYF() + y / height * mDoGph_gInf_c::getHeightF();
|
|
||||||
s_state.valid = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void clear_input_state() noexcept {
|
|
||||||
s_state = {};
|
|
||||||
s_clickConsumed = false;
|
|
||||||
s_lastDialogChoice = 0xFF;
|
|
||||||
s_currentDialogChoice = 0xFF;
|
|
||||||
s_lastDialogChoiceValid = false;
|
|
||||||
s_currentDialogChoiceValid = false;
|
|
||||||
s_lastDialogClicked = false;
|
|
||||||
s_currentDialogClicked = false;
|
|
||||||
s_mouseActive = false;
|
|
||||||
s_mouseButtonCaptured = false;
|
|
||||||
s_mouseButton = -1;
|
|
||||||
s_suppressedPadHoldMask = 0;
|
|
||||||
s_suppressedPadNextReadMask = 0;
|
|
||||||
s_deferredActivationContext = Context::None;
|
|
||||||
s_deferredActivationTarget = 0xFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
bool handle_fallthrough_pointer(f32 x, f32 y, Phase phase, bool touch, s32 mouseButton) noexcept {
|
|
||||||
if (!enabled()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
s_clickConsumed = false;
|
|
||||||
|
|
||||||
if (!touch) {
|
|
||||||
if (phase == Phase::Press) {
|
|
||||||
if (!mouse_button_is_menu_confirm(mouseButton)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
s_mouseButtonCaptured = true;
|
|
||||||
s_mouseButton = mouseButton;
|
|
||||||
suppress_pad_for_mouse_button(mouseButton, true);
|
|
||||||
} else if (phase == Phase::Release) {
|
|
||||||
if (!s_mouseButtonCaptured || s_mouseButton != mouseButton) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
suppress_pad_for_mouse_button(mouseButton, false);
|
|
||||||
s_mouseButtonCaptured = false;
|
|
||||||
s_mouseButton = -1;
|
|
||||||
} else if (phase == Phase::Cancel) {
|
|
||||||
if (s_mouseButtonCaptured) {
|
|
||||||
suppress_pad_for_mouse_button(s_mouseButton, false);
|
|
||||||
s_mouseButtonCaptured = false;
|
|
||||||
s_mouseButton = -1;
|
|
||||||
} else if (!s_mouseActive) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s_mouseActive = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (phase != Phase::Cancel) {
|
|
||||||
set_position_from_rml(x, y);
|
|
||||||
}
|
|
||||||
s_state.touch = touch;
|
|
||||||
|
|
||||||
switch (phase) {
|
|
||||||
case Phase::Press:
|
|
||||||
s_state.down = true;
|
|
||||||
s_state.pressed = true;
|
|
||||||
break;
|
|
||||||
case Phase::Release:
|
|
||||||
s_state.down = false;
|
|
||||||
s_state.released = true;
|
|
||||||
s_state.clicked = true;
|
|
||||||
break;
|
|
||||||
case Phase::Cancel:
|
|
||||||
s_state.down = false;
|
|
||||||
break;
|
|
||||||
case Phase::Move:
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void begin_game_frame() noexcept {
|
|
||||||
s_currentContext = Context::None;
|
|
||||||
s_currentDialogChoice = 0xFF;
|
|
||||||
s_currentDialogChoiceValid = false;
|
|
||||||
s_currentDialogClicked = false;
|
|
||||||
s_clickConsumed = false;
|
|
||||||
if (!enabled()) {
|
|
||||||
clear_input_state();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void end_game_frame() noexcept {
|
|
||||||
s_lastContext = s_currentContext;
|
|
||||||
s_lastDialogChoice = s_currentDialogChoice;
|
|
||||||
s_lastDialogChoiceValid = s_currentDialogChoiceValid;
|
|
||||||
s_lastDialogClicked = s_currentDialogClicked;
|
|
||||||
s_state.pressed = false;
|
|
||||||
s_state.released = false;
|
|
||||||
s_state.clicked = false;
|
|
||||||
if (!s_state.down) {
|
|
||||||
s_state.valid = false;
|
|
||||||
}
|
|
||||||
s_clickConsumed = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void begin_context(Context context) noexcept {
|
|
||||||
if (context == Context::None) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (s_lastContext == Context::None && s_currentContext == Context::None) {
|
|
||||||
s_state = {};
|
|
||||||
s_mouseActive = false;
|
|
||||||
s_mouseButtonCaptured = false;
|
|
||||||
s_mouseButton = -1;
|
|
||||||
s_suppressedPadHoldMask = 0;
|
|
||||||
s_suppressedPadNextReadMask = 0;
|
|
||||||
s_deferredActivationContext = Context::None;
|
|
||||||
s_deferredActivationTarget = 0xFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
s_currentContext = context;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool active() noexcept {
|
|
||||||
return s_currentContext != Context::None || s_lastContext != Context::None;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool enabled() noexcept {
|
|
||||||
return getSettings().game.enableMenuPointer.getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool mouse_capture_active() noexcept {
|
|
||||||
return enabled() && s_mouseButtonCaptured;
|
|
||||||
}
|
|
||||||
|
|
||||||
const State& state() noexcept {
|
|
||||||
return s_state;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool consume_click() noexcept {
|
|
||||||
if (!s_state.clicked || s_clickConsumed) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
s_clickConsumed = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_dialog_choice(u8 choice, bool clicked) noexcept {
|
|
||||||
s_currentDialogChoice = choice;
|
|
||||||
s_currentDialogChoiceValid = true;
|
|
||||||
s_currentDialogClicked = clicked;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool get_dialog_choice(u8& choice) noexcept {
|
|
||||||
if (s_currentDialogChoiceValid) {
|
|
||||||
choice = s_currentDialogChoice;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (s_lastDialogChoiceValid) {
|
|
||||||
choice = s_lastDialogChoice;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool consume_dialog_click(u8& choice) noexcept {
|
|
||||||
if (s_currentDialogChoiceValid && s_currentDialogClicked) {
|
|
||||||
choice = s_currentDialogChoice;
|
|
||||||
s_currentDialogClicked = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (s_lastDialogChoiceValid && s_lastDialogClicked) {
|
|
||||||
choice = s_lastDialogChoice;
|
|
||||||
s_lastDialogClicked = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void defer_activation(Context context, u8 target) noexcept {
|
|
||||||
s_deferredActivationContext = context;
|
|
||||||
s_deferredActivationTarget = target;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool consume_deferred_activation(Context context, u8 target) noexcept {
|
|
||||||
if (s_deferredActivationContext != context || s_deferredActivationTarget != target) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
s_deferredActivationContext = Context::None;
|
|
||||||
s_deferredActivationTarget = 0xFF;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void clear_deferred_activation(Context context) noexcept {
|
|
||||||
if (s_deferredActivationContext != context) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
s_deferredActivationContext = Context::None;
|
|
||||||
s_deferredActivationTarget = 0xFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 suppressed_pad_buttons(u32 port) noexcept {
|
|
||||||
if (port != PAD_CHAN0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return s_suppressedPadHoldMask | s_suppressedPadNextReadMask;
|
|
||||||
}
|
|
||||||
|
|
||||||
void finish_pad_suppression_read(u32 port) noexcept {
|
|
||||||
if (port != PAD_CHAN0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
s_suppressedPadNextReadMask = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool hit_rect(f32 left, f32 top, f32 right, f32 bottom, f32 padding) noexcept {
|
|
||||||
const auto& state = menu_pointer::state();
|
|
||||||
if (!state.valid) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (left > right) {
|
|
||||||
std::swap(left, right);
|
|
||||||
}
|
|
||||||
if (top > bottom) {
|
|
||||||
std::swap(top, bottom);
|
|
||||||
}
|
|
||||||
|
|
||||||
return state.x >= left - padding && state.x <= right + padding && state.y >= top - padding &&
|
|
||||||
state.y <= bottom + padding;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool hit_pane(CPaneMgr* pane, f32 padding) noexcept {
|
|
||||||
if (pane == nullptr || pane->getPanePtr() == nullptr) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Mtx mtx;
|
|
||||||
Vec v0 = pane->getGlobalVtx(&mtx, 0, false, 0);
|
|
||||||
Vec v1 = pane->getGlobalVtx(&mtx, 1, false, 0);
|
|
||||||
Vec v2 = pane->getGlobalVtx(&mtx, 2, false, 0);
|
|
||||||
Vec v3 = pane->getGlobalVtx(&mtx, 3, false, 0);
|
|
||||||
const f32 left = std::min({v0.x, v1.x, v2.x, v3.x});
|
|
||||||
const f32 right = std::max({v0.x, v1.x, v2.x, v3.x});
|
|
||||||
const f32 top = std::min({v0.y, v1.y, v2.y, v3.y});
|
|
||||||
const f32 bottom = std::max({v0.y, v1.y, v2.y, v3.y});
|
|
||||||
return hit_rect(left, top, right, bottom, padding);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool hit_pane(J2DPane* pane, f32 padding) noexcept {
|
|
||||||
if (pane == nullptr || !pane->isVisible()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const JGeometry::TBox2<f32>& bounds = pane->getBounds();
|
|
||||||
return hit_rect(bounds.i.x, bounds.i.y, bounds.f.x, bounds.f.y, padding);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace dusk::menu_pointer
|
|
||||||
+11
-3
@@ -1,5 +1,4 @@
|
|||||||
#include "dusk/mouse.h"
|
#include "dusk/mouse.h"
|
||||||
#include "dusk/menu_pointer.h"
|
|
||||||
#include "dusk/settings.h"
|
#include "dusk/settings.h"
|
||||||
#include "dusk/ui/ui.hpp"
|
#include "dusk/ui/ui.hpp"
|
||||||
#include "d/actor/d_a_alink.h"
|
#include "d/actor/d_a_alink.h"
|
||||||
@@ -27,7 +26,16 @@ void reset_deltas() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool queryMouseAimContext() {
|
bool queryMouseAimContext() {
|
||||||
return getSettings().game.enableMouseAim.getValue() && dCamera_c::isAimActive();
|
if (!getSettings().game.enableMouseAim) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
daAlink_c* link = daAlink_getAlinkActorClass();
|
||||||
|
if (link == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return link->checkAimContext() && dComIfGp_checkCameraAttentionStatus(link->field_0x317c, 0x10);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wantMouseCapture() {
|
bool wantMouseCapture() {
|
||||||
@@ -42,7 +50,7 @@ bool isWindowFocused(SDL_Window* window) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool shouldCaptureMouse(SDL_Window* window) {
|
bool shouldCaptureMouse(SDL_Window* window) {
|
||||||
if (window == nullptr || ui::any_document_visible() || menu_pointer::active()) {
|
if (window == nullptr || ui::any_document_visible()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return wantMouseCapture() && isWindowFocused(window);
|
return wantMouseCapture() && isWindowFocused(window);
|
||||||
|
|||||||
+5
-37
@@ -11,9 +11,6 @@ UserSettings g_userSettings = {
|
|||||||
.enableFpsOverlay {"game.enableFpsOverlay", false},
|
.enableFpsOverlay {"game.enableFpsOverlay", false},
|
||||||
.fpsOverlayCorner {"game.fpsOverlayCorner", 0},
|
.fpsOverlayCorner {"game.fpsOverlayCorner", 0},
|
||||||
.maxFrameRate {"video.maxFrameRate", 240},
|
.maxFrameRate {"video.maxFrameRate", 240},
|
||||||
.rememberWindowSize {"video.rememberWindowSize", false},
|
|
||||||
.lastWindowWidth {"video.lastWindowWidth", 0},
|
|
||||||
.lastWindowHeight {"video.lastWindowHeight", 0},
|
|
||||||
},
|
},
|
||||||
|
|
||||||
.audio = {
|
.audio = {
|
||||||
@@ -95,9 +92,6 @@ UserSettings g_userSettings = {
|
|||||||
.mouseCameraSensitivity {"game.mouseCameraSensitivity", 1.0f},
|
.mouseCameraSensitivity {"game.mouseCameraSensitivity", 1.0f},
|
||||||
.invertMouseY {"game.invertMouseY", false},
|
.invertMouseY {"game.invertMouseY", false},
|
||||||
.freeCamera {"game.freeCamera", false},
|
.freeCamera {"game.freeCamera", false},
|
||||||
.enableTouchControls {"game.enableTouchControls", false},
|
|
||||||
.enableMenuPointer {"game.enableMenuPointer", true},
|
|
||||||
.touchControlsLayout {"game.touchControlsLayout", ui::ControlLayout{}},
|
|
||||||
.invertCameraXAxis {"game.invertCameraXAxis", false},
|
.invertCameraXAxis {"game.invertCameraXAxis", false},
|
||||||
.invertCameraYAxis {"game.invertCameraYAxis", false},
|
.invertCameraYAxis {"game.invertCameraYAxis", false},
|
||||||
.invertFirstPersonXAxis {"game.invertFirstPersonXAxis", false},
|
.invertFirstPersonXAxis {"game.invertFirstPersonXAxis", false},
|
||||||
@@ -106,8 +100,6 @@ UserSettings g_userSettings = {
|
|||||||
.invertAirSwimY {"game.invertAirSwimY", false},
|
.invertAirSwimY {"game.invertAirSwimY", false},
|
||||||
.freeCameraXSensitivity {"game.freeCameraXSensitivity", 1.0f},
|
.freeCameraXSensitivity {"game.freeCameraXSensitivity", 1.0f},
|
||||||
.freeCameraYSensitivity {"game.freeCameraYSensitivity", 1.0f},
|
.freeCameraYSensitivity {"game.freeCameraYSensitivity", 1.0f},
|
||||||
.touchCameraXSensitivity {"game.touchCameraXSensitivity", 1.0f},
|
|
||||||
.touchCameraYSensitivity {"game.touchCameraYSensitivity", 1.0f},
|
|
||||||
.debugFlyCam {"game.debugFlyCam", false},
|
.debugFlyCam {"game.debugFlyCam", false},
|
||||||
.debugFlyCamLockEvents {"game.debugFlyCamLockEvents", true},
|
.debugFlyCamLockEvents {"game.debugFlyCamLockEvents", true},
|
||||||
.allowBackgroundInput {"game.allowBackgroundInput", true},
|
.allowBackgroundInput {"game.allowBackgroundInput", true},
|
||||||
@@ -152,7 +144,9 @@ UserSettings g_userSettings = {
|
|||||||
.recordingMode {"game.recordingMode", false},
|
.recordingMode {"game.recordingMode", false},
|
||||||
.removeQuestMapMarkers {"game.removeQuestMapMarkers", false},
|
.removeQuestMapMarkers {"game.removeQuestMapMarkers", false},
|
||||||
.showInputViewer {"game.showInputViewer", false},
|
.showInputViewer {"game.showInputViewer", false},
|
||||||
.showInputViewerGyro {"game.showInputViewerGyro", false}
|
.showInputViewerGyro {"game.showInputViewerGyro", false},
|
||||||
|
.enableMoveLinkCombo {"game.enableMoveLinkCombo", false},
|
||||||
|
.enableTeleportCombo {"game.enableTeleportCombo", false}
|
||||||
},
|
},
|
||||||
|
|
||||||
.backend = {
|
.backend = {
|
||||||
@@ -181,18 +175,6 @@ UserSettings g_userSettings = {
|
|||||||
ActionBindConfigVar{"actionBindings.callMidna_port2", PAD_NATIVE_BUTTON_INVALID},
|
ActionBindConfigVar{"actionBindings.callMidna_port2", PAD_NATIVE_BUTTON_INVALID},
|
||||||
ActionBindConfigVar{"actionBindings.callMidna_port3", PAD_NATIVE_BUTTON_INVALID},
|
ActionBindConfigVar{"actionBindings.callMidna_port3", PAD_NATIVE_BUTTON_INVALID},
|
||||||
},
|
},
|
||||||
.openMapScreen {
|
|
||||||
ActionBindConfigVar{"actionBindings.openMapScreen_port0", PAD_NATIVE_BUTTON_INVALID},
|
|
||||||
ActionBindConfigVar{"actionBindings.openMapScreen_port1", PAD_NATIVE_BUTTON_INVALID},
|
|
||||||
ActionBindConfigVar{"actionBindings.openMapScreen_port2", PAD_NATIVE_BUTTON_INVALID},
|
|
||||||
ActionBindConfigVar{"actionBindings.openMapScreen_port3", PAD_NATIVE_BUTTON_INVALID},
|
|
||||||
},
|
|
||||||
.toggleMinimap {
|
|
||||||
ActionBindConfigVar{"actionBindings.toggleMinimap_port0", PAD_NATIVE_BUTTON_INVALID},
|
|
||||||
ActionBindConfigVar{"actionBindings.toggleMinimap_port1", PAD_NATIVE_BUTTON_INVALID},
|
|
||||||
ActionBindConfigVar{"actionBindings.toggleMinimap_port2", PAD_NATIVE_BUTTON_INVALID},
|
|
||||||
ActionBindConfigVar{"actionBindings.toggleMinimap_port3", PAD_NATIVE_BUTTON_INVALID},
|
|
||||||
},
|
|
||||||
.openDusklightMenu {
|
.openDusklightMenu {
|
||||||
ActionBindConfigVar{"actionBindings.openDusklightMenu_port0", PAD_NATIVE_BUTTON_INVALID},
|
ActionBindConfigVar{"actionBindings.openDusklightMenu_port0", PAD_NATIVE_BUTTON_INVALID},
|
||||||
ActionBindConfigVar{"actionBindings.openDusklightMenu_port1", PAD_NATIVE_BUTTON_INVALID},
|
ActionBindConfigVar{"actionBindings.openDusklightMenu_port1", PAD_NATIVE_BUTTON_INVALID},
|
||||||
@@ -220,9 +202,6 @@ void registerSettings() {
|
|||||||
Register(g_userSettings.video.enableFpsOverlay);
|
Register(g_userSettings.video.enableFpsOverlay);
|
||||||
Register(g_userSettings.video.fpsOverlayCorner);
|
Register(g_userSettings.video.fpsOverlayCorner);
|
||||||
Register(g_userSettings.video.maxFrameRate);
|
Register(g_userSettings.video.maxFrameRate);
|
||||||
Register(g_userSettings.video.rememberWindowSize);
|
|
||||||
Register(g_userSettings.video.lastWindowWidth);
|
|
||||||
Register(g_userSettings.video.lastWindowHeight);
|
|
||||||
|
|
||||||
// Audio
|
// Audio
|
||||||
Register(g_userSettings.audio.masterVolume);
|
Register(g_userSettings.audio.masterVolume);
|
||||||
@@ -263,8 +242,6 @@ void registerSettings() {
|
|||||||
Register(g_userSettings.game.invertAirSwimY);
|
Register(g_userSettings.game.invertAirSwimY);
|
||||||
Register(g_userSettings.game.freeCameraXSensitivity);
|
Register(g_userSettings.game.freeCameraXSensitivity);
|
||||||
Register(g_userSettings.game.freeCameraYSensitivity);
|
Register(g_userSettings.game.freeCameraYSensitivity);
|
||||||
Register(g_userSettings.game.touchCameraXSensitivity);
|
|
||||||
Register(g_userSettings.game.touchCameraYSensitivity);
|
|
||||||
Register(g_userSettings.game.minimalHUD);
|
Register(g_userSettings.game.minimalHUD);
|
||||||
Register(g_userSettings.game.hudScale);
|
Register(g_userSettings.game.hudScale);
|
||||||
Register(g_userSettings.game.pauseOnFocusLost);
|
Register(g_userSettings.game.pauseOnFocusLost);
|
||||||
@@ -300,6 +277,8 @@ void registerSettings() {
|
|||||||
Register(g_userSettings.game.removeQuestMapMarkers);
|
Register(g_userSettings.game.removeQuestMapMarkers);
|
||||||
Register(g_userSettings.game.showInputViewer);
|
Register(g_userSettings.game.showInputViewer);
|
||||||
Register(g_userSettings.game.showInputViewerGyro);
|
Register(g_userSettings.game.showInputViewerGyro);
|
||||||
|
Register(g_userSettings.game.enableMoveLinkCombo);
|
||||||
|
Register(g_userSettings.game.enableTeleportCombo);
|
||||||
Register(g_userSettings.game.fastSpinner);
|
Register(g_userSettings.game.fastSpinner);
|
||||||
Register(g_userSettings.game.infiniteHearts);
|
Register(g_userSettings.game.infiniteHearts);
|
||||||
Register(g_userSettings.game.infiniteArrows);
|
Register(g_userSettings.game.infiniteArrows);
|
||||||
@@ -329,9 +308,6 @@ void registerSettings() {
|
|||||||
Register(g_userSettings.game.mouseCameraSensitivity);
|
Register(g_userSettings.game.mouseCameraSensitivity);
|
||||||
Register(g_userSettings.game.invertMouseY);
|
Register(g_userSettings.game.invertMouseY);
|
||||||
Register(g_userSettings.game.freeCamera);
|
Register(g_userSettings.game.freeCamera);
|
||||||
Register(g_userSettings.game.enableTouchControls);
|
|
||||||
Register(g_userSettings.game.enableMenuPointer);
|
|
||||||
Register(g_userSettings.game.touchControlsLayout);
|
|
||||||
Register(g_userSettings.game.debugFlyCam);
|
Register(g_userSettings.game.debugFlyCam);
|
||||||
Register(g_userSettings.game.debugFlyCamLockEvents);
|
Register(g_userSettings.game.debugFlyCamLockEvents);
|
||||||
Register(g_userSettings.game.allowBackgroundInput);
|
Register(g_userSettings.game.allowBackgroundInput);
|
||||||
@@ -359,14 +335,6 @@ void registerSettings() {
|
|||||||
Register(g_userSettings.actionBindings.callMidna[1]);
|
Register(g_userSettings.actionBindings.callMidna[1]);
|
||||||
Register(g_userSettings.actionBindings.callMidna[2]);
|
Register(g_userSettings.actionBindings.callMidna[2]);
|
||||||
Register(g_userSettings.actionBindings.callMidna[3]);
|
Register(g_userSettings.actionBindings.callMidna[3]);
|
||||||
Register(g_userSettings.actionBindings.openMapScreen[0]);
|
|
||||||
Register(g_userSettings.actionBindings.openMapScreen[1]);
|
|
||||||
Register(g_userSettings.actionBindings.openMapScreen[2]);
|
|
||||||
Register(g_userSettings.actionBindings.openMapScreen[3]);
|
|
||||||
Register(g_userSettings.actionBindings.toggleMinimap[0]);
|
|
||||||
Register(g_userSettings.actionBindings.toggleMinimap[1]);
|
|
||||||
Register(g_userSettings.actionBindings.toggleMinimap[2]);
|
|
||||||
Register(g_userSettings.actionBindings.toggleMinimap[3]);
|
|
||||||
Register(g_userSettings.actionBindings.openDusklightMenu[0]);
|
Register(g_userSettings.actionBindings.openDusklightMenu[0]);
|
||||||
Register(g_userSettings.actionBindings.openDusklightMenu[1]);
|
Register(g_userSettings.actionBindings.openDusklightMenu[1]);
|
||||||
Register(g_userSettings.actionBindings.openDusklightMenu[2]);
|
Register(g_userSettings.actionBindings.openDusklightMenu[2]);
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
#include "dusk/touch_camera.h"
|
|
||||||
|
|
||||||
namespace dusk::touch_camera {
|
|
||||||
namespace {
|
|
||||||
float s_yaw_dp = 0.0f;
|
|
||||||
float s_pitch_dp = 0.0f;
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
void add_delta(float yaw_dp, float pitch_dp) noexcept {
|
|
||||||
s_yaw_dp += yaw_dp;
|
|
||||||
s_pitch_dp += pitch_dp;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool consume_delta(float& yaw_dp, float& pitch_dp) noexcept {
|
|
||||||
yaw_dp = s_yaw_dp;
|
|
||||||
pitch_dp = s_pitch_dp;
|
|
||||||
clear();
|
|
||||||
return yaw_dp != 0.0f || pitch_dp != 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
void clear() noexcept {
|
|
||||||
s_yaw_dp = 0.0f;
|
|
||||||
s_pitch_dp = 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace dusk::touch_camera
|
|
||||||
@@ -19,6 +19,8 @@ public:
|
|||||||
void set_text(const Rml::String& text);
|
void set_text(const Rml::String& text);
|
||||||
Button& on_pressed(ButtonCallback callback);
|
Button& on_pressed(ButtonCallback callback);
|
||||||
|
|
||||||
|
const Rml::String& get_text() const { return mProps.text; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void update_props(Props props);
|
void update_props(Props props);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,209 @@
|
|||||||
|
#include "command_console.hpp"
|
||||||
|
|
||||||
|
#include <RmlUi/Core.h>
|
||||||
|
#include <RmlUi/Core/Elements/ElementFormControlInput.h>
|
||||||
|
#include <SDL3/SDL_keyboard.h>
|
||||||
|
#include <aurora/rmlui.hpp>
|
||||||
|
#include <imgui.h>
|
||||||
|
|
||||||
|
#include "dusk/settings.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
|
#include "fmt/format.h"
|
||||||
|
#include "ui.hpp"
|
||||||
|
|
||||||
|
namespace dusk::ui {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
static const Rml::String kDocumentSource = R"RML(
|
||||||
|
<rml>
|
||||||
|
<head>
|
||||||
|
<link type="text/rcss" href="res/rml/command_console.rcss" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<console id="console">
|
||||||
|
<output id="console-output"></output>
|
||||||
|
<input id="console-input" type="text" maxlength="255" />
|
||||||
|
</console>
|
||||||
|
</body>
|
||||||
|
</rml>
|
||||||
|
)RML";
|
||||||
|
|
||||||
|
static bool isCommand(std::string_view text) {
|
||||||
|
return text.size() >= 2 && text[0] == '>' && text[1] == ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
CommandConsole::CommandConsole() : Document(kDocumentSource) {
|
||||||
|
mConsole = mDocument ? mDocument->GetElementById("console") : nullptr;
|
||||||
|
mOutput = mDocument ? mDocument->GetElementById("console-output") : nullptr;
|
||||||
|
auto* rawInput = mDocument ? mDocument->GetElementById("console-input") : nullptr;
|
||||||
|
mInput = rmlui_dynamic_cast<Rml::ElementFormControlInput*>(rawInput);
|
||||||
|
|
||||||
|
listen(
|
||||||
|
Rml::EventId::Keydown,
|
||||||
|
[this](Rml::Event& event) {
|
||||||
|
if (!mInputActive) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto key = static_cast<Rml::Input::KeyIdentifier>(event.GetParameter<int>("key_identifier", Rml::Input::KI_UNKNOWN));
|
||||||
|
if (key == Rml::Input::KI_RETURN) {
|
||||||
|
executeFromInput();
|
||||||
|
event.StopImmediatePropagation();
|
||||||
|
} else if (key == Rml::Input::KI_ESCAPE) {
|
||||||
|
hide(true);
|
||||||
|
event.StopImmediatePropagation();
|
||||||
|
} else if (key == Rml::Input::KI_UP) {
|
||||||
|
navigateHistory(-1);
|
||||||
|
event.StopImmediatePropagation();
|
||||||
|
} else if (key == Rml::Input::KI_DOWN) {
|
||||||
|
navigateHistory(+1);
|
||||||
|
event.StopImmediatePropagation();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
true);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CommandConsole::handle_nav_command(Rml::Event&, NavCommand) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommandConsole::update() {
|
||||||
|
if (!getSettings().backend.enableAdvancedSettings) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const float dt = std::max(ImGui::GetIO().DeltaTime, 0.0f);
|
||||||
|
for (auto& line : mOutputLines) {
|
||||||
|
line.remain -= dt;
|
||||||
|
}
|
||||||
|
const auto [first, last] =
|
||||||
|
std::ranges::remove_if(mOutputLines, [](const OutputLine& l) { return l.remain <= 0.0f; });
|
||||||
|
mOutputLines.erase(first, last);
|
||||||
|
|
||||||
|
if (mOutputLines.empty() && !mInputActive) {
|
||||||
|
Document::hide(mPendingClose);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mOutput == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rml::String html;
|
||||||
|
if (mInputActive) {
|
||||||
|
for (const auto& msg : mMsgHistory) {
|
||||||
|
html += isCommand(msg) ? "<line class=\"cmd\">" + escape(msg) + "</line>" : "<line>" + escape(msg) + "</line>";
|
||||||
|
}
|
||||||
|
mOutput->SetAttribute("open", "");
|
||||||
|
} else {
|
||||||
|
const int total = (int)mOutputLines.size();
|
||||||
|
const int startIdx = std::max(0, total - kMaxVisibleLines);
|
||||||
|
for (int i = startIdx; i < total; ++i) {
|
||||||
|
const auto& line = mOutputLines[i];
|
||||||
|
const float alpha = line.remain < kFadeSeconds ? line.remain / kFadeSeconds : 1.0f;
|
||||||
|
const Rml::String cls = isCommand(line.text) ? " class=\"cmd\"" : "";
|
||||||
|
html += fmt::format(FMT_STRING("<line{} style=\"opacity: {:.3f}\">{}</line>"), cls,
|
||||||
|
alpha, escape(line.text));
|
||||||
|
}
|
||||||
|
mOutput->RemoveAttribute("open");
|
||||||
|
}
|
||||||
|
|
||||||
|
mOutput->SetInnerRML(html);
|
||||||
|
|
||||||
|
if (mScrollToBottom && mInputActive) {
|
||||||
|
mOutput->SetScrollTop(1e9f);
|
||||||
|
mScrollToBottom = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommandConsole::show() {
|
||||||
|
if (mDocument != nullptr) {
|
||||||
|
mDocument->Show(Rml::ModalFlag::None, Rml::FocusFlag::None, Rml::ScrollFlag::None);
|
||||||
|
}
|
||||||
|
mInputActive = true;
|
||||||
|
mScrollToBottom = true;
|
||||||
|
if (mConsole != nullptr) {
|
||||||
|
mConsole->SetAttribute("open", "");
|
||||||
|
}
|
||||||
|
focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CommandConsole::focus() {
|
||||||
|
if (mInput != nullptr) {
|
||||||
|
mInput->SetValue("");
|
||||||
|
aurora::rmlui::set_input_type(aurora::rmlui::InputType::Text);
|
||||||
|
return mInput->Focus(true);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommandConsole::hide(bool close) {
|
||||||
|
mInputActive = false;
|
||||||
|
mHistoryPos = -1;
|
||||||
|
if (mConsole != nullptr) {
|
||||||
|
mConsole->RemoveAttribute("open");
|
||||||
|
}
|
||||||
|
if (mInput != nullptr) {
|
||||||
|
mInput->SetValue("");
|
||||||
|
}
|
||||||
|
mPendingClose = close;
|
||||||
|
// Immediately refocus
|
||||||
|
if (auto* doc = top_document()) {
|
||||||
|
doc->focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommandConsole::executeFromInput() {
|
||||||
|
if (mInput == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const Rml::String value = mInput->GetValue();
|
||||||
|
hide(true);
|
||||||
|
if (!value.empty()) {
|
||||||
|
runCommand(value, mState, [this](std::string text) { ConsolePrint(std::move(text)); });
|
||||||
|
}
|
||||||
|
mScrollToBottom = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommandConsole::navigateHistory(int dir) {
|
||||||
|
if (mState.history.empty() || mInput == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const int prev = mHistoryPos;
|
||||||
|
if (dir < 0) {
|
||||||
|
if (mHistoryPos == -1) {
|
||||||
|
mHistoryPos = (int)mState.history.size() - 1;
|
||||||
|
} else if (mHistoryPos > 0) {
|
||||||
|
--mHistoryPos;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (mHistoryPos != -1 && ++mHistoryPos >= (int)mState.history.size()) {
|
||||||
|
mHistoryPos = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (prev != mHistoryPos) {
|
||||||
|
const char* str = mHistoryPos >= 0 ? mState.history[mHistoryPos].c_str() : "";
|
||||||
|
mInput->SetValue(str);
|
||||||
|
const int end = static_cast<int>(Rml::StringUtilities::LengthUTF8(mInput->GetValue()));
|
||||||
|
mInput->SetSelectionRange(end, end);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommandConsole::ConsolePrint(std::string text) {
|
||||||
|
mMsgHistory.push_back(text);
|
||||||
|
if ((int)mMsgHistory.size() > kMaxMsgHistory) {
|
||||||
|
mMsgHistory.erase(mMsgHistory.begin());
|
||||||
|
}
|
||||||
|
mOutputLines.push_back({std::move(text), kDurationNormal});
|
||||||
|
mScrollToBottom = true;
|
||||||
|
if ((int)mOutputLines.size() > kMaxStoredLines) {
|
||||||
|
mOutputLines.erase(mOutputLines.begin());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace dusk::ui
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "document.hpp"
|
||||||
|
#include "dusk/commands.hpp"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace Rml {
|
||||||
|
class ElementFormControlInput;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace dusk::ui {
|
||||||
|
|
||||||
|
class CommandConsole : public Document {
|
||||||
|
public:
|
||||||
|
CommandConsole();
|
||||||
|
|
||||||
|
void update() override;
|
||||||
|
void show() override;
|
||||||
|
bool focus() override;
|
||||||
|
void hide(bool close) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct OutputLine {
|
||||||
|
std::string text;
|
||||||
|
float remain;
|
||||||
|
};
|
||||||
|
|
||||||
|
static constexpr float kDurationNormal = 6.0f;
|
||||||
|
static constexpr float kFadeSeconds = 0.8f;
|
||||||
|
static constexpr int kMaxStoredLines = 64;
|
||||||
|
static constexpr int kMaxVisibleLines = 24;
|
||||||
|
static constexpr int kMaxMsgHistory = 500;
|
||||||
|
|
||||||
|
Rml::Element* mConsole = nullptr;
|
||||||
|
Rml::Element* mOutput = nullptr;
|
||||||
|
Rml::ElementFormControlInput* mInput = nullptr;
|
||||||
|
|
||||||
|
std::vector<OutputLine> mOutputLines;
|
||||||
|
std::vector<std::string> mMsgHistory;
|
||||||
|
int mHistoryPos = -1;
|
||||||
|
bool mInputActive = false;
|
||||||
|
bool mScrollToBottom = false;
|
||||||
|
|
||||||
|
CommandState mState;
|
||||||
|
|
||||||
|
bool handle_nav_command(Rml::Event& event, NavCommand cmd) override;
|
||||||
|
|
||||||
|
void ConsolePrint(std::string text);
|
||||||
|
void executeFromInput();
|
||||||
|
void navigateHistory(int dir);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace dusk::ui
|
||||||
@@ -861,20 +861,6 @@ void ControllerConfigWindow::render_page(Pane& pane, int port, Page page) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Page::Rumble: {
|
case Page::Rumble: {
|
||||||
if (PADCanForceDeviceRumble(static_cast<u32>(port))) {
|
|
||||||
pane.add_child<BoolButton>(BoolButton::Props{
|
|
||||||
.key = "Use Device Haptics",
|
|
||||||
.getValue = [port] { return PADGetForceDeviceRumble(static_cast<u32>(port)); },
|
|
||||||
.setValue =
|
|
||||||
[port](bool value) {
|
|
||||||
PADSetForceDeviceRumble(static_cast<u32>(port), value ? TRUE : FALSE);
|
|
||||||
PADSerializeMappings();
|
|
||||||
},
|
|
||||||
.isDisabled = [this] { return mRumbleTestActive; },
|
|
||||||
});
|
|
||||||
pane.add_text("Use native device haptics instead of controller rumble. "
|
|
||||||
"Useful for devices with built-in gamepads.");
|
|
||||||
}
|
|
||||||
auto& rumbleTest = pane.add_select_button({
|
auto& rumbleTest = pane.add_select_button({
|
||||||
.key = "Test Rumble",
|
.key = "Test Rumble",
|
||||||
.getValue =
|
.getValue =
|
||||||
|
|||||||
@@ -1,192 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
namespace dusk::ui {
|
|
||||||
|
|
||||||
struct EquipTarget {
|
|
||||||
float left = 0.0f;
|
|
||||||
float top = 0.0f;
|
|
||||||
float width = 0.0f;
|
|
||||||
float height = 0.0f;
|
|
||||||
bool valid = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class Control {
|
|
||||||
A,
|
|
||||||
B,
|
|
||||||
X,
|
|
||||||
Y,
|
|
||||||
Z,
|
|
||||||
L,
|
|
||||||
R,
|
|
||||||
FIRST_PERSON,
|
|
||||||
ITEMS,
|
|
||||||
COLLECTIONS,
|
|
||||||
MAP,
|
|
||||||
SKIP,
|
|
||||||
DPAD_UP,
|
|
||||||
DPAD_DOWN,
|
|
||||||
DPAD_LEFT,
|
|
||||||
DPAD_RIGHT,
|
|
||||||
COUNT,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class ControlAnchor : u8 {
|
|
||||||
None,
|
|
||||||
Top,
|
|
||||||
Left,
|
|
||||||
Bottom,
|
|
||||||
Right,
|
|
||||||
TopLeft,
|
|
||||||
TopRight,
|
|
||||||
BottomLeft,
|
|
||||||
BottomRight,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ControlProps {
|
|
||||||
float x = 0.0f;
|
|
||||||
float y = 0.0f;
|
|
||||||
float w = 0.0f;
|
|
||||||
float h = 0.0f;
|
|
||||||
float scale = 1.0f;
|
|
||||||
ControlAnchor anchor = ControlAnchor::None;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ControlRect {
|
|
||||||
float l = 0.0f;
|
|
||||||
float t = 0.0f;
|
|
||||||
float w = 0.0f;
|
|
||||||
float h = 0.0f;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ResolvedControlLayout {
|
|
||||||
ControlRect visual;
|
|
||||||
ControlRect box;
|
|
||||||
float scale = 1.0f;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ControlLayoutSize {
|
|
||||||
float w = 0.0f;
|
|
||||||
float h = 0.0f;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ControlLayout {
|
|
||||||
static constexpr int Version = 1;
|
|
||||||
|
|
||||||
int version = Version;
|
|
||||||
std::map<std::string, ControlProps, std::less<> > controls;
|
|
||||||
};
|
|
||||||
|
|
||||||
constexpr std::array<std::string_view, 9> kControlLayoutIds = {
|
|
||||||
"actionBar",
|
|
||||||
"buttonA",
|
|
||||||
"buttonB",
|
|
||||||
"buttonX",
|
|
||||||
"buttonY",
|
|
||||||
"buttonZ",
|
|
||||||
"skip",
|
|
||||||
"triggerL",
|
|
||||||
"triggerR",
|
|
||||||
};
|
|
||||||
|
|
||||||
constexpr bool is_control_layout_id(std::string_view id) noexcept {
|
|
||||||
for (const auto knownId : kControlLayoutIds) {
|
|
||||||
if (id == knownId) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr ControlRect resolve_anchored_rect(
|
|
||||||
ControlAnchor anchor, float x, float y, float w, float h, ControlLayoutSize docSize) noexcept {
|
|
||||||
switch (anchor) {
|
|
||||||
case ControlAnchor::None:
|
|
||||||
return {x * docSize.w - w * 0.5f, y * docSize.h - h * 0.5f, w, h};
|
|
||||||
case ControlAnchor::Top:
|
|
||||||
return {x * docSize.w - w * 0.5f, y, w, h};
|
|
||||||
case ControlAnchor::Bottom:
|
|
||||||
return {x * docSize.w - w * 0.5f, docSize.h - y - h, w, h};
|
|
||||||
case ControlAnchor::Left:
|
|
||||||
return {x, y * docSize.h - h * 0.5f, w, h};
|
|
||||||
case ControlAnchor::Right:
|
|
||||||
return {docSize.w - x - w, y * docSize.h - h * 0.5f, w, h};
|
|
||||||
case ControlAnchor::TopLeft:
|
|
||||||
return {x, y, w, h};
|
|
||||||
case ControlAnchor::TopRight:
|
|
||||||
return {docSize.w - x - w, y, w, h};
|
|
||||||
case ControlAnchor::BottomLeft:
|
|
||||||
return {x, docSize.h - y - h, w, h};
|
|
||||||
case ControlAnchor::BottomRight:
|
|
||||||
return {docSize.w - x - w, docSize.h - y - h, w, h};
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr ResolvedControlLayout resolve_control_layout(
|
|
||||||
ControlProps props, ControlLayoutSize docSize) noexcept {
|
|
||||||
const float visualW = props.w * props.scale;
|
|
||||||
const float visualH = props.h * props.scale;
|
|
||||||
const ControlRect visual =
|
|
||||||
resolve_anchored_rect(props.anchor, props.x, props.y, visualW, visualH, docSize);
|
|
||||||
const ControlRect box = {
|
|
||||||
visual.l + (visual.w - props.w) * 0.5f,
|
|
||||||
visual.t + (visual.h - props.h) * 0.5f,
|
|
||||||
props.w,
|
|
||||||
props.h,
|
|
||||||
};
|
|
||||||
return {
|
|
||||||
.visual = visual,
|
|
||||||
.box = box,
|
|
||||||
.scale = props.scale,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr ControlProps encode_control_props(ControlRect visual, ControlLayoutSize docSize,
|
|
||||||
ControlProps props, ControlAnchor anchor) noexcept {
|
|
||||||
props.anchor = anchor;
|
|
||||||
|
|
||||||
switch (anchor) {
|
|
||||||
case ControlAnchor::None:
|
|
||||||
props.x = (visual.l + visual.w * 0.5f) / docSize.w;
|
|
||||||
props.y = (visual.t + visual.h * 0.5f) / docSize.h;
|
|
||||||
break;
|
|
||||||
case ControlAnchor::Top:
|
|
||||||
props.x = (visual.l + visual.w * 0.5f) / docSize.w;
|
|
||||||
props.y = visual.t;
|
|
||||||
break;
|
|
||||||
case ControlAnchor::Bottom:
|
|
||||||
props.x = (visual.l + visual.w * 0.5f) / docSize.w;
|
|
||||||
props.y = docSize.h - visual.t - visual.h;
|
|
||||||
break;
|
|
||||||
case ControlAnchor::Left:
|
|
||||||
props.x = visual.l;
|
|
||||||
props.y = (visual.t + visual.h * 0.5f) / docSize.h;
|
|
||||||
break;
|
|
||||||
case ControlAnchor::Right:
|
|
||||||
props.x = docSize.w - visual.l - visual.w;
|
|
||||||
props.y = (visual.t + visual.h * 0.5f) / docSize.h;
|
|
||||||
break;
|
|
||||||
case ControlAnchor::TopLeft:
|
|
||||||
props.x = visual.l;
|
|
||||||
props.y = visual.t;
|
|
||||||
break;
|
|
||||||
case ControlAnchor::TopRight:
|
|
||||||
props.x = docSize.w - visual.l - visual.w;
|
|
||||||
props.y = visual.t;
|
|
||||||
break;
|
|
||||||
case ControlAnchor::BottomLeft:
|
|
||||||
props.x = visual.l;
|
|
||||||
props.y = docSize.h - visual.t - visual.h;
|
|
||||||
break;
|
|
||||||
case ControlAnchor::BottomRight:
|
|
||||||
props.x = docSize.w - visual.l - visual.w;
|
|
||||||
props.y = docSize.h - visual.t - visual.h;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return props;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace dusk::ui
|
|
||||||
+12
-44
@@ -3,6 +3,7 @@
|
|||||||
#include "aurora/rmlui.hpp"
|
#include "aurora/rmlui.hpp"
|
||||||
#include "ui.hpp"
|
#include "ui.hpp"
|
||||||
|
|
||||||
|
#include "Z2AudioLib/Z2SeMgr.h"
|
||||||
#include "m_Do/m_Do_audio.h"
|
#include "m_Do/m_Do_audio.h"
|
||||||
|
|
||||||
namespace dusk::ui {
|
namespace dusk::ui {
|
||||||
@@ -18,39 +19,32 @@ Rml::ElementDocument* load_document(const Rml::String& source) {
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
Document::Document(const Rml::String& source, bool passive)
|
Document::Document(const Rml::String& source) : mDocument(load_document(source)) {
|
||||||
: mDocument(load_document(source)), mPassive(passive) {
|
|
||||||
// Block events while hidden (except for Menu command); play nav sounds when visible
|
// Block events while hidden (except for Menu command); play nav sounds when visible
|
||||||
listen(
|
listen(
|
||||||
Rml::EventId::Keydown,
|
Rml::EventId::Keydown,
|
||||||
[this](Rml::Event& event) {
|
[this](Rml::Event& event) {
|
||||||
if (mPassive) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const auto cmd = map_nav_event(event);
|
const auto cmd = map_nav_event(event);
|
||||||
if (cmd != NavCommand::Menu && (!visible() || !active())) {
|
if (cmd != NavCommand::Menu && !visible()) {
|
||||||
event.StopImmediatePropagation();
|
event.StopImmediatePropagation();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
true);
|
true);
|
||||||
const auto blockUnlessActive = [this](Rml::Event& event) {
|
const auto blockUnlessVisible = [this](Rml::Event& event) {
|
||||||
if (!visible() || !active()) {
|
if (!visible()) {
|
||||||
event.StopImmediatePropagation();
|
event.StopImmediatePropagation();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
listen(Rml::EventId::Mouseover, blockUnlessActive, true);
|
listen(Rml::EventId::Mouseover, blockUnlessVisible, true);
|
||||||
listen(Rml::EventId::Click, blockUnlessActive, true);
|
listen(Rml::EventId::Click, blockUnlessVisible, true);
|
||||||
listen(Rml::EventId::Scroll, blockUnlessActive, true);
|
listen(Rml::EventId::Scroll, blockUnlessVisible, true);
|
||||||
|
|
||||||
listen(Rml::EventId::Keydown, [this](Rml::Event& event) {
|
listen(Rml::EventId::Keydown, [this](Rml::Event& event) {
|
||||||
if (mPassive) {
|
const auto cmd = map_nav_event(event);
|
||||||
auto* doc = top_document();
|
if (cmd == NavCommand::None) {
|
||||||
if (doc != nullptr && doc->handle_nav_event(event)) {
|
|
||||||
event.StopPropagation();
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (handle_nav_event(event)) {
|
if (handle_nav_command(event, cmd)) {
|
||||||
event.StopPropagation();
|
event.StopPropagation();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -74,6 +68,7 @@ void Document::show() {
|
|||||||
focus();
|
focus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
mPendingClose = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Document::hide(bool close) {
|
void Document::hide(bool close) {
|
||||||
@@ -103,18 +98,6 @@ void Document::listen(Rml::Element* element, Rml::EventId event,
|
|||||||
std::make_unique<ScopedEventListener>(element, event, std::move(callback), capture));
|
std::make_unique<ScopedEventListener>(element, event, std::move(callback), capture));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Document::listen(Rml::Element* element, const Rml::String& event,
|
|
||||||
ScopedEventListener::Callback callback, bool capture) {
|
|
||||||
if (element == nullptr) {
|
|
||||||
element = mDocument;
|
|
||||||
}
|
|
||||||
if (element == nullptr || event.empty() || !callback) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mListeners.emplace_back(
|
|
||||||
std::make_unique<ScopedEventListener>(element, event, std::move(callback), capture));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Document::visible() const {
|
bool Document::visible() const {
|
||||||
if (mDocument == nullptr) {
|
if (mDocument == nullptr) {
|
||||||
return false;
|
return false;
|
||||||
@@ -122,21 +105,6 @@ bool Document::visible() const {
|
|||||||
return *mDocument->GetProperty(Rml::PropertyId::Visibility) == Rml::Style::Visibility::Visible;
|
return *mDocument->GetProperty(Rml::PropertyId::Visibility) == Rml::Style::Visibility::Visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Document::active() const {
|
|
||||||
return !mClosed && !mPendingClose;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Document::handle_nav_event(Rml::Event& event) {
|
|
||||||
if (!active()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const auto cmd = map_nav_event(event);
|
|
||||||
if (cmd == NavCommand::None || (cmd != NavCommand::Menu && !visible())) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return handle_nav_command(event, cmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Document::handle_nav_command(Rml::Event& event, NavCommand cmd) {
|
bool Document::handle_nav_command(Rml::Event& event, NavCommand cmd) {
|
||||||
if (cmd == NavCommand::Menu) {
|
if (cmd == NavCommand::Menu) {
|
||||||
mDoAud_seStartMenu(visible() ? kSoundMenuClose : kSoundMenuOpen);
|
mDoAud_seStartMenu(visible() ? kSoundMenuClose : kSoundMenuOpen);
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ namespace dusk::ui {
|
|||||||
|
|
||||||
class Document {
|
class Document {
|
||||||
public:
|
public:
|
||||||
explicit Document(const Rml::String& source, bool passive = false);
|
Document(const Rml::String& source);
|
||||||
virtual ~Document();
|
virtual ~Document();
|
||||||
|
|
||||||
Document(const Document&) = delete;
|
Document(const Document&) = delete;
|
||||||
@@ -18,19 +18,12 @@ public:
|
|||||||
virtual void update();
|
virtual void update();
|
||||||
virtual bool focus();
|
virtual bool focus();
|
||||||
virtual bool visible() const;
|
virtual bool visible() const;
|
||||||
virtual bool active() const;
|
|
||||||
|
|
||||||
void listen(Rml::Element* element, Rml::EventId event, ScopedEventListener::Callback callback,
|
void listen(Rml::Element* element, Rml::EventId event, ScopedEventListener::Callback callback,
|
||||||
bool capture = false);
|
bool capture = false);
|
||||||
void listen(Rml::Element* element, const Rml::String& event,
|
|
||||||
ScopedEventListener::Callback callback, bool capture = false);
|
|
||||||
void listen(Rml::EventId event, ScopedEventListener::Callback callback, bool capture = false) {
|
void listen(Rml::EventId event, ScopedEventListener::Callback callback, bool capture = false) {
|
||||||
listen(mDocument, event, std::move(callback), capture);
|
listen(mDocument, event, std::move(callback), capture);
|
||||||
}
|
}
|
||||||
void listen(
|
|
||||||
const Rml::String& event, ScopedEventListener::Callback callback, bool capture = false) {
|
|
||||||
listen(mDocument, event, std::move(callback), capture);
|
|
||||||
}
|
|
||||||
void toggle() {
|
void toggle() {
|
||||||
if (visible()) {
|
if (visible()) {
|
||||||
hide(false);
|
hide(false);
|
||||||
@@ -42,15 +35,14 @@ public:
|
|||||||
push_document(std::move(document));
|
push_document(std::move(document));
|
||||||
hide(false);
|
hide(false);
|
||||||
}
|
}
|
||||||
void pop(bool show = true) {
|
void pop() {
|
||||||
hide(true);
|
hide(true);
|
||||||
focus_top_document(show);
|
show_top_document();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool pending_close() const { return mPendingClose; }
|
||||||
bool closed() const { return mClosed; }
|
bool closed() const { return mClosed; }
|
||||||
|
|
||||||
bool handle_nav_event(Rml::Event& event);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bool handle_nav_command(Rml::Event& event, NavCommand cmd);
|
virtual bool handle_nav_command(Rml::Event& event, NavCommand cmd);
|
||||||
|
|
||||||
@@ -58,7 +50,6 @@ protected:
|
|||||||
std::vector<std::unique_ptr<ScopedEventListener> > mListeners;
|
std::vector<std::unique_ptr<ScopedEventListener> > mListeners;
|
||||||
bool mPendingClose = false;
|
bool mPendingClose = false;
|
||||||
bool mClosed = false;
|
bool mClosed = false;
|
||||||
bool mPassive = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace dusk::ui
|
} // namespace dusk::ui
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user