mirror of
https://github.com/geode-sdk/geode.git
synced 2025-03-26 21:00:50 -04:00
Merge branch 'main' of https://github.com/geode-sdk/geode into main
This commit is contained in:
commit
3c2c8f8d8d
328 changed files with 18598 additions and 2939 deletions
.github
ISSUE_TEMPLATE
workflows
bindings
cmake
codegen
Broma/include
src
fmt/include/fmt
loader
CMakeLists.txt
hash
include/Geode
Bindings.hppDefaultInclude.hppEnums.hppGeode.hppLoader.hppModify.hppUI.hppUtils.hpp
cocos
cocos2dx
CCDirector.h
base_nodes
cocoa
label_nodes
platform
robtop/keyboard_dispatcher
sprite_nodes
touch_dispatcher
extensions/GUI/CCControlExtension
loader
API.hppDispatch.hppEvent.hppHook.hppInterface.hppLoader.hppLog.hppMod.hppSetting.hppSettingEvent.hppSettingNode.hpp
meta
modify
platform
ui
65
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
Normal file
65
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
Normal file
|
@ -0,0 +1,65 @@
|
|||
name: Bug Report
|
||||
description: Report a bug where something is not working as expected, which does not crash the game.
|
||||
labels: [ "unverified", "bug" ]
|
||||
body:
|
||||
- type: dropdown
|
||||
id: platform
|
||||
attributes:
|
||||
label: Platform
|
||||
description: The platform you were using when this bug was encountered.
|
||||
options:
|
||||
- "MacOS"
|
||||
- "Windows"
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: version
|
||||
attributes:
|
||||
label: Geode Version
|
||||
description: The version of Geode you were using when this bug was encountered. If you do not know where to find this, look for the mods listing.
|
||||
placeholder: "Example: v0.5.4"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: mods
|
||||
attributes:
|
||||
label: Mods Installed
|
||||
description: The mods and their respective versions used when this bug was encountered. If you were not using mods, please leave this field blank.
|
||||
placeholder: "Example: geode.test v1.0.0, geode.testdep v0.1.0"
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: expected
|
||||
attributes:
|
||||
label: Expected Behavior
|
||||
description: What you expected to happen. Attach screenshots here as necessary.
|
||||
placeholder: "Example: Expected to produce X by consuming Y."
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: result
|
||||
attributes:
|
||||
label: Actual Behavior
|
||||
description: What happened despite your expectations. Attach screenshots here as necessary.
|
||||
placeholder: "Example: Produced one X but Y was not consumed."
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: reproduction
|
||||
attributes:
|
||||
label: Steps to Reproduce
|
||||
description: How to reproduce the bug.
|
||||
placeholder: "Example: 1) I did X..."
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: additional-info
|
||||
attributes:
|
||||
label: Additional Information
|
||||
description: Any additional information you wish to provide. Please add anything which did not fit into the other sections here.
|
||||
placeholder: "Example: This is likely caused by X because..."
|
||||
validations:
|
||||
required: false
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: Thank you for taking the time to fill out this bug report.
|
4
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
4
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Discord link
|
||||
about: Find us at https://discord.gg/9e43WMKzhp
|
57
.github/ISSUE_TEMPLATE/crash-report.yml
vendored
Normal file
57
.github/ISSUE_TEMPLATE/crash-report.yml
vendored
Normal file
|
@ -0,0 +1,57 @@
|
|||
name: Crash Report
|
||||
description: Report a bug that crashes the game or prevents startup.
|
||||
labels: [ "unverified", "crash" ]
|
||||
body:
|
||||
- type: dropdown
|
||||
id: platform
|
||||
attributes:
|
||||
label: Platform
|
||||
description: The platform you were using when this bug was encountered.
|
||||
options:
|
||||
- "MacOS"
|
||||
- "Windows"
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: version
|
||||
attributes:
|
||||
label: Geode Version
|
||||
description: The version of Geode you were using when this bug was encountered. If you do not know where to find this, look for the mods listing.
|
||||
placeholder: "Example: v0.5.4"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: mods
|
||||
attributes:
|
||||
label: Mods Installed
|
||||
description: The mods and their respective versions used when this bug was encountered. If you were not using mods, please leave this field blank.
|
||||
placeholder: "Example: geode.test v1.0.0, geode.testdep v0.1.0"
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: reproduction
|
||||
attributes:
|
||||
label: Steps to Reproduce
|
||||
description: How to reproduce the crash.
|
||||
placeholder: "Example: 1) I did X..."
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: crash-report
|
||||
attributes:
|
||||
label: Crash Report
|
||||
description: "You can find the crash report in `geode/crashlogs/`, if one was created. If you are using MacOS you can find the crash report in `Console.app` too. Additionally, please attach latest log in `geode/log/`. If either or both files do not exist, state such. Please link to a paste site with their content, such as GitHub Gists or Pastebin. **Do not paste the contents of either these files directly into the text box.**"
|
||||
placeholder: "Example: a link to a paste site with the crash report and latest.log."
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: additional-info
|
||||
attributes:
|
||||
label: Additional Information
|
||||
description: Any additional information you wish to provide. Please add anything which did not fit into the other sections here.
|
||||
placeholder: "Example: This is likely caused by X because..."
|
||||
validations:
|
||||
required: false
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: Thank you for taking the time to fill out this crash report.
|
39
.github/ISSUE_TEMPLATE/feature-request.yml
vendored
Normal file
39
.github/ISSUE_TEMPLATE/feature-request.yml
vendored
Normal file
|
@ -0,0 +1,39 @@
|
|||
name: Request a Feature
|
||||
description: Request a new feature or a change to an existing one.
|
||||
labels: [ "feature" ]
|
||||
body:
|
||||
- type: input
|
||||
id: version
|
||||
attributes:
|
||||
label: Geode Version
|
||||
description: The version of Geode you are using for suggesting a feature on. If you do not know where to find this, look for the mods listing.
|
||||
placeholder: "Example: v0.5.4"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: problem
|
||||
attributes:
|
||||
label: Related Problem
|
||||
description: If the feature you wish to change is related to a problem, please describe it. Leave this field blank if it is not related to a problem.
|
||||
placeholder: "Example: I'm always frustrated when..."
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: solution
|
||||
attributes:
|
||||
label: Your Solution
|
||||
description: Describe the solution you would like to have happen.
|
||||
placeholder: "Example: If I could..."
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: additional-info
|
||||
attributes:
|
||||
label: Additional Information
|
||||
description: Any additional information you wish to provide. Please add anything which did not fit into the other sections here.
|
||||
placeholder: "Example: This is likely achieveable by doing X because..."
|
||||
validations:
|
||||
required: false
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: Thank you for taking the time to fill out this feature request.
|
19
.github/ISSUE_TEMPLATE/question.yml
vendored
Normal file
19
.github/ISSUE_TEMPLATE/question.yml
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
name: Ask a Question
|
||||
description: Ask a question regarding this project.
|
||||
labels: [ "question" ]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
If you are in need of quick response, Discord may be a better place. We are quite active on Discord, so you may get responses quicker.
|
||||
- type: textarea
|
||||
id: question
|
||||
attributes:
|
||||
label: Your Question
|
||||
description: Feel free to ask any question regarding this project here.
|
||||
placeholder: "Example: How can I...?"
|
||||
validations:
|
||||
required: true
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: Thank you for taking the time to ask me a question.
|
37
.github/workflows/build.yml
vendored
37
.github/workflows/build.yml
vendored
|
@ -17,17 +17,25 @@ jobs:
|
|||
os: windows-2019
|
||||
prefixes: ''
|
||||
extra_flags: '-G "Visual Studio 16 2019" -T host=x86 -A win32'
|
||||
out_paths: './bin/nightly/geode.dll ./bin/nightly/geode.lib ./bin/nightly/XInput9_1_0.dll'
|
||||
out_paths: './bin/nightly/Geode.dll ./bin/nightly/GeodeBootstrapper.dll ./bin/nightly/Geode.lib ./bin/nightly/XInput9_1_0.dll'
|
||||
cli_name: '*-win.zip'
|
||||
cli_cmd: ''
|
||||
|
||||
- name: "macOS"
|
||||
os: macos-latest
|
||||
prefixes: 'PATH="/usr/local/opt/ccache/libexec:$PATH"'
|
||||
extra_flags: "-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_DISABLE_PRECOMPILE_HEADERS=ON"
|
||||
out_paths: './bin/nightly/Geode.dylib'
|
||||
extra_flags: "-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++"
|
||||
out_paths: './bin/nightly/Geode.dylib ./bin/nightly/GeodeBootstrapper.dylib'
|
||||
cli_name: '*-mac.zip'
|
||||
cli_cmd: 'chmod +x $GITHUB_WORKSPACE/cli/geode'
|
||||
|
||||
name: ${{ matrix.config.name }}
|
||||
runs-on: ${{ matrix.config.os }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- uses: ilammy/msvc-dev-cmd@v1
|
||||
with:
|
||||
|
@ -40,14 +48,33 @@ jobs:
|
|||
key: ${{ matrix.config.os }}
|
||||
if: matrix.config.os == 'macos-latest'
|
||||
|
||||
- name: Download CLI
|
||||
uses: robinraju/release-downloader@v1.5
|
||||
with:
|
||||
repository: geode-sdk/cli
|
||||
latest: true
|
||||
fileName: ${{ matrix.config.cli_name }}
|
||||
tarBall: false
|
||||
zipBall: false
|
||||
out-file-path: "cli"
|
||||
|
||||
- name: Unzip CLI
|
||||
run: |
|
||||
7z x "${{ github.workspace }}/cli/${{ matrix.config.cli_name }}" -o"${{ github.workspace }}/cli"
|
||||
|
||||
- name: Add CLI to Path
|
||||
run: |
|
||||
${{ matrix.config.cli_cmd }}
|
||||
echo "${{ github.workspace }}/cli" >> $GITHUB_PATH
|
||||
|
||||
- name: Configure CMake
|
||||
run: |
|
||||
${{ matrix.config.prefixes }} cmake -B ${{ github.workspace }}/build ${{ matrix.config.extra_flags }}
|
||||
${{ matrix.config.prefixes }} cmake -B ${{ github.workspace }}/build ${{ matrix.config.extra_flags }} -DGEODE_DISABLE_CLI_CALLS=ON -DCLI_PATH="${{ github.workspace }}/cli"
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
cd build
|
||||
cmake --build . --config Release
|
||||
cmake --build . --config RelWithDebInfo
|
||||
|
||||
- name: Move to output folder
|
||||
shell: bash
|
||||
|
|
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -43,3 +43,7 @@ build
|
|||
bin
|
||||
|
||||
loader/src/internal/about.hpp
|
||||
loader/src/internal/resources.hpp
|
||||
loader/resources/mod.json
|
||||
fods-catgirl-hideout.txt
|
||||
|
||||
|
|
6
.gitmodules
vendored
Normal file
6
.gitmodules
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
[submodule "loader/md4c"]
|
||||
path = loader/md4c
|
||||
url = https://github.com/mity/md4c
|
||||
[submodule "loader/minhook"]
|
||||
path = loader/minhook
|
||||
url = https://github.com/TsudaKageyu/minhook
|
111
CHANGELOG.md
Normal file
111
CHANGELOG.md
Normal file
|
@ -0,0 +1,111 @@
|
|||
# Geode Changelog
|
||||
|
||||
## v0.4.6
|
||||
- Automatically checks & downloads loader resources if they are missing / corrupt on startup
|
||||
- CMake rework; `GeodeFile.cmake` now checks and verifies CLI version
|
||||
- Add optional `DONT_INSTALL` parameter to `create_geode_file`
|
||||
- Test mods are now no longer automatically installed
|
||||
- Add `package_geode_resources_now` command for packaging resources at configure time and creating a header with their calculated hashes
|
||||
- Fix `getSceneDelegate`
|
||||
- Change `CCArrayExt` to use `Ref`
|
||||
|
||||
## v0.4.5
|
||||
|
||||
- Rework bindings and codegen to improve compile times, now individual bindings can be included with `<Geode/binding/{ClassName}.hpp>`
|
||||
- Modify has also been separated, you can now include individual modifiers with `<Geode/modify/{ClassName}.hpp>`
|
||||
- Various other fixes to improve compile times
|
||||
- Fix mod resources not being loaded when installed from Index
|
||||
- Fix crashes related to downloading mods
|
||||
- Fix `Loader::queueInGDThread` sometimes leaving out functions
|
||||
- Fix crashes related to logging
|
||||
- Add new overloads to `file` utils and deprecate ones that don't use `ghc::filesystem::path`
|
||||
- Index mods now show their `about.md` files
|
||||
- More addresses
|
||||
- Various other fixes & improvements
|
||||
- Index reworked
|
||||
- Fix issues with `VERSION` file
|
||||
- Add `GEODE_DEBUG` macro for enabling `log::debug` to actually print stuff
|
||||
- Show crashlog on crash when `GEODE_DEBUG` is enabled
|
||||
- Add `JsonChecker::at` and `JsonChecker::array` for dealing with arrays
|
||||
- Add `geode::utils::web::fetchBytes` for fetching a byte array synchronously
|
||||
- Add `geode::utils::web::AsyncWebRequest` for creating thread-safe asynchronous web requests
|
||||
- Add `Loader::updateModResourcePaths` for adding a mods' resources to search paths. Not recommended to be called manually
|
||||
- Add an overload to `geode::createQuickPopup` for specifying popup width
|
||||
- `ModInfo::createFromFile` now checks for `about.md` and other special files in the same directory
|
||||
- Remove automatic mod updating for now, however automatic update checking for mods is still there
|
||||
|
||||
## v0.4.4
|
||||
|
||||
- New `listenForSettingChanges` API for more ergonomically listening for setting changes
|
||||
- Fixed bug where GD was unopenable through Steam
|
||||
- Various other internal fixes
|
||||
|
||||
## v0.4.3
|
||||
|
||||
- Simplified the minimum and maximum loader versions, loader will now load any mod whose target version major and minor match. In practice, this means that for example mods whose target version is v0.4.8 can be loaded by loader of version v0.4.6.
|
||||
- Add `Geode/ui/GeodeUI.hpp` header for exposing some access to internal Geode UI like opening a mod's settings popup
|
||||
- Fix crash with settings that could have a slider control
|
||||
|
||||
## v0.4.2
|
||||
|
||||
- Moved SDK version to its own file so CLI can query it
|
||||
- md4c is now linked statically on MacOS
|
||||
- Fix log filenames
|
||||
|
||||
## v0.4.1
|
||||
|
||||
- Initial dev release of Geode.
|
||||
|
||||
---
|
||||
|
||||
Note that from here on, changes to the framework were not tracked by versions as the framework was still considered to be in heavy development and not released. Instead, major changes are listed by dates.
|
||||
|
||||
## 2022/10/10
|
||||
|
||||
- Geode released for developers
|
||||
|
||||
## 2022/10/08
|
||||
|
||||
- `ui` branch merged to `main`
|
||||
|
||||
## 2022/10/03
|
||||
|
||||
- New CLI finished
|
||||
- `ui` branch finished
|
||||
|
||||
## 2022/08/01
|
||||
|
||||
- CLI redesign started
|
||||
|
||||
## 2022/07/30
|
||||
|
||||
- `sdk`, `loader` and `api` repos all merged into one `geode` repo
|
||||
|
||||
## 2022/05/24
|
||||
|
||||
- Geode announced to be merging with Hyperdash, later on it turned out we were all pathological liars
|
||||
|
||||
## 2022/05/02
|
||||
|
||||
- Installer on Windows
|
||||
|
||||
## 2022/04/30
|
||||
|
||||
- Installing mods in-game works
|
||||
|
||||
## 2022/01/23
|
||||
|
||||
- CLI started
|
||||
|
||||
## 2022/01/19
|
||||
|
||||
- Lilac and Cacao merged and renamed to Geode
|
||||
|
||||
## 2021/07/30
|
||||
|
||||
- Lilac started by Mat, HJfod and Pie
|
||||
|
||||
## 2021/01/25
|
||||
|
||||
- CacaoSDK started by Camila, based on CappuccinoSDK
|
||||
|
|
@ -1,14 +1,32 @@
|
|||
cmake_minimum_required(VERSION 3.21 FATAL_ERROR)
|
||||
|
||||
project(geode-sdk VERSION 0.2.0 LANGUAGES CXX C)
|
||||
set(BUILD_SHARED_LIBS OFF CACHE BOOL "Build libraries static" FORCE)
|
||||
file(READ VERSION GEODE_VERSION)
|
||||
string(STRIP "${GEODE_VERSION}" GEODE_VERSION)
|
||||
|
||||
project(geode-sdk VERSION ${GEODE_VERSION} LANGUAGES CXX C)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
if (PROJECT_IS_TOP_LEVEL AND APPLE)
|
||||
set(CMAKE_BUILD_TYPE Debug)
|
||||
endif()
|
||||
|
||||
add_library(${PROJECT_NAME} INTERFACE)
|
||||
|
||||
if (CMAKE_BUILD_TYPE STREQUAL Debug OR CMAKE_BUILD_TYPE STREQUAL RelWithDebInfo)
|
||||
target_compile_definitions(${PROJECT_NAME} INTERFACE -DGEODE_DEBUG)
|
||||
endif()
|
||||
|
||||
# Rerun CMake on VERSION file change
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES CMAKE_CONFIGURE_DEPENDS VERSION)
|
||||
|
||||
target_compile_definitions(${PROJECT_NAME} INTERFACE -DPROJECT_NAME=${CMAKE_PROJECT_NAME})
|
||||
|
||||
if (GEODE_DEBUG)
|
||||
target_compile_definitions(${PROJECT_NAME} INTERFACE GEODE_DEBUG)
|
||||
endif()
|
||||
|
||||
set(GEODE_CODEGEN_PATH ${CMAKE_CURRENT_BINARY_DIR}/codegenned)
|
||||
set(GEODE_BIN_PATH ${CMAKE_CURRENT_SOURCE_DIR}/bin)
|
||||
set(GEODE_LOADER_PATH ${CMAKE_CURRENT_SOURCE_DIR}/loader)
|
||||
|
@ -25,21 +43,22 @@ add_custom_target(CodegenRun ALL
|
|||
COMMAND Codegen ${GEODE_TARGET_PLATFORM} bindings ${GEODE_CODEGEN_PATH}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
COMMENT "Run Codegen"
|
||||
BYPRODUCTS ${GEODE_CODEGEN_PATH}/GeneratedSource.cpp
|
||||
BYPRODUCTS ${GEODE_CODEGEN_PATH}/Geode/GeneratedSource.cpp
|
||||
)
|
||||
add_dependencies(${PROJECT_NAME} CodegenRun)
|
||||
add_dependencies(CodegenRun Codegen)
|
||||
|
||||
# Hacky way to supress the not generated error
|
||||
if (NOT EXISTS ${GEODE_CODEGEN_PATH}/GeneratedSource.cpp)
|
||||
if (NOT EXISTS ${GEODE_CODEGEN_PATH}/Geode/GeneratedSource.cpp)
|
||||
make_directory(${GEODE_CODEGEN_PATH})
|
||||
execute_process(COMMAND touch ${GEODE_CODEGEN_PATH}/GeneratedSource.cpp)
|
||||
make_directory(${GEODE_CODEGEN_PATH}/Geode)
|
||||
file(TOUCH ${GEODE_CODEGEN_PATH}/Geode/GeneratedSource.cpp)
|
||||
endif()
|
||||
|
||||
target_sources(${PROJECT_NAME} INTERFACE ${GEODE_CODEGEN_PATH}/GeneratedSource.cpp)
|
||||
target_include_directories(${PROJECT_NAME} INTERFACE ${GEODE_CODEGEN_PATH}/..)
|
||||
target_sources(${PROJECT_NAME} INTERFACE ${GEODE_CODEGEN_PATH}/Geode/GeneratedSource.cpp)
|
||||
|
||||
target_include_directories(${PROJECT_NAME} INTERFACE
|
||||
${GEODE_CODEGEN_PATH}
|
||||
${GEODE_LOADER_PATH}/include
|
||||
${GEODE_LOADER_PATH}/include/Geode/cocos/
|
||||
${GEODE_LOADER_PATH}/include/Geode/cocos/cocos2dx
|
||||
|
@ -62,7 +81,7 @@ if (NOT EXISTS ${GEODE_BIN_PATH})
|
|||
make_directory(${GEODE_BIN_PATH})
|
||||
endif()
|
||||
|
||||
if (GEODE_LINK_SOURCE)
|
||||
if (${GEODE_LINK_NIGHTLY})
|
||||
set(GEODE_PLATFORM_BIN_PATH ${GEODE_BIN_PATH}/nightly/${GEODE_PLATFORM_BINARY})
|
||||
else()
|
||||
set(GEODE_PLATFORM_BIN_PATH ${GEODE_BIN_PATH}/${PROJECT_VERSION}/${GEODE_PLATFORM_BINARY})
|
||||
|
@ -74,7 +93,13 @@ if (PROJECT_IS_TOP_LEVEL)
|
|||
target_link_libraries(${PROJECT_NAME} INTERFACE geode-loader)
|
||||
elseif(EXISTS ${GEODE_PLATFORM_BIN_PATH})
|
||||
target_link_libraries(${PROJECT_NAME} INTERFACE "${GEODE_PLATFORM_BIN_PATH}")
|
||||
target_precompile_headers(${PROJECT_NAME} INTERFACE "${GEODE_LOADER_PATH}/include/Geode/Geode.hpp")
|
||||
target_precompile_headers(${PROJECT_NAME} INTERFACE
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include/Geode/DefaultInclude.hpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include/Geode/Loader.hpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include/Geode/UI.hpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include/Geode/cocos/cocos2dx/include/cocos2d.h"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include/Geode/cocos/extensions/cocos-ext.h"
|
||||
)
|
||||
else()
|
||||
message(FATAL_ERROR "No valid loader binary to link to! Install a pre-built binary for version ${PROJECT_VERSION} with Geode CLI or build it from source.")
|
||||
endif()
|
||||
|
|
|
@ -9,7 +9,8 @@
|
|||
There's nothing worse than having to read thousands of words just to see what some library's code actually looks like, so instead, here's a **Hello World** in Geode right off the bat:
|
||||
|
||||
```cpp
|
||||
#include <Geode.hpp>
|
||||
#include <Geode/bindings.hpp>
|
||||
#include <Geode/modify/MenuLayer.hpp>
|
||||
|
||||
USE_GEODE_NAMESPACE();
|
||||
|
||||
|
|
1
VERSION
Normal file
1
VERSION
Normal file
|
@ -0,0 +1 @@
|
|||
0.4.7
|
|
@ -21,8 +21,8 @@ class cocos2d::CCApplication {
|
|||
virtual auto setAnimationInterval(double) = mac 0x1a3ee0, ios 0x10e494;
|
||||
static auto sharedApplication() = mac 0x1a3f30;
|
||||
// ~CCApplication() = mac 0x1a3d10, ios 0x10e384;
|
||||
inline cocos2d::CCApplication::CCApplication() {}
|
||||
inline cocos2d::CCApplication::~CCApplication() {}
|
||||
CCApplication() {}
|
||||
~CCApplication() {}
|
||||
}
|
||||
|
||||
class cocos2d::CCArray {
|
||||
|
@ -96,8 +96,8 @@ class cocos2d::CCDictionary {
|
|||
}
|
||||
|
||||
class cocos2d::CCDirector {
|
||||
inline cocos2d::CCDirector::CCDirector() {}
|
||||
inline cocos2d::CCDirector::~CCDirector() {}
|
||||
CCDirector() {}
|
||||
~CCDirector() {}
|
||||
// virtual ~CCDirector() = mac 0x2493a0;
|
||||
virtual auto init() = mac 0x248df0;
|
||||
virtual auto getScheduler() = mac 0x24af00;
|
||||
|
@ -115,9 +115,6 @@ class cocos2d::CCDirector {
|
|||
virtual auto getAccelerometer() = mac 0x24b0e0;
|
||||
virtual auto setAccelerometer(cocos2d::CCAccelerometer*) = mac 0x24b0a0;
|
||||
virtual auto getDeltaTime() = mac 0x249bd0;
|
||||
virtual auto getSceneDelegate() = mac 0x24b320;
|
||||
virtual auto setSceneDelegate(cocos2d::CCSceneDelegate*) = mac 0x24b330;
|
||||
|
||||
|
||||
auto getWinSize() = mac 0x24a0f0, ios 0xece34;
|
||||
auto pushScene(cocos2d::CCScene*) = mac 0x24a620;
|
||||
|
@ -148,6 +145,10 @@ class cocos2d::CCDrawNode {
|
|||
virtual ~CCDrawNode() = mac 0x378cc0;
|
||||
}
|
||||
|
||||
class cocos2d::CCEaseBackIn {
|
||||
static cocos2d::CCEaseBackIn* create(cocos2d::CCActionInterval*) = mac 0x2a41b0;
|
||||
}
|
||||
|
||||
class cocos2d::CCEaseElasticOut {
|
||||
static cocos2d::CCEaseElasticOut* create(cocos2d::CCActionInterval*, float) = mac 0x2a3080;
|
||||
}
|
||||
|
@ -201,6 +202,7 @@ class cocos2d::CCFadeTo {
|
|||
|
||||
class cocos2d::CCFileUtils : cocos2d::TypeInfo {
|
||||
static cocos2d::CCFileUtils* sharedFileUtils() = mac 0x377030, ios 0x159450;
|
||||
virtual std::string fullPathForFilename(const char* filename, bool unk);
|
||||
}
|
||||
|
||||
class cocos2d::CCHide {
|
||||
|
@ -208,12 +210,12 @@ class cocos2d::CCHide {
|
|||
}
|
||||
|
||||
class cocos2d::CCIMEDelegate {
|
||||
inline cocos2d::CCIMEDelegate::~CCIMEDelegate() {
|
||||
~CCIMEDelegate() {
|
||||
CCIMEDispatcher::sharedDispatcher()->removeDelegate(this);
|
||||
}
|
||||
virtual auto attachWithIME() = mac 0x2776a0, ios 0x12d3d4;
|
||||
virtual auto detachWithIME() = mac 0x277880, ios 0x12d4e8;
|
||||
inline cocos2d::CCIMEDelegate::CCIMEDelegate() {
|
||||
CCIMEDelegate() {
|
||||
CCIMEDispatcher::sharedDispatcher()->addDelegate(this);
|
||||
}
|
||||
}
|
||||
|
@ -252,9 +254,37 @@ class cocos2d::CCKeypadHandler {
|
|||
class cocos2d::CCLabelBMFont {
|
||||
static cocos2d::CCLabelBMFont* create(char const*, char const*) = mac 0x347660;
|
||||
auto limitLabelWidth(float, float, float) = mac 0x34a6e0, ios 0x21b740;
|
||||
auto setScale(float) = mac 0x34a5d0;
|
||||
auto setString(char const*, bool) = mac 0x3489e0;
|
||||
auto setAnchorPoint(cocos2d::CCPoint const&) = mac 0x349440;
|
||||
|
||||
virtual ~CCLabelBMFont() = mac 0x347e80, ios 0x219afc;
|
||||
|
||||
virtual auto init() = mac 0x347b10, ios 0x2198e0;
|
||||
virtual auto setScaleX(float) = mac 0x34a5b0, ios 0x21b6e8;
|
||||
virtual auto setScaleY(float) = mac 0x34a5d0, ios 0x21b714;
|
||||
virtual auto setScale(float) = mac 0x34a590, ios 0x21b6bc;
|
||||
virtual auto setAnchorPoint(cocos2d::CCPoint const&) = mac 0x349440, ios 0x21aa7c;
|
||||
virtual auto setString(char const*) = mac 0x348990, ios 0x21a408;
|
||||
virtual auto setString(char const*, bool) = mac 0x3489e0, ios 0x21a42c;
|
||||
virtual auto getString() = mac 0x348bf0, ios 0x21a60c;
|
||||
virtual auto setCString(char const*) = mac 0x348c10, ios 0x21a63c;
|
||||
virtual auto updateLabel() = mac 0x349480, ios 0x21aad0;
|
||||
virtual auto setAlignment(cocos2d::CCTextAlignment) = mac 0x34a530, ios 0x21b68c;
|
||||
virtual auto setWidth(float) = mac 0x34a550, ios 0x21b69c;
|
||||
virtual auto setLineBreakWithoutSpace(bool) = mac 0x34a570, ios 0x21b6ac;
|
||||
virtual auto isOpacityModifyRGB() = mac 0x3490e0, ios 0x21a8c4;
|
||||
virtual auto setOpacityModifyRGB(bool) = mac 0x348f70, ios 0x21a80c;
|
||||
virtual auto getOpacity() = mac 0x348df0, ios 0x21a748;
|
||||
virtual auto getDisplayedOpacity() = mac 0x348e10, ios 0x21a758;
|
||||
virtual auto setOpacity(unsigned char) = mac 0x348e30, ios 0x21a768;
|
||||
virtual auto updateDisplayedOpacity(unsigned char) = mac 0x349100, ios 0x21a8d4;
|
||||
virtual auto isCascadeOpacityEnabled() = mac 0x349400, ios 0x21aa5c;
|
||||
virtual auto setCascadeOpacityEnabled(bool) = mac 0x349420, ios 0x21aa6c;
|
||||
virtual auto getColor() = mac 0x348c30, ios 0x21a648;
|
||||
virtual auto getDisplayedColor() = mac 0x348c50, ios 0x21a658;
|
||||
virtual auto setColor(cocos2d::ccColor3B const&) = mac 0x348c70, ios 0x21a668;
|
||||
virtual auto updateDisplayedColor(cocos2d::ccColor3B const&) = mac 0x349210, ios 0x21a968;
|
||||
virtual auto isCascadeColorEnabled() = mac 0x3493c0, ios 0x21aa3c;
|
||||
virtual auto setCascadeColorEnabled(bool) = mac 0x3493e0, ios 0x21aa4c;
|
||||
virtual auto setString(unsigned short*, bool) = mac 0x348a60, ios 0x21a4b4;
|
||||
}
|
||||
|
||||
class cocos2d::CCLabelTTF {
|
||||
|
@ -307,17 +337,18 @@ class cocos2d::CCLayer {
|
|||
class cocos2d::CCLayerColor {
|
||||
CCLayerColor() = mac 0x274320, ios 0xc8aec;
|
||||
static cocos2d::CCLayerColor* create(cocos2d::_ccColor4B const&, float, float) = mac 0x2745e0;
|
||||
auto draw() = mac 0x274b50, ios 0xc8fe0;
|
||||
auto getBlendFunc() = mac 0x274480, ios 0xc8bcc;
|
||||
auto init() = mac 0x274800, ios 0xc8de8;
|
||||
auto initWithColor(cocos2d::_ccColor4B const&) = mac 0x2749a0, ios 0xc8f14;
|
||||
auto initWithColor(cocos2d::_ccColor4B const&, float, float) = mac 0x274850, ios 0xc8e34;
|
||||
auto setBlendFunc(cocos2d::_ccBlendFunc) = mac 0x2744a0, ios 0xc8bdc;
|
||||
auto setColor(cocos2d::_ccColor3B const&) = mac 0x274c20, ios 0xc90ac;
|
||||
auto setContentSize(cocos2d::CCSize const&) = mac 0x2749f0, ios 0xc8f64;
|
||||
auto setOpacity(unsigned char) = mac 0x274db0, ios 0xc9108;
|
||||
auto updateColor() = mac 0x274ae0, ios 0xc8f80;
|
||||
~CCLayerColor() = mac 0x2743d0, ios 0x2743e0;
|
||||
static cocos2d::CCLayerColor* create(cocos2d::_ccColor4B const&) = mac 0x2744c0;
|
||||
virtual auto draw() = mac 0x274b50, ios 0xc8fe0;
|
||||
virtual auto getBlendFunc() = mac 0x274480, ios 0xc8bcc;
|
||||
virtual auto init() = mac 0x274800, ios 0xc8de8;
|
||||
virtual auto initWithColor(cocos2d::_ccColor4B const&) = mac 0x2749a0, ios 0xc8f14;
|
||||
virtual auto initWithColor(cocos2d::_ccColor4B const&, float, float) = mac 0x274850, ios 0xc8e34;
|
||||
virtual auto setBlendFunc(cocos2d::_ccBlendFunc) = mac 0x2744a0, ios 0xc8bdc;
|
||||
virtual auto setColor(cocos2d::_ccColor3B const&) = mac 0x274c20, ios 0xc90ac;
|
||||
virtual auto setContentSize(cocos2d::CCSize const&) = mac 0x2749f0, ios 0xc8f64;
|
||||
virtual auto setOpacity(unsigned char) = mac 0x274db0, ios 0xc9108;
|
||||
virtual auto updateColor() = mac 0x274ae0, ios 0xc8f80;
|
||||
virtual ~CCLayerColor() = mac 0x2743d0, ios 0x2743e0;
|
||||
}
|
||||
|
||||
class cocos2d::CCLayerRGBA {
|
||||
|
@ -364,6 +395,7 @@ class cocos2d::CCMenu {
|
|||
}
|
||||
|
||||
class cocos2d::CCMenuItem {
|
||||
auto initWithTarget(cocos2d::CCObject*, cocos2d::SEL_MenuHandler) = mac 0x1fb7f0;
|
||||
virtual ~CCMenuItem() = mac 0x1fb8e0, ios 0x2cdf4;
|
||||
virtual auto activate() = mac 0x1fba70, ios 0x2ceb0;
|
||||
virtual auto selected() = mac 0x1fb9e0, ios 0x2ce2e;
|
||||
|
@ -441,6 +473,7 @@ class cocos2d::CCMoveTo {
|
|||
|
||||
class cocos2d::CCNode {
|
||||
CCNode() = mac 0x122550;
|
||||
auto boundingBox() = mac 0x123030;
|
||||
virtual auto _setZOrder(int) = mac 0x122990, ios 0x15dd7c;
|
||||
virtual auto addChild(cocos2d::CCNode*) = mac 0x1233d0, ios 0x15e5d4;
|
||||
virtual auto addChild(cocos2d::CCNode*, int) = mac 0x1233b0, ios 0x15e5c4;
|
||||
|
@ -608,6 +641,10 @@ class cocos2d::CCPoolManager {
|
|||
static cocos2d::CCPoolManager* sharedPoolManager() = mac 0x2142c0;
|
||||
}
|
||||
|
||||
class cocos2d::CCRemoveSelf {
|
||||
static cocos2d::CCRemoveSelf* create(bool) = mac 0x454700;
|
||||
}
|
||||
|
||||
class cocos2d::CCRenderTexture {
|
||||
auto begin() = mac 0x35ce10;
|
||||
auto end() = mac 0x35d2c0;
|
||||
|
@ -615,6 +652,10 @@ class cocos2d::CCRenderTexture {
|
|||
auto newCCImage(bool) = mac 0x35d7d0;
|
||||
}
|
||||
|
||||
class cocos2d::CCRepeat {
|
||||
static cocos2d::CCRepeat* create(cocos2d::CCFiniteTimeAction*, unsigned int) = mac 0x1f3230;
|
||||
}
|
||||
|
||||
class cocos2d::CCRepeatForever {
|
||||
static cocos2d::CCRepeatForever* create(cocos2d::CCActionInterval*) = mac 0x1f3920;
|
||||
}
|
||||
|
@ -735,6 +776,23 @@ class cocos2d::CCSpriteBatchNode {
|
|||
static auto createWithTexture(cocos2d::CCTexture2D*, unsigned int) = mac 0xbb310;
|
||||
auto getUsedAtlasCapacity() = mac 0xbc6b0;
|
||||
auto increaseAtlasCapacity(unsigned int) = mac 0xbc670;
|
||||
|
||||
virtual ~CCSpriteBatchNode() = mac 0xbb790, ios 0x130d18;
|
||||
|
||||
virtual auto init() = mac 0xbb680, ios 0x130c20;
|
||||
virtual auto addChild(cocos2d::CCNode*) = mac 0xbbb40, ios 0x131034;
|
||||
virtual auto addChild(cocos2d::CCNode*, int) = mac 0xbbb50, ios 0x131038;
|
||||
virtual auto addChild(cocos2d::CCNode*, int, int) = mac 0xbb930, ios 0x130e0c;
|
||||
virtual auto removeChild(cocos2d::CCNode*, bool) = mac 0xbbbb0, ios 0x1310a4;
|
||||
virtual auto removeAllChildrenWithCleanup(bool) = mac 0xbbe30, ios 0x1312d8;
|
||||
virtual auto reorderChild(cocos2d::CCNode*, int) = mac 0xbbb60, ios 0x13103c;
|
||||
virtual auto sortAllChildren() = mac 0xbbee0, ios 0x13137c;
|
||||
virtual auto draw() = mac 0xbc540, ios 0x13191c;
|
||||
virtual auto visit() = mac 0xbb880, ios 0x130d54;
|
||||
virtual auto getTexture() = mac 0xbcd70, ios 0x131a70;
|
||||
virtual auto setTexture(cocos2d::CCTexture2D*) = mac 0xbcda0, ios 0x131a90;
|
||||
virtual auto setBlendFunc(cocos2d::ccBlendFunc) = mac 0xbcd30, ios 0x131a50;
|
||||
virtual auto getBlendFunc() = mac 0xbcd50, ios 0x131a60;
|
||||
}
|
||||
|
||||
class cocos2d::CCSpriteFrame {
|
||||
|
@ -822,6 +880,7 @@ class cocos2d::CCTouch {
|
|||
auto getLocationInView() const = mac 0x38250;
|
||||
auto getPreviousLocationInView() const = mac 0x38270;
|
||||
auto getLocation() const = mac 0x382b0, ios 0x21ce78;
|
||||
auto getStartLocation() const = mac 0x382e0;
|
||||
}
|
||||
|
||||
class cocos2d::CCTouchDispatcher {
|
||||
|
@ -851,7 +910,7 @@ class cocos2d::ZipUtils {
|
|||
}
|
||||
|
||||
class cocos2d::extension::CCControl {
|
||||
inline cocos2d::extension::CCControl::CCControl() {}
|
||||
CCControl() {}
|
||||
virtual bool init() = mac 0x1a71c0;
|
||||
virtual ~CCControl() = mac 0x1a7380;
|
||||
auto sendActionsForControlEvents(cocos2d::extension::CCControlEvent) = mac 0x1a7490;
|
||||
|
@ -874,7 +933,7 @@ class cocos2d::extension::CCControl {
|
|||
}
|
||||
|
||||
class cocos2d::extension::CCControlColourPicker {
|
||||
inline cocos2d::extension::CCControlColourPicker::CCControlColourPicker() {}
|
||||
CCControlColourPicker() {}
|
||||
~CCControlColourPicker() = mac 0x1aae30;
|
||||
auto setColorValue(cocos2d::_ccColor3B const&) = mac 0x1aac10;
|
||||
auto ccTouchBegan(cocos2d::CCTouch*, cocos2d::CCEvent*) = mac 0x1aae10;
|
||||
|
@ -892,6 +951,8 @@ class cocos2d::extension::CCScale9Sprite {
|
|||
CCScale9Sprite() = mac 0x211330;
|
||||
static cocos2d::extension::CCScale9Sprite* create(char const*) = mac 0x2130d0;
|
||||
static cocos2d::extension::CCScale9Sprite* create(char const*, cocos2d::CCRect) = mac 0x212ef0;
|
||||
static cocos2d::extension::CCScale9Sprite* createWithSpriteFrameName(char const*, cocos2d::CCRect) = mac 0x213380;
|
||||
static cocos2d::extension::CCScale9Sprite* createWithSpriteFrameName(char const*) = mac 0x213460;
|
||||
virtual ~CCScale9Sprite() = mac 0x211590;
|
||||
virtual auto init() = mac 0x2115d0;
|
||||
virtual auto setContentSize(cocos2d::CCSize const&) = mac 0x2127c0, ios 0x13e400;
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,35 +1,187 @@
|
|||
set(GEODE_CLI_MINIMUM_VERSION 1.0.5)
|
||||
|
||||
# for passing CLI through CMake arguments
|
||||
if (DEFINED CLI_PATH)
|
||||
list(APPEND CMAKE_PROGRAM_PATH ${CLI_PATH})
|
||||
endif()
|
||||
|
||||
# Find Geode CLI
|
||||
if (NOT DEFINED GEODE_CLI)
|
||||
find_program(GEODE_CLI NAMES geode.exe geode-cli.exe geode geode-cli)
|
||||
endif()
|
||||
|
||||
# Check if CLI was found
|
||||
if (GEODE_CLI STREQUAL "GEODE_CLI-NOTFOUND")
|
||||
message(STATUS "Unable to find Geode CLI")
|
||||
else()
|
||||
message(STATUS "Found Geode CLI: ${GEODE_CLI}")
|
||||
# `geode --version` returns `geode x.x.x\n` so gotta do some wacky shit
|
||||
execute_process(
|
||||
COMMAND ${GEODE_CLI} --version
|
||||
OUTPUT_VARIABLE GEODE_CLI_VERSION
|
||||
)
|
||||
# Remove trailing newline
|
||||
string(STRIP ${GEODE_CLI_VERSION} GEODE_CLI_VERSION)
|
||||
# Remove program name
|
||||
string(REPLACE "geode " "" GEODE_CLI_VERSION ${GEODE_CLI_VERSION})
|
||||
|
||||
# Need at least v1.0.5 (--shut-up arg in geode package resources)
|
||||
if (${GEODE_CLI_VERSION} VERSION_LESS ${GEODE_CLI_MINIMUM_VERSION})
|
||||
message(FATAL_ERROR
|
||||
"Found Geode CLI: ${GEODE_CLI}, however it is version ${GEODE_CLI_VERSION} "
|
||||
"while minimum required is version ${GEODE_CLI_MINIMUM_VERSION}. Please update: "
|
||||
"https://github.com/geode-sdk/cli/releases/latest"
|
||||
)
|
||||
endif()
|
||||
|
||||
message(STATUS "Found Geode CLI: ${GEODE_CLI} (version ${GEODE_CLI_VERSION})")
|
||||
endif()
|
||||
|
||||
function(create_geode_file proname)
|
||||
function(create_geode_file_old proname)
|
||||
message(
|
||||
DEPRECATION
|
||||
"create_geode_file_old has been deprecated. "
|
||||
"Please update to the new (v1.x.x) version of Geode CLI."
|
||||
)
|
||||
|
||||
if (GEODE_DISABLE_CLI_CALLS)
|
||||
message("Skipping creating geode file")
|
||||
return()
|
||||
endif()
|
||||
|
||||
message(STATUS "Creating geode file")
|
||||
|
||||
if(GEODE_CLI STREQUAL "GEODE_CLI-NOTFOUND")
|
||||
message(WARNING "create_geode_file called, but Geode CLI was not found - You will need to manually package the .geode files")
|
||||
else()
|
||||
|
||||
add_custom_target(${proname}_PACKAGE ALL
|
||||
DEPENDS ${proname}
|
||||
COMMAND ${GEODE_CLI} pkg ${CMAKE_CURRENT_SOURCE_DIR} $<TARGET_FILE_DIR:${proname}> $<TARGET_FILE_DIR:${proname}>/${proname}.geode --install --cached
|
||||
VERBATIM USES_TERMINAL
|
||||
)
|
||||
endif()
|
||||
|
||||
endfunction()
|
||||
|
||||
function(create_geode_file proname)
|
||||
# Get DONT_INSTALL argument
|
||||
set(options DONT_INSTALL)
|
||||
cmake_parse_arguments(CREATE_GEODE_FILE "${options}" "" "" ${ARGN})
|
||||
|
||||
if (GEODE_DISABLE_CLI_CALLS)
|
||||
message("Skipping creating geode file for ${proname}")
|
||||
return()
|
||||
endif()
|
||||
|
||||
# what is this for
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/mod.json ${CMAKE_CURRENT_BINARY_DIR}/what.txt)
|
||||
set_target_properties(${proname} PROPERTIES CMAKE_CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/mod.json)
|
||||
|
||||
if(GEODE_CLI STREQUAL "GEODE_CLI-NOTFOUND")
|
||||
message(WARNING "create_geode_file called, but Geode CLI was not found - You will need to manually package the .geode files")
|
||||
return()
|
||||
endif()
|
||||
|
||||
message(STATUS "Creating geode file for ${proname}")
|
||||
|
||||
execute_process(
|
||||
COMMAND ${GEODE_CLI} package get-id ${CMAKE_CURRENT_SOURCE_DIR} --raw
|
||||
OUTPUT_VARIABLE MOD_ID
|
||||
)
|
||||
|
||||
if (CREATE_GEODE_FILE_DONT_INSTALL)
|
||||
set(INSTALL_ARG "")
|
||||
else()
|
||||
set(INSTALL_ARG "--install")
|
||||
endif()
|
||||
|
||||
set_target_properties(${proname} PROPERTIES PREFIX "")
|
||||
set_target_properties(${proname} PROPERTIES OUTPUT_NAME ${MOD_ID})
|
||||
add_custom_target(${proname}_PACKAGE ALL
|
||||
DEPENDS ${proname} ${CMAKE_CURRENT_SOURCE_DIR}/mod.json
|
||||
COMMAND ${GEODE_CLI} package new ${CMAKE_CURRENT_SOURCE_DIR} --binary $<TARGET_FILE:${proname}> --output $<TARGET_FILE_DIR:${proname}>/${proname}.geode ${INSTALL_ARG}
|
||||
VERBATIM USES_TERMINAL
|
||||
)
|
||||
endfunction()
|
||||
|
||||
function(package_geode_resources proname src dest)
|
||||
if (GEODE_DISABLE_CLI_CALLS)
|
||||
message("Skipping packaging resources from ${src} into ${dest}")
|
||||
return()
|
||||
endif()
|
||||
|
||||
message(STATUS "Packaging resources from ${src} into ${dest}")
|
||||
|
||||
if(GEODE_CLI STREQUAL "GEODE_CLI-NOTFOUND")
|
||||
message(WARNING "create_geode_file called, but Geode CLI was not found - You will need to manually package the .geode files")
|
||||
message(WARNING
|
||||
"package_geode_resources called, but Geode CLI was "
|
||||
"not found - You will need to manually package the resources"
|
||||
)
|
||||
else()
|
||||
|
||||
add_custom_target(${proname}_PACKAGE ALL
|
||||
DEPENDS ${proname} ${CMAKE_CURRENT_SOURCE_DIR}/mod.json
|
||||
COMMAND ${GEODE_CLI} package new ${CMAKE_CURRENT_SOURCE_DIR} --binary $<TARGET_FILE:${proname}> --output $<TARGET_FILE_DIR:${proname}>/${proname}.geode --install
|
||||
DEPENDS ${proname}
|
||||
COMMAND ${GEODE_CLI} package resources ${src} ${dest}
|
||||
VERBATIM USES_TERMINAL
|
||||
)
|
||||
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(package_geode_resources_now proname src dest header_dest)
|
||||
if (GEODE_DISABLE_CLI_CALLS)
|
||||
message(WARNING
|
||||
"package_geode_resources_now called, but GEODE_DISABLE_CLI_CALLS
|
||||
is set to true - Ignoring it as this function requires CLI calls
|
||||
in order to work"
|
||||
)
|
||||
endif()
|
||||
|
||||
if(GEODE_CLI STREQUAL "GEODE_CLI-NOTFOUND")
|
||||
message(FATAL_ERROR
|
||||
"package_geode_resources_now called, but Geode CLI "
|
||||
"was not found - Please install Geode CLI from "
|
||||
"https://github.com/geode-sdk/cli/releases/latest"
|
||||
)
|
||||
return()
|
||||
endif()
|
||||
|
||||
message(STATUS "Packaging resources now from ${src} into ${dest}")
|
||||
|
||||
execute_process(
|
||||
COMMAND ${GEODE_CLI} package resources ${src} ${dest} --shut-up
|
||||
RESULT_VARIABLE GEODE_PACKAGE_RES
|
||||
)
|
||||
|
||||
if (NOT GEODE_PACKAGE_RES EQUAL "0")
|
||||
message(FATAL_ERROR
|
||||
"Command \"${GEODE_CLI} package resources ${src} ${dest}\" returned "
|
||||
"${GEODE_PACKAGE_RES} - Expected 0"
|
||||
)
|
||||
endif()
|
||||
|
||||
file(GLOB RESOURCE_FILES "${dest}/*.*")
|
||||
|
||||
set(HEADER_FILE
|
||||
"#include <unordered_map>\n\n"
|
||||
"static const std::unordered_map<std::string, std::string> "
|
||||
"LOADER_RESOURCE_HASHES {\n"
|
||||
)
|
||||
|
||||
foreach(file ${RESOURCE_FILES})
|
||||
cmake_path(GET file FILENAME FILE_NAME)
|
||||
if (NOT FILE_NAME STREQUAL ".geode_cache")
|
||||
|
||||
file(SHA256 ${file} COMPUTED_HASH)
|
||||
list(APPEND HEADER_FILE "\t{ \"${FILE_NAME}\", \"${COMPUTED_HASH}\" },\n")
|
||||
|
||||
endif()
|
||||
|
||||
endforeach()
|
||||
|
||||
list(APPEND HEADER_FILE "}\;\n")
|
||||
|
||||
file(WRITE ${header_dest} ${HEADER_FILE})
|
||||
message(STATUS "Wrote resource hashes to ${header_dest}")
|
||||
|
||||
endfunction()
|
||||
|
|
|
@ -39,8 +39,8 @@ elseif (GEODE_TARGET_PLATFORM STREQUAL "MacOS")
|
|||
${GEODE_LOADER_PATH}/include/Geode/cocos/cocos2dx/platform/third_party/mac/OGLES
|
||||
)
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} INTERFACE "-framework Cocoa")
|
||||
target_compile_options(${PROJECT_NAME} INTERFACE -fms-extensions -Wno-deprecated -Wno-ignored-attributes -Os -flto -fvisibility=internal)
|
||||
target_link_libraries(${PROJECT_NAME} INTERFACE curl "-framework Cocoa")
|
||||
target_compile_options(${PROJECT_NAME} INTERFACE -fms-extensions -Wno-deprecated -Wno-ignored-attributes -Os #[[-flto]] -fvisibility=internal)
|
||||
target_compile_definitions(${PROJECT_NAME} INTERFACE -DCC_TARGET_OS_MAC)
|
||||
|
||||
set(GEODE_PLATFORM_BINARY "Geode.dylib")
|
||||
|
|
|
@ -48,7 +48,7 @@ struct FunctionBegin {
|
|||
if (name != f.name || is_const != f.is_const || args.size() != f.args.size())
|
||||
return false;
|
||||
|
||||
for (int i=0; i<args.size(); ++i) {
|
||||
for (size_t i = 0; i < args.size(); ++i) {
|
||||
if (!(args[i].first == f.args[i].first))
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
namespace { namespace format_strings {
|
||||
|
||||
char const* declare_address = R"GEN(
|
||||
GEODE_NOINLINE GEODE_HIDDEN inline static uintptr_t address{index}() {{
|
||||
GEODE_INLINE GEODE_HIDDEN static uintptr_t address{index}() {{
|
||||
static uintptr_t ret = {address};
|
||||
return ret;
|
||||
}}
|
||||
|
|
|
@ -3,82 +3,101 @@
|
|||
#include <set>
|
||||
|
||||
namespace { namespace format_strings {
|
||||
char const* class_predeclare = "class {class_name};\n";
|
||||
// requires: base_classes, class_name
|
||||
char const* binding_include = R"GEN(#include "binding/{file_name}"
|
||||
)GEN";
|
||||
|
||||
char const* class_includes = R"GEN(#pragma once
|
||||
#include <Geode/c++stl/gdstdlib.hpp>
|
||||
#include <cocos2d.h>
|
||||
#include <cocos-ext.h>
|
||||
#include <Geode/GeneratedPredeclare.hpp>
|
||||
#include <Geode/Enums.hpp>
|
||||
|
||||
)GEN";
|
||||
|
||||
char const* class_include_prereq = R"GEN(#include "{file_name}"
|
||||
)GEN";
|
||||
|
||||
char const* class_start = R"GEN(
|
||||
class {class_name}{base_classes} {{
|
||||
public:
|
||||
)GEN";
|
||||
|
||||
char const* monostate_constructor = R"GEN(
|
||||
GEODE_MONOSTATE_CONSTRUCTOR_GD({class_name}, {first_base})
|
||||
char const* monostate_constructor = R"GEN( GEODE_MONOSTATE_CONSTRUCTOR_GD({class_name}, {first_base})
|
||||
)GEN";
|
||||
|
||||
char const* monostate_constructor_cutoff = R"GEN(
|
||||
GEODE_MONOSTATE_CONSTRUCTOR_CUTOFF({class_name}, {first_base})
|
||||
char const* monostate_constructor_cutoff = R"GEN( GEODE_MONOSTATE_CONSTRUCTOR_CUTOFF({class_name}, {first_base})
|
||||
)GEN";
|
||||
|
||||
char const* function_definition = R"GEN(
|
||||
{docs}{static}{virtual}{return_type} {function_name}({parameters}){const};
|
||||
char const* function_definition = R"GEN({docs} {static}{virtual}{return_type} {function_name}({parameters}){const};
|
||||
)GEN";
|
||||
|
||||
char const* error_definition = R"GEN(
|
||||
template <bool T=false>
|
||||
char const* error_definition = R"GEN( template <bool T=false>
|
||||
{static}{return_type} {function_name}({parameters}){const}{{
|
||||
static_assert(T, "Implement {class_name}::{function_name}");
|
||||
}}
|
||||
)GEN";
|
||||
|
||||
char const* error_definition_virtual = R"GEN( [[deprecated("Use of undefined virtual function - will crash at runtime!!!")]]
|
||||
{virtual}{return_type} {function_name}({parameters}){const}{{
|
||||
#ifdef GEODE_NO_UNDEFINED_VIRTUALS
|
||||
static_assert(false, "Undefined virtual function - implement in GeometryDash.bro");
|
||||
#endif
|
||||
throw std::runtime_error("Use of undefined virtual function " + GEODE_PRETTY_FUNCTION);
|
||||
}}
|
||||
)GEN";
|
||||
|
||||
char const* structor_definition = R"GEN(
|
||||
{function_name}({parameters});)GEN";
|
||||
|
||||
// requires: type, member_name, array
|
||||
char const* member_definition = R"GEN(
|
||||
{type} {member_name};)GEN";
|
||||
char const* member_definition = R"GEN( {type} {member_name};
|
||||
)GEN";
|
||||
|
||||
char const* pad_definition = R"GEN(
|
||||
GEODE_PAD({hardcode});)GEN";
|
||||
char const* unimplemented_definition = R"GEN(
|
||||
GEODE_UNIMPLEMENTED_PAD)GEN";
|
||||
char const* pad_definition = R"GEN( GEODE_PAD({hardcode});
|
||||
)GEN";
|
||||
|
||||
// requires: hardcode_macro, type, member_name, hardcode
|
||||
char const* hardcode_definition = R"GEN(
|
||||
CLASSPARAM({type}, {member_name}, {hardcode});)GEN";
|
||||
|
||||
char const* class_end = R"GEN(
|
||||
};
|
||||
char const* class_end = R"GEN(};
|
||||
)GEN";
|
||||
}}
|
||||
|
||||
std::string generateGDHeader(Root& root) {
|
||||
std::string output("#pragma once\n#include <Geode/c++stl/gdstdlib.hpp>\n#include <cocos2d.h>\n");
|
||||
|
||||
for (auto& cls : root.classes) {
|
||||
if (can_find(cls.name, "cocos2d"))
|
||||
continue;
|
||||
|
||||
output += fmt::format(::format_strings::class_predeclare,
|
||||
fmt::arg("class_name", cls.name)
|
||||
);
|
||||
}
|
||||
std::string generateBindingHeader(Root& root, ghc::filesystem::path const& singleFolder) {
|
||||
std::string output;
|
||||
|
||||
for (auto& cls : root.classes) {
|
||||
if (can_find(cls.name, "cocos2d"))
|
||||
continue;
|
||||
|
||||
std::string filename = (codegen::getUnqualifiedClassName(cls.name) + ".hpp");
|
||||
output += fmt::format(format_strings::binding_include,
|
||||
fmt::arg("file_name", filename)
|
||||
);
|
||||
|
||||
std::string single_output;
|
||||
single_output += format_strings::class_includes;
|
||||
|
||||
for (auto dep : cls.depends) {
|
||||
if (can_find(dep, "cocos2d::")) continue;
|
||||
|
||||
std::string depfilename = (codegen::getUnqualifiedClassName(dep) + ".hpp");
|
||||
|
||||
single_output += fmt::format(format_strings::class_include_prereq, fmt::arg("file_name", depfilename));
|
||||
}
|
||||
|
||||
std::string supers = str_if(
|
||||
fmt::format(" : public {}", fmt::join(cls.superclasses, ", ")),
|
||||
!cls.superclasses.empty()
|
||||
);
|
||||
|
||||
output += fmt::format(::format_strings::class_start,
|
||||
single_output += fmt::format(::format_strings::class_start,
|
||||
fmt::arg("class_name", cls.name),
|
||||
fmt::arg("base_classes", supers)
|
||||
);
|
||||
|
||||
// what.
|
||||
if (!cls.superclasses.empty()) {
|
||||
output += fmt::format(
|
||||
single_output += fmt::format(
|
||||
can_find(cls.superclasses[0], "cocos2d")
|
||||
? format_strings::monostate_constructor_cutoff
|
||||
: format_strings::monostate_constructor,
|
||||
|
@ -87,15 +106,17 @@ std::string generateGDHeader(Root& root) {
|
|||
);
|
||||
}
|
||||
|
||||
bool unimplementedField = false;
|
||||
for (auto field : cls.fields) {
|
||||
FunctionBegin* fb;
|
||||
char const* used_format = format_strings::function_definition;
|
||||
|
||||
if (auto i = field.get_as<InlineField>()) {
|
||||
output += "\t" + i->inner + "\n";
|
||||
single_output += "\t" + i->inner + "\n";
|
||||
continue;
|
||||
} else if (auto m = field.get_as<MemberField>()) {
|
||||
output += fmt::format(format_strings::member_definition,
|
||||
if (unimplementedField) single_output += "\t[[deprecated(\"Member placed incorrectly - will crash at runtime!!!\")]]\n";
|
||||
single_output += fmt::format(format_strings::member_definition,
|
||||
fmt::arg("type", m->type.name),
|
||||
fmt::arg("member_name", m->name + str_if(fmt::format("[{}]", m->count), m->count))
|
||||
);
|
||||
|
@ -104,9 +125,9 @@ std::string generateGDHeader(Root& root) {
|
|||
auto hardcode = codegen::platformNumber(p->amount);
|
||||
|
||||
if (hardcode) {
|
||||
output += fmt::format(format_strings::pad_definition, fmt::arg("hardcode", hardcode));
|
||||
single_output += fmt::format(format_strings::pad_definition, fmt::arg("hardcode", hardcode));
|
||||
} else {
|
||||
output += "\n GEODE_UNIMPLEMENTED_PAD";
|
||||
unimplementedField = true;
|
||||
}
|
||||
continue;
|
||||
} else if (auto fn = field.get_as<OutOfLineField>()) {
|
||||
|
@ -117,12 +138,15 @@ std::string generateGDHeader(Root& root) {
|
|||
if (!codegen::platformNumber(fn->binds)) {
|
||||
used_format = format_strings::error_definition;
|
||||
|
||||
if (fb->is_virtual)
|
||||
used_format = format_strings::error_definition_virtual;
|
||||
|
||||
if (fb->type != FunctionType::Normal)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
output += fmt::format(used_format,
|
||||
single_output += fmt::format(used_format,
|
||||
fmt::arg("virtual", str_if("virtual ", fb->is_virtual)),
|
||||
fmt::arg("static", str_if("static ", fb->is_static)),
|
||||
fmt::arg("class_name", cls.name),
|
||||
|
@ -136,9 +160,9 @@ std::string generateGDHeader(Root& root) {
|
|||
}
|
||||
|
||||
// if (hasClass)
|
||||
output += ::format_strings::class_end;
|
||||
single_output += ::format_strings::class_end;
|
||||
|
||||
// queued.pop_front();
|
||||
writeFile(singleFolder / filename, single_output);
|
||||
}
|
||||
|
||||
return output;
|
|
@ -3,22 +3,7 @@
|
|||
|
||||
using namespace codegen;
|
||||
|
||||
void writeFile(ghc::filesystem::path const& writePath, std::string const& output) {
|
||||
std::ifstream readfile;
|
||||
readfile >> std::noskipws;
|
||||
readfile.open(writePath);
|
||||
std::string data((std::istreambuf_iterator<char>(readfile)), std::istreambuf_iterator<char>());
|
||||
readfile.close();
|
||||
|
||||
if (data != output) {
|
||||
std::ofstream writefile;
|
||||
writefile.open(writePath);
|
||||
writefile << output;
|
||||
writefile.close();
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int main(int argc, char** argv) try {
|
||||
if (argc != 4) throw codegen::error("Invalid number of parameters (expected 3 found {})", argc-1);
|
||||
|
||||
std::string p = argv[1];
|
||||
|
@ -31,8 +16,10 @@ int main(int argc, char** argv) {
|
|||
|
||||
chdir(argv[2]);
|
||||
|
||||
ghc::filesystem::path writeDir = argv[3];
|
||||
auto writeDir = ghc::filesystem::path(argv[3]) / "Geode";
|
||||
ghc::filesystem::create_directories(writeDir);
|
||||
ghc::filesystem::create_directories(writeDir / "modify");
|
||||
ghc::filesystem::create_directories(writeDir / "binding");
|
||||
|
||||
Root root = broma::parse_file("Entry.bro");
|
||||
|
||||
|
@ -45,9 +32,13 @@ int main(int argc, char** argv) {
|
|||
}
|
||||
|
||||
writeFile(writeDir / "GeneratedAddress.hpp", generateAddressHeader(root));
|
||||
writeFile(writeDir / "GeneratedModify.hpp", generateModifyHeader(root)); // pretty much obsolete with a custom compiler
|
||||
writeFile(writeDir / "GeneratedModify.hpp", generateModifyHeader(root, writeDir / "modify")); // pretty much obsolete with a custom compiler
|
||||
writeFile(writeDir / "GeneratedWrapper.hpp", generateWrapperHeader(root)); // pretty much obsolete with a custom compiler
|
||||
writeFile(writeDir / "GeneratedType.hpp", generateTypeHeader(root)); // pretty much obsolete with a custom compiler
|
||||
writeFile(writeDir / "GeneratedHeader.hpp", generateGDHeader(root));
|
||||
writeFile(writeDir / "GeneratedSource.cpp", generateGDSource(root));
|
||||
writeFile(writeDir / "GeneratedBinding.hpp", generateBindingHeader(root, writeDir / "binding"));
|
||||
writeFile(writeDir / "GeneratedPredeclare.hpp", generatePredeclareHeader(root));
|
||||
writeFile(writeDir / "GeneratedSource.cpp", generateBindingSource(root));
|
||||
} catch(std::exception& e) {
|
||||
std::cout << "Codegen error: " << e.what() << "\n";
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -3,34 +3,51 @@
|
|||
|
||||
namespace { namespace format_strings {
|
||||
// requires: class_name
|
||||
char const* modify_start = R"GEN(
|
||||
template<class Derived>
|
||||
struct Modify<Derived, {class_name}> : ModifyBase<Modify<Derived, {class_name}>> {{
|
||||
using ModifyBase<Modify<Derived, {class_name}>>::ModifyBase;
|
||||
using Base = {class_name};
|
||||
static void apply() {{
|
||||
using namespace geode::core::meta;
|
||||
char const* modify_start = R"GEN(#pragma once
|
||||
#include <Geode/modify/Modify.hpp>
|
||||
#include <Geode/modify/Field.hpp>
|
||||
#include <Geode/modify/InternalMacros.hpp>
|
||||
using namespace geode::modifier;
|
||||
|
||||
namespace geode::modifier {{
|
||||
template<class Derived>
|
||||
struct Modify<Derived, {class_name}> : ModifyBase<Modify<Derived, {class_name}>> {{
|
||||
using ModifyBase<Modify<Derived, {class_name}>>::ModifyBase;
|
||||
using Base = {class_name};
|
||||
static void apply() {{
|
||||
using namespace geode::core::meta;
|
||||
)GEN";
|
||||
|
||||
// requires: index, class_name, arg_types, function_name, raw_arg_types, non_virtual
|
||||
char const* apply_function = R"GEN(
|
||||
GEODE_APPLY_MODIFY_FOR_FUNCTION({index}, {function_convention}, {class_name}, {function_name}))GEN";
|
||||
GEODE_APPLY_MODIFY_FOR_FUNCTION({index}, {function_convention}, {class_name}, {function_name}))GEN";
|
||||
|
||||
char const* modify_end = R"GEN(
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
)GEN";
|
||||
|
||||
char const* modify_include = R"GEN(#include "modify/{file_name}"
|
||||
)GEN";
|
||||
}}
|
||||
|
||||
|
||||
std::string generateModifyHeader(Root& root) {
|
||||
std::string generateModifyHeader(Root& root, ghc::filesystem::path const& singleFolder) {
|
||||
std::string output;
|
||||
|
||||
for (auto c : root.classes) {
|
||||
if (c.name == "cocos2d")
|
||||
continue;
|
||||
|
||||
output += fmt::format(format_strings::modify_start,
|
||||
std::string filename = (codegen::getUnqualifiedClassName(c.name) + ".hpp");
|
||||
output += fmt::format(format_strings::modify_include,
|
||||
fmt::arg("file_name", filename)
|
||||
);
|
||||
|
||||
std::string single_output;
|
||||
|
||||
single_output += fmt::format(format_strings::modify_start,
|
||||
fmt::arg("class_name", c.name)
|
||||
);
|
||||
|
||||
|
@ -52,7 +69,7 @@ std::string generateModifyHeader(Root& root) {
|
|||
break;
|
||||
}
|
||||
|
||||
output += fmt::format(format_strings::apply_function,
|
||||
single_output += fmt::format(format_strings::apply_function,
|
||||
fmt::arg("index", f.field_id),
|
||||
fmt::arg("class_name", c.name),
|
||||
fmt::arg("function_name", function_name),
|
||||
|
@ -61,7 +78,9 @@ std::string generateModifyHeader(Root& root) {
|
|||
}
|
||||
}
|
||||
|
||||
output += format_strings::modify_end;
|
||||
single_output += format_strings::modify_end;
|
||||
|
||||
writeFile(singleFolder / filename, single_output);
|
||||
}
|
||||
|
||||
return output;
|
||||
|
|
22
codegen/src/PredeclareGen.cpp
Normal file
22
codegen/src/PredeclareGen.cpp
Normal file
|
@ -0,0 +1,22 @@
|
|||
#include "Shared.hpp"
|
||||
#include <iostream>
|
||||
#include <set>
|
||||
|
||||
namespace { namespace format_strings {
|
||||
char const* class_predeclare = "class {class_name};\n";
|
||||
}}
|
||||
|
||||
std::string generatePredeclareHeader(Root& root) {
|
||||
std::string output("#pragma once\n");
|
||||
|
||||
for (auto& cls : root.classes) {
|
||||
if (can_find(cls.name, "cocos2d"))
|
||||
continue;
|
||||
|
||||
output += fmt::format(::format_strings::class_predeclare,
|
||||
fmt::arg("class_name", cls.name)
|
||||
);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
|
@ -5,6 +5,7 @@
|
|||
#include <fmt/format.h>
|
||||
#include <fmt/ranges.h>
|
||||
#include <fstream>
|
||||
#include <fs/filesystem.hpp> // bruh
|
||||
|
||||
using std::istreambuf_iterator;
|
||||
|
||||
|
@ -19,13 +20,29 @@ using std::istreambuf_iterator;
|
|||
#endif
|
||||
|
||||
std::string generateAddressHeader(Root& root);
|
||||
std::string generateModifyHeader(Root& root);
|
||||
std::string generateModifyHeader(Root& root, ghc::filesystem::path const& singleFolder);
|
||||
std::string generateWrapperHeader(Root& root);
|
||||
std::string generateTypeHeader(Root& root);
|
||||
std::string generateGDHeader(Root& root);
|
||||
std::string generateGDSource(Root& root);
|
||||
std::string generateBindingHeader(Root& root, ghc::filesystem::path const& singleFolder);
|
||||
std::string generatePredeclareHeader(Root& root);
|
||||
std::string generateBindingSource(Root& root);
|
||||
std::string generateTidyHeader(Root& root);
|
||||
|
||||
inline void writeFile(ghc::filesystem::path const& writePath, std::string const& output) {
|
||||
std::ifstream readfile;
|
||||
readfile >> std::noskipws;
|
||||
readfile.open(writePath);
|
||||
std::string data((std::istreambuf_iterator<char>(readfile)), std::istreambuf_iterator<char>());
|
||||
readfile.close();
|
||||
|
||||
if (data != output) {
|
||||
std::ofstream writefile;
|
||||
writefile.open(writePath);
|
||||
writefile << output;
|
||||
writefile.close();
|
||||
}
|
||||
}
|
||||
|
||||
inline std::string str_if(std::string&& str, bool cond) {
|
||||
return cond ? str : "";
|
||||
}
|
||||
|
|
|
@ -63,13 +63,16 @@ types::ret{index} {class_name}::{function_name}({parameters}){const} {{
|
|||
}}
|
||||
)GEN";
|
||||
|
||||
// requires: static, return_type, function_name, raw_parameters, const, class_name, definition
|
||||
char const* ool_function_definition = R"GEN(
|
||||
{return} {class_name}::{function_name}({parameters}){const} {definition}
|
||||
)GEN";
|
||||
|
||||
char const* ool_structor_function_definition = R"GEN(
|
||||
{class_name}::{function_name}({parameters}){const} {definition}
|
||||
)GEN";
|
||||
}}
|
||||
|
||||
std::string generateGDSource(Root& root) {
|
||||
std::string generateBindingSource(Root& root) {
|
||||
std::string output(format_strings::source_start);
|
||||
|
||||
for (auto& c : root.classes) {
|
||||
|
@ -81,15 +84,39 @@ std::string generateGDSource(Root& root) {
|
|||
output += i->inner + "\n";
|
||||
}
|
||||
} else if (auto fn = f.get_as<OutOfLineField>()) {
|
||||
output += fmt::format(format_strings::ool_function_definition,
|
||||
fmt::arg("function_name", fn->beginning.name),
|
||||
fmt::arg("const", str_if(" const ", fn->beginning.is_const)),
|
||||
fmt::arg("class_name", c.name),
|
||||
fmt::arg("parameters", codegen::getParameters(fn->beginning)),
|
||||
fmt::arg("index", f.field_id),
|
||||
fmt::arg("definition", fn->inner),
|
||||
fmt::arg("return", fn->beginning.ret.name)
|
||||
);
|
||||
if (codegen::getStatus(f) != BindStatus::Unbindable)
|
||||
continue;
|
||||
|
||||
// no cocos2d definitions on windows
|
||||
if (codegen::platform == Platform::Windows && f.parent.rfind("cocos2d::", 0) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (fn->beginning.type) {
|
||||
case FunctionType::Ctor:
|
||||
case FunctionType::Dtor:
|
||||
output += fmt::format(format_strings::ool_structor_function_definition,
|
||||
fmt::arg("function_name", fn->beginning.name),
|
||||
fmt::arg("const", str_if(" const ", fn->beginning.is_const)),
|
||||
fmt::arg("class_name", c.name),
|
||||
fmt::arg("parameters", codegen::getParameters(fn->beginning)),
|
||||
fmt::arg("index", f.field_id),
|
||||
fmt::arg("definition", fn->inner)
|
||||
);
|
||||
break;
|
||||
default:
|
||||
output += fmt::format(format_strings::ool_function_definition,
|
||||
fmt::arg("function_name", fn->beginning.name),
|
||||
fmt::arg("const", str_if(" const ", fn->beginning.is_const)),
|
||||
fmt::arg("class_name", c.name),
|
||||
fmt::arg("parameters", codegen::getParameters(fn->beginning)),
|
||||
fmt::arg("index", f.field_id),
|
||||
fmt::arg("definition", fn->inner),
|
||||
fmt::arg("return", fn->beginning.ret.name)
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
} else if (auto fn = f.get_as<FunctionBindField>()) {
|
||||
if (codegen::getStatus(f) != BindStatus::NeedsBinding)
|
||||
continue;
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
// included by default in every geode project
|
||||
|
||||
#include <Geode/Geode.hpp>
|
||||
#include <Geode/Loader.hpp>
|
||||
|
||||
GEODE_API bool GEODE_CALL geode_implicit_load(geode::Mod* m) {
|
||||
geode::Interface::get()->init(m);
|
||||
geode::Mod::setSharedMod(m);
|
||||
geode::log::releaseSchedules(m);
|
||||
geode::Loader::get()->releaseScheduledFunctions(m);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -15,6 +15,12 @@
|
|||
#include <locale>
|
||||
#include <ostream>
|
||||
#include <type_traits>
|
||||
#include <cmath>
|
||||
|
||||
// fix for msvc aliasing isnan to _isnan
|
||||
#ifdef isnan
|
||||
#undef isnan
|
||||
#endif
|
||||
|
||||
#include "format.h"
|
||||
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
cmake_minimum_required(VERSION 3.21 FATAL_ERROR)
|
||||
|
||||
project(geode-loader VERSION 0.2.0 LANGUAGES C CXX)
|
||||
project(geode-loader VERSION ${GEODE_VERSION} LANGUAGES C CXX)
|
||||
set(PROJECT_VERSION_TYPE Alpha)
|
||||
|
||||
# Package info file for internal representation
|
||||
configure_file(resources/mod.json.in ${CMAKE_CURRENT_SOURCE_DIR}/resources/mod.json)
|
||||
file(READ resources/mod.json LOADER_MOD_JSON)
|
||||
file(READ resources/about.md LOADER_ABOUT_MD)
|
||||
configure_file(src/internal/about.hpp.in ${CMAKE_CURRENT_SOURCE_DIR}/src/internal/about.hpp)
|
||||
|
||||
# Source files
|
||||
file(GLOB CORE_SOURCES
|
||||
src/cocos2d-ext/*.cpp
|
||||
src/core/*.cpp
|
||||
|
@ -22,6 +26,14 @@ file(GLOB CORE_SOURCES
|
|||
src/utils/*.cpp
|
||||
src/utils/windows/*.cpp
|
||||
src/utils/zip/*.cpp
|
||||
src/index/*.cpp
|
||||
src/ui/nodes/*.cpp
|
||||
src/ui/internal/*.cpp
|
||||
src/ui/internal/credits/*.cpp
|
||||
src/ui/internal/dev/*.cpp
|
||||
src/ui/internal/info/*.cpp
|
||||
src/ui/internal/list/*.cpp
|
||||
src/ui/internal/settings/*.cpp
|
||||
)
|
||||
|
||||
file(GLOB OBJC_SOURCES
|
||||
|
@ -33,7 +45,7 @@ file(GLOB OBJC_SOURCES
|
|||
src/utils/mac/*.mm
|
||||
)
|
||||
|
||||
# embed version info in binary
|
||||
# Embed version info in binary
|
||||
if (WIN32)
|
||||
configure_file(src/internal/windows/info.rc.in info.rc)
|
||||
set(CORE_SOURCES ${CORE_SOURCES} ${CMAKE_CURRENT_BINARY_DIR}/info.rc)
|
||||
|
@ -50,53 +62,73 @@ make_directory("${GEODE_BIN_PATH}/nightly")
|
|||
set_target_properties(${PROJECT_NAME} PROPERTIES
|
||||
PREFIX ""
|
||||
OUTPUT_NAME "Geode"
|
||||
LIBRARY_OUTPUT_DIRECTORY "${GEODE_BIN_PATH}"
|
||||
RUNTIME_OUTPUT_DIRECTORY "${GEODE_BIN_PATH}"
|
||||
ARCHIVE_OUTPUT_DIRECTORY "${GEODE_BIN_PATH}"
|
||||
# i'm going to say a slur that not a single soul has uttered in the last 200 years
|
||||
LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO "${GEODE_BIN_PATH}/nightly"
|
||||
RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO "${GEODE_BIN_PATH}/nightly"
|
||||
ARCHIVE_OUTPUT_DIRECTORY_RELWITHDEBINFO "${GEODE_BIN_PATH}/nightly"
|
||||
LIBRARY_OUTPUT_DIRECTORY_RELEASE "${GEODE_BIN_PATH}/nightly"
|
||||
RUNTIME_OUTPUT_DIRECTORY_RELEASE "${GEODE_BIN_PATH}/nightly"
|
||||
ARCHIVE_OUTPUT_DIRECTORY_RELEASE "${GEODE_BIN_PATH}/nightly"
|
||||
LIBRARY_OUTPUT_DIRECTORY_MINSIZEREL "${GEODE_BIN_PATH}/nightly"
|
||||
RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL "${GEODE_BIN_PATH}/nightly"
|
||||
ARCHIVE_OUTPUT_DIRECTORY_MINSIZEREL "${GEODE_BIN_PATH}/nightly"
|
||||
LIBRARY_OUTPUT_DIRECTORY "${GEODE_BIN_PATH}/nightly"
|
||||
RUNTIME_OUTPUT_DIRECTORY "${GEODE_BIN_PATH}/nightly"
|
||||
ARCHIVE_OUTPUT_DIRECTORY "${GEODE_BIN_PATH}/nightly"
|
||||
)
|
||||
|
||||
if (APPLE)
|
||||
add_custom_command(
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E rename "$<TARGET_FILE:${PROJECT_NAME}>" "${GEODE_BIN_PATH}/nightly/$<TARGET_FILE_NAME:${PROJECT_NAME}>"
|
||||
DEPENDS $<TARGET_FILE:${PROJECT_NAME}>
|
||||
VERBATIM
|
||||
TARGET ${PROJECT_NAME}
|
||||
)
|
||||
elseif(WIN32)
|
||||
add_custom_command(
|
||||
COMMAND ${CMAKE_COMMAND} -E rename "$<TARGET_FILE:${PROJECT_NAME}>" "${GEODE_BIN_PATH}/nightly/$<TARGET_FILE_NAME:${PROJECT_NAME}>"
|
||||
COMMAND ${CMAKE_COMMAND} -E rename "$<TARGET_LINKER_FILE:${PROJECT_NAME}>" "${GEODE_BIN_PATH}/nightly/$<TARGET_LINKER_FILE_NAME:${PROJECT_NAME}>"
|
||||
DEPENDS $<TARGET_FILE:${PROJECT_NAME}>
|
||||
VERBATIM
|
||||
TARGET ${PROJECT_NAME}
|
||||
)
|
||||
if (GEODE_NO_UNDEFINED_VIRTUALS)
|
||||
target_compile_definitions(${PROJECT_NAME} PUBLIC GEODE_NO_UNDEFINED_VIRTUALS)
|
||||
endif()
|
||||
|
||||
# Package resources for UI
|
||||
package_geode_resources_now(
|
||||
${PROJECT_NAME}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/resources
|
||||
${GEODE_BIN_PATH}/nightly/resources
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/internal/resources.hpp
|
||||
)
|
||||
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE
|
||||
src/internal/
|
||||
src/platform/
|
||||
src/gui/
|
||||
src/index/
|
||||
md4c/src/
|
||||
hash/
|
||||
./ # lilac
|
||||
)
|
||||
|
||||
# For profiling
|
||||
set_property(TARGET ${PROJECT_NAME} PROPERTY RULE_LAUNCH_COMPILE "${CMAKE_COMMAND} -E time")
|
||||
|
||||
target_compile_definitions(${PROJECT_NAME} PUBLIC GEODE_EXPORTING GEODE_PLATFORM_CONSOLE)
|
||||
target_compile_definitions(${PROJECT_NAME} PUBLIC GEODE_EXPORTING)
|
||||
|
||||
# Markdown support
|
||||
add_subdirectory(md4c)
|
||||
target_link_libraries(${PROJECT_NAME} md4c)
|
||||
|
||||
# Lilac (hooking)
|
||||
add_subdirectory(lilac)
|
||||
target_link_libraries(${PROJECT_NAME} z lilac_hook geode-sdk)
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} z lilac_hook geode-sdk) # lilac
|
||||
|
||||
# Use precompiled headers for faster builds
|
||||
set_source_files_properties(${OBJC_SOURCES} PROPERTIES SKIP_PRECOMPILE_HEADERS ON)
|
||||
target_precompile_headers(${PROJECT_NAME} PRIVATE
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include/Geode/DefaultInclude.hpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include/Geode/Modify.hpp"
|
||||
# "${CMAKE_CURRENT_SOURCE_DIR}/include/Geode/Utils.hpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include/Geode/Loader.hpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include/Geode/UI.hpp"
|
||||
# "${CMAKE_CURRENT_SOURCE_DIR}/include/Geode/Bindings.hpp"
|
||||
# "${CMAKE_CURRENT_SOURCE_DIR}/include/Geode/Modify.hpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include/Geode/cocos/cocos2dx/include/cocos2d.h"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include/Geode/cocos/extensions/cocos-ext.h"
|
||||
)
|
||||
|
||||
# Create launcher
|
||||
if (APPLE)
|
||||
add_subdirectory(launcher/mac)
|
||||
|
||||
if(CMAKE_SYSTEM_PROCESSOR MATCHES "arm" OR GEODE_TARGET_PLATFORM STREQUAL "iOS")
|
||||
add_custom_command(TARGET geode-loader
|
||||
POST_BUILD COMMAND
|
||||
|
@ -105,19 +137,30 @@ if (APPLE)
|
|||
endif()
|
||||
elseif (WIN32)
|
||||
add_subdirectory(launcher/windows)
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE dobby/include)
|
||||
target_link_directories(${PROJECT_NAME} PRIVATE dobby)
|
||||
target_link_libraries(${PROJECT_NAME} dobby)
|
||||
|
||||
set(DOBBY_GENERATE_SHARED OFF CACHE BOOL "Build dobby shared library" FORCE)
|
||||
# set(DOBBY_DEBUG ON CACHE BOOL "Build dobby shared library" FORCE)
|
||||
add_subdirectory(dobby)
|
||||
add_subdirectory(minhook)
|
||||
target_link_libraries(${PROJECT_NAME} minhook)
|
||||
|
||||
# target_include_directories(${PROJECT_NAME} PRIVATE dobby/include)
|
||||
# target_link_directories(${PROJECT_NAME} PRIVATE dobby)
|
||||
# target_link_libraries(${PROJECT_NAME} dobby)
|
||||
|
||||
# set(DOBBY_GENERATE_SHARED OFF CACHE BOOL "Build dobby shared library" FORCE)
|
||||
# # set(DOBBY_DEBUG ON CACHE BOOL "Build dobby shared library" FORCE)
|
||||
# add_subdirectory(dobby)
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} dbghelp)
|
||||
endif()
|
||||
|
||||
if(NOT GEODE_DONT_BUILD_TEST_MODS)
|
||||
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
|
||||
add_subdirectory(test)
|
||||
# disable warnings about CCNode::setID
|
||||
if (MSVC)
|
||||
target_link_options(${PROJECT_NAME} PUBLIC /ignore:4217)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Build test mods if needed
|
||||
if(NOT GEODE_DONT_BUILD_TEST_MODS)
|
||||
add_subdirectory(test)
|
||||
endif()
|
||||
|
||||
# Build index hashing algorithm test program
|
||||
add_subdirectory(hash)
|
||||
|
|
11
loader/hash/CMakeLists.txt
Normal file
11
loader/hash/CMakeLists.txt
Normal file
|
@ -0,0 +1,11 @@
|
|||
cmake_minimum_required(VERSION 3.0 FATAL_ERROR)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED On)
|
||||
|
||||
project(GeodeChecksum VERSION 1.0)
|
||||
|
||||
add_executable(${PROJECT_NAME} hash.cpp)
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC filesystem)
|
||||
|
||||
message(STATUS "Building Checksum Exe")
|
11
loader/hash/hash.cpp
Normal file
11
loader/hash/hash.cpp
Normal file
|
@ -0,0 +1,11 @@
|
|||
#include <iostream>
|
||||
#include "hash.hpp"
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
if (argc < 2 || !ghc::filesystem::exists(argv[1])) {
|
||||
std::cout << "Usage: \"checksum <file>\"\n";
|
||||
return 1;
|
||||
}
|
||||
std::cout << calculateHash(argv[1]) << std::endl;
|
||||
return 0;
|
||||
}
|
27
loader/hash/hash.hpp
Normal file
27
loader/hash/hash.hpp
Normal file
|
@ -0,0 +1,27 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <ciso646>
|
||||
#include "picosha3.h"
|
||||
#include "picosha2.h"
|
||||
#include <vector>
|
||||
#include <fs/filesystem.hpp>
|
||||
|
||||
static std::string calculateSHA3_256(ghc::filesystem::path const& path) {
|
||||
std::vector<uint8_t> s(picosha3::bits_to_bytes(256));
|
||||
auto sha3_256 = picosha3::get_sha3_generator<256>();
|
||||
std::ifstream file(path, std::ios::binary);
|
||||
return sha3_256.get_hex_string(file);
|
||||
}
|
||||
|
||||
static std::string calculateSHA256(ghc::filesystem::path const& path) {
|
||||
std::vector<uint8_t> hash(picosha2::k_digest_size);
|
||||
std::ifstream file(path, std::ios::binary);
|
||||
picosha2::hash256(file, hash.begin(), hash.end());
|
||||
return picosha2::bytes_to_hex_string(hash.begin(), hash.end());
|
||||
}
|
||||
|
||||
static std::string calculateHash(ghc::filesystem::path const& path) {
|
||||
return calculateSHA3_256(path);
|
||||
}
|
377
loader/hash/picosha2.h
Normal file
377
loader/hash/picosha2.h
Normal file
|
@ -0,0 +1,377 @@
|
|||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (C) 2017 okdshin
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
#ifndef PICOSHA2_H
|
||||
#define PICOSHA2_H
|
||||
// picosha2:20140213
|
||||
|
||||
#ifndef PICOSHA2_BUFFER_SIZE_FOR_INPUT_ITERATOR
|
||||
#define PICOSHA2_BUFFER_SIZE_FOR_INPUT_ITERATOR \
|
||||
1048576 //=1024*1024: default is 1MB memory
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <iterator>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
namespace picosha2 {
|
||||
typedef unsigned long word_t;
|
||||
typedef unsigned char byte_t;
|
||||
|
||||
static const size_t k_digest_size = 32;
|
||||
|
||||
namespace detail {
|
||||
inline byte_t mask_8bit(byte_t x) { return x & 0xff; }
|
||||
|
||||
inline word_t mask_32bit(word_t x) { return x & 0xffffffff; }
|
||||
|
||||
const word_t add_constant[64] = {
|
||||
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
|
||||
0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
|
||||
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
|
||||
0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
||||
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
|
||||
0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
|
||||
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
|
||||
0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
||||
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
|
||||
0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
|
||||
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2};
|
||||
|
||||
const word_t initial_message_digest[8] = {0x6a09e667, 0xbb67ae85, 0x3c6ef372,
|
||||
0xa54ff53a, 0x510e527f, 0x9b05688c,
|
||||
0x1f83d9ab, 0x5be0cd19};
|
||||
|
||||
inline word_t ch(word_t x, word_t y, word_t z) { return (x & y) ^ ((~x) & z); }
|
||||
|
||||
inline word_t maj(word_t x, word_t y, word_t z) {
|
||||
return (x & y) ^ (x & z) ^ (y & z);
|
||||
}
|
||||
|
||||
inline word_t rotr(word_t x, std::size_t n) {
|
||||
assert(n < 32);
|
||||
return mask_32bit((x >> n) | (x << (32 - n)));
|
||||
}
|
||||
|
||||
inline word_t bsig0(word_t x) { return rotr(x, 2) ^ rotr(x, 13) ^ rotr(x, 22); }
|
||||
|
||||
inline word_t bsig1(word_t x) { return rotr(x, 6) ^ rotr(x, 11) ^ rotr(x, 25); }
|
||||
|
||||
inline word_t shr(word_t x, std::size_t n) {
|
||||
assert(n < 32);
|
||||
return x >> n;
|
||||
}
|
||||
|
||||
inline word_t ssig0(word_t x) { return rotr(x, 7) ^ rotr(x, 18) ^ shr(x, 3); }
|
||||
|
||||
inline word_t ssig1(word_t x) { return rotr(x, 17) ^ rotr(x, 19) ^ shr(x, 10); }
|
||||
|
||||
template <typename RaIter1, typename RaIter2>
|
||||
void hash256_block(RaIter1 message_digest, RaIter2 first, RaIter2 last) {
|
||||
assert(first + 64 == last);
|
||||
static_cast<void>(last); // for avoiding unused-variable warning
|
||||
word_t w[64];
|
||||
std::fill(w, w + 64, word_t(0));
|
||||
for (std::size_t i = 0; i < 16; ++i) {
|
||||
w[i] = (static_cast<word_t>(mask_8bit(*(first + i * 4))) << 24) |
|
||||
(static_cast<word_t>(mask_8bit(*(first + i * 4 + 1))) << 16) |
|
||||
(static_cast<word_t>(mask_8bit(*(first + i * 4 + 2))) << 8) |
|
||||
(static_cast<word_t>(mask_8bit(*(first + i * 4 + 3))));
|
||||
}
|
||||
for (std::size_t i = 16; i < 64; ++i) {
|
||||
w[i] = mask_32bit(ssig1(w[i - 2]) + w[i - 7] + ssig0(w[i - 15]) +
|
||||
w[i - 16]);
|
||||
}
|
||||
|
||||
word_t a = *message_digest;
|
||||
word_t b = *(message_digest + 1);
|
||||
word_t c = *(message_digest + 2);
|
||||
word_t d = *(message_digest + 3);
|
||||
word_t e = *(message_digest + 4);
|
||||
word_t f = *(message_digest + 5);
|
||||
word_t g = *(message_digest + 6);
|
||||
word_t h = *(message_digest + 7);
|
||||
|
||||
for (std::size_t i = 0; i < 64; ++i) {
|
||||
word_t temp1 = h + bsig1(e) + ch(e, f, g) + add_constant[i] + w[i];
|
||||
word_t temp2 = bsig0(a) + maj(a, b, c);
|
||||
h = g;
|
||||
g = f;
|
||||
f = e;
|
||||
e = mask_32bit(d + temp1);
|
||||
d = c;
|
||||
c = b;
|
||||
b = a;
|
||||
a = mask_32bit(temp1 + temp2);
|
||||
}
|
||||
*message_digest += a;
|
||||
*(message_digest + 1) += b;
|
||||
*(message_digest + 2) += c;
|
||||
*(message_digest + 3) += d;
|
||||
*(message_digest + 4) += e;
|
||||
*(message_digest + 5) += f;
|
||||
*(message_digest + 6) += g;
|
||||
*(message_digest + 7) += h;
|
||||
for (std::size_t i = 0; i < 8; ++i) {
|
||||
*(message_digest + i) = mask_32bit(*(message_digest + i));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename InIter>
|
||||
void output_hex(InIter first, InIter last, std::ostream& os) {
|
||||
os.setf(std::ios::hex, std::ios::basefield);
|
||||
while (first != last) {
|
||||
os.width(2);
|
||||
os.fill('0');
|
||||
os << static_cast<unsigned int>(*first);
|
||||
++first;
|
||||
}
|
||||
os.setf(std::ios::dec, std::ios::basefield);
|
||||
}
|
||||
|
||||
template <typename InIter>
|
||||
void bytes_to_hex_string(InIter first, InIter last, std::string& hex_str) {
|
||||
std::ostringstream oss;
|
||||
output_hex(first, last, oss);
|
||||
hex_str.assign(oss.str());
|
||||
}
|
||||
|
||||
template <typename InContainer>
|
||||
void bytes_to_hex_string(const InContainer& bytes, std::string& hex_str) {
|
||||
bytes_to_hex_string(bytes.begin(), bytes.end(), hex_str);
|
||||
}
|
||||
|
||||
template <typename InIter>
|
||||
std::string bytes_to_hex_string(InIter first, InIter last) {
|
||||
std::string hex_str;
|
||||
bytes_to_hex_string(first, last, hex_str);
|
||||
return hex_str;
|
||||
}
|
||||
|
||||
template <typename InContainer>
|
||||
std::string bytes_to_hex_string(const InContainer& bytes) {
|
||||
std::string hex_str;
|
||||
bytes_to_hex_string(bytes, hex_str);
|
||||
return hex_str;
|
||||
}
|
||||
|
||||
class hash256_one_by_one {
|
||||
public:
|
||||
hash256_one_by_one() { init(); }
|
||||
|
||||
void init() {
|
||||
buffer_.clear();
|
||||
std::fill(data_length_digits_, data_length_digits_ + 4, word_t(0));
|
||||
std::copy(detail::initial_message_digest,
|
||||
detail::initial_message_digest + 8, h_);
|
||||
}
|
||||
|
||||
template <typename RaIter>
|
||||
void process(RaIter first, RaIter last) {
|
||||
add_to_data_length(static_cast<word_t>(std::distance(first, last)));
|
||||
std::copy(first, last, std::back_inserter(buffer_));
|
||||
std::size_t i = 0;
|
||||
for (; i + 64 <= buffer_.size(); i += 64) {
|
||||
detail::hash256_block(h_, buffer_.begin() + i,
|
||||
buffer_.begin() + i + 64);
|
||||
}
|
||||
buffer_.erase(buffer_.begin(), buffer_.begin() + i);
|
||||
}
|
||||
|
||||
void finish() {
|
||||
byte_t temp[64];
|
||||
std::fill(temp, temp + 64, byte_t(0));
|
||||
std::size_t remains = buffer_.size();
|
||||
std::copy(buffer_.begin(), buffer_.end(), temp);
|
||||
temp[remains] = 0x80;
|
||||
|
||||
if (remains > 55) {
|
||||
std::fill(temp + remains + 1, temp + 64, byte_t(0));
|
||||
detail::hash256_block(h_, temp, temp + 64);
|
||||
std::fill(temp, temp + 64 - 4, byte_t(0));
|
||||
} else {
|
||||
std::fill(temp + remains + 1, temp + 64 - 4, byte_t(0));
|
||||
}
|
||||
|
||||
write_data_bit_length(&(temp[56]));
|
||||
detail::hash256_block(h_, temp, temp + 64);
|
||||
}
|
||||
|
||||
template <typename OutIter>
|
||||
void get_hash_bytes(OutIter first, OutIter last) const {
|
||||
for (const word_t* iter = h_; iter != h_ + 8; ++iter) {
|
||||
for (std::size_t i = 0; i < 4 && first != last; ++i) {
|
||||
*(first++) = detail::mask_8bit(
|
||||
static_cast<byte_t>((*iter >> (24 - 8 * i))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void add_to_data_length(word_t n) {
|
||||
word_t carry = 0;
|
||||
data_length_digits_[0] += n;
|
||||
for (std::size_t i = 0; i < 4; ++i) {
|
||||
data_length_digits_[i] += carry;
|
||||
if (data_length_digits_[i] >= 65536u) {
|
||||
carry = data_length_digits_[i] >> 16;
|
||||
data_length_digits_[i] &= 65535u;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
void write_data_bit_length(byte_t* begin) {
|
||||
word_t data_bit_length_digits[4];
|
||||
std::copy(data_length_digits_, data_length_digits_ + 4,
|
||||
data_bit_length_digits);
|
||||
|
||||
// convert byte length to bit length (multiply 8 or shift 3 times left)
|
||||
word_t carry = 0;
|
||||
for (std::size_t i = 0; i < 4; ++i) {
|
||||
word_t before_val = data_bit_length_digits[i];
|
||||
data_bit_length_digits[i] <<= 3;
|
||||
data_bit_length_digits[i] |= carry;
|
||||
data_bit_length_digits[i] &= 65535u;
|
||||
carry = (before_val >> (16 - 3)) & 65535u;
|
||||
}
|
||||
|
||||
// write data_bit_length
|
||||
for (int i = 3; i >= 0; --i) {
|
||||
(*begin++) = static_cast<byte_t>(data_bit_length_digits[i] >> 8);
|
||||
(*begin++) = static_cast<byte_t>(data_bit_length_digits[i]);
|
||||
}
|
||||
}
|
||||
std::vector<byte_t> buffer_;
|
||||
word_t data_length_digits_[4]; // as 64bit integer (16bit x 4 integer)
|
||||
word_t h_[8];
|
||||
};
|
||||
|
||||
inline void get_hash_hex_string(const hash256_one_by_one& hasher,
|
||||
std::string& hex_str) {
|
||||
byte_t hash[k_digest_size];
|
||||
hasher.get_hash_bytes(hash, hash + k_digest_size);
|
||||
return bytes_to_hex_string(hash, hash + k_digest_size, hex_str);
|
||||
}
|
||||
|
||||
inline std::string get_hash_hex_string(const hash256_one_by_one& hasher) {
|
||||
std::string hex_str;
|
||||
get_hash_hex_string(hasher, hex_str);
|
||||
return hex_str;
|
||||
}
|
||||
|
||||
namespace impl {
|
||||
template <typename RaIter, typename OutIter>
|
||||
void hash256_impl(RaIter first, RaIter last, OutIter first2, OutIter last2, int,
|
||||
std::random_access_iterator_tag) {
|
||||
hash256_one_by_one hasher;
|
||||
// hasher.init();
|
||||
hasher.process(first, last);
|
||||
hasher.finish();
|
||||
hasher.get_hash_bytes(first2, last2);
|
||||
}
|
||||
|
||||
template <typename InputIter, typename OutIter>
|
||||
void hash256_impl(InputIter first, InputIter last, OutIter first2,
|
||||
OutIter last2, int buffer_size, std::input_iterator_tag) {
|
||||
std::vector<byte_t> buffer(buffer_size);
|
||||
hash256_one_by_one hasher;
|
||||
// hasher.init();
|
||||
while (first != last) {
|
||||
int size = buffer_size;
|
||||
for (int i = 0; i != buffer_size; ++i, ++first) {
|
||||
if (first == last) {
|
||||
size = i;
|
||||
break;
|
||||
}
|
||||
buffer[i] = *first;
|
||||
}
|
||||
hasher.process(buffer.begin(), buffer.begin() + size);
|
||||
}
|
||||
hasher.finish();
|
||||
hasher.get_hash_bytes(first2, last2);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename InIter, typename OutIter>
|
||||
void hash256(InIter first, InIter last, OutIter first2, OutIter last2,
|
||||
int buffer_size = PICOSHA2_BUFFER_SIZE_FOR_INPUT_ITERATOR) {
|
||||
picosha2::impl::hash256_impl(
|
||||
first, last, first2, last2, buffer_size,
|
||||
typename std::iterator_traits<InIter>::iterator_category());
|
||||
}
|
||||
|
||||
template <typename InIter, typename OutContainer>
|
||||
void hash256(InIter first, InIter last, OutContainer& dst) {
|
||||
hash256(first, last, dst.begin(), dst.end());
|
||||
}
|
||||
|
||||
template <typename InContainer, typename OutIter>
|
||||
void hash256(const InContainer& src, OutIter first, OutIter last) {
|
||||
hash256(src.begin(), src.end(), first, last);
|
||||
}
|
||||
|
||||
template <typename InContainer, typename OutContainer>
|
||||
void hash256(const InContainer& src, OutContainer& dst) {
|
||||
hash256(src.begin(), src.end(), dst.begin(), dst.end());
|
||||
}
|
||||
|
||||
template <typename InIter>
|
||||
void hash256_hex_string(InIter first, InIter last, std::string& hex_str) {
|
||||
byte_t hashed[k_digest_size];
|
||||
hash256(first, last, hashed, hashed + k_digest_size);
|
||||
std::ostringstream oss;
|
||||
output_hex(hashed, hashed + k_digest_size, oss);
|
||||
hex_str.assign(oss.str());
|
||||
}
|
||||
|
||||
template <typename InIter>
|
||||
std::string hash256_hex_string(InIter first, InIter last) {
|
||||
std::string hex_str;
|
||||
hash256_hex_string(first, last, hex_str);
|
||||
return hex_str;
|
||||
}
|
||||
|
||||
inline void hash256_hex_string(const std::string& src, std::string& hex_str) {
|
||||
hash256_hex_string(src.begin(), src.end(), hex_str);
|
||||
}
|
||||
|
||||
template <typename InContainer>
|
||||
void hash256_hex_string(const InContainer& src, std::string& hex_str) {
|
||||
hash256_hex_string(src.begin(), src.end(), hex_str);
|
||||
}
|
||||
|
||||
template <typename InContainer>
|
||||
std::string hash256_hex_string(const InContainer& src) {
|
||||
return hash256_hex_string(src.begin(), src.end());
|
||||
}
|
||||
template<typename OutIter>void hash256(std::ifstream& f, OutIter first, OutIter last){
|
||||
hash256(std::istreambuf_iterator<char>(f), std::istreambuf_iterator<char>(), first,last);
|
||||
|
||||
}
|
||||
}// namespace picosha2
|
||||
#endif // PICOSHA2_H
|
361
loader/hash/picosha3.h
Normal file
361
loader/hash/picosha3.h
Normal file
|
@ -0,0 +1,361 @@
|
|||
#ifndef PICOSHA3_H
|
||||
#define PICOSHA3_H
|
||||
|
||||
#include <array>
|
||||
#include <cassert>
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
|
||||
namespace picosha3 {
|
||||
constexpr size_t bits_to_bytes(size_t bits) { return bits / 8; };
|
||||
constexpr static size_t b_bytes = bits_to_bytes(1600);
|
||||
constexpr static uint64_t RC[24] = {
|
||||
0x0000000000000001ull, 0x0000000000008082ull, 0x800000000000808Aull,
|
||||
0x8000000080008000ull, 0x000000000000808Bull, 0x0000000080000001ull,
|
||||
0x8000000080008081ull, 0x8000000000008009ull, 0x000000000000008Aull,
|
||||
0x0000000000000088ull, 0x0000000080008009ull, 0x000000008000000Aull,
|
||||
0x000000008000808Bull, 0x800000000000008Bull, 0x8000000000008089ull,
|
||||
0x8000000000008003ull, 0x8000000000008002ull, 0x8000000000000080ull,
|
||||
0x000000000000800Aull, 0x800000008000000Aull, 0x8000000080008081ull,
|
||||
0x8000000000008080ull, 0x0000000080000001ull, 0x8000000080008008ull};
|
||||
|
||||
using byte_t = uint8_t;
|
||||
using state_t = std::array<std::array<uint64_t, 5>, 5>;
|
||||
|
||||
inline void theta(state_t& A) {
|
||||
uint64_t C[5] = {0, 0, 0, 0, 0};
|
||||
for(size_t x = 0; x < 5; ++x) {
|
||||
C[x] = A[x][0] ^ A[x][1] ^ A[x][2] ^ A[x][3] ^ A[x][4];
|
||||
};
|
||||
uint64_t D[5] = {0, 0, 0, 0, 0};
|
||||
D[0] = C[4] ^ (C[1] << 1 | C[1] >> (64 - 1));
|
||||
D[1] = C[0] ^ (C[2] << 1 | C[2] >> (64 - 1));
|
||||
D[2] = C[1] ^ (C[3] << 1 | C[3] >> (64 - 1));
|
||||
D[3] = C[2] ^ (C[4] << 1 | C[4] >> (64 - 1));
|
||||
D[4] = C[3] ^ (C[0] << 1 | C[0] >> (64 - 1));
|
||||
for(size_t x = 0; x < 5; ++x) {
|
||||
for(size_t y = 0; y < 5; ++y) {
|
||||
A[x][y] ^= D[x];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
inline void rho(state_t& A) {
|
||||
size_t x{1};
|
||||
size_t y{0};
|
||||
for(size_t t = 0; t < 24; ++t) {
|
||||
size_t offset = ((t + 1) * (t + 2) / 2) % 64;
|
||||
A[x][y] = (A[x][y] << offset) | (A[x][y] >> (64 - offset));
|
||||
size_t tmp{y};
|
||||
y = (2 * x + 3 * y) % 5;
|
||||
x = tmp;
|
||||
};
|
||||
};
|
||||
|
||||
inline void pi(state_t& A) {
|
||||
state_t tmp{A};
|
||||
for(size_t x = 0; x < 5; ++x) {
|
||||
for(size_t y = 0; y < 5; ++y) {
|
||||
A[x][y] = tmp[(x + 3 * y) % 5][x];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
inline void chi(state_t& A) {
|
||||
state_t tmp{A};
|
||||
for(size_t x = 0; x < 5; ++x) {
|
||||
for(size_t y = 0; y < 5; ++y) {
|
||||
A[x][y] =
|
||||
tmp[x][y] ^ (~(tmp[(x + 1) % 5][y]) & tmp[(x + 2) % 5][y]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
inline void iota(state_t& A, size_t round_index) {
|
||||
A[0][0] ^= RC[round_index];
|
||||
};
|
||||
|
||||
inline void keccak_p(state_t& A) {
|
||||
for(size_t round_index = 0; round_index < 24; ++round_index) {
|
||||
theta(A);
|
||||
rho(A);
|
||||
pi(A);
|
||||
chi(A);
|
||||
iota(A, round_index);
|
||||
}
|
||||
};
|
||||
|
||||
namespace {
|
||||
inline void next(size_t& x, size_t& y, size_t& i) {
|
||||
if(++i != 8) {
|
||||
return;
|
||||
}
|
||||
i = 0;
|
||||
if(++x != 5) {
|
||||
return;
|
||||
}
|
||||
x = 0;
|
||||
if(++y != 5) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
template <typename InIter>
|
||||
void absorb(InIter first, InIter last, state_t& A) {
|
||||
size_t x = 0;
|
||||
size_t y = 0;
|
||||
size_t i = 0;
|
||||
for(; first != last && y < 5; ++first) {
|
||||
auto tmp = static_cast<uint64_t>(*first);
|
||||
A[x][y] ^= (tmp << (i * 8));
|
||||
next(x, y, i);
|
||||
};
|
||||
}
|
||||
|
||||
template <typename InContainer>
|
||||
void absorb(const InContainer& src, state_t& A) {
|
||||
absorb(src.cbegin(), src.cend(), A);
|
||||
};
|
||||
|
||||
template <typename OutIter>
|
||||
OutIter squeeze(const state_t& A, OutIter first, OutIter last,
|
||||
size_t rate_bytes) {
|
||||
size_t x = 0;
|
||||
size_t y = 0;
|
||||
size_t i = 0;
|
||||
for(size_t read_bytes = 0;
|
||||
first != last && y < 5 && read_bytes < rate_bytes;
|
||||
++read_bytes, ++first) {
|
||||
auto tmp = static_cast<uint64_t>(A[x][y]);
|
||||
auto p = reinterpret_cast<byte_t*>(&tmp);
|
||||
*first = *(p + i);
|
||||
next(x, y, i);
|
||||
}
|
||||
return first;
|
||||
};
|
||||
|
||||
template <typename OutContainer>
|
||||
typename OutContainer::iterator
|
||||
squeeze(const state_t& A, OutContainer& dest, size_t rate_bytes) {
|
||||
return squeeze(A, dest.begin(), dest.end(), rate_bytes);
|
||||
}
|
||||
|
||||
enum class PaddingType {
|
||||
SHA,
|
||||
SHAKE,
|
||||
};
|
||||
|
||||
template <typename InIter>
|
||||
std::string bytes_to_hex_string(InIter first, InIter last) {
|
||||
std::stringstream ss;
|
||||
ss << std::hex;
|
||||
for(; first != last; ++first) {
|
||||
ss << std::setw(2) << std::setfill('0')
|
||||
<< static_cast<uint64_t>(*first);
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
template <typename InContainer>
|
||||
std::string bytes_to_hex_string(const InContainer& src) {
|
||||
return bytes_to_hex_string(src.cbegin(), src.cend());
|
||||
}
|
||||
|
||||
template <size_t rate_bytes, size_t d_bytes, PaddingType padding_type>
|
||||
class HashGenerator {
|
||||
public:
|
||||
HashGenerator()
|
||||
: buffer_{}, buffer_pos_{buffer_.begin()}, A_{}, hash_{},
|
||||
is_finished_{false} {}
|
||||
|
||||
void clear() {
|
||||
clear_state();
|
||||
clear_buffer();
|
||||
is_finished_ = false;
|
||||
}
|
||||
|
||||
template <typename InIter>
|
||||
void process(InIter first, InIter last) {
|
||||
static_assert(
|
||||
sizeof(typename std::iterator_traits<InIter>::value_type) == 1,
|
||||
"The size of input iterator value_type must be one byte.");
|
||||
|
||||
for(; first != last; ++first) {
|
||||
*buffer_pos_ = *first;
|
||||
if(++buffer_pos_ == buffer_.end()) {
|
||||
absorb(buffer_, A_);
|
||||
keccak_p(A_);
|
||||
clear_buffer();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void finish() {
|
||||
add_padding();
|
||||
absorb(buffer_, A_);
|
||||
keccak_p(A_);
|
||||
squeeze_();
|
||||
is_finished_ = true;
|
||||
};
|
||||
|
||||
template <typename OutIter>
|
||||
void get_hash_bytes(OutIter first, OutIter last) {
|
||||
if(!is_finished_) {
|
||||
throw std::runtime_error("Not finished!");
|
||||
}
|
||||
std::copy(hash_.cbegin(), hash_.cend(), first);
|
||||
};
|
||||
|
||||
template <typename OutCotainer>
|
||||
void get_hash_bytes(OutCotainer& dest) {
|
||||
get_hash_bytes(dest.begin(), dest.end());
|
||||
};
|
||||
|
||||
template <typename InIter, typename OutIter>
|
||||
void operator()(InIter in_first, InIter in_last, OutIter out_first,
|
||||
OutIter out_last) {
|
||||
static_assert(
|
||||
sizeof(typename std::iterator_traits<InIter>::value_type) == 1,
|
||||
"The size of input iterator value_type must be one byte.");
|
||||
static_assert(
|
||||
sizeof(typename std::iterator_traits<OutIter>::value_type) == 1,
|
||||
"The size of output iterator value_type must be one byte.");
|
||||
process(in_first, in_last);
|
||||
finish();
|
||||
std::copy(hash_.cbegin(), hash_.cend(), out_first);
|
||||
clear();
|
||||
};
|
||||
|
||||
template <typename InIter, typename OutCotainer>
|
||||
void operator()(InIter in_first, InIter in_last, OutCotainer& dest) {
|
||||
operator()(in_first, in_last, dest.begin(), dest.end());
|
||||
};
|
||||
|
||||
template <typename InContainer, typename OutIter>
|
||||
void operator()(const InContainer& src, OutIter out_first,
|
||||
OutIter out_last) {
|
||||
operator()(src.cbegin(), src.cend(), out_first, out_last);
|
||||
};
|
||||
|
||||
template <typename InContainer, typename OutContainer>
|
||||
void operator()(const InContainer& src, OutContainer& dest) {
|
||||
operator()(src.cbegin(), src.cend(), dest.begin(), dest.end());
|
||||
};
|
||||
|
||||
template <typename OutIter>
|
||||
void operator()(std::ifstream& ifs, OutIter out_first,
|
||||
OutIter out_last) {
|
||||
auto in_first = std::istreambuf_iterator<char>(ifs);
|
||||
auto in_last = std::istreambuf_iterator<char>();
|
||||
operator()(in_first, in_last, out_first, out_last);
|
||||
};
|
||||
|
||||
template <typename OutCotainer>
|
||||
void operator()(std::ifstream& ifs, OutCotainer& dest) {
|
||||
operator()(ifs, dest.begin(), dest.end());
|
||||
};
|
||||
|
||||
std::string get_hex_string() {
|
||||
if(!is_finished_) {
|
||||
throw std::runtime_error("Not finished!");
|
||||
}
|
||||
return bytes_to_hex_string(hash_);
|
||||
};
|
||||
|
||||
template <typename InIter>
|
||||
std::string get_hex_string(InIter in_first, InIter in_last) {
|
||||
process(in_first, in_last);
|
||||
finish();
|
||||
auto hash = get_hex_string();
|
||||
clear();
|
||||
return hash;
|
||||
};
|
||||
|
||||
template <typename InContainer>
|
||||
std::string get_hex_string(const InContainer& src) {
|
||||
return get_hex_string(src.cbegin(), src.cend());
|
||||
};
|
||||
|
||||
std::string get_hex_string(std::ifstream& ifs) {
|
||||
auto in_first = std::istreambuf_iterator<char>(ifs);
|
||||
auto in_last = std::istreambuf_iterator<char>();
|
||||
return get_hex_string(in_first, in_last);
|
||||
};
|
||||
|
||||
private:
|
||||
void clear_buffer() {
|
||||
buffer_.fill(0);
|
||||
buffer_pos_ = buffer_.begin();
|
||||
};
|
||||
|
||||
void clear_state() {
|
||||
for(auto& row : A_) {
|
||||
row.fill(0);
|
||||
}
|
||||
};
|
||||
|
||||
void add_padding() {
|
||||
const auto q =
|
||||
buffer_.size() - std::distance(buffer_pos_, buffer_.begin());
|
||||
|
||||
if(padding_type == PaddingType::SHA) {
|
||||
if(q == 1) {
|
||||
*buffer_pos_ = 0x86;
|
||||
} else {
|
||||
*buffer_pos_ = 0x06;
|
||||
buffer_.back() = 0x80;
|
||||
}
|
||||
} else if(padding_type == PaddingType::SHAKE) {
|
||||
if(q == 1) {
|
||||
*buffer_pos_ = 0x9F;
|
||||
} else {
|
||||
*buffer_pos_ = 0x1F;
|
||||
buffer_.back() = 0x80;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void squeeze_() {
|
||||
auto first = hash_.begin();
|
||||
auto last = hash_.end();
|
||||
first = squeeze(A_, first, last, rate_bytes);
|
||||
while(first != last) {
|
||||
keccak_p(A_);
|
||||
first = squeeze(A_, first, last, rate_bytes);
|
||||
}
|
||||
};
|
||||
|
||||
std::array<byte_t, rate_bytes> buffer_;
|
||||
typename decltype(buffer_)::iterator buffer_pos_;
|
||||
state_t A_;
|
||||
std::array<byte_t, d_bytes> hash_;
|
||||
bool is_finished_;
|
||||
};
|
||||
|
||||
template <size_t d_bits>
|
||||
auto get_sha3_generator() {
|
||||
static_assert(
|
||||
d_bits == 224 or d_bits == 256 or d_bits == 384 or d_bits == 512,
|
||||
"SHA3 only accepts digest message length 224, 256 384 or 512 bits.");
|
||||
constexpr auto d_bytes = bits_to_bytes(d_bits);
|
||||
constexpr auto capacity_bytes = d_bytes * 2;
|
||||
constexpr auto rate_bytes = b_bytes - capacity_bytes;
|
||||
return HashGenerator<rate_bytes, d_bytes, PaddingType::SHA>{};
|
||||
}
|
||||
|
||||
template <size_t strength_bits, size_t d_bits>
|
||||
auto get_shake_generator() {
|
||||
static_assert(strength_bits == 128 or strength_bits == 256,
|
||||
"SHAKE only accepts strength 128 or 256 bits.");
|
||||
constexpr auto strength_bytes = bits_to_bytes(strength_bits);
|
||||
constexpr auto capacity_bytes = strength_bytes * 2;
|
||||
constexpr auto rate_bytes = b_bytes - capacity_bytes;
|
||||
constexpr auto d_bytes = bits_to_bytes(d_bits);
|
||||
return HashGenerator<rate_bytes, d_bytes, PaddingType::SHAKE>{};
|
||||
}
|
||||
|
||||
} // namespace picosha3
|
||||
|
||||
#endif
|
373
loader/hash/picosha3_LICENSE
Normal file
373
loader/hash/picosha3_LICENSE
Normal file
|
@ -0,0 +1,373 @@
|
|||
Mozilla Public License Version 2.0
|
||||
==================================
|
||||
|
||||
1. Definitions
|
||||
--------------
|
||||
|
||||
1.1. "Contributor"
|
||||
means each individual or legal entity that creates, contributes to
|
||||
the creation of, or owns Covered Software.
|
||||
|
||||
1.2. "Contributor Version"
|
||||
means the combination of the Contributions of others (if any) used
|
||||
by a Contributor and that particular Contributor's Contribution.
|
||||
|
||||
1.3. "Contribution"
|
||||
means Covered Software of a particular Contributor.
|
||||
|
||||
1.4. "Covered Software"
|
||||
means Source Code Form to which the initial Contributor has attached
|
||||
the notice in Exhibit A, the Executable Form of such Source Code
|
||||
Form, and Modifications of such Source Code Form, in each case
|
||||
including portions thereof.
|
||||
|
||||
1.5. "Incompatible With Secondary Licenses"
|
||||
means
|
||||
|
||||
(a) that the initial Contributor has attached the notice described
|
||||
in Exhibit B to the Covered Software; or
|
||||
|
||||
(b) that the Covered Software was made available under the terms of
|
||||
version 1.1 or earlier of the License, but not also under the
|
||||
terms of a Secondary License.
|
||||
|
||||
1.6. "Executable Form"
|
||||
means any form of the work other than Source Code Form.
|
||||
|
||||
1.7. "Larger Work"
|
||||
means a work that combines Covered Software with other material, in
|
||||
a separate file or files, that is not Covered Software.
|
||||
|
||||
1.8. "License"
|
||||
means this document.
|
||||
|
||||
1.9. "Licensable"
|
||||
means having the right to grant, to the maximum extent possible,
|
||||
whether at the time of the initial grant or subsequently, any and
|
||||
all of the rights conveyed by this License.
|
||||
|
||||
1.10. "Modifications"
|
||||
means any of the following:
|
||||
|
||||
(a) any file in Source Code Form that results from an addition to,
|
||||
deletion from, or modification of the contents of Covered
|
||||
Software; or
|
||||
|
||||
(b) any new file in Source Code Form that contains any Covered
|
||||
Software.
|
||||
|
||||
1.11. "Patent Claims" of a Contributor
|
||||
means any patent claim(s), including without limitation, method,
|
||||
process, and apparatus claims, in any patent Licensable by such
|
||||
Contributor that would be infringed, but for the grant of the
|
||||
License, by the making, using, selling, offering for sale, having
|
||||
made, import, or transfer of either its Contributions or its
|
||||
Contributor Version.
|
||||
|
||||
1.12. "Secondary License"
|
||||
means either the GNU General Public License, Version 2.0, the GNU
|
||||
Lesser General Public License, Version 2.1, the GNU Affero General
|
||||
Public License, Version 3.0, or any later versions of those
|
||||
licenses.
|
||||
|
||||
1.13. "Source Code Form"
|
||||
means the form of the work preferred for making modifications.
|
||||
|
||||
1.14. "You" (or "Your")
|
||||
means an individual or a legal entity exercising rights under this
|
||||
License. For legal entities, "You" includes any entity that
|
||||
controls, is controlled by, or is under common control with You. For
|
||||
purposes of this definition, "control" means (a) the power, direct
|
||||
or indirect, to cause the direction or management of such entity,
|
||||
whether by contract or otherwise, or (b) ownership of more than
|
||||
fifty percent (50%) of the outstanding shares or beneficial
|
||||
ownership of such entity.
|
||||
|
||||
2. License Grants and Conditions
|
||||
--------------------------------
|
||||
|
||||
2.1. Grants
|
||||
|
||||
Each Contributor hereby grants You a world-wide, royalty-free,
|
||||
non-exclusive license:
|
||||
|
||||
(a) under intellectual property rights (other than patent or trademark)
|
||||
Licensable by such Contributor to use, reproduce, make available,
|
||||
modify, display, perform, distribute, and otherwise exploit its
|
||||
Contributions, either on an unmodified basis, with Modifications, or
|
||||
as part of a Larger Work; and
|
||||
|
||||
(b) under Patent Claims of such Contributor to make, use, sell, offer
|
||||
for sale, have made, import, and otherwise transfer either its
|
||||
Contributions or its Contributor Version.
|
||||
|
||||
2.2. Effective Date
|
||||
|
||||
The licenses granted in Section 2.1 with respect to any Contribution
|
||||
become effective for each Contribution on the date the Contributor first
|
||||
distributes such Contribution.
|
||||
|
||||
2.3. Limitations on Grant Scope
|
||||
|
||||
The licenses granted in this Section 2 are the only rights granted under
|
||||
this License. No additional rights or licenses will be implied from the
|
||||
distribution or licensing of Covered Software under this License.
|
||||
Notwithstanding Section 2.1(b) above, no patent license is granted by a
|
||||
Contributor:
|
||||
|
||||
(a) for any code that a Contributor has removed from Covered Software;
|
||||
or
|
||||
|
||||
(b) for infringements caused by: (i) Your and any other third party's
|
||||
modifications of Covered Software, or (ii) the combination of its
|
||||
Contributions with other software (except as part of its Contributor
|
||||
Version); or
|
||||
|
||||
(c) under Patent Claims infringed by Covered Software in the absence of
|
||||
its Contributions.
|
||||
|
||||
This License does not grant any rights in the trademarks, service marks,
|
||||
or logos of any Contributor (except as may be necessary to comply with
|
||||
the notice requirements in Section 3.4).
|
||||
|
||||
2.4. Subsequent Licenses
|
||||
|
||||
No Contributor makes additional grants as a result of Your choice to
|
||||
distribute the Covered Software under a subsequent version of this
|
||||
License (see Section 10.2) or under the terms of a Secondary License (if
|
||||
permitted under the terms of Section 3.3).
|
||||
|
||||
2.5. Representation
|
||||
|
||||
Each Contributor represents that the Contributor believes its
|
||||
Contributions are its original creation(s) or it has sufficient rights
|
||||
to grant the rights to its Contributions conveyed by this License.
|
||||
|
||||
2.6. Fair Use
|
||||
|
||||
This License is not intended to limit any rights You have under
|
||||
applicable copyright doctrines of fair use, fair dealing, or other
|
||||
equivalents.
|
||||
|
||||
2.7. Conditions
|
||||
|
||||
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
|
||||
in Section 2.1.
|
||||
|
||||
3. Responsibilities
|
||||
-------------------
|
||||
|
||||
3.1. Distribution of Source Form
|
||||
|
||||
All distribution of Covered Software in Source Code Form, including any
|
||||
Modifications that You create or to which You contribute, must be under
|
||||
the terms of this License. You must inform recipients that the Source
|
||||
Code Form of the Covered Software is governed by the terms of this
|
||||
License, and how they can obtain a copy of this License. You may not
|
||||
attempt to alter or restrict the recipients' rights in the Source Code
|
||||
Form.
|
||||
|
||||
3.2. Distribution of Executable Form
|
||||
|
||||
If You distribute Covered Software in Executable Form then:
|
||||
|
||||
(a) such Covered Software must also be made available in Source Code
|
||||
Form, as described in Section 3.1, and You must inform recipients of
|
||||
the Executable Form how they can obtain a copy of such Source Code
|
||||
Form by reasonable means in a timely manner, at a charge no more
|
||||
than the cost of distribution to the recipient; and
|
||||
|
||||
(b) You may distribute such Executable Form under the terms of this
|
||||
License, or sublicense it under different terms, provided that the
|
||||
license for the Executable Form does not attempt to limit or alter
|
||||
the recipients' rights in the Source Code Form under this License.
|
||||
|
||||
3.3. Distribution of a Larger Work
|
||||
|
||||
You may create and distribute a Larger Work under terms of Your choice,
|
||||
provided that You also comply with the requirements of this License for
|
||||
the Covered Software. If the Larger Work is a combination of Covered
|
||||
Software with a work governed by one or more Secondary Licenses, and the
|
||||
Covered Software is not Incompatible With Secondary Licenses, this
|
||||
License permits You to additionally distribute such Covered Software
|
||||
under the terms of such Secondary License(s), so that the recipient of
|
||||
the Larger Work may, at their option, further distribute the Covered
|
||||
Software under the terms of either this License or such Secondary
|
||||
License(s).
|
||||
|
||||
3.4. Notices
|
||||
|
||||
You may not remove or alter the substance of any license notices
|
||||
(including copyright notices, patent notices, disclaimers of warranty,
|
||||
or limitations of liability) contained within the Source Code Form of
|
||||
the Covered Software, except that You may alter any license notices to
|
||||
the extent required to remedy known factual inaccuracies.
|
||||
|
||||
3.5. Application of Additional Terms
|
||||
|
||||
You may choose to offer, and to charge a fee for, warranty, support,
|
||||
indemnity or liability obligations to one or more recipients of Covered
|
||||
Software. However, You may do so only on Your own behalf, and not on
|
||||
behalf of any Contributor. You must make it absolutely clear that any
|
||||
such warranty, support, indemnity, or liability obligation is offered by
|
||||
You alone, and You hereby agree to indemnify every Contributor for any
|
||||
liability incurred by such Contributor as a result of warranty, support,
|
||||
indemnity or liability terms You offer. You may include additional
|
||||
disclaimers of warranty and limitations of liability specific to any
|
||||
jurisdiction.
|
||||
|
||||
4. Inability to Comply Due to Statute or Regulation
|
||||
---------------------------------------------------
|
||||
|
||||
If it is impossible for You to comply with any of the terms of this
|
||||
License with respect to some or all of the Covered Software due to
|
||||
statute, judicial order, or regulation then You must: (a) comply with
|
||||
the terms of this License to the maximum extent possible; and (b)
|
||||
describe the limitations and the code they affect. Such description must
|
||||
be placed in a text file included with all distributions of the Covered
|
||||
Software under this License. Except to the extent prohibited by statute
|
||||
or regulation, such description must be sufficiently detailed for a
|
||||
recipient of ordinary skill to be able to understand it.
|
||||
|
||||
5. Termination
|
||||
--------------
|
||||
|
||||
5.1. The rights granted under this License will terminate automatically
|
||||
if You fail to comply with any of its terms. However, if You become
|
||||
compliant, then the rights granted under this License from a particular
|
||||
Contributor are reinstated (a) provisionally, unless and until such
|
||||
Contributor explicitly and finally terminates Your grants, and (b) on an
|
||||
ongoing basis, if such Contributor fails to notify You of the
|
||||
non-compliance by some reasonable means prior to 60 days after You have
|
||||
come back into compliance. Moreover, Your grants from a particular
|
||||
Contributor are reinstated on an ongoing basis if such Contributor
|
||||
notifies You of the non-compliance by some reasonable means, this is the
|
||||
first time You have received notice of non-compliance with this License
|
||||
from such Contributor, and You become compliant prior to 30 days after
|
||||
Your receipt of the notice.
|
||||
|
||||
5.2. If You initiate litigation against any entity by asserting a patent
|
||||
infringement claim (excluding declaratory judgment actions,
|
||||
counter-claims, and cross-claims) alleging that a Contributor Version
|
||||
directly or indirectly infringes any patent, then the rights granted to
|
||||
You by any and all Contributors for the Covered Software under Section
|
||||
2.1 of this License shall terminate.
|
||||
|
||||
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
|
||||
end user license agreements (excluding distributors and resellers) which
|
||||
have been validly granted by You or Your distributors under this License
|
||||
prior to termination shall survive termination.
|
||||
|
||||
************************************************************************
|
||||
* *
|
||||
* 6. Disclaimer of Warranty *
|
||||
* ------------------------- *
|
||||
* *
|
||||
* Covered Software is provided under this License on an "as is" *
|
||||
* basis, without warranty of any kind, either expressed, implied, or *
|
||||
* statutory, including, without limitation, warranties that the *
|
||||
* Covered Software is free of defects, merchantable, fit for a *
|
||||
* particular purpose or non-infringing. The entire risk as to the *
|
||||
* quality and performance of the Covered Software is with You. *
|
||||
* Should any Covered Software prove defective in any respect, You *
|
||||
* (not any Contributor) assume the cost of any necessary servicing, *
|
||||
* repair, or correction. This disclaimer of warranty constitutes an *
|
||||
* essential part of this License. No use of any Covered Software is *
|
||||
* authorized under this License except under this disclaimer. *
|
||||
* *
|
||||
************************************************************************
|
||||
|
||||
************************************************************************
|
||||
* *
|
||||
* 7. Limitation of Liability *
|
||||
* -------------------------- *
|
||||
* *
|
||||
* Under no circumstances and under no legal theory, whether tort *
|
||||
* (including negligence), contract, or otherwise, shall any *
|
||||
* Contributor, or anyone who distributes Covered Software as *
|
||||
* permitted above, be liable to You for any direct, indirect, *
|
||||
* special, incidental, or consequential damages of any character *
|
||||
* including, without limitation, damages for lost profits, loss of *
|
||||
* goodwill, work stoppage, computer failure or malfunction, or any *
|
||||
* and all other commercial damages or losses, even if such party *
|
||||
* shall have been informed of the possibility of such damages. This *
|
||||
* limitation of liability shall not apply to liability for death or *
|
||||
* personal injury resulting from such party's negligence to the *
|
||||
* extent applicable law prohibits such limitation. Some *
|
||||
* jurisdictions do not allow the exclusion or limitation of *
|
||||
* incidental or consequential damages, so this exclusion and *
|
||||
* limitation may not apply to You. *
|
||||
* *
|
||||
************************************************************************
|
||||
|
||||
8. Litigation
|
||||
-------------
|
||||
|
||||
Any litigation relating to this License may be brought only in the
|
||||
courts of a jurisdiction where the defendant maintains its principal
|
||||
place of business and such litigation shall be governed by laws of that
|
||||
jurisdiction, without reference to its conflict-of-law provisions.
|
||||
Nothing in this Section shall prevent a party's ability to bring
|
||||
cross-claims or counter-claims.
|
||||
|
||||
9. Miscellaneous
|
||||
----------------
|
||||
|
||||
This License represents the complete agreement concerning the subject
|
||||
matter hereof. If any provision of this License is held to be
|
||||
unenforceable, such provision shall be reformed only to the extent
|
||||
necessary to make it enforceable. Any law or regulation which provides
|
||||
that the language of a contract shall be construed against the drafter
|
||||
shall not be used to construe this License against a Contributor.
|
||||
|
||||
10. Versions of the License
|
||||
---------------------------
|
||||
|
||||
10.1. New Versions
|
||||
|
||||
Mozilla Foundation is the license steward. Except as provided in Section
|
||||
10.3, no one other than the license steward has the right to modify or
|
||||
publish new versions of this License. Each version will be given a
|
||||
distinguishing version number.
|
||||
|
||||
10.2. Effect of New Versions
|
||||
|
||||
You may distribute the Covered Software under the terms of the version
|
||||
of the License under which You originally received the Covered Software,
|
||||
or under the terms of any subsequent version published by the license
|
||||
steward.
|
||||
|
||||
10.3. Modified Versions
|
||||
|
||||
If you create software not governed by this License, and you want to
|
||||
create a new license for such software, you may create and use a
|
||||
modified version of this License if you rename the license and remove
|
||||
any references to the name of the license steward (except to note that
|
||||
such modified license differs from this License).
|
||||
|
||||
10.4. Distributing Source Code Form that is Incompatible With Secondary
|
||||
Licenses
|
||||
|
||||
If You choose to distribute Source Code Form that is Incompatible With
|
||||
Secondary Licenses under the terms of this version of the License, the
|
||||
notice described in Exhibit B of this License must be attached.
|
||||
|
||||
Exhibit A - Source Code Form License Notice
|
||||
-------------------------------------------
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public
|
||||
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
If it is not possible or desirable to put the notice in a particular
|
||||
file, then You may include the notice in a location (such as a LICENSE
|
||||
file in a relevant directory) where a recipient would be likely to look
|
||||
for such a notice.
|
||||
|
||||
You may add additional accurate notices of copyright ownership.
|
||||
|
||||
Exhibit B - "Incompatible With Secondary Licenses" Notice
|
||||
---------------------------------------------------------
|
||||
|
||||
This Source Code Form is "Incompatible With Secondary Licenses", as
|
||||
defined by the Mozilla Public License, v. 2.0.
|
|
@ -11,346 +11,15 @@
|
|||
#include <cocos-ext.h>
|
||||
#include <cocos2d.h>
|
||||
#include <fmod.hpp>
|
||||
//#include <Interface.hpp>
|
||||
#include <stdint.h>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
#include <Geode/utils/addresser.hpp>
|
||||
#include "Enums.hpp"
|
||||
|
||||
namespace geode::core::meta {}
|
||||
|
||||
template<auto F>
|
||||
struct address_of_t {
|
||||
static inline auto value = geode::base::get();
|
||||
};
|
||||
|
||||
template<auto F>
|
||||
inline auto address_of = address_of_t<F>::value;
|
||||
|
||||
//thanks pie
|
||||
enum class SearchType {
|
||||
Search = 0,
|
||||
Downloaded = 1,
|
||||
MostLiked = 2,
|
||||
Trending = 3,
|
||||
Recent = 4,
|
||||
UsersLevels = 5,
|
||||
Featured = 6,
|
||||
Magic = 7,
|
||||
Sends = 8,
|
||||
MapPack = 9,
|
||||
MapPackOnClick = 10,
|
||||
Awarded = 11,
|
||||
Followed = 12,
|
||||
Friends = 13,
|
||||
Users = 14,
|
||||
LikedGDW = 15,
|
||||
HallOfFame = 16,
|
||||
FeaturedGDW = 17,
|
||||
Similar = 18,
|
||||
MyLevels = 98,
|
||||
SavedLevels = 99,
|
||||
FavouriteLevels = 100
|
||||
};
|
||||
|
||||
// jesus fucking christ (painfully written by @hjfod)
|
||||
enum class GameObjectType {
|
||||
Solid = 0,
|
||||
Hazard = 2,
|
||||
InverseGravityPortal = 3,
|
||||
NormalGravityPortal = 4,
|
||||
ShipPortal = 5,
|
||||
CubePortal = 6,
|
||||
Decoration = 7,
|
||||
YellowJumpPad = 8,
|
||||
PinkJumpPad = 9,
|
||||
GravityPad = 10,
|
||||
YellowJumpRing = 11,
|
||||
PinkJumpRing = 12,
|
||||
GravityRing = 13,
|
||||
InverseMirrorPortal = 14,
|
||||
NormalMirrorPortal = 15,
|
||||
BallPortal = 16,
|
||||
RegularSizePortal = 17,
|
||||
MiniSizePortal = 18,
|
||||
UfoPortal = 19,
|
||||
Modifier = 20,
|
||||
SecretCoin = 22,
|
||||
DualPortal = 23,
|
||||
SoloPortal = 24,
|
||||
Slope = 25,
|
||||
WavePortal = 26,
|
||||
RobotPortal = 27,
|
||||
TeleportPortal = 28,
|
||||
GreenRing = 29,
|
||||
Collectible = 30,
|
||||
UserCoin = 31,
|
||||
DropRing = 32,
|
||||
SpiderPortal = 33,
|
||||
RedJumpPad = 34,
|
||||
RedJumpRing = 35,
|
||||
CustomRing = 36,
|
||||
DashRing = 37,
|
||||
GravityDashRing = 38,
|
||||
CollisionObject = 39,
|
||||
Special = 40,
|
||||
};
|
||||
|
||||
enum class PulseEffectType {};
|
||||
enum class TouchTriggerType {};
|
||||
enum class PlayerButton {};
|
||||
enum class GhostType {};
|
||||
enum class TableViewCellEditingStyle {};
|
||||
enum class UserListType {};
|
||||
enum class GJErrorCode {};
|
||||
enum class AccountError {};
|
||||
enum class GJSongError {};
|
||||
enum class LikeItemType {
|
||||
Unknown = 0,
|
||||
Level = 1,
|
||||
Comment = 2,
|
||||
AccountComment = 3
|
||||
};
|
||||
|
||||
enum class GJStoreItem {};
|
||||
enum class CommentError {};
|
||||
enum class BackupAccountError {};
|
||||
|
||||
enum class BoomListType {
|
||||
Default = 0x0,
|
||||
User = 0x2,
|
||||
Stats = 0x3,
|
||||
Achievement = 0x4,
|
||||
Level = 0x5,
|
||||
Level2 = 0x6,
|
||||
Comment = 0x7,
|
||||
Comment2 = 0x8,
|
||||
Song = 0xb,
|
||||
Score = 0xc,
|
||||
MapPack = 0xd,
|
||||
CustomSong = 0xe,
|
||||
Comment3 = 0xf,
|
||||
User2 = 0x10,
|
||||
Request = 0x11,
|
||||
Message = 0x12,
|
||||
LevelScore = 0x13,
|
||||
Artist = 0x14,
|
||||
};
|
||||
|
||||
enum class MenuAnimationType {
|
||||
Scale = 0,
|
||||
Move = 1,
|
||||
};
|
||||
|
||||
enum class ShopType {
|
||||
Normal,
|
||||
Secret,
|
||||
Community
|
||||
};
|
||||
|
||||
// Geode Addition
|
||||
enum class ZLayer {
|
||||
B4 = -3,
|
||||
B3 = -1,
|
||||
B2 = 1,
|
||||
B1 = 3,
|
||||
Default = 0,
|
||||
T1 = 5,
|
||||
T2 = 7,
|
||||
T3 = 9,
|
||||
};
|
||||
|
||||
enum class UpdateResponse {
|
||||
Unknown,
|
||||
UpToDate,
|
||||
GameVerOutOfDate,
|
||||
UpdateSuccess,
|
||||
};
|
||||
|
||||
enum class UnlockType {
|
||||
Cube = 0x1,
|
||||
Col1 = 0x2,
|
||||
Col2 = 0x3,
|
||||
Ship = 0x4,
|
||||
Ball = 0x5,
|
||||
Bird = 0x6,
|
||||
Dart = 0x7,
|
||||
Robot = 0x8,
|
||||
Spider = 0x9,
|
||||
Streak = 0xA,
|
||||
Death = 0xB,
|
||||
GJItem = 0xC,
|
||||
};
|
||||
|
||||
enum class SpecialRewardItem {
|
||||
FireShard = 0x1,
|
||||
IceShard = 0x2,
|
||||
PoisonShard = 0x3,
|
||||
ShadowShard = 0x4,
|
||||
LavaShard = 0x5,
|
||||
BonusKey = 0x6,
|
||||
Orbs = 0x7,
|
||||
Diamonds = 0x8,
|
||||
CustomItem = 0x9,
|
||||
};
|
||||
|
||||
enum class EditCommand {
|
||||
SmallLeft = 1,
|
||||
SmallRight = 2,
|
||||
SmallUp = 3,
|
||||
SmallDown = 4,
|
||||
|
||||
Left = 5,
|
||||
Right = 6,
|
||||
Up = 7,
|
||||
Down = 8,
|
||||
|
||||
BigLeft = 9,
|
||||
BigRight = 10,
|
||||
BigUp = 11,
|
||||
BigDown = 12,
|
||||
|
||||
TinyLeft = 13,
|
||||
TinyRight = 14,
|
||||
TinyUp = 15,
|
||||
TinyDown = 16,
|
||||
|
||||
FlipX = 17,
|
||||
FlipY = 18,
|
||||
RotateCW = 19,
|
||||
RotateCCW = 20,
|
||||
RotateCW45 = 21,
|
||||
RotateCCW45 = 22,
|
||||
RotateFree = 23,
|
||||
RotateSnap = 24,
|
||||
|
||||
Scale = 25,
|
||||
};
|
||||
|
||||
// Geode Addition
|
||||
enum class PlaybackMode {
|
||||
Not = 0,
|
||||
Playing = 1,
|
||||
Paused = 2,
|
||||
};
|
||||
|
||||
enum class SelectArtType {
|
||||
Background = 0,
|
||||
Ground = 1,
|
||||
};
|
||||
|
||||
enum class UndoCommand {
|
||||
Delete = 1,
|
||||
New = 2,
|
||||
Paste = 3,
|
||||
DeleteMulti = 4,
|
||||
Transform = 5,
|
||||
Select = 6,
|
||||
};
|
||||
|
||||
enum class EasingType {
|
||||
None = 0,
|
||||
EaseInOut = 1,
|
||||
EaseIn = 2,
|
||||
EaseOut = 3,
|
||||
ElasticInOut = 4,
|
||||
ElasticIn = 5,
|
||||
ElasticOut = 6,
|
||||
BounceInOut = 7,
|
||||
BounceIn = 8,
|
||||
BounceOut = 9,
|
||||
ExponentialInOut = 10,
|
||||
ExponentialIn = 11,
|
||||
ExponentialOut = 12,
|
||||
SineInOut = 13,
|
||||
SineIn = 14,
|
||||
SineOut = 15,
|
||||
BackInOut = 16,
|
||||
BackIn = 17,
|
||||
BackOut = 18,
|
||||
};
|
||||
|
||||
enum class GJDifficulty {
|
||||
Auto = 0,
|
||||
Easy = 1,
|
||||
Normal = 2,
|
||||
Hard = 3,
|
||||
Harder = 4,
|
||||
Insane = 5,
|
||||
Demon = 6,
|
||||
DemonEasy = 7,
|
||||
DemonMedium = 8,
|
||||
DemonInsane = 9,
|
||||
DemonExtreme = 10
|
||||
};
|
||||
|
||||
enum class GJLevelType {
|
||||
Local = 1,
|
||||
Editor = 2,
|
||||
Saved = 3
|
||||
};
|
||||
|
||||
enum class IconType {
|
||||
Cube = 0,
|
||||
Ship = 1,
|
||||
Ball = 2,
|
||||
Ufo = 3,
|
||||
Wave = 4,
|
||||
Robot = 5,
|
||||
Spider = 6,
|
||||
DeathEffect = 98,
|
||||
Special = 99,
|
||||
};
|
||||
|
||||
enum class GJChallengeType {
|
||||
Unknown = 0,
|
||||
Orbs = 1,
|
||||
UserCoins = 2,
|
||||
Stars = 3
|
||||
};
|
||||
|
||||
enum class GJScoreType {
|
||||
Unknown = 0,
|
||||
Creator = 1
|
||||
};
|
||||
|
||||
enum class LevelLeaderboardType {
|
||||
Friends = 0,
|
||||
Global = 1,
|
||||
Weekly = 2
|
||||
};
|
||||
|
||||
// Geode Addition
|
||||
enum class ComparisonType {
|
||||
Equals = 0,
|
||||
Larger = 1,
|
||||
Smaller = 2,
|
||||
};
|
||||
|
||||
// Geode Addition
|
||||
enum class MoveTargetType {
|
||||
Both = 0,
|
||||
XOnly = 1,
|
||||
YOnly = 2,
|
||||
};
|
||||
|
||||
// Geode Addition
|
||||
enum class TouchToggleMode {
|
||||
Normal = 0,
|
||||
ToggleOn = 1,
|
||||
ToggleOff = 2,
|
||||
};
|
||||
|
||||
// Geode Addition
|
||||
enum class LeaderboardState {
|
||||
Default = 0,
|
||||
Top100 = 1,
|
||||
Global = 2,
|
||||
Creator = 3,
|
||||
Friends = 4,
|
||||
};
|
||||
|
||||
#define CLASSPARAM(...)
|
||||
#define STRUCTPARAM(...)
|
||||
|
||||
#include <codegenned/GeneratedHeader.hpp>
|
||||
#include <Geode/GeneratedBinding.hpp>
|
||||
|
|
|
@ -103,82 +103,82 @@ _61,_62,_63,N,...) N
|
|||
9, 8, 7, 6, 5, 4, 3, 2, 1, 0
|
||||
|
||||
|
||||
#define GEODE_NEST1(macro, begin) \
|
||||
macro(GEODE_CONCAT(begin, 0)), \
|
||||
macro(GEODE_CONCAT(begin, 1)), \
|
||||
macro(GEODE_CONCAT(begin, 2)), \
|
||||
macro(GEODE_CONCAT(begin, 3)), \
|
||||
macro(GEODE_CONCAT(begin, 4)), \
|
||||
macro(GEODE_CONCAT(begin, 5)), \
|
||||
macro(GEODE_CONCAT(begin, 6)), \
|
||||
macro(GEODE_CONCAT(begin, 7)), \
|
||||
macro(GEODE_CONCAT(begin, 8)), \
|
||||
macro(GEODE_CONCAT(begin, 9)), \
|
||||
macro(GEODE_CONCAT(begin, a)), \
|
||||
macro(GEODE_CONCAT(begin, b)), \
|
||||
macro(GEODE_CONCAT(begin, c)), \
|
||||
macro(GEODE_CONCAT(begin, d)), \
|
||||
macro(GEODE_CONCAT(begin, e)), \
|
||||
macro(GEODE_CONCAT(begin, f))
|
||||
// #define GEODE_NEST1(macro, begin) \
|
||||
// macro(GEODE_CONCAT(begin, 0)), \
|
||||
// macro(GEODE_CONCAT(begin, 1)), \
|
||||
// macro(GEODE_CONCAT(begin, 2)), \
|
||||
// macro(GEODE_CONCAT(begin, 3)), \
|
||||
// macro(GEODE_CONCAT(begin, 4)), \
|
||||
// macro(GEODE_CONCAT(begin, 5)), \
|
||||
// macro(GEODE_CONCAT(begin, 6)), \
|
||||
// macro(GEODE_CONCAT(begin, 7)), \
|
||||
// macro(GEODE_CONCAT(begin, 8)), \
|
||||
// macro(GEODE_CONCAT(begin, 9)), \
|
||||
// macro(GEODE_CONCAT(begin, a)), \
|
||||
// macro(GEODE_CONCAT(begin, b)), \
|
||||
// macro(GEODE_CONCAT(begin, c)), \
|
||||
// macro(GEODE_CONCAT(begin, d)), \
|
||||
// macro(GEODE_CONCAT(begin, e)), \
|
||||
// macro(GEODE_CONCAT(begin, f))
|
||||
|
||||
#define GEODE_NEST2(macro, begin) \
|
||||
GEODE_NEST1(macro, GEODE_CONCAT(begin, 0)), \
|
||||
GEODE_NEST1(macro, GEODE_CONCAT(begin, 1)), \
|
||||
GEODE_NEST1(macro, GEODE_CONCAT(begin, 2)), \
|
||||
GEODE_NEST1(macro, GEODE_CONCAT(begin, 3)), \
|
||||
GEODE_NEST1(macro, GEODE_CONCAT(begin, 4)), \
|
||||
GEODE_NEST1(macro, GEODE_CONCAT(begin, 5)), \
|
||||
GEODE_NEST1(macro, GEODE_CONCAT(begin, 6)), \
|
||||
GEODE_NEST1(macro, GEODE_CONCAT(begin, 7)), \
|
||||
GEODE_NEST1(macro, GEODE_CONCAT(begin, 8)), \
|
||||
GEODE_NEST1(macro, GEODE_CONCAT(begin, 9)), \
|
||||
GEODE_NEST1(macro, GEODE_CONCAT(begin, a)), \
|
||||
GEODE_NEST1(macro, GEODE_CONCAT(begin, b)), \
|
||||
GEODE_NEST1(macro, GEODE_CONCAT(begin, c)), \
|
||||
GEODE_NEST1(macro, GEODE_CONCAT(begin, d)), \
|
||||
GEODE_NEST1(macro, GEODE_CONCAT(begin, e)), \
|
||||
GEODE_NEST1(macro, GEODE_CONCAT(begin, f))
|
||||
// #define GEODE_NEST2(macro, begin) \
|
||||
// GEODE_NEST1(macro, GEODE_CONCAT(begin, 0)), \
|
||||
// GEODE_NEST1(macro, GEODE_CONCAT(begin, 1)), \
|
||||
// GEODE_NEST1(macro, GEODE_CONCAT(begin, 2)), \
|
||||
// GEODE_NEST1(macro, GEODE_CONCAT(begin, 3)), \
|
||||
// GEODE_NEST1(macro, GEODE_CONCAT(begin, 4)), \
|
||||
// GEODE_NEST1(macro, GEODE_CONCAT(begin, 5)), \
|
||||
// GEODE_NEST1(macro, GEODE_CONCAT(begin, 6)), \
|
||||
// GEODE_NEST1(macro, GEODE_CONCAT(begin, 7)), \
|
||||
// GEODE_NEST1(macro, GEODE_CONCAT(begin, 8)), \
|
||||
// GEODE_NEST1(macro, GEODE_CONCAT(begin, 9)), \
|
||||
// GEODE_NEST1(macro, GEODE_CONCAT(begin, a)), \
|
||||
// GEODE_NEST1(macro, GEODE_CONCAT(begin, b)), \
|
||||
// GEODE_NEST1(macro, GEODE_CONCAT(begin, c)), \
|
||||
// GEODE_NEST1(macro, GEODE_CONCAT(begin, d)), \
|
||||
// GEODE_NEST1(macro, GEODE_CONCAT(begin, e)), \
|
||||
// GEODE_NEST1(macro, GEODE_CONCAT(begin, f))
|
||||
|
||||
#define GEODE_NEST3(macro, begin) \
|
||||
GEODE_NEST2(macro, GEODE_CONCAT(begin, 0)), \
|
||||
GEODE_NEST2(macro, GEODE_CONCAT(begin, 1)), \
|
||||
GEODE_NEST2(macro, GEODE_CONCAT(begin, 2)), \
|
||||
GEODE_NEST2(macro, GEODE_CONCAT(begin, 3)), \
|
||||
GEODE_NEST2(macro, GEODE_CONCAT(begin, 4)), \
|
||||
GEODE_NEST2(macro, GEODE_CONCAT(begin, 5)), \
|
||||
GEODE_NEST2(macro, GEODE_CONCAT(begin, 6)), \
|
||||
GEODE_NEST2(macro, GEODE_CONCAT(begin, 7)), \
|
||||
GEODE_NEST2(macro, GEODE_CONCAT(begin, 8)), \
|
||||
GEODE_NEST2(macro, GEODE_CONCAT(begin, 9)), \
|
||||
GEODE_NEST2(macro, GEODE_CONCAT(begin, a)), \
|
||||
GEODE_NEST2(macro, GEODE_CONCAT(begin, b)), \
|
||||
GEODE_NEST2(macro, GEODE_CONCAT(begin, c)), \
|
||||
GEODE_NEST2(macro, GEODE_CONCAT(begin, d)), \
|
||||
GEODE_NEST2(macro, GEODE_CONCAT(begin, e)), \
|
||||
GEODE_NEST2(macro, GEODE_CONCAT(begin, f))
|
||||
// #define GEODE_NEST3(macro, begin) \
|
||||
// GEODE_NEST2(macro, GEODE_CONCAT(begin, 0)), \
|
||||
// GEODE_NEST2(macro, GEODE_CONCAT(begin, 1)), \
|
||||
// GEODE_NEST2(macro, GEODE_CONCAT(begin, 2)), \
|
||||
// GEODE_NEST2(macro, GEODE_CONCAT(begin, 3)), \
|
||||
// GEODE_NEST2(macro, GEODE_CONCAT(begin, 4)), \
|
||||
// GEODE_NEST2(macro, GEODE_CONCAT(begin, 5)), \
|
||||
// GEODE_NEST2(macro, GEODE_CONCAT(begin, 6)), \
|
||||
// GEODE_NEST2(macro, GEODE_CONCAT(begin, 7)), \
|
||||
// GEODE_NEST2(macro, GEODE_CONCAT(begin, 8)), \
|
||||
// GEODE_NEST2(macro, GEODE_CONCAT(begin, 9)), \
|
||||
// GEODE_NEST2(macro, GEODE_CONCAT(begin, a)), \
|
||||
// GEODE_NEST2(macro, GEODE_CONCAT(begin, b)), \
|
||||
// GEODE_NEST2(macro, GEODE_CONCAT(begin, c)), \
|
||||
// GEODE_NEST2(macro, GEODE_CONCAT(begin, d)), \
|
||||
// GEODE_NEST2(macro, GEODE_CONCAT(begin, e)), \
|
||||
// GEODE_NEST2(macro, GEODE_CONCAT(begin, f))
|
||||
|
||||
#define GEODE_NEST4(macro, begin) \
|
||||
GEODE_NEST3(macro, GEODE_CONCAT(begin, 0)), \
|
||||
GEODE_NEST3(macro, GEODE_CONCAT(begin, 1)), \
|
||||
GEODE_NEST3(macro, GEODE_CONCAT(begin, 2)), \
|
||||
GEODE_NEST3(macro, GEODE_CONCAT(begin, 3)), \
|
||||
GEODE_NEST3(macro, GEODE_CONCAT(begin, 4)), \
|
||||
GEODE_NEST3(macro, GEODE_CONCAT(begin, 5)), \
|
||||
GEODE_NEST3(macro, GEODE_CONCAT(begin, 6)), \
|
||||
GEODE_NEST3(macro, GEODE_CONCAT(begin, 7)), \
|
||||
GEODE_NEST3(macro, GEODE_CONCAT(begin, 8)), \
|
||||
GEODE_NEST3(macro, GEODE_CONCAT(begin, 9)), \
|
||||
GEODE_NEST3(macro, GEODE_CONCAT(begin, a)), \
|
||||
GEODE_NEST3(macro, GEODE_CONCAT(begin, b)), \
|
||||
GEODE_NEST3(macro, GEODE_CONCAT(begin, c)), \
|
||||
GEODE_NEST3(macro, GEODE_CONCAT(begin, d)), \
|
||||
GEODE_NEST3(macro, GEODE_CONCAT(begin, e)), \
|
||||
GEODE_NEST3(macro, GEODE_CONCAT(begin, f))
|
||||
// #define GEODE_NEST4(macro, begin) \
|
||||
// GEODE_NEST3(macro, GEODE_CONCAT(begin, 0)), \
|
||||
// GEODE_NEST3(macro, GEODE_CONCAT(begin, 1)), \
|
||||
// GEODE_NEST3(macro, GEODE_CONCAT(begin, 2)), \
|
||||
// GEODE_NEST3(macro, GEODE_CONCAT(begin, 3)), \
|
||||
// GEODE_NEST3(macro, GEODE_CONCAT(begin, 4)), \
|
||||
// GEODE_NEST3(macro, GEODE_CONCAT(begin, 5)), \
|
||||
// GEODE_NEST3(macro, GEODE_CONCAT(begin, 6)), \
|
||||
// GEODE_NEST3(macro, GEODE_CONCAT(begin, 7)), \
|
||||
// GEODE_NEST3(macro, GEODE_CONCAT(begin, 8)), \
|
||||
// GEODE_NEST3(macro, GEODE_CONCAT(begin, 9)), \
|
||||
// GEODE_NEST3(macro, GEODE_CONCAT(begin, a)), \
|
||||
// GEODE_NEST3(macro, GEODE_CONCAT(begin, b)), \
|
||||
// GEODE_NEST3(macro, GEODE_CONCAT(begin, c)), \
|
||||
// GEODE_NEST3(macro, GEODE_CONCAT(begin, d)), \
|
||||
// GEODE_NEST3(macro, GEODE_CONCAT(begin, e)), \
|
||||
// GEODE_NEST3(macro, GEODE_CONCAT(begin, f))
|
||||
|
||||
|
||||
#define GEODE_ENUM_OFFSETS_DEFINE(hex) GEODE_CONCAT($, hex)
|
||||
#define GEODE_ENUM_OFFSETS_SET() GEODE_NEST4(GEODE_ENUM_OFFSETS_DEFINE, 0x)
|
||||
// #define GEODE_ENUM_OFFSETS_DEFINE(hex) GEODE_CONCAT($, hex)
|
||||
// #define GEODE_ENUM_OFFSETS_SET() GEODE_NEST4(GEODE_ENUM_OFFSETS_DEFINE, 0x)
|
||||
|
||||
enum class PrinterOffsets {
|
||||
GEODE_ENUM_OFFSETS_SET()
|
||||
};
|
||||
// enum class PrinterOffsets {
|
||||
// GEODE_ENUM_OFFSETS_SET()
|
||||
// };
|
||||
|
|
324
loader/include/Geode/Enums.hpp
Normal file
324
loader/include/Geode/Enums.hpp
Normal file
|
@ -0,0 +1,324 @@
|
|||
#pragma once
|
||||
|
||||
//thanks pie
|
||||
enum class SearchType {
|
||||
Search = 0,
|
||||
Downloaded = 1,
|
||||
MostLiked = 2,
|
||||
Trending = 3,
|
||||
Recent = 4,
|
||||
UsersLevels = 5,
|
||||
Featured = 6,
|
||||
Magic = 7,
|
||||
Sends = 8,
|
||||
MapPack = 9,
|
||||
MapPackOnClick = 10,
|
||||
Awarded = 11,
|
||||
Followed = 12,
|
||||
Friends = 13,
|
||||
Users = 14,
|
||||
LikedGDW = 15,
|
||||
HallOfFame = 16,
|
||||
FeaturedGDW = 17,
|
||||
Similar = 18,
|
||||
MyLevels = 98,
|
||||
SavedLevels = 99,
|
||||
FavouriteLevels = 100
|
||||
};
|
||||
|
||||
// jesus fucking christ (painfully written by @hjfod)
|
||||
enum class GameObjectType {
|
||||
Solid = 0,
|
||||
Hazard = 2,
|
||||
InverseGravityPortal = 3,
|
||||
NormalGravityPortal = 4,
|
||||
ShipPortal = 5,
|
||||
CubePortal = 6,
|
||||
Decoration = 7,
|
||||
YellowJumpPad = 8,
|
||||
PinkJumpPad = 9,
|
||||
GravityPad = 10,
|
||||
YellowJumpRing = 11,
|
||||
PinkJumpRing = 12,
|
||||
GravityRing = 13,
|
||||
InverseMirrorPortal = 14,
|
||||
NormalMirrorPortal = 15,
|
||||
BallPortal = 16,
|
||||
RegularSizePortal = 17,
|
||||
MiniSizePortal = 18,
|
||||
UfoPortal = 19,
|
||||
Modifier = 20,
|
||||
SecretCoin = 22,
|
||||
DualPortal = 23,
|
||||
SoloPortal = 24,
|
||||
Slope = 25,
|
||||
WavePortal = 26,
|
||||
RobotPortal = 27,
|
||||
TeleportPortal = 28,
|
||||
GreenRing = 29,
|
||||
Collectible = 30,
|
||||
UserCoin = 31,
|
||||
DropRing = 32,
|
||||
SpiderPortal = 33,
|
||||
RedJumpPad = 34,
|
||||
RedJumpRing = 35,
|
||||
CustomRing = 36,
|
||||
DashRing = 37,
|
||||
GravityDashRing = 38,
|
||||
CollisionObject = 39,
|
||||
Special = 40,
|
||||
};
|
||||
|
||||
enum class PulseEffectType {};
|
||||
enum class TouchTriggerType {};
|
||||
enum class PlayerButton {};
|
||||
enum class GhostType {};
|
||||
enum class TableViewCellEditingStyle {};
|
||||
enum class UserListType {};
|
||||
enum class GJErrorCode {};
|
||||
enum class AccountError {};
|
||||
enum class GJSongError {};
|
||||
enum class LikeItemType {
|
||||
Unknown = 0,
|
||||
Level = 1,
|
||||
Comment = 2,
|
||||
AccountComment = 3
|
||||
};
|
||||
|
||||
enum class GJStoreItem {};
|
||||
enum class CommentError {};
|
||||
enum class BackupAccountError {};
|
||||
|
||||
enum class BoomListType {
|
||||
Default = 0x0,
|
||||
User = 0x2,
|
||||
Stats = 0x3,
|
||||
Achievement = 0x4,
|
||||
Level = 0x5,
|
||||
Level2 = 0x6,
|
||||
Comment = 0x7,
|
||||
Comment2 = 0x8,
|
||||
Song = 0xb,
|
||||
Score = 0xc,
|
||||
MapPack = 0xd,
|
||||
CustomSong = 0xe,
|
||||
Comment3 = 0xf,
|
||||
User2 = 0x10,
|
||||
Request = 0x11,
|
||||
Message = 0x12,
|
||||
LevelScore = 0x13,
|
||||
Artist = 0x14,
|
||||
};
|
||||
|
||||
enum class MenuAnimationType {
|
||||
Scale = 0,
|
||||
Move = 1,
|
||||
};
|
||||
|
||||
enum class ShopType {
|
||||
Normal,
|
||||
Secret,
|
||||
Community
|
||||
};
|
||||
|
||||
// Geode Addition
|
||||
enum class ZLayer {
|
||||
B4 = -3,
|
||||
B3 = -1,
|
||||
B2 = 1,
|
||||
B1 = 3,
|
||||
Default = 0,
|
||||
T1 = 5,
|
||||
T2 = 7,
|
||||
T3 = 9,
|
||||
};
|
||||
|
||||
enum class UpdateResponse {
|
||||
Unknown,
|
||||
UpToDate,
|
||||
GameVerOutOfDate,
|
||||
UpdateSuccess,
|
||||
};
|
||||
|
||||
enum class UnlockType {
|
||||
Cube = 0x1,
|
||||
Col1 = 0x2,
|
||||
Col2 = 0x3,
|
||||
Ship = 0x4,
|
||||
Ball = 0x5,
|
||||
Bird = 0x6,
|
||||
Dart = 0x7,
|
||||
Robot = 0x8,
|
||||
Spider = 0x9,
|
||||
Streak = 0xA,
|
||||
Death = 0xB,
|
||||
GJItem = 0xC,
|
||||
};
|
||||
|
||||
enum class SpecialRewardItem {
|
||||
FireShard = 0x1,
|
||||
IceShard = 0x2,
|
||||
PoisonShard = 0x3,
|
||||
ShadowShard = 0x4,
|
||||
LavaShard = 0x5,
|
||||
BonusKey = 0x6,
|
||||
Orbs = 0x7,
|
||||
Diamonds = 0x8,
|
||||
CustomItem = 0x9,
|
||||
};
|
||||
|
||||
enum class EditCommand {
|
||||
SmallLeft = 1,
|
||||
SmallRight = 2,
|
||||
SmallUp = 3,
|
||||
SmallDown = 4,
|
||||
|
||||
Left = 5,
|
||||
Right = 6,
|
||||
Up = 7,
|
||||
Down = 8,
|
||||
|
||||
BigLeft = 9,
|
||||
BigRight = 10,
|
||||
BigUp = 11,
|
||||
BigDown = 12,
|
||||
|
||||
TinyLeft = 13,
|
||||
TinyRight = 14,
|
||||
TinyUp = 15,
|
||||
TinyDown = 16,
|
||||
|
||||
FlipX = 17,
|
||||
FlipY = 18,
|
||||
RotateCW = 19,
|
||||
RotateCCW = 20,
|
||||
RotateCW45 = 21,
|
||||
RotateCCW45 = 22,
|
||||
RotateFree = 23,
|
||||
RotateSnap = 24,
|
||||
|
||||
Scale = 25,
|
||||
};
|
||||
|
||||
// Geode Addition
|
||||
enum class PlaybackMode {
|
||||
Not = 0,
|
||||
Playing = 1,
|
||||
Paused = 2,
|
||||
};
|
||||
|
||||
enum class SelectArtType {
|
||||
Background = 0,
|
||||
Ground = 1,
|
||||
};
|
||||
|
||||
enum class UndoCommand {
|
||||
Delete = 1,
|
||||
New = 2,
|
||||
Paste = 3,
|
||||
DeleteMulti = 4,
|
||||
Transform = 5,
|
||||
Select = 6,
|
||||
};
|
||||
|
||||
enum class EasingType {
|
||||
None = 0,
|
||||
EaseInOut = 1,
|
||||
EaseIn = 2,
|
||||
EaseOut = 3,
|
||||
ElasticInOut = 4,
|
||||
ElasticIn = 5,
|
||||
ElasticOut = 6,
|
||||
BounceInOut = 7,
|
||||
BounceIn = 8,
|
||||
BounceOut = 9,
|
||||
ExponentialInOut = 10,
|
||||
ExponentialIn = 11,
|
||||
ExponentialOut = 12,
|
||||
SineInOut = 13,
|
||||
SineIn = 14,
|
||||
SineOut = 15,
|
||||
BackInOut = 16,
|
||||
BackIn = 17,
|
||||
BackOut = 18,
|
||||
};
|
||||
|
||||
enum class GJDifficulty {
|
||||
Auto = 0,
|
||||
Easy = 1,
|
||||
Normal = 2,
|
||||
Hard = 3,
|
||||
Harder = 4,
|
||||
Insane = 5,
|
||||
Demon = 6,
|
||||
DemonEasy = 7,
|
||||
DemonMedium = 8,
|
||||
DemonInsane = 9,
|
||||
DemonExtreme = 10
|
||||
};
|
||||
|
||||
enum class GJLevelType {
|
||||
Local = 1,
|
||||
Editor = 2,
|
||||
Saved = 3
|
||||
};
|
||||
|
||||
enum class IconType {
|
||||
Cube = 0,
|
||||
Ship = 1,
|
||||
Ball = 2,
|
||||
Ufo = 3,
|
||||
Wave = 4,
|
||||
Robot = 5,
|
||||
Spider = 6,
|
||||
DeathEffect = 98,
|
||||
Special = 99,
|
||||
};
|
||||
|
||||
enum class GJChallengeType {
|
||||
Unknown = 0,
|
||||
Orbs = 1,
|
||||
UserCoins = 2,
|
||||
Stars = 3
|
||||
};
|
||||
|
||||
enum class GJScoreType {
|
||||
Unknown = 0,
|
||||
Creator = 1
|
||||
};
|
||||
|
||||
enum class LevelLeaderboardType {
|
||||
Friends = 0,
|
||||
Global = 1,
|
||||
Weekly = 2
|
||||
};
|
||||
|
||||
// Geode Addition
|
||||
enum class ComparisonType {
|
||||
Equals = 0,
|
||||
Larger = 1,
|
||||
Smaller = 2,
|
||||
};
|
||||
|
||||
// Geode Addition
|
||||
enum class MoveTargetType {
|
||||
Both = 0,
|
||||
XOnly = 1,
|
||||
YOnly = 2,
|
||||
};
|
||||
|
||||
// Geode Addition
|
||||
enum class TouchToggleMode {
|
||||
Normal = 0,
|
||||
ToggleOn = 1,
|
||||
ToggleOff = 2,
|
||||
};
|
||||
|
||||
// Geode Addition
|
||||
enum class LeaderboardState {
|
||||
Default = 0,
|
||||
Top100 = 1,
|
||||
Global = 2,
|
||||
Creator = 3,
|
||||
Friends = 4,
|
||||
};
|
|
@ -3,4 +3,5 @@
|
|||
#include "Bindings.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "Loader.hpp"
|
||||
#include "Modify.hpp"
|
||||
// #include "Modify.hpp"
|
||||
#include "UI.hpp"
|
||||
|
|
|
@ -5,4 +5,5 @@
|
|||
#include "loader/Log.hpp"
|
||||
#include "loader/Mod.hpp"
|
||||
#include "loader/Loader.hpp"
|
||||
#include "loader/Interface.hpp"
|
||||
#include "loader/Setting.hpp"
|
||||
#include "loader/SettingEvent.hpp"
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
|
||||
#include <Geode/DefaultInclude.hpp>
|
||||
|
||||
#include "modify/Traits.hpp"
|
||||
#include "modify/Modify.hpp"
|
||||
#include <Geode/GeneratedModify.hpp>
|
||||
#include "modify/Field.hpp"
|
||||
#include "modify/InternalMacros.hpp"
|
||||
|
||||
|
|
14
loader/include/Geode/UI.hpp
Normal file
14
loader/include/Geode/UI.hpp
Normal file
|
@ -0,0 +1,14 @@
|
|||
#pragma once
|
||||
|
||||
#include "ui/BasedButtonSprite.hpp"
|
||||
#include "ui/BasedButton.hpp"
|
||||
#include "ui/IconButtonSprite.hpp"
|
||||
#include "ui/InputNode.hpp"
|
||||
#include "ui/ListView.hpp"
|
||||
#include "ui/MDTextArea.hpp"
|
||||
#include "ui/Notification.hpp"
|
||||
#include "ui/Popup.hpp"
|
||||
#include "ui/SceneManager.hpp"
|
||||
#include "ui/Scrollbar.hpp"
|
||||
#include "ui/ScrollLayer.hpp"
|
||||
#include "ui/TextRenderer.hpp"
|
|
@ -13,4 +13,5 @@
|
|||
#include "utils/ext.hpp"
|
||||
#include "utils/convert.hpp"
|
||||
#include "utils/cocos.hpp"
|
||||
#include "utils/operators.hpp"
|
||||
#include "utils/operators.hpp"
|
||||
#include "utils/Ref.hpp"
|
||||
|
|
|
@ -136,6 +136,10 @@ public:
|
|||
return id;
|
||||
}
|
||||
|
||||
GEODE_ADD(
|
||||
static CCDirector* get();
|
||||
)
|
||||
|
||||
// attribute
|
||||
|
||||
/** Get current running Scene. Director can only run one Scene at the time */
|
||||
|
@ -525,7 +529,7 @@ protected:
|
|||
CCDirectorDelegate *m_pProjectionDelegate;
|
||||
|
||||
RT_ADD(
|
||||
CC_PROPERTY(CCSceneDelegate*, m_pAppDelegate, SceneDelegate);
|
||||
CC_SYNTHESIZE(CCSceneDelegate*, m_pAppDelegate, SceneDelegate);
|
||||
CCSize m_obScaleFactor;
|
||||
CCSize m_obResolutionInPixels;
|
||||
TextureQuality m_eTextureQuality;
|
||||
|
|
|
@ -52,6 +52,7 @@ class CCActionManager;
|
|||
class CCComponent;
|
||||
class CCDictionary;
|
||||
class CCComponentContainer;
|
||||
class CCKeyboardDispatcher;
|
||||
|
||||
/**
|
||||
* @addtogroup base_nodes
|
||||
|
@ -841,6 +842,40 @@ public:
|
|||
|
||||
/// @} end of Tag & User Data
|
||||
|
||||
GEODE_ADD(
|
||||
private:
|
||||
friend class geode::modifier::FieldContainer;
|
||||
|
||||
geode::modifier::FieldContainer* getFieldContainer();
|
||||
|
||||
public:
|
||||
/**
|
||||
* Get the string ID of this node
|
||||
* @returns The ID, or an empty string if the node has no ID.
|
||||
*/
|
||||
std::string getID();
|
||||
/**
|
||||
* Set the string ID of this node. String IDs are a Geode addition
|
||||
* that are much safer to use to get nodes than absolute indexes
|
||||
* @param id The ID of the node, recommended to be in kebab case
|
||||
* without any spaces or uppercase letters
|
||||
*/
|
||||
void setID(std::string const& id);
|
||||
|
||||
/**
|
||||
* Get a child by its string ID
|
||||
* @param id ID of the child
|
||||
* @returns The child, or nullptr if none was found
|
||||
*/
|
||||
CCNode* getChildByID(std::string const& id);
|
||||
|
||||
/**
|
||||
* Get a child by its string ID. Recursively searches all the children
|
||||
* @param id ID of the child
|
||||
* @returns The child, or nullptr if none was found
|
||||
*/
|
||||
CCNode* getChildByIDRecursive(std::string const& id);
|
||||
);
|
||||
|
||||
/// @{
|
||||
/// @name Shader Program
|
||||
|
|
|
@ -79,8 +79,8 @@ public:
|
|||
class CCDestructor : public CCCopying {
|
||||
private:
|
||||
static inline auto& destructorLock() {
|
||||
static std::unordered_map<void*, bool> ret;
|
||||
return ret;
|
||||
static auto ret = new std::unordered_map<void*, bool>;
|
||||
return *ret;
|
||||
}
|
||||
public:
|
||||
static inline bool& globalLock() {
|
||||
|
|
|
@ -198,6 +198,7 @@ public:
|
|||
* @js ctor
|
||||
*/
|
||||
CCLabelBMFont();
|
||||
GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCLabelBMFont, CCSpriteBatchNode)
|
||||
/**
|
||||
* @js NA
|
||||
* @lua NA
|
||||
|
|
|
@ -104,15 +104,21 @@ It's new in cocos2d-x since v0.99.5
|
|||
* classes using stl containers. Easiest way to hijack this is redefining the NS_CC_BEGIN
|
||||
* macro.
|
||||
*/
|
||||
class GeodeNodeMetadata;
|
||||
namespace geode {
|
||||
struct modify;
|
||||
struct temp_name_find_better;
|
||||
namespace modifier {
|
||||
struct addresses;
|
||||
struct types;
|
||||
class FieldContainer;
|
||||
}
|
||||
}
|
||||
#define GEODE_FRIEND_MODIFY GEODE_ADD(friend struct geode::modify; friend struct geode::modifier::addresses; friend struct geode::modifier::types; friend struct geode::temp_name_find_better;)
|
||||
#define GEODE_FRIEND_MODIFY GEODE_ADD(\
|
||||
friend struct ::geode::modify;\
|
||||
friend struct ::geode::modifier::addresses;\
|
||||
friend struct ::geode::modifier::types;\
|
||||
friend class ::GeodeNodeMetadata;\
|
||||
)
|
||||
#define GEODE_ADD(...) __VA_ARGS__
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -32,6 +32,10 @@ public:
|
|||
*/
|
||||
static CCApplication* sharedApplication();
|
||||
|
||||
GEODE_ADD(
|
||||
static CCApplication* get();
|
||||
);
|
||||
|
||||
/**
|
||||
@brief Get current language config
|
||||
@return Current language config
|
||||
|
|
|
@ -49,6 +49,10 @@ public:
|
|||
@brief get the shared main open gl window
|
||||
*/
|
||||
static CCEGLView* sharedOpenGLView();
|
||||
|
||||
GEODE_ADD(
|
||||
static CCEGLView* get();
|
||||
);
|
||||
};
|
||||
|
||||
NS_CC_END
|
||||
|
|
|
@ -57,6 +57,10 @@ public:
|
|||
@js getInstance
|
||||
*/
|
||||
static CCApplication* sharedApplication();
|
||||
|
||||
GEODE_ADD(
|
||||
static CCApplication* get();
|
||||
);
|
||||
|
||||
/**
|
||||
@brief Callback by CCDirector for limit FPS.
|
||||
|
|
|
@ -49,6 +49,10 @@ public:
|
|||
virtual void setIMEKeyboardState(bool bOpen);
|
||||
|
||||
static CCEGLView* sharedOpenGLView();
|
||||
|
||||
GEODE_ADD(
|
||||
static CCEGLView* get();
|
||||
);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -60,6 +60,10 @@ public:
|
|||
*/
|
||||
static CCApplication* sharedApplication();
|
||||
|
||||
GEODE_ADD(
|
||||
static CCApplication* get();
|
||||
);
|
||||
|
||||
/**
|
||||
@brief Get current language config
|
||||
@return Current language config
|
||||
|
|
|
@ -40,6 +40,10 @@ class CC_DLL CCEGLView : public CCEGLViewProtocol
|
|||
public:
|
||||
static CCEGLView* sharedOpenGLView(void);
|
||||
|
||||
GEODE_ADD(
|
||||
static CCEGLView* get();
|
||||
);
|
||||
|
||||
virtual ~CCEGLView(void);
|
||||
|
||||
virtual bool isOpenGLReady(void);
|
||||
|
|
|
@ -30,6 +30,10 @@ public:
|
|||
*/
|
||||
static CCApplication* sharedApplication();
|
||||
|
||||
GEODE_ADD(
|
||||
static CCApplication* get();
|
||||
);
|
||||
|
||||
/* override functions */
|
||||
virtual void setAnimationInterval(double interval);
|
||||
virtual ccLanguageType getCurrentLanguage();
|
||||
|
@ -45,6 +49,7 @@ public:
|
|||
virtual void setupGLView();
|
||||
virtual void platformShutdown();
|
||||
void toggleVerticalSync(bool);
|
||||
bool getVerticalSyncEnabled() const;
|
||||
)
|
||||
|
||||
/**
|
||||
|
|
|
@ -95,6 +95,11 @@ public:
|
|||
@brief get the shared main open gl window
|
||||
*/
|
||||
static CCEGLView* sharedOpenGLView();
|
||||
|
||||
GEODE_ADD(
|
||||
static CCEGLView* get();
|
||||
);
|
||||
|
||||
RT_ADD( static CCEGLView* create(const gd::string&); )
|
||||
|
||||
RT_ADD(
|
||||
|
|
|
@ -52,6 +52,10 @@ public:
|
|||
*/
|
||||
static CCApplication* sharedApplication();
|
||||
|
||||
GEODE_ADD(
|
||||
static CCApplication* get();
|
||||
);
|
||||
|
||||
/* override functions */
|
||||
virtual void setAnimationInterval(double interval);
|
||||
virtual ccLanguageType getCurrentLanguage();
|
||||
|
|
|
@ -137,6 +137,10 @@ public:
|
|||
*/
|
||||
static CCEGLView* sharedOpenGLView();
|
||||
|
||||
GEODE_ADD(
|
||||
static CCEGLView* get();
|
||||
);
|
||||
|
||||
protected:
|
||||
|
||||
private:
|
||||
|
|
|
@ -14,24 +14,31 @@ RT_ADD(
|
|||
virtual ~CCKeyboardDispatcher();
|
||||
|
||||
void addDelegate(CCKeyboardDelegate* pDelegate);
|
||||
|
||||
void removeDelegate(CCKeyboardDelegate* pDelegate);
|
||||
|
||||
void forceAddDelegate(CCKeyboardDelegate* pDelegate);
|
||||
|
||||
void forceRemoveDelegate(CCKeyboardDelegate* pDelegate);
|
||||
|
||||
enumKeyCodes convertKeyCode(enumKeyCodes key);
|
||||
|
||||
bool dispatchKeyboardMSG(enumKeyCodes key, bool);
|
||||
|
||||
inline bool getAltKeyPressed() const {return m_bAltPressed;}
|
||||
inline bool getAltKeyPressed() const {
|
||||
return m_bAltPressed;
|
||||
}
|
||||
inline bool getCommandKeyPressed() const {
|
||||
return m_bCommandPressed;
|
||||
}
|
||||
inline bool getControlKeyPressed() const {
|
||||
return m_bControlPressed;
|
||||
}
|
||||
inline bool getShiftKeyPressed() const {
|
||||
return m_bShiftPressed;
|
||||
}
|
||||
|
||||
inline bool getCommandKeyPressed() const {return m_bCommandPressed;}
|
||||
|
||||
inline bool getControlKeyPressed() const {return m_bControlPressed;}
|
||||
|
||||
inline bool getShiftKeyPressed() const {return m_bShiftPressed;}
|
||||
GEODE_ADD(
|
||||
static CCKeyboardDispatcher* get();
|
||||
);
|
||||
|
||||
const char* keyToString(enumKeyCodes key);
|
||||
|
||||
|
|
|
@ -68,6 +68,7 @@ public:
|
|||
* @js ctor
|
||||
*/
|
||||
CCSpriteBatchNode();
|
||||
GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCSpriteBatchNode, CCNode)
|
||||
/**
|
||||
* @js NA
|
||||
* @lua NA
|
||||
|
|
|
@ -138,6 +138,10 @@ public:
|
|||
{}
|
||||
|
||||
public:
|
||||
GEODE_ADD(
|
||||
static CCTouchDispatcher* get();
|
||||
);
|
||||
|
||||
/** Whether or not the events are going to be dispatched. Default: true */
|
||||
bool isDispatchEvents(void);
|
||||
void setDispatchEvents(bool bDispatchEvents);
|
||||
|
|
|
@ -63,6 +63,9 @@ public:
|
|||
virtual ~CCControlColourPicker();
|
||||
|
||||
protected:
|
||||
RT_ADD(
|
||||
ccColor3B m_rgb;
|
||||
)
|
||||
HSV m_hsv;
|
||||
CC_SYNTHESIZE_RETAIN(CCControlSaturationBrightnessPicker*, m_colourPicker, colourPicker)
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ public:
|
|||
|
||||
public:
|
||||
/** Original sprite's size. */
|
||||
CC_SYNTHESIZE_READONLY(CCSize, m_originalSize, OriginalSize);
|
||||
CC_SYNTHESIZE_READONLY_NV(CCSize, m_originalSize, OriginalSize);
|
||||
/** Prefered sprite's size. By default the prefered size is the original size. */
|
||||
|
||||
//if the preferredSize component is given as -1, it is ignored
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
#include "Mod.hpp"
|
||||
#include "Loader.hpp"
|
||||
#include "Interface.hpp"
|
||||
|
||||
#ifdef API_DECL
|
||||
#undef API_DECL
|
||||
#endif
|
||||
|
||||
|
||||
#if GEODE_CONCAT(EXPORT_, EXPORT_NAME)
|
||||
#define API_DECL(func, ...) ; static inline auto GEODE_CONCAT(_dummy, __LINE__) = (geode::Interface::get()->exportAPIFunction(GEODE_STR(func), func), 0);
|
||||
#else
|
||||
#define API_DECL(func, ...) \
|
||||
{\
|
||||
static geode::Mod* src = geode::Loader::get()->getLoadedMod(_source);\
|
||||
static auto ptr = geode::Mod::get()->importAPIFunction<decltype(func)>(GEODE_STR(func), src);\
|
||||
return std::invoke(ptr, __VA_ARGS__);\
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef GEODE_API_HPP
|
||||
#define GEODE_API_HPP
|
||||
|
||||
#define API_INIT(name) static constexpr auto _source = name;
|
||||
|
||||
namespace geode {
|
||||
class GEODE_DLL ModAPI {};
|
||||
}
|
||||
#endif
|
||||
|
||||
#undef EXPORT_NAME
|
|
@ -1,6 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <Event.hpp>
|
||||
#include "Event.hpp"
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <functional>
|
||||
|
|
|
@ -3,45 +3,53 @@
|
|||
#include <Geode/DefaultInclude.hpp>
|
||||
#include <type_traits>
|
||||
#include "Mod.hpp"
|
||||
#include <unordered_set>
|
||||
|
||||
namespace geode {
|
||||
class Mod;
|
||||
class Event;
|
||||
|
||||
enum class PassThrough : bool {
|
||||
Propagate,
|
||||
Stop,
|
||||
};
|
||||
|
||||
struct GEODE_DLL BasicEventHandler {
|
||||
virtual bool onEvent(Event*) = 0;
|
||||
virtual PassThrough passThrough(Event*) = 0;
|
||||
|
||||
void listen();
|
||||
void unlisten();
|
||||
};
|
||||
|
||||
class GEODE_DLL Event {
|
||||
static std::vector<BasicEventHandler*> handlers;
|
||||
static std::unordered_set<BasicEventHandler*> s_handlers;
|
||||
|
||||
friend BasicEventHandler;
|
||||
|
||||
Mod* m_sender;
|
||||
public:
|
||||
static std::vector<BasicEventHandler*> const& getHandlers();
|
||||
|
||||
public:
|
||||
static std::unordered_set<BasicEventHandler*> const& getHandlers();
|
||||
|
||||
void postFrom(Mod* sender);
|
||||
inline void post() {
|
||||
postFrom(Mod::get());
|
||||
}
|
||||
|
||||
Mod* sender();
|
||||
Mod* getSender();
|
||||
|
||||
virtual ~Event();
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class EventHandler : public BasicEventHandler {
|
||||
public:
|
||||
virtual bool handle(T*) = 0;
|
||||
bool onEvent(Event* ev) override {
|
||||
public:
|
||||
virtual PassThrough handle(T*) = 0;
|
||||
PassThrough passThrough(Event* ev) override {
|
||||
if (auto myev = dynamic_cast<T*>(ev)) {
|
||||
return handle(myev);
|
||||
}
|
||||
return true;
|
||||
return PassThrough::Propagate;
|
||||
}
|
||||
|
||||
EventHandler() {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#include <Geode/utils/types.hpp>
|
||||
#include <string_view>
|
||||
|
||||
#include "../hook-core/Hook.hpp"
|
||||
#include <Geode/hook-core/Hook.hpp>
|
||||
|
||||
namespace geode {
|
||||
class Mod;
|
||||
|
|
|
@ -1,143 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <Geode/DefaultInclude.hpp>
|
||||
#include "Types.hpp"
|
||||
#include <vector>
|
||||
#include <variant>
|
||||
#include "../utils/casts.hpp"
|
||||
#include "../utils/Result.hpp"
|
||||
#include "Log.hpp"
|
||||
#include "Mod.hpp"
|
||||
|
||||
namespace geode {
|
||||
class Hook;
|
||||
class LogPtr;
|
||||
|
||||
/**
|
||||
* For developing your own mods, it is
|
||||
* often convenient to be able to do things
|
||||
* like create hooks using statically
|
||||
* initialized global classes.
|
||||
*
|
||||
* At that point however, your mod has not
|
||||
* yet received the Mod* to create hooks
|
||||
* through.
|
||||
*
|
||||
* For situations like that, you can instead
|
||||
* inherit from Interface to create your own
|
||||
* mod interface and create hooks through that;
|
||||
* calling `init` with the Mod* you receive
|
||||
* from geode will automatically create all
|
||||
* scheduled hooks, logs, etc.
|
||||
*
|
||||
* Interface also provides a handy &
|
||||
* standardized way to store access to your
|
||||
* Mod*; you can just define a `get` function
|
||||
* and a getter for the Mod* stored in the
|
||||
* Interface.
|
||||
*
|
||||
* @class Interface
|
||||
*/
|
||||
class Interface {
|
||||
protected:
|
||||
static GEODE_DLL Interface* create();
|
||||
|
||||
|
||||
struct ScheduledHook {
|
||||
std::string m_displayName;
|
||||
void* m_address;
|
||||
Result<Hook*>(Mod::*m_addFunction)(std::string const&, void*);
|
||||
};
|
||||
|
||||
struct ScheduledLog {
|
||||
std::string m_info;
|
||||
Severity m_severity;
|
||||
};
|
||||
|
||||
using ScheduledFunction = std::function<void()>;
|
||||
|
||||
Mod* m_mod = nullptr;
|
||||
std::vector<ScheduledHook> m_scheduledHooks;
|
||||
std::vector<ScheduledLog> m_scheduledLogs;
|
||||
std::vector<ScheduledFunction> m_scheduledFunctions;
|
||||
|
||||
public:
|
||||
static inline GEODE_HIDDEN Interface* get() {
|
||||
static Interface* ret = create();
|
||||
return ret;
|
||||
}
|
||||
|
||||
[[deprecated("Use Mod::get instead")]]
|
||||
static inline GEODE_HIDDEN Mod* mod() {
|
||||
return Interface::get()->m_mod;
|
||||
}
|
||||
|
||||
[[deprecated("Use Log::get instead")]]
|
||||
static inline GEODE_HIDDEN Log log() {
|
||||
return Interface::get()->m_mod->log();
|
||||
}
|
||||
|
||||
GEODE_DLL void init(Mod*);
|
||||
|
||||
/**
|
||||
* Create a hook at an address. This function can
|
||||
* be used at static initialization time, as it
|
||||
* doesn't require the Mod* to be set -- it will
|
||||
* create the hooks later when the Mod* is set.
|
||||
*
|
||||
* @param address The absolute address of
|
||||
* the function to hook, i.e. gd_base + 0xXXXX
|
||||
* @param detour Pointer to your detour function
|
||||
*
|
||||
* @returns Successful result containing the
|
||||
* Hook handle (or nullptr if Mod* is not loaded
|
||||
* yet), errorful result with info on error
|
||||
*/
|
||||
template<auto Detour, template <class, class...> class Convention>
|
||||
Result<Hook*> addHook(void* address) {
|
||||
return Interface::addHook<Detour, Convention>("", address);
|
||||
}
|
||||
|
||||
/**
|
||||
* The same as addHook(void*, void*), but also provides
|
||||
* a display name to show it in the list of the loader.
|
||||
* Mostly for internal use but if you don't like your
|
||||
* hooks showing up like base + 0x123456 it can be useful
|
||||
*/
|
||||
template<auto Detour, template <class, class...> class Convention>
|
||||
Result<Hook*> addHook(std::string const& displayName, void* address) {
|
||||
if (this->m_mod) {
|
||||
return this->m_mod->addHook<Detour, Convention>(displayName, address);
|
||||
}
|
||||
this->m_scheduledHooks.push_back({ displayName, address, &Mod::addHook<Detour, Convention> });
|
||||
return Ok<Hook*>(nullptr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log an information. Equivalent to
|
||||
* ```
|
||||
* Mod::log() << Severity::severity << info.
|
||||
* ```
|
||||
* @param info Log information
|
||||
* @param severity Log severity
|
||||
*/
|
||||
GEODE_DLL void logInfo(std::string const& info, Severity severity);
|
||||
|
||||
GEODE_DLL void scheduleOnLoad(ScheduledFunction function);
|
||||
|
||||
friend Mod* Mod::get<void>();
|
||||
};
|
||||
|
||||
template<>
|
||||
inline Mod* Mod::get<void>() {
|
||||
return Interface::get()->m_mod;
|
||||
}
|
||||
|
||||
inline Log Log::get() {
|
||||
return Mod::get()->log();
|
||||
}
|
||||
}
|
||||
|
||||
inline const char* operator"" _spr(const char* str, size_t) {
|
||||
return geode::Mod::get()->expandSpriteName(str);
|
||||
}
|
|
@ -10,9 +10,7 @@
|
|||
#include <functional>
|
||||
#include <unordered_set>
|
||||
#include <fs/filesystem.hpp>
|
||||
#include <Geode/utils/json.hpp>
|
||||
#include "Log.hpp"
|
||||
#include <Geode/utils/VersionInfo.hpp>
|
||||
|
||||
namespace geode {
|
||||
#pragma warning(disable: 4251)
|
||||
|
@ -26,14 +24,21 @@ namespace geode {
|
|||
|
||||
class Mod;
|
||||
class Hook;
|
||||
class Log;
|
||||
class LogPtr;
|
||||
struct ModInfo;
|
||||
class VersionInfo;
|
||||
|
||||
namespace modifier {
|
||||
template<class, class, class>
|
||||
class FieldIntermediate;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The predeclaration of the implicit entry
|
||||
*/
|
||||
GEODE_API bool GEODE_CALL geode_implicit_load(geode::Mod*);
|
||||
|
||||
namespace geode {
|
||||
|
||||
class GEODE_DLL Loader {
|
||||
public:
|
||||
|
@ -49,9 +54,12 @@ namespace geode {
|
|||
};
|
||||
std::unordered_map<std::string, ModSettings> m_mods;
|
||||
};
|
||||
|
||||
using ScheduledFunction = std::function<void GEODE_CALL(void)>;
|
||||
|
||||
std::vector<ScheduledFunction> m_scheduledFunctions;
|
||||
std::unordered_map<std::string, Mod*> m_mods;
|
||||
std::vector<LogPtr*> m_logs;
|
||||
std::vector<log::Log> m_logs;
|
||||
std::ofstream m_logStream;
|
||||
std::vector<ghc::filesystem::path> m_modDirectories;
|
||||
std::vector<FailedModInfo> m_erroredMods;
|
||||
|
@ -60,25 +68,6 @@ namespace geode {
|
|||
bool m_isSetup = false;
|
||||
static bool s_unloading;
|
||||
|
||||
/**
|
||||
* Lowest supported mod version.
|
||||
* Any mod targeting a geode version
|
||||
* lower than this will not be loaded,
|
||||
* as they will be considered out-of-date.
|
||||
*/
|
||||
static constexpr VersionInfo s_supportedVersionMin { 0, 1, 0 };
|
||||
/**
|
||||
* Highest support mod version.
|
||||
* Any mod targeting a geode version
|
||||
* higher than this will not be loaded,
|
||||
* as a higher version means that
|
||||
* the user's geode is out-of-date,
|
||||
* or that the user is a time traveller
|
||||
* and has downloaded a mod from the
|
||||
* future.
|
||||
*/
|
||||
static constexpr VersionInfo s_supportedVersionMax { 0, 2, 0 };
|
||||
|
||||
Result<std::string> createTempDirectoryForMod(ModInfo const& info);
|
||||
Result<Mod*> loadModFromFile(std::string const& file);
|
||||
size_t loadModsFromDirectory(
|
||||
|
@ -88,15 +77,18 @@ namespace geode {
|
|||
|
||||
void updateAllDependencies();
|
||||
|
||||
void releaseScheduledFunctions(Mod* mod);
|
||||
|
||||
friend class Mod;
|
||||
friend class CustomLoader;
|
||||
friend struct ModInfo;
|
||||
|
||||
private:
|
||||
size_t getFieldIndexForClass(size_t hash);
|
||||
|
||||
template <class, class, class>
|
||||
friend class modifier::FieldIntermediate;
|
||||
|
||||
friend bool GEODE_CALL ::geode_implicit_load(Mod*);
|
||||
|
||||
public:
|
||||
~Loader();
|
||||
|
@ -107,8 +99,8 @@ namespace geode {
|
|||
*/
|
||||
static Loader* get();
|
||||
|
||||
VersionInfo getVersion() const;
|
||||
std::string getVersionType() const;
|
||||
static VersionInfo getVersion();
|
||||
static std::string getVersionType();
|
||||
|
||||
Result<> saveSettings();
|
||||
Result<> loadSettings();
|
||||
|
@ -133,6 +125,19 @@ namespace geode {
|
|||
*/
|
||||
ghc::filesystem::path getGeodeSaveDirectory() const;
|
||||
|
||||
/**
|
||||
* Minimum supported mod version
|
||||
*/
|
||||
static VersionInfo minModVersion();
|
||||
/**
|
||||
* Maximum supported mod version
|
||||
*/
|
||||
static VersionInfo maxModVersion();
|
||||
/**
|
||||
* Check if a mod's version is within the supported range
|
||||
*/
|
||||
static bool supportedModVersion(VersionInfo const& version);
|
||||
|
||||
/**
|
||||
* Whether mod specified with ID is enabled
|
||||
* @param id The ID of the mod
|
||||
|
@ -163,12 +168,13 @@ namespace geode {
|
|||
*/
|
||||
static bool isUnloading();
|
||||
|
||||
void pushLog(LogPtr* log);
|
||||
void popLog(LogPtr* log);
|
||||
std::vector<LogPtr*> const& getLogs() const;
|
||||
std::vector<LogPtr*> getLogs(
|
||||
std::initializer_list<Severity> severityFilter
|
||||
void pushLog(log::Log&& log);
|
||||
void popLog(log::Log* log);
|
||||
std::vector<log::Log*> getLogs(
|
||||
std::initializer_list<Severity> severityFilter = {}
|
||||
);
|
||||
|
||||
void clearLogs();
|
||||
|
||||
/**
|
||||
* You shouldn't be calling this manually,
|
||||
|
@ -176,7 +182,7 @@ namespace geode {
|
|||
* Mod::m_addResourcesToSearchPath to true
|
||||
* first
|
||||
*/
|
||||
void addModResourcesPath(Mod* mod);
|
||||
void updateModResourcePaths(Mod*);
|
||||
void updateResourcePaths();
|
||||
void updateModResources(Mod* mod);
|
||||
void updateResources();
|
||||
|
@ -219,7 +225,7 @@ namespace geode {
|
|||
* Get all mods that are a serious
|
||||
* disappointment to their parents
|
||||
*/
|
||||
std::vector<FailedModInfo> const& getFailedMods() const;
|
||||
std::vector<FailedModInfo> getFailedMods() const;
|
||||
/**
|
||||
* Unload a mod fully. This will remove it
|
||||
* from the mods list and delete the Mod. If
|
||||
|
@ -243,6 +249,23 @@ namespace geode {
|
|||
* `CCScheduler::update` is called
|
||||
* @param func Function to run
|
||||
*/
|
||||
void queueInGDThread(std::function<void GEODE_CALL(void)> func);
|
||||
void queueInGDThread(ScheduledFunction func);
|
||||
|
||||
/**
|
||||
* Run a function when the Mod is loaded. Useful if for
|
||||
* some reason you need to run some function in
|
||||
* static initialization.
|
||||
* @param func Function to run
|
||||
*/
|
||||
void scheduleOnModLoad(Mod* m, ScheduledFunction func);
|
||||
|
||||
/**
|
||||
* Open the platform-specific external console (if one exists)
|
||||
*/
|
||||
static void openPlatformConsole();
|
||||
/**
|
||||
* Close the platform-specific external console (if one exists)
|
||||
*/
|
||||
static void closePlatfromConsole();
|
||||
};
|
||||
}
|
||||
|
|
|
@ -8,132 +8,163 @@
|
|||
#include <fs/filesystem.hpp>
|
||||
#include <ccTypes.h>
|
||||
|
||||
/*namespace cocos2d {
|
||||
class CCObject;
|
||||
class CCNode;
|
||||
class CCPoint;
|
||||
class CCSize;
|
||||
class CCRect;
|
||||
class CCArray;
|
||||
}*/
|
||||
|
||||
GEODE_DLL std::ostream& operator<<(std::ostream& os, geode::Mod* mod);
|
||||
GEODE_DLL std::ostream& operator<<(std::ostream& os, cocos2d::CCObject* obj);
|
||||
GEODE_DLL std::ostream& operator<<(std::ostream& os, cocos2d::CCArray* obj);
|
||||
GEODE_DLL std::ostream& operator<<(std::ostream& os, cocos2d::CCPoint const& pos);
|
||||
GEODE_DLL std::ostream& operator<<(std::ostream& os, cocos2d::CCSize const& size);
|
||||
GEODE_DLL std::ostream& operator<<(std::ostream& os, cocos2d::CCRect const& rect);
|
||||
GEODE_DLL std::ostream& operator<<(std::ostream& os, cocos2d::ccColor3B const& color);
|
||||
GEODE_DLL std::ostream& operator<<(std::ostream& os, cocos2d::ccColor4B const& color);
|
||||
#ifdef GEODE_IS_MACOS
|
||||
namespace std {
|
||||
// <concepts> isn't working for me lmao
|
||||
template <class From, class To>
|
||||
concept convertible_to =
|
||||
std::is_convertible_v<From, To> &&
|
||||
requires {
|
||||
static_cast<To>(std::declval<From>());
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace geode {
|
||||
class Mod;
|
||||
#pragma warning(disable: 4251)
|
||||
|
||||
using log_clock = std::chrono::system_clock;
|
||||
class Mod;
|
||||
inline Mod* getMod();
|
||||
|
||||
struct GEODE_DLL LogMetadata {
|
||||
std::string m_repr;
|
||||
LogMetadata(std::string const& r) : m_repr(r) {}
|
||||
LogMetadata() {}
|
||||
virtual ~LogMetadata() {}
|
||||
};
|
||||
namespace log {
|
||||
using log_clock = std::chrono::system_clock;
|
||||
|
||||
std::string generateLogName();
|
||||
|
||||
class Log;
|
||||
class GEODE_DLL LogPtr {
|
||||
protected:
|
||||
Mod* m_sender = nullptr;
|
||||
log_clock::time_point m_time = log_clock::now();
|
||||
std::vector<LogMetadata*> m_data;
|
||||
Severity m_severity = Severity::Debug;
|
||||
|
||||
friend class Log;
|
||||
|
||||
public:
|
||||
LogPtr(Mod* Mod) : m_sender(Mod) {}
|
||||
|
||||
~LogPtr();
|
||||
|
||||
std::string toString(bool logTime = true) const;
|
||||
std::vector<LogMetadata*> const& getData() const;
|
||||
|
||||
log_clock::time_point getTime() const;
|
||||
std::string getTimeString() const;
|
||||
Mod* getSender() const;
|
||||
Severity getSeverity() const;
|
||||
|
||||
};
|
||||
|
||||
using ostream_fn_type = std::ostream&(*)(std::ostream&);
|
||||
|
||||
class GEODE_DLL Log {
|
||||
protected:
|
||||
LogPtr* m_logptr = nullptr;
|
||||
std::stringstream m_stream;
|
||||
void flush();
|
||||
|
||||
public:
|
||||
static Log get();
|
||||
|
||||
inline Log(Mod* m) : m_logptr(new LogPtr(m)) {}
|
||||
inline Log() : Log(nullptr) {}
|
||||
|
||||
Log& operator<<(ostream_fn_type);
|
||||
|
||||
Log& operator<<(Severity::type s);
|
||||
Log& operator<<(Severity s);
|
||||
std::string generateLogName();
|
||||
|
||||
std::string parse(cocos2d::CCNode*);
|
||||
template <class T>
|
||||
requires std::convertible_to<T*, cocos2d::CCNode*>
|
||||
std::string parse(T* node) {
|
||||
return parse(static_cast<cocos2d::CCNode*>(node));
|
||||
}
|
||||
std::string parse(cocos2d::CCPoint const&);
|
||||
std::string parse(cocos2d::CCSize const&);
|
||||
std::string parse(cocos2d::CCRect const&);
|
||||
std::string parse(cocos2d::CCArray*);
|
||||
std::string parse(cocos2d::ccColor3B const&);
|
||||
std::string parse(cocos2d::ccColor4B const&);
|
||||
std::string parse(cocos2d::ccColor4F const&);
|
||||
std::string parse(cocos2d::CCObject*);
|
||||
std::string parse(Mod*);
|
||||
|
||||
template <typename T>
|
||||
Log& operator<<(T item) {
|
||||
this->m_stream << item;
|
||||
//static_assert(!std::is_same<Severity, T>::value, "didnt work :(");
|
||||
return *this;
|
||||
requires requires(T b) { std::stringstream() << b; }
|
||||
std::string parse(T const& thing) {
|
||||
std::stringstream buf;
|
||||
buf << thing;
|
||||
return buf.str();
|
||||
}
|
||||
|
||||
template <typename U, typename T>
|
||||
Log& streamMeta(T t) {
|
||||
static_assert(std::is_base_of<LogMetadata, U>::value, "Metadata class must derive from geode::LogMetadata");
|
||||
struct GEODE_DLL ComponentTrait {
|
||||
virtual ~ComponentTrait() {}
|
||||
virtual std::string _toString() = 0;
|
||||
};
|
||||
|
||||
auto md = new LogMetadata;
|
||||
md->m_repr = this->m_stream.str();
|
||||
this->m_logptr->m_data.push_back(md);
|
||||
m_stream.str("");
|
||||
template <typename T>
|
||||
struct ComponentBase : public ComponentTrait {
|
||||
T m_item;
|
||||
inline ~ComponentBase() override {}
|
||||
inline ComponentBase(T const& item) : m_item(item) {}
|
||||
// specialization must implement
|
||||
inline std::string _toString() override { return parse(m_item); }
|
||||
};
|
||||
|
||||
md = new U(t);
|
||||
m_stream << t;
|
||||
md->m_repr = m_stream.str();
|
||||
this->m_logptr->m_data.push_back(md);
|
||||
m_stream.str("");
|
||||
/*template <typename T> requires requires(T b) { std::stringstream() << b; }
|
||||
struct Component<T> : ComponentBase<T> {
|
||||
inline static std::string toString(T const& thing) {
|
||||
std::stringstream buf;
|
||||
buf << thing;
|
||||
return buf.str();
|
||||
}
|
||||
};*/
|
||||
|
||||
return *this;
|
||||
class GEODE_DLL Log {
|
||||
private:
|
||||
static std::vector<std::function<void(Mod*)>>& scheduled();
|
||||
protected:
|
||||
Mod* m_sender;
|
||||
log_clock::time_point m_time;
|
||||
std::vector<ComponentTrait*> m_components;
|
||||
Severity m_severity;
|
||||
|
||||
public:
|
||||
Log(Mod* mod, Severity sev);// : m_sender(mod), m_time(log_clock::now()), m_severity(sev) {}
|
||||
Log(Log&& l) = default;
|
||||
Log& operator=(Log&& l) = default;
|
||||
bool operator==(Log const& l);
|
||||
|
||||
std::string toString(bool logTime = true) const;
|
||||
void pushToLoader();
|
||||
|
||||
inline std::vector<ComponentTrait*>& getComponents() { return m_components; }
|
||||
inline log_clock::time_point getTime() const { return m_time; }
|
||||
inline Mod* getSender() const { return m_sender; }
|
||||
inline Severity getSeverity() const { return m_severity; }
|
||||
inline ~Log() {
|
||||
for (auto comp : m_components) {
|
||||
delete comp;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename ...Args>
|
||||
friend void schedule(Severity sev, Args... args);
|
||||
|
||||
friend void GEODE_DLL releaseSchedules(Mod* m);
|
||||
};
|
||||
|
||||
void GEODE_DLL vlogImpl(Severity, Mod*, std::string_view, std::function<void(Log&)>*, size_t);
|
||||
|
||||
template <typename... Args>
|
||||
requires requires(Args... b) { (parse(b), ...); }
|
||||
void log(Severity severity, Mod* mod, std::string_view formatStr, Args... args) {
|
||||
static constexpr auto pushSomething = [](Log& log, auto something) {
|
||||
// i think this line of code is very sad
|
||||
log.getComponents().push_back(new ComponentBase(something));
|
||||
};
|
||||
|
||||
std::array<std::function<void(Log&)>, sizeof...(Args)> comps = { [&](Log& log) { pushSomething(log, args); }... };
|
||||
// tfw no std::span
|
||||
vlogImpl(severity, mod, formatStr, comps.data(), comps.size());
|
||||
}
|
||||
|
||||
~Log();
|
||||
};
|
||||
void GEODE_DLL releaseSchedules(Mod* m);
|
||||
|
||||
// geode-defined metadata functions
|
||||
template <typename ...Args>
|
||||
void schedule(Severity sev, Args... args) {
|
||||
auto m = getMod();
|
||||
if (m) return log(sev, m, args...);
|
||||
|
||||
struct ModMeta : public LogMetadata {
|
||||
Mod* m_mod;
|
||||
ModMeta(Mod* m) : m_mod(m) {}
|
||||
ModMeta(std::string const& r, Mod* m) : m_mod(m), LogMetadata(r) {}
|
||||
};
|
||||
struct GEODE_DLL CCObjectMeta : public LogMetadata {
|
||||
cocos2d::CCObject* m_obj;
|
||||
CCObjectMeta(cocos2d::CCObject* obj);
|
||||
CCObjectMeta(std::string const& r, cocos2d::CCObject* obj);
|
||||
~CCObjectMeta();
|
||||
};
|
||||
struct GEODE_DLL CCArrayMeta : public LogMetadata {
|
||||
cocos2d::CCArray* m_arr;
|
||||
CCArrayMeta(cocos2d::CCArray* arr);
|
||||
CCArrayMeta(std::string const& r, cocos2d::CCArray* arr);
|
||||
~CCArrayMeta();
|
||||
};
|
||||
Log::scheduled().push_back([=](Mod* m2){
|
||||
log(sev, m2, args...);
|
||||
});
|
||||
}
|
||||
|
||||
template <typename ...Args>
|
||||
void debug(Args... args) {
|
||||
#ifdef GEODE_DEBUG
|
||||
schedule(Severity::Debug, args...);
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename ...Args>
|
||||
void info(Args... args) { schedule(Severity::Info, args...); }
|
||||
|
||||
template <typename ...Args>
|
||||
void notice(Args... args) { schedule(Severity::Notice, args...); }
|
||||
|
||||
template <typename ...Args>
|
||||
void warn(Args... args) { schedule(Severity::Warning, args...); }
|
||||
|
||||
template <typename ...Args>
|
||||
void error(Args... args) { schedule(Severity::Error, args...); }
|
||||
|
||||
template <typename ...Args>
|
||||
void critical(Args... args) { schedule(Severity::Critical, args...); }
|
||||
|
||||
template <typename ...Args>
|
||||
void alert(Args... args) { schedule(Severity::Alert, args...); }
|
||||
|
||||
template <typename ...Args>
|
||||
void emergency(Args... args) { schedule(Severity::Emergency, args...); }
|
||||
}
|
||||
}
|
||||
GEODE_DLL geode::Log& operator<<(geode::Log&, geode::Mod*);
|
||||
GEODE_DLL geode::Log& operator<<(geode::Log&, cocos2d::CCObject*);
|
||||
GEODE_DLL geode::Log& operator<<(geode::Log&, cocos2d::CCArray*);
|
||||
|
|
|
@ -3,32 +3,39 @@
|
|||
#include <Geode/DefaultInclude.hpp>
|
||||
#include "Types.hpp"
|
||||
#include "Hook.hpp"
|
||||
#include "../utils/types.hpp"
|
||||
#include "../utils/Result.hpp"
|
||||
#include "../utils/VersionInfo.hpp"
|
||||
#include <Geode/utils/types.hpp>
|
||||
#include <Geode/utils/Result.hpp>
|
||||
#include <Geode/utils/VersionInfo.hpp>
|
||||
#include <Geode/utils/json.hpp>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <type_traits>
|
||||
#include <cocos2d.h>
|
||||
|
||||
#include "Setting.hpp"
|
||||
#include <optional>
|
||||
|
||||
class InternalLoader;
|
||||
class InternalMod;
|
||||
|
||||
namespace geode {
|
||||
namespace geode {
|
||||
struct PlatformInfo;
|
||||
|
||||
class Hook;
|
||||
class Patch;
|
||||
class Loader;
|
||||
class Log;
|
||||
class Mod;
|
||||
class Setting;
|
||||
|
||||
class Unknown;
|
||||
using unknownmemfn_t = void(Unknown::*)();
|
||||
using unknownfn_t = void(*)();
|
||||
using unknownmemfn_t = void(Unknown::*)();
|
||||
using unknownfn_t = void(*)();
|
||||
}
|
||||
|
||||
/**
|
||||
* The predeclaration of the implicit entry
|
||||
*/
|
||||
GEODE_API bool GEODE_CALL geode_implicit_load(geode::Mod*);
|
||||
|
||||
namespace geode {
|
||||
|
||||
struct Dependency {
|
||||
std::string m_id;
|
||||
|
@ -40,6 +47,11 @@ namespace geode {
|
|||
bool isUnresolved() const;
|
||||
};
|
||||
|
||||
struct IssuesInfo {
|
||||
std::string m_info;
|
||||
std::optional<std::string> m_url;
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents all the data gatherable
|
||||
* from mod.json
|
||||
|
@ -94,23 +106,31 @@ namespace geode {
|
|||
* Short & concise description of the
|
||||
* mod.
|
||||
*/
|
||||
std::string m_description = "";
|
||||
std::optional<std::string> m_description;
|
||||
/**
|
||||
* Detailed description of the mod, writtenin Markdown (see
|
||||
* https://github.com/geode-sdk/api/blob/main/include/nodes/MDTextArea.hpp)
|
||||
* for more info
|
||||
* Detailed description of the mod, writtenin Markdown (see
|
||||
* <Geode/ui/MDTextArea.hpp>) for more info
|
||||
*/
|
||||
std::string m_details = "";
|
||||
std::optional<std::string> m_details;
|
||||
/**
|
||||
* Changelog for the mod, written in Markdown (see
|
||||
* https://github.com/geode-sdk/api/blob/main/include/nodes/MDTextArea.hpp)
|
||||
* for more info
|
||||
* <Geode/ui/MDTextArea.hpp>) for more info
|
||||
*/
|
||||
std::string m_changelog = "";
|
||||
std::optional<std::string> m_changelog;
|
||||
/**
|
||||
* Git Repository of the mod.
|
||||
* Support info for the mod; this means anything to show ways to
|
||||
* support the mod's development, like donations. Written in Markdown
|
||||
* (see <Geode/ui/MDTextArea.hpp>) for more info
|
||||
*/
|
||||
std::string m_repository = "";
|
||||
std::optional<std::string> m_supportInfo;
|
||||
/**
|
||||
* Git Repository of the mod
|
||||
*/
|
||||
std::optional<std::string> m_repository;
|
||||
/**
|
||||
* Info about where users should report issues and request help
|
||||
*/
|
||||
std::optional<IssuesInfo> m_issues;
|
||||
/**
|
||||
* Dependencies
|
||||
*/
|
||||
|
@ -123,7 +143,10 @@ namespace geode {
|
|||
* Default data store values
|
||||
*/
|
||||
nlohmann::json m_defaultDataStore;
|
||||
|
||||
/**
|
||||
* Mod settings
|
||||
*/
|
||||
std::vector<std::pair<std::string, std::shared_ptr<Setting>>> m_settings;
|
||||
/**
|
||||
* Whether the mod can be disabled or not
|
||||
*/
|
||||
|
@ -143,7 +166,7 @@ namespace geode {
|
|||
/**
|
||||
* Create ModInfo from a parsed json document
|
||||
*/
|
||||
static Result<ModInfo> create(nlohmann::json const& json);
|
||||
static Result<ModInfo> create(ModJson const& json);
|
||||
|
||||
private:
|
||||
/**
|
||||
|
@ -151,7 +174,15 @@ namespace geode {
|
|||
* compatibility if we update the mod.json
|
||||
* format
|
||||
*/
|
||||
static Result<ModInfo> createFromSchemaV010(nlohmann::json const& json);
|
||||
static Result<ModInfo> createFromSchemaV010(ModJson const& json);
|
||||
|
||||
Result<> addSpecialFiles(ghc::filesystem::path const& dir);
|
||||
Result<> addSpecialFiles(cocos2d::ZipFile& zip);
|
||||
|
||||
std::vector<std::pair<
|
||||
std::string,
|
||||
std::optional<std::string>*
|
||||
>> getSpecialFiles();
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -180,9 +211,7 @@ namespace geode {
|
|||
|
||||
/**
|
||||
* @class Mod
|
||||
* Represents a Mod ingame. Inherit
|
||||
* from this class to create your own
|
||||
* mod interfaces.
|
||||
* Represents a Mod ingame.
|
||||
* @abstract
|
||||
*/
|
||||
class GEODE_DLL Mod {
|
||||
|
@ -274,8 +303,8 @@ namespace geode {
|
|||
Result<> loadPlatformBinary();
|
||||
Result<> unloadPlatformBinary();
|
||||
|
||||
Result<> saveDataStore();
|
||||
Result<> loadDataStore();
|
||||
Result<> saveSettings();
|
||||
Result<> loadSettings();
|
||||
|
||||
void postDSUpdate();
|
||||
|
||||
|
@ -299,12 +328,22 @@ namespace geode {
|
|||
friend struct ModInfo;
|
||||
friend class DataStore;
|
||||
|
||||
template<class = void>
|
||||
static inline GEODE_HIDDEN Mod* sharedMod = nullptr;
|
||||
|
||||
template<class = void>
|
||||
static inline GEODE_HIDDEN void setSharedMod(Mod* mod) {
|
||||
sharedMod<> = mod;
|
||||
}
|
||||
|
||||
friend bool GEODE_CALL ::geode_implicit_load(Mod*);
|
||||
|
||||
public:
|
||||
std::string getID() const;
|
||||
std::string getName() const;
|
||||
std::string getDeveloper() const;
|
||||
std::string getDescription() const;
|
||||
std::string getDetails() const;
|
||||
std::optional<std::string> getDescription() const;
|
||||
std::optional<std::string> getDetails() const;
|
||||
std::string getPath() const;
|
||||
VersionInfo getVersion() const;
|
||||
bool isEnabled() const;
|
||||
|
@ -317,34 +356,37 @@ namespace geode {
|
|||
ghc::filesystem::path getTempDir() const;
|
||||
ghc::filesystem::path getBinaryPath() const;
|
||||
|
||||
bool hasSettings() const;
|
||||
decltype(ModInfo::m_settings) getSettings() const;
|
||||
bool hasSetting(std::string const& key) const;
|
||||
std::shared_ptr<Setting> getSetting(std::string const& key) const;
|
||||
template<class T>
|
||||
T getSettingValue(std::string const& key) const {
|
||||
if (this->hasSetting(key)) {
|
||||
return geode::getBuiltInSettingValue<T>(
|
||||
this->getSetting(key)
|
||||
);
|
||||
}
|
||||
return T();
|
||||
}
|
||||
template<class T>
|
||||
bool setSettingValue(std::string const& key, T const& value) {
|
||||
if (this->hasSetting(key)) {
|
||||
geode::setBuiltInSettingValue<T>(this->getSetting(key), value);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mod container stored in the Interface
|
||||
* @returns nullptr if Interface is not initialized,
|
||||
* the mod pointer if it is initialized
|
||||
*/
|
||||
template<class = void>
|
||||
static inline Mod* get();
|
||||
|
||||
/**
|
||||
* Log to geode's integrated console /
|
||||
* the platform debug console.
|
||||
* @returns Reference to log stream. Make sure
|
||||
* to end your logging with geode::endl.
|
||||
*/
|
||||
Log log();
|
||||
|
||||
/**
|
||||
* Log an information. Equivalent to
|
||||
* ```
|
||||
* Mod::log() << Severity::severity << info.
|
||||
* ```
|
||||
* @param info Log infomration
|
||||
* @param severity Log severity
|
||||
*/
|
||||
void logInfo(
|
||||
std::string const& info,
|
||||
Severity severity
|
||||
);
|
||||
static inline GEODE_HIDDEN Mod* get() {
|
||||
return sharedMod<>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all hooks owned by this Mod
|
||||
|
@ -523,4 +565,18 @@ namespace geode {
|
|||
|
||||
const char* expandSpriteName(const char* name);
|
||||
};
|
||||
|
||||
/**
|
||||
* To bypass the need for cyclic dependencies,
|
||||
* this function does the exact same as Mod::get()
|
||||
* However, it can be externed, unlike Mod::get()
|
||||
* @returns Same thing Mod::get() returns
|
||||
*/
|
||||
inline GEODE_HIDDEN Mod* getMod() {
|
||||
return Mod::get();
|
||||
}
|
||||
}
|
||||
|
||||
inline const char* operator"" _spr(const char* str, size_t) {
|
||||
return geode::Mod::get()->expandSpriteName(str);
|
||||
}
|
||||
|
|
507
loader/include/Geode/loader/Setting.hpp
Normal file
507
loader/include/Geode/loader/Setting.hpp
Normal file
|
@ -0,0 +1,507 @@
|
|||
#pragma once
|
||||
|
||||
#include <Geode/DefaultInclude.hpp>
|
||||
#include <optional>
|
||||
#include <unordered_set>
|
||||
#include <Geode/utils/container.hpp>
|
||||
#include <Geode/utils/json.hpp>
|
||||
#include <Geode/utils/Result.hpp>
|
||||
#include <Geode/utils/JsonValidation.hpp>
|
||||
#include <Geode/utils/convert.hpp>
|
||||
#include <Geode/utils/platform.hpp>
|
||||
#include <regex>
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4275)
|
||||
|
||||
namespace geode {
|
||||
using ModJson = nlohmann::ordered_json;
|
||||
|
||||
class Setting;
|
||||
class SettingNode;
|
||||
class BoolSetting;
|
||||
class IntSetting;
|
||||
class FloatSetting;
|
||||
class StringSetting;
|
||||
|
||||
struct ModInfo;
|
||||
|
||||
enum class SettingType {
|
||||
Bool,
|
||||
Int,
|
||||
Float,
|
||||
String,
|
||||
File,
|
||||
Color,
|
||||
ColorAlpha,
|
||||
User,
|
||||
};
|
||||
|
||||
/**
|
||||
* Base class for all settings in Geode mods. Note that for most purposes
|
||||
* you should use the built-in setting types. If you need a custom setting
|
||||
* type however, inherit from this class. Do note that you are responsible
|
||||
* for things like storing the default value, broadcasting value change
|
||||
* events, making the setting node etc.
|
||||
*/
|
||||
class GEODE_DLL Setting :
|
||||
public std::enable_shared_from_this<Setting>
|
||||
{
|
||||
protected:
|
||||
std::string m_key;
|
||||
std::string m_modID;
|
||||
|
||||
friend struct ModInfo;
|
||||
|
||||
static Result<std::shared_ptr<Setting>> parse(
|
||||
std::string const& type,
|
||||
std::string const& key,
|
||||
JsonMaybeObject<ModJson>& obj
|
||||
);
|
||||
|
||||
public:
|
||||
virtual ~Setting() = default;
|
||||
|
||||
// Load from mod.json
|
||||
static Result<std::shared_ptr<Setting>> parse(
|
||||
std::string const& key,
|
||||
ModJson const& json
|
||||
);
|
||||
// Load value from saved settings
|
||||
virtual bool load(nlohmann::json const& json) = 0;
|
||||
// Save setting value
|
||||
virtual bool save(nlohmann::json& json) const = 0;
|
||||
|
||||
virtual SettingNode* createNode(float width) = 0;
|
||||
|
||||
void valueChanged();
|
||||
|
||||
std::string getKey() const;
|
||||
virtual SettingType getType() const = 0;
|
||||
};
|
||||
|
||||
// built-in settings' implementation details
|
||||
namespace {
|
||||
#define GEODE_INT_PARSE_SETTING_IMPL(obj, func, ...) \
|
||||
if constexpr (std::is_base_of_v<__VA_ARGS__, Class>) {\
|
||||
auto r = std::static_pointer_cast<Class>(res)->func(obj);\
|
||||
if (!r) return Err(r.error());\
|
||||
}
|
||||
|
||||
#define GEODE_INT_CONSTRAIN_SETTING_CAN_IMPL(func, ...) \
|
||||
if constexpr (std::is_base_of_v<__VA_ARGS__, Class>) {\
|
||||
auto res = static_cast<Class*>(this)->func(value);\
|
||||
if (!res) {\
|
||||
return res;\
|
||||
}\
|
||||
}
|
||||
|
||||
template<class ValueType>
|
||||
class IMinMax;
|
||||
template<class Class, class ValueType>
|
||||
class IOneOf;
|
||||
template<class Class, class ValueType>
|
||||
class IMatch;
|
||||
|
||||
class ICArrows;
|
||||
template<class ValueType>
|
||||
class ICSlider;
|
||||
class ICInput;
|
||||
class ICFileFilters;
|
||||
|
||||
template<class Class, class ValueType, SettingType Type>
|
||||
class GeodeSetting : public Setting {
|
||||
protected:
|
||||
ValueType m_default;
|
||||
ValueType m_value;
|
||||
std::optional<std::string> m_name;
|
||||
std::optional<std::string> m_description;
|
||||
bool m_canResetToDefault = true;
|
||||
|
||||
friend class Setting;
|
||||
|
||||
static Result<std::shared_ptr<Class>> parse(
|
||||
std::string const& key,
|
||||
JsonMaybeObject<ModJson>& obj
|
||||
) {
|
||||
auto res = std::make_shared<Class>();
|
||||
|
||||
res->m_key = key;
|
||||
obj.needs("default").into(res->m_default);
|
||||
obj.has("name").intoAs<std::string>(res->m_name);
|
||||
obj.has("description").intoAs<std::string>(res->m_description);
|
||||
GEODE_INT_PARSE_SETTING_IMPL(obj, parseMinMax, IMinMax<ValueType>);
|
||||
GEODE_INT_PARSE_SETTING_IMPL(obj, parseOneOf, IOneOf<Class, ValueType>);
|
||||
GEODE_INT_PARSE_SETTING_IMPL(obj, parseMatch, IMatch<Class, ValueType>);
|
||||
res->setValue(res->m_default);
|
||||
|
||||
if (auto controls = obj.has("control").obj()) {
|
||||
// every built-in setting type has a reset button
|
||||
// by default
|
||||
controls.has("can-reset").into(res->m_canResetToDefault);
|
||||
GEODE_INT_PARSE_SETTING_IMPL(controls, parseArrows, ICArrows);
|
||||
GEODE_INT_PARSE_SETTING_IMPL(controls, parseSlider, ICSlider<ValueType>);
|
||||
GEODE_INT_PARSE_SETTING_IMPL(controls, parseInput, ICInput);
|
||||
GEODE_INT_PARSE_SETTING_IMPL(controls, parseFileFilters, ICFileFilters);
|
||||
}
|
||||
|
||||
return Ok(res);
|
||||
}
|
||||
|
||||
public:
|
||||
using value_t = ValueType;
|
||||
|
||||
std::optional<std::string> getName() const {
|
||||
return m_name;
|
||||
}
|
||||
|
||||
std::string getDisplayName() const {
|
||||
return m_name.value_or(m_key);
|
||||
}
|
||||
|
||||
std::optional<std::string> getDescription() const {
|
||||
return m_description;
|
||||
}
|
||||
|
||||
ValueType getDefault() const {
|
||||
return m_default;
|
||||
}
|
||||
|
||||
ValueType getValue() const {
|
||||
return m_value;
|
||||
}
|
||||
|
||||
void setValue(ValueType const& value) {
|
||||
m_value = value;
|
||||
if constexpr (std::is_base_of_v<IMinMax<ValueType>, Class>) {
|
||||
static_cast<Class*>(this)->constrainMinMax(m_value);
|
||||
}
|
||||
if constexpr (std::is_base_of_v<IOneOf<Class, ValueType>, Class>) {
|
||||
static_cast<Class*>(this)->constrainOneOf(m_value);
|
||||
}
|
||||
if constexpr (std::is_base_of_v<IMatch<Class, ValueType>, Class>) {
|
||||
static_cast<Class*>(this)->constrainMatch(m_value);
|
||||
}
|
||||
this->valueChanged();
|
||||
}
|
||||
|
||||
Result<> isValidValue(ValueType value) {
|
||||
GEODE_INT_CONSTRAIN_SETTING_CAN_IMPL(constrainMinMax, IMinMax<ValueType>);
|
||||
GEODE_INT_CONSTRAIN_SETTING_CAN_IMPL(constrainOneOf, IOneOf<Class, ValueType>);
|
||||
GEODE_INT_CONSTRAIN_SETTING_CAN_IMPL(constrainMatch, IMatch<Class, ValueType>);
|
||||
return Ok();
|
||||
}
|
||||
|
||||
bool load(nlohmann::json const& json) override {
|
||||
auto rawJson = json;
|
||||
JsonChecker(rawJson)
|
||||
.root("[setting value]")
|
||||
.into(m_value);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool save(nlohmann::json& json) const override {
|
||||
json = m_value;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool canResetToDefault() const {
|
||||
return m_canResetToDefault;
|
||||
}
|
||||
|
||||
SettingType getType() const override {
|
||||
return Type;
|
||||
}
|
||||
};
|
||||
|
||||
template<class ValueType>
|
||||
class IMinMax {
|
||||
protected:
|
||||
std::optional<ValueType> m_min = std::nullopt;
|
||||
std::optional<ValueType> m_max = std::nullopt;
|
||||
|
||||
public:
|
||||
Result<> constrainMinMax(ValueType& value) {
|
||||
if (m_min && value < m_min.value()) {
|
||||
value = m_min.value();
|
||||
return Err(
|
||||
"Value must be between " +
|
||||
std::to_string(m_min.value()) + " and " +
|
||||
std::to_string(m_max.value())
|
||||
);
|
||||
}
|
||||
if (m_max && value > m_max.value()) {
|
||||
value = m_max.value();
|
||||
return Err(
|
||||
"Value must be between " +
|
||||
std::to_string(m_min.value()) + " and " +
|
||||
std::to_string(m_max.value())
|
||||
);
|
||||
}
|
||||
return Ok();
|
||||
}
|
||||
|
||||
Result<> parseMinMax(JsonMaybeObject<ModJson>& obj) {
|
||||
obj.has("min").intoAs<ValueType>(m_min);
|
||||
obj.has("max").intoAs<ValueType>(m_max);
|
||||
return Ok();
|
||||
}
|
||||
|
||||
std::optional<ValueType> getMin() const {
|
||||
return m_min;
|
||||
}
|
||||
std::optional<ValueType> getMax() const {
|
||||
return m_max;
|
||||
}
|
||||
};
|
||||
|
||||
template<class Class, class ValueType>
|
||||
class IOneOf {
|
||||
protected:
|
||||
std::optional<std::unordered_set<ValueType>> m_oneOf = std::nullopt;
|
||||
|
||||
public:
|
||||
Result<> constrainOneOf(ValueType& value) {
|
||||
if (m_oneOf && !m_oneOf.value().count(value)) {
|
||||
value = static_cast<Class*>(this)->getDefault();
|
||||
return Err(
|
||||
"Value must be one of " +
|
||||
utils::container::join(m_oneOf.value(), ", ")
|
||||
);
|
||||
}
|
||||
return Ok();
|
||||
}
|
||||
|
||||
Result<> parseOneOf(JsonMaybeObject<ModJson>& obj) {
|
||||
std::unordered_set<ValueType> oneOf {};
|
||||
for (auto& item : obj.has("one-of").iterate()) {
|
||||
oneOf.insert(item.get<ValueType>());
|
||||
}
|
||||
if (oneOf.size()) {
|
||||
m_oneOf = oneOf;
|
||||
}
|
||||
return Ok();
|
||||
}
|
||||
|
||||
auto getOneOf() const {
|
||||
return m_oneOf;
|
||||
}
|
||||
};
|
||||
|
||||
template<class Class, class ValueType>
|
||||
class IMatch {
|
||||
protected:
|
||||
std::optional<ValueType> m_matchRegex = std::nullopt;
|
||||
|
||||
public:
|
||||
Result<> constrainMatch(ValueType& value) {
|
||||
if (m_matchRegex) {
|
||||
auto regex = std::regex(m_matchRegex.value());
|
||||
if (!std::regex_match(value, regex)) {
|
||||
value = static_cast<Class*>(this)->getDefault();
|
||||
return Err(
|
||||
"Value must match regex " + m_matchRegex.value()
|
||||
);
|
||||
}
|
||||
}
|
||||
return Ok();
|
||||
}
|
||||
|
||||
Result<> parseMatch(JsonMaybeObject<ModJson>& obj) {
|
||||
obj.has("match").intoAs<ValueType>(m_matchRegex);
|
||||
return Ok();
|
||||
}
|
||||
|
||||
std::optional<ValueType> getMatch() const {
|
||||
return m_matchRegex;
|
||||
}
|
||||
};
|
||||
|
||||
#define GEODE_INT_DECL_SETTING_CONTROL(Name, name, default, json) \
|
||||
class IC##Name {\
|
||||
protected:\
|
||||
bool m_##name = default;\
|
||||
public:\
|
||||
Result<> parse##Name(JsonMaybeObject<ModJson>& obj) {\
|
||||
obj.has(json).into(m_##name);\
|
||||
return Ok();\
|
||||
}\
|
||||
bool has##Name() const {\
|
||||
return m_##name;\
|
||||
}\
|
||||
}
|
||||
|
||||
class ICArrows {
|
||||
protected:
|
||||
bool m_hasArrows = true;
|
||||
bool m_hasBigArrows = false;
|
||||
size_t m_arrowStep = 1;
|
||||
size_t m_bigArrowStep = 5;
|
||||
|
||||
public:
|
||||
Result<> parseArrows(JsonMaybeObject<ModJson>& obj) {
|
||||
obj.has("arrows").into(m_hasArrows);
|
||||
obj.has("arrow-step").into(m_arrowStep);
|
||||
obj.has("big-arrows").into(m_hasBigArrows);
|
||||
obj.has("big-arrow-step").into(m_bigArrowStep);
|
||||
return Ok();
|
||||
}
|
||||
|
||||
bool hasArrows() const {
|
||||
return m_hasArrows;
|
||||
}
|
||||
bool hasBigArrows() const {
|
||||
return m_hasBigArrows;
|
||||
}
|
||||
size_t getArrowStepSize() const {
|
||||
return m_arrowStep;
|
||||
}
|
||||
size_t getBigArrowStepSize() const {
|
||||
return m_bigArrowStep;
|
||||
}
|
||||
};
|
||||
|
||||
template<class ValueType>
|
||||
class ICSlider {
|
||||
protected:
|
||||
bool m_hasSlider = true;
|
||||
std::optional<ValueType> m_sliderStep = std::nullopt;
|
||||
|
||||
public:
|
||||
Result<> parseSlider(JsonMaybeObject<ModJson>& obj) {
|
||||
obj.has("slider").into(m_hasSlider);
|
||||
obj.has("slider-step").intoAs<ValueType>(m_sliderStep);
|
||||
return Ok();
|
||||
}
|
||||
|
||||
bool hasSlider() const {
|
||||
return m_hasSlider;
|
||||
}
|
||||
std::optional<ValueType> getSliderStepSize() const {
|
||||
return m_sliderStep;
|
||||
}
|
||||
};
|
||||
|
||||
class ICFileFilters {
|
||||
protected:
|
||||
using Filter = utils::file::FilePickOptions::Filter;
|
||||
|
||||
std::optional<std::vector<Filter>> m_filters = std::nullopt;
|
||||
|
||||
public:
|
||||
Result<> parseFileFilters(JsonMaybeObject<ModJson>& obj) {
|
||||
std::vector<Filter> filters {};
|
||||
for (auto& item : obj.has("filters").iterate()) {
|
||||
if (auto iobj = item.obj()) {
|
||||
Filter filter;
|
||||
iobj.has("description").into(filter.description);
|
||||
iobj.has("files").into(filter.files);
|
||||
filters.push_back(filter);
|
||||
}
|
||||
}
|
||||
if (filters.size()) {
|
||||
m_filters = filters;
|
||||
}
|
||||
return Ok();
|
||||
}
|
||||
|
||||
auto getFileFilters() const {
|
||||
return m_filters;
|
||||
}
|
||||
};
|
||||
|
||||
GEODE_INT_DECL_SETTING_CONTROL(Input, hasInput, true, "input");
|
||||
}
|
||||
|
||||
class GEODE_DLL BoolSetting :
|
||||
public GeodeSetting<BoolSetting, bool, SettingType::Bool>
|
||||
{
|
||||
public:
|
||||
SettingNode* createNode(float width) override;
|
||||
};
|
||||
|
||||
class GEODE_DLL IntSetting :
|
||||
public GeodeSetting<IntSetting, int64_t, SettingType::Int>,
|
||||
public IOneOf<IntSetting, int64_t>,
|
||||
public IMinMax<int64_t>,
|
||||
public ICArrows, public ICSlider<int64_t>, public ICInput
|
||||
{
|
||||
public:
|
||||
SettingNode* createNode(float width) override;
|
||||
};
|
||||
|
||||
class GEODE_DLL FloatSetting :
|
||||
public GeodeSetting<FloatSetting, double, SettingType::Float>,
|
||||
public IOneOf<FloatSetting, double>,
|
||||
public IMinMax<double>,
|
||||
public ICArrows, public ICSlider<double>, public ICInput
|
||||
{
|
||||
public:
|
||||
SettingNode* createNode(float width) override;
|
||||
};
|
||||
|
||||
class GEODE_DLL StringSetting :
|
||||
public GeodeSetting<StringSetting, std::string, SettingType::String>,
|
||||
public IOneOf<StringSetting, std::string>,
|
||||
public IMatch<StringSetting, std::string>
|
||||
{
|
||||
public:
|
||||
SettingNode* createNode(float width) override;
|
||||
};
|
||||
|
||||
class GEODE_DLL FileSetting :
|
||||
public GeodeSetting<FileSetting, ghc::filesystem::path, SettingType::File>,
|
||||
public ICFileFilters
|
||||
{
|
||||
public:
|
||||
SettingNode* createNode(float width) override;
|
||||
};
|
||||
|
||||
class GEODE_DLL ColorSetting :
|
||||
public GeodeSetting<ColorSetting, cocos2d::ccColor3B, SettingType::Color>
|
||||
{
|
||||
public:
|
||||
SettingNode* createNode(float width) override;
|
||||
};
|
||||
|
||||
class GEODE_DLL ColorAlphaSetting :
|
||||
public GeodeSetting<ColorAlphaSetting, cocos2d::ccColor4B, SettingType::ColorAlpha>
|
||||
{
|
||||
public:
|
||||
SettingNode* createNode(float width) override;
|
||||
};
|
||||
|
||||
// these can't be member functions because C++ is single-pass >:(
|
||||
|
||||
#define GEODE_INT_BUILTIN_SETTING_IF(type, action, ...) \
|
||||
if constexpr (__VA_ARGS__) {\
|
||||
if (setting->getType() == SettingType::type) {\
|
||||
return std::static_pointer_cast<type##Setting>(setting)->action;\
|
||||
}\
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T getBuiltInSettingValue(const std::shared_ptr<Setting> setting) {
|
||||
GEODE_INT_BUILTIN_SETTING_IF(Bool, getValue(), std::is_same_v<T, bool>)
|
||||
else GEODE_INT_BUILTIN_SETTING_IF(Float, getValue(), std::is_floating_point_v<T>)
|
||||
else GEODE_INT_BUILTIN_SETTING_IF(Int, getValue(), std::is_integral_v<T>)
|
||||
else GEODE_INT_BUILTIN_SETTING_IF(String, getValue(), std::is_same_v<T, std::string>)
|
||||
else {
|
||||
static_assert(!std::is_same_v<T, T>, "todo: implement");
|
||||
}
|
||||
return T();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void setBuiltInSettingValue(const std::shared_ptr<Setting> setting, T const& value) {
|
||||
GEODE_INT_BUILTIN_SETTING_IF(Bool, setValue(value), std::is_same_v<T, bool>)
|
||||
else GEODE_INT_BUILTIN_SETTING_IF(Float, setValue(value), std::is_floating_point_v<T>)
|
||||
else GEODE_INT_BUILTIN_SETTING_IF(Int, setValue(value), std::is_integral_v<T>)
|
||||
else GEODE_INT_BUILTIN_SETTING_IF(String, setValue(value), std::is_same_v<T, std::string>)
|
||||
else {
|
||||
static_assert(!std::is_same_v<T, T>, "todo: implement");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning(pop)
|
97
loader/include/Geode/loader/SettingEvent.hpp
Normal file
97
loader/include/Geode/loader/SettingEvent.hpp
Normal file
|
@ -0,0 +1,97 @@
|
|||
#pragma once
|
||||
|
||||
#include "Event.hpp"
|
||||
#include <optional>
|
||||
#include "Setting.hpp"
|
||||
#include "Loader.hpp"
|
||||
|
||||
namespace geode {
|
||||
class GEODE_DLL SettingChangedEvent : public Event {
|
||||
protected:
|
||||
std::string m_modID;
|
||||
std::shared_ptr<Setting> m_setting;
|
||||
|
||||
public:
|
||||
SettingChangedEvent(
|
||||
std::string const& modID,
|
||||
std::shared_ptr<Setting> setting
|
||||
);
|
||||
std::string getModID() const;
|
||||
std::shared_ptr<Setting> getSetting() const;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class SettingChangedEventHandler : public EventHandler<SettingChangedEvent> {
|
||||
public:
|
||||
using Consumer = void(*)(std::shared_ptr<T>);
|
||||
|
||||
static_assert(
|
||||
std::is_base_of_v<Setting, T>,
|
||||
"Setting must inherit from the Setting class"
|
||||
);
|
||||
|
||||
protected:
|
||||
Consumer m_consumer;
|
||||
std::string m_modID;
|
||||
std::optional<std::string> m_targetKey;
|
||||
|
||||
public:
|
||||
PassThrough handle(SettingChangedEvent* event) override {
|
||||
if (
|
||||
m_modID == event->getModID() && (
|
||||
!m_targetKey ||
|
||||
m_targetKey.value() == event->getSetting()->getKey()
|
||||
)) {
|
||||
m_consumer(std::static_pointer_cast<T>(event->getSetting()));
|
||||
}
|
||||
return PassThrough::Propagate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Listen to changes on a specific setting
|
||||
*/
|
||||
SettingChangedEventHandler(
|
||||
std::string const& modID,
|
||||
std::string const& settingID,
|
||||
Consumer handler
|
||||
) : m_modID(modID),
|
||||
m_targetKey(settingID),
|
||||
m_consumer(handler) {}
|
||||
|
||||
/**
|
||||
* Listen to changes on all of a mods' settings
|
||||
*/
|
||||
SettingChangedEventHandler(
|
||||
std::string const& modID,
|
||||
Consumer handler
|
||||
) : m_modID(modID),
|
||||
m_targetKey(std::nullopt),
|
||||
m_consumer(handler) {}
|
||||
};
|
||||
|
||||
template<class T>
|
||||
requires std::is_base_of_v<Setting, T>
|
||||
std::monostate listenForSettingChanges(
|
||||
std::string const& settingID,
|
||||
void(*callback)(std::shared_ptr<T>)
|
||||
) {
|
||||
Loader::get()->scheduleOnModLoad(getMod(), [=]() {
|
||||
static SettingChangedEventHandler<T> _(
|
||||
getMod()->getID(), settingID, callback
|
||||
);
|
||||
});
|
||||
return std::monostate();
|
||||
}
|
||||
|
||||
static std::monostate listenForAllSettingChanges(
|
||||
void(*callback)(std::shared_ptr<Setting>)
|
||||
) {
|
||||
Loader::get()->scheduleOnModLoad(getMod(), [=]() {
|
||||
static SettingChangedEventHandler<Setting> _(
|
||||
getMod()->getID(), callback
|
||||
);
|
||||
});
|
||||
return std::monostate();
|
||||
}
|
||||
}
|
||||
|
29
loader/include/Geode/loader/SettingNode.hpp
Normal file
29
loader/include/Geode/loader/SettingNode.hpp
Normal file
|
@ -0,0 +1,29 @@
|
|||
#pragma once
|
||||
|
||||
#include "Setting.hpp"
|
||||
#include <cocos2d.h>
|
||||
|
||||
namespace geode {
|
||||
class SettingNode;
|
||||
|
||||
struct GEODE_DLL SettingNodeDelegate {
|
||||
virtual void settingValueChanged(SettingNode* node);
|
||||
virtual void settingValueCommitted(SettingNode* node);
|
||||
};
|
||||
|
||||
class GEODE_DLL SettingNode : public cocos2d::CCNode {
|
||||
protected:
|
||||
std::shared_ptr<Setting> m_setting;
|
||||
SettingNodeDelegate* m_delegate = nullptr;
|
||||
|
||||
bool init(std::shared_ptr<Setting> setting);
|
||||
|
||||
public:
|
||||
void setDelegate(SettingNodeDelegate* delegate);
|
||||
|
||||
virtual void commit() = 0;
|
||||
virtual bool hasUncommittedChanges() = 0;
|
||||
virtual bool hasNonDefaultValue() = 0;
|
||||
virtual void resetToDefault() = 0;
|
||||
};
|
||||
}
|
|
@ -4,7 +4,7 @@
|
|||
#include "callconv.hpp"
|
||||
#include "common.hpp"
|
||||
#include "function.hpp"
|
||||
#include "preproc.hpp"
|
||||
#include "../platform/platform.hpp"
|
||||
#include "defaultconv.hpp"
|
||||
|
||||
namespace geode::core::meta {}
|
||||
|
|
|
@ -1,69 +0,0 @@
|
|||
#ifndef GEODE_CORE_META_PREPROC_HPP
|
||||
#define GEODE_CORE_META_PREPROC_HPP
|
||||
|
||||
#if !defined(GEODE_CALL)
|
||||
// Windows
|
||||
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__)
|
||||
#define GEODE_WINDOWS(...) __VA_ARGS__
|
||||
#define GEODE_IS_WINDOWS
|
||||
#define GEODE_IS_DESKTOP
|
||||
#define GEODE_PLATFORM_NAME "Windows"
|
||||
#define GEODE_PLATFORM_TARGET PlatformID::Windows
|
||||
#define GEODE_CALL __stdcall
|
||||
#define GEODE_PLATFORM_EXTENSION ".dll"
|
||||
#else
|
||||
#define GEODE_WINDOWS(...)
|
||||
#endif
|
||||
|
||||
// Darwin
|
||||
#if defined(__APPLE__)
|
||||
#include <TargetConditionals.h>
|
||||
#if TARGET_OS_IPHONE
|
||||
#define GEODE_MACOS(...)
|
||||
#define GEODE_IOS(...) __VA_ARGS__
|
||||
#define GEODE_IS_IOS
|
||||
#define GEODE_IS_MOBILE
|
||||
#define GEODE_PLATFORM_NAME "iOS"
|
||||
#define GEODE_PLATFORM_TARGET PlatformID::iOS
|
||||
#define GEODE_PLATFORM_EXTENSION ".dylib"
|
||||
#else
|
||||
#define GEODE_IOS(...)
|
||||
#define GEODE_MACOS(...) __VA_ARGS__
|
||||
#define GEODE_IS_MACOS
|
||||
#define GEODE_IS_DESKTOP
|
||||
#define GEODE_PLATFORM_NAME "MacOS"
|
||||
#define GEODE_PLATFORM_TARGET PlatformID::MacOS
|
||||
#define GEODE_PLATFORM_EXTENSION ".dylib"
|
||||
#endif
|
||||
#define GEODE_CALL
|
||||
#else
|
||||
#define GEODE_MACOS(...)
|
||||
#define GEODE_IOS(...)
|
||||
#endif
|
||||
|
||||
// Android
|
||||
#if defined(__ANDROID__)
|
||||
#define GEODE_ANDROID(...) __VA_ARGS__
|
||||
#define GEODE_IS_ANDROID
|
||||
#define GEODE_IS_MOBILE
|
||||
#define GEODE_PLATFORM_NAME "Android"
|
||||
#define GEODE_PLATFORM_TARGET PlatformID::Android
|
||||
#define GEODE_CALL
|
||||
#define GEODE_PLATFORM_EXTENSION ".so"
|
||||
#else
|
||||
#define GEODE_ANDROID(...)
|
||||
#endif
|
||||
|
||||
#ifndef GEODE_PLATFORM_NAME
|
||||
#error "Unsupported PlatformID!"
|
||||
#endif
|
||||
|
||||
#ifdef GEODE_EXPORTING
|
||||
#define GEODE_DLL GEODE_WINDOWS(__declspec(dllexport))
|
||||
#else
|
||||
#define GEODE_DLL GEODE_WINDOWS(__declspec(dllimport))
|
||||
#endif
|
||||
#define GEODE_API GEODE_WINDOWS() // idk where this is
|
||||
#endif
|
||||
|
||||
#endif /* GEODE_CORE_META_PREPROC_HPP */
|
|
@ -4,6 +4,6 @@
|
|||
|
||||
namespace geode::modifier {
|
||||
struct addresses {
|
||||
#include <codegenned/GeneratedAddress.hpp>
|
||||
#include <Geode/GeneratedAddress.hpp>
|
||||
};
|
||||
}
|
||||
|
|
|
@ -26,6 +26,6 @@ namespace geode::modifier {
|
|||
>> {
|
||||
constexpr static inline bool value = true;
|
||||
};
|
||||
#include <codegenned/GeneratedCompare.hpp>
|
||||
#include <Geode/GeneratedCompare.hpp>
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,22 +1,20 @@
|
|||
#pragma once
|
||||
#include <Geode/Geode.hpp>
|
||||
|
||||
#include "Traits.hpp"
|
||||
#include <Geode/loader/Loader.hpp>
|
||||
#include <vector>
|
||||
|
||||
namespace cocos2d {
|
||||
class CCNode;
|
||||
}
|
||||
|
||||
namespace geode::modifier {
|
||||
class FieldContainer : public cocos2d::CCObject {
|
||||
class FieldContainer {
|
||||
private:
|
||||
std::vector<void*> m_containedFields;
|
||||
std::vector<std::function<void(void*)>> m_destructorFunctions;
|
||||
public:
|
||||
|
||||
static FieldContainer* create() {
|
||||
auto ret = new (std::nothrow) FieldContainer;
|
||||
if (ret) {
|
||||
ret->autorelease();
|
||||
return ret;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
public:
|
||||
~FieldContainer() {
|
||||
for (auto i = 0u; i < m_containedFields.size(); i++) {
|
||||
m_destructorFunctions[i](m_containedFields[i]);
|
||||
|
@ -35,13 +33,16 @@ namespace geode::modifier {
|
|||
m_destructorFunctions.at(index) = destructor;
|
||||
return m_containedFields.at(index);
|
||||
}
|
||||
static FieldContainer* from(cocos2d::CCNode* node) {
|
||||
return node->getFieldContainer();
|
||||
}
|
||||
};
|
||||
|
||||
template<class Base, class Intermediate, class Parent>
|
||||
class FieldIntermediate {
|
||||
// Padding used for guaranteeing any member of parents
|
||||
// will be in between sizeof(Intermediate) and sizeof(Parent)
|
||||
std::max_align_t m_padding;
|
||||
uintptr_t m_padding;
|
||||
public:
|
||||
static void fieldConstructor(void* offsetField) {
|
||||
std::array<std::byte, sizeof(Parent)> parentContainer;
|
||||
|
@ -73,12 +74,9 @@ namespace geode::modifier {
|
|||
template <class=std::enable_if_t<true>>
|
||||
Parent* operator->() {
|
||||
// get the this pointer of the base
|
||||
auto node = reinterpret_cast<Parent*>(reinterpret_cast<std::byte*>(this) - offsetof(Parent, m_fields));
|
||||
auto container = reinterpret_cast<FieldContainer*>(node->getUserObject());
|
||||
if (!container) {
|
||||
container = FieldContainer::create();
|
||||
node->setUserObject(container);
|
||||
}
|
||||
auto node = reinterpret_cast<Parent*>(reinterpret_cast<std::byte*>(this) - sizeof(Base));
|
||||
static_assert(sizeof(Base) == offsetof(Parent, m_fields), "offsetof not correct");
|
||||
auto container = FieldContainer::from(node);
|
||||
static size_t index = Loader::get()->getFieldIndexForClass(typeid(Base).hash_code());
|
||||
// this pointer is offset
|
||||
auto offsetField = container->getField(index);
|
||||
|
|
|
@ -89,8 +89,8 @@ void _##Line_##Function(); \
|
|||
namespace { \
|
||||
struct _##Line_##Unique {}; \
|
||||
} \
|
||||
static inline auto _line = (Interface::get()->scheduleOnLoad( \
|
||||
&_##Line_##Function<_##Line_##Unique> \
|
||||
static inline auto _line = (Loader::get()->scheduleOnModLoad( \
|
||||
nullptr, &_##Line_##Function<_##Line_##Unique> \
|
||||
), 0); \
|
||||
template<class> \
|
||||
void _##Line_##Function()
|
||||
|
|
|
@ -3,22 +3,19 @@
|
|||
#include "Types.hpp"
|
||||
#include "Addresses.hpp"
|
||||
#include "../meta/meta.hpp"
|
||||
#include "../loader/Interface.hpp"
|
||||
#include <Geode/loader/Loader.hpp>
|
||||
#include <Geode/loader/Mod.hpp>
|
||||
#include <iostream>
|
||||
|
||||
#define GEODE_APPLY_MODIFY_FOR_FUNCTION(index, convention, className, functionName) \
|
||||
using base##index = wrap::functionName<Base, types::pure##index>; \
|
||||
using derived##index = wrap::functionName<Derived, types::pure##index>; \
|
||||
if constexpr (derived##index::uuid != nullptr && (void*)base##index::uuid != (void*)derived##index::uuid) { \
|
||||
Interface::get()->logInfo( \
|
||||
"Adding hook at function " #className "::" #functionName, \
|
||||
Severity::Debug \
|
||||
); \
|
||||
Interface::get()->addHook<derived##index::value, convention>( \
|
||||
#className "::" #functionName, \
|
||||
(void*)addresses::address##index() \
|
||||
); \
|
||||
} \
|
||||
#define GEODE_APPLY_MODIFY_FOR_FUNCTION(index, convention, className, functionName) \
|
||||
using base##index = wrap::functionName<Base, types::pure##index>; \
|
||||
using derived##index = wrap::functionName<Derived, types::pure##index>; \
|
||||
if constexpr (derived##index::uuid != nullptr && (void*)base##index::uuid != (void*)derived##index::uuid) { \
|
||||
Mod::get()->addHook<derived##index::value, convention>( \
|
||||
#className "::" #functionName, \
|
||||
(void*)addresses::address##index() \
|
||||
); \
|
||||
} \
|
||||
|
||||
|
||||
namespace geode::modifier {
|
||||
|
@ -31,7 +28,9 @@ namespace geode::modifier {
|
|||
public:
|
||||
// unordered_map<handles> idea
|
||||
ModifyBase() {
|
||||
Derived::apply();
|
||||
Loader::get()->scheduleOnModLoad(getMod(), [](){
|
||||
Derived::apply();
|
||||
});
|
||||
}
|
||||
template <class, class>
|
||||
friend class Modify;
|
||||
|
@ -45,6 +44,4 @@ namespace geode::modifier {
|
|||
static_assert(core::meta::always_false<Derived>, "Custom Modify not implemented.");
|
||||
}
|
||||
};
|
||||
|
||||
#include <codegenned/GeneratedModify.hpp>
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ namespace geode::modifier {
|
|||
using type = FunctionType*;
|
||||
};
|
||||
|
||||
using geode::core::meta::always_false;
|
||||
using ::geode::core::meta::always_false;
|
||||
/**
|
||||
* The ~unevaluated~ function that gets the appropriate
|
||||
* version of a function type from its return, parameters, and classes.
|
||||
|
|
|
@ -3,6 +3,6 @@
|
|||
|
||||
namespace geode::modifier {
|
||||
struct types {
|
||||
#include <codegenned/GeneratedType.hpp>
|
||||
#include <Geode/GeneratedType.hpp>
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
#include "Traits.hpp"
|
||||
#include "../utils/addresser.hpp"
|
||||
|
||||
#define GEODE_WRAPPER_FOR_IDENTIFIER(identifier) \
|
||||
/* Default - function Return Class::identifier(Parameters...) does not exist */ \
|
||||
|
@ -29,6 +30,7 @@ struct identifier<
|
|||
> { \
|
||||
private: \
|
||||
static Return wrapperImpl(Class* self, Parameters... ps) { \
|
||||
self = addresser::rthunkAdjust(substitute<Return(Parameters...)>(&Class::identifier), self); \
|
||||
return self->Class::identifier(ps...); \
|
||||
} \
|
||||
public: \
|
||||
|
@ -66,7 +68,7 @@ namespace geode::modifier {
|
|||
struct wrap {
|
||||
GEODE_WRAPPER_FOR_IDENTIFIER(constructor)
|
||||
GEODE_WRAPPER_FOR_IDENTIFIER(destructor)
|
||||
#include <codegenned/GeneratedWrapper.hpp>
|
||||
#include <Geode/GeneratedWrapper.hpp>
|
||||
};
|
||||
|
||||
// template <template<class, class, class=void> class Identifier, class Base, class Derived, class ...Types>
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#define GEODE_PLATFORM_NAME "Windows"
|
||||
#define GEODE_CALL __stdcall
|
||||
#define GEODE_PLATFORM_EXTENSION ".dll"
|
||||
#define GEODE_PLATFORM_SHORT_IDENTIFIER "win"
|
||||
|
||||
#ifdef GEODE_EXPORTING
|
||||
#undef GEODE_C_DLL
|
||||
|
@ -42,7 +43,8 @@
|
|||
#define GEODE_IS_IOS
|
||||
#define GEODE_IS_MOBILE
|
||||
#define GEODE_PLATFORM_NAME "iOS"
|
||||
#define GEODE_PLATFORM_EXTENSION ".dylib"
|
||||
#define GEODE_PLATFORM_EXTENSION ".ios.dylib"
|
||||
#define GEODE_PLATFORM_SHORT_IDENTIFIER "ios"
|
||||
#else
|
||||
#define GEODE_IOS(...)
|
||||
#define GEODE_MACOS(...) __VA_ARGS__
|
||||
|
@ -50,6 +52,7 @@
|
|||
#define GEODE_IS_DESKTOP
|
||||
#define GEODE_PLATFORM_NAME "MacOS"
|
||||
#define GEODE_PLATFORM_EXTENSION ".dylib"
|
||||
#define GEODE_PLATFORM_SHORT_IDENTIFIER "mac"
|
||||
#endif
|
||||
#define GEODE_CALL
|
||||
#else
|
||||
|
@ -65,6 +68,7 @@
|
|||
#define GEODE_PLATFORM_NAME "Android"
|
||||
#define GEODE_CALL
|
||||
#define GEODE_PLATFORM_EXTENSION ".so"
|
||||
#define GEODE_PLATFORM_SHORT_IDENTIFIER "android"
|
||||
#else
|
||||
#define GEODE_ANDROID(...)
|
||||
#endif
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
|
||||
#if defined(GEODE_CALL)
|
||||
#undef GEODE_CALL
|
||||
#endif
|
||||
#include "cplatform.h"
|
||||
|
||||
namespace geode {
|
||||
class PlatformID {
|
||||
|
@ -28,12 +25,16 @@ namespace geode {
|
|||
bool operator==(PlatformID const& other) const { return m_value == other.m_value; }
|
||||
bool operator<(PlatformID const& other) const { return m_value < other.m_value; }
|
||||
bool operator>(PlatformID const& other) const { return m_value > other.m_value; }
|
||||
operator int() { return m_value; }
|
||||
operator int() const { return m_value; }
|
||||
|
||||
template<class T>
|
||||
static Type cast(T t) {
|
||||
static PlatformID from(T t) {
|
||||
return static_cast<Type>(t);
|
||||
}
|
||||
template<class T>
|
||||
T to() const {
|
||||
return static_cast<T>(m_value);
|
||||
}
|
||||
|
||||
static constexpr const char* toString(Type lp) {
|
||||
switch (lp) {
|
||||
|
@ -59,20 +60,20 @@ namespace std {
|
|||
};
|
||||
}
|
||||
|
||||
// Windows
|
||||
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__)
|
||||
#if !defined(__PRETTY_FUNCTION__) && !defined(__GNUC__)
|
||||
#define GEODE_PRETTY_FUNCTION std::string(__FUNCSIG__)
|
||||
#else
|
||||
#define GEODE_PRETTY_FUNCTION std::string(__PRETTY_FUNCTION__)
|
||||
#endif
|
||||
|
||||
// Windows
|
||||
#ifdef GEODE_IS_WINDOWS
|
||||
|
||||
#define GEODE_WINDOWS(...) __VA_ARGS__
|
||||
#define GEODE_IS_WINDOWS
|
||||
#define GEODE_IS_DESKTOP
|
||||
#define GEODE_PLATFORM_NAME "Windows"
|
||||
#define GEODE_PLATFORM_TARGET PlatformID::Windows
|
||||
#define GEODE_CALL __stdcall
|
||||
#define GEODE_HIDDEN
|
||||
#define GEODE_DUPABLE __forceinline
|
||||
#define GEODE_INLINE __forceinline
|
||||
#define GEODE_VIRTUAL_CONSTEXPR
|
||||
#define GEODE_NOINLINE __declspec(noinline)
|
||||
#define GEODE_PLATFORM_EXTENSION ".dll"
|
||||
|
||||
#ifdef GEODE_EXPORTING
|
||||
#define GEODE_DLL __declspec(dllexport)
|
||||
|
@ -85,54 +86,13 @@ namespace std {
|
|||
|
||||
#include "windows.hpp"
|
||||
|
||||
#else
|
||||
#define GEODE_WINDOWS(...)
|
||||
#endif
|
||||
#elif defined(GEODE_IS_MACOS)
|
||||
|
||||
// MacOS / iOS
|
||||
#if defined(__APPLE__)
|
||||
#include <TargetConditionals.h>
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
#define GEODE_MACOS(...)
|
||||
|
||||
#define GEODE_IOS(...) __VA_ARGS__
|
||||
#define GEODE_IS_IOS
|
||||
#define GEODE_IS_MOBILE
|
||||
#define GEODE_PLATFORM_NAME "iOS"
|
||||
#define GEODE_PLATFORM_TARGET PlatformID::iOS
|
||||
#define GEODE_CALL
|
||||
#define GEODE_HIDDEN __attribute__((visibility("hidden")))
|
||||
#define GEODE_DUPABLE __attribute__((always_inline))
|
||||
#define GEODE_VIRTUAL_CONSTEXPR constexpr
|
||||
#define GEODE_NOINLINE __attribute__((noinline))
|
||||
#define GEODE_PLATFORM_EXTENSION ".dylib"
|
||||
|
||||
#ifdef GEODE_EXPORTING
|
||||
#define GEODE_DLL __attribute__((visibility("default")))
|
||||
#else
|
||||
#define GEODE_DLL
|
||||
#endif
|
||||
|
||||
#define GEODE_API extern "C" __attribute__((visibility("default")))
|
||||
#define GEODE_EXPORT __attribute__((visibility("default")))
|
||||
|
||||
#include "ios.hpp"
|
||||
|
||||
#else
|
||||
#define GEODE_IOS(...)
|
||||
|
||||
#define GEODE_MACOS(...) __VA_ARGS__
|
||||
#define GEODE_IS_MACOS
|
||||
#define GEODE_IS_DESKTOP
|
||||
#define GEODE_PLATFORM_NAME "MacOS"
|
||||
#define GEODE_PLATFORM_TARGET PlatformID::MacOS
|
||||
#define GEODE_CALL
|
||||
#define GEODE_HIDDEN __attribute__((visibility("hidden")))
|
||||
#define GEODE_DUPABLE __attribute__((always_inline))
|
||||
#define GEODE_INLINE inline __attribute__((always_inline))
|
||||
#define GEODE_VIRTUAL_CONSTEXPR constexpr
|
||||
#define GEODE_NOINLINE __attribute__((noinline))
|
||||
#define GEODE_PLATFORM_EXTENSION ".dylib"
|
||||
|
||||
#ifdef GEODE_EXPORTING
|
||||
#define GEODE_DLL __attribute__((visibility("default")))
|
||||
|
@ -144,27 +104,33 @@ namespace std {
|
|||
#define GEODE_EXPORT __attribute__((visibility("default")))
|
||||
|
||||
#include "macos.hpp"
|
||||
#endif
|
||||
|
||||
#else
|
||||
#define GEODE_IOS(...)
|
||||
#define GEODE_MACOS(...)
|
||||
#elif defined(GEODE_IS_IOS)
|
||||
|
||||
#endif
|
||||
|
||||
// Android
|
||||
#if defined(__ANDROID__)
|
||||
#define GEODE_ANDROID(...) __VA_ARGS__
|
||||
#define GEODE_IS_ANDROID
|
||||
#define GEODE_IS_MOBILE
|
||||
#define GEODE_PLATFORM_NAME "Android"
|
||||
#define GEODE_PLATFORM_TARGET PlatformID::Android
|
||||
#define GEODE_CALL
|
||||
#define GEODE_PLATFORM_TARGET PlatformID::iOS
|
||||
#define GEODE_HIDDEN __attribute__((visibility("hidden")))
|
||||
#define GEODE_DUPABLE __attribute__((always_inline))
|
||||
#define GEODE_INLINE inline __attribute__((always_inline))
|
||||
#define GEODE_VIRTUAL_CONSTEXPR constexpr
|
||||
#define GEODE_NOINLINE __attribute__((noinline))
|
||||
|
||||
#ifdef GEODE_EXPORTING
|
||||
#define GEODE_DLL __attribute__((visibility("default")))
|
||||
#else
|
||||
#define GEODE_DLL
|
||||
#endif
|
||||
|
||||
#define GEODE_API extern "C" __attribute__((visibility("default")))
|
||||
#define GEODE_EXPORT __attribute__((visibility("default")))
|
||||
|
||||
#include "ios.hpp"
|
||||
|
||||
#elif defined(GEODE_IS_ANDROID)
|
||||
|
||||
#define GEODE_PLATFORM_TARGET PlatformID::Android
|
||||
#define GEODE_HIDDEN __attribute__((visibility("hidden")))
|
||||
#define GEODE_INLINE inline __attribute__((always_inline))
|
||||
#define GEODE_VIRTUAL_CONSTEXPR constexpr
|
||||
#define GEODE_NOINLINE __attribute__((noinline))
|
||||
#define GEODE_PLATFORM_EXTENSION ".so"
|
||||
|
||||
#ifdef GEODE_EXPORTING
|
||||
#define GEODE_DLL __attribute__((visibility("default")))
|
||||
|
@ -175,12 +141,10 @@ namespace std {
|
|||
#define GEODE_API extern "C" __attribute__((visibility("default")))
|
||||
#define GEODE_EXPORT __attribute__((visibility("default")))
|
||||
|
||||
#include "windows.hpp"
|
||||
#include "android.hpp"
|
||||
|
||||
#else
|
||||
#define GEODE_ANDROID(...)
|
||||
#endif
|
||||
|
||||
#ifndef GEODE_PLATFORM_NAME
|
||||
#error "Unsupported PlatformID!"
|
||||
#error "Unsupported Platform!"
|
||||
|
||||
#endif
|
||||
|
|
25
loader/include/Geode/ui/BasedButton.hpp
Normal file
25
loader/include/Geode/ui/BasedButton.hpp
Normal file
|
@ -0,0 +1,25 @@
|
|||
#pragma once
|
||||
|
||||
#include "BasedButtonSprite.hpp"
|
||||
#include <Geode/binding/CCMenuItemToggler.hpp>
|
||||
|
||||
#pragma warning(disable : 4275)
|
||||
|
||||
namespace geode {
|
||||
class GEODE_DLL TabButton : public CCMenuItemToggler {
|
||||
public:
|
||||
static TabButton* create(
|
||||
TabBaseColor unselected,
|
||||
TabBaseColor selected,
|
||||
const char* text,
|
||||
cocos2d::CCObject* target,
|
||||
cocos2d::SEL_MenuHandler callback
|
||||
);
|
||||
|
||||
static TabButton* create(
|
||||
const char* text,
|
||||
cocos2d::CCObject* target,
|
||||
cocos2d::SEL_MenuHandler callback
|
||||
);
|
||||
};
|
||||
}
|
146
loader/include/Geode/ui/BasedButtonSprite.hpp
Normal file
146
loader/include/Geode/ui/BasedButtonSprite.hpp
Normal file
|
@ -0,0 +1,146 @@
|
|||
#pragma once
|
||||
|
||||
#include <cocos2d.h>
|
||||
|
||||
namespace geode {
|
||||
enum class CircleBaseSize {
|
||||
Tiny = 0, // Equivalent to the tiny delete button
|
||||
Small = 1, // Equivalent to most circular buttons in the editor
|
||||
Small2 = 2, // Equivalent to the trash button in the editor
|
||||
Medium = 3, // Equivalent to most buttons
|
||||
Medium2 = 4, // Equivalent to the bottom buttons in MenuLayer
|
||||
Big = 5, // Equivalent to the New button
|
||||
Big2 = 6, // Equivalent to the Account button
|
||||
Large = 7, // Equivalent to the big Play Button
|
||||
};
|
||||
|
||||
enum class CrossBaseSize {
|
||||
Small = 0,
|
||||
Huge = 1,
|
||||
};
|
||||
|
||||
enum class CircleBaseColor {
|
||||
Green = 0,
|
||||
Pink = 1,
|
||||
Gray = 2,
|
||||
Blue = 3,
|
||||
Cyan = 4,
|
||||
Geode = 5,
|
||||
};
|
||||
|
||||
enum class AccountBaseColor {
|
||||
Blue = 0,
|
||||
Gray = 1,
|
||||
Purple = 2,
|
||||
};
|
||||
|
||||
enum class IconSelectBaseColor {
|
||||
Gray = 0,
|
||||
Selected = 1,
|
||||
};
|
||||
|
||||
enum class EditorBaseColor {
|
||||
LightBlue = 0,
|
||||
Green = 1,
|
||||
Orange = 2,
|
||||
DarkGray = 3,
|
||||
Gray = 4,
|
||||
Pink = 5,
|
||||
Teal = 6,
|
||||
Aqua = 7,
|
||||
Cyan = 8,
|
||||
};
|
||||
|
||||
enum class TabBaseColor {
|
||||
Unselected = 0,
|
||||
Selected = 1,
|
||||
UnselectedDark = 2,
|
||||
};
|
||||
|
||||
enum class BaseType {
|
||||
// Circle buttons
|
||||
Circle = 0,
|
||||
// Like the buttons in the main menu
|
||||
Cross = 1,
|
||||
// Like the friend request / account buttons
|
||||
BevelledSquare = 2,
|
||||
// Like the icon select button
|
||||
IconSelect = 3,
|
||||
// Like the leaderboard buttons
|
||||
BevelledSquare2 = 4,
|
||||
// Like the buttons in the editor sidebar
|
||||
Editor = 5,
|
||||
// Like a list view tab
|
||||
Tab = 6,
|
||||
// Like the buttons in CreatorLayer
|
||||
Category = 7,
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents a GD button sprite where there's
|
||||
* an icon sprite on top another default sprite.
|
||||
* You know, it has a base. It's based.
|
||||
* lmao trademark lizbith
|
||||
*/
|
||||
class GEODE_DLL BasedButtonSprite : public cocos2d::CCSprite {
|
||||
protected:
|
||||
int m_type;
|
||||
int m_size;
|
||||
int m_color;
|
||||
cocos2d::CCNode* m_onTop = nullptr;
|
||||
|
||||
bool init(cocos2d::CCNode* ontop, int type, int size, int color);
|
||||
bool initWithSprite(const char* sprName, float sprScale, int type, int size, int color);
|
||||
bool initWithSpriteFrameName(const char* sprName, float sprScale, int type, int size, int color);
|
||||
|
||||
cocos2d::CCPoint getTopOffset() const;
|
||||
|
||||
virtual ~BasedButtonSprite();
|
||||
|
||||
public:
|
||||
static BasedButtonSprite* create(cocos2d::CCNode* ontop, int type, int size, int color);
|
||||
|
||||
cocos2d::CCNode* getTopNode() const;
|
||||
};
|
||||
|
||||
class GEODE_DLL CircleButtonSprite : public BasedButtonSprite {
|
||||
public:
|
||||
static CircleButtonSprite* create(
|
||||
cocos2d::CCNode* top,
|
||||
CircleBaseColor color = CircleBaseColor::Green,
|
||||
CircleBaseSize size = CircleBaseSize::Medium
|
||||
);
|
||||
static CircleButtonSprite* createWithSprite(
|
||||
const char* sprName,
|
||||
float sprScale = 1.f,
|
||||
CircleBaseColor color = CircleBaseColor::Green,
|
||||
CircleBaseSize size = CircleBaseSize::Medium
|
||||
);
|
||||
static CircleButtonSprite* createWithSpriteFrameName(
|
||||
const char* sprName,
|
||||
float sprScale = 1.f,
|
||||
CircleBaseColor color = CircleBaseColor::Green,
|
||||
CircleBaseSize size = CircleBaseSize::Medium
|
||||
);
|
||||
};
|
||||
|
||||
class GEODE_DLL EditorButtonSprite : public BasedButtonSprite {
|
||||
public:
|
||||
static EditorButtonSprite* create(cocos2d::CCNode* top, EditorBaseColor color);
|
||||
static EditorButtonSprite* createWithSprite(
|
||||
const char* sprName,
|
||||
float sprScale = 1.f,
|
||||
EditorBaseColor color = EditorBaseColor::Green
|
||||
);
|
||||
static EditorButtonSprite* createWithSpriteFrameName(
|
||||
const char* sprName,
|
||||
float sprScale = 1.f,
|
||||
EditorBaseColor color = EditorBaseColor::Green
|
||||
);
|
||||
};
|
||||
|
||||
class GEODE_DLL TabButtonSprite : public BasedButtonSprite {
|
||||
public:
|
||||
static TabButtonSprite* create(const char* text, TabBaseColor color);
|
||||
};
|
||||
}
|
57
loader/include/Geode/ui/ColorPickPopup.hpp
Normal file
57
loader/include/Geode/ui/ColorPickPopup.hpp
Normal file
|
@ -0,0 +1,57 @@
|
|||
#include "Popup.hpp"
|
||||
#include "InputNode.hpp"
|
||||
|
||||
#include <Geode/binding/TextInputDelegate.hpp>
|
||||
|
||||
namespace geode {
|
||||
class ColorPickPopupDelegate {
|
||||
public:
|
||||
virtual void updateColor(cocos2d::ccColor4B const& color) {}
|
||||
};
|
||||
|
||||
class ColorPickPopup :
|
||||
public Popup<cocos2d::ccColor4B const&, bool>,
|
||||
public cocos2d::extension::ColorPickerDelegate,
|
||||
public TextInputDelegate
|
||||
{
|
||||
protected:
|
||||
cocos2d::ccColor4B m_color;
|
||||
cocos2d::ccColor4B m_originalColor;
|
||||
cocos2d::extension::CCControlColourPicker* m_picker;
|
||||
Slider* m_opacitySlider = nullptr;
|
||||
InputNode* m_rInput;
|
||||
InputNode* m_gInput;
|
||||
InputNode* m_bInput;
|
||||
InputNode* m_hexInput;
|
||||
InputNode* m_opacityInput = nullptr;
|
||||
ColorPickPopupDelegate* m_delegate = nullptr;
|
||||
cocos2d::CCSprite* m_newColorSpr;
|
||||
CCMenuItemSpriteExtra* m_resetBtn;
|
||||
|
||||
static constexpr auto TAG_OPACITY_INPUT = 0;
|
||||
static constexpr auto TAG_R_INPUT = 1;
|
||||
static constexpr auto TAG_G_INPUT = 2;
|
||||
static constexpr auto TAG_B_INPUT = 3;
|
||||
static constexpr auto TAG_HEX_INPUT = 4;
|
||||
|
||||
bool setup(cocos2d::ccColor4B const& color, bool isRGBA) override;
|
||||
|
||||
void onOpacitySlider(cocos2d::CCObject* sender);
|
||||
void onReset(cocos2d::CCObject* sender);
|
||||
|
||||
void textChanged(CCTextInputNode* input) override;
|
||||
void colorValueChanged(cocos2d::ccColor3B color) override;
|
||||
|
||||
void updateState(cocos2d::CCNode* except = nullptr);
|
||||
|
||||
static ColorPickPopup* create(cocos2d::ccColor4B const& color, bool isRGBA);
|
||||
|
||||
public:
|
||||
static ColorPickPopup* create(bool isRGBA);
|
||||
static ColorPickPopup* create(cocos2d::ccColor3B const& color);
|
||||
static ColorPickPopup* create(cocos2d::ccColor4B const& color);
|
||||
|
||||
void setColorTarget(cocos2d::CCSprite* spr);
|
||||
void setDelegate(ColorPickPopupDelegate* delegate);
|
||||
};
|
||||
}
|
23
loader/include/Geode/ui/GeodeUI.hpp
Normal file
23
loader/include/Geode/ui/GeodeUI.hpp
Normal file
|
@ -0,0 +1,23 @@
|
|||
#pragma once
|
||||
|
||||
#include "../loader/Mod.hpp"
|
||||
|
||||
namespace geode {
|
||||
/**
|
||||
* Open the Geode mods list
|
||||
*/
|
||||
GEODE_DLL void openModsList();
|
||||
/**
|
||||
* Open the info popup for a mod
|
||||
*/
|
||||
GEODE_DLL void openInfoPopup(Mod* mod);
|
||||
/**
|
||||
* Open the store page for a mod (if it exists)
|
||||
*/
|
||||
GEODE_DLL void openIndexPopup(Mod* mod);
|
||||
/**
|
||||
* Open the settings popup for a mod (if it has any settings)
|
||||
*/
|
||||
GEODE_DLL void openSettingsPopup(Mod* mod);
|
||||
}
|
||||
|
55
loader/include/Geode/ui/IconButtonSprite.hpp
Normal file
55
loader/include/Geode/ui/IconButtonSprite.hpp
Normal file
|
@ -0,0 +1,55 @@
|
|||
#pragma once
|
||||
|
||||
#include <cocos2d.h>
|
||||
|
||||
namespace cocos2d::extension {
|
||||
class CCScale9Sprite;
|
||||
}
|
||||
|
||||
namespace geode {
|
||||
class GEODE_DLL IconButtonSprite :
|
||||
public cocos2d::CCSprite,
|
||||
public cocos2d::CCLabelProtocol
|
||||
{
|
||||
protected:
|
||||
cocos2d::extension::CCScale9Sprite* m_bg = nullptr;
|
||||
cocos2d::CCLabelBMFont* m_label = nullptr;
|
||||
cocos2d::CCNode* m_icon = nullptr;
|
||||
|
||||
bool init(
|
||||
const char* bg,
|
||||
bool bgIsFrame,
|
||||
cocos2d::CCNode* icon,
|
||||
const char* text,
|
||||
const char* font
|
||||
);
|
||||
|
||||
void updateLayout();
|
||||
|
||||
IconButtonSprite() = default;
|
||||
IconButtonSprite(IconButtonSprite&&) = delete;
|
||||
IconButtonSprite& operator=(IconButtonSprite&&) = delete;
|
||||
|
||||
public:
|
||||
static IconButtonSprite* create(
|
||||
const char* bg,
|
||||
cocos2d::CCNode* icon,
|
||||
const char* text,
|
||||
const char* font
|
||||
);
|
||||
static IconButtonSprite* createWithSpriteFrameName(
|
||||
const char* bg,
|
||||
cocos2d::CCNode* icon,
|
||||
const char* text,
|
||||
const char* font
|
||||
);
|
||||
|
||||
void setBG(const char* bg, bool isFrame);
|
||||
|
||||
void setIcon(cocos2d::CCNode* icon);
|
||||
cocos2d::CCNode* getIcon() const;
|
||||
|
||||
void setString(const char* label) override;
|
||||
const char* getString() override;
|
||||
};
|
||||
}
|
55
loader/include/Geode/ui/InputNode.hpp
Normal file
55
loader/include/Geode/ui/InputNode.hpp
Normal file
|
@ -0,0 +1,55 @@
|
|||
#pragma once
|
||||
|
||||
#include <cocos2d.h>
|
||||
|
||||
namespace geode {
|
||||
class GEODE_DLL InputNode : public cocos2d::CCMenuItem {
|
||||
protected:
|
||||
cocos2d::extension::CCScale9Sprite* m_bgSprite;
|
||||
CCTextInputNode* m_input;
|
||||
|
||||
bool init(float, float, const char*, const char*, std::string const&, int);
|
||||
bool init(float, const char*, const char*, std::string const&, int);
|
||||
|
||||
public:
|
||||
static InputNode* create(
|
||||
float width,
|
||||
const char* placeholder,
|
||||
const char* fontFile,
|
||||
std::string const& filter,
|
||||
int limit
|
||||
);
|
||||
static InputNode* create(
|
||||
float width,
|
||||
const char* placeholder,
|
||||
std::string const& filter,
|
||||
int limit
|
||||
);
|
||||
static InputNode* create(
|
||||
float width,
|
||||
const char* placeholder,
|
||||
std::string const& filter
|
||||
);
|
||||
static InputNode* create(
|
||||
float width,
|
||||
const char* placeholder,
|
||||
const char* fontFile
|
||||
);
|
||||
static InputNode* create(
|
||||
float width,
|
||||
const char* placeholder
|
||||
);
|
||||
|
||||
void activate() override;
|
||||
|
||||
CCTextInputNode* getInput() const;
|
||||
cocos2d::extension::CCScale9Sprite* getBG() const;
|
||||
|
||||
void setEnabled(bool enabled) override;
|
||||
|
||||
void setString(std::string const&);
|
||||
const char* getString();
|
||||
};
|
||||
}
|
||||
|
||||
|
49
loader/include/Geode/ui/ListView.hpp
Normal file
49
loader/include/Geode/ui/ListView.hpp
Normal file
|
@ -0,0 +1,49 @@
|
|||
#pragma once
|
||||
|
||||
#include <Geode/binding/TableViewCell.hpp>
|
||||
#include <Geode/binding/CustomListView.hpp>
|
||||
|
||||
namespace geode {
|
||||
class GEODE_DLL GenericListCell : public TableViewCell {
|
||||
protected:
|
||||
GenericListCell(const char* name, cocos2d::CCSize size);
|
||||
|
||||
void draw() override;
|
||||
|
||||
public:
|
||||
static GenericListCell* create(const char* key, cocos2d::CCSize size);
|
||||
|
||||
void updateBGColor(int index);
|
||||
};
|
||||
|
||||
/**
|
||||
* Class for a generic scrollable list of
|
||||
* items like the level list in GD
|
||||
*/
|
||||
class GEODE_DLL ListView : public CustomListView {
|
||||
protected:
|
||||
void setupList() override;
|
||||
TableViewCell* getListCell(const char* key) override;
|
||||
void loadCell(TableViewCell* cell, unsigned int index) override;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Create a generic scrollable list of
|
||||
* items
|
||||
* @param items Nodes to add as children
|
||||
* @param itemHeight Height of each child
|
||||
* @param width Width of the list
|
||||
* @param height Height of the list
|
||||
* @returns The created ListView, or nullptr
|
||||
* on error
|
||||
*/
|
||||
static ListView* create(
|
||||
cocos2d::CCArray* items,
|
||||
float itemHeight = 40.f,
|
||||
float width = 358.f,
|
||||
float height = 220.f
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
|
42
loader/include/Geode/ui/MDPopup.hpp
Normal file
42
loader/include/Geode/ui/MDPopup.hpp
Normal file
|
@ -0,0 +1,42 @@
|
|||
#pragma once
|
||||
|
||||
#include "MDTextArea.hpp"
|
||||
#include "Popup.hpp"
|
||||
|
||||
namespace geode {
|
||||
/**
|
||||
* FLAlertLayer with support for Markdown. See <Geode/ui/MDTextArea.hpp>
|
||||
* for details on what features of MD are supported.
|
||||
*/
|
||||
class MDPopup : public Popup<
|
||||
std::string const&,
|
||||
std::string const&,
|
||||
const char*,
|
||||
const char*,
|
||||
std::function<void(bool)>
|
||||
> {
|
||||
protected:
|
||||
std::function<void(bool)> m_onClick = nullptr;
|
||||
|
||||
bool setup(
|
||||
std::string const& title,
|
||||
std::string const& info,
|
||||
const char* btn1,
|
||||
const char* btn2,
|
||||
std::function<void(bool)> onClick
|
||||
) override;
|
||||
|
||||
void onBtn(CCObject*);
|
||||
|
||||
static float estimateHeight(std::string const& content);
|
||||
|
||||
public:
|
||||
static MDPopup* create(
|
||||
std::string const& title,
|
||||
std::string const& content,
|
||||
const char* btn1,
|
||||
const char* btn2 = nullptr,
|
||||
std::function<void(bool)> onClick = nullptr
|
||||
);
|
||||
};
|
||||
}
|
75
loader/include/Geode/ui/MDTextArea.hpp
Normal file
75
loader/include/Geode/ui/MDTextArea.hpp
Normal file
|
@ -0,0 +1,75 @@
|
|||
#pragma once
|
||||
|
||||
#include <Geode/binding/FLAlertLayerProtocol.hpp>
|
||||
#include "TextRenderer.hpp"
|
||||
#include "ScrollLayer.hpp"
|
||||
|
||||
struct MDParser;
|
||||
class CCScrollLayerExt;
|
||||
|
||||
namespace geode {
|
||||
/**
|
||||
* TextArea for static markdown content. Supports the
|
||||
* following features:
|
||||
* - Links
|
||||
* - Images (sprites & spritesheets)
|
||||
* - Headings
|
||||
* - Paragraphs
|
||||
* - Code blocks
|
||||
* - Code spans
|
||||
* - TextArea color tags (<cr>, <cy>, etc.)
|
||||
* - Strikethrough
|
||||
* - Underline
|
||||
* - Bold & italic
|
||||
* - Horizontal rules
|
||||
* - Lists
|
||||
* Note that links also have some special protocols.
|
||||
* Use `user:<id>` or `user:<name>` to link to a GD
|
||||
* account; `level:<id>` to link to a GD level and
|
||||
* `mod:<id>` to link to another Geode mod.
|
||||
*/
|
||||
class GEODE_DLL MDTextArea :
|
||||
public cocos2d::CCLayer,
|
||||
public cocos2d::CCLabelProtocol,
|
||||
public FLAlertLayerProtocol
|
||||
{
|
||||
protected:
|
||||
std::string m_text;
|
||||
cocos2d::CCSize m_size;
|
||||
cocos2d::extension::CCScale9Sprite* m_bgSprite = nullptr;
|
||||
cocos2d::CCMenu* m_content = nullptr;
|
||||
CCScrollLayerExt* m_scrollLayer = nullptr;
|
||||
TextRenderer* m_renderer = nullptr;
|
||||
|
||||
bool init(std::string const& str, cocos2d::CCSize const& size);
|
||||
|
||||
virtual ~MDTextArea();
|
||||
|
||||
void onLink(CCObject*);
|
||||
void onGDProfile(CCObject*);
|
||||
void FLAlert_Clicked(FLAlertLayer*, bool btn) override;
|
||||
|
||||
friend struct ::MDParser;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Create a markdown text area. See class
|
||||
* documentation for details on supported
|
||||
* features & notes.
|
||||
* @param str String to render
|
||||
* @param size Size of the textarea
|
||||
*/
|
||||
static MDTextArea* create(std::string const& str, cocos2d::CCSize const& size);
|
||||
|
||||
/**
|
||||
* Update the label's content; call
|
||||
* sparingly as rendering may be slow
|
||||
*/
|
||||
void updateLabel();
|
||||
|
||||
void setString(const char* text) override;
|
||||
const char* getString() override;
|
||||
|
||||
CCScrollLayerExt* getScrollLayer() const;
|
||||
};
|
||||
}
|
188
loader/include/Geode/ui/Notification.hpp
Normal file
188
loader/include/Geode/ui/Notification.hpp
Normal file
|
@ -0,0 +1,188 @@
|
|||
#pragma once
|
||||
|
||||
#include <cocos2d.h>
|
||||
#include "SceneManager.hpp"
|
||||
#include <chrono>
|
||||
#include "../utils/Ref.hpp"
|
||||
|
||||
namespace geode {
|
||||
enum class NotificationLocation {
|
||||
TopLeft,
|
||||
TopCenter,
|
||||
TopRight,
|
||||
BottomLeft,
|
||||
BottomCenter,
|
||||
BottomRight,
|
||||
};
|
||||
|
||||
static constexpr float DEFAULT_NOTIFICATION_TIME = 4.f;
|
||||
static constexpr NotificationLocation PLATFORM_NOTIFICATION_LOCATION =
|
||||
#ifdef GEODE_IS_DESKTOP
|
||||
NotificationLocation::BottomRight;
|
||||
#else
|
||||
NotificationLocation::TopCenter;
|
||||
#endif
|
||||
|
||||
class Notification;
|
||||
class NotificationManager;
|
||||
|
||||
struct GEODE_DLL NotificationBuilder {
|
||||
Mod* m_owner = Mod::get();
|
||||
std::string m_title = "";
|
||||
std::string m_text = "";
|
||||
std::string m_icon = "GJ_infoIcon_001.png";
|
||||
Ref<cocos2d::CCNode> m_iconNode = nullptr;
|
||||
std::string m_bg = "GJ_square02.png";
|
||||
std::function<void(Notification*)> m_callback = nullptr;
|
||||
float m_time = DEFAULT_NOTIFICATION_TIME;
|
||||
NotificationLocation m_location = PLATFORM_NOTIFICATION_LOCATION;
|
||||
bool m_hideOnClick = true;
|
||||
|
||||
inline NotificationBuilder& from(Mod* owner) {
|
||||
m_owner = owner;
|
||||
return *this;
|
||||
}
|
||||
inline NotificationBuilder& title(std::string const& title) {
|
||||
m_title = title;
|
||||
return *this;
|
||||
}
|
||||
inline NotificationBuilder& text(std::string const& text) {
|
||||
m_text = text;
|
||||
return *this;
|
||||
}
|
||||
inline NotificationBuilder& icon(std::string const& icon) {
|
||||
m_icon = icon;
|
||||
m_iconNode = nullptr;
|
||||
return *this;
|
||||
}
|
||||
inline NotificationBuilder& icon(cocos2d::CCNode* icon) {
|
||||
m_icon = "";
|
||||
m_iconNode = icon;
|
||||
return *this;
|
||||
}
|
||||
inline NotificationBuilder& loading() {
|
||||
auto spr = cocos2d::CCSprite::create("loadingCircle.png");
|
||||
spr->runAction(cocos2d::CCRepeat::create(
|
||||
cocos2d::CCRotateBy::create(1.f, 360.f), 40000
|
||||
));
|
||||
spr->setBlendFunc({ GL_ONE, GL_ONE });
|
||||
return this->icon(spr);
|
||||
}
|
||||
inline NotificationBuilder& bg(std::string const& bg) {
|
||||
m_bg = bg;
|
||||
return *this;
|
||||
}
|
||||
inline NotificationBuilder& location(NotificationLocation location) {
|
||||
m_location = location;
|
||||
return *this;
|
||||
}
|
||||
inline NotificationBuilder& time(float time) {
|
||||
m_time = time;
|
||||
return *this;
|
||||
}
|
||||
inline NotificationBuilder& stay() {
|
||||
m_time = .0f;
|
||||
return *this;
|
||||
}
|
||||
inline NotificationBuilder& clicked(
|
||||
std::function<void(Notification*)> cb,
|
||||
bool hide = true
|
||||
) {
|
||||
m_callback = cb;
|
||||
m_hideOnClick = hide;
|
||||
return *this;
|
||||
}
|
||||
Notification* show();
|
||||
};
|
||||
|
||||
class GEODE_DLL Notification : public cocos2d::CCLayer {
|
||||
protected:
|
||||
Mod* m_owner;
|
||||
std::function<void(Notification*)> m_callback = nullptr;
|
||||
cocos2d::extension::CCScale9Sprite* m_bg;
|
||||
cocos2d::CCNode* m_icon = nullptr;
|
||||
cocos2d::CCLabelBMFont* m_title = nullptr;
|
||||
Ref<cocos2d::CCArray> m_labels = nullptr;
|
||||
cocos2d::CCPoint m_showDest;
|
||||
cocos2d::CCPoint m_hideDest;
|
||||
cocos2d::CCPoint m_posAtTouchStart;
|
||||
NotificationLocation m_location;
|
||||
float m_time;
|
||||
bool m_hiding = false;
|
||||
bool m_clicking;
|
||||
bool m_hovered;
|
||||
bool m_hideOnClicked = true;
|
||||
float m_targetScale = 1.f;
|
||||
|
||||
bool init(
|
||||
Mod* owner,
|
||||
std::string const& title,
|
||||
std::string const& text,
|
||||
cocos2d::CCNode* icon,
|
||||
const char* bg,
|
||||
std::function<void(Notification*)> callback,
|
||||
bool hideOnClick
|
||||
);
|
||||
|
||||
Notification();
|
||||
virtual ~Notification();
|
||||
|
||||
bool ccTouchBegan(
|
||||
cocos2d::CCTouch* touch, cocos2d::CCEvent* event
|
||||
) override;
|
||||
void ccTouchEnded(
|
||||
cocos2d::CCTouch* touch, cocos2d::CCEvent* event
|
||||
) override;
|
||||
void ccTouchMoved(
|
||||
cocos2d::CCTouch* touch, cocos2d::CCEvent* event
|
||||
) override;
|
||||
void registerWithTouchDispatcher() override;
|
||||
|
||||
void clicked();
|
||||
|
||||
void animateIn();
|
||||
void animateOut();
|
||||
void animateOutClicked();
|
||||
void animateClicking();
|
||||
|
||||
void hidden();
|
||||
void showForReal();
|
||||
|
||||
friend class NotificationManager;
|
||||
|
||||
public:
|
||||
static Notification* create(
|
||||
Mod* owner,
|
||||
std::string const& title,
|
||||
std::string const& text,
|
||||
cocos2d::CCNode* icon,
|
||||
const char* bg,
|
||||
std::function<void(Notification*)> callback,
|
||||
bool hideOnClick
|
||||
);
|
||||
static NotificationBuilder build();
|
||||
|
||||
void show(
|
||||
NotificationLocation = PLATFORM_NOTIFICATION_LOCATION,
|
||||
float time = DEFAULT_NOTIFICATION_TIME
|
||||
);
|
||||
void hide();
|
||||
};
|
||||
|
||||
class NotificationManager {
|
||||
protected:
|
||||
std::unordered_map<
|
||||
NotificationLocation, std::vector<Ref<Notification>>
|
||||
> m_notifications;
|
||||
|
||||
void push(Notification*);
|
||||
void pop(Notification*);
|
||||
|
||||
bool isInQueue(Notification*);
|
||||
|
||||
friend class Notification;
|
||||
|
||||
public:
|
||||
static NotificationManager* get();
|
||||
};
|
||||
}
|
117
loader/include/Geode/ui/Popup.hpp
Normal file
117
loader/include/Geode/ui/Popup.hpp
Normal file
|
@ -0,0 +1,117 @@
|
|||
#pragma once
|
||||
|
||||
#include <Geode/binding/FLAlertLayer.hpp>
|
||||
#include <Geode/binding/CCMenuItemSpriteExtra.hpp>
|
||||
|
||||
namespace geode {
|
||||
template<typename... InitArgs>
|
||||
class Popup : public FLAlertLayer {
|
||||
protected:
|
||||
cocos2d::CCSize m_size;
|
||||
cocos2d::extension::CCScale9Sprite* m_bgSprite;
|
||||
cocos2d::CCLabelBMFont* m_title = nullptr;
|
||||
CCMenuItemSpriteExtra* m_closeBtn;
|
||||
|
||||
bool init(
|
||||
float width,
|
||||
float height,
|
||||
InitArgs... args,
|
||||
const char* bg = "GJ_square01.png",
|
||||
cocos2d::CCRect bgRect = { 0, 0, 80, 80 }
|
||||
) {
|
||||
auto winSize = cocos2d::CCDirector::sharedDirector()->getWinSize();
|
||||
m_size = cocos2d::CCSize { width, height };
|
||||
|
||||
if (!this->initWithColor({ 0, 0, 0, 105 })) return false;
|
||||
m_mainLayer = cocos2d::CCLayer::create();
|
||||
this->addChild(m_mainLayer);
|
||||
|
||||
m_bgSprite = cocos2d::extension::CCScale9Sprite::create(bg, bgRect);
|
||||
m_bgSprite->setContentSize(m_size);
|
||||
m_bgSprite->setPosition(winSize.width / 2, winSize.height / 2);
|
||||
m_mainLayer->addChild(m_bgSprite);
|
||||
|
||||
m_buttonMenu = cocos2d::CCMenu::create();
|
||||
m_buttonMenu->setZOrder(100);
|
||||
m_mainLayer->addChild(m_buttonMenu);
|
||||
|
||||
cocos2d::CCDirector::sharedDirector()->getTouchDispatcher()->incrementForcePrio(2);
|
||||
this->registerWithTouchDispatcher();
|
||||
|
||||
auto closeSpr = cocos2d::CCSprite::createWithSpriteFrameName("GJ_closeBtn_001.png");
|
||||
closeSpr->setScale(.8f);
|
||||
|
||||
m_closeBtn = CCMenuItemSpriteExtra::create(
|
||||
closeSpr, this, (cocos2d::SEL_MenuHandler)(&Popup::onClose)
|
||||
);
|
||||
m_closeBtn->setPosition(
|
||||
-m_size.width / 2 + 3.f,
|
||||
m_size.height / 2 - 3.f
|
||||
);
|
||||
m_buttonMenu->addChild(m_closeBtn);
|
||||
|
||||
if (!setup(std::forward<InitArgs>(args)...)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this->setKeypadEnabled(true);
|
||||
this->setTouchEnabled(true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool setup(InitArgs... args) = 0;
|
||||
|
||||
void keyDown(cocos2d::enumKeyCodes key) {
|
||||
if (key == cocos2d::enumKeyCodes::KEY_Escape) return this->onClose(nullptr);
|
||||
if (key == cocos2d::enumKeyCodes::KEY_Space) return;
|
||||
return FLAlertLayer::keyDown(key);
|
||||
}
|
||||
|
||||
virtual void onClose(cocos2d::CCObject*) {
|
||||
this->setKeyboardEnabled(false);
|
||||
this->removeFromParentAndCleanup(true);
|
||||
}
|
||||
|
||||
void setTitle(
|
||||
const char* title,
|
||||
const char* font = "goldFont.fnt",
|
||||
float scale = .7f,
|
||||
float offset = 20.f
|
||||
) {
|
||||
if (m_title) {
|
||||
m_title->setString(title);
|
||||
} else {
|
||||
auto winSize = cocos2d::CCDirector::sharedDirector()->getWinSize();
|
||||
m_title = cocos2d::CCLabelBMFont::create(title, font);
|
||||
m_title->setPosition(
|
||||
winSize.width / 2,
|
||||
winSize.height / 2 + m_size.height / 2 - offset
|
||||
);
|
||||
m_mainLayer->addChild(m_title, 2);
|
||||
}
|
||||
m_title->limitLabelWidth(m_size.width - 20.f, scale, .1f);
|
||||
}
|
||||
};
|
||||
|
||||
GEODE_DLL FLAlertLayer* createQuickPopup(
|
||||
const char* title,
|
||||
std::string const& content,
|
||||
const char* btn1,
|
||||
const char* btn2,
|
||||
std::function<void(FLAlertLayer*, bool)> selected,
|
||||
bool doShow = true
|
||||
);
|
||||
|
||||
GEODE_DLL FLAlertLayer* createQuickPopup(
|
||||
const char* title,
|
||||
std::string const& content,
|
||||
const char* btn1,
|
||||
const char* btn2,
|
||||
float width,
|
||||
std::function<void(FLAlertLayer*, bool)> selected,
|
||||
bool doShow = true
|
||||
);
|
||||
}
|
||||
|
||||
|
25
loader/include/Geode/ui/SceneManager.hpp
Normal file
25
loader/include/Geode/ui/SceneManager.hpp
Normal file
|
@ -0,0 +1,25 @@
|
|||
#pragma once
|
||||
|
||||
namespace cocos2d {
|
||||
class CCArray;
|
||||
class CCNode;
|
||||
}
|
||||
|
||||
namespace geode {
|
||||
class GEODE_DLL SceneManager {
|
||||
protected:
|
||||
cocos2d::CCArray* m_persistedNodes;
|
||||
|
||||
bool setup();
|
||||
|
||||
virtual ~SceneManager();
|
||||
|
||||
public:
|
||||
static SceneManager* get();
|
||||
|
||||
void keepAcrossScenes(cocos2d::CCNode* node);
|
||||
void forget(cocos2d::CCNode* node);
|
||||
|
||||
void willSwitchToScene(cocos2d::CCScene* scene);
|
||||
};
|
||||
}
|
49
loader/include/Geode/ui/ScrollLayer.hpp
Normal file
49
loader/include/Geode/ui/ScrollLayer.hpp
Normal file
|
@ -0,0 +1,49 @@
|
|||
#pragma once
|
||||
|
||||
#include <Geode/binding/CCContentLayer.hpp>
|
||||
#include <Geode/binding/CCScrollLayerExt.hpp>
|
||||
|
||||
namespace geode {
|
||||
/**
|
||||
* CCContentLayer expects all of its children
|
||||
* to be TableViewCells, which is not ideal for
|
||||
* a generic content layer
|
||||
*/
|
||||
class GEODE_DLL GenericContentLayer : public CCContentLayer {
|
||||
public:
|
||||
static GenericContentLayer* create(
|
||||
float width, float height
|
||||
);
|
||||
|
||||
void setPosition(cocos2d::CCPoint const& pos) override;
|
||||
};
|
||||
|
||||
class GEODE_DLL ScrollLayer : public CCScrollLayerExt {
|
||||
protected:
|
||||
bool m_scrollWheelEnabled;
|
||||
|
||||
ScrollLayer(
|
||||
cocos2d::CCRect const& rect,
|
||||
bool scrollWheelEnabled,
|
||||
bool vertical
|
||||
);
|
||||
|
||||
bool ccTouchBegan(cocos2d::CCTouch*, cocos2d::CCEvent*) override;
|
||||
|
||||
public:
|
||||
static ScrollLayer* create(
|
||||
cocos2d::CCRect const& rect,
|
||||
bool scrollWheelEnabled = true,
|
||||
bool vertical = true
|
||||
);
|
||||
static ScrollLayer* create(
|
||||
cocos2d::CCSize const& size,
|
||||
bool scrollWheelEnabled = true,
|
||||
bool vertical = true
|
||||
);
|
||||
|
||||
void scrollWheel(float y, float) override;
|
||||
void enableScrollWheel(bool enable = true);
|
||||
};
|
||||
}
|
||||
|
34
loader/include/Geode/ui/Scrollbar.hpp
Normal file
34
loader/include/Geode/ui/Scrollbar.hpp
Normal file
|
@ -0,0 +1,34 @@
|
|||
#pragma once
|
||||
|
||||
#include <cocos2d.h>
|
||||
|
||||
namespace geode {
|
||||
class GEODE_DLL Scrollbar : public cocos2d::CCLayer {
|
||||
protected:
|
||||
CCScrollLayerExt* m_target = nullptr;
|
||||
cocos2d::extension::CCScale9Sprite* m_track;
|
||||
cocos2d::extension::CCScale9Sprite* m_thumb;
|
||||
cocos2d::CCPoint m_clickOffset;
|
||||
float m_width;
|
||||
bool m_resizeThumb;
|
||||
bool m_trackIsRotated;
|
||||
bool m_hoverHighlight;
|
||||
bool m_touchDown = false;
|
||||
|
||||
bool ccTouchBegan(cocos2d::CCTouch* touch, cocos2d::CCEvent* event) override;
|
||||
void ccTouchMoved(cocos2d::CCTouch* touch, cocos2d::CCEvent* event) override;
|
||||
void ccTouchEnded(cocos2d::CCTouch* touch, cocos2d::CCEvent* event) override;
|
||||
void ccTouchCancelled(cocos2d::CCTouch* touch, cocos2d::CCEvent* event) override;
|
||||
void scrollWheel(float y, float x) override;
|
||||
void registerWithTouchDispatcher() override;
|
||||
|
||||
void draw() override;
|
||||
|
||||
bool init(CCScrollLayerExt* list);
|
||||
|
||||
public:
|
||||
void setTarget(CCScrollLayerExt* list);
|
||||
|
||||
static Scrollbar* create(CCScrollLayerExt* list);
|
||||
};
|
||||
}
|
120
loader/include/Geode/ui/SelectList.hpp
Normal file
120
loader/include/Geode/ui/SelectList.hpp
Normal file
|
@ -0,0 +1,120 @@
|
|||
#pragma once
|
||||
|
||||
#include <Geode/binding/CCMenuItemSpriteExtra.hpp>
|
||||
|
||||
namespace geode {
|
||||
|
||||
template<class T>
|
||||
T do_nothing(T t) {
|
||||
return t;
|
||||
}
|
||||
|
||||
template<class T = std::string, auto Stringify = do_nothing<std::string>>
|
||||
class SelectList : public cocos2d::CCMenu {
|
||||
protected:
|
||||
std::vector<T> m_list;
|
||||
size_t m_index = 0;
|
||||
std::function<void(T const&, size_t)> m_onChange;
|
||||
cocos2d::CCLabelBMFont* m_label;
|
||||
CCMenuItemSpriteExtra* m_prevBtn;
|
||||
CCMenuItemSpriteExtra* m_nextBtn;
|
||||
|
||||
bool init(
|
||||
float width,
|
||||
std::vector<T> const& list,
|
||||
std::function<void(T const&, size_t)> onChange
|
||||
) {
|
||||
if (!cocos2d::CCMenu::init())
|
||||
return false;
|
||||
|
||||
m_list = list;
|
||||
m_onChange = onChange;
|
||||
|
||||
this->setContentSize({ width, 30.f });
|
||||
|
||||
auto prevSpr = cocos2d::CCSprite::createWithSpriteFrameName("navArrowBtn_001.png");
|
||||
prevSpr->setFlipX(true);
|
||||
prevSpr->setScale(.3f);
|
||||
|
||||
m_prevBtn = CCMenuItemSpriteExtra::create(
|
||||
prevSpr, this, menu_selector(SelectList<T>::onPrev)
|
||||
);
|
||||
m_prevBtn->setPosition(-width / 2 + 10.f, 0.f);
|
||||
this->addChild(m_prevBtn);
|
||||
|
||||
auto nextSpr = cocos2d::CCSprite::createWithSpriteFrameName("navArrowBtn_001.png");
|
||||
nextSpr->setScale(.3f);
|
||||
|
||||
m_nextBtn = CCMenuItemSpriteExtra::create(
|
||||
nextSpr, this, menu_selector(SelectList<T>::onNext)
|
||||
);
|
||||
m_nextBtn->setPosition(width / 2 - 10.f, 0.f);
|
||||
this->addChild(m_nextBtn);
|
||||
|
||||
m_label = cocos2d::CCLabelBMFont::create("", "bigFont.fnt");
|
||||
this->addChild(m_label);
|
||||
|
||||
this->updateLabel();
|
||||
|
||||
cocos2d::CCDirector::sharedDirector()->getTouchDispatcher()->incrementForcePrio(2);
|
||||
this->registerWithTouchDispatcher();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void updateLabel() {
|
||||
if (m_list.size()) {
|
||||
m_label->setString(Stringify(m_list.at(m_index)).c_str());
|
||||
m_prevBtn->setEnabled(true);
|
||||
m_nextBtn->setEnabled(true);
|
||||
} else {
|
||||
m_label->setString("-");
|
||||
m_prevBtn->setEnabled(false);
|
||||
m_nextBtn->setEnabled(false);
|
||||
}
|
||||
m_label->limitLabelWidth(m_obContentSize.width - 40.f, .6f, .1f);
|
||||
}
|
||||
|
||||
void onPrev(CCObject* sender) {
|
||||
if (m_index == 0) {
|
||||
m_index = m_list.size() - 1;
|
||||
} else {
|
||||
m_index--;
|
||||
}
|
||||
this->updateLabel();
|
||||
m_onChange(m_list.at(m_index), m_index);
|
||||
}
|
||||
|
||||
void onNext(CCObject* sender) {
|
||||
if (m_index == m_list.size() - 1) {
|
||||
m_index = 0;
|
||||
} else {
|
||||
m_index++;
|
||||
}
|
||||
this->updateLabel();
|
||||
m_onChange(m_list.at(m_index), m_index);
|
||||
}
|
||||
|
||||
public:
|
||||
static SelectList* create(
|
||||
float width,
|
||||
std::vector<T> const& list,
|
||||
std::function<void(T const&, size_t)> onChange
|
||||
) {
|
||||
auto ret = new SelectList();
|
||||
if (ret && ret->init(width, list, onChange)) {
|
||||
ret->autorelease();
|
||||
return ret;
|
||||
}
|
||||
CC_SAFE_DELETE(ret);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void setItems(std::vector<T> const& list) {
|
||||
m_index = 0;
|
||||
m_list = list;
|
||||
this->updateLabel();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
402
loader/include/Geode/ui/TextRenderer.hpp
Normal file
402
loader/include/Geode/ui/TextRenderer.hpp
Normal file
|
@ -0,0 +1,402 @@
|
|||
#pragma once
|
||||
|
||||
#include <cocos2d.h>
|
||||
|
||||
namespace geode {
|
||||
enum class TextAlignment {
|
||||
Begin,
|
||||
Center,
|
||||
End,
|
||||
};
|
||||
|
||||
enum class TextCapitalization {
|
||||
Normal,
|
||||
AllUpper,
|
||||
AllLower,
|
||||
};
|
||||
|
||||
// enum only as these are flags
|
||||
enum TextStyle {
|
||||
TextStyleRegular = 0b0,
|
||||
TextStyleBold = 0b1,
|
||||
TextStyleItalic = 0b10,
|
||||
};
|
||||
|
||||
// enum only as these are flags
|
||||
enum TextDecoration {
|
||||
TextDecorationNone = 0b0,
|
||||
TextDecorationUnderline = 0b1,
|
||||
TextDecorationStrikethrough= 0b10,
|
||||
};
|
||||
|
||||
class TextDecorationWrapper;
|
||||
class TextLinkedButtonWrapper;
|
||||
|
||||
/**
|
||||
* Utility class for creating rich text content.
|
||||
* Use to incrementally render strings, and push
|
||||
* variables to modify the renderer's state. Use
|
||||
* `begin` to start rendering to a target and
|
||||
* `end` to finish rendering.
|
||||
*
|
||||
* Works for any type of label, although relies
|
||||
* heavily on content sizes for labels and nodes.
|
||||
*
|
||||
* Not too well-performant and the rendering is
|
||||
* done linearly without so this is not suitable
|
||||
* for dynamic content. For something like a
|
||||
* static rich text -area though this can prove
|
||||
* useful. Used in MDTextArea.
|
||||
*/
|
||||
class GEODE_DLL TextRenderer : public cocos2d::CCObject {
|
||||
public:
|
||||
/**
|
||||
* Represents a label. As CCLabelBMFont and
|
||||
* CCLabelTTF have different inheritance
|
||||
* structures, this class can handle either
|
||||
* one universally. All relevant vtables are
|
||||
* stored in-class to avoid needing to
|
||||
* `dynamic_cast` everything. This way of
|
||||
* storing vtables also means that anything
|
||||
* which satisfies these 3 vtables can be used,
|
||||
* even if its true UX representation is
|
||||
* actually not a label.
|
||||
*/
|
||||
struct Label {
|
||||
/**
|
||||
* Label's CCNode vtable
|
||||
*/
|
||||
cocos2d::CCNode* m_node;
|
||||
/**
|
||||
* Label's CCLabelProtocol vtable
|
||||
*/
|
||||
cocos2d::CCLabelProtocol* m_labelProtocol;
|
||||
/**
|
||||
* Label's CCRGBAProtocol vtable
|
||||
*/
|
||||
cocos2d::CCRGBAProtocol* m_rgbaProtocol;
|
||||
/**
|
||||
* Line height. If 0, the renderer will dynamically
|
||||
* calculate line height based on content size.
|
||||
*/
|
||||
float m_lineHeight;
|
||||
|
||||
explicit inline Label() {
|
||||
m_node = nullptr;
|
||||
m_labelProtocol = nullptr;
|
||||
m_rgbaProtocol = nullptr;
|
||||
m_lineHeight = .0f;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
Label(T* label, float lineHeight = .0f) {
|
||||
static_assert(std::is_base_of_v<cocos2d::CCNode, T>, "Label must inherit from CCNode!");
|
||||
static_assert(std::is_base_of_v<cocos2d::CCLabelProtocol, T>, "Label must inherit from CCLabelProtocol!");
|
||||
static_assert(std::is_base_of_v<cocos2d::CCRGBAProtocol, T>, "Label must inherit from CCRGBAProtocol!");
|
||||
m_node = label;
|
||||
m_labelProtocol = label;
|
||||
m_rgbaProtocol = label;
|
||||
if (lineHeight) {
|
||||
m_lineHeight = lineHeight;
|
||||
} else {
|
||||
if constexpr (std::is_same_v<cocos2d::CCLabelBMFont, T>) {
|
||||
m_lineHeight = label->getConfiguration()->m_nCommonHeight / cocos2d::CC_CONTENT_SCALE_FACTOR();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Label generator function. The `int` parameter
|
||||
* represents the current text style flags. Use
|
||||
* to distinguish between bold, italic and
|
||||
* regular text.
|
||||
*/
|
||||
using Font = std::function<Label(int)>;
|
||||
|
||||
protected:
|
||||
cocos2d::CCPoint m_origin = cocos2d::CCPointZero;
|
||||
cocos2d::CCSize m_size = cocos2d::CCSizeZero;
|
||||
cocos2d::CCPoint m_cursor = cocos2d::CCPointZero;
|
||||
cocos2d::CCNode* m_target = nullptr;
|
||||
std::vector<Font> m_fontStack;
|
||||
std::vector<float> m_scaleStack;
|
||||
std::vector<int> m_styleStack;
|
||||
std::vector<cocos2d::ccColor3B> m_colorStack;
|
||||
std::vector<GLubyte> m_opacityStack;
|
||||
std::vector<int> m_decorationStack;
|
||||
std::vector<TextCapitalization> m_capsStack;
|
||||
std::vector<Label> m_lastRendered;
|
||||
std::vector<float> m_indentationStack;
|
||||
std::vector<float> m_wrapOffsetStack;
|
||||
std::vector<TextAlignment> m_hAlignmentStack;
|
||||
std::vector<TextAlignment> m_vAlignmentStack;
|
||||
std::vector<cocos2d::CCNode*> m_renderedLine;
|
||||
cocos2d::CCNode* m_lastRenderedNode = nullptr;
|
||||
|
||||
bool init();
|
||||
|
||||
Label addWrappers(
|
||||
Label const& label,
|
||||
bool isButton,
|
||||
cocos2d::CCObject* target,
|
||||
cocos2d::SEL_MenuHandler callback
|
||||
);
|
||||
bool render(std::string const& word, cocos2d::CCNode* to, cocos2d::CCLabelProtocol* label);
|
||||
float adjustLineAlignment();
|
||||
|
||||
public:
|
||||
/**
|
||||
* Create a TextRenderer
|
||||
* @returns Created TextRenderer
|
||||
*/
|
||||
static TextRenderer* create();
|
||||
virtual ~TextRenderer();
|
||||
|
||||
/**
|
||||
* Initialize renderer
|
||||
* @param target Target node to render to. If nullptr,
|
||||
* a new CCNode will be created.
|
||||
* @param pos Position to render to
|
||||
* @param size Size of the render area. Needed for
|
||||
* text wrapping & alignment
|
||||
*/
|
||||
void begin(
|
||||
cocos2d::CCNode* target,
|
||||
cocos2d::CCPoint const& pos = cocos2d::CCPointZero,
|
||||
cocos2d::CCSize const& size = cocos2d::CCSizeZero
|
||||
);
|
||||
/**
|
||||
* Finish rendering and clean up renderer
|
||||
* @param fitToContent Resize the target's content
|
||||
* size to match the rendered content
|
||||
* @param horizontalAlign Horizontal alignment of
|
||||
* the rendered text
|
||||
* @param verticalAlign Vertical alignment of
|
||||
* the rendered text
|
||||
* @returns Target that was rendered onto
|
||||
*/
|
||||
cocos2d::CCNode* end(
|
||||
bool fitToContent = true,
|
||||
TextAlignment horizontalAlign = TextAlignment::Begin,
|
||||
TextAlignment verticalAlign = TextAlignment::Begin
|
||||
);
|
||||
|
||||
/**
|
||||
* Render a string with specific settings, bypassing
|
||||
* current variable stacks.
|
||||
* @param str String to render
|
||||
* @param font Font function to use
|
||||
* @param scale Scale of label
|
||||
* @param color Label color
|
||||
* @param opacity Label opacity
|
||||
* @param style Label style (TextStyle enum)
|
||||
* @param deco Label decorations (TextDecoration enum)
|
||||
* @param caps String capitalization
|
||||
* @param addToTarget Whether to add the created label(s)
|
||||
* onto the target
|
||||
* @param isButton If the label should be created as an
|
||||
* interactive linked button
|
||||
* @param buttonTarget Target for the label if isButton is
|
||||
* true, defaults to current renderer target
|
||||
* @param callback Callback for the label if isButton is
|
||||
* true
|
||||
* @returns Vector of rendered labels. The label may be
|
||||
* split on multiple lines if it exceeds bounds
|
||||
*/
|
||||
std::vector<Label> renderStringEx(
|
||||
std::string const& str,
|
||||
Font font,
|
||||
float scale,
|
||||
cocos2d::ccColor3B color = { 255, 255, 255 },
|
||||
GLubyte opacity = 255,
|
||||
int style = TextStyleRegular,
|
||||
int deco = TextDecorationNone,
|
||||
TextCapitalization caps = TextCapitalization::Normal,
|
||||
bool addToTarget = true,
|
||||
bool isButton = false,
|
||||
cocos2d::CCObject* buttonTarget = nullptr,
|
||||
cocos2d::SEL_MenuHandler callback = nullptr
|
||||
);
|
||||
/**
|
||||
* Render a string to target. Uses current variable stacks
|
||||
* for styling and parameters
|
||||
* @param str String to render
|
||||
* @returns Vector of rendered labels. The label may be
|
||||
* split on multiple lines if it exceeds bounds
|
||||
*/
|
||||
std::vector<Label> renderString(std::string const& str);
|
||||
/**
|
||||
* Render a string to target as a button. Note that the
|
||||
* target should be a CCMenu for the button to do
|
||||
* anything. Uses current variable stacks for styling
|
||||
* and parameters
|
||||
* @param str String to render
|
||||
* @param buttonTarget Target for the label if isButton is
|
||||
* true, defaults to current renderer target
|
||||
* @param callback Callback for the label if isButton is
|
||||
* true
|
||||
* @returns Vector of rendered labels. The label may be
|
||||
* split on multiple lines if it exceeds bounds
|
||||
*/
|
||||
std::vector<Label> renderStringInteractive(
|
||||
std::string const& str,
|
||||
cocos2d::CCObject* buttonTarget,
|
||||
cocos2d::SEL_MenuHandler callback
|
||||
);
|
||||
/**
|
||||
* Render a node to the current target, use for adding
|
||||
* images & other content in the middle of text
|
||||
* @param node Node to render
|
||||
* @returns Rendered node
|
||||
*/
|
||||
cocos2d::CCNode* renderNode(cocos2d::CCNode* node);
|
||||
/**
|
||||
* Start next line
|
||||
* @param y Y offset amount from previous line. If 0,
|
||||
* will dynamically figure out based on content size
|
||||
*/
|
||||
void breakLine(float y = .0f);
|
||||
|
||||
/**
|
||||
* Helper for pushing a CCLabelBMFont. Make
|
||||
* sure the const char* outlives the renderer.
|
||||
*/
|
||||
void pushBMFont(const char* bmFont);
|
||||
void pushFont(Font const& font);
|
||||
void popFont();
|
||||
Font getCurrentFont() const;
|
||||
|
||||
void pushScale(float scale);
|
||||
void popScale();
|
||||
float getCurrentScale() const;
|
||||
|
||||
void pushStyleFlags(int style);
|
||||
void popStyleFlags();
|
||||
int getCurrentStyle() const;
|
||||
|
||||
void pushColor(cocos2d::ccColor3B const& color);
|
||||
void popColor();
|
||||
cocos2d::ccColor3B getCurrentColor() const;
|
||||
|
||||
void pushOpacity(GLubyte opacity);
|
||||
void popOpacity();
|
||||
GLubyte getCurrentOpacity() const;
|
||||
|
||||
void pushDecoFlags(int deco);
|
||||
void popDecoFlags();
|
||||
int getCurrentDeco() const;
|
||||
|
||||
void pushCaps(TextCapitalization caps);
|
||||
void popCaps();
|
||||
TextCapitalization getCurrentCaps() const;
|
||||
|
||||
void pushIndent(float indent);
|
||||
void popIndent();
|
||||
float getCurrentIndent() const;
|
||||
|
||||
void pushWrapOffset(float wrapOffset);
|
||||
void popWrapOffset();
|
||||
float getCurrentWrapOffset() const;
|
||||
|
||||
void pushVerticalAlign(TextAlignment align);
|
||||
void popVerticalAlign();
|
||||
TextAlignment getCurrentVerticalAlign() const;
|
||||
|
||||
void pushHorizontalAlign(TextAlignment align);
|
||||
void popHorizontalAlign();
|
||||
TextAlignment getCurrentHorizontalAlign() const;
|
||||
|
||||
void moveCursor(cocos2d::CCPoint const& pos);
|
||||
cocos2d::CCPoint getCursorPos();
|
||||
};
|
||||
|
||||
/**
|
||||
* Wrapper node for adding decorations (strikethrough,
|
||||
* underline) to an arbitary label. Is not agnostic of
|
||||
* font and as such will always render simple lines
|
||||
*/
|
||||
class TextDecorationWrapper : public cocos2d::CCNodeRGBA, public cocos2d::CCLabelProtocol {
|
||||
protected:
|
||||
int m_deco;
|
||||
TextRenderer::Label m_label;
|
||||
|
||||
bool init(
|
||||
TextRenderer::Label const& label,
|
||||
int decoration,
|
||||
cocos2d::ccColor3B const& color,
|
||||
GLubyte opacity
|
||||
);
|
||||
|
||||
void draw() override;
|
||||
|
||||
public:
|
||||
static TextDecorationWrapper* create(
|
||||
TextRenderer::Label const& label,
|
||||
int decoration,
|
||||
cocos2d::ccColor3B const& color,
|
||||
GLubyte opacity
|
||||
);
|
||||
static TextDecorationWrapper* wrap(
|
||||
TextRenderer::Label const& label,
|
||||
int decoration,
|
||||
cocos2d::ccColor3B const& color,
|
||||
GLubyte opacity
|
||||
);
|
||||
|
||||
void setColor(cocos2d::ccColor3B const& color) override;
|
||||
void setOpacity(GLubyte opacity) override;
|
||||
void updateDisplayedColor(cocos2d::ccColor3B const& color) override;
|
||||
void updateDisplayedOpacity(GLubyte opacity) override;
|
||||
|
||||
void setString(const char* text) override;
|
||||
const char* getString() override;
|
||||
};
|
||||
|
||||
/**
|
||||
* Wrapper node for making a label clickable.
|
||||
* Note that this should always be the top
|
||||
* wrapper above all other wrappers
|
||||
*/
|
||||
class TextLinkedButtonWrapper :
|
||||
public cocos2d::CCMenuItemSprite,
|
||||
public cocos2d::CCLabelProtocol
|
||||
{
|
||||
protected:
|
||||
TextRenderer::Label m_label;
|
||||
GLubyte m_opacity;
|
||||
cocos2d::ccColor3B m_color;
|
||||
std::vector<TextLinkedButtonWrapper*> m_linked;
|
||||
|
||||
bool init(
|
||||
TextRenderer::Label const& label,
|
||||
cocos2d::CCObject* target,
|
||||
cocos2d::SEL_MenuHandler handler
|
||||
);
|
||||
|
||||
public:
|
||||
static TextLinkedButtonWrapper* create(
|
||||
TextRenderer::Label const& label,
|
||||
cocos2d::CCObject* target,
|
||||
cocos2d::SEL_MenuHandler handler
|
||||
);
|
||||
static TextLinkedButtonWrapper* wrap(
|
||||
TextRenderer::Label const& label,
|
||||
cocos2d::CCObject* target,
|
||||
cocos2d::SEL_MenuHandler handler
|
||||
);
|
||||
|
||||
void link(TextLinkedButtonWrapper* other);
|
||||
|
||||
void selectedWithoutPropagation(bool selected);
|
||||
void selected() override;
|
||||
void unselected() override;
|
||||
|
||||
void setColor(cocos2d::ccColor3B const& color) override;
|
||||
void setOpacity(GLubyte opacity) override;
|
||||
void updateDisplayedColor(cocos2d::ccColor3B const& color) override;
|
||||
void updateDisplayedOpacity(GLubyte opacity) override;
|
||||
|
||||
void setString(const char* text) override;
|
||||
const char* getString() override;
|
||||
};
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue