Compare commits

...

1054 Commits
1.3 ... master

Author SHA1 Message Date
Sinai
1e1fb0e27b Merge branch 'master' of https://github.com/sinai-dev/UnityExplorer 2022-06-23 10:53:16 +10:00
Sinai
6b8a7d90c8 Update README.md 2022-06-23 10:53:14 +10:00
Sinai
1b4657dead
Update workflow for BepInEx CoreCLR build 2022-06-23 06:14:22 +10:00
Sinai
1af20ead9f Add BepInEx Il2CppInterop build 2022-06-23 06:03:58 +10:00
Sinai
706a18d1f6 Bump UniverseLib 2022-06-05 20:44:29 +10:00
Sinai
81dd8bad0e Update to C# 10.0, global usings 2022-05-26 06:19:50 +10:00
Sinai
97dffc81e1 Fix patch target on Time.timeScale 2022-05-19 00:07:12 +10:00
Sinai
bf2b22e768
Fix double zipped artifacts 2022-05-17 19:06:26 +10:00
Sinai
d1fbbfa62d Bump version 2022-05-15 19:12:00 +10:00
Sinai
56a3cef245 Add C# Console Assembly blacklist 2022-05-15 18:16:04 +10:00
Sinai
61e7915a55 Merge branch 'master' of https://github.com/sinai-dev/UnityExplorer 2022-05-14 01:55:13 +10:00
Sinai
88e63c8d6a Fix logic after changes in UniverseLib 2022-05-14 01:55:10 +10:00
Sinai
048e5980a0
Update README.md 2022-05-13 20:44:51 +10:00
Sinai
3b851b6e08 Use 7zip instead of Compress-Archive 2022-05-13 17:11:25 +10:00
Sinai
4c029dad90 Update TimeScaleWidget.cs 2022-05-11 22:49:28 +10:00
Sinai
3d61011e59 Move Time Scale Widget into separate class
And change "pause" to "lock" behaviour. Added patch to implement locking feature.
2022-05-10 01:44:08 +10:00
Sinai
5285239bc5 Update hooks list after edit save 2022-05-10 01:43:41 +10:00
Sinai
57d3a3f52e Fix UI Mouse Inspect hotkey not being implemented 2022-05-10 01:02:37 +10:00
Sinai
c88182c831 Bump version 2022-05-08 18:06:56 +10:00
Sinai
02e0102041 Merge branch 'master' of https://github.com/sinai-dev/UnityExplorer 2022-05-07 05:19:46 +10:00
Sinai
6adecef785 Fix generated patch code for static void methods
And always show the patch even if it failed to apply
2022-05-07 05:19:43 +10:00
Sinai
ff6c03e1f3
Update README.md 2022-05-06 15:46:49 +10:00
Sinai
1aedc505b2 Bump UniverseLib 2022-05-05 23:13:51 +10:00
Sinai
dbe993a7c7 Fix some casts for IL2CPP 2022-05-05 22:18:19 +10:00
Sinai
5a1676fb84 Update README.md 2022-05-05 19:56:29 +10:00
Sinai
a7a663aefa Prevent update overwriting input field changes 2022-05-05 19:53:02 +10:00
Sinai
76c77fb082 Add button to inspect scene of a GameObject 2022-05-05 19:52:25 +10:00
Sinai
a25017df69 Add wider Texture2DWidget support 2022-05-05 19:52:13 +10:00
Sinai
a1fab0c4a7 Add support for opening inspected Type in dnSpy 2022-05-05 19:50:52 +10:00
Sinai
4599747bfe Merge branch 'master' of https://github.com/sinai-dev/UnityExplorer 2022-05-05 02:45:43 +10:00
Sinai
3856e84c08 Bump version 2022-05-05 02:45:41 +10:00
Sinai
104288a912 Add support for Cubemaps in Texture2DWidget 2022-05-05 02:45:24 +10:00
Sinai
41e8a5ae33
Update README.md 2022-05-03 06:10:22 +10:00
Sinai
ef4bc75d5e Bump version 2022-04-30 20:53:31 +10:00
Sinai
68b81c6b53 Bump UniverseLib 2022-04-30 20:47:53 +10:00
Sinai
bd86f09313 Cleanup and refactor GameObjectControls
Split into proper classes, cleanup ugly code
2022-04-30 20:32:31 +10:00
Sinai
b35d6f5787 Cleanup 2022-04-30 20:31:33 +10:00
Sinai
b97eada516
Update README.md 2022-04-29 16:56:29 +10:00
Sinai
0a05848bef Implement control modifier to Home/End jump 2022-04-28 04:10:36 +10:00
Sinai
6e5610129a Add ILRepack back to build process 2022-04-27 20:13:17 +10:00
Sinai
acd30880a8 Bump UniverseLib 2022-04-27 03:04:28 +10:00
Sinai
f54ff89290 Bump UniverseLib 2022-04-25 22:52:24 +10:00
Sinai
62d565777d Bump UniverseLib and version 2022-04-25 19:39:44 +10:00
Sinai
870f82ab26 Fix Home jump when line is entirely whitespace 2022-04-25 05:48:13 +10:00
Sinai
9370c5e0e6 Fix jumpToTop and panel position behaviour 2022-04-25 05:47:57 +10:00
Sinai
b8cf96438c Correct a comment position 2022-04-24 19:38:17 +10:00
Sinai
7be7daf4d7 Bump version 2022-04-24 19:24:43 +10:00
Sinai
8f54415ae0 Remove small logic error with SymbolLexer 2022-04-24 19:23:05 +10:00
Sinai
aef4e11c01 C# Console: Implement Home and End keys 2022-04-24 19:13:43 +10:00
Sinai
af7e32ec49 Add a null check 2022-04-24 18:16:13 +10:00
Sinai
6f44a3376b Bump UniverseLib 2022-04-24 05:58:36 +10:00
Sinai
3a6b573ac3 Bump version 2022-04-24 05:57:29 +10:00
Sinai
cbe17927fb Ensure valid panel size after loading save data 2022-04-24 05:57:22 +10:00
Sinai
15f3f37948 Clean up all objects in editor 2022-04-24 05:56:47 +10:00
Sinai
de6760e427 Add more convenient editor config serialization 2022-04-24 05:56:36 +10:00
Sinai
83edd1b9bb Bump editor package 2022-04-24 02:12:57 +10:00
Sinai
613be34e95 Bump UniverseLib 2022-04-24 02:04:08 +10:00
Sinai
58c65b9b8b Make TypeCompleter asynchronous 2022-04-24 02:02:34 +10:00
Sinai
6fcf6a521c Bump version 2022-04-24 02:02:29 +10:00
Sinai
81a174f865 Remove call to obsolete methods 2022-04-24 01:59:53 +10:00
Sinai
b5e3cc2ea5 Use separate TypeCompleters for different contexts 2022-04-24 01:59:03 +10:00
Sinai
14f46ade6a Cancel pending generic when edit button pressed 2022-04-24 01:58:27 +10:00
Sinai
e92556805b Update BepInExConfigHandler.cs 2022-04-23 01:05:51 +10:00
Sinai
8662742461 Bump version 2022-04-23 00:19:31 +10:00
Sinai
63393a9d66 Update README.md 2022-04-22 22:31:36 +10:00
Sinai
13986f95c1 Update UnityExplorer.STANDALONE.Mono.dll 2022-04-22 22:27:48 +10:00
Sinai
b47bfa1e83 Remove Mono restriction on generic type eligibility 2022-04-22 22:27:43 +10:00
Sinai
12c51248fe Update Editor package 2022-04-22 22:20:01 +10:00
Sinai
9b9cb54a79 Fix a typo 2022-04-22 22:19:43 +10:00
Sinai
6a28a93e3a Update for obsolete method 2022-04-22 22:11:24 +10:00
Sinai
32e718faeb Bump UniverseLib 2022-04-22 21:31:30 +10:00
Sinai
4d46b74d54 Fix references for rename 2022-04-22 21:04:50 +10:00
Sinai
7e5246cead Recache types when borrowing 2022-04-22 21:04:23 +10:00
Sinai
abf5267364 Fix HookCreator method filtering 2022-04-22 21:03:51 +10:00
Sinai
3afee7254c Fix results TypeCompleter issues 2022-04-22 21:03:33 +10:00
Sinai
1643d4b7dd Allow generic class construction for unbound types 2022-04-22 21:03:11 +10:00
Sinai
cef8c12d20 Fix TryFocusActiveInspector for classes 2022-04-22 21:02:45 +10:00
Sinai
5e07847356 Make current hooks view smaller in height 2022-04-22 21:02:08 +10:00
Sinai
2dc6e386df Fix generated patch code for ref and subclasses 2022-04-22 21:01:47 +10:00
Sinai
ff882296fd Fix for GenericConstructorWidget, adjust UI 2022-04-22 21:01:09 +10:00
Sinai
ecc33927ee Make GenericConstructorWidget reusable 2022-04-22 21:00:18 +10:00
Sinai
6e91f2a792 Hooks: Add support for generic classes and methods 2022-04-22 09:15:51 +10:00
Sinai
97cb14d6fc HookInstance: Clean up generated patch code 2022-04-22 09:12:38 +10:00
Sinai
8b861f7c77 Log Panel: Remove a todo 2022-04-22 09:12:22 +10:00
Sinai
9379e0f813 Fix constraints on AddComponent TypeCompleter 2022-04-22 09:08:49 +10:00
Sinai
bdda12a040 Remove redundant reference to EvaluateWidget 2022-04-22 09:08:17 +10:00
Sinai
75bd654a94 TypeCompleter: Allow generics, support shorthand names 2022-04-22 09:07:51 +10:00
Sinai
f174c7543a C# Console: Fix autocomplete caret deselection 2022-04-22 09:06:52 +10:00
Sinai
08f2c6035e Bump version 2022-04-20 18:47:23 +10:00
Sinai
475e24a66a Update editor package 2022-04-20 18:47:19 +10:00
Sinai
c62b93535d Update position input when Reset button clicked 2022-04-20 18:47:12 +10:00
Sinai
374d0b3bae Bump UniverseLib 2022-04-20 18:46:48 +10:00
Sinai
1f87e89b97 Add some more functionality to Freecam
- Option to use Game's camera
- Button to reset position back to original cam pos
- Free cam position will be stored between stopping/starting free cam
2022-04-19 19:37:05 +10:00
Sinai
495bc41a8d Bump Editor package 2022-04-19 18:06:16 +10:00
Sinai
9cf62c3250 Bump UniverseLib, fix EventSystem issue 2022-04-19 18:05:55 +10:00
Sinai
4c9b3115cd Update UnityEditorPackage 2022-04-19 01:23:11 +10:00
Sinai
ebdce70418 Move instructions 2022-04-19 01:22:25 +10:00
Sinai
7c0b37440b Update UnityEditorPackage 2022-04-19 01:19:04 +10:00
Sinai
0d8ab8bf14 Allow FreeCam to run when menu closed 2022-04-19 01:12:33 +10:00
Sinai
5a3cad9be2 Fix weird Behaviour inheritance issue 2022-04-19 00:57:13 +10:00
Sinai
70d67f1dad Bump version 2022-04-18 21:39:50 +10:00
Sinai
469484d129 Add FreeCam panel 2022-04-18 21:39:17 +10:00
Sinai
c5e262d1c3 Fix UEPanel save data issue 2022-04-18 21:39:11 +10:00
Sinai
53c8dfcb6d Bump UniverseLib 2022-04-18 21:38:49 +10:00
Sinai
ae3ac21992 Add test for Il2CppSystem.Array 2022-04-18 19:12:42 +10:00
Sinai
7765b64748 Make MouseInspector panel just a PanelBase 2022-04-18 19:12:21 +10:00
Sinai
a5023d03f4 Update to UniverseLib 1.3.4 2022-04-18 19:11:39 +10:00
Sinai
a5e6b65dee Add UniverseLib to C# Console default usings 2022-04-18 19:10:24 +10:00
Sinai
c45cd8c1e1 Update editor package 2022-04-14 02:41:18 +10:00
Sinai
e46e24e1af Fix typo 2022-04-14 02:32:01 +10:00
Sinai
3d66493f9c Use UniverseLib PanelBase/PanelDragger 2022-04-14 01:25:59 +10:00
Sinai
7e0f98ef91 Automatic code cleanup (no real changes)
- Use explicit type of var
- Use 'new()'
- Remove unnecessary usings
- Sort usings
- Apply formatting
2022-04-12 05:20:35 +10:00
Sinai
693f5818be Remove duplicate UIManager.Update call 2022-04-12 04:46:04 +10:00
Sinai
1d1dad5cb1 Merge branch 'master' of https://github.com/sinai-dev/UnityExplorer 2022-04-12 02:52:17 +10:00
Sinai
79157a2fab Add UnityEditorPackage 2022-04-12 02:52:09 +10:00
Sinai
7ef8eff0d4
Fix missing space character in dotnet.yaml 2022-04-12 02:40:25 +10:00
Sinai
8a4d418ffb Finalize 4.7.0 release, cleanups 2022-04-12 02:36:12 +10:00
Sinai
b56960dba2 Update readme, remove pause from build script 2022-04-12 01:34:43 +10:00
Sinai
006ab2ee6f Update dotnet.yml 2022-04-12 01:20:13 +10:00
Sinai
a0ed26eb8e Delete .gitmodules 2022-04-12 00:36:24 +10:00
Sinai
7665987794 Add powershell build script 2022-04-12 00:29:02 +10:00
Sinai
4516e9b9f6 Migrate project to dotnet SDK, add net6 build 2022-04-12 00:28:53 +10:00
Sinai
e1aac57a51 Refactor class for future expansion 2022-04-12 00:27:20 +10:00
Sinai
8f1f6cd0b2 Fix JumpToTransform exception with HideAndDontSave 2022-04-12 00:27:05 +10:00
Sinai
409a468b55 Fix exception when adding certain references in net6 2022-04-12 00:26:49 +10:00
Sinai
6110c59721 Update Emit exception message 2022-04-12 00:26:29 +10:00
Sinai
96451477ee Change ExplorerFolder path and refactor 2022-04-12 00:26:01 +10:00
Sinai
f19a1dd25e Code cleanup 2022-04-12 00:17:06 +10:00
Sinai
47629d4764 Update libs
- Added net6 MelonLoader.dll reference
- Added net6 mcs.dll reference
- Restructured dlls into framework folders
2022-04-11 23:17:13 +10:00
Sinai
62fa7f30f3 Fix exception state being "sticky" 2022-04-11 17:37:03 +10:00
Sinai
4af86e0e25 Fix InspectingAssetScene returning incorrect value 2022-04-11 17:14:20 +10:00
Sinai
27ae78a043 Remove redundant UIManager.Update call 2022-04-11 17:14:05 +10:00
Sinai
d6a07f05ea Bump version 2022-04-10 05:37:28 +10:00
Sinai
27d5398dea Add throttling to prune method, remove logging 2022-04-10 05:32:07 +10:00
Sinai
7a5570a070 Bump version 2022-04-09 18:59:34 +10:00
Sinai
d40537775f Bump UniverseLib 2022-04-09 18:59:13 +10:00
Sinai
9b6f3fd3ea Cleanups / refactoring 2022-04-09 18:58:56 +10:00
Sinai
bacac929e9 Show InputField for exceptions to view/copy full exception 2022-04-01 18:14:50 +11:00
Sinai
4e3d3a2e5c Update README.md 2022-04-01 01:37:51 +11:00
Sinai
7dbc8fd66e Merge branch 'master' of https://github.com/sinai-dev/UnityExplorer 2022-04-01 01:31:53 +11:00
Sinai
892cefcc91 Bump version 2022-04-01 01:31:45 +11:00
Sinai
a986b92963 Don't try to get UnityObjectWidget for static class inspection 2022-04-01 01:31:40 +11:00
Sinai
8837119781
Merge pull request #132 from liesauer/master
Fix standalone reading config item type casting bug
2022-04-01 01:21:39 +11:00
L!εsAμεr
7eda249ddb
Fix standalone reading config item type casting bug 2022-03-31 21:07:06 +08:00
Sinai
710b4ba74a Use switch expression instead of if/else block 2022-03-29 22:39:26 +11:00
Sinai
4bee55fb25 Cleanups, remove redundancy 2022-03-29 22:36:17 +11:00
Sinai
c71748d22a Remove pointless ToArray() call 2022-03-23 19:02:17 +11:00
Sinai
621035c732 Bump UniverseLib 2022-03-23 18:04:27 +11:00
Sinai
2285a495be Add support for Unity Editor release 2022-03-21 21:25:51 +11:00
Sinai
efdf2446bd A few cleanups and optimizations 2022-03-21 21:25:18 +11:00
Sinai
6ad45ac8ae Delete social.png 2022-03-21 21:24:36 +11:00
Sinai
2d3c83cfa3 Bump version 2022-03-21 01:05:00 +11:00
Sinai
3213717ff6 Add outline to resize arrow 2022-03-21 01:04:55 +11:00
Sinai
a6a1a4d046 cleanup 2022-03-21 01:04:44 +11:00
Sinai
078c2e2b51 Add AudioClipWidget 2022-03-21 01:04:39 +11:00
Sinai
49bce650b4 Fix text clipping with transform cell name and sibling index 2022-03-20 21:21:23 +11:00
Sinai
bd9e80f2b4 Refactor unity inspector widgets into proper classes 2022-03-20 21:21:01 +11:00
Sinai
d1eb5671bf Move GetCacheMembers into separate class 2022-03-20 21:20:17 +11:00
Sinai
f1ca484712 Fix generic arguments for parameterless struct ctors 2022-03-16 23:21:39 +11:00
Sinai
3b71b40843 More accurate check if enum value has flag 2022-03-15 01:51:27 +11:00
Sinai
1292affe6d Fix autocomplete panel resizing 2022-03-15 01:50:50 +11:00
Sinai
6614762fe8 Bump version 2022-03-15 01:19:52 +11:00
Sinai
d81d6d034b Implement support for implicit struct constructors 2022-03-15 01:19:48 +11:00
Sinai
5dfe3bbf0c Fix missing and incorrect ctor caching
- Shouldn't include ctors on abstract types
- Missing parameterless ctors for structs (implicit)
2022-03-15 01:19:01 +11:00
Sinai
dc81451ce5 Make Constructor toggle button actually do something 2022-03-15 01:18:12 +11:00
Sinai
d7ab0a23c6 Skip private/anonymous types in TypeCompleter results 2022-03-15 01:17:54 +11:00
Sinai
1a01c740e2 Move AutoCompleteModal into Panels folder 2022-03-15 01:17:35 +11:00
Sinai
040fb1f11a Bump version 2022-03-14 05:22:44 +11:00
Sinai
e44ff9e207 Add support for Constructors in Reflection Inspector
- Added CacheConstructor : CacheMember
- Changed default scope to "All" from "Instance" when inspecting an instance
- Bumped UniverseLib
2022-03-14 05:20:43 +11:00
Sinai
b5c69fc1ea Fix UI mouse inspector results panel not always coming to front 2022-03-13 02:59:52 +11:00
Sinai
4fdb2aacd8 Move logic out of UIManager.SetPanelActive into panel.SetActive 2022-03-13 02:21:25 +11:00
Sinai
48e688cb75 use SetPanelActive instead of manually setting gameobject active 2022-03-13 02:08:46 +11:00
Sinai
647b0d353d Fix text clipping on inspector tab button 2022-03-12 20:17:03 +11:00
Sinai
2b715f3dbe Hide SiblingIndex input when invalid 2022-03-12 20:16:55 +11:00
Sinai
938a991594 Update TransformTree immediately on user changes 2022-03-12 20:16:37 +11:00
Sinai
f00134b283 Add "one-shot" option for TransformTree updating 2022-03-10 17:56:21 +11:00
Sinai
3b6b9768fb Bump UniverseLib 2022-03-10 05:29:55 +11:00
Sinai
5fbfa1b7aa Bump UniverseLib 2022-03-10 05:06:49 +11:00
Sinai
7d26965c12 Bump UniverseLib 2022-03-10 04:44:45 +11:00
Sinai
862523399a Bump version 2022-03-10 04:35:11 +11:00
Sinai
0afccadc64 Improve TransformTree efficiency
- Added batching to the update method so that a maximum of 2000 GameObjects are traversed each frame.
- Changed from OrderedDictionary.Remove to OrderedDictionary.RemoveAt when pruning entries as the former needs to iterate through all entries to find the index of the key, whereas the latter is constant time.
2022-03-10 04:35:06 +11:00
Sinai
0e37e8030c Add sibling index input to transform tree cells 2022-03-10 04:32:19 +11:00
Sinai
621a9cd72e Use RemoveHighlighting to get raw copy+paste name 2022-03-10 04:31:19 +11:00
Sinai
56be5414f9 Bump UniverseLib 2022-03-10 04:30:52 +11:00
Sinai
b8c4be473f Fix disposed TextWriter bug, bump version 2022-03-06 00:21:48 +11:00
Sinai
b6966f8836 Bump UniverseLib, bump version 2022-03-05 07:32:32 +11:00
Sinai
ad8c5293a0 Add keybinds for Mouse Inspect, small cleanup 2022-03-04 00:20:04 +11:00
Sinai
a7165c849c Bump UniverseLib, cleanup, bump version 2022-03-04 00:09:19 +11:00
Sinai
79f2514109 Fix issue with partially unloaded scenes(?) 2022-03-03 03:22:17 +11:00
Sinai
4e76eca73a Use new melonloader logging method 2022-02-24 19:26:16 +11:00
Sinai
2f0876466c bump mod loader versions 2022-02-24 19:26:01 +11:00
Sinai
fdefc3d567 Include runtime context in "initialized" log. 2022-02-21 01:46:13 +11:00
Sinai
64193ff1b0 Use a patch instead of manual check on every property 2022-02-21 01:45:46 +11:00
Sinai
a90292f47f Prevent Unity crashing on PropertyInfo evaluation
Unity crashes from checking Canvas.renderingDisplaySize on a Canvas set to WorldSpace with no worldCamera set.
2022-02-19 17:50:10 +11:00
Sinai
d0bccae50c Update TypeCompleter.cs 2022-02-11 19:39:11 +11:00
Sinai
bdf08f014f Use ReflectionUtility.AllTypes for type autocompleter, bump UniverseLib 2022-02-11 19:37:17 +11:00
Sinai
df8522963e Use reflection for AllTypes until it's public 2022-02-07 22:12:18 +11:00
Sinai
f6d0acab7b Bump version 2022-02-07 00:45:19 +11:00
Sinai
d4fbc89158 Use ReflectionUtility.AllTypes when doing class search to include static classes 2022-02-06 04:50:52 +11:00
Sinai
9e49f09a79 Bump UniverseLib, fix C# Console issues, add Stop helper 2022-02-04 20:34:05 +11:00
Sinai
b9a3ab7439 Fix CSConsole not re-selecting properly after Escape is pressed 2022-02-04 18:07:34 +11:00
Sinai
03661cdd0b Bump UniverseLib 2022-02-03 23:51:38 +11:00
Sinai
10f2b7e849 Bump UniverseLib and fix changes to CreatePanel 2022-02-03 23:33:45 +11:00
Sinai
4602f07c34 Add NuGet config 2022-02-01 18:20:01 +11:00
Sinai
18bcfed434 Bump UniverseLib 2022-02-01 08:05:01 +11:00
Sinai
c7d2ce6d36 Merge branch 'master' of https://github.com/sinai-dev/UnityExplorer 2022-01-31 22:01:35 +11:00
Sinai
f961add7f4 Bump version 2022-01-31 22:00:59 +11:00
Sinai
798b881dcb
Update dotnet.yml 2022-01-31 21:31:18 +11:00
Sinai
c90f339882
Update dotnet.yml 2022-01-31 21:29:10 +11:00
Sinai
c351ce5a6d
Remove Il2CppAssemblyUnhollower from build process 2022-01-31 21:24:57 +11:00
Sinai
9985ed0fd8 Update to UniverseLib 1.2, cleanups 2022-01-31 21:24:01 +11:00
Sinai
f35232bb64 Removed Unhollower submodule 2022-01-30 06:36:01 +11:00
Sinai
49cc1f7df3 Fix issue with DontDestroyOnLoad not existing in some games, cleanups 2022-01-24 17:50:01 +11:00
Sinai
9f78c50854 Use "untitled" for transforms with empty names 2022-01-24 17:49:49 +11:00
Sinai
bc64a04339 Cleanup 2022-01-24 17:49:34 +11:00
Sinai
7d961ce8ad Cleanup and DontDestroy fixes 2022-01-24 17:49:22 +11:00
Sinai
c7d7569f71 Fix NullReferenceException in some older Unity games 2022-01-24 17:49:01 +11:00
Sinai
ee8f33a754 Bump version 2022-01-24 01:10:19 +11:00
Sinai
a95d91c824 Fix hidden UiBase not being deactivated with main one 2022-01-24 00:35:45 +11:00
Sinai
177b78f4e7 Bump UniverseLib 2022-01-23 23:12:06 +11:00
Sinai
3804d0aab0 Update ConfigManager.cs 2022-01-23 23:09:01 +11:00
Sinai
97a82c1661 Make sure mouse is in target display for resize/dragging/panel operations 2022-01-23 23:08:34 +11:00
Sinai
96a1cc69fb Bump UniverseLib 2022-01-23 17:44:01 +11:00
Sinai
589abe6193 Fix panel draggers on display change 2022-01-22 21:44:22 +11:00
Sinai
91bb58b020 Fix panel resizing on alternate monitors 2022-01-22 21:08:12 +11:00
Sinai
d67507ead2 Implement DisplayManager, ability to use other monitors 2022-01-22 20:20:44 +11:00
Sinai
d730fbe49c
Update FUNDING.yml 2022-01-19 18:25:16 +11:00
Sinai
9e0784ce54
Create FUNDING.yml 2022-01-19 18:24:49 +11:00
Sinai
67c602b32f Use Tomlet for Standalone config, fix ML double reference 2022-01-19 18:20:26 +11:00
Sinai
8fb7d87ca6 Use Tomlet, simplify panel data saving 2022-01-19 17:34:53 +11:00
Sinai
c740c3c54d Update README.md 2022-01-18 20:34:15 +11:00
Sinai
ea7b91f7fd Implement Clipboard and Notifications, misc cleanups 2022-01-18 20:19:20 +11:00
Sinai
c79223f537 Move MouseInspector dropdown to Inspector panel 2022-01-17 21:00:55 +11:00
Sinai
aae248bf69 Bump UniverseLib to 1.0.4, use HighlightMethod, add Clipboard (unfinished) 2022-01-17 20:23:58 +11:00
Sinai
a73e992a0c Remove "Core" namespace, move everything in it up one level 2022-01-17 19:42:05 +11:00
Sinai
3984550bb6 Bump Unhollower to latest 2022-01-17 19:41:00 +11:00
Sinai
7928363aeb Bumped UniverseLib to 1.0.3 2022-01-11 05:54:38 +11:00
Sinai
12758606fa Bump UniverseLib to 1.0.2 2022-01-09 19:56:59 +11:00
Sinai
c927ac54be Fix potential NullReference in UpdateMouseInspect 2022-01-09 19:20:17 +11:00
Sinai
9f1df11940 Add some more tests 2022-01-08 17:56:56 +11:00
Sinai
62354b6aa2 Fix disposed TextWriter bug, add System.Collections to default using 2022-01-08 17:56:48 +11:00
Sinai
44e57c32c3 Raise LangVersion to 9.0 2022-01-08 17:56:33 +11:00
Sinai
274352d665 fix ParameterHandler parsing Types 2022-01-02 19:55:09 +11:00
Sinai
7b477a8b0e Rewrite EvaluateWidget, add BaseArgumentHandler, use autocomplete for InteractiveEnum 2022-01-02 19:43:55 +11:00
Sinai
e585fc6da0 Allow evaluating non-primitive methods 2022-01-01 21:40:47 +11:00
Sinai
0dd19345ed Fix FPS drop with MelonLoader 2021-12-28 23:24:44 +11:00
Sinai
0050cff185 bump version 2021-12-24 15:17:53 +11:00
Sinai
5f1d635eb3 Only filter transform tree on end edit 2021-12-24 15:17:48 +11:00
Sinai
e0f7fad00e Cleanup 2021-12-24 15:17:35 +11:00
Sinai
f92c215a88 update libs 2021-12-24 15:17:28 +11:00
Sinai
d58a5df82c Merge branch 'master' of https://github.com/sinai-dev/UnityExplorer 2021-12-24 15:17:23 +11:00
Sinai
12dd85ecfd Update README.md 2021-12-03 01:06:57 +11:00
Sinai
03fb165967
Update README (moved to UniverseLib) -noci 2021-12-02 21:11:25 +11:00
Sinai
834f4b7c4c Update README.md 2021-12-02 20:27:51 +11:00
Sinai
3415eb8e77 Bump version 2021-12-02 20:25:09 +11:00
Sinai
6c1a5b8ae2 Update README.md 2021-12-02 18:36:33 +11:00
Sinai
3334549902 use UniverseLib 2021-12-02 18:35:46 +11:00
Sinai
077a2b434a Null ptr check on AssetBundle loading 2021-11-30 17:31:49 +11:00
Sinai
8123ec2412 Revert "Use PatchProcessor ctor directly instead of Harmony.CreatePatchProcessor"
This reverts commit 9c1d4596554773c4cce9fbccba837c927800e16c.
2021-11-20 18:57:53 +11:00
Sinai
3f31db8dd8 Merge branch 'master' of https://github.com/sinai-dev/UnityExplorer 2021-11-20 17:47:14 +11:00
Sinai
9c1d459655 Use PatchProcessor ctor directly instead of Harmony.CreatePatchProcessor 2021-11-20 17:47:01 +11:00
Sinai
2cb510a82e
Cleanup readme
"Common issues" probably not that common anymore, removing to reduce clutter.
2021-11-18 05:12:04 +11:00
Sinai
6aa9b3aa15 Bump version 2021-10-26 15:12:56 +11:00
Sinai
587842f46b Add search filter to scene loader dropdown 2021-10-26 15:12:52 +11:00
Sinai
b9c641f170 Fix scene loader not showing 2021-10-26 15:12:44 +11:00
Sinai
1e68529430 Don't patch stripped UnloadAllAssetBundles 2021-10-22 15:54:14 +11:00
Sinai
e84e96a63c Bump version 2021-10-21 20:04:48 +11:00
Sinai
ec8c88ab9b Actually fix Logs folder 2021-10-19 16:34:46 +11:00
Sinai
0eae78eeb2 Update LogPanel.cs 2021-10-19 16:32:33 +11:00
Sinai
a07ead2142 Fix log folder not being created 2021-10-19 04:30:35 +11:00
Sinai
b93567c7ea Bump version 2021-10-16 18:11:08 +11:00
Sinai
957d80c7ec Fix IOUtility creating folders for file paths 2021-10-16 18:10:23 +11:00
Sinai
d530d10798 Exceptions is IsNullOrDestroyed should return true 2021-10-12 20:27:32 +11:00
Sinai
66daabf770 Add try/catch to IsNullOrDestroyed 2021-10-12 20:20:08 +11:00
Sinai
9fe998aa22 Cleanup 2021-10-01 17:21:54 +10:00
Sinai
28b6db80f9 Fix InputSystem EventSystem bug 2021-10-01 17:21:50 +10:00
Sinai
22effbb399 Update README.md 2021-09-30 21:13:29 +10:00
Sinai
50f0c31e98 Add patch for asset bundle unloading to prevent UnityExplorer's bundle being unloaded 2021-09-30 21:09:27 +10:00
Sinai
911522457e Clarify "Classes" help in C# Console 2021-09-30 21:09:04 +10:00
Sinai
d5d1841109 Include Unhollower in ILRepack references 2021-09-30 21:08:45 +10:00
Sinai
239534e09c Add GetAllLoadedAssetBundles 2021-09-30 21:08:29 +10:00
Sinai
bc5d16051f Fix issue with InputSystem 2021-09-30 21:08:08 +10:00
Sinai
f81822f219 bump lib versions 2021-09-30 21:06:38 +10:00
Sinai
f159cf5ea7 Attempt fix at bundle unloading 2021-09-23 16:40:47 +10:00
Sinai
1e6bacb32b manual unity libs no longer required for BepInEx 2021-09-23 16:21:47 +10:00
Sinai
a80cef4c1d Bump version 2021-09-07 19:11:58 +10:00
Sinai
450bb77f2e Use Harmony's FullDescription for hook parameter types 2021-09-07 19:11:19 +10:00
Sinai
0479102db6 Cleanup toggle Enabled logic 2021-09-07 18:06:38 +10:00
Sinai
93181f02be Update README.md 2021-09-07 17:33:01 +10:00
Sinai
371054d6df Add hook source editor for custom dynamic hooks 2021-09-07 17:23:20 +10:00
Sinai
427f23b80a Bump version 2021-09-07 03:40:14 +10:00
Sinai
a0d5ab8792 Fix ByRef parameters breaking generated patch code 2021-09-07 03:40:09 +10:00
Sinai
297034e38b Cleanup 2021-09-07 03:19:40 +10:00
Sinai
57f59d1295 Finalize hook manager update 2021-09-06 23:10:10 +10:00
Sinai
fbdb84eefa Implement HookManager UI and logic 2021-09-06 23:04:40 +10:00
Sinai
6989ea1b19 Misc cleanups 2021-09-06 23:03:55 +10:00
Sinai
fcdfeb2dec Redesign mouse inspector class, add UI results panel 2021-09-06 17:10:01 +10:00
Sinai
a1d0b6432e Cleanup 2021-09-06 15:51:40 +10:00
Sinai
0b84405e57 Fix incorrect startup delay logic 2021-09-02 18:29:21 +10:00
Sinai
c31e0949d3 Update ExplorerMelonMod.cs 2021-09-02 17:30:56 +10:00
Sinai
5f0495a7ea
Update README.md 2021-08-24 18:42:22 +10:00
Sinai
28de6779d8 Fix for Canvas.renderingDisplaySize crash 2021-08-24 17:47:42 +10:00
Sinai
fae85c2968 Bump version 2021-08-23 18:35:36 +10:00
Sinai
fc8fa9aa7a Fix TestClass init mistake 2021-08-23 18:35:31 +10:00
Sinai
bcf9a801a9 Fix suggestions still being given in comments sometimes 2021-08-23 18:35:22 +10:00
Sinai
20298aa47b Make Type and Member names selectable / copy+paste-able 2021-08-23 18:35:08 +10:00
Sinai
e2c1c186c3 Add wrapper to handle LemonAction issue 2021-08-23 18:31:26 +10:00
Sinai
9ce6508828 Update README.md 2021-08-19 16:20:41 +10:00
Sinai
506e75c5fe Handle Unhollowed modules path through IExplorerLoader. Allow Standalone release to specify manually. 2021-08-19 16:20:25 +10:00
Sinai
a2f22051f0 Cleanup 2021-08-19 16:19:49 +10:00
Sinai
4e3203a91b Make Assembly.GetTypes patch a finalizer instead of prefix 2021-08-10 17:31:12 +10:00
Sinai
a411ce2dba Add patch for Assembly.GetTypes to catch exceptions 2021-08-10 17:17:44 +10:00
Sinai
48132b3d46 Cleanup ILRepack 2021-08-10 17:17:21 +10:00
Sinai
e49ed3028f Cleanup 2021-08-06 18:44:13 +10:00
Sinai
31dd54d25c Reduce string alloc 2021-08-06 16:02:58 +10:00
Sinai
3cfdd6fa43 Update readme -noci 2021-08-04 01:16:52 +10:00
Sinai
1fa1283a68 Cleanup and update readme 2021-08-03 18:30:07 +10:00
Sinai
afa4135b67 Update ML lib for "LemonCleanup" breaking changes 2021-08-03 16:12:28 +10:00
Sinai
48d1cf574d Fix evaluate exception logic with methods that have arguments 2021-08-03 16:11:54 +10:00
Sinai
df0abbc847 Small optimizations/cleanup 2021-08-03 16:11:16 +10:00
Sinai
5c9dcb1d43 Bump HarmonyX to 2.5.2 2021-07-28 19:14:37 +10:00
Sinai
602770d980 Cleanup 2021-07-28 19:01:43 +10:00
Sinai
f26371f95f Go back to previous panel transform saving, no need to change 2021-07-28 18:27:10 +10:00
Sinai
a673c39f4a Include arial in legacy bundles 2021-07-28 18:26:53 +10:00
Sinai
40583cae3d Include arial in legacy bundles, cleanup 2021-07-28 06:41:02 +10:00
Sinai
20018a9ba9 Use invariant decimal separator for NumberFormatString 2021-07-28 06:40:05 +10:00
Sinai
dabf92a1a5 Use CurrentCulture, and use whitespace instead of comma as separator 2021-07-27 22:17:26 +10:00
Sinai
b7e275f02c Cleanup 2021-07-27 22:12:48 +10:00
Sinai
f393e0d706 Include Arial font, don't rely on built-in resource
TODO add font to legacy bundles
2021-07-27 18:14:44 +10:00
Sinai
ab8acc9e84 Change directory case 2021-07-21 20:53:03 +10:00
Sinai
66c30ee70e Cleanup 2021-07-21 20:48:21 +10:00
Sinai
ddd271c00d Cleanup 2021-07-21 20:12:34 +10:00
Sinai
30fe9e4dde Cleanup 2021-07-21 18:37:01 +10:00
Sinai
fa3a436037 Cleanup 2021-07-21 18:29:01 +10:00
Sinai
ca27d2b20f Update CursorUnlocker.cs 2021-07-21 05:18:22 +10:00
Sinai
4315e0c547 Merge branch 'master' of https://github.com/sinai-dev/UnityExplorer 2021-07-21 04:23:55 +10:00
Sinai
3e19e74329 Update readme -noci 2021-07-21 04:17:41 +10:00
Sinai
5a3ffebadc
Remove legacy build 2021-07-21 04:16:53 +10:00
Sinai
6e6b6239d8 Do patching in CursorUnlocker, add patch for SetSelectedGameObject 2021-07-21 04:14:34 +10:00
Sinai
03c8e5a8bd Add Harmony instance to ExplorerCore, bump version 2021-07-21 04:14:12 +10:00
Sinai
44f7209843 Remove ML 0.3 builds 2021-07-21 04:13:54 +10:00
Sinai
734e45cf9f Remove patching in mod loader classes 2021-07-21 04:13:42 +10:00
Sinai
97838e0b3a Update Unhollower 2021-07-21 04:13:15 +10:00
Sinai
304b47f898 Bump version 2021-07-19 21:43:40 +10:00
Sinai
3d1fcbcd9f Fix duplicate Scene hashcodes breaking PopulateSceneDropdown 2021-07-19 21:43:36 +10:00
Sinai
36fc17aa43 Get rid of pointless ReadOnlyCollection properties 2021-07-19 21:43:16 +10:00
Sinai
adfa29e63c Bump version 2021-07-15 05:20:31 +10:00
Sinai
3ffdcea73b Force all devices to always be supported by InputSystem 2021-07-15 05:20:26 +10:00
Sinai
dfd55260a8 Fallback to null check loading if unityVersion throws an exception 2021-07-15 05:19:48 +10:00
Sinai
29c78dc5a6 Manually get Major and Minor instead of using Version class 2021-07-11 23:22:33 +10:00
Sinai
bf59d9d6cd Handle cases where Unity doesn't include 'f' suffix on version
Not sure if this ever happens but just in case
2021-07-11 18:19:09 +10:00
Sinai
bb0c59534a Bump version 2021-07-11 18:11:18 +10:00
Sinai
802bb722bc Use Application.unityVersion to load appropriate AssetBundle
And fix issue with Dropdowns and Time input label not refreshing properly on launch
2021-07-11 18:11:14 +10:00
Sinai
9ca992b0d7
Fix incorrect config description example 2021-07-07 23:27:43 +10:00
Sinai
5f3b3a6870
cleanup -noci 2021-07-07 23:21:40 +10:00
Sinai
f5bce439cb Favor public GetEnumerator over private. Use GetActualType. Improve logging. 2021-07-06 16:42:20 +10:00
Sinai
e2b2c9038a Add 'other' issue template -noci 2021-07-05 19:05:04 +10:00
Sinai
fbefccd6b7 Update issue template -noci 2021-07-02 23:32:02 +10:00
Sinai
271c91f0d0 Update README.md 2021-07-02 20:03:41 +10:00
Sinai
eb221bd868 Bump version 2021-07-02 18:45:09 +10:00
Sinai
5b516eb4cc Add assembly name to class search result labels 2021-07-02 18:45:03 +10:00
Sinai
601567f9d2 Remove arbitrary static restriction on class search 2021-07-02 17:53:12 +10:00
Sinai
7ff508b874 [IL2CPP] Support private interface implementations on IDictionary and IEnumerable 2021-07-02 17:45:18 +10:00
Sinai
09a7cd35cf Remove known issues from readme -noci 2021-07-02 17:35:34 +10:00
Sinai
db4a338d26 Update issue template -noci 2021-07-02 17:33:41 +10:00
Sinai
c08e02057c
Create enhancement.yaml 2021-07-02 17:31:36 +10:00
Sinai
362fcdc51a Update bug_report.yaml 2021-07-02 17:22:24 +10:00
Sinai
73bd172e4d Update bug_report.yaml 2021-07-02 17:16:09 +10:00
Sinai
454d3bd0b4 Add bug report issue template 2021-07-02 17:10:26 +10:00
Sinai
f815a13d9a Namespace cleanup, move some categories out of UI namespace 2021-06-30 07:49:58 +10:00
Sinai
65c4d49274 Update readme 2021-06-26 18:08:21 +10:00
Sinai
d99137526e Fix InspectUnderMouse breaking ScrollPool in rare cases 2021-06-22 20:39:46 +10:00
Sinai
92447b55cd Update README.md 2021-06-22 19:48:41 +10:00
Sinai
87d5d5a2de Bump version 2021-06-22 19:46:14 +10:00
Sinai
08cff3386b Fix issues with Il2Cpp nullables 2021-06-22 19:46:09 +10:00
Sinai
6033200579 Don't use WaitForEndOfFrame in SrollPool init coroutine 2021-06-22 19:45:57 +10:00
Sinai
94ec1c4908 Update line numbers on panel resize 2021-06-21 19:50:11 +10:00
Sinai
7a400e762c Cleanup 2021-06-21 19:49:44 +10:00
Sinai
67f9f744bb Handle Unity 2021+ InputField.onEndEdit change 2021-06-21 19:26:05 +10:00
Sinai
7a59f9a2a1 Update info about startup script -noci 2021-06-20 19:10:44 +10:00
Sinai
9b42eef1b9 Line numbers and startup script 2021-06-20 19:06:52 +10:00
Sinai
830000b019 Bump version 2021-06-20 19:06:33 +10:00
Sinai
34910ab273 Bump version 2021-06-14 18:56:56 +10:00
Sinai
86b036095e Allow panels to be dragged further outside the game window 2021-06-14 18:56:51 +10:00
Sinai
b57e5be2e6 Add GameObject.activeSelf toggle to TransformTree, adjust UI Toggle design 2021-06-14 18:43:26 +10:00
Sinai
2d8ae45814 Cleanup 2021-06-14 18:43:08 +10:00
Sinai
66dc262a68 Move inner exception null check outside IL2CPP ppd 2021-06-11 18:12:14 +10:00
Sinai
4342901206 Prevent null exceptions being used in ReflectionExToString 2021-06-11 17:36:35 +10:00
Sinai
58b7c72a5c Allow UI inspect without main camera 2021-06-11 17:36:17 +10:00
Sinai
623dc7b7be Clarify VS build instructions 2021-06-10 18:14:33 +10:00
Sinai
e6f4939cc9
Update README.md 2021-06-07 19:50:36 +10:00
Sinai
7a539ba78b Bump version 2021-06-07 19:28:25 +10:00
Sinai
0d10f94eb5 Use Paths.BepInExRootPath, and cleanup dirs 2021-06-07 19:27:39 +10:00
Sinai
91671bf243 Failsafe in case Component is null from GetComponents? 2021-06-07 19:27:09 +10:00
Sinai
a72877befb Make AllTypes protected, force using GetTypeByName 2021-06-07 19:26:46 +10:00
Sinai
16335c1bc4 Auto-cleanup 2021-06-05 19:36:09 +10:00
Sinai
8fab9e6268 Update readme -noci 2021-06-03 17:50:48 +10:00
Sinai
fdd9039cca Update README.md 2021-06-03 17:47:57 +10:00
Sinai
dcca980635 Merge branch 'master' of https://github.com/sinai-dev/Explorer 2021-06-03 17:19:01 +10:00
Sinai
bfcab8248e Bump version 2021-06-03 17:18:52 +10:00
Sinai
97c20144f1 Fix string/comment state being incorrect if match ended at last character 2021-06-03 17:18:46 +10:00
Sinai
aaab10a0a0 Do auto-indent before highlighting so the characters are in the correct position 2021-06-03 17:18:11 +10:00
Sinai
b42a8dbe6a
Update readme -noci 2021-06-03 02:48:14 +10:00
Sinai
d7008db22e
Update README.md 2021-06-02 16:25:12 +10:00
Sinai
8c1913fe80
Update README.md 2021-06-02 15:33:19 +10:00
Sinai
8d8c9ac7c9 Use whitespace as delimiter in completion composition, handle string/comment state with Lexer 2021-06-01 16:40:51 +10:00
Sinai
f35beeaf58 Bump version 2021-06-01 16:00:56 +10:00
Sinai
d150ff3455 Fix minor issues with CSConsole delimiter logic 2021-06-01 16:00:52 +10:00
Sinai
c4fa0d6bcd Add better time logging to reflection init 2021-06-01 16:00:18 +10:00
Sinai
a5f56cf5a3 Prevent very large Texture images from overflowing outside the Texture Viewer 2021-05-31 19:10:05 +10:00
Sinai
8c822b2ee9
Simplify ci workflow 2021-05-30 04:50:37 +10:00
Sinai
4681b7e192 Update README -noci 2021-05-29 19:46:39 +10:00
Sinai
97093733d8
Update README -noci 2021-05-29 19:42:12 +10:00
Sinai
615f77979f Update README -noci 2021-05-29 19:41:14 +10:00
Sinai
ba3cf970d9
Update README.md 2021-05-29 19:30:08 +10:00
Sinai
b2fb571b18
Testing ci skip -noci 2021-05-29 19:15:28 +10:00
Sinai
67ce6f946a
Update dotnet.yml 2021-05-29 19:13:30 +10:00
Sinai
1b82ccb49f Bump version 2021-05-29 19:07:44 +10:00
Sinai
480eb5afd5 Use HarmonyX NuGet package 2021-05-29 19:07:26 +10:00
Sinai
88ea2a09c9
Update README.md 2021-05-29 18:46:17 +10:00
Sinai
a678aa4d78
Update dotnet.yml 2021-05-29 18:30:52 +10:00
Sinai
eaf478e314 Using temporary manual HarmonyX reference 2021-05-29 18:27:40 +10:00
Sinai
d391968b32
Update dotnet.yml 2021-05-29 17:50:59 +10:00
Sinai
70349ad7c7
Update dotnet.yml 2021-05-29 17:48:02 +10:00
Sinai
78f2d1070f
Update dotnet.yml 2021-05-29 17:46:59 +10:00
Sinai
51307563ab
Update dotnet.yml 2021-05-29 17:41:08 +10:00
Sinai
185d1aaa0f
Update dotnet.yml 2021-05-29 17:38:21 +10:00
Sinai
3d6e8fcbf8
Update dotnet.yml 2021-05-29 17:36:56 +10:00
Sinai
1daf4fade4 Use HarmonyX NuGet instead of submodule 2021-05-29 17:36:07 +10:00
Sinai
d92fb3f83f
Update dotnet.yml 2021-05-29 17:27:52 +10:00
Sinai
fe24b68fe2
Update dotnet.yml 2021-05-29 17:24:53 +10:00
Sinai
6bf92b9a96
Update dotnet.yml 2021-05-29 17:20:42 +10:00
Sinai
9f1cab019d
Create dotnet.yml 2021-05-29 17:18:09 +10:00
Sinai
a131404ac7 Cleanup 2021-05-29 14:50:27 +10:00
Sinai
773900d749 Fix CacheProperty not resetting Exception state when it has arguments 2021-05-29 14:50:21 +10:00
Sinai
342fc6bdb8 Maintain last timeScale value 2021-05-28 18:48:55 +10:00
Sinai
e85ea6ac3a Make Il2CppProvider actually process FixedUpdate coroutines 2021-05-28 18:23:45 +10:00
Sinai
af889e64cb Fix exception when inspecting UnityObject classes with static reflection 2021-05-28 18:23:30 +10:00
Sinai
0274022ce4 Make sure WaitForEndOfFrame object is never null 2021-05-28 18:23:07 +10:00
Sinai
211576e0f8 Fallback to LateUpdate if OnPostRender listener failed 2021-05-28 18:22:44 +10:00
Sinai
3e42d7479f Update README.md 2021-05-28 16:59:22 +10:00
Sinai
df4dea20c1 Update README.md 2021-05-28 16:55:01 +10:00
Sinai
ece0c43067 Add Time.timeScale helper on main navbar 2021-05-28 16:39:42 +10:00
Sinai
6311c8d09a Bump version 2021-05-28 15:51:09 +10:00
Sinai
04739d0be8 Separate default reflection blacklist from user list, add try/catch 2021-05-28 15:51:03 +10:00
Sinai
a46acba265 Better JumpToIndex height calculation 2021-05-27 19:44:17 +10:00
Sinai
5515b2eae4 Bump version 2021-05-27 19:31:01 +10:00
Sinai
9992029e28 Set DataViewInfo struct back to array in rebuild, cleanup 2021-05-27 19:30:55 +10:00
Sinai
14105785f0 Fix SceneExplorer not properly detecting scene changes sometimes 2021-05-27 19:30:19 +10:00
Sinai
365269b0dd Clear GameObject Component and Transform lists properly on close 2021-05-27 19:29:00 +10:00
Sinai
0b973393d1 Cleanup 2021-05-27 19:28:22 +10:00
Sinai
701d4431ae Delete explorerui.legacy.bundle.bak.5.3.8 2021-05-27 16:00:42 +10:00
Sinai
bfa73bcb55 Cleanup Pool.cs 2021-05-26 19:42:56 +10:00
Sinai
b0bbeb3cf8 Cleanup and fix small issue with JumpToIndex 2021-05-26 18:32:47 +10:00
Sinai
1a26623080 Add option to disable EventSystem override 2021-05-26 18:02:10 +10:00
Sinai
041f2938f7 Implement jumping to index in TransformTree 2021-05-26 17:42:31 +10:00
Sinai
9e7bb1a625 Cleanup 2021-05-26 17:42:14 +10:00
Sinai
36f23b7cdc Move SceneHandler.cs 2021-05-26 17:41:51 +10:00
Sinai
b51b743df4 Prevent very niche recursion situation 2021-05-26 17:41:38 +10:00
Sinai
805aff07cc Update README.md 2021-05-26 17:41:19 +10:00
Sinai
bcdaf3b97e Bump version 2021-05-26 17:41:14 +10:00
Sinai
cb8e947fdf Namespace/structure cleanup 2021-05-26 17:40:09 +10:00
Sinai
c8899be3ae Bump version 2021-05-26 03:59:50 +10:00
Sinai
cd5c69c965 Add timer debug to deobfuscation cache 2021-05-26 03:59:45 +10:00
Sinai
5427312f18 Filter UnityExplorer objects from search results 2021-05-26 03:59:17 +10:00
Sinai
eb7e80d910 Make sure Mouse Inspect dropdown list gets destroyed after option chosen 2021-05-26 03:59:08 +10:00
Sinai
a54888ae3a Make DataViewInfo a struct instead of class 2021-05-25 15:46:30 +10:00
Sinai
4f0553d293 Remove formatting from ToStringUtility 2021-05-23 19:34:32 +10:00
Sinai
9f0f7f9b57 Prevent some niche exceptions with EventSystem 2021-05-23 18:33:19 +10:00
Sinai
383c6f19e8 Update README.md 2021-05-23 16:20:09 +10:00
Sinai
428fab28f9 Cleanup HideAndDontSave detection and support 2021-05-23 16:16:32 +10:00
Sinai
760b2981ad Update README.md 2021-05-23 13:59:29 +10:00
Sinai
eee7d6bcc4 Add ML 0.3.0 build 2021-05-23 13:58:26 +10:00
Sinai
e270f205a1 Fix scroll pool inserting off-by-one 2021-05-20 20:22:45 +10:00
Sinai
084aee617c Prevent null reference if Canvas isn't created yet 2021-05-19 22:21:08 +10:00
Sinai
d0e508727a Prevent deobfuscation crash from using Il2CppType.From, and use faster method anyway 2021-05-19 21:26:44 +10:00
Sinai
a9a53ba924 Force load all Unhollowed DLLs, use Assembly.LoadFile instead of .Load, blacklist some more types 2021-05-19 20:48:34 +10:00
Sinai
3cd9819790 remove backup libs 2021-05-19 19:47:13 +10:00
Sinai
5abfa3da67 Better EntryType checking for enumerables and dicts 2021-05-19 19:24:33 +10:00
Sinai
e5d2d29a47 Update README.md 2021-05-19 19:24:06 +10:00
Sinai
6a47e542e5 Update Extensions.cs 2021-05-19 18:46:01 +10:00
Sinai
f1b83e7c9e Cleanup 2021-05-19 18:45:53 +10:00
Sinai
44c6503ae2 Update unhollowed libs 2021-05-19 18:45:19 +10:00
Sinai
6970dcbbc7
Merge pull request #68 from sinai-dev/4.0.0-alpha
4.0 hotfixes
2021-05-18 21:20:09 +10:00
Sinai
ac9c2d5286 Use recursive GetGenericArguments to catch unusual type structures, cleanup InteractiveList value caching 2021-05-18 20:55:18 +10:00
Sinai
496a5de55e Update README.md 2021-05-18 20:44:42 +10:00
Sinai
b062924af7 Add support for writing to IList<T>'s which don't implement IList 2021-05-18 20:43:51 +10:00
Sinai
5aef8ddc99 Fix UIPanels being broken after resolution changes, better checks on size/position 2021-05-18 19:55:27 +10:00
Sinai
c134c1752e Update README.md 2021-05-18 01:25:57 +10:00
Sinai
e4615aff84
Merge pull request #67 from sinai-dev/4.0.0-alpha
4.0.0 RC1
2021-05-18 00:18:29 +10:00
Sinai
8c5640dd12 Merge branch 'master' into 4.0.0-alpha 2021-05-18 00:18:04 +10:00
Sinai
76f71d9f3d Update README.md 2021-05-18 00:15:20 +10:00
Sinai
82e9c08ae6 Update img and README, cleanup 2021-05-18 00:13:29 +10:00
Sinai
019e589947 Add namespace autocompletions, some adjustments to autocomplete logic 2021-05-17 23:20:06 +10:00
Sinai
d7b0fff949 IL2CPP List/Dict support, cleanups 2021-05-17 21:48:39 +10:00
Sinai
7dbf694642 IL2CPP reflection fixes and improvements 2021-05-17 21:48:10 +10:00
Sinai
2fc9657560 Some UI adjustments and layout fixes 2021-05-17 18:47:37 +10:00
Sinai
fb6e413153 Misc cleanups and adjustments 2021-05-16 21:46:38 +10:00
Sinai
ca65affb5c Finish GameObject Inspector, some UI cleanups 2021-05-16 21:46:19 +10:00
Sinai
f4e473f8e6 Use StringBuilder for GetTransformPath 2021-05-16 21:45:38 +10:00
Sinai
8c5e7678a6 Fix LayerMask Parsing 2021-05-16 21:45:29 +10:00
Sinai
32ad61baea Rename ButtonListSource 2021-05-16 21:45:19 +10:00
Sinai
df330420a3 Add config to change main navbar anchor 2021-05-16 21:45:09 +10:00
Sinai
5af9d3104d Start GO inspector 2021-05-15 20:39:56 +10:00
Sinai
6977f1a31c Prevent any height value being smaller than default height 2021-05-15 20:39:51 +10:00
Sinai
26fb53f183 Color adjustments 2021-05-15 20:39:38 +10:00
Sinai
cccd02255f Force stop panel drag/resize when starting Inspect Under Mouse 2021-05-15 20:39:29 +10:00
Sinai
83f15c7168 Use Il2CppObjectBase instead of Il2CppSystem.Object where possible.
Attempt to fix il2cpp lists/dicts, not currently working properly. Will probably wait for Unhollower rewrite.
2021-05-15 18:00:16 +10:00
Sinai
bf8f838f01 Remove Control Key requirement on autocomplete navigation 2021-05-15 06:23:32 +10:00
Sinai
a915e1028f Update UIManager for new additions, cleanup 2021-05-15 06:23:13 +10:00
Sinai
8b1379f17e Adjust main navbar, expose nav gameobject 2021-05-15 06:23:01 +10:00
Sinai
0c7d8f8435 Update UnityExplorer.csproj 2021-05-15 06:21:45 +10:00
Sinai
72c3af3dd7 Prevent panels dragging outside screen 2021-05-15 06:21:42 +10:00
Sinai
54f78ac10b Implement InspectUnderMouse 2021-05-15 06:20:56 +10:00
Sinai
2a9c4972dd Revised C# Console help/feedback 2021-05-15 06:20:44 +10:00
Sinai
e93edc5b19 Options cleanup 2021-05-15 06:20:07 +10:00
Sinai
c25abfe3ff Fix normal args setting generic arg input field placeholder text 2021-05-15 06:19:44 +10:00
Sinai
8c3603baa0 Add AllowNavigation property to ISuggestionProvider, implement 2021-05-15 01:41:03 +10:00
Sinai
021db69409 Improve C# Console, key navigation on AutoCompleter 2021-05-15 01:21:07 +10:00
Sinai
1c216c0d86 Add some CSConsole interactions, some UI Cleanups 2021-05-14 06:14:25 +10:00
Sinai
12fe19ba8e Implemented the console log, some cleanups 2021-05-14 02:45:59 +10:00
Sinai
89022db5fc Implement Options panel, some cleanups 2021-05-13 23:03:30 +10:00
Sinai
ccd08c3a63 Add configurable reflection signature blacklist, extends to MCS as well 2021-05-13 23:02:46 +10:00
Sinai
843d7ed451 Update mcs-unity 2021-05-13 22:56:23 +10:00
Sinai
3e44317861 Cleanup CSConsole, add start of Options and Log panels 2021-05-13 03:55:08 +10:00
Sinai
70d66f93a5 Update ReflectionUtility.cs 2021-05-13 01:06:14 +10:00
Sinai
275225a284 Better number ToString formatting, cleanups 2021-05-13 00:58:23 +10:00
Sinai
b61020fe67 Cleanup 2021-05-12 21:29:59 +10:00
Sinai
ada239c828 Implement auto-indenting for CSConsole, some cleanups 2021-05-12 20:48:56 +10:00
Sinai
fedecb80a0 Update mcs-unity 2021-05-12 20:47:46 +10:00
Sinai
97738b00c1 Update mcs-unity 2021-05-11 23:17:11 +10:00
Sinai
59cbeec103 cleanup 2021-05-11 23:10:12 +10:00
Sinai
a9f6ed8729 Cleanup libs, target ML 0.3.1 2021-05-11 20:23:52 +10:00
Sinai
7241247d05 Rename some members to avoid confusion 2021-05-11 19:18:27 +10:00
Sinai
ec215a0006 Use SortedSet for type name cache, expose OnTypeLoaded event 2021-05-11 19:16:19 +10:00
Sinai
6e9bb83099 More progress on C# Console - implement AutoCompletes, some cleanups 2021-05-11 19:15:46 +10:00
Sinai
712bf7b669 Cleanup libs, use submodules and packages where appropriate 2021-05-11 19:13:58 +10:00
Sinai
b4b96134c4 add mcs-unity submodule properly 2021-05-11 17:55:47 +10:00
Sinai
d3b942065d temp remove mcs submodule 2021-05-11 17:55:23 +10:00
Sinai
9ea50e232c use submodules for HarmonyX and Unhollower 2021-05-11 17:47:22 +10:00
Sinai
4128f8519d Update .gitmodules 2021-05-11 17:45:54 +10:00
Sinai
53e1e6bf22 Update .gitmodules 2021-05-11 17:44:31 +10:00
Sinai
b67ac145d4 Update .gitmodules 2021-05-11 17:39:00 +10:00
Sinai
586c63b668 Update .gitmodules 2021-05-11 17:32:13 +10:00
Sinai
65323e3b16 Update .gitmodules 2021-05-11 17:29:34 +10:00
Sinai
cfeb5ba018 Create .gitmodules 2021-05-11 17:24:03 +10:00
Sinai
8a15c11289 Remove redundant GameObject search context 2021-05-11 02:39:01 +10:00
Sinai
4019af5936 Hide TypeCompleter on suggestion chosen 2021-05-11 02:38:39 +10:00
Sinai
34c8ad3646 Make PruneString helper 2021-05-11 02:38:24 +10:00
Sinai
617d68f7e9 rename Lexer folder to match namespace, some cleanups and color adjustments 2021-05-11 01:43:08 +10:00
Sinai
2efce9eb0e Simplify keyword highlighting 2021-05-10 23:24:52 +10:00
Sinai
18d2518231 Use the Member color for the member filter toggles, move InspectorManager 2021-05-10 23:09:21 +10:00
Sinai
cef4c2f3fb Cleanup and simplify highlight process, reduce string alloc 2021-05-10 23:00:02 +10:00
Sinai
1d24af5666 Only lexer-highlight what is shown in CS console (fix max vert overflow) 2021-05-10 21:07:27 +10:00
Sinai
4f50afdddc Update SymbolLexer.cs 2021-05-10 16:35:37 +10:00
Sinai
caad39bb9a Rewrite lexer from scratch 2021-05-10 15:58:49 +10:00
Sinai
06122fe8c9 Update CSLexer.cs 2021-05-09 20:32:47 +10:00
Sinai
e6b253fed9 Enum parse support, start work on CSConsole, cleanup 2021-05-09 20:18:33 +10:00
Sinai
7b700cbe55 Cleanup, extend ParseUtility to dict keys 2021-05-09 02:22:03 +10:00
Sinai
c04a864b74 Made ParseUtility helper to simplify and improve parsing of various input types 2021-05-09 01:25:26 +10:00
Sinai
c828d9b642 InteractiveValueStruct, and a few cleanups 2021-05-08 20:54:16 +10:00
Sinai
26052621e5 Cleanup 2021-05-08 06:19:17 +10:00
Sinai
d101e7e35c Cleanup 2021-05-08 06:18:46 +10:00
Sinai
57aace26d3 Refresh for child count or name changes in TransformTree 2021-05-08 06:18:28 +10:00
Sinai
3d94b51d40 Catch bad user input on number input 2021-05-08 06:17:30 +10:00
Sinai
d34aeb81b3 InteractiveEnum, InteractiveColor 2021-05-08 06:16:43 +10:00
Sinai
d8f532d913 Make InputFieldRef helper, InteractiveString and IOUtility 2021-05-07 17:06:56 +10:00
Sinai
4931117b1e Make helper for cache object controller SetCell 2021-05-07 06:27:44 +10:00
Sinai
1f996f52fe Fix casting for dictionary keys, only cast displayed key
And fix layout
2021-05-07 06:27:23 +10:00
Sinai
00c28f781a Allow editing null strings, remove "null" ValueState 2021-05-07 06:26:48 +10:00
Sinai
f080379e8a Update ReflectionUtility.cs 2021-05-07 06:25:49 +10:00
Sinai
2977fd4df5 Handle il2cpp primitives (not boxed) 2021-05-07 06:25:31 +10:00
Sinai
56875e0641 Simplify string obfuscation processing 2021-05-07 01:53:02 +10:00
Sinai
8534c08f49 Reflection cleanup, fix il2cpp struct and enum boxing
And temp removing il2cpp IDictionary / IEnumerable helpers, will see what is necessary after knah's rewrite.
2021-05-07 01:22:55 +10:00
Sinai
1ee10c2507 Setting values from IList / IDictionary to source 2021-05-06 20:28:04 +10:00
Sinai
9e8a18a5e1 Fix cell view link mismatch 2021-05-06 16:47:37 +10:00
Sinai
6c7acf7690 Handle boxing value types to Il2CppSystem.Object, some cleanups 2021-05-06 06:36:39 +10:00
Sinai
e70a1e96da Update ReflectionInspector.cs 2021-05-06 04:18:35 +10:00
Sinai
22435176bf Fix some issues in IL2CPP, improve type cache efficiency, reduce alloc 2021-05-06 04:02:42 +10:00
Sinai
e4ff86259b More progress 2021-05-05 21:27:09 +10:00
Sinai
961ff80c6d Update GameObjectInspector.cs 2021-05-04 20:39:54 +10:00
Sinai
a89d66cf81 More progress, cleanups and fixes 2021-05-04 20:10:46 +10:00
Sinai
302ff29e36 Merge branch '4.0.0-alpha' of https://github.com/sinai-dev/Explorer into 4.0.0-alpha 2021-05-03 21:02:09 +10:00
Sinai
8d9d8f76c2 Cleanup, use Time.realTimeSinceStartup instead of Time.time, add some stuff 2021-05-03 21:02:01 +10:00
Sinai
3dc458ab1b
Merge pull request #62 from HerpDerpinstine/4.0.0-alpha
Added ML v0.3.1 Support and Commented it Out
2021-05-03 20:59:47 +10:00
Herp Derpinstine
f5c0b339ae
Added ML v0.3.1 Support and Commented it Out 2021-05-03 01:13:43 -05:00
Sinai
ad61ff243a progress on lists and dictionaries, fixes for scrollpool 2021-05-03 01:29:02 +10:00
Sinai
bfaba56b76 bump lib versions 2021-05-03 01:10:12 +10:00
Sinai
1c5306b7c8 Fix the onValueChange throttling affecting internal features 2021-05-03 00:59:39 +10:00
Sinai
15ec64b106 Progress on inspector, interactive list basically done 2021-05-01 20:55:27 +10:00
Sinai
ab8b736f7e Improve Il2Cpp Coroutine support, make universal ExplorerBehaviour class 2021-05-01 20:55:14 +10:00
Sinai
ea1e183c4a Fix onValueChanged bursts 2021-05-01 16:32:11 +10:00
Sinai
d6cde68a44 Fix namespaces being included for generic parameters 2021-04-30 23:43:36 +10:00
Sinai
d76bc1f812 Add ContainsIgnoreCase helper to reduce string alloc, cleanup 2021-04-30 23:43:27 +10:00
Sinai
74ff1d8f01 Cleanup 2021-04-30 23:12:18 +10:00
Sinai
2378925a8b More progress 2021-04-30 21:34:50 +10:00
Sinai
8080129d58 Merge branch 'master' of https://github.com/sinai-dev/Explorer 2021-04-30 00:12:48 +10:00
Sinai
4b8298fd2e Update CursorUnlocker.cs 2021-04-30 00:12:41 +10:00
Sinai
ad055b4383
Update README.md 2021-04-29 21:54:13 +10:00
Sinai
23483a6108 Add aggressive mouse unlock option using WaitForEndOfFrame 2021-04-29 21:45:45 +10:00
Sinai
0bc14b2f76 Update CursorUnlocker.cs 2021-04-29 21:05:53 +10:00
Sinai
dba9bdbdc2 More progress, and change Aggressive Mouse Unlock behaviour 2021-04-29 21:01:08 +10:00
Sinai
a2a2b09d33 more progress 2021-04-28 23:58:13 +10:00
Sinai
324d3afa5b
Update CacheMember.cs 2021-04-28 21:52:42 +10:00
Sinai
99e11b41a3
Update DataHeightCache.cs 2021-04-28 21:20:41 +10:00
Sinai
b0d54b1d80 Progress on ReflectionInspector, framework mostly done 2021-04-28 20:47:48 +10:00
Sinai
a2ff37e36d Some progress on inspector rewrites, most of the framework figured out now. 2021-04-27 21:22:48 +10:00
Sinai
07ddba3c3d Update ReflectionUtility.cs 2021-04-27 21:22:21 +10:00
Sinai
73cde0f91f Fix for games where InputSystem is present but not active 2021-04-27 21:22:16 +10:00
Sinai
af3ee07143 Rewriting everything from scratch, added generic ObjectPool system 2021-04-26 19:56:41 +10:00
Sinai
9f8d53f55a Rewriting everything from scratch, developed generic ObjectPool system 2021-04-26 19:56:21 +10:00
Sinai
5a0c2390ce Use StringBuilder and add caching to reduce string allocs 2021-04-25 21:21:05 +10:00
Sinai
f3cd84804d Some UI cleanups, improving caching and reduce image allocation 2021-04-25 21:20:50 +10:00
Sinai
fda5afae46 stress test 2021-04-25 21:19:12 +10:00
Sinai
7f6a4514e4 Handle cases where InputSystem is present but not active 2021-04-25 21:19:00 +10:00
Sinai
1487372832 Update DataHeightCache.cs 2021-04-25 00:28:30 +10:00
Sinai
6d4cc66079 Adding back rest of the menu, ported most of Reflection Inspector for new UI 2021-04-25 00:21:12 +10:00
Sinai
0cf8309a82 Fix DataHeightCache logic, cleanup some loose ends and edge cases, add rebuild fix 2021-04-24 16:45:17 +10:00
Sinai
38bd19c243 cleanup 2021-04-24 05:23:29 +10:00
Sinai
bda286ddae Make AutoCompleter a global widget which anything can use, add support to object search for it 2021-04-24 04:03:33 +10:00
Sinai
5f2f3fe1c6 Fix logic in data height cache, account for spread properly 2021-04-24 04:02:26 +10:00
Sinai
59156492e7 Add jump to top logic for rebuild and refresh 2021-04-24 04:01:30 +10:00
Sinai
ebb89b1b8b Update UnityExplorer.csproj 2021-04-24 04:01:03 +10:00
Sinai
30f847dc23 Some improvements to panel dragging logic 2021-04-24 04:00:58 +10:00
Sinai
7ffaf62895 Improve deobfuscation efficiency 2021-04-24 04:00:15 +10:00
Sinai
f509a985e7 Added Search page and AutoCompleter 2021-04-23 21:50:58 +10:00
Sinai
eb58ab5327 Fix TransformCell for destroyed transforms 2021-04-22 22:57:04 +10:00
Sinai
feb86a77fd Cleanup scroll pool, fix some minor things 2021-04-22 22:56:46 +10:00
Sinai
012994ed02
Fix typo 2021-04-22 21:19:48 +10:00
Sinai
212d9a4d5e
Fix Take from sister cache 2021-04-22 21:18:31 +10:00
Sinai
a4f774b6b2 Fix unity log listeners 2021-04-22 20:11:34 +10:00
Sinai
bd6de84f93 Prevent dragging/resizing panels underneath the focused panel 2021-04-22 20:11:27 +10:00
Sinai
0d385c9cb8 Update ExplorerCore.cs 2021-04-22 19:12:16 +10:00
Sinai
fdfadcefc1 Added 'temp height cache' to ScrollPool for when filtering, fix some issues 2021-04-22 17:53:29 +10:00
Sinai
fc26452f64 Add elasticity to ScrollPool, stop movement on mouse scroll or slider change 2021-04-22 03:57:34 +10:00
Sinai
31fa786574 add MouseScrollDelta support to InputManager 2021-04-22 03:57:11 +10:00
Sinai
29b453dc91 final touches on scroll pool 2021-04-22 03:31:03 +10:00
Sinai
837d5792be Update DataHeightManager.cs 2021-04-22 01:04:59 +10:00
Sinai
1a8c2499fa Improve range start lookup efficiency 2021-04-21 23:39:18 +10:00
Sinai
e1e40950f8 Update DataHeightManager.cs 2021-04-21 23:08:16 +10:00
Sinai
edbb9a2882 Cleanup and fix some small issues with scroll pool 2021-04-21 23:07:15 +10:00
Sinai
0a9639f8a9 attempt at auto-increasing pool size, not quite working properly 2021-04-21 21:04:26 +10:00
Sinai
b32675e3b1 Finally got dynamic scroll pool working perfectly
Just need to add cells to pool if viewport height is expanded, otherwise I'd say its done.
2021-04-21 18:44:43 +10:00
Sinai
ff7c822d69 More progress on the dynamic scroll pool, almost done 2021-04-20 21:09:07 +10:00
Sinai
a619df8e01 Delete ScrollPool_bak.cs 2021-04-19 23:47:41 +10:00
Sinai
300b35c2d3 Finally got the scrollpool working properly with dynamic content height 2021-04-19 23:47:25 +10:00
Sinai
7a253fa0a0 replace old scrollpool with new dynamic one, more progress 2021-04-19 20:08:07 +10:00
Sinai
8b5e385c28 Working on a dynamic-height scroll pool, almost done 2021-04-18 21:38:09 +10:00
Sinai
bcc89455a7 rename "InfiniteScrollRect" to "ScrollPool" 2021-04-17 04:11:45 +10:00
Sinai
2e5fb72716 Update PanelDragger to handle multiple panels, add panel 'focusing' 2021-04-17 04:05:27 +10:00
Sinai
876cffd864 Delete PageHandler.cs 2021-04-16 23:59:58 +10:00
Sinai
7cb4faa596 Adjust panel size/pos 2021-04-16 23:59:54 +10:00
Sinai
c8f3a7f430 Fix min resize 2021-04-16 23:59:41 +10:00
Sinai
6cd7029ffc fix internal config overwriting standalone config 2021-04-16 21:07:54 +10:00
Sinai
225a07bc1b Create ToStringUtility for default labels 2021-04-16 21:07:45 +10:00
Sinai
085c79441b Create preliminary GameObject inspector for testing, cleanup some UI 2021-04-16 21:07:32 +10:00
Sinai
40d32e1919 cleanup scene loader, redundant code 2021-04-16 18:37:26 +10:00
Sinai
480a8cb31c fix DivideByZeroExceptions and add minimum handle size 2021-04-16 18:24:45 +10:00
Sinai
9bdcccaaa1 Add keybind for mouse unlock, and aggressive unlock mode 2021-04-16 18:24:31 +10:00
Sinai
0f69833283 Separate internal and public configs 2021-04-16 17:49:19 +10:00
Sinai
1769a4ed8d Make abstract UIPanel class, refactor SceneExplorer into that, some fixes 2021-04-16 17:49:05 +10:00
Sinai
c8a64c39b1 rename Model folder 2021-04-16 04:33:42 +10:00
Sinai
c1d3aab8e3 Fix transform tree and scroller, add update toggle and refresh button 2021-04-16 04:33:13 +10:00
Sinai
9a9048bcd8 Add CreateCell to ICell interface 2021-04-16 02:53:17 +10:00
Sinai
dec113d2ee Fix RectTransform.GetWorldCorners in il2cpp 2021-04-16 02:53:07 +10:00
Sinai
b03349a3e0 Use HashSet and List instead of Dictionary for TransformTree caching, fix logic 2021-04-16 02:52:54 +10:00
Sinai
896da0157d InfiniteScroll classes no longer need injection, using internal behaviour classes 2021-04-16 02:49:46 +10:00
Sinai
a58e2a0fad Detach ScrollRect class from InfiniteScrollRect, use UIBehaviourModel. Cleanup and fix for il2cpp 2021-04-16 02:48:49 +10:00
Sinai
b13aa74fa1 Use HashSet and List instead of Dictionary for SceneExplorer caching, fix refresh logic 2021-04-16 02:47:15 +10:00
Sinai
8ef6df043c safer UIRoot visibility check 2021-04-16 02:46:21 +10:00
Sinai
f89455549e safer UIBehaviour instance updates, init method 2021-04-16 02:46:04 +10:00
Sinai
a6ff9e02e2 remove menupages enum config entry 2021-04-16 02:45:38 +10:00
Sinai
51f5c68598 Remove temp gameobject creation, scene explorer is working fine 2021-04-15 20:28:27 +10:00
Sinai
5bb612cb5a Update SceneHandler.cs 2021-04-15 20:23:33 +10:00
Sinai
a3fcac1acb Update Il2CppProvider.cs 2021-04-15 20:21:14 +10:00
Sinai
d1d7572945 Remove test assembly resolver 2021-04-15 20:20:11 +10:00
Sinai
7eb4b1bc77 WIP
* Using publicized mono assemblies
* Remaking UI from scratch. Done the Scene Explorer so far.
2021-04-15 20:18:03 +10:00
Sinai
a6c24f91e4 Add startup delay 2021-04-11 20:45:02 +10:00
Sinai
9e4c335a05 Update MelonLoaderConfigHandler.cs 2021-04-10 23:17:49 +10:00
Sinai
a1c2dfbe50 Add support for setting disabled color on ColoBlock 2021-04-10 20:15:03 +10:00
Sinai
a5a07a0a23 Add RuntimeProvider method for setting Selectable.colors 2021-04-10 18:25:13 +10:00
Sinai
e0fd682c81 Add MethodInfo helper 2021-04-10 18:24:16 +10:00
Sinai
7426bd1dd6 Bump version 2021-04-10 17:44:15 +10:00
Sinai
b39b044f79 Add advanced attributes to BepInEx config 2021-04-10 17:44:09 +10:00
Sinai
7a2b4aa257 Fix setting color block when partially stripped 2021-04-10 17:43:56 +10:00
Sinai
3762d14bdb Fix InputSystem for IL2CPP 2021-04-10 17:43:32 +10:00
Sinai
3628f3db31 Fix event system control 2021-04-09 01:46:26 +10:00
Sinai
d39fea69c3 Better InputSystem Key enum resolving 2021-04-07 20:54:08 +10:00
Sinai
95e8b3aa58 fix string unbox 2021-04-07 17:31:06 +10:00
Sinai
b68145385c Fix issue with float struct check 2021-04-07 17:20:54 +10:00
Sinai
2310f2f7ce Add "Default Tab" config setting instead of "last active tab" 2021-04-07 17:20:42 +10:00
Sinai
2cc403ad17 Cleanup runtime-specific 2021-04-07 17:20:09 +10:00
Sinai
c2d9b9b59e a few small fixes
* Fix InteractiveFlags toggles not being properly updated
* Fix cases where games that don't have Reflection.Emit would still have the C# Console available. Also added a "(disabled)" message to the tab button.
2021-04-06 01:01:46 +10:00
Sinai
c748be7bcc Rewrite InteractiveUnityStruct, now called InteractiveFloatStruct
InteractiveFloatStruct supports any struct where all the fields are floats.
2021-04-05 20:32:47 +10:00
Sinai
09dae6f1d3 Add proper support for InputSystem 2021-04-05 16:28:30 +10:00
Sinai
6ca117b070 Fix strings boxed as Il2CppSystem.Objects 2021-04-04 13:44:58 +10:00
Sinai
113f2fd922 3.3.5 - fix Il2Cpp Hashtable, boxed strings 2021-04-04 03:41:36 +10:00
Sinai
7443f6500e Update README.md 2021-04-03 17:24:28 +11:00
Sinai
92566c2729
Update README.md 2021-04-02 19:56:18 +11:00
Sinai
713f87f455
Update THIRDPARTY_LICENSES.md 2021-04-02 17:45:50 +11:00
Sinai
4241e7e207 Include third-party licenses 2021-04-02 17:44:49 +11:00
Sinai
6d479a6703 3.3.4
* Fixed Harmony patches not working properly for games which use older BepInEx releases (ie. Risk of Rain 2)
* Fixed a couple minor issues with the config settings
2021-04-02 17:06:49 +11:00
Sinai
6539f818c3
Update README.md 2021-04-01 22:04:58 +11:00
Sinai
bc5ffcab40 Update README.md 2021-04-01 17:15:50 +11:00
Sinai
d070ded036 3.3.3
* Fix `Hide on Startup` not working
* Fix for cases when we try to `scene.GetRootGameObjects()` but the scene has not yet fully loaded.
* MelonLoader releases will no longer spam "Preferences Saved!" constantly in the Console log
* Fix mistake with UI Event System setting/releasing
* Fix some UI elements not having correct Color transition values
2021-04-01 17:13:31 +11:00
Sinai
8f025622b4 3.3.2
* Added InteractiveColor UI editor to make changing a Color easier
* Added a "Scene Loader" helper which allows you to load any Scene that the game was built with. In some cases you may not find all the Scenes that the game uses, they may be loaded through AssetBundles or other means and won't show up here yet
* Adjusted the SceneExplorer UI, the "Hide" button is now always on the left of the window
*
* Handled some errors related to UI unstripping that could occur in rare cases
2021-03-31 22:58:17 +11:00
Sinai
89f137680e Update DebugConsole.cs 2021-03-31 02:02:12 +11:00
Sinai
f280b45ed3 3.3.1
* Added a 'Default' button for config values to revert to the default value
* Added an internal config entry to save the window position between sessions
* Reordered the config settings in the menu so the important ones are at the top
* Adjusted the UI for config entries, should be a bit easier to read now.
* Adjusted the UI for Dictionaries, the keys and values now alternate background colors.
* A few other minor UI fixes and tweaks for 3.3.0
2021-03-31 01:42:32 +11:00
Sinai
456e15020f
Update README.md 2021-03-31 00:00:39 +11:00
Sinai
d33d46927d
Update README.md 2021-03-30 23:59:08 +11:00
Sinai
7a872cecf9 Update UIFactory.cs 2021-03-30 22:34:59 +11:00
Sinai
b2cbdc1802 Update README.md 2021-03-30 21:31:12 +11:00
Sinai
3501a28fd1 Restore UnlockMouse config, adjust config saving 2021-03-30 21:23:45 +11:00
Sinai
40f698122d Revert colorblock changes 2021-03-30 19:55:18 +11:00
Sinai
0555a644b7 3.3.0 rewrite
* Huge restructure/rewrite. No real changes to any functionality, just a cleaner and more manageable project.
2021-03-30 19:50:04 +11:00
Sinai
f66a04c93f Update README.md 2021-03-26 23:34:06 +11:00
Sinai
8f07255d1b Update README.md 2021-03-26 23:12:31 +11:00
Sinai
46f35129c5 3.2.10
* The following preferences are now persistent between sessions: Active Menu Page, Scene Explorer Hide State, Debug Console Hide State
* The "Resize Cursor" is now just a `↔` Text label instead of a sprite.
* Added support for Unity 5.2+ games (previously was only supporting 5.6)
2021-03-26 19:49:53 +11:00
Sinai
604c499822 Add Reset button to C# Console 2021-03-26 07:31:30 +11:00
Sinai
8964c48ba0 Move melon attributes to ExplorerMelonMod.cs 2021-03-26 06:38:59 +11:00
Sinai
e85a3e0f1e Merge bepinex/melonloader unhollowed libs 2021-03-26 06:04:44 +11:00
Sinai
c658d393f5 Update README.md 2021-03-26 05:59:17 +11:00
Sinai
9a45e29e02 Update README.md 2021-03-26 05:53:03 +11:00
Sinai
418ece55e3 Improve UI inspect-under-mouse 2021-03-26 05:43:53 +11:00
Sinai
bf455893e7 Include all references in lib folder 2021-03-26 05:40:12 +11:00
Sinai
6d9cb8205a Update README.md 2021-03-25 18:48:40 +11:00
Sinai
0f431e997b Update README.md 2021-03-25 18:47:52 +11:00
Sinai
2107df70ad Improvements to CS Console
* Errors are now logged properly.
* Can now define classes, methods, etc - no longer has to be an expression body.
* Added `StartCoroutine(IEnumerator routine)` helper method to easily run a Coroutine
* Disabling suggestions now properly stops Explorer trying to update suggestion cache instead of just not showing them. In the rare cases that suggestions cause a crash, disabling them will now prevent those crashes.
* Various other misc improvements behind the scenes
2021-03-25 18:39:35 +11:00
Sinai
a9fbea7c96 (C# Console) Only update autocomplete and indent if they are enabled 2021-03-24 17:14:13 +11:00
Sinai
77878ddd94 Use reflection for adding Unity log callback to avoid unstripping errors 2021-03-24 17:13:43 +11:00
Sinai
594abc47f8 Move RuntimeProvider.Init to after config is loaded 2021-03-24 17:13:26 +11:00
Sinai
5e326916a2 bump version 2021-03-23 16:16:09 +11:00
Sinai
31c2debb78 fix typo mistake in previous version 2021-03-23 16:15:16 +11:00
Sinai
d919497e43 Config: use en-us culture, fix recursive exception 2021-03-23 04:47:55 +11:00
Sinai
0c40b4fad9 Merge branch 'master' of https://github.com/sinai-dev/Explorer 2021-03-21 16:18:56 +11:00
Sinai
bba912667f fix ToString exception 2021-03-21 16:18:47 +11:00
Sinai
1807e7c5ff
Update TextureUtilProvider.cs 2021-03-21 15:16:36 +11:00
Sinai
9da2ea9b1b Update README and Lexer namespaces 2021-03-18 18:52:30 +11:00
Sinai
1a5843f8e1 disable main menu page on failed init 2021-03-18 18:38:51 +11:00
Sinai
25e48f2f37 Project refactor, namespace cleanup, splitting UI/functionality. 2021-03-18 17:17:29 +11:00
Sinai
1c0011bef9 bump version 2021-03-16 18:13:14 +11:00
Sinai
9e996816ef starting work on a cleanup/rewrite 2021-03-16 18:12:39 +11:00
Sinai
9665753dc8 fix BIE5 mono release 2021-03-16 18:12:26 +11:00
Sinai
942e9d7555 some commenting 2021-03-14 16:08:53 +11:00
Sinai
9efb9581f5 Cleanups, method summaries, bump version 2021-03-12 18:41:57 +11:00
Sinai
f10a462b00 More reflection caching, use deobfuscated names for ToString labels 2021-03-12 18:41:38 +11:00
Sinai
9072b16c5a Save window size between launches 2021-03-12 18:39:57 +11:00
Sinai
21408993c2 create subfolder for standalone 2021-03-11 18:40:04 +11:00
Sinai
7a8b5b50d1 bump version, update readme 2021-03-11 18:32:57 +11:00
Sinai
1a5e843070 handle ExplorerStandalone update internally 2021-03-11 18:16:52 +11:00
Sinai
ade7539fde cleanups 2021-03-11 17:57:58 +11:00
Sinai
5c588e5a03
Update README.md 2021-03-10 05:04:43 +11:00
Sinai
af094832fe Update README.md 2021-03-09 22:31:26 +11:00
Sinai
af0ee2e690 Update README.md 2021-03-09 22:29:53 +11:00
Sinai
d2d6fb4d55 Update README.md 2021-03-09 22:28:43 +11:00
Sinai
6c25662fe9 Update README.md 2021-03-09 17:36:49 +11:00
Sinai
4bcf82ca10 separate Bep5 and Bep6 support. Fix enums not backed by ints. 2021-03-09 17:35:54 +11:00
Sinai
ce38e8ac50 bump to MelonLoader 0.3.0 2021-03-06 17:25:54 +11:00
Sinai
12cd718f12 3.1.12: store Il2CppToMonoType key as string AssemblyQualifiedName instead of Type object 2021-03-04 01:44:34 +11:00
Sinai
995e2a3e93 3.1.11: fix potential crash on scene reload 2021-03-03 22:09:14 +11:00
Sinai
2c95fec646 3.1.10: Add "Hide on startup" config option 2021-02-27 17:04:47 +11:00
Sinai
69912d7ea4 Prevent GC Mark Overflow on C# Console copy+paste 2021-02-26 17:54:00 +11:00
Sinai
9c5596ace4 Update lib versions 2021-02-26 17:52:21 +11:00
Sinai
d4dac58fc8 Fix for deobfuscated unhollowed types not being properly resolved 2021-02-20 19:39:19 +11:00
Sinai
77b97cbe17 Update README.md 2021-02-03 18:31:29 +11:00
Sinai
c6f0f34ac0 Update README.md 2021-01-28 02:09:40 +11:00
Sinai
d1f4f74d32 some ui cleanups (minor) 2021-01-22 21:56:00 +11:00
Sinai
f13068bf01 Update README.md 2021-01-20 23:05:04 +11:00
Sinai
dfc288a101 Update README.md 2021-01-20 19:10:13 +11:00
Sinai
544009dc21 3.1.7
* Added standalone release build (thanks @Alloc86)
* Improved formatting for ToString methods which accept an IFormatProvider
* When editing a struct, the reference to the parent member will now be updated if you modify the struct values.
2021-01-20 17:22:36 +11:00
Sinai
fdfaaadd89 3.1.6 - don't bother setting pixelPerfect on canvas 2021-01-14 17:46:32 +11:00
sinaioutlander
58d60a10d4 Update ForceUnlockCursor.cs 2021-01-04 01:23:20 +11:00
sinaioutlander
0432c6d56c 3.1.5
* Integrate PR from js6pak
2021-01-03 19:27:02 +11:00
Sinai
8c34aa2be5
Merge pull request #29 from js6pak/embedded-assetbundle
Load assetbundle from EmbeddedResource
2021-01-03 19:13:15 +11:00
js6pak
4a1c54fac1
Load assetbundle from EmbeddedResource 2021-01-02 19:38:01 +01:00
sinaioutlander
190467fa5c Update README.md 2020-12-31 18:34:26 +11:00
sinaioutlander
44f54d9190 3.1.4 2020-12-31 18:32:52 +11:00
sinaioutlander
3b4ea31b50 Fix Texture2D saver in Mono and for non-readable textures 2020-12-24 18:10:17 +11:00
sinaioutlander
ad7b05f721 Just disable EventSystem component and not the entire gameobject 2020-12-21 16:33:34 +11:00
sinaioutlander
852ca8e9eb New attempt at fixing conflicting EventSystem problems in IL2CPP 2020-12-16 14:28:54 +11:00
sinaioutlander
7386eca0c2 Update UIManager.cs 2020-12-15 19:33:04 +11:00
sinaioutlander
97325a5f3a Fix an issue causing duplicated clicks in some IL2CPP games, fix setting Component.enabled in IL2CPP 2020-12-15 19:32:50 +11:00
sinaioutlander
82e52de557 Cleanup and fix Singleton search slightly 2020-12-14 19:26:59 +11:00
sinaioutlander
28181e2266 Restoring Texture viewer/saver, and Static/Singleton class searching 2020-12-14 18:35:43 +11:00
sinaioutlander
6dfa4806ce 3.0.8
Reverting to the previous World-Raycast method as it gave more accurate/expected results
2020-12-12 23:24:44 +11:00
Sinai
27f6a6ca52
Update README.md 2020-12-10 03:21:22 +11:00
sinaioutlander
cd7b260ea7 Fix in issue where the Behaviour Enabled toggle doesn't work in IL2CPP 2020-12-08 19:42:44 +11:00
sinaioutlander
ba986274be Bump version 2020-12-07 22:22:25 +11:00
sinaioutlander
d181c0bee9 Improved Enumerable and Dictionary enumeration in IL2CPP 2020-12-07 22:22:03 +11:00
sinaioutlander
a9faec8cf9 Some cleanups 2020-12-03 22:12:30 +11:00
sinaioutlander
a6bf91b7af accidentally replaced the original asset bundle 2020-11-25 16:47:13 +11:00
sinaioutlander
e7c5170232 3.0.5 2020-11-25 16:41:42 +11:00
sinaioutlander
be635e46a0 Swapping to INI instead of XML config, including an AssetBundle for old (5.6.1) Unity versions. 2020-11-25 16:40:36 +11:00
Sinai
687f56eac9
Update README.md 2020-11-23 21:16:29 +11:00
sinaioutlander
1dfcdb2dca Update build instructions, remove unnecessary references from CS project file 2020-11-23 20:28:22 +11:00
sinaioutlander
0025c83930 Fix a preprocessor directive 2020-11-23 20:17:54 +11:00
sinaioutlander
cfa4b12039 3.0.4
see release notes
2020-11-23 18:23:25 +11:00
sinaioutlander
c7ccdf387c update version 2020-11-22 18:23:07 +11:00
sinaioutlander
bb46d77a02 3.0.3
* Fixed not being able to set values on Enums
* [MONO] Fixed an issue where GameObjects in no scene (a Resource/Asset) would display nothing for their scene name, instead of "None (Resource/Asset)".
* Some UI layout cleanups and fixes, the Child/Component lists on the GameObject inspector should now expand to fill available height.
2020-11-22 18:22:57 +11:00
sinaioutlander
c38155ab04 Fix for InputSystem in 3.0.0 (temp fix for il2cpp) 2020-11-20 17:12:40 +11:00
sinaioutlander
97dbecaa2a Made instance inspector helper (owner gameobject/name), force loading unhollowed Assembly-CSharp on game start 2020-11-19 16:47:18 +11:00
sinaioutlander
e77e4cce07 fix release links 2020-11-19 01:41:11 +11:00
sinaioutlander
dcf0bdce48 disabling EventSystem.current patch for bepinex il2cpp as its causing a crash in some games 2020-11-19 00:55:17 +11:00
sinaioutlander
2a3df5de9d cleanup CacheMembers a bit 2020-11-17 23:26:22 +11:00
sinaioutlander
44ac4312e8 3.0.1: Update BepInEx build for 5.4.1, remove Test Class inspection on start, update libs, remove commented references 2020-11-17 19:46:54 +11:00
Sinai
3494b043bc
Changing from MIT to GPL 2020-11-17 18:09:21 +11:00
sinaioutlander
c552c4ac5b Update licensing info 2020-11-17 17:56:48 +11:00
sinaioutlander
4f88d216d9 move images 2020-11-17 17:08:11 +11:00
sinaioutlander
095ecd2aeb Create preview.png 2020-11-17 16:40:51 +11:00
sinaioutlander
5a766682a3 Update README.md 2020-11-17 04:29:23 +11:00
sinaioutlander
3963674cb2 Merge branch 'master' of https://github.com/sinai-dev/Explorer 2020-11-17 04:27:34 +11:00
Sinai
7b03554cd2
Update README.md 2020-11-17 04:27:00 +11:00
Sinai
43442587c5
Update README.md 2020-11-17 03:18:03 +11:00
sinaioutlander
2f32e29c04 Update overview.png 2020-11-17 03:11:29 +11:00
Sinai
f946f33d96
Update README.md 2020-11-17 03:08:29 +11:00
sinaioutlander
7ac905e1f4 Update overview.png 2020-11-17 03:07:10 +11:00
sinaioutlander
627a317308 Update README.md 2020-11-17 02:56:20 +11:00
Sinai
48e98a1d33
Merge pull request #22 from sinai-dev/3.0.0-rewrite
3.0.0 rewrite, see release for details
2020-11-17 02:53:13 +11:00
sinaioutlander
d379d6b129 InteracitveNumber update validation on potential type change 2020-11-17 02:51:20 +11:00
sinaioutlander
8e2e2abef4 finishing off interactive values 2020-11-17 02:05:45 +11:00
sinaioutlander
7920c54761 added InteractiveUnityStruct, thats the end of the interactive values for now 2020-11-17 00:52:15 +11:00
sinaioutlander
fd50996cb2 Merge remote-tracking branch 'origin/master' into 3.0.0-rewrite 2020-11-16 22:54:59 +11:00
sinaioutlander
5207b1a1c4 fix destroy logic with lists/dicts 2020-11-16 22:44:47 +11:00
sinaioutlander
91d5fc284f almost done, just interactive unity structs and a few minor things to finish off. 2020-11-16 21:21:04 +11:00
sinaioutlander
4a1125cf1d Fix SubContentWanted for InteractiveDictionary, remove redundant IValueTypes enum/dict 2020-11-16 01:32:58 +11:00
sinaioutlander
2e96d09f67 fix SubContentWanted logic for InteractiveEnumerable 2020-11-16 00:56:20 +11:00
sinaioutlander
8acc85061d InteractiveBool, Il2Cpp>Mono type dict cache, some UI fixes 2020-11-16 00:50:06 +11:00
sinaioutlander
41f0b0ed55 Implemented Interactive List/Dictionary support (todo IL2CPP) 2020-11-15 21:11:43 +11:00
sinaioutlander
02eca61f40 a couple minor fixes 2020-11-14 20:42:54 +11:00
sinaioutlander
2819ced303 Finished argument inputs for Method/Props, some UI cleanups and fixes 2020-11-14 19:51:16 +11:00
Sinai
755eae293e
Update ImageConversionUnstrip.cs 2020-11-14 02:49:14 +11:00
sinaioutlander
60580c8183 some UI cleanups 2020-11-14 00:46:26 +11:00
sinaioutlander
e9acd68ee4 fix Autocomplete buttons moving when you click them, rename Console namespace to CSConsole 2020-11-13 23:50:24 +11:00
sinaioutlander
7a4c7eb498 Fix vertices overflow on debug console, move UISyntaxHighlight 2020-11-13 23:37:04 +11:00
sinaioutlander
eb693eceb5 add AddListener helper for IL2CPP, cleanup some unity extensions 2020-11-13 23:14:57 +11:00
sinaioutlander
eedb7dd76f starting reflection inspector filters, some fixes 2020-11-13 21:39:25 +11:00
sinaioutlander
bc113e9093 A few important fixes
* Reflection on Il2CppSystem-namespace instances has been fixed
* Type/Value Syntax highlighting generalized and improved globally
* Scene changes now refresh the scene-picker dropdown
* probably other minor stuff too
2020-11-13 18:46:36 +11:00
sinaioutlander
dc449d4a1e DebugConsole save log on quit, some work on CacheObjects, fix missing-material issue on games without default UI Shader 2020-11-12 20:31:08 +11:00
Sinai
668c8f7c3f
Updated README for 3.0 (temp overview pic) 2020-11-12 16:30:41 +11:00
sinaioutlander
5afebc7d07 Update icon.png 2020-11-12 16:23:30 +11:00
Sinai
35b0e3808a
Update README.md 2020-11-12 16:20:26 +11:00
sinaioutlander
4b08cb55f5 Update icon.png 2020-11-12 16:16:55 +11:00
sinaioutlander
a7f86227fb various improvements to reflection inspector and C# console 2020-11-12 16:15:41 +11:00
Sinai
2077601464
Update README.md 2020-11-12 15:59:34 +11:00
Sinai
6a7596c40b
Update README.md 2020-11-12 15:58:28 +11:00
sinaioutlander
e4d38af4f5 Lots of fixes, everything basically done except Reflection Inspector 2020-11-11 20:16:43 +11:00
sinaioutlander
70a1570441 cleanup and refactor C# lexer classes 2020-11-11 00:16:01 +11:00
sinaioutlander
9c077b3aa3 Update ReflectionInspector.cs 2020-11-10 20:31:48 +11:00
sinaioutlander
ca90b64378 Revert a temporary attempt at fixing a crash 2020-11-10 20:30:22 +11:00
sinaioutlander
f87b06989d Removed TextMeshPro dependency, using only vanilla UI now. Also fixes for games which dont ship with Default UI Shader. 2020-11-10 20:18:14 +11:00
sinaioutlander
6766a8cf4c some early work on Reflection Inspector 2020-11-09 21:38:25 +11:00
sinaioutlander
5e761e2379 cleanup unstripping 2020-11-09 16:43:19 +11:00
sinaioutlander
3783638c89 Add TMP bundle, make Debug Console "Clear" reset message count 2020-11-08 22:53:18 +11:00
sinaioutlander
d038d13867 lots...
* Created a TMP AssetBundle for games which don't have the default TextMeshPro Resources package. This also allows us to use a custom monospace font for the Console and Debug window.
* Unstripped the AssetBundle class (just the stuff we need)
* Finished Search Page
* Finished Options Page (very simple)
* Various refactoring and restructuring of the project
* cleanups
2020-11-08 21:04:41 +11:00
sinaioutlander
2efc3f6578 Finish GameObject Inspector, start Search page, some other UI changes/fixes 2020-11-06 20:42:16 +11:00
sinaioutlander
e175e9c438 refactor 2020-11-05 17:33:04 +11:00
sinaioutlander
a46bc11e42 more progress, GameObject inspector almost done 2020-11-03 20:59:13 +11:00
sinaioutlander
b9b5d721c8 GameObject inspector taking shape 2020-11-02 20:48:53 +11:00
sinaioutlander
f4ba14cd13 2.1.0
* Fix a bug with Il2Cpp reflection causing TargetInvocationException and other weird issues.
2020-10-30 19:24:42 +11:00
sinaioutlander
b5b3e90b09 A little bit of work on Inspectors, fixed a few issues in Mono/BepInEx builds 2020-10-28 20:52:40 +11:00
sinaioutlander
4263cef26a Update ExplorerCore.cs 2020-10-28 20:49:53 +11:00
sinaioutlander
626e680510 2.0.9
* Fix an issue in mono builds causing a crash
* Fix for games which only contain one scene
* A few small cleanups
2020-10-28 20:49:18 +11:00
sinaioutlander
b61ac481b9 Fix null-coalescing operators in the C# console crashing the game 2020-10-28 07:14:00 +11:00
sinaioutlander
ff684d4d4b Finished scene explorer, lots of cleanups. Inspector and Search left now. 2020-10-28 06:39:26 +11:00
sinaioutlander
7328610252 a bit more scene page development, cleaned up console page a bit 2020-10-27 01:42:29 +11:00
sinaioutlander
fd950e2aef finished C# Console and Debug Console, starting work on Scene Explorer 2020-10-27 00:54:08 +11:00
sinaioutlander
2256828384 cleanup and refactor code editor 2020-10-26 01:07:59 +11:00
Sinai
32684bc63e
Update ColorUtilityUnstrip.cs 2020-10-25 21:28:58 +11:00
sinaioutlander
648ac941df developed new C# console
Derived heavily from notepad++ and Unity In-Game Code Editor, work will be done to refactor and strip down the code, most of it is unnecessary for our needs anyway. Temporary credit to IGCE for most of it.
2020-10-25 20:57:34 +11:00
sinaioutlander
0d4b4dc826 Debug console basically finished and working (using TMP now) 2020-10-24 20:18:42 +11:00
sinaioutlander
7c85969085 Update ExplorerCore.cs 2020-10-24 15:46:11 +11:00
sinaioutlander
1fce3465c2 Fix bug in ForceUnlockCursor, fix mistake in Reflection Inspector, reduced amount casting with Reflection Inspector 2020-10-24 15:45:37 +11:00
sinaioutlander
25747503cc Implemented PageHandler proof of concept, fixed something with scrollviews 2020-10-24 00:41:55 +11:00
sinaioutlander
76c578a9ea little bit more progress, creating main menu page structure 2020-10-23 20:40:44 +11:00
sinaioutlander
2da293ab21 A bit more progress, got a good framework for the UI going now. 2020-10-23 19:55:02 +11:00
sinaioutlander
88cbd0e970 cleaned up the resizer, fixed a mistake in UIFactory 2020-10-23 02:56:22 +11:00
sinaioutlander
a82abe2ec3 Update UIManager.cs 2020-10-23 01:53:19 +11:00
sinaioutlander
17ee92479c Update UIFactory.cs 2020-10-23 01:52:55 +11:00
sinaioutlander
508ca27ec2 some early steps remaking the GUI with UnityEngine.UI, working in all tested game so far 2020-10-23 01:50:33 +11:00
sinaioutlander
8949e3dc7d Revert "some early steps remaking the GUI with UnityEngine.UI, working in all tested game so far"
This reverts commit 4280a071f61ff0bdff713f7fb9970ee972af08a9.
2020-10-23 01:48:18 +11:00
sinaioutlander
4280a071f6 some early steps remaking the GUI with UnityEngine.UI, working in all tested game so far 2020-10-23 01:48:00 +11:00
sinaioutlander
48ed78ec36 A few small fixes 2020-10-22 21:00:33 +11:00
sinaioutlander
3c964cfef9 2.0.7
* More unstripping fixes. Explorer now works 100% on a blank Unity project (so should therefore work on any Unity game, regardless of stripping).
* Some cleanups
2020-10-18 21:41:04 +11:00
sinaioutlander
184b037523 Update ReflectionHelpers.cs 2020-10-18 04:46:50 +11:00
sinaioutlander
a49a918790 faster il2cpp cast, a few cleanups 2020-10-18 04:39:50 +11:00
Sinai
e3a58bf675
Update CacheMember.cs 2020-10-17 22:00:53 +11:00
Sinai
cc29dbda30
Update ReflectionInspector.cs 2020-10-16 20:20:36 +11:00
sinaioutlander
bc0ad5eab6 refactored icalls using icall helper 2020-10-16 19:40:01 +11:00
sinaioutlander
bdf86a7448 2.0.6 2020-10-14 20:55:44 +11:00
sinaioutlander
968546d43c 2.0.6
* Unstrip fixes and cleanups
2020-10-14 20:47:19 +11:00
sinaioutlander
680556d74e Update README.md 2020-10-12 20:23:21 +11:00
sinaioutlander
f490203b10 2.0.5
* Added Max Results option to Search (default 5000)
* Fixed a TypeInitializationException which can happen when inspecting some classes with Dictionary members
* Fixed an issue which could prevent Input support from initializating
* Improved and fixed the display of TextAsset objects
* A few other minor fixes
2020-10-12 20:15:41 +11:00
sinaioutlander
39d9585f1d 2.0.4
* Added ability to see and change the layer of a gameobject from the GameObject inspector more easily, and shows you the actual layer name (where possible).
* Fixed an issue related to the recently-added clickthrough prevention and resize drag
* Fixed write-only properties in the inspector
* A few other minor fixes
2020-10-11 22:57:46 +11:00
sinaioutlander
2d414e544b Update README.md 2020-10-11 20:52:08 +11:00
sinaioutlander
513fcaa534 Universal click-through prevention attempt 2020-10-11 20:49:14 +11:00
sinaioutlander
b41f7211e5 2.0.3
* Fixed a few issues related to the Texture2D support/export.
2020-10-11 20:07:23 +11:00
sinaioutlander
dd6cce1df1 2.0.2 2020-10-10 20:20:10 +11:00
sinaioutlander
ad54d2c76b 2.0.2
* Added support for viewing Texture2D (and Sprite) from the Inspector, and exporting them to PNG
* Fixed an issue with generic methods not showing their return value type
* Fixed an issue where destroyed UnityEngine.Objects would cause issues in the inspector
* Fixed an issue when caching a ValueCollection of a Dictionary (the generic argument for the Entry Type is the last arg, not the first as with other Enumerables)
2020-10-10 20:19:56 +11:00
sinaioutlander
867370ccee 2.0.1
* Added unstrip fix for GetRootSceneObjects using Il2CPP internal call
2020-10-09 21:11:15 +11:00
sinaioutlander
35eb78ca5d Update overview.png 2020-10-08 06:26:15 +11:00
sinaioutlander
f1c3771c24 2.0.0
lots, see release description
2020-10-08 06:15:42 +11:00
sinaioutlander
b012e2305c Cleanups 2020-10-07 16:20:34 +11:00
sinaioutlander
e309821743 Update README.md 2020-10-05 23:13:09 +11:00
sinaioutlander
56bedc9c6b Merging the two Mono builds, now just targets .NET 3.5 2020-10-05 23:08:59 +11:00
sinaioutlander
59c5b13a05 1.8.3.1 2020-10-05 20:25:51 +11:00
sinaioutlander
b8b6cc1605 1.8.0.1
* Added some internal caching for Enum Names, should vastly improve speed when inspecting certain classes (worst case scenario I found went from over 50 seconds to less than 1 second).
* ILRepack is now done as part of the build process, should simplify things if you are building the project yourself.
2020-10-05 20:25:25 +11:00
sinaioutlander
912b1b80ff using ILRepack MSBuild task, adding some base libs 2020-10-05 18:32:38 +11:00
sinaioutlander
6a9c64c2a1 Update README for new build process 2020-10-04 20:48:08 +11:00
sinaioutlander
54deecd312 Update README.md 2020-10-04 20:11:05 +11:00
sinaioutlander
403943a41f Update README.md 2020-10-04 20:09:45 +11:00
sinaioutlander
e7aa01ebc8 1.8.3
* Merging `mcs.dll` into the main `Explorer.dll` file, no longer needs to be in the Mods / Plugins folder.
2020-10-04 19:01:39 +11:00
sinaioutlander
bf6d526284 1.8.23
* Fixed an issue in Mono games when the target you are inspecting is destroyed (window would not close as it should).
* Cleaned up and refactored the Input support so it's easier to manage.
2020-10-03 20:19:44 +10:00
sinaioutlander
c991cb4b22 1.8.22
* Some performance improvements for the new InputSystem support (affects some 2019.3+ games)
* Fixed a small mistake with left/right mouse button checking.
2020-10-02 18:40:51 +10:00
sinaioutlander
3971e49ce1 Update README.md 2020-10-01 20:41:48 +10:00
sinaioutlander
6920ca1129 Update README.md 2020-10-01 20:26:25 +10:00
sinaioutlander
748e0cabcb 1.8.21
* Fixed a bug when editing a Text Field and the input string is `null`. Only affected Il2Cpp games, appeared in 1.8.0.
* Added a menu page for editing the Explorer Settings in-game, called `Options`.
* Added a new setting for default Items per Page Limit (for all "Pages" in Explorer).
2020-10-01 20:20:52 +10:00
sinaioutlander
b4b5f1ec93 1.8.2
* Added support for games which use the new InputSystem module and have disabled LegacyInputModule
2020-10-01 18:57:28 +10:00
Sinai
5afaf85859
Update README.md 2020-10-01 17:16:00 +10:00
sinaioutlander
b65e417ecb Update GUIUnstrip.cs 2020-09-30 01:59:35 +10:00
sinaioutlander
23723a4ffd Some more unstrip fixes, and a few cleanups 2020-09-30 01:52:49 +10:00
sinaioutlander
dab7ecd441 Cleanups and refactorings, and some small UI fixes 2020-09-29 05:40:06 +10:00
Sinai
f1406d016f
Update README.md 2020-09-28 16:19:23 +10:00
Sinai
99e801b3bd
Update README.md 2020-09-28 02:11:35 +10:00
Sinai
20133e123c
Update README.md 2020-09-28 02:04:03 +10:00
sinaioutlander
142a2a4750 Update README.md 2020-09-27 23:04:42 +10:00
sinaioutlander
629403a74d 1.8.0 cleanup 2020-09-27 22:52:08 +10:00
Sinai
873d0f277d
Update README.md 2020-09-27 22:15:54 +10:00
Sinai
99719fafaf
Update README.md 2020-09-27 22:07:30 +10:00
sinaioutlander
b550356f14 1.8.0, merging Mono and Il2Cpp builds, adding BepInEx support
* Project renamed to Explorer to reflect the new scope
* Merged Mono and Il2Cpp builds
* Merged BepInEx and MelonLoader builds
* Some minor changes to accommodate for this
* The release DLL and the config file now use "Explorer" in place of "CppExplorer" for file and folder names
2020-09-27 22:04:23 +10:00
sinaioutlander
8c6202c194 Allow for inherited flags attributes 2020-09-23 19:42:37 +10:00
sinaioutlander
f203ae37fc 1.7.5
* Added support for Enums with [Flags] attribute (can set each flag individually)
* Added support for easier bitwise operations on ints (or any primitive assignable to int), and viewing the int as binary. This is intended for things like `Camera.cullingMask`, etc.
* Fixed an issue with Enums that contain duplicate values, for example `CameraClearFlags` (has duplicate values for 2).
2020-09-23 19:19:29 +10:00
sinaioutlander
2006a9ea76 Faster non-generic Il2Cpp casting 2020-09-21 22:45:33 +10:00
sinaioutlander
c9bc450d09 Update README.md 2020-09-21 17:48:13 +10:00
Sinai
a1198f3a92
Update CacheColor.cs 2020-09-21 05:59:01 +10:00
sinaioutlander
04248a89ce Fix for cases when structs return null (due to null declaring instance) 2020-09-20 20:26:05 +10:00
sinaioutlander
3639824df3 Cleanup 2020-09-19 01:55:27 +10:00
sinaioutlander
939861b5f0 Cleanup 2020-09-19 01:44:38 +10:00
sinaioutlander
ad5fc04a3b Fix methods with multiple generic constraints 2020-09-19 01:27:33 +10:00
sinaioutlander
c39e097378 Add support for methods with ref/in/out args 2020-09-19 00:14:04 +10:00
sinaioutlander
129a7e3765 Improved interaction with generic methods and some minor UI fixes 2020-09-18 23:10:46 +10:00
sinaioutlander
643bb4519c Remove and sort usings 2020-09-18 18:38:11 +10:00
sinaioutlander
b154cbf39d Add support for generic methods, improved non-generic dictionary output 2020-09-18 18:03:17 +10:00
sinaioutlander
db91968519 Cleanup and improve syntax highlighting
* Static class members are now displayed in Italics and in a darker color, making them easier to distinguish.
* Cleaned up some issues related to syntax highlighting and refactored it into a global class.
* Methods and properties no longer display their arguments as part of the member name, they are only displayed when "Evaluate" is pressed.
2020-09-16 20:03:57 +10:00
sinaioutlander
5d58993b07 1.7.31
* Added support for Il2Cpp Hashtable (non-generic Dict)
* Dictionaries should now display CacheOther values better (smaller buttons)
* Cleaned up and improved some of CacheDictionary performance
2020-09-15 17:38:10 +10:00
sinaioutlander
eea581f8d5 Update ResizeDrag.cs 2020-09-14 20:27:49 +10:00
sinaioutlander
9bb3c77bae 1.7.3
* Reverted some unstrip fixes from 1.7.2 because it was causing more problems than it solved.
2020-09-14 20:25:38 +10:00
sinaioutlander
477a6859d7 Update README.md 2020-09-14 17:07:52 +10:00
sinaioutlander
f8f9671746 Update README.md 2020-09-14 16:56:42 +10:00
sinaioutlander
dc2759c599 1.7.2
unstrip fixes
2020-09-14 01:42:29 +10:00
sinaioutlander
653b4a2304 Fix BeginVertical and BeginHorizontal 2020-09-13 23:16:12 +10:00
sinaioutlander
065ab033c9 Fix crash when inspecting RigidBody2D objects 2020-09-13 17:39:15 +10:00
sinaioutlander
11cbd24a6a 1.7.1 2020-09-13 17:29:01 +10:00
sinaioutlander
fbf9859e0f Fix for GUILayout.BeginArea unstrip and UnityEngine.SystemClock unstrip
and remove some old comments
2020-09-13 17:11:15 +10:00
sinaioutlander
2d7dfa53eb Fix scroll not working in 2017 games 2020-09-12 16:14:42 +10:00
Sinai
eff8d63c81
Update README.md 2020-09-12 04:03:53 +10:00
sinaioutlander
006cf0fc2c Create icon.png 2020-09-12 04:03:30 +10:00
sinaioutlander
e5ca3530ff Merge branch 'master' of https://github.com/sinai-dev/CppExplorer 2020-09-12 04:01:18 +10:00
sinaioutlander
4de378907b Update GameObjectWindow.cs 2020-09-12 02:52:52 +10:00
Sinai
bbdfb46a1e
Update README.md 2020-09-12 02:35:41 +10:00
sinaioutlander
e6e2b3cd67 Update README.md 2020-09-12 02:30:34 +10:00
sinaioutlander
1d07046a74 Update README.md, hide Console when it fails to init 2020-09-12 02:20:27 +10:00
sinaioutlander
de663f34b2 1.7.0
* Fix for GuiLayout.Space unstrip
* Cleanups
2020-09-12 00:59:59 +10:00
sinaioutlander
8d648fec43 1.6.9
* Fix for games where patching Cursor methods fails.
* Added backup attempt for loading Cursor module if not present.
* HashSet collections are now supported by CacheList
* try/catch for loading Mod Config
2020-09-11 18:53:17 +10:00
sinaioutlander
835a81765e Add support for Hashset, add try/catch for loading settings 2020-09-11 00:17:13 +10:00
Sinai
51ed936e30
Revert PR changes 2020-09-10 22:40:23 +10:00
Sinai
ac16587cdc
Merge pull request #11 from PsymoNBond/master
Fixed Rect init
2020-09-10 22:38:16 +10:00
Tanami
1e1eaa6c38 Fixed Rect init 2020-09-10 14:16:25 +03:00
sinaioutlander
af17ae82c6 Update README.md 2020-09-10 20:47:13 +10:00
sinaioutlander
e23341c2b1 Update README.md 2020-09-10 20:36:24 +10:00
sinaioutlander
080bde4a63 Update README.md 2020-09-10 20:35:41 +10:00
sinaioutlander
1d739a1936 1.6.8
* Added a ModConfig, allowing you to define the main menu toggle keybind and the default window size (so far).
* Made the parsing of arguments more intelligent, should now behave as expected for null or empty arguments.
2020-09-10 20:31:09 +10:00
sinaioutlander
a927b5ed21 1.6.7
* Parameters (in Methods or Properties) with default values will now show these default values in the Inspector, and if you don't provide any input then this default value will be used as the argument.
* Removed an unnecessary update of cached members when you open a Reflection Inspector, should be a bit faster now.
* When entering arguments, the name of the argument is now white instead of cyan to avoid confusion with the Type name.
* A few clean ups
2020-09-10 18:02:41 +10:00
sinaioutlander
642c97812c fix img 2020-09-09 19:20:52 +10:00
sinaioutlander
e43d3579de Update img.png 2020-09-09 19:18:39 +10:00
sinaioutlander
6ea435deee 1.6.6
* Added better support for Properties with index parameters, can now support multiple parameters and non-int parameters.
* Parameters are now formatted in a more expected fashion (in the `(Type arg0, Type arg1)` format).
* Got rid of all the ugly yellow text.
* Cleaned up some minor GUI display / layout issues.
* Refactored some of CacheMethod into CacheObjectBase
2020-09-09 19:15:47 +10:00
sinaioutlander
94f749342d Update .gitignore 2020-09-09 00:53:31 +10:00
sinaioutlander
0769b7ef23 1.6.5
* Add expander to Unity struct inspectors, collapsed by default
* `UnityEngine.Color` labels in Reflection Inspector are now the same color as the value for convenience
* Cleaned up InputHelper
2020-09-08 23:47:17 +10:00
sinaioutlander
5086dcc82b Update README.md 2020-09-08 20:21:34 +10:00
sinaioutlander
56abd38e92 Add build instructions to Readme 2020-09-08 20:18:37 +10:00
sinaioutlander
a7e6ae87df Update README.md 2020-09-08 19:47:07 +10:00
sinaioutlander
b5c584bb02 Update README.md 2020-09-08 19:46:54 +10:00
sinaioutlander
c8a3aecdf4 Update README.md 2020-09-08 17:09:23 +10:00
sinaioutlander
33c2378f41 Update README.md 2020-09-08 17:09:12 +10:00
sinaioutlander
38aafa7e5b 1.6.4
* Fix for games which do not load InputModule on startup. CppExplorer will now try to load the module itself.
* Cleanups
2020-09-08 17:07:10 +10:00
sinaioutlander
4bb0811b2c 1.6.3
* Merged the two builds into one, there is now only one release. Using Reflection for UnityEngine.Input
* A few small fixes and cleanups
2020-09-08 06:21:45 +10:00
sinaioutlander
4aefe1c5a3 a few tidy ups 2020-09-08 04:33:27 +10:00
sinaioutlander
c228d29707 Update CppExplorer.cs 2020-09-07 20:28:43 +10:00
sinaioutlander
56d1507aff 1.6.2
* Fix for a crash that can occur when inspecting unsupported Dictionaries
* Added a scroll bar to the REPL console input area, fixes the issue of the code just being cut off when it goes too long.
2020-09-07 20:28:33 +10:00
sinaioutlander
72d31eaa64 1.6.1
* Fix for when inspected object gets destroyed
* Fix for displaying Dictionaries/Lists nested inside a Dictionary
* Cleanups
2020-09-07 17:05:37 +10:00
sinaioutlander
4e8b84b67e Update CppExplorer.cs 2020-09-07 03:26:10 +10:00
sinaioutlander
5b94e31a12 1.6.0
* Fix for failed unstrip with RectOffset(int, int, int, int) ctor
* Cleanups
2020-09-07 03:25:43 +10:00
sinaioutlander
692a37635e 1.5.9
* Added beta support for Dictionaries. Should work fine for simple dictionaries, may be janky or broken for more complex ones (eg. Dicts nested inside a Dict).
* Fixed a bug with Lists of primitive values.
2020-09-06 21:33:09 +10:00
sinaioutlander
9cb1cea025 Update README.md 2020-09-06 17:48:40 +10:00
sinaioutlander
e13f198815 1.5.8
* Fixed a bug where the Page Helper would not update the total page count after changing the limit per page
* Cleaned up the "Find Instances" helper, it will now filter out all types in the `System`, `Mono`, `Il2CppSystem` and `Iced` namespaces.
* Improved the Find Instances helper so that it will avoid exceptions and get more results.
* Enums now display their value type name
* Changed the Scroll View unstrip so that it is less hard-coded for different unity versions and more dynamic.
2020-09-06 16:55:39 +10:00
sinaioutlander
9a059c1056 Update ScenePage.cs 2020-09-06 03:19:39 +10:00
sinaioutlander
ffb6cad8c2 1.5.7
* More fixes for failed unstripping, should fix most issues in Audica and other games
* If `GetRootSceneObjects` fails and we fall back to the manual implementation, the auto-update for root scene objects will be disabled. Instead, there will be a button to press to update the list.
* Transforms are now listed on the Components list in the GameObject inspector
* Various cleanups
2020-09-06 03:19:21 +10:00
sinaioutlander
d0a4863139 Update ScenePage.cs 2020-09-05 23:18:58 +10:00
sinaioutlander
bb8837d58c 1.5.6 hotfix
* Fix for setting CacheColor value
* Cleanup
2020-09-05 23:10:50 +10:00
sinaioutlander
a236b272c1 Update README.md 2020-09-05 20:41:48 +10:00
sinaioutlander
18de1eaf1c 1.5.6
Cleanup
2020-09-05 20:38:46 +10:00
sinaioutlander
b1264c6912 1.5.6
* Added a fallback method for GetRootSceneObjects for games where this fails.
* Fixed an issue where the `new Rect(Rect source)` constructor was failing in some games, using the normal ctor now.
* Added special support for `Vector2`, `Vector3`, `Vector4`, `Quaternion`, `Color` and `Rect` structs in the reflection inspector to allow for easier editing.
* Several improvements to GameObject Inspector, such as position/rotation freezing, local/global context, and an improved way to edit the transform values.
2020-09-05 20:27:00 +10:00
sinaioutlander
9836566e55 tidy up 2020-09-05 01:30:50 +10:00
sinaioutlander
d20461fa0e 1.5.5
* Fix for GetRootSceneObjects
* Tidy ups
2020-09-04 23:49:43 +10:00
sinaioutlander
72ec34090d 1.5.4 cleanup 2020-09-04 21:51:38 +10:00
sinaioutlander
883a8705c3 Update README.md 2020-09-04 21:42:09 +10:00
sinaioutlander
6adaaf5500 1.5.4
* Implemented manual unstripping for ScrollView and Resize, should now work on any Unity 2018 or 2019 game.
* Fixed a bug with page view on the Scene Explorer
* Back-end cleanups
2020-09-04 21:36:40 +10:00
sinaioutlander
5de771389e 1.5.3
* Added exception handling for scrollview when unstripping fails
* Added some better logging in some places
2020-09-04 01:27:44 +10:00
sinaioutlander
51cfbe524e Update README.md 2020-09-03 20:59:54 +10:00
sinaioutlander
217b93ef4f 1.5.2
* Added ability to force Reflection Inspector for GameObjects and Transforms if you hold Left Shift while clicking the Inspect button
* Fixed a bug causing duplicate windows to open when you inspect Transforms, the current active window will now be focused. Note: does not apply if you hold Left Shift for forced reflection.
2020-09-03 20:58:04 +10:00
sinaioutlander
42156e1160 1.5.2
* Added page view to GameObject Children/Component lists
* Made a generic Page Handler helper class, replaced all page view implementations with the helper (no real change for users but should make things easier to maintain in the future, and they were basically all copy+pastes).
2020-09-03 19:48:50 +10:00
sinaioutlander
e7208d0c9d 1.5.1 2020-09-01 18:04:38 +10:00
sinaioutlander
2f3b779199 1.5.1
* Added support for Properties with an index parameter on the Reflection Window (ie. "this[index]")
* Fixed a crash that occured when inspecting Il2CppSystem.Type objects
* Back-end cleanups
2020-09-01 18:03:44 +10:00
sinaioutlander
916bdea59b 1.5.0 2020-08-31 23:28:44 +10:00
sinaioutlander
d8688193d5 1.4.7
* Added support for Il2Cpp IList objects
* Improved support for Lists in general, they should now work better.
2020-08-31 18:23:19 +10:00
sinaioutlander
30b48b1f1f 1.4.6
* Fix a bug with the Scene Explorer Search feature (not Object search)
* Simplified parsing of primitive values to a better method
2020-08-31 16:27:14 +10:00
sinaioutlander
0fd382c1f6 1.4.5 finalize and release 2020-08-30 23:29:37 +10:00
sinaioutlander
fd20a1120b Merge branch 'master' of https://github.com/sinai-dev/CppExplorer 2020-08-30 17:32:28 +10:00
sinaioutlander
abcb548706 1.4.5 finalize
Will be pushed when MelonLoader releases 0.2.7.
2020-08-30 17:32:25 +10:00
Sinai
b056644385
Update CacheMethod.cs 2020-08-30 16:55:14 +10:00
Sinai
71f72e8f36
Update README.md 2020-08-30 16:51:03 +10:00
sinaioutlander
1ab41f5a30 Update README.md 2020-08-30 16:49:44 +10:00
sinaioutlander
7dc58ea02c 1.4.5 (pre-release)
* Added support for MethodInfos with only primitive arguments on reflection window
* Added backup resize mode incase resizing experiences an exception
2020-08-30 07:01:13 +10:00
sinaioutlander
68eeee353e 1.4.5 (pre-release) - Implement Tab View
* Implemented Tab View
2020-08-30 01:08:48 +10:00
sinaioutlander
92fe1dc704 1.4.5 (pre-release)
* Added MethodInfo support for basic methods with no arguments.
* Added support for missing primitive types (char, short, byte)
* Added CacheDictionary class (currently unsupported)
* Cleaned up some stuff, using System.Reflection.MemberType instead of a custom enum.
2020-08-29 21:15:54 +10:00
sinaioutlander
6e644b4f50 1.4.5 (pre-release)
* Windows now display the gameobject name or the object type in the header
* Added "Set DontDestroyOnLoad" button to Gameobject controls.
* Added dynamic input field size and more intelligent auto-wrap for primitive values
* Resize Drag will now disable itself on Exceptions, and log the error (affects VRChat)
* Various misc UI improvements
* Various small fixes
2020-08-28 00:45:34 +10:00
sinaioutlander
c47974115b WindowManager.cs, restore 2 lines accidentally deleted 2020-08-27 20:15:38 +10:00
sinaioutlander
535e88be9a 1.4.5 (pre-release)
* Pre-release. Will be released once MelonLoader bumps to Unhollower 0.4.9.0
* Added global "Force Unlock Mouse" option, should work on almost all games. Has smart behaviour and will maintain the previous value (or the value which should be set).
* Improve performacne of CacheList casting List ->IEnumerable
* Fix a bug causing some Components to not show the GameObject button in the Reflection Window (top-right corner).
* Fix a bug making the Window Manager think that two of the same Il2Cpp Object are not ReferenceEquals.
* Added logging when C# Console fails to compile anything
* Improve display of Reflection Window member name label, now expands with window resize.
2020-08-27 18:05:55 +10:00
Sinai
e567c16221
Update README.md 2020-08-24 01:53:59 +10:00
Sinai
d13af7548e
Update README.md 2020-08-24 01:52:19 +10:00
Sinai
5d750aec77
Update README.md 2020-08-24 01:50:03 +10:00
sinaioutlander
45b5ce0ef8 1.4.2
* Fixed a bug on the Reflection window which would prevent primitive values from being applied
* Improved some parts of the Scene Explorer and the Reflection Window interfaces
* Scene Explorer now has "page view" like other lists
* Various minor cleanups and refactorings
2020-08-24 01:42:19 +10:00
Sinai
e3d1add090
Update README.md 2020-08-23 03:00:19 +10:00
Sinai
a59bcc95e4
Update README.md 2020-08-23 03:00:12 +10:00
Sinai
ac4414ca86
Update README.md 2020-08-23 02:50:59 +10:00
sinaioutlander
19263092fe Update CacheObject.cs 2020-08-22 19:36:06 +10:00
sinaioutlander
6bafab785b 1.4.1
* Cleanup some small bugs introduced in 1.4.0
* Added better exception handling for failed Reflection, and the ability to hide failed reflection members in the Reflection window, as well as see the error type.
* Reflection window members now display the full name instead of just the member name (eg. "Camera.main" instead of just "main").
2020-08-22 17:17:11 +10:00
Sinai
62b1688d53
Update README.md 2020-08-22 01:42:29 +10:00
Sinai
4d015cbe93
Update README.md 2020-08-22 01:08:09 +10:00
Sinai
0da8f4faea
Update README.md 2020-08-22 01:02:04 +10:00
sinaioutlander
b264151c46 1.4.0
- Wrote the CacheObject class to replace MemberInfoHolder, resulting code is better perfomance and much easier to read.
- Added pages to Object Reflection window, now limited to 20 members per page to improve performance further.
2020-08-22 00:16:05 +10:00
Sinai
3d2bc7cd4b
Update README.md 2020-08-20 18:59:59 +10:00
Sinai
85c26e6af7
Update README.md 2020-08-20 18:56:07 +10:00
Sinai
b149efa234
Update README.md 2020-08-20 18:53:56 +10:00
sinaioutlander
72c222d59a 1.3.5
- Project structure cleanup
- Code refactoring
- Adding some extension methods for cleaner looking code
- Performance improvements on Object Reflection window
2020-08-18 17:38:09 +10:00
sinaioutlander
153ad2268b Cleanup project structure
Restructured the project somewhat and cleaned up classes so that things are where they belong. Created "Helpers" folder and put appropriate helper classes in there.

Important things:
- The "GameObject path" methods are now extension methods on UnityEngine.Transform
- Removed AccessTools (Reflection helpers) as there was no use of it. Replaced with ReflectionHelpers class.
- Some improvements to the "Object Reflection" window, should be a bit faster now. Code cleaned up significantly.
2020-08-18 17:11:58 +10:00
Sinai
1ba9b2eae1
Update README.md 2020-08-15 16:08:56 +10:00
Sinai
be2da96cc0
Update README.md 2020-08-15 16:07:20 +10:00
Sinai
a2405d69c5
Update README.md 2020-08-14 17:51:09 +10:00
sinaioutlander
b2a90c832f 1.3.3
Fix scene change buttons not actually working properly.
2020-08-14 16:19:39 +10:00
Sinai
9a784fd467
Update README.md 2020-08-13 23:42:31 +10:00
sinaioutlander
d399b6acd1 Merging the two projects into one with build configurations
Removed the "src_2018" project, since it's now 1:1 with the main project and the only difference is references. Now using build configurations and preprocessor directives to accomplish the same thing.
2020-08-13 23:34:21 +10:00
sinaioutlander
0c3067973e 1.3.2 cleanup
- cleanup
- fixed a mistake with FieldInfos on reflection window, causing all values to be null.
- improved displaying of generic objects (now shows object Type after the name)
2020-08-13 18:43:34 +10:00
sinaioutlander
411593590d 1.3.2
- Fixed the Scene Filters on the search page, it was not functionally correctly at all.
- Fixed GameObjects and Components being displayed as basic objects on search view (they now open to GameObject inspector like they should).
2020-08-13 17:00:53 +10:00
sinaioutlander
a2677e2321 1.3.1
- Added ability to cycle through "pages" with lists/arrays and with search results. Also reduced default array display limit to 20 elements, since we can now just cycle through pages.
- Some backend restructuring / cleanups
2020-08-13 00:06:39 +10:00
209 changed files with 19658 additions and 6956 deletions

3
.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1,3 @@
# These are supported funding model platforms
ko_fi: sinaidev

60
.github/ISSUE_TEMPLATE/bug_report.yaml vendored Normal file
View File

@ -0,0 +1,60 @@
name: Bug Report
description: File a bug or crash report
title: "[Bug]: "
labels: [bug]
body:
- type: markdown
attributes:
value: |
Thanks for submitting a bug report, please fill out as much detail as possible.
- type: checkboxes
id: latestversion
attributes:
label: Are you on the latest version of UnityExplorer?
description: If not, you must update first.
options:
- label: Yes, I'm on the latest version of UnityExplorer.
required: true
- type: dropdown
id: version
attributes:
label: Which release are you using?
description: Please select your environment for UnityExplorer.
options:
- BepInEx IL2CPP
- BepInEx 6.X Mono
- BepInEx 5.X Mono
- MelonLoader IL2CPP
- MelonLoader Mono
- Standalone IL2CPP
- Standalone Mono
validations:
required: true
- type: textarea
id: game
attributes:
label: Which game did this occur on?
description: Please tell us the name of the game. If it's a personal or private project, just let us know the Unity version.
validations:
required: true
- type: textarea
id: what-happened
attributes:
label: Describe the issue.
description: What happened? Should something else have happened instead? Please provide steps to reproduce the issue if possible.
placeholder: Tell us what you see!
validations:
required: true
- type: textarea
id: logs
attributes:
label: Relevant log output
description: |
Please copy and paste any relevant logs and stack traces.
* Unity log: `%userprofile%\AppData\LocalLow\{Company}\{Game}\Player.log` or `output_log.txt`
* BepInEx: `BepInEx\LogOutput.log`
* MelonLoader: `MelonLoader\latest.log`
* Standalone: `{DLL_Location}\UnityExplorer\Logs\` (pick the most recent one)
render: shell
validations:
required: false

1
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@ -0,0 +1 @@
blank_issues_enabled: false

18
.github/ISSUE_TEMPLATE/enhancement.yaml vendored Normal file
View File

@ -0,0 +1,18 @@
name: New feature or enhancement
description: Suggest or discuss a feature or enhancement for UnityExplorer
title: "[Enhancement]: "
labels: [enhancement]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to discuss UnityExplorer, please provide as much detail as possible.
- type: textarea
id: description
attributes:
label: Describe the new feature or enhancement
description: |
Please go into as much detail as necessary in describing the new feature or enhancement.
If providing examples or suggestions for the required C# code, please use syntax-highlighted code blocks.
validations:
required: true

13
.github/ISSUE_TEMPLATE/other.yaml vendored Normal file
View File

@ -0,0 +1,13 @@
name: Other
description: Something else?
title: "[Other]: "
labels: [Other]
body:
- type: textarea
id: description
attributes:
label: Describe the issue
description: |
Please describe the issue in as much detail as possible.
validations:
required: true

92
.github/workflows/dotnet.yml vendored Normal file
View File

@ -0,0 +1,92 @@
name: Build UnityExplorer
# Controls when the action will run.
on:
push:
branches: [master]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
jobs:
build:
runs-on: windows-latest
if: "!contains(github.event.head_commit.message, '-noci')"
steps:
# Setup
- name: Checkout latest
uses: actions/checkout@v2
- name: Setup dotnet
uses: actions/setup-dotnet@v2
with:
dotnet-version: '6.0.x'
include-prerelease: true
# Run build script
- run: |
./build.ps1
# Upload artifacts
# BepInEx IL2CPP
- uses: actions/upload-artifact@v2
with:
name: UnityExplorer.BepInEx.IL2CPP.zip
path: ./Release/UnityExplorer.BepInEx.IL2CPP/
# BepInEx IL2CPP CoreCLR
- uses: actions/upload-artifact@v2
with:
name: UnityExplorer.BepInEx.IL2CPP.CoreCLR.zip
path: ./Release/UnityExplorer.BepInEx.IL2CPP.CoreCLR/
# BepInEx 5 Mono
- uses: actions/upload-artifact@v2
with:
name: UnityExplorer.BepInEx5.Mono.zip
path: ./Release/UnityExplorer.BepInEx5.Mono/
# BepInEx 6 Mono
- uses: actions/upload-artifact@v2
with:
name: UnityExplorer.BepInEx6.Mono.zip
path: ./Release/UnityExplorer.BepInEx6.Mono/
# Editor
- uses: actions/upload-artifact@v2
with:
name: UnityExplorer.Editor.zip
path: ./UnityEditorPackage/
# MelonLoader IL2CPP net6preview
- uses: actions/upload-artifact@v2
with:
name: UnityExplorer.MelonLoader.IL2CPP.net6preview.zip
path: ./Release/UnityExplorer.MelonLoader.IL2CPP.net6preview/
# MelonLoader IL2CPP net472
- uses: actions/upload-artifact@v2
with:
name: UnityExplorer.MelonLoader.IL2CPP.zip
path: ./Release/UnityExplorer.MelonLoader.IL2CPP/
# MelonLoader Mono
- uses: actions/upload-artifact@v2
with:
name: UnityExplorer.MelonLoader.Mono.zip
path: ./Release/UnityExplorer.MelonLoader.Mono/
# Standalone Il2Cpp
- uses: actions/upload-artifact@v2
with:
name: UnityExplorer.Standalone.IL2CPP.zip
path: ./Release/UnityExplorer.Standalone.IL2CPP/
# Standalone Mono
- uses: actions/upload-artifact@v2
with:
name: UnityExplorer.Standalone.Mono.zip
path: ./Release/UnityExplorer.Standalone.Mono/

687
LICENSE
View File

@ -1,21 +1,674 @@
MIT License
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (c) 2020 sinaioutlander
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
Preamble
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.

195
README.md
View File

@ -1,51 +1,184 @@
# CppExplorer
<p align="center">
<img align="center" src="img/icon.png">
</p>
[![Version](https://img.shields.io/badge/MelonLoader-0.2.6-green.svg)]()
<p align="center">
🔍 An in-game UI for exploring, debugging and modifying Unity games.
</p>
<p align="center">
✔️ Supports most Unity versions from 5.2 to 2021+ (IL2CPP and Mono).
</p>
<p align="center">
✨ Powered by <a href="https://github.com/sinai-dev/UniverseLib">UniverseLib</a>
</p>
An in-game explorer and a suite of debugging tools for [IL2CPP](https://docs.unity3d.com/Manual/IL2CPP.html) Unity games, using [MelonLoader](https://github.com/HerpDerpinstine/MelonLoader).
# Releases [![](https://img.shields.io/github/downloads/sinai-dev/UnityExplorer/total.svg)](../../releases)
This was designed to be an IL2CPP-compatible equivalent to [Runtime Unity Editor](https://github.com/ManlyMarco/RuntimeUnityEditor).
[![](https://img.shields.io/github/release/sinai-dev/UnityExplorer.svg?label=version)](../../releases/latest) [![](https://img.shields.io/github/workflow/status/sinai-dev/UnityExplorer/Build%20UnityExplorer)](https://github.com/sinai-dev/UnityExplorer/actions) [![](https://img.shields.io/github/downloads/sinai-dev/UnityExplorer/latest/total.svg)](../../releases/latest)
## Features
* Scene hierarchy explorer
* Search loaded assets with filters
* Traverse and manipulate GameObjects
* Generic Reflection inspector
* REPL Console
* Inspect-under-mouse
⚡ Thunderstore releases: [BepInEx Mono](https://thunderstore.io/package/sinai-dev/UnityExplorer) | [BepInEx IL2CPP](https://gtfo.thunderstore.io/package/sinai-dev/UnityExplorer_IL2CPP) | [MelonLoader IL2CPP](https://boneworks.thunderstore.io/package/sinai-dev/UnityExplorer_IL2CPP_ML)
## How to install
## Release schedule
Requires [MelonLoader](https://github.com/HerpDerpinstine/MelonLoader) to be installed for your game.
Releases will be posted at most once per week, generally on weekends.
1. Download <b>CppExplorer.zip</b> from [Releases](https://github.com/sinaioutlander/CppExplorer/releases).
2. Unzip the file into the `Mods` folder in your game's installation directory, created by MelonLoader.
3. Make sure it's not in a sub-folder, `CppExplorer.dll` and `mcs.dll` should be directly in the `Mods\` folder.
Nightly builds can be found [here](https://github.com/sinai-dev/UnityExplorer/actions).
## How to use
## BepInEx
* Press F7 to show or hide the menu.
* Simply browse through the scene, search for objects, etc, it's pretty self-explanatory.
| Release | IL2CPP | Mono |
| ------- | ------ | ---- |
| BIE 6.X | ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.BepInEx.IL2CPP.zip) | ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.BepInEx6.Mono.zip) |
| BIE 6.X (CoreCLR) | ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.BepInEx.IL2CPP.CoreCLR.zip) | ✖ |
| BIE 5.X | ✖️ n/a | ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.BepInEx5.Mono.zip) |
## Images
1. Unzip the release file into a folder
2. Take the `plugins/sinai-dev-UnityExplorer` folder and place it in `BepInEx/plugins/`
Scene explorer, and inspection of a MonoBehaviour object:
<i>Note: BepInEx 6 is obtainable via [builds.bepinex.dev](https://builds.bepinex.dev/projects/bepinex_be)</i>
[![](https://i.imgur.com/Yxizwcz.png)](https://i.imgur.com/Yxizwcz.png)
## MelonLoader
Search feature:
| Release | IL2CPP | Mono |
| ------- | ------ | ---- |
| ML 0.5 | ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.MelonLoader.IL2CPP.zip) | ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.MelonLoader.Mono.zip) |
| ML 0.6 | ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.MelonLoader.IL2CPP.net6preview.zip) | ✖️ |
[![](https://i.imgur.com/F9ZfMvz.png)](https://i.imgur.com/F9ZfMvz.png)
1. Unzip the release file into a folder
2. Copy the DLL inside the `Mods` folder into your MelonLoader `Mods` folder
3. Copy all of the DLLs inside the `UserLibs` folder into your MelonLoader `UserLibs` folder
## Standalone
REPL console:
| IL2CPP | Mono |
| ------ | ---- |
| ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.Standalone.IL2CPP.zip) | ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.Standalone.Mono.zip) |
[![](https://i.imgur.com/14Dbtf8.png)](https://i.imgur.com/14Dbtf8.png)
The standalone release can be used with any injector or loader of your choice, but it requires you to load the dependencies manually.
## Credits
1. Ensure the required libs are loaded - UniverseLib, HarmonyX and MonoMod. Take them from the [`UnityExplorer.Editor`](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.Editor.zip) release if you need them.
2. For IL2CPP, load Il2CppAssemblyUnhollower and start an [Il2CppAssemblyUnhollower runtime](https://github.com/knah/Il2CppAssemblyUnhollower#required-external-setup)
2. Load the UnityExplorer DLL
3. Create an instance of Unity Explorer with `UnityExplorer.ExplorerStandalone.CreateInstance();`
4. Optionally subscribe to the `ExplorerStandalone.OnLog` event to handle logging if you wish
Written by Sinai.
## Unity Editor
Thanks to:
* [ManlyMarco](https://github.com/ManlyMarco) for their [Runtime Unity Editor](https://github.com/ManlyMarco/RuntimeUnityEditor), which I used for the REPL Console and the "Find instances" snippet, and the UI style.
* [denikson](https://github.com/denikson) for [mcs-unity](https://github.com/denikson/mcs-unity). I commented out the `SkipVisibilityExt` constructor in `mcs.dll` since it was causing an exception with the Hook it attempted.
1. Download the [`UnityExplorer.Editor`](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.Editor.zip) release.
2. Install the package, either by using the Package Manager and importing the `package.json` file, or by manually dragging the folder into your `Assets` folder.
3. Drag the `Runtime/UnityExplorer` prefab into your scene, or create a GameObject and add the `Explorer Editor Behaviour` script to it.
# Common issues and solutions
Although UnityExplorer should work out of the box for most Unity games, in some cases you may need to tweak the settings for it to work properly.
To adjust the settings, open the config file:
* BepInEx: `BepInEx\config\com.sinai.unityexplorer.cfg`
* MelonLoader: `UserData\MelonPreferences.cfg`
* Standalone: `sinai-dev-UnityExplorer\config.cfg`
Try adjusting the following settings and see if it fixes your issues:
* `Startup_Delay_Time` - increase to 5-10 seconds (or more as needed), can fix issues with UnityExplorer being destroyed or corrupted during startup.
* `Disable_EventSystem_Override` - if input is not working properly, try setting this to `true`.
If these fixes do not work, please create an issue in this repo and I'll do my best to look into it.
# Features
<p align="center">
<a href="https://raw.githubusercontent.com/sinai-dev/UnityExplorer/master/img/preview.png">
<img src="img/preview.png" />
</a>
</p>
### Inspector API
If you want to inspect an object or Type from outside the C# console, use the `InspectorManager` class:
**To inspect an object:**
```csharp
UnityExplorer.InspectorManager.Inspect(theObject);
```
**To inspect a Type:**
```cs
UnityExplorer.InspectorManager.Inspect(typeof(SomeClass));
```
### Object Explorer
* Use the <b>Scene Explorer</b> tab to traverse the active scenes, as well as the DontDestroyOnLoad and HideAndDontSave objects.
* The "HideAndDontSave" scene contains objects with that flag, as well as Assets and Resources which are not in any scene but behave the same way.
* You can use the Scene Loader to easily load any of the scenes in the build (may not work for Unity 5.X games)
* Use the <b>Object Search</b> tab to search for Unity objects (including GameObjects, Components, etc), C# Singletons or Static Classes.
* Use the UnityObject search to look for any objects which derive from `UnityEngine.Object`, with optional filters
* The singleton search will look for any classes with a typical "Instance" field, and check it for a current value. This may cause unexpected behaviour in some IL2CPP games as we cannot distinguish between true properties and field-properties, so some property accessors will be invoked.
### Inspector
The inspector is used to see detailed information on objects of any type and manipulate their values, as well as to inspect C# Classes with static reflection.
* The <b>GameObject Inspector</b> (tab prefix `[G]`) is used to inspect a `GameObject`, and to see and manipulate its Transform and Components.
* You can edit any of the input fields in the inspector (excluding readonly fields) and press <b>Enter</b> to apply your changes. You can also do this to the GameObject path as a way to change the GameObject's parent. Press the <b>Escape</b> key to cancel your edits.
* <i>note: When inspecting a GameObject with a Canvas, the transform controls may be overridden by the RectTransform anchors.</i>
* The <b>Reflection Inspectors</b> (tab prefix `[R]` and `[S]`) are used for everything else
* Automatic updating is not enabled by default, and you must press Apply for any changes you make to take effect.
* Press the `▼` button to expand certain values such as strings, enums, lists, dictionaries, some structs, etc
* Use the filters at the top to quickly find the members you are looking for
* For `Texture2D`, `Image`, `Sprite` and `Material` objects, there is a `View Texture` button at the top of the inspector which lets you view the Texture(s) and save them as a PNG file.
* For `AudioClip` objects there is a `Show Player` button which opens an audio player widget. For clips which are loaded as `DecompressOnLoad`, there is also a button to save them to a `.wav` file.
### C# Console
* The C# Console uses the `Mono.CSharp.Evaluator` to define temporary classes or run immediate REPL code.
* You can execute a script automatically on startup by naming it `startup.cs` and placing it in the `sinai-dev-UnityExplorer\Scripts\` folder (this folder will be created where you placed the DLL file).
* See the "Help" dropdown in the C# console menu for more detailed information.
### Hook Manager
* The Hooks panel allows you to hook methods at the click of a button for debugging purposes.
* Simply enter any class and hook the methods you want from the menu.
* You can edit the source code of the generated hook with the "Edit Hook Source" button. Accepted method names are `Prefix` (which can return `bool` or `void`), `Postfix`, `Finalizer` (which can return `Exception` or `void`), and `Transpiler` (which must return `IEnumerable<HarmonyLib.CodeInstruction>`). You can define multiple patches if you wish.
### Mouse-Inspect
* The "Mouse Inspect" dropdown in the "Inspector" panel allows you to inspect objects under the mouse.
* <b>World</b>: uses Physics.Raycast to look for Colliders
* <b>UI</b>: uses GraphicRaycasters to find UI objects
### Freecam
* UnityExplorer provides a basic Free Camera which you can control with your keyboard and mouse.
* Unlike all other features of UnityExplorer, you can still use Freecam while UnityExplorer's menu is hidden.
* Supports using the game's main Camera or a separate custom Camera.
* See the Freecam panel for further instructions and details.
### Clipboard
* The "Clipboard" panel allows you to see your current paste value, or clear it (resets it to `null`)
* Can copy the value from any member in a Reflection Inspector, Enumerable or Dictionary, and from the target of any Inspector tab
* Can paste values onto any member in a Reflection Inspector
* Non-parsable arguments in Method/Property Evaluators allow pasting values
* The C# Console has helper methods `Copy(obj)` and `Paste()` for accessing the Clipboard
### Settings
* You can change the settings via the "Options" tab of the menu, or directly from the config file.
* BepInEx: `BepInEx\config\com.sinai.unityexplorer.cfg`
* MelonLoader: `UserData\MelonPreferences.cfg`
* Standalone `{DLL_location}\sinai-dev-UnityExplorer\config.cfg`
# Building
1. Run the `build.ps1` powershell script to build UnityExplorer. Releases are found in the `Release` folder.
Building individual configurations from your IDE is fine, though note that the intial build process builds into `Release/<version>/...` instead of the subfolders that the powershell script uses. Batch building is not currently supported with the project.
# Acknowledgments
* [ManlyMarco](https://github.com/ManlyMarco) for [Runtime Unity Editor](https://github.com/ManlyMarco/RuntimeUnityEditor) \[[license](THIRDPARTY_LICENSES.md#runtimeunityeditor-license)\], the ScriptEvaluator from RUE's REPL console was used as the base for UnityExplorer's C# console.
* [Geoffrey Horsington](https://github.com/ghorsington) for [mcs-unity](https://github.com/sinai-dev/mcs-unity) \[no license\], used as the `Mono.CSharp` reference for the C# Console.
### Disclaimer
UnityExplorer is in no way associated with Unity Technologies. "Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere.

874
THIRDPARTY_LICENSES.md Normal file
View File

@ -0,0 +1,874 @@
* [RuntimeUnityEditor License](#runtimeunityeditor-license)
* [MelonLoader License](#melonloader-license)
## RuntimeUnityEditor License
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.
## MelonLoader License
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
Copyright 2020 - 2021 Lava Gang
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -0,0 +1,674 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.

View File

@ -0,0 +1,74 @@
# UnityExplorer
🔍 An in-game UI for exploring, debugging and modifying Unity games.
✔️ Supports most Unity versions from 5.2 to 2021+ (IL2CPP and Mono).
✨ Powered by [UniverseLib](https://github.com/sinai-dev/UniverseLib)
# Setup
* Install this package, either by using the Package Manager and importing the `package.json` file, or by manually dragging this folder into your Assets folder.
* Drag the `Runtime/UnityExplorer` prefab into your scene, or create a GameObject and add the `Explorer Editor Behaviour` script to it.
# Features
### Object Explorer
* Use the <b>Scene Explorer</b> tab to traverse the active scenes, as well as the DontDestroyOnLoad and HideAndDontSave objects.
* The "HideAndDontSave" scene contains objects with that flag, as well as Assets and Resources which are not in any scene but behave the same way.
* You can use the Scene Loader to easily load any of the scenes in the build (may not work for Unity 5.X games)
* Use the <b>Object Search</b> tab to search for Unity objects (including GameObjects, Components, etc), C# Singletons or Static Classes.
* Use the UnityObject search to look for any objects which derive from `UnityEngine.Object`, with optional filters
* The singleton search will look for any classes with a typical "Instance" field, and check it for a current value. This may cause unexpected behaviour in some IL2CPP games as we cannot distinguish between true properties and field-properties, so some property accessors will be invoked.
### Inspector
The inspector is used to see detailed information on objects of any type and manipulate their values, as well as to inspect C# Classes with static reflection.
* The <b>GameObject Inspector</b> (tab prefix `[G]`) is used to inspect a `GameObject`, and to see and manipulate its Transform and Components.
* You can edit any of the input fields in the inspector (excluding readonly fields) and press <b>Enter</b> to apply your changes. You can also do this to the GameObject path as a way to change the GameObject's parent. Press the <b>Escape</b> key to cancel your edits.
* <i>note: When inspecting a GameObject with a Canvas, the transform controls may be overridden by the RectTransform anchors.</i>
* The <b>Reflection Inspectors</b> (tab prefix `[R]` and `[S]`) are used for everything else
* Automatic updating is not enabled by default, and you must press Apply for any changes you make to take effect.
* Press the `▼` button to expand certain values such as strings, enums, lists, dictionaries, some structs, etc
* Use the filters at the top to quickly find the members you are looking for
* For `Texture2D` objects, there is a `View Texture` button at the top of the inspector which lets you view it and save it as a PNG file. Currently there are no other similar helpers yet, but I may add more at some point for Mesh, Sprite, Material, etc
### C# Console
* The C# Console uses the `Mono.CSharp.Evaluator` to define temporary classes or run immediate REPL code.
* You can execute a script automatically on startup by naming it `startup.cs` and placing it in the `UnityExplorer\Scripts\` folder (this folder will be created where you placed the DLL file).
* See the "Help" dropdown in the C# console menu for more detailed information.
### Hook Manager
* The Hooks panel allows you to hook methods at the click of a button for debugging purposes.
* Simply enter any class (generic types not yet supported) and hook the methods you want from the menu.
* You can edit the source code of the generated hook with the "Edit Hook Source" button. Accepted method names are `Prefix` (which can return `bool` or `void`), `Postfix`, `Finalizer` (which can return `Exception` or `void`), and `Transpiler` (which must return `IEnumerable<HarmonyLib.CodeInstruction>`). You can define multiple patches if you wish.
### Mouse-Inspect
* The "Mouse Inspect" dropdown in the "Inspector" panel allows you to inspect objects under the mouse.
* <b>World</b>: uses Physics.Raycast to look for Colliders
* <b>UI</b>: uses GraphicRaycasters to find UI objects
### Clipboard
* The "Clipboard" panel allows you to see your current paste value, or clear it (resets it to `null`)
* Can copy the value from any member in a Reflection Inspector, Enumerable or Dictionary, and from the target of any Inspector tab
* Can paste values onto any member in a Reflection Inspector
* Non-parsable arguments in Method/Property Evaluators allow pasting values
* The C# Console has helper methods `Copy(obj)` and `Paste()` for accessing the Clipboard
### Settings
* You can change the settings via the "Options" tab of the menu, or directly from the config file.
* <AssetsFolder>/sinai-dev-UnityExplorer~/config.cfg
# Acknowledgments
* [ManlyMarco](https://github.com/ManlyMarco) for [Runtime Unity Editor](https://github.com/ManlyMarco/RuntimeUnityEditor) \[[license](THIRDPARTY_LICENSES.md#runtimeunityeditor-license)\], the ScriptEvaluator from RUE's REPL console was used as the base for UnityExplorer's C# console.
* [Geoffrey Horsington](https://github.com/ghorsington) for [mcs-unity](https://github.com/sinai-dev/mcs-unity) \[no license\], used as the `Mono.CSharp` reference for the C# Console.
### Disclaimer
UnityExplorer is in no way associated with Unity Technologies. "Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,45 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &2342243352467007562
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 2342243352467007560}
- component: {fileID: 2342243352467007563}
m_Layer: 0
m_Name: UnityExplorer
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &2342243352467007560
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2342243352467007562}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &2342243352467007563
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2342243352467007562}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 255528132, guid: 7e940c577136f52428020c8e128f06f3, type: 3}
m_Name:
m_EditorClassIdentifier:

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,874 @@
* [RuntimeUnityEditor License](#runtimeunityeditor-license)
* [MelonLoader License](#melonloader-license)
## RuntimeUnityEditor License
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.
## MelonLoader License
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
Copyright 2020 - 2021 Lava Gang
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -0,0 +1,19 @@
{
"name": "com.sinai-dev.unityexplorer",
"version": "4.7.12",
"displayName": "UnityExplorer",
"description": "An in-game UI for exploring, debugging and modifying Unity games.",
"unity": "2017.1",
"documentationUrl": "https://github.com/sinai-dev/UnityExplorer",
"changelogUrl": "https://github.com/sinai-dev/UnityExplorer/releases",
"licensesUrl": "https://github.com/sinai-dev/UnityExplorer/blob/master/LICENSE",
"keywords": [
"inspector",
"debug",
"runtime"
],
"author": {
"name": "Sinai",
"url": "https://github.com/sinai-dev"
}
}

155
build.ps1 Normal file
View File

@ -0,0 +1,155 @@
# ----------- MelonLoader IL2CPP (net6) -----------
dotnet build src/UnityExplorer.sln -c Release_ML_Cpp_net6
$Path = "Release\UnityExplorer.MelonLoader.IL2CPP.net6preview"
# ILRepack
lib/ILRepack.exe /target:library /lib:lib/net6 /lib:lib/unhollowed /lib:$Path /internalize /out:$Path/UnityExplorer.ML.IL2CPP.net6preview.dll $Path/UnityExplorer.ML.IL2CPP.net6preview.dll $Path/mcs.dll
# (cleanup and move files)
Remove-Item $Path/UnityExplorer.ML.IL2CPP.net6preview.deps.json
Remove-Item $Path/Tomlet.dll
Remove-Item $Path/mcs.dll
Remove-Item $Path/Iced.dll
Remove-Item $Path/UnhollowerBaseLib.dll
New-Item -Path "$Path" -Name "Mods" -ItemType "directory" -Force
Move-Item -Path $Path/UnityExplorer.ML.IL2CPP.net6preview.dll -Destination $Path/Mods -Force
New-Item -Path "$Path" -Name "UserLibs" -ItemType "directory" -Force
Move-Item -Path $Path/UniverseLib.IL2CPP.Unhollower.dll -Destination $Path/UserLibs -Force
# (create zip archive)
Remove-Item $Path/../UnityExplorer.MelonLoader.IL2CPP.net6preview.zip -ErrorAction SilentlyContinue
7z a $Path/../UnityExplorer.MelonLoader.IL2CPP.net6preview.zip .\$Path\*
# ----------- MelonLoader IL2CPP (net472) -----------
dotnet build src/UnityExplorer.sln -c Release_ML_Cpp_net472
$Path = "Release/UnityExplorer.MelonLoader.IL2CPP"
# ILRepack
lib/ILRepack.exe /target:library /lib:lib/net472 /lib:lib/net35 /lib:lib/unhollowed /lib:$Path /internalize /out:$Path/UnityExplorer.ML.IL2CPP.dll $Path/UnityExplorer.ML.IL2CPP.dll $Path/mcs.dll
# (cleanup and move files)
Remove-Item $Path/Tomlet.dll
Remove-Item $Path/mcs.dll
Remove-Item $Path/Iced.dll
Remove-Item $Path/UnhollowerBaseLib.dll
New-Item -Path "$Path" -Name "Mods" -ItemType "directory" -Force
Move-Item -Path $Path/UnityExplorer.ML.IL2CPP.dll -Destination $Path/Mods -Force
New-Item -Path "$Path" -Name "UserLibs" -ItemType "directory" -Force
Move-Item -Path $Path/UniverseLib.IL2CPP.Unhollower.dll -Destination $Path/UserLibs -Force
# (create zip archive)
Remove-Item $Path/../UnityExplorer.MelonLoader.IL2CPP.zip -ErrorAction SilentlyContinue
7z a $Path/../UnityExplorer.MelonLoader.IL2CPP.zip .\$Path\*
# ----------- MelonLoader Mono -----------
dotnet build src/UnityExplorer.sln -c Release_ML_Mono
$Path = "Release/UnityExplorer.MelonLoader.Mono"
# ILRepack
lib/ILRepack.exe /target:library /lib:lib/net35 /lib:$Path /internalize /out:$Path/UnityExplorer.ML.Mono.dll $Path/UnityExplorer.ML.Mono.dll $Path/mcs.dll
# (cleanup and move files)
Remove-Item $Path/Tomlet.dll
Remove-Item $Path/mcs.dll
New-Item -Path "$Path" -Name "Mods" -ItemType "directory" -Force
Move-Item -Path $Path/UnityExplorer.ML.Mono.dll -Destination $Path/Mods -Force
New-Item -Path "$Path" -Name "UserLibs" -ItemType "directory" -Force
Move-Item -Path $Path/UniverseLib.Mono.dll -Destination $Path/UserLibs -Force
# (create zip archive)
Remove-Item $Path/../UnityExplorer.MelonLoader.Mono.zip -ErrorAction SilentlyContinue
7z a $Path/../UnityExplorer.MelonLoader.Mono.zip .\$Path\*
# ----------- BepInEx IL2CPP -----------
dotnet build src/UnityExplorer.sln -c Release_BIE_Cpp
$Path = "Release/UnityExplorer.BepInEx.IL2CPP"
# ILRepack
lib/ILRepack.exe /target:library /lib:lib/net472 /lib:lib/unhollowed /lib:$Path /internalize /out:$Path/UnityExplorer.BIE.IL2CPP.dll $Path/UnityExplorer.BIE.IL2CPP.dll $Path/mcs.dll $Path/Tomlet.dll
# (cleanup and move files)
Remove-Item $Path/Tomlet.dll
Remove-Item $Path/mcs.dll
Remove-Item $Path/Iced.dll
Remove-Item $Path/UnhollowerBaseLib.dll
New-Item -Path "$Path" -Name "plugins" -ItemType "directory" -Force
New-Item -Path "$Path" -Name "plugins/sinai-dev-UnityExplorer" -ItemType "directory" -Force
Move-Item -Path $Path/UnityExplorer.BIE.IL2CPP.dll -Destination $Path/plugins/sinai-dev-UnityExplorer -Force
Move-Item -Path $Path/UniverseLib.IL2CPP.Unhollower.dll -Destination $Path/plugins/sinai-dev-UnityExplorer -Force
# (create zip archive)
Remove-Item $Path/../UnityExplorer.BepInEx.IL2CPP.zip -ErrorAction SilentlyContinue
7z a $Path/../UnityExplorer.BepInEx.IL2CPP.zip .\$Path\*
# ----------- BepInEx IL2CPP CoreCLR -----------
dotnet build src/UnityExplorer.sln -c Release_BIE_CoreCLR
$Path = "Release/UnityExplorer.BepInEx.IL2CPP.CoreCLR"
# ILRepack
lib/ILRepack.exe /target:library /lib:lib/net472 /lib:lib/net6/ /lib:lib/interop/ /lib:$Path /internalize /out:$Path/UnityExplorer.BIE.IL2CPP.CoreCLR.dll $Path/UnityExplorer.BIE.IL2CPP.CoreCLR.dll $Path/mcs.dll $Path/Tomlet.dll
# (cleanup and move files)
Remove-Item $Path/Tomlet.dll
Remove-Item $Path/mcs.dll
Remove-Item $Path/Iced.dll
Remove-Item $Path/Il2CppInterop.Common.dll
Remove-Item $Path/Il2CppInterop.Runtime.dll
Remove-Item $Path/Microsoft.Extensions.Logging.Abstractions.dll
Remove-Item $Path/UnityExplorer.BIE.IL2CPP.CoreCLR.deps.json
New-Item -Path "$Path" -Name "plugins" -ItemType "directory" -Force
New-Item -Path "$Path" -Name "plugins/sinai-dev-UnityExplorer" -ItemType "directory" -Force
Move-Item -Path $Path/UnityExplorer.BIE.IL2CPP.CoreCLR.dll -Destination $Path/plugins/sinai-dev-UnityExplorer -Force
Move-Item -Path $Path/UniverseLib.IL2CPP.Interop.dll -Destination $Path/plugins/sinai-dev-UnityExplorer -Force
# (create zip archive)
Remove-Item $Path/../UnityExplorer.BepInEx.IL2CPP.CoreCLR.zip -ErrorAction SilentlyContinue
7z a $Path/../UnityExplorer.BepInEx.IL2CPP.CoreCLR.zip .\$Path\*
# ----------- BepInEx 5 Mono -----------
dotnet build src/UnityExplorer.sln -c Release_BIE5_Mono
$Path = "Release/UnityExplorer.BepInEx5.Mono"
# ILRepack
lib/ILRepack.exe /target:library /lib:lib/net35 /lib:$Path /internalize /out:$Path/UnityExplorer.BIE5.Mono.dll $Path/UnityExplorer.BIE5.Mono.dll $Path/mcs.dll $Path/Tomlet.dll
# (cleanup and move files)
Remove-Item $Path/Tomlet.dll
Remove-Item $Path/mcs.dll
New-Item -Path "$Path" -Name "plugins" -ItemType "directory" -Force
New-Item -Path "$Path" -Name "plugins/sinai-dev-UnityExplorer" -ItemType "directory" -Force
Move-Item -Path $Path/UnityExplorer.BIE5.Mono.dll -Destination $Path/plugins/sinai-dev-UnityExplorer -Force
Move-Item -Path $Path/UniverseLib.Mono.dll -Destination $Path/plugins/sinai-dev-UnityExplorer -Force
# (create zip archive)
Remove-Item $Path/../UnityExplorer.BepInEx5.Mono.zip -ErrorAction SilentlyContinue
7z a $Path/../UnityExplorer.BepInEx5.Mono.zip .\$Path\*
# ----------- BepInEx 6 Mono -----------
dotnet build src/UnityExplorer.sln -c Release_BIE6_Mono
$Path = "Release/UnityExplorer.BepInEx6.Mono"
# ILRepack
lib/ILRepack.exe /target:library /lib:lib/net35 /lib:$Path /internalize /out:$Path/UnityExplorer.BIE6.Mono.dll $Path/UnityExplorer.BIE6.Mono.dll $Path/mcs.dll $Path/Tomlet.dll
# (cleanup and move files)
Remove-Item $Path/Tomlet.dll
Remove-Item $Path/mcs.dll
New-Item -Path "$Path" -Name "plugins" -ItemType "directory" -Force
New-Item -Path "$Path" -Name "plugins/sinai-dev-UnityExplorer" -ItemType "directory" -Force
Move-Item -Path $Path/UnityExplorer.BIE6.Mono.dll -Destination $Path/plugins/sinai-dev-UnityExplorer -Force
Move-Item -Path $Path/UniverseLib.Mono.dll -Destination $Path/plugins/sinai-dev-UnityExplorer -Force
# (create zip archive)
Remove-Item $Path/../UnityExplorer.BepInEx6.Mono.zip -ErrorAction SilentlyContinue
7z a $Path/../UnityExplorer.BepInEx6.Mono.zip .\$Path\*
# ----------- Standalone Mono -----------
dotnet build src/UnityExplorer.sln -c Release_STANDALONE_Mono
$Path = "Release/UnityExplorer.Standalone.Mono"
# ILRepack
lib/ILRepack.exe /target:library /lib:lib/net35 /lib:$Path /internalize /out:$Path/UnityExplorer.Standalone.Mono.dll $Path/UnityExplorer.Standalone.Mono.dll $Path/mcs.dll $Path/Tomlet.dll
# (cleanup and move files)
Remove-Item $Path/Tomlet.dll
Remove-Item $Path/mcs.dll
Remove-Item $Path/../UnityExplorer.Standalone.Mono.zip -ErrorAction SilentlyContinue
7z a $Path/../UnityExplorer.Standalone.Mono.zip .\$Path\*
# ----------- Standalone IL2CPP -----------
dotnet build src/UnityExplorer.sln -c Release_STANDALONE_Cpp
$Path = "Release/UnityExplorer.Standalone.IL2CPP"
# ILRepack
lib/ILRepack.exe /target:library /lib:lib/net472 /lib:lib/unhollowed /lib:$Path /internalize /out:$Path/UnityExplorer.Standalone.IL2CPP.dll $Path/UnityExplorer.Standalone.IL2CPP.dll $Path/mcs.dll $Path/Tomlet.dll
# (cleanup and move files)
Remove-Item $Path/Tomlet.dll
Remove-Item $Path/mcs.dll
Remove-Item $Path/Iced.dll
Remove-Item $Path/UnhollowerBaseLib.dll
Remove-Item $Path/../UnityExplorer.Standalone.IL2CPP.zip -ErrorAction SilentlyContinue
7z a $Path/../UnityExplorer.Standalone.IL2CPP.zip .\$Path\*
# ----------- Editor (mono) -----------
$Path1 = "Release/UnityExplorer.Standalone.Mono"
$Path2 = "UnityEditorPackage/Runtime"
Copy-Item $Path1/UnityExplorer.STANDALONE.Mono.dll -Destination $Path2
Copy-Item $Path1/UniverseLib.Mono.dll -Destination $Path2
Remove-Item Release/UnityExplorer.Editor.zip -ErrorAction SilentlyContinue
7z a Release/UnityExplorer.Editor.zip .\UnityEditorPackage\*

BIN
img/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

BIN
img/preview.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 495 KiB

BIN
lib/ILRepack.exe Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
lib/interop/UnityEngine.dll Normal file

Binary file not shown.

Binary file not shown.

BIN
lib/net35/BepInEx.Core.dll Normal file

Binary file not shown.

BIN
lib/net35/BepInEx.Unity.dll Normal file

Binary file not shown.

BIN
lib/net35/BepInEx.dll Normal file

Binary file not shown.

BIN
lib/net35/MelonLoader.dll Normal file

Binary file not shown.

Binary file not shown.

BIN
lib/net35/UnityEngine.dll Normal file

Binary file not shown.

BIN
lib/net35/mcs.dll Normal file

Binary file not shown.

BIN
lib/net472/BepInEx.Core.dll Normal file

Binary file not shown.

Binary file not shown.

BIN
lib/net6/MelonLoader.dll Normal file

Binary file not shown.

BIN
lib/net6/System.Runtime.dll Normal file

Binary file not shown.

BIN
lib/net6/mcs.dll Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,147 @@
using System.Text;
using UnityExplorer.CSConsole.Lexers;
using UnityExplorer.UI.Panels;
using UnityExplorer.UI.Widgets.AutoComplete;
using UniverseLib.UI.Models;
namespace UnityExplorer.CSConsole
{
public class CSAutoCompleter : ISuggestionProvider
{
public InputFieldRef InputField => ConsoleController.Input;
public bool AnchorToCaretPosition => true;
bool ISuggestionProvider.AllowNavigation => true;
public void OnSuggestionClicked(Suggestion suggestion)
{
ConsoleController.InsertSuggestionAtCaret(suggestion.UnderlyingValue);
AutoCompleteModal.Instance.ReleaseOwnership(this);
}
private readonly HashSet<char> delimiters = new()
{
'{',
'}',
',',
';',
'<',
'>',
'(',
')',
'[',
']',
'=',
'|',
'&',
'?'
};
private readonly List<Suggestion> suggestions = new();
public void CheckAutocompletes()
{
if (string.IsNullOrEmpty(InputField.Text))
{
AutoCompleteModal.Instance.ReleaseOwnership(this);
return;
}
suggestions.Clear();
int caret = Math.Max(0, Math.Min(InputField.Text.Length - 1, InputField.Component.caretPosition - 1));
int startIdx = caret;
// If the character at the caret index is whitespace or delimiter,
// or if the next character (if it exists) is not whitespace,
// then we don't want to provide suggestions.
if (char.IsWhiteSpace(InputField.Text[caret])
|| delimiters.Contains(InputField.Text[caret])
|| (InputField.Text.Length > caret + 1 && !char.IsWhiteSpace(InputField.Text[caret + 1])))
{
AutoCompleteModal.Instance.ReleaseOwnership(this);
return;
}
// get the current composition string (from caret back to last delimiter)
while (startIdx > 0)
{
startIdx--;
char c = InputField.Text[startIdx];
if (delimiters.Contains(c) || char.IsWhiteSpace(c))
{
startIdx++;
break;
}
}
string input = InputField.Text.Substring(startIdx, caret - startIdx + 1);
// Get MCS completions
string[] evaluatorCompletions = ConsoleController.Evaluator.GetCompletions(input, out string prefix);
if (evaluatorCompletions != null && evaluatorCompletions.Any())
{
suggestions.AddRange(from completion in evaluatorCompletions
select new Suggestion(GetHighlightString(prefix, completion), completion));
}
// Get manual namespace completions
foreach (string ns in ReflectionUtility.AllNamespaces)
{
if (ns.StartsWith(input))
{
if (!namespaceHighlights.ContainsKey(ns))
namespaceHighlights.Add(ns, $"<color=#CCCCCC>{ns}</color>");
string completion = ns.Substring(input.Length, ns.Length - input.Length);
suggestions.Add(new Suggestion(namespaceHighlights[ns], completion));
}
}
// Get manual keyword completions
foreach (string kw in KeywordLexer.keywords)
{
if (kw.StartsWith(input))// && kw.Length > input.Length)
{
if (!keywordHighlights.ContainsKey(kw))
keywordHighlights.Add(kw, $"<color=#{SignatureHighlighter.keywordBlueHex}>{kw}</color>");
string completion = kw.Substring(input.Length, kw.Length - input.Length);
suggestions.Add(new Suggestion(keywordHighlights[kw], completion));
}
}
if (suggestions.Any())
{
AutoCompleteModal.TakeOwnership(this);
AutoCompleteModal.Instance.SetSuggestions(suggestions);
}
else
{
AutoCompleteModal.Instance.ReleaseOwnership(this);
}
}
private readonly Dictionary<string, string> namespaceHighlights = new();
private readonly Dictionary<string, string> keywordHighlights = new();
private readonly StringBuilder highlightBuilder = new();
private const string OPEN_HIGHLIGHT = "<color=cyan>";
private string GetHighlightString(string prefix, string completion)
{
highlightBuilder.Clear();
highlightBuilder.Append(OPEN_HIGHLIGHT);
highlightBuilder.Append(prefix);
highlightBuilder.Append(SignatureHighlighter.CLOSE_COLOR);
highlightBuilder.Append(completion);
return highlightBuilder.ToString();
}
}
}

View File

@ -0,0 +1,747 @@
using Mono.CSharp;
using System.Collections;
using System.Text;
using UnityExplorer.UI;
using UnityExplorer.UI.Panels;
using UniverseLib.Input;
using UniverseLib.UI.Models;
namespace UnityExplorer.CSConsole
{
public static class ConsoleController
{
public static ScriptEvaluator Evaluator { get; private set; }
public static LexerBuilder Lexer { get; private set; }
public static CSAutoCompleter Completer { get; private set; }
public static bool SRENotSupported { get; private set; }
public static int LastCaretPosition { get; private set; }
public static float DefaultInputFieldAlpha { get; set; }
public static bool EnableCtrlRShortcut { get; private set; } = true;
public static bool EnableAutoIndent { get; private set; } = true;
public static bool EnableSuggestions { get; private set; } = true;
public static CSConsolePanel Panel => UIManager.GetPanel<CSConsolePanel>(UIManager.Panels.CSConsole);
public static InputFieldRef Input => Panel.Input;
public static string ScriptsFolder => Path.Combine(ExplorerCore.ExplorerFolder, "Scripts");
static HashSet<string> usingDirectives;
static StringBuilder evaluatorOutput;
static StringWriter evaluatorStringWriter;
static float timeOfLastCtrlR;
static bool settingCaretCoroutine;
static string previousInput;
static int previousContentLength = 0;
static readonly string[] DefaultUsing = new string[]
{
"System",
"System.Linq",
"System.Text",
"System.Collections",
"System.Collections.Generic",
"System.Reflection",
"UnityEngine",
"UniverseLib",
#if CPP
"UnhollowerBaseLib",
"UnhollowerRuntimeLib",
#endif
};
const int CSCONSOLE_LINEHEIGHT = 18;
public static void Init()
{
try
{
ResetConsole(false);
// ensure the compiler is supported (if this fails then SRE is probably stripped)
Evaluator.Compile("0 == 0");
}
catch (Exception ex)
{
DisableConsole(ex);
return;
}
// Setup console
Lexer = new LexerBuilder();
Completer = new CSAutoCompleter();
SetupHelpInteraction();
Panel.OnInputChanged += OnInputChanged;
Panel.InputScroller.OnScroll += OnInputScrolled;
Panel.OnCompileClicked += Evaluate;
Panel.OnResetClicked += ResetConsole;
Panel.OnHelpDropdownChanged += HelpSelected;
Panel.OnAutoIndentToggled += OnToggleAutoIndent;
Panel.OnCtrlRToggled += OnToggleCtrlRShortcut;
Panel.OnSuggestionsToggled += OnToggleSuggestions;
Panel.OnPanelResized += OnInputScrolled;
// Run startup script
try
{
if (!Directory.Exists(ScriptsFolder))
Directory.CreateDirectory(ScriptsFolder);
string startupPath = Path.Combine(ScriptsFolder, "startup.cs");
if (File.Exists(startupPath))
{
ExplorerCore.Log($"Executing startup script from '{startupPath}'...");
string text = File.ReadAllText(startupPath);
Input.Text = text;
Evaluate();
}
}
catch (Exception ex)
{
ExplorerCore.LogWarning($"Exception executing startup script: {ex}");
}
}
#region Evaluating
static void GenerateTextWriter()
{
evaluatorOutput = new StringBuilder();
evaluatorStringWriter = new StringWriter(evaluatorOutput);
}
public static void ResetConsole() => ResetConsole(true);
public static void ResetConsole(bool logSuccess = true)
{
if (SRENotSupported)
return;
if (Evaluator != null)
Evaluator.Dispose();
GenerateTextWriter();
Evaluator = new ScriptEvaluator(evaluatorStringWriter)
{
InteractiveBaseClass = typeof(ScriptInteraction)
};
usingDirectives = new HashSet<string>();
foreach (string use in DefaultUsing)
AddUsing(use);
if (logSuccess)
ExplorerCore.Log($"C# Console reset");//. Using directives:\r\n{Evaluator.GetUsing()}");
}
public static void AddUsing(string assemblyName)
{
if (!usingDirectives.Contains(assemblyName))
{
Evaluate($"using {assemblyName};", true);
usingDirectives.Add(assemblyName);
}
}
public static void Evaluate()
{
if (SRENotSupported)
return;
Evaluate(Input.Text);
}
public static void Evaluate(string input, bool supressLog = false)
{
if (SRENotSupported)
return;
if (evaluatorStringWriter == null || evaluatorOutput == null)
{
GenerateTextWriter();
Evaluator._textWriter = evaluatorStringWriter;
}
try
{
// Compile the code. If it returned a CompiledMethod, it is REPL.
CompiledMethod repl = Evaluator.Compile(input);
if (repl != null)
{
// Valid REPL, we have a delegate to the evaluation.
try
{
object ret = null;
repl.Invoke(ref ret);
string result = ret?.ToString();
if (!string.IsNullOrEmpty(result))
ExplorerCore.Log($"Invoked REPL, result: {ret}");
else
ExplorerCore.Log($"Invoked REPL (no return value)");
}
catch (Exception ex)
{
ExplorerCore.LogWarning($"Exception invoking REPL: {ex}");
}
}
else
{
// The compiled code was not REPL, so it was a using directive or it defined classes.
string output = Evaluator._textWriter.ToString();
string[] outputSplit = output.Split('\n');
if (outputSplit.Length >= 2)
output = outputSplit[outputSplit.Length - 2];
evaluatorOutput.Clear();
if (ScriptEvaluator._reportPrinter.ErrorsCount > 0)
throw new FormatException($"Unable to compile the code. Evaluator's last output was:\r\n{output}");
else if (!supressLog)
ExplorerCore.Log($"Code compiled without errors.");
}
}
catch (FormatException fex)
{
if (!supressLog)
ExplorerCore.LogWarning(fex.Message);
}
catch (Exception ex)
{
if (!supressLog)
ExplorerCore.LogWarning(ex);
}
}
#endregion
#region Update loop and event listeners
public static void Update()
{
if (SRENotSupported)
return;
if (!InputManager.GetKey(KeyCode.LeftControl) && !InputManager.GetKey(KeyCode.RightControl))
{
if (InputManager.GetKeyDown(KeyCode.Home))
JumpToStartOrEndOfLine(true);
else if (InputManager.GetKeyDown(KeyCode.End))
JumpToStartOrEndOfLine(false);
}
UpdateCaret(out bool caretMoved);
if (!settingCaretCoroutine && EnableSuggestions)
{
if (AutoCompleteModal.CheckEscape(Completer))
{
OnAutocompleteEscaped();
return;
}
if (caretMoved)
AutoCompleteModal.Instance.ReleaseOwnership(Completer);
}
if (EnableCtrlRShortcut
&& (InputManager.GetKey(KeyCode.LeftControl) || InputManager.GetKey(KeyCode.RightControl))
&& InputManager.GetKeyDown(KeyCode.R)
&& timeOfLastCtrlR.OccuredEarlierThanDefault())
{
timeOfLastCtrlR = Time.realtimeSinceStartup;
Evaluate(Panel.Input.Text);
}
}
static void OnInputScrolled() => HighlightVisibleInput(out _);
static void OnInputChanged(string value)
{
if (SRENotSupported)
return;
// prevent escape wiping input
if (InputManager.GetKeyDown(KeyCode.Escape))
{
Input.Text = previousInput;
if (EnableSuggestions && AutoCompleteModal.CheckEscape(Completer))
OnAutocompleteEscaped();
return;
}
previousInput = value;
if (EnableSuggestions && AutoCompleteModal.CheckEnter(Completer))
OnAutocompleteEnter();
if (!settingCaretCoroutine)
{
if (EnableAutoIndent)
DoAutoIndent();
}
HighlightVisibleInput(out bool inStringOrComment);
if (!settingCaretCoroutine)
{
if (EnableSuggestions)
{
if (inStringOrComment)
AutoCompleteModal.Instance.ReleaseOwnership(Completer);
else
Completer.CheckAutocompletes();
}
}
UpdateCaret(out _);
}
static void OnToggleAutoIndent(bool value)
{
EnableAutoIndent = value;
}
static void OnToggleCtrlRShortcut(bool value)
{
EnableCtrlRShortcut = value;
}
static void OnToggleSuggestions(bool value)
{
EnableSuggestions = value;
}
#endregion
#region Caret position
static void UpdateCaret(out bool caretMoved)
{
int prevCaret = LastCaretPosition;
caretMoved = false;
// Override up/down arrow movement when autocompleting
if (EnableSuggestions && AutoCompleteModal.CheckNavigation(Completer))
{
Input.Component.caretPosition = LastCaretPosition;
return;
}
if (Input.Component.isFocused)
{
LastCaretPosition = Input.Component.caretPosition;
caretMoved = LastCaretPosition != prevCaret;
}
if (Input.Text.Length == 0)
return;
// If caret moved, ensure caret is visible in the viewport
if (caretMoved)
{
UICharInfo charInfo = Input.TextGenerator.characters[LastCaretPosition];
float charTop = charInfo.cursorPos.y;
float charBot = charTop - CSCONSOLE_LINEHEIGHT;
float viewportMin = Input.Transform.rect.height - Input.Transform.anchoredPosition.y - (Input.Transform.rect.height * 0.5f);
float viewportMax = viewportMin - Panel.InputScroller.ViewportRect.rect.height;
float diff = 0f;
if (charTop > viewportMin)
diff = charTop - viewportMin;
else if (charBot < viewportMax)
diff = charBot - viewportMax;
if (Math.Abs(diff) > 1)
{
RectTransform rect = Input.Transform;
rect.anchoredPosition = new Vector2(rect.anchoredPosition.x, rect.anchoredPosition.y - diff);
}
}
}
public static void SetCaretPosition(int caretPosition)
{
Input.Component.caretPosition = caretPosition;
// Fix to make sure we always really set the caret position.
// Yields a frame and fixes text-selection issues.
settingCaretCoroutine = true;
Input.Component.readOnly = true;
RuntimeHelper.StartCoroutine(DoSetCaretCoroutine(caretPosition));
}
static IEnumerator DoSetCaretCoroutine(int caretPosition)
{
Color color = Input.Component.selectionColor;
color.a = 0f;
Input.Component.selectionColor = color;
EventSystemHelper.SetSelectionGuard(false);
Input.Component.Select();
yield return null; // ~~~~~~~ YIELD FRAME ~~~~~~~~~
Input.Component.caretPosition = caretPosition;
Input.Component.selectionFocusPosition = caretPosition;
LastCaretPosition = Input.Component.caretPosition;
color.a = DefaultInputFieldAlpha;
Input.Component.selectionColor = color;
Input.Component.readOnly = false;
settingCaretCoroutine = false;
}
// For Home and End keys
static void JumpToStartOrEndOfLine(bool toStart)
{
// Determine the current and next line
UILineInfo thisline = default;
UILineInfo? nextLine = null;
for (int i = 0; i < Input.Component.cachedInputTextGenerator.lineCount; i++)
{
UILineInfo line = Input.Component.cachedInputTextGenerator.lines[i];
if (line.startCharIdx > LastCaretPosition)
{
nextLine = line;
break;
}
thisline = line;
}
if (toStart)
{
// Determine where the indented text begins
int endOfLine = nextLine == null ? Input.Text.Length : nextLine.Value.startCharIdx;
int indentedStart = thisline.startCharIdx;
while (indentedStart < endOfLine - 1 && char.IsWhiteSpace(Input.Text[indentedStart]))
indentedStart++;
// Jump to either the true start or the non-whitespace position,
// depending on which one we are not at.
if (LastCaretPosition == indentedStart)
SetCaretPosition(thisline.startCharIdx);
else
SetCaretPosition(indentedStart);
}
else
{
// If there is no next line, jump to the end of this line (+1, to the invisible next character position)
if (nextLine == null)
SetCaretPosition(Input.Text.Length);
else // jump to the next line start index - 1, ie. end of this line
SetCaretPosition(nextLine.Value.startCharIdx - 1);
}
}
#endregion
#region Lexer Highlighting
private static void HighlightVisibleInput(out bool inStringOrComment)
{
inStringOrComment = false;
if (string.IsNullOrEmpty(Input.Text))
{
Panel.HighlightText.text = "";
Panel.LineNumberText.text = "1";
return;
}
// Calculate the visible lines
int topLine = -1;
int bottomLine = -1;
// the top and bottom position of the viewport in relation to the text height
// they need the half-height adjustment to normalize against the 'line.topY' value.
float viewportMin = Input.Transform.rect.height - Input.Transform.anchoredPosition.y - (Input.Transform.rect.height * 0.5f);
float viewportMax = viewportMin - Panel.InputScroller.ViewportRect.rect.height;
for (int i = 0; i < Input.TextGenerator.lineCount; i++)
{
UILineInfo line = Input.TextGenerator.lines[i];
// if not set the top line yet, and top of line is below the viewport top
if (topLine == -1 && line.topY <= viewportMin)
topLine = i;
// if bottom of line is below the viewport bottom
if ((line.topY - line.height) >= viewportMax)
bottomLine = i;
}
topLine = Math.Max(0, topLine - 1);
bottomLine = Math.Min(Input.TextGenerator.lineCount - 1, bottomLine + 1);
int startIdx = Input.TextGenerator.lines[topLine].startCharIdx;
int endIdx = (bottomLine >= Input.TextGenerator.lineCount - 1)
? Input.Text.Length - 1
: (Input.TextGenerator.lines[bottomLine + 1].startCharIdx - 1);
// Highlight the visible text with the LexerBuilder
Panel.HighlightText.text = Lexer.BuildHighlightedString(Input.Text, startIdx, endIdx, topLine, LastCaretPosition, out inStringOrComment);
// Set the line numbers
// determine true starting line number (not the same as the cached TextGenerator line numbers)
int realStartLine = 0;
for (int i = 0; i < startIdx; i++)
{
if (LexerBuilder.IsNewLine(Input.Text[i]))
realStartLine++;
}
realStartLine++;
char lastPrev = '\n';
StringBuilder sb = new();
// append leading new lines for spacing (no point rendering line numbers we cant see)
for (int i = 0; i < topLine; i++)
sb.Append('\n');
// append the displayed line numbers
for (int i = topLine; i <= bottomLine; i++)
{
if (i > 0)
lastPrev = Input.Text[Input.TextGenerator.lines[i].startCharIdx - 1];
// previous line ended with a newline character, this is an actual new line.
if (LexerBuilder.IsNewLine(lastPrev))
{
sb.Append(realStartLine.ToString());
realStartLine++;
}
sb.Append('\n');
}
Panel.LineNumberText.text = sb.ToString();
return;
}
#endregion
#region Autocompletes
public static void InsertSuggestionAtCaret(string suggestion)
{
settingCaretCoroutine = true;
Input.Text = Input.Text.Insert(LastCaretPosition, suggestion);
SetCaretPosition(LastCaretPosition + suggestion.Length);
LastCaretPosition = Input.Component.caretPosition;
}
private static void OnAutocompleteEnter()
{
// Remove the new line
int lastIdx = Input.Component.caretPosition - 1;
Input.Text = Input.Text.Remove(lastIdx, 1);
// Use the selected suggestion
Input.Component.caretPosition = LastCaretPosition;
Completer.OnSuggestionClicked(AutoCompleteModal.SelectedSuggestion);
}
private static void OnAutocompleteEscaped()
{
AutoCompleteModal.Instance.ReleaseOwnership(Completer);
SetCaretPosition(LastCaretPosition);
}
#endregion
#region Auto indenting
private static void DoAutoIndent()
{
if (Input.Text.Length > previousContentLength)
{
int inc = Input.Text.Length - previousContentLength;
if (inc == 1)
{
int caret = Input.Component.caretPosition;
Input.Text = Lexer.IndentCharacter(Input.Text, ref caret);
Input.Component.caretPosition = caret;
LastCaretPosition = caret;
}
else
{
// todo indenting for copy+pasted content
//ExplorerCore.Log("Content increased by " + inc);
//var comp = Input.Text.Substring(PreviousCaretPosition, inc);
//ExplorerCore.Log("composition string: " + comp);
}
}
previousContentLength = Input.Text.Length;
}
#endregion
#region "Help" interaction
private static void DisableConsole(Exception ex)
{
SRENotSupported = true;
Input.Component.readOnly = true;
Input.Component.textComponent.color = "5d8556".ToColor();
if (ex is NotSupportedException)
{
Input.Text = $@"The C# Console has been disabled because System.Reflection.Emit threw a NotSupportedException.
Easy, dirty fix: (will likely break on game updates)
* Download the corlibs for the game's Unity version from here: https://unity.bepinex.dev/corlibs/
* Unzip and copy mscorlib.dll (and System.Reflection.Emit DLLs, if present) from the folder
* Paste and overwrite the files into <Game>_Data/Managed/
With UnityDoorstop: (BepInEx only, or if you use UnityDoorstop + Standalone release):
* Download the corlibs for the game's Unity version from here: https://unity.bepinex.dev/corlibs/
* Unzip and copy mscorlib.dll (and System.Reflection.Emit DLLs, if present) from the folder
* Find the folder which contains doorstop_config.ini (the game folder, or your r2modman/ThunderstoreModManager profile folder)
* Make a subfolder called 'corlibs' inside this folder.
* Paste the DLLs inside the corlibs folder.
* In doorstop_config.ini, set 'dllSearchPathOverride=corlibs'.
Doorstop example:
- <Game>\
- <Game>_Data\...
- BepInEx\...
- corlibs\
- mscorlib.dll
- doorstop_config.ini (with dllSearchPathOverride=corlibs)
- <Game>.exe
- winhttp.dll";
}
else
{
Input.Text = $"The C# Console has been disabled. {ex}";
}
}
private static readonly Dictionary<string, string> helpDict = new();
public static void SetupHelpInteraction()
{
Dropdown drop = Panel.HelpDropdown;
helpDict.Add("Help", "");
helpDict.Add("Usings", HELP_USINGS);
helpDict.Add("REPL", HELP_REPL);
helpDict.Add("Classes", HELP_CLASSES);
helpDict.Add("Coroutines", HELP_COROUTINES);
foreach (KeyValuePair<string, string> opt in helpDict)
drop.options.Add(new Dropdown.OptionData(opt.Key));
}
public static void HelpSelected(int index)
{
if (index == 0)
return;
KeyValuePair<string, string> helpText = helpDict.ElementAt(index);
Input.Text = helpText.Value;
Panel.HelpDropdown.value = 0;
}
internal const string STARTUP_TEXT = @"<color=#5d8556>// Welcome to the UnityExplorer C# Console!
// It is recommended to use the Log panel (or a console log window) while using this tool.
// Use the Help dropdown to see detailed examples of how to use the console.
// To execute a script automatically on startup, put the script at 'sinai-dev-UnityExplorer\Scripts\startup.cs'</color>";
internal const string HELP_USINGS = @"// You can add a using directive to any namespace, but you must compile for it to take effect.
// It will remain in effect until you Reset the console.
using UnityEngine.UI;
// To see your current usings, use the ""GetUsing();"" helper.
// Note: You cannot add usings and evaluate REPL at the same time.";
internal const string HELP_REPL = @"/* REPL (Read-Evaluate-Print-Loop) is a way to execute code immediately.
* REPL code cannot contain any using directives or classes.
* The return value of the last line of your REPL will be printed to the log.
* Variables defined in REPL will exist until you Reset the console.
*/
// eg: This code would print 'Hello, World!', and then print 6 as the return value.
Log(""Hello, world!"");
var x = 5;
++x;
/* The following helpers are available in REPL mode:
* CurrentTarget; - System.Object, the target of the active Inspector tab
* AllTargets; - System.Object[], the targets of all Inspector tabs
* Log(obj); - prints a message to the console log
* Inspect(obj); - inspect the object with the Inspector
* Inspect(someType); - inspect a Type with static reflection
* Start(enumerator); - Coroutine, starts the IEnumerator as a Coroutine, and returns the Coroutine.
* Stop(coroutine); - stop the Coroutine ONLY if it was started with Start(ienumerator).
* Copy(obj); - copies the object to the UnityExplorer Clipboard
* Paste(); - System.Object, the contents of the Clipboard.
* GetUsing(); - prints the current using directives to the console log
* GetVars(); - prints the names and values of the REPL variables you have defined
* GetClasses(); - prints the names and members of the classes you have defined
* help; - the default REPL help command, contains additional helpers.
*/";
internal const string HELP_CLASSES = @"// Classes you compile will exist until the application closes.
// You can soft-overwrite a class by compiling it again with the same name. The old class will still technically exist in memory.
// Compiled classes can be accessed from both inside and outside this console.
// Note: in IL2CPP, you must declare a Namespace to inject these classes with ClassInjector or it will crash the game.
public class HelloWorld
{
public static void Main()
{
UnityExplorer.ExplorerCore.Log(""Hello, world!"");
}
}
// In REPL, you could call the example method above with ""HelloWorld.Main();""
// Note: The compiler does not allow you to run REPL code and define classes at the same time.
// In REPL, use the ""GetClasses();"" helper to see the classes you have defined since the last Reset.";
internal const string HELP_COROUTINES = @"// To start a Coroutine directly, use ""Start(SomeCoroutine());"" in REPL mode.
// To declare a coroutine, you will need to compile it separately. For example:
public class MyCoro
{
public static IEnumerator Main()
{
yield return null;
UnityExplorer.ExplorerCore.Log(""Hello, world after one frame!"");
}
}
// To run this Coroutine in REPL, it would look like ""Start(MyCoro.Main());""";
#endregion
}
}

View File

@ -0,0 +1,351 @@
using System.Text;
using UnityExplorer.CSConsole.Lexers;
namespace UnityExplorer.CSConsole
{
public struct MatchInfo
{
public int startIndex;
public int endIndex;
public bool isStringOrComment;
public bool matchToEndOfLine;
public string htmlColorTag;
}
public class LexerBuilder
{
public const char WHITESPACE = ' ';
public readonly HashSet<char> IndentOpenChars = new() { '{', '(' };
public readonly HashSet<char> IndentCloseChars = new() { '}', ')' };
private readonly Lexer[] lexers;
private readonly HashSet<char> delimiters = new();
private readonly StringLexer stringLexer = new();
private readonly CommentLexer commentLexer = new();
public LexerBuilder()
{
lexers = new Lexer[]
{
commentLexer,
stringLexer,
new SymbolLexer(),
new NumberLexer(),
new KeywordLexer(),
};
foreach (Lexer matcher in lexers)
{
foreach (char c in matcher.Delimiters)
{
if (!delimiters.Contains(c))
delimiters.Add(c);
}
}
}
/// <summary>The last committed index for a match or no-match. Starts at -1 for a new parse.</summary>
public int CommittedIndex { get; private set; }
/// <summary>The index of the character we are currently parsing, at minimum it will be CommittedIndex + 1.</summary>
public int CurrentIndex { get; private set; }
/// <summary>The current character we are parsing, determined by CurrentIndex.</summary>
public char Current => !EndOfInput ? currentInput[CurrentIndex] : WHITESPACE;
/// <summary>The previous character (CurrentIndex - 1), or whitespace if no previous character.</summary>
public char Previous => CurrentIndex >= 1 ? currentInput[CurrentIndex - 1] : WHITESPACE;
/// <summary>Returns true if CurrentIndex is >= the current input length.</summary>
public bool EndOfInput => CurrentIndex > currentEndIdx;
/// <summary>Returns true if EndOfInput or current character is a new line.</summary>
public bool EndOrNewLine => EndOfInput || IsNewLine(Current);
public static bool IsNewLine(char c) => c == '\n' || c == '\r';
private string currentInput;
private int currentStartIdx;
private int currentEndIdx;
/// <summary>
/// Parse the range of the string with the Lexer and build a RichText-highlighted representation of it.
/// </summary>
/// <param name="input">The entire input string which you want to parse a section (or all) of</param>
/// <param name="startIdx">The first character you want to highlight</param>
/// <param name="endIdx">The last character you want to highlight</param>
/// <param name="leadingLines">The amount of leading empty lines you want before the first character in the return string.</param>
/// <returns>A string which contains the amount of leading lines specified, as well as the rich-text highlighted section.</returns>
public string BuildHighlightedString(string input, int startIdx, int endIdx, int leadingLines, int caretIdx, out bool caretInStringOrComment)
{
caretInStringOrComment = false;
if (string.IsNullOrEmpty(input) || endIdx <= startIdx)
return input;
currentInput = input;
currentStartIdx = startIdx;
currentEndIdx = endIdx;
StringBuilder sb = new();
for (int i = 0; i < leadingLines; i++)
sb.Append('\n');
int lastUnhighlighted = startIdx;
foreach (MatchInfo match in GetMatches())
{
// append non-highlighted text between last match and this
for (int i = lastUnhighlighted; i < match.startIndex; i++)
sb.Append(input[i]);
// append the highlighted match
sb.Append(match.htmlColorTag);
for (int i = match.startIndex; i <= match.endIndex && i <= currentEndIdx; i++)
sb.Append(input[i]);
sb.Append(SignatureHighlighter.CLOSE_COLOR);
// update the last unhighlighted start index
lastUnhighlighted = match.endIndex + 1;
int matchEndIdx = match.endIndex;
if (match.matchToEndOfLine)
{
while (input.Length - 1 >= matchEndIdx)
{
matchEndIdx++;
if (IsNewLine(input[matchEndIdx]))
break;
}
}
// check caretIdx to determine inStringOrComment state
if (caretIdx >= match.startIndex && (caretIdx <= (matchEndIdx + 1) || (caretIdx >= input.Length && matchEndIdx >= input.Length - 1)))
caretInStringOrComment = match.isStringOrComment;
}
// Append trailing unhighlighted input
while (lastUnhighlighted <= endIdx)
{
sb.Append(input[lastUnhighlighted]);
lastUnhighlighted++;
}
return sb.ToString();
}
// Match builder, iterates through each Lexer and returns all matches found.
public IEnumerable<MatchInfo> GetMatches()
{
CommittedIndex = currentStartIdx - 1;
Rollback();
while (!EndOfInput)
{
SkipWhitespace();
bool anyMatch = false;
int startIndex = CommittedIndex + 1;
foreach (Lexer lexer in lexers)
{
if (lexer.TryMatchCurrent(this))
{
anyMatch = true;
yield return new MatchInfo
{
startIndex = startIndex,
endIndex = CommittedIndex,
htmlColorTag = lexer.ColorTag,
isStringOrComment = lexer is StringLexer || lexer is CommentLexer,
};
break;
}
else
Rollback();
}
if (!anyMatch)
{
CurrentIndex = CommittedIndex + 1;
Commit();
}
}
}
// Methods used by the Lexers for interfacing with the current parse process
public char PeekNext(int amount = 1)
{
CurrentIndex += amount;
return Current;
}
public void Commit()
{
CommittedIndex = Math.Min(currentEndIdx, CurrentIndex);
}
public void Rollback()
{
CurrentIndex = CommittedIndex + 1;
}
public void RollbackBy(int amount)
{
CurrentIndex = Math.Max(CommittedIndex + 1, CurrentIndex - amount);
}
public bool IsDelimiter(char character, bool orWhitespace = false, bool orLetterOrDigit = false)
{
return delimiters.Contains(character)
|| (orWhitespace && char.IsWhiteSpace(character))
|| (orLetterOrDigit && char.IsLetterOrDigit(character));
}
private void SkipWhitespace()
{
// peek and commit as long as there is whitespace
while (!EndOfInput && char.IsWhiteSpace(Current))
{
Commit();
PeekNext();
}
if (!char.IsWhiteSpace(Current))
Rollback();
}
#region Auto Indenting
// Using the Lexer for indenting as it already has what we need to tokenize strings and comments.
// At the moment this only handles when a single newline or close-delimiter is composed.
// Does not handle copy+paste or any other characters yet.
public string IndentCharacter(string input, ref int caretIndex)
{
int lastCharIndex = caretIndex - 1;
char c = input[lastCharIndex];
// we only want to indent for new lines and close indents
if (!IsNewLine(c) && !IndentCloseChars.Contains(c))
return input;
// perform a light parse up to the caret to determine indent level
currentInput = input;
currentStartIdx = 0;
currentEndIdx = lastCharIndex;
CommittedIndex = -1;
Rollback();
int indent = 0;
while (!EndOfInput)
{
if (CurrentIndex >= lastCharIndex)
{
// reached the caret index
if (indent <= 0)
break;
if (IsNewLine(c))
input = IndentNewLine(input, indent, ref caretIndex);
else // closing indent
input = IndentCloseDelimiter(input, indent, lastCharIndex, ref caretIndex);
break;
}
// Try match strings and comments (Lexer will commit to the end of the match)
if (stringLexer.TryMatchCurrent(this) || commentLexer.TryMatchCurrent(this))
{
PeekNext();
continue;
}
// Still parsing, check indent
if (IndentOpenChars.Contains(Current))
indent++;
else if (IndentCloseChars.Contains(Current))
indent--;
Commit();
PeekNext();
}
return input;
}
private string IndentNewLine(string input, int indent, ref int caretIndex)
{
// continue until the end of line or next non-whitespace character.
// if there's a close-indent on this line, reduce the indent level.
while (CurrentIndex < input.Length - 1)
{
CurrentIndex++;
char next = input[CurrentIndex];
if (IsNewLine(next))
break;
if (char.IsWhiteSpace(next))
continue;
else if (IndentCloseChars.Contains(next))
indent--;
break;
}
if (indent > 0)
{
input = input.Insert(caretIndex, new string('\t', indent));
caretIndex += indent;
}
return input;
}
private string IndentCloseDelimiter(string input, int indent, int lastCharIndex, ref int caretIndex)
{
if (CurrentIndex > lastCharIndex)
{
return input;
}
// lower the indent level by one as we would not have accounted for this closing symbol
indent--;
// go back from the caret to the start of the line, calculate how much indent we need to adjust.
while (CurrentIndex > 0)
{
CurrentIndex--;
char prev = input[CurrentIndex];
if (IsNewLine(prev))
break;
if (!char.IsWhiteSpace(prev))
{
// the line containing the closing bracket has non-whitespace characters before it. do not indent.
indent = 0;
break;
}
else if (prev == '\t')
indent--;
}
if (indent > 0)
{
input = input.Insert(caretIndex, new string('\t', indent));
caretIndex += indent;
}
else if (indent < 0)
{
// line is overly indented
input = input.Remove(lastCharIndex - 1, -indent);
caretIndex += indent;
}
return input;
}
#endregion
}
}

View File

@ -0,0 +1,49 @@
namespace UnityExplorer.CSConsole.Lexers
{
public class CommentLexer : Lexer
{
private enum CommentType
{
Line,
Block
}
// forest green
protected override Color HighlightColor => new(0.34f, 0.65f, 0.29f, 1.0f);
public override bool TryMatchCurrent(LexerBuilder lexer)
{
if (lexer.Current == '/')
{
lexer.PeekNext();
if (lexer.Current == '/')
{
// line comment. read to end of line or file.
do
{
lexer.Commit();
lexer.PeekNext();
}
while (!lexer.EndOrNewLine);
return true;
}
else if (lexer.Current == '*')
{
// block comment, read until end of file or closing '*/'
lexer.PeekNext();
do
{
lexer.PeekNext();
lexer.Commit();
}
while (!lexer.EndOfInput && !(lexer.Current == '/' && lexer.Previous == '*'));
return true;
}
}
return false;
}
}
}

View File

@ -0,0 +1,61 @@
using System.Text;
namespace UnityExplorer.CSConsole.Lexers
{
public class KeywordLexer : Lexer
{
// system blue
protected override Color HighlightColor => new(0.33f, 0.61f, 0.83f, 1.0f);
public static readonly HashSet<string> keywords = new()
{
// reserved keywords
"abstract", "as", "base", "bool", "break", "byte", "case", "catch", "char", "checked", "class", "const", "continue",
"decimal", "default", "delegate", "do", "double", "else", "enum", "event", "explicit", "extern", "false", "finally",
"fixed", "float", "for", "foreach", "goto", "if", "implicit", "in", "int", "interface", "internal", "is", "lock",
"long", "namespace", "new", "null", "object", "operator", "out", "override", "params", "private", "protected", "public",
"readonly", "ref", "return", "sbyte", "sealed", "short", "sizeof", "stackalloc", "static", "string", "struct", "switch",
"this", "throw", "true", "try", "typeof", "uint", "ulong", "unchecked", "unsafe", "ushort", "using", "virtual", "void",
"volatile", "while",
// contextual keywords
"add", "and", "alias", "ascending", "async", "await", "by", "descending", "dynamic", "equals", "from", "get",
"global", "group", "init", "into", "join", "let", "managed", "nameof", "not", "notnull", "on",
"or", "orderby", "partial", "record", "remove", "select", "set", "unmanaged", "value", "var", "when", "where",
"where", "with", "yield", "nint", "nuint"
};
public override bool TryMatchCurrent(LexerBuilder lexer)
{
char prev = lexer.Previous;
char first = lexer.Current;
// check for keywords
if (lexer.IsDelimiter(prev, true) && char.IsLetter(first))
{
// can be a keyword...
StringBuilder sb = new();
sb.Append(lexer.Current);
while (!lexer.EndOfInput && char.IsLetter(lexer.PeekNext()))
sb.Append(lexer.Current);
// next must be whitespace or delimiter
if (!lexer.EndOfInput && !(char.IsWhiteSpace(lexer.Current) || lexer.IsDelimiter(lexer.Current)))
return false;
if (keywords.Contains(sb.ToString()))
{
if (!lexer.EndOfInput)
lexer.RollbackBy(1);
lexer.Commit();
return true;
}
return false;
}
else
return false;
}
}
}

View File

@ -0,0 +1,14 @@
namespace UnityExplorer.CSConsole.Lexers
{
public abstract class Lexer
{
public virtual IEnumerable<char> Delimiters => Enumerable.Empty<char>();
protected abstract Color HighlightColor { get; }
public string ColorTag => colorTag ?? (colorTag = "<color=#" + HighlightColor.ToHex() + ">");
private string colorTag;
public abstract bool TryMatchCurrent(LexerBuilder lexer);
}
}

View File

@ -0,0 +1,30 @@
namespace UnityExplorer.CSConsole.Lexers
{
public class NumberLexer : Lexer
{
// Maroon
protected override Color HighlightColor => new(0.58f, 0.33f, 0.33f, 1.0f);
private bool IsNumeric(char c) => char.IsNumber(c) || c == '.';
public override bool TryMatchCurrent(LexerBuilder lexer)
{
// previous character must be whitespace or delimiter
if (!lexer.IsDelimiter(lexer.Previous, true))
return false;
if (!IsNumeric(lexer.Current))
return false;
while (!lexer.EndOfInput)
{
lexer.Commit();
if (!IsNumeric(lexer.PeekNext()))
break;
}
return true;
}
}
}

View File

@ -0,0 +1,77 @@
namespace UnityExplorer.CSConsole.Lexers
{
public class StringLexer : Lexer
{
public override IEnumerable<char> Delimiters => new[] { '"', '\'', };
// orange
protected override Color HighlightColor => new(0.79f, 0.52f, 0.32f, 1.0f);
public override bool TryMatchCurrent(LexerBuilder lexer)
{
if (lexer.Current == '"')
{
if (lexer.Previous == '@')
{
// verbatim string, continue until un-escaped quote.
while (!lexer.EndOfInput)
{
lexer.Commit();
if (lexer.PeekNext() == '"')
{
lexer.Commit();
// possibly the end, check for escaped quotes.
// commit the character and flip the escape bool for each quote.
bool escaped = false;
while (lexer.PeekNext() == '"')
{
lexer.Commit();
escaped = !escaped;
}
// if the last quote wasnt escaped, that was the end of the string.
if (!escaped)
break;
}
}
}
else
{
// normal string
// continue until a quote which is not escaped, or end of input
while (!lexer.EndOfInput)
{
lexer.Commit();
lexer.PeekNext();
if ((lexer.Current == '"') && lexer.Previous != '\\')
{
lexer.Commit();
break;
}
}
}
return true;
}
else if (lexer.Current == '\'')
{
// char
while (!lexer.EndOfInput)
{
lexer.Commit();
lexer.PeekNext();
if ((lexer.Current == '\'') && lexer.Previous != '\\')
{
lexer.Commit();
break;
}
}
return true;
}
else
return false;
}
}
}

View File

@ -0,0 +1,38 @@
namespace UnityExplorer.CSConsole.Lexers
{
public class SymbolLexer : Lexer
{
// silver
protected override Color HighlightColor => new(0.6f, 0.6f, 0.6f);
// all symbols are delimiters
public override IEnumerable<char> Delimiters => symbols.Where(it => it != '.'); // '.' is not a delimiter, only a separator.
public static bool IsSymbol(char c) => symbols.Contains(c);
public static readonly HashSet<char> symbols = new()
{
'[', '{', '(', // open
']', '}', ')', // close
'.', ',', ';', ':', '?', '@', // special
// operators
'+', '-', '*', '/', '%', '&', '|', '^', '~', '=', '<', '>', '!',
};
public override bool TryMatchCurrent(LexerBuilder lexer)
{
// previous character must be delimiter, whitespace, or alphanumeric.
if (!lexer.IsDelimiter(lexer.Previous, true, true))
return false;
if (IsSymbol(lexer.Current))
{
lexer.Commit();
return true;
}
return false;
}
}
}

View File

@ -0,0 +1,100 @@
using Mono.CSharp;
using UnityExplorer.Config;
// Thanks to ManlyMarco for this
namespace UnityExplorer.CSConsole
{
public class ScriptEvaluator : Evaluator, IDisposable
{
internal TextWriter _textWriter;
internal static StreamReportPrinter _reportPrinter;
private static readonly HashSet<string> StdLib = new(StringComparer.InvariantCultureIgnoreCase)
{
"mscorlib",
"System.Core",
"System",
"System.Xml"
};
public ScriptEvaluator(TextWriter tw) : base(BuildContext(tw))
{
_textWriter = tw;
ImportAppdomainAssemblies();
AppDomain.CurrentDomain.AssemblyLoad += OnAssemblyLoad;
}
public void Dispose()
{
AppDomain.CurrentDomain.AssemblyLoad -= OnAssemblyLoad;
_textWriter.Dispose();
}
private void OnAssemblyLoad(object sender, AssemblyLoadEventArgs args)
{
string name = args.LoadedAssembly.GetName().Name;
if (StdLib.Contains(name))
return;
Reference(args.LoadedAssembly);
}
private void Reference(Assembly asm)
{
string name = asm.GetName().Name;
if (name == "completions") // ignore assemblies generated by mcs' autocomplete.
return;
foreach (string blacklisted in ConfigManager.CSConsole_Assembly_Blacklist.Value.Split(';'))
{
string bl = blacklisted;
if (bl.EndsWith(".dll", StringComparison.OrdinalIgnoreCase))
bl = blacklisted.Substring(0, bl.Length - 4);
if (string.Equals(bl, name, StringComparison.OrdinalIgnoreCase))
return;
}
ReferenceAssembly(asm);
}
private static CompilerContext BuildContext(TextWriter tw)
{
_reportPrinter = new StreamReportPrinter(tw);
CompilerSettings settings = new()
{
Version = LanguageVersion.Experimental,
GenerateDebugInfo = false,
StdLib = true,
Target = Target.Library,
WarningLevel = 0,
EnhancedWarnings = false
};
return new CompilerContext(settings, _reportPrinter);
}
private void ImportAppdomainAssemblies()
{
foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
{
string name = assembly.GetName().Name;
if (StdLib.Contains(name))
continue;
try
{
Reference(assembly);
}
catch // (Exception ex)
{
//ExplorerCore.LogWarning($"Excepting referencing '{name}': {ex.GetType()}.{ex.Message}");
}
}
}
}
}

View File

@ -0,0 +1,71 @@
using HarmonyLib;
using Mono.CSharp;
using System.Collections;
using System.Text;
using UnityExplorer.UI.Panels;
namespace UnityExplorer.CSConsole
{
public class ScriptInteraction : InteractiveBase
{
public static object CurrentTarget
=> InspectorManager.ActiveInspector?.Target;
public static object[] AllTargets
=> InspectorManager.Inspectors.Select(it => it.Target).ToArray();
public static void Log(object message)
=> ExplorerCore.Log(message);
public static void Inspect(object obj)
=> InspectorManager.Inspect(obj);
public static void Inspect(Type type)
=> InspectorManager.Inspect(type);
public static Coroutine Start(IEnumerator ienumerator)
=> RuntimeHelper.StartCoroutine(ienumerator);
public static void Stop(Coroutine coro)
=> RuntimeHelper.StopCoroutine(coro);
public static void Copy(object obj)
=> ClipboardPanel.Copy(obj);
public static object Paste()
=> ClipboardPanel.Current;
public static void GetUsing()
=> Log(Evaluator.GetUsing());
public static void GetVars()
{
string vars = Evaluator.GetVars()?.Trim();
if (string.IsNullOrEmpty(vars))
ExplorerCore.LogWarning("No variables seem to be defined!");
else
Log(vars);
}
public static void GetClasses()
{
if (AccessTools.Field(typeof(Evaluator), "source_file")
.GetValue(Evaluator) is CompilationSourceFile sourceFile
&& sourceFile.Containers.Any())
{
StringBuilder sb = new();
sb.Append($"There are {sourceFile.Containers.Count} defined classes:");
foreach (TypeDefinition type in sourceFile.Containers.Where(it => it is TypeDefinition))
{
sb.Append($"\n\n{type.MemberName.Name}:");
foreach (MemberCore member in type.Members)
sb.Append($"\n\t- {member.AttributeTargets}: \"{member.MemberName.Name}\" ({member.ModFlags})");
}
Log(sb.ToString());
}
else
ExplorerCore.LogWarning("No classes seem to be defined.");
}
}
}

View File

@ -0,0 +1,45 @@
using UnityExplorer.CacheObject.Views;
using UnityExplorer.Config;
namespace UnityExplorer.CacheObject
{
public class CacheConfigEntry : CacheObjectBase
{
public CacheConfigEntry(IConfigElement configElement)
{
this.RefConfigElement = configElement;
this.FallbackType = configElement.ElementType;
this.NameLabelText = $"<color=cyan>{configElement.Name}</color>" +
$"\r\n<color=grey><i>{configElement.Description}</i></color>";
this.NameLabelTextRaw = string.Empty;
configElement.OnValueChangedNotify += UpdateValueFromSource;
}
public IConfigElement RefConfigElement;
public override bool ShouldAutoEvaluate => true;
public override bool HasArguments => false;
public override bool CanWrite => true;
public void UpdateValueFromSource()
{
//if (RefConfigElement.BoxedValue.Equals(this.Value))
// return;
SetValueFromSource(RefConfigElement.BoxedValue);
if (this.CellView != null)
this.SetDataToCell(CellView);
}
public override void TrySetUserValue(object value)
{
this.Value = value;
RefConfigElement.BoxedValue = value;
}
protected override bool TryAutoEvaluateIfUnitialized(CacheObjectCell cell) => true;
}
}

View File

@ -0,0 +1,81 @@
using UnityExplorer.Inspectors;
namespace UnityExplorer.CacheObject
{
public class CacheConstructor : CacheMember
{
public ConstructorInfo CtorInfo { get; }
readonly Type typeForStructConstructor;
public override Type DeclaringType => typeForStructConstructor ?? CtorInfo.DeclaringType;
public override bool IsStatic => true;
public override bool ShouldAutoEvaluate => false;
public override bool CanWrite => false;
public CacheConstructor(ConstructorInfo ci)
{
this.CtorInfo = ci;
}
public CacheConstructor(Type typeForStructConstructor)
{
this.typeForStructConstructor = typeForStructConstructor;
}
public override void SetInspectorOwner(ReflectionInspector inspector, MemberInfo member)
{
Type ctorReturnType;
// if is parameterless struct ctor
if (typeForStructConstructor != null)
{
ctorReturnType = typeForStructConstructor;
this.Owner = inspector;
// eg. Vector3.Vector3()
this.NameLabelText = SignatureHighlighter.Parse(typeForStructConstructor, false);
NameLabelText += $".{NameLabelText}()";
this.NameForFiltering = SignatureHighlighter.RemoveHighlighting(NameLabelText);
this.NameLabelTextRaw = NameForFiltering;
return;
}
else
{
base.SetInspectorOwner(inspector, member);
Arguments = CtorInfo.GetParameters();
ctorReturnType = CtorInfo.DeclaringType;
}
if (ctorReturnType.IsGenericTypeDefinition)
GenericArguments = ctorReturnType.GetGenericArguments();
}
protected override object TryEvaluate()
{
try
{
Type returnType = DeclaringType;
if (returnType.IsGenericTypeDefinition)
returnType = DeclaringType.MakeGenericType(Evaluator.TryParseGenericArguments());
object ret;
if (HasArguments)
ret = Activator.CreateInstance(returnType, Evaluator.TryParseArguments());
else
ret = Activator.CreateInstance(returnType, ArgumentUtility.EmptyArgs);
LastException = null;
return ret;
}
catch (Exception ex)
{
LastException = ex;
return null;
}
}
protected override void TrySetValue(object value) => throw new NotImplementedException("You can't set a constructor");
}
}

View File

@ -0,0 +1,52 @@
using UnityExplorer.Inspectors;
namespace UnityExplorer.CacheObject
{
public class CacheField : CacheMember
{
public FieldInfo FieldInfo { get; internal set; }
public override Type DeclaringType => FieldInfo.DeclaringType;
public override bool IsStatic => FieldInfo.IsStatic;
public override bool CanWrite => m_canWrite ?? (bool)(m_canWrite = !(FieldInfo.IsLiteral && !FieldInfo.IsInitOnly));
private bool? m_canWrite;
public override bool ShouldAutoEvaluate => true;
public CacheField(FieldInfo fi)
{
this.FieldInfo = fi;
}
public override void SetInspectorOwner(ReflectionInspector inspector, MemberInfo member)
{
base.SetInspectorOwner(inspector, member);
}
protected override object TryEvaluate()
{
try
{
object ret = FieldInfo.GetValue(DeclaringInstance);
LastException = null;
return ret;
}
catch (Exception ex)
{
LastException = ex;
return null;
}
}
protected override void TrySetValue(object value)
{
try
{
FieldInfo.SetValue(DeclaringInstance, value);
}
catch (Exception ex)
{
ExplorerCore.LogWarning(ex);
}
}
}
}

View File

@ -0,0 +1,92 @@
using UnityExplorer.CacheObject.IValues;
using UnityExplorer.CacheObject.Views;
namespace UnityExplorer.CacheObject
{
public class CacheKeyValuePair : CacheObjectBase
{
//public InteractiveList CurrentList { get; set; }
public int DictIndex;
public object DictKey;
public object DisplayedKey;
public bool KeyInputWanted;
public bool InspectWanted;
public string KeyLabelText;
public string KeyInputText;
public string KeyInputTypeText;
public float DesiredKeyWidth;
public float DesiredValueWidth;
public override bool ShouldAutoEvaluate => true;
public override bool HasArguments => false;
public override bool CanWrite => Owner.CanWrite;
public void SetDictOwner(InteractiveDictionary dict, int index)
{
this.Owner = dict;
this.DictIndex = index;
}
public void SetKey(object key)
{
this.DictKey = key;
this.DisplayedKey = key.TryCast();
Type type = DisplayedKey.GetType();
if (ParseUtility.CanParse(type))
{
KeyInputWanted = true;
KeyInputText = ParseUtility.ToStringForInput(DisplayedKey, type);
KeyInputTypeText = SignatureHighlighter.Parse(type, false);
}
else
{
KeyInputWanted = false;
InspectWanted = type != typeof(bool) && !type.IsEnum;
KeyLabelText = ToStringUtility.ToStringWithType(DisplayedKey, type, true);
}
}
public override void SetDataToCell(CacheObjectCell cell)
{
base.SetDataToCell(cell);
CacheKeyValuePairCell kvpCell = cell as CacheKeyValuePairCell;
kvpCell.NameLabel.text = $"{DictIndex}:";
kvpCell.HiddenNameLabel.Text = "";
kvpCell.Image.color = DictIndex % 2 == 0 ? CacheListEntryCell.EvenColor : CacheListEntryCell.OddColor;
if (KeyInputWanted)
{
kvpCell.KeyInputField.UIRoot.SetActive(true);
kvpCell.KeyInputTypeLabel.gameObject.SetActive(true);
kvpCell.KeyLabel.gameObject.SetActive(false);
kvpCell.KeyInspectButton.Component.gameObject.SetActive(false);
kvpCell.KeyInputField.Text = KeyInputText;
kvpCell.KeyInputTypeLabel.text = KeyInputTypeText;
}
else
{
kvpCell.KeyInputField.UIRoot.SetActive(false);
kvpCell.KeyInputTypeLabel.gameObject.SetActive(false);
kvpCell.KeyLabel.gameObject.SetActive(true);
kvpCell.KeyInspectButton.Component.gameObject.SetActive(InspectWanted);
kvpCell.KeyLabel.text = KeyLabelText;
}
}
public override void TrySetUserValue(object value)
{
(Owner as InteractiveDictionary).TrySetValueToKey(DictKey, value, DictIndex);
}
protected override bool TryAutoEvaluateIfUnitialized(CacheObjectCell cell) => true;
}
}

View File

@ -0,0 +1,38 @@
using UnityExplorer.CacheObject.IValues;
using UnityExplorer.CacheObject.Views;
namespace UnityExplorer.CacheObject
{
public class CacheListEntry : CacheObjectBase
{
public int ListIndex;
public override bool ShouldAutoEvaluate => true;
public override bool HasArguments => false;
public override bool CanWrite => Owner?.CanWrite ?? false;
public void SetListOwner(InteractiveList list, int listIndex)
{
this.Owner = list;
this.ListIndex = listIndex;
}
public override void SetDataToCell(CacheObjectCell cell)
{
base.SetDataToCell(cell);
CacheListEntryCell listCell = cell as CacheListEntryCell;
listCell.NameLabel.text = $"{ListIndex}:";
listCell.HiddenNameLabel.Text = "";
listCell.Image.color = ListIndex % 2 == 0 ? CacheListEntryCell.EvenColor : CacheListEntryCell.OddColor;
}
public override void TrySetUserValue(object value)
{
(Owner as InteractiveList).TrySetValueToIndex(value, this.ListIndex);
}
protected override bool TryAutoEvaluateIfUnitialized(CacheObjectCell cell) => true;
}
}

View File

@ -0,0 +1,159 @@
using UnityExplorer.CacheObject.Views;
using UnityExplorer.Inspectors;
using UnityExplorer.UI.Widgets;
using UniverseLib.UI.ObjectPool;
namespace UnityExplorer.CacheObject
{
public abstract class CacheMember : CacheObjectBase
{
public abstract Type DeclaringType { get; }
public string NameForFiltering { get; protected set; }
public object DeclaringInstance => IsStatic ? null : (m_declaringInstance ??= Owner.Target.TryCast(DeclaringType));
private object m_declaringInstance;
public abstract bool IsStatic { get; }
public override bool HasArguments => Arguments?.Length > 0 || GenericArguments.Length > 0;
public ParameterInfo[] Arguments { get; protected set; } = new ParameterInfo[0];
public Type[] GenericArguments { get; protected set; } = ArgumentUtility.EmptyTypes;
public EvaluateWidget Evaluator { get; protected set; }
public bool Evaluating => Evaluator != null && Evaluator.UIRoot.activeSelf;
public virtual void SetInspectorOwner(ReflectionInspector inspector, MemberInfo member)
{
this.Owner = inspector;
this.NameLabelText = this switch
{
CacheMethod => SignatureHighlighter.ParseMethod(member as MethodInfo),
CacheConstructor => SignatureHighlighter.ParseConstructor(member as ConstructorInfo),
_ => SignatureHighlighter.Parse(member.DeclaringType, false, member),
};
this.NameForFiltering = SignatureHighlighter.RemoveHighlighting(NameLabelText);
this.NameLabelTextRaw = NameForFiltering;
}
public override void ReleasePooledObjects()
{
base.ReleasePooledObjects();
if (this.Evaluator != null)
{
this.Evaluator.OnReturnToPool();
Pool<EvaluateWidget>.Return(this.Evaluator);
this.Evaluator = null;
}
}
public override void UnlinkFromView()
{
if (this.Evaluator != null)
this.Evaluator.UIRoot.transform.SetParent(Pool<EvaluateWidget>.Instance.InactiveHolder.transform, false);
base.UnlinkFromView();
}
protected abstract object TryEvaluate();
protected abstract void TrySetValue(object value);
/// <summary>
/// Evaluate is called when first shown (if ShouldAutoEvaluate), or else when Evaluate button is clicked, or auto-updated.
/// </summary>
public void Evaluate()
{
SetValueFromSource(TryEvaluate());
}
/// <summary>
/// Called when user presses the Evaluate button.
/// </summary>
public void EvaluateAndSetCell()
{
Evaluate();
if (CellView != null)
SetDataToCell(CellView);
}
public override void TrySetUserValue(object value)
{
TrySetValue(value);
Evaluate();
}
protected override void SetValueState(CacheObjectCell cell, ValueStateArgs args)
{
base.SetValueState(cell, args);
}
private static readonly Color evalEnabledColor = new(0.15f, 0.25f, 0.15f);
private static readonly Color evalDisabledColor = new(0.15f, 0.15f, 0.15f);
protected override bool TryAutoEvaluateIfUnitialized(CacheObjectCell objectcell)
{
CacheMemberCell cell = objectcell as CacheMemberCell;
cell.EvaluateHolder.SetActive(!ShouldAutoEvaluate);
if (!ShouldAutoEvaluate)
{
cell.EvaluateButton.Component.gameObject.SetActive(true);
if (HasArguments)
{
if (!Evaluating)
cell.EvaluateButton.ButtonText.text = $"Evaluate ({Arguments.Length + GenericArguments.Length})";
else
{
cell.EvaluateButton.ButtonText.text = "Hide";
Evaluator.UIRoot.transform.SetParent(cell.EvaluateHolder.transform, false);
RuntimeHelper.SetColorBlock(cell.EvaluateButton.Component, evalEnabledColor, evalEnabledColor * 1.3f);
}
}
else
cell.EvaluateButton.ButtonText.text = "Evaluate";
if (!Evaluating)
RuntimeHelper.SetColorBlock(cell.EvaluateButton.Component, evalDisabledColor, evalDisabledColor * 1.3f);
}
if (State == ValueState.NotEvaluated && !ShouldAutoEvaluate)
{
SetValueState(cell, ValueStateArgs.Default);
cell.RefreshSubcontentButton();
return false;
}
if (State == ValueState.NotEvaluated)
Evaluate();
return true;
}
public void OnEvaluateClicked()
{
if (!HasArguments)
{
EvaluateAndSetCell();
}
else
{
if (Evaluator == null)
{
this.Evaluator = Pool<EvaluateWidget>.Borrow();
Evaluator.OnBorrowedFromPool(this);
Evaluator.UIRoot.transform.SetParent((CellView as CacheMemberCell).EvaluateHolder.transform, false);
TryAutoEvaluateIfUnitialized(CellView);
}
else
{
if (Evaluator.UIRoot.activeSelf)
Evaluator.UIRoot.SetActive(false);
else
Evaluator.UIRoot.SetActive(true);
TryAutoEvaluateIfUnitialized(CellView);
}
}
}
}
}

View File

@ -0,0 +1,160 @@
using HarmonyLib;
using UnityExplorer.Inspectors;
using UnityExplorer.Runtime;
namespace UnityExplorer.CacheObject
{
public static class CacheMemberFactory
{
public static List<CacheMember> GetCacheMembers(Type type, ReflectionInspector inspector)
{
//var list = new List<CacheMember>();
HashSet<string> cachedSigs = new();
List<CacheMember> props = new();
List<CacheMember> fields = new();
List<CacheMember> ctors = new();
List<CacheMember> methods = new();
Type[] types = ReflectionUtility.GetAllBaseTypes(type);
BindingFlags flags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static;
if (!inspector.StaticOnly)
flags |= BindingFlags.Instance;
if (!type.IsAbstract)
{
// Get non-static constructors of the main type.
// There's no reason to get the static cctor, it will be invoked when we inspect the class.
// Also no point getting ctors on inherited types.
foreach (ConstructorInfo ctor in type.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
TryCacheMember(ctor, ctors, cachedSigs, type, inspector);
// structs always have a parameterless constructor
if (type.IsValueType)
{
CacheConstructor cached = new(type);
cached.SetFallbackType(type);
cached.SetInspectorOwner(inspector, null);
ctors.Add(cached);
}
}
foreach (Type declaringType in types)
{
foreach (PropertyInfo prop in declaringType.GetProperties(flags))
if (prop.DeclaringType == declaringType)
TryCacheMember(prop, props, cachedSigs, declaringType, inspector);
foreach (FieldInfo field in declaringType.GetFields(flags))
if (field.DeclaringType == declaringType)
TryCacheMember(field, fields, cachedSigs, declaringType, inspector);
foreach (MethodInfo method in declaringType.GetMethods(flags))
if (method.DeclaringType == declaringType)
TryCacheMember(method, methods, cachedSigs, declaringType, inspector);
}
List<CacheMember> sorted = new();
sorted.AddRange(props.OrderBy(it => Array.IndexOf(types, it.DeclaringType))
.ThenBy(it => it.NameForFiltering));
sorted.AddRange(fields.OrderBy(it => Array.IndexOf(types, it.DeclaringType))
.ThenBy(it => it.NameForFiltering));
sorted.AddRange(ctors.OrderBy(it => Array.IndexOf(types, it.DeclaringType))
.ThenBy(it => it.NameForFiltering));
sorted.AddRange(methods.OrderBy(it => Array.IndexOf(types, it.DeclaringType))
.ThenBy(it => it.NameForFiltering));
return sorted;
}
static void TryCacheMember<T>(MemberInfo member, List<T> list, HashSet<string> cachedSigs,
Type declaringType, ReflectionInspector inspector, bool ignorePropertyMethodInfos = true)
where T : CacheMember
{
try
{
if (UERuntimeHelper.IsBlacklisted(member))
return;
string sig = member switch
{
MethodBase mb => mb.FullDescription(), // (method or constructor)
PropertyInfo or FieldInfo => $"{member.DeclaringType.FullDescription()}.{member.Name}",
_ => throw new NotImplementedException(),
};
if (cachedSigs.Contains(sig))
return;
// ExplorerCore.Log($"Trying to cache member {sig}... ({member.MemberType})");
CacheMember cached;
Type returnType;
switch (member.MemberType)
{
case MemberTypes.Constructor:
{
ConstructorInfo ci = member as ConstructorInfo;
cached = new CacheConstructor(ci);
returnType = ci.DeclaringType;
}
break;
case MemberTypes.Method:
{
MethodInfo mi = member as MethodInfo;
if (ignorePropertyMethodInfos
&& (mi.Name.StartsWith("get_") || mi.Name.StartsWith("set_")))
return;
cached = new CacheMethod(mi);
returnType = mi.ReturnType;
break;
}
case MemberTypes.Property:
{
PropertyInfo pi = member as PropertyInfo;
if (!pi.CanRead && pi.CanWrite)
{
// write-only property, cache the set method instead.
MethodInfo setMethod = pi.GetSetMethod(true);
if (setMethod != null)
TryCacheMember(setMethod, list, cachedSigs, declaringType, inspector, false);
return;
}
cached = new CacheProperty(pi);
returnType = pi.PropertyType;
break;
}
case MemberTypes.Field:
{
FieldInfo fi = member as FieldInfo;
cached = new CacheField(fi);
returnType = fi.FieldType;
break;
}
default:
throw new NotImplementedException();
}
cachedSigs.Add(sig);
cached.SetFallbackType(returnType);
cached.SetInspectorOwner(inspector, member);
list.Add((T)cached);
}
catch (Exception e)
{
ExplorerCore.LogWarning($"Exception caching member {member.DeclaringType.FullName}.{member.Name}!");
ExplorerCore.Log(e);
}
}
}
}

View File

@ -0,0 +1,53 @@
using UnityExplorer.Inspectors;
namespace UnityExplorer.CacheObject
{
public class CacheMethod : CacheMember
{
public MethodInfo MethodInfo { get; }
public override Type DeclaringType => MethodInfo.DeclaringType;
public override bool CanWrite => false;
public override bool IsStatic => MethodInfo.IsStatic;
public override bool ShouldAutoEvaluate => false;
public CacheMethod(MethodInfo mi)
{
this.MethodInfo = mi;
}
public override void SetInspectorOwner(ReflectionInspector inspector, MemberInfo member)
{
base.SetInspectorOwner(inspector, member);
Arguments = MethodInfo.GetParameters();
if (MethodInfo.IsGenericMethod)
GenericArguments = MethodInfo.GetGenericArguments();
}
protected override object TryEvaluate()
{
try
{
MethodInfo methodInfo = MethodInfo;
if (methodInfo.IsGenericMethod)
methodInfo = MethodInfo.MakeGenericMethod(Evaluator.TryParseGenericArguments());
object ret;
if (HasArguments)
ret = methodInfo.Invoke(DeclaringInstance, Evaluator.TryParseArguments());
else
ret = methodInfo.Invoke(DeclaringInstance, ArgumentUtility.EmptyArgs);
LastException = null;
return ret;
}
catch (Exception ex)
{
LastException = ex;
return null;
}
}
protected override void TrySetValue(object value) => throw new NotImplementedException("You can't set a method");
}
}

View File

@ -0,0 +1,488 @@
using System.Collections;
using UnityExplorer.CacheObject.IValues;
using UnityExplorer.CacheObject.Views;
using UniverseLib.UI;
using UniverseLib.UI.ObjectPool;
namespace UnityExplorer.CacheObject
{
public enum ValueState
{
NotEvaluated,
Exception,
Boolean,
Number,
String,
Enum,
Collection,
Dictionary,
ValueStruct,
Color,
Unsupported
}
public abstract class CacheObjectBase
{
public ICacheObjectController Owner { get; set; }
public CacheObjectCell CellView { get; internal set; }
public object Value { get; protected set; }
public Type FallbackType { get; protected set; }
public ValueState State { get; set; }
public Exception LastException { get; protected set; }
bool valueIsNull;
Type currentValueType;
// InteractiveValues
public InteractiveValue IValue { get; private set; }
public Type CurrentIValueType { get; private set; }
public bool SubContentShowWanted { get; private set; }
// UI
public string NameLabelText { get; protected set; }
public string NameLabelTextRaw { get; protected set; }
public string ValueLabelText { get; protected set; }
// Abstract
public abstract bool ShouldAutoEvaluate { get; }
public abstract bool HasArguments { get; }
public abstract bool CanWrite { get; }
protected const string NOT_YET_EVAL = "<color=grey>Not yet evaluated</color>";
public virtual void SetFallbackType(Type fallbackType)
{
this.FallbackType = fallbackType;
this.ValueLabelText = GetValueLabel();
}
public virtual void SetView(CacheObjectCell cellView)
{
this.CellView = cellView;
cellView.Occupant = this;
}
public virtual void UnlinkFromView()
{
if (this.CellView == null)
return;
this.CellView.Occupant = null;
this.CellView = null;
if (this.IValue != null)
this.IValue.UIRoot.transform.SetParent(InactiveIValueHolder.transform, false);
}
public virtual void ReleasePooledObjects()
{
if (this.IValue != null)
ReleaseIValue();
if (this.CellView != null)
UnlinkFromView();
}
// Updating and applying values
// The only method which sets the CacheObjectBase.Value
public virtual void SetValueFromSource(object value)
{
this.Value = value;
if (!Value.IsNullOrDestroyed())
Value = Value.TryCast();
ProcessOnEvaluate();
if (this.IValue != null)
{
if (SubContentShowWanted)
this.IValue.SetValue(Value);
else
IValue.PendingValueWanted = true;
}
}
public void SetUserValue(object value)
{
value = value.TryCast(FallbackType);
TrySetUserValue(value);
if (CellView != null)
SetDataToCell(CellView);
// If the owner's ParentCacheObject is set, we are setting the value of an inspected struct.
// Set the inspector target as the value back to that parent.
if (Owner.ParentCacheObject != null)
Owner.ParentCacheObject.SetUserValue(Owner.Target);
}
public abstract void TrySetUserValue(object value);
protected virtual void ProcessOnEvaluate()
{
ValueState prevState = State;
if (LastException != null)
{
valueIsNull = true;
currentValueType = FallbackType;
State = ValueState.Exception;
}
else if (Value.IsNullOrDestroyed())
{
valueIsNull = true;
State = GetStateForType(FallbackType);
}
else
{
valueIsNull = false;
State = GetStateForType(Value.GetActualType());
}
if (IValue != null)
{
// If we changed states (always needs IValue change)
// or if the value is null, and the fallback type isnt string (we always want to edit strings).
if (State != prevState || (State != ValueState.String && State != ValueState.Exception && Value.IsNullOrDestroyed()))
{
// need to return IValue
ReleaseIValue();
SubContentShowWanted = false;
}
}
// Set label text
this.ValueLabelText = GetValueLabel();
}
public ValueState GetStateForType(Type type)
{
if (currentValueType == type && (State != ValueState.Exception || LastException != null))
return State;
currentValueType = type;
if (type == typeof(bool))
return ValueState.Boolean;
else if (type.IsPrimitive || type == typeof(decimal))
return ValueState.Number;
else if (type == typeof(string))
return ValueState.String;
else if (type.IsEnum)
return ValueState.Enum;
else if (type == typeof(Color) || type == typeof(Color32))
return ValueState.Color;
else if (InteractiveValueStruct.SupportsType(type))
return ValueState.ValueStruct;
else if (ReflectionUtility.IsDictionary(type))
return ValueState.Dictionary;
else if (!typeof(Transform).IsAssignableFrom(type) && ReflectionUtility.IsEnumerable(type))
return ValueState.Collection;
else
return ValueState.Unsupported;
}
protected string GetValueLabel()
{
string label = string.Empty;
switch (State)
{
case ValueState.NotEvaluated:
return $"<i>{NOT_YET_EVAL} ({SignatureHighlighter.Parse(FallbackType, true)})</i>";
case ValueState.Exception:
return $"<i><color=#eb4034>{LastException.ReflectionExToString()}</color></i>";
// bool and number dont want the label for the value at all
case ValueState.Boolean:
case ValueState.Number:
return null;
// and valuestruct also doesnt want it if we can parse it
case ValueState.ValueStruct:
if (ParseUtility.CanParse(currentValueType))
return null;
break;
// string wants it trimmed to max 200 chars
case ValueState.String:
if (!valueIsNull)
return $"\"{ToStringUtility.PruneString(Value as string, 200, 5)}\"";
break;
// try to prefix the count of the collection for lists and dicts
case ValueState.Collection:
if (!valueIsNull)
{
if (Value is IList iList)
label = $"[{iList.Count}] ";
else if (Value is ICollection iCol)
label = $"[{iCol.Count}] ";
else
label = "[?] ";
}
break;
case ValueState.Dictionary:
if (!valueIsNull)
{
if (Value is IDictionary iDict)
label = $"[{iDict.Count}] ";
else
label = "[?] ";
}
break;
}
// Cases which dont return will append to ToStringWithType
return label += ToStringUtility.ToStringWithType(Value, FallbackType, true);
}
// Setting cell state from our model
/// <summary>Return false if SetCell should abort, true if it should continue.</summary>
protected abstract bool TryAutoEvaluateIfUnitialized(CacheObjectCell cell);
public virtual void SetDataToCell(CacheObjectCell cell)
{
cell.NameLabel.text = NameLabelText;
if (cell.HiddenNameLabel != null)
cell.HiddenNameLabel.Text = NameLabelTextRaw ?? string.Empty;
cell.ValueLabel.gameObject.SetActive(true);
cell.SubContentHolder.gameObject.SetActive(SubContentShowWanted);
if (IValue != null)
{
IValue.UIRoot.transform.SetParent(cell.SubContentHolder.transform, false);
IValue.SetLayout();
}
bool evaluated = TryAutoEvaluateIfUnitialized(cell);
if (cell.CopyButton != null)
{
bool canCopy = State != ValueState.NotEvaluated && State != ValueState.Exception;
cell.CopyButton.Component.gameObject.SetActive(canCopy);
cell.PasteButton.Component.gameObject.SetActive(canCopy && this.CanWrite);
}
if (!evaluated)
return;
// The following only executes if the object has evaluated.
// For members and properties with args, they will return by default now.
switch (State)
{
case ValueState.Exception:
SetValueState(cell, new(true, subContentButtonActive: true));
break;
case ValueState.Boolean:
SetValueState(cell, new(false, toggleActive: true, applyActive: CanWrite));
break;
case ValueState.Number:
SetValueState(cell, new(false, typeLabelActive: true, inputActive: true, applyActive: CanWrite));
break;
case ValueState.String:
if (valueIsNull)
SetValueState(cell, new(true, subContentButtonActive: true));
else
SetValueState(cell, new(true, false, SignatureHighlighter.StringOrange, subContentButtonActive: true));
break;
case ValueState.Enum:
SetValueState(cell, new(true, subContentButtonActive: CanWrite));
break;
case ValueState.Color:
case ValueState.ValueStruct:
if (ParseUtility.CanParse(currentValueType))
SetValueState(cell, new(false, false, null, true, false, true, CanWrite, true, true));
else
SetValueState(cell, new(true, inspectActive: true, subContentButtonActive: true));
break;
case ValueState.Collection:
case ValueState.Dictionary:
SetValueState(cell, new(true, inspectActive: !valueIsNull, subContentButtonActive: !valueIsNull));
break;
case ValueState.Unsupported:
SetValueState(cell, new(true, inspectActive: !valueIsNull));
break;
}
cell.RefreshSubcontentButton();
}
protected virtual void SetValueState(CacheObjectCell cell, ValueStateArgs args)
{
// main value label
if (args.valueActive)
{
cell.ValueLabel.text = ValueLabelText;
cell.ValueLabel.supportRichText = args.valueRichText;
cell.ValueLabel.color = args.valueColor;
}
else
cell.ValueLabel.text = "";
// Type label (for primitives)
cell.TypeLabel.gameObject.SetActive(args.typeLabelActive);
if (args.typeLabelActive)
cell.TypeLabel.text = SignatureHighlighter.Parse(currentValueType, false);
// toggle for bools
cell.Toggle.gameObject.SetActive(args.toggleActive);
if (args.toggleActive)
{
cell.Toggle.interactable = CanWrite;
cell.Toggle.isOn = (bool)Value;
cell.ToggleText.text = Value.ToString();
}
// inputfield for numbers
cell.InputField.UIRoot.SetActive(args.inputActive);
if (args.inputActive)
{
cell.InputField.Text = ParseUtility.ToStringForInput(Value, currentValueType);
cell.InputField.Component.readOnly = !CanWrite;
}
// apply for bool and numbers
cell.ApplyButton.Component.gameObject.SetActive(args.applyActive);
// Inspect button only if last value not null.
if (cell.InspectButton != null)
cell.InspectButton.Component.gameObject.SetActive(args.inspectActive && !valueIsNull);
// set subcontent button if needed, and for null strings and exceptions
cell.SubContentButton.Component.gameObject.SetActive(
args.subContentButtonActive
&& (!valueIsNull || State == ValueState.String || State == ValueState.Exception));
}
// CacheObjectCell Apply
public virtual void OnCellApplyClicked()
{
if (State == ValueState.Boolean)
SetUserValue(this.CellView.Toggle.isOn);
else
{
if (ParseUtility.TryParse(CellView.InputField.Text, currentValueType, out object value, out Exception ex))
{
SetUserValue(value);
}
else
{
ExplorerCore.LogWarning("Unable to parse input!");
if (ex != null)
ExplorerCore.Log(ex.ReflectionExToString());
}
}
SetDataToCell(this.CellView);
}
// IValues
public virtual void OnCellSubContentToggle()
{
if (this.IValue == null)
{
Type ivalueType = InteractiveValue.GetIValueTypeForState(State);
if (ivalueType == null)
return;
IValue = (InteractiveValue)Pool.Borrow(ivalueType);
CurrentIValueType = ivalueType;
IValue.OnBorrowed(this);
IValue.SetValue(this.Value);
IValue.UIRoot.transform.SetParent(CellView.SubContentHolder.transform, false);
CellView.SubContentHolder.SetActive(true);
SubContentShowWanted = true;
// update our cell after creating the ivalue (the value may have updated, make sure its consistent)
this.ProcessOnEvaluate();
this.SetDataToCell(this.CellView);
}
else
{
SubContentShowWanted = !SubContentShowWanted;
CellView.SubContentHolder.SetActive(SubContentShowWanted);
if (SubContentShowWanted && IValue.PendingValueWanted)
{
IValue.PendingValueWanted = false;
this.ProcessOnEvaluate();
this.SetDataToCell(this.CellView);
IValue.SetValue(this.Value);
}
}
CellView.RefreshSubcontentButton();
}
public virtual void ReleaseIValue()
{
if (IValue == null)
return;
IValue.ReleaseFromOwner();
Pool.Return(CurrentIValueType, IValue);
IValue = null;
}
internal static GameObject InactiveIValueHolder
{
get
{
if (!inactiveIValueHolder)
{
inactiveIValueHolder = new GameObject("Temp_IValue_Holder");
GameObject.DontDestroyOnLoad(inactiveIValueHolder);
inactiveIValueHolder.hideFlags = HideFlags.HideAndDontSave;
inactiveIValueHolder.transform.parent = UniversalUI.PoolHolder.transform;
inactiveIValueHolder.SetActive(false);
}
return inactiveIValueHolder;
}
}
private static GameObject inactiveIValueHolder;
// Value state args helper
public struct ValueStateArgs
{
public static ValueStateArgs Default { get; } = new(true);
public Color valueColor;
public bool valueActive, valueRichText, typeLabelActive, toggleActive, inputActive, applyActive, inspectActive, subContentButtonActive;
public ValueStateArgs(bool valueActive = true,
bool valueRichText = true,
Color? valueColor = null,
bool typeLabelActive = false,
bool toggleActive = false,
bool inputActive = false,
bool applyActive = false,
bool inspectActive = false,
bool subContentButtonActive = false)
{
this.valueActive = valueActive;
this.valueRichText = valueRichText;
this.valueColor = valueColor == null ? Color.white : (Color)valueColor;
this.typeLabelActive = typeLabelActive;
this.toggleActive = toggleActive;
this.inputActive = inputActive;
this.applyActive = applyActive;
this.inspectActive = inspectActive;
this.subContentButtonActive = subContentButtonActive;
}
}
}
}

View File

@ -0,0 +1,66 @@
using UnityExplorer.Inspectors;
namespace UnityExplorer.CacheObject
{
public class CacheProperty : CacheMember
{
public PropertyInfo PropertyInfo { get; internal set; }
public override Type DeclaringType => PropertyInfo.DeclaringType;
public override bool CanWrite => PropertyInfo.CanWrite;
public override bool IsStatic => m_isStatic ?? (bool)(m_isStatic = PropertyInfo.GetAccessors(true)[0].IsStatic);
private bool? m_isStatic;
public override bool ShouldAutoEvaluate => !HasArguments;
public CacheProperty(PropertyInfo pi)
{
this.PropertyInfo = pi;
}
public override void SetInspectorOwner(ReflectionInspector inspector, MemberInfo member)
{
base.SetInspectorOwner(inspector, member);
Arguments = PropertyInfo.GetIndexParameters();
}
protected override object TryEvaluate()
{
try
{
object ret;
if (HasArguments)
ret = PropertyInfo.GetValue(DeclaringInstance, this.Evaluator.TryParseArguments());
else
ret = PropertyInfo.GetValue(DeclaringInstance, null);
LastException = null;
return ret;
}
catch (Exception ex)
{
LastException = ex;
return null;
}
}
protected override void TrySetValue(object value)
{
if (!CanWrite)
return;
try
{
bool _static = PropertyInfo.GetAccessors(true)[0].IsStatic;
if (HasArguments)
PropertyInfo.SetValue(DeclaringInstance, value, Evaluator.TryParseArguments());
else
PropertyInfo.SetValue(DeclaringInstance, value, null);
}
catch (Exception ex)
{
ExplorerCore.LogWarning(ex);
}
}
}
}

View File

@ -0,0 +1,47 @@
using System.Collections;
using UnityExplorer.CacheObject.Views;
namespace UnityExplorer.CacheObject
{
public interface ICacheObjectController
{
CacheObjectBase ParentCacheObject { get; }
object Target { get; }
Type TargetType { get; }
bool CanWrite { get; }
}
public static class CacheObjectControllerHelper
{
// Helper so that this doesn't need to be copy+pasted between each implementation of the interface
public static void SetCell(CacheObjectCell cell, int index, IList cachedEntries, Action<CacheObjectCell> onDataSetToCell)
{
if (index < 0 || index >= cachedEntries.Count)
{
if (cell.Occupant != null)
cell.Occupant.UnlinkFromView();
cell.Disable();
return;
}
CacheObjectBase entry = (CacheObjectBase)cachedEntries[index];
if (entry.CellView != null && entry.CellView != cell)
entry.UnlinkFromView();
if (cell.Occupant != null && cell.Occupant != entry)
cell.Occupant.UnlinkFromView();
if (entry.CellView != cell)
entry.SetView(cell);
entry.SetDataToCell(cell);
onDataSetToCell?.Invoke(cell);
}
}
}

View File

@ -0,0 +1,197 @@
using UniverseLib.UI;
using UniverseLib.UI.Models;
namespace UnityExplorer.CacheObject.IValues
{
public class InteractiveColor : InteractiveValue
{
public bool IsValueColor32;
public Color EditedColor;
private Image colorImage;
private readonly InputFieldRef[] inputs = new InputFieldRef[4];
private readonly Slider[] sliders = new Slider[4];
private ButtonRef applyButton;
private static readonly string[] fieldNames = new[] { "R", "G", "B", "A" };
public override void OnBorrowed(CacheObjectBase owner)
{
base.OnBorrowed(owner);
applyButton.Component.gameObject.SetActive(owner.CanWrite);
foreach (Slider slider in sliders)
slider.interactable = owner.CanWrite;
foreach (InputFieldRef input in inputs)
input.Component.readOnly = !owner.CanWrite;
}
// owner setting value to this
public override void SetValue(object value)
{
OnOwnerSetValue(value);
}
private void OnOwnerSetValue(object value)
{
if (value is Color32 c32)
{
IsValueColor32 = true;
EditedColor = c32;
inputs[0].Text = c32.r.ToString();
inputs[1].Text = c32.g.ToString();
inputs[2].Text = c32.b.ToString();
inputs[3].Text = c32.a.ToString();
foreach (Slider slider in sliders)
slider.maxValue = 255;
}
else
{
IsValueColor32 = false;
EditedColor = (Color)value;
inputs[0].Text = EditedColor.r.ToString();
inputs[1].Text = EditedColor.g.ToString();
inputs[2].Text = EditedColor.b.ToString();
inputs[3].Text = EditedColor.a.ToString();
foreach (Slider slider in sliders)
slider.maxValue = 1;
}
if (colorImage)
colorImage.color = EditedColor;
}
// setting value to owner
public void SetValueToOwner()
{
if (IsValueColor32)
CurrentOwner.SetUserValue((Color32)EditedColor);
else
CurrentOwner.SetUserValue(EditedColor);
}
private void SetColorField(float val, int fieldIndex)
{
switch (fieldIndex)
{
case 0: EditedColor.r = val; break;
case 1: EditedColor.g = val; break;
case 2: EditedColor.b = val; break;
case 3: EditedColor.a = val; break;
}
if (colorImage)
colorImage.color = EditedColor;
}
private void OnInputChanged(string val, int fieldIndex)
{
try
{
float f;
if (IsValueColor32)
{
byte value = byte.Parse(val);
sliders[fieldIndex].value = value;
f = (float)((decimal)value / 255);
}
else
{
f = float.Parse(val);
sliders[fieldIndex].value = f;
}
SetColorField(f, fieldIndex);
}
catch (ArgumentException) { } // ignore bad user input
catch (FormatException) { }
catch (OverflowException) { }
catch (Exception ex)
{
ExplorerCore.LogWarning("InteractiveColor OnInput: " + ex.ToString());
}
}
private void OnSliderValueChanged(float val, int fieldIndex)
{
try
{
if (IsValueColor32)
{
inputs[fieldIndex].Text = ((byte)val).ToString();
val /= 255f;
}
else
{
inputs[fieldIndex].Text = val.ToString();
}
SetColorField(val, fieldIndex);
}
catch (Exception ex)
{
ExplorerCore.LogWarning("InteractiveColor OnSlider: " + ex.ToString());
}
}
// UI Construction
public override GameObject CreateContent(GameObject parent)
{
UIRoot = UIFactory.CreateVerticalGroup(parent, "InteractiveColor", false, false, true, true, 3, new Vector4(4, 4, 4, 4),
new Color(0.06f, 0.06f, 0.06f));
// hori group
GameObject horiGroup = UIFactory.CreateHorizontalGroup(UIRoot, "ColorEditor", false, false, true, true, 5,
default, new Color(1, 1, 1, 0), TextAnchor.MiddleLeft);
// sliders / inputs
GameObject grid = UIFactory.CreateGridGroup(horiGroup, "Grid", new Vector2(140, 25), new Vector2(2, 2), new Color(1, 1, 1, 0));
UIFactory.SetLayoutElement(grid, minWidth: 580, minHeight: 25, flexibleWidth: 0);
for (int i = 0; i < 4; i++)
AddEditorRow(i, grid);
// apply button
applyButton = UIFactory.CreateButton(horiGroup, "ApplyButton", "Apply", new Color(0.2f, 0.26f, 0.2f));
UIFactory.SetLayoutElement(applyButton.Component.gameObject, minHeight: 25, minWidth: 90);
applyButton.OnClick += SetValueToOwner;
// image of color
GameObject imgObj = UIFactory.CreateUIObject("ColorImageHelper", horiGroup);
UIFactory.SetLayoutElement(imgObj, minHeight: 25, minWidth: 50, flexibleWidth: 50);
colorImage = imgObj.AddComponent<Image>();
return UIRoot;
}
internal void AddEditorRow(int index, GameObject groupObj)
{
GameObject row = UIFactory.CreateHorizontalGroup(groupObj, "EditorRow_" + fieldNames[index],
false, true, true, true, 5, default, new Color(1, 1, 1, 0));
Text label = UIFactory.CreateLabel(row, "RowLabel", $"{fieldNames[index]}:", TextAnchor.MiddleRight, Color.cyan);
UIFactory.SetLayoutElement(label.gameObject, minWidth: 17, flexibleWidth: 0, minHeight: 25);
InputFieldRef input = UIFactory.CreateInputField(row, "Input", "...");
UIFactory.SetLayoutElement(input.UIRoot, minWidth: 40, minHeight: 25, flexibleHeight: 0);
inputs[index] = input;
input.OnValueChanged += (string val) => { OnInputChanged(val, index); };
GameObject sliderObj = UIFactory.CreateSlider(row, "Slider", out Slider slider);
sliders[index] = slider;
UIFactory.SetLayoutElement(sliderObj, minHeight: 25, minWidth: 70, flexibleWidth: 999, flexibleHeight: 0);
slider.minValue = 0;
slider.maxValue = 1;
slider.onValueChanged.AddListener((float val) => { OnSliderValueChanged(val, index); });
}
}
}

View File

@ -0,0 +1,241 @@
using System.Collections;
using UnityExplorer.CacheObject.Views;
using UnityExplorer.UI.Panels;
using UniverseLib.UI;
using UniverseLib.UI.Widgets.ScrollView;
namespace UnityExplorer.CacheObject.IValues
{
public class InteractiveDictionary : InteractiveValue, ICellPoolDataSource<CacheKeyValuePairCell>, ICacheObjectController
{
CacheObjectBase ICacheObjectController.ParentCacheObject => this.CurrentOwner;
object ICacheObjectController.Target => this.CurrentOwner.Value;
public Type TargetType { get; private set; }
public override bool CanWrite => base.CanWrite && RefIDictionary != null && !RefIDictionary.IsReadOnly;
public Type KeysType;
public Type ValuesType;
public IDictionary RefIDictionary;
public int ItemCount => cachedEntries.Count;
private readonly List<CacheKeyValuePair> cachedEntries = new();
public ScrollPool<CacheKeyValuePairCell> DictScrollPool { get; private set; }
private Text NotSupportedLabel;
public Text TopLabel;
public LayoutElement KeyTitleLayout;
public LayoutElement ValueTitleLayout;
public override void OnBorrowed(CacheObjectBase owner)
{
base.OnBorrowed(owner);
DictScrollPool.Refresh(true, true);
}
public override void ReleaseFromOwner()
{
base.ReleaseFromOwner();
ClearAndRelease();
}
private void ClearAndRelease()
{
RefIDictionary = null;
foreach (CacheKeyValuePair entry in cachedEntries)
{
entry.UnlinkFromView();
entry.ReleasePooledObjects();
}
cachedEntries.Clear();
}
public override void SetValue(object value)
{
if (value == null)
{
// should never be null
ClearAndRelease();
return;
}
else
{
Type type = value.GetActualType();
ReflectionUtility.TryGetEntryTypes(type, out KeysType, out ValuesType);
CacheEntries(value);
TopLabel.text = $"[{cachedEntries.Count}] {SignatureHighlighter.Parse(type, false)}";
}
this.DictScrollPool.Refresh(true, false);
}
private void CacheEntries(object value)
{
RefIDictionary = value as IDictionary;
if (ReflectionUtility.TryGetDictEnumerator(value, out IEnumerator<DictionaryEntry> dictEnumerator))
{
NotSupportedLabel.gameObject.SetActive(false);
int idx = 0;
while (dictEnumerator.MoveNext())
{
CacheKeyValuePair cache;
if (idx >= cachedEntries.Count)
{
cache = new CacheKeyValuePair();
cache.SetDictOwner(this, idx);
cachedEntries.Add(cache);
}
else
cache = cachedEntries[idx];
cache.SetFallbackType(ValuesType);
cache.SetKey(dictEnumerator.Current.Key);
cache.SetValueFromSource(dictEnumerator.Current.Value);
idx++;
}
// Remove excess cached entries if dict count decreased
if (cachedEntries.Count > idx)
{
for (int i = cachedEntries.Count - 1; i >= idx; i--)
{
CacheKeyValuePair cache = cachedEntries[i];
if (cache.CellView != null)
cache.UnlinkFromView();
cache.ReleasePooledObjects();
cachedEntries.RemoveAt(i);
}
}
}
else
{
NotSupportedLabel.gameObject.SetActive(true);
}
}
// Setting value to dictionary
public void TrySetValueToKey(object key, object value, int keyIndex)
{
try
{
if (!RefIDictionary.Contains(key))
{
ExplorerCore.LogWarning("Unable to set key! Key may have been boxed to/from Il2Cpp Object.");
return;
}
RefIDictionary[key] = value;
CacheKeyValuePair entry = cachedEntries[keyIndex];
entry.SetValueFromSource(value);
if (entry.CellView != null)
entry.SetDataToCell(entry.CellView);
}
catch (Exception ex)
{
ExplorerCore.LogWarning($"Exception setting IDictionary key! {ex}");
}
}
// KVP entry scroll pool
public void OnCellBorrowed(CacheKeyValuePairCell cell) { }
public void SetCell(CacheKeyValuePairCell cell, int index)
{
CacheObjectControllerHelper.SetCell(cell, index, cachedEntries, SetCellLayout);
}
public int AdjustedWidth => (int)UIRect.rect.width - 80;
public override void SetLayout()
{
float minHeight = 5f;
KeyTitleLayout.minWidth = AdjustedWidth * 0.44f;
ValueTitleLayout.minWidth = AdjustedWidth * 0.55f;
foreach (CacheKeyValuePairCell cell in DictScrollPool.CellPool)
{
SetCellLayout(cell);
if (cell.Enabled)
minHeight += cell.Rect.rect.height;
}
this.scrollLayout.minHeight = Math.Min(InspectorPanel.CurrentPanelHeight - 400f, minHeight);
}
private void SetCellLayout(CacheObjectCell objcell)
{
CacheKeyValuePairCell cell = objcell as CacheKeyValuePairCell;
cell.KeyGroupLayout.minWidth = cell.AdjustedWidth * 0.44f;
cell.RightGroupLayout.minWidth = cell.AdjustedWidth * 0.55f;
if (cell.Occupant?.IValue != null)
cell.Occupant.IValue.SetLayout();
}
private LayoutElement scrollLayout;
private RectTransform UIRect;
public override GameObject CreateContent(GameObject parent)
{
UIRoot = UIFactory.CreateVerticalGroup(parent, "InteractiveDict", true, true, true, true, 6, new Vector4(10, 3, 15, 4),
new Color(0.05f, 0.05f, 0.05f));
UIFactory.SetLayoutElement(UIRoot, flexibleWidth: 9999, minHeight: 25, flexibleHeight: 475);
UIRoot.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
UIRect = UIRoot.GetComponent<RectTransform>();
// Entries label
TopLabel = UIFactory.CreateLabel(UIRoot, "EntryLabel", "not set", TextAnchor.MiddleLeft, fontSize: 16);
TopLabel.horizontalOverflow = HorizontalWrapMode.Overflow;
// key / value titles
GameObject titleGroup = UIFactory.CreateUIObject("TitleGroup", UIRoot);
UIFactory.SetLayoutElement(titleGroup, minHeight: 25, flexibleWidth: 9999, flexibleHeight: 0);
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(titleGroup, false, true, true, true, padLeft: 65, padRight: 0, childAlignment: TextAnchor.LowerLeft);
Text keyTitle = UIFactory.CreateLabel(titleGroup, "KeyTitle", "Keys", TextAnchor.MiddleLeft);
UIFactory.SetLayoutElement(keyTitle.gameObject, minWidth: 100, flexibleWidth: 0);
KeyTitleLayout = keyTitle.GetComponent<LayoutElement>();
Text valueTitle = UIFactory.CreateLabel(titleGroup, "ValueTitle", "Values", TextAnchor.MiddleLeft);
UIFactory.SetLayoutElement(valueTitle.gameObject, minWidth: 100, flexibleWidth: 0);
ValueTitleLayout = valueTitle.GetComponent<LayoutElement>();
// entry scroll pool
DictScrollPool = UIFactory.CreateScrollPool<CacheKeyValuePairCell>(UIRoot, "EntryList", out GameObject scrollObj,
out GameObject _, new Color(0.09f, 0.09f, 0.09f));
UIFactory.SetLayoutElement(scrollObj, minHeight: 150, flexibleHeight: 0);
DictScrollPool.Initialize(this, SetLayout);
scrollLayout = scrollObj.GetComponent<LayoutElement>();
NotSupportedLabel = UIFactory.CreateLabel(DictScrollPool.Content.gameObject, "NotSupportedMessage",
"The IDictionary failed to enumerate. This is likely due to an issue with Unhollowed interfaces.",
TextAnchor.MiddleLeft, Color.red);
UIFactory.SetLayoutElement(NotSupportedLabel.gameObject, minHeight: 25, flexibleWidth: 9999);
NotSupportedLabel.gameObject.SetActive(false);
return UIRoot;
}
}
}

View File

@ -0,0 +1,244 @@
using System.Collections.Specialized;
using UnityExplorer.UI.Panels;
using UnityExplorer.UI.Widgets.AutoComplete;
using UniverseLib.UI;
using UniverseLib.UI.Models;
namespace UnityExplorer.CacheObject.IValues
{
public class InteractiveEnum : InteractiveValue
{
public bool IsFlags;
public Type EnumType;
private Type lastType;
public OrderedDictionary CurrentValues;
private InputFieldRef inputField;
private ButtonRef enumHelperButton;
private EnumCompleter enumCompleter;
private GameObject toggleHolder;
private readonly List<Toggle> flagToggles = new();
private readonly List<Text> flagTexts = new();
public CachedEnumValue ValueAtIndex(int idx) => (CachedEnumValue)CurrentValues[idx];
public CachedEnumValue ValueAtKey(object key) => (CachedEnumValue)CurrentValues[key];
// Setting value from owner
public override void SetValue(object value)
{
EnumType = value.GetType();
if (lastType != EnumType)
{
CurrentValues = GetEnumValues(EnumType);
IsFlags = EnumType.GetCustomAttributes(typeof(FlagsAttribute), true) is object[] fa && fa.Any();
if (IsFlags)
SetupTogglesForEnumType();
else
{
inputField.Component.gameObject.SetActive(true);
enumHelperButton.Component.gameObject.SetActive(true);
toggleHolder.SetActive(false);
}
enumCompleter.EnumType = EnumType;
enumCompleter.CacheEnumValues();
lastType = EnumType;
}
if (!IsFlags)
inputField.Text = value.ToString();
else
SetTogglesForValue(value);
this.enumCompleter.chosenSuggestion = value.ToString();
AutoCompleteModal.Instance.ReleaseOwnership(this.enumCompleter);
}
private void SetTogglesForValue(object value)
{
try
{
for (int i = 0; i < CurrentValues.Count; i++)
flagToggles[i].isOn = (value as Enum).HasFlag(ValueAtIndex(i).ActualValue as Enum);
}
catch (Exception ex)
{
ExplorerCore.LogWarning("Exception setting flag toggles: " + ex);
}
}
// Setting value to owner
private void OnApplyClicked()
{
try
{
if (!IsFlags)
{
if (ParseUtility.TryParse(this.inputField.Text, EnumType, out object value, out Exception ex))
CurrentOwner.SetUserValue(value);
else
throw ex;
}
else
{
SetValueFromFlags();
}
}
catch (Exception ex)
{
ExplorerCore.LogWarning("Exception setting from dropdown: " + ex);
}
}
private void SetValueFromFlags()
{
try
{
List<string> values = new();
for (int i = 0; i < CurrentValues.Count; i++)
{
if (flagToggles[i].isOn)
values.Add(ValueAtIndex(i).Name);
}
CurrentOwner.SetUserValue(Enum.Parse(EnumType, string.Join(", ", values.ToArray())));
}
catch (Exception ex)
{
ExplorerCore.LogWarning("Exception setting from flag toggles: " + ex);
}
}
// UI Construction
private void EnumHelper_OnClick()
{
enumCompleter.HelperButtonClicked();
}
public override GameObject CreateContent(GameObject parent)
{
UIRoot = UIFactory.CreateVerticalGroup(parent, "InteractiveEnum", false, false, true, true, 3, new Vector4(4, 4, 4, 4),
new Color(0.06f, 0.06f, 0.06f));
UIFactory.SetLayoutElement(UIRoot, minHeight: 25, flexibleHeight: 9999, flexibleWidth: 9999);
GameObject hori = UIFactory.CreateUIObject("Hori", UIRoot);
UIFactory.SetLayoutElement(hori, minHeight: 25, flexibleWidth: 9999);
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(hori, false, false, true, true, 2);
ButtonRef applyButton = UIFactory.CreateButton(hori, "ApplyButton", "Apply", new Color(0.2f, 0.27f, 0.2f));
UIFactory.SetLayoutElement(applyButton.Component.gameObject, minHeight: 25, minWidth: 100);
applyButton.OnClick += OnApplyClicked;
inputField = UIFactory.CreateInputField(hori, "InputField", "Enter name or underlying value...");
UIFactory.SetLayoutElement(inputField.UIRoot, minHeight: 25, flexibleHeight: 50, minWidth: 100, flexibleWidth: 1000);
inputField.Component.lineType = InputField.LineType.MultiLineNewline;
inputField.UIRoot.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
enumHelperButton = UIFactory.CreateButton(hori, "EnumHelper", "▼");
UIFactory.SetLayoutElement(enumHelperButton.Component.gameObject, minWidth: 25, minHeight: 25, flexibleWidth: 0, flexibleHeight: 0);
enumHelperButton.OnClick += EnumHelper_OnClick;
enumCompleter = new EnumCompleter(this.EnumType, this.inputField);
toggleHolder = UIFactory.CreateUIObject("ToggleHolder", UIRoot);
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(toggleHolder, false, false, true, true, 4);
UIFactory.SetLayoutElement(toggleHolder, minHeight: 25, flexibleWidth: 9999, flexibleHeight: 9999);
return UIRoot;
}
private void SetupTogglesForEnumType()
{
toggleHolder.SetActive(true);
inputField.Component.gameObject.SetActive(false);
enumHelperButton.Component.gameObject.SetActive(false);
// create / set / hide toggles
for (int i = 0; i < CurrentValues.Count || i < flagToggles.Count; i++)
{
if (i >= CurrentValues.Count)
{
if (i >= flagToggles.Count)
break;
flagToggles[i].gameObject.SetActive(false);
continue;
}
if (i >= flagToggles.Count)
AddToggleRow();
flagToggles[i].isOn = false;
flagTexts[i].text = ValueAtIndex(i).Name;
}
}
private void AddToggleRow()
{
GameObject row = UIFactory.CreateUIObject("ToggleRow", toggleHolder);
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(row, false, false, true, true, 2);
UIFactory.SetLayoutElement(row, minHeight: 25, flexibleWidth: 9999);
GameObject toggleObj = UIFactory.CreateToggle(row, "ToggleObj", out Toggle toggle, out Text toggleText);
UIFactory.SetLayoutElement(toggleObj, minHeight: 25, flexibleWidth: 9999);
flagToggles.Add(toggle);
flagTexts.Add(toggleText);
}
#region Enum cache
internal static readonly Dictionary<string, OrderedDictionary> enumCache = new();
internal static OrderedDictionary GetEnumValues(Type enumType)
{
//isFlags = enumType.GetCustomAttributes(typeof(FlagsAttribute), true) is object[] fa && fa.Any();
if (!enumCache.ContainsKey(enumType.AssemblyQualifiedName))
{
OrderedDictionary dict = new();
HashSet<string> addedNames = new();
int i = 0;
foreach (object value in Enum.GetValues(enumType))
{
string name = value.ToString();
if (addedNames.Contains(name))
continue;
addedNames.Add(name);
dict.Add(value, new CachedEnumValue(value, i, name));
i++;
}
enumCache.Add(enumType.AssemblyQualifiedName, dict);
}
return enumCache[enumType.AssemblyQualifiedName];
}
#endregion
}
public struct CachedEnumValue
{
public CachedEnumValue(object value, int index, string name)
{
EnumIndex = index;
Name = name;
ActualValue = value;
}
public readonly object ActualValue;
public int EnumIndex;
public readonly string Name;
}
}

View File

@ -0,0 +1,258 @@
using System.Collections;
using UnityExplorer.CacheObject.Views;
using UnityExplorer.UI.Panels;
using UniverseLib.UI;
using UniverseLib.UI.Widgets.ScrollView;
namespace UnityExplorer.CacheObject.IValues
{
public class InteractiveList : InteractiveValue, ICellPoolDataSource<CacheListEntryCell>, ICacheObjectController
{
CacheObjectBase ICacheObjectController.ParentCacheObject => this.CurrentOwner;
object ICacheObjectController.Target => this.CurrentOwner.Value;
public Type TargetType { get; private set; }
public override bool CanWrite => base.CanWrite && ((RefIList != null && !RefIList.IsReadOnly) || IsWritableGenericIList);
public Type EntryType;
public IList RefIList;
private bool IsWritableGenericIList;
private PropertyInfo genericIndexer;
public int ItemCount => cachedEntries.Count;
private readonly List<CacheListEntry> cachedEntries = new();
public ScrollPool<CacheListEntryCell> ListScrollPool { get; private set; }
public Text TopLabel;
private LayoutElement scrollLayout;
private Text NotSupportedLabel;
public override void OnBorrowed(CacheObjectBase owner)
{
base.OnBorrowed(owner);
ListScrollPool.Refresh(true, true);
}
public override void ReleaseFromOwner()
{
base.ReleaseFromOwner();
ClearAndRelease();
}
private void ClearAndRelease()
{
RefIList = null;
foreach (CacheListEntry entry in cachedEntries)
{
entry.UnlinkFromView();
entry.ReleasePooledObjects();
}
cachedEntries.Clear();
}
// List entry scroll pool
public override void SetLayout()
{
float minHeight = 5f;
foreach (CacheListEntryCell cell in ListScrollPool.CellPool)
{
if (cell.Enabled)
minHeight += cell.Rect.rect.height;
}
this.scrollLayout.minHeight = Math.Min(InspectorPanel.CurrentPanelHeight - 400f, minHeight);
}
public void OnCellBorrowed(CacheListEntryCell cell) { } // not needed
public void SetCell(CacheListEntryCell cell, int index)
{
CacheObjectControllerHelper.SetCell(cell, index, cachedEntries, null);
}
// Setting the List value itself to this model
public override void SetValue(object value)
{
if (value == null)
{
// should never be null
if (cachedEntries.Any())
ClearAndRelease();
}
else
{
Type type = value.GetActualType();
ReflectionUtility.TryGetEntryType(type, out EntryType);
CacheEntries(value);
TopLabel.text = $"[{cachedEntries.Count}] {SignatureHighlighter.Parse(type, false)}";
}
//this.ScrollPoolLayout.minHeight = Math.Min(400f, 35f * values.Count);
this.ListScrollPool.Refresh(true, false);
}
private void CacheEntries(object value)
{
RefIList = value as IList;
// Check if the type implements IList<T> but not IList (ie. Il2CppArrayBase)
if (RefIList == null)
CheckGenericIList(value);
else
IsWritableGenericIList = false;
int idx = 0;
if (ReflectionUtility.TryGetEnumerator(value, out IEnumerator enumerator))
{
NotSupportedLabel.gameObject.SetActive(false);
while (enumerator.MoveNext())
{
object entry = enumerator.Current;
// If list count increased, create new cache entries
CacheListEntry cache;
if (idx >= cachedEntries.Count)
{
cache = new CacheListEntry();
cache.SetListOwner(this, idx);
cachedEntries.Add(cache);
}
else
cache = cachedEntries[idx];
cache.SetFallbackType(this.EntryType);
cache.SetValueFromSource(entry);
idx++;
}
// Remove excess cached entries if list count decreased
if (cachedEntries.Count > idx)
{
for (int i = cachedEntries.Count - 1; i >= idx; i--)
{
CacheListEntry cache = cachedEntries[i];
if (cache.CellView != null)
cache.UnlinkFromView();
cache.ReleasePooledObjects();
cachedEntries.RemoveAt(i);
}
}
}
else
{
NotSupportedLabel.gameObject.SetActive(true);
}
}
private void CheckGenericIList(object value)
{
try
{
Type type = value.GetType();
if (type.GetInterfaces().Any(it => it.IsGenericType && it.GetGenericTypeDefinition() == typeof(IList<>)))
IsWritableGenericIList = !(bool)type.GetProperty("IsReadOnly").GetValue(value, null);
else
IsWritableGenericIList = false;
if (IsWritableGenericIList)
{
// Find the "this[int index]" property.
// It might be a private implementation.
foreach (PropertyInfo prop in type.GetProperties(ReflectionUtility.FLAGS))
{
if ((prop.Name == "Item"
|| (prop.Name.StartsWith("System.Collections.Generic.IList<") && prop.Name.EndsWith(">.Item")))
&& prop.GetIndexParameters() is ParameterInfo[] parameters
&& parameters.Length == 1
&& parameters[0].ParameterType == typeof(int))
{
genericIndexer = prop;
break;
}
}
if (genericIndexer == null)
{
ExplorerCore.LogWarning($"Failed to find indexer property for IList<T> type '{type.FullName}'!");
IsWritableGenericIList = false;
}
}
}
catch (Exception ex)
{
ExplorerCore.LogWarning($"Exception processing IEnumerable for IList<T> check: {ex.ReflectionExToString()}");
IsWritableGenericIList = false;
}
}
// Setting the value of an index to the list
public void TrySetValueToIndex(object value, int index)
{
try
{
if (!IsWritableGenericIList)
{
RefIList[index] = value;
}
else
{
genericIndexer.SetValue(CurrentOwner.Value, value, new object[] { index });
}
CacheListEntry entry = cachedEntries[index];
entry.SetValueFromSource(value);
if (entry.CellView != null)
entry.SetDataToCell(entry.CellView);
}
catch (Exception ex)
{
ExplorerCore.LogWarning($"Exception setting IList value: {ex}");
}
}
public override GameObject CreateContent(GameObject parent)
{
UIRoot = UIFactory.CreateVerticalGroup(parent, "InteractiveList", true, true, true, true, 6, new Vector4(10, 3, 15, 4),
new Color(0.05f, 0.05f, 0.05f));
UIFactory.SetLayoutElement(UIRoot, flexibleWidth: 9999, minHeight: 25, flexibleHeight: 600);
UIRoot.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
// Entries label
TopLabel = UIFactory.CreateLabel(UIRoot, "EntryLabel", "not set", TextAnchor.MiddleLeft, fontSize: 16);
TopLabel.horizontalOverflow = HorizontalWrapMode.Overflow;
// entry scroll pool
ListScrollPool = UIFactory.CreateScrollPool<CacheListEntryCell>(UIRoot, "EntryList", out GameObject scrollObj,
out GameObject _, new Color(0.09f, 0.09f, 0.09f));
UIFactory.SetLayoutElement(scrollObj, minHeight: 400, flexibleHeight: 0);
ListScrollPool.Initialize(this, SetLayout);
scrollLayout = scrollObj.GetComponent<LayoutElement>();
NotSupportedLabel = UIFactory.CreateLabel(ListScrollPool.Content.gameObject, "NotSupportedMessage",
"The IEnumerable failed to enumerate. This is likely due to an issue with Unhollowed interfaces.",
TextAnchor.MiddleLeft, Color.red);
UIFactory.SetLayoutElement(NotSupportedLabel.gameObject, minHeight: 25, flexibleWidth: 9999);
NotSupportedLabel.gameObject.SetActive(false);
return UIRoot;
}
}
}

View File

@ -0,0 +1,127 @@
using UnityExplorer.Config;
using UniverseLib.UI;
using UniverseLib.UI.Models;
namespace UnityExplorer.CacheObject.IValues
{
public class InteractiveString : InteractiveValue
{
private string RealValue;
public string EditedValue = "";
public InputFieldRef inputField;
public ButtonRef ApplyButton;
public GameObject SaveFileRow;
public InputFieldRef SaveFilePath;
public override void OnBorrowed(CacheObjectBase owner)
{
base.OnBorrowed(owner);
bool canWrite = owner.CanWrite && owner.State != ValueState.Exception;
inputField.Component.readOnly = !canWrite;
ApplyButton.Component.gameObject.SetActive(canWrite);
SaveFilePath.Text = Path.Combine(ConfigManager.Default_Output_Path.Value, "untitled.txt");
}
private bool IsStringTooLong(string s)
{
if (s == null)
return false;
return s.Length >= UniversalUI.MAX_INPUTFIELD_CHARS;
}
public override void SetValue(object value)
{
if (CurrentOwner.State == ValueState.Exception)
value = CurrentOwner.LastException.ToString();
RealValue = value as string;
SaveFileRow.SetActive(IsStringTooLong(RealValue));
if (value == null)
{
inputField.Text = "";
EditedValue = "";
}
else
{
EditedValue = (string)value;
inputField.Text = EditedValue;
}
}
private void OnApplyClicked()
{
CurrentOwner.SetUserValue(EditedValue);
}
private void OnInputChanged(string input)
{
EditedValue = input;
SaveFileRow.SetActive(IsStringTooLong(EditedValue));
}
private void OnSaveFileClicked()
{
if (RealValue == null)
return;
if (string.IsNullOrEmpty(SaveFilePath.Text))
{
ExplorerCore.LogWarning("Cannot save an empty file path!");
return;
}
string path = IOUtility.EnsureValidFilePath(SaveFilePath.Text);
if (File.Exists(path))
File.Delete(path);
File.WriteAllText(path, RealValue);
}
public override GameObject CreateContent(GameObject parent)
{
UIRoot = UIFactory.CreateVerticalGroup(parent, "InteractiveString", false, false, true, true, 3, new Vector4(4, 4, 4, 4),
new Color(0.06f, 0.06f, 0.06f));
// Save to file helper
SaveFileRow = UIFactory.CreateUIObject("SaveFileRow", UIRoot);
UIFactory.SetLayoutElement(SaveFileRow, flexibleWidth: 9999);
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(SaveFileRow, false, true, true, true, 3);
UIFactory.CreateLabel(SaveFileRow, "Info", "<color=red>String is too long! Save to file if you want to see the full string.</color>",
TextAnchor.MiddleLeft);
GameObject horizRow = UIFactory.CreateUIObject("Horiz", SaveFileRow);
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(horizRow, false, false, true, true, 4);
ButtonRef saveButton = UIFactory.CreateButton(horizRow, "SaveButton", "Save file");
UIFactory.SetLayoutElement(saveButton.Component.gameObject, minHeight: 25, minWidth: 100, flexibleWidth: 0);
saveButton.OnClick += OnSaveFileClicked;
SaveFilePath = UIFactory.CreateInputField(horizRow, "SaveInput", "...");
UIFactory.SetLayoutElement(SaveFilePath.UIRoot, minHeight: 25, flexibleWidth: 9999);
// Main Input / apply
ApplyButton = UIFactory.CreateButton(UIRoot, "ApplyButton", "Apply", new Color(0.2f, 0.27f, 0.2f));
UIFactory.SetLayoutElement(ApplyButton.Component.gameObject, minHeight: 25, minWidth: 100, flexibleWidth: 0);
ApplyButton.OnClick += OnApplyClicked;
inputField = UIFactory.CreateInputField(UIRoot, "InputField", "empty");
inputField.UIRoot.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
UIFactory.SetLayoutElement(inputField.UIRoot, minHeight: 25, flexibleHeight: 500, flexibleWidth: 9999);
inputField.Component.lineType = InputField.LineType.MultiLineNewline;
inputField.OnValueChanged += OnInputChanged;
return UIRoot;
}
}
}

View File

@ -0,0 +1,56 @@
using UniverseLib.UI.ObjectPool;
namespace UnityExplorer.CacheObject.IValues
{
public abstract class InteractiveValue : IPooledObject
{
public static Type GetIValueTypeForState(ValueState state)
{
return state switch
{
ValueState.Exception or ValueState.String => typeof(InteractiveString),
ValueState.Enum => typeof(InteractiveEnum),
ValueState.Collection => typeof(InteractiveList),
ValueState.Dictionary => typeof(InteractiveDictionary),
ValueState.ValueStruct => typeof(InteractiveValueStruct),
ValueState.Color => typeof(InteractiveColor),
_ => null,
};
}
public GameObject UIRoot { get; set; }
public float DefaultHeight => -1f;
public virtual bool CanWrite => this.CurrentOwner.CanWrite;
public CacheObjectBase CurrentOwner => owner;
private CacheObjectBase owner;
public bool PendingValueWanted;
public virtual void OnBorrowed(CacheObjectBase owner)
{
if (this.owner != null)
{
ExplorerCore.LogWarning("Setting an IValue's owner but there is already one set. Maybe it wasn't cleaned up?");
ReleaseFromOwner();
}
this.owner = owner;
}
public virtual void ReleaseFromOwner()
{
if (this.owner == null)
return;
this.owner = null;
}
public abstract void SetValue(object value);
public virtual void SetLayout() { }
public abstract GameObject CreateContent(GameObject parent);
}
}

View File

@ -0,0 +1,205 @@
using UniverseLib.UI;
using UniverseLib.UI.Models;
namespace UnityExplorer.CacheObject.IValues
{
public class InteractiveValueStruct : InteractiveValue
{
#region Struct cache / wrapper
public class StructInfo
{
public bool IsSupported;
public FieldInfo[] Fields;
public StructInfo(bool isSupported, FieldInfo[] fields)
{
IsSupported = isSupported;
Fields = fields;
}
public void SetValue(object instance, string input, int fieldIndex)
{
FieldInfo field = Fields[fieldIndex];
object val;
if (field.FieldType == typeof(string))
val = input;
else
{
if (!ParseUtility.TryParse(input, field.FieldType, out val, out Exception ex))
{
ExplorerCore.LogWarning("Unable to parse input!");
if (ex != null) ExplorerCore.Log(ex.ReflectionExToString());
return;
}
}
field.SetValue(instance, val);
}
public string GetValue(object instance, int fieldIndex)
{
FieldInfo field = Fields[fieldIndex];
object value = field.GetValue(instance);
return ParseUtility.ToStringForInput(value, field.FieldType);
}
}
private static readonly Dictionary<string, StructInfo> typeSupportCache = new();
private const BindingFlags INSTANCE_FLAGS = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;
private const string SYSTEM_VOID = "System.Void";
public static bool SupportsType(Type type)
{
if (!type.IsValueType || string.IsNullOrEmpty(type.AssemblyQualifiedName) || type.FullName == SYSTEM_VOID)
return false;
if (typeSupportCache.TryGetValue(type.AssemblyQualifiedName, out StructInfo info))
return info.IsSupported;
bool supported = false;
FieldInfo[] fields = type.GetFields(INSTANCE_FLAGS);
if (fields.Length > 0)
{
if (fields.Any(it => !ParseUtility.CanParse(it.FieldType)))
{
supported = false;
info = new StructInfo(supported, null);
}
else
{
supported = true;
info = new StructInfo(supported, fields);
}
}
typeSupportCache.Add(type.AssemblyQualifiedName, info);
return supported;
}
#endregion
public object RefInstance;
public StructInfo CurrentInfo;
private Type lastStructType;
private ButtonRef applyButton;
private readonly List<GameObject> fieldRows = new();
private readonly List<InputFieldRef> inputFields = new();
private readonly List<Text> labels = new();
public override void OnBorrowed(CacheObjectBase owner)
{
base.OnBorrowed(owner);
applyButton.Component.gameObject.SetActive(owner.CanWrite);
}
// Setting value from owner to this
public override void SetValue(object value)
{
RefInstance = value;
Type type = RefInstance.GetType();
if (type != lastStructType)
{
CurrentInfo = typeSupportCache[type.AssemblyQualifiedName];
SetupUIForType();
lastStructType = type;
}
for (int i = 0; i < CurrentInfo.Fields.Length; i++)
{
inputFields[i].Text = CurrentInfo.GetValue(RefInstance, i);
}
}
private void OnApplyClicked()
{
try
{
for (int i = 0; i < CurrentInfo.Fields.Length; i++)
{
CurrentInfo.SetValue(RefInstance, inputFields[i].Text, i);
}
CurrentOwner.SetUserValue(RefInstance);
}
catch (Exception ex)
{
ExplorerCore.LogWarning("Exception setting value: " + ex);
}
}
// UI Setup for type
private void SetupUIForType()
{
for (int i = 0; i < CurrentInfo.Fields.Length || i <= inputFields.Count; i++)
{
if (i >= CurrentInfo.Fields.Length)
{
if (i >= inputFields.Count)
break;
fieldRows[i].SetActive(false);
continue;
}
if (i >= inputFields.Count)
AddEditorRow();
fieldRows[i].SetActive(true);
string label = SignatureHighlighter.Parse(CurrentInfo.Fields[i].FieldType, false);
label += $" <color={SignatureHighlighter.FIELD_INSTANCE}>{CurrentInfo.Fields[i].Name}</color>:";
labels[i].text = label;
}
}
private void AddEditorRow()
{
GameObject row = UIFactory.CreateUIObject("HoriGroup", UIRoot);
//row.AddComponent<ContentSizeFitter>().horizontalFit = ContentSizeFitter.FitMode.PreferredSize;
UIFactory.SetLayoutElement(row, minHeight: 25, flexibleWidth: 9999);
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(row, false, false, true, true, 8, childAlignment: TextAnchor.MiddleLeft);
fieldRows.Add(row);
Text label = UIFactory.CreateLabel(row, "Label", "notset", TextAnchor.MiddleLeft);
UIFactory.SetLayoutElement(label.gameObject, minHeight: 25, minWidth: 50, flexibleWidth: 0);
label.horizontalOverflow = HorizontalWrapMode.Wrap;
labels.Add(label);
InputFieldRef input = UIFactory.CreateInputField(row, "InputField", "...");
UIFactory.SetLayoutElement(input.UIRoot, minHeight: 25, minWidth: 200);
ContentSizeFitter fitter = input.UIRoot.AddComponent<ContentSizeFitter>();
fitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
fitter.horizontalFit = ContentSizeFitter.FitMode.PreferredSize;
input.Component.lineType = InputField.LineType.MultiLineNewline;
inputFields.Add(input);
}
// UI Construction
public override GameObject CreateContent(GameObject parent)
{
UIRoot = UIFactory.CreateVerticalGroup(parent, "InteractiveValueStruct", false, false, true, true, 3, new Vector4(4, 4, 4, 4),
new Color(0.06f, 0.06f, 0.06f), TextAnchor.MiddleLeft);
UIFactory.SetLayoutElement(UIRoot, minHeight: 25, flexibleWidth: 9999);
applyButton = UIFactory.CreateButton(UIRoot, "ApplyButton", "Apply", new Color(0.2f, 0.27f, 0.2f));
UIFactory.SetLayoutElement(applyButton.Component.gameObject, minHeight: 25, minWidth: 175);
applyButton.OnClick += OnApplyClicked;
return UIRoot;
}
}
}

View File

@ -0,0 +1,80 @@
using UniverseLib.UI;
namespace UnityExplorer.CacheObject.Views
{
public class ConfigEntryCell : CacheObjectCell
{
public override GameObject CreateContent(GameObject parent)
{
// Main layout
UIRoot = UIFactory.CreateUIObject(this.GetType().Name, parent, new Vector2(100, 30));
Rect = UIRoot.GetComponent<RectTransform>();
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(UIRoot, false, false, true, true, 4, 4, 4, 4, 4, childAlignment: TextAnchor.UpperLeft);
UIFactory.SetLayoutElement(UIRoot, minWidth: 100, flexibleWidth: 9999, minHeight: 30, flexibleHeight: 600);
UIRoot.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
// Left label
NameLabel = UIFactory.CreateLabel(UIRoot, "NameLabel", "<notset>", TextAnchor.MiddleLeft);
NameLabel.horizontalOverflow = HorizontalWrapMode.Wrap;
UIFactory.SetLayoutElement(NameLabel.gameObject, minHeight: 25, flexibleWidth: 9999, flexibleHeight: 300);
NameLayout = NameLabel.GetComponent<LayoutElement>();
// horizontal group
GameObject horiGroup = UIFactory.CreateUIObject("RightHoriGroup", UIRoot);
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(horiGroup, false, false, true, true, 4, childAlignment: TextAnchor.UpperLeft);
UIFactory.SetLayoutElement(horiGroup, minHeight: 25, minWidth: 200, flexibleWidth: 9999, flexibleHeight: 800);
SubContentButton = UIFactory.CreateButton(horiGroup, "SubContentButton", "▲", subInactiveColor);
UIFactory.SetLayoutElement(SubContentButton.Component.gameObject, minWidth: 25, minHeight: 25, flexibleWidth: 0, flexibleHeight: 0);
SubContentButton.OnClick += SubContentClicked;
// Type label
TypeLabel = UIFactory.CreateLabel(horiGroup, "TypeLabel", "<notset>", TextAnchor.MiddleLeft);
TypeLabel.horizontalOverflow = HorizontalWrapMode.Wrap;
UIFactory.SetLayoutElement(TypeLabel.gameObject, minHeight: 25, flexibleHeight: 150, minWidth: 60, flexibleWidth: 0);
// Bool and number value interaction
GameObject toggleObj = UIFactory.CreateToggle(horiGroup, "Toggle", out Toggle, out ToggleText);
UIFactory.SetLayoutElement(toggleObj, minWidth: 70, minHeight: 25, flexibleWidth: 0, flexibleHeight: 0);
ToggleText.color = SignatureHighlighter.KeywordBlue;
Toggle.onValueChanged.AddListener(ToggleClicked);
InputField = UIFactory.CreateInputField(horiGroup, "InputField", "...");
UIFactory.SetLayoutElement(InputField.UIRoot, minWidth: 150, flexibleWidth: 0, minHeight: 25, flexibleHeight: 0);
// Apply
ApplyButton = UIFactory.CreateButton(horiGroup, "ApplyButton", "Apply", new Color(0.15f, 0.19f, 0.15f));
UIFactory.SetLayoutElement(ApplyButton.Component.gameObject, minWidth: 70, minHeight: 25, flexibleWidth: 0, flexibleHeight: 0);
ApplyButton.OnClick += ApplyClicked;
// Main value label
ValueLabel = UIFactory.CreateLabel(horiGroup, "ValueLabel", "Value goes here", TextAnchor.MiddleLeft);
ValueLabel.horizontalOverflow = HorizontalWrapMode.Wrap;
UIFactory.SetLayoutElement(ValueLabel.gameObject, minHeight: 25, flexibleHeight: 150, flexibleWidth: 9999);
// Subcontent
SubContentHolder = UIFactory.CreateUIObject("SubContent", UIRoot);
UIFactory.SetLayoutElement(SubContentHolder.gameObject, minHeight: 30, flexibleHeight: 600, minWidth: 100, flexibleWidth: 9999);
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(SubContentHolder, true, true, true, true, 2, childAlignment: TextAnchor.UpperLeft);
//SubContentHolder.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.MinSize;
SubContentHolder.SetActive(false);
// Bottom separator
GameObject separator = UIFactory.CreateUIObject("BottomSeperator", UIRoot);
UIFactory.SetLayoutElement(separator, minHeight: 1, flexibleHeight: 0, flexibleWidth: 9999);
separator.AddComponent<Image>().color = Color.black;
return UIRoot;
}
protected override void ConstructEvaluateHolder(GameObject parent) { }
}
}

View File

@ -0,0 +1,85 @@
using UnityExplorer.CacheObject.IValues;
using UniverseLib.UI;
using UniverseLib.UI.Models;
namespace UnityExplorer.CacheObject.Views
{
public class CacheKeyValuePairCell : CacheObjectCell
{
public Image Image { get; private set; }
public InteractiveDictionary DictOwner => Occupant.Owner as InteractiveDictionary;
public LayoutElement KeyGroupLayout;
public Text KeyLabel;
public ButtonRef KeyInspectButton;
public InputFieldRef KeyInputField;
public Text KeyInputTypeLabel;
public static Color EvenColor = new(0.07f, 0.07f, 0.07f);
public static Color OddColor = new(0.063f, 0.063f, 0.063f);
public int AdjustedWidth => (int)Rect.rect.width - 70;
//public int HalfWidth => (int)(0.5f * Rect.rect.width) - 75;
//public int AdjustedKeyWidth => HalfWidth - 50;
//public int AdjustedRightWidth => HalfWidth;
private void KeyInspectClicked()
{
InspectorManager.Inspect((Occupant as CacheKeyValuePair).DictKey, this.Occupant);
}
public override GameObject CreateContent(GameObject parent)
{
GameObject root = base.CreateContent(parent);
Image = root.AddComponent<Image>();
this.NameLayout.minWidth = 70;
this.NameLayout.flexibleWidth = 0;
this.NameLayout.minHeight = 30;
this.NameLayout.flexibleHeight = 0;
this.NameLabel.alignment = TextAnchor.MiddleRight;
this.RightGroupLayout.minWidth = AdjustedWidth * 0.55f;
// Key area
GameObject keyGroup = UIFactory.CreateUIObject("KeyHolder", root.transform.Find("HoriGroup").gameObject);
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(keyGroup, false, false, true, true, 2, 0, 0, 4, 4, childAlignment: TextAnchor.MiddleLeft);
KeyGroupLayout = UIFactory.SetLayoutElement(keyGroup, minHeight: 30, minWidth: (int)(AdjustedWidth * 0.44f), flexibleWidth: 0);
// set to be after the NameLabel (our index label), and before the main horizontal group.
keyGroup.transform.SetSiblingIndex(1);
// key Inspect
KeyInspectButton = UIFactory.CreateButton(keyGroup, "KeyInspectButton", "Inspect", new Color(0.15f, 0.15f, 0.15f));
UIFactory.SetLayoutElement(KeyInspectButton.Component.gameObject, minWidth: 60, flexibleWidth: 0, minHeight: 25, flexibleHeight: 0);
KeyInspectButton.OnClick += KeyInspectClicked;
// label
KeyLabel = UIFactory.CreateLabel(keyGroup, "KeyLabel", "<i>empty</i>", TextAnchor.MiddleLeft);
UIFactory.SetLayoutElement(KeyLabel.gameObject, minWidth: 50, flexibleWidth: 999, minHeight: 25);
// Type label for input field
KeyInputTypeLabel = UIFactory.CreateLabel(keyGroup, "InputTypeLabel", "<i>null</i>", TextAnchor.MiddleLeft);
UIFactory.SetLayoutElement(KeyInputTypeLabel.gameObject, minWidth: 55, flexibleWidth: 0, minHeight: 25, flexibleHeight: 0);
// input field
KeyInputField = UIFactory.CreateInputField(keyGroup, "KeyInput", "empty");
UIFactory.SetLayoutElement(KeyInputField.UIRoot, minHeight: 25, flexibleHeight: 0, flexibleWidth: 0, preferredWidth: 200);
//KeyInputField.lineType = InputField.LineType.MultiLineNewline;
KeyInputField.Component.readOnly = true;
return root;
}
protected override void ConstructEvaluateHolder(GameObject parent)
{
// not used
}
}
}

View File

@ -0,0 +1,38 @@
using UnityExplorer.CacheObject.IValues;
namespace UnityExplorer.CacheObject.Views
{
public class CacheListEntryCell : CacheObjectCell
{
public Image Image { get; private set; }
public InteractiveList ListOwner => Occupant.Owner as InteractiveList;
public static Color EvenColor = new(0.12f, 0.12f, 0.12f);
public static Color OddColor = new(0.1f, 0.1f, 0.1f);
public override GameObject CreateContent(GameObject parent)
{
GameObject root = base.CreateContent(parent);
Image = root.AddComponent<Image>();
this.NameLayout.minWidth = 40;
this.NameLayout.flexibleWidth = 50;
this.NameLayout.minHeight = 25;
this.NameLayout.flexibleHeight = 0;
this.NameLabel.alignment = TextAnchor.MiddleRight;
return root;
}
protected override void ConstructEvaluateHolder(GameObject parent)
{
// not used
}
//protected override void ConstructUpdateToggle(GameObject parent)
//{
// // not used
//}
}
}

View File

@ -0,0 +1,31 @@
using UniverseLib.UI;
using UniverseLib.UI.Models;
namespace UnityExplorer.CacheObject.Views
{
public class CacheMemberCell : CacheObjectCell
{
public CacheMember MemberOccupant => Occupant as CacheMember;
public GameObject EvaluateHolder;
public ButtonRef EvaluateButton;
protected virtual void EvaluateClicked()
{
this.MemberOccupant.OnEvaluateClicked();
}
protected override void ConstructEvaluateHolder(GameObject parent)
{
// Evaluate vert group
EvaluateHolder = UIFactory.CreateUIObject("EvalGroup", parent);
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(EvaluateHolder, false, false, true, true, 3);
UIFactory.SetLayoutElement(EvaluateHolder, minHeight: 25, flexibleWidth: 9999, flexibleHeight: 775);
EvaluateButton = UIFactory.CreateButton(EvaluateHolder, "EvaluateButton", "Evaluate", new Color(0.15f, 0.15f, 0.15f));
UIFactory.SetLayoutElement(EvaluateButton.Component.gameObject, minWidth: 100, minHeight: 25);
EvaluateButton.OnClick += EvaluateClicked;
}
}
}

View File

@ -0,0 +1,221 @@
using UnityExplorer.UI.Panels;
using UniverseLib.UI;
using UniverseLib.UI.Models;
using UniverseLib.UI.Widgets.ScrollView;
namespace UnityExplorer.CacheObject.Views
{
public abstract class CacheObjectCell : ICell
{
#region ICell
public float DefaultHeight => 30f;
public GameObject UIRoot { get; set; }
public bool Enabled => m_enabled;
private bool m_enabled;
public RectTransform Rect { get; set; }
public void Disable()
{
m_enabled = false;
UIRoot.SetActive(false);
}
public void Enable()
{
m_enabled = true;
UIRoot.SetActive(true);
}
#endregion
public CacheObjectBase Occupant { get; set; }
public bool SubContentActive => SubContentHolder.activeSelf;
public LayoutElement NameLayout;
public GameObject RightGroupContent;
public LayoutElement RightGroupLayout;
public GameObject SubContentHolder;
public Text NameLabel;
public InputFieldRef HiddenNameLabel; // for selecting the name label
public Text TypeLabel;
public Text ValueLabel;
public Toggle Toggle;
public Text ToggleText;
public InputFieldRef InputField;
public ButtonRef InspectButton;
public ButtonRef SubContentButton;
public ButtonRef ApplyButton;
public ButtonRef CopyButton;
public ButtonRef PasteButton;
public readonly Color subInactiveColor = new(0.23f, 0.23f, 0.23f);
public readonly Color subActiveColor = new(0.23f, 0.33f, 0.23f);
protected virtual void ApplyClicked()
{
Occupant.OnCellApplyClicked();
}
protected virtual void InspectClicked()
{
InspectorManager.Inspect(Occupant.Value, this.Occupant);
}
protected virtual void ToggleClicked(bool value)
{
ToggleText.text = value.ToString();
}
protected virtual void SubContentClicked()
{
this.Occupant.OnCellSubContentToggle();
}
protected virtual void OnCopyClicked()
{
ClipboardPanel.Copy(this.Occupant.Value);
}
protected virtual void OnPasteClicked()
{
if (ClipboardPanel.TryPaste(this.Occupant.FallbackType, out object paste))
this.Occupant.SetUserValue(paste);
}
public void RefreshSubcontentButton()
{
this.SubContentButton.ButtonText.text = SubContentHolder.activeSelf ? "▼" : "▲";
Color color = SubContentHolder.activeSelf ? subActiveColor : subInactiveColor;
RuntimeHelper.SetColorBlock(SubContentButton.Component, color, color * 1.3f);
}
protected abstract void ConstructEvaluateHolder(GameObject parent);
public virtual GameObject CreateContent(GameObject parent)
{
// Main layout
UIRoot = UIFactory.CreateUIObject(this.GetType().Name, parent, new Vector2(100, 30));
Rect = UIRoot.GetComponent<RectTransform>();
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(UIRoot, false, false, true, true, childAlignment: TextAnchor.UpperLeft);
UIFactory.SetLayoutElement(UIRoot, minWidth: 100, flexibleWidth: 9999, minHeight: 30, flexibleHeight: 600);
UIRoot.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
GameObject horiRow = UIFactory.CreateUIObject("HoriGroup", UIRoot);
UIFactory.SetLayoutElement(horiRow, minHeight: 29, flexibleHeight: 150, flexibleWidth: 9999);
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(horiRow, false, false, true, true, 5, 2, childAlignment: TextAnchor.UpperLeft);
horiRow.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
// Left name label
NameLabel = UIFactory.CreateLabel(horiRow, "NameLabel", "<notset>", TextAnchor.MiddleLeft);
NameLabel.horizontalOverflow = HorizontalWrapMode.Wrap;
NameLayout = UIFactory.SetLayoutElement(NameLabel.gameObject, minHeight: 25, minWidth: 20, flexibleHeight: 300, flexibleWidth: 0);
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(NameLabel.gameObject, true, true, true, true);
HiddenNameLabel = UIFactory.CreateInputField(NameLabel.gameObject, "HiddenNameLabel", "");
RectTransform hiddenRect = HiddenNameLabel.Component.GetComponent<RectTransform>();
hiddenRect.anchorMin = Vector2.zero;
hiddenRect.anchorMax = Vector2.one;
HiddenNameLabel.Component.readOnly = true;
HiddenNameLabel.Component.lineType = UnityEngine.UI.InputField.LineType.MultiLineNewline;
HiddenNameLabel.Component.textComponent.horizontalOverflow = HorizontalWrapMode.Wrap;
HiddenNameLabel.Component.gameObject.GetComponent<Image>().color = Color.clear;
HiddenNameLabel.Component.textComponent.color = Color.clear;
UIFactory.SetLayoutElement(HiddenNameLabel.Component.gameObject, minHeight: 25, minWidth: 20, flexibleHeight: 300, flexibleWidth: 0);
// Right vertical group
RightGroupContent = UIFactory.CreateUIObject("RightGroup", horiRow);
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(RightGroupContent, false, false, true, true, 4, childAlignment: TextAnchor.UpperLeft);
UIFactory.SetLayoutElement(RightGroupContent, minHeight: 25, minWidth: 200, flexibleWidth: 9999, flexibleHeight: 800);
RightGroupLayout = RightGroupContent.GetComponent<LayoutElement>();
ConstructEvaluateHolder(RightGroupContent);
// Right horizontal group
GameObject rightHoriGroup = UIFactory.CreateUIObject("RightHoriGroup", RightGroupContent);
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(rightHoriGroup, false, false, true, true, 4, childAlignment: TextAnchor.UpperLeft);
UIFactory.SetLayoutElement(rightHoriGroup, minHeight: 25, minWidth: 200, flexibleWidth: 9999, flexibleHeight: 800);
SubContentButton = UIFactory.CreateButton(rightHoriGroup, "SubContentButton", "▲", subInactiveColor);
UIFactory.SetLayoutElement(SubContentButton.Component.gameObject, minWidth: 25, minHeight: 25, flexibleWidth: 0, flexibleHeight: 0);
SubContentButton.OnClick += SubContentClicked;
// Type label
TypeLabel = UIFactory.CreateLabel(rightHoriGroup, "ReturnLabel", "<notset>", TextAnchor.MiddleLeft);
TypeLabel.horizontalOverflow = HorizontalWrapMode.Wrap;
UIFactory.SetLayoutElement(TypeLabel.gameObject, minHeight: 25, flexibleHeight: 150, minWidth: 45, flexibleWidth: 0);
// Bool and number value interaction
GameObject toggleObj = UIFactory.CreateToggle(rightHoriGroup, "Toggle", out Toggle, out ToggleText);
UIFactory.SetLayoutElement(toggleObj, minWidth: 70, minHeight: 25, flexibleWidth: 0, flexibleHeight: 0);
ToggleText.color = SignatureHighlighter.KeywordBlue;
Toggle.onValueChanged.AddListener(ToggleClicked);
InputField = UIFactory.CreateInputField(rightHoriGroup, "InputField", "...");
UIFactory.SetLayoutElement(InputField.UIRoot, minWidth: 150, flexibleWidth: 0, minHeight: 25, flexibleHeight: 0);
// Apply
ApplyButton = UIFactory.CreateButton(rightHoriGroup, "ApplyButton", "Apply", new Color(0.15f, 0.19f, 0.15f));
UIFactory.SetLayoutElement(ApplyButton.Component.gameObject, minWidth: 70, minHeight: 25, flexibleWidth: 0, flexibleHeight: 0);
ApplyButton.OnClick += ApplyClicked;
// Inspect
InspectButton = UIFactory.CreateButton(rightHoriGroup, "InspectButton", "Inspect", new Color(0.15f, 0.15f, 0.15f));
UIFactory.SetLayoutElement(InspectButton.Component.gameObject, minWidth: 70, flexibleWidth: 0, minHeight: 25);
InspectButton.OnClick += InspectClicked;
// Main value label
ValueLabel = UIFactory.CreateLabel(rightHoriGroup, "ValueLabel", "Value goes here", TextAnchor.MiddleLeft);
ValueLabel.horizontalOverflow = HorizontalWrapMode.Wrap;
UIFactory.SetLayoutElement(ValueLabel.gameObject, minHeight: 25, flexibleHeight: 150, flexibleWidth: 9999);
// Copy and Paste buttons
GameObject buttonHolder = UIFactory.CreateHorizontalGroup(rightHoriGroup, "CopyPasteButtons", false, false, true, true, 4,
bgColor: new(1, 1, 1, 0), childAlignment: TextAnchor.MiddleLeft);
UIFactory.SetLayoutElement(buttonHolder, minWidth: 60, flexibleWidth: 0);
CopyButton = UIFactory.CreateButton(buttonHolder, "CopyButton", "Copy", new Color(0.13f, 0.13f, 0.13f, 1f));
UIFactory.SetLayoutElement(CopyButton.Component.gameObject, minHeight: 25, minWidth: 28, flexibleWidth: 0);
CopyButton.ButtonText.color = Color.yellow;
CopyButton.ButtonText.fontSize = 10;
CopyButton.OnClick += OnCopyClicked;
PasteButton = UIFactory.CreateButton(buttonHolder, "PasteButton", "Paste", new Color(0.13f, 0.13f, 0.13f, 1f));
UIFactory.SetLayoutElement(PasteButton.Component.gameObject, minHeight: 25, minWidth: 28, flexibleWidth: 0);
PasteButton.ButtonText.color = Color.green;
PasteButton.ButtonText.fontSize = 10;
PasteButton.OnClick += OnPasteClicked;
// Subcontent
SubContentHolder = UIFactory.CreateUIObject("SubContent", UIRoot);
UIFactory.SetLayoutElement(SubContentHolder.gameObject, minHeight: 30, flexibleHeight: 600, minWidth: 100, flexibleWidth: 9999);
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(SubContentHolder, true, true, true, true, 2, childAlignment: TextAnchor.UpperLeft);
//SubContentHolder.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.MinSize;
SubContentHolder.SetActive(false);
// Bottom separator
GameObject separator = UIFactory.CreateUIObject("BottomSeperator", UIRoot);
UIFactory.SetLayoutElement(separator, minHeight: 1, flexibleHeight: 0, flexibleWidth: 9999);
separator.AddComponent<Image>().color = Color.black;
return UIRoot;
}
}
}

View File

@ -0,0 +1,73 @@
namespace UnityExplorer.Config
{
public class ConfigElement<T> : IConfigElement
{
public string Name { get; }
public string Description { get; }
public bool IsInternal { get; }
public Type ElementType => typeof(T);
public Action<T> OnValueChanged;
public Action OnValueChangedNotify { get; set; }
public object DefaultValue { get; }
public ConfigHandler Handler => IsInternal
? ConfigManager.InternalHandler
: ConfigManager.Handler;
public T Value
{
get => m_value;
set => SetValue(value);
}
private T m_value;
object IConfigElement.BoxedValue
{
get => m_value;
set => SetValue((T)value);
}
public ConfigElement(string name, string description, T defaultValue, bool isInternal = false)
{
Name = name;
Description = description;
m_value = defaultValue;
DefaultValue = defaultValue;
IsInternal = isInternal;
ConfigManager.RegisterConfigElement(this);
}
private void SetValue(T value)
{
if ((m_value == null && value == null) || (m_value != null && m_value.Equals(value)))
return;
m_value = value;
Handler.SetConfigValue(this, value);
OnValueChanged?.Invoke(value);
OnValueChangedNotify?.Invoke();
Handler.OnAnyConfigChanged();
}
object IConfigElement.GetLoaderConfigValue() => GetLoaderConfigValue();
public T GetLoaderConfigValue()
{
return Handler.GetConfigValue(this);
}
public void RevertToDefaultValue()
{
Value = (T)DefaultValue;
}
}
}

View File

@ -0,0 +1,19 @@
namespace UnityExplorer.Config
{
public abstract class ConfigHandler
{
public abstract void RegisterConfigElement<T>(ConfigElement<T> element);
public abstract void SetConfigValue<T>(ConfigElement<T> element, T value);
public abstract T GetConfigValue<T>(ConfigElement<T> element);
public abstract void Init();
public abstract void LoadConfig();
public abstract void SaveConfig();
public virtual void OnAnyConfigChanged() { }
}
}

Some files were not shown because too many files have changed in this diff Show More