using System; using System.Collections.Generic; using Ichni.RhythmGame.Beatmap; using UnityEngine; namespace Ichni.RhythmGame.ThemeBundles.Basic { /// /// 自定义 2D 形状环境物体,支持从 AssetBundle 动态加载 Sprite, /// 并通过 ColorSubmodule 同步颜色。接入了 DirtyMark 集中刷新机制。 /// public class Custom2DShape : EnvironmentObject { #region [暴露属性字段] Exposed Fields public string spriteName = "None"; public SpriteRenderer spriteRenderer; #endregion #region [生命周期与工厂] Lifecycle & Factory public static Custom2DShape GenerateElement(string elementName, Guid id, List tags, bool isFirstGenerated, string themeBundleName, string objectName, GameElement parentElement, bool isStatic, string spriteName) { // 通过 EnvironmentObject.GenerateElement 创建 GameObject 并获取组件 Custom2DShape obj = EnvironmentObject.GenerateElement(elementName, id, tags, isFirstGenerated, themeBundleName, objectName, parentElement, isStatic).GetComponent(); obj.spriteName = spriteName; return obj; } public override void FirstSetUpObject(bool isFirstGenerated) { if (spriteRenderer == null) spriteRenderer = GetComponentInChildren(); UpdateSprite(); Refresh(); } // 响应由 PropertyAnimation 触发的延迟刷新 public override void OnDirtyRefresh(Dictionary flags) { Refresh(); } #endregion #region [效果核心逻辑] Core Effect Logic /// /// 从当前 ThemeBundle 获取 Sprite 资源 /// public void UpdateSprite() { if (spriteRenderer != null && !string.IsNullOrEmpty(spriteName) && spriteName != "None") { // 通过 ThemeBundleManager 获取 Sprite Sprite sp = ThemeBundleManager.instance.GetObject(themeBundleName, spriteName); if (sp != null) { spriteRenderer.sprite = sp; } else { Debug.LogWarning($"[Custom2DShape] 无法在包 '{themeBundleName}' 中找到 Sprite: {spriteName}"); } } } public override void Refresh() { // 同步 ColorSubmodule 的颜色状态 base.Refresh(); if (spriteRenderer != null) { spriteRenderer.color = colorSubmodule.currentBaseColor; } } #endregion #region [继承接口实现] Inherited Logic overrides // 如果有特定的子物体需要刷新逻辑,可在此重载 #endregion } namespace Beatmap { [System.Serializable] public class Custom2DShape_BM : EnvironmentObject_BM { public string spriteName = "None"; public Custom2DShape_BM() { } public Custom2DShape_BM(string elementName, Guid elementGuid, List tags, GameElement_BM parentElement, string themeBundleName, string objectName, bool isStatic, string spriteName) : base(elementName, elementGuid, tags, parentElement, themeBundleName, objectName, isStatic) { this.spriteName = spriteName; } public override void ExecuteBM() { matchedElement = Custom2DShape.GenerateElement(elementName, elementGuid, tags, false, themeBundleName, objectName, GetElement(attachedElementGuid), isStatic, spriteName); } } } }