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 spriteThemeBundleName; 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 spriteThemeBundleName, string spriteName) { // 通过 EnvironmentObject.GenerateElement 创建 GameObject 并获取组件 Custom2DShape obj = EnvironmentObject.GenerateElement(elementName, id, tags, isFirstGenerated, themeBundleName, objectName, parentElement, isStatic).GetComponent(); obj.spriteThemeBundleName = spriteThemeBundleName; obj.spriteName = spriteName; return obj; } public override void AfterInitialize() { 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(spriteThemeBundleName, spriteName); if (sp == null) { // 如果没有找到 Sprite,则从 Texture2D 列表中获取并动态创建 Sprite Texture2D tex = ThemeBundleManager.instance.GetObject(spriteThemeBundleName, spriteName); if (tex != null) { sp = Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), new Vector2(0.5f, 0.5f)); } } if (sp != null) { spriteRenderer.sprite = sp; } else { Debug.LogWarning($"[Custom2DShape] 无法在包 '{spriteThemeBundleName}' 中找到 Sprite/Texture: {spriteName}"); } } } public override void Refresh() { // 同步 ColorSubmodule 的颜色状态 base.Refresh(); if (spriteRenderer != null) { spriteRenderer.color = colorSubmodule.currentBaseColor; if (colorSubmodule.emissionEnabled) { // 如果启用了发光,尝试设置发光颜色(需要对应的 Shader 支持) spriteRenderer.material.SetFloat("_EnableEmission", 1); spriteRenderer.material.SetColor("_EmissionColor", colorSubmodule.GetCurrentEmissionColor()); } } } #endregion #region [继承接口实现] Inherited Logic overrides // 如果有特定的子物体需要刷新逻辑,可在此重载 #endregion } namespace Beatmap { [System.Serializable] public class Custom2DShape_BM : EnvironmentObject_BM { public string spriteThemeBundleName; 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 spriteThemeBundleName, string spriteName) : base(elementName, elementGuid, tags, parentElement, themeBundleName, objectName, isStatic) { this.spriteThemeBundleName = spriteThemeBundleName; this.spriteName = spriteName; } public override void ExecuteBM() { matchedElement = Custom2DShape.GenerateElement(elementName, elementGuid, tags, false, themeBundleName, objectName, GetElement(attachedElementGuid), isStatic, spriteThemeBundleName, spriteName); } } } }