mirror of
https://github.com/originalnicodr/CinematicUnityExplorer.git
synced 2025-07-19 01:57:56 +08:00
Compare commits
40 Commits
Author | SHA1 | Date | |
---|---|---|---|
e3584654a6 | |||
388c9fbc29 | |||
2f35b9d2c7 | |||
b82cc62186 | |||
9429b84cfa | |||
2719c69753 | |||
9144f89e32 | |||
3bc1268444 | |||
4c100daf83 | |||
e7d591176e | |||
ca46607c49 | |||
7fb67b4e28 | |||
c0f42ad983 | |||
6111c1743b | |||
b03d81052b | |||
173eeb993a | |||
07971489c4 | |||
2604dd8286 | |||
ca81bcc5dc | |||
b95178775c | |||
3928cdc4fe | |||
81d15270fe | |||
2b557a8c23 | |||
462201534d | |||
f3b154658c | |||
7ab907d7b0 | |||
736ebdfa1b | |||
c9aa93a6a4 | |||
78bf2fc634 | |||
6c493aaf7d | |||
b6d459b664 | |||
7a580d12ed | |||
8f2ec19660 | |||
f855f6d430 | |||
a6446c50e4 | |||
f3b48bf069 | |||
396e653495 | |||
68c482df22 | |||
a868cc74ac | |||
343ccb9474 |
34
.github/workflows/dotnet.yml
vendored
34
.github/workflows/dotnet.yml
vendored
@ -29,79 +29,79 @@ jobs:
|
|||||||
|
|
||||||
# Upload artifacts
|
# Upload artifacts
|
||||||
- name: Upload BepInEx.IL2CPP
|
- name: Upload BepInEx.IL2CPP
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: CinematicUnityExplorer.BepInEx.IL2CPP.zip
|
name: CinematicUnityExplorer.BepInEx.IL2CPP.zip
|
||||||
path: ./Release/CinematicUnityExplorer.BepInEx.IL2CPP/
|
path: ./Release/CinematicUnityExplorer.BepInEx.IL2CPP/
|
||||||
|
|
||||||
- name: Upload BepInEx.IL2CPP.CoreCLR
|
- name: Upload BepInEx.IL2CPP.CoreCLR
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: CinematicUnityExplorer.BepInEx.IL2CPP.CoreCLR.zip
|
name: CinematicUnityExplorer.BepInEx.IL2CPP.CoreCLR.zip
|
||||||
path: ./Release/CinematicUnityExplorer.BepInEx.IL2CPP.CoreCLR/
|
path: ./Release/CinematicUnityExplorer.BepInEx.IL2CPP.CoreCLR/
|
||||||
|
|
||||||
- name: Upload BepInEx.Unity.IL2CPP.CoreCLR
|
- name: Upload BepInEx.Unity.IL2CPP.CoreCLR
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: CinematicUnityExplorer.BepInEx.Unity.IL2CPP.CoreCLR.zip
|
name: CinematicUnityExplorer.BepInEx.Unity.IL2CPP.CoreCLR.zip
|
||||||
path: ./Release/CinematicUnityExplorer.BepInEx.Unity.IL2CPP.CoreCLR/
|
path: ./Release/CinematicUnityExplorer.BepInEx.Unity.IL2CPP.CoreCLR/
|
||||||
|
|
||||||
- name: Upload BepInEx5.Mono
|
- name: Upload BepInEx5.Mono
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: CinematicUnityExplorer.BepInEx5.Mono.zip
|
name: CinematicUnityExplorer.BepInEx5.Mono.zip
|
||||||
path: ./Release/CinematicUnityExplorer.BepInEx5.Mono/
|
path: ./Release/CinematicUnityExplorer.BepInEx5.Mono/
|
||||||
|
|
||||||
- name: Upload BepInEx6.Mono
|
- name: Upload BepInEx6.Mono
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: CinematicUnityExplorer.BepInEx6.Mono.zip
|
name: CinematicUnityExplorer.BepInEx6.Mono.zip
|
||||||
path: ./Release/CinematicUnityExplorer.BepInEx6.Mono/
|
path: ./Release/CinematicUnityExplorer.BepInEx6.Mono/
|
||||||
|
|
||||||
- name: Upload BepInEx6.Unity.Mono
|
- name: Upload BepInEx6.Unity.Mono
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: CinematicUnityExplorer.BepInEx6.Unity.Mono.zip
|
name: CinematicUnityExplorer.BepInEx6.Unity.Mono.zip
|
||||||
path: ./Release/CinematicUnityExplorer.BepInEx6.Unity.Mono/
|
path: ./Release/CinematicUnityExplorer.BepInEx6.Unity.Mono/
|
||||||
|
|
||||||
- name: Upload MelonLoader.IL2CPP
|
- name: Upload MelonLoader.IL2CPP
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: CinematicUnityExplorer.MelonLoader.IL2CPP.zip
|
name: CinematicUnityExplorer.MelonLoader.IL2CPP.zip
|
||||||
path: ./Release/CinematicUnityExplorer.MelonLoader.IL2CPP/
|
path: ./Release/CinematicUnityExplorer.MelonLoader.IL2CPP/
|
||||||
|
|
||||||
- name: Upload MelonLoader.IL2CPP.net6preview
|
- name: Upload MelonLoader.IL2CPP.net6preview
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: CinematicUnityExplorer.MelonLoader.IL2CPP.net6preview.zip
|
name: CinematicUnityExplorer.MelonLoader.IL2CPP.net6preview.zip
|
||||||
path: ./Release/CinematicUnityExplorer.MelonLoader.IL2CPP.net6preview/
|
path: ./Release/CinematicUnityExplorer.MelonLoader.IL2CPP.net6preview/
|
||||||
|
|
||||||
- name: Upload MelonLoader.IL2CPP.CoreCLR
|
- name: Upload MelonLoader.IL2CPP.CoreCLR
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: CinematicUnityExplorer.MelonLoader.IL2CPP.CoreCLR.zip
|
name: CinematicUnityExplorer.MelonLoader.IL2CPP.CoreCLR.zip
|
||||||
path: ./Release/CinematicUnityExplorer.MelonLoader.IL2CPP.CoreCLR/
|
path: ./Release/CinematicUnityExplorer.MelonLoader.IL2CPP.CoreCLR/
|
||||||
|
|
||||||
- name: Upload MelonLoader.Mono
|
- name: Upload MelonLoader.Mono
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: CinematicUnityExplorer.MelonLoader.Mono.zip
|
name: CinematicUnityExplorer.MelonLoader.Mono.zip
|
||||||
path: ./Release/CinematicUnityExplorer.MelonLoader.Mono/
|
path: ./Release/CinematicUnityExplorer.MelonLoader.Mono/
|
||||||
|
|
||||||
- name: Upload Standalone.IL2CPP
|
- name: Upload Standalone.IL2CPP
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: CinematicUnityExplorer.Standalone.IL2CPP.zip
|
name: CinematicUnityExplorer.Standalone.IL2CPP.zip
|
||||||
path: ./Release/CinematicUnityExplorer.Standalone.IL2CPP/
|
path: ./Release/CinematicUnityExplorer.Standalone.IL2CPP/
|
||||||
|
|
||||||
- name: Upload Standalone.Mono
|
- name: Upload Standalone.Mono
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: CinematicUnityExplorer.Standalone.Mono.zip
|
name: CinematicUnityExplorer.Standalone.Mono.zip
|
||||||
path: ./Release/CinematicUnityExplorer.Standalone.Mono/
|
path: ./Release/CinematicUnityExplorer.Standalone.Mono/
|
||||||
|
|
||||||
- name: Upload Editor
|
- name: Upload Editor
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: CinematicUnityExplorer.Editor.zip
|
name: CinematicUnityExplorer.Editor.zip
|
||||||
path: ./UnityEditorPackage/
|
path: ./UnityEditorPackage/
|
||||||
@ -127,7 +127,13 @@ jobs:
|
|||||||
run: ./build_connector.ps1
|
run: ./build_connector.ps1
|
||||||
|
|
||||||
- name: Upload Unity IGCS Connector
|
- name: Upload Unity IGCS Connector
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: UnityIGCSConnector.dll
|
name: UnityIGCSConnector.dll
|
||||||
path: ./Release/UnityIGCSConnector.dll
|
path: ./Release/UnityIGCSConnector.dll
|
||||||
|
|
||||||
|
- name: Upload Unity IGCS Connector 32bit
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: UnityIGCSConnector.32.dll
|
||||||
|
path: ./Release/UnityIGCSConnector.32.dll
|
||||||
|
@ -136,6 +136,7 @@ The original Unity Explorer had a Freecam feature, but even if it was useful at
|
|||||||
- Added tilt support.
|
- Added tilt support.
|
||||||
- Added FOV control support.
|
- Added FOV control support.
|
||||||
- Added near and far clip sliders on the Freecam panel, to cut out objects near the camera out of view, or include more scene objects on sight.
|
- Added near and far clip sliders on the Freecam panel, to cut out objects near the camera out of view, or include more scene objects on sight.
|
||||||
|
- Added new freecam methods to increase compatibility across games.
|
||||||
- Automatically disable the Cinemachine component if present when using the gameplay camera, to avoid the game from trying to take control.
|
- Automatically disable the Cinemachine component if present when using the gameplay camera, to avoid the game from trying to take control.
|
||||||
- Added a toggle to block the freecam from moving with user input.
|
- Added a toggle to block the freecam from moving with user input.
|
||||||
- Unlocked the mouse on freecam even when the mod UI is hidden.
|
- Unlocked the mouse on freecam even when the mod UI is hidden.
|
||||||
@ -147,6 +148,10 @@ You can click on the "Follow object" button on the panel and select the object y
|
|||||||
|
|
||||||
By default the camera only follows the object's position, but you can also make it follow its rotation as if the camera was physically bound to the object by checking the "Follow Object Rotation" toggle. Should be useful for mimicking a car camera, a character POV, or creating motion blur.
|
By default the camera only follows the object's position, but you can also make it follow its rotation as if the camera was physically bound to the object by checking the "Follow Object Rotation" toggle. Should be useful for mimicking a car camera, a character POV, or creating motion blur.
|
||||||
|
|
||||||
|
### Look At Object
|
||||||
|
|
||||||
|
As a side note, you can also "look at" a specific object in the world to force the camera to look directly toward it no matter the camera movement.
|
||||||
|
|
||||||
### Game input block for Unity's legacy system
|
### Game input block for Unity's legacy system
|
||||||
Added game input block for Unity's legacy system. You can now block (or unblock) the game's input when using the freecam, as long as the game is using the Unity Legacy Input system. If the game uses a custom solution or the latest Unity system then this won't work. Implementing this for Unity's new system is in the backlog, so if you find a game using it (should say "Initialized new InputSystem support." on the logs) then please let me know so I can implement it using that game!
|
Added game input block for Unity's legacy system. You can now block (or unblock) the game's input when using the freecam, as long as the game is using the Unity Legacy Input system. If the game uses a custom solution or the latest Unity system then this won't work. Implementing this for Unity's new system is in the backlog, so if you find a game using it (should say "Initialized new InputSystem support." on the logs) then please let me know so I can implement it using that game!
|
||||||
|
|
||||||
@ -188,6 +193,7 @@ It allows you to create nodes to build camera paths for videos and cinematics. F
|
|||||||
- Wait 3 seconds before start toggler.
|
- Wait 3 seconds before start toggler.
|
||||||
- Move nodes up or down on the list.
|
- Move nodes up or down on the list.
|
||||||
- Control over the tension and alpha values of the path, which are curve constants that change the resulting path created from the nodes. Their effect can be clearly seen when visualizing the path, as explained below.
|
- Control over the tension and alpha values of the path, which are curve constants that change the resulting path created from the nodes. Their effect can be clearly seen when visualizing the path, as explained below.
|
||||||
|
- Saving and loading camera paths to reuse them in different sessions.
|
||||||
|
|
||||||
As a side note, the mod UI will be disabled once the path starts, to ease video recording.
|
As a side note, the mod UI will be disabled once the path starts, to ease video recording.
|
||||||
|
|
||||||
@ -212,6 +218,8 @@ Alongside all of this, you can also open each character game object by clicking
|
|||||||
|
|
||||||
For each animator, you can also spawn a Bones Panel. This panel will list all of the character's bones and meshes, and provide easy-to-access toggles to disable them and sliders to move them around, allowing you to pose a character to your liking.
|
For each animator, you can also spawn a Bones Panel. This panel will list all of the character's bones and meshes, and provide easy-to-access toggles to disable them and sliders to move them around, allowing you to pose a character to your liking.
|
||||||
|
|
||||||
|
You can also save and load poses across different characters (if they have the same skeleton) and sessions.
|
||||||
|
|
||||||
## Misc Panel
|
## Misc Panel
|
||||||
- HUD toggle.
|
- HUD toggle.
|
||||||
- Force high LODs toggle. This means that the highest models possible will be forced on all meshes.
|
- Force high LODs toggle. This means that the highest models possible will be forced on all meshes.
|
||||||
|
Binary file not shown.
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "com.originalnicodr.cinematicunityexplorer",
|
"name": "com.originalnicodr.cinematicunityexplorer",
|
||||||
"version": "1.2.0",
|
"version": "1.3.0",
|
||||||
"displayName": "CinematicUnityExplorer",
|
"displayName": "CinematicUnityExplorer",
|
||||||
"description": "UnityExplorer fork focused on providing tools for creating marketing material for Unity games.",
|
"description": "UnityExplorer fork focused on providing tools for creating marketing material for Unity games.",
|
||||||
"unity": "2017.1",
|
"unity": "2017.1",
|
||||||
|
@ -76,13 +76,19 @@
|
|||||||
<PostBuildEventUseInBuild>false</PostBuildEventUseInBuild>
|
<PostBuildEventUseInBuild>false</PostBuildEventUseInBuild>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<TargetName>UnityIGCSConnector</TargetName>
|
<TargetName>UnityIGCSConnector.32</TargetName>
|
||||||
|
<OutDir>$(SolutionDir)..\$(Configuration)\</OutDir>
|
||||||
|
<PostBuildEventUseInBuild>false</PostBuildEventUseInBuild>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<TargetName>UnityIGCSConnector</TargetName>
|
<TargetName>UnityIGCSConnector</TargetName>
|
||||||
|
<OutDir>$(SolutionDir)..\$(Configuration)\</OutDir>
|
||||||
|
<PostBuildEventUseInBuild>false</PostBuildEventUseInBuild>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
<TargetName>UnityIGCSConnector</TargetName>
|
<TargetName>UnityIGCSConnector.32</TargetName>
|
||||||
|
<OutDir>$(SolutionDir)..\$(Configuration)\</OutDir>
|
||||||
|
<PostBuildEventUseInBuild>false</PostBuildEventUseInBuild>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
@ -90,7 +96,7 @@
|
|||||||
<SDLCheck>true</SDLCheck>
|
<SDLCheck>true</SDLCheck>
|
||||||
<PreprocessorDefinitions>WIN32;_DEBUG;UNITYIGCSCONNECTOR_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>WIN32;_DEBUG;UNITYIGCSCONNECTOR_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<ConformanceMode>true</ConformanceMode>
|
<ConformanceMode>true</ConformanceMode>
|
||||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
@ -107,7 +113,7 @@
|
|||||||
<SDLCheck>true</SDLCheck>
|
<SDLCheck>true</SDLCheck>
|
||||||
<PreprocessorDefinitions>WIN32;NDEBUG;UNITYIGCSCONNECTOR_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>WIN32;NDEBUG;UNITYIGCSCONNECTOR_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<ConformanceMode>true</ConformanceMode>
|
<ConformanceMode>true</ConformanceMode>
|
||||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
@ -164,4 +170,4 @@
|
|||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -19,7 +19,7 @@ SessionCallback GlobalEndSession = NULL;
|
|||||||
// There are things that only needs to be run once.
|
// There are things that only needs to be run once.
|
||||||
static int first_initialization = 1;
|
static int first_initialization = 1;
|
||||||
|
|
||||||
EXPOSE int IGCS_StartScreenshotSession(uint8_t _ignore) {
|
EXPOSE int __cdecl IGCS_StartScreenshotSession(uint8_t _ignore) {
|
||||||
if (GlobalStartSession) {
|
if (GlobalStartSession) {
|
||||||
GlobalStartSession();
|
GlobalStartSession();
|
||||||
printf("Called StartSession\n");
|
printf("Called StartSession\n");
|
||||||
@ -27,12 +27,12 @@ EXPOSE int IGCS_StartScreenshotSession(uint8_t _ignore) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPOSE void IGCS_EndScreenshotSession() {
|
EXPOSE void __cdecl IGCS_EndScreenshotSession() {
|
||||||
GlobalEndSession();
|
GlobalEndSession();
|
||||||
printf("Called EndSession\n");
|
printf("Called EndSession\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPOSE uint8_t* U_IGCS_Initialize(MoveCameraCallback cb, SessionCallback start_cb, SessionCallback end_cb) {
|
EXPOSE uint8_t* __cdecl U_IGCS_Initialize(MoveCameraCallback cb, SessionCallback start_cb, SessionCallback end_cb) {
|
||||||
AllocConsole();
|
AllocConsole();
|
||||||
printf("Initializing callback\n");
|
printf("Initializing callback\n");
|
||||||
GlobalCallback = cb;
|
GlobalCallback = cb;
|
||||||
@ -40,7 +40,11 @@ EXPOSE uint8_t* U_IGCS_Initialize(MoveCameraCallback cb, SessionCallback start_c
|
|||||||
GlobalEndSession = end_cb;
|
GlobalEndSession = end_cb;
|
||||||
|
|
||||||
// Load IGCS
|
// Load IGCS
|
||||||
|
#ifdef _M_IX86
|
||||||
|
HMODULE igcs = LoadLibraryA("IgcsConnector.addon32");
|
||||||
|
#else
|
||||||
HMODULE igcs = LoadLibraryA("IgcsConnector.addon64");
|
HMODULE igcs = LoadLibraryA("IgcsConnector.addon64");
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!igcs) {
|
if (!igcs) {
|
||||||
MessageBoxA(
|
MessageBoxA(
|
||||||
@ -69,9 +73,9 @@ EXPOSE uint8_t* U_IGCS_Initialize(MoveCameraCallback cb, SessionCallback start_c
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPOSE void IGCS_MoveCameraPanorama() {}
|
EXPOSE void __cdecl IGCS_MoveCameraPanorama() {}
|
||||||
|
|
||||||
EXPOSE void IGCS_MoveCameraMultishot(float step_left, float step_up, float fov, int from_start) {
|
EXPOSE void __cdecl IGCS_MoveCameraMultishot(float step_left, float step_up, float fov, int from_start) {
|
||||||
GlobalCallback(step_left, step_up, fov, from_start);
|
GlobalCallback(step_left, step_up, fov, from_start);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
# ----------- Build UnityIGCSConnector ------------
|
# ----------- Build UnityIGCSConnector ------------
|
||||||
msbuild.exe UnityIGCSConnector/UnityIGCSConnector.sln -p:Configuration=Release
|
msbuild.exe UnityIGCSConnector/UnityIGCSConnector.sln -p:Configuration=Release -p:Platform=x64
|
||||||
|
|
||||||
|
msbuild.exe UnityIGCSConnector/UnityIGCSConnector.sln -p:Configuration=Release -p:Platform=x86
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using UnityExplorer.Config;
|
||||||
#if UNHOLLOWER
|
#if UNHOLLOWER
|
||||||
using IL2CPPUtils = UnhollowerBaseLib.UnhollowerUtils;
|
using IL2CPPUtils = UnhollowerBaseLib.UnhollowerUtils;
|
||||||
#endif
|
#endif
|
||||||
@ -12,8 +13,12 @@ namespace UnityExplorer
|
|||||||
{
|
{
|
||||||
public class ArrowGenerator
|
public class ArrowGenerator
|
||||||
{
|
{
|
||||||
public static GameObject CreateArrow(Vector3 arrowPosition, Quaternion arrowRotation, Color color){
|
public static GameObject CreateArrow(Vector3 arrowPosition, Quaternion arrowRotation, Color color)
|
||||||
|
{
|
||||||
try {
|
try {
|
||||||
|
float arrowSizeValue = ConfigManager.Arrow_Size.Value;
|
||||||
|
Vector3 arrowSize = new Vector3(Math.Max(arrowSizeValue, 0.1f), Math.Max(arrowSizeValue, 0.1f), Math.Max(arrowSizeValue, 0.1f));
|
||||||
|
|
||||||
GameObject cylinder = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
|
GameObject cylinder = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
|
||||||
cylinder.GetComponent<Collider>().enabled = false;
|
cylinder.GetComponent<Collider>().enabled = false;
|
||||||
cylinder.GetComponent<MeshFilter>().mesh = CreateCylinderMesh(0.01f, 20, 2);
|
cylinder.GetComponent<MeshFilter>().mesh = CreateCylinderMesh(0.01f, 20, 2);
|
||||||
@ -34,6 +39,7 @@ namespace UnityExplorer
|
|||||||
|
|
||||||
GameObject arrow = new GameObject("CUE-Arrow");
|
GameObject arrow = new GameObject("CUE-Arrow");
|
||||||
cylinder.transform.SetParent(arrow.transform, true);
|
cylinder.transform.SetParent(arrow.transform, true);
|
||||||
|
arrow.transform.localScale = arrowSize;
|
||||||
arrow.transform.position = arrowPosition;
|
arrow.transform.position = arrowPosition;
|
||||||
arrow.transform.rotation = arrowRotation;
|
arrow.transform.rotation = arrowRotation;
|
||||||
arrow.transform.position += 0.5f * arrow.transform.forward; // Move the arrow forward so the cylinder starts on the wanted position
|
arrow.transform.position += 0.5f * arrow.transform.forward; // Move the arrow forward so the cylinder starts on the wanted position
|
||||||
|
@ -20,7 +20,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
public AnimatorPlayer animatorPlayer;
|
public AnimatorPlayer animatorPlayer;
|
||||||
|
|
||||||
public Toggle IgnoreMasterToggle;
|
public Toggle IgnoreMasterToggle;
|
||||||
public Toggle AnimatorToggle;
|
public AnimatorPausePlayButton animatorToggler;
|
||||||
public Toggle MeshToggle;
|
public Toggle MeshToggle;
|
||||||
public ButtonRef inspectButton;
|
public ButtonRef inspectButton;
|
||||||
public Dropdown animatorDropdown;
|
public Dropdown animatorDropdown;
|
||||||
@ -42,7 +42,8 @@ namespace UnityExplorer.UI.Panels
|
|||||||
this.animatorPlayer = animatorPlayer;
|
this.animatorPlayer = animatorPlayer;
|
||||||
inspectButton.ButtonText.text = animatorPlayer.animator.name;
|
inspectButton.ButtonText.text = animatorPlayer.animator.name;
|
||||||
IgnoreMasterToggle.isOn = animatorPlayer.shouldIgnoreMasterToggle;
|
IgnoreMasterToggle.isOn = animatorPlayer.shouldIgnoreMasterToggle;
|
||||||
AnimatorToggle.isOn = animatorPlayer.animator.speed != 0;
|
animatorToggler.isOn = animatorPlayer.animator.speed != 0;
|
||||||
|
MeshToggle.isOn = animatorPlayer.IsMeshHidden();
|
||||||
|
|
||||||
UpdateDropdownOptions();
|
UpdateDropdownOptions();
|
||||||
}
|
}
|
||||||
@ -95,10 +96,8 @@ namespace UnityExplorer.UI.Panels
|
|||||||
UIFactory.SetLayoutElement(inspectButton.GameObject, minWidth: 200, minHeight: 25);
|
UIFactory.SetLayoutElement(inspectButton.GameObject, minWidth: 200, minHeight: 25);
|
||||||
inspectButton.OnClick += () => InspectorManager.Inspect(animatorPlayer.animator.gameObject);
|
inspectButton.OnClick += () => InspectorManager.Inspect(animatorPlayer.animator.gameObject);
|
||||||
|
|
||||||
GameObject AnimatorToggleObj = UIFactory.CreateToggle(UIRoot, "AnimatorToggle", out AnimatorToggle, out Text animatorToggleText);
|
animatorToggler = new AnimatorPausePlayButton(UIRoot, animatorPlayer != null && animatorPlayer.animator.speed == 1);
|
||||||
UIFactory.SetLayoutElement(AnimatorToggleObj, minHeight: 30);
|
animatorToggler.OnClick += ButtonEnableAnimation;
|
||||||
AnimatorToggle.isOn = animatorPlayer != null && animatorPlayer.animator.speed == 1;
|
|
||||||
AnimatorToggle.onValueChanged.AddListener(EnableAnimation);
|
|
||||||
|
|
||||||
ButtonRef resetAnimation = UIFactory.CreateButton(UIRoot, "Reset Animation", "Reset");
|
ButtonRef resetAnimation = UIFactory.CreateButton(UIRoot, "Reset Animation", "Reset");
|
||||||
UIFactory.SetLayoutElement(resetAnimation.GameObject, minWidth: 50, minHeight: 25);
|
UIFactory.SetLayoutElement(resetAnimation.GameObject, minWidth: 50, minHeight: 25);
|
||||||
@ -165,7 +164,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
animationTimeline.maxValue = 1;
|
animationTimeline.maxValue = 1;
|
||||||
animationTimeline.onValueChanged.AddListener((float val) => {
|
animationTimeline.onValueChanged.AddListener((float val) => {
|
||||||
animatorPlayer.PlayOverridingAnimation(val);
|
animatorPlayer.PlayOverridingAnimation(val);
|
||||||
AnimatorToggle.isOn = false;
|
animatorToggler.isOn = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
playButton = UIFactory.CreateButton(UIRoot, "PlayButton", "Play", new Color(0.2f, 0.26f, 0.2f));
|
playButton = UIFactory.CreateButton(UIRoot, "PlayButton", "Play", new Color(0.2f, 0.26f, 0.2f));
|
||||||
@ -188,6 +187,10 @@ namespace UnityExplorer.UI.Panels
|
|||||||
animatorPlayer.shouldIgnoreMasterToggle = value;
|
animatorPlayer.shouldIgnoreMasterToggle = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal void ButtonEnableAnimation(){
|
||||||
|
EnableAnimation(animatorToggler.isOn);
|
||||||
|
}
|
||||||
|
|
||||||
internal void EnableAnimation(bool value){
|
internal void EnableAnimation(bool value){
|
||||||
if (animatorPlayer.animator.wrappedObject != null)
|
if (animatorPlayer.animator.wrappedObject != null)
|
||||||
animatorPlayer.animator.speed = value ? 1 : 0;
|
animatorPlayer.animator.speed = value ? 1 : 0;
|
||||||
|
@ -48,8 +48,12 @@ namespace UnityExplorer.UI.Panels
|
|||||||
|
|
||||||
this.favAnimations = new List<IAnimationClip>();
|
this.favAnimations = new List<IAnimationClip>();
|
||||||
|
|
||||||
this.skinnedMeshes.AddRange(this.animator.wrappedObject.gameObject.GetComponentsInChildren<SkinnedMeshRenderer>(false));
|
SearchMeshes();
|
||||||
this.extraMeshes.AddRange(this.animator.wrappedObject.gameObject.GetComponentsInChildren<MeshRenderer>(false));
|
}
|
||||||
|
|
||||||
|
public void SearchMeshes(){
|
||||||
|
skinnedMeshes = new List<SkinnedMeshRenderer>(animator.wrappedObject.gameObject.GetComponentsInChildren<SkinnedMeshRenderer>(false));
|
||||||
|
extraMeshes = new List<MeshRenderer>(animator.wrappedObject.gameObject.GetComponentsInChildren<MeshRenderer>(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Include the animations being played in other layers
|
// Include the animations being played in other layers
|
||||||
@ -125,25 +129,30 @@ namespace UnityExplorer.UI.Panels
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Transform> GetMeshes(){
|
private List<Transform> GetMeshesTransforms(){
|
||||||
List<Transform> meshes = new List<Transform>();
|
List<Transform> meshes = new List<Transform>();
|
||||||
|
|
||||||
foreach (SkinnedMeshRenderer skinnedMesh in skinnedMeshes) {
|
foreach (SkinnedMeshRenderer skinnedMesh in skinnedMeshes) {
|
||||||
meshes.AddRange(skinnedMesh.bones);
|
meshes.AddRange(skinnedMesh.bones);
|
||||||
}
|
}
|
||||||
meshes.AddRange(extraMeshes.Select(m => m.transform));
|
meshes.AddRange(extraMeshes.Select(m => m.transform));
|
||||||
|
meshes.RemoveAll(item => item == null);
|
||||||
return meshes.GroupBy(b => b.name).Select(b => b.First()).ToList().OrderBy(b => b.name).ToList();
|
return meshes.GroupBy(b => b.name).Select(b => b.First()).ToList().OrderBy(b => b.name).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OpenBonesPanel(){
|
public void OpenBonesPanel(){
|
||||||
if (skinnedMeshes.Count == 0 && extraMeshes.Count == 0) return;
|
if (skinnedMeshes.Count == 0 && extraMeshes.Count == 0) return;
|
||||||
if (bonesManager == null){
|
if (bonesManager == null){
|
||||||
bonesManager = new BonesManager(UIManager.GetPanel<UnityExplorer.UI.Panels.AnimatorPanel>(UIManager.Panels.AnimatorPanel).Owner, GetMeshes(), animator);
|
bonesManager = new BonesManager(UIManager.GetPanel<UnityExplorer.UI.Panels.AnimatorPanel>(UIManager.Panels.AnimatorPanel).Owner, GetMeshesTransforms(), animator);
|
||||||
}
|
}
|
||||||
bonesManager.SetActive(true);
|
bonesManager.SetActive(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void MaybeResetBonesPanel(){
|
||||||
|
if (bonesManager == null) return;
|
||||||
|
bonesManager.RefreshBones(GetMeshesTransforms());
|
||||||
|
}
|
||||||
|
|
||||||
public void SetMeshesEnabled(bool value){
|
public void SetMeshesEnabled(bool value){
|
||||||
foreach (SkinnedMeshRenderer skinnedMesh in skinnedMeshes) {
|
foreach (SkinnedMeshRenderer skinnedMesh in skinnedMeshes) {
|
||||||
skinnedMesh.TryCast<Renderer>().enabled = value;
|
skinnedMesh.TryCast<Renderer>().enabled = value;
|
||||||
@ -153,6 +162,11 @@ namespace UnityExplorer.UI.Panels
|
|||||||
meshRenderer.gameObject.SetActive(value);
|
meshRenderer.gameObject.SetActive(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool IsMeshHidden(){
|
||||||
|
// Could maybe save a variable to set on SetMeshesEnabled instead
|
||||||
|
return skinnedMeshes.Any( m => m.TryCast<Renderer>().enabled) || extraMeshes.Any( m => m.gameObject.activeSelf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class IAnimator
|
public class IAnimator
|
||||||
|
@ -8,7 +8,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
{
|
{
|
||||||
public class BonesCell : ICell
|
public class BonesCell : ICell
|
||||||
{
|
{
|
||||||
public Transform bone;
|
public BoneTree boneTree;
|
||||||
public TransformControls transformControls;
|
public TransformControls transformControls;
|
||||||
|
|
||||||
ComponentControl positionControl;
|
ComponentControl positionControl;
|
||||||
@ -16,7 +16,13 @@ namespace UnityExplorer.UI.Panels
|
|||||||
ComponentControl scaleControl;
|
ComponentControl scaleControl;
|
||||||
public AxisComponentControl CurrentSlidingAxisControl { get; set; }
|
public AxisComponentControl CurrentSlidingAxisControl { get; set; }
|
||||||
public BonesManager Owner;
|
public BonesManager Owner;
|
||||||
private ButtonRef inspectButton;
|
private Text boneName;
|
||||||
|
|
||||||
|
private GameObject expandBonesRow;
|
||||||
|
private ButtonRef expandBonesButton;
|
||||||
|
private Text expandBonesText;
|
||||||
|
private LayoutElement spaceLayout;
|
||||||
|
static private int TREE_LEVEL_IDENTATION = 20;
|
||||||
|
|
||||||
// ICell
|
// ICell
|
||||||
public float DefaultHeight => 25f;
|
public float DefaultHeight => 25f;
|
||||||
@ -27,20 +33,69 @@ namespace UnityExplorer.UI.Panels
|
|||||||
public void Enable() => UIRoot.SetActive(true);
|
public void Enable() => UIRoot.SetActive(true);
|
||||||
public void Disable() => UIRoot.SetActive(false);
|
public void Disable() => UIRoot.SetActive(false);
|
||||||
|
|
||||||
public void SetBone(Transform bone, BonesManager bonesManager){
|
public void SetBoneTree(BoneTree boneTree, BonesManager bonesManager){
|
||||||
this.bone = bone;
|
this.boneTree = boneTree;
|
||||||
inspectButton.ButtonText.text = bone.name;
|
boneName.text = boneTree.obj.name;
|
||||||
Owner = bonesManager;
|
Owner = bonesManager;
|
||||||
|
|
||||||
|
if (boneTree.childTrees.Count == 0){
|
||||||
|
expandBonesRow.SetActive(false);
|
||||||
|
} else {
|
||||||
|
expandBonesRow.SetActive(true);
|
||||||
|
bool isTreeExpanded = IsTreeExpanded();
|
||||||
|
expandBonesButton.ButtonText.text = isTreeExpanded ? "▼" : "▶";
|
||||||
|
expandBonesText.text = isTreeExpanded ? "Collapse bones" : "Expand bones";
|
||||||
|
}
|
||||||
|
|
||||||
|
spaceLayout.minWidth = TREE_LEVEL_IDENTATION * boneTree.level;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ExpandOrCollapseBoneTree(){
|
||||||
|
if (IsTreeExpanded()){
|
||||||
|
// Collapse
|
||||||
|
List<BoneTree> treesToRemove = boneTree.childTrees.Select(t => t.flatten()).SelectMany(l => l).ToList();
|
||||||
|
Owner.boneTrees = Owner.boneTrees.Except(treesToRemove).ToList();
|
||||||
|
expandBonesButton.ButtonText.text = "▶";
|
||||||
|
expandBonesText.text = "Expand bones";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Expand
|
||||||
|
int index = Owner.boneTrees.FindIndex(t => t == boneTree);
|
||||||
|
if (index == -1) return;
|
||||||
|
|
||||||
|
Owner.boneTrees.InsertRange(index + 1, boneTree.childTrees);
|
||||||
|
expandBonesButton.ButtonText.text = "▼";
|
||||||
|
expandBonesText.text = "Collapse bones";
|
||||||
|
}
|
||||||
|
|
||||||
|
Owner.boneScrollPool.Refresh(true, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsTreeExpanded(){
|
||||||
|
if (boneTree == null) return true;
|
||||||
|
return boneTree.childTrees.Any(t1 => Owner.boneTrees.Any(t2 => t2 == t1));
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual GameObject CreateContent(GameObject parent)
|
public virtual GameObject CreateContent(GameObject parent)
|
||||||
{
|
{
|
||||||
UIRoot = UIFactory.CreateUIObject("BoneCell", parent, new Vector2(25, 25));
|
UIRoot = UIFactory.CreateUIObject("CellRoot", parent, new Vector2(25, 25));
|
||||||
Rect = UIRoot.GetComponent<RectTransform>();
|
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(UIRoot, false, false, true, true, 4, childAlignment: TextAnchor.MiddleRight);
|
||||||
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(UIRoot, false, false, true, true, 3);
|
UIFactory.SetLayoutElement(UIRoot, minHeight: 25, flexibleWidth: 9999, flexibleHeight: 800);
|
||||||
UIFactory.SetLayoutElement(UIRoot, minHeight: 25, minWidth: 50, flexibleWidth: 9999);
|
|
||||||
|
|
||||||
GameObject header = UIFactory.CreateUIObject("BoneHeader", UIRoot);
|
Rect = UIRoot.GetComponent<RectTransform>();
|
||||||
|
Rect.anchorMin = new Vector2(0, 1);
|
||||||
|
Rect.anchorMax = new Vector2(0, 1);
|
||||||
|
Rect.pivot = new Vector2(0.5f, 1);
|
||||||
|
Rect.sizeDelta = new Vector2(30, 30);
|
||||||
|
|
||||||
|
GameObject spacer = UIFactory.CreateUIObject("Spacer", UIRoot);
|
||||||
|
spaceLayout = UIFactory.SetLayoutElement(spacer, minWidth: 0, flexibleWidth: 0);
|
||||||
|
|
||||||
|
GameObject baseCell = UIFactory.CreateUIObject("BaseCell", UIRoot);
|
||||||
|
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(baseCell, false, false, true, true, 3);
|
||||||
|
UIFactory.SetLayoutElement(baseCell, minHeight: 25, minWidth: 50, flexibleWidth: 9999);
|
||||||
|
|
||||||
|
GameObject header = UIFactory.CreateUIObject("BoneHeader", baseCell);
|
||||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(header, false, false, true, true, 4, childAlignment: TextAnchor.MiddleLeft);
|
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(header, false, false, true, true, 4, childAlignment: TextAnchor.MiddleLeft);
|
||||||
UIFactory.SetLayoutElement(header, minHeight: 25, flexibleWidth: 9999, flexibleHeight: 800);
|
UIFactory.SetLayoutElement(header, minHeight: 25, flexibleWidth: 9999, flexibleHeight: 800);
|
||||||
|
|
||||||
@ -48,31 +103,45 @@ namespace UnityExplorer.UI.Panels
|
|||||||
UIFactory.SetLayoutElement(MeshToggleObj, minHeight: 30);
|
UIFactory.SetLayoutElement(MeshToggleObj, minHeight: 30);
|
||||||
MeshToggle.onValueChanged.AddListener(SetBoneEnabled);
|
MeshToggle.onValueChanged.AddListener(SetBoneEnabled);
|
||||||
|
|
||||||
inspectButton = UIFactory.CreateButton(header, "InspectButton", "");
|
boneName = UIFactory.CreateLabel(header, $"BoneName", "", fontSize: 18);
|
||||||
UIFactory.SetLayoutElement(inspectButton.GameObject, minWidth: 150, minHeight: 25);
|
UIFactory.SetLayoutElement(boneName.gameObject, minWidth: 100, minHeight: 25, flexibleWidth: 9999);
|
||||||
inspectButton.OnClick += () => InspectorManager.Inspect(bone.gameObject);
|
|
||||||
|
|
||||||
GameObject headerButtons = UIFactory.CreateUIObject("BoneHeader", header);
|
GameObject headerButtons = UIFactory.CreateUIObject("BoneHeader", header);
|
||||||
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(headerButtons, false, false, true, true, 4, childAlignment: TextAnchor.MiddleRight);
|
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(headerButtons, false, false, true, true, 4, childAlignment: TextAnchor.MiddleRight);
|
||||||
UIFactory.SetLayoutElement(headerButtons, minHeight: 25, flexibleWidth: 9999, flexibleHeight: 800);
|
UIFactory.SetLayoutElement(headerButtons, minHeight: 25, flexibleWidth: 9999, flexibleHeight: 800);
|
||||||
|
|
||||||
|
ButtonRef inspectButton = UIFactory.CreateButton(headerButtons, "InspectButton", "Inspect");
|
||||||
|
UIFactory.SetLayoutElement(inspectButton.GameObject, minWidth: 75, minHeight: 25);
|
||||||
|
inspectButton.OnClick += () => InspectorManager.Inspect(boneTree.obj);
|
||||||
|
|
||||||
ButtonRef restoreBoneStateButton = UIFactory.CreateButton(headerButtons, "RestoreBoneState", "Restore State");
|
ButtonRef restoreBoneStateButton = UIFactory.CreateButton(headerButtons, "RestoreBoneState", "Restore State");
|
||||||
UIFactory.SetLayoutElement(restoreBoneStateButton.GameObject, minWidth: 125, minHeight: 25);
|
UIFactory.SetLayoutElement(restoreBoneStateButton.GameObject, minWidth: 125, minHeight: 25);
|
||||||
restoreBoneStateButton.OnClick += RestoreBoneState;
|
restoreBoneStateButton.OnClick += RestoreBoneState;
|
||||||
|
|
||||||
positionControl = ComponentControl.Create(this, UIRoot, "Local Position", TransformType.LocalPosition, 0.01f);
|
positionControl = ComponentControl.Create(this, baseCell, "Local Position", TransformType.LocalPosition, 0.01f);
|
||||||
rotationControl = ComponentControl.Create(this, UIRoot, "Rotation", TransformType.Rotation, 10f);
|
rotationControl = ComponentControl.Create(this, baseCell, "Rotation", TransformType.Rotation, 10f);
|
||||||
scaleControl = ComponentControl.Create(this, UIRoot, "Scale", TransformType.Scale, 0.1f);
|
scaleControl = ComponentControl.Create(this, baseCell, "Scale", TransformType.Scale, 0.1f);
|
||||||
|
|
||||||
|
expandBonesRow = UIFactory.CreateUIObject("ExpandBonesRow", baseCell);
|
||||||
|
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(expandBonesRow, false, false, true, true, 4, childAlignment: TextAnchor.MiddleLeft);
|
||||||
|
UIFactory.SetLayoutElement(expandBonesRow, minHeight: 25, flexibleWidth: 9999, flexibleHeight: 800);
|
||||||
|
|
||||||
|
expandBonesButton = UIFactory.CreateButton(expandBonesRow, "ExpandBonesButton", IsTreeExpanded() ? "⯆" : "▶", new Color(0.05f, 0.05f, 0.05f));
|
||||||
|
UIFactory.SetLayoutElement(expandBonesButton.Component.gameObject, minHeight: 25, minWidth: 25);
|
||||||
|
expandBonesButton.OnClick += ExpandOrCollapseBoneTree;
|
||||||
|
|
||||||
|
expandBonesText = UIFactory.CreateLabel(expandBonesRow, $"ExpandBonesText", IsTreeExpanded() ? "Collapse bones" : "Expand bones");
|
||||||
|
UIFactory.SetLayoutElement(expandBonesText.gameObject, minWidth: 100, minHeight: 25);
|
||||||
|
|
||||||
return UIRoot;
|
return UIRoot;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RestoreBoneState(){
|
private void RestoreBoneState(){
|
||||||
Owner.RestoreBoneState(bone.name);
|
Owner.RestoreBoneState(boneTree.obj.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetBoneEnabled(bool value){
|
private void SetBoneEnabled(bool value){
|
||||||
bone.gameObject.SetActive(value);
|
boneTree.obj.SetActive(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TransformControls-like functions
|
// TransformControls-like functions
|
||||||
@ -103,7 +172,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
|
|
||||||
public void AxisControlOperation(float value, ComponentControl parent, int axis)
|
public void AxisControlOperation(float value, ComponentControl parent, int axis)
|
||||||
{
|
{
|
||||||
Transform transform = bone;
|
Transform transform = boneTree.obj.transform;
|
||||||
|
|
||||||
Vector3 vector = parent.Type switch
|
Vector3 vector = parent.Type switch
|
||||||
{
|
{
|
||||||
@ -146,7 +215,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
public class ComponentControl
|
public class ComponentControl
|
||||||
{
|
{
|
||||||
public BonesCell Owner { get; }
|
public BonesCell Owner { get; }
|
||||||
public Transform Transform => Owner.bone;
|
public Transform Transform => Owner.boneTree.obj.transform;
|
||||||
public TransformType Type { get; }
|
public TransformType Type { get; }
|
||||||
|
|
||||||
public InputFieldRef MainInput { get; }
|
public InputFieldRef MainInput { get; }
|
||||||
@ -275,7 +344,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
uniformScaleControl.minValue = 0.0001f;
|
uniformScaleControl.minValue = 0.0001f;
|
||||||
uniformScaleControl.maxValue = 10;
|
uniformScaleControl.maxValue = 10;
|
||||||
uniformScaleControl.value = 1;
|
uniformScaleControl.value = 1;
|
||||||
uniformScaleControl.onValueChanged.AddListener((float val) => { cell.bone.localScale = new Vector3(val, val, val); });
|
uniformScaleControl.onValueChanged.AddListener((float val) => { cell.boneTree.obj.transform.localScale = new Vector3(val, val, val); });
|
||||||
}
|
}
|
||||||
|
|
||||||
return control;
|
return control;
|
||||||
|
@ -43,8 +43,11 @@ namespace UnityExplorer.UI.Panels
|
|||||||
ButtonRef copyFovButton = UIFactory.CreateButton(UIRoot, "Copy Camera FoV", "Copy Camera FoV");
|
ButtonRef copyFovButton = UIFactory.CreateButton(UIRoot, "Copy Camera FoV", "Copy Camera FoV");
|
||||||
UIFactory.SetLayoutElement(copyFovButton.GameObject, minWidth: 100, minHeight: 25, flexibleWidth: 9999);
|
UIFactory.SetLayoutElement(copyFovButton.GameObject, minWidth: 100, minHeight: 25, flexibleWidth: 9999);
|
||||||
copyFovButton.OnClick += () => {
|
copyFovButton.OnClick += () => {
|
||||||
point.fov = FreeCamPanel.ourCamera.fieldOfView;
|
Camera freecam = FreeCamPanel.GetFreecam();
|
||||||
GetCamPathsPanel().controlPoints[index] = point;
|
if (freecam != null) {
|
||||||
|
point.fov = freecam.fieldOfView;
|
||||||
|
GetCamPathsPanel().controlPoints[index] = point;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ButtonRef moveToPointButton = UIFactory.CreateButton(UIRoot, "Move Cam to Node", "Move Cam to Node");
|
ButtonRef moveToPointButton = UIFactory.CreateButton(UIRoot, "Move Cam to Node", "Move Cam to Node");
|
||||||
@ -52,7 +55,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
moveToPointButton.OnClick += () => {
|
moveToPointButton.OnClick += () => {
|
||||||
FreeCamPanel.SetCameraRotation(point.rotation);
|
FreeCamPanel.SetCameraRotation(point.rotation);
|
||||||
FreeCamPanel.SetCameraPosition(point.position);
|
FreeCamPanel.SetCameraPosition(point.position);
|
||||||
FreeCamPanel.ourCamera.fieldOfView = point.fov;
|
FreeCamPanel.SetFOV(point.fov);
|
||||||
};
|
};
|
||||||
|
|
||||||
ButtonRef moveUpButton = UIFactory.CreateButton(UIRoot, "MoveUp", "▲");
|
ButtonRef moveUpButton = UIFactory.CreateButton(UIRoot, "MoveUp", "▲");
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using UnityExplorer.Config;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
using UniverseLib.UI.Models;
|
using UniverseLib.UI.Models;
|
||||||
using UniverseLib.UI.Widgets.ScrollView;
|
using UniverseLib.UI.Widgets.ScrollView;
|
||||||
@ -29,7 +30,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
|
|
||||||
//Active toggle
|
//Active toggle
|
||||||
Toggle toggleLight;
|
Toggle toggleLight;
|
||||||
GameObject toggleObj = UIFactory.CreateToggle(UIRoot, "UseGameCameraToggle", out toggleLight, out label);
|
GameObject toggleObj = UIFactory.CreateToggle(UIRoot, "ActivateLightToggle", out toggleLight, out label);
|
||||||
UIFactory.SetLayoutElement(toggleObj, minHeight: 25, flexibleWidth: 9999);
|
UIFactory.SetLayoutElement(toggleObj, minHeight: 25, flexibleWidth: 9999);
|
||||||
toggleLight.onValueChanged.AddListener(value => { light.SetActive(value); });
|
toggleLight.onValueChanged.AddListener(value => { light.SetActive(value); });
|
||||||
toggleLight.isOn = true;
|
toggleLight.isOn = true;
|
||||||
@ -69,6 +70,9 @@ namespace UnityExplorer.UI.Panels
|
|||||||
|
|
||||||
private void ToggleVisualizer(){
|
private void ToggleVisualizer(){
|
||||||
GameObject visualizer = light.transform.GetChild(0).gameObject;
|
GameObject visualizer = light.transform.GetChild(0).gameObject;
|
||||||
|
float arrowSize = ConfigManager.Arrow_Size.Value;
|
||||||
|
Vector3 arrowSizeVec = new Vector3(Math.Max(arrowSize, 0.1f), Math.Max(arrowSize, 0.1f), Math.Max(arrowSize, 0.1f));
|
||||||
|
light.transform.GetChild(0).localScale = arrowSizeVec;
|
||||||
visualizer.SetActive(!visualizer.activeSelf);
|
visualizer.SetActive(!visualizer.activeSelf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,7 +94,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void CopyFreeCamTransform(GameObject obj){
|
public static void CopyFreeCamTransform(GameObject obj){
|
||||||
Camera freeCam = FreeCamPanel.ourCamera;
|
Camera freeCam = FreeCamPanel.GetFreecam();
|
||||||
|
|
||||||
if (freeCam != null) {
|
if (freeCam != null) {
|
||||||
obj.transform.position = freeCam.transform.position;
|
obj.transform.position = freeCam.transform.position;
|
||||||
|
89
src/Cinematic/Serializers/BonesSerializer.cs
Normal file
89
src/Cinematic/Serializers/BonesSerializer.cs
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
|
namespace UnityExplorer.Serializers
|
||||||
|
{
|
||||||
|
public class BonesSerializer
|
||||||
|
{
|
||||||
|
public static string Serialize(Dictionary<string, List<CachedBonesTransform>> dict)
|
||||||
|
{
|
||||||
|
SerializableDictionary serializableDict = new SerializableDictionary(dict);
|
||||||
|
|
||||||
|
var serializer = new XmlSerializer(typeof(SerializableDictionary));
|
||||||
|
using (var writer = new StringWriter())
|
||||||
|
{
|
||||||
|
serializer.Serialize(writer, serializableDict);
|
||||||
|
return writer.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Dictionary<string, List<CachedBonesTransform>> Deserialize(string xml)
|
||||||
|
{
|
||||||
|
var serializer = new XmlSerializer(typeof(SerializableDictionary));
|
||||||
|
using (var reader = new StringReader(xml))
|
||||||
|
{
|
||||||
|
return ((SerializableDictionary)serializer.Deserialize(reader)).ToDictionary();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Old versions of .net can't natively serialize dictionaries, therefore we make a couple of classes to do it ourselves
|
||||||
|
[XmlRoot("Dictionary")]
|
||||||
|
public class SerializableDictionary
|
||||||
|
{
|
||||||
|
[XmlElement("Item")]
|
||||||
|
public List<DictionaryItem> Items { get; set; } = new List<DictionaryItem>();
|
||||||
|
|
||||||
|
public SerializableDictionary() { }
|
||||||
|
|
||||||
|
public SerializableDictionary(Dictionary<string, List<CachedBonesTransform>> dictionary)
|
||||||
|
{
|
||||||
|
foreach (var kvp in dictionary)
|
||||||
|
{
|
||||||
|
Items.Add(new DictionaryItem { Key = kvp.Key, Value = kvp.Value });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Dictionary<string, List<CachedBonesTransform>> ToDictionary()
|
||||||
|
{
|
||||||
|
var dictionary = new Dictionary<string, List<CachedBonesTransform>>();
|
||||||
|
foreach (var item in Items)
|
||||||
|
{
|
||||||
|
dictionary[item.Key] = item.Value;
|
||||||
|
}
|
||||||
|
return dictionary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class DictionaryItem
|
||||||
|
{
|
||||||
|
[XmlAttribute("Key")]
|
||||||
|
public string Key { get; set; }
|
||||||
|
|
||||||
|
[XmlElement("Value")]
|
||||||
|
public List<CachedBonesTransform> Value { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct CachedBonesTransform
|
||||||
|
{
|
||||||
|
public CachedBonesTransform(Vector3 position, Vector3 angles, Vector3 scale)
|
||||||
|
{
|
||||||
|
this.position = position;
|
||||||
|
this.angles = angles;
|
||||||
|
this.scale = scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
// They cant be read-only because it causes problems with XML serialization in older versions of .NET
|
||||||
|
public Vector3 position { get; set; }
|
||||||
|
public Vector3 angles { get; set; }
|
||||||
|
public Vector3 scale { get; set; }
|
||||||
|
|
||||||
|
public void CopyToTransform(Transform transform){
|
||||||
|
transform.localPosition = position;
|
||||||
|
transform.localEulerAngles = angles;
|
||||||
|
transform.localScale = scale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
50
src/Cinematic/Serializers/CamPathSerializer.cs
Normal file
50
src/Cinematic/Serializers/CamPathSerializer.cs
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
|
namespace UnityExplorer.Serializers
|
||||||
|
{
|
||||||
|
public class CamPathSerializer
|
||||||
|
{
|
||||||
|
public static string Serialize(List<CatmullRom.CatmullRomPoint> points, float time, float alpha, float tension, bool closePath, string sceneName)
|
||||||
|
{
|
||||||
|
CamPathSerializeObject serializeObject = new CamPathSerializeObject(points, time, alpha, tension, closePath, sceneName);
|
||||||
|
var serializer = new XmlSerializer(typeof(CamPathSerializeObject));
|
||||||
|
using (var writer = new StringWriter())
|
||||||
|
{
|
||||||
|
serializer.Serialize(writer, serializeObject);
|
||||||
|
return writer.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CamPathSerializeObject Deserialize(string xml)
|
||||||
|
{
|
||||||
|
var serializer = new XmlSerializer(typeof(CamPathSerializeObject));
|
||||||
|
using (var reader = new StringReader(xml))
|
||||||
|
{
|
||||||
|
return ((CamPathSerializeObject)serializer.Deserialize(reader));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct CamPathSerializeObject
|
||||||
|
{
|
||||||
|
public CamPathSerializeObject(List<CatmullRom.CatmullRomPoint> points, float time, float alpha, float tension, bool closePath, string sceneName)
|
||||||
|
{
|
||||||
|
this.points = points;
|
||||||
|
this.time = time;
|
||||||
|
this.tension = tension;
|
||||||
|
this.alpha = alpha;
|
||||||
|
this.closePath = closePath;
|
||||||
|
this.sceneName = sceneName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly List<CatmullRom.CatmullRomPoint> points;
|
||||||
|
public readonly float time;
|
||||||
|
public readonly float alpha;
|
||||||
|
public readonly float tension;
|
||||||
|
public readonly bool closePath;
|
||||||
|
public readonly string sceneName;
|
||||||
|
}
|
||||||
|
}
|
@ -22,8 +22,13 @@ namespace CinematicUnityExplorer.Cinematic
|
|||||||
public class UnityIGCSConnector
|
public class UnityIGCSConnector
|
||||||
{
|
{
|
||||||
// UnityIGCSConnector.dll definitions.
|
// UnityIGCSConnector.dll definitions.
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
private delegate void MoveCameraCallback(float step_left, float step_up, float fov, int from_start);
|
private delegate void MoveCameraCallback(float step_left, float step_up, float fov, int from_start);
|
||||||
|
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
private delegate void SessionCallback();
|
private delegate void SessionCallback();
|
||||||
|
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
private delegate IntPtr U_IGCS_Initialize(MoveCameraCallback callback, SessionCallback start_cb, SessionCallback end_cb);
|
private delegate IntPtr U_IGCS_Initialize(MoveCameraCallback callback, SessionCallback start_cb, SessionCallback end_cb);
|
||||||
|
|
||||||
// Store the initial position when a session start in IGCSDof.
|
// Store the initial position when a session start in IGCSDof.
|
||||||
@ -118,10 +123,11 @@ namespace CinematicUnityExplorer.Cinematic
|
|||||||
|
|
||||||
public UnityIGCSConnector()
|
public UnityIGCSConnector()
|
||||||
{
|
{
|
||||||
var lib = NativeMethods.LoadLibrary(@"UnityIGCSConnector.dll");
|
var libraryName = IntPtr.Size == 8 ? @"UnityIGCSConnector.dll" : @"UnityIGCSConnector.32.dll";
|
||||||
|
var lib = NativeMethods.LoadLibrary(libraryName);
|
||||||
if (lib == IntPtr.Zero)
|
if (lib == IntPtr.Zero)
|
||||||
{
|
{
|
||||||
ExplorerCore.LogWarning("UnityIGCSConnector.dll was not found so IGCSDof will not be available");
|
ExplorerCore.LogWarning($"{libraryName} was not found so IGCSDof will not be available");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,7 +145,8 @@ namespace CinematicUnityExplorer.Cinematic
|
|||||||
|
|
||||||
CameraStatus = initFunc((MoveCameraCallback)delegates[0], (SessionCallback)delegates[1], (SessionCallback)delegates[2]);
|
CameraStatus = initFunc((MoveCameraCallback)delegates[0], (SessionCallback)delegates[1], (SessionCallback)delegates[2]);
|
||||||
if (CameraStatus == IntPtr.Zero){
|
if (CameraStatus == IntPtr.Zero){
|
||||||
throw new InvalidDataException("IGCSDof returned an invalid pointer which means something went wrong");
|
// This is actually a InvalidDataException, but some games dont allow you to throw that.
|
||||||
|
throw new Exception("IGCSDof returned an invalid pointer which means something went wrong");
|
||||||
}
|
}
|
||||||
|
|
||||||
isValid = true;
|
isValid = true;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
|
using UnityExplorer.UI.Panels;
|
||||||
|
|
||||||
namespace UnityExplorer.Config
|
namespace UnityExplorer.Config
|
||||||
{
|
{
|
||||||
@ -30,8 +31,10 @@ namespace UnityExplorer.Config
|
|||||||
public static ConfigElement<string> Reflection_Signature_Blacklist;
|
public static ConfigElement<string> Reflection_Signature_Blacklist;
|
||||||
public static ConfigElement<bool> Reflection_Hide_NativeInfoPtrs;
|
public static ConfigElement<bool> Reflection_Hide_NativeInfoPtrs;
|
||||||
public static ConfigElement<bool> Auto_Scale_UI;
|
public static ConfigElement<bool> Auto_Scale_UI;
|
||||||
|
public static ConfigElement<bool> Reset_Camera_Transform;
|
||||||
|
public static ConfigElement<float> Arrow_Size;
|
||||||
|
public static ConfigElement<bool> Advanced_Freecam_Selection;
|
||||||
|
|
||||||
public static ConfigElement<bool> Default_Gameplay_Freecam;
|
|
||||||
public static ConfigElement<KeyCode> Pause;
|
public static ConfigElement<KeyCode> Pause;
|
||||||
public static ConfigElement<KeyCode> Frameskip;
|
public static ConfigElement<KeyCode> Frameskip;
|
||||||
public static ConfigElement<KeyCode> Screenshot;
|
public static ConfigElement<KeyCode> Screenshot;
|
||||||
@ -59,6 +62,10 @@ namespace UnityExplorer.Config
|
|||||||
public static ConfigElement<KeyCode> Reset_FOV;
|
public static ConfigElement<KeyCode> Reset_FOV;
|
||||||
public static ConfigElement<KeyCode> Toggle_Animations;
|
public static ConfigElement<KeyCode> Toggle_Animations;
|
||||||
|
|
||||||
|
public static ConfigElement<FreeCamPanel.FreeCameraType> Default_Freecam;
|
||||||
|
public static ConfigElement<string> Custom_Components_To_Disable;
|
||||||
|
public static ConfigElement<string> Preferred_Target_Camera;
|
||||||
|
|
||||||
// internal configs
|
// internal configs
|
||||||
internal static InternalConfigHandler InternalHandler { get; private set; }
|
internal static InternalConfigHandler InternalHandler { get; private set; }
|
||||||
internal static readonly Dictionary<UIManager.Panels, ConfigElement<string>> PanelSaveData = new();
|
internal static readonly Dictionary<UIManager.Panels, ConfigElement<string>> PanelSaveData = new();
|
||||||
@ -164,7 +171,7 @@ namespace UnityExplorer.Config
|
|||||||
"Optional keybind to begin a UI-mode Mouse Inspect.",
|
"Optional keybind to begin a UI-mode Mouse Inspect.",
|
||||||
KeyCode.None);
|
KeyCode.None);
|
||||||
|
|
||||||
CSConsole_Assembly_Blacklist = new("CSharp Console Assembly Blacklist",
|
CSConsole_Assembly_Blacklist = new("CSharp Console Assembly Blacklist",
|
||||||
"Use this to blacklist Assembly names from being referenced by the C# Console. Requires a Reset of the C# Console.\n" +
|
"Use this to blacklist Assembly names from being referenced by the C# Console. Requires a Reset of the C# Console.\n" +
|
||||||
"Separate each Assembly with a semicolon ';'." +
|
"Separate each Assembly with a semicolon ';'." +
|
||||||
"For example, to blacklist Assembly-CSharp, you would add 'Assembly-CSharp;'",
|
"For example, to blacklist Assembly-CSharp, you would add 'Assembly-CSharp;'",
|
||||||
@ -175,7 +182,7 @@ namespace UnityExplorer.Config
|
|||||||
"Seperate signatures with a semicolon ';'.\r\n" +
|
"Seperate signatures with a semicolon ';'.\r\n" +
|
||||||
"For example, to blacklist Camera.main, you would add 'UnityEngine.Camera.main;'",
|
"For example, to blacklist Camera.main, you would add 'UnityEngine.Camera.main;'",
|
||||||
"");
|
"");
|
||||||
|
|
||||||
Reflection_Hide_NativeInfoPtrs = new("Hide NativeMethodInfoPtr_s and NativeFieldInfoPtr_s",
|
Reflection_Hide_NativeInfoPtrs = new("Hide NativeMethodInfoPtr_s and NativeFieldInfoPtr_s",
|
||||||
"Use this to blacklist NativeMethodPtr_s and NativeFieldInfoPtrs_s from the class inspector, mainly to reduce clutter.\r\n" +
|
"Use this to blacklist NativeMethodPtr_s and NativeFieldInfoPtrs_s from the class inspector, mainly to reduce clutter.\r\n" +
|
||||||
"For example, this will hide 'Class.NativeFieldInfoPtr_value' for the field 'Class.value'.",
|
"For example, this will hide 'Class.NativeFieldInfoPtr_value' for the field 'Class.value'.",
|
||||||
@ -185,14 +192,22 @@ namespace UnityExplorer.Config
|
|||||||
"Especially useful when running games in high resolutions and you are having a hard time reading the mods menu (requires restart).",
|
"Especially useful when running games in high resolutions and you are having a hard time reading the mods menu (requires restart).",
|
||||||
true);
|
true);
|
||||||
|
|
||||||
Default_Gameplay_Freecam = new("Default Gameplay Freecam",
|
Reset_Camera_Transform = new("Reset Camera transform on freecam disable",
|
||||||
"Turn this on if you want the default gameplay freecam toggle on the Freecam panel to be on on startup.",
|
"Reset the camera position and rotation between freecam sessions, so the freecam always starts from the gameplay position and rotation.",
|
||||||
|
true);
|
||||||
|
|
||||||
|
Arrow_Size = new("Visualizers arrows size",
|
||||||
|
"Cam Paths nodes and Lights Manager lights visualizers' arrow size (must be positive) (needs visualizer toggled to reflect changes).",
|
||||||
|
1f);
|
||||||
|
|
||||||
|
Advanced_Freecam_Selection = new("Advanced Freecam Selection",
|
||||||
|
"Enables certain advanced settings on the Freecam panel, in case the user can't get the freecam to work properly (requires game reset).",
|
||||||
false);
|
false);
|
||||||
|
|
||||||
Pause = new("Pause",
|
Pause = new("Pause",
|
||||||
"Toggle the pause of the game.",
|
"Toggle the pause of the game.",
|
||||||
KeyCode.PageUp);
|
KeyCode.PageUp);
|
||||||
|
|
||||||
Frameskip = new("Frameskip",
|
Frameskip = new("Frameskip",
|
||||||
"Skip a frame when the game is paused.",
|
"Skip a frame when the game is paused.",
|
||||||
KeyCode.PageDown);
|
KeyCode.PageDown);
|
||||||
@ -246,7 +261,7 @@ namespace UnityExplorer.Config
|
|||||||
Left_1 = new("Left 1",
|
Left_1 = new("Left 1",
|
||||||
"Move the freecam to the left.",
|
"Move the freecam to the left.",
|
||||||
KeyCode.A);
|
KeyCode.A);
|
||||||
|
|
||||||
Left_2 = new("Left 2",
|
Left_2 = new("Left 2",
|
||||||
"Move the freecam to the left, alt key.",
|
"Move the freecam to the left, alt key.",
|
||||||
KeyCode.LeftArrow);
|
KeyCode.LeftArrow);
|
||||||
@ -294,6 +309,19 @@ namespace UnityExplorer.Config
|
|||||||
Toggle_Animations = new("Toggle NPC animations",
|
Toggle_Animations = new("Toggle NPC animations",
|
||||||
"Toggle NPC animations as selected in the Animator panel.",
|
"Toggle NPC animations as selected in the Animator panel.",
|
||||||
KeyCode.Keypad0);
|
KeyCode.Keypad0);
|
||||||
|
|
||||||
|
Default_Freecam = new("Default Freecam mode",
|
||||||
|
"Default type of freecam selected on startup (gets automatically updated with the last type of camera used).",
|
||||||
|
FreeCamPanel.FreeCameraType.New);
|
||||||
|
|
||||||
|
Custom_Components_To_Disable = new("Custom components to disable",
|
||||||
|
"List of custom components to disable when enabling the freecam (gets automatically updated when editing it from the freecam panel).",
|
||||||
|
"");
|
||||||
|
|
||||||
|
Preferred_Target_Camera = new("Preferred Target Camera",
|
||||||
|
"The camera that will be targeted by the freecam methods.\n" +
|
||||||
|
"Only used when Advanced Freecam Selection is enabled.",
|
||||||
|
"\\");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ namespace UnityExplorer
|
|||||||
public static class ExplorerCore
|
public static class ExplorerCore
|
||||||
{
|
{
|
||||||
public const string NAME = "CinematicUnityExplorer";
|
public const string NAME = "CinematicUnityExplorer";
|
||||||
public const string VERSION = "1.2.0";
|
public const string VERSION = "1.3.0";
|
||||||
public const string AUTHOR = "originalnicodr, Sinai, yukieiji";
|
public const string AUTHOR = "originalnicodr, Sinai, yukieiji";
|
||||||
public const string GUID = "com.originalnicodr.cinematicunityexplorer";
|
public const string GUID = "com.originalnicodr.cinematicunityexplorer";
|
||||||
|
|
||||||
@ -205,6 +205,8 @@ namespace UnityExplorer
|
|||||||
foreach (CanvasScaler scaler in canvasScalers)
|
foreach (CanvasScaler scaler in canvasScalers)
|
||||||
{
|
{
|
||||||
scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
|
scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
|
||||||
|
scaler.screenMatchMode = CanvasScaler.ScreenMatchMode.MatchWidthOrHeight;
|
||||||
|
scaler.matchWidthOrHeight = 0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -100,6 +100,9 @@ namespace UnityExplorer
|
|||||||
|
|
||||||
public static void InspectWithFilters(object target, string filterInputField, UnityExplorer.Inspectors.MemberFilter memberFilterFlags = UnityExplorer.Inspectors.MemberFilter.All, bool staticReflection = false, CacheObjectBase parent = null)
|
public static void InspectWithFilters(object target, string filterInputField, UnityExplorer.Inspectors.MemberFilter memberFilterFlags = UnityExplorer.Inspectors.MemberFilter.All, bool staticReflection = false, CacheObjectBase parent = null)
|
||||||
{
|
{
|
||||||
|
if (TryFocusActiveInspector(target))
|
||||||
|
return;
|
||||||
|
|
||||||
ReflectionInspector inspector = CreateInspector<ReflectionInspector>(target, staticReflection, parent);
|
ReflectionInspector inspector = CreateInspector<ReflectionInspector>(target, staticReflection, parent);
|
||||||
inspector.filterInputField.Text = filterInputField;
|
inspector.filterInputField.Text = filterInputField;
|
||||||
//TODO: Update the member flags visually on the inspector.
|
//TODO: Update the member flags visually on the inspector.
|
||||||
|
@ -46,9 +46,10 @@ namespace UnityExplorer.Inspectors
|
|||||||
public override bool CanDragAndResize => false;
|
public override bool CanDragAndResize => false;
|
||||||
private Action<GameObject> inspectorAction = null;
|
private Action<GameObject> inspectorAction = null;
|
||||||
|
|
||||||
internal Text objNameLabel;
|
private Text inspectorLabelTitle;
|
||||||
internal Text objPathLabel;
|
private Text objNameLabel;
|
||||||
internal Text mousePosLabel;
|
private Text objPathLabel;
|
||||||
|
private Text mousePosLabel;
|
||||||
|
|
||||||
public MouseInspector(UIBase owner) : base(owner)
|
public MouseInspector(UIBase owner) : base(owner)
|
||||||
{
|
{
|
||||||
@ -125,6 +126,43 @@ namespace UnityExplorer.Inspectors
|
|||||||
return Inspecting;
|
return Inspecting;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates the title text in the inspector UI, if the inspector title label is assigned.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="title">The new title text to display in the inspector.</param>
|
||||||
|
internal void UpdateInspectorTitle(string title)
|
||||||
|
{
|
||||||
|
// Unity null check - if inspectorLabelTitle is assigned, update its text.
|
||||||
|
if (inspectorLabelTitle)
|
||||||
|
{
|
||||||
|
inspectorLabelTitle.text = title;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Updates the object name label in the inspector UI, if the label is assigned.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name">The new object name to display.</param>
|
||||||
|
internal void UpdateObjectNameLabel(string name)
|
||||||
|
{
|
||||||
|
// Unity null check - if objNameLabel is assigned, update its text.
|
||||||
|
if (objNameLabel)
|
||||||
|
{
|
||||||
|
objNameLabel.text = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Updates the object path label in the inspector UI, if the label is assigned.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path">The new object path to display.</param>
|
||||||
|
internal void UpdateObjectPathLabel(string path)
|
||||||
|
{
|
||||||
|
// Unity null check - if objPathLabel is assigned, update its text.
|
||||||
|
if (objPathLabel)
|
||||||
|
{
|
||||||
|
objPathLabel.text = path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void UpdateInspect()
|
public void UpdateInspect()
|
||||||
{
|
{
|
||||||
if (IInputManager.GetKeyDown(KeyCode.Escape))
|
if (IInputManager.GetKeyDown(KeyCode.Escape))
|
||||||
@ -156,7 +194,7 @@ namespace UnityExplorer.Inspectors
|
|||||||
lastMousePos = mousePos;
|
lastMousePos = mousePos;
|
||||||
|
|
||||||
// use the raw mouse pos for the label
|
// use the raw mouse pos for the label
|
||||||
mousePosLabel.text = $"<color=grey>Mouse Position:</color> {mousePos.ToString()}";
|
mousePosLabel.text = $"<color=grey>Mouse Position:</color> {mousePos.x}, {mousePos.y}";
|
||||||
|
|
||||||
// constrain the mouse pos we use within certain bounds
|
// constrain the mouse pos we use within certain bounds
|
||||||
if (mousePos.x < 350)
|
if (mousePos.x < 350)
|
||||||
@ -196,11 +234,11 @@ namespace UnityExplorer.Inspectors
|
|||||||
|
|
||||||
// Title text
|
// Title text
|
||||||
|
|
||||||
Text title = UIFactory.CreateLabel(inspectContent,
|
inspectorLabelTitle = UIFactory.CreateLabel(inspectContent,
|
||||||
"InspectLabel",
|
"InspectLabel",
|
||||||
"<b>Mouse Inspector</b> (press <b>ESC</b> to cancel)",
|
"",
|
||||||
TextAnchor.MiddleCenter);
|
TextAnchor.MiddleCenter);
|
||||||
UIFactory.SetLayoutElement(title.gameObject, flexibleWidth: 9999);
|
UIFactory.SetLayoutElement(inspectorLabelTitle.gameObject, flexibleWidth: 9999);
|
||||||
|
|
||||||
mousePosLabel = UIFactory.CreateLabel(inspectContent, "MousePosLabel", "Mouse Position:", TextAnchor.MiddleCenter);
|
mousePosLabel = UIFactory.CreateLabel(inspectContent, "MousePosLabel", "Mouse Position:", TextAnchor.MiddleCenter);
|
||||||
|
|
||||||
|
@ -17,10 +17,13 @@ namespace UnityExplorer.Inspectors.MouseInspectors
|
|||||||
private static readonly List<CanvasGroup> wasDisabledCanvasGroups = new();
|
private static readonly List<CanvasGroup> wasDisabledCanvasGroups = new();
|
||||||
private static readonly List<GameObject> objectsAddedCastersTo = new();
|
private static readonly List<GameObject> objectsAddedCastersTo = new();
|
||||||
|
|
||||||
|
private const string DEFAULT_INSPECTOR_TITLE = "<b>UI Inspector</b> (press <b>ESC</b> to cancel)";
|
||||||
|
|
||||||
public override void OnBeginMouseInspect()
|
public override void OnBeginMouseInspect()
|
||||||
{
|
{
|
||||||
SetupUIRaycast();
|
SetupUIRaycast();
|
||||||
MouseInspector.Instance.objPathLabel.text = "";
|
MouseInspector.Instance.UpdateInspectorTitle(DEFAULT_INSPECTOR_TITLE);
|
||||||
|
MouseInspector.Instance.UpdateObjectPathLabel("");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void ClearHitData()
|
public override void ClearHitData()
|
||||||
@ -71,9 +74,9 @@ namespace UnityExplorer.Inspectors.MouseInspectors
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (currentHitObjects.Any())
|
if (currentHitObjects.Any())
|
||||||
MouseInspector.Instance.objNameLabel.text = $"Click to view UI Objects under mouse: {currentHitObjects.Count}";
|
MouseInspector.Instance.UpdateObjectNameLabel($"Click to view UI Objects under mouse: {currentHitObjects.Count}");
|
||||||
else
|
else
|
||||||
MouseInspector.Instance.objNameLabel.text = $"No UI objects under mouse.";
|
MouseInspector.Instance.UpdateObjectNameLabel( $"No UI objects under mouse.");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void SetupUIRaycast()
|
private static void SetupUIRaycast()
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
namespace UnityExplorer.Inspectors.MouseInspectors
|
using UnityExplorer.UI.Panels;
|
||||||
|
|
||||||
|
namespace UnityExplorer.Inspectors.MouseInspectors
|
||||||
{
|
{
|
||||||
public class WorldInspector : MouseInspectorBase
|
public class WorldInspector : MouseInspectorBase
|
||||||
{
|
{
|
||||||
@ -7,15 +9,26 @@
|
|||||||
|
|
||||||
public override void OnBeginMouseInspect()
|
public override void OnBeginMouseInspect()
|
||||||
{
|
{
|
||||||
MainCamera = Camera.main;
|
|
||||||
|
|
||||||
if (!MainCamera)
|
if (!EnsureMainCamera())
|
||||||
{
|
{
|
||||||
ExplorerCore.LogWarning("No MainCamera found! Cannot inspect world!");
|
ExplorerCore.LogWarning("No MainCamera found! Cannot inspect world!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Assigns it as the MainCamera and updates the inspector title.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="cam">The camera to assign.</param>
|
||||||
|
private static void AssignCamAndUpdateTitle(Camera cam)
|
||||||
|
{
|
||||||
|
MainCamera = cam;
|
||||||
|
MouseInspector.Instance.UpdateInspectorTitle(
|
||||||
|
$"<b>World Inspector ({MainCamera.name})</b> (press <b>ESC</b> to cancel)"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public override void ClearHitData()
|
public override void ClearHitData()
|
||||||
{
|
{
|
||||||
lastHitObject = null;
|
lastHitObject = null;
|
||||||
@ -26,11 +39,52 @@
|
|||||||
inspectorAction(lastHitObject);
|
inspectorAction(lastHitObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Attempts to ensure that MainCamera is assigned. If not then attempts to find it.
|
||||||
|
/// If no cameras are available, logs a warning and returns null.
|
||||||
|
/// </summary>
|
||||||
|
private static Camera EnsureMainCamera()
|
||||||
|
{
|
||||||
|
if (MainCamera){
|
||||||
|
// We still call this in case the last title was from the UIInspector
|
||||||
|
AssignCamAndUpdateTitle(MainCamera);
|
||||||
|
return MainCamera;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Camera.main){
|
||||||
|
AssignCamAndUpdateTitle(Camera.main);
|
||||||
|
return MainCamera;
|
||||||
|
}
|
||||||
|
|
||||||
|
ExplorerCore.LogWarning("No Camera.main found, trying to find a camera named 'Main Camera' or 'MainCamera'...");
|
||||||
|
Camera namedCam = Camera.allCameras.FirstOrDefault(c => c.name is "Main Camera" or "MainCamera");
|
||||||
|
if (namedCam) {
|
||||||
|
AssignCamAndUpdateTitle(namedCam);
|
||||||
|
return MainCamera;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FreeCamPanel.inFreeCamMode && FreeCamPanel.GetFreecam()){
|
||||||
|
AssignCamAndUpdateTitle(FreeCamPanel.GetFreecam());
|
||||||
|
return MainCamera;
|
||||||
|
}
|
||||||
|
|
||||||
|
ExplorerCore.LogWarning("No camera named found, using the first camera created...");
|
||||||
|
var fallbackCam = Camera.allCameras.FirstOrDefault();
|
||||||
|
if (fallbackCam) {
|
||||||
|
AssignCamAndUpdateTitle(fallbackCam);
|
||||||
|
return MainCamera;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we reach here, no cameras were found at all.
|
||||||
|
ExplorerCore.LogWarning("No valid cameras found!");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public override void UpdateMouseInspect(Vector2 mousePos)
|
public override void UpdateMouseInspect(Vector2 mousePos)
|
||||||
{
|
{
|
||||||
if (!MainCamera)
|
// Attempt to ensure camera each time UpdateMouseInspect is called
|
||||||
MainCamera = Camera.main;
|
// in case something changed or wasn't set initially.
|
||||||
if (!MainCamera)
|
if (!EnsureMainCamera())
|
||||||
{
|
{
|
||||||
ExplorerCore.LogWarning("No Main Camera was found, unable to inspect world!");
|
ExplorerCore.LogWarning("No Main Camera was found, unable to inspect world!");
|
||||||
MouseInspector.Instance.StopInspect();
|
MouseInspector.Instance.StopInspect();
|
||||||
@ -51,8 +105,8 @@
|
|||||||
if (obj != lastHitObject)
|
if (obj != lastHitObject)
|
||||||
{
|
{
|
||||||
lastHitObject = obj;
|
lastHitObject = obj;
|
||||||
MouseInspector.Instance.objNameLabel.text = $"<b>Click to Inspect:</b> <color=cyan>{obj.name}</color>";
|
MouseInspector.Instance.UpdateObjectNameLabel($"<b>Click to Inspect:</b> <color=cyan>{obj.name}</color>");
|
||||||
MouseInspector.Instance.objPathLabel.text = $"Path: {obj.transform.GetTransformPath(true)}";
|
MouseInspector.Instance.UpdateObjectPathLabel($"Path: {obj.transform.GetTransformPath(true)}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ using System.Text;
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityExplorer.Config;
|
using UnityExplorer.Config;
|
||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
|
using UnityExplorer.UI.Panels;
|
||||||
using UniverseLib;
|
using UniverseLib;
|
||||||
|
|
||||||
namespace UnityExplorer.Loader.Standalone
|
namespace UnityExplorer.Loader.Standalone
|
||||||
@ -26,6 +27,13 @@ namespace UnityExplorer.Loader.Standalone
|
|||||||
public bool Force_Unlock_Mouse = true;
|
public bool Force_Unlock_Mouse = true;
|
||||||
public KeyCode Force_Unlock_Toggle;
|
public KeyCode Force_Unlock_Toggle;
|
||||||
public bool Disable_EventSystem_Override;
|
public bool Disable_EventSystem_Override;
|
||||||
|
public bool Auto_Scale_UI;
|
||||||
|
public bool Reset_Camera_Transform;
|
||||||
|
public FreeCamPanel.FreeCameraType Default_Freecam;
|
||||||
|
public string Custom_Components_To_Disable;
|
||||||
|
public string Preferred_Target_Camera;
|
||||||
|
public float Arrow_Size = 1f;
|
||||||
|
public bool Advanced_Freecam_Selection;
|
||||||
|
|
||||||
public KeyCode Pause;
|
public KeyCode Pause;
|
||||||
public KeyCode Frameskip;
|
public KeyCode Frameskip;
|
||||||
@ -80,6 +88,14 @@ namespace UnityExplorer.Loader.Standalone
|
|||||||
ConfigManager.Force_Unlock_Mouse.Value = this.Force_Unlock_Mouse;
|
ConfigManager.Force_Unlock_Mouse.Value = this.Force_Unlock_Mouse;
|
||||||
ConfigManager.Force_Unlock_Toggle.Value = this.Force_Unlock_Toggle;
|
ConfigManager.Force_Unlock_Toggle.Value = this.Force_Unlock_Toggle;
|
||||||
ConfigManager.Disable_EventSystem_Override.Value = this.Disable_EventSystem_Override;
|
ConfigManager.Disable_EventSystem_Override.Value = this.Disable_EventSystem_Override;
|
||||||
|
ConfigManager.Auto_Scale_UI.Value = this.Auto_Scale_UI;
|
||||||
|
ConfigManager.Reset_Camera_Transform.Value = this.Reset_Camera_Transform;
|
||||||
|
ConfigManager.Default_Freecam.Value = this.Default_Freecam;
|
||||||
|
ConfigManager.Custom_Components_To_Disable.Value = this.Custom_Components_To_Disable;
|
||||||
|
ConfigManager.Preferred_Target_Camera.Value = this.Preferred_Target_Camera;
|
||||||
|
|
||||||
|
ConfigManager.Arrow_Size.Value = this.Arrow_Size;
|
||||||
|
ConfigManager.Advanced_Freecam_Selection.Value = this.Advanced_Freecam_Selection;
|
||||||
|
|
||||||
ConfigManager.Pause.Value = this.Pause;
|
ConfigManager.Pause.Value = this.Pause;
|
||||||
ConfigManager.Frameskip.Value = this.Frameskip;
|
ConfigManager.Frameskip.Value = this.Frameskip;
|
||||||
|
@ -163,7 +163,7 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
if (!string.IsNullOrEmpty(input))
|
if (!string.IsNullOrEmpty(input))
|
||||||
nameFilter = input;
|
nameFilter = input;
|
||||||
|
|
||||||
BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static;
|
BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.FlattenHierarchy;
|
||||||
|
|
||||||
foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies())
|
foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies())
|
||||||
{
|
{
|
||||||
@ -181,7 +181,7 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return instances;
|
return instances.Distinct().ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
public override bool NavButtonWanted => true;
|
public override bool NavButtonWanted => true;
|
||||||
public override bool ShouldSaveActiveState => true;
|
public override bool ShouldSaveActiveState => true;
|
||||||
|
|
||||||
Toggle masterAnimatorToggle;
|
AnimatorPausePlayButton masterAnimatorPlayer;
|
||||||
Toggle masterMeshToggle;
|
Toggle masterMeshToggle;
|
||||||
|
|
||||||
private static ScrollPool<AnimatorCell> animatorScrollPool;
|
private static ScrollPool<AnimatorCell> animatorScrollPool;
|
||||||
@ -52,7 +52,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
|
|
||||||
private void FindAllAnimators(){
|
private void FindAllAnimators(){
|
||||||
// Enable all animators on refresh
|
// Enable all animators on refresh
|
||||||
masterAnimatorToggle.isOn = true; // Will also trigger "MasterToggleAnimators(true)"
|
masterAnimatorPlayer.isOn = true; // Will also trigger "MasterToggleAnimators(true)"
|
||||||
|
|
||||||
Type searchType = ReflectionUtility.GetTypeByName("UnityEngine.Animator");
|
Type searchType = ReflectionUtility.GetTypeByName("UnityEngine.Animator");
|
||||||
searchType = searchType is Type type ? type : searchType.GetActualType();
|
searchType = searchType is Type type ? type : searchType.GetActualType();
|
||||||
@ -76,6 +76,10 @@ namespace UnityExplorer.UI.Panels
|
|||||||
animators[i].animations.Add(animationClip);
|
animators[i].animations.Add(animationClip);
|
||||||
}
|
}
|
||||||
newAnimators[newAnimatorsIndex] = animators[i];
|
newAnimators[newAnimatorsIndex] = animators[i];
|
||||||
|
|
||||||
|
// Reset meshes
|
||||||
|
newAnimators[newAnimatorsIndex].SearchMeshes();
|
||||||
|
newAnimators[newAnimatorsIndex].MaybeResetBonesPanel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -92,7 +96,9 @@ namespace UnityExplorer.UI.Panels
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void MasterToggleAnimators(bool enable){
|
public void MasterToggleAnimators(){
|
||||||
|
bool enable = masterAnimatorPlayer.isOn;
|
||||||
|
|
||||||
// Load animators for the first time if there are not any
|
// Load animators for the first time if there are not any
|
||||||
if (animators.Count == 0) FindAllAnimators();
|
if (animators.Count == 0) FindAllAnimators();
|
||||||
|
|
||||||
@ -120,7 +126,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void HotkeyToggleAnimators(){
|
public void HotkeyToggleAnimators(){
|
||||||
masterAnimatorToggle.isOn = !masterAnimatorToggle.isOn;
|
masterAnimatorPlayer.isOn = !masterAnimatorPlayer.isOn;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ~~~~~~~~ UI construction / callbacks ~~~~~~~~
|
// ~~~~~~~~ UI construction / callbacks ~~~~~~~~
|
||||||
@ -139,10 +145,11 @@ namespace UnityExplorer.UI.Panels
|
|||||||
masterMeshToggle.onValueChanged.AddListener(value => MasterToggleMeshes(value));
|
masterMeshToggle.onValueChanged.AddListener(value => MasterToggleMeshes(value));
|
||||||
masterMeshText.text = "Master Mesh Toggler";
|
masterMeshText.text = "Master Mesh Toggler";
|
||||||
|
|
||||||
GameObject animatorObj = UIFactory.CreateToggle(firstGroup, "Master Animation Toggle", out masterAnimatorToggle, out Text masterAnimatorText);
|
masterAnimatorPlayer = new AnimatorPausePlayButton(firstGroup);
|
||||||
UIFactory.SetLayoutElement(animatorObj, minHeight: 25);
|
masterAnimatorPlayer.OnClick += MasterToggleAnimators;
|
||||||
masterAnimatorToggle.onValueChanged.AddListener(value => MasterToggleAnimators(value));
|
|
||||||
masterAnimatorText.text = "Master Animator Toggler";
|
Text masterAnimatorPlayerText = UIFactory.CreateLabel(firstGroup, "MasterAnimatorToggleLabel", "Master Animator Toggler", TextAnchor.MiddleRight);
|
||||||
|
UIFactory.SetLayoutElement(masterAnimatorPlayerText.gameObject, flexibleWidth: 0, minHeight: 25);
|
||||||
|
|
||||||
GameObject headerSpace2 = UIFactory.CreateUIObject("HeaderSpace2", firstGroup);
|
GameObject headerSpace2 = UIFactory.CreateUIObject("HeaderSpace2", firstGroup);
|
||||||
UIFactory.SetLayoutElement(headerSpace2, minWidth: 10, flexibleWidth: 0);
|
UIFactory.SetLayoutElement(headerSpace2, minWidth: 10, flexibleWidth: 0);
|
||||||
@ -193,4 +200,71 @@ namespace UnityExplorer.UI.Panels
|
|||||||
|
|
||||||
public void OnCellBorrowed(AnimatorCell cell) { }
|
public void OnCellBorrowed(AnimatorCell cell) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ButtonRef wrapper to act as a toggle with clearer UI
|
||||||
|
public class AnimatorPausePlayButton
|
||||||
|
{
|
||||||
|
private ButtonRef innerButton;
|
||||||
|
public Button Component => innerButton.Component;
|
||||||
|
public GameObject GameObject => innerButton.GameObject;
|
||||||
|
private bool isPlaying;
|
||||||
|
|
||||||
|
public AnimatorPausePlayButton(GameObject ui, bool state = true)
|
||||||
|
{
|
||||||
|
innerButton = UIFactory.CreateButton(ui, "InnerAnimatorPlayButton", "");
|
||||||
|
UIFactory.SetLayoutElement(innerButton.GameObject, minHeight: 25, minWidth: 25);
|
||||||
|
innerButton.OnClick += SetToggleButtonState;
|
||||||
|
isPlaying = state;
|
||||||
|
UpdateButton();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnPlay(){
|
||||||
|
innerButton.ButtonText.text = "❚❚";
|
||||||
|
RuntimeHelper.SetColorBlockAuto(innerButton.Component, new(0.4f, 0.2f, 0.2f));
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnPause(){
|
||||||
|
innerButton.ButtonText.text = "►";
|
||||||
|
RuntimeHelper.SetColorBlockAuto(innerButton.Component, new(0.2f, 0.4f, 0.2f));
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateButton(){
|
||||||
|
if (isPlaying)
|
||||||
|
{
|
||||||
|
OnPlay();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
OnPause();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetToggleButtonState()
|
||||||
|
{
|
||||||
|
isPlaying = !isPlaying;
|
||||||
|
UpdateButton();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool isOn
|
||||||
|
{
|
||||||
|
get {
|
||||||
|
return isPlaying;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
if (value != isPlaying){
|
||||||
|
SetToggleButtonState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action OnClick
|
||||||
|
{
|
||||||
|
get {
|
||||||
|
return innerButton.OnClick;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
innerButton.OnClick = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
using UniverseLib.UI;
|
using UnityExplorer.Serializers;
|
||||||
|
using UniverseLib.UI;
|
||||||
|
using UniverseLib.UI.Models;
|
||||||
using UniverseLib.UI.Panels;
|
using UniverseLib.UI.Panels;
|
||||||
using UniverseLib.UI.Widgets.ScrollView;
|
using UniverseLib.UI.Widgets.ScrollView;
|
||||||
|
|
||||||
@ -8,25 +10,75 @@ namespace UnityExplorer.UI.Panels
|
|||||||
{
|
{
|
||||||
public override string Name => $"Bones Manager";
|
public override string Name => $"Bones Manager";
|
||||||
public override int MinWidth => 1000;
|
public override int MinWidth => 1000;
|
||||||
public override int MinHeight => 400;
|
public override int MinHeight => 800;
|
||||||
public override Vector2 DefaultAnchorMin => Vector2.zero;
|
public override Vector2 DefaultAnchorMin => Vector2.zero;
|
||||||
public override Vector2 DefaultAnchorMax => Vector2.zero;
|
public override Vector2 DefaultAnchorMax => Vector2.zero;
|
||||||
public Toggle turnOffAnimatorToggle;
|
public Toggle turnOffAnimatorToggle;
|
||||||
|
|
||||||
private IAnimator animator;
|
private IAnimator animator;
|
||||||
private Text skeletonName;
|
private Text skeletonName;
|
||||||
|
private InputFieldRef saveLoadinputField;
|
||||||
|
private InputFieldRef searchBoneNameInput;
|
||||||
private List<Transform> bones = new List<Transform>();
|
private List<Transform> bones = new List<Transform>();
|
||||||
private Dictionary<string, CachedBonesTransform> bonesOriginalState = new();
|
private Dictionary<string, CachedBonesTransform> bonesOriginalState = new();
|
||||||
|
|
||||||
private ScrollPool<BonesCell> boneScrollPool;
|
public List<BoneTree> boneTrees = new();
|
||||||
public int ItemCount => bones.Count;
|
public ScrollPool<BonesCell> boneScrollPool;
|
||||||
|
public int ItemCount => boneTrees.Count;
|
||||||
private bool DoneScrollPoolInit;
|
private bool DoneScrollPoolInit;
|
||||||
|
|
||||||
public BonesManager(UIBase owner, List<Transform> bones, IAnimator animator) : base(owner)
|
public BonesManager(UIBase owner, List<Transform> bones, IAnimator animator) : base(owner)
|
||||||
{
|
{
|
||||||
this.bones = bones;
|
this.bones = bones;
|
||||||
this.animator = animator;
|
this.animator = animator;
|
||||||
skeletonName.text = $"Skeleton: {animator?.name}";
|
skeletonName.text = $"Skeleton: {animator?.name} ";
|
||||||
|
BuildBoneTrees();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RefreshBones(List<Transform> bones) {
|
||||||
|
this.bones = bones;
|
||||||
|
boneTrees.Clear();
|
||||||
|
BuildBoneTrees();
|
||||||
|
boneScrollPool.Refresh(true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BuildBoneTrees(){
|
||||||
|
BoneTree root = new BoneTree(animator.wrappedObject.gameObject, bones);
|
||||||
|
if (root.obj != null){
|
||||||
|
root.AssignLevels();
|
||||||
|
boneTrees.Add(root);
|
||||||
|
} else {
|
||||||
|
foreach(BoneTree childTree in root.childTrees){
|
||||||
|
childTree.AssignLevels();
|
||||||
|
boneTrees.Add(childTree);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CollapseBoneTrees(){
|
||||||
|
boneTrees.Clear();
|
||||||
|
BuildBoneTrees();
|
||||||
|
boneScrollPool.Refresh(true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ExpandBoneTrees(){
|
||||||
|
// We collapse before expanding to start from scratch and dont duplicate nodes
|
||||||
|
CollapseBoneTrees();
|
||||||
|
|
||||||
|
List<BoneTree> newBoneTrees = new();
|
||||||
|
|
||||||
|
foreach(BoneTree childTree in boneTrees){
|
||||||
|
newBoneTrees.AddRange(childTree.flatten());
|
||||||
|
}
|
||||||
|
|
||||||
|
boneTrees = newBoneTrees;
|
||||||
|
boneScrollPool.Refresh(true, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SearchBones(){
|
||||||
|
ExpandBoneTrees();
|
||||||
|
boneTrees = boneTrees.Where(tree => tree.obj.name.IndexOf(searchBoneNameInput.Component.text, 0, StringComparison.OrdinalIgnoreCase) >= 0).ToList();
|
||||||
|
boneScrollPool.Refresh(true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void SetActive(bool active)
|
public override void SetActive(bool active)
|
||||||
@ -43,15 +95,59 @@ namespace UnityExplorer.UI.Panels
|
|||||||
|
|
||||||
protected override void ConstructPanelContent()
|
protected override void ConstructPanelContent()
|
||||||
{
|
{
|
||||||
skeletonName = UIFactory.CreateLabel(ContentRoot, $"SkeletonName", "");
|
GameObject bonesPanelHeader = UIFactory.CreateHorizontalGroup(ContentRoot, "BonesPanelHeader", false, false, true, true, 3,
|
||||||
UIFactory.SetLayoutElement(skeletonName.gameObject, minWidth: 100, minHeight: 25);
|
default, new Color(1, 1, 1, 0), TextAnchor.MiddleLeft);
|
||||||
|
UIFactory.SetLayoutElement(bonesPanelHeader, minHeight: 25, flexibleWidth: 9999);
|
||||||
|
|
||||||
|
skeletonName = UIFactory.CreateLabel(bonesPanelHeader, $"SkeletonName", "");
|
||||||
|
UIFactory.SetLayoutElement(skeletonName.gameObject, minWidth: 100, minHeight: 25, flexibleWidth: 9999);
|
||||||
skeletonName.fontSize = 16;
|
skeletonName.fontSize = 16;
|
||||||
|
|
||||||
GameObject turnOffAnimatorToggleObj = UIFactory.CreateToggle(ContentRoot, "Animator toggle", out turnOffAnimatorToggle, out Text turnOffAnimatorToggleText);
|
saveLoadinputField = UIFactory.CreateInputField(bonesPanelHeader, $"FileNameInput", "File name");
|
||||||
|
UIFactory.SetLayoutElement(saveLoadinputField.GameObject, minWidth: 380, minHeight: 25);
|
||||||
|
|
||||||
|
GameObject spacer1 = UIFactory.CreateUIObject("Spacer", bonesPanelHeader);
|
||||||
|
LayoutElement spaceLayout1 = UIFactory.SetLayoutElement(spacer1, minWidth: 20, flexibleWidth: 0);
|
||||||
|
|
||||||
|
ButtonRef savePose = UIFactory.CreateButton(bonesPanelHeader, "SavePoseButton", "Save pose");
|
||||||
|
UIFactory.SetLayoutElement(savePose.GameObject, minWidth: 100, minHeight: 25);
|
||||||
|
savePose.OnClick += SaveBones;
|
||||||
|
|
||||||
|
ButtonRef loadPose = UIFactory.CreateButton(bonesPanelHeader, "LoadPoseButton", "Load pose");
|
||||||
|
UIFactory.SetLayoutElement(loadPose.GameObject, minWidth: 100, minHeight: 25);
|
||||||
|
loadPose.OnClick += LoadBones;
|
||||||
|
|
||||||
|
GameObject header = UIFactory.CreateHorizontalGroup(ContentRoot, "BonesPanelHeader", false, false, true, true, 3,
|
||||||
|
default, new Color(1, 1, 1, 0), TextAnchor.MiddleLeft);
|
||||||
|
UIFactory.SetLayoutElement(header, minHeight: 35, flexibleWidth: 9999);
|
||||||
|
|
||||||
|
GameObject turnOffAnimatorToggleObj = UIFactory.CreateToggle(header, "Animator toggle", out turnOffAnimatorToggle, out Text turnOffAnimatorToggleText);
|
||||||
UIFactory.SetLayoutElement(turnOffAnimatorToggleObj, minHeight: 25, flexibleWidth: 9999);
|
UIFactory.SetLayoutElement(turnOffAnimatorToggleObj, minHeight: 25, flexibleWidth: 9999);
|
||||||
turnOffAnimatorToggle.onValueChanged.AddListener(OnTurnOffAnimatorToggle);
|
turnOffAnimatorToggle.onValueChanged.AddListener(OnTurnOffAnimatorToggle);
|
||||||
turnOffAnimatorToggleText.text = "Toggle animator (needs to be off to move bones)";
|
turnOffAnimatorToggleText.text = "Toggle animator (needs to be off to move bones)";
|
||||||
|
|
||||||
|
searchBoneNameInput = UIFactory.CreateInputField(header, $"SearchBoneInput", "Search bone name");
|
||||||
|
UIFactory.SetLayoutElement(searchBoneNameInput.GameObject, minWidth: 225, minHeight: 25);
|
||||||
|
|
||||||
|
ButtonRef searchButton = UIFactory.CreateButton(header, "SearchButton", "Search");
|
||||||
|
UIFactory.SetLayoutElement(searchButton.GameObject, minWidth: 75, minHeight: 25);
|
||||||
|
searchButton.OnClick += SearchBones;
|
||||||
|
|
||||||
|
ButtonRef resetButton = UIFactory.CreateButton(header, "ResetSearchButton", "Reset");
|
||||||
|
UIFactory.SetLayoutElement(resetButton.GameObject, minWidth: 75, minHeight: 25);
|
||||||
|
resetButton.OnClick += () => { CollapseBoneTrees(); searchBoneNameInput.Component.text = ""; };
|
||||||
|
|
||||||
|
GameObject spacer2 = UIFactory.CreateUIObject("Spacer", header);
|
||||||
|
LayoutElement spaceLayout2 = UIFactory.SetLayoutElement(spacer2, minWidth: 20, flexibleWidth: 0);
|
||||||
|
|
||||||
|
ButtonRef collapseAllButton = UIFactory.CreateButton(header, "CollapseAllButton", "Collapse all");
|
||||||
|
UIFactory.SetLayoutElement(collapseAllButton.GameObject, minWidth: 100, minHeight: 25);
|
||||||
|
collapseAllButton.OnClick += CollapseBoneTrees;
|
||||||
|
|
||||||
|
ButtonRef expandAllButton = UIFactory.CreateButton(header, "ExpandAllButton", "Expand all");
|
||||||
|
UIFactory.SetLayoutElement(expandAllButton.GameObject, minWidth: 100, minHeight: 25);
|
||||||
|
expandAllButton.OnClick += ExpandBoneTrees;
|
||||||
|
|
||||||
boneScrollPool = UIFactory.CreateScrollPool<BonesCell>(ContentRoot, "BonesList", out GameObject scrollObj,
|
boneScrollPool = UIFactory.CreateScrollPool<BonesCell>(ContentRoot, "BonesList", out GameObject scrollObj,
|
||||||
out GameObject scrollContent, new Color(0.06f, 0.06f, 0.06f));
|
out GameObject scrollContent, new Color(0.06f, 0.06f, 0.06f));
|
||||||
UIFactory.SetLayoutElement(scrollObj, flexibleWidth: 9999, flexibleHeight: 9999);
|
UIFactory.SetLayoutElement(scrollObj, flexibleWidth: 9999, flexibleHeight: 9999);
|
||||||
@ -63,10 +159,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
// Restore meshes manually in case some are not part of a skeleton and won't get restored automatically.
|
// Restore meshes manually in case some are not part of a skeleton and won't get restored automatically.
|
||||||
// Besides, this restores the scale, which the animator doesn't.
|
// Besides, this restores the scale, which the animator doesn't.
|
||||||
foreach (Transform bone in bones){
|
foreach (Transform bone in bones){
|
||||||
CachedBonesTransform CachedBonesTransform = bonesOriginalState[bone.name];
|
bonesOriginalState[bone.name].CopyToTransform(bone);
|
||||||
bone.localPosition = CachedBonesTransform.position;
|
|
||||||
bone.localEulerAngles = CachedBonesTransform.angles;
|
|
||||||
bone.localScale = CachedBonesTransform.scale;
|
|
||||||
// We assume these were on before. If not we should save its state beforehand.
|
// We assume these were on before. If not we should save its state beforehand.
|
||||||
bone.gameObject.SetActive(true);
|
bone.gameObject.SetActive(true);
|
||||||
}
|
}
|
||||||
@ -83,25 +176,97 @@ namespace UnityExplorer.UI.Panels
|
|||||||
{
|
{
|
||||||
foreach (Transform bone in bones){
|
foreach (Transform bone in bones){
|
||||||
if (bone.name == boneName){
|
if (bone.name == boneName){
|
||||||
CachedBonesTransform CachedBonesTransform = bonesOriginalState[boneName];
|
bonesOriginalState[boneName].CopyToTransform(bone);
|
||||||
bone.localPosition = CachedBonesTransform.position;
|
|
||||||
bone.localEulerAngles = CachedBonesTransform.angles;
|
|
||||||
bone.localScale = CachedBonesTransform.scale;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void SaveBones(){
|
||||||
|
Dictionary<string, List<CachedBonesTransform>> bonesTreeCache = new();
|
||||||
|
// Get the list of bones based on the hierarchy order so we can deserialize it in the same order, instead of just using the bones list.
|
||||||
|
List<BoneTree> allBoneTrees = new();
|
||||||
|
foreach(BoneTree tree in boneTrees) {
|
||||||
|
allBoneTrees.AddRange(tree.flatten());
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach(BoneTree tree in allBoneTrees){
|
||||||
|
if (!bonesTreeCache.ContainsKey(tree.obj.name)){
|
||||||
|
bonesTreeCache.Add(tree.obj.name, new List<CachedBonesTransform>());
|
||||||
|
}
|
||||||
|
CachedBonesTransform entry = new CachedBonesTransform(tree.obj.transform.localPosition, tree.obj.transform.localEulerAngles, tree.obj.transform.localScale);
|
||||||
|
bonesTreeCache[tree.obj.name].Add(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
string filename = saveLoadinputField.Component.text;
|
||||||
|
if (filename.EndsWith(".cuepose") || filename.EndsWith(".CUEPOSE")) filename = filename.Substring(filename.Length-7);
|
||||||
|
if (string.IsNullOrEmpty(filename)) filename = $"{animator?.name}-{DateTime.Now.ToString("yyyy-M-d HH-mm-ss")}";
|
||||||
|
string posesPath = Path.Combine(ExplorerCore.ExplorerFolder, "Poses");
|
||||||
|
System.IO.Directory.CreateDirectory(posesPath);
|
||||||
|
|
||||||
|
// Serialize
|
||||||
|
string serializedData = BonesSerializer.Serialize(bonesTreeCache);
|
||||||
|
File.WriteAllText($"{posesPath}\\{filename}.cuepose", serializedData);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadBones(){
|
||||||
|
string filename = saveLoadinputField.Component.text;
|
||||||
|
if (filename.EndsWith(".cuepose") || filename.EndsWith(".CUEPOSE")) filename = filename.Substring(filename.Length-7);
|
||||||
|
if (string.IsNullOrEmpty(filename)){
|
||||||
|
ExplorerCore.LogWarning("Empty file name. Please write the name of the file to load.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string posesPath = Path.Combine(ExplorerCore.ExplorerFolder, "Poses");
|
||||||
|
string xml;
|
||||||
|
try {
|
||||||
|
xml = File.ReadAllText($"{posesPath}\\{filename}.cuepose");
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
ExplorerCore.LogWarning(ex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Dictionary<string, List<CachedBonesTransform>> deserializedDict;
|
||||||
|
try {
|
||||||
|
deserializedDict = BonesSerializer.Deserialize(xml);
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
ExplorerCore.LogWarning(ex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
turnOffAnimatorToggle.isOn = false;
|
||||||
|
foreach(Transform boneTransform in bones) {
|
||||||
|
List<CachedBonesTransform> cachedTransformList;
|
||||||
|
deserializedDict.TryGetValue(boneTransform.name, out cachedTransformList);
|
||||||
|
if (cachedTransformList != null && cachedTransformList.Count > 0){
|
||||||
|
CachedBonesTransform cachedTransform = cachedTransformList[0];
|
||||||
|
cachedTransform.CopyToTransform(boneTransform);
|
||||||
|
|
||||||
|
cachedTransformList.RemoveAt(0);
|
||||||
|
if (cachedTransformList.Count == 0) {
|
||||||
|
deserializedDict.Remove(boneTransform.name);
|
||||||
|
} else {
|
||||||
|
deserializedDict[boneTransform.name] = cachedTransformList;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (deserializedDict.Count > 0) {
|
||||||
|
ExplorerCore.LogWarning($"Couldn't apply every bone in the pose. Wrong entity?");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void SetCell(BonesCell cell, int index)
|
public void SetCell(BonesCell cell, int index)
|
||||||
{
|
{
|
||||||
if (index >= bones.Count)
|
if (index >= boneTrees.Count)
|
||||||
{
|
{
|
||||||
cell.Disable();
|
cell.Disable();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Transform bone = bones[index];
|
BoneTree boneTree = boneTrees[index];
|
||||||
cell.SetBone(bone, this);
|
cell.SetBoneTree(boneTree, this);
|
||||||
cell.UpdateTransformControlValues(true);
|
cell.UpdateTransformControlValues(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,17 +284,102 @@ namespace UnityExplorer.UI.Panels
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CachedBonesTransform
|
public class BoneTree
|
||||||
{
|
{
|
||||||
public CachedBonesTransform(Vector3 position, Vector3 angles, Vector3 scale)
|
public GameObject obj;
|
||||||
{
|
public int level;
|
||||||
this.position = position;
|
public List<BoneTree> childTrees = new();
|
||||||
this.angles = angles;
|
|
||||||
this.scale = scale;
|
public BoneTree(GameObject obj, List<Transform> bones){
|
||||||
|
// For some reason comparing GameObjects isn't working as intended in IL2CPP games, therefore we use their instance hash.
|
||||||
|
#if CPP
|
||||||
|
if (bones.Any(bone => bone.gameObject.GetInstanceID() == obj.GetInstanceID())) {
|
||||||
|
this.obj = obj;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (bones.Contains(obj.transform)) {
|
||||||
|
this.obj = obj;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
for (int i = 0; i < obj.transform.childCount; i++)
|
||||||
|
{
|
||||||
|
Transform child = obj.transform.GetChild(i);
|
||||||
|
if (child.gameObject.activeSelf){
|
||||||
|
childTrees.Add(new BoneTree(child.gameObject, bones));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Trim();
|
||||||
|
childTrees = childTrees.OrderBy(b => b.obj.name).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly Vector3 position;
|
private void Trim(){
|
||||||
public readonly Vector3 angles;
|
List<BoneTree> newList = new();
|
||||||
public readonly Vector3 scale;
|
foreach (BoneTree childTree in childTrees)
|
||||||
|
{
|
||||||
|
if (childTree.obj == null){
|
||||||
|
newList.AddRange(childTree.childTrees);
|
||||||
|
} else {
|
||||||
|
newList.Add(childTree);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.childTrees = newList;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: refactor BoneTree so we don't need to call this after creating an instance.
|
||||||
|
public void AssignLevels(){
|
||||||
|
AssignLevel(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AssignLevel(int distanceFromRoot){
|
||||||
|
level = distanceFromRoot;
|
||||||
|
foreach (BoneTree childTree in childTrees)
|
||||||
|
{
|
||||||
|
childTree.AssignLevel(distanceFromRoot + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString(){
|
||||||
|
string return_string = "";
|
||||||
|
if (obj != null){
|
||||||
|
return_string = $"{obj.name} lvl: {level} - ";
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (BoneTree childTree in childTrees)
|
||||||
|
{
|
||||||
|
return_string = return_string + childTree.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
return return_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GameObject> getGameObjects(){
|
||||||
|
List<GameObject> return_list = new();
|
||||||
|
if (obj != null){
|
||||||
|
return_list.Add(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (BoneTree childTree in childTrees)
|
||||||
|
{
|
||||||
|
return_list.AddRange(childTree.getGameObjects());
|
||||||
|
}
|
||||||
|
|
||||||
|
return return_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<BoneTree> flatten(){
|
||||||
|
List<BoneTree> return_list = new();
|
||||||
|
if (obj != null){
|
||||||
|
return_list.Add(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (BoneTree childTree in childTrees)
|
||||||
|
{
|
||||||
|
return_list.AddRange(childTree.flatten());
|
||||||
|
}
|
||||||
|
|
||||||
|
return return_list;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
using UniverseLib.Input;
|
using UnityEngine.SceneManagement;
|
||||||
|
using UnityExplorer.Serializers;
|
||||||
|
using UniverseLib.Input;
|
||||||
using UniverseLib.UI;
|
using UniverseLib.UI;
|
||||||
using UniverseLib.UI.Models;
|
using UniverseLib.UI.Models;
|
||||||
#if UNHOLLOWER
|
#if UNHOLLOWER
|
||||||
@ -9,11 +11,6 @@ using Il2CppInterop.Runtime.Injection;
|
|||||||
#endif
|
#endif
|
||||||
using UniverseLib.UI.Widgets.ScrollView;
|
using UniverseLib.UI.Widgets.ScrollView;
|
||||||
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using UnityEngine;
|
|
||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Panels
|
namespace UnityExplorer.UI.Panels
|
||||||
{
|
{
|
||||||
public class CamPaths : UEPanel, ICellPoolDataSource<CamPathNodeCell>
|
public class CamPaths : UEPanel, ICellPoolDataSource<CamPathNodeCell>
|
||||||
@ -51,6 +48,8 @@ namespace UnityExplorer.UI.Panels
|
|||||||
|
|
||||||
Toggle visualizePathToggle;
|
Toggle visualizePathToggle;
|
||||||
public GameObject pathVisualizer;
|
public GameObject pathVisualizer;
|
||||||
|
Toggle closedLoopToggle;
|
||||||
|
InputFieldRef TimeInput;
|
||||||
|
|
||||||
bool unpauseOnPlay;
|
bool unpauseOnPlay;
|
||||||
bool waitBeforePlay;
|
bool waitBeforePlay;
|
||||||
@ -65,6 +64,9 @@ namespace UnityExplorer.UI.Panels
|
|||||||
Slider tensionCatmullRomSlider;
|
Slider tensionCatmullRomSlider;
|
||||||
float tensionCatmullRomValue = 0;
|
float tensionCatmullRomValue = 0;
|
||||||
|
|
||||||
|
private InputFieldRef saveLoadInputField;
|
||||||
|
private Toggle loadPathOnCamToggle;
|
||||||
|
|
||||||
public ScrollPool<CamPathNodeCell> nodesScrollPool;
|
public ScrollPool<CamPathNodeCell> nodesScrollPool;
|
||||||
public int ItemCount => controlPoints.Count;
|
public int ItemCount => controlPoints.Count;
|
||||||
private static bool DoneScrollPoolInit;
|
private static bool DoneScrollPoolInit;
|
||||||
@ -107,23 +109,22 @@ namespace UnityExplorer.UI.Panels
|
|||||||
default, new Color(1, 1, 1, 0), TextAnchor.MiddleLeft);
|
default, new Color(1, 1, 1, 0), TextAnchor.MiddleLeft);
|
||||||
UIFactory.SetLayoutElement(horiGroup, minHeight: 25, flexibleWidth: 9999);
|
UIFactory.SetLayoutElement(horiGroup, minHeight: 25, flexibleWidth: 9999);
|
||||||
|
|
||||||
ButtonRef startButton = UIFactory.CreateButton(horiGroup, "Start", "▶");
|
ButtonRef startButton = UIFactory.CreateButton(horiGroup, "Start", "►", new Color(0.2f, 0.4f, 0.2f));
|
||||||
UIFactory.SetLayoutElement(startButton.GameObject, minWidth: 50, minHeight: 25);
|
UIFactory.SetLayoutElement(startButton.GameObject, minWidth: 50, minHeight: 25);
|
||||||
startButton.ButtonText.fontSize = 20;
|
|
||||||
startButton.OnClick += StartButton_OnClick;
|
startButton.OnClick += StartButton_OnClick;
|
||||||
|
|
||||||
ButtonRef pauseContinueButton = UIFactory.CreateButton(horiGroup, "Pause/Continue", "❚❚/▶");
|
ButtonRef pauseContinueButton = UIFactory.CreateButton(horiGroup, "Pause/Continue", "❚❚/►");
|
||||||
UIFactory.SetLayoutElement(pauseContinueButton.GameObject, minWidth: 50, minHeight: 25);
|
UIFactory.SetLayoutElement(pauseContinueButton.GameObject, minWidth: 50, minHeight: 25);
|
||||||
pauseContinueButton.ButtonText.fontSize = 20;
|
|
||||||
pauseContinueButton.OnClick += TogglePause_OnClick;
|
pauseContinueButton.OnClick += TogglePause_OnClick;
|
||||||
|
|
||||||
ButtonRef stopButton = UIFactory.CreateButton(horiGroup, "Stop", "■");
|
ButtonRef stopButton = UIFactory.CreateButton(horiGroup, "Stop", "■", new Color(0.4f, 0.2f, 0.2f));
|
||||||
UIFactory.SetLayoutElement(stopButton.GameObject, minWidth: 50, minHeight: 25);
|
UIFactory.SetLayoutElement(stopButton.GameObject, minWidth: 50, minHeight: 25);
|
||||||
stopButton.ButtonText.fontSize = 20;
|
stopButton.ButtonText.fontSize = 20;
|
||||||
stopButton.OnClick += Stop_OnClick;
|
stopButton.OnClick += Stop_OnClick;
|
||||||
|
|
||||||
ButtonRef AddNode = UIFactory.CreateButton(horiGroup, "AddCamNode", "+");
|
ButtonRef AddNode = UIFactory.CreateButton(horiGroup, "AddCamNode", "+");
|
||||||
UIFactory.SetLayoutElement(AddNode.GameObject, minWidth: 50, minHeight: 25);
|
UIFactory.SetLayoutElement(AddNode.GameObject, minWidth: 50, minHeight: 25);
|
||||||
|
AddNode.ButtonText.fontSize = 20;
|
||||||
AddNode.OnClick += AddNode_OnClick;
|
AddNode.OnClick += AddNode_OnClick;
|
||||||
|
|
||||||
ButtonRef DeletePath = UIFactory.CreateButton(horiGroup, "DeletePath", "Clear");
|
ButtonRef DeletePath = UIFactory.CreateButton(horiGroup, "DeletePath", "Clear");
|
||||||
@ -134,14 +135,13 @@ namespace UnityExplorer.UI.Panels
|
|||||||
MaybeRedrawPath();
|
MaybeRedrawPath();
|
||||||
};
|
};
|
||||||
|
|
||||||
Toggle closedLoopToggle = new Toggle();
|
closedLoopToggle = new Toggle();
|
||||||
GameObject toggleClosedLoopObj = UIFactory.CreateToggle(horiGroup, "Close path in a loop", out closedLoopToggle, out Text toggleClosedLoopText);
|
GameObject toggleClosedLoopObj = UIFactory.CreateToggle(horiGroup, "Close path in a loop", out closedLoopToggle, out Text toggleClosedLoopText);
|
||||||
UIFactory.SetLayoutElement(toggleClosedLoopObj, minHeight: 25, flexibleWidth: 9999);
|
UIFactory.SetLayoutElement(toggleClosedLoopObj, minHeight: 25, flexibleWidth: 9999);
|
||||||
closedLoopToggle.isOn = false;
|
closedLoopToggle.isOn = false;
|
||||||
closedLoopToggle.onValueChanged.AddListener((isClosedLoop) => {closedLoop = isClosedLoop; MaybeRedrawPath(); EventSystemHelper.SetSelectedGameObject(null);});
|
closedLoopToggle.onValueChanged.AddListener((isClosedLoop) => {closedLoop = isClosedLoop; MaybeRedrawPath(); EventSystemHelper.SetSelectedGameObject(null);});
|
||||||
toggleClosedLoopText.text = "Close path in a loop";
|
toggleClosedLoopText.text = "Close path in a loop";
|
||||||
|
|
||||||
InputFieldRef TimeInput = null;
|
|
||||||
AddInputField("Time", "Path time (in seconds at 60fps):", $"Default: {time}", out TimeInput, Time_OnEndEdit, 50, horiGroup);
|
AddInputField("Time", "Path time (in seconds at 60fps):", $"Default: {time}", out TimeInput, Time_OnEndEdit, 50, horiGroup);
|
||||||
TimeInput.Text = time.ToString();
|
TimeInput.Text = time.ToString();
|
||||||
|
|
||||||
@ -209,6 +209,29 @@ namespace UnityExplorer.UI.Panels
|
|||||||
MaybeRedrawPath();
|
MaybeRedrawPath();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
GameObject fourthRow = UIFactory.CreateHorizontalGroup(ContentRoot, "SerializationOptions", false, false, true, true, 3,
|
||||||
|
default, new Color(1, 1, 1, 0), TextAnchor.MiddleLeft);
|
||||||
|
UIFactory.SetLayoutElement(fourthRow, minHeight: 25, flexibleWidth: 9999);
|
||||||
|
|
||||||
|
saveLoadInputField = UIFactory.CreateInputField(fourthRow, "PathName", "File name");
|
||||||
|
UIFactory.SetLayoutElement(saveLoadInputField.GameObject, minWidth: 320, minHeight: 25);
|
||||||
|
|
||||||
|
GameObject spacer1 = UIFactory.CreateUIObject("Spacer", fourthRow);
|
||||||
|
LayoutElement spaceLayout1 = UIFactory.SetLayoutElement(spacer1, minWidth: 20, flexibleWidth: 0);
|
||||||
|
|
||||||
|
ButtonRef savePath = UIFactory.CreateButton(fourthRow, "SavePathButton", "Save path");
|
||||||
|
UIFactory.SetLayoutElement(savePath.GameObject, minWidth: 100, minHeight: 25);
|
||||||
|
savePath.OnClick += SavePath;
|
||||||
|
|
||||||
|
ButtonRef loadPath = UIFactory.CreateButton(fourthRow, "LoadPathButton", "Load path");
|
||||||
|
UIFactory.SetLayoutElement(loadPath.GameObject, minWidth: 100, minHeight: 25);
|
||||||
|
loadPath.OnClick += LoadPath;
|
||||||
|
|
||||||
|
GameObject loadPathOnCamObj = UIFactory.CreateToggle(fourthRow, "Load path on cam", out loadPathOnCamToggle, out Text loadPathOnCamText);
|
||||||
|
UIFactory.SetLayoutElement(loadPathOnCamObj, minHeight: 25, flexibleWidth: 9999);
|
||||||
|
loadPathOnCamToggle.isOn = false;
|
||||||
|
loadPathOnCamText.text = "Load path starting on current camera state";
|
||||||
|
|
||||||
nodesScrollPool = UIFactory.CreateScrollPool<CamPathNodeCell>(ContentRoot, "NodeList", out GameObject scrollObj,
|
nodesScrollPool = UIFactory.CreateScrollPool<CamPathNodeCell>(ContentRoot, "NodeList", out GameObject scrollObj,
|
||||||
out GameObject scrollContent, new Color(0.03f, 0.03f, 0.03f));
|
out GameObject scrollContent, new Color(0.03f, 0.03f, 0.03f));
|
||||||
UIFactory.SetLayoutElement(scrollObj, flexibleWidth: 9999, flexibleHeight: 9999);
|
UIFactory.SetLayoutElement(scrollObj, flexibleWidth: 9999, flexibleHeight: 9999);
|
||||||
@ -216,8 +239,6 @@ namespace UnityExplorer.UI.Panels
|
|||||||
|
|
||||||
void AlphaCatmullRom_OnEndEdit(string input)
|
void AlphaCatmullRom_OnEndEdit(string input)
|
||||||
{
|
{
|
||||||
EventSystemHelper.SetSelectedGameObject(null);
|
|
||||||
|
|
||||||
if (!ParseUtility.TryParse(input, out float parsed, out Exception parseEx))
|
if (!ParseUtility.TryParse(input, out float parsed, out Exception parseEx))
|
||||||
{
|
{
|
||||||
ExplorerCore.LogWarning($"Could not parse value: {parseEx.ReflectionExToString()}");
|
ExplorerCore.LogWarning($"Could not parse value: {parseEx.ReflectionExToString()}");
|
||||||
@ -229,12 +250,11 @@ namespace UnityExplorer.UI.Panels
|
|||||||
alphaCatmullRomSlider.value = alphaCatmullRomValue;
|
alphaCatmullRomSlider.value = alphaCatmullRomValue;
|
||||||
|
|
||||||
MaybeRedrawPath();
|
MaybeRedrawPath();
|
||||||
|
EventSystemHelper.SetSelectedGameObject(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TensionCatmullRom_OnEndEdit(string input)
|
void TensionCatmullRom_OnEndEdit(string input)
|
||||||
{
|
{
|
||||||
EventSystemHelper.SetSelectedGameObject(null);
|
|
||||||
|
|
||||||
if (!ParseUtility.TryParse(input, out float parsed, out Exception parseEx))
|
if (!ParseUtility.TryParse(input, out float parsed, out Exception parseEx))
|
||||||
{
|
{
|
||||||
ExplorerCore.LogWarning($"Could not parse value: {parseEx.ReflectionExToString()}");
|
ExplorerCore.LogWarning($"Could not parse value: {parseEx.ReflectionExToString()}");
|
||||||
@ -246,6 +266,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
tensionCatmullRomSlider.value = tensionCatmullRomValue;
|
tensionCatmullRomSlider.value = tensionCatmullRomValue;
|
||||||
|
|
||||||
MaybeRedrawPath();
|
MaybeRedrawPath();
|
||||||
|
EventSystemHelper.SetSelectedGameObject(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ToggleVisualizePath(bool enable){
|
private void ToggleVisualizePath(bool enable){
|
||||||
@ -365,7 +386,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
CatmullRom.CatmullRomPoint point = new CatmullRom.CatmullRomPoint(
|
CatmullRom.CatmullRomPoint point = new CatmullRom.CatmullRomPoint(
|
||||||
FreeCamPanel.GetCameraPosition(),
|
FreeCamPanel.GetCameraPosition(),
|
||||||
FreeCamPanel.GetCameraRotation(),
|
FreeCamPanel.GetCameraRotation(),
|
||||||
FreeCamPanel.ourCamera.fieldOfView
|
FreeCamPanel.GetFreecam().fieldOfView
|
||||||
);
|
);
|
||||||
|
|
||||||
controlPoints.Add(point);
|
controlPoints.Add(point);
|
||||||
@ -377,7 +398,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
{
|
{
|
||||||
EventSystemHelper.SetSelectedGameObject(null);
|
EventSystemHelper.SetSelectedGameObject(null);
|
||||||
|
|
||||||
if (!ParseUtility.TryParse(input, out int parsed, out Exception parseEx))
|
if (!ParseUtility.TryParse(input, out float parsed, out Exception parseEx))
|
||||||
{
|
{
|
||||||
ExplorerCore.LogWarning($"Could not parse value: {parseEx.ReflectionExToString()}");
|
ExplorerCore.LogWarning($"Could not parse value: {parseEx.ReflectionExToString()}");
|
||||||
return;
|
return;
|
||||||
@ -494,6 +515,92 @@ namespace UnityExplorer.UI.Panels
|
|||||||
|
|
||||||
GetCameraPathsManager().CalculateLookahead();
|
GetCameraPathsManager().CalculateLookahead();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void SavePath(){
|
||||||
|
string filename = saveLoadInputField.Component.text;
|
||||||
|
if (filename.EndsWith(".cuepath") || filename.EndsWith(".CUEPATH")) filename = filename.Substring(filename.Length-7);
|
||||||
|
if (string.IsNullOrEmpty(filename)) filename = $"{DateTime.Now.ToString("yyyy-M-d HH-mm-ss")}";
|
||||||
|
string camPathsFolderPath = Path.Combine(ExplorerCore.ExplorerFolder, "CamPaths");
|
||||||
|
System.IO.Directory.CreateDirectory(camPathsFolderPath);
|
||||||
|
|
||||||
|
// Serialize
|
||||||
|
string serializedData = CamPathSerializer.Serialize(controlPoints, time, alphaCatmullRomValue, tensionCatmullRomValue, closedLoop, SceneManager.GetActiveScene().name);
|
||||||
|
File.WriteAllText($"{camPathsFolderPath}\\{filename}.cuepath", serializedData);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadPath(){
|
||||||
|
string filename = saveLoadInputField.Component.text;
|
||||||
|
if (filename.EndsWith(".cuepath") || filename.EndsWith(".CUEPATH")) filename = filename.Substring(filename.Length-7);
|
||||||
|
if (string.IsNullOrEmpty(filename)){
|
||||||
|
ExplorerCore.LogWarning("Empty file name. Please write the name of the file to load.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string camPathsFolderPath = Path.Combine(ExplorerCore.ExplorerFolder, "CamPaths");
|
||||||
|
string pathFile;
|
||||||
|
try {
|
||||||
|
pathFile = File.ReadAllText($"{camPathsFolderPath}\\{filename}.cuepath");
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
ExplorerCore.LogWarning(ex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
CamPathSerializeObject deserializedObj;
|
||||||
|
try {
|
||||||
|
deserializedObj = CamPathSerializer.Deserialize(pathFile);
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
ExplorerCore.LogWarning(ex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (deserializedObj.sceneName != SceneManager.GetActiveScene().name && !loadPathOnCamToggle.isOn) {
|
||||||
|
loadPathOnCamToggle.isOn = true;
|
||||||
|
ExplorerCore.LogWarning("Loaded a path on a different scene than the one it was saved on. Spawning it starting from the current camera state.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (loadPathOnCamToggle.isOn) {
|
||||||
|
|
||||||
|
// We enable the freecam so we can use it to spawn the camera path relative to it
|
||||||
|
if (!FreeCamPanel.inFreeCamMode) {
|
||||||
|
FreeCamPanel.StartStopButton_OnClick();
|
||||||
|
}
|
||||||
|
|
||||||
|
controlPoints.Clear();
|
||||||
|
// The first point will be the camera position, and we adapt the following points from there
|
||||||
|
AddNode_OnClick();
|
||||||
|
|
||||||
|
CatmullRom.CatmullRomPoint startingPoint = controlPoints.ElementAt(0);
|
||||||
|
CatmullRom.CatmullRomPoint originalStartingPoint = deserializedObj.points.ElementAt(0);
|
||||||
|
// We only want to use the camera pos and rotation, not the fov
|
||||||
|
startingPoint.fov = originalStartingPoint.fov;
|
||||||
|
controlPoints[0] = startingPoint;
|
||||||
|
|
||||||
|
foreach (CatmullRom.CatmullRomPoint point in deserializedObj.points.Skip(1)) {
|
||||||
|
CatmullRom.CatmullRomPoint newPoint = point;
|
||||||
|
|
||||||
|
Quaternion offsetRot = startingPoint.rotation * Quaternion.Inverse(originalStartingPoint.rotation);
|
||||||
|
newPoint.position = offsetRot * (newPoint.position - originalStartingPoint.position) + startingPoint.position;
|
||||||
|
newPoint.rotation = offsetRot * newPoint.rotation;
|
||||||
|
|
||||||
|
controlPoints.Add(newPoint);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
controlPoints = deserializedObj.points;
|
||||||
|
}
|
||||||
|
|
||||||
|
TimeInput.Text = deserializedObj.time.ToString("0.00");
|
||||||
|
Time_OnEndEdit(TimeInput.Text);
|
||||||
|
alphaCatmullRomInput.Text = deserializedObj.alpha.ToString("0.00");
|
||||||
|
AlphaCatmullRom_OnEndEdit(alphaCatmullRomInput.Text);
|
||||||
|
tensionCatmullRomInput.Text = deserializedObj.tension.ToString("0.00");
|
||||||
|
TensionCatmullRom_OnEndEdit(tensionCatmullRomInput.Text);
|
||||||
|
closedLoopToggle.isOn = deserializedObj.closePath;
|
||||||
|
|
||||||
|
// Update nodes
|
||||||
|
nodesScrollPool.Refresh(true, false);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class CamPointsUpdater : MonoBehaviour
|
public class CamPointsUpdater : MonoBehaviour
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -48,6 +48,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
Toggle HighLodToggle;
|
Toggle HighLodToggle;
|
||||||
object qualitySettings = null;
|
object qualitySettings = null;
|
||||||
PropertyInfo lodBias = null;
|
PropertyInfo lodBias = null;
|
||||||
|
float _defaultLodBias = 1;
|
||||||
|
|
||||||
// We save the current properties of the Renderers and Lights to restore them after editing them with togglers
|
// We save the current properties of the Renderers and Lights to restore them after editing them with togglers
|
||||||
internal Dictionary<Renderer, bool> renderersReceiveShadows = new();
|
internal Dictionary<Renderer, bool> renderersReceiveShadows = new();
|
||||||
@ -122,9 +123,9 @@ namespace UnityExplorer.UI.Panels
|
|||||||
if (lodBias == null){
|
if (lodBias == null){
|
||||||
Type qualitySettingsType = qualitySettings is Type type ? type : qualitySettings.GetActualType();
|
Type qualitySettingsType = qualitySettings is Type type ? type : qualitySettings.GetActualType();
|
||||||
lodBias = qualitySettingsType.GetProperty("lodBias");
|
lodBias = qualitySettingsType.GetProperty("lodBias");
|
||||||
|
_defaultLodBias = (float)lodBias.GetValue(null, null);
|
||||||
}
|
}
|
||||||
|
lodBias.SetValue(null, areHighLodsOn ? 10000 : _defaultLodBias, null);
|
||||||
lodBias.SetValue(null, areHighLodsOn ? 10000 : 1, null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ToggleAllMeshesCastAndRecieveShadows(bool enable){
|
private void ToggleAllMeshesCastAndRecieveShadows(bool enable){
|
||||||
|
@ -183,7 +183,7 @@ namespace UnityExplorer.CatmullRom
|
|||||||
Vector3 camPos = FreeCamPanel.GetCameraPosition();
|
Vector3 camPos = FreeCamPanel.GetCameraPosition();
|
||||||
Quaternion camRot = FreeCamPanel.GetCameraRotation();
|
Quaternion camRot = FreeCamPanel.GetCameraRotation();
|
||||||
|
|
||||||
return new CatmullRomPoint(camPos, camRot, FreeCamPanel.ourCamera.fieldOfView);
|
return new CatmullRomPoint(camPos, camRot, FreeCamPanel.GetFreecam().fieldOfView);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AdvanceMover(float dt){
|
private void AdvanceMover(float dt){
|
||||||
@ -238,14 +238,14 @@ namespace UnityExplorer.CatmullRom
|
|||||||
|
|
||||||
FreeCamPanel.SetCameraRotation(CatmullRomPoint.Vector4ToQuaternion(newRot));
|
FreeCamPanel.SetCameraRotation(CatmullRomPoint.Vector4ToQuaternion(newRot));
|
||||||
FreeCamPanel.SetCameraPosition(FreeCamPanel.GetCameraPosition() + direction.position);
|
FreeCamPanel.SetCameraPosition(FreeCamPanel.GetCameraPosition() + direction.position);
|
||||||
FreeCamPanel.ourCamera.fieldOfView += direction.fov * actual / room;
|
FreeCamPanel.SetFOV(FreeCamPanel.GetFreecam().fieldOfView + direction.fov * actual / room);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void MoveCameraToPoint(CatmullRomPoint newPoint){
|
public void MoveCameraToPoint(CatmullRomPoint newPoint){
|
||||||
FreeCamPanel.SetCameraRotation(newPoint.rotation);
|
FreeCamPanel.SetCameraRotation(newPoint.rotation);
|
||||||
FreeCamPanel.SetCameraPosition(newPoint.position);
|
FreeCamPanel.SetCameraPosition(newPoint.position);
|
||||||
|
|
||||||
FreeCamPanel.ourCamera.fieldOfView = newPoint.fov;
|
FreeCamPanel.SetFOV(newPoint.fov);
|
||||||
}
|
}
|
||||||
|
|
||||||
private CatmullRomPoint GetPointFromPath(float d)
|
private CatmullRomPoint GetPointFromPath(float d)
|
||||||
|
@ -19,6 +19,7 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
|
|
||||||
ButtonRef ViewParentButton;
|
ButtonRef ViewParentButton;
|
||||||
ButtonRef FollowObjectButton;
|
ButtonRef FollowObjectButton;
|
||||||
|
ButtonRef LookAtObjectButton;
|
||||||
InputFieldRef PathInput;
|
InputFieldRef PathInput;
|
||||||
|
|
||||||
InputFieldRef NameInput;
|
InputFieldRef NameInput;
|
||||||
@ -295,6 +296,11 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
UIFactory.SetLayoutElement(FollowObjectButton.Component.gameObject, minHeight: 25, minWidth: 100);
|
UIFactory.SetLayoutElement(FollowObjectButton.Component.gameObject, minHeight: 25, minWidth: 100);
|
||||||
FollowObjectButton.OnClick += () => FreeCamPanel.FollowObjectAction(this.Target.gameObject);
|
FollowObjectButton.OnClick += () => FreeCamPanel.FollowObjectAction(this.Target.gameObject);
|
||||||
|
|
||||||
|
LookAtObjectButton = UIFactory.CreateButton(firstRow, "LookAtObjectButton", "Look at object with Freecam", new Color(0.2f, 0.2f, 0.2f));
|
||||||
|
LookAtObjectButton.ButtonText.fontSize = 13;
|
||||||
|
UIFactory.SetLayoutElement(LookAtObjectButton.Component.gameObject, minHeight: 25, minWidth: 100);
|
||||||
|
LookAtObjectButton.OnClick += () => FreeCamPanel.LookAtObjectAction(this.Target.gameObject);
|
||||||
|
|
||||||
this.PathInput = UIFactory.CreateInputField(firstRow, "PathInput", "...");
|
this.PathInput = UIFactory.CreateInputField(firstRow, "PathInput", "...");
|
||||||
PathInput.Component.textComponent.color = Color.grey;
|
PathInput.Component.textComponent.color = Color.grey;
|
||||||
PathInput.Component.textComponent.fontSize = 14;
|
PathInput.Component.textComponent.fontSize = 14;
|
||||||
@ -324,6 +330,19 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
NameInput.Component.textComponent.fontSize = 15;
|
NameInput.Component.textComponent.fontSize = 15;
|
||||||
NameInput.Component.GetOnEndEdit().AddListener((string val) => { OnNameEndEdit(val); });
|
NameInput.Component.GetOnEndEdit().AddListener((string val) => { OnNameEndEdit(val); });
|
||||||
|
|
||||||
|
ButtonRef MoveToCameraButton = UIFactory.CreateButton(titleRow, "MoveToCameraButton", "Move to Camera", new Color(0.2f, 0.2f, 0.2f));
|
||||||
|
MoveToCameraButton.ButtonText.fontSize = 13;
|
||||||
|
UIFactory.SetLayoutElement(MoveToCameraButton.Component.gameObject, minHeight: 25, minWidth: 120);
|
||||||
|
MoveToCameraButton.OnClick += () => {
|
||||||
|
if (FreeCamPanel.inFreeCamMode) {
|
||||||
|
Transform freecamTransform = FreeCamPanel.GetFreecam().transform;
|
||||||
|
this.Target.gameObject.transform.position = freecamTransform.position;
|
||||||
|
this.Target.gameObject.transform.rotation = freecamTransform.rotation;
|
||||||
|
} else {
|
||||||
|
ExplorerCore.LogWarning("Enable freecam before trying to move an object to the camera!");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// second row (toggles, instanceID, tag, buttons)
|
// second row (toggles, instanceID, tag, buttons)
|
||||||
|
|
||||||
GameObject secondRow = UIFactory.CreateUIObject("ParentRow", topInfoHolder);
|
GameObject secondRow = UIFactory.CreateUIObject("ParentRow", topInfoHolder);
|
||||||
|
Reference in New Issue
Block a user