| | 1 | | using DCL; |
| | 2 | | using DCL.Helpers; |
| | 3 | | using System; |
| | 4 | | using DCL.Builder; |
| | 5 | | using TMPro; |
| | 6 | | using UnityEngine; |
| | 7 | | using UnityEngine.UI; |
| | 8 | |
|
| | 9 | | /// <summary> |
| | 10 | | /// This interface represent a scene card |
| | 11 | | /// </summary> |
| | 12 | | internal interface ISceneCardView : IDisposable |
| | 13 | | { |
| | 14 | | /// <summary> |
| | 15 | | /// Jump button pressed |
| | 16 | | /// </summary> |
| | 17 | | event Action<Vector2Int> OnJumpInPressed; |
| | 18 | |
|
| | 19 | | /// <summary> |
| | 20 | | /// Editor button pressed |
| | 21 | | /// </summary> |
| | 22 | | event Action<Vector2Int> OnEditorPressed; |
| | 23 | |
|
| | 24 | | /// <summary> |
| | 25 | | /// Setting button presed |
| | 26 | | /// </summary> |
| | 27 | | event Action<ISceneData> OnSettingsPressed; |
| | 28 | |
|
| | 29 | | /// <summary> |
| | 30 | | /// Context button present |
| | 31 | | /// </summary> |
| | 32 | | event Action<ISceneData, ISceneCardView> OnContextMenuPressed; |
| | 33 | |
|
| | 34 | | /// <summary> |
| | 35 | | /// Data of the scene |
| | 36 | | /// </summary> |
| | 37 | | ISceneData SceneData { get; } |
| | 38 | |
|
| | 39 | | /// <summary> |
| | 40 | | /// Info of the search |
| | 41 | | /// </summary> |
| | 42 | | ISearchInfo searchInfo { get; } |
| | 43 | |
|
| | 44 | | /// <summary> |
| | 45 | | /// Position of the context menu |
| | 46 | | /// </summary> |
| | 47 | | Vector3 contextMenuButtonPosition { get; } |
| | 48 | |
|
| | 49 | | /// <summary> |
| | 50 | | /// This set the data of the card |
| | 51 | | /// </summary> |
| | 52 | | /// <param name="sceneData">data of the card</param> |
| | 53 | | void Setup(ISceneData sceneData); |
| | 54 | |
|
| | 55 | | /// <summary> |
| | 56 | | /// Set Parent of the card |
| | 57 | | /// </summary> |
| | 58 | | /// <param name="parent"></param> |
| | 59 | | void SetParent(Transform parent); |
| | 60 | |
|
| | 61 | | /// <summary> |
| | 62 | | /// Reset to default parent |
| | 63 | | /// </summary> |
| | 64 | | void SetToDefaultParent(); |
| | 65 | |
|
| | 66 | | /// <summary> |
| | 67 | | /// Configure the default parent |
| | 68 | | /// </summary> |
| | 69 | | /// <param name="parent">default parent to apply</param> |
| | 70 | | void ConfigureDefaultParent(Transform parent); |
| | 71 | |
|
| | 72 | | /// <summary> |
| | 73 | | /// This set the order of the card |
| | 74 | | /// </summary> |
| | 75 | | /// <param name="index"></param> |
| | 76 | | void SetSiblingIndex(int index); |
| | 77 | |
|
| | 78 | | void SetName(string name); |
| | 79 | | void SetCoords(Vector2Int coords); |
| | 80 | | void SetSize(Vector2Int size); |
| | 81 | | void SetThumbnail(string thumbnailUrl); |
| | 82 | | void SetThumbnail(Texture2D thumbnailTexture); |
| | 83 | | void SetDeployed(bool deployed); |
| | 84 | | void SetEditable(bool isEditable); |
| | 85 | | void SetUserRole(bool isOwner, bool isOperator, bool isContributor); |
| | 86 | | void SetActive(bool active); |
| | 87 | | } |
| | 88 | |
|
| | 89 | | internal class SceneCardView : MonoBehaviour, ISceneCardView |
| | 90 | | { |
| | 91 | | const int THMBL_MARKETPLACE_WIDTH = 196; |
| | 92 | | const int THMBL_MARKETPLACE_HEIGHT = 143; |
| | 93 | | const int THMBL_MARKETPLACE_SIZEFACTOR = 50; |
| | 94 | |
|
| 1 | 95 | | static readonly Vector3 CONTEXT_MENU_OFFSET = new Vector3(6.24f, 12f, 0); |
| | 96 | |
|
| | 97 | | public event Action<Vector2Int> OnJumpInPressed; |
| | 98 | | public event Action<Vector2Int> OnEditorPressed; |
| | 99 | | public event Action<ISceneData> OnSettingsPressed; |
| | 100 | | public event Action<ISceneData, ISceneCardView> OnContextMenuPressed; |
| | 101 | |
|
| | 102 | | [SerializeField] private Texture2D defaultThumbnail; |
| | 103 | |
|
| | 104 | | [Space] |
| | 105 | | [SerializeField] private RawImageFillParent thumbnail; |
| | 106 | |
|
| | 107 | | [SerializeField] private TextMeshProUGUI sceneName; |
| | 108 | |
|
| | 109 | | [Space] |
| | 110 | | [SerializeField] internal GameObject coordsContainer; |
| | 111 | |
|
| | 112 | | [SerializeField] private TextMeshProUGUI coordsText; |
| | 113 | |
|
| | 114 | | [Space] |
| | 115 | | [SerializeField] internal GameObject sizeContainer; |
| | 116 | |
|
| | 117 | | [SerializeField] private TextMeshProUGUI sizeText; |
| | 118 | |
|
| | 119 | | [Space] |
| | 120 | | [SerializeField] internal Button jumpInButton; |
| | 121 | |
|
| | 122 | | [SerializeField] internal Button editorButton; |
| | 123 | | [SerializeField] internal Button contextMenuButton; |
| | 124 | | [SerializeField] internal Button settingsButton; |
| | 125 | |
|
| | 126 | | [Space] |
| | 127 | | [SerializeField] internal GameObject roleOwnerGO; |
| | 128 | |
|
| | 129 | | [SerializeField] internal GameObject roleOperatorGO; |
| | 130 | | [SerializeField] internal GameObject roleContributorGO; |
| | 131 | |
|
| | 132 | | [Space] |
| | 133 | | [SerializeField] internal GameObject editorLockedGO; |
| | 134 | |
|
| | 135 | | [SerializeField] internal GameObject editorLockedTooltipGO; |
| | 136 | |
|
| | 137 | | [SerializeField] internal Animator loadingAnimator; |
| | 138 | |
|
| 1 | 139 | | private static readonly int isLoadingAnimation = Animator.StringToHash("isLoading"); |
| | 140 | |
|
| 154 | 141 | | ISearchInfo ISceneCardView.searchInfo { get; } = new SearchInfo(); |
| 46 | 142 | | ISceneData ISceneCardView.SceneData => sceneData; |
| 0 | 143 | | Vector3 ISceneCardView.contextMenuButtonPosition => contextMenuButton.transform.position + CONTEXT_MENU_OFFSET; |
| | 144 | |
|
| | 145 | | private ISceneData sceneData; |
| | 146 | | private string thumbnailUrl = null; |
| | 147 | | private AssetPromise_Texture thumbnailPromise; |
| | 148 | | private bool isDestroyed = false; |
| | 149 | | private Transform defaultParent; |
| | 150 | | private bool isLoadingThumbnail = false; |
| | 151 | |
|
| | 152 | | private void Awake() |
| | 153 | | { |
| 18 | 154 | | jumpInButton.onClick.AddListener( JumpInButtonPressed ); |
| 18 | 155 | | editorButton.onClick.AddListener( EditorButtonPressed ); |
| 18 | 156 | | contextMenuButton.onClick.AddListener(() => OnContextMenuPressed?.Invoke(sceneData, this)); |
| 18 | 157 | | settingsButton.onClick.AddListener(() => OnSettingsPressed?.Invoke(sceneData)); |
| | 158 | |
|
| 18 | 159 | | editorLockedGO.SetActive(false); |
| 18 | 160 | | editorLockedTooltipGO.SetActive(false); |
| 18 | 161 | | } |
| | 162 | |
|
| | 163 | | private void JumpInButtonPressed() |
| | 164 | | { |
| 0 | 165 | | OnJumpInPressed?.Invoke(sceneData.coords); |
| 0 | 166 | | BIWAnalytics.PlayerJumpOrEdit("Scene", "JumpIn", sceneData.coords, "Scene Owner"); |
| 0 | 167 | | } |
| | 168 | |
|
| | 169 | | private void EditorButtonPressed() |
| | 170 | | { |
| 0 | 171 | | OnEditorPressed?.Invoke(sceneData.coords); |
| 0 | 172 | | BIWAnalytics.PlayerJumpOrEdit("Scene", "Editor", sceneData.coords, "Scene Owner"); |
| 0 | 173 | | } |
| | 174 | |
|
| 56 | 175 | | private void OnEnable() { loadingAnimator.SetBool(isLoadingAnimation, isLoadingThumbnail); } |
| | 176 | |
|
| | 177 | | void ISceneCardView.Setup(ISceneData sceneData) |
| | 178 | | { |
| 25 | 179 | | this.sceneData = sceneData; |
| | 180 | |
|
| 25 | 181 | | string sceneThumbnailUrl = sceneData.thumbnailUrl; |
| 25 | 182 | | if (string.IsNullOrEmpty(sceneThumbnailUrl) && sceneData.parcels != null) |
| | 183 | | { |
| 0 | 184 | | sceneThumbnailUrl = MapUtils.GetMarketPlaceThumbnailUrl(sceneData.parcels, |
| | 185 | | THMBL_MARKETPLACE_WIDTH, THMBL_MARKETPLACE_HEIGHT, THMBL_MARKETPLACE_SIZEFACTOR); |
| | 186 | | } |
| | 187 | |
|
| 25 | 188 | | ISceneCardView thisView = this; |
| 25 | 189 | | thisView.SetThumbnail(sceneThumbnailUrl); |
| 25 | 190 | | thisView.SetName(sceneData.name); |
| 25 | 191 | | thisView.SetCoords(sceneData.coords); |
| 25 | 192 | | thisView.SetSize(sceneData.size); |
| 25 | 193 | | thisView.SetDeployed(sceneData.isDeployed); |
| 25 | 194 | | thisView.SetUserRole(sceneData.isOwner, sceneData.isOperator, sceneData.isContributor); |
| 25 | 195 | | thisView.SetEditable(sceneData.isEditable); |
| | 196 | |
|
| 25 | 197 | | thisView.searchInfo.SetId(sceneData.id); |
| 25 | 198 | | } |
| | 199 | |
|
| | 200 | | void ISceneCardView.SetParent(Transform parent) |
| | 201 | | { |
| 10 | 202 | | if (transform.parent == parent) |
| 0 | 203 | | return; |
| | 204 | |
|
| 10 | 205 | | transform.SetParent(parent); |
| 10 | 206 | | transform.ResetLocalTRS(); |
| 10 | 207 | | } |
| | 208 | |
|
| | 209 | | void ISceneCardView.SetName(string name) |
| | 210 | | { |
| 25 | 211 | | sceneName.text = name; |
| 25 | 212 | | ((ISceneCardView)this).searchInfo.SetName(name); |
| 25 | 213 | | } |
| | 214 | |
|
| | 215 | | void ISceneCardView.SetCoords(Vector2Int coords) |
| | 216 | | { |
| 25 | 217 | | string coordStr = $"{coords.x},{coords.y}"; |
| 25 | 218 | | coordsText.text = coordStr; |
| 25 | 219 | | ((ISceneCardView)this).searchInfo.SetCoords(coordStr); |
| 25 | 220 | | } |
| | 221 | |
|
| | 222 | | void ISceneCardView.SetSize(Vector2Int size) |
| | 223 | | { |
| 25 | 224 | | sizeText.text = $"{size.x},{size.y}m"; |
| 25 | 225 | | ((ISceneCardView)this).searchInfo.SetSize(size.x * size.y); |
| 25 | 226 | | } |
| | 227 | |
|
| | 228 | | void ISceneCardView.SetThumbnail(string thumbnailUrl) |
| | 229 | | { |
| 25 | 230 | | if (this.thumbnailUrl == thumbnailUrl) |
| 25 | 231 | | return; |
| | 232 | |
|
| 0 | 233 | | this.thumbnailUrl = thumbnailUrl; |
| | 234 | |
|
| 0 | 235 | | isLoadingThumbnail = true; |
| 0 | 236 | | loadingAnimator.SetBool(isLoadingAnimation, isLoadingThumbnail); |
| | 237 | |
|
| 0 | 238 | | if (thumbnailPromise != null) |
| | 239 | | { |
| 0 | 240 | | AssetPromiseKeeper_Texture.i.Forget(thumbnailPromise); |
| 0 | 241 | | thumbnailPromise = null; |
| | 242 | | } |
| | 243 | |
|
| | 244 | |
|
| 0 | 245 | | if (string.IsNullOrEmpty(thumbnailUrl)) |
| | 246 | | { |
| 0 | 247 | | ((ISceneCardView)this).SetThumbnail((Texture2D) null); |
| 0 | 248 | | return; |
| | 249 | | } |
| | 250 | |
|
| 0 | 251 | | thumbnailPromise = new AssetPromise_Texture(thumbnailUrl); |
| 0 | 252 | | thumbnailPromise.OnSuccessEvent += texture => ((ISceneCardView)this).SetThumbnail(texture.texture); |
| 0 | 253 | | thumbnailPromise.OnFailEvent += (texture, error) => ((ISceneCardView)this).SetThumbnail((Texture2D) null); |
| | 254 | |
|
| 0 | 255 | | AssetPromiseKeeper_Texture.i.Keep(thumbnailPromise); |
| 0 | 256 | | } |
| | 257 | |
|
| | 258 | | void ISceneCardView.SetThumbnail(Texture2D thumbnailTexture) |
| | 259 | | { |
| 0 | 260 | | thumbnail.texture = thumbnailTexture ?? defaultThumbnail; |
| 0 | 261 | | isLoadingThumbnail = false; |
| 0 | 262 | | loadingAnimator.SetBool(isLoadingAnimation, isLoadingThumbnail); |
| 0 | 263 | | } |
| | 264 | |
|
| | 265 | | void ISceneCardView.SetDeployed(bool deployed) |
| | 266 | | { |
| 25 | 267 | | coordsContainer.SetActive(deployed); |
| 25 | 268 | | sizeContainer.SetActive(!deployed); |
| 25 | 269 | | jumpInButton.gameObject.SetActive(deployed); |
| 25 | 270 | | } |
| | 271 | |
|
| | 272 | | void ISceneCardView.SetUserRole(bool isOwner, bool isOperator, bool isContributor) |
| | 273 | | { |
| 25 | 274 | | roleOwnerGO.SetActive(false); |
| 25 | 275 | | roleOperatorGO.SetActive(false); |
| 25 | 276 | | roleContributorGO.SetActive(false); |
| 25 | 277 | | ((ISceneCardView)this).searchInfo.SetRole(isOwner); |
| | 278 | |
|
| 25 | 279 | | if (isOwner) |
| | 280 | | { |
| 1 | 281 | | roleOwnerGO.SetActive(true); |
| 1 | 282 | | } |
| 24 | 283 | | else if (isOperator) |
| | 284 | | { |
| 0 | 285 | | roleOperatorGO.SetActive(true); |
| 0 | 286 | | } |
| 24 | 287 | | else if (isContributor) |
| | 288 | | { |
| 3 | 289 | | roleContributorGO.SetActive(true); |
| | 290 | | } |
| 24 | 291 | | } |
| | 292 | |
|
| 44 | 293 | | void ISceneCardView.SetActive(bool active) { gameObject.SetActive(active); } |
| | 294 | |
|
| 20 | 295 | | void ISceneCardView.SetSiblingIndex(int index) { transform.SetSiblingIndex(index); } |
| 4 | 296 | | void ISceneCardView.SetToDefaultParent() { transform.SetParent(defaultParent); } |
| | 297 | |
|
| 4 | 298 | | void ISceneCardView.ConfigureDefaultParent(Transform parent) { defaultParent = parent; } |
| | 299 | |
|
| | 300 | | void ISceneCardView.SetEditable(bool isEditable) |
| | 301 | | { |
| 25 | 302 | | editorButton.gameObject.SetActive(isEditable); |
| 25 | 303 | | editorLockedGO.SetActive(!isEditable); |
| 25 | 304 | | } |
| | 305 | |
|
| | 306 | | public void Dispose() |
| | 307 | | { |
| 12 | 308 | | if (!isDestroyed) |
| | 309 | | { |
| 12 | 310 | | Destroy(gameObject); |
| | 311 | | } |
| 12 | 312 | | } |
| | 313 | |
|
| | 314 | | private void OnDestroy() |
| | 315 | | { |
| 18 | 316 | | AssetPromiseKeeper_Texture.i.Forget(thumbnailPromise); |
| 18 | 317 | | isDestroyed = true; |
| 18 | 318 | | } |
| | 319 | | } |