mirror of
https://github.com/GrahamKracker/UnityExplorer.git
synced 2025-07-02 03:22:41 +08:00
Compare commits
8 Commits
Author | SHA1 | Date | |
---|---|---|---|
ef4bc75d5e | |||
68b81c6b53 | |||
bd86f09313 | |||
b35d6f5787 | |||
b97eada516 | |||
0a05848bef | |||
6e5610129a | |||
acd30880a8 |
@ -18,6 +18,12 @@
|
|||||||
|
|
||||||
⚡ 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)
|
⚡ 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)
|
||||||
|
|
||||||
|
## Release schedule
|
||||||
|
|
||||||
|
Releases will be posted at most once per week, generally on weekends.
|
||||||
|
|
||||||
|
Nightly builds can be found [here](https://github.com/sinai-dev/UnityExplorer/actions).
|
||||||
|
|
||||||
## BepInEx
|
## BepInEx
|
||||||
|
|
||||||
| Release | IL2CPP | Mono |
|
| Release | IL2CPP | Mono |
|
||||||
|
Binary file not shown.
Binary file not shown.
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "com.sinai-dev.unityexplorer",
|
"name": "com.sinai-dev.unityexplorer",
|
||||||
"version": "4.7.11",
|
"version": "4.7.12",
|
||||||
"displayName": "UnityExplorer",
|
"displayName": "UnityExplorer",
|
||||||
"description": "An in-game UI for exploring, debugging and modifying Unity games.",
|
"description": "An in-game UI for exploring, debugging and modifying Unity games.",
|
||||||
"unity": "2017.1",
|
"unity": "2017.1",
|
||||||
|
80
build.ps1
80
build.ps1
@ -1,97 +1,125 @@
|
|||||||
# MelonLoader IL2CPP (net6)
|
# ----------- MelonLoader IL2CPP (net6) -----------
|
||||||
dotnet build src\UnityExplorer.sln -c Release_ML_Cpp_net6
|
dotnet build src\UnityExplorer.sln -c Release_ML_Cpp_net6
|
||||||
# (cleanup and move files)
|
|
||||||
$Path = "Release\UnityExplorer.MelonLoader.IL2CPP.net6preview"
|
$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\UnityExplorer.ML.IL2CPP.net6preview.deps.json
|
||||||
Remove-Item $Path\Tomlet.dll
|
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
|
New-Item -Path "$Path" -Name "Mods" -ItemType "directory" -Force
|
||||||
Move-Item -Path $Path\UnityExplorer.ML.IL2CPP.net6preview.dll -Destination $Path\Mods -Force
|
Move-Item -Path $Path\UnityExplorer.ML.IL2CPP.net6preview.dll -Destination $Path\Mods -Force
|
||||||
New-Item -Path "$Path" -Name "UserLibs" -ItemType "directory" -Force
|
New-Item -Path "$Path" -Name "UserLibs" -ItemType "directory" -Force
|
||||||
Move-Item -Path $Path\mcs.dll -Destination $Path\UserLibs -Force
|
|
||||||
Move-Item -Path $Path\UniverseLib.IL2CPP.dll -Destination $Path\UserLibs -Force
|
Move-Item -Path $Path\UniverseLib.IL2CPP.dll -Destination $Path\UserLibs -Force
|
||||||
# (create zip archive)
|
# (create zip archive)
|
||||||
Compress-Archive -Path $Path\* -CompressionLevel Fastest -DestinationPath $Path\..\UnityExplorer.MelonLoader.IL2CPP.net6preview.zip -Force
|
Compress-Archive -Path $Path\* -CompressionLevel Fastest -DestinationPath $Path\..\UnityExplorer.MelonLoader.IL2CPP.net6preview.zip -Force
|
||||||
|
|
||||||
# MelonLoader IL2CPP (net472)
|
# ----------- MelonLoader IL2CPP (net472) -----------
|
||||||
dotnet build src\UnityExplorer.sln -c Release_ML_Cpp_net472
|
dotnet build src\UnityExplorer.sln -c Release_ML_Cpp_net472
|
||||||
# (cleanup and move files)
|
|
||||||
$Path = "Release\UnityExplorer.MelonLoader.IL2CPP"
|
$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\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
|
New-Item -Path "$Path" -Name "Mods" -ItemType "directory" -Force
|
||||||
Move-Item -Path $Path\UnityExplorer.ML.IL2CPP.dll -Destination $Path\Mods -Force
|
Move-Item -Path $Path\UnityExplorer.ML.IL2CPP.dll -Destination $Path\Mods -Force
|
||||||
New-Item -Path "$Path" -Name "UserLibs" -ItemType "directory" -Force
|
New-Item -Path "$Path" -Name "UserLibs" -ItemType "directory" -Force
|
||||||
Move-Item -Path $Path\mcs.dll -Destination $Path\UserLibs -Force
|
|
||||||
Move-Item -Path $Path\UniverseLib.IL2CPP.dll -Destination $Path\UserLibs -Force
|
Move-Item -Path $Path\UniverseLib.IL2CPP.dll -Destination $Path\UserLibs -Force
|
||||||
# (create zip archive)
|
# (create zip archive)
|
||||||
Compress-Archive -Path $Path\* -CompressionLevel Fastest -DestinationPath $Path\..\UnityExplorer.MelonLoader.IL2CPP.zip -Force
|
Compress-Archive -Path $Path\* -CompressionLevel Fastest -DestinationPath $Path\..\UnityExplorer.MelonLoader.IL2CPP.zip -Force
|
||||||
|
|
||||||
# MelonLoader Mono
|
# ----------- MelonLoader Mono -----------
|
||||||
dotnet build src\UnityExplorer.sln -c Release_ML_Mono
|
dotnet build src\UnityExplorer.sln -c Release_ML_Mono
|
||||||
# (cleanup and move files)
|
|
||||||
$Path = "Release\UnityExplorer.MelonLoader.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\Tomlet.dll
|
||||||
|
Remove-Item $Path\mcs.dll
|
||||||
New-Item -Path "$Path" -Name "Mods" -ItemType "directory" -Force
|
New-Item -Path "$Path" -Name "Mods" -ItemType "directory" -Force
|
||||||
Move-Item -Path $Path\UnityExplorer.ML.Mono.dll -Destination $Path\Mods -Force
|
Move-Item -Path $Path\UnityExplorer.ML.Mono.dll -Destination $Path\Mods -Force
|
||||||
New-Item -Path "$Path" -Name "UserLibs" -ItemType "directory" -Force
|
New-Item -Path "$Path" -Name "UserLibs" -ItemType "directory" -Force
|
||||||
Move-Item -Path $Path\mcs.dll -Destination $Path\UserLibs -Force
|
|
||||||
Move-Item -Path $Path\UniverseLib.Mono.dll -Destination $Path\UserLibs -Force
|
Move-Item -Path $Path\UniverseLib.Mono.dll -Destination $Path\UserLibs -Force
|
||||||
# (create zip archive)
|
# (create zip archive)
|
||||||
Compress-Archive -Path $Path\* -CompressionLevel Fastest -DestinationPath $Path\..\UnityExplorer.MelonLoader.Mono.zip -Force
|
Compress-Archive -Path $Path\* -CompressionLevel Fastest -DestinationPath $Path\..\UnityExplorer.MelonLoader.Mono.zip -Force
|
||||||
|
|
||||||
# BepInEx IL2CPP
|
# ----------- BepInEx IL2CPP -----------
|
||||||
dotnet build src\UnityExplorer.sln -c Release_BIE_Cpp
|
dotnet build src\UnityExplorer.sln -c Release_BIE_Cpp
|
||||||
# (cleanup and move files)
|
|
||||||
$Path = "Release\UnityExplorer.BepInEx.IL2CPP"
|
$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" -ItemType "directory" -Force
|
||||||
New-Item -Path "$Path" -Name "plugins\sinai-dev-UnityExplorer" -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\UnityExplorer.BIE.IL2CPP.dll -Destination $Path\plugins\sinai-dev-UnityExplorer -Force
|
||||||
Move-Item -Path $Path\mcs.dll -Destination $Path\plugins\sinai-dev-UnityExplorer -Force
|
|
||||||
Move-Item -Path $Path\Tomlet.dll -Destination $Path\plugins\sinai-dev-UnityExplorer -Force
|
|
||||||
Move-Item -Path $Path\UniverseLib.IL2CPP.dll -Destination $Path\plugins\sinai-dev-UnityExplorer -Force
|
Move-Item -Path $Path\UniverseLib.IL2CPP.dll -Destination $Path\plugins\sinai-dev-UnityExplorer -Force
|
||||||
# (create zip archive)
|
# (create zip archive)
|
||||||
Compress-Archive -Path $Path\* -CompressionLevel Fastest -DestinationPath $Path\..\UnityExplorer.BepInEx.IL2CPP.zip -Force
|
Compress-Archive -Path $Path\* -CompressionLevel Fastest -DestinationPath $Path\..\UnityExplorer.BepInEx.IL2CPP.zip -Force
|
||||||
|
|
||||||
# BepInEx 5 Mono
|
# ----------- BepInEx 5 Mono -----------
|
||||||
dotnet build src\UnityExplorer.sln -c Release_BIE5_Mono
|
dotnet build src\UnityExplorer.sln -c Release_BIE5_Mono
|
||||||
# (cleanup and move files)
|
|
||||||
$Path = "Release\UnityExplorer.BepInEx5.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" -ItemType "directory" -Force
|
||||||
New-Item -Path "$Path" -Name "plugins\sinai-dev-UnityExplorer" -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\UnityExplorer.BIE5.Mono.dll -Destination $Path\plugins\sinai-dev-UnityExplorer -Force
|
||||||
Move-Item -Path $Path\mcs.dll -Destination $Path\plugins\sinai-dev-UnityExplorer -Force
|
|
||||||
Move-Item -Path $Path\Tomlet.dll -Destination $Path\plugins\sinai-dev-UnityExplorer -Force
|
|
||||||
Move-Item -Path $Path\UniverseLib.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)
|
# (create zip archive)
|
||||||
Compress-Archive -Path $Path\* -CompressionLevel Fastest -DestinationPath $Path\..\UnityExplorer.BepInEx5.Mono.zip -Force
|
Compress-Archive -Path $Path\* -CompressionLevel Fastest -DestinationPath $Path\..\UnityExplorer.BepInEx5.Mono.zip -Force
|
||||||
|
|
||||||
# BepInEx 6 Mono
|
# ----------- BepInEx 6 Mono -----------
|
||||||
dotnet build src\UnityExplorer.sln -c Release_BIE6_Mono
|
dotnet build src\UnityExplorer.sln -c Release_BIE6_Mono
|
||||||
# (cleanup and move files)
|
|
||||||
$Path = "Release\UnityExplorer.BepInEx6.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" -ItemType "directory" -Force
|
||||||
New-Item -Path "$Path" -Name "plugins\sinai-dev-UnityExplorer" -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\UnityExplorer.BIE6.Mono.dll -Destination $Path\plugins\sinai-dev-UnityExplorer -Force
|
||||||
Move-Item -Path $Path\mcs.dll -Destination $Path\plugins\sinai-dev-UnityExplorer -Force
|
|
||||||
Move-Item -Path $Path\Tomlet.dll -Destination $Path\plugins\sinai-dev-UnityExplorer -Force
|
|
||||||
Move-Item -Path $Path\UniverseLib.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)
|
# (create zip archive)
|
||||||
Compress-Archive -Path $Path\* -CompressionLevel Fastest -DestinationPath $Path\..\UnityExplorer.BepInEx6.Mono.zip -Force
|
Compress-Archive -Path $Path\* -CompressionLevel Fastest -DestinationPath $Path\..\UnityExplorer.BepInEx6.Mono.zip -Force
|
||||||
|
|
||||||
# Standalone Mono
|
# ----------- Standalone Mono -----------
|
||||||
dotnet build src\UnityExplorer.sln -c Release_STANDALONE_Mono
|
dotnet build src\UnityExplorer.sln -c Release_STANDALONE_Mono
|
||||||
$Path = "Release\UnityExplorer.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
|
||||||
Compress-Archive -Path $Path\* -CompressionLevel Fastest -DestinationPath $Path\..\UnityExplorer.Standalone.Mono.zip -Force
|
Compress-Archive -Path $Path\* -CompressionLevel Fastest -DestinationPath $Path\..\UnityExplorer.Standalone.Mono.zip -Force
|
||||||
|
|
||||||
# Standalone IL2CPP
|
# ----------- Standalone IL2CPP -----------
|
||||||
dotnet build src\UnityExplorer.sln -c Release_STANDALONE_Cpp
|
dotnet build src\UnityExplorer.sln -c Release_STANDALONE_Cpp
|
||||||
$Path = "Release\UnityExplorer.Standalone.IL2CPP"
|
$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
|
||||||
Compress-Archive -Path $Path\* -CompressionLevel Fastest -DestinationPath $Path\..\UnityExplorer.Standalone.IL2CPP.zip -Force
|
Compress-Archive -Path $Path\* -CompressionLevel Fastest -DestinationPath $Path\..\UnityExplorer.Standalone.IL2CPP.zip -Force
|
||||||
|
|
||||||
# Editor (mono)
|
# ----------- Editor (mono) -----------
|
||||||
$Path1 = "Release\UnityExplorer.Standalone.Mono"
|
$Path1 = "Release\UnityExplorer.Standalone.Mono"
|
||||||
$Path2 = "UnityEditorPackage\Runtime"
|
$Path2 = "UnityEditorPackage\Runtime"
|
||||||
Copy-Item $Path1\UnityExplorer.STANDALONE.Mono.dll -Destination $Path2
|
Copy-Item $Path1\UnityExplorer.STANDALONE.Mono.dll -Destination $Path2
|
||||||
Copy-Item $Path1\mcs.dll -Destination $Path2
|
|
||||||
Copy-Item $Path1\Tomlet.dll -Destination $Path2
|
|
||||||
Copy-Item $Path1\UniverseLib.Mono.dll -Destination $Path2
|
Copy-Item $Path1\UniverseLib.Mono.dll -Destination $Path2
|
||||||
Compress-Archive -Path UnityEditorPackage\* -CompressionLevel Fastest -DestinationPath Release\UnityExplorer.Editor.zip -Force
|
Compress-Archive -Path UnityEditorPackage\* -CompressionLevel Fastest -DestinationPath Release\UnityExplorer.Editor.zip -Force
|
BIN
lib/ILRepack.exe
Normal file
BIN
lib/ILRepack.exe
Normal file
Binary file not shown.
BIN
lib/net6/System.Runtime.dll
Normal file
BIN
lib/net6/System.Runtime.dll
Normal file
Binary file not shown.
@ -239,10 +239,13 @@ namespace UnityExplorer.CSConsole
|
|||||||
if (SRENotSupported)
|
if (SRENotSupported)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (InputManager.GetKeyDown(KeyCode.Home))
|
if (!InputManager.GetKey(KeyCode.LeftControl) && !InputManager.GetKey(KeyCode.RightControl))
|
||||||
JumpToStartOrEndOfLine(true);
|
{
|
||||||
else if (InputManager.GetKeyDown(KeyCode.End))
|
if (InputManager.GetKeyDown(KeyCode.Home))
|
||||||
JumpToStartOrEndOfLine(false);
|
JumpToStartOrEndOfLine(true);
|
||||||
|
else if (InputManager.GetKeyDown(KeyCode.End))
|
||||||
|
JumpToStartOrEndOfLine(false);
|
||||||
|
}
|
||||||
|
|
||||||
UpdateCaret(out bool caretMoved);
|
UpdateCaret(out bool caretMoved);
|
||||||
|
|
||||||
@ -459,9 +462,6 @@ namespace UnityExplorer.CSConsole
|
|||||||
|
|
||||||
#region Lexer Highlighting
|
#region Lexer Highlighting
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Returns true if caret is inside string or comment, false otherwise
|
|
||||||
/// </summary>
|
|
||||||
private static void HighlightVisibleInput(out bool inStringOrComment)
|
private static void HighlightVisibleInput(out bool inStringOrComment)
|
||||||
{
|
{
|
||||||
inStringOrComment = false;
|
inStringOrComment = false;
|
||||||
|
@ -28,28 +28,31 @@ namespace UnityExplorer.CacheObject
|
|||||||
public abstract class CacheObjectBase
|
public abstract class CacheObjectBase
|
||||||
{
|
{
|
||||||
public ICacheObjectController Owner { get; set; }
|
public ICacheObjectController Owner { get; set; }
|
||||||
|
|
||||||
public CacheObjectCell CellView { get; internal set; }
|
public CacheObjectCell CellView { get; internal set; }
|
||||||
|
|
||||||
public object Value { get; protected set; }
|
public object Value { get; protected set; }
|
||||||
public Type FallbackType { get; protected set; }
|
public Type FallbackType { get; protected set; }
|
||||||
public bool LastValueWasNull { get; private set; }
|
public ValueState State { get; set; }
|
||||||
|
public Exception LastException { get; protected set; }
|
||||||
public ValueState State = ValueState.NotEvaluated;
|
bool valueIsNull;
|
||||||
public Type LastValueType;
|
Type currentValueType;
|
||||||
|
|
||||||
|
// InteractiveValues
|
||||||
public InteractiveValue IValue { get; private set; }
|
public InteractiveValue IValue { get; private set; }
|
||||||
public Type CurrentIValueType { get; private set; }
|
public Type CurrentIValueType { get; private set; }
|
||||||
public bool SubContentShowWanted { get; private set; }
|
public bool SubContentShowWanted { get; private set; }
|
||||||
|
|
||||||
|
// UI
|
||||||
public string NameLabelText { get; protected set; }
|
public string NameLabelText { get; protected set; }
|
||||||
public string NameLabelTextRaw { get; protected set; }
|
public string NameLabelTextRaw { get; protected set; }
|
||||||
public string ValueLabelText { get; protected set; }
|
public string ValueLabelText { get; protected set; }
|
||||||
|
|
||||||
|
// Abstract
|
||||||
public abstract bool ShouldAutoEvaluate { get; }
|
public abstract bool ShouldAutoEvaluate { get; }
|
||||||
public abstract bool HasArguments { get; }
|
public abstract bool HasArguments { get; }
|
||||||
public abstract bool CanWrite { get; }
|
public abstract bool CanWrite { get; }
|
||||||
public Exception LastException { get; protected set; }
|
|
||||||
|
protected const string NOT_YET_EVAL = "<color=grey>Not yet evaluated</color>";
|
||||||
|
|
||||||
public virtual void SetFallbackType(Type fallbackType)
|
public virtual void SetFallbackType(Type fallbackType)
|
||||||
{
|
{
|
||||||
@ -57,17 +60,6 @@ namespace UnityExplorer.CacheObject
|
|||||||
this.ValueLabelText = GetValueLabel();
|
this.ValueLabelText = GetValueLabel();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected const string NOT_YET_EVAL = "<color=grey>Not yet evaluated</color>";
|
|
||||||
|
|
||||||
public virtual void ReleasePooledObjects()
|
|
||||||
{
|
|
||||||
if (this.IValue != null)
|
|
||||||
ReleaseIValue();
|
|
||||||
|
|
||||||
if (this.CellView != null)
|
|
||||||
UnlinkFromView();
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual void SetView(CacheObjectCell cellView)
|
public virtual void SetView(CacheObjectCell cellView)
|
||||||
{
|
{
|
||||||
this.CellView = cellView;
|
this.CellView = cellView;
|
||||||
@ -86,6 +78,15 @@ namespace UnityExplorer.CacheObject
|
|||||||
this.IValue.UIRoot.transform.SetParent(InactiveIValueHolder.transform, false);
|
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
|
// Updating and applying values
|
||||||
|
|
||||||
// The only method which sets the CacheObjectBase.Value
|
// The only method which sets the CacheObjectBase.Value
|
||||||
@ -130,18 +131,18 @@ namespace UnityExplorer.CacheObject
|
|||||||
|
|
||||||
if (LastException != null)
|
if (LastException != null)
|
||||||
{
|
{
|
||||||
LastValueWasNull = true;
|
valueIsNull = true;
|
||||||
LastValueType = FallbackType;
|
currentValueType = FallbackType;
|
||||||
State = ValueState.Exception;
|
State = ValueState.Exception;
|
||||||
}
|
}
|
||||||
else if (Value.IsNullOrDestroyed())
|
else if (Value.IsNullOrDestroyed())
|
||||||
{
|
{
|
||||||
LastValueWasNull = true;
|
valueIsNull = true;
|
||||||
State = GetStateForType(FallbackType);
|
State = GetStateForType(FallbackType);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LastValueWasNull = false;
|
valueIsNull = false;
|
||||||
State = GetStateForType(Value.GetActualType());
|
State = GetStateForType(Value.GetActualType());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -163,10 +164,10 @@ namespace UnityExplorer.CacheObject
|
|||||||
|
|
||||||
public ValueState GetStateForType(Type type)
|
public ValueState GetStateForType(Type type)
|
||||||
{
|
{
|
||||||
if (LastValueType == type && (State != ValueState.Exception || LastException != null))
|
if (currentValueType == type && (State != ValueState.Exception || LastException != null))
|
||||||
return State;
|
return State;
|
||||||
|
|
||||||
LastValueType = type;
|
currentValueType = type;
|
||||||
if (type == typeof(bool))
|
if (type == typeof(bool))
|
||||||
return ValueState.Boolean;
|
return ValueState.Boolean;
|
||||||
else if (type.IsPrimitive || type == typeof(decimal))
|
else if (type.IsPrimitive || type == typeof(decimal))
|
||||||
@ -189,7 +190,7 @@ namespace UnityExplorer.CacheObject
|
|||||||
|
|
||||||
protected string GetValueLabel()
|
protected string GetValueLabel()
|
||||||
{
|
{
|
||||||
string label = "";
|
string label = string.Empty;
|
||||||
|
|
||||||
switch (State)
|
switch (State)
|
||||||
{
|
{
|
||||||
@ -206,19 +207,19 @@ namespace UnityExplorer.CacheObject
|
|||||||
|
|
||||||
// and valuestruct also doesnt want it if we can parse it
|
// and valuestruct also doesnt want it if we can parse it
|
||||||
case ValueState.ValueStruct:
|
case ValueState.ValueStruct:
|
||||||
if (ParseUtility.CanParse(LastValueType))
|
if (ParseUtility.CanParse(currentValueType))
|
||||||
return null;
|
return null;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// string wants it trimmed to max 200 chars
|
// string wants it trimmed to max 200 chars
|
||||||
case ValueState.String:
|
case ValueState.String:
|
||||||
if (!LastValueWasNull)
|
if (!valueIsNull)
|
||||||
return $"\"{ToStringUtility.PruneString(Value as string, 200, 5)}\"";
|
return $"\"{ToStringUtility.PruneString(Value as string, 200, 5)}\"";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// try to prefix the count of the collection for lists and dicts
|
// try to prefix the count of the collection for lists and dicts
|
||||||
case ValueState.Collection:
|
case ValueState.Collection:
|
||||||
if (!LastValueWasNull)
|
if (!valueIsNull)
|
||||||
{
|
{
|
||||||
if (Value is IList iList)
|
if (Value is IList iList)
|
||||||
label = $"[{iList.Count}] ";
|
label = $"[{iList.Count}] ";
|
||||||
@ -230,7 +231,7 @@ namespace UnityExplorer.CacheObject
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case ValueState.Dictionary:
|
case ValueState.Dictionary:
|
||||||
if (!LastValueWasNull)
|
if (!valueIsNull)
|
||||||
{
|
{
|
||||||
if (Value is IDictionary iDict)
|
if (Value is IDictionary iDict)
|
||||||
label = $"[{iDict.Count}] ";
|
label = $"[{iDict.Count}] ";
|
||||||
@ -291,7 +292,7 @@ namespace UnityExplorer.CacheObject
|
|||||||
SetValueState(cell, new(false, typeLabelActive: true, inputActive: true, applyActive: CanWrite));
|
SetValueState(cell, new(false, typeLabelActive: true, inputActive: true, applyActive: CanWrite));
|
||||||
break;
|
break;
|
||||||
case ValueState.String:
|
case ValueState.String:
|
||||||
if (LastValueWasNull)
|
if (valueIsNull)
|
||||||
SetValueState(cell, new(true, subContentButtonActive: true));
|
SetValueState(cell, new(true, subContentButtonActive: true));
|
||||||
else
|
else
|
||||||
SetValueState(cell, new(true, false, SignatureHighlighter.StringOrange, subContentButtonActive: true));
|
SetValueState(cell, new(true, false, SignatureHighlighter.StringOrange, subContentButtonActive: true));
|
||||||
@ -301,17 +302,17 @@ namespace UnityExplorer.CacheObject
|
|||||||
break;
|
break;
|
||||||
case ValueState.Color:
|
case ValueState.Color:
|
||||||
case ValueState.ValueStruct:
|
case ValueState.ValueStruct:
|
||||||
if (ParseUtility.CanParse(LastValueType))
|
if (ParseUtility.CanParse(currentValueType))
|
||||||
SetValueState(cell, new(false, false, null, true, false, true, CanWrite, true, true));
|
SetValueState(cell, new(false, false, null, true, false, true, CanWrite, true, true));
|
||||||
else
|
else
|
||||||
SetValueState(cell, new(true, inspectActive: true, subContentButtonActive: true));
|
SetValueState(cell, new(true, inspectActive: true, subContentButtonActive: true));
|
||||||
break;
|
break;
|
||||||
case ValueState.Collection:
|
case ValueState.Collection:
|
||||||
case ValueState.Dictionary:
|
case ValueState.Dictionary:
|
||||||
SetValueState(cell, new(true, inspectActive: !LastValueWasNull, subContentButtonActive: !LastValueWasNull));
|
SetValueState(cell, new(true, inspectActive: !valueIsNull, subContentButtonActive: !valueIsNull));
|
||||||
break;
|
break;
|
||||||
case ValueState.Unsupported:
|
case ValueState.Unsupported:
|
||||||
SetValueState(cell, new(true, inspectActive: !LastValueWasNull));
|
SetValueState(cell, new(true, inspectActive: !valueIsNull));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -333,7 +334,7 @@ namespace UnityExplorer.CacheObject
|
|||||||
// Type label (for primitives)
|
// Type label (for primitives)
|
||||||
cell.TypeLabel.gameObject.SetActive(args.typeLabelActive);
|
cell.TypeLabel.gameObject.SetActive(args.typeLabelActive);
|
||||||
if (args.typeLabelActive)
|
if (args.typeLabelActive)
|
||||||
cell.TypeLabel.text = SignatureHighlighter.Parse(LastValueType, false);
|
cell.TypeLabel.text = SignatureHighlighter.Parse(currentValueType, false);
|
||||||
|
|
||||||
// toggle for bools
|
// toggle for bools
|
||||||
cell.Toggle.gameObject.SetActive(args.toggleActive);
|
cell.Toggle.gameObject.SetActive(args.toggleActive);
|
||||||
@ -348,7 +349,7 @@ namespace UnityExplorer.CacheObject
|
|||||||
cell.InputField.UIRoot.SetActive(args.inputActive);
|
cell.InputField.UIRoot.SetActive(args.inputActive);
|
||||||
if (args.inputActive)
|
if (args.inputActive)
|
||||||
{
|
{
|
||||||
cell.InputField.Text = ParseUtility.ToStringForInput(Value, LastValueType);
|
cell.InputField.Text = ParseUtility.ToStringForInput(Value, currentValueType);
|
||||||
cell.InputField.Component.readOnly = !CanWrite;
|
cell.InputField.Component.readOnly = !CanWrite;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -357,12 +358,12 @@ namespace UnityExplorer.CacheObject
|
|||||||
|
|
||||||
// Inspect button only if last value not null.
|
// Inspect button only if last value not null.
|
||||||
if (cell.InspectButton != null)
|
if (cell.InspectButton != null)
|
||||||
cell.InspectButton.Component.gameObject.SetActive(args.inspectActive && !LastValueWasNull);
|
cell.InspectButton.Component.gameObject.SetActive(args.inspectActive && !valueIsNull);
|
||||||
|
|
||||||
// set subcontent button if needed, and for null strings and exceptions
|
// set subcontent button if needed, and for null strings and exceptions
|
||||||
cell.SubContentButton.Component.gameObject.SetActive(
|
cell.SubContentButton.Component.gameObject.SetActive(
|
||||||
args.subContentButtonActive
|
args.subContentButtonActive
|
||||||
&& (!LastValueWasNull || State == ValueState.String || State == ValueState.Exception));
|
&& (!valueIsNull || State == ValueState.String || State == ValueState.Exception));
|
||||||
}
|
}
|
||||||
|
|
||||||
// CacheObjectCell Apply
|
// CacheObjectCell Apply
|
||||||
@ -373,7 +374,7 @@ namespace UnityExplorer.CacheObject
|
|||||||
SetUserValue(this.CellView.Toggle.isOn);
|
SetUserValue(this.CellView.Toggle.isOn);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (ParseUtility.TryParse(CellView.InputField.Text, LastValueType, out object value, out Exception ex))
|
if (ParseUtility.TryParse(CellView.InputField.Text, currentValueType, out object value, out Exception ex))
|
||||||
{
|
{
|
||||||
SetUserValue(value);
|
SetUserValue(value);
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ namespace UnityExplorer
|
|||||||
public static class ExplorerCore
|
public static class ExplorerCore
|
||||||
{
|
{
|
||||||
public const string NAME = "UnityExplorer";
|
public const string NAME = "UnityExplorer";
|
||||||
public const string VERSION = "4.7.11";
|
public const string VERSION = "4.7.12";
|
||||||
public const string AUTHOR = "Sinai";
|
public const string AUTHOR = "Sinai";
|
||||||
public const string GUID = "com.sinai.unityexplorer";
|
public const string GUID = "com.sinai.unityexplorer";
|
||||||
|
|
||||||
|
@ -18,11 +18,11 @@ namespace UnityExplorer.Inspectors
|
|||||||
{
|
{
|
||||||
public class GameObjectInspector : InspectorBase
|
public class GameObjectInspector : InspectorBase
|
||||||
{
|
{
|
||||||
public GameObject GOTarget => Target as GameObject;
|
public new GameObject Target => base.Target as GameObject;
|
||||||
|
|
||||||
public GameObject Content;
|
public GameObject Content;
|
||||||
|
|
||||||
public GameObjectControls GOControls;
|
public GameObjectControls Controls;
|
||||||
|
|
||||||
public TransformTree TransformTree;
|
public TransformTree TransformTree;
|
||||||
private ScrollPool<TransformCell> transformScroll;
|
private ScrollPool<TransformCell> transformScroll;
|
||||||
@ -38,10 +38,10 @@ namespace UnityExplorer.Inspectors
|
|||||||
{
|
{
|
||||||
base.OnBorrowedFromPool(target);
|
base.OnBorrowedFromPool(target);
|
||||||
|
|
||||||
Target = target as GameObject;
|
base.Target = target as GameObject;
|
||||||
|
|
||||||
GOControls.UpdateGameObjectInfo(true, true);
|
Controls.UpdateGameObjectInfo(true, true);
|
||||||
GOControls.UpdateTransformControlValues(true);
|
Controls.TransformControl.UpdateTransformControlValues(true);
|
||||||
|
|
||||||
RuntimeHelper.StartCoroutine(InitCoroutine());
|
RuntimeHelper.StartCoroutine(InitCoroutine());
|
||||||
}
|
}
|
||||||
@ -76,9 +76,9 @@ namespace UnityExplorer.Inspectors
|
|||||||
|
|
||||||
public void OnTransformCellClicked(GameObject newTarget)
|
public void OnTransformCellClicked(GameObject newTarget)
|
||||||
{
|
{
|
||||||
this.Target = newTarget;
|
base.Target = newTarget;
|
||||||
GOControls.UpdateGameObjectInfo(true, true);
|
Controls.UpdateGameObjectInfo(true, true);
|
||||||
GOControls.UpdateTransformControlValues(true);
|
Controls.TransformControl.UpdateTransformControlValues(true);
|
||||||
TransformTree.RefreshData(true, false, true, false);
|
TransformTree.RefreshData(true, false, true, false);
|
||||||
UpdateComponents();
|
UpdateComponents();
|
||||||
}
|
}
|
||||||
@ -90,21 +90,21 @@ namespace UnityExplorer.Inspectors
|
|||||||
if (!this.IsActive)
|
if (!this.IsActive)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (Target.IsNullOrDestroyed(false))
|
if (base.Target.IsNullOrDestroyed(false))
|
||||||
{
|
{
|
||||||
InspectorManager.ReleaseInspector(this);
|
InspectorManager.ReleaseInspector(this);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GOControls.UpdateVectorSlider();
|
Controls.UpdateVectorSlider();
|
||||||
GOControls.UpdateTransformControlValues(false);
|
Controls.TransformControl.UpdateTransformControlValues(false);
|
||||||
|
|
||||||
// Slow update
|
// Slow update
|
||||||
if (timeOfLastUpdate.OccuredEarlierThan(1))
|
if (timeOfLastUpdate.OccuredEarlierThan(1))
|
||||||
{
|
{
|
||||||
timeOfLastUpdate = Time.realtimeSinceStartup;
|
timeOfLastUpdate = Time.realtimeSinceStartup;
|
||||||
|
|
||||||
GOControls.UpdateGameObjectInfo(false, false);
|
Controls.UpdateGameObjectInfo(false, false);
|
||||||
|
|
||||||
TransformTree.RefreshData(true, false, false, false);
|
TransformTree.RefreshData(true, false, false, false);
|
||||||
UpdateComponents();
|
UpdateComponents();
|
||||||
@ -115,12 +115,12 @@ namespace UnityExplorer.Inspectors
|
|||||||
|
|
||||||
private IEnumerable<GameObject> GetTransformEntries()
|
private IEnumerable<GameObject> GetTransformEntries()
|
||||||
{
|
{
|
||||||
if (!GOTarget)
|
if (!Target)
|
||||||
return Enumerable.Empty<GameObject>();
|
return Enumerable.Empty<GameObject>();
|
||||||
|
|
||||||
cachedChildren.Clear();
|
cachedChildren.Clear();
|
||||||
for (int i = 0; i < GOTarget.transform.childCount; i++)
|
for (int i = 0; i < Target.transform.childCount; i++)
|
||||||
cachedChildren.Add(GOTarget.transform.GetChild(i).gameObject);
|
cachedChildren.Add(Target.transform.GetChild(i).gameObject);
|
||||||
return cachedChildren;
|
return cachedChildren;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,11 +130,11 @@ namespace UnityExplorer.Inspectors
|
|||||||
private readonly List<bool> behaviourEnabledStates = new();
|
private readonly List<bool> behaviourEnabledStates = new();
|
||||||
|
|
||||||
// ComponentList.GetRootEntriesMethod
|
// ComponentList.GetRootEntriesMethod
|
||||||
private List<Component> GetComponentEntries() => GOTarget ? componentEntries : Enumerable.Empty<Component>().ToList();
|
private List<Component> GetComponentEntries() => Target ? componentEntries : Enumerable.Empty<Component>().ToList();
|
||||||
|
|
||||||
public void UpdateComponents()
|
public void UpdateComponents()
|
||||||
{
|
{
|
||||||
if (!GOTarget)
|
if (!Target)
|
||||||
{
|
{
|
||||||
componentEntries.Clear();
|
componentEntries.Clear();
|
||||||
compInstanceIDs.Clear();
|
compInstanceIDs.Clear();
|
||||||
@ -146,8 +146,8 @@ namespace UnityExplorer.Inspectors
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if we actually need to refresh the component cells or not.
|
// Check if we actually need to refresh the component cells or not.
|
||||||
IEnumerable<Component> comps = GOTarget.GetComponents<Component>();
|
IEnumerable<Component> comps = Target.GetComponents<Component>();
|
||||||
IEnumerable<Behaviour> behaviours = GOTarget.GetComponents<Behaviour>();
|
IEnumerable<Behaviour> behaviours = Target.GetComponents<Behaviour>();
|
||||||
|
|
||||||
bool needRefresh = false;
|
bool needRefresh = false;
|
||||||
|
|
||||||
@ -231,7 +231,7 @@ namespace UnityExplorer.Inspectors
|
|||||||
private void OnAddChildClicked(string input)
|
private void OnAddChildClicked(string input)
|
||||||
{
|
{
|
||||||
GameObject newObject = new(input);
|
GameObject newObject = new(input);
|
||||||
newObject.transform.parent = GOTarget.transform;
|
newObject.transform.parent = Target.transform;
|
||||||
|
|
||||||
TransformTree.RefreshData(true, false, true, false);
|
TransformTree.RefreshData(true, false, true, false);
|
||||||
}
|
}
|
||||||
@ -242,7 +242,7 @@ namespace UnityExplorer.Inspectors
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
RuntimeHelper.AddComponent<Component>(GOTarget, type);
|
RuntimeHelper.AddComponent<Component>(Target, type);
|
||||||
UpdateComponents();
|
UpdateComponents();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@ -270,7 +270,7 @@ namespace UnityExplorer.Inspectors
|
|||||||
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(Content, spacing: 3, padTop: 2, padBottom: 2, padLeft: 2, padRight: 2);
|
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(Content, spacing: 3, padTop: 2, padBottom: 2, padLeft: 2, padRight: 2);
|
||||||
|
|
||||||
// Construct GO Controls
|
// Construct GO Controls
|
||||||
GOControls = new GameObjectControls(this);
|
Controls = new GameObjectControls(this);
|
||||||
|
|
||||||
ConstructLists();
|
ConstructLists();
|
||||||
|
|
||||||
|
@ -1,696 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using UnityEngine;
|
|
||||||
using UnityEngine.UI;
|
|
||||||
using UnityExplorer.UI;
|
|
||||||
using UnityExplorer.UI.Panels;
|
|
||||||
using UniverseLib;
|
|
||||||
using UniverseLib.Input;
|
|
||||||
using UniverseLib.UI;
|
|
||||||
using UniverseLib.UI.Models;
|
|
||||||
using UniverseLib.Utility;
|
|
||||||
|
|
||||||
namespace UnityExplorer.Inspectors
|
|
||||||
{
|
|
||||||
public class GameObjectControls
|
|
||||||
{
|
|
||||||
public GameObjectInspector Parent;
|
|
||||||
private GameObject GOTarget => Parent.GOTarget;
|
|
||||||
|
|
||||||
// Top info
|
|
||||||
|
|
||||||
private ButtonRef ViewParentButton;
|
|
||||||
private InputFieldRef PathInput;
|
|
||||||
|
|
||||||
private InputFieldRef NameInput;
|
|
||||||
private Toggle ActiveSelfToggle;
|
|
||||||
private Text ActiveSelfText;
|
|
||||||
private Toggle IsStaticToggle;
|
|
||||||
|
|
||||||
private InputFieldRef SceneInput;
|
|
||||||
private InputFieldRef InstanceIDInput;
|
|
||||||
private InputFieldRef TagInput;
|
|
||||||
|
|
||||||
private Dropdown LayerDropdown;
|
|
||||||
private Dropdown FlagsDropdown;
|
|
||||||
|
|
||||||
// transform controls
|
|
||||||
|
|
||||||
private TransformControl PositionControl;
|
|
||||||
private TransformControl LocalPositionControl;
|
|
||||||
private TransformControl RotationControl;
|
|
||||||
private TransformControl ScaleControl;
|
|
||||||
|
|
||||||
private VectorSlider currentSlidingVectorControl;
|
|
||||||
private float currentVectorValue;
|
|
||||||
|
|
||||||
public GameObjectControls(GameObjectInspector parent)
|
|
||||||
{
|
|
||||||
this.Parent = parent;
|
|
||||||
|
|
||||||
ConstructTopInfo();
|
|
||||||
ConstructTransformControls();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnCopyClicked()
|
|
||||||
{
|
|
||||||
ClipboardPanel.Copy(this.GOTarget);
|
|
||||||
}
|
|
||||||
|
|
||||||
#region GO Controls
|
|
||||||
|
|
||||||
private string lastGoName;
|
|
||||||
private string lastPath;
|
|
||||||
private bool lastParentState;
|
|
||||||
private int lastSceneHandle;
|
|
||||||
private string lastTag;
|
|
||||||
private int lastLayer;
|
|
||||||
private int lastFlags;
|
|
||||||
|
|
||||||
public void UpdateGameObjectInfo(bool firstUpdate, bool force)
|
|
||||||
{
|
|
||||||
if (firstUpdate)
|
|
||||||
{
|
|
||||||
InstanceIDInput.Text = GOTarget.GetInstanceID().ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (force || (!NameInput.Component.isFocused && GOTarget.name != lastGoName))
|
|
||||||
{
|
|
||||||
lastGoName = GOTarget.name;
|
|
||||||
Parent.Tab.TabText.text = $"[G] {GOTarget.name}";
|
|
||||||
NameInput.Text = GOTarget.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (force || !PathInput.Component.isFocused)
|
|
||||||
{
|
|
||||||
string path = GOTarget.transform.GetTransformPath();
|
|
||||||
if (path != lastPath)
|
|
||||||
{
|
|
||||||
lastPath = path;
|
|
||||||
PathInput.Text = path;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (force || GOTarget.transform.parent != lastParentState)
|
|
||||||
{
|
|
||||||
lastParentState = GOTarget.transform.parent;
|
|
||||||
ViewParentButton.Component.interactable = lastParentState;
|
|
||||||
if (lastParentState)
|
|
||||||
{
|
|
||||||
ViewParentButton.ButtonText.color = Color.white;
|
|
||||||
ViewParentButton.ButtonText.text = "◄ View Parent";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ViewParentButton.ButtonText.color = Color.grey;
|
|
||||||
ViewParentButton.ButtonText.text = "No parent";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (force || GOTarget.activeSelf != ActiveSelfToggle.isOn)
|
|
||||||
{
|
|
||||||
ActiveSelfToggle.Set(GOTarget.activeSelf, false);
|
|
||||||
ActiveSelfText.color = ActiveSelfToggle.isOn ? Color.green : Color.red;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (force || GOTarget.isStatic != IsStaticToggle.isOn)
|
|
||||||
{
|
|
||||||
IsStaticToggle.Set(GOTarget.isStatic, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (force || GOTarget.scene.handle != lastSceneHandle)
|
|
||||||
{
|
|
||||||
lastSceneHandle = GOTarget.scene.handle;
|
|
||||||
SceneInput.Text = GOTarget.scene.IsValid() ? GOTarget.scene.name : "None (Asset/Resource)";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (force || (!TagInput.Component.isFocused && GOTarget.tag != lastTag))
|
|
||||||
{
|
|
||||||
lastTag = GOTarget.tag;
|
|
||||||
TagInput.Text = lastTag;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (force || (GOTarget.layer != lastLayer))
|
|
||||||
{
|
|
||||||
lastLayer = GOTarget.layer;
|
|
||||||
LayerDropdown.value = GOTarget.layer;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (force || ((int)GOTarget.hideFlags != lastFlags))
|
|
||||||
{
|
|
||||||
lastFlags = (int)GOTarget.hideFlags;
|
|
||||||
FlagsDropdown.captionText.text = GOTarget.hideFlags.ToString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnViewParentClicked()
|
|
||||||
{
|
|
||||||
if (this.GOTarget && this.GOTarget.transform.parent)
|
|
||||||
{
|
|
||||||
Parent.OnTransformCellClicked(this.GOTarget.transform.parent.gameObject);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnPathEndEdit(string input)
|
|
||||||
{
|
|
||||||
lastPath = input;
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(input))
|
|
||||||
{
|
|
||||||
DoSetParent(null);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Transform parentToSet = null;
|
|
||||||
|
|
||||||
if (input.EndsWith("/"))
|
|
||||||
input = input.Remove(input.Length - 1);
|
|
||||||
|
|
||||||
// try the easy way
|
|
||||||
if (GameObject.Find(input) is GameObject found)
|
|
||||||
{
|
|
||||||
parentToSet = found.transform;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// look for inactive objects
|
|
||||||
string name = input.Split('/').Last();
|
|
||||||
UnityEngine.Object[] allObjects = RuntimeHelper.FindObjectsOfTypeAll(typeof(GameObject));
|
|
||||||
List<GameObject> shortList = new();
|
|
||||||
foreach (UnityEngine.Object obj in allObjects)
|
|
||||||
if (obj.name == name) shortList.Add(obj.TryCast<GameObject>());
|
|
||||||
foreach (GameObject go in shortList)
|
|
||||||
{
|
|
||||||
string path = go.transform.GetTransformPath(true);
|
|
||||||
if (path.EndsWith("/"))
|
|
||||||
path = path.Remove(path.Length - 1);
|
|
||||||
if (path == input)
|
|
||||||
{
|
|
||||||
parentToSet = go.transform;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parentToSet)
|
|
||||||
DoSetParent(parentToSet);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ExplorerCore.LogWarning($"Could not find any GameObject name or path '{input}'!");
|
|
||||||
UpdateGameObjectInfo(false, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DoSetParent(Transform transform)
|
|
||||||
{
|
|
||||||
ExplorerCore.Log($"Setting target's transform parent to: {(transform == null ? "null" : $"'{transform.name}'")}");
|
|
||||||
|
|
||||||
if (GOTarget.GetComponent<RectTransform>())
|
|
||||||
GOTarget.transform.SetParent(transform, false);
|
|
||||||
else
|
|
||||||
GOTarget.transform.parent = transform;
|
|
||||||
|
|
||||||
UpdateGameObjectInfo(false, false);
|
|
||||||
UpdateTransformControlValues(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnNameEndEdit(string value)
|
|
||||||
{
|
|
||||||
GOTarget.name = value;
|
|
||||||
UpdateGameObjectInfo(false, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnActiveSelfToggled(bool value)
|
|
||||||
{
|
|
||||||
GOTarget.SetActive(value);
|
|
||||||
UpdateGameObjectInfo(false, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnTagEndEdit(string value)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
GOTarget.tag = value;
|
|
||||||
UpdateGameObjectInfo(false, true);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
ExplorerCore.LogWarning($"Exception setting tag! {ex.ReflectionExToString()}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnExploreButtonClicked()
|
|
||||||
{
|
|
||||||
ObjectExplorerPanel panel = UIManager.GetPanel<UI.Panels.ObjectExplorerPanel>(UIManager.Panels.ObjectExplorer);
|
|
||||||
panel.SceneExplorer.JumpToTransform(this.Parent.GOTarget.transform);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnLayerDropdownChanged(int value)
|
|
||||||
{
|
|
||||||
GOTarget.layer = value;
|
|
||||||
UpdateGameObjectInfo(false, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnFlagsDropdownChanged(int value)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
HideFlags enumVal = hideFlagsValues[FlagsDropdown.options[value].text];
|
|
||||||
GOTarget.hideFlags = enumVal;
|
|
||||||
|
|
||||||
UpdateGameObjectInfo(false, true);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
ExplorerCore.LogWarning($"Exception setting hideFlags: {ex}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnDestroyClicked()
|
|
||||||
{
|
|
||||||
GameObject.Destroy(this.GOTarget);
|
|
||||||
InspectorManager.ReleaseInspector(Parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnInstantiateClicked()
|
|
||||||
{
|
|
||||||
GameObject clone = GameObject.Instantiate(this.GOTarget);
|
|
||||||
InspectorManager.Inspect(clone);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
#region Transform Controls
|
|
||||||
|
|
||||||
private enum TransformType { Position, LocalPosition, Rotation, Scale }
|
|
||||||
|
|
||||||
private class TransformControl
|
|
||||||
{
|
|
||||||
public TransformType Type;
|
|
||||||
public InputFieldRef Input;
|
|
||||||
|
|
||||||
public TransformControl(TransformType type, InputFieldRef input)
|
|
||||||
{
|
|
||||||
this.Type = type;
|
|
||||||
this.Input = input;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class VectorSlider
|
|
||||||
{
|
|
||||||
public int axis;
|
|
||||||
public Slider slider;
|
|
||||||
public TransformControl parentControl;
|
|
||||||
|
|
||||||
public VectorSlider(int axis, Slider slider, TransformControl parentControl)
|
|
||||||
{
|
|
||||||
this.axis = axis;
|
|
||||||
this.slider = slider;
|
|
||||||
this.parentControl = parentControl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Vector3 lastPosValue;
|
|
||||||
private Vector3 lastLocalValue;
|
|
||||||
private Quaternion lastRotValue;
|
|
||||||
private Vector3 lastScaleValue;
|
|
||||||
|
|
||||||
public void UpdateTransformControlValues(bool force)
|
|
||||||
{
|
|
||||||
Transform transform = GOTarget.transform;
|
|
||||||
if (force || (!PositionControl.Input.Component.isFocused && lastPosValue != transform.position))
|
|
||||||
{
|
|
||||||
PositionControl.Input.Text = ParseUtility.ToStringForInput(transform.position, typeof(Vector3));
|
|
||||||
lastPosValue = transform.position;
|
|
||||||
}
|
|
||||||
if (force || (!LocalPositionControl.Input.Component.isFocused && lastLocalValue != transform.localPosition))
|
|
||||||
{
|
|
||||||
LocalPositionControl.Input.Text = ParseUtility.ToStringForInput(transform.localPosition, typeof(Vector3));
|
|
||||||
lastLocalValue = transform.localPosition;
|
|
||||||
}
|
|
||||||
if (force || (!RotationControl.Input.Component.isFocused && lastRotValue != transform.localRotation))
|
|
||||||
{
|
|
||||||
RotationControl.Input.Text = ParseUtility.ToStringForInput(transform.localRotation, typeof(Quaternion));
|
|
||||||
lastRotValue = transform.localRotation;
|
|
||||||
}
|
|
||||||
if (force || (!ScaleControl.Input.Component.isFocused && lastScaleValue != transform.localScale))
|
|
||||||
{
|
|
||||||
ScaleControl.Input.Text = ParseUtility.ToStringForInput(transform.localScale, typeof(Vector3));
|
|
||||||
lastScaleValue = transform.localScale;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnTransformInputEndEdit(TransformType type, string input)
|
|
||||||
{
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case TransformType.Position:
|
|
||||||
{
|
|
||||||
if (ParseUtility.TryParse(input, typeof(Vector3), out object boxed, out _))
|
|
||||||
GOTarget.transform.position = (Vector3)boxed;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case TransformType.LocalPosition:
|
|
||||||
{
|
|
||||||
if (ParseUtility.TryParse(input, typeof(Vector3), out object boxed, out _))
|
|
||||||
GOTarget.transform.localPosition = (Vector3)boxed;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case TransformType.Rotation:
|
|
||||||
{
|
|
||||||
if (ParseUtility.TryParse(input, typeof(Quaternion), out object boxed, out _))
|
|
||||||
GOTarget.transform.localRotation = (Quaternion)boxed;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case TransformType.Scale:
|
|
||||||
{
|
|
||||||
if (ParseUtility.TryParse(input, typeof(Vector3), out object boxed, out _))
|
|
||||||
GOTarget.transform.localScale = (Vector3)boxed;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateTransformControlValues(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnVectorSliderChanged(VectorSlider slider, float value)
|
|
||||||
{
|
|
||||||
if (value == 0f)
|
|
||||||
{
|
|
||||||
currentSlidingVectorControl = null;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
currentSlidingVectorControl = slider;
|
|
||||||
currentVectorValue = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateVectorSlider()
|
|
||||||
{
|
|
||||||
if (currentSlidingVectorControl == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!InputManager.GetMouseButton(0))
|
|
||||||
{
|
|
||||||
currentSlidingVectorControl.slider.value = 0f;
|
|
||||||
currentSlidingVectorControl = null;
|
|
||||||
currentVectorValue = 0f;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Transform transform = GOTarget.transform;
|
|
||||||
|
|
||||||
Vector3 vector = Vector2.zero;
|
|
||||||
switch (currentSlidingVectorControl.parentControl.Type)
|
|
||||||
{
|
|
||||||
case TransformType.Position:
|
|
||||||
vector = transform.position; break;
|
|
||||||
case TransformType.LocalPosition:
|
|
||||||
vector = transform.localPosition; break;
|
|
||||||
case TransformType.Rotation:
|
|
||||||
vector = transform.eulerAngles; break;
|
|
||||||
case TransformType.Scale:
|
|
||||||
vector = transform.localScale; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// apply vector value change
|
|
||||||
switch (currentSlidingVectorControl.axis)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
vector.x += currentVectorValue; break;
|
|
||||||
case 1:
|
|
||||||
vector.y += currentVectorValue; break;
|
|
||||||
case 2:
|
|
||||||
vector.z += currentVectorValue; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// set vector back to transform
|
|
||||||
switch (currentSlidingVectorControl.parentControl.Type)
|
|
||||||
{
|
|
||||||
case TransformType.Position:
|
|
||||||
transform.position = vector; break;
|
|
||||||
case TransformType.LocalPosition:
|
|
||||||
transform.localPosition = vector; break;
|
|
||||||
case TransformType.Rotation:
|
|
||||||
transform.eulerAngles = vector; break;
|
|
||||||
case TransformType.Scale:
|
|
||||||
transform.localScale = vector; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateTransformControlValues(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
#region GO Controls UI Construction
|
|
||||||
|
|
||||||
private void ConstructTopInfo()
|
|
||||||
{
|
|
||||||
GameObject topInfoHolder = UIFactory.CreateVerticalGroup(Parent.Content, "TopInfoHolder", false, false, true, true, 3,
|
|
||||||
new Vector4(3, 3, 3, 3), new Color(0.1f, 0.1f, 0.1f), TextAnchor.MiddleLeft);
|
|
||||||
UIFactory.SetLayoutElement(topInfoHolder, minHeight: 100, flexibleWidth: 9999);
|
|
||||||
topInfoHolder.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
|
||||||
|
|
||||||
// first row (parent, path)
|
|
||||||
|
|
||||||
GameObject firstRow = UIFactory.CreateUIObject("ParentRow", topInfoHolder);
|
|
||||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(firstRow, false, false, true, true, 5, 0, 0, 0, 0, default);
|
|
||||||
UIFactory.SetLayoutElement(firstRow, minHeight: 25, flexibleWidth: 9999);
|
|
||||||
|
|
||||||
ViewParentButton = UIFactory.CreateButton(firstRow, "ViewParentButton", "◄ View Parent", new Color(0.2f, 0.2f, 0.2f));
|
|
||||||
ViewParentButton.ButtonText.fontSize = 13;
|
|
||||||
UIFactory.SetLayoutElement(ViewParentButton.Component.gameObject, minHeight: 25, minWidth: 100);
|
|
||||||
ViewParentButton.OnClick += OnViewParentClicked;
|
|
||||||
|
|
||||||
this.PathInput = UIFactory.CreateInputField(firstRow, "PathInput", "...");
|
|
||||||
PathInput.Component.textComponent.color = Color.grey;
|
|
||||||
PathInput.Component.textComponent.fontSize = 14;
|
|
||||||
UIFactory.SetLayoutElement(PathInput.UIRoot, minHeight: 25, minWidth: 100, flexibleWidth: 9999);
|
|
||||||
PathInput.Component.lineType = InputField.LineType.MultiLineSubmit;
|
|
||||||
|
|
||||||
ButtonRef copyButton = UIFactory.CreateButton(firstRow, "CopyButton", "Copy to Clipboard", new Color(0.2f, 0.2f, 0.2f, 1));
|
|
||||||
copyButton.ButtonText.color = Color.yellow;
|
|
||||||
UIFactory.SetLayoutElement(copyButton.Component.gameObject, minHeight: 25, minWidth: 120);
|
|
||||||
copyButton.OnClick += OnCopyClicked;
|
|
||||||
|
|
||||||
//var pathApplyBtn = UIFactory.CreateButton(firstRow, "PathButton", "Set Parent Path", new Color(0.2f, 0.2f, 0.2f));
|
|
||||||
//UIFactory.SetLayoutElement(pathApplyBtn.Component.gameObject, minHeight: 25, minWidth: 120);
|
|
||||||
//pathApplyBtn.OnClick += () => { OnPathEndEdit(PathInput.Text); };
|
|
||||||
|
|
||||||
PathInput.Component.GetOnEndEdit().AddListener((string val) => { OnPathEndEdit(val); });
|
|
||||||
|
|
||||||
// Title and update row
|
|
||||||
|
|
||||||
GameObject titleRow = UIFactory.CreateUIObject("TitleRow", topInfoHolder);
|
|
||||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(titleRow, false, false, true, true, 5);
|
|
||||||
|
|
||||||
Text titleLabel = UIFactory.CreateLabel(titleRow, "Title", SignatureHighlighter.Parse(typeof(GameObject), false),
|
|
||||||
TextAnchor.MiddleLeft, fontSize: 17);
|
|
||||||
UIFactory.SetLayoutElement(titleLabel.gameObject, minHeight: 30, minWidth: 100);
|
|
||||||
|
|
||||||
// name
|
|
||||||
|
|
||||||
NameInput = UIFactory.CreateInputField(titleRow, "NameInput", "untitled");
|
|
||||||
UIFactory.SetLayoutElement(NameInput.Component.gameObject, minHeight: 30, minWidth: 100, flexibleWidth: 9999);
|
|
||||||
NameInput.Component.textComponent.fontSize = 15;
|
|
||||||
NameInput.Component.GetOnEndEdit().AddListener((string val) => { OnNameEndEdit(val); });
|
|
||||||
|
|
||||||
// second row (toggles, instanceID, tag, buttons)
|
|
||||||
|
|
||||||
GameObject secondRow = UIFactory.CreateUIObject("ParentRow", topInfoHolder);
|
|
||||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(secondRow, false, false, true, true, 5, 0, 0, 0, 0, default);
|
|
||||||
UIFactory.SetLayoutElement(secondRow, minHeight: 25, flexibleWidth: 9999);
|
|
||||||
|
|
||||||
// activeSelf
|
|
||||||
GameObject activeToggleObj = UIFactory.CreateToggle(secondRow, "ActiveSelf", out ActiveSelfToggle, out ActiveSelfText);
|
|
||||||
UIFactory.SetLayoutElement(activeToggleObj, minHeight: 25, minWidth: 100);
|
|
||||||
ActiveSelfText.text = "ActiveSelf";
|
|
||||||
ActiveSelfToggle.onValueChanged.AddListener(OnActiveSelfToggled);
|
|
||||||
|
|
||||||
// isStatic
|
|
||||||
GameObject isStaticObj = UIFactory.CreateToggle(secondRow, "IsStatic", out IsStaticToggle, out Text staticText);
|
|
||||||
UIFactory.SetLayoutElement(isStaticObj, minHeight: 25, minWidth: 80);
|
|
||||||
staticText.text = "IsStatic";
|
|
||||||
staticText.color = Color.grey;
|
|
||||||
IsStaticToggle.interactable = false;
|
|
||||||
|
|
||||||
// InstanceID
|
|
||||||
Text instanceIdLabel = UIFactory.CreateLabel(secondRow, "InstanceIDLabel", "Instance ID:", TextAnchor.MiddleRight, Color.grey);
|
|
||||||
UIFactory.SetLayoutElement(instanceIdLabel.gameObject, minHeight: 25, minWidth: 90);
|
|
||||||
|
|
||||||
InstanceIDInput = UIFactory.CreateInputField(secondRow, "InstanceIDInput", "error");
|
|
||||||
UIFactory.SetLayoutElement(InstanceIDInput.Component.gameObject, minHeight: 25, minWidth: 110);
|
|
||||||
InstanceIDInput.Component.textComponent.color = Color.grey;
|
|
||||||
InstanceIDInput.Component.readOnly = true;
|
|
||||||
|
|
||||||
//Tag
|
|
||||||
Text tagLabel = UIFactory.CreateLabel(secondRow, "TagLabel", "Tag:", TextAnchor.MiddleRight, Color.grey);
|
|
||||||
UIFactory.SetLayoutElement(tagLabel.gameObject, minHeight: 25, minWidth: 40);
|
|
||||||
|
|
||||||
TagInput = UIFactory.CreateInputField(secondRow, "TagInput", "none");
|
|
||||||
UIFactory.SetLayoutElement(TagInput.Component.gameObject, minHeight: 25, minWidth: 100, flexibleWidth: 999);
|
|
||||||
TagInput.Component.textComponent.color = Color.white;
|
|
||||||
TagInput.Component.GetOnEndEdit().AddListener((string val) => { OnTagEndEdit(val); });
|
|
||||||
|
|
||||||
// Instantiate
|
|
||||||
ButtonRef instantiateBtn = UIFactory.CreateButton(secondRow, "InstantiateBtn", "Instantiate", new Color(0.2f, 0.2f, 0.2f));
|
|
||||||
UIFactory.SetLayoutElement(instantiateBtn.Component.gameObject, minHeight: 25, minWidth: 120);
|
|
||||||
instantiateBtn.OnClick += OnInstantiateClicked;
|
|
||||||
|
|
||||||
// Destroy
|
|
||||||
ButtonRef destroyBtn = UIFactory.CreateButton(secondRow, "DestroyBtn", "Destroy", new Color(0.3f, 0.2f, 0.2f));
|
|
||||||
UIFactory.SetLayoutElement(destroyBtn.Component.gameObject, minHeight: 25, minWidth: 80);
|
|
||||||
destroyBtn.OnClick += OnDestroyClicked;
|
|
||||||
|
|
||||||
// third row (scene, layer, flags)
|
|
||||||
|
|
||||||
GameObject thirdrow = UIFactory.CreateUIObject("ParentRow", topInfoHolder);
|
|
||||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(thirdrow, false, false, true, true, 5, 0, 0, 0, 0, default);
|
|
||||||
UIFactory.SetLayoutElement(thirdrow, minHeight: 25, flexibleWidth: 9999);
|
|
||||||
|
|
||||||
// Inspect in Explorer button
|
|
||||||
ButtonRef explorerBtn = UIFactory.CreateButton(thirdrow, "ExploreBtn", "Show in Explorer", new Color(0.15f, 0.15f, 0.15f));
|
|
||||||
UIFactory.SetLayoutElement(explorerBtn.Component.gameObject, minHeight: 25, minWidth: 100);
|
|
||||||
explorerBtn.ButtonText.fontSize = 12;
|
|
||||||
explorerBtn.OnClick += OnExploreButtonClicked;
|
|
||||||
|
|
||||||
// Scene
|
|
||||||
Text sceneLabel = UIFactory.CreateLabel(thirdrow, "SceneLabel", "Scene:", TextAnchor.MiddleLeft, Color.grey);
|
|
||||||
UIFactory.SetLayoutElement(sceneLabel.gameObject, minHeight: 25, minWidth: 50);
|
|
||||||
|
|
||||||
SceneInput = UIFactory.CreateInputField(thirdrow, "SceneInput", "untitled");
|
|
||||||
UIFactory.SetLayoutElement(SceneInput.Component.gameObject, minHeight: 25, minWidth: 120, flexibleWidth: 999);
|
|
||||||
SceneInput.Component.readOnly = true;
|
|
||||||
SceneInput.Component.textComponent.color = new Color(0.7f, 0.7f, 0.7f);
|
|
||||||
|
|
||||||
// Layer
|
|
||||||
Text layerLabel = UIFactory.CreateLabel(thirdrow, "LayerLabel", "Layer:", TextAnchor.MiddleLeft, Color.grey);
|
|
||||||
UIFactory.SetLayoutElement(layerLabel.gameObject, minHeight: 25, minWidth: 50);
|
|
||||||
|
|
||||||
GameObject layerDrop = UIFactory.CreateDropdown(thirdrow, "LayerDropdown", out LayerDropdown, "0", 14, OnLayerDropdownChanged);
|
|
||||||
UIFactory.SetLayoutElement(layerDrop, minHeight: 25, minWidth: 110, flexibleWidth: 999);
|
|
||||||
LayerDropdown.captionText.color = SignatureHighlighter.EnumGreen;
|
|
||||||
if (layerToNames == null)
|
|
||||||
GetLayerNames();
|
|
||||||
foreach (string name in layerToNames)
|
|
||||||
LayerDropdown.options.Add(new Dropdown.OptionData(name));
|
|
||||||
LayerDropdown.value = 0;
|
|
||||||
LayerDropdown.RefreshShownValue();
|
|
||||||
|
|
||||||
// Flags
|
|
||||||
Text flagsLabel = UIFactory.CreateLabel(thirdrow, "FlagsLabel", "Flags:", TextAnchor.MiddleRight, Color.grey);
|
|
||||||
UIFactory.SetLayoutElement(flagsLabel.gameObject, minHeight: 25, minWidth: 50);
|
|
||||||
|
|
||||||
GameObject flagsDrop = UIFactory.CreateDropdown(thirdrow, "FlagsDropdown", out FlagsDropdown, "None", 14, OnFlagsDropdownChanged);
|
|
||||||
FlagsDropdown.captionText.color = SignatureHighlighter.EnumGreen;
|
|
||||||
UIFactory.SetLayoutElement(flagsDrop, minHeight: 25, minWidth: 135, flexibleWidth: 999);
|
|
||||||
if (hideFlagsValues == null)
|
|
||||||
GetHideFlagNames();
|
|
||||||
foreach (string name in hideFlagsValues.Keys)
|
|
||||||
FlagsDropdown.options.Add(new Dropdown.OptionData(name));
|
|
||||||
FlagsDropdown.value = 0;
|
|
||||||
FlagsDropdown.RefreshShownValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<string> layerToNames;
|
|
||||||
|
|
||||||
private static void GetLayerNames()
|
|
||||||
{
|
|
||||||
layerToNames = new List<string>();
|
|
||||||
for (int i = 0; i < 32; i++)
|
|
||||||
{
|
|
||||||
string name = RuntimeHelper.LayerToName(i);
|
|
||||||
if (string.IsNullOrEmpty(name))
|
|
||||||
name = i.ToString();
|
|
||||||
layerToNames.Add(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Dictionary<string, HideFlags> hideFlagsValues;
|
|
||||||
|
|
||||||
private static void GetHideFlagNames()
|
|
||||||
{
|
|
||||||
hideFlagsValues = new Dictionary<string, HideFlags>();
|
|
||||||
|
|
||||||
Array names = Enum.GetValues(typeof(HideFlags));
|
|
||||||
foreach (HideFlags value in names)
|
|
||||||
{
|
|
||||||
hideFlagsValues.Add(value.ToString(), value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
#region Transform Controls UI Construction
|
|
||||||
|
|
||||||
private void ConstructTransformControls()
|
|
||||||
{
|
|
||||||
GameObject transformGroup = UIFactory.CreateVerticalGroup(Parent.Content, "TransformControls", false, false, true, true, 2,
|
|
||||||
new Vector4(2, 2, 0, 0), new Color(0.1f, 0.1f, 0.1f));
|
|
||||||
UIFactory.SetLayoutElement(transformGroup, minHeight: 100, flexibleWidth: 9999);
|
|
||||||
//transformGroup.SetActive(false);
|
|
||||||
//var groupRect = transformGroup.GetComponent<RectTransform>();
|
|
||||||
//groupRect.anchorMin = new Vector2(0, 1);
|
|
||||||
//groupRect.anchorMax = new Vector2(1, 1);
|
|
||||||
//groupRect.SetInsetAndSizeFromParentEdge(RectTransform.Edge.Top, 0, 100);
|
|
||||||
|
|
||||||
PositionControl = AddTransformRow(transformGroup, "Position:", TransformType.Position);
|
|
||||||
LocalPositionControl = AddTransformRow(transformGroup, "Local Position:", TransformType.LocalPosition);
|
|
||||||
RotationControl = AddTransformRow(transformGroup, "Rotation:", TransformType.Rotation);
|
|
||||||
ScaleControl = AddTransformRow(transformGroup, "Scale:", TransformType.Scale);
|
|
||||||
}
|
|
||||||
|
|
||||||
private TransformControl AddTransformRow(GameObject transformGroup, string title, TransformType type)
|
|
||||||
{
|
|
||||||
GameObject rowObj = UIFactory.CreateUIObject("Row_" + title, transformGroup);
|
|
||||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(rowObj, false, false, true, true, 5, 0, 0, 0, 0, default);
|
|
||||||
UIFactory.SetLayoutElement(rowObj, minHeight: 25, flexibleWidth: 9999);
|
|
||||||
|
|
||||||
Text titleLabel = UIFactory.CreateLabel(rowObj, "PositionLabel", title, TextAnchor.MiddleRight, Color.grey);
|
|
||||||
UIFactory.SetLayoutElement(titleLabel.gameObject, minHeight: 25, minWidth: 110);
|
|
||||||
|
|
||||||
InputFieldRef inputField = UIFactory.CreateInputField(rowObj, "InputField", "...");
|
|
||||||
UIFactory.SetLayoutElement(inputField.Component.gameObject, minHeight: 25, minWidth: 100, flexibleWidth: 999);
|
|
||||||
|
|
||||||
inputField.Component.GetOnEndEdit().AddListener((string value) => { OnTransformInputEndEdit(type, value); });
|
|
||||||
|
|
||||||
TransformControl control = new(type, inputField);
|
|
||||||
|
|
||||||
AddVectorAxisSlider(rowObj, "X", 0, control);
|
|
||||||
AddVectorAxisSlider(rowObj, "Y", 1, control);
|
|
||||||
AddVectorAxisSlider(rowObj, "Z", 2, control);
|
|
||||||
|
|
||||||
return control;
|
|
||||||
}
|
|
||||||
|
|
||||||
private VectorSlider AddVectorAxisSlider(GameObject parent, string title, int axis, TransformControl control)
|
|
||||||
{
|
|
||||||
Text label = UIFactory.CreateLabel(parent, "Label_" + title, title + ":", TextAnchor.MiddleRight, Color.grey);
|
|
||||||
UIFactory.SetLayoutElement(label.gameObject, minHeight: 25, minWidth: 30);
|
|
||||||
|
|
||||||
GameObject sliderObj = UIFactory.CreateSlider(parent, "Slider_" + title, out Slider slider);
|
|
||||||
UIFactory.SetLayoutElement(sliderObj, minHeight: 25, minWidth: 120, flexibleWidth: 0);
|
|
||||||
slider.m_FillImage.color = Color.clear;
|
|
||||||
|
|
||||||
slider.minValue = -1;
|
|
||||||
slider.maxValue = 1;
|
|
||||||
VectorSlider sliderControl = new(axis, slider, control);
|
|
||||||
|
|
||||||
slider.onValueChanged.AddListener((float val) =>
|
|
||||||
{
|
|
||||||
OnVectorSliderChanged(sliderControl, val);
|
|
||||||
});
|
|
||||||
|
|
||||||
return sliderControl;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
68
src/UI/Widgets/GameObjects/AxisControl.cs
Normal file
68
src/UI/Widgets/GameObjects/AxisControl.cs
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
using UniverseLib;
|
||||||
|
using UniverseLib.UI;
|
||||||
|
using UniverseLib.UI.Models;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
|
namespace UnityExplorer.UI.Widgets
|
||||||
|
{
|
||||||
|
// Handles the slider and +/- buttons for a specific axis of a transform property.
|
||||||
|
|
||||||
|
public class AxisControl
|
||||||
|
{
|
||||||
|
public readonly Vector3Control parent;
|
||||||
|
|
||||||
|
public readonly int axis;
|
||||||
|
public readonly Slider slider;
|
||||||
|
|
||||||
|
public AxisControl(int axis, Slider slider, Vector3Control parentControl)
|
||||||
|
{
|
||||||
|
this.parent = parentControl;
|
||||||
|
this.axis = axis;
|
||||||
|
this.slider = slider;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnVectorSliderChanged(float value)
|
||||||
|
{
|
||||||
|
parent.Owner.CurrentSlidingAxisControl = value == 0f ? null : this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnVectorMinusClicked()
|
||||||
|
{
|
||||||
|
parent.Owner.AxisControlOperation(-this.parent.Increment, this.parent, this.axis);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnVectorPlusClicked()
|
||||||
|
{
|
||||||
|
parent.Owner.AxisControlOperation(this.parent.Increment, this.parent, this.axis);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AxisControl Create(GameObject parent, string title, int axis, Vector3Control owner)
|
||||||
|
{
|
||||||
|
Text label = UIFactory.CreateLabel(parent, $"Label_{title}", $"{title}:", TextAnchor.MiddleRight, Color.grey);
|
||||||
|
UIFactory.SetLayoutElement(label.gameObject, minHeight: 25, minWidth: 30);
|
||||||
|
|
||||||
|
GameObject sliderObj = UIFactory.CreateSlider(parent, $"Slider_{title}", out Slider slider);
|
||||||
|
UIFactory.SetLayoutElement(sliderObj, minHeight: 25, minWidth: 75, flexibleWidth: 0);
|
||||||
|
slider.m_FillImage.color = Color.clear;
|
||||||
|
|
||||||
|
slider.minValue = -0.1f;
|
||||||
|
slider.maxValue = 0.1f;
|
||||||
|
|
||||||
|
AxisControl sliderControl = new(axis, slider, owner);
|
||||||
|
|
||||||
|
slider.onValueChanged.AddListener(sliderControl.OnVectorSliderChanged);
|
||||||
|
|
||||||
|
ButtonRef minusButton = UIFactory.CreateButton(parent, "MinusIncrementButton", "-");
|
||||||
|
UIFactory.SetLayoutElement(minusButton.GameObject, minWidth: 20, flexibleWidth: 0, minHeight: 25);
|
||||||
|
minusButton.OnClick += sliderControl.OnVectorMinusClicked;
|
||||||
|
|
||||||
|
ButtonRef plusButton = UIFactory.CreateButton(parent, "PlusIncrementButton", "+");
|
||||||
|
UIFactory.SetLayoutElement(plusButton.GameObject, minWidth: 20, flexibleWidth: 0, minHeight: 25);
|
||||||
|
plusButton.OnClick += sliderControl.OnVectorPlusClicked;
|
||||||
|
|
||||||
|
return sliderControl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -6,7 +6,7 @@ using UniverseLib.UI.Models;
|
|||||||
using UniverseLib.UI.Widgets.ButtonList;
|
using UniverseLib.UI.Widgets.ButtonList;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
|
|
||||||
namespace UnityExplorer.Inspectors
|
namespace UnityExplorer.UI.Widgets
|
||||||
{
|
{
|
||||||
public class ComponentCell : ButtonCell
|
public class ComponentCell : ButtonCell
|
||||||
{
|
{
|
@ -1,12 +1,13 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using UnityExplorer.Inspectors;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
using UniverseLib.UI.Widgets.ButtonList;
|
using UniverseLib.UI.Widgets.ButtonList;
|
||||||
using UniverseLib.UI.Widgets.ScrollView;
|
using UniverseLib.UI.Widgets.ScrollView;
|
||||||
using UniverseLib.Utility;
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
namespace UnityExplorer.Inspectors
|
namespace UnityExplorer.UI.Widgets
|
||||||
{
|
{
|
||||||
public class ComponentList : ButtonListHandler<Component, ComponentCell>
|
public class ComponentList : ButtonListHandler<Component, ComponentCell>
|
||||||
{
|
{
|
35
src/UI/Widgets/GameObjects/GameObjectControls.cs
Normal file
35
src/UI/Widgets/GameObjects/GameObjectControls.cs
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
using UnityExplorer.Inspectors;
|
||||||
|
|
||||||
|
namespace UnityExplorer.UI.Widgets
|
||||||
|
{
|
||||||
|
// The base wrapper to hold a reference to the parent Inspector and the GameObjectInfo and TransformControls widgets.
|
||||||
|
|
||||||
|
public class GameObjectControls
|
||||||
|
{
|
||||||
|
public GameObjectInspector Parent { get; }
|
||||||
|
public GameObject Target => Parent.Target;
|
||||||
|
|
||||||
|
public GameObjectInfoPanel GameObjectInfo { get; }
|
||||||
|
|
||||||
|
public TransformControls TransformControl { get; }
|
||||||
|
|
||||||
|
public GameObjectControls(GameObjectInspector parent)
|
||||||
|
{
|
||||||
|
this.Parent = parent;
|
||||||
|
|
||||||
|
this.GameObjectInfo = new(this);
|
||||||
|
this.TransformControl = new(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateGameObjectInfo(bool firstUpdate, bool force)
|
||||||
|
{
|
||||||
|
GameObjectInfo.UpdateGameObjectInfo(firstUpdate, force);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateVectorSlider()
|
||||||
|
{
|
||||||
|
TransformControl.UpdateVectorSlider();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
450
src/UI/Widgets/GameObjects/GameObjectInfoPanel.cs
Normal file
450
src/UI/Widgets/GameObjects/GameObjectInfoPanel.cs
Normal file
@ -0,0 +1,450 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
using UnityExplorer.UI.Panels;
|
||||||
|
using UniverseLib;
|
||||||
|
using UniverseLib.UI;
|
||||||
|
using UniverseLib.UI.Models;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
|
namespace UnityExplorer.UI.Widgets
|
||||||
|
{
|
||||||
|
public class GameObjectInfoPanel
|
||||||
|
{
|
||||||
|
public GameObjectControls Owner { get; }
|
||||||
|
GameObject Target => Owner.Target;
|
||||||
|
|
||||||
|
string lastGoName;
|
||||||
|
string lastPath;
|
||||||
|
bool lastParentState;
|
||||||
|
int lastSceneHandle;
|
||||||
|
string lastTag;
|
||||||
|
int lastLayer;
|
||||||
|
int lastFlags;
|
||||||
|
|
||||||
|
ButtonRef ViewParentButton;
|
||||||
|
InputFieldRef PathInput;
|
||||||
|
|
||||||
|
InputFieldRef NameInput;
|
||||||
|
Toggle ActiveSelfToggle;
|
||||||
|
Text ActiveSelfText;
|
||||||
|
Toggle IsStaticToggle;
|
||||||
|
|
||||||
|
InputFieldRef SceneInput;
|
||||||
|
InputFieldRef InstanceIDInput;
|
||||||
|
InputFieldRef TagInput;
|
||||||
|
|
||||||
|
Dropdown LayerDropdown;
|
||||||
|
Dropdown FlagsDropdown;
|
||||||
|
|
||||||
|
public GameObjectInfoPanel(GameObjectControls owner)
|
||||||
|
{
|
||||||
|
this.Owner = owner;
|
||||||
|
Create();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateGameObjectInfo(bool firstUpdate, bool force)
|
||||||
|
{
|
||||||
|
if (firstUpdate)
|
||||||
|
{
|
||||||
|
InstanceIDInput.Text = Target.GetInstanceID().ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (force || (!NameInput.Component.isFocused && Target.name != lastGoName))
|
||||||
|
{
|
||||||
|
lastGoName = Target.name;
|
||||||
|
Owner.Parent.Tab.TabText.text = $"[G] {Target.name}";
|
||||||
|
NameInput.Text = Target.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (force || !PathInput.Component.isFocused)
|
||||||
|
{
|
||||||
|
string path = Target.transform.GetTransformPath();
|
||||||
|
if (path != lastPath)
|
||||||
|
{
|
||||||
|
lastPath = path;
|
||||||
|
PathInput.Text = path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (force || Target.transform.parent != lastParentState)
|
||||||
|
{
|
||||||
|
lastParentState = Target.transform.parent;
|
||||||
|
ViewParentButton.Component.interactable = lastParentState;
|
||||||
|
if (lastParentState)
|
||||||
|
{
|
||||||
|
ViewParentButton.ButtonText.color = Color.white;
|
||||||
|
ViewParentButton.ButtonText.text = "◄ View Parent";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ViewParentButton.ButtonText.color = Color.grey;
|
||||||
|
ViewParentButton.ButtonText.text = "No parent";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (force || Target.activeSelf != ActiveSelfToggle.isOn)
|
||||||
|
{
|
||||||
|
ActiveSelfToggle.Set(Target.activeSelf, false);
|
||||||
|
ActiveSelfText.color = ActiveSelfToggle.isOn ? Color.green : Color.red;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (force || Target.isStatic != IsStaticToggle.isOn)
|
||||||
|
{
|
||||||
|
IsStaticToggle.Set(Target.isStatic, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (force || Target.scene.handle != lastSceneHandle)
|
||||||
|
{
|
||||||
|
lastSceneHandle = Target.scene.handle;
|
||||||
|
SceneInput.Text = Target.scene.IsValid() ? Target.scene.name : "None (Asset/Resource)";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (force || (!TagInput.Component.isFocused && Target.tag != lastTag))
|
||||||
|
{
|
||||||
|
lastTag = Target.tag;
|
||||||
|
TagInput.Text = lastTag;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (force || (Target.layer != lastLayer))
|
||||||
|
{
|
||||||
|
lastLayer = Target.layer;
|
||||||
|
LayerDropdown.value = Target.layer;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (force || ((int)Target.hideFlags != lastFlags))
|
||||||
|
{
|
||||||
|
lastFlags = (int)Target.hideFlags;
|
||||||
|
FlagsDropdown.captionText.text = Target.hideFlags.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoSetParent(Transform transform)
|
||||||
|
{
|
||||||
|
ExplorerCore.Log($"Setting target's transform parent to: {(transform == null ? "null" : $"'{transform.name}'")}");
|
||||||
|
|
||||||
|
if (Target.GetComponent<RectTransform>())
|
||||||
|
Target.transform.SetParent(transform, false);
|
||||||
|
else
|
||||||
|
Target.transform.parent = transform;
|
||||||
|
|
||||||
|
UpdateGameObjectInfo(false, false);
|
||||||
|
|
||||||
|
Owner.TransformControl.UpdateTransformControlValues(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#region UI event listeners
|
||||||
|
|
||||||
|
void OnViewParentClicked()
|
||||||
|
{
|
||||||
|
if (this.Target && this.Target.transform.parent)
|
||||||
|
{
|
||||||
|
Owner.Parent.OnTransformCellClicked(this.Target.transform.parent.gameObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnPathEndEdit(string input)
|
||||||
|
{
|
||||||
|
lastPath = input;
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(input))
|
||||||
|
{
|
||||||
|
DoSetParent(null);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Transform parentToSet = null;
|
||||||
|
|
||||||
|
if (input.EndsWith("/"))
|
||||||
|
input = input.Remove(input.Length - 1);
|
||||||
|
|
||||||
|
// try the easy way
|
||||||
|
if (GameObject.Find(input) is GameObject found)
|
||||||
|
{
|
||||||
|
parentToSet = found.transform;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// look for inactive objects
|
||||||
|
string name = input.Split('/').Last();
|
||||||
|
UnityEngine.Object[] allObjects = RuntimeHelper.FindObjectsOfTypeAll(typeof(GameObject));
|
||||||
|
List<GameObject> shortList = new();
|
||||||
|
foreach (UnityEngine.Object obj in allObjects)
|
||||||
|
if (obj.name == name) shortList.Add(obj.TryCast<GameObject>());
|
||||||
|
foreach (GameObject go in shortList)
|
||||||
|
{
|
||||||
|
string path = go.transform.GetTransformPath(true);
|
||||||
|
if (path.EndsWith("/"))
|
||||||
|
path = path.Remove(path.Length - 1);
|
||||||
|
if (path == input)
|
||||||
|
{
|
||||||
|
parentToSet = go.transform;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parentToSet)
|
||||||
|
DoSetParent(parentToSet);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ExplorerCore.LogWarning($"Could not find any GameObject name or path '{input}'!");
|
||||||
|
UpdateGameObjectInfo(false, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnNameEndEdit(string value)
|
||||||
|
{
|
||||||
|
Target.name = value;
|
||||||
|
UpdateGameObjectInfo(false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnCopyClicked()
|
||||||
|
{
|
||||||
|
ClipboardPanel.Copy(this.Target);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnActiveSelfToggled(bool value)
|
||||||
|
{
|
||||||
|
Target.SetActive(value);
|
||||||
|
UpdateGameObjectInfo(false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnTagEndEdit(string value)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Target.tag = value;
|
||||||
|
UpdateGameObjectInfo(false, true);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
ExplorerCore.LogWarning($"Exception setting tag! {ex.ReflectionExToString()}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnExploreButtonClicked()
|
||||||
|
{
|
||||||
|
ObjectExplorerPanel panel = UIManager.GetPanel<ObjectExplorerPanel>(UIManager.Panels.ObjectExplorer);
|
||||||
|
panel.SceneExplorer.JumpToTransform(this.Owner.Parent.Target.transform);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnLayerDropdownChanged(int value)
|
||||||
|
{
|
||||||
|
Target.layer = value;
|
||||||
|
UpdateGameObjectInfo(false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnFlagsDropdownChanged(int value)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
HideFlags enumVal = hideFlagsValues[FlagsDropdown.options[value].text];
|
||||||
|
Target.hideFlags = enumVal;
|
||||||
|
|
||||||
|
UpdateGameObjectInfo(false, true);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
ExplorerCore.LogWarning($"Exception setting hideFlags: {ex}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnDestroyClicked()
|
||||||
|
{
|
||||||
|
GameObject.Destroy(this.Target);
|
||||||
|
InspectorManager.ReleaseInspector(Owner.Parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnInstantiateClicked()
|
||||||
|
{
|
||||||
|
GameObject clone = GameObject.Instantiate(this.Target);
|
||||||
|
InspectorManager.Inspect(clone);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region UI Construction
|
||||||
|
|
||||||
|
public void Create()
|
||||||
|
{
|
||||||
|
GameObject topInfoHolder = UIFactory.CreateVerticalGroup(Owner.Parent.Content, "TopInfoHolder", false, false, true, true, 3,
|
||||||
|
new Vector4(3, 3, 3, 3), new Color(0.1f, 0.1f, 0.1f), TextAnchor.MiddleLeft);
|
||||||
|
UIFactory.SetLayoutElement(topInfoHolder, minHeight: 100, flexibleWidth: 9999);
|
||||||
|
topInfoHolder.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||||
|
|
||||||
|
// first row (parent, path)
|
||||||
|
|
||||||
|
GameObject firstRow = UIFactory.CreateUIObject("ParentRow", topInfoHolder);
|
||||||
|
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(firstRow, false, false, true, true, 5, 0, 0, 0, 0, default);
|
||||||
|
UIFactory.SetLayoutElement(firstRow, minHeight: 25, flexibleWidth: 9999);
|
||||||
|
|
||||||
|
ViewParentButton = UIFactory.CreateButton(firstRow, "ViewParentButton", "◄ View Parent", new Color(0.2f, 0.2f, 0.2f));
|
||||||
|
ViewParentButton.ButtonText.fontSize = 13;
|
||||||
|
UIFactory.SetLayoutElement(ViewParentButton.Component.gameObject, minHeight: 25, minWidth: 100);
|
||||||
|
ViewParentButton.OnClick += OnViewParentClicked;
|
||||||
|
|
||||||
|
this.PathInput = UIFactory.CreateInputField(firstRow, "PathInput", "...");
|
||||||
|
PathInput.Component.textComponent.color = Color.grey;
|
||||||
|
PathInput.Component.textComponent.fontSize = 14;
|
||||||
|
UIFactory.SetLayoutElement(PathInput.UIRoot, minHeight: 25, minWidth: 100, flexibleWidth: 9999);
|
||||||
|
PathInput.Component.lineType = InputField.LineType.MultiLineSubmit;
|
||||||
|
|
||||||
|
ButtonRef copyButton = UIFactory.CreateButton(firstRow, "CopyButton", "Copy to Clipboard", new Color(0.2f, 0.2f, 0.2f, 1));
|
||||||
|
copyButton.ButtonText.color = Color.yellow;
|
||||||
|
UIFactory.SetLayoutElement(copyButton.Component.gameObject, minHeight: 25, minWidth: 120);
|
||||||
|
copyButton.OnClick += OnCopyClicked;
|
||||||
|
|
||||||
|
PathInput.Component.GetOnEndEdit().AddListener((string val) => { OnPathEndEdit(val); });
|
||||||
|
|
||||||
|
// Title and update row
|
||||||
|
|
||||||
|
GameObject titleRow = UIFactory.CreateUIObject("TitleRow", topInfoHolder);
|
||||||
|
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(titleRow, false, false, true, true, 5);
|
||||||
|
|
||||||
|
Text titleLabel = UIFactory.CreateLabel(titleRow, "Title", SignatureHighlighter.Parse(typeof(GameObject), false),
|
||||||
|
TextAnchor.MiddleLeft, fontSize: 17);
|
||||||
|
UIFactory.SetLayoutElement(titleLabel.gameObject, minHeight: 30, minWidth: 100);
|
||||||
|
|
||||||
|
// name
|
||||||
|
|
||||||
|
NameInput = UIFactory.CreateInputField(titleRow, "NameInput", "untitled");
|
||||||
|
UIFactory.SetLayoutElement(NameInput.Component.gameObject, minHeight: 30, minWidth: 100, flexibleWidth: 9999);
|
||||||
|
NameInput.Component.textComponent.fontSize = 15;
|
||||||
|
NameInput.Component.GetOnEndEdit().AddListener((string val) => { OnNameEndEdit(val); });
|
||||||
|
|
||||||
|
// second row (toggles, instanceID, tag, buttons)
|
||||||
|
|
||||||
|
GameObject secondRow = UIFactory.CreateUIObject("ParentRow", topInfoHolder);
|
||||||
|
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(secondRow, false, false, true, true, 5, 0, 0, 0, 0, default);
|
||||||
|
UIFactory.SetLayoutElement(secondRow, minHeight: 25, flexibleWidth: 9999);
|
||||||
|
|
||||||
|
// activeSelf
|
||||||
|
GameObject activeToggleObj = UIFactory.CreateToggle(secondRow, "ActiveSelf", out ActiveSelfToggle, out ActiveSelfText);
|
||||||
|
UIFactory.SetLayoutElement(activeToggleObj, minHeight: 25, minWidth: 100);
|
||||||
|
ActiveSelfText.text = "ActiveSelf";
|
||||||
|
ActiveSelfToggle.onValueChanged.AddListener(OnActiveSelfToggled);
|
||||||
|
|
||||||
|
// isStatic
|
||||||
|
GameObject isStaticObj = UIFactory.CreateToggle(secondRow, "IsStatic", out IsStaticToggle, out Text staticText);
|
||||||
|
UIFactory.SetLayoutElement(isStaticObj, minHeight: 25, minWidth: 80);
|
||||||
|
staticText.text = "IsStatic";
|
||||||
|
staticText.color = Color.grey;
|
||||||
|
IsStaticToggle.interactable = false;
|
||||||
|
|
||||||
|
// InstanceID
|
||||||
|
Text instanceIdLabel = UIFactory.CreateLabel(secondRow, "InstanceIDLabel", "Instance ID:", TextAnchor.MiddleRight, Color.grey);
|
||||||
|
UIFactory.SetLayoutElement(instanceIdLabel.gameObject, minHeight: 25, minWidth: 90);
|
||||||
|
|
||||||
|
InstanceIDInput = UIFactory.CreateInputField(secondRow, "InstanceIDInput", "error");
|
||||||
|
UIFactory.SetLayoutElement(InstanceIDInput.Component.gameObject, minHeight: 25, minWidth: 110);
|
||||||
|
InstanceIDInput.Component.textComponent.color = Color.grey;
|
||||||
|
InstanceIDInput.Component.readOnly = true;
|
||||||
|
|
||||||
|
//Tag
|
||||||
|
Text tagLabel = UIFactory.CreateLabel(secondRow, "TagLabel", "Tag:", TextAnchor.MiddleRight, Color.grey);
|
||||||
|
UIFactory.SetLayoutElement(tagLabel.gameObject, minHeight: 25, minWidth: 40);
|
||||||
|
|
||||||
|
TagInput = UIFactory.CreateInputField(secondRow, "TagInput", "none");
|
||||||
|
UIFactory.SetLayoutElement(TagInput.Component.gameObject, minHeight: 25, minWidth: 100, flexibleWidth: 999);
|
||||||
|
TagInput.Component.textComponent.color = Color.white;
|
||||||
|
TagInput.Component.GetOnEndEdit().AddListener((string val) => { OnTagEndEdit(val); });
|
||||||
|
|
||||||
|
// Instantiate
|
||||||
|
ButtonRef instantiateBtn = UIFactory.CreateButton(secondRow, "InstantiateBtn", "Instantiate", new Color(0.2f, 0.2f, 0.2f));
|
||||||
|
UIFactory.SetLayoutElement(instantiateBtn.Component.gameObject, minHeight: 25, minWidth: 120);
|
||||||
|
instantiateBtn.OnClick += OnInstantiateClicked;
|
||||||
|
|
||||||
|
// Destroy
|
||||||
|
ButtonRef destroyBtn = UIFactory.CreateButton(secondRow, "DestroyBtn", "Destroy", new Color(0.3f, 0.2f, 0.2f));
|
||||||
|
UIFactory.SetLayoutElement(destroyBtn.Component.gameObject, minHeight: 25, minWidth: 80);
|
||||||
|
destroyBtn.OnClick += OnDestroyClicked;
|
||||||
|
|
||||||
|
// third row (scene, layer, flags)
|
||||||
|
|
||||||
|
GameObject thirdrow = UIFactory.CreateUIObject("ParentRow", topInfoHolder);
|
||||||
|
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(thirdrow, false, false, true, true, 5, 0, 0, 0, 0, default);
|
||||||
|
UIFactory.SetLayoutElement(thirdrow, minHeight: 25, flexibleWidth: 9999);
|
||||||
|
|
||||||
|
// Inspect in Explorer button
|
||||||
|
ButtonRef explorerBtn = UIFactory.CreateButton(thirdrow, "ExploreBtn", "Show in Explorer", new Color(0.15f, 0.15f, 0.15f));
|
||||||
|
UIFactory.SetLayoutElement(explorerBtn.Component.gameObject, minHeight: 25, minWidth: 100);
|
||||||
|
explorerBtn.ButtonText.fontSize = 12;
|
||||||
|
explorerBtn.OnClick += OnExploreButtonClicked;
|
||||||
|
|
||||||
|
// Scene
|
||||||
|
Text sceneLabel = UIFactory.CreateLabel(thirdrow, "SceneLabel", "Scene:", TextAnchor.MiddleLeft, Color.grey);
|
||||||
|
UIFactory.SetLayoutElement(sceneLabel.gameObject, minHeight: 25, minWidth: 50);
|
||||||
|
|
||||||
|
SceneInput = UIFactory.CreateInputField(thirdrow, "SceneInput", "untitled");
|
||||||
|
UIFactory.SetLayoutElement(SceneInput.Component.gameObject, minHeight: 25, minWidth: 120, flexibleWidth: 999);
|
||||||
|
SceneInput.Component.readOnly = true;
|
||||||
|
SceneInput.Component.textComponent.color = new Color(0.7f, 0.7f, 0.7f);
|
||||||
|
|
||||||
|
// Layer
|
||||||
|
Text layerLabel = UIFactory.CreateLabel(thirdrow, "LayerLabel", "Layer:", TextAnchor.MiddleLeft, Color.grey);
|
||||||
|
UIFactory.SetLayoutElement(layerLabel.gameObject, minHeight: 25, minWidth: 50);
|
||||||
|
|
||||||
|
GameObject layerDrop = UIFactory.CreateDropdown(thirdrow, "LayerDropdown", out LayerDropdown, "0", 14, OnLayerDropdownChanged);
|
||||||
|
UIFactory.SetLayoutElement(layerDrop, minHeight: 25, minWidth: 110, flexibleWidth: 999);
|
||||||
|
LayerDropdown.captionText.color = SignatureHighlighter.EnumGreen;
|
||||||
|
if (layerToNames == null)
|
||||||
|
GetLayerNames();
|
||||||
|
foreach (string name in layerToNames)
|
||||||
|
LayerDropdown.options.Add(new Dropdown.OptionData(name));
|
||||||
|
LayerDropdown.value = 0;
|
||||||
|
LayerDropdown.RefreshShownValue();
|
||||||
|
|
||||||
|
// Flags
|
||||||
|
Text flagsLabel = UIFactory.CreateLabel(thirdrow, "FlagsLabel", "Flags:", TextAnchor.MiddleRight, Color.grey);
|
||||||
|
UIFactory.SetLayoutElement(flagsLabel.gameObject, minHeight: 25, minWidth: 50);
|
||||||
|
|
||||||
|
GameObject flagsDrop = UIFactory.CreateDropdown(thirdrow, "FlagsDropdown", out FlagsDropdown, "None", 14, OnFlagsDropdownChanged);
|
||||||
|
FlagsDropdown.captionText.color = SignatureHighlighter.EnumGreen;
|
||||||
|
UIFactory.SetLayoutElement(flagsDrop, minHeight: 25, minWidth: 135, flexibleWidth: 999);
|
||||||
|
if (hideFlagsValues == null)
|
||||||
|
GetHideFlagNames();
|
||||||
|
foreach (string name in hideFlagsValues.Keys)
|
||||||
|
FlagsDropdown.options.Add(new Dropdown.OptionData(name));
|
||||||
|
FlagsDropdown.value = 0;
|
||||||
|
FlagsDropdown.RefreshShownValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<string> layerToNames;
|
||||||
|
|
||||||
|
private static void GetLayerNames()
|
||||||
|
{
|
||||||
|
layerToNames = new List<string>();
|
||||||
|
for (int i = 0; i < 32; i++)
|
||||||
|
{
|
||||||
|
string name = RuntimeHelper.LayerToName(i);
|
||||||
|
if (string.IsNullOrEmpty(name))
|
||||||
|
name = i.ToString();
|
||||||
|
layerToNames.Add(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Dictionary<string, HideFlags> hideFlagsValues;
|
||||||
|
|
||||||
|
private static void GetHideFlagNames()
|
||||||
|
{
|
||||||
|
hideFlagsValues = new Dictionary<string, HideFlags>();
|
||||||
|
|
||||||
|
Array names = Enum.GetValues(typeof(HideFlags));
|
||||||
|
foreach (HideFlags value in names)
|
||||||
|
{
|
||||||
|
hideFlagsValues.Add(value.ToString(), value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
111
src/UI/Widgets/GameObjects/TransformControls.cs
Normal file
111
src/UI/Widgets/GameObjects/TransformControls.cs
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
using UniverseLib.Input;
|
||||||
|
using UniverseLib.UI;
|
||||||
|
using UniverseLib.UI.Models;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
|
namespace UnityExplorer.UI.Widgets
|
||||||
|
{
|
||||||
|
// Handles axis change operations and holds references to the Vector3Controls for each transform property
|
||||||
|
|
||||||
|
public class TransformControls
|
||||||
|
{
|
||||||
|
public GameObjectControls Owner { get; }
|
||||||
|
GameObject Target => Owner.Target;
|
||||||
|
|
||||||
|
public AxisControl CurrentSlidingAxisControl { get; set; }
|
||||||
|
|
||||||
|
Vector3Control PositionControl;
|
||||||
|
Vector3Control LocalPositionControl;
|
||||||
|
Vector3Control RotationControl;
|
||||||
|
Vector3Control ScaleControl;
|
||||||
|
|
||||||
|
public TransformControls(GameObjectControls owner)
|
||||||
|
{
|
||||||
|
this.Owner = owner;
|
||||||
|
Create();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateTransformControlValues(bool force)
|
||||||
|
{
|
||||||
|
PositionControl.Update(force);
|
||||||
|
LocalPositionControl.Update(force);
|
||||||
|
RotationControl.Update(force);
|
||||||
|
ScaleControl.Update(force);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateVectorSlider()
|
||||||
|
{
|
||||||
|
AxisControl control = CurrentSlidingAxisControl;
|
||||||
|
|
||||||
|
if (control == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!InputManager.GetMouseButton(0))
|
||||||
|
{
|
||||||
|
control.slider.value = 0f;
|
||||||
|
control = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
AxisControlOperation(control.slider.value, control.parent, control.axis);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AxisControlOperation(float value, Vector3Control parent, int axis)
|
||||||
|
{
|
||||||
|
Transform transform = Target.transform;
|
||||||
|
|
||||||
|
Vector3 vector = parent.Type switch
|
||||||
|
{
|
||||||
|
TransformType.Position => transform.position,
|
||||||
|
TransformType.LocalPosition => transform.localPosition,
|
||||||
|
TransformType.Rotation => transform.localEulerAngles,
|
||||||
|
TransformType.Scale => transform.localScale,
|
||||||
|
_ => throw new NotImplementedException()
|
||||||
|
};
|
||||||
|
|
||||||
|
// apply vector value change
|
||||||
|
switch (axis)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
vector.x += value; break;
|
||||||
|
case 1:
|
||||||
|
vector.y += value; break;
|
||||||
|
case 2:
|
||||||
|
vector.z += value; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set vector back to transform
|
||||||
|
switch (parent.Type)
|
||||||
|
{
|
||||||
|
case TransformType.Position:
|
||||||
|
transform.position = vector; break;
|
||||||
|
case TransformType.LocalPosition:
|
||||||
|
transform.localPosition = vector; break;
|
||||||
|
case TransformType.Rotation:
|
||||||
|
transform.localEulerAngles = vector; break;
|
||||||
|
case TransformType.Scale:
|
||||||
|
transform.localScale = vector; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateTransformControlValues(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Create()
|
||||||
|
{
|
||||||
|
GameObject transformGroup = UIFactory.CreateVerticalGroup(Owner.Parent.Content, "TransformControls", false, false, true, true, 2,
|
||||||
|
new Vector4(2, 2, 0, 0), new Color(0.1f, 0.1f, 0.1f));
|
||||||
|
UIFactory.SetLayoutElement(transformGroup, minHeight: 100, flexibleWidth: 9999);
|
||||||
|
|
||||||
|
PositionControl = Vector3Control.Create(this, transformGroup, "Position:", TransformType.Position);
|
||||||
|
LocalPositionControl = Vector3Control.Create(this, transformGroup, "Local Position:", TransformType.LocalPosition);
|
||||||
|
RotationControl = Vector3Control.Create(this, transformGroup, "Rotation:", TransformType.Rotation);
|
||||||
|
ScaleControl = Vector3Control.Create(this, transformGroup, "Scale:", TransformType.Scale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
4
src/UI/Widgets/GameObjects/TransformType.cs
Normal file
4
src/UI/Widgets/GameObjects/TransformType.cs
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
namespace UnityExplorer.UI.Widgets
|
||||||
|
{
|
||||||
|
public enum TransformType { Position, LocalPosition, Rotation, Scale }
|
||||||
|
}
|
131
src/UI/Widgets/GameObjects/Vector3Control.cs
Normal file
131
src/UI/Widgets/GameObjects/Vector3Control.cs
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
using System;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
using UniverseLib;
|
||||||
|
using UniverseLib.UI;
|
||||||
|
using UniverseLib.UI.Models;
|
||||||
|
using UniverseLib.Utility;
|
||||||
|
|
||||||
|
namespace UnityExplorer.UI.Widgets
|
||||||
|
{
|
||||||
|
// Controls a Vector3 property of a Transform, and holds references to each AxisControl for X/Y/Z.
|
||||||
|
|
||||||
|
public class Vector3Control
|
||||||
|
{
|
||||||
|
public TransformControls Owner { get; }
|
||||||
|
public GameObject Target => Owner.Owner.Target;
|
||||||
|
public Transform Transform => Target.transform;
|
||||||
|
public TransformType Type { get; }
|
||||||
|
|
||||||
|
public InputFieldRef MainInput { get; }
|
||||||
|
|
||||||
|
public AxisControl[] AxisControls { get; } = new AxisControl[3];
|
||||||
|
|
||||||
|
public InputFieldRef IncrementInput { get; set; }
|
||||||
|
public float Increment { get; set; } = 0.1f;
|
||||||
|
|
||||||
|
Vector3 lastValue;
|
||||||
|
|
||||||
|
Vector3 CurrentValue => Type switch
|
||||||
|
{
|
||||||
|
TransformType.Position => Transform.position,
|
||||||
|
TransformType.LocalPosition => Transform.localPosition,
|
||||||
|
TransformType.Rotation => Transform.localEulerAngles,
|
||||||
|
TransformType.Scale => Transform.localScale,
|
||||||
|
_ => throw new NotImplementedException()
|
||||||
|
};
|
||||||
|
|
||||||
|
public Vector3Control(TransformControls owner, TransformType type, InputFieldRef input)
|
||||||
|
{
|
||||||
|
this.Owner = owner;
|
||||||
|
this.Type = type;
|
||||||
|
this.MainInput = input;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update(bool force)
|
||||||
|
{
|
||||||
|
Vector3 currValue = CurrentValue;
|
||||||
|
if (force || (!MainInput.Component.isFocused && !lastValue.Equals(currValue)))
|
||||||
|
{
|
||||||
|
MainInput.Text = ParseUtility.ToStringForInput<Vector3>(currValue);
|
||||||
|
lastValue = currValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnTransformInputEndEdit(TransformType type, string input)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case TransformType.Position:
|
||||||
|
{
|
||||||
|
if (ParseUtility.TryParse(input, out Vector3 val, out _))
|
||||||
|
Target.transform.position = val;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TransformType.LocalPosition:
|
||||||
|
{
|
||||||
|
if (ParseUtility.TryParse(input, out Vector3 val, out _))
|
||||||
|
Target.transform.localPosition = val;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TransformType.Rotation:
|
||||||
|
{
|
||||||
|
if (ParseUtility.TryParse(input, out Vector3 val, out _))
|
||||||
|
Target.transform.localEulerAngles = val;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TransformType.Scale:
|
||||||
|
{
|
||||||
|
if (ParseUtility.TryParse(input, out Vector3 val, out _))
|
||||||
|
Target.transform.localScale = val;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Owner.UpdateTransformControlValues(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IncrementInput_OnEndEdit(string value)
|
||||||
|
{
|
||||||
|
if (!ParseUtility.TryParse(value, out float increment, out _))
|
||||||
|
IncrementInput.Text = ParseUtility.ToStringForInput<float>(Increment);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Increment = increment;
|
||||||
|
foreach (AxisControl slider in AxisControls)
|
||||||
|
{
|
||||||
|
slider.slider.minValue = -increment;
|
||||||
|
slider.slider.maxValue = increment;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector3Control Create(TransformControls owner, GameObject transformGroup, string title, TransformType type)
|
||||||
|
{
|
||||||
|
GameObject rowObj = UIFactory.CreateUIObject($"Row_{title}", transformGroup);
|
||||||
|
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(rowObj, false, false, true, true, 5, 0, 0, 0, 0, default);
|
||||||
|
UIFactory.SetLayoutElement(rowObj, minHeight: 25, flexibleWidth: 9999);
|
||||||
|
|
||||||
|
Text titleLabel = UIFactory.CreateLabel(rowObj, "PositionLabel", title, TextAnchor.MiddleRight, Color.grey);
|
||||||
|
UIFactory.SetLayoutElement(titleLabel.gameObject, minHeight: 25, minWidth: 110);
|
||||||
|
|
||||||
|
InputFieldRef inputField = UIFactory.CreateInputField(rowObj, "InputField", "...");
|
||||||
|
UIFactory.SetLayoutElement(inputField.Component.gameObject, minHeight: 25, minWidth: 100, flexibleWidth: 999);
|
||||||
|
|
||||||
|
Vector3Control control = new(owner, type, inputField);
|
||||||
|
|
||||||
|
inputField.Component.GetOnEndEdit().AddListener((string value) => { control.OnTransformInputEndEdit(type, value); });
|
||||||
|
|
||||||
|
control.AxisControls[0] = AxisControl.Create(rowObj, "X", 0, control);
|
||||||
|
control.AxisControls[1] = AxisControl.Create(rowObj, "Y", 1, control);
|
||||||
|
control.AxisControls[2] = AxisControl.Create(rowObj, "Z", 2, control);
|
||||||
|
|
||||||
|
control.IncrementInput = UIFactory.CreateInputField(rowObj, "IncrementInput", "...");
|
||||||
|
control.IncrementInput.Text = "0.1";
|
||||||
|
UIFactory.SetLayoutElement(control.IncrementInput.GameObject, minWidth: 30, flexibleWidth: 0, minHeight: 25);
|
||||||
|
control.IncrementInput.Component.GetOnEndEdit().AddListener(control.IncrementInput_OnEndEdit);
|
||||||
|
|
||||||
|
return control;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -78,12 +78,12 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<!-- il2cpp nuget -->
|
<!-- il2cpp nuget -->
|
||||||
<ItemGroup Condition="'$(Configuration)'=='ML_Cpp_net6' or '$(Configuration)'=='ML_Cpp_net472' or '$(Configuration)'=='STANDALONE_Cpp' or '$(Configuration)'=='BIE_Cpp'">
|
<ItemGroup Condition="'$(Configuration)'=='ML_Cpp_net6' or '$(Configuration)'=='ML_Cpp_net472' or '$(Configuration)'=='STANDALONE_Cpp' or '$(Configuration)'=='BIE_Cpp'">
|
||||||
<PackageReference Include="Il2CppAssemblyUnhollower.BaseLib" Version="0.4.22" IncludeAssets="compile" />
|
<PackageReference Include="Il2CppAssemblyUnhollower.BaseLib" Version="0.4.22" />
|
||||||
<PackageReference Include="UniverseLib.IL2CPP" Version="1.3.12" />
|
<PackageReference Include="UniverseLib.IL2CPP" Version="1.3.14" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<!-- mono nuget -->
|
<!-- mono nuget -->
|
||||||
<ItemGroup Condition="'$(Configuration)'=='BIE6_Mono' or '$(Configuration)'=='BIE5_Mono' or '$(Configuration)'=='ML_Mono' or '$(Configuration)'=='STANDALONE_Mono'">
|
<ItemGroup Condition="'$(Configuration)'=='BIE6_Mono' or '$(Configuration)'=='BIE5_Mono' or '$(Configuration)'=='ML_Mono' or '$(Configuration)'=='STANDALONE_Mono'">
|
||||||
<PackageReference Include="UniverseLib.Mono" Version="1.3.12" />
|
<PackageReference Include="UniverseLib.Mono" Version="1.3.14" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<!-- ~~~~~ ASSEMBLY REFERENCES ~~~~~ -->
|
<!-- ~~~~~ ASSEMBLY REFERENCES ~~~~~ -->
|
||||||
|
Reference in New Issue
Block a user