From 7d0aa1bf36bf640268374675be77207a2aeaa713 Mon Sep 17 00:00:00 2001 From: Anton Siebert Date: Wed, 29 Jul 2026 01:46:02 +0200 Subject: [PATCH 01/16] #922 implementation of cinemachine-structure components to provide better means for video recording; includes all changes made for bachelor-thesis --- Assets/Cinemachines.meta | 8 + .../CinemachinesMainOutput.renderTexture | 39 + .../CinemachinesMainOutput.renderTexture.meta | 8 + .../CinemachinesPIPOutput.renderTexture | 39 + .../CinemachinesPIPOutput.renderTexture.meta | 8 + Assets/Cinemachines/Scenes.meta | 8 + Assets/Resources/Prefabs/Cinemachines.meta | 8 + .../Cinemachines/CinemachinesRoot.meta | 8 + .../CinemachinesBrains.prefab | 375 +++++++++ .../CinemachinesBrains.prefab.meta | 7 + .../CinemachinesRoot/ControlCamera.prefab | 160 ++++ .../ControlCamera.prefab.meta | 7 + .../Prefabs/Cinemachines/SceneTemplate.prefab | 223 ++++++ .../Cinemachines/SceneTemplate.prefab.meta | 7 + .../Prefabs/Players/DesktopPlayer.prefab | 44 + Assets/Resources/UI.meta | 8 + Assets/Resources/UI/Cinemachines.meta | 8 + .../UI/Cinemachines/ControlCamera.asset | 50 ++ .../UI/Cinemachines/ControlCamera.asset.meta | 8 + .../ControlCameraDataSource.asset | 16 + .../ControlCameraDataSource.asset.meta | 8 + .../UI/Cinemachines/ControlCameraView.uxml | 7 + .../Cinemachines/ControlCameraView.uxml.meta | 10 + Assets/Resources/UI/PictureInPicture.meta | 8 + .../UI/PictureInPicture/RenderTextures.meta | 8 + .../RenderTextures/rtpip_blank.renderTexture | 39 + .../rtpip_blank.renderTexture.meta | 8 + .../UI/PictureInPicture/pip-camera.uxml | 13 + .../UI/PictureInPicture/pip-camera.uxml.meta | 10 + .../Resources/UI/PictureInPicture/pip.asset | 50 ++ .../UI/PictureInPicture/pip.asset.meta | 8 + .../UI/PictureInPicture/pipDataSource.asset | 16 + .../PictureInPicture/pipDataSource.asset.meta | 8 + .../Resources/UI/UnityDefaultRuntimeTheme.tss | 2 + .../UI/UnityDefaultRuntimeTheme.tss.meta | 11 + Assets/SEE/Cinemachines.meta | 8 + .../SEE/Cinemachines/CinemachineSceneRoot.cs | 369 +++++++++ .../Cinemachines/CinemachineSceneRoot.cs.meta | 2 + Assets/SEE/Cinemachines/Cinemachines.cs | 7 + Assets/SEE/Cinemachines/Cinemachines.cs.meta | 2 + Assets/SEE/Cinemachines/CinemachinesRoot.cs | 402 ++++++++++ .../SEE/Cinemachines/CinemachinesRoot.cs.meta | 2 + Assets/SEE/Cinemachines/Dolly.meta | 8 + Assets/SEE/Cinemachines/Dolly/Dolly.cs | 6 + Assets/SEE/Cinemachines/Dolly/Dolly.cs.meta | 2 + .../Dolly/SimpleSpeedController.cs | 135 ++++ .../Dolly/SimpleSpeedController.cs.meta | 2 + Assets/SEE/Cinemachines/Utility.meta | 8 + .../Utility/CinemachinesUtility.cs | 755 ++++++++++++++++++ .../Utility/CinemachinesUtility.cs.meta | 2 + Assets/SEE/Cinemachines/Utility/Utility.cs | 7 + .../SEE/Cinemachines/Utility/Utility.cs.meta | 2 + Assets/SEE/SEE.asmdef | 8 +- Assets/SEE/UI/PictureInPicture.meta | 8 + .../UI/PictureInPicture/PictureInPicture.cs | 7 + .../PictureInPicture/PictureInPicture.cs.meta | 2 + .../SEE/UI/PictureInPicture/pipDataSource.cs | 26 + .../UI/PictureInPicture/pipDataSource.cs.meta | 2 + Packages/manifest.json | 1 + Packages/packages-lock.json | 21 + 60 files changed, 3038 insertions(+), 1 deletion(-) create mode 100644 Assets/Cinemachines.meta create mode 100644 Assets/Cinemachines/CinemachinesMainOutput.renderTexture create mode 100644 Assets/Cinemachines/CinemachinesMainOutput.renderTexture.meta create mode 100644 Assets/Cinemachines/CinemachinesPIPOutput.renderTexture create mode 100644 Assets/Cinemachines/CinemachinesPIPOutput.renderTexture.meta create mode 100644 Assets/Cinemachines/Scenes.meta create mode 100644 Assets/Resources/Prefabs/Cinemachines.meta create mode 100644 Assets/Resources/Prefabs/Cinemachines/CinemachinesRoot.meta create mode 100644 Assets/Resources/Prefabs/Cinemachines/CinemachinesRoot/CinemachinesBrains.prefab create mode 100644 Assets/Resources/Prefabs/Cinemachines/CinemachinesRoot/CinemachinesBrains.prefab.meta create mode 100644 Assets/Resources/Prefabs/Cinemachines/CinemachinesRoot/ControlCamera.prefab create mode 100644 Assets/Resources/Prefabs/Cinemachines/CinemachinesRoot/ControlCamera.prefab.meta create mode 100644 Assets/Resources/Prefabs/Cinemachines/SceneTemplate.prefab create mode 100644 Assets/Resources/Prefabs/Cinemachines/SceneTemplate.prefab.meta create mode 100644 Assets/Resources/UI.meta create mode 100644 Assets/Resources/UI/Cinemachines.meta create mode 100644 Assets/Resources/UI/Cinemachines/ControlCamera.asset create mode 100644 Assets/Resources/UI/Cinemachines/ControlCamera.asset.meta create mode 100644 Assets/Resources/UI/Cinemachines/ControlCameraDataSource.asset create mode 100644 Assets/Resources/UI/Cinemachines/ControlCameraDataSource.asset.meta create mode 100644 Assets/Resources/UI/Cinemachines/ControlCameraView.uxml create mode 100644 Assets/Resources/UI/Cinemachines/ControlCameraView.uxml.meta create mode 100644 Assets/Resources/UI/PictureInPicture.meta create mode 100644 Assets/Resources/UI/PictureInPicture/RenderTextures.meta create mode 100644 Assets/Resources/UI/PictureInPicture/RenderTextures/rtpip_blank.renderTexture create mode 100644 Assets/Resources/UI/PictureInPicture/RenderTextures/rtpip_blank.renderTexture.meta create mode 100644 Assets/Resources/UI/PictureInPicture/pip-camera.uxml create mode 100644 Assets/Resources/UI/PictureInPicture/pip-camera.uxml.meta create mode 100644 Assets/Resources/UI/PictureInPicture/pip.asset create mode 100644 Assets/Resources/UI/PictureInPicture/pip.asset.meta create mode 100644 Assets/Resources/UI/PictureInPicture/pipDataSource.asset create mode 100644 Assets/Resources/UI/PictureInPicture/pipDataSource.asset.meta create mode 100644 Assets/Resources/UI/UnityDefaultRuntimeTheme.tss create mode 100644 Assets/Resources/UI/UnityDefaultRuntimeTheme.tss.meta create mode 100644 Assets/SEE/Cinemachines.meta create mode 100644 Assets/SEE/Cinemachines/CinemachineSceneRoot.cs create mode 100644 Assets/SEE/Cinemachines/CinemachineSceneRoot.cs.meta create mode 100644 Assets/SEE/Cinemachines/Cinemachines.cs create mode 100644 Assets/SEE/Cinemachines/Cinemachines.cs.meta create mode 100644 Assets/SEE/Cinemachines/CinemachinesRoot.cs create mode 100644 Assets/SEE/Cinemachines/CinemachinesRoot.cs.meta create mode 100644 Assets/SEE/Cinemachines/Dolly.meta create mode 100644 Assets/SEE/Cinemachines/Dolly/Dolly.cs create mode 100644 Assets/SEE/Cinemachines/Dolly/Dolly.cs.meta create mode 100644 Assets/SEE/Cinemachines/Dolly/SimpleSpeedController.cs create mode 100644 Assets/SEE/Cinemachines/Dolly/SimpleSpeedController.cs.meta create mode 100644 Assets/SEE/Cinemachines/Utility.meta create mode 100644 Assets/SEE/Cinemachines/Utility/CinemachinesUtility.cs create mode 100644 Assets/SEE/Cinemachines/Utility/CinemachinesUtility.cs.meta create mode 100644 Assets/SEE/Cinemachines/Utility/Utility.cs create mode 100644 Assets/SEE/Cinemachines/Utility/Utility.cs.meta create mode 100644 Assets/SEE/UI/PictureInPicture.meta create mode 100644 Assets/SEE/UI/PictureInPicture/PictureInPicture.cs create mode 100644 Assets/SEE/UI/PictureInPicture/PictureInPicture.cs.meta create mode 100644 Assets/SEE/UI/PictureInPicture/pipDataSource.cs create mode 100644 Assets/SEE/UI/PictureInPicture/pipDataSource.cs.meta diff --git a/Assets/Cinemachines.meta b/Assets/Cinemachines.meta new file mode 100644 index 0000000000..2d7b2beab5 --- /dev/null +++ b/Assets/Cinemachines.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4a5f9535e90ca639da1563171160cfe7 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Cinemachines/CinemachinesMainOutput.renderTexture b/Assets/Cinemachines/CinemachinesMainOutput.renderTexture new file mode 100644 index 0000000000..c57bfb0c75 --- /dev/null +++ b/Assets/Cinemachines/CinemachinesMainOutput.renderTexture @@ -0,0 +1,39 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!84 &8400000 +RenderTexture: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: CinemachinesMainOutput + m_ImageContentsHash: + serializedVersion: 2 + Hash: 00000000000000000000000000000000 + m_IsAlphaChannelOptional: 0 + serializedVersion: 6 + m_Width: 1920 + m_Height: 1080 + m_AntiAliasing: 1 + m_MipCount: -1 + m_DepthStencilFormat: 90 + m_ColorFormat: 8 + m_MipMap: 0 + m_GenerateMips: 1 + m_SRGB: 0 + m_UseDynamicScale: 0 + m_UseDynamicScaleExplicit: 0 + m_BindMS: 0 + m_EnableCompatibleFormat: 1 + m_EnableRandomWrite: 0 + m_TextureSettings: + serializedVersion: 2 + m_FilterMode: 1 + m_Aniso: 1 + m_MipBias: 0 + m_WrapU: 1 + m_WrapV: 1 + m_WrapW: 1 + m_Dimension: 2 + m_VolumeDepth: 1 + m_ShadowSamplingMode: 2 diff --git a/Assets/Cinemachines/CinemachinesMainOutput.renderTexture.meta b/Assets/Cinemachines/CinemachinesMainOutput.renderTexture.meta new file mode 100644 index 0000000000..3a16d2b175 --- /dev/null +++ b/Assets/Cinemachines/CinemachinesMainOutput.renderTexture.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f59929735c684d198afcfc09f488ab46 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 8400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Cinemachines/CinemachinesPIPOutput.renderTexture b/Assets/Cinemachines/CinemachinesPIPOutput.renderTexture new file mode 100644 index 0000000000..4f1a59a547 --- /dev/null +++ b/Assets/Cinemachines/CinemachinesPIPOutput.renderTexture @@ -0,0 +1,39 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!84 &8400000 +RenderTexture: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: CinemachinesPIPOutput + m_ImageContentsHash: + serializedVersion: 2 + Hash: 00000000000000000000000000000000 + m_IsAlphaChannelOptional: 0 + serializedVersion: 6 + m_Width: 1920 + m_Height: 1080 + m_AntiAliasing: 1 + m_MipCount: -1 + m_DepthStencilFormat: 90 + m_ColorFormat: 8 + m_MipMap: 0 + m_GenerateMips: 1 + m_SRGB: 0 + m_UseDynamicScale: 0 + m_UseDynamicScaleExplicit: 0 + m_BindMS: 0 + m_EnableCompatibleFormat: 1 + m_EnableRandomWrite: 0 + m_TextureSettings: + serializedVersion: 2 + m_FilterMode: 1 + m_Aniso: 1 + m_MipBias: 0 + m_WrapU: 1 + m_WrapV: 1 + m_WrapW: 1 + m_Dimension: 2 + m_VolumeDepth: 1 + m_ShadowSamplingMode: 2 diff --git a/Assets/Cinemachines/CinemachinesPIPOutput.renderTexture.meta b/Assets/Cinemachines/CinemachinesPIPOutput.renderTexture.meta new file mode 100644 index 0000000000..1e4c3143a2 --- /dev/null +++ b/Assets/Cinemachines/CinemachinesPIPOutput.renderTexture.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: cbc02f9f8e3cea552babbcf1601bec17 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 8400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Cinemachines/Scenes.meta b/Assets/Cinemachines/Scenes.meta new file mode 100644 index 0000000000..2ec64a3622 --- /dev/null +++ b/Assets/Cinemachines/Scenes.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2adc3f7c824160b36a6c0ce81fbc6dfd +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Resources/Prefabs/Cinemachines.meta b/Assets/Resources/Prefabs/Cinemachines.meta new file mode 100644 index 0000000000..1dcdf86cd4 --- /dev/null +++ b/Assets/Resources/Prefabs/Cinemachines.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a47af7f6bf1b65712a8dfb11813e0cdf +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Resources/Prefabs/Cinemachines/CinemachinesRoot.meta b/Assets/Resources/Prefabs/Cinemachines/CinemachinesRoot.meta new file mode 100644 index 0000000000..81d30e7a10 --- /dev/null +++ b/Assets/Resources/Prefabs/Cinemachines/CinemachinesRoot.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b81c1d8a3fb04bbb5b18529db96be098 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Resources/Prefabs/Cinemachines/CinemachinesRoot/CinemachinesBrains.prefab b/Assets/Resources/Prefabs/Cinemachines/CinemachinesRoot/CinemachinesBrains.prefab new file mode 100644 index 0000000000..627ceae54a --- /dev/null +++ b/Assets/Resources/Prefabs/Cinemachines/CinemachinesRoot/CinemachinesBrains.prefab @@ -0,0 +1,375 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &3976480380242000097 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 943761945907795268} + - component: {fileID: 2297140524550656847} + - component: {fileID: 3386221687542845825} + - component: {fileID: 533780668452257913} + - component: {fileID: 5153989937071496418} + m_Layer: 0 + m_Name: CMC_MainPicture + m_TagString: EditorOnly + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &943761945907795268 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3976480380242000097} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 674836566232368238} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!20 &2297140524550656847 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3976480380242000097} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} + m_projectionMatrixMode: 2 + m_GateFitMode: 1 + m_FOVAxisMode: 0 + m_Iso: 200 + m_ShutterSpeed: 0.005 + m_Aperture: 16 + m_FocusDistance: 10 + m_FocalLength: 22.155977 + m_BladeCount: 5 + m_Curvature: {x: 2, y: 11} + m_BarrelClipping: 0.25 + m_Anamorphism: 0 + m_SensorSize: {x: 24.89, y: 18.66} + m_LensShift: {x: 0, y: 0} + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.01 + far clip plane: 1000 + field of view: 45.672436 + orthographic: 0 + orthographic size: 5 + m_Depth: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4160813015 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 8400000, guid: fc476579fa0193a8b893ed5d0ea454a7, type: 2} + m_TargetDisplay: 7 + m_TargetEye: 3 + m_HDR: 1 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!81 &3386221687542845825 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3976480380242000097} + m_Enabled: 1 +--- !u!114 &533780668452257913 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3976480380242000097} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: a79441f348de89743a2939f4d699eac1, type: 3} + m_Name: + m_EditorClassIdentifier: + m_RenderShadows: 1 + m_RequiresDepthTextureOption: 2 + m_RequiresOpaqueTextureOption: 2 + m_CameraType: 0 + m_Cameras: [] + m_RendererIndex: -1 + m_VolumeLayerMask: + serializedVersion: 2 + m_Bits: 1 + m_VolumeTrigger: {fileID: 0} + m_VolumeFrameworkUpdateModeOption: 2 + m_RenderPostProcessing: 1 + m_Antialiasing: 3 + m_AntialiasingQuality: 2 + m_StopNaN: 0 + m_Dithering: 0 + m_ClearDepth: 1 + m_AllowXRRendering: 1 + m_AllowHDROutput: 1 + m_UseScreenCoordOverride: 0 + m_ScreenSizeOverride: {x: 0, y: 0, z: 0, w: 0} + m_ScreenCoordScaleBias: {x: 0, y: 0, z: 0, w: 0} + m_RequiresDepthTexture: 0 + m_RequiresColorTexture: 0 + m_Version: 2 + m_TaaSettings: + m_Quality: 3 + m_FrameInfluence: 0.1 + m_JitterScale: 1 + m_MipBias: 0 + m_VarianceClampScale: 0.9 + m_ContrastAdaptiveSharpening: 0 +--- !u!114 &5153989937071496418 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3976480380242000097} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 72ece51f2901e7445ab60da3685d6b5f, type: 3} + m_Name: + m_EditorClassIdentifier: + ShowDebugText: 0 + ShowCameraFrustum: 1 + IgnoreTimeScale: 0 + WorldUpOverride: {fileID: 0} + ChannelMask: -1 + UpdateMethod: 2 + BlendUpdateMethod: 1 + LensModeOverride: + Enabled: 1 + DefaultMode: 2 + DefaultBlend: + Style: 1 + Time: 2 + CustomCurve: + serializedVersion: 2 + m_Curve: [] + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + CustomBlends: {fileID: 0} +--- !u!1 &5264161247443515788 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 5630928931663925496} + - component: {fileID: 4471281427879547792} + - component: {fileID: 2984869823797931279} + - component: {fileID: 2012635475345146611} + - component: {fileID: 6985156430517444999} + m_Layer: 0 + m_Name: CMC_PictureInPicture + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &5630928931663925496 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5264161247443515788} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 674836566232368238} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!20 &4471281427879547792 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5264161247443515788} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} + m_projectionMatrixMode: 1 + m_GateFitMode: 2 + m_FOVAxisMode: 0 + m_Iso: 200 + m_ShutterSpeed: 0.005 + m_Aperture: 16 + m_FocusDistance: 10 + m_FocalLength: 50 + m_BladeCount: 5 + m_Curvature: {x: 2, y: 11} + m_BarrelClipping: 0.25 + m_Anamorphism: 0 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.01 + far clip plane: 1000 + field of view: 45.672436 + orthographic: 0 + orthographic size: 5 + m_Depth: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4160813015 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 8400000, guid: 28773ac73b82320b48f9fc5e7787ec21, type: 2} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 1 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!81 &2984869823797931279 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5264161247443515788} + m_Enabled: 1 +--- !u!114 &2012635475345146611 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5264161247443515788} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: a79441f348de89743a2939f4d699eac1, type: 3} + m_Name: + m_EditorClassIdentifier: + m_RenderShadows: 1 + m_RequiresDepthTextureOption: 2 + m_RequiresOpaqueTextureOption: 2 + m_CameraType: 0 + m_Cameras: [] + m_RendererIndex: -1 + m_VolumeLayerMask: + serializedVersion: 2 + m_Bits: 1 + m_VolumeTrigger: {fileID: 0} + m_VolumeFrameworkUpdateModeOption: 2 + m_RenderPostProcessing: 1 + m_Antialiasing: 3 + m_AntialiasingQuality: 2 + m_StopNaN: 0 + m_Dithering: 0 + m_ClearDepth: 1 + m_AllowXRRendering: 1 + m_AllowHDROutput: 1 + m_UseScreenCoordOverride: 0 + m_ScreenSizeOverride: {x: 0, y: 0, z: 0, w: 0} + m_ScreenCoordScaleBias: {x: 0, y: 0, z: 0, w: 0} + m_RequiresDepthTexture: 0 + m_RequiresColorTexture: 0 + m_Version: 2 + m_TaaSettings: + m_Quality: 3 + m_FrameInfluence: 0.1 + m_JitterScale: 1 + m_MipBias: 0 + m_VarianceClampScale: 0.9 + m_ContrastAdaptiveSharpening: 0 +--- !u!114 &6985156430517444999 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5264161247443515788} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 72ece51f2901e7445ab60da3685d6b5f, type: 3} + m_Name: + m_EditorClassIdentifier: + ShowDebugText: 0 + ShowCameraFrustum: 1 + IgnoreTimeScale: 0 + WorldUpOverride: {fileID: 0} + ChannelMask: -1 + UpdateMethod: 2 + BlendUpdateMethod: 1 + LensModeOverride: + Enabled: 0 + DefaultMode: 2 + DefaultBlend: + Style: 1 + Time: 2 + CustomCurve: + serializedVersion: 2 + m_Curve: [] + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + CustomBlends: {fileID: 0} +--- !u!1 &9208593710004002725 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 674836566232368238} + m_Layer: 0 + m_Name: CinemachinesBrains + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &674836566232368238 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 9208593710004002725} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 943761945907795268} + - {fileID: 5630928931663925496} + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} diff --git a/Assets/Resources/Prefabs/Cinemachines/CinemachinesRoot/CinemachinesBrains.prefab.meta b/Assets/Resources/Prefabs/Cinemachines/CinemachinesRoot/CinemachinesBrains.prefab.meta new file mode 100644 index 0000000000..d7df32d4d5 --- /dev/null +++ b/Assets/Resources/Prefabs/Cinemachines/CinemachinesRoot/CinemachinesBrains.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 845e926b2130244478dcf1ca8cf2c728 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Resources/Prefabs/Cinemachines/CinemachinesRoot/ControlCamera.prefab b/Assets/Resources/Prefabs/Cinemachines/CinemachinesRoot/ControlCamera.prefab new file mode 100644 index 0000000000..714b2cc255 --- /dev/null +++ b/Assets/Resources/Prefabs/Cinemachines/CinemachinesRoot/ControlCamera.prefab @@ -0,0 +1,160 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &8970444805841896186 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 7671238445287187331} + - component: {fileID: 4729896765743108432} + - component: {fileID: 2730496195725795670} + - component: {fileID: 6951109328680270292} + - component: {fileID: 1900162122134153581} + m_Layer: 0 + m_Name: ControlCamera + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &7671238445287187331 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8970444805841896186} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!20 &4729896765743108432 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8970444805841896186} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} + m_projectionMatrixMode: 1 + m_GateFitMode: 2 + m_FOVAxisMode: 0 + m_Iso: 200 + m_ShutterSpeed: 0.005 + m_Aperture: 16 + m_FocusDistance: 10 + m_FocalLength: 50 + m_BladeCount: 5 + m_Curvature: {x: 2, y: 11} + m_BarrelClipping: 0.25 + m_Anamorphism: 0 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 0 + orthographic size: 5 + m_Depth: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 0 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 7 + m_TargetEye: 3 + m_HDR: 1 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!81 &2730496195725795670 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8970444805841896186} + m_Enabled: 1 +--- !u!114 &6951109328680270292 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8970444805841896186} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: a79441f348de89743a2939f4d699eac1, type: 3} + m_Name: + m_EditorClassIdentifier: + m_RenderShadows: 1 + m_RequiresDepthTextureOption: 2 + m_RequiresOpaqueTextureOption: 2 + m_CameraType: 0 + m_Cameras: [] + m_RendererIndex: -1 + m_VolumeLayerMask: + serializedVersion: 2 + m_Bits: 1 + m_VolumeTrigger: {fileID: 0} + m_VolumeFrameworkUpdateModeOption: 2 + m_RenderPostProcessing: 0 + m_Antialiasing: 0 + m_AntialiasingQuality: 2 + m_StopNaN: 0 + m_Dithering: 0 + m_ClearDepth: 1 + m_AllowXRRendering: 1 + m_AllowHDROutput: 1 + m_UseScreenCoordOverride: 0 + m_ScreenSizeOverride: {x: 0, y: 0, z: 0, w: 0} + m_ScreenCoordScaleBias: {x: 0, y: 0, z: 0, w: 0} + m_RequiresDepthTexture: 0 + m_RequiresColorTexture: 0 + m_Version: 2 + m_TaaSettings: + m_Quality: 3 + m_FrameInfluence: 0.1 + m_JitterScale: 1 + m_MipBias: 0 + m_VarianceClampScale: 0.9 + m_ContrastAdaptiveSharpening: 0 +--- !u!114 &1900162122134153581 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8970444805841896186} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 19102, guid: 0000000000000000e000000000000000, type: 0} + m_Name: + m_EditorClassIdentifier: + m_PanelSettings: {fileID: 11400000, guid: c63b1081fc7d72101a389550160bcc3a, type: 2} + m_ParentUI: {fileID: 0} + sourceAsset: {fileID: 9197481963319205126, guid: 9d02ca329da0ba700bce096849c13b9a, + type: 3} + m_SortingOrder: 0 + m_WorldSpaceSizeMode: 1 + m_WorldSpaceWidth: 1920 + m_WorldSpaceHeight: 1080 diff --git a/Assets/Resources/Prefabs/Cinemachines/CinemachinesRoot/ControlCamera.prefab.meta b/Assets/Resources/Prefabs/Cinemachines/CinemachinesRoot/ControlCamera.prefab.meta new file mode 100644 index 0000000000..9ebbf5d7de --- /dev/null +++ b/Assets/Resources/Prefabs/Cinemachines/CinemachinesRoot/ControlCamera.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 4f0310ccb08b6737db548bca3ce4d654 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Resources/Prefabs/Cinemachines/SceneTemplate.prefab b/Assets/Resources/Prefabs/Cinemachines/SceneTemplate.prefab new file mode 100644 index 0000000000..c0fa1b2f96 --- /dev/null +++ b/Assets/Resources/Prefabs/Cinemachines/SceneTemplate.prefab @@ -0,0 +1,223 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &324327809438091302 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2140725804723030949} + m_Layer: 0 + m_Name: FocusObjects + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &2140725804723030949 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 324327809438091302} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 9207537824882640757} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &392207441576774055 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2839293154195611454} + m_Layer: 0 + m_Name: OtherObjects + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &2839293154195611454 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 392207441576774055} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 9207537824882640757} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &7096091658220090398 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 6529366561688718673} + m_Layer: 0 + m_Name: Cameras + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &6529366561688718673 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7096091658220090398} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 9207537824882640757} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &7475867141918043811 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2412182297654771841} + m_Layer: 0 + m_Name: Splines + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &2412182297654771841 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7475867141918043811} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 9207537824882640757} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &8979931306117858044 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 9207537824882640757} + - component: {fileID: -1542070960073348178} + - component: {fileID: -5748540832307934184} + - component: {fileID: 4465625675166380036} + m_Layer: 0 + m_Name: SceneTemplate + m_TagString: EditorOnly + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &9207537824882640757 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8979931306117858044} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 2412182297654771841} + - {fileID: 6529366561688718673} + - {fileID: 2140725804723030949} + - {fileID: 2839293154195611454} + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &-1542070960073348178 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8979931306117858044} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d1e471f6d63fc6dcaac5df22e43afd8d, type: 3} + m_Name: + m_EditorClassIdentifier: + serializationData: + SerializedFormat: 2 + SerializedBytes: + ReferencedUnityObjects: [] + SerializedBytesString: + Prefab: {fileID: 0} + PrefabModificationsReferencedUnityObjects: [] + PrefabModifications: [] + SerializationNodes: [] + CinemachinesCameraCount: 0 + SplineCount: 0 + SignalCount: 0 + FocusObjectCount: 0 + SceneGUID: + ObjectNameSuffix: +--- !u!320 &-5748540832307934184 +PlayableDirector: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8979931306117858044} + m_Enabled: 1 + serializedVersion: 3 + m_PlayableAsset: {fileID: 0} + m_InitialState: 0 + m_WrapMode: 2 + m_DirectorUpdateMode: 1 + m_InitialTime: 0 + m_SceneBindings: [] + m_ExposedReferences: + m_References: [] +--- !u!114 &4465625675166380036 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8979931306117858044} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: e52de21a22b6dd44c9cc19f810c65059, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Events: + m_Signals: [] + m_Events: [] diff --git a/Assets/Resources/Prefabs/Cinemachines/SceneTemplate.prefab.meta b/Assets/Resources/Prefabs/Cinemachines/SceneTemplate.prefab.meta new file mode 100644 index 0000000000..22ae8724da --- /dev/null +++ b/Assets/Resources/Prefabs/Cinemachines/SceneTemplate.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 4da1e676a502999a8b0c07ee95b6067b +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Resources/Prefabs/Players/DesktopPlayer.prefab b/Assets/Resources/Prefabs/Players/DesktopPlayer.prefab index 30b3d040c0..56b73860b1 100644 --- a/Assets/Resources/Prefabs/Players/DesktopPlayer.prefab +++ b/Assets/Resources/Prefabs/Players/DesktopPlayer.prefab @@ -10,6 +10,7 @@ GameObject: m_Component: - component: {fileID: 6839967699279661577} - component: {fileID: 6839967699279661569} + - component: {fileID: 6035500719040483256} - component: {fileID: 6839967699279661580} - component: {fileID: 6839967699279661582} - component: {fileID: 637028239384079898} @@ -106,6 +107,49 @@ Camera: m_OcclusionCulling: 1 m_StereoConvergence: 10 m_StereoSeparation: 0.022 +--- !u!114 &6035500719040483256 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6839967699279661599} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f9dfa5b682dcd46bda6128250e975f58, type: 3} + m_Name: + m_EditorClassIdentifier: + Priority: + Enabled: 0 + m_Value: 0 + OutputChannel: 1 + StandbyUpdate: 2 + m_StreamingVersion: 20241001 + m_LegacyPriority: 0 + Target: + TrackingTarget: {fileID: 0} + LookAtTarget: {fileID: 0} + CustomLookAtTarget: 0 + Lens: + FieldOfView: 60 + OrthographicSize: 10 + NearClipPlane: 0.01 + FarClipPlane: 10000 + Dutch: 0 + ModeOverride: 0 + PhysicalProperties: + GateFit: 2 + SensorSize: {x: 21.946, y: 16.002} + LensShift: {x: 0, y: 0} + FocusDistance: 10 + Iso: 200 + ShutterSpeed: 0.005 + Aperture: 16 + BladeCount: 5 + Curvature: {x: 2, y: 11} + BarrelClipping: 0.25 + Anamorphism: 0 + BlendHint: 0 --- !u!114 &6839967699279661580 MonoBehaviour: m_ObjectHideFlags: 0 diff --git a/Assets/Resources/UI.meta b/Assets/Resources/UI.meta new file mode 100644 index 0000000000..7c635ae60f --- /dev/null +++ b/Assets/Resources/UI.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 52c92addb54282d4c993fb3ab8c62a34 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Resources/UI/Cinemachines.meta b/Assets/Resources/UI/Cinemachines.meta new file mode 100644 index 0000000000..6c56ec906e --- /dev/null +++ b/Assets/Resources/UI/Cinemachines.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1eb2775bafac323d6aab527ef2145532 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Resources/UI/Cinemachines/ControlCamera.asset b/Assets/Resources/UI/Cinemachines/ControlCamera.asset new file mode 100644 index 0000000000..b27353e45a --- /dev/null +++ b/Assets/Resources/UI/Cinemachines/ControlCamera.asset @@ -0,0 +1,50 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 19101, guid: 0000000000000000e000000000000000, type: 0} + m_Name: ControlCamera + m_EditorClassIdentifier: + themeUss: {fileID: -4733365628477956816, guid: 77642052d3396d50c8c0cff835a25b12, + type: 3} + m_DisableNoThemeWarning: 0 + m_TargetTexture: {fileID: 0} + m_RenderMode: 0 + m_WorldSpaceLayer: 0 + m_ScaleMode: 1 + m_ReferenceSpritePixelsPerUnit: 100 + m_PixelsPerUnit: 100 + m_Scale: 1 + m_ReferenceDpi: 96 + m_FallbackDpi: 96 + m_ReferenceResolution: {x: 1200, y: 800} + m_ScreenMatchMode: 0 + m_Match: 0 + m_SortingOrder: 0 + m_TargetDisplay: 7 + m_BindingLogLevel: 0 + m_ClearDepthStencil: 1 + m_ClearColor: 0 + m_ColorClearValue: {r: 0, g: 0, b: 0, a: 0} + m_VertexBudget: 0 + m_DynamicAtlasSettings: + m_MinAtlasSize: 64 + m_MaxAtlasSize: 4096 + m_MaxSubTextureSize: 64 + m_ActiveFilters: -1 + m_AtlasBlitShader: {fileID: 9101, guid: 0000000000000000f000000000000000, type: 0} + m_RuntimeShader: {fileID: 9100, guid: 0000000000000000f000000000000000, type: 0} + m_RuntimeWorldShader: {fileID: 9102, guid: 0000000000000000f000000000000000, type: 0} + m_SDFShader: {fileID: 19011, guid: 0000000000000000f000000000000000, type: 0} + m_BitmapShader: {fileID: 9001, guid: 0000000000000000f000000000000000, type: 0} + m_SpriteShader: {fileID: 19012, guid: 0000000000000000f000000000000000, type: 0} + m_ICUDataAsset: {fileID: 0} + forceGammaRendering: 0 + textSettings: {fileID: 0} diff --git a/Assets/Resources/UI/Cinemachines/ControlCamera.asset.meta b/Assets/Resources/UI/Cinemachines/ControlCamera.asset.meta new file mode 100644 index 0000000000..e65bc78ec5 --- /dev/null +++ b/Assets/Resources/UI/Cinemachines/ControlCamera.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c63b1081fc7d72101a389550160bcc3a +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Resources/UI/Cinemachines/ControlCameraDataSource.asset b/Assets/Resources/UI/Cinemachines/ControlCameraDataSource.asset new file mode 100644 index 0000000000..81e4a306b6 --- /dev/null +++ b/Assets/Resources/UI/Cinemachines/ControlCameraDataSource.asset @@ -0,0 +1,16 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: db1fb8f5ed60c6cea8d5d75180934509, type: 3} + m_Name: ControlCameraDataSource + m_EditorClassIdentifier: + k__BackingField: {fileID: 8400000, guid: 09576b2e589ec913ba5b3e5e00ba889c, + type: 2} diff --git a/Assets/Resources/UI/Cinemachines/ControlCameraDataSource.asset.meta b/Assets/Resources/UI/Cinemachines/ControlCameraDataSource.asset.meta new file mode 100644 index 0000000000..37b20fe963 --- /dev/null +++ b/Assets/Resources/UI/Cinemachines/ControlCameraDataSource.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 81014f6a2c5112d15ab7369d18751deb +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Resources/UI/Cinemachines/ControlCameraView.uxml b/Assets/Resources/UI/Cinemachines/ControlCameraView.uxml new file mode 100644 index 0000000000..6034bb32b9 --- /dev/null +++ b/Assets/Resources/UI/Cinemachines/ControlCameraView.uxml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Assets/Resources/UI/Cinemachines/ControlCameraView.uxml.meta b/Assets/Resources/UI/Cinemachines/ControlCameraView.uxml.meta new file mode 100644 index 0000000000..b98385d139 --- /dev/null +++ b/Assets/Resources/UI/Cinemachines/ControlCameraView.uxml.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 9d02ca329da0ba700bce096849c13b9a +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0} diff --git a/Assets/Resources/UI/PictureInPicture.meta b/Assets/Resources/UI/PictureInPicture.meta new file mode 100644 index 0000000000..2fb3fc75dd --- /dev/null +++ b/Assets/Resources/UI/PictureInPicture.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f52cff7256870d7cd8afdcd964c0db25 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Resources/UI/PictureInPicture/RenderTextures.meta b/Assets/Resources/UI/PictureInPicture/RenderTextures.meta new file mode 100644 index 0000000000..347faeb352 --- /dev/null +++ b/Assets/Resources/UI/PictureInPicture/RenderTextures.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c3156420774daa1458c07fe6deee648d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Resources/UI/PictureInPicture/RenderTextures/rtpip_blank.renderTexture b/Assets/Resources/UI/PictureInPicture/RenderTextures/rtpip_blank.renderTexture new file mode 100644 index 0000000000..f9ca120acb --- /dev/null +++ b/Assets/Resources/UI/PictureInPicture/RenderTextures/rtpip_blank.renderTexture @@ -0,0 +1,39 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!84 &8400000 +RenderTexture: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: rtpip_blank + m_ImageContentsHash: + serializedVersion: 2 + Hash: 00000000000000000000000000000000 + m_IsAlphaChannelOptional: 0 + serializedVersion: 6 + m_Width: 1 + m_Height: 1 + m_AntiAliasing: 1 + m_MipCount: -1 + m_DepthStencilFormat: 92 + m_ColorFormat: 8 + m_MipMap: 0 + m_GenerateMips: 1 + m_SRGB: 0 + m_UseDynamicScale: 0 + m_UseDynamicScaleExplicit: 0 + m_BindMS: 0 + m_EnableCompatibleFormat: 1 + m_EnableRandomWrite: 0 + m_TextureSettings: + serializedVersion: 2 + m_FilterMode: 1 + m_Aniso: 0 + m_MipBias: 0 + m_WrapU: 1 + m_WrapV: 1 + m_WrapW: 1 + m_Dimension: 2 + m_VolumeDepth: 1 + m_ShadowSamplingMode: 2 diff --git a/Assets/Resources/UI/PictureInPicture/RenderTextures/rtpip_blank.renderTexture.meta b/Assets/Resources/UI/PictureInPicture/RenderTextures/rtpip_blank.renderTexture.meta new file mode 100644 index 0000000000..19b94543f3 --- /dev/null +++ b/Assets/Resources/UI/PictureInPicture/RenderTextures/rtpip_blank.renderTexture.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1f07d7183cf77cf4a9d697276fe6cb4b +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 8400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Resources/UI/PictureInPicture/pip-camera.uxml b/Assets/Resources/UI/PictureInPicture/pip-camera.uxml new file mode 100644 index 0000000000..9cf74a0bf0 --- /dev/null +++ b/Assets/Resources/UI/PictureInPicture/pip-camera.uxml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/Assets/Resources/UI/PictureInPicture/pip-camera.uxml.meta b/Assets/Resources/UI/PictureInPicture/pip-camera.uxml.meta new file mode 100644 index 0000000000..e9c9404c9c --- /dev/null +++ b/Assets/Resources/UI/PictureInPicture/pip-camera.uxml.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 3c71adf8850f3fd3f963246526391708 +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0} diff --git a/Assets/Resources/UI/PictureInPicture/pip.asset b/Assets/Resources/UI/PictureInPicture/pip.asset new file mode 100644 index 0000000000..daa13303b7 --- /dev/null +++ b/Assets/Resources/UI/PictureInPicture/pip.asset @@ -0,0 +1,50 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 19101, guid: 0000000000000000e000000000000000, type: 0} + m_Name: pip + m_EditorClassIdentifier: + themeUss: {fileID: -4733365628477956816, guid: ba0e3766823c59f06851aa74c35e1163, + type: 3} + m_DisableNoThemeWarning: 0 + m_TargetTexture: {fileID: 8400000, guid: fc476579fa0193a8b893ed5d0ea454a7, type: 2} + m_RenderMode: 0 + m_WorldSpaceLayer: 0 + m_ScaleMode: 1 + m_ReferenceSpritePixelsPerUnit: 100 + m_PixelsPerUnit: 100 + m_Scale: 1 + m_ReferenceDpi: 96 + m_FallbackDpi: 96 + m_ReferenceResolution: {x: 1200, y: 800} + m_ScreenMatchMode: 0 + m_Match: 0 + m_SortingOrder: 0 + m_TargetDisplay: 7 + m_BindingLogLevel: 0 + m_ClearDepthStencil: 1 + m_ClearColor: 0 + m_ColorClearValue: {r: 0, g: 0, b: 0, a: 0} + m_VertexBudget: 0 + m_DynamicAtlasSettings: + m_MinAtlasSize: 64 + m_MaxAtlasSize: 4096 + m_MaxSubTextureSize: 64 + m_ActiveFilters: -1 + m_AtlasBlitShader: {fileID: 9101, guid: 0000000000000000f000000000000000, type: 0} + m_RuntimeShader: {fileID: 9100, guid: 0000000000000000f000000000000000, type: 0} + m_RuntimeWorldShader: {fileID: 9102, guid: 0000000000000000f000000000000000, type: 0} + m_SDFShader: {fileID: 19011, guid: 0000000000000000f000000000000000, type: 0} + m_BitmapShader: {fileID: 9001, guid: 0000000000000000f000000000000000, type: 0} + m_SpriteShader: {fileID: 19012, guid: 0000000000000000f000000000000000, type: 0} + m_ICUDataAsset: {fileID: 0} + forceGammaRendering: 0 + textSettings: {fileID: 0} diff --git a/Assets/Resources/UI/PictureInPicture/pip.asset.meta b/Assets/Resources/UI/PictureInPicture/pip.asset.meta new file mode 100644 index 0000000000..74386e600e --- /dev/null +++ b/Assets/Resources/UI/PictureInPicture/pip.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8640b656f65edd6adbeb4a6e08b8be06 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Resources/UI/PictureInPicture/pipDataSource.asset b/Assets/Resources/UI/PictureInPicture/pipDataSource.asset new file mode 100644 index 0000000000..5e3fb2b988 --- /dev/null +++ b/Assets/Resources/UI/PictureInPicture/pipDataSource.asset @@ -0,0 +1,16 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: db1fb8f5ed60c6cea8d5d75180934509, type: 3} + m_Name: pipDataSource + m_EditorClassIdentifier: + k__BackingField: {fileID: 8400000, guid: 1f07d7183cf77cf4a9d697276fe6cb4b, + type: 2} diff --git a/Assets/Resources/UI/PictureInPicture/pipDataSource.asset.meta b/Assets/Resources/UI/PictureInPicture/pipDataSource.asset.meta new file mode 100644 index 0000000000..afaf843323 --- /dev/null +++ b/Assets/Resources/UI/PictureInPicture/pipDataSource.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 475f1a68f58038027ab7093c73d79774 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Resources/UI/UnityDefaultRuntimeTheme.tss b/Assets/Resources/UI/UnityDefaultRuntimeTheme.tss new file mode 100644 index 0000000000..79453c7fa2 --- /dev/null +++ b/Assets/Resources/UI/UnityDefaultRuntimeTheme.tss @@ -0,0 +1,2 @@ +@import url("unity-theme://default"); +VisualElement {} \ No newline at end of file diff --git a/Assets/Resources/UI/UnityDefaultRuntimeTheme.tss.meta b/Assets/Resources/UI/UnityDefaultRuntimeTheme.tss.meta new file mode 100644 index 0000000000..9050a077c7 --- /dev/null +++ b/Assets/Resources/UI/UnityDefaultRuntimeTheme.tss.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 77642052d3396d50c8c0cff835a25b12 +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 12388, guid: 0000000000000000e000000000000000, type: 0} + disableValidation: 0 diff --git a/Assets/SEE/Cinemachines.meta b/Assets/SEE/Cinemachines.meta new file mode 100644 index 0000000000..8fb5c02e92 --- /dev/null +++ b/Assets/SEE/Cinemachines.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0015ae45f363f4dfc8619606065cf1da +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/SEE/Cinemachines/CinemachineSceneRoot.cs b/Assets/SEE/Cinemachines/CinemachineSceneRoot.cs new file mode 100644 index 0000000000..bb5219567b --- /dev/null +++ b/Assets/SEE/Cinemachines/CinemachineSceneRoot.cs @@ -0,0 +1,369 @@ +using SEE.UI.RuntimeConfigMenu; +using SEE.Cinemachines.Utility; +using Sirenix.OdinInspector; +using Sirenix.Serialization; +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.Playables; +using UnityEditor; +using UnityEngine.Splines; +using UnityEditor.Splines; +using UnityEditor.Timeline; +using UnityEngine.Timeline; +using UnityEngine.SceneManagement; +using UnityEngine.Events; +using Unity.Properties; +using Unity.Cinemachine; +using Debug = UnityEngine.Debug; + +namespace SEE.Cinemachines +{ + /// + /// Scene Component, that controls and handles GameObjects and Assets specific to a Cinemachines-Scene. + /// + [Serializable] + [ExecuteInEditMode] + [RequireComponent(typeof(PlayableDirector))] + [RequireComponent(typeof(SignalReceiver))] + internal class CinemachinesScene : SerializedMonoBehaviour + { + /// + /// Incremental Counter for Cinemachines Camera. Counter not decremented on Camera deletion to avoid duplication. + /// + [HideInInspector, SerializeField] + private int cinemachinesCameraCount; + + /// + /// Incremental Counter for Splines. Counter not decremented on Spline deletion to avoid duplication. + /// + [HideInInspector, SerializeField] + private int splineCount; + + /// + /// Incremental Counter for Signals. Counter not decremented on Signal deletion to avoid duplication. + /// + [HideInInspector, SerializeField] + private int signalCount; + + /// + /// Incremental Counter for Focus Objects. Counter not decremented on Object deletion to avoid duplication. + /// + [HideInInspector, SerializeField] + private int focusObjectCount; + + /// + /// The GameObject, that points to the Cinemachines-Cameras Root of the Scene. + /// + [HideInInspector] + private GameObject? cinemachinesCamerasGameObject; + + /// + /// The GameObject, that points to the Splines Root of the Scene. + /// + [HideInInspector] + private GameObject? cinemachinesSplinesGameObject; + + /// + /// The GameObject, that points to the Focus-Object Root of the Scene. + /// + [HideInInspector] + private GameObject? cinemachinesFocusObjectGameObject; + + /// + /// The GameObject, that points to the Miscellaneous root of the Scene. + /// + [HideInInspector] + private GameObject? cinemachinesOtherObjectGameObject; + + /// + /// The Start Function to the Component, that initializes every Variable for the Scenes. + /// + protected void Start() + { + // Find relevant GameObject and remember them + cinemachinesCamerasGameObject = transform.Find("Cameras")?.gameObject; + cinemachinesSplinesGameObject = transform.Find("Splines")?.gameObject; + cinemachinesFocusObjectGameObject = transform.Find("FocusObjects")?.gameObject; + cinemachinesOtherObjectGameObject = transform.Find("OtherObjects")?.gameObject; + + // create gameobjects, if they are not found + if (!cinemachinesCamerasGameObject || !cinemachinesSplinesGameObject || !cinemachinesFocusObjectGameObject || !cinemachinesOtherObjectGameObject) + { + if (!cinemachinesCamerasGameObject) + { + cinemachinesCamerasGameObject = new GameObject("Cameras"); + cinemachinesCamerasGameObject.transform.SetParent(transform); + } + + if (!cinemachinesSplinesGameObject) + { + cinemachinesSplinesGameObject = new GameObject("Splines"); + cinemachinesSplinesGameObject.transform.SetParent(transform); + } + + if (!cinemachinesFocusObjectGameObject) + { + cinemachinesFocusObjectGameObject = new GameObject("FocusObjects"); + cinemachinesFocusObjectGameObject.transform.SetParent(transform); + } + + if (!cinemachinesOtherObjectGameObject) + { + cinemachinesOtherObjectGameObject = new GameObject("OtherObjects"); + cinemachinesOtherObjectGameObject.transform.SetParent(transform); + } + } + } + + /// + /// The Updater Function, that is unused in this Component. + /// + protected void Update() + { + // Intentionally left blank + } + + /// + /// AssetGUID of the Folder associated with this Scene. (Field). + /// + [SerializeField, DisableInPlayMode, DisableInEditorMode] + [Title("Scene Maintenance", horizontalLine: true)] + [PropertyOrder(CinemachineSceneConfigOrderDeletion), RuntimeGroupOrder(CinemachineSceneConfigOrderDeletion)] + [LabelText("GUID of the Scene")] + private string sceneGUID = ""; + + /// + /// AssetGUID of the Folder associated with this Scene. (Property). + /// + public string SceneGUID + { + get + { + return sceneGUID; + } + set + { + if (String.IsNullOrWhiteSpace(sceneGUID)) + { + sceneGUID = value; + } + } + } + + /// + /// Deletes this CinemachineScene from the Scenes. + /// + [Button("Delete selected Scene", ButtonSizes.Small), RuntimeButton(CinemachineSceneConfig, "Delete Scene")] + [ButtonGroup(CinemachineSceneConfig)] + [PropertyOrder(CinemachineSceneConfigOrderDeletion), RuntimeGroupOrder(CinemachineSceneConfigOrderDeletion)] + [InfoBox("@CinemachinesUtility.GetSceneDeletionWarningMessage(SceneGUID)", InfoMessageType.Warning)] + [Tooltip("Removes the currently selected Cinemachine Scene and its associated Timeline and other Assets.")] + internal void DestroyObject() + { + // Confirm, if the user wants to delete the Scene, permanently + if (!EditorUtility.DisplayDialog("Deletion Confirmation", "Are you sure, you want to remove this Scene?\n This will also permanently remove any associated files?", "Yes, delete", "No, keep Scene")) + { + return; + } + + // Delete Children before destroying the Object + foreach (Transform Child in transform) + { + #if UNITY_EDITOR + Debug.Log("Immediate Destroying Scene-Children within Editor", Child.gameObject); + DestroyImmediate(Child.gameObject); + #else + Debug.Log("Destroying Scene-Children during Runtime", Child.gameObject); + Destroy(child.gameObject); + #endif + } + + // Remove SceneFolder inside Assets/Cinemachines/Scenes, if one is assigned to this scene + if (!String.IsNullOrWhiteSpace(SceneGUID)) + { + string PathToSceneFolder = AssetDatabase.GUIDToAssetPath(SceneGUID); + Debug.Log($"Attempting to remove associated Scenes Folder from Project. Path: {PathToSceneFolder}", this); + if (!String.IsNullOrWhiteSpace(PathToSceneFolder)) + { + AssetDatabase.DeleteAsset(PathToSceneFolder); + } + else + { + Debug.LogWarning("Failed to find Scene-Folder. Assuming it never existed.", this); + } + } + else + { + Debug.LogWarning("GUID of Scene-Folder not set. Assuming it never existed.", this); + } + + // Remove self + #if UNITY_EDITOR + Debug.Log("Immediate Destroying Scene-Root from Editor", transform.gameObject); + DestroyImmediate(transform.gameObject); + #else + Debug.Log("Destroying Scene-Root during Runtime", transform.gameObject); + Destroy(transform.gameObject); + #endif + } + + /// + /// Stores this CinemachineScene as a Prefab. + /// + [Button("Backup Scene", ButtonSizes.Small), RuntimeButton(CinemachineSceneConfig, "Backup Scene")] + [ButtonGroup(CinemachineSceneConfig)] + [PropertyOrder(CinemachineSceneConfigOrderStore), RuntimeGroupOrder(CinemachineSceneConfigOrderStore)] + // [InfoBox("@CinemachinesUtility.GetSceneDeletionWarningMessage(SceneGUID)", InfoMessageType.Warning)] + [Tooltip("Stores the current Scene as a Prefab for loading in a different Unity-Scene or in the same in a different spot. This does not carry over References specific to a Scene.")] + internal void SaveScene() + { + // Generate the Prefabs Structure, if it doesn't exist yet + CinemachinesUtility.GenerateCinemachinesPrefabFolder(); + + // Full Path to the to be created Prefab Asset + string assetPathOfScene = $"{CinemachinesUtility.CinemachinesPrefabsRoot}/Scenes/{SceneManager.GetActiveScene().name} - {gameObject.name}.prefab"; + + // Ensuring, that the path is unique + assetPathOfScene = AssetDatabase.GenerateUniqueAssetPath(assetPathOfScene); + + // Attempt to create the Prefab + bool prefabCreationSuccess; + PrefabUtility.SaveAsPrefabAsset(gameObject, assetPathOfScene, out prefabCreationSuccess); + + // Log result + if (prefabCreationSuccess) + Debug.Log($"Scene has been successfully stored under {assetPathOfScene}"); + else + Debug.LogError($"Failed to store Scene under {assetPathOfScene}"); + } + + /// + /// Text-Field for a Name Suffix, to be appended to the Objects Name after creation. + /// + [Title("Scene Object Creation", horizontalLine: true)] + [LabelText("Suffix for Object")] + [PropertyOrder(CinemachinesSceneRootOptionsOrderCreateSpline), RuntimeGroupOrder(CinemachinesSceneRootOptionsOrderCreateSpline)] + [Tooltip("Name to be added as a Suffix to the Spline or Cinemachines Camera.")] + public string ObjectNameSuffix = ""; + + /// + /// Creates a new Spline, that can be assigned inside Cinemachine-Cameras with SplineDolly-Component. + /// + [Button("Create Spline", ButtonSizes.Small), RuntimeButton(CinemachinesSceneRootOptions, "Create Spline")] + [ButtonGroup(CinemachinesSceneRootOptions)] + [PropertyOrder(CinemachinesSceneRootOptionsOrderCreateSpline), RuntimeGroupOrder(CinemachinesSceneRootOptionsOrderCreateSpline)] + [Tooltip("Creates a GameObject, including an empty SplineContainer-Component. Note that the Positions inside the SplineContainer are relative to the root of the GameObject and its always placed at Scene Origin.")] + internal void CreateEmptySpline() + { + CinemachinesUtility.CreateGameObject("CinemachinesSpline", ref splineCount, ref ObjectNameSuffix, cinemachinesSplinesGameObject, typeof(SplineContainer), true); + + // Set current Active ToolContext to Spline + EditorApplication.delayCall += () => + { + EditorSplineUtility.SetKnotPlacementTool(); + }; + } + + /// + /// Creates a Signal inside the Scene-Folder, which can be used on the Scenes Timeline to trigger or invoke Functions of certain Objects or Scripts. + /// + [Button("Create Signal", ButtonSizes.Small), RuntimeButton(CinemachinesSceneRootOptions, "Create Signal")] + [ButtonGroup(CinemachinesSceneRootOptions)] + [PropertyOrder(CinemachinesSceneRootOptionsOrderCreateSignal), RuntimeGroupOrder(CinemachinesSceneRootOptionsOrderCreateSignal)] + [Tooltip("Creates a Signal inside the current Scenes Folder. This Signal then can be used on the current Scenes Timeline for triggering or accessing specific Functions")] + internal void CreateNewSignal() + { + string signalName = $"{transform.name} - {CinemachinesUtility.GetNewObjectName("Signal", ref signalCount, ref ObjectNameSuffix)}"; + + // Create a new Signal, and store it under this Scenes Signals Folder + SignalAsset newSignal = ScriptableObject.CreateInstance(); + + string scenePath = AssetDatabase.GUIDToAssetPath(SceneGUID); + + Debug.Log($"Creating SignalsAsset in: \"{scenePath}/Signals\""); + AssetDatabase.CreateAsset(newSignal, $"{scenePath}/Signals/{signalName}.signal"); + } + + /// + /// Creates a new Cinemachines Camera, that can be assigned to a Timeline. + /// + [Button("Add Camera", ButtonSizes.Small), RuntimeButton(CinemachinesSceneRootOptions, "Create Cinemachine-Camera")] + [ButtonGroup(CinemachinesSceneRootOptions)] + [PropertyOrder(CinemachinesSceneRootOptionsOrderCreateCamera), RuntimeGroupOrder(CinemachinesSceneRootOptionsOrderCreateCamera)] + [Tooltip("Creates a GameObject, including the Cinemachines Camera Component.")] + internal void CreateNewCamera() + { + CinemachinesUtility.CreateGameObject("CinemachinesCamera", ref cinemachinesCameraCount, ref ObjectNameSuffix, cinemachinesCamerasGameObject, typeof(CinemachineCamera), true); + } + + /// + /// Creates a new GameObject, that can used to focus a Cinemachine-Camera on. + /// + [Button("Create Focus-Object", ButtonSizes.Small), RuntimeButton(CinemachinesSceneRootOptions, "Create Focus-Object")] + [ButtonGroup(CinemachinesSceneRootOptions)] + [PropertyOrder(CinemachinesSceneRootOptionsOrderCreateFocus), RuntimeGroupOrder(CinemachinesSceneRootOptionsOrderCreateFocus)] + [Tooltip("Creates a GameObject, which can be used to focus a Cinemachine-Camera onto.")] + internal void CreateNewFocusObject() + { + CinemachinesUtility.CreateGameObject("FocusObject", ref focusObjectCount, ref ObjectNameSuffix, cinemachinesFocusObjectGameObject, null, false); + } + + /// + /// Creates a new Spline, that can be assigned inside Cinemachine-Cameras with SplineDolly-Component. + /// + [Button("Open Timeline", ButtonSizes.Small), RuntimeButton(CinemachinesSceneRootActions, "Open Timeline")] + [ButtonGroup(CinemachinesSceneRootActions)] + [PropertyOrder(CinemachinesSceneRootOptionsOrderOpenTimeline), RuntimeGroupOrder(CinemachinesSceneRootOptionsOrderOpenTimeline)] + [Tooltip("Open Timeline of the current Scene.")] + internal void OpenTimelineWindow() + { + // Get or Create the Timeline Window and lock it to current Scene + TimelineEditorWindow timelineEditorWindow = TimelineEditor.GetOrCreateWindow(); + + // select and lock the current Scene, selecting the current scenes PlayableDirector + timelineEditorWindow.locked = true; + timelineEditorWindow.SetTimeline(transform.GetComponent()); + } + + #region Odin Inspector Attributes + + #region Scene Configuration + + protected const string CinemachineSceneConfig = "CinemachineSceneConfig"; + + protected const float CinemachineSceneConfigOrderStore = 0; + + protected const float CinemachineSceneConfigOrderDeletion = CinemachineSceneConfigOrderStore + 1; + + #endregion Scene Configuration + + #region Options for CinemachinesSceneRoot + + protected const string CinemachinesSceneRootOptions = "CinemachinesSceneRootOptions"; + + protected const float CinemachinesSceneRootOptionsOrderCreateSpline = 10; + + protected const float CinemachinesSceneRootOptionsOrderCreateCamera = CinemachinesSceneRootOptionsOrderCreateSpline + 1; + + protected const float CinemachinesSceneRootOptionsOrderCreateSignal = CinemachinesSceneRootOptionsOrderCreateCamera + 1; + + protected const float CinemachinesSceneRootOptionsOrderCreateFocus = CinemachinesSceneRootOptionsOrderCreateSignal + 1; + + protected const string CinemachinesSceneRootActions = "CinemachinesSceneRootActions"; + + protected const float CinemachinesSceneRootOptionsOrderOpenTimeline = 15; + + #endregion Options for CinemachinesSceneRoot + + #region Scene Maintenance + + protected const string CinemachinesSceneRootMaintenance = "CinemachinesSceneRootMaintenance"; + + protected const float CinemachinesSceneRootMaintenanceOrderRepair = 20; + + #endregion Scene Maintenance + + #endregion Odin Inspector Attributes + } +} \ No newline at end of file diff --git a/Assets/SEE/Cinemachines/CinemachineSceneRoot.cs.meta b/Assets/SEE/Cinemachines/CinemachineSceneRoot.cs.meta new file mode 100644 index 0000000000..062b9ca0d6 --- /dev/null +++ b/Assets/SEE/Cinemachines/CinemachineSceneRoot.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: d1e471f6d63fc6dcaac5df22e43afd8d \ No newline at end of file diff --git a/Assets/SEE/Cinemachines/Cinemachines.cs b/Assets/SEE/Cinemachines/Cinemachines.cs new file mode 100644 index 0000000000..22e2e1cd1c --- /dev/null +++ b/Assets/SEE/Cinemachines/Cinemachines.cs @@ -0,0 +1,7 @@ +/// +/// Namespace for the Cinemachines. +/// This includes every GameObject-Component associated with Cinemachines, Utilities required for Structure Generation, (re-)initialization, etc. +/// +namespace SEE.Cinemachines +{ +} \ No newline at end of file diff --git a/Assets/SEE/Cinemachines/Cinemachines.cs.meta b/Assets/SEE/Cinemachines/Cinemachines.cs.meta new file mode 100644 index 0000000000..d27389c6e3 --- /dev/null +++ b/Assets/SEE/Cinemachines/Cinemachines.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 5e7bbd8071aae03ba9812d775a00a097 \ No newline at end of file diff --git a/Assets/SEE/Cinemachines/CinemachinesRoot.cs b/Assets/SEE/Cinemachines/CinemachinesRoot.cs new file mode 100644 index 0000000000..343ca40739 --- /dev/null +++ b/Assets/SEE/Cinemachines/CinemachinesRoot.cs @@ -0,0 +1,402 @@ +using SEE.UI.RuntimeConfigMenu; +using SEE.Cinemachines.Utility; +using SEE.UI.PictureInPicture; +using Sirenix.OdinInspector; +using Sirenix.Serialization; +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.Playables; +using UnityEngine.Timeline; +using UnityEngine.Experimental.Rendering; +using Debug = UnityEngine.Debug; +using UnityEditor; +using UnityEditor.EditorTools; + +namespace SEE.Cinemachines +{ + /// + /// Cinemachines Component, that initializes a Folder Structure inside the Project, specifically for Cinemachine and all of its associated components and elements. + /// + [Serializable] + [ExecuteInEditMode] + internal class CinemachinesRoot : SerializedMonoBehaviour + { + /// + /// Boolean value to keep track, if the Root of the Cinemachines is fully initialized. + /// + [SerializeField, DisableInPlayMode, DisableInEditorMode] + [Title("Cinemachines-Root Mainenance", horizontalLine: true)] + // [InfoBox("Maintenance Section for the Cinemachines-Root")] + [PropertyOrder(CinemachinesRootMaintenanceOrderSetupReset), RuntimeGroupOrder(CinemachinesRootMaintenanceOrderSetupReset)] + [LabelText("CinemachinesRoot initialized?")] + [Tooltip("Displays the State of Initialization of the CinemachinesRoot.")] + private bool isInitialized = false; + + /// + /// Amount of Scenes inside this CinemachinesRoot. Doesn't decrement on scene-deletion to prevent duplicates. + /// + [HideInInspector, SerializeField] + private int sceneCounter; + + /// + /// The GUID of the RenderTexture assign with capturing the Cinemachine-Output. + /// + [HideInInspector, SerializeField] + private UnityEditor.GUID mainOutputGUID; + + /// + /// The GUID of the RenderTexture associated with the Picture-In-Picture Option. + /// + [HideInInspector, SerializeField] + private UnityEditor.GUID pictureInPictureGUID; + + /// + /// Root of the Cinemachine-Brains GameObjects. + /// + private GameObject cinemachineBrainsGameObject; + + /// + /// GameObject for the ControlCamera. + /// + private GameObject cinemachineControlCameraGameObject; + + /// + /// Root of the Cinemachine-Scene GameObjects. + /// + private GameObject cinemachineScenesGameObject; + + /// + /// Function to be run once on creation/startup of the Component. + /// + protected void Start() + { + // Ensure, that only one CinemachinesRoot exists per Scene + // var possibleRoots = UnityEngine.Object.FindObjectsByType(FindObjectsInactive.Exclude, FindObjectsSortMode.None); + CinemachinesRoot[] possibleRoots = CinemachinesUtility.FindAllCinemachinesRootsInScene(); + + if (possibleRoots.Length > 1) + { + Debug.LogError("Multiple CinemachinesRoot are not supported. Only use one per Unity-Scene."); + + // Disable GameObject + gameObject.SetActive(false); + enabled = false; + + return; + } + + // If the CinemachinesRoot has not been initialized on Start, initialize it + if (!isInitialized) + { + SetupCinemachinesRoot(); + } + } + + /// + /// Update Function to run on every Frame. Unused on this Component. + /// + protected void Update() + { + // Intentionally left blank + } + + #region Root Maintenance + + /// + /// Sets-up the CinemachinesRoot Prefab. + /// + [Button("Setup Cinemachines-Root", ButtonSizes.Small), RuntimeButton(CinemachinesRootMaintenance, "Setup Cinemachines-Root")] + [PropertyOrder(CinemachinesRootMaintenanceOrderSetupReset), RuntimeGroupOrder(CinemachinesRootMaintenanceOrderSetupReset)] + [ButtonGroup(CinemachinesRootMaintenance)] + [HideIf(nameof(isInitialized)), RuntimeHideIf(nameof(isInitialized))] + [Tooltip("Sets up the Root for the Cinemachines. Generates the Structure for crucial Elements and Organization.")] + internal void SetupCinemachinesRoot() + { + // Create the Structure of the CinemachinesRoot. It fails, if the Prefabs are not awailable. + if(!CreateCinemachinesRootStructure()) + { + return; + } + + // build the folder structure under "Assets/Cinemachine" + CreateCinemachineFolderStructure(); + + // Either Create or Confirm existance of the RenderTextures. + CreateRenderTextures(); + + isInitialized = true; + } + + + /// + /// Resets the CinemachinesRoot. + /// + [Button("Reset Cinemachines", ButtonSizes.Small), RuntimeButton(CinemachinesRootMaintenance, "Reset Cinemachines")] + [PropertyOrder(CinemachinesRootMaintenanceOrderSetupReset), RuntimeGroupOrder(CinemachinesRootMaintenanceOrderSetupReset)] + [ButtonGroup(CinemachinesRootMaintenance)] + [Tooltip("Resets the Root for the Cinemachines. This will also remove any created Scenes.")] + [ShowIf(nameof(isInitialized)), RuntimeShowIf(nameof(isInitialized))] + internal void ResetCinemachinesRoot() + { + // reset initialization, in case the root could not be reset. + isInitialized = false; + + // clear children of CinemachinesRoot + List rootChildren = new List(); + + rootChildren.Add(transform.Find(CinemachinesUtility.CinemachinesBrainsName)); + rootChildren.Add(transform.Find(CinemachinesUtility.CinemachinesScenesName)); + rootChildren.Add(transform.Find(CinemachinesUtility.CinemachinesControlCameraName)); + + foreach (Transform child in rootChildren) + { + if (child == null) + { + continue; + } + + #if UNITY_EDITOR + Debug.Log("Immediate Destroying Cinemachine-Children within Editor", child.gameObject); + DestroyImmediate(child.gameObject); + #else + Debug.Log("Destroying Cinemachine-Children during Runtime", child.gameObject); + Destroy(child.gameObject); + #endif + } + + // Remove every Scene-Folder from Assets/Cinemachines/Scenes + string[] sceneFolders = AssetDatabase.GetSubFolders($"{CinemachinesUtility.CinemachinesAssetsRoot}/Scenes"); + foreach (string sceneFolder in sceneFolders) + { + if (sceneFolder == $"{CinemachinesUtility.CinemachinesAssetsRoot}/Scenes/general") + { + continue; + } + + Debug.Log($"Removing {sceneFolder} from Project"); + AssetDatabase.DeleteAsset(sceneFolder); + } + + // Reset Scene Counter + sceneCounter = 0; + + // Create CinemachinesRoot + SetupCinemachinesRoot(); + } + + #endregion Root Maintenance + + #region Scene Creation + + /// + /// Text-Field for adding a Suffix to a Scene name. + /// + [SerializeField] + [Title("Scene Creation", horizontalLine: true)] + [LabelText("Scene Name")] + [PropertyOrder(CinemachineSceneConfigOrderCreate), RuntimeGroupOrder(CinemachineSceneConfigOrderCreate)] + [EnableIf(nameof(isInitialized)), RuntimeEnableIf(nameof(isInitialized))] + [Tooltip("Name of the Scene to be added as a Suffix to the GameObject.")] + public string SceneNameSuffix = ""; + + /// + /// Creates a new Cinemachine-Scene Structure inside the . + /// + [Button("Create new Scene", ButtonSizes.Small), RuntimeButton(CinemachineSceneConfig, "Create new Scene")] + [ButtonGroup(CinemachineSceneConfig)] + [PropertyOrder(CinemachineSceneConfigOrderCreate + 1), RuntimeGroupOrder(CinemachineSceneConfigOrderCreate + 1)] + [EnableIf(nameof(isInitialized)), RuntimeEnableIf(nameof(isInitialized))] + [Tooltip("Creates a new Cinemachine-Scene Structure inside the Unity-Scene.")] + internal void CreateNewScene() + { + // find the Scenes Transform within the CinemachinesRoot-Prefab + Transform? scenesTransform = transform.Find("Scenes"); + + // Generate the Scene Name with the sceneCounter and the optional SceneNameSuffix + string sceneName = $"Scene{sceneCounter}"; + if (!String.IsNullOrWhiteSpace(SceneNameSuffix)) + { + sceneName += $" - {SceneNameSuffix}"; + } + sceneCounter += 1; + + // Clear Text Input + SceneNameSuffix = ""; + + // Create Prefab inside Cinemachines -> Scenes + GameObject newScene = new GameObject(sceneName, typeof(CinemachinesScene)); + + // check, if the Scenes GameObject exists + if (scenesTransform) + { + newScene.transform.SetParent(scenesTransform); + } + else + { + newScene.transform.SetParent(transform); + + Debug.LogWarning("Missing Structure. Reset CinemachinesRoot to repair."); + } + + // confirm, that the underlining Structure exists + CreateCinemachineFolderStructure(); + + // Setup Scene Structure + CinemachinesUtility.GenerateSceneStructure(newScene, sceneName); + + // create new Timeline-Asset and store it in the newly created Scenes-Folder + TimelineAsset newTimeline = ScriptableObject.CreateInstance(); + + string scenePath = AssetDatabase.GUIDToAssetPath(newScene.GetComponent().SceneGUID); + + Debug.Log($"Creating TimelineAsset in: \"{scenePath}\""); + AssetDatabase.CreateAsset(newTimeline, $"{scenePath}/Timeline.playable"); + + // assign to SceneRoot -> Playable Director + newScene.GetComponent().playableAsset = newTimeline; + + // Open Timeline Window with the current Scene Selected + newScene.GetComponent().OpenTimelineWindow(); + } + + #endregion Scene Creation + + #region Helper-Functions + + /// + /// Checks for missing Prefabs and generates the CinemachinesRoot Structure. + /// + /// True, if creation of the Structure was successful, false otherwise. + private bool CreateCinemachinesRootStructure() + { + // Pre-Load any of the required sub-Prefabs + GameObject brains = Resources.Load($"{CinemachinesUtility.CinemachinesRootPrefabsRoot}/{CinemachinesUtility.CinemachinesBrainsName}"); + GameObject controlCamera = Resources.Load($"{CinemachinesUtility.CinemachinesRootPrefabsRoot}/{CinemachinesUtility.CinemachinesControlCameraName}"); + + // check for missing Prefabs + if (!brains || !controlCamera) + { + // report with error + Debug.LogError("Unable to reconstruct the CinemachinesRoot. Missing Prefabs."); + + // Log, which Prefabs are missing + if (!brains) + { + Debug.LogError($"Missing {CinemachinesUtility.CinemachinesBrainsName} Prefab"); + } + + if (!controlCamera) + { + Debug.LogError($"Missing {CinemachinesUtility.CinemachinesControlCameraName} Prefab"); + } + + return false; + } + + // Create GameObject Structure under CincemachinesRoot + cinemachineBrainsGameObject = Instantiate(brains, transform, false); + cinemachineControlCameraGameObject = Instantiate(controlCamera, transform, false); + + cinemachineScenesGameObject = new GameObject(CinemachinesUtility.CinemachinesScenesName); + cinemachineScenesGameObject.transform.SetParent(transform); + + // Correct their Names, so that they don't include the "(Clone)" suffix + cinemachineBrainsGameObject.name = $"{CinemachinesUtility.CinemachinesBrainsName}"; + cinemachineControlCameraGameObject.name = $"{CinemachinesUtility.CinemachinesControlCameraName}"; + + return true; + } + + /// + /// Checks, if the required Folder-Structure exists. + /// If not, it will create the Folder Structure. + /// + private void CreateCinemachineFolderStructure() + { + // create new Folder for Scene in Assets/Cinemachines/Scenes + if (!AssetDatabase.IsValidFolder($"{CinemachinesUtility.CinemachinesAssetsRoot}/Scenes")) + { + AssetDatabase.CreateFolder("Assets", "Cinemachines"); + AssetDatabase.CreateFolder($"{CinemachinesUtility.CinemachinesAssetsRoot}", "Scenes"); + Debug.Log($"Created Scenes-Root Folder in \"{CinemachinesUtility.CinemachinesAssetsRoot}\""); + } + } + + /// + /// Helper Function to create the required RenderTextures and storing them as Assets. + /// If these RenderTextures already exist, they will be overwritten + /// + private void CreateRenderTextures() + { + // Create the RenderTextureDescriptor, that both RenderTextures should abide by + RenderTextureDescriptor renderTextureDescriptor = new RenderTextureDescriptor(1920, 1080, RenderTextureFormat.ARGB32); + renderTextureDescriptor.depthStencilFormat = GraphicsFormat.D16_UNorm; + + // Create the RenderTexture for Main Cinemachines-Output, if none exists + string pathCinemachineMain = $"{CinemachinesUtility.CinemachinesAssetsRoot}/{CinemachinesUtility.CinemachinesMainOutputName}"; + if (!AssetDatabase.AssetPathExists(pathCinemachineMain)) + { + AssetDatabase.CreateAsset(new RenderTexture(renderTextureDescriptor), pathCinemachineMain); + } + mainOutputGUID = AssetDatabase.GUIDFromAssetPath(pathCinemachineMain); + + // Create the RenderTexture for PIP Cinemachines-Output, if none exists + string pathCinemachinePIP = $"{CinemachinesUtility.CinemachinesAssetsRoot}/{CinemachinesUtility.CinemachinesPIPOutputName}"; + if (!AssetDatabase.AssetPathExists(pathCinemachinePIP)) + { + AssetDatabase.CreateAsset(new RenderTexture(renderTextureDescriptor), pathCinemachinePIP); + } + pictureInPictureGUID = AssetDatabase.GUIDFromAssetPath(pathCinemachinePIP); + + PIPDataSource controlDataSource = Resources.Load("UI/Cinemachines/ControlCameraDataSource.asset"); + if (controlDataSource != null) + { + controlDataSource.PIPImage = AssetDatabase.LoadAssetByGUID(mainOutputGUID); + } + + // Find the Cinemachine-Brains in the Child-GameObjects + foreach (Transform child in cinemachineBrainsGameObject.transform) + { + switch(child.name) + { + case "CMC_MainPicture": + Debug.Log("Found Main Cinemachine Brain"); + child.GetComponent().targetTexture = AssetDatabase.LoadAssetByGUID(mainOutputGUID); + break; + case "CMC_PictureInPicture": + Debug.Log("Found PIP Cinemachine Brain"); + child.GetComponent().targetTexture = AssetDatabase.LoadAssetByGUID(pictureInPictureGUID); + break; + default: + Debug.LogWarning("Failed to find CinemachineBrains"); + break; + } + } + } + + #endregion + + #region Odin Inspector Attributes + + #region Maintenance of CinemachinesRoot + + protected const string CinemachinesRootMaintenance = "CinemachinesRootMaintenance"; + + protected const int CinemachinesRootMaintenanceOrderSetupReset = 0; + + // protected const int CinemachinesRootMaintenanceOrderRepair = CinemachinesRootMaintenanceOrderReset + 1; + + #endregion Maintenance of CinemachinesRoot + + #region Scene Creation + + protected const string CinemachineSceneConfig = "CinemachineSceneConfig"; + + protected const int CinemachineSceneConfigOrderCreate = 10; + + #endregion Scene Creation + + #endregion Odin Inspector Attributes + } +} \ No newline at end of file diff --git a/Assets/SEE/Cinemachines/CinemachinesRoot.cs.meta b/Assets/SEE/Cinemachines/CinemachinesRoot.cs.meta new file mode 100644 index 0000000000..665453d418 --- /dev/null +++ b/Assets/SEE/Cinemachines/CinemachinesRoot.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: ee97d6d05b41037a5b014ef641b040a4 \ No newline at end of file diff --git a/Assets/SEE/Cinemachines/Dolly.meta b/Assets/SEE/Cinemachines/Dolly.meta new file mode 100644 index 0000000000..0bd7f2c274 --- /dev/null +++ b/Assets/SEE/Cinemachines/Dolly.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 72a308144b44ad5d48efc74224171b80 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/SEE/Cinemachines/Dolly/Dolly.cs b/Assets/SEE/Cinemachines/Dolly/Dolly.cs new file mode 100644 index 0000000000..a6a8f0366f --- /dev/null +++ b/Assets/SEE/Cinemachines/Dolly/Dolly.cs @@ -0,0 +1,6 @@ +/// +/// Namespace for all custom ISplineDolly implementations. +/// +namespace SEE.Cinemachines.Dolly +{ +} \ No newline at end of file diff --git a/Assets/SEE/Cinemachines/Dolly/Dolly.cs.meta b/Assets/SEE/Cinemachines/Dolly/Dolly.cs.meta new file mode 100644 index 0000000000..bd5c233495 --- /dev/null +++ b/Assets/SEE/Cinemachines/Dolly/Dolly.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 179259e5d39d8d9ecb7abfa0d0130c09 \ No newline at end of file diff --git a/Assets/SEE/Cinemachines/Dolly/SimpleSpeedController.cs b/Assets/SEE/Cinemachines/Dolly/SimpleSpeedController.cs new file mode 100644 index 0000000000..ad42113de7 --- /dev/null +++ b/Assets/SEE/Cinemachines/Dolly/SimpleSpeedController.cs @@ -0,0 +1,135 @@ +using System; +using UnityEngine; +using Unity.Cinemachine; +using UnityEngine.Splines; +using System.Collections.Generic; +using UnityEngine.Pool; + +namespace SEE.Cinemachines.Dolly +{ + /// + [Tooltip("A simplistic Speed Controller for SplineAutoDolly on CinemachineSplineDolly, which apply fixed Speeds on SplineSegments")] + [Serializable] + public class SimpleSpeedController : SplineAutoDolly.ISplineAutoDolly + { + /// + /// Structure for storing Sector-Data, specificly Start-Point on a Line [0,1), and its Speed on that sector. + /// + [Serializable] + public struct SplineSector + { + public float SectorStart; + public float SectorSpeed; + } + + bool SplineAutoDolly.ISplineAutoDolly.RequiresTrackingTarget => false; + + [Tooltip("If true, the Camera will only move, when the CinemachineBrain is actively selecting this Camera. Otherwise will move, regardless if active or not, when this Setting is false.")] + public bool PauseWhenInactive = true; + + [Tooltip("List of Sections on a Spline, with its corresponding Speeds, inwhich that section needs to be paced with.")] + public SplineSector[] SpeedList = {}; + + /// + /// Calculation Function to get new Spline Position. + /// + /// (Unused) Behaviour-Script, that triggered the function. + /// (Unused) The Transform to apply the changes to. + /// (Unused) The Spline, where the Object should be moved on. + /// The Current Position on the . + /// (Unused) Units used for the Splines. + /// Delta-Time between the current and last Frame. + /// Gets thrown, if the Speed-List has less than one Entries. + /// Either the unmodified , if the Editor is in EditMode and the component is paused, or + SectorSpeed, when in PlayMode. + float SplineAutoDolly.ISplineAutoDolly.GetSplinePosition(MonoBehaviour _sender, Transform _target, SplineContainer _spline, float currentPosition, PathIndexUnit _positionUnit, float deltaTime) + { + // pause movement, when setting 'pauseWhenInactive' is selected and the camera is not Live, otherwise move camera along spline + if (PauseWhenInactive) + { + return currentPosition; + } + + SplineSector selectedSector; + + if (SpeedList.Length >= 1) + { + selectedSector = SpeedList[0]; + } + else + { + throw new IndexOutOfRangeException("Speed-List must be longer than one (1) entry"); + } + + for (int i = 1; i < SpeedList.Length; i++) + { + SplineSector tmpSector = SpeedList[i]; + + if (tmpSector.SectorStart >= selectedSector.SectorStart) + if (tmpSector.SectorStart <= currentPosition) + selectedSector = tmpSector; + } + + // Dont Progress inside Editor; Credit https://gist.github.com/adammyhre/b81eb6e1d07ebe24a49844fbbddf368b + if (deltaTime <= 0) { return currentPosition; } + + // Progress in Preview/Export + + return currentPosition + (selectedSector.SectorSpeed * deltaTime); + } + + /// + /// Reset Data that needs to be reset before Scene Start (Dynamic Data). + /// + void SplineAutoDolly.ISplineAutoDolly.Reset() + { + // Intentionally left blank + } + + /// + /// Validation Function, to make sure that all values are validly set. + /// + /// Thrown, if the Speed-List is not initialized. + /// Thrown, if the Speed-List has less than one Entry. + /// Thrown, if the Speed is zero or the Sectors are out of range in an Entry. + void SplineAutoDolly.ISplineAutoDolly.Validate() { + // NullReference and Index Checks + if (SpeedList == null) + { + // Debug.LogError("Spline Speed-List needs to be initialized"); + throw new NullReferenceException("Spline Speed-List needs to be initialized"); + } + + if (SpeedList != null && SpeedList.Length <= 0) + { + // Debug.LogError("Spline SpeedController needs at least one Entry in the Speed-List"); + throw new IndexOutOfRangeException("Spline SpeedController needs at least one Entry in the Speed-List"); + } + + for (int i = 0; i < SpeedList.Length; i++) + { + SplineSector currentEntry = SpeedList[i]; + if (currentEntry.SectorStart < 0) + { + // Debug.LogError(String.Format("Sector can only start at '0'; At Entry {0}", i)); + throw new ArgumentException(String.Format("Sector can only start at '0'; At Entry {0}", i), "SectorRange"); + } + + if (currentEntry.SectorStart >= 1) + { + // Debug.LogError(String.Format("Sector can only start before '1'; At Entry {0}", i)); + throw new ArgumentException(String.Format("Sector can only start before '1'; At Entry {0}", i), "SectorRange"); + } + + if (currentEntry.SectorSpeed <= 0) + { + // Debug.LogErrorFormat(String.Format("Speed should not be zero; At Entry {0}", i)); + throw new ArgumentException(String.Format("Speed should not be zero; At Entry {0}", i), "SectorSpeed"); + } + } + + return; + } + } +} \ No newline at end of file diff --git a/Assets/SEE/Cinemachines/Dolly/SimpleSpeedController.cs.meta b/Assets/SEE/Cinemachines/Dolly/SimpleSpeedController.cs.meta new file mode 100644 index 0000000000..cd82046e8b --- /dev/null +++ b/Assets/SEE/Cinemachines/Dolly/SimpleSpeedController.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 17320a84531385f4488651c85e32daf0 \ No newline at end of file diff --git a/Assets/SEE/Cinemachines/Utility.meta b/Assets/SEE/Cinemachines/Utility.meta new file mode 100644 index 0000000000..cff0430bf9 --- /dev/null +++ b/Assets/SEE/Cinemachines/Utility.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1d535d2058d1a19938e90dfdab89c55d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/SEE/Cinemachines/Utility/CinemachinesUtility.cs b/Assets/SEE/Cinemachines/Utility/CinemachinesUtility.cs new file mode 100644 index 0000000000..8df2c44f4f --- /dev/null +++ b/Assets/SEE/Cinemachines/Utility/CinemachinesUtility.cs @@ -0,0 +1,755 @@ +using System; +using System.Text; +using System.IO; +using System.Collections.Generic; +using System.Reflection; +using UnityEngine; +using UnityEngine.SceneManagement; +using UnityEngine.Timeline; +using UnityEngine.Events; +using UnityEngine.Playables; +using UnityEditor; +using Unity.Cinemachine; +using SEE.Cinemachines; + +namespace SEE.Cinemachines.Utility { + /// + /// Static Utility-Class for general functions shared between the custom Cinemachines Components. + /// + internal static class CinemachinesUtility + { + #region Constant String names + internal const string CinemachinesBrainsName = "CinemachinesBrains"; + internal const string CinemachinesScenesName = "Scenes"; + internal const string CinemachinesControlCameraName = "ControlCamera"; + internal const string CinemachinesMainOutputName = "CinemachinesMainOutput.renderTexture"; + internal const string CinemachinesPIPOutputName = "CinemachinesPIPOutput.renderTexture"; + + internal const string CinemachinesPrefabsRoot = "Assets/Resources/Prefabs/Cinemachines"; + internal const string CinemachinesRootPrefabsRoot = "Prefabs/Cinemachines/CinemachinesRoot"; + internal const string CinemachinesAssetsRoot = "Assets/Cinemachines"; + + internal const string CinemachinesPersistanceKeyName = "CinemachinesPersistanceKey"; + internal const string CinemachinesPersistanceKeyRestorableName = "CinemachinesPersistanceKeyRestorable"; + #endregion Constant String names + + /// + /// Class for Restoring GameObjects related to the Cinemachines. + /// + [InitializeOnLoad] + internal static class CinemachinesStateRestorer + { + /// + /// Structure-Class for storing References of Components in a serializable form. + /// + [Serializable] + internal class StoredReference + { + public int InstanceID; + public bool IsNull; + } + + /// + /// Structure-Class for storing Components inside GameObjects in a serializable form. + /// + [Serializable] + internal class StoredComponent + { + // Data for reconstructing the Type + public string AssemblyName; + public string TypeName; + + // Component Data + public int InstanceID; + public string JSONContent; + public List ListReferences = new List(); + } + + /// + /// Structure-Class for storing GameObjects in a serializable form. + /// + [Serializable] + internal class StoredGameObject + { + // Data of this GameObject + public int InstanceID; + public string JSONGameObject; + public List ListComponents = new List(); + + // List of Children inside this GameObject + [SerializeReference] + public List ChildGameObjects = new List(0); + } + + /// + /// Implementation of a Serializer to store changes made in PlayMode persistently. + /// + internal class Serializer + { + /// + /// Helper-Function to Serialize References inside Components. + /// + /// The Component to be serialized. + /// List of StoredReferences, that will be included to the respective Component. + private List SerializeReference(Component component) + { + // List for storing required References, that can not be applied normally + List referenceList = new List(); + + // Create SerializedObject from the Object/Component and get its SerializedProperty as an Iterator + SerializedObject serializedObject = new SerializedObject(component); + SerializedProperty propertyIterator = serializedObject.GetIterator(); + + // while there still are properties + while (propertyIterator.NextVisible(true)) + { + // check, if the type of property is relevant to us + if (propertyIterator.propertyType == SerializedPropertyType.ObjectReference) + { + StoredReference storedReference = new StoredReference(); + + // get Object referenced in Property + UnityEngine.Object objectReference = propertyIterator.objectReferenceValue; + + // setup StoredReference appropriatly, based on if its null or not + switch (objectReference) + { + case null: + storedReference.IsNull = true; + break; + default: + storedReference.InstanceID = objectReference.GetInstanceID(); + storedReference.IsNull = false; + break; + } + + referenceList.Add(storedReference); + } + } + + return referenceList; + } + + /// + /// Serializing Function for Transforms and their associated Data. + /// + /// The GameObject to be serialized. + /// Returns a StoredGameObject, that can be serialized into JSON. + internal StoredGameObject Serialize(Transform rootObject) + { + StoredGameObject storedGameObject = new StoredGameObject(); + + // Store base Data of this Object into the StoredGameObject + storedGameObject.InstanceID = rootObject.GetInstanceID(); + storedGameObject.JSONGameObject = EditorJsonUtility.ToJson(rootObject.gameObject); + + // iterate through all components + foreach (Component component in rootObject.GetComponents(typeof(Component))) + { + StoredComponent storedComponent = new StoredComponent(); + + // deconstruct the type of the Component + storedComponent.AssemblyName = component.GetType().Assembly.GetName().Name; + storedComponent.TypeName = component.GetType().FullName; + + // store base data of this Component + storedComponent.InstanceID = component.GetInstanceID(); + storedComponent.JSONContent = EditorJsonUtility.ToJson(component); + + // serialize references made inside component + storedComponent.ListReferences = SerializeReference(component); + + storedGameObject.ListComponents.Add(storedComponent); + } + + // re-iterate through all GameObjects, that are a child of this Object + // needs to be done in a depth-first way + foreach (Transform child in rootObject) + storedGameObject.ChildGameObjects.Add(Serialize(child)); + + return storedGameObject; + } + } + + /// + /// Implementation of a Deserializer to store changes made in PlayMode persistently. + /// + internal class Deserializer + { + /// + /// Temporary Dictionary for storing InstanceIDs of Objects with their respective StoredProperties. + /// + private Dictionary> storedReferences = new Dictionary>(); + + /// + /// Reference List between original InstanceIDs and restored IDs. + /// + private Dictionary referenceList = new Dictionary(); + + /// + /// Helper-Function to Deserialize References inside Components, like Transform, UnityEvents, etc. + /// + private void DeserializeReferences() + { + // Loop through every KeyValuePair in the storedReferences + foreach (var kvp in storedReferences) + { + // Find the Object/Component, you want to apply the References to + UnityEngine.Object restoredObject = Resources.InstanceIDToObject(kvp.Key); + + // create SerializedObject and Property + SerializedObject serializedObject = new SerializedObject(restoredObject); + SerializedProperty propertyIterator = serializedObject.GetIterator(); + + // get the stored References list from the KeyValuePair + List storedReferences = kvp.Value; + + // local Counter for iterating through the storedReferences for this Object + int Index = 0; + + // check, if there is still a Property accessable + while (propertyIterator.NextVisible(true)) + { + // check, if the type of the Property is relevant to us + if (propertyIterator.propertyType == SerializedPropertyType.ObjectReference) + { + // Select the indexed StoredReference, which potentially needs to be applied + StoredReference storedReference = storedReferences[Index]; + + // If the StoredReference was null, ignore it, ... + if (!storedReference.IsNull) + { + // ... else get the Object by InstanceID and apply it + int objectInstanceID; + if (referenceList.ContainsKey(storedReference.InstanceID)) + // TODO This part is not working correctly, since Unity differenciates InstanceIDs from actual Objects and References + objectInstanceID = referenceList[storedReference.InstanceID]; + else + objectInstanceID = storedReference.InstanceID; + + UnityEngine.Object objectReference = Resources.InstanceIDToObject(objectInstanceID); + + if (objectReference == null) + Debug.LogWarning($"Object with InstanceID '{objectInstanceID}' does not exist.\n Maybe the Object was created during Runtime, which must then be manually recreated and reapplied."); + + propertyIterator.objectReferenceValue = objectReference; + } + + // Increment Index for next Reference + Index++; + } + } + + // Apply all modified Properties to the SerializedObject, which applies the changes to the regular Objects/Components + serializedObject.ApplyModifiedProperties(); + } + } + + /// + /// Actual Deserializing Method, which returns the root transform. + /// + /// The StoredGameObject, that will be restored to actual GameObjects. + /// The Transform reconstructed from the StoredGameObject, including their Children. + private Transform Deserialize(StoredGameObject storedGameObject) + { + // Find Object as Child of rootTransform + GameObject restoredGameObject = new GameObject(); + EditorJsonUtility.FromJsonOverwrite(storedGameObject.JSONGameObject, restoredGameObject); + + // Iterate through all Components for this GameObject + foreach (StoredComponent storedComponent in storedGameObject.ListComponents) + { + // Reconstruct Type of this Component + Component readComponent = null; + Type ComponentType = Assembly.Load(storedComponent.AssemblyName).GetType(storedComponent.TypeName); + + // check, if the component is a Transform + if (ComponentType == typeof(Transform)) + readComponent = restoredGameObject.transform; + else if (ComponentType == typeof(PlayableDirector)) + { + readComponent = restoredGameObject.GetComponent(); + + if (readComponent == null) + readComponent = restoredGameObject.AddComponent(typeof(PlayableDirector)); + } + else if (ComponentType == typeof(SignalReceiver)) + { + readComponent = restoredGameObject.GetComponent(); + + if (readComponent == null) + readComponent = restoredGameObject.AddComponent(typeof(SignalReceiver)); + } + else + readComponent = restoredGameObject.AddComponent(ComponentType); + + // apply Data onto the component + EditorJsonUtility.FromJsonOverwrite(storedComponent.JSONContent, readComponent); + + // store References, that might need to be applied after everything has been applied + storedReferences.Add(readComponent.GetInstanceID(), storedComponent.ListReferences); + + // store mapping of old InstanceID to new InstanceID for Components + try + { + referenceList.Add(storedComponent.InstanceID, readComponent.GetInstanceID()); + } + catch (Exception _) + { + Debug.LogWarning($"Attempted to Map '{storedComponent.InstanceID}' to '{readComponent.GetInstanceID()}'"); + } + } + + // Iterate depth-first through all child GameObjects + foreach (StoredGameObject childStoredGameObject in storedGameObject.ChildGameObjects) + { + Transform child = Deserialize(childStoredGameObject); + + // reposition accordingly + child.SetParent(restoredGameObject.transform); + } + + return restoredGameObject.transform; + } + + /// + /// Primer Deserializer Function for GameObjects, initialized by inputing serialized Data. + /// + /// The serialized data, that will be restored from. + /// The restored Transform, including restored components and children. + internal Transform Deserialize(string jsonData) + { + // Deserialize first layer + StoredGameObject storedGameObject = JsonUtility.FromJson(jsonData); + + // Reconstruct root GameObject from deserialized Data + Transform restoredRootTransform = Deserialize(storedGameObject); + + // apply references to gameObject + DeserializeReferences(); + + return restoredRootTransform; + } + } + + /// + /// Constructor for the Cinemachines State Restorer, which enables an Event to restore changes made inside CinemachinesRoot to be re-applied after exiting PlayMode. + /// + static CinemachinesStateRestorer() + { + // Register new Event for restoring changes made in PlayMode + EditorApplication.playModeStateChanged += StoreCinemachinesChanges; + } + + /// + /// Save function, utilizing the custom Serializer Class for Cinemachines. + /// + /// The Name of the Unity-Scene, that the Object will be stored from. + private static void Save(string unitySceneName) + { + // Locating CinemachinesRoot + Transform cinemachinesRootTransform = GetCinemachinesRootInScene(); + + if (cinemachinesRootTransform == null) + { + return; + } + + // JSON storage + string serializedData = ""; + + // Serialize ScenesRoot + Serializer serializer = new Serializer(); + StoredGameObject storedGameObject = serializer.Serialize(cinemachinesRootTransform); + + serializedData = JsonUtility.ToJson(storedGameObject); + + // Store generated JSON inside EditorPrefs for persistance + EditorPrefs.SetString($"{unitySceneName}.{CinemachinesPersistanceKeyName}", serializedData); + } + + /// + /// Load function, utilizing the custom Deserializer Class for Cinemachines. + /// + /// The Unity-Scene to reconstruct the serialized GameObjects. + private static void Load(Scene unityScene) + { + string serializedDataKeyName = $"{unityScene.name}.{CinemachinesPersistanceKeyName}"; + + if (!EditorPrefs.HasKey(serializedDataKeyName)) + { + return; + } + // JSON storage + string serializedData = ""; + + // prepare deserializer + Deserializer deserializer = new Deserializer(); + serializedData = EditorPrefs.GetString(serializedDataKeyName); + + // get stored scenes-data with deserializer + Transform restoredObject = deserializer.Deserialize(serializedData); + + // Display warning about referencing original Objects + EditorUtility.DisplayDialog( + "Restoration of Cinemachines", + "Warning! The restored Backup is using parts of the original Cinemachine Structure.\nPlease check the Timelines and other Objects and update these components to their restored equivalents before continuing.", + "Okay" + ); + + // Reset PersistanceKey + if (EditorPrefs.HasKey(serializedDataKeyName)) + { + EditorPrefs.DeleteKey(serializedDataKeyName); + } + } + + /// + /// Helper-Function to get Unity-Scene names with CinemachineRoot-Backups. + /// + /// Name of Unity-Scenes, that have GameObject backups. + private static string[] GetRestorableScenes() + { + // find all Unity-Scenes in Project + string[] scenesGUIDs = AssetDatabase.FindAssets("t:Scene"); + List scenesPaths = new List(); + + foreach (string guid in scenesGUIDs) + scenesPaths.Add(AssetDatabase.GUIDToAssetPath(guid)); + + StringBuilder result = new StringBuilder(); + + foreach (string scenePath in scenesPaths) + { + // check, if scene-path starts at the correct location + // doing so will exclude every example scene from Extensions + if (!scenePath.StartsWith("Assets/Scenes")) + continue; + + // Logic for trimming the path down to the File-name of the Scene + int ToDeleteSuffixLength = ".unity".Length; + string[] UnitySceneNameSplit = scenePath.Remove(scenePath.Length - ToDeleteSuffixLength, ToDeleteSuffixLength).Split('/'); + string UnitySceneName = UnitySceneNameSplit[UnitySceneNameSplit.Length - 1]; + + // checking, if a persistance key for the scene exists + string prefKeyName = $"{UnitySceneName}.{CinemachinesPersistanceKeyName}"; + if (EditorPrefs.HasKey(prefKeyName)) + result.AppendFormat("{0}\n", UnitySceneName); + } + + return result.ToString().Split('\n'); + } + + /// + /// Display Function to get list of restorable scenes. + /// + [MenuItem("SEE/Cinemachines/Get restorable Cinemachine Roots", false, 12)] + internal static void GetRestorableRoots() + { + // String Builder for Dialog Body, which includes the names of the Scenes, that can restore a CinemachinesRoot + StringBuilder stringBuilder = new StringBuilder("The CinemachineRoots of the following Unity-Scenes have been backed up.\n"); + string[] restorableScenes = GetRestorableScenes(); + + // Format Scene Names + foreach (string scene in restorableScenes) + { + if (scene != "") + { + stringBuilder.AppendFormat("* {0}\n", scene); + } + } + + stringBuilder.Append("\nTo restore a CinemachineRoot, enter Unity-Scene and select SEE > Cinemachines > Restore Cinemachine Root"); + + EditorUtility.DisplayDialog( + "Restoration of Cinemachines", + stringBuilder.ToString(), + "Okay" + ); + } + + /// + /// Checker function, to see if current Unity-Scene has a restoreable CinemachinesRoot. + /// + /// True, if the current Scene has a backup, else false. + [MenuItem("SEE/Cinemachines/Restore Cinemachines Root", true, 10)] + private static bool HasUnitySceneBackup() { + return EditorPrefs.HasKey($"{SceneManager.GetActiveScene().name}.{CinemachinesPersistanceKeyName}"); + } + + /// + /// Menu Entry for restoring the CinemachinesRoot at current Scene. + /// + [MenuItem("SEE/Cinemachines/Restore Cinemachines Root", false, 10)] + internal static void RestoreCinemachinesRoot() + { + // Get Current Scenes Name + string UnitySceneName = SceneManager.GetActiveScene().name; + string prefKeyName = $"{UnitySceneName}.{CinemachinesPersistanceKeyName}"; + + if (!EditorPrefs.HasKey(prefKeyName)) + { + EditorUtility.DisplayDialog( + "Restoration of Cinemachines", + "This Scene contains no valid Backups for CinemachinesRoot.", + "Okay" + ); + return; + } + + // Confirm, if the user wants to restore to the last PlayTime State + if (!EditorUtility.DisplayDialog("Restoration of Cinemachines", "The Editor is in the process of restoring the Cinemachines, like they where at the time of exiting PlayTime.\n Do you want to restore to this Point?\n A Backup of the old Cinemachines will be created.", "Yes, restore", "No, don't restore")) + { + // // Reset PersistanceKey and abort + // if (EditorPrefs.HasKey(prefKeyName)) + // EditorPrefs.DeleteKey(prefKeyName); + return; + } + + // rename and deactivate old Scenes as backup + Transform CinemachinesRootTransform = GetCinemachinesRootInScene(); + + if (CinemachinesRootTransform != null) + // backup old root + HandleOldGameObject(CinemachinesRootTransform, true); + + // Load serialized Data + Load(SceneManager.GetActiveScene()); + } + + /// + /// Event Function to be called when the Play-State changes from PlayMode to EditMode. + /// Specific for restoring the Cinemachine-Scenes. + /// + /// The current state of the Editor. + private static void StoreCinemachinesChanges(PlayModeStateChange state) + { + switch (state) + { + case PlayModeStateChange.ExitingPlayMode: // Editor is exiting Play-Mode, proceed to save changes made + // Iterate through all Scenes inside the Project + for (int i = 0; i < SceneManager.sceneCount; i++) + { + // currently selected Scene + Scene currScene = SceneManager.GetSceneAt(i); + + // Save serialized Data + Save(currScene.name); + } + + GetRestorableRoots(); + break; + default: + break; + } + } + + /// + /// Helper Function to handle old GameObject on load. + /// + /// The GameObject, that will be deactivated or removed. + /// Parameter that determines, if the gets removed or deactivated. + private static void HandleOldGameObject(Transform oldRoot, bool backupOldRoot) + { + // if the Scenes root doesn't exist, don't try to create a backup + if (oldRoot != null) + { + if (backupOldRoot) + { + // backup old transform + oldRoot.gameObject.name = $"{oldRoot.gameObject.name} - Backup"; + oldRoot.gameObject.SetActive(false); + oldRoot.GetComponent().enabled = false; + } + else + { + // Remove old transform +#if UNITY_EDITOR + Debug.Log("Immediate Destroying from Editor", oldRoot); + UnityEngine.Object.DestroyImmediate(oldRoot); +#else + Debug.Log("Destroying during Runtime", oldRoot); + UnityEngine.Object.Destroy(oldRoot); +#endif + } + } + } + } + + /// + /// Returns the active CinemachineRoots-Transform, if one exists in the current Scene. + /// + /// Returns the active Transform, that includes the Cinemachines-Root Component, or null, of none is found. + internal static Transform GetCinemachinesRootInScene() + { + CinemachinesRoot[] CinemachinesRootComponents = FindAllCinemachinesRootsInScene(); + + if (CinemachinesRootComponents.Length < 1) + return null; + + return CinemachinesRootComponents[0].transform; + } + + /// + /// Function that finds all active -Components in the current Unity-Scene. + /// + /// There should only be one active -Component in a Unity-Scene. + /// List of -Components in the current Unity-Scene. + internal static CinemachinesRoot[] FindAllCinemachinesRootsInScene() + { + return UnityEngine.Object.FindObjectsByType(FindObjectsInactive.Exclude, FindObjectsSortMode.None); + } + + /// + /// Menu Entry for creating the CinemachinesRoot easily. + /// + [MenuItem("SEE/Cinemachines/Create Cinemachines Root", false, 10)] + [MenuItem("GameObject/SEE/Cinemachines/Create Cinemachines Root", false, 10)] + internal static void CreateCinemachinesRoot() + { + // Create a new CinemachinesRoot at the Root of the Scene + GameObject NewRoot = new GameObject("CinemachinesRoot", typeof(CinemachinesRoot)); + } + + /// + /// Helper Function to generate the "Scene Deletion Warning"-Message, including the Path to the respective Folder. + /// + /// The GUID of the Folder for the corresponding Cinemachines-Scene. + /// The Message generated for the Cinemachines-Scene. + internal static string GetSceneDeletionWarningMessage(string guid) { + return $"Deleting the Scene will also delete its associated Scene Folder, which is \"{AssetDatabase.GUIDToAssetPath(guid)}\""; + } + + /// + /// Helper Function to generate the Scene Folder, based on the current active UnityScene. + /// + /// The Name of the Cinemachines-Scene. + /// The GUID of the Cinemachines-Scene folder. + internal static string GenerateSceneFolder(string sceneName) + { + // create new Folder for Scene in Assets/Cinemachines/Scenes + string SceneGUID = AssetDatabase.CreateFolder($"{CinemachinesAssetsRoot}/Scenes", $"{SceneManager.GetActiveScene().name} - {sceneName}"); + // create Signals folder to store Timeline Signals + if (!AssetDatabase.IsValidFolder($"{AssetDatabase.GUIDToAssetPath(SceneGUID)}/Signals")) + AssetDatabase.CreateFolder(AssetDatabase.GUIDToAssetPath(SceneGUID), "Signals"); + + return SceneGUID; + } + + /// + /// Generator-Function to create the Cinemachines-Prefab Structure. + /// + internal static void GenerateCinemachinesPrefabFolder() + { + // If the Directory doesn't exists, create it + if(!AssetDatabase.IsValidFolder($"{CinemachinesPrefabsRoot}/Scenes")) + { + // Check and create Sub-Directories, if they don't exist + if (!AssetDatabase.IsValidFolder("Assets/Resources")) + AssetDatabase.CreateFolder("Assets", "Resources"); + + if (!AssetDatabase.IsValidFolder("Assets/Resources/Prefabs")) + AssetDatabase.CreateFolder("Assets/Resources", "Prefabs"); + + if (!AssetDatabase.IsValidFolder(CinemachinesPrefabsRoot)) + AssetDatabase.CreateFolder("Assets/Resources/Prefabs", "Cinemachines"); + + if (!AssetDatabase.IsValidFolder($"{CinemachinesPrefabsRoot}/Scenes")) + AssetDatabase.CreateFolder(CinemachinesPrefabsRoot, "Scenes"); + + Debug.Log($"Created Folder Structure: {CinemachinesPrefabsRoot}/Scenes"); + return; + } + } + + /// + /// Generator-Function to create the Scene Structure. + /// + /// The Cinemachine-Scene GameObject. + /// The Name of the Cinemachines-Scene. + internal static void GenerateSceneStructure(GameObject scene, string sceneName) + { + // Create Scene Folder + string SceneRootGUID = GenerateSceneFolder(sceneName); + // assign Scene-Folder to Scene-GameObject + string ScenePath = AssetDatabase.GUIDToAssetPath(SceneRootGUID); + + // Add the CinemachinesScenes Component to the newly created Scene GameObject + scene.GetComponent().SceneGUID = SceneRootGUID; + } + + /// + /// Helper-Function to construct the Name of the Object. + /// + /// Type of Object the Name should be constructed. + /// Amount of Objects already created. + /// Gets thrown, if the objectType is not defined or invalid. + /// Fully constructed Name for the Object. + internal static string GetNewObjectName(string objectType, ref int objectCount, ref string suffixText) + { + if (objectType == string.Empty || objectType == null) + { + throw new ArgumentException("objectType string cannot be empty or null"); + } + + // Form Name based on Type and Count + string newName = $"{objectType}{objectCount}"; + + // add optional suffix to name, if one is defined + if (!String.IsNullOrWhiteSpace(suffixText)) + { + newName += $" - {suffixText}"; + } + + // Reset the Text-Field and increment the counter + suffixText = ""; + objectCount += 1; + + return newName; + } + + /// + /// General Helper-Function to construct any GameObject with only one component added. + /// + /// Type of Object the Name should be constructed. + /// Amount of Objects already created. + /// The Root GameObject, that the new GameObject should be attached to. + /// The Component to add to the newly created GameObject. By default, it will not add any components. + /// Whether the newly created GameObject should be selected or not. By default, it will get selected. + /// Gets thrown, if either the objectType and/or rootGameObject are not defined or invalid. + internal static void CreateGameObject(string objectType, ref int objectCount, ref string suffixText, GameObject rootGameObject, System.Type componentToAdd = null, bool shouldBeFocused = true) + { + // Throw exception, if objectType is empty or null + if (objectType == string.Empty || objectType == null) + { + throw new ArgumentException("objectType string cannot be empty or null."); + } + + // Throw exception, if rootGameObject is null + if (rootGameObject == null) + { + throw new ArgumentNullException("rootGameObject cannot be null."); + } + + string objectName = GetNewObjectName(objectType, ref objectCount, ref suffixText); + + GameObject newObject; + // Create a new GameObject, and place it in under the correct GameObject + if (componentToAdd == null) + { + newObject = new GameObject(objectName); + } + else + { + newObject = new GameObject(objectName, componentToAdd); + } + newObject.transform.SetParent(rootGameObject.transform); + + // Select newly created GameObject + if (shouldBeFocused) + { + Selection.activeGameObject = newObject; + } + } + } +} \ No newline at end of file diff --git a/Assets/SEE/Cinemachines/Utility/CinemachinesUtility.cs.meta b/Assets/SEE/Cinemachines/Utility/CinemachinesUtility.cs.meta new file mode 100644 index 0000000000..dbc63b9b58 --- /dev/null +++ b/Assets/SEE/Cinemachines/Utility/CinemachinesUtility.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 3af03c495d0e783a084b3f7f25687911 \ No newline at end of file diff --git a/Assets/SEE/Cinemachines/Utility/Utility.cs b/Assets/SEE/Cinemachines/Utility/Utility.cs new file mode 100644 index 0000000000..8b025ed15f --- /dev/null +++ b/Assets/SEE/Cinemachines/Utility/Utility.cs @@ -0,0 +1,7 @@ +/// +/// Namespace for the Cinemachines Utilities. +/// These Classes handle generation and handling of general structures and shared Assets of the Cinemachines. +/// +namespace SEE.Cinemachines.Utility +{ +} \ No newline at end of file diff --git a/Assets/SEE/Cinemachines/Utility/Utility.cs.meta b/Assets/SEE/Cinemachines/Utility/Utility.cs.meta new file mode 100644 index 0000000000..8f70171fa4 --- /dev/null +++ b/Assets/SEE/Cinemachines/Utility/Utility.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 5cc59e7643077d84598f6cf997aff1e0 \ No newline at end of file diff --git a/Assets/SEE/SEE.asmdef b/Assets/SEE/SEE.asmdef index 1653838469..b902ca3fde 100644 --- a/Assets/SEE/SEE.asmdef +++ b/Assets/SEE/SEE.asmdef @@ -33,7 +33,13 @@ "GUID:e0cd26848372d4e5c891c569017e11f1", "GUID:13e34609dade4964e97712dc04b1cc6a", "GUID:702f733b4deb246808c6ce84d93b5c9c", - "GUID:04c4d86a70aa56c55a78c61f1ab1a56d" + "GUID:04c4d86a70aa56c55a78c61f1ab1a56d", + "GUID:4307f53044263cf4b835bd812fc161a4", + "GUID:ba8c092d026123a418fb4bfb797a7bd8", + "GUID:21d1eb854b91ade49bc69a263d12bee2", + "GUID:e43142fc3fec6554980dde6126631f1d", + "GUID:f06555f75b070af458a003d92f9efb00", + "GUID:02f771204943f4a40949438e873e3eff" ], "includePlatforms": [], "excludePlatforms": [], diff --git a/Assets/SEE/UI/PictureInPicture.meta b/Assets/SEE/UI/PictureInPicture.meta new file mode 100644 index 0000000000..6a9ee39448 --- /dev/null +++ b/Assets/SEE/UI/PictureInPicture.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 796f4b4fb6254a18da414eeabcce3bd3 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/SEE/UI/PictureInPicture/PictureInPicture.cs b/Assets/SEE/UI/PictureInPicture/PictureInPicture.cs new file mode 100644 index 0000000000..f317f92dca --- /dev/null +++ b/Assets/SEE/UI/PictureInPicture/PictureInPicture.cs @@ -0,0 +1,7 @@ +/// +/// Namespace for Elements associated with the Picture-in-Picture functionality. +/// This includes a Data Source Structure for the UIDocument "pip". +/// +namespace SEE.UI.PictureInPicture +{ +} \ No newline at end of file diff --git a/Assets/SEE/UI/PictureInPicture/PictureInPicture.cs.meta b/Assets/SEE/UI/PictureInPicture/PictureInPicture.cs.meta new file mode 100644 index 0000000000..494bdc3b95 --- /dev/null +++ b/Assets/SEE/UI/PictureInPicture/PictureInPicture.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: bd429ffda57c073d683e80579a7e7aad \ No newline at end of file diff --git a/Assets/SEE/UI/PictureInPicture/pipDataSource.cs b/Assets/SEE/UI/PictureInPicture/pipDataSource.cs new file mode 100644 index 0000000000..3f206cfb7d --- /dev/null +++ b/Assets/SEE/UI/PictureInPicture/pipDataSource.cs @@ -0,0 +1,26 @@ +using Unity.Properties; +using UnityEngine; +using UnityEngine.UIElements; + +#if UNITY_EDITOR +using UnityEditor; +#endif + +namespace SEE.UI.PictureInPicture +{ + /// + /// The Data Source Structure for the Picture-In-Picture UI-Element. + /// + [CreateAssetMenu(menuName = "SEE/UI/Picture-in-Picture/Data Source")] + public class PIPDataSource : ScriptableObject + { + [Header("Render Images")] + /// + /// The that is currently being displayed. + /// + [field: SerializeField, DontCreateProperty] + [CreateProperty] + public RenderTexture PIPImage { get; set; } + + } +} \ No newline at end of file diff --git a/Assets/SEE/UI/PictureInPicture/pipDataSource.cs.meta b/Assets/SEE/UI/PictureInPicture/pipDataSource.cs.meta new file mode 100644 index 0000000000..fb0cc46a42 --- /dev/null +++ b/Assets/SEE/UI/PictureInPicture/pipDataSource.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: db1fb8f5ed60c6cea8d5d75180934509 \ No newline at end of file diff --git a/Packages/manifest.json b/Packages/manifest.json index 3a6386968c..afbf5646c4 100644 --- a/Packages/manifest.json +++ b/Packages/manifest.json @@ -11,6 +11,7 @@ "com.unity.2d.tilemap": "1.0.0", "com.unity.ai.navigation": "2.0.13", "com.unity.burst": "1.8.27", + "com.unity.cinemachine": "3.1.6", "com.unity.collections": "2.6.7", "com.unity.formats.fbx": "5.1.6", "com.unity.ide.rider": "3.0.40", diff --git a/Packages/packages-lock.json b/Packages/packages-lock.json index 78715ab8b0..47748dc204 100644 --- a/Packages/packages-lock.json +++ b/Packages/packages-lock.json @@ -100,6 +100,16 @@ }, "url": "https://packages.unity.com" }, + "com.unity.cinemachine": { + "version": "3.1.6", + "depth": 0, + "source": "registry", + "dependencies": { + "com.unity.splines": "2.0.0", + "com.unity.modules.imgui": "1.0.0" + }, + "url": "https://packages.unity.com" + }, "com.unity.collections": { "version": "2.6.7", "depth": 0, @@ -278,6 +288,17 @@ "com.unity.searcher": "4.9.3" } }, + "com.unity.splines": { + "version": "2.8.2", + "depth": 1, + "source": "registry", + "dependencies": { + "com.unity.mathematics": "1.2.1", + "com.unity.modules.imgui": "1.0.0", + "com.unity.settings-manager": "1.0.3" + }, + "url": "https://packages.unity.com" + }, "com.unity.sysroot": { "version": "2.0.10", "depth": 1, From cfe67c6d9a8f6c4c7af555c01140aab4b29f301c Mon Sep 17 00:00:00 2001 From: Anton Siebert Date: Wed, 29 Jul 2026 11:35:12 +0200 Subject: [PATCH 02/16] #922 added suggestions made by github-actions and fixed overlooked styling errors --- .../SEE/Cinemachines/CinemachineSceneRoot.cs | 7 +++-- Assets/SEE/Cinemachines/Cinemachines.cs | 2 +- Assets/SEE/Cinemachines/CinemachinesRoot.cs | 5 ++-- Assets/SEE/Cinemachines/Dolly/Dolly.cs | 2 +- .../Dolly/SimpleSpeedController.cs | 2 +- .../Utility/CinemachinesUtility.cs | 28 +++++++++++++++---- Assets/SEE/Cinemachines/Utility/Utility.cs | 2 +- 7 files changed, 33 insertions(+), 15 deletions(-) diff --git a/Assets/SEE/Cinemachines/CinemachineSceneRoot.cs b/Assets/SEE/Cinemachines/CinemachineSceneRoot.cs index bb5219567b..16bfa97a3c 100644 --- a/Assets/SEE/Cinemachines/CinemachineSceneRoot.cs +++ b/Assets/SEE/Cinemachines/CinemachineSceneRoot.cs @@ -1,5 +1,6 @@ using SEE.UI.RuntimeConfigMenu; using SEE.Cinemachines.Utility; +using SEE.Utils; using Sirenix.OdinInspector; using Sirenix.Serialization; using System; @@ -175,7 +176,7 @@ internal void DestroyObject() DestroyImmediate(Child.gameObject); #else Debug.Log("Destroying Scene-Children during Runtime", Child.gameObject); - Destroy(child.gameObject); + Destroyer.Destroy(child.gameObject); #endif } @@ -204,7 +205,7 @@ internal void DestroyObject() DestroyImmediate(transform.gameObject); #else Debug.Log("Destroying Scene-Root during Runtime", transform.gameObject); - Destroy(transform.gameObject); + Destroyer.Destroy(transform.gameObject); #endif } @@ -366,4 +367,4 @@ internal void OpenTimelineWindow() #endregion Odin Inspector Attributes } -} \ No newline at end of file +} diff --git a/Assets/SEE/Cinemachines/Cinemachines.cs b/Assets/SEE/Cinemachines/Cinemachines.cs index 22e2e1cd1c..f81fb5edd0 100644 --- a/Assets/SEE/Cinemachines/Cinemachines.cs +++ b/Assets/SEE/Cinemachines/Cinemachines.cs @@ -4,4 +4,4 @@ /// namespace SEE.Cinemachines { -} \ No newline at end of file +} diff --git a/Assets/SEE/Cinemachines/CinemachinesRoot.cs b/Assets/SEE/Cinemachines/CinemachinesRoot.cs index 343ca40739..5845eaad18 100644 --- a/Assets/SEE/Cinemachines/CinemachinesRoot.cs +++ b/Assets/SEE/Cinemachines/CinemachinesRoot.cs @@ -1,6 +1,7 @@ using SEE.UI.RuntimeConfigMenu; using SEE.Cinemachines.Utility; using SEE.UI.PictureInPicture; +using SEE.Utils; using Sirenix.OdinInspector; using Sirenix.Serialization; using System; @@ -161,7 +162,7 @@ internal void ResetCinemachinesRoot() DestroyImmediate(child.gameObject); #else Debug.Log("Destroying Cinemachine-Children during Runtime", child.gameObject); - Destroy(child.gameObject); + Destroyer.Destroy(child.gameObject); #endif } @@ -399,4 +400,4 @@ private void CreateRenderTextures() #endregion Odin Inspector Attributes } -} \ No newline at end of file +} diff --git a/Assets/SEE/Cinemachines/Dolly/Dolly.cs b/Assets/SEE/Cinemachines/Dolly/Dolly.cs index a6a8f0366f..f780af633a 100644 --- a/Assets/SEE/Cinemachines/Dolly/Dolly.cs +++ b/Assets/SEE/Cinemachines/Dolly/Dolly.cs @@ -3,4 +3,4 @@ /// namespace SEE.Cinemachines.Dolly { -} \ No newline at end of file +} diff --git a/Assets/SEE/Cinemachines/Dolly/SimpleSpeedController.cs b/Assets/SEE/Cinemachines/Dolly/SimpleSpeedController.cs index ad42113de7..0d224d5a0a 100644 --- a/Assets/SEE/Cinemachines/Dolly/SimpleSpeedController.cs +++ b/Assets/SEE/Cinemachines/Dolly/SimpleSpeedController.cs @@ -132,4 +132,4 @@ void SplineAutoDolly.ISplineAutoDolly.Validate() { return; } } -} \ No newline at end of file +} diff --git a/Assets/SEE/Cinemachines/Utility/CinemachinesUtility.cs b/Assets/SEE/Cinemachines/Utility/CinemachinesUtility.cs index 8df2c44f4f..45e0ac7f87 100644 --- a/Assets/SEE/Cinemachines/Utility/CinemachinesUtility.cs +++ b/Assets/SEE/Cinemachines/Utility/CinemachinesUtility.cs @@ -165,7 +165,9 @@ internal StoredGameObject Serialize(Transform rootObject) // re-iterate through all GameObjects, that are a child of this Object // needs to be done in a depth-first way foreach (Transform child in rootObject) + { storedGameObject.ChildGameObjects.Add(Serialize(child)); + } return storedGameObject; } @@ -222,15 +224,21 @@ private void DeserializeReferences() // ... else get the Object by InstanceID and apply it int objectInstanceID; if (referenceList.ContainsKey(storedReference.InstanceID)) - // TODO This part is not working correctly, since Unity differenciates InstanceIDs from actual Objects and References + { + // This part is not working correctly, since Unity differenciates InstanceIDs from actual Objects and References objectInstanceID = referenceList[storedReference.InstanceID]; + } else + { objectInstanceID = storedReference.InstanceID; + } UnityEngine.Object objectReference = Resources.InstanceIDToObject(objectInstanceID); if (objectReference == null) + { Debug.LogWarning($"Object with InstanceID '{objectInstanceID}' does not exist.\n Maybe the Object was created during Runtime, which must then be manually recreated and reapplied."); + } propertyIterator.objectReferenceValue = objectReference; } @@ -265,23 +273,31 @@ private Transform Deserialize(StoredGameObject storedGameObject) // check, if the component is a Transform if (ComponentType == typeof(Transform)) + { readComponent = restoredGameObject.transform; + } else if (ComponentType == typeof(PlayableDirector)) { readComponent = restoredGameObject.GetComponent(); if (readComponent == null) + { readComponent = restoredGameObject.AddComponent(typeof(PlayableDirector)); + } } else if (ComponentType == typeof(SignalReceiver)) { readComponent = restoredGameObject.GetComponent(); if (readComponent == null) + { readComponent = restoredGameObject.AddComponent(typeof(SignalReceiver)); + } } else + { readComponent = restoredGameObject.AddComponent(ComponentType); + } // apply Data onto the component EditorJsonUtility.FromJsonOverwrite(storedComponent.JSONContent, readComponent); @@ -608,7 +624,7 @@ internal static CinemachinesRoot[] FindAllCinemachinesRootsInScene() internal static void CreateCinemachinesRoot() { // Create a new CinemachinesRoot at the Root of the Scene - GameObject NewRoot = new GameObject("CinemachinesRoot", typeof(CinemachinesRoot)); + GameObject newRoot = new GameObject("CinemachinesRoot", typeof(CinemachinesRoot)); } /// @@ -670,12 +686,12 @@ internal static void GenerateCinemachinesPrefabFolder() internal static void GenerateSceneStructure(GameObject scene, string sceneName) { // Create Scene Folder - string SceneRootGUID = GenerateSceneFolder(sceneName); + string sceneRootGUID = GenerateSceneFolder(sceneName); // assign Scene-Folder to Scene-GameObject - string ScenePath = AssetDatabase.GUIDToAssetPath(SceneRootGUID); + string scenePath = AssetDatabase.GUIDToAssetPath(SceneRootGUID); // Add the CinemachinesScenes Component to the newly created Scene GameObject - scene.GetComponent().SceneGUID = SceneRootGUID; + scene.GetComponent().SceneGUID = sceneRootGUID; } /// @@ -752,4 +768,4 @@ internal static void CreateGameObject(string objectType, ref int objectCount, re } } } -} \ No newline at end of file +} diff --git a/Assets/SEE/Cinemachines/Utility/Utility.cs b/Assets/SEE/Cinemachines/Utility/Utility.cs index 8b025ed15f..d0a8be8bf4 100644 --- a/Assets/SEE/Cinemachines/Utility/Utility.cs +++ b/Assets/SEE/Cinemachines/Utility/Utility.cs @@ -4,4 +4,4 @@ /// namespace SEE.Cinemachines.Utility { -} \ No newline at end of file +} From d71d1eca575d3c98e5fe70acc5d54e3cc44932a2 Mon Sep 17 00:00:00 2001 From: Anton Siebert Date: Wed, 29 Jul 2026 09:37:05 +0000 Subject: [PATCH 03/16] Potential fix for pull request finding added missing / to the tag Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- Assets/SEE/UI/PictureInPicture/pipDataSource.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Assets/SEE/UI/PictureInPicture/pipDataSource.cs b/Assets/SEE/UI/PictureInPicture/pipDataSource.cs index 3f206cfb7d..35dc36150c 100644 --- a/Assets/SEE/UI/PictureInPicture/pipDataSource.cs +++ b/Assets/SEE/UI/PictureInPicture/pipDataSource.cs @@ -16,8 +16,8 @@ public class PIPDataSource : ScriptableObject { [Header("Render Images")] /// - /// The that is currently being displayed. - /// + /// The that is currently being displayed. + /// Date: Wed, 29 Jul 2026 11:48:17 +0200 Subject: [PATCH 04/16] #922 fixed up more coding style errors and included more suggestions from github-actions --- Assets/SEE/Cinemachines/Dolly/SimpleSpeedController.cs | 2 +- Assets/SEE/Cinemachines/Utility/CinemachinesUtility.cs | 2 +- Assets/SEE/UI/PictureInPicture/pipDataSource.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Assets/SEE/Cinemachines/Dolly/SimpleSpeedController.cs b/Assets/SEE/Cinemachines/Dolly/SimpleSpeedController.cs index 0d224d5a0a..62b6793579 100644 --- a/Assets/SEE/Cinemachines/Dolly/SimpleSpeedController.cs +++ b/Assets/SEE/Cinemachines/Dolly/SimpleSpeedController.cs @@ -7,7 +7,7 @@ namespace SEE.Cinemachines.Dolly { - /// /// Class for a simple implementation of a Speed Controller, based on which section of the Spline the Object is. /// [Tooltip("A simplistic Speed Controller for SplineAutoDolly on CinemachineSplineDolly, which apply fixed Speeds on SplineSegments")] diff --git a/Assets/SEE/Cinemachines/Utility/CinemachinesUtility.cs b/Assets/SEE/Cinemachines/Utility/CinemachinesUtility.cs index 45e0ac7f87..182d5f8ce3 100644 --- a/Assets/SEE/Cinemachines/Utility/CinemachinesUtility.cs +++ b/Assets/SEE/Cinemachines/Utility/CinemachinesUtility.cs @@ -688,7 +688,7 @@ internal static void GenerateSceneStructure(GameObject scene, string sceneName) // Create Scene Folder string sceneRootGUID = GenerateSceneFolder(sceneName); // assign Scene-Folder to Scene-GameObject - string scenePath = AssetDatabase.GUIDToAssetPath(SceneRootGUID); + string scenePath = AssetDatabase.GUIDToAssetPath(sceneRootGUID); // Add the CinemachinesScenes Component to the newly created Scene GameObject scene.GetComponent().SceneGUID = sceneRootGUID; diff --git a/Assets/SEE/UI/PictureInPicture/pipDataSource.cs b/Assets/SEE/UI/PictureInPicture/pipDataSource.cs index 35dc36150c..bca1379b8d 100644 --- a/Assets/SEE/UI/PictureInPicture/pipDataSource.cs +++ b/Assets/SEE/UI/PictureInPicture/pipDataSource.cs @@ -17,7 +17,7 @@ public class PIPDataSource : ScriptableObject [Header("Render Images")] /// /// The that is currently being displayed. - /// [field: SerializeField, DontCreateProperty] [CreateProperty] public RenderTexture PIPImage { get; set; } From af88316d0cdf8b67ca3c64a282ddd4eb4c183acd Mon Sep 17 00:00:00 2001 From: Anton Siebert Date: Wed, 29 Jul 2026 11:54:42 +0200 Subject: [PATCH 05/16] #922 included the new lines at the end of the file, as suggested by github-actions --- Assets/SEE/UI/PictureInPicture/PictureInPicture.cs | 2 +- Assets/SEE/UI/PictureInPicture/pipDataSource.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Assets/SEE/UI/PictureInPicture/PictureInPicture.cs b/Assets/SEE/UI/PictureInPicture/PictureInPicture.cs index f317f92dca..59f9908d49 100644 --- a/Assets/SEE/UI/PictureInPicture/PictureInPicture.cs +++ b/Assets/SEE/UI/PictureInPicture/PictureInPicture.cs @@ -4,4 +4,4 @@ /// namespace SEE.UI.PictureInPicture { -} \ No newline at end of file +} diff --git a/Assets/SEE/UI/PictureInPicture/pipDataSource.cs b/Assets/SEE/UI/PictureInPicture/pipDataSource.cs index bca1379b8d..98fd922958 100644 --- a/Assets/SEE/UI/PictureInPicture/pipDataSource.cs +++ b/Assets/SEE/UI/PictureInPicture/pipDataSource.cs @@ -23,4 +23,4 @@ public class PIPDataSource : ScriptableObject public RenderTexture PIPImage { get; set; } } -} \ No newline at end of file +} From 146f687c32f07e88f838f51050c759d8cc10ccb0 Mon Sep 17 00:00:00 2001 From: Anton Siebert Date: Wed, 29 Jul 2026 12:30:50 +0200 Subject: [PATCH 06/16] #922 removed the ability for the SimpleSpeedController to pause when not selected --- Assets/SEE/Cinemachines/Dolly/SimpleSpeedController.cs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/Assets/SEE/Cinemachines/Dolly/SimpleSpeedController.cs b/Assets/SEE/Cinemachines/Dolly/SimpleSpeedController.cs index 62b6793579..487dd1e8a4 100644 --- a/Assets/SEE/Cinemachines/Dolly/SimpleSpeedController.cs +++ b/Assets/SEE/Cinemachines/Dolly/SimpleSpeedController.cs @@ -26,9 +26,6 @@ public struct SplineSector bool SplineAutoDolly.ISplineAutoDolly.RequiresTrackingTarget => false; - [Tooltip("If true, the Camera will only move, when the CinemachineBrain is actively selecting this Camera. Otherwise will move, regardless if active or not, when this Setting is false.")] - public bool PauseWhenInactive = true; - [Tooltip("List of Sections on a Spline, with its corresponding Speeds, inwhich that section needs to be paced with.")] public SplineSector[] SpeedList = {}; @@ -45,8 +42,8 @@ public struct SplineSector /// Either the unmodified , if the Editor is in EditMode and the component is paused, or + SectorSpeed, when in PlayMode. float SplineAutoDolly.ISplineAutoDolly.GetSplinePosition(MonoBehaviour _sender, Transform _target, SplineContainer _spline, float currentPosition, PathIndexUnit _positionUnit, float deltaTime) { - // pause movement, when setting 'pauseWhenInactive' is selected and the camera is not Live, otherwise move camera along spline - if (PauseWhenInactive) + // Dont Progress inside Editor; Credit https://gist.github.com/adammyhre/b81eb6e1d07ebe24a49844fbbddf368b + if (deltaTime <= 0) { return currentPosition; } @@ -71,9 +68,6 @@ float SplineAutoDolly.ISplineAutoDolly.GetSplinePosition(MonoBehaviour _sender, selectedSector = tmpSector; } - // Dont Progress inside Editor; Credit https://gist.github.com/adammyhre/b81eb6e1d07ebe24a49844fbbddf368b - if (deltaTime <= 0) { return currentPosition; } - // Progress in Preview/Export return currentPosition + (selectedSector.SectorSpeed * deltaTime); From 8f9ff5ddb04faa47e76d7556ee7eb030388d62b1 Mon Sep 17 00:00:00 2001 From: Anton Siebert Date: Wed, 29 Jul 2026 12:44:14 +0200 Subject: [PATCH 07/16] #922 applied more suggestions to pip-camera.uxml and ControlCameraView.uxml; including new RenderTextures for CinemachinesBrains --- Assets/Cinemachines/CinemachinesMainOutput.renderTexture | 2 +- Assets/Cinemachines/CinemachinesPIPOutput.renderTexture | 2 +- Assets/Resources/UI/Cinemachines/ControlCameraView.uxml | 4 ++-- Assets/Resources/UI/PictureInPicture/pip-camera.uxml | 1 - 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/Assets/Cinemachines/CinemachinesMainOutput.renderTexture b/Assets/Cinemachines/CinemachinesMainOutput.renderTexture index c57bfb0c75..a037251cd0 100644 --- a/Assets/Cinemachines/CinemachinesMainOutput.renderTexture +++ b/Assets/Cinemachines/CinemachinesMainOutput.renderTexture @@ -29,7 +29,7 @@ RenderTexture: m_TextureSettings: serializedVersion: 2 m_FilterMode: 1 - m_Aniso: 1 + m_Aniso: 0 m_MipBias: 0 m_WrapU: 1 m_WrapV: 1 diff --git a/Assets/Cinemachines/CinemachinesPIPOutput.renderTexture b/Assets/Cinemachines/CinemachinesPIPOutput.renderTexture index 4f1a59a547..a6df46f109 100644 --- a/Assets/Cinemachines/CinemachinesPIPOutput.renderTexture +++ b/Assets/Cinemachines/CinemachinesPIPOutput.renderTexture @@ -29,7 +29,7 @@ RenderTexture: m_TextureSettings: serializedVersion: 2 m_FilterMode: 1 - m_Aniso: 1 + m_Aniso: 0 m_MipBias: 0 m_WrapU: 1 m_WrapV: 1 diff --git a/Assets/Resources/UI/Cinemachines/ControlCameraView.uxml b/Assets/Resources/UI/Cinemachines/ControlCameraView.uxml index 6034bb32b9..da1e57424f 100644 --- a/Assets/Resources/UI/Cinemachines/ControlCameraView.uxml +++ b/Assets/Resources/UI/Cinemachines/ControlCameraView.uxml @@ -1,7 +1,7 @@ - + - + diff --git a/Assets/Resources/UI/PictureInPicture/pip-camera.uxml b/Assets/Resources/UI/PictureInPicture/pip-camera.uxml index 9cf74a0bf0..ae3777aeeb 100644 --- a/Assets/Resources/UI/PictureInPicture/pip-camera.uxml +++ b/Assets/Resources/UI/PictureInPicture/pip-camera.uxml @@ -5,7 +5,6 @@ - From 2e4ccb746b922187c3a297930e4ace3cfa7f619e Mon Sep 17 00:00:00 2001 From: Anton Siebert Date: Fri, 31 Jul 2026 14:46:50 +0200 Subject: [PATCH 08/16] #922 applied suggestions to remove unnecessary and unused assignments from CinemachinesUtility. --- Assets/SEE/Cinemachines/Utility/CinemachinesUtility.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Assets/SEE/Cinemachines/Utility/CinemachinesUtility.cs b/Assets/SEE/Cinemachines/Utility/CinemachinesUtility.cs index 182d5f8ce3..d5649db26c 100644 --- a/Assets/SEE/Cinemachines/Utility/CinemachinesUtility.cs +++ b/Assets/SEE/Cinemachines/Utility/CinemachinesUtility.cs @@ -624,7 +624,7 @@ internal static CinemachinesRoot[] FindAllCinemachinesRootsInScene() internal static void CreateCinemachinesRoot() { // Create a new CinemachinesRoot at the Root of the Scene - GameObject newRoot = new GameObject("CinemachinesRoot", typeof(CinemachinesRoot)); + new GameObject("CinemachinesRoot", typeof(CinemachinesRoot)); } /// @@ -687,8 +687,6 @@ internal static void GenerateSceneStructure(GameObject scene, string sceneName) { // Create Scene Folder string sceneRootGUID = GenerateSceneFolder(sceneName); - // assign Scene-Folder to Scene-GameObject - string scenePath = AssetDatabase.GUIDToAssetPath(sceneRootGUID); // Add the CinemachinesScenes Component to the newly created Scene GameObject scene.GetComponent().SceneGUID = sceneRootGUID; From 5a7b32aab8f9b73fcef6540042ce4f466619793f Mon Sep 17 00:00:00 2001 From: Rainer Koschke Date: Mon, 10 Aug 2026 11:15:37 +0200 Subject: [PATCH 09/16] #922 Fixed a few minor coding issues. --- .../Utility/CinemachinesUtility.cs | 56 ++++++++----------- 1 file changed, 23 insertions(+), 33 deletions(-) diff --git a/Assets/SEE/Cinemachines/Utility/CinemachinesUtility.cs b/Assets/SEE/Cinemachines/Utility/CinemachinesUtility.cs index d5649db26c..0f4a7b4e3c 100644 --- a/Assets/SEE/Cinemachines/Utility/CinemachinesUtility.cs +++ b/Assets/SEE/Cinemachines/Utility/CinemachinesUtility.cs @@ -225,7 +225,8 @@ private void DeserializeReferences() int objectInstanceID; if (referenceList.ContainsKey(storedReference.InstanceID)) { - // This part is not working correctly, since Unity differenciates InstanceIDs from actual Objects and References + // This part is not working correctly, since Unity differentiates InstanceIDs + // from actual Objects and References objectInstanceID = referenceList[storedReference.InstanceID]; } else @@ -310,7 +311,7 @@ private Transform Deserialize(StoredGameObject storedGameObject) { referenceList.Add(storedComponent.InstanceID, readComponent.GetInstanceID()); } - catch (Exception _) + catch (Exception) { Debug.LogWarning($"Attempted to Map '{storedComponent.InstanceID}' to '{readComponent.GetInstanceID()}'"); } @@ -349,7 +350,8 @@ internal Transform Deserialize(string jsonData) } /// - /// Constructor for the Cinemachines State Restorer, which enables an Event to restore changes made inside CinemachinesRoot to be re-applied after exiting PlayMode. + /// Constructor for the Cinemachines State Restorer, which enables an Event to restore changes + /// made inside CinemachinesRoot to be re-applied after exiting PlayMode. /// static CinemachinesStateRestorer() { @@ -371,17 +373,12 @@ private static void Save(string unitySceneName) return; } - // JSON storage - string serializedData = ""; - // Serialize ScenesRoot Serializer serializer = new Serializer(); StoredGameObject storedGameObject = serializer.Serialize(cinemachinesRootTransform); - serializedData = JsonUtility.ToJson(storedGameObject); - // Store generated JSON inside EditorPrefs for persistance - EditorPrefs.SetString($"{unitySceneName}.{CinemachinesPersistanceKeyName}", serializedData); + EditorPrefs.SetString($"{unitySceneName}.{CinemachinesPersistanceKeyName}", JsonUtility.ToJson(storedGameObject)); } /// @@ -396,20 +393,17 @@ private static void Load(Scene unityScene) { return; } - // JSON storage - string serializedData = ""; // prepare deserializer - Deserializer deserializer = new Deserializer(); - serializedData = EditorPrefs.GetString(serializedDataKeyName); + Deserializer deserializer = new(); // get stored scenes-data with deserializer - Transform restoredObject = deserializer.Deserialize(serializedData); + deserializer.Deserialize(EditorPrefs.GetString(serializedDataKeyName)); // Display warning about referencing original Objects EditorUtility.DisplayDialog( "Restoration of Cinemachines", - "Warning! The restored Backup is using parts of the original Cinemachine Structure.\nPlease check the Timelines and other Objects and update these components to their restored equivalents before continuing.", + "Warning! The restored backup is using parts of the original Cinemachine Structure.\nPlease check the Timelines and other Objects and update these components to their restored equivalents before continuing.", "Okay" ); @@ -428,19 +422,23 @@ private static string[] GetRestorableScenes() { // find all Unity-Scenes in Project string[] scenesGUIDs = AssetDatabase.FindAssets("t:Scene"); - List scenesPaths = new List(); + List scenesPaths = new(); foreach (string guid in scenesGUIDs) + { scenesPaths.Add(AssetDatabase.GUIDToAssetPath(guid)); + } - StringBuilder result = new StringBuilder(); + StringBuilder result = new(); foreach (string scenePath in scenesPaths) { // check, if scene-path starts at the correct location // doing so will exclude every example scene from Extensions if (!scenePath.StartsWith("Assets/Scenes")) + { continue; + } // Logic for trimming the path down to the File-name of the Scene int ToDeleteSuffixLength = ".unity".Length; @@ -450,7 +448,9 @@ private static string[] GetRestorableScenes() // checking, if a persistance key for the scene exists string prefKeyName = $"{UnitySceneName}.{CinemachinesPersistanceKeyName}"; if (EditorPrefs.HasKey(prefKeyName)) + { result.AppendFormat("{0}\n", UnitySceneName); + } } return result.ToString().Split('\n'); @@ -685,11 +685,8 @@ internal static void GenerateCinemachinesPrefabFolder() /// The Name of the Cinemachines-Scene. internal static void GenerateSceneStructure(GameObject scene, string sceneName) { - // Create Scene Folder - string sceneRootGUID = GenerateSceneFolder(sceneName); - // Add the CinemachinesScenes Component to the newly created Scene GameObject - scene.GetComponent().SceneGUID = sceneRootGUID; + scene.GetComponent().SceneGUID = GenerateSceneFolder(sceneName); } /// @@ -701,7 +698,7 @@ internal static void GenerateSceneStructure(GameObject scene, string sceneName) /// Fully constructed Name for the Object. internal static string GetNewObjectName(string objectType, ref int objectCount, ref string suffixText) { - if (objectType == string.Empty || objectType == null) + if (string.IsNullOrEmpty(objectType)) { throw new ArgumentException("objectType string cannot be empty or null"); } @@ -731,10 +728,11 @@ internal static string GetNewObjectName(string objectType, ref int objectCount, /// The Component to add to the newly created GameObject. By default, it will not add any components. /// Whether the newly created GameObject should be selected or not. By default, it will get selected. /// Gets thrown, if either the objectType and/or rootGameObject are not defined or invalid. - internal static void CreateGameObject(string objectType, ref int objectCount, ref string suffixText, GameObject rootGameObject, System.Type componentToAdd = null, bool shouldBeFocused = true) + internal static void CreateGameObject(string objectType, ref int objectCount, ref string suffixText, + GameObject rootGameObject, System.Type componentToAdd = null, bool shouldBeFocused = true) { // Throw exception, if objectType is empty or null - if (objectType == string.Empty || objectType == null) + if (string.IsNullOrEmpty(objectType)) { throw new ArgumentException("objectType string cannot be empty or null."); } @@ -747,16 +745,8 @@ internal static void CreateGameObject(string objectType, ref int objectCount, re string objectName = GetNewObjectName(objectType, ref objectCount, ref suffixText); - GameObject newObject; + GameObject newObject = componentToAdd == null ? new GameObject(objectName) : new GameObject(objectName, componentToAdd); // Create a new GameObject, and place it in under the correct GameObject - if (componentToAdd == null) - { - newObject = new GameObject(objectName); - } - else - { - newObject = new GameObject(objectName, componentToAdd); - } newObject.transform.SetParent(rootGameObject.transform); // Select newly created GameObject From d2231787186008cb84480ccd0a74c73567b0ac81 Mon Sep 17 00:00:00 2001 From: Rainer Koschke Date: Mon, 10 Aug 2026 11:47:20 +0200 Subject: [PATCH 10/16] #922 More minor code improvements. --- Assets/SEE/Cinemachines/CinemachinesRoot.cs | 25 ++++++-------- .../Utility/CinemachinesUtility.cs | 34 +++++++++---------- 2 files changed, 28 insertions(+), 31 deletions(-) diff --git a/Assets/SEE/Cinemachines/CinemachinesRoot.cs b/Assets/SEE/Cinemachines/CinemachinesRoot.cs index 5845eaad18..0c8efd14bc 100644 --- a/Assets/SEE/Cinemachines/CinemachinesRoot.cs +++ b/Assets/SEE/Cinemachines/CinemachinesRoot.cs @@ -1,9 +1,7 @@ using SEE.UI.RuntimeConfigMenu; using SEE.Cinemachines.Utility; using SEE.UI.PictureInPicture; -using SEE.Utils; using Sirenix.OdinInspector; -using Sirenix.Serialization; using System; using System.Collections.Generic; using UnityEngine; @@ -12,12 +10,12 @@ using UnityEngine.Experimental.Rendering; using Debug = UnityEngine.Debug; using UnityEditor; -using UnityEditor.EditorTools; namespace SEE.Cinemachines { /// - /// Cinemachines Component, that initializes a Folder Structure inside the Project, specifically for Cinemachine and all of its associated components and elements. + /// Cinemachines Component, that initializes a Folder Structure inside the Project, specifically for + /// Cinemachine and all of its associated components and elements. /// [Serializable] [ExecuteInEditMode] @@ -44,13 +42,13 @@ internal class CinemachinesRoot : SerializedMonoBehaviour /// The GUID of the RenderTexture assign with capturing the Cinemachine-Output. /// [HideInInspector, SerializeField] - private UnityEditor.GUID mainOutputGUID; + private GUID mainOutputGUID; /// /// The GUID of the RenderTexture associated with the Picture-In-Picture Option. /// [HideInInspector, SerializeField] - private UnityEditor.GUID pictureInPictureGUID; + private GUID pictureInPictureGUID; /// /// Root of the Cinemachine-Brains GameObjects. @@ -72,13 +70,13 @@ internal class CinemachinesRoot : SerializedMonoBehaviour /// protected void Start() { - // Ensure, that only one CinemachinesRoot exists per Scene + // Ensure, that only one CinemachinesRoot exists per scene // var possibleRoots = UnityEngine.Object.FindObjectsByType(FindObjectsInactive.Exclude, FindObjectsSortMode.None); CinemachinesRoot[] possibleRoots = CinemachinesUtility.FindAllCinemachinesRootsInScene(); if (possibleRoots.Length > 1) { - Debug.LogError("Multiple CinemachinesRoot are not supported. Only use one per Unity-Scene."); + Debug.LogError("Multiple CinemachinesRoot are not supported. Only use one per Unity-Scene.\n"); // Disable GameObject gameObject.SetActive(false); @@ -87,7 +85,7 @@ protected void Start() return; } - // If the CinemachinesRoot has not been initialized on Start, initialize it + // If the CinemachinesRoot has not been initialized on Start, initialize it. if (!isInitialized) { SetupCinemachinesRoot(); @@ -95,11 +93,11 @@ protected void Start() } /// - /// Update Function to run on every Frame. Unused on this Component. + /// Update Function to run on every Frame. Unused on this component. /// protected void Update() { - // Intentionally left blank + // Intentionally left blank. } #region Root Maintenance @@ -123,13 +121,12 @@ internal void SetupCinemachinesRoot() // build the folder structure under "Assets/Cinemachine" CreateCinemachineFolderStructure(); - // Either Create or Confirm existance of the RenderTextures. + // Either Create or Confirm existence of the RenderTextures. CreateRenderTextures(); isInitialized = true; } - /// /// Resets the CinemachinesRoot. /// @@ -144,7 +141,7 @@ internal void ResetCinemachinesRoot() isInitialized = false; // clear children of CinemachinesRoot - List rootChildren = new List(); + List rootChildren = new(); rootChildren.Add(transform.Find(CinemachinesUtility.CinemachinesBrainsName)); rootChildren.Add(transform.Find(CinemachinesUtility.CinemachinesScenesName)); diff --git a/Assets/SEE/Cinemachines/Utility/CinemachinesUtility.cs b/Assets/SEE/Cinemachines/Utility/CinemachinesUtility.cs index 0f4a7b4e3c..45bf350823 100644 --- a/Assets/SEE/Cinemachines/Utility/CinemachinesUtility.cs +++ b/Assets/SEE/Cinemachines/Utility/CinemachinesUtility.cs @@ -1,18 +1,15 @@ using System; using System.Text; -using System.IO; using System.Collections.Generic; using System.Reflection; using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.Timeline; -using UnityEngine.Events; using UnityEngine.Playables; using UnityEditor; -using Unity.Cinemachine; -using SEE.Cinemachines; -namespace SEE.Cinemachines.Utility { +namespace SEE.Cinemachines.Utility +{ /// /// Static Utility-Class for general functions shared between the custom Cinemachines Components. /// @@ -31,6 +28,10 @@ internal static class CinemachinesUtility internal const string CinemachinesPersistanceKeyName = "CinemachinesPersistanceKey"; internal const string CinemachinesPersistanceKeyRestorableName = "CinemachinesPersistanceKeyRestorable"; + /// + /// The name of the root GameObject, that contains all Cinemachines related GameObjects in the scene. + /// + private const string CinemachinesRootName = "CinemachinesRoot"; #endregion Constant String names /// @@ -62,7 +63,7 @@ internal class StoredComponent // Component Data public int InstanceID; public string JSONContent; - public List ListReferences = new List(); + public List ListReferences = new(); } /// @@ -74,11 +75,11 @@ internal class StoredGameObject // Data of this GameObject public int InstanceID; public string JSONGameObject; - public List ListComponents = new List(); + public readonly List ListComponents = new(); // List of Children inside this GameObject [SerializeReference] - public List ChildGameObjects = new List(0); + public List ChildGameObjects = new(); } /// @@ -94,10 +95,10 @@ internal class Serializer private List SerializeReference(Component component) { // List for storing required References, that can not be applied normally - List referenceList = new List(); + List referenceList = new(); // Create SerializedObject from the Object/Component and get its SerializedProperty as an Iterator - SerializedObject serializedObject = new SerializedObject(component); + SerializedObject serializedObject = new(component); SerializedProperty propertyIterator = serializedObject.GetIterator(); // while there still are properties @@ -262,17 +263,16 @@ private void DeserializeReferences() private Transform Deserialize(StoredGameObject storedGameObject) { // Find Object as Child of rootTransform - GameObject restoredGameObject = new GameObject(); + GameObject restoredGameObject = new(); EditorJsonUtility.FromJsonOverwrite(storedGameObject.JSONGameObject, restoredGameObject); // Iterate through all Components for this GameObject foreach (StoredComponent storedComponent in storedGameObject.ListComponents) { - // Reconstruct Type of this Component - Component readComponent = null; Type ComponentType = Assembly.Load(storedComponent.AssemblyName).GetType(storedComponent.TypeName); - // check, if the component is a Transform + // Reconstruct type of this component. + Component readComponent; if (ComponentType == typeof(Transform)) { readComponent = restoredGameObject.transform; @@ -313,7 +313,7 @@ private Transform Deserialize(StoredGameObject storedGameObject) } catch (Exception) { - Debug.LogWarning($"Attempted to Map '{storedComponent.InstanceID}' to '{readComponent.GetInstanceID()}'"); + Debug.LogWarning($"Attempted to Map '{storedComponent.InstanceID}' to '{readComponent.GetInstanceID()}'\n"); } } @@ -623,8 +623,8 @@ internal static CinemachinesRoot[] FindAllCinemachinesRootsInScene() [MenuItem("GameObject/SEE/Cinemachines/Create Cinemachines Root", false, 10)] internal static void CreateCinemachinesRoot() { - // Create a new CinemachinesRoot at the Root of the Scene - new GameObject("CinemachinesRoot", typeof(CinemachinesRoot)); + // Create a new CinemachinesRoot at the root of the scene + new GameObject(CinemachinesRootName, typeof(CinemachinesRoot)); } /// From 8a16a6a21512a9c026dc7e823ee2d94a575c3622 Mon Sep 17 00:00:00 2001 From: Rainer Koschke Date: Mon, 10 Aug 2026 11:55:39 +0200 Subject: [PATCH 11/16] #922 Added \n at the end of Debug.Log* messages. --- Assets/SEE/Cinemachines/CinemachinesRoot.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Assets/SEE/Cinemachines/CinemachinesRoot.cs b/Assets/SEE/Cinemachines/CinemachinesRoot.cs index 0c8efd14bc..59b5a89dc9 100644 --- a/Assets/SEE/Cinemachines/CinemachinesRoot.cs +++ b/Assets/SEE/Cinemachines/CinemachinesRoot.cs @@ -359,15 +359,15 @@ private void CreateRenderTextures() switch(child.name) { case "CMC_MainPicture": - Debug.Log("Found Main Cinemachine Brain"); + Debug.Log("Found Main Cinemachine Brain.\n"); child.GetComponent().targetTexture = AssetDatabase.LoadAssetByGUID(mainOutputGUID); break; case "CMC_PictureInPicture": - Debug.Log("Found PIP Cinemachine Brain"); + Debug.Log("Found PIP Cinemachine Brain.\n"); child.GetComponent().targetTexture = AssetDatabase.LoadAssetByGUID(pictureInPictureGUID); break; default: - Debug.LogWarning("Failed to find CinemachineBrains"); + Debug.LogWarning("Failed to find CinemachineBrains.\n"); break; } } From 8d524f71c1c13f4453c1524438f8f7a6695c6d5c Mon Sep 17 00:00:00 2001 From: Rainer Koschke Date: Mon, 10 Aug 2026 11:57:53 +0200 Subject: [PATCH 12/16] #922 Tooltip not applicable here. Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- Assets/SEE/Cinemachines/Dolly/SimpleSpeedController.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/Assets/SEE/Cinemachines/Dolly/SimpleSpeedController.cs b/Assets/SEE/Cinemachines/Dolly/SimpleSpeedController.cs index 487dd1e8a4..37f5983ea9 100644 --- a/Assets/SEE/Cinemachines/Dolly/SimpleSpeedController.cs +++ b/Assets/SEE/Cinemachines/Dolly/SimpleSpeedController.cs @@ -10,7 +10,6 @@ namespace SEE.Cinemachines.Dolly /// /// Class for a simple implementation of a Speed Controller, based on which section of the Spline the Object is. /// - [Tooltip("A simplistic Speed Controller for SplineAutoDolly on CinemachineSplineDolly, which apply fixed Speeds on SplineSegments")] [Serializable] public class SimpleSpeedController : SplineAutoDolly.ISplineAutoDolly { From e9cbc5e215d8aee7096b4073e9e3f83d1456c524 Mon Sep 17 00:00:00 2001 From: Anton Siebert Date: Wed, 12 Aug 2026 21:15:57 +0200 Subject: [PATCH 13/16] #922 applied suggestions, encased every component inside '#if UNITY_EDITOR' pre-processor directive and moved the CinemachinesStateRestorer into its own file inside 'SEEEditor' to clarify that it is only for the Editor. --- .../Cinemachines.meta} | 5 +- Assets/Editor/Cinemachines/Cinemachines.cs | 6 + .../Editor/Cinemachines/Cinemachines.cs.meta | 2 + Assets/Editor/Cinemachines/Utility.meta | 8 + .../Utility/CinemachinesStateRestorer.cs | 589 +++++++++++++++++ .../Utility/CinemachinesStateRestorer.cs.meta | 2 + Assets/Editor/Cinemachines/Utility/Utility.cs | 6 + .../Cinemachines/Utility/Utility.cs.meta | 2 + Assets/Editor/SEE_Editor.asmdef | 3 +- .../Prefabs/Cinemachines/SceneTemplate.prefab | 223 ------- .../PictureInPicture/{pip.asset => PIP.asset} | 2 +- .../{pip.asset.meta => PIP.asset.meta} | 0 .../{pip-camera.uxml => PIPCamera.uxml} | 0 ...p-camera.uxml.meta => PIPCamera.uxml.meta} | 0 ...ipDataSource.asset => PIPDataSource.asset} | 2 +- ...ce.asset.meta => PIPDataSource.asset.meta} | 0 .../SEE/Cinemachines/CinemachineSceneRoot.cs | 47 +- Assets/SEE/Cinemachines/CinemachinesRoot.cs | 71 +- .../Dolly/SimpleSpeedController.cs | 19 +- Assets/SEE/Cinemachines/UI.meta | 8 + .../UI/PictureInPicture.meta | 0 .../UI/PictureInPicture/PIPDataSource.cs} | 9 +- .../PictureInPicture/PIPDataSource.cs.meta} | 0 .../UI/PictureInPicture/PictureInPicture.cs | 2 +- .../PictureInPicture/PictureInPicture.cs.meta | 0 Assets/SEE/Cinemachines/UI/UI.cs | 6 + Assets/SEE/Cinemachines/UI/UI.cs.meta | 3 + .../Utility/CinemachinesUtility.cs | 616 ++---------------- Assets/SEE/SEE.asmdef | 3 +- 29 files changed, 763 insertions(+), 871 deletions(-) rename Assets/{Resources/Prefabs/Cinemachines/SceneTemplate.prefab.meta => Editor/Cinemachines.meta} (57%) create mode 100644 Assets/Editor/Cinemachines/Cinemachines.cs create mode 100644 Assets/Editor/Cinemachines/Cinemachines.cs.meta create mode 100644 Assets/Editor/Cinemachines/Utility.meta create mode 100644 Assets/Editor/Cinemachines/Utility/CinemachinesStateRestorer.cs create mode 100644 Assets/Editor/Cinemachines/Utility/CinemachinesStateRestorer.cs.meta create mode 100644 Assets/Editor/Cinemachines/Utility/Utility.cs create mode 100644 Assets/Editor/Cinemachines/Utility/Utility.cs.meta delete mode 100644 Assets/Resources/Prefabs/Cinemachines/SceneTemplate.prefab rename Assets/Resources/UI/PictureInPicture/{pip.asset => PIP.asset} (99%) rename Assets/Resources/UI/PictureInPicture/{pip.asset.meta => PIP.asset.meta} (100%) rename Assets/Resources/UI/PictureInPicture/{pip-camera.uxml => PIPCamera.uxml} (100%) rename Assets/Resources/UI/PictureInPicture/{pip-camera.uxml.meta => PIPCamera.uxml.meta} (100%) rename Assets/Resources/UI/PictureInPicture/{pipDataSource.asset => PIPDataSource.asset} (95%) rename Assets/Resources/UI/PictureInPicture/{pipDataSource.asset.meta => PIPDataSource.asset.meta} (100%) create mode 100644 Assets/SEE/Cinemachines/UI.meta rename Assets/SEE/{ => Cinemachines}/UI/PictureInPicture.meta (100%) rename Assets/SEE/{UI/PictureInPicture/pipDataSource.cs => Cinemachines/UI/PictureInPicture/PIPDataSource.cs} (81%) rename Assets/SEE/{UI/PictureInPicture/pipDataSource.cs.meta => Cinemachines/UI/PictureInPicture/PIPDataSource.cs.meta} (100%) rename Assets/SEE/{ => Cinemachines}/UI/PictureInPicture/PictureInPicture.cs (79%) rename Assets/SEE/{ => Cinemachines}/UI/PictureInPicture/PictureInPicture.cs.meta (100%) create mode 100644 Assets/SEE/Cinemachines/UI/UI.cs create mode 100644 Assets/SEE/Cinemachines/UI/UI.cs.meta diff --git a/Assets/Resources/Prefabs/Cinemachines/SceneTemplate.prefab.meta b/Assets/Editor/Cinemachines.meta similarity index 57% rename from Assets/Resources/Prefabs/Cinemachines/SceneTemplate.prefab.meta rename to Assets/Editor/Cinemachines.meta index 22ae8724da..0b5b0b7d85 100644 --- a/Assets/Resources/Prefabs/Cinemachines/SceneTemplate.prefab.meta +++ b/Assets/Editor/Cinemachines.meta @@ -1,6 +1,7 @@ fileFormatVersion: 2 -guid: 4da1e676a502999a8b0c07ee95b6067b -PrefabImporter: +guid: 1fb66347d7bcb72e08f752c8bffb4121 +folderAsset: yes +DefaultImporter: externalObjects: {} userData: assetBundleName: diff --git a/Assets/Editor/Cinemachines/Cinemachines.cs b/Assets/Editor/Cinemachines/Cinemachines.cs new file mode 100644 index 0000000000..edf3aa64b1 --- /dev/null +++ b/Assets/Editor/Cinemachines/Cinemachines.cs @@ -0,0 +1,6 @@ +/// +/// Namespace for the Cinemachines, specific for the fully Editor-Only components. +/// +namespace SEEEditor.Cinemachines +{ +} diff --git a/Assets/Editor/Cinemachines/Cinemachines.cs.meta b/Assets/Editor/Cinemachines/Cinemachines.cs.meta new file mode 100644 index 0000000000..a3f4c8b2ae --- /dev/null +++ b/Assets/Editor/Cinemachines/Cinemachines.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: ae9645c696ed3dbf3a378ecb9748f8ad \ No newline at end of file diff --git a/Assets/Editor/Cinemachines/Utility.meta b/Assets/Editor/Cinemachines/Utility.meta new file mode 100644 index 0000000000..8bf2a5656a --- /dev/null +++ b/Assets/Editor/Cinemachines/Utility.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e15f2758241322b9a960083e6e5e4808 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor/Cinemachines/Utility/CinemachinesStateRestorer.cs b/Assets/Editor/Cinemachines/Utility/CinemachinesStateRestorer.cs new file mode 100644 index 0000000000..ec8557731c --- /dev/null +++ b/Assets/Editor/Cinemachines/Utility/CinemachinesStateRestorer.cs @@ -0,0 +1,589 @@ +using System; +using System.Text; +using System.Collections.Generic; +using System.Reflection; +using UnityEngine; +using UnityEngine.Timeline; +using UnityEngine.Playables; +using UnityEngine.SceneManagement; + +using SEE.Cinemachines; +using SEE.Cinemachines.Utility; + +#if UNITY_EDITOR + +using UnityEditor; + +#endif + +namespace SEEEditor.Cinemachines.Utility +{ + /// + /// Class for Restoring GameObjects related to the Cinemachines. + /// Based on work done by inkle Studios: https://github.com/inkle/Unity-Save-Play-Mode-Changes under MIT License + /// + [InitializeOnLoad] + internal static class CinemachinesStateRestorer + { + /// + /// Structure-Class for storing References of Components in a serializable form. + /// + [Serializable] + internal class StoredReference + { + public int InstanceID; + public bool IsNull; + } + + /// + /// Structure-Class for storing Components inside GameObjects in a serializable form. + /// + [Serializable] + internal class StoredComponent + { + // Data for reconstructing the Type + public string AssemblyName; + public string TypeName; + + // Component Data + public int InstanceID; + public string JSONContent; + public List ListReferences = new(); + } + + /// + /// Structure-Class for storing GameObjects in a serializable form. + /// + [Serializable] + internal class StoredGameObject + { + // Data of this GameObject + public int InstanceID; + public string JSONGameObject; + public readonly List ListComponents = new(); + + // List of Children inside this GameObject + [SerializeReference] + public List ChildGameObjects = new(); + } + + /// + /// Implementation of a Serializer to store changes made in PlayMode persistently. + /// + internal class Serializer + { + /// + /// Helper-Function to Serialize References inside Components. + /// + /// The Component to be serialized. + /// List of StoredReferences, that will be included to the respective Component. + private List SerializeReference(Component component) + { + // List for storing required References, that can not be applied normally + List referenceList = new(); + + // Create SerializedObject from the Object/Component and get its SerializedProperty as an Iterator + SerializedObject serializedObject = new(component); + SerializedProperty propertyIterator = serializedObject.GetIterator(); + + // while there still are properties + while (propertyIterator.NextVisible(true)) + { + // check, if the type of property is relevant to us + if (propertyIterator.propertyType == SerializedPropertyType.ObjectReference) + { + StoredReference storedReference = new(); + + // get Object referenced in Property + UnityEngine.Object objectReference = propertyIterator.objectReferenceValue; + + // setup StoredReference appropriatly, based on if its null or not + switch (objectReference) + { + case null: + storedReference.IsNull = true; + break; + default: + storedReference.InstanceID = objectReference.GetInstanceID(); + storedReference.IsNull = false; + break; + } + + referenceList.Add(storedReference); + } + } + + return referenceList; + } + + /// + /// Serializing Function for Transforms and their associated Data. + /// + /// The GameObject to be serialized. + /// Returns a StoredGameObject, that can be serialized into JSON. + internal StoredGameObject Serialize(Transform rootObject) + { + StoredGameObject storedGameObject = new(); + + // Store base Data of this Object into the StoredGameObject + storedGameObject.InstanceID = rootObject.GetInstanceID(); + storedGameObject.JSONGameObject = EditorJsonUtility.ToJson(rootObject.gameObject); + + // iterate through all components + foreach (Component component in rootObject.GetComponents(typeof(Component))) + { + StoredComponent storedComponent = new(); + + // deconstruct the type of the Component + storedComponent.AssemblyName = component.GetType().Assembly.GetName().Name; + storedComponent.TypeName = component.GetType().FullName; + + // store base data of this Component + storedComponent.InstanceID = component.GetInstanceID(); + storedComponent.JSONContent = EditorJsonUtility.ToJson(component); + + // serialize references made inside component + storedComponent.ListReferences = SerializeReference(component); + + storedGameObject.ListComponents.Add(storedComponent); + } + + // re-iterate through all GameObjects, that are a child of this Object + // needs to be done in a depth-first way + foreach (Transform child in rootObject) + { + storedGameObject.ChildGameObjects.Add(Serialize(child)); + } + + return storedGameObject; + } + } + + /// + /// Implementation of a Deserializer to store changes made in PlayMode persistently. + /// + internal class Deserializer + { + /// + /// Temporary Dictionary for storing InstanceIDs of Objects with their respective StoredProperties. + /// + private Dictionary> storedReferences = new(); + + /// + /// Reference List between original InstanceIDs and restored IDs. + /// + private Dictionary referenceList = new(); + + /// + /// Helper-Function to Deserialize References inside Components, like Transform, UnityEvents, etc. + /// + private void DeserializeReferences() + { + // Loop through every KeyValuePair in the storedReferences + foreach (var kvp in storedReferences) + { + // Find the Object/Component, you want to apply the References to + UnityEngine.Object restoredObject = Resources.InstanceIDToObject(kvp.Key); + + // create SerializedObject and Property + SerializedObject serializedObject = new(restoredObject); + SerializedProperty propertyIterator = serializedObject.GetIterator(); + + // get the stored References list from the KeyValuePair + List storedReferencesList = kvp.Value; + + // local Counter for iterating through the storedReferences for this Object + int Index = 0; + + // check, if there is still a Property accessable + while (propertyIterator.NextVisible(true)) + { + // check, if the type of the Property is relevant to us + if (propertyIterator.propertyType == SerializedPropertyType.ObjectReference) + { + // Select the indexed StoredReference, which potentially needs to be applied + StoredReference storedReference = storedReferencesList[Index]; + + // If the StoredReference was null, ignore it, ... + if (!storedReference.IsNull) + { + // ... else get the Object by InstanceID and apply it + int objectInstanceID; + if (referenceList.ContainsKey(storedReference.InstanceID)) + { + // This part is not working correctly, since Unity differentiates InstanceIDs + // from actual Objects and References + objectInstanceID = referenceList[storedReference.InstanceID]; + } + else + { + objectInstanceID = storedReference.InstanceID; + } + + UnityEngine.Object objectReference = Resources.InstanceIDToObject(objectInstanceID); + + if (objectReference == null) + { + Debug.LogWarning($"Object with InstanceID '{objectInstanceID}' does not exist.\n Maybe the Object was created during Runtime, which must then be manually recreated and reapplied."); + } + + propertyIterator.objectReferenceValue = objectReference; + } + + // Increment Index for next Reference + Index++; + } + } + + // Apply all modified Properties to the SerializedObject, which applies the changes to the regular Objects/Components + serializedObject.ApplyModifiedProperties(); + } + } + + /// + /// Actual Deserializing Method, which returns the root transform. + /// + /// The StoredGameObject, that will be restored to actual GameObjects. + /// The Transform reconstructed from the StoredGameObject, including their Children. + private Transform Deserialize(StoredGameObject storedGameObject) + { + // Find Object as Child of rootTransform + GameObject restoredGameObject = new(); + EditorJsonUtility.FromJsonOverwrite(storedGameObject.JSONGameObject, restoredGameObject); + + // Iterate through all Components for this GameObject + foreach (StoredComponent storedComponent in storedGameObject.ListComponents) + { + Type ComponentType = Assembly.Load(storedComponent.AssemblyName).GetType(storedComponent.TypeName); + + // Reconstruct type of this component. + Component readComponent; + if (ComponentType == typeof(Transform)) + { + readComponent = restoredGameObject.transform; + } + else if (ComponentType == typeof(PlayableDirector)) + { + readComponent = restoredGameObject.GetComponent(); + + if (readComponent == null) + { + readComponent = restoredGameObject.AddComponent(typeof(PlayableDirector)); + } + } + else if (ComponentType == typeof(SignalReceiver)) + { + readComponent = restoredGameObject.GetComponent(); + + if (readComponent == null) + { + readComponent = restoredGameObject.AddComponent(typeof(SignalReceiver)); + } + } + else + { + readComponent = restoredGameObject.AddComponent(ComponentType); + } + + // apply Data onto the component + EditorJsonUtility.FromJsonOverwrite(storedComponent.JSONContent, readComponent); + + // store References, that might need to be applied after everything has been applied + try + { + storedReferences.Add(readComponent.GetInstanceID(), storedComponent.ListReferences); + } + catch (Exception) + { + Debug.LogWarning($"Attempted to Map '{readComponent.GetInstanceID()}' to a References List, while already having one accosiated to it.\n"); + } + + // store mapping of old InstanceID to new InstanceID for Components + try + { + referenceList.Add(storedComponent.InstanceID, readComponent.GetInstanceID()); + } + catch (Exception) + { + Debug.LogWarning($"Attempted to Map '{storedComponent.InstanceID}' to '{readComponent.GetInstanceID()}'\n"); + } + } + + // Iterate depth-first through all child GameObjects + foreach (StoredGameObject childStoredGameObject in storedGameObject.ChildGameObjects) + { + Transform child = Deserialize(childStoredGameObject); + + // reposition accordingly + child.SetParent(restoredGameObject.transform); + } + + return restoredGameObject.transform; + } + + /// + /// Primer Deserializer Function for GameObjects, initialized by inputing serialized Data. + /// + /// The serialized data, that will be restored from. + /// The restored Transform, including restored components and children. + internal Transform Deserialize(string jsonData) + { + // Deserialize first layer + StoredGameObject storedGameObject = JsonUtility.FromJson(jsonData); + + // Reconstruct root GameObject from deserialized Data + Transform restoredRootTransform = Deserialize(storedGameObject); + + // apply references to gameObject + DeserializeReferences(); + + return restoredRootTransform; + } + } + + /// + /// Constructor for the Cinemachines State Restorer, which enables an Event to restore changes + /// made inside CinemachinesRoot to be re-applied after exiting PlayMode. + /// + static CinemachinesStateRestorer() + { + // Register new Event for restoring changes made in PlayMode + EditorApplication.playModeStateChanged += StoreCinemachinesChanges; + } + + /// + /// Save function, utilizing the custom Serializer Class for Cinemachines. + /// + /// The Name of the Unity-Scene, that the Object will be stored from. + private static void Save(string unitySceneName) + { + // Locating CinemachinesRoot + Transform cinemachinesRootTransform = CinemachinesUtility.GetCinemachinesRootInScene(); + + if (cinemachinesRootTransform == null) + { + return; + } + + // Serialize ScenesRoot + Serializer serializer = new(); + StoredGameObject storedGameObject = serializer.Serialize(cinemachinesRootTransform); + + // Store generated JSON inside EditorPrefs for persistance + EditorPrefs.SetString($"{unitySceneName}.{CinemachinesUtility.CinemachinesPersistanceKeyName}", JsonUtility.ToJson(storedGameObject)); + } + + /// + /// Load function, utilizing the custom Deserializer Class for Cinemachines. + /// + /// The Unity-Scene to reconstruct the serialized GameObjects. + private static void Load(Scene unityScene) + { + string serializedDataKeyName = $"{unityScene.name}.{CinemachinesUtility.CinemachinesPersistanceKeyName}"; + + if (!EditorPrefs.HasKey(serializedDataKeyName)) + { + return; + } + + // prepare deserializer + Deserializer deserializer = new(); + + // get stored scenes-data with deserializer + deserializer.Deserialize(EditorPrefs.GetString(serializedDataKeyName)); + + // Display warning about referencing original Objects + EditorUtility.DisplayDialog( + "Restoration of Cinemachines", + "Warning! The restored backup is using parts of the original Cinemachine Structure.\nPlease check the Timelines and other Objects and update these components to their restored equivalents before continuing.", + "Okay" + ); + + // Reset PersistanceKey + if (EditorPrefs.HasKey(serializedDataKeyName)) + { + EditorPrefs.DeleteKey(serializedDataKeyName); + } + } + + /// + /// Helper-Function to get Unity-Scene names with CinemachineRoot-Backups. + /// + /// Name of Unity-Scenes, that have GameObject backups. + private static string[] GetRestorableScenes() + { + // find all Unity-Scenes in Project + string[] scenesGUIDs = AssetDatabase.FindAssets("t:Scene"); + List scenesPaths = new(); + + foreach (string guid in scenesGUIDs) + { + scenesPaths.Add(AssetDatabase.GUIDToAssetPath(guid)); + } + + StringBuilder result = new(); + + foreach (string scenePath in scenesPaths) + { + // check, if scene-path starts at the correct location + // doing so will exclude every example scene from Extensions + if (!scenePath.StartsWith("Assets/Scenes")) + { + continue; + } + + // Logic for trimming the path down to the File-name of the Scene + int ToDeleteSuffixLength = ".unity".Length; + string[] UnitySceneNameSplit = scenePath.Remove(scenePath.Length - ToDeleteSuffixLength, ToDeleteSuffixLength).Split('/'); + string UnitySceneName = UnitySceneNameSplit[UnitySceneNameSplit.Length - 1]; + + // checking, if a persistance key for the scene exists + string prefKeyName = $"{UnitySceneName}.{CinemachinesUtility.CinemachinesPersistanceKeyName}"; + if (EditorPrefs.HasKey(prefKeyName)) + { + result.AppendFormat("{0}\n", UnitySceneName); + } + } + + return result.ToString().Split('\n'); + } + + /// + /// Display Function to get list of restorable scenes. + /// + [MenuItem("SEE/Cinemachines/Get restorable Cinemachine Roots", false, 12)] + internal static void GetRestorableRoots() + { + // String Builder for Dialog Body, which includes the names of the Scenes, that can restore a CinemachinesRoot + StringBuilder stringBuilder = new("The CinemachineRoots of the following Unity-Scenes have been backed up.\n"); + string[] restorableScenes = GetRestorableScenes(); + + // Format Scene Names + foreach (string scene in restorableScenes) + { + if (scene != "") + { + stringBuilder.AppendFormat("* {0}\n", scene); + } + } + + stringBuilder.Append("\nTo restore a CinemachineRoot, enter Unity-Scene and select SEE > Cinemachines > Restore Cinemachine Root"); + + EditorUtility.DisplayDialog( + "Restoration of Cinemachines", + stringBuilder.ToString(), + "Okay" + ); + } + + /// + /// Checker function, to see if current Unity-Scene has a restoreable CinemachinesRoot. + /// + /// True, if the current Scene has a backup, else false. + [MenuItem("SEE/Cinemachines/Restore Cinemachines Root", true, 10)] + private static bool HasUnitySceneBackup() + { + return EditorPrefs.HasKey($"{SceneManager.GetActiveScene().name}.{CinemachinesUtility.CinemachinesPersistanceKeyName}"); + } + + /// + /// Menu Entry for restoring the CinemachinesRoot at current Scene. + /// + [MenuItem("SEE/Cinemachines/Restore Cinemachines Root", false, 10)] + internal static void RestoreCinemachinesRoot() + { + // Get Current Scenes Name + string UnitySceneName = SceneManager.GetActiveScene().name; + string prefKeyName = $"{UnitySceneName}.{CinemachinesUtility.CinemachinesPersistanceKeyName}"; + + if (!EditorPrefs.HasKey(prefKeyName)) + { + EditorUtility.DisplayDialog( + "Restoration of Cinemachines", + "This Scene contains no valid Backups for CinemachinesRoot.", + "Okay" + ); + return; + } + + // Confirm, if the user wants to restore to the last PlayTime State + if (!EditorUtility.DisplayDialog("Restoration of Cinemachines", "The Editor is in the process of restoring the Cinemachines, like they where at the time of exiting PlayTime.\n Do you want to restore to this Point?\n A Backup of the old Cinemachines will be created.", "Yes, restore", "No, don't restore")) + { + // // Reset PersistanceKey and abort + // if (EditorPrefs.HasKey(prefKeyName)) + // EditorPrefs.DeleteKey(prefKeyName); + return; + } + + // rename and deactivate old Scenes as backup + Transform CinemachinesRootTransform = CinemachinesUtility.GetCinemachinesRootInScene(); + + if (CinemachinesRootTransform != null) + { + // backup old root + HandleOldGameObject(CinemachinesRootTransform, true); + } + + // Load serialized Data + Load(SceneManager.GetActiveScene()); + } + + /// + /// Event Function to be called when the Play-State changes from PlayMode to EditMode. + /// Specific for restoring the Cinemachine-Scenes. + /// + /// The current state of the Editor. + private static void StoreCinemachinesChanges(PlayModeStateChange state) + { + switch (state) + { + case PlayModeStateChange.ExitingPlayMode: // Editor is exiting Play-Mode, proceed to save changes made + // Iterate through all Scenes inside the Project + for (int i = 0; i < SceneManager.sceneCount; i++) + { + // currently selected Scene + Scene currScene = SceneManager.GetSceneAt(i); + + // Save serialized Data + Save(currScene.name); + } + + GetRestorableRoots(); + break; + default: + break; + } + } + + /// + /// Helper Function to handle old GameObject on load. + /// + /// The GameObject, that will be deactivated or removed. + /// Parameter that determines, if the gets removed or deactivated. + private static void HandleOldGameObject(Transform oldRoot, bool backupOldRoot) + { + // if the Scenes root doesn't exist, don't try to create a backup + if (oldRoot != null) + { + if (backupOldRoot) + { + // backup old transform + oldRoot.gameObject.name = $"{oldRoot.gameObject.name} - Backup"; + oldRoot.gameObject.SetActive(false); + oldRoot.GetComponent().enabled = false; + } + else + { + // Remove old transform + #if UNITY_EDITOR + Debug.Log("Immediate Destroying from Editor", oldRoot); + UnityEngine.Object.DestroyImmediate(oldRoot); + #else + Debug.Log("Destroying during Runtime", oldRoot); + UnityEngine.Object.Destroy(oldRoot); + #endif + } + } + } + } +} diff --git a/Assets/Editor/Cinemachines/Utility/CinemachinesStateRestorer.cs.meta b/Assets/Editor/Cinemachines/Utility/CinemachinesStateRestorer.cs.meta new file mode 100644 index 0000000000..9533dc959e --- /dev/null +++ b/Assets/Editor/Cinemachines/Utility/CinemachinesStateRestorer.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 4ed98167596b3172abbf6863eba6e262 \ No newline at end of file diff --git a/Assets/Editor/Cinemachines/Utility/Utility.cs b/Assets/Editor/Cinemachines/Utility/Utility.cs new file mode 100644 index 0000000000..db6646040e --- /dev/null +++ b/Assets/Editor/Cinemachines/Utility/Utility.cs @@ -0,0 +1,6 @@ +/// +/// Namespace for the Cinemachines Utilities, that are only available inside the Unity-Editor. +/// +namespace SEEEditor.Cinemachines.Utility +{ +} diff --git a/Assets/Editor/Cinemachines/Utility/Utility.cs.meta b/Assets/Editor/Cinemachines/Utility/Utility.cs.meta new file mode 100644 index 0000000000..3a46460950 --- /dev/null +++ b/Assets/Editor/Cinemachines/Utility/Utility.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 3001b8fc27eef5269933b4bf1f6c3653 \ No newline at end of file diff --git a/Assets/Editor/SEE_Editor.asmdef b/Assets/Editor/SEE_Editor.asmdef index dd61bd6d04..62d037b267 100644 --- a/Assets/Editor/SEE_Editor.asmdef +++ b/Assets/Editor/SEE_Editor.asmdef @@ -26,7 +26,8 @@ "GUID:ad04e4f5949be9644989a3ea11bdc60e", "GUID:1491147abca9d7d4bb7105af628b223e", "GUID:806cab1205da0ff4588051d2fd0d130a", - "GUID:48f8a7808076097469421b5c5e5c6267" + "GUID:48f8a7808076097469421b5c5e5c6267", + "GUID:f06555f75b070af458a003d92f9efb00" ], "includePlatforms": [ "Editor" diff --git a/Assets/Resources/Prefabs/Cinemachines/SceneTemplate.prefab b/Assets/Resources/Prefabs/Cinemachines/SceneTemplate.prefab deleted file mode 100644 index c0fa1b2f96..0000000000 --- a/Assets/Resources/Prefabs/Cinemachines/SceneTemplate.prefab +++ /dev/null @@ -1,223 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!1 &324327809438091302 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 2140725804723030949} - m_Layer: 0 - m_Name: FocusObjects - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &2140725804723030949 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 324327809438091302} - serializedVersion: 2 - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 9207537824882640757} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &392207441576774055 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 2839293154195611454} - m_Layer: 0 - m_Name: OtherObjects - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &2839293154195611454 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 392207441576774055} - serializedVersion: 2 - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 9207537824882640757} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &7096091658220090398 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 6529366561688718673} - m_Layer: 0 - m_Name: Cameras - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &6529366561688718673 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7096091658220090398} - serializedVersion: 2 - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 9207537824882640757} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &7475867141918043811 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 2412182297654771841} - m_Layer: 0 - m_Name: Splines - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &2412182297654771841 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7475867141918043811} - serializedVersion: 2 - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 9207537824882640757} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &8979931306117858044 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 9207537824882640757} - - component: {fileID: -1542070960073348178} - - component: {fileID: -5748540832307934184} - - component: {fileID: 4465625675166380036} - m_Layer: 0 - m_Name: SceneTemplate - m_TagString: EditorOnly - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &9207537824882640757 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8979931306117858044} - serializedVersion: 2 - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: - - {fileID: 2412182297654771841} - - {fileID: 6529366561688718673} - - {fileID: 2140725804723030949} - - {fileID: 2839293154195611454} - m_Father: {fileID: 0} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!114 &-1542070960073348178 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8979931306117858044} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: d1e471f6d63fc6dcaac5df22e43afd8d, type: 3} - m_Name: - m_EditorClassIdentifier: - serializationData: - SerializedFormat: 2 - SerializedBytes: - ReferencedUnityObjects: [] - SerializedBytesString: - Prefab: {fileID: 0} - PrefabModificationsReferencedUnityObjects: [] - PrefabModifications: [] - SerializationNodes: [] - CinemachinesCameraCount: 0 - SplineCount: 0 - SignalCount: 0 - FocusObjectCount: 0 - SceneGUID: - ObjectNameSuffix: ---- !u!320 &-5748540832307934184 -PlayableDirector: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8979931306117858044} - m_Enabled: 1 - serializedVersion: 3 - m_PlayableAsset: {fileID: 0} - m_InitialState: 0 - m_WrapMode: 2 - m_DirectorUpdateMode: 1 - m_InitialTime: 0 - m_SceneBindings: [] - m_ExposedReferences: - m_References: [] ---- !u!114 &4465625675166380036 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8979931306117858044} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: e52de21a22b6dd44c9cc19f810c65059, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Events: - m_Signals: [] - m_Events: [] diff --git a/Assets/Resources/UI/PictureInPicture/pip.asset b/Assets/Resources/UI/PictureInPicture/PIP.asset similarity index 99% rename from Assets/Resources/UI/PictureInPicture/pip.asset rename to Assets/Resources/UI/PictureInPicture/PIP.asset index daa13303b7..fc3c0fca43 100644 --- a/Assets/Resources/UI/PictureInPicture/pip.asset +++ b/Assets/Resources/UI/PictureInPicture/PIP.asset @@ -10,7 +10,7 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 19101, guid: 0000000000000000e000000000000000, type: 0} - m_Name: pip + m_Name: PIP m_EditorClassIdentifier: themeUss: {fileID: -4733365628477956816, guid: ba0e3766823c59f06851aa74c35e1163, type: 3} diff --git a/Assets/Resources/UI/PictureInPicture/pip.asset.meta b/Assets/Resources/UI/PictureInPicture/PIP.asset.meta similarity index 100% rename from Assets/Resources/UI/PictureInPicture/pip.asset.meta rename to Assets/Resources/UI/PictureInPicture/PIP.asset.meta diff --git a/Assets/Resources/UI/PictureInPicture/pip-camera.uxml b/Assets/Resources/UI/PictureInPicture/PIPCamera.uxml similarity index 100% rename from Assets/Resources/UI/PictureInPicture/pip-camera.uxml rename to Assets/Resources/UI/PictureInPicture/PIPCamera.uxml diff --git a/Assets/Resources/UI/PictureInPicture/pip-camera.uxml.meta b/Assets/Resources/UI/PictureInPicture/PIPCamera.uxml.meta similarity index 100% rename from Assets/Resources/UI/PictureInPicture/pip-camera.uxml.meta rename to Assets/Resources/UI/PictureInPicture/PIPCamera.uxml.meta diff --git a/Assets/Resources/UI/PictureInPicture/pipDataSource.asset b/Assets/Resources/UI/PictureInPicture/PIPDataSource.asset similarity index 95% rename from Assets/Resources/UI/PictureInPicture/pipDataSource.asset rename to Assets/Resources/UI/PictureInPicture/PIPDataSource.asset index 5e3fb2b988..7330542017 100644 --- a/Assets/Resources/UI/PictureInPicture/pipDataSource.asset +++ b/Assets/Resources/UI/PictureInPicture/PIPDataSource.asset @@ -10,7 +10,7 @@ MonoBehaviour: m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: db1fb8f5ed60c6cea8d5d75180934509, type: 3} - m_Name: pipDataSource + m_Name: PIPDataSource m_EditorClassIdentifier: k__BackingField: {fileID: 8400000, guid: 1f07d7183cf77cf4a9d697276fe6cb4b, type: 2} diff --git a/Assets/Resources/UI/PictureInPicture/pipDataSource.asset.meta b/Assets/Resources/UI/PictureInPicture/PIPDataSource.asset.meta similarity index 100% rename from Assets/Resources/UI/PictureInPicture/pipDataSource.asset.meta rename to Assets/Resources/UI/PictureInPicture/PIPDataSource.asset.meta diff --git a/Assets/SEE/Cinemachines/CinemachineSceneRoot.cs b/Assets/SEE/Cinemachines/CinemachineSceneRoot.cs index 16bfa97a3c..cb5407bddf 100644 --- a/Assets/SEE/Cinemachines/CinemachineSceneRoot.cs +++ b/Assets/SEE/Cinemachines/CinemachineSceneRoot.cs @@ -1,16 +1,22 @@ using SEE.UI.RuntimeConfigMenu; -using SEE.Cinemachines.Utility; using SEE.Utils; +using SEE.Cinemachines.Utility; using Sirenix.OdinInspector; using Sirenix.Serialization; using System; using System.Collections.Generic; -using UnityEngine; -using UnityEngine.Playables; + +#if UNITY_EDITOR + using UnityEditor; -using UnityEngine.Splines; using UnityEditor.Splines; using UnityEditor.Timeline; + +#endif + +using UnityEngine; +using UnityEngine.Playables; +using UnityEngine.Splines; using UnityEngine.Timeline; using UnityEngine.SceneManagement; using UnityEngine.Events; @@ -29,6 +35,8 @@ namespace SEE.Cinemachines [RequireComponent(typeof(SignalReceiver))] internal class CinemachinesScene : SerializedMonoBehaviour { + #if UNITY_EDITOR + /// /// Incremental Counter for Cinemachines Camera. Counter not decremented on Camera deletion to avoid duplication. /// @@ -117,14 +125,6 @@ protected void Start() } } - /// - /// The Updater Function, that is unused in this Component. - /// - protected void Update() - { - // Intentionally left blank - } - /// /// AssetGUID of the Folder associated with this Scene. (Field). /// @@ -172,10 +172,10 @@ internal void DestroyObject() foreach (Transform Child in transform) { #if UNITY_EDITOR - Debug.Log("Immediate Destroying Scene-Children within Editor", Child.gameObject); + Debug.Log("Immediate Destroying Scene-Children within Editor\n", Child.gameObject); DestroyImmediate(Child.gameObject); #else - Debug.Log("Destroying Scene-Children during Runtime", Child.gameObject); + Debug.Log("Destroying Scene-Children during Runtime\n", Child.gameObject); Destroyer.Destroy(child.gameObject); #endif } @@ -184,27 +184,27 @@ internal void DestroyObject() if (!String.IsNullOrWhiteSpace(SceneGUID)) { string PathToSceneFolder = AssetDatabase.GUIDToAssetPath(SceneGUID); - Debug.Log($"Attempting to remove associated Scenes Folder from Project. Path: {PathToSceneFolder}", this); + Debug.Log($"Attempting to remove associated Scenes Folder from Project. Path: {PathToSceneFolder}\n", this); if (!String.IsNullOrWhiteSpace(PathToSceneFolder)) { AssetDatabase.DeleteAsset(PathToSceneFolder); } else { - Debug.LogWarning("Failed to find Scene-Folder. Assuming it never existed.", this); + Debug.LogWarning("Failed to find Scene-Folder. Assuming it never existed.\n", this); } } else { - Debug.LogWarning("GUID of Scene-Folder not set. Assuming it never existed.", this); + Debug.LogWarning("GUID of Scene-Folder not set. Assuming it never existed.\n", this); } // Remove self #if UNITY_EDITOR - Debug.Log("Immediate Destroying Scene-Root from Editor", transform.gameObject); + Debug.Log("Immediate Destroying Scene-Root from Editor\n", transform.gameObject); DestroyImmediate(transform.gameObject); #else - Debug.Log("Destroying Scene-Root during Runtime", transform.gameObject); + Debug.Log("Destroying Scene-Root during Runtime\n", transform.gameObject); Destroyer.Destroy(transform.gameObject); #endif } @@ -215,7 +215,6 @@ internal void DestroyObject() [Button("Backup Scene", ButtonSizes.Small), RuntimeButton(CinemachineSceneConfig, "Backup Scene")] [ButtonGroup(CinemachineSceneConfig)] [PropertyOrder(CinemachineSceneConfigOrderStore), RuntimeGroupOrder(CinemachineSceneConfigOrderStore)] - // [InfoBox("@CinemachinesUtility.GetSceneDeletionWarningMessage(SceneGUID)", InfoMessageType.Warning)] [Tooltip("Stores the current Scene as a Prefab for loading in a different Unity-Scene or in the same in a different spot. This does not carry over References specific to a Scene.")] internal void SaveScene() { @@ -234,9 +233,9 @@ internal void SaveScene() // Log result if (prefabCreationSuccess) - Debug.Log($"Scene has been successfully stored under {assetPathOfScene}"); + Debug.Log($"Scene has been successfully stored under {assetPathOfScene}.\n"); else - Debug.LogError($"Failed to store Scene under {assetPathOfScene}"); + Debug.LogError($"Failed to store Scene under {assetPathOfScene}.\n"); } /// @@ -282,7 +281,7 @@ internal void CreateNewSignal() string scenePath = AssetDatabase.GUIDToAssetPath(SceneGUID); - Debug.Log($"Creating SignalsAsset in: \"{scenePath}/Signals\""); + Debug.Log($"Creating SignalsAsset in: \"{scenePath}/Signals\"\n"); AssetDatabase.CreateAsset(newSignal, $"{scenePath}/Signals/{signalName}.signal"); } @@ -366,5 +365,7 @@ internal void OpenTimelineWindow() #endregion Scene Maintenance #endregion Odin Inspector Attributes + + #endif } } diff --git a/Assets/SEE/Cinemachines/CinemachinesRoot.cs b/Assets/SEE/Cinemachines/CinemachinesRoot.cs index 59b5a89dc9..f0e1cfaf66 100644 --- a/Assets/SEE/Cinemachines/CinemachinesRoot.cs +++ b/Assets/SEE/Cinemachines/CinemachinesRoot.cs @@ -1,6 +1,6 @@ using SEE.UI.RuntimeConfigMenu; using SEE.Cinemachines.Utility; -using SEE.UI.PictureInPicture; +using SEE.Cinemachines.UI.PictureInPicture; using Sirenix.OdinInspector; using System; using System.Collections.Generic; @@ -8,9 +8,15 @@ using UnityEngine.Playables; using UnityEngine.Timeline; using UnityEngine.Experimental.Rendering; +using UnityEngine.SceneManagement; using Debug = UnityEngine.Debug; + +#if UNITY_EDITOR + using UnityEditor; +#endif + namespace SEE.Cinemachines { /// @@ -21,12 +27,13 @@ namespace SEE.Cinemachines [ExecuteInEditMode] internal class CinemachinesRoot : SerializedMonoBehaviour { + #if UNITY_EDITOR + /// /// Boolean value to keep track, if the Root of the Cinemachines is fully initialized. /// [SerializeField, DisableInPlayMode, DisableInEditorMode] [Title("Cinemachines-Root Mainenance", horizontalLine: true)] - // [InfoBox("Maintenance Section for the Cinemachines-Root")] [PropertyOrder(CinemachinesRootMaintenanceOrderSetupReset), RuntimeGroupOrder(CinemachinesRootMaintenanceOrderSetupReset)] [LabelText("CinemachinesRoot initialized?")] [Tooltip("Displays the State of Initialization of the CinemachinesRoot.")] @@ -71,7 +78,6 @@ internal class CinemachinesRoot : SerializedMonoBehaviour protected void Start() { // Ensure, that only one CinemachinesRoot exists per scene - // var possibleRoots = UnityEngine.Object.FindObjectsByType(FindObjectsInactive.Exclude, FindObjectsSortMode.None); CinemachinesRoot[] possibleRoots = CinemachinesUtility.FindAllCinemachinesRootsInScene(); if (possibleRoots.Length > 1) @@ -92,14 +98,6 @@ protected void Start() } } - /// - /// Update Function to run on every Frame. Unused on this component. - /// - protected void Update() - { - // Intentionally left blank. - } - #region Root Maintenance /// @@ -113,7 +111,7 @@ protected void Update() internal void SetupCinemachinesRoot() { // Create the Structure of the CinemachinesRoot. It fails, if the Prefabs are not awailable. - if(!CreateCinemachinesRootStructure()) + if (!CreateCinemachinesRootStructure()) { return; } @@ -155,24 +153,24 @@ internal void ResetCinemachinesRoot() } #if UNITY_EDITOR - Debug.Log("Immediate Destroying Cinemachine-Children within Editor", child.gameObject); + Debug.Log("Immediate Destroying Cinemachine-Children within Editor\n", child.gameObject); DestroyImmediate(child.gameObject); #else - Debug.Log("Destroying Cinemachine-Children during Runtime", child.gameObject); + Debug.Log("Destroying Cinemachine-Children during Runtime\n", child.gameObject); Destroyer.Destroy(child.gameObject); #endif } // Remove every Scene-Folder from Assets/Cinemachines/Scenes - string[] sceneFolders = AssetDatabase.GetSubFolders($"{CinemachinesUtility.CinemachinesAssetsRoot}/Scenes"); + string[] sceneFolders = AssetDatabase.GetSubFolders($"{CinemachinesUtility.CinemachinesAssetsRoot}/Scenes/{SceneManager.GetActiveScene().name}"); foreach (string sceneFolder in sceneFolders) { - if (sceneFolder == $"{CinemachinesUtility.CinemachinesAssetsRoot}/Scenes/general") + if (sceneFolder == $"{CinemachinesUtility.CinemachinesAssetsRoot}/Scenes/{SceneManager.GetActiveScene().name}/general") { continue; } - Debug.Log($"Removing {sceneFolder} from Project"); + Debug.Log($"Removing {sceneFolder} from Project\n"); AssetDatabase.DeleteAsset(sceneFolder); } @@ -196,7 +194,7 @@ internal void ResetCinemachinesRoot() [PropertyOrder(CinemachineSceneConfigOrderCreate), RuntimeGroupOrder(CinemachineSceneConfigOrderCreate)] [EnableIf(nameof(isInitialized)), RuntimeEnableIf(nameof(isInitialized))] [Tooltip("Name of the Scene to be added as a Suffix to the GameObject.")] - public string SceneNameSuffix = ""; + private string SceneNameSuffix = ""; /// /// Creates a new Cinemachine-Scene Structure inside the . @@ -223,7 +221,7 @@ internal void CreateNewScene() SceneNameSuffix = ""; // Create Prefab inside Cinemachines -> Scenes - GameObject newScene = new GameObject(sceneName, typeof(CinemachinesScene)); + GameObject newScene = new(sceneName, typeof(CinemachinesScene)); // check, if the Scenes GameObject exists if (scenesTransform) @@ -248,7 +246,7 @@ internal void CreateNewScene() string scenePath = AssetDatabase.GUIDToAssetPath(newScene.GetComponent().SceneGUID); - Debug.Log($"Creating TimelineAsset in: \"{scenePath}\""); + Debug.Log($"Creating TimelineAsset in: \"{scenePath}\"\n"); AssetDatabase.CreateAsset(newTimeline, $"{scenePath}/Timeline.playable"); // assign to SceneRoot -> Playable Director @@ -293,14 +291,14 @@ private bool CreateCinemachinesRootStructure() } // Create GameObject Structure under CincemachinesRoot - cinemachineBrainsGameObject = Instantiate(brains, transform, false); - cinemachineControlCameraGameObject = Instantiate(controlCamera, transform, false); + cinemachineBrainsGameObject = Instantiate(brains, transform, false); + cinemachineControlCameraGameObject = Instantiate(controlCamera, transform, false); - cinemachineScenesGameObject = new GameObject(CinemachinesUtility.CinemachinesScenesName); + cinemachineScenesGameObject = new GameObject(CinemachinesUtility.CinemachinesScenesName); cinemachineScenesGameObject.transform.SetParent(transform); // Correct their Names, so that they don't include the "(Clone)" suffix - cinemachineBrainsGameObject.name = $"{CinemachinesUtility.CinemachinesBrainsName}"; + cinemachineBrainsGameObject.name = $"{CinemachinesUtility.CinemachinesBrainsName}"; cinemachineControlCameraGameObject.name = $"{CinemachinesUtility.CinemachinesControlCameraName}"; return true; @@ -313,11 +311,20 @@ private bool CreateCinemachinesRootStructure() private void CreateCinemachineFolderStructure() { // create new Folder for Scene in Assets/Cinemachines/Scenes - if (!AssetDatabase.IsValidFolder($"{CinemachinesUtility.CinemachinesAssetsRoot}/Scenes")) + if (!AssetDatabase.IsValidFolder($"{CinemachinesUtility.CinemachinesAssetsRoot}/Scenes/{SceneManager.GetActiveScene().name}")) { - AssetDatabase.CreateFolder("Assets", "Cinemachines"); - AssetDatabase.CreateFolder($"{CinemachinesUtility.CinemachinesAssetsRoot}", "Scenes"); - Debug.Log($"Created Scenes-Root Folder in \"{CinemachinesUtility.CinemachinesAssetsRoot}\""); + if (!AssetDatabase.IsValidFolder("Cinemachines")) + { + AssetDatabase.CreateFolder("Assets", "Cinemachines"); + } + + if (!AssetDatabase.IsValidFolder($"CinemachinesUtility.CinemachinesAssetsRoot")) + { + AssetDatabase.CreateFolder($"{CinemachinesUtility.CinemachinesAssetsRoot}", "Scenes"); + } + + AssetDatabase.CreateFolder($"{CinemachinesUtility.CinemachinesAssetsRoot}/Scenes", $"{SceneManager.GetActiveScene().name}"); + Debug.Log($"Created Scenes-Root Folder in \"{CinemachinesUtility.CinemachinesAssetsRoot}/Scenes/{SceneManager.GetActiveScene().name}\"\n"); } } @@ -328,7 +335,7 @@ private void CreateCinemachineFolderStructure() private void CreateRenderTextures() { // Create the RenderTextureDescriptor, that both RenderTextures should abide by - RenderTextureDescriptor renderTextureDescriptor = new RenderTextureDescriptor(1920, 1080, RenderTextureFormat.ARGB32); + RenderTextureDescriptor renderTextureDescriptor = new(1920, 1080, RenderTextureFormat.ARGB32); renderTextureDescriptor.depthStencilFormat = GraphicsFormat.D16_UNorm; // Create the RenderTexture for Main Cinemachines-Output, if none exists @@ -356,7 +363,7 @@ private void CreateRenderTextures() // Find the Cinemachine-Brains in the Child-GameObjects foreach (Transform child in cinemachineBrainsGameObject.transform) { - switch(child.name) + switch (child.name) { case "CMC_MainPicture": Debug.Log("Found Main Cinemachine Brain.\n"); @@ -383,8 +390,6 @@ private void CreateRenderTextures() protected const int CinemachinesRootMaintenanceOrderSetupReset = 0; - // protected const int CinemachinesRootMaintenanceOrderRepair = CinemachinesRootMaintenanceOrderReset + 1; - #endregion Maintenance of CinemachinesRoot #region Scene Creation @@ -396,5 +401,7 @@ private void CreateRenderTextures() #endregion Scene Creation #endregion Odin Inspector Attributes + + #endif } } diff --git a/Assets/SEE/Cinemachines/Dolly/SimpleSpeedController.cs b/Assets/SEE/Cinemachines/Dolly/SimpleSpeedController.cs index 37f5983ea9..7a62abf148 100644 --- a/Assets/SEE/Cinemachines/Dolly/SimpleSpeedController.cs +++ b/Assets/SEE/Cinemachines/Dolly/SimpleSpeedController.cs @@ -1,9 +1,9 @@ using System; +using System.Collections.Generic; using UnityEngine; -using Unity.Cinemachine; using UnityEngine.Splines; -using System.Collections.Generic; using UnityEngine.Pool; +using Unity.Cinemachine; namespace SEE.Cinemachines.Dolly { @@ -11,13 +11,13 @@ namespace SEE.Cinemachines.Dolly /// Class for a simple implementation of a Speed Controller, based on which section of the Spline the Object is. /// [Serializable] - public class SimpleSpeedController : SplineAutoDolly.ISplineAutoDolly + internal class SimpleSpeedController : SplineAutoDolly.ISplineAutoDolly { /// /// Structure for storing Sector-Data, specificly Start-Point on a Line [0,1), and its Speed on that sector. /// [Serializable] - public struct SplineSector + internal struct SplineSector { public float SectorStart; public float SectorSpeed; @@ -26,7 +26,7 @@ public struct SplineSector bool SplineAutoDolly.ISplineAutoDolly.RequiresTrackingTarget => false; [Tooltip("List of Sections on a Spline, with its corresponding Speeds, inwhich that section needs to be paced with.")] - public SplineSector[] SpeedList = {}; + private SplineSector[] SpeedList = {}; /// /// Calculation Function to get new Spline Position. @@ -49,7 +49,7 @@ float SplineAutoDolly.ISplineAutoDolly.GetSplinePosition(MonoBehaviour _sender, SplineSector selectedSector; - if (SpeedList.Length >= 1) + if (SpeedList.Length > 0) { selectedSector = SpeedList[0]; } @@ -63,8 +63,12 @@ float SplineAutoDolly.ISplineAutoDolly.GetSplinePosition(MonoBehaviour _sender, SplineSector tmpSector = SpeedList[i]; if (tmpSector.SectorStart >= selectedSector.SectorStart) + { if (tmpSector.SectorStart <= currentPosition) + { selectedSector = tmpSector; + } + } } // Progress in Preview/Export @@ -86,7 +90,8 @@ void SplineAutoDolly.ISplineAutoDolly.Reset() /// Thrown, if the Speed-List is not initialized. /// Thrown, if the Speed-List has less than one Entry. /// Thrown, if the Speed is zero or the Sectors are out of range in an Entry. - void SplineAutoDolly.ISplineAutoDolly.Validate() { + void SplineAutoDolly.ISplineAutoDolly.Validate() + { // NullReference and Index Checks if (SpeedList == null) { diff --git a/Assets/SEE/Cinemachines/UI.meta b/Assets/SEE/Cinemachines/UI.meta new file mode 100644 index 0000000000..a10c399005 --- /dev/null +++ b/Assets/SEE/Cinemachines/UI.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 439cc21cc1ab9aba7ba2fe9d9ceb80df +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/SEE/UI/PictureInPicture.meta b/Assets/SEE/Cinemachines/UI/PictureInPicture.meta similarity index 100% rename from Assets/SEE/UI/PictureInPicture.meta rename to Assets/SEE/Cinemachines/UI/PictureInPicture.meta diff --git a/Assets/SEE/UI/PictureInPicture/pipDataSource.cs b/Assets/SEE/Cinemachines/UI/PictureInPicture/PIPDataSource.cs similarity index 81% rename from Assets/SEE/UI/PictureInPicture/pipDataSource.cs rename to Assets/SEE/Cinemachines/UI/PictureInPicture/PIPDataSource.cs index 98fd922958..8d2b4a8992 100644 --- a/Assets/SEE/UI/PictureInPicture/pipDataSource.cs +++ b/Assets/SEE/Cinemachines/UI/PictureInPicture/PIPDataSource.cs @@ -3,17 +3,21 @@ using UnityEngine.UIElements; #if UNITY_EDITOR + using UnityEditor; + #endif -namespace SEE.UI.PictureInPicture +namespace SEE.Cinemachines.UI.PictureInPicture { /// /// The Data Source Structure for the Picture-In-Picture UI-Element. /// [CreateAssetMenu(menuName = "SEE/UI/Picture-in-Picture/Data Source")] - public class PIPDataSource : ScriptableObject + internal class PIPDataSource : ScriptableObject { + #if UNITY_EDITOR + [Header("Render Images")] /// /// The that is currently being displayed. @@ -22,5 +26,6 @@ public class PIPDataSource : ScriptableObject [CreateProperty] public RenderTexture PIPImage { get; set; } + #endif } } diff --git a/Assets/SEE/UI/PictureInPicture/pipDataSource.cs.meta b/Assets/SEE/Cinemachines/UI/PictureInPicture/PIPDataSource.cs.meta similarity index 100% rename from Assets/SEE/UI/PictureInPicture/pipDataSource.cs.meta rename to Assets/SEE/Cinemachines/UI/PictureInPicture/PIPDataSource.cs.meta diff --git a/Assets/SEE/UI/PictureInPicture/PictureInPicture.cs b/Assets/SEE/Cinemachines/UI/PictureInPicture/PictureInPicture.cs similarity index 79% rename from Assets/SEE/UI/PictureInPicture/PictureInPicture.cs rename to Assets/SEE/Cinemachines/UI/PictureInPicture/PictureInPicture.cs index 59f9908d49..ddfc51c23f 100644 --- a/Assets/SEE/UI/PictureInPicture/PictureInPicture.cs +++ b/Assets/SEE/Cinemachines/UI/PictureInPicture/PictureInPicture.cs @@ -2,6 +2,6 @@ /// Namespace for Elements associated with the Picture-in-Picture functionality. /// This includes a Data Source Structure for the UIDocument "pip". /// -namespace SEE.UI.PictureInPicture +namespace SEE.Cinemachines.UI.PictureInPicture { } diff --git a/Assets/SEE/UI/PictureInPicture/PictureInPicture.cs.meta b/Assets/SEE/Cinemachines/UI/PictureInPicture/PictureInPicture.cs.meta similarity index 100% rename from Assets/SEE/UI/PictureInPicture/PictureInPicture.cs.meta rename to Assets/SEE/Cinemachines/UI/PictureInPicture/PictureInPicture.cs.meta diff --git a/Assets/SEE/Cinemachines/UI/UI.cs b/Assets/SEE/Cinemachines/UI/UI.cs new file mode 100644 index 0000000000..4542dc265d --- /dev/null +++ b/Assets/SEE/Cinemachines/UI/UI.cs @@ -0,0 +1,6 @@ +/// +/// SEEEditor.UI contains code for the user interface in SEE inside the Editor. +/// +namespace SEE.Cinemachines.UI +{ +} diff --git a/Assets/SEE/Cinemachines/UI/UI.cs.meta b/Assets/SEE/Cinemachines/UI/UI.cs.meta new file mode 100644 index 0000000000..d3f6d8e842 --- /dev/null +++ b/Assets/SEE/Cinemachines/UI/UI.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 59dbf30accbbac65cb66e1d54c85db31 +timeCreated: 1610307000 diff --git a/Assets/SEE/Cinemachines/Utility/CinemachinesUtility.cs b/Assets/SEE/Cinemachines/Utility/CinemachinesUtility.cs index 45bf350823..03f5ac46dc 100644 --- a/Assets/SEE/Cinemachines/Utility/CinemachinesUtility.cs +++ b/Assets/SEE/Cinemachines/Utility/CinemachinesUtility.cs @@ -1,13 +1,18 @@ using System; -using System.Text; +// using System.Text; using System.Collections.Generic; -using System.Reflection; +// using System.Reflection; using UnityEngine; using UnityEngine.SceneManagement; -using UnityEngine.Timeline; -using UnityEngine.Playables; +// using UnityEngine.Timeline; +// using UnityEngine.Playables; + +#if UNITY_EDITOR + using UnityEditor; +#endif + namespace SEE.Cinemachines.Utility { /// @@ -15,583 +20,27 @@ namespace SEE.Cinemachines.Utility /// internal static class CinemachinesUtility { + #if UNITY_EDITOR + #region Constant String names - internal const string CinemachinesBrainsName = "CinemachinesBrains"; - internal const string CinemachinesScenesName = "Scenes"; - internal const string CinemachinesControlCameraName = "ControlCamera"; - internal const string CinemachinesMainOutputName = "CinemachinesMainOutput.renderTexture"; - internal const string CinemachinesPIPOutputName = "CinemachinesPIPOutput.renderTexture"; - - internal const string CinemachinesPrefabsRoot = "Assets/Resources/Prefabs/Cinemachines"; - internal const string CinemachinesRootPrefabsRoot = "Prefabs/Cinemachines/CinemachinesRoot"; - internal const string CinemachinesAssetsRoot = "Assets/Cinemachines"; - - internal const string CinemachinesPersistanceKeyName = "CinemachinesPersistanceKey"; - internal const string CinemachinesPersistanceKeyRestorableName = "CinemachinesPersistanceKeyRestorable"; + internal const string CinemachinesBrainsName = "CinemachinesBrains"; + internal const string CinemachinesScenesName = "Scenes"; + internal const string CinemachinesControlCameraName = "ControlCamera"; + internal const string CinemachinesMainOutputName = "CinemachinesMainOutput.renderTexture"; + internal const string CinemachinesPIPOutputName = "CinemachinesPIPOutput.renderTexture"; + + internal const string CinemachinesPrefabsRoot = "Assets/Resources/Prefabs/Cinemachines"; + internal const string CinemachinesRootPrefabsRoot = "Prefabs/Cinemachines/CinemachinesRoot"; + internal const string CinemachinesAssetsRoot = "Assets/Cinemachines"; + + internal const string CinemachinesPersistanceKeyName = "CinemachinesPersistanceKey"; + internal const string CinemachinesPersistanceKeyRestorableName = "CinemachinesPersistanceKeyRestorable"; /// /// The name of the root GameObject, that contains all Cinemachines related GameObjects in the scene. /// private const string CinemachinesRootName = "CinemachinesRoot"; #endregion Constant String names - /// - /// Class for Restoring GameObjects related to the Cinemachines. - /// - [InitializeOnLoad] - internal static class CinemachinesStateRestorer - { - /// - /// Structure-Class for storing References of Components in a serializable form. - /// - [Serializable] - internal class StoredReference - { - public int InstanceID; - public bool IsNull; - } - - /// - /// Structure-Class for storing Components inside GameObjects in a serializable form. - /// - [Serializable] - internal class StoredComponent - { - // Data for reconstructing the Type - public string AssemblyName; - public string TypeName; - - // Component Data - public int InstanceID; - public string JSONContent; - public List ListReferences = new(); - } - - /// - /// Structure-Class for storing GameObjects in a serializable form. - /// - [Serializable] - internal class StoredGameObject - { - // Data of this GameObject - public int InstanceID; - public string JSONGameObject; - public readonly List ListComponents = new(); - - // List of Children inside this GameObject - [SerializeReference] - public List ChildGameObjects = new(); - } - - /// - /// Implementation of a Serializer to store changes made in PlayMode persistently. - /// - internal class Serializer - { - /// - /// Helper-Function to Serialize References inside Components. - /// - /// The Component to be serialized. - /// List of StoredReferences, that will be included to the respective Component. - private List SerializeReference(Component component) - { - // List for storing required References, that can not be applied normally - List referenceList = new(); - - // Create SerializedObject from the Object/Component and get its SerializedProperty as an Iterator - SerializedObject serializedObject = new(component); - SerializedProperty propertyIterator = serializedObject.GetIterator(); - - // while there still are properties - while (propertyIterator.NextVisible(true)) - { - // check, if the type of property is relevant to us - if (propertyIterator.propertyType == SerializedPropertyType.ObjectReference) - { - StoredReference storedReference = new StoredReference(); - - // get Object referenced in Property - UnityEngine.Object objectReference = propertyIterator.objectReferenceValue; - - // setup StoredReference appropriatly, based on if its null or not - switch (objectReference) - { - case null: - storedReference.IsNull = true; - break; - default: - storedReference.InstanceID = objectReference.GetInstanceID(); - storedReference.IsNull = false; - break; - } - - referenceList.Add(storedReference); - } - } - - return referenceList; - } - - /// - /// Serializing Function for Transforms and their associated Data. - /// - /// The GameObject to be serialized. - /// Returns a StoredGameObject, that can be serialized into JSON. - internal StoredGameObject Serialize(Transform rootObject) - { - StoredGameObject storedGameObject = new StoredGameObject(); - - // Store base Data of this Object into the StoredGameObject - storedGameObject.InstanceID = rootObject.GetInstanceID(); - storedGameObject.JSONGameObject = EditorJsonUtility.ToJson(rootObject.gameObject); - - // iterate through all components - foreach (Component component in rootObject.GetComponents(typeof(Component))) - { - StoredComponent storedComponent = new StoredComponent(); - - // deconstruct the type of the Component - storedComponent.AssemblyName = component.GetType().Assembly.GetName().Name; - storedComponent.TypeName = component.GetType().FullName; - - // store base data of this Component - storedComponent.InstanceID = component.GetInstanceID(); - storedComponent.JSONContent = EditorJsonUtility.ToJson(component); - - // serialize references made inside component - storedComponent.ListReferences = SerializeReference(component); - - storedGameObject.ListComponents.Add(storedComponent); - } - - // re-iterate through all GameObjects, that are a child of this Object - // needs to be done in a depth-first way - foreach (Transform child in rootObject) - { - storedGameObject.ChildGameObjects.Add(Serialize(child)); - } - - return storedGameObject; - } - } - - /// - /// Implementation of a Deserializer to store changes made in PlayMode persistently. - /// - internal class Deserializer - { - /// - /// Temporary Dictionary for storing InstanceIDs of Objects with their respective StoredProperties. - /// - private Dictionary> storedReferences = new Dictionary>(); - - /// - /// Reference List between original InstanceIDs and restored IDs. - /// - private Dictionary referenceList = new Dictionary(); - - /// - /// Helper-Function to Deserialize References inside Components, like Transform, UnityEvents, etc. - /// - private void DeserializeReferences() - { - // Loop through every KeyValuePair in the storedReferences - foreach (var kvp in storedReferences) - { - // Find the Object/Component, you want to apply the References to - UnityEngine.Object restoredObject = Resources.InstanceIDToObject(kvp.Key); - - // create SerializedObject and Property - SerializedObject serializedObject = new SerializedObject(restoredObject); - SerializedProperty propertyIterator = serializedObject.GetIterator(); - - // get the stored References list from the KeyValuePair - List storedReferences = kvp.Value; - - // local Counter for iterating through the storedReferences for this Object - int Index = 0; - - // check, if there is still a Property accessable - while (propertyIterator.NextVisible(true)) - { - // check, if the type of the Property is relevant to us - if (propertyIterator.propertyType == SerializedPropertyType.ObjectReference) - { - // Select the indexed StoredReference, which potentially needs to be applied - StoredReference storedReference = storedReferences[Index]; - - // If the StoredReference was null, ignore it, ... - if (!storedReference.IsNull) - { - // ... else get the Object by InstanceID and apply it - int objectInstanceID; - if (referenceList.ContainsKey(storedReference.InstanceID)) - { - // This part is not working correctly, since Unity differentiates InstanceIDs - // from actual Objects and References - objectInstanceID = referenceList[storedReference.InstanceID]; - } - else - { - objectInstanceID = storedReference.InstanceID; - } - - UnityEngine.Object objectReference = Resources.InstanceIDToObject(objectInstanceID); - - if (objectReference == null) - { - Debug.LogWarning($"Object with InstanceID '{objectInstanceID}' does not exist.\n Maybe the Object was created during Runtime, which must then be manually recreated and reapplied."); - } - - propertyIterator.objectReferenceValue = objectReference; - } - - // Increment Index for next Reference - Index++; - } - } - - // Apply all modified Properties to the SerializedObject, which applies the changes to the regular Objects/Components - serializedObject.ApplyModifiedProperties(); - } - } - - /// - /// Actual Deserializing Method, which returns the root transform. - /// - /// The StoredGameObject, that will be restored to actual GameObjects. - /// The Transform reconstructed from the StoredGameObject, including their Children. - private Transform Deserialize(StoredGameObject storedGameObject) - { - // Find Object as Child of rootTransform - GameObject restoredGameObject = new(); - EditorJsonUtility.FromJsonOverwrite(storedGameObject.JSONGameObject, restoredGameObject); - - // Iterate through all Components for this GameObject - foreach (StoredComponent storedComponent in storedGameObject.ListComponents) - { - Type ComponentType = Assembly.Load(storedComponent.AssemblyName).GetType(storedComponent.TypeName); - - // Reconstruct type of this component. - Component readComponent; - if (ComponentType == typeof(Transform)) - { - readComponent = restoredGameObject.transform; - } - else if (ComponentType == typeof(PlayableDirector)) - { - readComponent = restoredGameObject.GetComponent(); - - if (readComponent == null) - { - readComponent = restoredGameObject.AddComponent(typeof(PlayableDirector)); - } - } - else if (ComponentType == typeof(SignalReceiver)) - { - readComponent = restoredGameObject.GetComponent(); - - if (readComponent == null) - { - readComponent = restoredGameObject.AddComponent(typeof(SignalReceiver)); - } - } - else - { - readComponent = restoredGameObject.AddComponent(ComponentType); - } - - // apply Data onto the component - EditorJsonUtility.FromJsonOverwrite(storedComponent.JSONContent, readComponent); - - // store References, that might need to be applied after everything has been applied - storedReferences.Add(readComponent.GetInstanceID(), storedComponent.ListReferences); - - // store mapping of old InstanceID to new InstanceID for Components - try - { - referenceList.Add(storedComponent.InstanceID, readComponent.GetInstanceID()); - } - catch (Exception) - { - Debug.LogWarning($"Attempted to Map '{storedComponent.InstanceID}' to '{readComponent.GetInstanceID()}'\n"); - } - } - - // Iterate depth-first through all child GameObjects - foreach (StoredGameObject childStoredGameObject in storedGameObject.ChildGameObjects) - { - Transform child = Deserialize(childStoredGameObject); - - // reposition accordingly - child.SetParent(restoredGameObject.transform); - } - - return restoredGameObject.transform; - } - - /// - /// Primer Deserializer Function for GameObjects, initialized by inputing serialized Data. - /// - /// The serialized data, that will be restored from. - /// The restored Transform, including restored components and children. - internal Transform Deserialize(string jsonData) - { - // Deserialize first layer - StoredGameObject storedGameObject = JsonUtility.FromJson(jsonData); - - // Reconstruct root GameObject from deserialized Data - Transform restoredRootTransform = Deserialize(storedGameObject); - - // apply references to gameObject - DeserializeReferences(); - - return restoredRootTransform; - } - } - - /// - /// Constructor for the Cinemachines State Restorer, which enables an Event to restore changes - /// made inside CinemachinesRoot to be re-applied after exiting PlayMode. - /// - static CinemachinesStateRestorer() - { - // Register new Event for restoring changes made in PlayMode - EditorApplication.playModeStateChanged += StoreCinemachinesChanges; - } - - /// - /// Save function, utilizing the custom Serializer Class for Cinemachines. - /// - /// The Name of the Unity-Scene, that the Object will be stored from. - private static void Save(string unitySceneName) - { - // Locating CinemachinesRoot - Transform cinemachinesRootTransform = GetCinemachinesRootInScene(); - - if (cinemachinesRootTransform == null) - { - return; - } - - // Serialize ScenesRoot - Serializer serializer = new Serializer(); - StoredGameObject storedGameObject = serializer.Serialize(cinemachinesRootTransform); - - // Store generated JSON inside EditorPrefs for persistance - EditorPrefs.SetString($"{unitySceneName}.{CinemachinesPersistanceKeyName}", JsonUtility.ToJson(storedGameObject)); - } - - /// - /// Load function, utilizing the custom Deserializer Class for Cinemachines. - /// - /// The Unity-Scene to reconstruct the serialized GameObjects. - private static void Load(Scene unityScene) - { - string serializedDataKeyName = $"{unityScene.name}.{CinemachinesPersistanceKeyName}"; - - if (!EditorPrefs.HasKey(serializedDataKeyName)) - { - return; - } - - // prepare deserializer - Deserializer deserializer = new(); - - // get stored scenes-data with deserializer - deserializer.Deserialize(EditorPrefs.GetString(serializedDataKeyName)); - - // Display warning about referencing original Objects - EditorUtility.DisplayDialog( - "Restoration of Cinemachines", - "Warning! The restored backup is using parts of the original Cinemachine Structure.\nPlease check the Timelines and other Objects and update these components to their restored equivalents before continuing.", - "Okay" - ); - - // Reset PersistanceKey - if (EditorPrefs.HasKey(serializedDataKeyName)) - { - EditorPrefs.DeleteKey(serializedDataKeyName); - } - } - - /// - /// Helper-Function to get Unity-Scene names with CinemachineRoot-Backups. - /// - /// Name of Unity-Scenes, that have GameObject backups. - private static string[] GetRestorableScenes() - { - // find all Unity-Scenes in Project - string[] scenesGUIDs = AssetDatabase.FindAssets("t:Scene"); - List scenesPaths = new(); - - foreach (string guid in scenesGUIDs) - { - scenesPaths.Add(AssetDatabase.GUIDToAssetPath(guid)); - } - - StringBuilder result = new(); - - foreach (string scenePath in scenesPaths) - { - // check, if scene-path starts at the correct location - // doing so will exclude every example scene from Extensions - if (!scenePath.StartsWith("Assets/Scenes")) - { - continue; - } - - // Logic for trimming the path down to the File-name of the Scene - int ToDeleteSuffixLength = ".unity".Length; - string[] UnitySceneNameSplit = scenePath.Remove(scenePath.Length - ToDeleteSuffixLength, ToDeleteSuffixLength).Split('/'); - string UnitySceneName = UnitySceneNameSplit[UnitySceneNameSplit.Length - 1]; - - // checking, if a persistance key for the scene exists - string prefKeyName = $"{UnitySceneName}.{CinemachinesPersistanceKeyName}"; - if (EditorPrefs.HasKey(prefKeyName)) - { - result.AppendFormat("{0}\n", UnitySceneName); - } - } - - return result.ToString().Split('\n'); - } - - /// - /// Display Function to get list of restorable scenes. - /// - [MenuItem("SEE/Cinemachines/Get restorable Cinemachine Roots", false, 12)] - internal static void GetRestorableRoots() - { - // String Builder for Dialog Body, which includes the names of the Scenes, that can restore a CinemachinesRoot - StringBuilder stringBuilder = new StringBuilder("The CinemachineRoots of the following Unity-Scenes have been backed up.\n"); - string[] restorableScenes = GetRestorableScenes(); - - // Format Scene Names - foreach (string scene in restorableScenes) - { - if (scene != "") - { - stringBuilder.AppendFormat("* {0}\n", scene); - } - } - - stringBuilder.Append("\nTo restore a CinemachineRoot, enter Unity-Scene and select SEE > Cinemachines > Restore Cinemachine Root"); - - EditorUtility.DisplayDialog( - "Restoration of Cinemachines", - stringBuilder.ToString(), - "Okay" - ); - } - - /// - /// Checker function, to see if current Unity-Scene has a restoreable CinemachinesRoot. - /// - /// True, if the current Scene has a backup, else false. - [MenuItem("SEE/Cinemachines/Restore Cinemachines Root", true, 10)] - private static bool HasUnitySceneBackup() { - return EditorPrefs.HasKey($"{SceneManager.GetActiveScene().name}.{CinemachinesPersistanceKeyName}"); - } - - /// - /// Menu Entry for restoring the CinemachinesRoot at current Scene. - /// - [MenuItem("SEE/Cinemachines/Restore Cinemachines Root", false, 10)] - internal static void RestoreCinemachinesRoot() - { - // Get Current Scenes Name - string UnitySceneName = SceneManager.GetActiveScene().name; - string prefKeyName = $"{UnitySceneName}.{CinemachinesPersistanceKeyName}"; - - if (!EditorPrefs.HasKey(prefKeyName)) - { - EditorUtility.DisplayDialog( - "Restoration of Cinemachines", - "This Scene contains no valid Backups for CinemachinesRoot.", - "Okay" - ); - return; - } - - // Confirm, if the user wants to restore to the last PlayTime State - if (!EditorUtility.DisplayDialog("Restoration of Cinemachines", "The Editor is in the process of restoring the Cinemachines, like they where at the time of exiting PlayTime.\n Do you want to restore to this Point?\n A Backup of the old Cinemachines will be created.", "Yes, restore", "No, don't restore")) - { - // // Reset PersistanceKey and abort - // if (EditorPrefs.HasKey(prefKeyName)) - // EditorPrefs.DeleteKey(prefKeyName); - return; - } - - // rename and deactivate old Scenes as backup - Transform CinemachinesRootTransform = GetCinemachinesRootInScene(); - - if (CinemachinesRootTransform != null) - // backup old root - HandleOldGameObject(CinemachinesRootTransform, true); - - // Load serialized Data - Load(SceneManager.GetActiveScene()); - } - - /// - /// Event Function to be called when the Play-State changes from PlayMode to EditMode. - /// Specific for restoring the Cinemachine-Scenes. - /// - /// The current state of the Editor. - private static void StoreCinemachinesChanges(PlayModeStateChange state) - { - switch (state) - { - case PlayModeStateChange.ExitingPlayMode: // Editor is exiting Play-Mode, proceed to save changes made - // Iterate through all Scenes inside the Project - for (int i = 0; i < SceneManager.sceneCount; i++) - { - // currently selected Scene - Scene currScene = SceneManager.GetSceneAt(i); - - // Save serialized Data - Save(currScene.name); - } - - GetRestorableRoots(); - break; - default: - break; - } - } - - /// - /// Helper Function to handle old GameObject on load. - /// - /// The GameObject, that will be deactivated or removed. - /// Parameter that determines, if the gets removed or deactivated. - private static void HandleOldGameObject(Transform oldRoot, bool backupOldRoot) - { - // if the Scenes root doesn't exist, don't try to create a backup - if (oldRoot != null) - { - if (backupOldRoot) - { - // backup old transform - oldRoot.gameObject.name = $"{oldRoot.gameObject.name} - Backup"; - oldRoot.gameObject.SetActive(false); - oldRoot.GetComponent().enabled = false; - } - else - { - // Remove old transform -#if UNITY_EDITOR - Debug.Log("Immediate Destroying from Editor", oldRoot); - UnityEngine.Object.DestroyImmediate(oldRoot); -#else - Debug.Log("Destroying during Runtime", oldRoot); - UnityEngine.Object.Destroy(oldRoot); -#endif - } - } - } - } - /// /// Returns the active CinemachineRoots-Transform, if one exists in the current Scene. /// @@ -601,7 +50,9 @@ internal static Transform GetCinemachinesRootInScene() CinemachinesRoot[] CinemachinesRootComponents = FindAllCinemachinesRootsInScene(); if (CinemachinesRootComponents.Length < 1) + { return null; + } return CinemachinesRootComponents[0].transform; } @@ -632,7 +83,8 @@ internal static void CreateCinemachinesRoot() /// /// The GUID of the Folder for the corresponding Cinemachines-Scene. /// The Message generated for the Cinemachines-Scene. - internal static string GetSceneDeletionWarningMessage(string guid) { + internal static string GetSceneDeletionWarningMessage(string guid) + { return $"Deleting the Scene will also delete its associated Scene Folder, which is \"{AssetDatabase.GUIDToAssetPath(guid)}\""; } @@ -644,10 +96,12 @@ internal static string GetSceneDeletionWarningMessage(string guid) { internal static string GenerateSceneFolder(string sceneName) { // create new Folder for Scene in Assets/Cinemachines/Scenes - string SceneGUID = AssetDatabase.CreateFolder($"{CinemachinesAssetsRoot}/Scenes", $"{SceneManager.GetActiveScene().name} - {sceneName}"); + string SceneGUID = AssetDatabase.CreateFolder($"{CinemachinesAssetsRoot}/Scenes/{SceneManager.GetActiveScene().name}", $"{sceneName}"); // create Signals folder to store Timeline Signals if (!AssetDatabase.IsValidFolder($"{AssetDatabase.GUIDToAssetPath(SceneGUID)}/Signals")) + { AssetDatabase.CreateFolder(AssetDatabase.GUIDToAssetPath(SceneGUID), "Signals"); + } return SceneGUID; } @@ -662,16 +116,24 @@ internal static void GenerateCinemachinesPrefabFolder() { // Check and create Sub-Directories, if they don't exist if (!AssetDatabase.IsValidFolder("Assets/Resources")) + { AssetDatabase.CreateFolder("Assets", "Resources"); + } if (!AssetDatabase.IsValidFolder("Assets/Resources/Prefabs")) + { AssetDatabase.CreateFolder("Assets/Resources", "Prefabs"); + } if (!AssetDatabase.IsValidFolder(CinemachinesPrefabsRoot)) + { AssetDatabase.CreateFolder("Assets/Resources/Prefabs", "Cinemachines"); + } if (!AssetDatabase.IsValidFolder($"{CinemachinesPrefabsRoot}/Scenes")) + { AssetDatabase.CreateFolder(CinemachinesPrefabsRoot, "Scenes"); + } Debug.Log($"Created Folder Structure: {CinemachinesPrefabsRoot}/Scenes"); return; @@ -755,5 +217,7 @@ internal static void CreateGameObject(string objectType, ref int objectCount, re Selection.activeGameObject = newObject; } } + + #endif } } diff --git a/Assets/SEE/SEE.asmdef b/Assets/SEE/SEE.asmdef index b902ca3fde..5047b11907 100644 --- a/Assets/SEE/SEE.asmdef +++ b/Assets/SEE/SEE.asmdef @@ -34,10 +34,9 @@ "GUID:13e34609dade4964e97712dc04b1cc6a", "GUID:702f733b4deb246808c6ce84d93b5c9c", "GUID:04c4d86a70aa56c55a78c61f1ab1a56d", - "GUID:4307f53044263cf4b835bd812fc161a4", - "GUID:ba8c092d026123a418fb4bfb797a7bd8", "GUID:21d1eb854b91ade49bc69a263d12bee2", "GUID:e43142fc3fec6554980dde6126631f1d", + "GUID:4307f53044263cf4b835bd812fc161a4", "GUID:f06555f75b070af458a003d92f9efb00", "GUID:02f771204943f4a40949438e873e3eff" ], From 2a47bdf7806bd0bd967c1f12c508fad47c8b4ec0 Mon Sep 17 00:00:00 2001 From: Anton Siebert Date: Thu, 13 Aug 2026 19:18:07 +0200 Subject: [PATCH 14/16] #922 included documentation to the '#if UNITY_EDITOR' pre-processor directives to clarify, that these components and classes only work inside the Unity-Editor. Also correctly tagged the associated GameObjects to 'EditorOnly' during creation for the same reason. --- .../Utility/CinemachinesStateRestorer.cs | 1 + .../CinemachinesRoot/CinemachinesBrains.prefab | 4 ++-- .../CinemachinesRoot/ControlCamera.prefab | 2 +- Assets/SEE/Cinemachines/CinemachineSceneRoot.cs | 17 +++++++++++++++++ Assets/SEE/Cinemachines/CinemachinesRoot.cs | 12 ++++++++++++ .../UI/PictureInPicture/PIPDataSource.cs | 2 ++ .../Cinemachines/Utility/CinemachinesUtility.cs | 9 +++++---- 7 files changed, 40 insertions(+), 7 deletions(-) diff --git a/Assets/Editor/Cinemachines/Utility/CinemachinesStateRestorer.cs b/Assets/Editor/Cinemachines/Utility/CinemachinesStateRestorer.cs index ec8557731c..09ae37f289 100644 --- a/Assets/Editor/Cinemachines/Utility/CinemachinesStateRestorer.cs +++ b/Assets/Editor/Cinemachines/Utility/CinemachinesStateRestorer.cs @@ -10,6 +10,7 @@ using SEE.Cinemachines; using SEE.Cinemachines.Utility; +// Only use UnityEditor-Namespaces when inside the Unity-Editor. #if UNITY_EDITOR using UnityEditor; diff --git a/Assets/Resources/Prefabs/Cinemachines/CinemachinesRoot/CinemachinesBrains.prefab b/Assets/Resources/Prefabs/Cinemachines/CinemachinesRoot/CinemachinesBrains.prefab index 627ceae54a..7712bbb52a 100644 --- a/Assets/Resources/Prefabs/Cinemachines/CinemachinesRoot/CinemachinesBrains.prefab +++ b/Assets/Resources/Prefabs/Cinemachines/CinemachinesRoot/CinemachinesBrains.prefab @@ -185,7 +185,7 @@ GameObject: - component: {fileID: 6985156430517444999} m_Layer: 0 m_Name: CMC_PictureInPicture - m_TagString: Untagged + m_TagString: EditorOnly m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 @@ -351,7 +351,7 @@ GameObject: - component: {fileID: 674836566232368238} m_Layer: 0 m_Name: CinemachinesBrains - m_TagString: Untagged + m_TagString: EditorOnly m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 diff --git a/Assets/Resources/Prefabs/Cinemachines/CinemachinesRoot/ControlCamera.prefab b/Assets/Resources/Prefabs/Cinemachines/CinemachinesRoot/ControlCamera.prefab index 714b2cc255..885bd785eb 100644 --- a/Assets/Resources/Prefabs/Cinemachines/CinemachinesRoot/ControlCamera.prefab +++ b/Assets/Resources/Prefabs/Cinemachines/CinemachinesRoot/ControlCamera.prefab @@ -15,7 +15,7 @@ GameObject: - component: {fileID: 1900162122134153581} m_Layer: 0 m_Name: ControlCamera - m_TagString: Untagged + m_TagString: EditorOnly m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 diff --git a/Assets/SEE/Cinemachines/CinemachineSceneRoot.cs b/Assets/SEE/Cinemachines/CinemachineSceneRoot.cs index cb5407bddf..4b537aa7a3 100644 --- a/Assets/SEE/Cinemachines/CinemachineSceneRoot.cs +++ b/Assets/SEE/Cinemachines/CinemachineSceneRoot.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; +// Only use UnityEditor-Namespaces when inside the Unity-Editor. #if UNITY_EDITOR using UnityEditor; @@ -35,6 +36,7 @@ namespace SEE.Cinemachines [RequireComponent(typeof(SignalReceiver))] internal class CinemachinesScene : SerializedMonoBehaviour { + // Encasing Class content inside the UNITY_EDITOR directive to ensure, that these Components only activly work inside the Unity-Editor. #if UNITY_EDITOR /// @@ -103,26 +105,41 @@ protected void Start() { cinemachinesCamerasGameObject = new GameObject("Cameras"); cinemachinesCamerasGameObject.transform.SetParent(transform); + + // Dont Save in Build + cinemachinesCamerasGameObject.tag = "EditorOnly"; } if (!cinemachinesSplinesGameObject) { cinemachinesSplinesGameObject = new GameObject("Splines"); cinemachinesSplinesGameObject.transform.SetParent(transform); + + // Dont Save in Build + cinemachinesSplinesGameObject.tag = "EditorOnly"; } if (!cinemachinesFocusObjectGameObject) { cinemachinesFocusObjectGameObject = new GameObject("FocusObjects"); cinemachinesFocusObjectGameObject.transform.SetParent(transform); + + // Dont Save in Build + cinemachinesFocusObjectGameObject.tag = "EditorOnly"; } if (!cinemachinesOtherObjectGameObject) { cinemachinesOtherObjectGameObject = new GameObject("OtherObjects"); cinemachinesOtherObjectGameObject.transform.SetParent(transform); + + // Dont Save in Build + cinemachinesOtherObjectGameObject.tag = "EditorOnly"; } } + + // Dont Save in Build + tag = "EditorOnly"; } /// diff --git a/Assets/SEE/Cinemachines/CinemachinesRoot.cs b/Assets/SEE/Cinemachines/CinemachinesRoot.cs index f0e1cfaf66..686fd1ecde 100644 --- a/Assets/SEE/Cinemachines/CinemachinesRoot.cs +++ b/Assets/SEE/Cinemachines/CinemachinesRoot.cs @@ -11,6 +11,7 @@ using UnityEngine.SceneManagement; using Debug = UnityEngine.Debug; +// Only use UnityEditor-Namespaces when inside the Unity-Editor #if UNITY_EDITOR using UnityEditor; @@ -27,6 +28,7 @@ namespace SEE.Cinemachines [ExecuteInEditMode] internal class CinemachinesRoot : SerializedMonoBehaviour { + // Encasing Class content inside the UNITY_EDITOR directive to ensure, that these Components only activly work inside the Unity-Editor #if UNITY_EDITOR /// @@ -123,6 +125,9 @@ internal void SetupCinemachinesRoot() CreateRenderTextures(); isInitialized = true; + + // Make sure, that this Object doesn't get put into a build + tag = "EditorOnly"; } /// @@ -301,6 +306,13 @@ private bool CreateCinemachinesRootStructure() cinemachineBrainsGameObject.name = $"{CinemachinesUtility.CinemachinesBrainsName}"; cinemachineControlCameraGameObject.name = $"{CinemachinesUtility.CinemachinesControlCameraName}"; + // Dont Save these GameObjects into the Build by marking these as EditorOnly + cinemachineBrainsGameObject.tag = "EditorOnly"; + + cinemachineScenesGameObject.tag = "EditorOnly"; + + cinemachineControlCameraGameObject.tag = "EditorOnly"; + return true; } diff --git a/Assets/SEE/Cinemachines/UI/PictureInPicture/PIPDataSource.cs b/Assets/SEE/Cinemachines/UI/PictureInPicture/PIPDataSource.cs index 8d2b4a8992..3cee0e7202 100644 --- a/Assets/SEE/Cinemachines/UI/PictureInPicture/PIPDataSource.cs +++ b/Assets/SEE/Cinemachines/UI/PictureInPicture/PIPDataSource.cs @@ -2,6 +2,7 @@ using UnityEngine; using UnityEngine.UIElements; +// Only use UnityEditor-Namespaces when inside the Unity-Editor. #if UNITY_EDITOR using UnityEditor; @@ -16,6 +17,7 @@ namespace SEE.Cinemachines.UI.PictureInPicture [CreateAssetMenu(menuName = "SEE/UI/Picture-in-Picture/Data Source")] internal class PIPDataSource : ScriptableObject { + // Encasing Class content inside the UNITY_EDITOR directive to ensure, that these Components only activly work inside the Unity-Editor. #if UNITY_EDITOR [Header("Render Images")] diff --git a/Assets/SEE/Cinemachines/Utility/CinemachinesUtility.cs b/Assets/SEE/Cinemachines/Utility/CinemachinesUtility.cs index 03f5ac46dc..a4675a3155 100644 --- a/Assets/SEE/Cinemachines/Utility/CinemachinesUtility.cs +++ b/Assets/SEE/Cinemachines/Utility/CinemachinesUtility.cs @@ -1,12 +1,9 @@ using System; -// using System.Text; using System.Collections.Generic; -// using System.Reflection; using UnityEngine; using UnityEngine.SceneManagement; -// using UnityEngine.Timeline; -// using UnityEngine.Playables; +// Only use UnityEditor-Namespaces when inside the Unity-Editor. #if UNITY_EDITOR using UnityEditor; @@ -20,6 +17,7 @@ namespace SEE.Cinemachines.Utility /// internal static class CinemachinesUtility { + // Encasing Class content inside the UNITY_EDITOR directive to ensure, that this Utility-Class only activly works inside the Unity-Editor. #if UNITY_EDITOR #region Constant String names @@ -216,6 +214,9 @@ internal static void CreateGameObject(string objectType, ref int objectCount, re { Selection.activeGameObject = newObject; } + + // Sets the new Objects hideFlags to not Save into a build + newObject.tag = "EditorOnly"; } #endif From 0c38000a36433beaa84e6d7fb1d846567ad1b508 Mon Sep 17 00:00:00 2001 From: Anton Siebert Date: Tue, 18 Aug 2026 21:32:01 +0200 Subject: [PATCH 15/16] #922 added more newline characters to Debug.Log* calls and fixed-up documentation errors. --- .../Cinemachines/Utility/CinemachinesStateRestorer.cs | 6 +++--- Assets/SEE/Cinemachines/CinemachinesRoot.cs | 8 ++++---- Assets/SEE/Cinemachines/Dolly/SimpleSpeedController.cs | 5 ----- Assets/SEE/Cinemachines/UI/UI.cs | 2 +- Assets/SEE/Cinemachines/Utility/CinemachinesUtility.cs | 2 +- 5 files changed, 9 insertions(+), 14 deletions(-) diff --git a/Assets/Editor/Cinemachines/Utility/CinemachinesStateRestorer.cs b/Assets/Editor/Cinemachines/Utility/CinemachinesStateRestorer.cs index 09ae37f289..44910936d5 100644 --- a/Assets/Editor/Cinemachines/Utility/CinemachinesStateRestorer.cs +++ b/Assets/Editor/Cinemachines/Utility/CinemachinesStateRestorer.cs @@ -225,7 +225,7 @@ private void DeserializeReferences() if (objectReference == null) { - Debug.LogWarning($"Object with InstanceID '{objectInstanceID}' does not exist.\n Maybe the Object was created during Runtime, which must then be manually recreated and reapplied."); + Debug.LogWarning($"Object with InstanceID '{objectInstanceID}' does not exist.\n Maybe the Object was created during Runtime, which must then be manually recreated and reapplied.\n"); } propertyIterator.objectReferenceValue = objectReference; @@ -577,10 +577,10 @@ private static void HandleOldGameObject(Transform oldRoot, bool backupOldRoot) { // Remove old transform #if UNITY_EDITOR - Debug.Log("Immediate Destroying from Editor", oldRoot); + Debug.Log("Immediate Destroying from Editor\n", oldRoot); UnityEngine.Object.DestroyImmediate(oldRoot); #else - Debug.Log("Destroying during Runtime", oldRoot); + Debug.Log("Destroying during Runtime\n", oldRoot); UnityEngine.Object.Destroy(oldRoot); #endif } diff --git a/Assets/SEE/Cinemachines/CinemachinesRoot.cs b/Assets/SEE/Cinemachines/CinemachinesRoot.cs index 686fd1ecde..d818246b54 100644 --- a/Assets/SEE/Cinemachines/CinemachinesRoot.cs +++ b/Assets/SEE/Cinemachines/CinemachinesRoot.cs @@ -237,7 +237,7 @@ internal void CreateNewScene() { newScene.transform.SetParent(transform); - Debug.LogWarning("Missing Structure. Reset CinemachinesRoot to repair."); + Debug.LogWarning("Missing Structure. Reset CinemachinesRoot to repair.\n"); } // confirm, that the underlining Structure exists @@ -279,17 +279,17 @@ private bool CreateCinemachinesRootStructure() if (!brains || !controlCamera) { // report with error - Debug.LogError("Unable to reconstruct the CinemachinesRoot. Missing Prefabs."); + Debug.LogError("Unable to reconstruct the CinemachinesRoot. Missing Prefabs.\n"); // Log, which Prefabs are missing if (!brains) { - Debug.LogError($"Missing {CinemachinesUtility.CinemachinesBrainsName} Prefab"); + Debug.LogError($"Missing {CinemachinesUtility.CinemachinesBrainsName} Prefab.\n"); } if (!controlCamera) { - Debug.LogError($"Missing {CinemachinesUtility.CinemachinesControlCameraName} Prefab"); + Debug.LogError($"Missing {CinemachinesUtility.CinemachinesControlCameraName} Prefab.\n"); } return false; diff --git a/Assets/SEE/Cinemachines/Dolly/SimpleSpeedController.cs b/Assets/SEE/Cinemachines/Dolly/SimpleSpeedController.cs index 7a62abf148..4fce51e185 100644 --- a/Assets/SEE/Cinemachines/Dolly/SimpleSpeedController.cs +++ b/Assets/SEE/Cinemachines/Dolly/SimpleSpeedController.cs @@ -95,13 +95,11 @@ void SplineAutoDolly.ISplineAutoDolly.Validate() // NullReference and Index Checks if (SpeedList == null) { - // Debug.LogError("Spline Speed-List needs to be initialized"); throw new NullReferenceException("Spline Speed-List needs to be initialized"); } if (SpeedList != null && SpeedList.Length <= 0) { - // Debug.LogError("Spline SpeedController needs at least one Entry in the Speed-List"); throw new IndexOutOfRangeException("Spline SpeedController needs at least one Entry in the Speed-List"); } @@ -110,19 +108,16 @@ void SplineAutoDolly.ISplineAutoDolly.Validate() SplineSector currentEntry = SpeedList[i]; if (currentEntry.SectorStart < 0) { - // Debug.LogError(String.Format("Sector can only start at '0'; At Entry {0}", i)); throw new ArgumentException(String.Format("Sector can only start at '0'; At Entry {0}", i), "SectorRange"); } if (currentEntry.SectorStart >= 1) { - // Debug.LogError(String.Format("Sector can only start before '1'; At Entry {0}", i)); throw new ArgumentException(String.Format("Sector can only start before '1'; At Entry {0}", i), "SectorRange"); } if (currentEntry.SectorSpeed <= 0) { - // Debug.LogErrorFormat(String.Format("Speed should not be zero; At Entry {0}", i)); throw new ArgumentException(String.Format("Speed should not be zero; At Entry {0}", i), "SectorSpeed"); } } diff --git a/Assets/SEE/Cinemachines/UI/UI.cs b/Assets/SEE/Cinemachines/UI/UI.cs index 4542dc265d..f511a8ae21 100644 --- a/Assets/SEE/Cinemachines/UI/UI.cs +++ b/Assets/SEE/Cinemachines/UI/UI.cs @@ -1,5 +1,5 @@ /// -/// SEEEditor.UI contains code for the user interface in SEE inside the Editor. +/// SEE.UI contains code for the user interface in SEE. /// namespace SEE.Cinemachines.UI { diff --git a/Assets/SEE/Cinemachines/Utility/CinemachinesUtility.cs b/Assets/SEE/Cinemachines/Utility/CinemachinesUtility.cs index a4675a3155..2c09b5def6 100644 --- a/Assets/SEE/Cinemachines/Utility/CinemachinesUtility.cs +++ b/Assets/SEE/Cinemachines/Utility/CinemachinesUtility.cs @@ -133,7 +133,7 @@ internal static void GenerateCinemachinesPrefabFolder() AssetDatabase.CreateFolder(CinemachinesPrefabsRoot, "Scenes"); } - Debug.Log($"Created Folder Structure: {CinemachinesPrefabsRoot}/Scenes"); + Debug.Log($"Created Folder Structure: {CinemachinesPrefabsRoot}/Scenes.\n"); return; } } From c96761227cb56cb6368b328990254627cdc8a350 Mon Sep 17 00:00:00 2001 From: Rainer Koschke Date: Tue, 8 Sep 2026 09:20:18 +0200 Subject: [PATCH 16/16] #922 Refactored HandleOldGameObject. Parameter oldRoot can be a GameObject. It was a Transform, but the actual computation took place only for its .gameObject attribute. Replaced object destruction garded by preprocessor directive UNITY_EDITOR by our own Destroyer.Destroy() method. @ThePlays001 needs to check this. Local variable must start with a lower-case letter. Added documentation. Split long lines. --- .../Utility/CinemachinesStateRestorer.cs | 31 +++++++++---------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/Assets/Editor/Cinemachines/Utility/CinemachinesStateRestorer.cs b/Assets/Editor/Cinemachines/Utility/CinemachinesStateRestorer.cs index 44910936d5..20f1b3ffc5 100644 --- a/Assets/Editor/Cinemachines/Utility/CinemachinesStateRestorer.cs +++ b/Assets/Editor/Cinemachines/Utility/CinemachinesStateRestorer.cs @@ -9,10 +9,13 @@ using SEE.Cinemachines; using SEE.Cinemachines.Utility; +using SEE.Utils; + // Only use UnityEditor-Namespaces when inside the Unity-Editor. #if UNITY_EDITOR +/// Required for . using UnityEditor; #endif @@ -21,7 +24,8 @@ namespace SEEEditor.Cinemachines.Utility { /// /// Class for Restoring GameObjects related to the Cinemachines. - /// Based on work done by inkle Studios: https://github.com/inkle/Unity-Save-Play-Mode-Changes under MIT License + /// Based on work done by inkle Studios: https://github.com/inkle/Unity-Save-Play-Mode-Changes + /// under MIT License. /// [InitializeOnLoad] internal static class CinemachinesStateRestorer @@ -194,7 +198,7 @@ private void DeserializeReferences() List storedReferencesList = kvp.Value; // local Counter for iterating through the storedReferences for this Object - int Index = 0; + int index = 0; // check, if there is still a Property accessable while (propertyIterator.NextVisible(true)) @@ -203,7 +207,7 @@ private void DeserializeReferences() if (propertyIterator.propertyType == SerializedPropertyType.ObjectReference) { // Select the indexed StoredReference, which potentially needs to be applied - StoredReference storedReference = storedReferencesList[Index]; + StoredReference storedReference = storedReferencesList[index]; // If the StoredReference was null, ignore it, ... if (!storedReference.IsNull) @@ -232,11 +236,12 @@ private void DeserializeReferences() } // Increment Index for next Reference - Index++; + index++; } } - // Apply all modified Properties to the SerializedObject, which applies the changes to the regular Objects/Components + // Apply all modified Properties to the SerializedObject, which applies the + // changes to the regular Objects/Components serializedObject.ApplyModifiedProperties(); } } @@ -522,7 +527,7 @@ internal static void RestoreCinemachinesRoot() if (CinemachinesRootTransform != null) { // backup old root - HandleOldGameObject(CinemachinesRootTransform, true); + HandleOldGameObject(CinemachinesRootTransform.gameObject, true); } // Load serialized Data @@ -561,7 +566,7 @@ private static void StoreCinemachinesChanges(PlayModeStateChange state) /// /// The GameObject, that will be deactivated or removed. /// Parameter that determines, if the gets removed or deactivated. - private static void HandleOldGameObject(Transform oldRoot, bool backupOldRoot) + private static void HandleOldGameObject(GameObject oldRoot, bool backupOldRoot) { // if the Scenes root doesn't exist, don't try to create a backup if (oldRoot != null) @@ -569,20 +574,14 @@ private static void HandleOldGameObject(Transform oldRoot, bool backupOldRoot) if (backupOldRoot) { // backup old transform - oldRoot.gameObject.name = $"{oldRoot.gameObject.name} - Backup"; - oldRoot.gameObject.SetActive(false); + oldRoot.name = $"{oldRoot.name} - Backup"; + oldRoot.SetActive(false); oldRoot.GetComponent().enabled = false; } else { // Remove old transform - #if UNITY_EDITOR - Debug.Log("Immediate Destroying from Editor\n", oldRoot); - UnityEngine.Object.DestroyImmediate(oldRoot); - #else - Debug.Log("Destroying during Runtime\n", oldRoot); - UnityEngine.Object.Destroy(oldRoot); - #endif + Destroyer.Destroy(oldRoot); } } }