This commit is contained in:
SoulliesOfficial
2026-03-26 14:48:04 -04:00
parent 731726239a
commit 11423add8f
100 changed files with 196597 additions and 1049 deletions

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 9064f7ed277cabe4fbfa2f982dcf3ee4
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 51a0372bcf911564081d22e0d89b61f1
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,89 @@
using System;
using System.Collections.Generic;
using Ichni.Editor;
using Ichni.RhythmGame.Beatmap;
using Ichni.RhythmGame.ThemeBundles.Basic.Beatmap;
using UnityEngine;
namespace Ichni.RhythmGame.ThemeBundles.Basic
{
public partial class Custom2DShape
{
#region [] Save & Serialize
public override void SaveBM()
{
matchedBM = new Custom2DShape_BM(elementName, elementGuid, tags, parentElement.matchedBM as GameElement_BM,
themeBundleName, objectName, isStatic, spriteThemeBundleName, spriteName);
}
#endregion
#region [] Inspector Setup
public override void SetUpInspector()
{
IHaveInspection inspector = EditorManager.instance.uiManager.inspector;
Inspector inspectorMain = EditorManager.instance.uiManager.inspector;
base.SetUpInspector();
var container = inspector.GenerateContainer("Custom 2D Shape");
// 获取可选的主题包列表
themeBundleList = ThemeBundleManager.instance.loadedThemeBundleList.ConvertAll(x => x.themeBundleName);
// 排版布置
var selectionGroup = container.GenerateSubcontainer(3);
// 选择主题包列表
inspector.GenerateDropdown(this, selectionGroup, "Sprite Theme", themeBundleList, nameof(spriteThemeBundleName))
.AddListenerFunction(() => {
// 当切换主题包时,强制重置下面的物体名称列表,并刷新面板以装填新列表
spriteName = string.Empty;
inspectorMain.SetInspector(this);
});
// 如果选择了主题包,则填充其 图片资源 列表
if (!string.IsNullOrEmpty(spriteThemeBundleName) && ThemeBundleManager.instance.TryGetThemeBundle(spriteThemeBundleName, out ThemeBundle themeBundle))
{
// 注意:由于资源加载规则,一些图片可能存在于 assetList_Other (Sprite 类型),另一些在 assetList_Texture (Texture2D 类型)
spriteNameList = new List<string>();
// 收集两个列表中的所有资源名称进行合并
var spriteNames = themeBundle.assetList_Other.FindAll(x => x is Sprite).ConvertAll(x => x.name);
var textureNames = themeBundle.assetList_Texture.ConvertAll(x => x.name);
spriteNameList.AddRange(spriteNames);
spriteNameList.AddRange(textureNames);
// 去重以防万一(有些包里同名资源可能存在多态)
spriteNameList = new List<string>(new HashSet<string>(spriteNameList));
inspector.GenerateDropdown(this, selectionGroup, "Sprite Name", spriteNameList, nameof(spriteName))
.AddListenerFunction(() => inspectorMain.SetInspector(this));
}
else
{
// 未选择或选择无效时,禁用下一级列表
var spriteDropdown = inspector.GenerateDropdown(this, selectionGroup, "Sprite Name", new List<string>(), nameof(spriteName));
spriteDropdown.dropdown.interactable = false;
}
// 确认并应用按钮
var applyButton = inspector.GenerateButton(this, selectionGroup, "Apply Sprite", () =>
{
UpdateSprite();
Refresh();
});
// 如果没有选好,则不给确认
if (string.IsNullOrEmpty(spriteThemeBundleName) || string.IsNullOrEmpty(spriteName))
{
applyButton.button.interactable = false;
}
// 最后把通用的 Transform 和 颜色面板附加上去
var settings = container.GenerateSubcontainer(3);
StandardInspectionElement.GenerateForTransform(this, container);
}
#endregion
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: aed80aa0a39f68f4ab45db9b7882eb89

View File

@@ -0,0 +1,97 @@
using UnityEngine;
using System;
using System.Collections.Generic;
using Ichni.Editor;
using Ichni.RhythmGame.Beatmap;
namespace Ichni.RhythmGame.ThemeBundles.Basic
{
/// <summary>
/// 自定义 2D 形状环境物体,支持从 AssetBundle 动态加载 Sprite
/// 并通过 ColorSubmodule 同步颜色。接入了 DirtyMark 集中刷新机制。
/// </summary>
public partial class Custom2DShape : EnvironmentObject
{
#region [] Exposed Fields
public List<string> themeBundleList = new List<string>();
public List<string> spriteNameList = new List<string>();
public string spriteThemeBundleName;
public string spriteName = "None";
public SpriteRenderer spriteRenderer;
#endregion
#region [] Lifecycle & Factory
public static Custom2DShape GenerateElement(string elementName, Guid id, List<string> 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<Custom2DShape>();
obj.spriteThemeBundleName = spriteThemeBundleName;
obj.spriteName = spriteName;
return obj;
}
public override void FirstSetUpObject(bool isFirstGenerated)
{
spriteRenderer ??= GetComponentInChildren<SpriteRenderer>();
}
public override void AfterInitialize()
{
UpdateSprite();
Refresh();
}
// 响应由 PropertyAnimation 触发的延迟刷新
public override void OnDirtyRefresh(Dictionary<string, bool> flags)
{
Refresh();
}
#endregion
#region [] Core Effect Logic
/// <summary>
/// 从当前 ThemeBundle 获取 Sprite 资源
/// </summary>
public void UpdateSprite()
{
if (spriteRenderer != null && !string.IsNullOrEmpty(spriteName) && spriteName != "None")
{
// 优先尝试直接获取 Sprite 资源(兼容老版或特殊包)
Sprite sp = ThemeBundleManager.instance.GetObject<Sprite>(spriteThemeBundleName, spriteName);
if (sp == null)
{
// 如果没有找到 Sprite则从 Texture2D 列表中获取并动态创建 Sprite
Texture2D tex = ThemeBundleManager.instance.GetObject<Texture2D>(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;
}
}
#endregion
#region [] Inherited Logic overrides
// 如果有特定的子物体需要刷新逻辑,可在此重载
#endregion
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 1950337aa8bc8c04f9e99db80a4a9aac

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: a189c011db566c745993601ee16e08cb
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using Ichni.RhythmGame.Beatmap;
namespace Ichni.RhythmGame.ThemeBundles.Basic.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<string> 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);
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 6b853ccb87309754c8965b43c38db8a8