1
0
mirror of https://github.com/originalnicodr/CinematicUnityExplorer.git synced 2026-10-10 04:53:15 +08:00

Added new freecam methods, one for cloning the gameplay camera and another one for replacing the worldToCameraMatrix of the gameplay camera.

This commit is contained in:
originalnicodr
2024-11-23 11:52:00 -03:00
parent c9aa93a6a4
commit 736ebdfa1b
6 changed files with 400 additions and 89 deletions
+6 -3
View File
@@ -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", "▲");
+2 -2
View File
@@ -29,7 +29,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;
@@ -90,7 +90,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;
+5 -4
View File
@@ -1,4 +1,5 @@
using UnityExplorer.UI; using UnityExplorer.UI;
using UnityExplorer.UI.Panels;
namespace UnityExplorer.Config namespace UnityExplorer.Config
{ {
@@ -31,7 +32,7 @@ namespace UnityExplorer.Config
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> Default_Gameplay_Freecam; public static ConfigElement<FreeCamPanel.FreeCameraType> Default_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;
@@ -185,9 +186,9 @@ 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", Default_Freecam = new("Default Freecam mode",
"Turn this on if you want the default gameplay freecam toggle on the Freecam panel to be on on startup.", "Default type of freecam selected on startup.",
false); FreeCamPanel.FreeCameraType.New);
Pause = new("Pause", Pause = new("Pause",
"Toggle the pause of the game.", "Toggle the pause of the game.",
+3 -3
View File
@@ -107,7 +107,7 @@ 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.OnClick += StartButton_OnClick; startButton.OnClick += StartButton_OnClick;
@@ -115,7 +115,7 @@ namespace UnityExplorer.UI.Panels
UIFactory.SetLayoutElement(pauseContinueButton.GameObject, minWidth: 50, minHeight: 25); UIFactory.SetLayoutElement(pauseContinueButton.GameObject, minWidth: 50, minHeight: 25);
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;
@@ -364,7 +364,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);
+381 -74
View File
@@ -18,6 +18,13 @@ namespace UnityExplorer.UI.Panels
{ {
public class FreeCamPanel : UEPanel public class FreeCamPanel : UEPanel
{ {
public enum FreeCameraType {
New,
Gameplay,
Cloned,
ForcedMatrix,
}
public FreeCamPanel(UIBase owner) : base(owner) public FreeCamPanel(UIBase owner) : base(owner)
{ {
try { try {
@@ -38,9 +45,9 @@ namespace UnityExplorer.UI.Panels
public override bool ShouldSaveActiveState => true; public override bool ShouldSaveActiveState => true;
internal static bool inFreeCamMode; internal static bool inFreeCamMode;
internal static bool usingGameCamera;
public static Camera ourCamera; public static Camera ourCamera;
public static Camera lastMainCamera; public static Camera lastMainCamera;
public static Camera cameraMatrixOverrider;
internal static FreeCamBehaviour freeCamScript; internal static FreeCamBehaviour freeCamScript;
internal static CatmullRom.CatmullRomMover cameraPathMover; internal static CatmullRom.CatmullRomMover cameraPathMover;
@@ -53,13 +60,15 @@ namespace UnityExplorer.UI.Panels
internal static Vector3? currentUserCameraPosition; internal static Vector3? currentUserCameraPosition;
internal static Quaternion? currentUserCameraRotation; internal static Quaternion? currentUserCameraRotation;
internal static float currentUserCameraFov;
internal static Vector3 previousMousePosition; internal static Vector3 previousMousePosition;
internal static Vector3 lastSetCameraPosition; internal static Vector3 lastSetCameraPosition;
static ButtonRef startStopButton; static ButtonRef startStopButton;
public static Toggle useGameCameraToggle; public static Dropdown cameraTypeDropdown;
internal static FreeCameraType currentCameraType;
public static Toggle blockFreecamMovementToggle; public static Toggle blockFreecamMovementToggle;
public static Toggle blockGamesInputOnFreecamToggle; public static Toggle blockGamesInputOnFreecamToggle;
static InputFieldRef positionInput; static InputFieldRef positionInput;
@@ -119,6 +128,7 @@ namespace UnityExplorer.UI.Panels
{ {
currentUserCameraPosition = currentMain.transform.position; currentUserCameraPosition = currentMain.transform.position;
currentUserCameraRotation = currentMain.transform.rotation; currentUserCameraRotation = currentMain.transform.rotation;
currentUserCameraFov = currentMain.fieldOfView;
} }
} }
else else
@@ -127,38 +137,90 @@ namespace UnityExplorer.UI.Panels
static void SetupFreeCamera() static void SetupFreeCamera()
{ {
if (useGameCameraToggle.isOn) switch ((FreeCameraType)cameraTypeDropdown.value)
{ {
if (!lastMainCamera) case FreeCameraType.Gameplay:
{ if (!lastMainCamera)
ExplorerCore.LogWarning($"There is no previous Camera found, reverting to default Free Cam."); {
useGameCameraToggle.isOn = false; ExplorerCore.LogWarning($"There is no previous Camera found, reverting to New Free Cam.");
} cameraTypeDropdown.value = (int)FreeCameraType.New;
else
{
usingGameCamera = true;
ourCamera = lastMainCamera;
MaybeToggleCinemachine(false);
// If the farClipPlaneValue is the default one try to use the one from the gameplay camera
if (farClipPlaneValue == 2000){
farClipPlaneValue = ourCamera.farClipPlane;
farClipPlaneInput.Text = farClipPlaneValue.ToString();
// Let the default farClipPlane value exceed the slider max value
if (farClipPlaneValue <= farClipPlaneSlider.maxValue)
farClipPlaneSlider.value = farClipPlaneValue;
} }
} else
} {
currentCameraType = FreeCameraType.Gameplay;
if (!useGameCameraToggle.isOn) ourCamera = lastMainCamera;
{ MaybeToggleCinemachine(false);
usingGameCamera = false;
// If the farClipPlaneValue is the default one try to use the one from the gameplay camera
if (lastMainCamera) if (farClipPlaneValue == 2000){
lastMainCamera.enabled = false; farClipPlaneValue = ourCamera.farClipPlane;
farClipPlaneInput.Text = farClipPlaneValue.ToString();
// Let the default farClipPlane value exceed the slider max value
if (farClipPlaneValue <= farClipPlaneSlider.maxValue)
farClipPlaneSlider.value = farClipPlaneValue;
}
}
break;
case FreeCameraType.New:
currentCameraType = FreeCameraType.New;
if (lastMainCamera){
lastMainCamera.enabled = false;
}
ourCamera = new GameObject("UE_Freecam").AddComponent<Camera>();
ourCamera.gameObject.tag = "MainCamera";
GameObject.DontDestroyOnLoad(ourCamera.gameObject);
ourCamera.gameObject.hideFlags = HideFlags.HideAndDontSave;
break;
case FreeCameraType.Cloned:
if (!lastMainCamera)
{
ExplorerCore.LogWarning($"There is no previous Camera found, reverting to New Free Cam.");
cameraTypeDropdown.value = (int)FreeCameraType.New;
} else {
currentCameraType = FreeCameraType.Cloned;
ourCamera = GameObject.Instantiate(lastMainCamera);
lastMainCamera.enabled = false;
MaybeToggleCinemachine(false);
// If the farClipPlaneValue is the default one try to use the one from the gameplay camera
if (farClipPlaneValue == 2000){
farClipPlaneValue = ourCamera.farClipPlane;
farClipPlaneInput.Text = farClipPlaneValue.ToString();
// Let the default farClipPlane value exceed the slider max value
if (farClipPlaneValue <= farClipPlaneSlider.maxValue)
farClipPlaneSlider.value = farClipPlaneValue;
}
}
break;
case FreeCameraType.ForcedMatrix:
if (!lastMainCamera)
{
ExplorerCore.LogWarning($"There is no previous Camera found, reverting to New Free Cam.");
cameraTypeDropdown.value = (int)FreeCameraType.New;
} else {
currentCameraType = FreeCameraType.ForcedMatrix;
ourCamera = lastMainCamera;
// HDRP might introduce problems when moving the camera when replacing the worldToCameraMatrix,
// so we will try to move the real camera as well.
MaybeToggleCinemachine(false);
cameraMatrixOverrider = new GameObject("[CUE] Camera Matrix Overrider").AddComponent<Camera>();
cameraMatrixOverrider.enabled = false;
cameraMatrixOverrider.transform.position = lastMainCamera.transform.position;
cameraMatrixOverrider.transform.rotation = lastMainCamera.transform.rotation;
}
break;
default:
ExplorerCore.LogWarning($"Error: Camera type not implemented");
break;
} }
// Fallback in case we couldn't find the main camera for some reason
if (!ourCamera) if (!ourCamera)
{ {
ourCamera = new GameObject("UE_Freecam").AddComponent<Camera>(); ourCamera = new GameObject("UE_Freecam").AddComponent<Camera>();
@@ -173,8 +235,9 @@ namespace UnityExplorer.UI.Panels
if (!cameraPathMover) if (!cameraPathMover)
cameraPathMover = ourCamera.gameObject.AddComponent<CatmullRom.CatmullRomMover>(); cameraPathMover = ourCamera.gameObject.AddComponent<CatmullRom.CatmullRomMover>();
ourCamera.transform.position = (Vector3)currentUserCameraPosition; GetFreecam().transform.position = (Vector3)currentUserCameraPosition;
ourCamera.transform.rotation = (Quaternion)currentUserCameraRotation; GetFreecam().transform.rotation = (Quaternion)currentUserCameraRotation;
SetFOV(currentUserCameraFov);
ourCamera.gameObject.SetActive(true); ourCamera.gameObject.SetActive(true);
ourCamera.enabled = true; ourCamera.enabled = true;
@@ -191,18 +254,41 @@ namespace UnityExplorer.UI.Panels
inFreeCamMode = false; inFreeCamMode = false;
connector?.UpdateFreecamStatus(false); connector?.UpdateFreecamStatus(false);
if (usingGameCamera) switch(currentCameraType) {
{ case FreeCameraType.Gameplay:
MaybeToggleCinemachine(true);
ourCamera = null;
MaybeToggleCinemachine(true); if (lastMainCamera)
ourCamera = null; {
lastMainCamera.transform.position = originalCameraPosition;
lastMainCamera.transform.rotation = originalCameraRotation;
lastMainCamera.fieldOfView = originalCameraFOV;
}
break;
case FreeCameraType.New:
GameObject.Destroy(ourCamera.gameObject);
ourCamera = null;
break;
case FreeCameraType.Cloned:
GameObject.Destroy(ourCamera.gameObject);
ourCamera = null;
break;
case FreeCameraType.ForcedMatrix:
MaybeToggleCinemachine(true);
MethodInfo resetCullingMatrixMethod = typeof(Camera).GetMethod("ResetCullingMatrix", new Type[] {});
resetCullingMatrixMethod.Invoke(ourCamera, null);
if (lastMainCamera) ourCamera.ResetWorldToCameraMatrix();
{ ourCamera.ResetProjectionMatrix();
lastMainCamera.transform.position = originalCameraPosition; ourCamera = null;
lastMainCamera.transform.rotation = originalCameraRotation;
lastMainCamera.fieldOfView = originalCameraFOV; GameObject.Destroy(cameraMatrixOverrider.gameObject);
} cameraMatrixOverrider = null;
break;
default:
ExplorerCore.LogWarning($"Error: Camera type not implemented");
break;
} }
if (ourCamera) if (ourCamera)
@@ -271,7 +357,7 @@ namespace UnityExplorer.UI.Panels
if (connector != null && connector.IsActive) if (connector != null && connector.IsActive)
return; return;
lastSetCameraPosition = ourCamera.transform.position; lastSetCameraPosition = GetFreecam().transform.position;
positionInput.Text = ParseUtility.ToStringForInput<Vector3>(lastSetCameraPosition); positionInput.Text = ParseUtility.ToStringForInput<Vector3>(lastSetCameraPosition);
} }
@@ -280,6 +366,11 @@ namespace UnityExplorer.UI.Panels
ourCamera.nearClipPlane = nearClipPlaneValue; ourCamera.nearClipPlane = nearClipPlaneValue;
ourCamera.farClipPlane = farClipPlaneValue; ourCamera.farClipPlane = farClipPlaneValue;
} }
if (cameraMatrixOverrider) {
cameraMatrixOverrider.nearClipPlane = nearClipPlaneValue;
cameraMatrixOverrider.farClipPlane = farClipPlaneValue;
}
} }
// ~~~~~~~~ UI construction / callbacks ~~~~~~~~ // ~~~~~~~~ UI construction / callbacks ~~~~~~~~
@@ -293,11 +384,22 @@ namespace UnityExplorer.UI.Panels
AddSpacer(5); AddSpacer(5);
GameObject toggleObj = UIFactory.CreateToggle(ContentRoot, "UseGameCameraToggle", out useGameCameraToggle, out Text useGameCameraText); GameObject CameraModeRow = UIFactory.CreateHorizontalGroup(ContentRoot, "CameraModeRow", false, false, true, true, 3, default, new(1, 1, 1, 0));
UIFactory.SetLayoutElement(toggleObj, minHeight: 25, flexibleWidth: 9999);
useGameCameraToggle.onValueChanged.AddListener(OnUseGameCameraToggled); Text CameraMode = UIFactory.CreateLabel(CameraModeRow, "Camera Mode", "Camera Mode:");
useGameCameraToggle.isOn = ConfigManager.Default_Gameplay_Freecam.Value; UIFactory.SetLayoutElement(CameraMode.gameObject, minWidth: 100, minHeight: 25);
useGameCameraText.text = "Use Game Camera?";
GameObject cameraTypeDropdownObj = UIFactory.CreateDropdown(CameraModeRow, "CameraType_Dropdown", out cameraTypeDropdown, null, 14, (idx) => {
if (inFreeCamMode) {
EndFreecam();
BeginFreecam();
}
});
foreach (FreeCameraType type in Enum.GetValues(typeof(FreeCameraType)).Cast<FreeCameraType>()) {
cameraTypeDropdown.options.Add(new Dropdown.OptionData(Enum.GetName(typeof(FreeCameraType), type)));
}
UIFactory.SetLayoutElement(cameraTypeDropdownObj, minHeight: 25, minWidth: 150);
cameraTypeDropdown.value = (int)ConfigManager.Default_Freecam.Value;
AddSpacer(5); AddSpacer(5);
@@ -616,54 +718,67 @@ namespace UnityExplorer.UI.Panels
return inFreeCamMode && blockGamesInputOnFreecamToggle.isOn; return inFreeCamMode && blockGamesInputOnFreecamToggle.isOn;
} }
public static Camera GetFreecam(){
if (currentCameraType == FreeCameraType.ForcedMatrix) return cameraMatrixOverrider;
return ourCamera;
}
// Getters and Setters for camera position and rotation // Getters and Setters for camera position and rotation
public static Vector3 GetCameraPosition(bool isAbsolute = false){ public static Vector3 GetCameraPosition(bool isAbsolute = false){
if (isAbsolute) return ourCamera.transform.position; Camera freecam = GetFreecam();
if (isAbsolute) return freecam.transform.position;
if (followObject){ if (followObject){
if (followRotationToggle.isOn){ if (followRotationToggle.isOn){
return Quaternion.Inverse(followObject.transform.rotation) * (ourCamera.transform.position - followObject.transform.position); return Quaternion.Inverse(followObject.transform.rotation) * (freecam.transform.position - followObject.transform.position);
} }
else { else {
return ourCamera.transform.position - followObject.transform.position; return freecam.transform.position - followObject.transform.position;
} }
} }
return ourCamera.transform.position; return freecam.transform.position;
} }
public static Quaternion GetCameraRotation(bool isAbsolute = false){ public static Quaternion GetCameraRotation(bool isAbsolute = false){
if (isAbsolute) return ourCamera.transform.rotation; Camera freecam = GetFreecam();
if (followObject && followRotationToggle.isOn) return Quaternion.Inverse(followObjectLastRotation) * ourCamera.transform.rotation; if (isAbsolute) return freecam.transform.rotation;
return ourCamera.transform.rotation; if (followObject && followRotationToggle.isOn) return Quaternion.Inverse(followObjectLastRotation) * freecam.transform.rotation;
return freecam.transform.rotation;
} }
public static void SetCameraPosition(Vector3 newPosition, bool isAbsolute = false){ public static void SetCameraPosition(Vector3 newPosition, bool isAbsolute = false){
Camera freecam = GetFreecam();
if (isAbsolute){ if (isAbsolute){
ourCamera.transform.position = newPosition; freecam.transform.position = newPosition;
} }
else if (followObject){ else if (followObject){
if (followRotationToggle.isOn){ if (followRotationToggle.isOn){
ourCamera.transform.position = followObject.transform.rotation * newPosition + followObject.transform.position; freecam.transform.position = followObject.transform.rotation * newPosition + followObject.transform.position;
} }
else { else {
ourCamera.transform.position = newPosition + followObject.transform.position; freecam.transform.position = newPosition + followObject.transform.position;
} }
} }
else { else {
ourCamera.transform.position = newPosition; freecam.transform.position = newPosition;
} }
} }
public static void SetCameraRotation(Quaternion newRotation, bool isAbsolute = false){ public static void SetCameraRotation(Quaternion newRotation, bool isAbsolute = false){
Camera freecam = GetFreecam();
if (isAbsolute){ if (isAbsolute){
ourCamera.transform.rotation = newRotation; freecam.transform.rotation = newRotation;
} }
else if (followObject && followRotationToggle.isOn){ else if (followObject && followRotationToggle.isOn){
ourCamera.transform.rotation = followObjectLastRotation * newRotation; freecam.transform.rotation = followObjectLastRotation * newRotation;
} }
else { else {
ourCamera.transform.rotation = newRotation; freecam.transform.rotation = newRotation;
} }
} }
public static void SetFOV(float newFOV){
GetFreecam().fieldOfView = newFOV;
}
} }
internal class FreeCamBehaviour : MonoBehaviour internal class FreeCamBehaviour : MonoBehaviour
@@ -676,6 +791,9 @@ namespace UnityExplorer.UI.Panels
public FreeCamBehaviour(IntPtr ptr) : base(ptr) { } public FreeCamBehaviour(IntPtr ptr) : base(ptr) { }
#endif #endif
private Action onBeforeRenderAction;
private Vector3 cachedPosition;
private Quaternion cachedRotation;
internal void Update() internal void Update()
{ {
@@ -686,35 +804,88 @@ namespace UnityExplorer.UI.Panels
FreeCamPanel.EndFreecam(); FreeCamPanel.EndFreecam();
return; return;
} }
Transform transform = FreeCamPanel.ourCamera.transform; Transform movingTransform = FreeCamPanel.GetFreecam().transform;
if (!FreeCamPanel.blockFreecamMovementToggle.isOn && !FreeCamPanel.cameraPathMover.playingPath && FreeCamPanel.connector?.IsActive != true) { if (!FreeCamPanel.blockFreecamMovementToggle.isOn && !FreeCamPanel.cameraPathMover.playingPath && FreeCamPanel.connector?.IsActive != true) {
ProcessInput(); ProcessInput(movingTransform);
} }
if (FreeCamPanel.followObject != null){ if (FreeCamPanel.followObject != null){
// position update // position update
transform.position += FreeCamPanel.followObject.transform.position - FreeCamPanel.followObjectLastPosition; movingTransform.position += FreeCamPanel.followObject.transform.position - FreeCamPanel.followObjectLastPosition;
if (FreeCamPanel.followRotationToggle.isOn){ if (FreeCamPanel.followRotationToggle.isOn){
// rotation update // rotation update
Quaternion deltaRotation = FreeCamPanel.followObject.transform.rotation * Quaternion.Inverse(FreeCamPanel.followObjectLastRotation); Quaternion deltaRotation = FreeCamPanel.followObject.transform.rotation * Quaternion.Inverse(FreeCamPanel.followObjectLastRotation);
Vector3 offset = transform.position - FreeCamPanel.followObject.transform.position; Vector3 offset = movingTransform.position - FreeCamPanel.followObject.transform.position;
transform.position = transform.position - offset + deltaRotation * offset; movingTransform.position = movingTransform.position - offset + deltaRotation * offset;
transform.rotation = deltaRotation * transform.rotation; movingTransform.rotation = deltaRotation * movingTransform.rotation;
} }
FreeCamPanel.followObjectLastPosition = FreeCamPanel.followObject.transform.position; FreeCamPanel.followObjectLastPosition = FreeCamPanel.followObject.transform.position;
FreeCamPanel.followObjectLastRotation = FreeCamPanel.followObject.transform.rotation; FreeCamPanel.followObjectLastRotation = FreeCamPanel.followObject.transform.rotation;
} }
FreeCamPanel.connector?.ExecuteCameraCommand(FreeCamPanel.ourCamera); UpdateRelativeMatrix();
UpdateRealCamera();
FreeCamPanel.connector?.ExecuteCameraCommand(FreeCamPanel.GetFreecam());
FreeCamPanel.UpdatePositionInput(); FreeCamPanel.UpdatePositionInput();
} }
} }
internal void ProcessInput(){ private void OnPreCull()
{
UpdateRelativeMatrix();
UpdateRealCamera();
}
private void OnPreRender()
{
UpdateRelativeMatrix();
UpdateRealCamera();
}
private void OnCameraPostRender()
{
UpdateRelativeMatrix();
//RestoreRealCameraTransform();
}
private void LateUpdate()
{
UpdateRelativeMatrix();
//RestoreRealCameraTransform();
}
internal void UpdateRelativeMatrix() {
if (FreeCamPanel.cameraMatrixOverrider != null){
try
{
MethodInfo getStereoViewMatrixMethod = typeof(Camera).GetMethod("GetStereoViewMatrix");
Matrix4x4 stereoViewMatrixOverrider = getStereoViewMatrixMethod.Invoke(FreeCamPanel.cameraMatrixOverrider, new object[] {0}).TryCast<Matrix4x4>();
MethodInfo setStereoViewMatrixMethod = typeof(Camera).GetMethod("SetStereoViewMatrix");
setStereoViewMatrixMethod.Invoke(FreeCamPanel.ourCamera, new object[] {0, stereoViewMatrixOverrider});
}
catch (Exception ex) {
ExplorerCore.LogWarning(ex);
}
FreeCamPanel.ourCamera.worldToCameraMatrix = FreeCamPanel.cameraMatrixOverrider.worldToCameraMatrix;
// Maybe I should use nonJitteredProjectionMatrix instead
FreeCamPanel.ourCamera.projectionMatrix = FreeCamPanel.cameraMatrixOverrider.projectionMatrix;
// Could be optimized so to not look up cullingMatrixProperty each frame
PropertyInfo cullingMatrixProperty = typeof(Camera).GetProperty("cullingMatrix");
Matrix4x4 cullingMatrixOverrider = cullingMatrixProperty.GetValue(FreeCamPanel.cameraMatrixOverrider, null).TryCast<Matrix4x4>();
MethodInfo setCullingMatrixMethod = cullingMatrixProperty.GetSetMethod();
setCullingMatrixMethod.Invoke(FreeCamPanel.ourCamera, new object[] {cullingMatrixOverrider});
}
}
internal void ProcessInput(Transform transform){
FreeCamPanel.currentUserCameraPosition = transform.position; FreeCamPanel.currentUserCameraPosition = transform.position;
FreeCamPanel.currentUserCameraRotation = transform.rotation; FreeCamPanel.currentUserCameraRotation = transform.rotation;
@@ -793,20 +964,156 @@ namespace UnityExplorer.UI.Panels
if (IInputManager.GetKey(ConfigManager.Decrease_FOV.Value)) if (IInputManager.GetKey(ConfigManager.Decrease_FOV.Value))
{ {
FreeCamPanel.ourCamera.fieldOfView -= moveSpeed; FreeCamPanel.GetFreecam().fieldOfView -= moveSpeed;
} }
if (IInputManager.GetKey(ConfigManager.Increase_FOV.Value)) if (IInputManager.GetKey(ConfigManager.Increase_FOV.Value))
{ {
FreeCamPanel.ourCamera.fieldOfView += moveSpeed; FreeCamPanel.GetFreecam().fieldOfView += moveSpeed;
} }
if (IInputManager.GetKey(ConfigManager.Reset_FOV.Value)){ if (IInputManager.GetKey(ConfigManager.Reset_FOV.Value)){
FreeCamPanel.ourCamera.fieldOfView = FreeCamPanel.usingGameCamera ? FreeCamPanel.originalCameraFOV : 60; FreeCamPanel.GetFreecam().fieldOfView = FreeCamPanel.currentCameraType == FreeCamPanel.FreeCameraType.New ? 60 : FreeCamPanel.originalCameraFOV;
} }
FreeCamPanel.previousMousePosition = IInputManager.MousePosition; FreeCamPanel.previousMousePosition = IInputManager.MousePosition;
} }
// The following code forces the freecamcam to update before rendering a frame
protected virtual void Awake()
{
onBeforeRenderAction = () => { UpdateRelativeMatrix(); UpdateRealCamera(); };
}
protected virtual void OnEnable()
{
#if CPP
try
{
Application.add_onBeforeRender(onBeforeRenderAction);
}
catch (Exception exception)
{
ExplorerCore.LogWarning($"Failed to listen to BeforeRender: {exception}");
}
#endif
// These doesn't exist for Unity <2017 nor when using HDRP
Type renderPipelineManagerType = ReflectionUtility.GetTypeByName("RenderPipelineManager");
if (renderPipelineManagerType != null){
EventInfo beginFrameRenderingEvent = renderPipelineManagerType.GetEvent("beginFrameRendering");
if (beginFrameRenderingEvent != null) {
beginFrameRenderingEvent.AddEventHandler(null, OnBeforeEvent);
}
EventInfo endFrameRenderingEvent = renderPipelineManagerType.GetEvent("endFrameRendering");
if (endFrameRenderingEvent != null) {
endFrameRenderingEvent.AddEventHandler(null, OnAfterEvent);
}
EventInfo beginCameraRenderingEvent = renderPipelineManagerType.GetEvent("beginCameraRendering");
if (beginCameraRenderingEvent != null) {
beginCameraRenderingEvent.AddEventHandler(null, OnBeforeEvent);
}
EventInfo endCameraRenderingEvent = renderPipelineManagerType.GetEvent("endCameraRendering");
if (endCameraRenderingEvent != null) {
endCameraRenderingEvent.AddEventHandler(null, OnAfterEvent);
}
EventInfo beginContextRenderingEvent = renderPipelineManagerType.GetEvent("beginContextRendering");
if (beginContextRenderingEvent != null) {
beginContextRenderingEvent.AddEventHandler(null, OnBeforeEvent);
}
EventInfo endContextRenderingEvent = renderPipelineManagerType.GetEvent("endContextRendering");
if (endContextRenderingEvent != null) {
endContextRenderingEvent.AddEventHandler(null, OnAfterEvent);
}
}
EventInfo onBeforeRenderEvent = typeof(Application).GetEvent("onBeforeRender");
if (onBeforeRenderEvent != null) {
onBeforeRenderEvent.AddEventHandler(null, onBeforeRenderAction);
}
}
protected virtual void OnDisable()
{
#if CPP
try
{
Application.remove_onBeforeRender(onBeforeRenderAction);
}
catch (Exception exception)
{
ExplorerCore.LogWarning($"Failed to unlisten from BeforeRender: {exception}");
}
#endif
// These doesn't exist for Unity <2017 nor when using HDRP
Type renderPipelineManagerType = ReflectionUtility.GetTypeByName("RenderPipelineManager");
if (renderPipelineManagerType != null){
EventInfo beginFrameRenderingEvent = renderPipelineManagerType.GetEvent("beginFrameRendering");
if (beginFrameRenderingEvent != null) {
beginFrameRenderingEvent.RemoveEventHandler(null, OnBeforeEvent);
}
EventInfo endFrameRenderingEvent = renderPipelineManagerType.GetEvent("endFrameRendering");
if (endFrameRenderingEvent != null) {
endFrameRenderingEvent.RemoveEventHandler(null, OnAfterEvent);
}
EventInfo beginCameraRenderingEvent = renderPipelineManagerType.GetEvent("beginCameraRendering");
if (beginCameraRenderingEvent != null) {
beginCameraRenderingEvent.RemoveEventHandler(null, OnBeforeEvent);
}
EventInfo endCameraRenderingEvent = renderPipelineManagerType.GetEvent("endCameraRendering");
if (endCameraRenderingEvent != null) {
endCameraRenderingEvent.RemoveEventHandler(null, OnAfterEvent);
}
EventInfo beginContextRenderingEvent = renderPipelineManagerType.GetEvent("beginContextRendering");
if (beginContextRenderingEvent != null) {
beginContextRenderingEvent.RemoveEventHandler(null, OnBeforeEvent);
}
EventInfo endContextRenderingEvent = renderPipelineManagerType.GetEvent("endContextRendering");
if (endContextRenderingEvent != null) {
endContextRenderingEvent.RemoveEventHandler(null, OnAfterEvent);
}
}
EventInfo onBeforeRenderEvent = typeof(Application).GetEvent("onBeforeRender");
if (onBeforeRenderEvent != null) {
onBeforeRenderEvent.RemoveEventHandler(null, onBeforeRenderAction);
}
}
private void OnBeforeEvent(object arg1, Camera[] arg2)
{
UpdateRelativeMatrix();
UpdateRealCamera();
}
private void OnAfterEvent(object arg1, Camera[] arg2)
{
UpdateRelativeMatrix();
//RestoreRealCameraTransform();
}
// HDRP matrix override ignores us moving the camera unfortunately, so we try to copy over the position of the camera matrix overrider.
protected void UpdateRealCamera() {
if (FreeCamPanel.cameraMatrixOverrider != null) {
cachedPosition = FreeCamPanel.ourCamera.transform.position;
FreeCamPanel.ourCamera.transform.position = FreeCamPanel.cameraMatrixOverrider.transform.position;
// We also try to update the rotation in case there are game shaders that use the real camera rotation
cachedRotation = FreeCamPanel.ourCamera.transform.rotation;
FreeCamPanel.ourCamera.transform.rotation = FreeCamPanel.cameraMatrixOverrider.transform.rotation;
}
}
protected void RestoreRealCameraTransform() {
if (FreeCamPanel.cameraMatrixOverrider != null) {
FreeCamPanel.ourCamera.transform.position = cachedPosition;
FreeCamPanel.ourCamera.transform.rotation = cachedRotation;
}
UpdateRealCamera();
}
} }
// Dummy UI class to unlock the cursor when freecam is active but the UI is hidden // Dummy UI class to unlock the cursor when freecam is active but the UI is hidden
+3 -3
View File
@@ -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)