diff --git a/Assets/PerfectWorld/Scripts/Objet/CECMatter.cs b/Assets/PerfectWorld/Scripts/Objet/CECMatter.cs index f96cae980d..ae4f5c1308 100644 --- a/Assets/PerfectWorld/Scripts/Objet/CECMatter.cs +++ b/Assets/PerfectWorld/Scripts/Objet/CECMatter.cs @@ -6,12 +6,16 @@ using BrewMonster.Scripts; using CSNetwork.GPDataType; using ModelRenderer.Scripts.Common; using PerfectWorld.Scripts.Managers; +using TMPro; using UnityEngine; namespace PerfectWorld.Scripts { public class CECMatter : CECObject { + private static Mesh s_itemNameQuadMesh; + private static Material s_itemNameBgMaterial; + // Matter information got from server public struct INFO { @@ -118,12 +122,12 @@ namespace PerfectWorld.Scripts public static async Task Init(info_matter Info) { INFO matterInfo = new INFO(); - matterInfo.mid = Info.mid; + matterInfo.mid = Info.mid; matterInfo.tid = Info.tid & 0x0000ffff; // get the matter template from elementdataman DATA_TYPE DataType = DATA_TYPE.DT_INVALID; var matterData = ElementDataManProvider.GetElementDataMan().get_data_ptr((uint)matterInfo.tid, ID_SPACE.ID_SPACE_ESSENCE, ref DataType); - + // Determine matter type based on DataType / Determine matter type based on DataType uint dwMatterType = MATTER_UNKNOWN; if (DataType == DATA_TYPE.DT_MINE_ESSENCE) @@ -142,7 +146,7 @@ namespace PerfectWorld.Scripts { dwMatterType = MATTER_MONEY; } - + if (matterData != null) { var matterDataType = matterData.GetType(); @@ -179,8 +183,8 @@ namespace PerfectWorld.Scripts collider.size = size; } // Create text object to display item name above the cube - // CreateItemNameText(matterObject, info.tid); - + CreateItemNameText(matterObject, Info.tid); + // Add a script to handle click events // MatterCubeClickHandler clickHandler = matterObject.AddComponent(); // clickHandler.Initialize(Info.mid, this); @@ -189,7 +193,7 @@ namespace PerfectWorld.Scripts matterScript.m_iCID = Class_ID.OCID_MATTER; matterScript.SetMatterInfo(matterInfo); matterScript.m_dwMatterType = dwMatterType; // Set matter type / Set matter type - + // Set level requirement and gather distance for mines / Set level requirement and gather distance for mines if (dwMatterType == MATTER_MINE && DataType == DATA_TYPE.DT_MINE_ESSENCE) { @@ -214,11 +218,11 @@ namespace PerfectWorld.Scripts // For non-mine items, set a default pickup distance / For non-mine items, set a default pickup distance matterScript.m_fGatherDist = 3.0f; // Default pickup distance / Default pickup distance } - + matterScript.SetUpCECObject(); // This will reset m_iCID, so we set it again after / This will reset m_iCID, so we set it again after // Force set CID again after SetUpCECObject (which resets it to OCID_OBJECT) / Force set CID again after SetUpCECObject (which resets it to OCID_OBJECT) matterScript.m_iCID = Class_ID.OCID_MATTER; - + // Store reference to the cube // matterGameObjects[info.mid] = matterObject; @@ -237,10 +241,108 @@ namespace PerfectWorld.Scripts return null; } + private static void CreateItemNameText(GameObject matterObject, int tid) + { + if (matterObject == null) + return; + + // Avoid duplicating if prefab already contains it (or Init called twice). + if (matterObject.transform.Find("ItemNameText") != null) + return; + + var textObject = new GameObject("ItemNameText"); + textObject.transform.SetParent(matterObject.transform, false); + textObject.transform.localPosition = new Vector3(0f, 0.6f, 0f); + + var textMesh = textObject.AddComponent(); + + string itemName = null; + if (EC_IvtrItemUtils.Instance != null) + itemName = EC_IvtrItemUtils.Instance.ResolveItemName(tid); + + if (string.IsNullOrEmpty(itemName)) + itemName = $"Item {tid}"; + + textMesh.text = itemName; + textMesh.fontSize = 3f; + textMesh.color = Color.white; + textMesh.alignment = TextAlignmentOptions.Center; + textMesh.textWrappingMode = TextWrappingModes.NoWrap; + textMesh.overflowMode = TextOverflowModes.Overflow; + + textObject.AddComponent(); + + var background = new GameObject("TextBackground"); + background.transform.SetParent(textObject.transform, false); + background.transform.localPosition = Vector3.zero; + background.transform.localScale = new Vector3(2f, 0.8f, 0.1f); + + var bgRenderer = background.AddComponent(); + var bgFilter = background.AddComponent(); + + bgFilter.sharedMesh = GetOrCreateItemNameQuadMesh(); + bgRenderer.sharedMaterial = GetOrCreateItemNameBgMaterial(); + } + + private static Mesh GetOrCreateItemNameQuadMesh() + { + if (s_itemNameQuadMesh != null) + return s_itemNameQuadMesh; + + var quadMesh = new Mesh { name = "CECMatter_ItemNameQuad" }; + quadMesh.vertices = new[] + { + new Vector3(-0.5f, -0.5f, 0), + new Vector3(0.5f, -0.5f, 0), + new Vector3(0.5f, 0.5f, 0), + new Vector3(-0.5f, 0.5f, 0) + }; + quadMesh.triangles = new[] { 0, 1, 2, 0, 2, 3 }; + quadMesh.uv = new[] + { + new Vector2(0, 0), + new Vector2(1, 0), + new Vector2(1, 1), + new Vector2(0, 1) + }; + quadMesh.RecalculateNormals(); + quadMesh.RecalculateBounds(); + + s_itemNameQuadMesh = quadMesh; + return s_itemNameQuadMesh; + } + + private static Material GetOrCreateItemNameBgMaterial() + { + if (s_itemNameBgMaterial != null) + return s_itemNameBgMaterial; + + var shader = Shader.Find("Unlit/Color"); + if (shader == null) + shader = Shader.Find("Sprites/Default"); + if (shader == null) + shader = Shader.Find("Standard"); + + if (shader == null) + return null; + + var mat = new Material(shader) { name = "CECMatter_ItemNameBg" }; + mat.color = new Color(0f, 0f, 0f, 0.7f); + + // Best-effort: make it transparent if the shader supports it. + if (mat.HasProperty("_Mode")) + mat.SetFloat("_Mode", 3f); + if (mat.HasProperty("_Surface")) + mat.SetFloat("_Surface", 1f); + + s_itemNameBgMaterial = mat; + return s_itemNameBgMaterial; + } + private new void Update() { base.Update(); - + // Recovery: after Unity domain reload, manager dictionaries reset but scene objects persist. // Keep trying until we successfully register. if (!m_registeredToManMatter) @@ -269,17 +371,17 @@ namespace PerfectWorld.Scripts // return; // // Ray ray = mainCamera.ScreenPointToRay(screenPosition); - // + // // RaycastHit[] hits = Physics.RaycastAll(ray); - // + // // foreach (RaycastHit hit in hits) // { - // if (hit.collider.gameObject == this.gameObject || + // if (hit.collider.gameObject == this.gameObject || // hit.collider.transform.IsChildOf(this.transform)) // { // Debug.Log($"CECMatter::RaycastHit():: mid: {m_MatterInfo.mid}"); // UnityGameSession.RequestPickupItem(m_MatterInfo.mid, m_MatterInfo.tid); - // break; + // break; // } // } // } @@ -290,4 +392,4 @@ namespace PerfectWorld.Scripts return m_MatterInfo.mid; } } -} \ No newline at end of file +}