mirror of
https://github.com/originalnicodr/CinematicUnityExplorer.git
synced 2025-07-19 01:57:56 +08:00
IGCS Support for CUE (#72)
* Initial work on supporting IGCS
* feat: Added callback when starting session, adding missing func.
* chore: tidy up math and cleanup.
* chore: tidy up some verbose code
* Added more callbacks, fixed math.
* fix: use queue command system instead of directly writing to the camera.
* lock camera while igcsdof is active.
* build system shenanigans
Now we can build the project just fine by building separately the C
project and the C# project.
* small syntax changes.
learning c# and stuff
* Refactor executeCameraCommand and improve thread-safety in FreeCamPanel
* woops, correct order of arguments for MessageBoxA
* fix: move the ourCamera check where it's actually needed.
* chore: formatting c file
* rewrite: move all igcsdof logic to its own class.
Since CUE *must* work without igcsdof, I thought it would be convenient
to handle all the logic regarding igcsdof in its own class. The
initialization is a bit of a mess because since most of what it's on
FreeCam is static I had to do some trickery.
I wanted to specifically avoid calling LoadLibrary every time so I
thought on only initializing one and having an internal flag either the
thing loaded correctly or not (`isValid`).
* fix: Pin callbacks to avoid garbage collection
* chore: removed unused code
* chore: fix typo.
* nit: more idiomatic C# usage.
Just applied what rider suggested =)
* fix: remove unnecesary GCHandle, store delegates.
* feat: Update IGCS dof camera status accordingly.
Before, we just left igcsdof always enabled, now we handle the cases
properly, avoiding the posibility of the user using igcsdof with the
freecam disabled.
* nit: fix comments and added some to UnityIGCSConnector.
* feat: Get the transform reference earlier for perf™️
* fix: Properly handle an initialization error.
* chore: remove overly verbose debugging
* fix: make sure we start with a clear queue after we end a session.
This was what maybe was causing the misaligning after you cancel a
session since we never checked if the queue was emptied by the code.
* fix: properly cast a function pointer to use what it returns.
This commit is contained in:
31
UnityIGCSConnector/UnityIGCSConnector.sln
Normal file
31
UnityIGCSConnector/UnityIGCSConnector.sln
Normal file
@ -0,0 +1,31 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.9.34723.18
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UnityIGCSConnector", "UnityIGCSConnector.vcxproj", "{676E7EC4-E40E-4D59-9587-2E2CD04BC562}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{676E7EC4-E40E-4D59-9587-2E2CD04BC562}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{676E7EC4-E40E-4D59-9587-2E2CD04BC562}.Debug|x64.Build.0 = Debug|x64
|
||||
{676E7EC4-E40E-4D59-9587-2E2CD04BC562}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{676E7EC4-E40E-4D59-9587-2E2CD04BC562}.Debug|x86.Build.0 = Debug|Win32
|
||||
{676E7EC4-E40E-4D59-9587-2E2CD04BC562}.Release|x64.ActiveCfg = Release|x64
|
||||
{676E7EC4-E40E-4D59-9587-2E2CD04BC562}.Release|x64.Build.0 = Release|x64
|
||||
{676E7EC4-E40E-4D59-9587-2E2CD04BC562}.Release|x86.ActiveCfg = Release|Win32
|
||||
{676E7EC4-E40E-4D59-9587-2E2CD04BC562}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {CCC0598B-A93B-4F40-B29D-43164253230A}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
167
UnityIGCSConnector/UnityIGCSConnector.vcxproj
Normal file
167
UnityIGCSConnector/UnityIGCSConnector.vcxproj
Normal file
@ -0,0 +1,167 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>17.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{676e7ec4-e40e-4d59-9587-2e2cd04bc562}</ProjectGuid>
|
||||
<RootNamespace>UnityIGCSConnector</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<TargetName>UnityIGCSConnector</TargetName>
|
||||
<OutDir>$(SolutionDir)..\$(Configuration)\</OutDir>
|
||||
<PostBuildEventUseInBuild>false</PostBuildEventUseInBuild>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<TargetName>UnityIGCSConnector</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<TargetName>UnityIGCSConnector</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<TargetName>UnityIGCSConnector</TargetName>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;UNITYIGCSCONNECTOR_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;UNITYIGCSCONNECTOR_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;UNITYIGCSCONNECTOR_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;UNITYIGCSCONNECTOR_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<LanguageStandard_C>stdc11</LanguageStandard_C>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
<Command>xcopy /y /d "$(SolutionDir)$(Platform)\$(Configuration)\UnityIGCSConnector.dll" "$(SolutionDir)..\$(Configuration)\UnityIGCSConnector.dll"</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="dllmain.c">
|
||||
<DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
22
UnityIGCSConnector/UnityIGCSConnector.vcxproj.filters
Normal file
22
UnityIGCSConnector/UnityIGCSConnector.vcxproj.filters
Normal file
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="dllmain.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
93
UnityIGCSConnector/dllmain.c
Normal file
93
UnityIGCSConnector/dllmain.c
Normal file
@ -0,0 +1,93 @@
|
||||
// dllmain.cpp : Defines the entry point for the DLL application.
|
||||
#include <Windows.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define EXPOSE __declspec(dllexport)
|
||||
|
||||
// The function that will be the one called from the C# side, that will update the corresponding values.
|
||||
typedef void (*MoveCameraCallback)(float, float, float, int);
|
||||
|
||||
typedef void (*SessionCallback)(void);
|
||||
|
||||
typedef uint8_t* (*GetCameraDataFunc)(void);
|
||||
|
||||
MoveCameraCallback GlobalCallback = NULL;
|
||||
SessionCallback GlobalStartSession = NULL;
|
||||
SessionCallback GlobalEndSession = NULL;
|
||||
|
||||
// There are things that only needs to be run once.
|
||||
static int first_initialization = 1;
|
||||
|
||||
EXPOSE int IGCS_StartScreenshotSession(uint8_t _ignore) {
|
||||
if (GlobalStartSession) {
|
||||
GlobalStartSession();
|
||||
printf("Called StartSession\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPOSE void IGCS_EndScreenshotSession() {
|
||||
GlobalEndSession();
|
||||
printf("Called EndSession\n");
|
||||
}
|
||||
|
||||
EXPOSE uint8_t* U_IGCS_Initialize(MoveCameraCallback cb, SessionCallback start_cb, SessionCallback end_cb) {
|
||||
AllocConsole();
|
||||
printf("Initializing callback\n");
|
||||
GlobalCallback = cb;
|
||||
GlobalStartSession = start_cb;
|
||||
GlobalEndSession = end_cb;
|
||||
|
||||
// Load IGCS
|
||||
HMODULE igcs = LoadLibraryA("IgcsConnector.addon64");
|
||||
|
||||
if (!igcs) {
|
||||
MessageBoxA(
|
||||
NULL,
|
||||
"IgcsConnector.addon64 was not found, make sure it is in the same directory as the executable.",
|
||||
"Unable to find IgcsConnector",
|
||||
MB_OK | MB_ICONERROR);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FARPROC cameraToolsFunction = GetProcAddress(igcs, "connectFromCameraTools");
|
||||
GetCameraDataFunc getCameraData = (GetCameraDataFunc)GetProcAddress(igcs, "getDataFromCameraToolsBuffer");
|
||||
|
||||
if (first_initialization) {
|
||||
cameraToolsFunction();
|
||||
first_initialization = 0;
|
||||
}
|
||||
|
||||
// TODO: move this where it belongs. Maybe at some point we should actually fill in the data.
|
||||
uint8_t* cameraData = getCameraData();
|
||||
cameraData[0] = 0;
|
||||
|
||||
printf("Camera connected!\n");
|
||||
|
||||
return cameraData;
|
||||
|
||||
}
|
||||
|
||||
EXPOSE void IGCS_MoveCameraPanorama() {}
|
||||
|
||||
EXPOSE void IGCS_MoveCameraMultishot(float step_left, float step_up, float fov, int from_start) {
|
||||
GlobalCallback(step_left, step_up, fov, from_start);
|
||||
return;
|
||||
}
|
||||
|
||||
BOOL WINAPI DllMain(HMODULE hModule,
|
||||
DWORD ul_reason_for_call,
|
||||
LPVOID lpReserved
|
||||
)
|
||||
{
|
||||
switch (ul_reason_for_call)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
case DLL_THREAD_ATTACH:
|
||||
case DLL_THREAD_DETACH:
|
||||
case DLL_PROCESS_DETACH:
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
@ -2,6 +2,8 @@ cd UniverseLib
|
||||
.\build.ps1
|
||||
cd ..
|
||||
|
||||
# ----------- Build UnityIGCSConnector ------------
|
||||
msbuild.exe UnityIGCSConnector/UnityIGCSConnector.sln -p:Configuration=Release
|
||||
|
||||
# ----------- MelonLoader IL2CPP (net6) -----------
|
||||
dotnet build src/CinematicUnityExplorer.sln -c Release_ML_Cpp_net6preview
|
||||
|
129
src/Cinematic/UnityIGCSConnector.cs
Normal file
129
src/Cinematic/UnityIGCSConnector.cs
Normal file
@ -0,0 +1,129 @@
|
||||
using MonoMod.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using UnityExplorer;
|
||||
|
||||
namespace CinematicUnityExplorer.Cinematic
|
||||
{
|
||||
// StepCommand is basically the offset of step_left and step_up, what IGCS sends to move the camera.
|
||||
using StepCommand = Mono.CSharp.Tuple<float, float>;
|
||||
|
||||
internal static class NativeMethods
|
||||
{
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern IntPtr LoadLibrary(string dll);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
|
||||
}
|
||||
public class UnityIGCSConnector
|
||||
{
|
||||
// UnityIGCSConnector.dll definitions.
|
||||
private delegate void MoveCameraCallback(float step_left, float step_up, float fov, int from_start);
|
||||
private delegate void SessionCallback();
|
||||
private delegate IntPtr U_IGCS_Initialize(MoveCameraCallback callback, SessionCallback start_cb, SessionCallback end_cb);
|
||||
|
||||
// Store the initial position when a session start in IGCSDof.
|
||||
Mono.CSharp.Tuple<Vector3, Quaternion> position = null;
|
||||
|
||||
private readonly bool isValid = false;
|
||||
private bool _isActive = false;
|
||||
public bool IsActive => isValid && _isActive;
|
||||
|
||||
// Delegate holder for the MoveCamera, StartSession and EndSession.
|
||||
private readonly List<System.Delegate> delegates = new();
|
||||
|
||||
// Since some games use multi-threaded, in order to make sure we're only moving things during
|
||||
// the main thread is executing, we use this Queue to enqueue the move commands and dequeue them in the Update function.
|
||||
// This object *must* be used with a Lock.
|
||||
private readonly Queue<StepCommand> commands = new();
|
||||
|
||||
private IntPtr CameraStatus = IntPtr.Zero;
|
||||
// In order to avoid allocations on every Update call, we create this buffer to allocate once
|
||||
// and copy from here the CameraStatus (because Marshal.Copy requires a buffer, urgh).
|
||||
private readonly byte[] CameraStatusBuffer = new byte[] { 0x0 };
|
||||
|
||||
public void UpdateFreecamStatus(bool enabled)
|
||||
{
|
||||
if (CameraStatus == IntPtr.Zero) return;
|
||||
|
||||
CameraStatusBuffer[0] = enabled ? (byte)0x1 : (byte)0x0;
|
||||
Marshal.Copy(CameraStatusBuffer, 0, CameraStatus, 1);
|
||||
}
|
||||
|
||||
public void ExecuteCameraCommand(Camera cam)
|
||||
{
|
||||
var transform = cam.transform;
|
||||
if (!_isActive || position == null)
|
||||
{
|
||||
position = new(transform.position, transform.rotation);
|
||||
}
|
||||
|
||||
if (!_isActive || position == null) { return; }
|
||||
|
||||
StepCommand c = null;
|
||||
|
||||
lock (commands)
|
||||
{
|
||||
if (commands.Count <= 0) return;
|
||||
c = commands.Dequeue();
|
||||
}
|
||||
|
||||
transform.position = position.Item1;
|
||||
transform.rotation = position.Item2;
|
||||
transform.Translate(c.Item1, c.Item2, 0.0f);
|
||||
}
|
||||
|
||||
private void MoveCamera(float stepLeft, float stepUp, float fov, int fromStart)
|
||||
{
|
||||
lock (commands)
|
||||
{
|
||||
commands.Enqueue(new StepCommand(stepLeft, stepUp));
|
||||
}
|
||||
}
|
||||
private void StartSession()
|
||||
{
|
||||
_isActive = true;
|
||||
}
|
||||
|
||||
private void EndSession()
|
||||
{
|
||||
position = null;
|
||||
_isActive = false;
|
||||
|
||||
lock (commands)
|
||||
commands.Clear();
|
||||
}
|
||||
|
||||
public UnityIGCSConnector()
|
||||
{
|
||||
var lib = NativeMethods.LoadLibrary(@"UnityIGCSConnector.dll");
|
||||
if (lib == IntPtr.Zero)
|
||||
{
|
||||
ExplorerCore.LogWarning("UnityIGCSConnector.dll was not found so IGCSDof will not be available");
|
||||
return;
|
||||
}
|
||||
|
||||
var func = NativeMethods.GetProcAddress(lib, @"U_IGCS_Initialize");
|
||||
if (func == IntPtr.Zero)
|
||||
{
|
||||
throw new EntryPointNotFoundException("Failed to find 'U_IGCS_Initialize' which means you can have a corrupt UnityIGCSConnector.dll.");
|
||||
}
|
||||
|
||||
var initFunc = (U_IGCS_Initialize)Marshal.GetDelegateForFunctionPointer(func, typeof(U_IGCS_Initialize));
|
||||
|
||||
delegates.Add(new MoveCameraCallback(MoveCamera));
|
||||
delegates.Add(new SessionCallback(StartSession));
|
||||
delegates.Add(new SessionCallback(EndSession));
|
||||
|
||||
CameraStatus = initFunc((MoveCameraCallback)delegates[0], (SessionCallback)delegates[1], (SessionCallback)delegates[2]);
|
||||
if (CameraStatus == IntPtr.Zero)
|
||||
throw new InvalidDataException("IGCSDof returned an invalid pointer which means something went wrong");
|
||||
|
||||
isValid = true;
|
||||
}
|
||||
}
|
||||
}
|
@ -4,6 +4,9 @@ using UnityExplorer.Inspectors;
|
||||
using UniverseLib.Input;
|
||||
using UniverseLib.UI;
|
||||
using UniverseLib.UI.Models;
|
||||
using System.Runtime.InteropServices;
|
||||
using CinematicUnityExplorer.Cinematic;
|
||||
|
||||
#if UNHOLLOWER
|
||||
using UnhollowerRuntimeLib;
|
||||
#endif
|
||||
@ -76,9 +79,12 @@ namespace UnityExplorer.UI.Panels
|
||||
|
||||
private static FreecamCursorUnlocker freecamCursorUnlocker = null;
|
||||
|
||||
public static UnityIGCSConnector connector = new();
|
||||
|
||||
internal static void BeginFreecam()
|
||||
{
|
||||
inFreeCamMode = true;
|
||||
connector.UpdateFreecamStatus(true);
|
||||
|
||||
previousMousePosition = IInputManager.MousePosition;
|
||||
|
||||
@ -177,6 +183,7 @@ namespace UnityExplorer.UI.Panels
|
||||
internal static void EndFreecam()
|
||||
{
|
||||
inFreeCamMode = false;
|
||||
connector.UpdateFreecamStatus(false);
|
||||
|
||||
if (usingGameCamera)
|
||||
{
|
||||
@ -254,6 +261,9 @@ namespace UnityExplorer.UI.Panels
|
||||
if (positionInput.Component.isFocused)
|
||||
return;
|
||||
|
||||
if (connector.IsActive)
|
||||
return;
|
||||
|
||||
lastSetCameraPosition = ourCamera.transform.position;
|
||||
positionInput.Text = ParseUtility.ToStringForInput<Vector3>(lastSetCameraPosition);
|
||||
}
|
||||
@ -672,7 +682,7 @@ namespace UnityExplorer.UI.Panels
|
||||
|
||||
Transform transform = FreeCamPanel.ourCamera.transform;
|
||||
|
||||
if (!FreeCamPanel.blockFreecamMovementToggle.isOn && !FreeCamPanel.cameraPathMover.playingPath){
|
||||
if (!FreeCamPanel.blockFreecamMovementToggle.isOn && !FreeCamPanel.cameraPathMover.playingPath && !FreeCamPanel.connector.IsActive) {
|
||||
ProcessInput();
|
||||
}
|
||||
|
||||
@ -692,6 +702,8 @@ namespace UnityExplorer.UI.Panels
|
||||
FreeCamPanel.followObjectLastRotation = FreeCamPanel.followObject.transform.rotation;
|
||||
}
|
||||
|
||||
FreeCamPanel.connector.ExecuteCameraCommand(FreeCamPanel.ourCamera);
|
||||
|
||||
FreeCamPanel.UpdatePositionInput();
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user