From 71c73de135c4e5a6c069d8baa3d7f20aa0cac997 Mon Sep 17 00:00:00 2001 From: Ludovic LEROUGE - TheRed Games Date: Tue, 7 May 2024 17:48:59 +0200 Subject: [PATCH 01/25] feat: beginning of the planar projection feature --- package/Editor/PlanarProjection.meta | 8 + .../PlanarProjection/PlanarProjection.cs | 112 +++++++++++++ .../PlanarProjection/PlanarProjection.cs.meta | 11 ++ .../PlanarProjectionAssembly.asmdef | 28 ++++ .../PlanarProjectionAssembly.asmdef.meta | 7 + .../PlanarProjection/PlanarProjectionView.cs | 157 ++++++++++++++++++ .../PlanarProjectionView.cs.meta | 11 ++ 7 files changed, 334 insertions(+) create mode 100644 package/Editor/PlanarProjection.meta create mode 100644 package/Editor/PlanarProjection/PlanarProjection.cs create mode 100644 package/Editor/PlanarProjection/PlanarProjection.cs.meta create mode 100644 package/Editor/PlanarProjection/PlanarProjectionAssembly.asmdef create mode 100644 package/Editor/PlanarProjection/PlanarProjectionAssembly.asmdef.meta create mode 100644 package/Editor/PlanarProjection/PlanarProjectionView.cs create mode 100644 package/Editor/PlanarProjection/PlanarProjectionView.cs.meta diff --git a/package/Editor/PlanarProjection.meta b/package/Editor/PlanarProjection.meta new file mode 100644 index 0000000..897ed28 --- /dev/null +++ b/package/Editor/PlanarProjection.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: db83e8ac48d27ba4080e05e741830934 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Editor/PlanarProjection/PlanarProjection.cs b/package/Editor/PlanarProjection/PlanarProjection.cs new file mode 100644 index 0000000..d94ef50 --- /dev/null +++ b/package/Editor/PlanarProjection/PlanarProjection.cs @@ -0,0 +1,112 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; +using UnityEngine.Assertions.Must; +using UnityEngine.Rendering.PostProcessing; + +namespace Scenario.Editor +{ + public class PlanarProjection : EditorWindow + { + #region Public Fields + + public int FlagWindow { get { return flagWindow; } set { flagWindow = value; } } + + public GameObject ReferenceObject { get { return referenceObject; } set { referenceObject = value; } } + + #endregion + + #region Private Fields + + private PlanarProjectionView planarProjectionView = null; + + private int flagWindow = 0; + + private GameObject referenceObject = null; + + private Camera mainCamera = null; + + private GameObject volumePP = null; + + #endregion + + #region MonoBehaviour Callbacks + + [MenuItem("Window/Scenario/Workflow/Planar Projection", false,2)] + public static void ShowWindow() + { + GetWindow("Planar Projection"); + } + + private void OnEnable() + { + planarProjectionView = new PlanarProjectionView(this); + } + + private void OnGUI() + { + planarProjectionView.Render(this.position); + } + + #endregion + + #region Public Methods + + public void CreateReferenceObject() + { + referenceObject = new GameObject("LEVEL"); + } + + public void AutoConfigureScene() + { + if (mainCamera == null) + { + GetMainCamera(); + } + + if (!mainCamera.gameObject.GetComponent()) + { + PostProcessLayer layer = mainCamera.gameObject.AddComponent(); + } + + volumePP = new GameObject("Volume"); + + PostProcessVolume volume = volumePP.AddComponent(); + + volume.isGlobal = true; + PostProcessProfile profile = new PostProcessProfile(); + AmbientOcclusion ao = new AmbientOcclusion(); + + AmbientOcclusionModeParameter aoMode = new AmbientOcclusionModeParameter(); + aoMode.value = AmbientOcclusionMode.MultiScaleVolumetricObscurance; + aoMode.overrideState = true; + + ao.active = true; + ao.enabled.value = true; + + ao.mode = aoMode; + + ao.intensity.value = 0.55f; + ao.intensity.overrideState = true; + + ao.thicknessModifier.value = 1f; + ao.thicknessModifier.overrideState = true; + profile.AddSettings(ao); + volume.profile = profile; + volume.sharedProfile = profile; + volume.runInEditMode = true; + } + + #endregion + + #region Private Methods + + private void GetMainCamera() + { + mainCamera = Camera.main; + } + + #endregion + } +} diff --git a/package/Editor/PlanarProjection/PlanarProjection.cs.meta b/package/Editor/PlanarProjection/PlanarProjection.cs.meta new file mode 100644 index 0000000..ab337f6 --- /dev/null +++ b/package/Editor/PlanarProjection/PlanarProjection.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 412f8edfa042ee443a804b330911973d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Editor/PlanarProjection/PlanarProjectionAssembly.asmdef b/package/Editor/PlanarProjection/PlanarProjectionAssembly.asmdef new file mode 100644 index 0000000..0abdfaf --- /dev/null +++ b/package/Editor/PlanarProjection/PlanarProjectionAssembly.asmdef @@ -0,0 +1,28 @@ +{ + "name": "PlanarProjectionAssembly", + "rootNamespace": "", + "references": [ + "GUID:d60799ab2a985554ea1a39cd38695018", + "GUID:832a8ef6e615e9a41a5076e1c9a43782" + ], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [ + { + "name": "com.unity.recorder", + "expression": "", + "define": "UNITY_RECORDER" + }, + { + "name": "com.unity.postprocessing", + "expression": "", + "define": "UNITY_PP" + } + ], + "noEngineReferences": false +} \ No newline at end of file diff --git a/package/Editor/PlanarProjection/PlanarProjectionAssembly.asmdef.meta b/package/Editor/PlanarProjection/PlanarProjectionAssembly.asmdef.meta new file mode 100644 index 0000000..8299e8d --- /dev/null +++ b/package/Editor/PlanarProjection/PlanarProjectionAssembly.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 408886f41544b614bb58596bf4c9ca02 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Editor/PlanarProjection/PlanarProjectionView.cs b/package/Editor/PlanarProjection/PlanarProjectionView.cs new file mode 100644 index 0000000..c632ab1 --- /dev/null +++ b/package/Editor/PlanarProjection/PlanarProjectionView.cs @@ -0,0 +1,157 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; + +namespace Scenario.Editor +{ + public class PlanarProjectionView + { + #region Public Fields + #endregion + + #region Private Fields + + private PlanarProjection planarProjection = null; + + #endregion + + #region MonoBehaviour Callbacks + + public PlanarProjectionView() + { + planarProjection = new PlanarProjection(); + } + + public PlanarProjectionView(PlanarProjection _planarProjection) + { + planarProjection = _planarProjection; + } + + #endregion + + #region Public Methods + + public void Render(Rect _position) + { + switch (planarProjection.FlagWindow) + { + case 0: + MainView(); + break; + + case 1: + BasicPrepareView(); + break; + + case 2: + RenderSceneView(); + break; + + case 3: + break; + + default: + MainView(); + break; + } + } + + #endregion + + #region Private Methods + + private void MainView() + { + GUILayout.BeginVertical(); + { + GUIStyle title = new GUIStyle(GUI.skin.label); + title.fontSize = 18; + title.fontStyle = FontStyle.Bold; + + GUILayout.Label("Planar Projection", title); + + GUIStyle button = new GUIStyle(GUI.skin.button); + button.fontSize = 16; + button.alignment = TextAnchor.MiddleCenter; + button.fontStyle = FontStyle.Bold; + + if (GUILayout.Button("Project !", button)) + { + planarProjection.FlagWindow = 1; + } + } + GUILayout.EndVertical(); + } + + private void BasicPrepareView() + { + GUILayout.BeginVertical(); + { + GUIStyle title = new GUIStyle(GUI.skin.label); + title.fontSize = 18; + title.fontStyle = FontStyle.Bold; + + GUIStyle button = new GUIStyle(GUI.skin.button); + button.fontSize = 14; + button.fixedWidth = 250; + button.fixedHeight = 50; + button.alignment = TextAnchor.MiddleCenter; + button.fontStyle = FontStyle.Bold; + + GUILayout.Label("Prepare your scene", title); + + if (GUILayout.Button("Create reference object", button)) + { + planarProjection.CreateReferenceObject(); + } + + planarProjection.ReferenceObject = (GameObject)EditorGUILayout.ObjectField(planarProjection.ReferenceObject, typeof(GameObject), true); + + if (GUILayout.Button("Auto configure scene", button)) + { + planarProjection.AutoConfigureScene(); + } + + if (GUILayout.Button("Next", button)) + { + planarProjection.FlagWindow = 2; + } + + } + GUILayout.EndVertical(); + } + + private void RenderSceneView() + { + GUILayout.BeginVertical(); + { + GUIStyle title = new GUIStyle(GUI.skin.label); + title.fontSize = 18; + title.fontStyle = FontStyle.Bold; + + GUIStyle button = new GUIStyle(GUI.skin.button); + button.fontSize = 14; + button.fixedWidth = 250; + button.fixedHeight = 50; + button.alignment = TextAnchor.MiddleCenter; + button.fontStyle = FontStyle.Bold; + + GUILayout.Label("Render scene", title); + + if (GUILayout.Button("Capture Scene", button)) + { + + } + + if (GUILayout.Button("Next", button)) + { + planarProjection.FlagWindow = 3; + } + } + GUILayout.EndVertical(); + } + + #endregion + } +} diff --git a/package/Editor/PlanarProjection/PlanarProjectionView.cs.meta b/package/Editor/PlanarProjection/PlanarProjectionView.cs.meta new file mode 100644 index 0000000..50f7f8e --- /dev/null +++ b/package/Editor/PlanarProjection/PlanarProjectionView.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ecbdbb3c5a19534469fda389a2523273 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: From 0863ef283d5ec0d2232a321e9b26e260d986fdc6 Mon Sep 17 00:00:00 2001 From: Ludovic LEROUGE - TheRed Games Date: Fri, 10 May 2024 17:59:58 +0200 Subject: [PATCH 02/25] fix: auto install and launch unity recorder --- .../PlanarProjection/PlanarProjection.cs | 98 ++++++++++++++++++- .../PlanarProjectionAssembly.asmdef | 6 +- .../PlanarProjection/PlanarProjectionView.cs | 50 ++++++++-- 3 files changed, 143 insertions(+), 11 deletions(-) diff --git a/package/Editor/PlanarProjection/PlanarProjection.cs b/package/Editor/PlanarProjection/PlanarProjection.cs index d94ef50..8ce297a 100644 --- a/package/Editor/PlanarProjection/PlanarProjection.cs +++ b/package/Editor/PlanarProjection/PlanarProjection.cs @@ -1,8 +1,13 @@ using System.Collections; using System.Collections.Generic; +using System.IO; +using Unity.EditorCoroutines.Editor; using UnityEditor; +using UnityEditor.PackageManager; +using UnityEditor.PackageManager.Requests; +using UnityEditor.Recorder; +using UnityEditor.Recorder.Input; using UnityEngine; -using UnityEngine.Assertions.Must; using UnityEngine.Rendering.PostProcessing; namespace Scenario.Editor @@ -12,8 +17,9 @@ public class PlanarProjection : EditorWindow #region Public Fields public int FlagWindow { get { return flagWindow; } set { flagWindow = value; } } - public GameObject ReferenceObject { get { return referenceObject; } set { referenceObject = value; } } + public bool CallRecorderInstall { get { return callRecorderInstall; } set { callRecorderInstall = value; } } + public bool CallPPInstall { get { return callPPInstall; } set { callPPInstall = value; } } #endregion @@ -29,6 +35,17 @@ public class PlanarProjection : EditorWindow private GameObject volumePP = null; + private Request request = null; + + private bool callRecorderInstall = false; + + private bool callPPInstall = false; + + private RecorderWindow recorderWindow = null; + private RecorderControllerSettings recorderSettings = null; + private RecorderController recorderController = null; + private ImageRecorderSettings imageRecorderSettings = null; + #endregion #region MonoBehaviour Callbacks @@ -98,6 +115,66 @@ public void AutoConfigureScene() volume.runInEditMode = true; } + public void CheckUnityRecorder() + { + request = Client.Add("com.unity.recorder"); + EditorApplication.update += Progress; + } + + public void LaunchUnityRecorder() + { + recorderWindow = GetWindow(); + + PrepareRecorderSettings(); + + } + + private void PrepareRecorderSettings() + { + recorderSettings = CreateInstance(); + recorderSettings.ExitPlayMode = true; + recorderSettings.SetRecordModeToSingleFrame(1); + + imageRecorderSettings = CreateInstance(); + imageRecorderSettings.Enabled = true; + imageRecorderSettings.RecordMode = RecordMode.Manual; + imageRecorderSettings.name = "Scenario Sequence"; + + imageRecorderSettings.imageInputSettings = new GameViewInputSettings + { + OutputWidth = 1824, + OutputHeight = 1024, + }; + + imageRecorderSettings.Enabled = true; + imageRecorderSettings.FileNameGenerator.ForceAssetsFolder = true; + imageRecorderSettings.FileNameGenerator.FileName = "_"; + + if (!Directory.Exists($"{Application.dataPath}/{imageRecorderSettings.FileNameGenerator.Leaf}")) + { + Directory.CreateDirectory($"{Application.dataPath}/{imageRecorderSettings.FileNameGenerator.Leaf}"); + } + + recorderSettings.AddRecorderSettings(imageRecorderSettings); + recorderController = new RecorderController(recorderSettings); + recorderWindow.SetRecorderControllerSettings(recorderSettings); + + EditorCoroutineUtility.StartCoroutine(Start(), this); + } + + IEnumerator Start() + { + yield return new WaitForSeconds(1f); + recorderWindow.StartRecording(); + + while (recorderWindow.IsRecording()) + { + yield return new WaitForEndOfFrame(); + } + Debug.Log("CLose window ?"); + recorderWindow.Close(); + } + #endregion #region Private Methods @@ -107,6 +184,23 @@ private void GetMainCamera() mainCamera = Camera.main; } + private void Progress() + { + if (request.IsCompleted) + { + if (request.Status == StatusCode.Success) + { + Debug.Log("Installed: " + request.ToString()); + } + else if (request.Status >= StatusCode.Failure) + { + Debug.Log(request.Error.message); + } + + EditorApplication.update -= Progress; + } + } + #endregion } } diff --git a/package/Editor/PlanarProjection/PlanarProjectionAssembly.asmdef b/package/Editor/PlanarProjection/PlanarProjectionAssembly.asmdef index 0abdfaf..08cd698 100644 --- a/package/Editor/PlanarProjection/PlanarProjectionAssembly.asmdef +++ b/package/Editor/PlanarProjection/PlanarProjectionAssembly.asmdef @@ -1,9 +1,11 @@ { "name": "PlanarProjectionAssembly", - "rootNamespace": "", + "rootNamespace": "Scenario", "references": [ "GUID:d60799ab2a985554ea1a39cd38695018", - "GUID:832a8ef6e615e9a41a5076e1c9a43782" + "GUID:832a8ef6e615e9a41a5076e1c9a43782", + "GUID:847b179520b009e4c8d15c296b1cbf35", + "GUID:478a2357cc57436488a56e564b08d223" ], "includePlatforms": [], "excludePlatforms": [], diff --git a/package/Editor/PlanarProjection/PlanarProjectionView.cs b/package/Editor/PlanarProjection/PlanarProjectionView.cs index c632ab1..deda7ab 100644 --- a/package/Editor/PlanarProjection/PlanarProjectionView.cs +++ b/package/Editor/PlanarProjection/PlanarProjectionView.cs @@ -113,11 +113,18 @@ private void BasicPrepareView() planarProjection.AutoConfigureScene(); } - if (GUILayout.Button("Next", button)) + GUILayout.BeginHorizontal(); { - planarProjection.FlagWindow = 2; + if (GUILayout.Button("Previous", button)) + { + planarProjection.FlagWindow = 0; + } + if (GUILayout.Button("Next", button)) + { + planarProjection.FlagWindow = 2; + } } - + GUILayout.EndHorizontal(); } GUILayout.EndVertical(); } @@ -139,19 +146,48 @@ private void RenderSceneView() GUILayout.Label("Render scene", title); +#if UNITY_RECORDER +#else + if(!planarProjection.CallRecorderInstall) + { + if (EditorUtility.DisplayDialog("Unity Recorder required", "Unity Recorder is required for this stage. Would you like to install it?", "Install", "Cancel")) + { + planarProjection.CheckUnityRecorder(); + planarProjection.CallRecorderInstall = true; + } + else + { + planarProjection.CallRecorderInstall = true; + } + } + + if (GUILayout.Button("Install Recorder", button)) + { + planarProjection.CheckUnityRecorder(); + } +#endif + if (GUILayout.Button("Capture Scene", button)) { - + planarProjection.LaunchUnityRecorder(); } - if (GUILayout.Button("Next", button)) + GUILayout.BeginHorizontal(); { - planarProjection.FlagWindow = 3; + if (GUILayout.Button("Previous", button)) + { + planarProjection.FlagWindow = 1; + } + if (GUILayout.Button("Next", button)) + { + planarProjection.FlagWindow = 3; + } } + GUILayout.EndHorizontal(); } GUILayout.EndVertical(); } - #endregion +#endregion } } From c3cdbf713c32282752ed1f632fa673b44ca1cfc2 Mon Sep 17 00:00:00 2001 From: TheRed Games <30622829+TheLLspectre@users.noreply.github.com> Date: Fri, 10 May 2024 21:18:01 +0200 Subject: [PATCH 03/25] fix: loading last capture --- .../PlanarProjection/PlanarProjection.cs | 101 ++++++++++++++---- .../PlanarProjection/PlanarProjectionView.cs | 5 + 2 files changed, 85 insertions(+), 21 deletions(-) diff --git a/package/Editor/PlanarProjection/PlanarProjection.cs b/package/Editor/PlanarProjection/PlanarProjection.cs index 8ce297a..ed5ff72 100644 --- a/package/Editor/PlanarProjection/PlanarProjection.cs +++ b/package/Editor/PlanarProjection/PlanarProjection.cs @@ -1,3 +1,4 @@ +using System; using System.Collections; using System.Collections.Generic; using System.IO; @@ -20,6 +21,7 @@ public class PlanarProjection : EditorWindow public GameObject ReferenceObject { get { return referenceObject; } set { referenceObject = value; } } public bool CallRecorderInstall { get { return callRecorderInstall; } set { callRecorderInstall = value; } } public bool CallPPInstall { get { return callPPInstall; } set { callPPInstall = value; } } + public Texture2D CaptureImage { get { return captureImage; } set { captureImage = value; } } #endregion @@ -46,6 +48,10 @@ public class PlanarProjection : EditorWindow private RecorderController recorderController = null; private ImageRecorderSettings imageRecorderSettings = null; + private DirectoryInfo directoryInfo = null; + + private Texture2D captureImage = null; + #endregion #region MonoBehaviour Callbacks @@ -59,6 +65,18 @@ public static void ShowWindow() private void OnEnable() { planarProjectionView = new PlanarProjectionView(this); + + if (recorderWindow != null) + { + EditorCoroutineUtility.StartCoroutine(CloseRecorder(), this); + } + + if (directoryInfo == null) + { + directoryInfo = new DirectoryInfo($"{Application.dataPath}/Recordings"); + LoadLastCapture(); + Debug.Log(directoryInfo.FullName); + } } private void OnGUI() @@ -121,6 +139,12 @@ public void CheckUnityRecorder() EditorApplication.update += Progress; } + public void CheckPostProcessing() + { + request = Client.Add("com.unity.postprocessing"); + EditorApplication.update += Progress; + } + public void LaunchUnityRecorder() { recorderWindow = GetWindow(); @@ -129,12 +153,21 @@ public void LaunchUnityRecorder() } - private void PrepareRecorderSettings() + #endregion + + #region Private Methods + + private void GetMainCamera() { + mainCamera = Camera.main; + } + + private void PrepareRecorderSettings() + { recorderSettings = CreateInstance(); recorderSettings.ExitPlayMode = true; recorderSettings.SetRecordModeToSingleFrame(1); - + imageRecorderSettings = CreateInstance(); imageRecorderSettings.Enabled = true; imageRecorderSettings.RecordMode = RecordMode.Manual; @@ -151,8 +184,13 @@ private void PrepareRecorderSettings() imageRecorderSettings.FileNameGenerator.FileName = "_"; if (!Directory.Exists($"{Application.dataPath}/{imageRecorderSettings.FileNameGenerator.Leaf}")) - { - Directory.CreateDirectory($"{Application.dataPath}/{imageRecorderSettings.FileNameGenerator.Leaf}"); + { + directoryInfo = Directory.CreateDirectory($"{Application.dataPath}/{imageRecorderSettings.FileNameGenerator.Leaf}"); + } + else + { + directoryInfo = new DirectoryInfo($"{Application.dataPath}/{imageRecorderSettings.FileNameGenerator.Leaf}"); + Debug.Log(directoryInfo.FullName); } recorderSettings.AddRecorderSettings(imageRecorderSettings); @@ -162,26 +200,33 @@ private void PrepareRecorderSettings() EditorCoroutineUtility.StartCoroutine(Start(), this); } - IEnumerator Start() + private void LoadLastCapture() { - yield return new WaitForSeconds(1f); - recorderWindow.StartRecording(); - - while (recorderWindow.IsRecording()) + if (directoryInfo != null && directoryInfo.GetFileSystemInfos().Length > 0) { - yield return new WaitForEndOfFrame(); - } - Debug.Log("CLose window ?"); - recorderWindow.Close(); - } - - #endregion - - #region Private Methods + string pathFile = string.Empty; + FileSystemInfo fileSystemInfo = null; + foreach (FileSystemInfo fsi in directoryInfo.EnumerateFileSystemInfos()) + { + if (fileSystemInfo == null) + { + fileSystemInfo = fsi; + continue; + } + + if (fsi.CreationTimeUtc < fileSystemInfo.CreationTimeUtc) + { + fileSystemInfo = fsi; + continue; + } + } + Debug.Log(fileSystemInfo.FullName); + pathFile = fileSystemInfo.FullName; - private void GetMainCamera() - { - mainCamera = Camera.main; + captureImage = new Texture2D(2, 2); + byte[] imageData = File.ReadAllBytes(pathFile); + captureImage.LoadImage(imageData); + } } private void Progress() @@ -201,6 +246,20 @@ private void Progress() } } + IEnumerator Start() + { + yield return new EditorWaitForSeconds(1f); + // TODO Trouble on register the first capture from the recorder inside assets folder + recorderWindow.StartRecording(); + } + + IEnumerator CloseRecorder() + { + yield return new EditorWaitForSeconds(1f); + recorderWindow.Close(); + recorderWindow = null; + } + #endregion } } diff --git a/package/Editor/PlanarProjection/PlanarProjectionView.cs b/package/Editor/PlanarProjection/PlanarProjectionView.cs index deda7ab..70b62e3 100644 --- a/package/Editor/PlanarProjection/PlanarProjectionView.cs +++ b/package/Editor/PlanarProjection/PlanarProjectionView.cs @@ -172,6 +172,11 @@ private void RenderSceneView() planarProjection.LaunchUnityRecorder(); } + if (planarProjection.CaptureImage != null) + { + GUI.DrawTexture(planarProjection.position, planarProjection.CaptureImage); + } + GUILayout.BeginHorizontal(); { if (GUILayout.Button("Previous", button)) From 773cda052d97ec101764491396bf5f56b4f0e9cf Mon Sep 17 00:00:00 2001 From: TheRed Games <30622829+TheLLspectre@users.noreply.github.com> Date: Sat, 11 May 2024 21:41:23 +0200 Subject: [PATCH 04/25] fix: update image position and size --- .../PlanarProjection/PlanarProjection.cs | 1 - .../PlanarProjection/PlanarProjectionView.cs | 22 +++++++++++++++++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/package/Editor/PlanarProjection/PlanarProjection.cs b/package/Editor/PlanarProjection/PlanarProjection.cs index ed5ff72..4dc6f9e 100644 --- a/package/Editor/PlanarProjection/PlanarProjection.cs +++ b/package/Editor/PlanarProjection/PlanarProjection.cs @@ -75,7 +75,6 @@ private void OnEnable() { directoryInfo = new DirectoryInfo($"{Application.dataPath}/Recordings"); LoadLastCapture(); - Debug.Log(directoryInfo.FullName); } } diff --git a/package/Editor/PlanarProjection/PlanarProjectionView.cs b/package/Editor/PlanarProjection/PlanarProjectionView.cs index 70b62e3..d3614d6 100644 --- a/package/Editor/PlanarProjection/PlanarProjectionView.cs +++ b/package/Editor/PlanarProjection/PlanarProjectionView.cs @@ -172,9 +172,11 @@ private void RenderSceneView() planarProjection.LaunchUnityRecorder(); } + Rect boxRect = CalculateBoxRect(75, 75, 2, 1); + if (planarProjection.CaptureImage != null) { - GUI.DrawTexture(planarProjection.position, planarProjection.CaptureImage); + GUI.DrawTexture(boxRect, planarProjection.CaptureImage, ScaleMode.ScaleToFit); } GUILayout.BeginHorizontal(); @@ -193,6 +195,22 @@ private void RenderSceneView() GUILayout.EndVertical(); } -#endregion + + /// + /// Calculates the position and dimensions of each texture box within the grid based on the specified box width, box height, row index, and column index. + /// + /// The width of each texture box. + /// The height of each texture box. + /// The row index of the texture box. + /// The column index of the texture box. + /// A Rect representing the position and dimensions of the texture box. + private Rect CalculateBoxRect(float boxWidth, float boxHeight, int rowIndex, int colIndex) + { + float padding = 2.5f; + float x = colIndex * (boxWidth + padding); + float y = rowIndex * (boxHeight + padding); + return new Rect(x, y, boxWidth, boxHeight); + } + #endregion } } From 72adbb1e4d4ae1fc05c8ab0e85666d38a9f7aa8d Mon Sep 17 00:00:00 2001 From: TheRed Games <30622829+TheLLspectre@users.noreply.github.com> Date: Sun, 12 May 2024 21:10:08 +0200 Subject: [PATCH 05/25] fix: progress on implementation of the workflow Prepare documentation --- .../PlanarProjection/PlanarProjection.cs | 115 ++++++++++++++++++ .../PlanarProjectionAssembly.asmdef | 3 +- .../PlanarProjection/PlanarProjectionView.cs | 77 ++++++++---- package/Editor/PromptWindow/PromptWindow.cs | 88 +++++++++++--- package/Editor/_Services/InferenceManager.cs | 2 + 5 files changed, 247 insertions(+), 38 deletions(-) diff --git a/package/Editor/PlanarProjection/PlanarProjection.cs b/package/Editor/PlanarProjection/PlanarProjection.cs index 4dc6f9e..82455ed 100644 --- a/package/Editor/PlanarProjection/PlanarProjection.cs +++ b/package/Editor/PlanarProjection/PlanarProjection.cs @@ -27,31 +27,81 @@ public class PlanarProjection : EditorWindow #region Private Fields + /// + /// + /// private PlanarProjectionView planarProjectionView = null; + /// + /// + /// private int flagWindow = 0; + /// + /// + /// private GameObject referenceObject = null; + /// + /// + /// private Camera mainCamera = null; + /// + /// + /// private GameObject volumePP = null; + /// + /// + /// private Request request = null; + /// + /// + /// private bool callRecorderInstall = false; + /// + /// + /// private bool callPPInstall = false; + /// + /// + /// private RecorderWindow recorderWindow = null; + + /// + /// + /// private RecorderControllerSettings recorderSettings = null; + + /// + /// + /// private RecorderController recorderController = null; + + /// + /// + /// private ImageRecorderSettings imageRecorderSettings = null; + /// + /// + /// private DirectoryInfo directoryInfo = null; + /// + /// + /// private Texture2D captureImage = null; + /// + /// + /// + private PromptWindow promptWindow = null; + #endregion #region MonoBehaviour Callbacks @@ -87,11 +137,17 @@ private void OnGUI() #region Public Methods + /// + /// + /// public void CreateReferenceObject() { referenceObject = new GameObject("LEVEL"); } + /// + /// + /// public void AutoConfigureScene() { if (mainCamera == null) @@ -132,18 +188,27 @@ public void AutoConfigureScene() volume.runInEditMode = true; } + /// + /// + /// public void CheckUnityRecorder() { request = Client.Add("com.unity.recorder"); EditorApplication.update += Progress; } + /// + /// + /// public void CheckPostProcessing() { request = Client.Add("com.unity.postprocessing"); EditorApplication.update += Progress; } + /// + /// + /// public void LaunchUnityRecorder() { recorderWindow = GetWindow(); @@ -152,15 +217,39 @@ public void LaunchUnityRecorder() } + /// + /// + /// + public void OpenPromptWindow() + { + promptWindow = GetWindow(); + if (PromptPusher.Instance != null) + { + promptWindow.SetActiveModeUI(ECreationMode.ControlNet); + PromptWindow.SetDropImageContent(captureImage); + promptWindow.ActiveAdvanceSettings(true); + SetControlNetOptions(); + InferenceManager.SilenceMode = true; + promptWindow.SetImageSettingWidth(1824); + promptWindow.SetImageSettingHeight(1024); + } + } + #endregion #region Private Methods + /// + /// + /// private void GetMainCamera() { mainCamera = Camera.main; } + /// + /// + /// private void PrepareRecorderSettings() { recorderSettings = CreateInstance(); @@ -199,6 +288,9 @@ private void PrepareRecorderSettings() EditorCoroutineUtility.StartCoroutine(Start(), this); } + /// + /// + /// private void LoadLastCapture() { if (directoryInfo != null && directoryInfo.GetFileSystemInfos().Length > 0) @@ -228,6 +320,21 @@ private void LoadLastCapture() } } + /// + /// + /// + private void SetControlNetOptions() + { + if (promptWindow != null) + { + promptWindow.SetAdvancedModality(6); + promptWindow.SetAdvancedModalityValue(75); + } + } + + /// + /// + /// private void Progress() { if (request.IsCompleted) @@ -245,6 +352,10 @@ private void Progress() } } + /// + /// + /// + /// IEnumerator Start() { yield return new EditorWaitForSeconds(1f); @@ -252,6 +363,10 @@ IEnumerator Start() recorderWindow.StartRecording(); } + /// + /// + /// + /// IEnumerator CloseRecorder() { yield return new EditorWaitForSeconds(1f); diff --git a/package/Editor/PlanarProjection/PlanarProjectionAssembly.asmdef b/package/Editor/PlanarProjection/PlanarProjectionAssembly.asmdef index 08cd698..cfbb994 100644 --- a/package/Editor/PlanarProjection/PlanarProjectionAssembly.asmdef +++ b/package/Editor/PlanarProjection/PlanarProjectionAssembly.asmdef @@ -5,7 +5,8 @@ "GUID:d60799ab2a985554ea1a39cd38695018", "GUID:832a8ef6e615e9a41a5076e1c9a43782", "GUID:847b179520b009e4c8d15c296b1cbf35", - "GUID:478a2357cc57436488a56e564b08d223" + "GUID:478a2357cc57436488a56e564b08d223", + "GUID:f6a2e22ca0a59c7409203ee37636196c" ], "includePlatforms": [], "excludePlatforms": [], diff --git a/package/Editor/PlanarProjection/PlanarProjectionView.cs b/package/Editor/PlanarProjection/PlanarProjectionView.cs index d3614d6..3568fcc 100644 --- a/package/Editor/PlanarProjection/PlanarProjectionView.cs +++ b/package/Editor/PlanarProjection/PlanarProjectionView.cs @@ -49,6 +49,7 @@ public void Render(Rect _position) break; case 3: + RenderPromptView(); break; default: @@ -166,18 +167,25 @@ private void RenderSceneView() planarProjection.CheckUnityRecorder(); } #endif + EditorGUILayout.BeginHorizontal(); + { + if (GUILayout.Button("Capture Scene", button)) + { + planarProjection.LaunchUnityRecorder(); + } - if (GUILayout.Button("Capture Scene", button)) - { - planarProjection.LaunchUnityRecorder(); - } - Rect boxRect = CalculateBoxRect(75, 75, 2, 1); + if (planarProjection.CaptureImage != null) + { + GUIStyle imageStyle = new GUIStyle(GUI.skin.box); - if (planarProjection.CaptureImage != null) - { - GUI.DrawTexture(boxRect, planarProjection.CaptureImage, ScaleMode.ScaleToFit); + imageStyle.fixedWidth = planarProjection.CaptureImage.width / 6; + imageStyle.fixedHeight = planarProjection.CaptureImage.height / 6; + + GUILayout.Box(planarProjection.CaptureImage, imageStyle); + } } + EditorGUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); { @@ -188,6 +196,8 @@ private void RenderSceneView() if (GUILayout.Button("Next", button)) { planarProjection.FlagWindow = 3; + + planarProjection.OpenPromptWindow(); } } GUILayout.EndHorizontal(); @@ -195,22 +205,45 @@ private void RenderSceneView() GUILayout.EndVertical(); } - - /// - /// Calculates the position and dimensions of each texture box within the grid based on the specified box width, box height, row index, and column index. - /// - /// The width of each texture box. - /// The height of each texture box. - /// The row index of the texture box. - /// The column index of the texture box. - /// A Rect representing the position and dimensions of the texture box. - private Rect CalculateBoxRect(float boxWidth, float boxHeight, int rowIndex, int colIndex) + private void RenderPromptView() { - float padding = 2.5f; - float x = colIndex * (boxWidth + padding); - float y = rowIndex * (boxHeight + padding); - return new Rect(x, y, boxWidth, boxHeight); + GUILayout.BeginVertical(); + { + GUIStyle title = new GUIStyle(GUI.skin.label); + title.fontSize = 18; + title.fontStyle = FontStyle.Bold; + + GUIStyle infoLabel = new GUIStyle(GUI.skin.label); + infoLabel.fontSize = 14; + infoLabel.alignment = TextAnchor.MiddleLeft; + + GUIStyle button = new GUIStyle(GUI.skin.button); + button.fontSize = 14; + button.fixedWidth = 250; + button.fixedHeight = 50; + button.alignment = TextAnchor.MiddleCenter; + button.fontStyle = FontStyle.Bold; + + GUILayout.Label("Create your scene !", title); + GUILayout.Label("Prompt your projection ideas into the prompt window.", infoLabel); + + + GUILayout.BeginHorizontal(); + { + if (GUILayout.Button("Previous", button)) + { + planarProjection.FlagWindow = 2; + } + if (GUILayout.Button("Next", button)) + { + planarProjection.FlagWindow = 3; + } + } + GUILayout.EndHorizontal(); + } + GUILayout.EndVertical(); } + #endregion } } diff --git a/package/Editor/PromptWindow/PromptWindow.cs b/package/Editor/PromptWindow/PromptWindow.cs index c99e247..adb63c5 100644 --- a/package/Editor/PromptWindow/PromptWindow.cs +++ b/package/Editor/PromptWindow/PromptWindow.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Security.Policy; using UnityEditor; using UnityEngine; @@ -44,21 +45,6 @@ private void Update() PromptWindowUI.imageUpload.LoadImage(pngBytesUploadImage); } - private void UpdateSelectedModel() - { - string selectedModelId = DataCache.instance.SelectedModelId; - string selectedModelName = EditorPrefs.GetString("SelectedModelName"); - - if (!string.IsNullOrEmpty(selectedModelId) && !string.IsNullOrEmpty(selectedModelName)) - { - promptWindowUI.selectedModelName = selectedModelName; - } - else - { - promptWindowUI.selectedModelName = "Choose Model"; - } - } - private void OnGUI() { promptWindowUI.Render(this.position); @@ -105,6 +91,78 @@ public static void SetDropAdditionalImageContent(Texture2D _newContent) promptWindowUI.SetAdditionalDropImage(_newContent); } + /// + /// + /// + /// + public void SetActiveModeUI(ECreationMode _creationMode) + { + promptWindowUI.imageControlTab = (int)_creationMode; + } + + /// + /// + /// + /// + public void ActiveAdvanceSettings(bool _active) + { + promptWindowUI.isAdvancedSettings = _active; + } + + /// + /// + /// + /// + public void SetAdvancedModality(int _selectedModality) + { + promptWindowUI.selectedOptionIndex = _selectedModality; + } + + /// + /// + /// + /// + public void SetAdvancedModalityValue(int _value) + { + promptWindowUI.sliderDisplayedValue = _value; + } + + /// + /// + /// + /// + public void SetImageSettingWidth(int _indexValue) + { + promptWindowUI.WidthSliderValue = _indexValue; + } + + /// + /// + /// + /// + public void SetImageSettingHeight(int _indexValue) + { + promptWindowUI.HeightSliderValue = _indexValue; + } + + /// + /// + /// + private void UpdateSelectedModel() + { + string selectedModelId = DataCache.instance.SelectedModelId; + string selectedModelName = EditorPrefs.GetString("SelectedModelName"); + + if (!string.IsNullOrEmpty(selectedModelId) && !string.IsNullOrEmpty(selectedModelName)) + { + promptWindowUI.selectedModelName = selectedModelName; + } + else + { + promptWindowUI.selectedModelName = "Choose Model"; + } + } + #region API_DTO [Serializable] diff --git a/package/Editor/_Services/InferenceManager.cs b/package/Editor/_Services/InferenceManager.cs index 830898e..ed8ccf2 100644 --- a/package/Editor/_Services/InferenceManager.cs +++ b/package/Editor/_Services/InferenceManager.cs @@ -12,6 +12,8 @@ namespace Scenario.Editor public class InferenceManager { public static List cancelledInferences = new(); + + public static bool SilenceMode = false; public static void PostInferenceRequest(string inputData, int imagesliderIntValue, string promptinputText, int samplesliderValue, float widthSliderValue, float heightSliderValue, From f8a146b4f9d3dc6a2e0ba23bba3fd3b25029542f Mon Sep 17 00:00:00 2001 From: Ludovic LEROUGE - TheRed Games Date: Mon, 13 May 2024 18:03:38 +0200 Subject: [PATCH 06/25] fix: adding image button to project planar, starting all the process --- package/Editor/Images/ImagesUI.cs | 12 ++++ .../PlanarProjection/PlanarProjection.cs | 72 +++++++++++++++++++ .../PlanarProjectionAssembly.asmdef | 31 -------- .../PlanarProjectionAssembly.asmdef.meta | 7 -- .../PlanarProjection/PlanarProjectionView.cs | 61 ++++++++++++++++ .../com.scenarioinc.scenario.editor.asmdef | 17 ++++- 6 files changed, 160 insertions(+), 40 deletions(-) delete mode 100644 package/Editor/PlanarProjection/PlanarProjectionAssembly.asmdef delete mode 100644 package/Editor/PlanarProjection/PlanarProjectionAssembly.asmdef.meta diff --git a/package/Editor/Images/ImagesUI.cs b/package/Editor/Images/ImagesUI.cs index 3faba25..85d3dd3 100644 --- a/package/Editor/Images/ImagesUI.cs +++ b/package/Editor/Images/ImagesUI.cs @@ -193,6 +193,18 @@ private void InitializeButtons() } } }; + + if (InferenceManager.SilenceMode) + { + buttonActions.Add("Projection Planar",()=> + { + if (PlanarProjection.Instance != null) + { + PlanarProjection.Instance.OpenPlanarProjection(selectedTexture); + } + } + ); + } } /// diff --git a/package/Editor/PlanarProjection/PlanarProjection.cs b/package/Editor/PlanarProjection/PlanarProjection.cs index 82455ed..9b46e0c 100644 --- a/package/Editor/PlanarProjection/PlanarProjection.cs +++ b/package/Editor/PlanarProjection/PlanarProjection.cs @@ -10,6 +10,7 @@ using UnityEditor.Recorder.Input; using UnityEngine; using UnityEngine.Rendering.PostProcessing; +using Scenario.Editor; namespace Scenario.Editor { @@ -17,11 +18,14 @@ public class PlanarProjection : EditorWindow { #region Public Fields + public static PlanarProjection Instance = null; + public int FlagWindow { get { return flagWindow; } set { flagWindow = value; } } public GameObject ReferenceObject { get { return referenceObject; } set { referenceObject = value; } } public bool CallRecorderInstall { get { return callRecorderInstall; } set { callRecorderInstall = value; } } public bool CallPPInstall { get { return callPPInstall; } set { callPPInstall = value; } } public Texture2D CaptureImage { get { return captureImage; } set { captureImage = value; } } + public Texture2D RenderResultSelected { get { return renderResultSelected; } set { renderResultSelected = value; } } #endregion @@ -97,11 +101,21 @@ public class PlanarProjection : EditorWindow /// private Texture2D captureImage = null; + /// + /// + /// + private Texture2D renderResultSelected = null; + /// /// /// private PromptWindow promptWindow = null; + /// + /// + /// + private Projector projector = null; + #endregion #region MonoBehaviour Callbacks @@ -116,6 +130,11 @@ private void OnEnable() { planarProjectionView = new PlanarProjectionView(this); + if (Instance == null) + { + Instance = this; + } + if (recorderWindow != null) { EditorCoroutineUtility.StartCoroutine(CloseRecorder(), this); @@ -235,6 +254,38 @@ public void OpenPromptWindow() } } + /// + /// + /// + /// + public void OpenPlanarProjection(Texture2D _renderResult) + { + ShowWindow(); + flagWindow = 4; + + renderResultSelected = new Texture2D(2,2); + renderResultSelected = _renderResult; + } + + /// + /// + /// + public void RenderProjectionWork() + { + if (projector == null) + { + if (mainCamera != null) + { + GameObject projectorObject = new GameObject("Projector"); + projectorObject.transform.parent = mainCamera.transform; + projector = projectorObject.AddComponent(); + + } + } + + CreateProjectedLayer(); + } + #endregion #region Private Methods @@ -332,6 +383,27 @@ private void SetControlNetOptions() } } + /// + /// + /// + private void CreateProjectedLayer() + { + SerializedObject tagManager = new SerializedObject(AssetDatabase.LoadAllAssetsAtPath("ProjectSettings/TagManager.asset")[0]); + + SerializedProperty it = tagManager.GetIterator(); + bool showChildren = true; + while (it.NextVisible(showChildren)) + { + //set your tags here + if (it.name == "User Layer 30") + { + Debug.Log(it.ToString()); + it.stringValue = "My New Layer Name"; + } + } + tagManager.ApplyModifiedProperties(); + } + /// /// /// diff --git a/package/Editor/PlanarProjection/PlanarProjectionAssembly.asmdef b/package/Editor/PlanarProjection/PlanarProjectionAssembly.asmdef deleted file mode 100644 index cfbb994..0000000 --- a/package/Editor/PlanarProjection/PlanarProjectionAssembly.asmdef +++ /dev/null @@ -1,31 +0,0 @@ -{ - "name": "PlanarProjectionAssembly", - "rootNamespace": "Scenario", - "references": [ - "GUID:d60799ab2a985554ea1a39cd38695018", - "GUID:832a8ef6e615e9a41a5076e1c9a43782", - "GUID:847b179520b009e4c8d15c296b1cbf35", - "GUID:478a2357cc57436488a56e564b08d223", - "GUID:f6a2e22ca0a59c7409203ee37636196c" - ], - "includePlatforms": [], - "excludePlatforms": [], - "allowUnsafeCode": false, - "overrideReferences": false, - "precompiledReferences": [], - "autoReferenced": true, - "defineConstraints": [], - "versionDefines": [ - { - "name": "com.unity.recorder", - "expression": "", - "define": "UNITY_RECORDER" - }, - { - "name": "com.unity.postprocessing", - "expression": "", - "define": "UNITY_PP" - } - ], - "noEngineReferences": false -} \ No newline at end of file diff --git a/package/Editor/PlanarProjection/PlanarProjectionAssembly.asmdef.meta b/package/Editor/PlanarProjection/PlanarProjectionAssembly.asmdef.meta deleted file mode 100644 index 8299e8d..0000000 --- a/package/Editor/PlanarProjection/PlanarProjectionAssembly.asmdef.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 408886f41544b614bb58596bf4c9ca02 -AssemblyDefinitionImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/package/Editor/PlanarProjection/PlanarProjectionView.cs b/package/Editor/PlanarProjection/PlanarProjectionView.cs index 3568fcc..466fe46 100644 --- a/package/Editor/PlanarProjection/PlanarProjectionView.cs +++ b/package/Editor/PlanarProjection/PlanarProjectionView.cs @@ -52,6 +52,10 @@ public void Render(Rect _position) RenderPromptView(); break; + case 4: + RenderResult(); + break; + default: MainView(); break; @@ -235,9 +239,66 @@ private void RenderPromptView() planarProjection.FlagWindow = 2; } if (GUILayout.Button("Next", button)) + { + planarProjection.FlagWindow = 4; + } + } + GUILayout.EndHorizontal(); + } + GUILayout.EndVertical(); + } + + private void RenderResult() + { + GUILayout.BeginVertical(); + { + GUIStyle title = new GUIStyle(GUI.skin.label); + title.fontSize = 18; + title.fontStyle = FontStyle.Bold; + + GUIStyle infoLabel = new GUIStyle(GUI.skin.label); + infoLabel.fontSize = 14; + infoLabel.alignment = TextAnchor.MiddleLeft; + + GUIStyle button = new GUIStyle(GUI.skin.button); + button.fontSize = 14; + button.fixedWidth = 250; + button.fixedHeight = 50; + button.alignment = TextAnchor.MiddleCenter; + button.fontStyle = FontStyle.Bold; + + GUILayout.Label("Projection Menu", title); + GUILayout.Label("Project the result", infoLabel); + + if (planarProjection.RenderResultSelected != null) + { + GUIStyle imageStyle = new GUIStyle(GUI.skin.box); + + imageStyle.fixedWidth = planarProjection.RenderResultSelected.width / 2; + imageStyle.fixedHeight = planarProjection.RenderResultSelected.height / 2; + + GUILayout.Box(planarProjection.RenderResultSelected, imageStyle); + } + + GUILayout.Space(25); + + if (GUILayout.Button("Render Projection", button)) + { + planarProjection.RenderProjectionWork(); + } + + GUILayout.Space(25); + + GUILayout.BeginHorizontal(); + { + if (GUILayout.Button("Previous", button)) { planarProjection.FlagWindow = 3; } + if (GUILayout.Button("Next", button)) + { + planarProjection.FlagWindow = 4; + } } GUILayout.EndHorizontal(); } diff --git a/package/Editor/com.scenarioinc.scenario.editor.asmdef b/package/Editor/com.scenarioinc.scenario.editor.asmdef index 93c8d82..a0bd6eb 100644 --- a/package/Editor/com.scenarioinc.scenario.editor.asmdef +++ b/package/Editor/com.scenarioinc.scenario.editor.asmdef @@ -4,7 +4,9 @@ "references": [ "Unity.EditorCoroutines.Editor", "RestSharp.Unity", - "Needle.Deeplink" + "Needle.Deeplink", + "Unity.Recorder.Editor", + "Unity.Postprocessing.Runtime" ], "includePlatforms": [ "Editor" @@ -15,6 +17,17 @@ "precompiledReferences": [], "autoReferenced": true, "defineConstraints": [], - "versionDefines": [], + "versionDefines": [ + { + "name": "com.unity.postprocessing", + "expression": "", + "define": "POST_PROCESSING" + }, + { + "name": "com.unity.recorder", + "expression": "", + "define": "UNITY_RECORDER" + } + ], "noEngineReferences": false } \ No newline at end of file From 50d77a48a4565583e2ee83db62db90c56707b351 Mon Sep 17 00:00:00 2001 From: TheRed Games <30622829+TheLLspectre@users.noreply.github.com> Date: Mon, 13 May 2024 21:00:53 +0200 Subject: [PATCH 07/25] fix: creation of a layer projected --- .../PlanarProjection/PlanarProjection.cs | 48 +++++++++++++++---- 1 file changed, 38 insertions(+), 10 deletions(-) diff --git a/package/Editor/PlanarProjection/PlanarProjection.cs b/package/Editor/PlanarProjection/PlanarProjection.cs index 9b46e0c..812c745 100644 --- a/package/Editor/PlanarProjection/PlanarProjection.cs +++ b/package/Editor/PlanarProjection/PlanarProjection.cs @@ -283,7 +283,7 @@ public void RenderProjectionWork() } } - CreateProjectedLayer(); + CreateProjectedLayer("Projected"); } #endregion @@ -386,22 +386,50 @@ private void SetControlNetOptions() /// /// /// - private void CreateProjectedLayer() + private bool CreateProjectedLayer(string _layerName) { + // Open tag manager SerializedObject tagManager = new SerializedObject(AssetDatabase.LoadAllAssetsAtPath("ProjectSettings/TagManager.asset")[0]); + // Layers Property + SerializedProperty layersProp = tagManager.FindProperty("layers"); + if (!PropertyExists(layersProp, 0, 31, _layerName)) + { + SerializedProperty sp; + // Start at layer 9th index -> 8 (zero based) => first 8 reserved for unity / greyed out + for (int i = 8, j = 31; i < j; i++) + { + sp = layersProp.GetArrayElementAtIndex(i); + if (sp.stringValue == "") + { + // Assign string value to layer + sp.stringValue = _layerName; + Debug.Log("Layer: " + _layerName + " has been added"); + // Save settings + tagManager.ApplyModifiedProperties(); + return true; + } + if (i == j) + Debug.Log("All allowed layers have been filled"); + } + } + else + { + //Debug.Log ("Layer: " + layerName + " already exists"); + } + return false; + } - SerializedProperty it = tagManager.GetIterator(); - bool showChildren = true; - while (it.NextVisible(showChildren)) + private bool PropertyExists(SerializedProperty property, int start, int end, string value) + { + for (int i = start; i < end; i++) { - //set your tags here - if (it.name == "User Layer 30") + SerializedProperty t = property.GetArrayElementAtIndex(i); + if (t.stringValue.Equals(value)) { - Debug.Log(it.ToString()); - it.stringValue = "My New Layer Name"; + return true; } } - tagManager.ApplyModifiedProperties(); + return false; } /// From a31349cedfcf5f4109c9c4cc6fdae7e14c2bef87 Mon Sep 17 00:00:00 2001 From: Ludovic LEROUGE - TheRed Games Date: Tue, 14 May 2024 16:57:41 +0200 Subject: [PATCH 08/25] fix: add CommonGraphics to load graphics ressources, add all the process to render need to be fixed --- package/Assets.meta | 8 + package/Assets/Built-in.meta | 8 + package/Assets/Built-in/Materials.meta | 8 + .../Materials/Scenario_Projector Global.mat | 55 ++ .../Scenario_Projector Global.mat.meta | 8 + package/Assets/Built-in/Shaders.meta | 8 + .../Built-in/Shaders/Scenario 2UV.shader | 59 ++ .../Built-in/Shaders/Scenario 2UV.shader.meta | 9 + .../Shaders/Scenario Projected Debug.shader | 126 ++++ .../Scenario Projected Debug.shader.meta | 9 + .../Shaders/Scenario Projected.shader | 126 ++++ .../Shaders/Scenario Projected.shader.meta | 16 + .../Shaders/ScenarioProjector Debug.shader | 106 +++ .../ScenarioProjector Debug.shader.meta | 10 + .../Built-in/Shaders/ScenarioProjector.shader | 130 ++++ .../Shaders/ScenarioProjector.shader.meta | 10 + package/Assets/URP.meta | 8 + .../PlanarProjection/PlanarProjection.cs | 707 +++++++++++++++++- .../PlanarProjection/PlanarProjectionView.cs | 21 +- package/Editor/Plugins/CommonGraphics.cs | 206 +++++ package/Editor/Plugins/CommonGraphics.cs.meta | 11 + package/Editor/Plugins/CommonUtils.cs | 29 + 22 files changed, 1671 insertions(+), 7 deletions(-) create mode 100644 package/Assets.meta create mode 100644 package/Assets/Built-in.meta create mode 100644 package/Assets/Built-in/Materials.meta create mode 100644 package/Assets/Built-in/Materials/Scenario_Projector Global.mat create mode 100644 package/Assets/Built-in/Materials/Scenario_Projector Global.mat.meta create mode 100644 package/Assets/Built-in/Shaders.meta create mode 100644 package/Assets/Built-in/Shaders/Scenario 2UV.shader create mode 100644 package/Assets/Built-in/Shaders/Scenario 2UV.shader.meta create mode 100644 package/Assets/Built-in/Shaders/Scenario Projected Debug.shader create mode 100644 package/Assets/Built-in/Shaders/Scenario Projected Debug.shader.meta create mode 100644 package/Assets/Built-in/Shaders/Scenario Projected.shader create mode 100644 package/Assets/Built-in/Shaders/Scenario Projected.shader.meta create mode 100644 package/Assets/Built-in/Shaders/ScenarioProjector Debug.shader create mode 100644 package/Assets/Built-in/Shaders/ScenarioProjector Debug.shader.meta create mode 100644 package/Assets/Built-in/Shaders/ScenarioProjector.shader create mode 100644 package/Assets/Built-in/Shaders/ScenarioProjector.shader.meta create mode 100644 package/Assets/URP.meta create mode 100644 package/Editor/Plugins/CommonGraphics.cs create mode 100644 package/Editor/Plugins/CommonGraphics.cs.meta diff --git a/package/Assets.meta b/package/Assets.meta new file mode 100644 index 0000000..84397ab --- /dev/null +++ b/package/Assets.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: aac54d678e692ec4690828a1fd5644f1 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Assets/Built-in.meta b/package/Assets/Built-in.meta new file mode 100644 index 0000000..311f2ae --- /dev/null +++ b/package/Assets/Built-in.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0ee491f179c377b46a503e7c37964d8f +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Assets/Built-in/Materials.meta b/package/Assets/Built-in/Materials.meta new file mode 100644 index 0000000..c464c20 --- /dev/null +++ b/package/Assets/Built-in/Materials.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ac0cd2893494bd3448f3c6edb406eac7 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Assets/Built-in/Materials/Scenario_Projector Global.mat b/package/Assets/Built-in/Materials/Scenario_Projector Global.mat new file mode 100644 index 0000000..e042829 --- /dev/null +++ b/package/Assets/Built-in/Materials/Scenario_Projector Global.mat @@ -0,0 +1,55 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 8 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Scenario_Projector Global + m_Shader: {fileID: 4800000, guid: f658d0c4a8aac0543814f6a7b7704767, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 + m_ValidKeywords: + - UV2 + m_InvalidKeywords: [] + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_LockedProperties: + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _Decal: + m_Texture: {fileID: 2800000, guid: 8da06c97000bd3f4fb2de7f0fbec4993, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _FalloffTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ShadowTex: + m_Texture: {fileID: 2800000, guid: 1c5a069a0ea942f4a880abbccd241434, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Ints: [] + m_Floats: + - _Angle: -1.38 + - _Float: 6 + - _Offset: 0 + - _OffsetFlat: 1.11 + - _OffsetXFlat: 1 + - _OffsetYFlat: 1 + - _ScaleFlat: 2 + - _Slider: 1 + - _UV2: 1 + - _UVSelector: 1 + m_Colors: + - _Color: {r: 1, g: 1, b: 1, a: 1} + - _Offset: {r: 0, g: 0, b: 0, a: 0} + - _Vector: {r: 1, g: 1, b: 1, a: 1} + m_BuildTextureStacks: [] diff --git a/package/Assets/Built-in/Materials/Scenario_Projector Global.mat.meta b/package/Assets/Built-in/Materials/Scenario_Projector Global.mat.meta new file mode 100644 index 0000000..16799f2 --- /dev/null +++ b/package/Assets/Built-in/Materials/Scenario_Projector Global.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ec48ac956eacf1a4a87057dc9b31a379 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Assets/Built-in/Shaders.meta b/package/Assets/Built-in/Shaders.meta new file mode 100644 index 0000000..39d3499 --- /dev/null +++ b/package/Assets/Built-in/Shaders.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 694d701585a4a444ea2a0890536c2828 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Assets/Built-in/Shaders/Scenario 2UV.shader b/package/Assets/Built-in/Shaders/Scenario 2UV.shader new file mode 100644 index 0000000..d6cb659 --- /dev/null +++ b/package/Assets/Built-in/Shaders/Scenario 2UV.shader @@ -0,0 +1,59 @@ +Shader "Scenario/Unlit/Scenario 2UV" +{ + Properties + { + _MainTex ("Texture", 2D) = "white" {} + } + SubShader + { + Tags { "RenderType"="Opaque" } + + Pass + { + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + + #include "UnityCG.cginc" + + struct appdata + { + float4 vertex : POSITION; + float2 uv : TEXCOORD0; + float2 uv2 : TEXCOORD2; + }; + + struct v2f + { + float2 uv : TEXCOORD0; + float2 uv2 : TEXCOORD1; + float4 vertex : SV_POSITION; + }; + + sampler2D _MainTex; + float4 _MainTex_ST; + + v2f vert (appdata v) + { + v2f o; + o.uv2 = v.uv2; + + o.vertex = UnityObjectToClipPos(v.vertex); + o.uv = TRANSFORM_TEX(v.uv, _MainTex); + return o; + } + + fixed4 frag (v2f i) : SV_Target + { + float4 finalColor; + // Sample UV2 coordinate to determine face + float2 uv2Coord = i.uv2; + + // sample the texture + finalColor = tex2D(_MainTex, i.uv2); + return finalColor; +} + ENDCG + } + } +} diff --git a/package/Assets/Built-in/Shaders/Scenario 2UV.shader.meta b/package/Assets/Built-in/Shaders/Scenario 2UV.shader.meta new file mode 100644 index 0000000..48d9dd9 --- /dev/null +++ b/package/Assets/Built-in/Shaders/Scenario 2UV.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: a54bba9ebbf2a744b88107b84f0360cd +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Assets/Built-in/Shaders/Scenario Projected Debug.shader b/package/Assets/Built-in/Shaders/Scenario Projected Debug.shader new file mode 100644 index 0000000..30ea094 --- /dev/null +++ b/package/Assets/Built-in/Shaders/Scenario Projected Debug.shader @@ -0,0 +1,126 @@ +Shader "Scenario/Projected Debug" +{ + Properties + { + _MainTexFront ("Front Texture", 2D) = "white" {} + _MainTexBack ("Back Texture", 2D) = "white" {} + _MainTexLeft ("Left Texture", 2D) = "white" {} + _MainTexRight ("Right Texture", 2D) = "white" {} + _MainTexTop ("Top Texture", 2D) = "white" {} + _MainTexBottom ("Bottom Texture", 2D) = "white" {} + _MainTexOther ("Other Texture", 2D) = "white" {} + } + + SubShader + { + Tags { "RenderType"="Opaque" } + + Pass + { + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #include "UnityCG.cginc" + + struct MeshData + { + float4 vertex : POSITION; + float3 normal : NORMAL; + float2 uv: TEXCOORD0; + float2 uv2 : TEXCOORD2; + }; + + struct v2f + { + float2 uv2 : TEXCOORD11; + float2 uv_MainTexFront : TEXCOORD0; + float2 uv_MainTexBack : TEXCOORD1; + float2 uv_MainTexLeft : TEXCOORD2; + float2 uv_MainTexRight : TEXCOORD3; + float2 uv_MainTexTop : TEXCOORD4; + float2 uv_MainTexBottom : TEXCOORD5; + float2 uv_MainTexOther : TEXCOORD6; + float4 vertex : SV_POSITION; + float3 normal : NORMAL; + }; + + sampler2D _MainTexFront; + float4 _MainTexFront_ST; + + sampler2D _MainTexBack; + float4 _MainTexBack_ST; + + sampler2D _MainTexLeft; + float4 _MainTexLeft_ST; + + sampler2D _MainTexRight; + float4 _MainTexRight_ST; + + sampler2D _MainTexTop; + float4 _MainTexTop_ST; + + sampler2D _MainTexBottom; + float4 _MainTexBottom_ST; + + sampler2D _MainTexOther; + float4 _MainTexOther_ST; + + v2f vert(MeshData v) + { + v2f o; + o.vertex = UnityObjectToClipPos(v.vertex); + o.normal = v.normal; + o.uv2 = v.uv2; + + o.uv_MainTexFront = TRANSFORM_TEX(v.uv, _MainTexFront); + o.uv_MainTexBack = TRANSFORM_TEX(v.uv, _MainTexBack); + o.uv_MainTexLeft = TRANSFORM_TEX(v.uv, _MainTexLeft); + o.uv_MainTexRight = TRANSFORM_TEX(v.uv, _MainTexRight); + o.uv_MainTexTop = TRANSFORM_TEX(v.uv, _MainTexTop); + o.uv_MainTexBottom = TRANSFORM_TEX(v.uv, _MainTexBottom); + o.uv_MainTexOther = TRANSFORM_TEX(v.uv, _MainTexOther); + return o; + } + + fixed4 frag(v2f i) : SV_Target + { + fixed4 finalColor; + + // Sample UV2 coordinate to determine face + float2 uv2Coord = i.uv2; + + fixed4 front = tex2D(_MainTexFront, i.uv_MainTexFront); + fixed4 back = tex2D(_MainTexBack, i.uv_MainTexBack); + fixed4 left = tex2D(_MainTexLeft, i.uv_MainTexLeft); + fixed4 right = tex2D(_MainTexRight, i.uv_MainTexRight); + fixed4 top = tex2D(_MainTexTop, i.uv_MainTexTop); + fixed4 bottom = tex2D(_MainTexBottom, i.uv_MainTexBottom); + fixed4 other = tex2D(_MainTexOther, i.uv_MainTexOther); + + // Determine which face the fragment belongs to based on UV2 coordinate + if (uv2Coord.x < 0.333 && uv2Coord.y < 0.333) + finalColor = top; + else if (uv2Coord.x < 0.666 && uv2Coord.y < 0.333) + finalColor = front; + else if (uv2Coord.x < 1.0 && uv2Coord.y < 0.333) + finalColor = left; + else if (uv2Coord.x < 0.333 && uv2Coord.y < 0.666) + finalColor = bottom; + else if (uv2Coord.x < 0.666 && uv2Coord.y < 0.666) + finalColor = back; + else if (uv2Coord.x < 1.0 && uv2Coord.y < 0.666) + finalColor = right; + /*else if (uv2Coord.x < 0.333 && uv2Coord.y < 1.0) + finalColor = float4(1, 0, 1, 0); + else if (uv2Coord.x < 0.666 && uv2Coord.y < 1.0) + finalColor = float4(1, 1, 1, 0);*/ + else + finalColor = other; + + return finalColor; +} + ENDCG + } + } + FallBack "Diffuse" +} diff --git a/package/Assets/Built-in/Shaders/Scenario Projected Debug.shader.meta b/package/Assets/Built-in/Shaders/Scenario Projected Debug.shader.meta new file mode 100644 index 0000000..641cd2b --- /dev/null +++ b/package/Assets/Built-in/Shaders/Scenario Projected Debug.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 31c98d2dbc352054cb20f8154277802e +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Assets/Built-in/Shaders/Scenario Projected.shader b/package/Assets/Built-in/Shaders/Scenario Projected.shader new file mode 100644 index 0000000..599452c --- /dev/null +++ b/package/Assets/Built-in/Shaders/Scenario Projected.shader @@ -0,0 +1,126 @@ +Shader"Scenario/Projected" +{ + Properties + { + _MainTexFront ("Front Texture", 2D) = "white" {} + _MainTexBack ("Back Texture", 2D) = "white" {} + _MainTexLeft ("Left Texture", 2D) = "white" {} + _MainTexRight ("Right Texture", 2D) = "white" {} + _MainTexTop ("Top Texture", 2D) = "white" {} + _MainTexBottom ("Bottom Texture", 2D) = "white" {} + _MainTexOther ("Other Texture", 2D) = "white" {} + } + + SubShader + { + Tags { "RenderType"="Opaque" } + + Pass + { + CGPROGRAM + #pragma vertex vert + #pragma fragment frag +#include "UnityCG.cginc" + +struct MeshData +{ + float4 vertex : POSITION; + float3 normal : NORMAL; + float2 uv : TEXCOORD0; + float2 uv2 : TEXCOORD2; +}; + +struct v2f +{ + float2 uv2 : TEXCOORD11; + float2 uv_MainTexFront : TEXCOORD0; + float2 uv_MainTexBack : TEXCOORD1; + float2 uv_MainTexLeft : TEXCOORD2; + float2 uv_MainTexRight : TEXCOORD3; + float2 uv_MainTexTop : TEXCOORD4; + float2 uv_MainTexBottom : TEXCOORD5; + float2 uv_MainTexOther : TEXCOORD6; + float4 vertex : SV_POSITION; + float3 normal : NORMAL; +}; + +sampler2D _MainTexFront; +float4 _MainTexFront_ST; + +sampler2D _MainTexBack; +float4 _MainTexBack_ST; + +sampler2D _MainTexLeft; +float4 _MainTexLeft_ST; + +sampler2D _MainTexRight; +float4 _MainTexRight_ST; + +sampler2D _MainTexTop; +float4 _MainTexTop_ST; + +sampler2D _MainTexBottom; +float4 _MainTexBottom_ST; + +sampler2D _MainTexOther; +float4 _MainTexOther_ST; + +v2f vert(MeshData v) +{ + v2f o; + o.vertex = UnityObjectToClipPos(v.vertex); + o.normal = v.normal; + o.uv2 = v.uv2; + + o.uv_MainTexFront = TRANSFORM_TEX(v.uv, _MainTexFront); + o.uv_MainTexBack = TRANSFORM_TEX(v.uv, _MainTexBack); + o.uv_MainTexLeft = TRANSFORM_TEX(v.uv, _MainTexLeft); + o.uv_MainTexRight = TRANSFORM_TEX(v.uv, _MainTexRight); + o.uv_MainTexTop = TRANSFORM_TEX(v.uv, _MainTexTop); + o.uv_MainTexBottom = TRANSFORM_TEX(v.uv, _MainTexBottom); + o.uv_MainTexOther = TRANSFORM_TEX(v.uv, _MainTexOther); + return o; +} + +fixed4 frag(v2f i) : SV_Target +{ + fixed4 finalColor; + + // Sample UV2 coordinate to determine face + float2 uv2Coord = i.uv2; + + fixed4 front = tex2D(_MainTexFront, i.uv_MainTexFront); + fixed4 back = tex2D(_MainTexBack, i.uv_MainTexBack); + fixed4 left = tex2D(_MainTexLeft, i.uv_MainTexLeft); + fixed4 right = tex2D(_MainTexRight, i.uv_MainTexRight); + fixed4 top = tex2D(_MainTexTop, i.uv_MainTexTop); + fixed4 bottom = tex2D(_MainTexBottom, i.uv_MainTexBottom); + fixed4 other = tex2D(_MainTexOther, i.uv_MainTexOther); + + // Determine which face the fragment belongs to based on UV2 coordinate + if (uv2Coord.x < 0.333 && uv2Coord.y < 0.333) + finalColor = top; + else if (uv2Coord.x < 0.666 && uv2Coord.y < 0.333) + finalColor = front; + else if (uv2Coord.x < 1.0 && uv2Coord.y < 0.333) + finalColor = left; + else if (uv2Coord.x < 0.333 && uv2Coord.y < 0.666) + finalColor = bottom; + else if (uv2Coord.x < 0.666 && uv2Coord.y < 0.666) + finalColor = back; + else if (uv2Coord.x < 1.0 && uv2Coord.y < 0.666) + finalColor = right; + /*else if (uv2Coord.x < 0.333 && uv2Coord.y < 1.0) + finalColor = float4(1, 0, 1, 0); + else if (uv2Coord.x < 0.666 && uv2Coord.y < 1.0) + finalColor = float4(1, 1, 1, 0);*/ + else + finalColor = other; + + return finalColor; +} + ENDCG + } + } +FallBack"Diffuse" +} diff --git a/package/Assets/Built-in/Shaders/Scenario Projected.shader.meta b/package/Assets/Built-in/Shaders/Scenario Projected.shader.meta new file mode 100644 index 0000000..40d9189 --- /dev/null +++ b/package/Assets/Built-in/Shaders/Scenario Projected.shader.meta @@ -0,0 +1,16 @@ +fileFormatVersion: 2 +guid: 4aa5ba2fce1ceaa4897ff70e819028d6 +ShaderImporter: + externalObjects: {} + defaultTextures: + - _MainTexFront: {instanceID: 0} + - _MainTexBack: {instanceID: 0} + - _MainTexLeft: {instanceID: 0} + - _MainTexRight: {instanceID: 0} + - _MainTexTop: {instanceID: 0} + - _MainTexBottom: {instanceID: 0} + - _MainTexOther: {instanceID: 0} + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Assets/Built-in/Shaders/ScenarioProjector Debug.shader b/package/Assets/Built-in/Shaders/ScenarioProjector Debug.shader new file mode 100644 index 0000000..a6ab717 --- /dev/null +++ b/package/Assets/Built-in/Shaders/ScenarioProjector Debug.shader @@ -0,0 +1,106 @@ +// Upgrade NOTE: replaced '_Projector' with 'unity_Projector' +// Upgrade NOTE: replaced '_ProjectorClip' with 'unity_ProjectorClip' + +Shader"Scenario/Projector Debug" { + Properties { + _Color ("Main Color", Color) = (1,1,1,1) + _Decal ("Cookie", 2D) = "" {} + _Slider ("Slider", Range(0,1)) = 0 + _ScaleFlat ("Scale Flat", Range(0,10)) = 2 + _OffsetXFlat ("Offset X Flat", Range(-10,10)) = 0 + _OffsetYFlat ("Offset Y Flat", Range(-10,10)) = 0 + _Angle ("Angle", Float) = 0 + [Toggle(UV2)] _UV2 ("Use Second UV Map?", Float) = 0 + _UVSelector ("UV Selector", Range(1,5))= 1 + _Vector ("Vector", Vector) = (0,0,0,1) + _Offset ("Offset", Vector) = (0,0,0,1) + } + + Subshader { + Tags {"RenderType"="Opaque"} + Pass { + /*ZWrite Off + Cull Front + ColorMask RGBA + Blend SrcAlpha OneMinusSrcAlpha*/ + Offset -1, -1 + + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #pragma shader_feature UV2 + #include "UnityCG.cginc" + + struct MeshData{ + float4 vertex : POSITION; // Vertex position + float3 normal : NORMAL; // normal position + float4 tangent : TANGENT; + float4 color : COLOR; + float2 uv0 : TEXCOORD0; // uv0 for diffuse / normal map textures + float2 uv1 : TEXCOORD1; // uv1 coordinates lightmap + float2 uv2 : TEXCOORD2; + }; + + struct v2f { + float4 position : SV_POSITION; + float4 vertexUV : TEXCOORD0; + float4 uvShadow : TEXCOORD1; + float4 normalView: TEXCOORD2; + fixed4 worldPos : TEXCOORD10; + float4 normalRender : TEXCOORD3; + float4 uvShadow3: TEXCOORD4; + }; + + float4x4 unity_Projector; + float4x4 unity_ProjectorClip; + float _Slider; + float4 _Color; + + int _UVSelector; + float _ScaleFlat; + float _OffsetXFlat; + float _OffsetYFlat; + float _Angle; + + float4 _Vector; + float4 _Offset; + + float4 _UvShadow; + + sampler2D _Decal; + + v2f vert (MeshData v) + { + v2f o; + o.position = UnityObjectToClipPos(v.vertex); + float x = v.vertex.x; + float y = v.vertex.y; + + #if UV2 + x = v.uv2.x; + y = v.uv2.y; + #endif + x= x * _ScaleFlat - _OffsetXFlat; + y= y * -_ScaleFlat + _OffsetYFlat; + + o.vertexUV = float4(x, y, 0.1, 1); + o.normalView = UnityObjectToClipPos(v.vertex); + o.position = lerp(o.vertexUV, o.normalView, _Slider); + o.normalRender = (v.normal,0); + o.worldPos = mul(unity_ObjectToWorld, v.vertex); + o.uvShadow = mul(unity_Projector, (v.vertex + _Offset) * _Vector ); + + return o; + } + + fixed4 frag (v2f i) : SV_Target + { + return i.vertexUV; + //fixed4 texS = tex2Dproj(_Decal, i.uvShadow) * _Color; + //return texS; + + } + ENDCG + } + } +} \ No newline at end of file diff --git a/package/Assets/Built-in/Shaders/ScenarioProjector Debug.shader.meta b/package/Assets/Built-in/Shaders/ScenarioProjector Debug.shader.meta new file mode 100644 index 0000000..d04f432 --- /dev/null +++ b/package/Assets/Built-in/Shaders/ScenarioProjector Debug.shader.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 90efea80150482d47b57ea00f963ee36 +ShaderImporter: + externalObjects: {} + defaultTextures: + - _Decal: {instanceID: 0} + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Assets/Built-in/Shaders/ScenarioProjector.shader b/package/Assets/Built-in/Shaders/ScenarioProjector.shader new file mode 100644 index 0000000..8e997d2 --- /dev/null +++ b/package/Assets/Built-in/Shaders/ScenarioProjector.shader @@ -0,0 +1,130 @@ +// Upgrade NOTE: replaced '_Projector' with 'unity_Projector' +// Upgrade NOTE: replaced '_ProjectorClip' with 'unity_ProjectorClip' + +Shader"Scenario/Projector" { + Properties { + _Color ("Main Color", Color) = (1,1,1,1) + _Decal ("Cookie", 2D) = "" {} + _Slider ("Slider", Range(0,1)) = 0 + _ScaleFlat ("Scale Flat", Range(0,10)) = 2 + _OffsetXFlat ("Offset X Flat", Range(-10,10)) = 0 + _OffsetYFlat ("Offset Y Flat", Range(-10,10)) = 0 + _Angle ("Angle", Float) = 0 + [Toggle(UV2)] _UV2 ("Use Second UV Map?", Float) = 0 + _UVSelector ("UV Selector", Range(1,5))= 1 + _Vector ("Vector", Vector) = (0,0,0,1) + _Offset ("Offset", Vector) = (0,0,0,1) + } + + Subshader { + Tags {"RenderType"="Opaque"} + Pass { + /*ZWrite Off + Cull Front + ColorMask RGBA + Blend SrcAlpha OneMinusSrcAlpha*/ + Offset -1, -1 + + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #pragma shader_feature UV2 + #include "UnityCG.cginc" + + struct MeshData{ + float4 vertex : POSITION; // Vertex position + float3 normal : NORMAL; // normal position + float4 tangent : TANGENT; + float4 color : COLOR; + float2 uv0 : TEXCOORD0; // uv0 for diffuse / normal map textures + float2 uv1 : TEXCOORD1; // uv1 coordinates lightmap + float2 uv2 : TEXCOORD2; + }; + + struct v2f { + float4 position : SV_POSITION; + float4 vertexUV : TEXCOORD0; + float4 uvShadow : TEXCOORD1; + float4 normalView: TEXCOORD2; + fixed4 worldPos : TEXCOORD10; + float4 uvShadow2: TEXCOORD3; + float4 uvShadow3: TEXCOORD4; + }; + + float4x4 unity_Projector; + float4x4 unity_ProjectorClip; + float _Slider; + float4 _Color; + + int _UVSelector; + float _ScaleFlat; + float _OffsetXFlat; + float _OffsetYFlat; + float _Angle; + + float4 _Vector; + float4 _Offset; + + float4 _UvShadow; + + sampler2D _Decal; + + v2f vert (MeshData v) + { + v2f o; + o.position = UnityObjectToClipPos(v.vertex); + float x = v.vertex.x; + float y = v.vertex.y; + + #if UV2 + x = v.uv2.x; + y = v.uv2.y; + #endif + x= x * _ScaleFlat - _OffsetXFlat; + y= y * -_ScaleFlat + _OffsetYFlat; + + o.vertexUV = float4(x, y, 0.1, 1); + o.normalView = UnityObjectToClipPos(v.vertex); + o.position = lerp(o.vertexUV, o.normalView, _Slider); + o.worldPos = mul(unity_ObjectToWorld, v.vertex); + + if(_UVSelector == 1) + { + o.uvShadow = mul(unity_Projector, (v.vertex + _Offset) * _Vector ); + } + else if(_UVSelector == 2) + { + o.uvShadow2 = mul(unity_Projector, (v.vertex + _Offset) * _Vector); + } + else + { + o.uvShadow3 = mul(unity_Projector, (v.vertex + _Offset) * _Vector); + } + + return o; + } + + fixed4 frag (v2f i) : SV_Target + { + //return i.uvShadow; + if(_UVSelector == 1) + { + fixed4 texS = tex2Dproj (_Decal, i.uvShadow) * _Color ; + return texS; + } + else if(_UVSelector == 2) + { + fixed4 texS = tex2Dproj (_Decal, i.uvShadow2 + _Angle); + return texS; + } + else + { + fixed4 texS = tex2Dproj (_Decal, i.uvShadow3); + return texS; + } + + } + ENDCG + } + } +} \ No newline at end of file diff --git a/package/Assets/Built-in/Shaders/ScenarioProjector.shader.meta b/package/Assets/Built-in/Shaders/ScenarioProjector.shader.meta new file mode 100644 index 0000000..e0514dd --- /dev/null +++ b/package/Assets/Built-in/Shaders/ScenarioProjector.shader.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: f658d0c4a8aac0543814f6a7b7704767 +ShaderImporter: + externalObjects: {} + defaultTextures: + - _Decal: {instanceID: 0} + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Assets/URP.meta b/package/Assets/URP.meta new file mode 100644 index 0000000..dbe2a64 --- /dev/null +++ b/package/Assets/URP.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3e1ae1e6cf90b054a8a7966b5d60e083 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Editor/PlanarProjection/PlanarProjection.cs b/package/Editor/PlanarProjection/PlanarProjection.cs index 812c745..7b11410 100644 --- a/package/Editor/PlanarProjection/PlanarProjection.cs +++ b/package/Editor/PlanarProjection/PlanarProjection.cs @@ -11,9 +11,51 @@ using UnityEngine; using UnityEngine.Rendering.PostProcessing; using Scenario.Editor; +using static Unity.IO.LowLevel.Unsafe.AsyncReadManagerMetrics; +using System.Runtime.CompilerServices; +using Codice.Utils; namespace Scenario.Editor { + [Serializable] + public struct TargetBundle + { + #region Public Fields + + public GameObject Target { get { return target; } set { target = value; } } + public MeshFilter MeshTarget { get { return meshTarget; } set { meshTarget = value; } } + public MeshRenderer MeshRenderer { get { return meshRenderer; } set { meshRenderer = value; } } + //public EOrientation EOrientation { get { return eOrientation; } set { eOrientation = value; } } + public List TexturesGenerated { get { return texturesGenerated; } set { texturesGenerated = value; } } + + #endregion + + #region Private Fields + + [SerializeField] + private GameObject target; + + [SerializeField] + private MeshFilter meshTarget; + + [SerializeField] + private MeshRenderer meshRenderer; + + /*[SerializeField] + private EOrientation eOrientation;*/ + + [SerializeField] + private List texturesGenerated; + + #endregion + + #region Public Methods + #endregion + + #region Private Methods + #endregion + } + public class PlanarProjection : EditorWindow { #region Public Fields @@ -106,6 +148,11 @@ public class PlanarProjection : EditorWindow /// private Texture2D renderResultSelected = null; + /// + /// + /// + private Texture2D projectedTexture = null; + /// /// /// @@ -116,6 +163,57 @@ public class PlanarProjection : EditorWindow /// private Projector projector = null; + /// + /// + /// + private Material globalProjector = null; + + /// + /// + /// + private Shader projectionShader = null; + + /// + /// + /// + private Shader renderShader = null; + + /// + /// + /// + private Camera renderCamera = null; + + /// + /// + /// + private RenderTexture renderTexture = null; + + private int flag = -1; + + private List targetBundles = new List(); + + private TargetBundle selectedTargetBundle; + + private string destinationPath = string.Empty; + + private float scaleFlat = 2f; + + private float xOffset = 1f; + + private float yOffset = 1f; + + private Vector2[] meshUVs = new Vector2[0]; + + private Vector2 textureSize = new Vector2(1024, 1024); + + private int textureWidth = 1024; + + private int textureHeight = 1024; + + private bool activeSelectFolderSave = true; + + private bool processing = false; + #endregion #region MonoBehaviour Callbacks @@ -274,22 +372,158 @@ public void RenderProjectionWork() { if (projector == null) { - if (mainCamera != null) + SetProjector(); + } + + CreateProjectedLayer("Projected"); + + globalProjector = CommonGraphics.GetMaterial("Scenario_Projector Global"); + + if (globalProjector != null) + { + if (globalProjector.HasTexture("_Decals")) { - GameObject projectorObject = new GameObject("Projector"); - projectorObject.transform.parent = mainCamera.transform; - projector = projectorObject.AddComponent(); + if (renderResultSelected != null) + { + globalProjector.SetTexture("_Decals", renderResultSelected); + } + else + { + throw new Exception("Result selected texture is empty"); + } + } + projector.material = globalProjector; + } + + renderShader = null; + if (renderShader == null) + { + renderShader = CommonGraphics.GetShader("Scenario/Unlit/Scenario 2UV"); + } + + if (referenceObject != null) + { + referenceObject.layer = LayerMask.NameToLayer("Projected"); + + if (referenceObject.GetComponent()) + { + MeshRenderer renderer = referenceObject.GetComponent(); + renderer.material = globalProjector; } + + SetLevel(); } - CreateProjectedLayer("Projected"); + if (renderCamera == null) + { + CreateRenderCamera(); + } + + SearchTargets(); + + RenderProjection(); } #endregion #region Private Methods + /// + /// + /// + private void SearchTargets() + { + if (targetBundles != null && targetBundles.Count > 0) + { + targetBundles.Clear(); + } + + if (referenceObject != null) + { + SearchTarget(referenceObject.transform); + } + else + { + throw new Exception("Reference Object not filled, go back to previous step."); + } + } + + /// + /// + /// + private void RenderProjection() + { + flag = -1; + EditorCoroutineUtility.StartCoroutine(RenderAll(), this); + } + + /// + /// + /// + /// + private void SearchTarget(Transform _searchTarget) + { + if (_searchTarget != null) + { + foreach (Transform child in _searchTarget.transform) + { + if (child.childCount > 0) + { + SearchTarget(child); + } + + TargetBundle bundleObject = new TargetBundle(); + bundleObject.Target = child.gameObject; + if (child.GetComponent()) + { + bundleObject.MeshTarget = child.GetComponent(); + } + else + { + Debug.LogError($"{bundleObject.Target} does not have a Mesh Filter Component", bundleObject.Target); + } + + if (child.GetComponent()) + { + bundleObject.MeshRenderer = child.GetComponent(); + } + else + { + Debug.LogError($"{bundleObject.Target} does not have a Mesh Renderer Component", bundleObject.Target); + } + + //bundleObject.EOrientation = facingOrientation; + + targetBundles.Add(bundleObject); + + } + } + } + + /// + /// + /// + /// + private bool SelectTarget() + { + if (targetBundles != null && targetBundles.Count > 0) + { + if (flag + 1 < targetBundles.Count) + { + flag++; + selectedTargetBundle = targetBundles[flag]; + return true; + } + else + { + flag = -1; + return false; + } + } + return false; + } + /// /// /// @@ -298,6 +532,148 @@ private void GetMainCamera() mainCamera = Camera.main; } + /// + /// + /// + private void CreateRenderCamera() + { + // Calculate the orthographic size of the camera to fit the mesh + //Bounds bounds = selectedTargetBundle.MeshRenderer.bounds; + //float maxDimension = Mathf.Max(bounds.size.x, bounds.size.y, bounds.size.z); + float maxDimension = 20; + float orthographicSize = maxDimension / 2f; + + GameObject tempCameraObject = new GameObject("RenderCamera"); + renderCamera = tempCameraObject.AddComponent(); + renderCamera.orthographic = true; + renderCamera.farClipPlane = 50; + renderCamera.clearFlags = CameraClearFlags.Color; + renderCamera.backgroundColor = Color.white; + renderCamera.orthographicSize = orthographicSize; + renderCamera.cullingMask = 1 << LayerMask.NameToLayer("Projected"); + + /*float sizeA, sizeB; + + sizeB = Mathf.Max(bounds.size.x, bounds.size.y, bounds.size.z); + + if (sizeB == bounds.size.x) + { + sizeA = Mathf.Max(bounds.size.y, bounds.size.z); + } + else if (sizeB == bounds.size.y) + { + sizeA = Mathf.Max(bounds.size.x, bounds.size.z); + } + else + { + sizeA = Mathf.Max(bounds.size.x, bounds.size.y); + } + + if ((sizeA / sizeB) > 1.0f) + { + renderCamera.aspect = sizeB / sizeA; + } + else + { + renderCamera.aspect = sizeA / sizeB; + } + Debug.Log("Vector3 bounds: " + bounds.size + " calcul: " + sizeA + " / " + sizeB + " = " + renderCamera.aspect, renderCamera.gameObject); + //tempCamera.aspect = 0.9f; + */ + + renderCamera.transform.position = referenceObject.transform.position + referenceObject.transform.forward * (maxDimension * 2f); + //renderCamera.transform.parent = selectedTargetBundle.Target.transform; + renderCamera.transform.LookAt(referenceObject.transform.position); + + /*Quaternion tempCameraRotation = renderCamera.transform.localRotation; + tempCameraRotation.eulerAngles = new Vector3(renderCamera.transform.localRotation.eulerAngles.x, 0, 0); + renderCamera.transform.localRotation = tempCameraRotation;*/ + + //Create a render texture for rendering + if (renderResultSelected != null) + { + renderTexture = new RenderTexture(renderResultSelected.width, renderResultSelected.height, 0); + } + else + { + renderTexture = new RenderTexture(1824, 1024, 0); + } + renderCamera.targetTexture = renderTexture; + } + + /// + /// + /// + private void SetProjector() + { + if (mainCamera != null) + { + GameObject projectorObject = new GameObject("Projector"); + projectorObject.transform.parent = mainCamera.transform; + projector = projectorObject.AddComponent(); + + projector.aspectRatio = captureImage.width / captureImage.height; + projector.orthographicSize = 5; + Debug.Log(LayerMask.NameToLayer("Projected")); + projector.ignoreLayers = LayerMask.NameToLayer("Everything") - ( 1 << LayerMask.NameToLayer("Projected")); + } + else + { + GetMainCamera(); + SetProjector(); + } + } + + /// + /// + /// + private void SetLevel() + { + if (referenceObject != null) + { + if (referenceObject.transform.childCount > 0) + { + foreach (Transform child in referenceObject.transform) + { + SetPart(child); + } + } + else + { + SetPart(referenceObject.transform); + } + } + } + + /// + /// + /// + /// + private void SetPart(Transform _part) + { + if (_part != null) + { + _part.gameObject.layer = LayerMask.NameToLayer("Projected"); + + if (_part.GetComponent()) + { + MeshRenderer childRenderer = _part.GetComponent(); + if (globalProjector != null) + { + childRenderer.material = globalProjector; + } + } + + if (_part.childCount > 0) + { + foreach (Transform child in _part) + { + SetPart(child); + } + } + } + } + /// /// /// @@ -383,6 +759,246 @@ private void SetControlNetOptions() } } + /// + /// + /// + public void SetPropertiesToRender() + { + Material projectorMaterial = selectedTargetBundle.MeshRenderer.material; + + if (projectorMaterial.HasFloat("_Slider")) + { + projectorMaterial.SetFloat("_Slider", 0.0f); + projectorMaterial.SetFloat("_ScaleFlat", scaleFlat); + projectorMaterial.SetFloat("_OffsetXFlat", xOffset); + projectorMaterial.SetFloat("_OffsetYFlat", yOffset); + } + } + + [ContextMenu("Reset properties")] + public void ResetPropertiesToRender() + { + Material projectorMaterial = selectedTargetBundle.MeshRenderer.material; + + if (projectorMaterial.HasFloat("_Slider")) + { + projectorMaterial.SetFloat("_Slider", 1.0f); + /*projectorMaterial.SetFloat("_ScaleFlat", scaleFlat); + projectorMaterial.SetFloat("_OffsetXFlat", xOffset); + projectorMaterial.SetFloat("_OffsetYFlat", yOffset);*/ + } + } + + /// + /// + /// + private void PrepareBundleProperties() + { + if (selectedTargetBundle.Target != null) + { + if (selectedTargetBundle.TexturesGenerated == null) + { + selectedTargetBundle.TexturesGenerated = new List(); + } + else if (selectedTargetBundle.TexturesGenerated.Count > 0) + { + selectedTargetBundle.TexturesGenerated.Clear(); + } + } + } + + /// + /// + /// + public void RenderCamera() + { + // Render the scene from the camera's perspective + renderCamera.Render(); + + // Read pixels from the render texture + RenderTexture.active = renderTexture; + projectedTexture.ReadPixels(new Rect(0, 0, textureWidth, textureHeight), 0, 0); + projectedTexture.Apply(); + RenderTexture.active = null; + + // TODO Check if it's usefull + // Map the projected texture onto the UV coordinates + Color[] pixels = projectedTexture.GetPixels(); + for (int i = 0; i < meshUVs.Length; i++) + { + // Scale UV coordinates based on mesh scale to prevent texture deformation + Vector2 scaledUV = new Vector2(meshUVs[i].x * selectedTargetBundle.MeshRenderer.transform.localScale.x, meshUVs[i].y * selectedTargetBundle.MeshRenderer.transform.localScale.y); + int x = Mathf.FloorToInt(scaledUV.x * renderCamera.aspect); + int y = Mathf.FloorToInt(scaledUV.y * renderCamera.aspect); + projectedTexture.SetPixel(x, y, pixels[i]); + } + + projectedTexture.Apply(); + + if (selectedTargetBundle.Target != null) + { + Texture2D toAdd = projectedTexture; + if (selectedTargetBundle.TexturesGenerated != null) + { + selectedTargetBundle.TexturesGenerated.Add(toAdd); + } + else + { + selectedTargetBundle.TexturesGenerated = new List(); + selectedTargetBundle.TexturesGenerated.Add(toAdd); + } + } + } + + /// + /// + /// + private void SetTexture() + { + // Get the texture size + textureWidth = (int)textureSize.x; // Adjust as needed + textureHeight = (int)textureSize.y; // Adjust as needed + + // Create a new texture to store the projected result + projectedTexture = new Texture2D(textureWidth, textureHeight, TextureFormat.RGB24, false); + } + + /// + /// + /// + [ContextMenu("Isolate Target")] + public void IsolateTarget() + { + if (selectedTargetBundle.MeshRenderer != null) + { + if (selectedTargetBundle.MeshRenderer.transform.parent != null) + { + Transform parent = selectedTargetBundle.MeshRenderer.transform.parent; + + if (parent.childCount > 0) + { + foreach (Transform child in parent) + { + if (child != selectedTargetBundle.MeshRenderer.transform) + { + child.gameObject.SetActive(false); + } + else + { + child.gameObject.SetActive(true); + } + } + } + } + } + } + + /// + /// + /// + private void GetBackOthers() + { + if (selectedTargetBundle.MeshRenderer != null) + { + if (selectedTargetBundle.MeshRenderer.transform.parent != null) + { + Transform parent = selectedTargetBundle.MeshRenderer.transform.parent; + + if (parent.childCount > 0) + { + foreach (Transform child in parent) + { + if (child != selectedTargetBundle.MeshRenderer.transform) + { + child.gameObject.SetActive(true); + } + } + } + } + } + } + + /// + /// + /// + public void SaveRender(/*int _index*/) + { + if (activeSelectFolderSave) + { + // Save the texture + + if (string.IsNullOrEmpty(destinationPath)) + { + destinationPath = EditorUtility.SaveFolderPanel("Save Projected Texture", "", $@"ProjectedTexture_{flag}.png"); + Debug.Log(destinationPath); + } + + if (destinationPath.Length != 0) + { + byte[] bytes = projectedTexture.EncodeToPNG(); + System.IO.File.WriteAllBytes($@"{destinationPath}/ProjectedTexture_{flag}_{selectedTargetBundle.Target.gameObject.name}.png", bytes); + Debug.Log("Projected texture saved to: " + $@"{destinationPath}/ProjectedTexture_{flag}_{selectedTargetBundle.Target.gameObject.name}.png"); + + // Apply the texture to the material of the target mesh + //Material material = selectedTargetBundle.MeshRenderer.material; + //material.mainTexture = projectedTexture; + } + } + else + { + // TODO save by default + } + } + + /// + /// + /// + private void ApplyProjection() + { + if (renderShader != null && selectedTargetBundle.TexturesGenerated != null && selectedTargetBundle.TexturesGenerated.Count > 0) + { + Material resultProjected = new Material(renderShader); + + + if (resultProjected.HasTexture("_MainTex")) + { + resultProjected.SetTexture("_MainTex", selectedTargetBundle.TexturesGenerated[0]); + } + + /*if (resultProjected.HasTexture("_MainTexFront")) + { + resultProjected.SetTexture("_MainTexFront", selectedTargetBundle.TexturesGenerated[1]); + } + + if (resultProjected.HasTexture("_MainTexBack")) + { + resultProjected.SetTexture("_MainTexBack", selectedTargetBundle.TexturesGenerated[3]); + } + + if (resultProjected.HasTexture("_MainTexLeft")) + { + resultProjected.SetTexture("_MainTexLeft", selectedTargetBundle.TexturesGenerated[4]); + } + + if (resultProjected.HasTexture("_MainTexRight")) + { + resultProjected.SetTexture("_MainTexRight", selectedTargetBundle.TexturesGenerated[5]); + } + + if (resultProjected.HasTexture("_MainTexTop")) + { + resultProjected.SetTexture("_MainTexTop", selectedTargetBundle.TexturesGenerated[0]); + } + + if (resultProjected.HasTexture("_MainTexBottom")) + { + resultProjected.SetTexture("_MainTexBottom", selectedTargetBundle.TexturesGenerated[2]); + }*/ + + selectedTargetBundle.MeshRenderer.material = resultProjected; + } + } + /// /// /// @@ -474,6 +1090,85 @@ IEnumerator CloseRecorder() recorderWindow = null; } + IEnumerator RenderAll() + { + EditorCoroutine renderCoroutine = null; + while (flag < targetBundles.Count - 1) + { + SelectTarget(); + + if (renderCoroutine == null) + { + processing = true; + renderCoroutine = EditorCoroutineUtility.StartCoroutine(RenderOneGeneration(), this); + } + + while (processing) + { + yield return new WaitForEndOfFrame(); + } + + renderCoroutine = null; + } + + renderCoroutine = null; + destinationPath = string.Empty; + yield return null; + } + + IEnumerator RenderOneGeneration() + { + // Ensure Projector component is assigned + if (projector == null) + { + Debug.LogError("Projector component not assigned."); + yield return null; + } + else if (!projector.enabled) + { + projector.enabled = true; + } + + // Get the mesh + if (selectedTargetBundle.Target == null || selectedTargetBundle.MeshTarget.sharedMesh == null) + { + Debug.LogError("MeshFilter component or mesh not found."); + yield return null; + } + + processing = true; + + //GetMeshFromMeshFilter(); + IsolateTarget(); + + //ClearMaterialTexture(); + + SetTexture(); + + //CreateTemporaryRenderCamera(); + + SetPropertiesToRender(); + yield return new WaitForSeconds(1.0f); + + PrepareBundleProperties(); + + RenderCamera(); + + SaveRender(); + yield return new WaitForSeconds(1.0f); + ResetPropertiesToRender(); + + ApplyProjection(); + + // Deactivate the projector + projector.enabled = false; + + GetBackOthers(); + + processing = false; + yield return null; + } + #endregion } -} +} \ No newline at end of file diff --git a/package/Editor/PlanarProjection/PlanarProjectionView.cs b/package/Editor/PlanarProjection/PlanarProjectionView.cs index 466fe46..5745681 100644 --- a/package/Editor/PlanarProjection/PlanarProjectionView.cs +++ b/package/Editor/PlanarProjection/PlanarProjectionView.cs @@ -32,6 +32,10 @@ public PlanarProjectionView(PlanarProjection _planarProjection) #region Public Methods + /// + /// + /// + /// public void Render(Rect _position) { switch (planarProjection.FlagWindow) @@ -66,6 +70,9 @@ public void Render(Rect _position) #region Private Methods + /// + /// + /// private void MainView() { GUILayout.BeginVertical(); @@ -89,6 +96,9 @@ private void MainView() GUILayout.EndVertical(); } + /// + /// + /// private void BasicPrepareView() { GUILayout.BeginVertical(); @@ -134,6 +144,9 @@ private void BasicPrepareView() GUILayout.EndVertical(); } + /// + /// + /// private void RenderSceneView() { GUILayout.BeginVertical(); @@ -209,6 +222,9 @@ private void RenderSceneView() GUILayout.EndVertical(); } + /// + /// + /// private void RenderPromptView() { GUILayout.BeginVertical(); @@ -248,6 +264,9 @@ private void RenderPromptView() GUILayout.EndVertical(); } + /// + /// + /// private void RenderResult() { GUILayout.BeginVertical(); @@ -307,4 +326,4 @@ private void RenderResult() #endregion } -} +} \ No newline at end of file diff --git a/package/Editor/Plugins/CommonGraphics.cs b/package/Editor/Plugins/CommonGraphics.cs new file mode 100644 index 0000000..4754204 --- /dev/null +++ b/package/Editor/Plugins/CommonGraphics.cs @@ -0,0 +1,206 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Linq; +using Unity.EditorCoroutines.Editor; +using UnityEditor; +using UnityEngine; + +namespace Scenario.Editor +{ + /// + /// + /// + [ExecuteInEditMode] + public class CommonGraphics + { + #region Public Fields + + /// + /// + /// + public static List Shaders = new List(); + + /// + /// + /// + public static List Materials = new List(); + + #endregion + + #region Private Fields + + /// + /// + /// + private static DirectoryInfo directory = null; + + /// + /// + /// + private static List filesInfo = new List(); + + #endregion + + static CommonGraphics() + { + LoadStandardShaders(); + LoadStandardMaterials(); + } + + #region Public Methods + + /// + /// + /// + /// + /// + /// + public static Material GetMaterial(string _materialName) + { + if (Materials != null && Materials.Count > 0) + { + foreach (Material mat in Materials) + { + if (mat.name.Equals(_materialName)) + { + return mat; + } + } + + throw new Exception($"No material {_materialName} loaded"); + } + return null; + } + + /// + /// + /// + /// + /// + /// + public static Shader GetShader(string _shaderName) + { + if (Shaders != null && Shaders.Count > 0) + { + foreach (Shader shade in Shaders) + { + if (shade.name.Equals(_shaderName)) + { + return shade; + } + } + + throw new Exception($"No shader {_shaderName} loaded"); + } + return null; + } + + #endregion + + #region Private Methods + + /// + /// + /// + static void LoadStandardShaders() + { + directory = new DirectoryInfo(CommonUtils.PluginFolderPath() + "Assets/Built-in/Shaders/"); + + filesInfo = directory.GetFiles().ToList(); + + Shaders.Clear(); + + foreach (FileInfo info in filesInfo) + { + if (!info.Extension.Equals(".meta")) + { + LoadStandardShader(CommonUtils.PluginFolderPath() + "Assets/Built-in/Shaders/" + info.Name); + } + } + } + + /// + /// + /// + /// + /// + static void LoadStandardShader(string _path) + { + Shader shade = AssetDatabase.LoadAssetAtPath(_path); + + if (shade != null) + { + Shaders.Add(shade); + } + else + { + throw new Exception($"There is no shader {_path}"); + } + } + + /// + /// + /// + public static void LoadStandardMaterials() + { + directory = new DirectoryInfo(CommonUtils.PluginFolderPath() + "Assets/Built-in/Materials/"); + + filesInfo = directory.GetFiles().ToList(); + + Materials.Clear(); + + foreach (FileInfo info in filesInfo) + { + if (!info.Extension.Equals(".meta")) + { + LoadStandardMaterial(CommonUtils.PluginFolderPath() + "Assets/Built-in/Materials/" + info.Name); + } + } + } + + /// + /// + /// + /// + /// + static void LoadStandardMaterial(string _path) + { + Material mat = AssetDatabase.LoadAssetAtPath(_path); + + if (mat != null) + { + Materials.Add(mat); + } + else + { + throw new Exception($"There is no material {_path}"); + } + } + + /// + /// Coroutine to wait assets to be ready to load it + /// + /// + static IEnumerator WaitToAssetToBeLoaded() + { + var icons = Enum.GetValues(typeof(Icon)); + + foreach (Icon icon in icons) + { + string path = CommonUtils.PluginFolderPath() + "Assets/Icons/" + icon.ToString() + ".png"; + if (!AssetDatabase.LoadMainAssetAtPath(path)) + { + yield break; + } + + //LoadIcon(icon, path); + } + yield return null; + } + + #endregion + } +} diff --git a/package/Editor/Plugins/CommonGraphics.cs.meta b/package/Editor/Plugins/CommonGraphics.cs.meta new file mode 100644 index 0000000..9384fcc --- /dev/null +++ b/package/Editor/Plugins/CommonGraphics.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 691a2dc0fa7d4e14baa69760ca8de952 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Editor/Plugins/CommonUtils.cs b/package/Editor/Plugins/CommonUtils.cs index 258fab5..4382ca2 100644 --- a/package/Editor/Plugins/CommonUtils.cs +++ b/package/Editor/Plugins/CommonUtils.cs @@ -16,6 +16,35 @@ namespace Scenario.Editor [ExecuteInEditMode] public static class CommonUtils { + + private static string assemblyDefinitionFileName = "com.scenarioinc.scenario.editor"; + + /// + /// Return the path to the root of the folder of the plugin + /// + /// + public static string PluginFolderPath() + { + //Find the assembly Definition which should be at package/Editor/ folder because it's a unique file. + string[] guids = AssetDatabase.FindAssets($"{assemblyDefinitionFileName} t:assemblydefinitionasset"); + + if (guids.Length > 1) + { + Debug.LogError($"it seems that you have multiple file '{assemblyDefinitionFileName}.asmdef'. Please delete one"); + return "0"; + } + + if (guids.Length == 0) + { + Debug.LogError($"It seems that you don't have the file '{assemblyDefinitionFileName}.asmdef'. Please redownload the plugin from the asset store."); + return "0"; + } + + //find the folder of that file + string folderPath = AssetDatabase.GUIDToAssetPath(guids[0]); + return folderPath.Remove(folderPath.IndexOf($"Editor/{assemblyDefinitionFileName}.asmdef")); + } + public static Texture2D CreateColorTexture(Color color) { Texture2D texture = new Texture2D(1, 1); From bc6075a4abb386bb204e4a7d0e3850d283f6d782 Mon Sep 17 00:00:00 2001 From: Ludovic LEROUGE - TheRed Games Date: Wed, 15 May 2024 17:34:03 +0200 Subject: [PATCH 09/25] feat: first version with all the workflow --- .../Materials/Scenario_Projector Global.mat | 2 +- package/Assets/Recorder.meta | 8 + .../Recorder/RecorderSettingPreset.asset | 459 ++++++++++++++++++ .../Recorder/RecorderSettingPreset.asset.meta | 8 + .../Recorder/ScenarioRecorderSettings.preset | 375 ++++++++++++++ .../ScenarioRecorderSettings.preset.meta | 8 + package/Editor/Images/ImagesUI.cs | 19 +- .../PlanarProjection/PlanarProjection.cs | 143 +++--- .../PlanarProjection/PlanarProjectionView.cs | 12 +- 9 files changed, 946 insertions(+), 88 deletions(-) create mode 100644 package/Assets/Recorder.meta create mode 100644 package/Assets/Recorder/RecorderSettingPreset.asset create mode 100644 package/Assets/Recorder/RecorderSettingPreset.asset.meta create mode 100644 package/Assets/Recorder/ScenarioRecorderSettings.preset create mode 100644 package/Assets/Recorder/ScenarioRecorderSettings.preset.meta diff --git a/package/Assets/Built-in/Materials/Scenario_Projector Global.mat b/package/Assets/Built-in/Materials/Scenario_Projector Global.mat index e042829..f9b1972 100644 --- a/package/Assets/Built-in/Materials/Scenario_Projector Global.mat +++ b/package/Assets/Built-in/Materials/Scenario_Projector Global.mat @@ -25,7 +25,7 @@ Material: serializedVersion: 3 m_TexEnvs: - _Decal: - m_Texture: {fileID: 2800000, guid: 8da06c97000bd3f4fb2de7f0fbec4993, type: 3} + m_Texture: {fileID: 0} m_Scale: {x: 1, y: 1} m_Offset: {x: 0, y: 0} - _FalloffTex: diff --git a/package/Assets/Recorder.meta b/package/Assets/Recorder.meta new file mode 100644 index 0000000..b3b2b54 --- /dev/null +++ b/package/Assets/Recorder.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3055b5fc4bfdd8d49a9b4edf3e94c7cb +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package/Assets/Recorder/RecorderSettingPreset.asset b/package/Assets/Recorder/RecorderSettingPreset.asset new file mode 100644 index 0000000..0c4febd --- /dev/null +++ b/package/Assets/Recorder/RecorderSettingPreset.asset @@ -0,0 +1,459 @@ +%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: 5537212fe2c4414c9a0cdd7ba0728908, type: 3} + m_Name: RecorderSettingPreset + m_EditorClassIdentifier: + m_Model: {fileID: 2066056468080413454} + m_RecorderPresets: + - {fileID: 2391650939217954612} +--- !u!181963792 &2066056468080413454 +Preset: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Global Settings + m_TargetType: + m_NativeTypeID: 114 + m_ManagedTypePPtr: {fileID: 11500000, guid: a0888db1d9f84d6da3b0d5de41f42c2d, type: 3} + m_ManagedTypeFallback: + m_Properties: + - target: {fileID: 0} + propertyPath: m_Enabled + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_EditorHideFlags + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_EditorClassIdentifier + value: + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_RecordMode + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_FrameRatePlayback + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_FrameRateType + value: 4 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_CustomFrameRateValue + value: 30 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_StartFrame + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_EndFrame + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_StartTime + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_EndTime + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_CapFrameRate + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_ExitPlayMode + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_RecorderSettings.Array.size + value: 0 + objectReference: {fileID: 0} + m_ExcludedProperties: [] +--- !u!181963792 &2391650939217954612 +Preset: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Scenario Sequence + m_TargetType: + m_NativeTypeID: 114 + m_ManagedTypePPtr: {fileID: 11500000, guid: 06397f605c749fe4dbe2df4bbd1ef4a1, type: 3} + m_ManagedTypeFallback: + m_Properties: + - target: {fileID: 0} + propertyPath: m_Enabled + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_EditorHideFlags + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_EditorClassIdentifier + value: + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: enabled + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: take + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: captureEveryNthFrame + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: fileNameGenerator.m_Path.m_Root + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: fileNameGenerator.m_Path.m_Leaf + value: Recordings + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: fileNameGenerator.m_Path.m_ForceAssetFolder + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: fileNameGenerator.m_Path.m_AbsolutePath + value: + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: fileNameGenerator.m_FileName + value: __