├── .gitignore ├── .gitmodules ├── .idea └── runConfigurations │ ├── assembleDebug.xml │ └── assembleRelease.xml ├── README.md ├── app ├── .gitignore ├── build.gradle └── src │ └── main │ ├── AndroidManifest.xml │ └── cpp │ ├── CMakeLists.txt │ ├── Engine │ ├── API │ │ ├── API.cpp │ │ ├── API.h │ │ ├── Color.hpp │ │ ├── Matrix4x4.hpp │ │ ├── Quaternion.hpp │ │ ├── Rect.hpp │ │ ├── Unity.h │ │ ├── Vector2.hpp │ │ └── Vector3.hpp │ ├── Includes.hpp │ └── Structure │ │ ├── CBaseEntry.cpp │ │ ├── CBaseEntry.hpp │ │ ├── ExampleEntry.cpp │ │ └── ExampleEntry.hpp │ ├── Utils │ └── Logger.h │ └── native-lib.cpp ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | /.idea/.gitignore 11 | /.idea/.name 12 | /.idea/compiler.xml 13 | /.idea/discord.xml 14 | /.idea/gradle.xml 15 | /.idea/misc.xml 16 | .DS_Store 17 | /build 18 | /captures 19 | .externalNativeBuild 20 | .cxx 21 | local.properties 22 | /.idea/vcs.xml 23 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "app/src/main/cpp/External/Dobby"] 2 | path = app/src/main/cpp/External/Dobby 3 | url = https://github.com/LSPosed/Dobby 4 | [submodule "app/src/main/cpp/External/KittyMemory"] 5 | path = app/src/main/cpp/External/KittyMemory 6 | url = https://github.com/MJx0/KittyMemory 7 | -------------------------------------------------------------------------------- /.idea/runConfigurations/assembleDebug.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 16 | 18 | true 19 | true 20 | false 21 | 22 | 23 | -------------------------------------------------------------------------------- /.idea/runConfigurations/assembleRelease.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 16 | 18 | true 19 | true 20 | false 21 | 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Android Native Mod Template 2 | 3 | A minimal native only template for Android modding. 4 | 5 | ### Background 6 | 7 | Recently i wanted to begin doing again some Android modding, but i didn't want to use any of the 8 | existing frameworks, since it messy and i don't like it. 9 |
So i created this template to make it easier for me to start a new project. 10 | 11 | ### How To Use 12 | 13 | 1. Clone the repo 14 | 2. Open the project in Android Studio / Visual Studio Code 15 | 3. Change the package name in `app/build.gradle` and library name 16 | in `app/src/main/cpp/CMakeLists.txt` 17 | 4. Start coding 18 | 5. Build the project 19 | 6. Copy the generated .so from `app/build/outputs/native/{debug/release}/lib{template}.so` 20 | 7. Load the library in your modded app 21 |
You can use many various methods to load the library, see [Injecting the library](#injecting-the-library) 22 | 23 | ### Injecting the library 24 | This project is merely a template, so you can use any method you want to load the library.
25 | Here are some examples:

26 | Note: Modify "**template**" to your library name 27 | 28 | - #### [Android-Ptrace-Injector - reveny](https://github.com/reveny/Android-Ptrace-Injector) 29 | ```bash 30 | ./Injector -p "com.target.package" -l "template" 31 | ``` 32 | 33 | - #### [System.loadLibrary](https://docs.oracle.com/javase/8/docs/api/java/lang/System.html#loadLibrary-java.lang.String) 34 | ```java 35 | const-string v0, "template" 36 | 37 | invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V 38 | ``` 39 | 40 | - #### [xDL - hexhacking](https://github.com/hexhacking/xDL) 41 | ```c 42 | void* handle = xdl_open("template", RTLD_NOW); 43 | ``` 44 | 45 | - #### Other methods 46 | As long as you can load the library into the target process, you can use any method you want. 47 | 48 | ### To-Do 49 | - [x] Polymorphism design pattern 50 | - [x] Unity API (Vector2, Vector3, Quaternion, etc) 51 | - [x] Doc: How to use 52 | - [ ] Doc: What need to be changed 53 | - [ ] Doc: What each file does 54 | - [ ] Doc: How to add new functions 55 | - [ ] Doc: How to add new classes 56 | 57 | ### Credit 58 | 59 | - [Dobby](https://github.com/jmpews/Dobby) - Hooking library 60 | - [KittyMemory](https://github.com/MJx0/KittyMemory) - Android, IOS runtime code patching library 61 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.android.library' 3 | } 4 | 5 | android { 6 | namespace 'com.cheat.template' 7 | compileSdk 34 8 | 9 | defaultConfig { 10 | minSdk 24 11 | targetSdk 34 12 | versionCode 1 13 | versionName "1.0" 14 | } 15 | 16 | compileOptions { 17 | sourceCompatibility JavaVersion.VERSION_1_8 18 | targetCompatibility JavaVersion.VERSION_1_8 19 | } 20 | 21 | externalNativeBuild { 22 | cmake { 23 | path file('src/main/cpp/CMakeLists.txt') 24 | version '3.22.1' 25 | } 26 | } 27 | 28 | buildFeatures { 29 | aidl false 30 | viewBinding false 31 | buildConfig false 32 | } 33 | } 34 | 35 | afterEvaluate { 36 | android.libraryVariants.forEach { variant -> 37 | def variantCapped = variant.name.capitalize() 38 | def variantLowered = variant.name.toLowerCase() 39 | 40 | // Windows 41 | def strippedLibs = file("$buildDir/intermediates/stripped_native_libs/$variantLowered/out/lib") 42 | if (!strippedLibs.exists() || !strippedLibs.directory) { 43 | // Linux 44 | strippedLibs = file("$buildDir/intermediates/stripped_native_libs/${variant.name}/out/lib") 45 | } 46 | 47 | tasks.register("copyOutputNative${variantCapped}", Sync) { 48 | dependsOn("assemble$variantCapped") 49 | from(strippedLibs) { 50 | include "**/*.so" 51 | } 52 | into file("$buildDir/outputs/native/${variant.name}") 53 | } 54 | 55 | variant.assembleProvider.get().finalizedBy("copyOutputNative${variantCapped}") 56 | } 57 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/cpp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.22.1) 2 | 3 | # set the project name 4 | project("template") 5 | 6 | # Dobby setup 7 | macro(SET_OPTION option value) 8 | set(${option} ${value} CACHE INTERNAL "" FORCE) 9 | endmacro() 10 | 11 | SET_OPTION(DOBBY_GENERATE_SHARED OFF) 12 | SET_OPTION(Plugin.SymbolResolver OFF) 13 | add_subdirectory(External/Dobby) 14 | 15 | # KittyMemory setup 16 | add_compile_definitions(kNO_KEYSTONE) 17 | file(GLOB_RECURSE KITTY_MEMORY_SOURCES External/KittyMemory/KittyMemory/*.cpp) 18 | 19 | # Engine setup 20 | file(GLOB_RECURSE ENGINE_SOURCES Engine/Structure/*.cpp) 21 | file(GLOB_RECURSE ENGINE_HEADER_SOURCES Engine/Structure/*.hpp) 22 | 23 | add_library(${CMAKE_PROJECT_NAME} SHARED 24 | native-lib.cpp 25 | Engine/API/API.cpp 26 | ${ENGINE_SOURCES} 27 | ${KITTY_MEMORY_SOURCES}) 28 | 29 | target_include_directories(${CMAKE_PROJECT_NAME} PUBLIC 30 | External/Dobby/include 31 | External/KittyMemory 32 | Utils) 33 | 34 | target_link_libraries(${CMAKE_PROJECT_NAME} log dobby) 35 | -------------------------------------------------------------------------------- /app/src/main/cpp/Engine/API/API.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by aimar on 12/28/2019. 3 | // 4 | 5 | #include "API.h" 6 | #include 7 | #include 8 | #include 9 | 10 | namespace { 11 | const void *(*il2cpp_assembly_get_image)(const void *assembly); 12 | 13 | void *(*il2cpp_domain_get)(); 14 | 15 | void **(*il2cpp_domain_get_assemblies)(const void *domain, size_t *size); 16 | 17 | const char *(*il2cpp_image_get_name)(void *image); 18 | 19 | void *(*il2cpp_class_from_name)(const void *image, const char *namespaze, const char *name); 20 | 21 | void *(*il2cpp_class_get_property_from_name)(void *klass, const char *name); 22 | 23 | void *(*il2cpp_class_get_field_from_name)(void *klass, const char *name); 24 | 25 | void *(*il2cpp_class_get_method_from_name)(void *klass, const char *name, int argsCount); 26 | 27 | void *(*il2cpp_runtime_invoke)(void* method, void* obj, void** params, void* exec); 28 | 29 | void *(*il2cpp_property_get_get_method)(void *prop); 30 | 31 | void *(*il2cpp_property_get_set_method)(void *prop); 32 | 33 | size_t (*il2cpp_field_get_offset)(void *field); 34 | 35 | void (*il2cpp_field_static_get_value)(void *field, void *value); 36 | 37 | void (*il2cpp_field_static_set_value)(void *field, void *value); 38 | 39 | void *(*il2cpp_array_new)(void *elementTypeInfo, size_t length); 40 | 41 | int32_t (*il2cpp_string_length)(void *str); 42 | 43 | char16_t *(*il2cpp_string_chars)(void *str); 44 | 45 | void* (*il2cpp_string_new)(const char* str); 46 | 47 | char *(*il2cpp_type_get_name)(void *type); 48 | 49 | void* (*il2cpp_method_get_param)(void *method, uint32_t index); 50 | 51 | void* (*il2cpp_class_get_methods)(void *klass, void* *iter); 52 | 53 | const char* (*il2cpp_method_get_name)(void *method); 54 | 55 | void *(*il2cpp_class_get_interfaces)(void *klass, void **iter); 56 | 57 | const char *(*il2cpp_class_get_name)(void *klass); 58 | 59 | void *(*il2cpp_class_from_type)(int); 60 | 61 | int (*il2cpp_class_get_type)(void *); 62 | 63 | void *(*il2cpp_class_get_parent)(void *); 64 | 65 | void *(*il2cpp_class_get_declaring_type)(void *); 66 | 67 | void *(*il2cpp_class_get_nested_types)(void *, void **); 68 | 69 | void *(*il2cpp_object_new)(void *); 70 | } 71 | // ================================================================================================================ // 72 | void *getExportFunction(void *handle, const char *name) 73 | { 74 | void *fn = dlsym(handle, name); 75 | if (fn) { 76 | return fn; 77 | } 78 | 79 | LOGI("%s: %p %s", __FUNCTION__, handle, name); 80 | return nullptr; 81 | } 82 | 83 | int init(void *handle) 84 | { 85 | il2cpp_assembly_get_image = (const void *(*)(const void *)) getExportFunction(handle, "il2cpp_assembly_get_image"); 86 | 87 | il2cpp_domain_get = (void *(*)()) getExportFunction(handle, "il2cpp_domain_get"); 88 | 89 | il2cpp_domain_get_assemblies = (void **(*)(const void* , size_t*)) getExportFunction(handle, "il2cpp_domain_get_assemblies"); 90 | 91 | il2cpp_image_get_name = (const char *(*)(void *)) getExportFunction(handle, "il2cpp_image_get_name"); 92 | 93 | il2cpp_class_from_name = (void* (*)(const void*, const char*, const char *)) getExportFunction(handle, "il2cpp_class_from_name"); 94 | 95 | il2cpp_class_get_property_from_name = (void* (*)(void *, const char *)) getExportFunction(handle, "il2cpp_class_get_property_from_name");; 96 | 97 | il2cpp_class_get_field_from_name = (void* (*)(void*, const char *)) getExportFunction(handle, "il2cpp_class_get_field_from_name");; 98 | 99 | il2cpp_class_get_method_from_name = (void* (*)(void *, const char*, int)) getExportFunction(handle, "il2cpp_class_get_method_from_name"); 100 | 101 | il2cpp_runtime_invoke = (void *(*)(void* , void* , void** , void*)) getExportFunction(handle, "il2cpp_runtime_invoke"); 102 | 103 | il2cpp_property_get_get_method = (void* (*)(void *)) getExportFunction(handle, "il2cpp_property_get_get_method");; 104 | 105 | il2cpp_property_get_set_method = (void* (*)(void *)) getExportFunction(handle, "il2cpp_property_get_set_method");; 106 | 107 | il2cpp_field_get_offset = (size_t (*)(void *)) getExportFunction(handle, "il2cpp_field_get_offset");; 108 | 109 | il2cpp_field_static_get_value = (void (*)(void*, void *)) getExportFunction(handle, "il2cpp_field_static_get_value");; 110 | 111 | il2cpp_field_static_set_value = (void (*)(void*, void *)) getExportFunction(handle, "il2cpp_field_static_set_value");; 112 | 113 | il2cpp_array_new = (void *(*)(void*, size_t)) getExportFunction(handle, "il2cpp_array_new");; 114 | 115 | il2cpp_string_chars = (char16_t *(*)(void*)) getExportFunction(handle, "il2cpp_string_chars");; 116 | 117 | il2cpp_string_length = (int32_t (*)(void*)) getExportFunction(handle, "il2cpp_string_length");; 118 | 119 | il2cpp_string_new = (void *(*)(const char *)) getExportFunction(handle, "il2cpp_string_new");; 120 | 121 | il2cpp_type_get_name = (char *(*)(void *)) getExportFunction(handle, "il2cpp_type_get_name");; 122 | 123 | il2cpp_method_get_param = (void *(*)(void *, uint32_t)) getExportFunction(handle, "il2cpp_method_get_param");; 124 | 125 | il2cpp_class_get_methods = (void *(*)(void *, void **)) getExportFunction(handle, "il2cpp_class_get_methods");; 126 | 127 | il2cpp_method_get_name = (const char *(*)(void *)) getExportFunction(handle, "il2cpp_method_get_name");; 128 | 129 | il2cpp_class_get_interfaces = (void *(*)(void *, void **)) getExportFunction(handle, "il2cpp_class_get_interfaces");; 130 | 131 | il2cpp_class_get_name = (const char *(*)(void *)) getExportFunction(handle, "il2cpp_class_get_name"); 132 | 133 | il2cpp_class_from_type = (void *(*)(int)) getExportFunction(handle, "il2cpp_class_from_type"); 134 | 135 | il2cpp_class_get_type = (int (*)(void *)) getExportFunction(handle, "il2cpp_class_get_type"); 136 | 137 | il2cpp_class_get_parent = (void *(*)(void *)) getExportFunction(handle, "il2cpp_class_get_parent"); 138 | 139 | il2cpp_class_get_declaring_type = (void *(*)(void *)) getExportFunction(handle, "il2cpp_class_get_declaring_type"); 140 | 141 | il2cpp_class_get_nested_types = (void *(*)(void *, void **)) getExportFunction(handle, "il2cpp_class_get_nested_types"); 142 | 143 | il2cpp_object_new = (void *(*)(void *)) getExportFunction(handle, "il2cpp_object_new"); 144 | 145 | return 0; 146 | } 147 | // ================================================================================================================ // 148 | int Il2Cpp::Init(const char *lib) { 149 | if(!lib) return -1; 150 | 151 | return init(dlopen(lib, 4)); 152 | 153 | } 154 | // ================================================================================================================ // 155 | int Il2Cpp::Init(void *handle) { 156 | if(!handle) return -1; 157 | 158 | return init(handle); 159 | 160 | } 161 | // ================================================================================================================ // 162 | void *Il2Cpp::GetImageByName(const char *image) { 163 | size_t size; 164 | void **assemblies = il2cpp_domain_get_assemblies(il2cpp_domain_get(), &size); 165 | for(int i = 0; i < size; ++i) 166 | { 167 | void *img = (void *)il2cpp_assembly_get_image(assemblies[i]); 168 | 169 | const char *img_name = il2cpp_image_get_name(img); 170 | 171 | if(strcmp(img_name, image) == 0) 172 | { 173 | return img; 174 | } 175 | } 176 | return nullptr; 177 | } 178 | // ================================================================================================================ // 179 | void Il2Cpp::GetStaticFieldValue(const char *image, const char *namespaze, const char *clazz, const char *name, void *output) { 180 | void *img = GetImageByName(image); 181 | if(!img) { 182 | LOGI("Can't find image %s!", image); 183 | return; 184 | } 185 | void *klass = GetClassType(image, namespaze, clazz); 186 | if(!klass) { 187 | LOGI("Can't find class %s for field %s!", clazz, name); 188 | return; 189 | } 190 | 191 | void *field = il2cpp_class_get_field_from_name(klass, name); 192 | if(!field) { 193 | LOGI("Can't find field %s in class %s!", name, clazz); 194 | return; 195 | } 196 | 197 | il2cpp_field_static_get_value(field, output); 198 | } 199 | // ================================================================================================================ // 200 | void Il2Cpp::SetStaticFieldValue(const char *image, const char *namespaze, const char *clazz, const char *name, void* value) { 201 | void *img = GetImageByName(image); 202 | if(!img) { 203 | LOGI("Can't find image %s!", image); 204 | return; 205 | } 206 | void *klass = GetClassType(image, namespaze, clazz); 207 | if(!klass) { 208 | LOGI("Can't find class %s for field %s!", clazz, name); 209 | return; 210 | } 211 | 212 | void *field = il2cpp_class_get_field_from_name(klass, name); 213 | if(!field) { 214 | LOGI("Can't find field %s in class %s!", name, clazz); 215 | return; 216 | } 217 | 218 | il2cpp_field_static_set_value(field, value); 219 | } 220 | // ================================================================================================================ // 221 | void *Il2Cpp::GetClassType(const char *image, const char *namespaze, const char *clazz) { 222 | void *img = GetImageByName(image); 223 | if(!img) { 224 | LOGI("Can't find image %s!", image); 225 | return nullptr; 226 | } 227 | 228 | void *klass = il2cpp_class_from_name(img, namespaze, clazz); 229 | if(!klass) { 230 | LOGI("Can't find class %s!", clazz); 231 | return nullptr; 232 | } 233 | return klass; 234 | } 235 | // ================================================================================================================ // 236 | void *Il2Cpp::CreateClassInstance(const char *image, const char *namespaze, const char *clazz) { 237 | void *img = GetImageByName(image); 238 | if(!img) { 239 | LOGI("Can't find image %s!", image); 240 | return nullptr; 241 | } 242 | 243 | void *klass = GetClassType(image, namespaze, clazz); 244 | if(!klass) { 245 | LOGI("Can't find class %s!", clazz); 246 | return nullptr; 247 | } 248 | 249 | void *obj = il2cpp_object_new(klass); 250 | if(!obj) 251 | { 252 | LOGI("Can't create object for %s", clazz); 253 | return nullptr; 254 | } 255 | 256 | return obj; 257 | } 258 | // ================================================================================================================ // 259 | void *Il2Cpp::GetMethodOffset(const char *image, const char *namespaze, const char *clazz, const char *name, int argsCount) { 260 | void *img = GetImageByName(image); 261 | if(!img) { 262 | LOGI("Can't find image %s!", image); 263 | return nullptr; 264 | } 265 | 266 | void *klass = GetClassType(image, namespaze, clazz); 267 | if(!klass) { 268 | LOGI("Can't find class %s for method %s!", clazz, name); 269 | return nullptr; 270 | } 271 | 272 | void **method = (void**)il2cpp_class_get_method_from_name(klass, name, argsCount); 273 | if(!method) { 274 | LOGI("Can't find method %s in class %s!", name, clazz); 275 | return nullptr; 276 | } 277 | 278 | return *method; 279 | } 280 | // ================================================================================================================ // 281 | void *Il2Cpp::GetMethodOffset(const char *image, const char *namespaze, const char *clazz, const char *name, char** args, int argsCount) { 282 | void *img = GetImageByName(image); 283 | if(!img) { 284 | LOGI("Can't find image %s!", image); 285 | return nullptr; 286 | } 287 | 288 | void *klass = GetClassType(image, namespaze, clazz); 289 | if(!klass) { 290 | LOGI("Can't find class %s for method %s!", clazz, name); 291 | return nullptr; 292 | } 293 | 294 | void *iter = nullptr; 295 | 296 | int score = 0; 297 | 298 | void **method = (void**) il2cpp_class_get_methods(klass, &iter); 299 | while(method) { 300 | const char *fname = il2cpp_method_get_name(method); 301 | if(strcmp(fname, name) == 0) { 302 | for (int i = 0; i < argsCount; i++) { 303 | void *arg = il2cpp_method_get_param(method, i); 304 | if (arg) { 305 | const char *tname = il2cpp_type_get_name(arg); 306 | if (strcmp(tname, args[i]) == 0) { 307 | score++; 308 | } else { 309 | LOGI("Argument at index %d didn't matched requested argument!\r\n\tRequested: %s\r\n\tActual: %s\r\nSkipping function...", i, args[i], tname); 310 | score = 0; 311 | goto skip; 312 | } 313 | } 314 | } 315 | } 316 | skip: 317 | 318 | if(score == argsCount) 319 | { 320 | LOGI("Found matched function!"); 321 | return *method; 322 | } 323 | 324 | method = (void **) il2cpp_class_get_methods(klass, &iter); 325 | } 326 | LOGI("Cannot find function %s in class %s!", name, clazz); 327 | return nullptr; 328 | } 329 | 330 | const char *Il2Cpp::GetMethodName(void* method){ 331 | return il2cpp_method_get_name(method); 332 | } 333 | 334 | uintptr_t Il2Cpp::GetFieldOffset(void *clazz, const char *name){ 335 | void *field = il2cpp_class_get_field_from_name(clazz, name); 336 | if(!field) { 337 | LOGI("Can't find field %s!", name); 338 | return -1; 339 | } 340 | return il2cpp_field_get_offset(field); 341 | } 342 | // ================================================================================================================ // 343 | size_t Il2Cpp::GetFieldOffset(const char *image, const char *namespaze, const char *clazz, const char *name) { 344 | void *img = GetImageByName(image); 345 | if(!img) { 346 | LOGI("Can't find image %s!", image); 347 | return -1; 348 | } 349 | void *klass = GetClassType(image, namespaze, clazz); 350 | if(!klass) { 351 | LOGI("Can't find class %s for field %s!", clazz, name); 352 | return -1; 353 | } 354 | 355 | void *field = il2cpp_class_get_field_from_name(klass, name); 356 | if(!field) { 357 | LOGI("Can't find field %s in class %s!", name, clazz); 358 | return -1; 359 | } 360 | return il2cpp_field_get_offset(field); 361 | } 362 | // ================================================================================================================ // 363 | bool Il2Cpp::IsAssembliesLoaded() { 364 | size_t size; 365 | void **assemblies = il2cpp_domain_get_assemblies(il2cpp_domain_get(), &size); 366 | 367 | return size != 0 && assemblies != nullptr; 368 | } 369 | // ================================================================================================================ // 370 | void* Il2Cpp::CreateArray(const char *image, const char *namespaze, const char *clazz, size_t length) { 371 | void *img = GetImageByName(image); 372 | if(!img) { 373 | LOGI("Can't find image %s!", image); 374 | return nullptr; 375 | } 376 | void *klass = GetClassType(image, namespaze, clazz); 377 | if(!klass) { 378 | LOGI("Can't find class %s!", clazz); 379 | return nullptr; 380 | } 381 | 382 | return il2cpp_array_new(klass, length); 383 | } 384 | // ================================================================================================================ // 385 | 386 | std::string Il2Cpp::GetString(void *string) { 387 | if (string) { 388 | std::u16string str = il2cpp_string_chars(string); 389 | std::wstring wide_string(str.begin(), str.end()); 390 | std::wstring_convert> convert; 391 | return convert.to_bytes(wide_string); 392 | } 393 | return "Object NULL!"; 394 | } -------------------------------------------------------------------------------- /app/src/main/cpp/Engine/API/API.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | #ifndef API_H 11 | #define API_H 12 | 13 | namespace Il2Cpp { 14 | 15 | int Init(const char *lib); 16 | 17 | int Init(void *handle); 18 | 19 | void *GetImageByName(const char *image); 20 | 21 | void *GetClassType(const char *image, const char *namespaze, const char *clazz); 22 | 23 | void *CreateArray(const char *image, const char *namespaze, const char *clazz, size_t length); 24 | 25 | void *GetMethodOffset(const char *image, const char *namespaze, const char *clazz, const char *name, int argsCount = 0); 26 | 27 | void *GetMethodOffset(const char *image, const char *namespaze, const char *clazz, const char *name, char **args, int argsCount = 0); 28 | 29 | const char *GetMethodName(void* method); 30 | 31 | size_t GetFieldOffset(const char *image, const char *namespaze, const char *clazz, const char *name); 32 | 33 | void GetStaticFieldValue(const char *image, const char *namespaze, const char *clazz, const char *name, void *output); 34 | 35 | void SetStaticFieldValue(const char *image, const char *namespaze, const char *clazz, const char *name, void* value); 36 | 37 | void *CreateClassInstance(const char *image, const char *namespaze, const char *clazz); 38 | 39 | bool IsAssembliesLoaded(); 40 | 41 | void *CreateString(const char *str); 42 | 43 | template 44 | inline T GetMethod(uintptr_t realOffset) { 45 | return (T) (realOffset); 46 | } 47 | 48 | template 49 | inline T GetMethod(const char *image, const char *namespaze, const char *clazz, const char *name, int argsCount) { 50 | auto realOffset = Il2Cpp::GetMethodOffset(image, namespaze, clazz, name, argsCount); 51 | return (T) (realOffset); 52 | } 53 | 54 | template 55 | inline T GetField(void* obj, std::ptrdiff_t Offset) { 56 | if (Offset == 0) 57 | __android_log_print(ANDROID_LOG_INFO, "Rewtio", "GetField: Offset is 0"); 58 | return *(T *) ((std::uint8_t *) obj + Offset); 59 | } 60 | 61 | template 62 | void SetField(void* obj, std::ptrdiff_t Offset, T val) 63 | { 64 | *(T*)((std::uint8_t*)obj + Offset) = val; 65 | } 66 | 67 | std::string GetString(void *string); 68 | 69 | uintptr_t GetFieldOffset(void *clazz, const char *name); 70 | }; 71 | 72 | 73 | #endif //API_H 74 | -------------------------------------------------------------------------------- /app/src/main/cpp/Engine/API/Color.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define _USE_MATH_DEFINES 4 | #include 5 | #include 6 | 7 | struct Color 8 | { 9 | union 10 | { 11 | struct 12 | { 13 | float R; 14 | float G; 15 | float B; 16 | float A; 17 | }; 18 | float data[4]; 19 | }; 20 | 21 | inline Color(); 22 | inline Color(float r, float g, float b, float a); 23 | 24 | static inline Color red(); 25 | static inline Color green(); 26 | static inline Color blue(); 27 | static inline Color white(); 28 | static inline Color black(); 29 | static inline Color purpleSense(); 30 | static inline Color yellow(); 31 | static inline Color magenta(); 32 | static inline Color gray(); 33 | static inline Color grey(); 34 | static inline Color clear(); 35 | }; 36 | 37 | Color::Color() : R(0), G(0), B(0), A(0) {} 38 | Color::Color(float r, float g, float b, float a) : R(r), G(g), B(b), A(a) {} 39 | 40 | Color Color::red() { return Color(1,0,0,1); } 41 | Color Color::green() { return Color(0,1,0,1); } 42 | Color Color::blue() { return Color(0,0,1,1); } 43 | Color Color::white() { return Color(1,1,1,1); } 44 | Color Color::black() { return Color(0,0,0,1); } 45 | Color Color::purpleSense() { return Color(0.6039215, 0.0705882, 0.7019607, 1); } 46 | Color Color::yellow() { return Color(1,0.921569,0.0156863,1); } 47 | Color Color::magenta() { return Color(1,0,1,1); } 48 | Color Color::gray() { return Color(0.5,0.5,0.5,1); } 49 | Color Color::grey() { return Color(0.5,0.5,0.5,1); } 50 | Color Color::clear() { return Color(0,0,0,0.5); } -------------------------------------------------------------------------------- /app/src/main/cpp/Engine/API/Matrix4x4.hpp: -------------------------------------------------------------------------------- 1 | #ifndef MATRIX4_HPP 2 | #define MATRIX4_HPP 3 | 4 | struct Matrix4x4 { 5 | 6 | 7 | union { 8 | struct { 9 | float m00; 10 | float m10; 11 | float m20; 12 | float m30; 13 | float m01; 14 | float m11; 15 | float m21; 16 | float m31; 17 | float m02; 18 | float m12; 19 | float m22; 20 | float m32; 21 | float m03; 22 | float m13; 23 | float m23; 24 | float m33; 25 | }; 26 | float m[16]; 27 | }; 28 | 29 | inline Matrix4x4(); 30 | 31 | inline Matrix4x4 operator*(const Matrix4x4 &m2) const; 32 | 33 | inline Matrix4x4(float entry00, float entry01, float entry02, float entry03, float entry10, 34 | float entry11, float entry12, float entry13, float entry20, float entry21, 35 | float entry22, float entry23, float entry30, float entry31, float entry32, 36 | float entry33); 37 | 38 | inline Vector3 MultiplyPoint(Vector3 point); 39 | }; 40 | 41 | Matrix4x4::Matrix4x4() : m00(1.0f), m10(0.0f), m20(0.0f), m30(0.0f), 42 | m01(0.0f), m11(1.0f), m21(0.0f), m31(0.0f), 43 | m02(0.0f), m12(0.0f), m22(1.0f), m32(0.0f), 44 | m03(0.0f), m13(0.0f), m23(0.0f), m33(1.0f) {} 45 | 46 | Matrix4x4::Matrix4x4(float entry00, float entry01, float entry02, float entry03, 47 | float entry10, float entry11, float entry12, float entry13, 48 | float entry20, float entry21, float entry22, float entry23, 49 | float entry30, float entry31, float entry32, float entry33) 50 | : m{entry00, entry01, entry02, entry03, 51 | entry10, entry11, entry12, entry13, 52 | entry20, entry21, entry22, entry23, 53 | entry30, entry31, entry32, entry33} {} 54 | 55 | Matrix4x4 Matrix4x4::operator*(const Matrix4x4 &rhs) const { 56 | Matrix4x4 res; 57 | res.m00 = this->m00 * rhs.m00 + this->m01 * rhs.m10 + this->m02 * rhs.m20 + this->m03 * rhs.m30; 58 | res.m01 = this->m00 * rhs.m01 + this->m01 * rhs.m11 + this->m02 * rhs.m21 + this->m03 * rhs.m31; 59 | res.m02 = this->m00 * rhs.m02 + this->m01 * rhs.m12 + this->m02 * rhs.m22 + this->m03 * rhs.m32; 60 | res.m03 = this->m00 * rhs.m03 + this->m01 * rhs.m13 + this->m02 * rhs.m23 + this->m03 * rhs.m33; 61 | 62 | res.m10 = this->m10 * rhs.m00 + this->m11 * rhs.m10 + this->m12 * rhs.m20 + this->m13 * rhs.m30; 63 | res.m11 = this->m10 * rhs.m01 + this->m11 * rhs.m11 + this->m12 * rhs.m21 + this->m13 * rhs.m31; 64 | res.m12 = this->m10 * rhs.m02 + this->m11 * rhs.m12 + this->m12 * rhs.m22 + this->m13 * rhs.m32; 65 | res.m13 = this->m10 * rhs.m03 + this->m11 * rhs.m13 + this->m12 * rhs.m23 + this->m13 * rhs.m33; 66 | 67 | res.m20 = this->m20 * rhs.m00 + this->m21 * rhs.m10 + this->m22 * rhs.m20 + this->m23 * rhs.m30; 68 | res.m21 = this->m20 * rhs.m01 + this->m21 * rhs.m11 + this->m22 * rhs.m21 + this->m23 * rhs.m31; 69 | res.m22 = this->m20 * rhs.m02 + this->m21 * rhs.m12 + this->m22 * rhs.m22 + this->m23 * rhs.m32; 70 | res.m23 = this->m20 * rhs.m03 + this->m21 * rhs.m13 + this->m22 * rhs.m23 + this->m23 * rhs.m33; 71 | 72 | res.m30 = this->m30 * rhs.m00 + this->m31 * rhs.m10 + this->m32 * rhs.m20 + this->m33 * rhs.m30; 73 | res.m31 = this->m30 * rhs.m01 + this->m31 * rhs.m11 + this->m32 * rhs.m21 + this->m33 * rhs.m31; 74 | res.m32 = this->m30 * rhs.m02 + this->m31 * rhs.m12 + this->m32 * rhs.m22 + this->m33 * rhs.m32; 75 | res.m33 = this->m30 * rhs.m03 + this->m31 * rhs.m13 + this->m32 * rhs.m23 + this->m33 * rhs.m33; 76 | 77 | return res; 78 | } 79 | 80 | Vector3 Matrix4x4::MultiplyPoint(Vector3 point) { 81 | Vector3 res; 82 | float w; 83 | res.X = this->m00 * point.X + this->m01 * point.Y + this->m02 * point.Z + this->m03; 84 | res.Y = this->m10 * point.X + this->m11 * point.Y + this->m12 * point.Z + this->m13; 85 | res.Z = this->m20 * point.X + this->m21 * point.Y + this->m22 * point.Z + this->m23; 86 | w = this->m30 * point.X + this->m31 * point.Y + this->m32 * point.Z + this->m33; 87 | if (w > 0.01f) { 88 | w = 1.0F / w; 89 | res.X *= w; 90 | res.Y *= w; 91 | res.Z *= w; 92 | return res; 93 | } else { 94 | return Vector3::Zero(); 95 | } 96 | } 97 | 98 | #endif 99 | -------------------------------------------------------------------------------- /app/src/main/cpp/Engine/API/Quaternion.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define _USE_MATH_DEFINES 4 | #include 5 | #include 6 | 7 | #define SMALL_float 0.0000000001 8 | 9 | 10 | /** 11 | * Attempt to include a header file if the file exists. 12 | * If the file does not exist, create a dummy data structure for that type. 13 | * If it cannot be determined if it exists, just attempt to include it. 14 | */ 15 | #ifdef __has_include 16 | # if __has_include("Vector3.hpp") 17 | # include "Vector3.hpp" 18 | # elif !defined(GMATH_VECTOR3) 19 | #define GMATH_VECTOR3 20 | struct Vector3 21 | { 22 | union 23 | { 24 | struct 25 | { 26 | float X; 27 | float Y; 28 | float Z; 29 | }; 30 | float data[3]; 31 | }; 32 | 33 | inline Vector3() : X(0), Y(0), Z(0) {} 34 | inline Vector3(float data[]) : X(data[0]), Y(data[1]), Z(data[2]) 35 | {} 36 | inline Vector3(float value) : X(value), Y(value), Z(value) {} 37 | inline Vector3(float x, float y) : X(x), Y(y), Z(0) {} 38 | inline Vector3(float x, float y, float z) : X(x), Y(y), Z(z) {} 39 | 40 | static inline Vector3 Cross(Vector3 lhs, Vector3 rhs) 41 | { 42 | float x = lhs.Y * rhs.Z - lhs.Z * rhs.Y; 43 | float y = lhs.Z * rhs.X - lhs.X * rhs.Z; 44 | float z = lhs.X * rhs.Y - lhs.Y * rhs.X; 45 | return Vector3(x, y, z); 46 | } 47 | 48 | static inline float Dot(Vector3 lhs, Vector3 rhs) 49 | { 50 | return lhs.X * rhs.X + lhs.Y * rhs.Y + lhs.Z * rhs.Z; 51 | } 52 | 53 | static inline Vector3 Normalized(Vector3 v) 54 | { 55 | float mag = sqrt(v.X * v.X + v.Y * v.Y + v.Z * v.Z); 56 | if (mag == 0) 57 | return Vector3::Zero(); 58 | return v / mag; 59 | } 60 | 61 | static inline Vector3 Orthogonal(Vector3 v) 62 | { 63 | return v.Z < v.X ? 64 | Vector3(v.Y, -v.X, 0) : Vector3(0, -v.Z, v.Y); 65 | } 66 | 67 | static inline float SqrMagnitude(Vector3 v) 68 | { 69 | return v.X * v.X + v.Y * v.Y + v.Z * v.Z; 70 | } 71 | }; 72 | 73 | 74 | inline Vector3 operator+(Vector3 lhs, const Vector3 rhs) 75 | { 76 | return Vector3(lhs.X + rhs.X, lhs.Y + rhs.Y, lhs.Z + rhs.Z); 77 | } 78 | 79 | inline Vector3 operator*(Vector3 lhs, const float rhs) 80 | { 81 | return Vector3(lhs.X * rhs, lhs.Y * rhs, lhs.Z * rhs); 82 | } 83 | # endif 84 | #else 85 | # include "Vector3.hpp" 86 | #endif 87 | 88 | 89 | struct Quaternion 90 | { 91 | union 92 | { 93 | struct 94 | { 95 | float X; 96 | float Y; 97 | float Z; 98 | float W; 99 | }; 100 | float data[4]; 101 | }; 102 | 103 | 104 | /** 105 | * Constructors. 106 | */ 107 | inline Quaternion(); 108 | inline Quaternion(float data[]); 109 | inline Quaternion(Vector3 vector, float scalar); 110 | inline Quaternion(float x, float y, float z, float w); 111 | 112 | 113 | /** 114 | * Constants for common quaternions. 115 | */ 116 | static inline Quaternion Identity(); 117 | 118 | 119 | /** 120 | * Returns the angle between two quaternions. 121 | * The quaternions must be normalized. 122 | * @param a: The first quaternion. 123 | * @param b: The second quaternion. 124 | * @return: A scalar value. 125 | */ 126 | static inline float Angle(Quaternion a, Quaternion b); 127 | 128 | /** 129 | * Returns the conjugate of a quaternion. 130 | * @param rotation: The quaternion in question. 131 | * @return: A new quaternion. 132 | */ 133 | static inline Quaternion Conjugate(Quaternion rotation); 134 | 135 | /** 136 | * Returns the dot product of two quaternions. 137 | * @param lhs: The left side of the multiplication. 138 | * @param rhs: The right side of the multiplication. 139 | * @return: A scalar value. 140 | */ 141 | static inline float Dot(Quaternion lhs, Quaternion rhs); 142 | 143 | /** 144 | * Creates a new quaternion from the angle-axis representation of 145 | * a rotation. 146 | * @param angle: The rotation angle in radians. 147 | * @param axis: The vector about which the rotation occurs. 148 | * @return: A new quaternion. 149 | */ 150 | static inline Quaternion FromAngleAxis(float angle, Vector3 axis); 151 | 152 | /** 153 | * Create a new quaternion from the euler angle representation of 154 | * a rotation. The z, x and y values represent rotations about those 155 | * axis in that respective order. 156 | * @param rotation: The x, y and z rotations. 157 | * @return: A new quaternion. 158 | */ 159 | static inline Quaternion FromEuler(Vector3 rotation); 160 | 161 | /** 162 | * Create a new quaternion from the euler angle representation of 163 | * a rotation. The z, x and y values represent rotations about those 164 | * axis in that respective order. 165 | * @param x: The rotation about the x-axis in radians. 166 | * @param y: The rotation about the y-axis in radians. 167 | * @param z: The rotation about the z-axis in radians. 168 | * @return: A new quaternion. 169 | */ 170 | static inline Quaternion FromEuler(float x, float y, float z); 171 | 172 | /** 173 | * Create a quaternion rotation which rotates "fromVector" to "toVector". 174 | * @param fromVector: The vector from which to start the rotation. 175 | * @param toVector: The vector at which to end the rotation. 176 | * @return: A new quaternion. 177 | */ 178 | static inline Quaternion FromToRotation(Vector3 fromVector, 179 | Vector3 toVector); 180 | 181 | /** 182 | * Returns the inverse of a rotation. 183 | * @param rotation: The quaternion in question. 184 | * @return: A new quaternion. 185 | */ 186 | static inline Quaternion Inverse(Quaternion rotation); 187 | 188 | /** 189 | * Interpolates between a and b by t, which is clamped to the range [0-1]. 190 | * The result is normalized before being returned. 191 | * @param a: The starting rotation. 192 | * @param b: The ending rotation. 193 | * @return: A new quaternion. 194 | */ 195 | static inline Quaternion Lerp(Quaternion a, Quaternion b, float t); 196 | 197 | /** 198 | * Interpolates between a and b by t. This normalizes the result when 199 | * complete. 200 | * @param a: The starting rotation. 201 | * @param b: The ending rotation. 202 | * @param t: The interpolation value. 203 | * @return: A new quaternion. 204 | */ 205 | static inline Quaternion LerpUnclamped(Quaternion a, Quaternion b, 206 | float t); 207 | 208 | /** 209 | * Creates a rotation with the specified forward direction. This is the 210 | * same as calling LookRotation with (0, 1, 0) as the upwards vector. 211 | * The output is undefined for parallel vectors. 212 | * @param forward: The forward direction to look toward. 213 | * @return: A new quaternion. 214 | */ 215 | static inline Quaternion LookRotation(Vector3 forward); 216 | 217 | /** 218 | * Creates a rotation with the specified forward and upwards directions. 219 | * The output is undefined for parallel vectors. 220 | * @param forward: The forward direction to look toward. 221 | * @param upwards: The direction to treat as up. 222 | * @return: A new quaternion. 223 | */ 224 | static inline Quaternion LookRotation(Vector3 forward, Vector3 upwards); 225 | 226 | /** 227 | * Returns the norm of a quaternion. 228 | * @param rotation: The quaternion in question. 229 | * @return: A scalar value. 230 | */ 231 | static inline float Norm(Quaternion rotation); 232 | 233 | /** 234 | * Returns a quaternion with identical rotation and a norm of one. 235 | * @param rotation: The quaternion in question. 236 | * @return: A new quaternion. 237 | */ 238 | static inline Quaternion Normalized(Quaternion rotation); 239 | 240 | /** 241 | * Returns a new Quaternion created by rotating "from" towards "to" by 242 | * "maxRadiansDelta". This will not overshoot, and if a negative delta is 243 | * applied, it will rotate till completely opposite "to" and then stop. 244 | * @param from: The rotation at which to start. 245 | * @param to: The rotation at which to end. 246 | # @param maxRadiansDelta: The maximum number of radians to rotate. 247 | * @return: A new Quaternion. 248 | */ 249 | static inline Quaternion RotateTowards(Quaternion from, Quaternion to, 250 | float maxRadiansDelta); 251 | 252 | /** 253 | * Returns a new quaternion interpolated between a and b, using spherical 254 | * linear interpolation. The variable t is clamped to the range [0-1]. The 255 | * resulting quaternion will be normalized. 256 | * @param a: The starting rotation. 257 | * @param b: The ending rotation. 258 | * @param t: The interpolation value. 259 | * @return: A new quaternion. 260 | */ 261 | static inline Quaternion Slerp(Quaternion a, Quaternion b, float t); 262 | 263 | /** 264 | * Returns a new quaternion interpolated between a and b, using spherical 265 | * linear interpolation. The resulting quaternion will be normalized. 266 | * @param a: The starting rotation. 267 | * @param b: The ending rotation. 268 | * @param t: The interpolation value. 269 | * @return: A new quaternion. 270 | */ 271 | static inline Quaternion SlerpUnclamped(Quaternion a, Quaternion b, 272 | float t); 273 | 274 | /** 275 | * Outputs the angle axis representation of the provided quaternion. 276 | * @param rotation: The input quaternion. 277 | * @param angle: The output angle. 278 | * @param axis: The output axis. 279 | */ 280 | static inline void ToAngleAxis(Quaternion rotation, float &angle, 281 | Vector3 &axis); 282 | 283 | /** 284 | * Returns the Euler angle representation of a rotation. The resulting 285 | * vector contains the rotations about the z, x and y axis, in that order. 286 | * @param rotation: The quaternion to convert. 287 | * @return: A new vector. 288 | */ 289 | static inline Vector3 ToEuler(Quaternion rotation); 290 | 291 | /** 292 | * Operator overloading. 293 | */ 294 | inline struct Quaternion& operator+=(const float rhs); 295 | inline struct Quaternion& operator-=(const float rhs); 296 | inline struct Quaternion& operator*=(const float rhs); 297 | inline struct Quaternion& operator/=(const float rhs); 298 | inline struct Quaternion& operator+=(const Quaternion rhs); 299 | inline struct Quaternion& operator-=(const Quaternion rhs); 300 | inline struct Quaternion& operator*=(const Quaternion rhs); 301 | }; 302 | 303 | inline Quaternion operator-(Quaternion rhs); 304 | inline Quaternion operator+(Quaternion lhs, const float rhs); 305 | inline Quaternion operator-(Quaternion lhs, const float rhs); 306 | inline Quaternion operator*(Quaternion lhs, const float rhs); 307 | inline Quaternion operator/(Quaternion lhs, const float rhs); 308 | inline Quaternion operator+(const float lhs, Quaternion rhs); 309 | inline Quaternion operator-(const float lhs, Quaternion rhs); 310 | inline Quaternion operator*(const float lhs, Quaternion rhs); 311 | inline Quaternion operator/(const float lhs, Quaternion rhs); 312 | inline Quaternion operator+(Quaternion lhs, const Quaternion rhs); 313 | inline Quaternion operator-(Quaternion lhs, const Quaternion rhs); 314 | inline Quaternion operator*(Quaternion lhs, const Quaternion rhs); 315 | inline Vector3 operator*(Quaternion lhs, const Vector3 rhs); 316 | inline bool operator==(const Quaternion lhs, const Quaternion rhs); 317 | inline bool operator!=(const Quaternion lhs, const Quaternion rhs); 318 | 319 | 320 | 321 | /******************************************************************************* 322 | * Implementation 323 | */ 324 | 325 | Quaternion::Quaternion() : X(0), Y(0), Z(0), W(1) {} 326 | Quaternion::Quaternion(float data[]) : X(data[0]), Y(data[1]), Z(data[2]), 327 | W(data[3]) {} 328 | Quaternion::Quaternion(Vector3 vector, float scalar) : X(vector.X), 329 | Y(vector.Y), Z(vector.Z), W(scalar) {} 330 | Quaternion::Quaternion(float x, float y, float z, float w) : X(x), Y(y), 331 | Z(z), W(w) {} 332 | 333 | 334 | Quaternion Quaternion::Identity() { return Quaternion(0, 0, 0, 1); } 335 | 336 | 337 | float Quaternion::Angle(Quaternion a, Quaternion b) 338 | { 339 | float dot = Dot(a, b); 340 | return acos(fmin(fabs(dot), 1)) * 2; 341 | } 342 | 343 | Quaternion Quaternion::Conjugate(Quaternion rotation) 344 | { 345 | return Quaternion(-rotation.X, -rotation.Y, -rotation.Z, rotation.W); 346 | } 347 | 348 | float Quaternion::Dot(Quaternion lhs, Quaternion rhs) 349 | { 350 | return lhs.X * rhs.X + lhs.Y * rhs.Y + lhs.Z * rhs.Z + lhs.W * rhs.W; 351 | } 352 | 353 | Quaternion Quaternion::FromAngleAxis(float angle, Vector3 axis) 354 | { 355 | Quaternion q; 356 | float m = sqrt(axis.X * axis.X + axis.Y * axis.Y + axis.Z * axis.Z); 357 | float s = sin(angle / 2) / m; 358 | q.X = axis.X * s; 359 | q.Y = axis.Y * s; 360 | q.Z = axis.Z * s; 361 | q.W = cos(angle / 2); 362 | return q; 363 | } 364 | 365 | Quaternion Quaternion::FromEuler(Vector3 rotation) 366 | { 367 | return FromEuler(rotation.X, rotation.Y, rotation.Z); 368 | } 369 | 370 | Quaternion Quaternion::FromEuler(float x, float y, float z) 371 | { 372 | float cx = cos(x * 0.5); 373 | float cy = cos(y * 0.5); 374 | float cz = cos(z * 0.5); 375 | float sx = sin(x * 0.5); 376 | float sy = sin(y * 0.5); 377 | float sz = sin(z * 0.5); 378 | Quaternion q; 379 | q.X = cx * sy * sz + cy * cz * sx; 380 | q.Y = cx * cz * sy - cy * sx * sz; 381 | q.Z = cx * cy * sz - cz * sx * sy; 382 | q.W = sx * sy * sz + cx * cy * cz; 383 | return q; 384 | } 385 | 386 | Quaternion Quaternion::FromToRotation(Vector3 fromVector, Vector3 toVector) 387 | { 388 | float dot = Vector3::Dot(fromVector, toVector); 389 | float k = sqrt(Vector3::SqrMagnitude(fromVector) * 390 | Vector3::SqrMagnitude(toVector)); 391 | if (fabs(dot / k + 1) < 0.00001) 392 | { 393 | Vector3 ortho = Vector3::Orthogonal(fromVector); 394 | return Quaternion(Vector3::Normalized(ortho), 0); 395 | } 396 | Vector3 cross = Vector3::Cross(fromVector, toVector); 397 | return Normalized(Quaternion(cross, dot + k)); 398 | } 399 | 400 | Quaternion Quaternion::Inverse(Quaternion rotation) 401 | { 402 | float n = Norm(rotation); 403 | return Conjugate(rotation) / (n * n); 404 | } 405 | 406 | Quaternion Quaternion::Lerp(Quaternion a, Quaternion b, float t) 407 | { 408 | if (t < 0) return Normalized(a); 409 | else if (t > 1) return Normalized(b); 410 | return LerpUnclamped(a, b, t); 411 | } 412 | 413 | Quaternion Quaternion::LerpUnclamped(Quaternion a, Quaternion b, float t) 414 | { 415 | Quaternion quaternion; 416 | if (Dot(a, b) >= 0) 417 | quaternion = a * (1 - t) + b * t; 418 | else 419 | quaternion = a * (1 - t) - b * t; 420 | return Normalized(quaternion); 421 | } 422 | 423 | Quaternion Quaternion::LookRotation(Vector3 forward) 424 | { 425 | return LookRotation(forward, Vector3(0, 1, 0)); 426 | } 427 | 428 | Quaternion Quaternion::LookRotation(Vector3 forward, Vector3 upwards) 429 | { 430 | // Normalize inputs 431 | forward = Vector3::Normalized(forward); 432 | upwards = Vector3::Normalized(upwards); 433 | // Don't allow zero vectors 434 | if (Vector3::SqrMagnitude(forward) < SMALL_float || Vector3::SqrMagnitude(upwards) < SMALL_float) 435 | return Quaternion::Identity(); 436 | // Handle alignment with up direction 437 | if (1 - fabs(Vector3::Dot(forward, upwards)) < SMALL_float) 438 | return FromToRotation(Vector3::Forward(), forward); 439 | // Get orthogonal vectors 440 | Vector3 right = Vector3::Normalized(Vector3::Cross(upwards, forward)); 441 | upwards = Vector3::Cross(forward, right); 442 | // Calculate rotation 443 | Quaternion quaternion; 444 | float radicand = right.X + upwards.Y + forward.Z; 445 | if (radicand > 0) 446 | { 447 | quaternion.W = sqrt(1.0 + radicand) * 0.5; 448 | float recip = 1.0 / (4.0 * quaternion.W); 449 | quaternion.X = (upwards.Z - forward.Y) * recip; 450 | quaternion.Y = (forward.X - right.Z) * recip; 451 | quaternion.Z = (right.Y - upwards.X) * recip; 452 | } 453 | else if (right.X >= upwards.Y && right.X >= forward.Z) 454 | { 455 | quaternion.X = sqrt(1.0 + right.X - upwards.Y - forward.Z) * 0.5; 456 | float recip = 1.0 / (4.0 * quaternion.X); 457 | quaternion.W = (upwards.Z - forward.Y) * recip; 458 | quaternion.Z = (forward.X + right.Z) * recip; 459 | quaternion.Y = (right.Y + upwards.X) * recip; 460 | } 461 | else if (upwards.Y > forward.Z) 462 | { 463 | quaternion.Y = sqrt(1.0 - right.X + upwards.Y - forward.Z) * 0.5; 464 | float recip = 1.0 / (4.0 * quaternion.Y); 465 | quaternion.Z = (upwards.Z + forward.Y) * recip; 466 | quaternion.W = (forward.X - right.Z) * recip; 467 | quaternion.X = (right.Y + upwards.X) * recip; 468 | } 469 | else 470 | { 471 | quaternion.Z = sqrt(1.0 - right.X - upwards.Y + forward.Z) * 0.5; 472 | float recip = 1.0 / (4.0 * quaternion.Z); 473 | quaternion.Y = (upwards.Z + forward.Y) * recip; 474 | quaternion.X = (forward.X + right.Z) * recip; 475 | quaternion.W = (right.Y - upwards.X) * recip; 476 | } 477 | return quaternion; 478 | } 479 | 480 | float Quaternion::Norm(Quaternion rotation) 481 | { 482 | return sqrt(rotation.X * rotation.X + 483 | rotation.Y * rotation.Y + 484 | rotation.Z * rotation.Z + 485 | rotation.W * rotation.W); 486 | } 487 | 488 | Quaternion Quaternion::Normalized(Quaternion rotation) 489 | { 490 | return rotation / Norm(rotation); 491 | } 492 | 493 | Quaternion Quaternion::RotateTowards(Quaternion from, Quaternion to, 494 | float maxRadiansDelta) 495 | { 496 | float angle = Quaternion::Angle(from, to); 497 | if (angle == 0) 498 | return to; 499 | maxRadiansDelta = fmax(maxRadiansDelta, angle - M_PI); 500 | float t = fmin(1, maxRadiansDelta / angle); 501 | return Quaternion::SlerpUnclamped(from, to, t); 502 | } 503 | 504 | Quaternion Quaternion::Slerp(Quaternion a, Quaternion b, float t) 505 | { 506 | if (t < 0) return Normalized(a); 507 | else if (t > 1) return Normalized(b); 508 | return SlerpUnclamped(a, b, t); 509 | } 510 | 511 | Quaternion Quaternion::SlerpUnclamped(Quaternion a, Quaternion b, float t) 512 | { 513 | float n1; 514 | float n2; 515 | float n3 = Dot(a, b); 516 | bool flag = false; 517 | if (n3 < 0) 518 | { 519 | flag = true; 520 | n3 = -n3; 521 | } 522 | if (n3 > 0.999999) 523 | { 524 | n2 = 1 - t; 525 | n1 = flag ? -t : t; 526 | } 527 | else 528 | { 529 | float n4 = acos(n3); 530 | float n5 = 1 / sin(n4); 531 | n2 = sin((1 - t) * n4) * n5; 532 | n1 = flag ? -sin(t * n4) * n5 : sin(t * n4) * n5; 533 | } 534 | Quaternion quaternion; 535 | quaternion.X = (n2 * a.X) + (n1 * b.X); 536 | quaternion.Y = (n2 * a.Y) + (n1 * b.Y); 537 | quaternion.Z = (n2 * a.Z) + (n1 * b.Z); 538 | quaternion.W = (n2 * a.W) + (n1 * b.W); 539 | return Normalized(quaternion); 540 | } 541 | 542 | void Quaternion::ToAngleAxis(Quaternion rotation, float &angle, Vector3 &axis) 543 | { 544 | if (rotation.W > 1) 545 | rotation = Normalized(rotation); 546 | angle = 2 * acos(rotation.W); 547 | float s = sqrt(1 - rotation.W * rotation.W); 548 | if (s < 0.00001) { 549 | axis.X = 1; 550 | axis.Y = 0; 551 | axis.Z = 0; 552 | } else { 553 | axis.X = rotation.X / s; 554 | axis.Y = rotation.Y / s; 555 | axis.Z = rotation.Z / s; 556 | } 557 | } 558 | 559 | Vector3 Quaternion::ToEuler(Quaternion rotation) 560 | { 561 | float sqw = rotation.W * rotation.W; 562 | float sqx = rotation.X * rotation.X; 563 | float sqy = rotation.Y * rotation.Y; 564 | float sqz = rotation.Z * rotation.Z; 565 | // If normalized is one, otherwise is correction factor 566 | float unit = sqx + sqy + sqz + sqw; 567 | float test = rotation.X * rotation.W - rotation.Y * rotation.Z; 568 | Vector3 v; 569 | // Singularity at north pole 570 | if (test > 0.4995f * unit) 571 | { 572 | v.Y = 2 * atan2(rotation.Y, rotation.X); 573 | v.X = M_PI_2; 574 | v.Z = 0; 575 | return v; 576 | } 577 | // Singularity at south pole 578 | if (test < -0.4995f * unit) 579 | { 580 | v.Y = -2 * atan2(rotation.Y, rotation.X); 581 | v.X = -M_PI_2; 582 | v.Z = 0; 583 | return v; 584 | } 585 | // Yaw 586 | v.Y = atan2(2 * rotation.W * rotation.Y + 2 * rotation.Z * rotation.X, 587 | 1 - 2 * (rotation.X * rotation.X + rotation.Y * rotation.Y)); 588 | // Pitch 589 | v.X = asin(2 * (rotation.W * rotation.X - rotation.Y * rotation.Z)); 590 | // Roll 591 | v.Z = atan2(2 * rotation.W * rotation.Z + 2 * rotation.X * rotation.Y, 592 | 1 - 2 * (rotation.Z * rotation.Z + rotation.X * rotation.X)); 593 | return v; 594 | } 595 | 596 | struct Quaternion& Quaternion::operator+=(const float rhs) 597 | { 598 | X += rhs; 599 | Y += rhs; 600 | Z += rhs; 601 | W += rhs; 602 | return *this; 603 | } 604 | 605 | struct Quaternion& Quaternion::operator-=(const float rhs) 606 | { 607 | X -= rhs; 608 | Y -= rhs; 609 | Z -= rhs; 610 | W -= rhs; 611 | return *this; 612 | } 613 | 614 | struct Quaternion& Quaternion::operator*=(const float rhs) 615 | { 616 | X *= rhs; 617 | Y *= rhs; 618 | Z *= rhs; 619 | W *= rhs; 620 | return *this; 621 | } 622 | 623 | struct Quaternion& Quaternion::operator/=(const float rhs) 624 | { 625 | X /= rhs; 626 | Y /= rhs; 627 | Z /= rhs; 628 | W /= rhs; 629 | return *this; 630 | } 631 | 632 | struct Quaternion& Quaternion::operator+=(const Quaternion rhs) 633 | { 634 | X += rhs.X; 635 | Y += rhs.Y; 636 | Z += rhs.Z; 637 | W += rhs.W; 638 | return *this; 639 | } 640 | 641 | struct Quaternion& Quaternion::operator-=(const Quaternion rhs) 642 | { 643 | X -= rhs.X; 644 | Y -= rhs.Y; 645 | Z -= rhs.Z; 646 | W -= rhs.W; 647 | return *this; 648 | } 649 | 650 | struct Quaternion& Quaternion::operator*=(const Quaternion rhs) 651 | { 652 | Quaternion q; 653 | q.W = W * rhs.W - X * rhs.X - Y * rhs.Y - Z * rhs.Z; 654 | q.X = X * rhs.W + W * rhs.X + Y * rhs.Z - Z * rhs.Y; 655 | q.Y = W * rhs.Y - X * rhs.Z + Y * rhs.W + Z * rhs.X; 656 | q.Z = W * rhs.Z + X * rhs.Y - Y * rhs.X + Z * rhs.W; 657 | *this = q; 658 | return *this; 659 | } 660 | 661 | Quaternion operator-(Quaternion rhs) { return rhs * -1; } 662 | Quaternion operator+(Quaternion lhs, const float rhs) { return lhs += rhs; } 663 | Quaternion operator-(Quaternion lhs, const float rhs) { return lhs -= rhs; } 664 | Quaternion operator*(Quaternion lhs, const float rhs) { return lhs *= rhs; } 665 | Quaternion operator/(Quaternion lhs, const float rhs) { return lhs /= rhs; } 666 | Quaternion operator+(const float lhs, Quaternion rhs) { return rhs += lhs; } 667 | Quaternion operator-(const float lhs, Quaternion rhs) { return rhs -= lhs; } 668 | Quaternion operator*(const float lhs, Quaternion rhs) { return rhs *= lhs; } 669 | Quaternion operator/(const float lhs, Quaternion rhs) { return rhs /= lhs; } 670 | Quaternion operator+(Quaternion lhs, const Quaternion rhs) 671 | { 672 | return lhs += rhs; 673 | } 674 | Quaternion operator-(Quaternion lhs, const Quaternion rhs) 675 | { 676 | return lhs -= rhs; 677 | } 678 | Quaternion operator*(Quaternion lhs, const Quaternion rhs) 679 | { 680 | return lhs *= rhs; 681 | } 682 | 683 | Vector3 operator*(Quaternion lhs, const Vector3 rhs) 684 | { 685 | Vector3 u = Vector3(lhs.X, lhs.Y, lhs.Z); 686 | float s = lhs.W; 687 | return u * (Vector3::Dot(u, rhs) * 2) 688 | + rhs * (s * s - Vector3::Dot(u, u)) 689 | + Vector3::Cross(u, rhs) * (2.0 * s); 690 | } 691 | 692 | bool operator==(const Quaternion lhs, const Quaternion rhs) 693 | { 694 | return lhs.X == rhs.X && 695 | lhs.Y == rhs.Y && 696 | lhs.Z == rhs.Z && 697 | lhs.W == rhs.W; 698 | } 699 | 700 | bool operator!=(const Quaternion lhs, const Quaternion rhs) 701 | { 702 | return !(lhs == rhs); 703 | } -------------------------------------------------------------------------------- /app/src/main/cpp/Engine/API/Rect.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define _USE_MATH_DEFINES 4 | #include 5 | #include 6 | 7 | struct Rect 8 | { 9 | union 10 | { 11 | struct 12 | { 13 | float x; 14 | float y; 15 | float width; 16 | float height; 17 | }; 18 | float data[4]; 19 | }; 20 | 21 | inline Rect(); 22 | inline Rect(float XMin, float YMin, float Width, float Height); 23 | }; 24 | 25 | Rect::Rect() : x(0), y(0), width(0), height(0) {} 26 | Rect::Rect(float XMin, float YMin, float Width, float Height) : x(XMin), y(YMin), width(Width), height(Height) {} 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/cpp/Engine/API/Unity.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "API.h" 11 | #include "Rect.hpp" 12 | #include "Color.hpp" 13 | #include "Vector3.hpp" 14 | #include "Vector2.hpp" 15 | #include "Matrix4x4.hpp" 16 | #include "Quaternion.hpp" 17 | 18 | static inline float NormalizeAngle(float angle) { 19 | while (angle > 360) 20 | angle -= 360; 21 | while (angle < 0) 22 | angle += 360; 23 | return angle; 24 | } 25 | 26 | static inline Vector3 NormalizeAngles(Vector3 angles) { 27 | angles.X = NormalizeAngle(angles.X); 28 | angles.Y = NormalizeAngle(angles.Y); 29 | angles.Z = NormalizeAngle(angles.Z); 30 | return angles; 31 | } 32 | 33 | static inline Vector3 ToEulerRad(Quaternion q1) { 34 | float Rad2Deg = 360.0 / (M_PI * 2.0); 35 | 36 | float sqw = q1.W * q1.W; 37 | float sqx = q1.X * q1.X; 38 | float sqy = q1.Y * q1.Y; 39 | float sqz = q1.Z * q1.Z; 40 | float unit = sqx + sqy + sqz + sqw; 41 | float test = q1.X * q1.W - q1.Y * q1.Z; 42 | Vector3 v; 43 | 44 | if (test > 0.4995 * unit) { 45 | v.Y = 2.0 * atan2f(q1.Y, q1.X); 46 | v.X = M_PI / 2.0; 47 | v.Z = 0; 48 | return NormalizeAngles(v * Rad2Deg); 49 | } 50 | if (test < -0.4995 * unit) { 51 | v.Y = -2.0 * atan2f(q1.Y, q1.X); 52 | v.X = -M_PI / 2.0; 53 | v.Z = 0; 54 | return NormalizeAngles(v * Rad2Deg); 55 | } 56 | Quaternion q(q1.W, q1.Z, q1.X, q1.Y); 57 | v.Y = atan2f(2.0 * q.X * q.W + 2.0 * q.Y * q.Z, 1 - 2.0 * (q.Z * q.Z + q.W * q.W)); // yaw 58 | v.X = asinf(2.0 * (q.X * q.Z - q.W * q.Y)); // pitch 59 | v.Z = atan2f(2.0 * q.X * q.Y + 2.0 * q.Z * q.W, 1 - 2.0 * (q.Y * q.Y + q.Z * q.Z)); // roll 60 | return NormalizeAngles(v * Rad2Deg); 61 | } 62 | 63 | static inline Quaternion GetRotationToLocation(Vector3 targetLocation, float y_bias, Vector3 myLoc) { 64 | return Quaternion::LookRotation((targetLocation + Vector3(0, y_bias, 0)) - myLoc, 65 | Vector3(0, 1, 0)); 66 | } 67 | 68 | template 69 | struct monoArray { 70 | void *klass; 71 | void *monitor; 72 | void *bounds; 73 | int max_length; 74 | void *vector[1]; 75 | 76 | int getLength() { 77 | return max_length; 78 | } 79 | 80 | T getPointer() { 81 | return (T) vector; 82 | } 83 | }; 84 | 85 | template 86 | struct monoList { 87 | void *unk0; 88 | void *unk1; 89 | monoArray *items; 90 | int size; 91 | int version; 92 | 93 | T getItems() { 94 | return items->getPointer(); 95 | } 96 | 97 | auto operator[](int dex) { 98 | return items->getPointer()[dex]; 99 | } 100 | 101 | int getSize() { 102 | return size; 103 | } 104 | 105 | int getVersion() { 106 | return version; 107 | } 108 | }; 109 | 110 | template 111 | struct monoDictionary { 112 | void *unk0; 113 | void *unk1; 114 | monoArray *table; 115 | monoArray *linkSlots; 116 | monoArray *keys; 117 | monoArray *values; 118 | int touchedSlots; 119 | int emptySlot; 120 | int size; 121 | 122 | K getKeys() { 123 | return keys->getPointer(); 124 | } 125 | 126 | V getValues() { 127 | return values->getPointer(); 128 | } 129 | 130 | int getNumKeys() { 131 | return keys->getLength(); 132 | } 133 | 134 | int getNumValues() { 135 | return values->getLength(); 136 | } 137 | 138 | int getSize() { 139 | return size; 140 | } 141 | }; -------------------------------------------------------------------------------- /app/src/main/cpp/Engine/API/Vector2.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define _USE_MATH_DEFINES 4 | #include 5 | 6 | 7 | struct Vector2 8 | { 9 | union 10 | { 11 | struct 12 | { 13 | float X; 14 | float Y; 15 | }; 16 | float data[2]; 17 | }; 18 | 19 | 20 | /** 21 | * Constructors. 22 | */ 23 | inline Vector2(); 24 | inline Vector2(float value); 25 | inline Vector2(float x, float y); 26 | 27 | 28 | /** 29 | * Constants for common vectors. 30 | */ 31 | static inline Vector2 Zero(); 32 | static inline Vector2 One(); 33 | static inline Vector2 Right(); 34 | static inline Vector2 Left(); 35 | static inline Vector2 Up(); 36 | static inline Vector2 Down(); 37 | 38 | 39 | /** 40 | * Returns the angle between two vectors in radians. 41 | * @param a: The first vector. 42 | * @param b: The second vector. 43 | * @return: A scalar value. 44 | */ 45 | static inline float Angle(Vector2 a, Vector2 b); 46 | 47 | /** 48 | * Returns a vector with its magnitude clamped to maxLength. 49 | * @param vector: The target vector. 50 | * @param maxLength: The maximum length of the return vector. 51 | * @return: A new vector. 52 | */ 53 | static inline Vector2 ClampMagnitude(Vector2 vector, float maxLength); 54 | 55 | /** 56 | * Returns the component of a in the direction of b (scalar projection). 57 | * @param a: The target vector. 58 | * @param b: The vector being compared against. 59 | * @return: A scalar value. 60 | */ 61 | static inline float Component(Vector2 a, Vector2 b); 62 | 63 | /** 64 | * Returns the distance between a and b. 65 | * @param a: The first point. 66 | * @param b: The second point. 67 | * @return: A scalar value. 68 | */ 69 | static inline float Distance(Vector2 a, Vector2 b); 70 | 71 | static inline std::string ToString(Vector2 a); 72 | 73 | /** 74 | * Returns the dot product of two vectors. 75 | * @param lhs: The left side of the multiplication. 76 | * @param rhs: The right side of the multiplication. 77 | * @return: A scalar value. 78 | */ 79 | static inline float Dot(Vector2 lhs, Vector2 rhs); 80 | 81 | /** 82 | * Converts a polar representation of a vector into cartesian 83 | * coordinates. 84 | * @param rad: The magnitude of the vector. 85 | * @param theta: The angle from the X axis. 86 | * @return: A new vector. 87 | */ 88 | static inline Vector2 FromPolar(float rad, float theta); 89 | 90 | /** 91 | * Returns a vector linearly interpolated between a and b, moving along 92 | * a straight line. The vector is clamped to never go beyond the end points. 93 | * @param a: The starting point. 94 | * @param b: The ending point. 95 | * @param t: The interpolation value [0-1]. 96 | * @return: A new vector. 97 | */ 98 | static inline Vector2 Lerp(Vector2 a, Vector2 b, float t); 99 | 100 | /** 101 | * Returns a vector linearly interpolated between a and b, moving along 102 | * a straight line. 103 | * @param a: The starting point. 104 | * @param b: The ending point. 105 | * @param t: The interpolation value [0-1] (no actual bounds). 106 | * @return: A new vector. 107 | */ 108 | static inline Vector2 LerpUnclamped(Vector2 a, Vector2 b, float t); 109 | 110 | /** 111 | * Returns the magnitude of a vector. 112 | * @param v: The vector in question. 113 | * @return: A scalar value. 114 | */ 115 | static inline float Magnitude(Vector2 v); 116 | 117 | /** 118 | * Returns a vector made from the largest components of two other vectors. 119 | * @param a: The first vector. 120 | * @param b: The second vector. 121 | * @return: A new vector. 122 | */ 123 | static inline Vector2 Max(Vector2 a, Vector2 b); 124 | 125 | /** 126 | * Returns a vector made from the smallest components of two other vectors. 127 | * @param a: The first vector. 128 | * @param b: The second vector. 129 | * @return: A new vector. 130 | */ 131 | static inline Vector2 Min(Vector2 a, Vector2 b); 132 | 133 | /** 134 | * Returns a vector "maxDistanceDelta" units closer to the target. This 135 | * interpolation is in a straight line, and will not overshoot. 136 | * @param current: The current position. 137 | * @param target: The destination position. 138 | * @param maxDistanceDelta: The maximum distance to move. 139 | * @return: A new vector. 140 | */ 141 | static inline Vector2 MoveTowards(Vector2 current, Vector2 target, 142 | float maxDistanceDelta); 143 | 144 | /** 145 | * Returns a new vector with magnitude of one. 146 | * @param v: The vector in question. 147 | * @return: A new vector. 148 | */ 149 | static inline Vector2 Normalized(Vector2 v); 150 | 151 | /** 152 | * Creates a new coordinate system out of the two vectors. 153 | * Normalizes "normal" and normalizes "tangent" and makes it orthogonal to 154 | * "normal".. 155 | * @param normal: A reference to the first axis vector. 156 | * @param tangent: A reference to the second axis vector. 157 | */ 158 | static inline void OrthoNormalize(Vector2 &normal, Vector2 &tangent); 159 | 160 | /** 161 | * Returns the vector projection of a onto b. 162 | * @param a: The target vector. 163 | * @param b: The vector being projected onto. 164 | * @return: A new vector. 165 | */ 166 | static inline Vector2 Project(Vector2 a, Vector2 b); 167 | 168 | /** 169 | * Returns a vector reflected about the provided line. 170 | * This behaves as if there is a plane with the line as its normal, and the 171 | * vector comes in and bounces off this plane. 172 | * @param vector: The vector traveling inward at the imaginary plane. 173 | * @param line: The line about which to reflect. 174 | * @return: A new vector pointing outward from the imaginary plane. 175 | */ 176 | static inline Vector2 Reflect(Vector2 vector, Vector2 line); 177 | 178 | /** 179 | * Returns the vector rejection of a on b. 180 | * @param a: The target vector. 181 | * @param b: The vector being projected onto. 182 | * @return: A new vector. 183 | */ 184 | static inline Vector2 Reject(Vector2 a, Vector2 b); 185 | 186 | /** 187 | * Rotates vector "current" towards vector "target" by "maxRadiansDelta". 188 | * This treats the vectors as directions and will linearly interpolate 189 | * between their magnitudes by "maxMagnitudeDelta". This function does not 190 | * overshoot. If a negative delta is supplied, it will rotate away from 191 | * "target" until it is pointing the opposite direction, but will not 192 | * overshoot that either. 193 | * @param current: The starting direction. 194 | * @param target: The destination direction. 195 | * @param maxRadiansDelta: The maximum number of radians to rotate. 196 | * @param maxMagnitudeDelta: The maximum delta for magnitude interpolation. 197 | * @return: A new vector. 198 | */ 199 | static inline Vector2 RotateTowards(Vector2 current, Vector2 target, 200 | float maxRadiansDelta, 201 | float maxMagnitudeDelta); 202 | 203 | /** 204 | * Multiplies two vectors component-wise. 205 | * @param a: The lhs of the multiplication. 206 | * @param b: The rhs of the multiplication. 207 | * @return: A new vector. 208 | */ 209 | static inline Vector2 Scale(Vector2 a, Vector2 b); 210 | 211 | /** 212 | * Returns a vector rotated towards b from a by the percent t. 213 | * Since interpolation is done spherically, the vector moves at a constant 214 | * angular velocity. This rotation is clamped to 0 <= t <= 1. 215 | * @param a: The starting direction. 216 | * @param b: The ending direction. 217 | * @param t: The interpolation value [0-1]. 218 | */ 219 | static inline Vector2 Slerp(Vector2 a, Vector2 b, float t); 220 | 221 | /** 222 | * Returns a vector rotated towards b from a by the percent t. 223 | * Since interpolation is done spherically, the vector moves at a constant 224 | * angular velocity. This rotation is unclamped. 225 | * @param a: The starting direction. 226 | * @param b: The ending direction. 227 | * @param t: The interpolation value [0-1]. 228 | */ 229 | static inline Vector2 SlerpUnclamped(Vector2 a, Vector2 b, float t); 230 | 231 | /** 232 | * Returns the squared magnitude of a vector. 233 | * This is useful when comparing relative lengths, where the exact length 234 | * is not important, and much time can be saved by not calculating the 235 | * square root. 236 | * @param v: The vector in question. 237 | * @return: A scalar value. 238 | */ 239 | static inline float SqrMagnitude(Vector2 v); 240 | 241 | /** 242 | * Calculates the polar coordinate space representation of a vector. 243 | * @param vector: The vector to convert. 244 | * @param rad: The magnitude of the vector. 245 | * @param theta: The angle from the X axis. 246 | */ 247 | static inline void ToPolar(Vector2 vector, float &rad, float &theta); 248 | 249 | 250 | /** 251 | * Operator overloading. 252 | */ 253 | inline struct Vector2& operator+=(const float rhs); 254 | inline struct Vector2& operator-=(const float rhs); 255 | inline struct Vector2& operator*=(const float rhs); 256 | inline struct Vector2& operator/=(const float rhs); 257 | inline struct Vector2& operator+=(const Vector2 rhs); 258 | inline struct Vector2& operator-=(const Vector2 rhs); 259 | }; 260 | 261 | inline Vector2 operator-(Vector2 rhs); 262 | inline Vector2 operator+(Vector2 lhs, const float rhs); 263 | inline Vector2 operator-(Vector2 lhs, const float rhs); 264 | inline Vector2 operator*(Vector2 lhs, const float rhs); 265 | inline Vector2 operator/(Vector2 lhs, const float rhs); 266 | inline Vector2 operator+(const float lhs, Vector2 rhs); 267 | inline Vector2 operator-(const float lhs, Vector2 rhs); 268 | inline Vector2 operator*(const float lhs, Vector2 rhs); 269 | inline Vector2 operator/(const float lhs, Vector2 rhs); 270 | inline Vector2 operator+(Vector2 lhs, const Vector2 rhs); 271 | inline Vector2 operator-(Vector2 lhs, const Vector2 rhs); 272 | inline bool operator==(const Vector2 lhs, const Vector2 rhs); 273 | inline bool operator!=(const Vector2 lhs, const Vector2 rhs); 274 | 275 | 276 | 277 | /******************************************************************************* 278 | * Implementation 279 | */ 280 | 281 | Vector2::Vector2() : X(0), Y(0) {} 282 | Vector2::Vector2(float value) : X(value), Y(value) {} 283 | Vector2::Vector2(float x, float y) : X(x), Y(y) {} 284 | 285 | 286 | Vector2 Vector2::Zero() { return Vector2(0, 0); } 287 | Vector2 Vector2::One() { return Vector2(1, 1); } 288 | Vector2 Vector2::Right() { return Vector2(1, 0); } 289 | Vector2 Vector2::Left() { return Vector2(-1, 0); } 290 | Vector2 Vector2::Up() { return Vector2(0, 1); } 291 | Vector2 Vector2::Down() { return Vector2(0, -1); } 292 | 293 | 294 | float Vector2::Angle(Vector2 a, Vector2 b) 295 | { 296 | float v = Dot(a, b) / (Magnitude(a) * Magnitude(b)); 297 | v = fmax(v, -1.0); 298 | v = fmin(v, 1.0); 299 | return acos(v); 300 | } 301 | 302 | Vector2 Vector2::ClampMagnitude(Vector2 vector, float maxLength) 303 | { 304 | float length = Magnitude(vector); 305 | if (length > maxLength) 306 | vector *= maxLength / length; 307 | return vector; 308 | } 309 | 310 | float Vector2::Component(Vector2 a, Vector2 b) 311 | { 312 | return Dot(a, b) / Magnitude(b); 313 | } 314 | 315 | float Vector2::Distance(Vector2 a, Vector2 b) 316 | { 317 | return Vector2::Magnitude(a - b); 318 | } 319 | 320 | std::string Vector2::ToString(Vector2 a){ 321 | return to_string((int) a.X) + ", " + to_string((int) a.Y); 322 | } 323 | 324 | float Vector2::Dot(Vector2 lhs, Vector2 rhs) 325 | { 326 | return lhs.X * rhs.X + lhs.Y * rhs.Y; 327 | } 328 | 329 | Vector2 Vector2::FromPolar(float rad, float theta) 330 | { 331 | Vector2 v; 332 | v.X = rad * cos(theta); 333 | v.Y = rad * sin(theta); 334 | return v; 335 | } 336 | 337 | Vector2 Vector2::Lerp(Vector2 a, Vector2 b, float t) 338 | { 339 | if (t < 0) return a; 340 | else if (t > 1) return b; 341 | return LerpUnclamped(a, b, t); 342 | } 343 | 344 | Vector2 Vector2::LerpUnclamped(Vector2 a, Vector2 b, float t) 345 | { 346 | return (b - a) * t + a; 347 | } 348 | 349 | float Vector2::Magnitude(Vector2 v) 350 | { 351 | return sqrt(SqrMagnitude(v)); 352 | } 353 | 354 | Vector2 Vector2::Max(Vector2 a, Vector2 b) 355 | { 356 | float x = a.X > b.X ? a.X : b.X; 357 | float y = a.Y > b.Y ? a.Y : b.Y; 358 | return Vector2(x, y); 359 | } 360 | 361 | Vector2 Vector2::Min(Vector2 a, Vector2 b) 362 | { 363 | float x = a.X > b.X ? b.X : a.X; 364 | float y = a.Y > b.Y ? b.Y : a.Y; 365 | return Vector2(x, y); 366 | } 367 | 368 | Vector2 Vector2::MoveTowards(Vector2 current, Vector2 target, 369 | float maxDistanceDelta) 370 | { 371 | Vector2 d = target - current; 372 | float m = Magnitude(d); 373 | if (m < maxDistanceDelta || m == 0) 374 | return target; 375 | return current + (d * maxDistanceDelta / m); 376 | } 377 | 378 | Vector2 Vector2::Normalized(Vector2 v) 379 | { 380 | float mag = Magnitude(v); 381 | if (mag == 0) 382 | return Vector2::Zero(); 383 | return v / mag; 384 | } 385 | 386 | void Vector2::OrthoNormalize(Vector2 &normal, Vector2 &tangent) 387 | { 388 | normal = Normalized(normal); 389 | tangent = Reject(tangent, normal); 390 | tangent = Normalized(tangent); 391 | } 392 | 393 | Vector2 Vector2::Project(Vector2 a, Vector2 b) 394 | { 395 | float m = Magnitude(b); 396 | return Dot(a, b) / (m * m) * b; 397 | } 398 | 399 | Vector2 Vector2::Reflect(Vector2 vector, Vector2 planeNormal) 400 | { 401 | return vector - 2 * Project(vector, planeNormal); 402 | } 403 | 404 | Vector2 Vector2::Reject(Vector2 a, Vector2 b) 405 | { 406 | return a - Project(a, b); 407 | } 408 | 409 | Vector2 Vector2::RotateTowards(Vector2 current, Vector2 target, 410 | float maxRadiansDelta, 411 | float maxMagnitudeDelta) 412 | { 413 | float magCur = Magnitude(current); 414 | float magTar = Magnitude(target); 415 | float newMag = magCur + maxMagnitudeDelta * 416 | ((magTar > magCur) - (magCur > magTar)); 417 | newMag = fmin(newMag, fmax(magCur, magTar)); 418 | newMag = fmax(newMag, fmin(magCur, magTar)); 419 | 420 | float totalAngle = Angle(current, target) - maxRadiansDelta; 421 | if (totalAngle <= 0) 422 | return Normalized(target) * newMag; 423 | else if (totalAngle >= M_PI) 424 | return Normalized(-target) * newMag; 425 | 426 | float axis = current.X * target.Y - current.Y * target.X; 427 | axis = axis / fabs(axis); 428 | if (1 - fabs(axis) >= 0.00001) 429 | axis = 1; 430 | current = Normalized(current); 431 | Vector2 newVector = current * cos(maxRadiansDelta) + 432 | Vector2(-current.Y, current.X) * sin(maxRadiansDelta) * axis; 433 | return newVector * newMag; 434 | } 435 | 436 | Vector2 Vector2::Scale(Vector2 a, Vector2 b) 437 | { 438 | return Vector2(a.X * b.X, a.Y * b.Y); 439 | } 440 | 441 | Vector2 Vector2::Slerp(Vector2 a, Vector2 b, float t) 442 | { 443 | if (t < 0) return a; 444 | else if (t > 1) return b; 445 | return SlerpUnclamped(a, b, t); 446 | } 447 | 448 | Vector2 Vector2::SlerpUnclamped(Vector2 a, Vector2 b, float t) 449 | { 450 | float magA = Magnitude(a); 451 | float magB = Magnitude(b); 452 | a /= magA; 453 | b /= magB; 454 | float dot = Dot(a, b); 455 | dot = fmax(dot, -1.0); 456 | dot = fmin(dot, 1.0); 457 | float theta = acos(dot) * t; 458 | Vector2 relativeVec = Normalized(b - a * dot); 459 | Vector2 newVec = a * cos(theta) + relativeVec * sin(theta); 460 | return newVec * (magA + (magB - magA) * t); 461 | } 462 | 463 | float Vector2::SqrMagnitude(Vector2 v) 464 | { 465 | return v.X * v.X + v.Y * v.Y; 466 | } 467 | 468 | void Vector2::ToPolar(Vector2 vector, float &rad, float &theta) 469 | { 470 | rad = Magnitude(vector); 471 | theta = atan2(vector.Y, vector.X); 472 | } 473 | 474 | 475 | struct Vector2& Vector2::operator+=(const float rhs) 476 | { 477 | X += rhs; 478 | Y += rhs; 479 | return *this; 480 | } 481 | 482 | struct Vector2& Vector2::operator-=(const float rhs) 483 | { 484 | X -= rhs; 485 | Y -= rhs; 486 | return *this; 487 | } 488 | 489 | struct Vector2& Vector2::operator*=(const float rhs) 490 | { 491 | X *= rhs; 492 | Y *= rhs; 493 | return *this; 494 | } 495 | 496 | struct Vector2& Vector2::operator/=(const float rhs) 497 | { 498 | X /= rhs; 499 | Y /= rhs; 500 | return *this; 501 | } 502 | 503 | struct Vector2& Vector2::operator+=(const Vector2 rhs) 504 | { 505 | X += rhs.X; 506 | Y += rhs.Y; 507 | return *this; 508 | } 509 | 510 | struct Vector2& Vector2::operator-=(const Vector2 rhs) 511 | { 512 | X -= rhs.X; 513 | Y -= rhs.Y; 514 | return *this; 515 | } 516 | 517 | Vector2 operator-(Vector2 rhs) { return rhs * -1; } 518 | Vector2 operator+(Vector2 lhs, const float rhs) { return lhs += rhs; } 519 | Vector2 operator-(Vector2 lhs, const float rhs) { return lhs -= rhs; } 520 | Vector2 operator*(Vector2 lhs, const float rhs) { return lhs *= rhs; } 521 | Vector2 operator/(Vector2 lhs, const float rhs) { return lhs /= rhs; } 522 | Vector2 operator+(const float lhs, Vector2 rhs) { return rhs += lhs; } 523 | Vector2 operator-(const float lhs, Vector2 rhs) { return rhs -= lhs; } 524 | Vector2 operator*(const float lhs, Vector2 rhs) { return rhs *= lhs; } 525 | Vector2 operator/(const float lhs, Vector2 rhs) { return rhs /= lhs; } 526 | Vector2 operator+(Vector2 lhs, const Vector2 rhs) { return lhs += rhs; } 527 | Vector2 operator-(Vector2 lhs, const Vector2 rhs) { return lhs -= rhs; } 528 | 529 | bool operator==(const Vector2 lhs, const Vector2 rhs) 530 | { 531 | return lhs.X == rhs.X && lhs.Y == rhs.Y; 532 | } 533 | 534 | bool operator!=(const Vector2 lhs, const Vector2 rhs) 535 | { 536 | return !(lhs == rhs); 537 | } -------------------------------------------------------------------------------- /app/src/main/cpp/Engine/API/Vector3.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define _USE_MATH_DEFINES 4 | #include 5 | #include 6 | 7 | 8 | struct Vector3 9 | { 10 | union 11 | { 12 | struct 13 | { 14 | float X; 15 | float Y; 16 | float Z; 17 | }; 18 | float data[3]; 19 | }; 20 | 21 | 22 | /** 23 | * Constructors. 24 | */ 25 | inline Vector3(); 26 | inline Vector3(float data[]); 27 | inline Vector3(float value); 28 | inline Vector3(float x, float y); 29 | inline Vector3(float x, float y, float z); 30 | 31 | 32 | /** 33 | * Constants for common vectors. 34 | */ 35 | static inline Vector3 Zero(); 36 | static inline Vector3 One(); 37 | static inline Vector3 Right(); 38 | static inline Vector3 Left(); 39 | static inline Vector3 Up(); 40 | static inline Vector3 Down(); 41 | static inline Vector3 Forward(); 42 | static inline Vector3 Backward(); 43 | 44 | 45 | /** 46 | * Returns the angle between two vectors in radians. 47 | * @param a: The first vector. 48 | * @param b: The second vector. 49 | * @return: A scalar value. 50 | */ 51 | static inline float Angle(Vector3 a, Vector3 b); 52 | 53 | /** 54 | * Returns a vector with its magnitude clamped to maxLength. 55 | * @param vector: The target vector. 56 | * @param maxLength: The maximum length of the return vector. 57 | * @return: A new vector. 58 | */ 59 | static inline Vector3 ClampMagnitude(Vector3 vector, float maxLength); 60 | 61 | /** 62 | * Returns the component of a in the direction of b (scalar projection). 63 | * @param a: The target vector. 64 | * @param b: The vector being compared against. 65 | * @return: A scalar value. 66 | */ 67 | static inline float Component(Vector3 a, Vector3 b); 68 | 69 | /** 70 | * Returns the cross product of two vectors. 71 | * @param lhs: The left side of the multiplication. 72 | * @param rhs: The right side of the multiplication. 73 | * @return: A new vector. 74 | */ 75 | static inline Vector3 Cross(Vector3 lhs, Vector3 rhs); 76 | 77 | /** 78 | * Returns the distance between a and b. 79 | * @param a: The first point. 80 | * @param b: The second point. 81 | * @return: A scalar value. 82 | */ 83 | static inline float Distance(Vector3 a, Vector3 b); 84 | 85 | static inline std::string ToString(Vector3 a); 86 | 87 | /** 88 | * Returns the dot product of two vectors. 89 | * @param lhs: The left side of the multiplication. 90 | * @param rhs: The right side of the multiplication. 91 | * @return: A scalar value. 92 | */ 93 | static inline float Dot(Vector3 lhs, Vector3 rhs); 94 | 95 | /** 96 | * Converts a spherical representation of a vector into cartesian 97 | * coordinates. 98 | * This uses the ISO convention (radius r, inclination theta, azimuth phi). 99 | * @param rad: The magnitude of the vector. 100 | * @param theta: The angle in the XY plane from the X axis. 101 | * @param phi: The angle from the positive Z axis to the vector. 102 | * @return: A new vector. 103 | */ 104 | static inline Vector3 FromSpherical(float rad, float theta, float phi); 105 | 106 | /** 107 | * Returns a vector linearly interpolated between a and b, moving along 108 | * a straight line. The vector is clamped to never go beyond the end points. 109 | * @param a: The starting point. 110 | * @param b: The ending point. 111 | * @param t: The interpolation value [0-1]. 112 | * @return: A new vector. 113 | */ 114 | static inline Vector3 Lerp(Vector3 a, Vector3 b, float t); 115 | 116 | /** 117 | * Returns a vector linearly interpolated between a and b, moving along 118 | * a straight line. 119 | * @param a: The starting point. 120 | * @param b: The ending point. 121 | * @param t: The interpolation value [0-1] (no actual bounds). 122 | * @return: A new vector. 123 | */ 124 | static inline Vector3 LerpUnclamped(Vector3 a, Vector3 b, float t); 125 | 126 | /** 127 | * Returns the magnitude of a vector. 128 | * @param v: The vector in question. 129 | * @return: A scalar value. 130 | */ 131 | static inline float Magnitude(Vector3 v); 132 | 133 | /** 134 | * Returns a vector made from the largest components of two other vectors. 135 | * @param a: The first vector. 136 | * @param b: The second vector. 137 | * @return: A new vector. 138 | */ 139 | static inline Vector3 Max(Vector3 a, Vector3 b); 140 | 141 | /** 142 | * Returns a vector made from the smallest components of two other vectors. 143 | * @param a: The first vector. 144 | * @param b: The second vector. 145 | * @return: A new vector. 146 | */ 147 | static inline Vector3 Min(Vector3 a, Vector3 b); 148 | 149 | /** 150 | * Returns a vector "maxDistanceDelta" units closer to the target. This 151 | * interpolation is in a straight line, and will not overshoot. 152 | * @param current: The current position. 153 | * @param target: The destination position. 154 | * @param maxDistanceDelta: The maximum distance to move. 155 | * @return: A new vector. 156 | */ 157 | static inline Vector3 MoveTowards(Vector3 current, Vector3 target, 158 | float maxDistanceDelta); 159 | 160 | /** 161 | * Returns a new vector with magnitude of one. 162 | * @param v: The vector in question. 163 | * @return: A new vector. 164 | */ 165 | static inline Vector3 Normalized(Vector3 v); 166 | 167 | /** 168 | * Returns an arbitrary vector orthogonal to the input. 169 | * This vector is not normalized. 170 | * @param v: The input vector. 171 | * @return: A new vector. 172 | */ 173 | static inline Vector3 Orthogonal(Vector3 v); 174 | 175 | /** 176 | * Creates a new coordinate system out of the three vectors. 177 | * Normalizes "normal", normalizes "tangent" and makes it orthogonal to 178 | * "normal" and normalizes "binormal" and makes it orthogonal to both 179 | * "normal" and "tangent". 180 | * @param normal: A reference to the first axis vector. 181 | * @param tangent: A reference to the second axis vector. 182 | * @param binormal: A reference to the third axis vector. 183 | */ 184 | static inline void OrthoNormalize(Vector3 &normal, Vector3 &tangent, 185 | Vector3 &binormal); 186 | 187 | /** 188 | * Returns the vector projection of a onto b. 189 | * @param a: The target vector. 190 | * @param b: The vector being projected onto. 191 | * @return: A new vector. 192 | */ 193 | static inline Vector3 Project(Vector3 a, Vector3 b); 194 | 195 | /** 196 | * Returns a vector projected onto a plane orthogonal to "planeNormal". 197 | * This can be visualized as the shadow of the vector onto the plane, if 198 | * the light source were in the direction of the plane normal. 199 | * @param vector: The vector to project. 200 | * @param planeNormal: The normal of the plane onto which to project. 201 | * @param: A new vector. 202 | */ 203 | static inline Vector3 ProjectOnPlane(Vector3 vector, Vector3 planeNormal); 204 | 205 | /** 206 | * Returns a vector reflected off the plane orthogonal to the normal. 207 | * The input vector is pointed inward, at the plane, and the return vector 208 | * is pointed outward from the plane, like a beam of light hitting and then 209 | * reflecting off a mirror. 210 | * @param vector: The vector traveling inward at the plane. 211 | * @param planeNormal: The normal of the plane off of which to reflect. 212 | * @return: A new vector pointing outward from the plane. 213 | */ 214 | static inline Vector3 Reflect(Vector3 vector, Vector3 planeNormal); 215 | 216 | /** 217 | * Returns the vector rejection of a on b. 218 | * @param a: The target vector. 219 | * @param b: The vector being projected onto. 220 | * @return: A new vector. 221 | */ 222 | static inline Vector3 Reject(Vector3 a, Vector3 b); 223 | 224 | /** 225 | * Rotates vector "current" towards vector "target" by "maxRadiansDelta". 226 | * This treats the vectors as directions and will linearly interpolate 227 | * between their magnitudes by "maxMagnitudeDelta". This function does not 228 | * overshoot. If a negative delta is supplied, it will rotate away from 229 | * "target" until it is pointing the opposite direction, but will not 230 | * overshoot that either. 231 | * @param current: The starting direction. 232 | * @param target: The destination direction. 233 | * @param maxRadiansDelta: The maximum number of radians to rotate. 234 | * @param maxMagnitudeDelta: The maximum delta for magnitude interpolation. 235 | * @return: A new vector. 236 | */ 237 | static inline Vector3 RotateTowards(Vector3 current, Vector3 target, 238 | float maxRadiansDelta, 239 | float maxMagnitudeDelta); 240 | 241 | /** 242 | * Multiplies two vectors element-wise. 243 | * @param a: The lhs of the multiplication. 244 | * @param b: The rhs of the multiplication. 245 | * @return: A new vector. 246 | */ 247 | static inline Vector3 Scale(Vector3 a, Vector3 b); 248 | 249 | /** 250 | * Returns a vector rotated towards b from a by the percent t. 251 | * Since interpolation is done spherically, the vector moves at a constant 252 | * angular velocity. This rotation is clamped to 0 <= t <= 1. 253 | * @param a: The starting direction. 254 | * @param b: The ending direction. 255 | * @param t: The interpolation value [0-1]. 256 | */ 257 | static inline Vector3 Slerp(Vector3 a, Vector3 b, float t); 258 | 259 | /** 260 | * Returns a vector rotated towards b from a by the percent t. 261 | * Since interpolation is done spherically, the vector moves at a constant 262 | * angular velocity. This rotation is unclamped. 263 | * @param a: The starting direction. 264 | * @param b: The ending direction. 265 | * @param t: The interpolation value [0-1]. 266 | */ 267 | static inline Vector3 SlerpUnclamped(Vector3 a, Vector3 b, float t); 268 | 269 | /** 270 | * Returns the squared magnitude of a vector. 271 | * This is useful when comparing relative lengths, where the exact length 272 | * is not important, and much time can be saved by not calculating the 273 | * square root. 274 | * @param v: The vector in question. 275 | * @return: A scalar value. 276 | */ 277 | static inline float SqrMagnitude(Vector3 v); 278 | 279 | /** 280 | * Calculates the spherical coordinate space representation of a vector. 281 | * This uses the ISO convention (radius r, inclination theta, azimuth phi). 282 | * @param vector: The vector to convert. 283 | * @param rad: The magnitude of the vector. 284 | * @param theta: The angle in the XY plane from the X axis. 285 | * @param phi: The angle from the positive Z axis to the vector. 286 | */ 287 | static inline void ToSpherical(Vector3 vector, float &rad, float &theta, 288 | float &phi); 289 | 290 | 291 | /** 292 | * Operator overloading. 293 | */ 294 | inline struct Vector3& operator+=(const float rhs); 295 | inline struct Vector3& operator-=(const float rhs); 296 | inline struct Vector3& operator*=(const float rhs); 297 | inline struct Vector3& operator/=(const float rhs); 298 | inline struct Vector3& operator+=(const Vector3 rhs); 299 | inline struct Vector3& operator-=(const Vector3 rhs); 300 | }; 301 | 302 | inline Vector3 operator-(Vector3 rhs); 303 | inline Vector3 operator+(Vector3 lhs, const float rhs); 304 | inline Vector3 operator-(Vector3 lhs, const float rhs); 305 | inline Vector3 operator*(Vector3 lhs, const float rhs); 306 | inline Vector3 operator/(Vector3 lhs, const float rhs); 307 | inline Vector3 operator+(const float lhs, Vector3 rhs); 308 | inline Vector3 operator-(const float lhs, Vector3 rhs); 309 | inline Vector3 operator*(const float lhs, Vector3 rhs); 310 | inline Vector3 operator/(const float lhs, Vector3 rhs); 311 | inline Vector3 operator+(Vector3 lhs, const Vector3 rhs); 312 | inline Vector3 operator-(Vector3 lhs, const Vector3 rhs); 313 | inline bool operator==(const Vector3 lhs, const Vector3 rhs); 314 | inline bool operator!=(const Vector3 lhs, const Vector3 rhs); 315 | 316 | 317 | 318 | /******************************************************************************* 319 | * Implementation 320 | */ 321 | 322 | Vector3::Vector3() : X(0), Y(0), Z(0) {} 323 | Vector3::Vector3(float data[]) : X(data[0]), Y(data[1]), Z(data[2]) {} 324 | Vector3::Vector3(float value) : X(value), Y(value), Z(value) {} 325 | Vector3::Vector3(float x, float y) : X(x), Y(y), Z(0) {} 326 | Vector3::Vector3(float x, float y, float z) : X(x), Y(y), Z(z) {} 327 | 328 | 329 | Vector3 Vector3::Zero() { return Vector3(0, 0, 0); } 330 | Vector3 Vector3::One() { return Vector3(1, 1, 1); } 331 | Vector3 Vector3::Right() { return Vector3(1, 0, 0); } 332 | Vector3 Vector3::Left() { return Vector3(-1, 0, 0); } 333 | Vector3 Vector3::Up() { return Vector3(0, 1, 0); } 334 | Vector3 Vector3::Down() { return Vector3(0, -1, 0); } 335 | Vector3 Vector3::Forward() { return Vector3(0, 0, 1); } 336 | Vector3 Vector3::Backward() { return Vector3(0, 0, -1); } 337 | 338 | 339 | float Vector3::Angle(Vector3 a, Vector3 b) 340 | { 341 | float v = Dot(a, b) / (Magnitude(a) * Magnitude(b)); 342 | v = fmax(v, -1.0); 343 | v = fmin(v, 1.0); 344 | return acos(v); 345 | } 346 | 347 | Vector3 Vector3::ClampMagnitude(Vector3 vector, float maxLength) 348 | { 349 | float length = Magnitude(vector); 350 | if (length > maxLength) 351 | vector *= maxLength / length; 352 | return vector; 353 | } 354 | 355 | float Vector3::Component(Vector3 a, Vector3 b) 356 | { 357 | return Dot(a, b) / Magnitude(b); 358 | } 359 | 360 | Vector3 Vector3::Cross(Vector3 lhs, Vector3 rhs) 361 | { 362 | float x = lhs.Y * rhs.Z - lhs.Z * rhs.Y; 363 | float y = lhs.Z * rhs.X - lhs.X * rhs.Z; 364 | float z = lhs.X * rhs.Y - lhs.Y * rhs.X; 365 | return Vector3(x, y, z); 366 | } 367 | 368 | float Vector3::Distance(Vector3 a, Vector3 b) 369 | { 370 | return Vector3::Magnitude(a - b); 371 | } 372 | 373 | float Vector3::Dot(Vector3 lhs, Vector3 rhs) 374 | { 375 | return lhs.X * rhs.X + lhs.Y * rhs.Y + lhs.Z * rhs.Z; 376 | } 377 | 378 | Vector3 Vector3::FromSpherical(float rad, float theta, float phi) 379 | { 380 | Vector3 v; 381 | v.X = rad * sin(theta) * cos(phi); 382 | v.Y = rad * sin(theta) * sin(phi); 383 | v.Z = rad * cos(theta); 384 | return v; 385 | } 386 | 387 | Vector3 Vector3::Lerp(Vector3 a, Vector3 b, float t) 388 | { 389 | if (t < 0) return a; 390 | else if (t > 1) return b; 391 | return LerpUnclamped(a, b, t); 392 | } 393 | 394 | Vector3 Vector3::LerpUnclamped(Vector3 a, Vector3 b, float t) 395 | { 396 | return (b - a) * t + a; 397 | } 398 | 399 | float Vector3::Magnitude(Vector3 v) 400 | { 401 | return sqrt(SqrMagnitude(v)); 402 | } 403 | 404 | Vector3 Vector3::Max(Vector3 a, Vector3 b) 405 | { 406 | float x = a.X > b.X ? a.X : b.X; 407 | float y = a.Y > b.Y ? a.Y : b.Y; 408 | float z = a.Z > b.Z ? a.Z : b.Z; 409 | return Vector3(x, y, z); 410 | } 411 | 412 | Vector3 Vector3::Min(Vector3 a, Vector3 b) 413 | { 414 | float x = a.X > b.X ? b.X : a.X; 415 | float y = a.Y > b.Y ? b.Y : a.Y; 416 | float z = a.Z > b.Z ? b.Z : a.Z; 417 | return Vector3(x, y, z); 418 | } 419 | 420 | Vector3 Vector3::MoveTowards(Vector3 current, Vector3 target, 421 | float maxDistanceDelta) 422 | { 423 | Vector3 d = target - current; 424 | float m = Magnitude(d); 425 | if (m < maxDistanceDelta || m == 0) 426 | return target; 427 | return current + (d * maxDistanceDelta / m); 428 | } 429 | 430 | Vector3 Vector3::Normalized(Vector3 v) 431 | { 432 | float mag = Magnitude(v); 433 | if (mag == 0) 434 | return Vector3::Zero(); 435 | return v / mag; 436 | } 437 | 438 | Vector3 Vector3::Orthogonal(Vector3 v) 439 | { 440 | return v.Z < v.X ? Vector3(v.Y, -v.X, 0) : Vector3(0, -v.Z, v.Y); 441 | } 442 | 443 | void Vector3::OrthoNormalize(Vector3 &normal, Vector3 &tangent, 444 | Vector3 &binormal) 445 | { 446 | normal = Normalized(normal); 447 | tangent = ProjectOnPlane(tangent, normal); 448 | tangent = Normalized(tangent); 449 | binormal = ProjectOnPlane(binormal, tangent); 450 | binormal = ProjectOnPlane(binormal, normal); 451 | binormal = Normalized(binormal); 452 | } 453 | 454 | Vector3 Vector3::Project(Vector3 a, Vector3 b) 455 | { 456 | float m = Magnitude(b); 457 | return Dot(a, b) / (m * m) * b; 458 | } 459 | 460 | Vector3 Vector3::ProjectOnPlane(Vector3 vector, Vector3 planeNormal) 461 | { 462 | return Reject(vector, planeNormal); 463 | } 464 | 465 | Vector3 Vector3::Reflect(Vector3 vector, Vector3 planeNormal) 466 | { 467 | return vector - 2 * Project(vector, planeNormal); 468 | } 469 | 470 | Vector3 Vector3::Reject(Vector3 a, Vector3 b) 471 | { 472 | return a - Project(a, b); 473 | } 474 | 475 | Vector3 Vector3::RotateTowards(Vector3 current, Vector3 target, 476 | float maxRadiansDelta, 477 | float maxMagnitudeDelta) 478 | { 479 | float magCur = Magnitude(current); 480 | float magTar = Magnitude(target); 481 | float newMag = magCur + maxMagnitudeDelta * 482 | ((magTar > magCur) - (magCur > magTar)); 483 | newMag = fmin(newMag, fmax(magCur, magTar)); 484 | newMag = fmax(newMag, fmin(magCur, magTar)); 485 | 486 | float totalAngle = Angle(current, target) - maxRadiansDelta; 487 | if (totalAngle <= 0) 488 | return Normalized(target) * newMag; 489 | else if (totalAngle >= M_PI) 490 | return Normalized(-target) * newMag; 491 | 492 | Vector3 axis = Cross(current, target); 493 | float magAxis = Magnitude(axis); 494 | if (magAxis == 0) 495 | axis = Normalized(Cross(current, current + Vector3(3.95, 5.32, -4.24))); 496 | else 497 | axis /= magAxis; 498 | current = Normalized(current); 499 | Vector3 newVector = current * cos(maxRadiansDelta) + 500 | Cross(axis, current) * sin(maxRadiansDelta); 501 | return newVector * newMag; 502 | } 503 | 504 | Vector3 Vector3::Scale(Vector3 a, Vector3 b) 505 | { 506 | return Vector3(a.X * b.X, a.Y * b.Y, a.Z * b.Z); 507 | } 508 | 509 | Vector3 Vector3::Slerp(Vector3 a, Vector3 b, float t) 510 | { 511 | if (t < 0) return a; 512 | else if (t > 1) return b; 513 | return SlerpUnclamped(a, b, t); 514 | } 515 | 516 | Vector3 Vector3::SlerpUnclamped(Vector3 a, Vector3 b, float t) 517 | { 518 | float magA = Magnitude(a); 519 | float magB = Magnitude(b); 520 | a /= magA; 521 | b /= magB; 522 | float dot = Dot(a, b); 523 | dot = fmax(dot, -1.0); 524 | dot = fmin(dot, 1.0); 525 | float theta = acos(dot) * t; 526 | Vector3 relativeVec = Normalized(b - a * dot); 527 | Vector3 newVec = a * cos(theta) + relativeVec * sin(theta); 528 | return newVec * (magA + (magB - magA) * t); 529 | } 530 | 531 | float Vector3::SqrMagnitude(Vector3 v) 532 | { 533 | return v.X * v.X + v.Y * v.Y + v.Z * v.Z; 534 | } 535 | 536 | void Vector3::ToSpherical(Vector3 vector, float &rad, float &theta, 537 | float &phi) 538 | { 539 | rad = Magnitude(vector); 540 | float v = vector.Z / rad; 541 | v = fmax(v, -1.0); 542 | v = fmin(v, 1.0); 543 | theta = acos(v); 544 | phi = atan2(vector.Y, vector.X); 545 | } 546 | 547 | 548 | struct Vector3& Vector3::operator+=(const float rhs) 549 | { 550 | X += rhs; 551 | Y += rhs; 552 | Z += rhs; 553 | return *this; 554 | } 555 | 556 | struct Vector3& Vector3::operator-=(const float rhs) 557 | { 558 | X -= rhs; 559 | Y -= rhs; 560 | Z -= rhs; 561 | return *this; 562 | } 563 | 564 | struct Vector3& Vector3::operator*=(const float rhs) 565 | { 566 | X *= rhs; 567 | Y *= rhs; 568 | Z *= rhs; 569 | return *this; 570 | } 571 | 572 | struct Vector3& Vector3::operator/=(const float rhs) 573 | { 574 | X /= rhs; 575 | Y /= rhs; 576 | Z /= rhs; 577 | return *this; 578 | } 579 | 580 | struct Vector3& Vector3::operator+=(const Vector3 rhs) 581 | { 582 | X += rhs.X; 583 | Y += rhs.Y; 584 | Z += rhs.Z; 585 | return *this; 586 | } 587 | 588 | struct Vector3& Vector3::operator-=(const Vector3 rhs) 589 | { 590 | X -= rhs.X; 591 | Y -= rhs.Y; 592 | Z -= rhs.Z; 593 | return *this; 594 | } 595 | 596 | std::string Vector3::ToString(Vector3 a) { 597 | return to_string((int) a.X) + ", " + to_string((int) a.Y) + ", " + to_string((int) a.Z); 598 | } 599 | 600 | Vector3 operator-(Vector3 rhs) { return rhs * -1; } 601 | Vector3 operator+(Vector3 lhs, const float rhs) { return lhs += rhs; } 602 | Vector3 operator-(Vector3 lhs, const float rhs) { return lhs -= rhs; } 603 | Vector3 operator*(Vector3 lhs, const float rhs) { return lhs *= rhs; } 604 | Vector3 operator/(Vector3 lhs, const float rhs) { return lhs /= rhs; } 605 | Vector3 operator+(const float lhs, Vector3 rhs) { return rhs += lhs; } 606 | Vector3 operator-(const float lhs, Vector3 rhs) { return rhs -= lhs; } 607 | Vector3 operator*(const float lhs, Vector3 rhs) { return rhs *= lhs; } 608 | Vector3 operator/(const float lhs, Vector3 rhs) { return rhs /= lhs; } 609 | Vector3 operator+(Vector3 lhs, const Vector3 rhs) { return lhs += rhs; } 610 | Vector3 operator-(Vector3 lhs, const Vector3 rhs) { return lhs -= rhs; } 611 | 612 | bool operator==(const Vector3 lhs, const Vector3 rhs) 613 | { 614 | return lhs.X == rhs.X && lhs.Y == rhs.Y && lhs.Z == rhs.Z; 615 | } 616 | 617 | bool operator!=(const Vector3 lhs, const Vector3 rhs) 618 | { 619 | return !(lhs == rhs); 620 | } -------------------------------------------------------------------------------- /app/src/main/cpp/Engine/Includes.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /* 4 | * macro definitions 5 | */ 6 | 7 | #define getFieldOffset(method) Il2Cpp::GetFieldOffset(getAssembly(), getNamespace(), getClass(), method) 8 | #define getMethodOffset(method, param) (uintptr_t) Il2Cpp::GetMethodOffset(getAssembly(), getNamespace(), getClass(), method, param) 9 | #define getFieldStaticVal(method, out) Il2Cpp::GetStaticFieldValue(getAssembly(), getNamespace(), getClass(),method,out) 10 | #define setPointer(func, method, param) func = Il2Cpp::GetMethod(getAssembly(), getNamespace(), getClass(), method, param) 11 | #define setHook(func, func_name) \ 12 | if (func != nullptr) \ 13 | DobbyHook((void *) func, reinterpret_cast(new_##func), reinterpret_cast(&func)); \ 14 | else \ 15 | LOGE("Failed to hook %s", func_name); \ 16 | \ 17 | /* 18 | * API define 19 | */ 20 | 21 | #include "Logger.h" 22 | #include "API/Unity.h" 23 | #include "KittyMemory/KittyInclude.hpp" 24 | #include 25 | 26 | /* 27 | * Early class define so it can be used for other classes 28 | */ 29 | class ExampleEntry; 30 | 31 | /* 32 | * Include our structure classes 33 | */ 34 | #include "Structure/ExampleEntry.hpp" -------------------------------------------------------------------------------- /app/src/main/cpp/Engine/Structure/CBaseEntry.cpp: -------------------------------------------------------------------------------- 1 | #include "CBaseEntry.hpp" 2 | 3 | std::mutex listMutex; 4 | std::vector> list; 5 | 6 | template 7 | std::shared_ptr ListCBaseEntry::get() { 8 | std::lock_guard guard(listMutex); 9 | for (auto &entry : list) { 10 | if (dynamic_cast(entry)) { 11 | return std::static_pointer_cast(entry); 12 | } 13 | } 14 | return nullptr; 15 | } 16 | 17 | void ListCBaseEntry::add(const std::shared_ptr& entry) { 18 | std::lock_guard guard(listMutex); 19 | list.push_back(entry); 20 | } 21 | 22 | void ListCBaseEntry::remove(const std::shared_ptr& entry) { 23 | std::lock_guard guard(listMutex); 24 | auto it = std::find(list.begin(), list.end(), entry); 25 | if (it != list.end()) { 26 | list.erase(it); 27 | } 28 | } 29 | 30 | std::vector> ListCBaseEntry::getList() { 31 | std::lock_guard guard(listMutex); 32 | return list; // This makes a copy of the list 33 | } 34 | 35 | void ListCBaseEntry::Initialize() { 36 | std::lock_guard guard(listMutex); 37 | for (auto &entry : list) { 38 | entry->Initialize(); 39 | entry->Hook(); 40 | } 41 | } -------------------------------------------------------------------------------- /app/src/main/cpp/Engine/Structure/CBaseEntry.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | class CBaseEntry { 8 | public: 9 | virtual const char *getAssembly() = 0; 10 | virtual const char *getNamespace() = 0; 11 | virtual const char *getClass() = 0; 12 | virtual void Initialize() = 0; 13 | 14 | // TODO: Add this to the game loop 15 | virtual void Update() {}; 16 | 17 | // Define all necessary hooks here 18 | virtual void Hook() = 0; 19 | 20 | virtual ~CBaseEntry() = default; 21 | }; 22 | 23 | namespace ListCBaseEntry { 24 | 25 | void add(const std::shared_ptr& entry); 26 | 27 | void remove(const std::shared_ptr& entry); 28 | 29 | template 30 | std::shared_ptr get(); 31 | 32 | std::vector> getList(); 33 | 34 | void Initialize(); 35 | }; -------------------------------------------------------------------------------- /app/src/main/cpp/Engine/Structure/ExampleEntry.cpp: -------------------------------------------------------------------------------- 1 | #include "../Includes.hpp" 2 | 3 | bool (*AreStatsValid)(ExampleEntry *, void *) = nullptr; 4 | 5 | bool new_AreStatsValid(ExampleEntry *self, void *a2) { 6 | return true; 7 | } 8 | 9 | void ExampleEntry::Initialize() { 10 | setPointer(AreStatsValid, "AreStatsValid", 1); 11 | } 12 | 13 | void ExampleEntry::Hook() { 14 | setHook(AreStatsValid, "AreStatsValid"); 15 | } 16 | 17 | const char *ExampleEntry::getAssembly() { 18 | return "Assembly-CSharp.dll"; 19 | } 20 | 21 | const char *ExampleEntry::getNamespace() { 22 | return ""; 23 | } 24 | 25 | const char *ExampleEntry::getClass() { 26 | return "ExampleEntry"; 27 | } -------------------------------------------------------------------------------- /app/src/main/cpp/Engine/Structure/ExampleEntry.hpp: -------------------------------------------------------------------------------- 1 | #include "CBaseEntry.hpp" 2 | 3 | /* 4 | * This file is just sample, you can modify this 5 | */ 6 | class ExampleEntry : public CBaseEntry { 7 | public: 8 | const char *getAssembly() override; 9 | 10 | const char *getNamespace() override; 11 | 12 | const char *getClass() override; 13 | 14 | void Initialize() override; 15 | 16 | void Hook() override; 17 | }; 18 | -------------------------------------------------------------------------------- /app/src/main/cpp/Utils/Logger.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define _TAG "cheat_native" 4 | #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,_TAG,__VA_ARGS__) 5 | #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,_TAG,__VA_ARGS__) 6 | #define LOGW(...) __android_log_print(ANDROID_LOG_WARN,_TAG,__VA_ARGS__) 7 | #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,_TAG,__VA_ARGS__) -------------------------------------------------------------------------------- /app/src/main/cpp/native-lib.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "Engine/Includes.hpp" 5 | 6 | __attribute__ ((constructor)) 7 | void lib_main() { 8 | std::thread([]() { 9 | ProcMap map; 10 | do { 11 | map = KittyMemory::getElfBaseMap("libil2cpp.so"); 12 | sleep(1); 13 | } while (!map.isValid() && !map.isValidELF()); 14 | 15 | if (Il2Cpp::Init("libil2cpp.so") == -1) { 16 | LOGE("Il2Cpp::Init Failed!"); 17 | return; 18 | } 19 | 20 | // Initialize the classes 21 | ListCBaseEntry::add(std::make_shared()); 22 | ListCBaseEntry::Initialize(); 23 | }).detach(); 24 | } 25 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | plugins { 3 | id 'com.android.library' version '8.1.0' apply false 4 | } -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | # AndroidX package structure to make it clearer which packages are bundled with the 15 | # Android operating system, and which are packaged with your app's APK 16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 17 | android.useAndroidX=true 18 | # Enables namespacing of each library's R class so that its R class includes only the 19 | # resources declared in the library itself and none from the library's dependencies, 20 | # thereby reducing the size of the R class for that library 21 | android.nonTransitiveRClass=true -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BryanGIG/Android-Native-Mod/c7056e4c2b728ef298c0e816bbfe6971cdb1281e/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Jan 03 17:57:32 ICT 2024 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip 5 | zipStoreBase=GRADLE_USER_HOME 6 | zipStorePath=wrapper/dists 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 4 | # Copyright 2015 the original author or authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | ## 21 | ## Gradle start up script for UN*X 22 | ## 23 | ############################################################################## 24 | 25 | # Attempt to set APP_HOME 26 | # Resolve links: $0 may be a link 27 | PRG="$0" 28 | # Need this for relative symlinks. 29 | while [ -h "$PRG" ] ; do 30 | ls=`ls -ld "$PRG"` 31 | link=`expr "$ls" : '.*-> \(.*\)$'` 32 | if expr "$link" : '/.*' > /dev/null; then 33 | PRG="$link" 34 | else 35 | PRG=`dirname "$PRG"`"/$link" 36 | fi 37 | done 38 | SAVED="`pwd`" 39 | cd "`dirname \"$PRG\"`/" >/dev/null 40 | APP_HOME="`pwd -P`" 41 | cd "$SAVED" >/dev/null 42 | 43 | APP_NAME="Gradle" 44 | APP_BASE_NAME=`basename "$0"` 45 | 46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 48 | 49 | # Use the maximum available, or set MAX_FD != -1 to use that value. 50 | MAX_FD="maximum" 51 | 52 | warn () { 53 | echo "$*" 54 | } 55 | 56 | die () { 57 | echo 58 | echo "$*" 59 | echo 60 | exit 1 61 | } 62 | 63 | # OS specific support (must be 'true' or 'false'). 64 | cygwin=false 65 | msys=false 66 | darwin=false 67 | nonstop=false 68 | case "`uname`" in 69 | CYGWIN* ) 70 | cygwin=true 71 | ;; 72 | Darwin* ) 73 | darwin=true 74 | ;; 75 | MINGW* ) 76 | msys=true 77 | ;; 78 | NONSTOP* ) 79 | nonstop=true 80 | ;; 81 | esac 82 | 83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 84 | 85 | 86 | # Determine the Java command to use to start the JVM. 87 | if [ -n "$JAVA_HOME" ] ; then 88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 89 | # IBM's JDK on AIX uses strange locations for the executables 90 | JAVACMD="$JAVA_HOME/jre/sh/java" 91 | else 92 | JAVACMD="$JAVA_HOME/bin/java" 93 | fi 94 | if [ ! -x "$JAVACMD" ] ; then 95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 96 | 97 | Please set the JAVA_HOME variable in your environment to match the 98 | location of your Java installation." 99 | fi 100 | else 101 | JAVACMD="java" 102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 103 | 104 | Please set the JAVA_HOME variable in your environment to match the 105 | location of your Java installation." 106 | fi 107 | 108 | # Increase the maximum file descriptors if we can. 109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 110 | MAX_FD_LIMIT=`ulimit -H -n` 111 | if [ $? -eq 0 ] ; then 112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 113 | MAX_FD="$MAX_FD_LIMIT" 114 | fi 115 | ulimit -n $MAX_FD 116 | if [ $? -ne 0 ] ; then 117 | warn "Could not set maximum file descriptor limit: $MAX_FD" 118 | fi 119 | else 120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 121 | fi 122 | fi 123 | 124 | # For Darwin, add options to specify how the application appears in the dock 125 | if $darwin; then 126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 127 | fi 128 | 129 | # For Cygwin or MSYS, switch paths to Windows format before running java 130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then 131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 133 | 134 | JAVACMD=`cygpath --unix "$JAVACMD"` 135 | 136 | # We build the pattern for arguments to be converted via cygpath 137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 138 | SEP="" 139 | for dir in $ROOTDIRSRAW ; do 140 | ROOTDIRS="$ROOTDIRS$SEP$dir" 141 | SEP="|" 142 | done 143 | OURCYGPATTERN="(^($ROOTDIRS))" 144 | # Add a user-defined pattern to the cygpath arguments 145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 147 | fi 148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 149 | i=0 150 | for arg in "$@" ; do 151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 153 | 154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 156 | else 157 | eval `echo args$i`="\"$arg\"" 158 | fi 159 | i=`expr $i + 1` 160 | done 161 | case $i in 162 | 0) set -- ;; 163 | 1) set -- "$args0" ;; 164 | 2) set -- "$args0" "$args1" ;; 165 | 3) set -- "$args0" "$args1" "$args2" ;; 166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;; 167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 172 | esac 173 | fi 174 | 175 | # Escape application args 176 | save () { 177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 178 | echo " " 179 | } 180 | APP_ARGS=`save "$@"` 181 | 182 | # Collect all arguments for the java command, following the shell quoting and substitution rules 183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 184 | 185 | exec "$JAVACMD" "$@" 186 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | google() 4 | mavenCentral() 5 | gradlePluginPortal() 6 | } 7 | } 8 | dependencyResolutionManagement { 9 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) 10 | repositories { 11 | google() 12 | mavenCentral() 13 | } 14 | } 15 | 16 | rootProject.name = "Android Native Mod Template" 17 | include ':app' 18 | --------------------------------------------------------------------------------