A game about forced loneliness, made by TACStudios
1#if (ENABLE_INPUT_SYSTEM && INPUT_SYSTEM_INSTALLED) 2#define USE_INPUT_SYSTEM 3#endif 4 5using System.Collections.Generic; 6#if UNITY_EDITOR 7using UnityEditor; 8using UnityEngine.SceneManagement; 9using UnityEditor.SceneManagement; 10#endif 11using UnityEngine; 12using TMPro; 13using System.Collections; 14using UnityEngine.Rendering; 15using System.Text.RegularExpressions; 16#if USE_INPUT_SYSTEM 17using UnityEngine.InputSystem; 18#endif 19 20 21[ExecuteInEditMode] 22public class SamplesShowcase : MonoBehaviour 23{ 24 25 public string headline = "Headline Goes Here"; 26 // Color of the headline. light and dark theme variant. 27 public Color headlineLightColor = new Color(0.066f,0.066f,0.066f,1f); 28 public Color headlineDarkColor = new Color(0.82f,0.82f,0.82f,1f); 29 // Color of the text when a link is used to open an asset. light and dark theme variant. 30 public Color openLightColor = new Color(0.086f,0.427f,0.792f,1f); 31 public Color openDarkColor = new Color(0.478f,0.658f,0.933f,1f); 32 // Color of the text when a link is used to highlight an asset in the scene. light and dark theme variant. 33 public Color highlightLightColor = new Color(0.6f,0.4f,0f,1f); 34 public Color highlightDarkColor = new Color(1f,0.89f,0.45f,1f); 35 // Color for code markdown. light and dark theme variant. 36 public Color codeLightColor = new Color(0.76f,0.41f,0f,1f); 37 public Color codeDarkColor = new Color(0.91f,0.57f,0.17f,1f); 38 public TextAsset SamplesDescriptionsJson; 39 public enum Mode {Instantiation, Focus, TextOnly}; 40 public GameObject[] samplesPrefabs; 41 public Mode PresentationMode = Mode.TextOnly; 42 public bool enableSelectButton = true; 43 public int currentIndex; 44 public GameObject currentPrefab; 45 int prefabIndex; 46 private Coroutine cameraCoroutine; 47 48 #if UNITY_EDITOR 49 [SerializeField] 50 public RequiredSettingsSO requiredSettingsSO; 51 #endif 52 53 //Variable containing TMPPro compatible sanitized text 54 public static string SanitizedIntroduction; 55 public static Dictionary<string, string> SanitizedDescriptions; //Key should be the prefabName, value is the description; 56 public static Dictionary<string, string> SanitizedTitles; //Key should be the prefabName, value is the title; 57 58 public TMP_Text gameobjectSamplesName; //if we want to have the samples name on a text mesh pro asset. 59 public TMP_Text gameobjectSamplesDescription; //if we want to have the samples name on a text mesh pro asset. 60 61 //Camera used to update view of samples focus in gameview 62 public Camera gameViewCamera; 63 64 private bool needUpdate; 65 private Vector3 savedPrefabPosition; 66 67 //Delegate to update every instance of samples showcase inspector UI 68 #if UNITY_EDITOR 69 public delegate void UpdateSamplesInspectorDelegate(); 70 public static UpdateSamplesInspectorDelegate OnUpdateSamplesInspector; 71 void UpdateSamplesInspector() 72 { 73 if (OnUpdateSamplesInspector != null) 74 { 75 OnUpdateSamplesInspector(); 76 } 77 } 78 #endif 79 80 void OnEnable() 81 { 82 // JSon data of the samples 83 if (SamplesDescriptionsJson != null) 84 { 85 string jsonText = CleanupJson(SamplesDescriptionsJson.text); 86 87 Samples sampleJsonObject = Samples.CreateFromJSON(jsonText, samplesPrefabs); 88 89 //Introduction, it's the first part of the Samples Description text asset 90 string introText = sampleJsonObject.introduction; 91 SamplesShowcase.SanitizedIntroduction = SanitizeText(introText); 92 93 SamplesShowcase.SanitizedDescriptions = new Dictionary<string, string>(); 94 SamplesShowcase.SanitizedTitles = new Dictionary<string, string>(); 95 foreach(GameObject prefab in samplesPrefabs) 96 { 97 Sample currentSample = sampleJsonObject.FindSampleWithPrefab(prefab); 98 if (currentSample == null) 99 continue; 100 101 string description = SanitizeText(currentSample.description); 102 SamplesShowcase.SanitizedDescriptions.Add(prefab.name, description); 103 SamplesShowcase.SanitizedTitles.Add(prefab.name, currentSample.title); 104 } 105 } 106 } 107 108 void OnValidate() 109 { 110 needUpdate = true; 111 } 112 113 void Update() 114 { 115 if (PresentationMode != Mode.TextOnly) 116 { 117 //Controls in GameMode 118 if (Application.isFocused && Application.isPlaying) 119 { 120#if ENABLE_LEGACY_INPUT_MANAGER 121 if (Input.GetKeyDown(KeyCode.RightArrow) || Input.GetKeyDown(KeyCode.UpArrow) ) 122 { 123 SwitchEffect(currentIndex+1); 124 } 125 if (Input.GetKeyDown(KeyCode.LeftArrow) || Input.GetKeyDown(KeyCode.DownArrow) ) 126 { 127 SwitchEffect(currentIndex-1); 128 } 129#endif 130 131#if USE_INPUT_SYSTEM 132 if (Keyboard.current.rightArrowKey.wasPressedThisFrame || Keyboard.current.upArrowKey.wasPressedThisFrame) 133 { 134 SwitchEffect(currentIndex+1); 135 } 136 137 if(Keyboard.current.leftArrowKey.wasPressedThisFrame ||Keyboard.current.downArrowKey.wasPressedThisFrame) 138 { 139 SwitchEffect(currentIndex-1); 140 } 141#endif 142 143 } 144 145 if (needUpdate) 146 { 147 PresentSample(currentIndex); 148 needUpdate = false; 149 } 150 } 151 152 153 } 154 155 void SwitchEffect(int value) 156 { 157 currentIndex = value; 158 currentIndex = currentIndex > samplesPrefabs.Length - 1 ? 0 : currentIndex; 159 currentIndex = currentIndex < 0 ? samplesPrefabs.Length - 1 : currentIndex; 160 needUpdate = true; 161 } 162 163 164 void PresentSample(int index) 165 { 166 switch (PresentationMode) 167 { 168 case Mode.Instantiation: 169 if (index != prefabIndex) 170 { 171 CleanChildren(); 172 if (index <= samplesPrefabs.Length && samplesPrefabs.Length > 0) 173 { 174 currentPrefab = samplesPrefabs[index]; 175 } 176 177 // Instantiate the prefab as child 178 if (currentPrefab != null) 179 { 180 GameObject instantiatedPrefab = Instantiate(currentPrefab, transform.position, Quaternion.identity) as GameObject; 181 instantiatedPrefab.transform.parent = gameObject.transform; 182 instantiatedPrefab.transform.localRotation = Quaternion.identity; 183 currentPrefab = instantiatedPrefab; 184 prefabIndex = index; 185 186 // This is for keeping the prefab at the same position as before 187 instantiatedPrefab.transform.position = savedPrefabPosition; 188 189 } 190 } 191 break; 192 193 case Mode.Focus: 194 if (index <= samplesPrefabs.Length && samplesPrefabs.Length > 0) 195 { 196 currentPrefab = samplesPrefabs[index]; 197 } 198 199 if (currentPrefab != null) 200 { 201 Transform viewPoint = currentPrefab.transform.Find("ViewPoint"); 202 if (viewPoint != null) 203 { 204 // Align Scene View Camera 205 #if UNITY_EDITOR 206 SceneView view = SceneView.lastActiveSceneView; 207 if (view != null) 208 { 209 view.AlignViewToObject(viewPoint.transform); 210 } 211 #endif 212 213 // Align game view if a gameViewCamera is set 214 if (gameViewCamera != null) 215 { 216 if(cameraCoroutine !=null) 217 { 218 StopCoroutine(cameraCoroutine); 219 } 220 cameraCoroutine = StartCoroutine(lerpTransform(gameViewCamera.transform, viewPoint)); 221 } 222 } 223 } 224 break; 225 } 226 227 #if UNITY_EDITOR 228 UpdateSamplesInspector(); 229 #endif 230 } 231 232 private IEnumerator lerpTransform(Transform transformA, Transform transformB) 233 { 234 float startTime=Time.time; 235 while(Time.time-startTime<=1)//one second 236 { 237 transformA.position=Vector3.Lerp(transformA.position,transformB.position,Time.time-startTime); 238 transformA.rotation = Quaternion.Lerp(transformA.rotation,transformB.rotation, Time.time-startTime); 239 yield return 1; // wait for next frame 240 } 241 } 242 243 244 void CleanChildren() 245 { 246 //We just remove anything that has been spawn as child 247 if (transform.childCount > 0) 248 { 249 // This is for keeping the prefab at the same position as before 250 savedPrefabPosition = transform.GetChild(0).position; 251 252 foreach (Transform child in transform) 253 { 254 GameObject.DestroyImmediate(child.gameObject); 255 } 256 } 257 } 258 259 public static string GetSanitizedDescription(string prefabName) 260 { 261 if(SanitizedDescriptions == null) return ""; 262 263 if(SanitizedDescriptions.ContainsKey(prefabName)) 264 return SanitizedDescriptions[prefabName]; 265 266 return ""; 267 } 268 269 public static string GetSanitizedTitle(string prefabName) 270 { 271 if(SanitizedTitles == null) return ""; 272 273 if(SanitizedTitles.ContainsKey(prefabName)) 274 return SanitizedTitles[prefabName]; 275 276 return ""; 277 } 278 279 public static string GetSanitizedIntroduction() 280 { 281 return SanitizedIntroduction; 282 } 283 284 public static string SanitizeText(string text) 285 { 286 // Convert <br> to line break characters 287 text = text.Replace("<br>", "\n"); 288 289 // Format <link> and <a> 290 text = Regex.Replace(text, @"<a[\s\S]*?>([\s\S]*?)<\/a>", $"$1"); 291 text = Regex.Replace(text, @"<link[\s\S]*?>([\s\S]*?)<\/link>", $"$1"); 292 293 // Add some offset to lists 294 text = text.Replace("�", " �"); 295 296 // Remove text between <ignore> tags 297 text = Regex.Replace(text, @"<ignore>[\s\S]*?</ignore>", ""); 298 299 return text; 300 } 301 302 public static string CleanupJson(string jsonString) 303 { 304 // Reformat json 305 // For text between triple quotes, remove \r \n \t characters 306 307 // Select text between triple quotes 308 string pattern = @"(\""\""\"")([\s\S]*?)(\""\""\"")"; 309 310 // Clean it 311 jsonString = Regex.Replace(jsonString, pattern, m => 312 { 313 string tripleQuotedText = m.Groups[2].Value; 314 // Replace newline by <br> 315 tripleQuotedText = tripleQuotedText.Replace("\n", "<br>"); 316 // Escape quotes 317 tripleQuotedText = tripleQuotedText.Replace("\"", "\\\""); 318 // Remove carriage return and tabs 319 tripleQuotedText = Regex.Replace(tripleQuotedText, "[\r\t]", ""); 320 321 return $"\"{tripleQuotedText}\""; 322 }); 323 324 return jsonString; 325 } 326 327}