| | 1 | | using System; |
| | 2 | | using System.Collections; |
| | 3 | | using System.Collections.Generic; |
| | 4 | | using System.Configuration; |
| | 5 | | using DCL; |
| | 6 | | using DCL.Builder; |
| | 7 | | using DCL.Configuration; |
| | 8 | | using UnityEngine; |
| | 9 | | using DCL.Helpers; |
| | 10 | | using TMPro; |
| | 11 | | using UnityEngine.UI; |
| | 12 | |
|
| | 13 | | internal interface IProjectCardView : IDisposable |
| | 14 | | { |
| | 15 | | /// <summary> |
| | 16 | | /// Edit project button pressed |
| | 17 | | /// </summary> |
| | 18 | | event Action<ProjectData> OnEditorPressed; |
| | 19 | |
|
| | 20 | | /// <summary> |
| | 21 | | /// Setting button pressed |
| | 22 | | /// </summary> |
| | 23 | | event Action<ProjectData> OnSettingsPressed; |
| | 24 | |
|
| | 25 | | /// <summary> |
| | 26 | | /// Expand button pressed |
| | 27 | | /// </summary> |
| | 28 | | event Action OnExpandMenuPressed; |
| | 29 | |
|
| | 30 | | /// <summary> |
| | 31 | | /// Data of the project card |
| | 32 | | /// </summary> |
| | 33 | | ProjectData projectData { get; } |
| | 34 | |
|
| | 35 | | /// <summary> |
| | 36 | | /// Info for the search result |
| | 37 | | /// </summary> |
| | 38 | | ISearchInfo searchInfo { get; } |
| | 39 | |
|
| | 40 | | /// <summary> |
| | 41 | | /// Position of the context menu button |
| | 42 | | /// </summary> |
| | 43 | | Vector3 contextMenuButtonPosition { get; } |
| | 44 | |
|
| | 45 | | /// <summary> |
| | 46 | | /// Set the scenes of the project |
| | 47 | | /// </summary> |
| | 48 | | /// <param name="scenes"></param> |
| | 49 | | void SetScenes(List<Scene> scenes); |
| | 50 | |
|
| | 51 | | /// <summary> |
| | 52 | | /// This setup the project data |
| | 53 | | /// </summary> |
| | 54 | | /// <param name="projectData"></param> |
| | 55 | | void Setup(ProjectData projectData); |
| | 56 | |
|
| | 57 | | /// <summary> |
| | 58 | | /// Set Parent of the card |
| | 59 | | /// </summary> |
| | 60 | | /// <param name="parent"></param> |
| | 61 | | void SetParent(Transform parent); |
| | 62 | |
|
| | 63 | | /// <summary> |
| | 64 | | /// Reset to default parent |
| | 65 | | /// </summary> |
| | 66 | | void SetToDefaultParent(); |
| | 67 | |
|
| | 68 | | /// <summary> |
| | 69 | | /// Configure the default parent |
| | 70 | | /// </summary> |
| | 71 | | /// <param name="parent">default parent to apply</param> |
| | 72 | | void ConfigureDefaultParent(Transform parent); |
| | 73 | |
|
| | 74 | | /// <summary> |
| | 75 | | /// Active the card |
| | 76 | | /// </summary> |
| | 77 | | /// <param name="active"></param> |
| | 78 | | void SetActive(bool active); |
| | 79 | |
|
| | 80 | | /// <summary> |
| | 81 | | /// This set the order of the card |
| | 82 | | /// </summary> |
| | 83 | | /// <param name="index"></param> |
| | 84 | | void SetSiblingIndex(int index); |
| | 85 | |
|
| | 86 | | void SetName(string name); |
| | 87 | | void SetSize(int rows, int columns); |
| | 88 | | void SetThumbnail(string thumbnailUrl, string filename); |
| | 89 | | void SetThumbnail(Texture2D thumbnailTexture); |
| | 90 | | } |
| | 91 | |
|
| | 92 | | internal class ProjectCardView : MonoBehaviour, IProjectCardView |
| | 93 | | { |
| 1 | 94 | | static readonly Vector3 CONTEXT_MENU_OFFSET = new Vector3(6.24f, 12f, 0); |
| | 95 | |
|
| | 96 | | internal const string NOT_PUBLISHED = "NOT PUBLISHED"; |
| | 97 | | internal const string PUBLISHED_IN = "PUBLISHED IN"; |
| | 98 | |
|
| | 99 | | internal const float SCENE_CARD_SIZE = 84; |
| | 100 | | internal const float SCENE_CARD_ITEM_PADDING = 18; |
| | 101 | | internal const float SCENE_CARD_TOTAL_PADDING = 36; |
| | 102 | |
|
| | 103 | | public event Action<ProjectData> OnEditorPressed; |
| | 104 | | public event Action<ProjectData> OnSettingsPressed; |
| | 105 | | public event Action OnExpandMenuPressed; |
| | 106 | |
|
| | 107 | | [Header("Design Variables")] |
| 8 | 108 | | [SerializeField] private float animationSpeed = 6f; |
| | 109 | |
|
| | 110 | | [Header("Project References")] |
| | 111 | | [SerializeField] internal Color syncColor; |
| | 112 | |
|
| | 113 | | [SerializeField] internal Color desyncColor; |
| | 114 | | [SerializeField] private Texture2D defaultThumbnail; |
| | 115 | | [SerializeField] private GameObject projectSceneCardViewPrefab; |
| | 116 | |
|
| | 117 | |
|
| | 118 | | [Header("Prefab references")] |
| | 119 | | [SerializeField] internal Image syncImage; |
| | 120 | |
|
| | 121 | | [SerializeField] internal Button contextMenuButton; |
| | 122 | | [SerializeField] internal Button expandButton; |
| | 123 | | [SerializeField] internal Button editorButton; |
| | 124 | |
|
| | 125 | | [SerializeField] internal RectTransform scenesContainer; |
| | 126 | | [SerializeField] internal VerticalLayoutGroup layoutGroup; |
| | 127 | |
|
| | 128 | | [SerializeField] private GameObject loadingImgGameObject; |
| | 129 | | [SerializeField] private GameObject publishedGameObject; |
| | 130 | | [SerializeField] private RectTransform downButtonTransform; |
| | 131 | | [SerializeField] internal TextMeshProUGUI projectNameTxt; |
| | 132 | | [SerializeField] internal TextMeshProUGUI projectSizeTxt; |
| | 133 | | [SerializeField] internal TextMeshProUGUI projectSyncTxt; |
| | 134 | |
|
| | 135 | | [Space] |
| | 136 | | [SerializeField] private RawImageFillParent thumbnail; |
| | 137 | |
|
| 0 | 138 | | ProjectData IProjectCardView.projectData => projectData; |
| 30 | 139 | | ISearchInfo IProjectCardView.searchInfo { get; } = new SearchInfo(); |
| 0 | 140 | | Vector3 IProjectCardView.contextMenuButtonPosition => contextMenuButton.transform.position + CONTEXT_MENU_OFFSET; |
| | 141 | |
|
| | 142 | | private ProjectData projectData; |
| | 143 | | private ISearchInfo searchInfo; |
| | 144 | | private Vector3 contextMenuButtonPosition; |
| | 145 | |
|
| | 146 | | private string thumbnailId = null; |
| | 147 | | private Transform defaultParent; |
| | 148 | | private AssetPromise_Texture thumbnailPromise; |
| | 149 | | private bool scenesAreVisible = false; |
| | 150 | | private bool isDestroyed = false; |
| | 151 | |
|
| | 152 | | private RectTransform rectTransform; |
| | 153 | |
|
| 8 | 154 | | internal List<Scene> scenesDeployedFromProject = new List<Scene>(); |
| 8 | 155 | | internal List<IProjectSceneCardView> sceneCardViews = new List<IProjectSceneCardView>(); |
| | 156 | |
|
| | 157 | | private Coroutine animationCoroutine; |
| | 158 | |
|
| | 159 | | private void Awake() |
| | 160 | | { |
| 7 | 161 | | editorButton.onClick.AddListener(EditorButtonClicked); |
| 7 | 162 | | expandButton.onClick.AddListener(ExpandButtonPressed); |
| 7 | 163 | | contextMenuButton.onClick.AddListener(EditorButtonClicked); |
| | 164 | |
|
| 7 | 165 | | rectTransform = GetComponent<RectTransform>(); |
| 7 | 166 | | } |
| | 167 | |
|
| | 168 | | private void OnDestroy() |
| | 169 | | { |
| 7 | 170 | | isDestroyed = true; |
| 7 | 171 | | Dispose(); |
| 7 | 172 | | } |
| | 173 | |
|
| | 174 | | public void Dispose() |
| | 175 | | { |
| 8 | 176 | | CoroutineStarter.Stop(animationCoroutine); |
| 8 | 177 | | AssetPromiseKeeper_Texture.i.Forget(thumbnailPromise); |
| 8 | 178 | | editorButton.onClick.RemoveAllListeners(); |
| 8 | 179 | | if(!isDestroyed) |
| 1 | 180 | | Destroy(gameObject); |
| 8 | 181 | | } |
| | 182 | |
|
| | 183 | | public void Setup(ProjectData projectData) |
| | 184 | | { |
| 7 | 185 | | this.projectData = projectData; |
| 7 | 186 | | SetName(projectData.title); |
| 7 | 187 | | SetSize(projectData.rows, projectData.cols); |
| | 188 | |
|
| 7 | 189 | | SetThumbnail(projectData.id, projectData.thumbnail); |
| | 190 | |
|
| 7 | 191 | | ((IProjectCardView)this).searchInfo.SetId(projectData.id); |
| 7 | 192 | | } |
| | 193 | |
|
| | 194 | | public void SetScenes(List<Scene> scenes) |
| | 195 | | { |
| 4 | 196 | | scenesDeployedFromProject = scenes; |
| 4 | 197 | | publishedGameObject.gameObject.SetActive(true); |
| 4 | 198 | | if (scenes.Count == 0) |
| | 199 | | { |
| 1 | 200 | | syncImage.enabled = false; |
| 1 | 201 | | projectSyncTxt.text = NOT_PUBLISHED; |
| 1 | 202 | | downButtonTransform.gameObject.SetActive(false); |
| 1 | 203 | | } |
| | 204 | | else |
| | 205 | | { |
| 3 | 206 | | downButtonTransform.gameObject.SetActive(true); |
| 3 | 207 | | bool isSync = true; |
| 3 | 208 | | long projectTimestamp = BIWUtils.ConvertToMilisecondsTimestamp(projectData.updated_at); |
| 10 | 209 | | foreach (Scene scene in scenes) |
| | 210 | | { |
| 3 | 211 | | if (scene.deployTimestamp < projectTimestamp) |
| | 212 | | { |
| 2 | 213 | | isSync = false; |
| 2 | 214 | | break; |
| | 215 | | } |
| | 216 | | } |
| | 217 | |
|
| 3 | 218 | | if (isSync) |
| 1 | 219 | | syncImage.color = syncColor; |
| | 220 | | else |
| 2 | 221 | | syncImage.color = desyncColor; |
| | 222 | |
|
| 3 | 223 | | projectSyncTxt.text = PUBLISHED_IN; |
| | 224 | | } |
| 3 | 225 | | } |
| | 226 | |
|
| | 227 | | internal void ExpandButtonPressed() |
| | 228 | | { |
| 1 | 229 | | if (scenesDeployedFromProject.Count == 0 ) |
| 0 | 230 | | return; |
| | 231 | |
|
| 1 | 232 | | downButtonTransform.Rotate(Vector3.forward, 180); |
| | 233 | |
|
| 1 | 234 | | scenesAreVisible = !scenesAreVisible; |
| 1 | 235 | | ScenesVisiblitityChange(scenesAreVisible); |
| | 236 | |
|
| 1 | 237 | | float amountToIncrease = sceneCardViews.Count * SCENE_CARD_SIZE + SCENE_CARD_TOTAL_PADDING + SCENE_CARD_ITEM_PAD |
| | 238 | |
|
| 1 | 239 | | if (scenesAreVisible) |
| | 240 | | { |
| 1 | 241 | | layoutGroup.padding.bottom = 18; |
| 1 | 242 | | AddRectTransformHeight(rectTransform, amountToIncrease); |
| 1 | 243 | | AddRectTransformHeight(scenesContainer, amountToIncrease); |
| 1 | 244 | | } |
| | 245 | | else |
| | 246 | | { |
| 0 | 247 | | layoutGroup.padding.bottom = 0; |
| 0 | 248 | | AddRectTransformHeight(rectTransform, -amountToIncrease); |
| 0 | 249 | | AddRectTransformHeight(scenesContainer, -amountToIncrease); |
| | 250 | | } |
| | 251 | |
|
| 1 | 252 | | OnExpandMenuPressed?.Invoke(); |
| 1 | 253 | | } |
| | 254 | |
|
| | 255 | |
|
| | 256 | | private void AddRectTransformHeight(RectTransform rectTransform, float height) |
| | 257 | | { |
| 2 | 258 | | if(animationCoroutine != null) |
| 1 | 259 | | CoroutineStarter.Stop(animationCoroutine); |
| | 260 | |
|
| 2 | 261 | | animationCoroutine = CoroutineStarter.Start(ChangeHeightAnimation(rectTransform, height)); |
| 2 | 262 | | } |
| | 263 | |
|
| | 264 | | private void ScenesVisiblitityChange(bool isVisible) |
| | 265 | | { |
| 1 | 266 | | if (sceneCardViews.Count == 0) |
| 1 | 267 | | InstantiateScenesCards(); |
| | 268 | |
|
| 4 | 269 | | foreach (IProjectSceneCardView scene in sceneCardViews) |
| | 270 | | { |
| 1 | 271 | | scene.SetActive(isVisible); |
| | 272 | | } |
| 1 | 273 | | } |
| | 274 | |
|
| | 275 | | private void InstantiateScenesCards() |
| | 276 | | { |
| 1 | 277 | | long projectTimestamp = BIWUtils.ConvertToMilisecondsTimestamp(projectData.updated_at); |
| 4 | 278 | | foreach (Scene scene in scenesDeployedFromProject) |
| | 279 | | { |
| 1 | 280 | | bool isSync = scene.deployTimestamp < projectTimestamp; |
| | 281 | |
|
| 1 | 282 | | IProjectSceneCardView cardView = Instantiate(projectSceneCardViewPrefab, scenesContainer).GetComponent<Proje |
| 1 | 283 | | cardView.Setup(scene, isSync); |
| 1 | 284 | | sceneCardViews.Add(cardView); |
| | 285 | | } |
| 1 | 286 | | } |
| | 287 | |
|
| | 288 | | internal void EditorButtonClicked() |
| | 289 | | { |
| 1 | 290 | | OnEditorPressed?.Invoke(projectData); |
| 1 | 291 | | } |
| | 292 | |
|
| | 293 | | public void SetThumbnail(string thumbnailId, string thumbnailEndpoint) |
| | 294 | | { |
| 7 | 295 | | if (this.thumbnailId == thumbnailId) |
| 0 | 296 | | return; |
| | 297 | |
|
| 7 | 298 | | string projectThumbnailUrl = ""; |
| 7 | 299 | | if (!string.IsNullOrEmpty(thumbnailId)) |
| | 300 | | { |
| 0 | 301 | | projectThumbnailUrl = BIWUrlUtils.GetBuilderProjecThumbnailUrl(thumbnailId, thumbnailEndpoint); |
| | 302 | | } |
| | 303 | |
|
| 7 | 304 | | this.thumbnailId = thumbnailId; |
| | 305 | |
|
| 7 | 306 | | if (thumbnailPromise != null) |
| | 307 | | { |
| 0 | 308 | | AssetPromiseKeeper_Texture.i.Forget(thumbnailPromise); |
| 0 | 309 | | thumbnailPromise = null; |
| | 310 | | } |
| | 311 | |
|
| 7 | 312 | | if (string.IsNullOrEmpty(projectThumbnailUrl)) |
| | 313 | | { |
| 7 | 314 | | SetThumbnail((Texture2D) null); |
| 7 | 315 | | return; |
| | 316 | | } |
| | 317 | |
|
| 0 | 318 | | thumbnailPromise = new AssetPromise_Texture(projectThumbnailUrl); |
| 0 | 319 | | thumbnailPromise.OnSuccessEvent += texture => SetThumbnail(texture.texture); |
| 0 | 320 | | thumbnailPromise.OnFailEvent += (texture, error) => SetThumbnail(null); |
| | 321 | |
|
| 0 | 322 | | loadingImgGameObject.SetActive(true); |
| 0 | 323 | | thumbnail.enabled = false; |
| 0 | 324 | | AssetPromiseKeeper_Texture.i.Keep(thumbnailPromise); |
| 0 | 325 | | } |
| | 326 | |
|
| | 327 | | public void SetThumbnail(Texture2D thumbnailTexture) |
| | 328 | | { |
| 7 | 329 | | loadingImgGameObject.SetActive(false); |
| 7 | 330 | | thumbnail.texture = thumbnailTexture ?? defaultThumbnail; |
| 7 | 331 | | thumbnail.enabled = true; |
| 7 | 332 | | } |
| | 333 | |
|
| | 334 | | public void SetParent(Transform parent) |
| | 335 | | { |
| 0 | 336 | | if (transform.parent == parent) |
| 0 | 337 | | return; |
| | 338 | |
|
| 0 | 339 | | transform.SetParent(parent); |
| 0 | 340 | | transform.ResetLocalTRS(); |
| 0 | 341 | | } |
| | 342 | |
|
| 2 | 343 | | public void SetToDefaultParent() { transform.SetParent(defaultParent); } |
| | 344 | |
|
| 2 | 345 | | public void ConfigureDefaultParent(Transform parent) { defaultParent = parent; } |
| | 346 | |
|
| 2 | 347 | | public void SetActive(bool active) { gameObject.SetActive(active); } |
| | 348 | |
|
| 0 | 349 | | public void SetSiblingIndex(int index) { transform.SetSiblingIndex(index); } |
| | 350 | |
|
| | 351 | | public void SetName(string name) |
| | 352 | | { |
| 7 | 353 | | projectNameTxt.text = name; |
| 7 | 354 | | ((IProjectCardView)this).searchInfo.SetName(name); |
| 7 | 355 | | } |
| | 356 | |
|
| | 357 | | public void SetSize(int rows, int columns) |
| | 358 | | { |
| 7 | 359 | | projectSizeTxt.text = GetSizeText(rows, columns); |
| 7 | 360 | | ((IProjectCardView)this).searchInfo.SetSize(rows * columns); |
| 7 | 361 | | } |
| | 362 | |
|
| | 363 | | internal string GetSizeText(int rows, int columns) |
| | 364 | | { |
| 8 | 365 | | return (rows * ParcelSettings.PARCEL_SIZE) + "x" + (columns * ParcelSettings.PARCEL_SIZE) + "m"; |
| | 366 | | } |
| | 367 | |
|
| | 368 | | IEnumerator ChangeHeightAnimation(RectTransform rectTransform, float height) |
| | 369 | | { |
| 2 | 370 | | float time = 0; |
| | 371 | |
|
| 2 | 372 | | Vector2 rect2 = rectTransform.sizeDelta; |
| 2 | 373 | | float objective = rect2.y + height; |
| | 374 | |
|
| 2 | 375 | | while (time < 1) |
| | 376 | | { |
| 2 | 377 | | time += Time.deltaTime * animationSpeed / scenesDeployedFromProject.Count; |
| 2 | 378 | | rect2.y = Mathf.Lerp(rect2.y, objective, time); |
| 2 | 379 | | rectTransform.sizeDelta = rect2; |
| 2 | 380 | | yield return null; |
| | 381 | | } |
| 0 | 382 | | } |
| | 383 | | } |