Track内容更新,增加自定义材质

This commit is contained in:
SoulliesOfficial
2025-03-12 15:50:07 -04:00
parent 900bf16330
commit f9f4a37a79
127 changed files with 3419 additions and 5731 deletions

View File

@@ -19,10 +19,11 @@ namespace Ichni.RhythmGame
public static Track GenerateElement(string elementName, Guid id, List<string> tags, bool isFirstGenerated, GameElement parentElement)
{
Track track = Instantiate(EditorManager.instance.basePrefabs.track, parentElement.transform).GetComponent<Track>();
track.Initialize(elementName, id, tags, isFirstGenerated, parentElement);
if(parentElement is ElementFolder folder) folder.trackList.Add(track);
if (parentElement is ElementFolder folder)
{
folder.trackList.Add(track);
}
return track;
}
@@ -31,7 +32,7 @@ namespace Ichni.RhythmGame
{
transformSubmodule = new TransformSubmodule(this);
timeDurationSubmodule = new TimeDurationSubmodule(this);
trackPathSubmodule = null;
trackPathSubmodule = new TrackPathSubmodule(this, TrackSpaceType.CatmullRom, TrackSamplingType.TimeDistributed, false, false);
trackTimeSubmodule = null;
trackRendererSubmodule = null;
}
@@ -86,7 +87,7 @@ namespace Ichni.RhythmGame
() =>
{
trackPathSubmodule = new TrackPathSubmodule(this, TrackSpaceType.CatmullRom,
TrackSamplingType.TimeDistributed, false);
TrackSamplingType.TimeDistributed, false, false);
inspectorMain.SetInspector(this);
});
var trackTimeMovableButton = inspector.GenerateButton(this, trackSubmodulesContainer, "Track Time Movable",
@@ -105,7 +106,7 @@ namespace Ichni.RhythmGame
var trackRendererAutoOrientButton = inspector.GenerateButton(this, trackSubmodulesContainer, "Track Renderer Auto Orient",
() =>
{
trackRendererSubmodule = new TrackRendererSubmoduleAutoOrient(this);
trackRendererSubmodule = new TrackRendererSubmoduleAutoOrient(this, false, 0);
inspectorMain.SetInspector(this);
});
@@ -113,26 +114,16 @@ namespace Ichni.RhythmGame
"Track Renderer Path Generator",
() =>
{
trackRendererSubmodule = new TrackRendererSubmodulePathGenerator(this);
trackRendererSubmodule = new TrackRendererSubmodulePathGenerator(this, false, 0);
inspectorMain.SetInspector(this);
});
var trackRendererSurfaceButton = inspector.GenerateButton(this, trackSubmodulesContainer, "Track Renderer Surface",
() =>
{
trackRendererSubmodule = new TrackRendererSubmoduleSurface(this, false, 0);
inspectorMain.SetInspector(this);
});
if (trackPathSubmodule != null)
{
trackPathButton.button.interactable = false;
}
if (trackTimeSubmodule != null)
{
trackTimeMovableButton.button.interactable = false;
trackTimeStaticButton.button.interactable = false;
}
if (trackRendererSubmodule != null)
{
trackRendererAutoOrientButton.button.interactable = false;
trackRendererPathGeneratorButton.button.interactable = false;
}
var generateContainer = inspector.GenerateContainer("Generate Elements"); //物体生成
@@ -196,6 +187,28 @@ namespace Ichni.RhythmGame
new FlexibleFloat(), new FlexibleFloat(), new FlexibleFloat());
}); //旋转
if (trackPathSubmodule != null)
{
trackPathButton.button.interactable = false;
}
else
{
pathNodeButton.button.interactable = false;
}
if (trackTimeSubmodule != null)
{
trackTimeMovableButton.button.interactable = false;
trackTimeStaticButton.button.interactable = false;
}
if (trackRendererSubmodule != null)
{
trackRendererAutoOrientButton.button.interactable = false;
trackRendererPathGeneratorButton.button.interactable = false;
}
var toolsContainerTrack = inspector.GenerateContainer("Track Tools"); //轨道(整体)快捷工具
var quickCopyButton = inspector.GenerateButton(this, toolsContainerTrack, "QuickCopy", () =>
{

View File

@@ -18,8 +18,11 @@ namespace Ichni.RhythmGame
public Track.TrackSpaceType trackSpaceType;
public Track.TrackSamplingType trackSamplingType;
public bool isClosed;
public bool isShowingDisplay;
public TrackPathSubmodule(Track track, Track.TrackSpaceType trackSpaceType, Track.TrackSamplingType trackSamplingType, bool isClosed) : base(track)
public TrackPathSubmodule(Track track, Track.TrackSpaceType trackSpaceType,
Track.TrackSamplingType trackSamplingType, bool isClosed, bool isShowingDisplay) : base(track)
{
this.path = track.AddComponent<SplineComputer>();
@@ -32,9 +35,12 @@ namespace Ichni.RhythmGame
SetUpSplineComputer(this.trackSpaceType, this.trackSamplingType);
//闭合路径在PathNode生成时执行在初始化的情况下PathNode数量为0不会执行闭合操作
this.isShowingDisplay = isShowingDisplay;
this.trackDisplay = UnityEngine.Object.Instantiate(EditorManager.instance.basePrefabs.trackDisplay, track.transform).GetComponent<SplineRenderer>();
this.trackDisplay.spline = path;
this.trackDisplay.size = 0.1f;
this.trackDisplay.gameObject.SetActive(isShowingDisplay);
}
}
@@ -93,6 +99,9 @@ namespace Ichni.RhythmGame
{
PathNode.GenerateElement("New Path Node", Guid.NewGuid(), new List<string>(), true, track, true);
});
var showDisplayToggle = inspector.GenerateToggle(this, container, "Show Display", nameof(isShowingDisplay));
showDisplayToggle.AddListenerFunction(_ => trackDisplay.gameObject.SetActive(isShowingDisplay));
}
}
@@ -103,6 +112,7 @@ namespace Ichni.RhythmGame
public Track.TrackSpaceType trackSpaceType;
public Track.TrackSamplingType trackSamplingType;
public bool isClosed;
public bool isShowingDisplay;
public TrackPathSubmodule_BM()
{
@@ -116,19 +126,20 @@ namespace Ichni.RhythmGame
this.trackSpaceType = trackPathSubmodule.trackSpaceType;
this.trackSamplingType = trackPathSubmodule.trackSamplingType;
this.isClosed = trackPathSubmodule.isClosed;
this.isShowingDisplay = trackPathSubmodule.isShowingDisplay;
}
public override void ExecuteBM()
{
attachedElement = GameElement_BM.GetElement(attachedElementGuid);
Track track = attachedElement as Track;
track.trackPathSubmodule = new TrackPathSubmodule(track, trackSpaceType, trackSamplingType, isClosed);
track.trackPathSubmodule = new TrackPathSubmodule(track, trackSpaceType, trackSamplingType, isClosed, isShowingDisplay);
}
public override void DuplicateBM(GameElement attached)
{
Track track = attached as Track;
track.trackPathSubmodule = new TrackPathSubmodule(track, trackSpaceType, trackSamplingType, isClosed);
track.trackPathSubmodule = new TrackPathSubmodule(track, trackSpaceType, trackSamplingType, isClosed, isShowingDisplay);
}
}

View File

@@ -1,22 +1,62 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Dreamteck.Splines;
using Ichni.Editor;
using Ichni.RhythmGame.Beatmap;
using Unity.VisualScripting;
using UnityEngine;
using Inspector = Ichni.Editor.Inspector;
namespace Ichni.RhythmGame
{
public class TrackRendererSubmodule : TrackSubmodule
public partial class TrackRendererSubmodule : TrackSubmodule
{
public MeshGenerator meshGenerator;
public MeshRenderer meshRenderer;
public Material renderMaterial;
public TrackRendererSubmodule(Track track) : base(track)
public string materialThemeBundleName;
public string materialName;
public bool enableEmission;
public float emissionIntensity;
public TrackRendererSubmodule(Track track, bool enableEmission, float emissionIntensity) : base(track)
{
this.track.trackRendererSubmodule = this;
this.enableEmission = enableEmission;
this.emissionIntensity = emissionIntensity;
this.materialThemeBundleName = String.Empty;
this.materialName = String.Empty;
}
public void ApplyMaterial(string materialThemeBundleName, string materialName)
{
this.materialThemeBundleName = materialThemeBundleName;
this.materialName = materialName;
Material mat = ThemeBundleManager.instance.GetObject<Material>(materialThemeBundleName, materialName);
if(mat != null)
{
renderMaterial = mat;
meshRenderer.material = renderMaterial;
}
}
public override void Refresh()
{
SetEnableEmission();
SetEmissionIntensity();
if (track.trackTimeSubmodule is TrackTimeSubmoduleMovable)
{
meshGenerator.clipFrom = 0;
meshGenerator.clipTo = 0;
}
else
{
meshGenerator.clipFrom = 0;
meshGenerator.clipTo = 1;
}
}
public override void SaveBM()
@@ -24,6 +64,18 @@ namespace Ichni.RhythmGame
throw new System.NotImplementedException();
}
}
public partial class TrackRendererSubmodule
{
protected void SetEnableEmission()
{
meshRenderer.material.SetInt("_Emission", enableEmission ? 1 : 0);
}
protected void SetEmissionIntensity()
{
meshRenderer.material.SetColor("_EmissionColor", Color.white * Mathf.Pow(2, emissionIntensity));
}
}
#region AutoOrient
@@ -31,7 +83,8 @@ namespace Ichni.RhythmGame
{
public SplineRenderer splineRenderer;
public TrackRendererSubmoduleAutoOrient(Track track, Material material = null) : base(track)
public TrackRendererSubmoduleAutoOrient(Track track, bool enableEmission, float emissionIntensity, Material material = null) :
base(track, enableEmission, emissionIntensity)
{
this.splineRenderer = track.AddComponent<SplineRenderer>();
this.meshRenderer = splineRenderer.GetComponent<MeshRenderer>();
@@ -42,32 +95,47 @@ namespace Ichni.RhythmGame
this.splineRenderer.clipTo = 1;
this.meshRenderer.material = renderMaterial;
this.splineRenderer.color = Color.white;
}
public override void Refresh()
{
if (track.trackTimeSubmodule is TrackTimeSubmoduleMovable)
{
splineRenderer.clipFrom = 0;
splineRenderer.clipTo = 0;
}
else
{
splineRenderer.clipFrom = 0;
splineRenderer.clipTo = 1;
}
this.splineRenderer.uvRotation = 90;
}
public override void SaveBM()
{
matchedBM = new Beatmap.TrackRendererSubmoduleAutoOrient_BM(attachedGameElement, this);
matchedBM = new TrackRendererSubmoduleAutoOrient_BM(attachedGameElement, this);
}
public override void SetUpInspector()
{
IHaveInspection inspector = EditorManager.instance.uiManager.inspector;
Inspector inspectorMain = EditorManager.instance.uiManager.inspector;
var container = inspector.GenerateContainer("Track Renderer Auto Orient");
var enableEmissionToggle = inspector.GenerateToggle(this, container, "Enable Emission", nameof(enableEmission));
enableEmissionToggle.AddListenerFunction(_ => SetEnableEmission());
var emissionIntensityInputField = inspector.GenerateInputField(this, container, "Emission Intensity", nameof(emissionIntensity));
emissionIntensityInputField.AddListenerFunction(_ => SetEmissionIntensity());
var themeBundleDropdown = inspector.GenerateDropdown(this, container, "Theme Bundle", ThemeBundleManager.instance.selectedThemeBundleList, nameof(materialThemeBundleName));
themeBundleDropdown.AddListenerFunction(_ => inspectorMain.SetInspector(track));
if (materialThemeBundleName != String.Empty && ThemeBundleManager.instance.TryGetThemeBundle(materialThemeBundleName, out ThemeBundle themeBundle))
{
List<string> materialNameList = themeBundle.assetList_Material.ConvertAll(x => x.name);
var objectNameDropdown = inspector.GenerateDropdown(this, container, "Material Name", materialNameList, nameof(materialName));
objectNameDropdown.AddListenerFunction(_ => inspectorMain.SetInspector(track));
}
else
{
var objectNameDropdown = inspector.GenerateDropdown(this, container, "Material Name", new List<string>(), nameof(materialName));
objectNameDropdown.dropdown.interactable = false;
}
var applyMaterialButton = inspector.GenerateButton(this, container, "Apply Material", () =>
{
ApplyMaterial(materialThemeBundleName, materialName);
});
var deleteButton = inspector.GenerateButton(this, container, "Delete",
() =>
{
@@ -83,7 +151,10 @@ namespace Ichni.RhythmGame
{
public class TrackRendererSubmoduleAutoOrient_BM : Submodule_BM
{
public string renderMaterialName;
public string materialThemeBundleName;
public string materialName;
public bool enableEmission;
public float emissionIntensity;
public TrackRendererSubmoduleAutoOrient_BM()
{
@@ -93,20 +164,31 @@ namespace Ichni.RhythmGame
public TrackRendererSubmoduleAutoOrient_BM(GameElement attachedElement,
TrackRendererSubmoduleAutoOrient trackRendererSubmodule) : base(attachedElement)
{
renderMaterialName = trackRendererSubmodule.renderMaterial.name;
materialThemeBundleName = trackRendererSubmodule.materialThemeBundleName;
materialName = trackRendererSubmodule.materialName;
enableEmission = trackRendererSubmodule.enableEmission;
emissionIntensity = trackRendererSubmodule.emissionIntensity;
}
public override void ExecuteBM()
{
attachedElement = GameElement_BM.GetElement(attachedElementGuid);
Track track = attachedElement as Track;
track.trackRendererSubmodule = new TrackRendererSubmoduleAutoOrient(track); //TODO: Implement Material
track.trackRendererSubmodule = new TrackRendererSubmoduleAutoOrient(track, enableEmission, emissionIntensity);
if (materialName.Trim() != String.Empty)
{
track.trackRendererSubmodule.ApplyMaterial(materialThemeBundleName, materialName);
}
}
public override void DuplicateBM(GameElement attached)
{
Track track = attached as Track;
track.trackRendererSubmodule = new TrackRendererSubmoduleAutoOrient(track); //TODO: Implement Material
track.trackRendererSubmodule = new TrackRendererSubmoduleAutoOrient(track, enableEmission, emissionIntensity);
if (materialName.Trim() != String.Empty)
{
track.trackRendererSubmodule.ApplyMaterial(materialThemeBundleName, materialName);
}
}
}
}
@@ -119,7 +201,8 @@ namespace Ichni.RhythmGame
{
public PathGenerator pathGenerator;
public TrackRendererSubmodulePathGenerator(Track track, Material material = null) : base(track)
public TrackRendererSubmodulePathGenerator(Track track, bool enableEmission, float emissionIntensity, Material material = null) :
base(track, enableEmission, emissionIntensity)
{
this.pathGenerator = track.AddComponent<PathGenerator>();
this.meshRenderer = pathGenerator.GetComponent<MeshRenderer>();
@@ -130,32 +213,47 @@ namespace Ichni.RhythmGame
this.pathGenerator.clipTo = 1;
this.meshRenderer.material = renderMaterial;
this.pathGenerator.color = Color.white;
}
public override void Refresh()
{
if (track.trackTimeSubmodule is TrackTimeSubmoduleMovable)
{
pathGenerator.clipFrom = 0;
pathGenerator.clipTo = 0;
}
else
{
pathGenerator.clipFrom = 0;
pathGenerator.clipTo = 1;
}
this.pathGenerator.uvRotation = 90;
}
public override void SaveBM()
{
matchedBM = new Beatmap.TrackRendererSubmodulePathGenerator_BM(attachedGameElement, this);
matchedBM = new TrackRendererSubmodulePathGenerator_BM(attachedGameElement, this);
}
public override void SetUpInspector()
{
IHaveInspection inspector = EditorManager.instance.uiManager.inspector;
Inspector inspectorMain = EditorManager.instance.uiManager.inspector;
var container = inspector.GenerateContainer("Track Renderer Path Generator");
var enableEmissionToggle = inspector.GenerateToggle(this, container, "Enable Emission", nameof(enableEmission));
enableEmissionToggle.AddListenerFunction(_ => SetEnableEmission());
var emissionIntensityInputField = inspector.GenerateInputField(this, container, "Emission Intensity", nameof(emissionIntensity));
emissionIntensityInputField.AddListenerFunction(_ => SetEmissionIntensity());
var themeBundleDropdown = inspector.GenerateDropdown(this, container, "Theme Bundle", ThemeBundleManager.instance.selectedThemeBundleList, nameof(materialThemeBundleName));
themeBundleDropdown.AddListenerFunction(_ => inspectorMain.SetInspector(track));
if (materialThemeBundleName != String.Empty && ThemeBundleManager.instance.TryGetThemeBundle(materialThemeBundleName, out ThemeBundle themeBundle))
{
List<string> materialNameList = themeBundle.assetList_Material.ConvertAll(x => x.name);
var objectNameDropdown = inspector.GenerateDropdown(this, container, "Material Name", materialNameList, nameof(materialName));
objectNameDropdown.AddListenerFunction(_ => inspectorMain.SetInspector(track));
}
else
{
var objectNameDropdown = inspector.GenerateDropdown(this, container, "Material Name", new List<string>(), nameof(materialName));
objectNameDropdown.dropdown.interactable = false;
}
var applyMaterialButton = inspector.GenerateButton(this, container, "Apply Material", () =>
{
ApplyMaterial(materialThemeBundleName, materialName);
});
var deleteButton = inspector.GenerateButton(this, container, "Delete",
() =>
{
@@ -171,7 +269,10 @@ namespace Ichni.RhythmGame
{
public class TrackRendererSubmodulePathGenerator_BM : Submodule_BM
{
public string renderMaterialName;
public string materialThemeBundleName;
public string materialName;
public bool enableEmission;
public float emissionIntensity;
public TrackRendererSubmodulePathGenerator_BM()
{
@@ -181,23 +282,151 @@ namespace Ichni.RhythmGame
public TrackRendererSubmodulePathGenerator_BM(GameElement attachedElement,
TrackRendererSubmodulePathGenerator trackRendererSubmodule) : base(attachedElement)
{
renderMaterialName = trackRendererSubmodule.renderMaterial.name;
materialThemeBundleName = trackRendererSubmodule.materialThemeBundleName;
materialName = trackRendererSubmodule.materialName;
enableEmission = trackRendererSubmodule.enableEmission;
emissionIntensity = trackRendererSubmodule.emissionIntensity;
}
public override void ExecuteBM()
{
attachedElement = GameElement_BM.GetElement(attachedElementGuid);
Track track = attachedElement as Track;
track.trackRendererSubmodule = new TrackRendererSubmodulePathGenerator(track);//TODO: Implement Material
track.trackRendererSubmodule = new TrackRendererSubmodulePathGenerator(track, enableEmission, emissionIntensity);
if (materialName.Trim() != String.Empty)
{
track.trackRendererSubmodule.ApplyMaterial(materialThemeBundleName, materialName);
}
}
public override void DuplicateBM(GameElement attached)
{
Track track = attached as Track;
track.trackRendererSubmodule = new TrackRendererSubmodulePathGenerator(track);//TODO: Implement Material
track.trackRendererSubmodule = new TrackRendererSubmodulePathGenerator(track, enableEmission, emissionIntensity);
if (materialName.Trim() != String.Empty)
{
track.trackRendererSubmodule.ApplyMaterial(materialThemeBundleName, materialName);
}
}
}
}
#endregion
#region Surface
public class TrackRendererSubmoduleSurface : TrackRendererSubmodule
{
public SurfaceGenerator surface;
public TrackRendererSubmoduleSurface(Track track, bool enableEmission, float emissionIntensity, Material material = null) :
base(track, enableEmission, emissionIntensity)
{
this.surface = track.AddComponent<SurfaceGenerator>();
this.meshRenderer = surface.GetComponent<MeshRenderer>();
this.meshGenerator = surface;
this.renderMaterial = material == null ? EditorManager.instance.basePrefabs.defaultTrackMaterial : material;
this.surface.spline = track.trackPathSubmodule.path;
this.surface.clipFrom = 0;
this.surface.clipTo = 1;
this.meshRenderer.material = renderMaterial;
this.surface.color = Color.white;
this.surface.uvRotation = 90;
}
public override void SaveBM()
{
matchedBM = new TrackRendererSubmoduleSurface_BM(attachedGameElement, this);
}
public override void SetUpInspector()
{
IHaveInspection inspector = EditorManager.instance.uiManager.inspector;
Inspector inspectorMain = EditorManager.instance.uiManager.inspector;
var container = inspector.GenerateContainer("Track Renderer Surface");
var enableEmissionToggle = inspector.GenerateToggle(this, container, "Enable Emission", nameof(enableEmission));
enableEmissionToggle.AddListenerFunction(_ => SetEnableEmission());
var emissionIntensityInputField = inspector.GenerateInputField(this, container, "Emission Intensity", nameof(emissionIntensity));
emissionIntensityInputField.AddListenerFunction(_ => SetEmissionIntensity());
var themeBundleDropdown = inspector.GenerateDropdown(this, container, "Theme Bundle", ThemeBundleManager.instance.selectedThemeBundleList, nameof(materialThemeBundleName));
themeBundleDropdown.AddListenerFunction(_ => inspectorMain.SetInspector(track));
if (materialThemeBundleName != String.Empty && ThemeBundleManager.instance.TryGetThemeBundle(materialThemeBundleName, out ThemeBundle themeBundle))
{
List<string> materialNameList = themeBundle.assetList_Material.ConvertAll(x => x.name);
var objectNameDropdown = inspector.GenerateDropdown(this, container, "Material Name", materialNameList, nameof(materialName));
objectNameDropdown.AddListenerFunction(_ => inspectorMain.SetInspector(track));
}
else
{
var objectNameDropdown = inspector.GenerateDropdown(this, container, "Material Name", new List<string>(), nameof(materialName));
objectNameDropdown.dropdown.interactable = false;
}
var applyMaterialButton = inspector.GenerateButton(this, container, "Apply Material", () =>
{
ApplyMaterial(materialThemeBundleName, materialName);
});
var deleteButton = inspector.GenerateButton(this, container, "Delete",
() =>
{
Delete();
track.trackRendererSubmodule = null;
inspectorMain.SetInspector(track);
track.Refresh();
});
}
}
namespace Beatmap
{
public class TrackRendererSubmoduleSurface_BM : Submodule_BM
{
public string materialThemeBundleName;
public string materialName;
public bool enableEmission;
public float emissionIntensity;
public TrackRendererSubmoduleSurface_BM()
{
}
public TrackRendererSubmoduleSurface_BM(GameElement attachedElement,
TrackRendererSubmoduleSurface trackRendererSubmodule) : base(attachedElement)
{
materialThemeBundleName = trackRendererSubmodule.materialThemeBundleName;
materialName = trackRendererSubmodule.materialName;
enableEmission = trackRendererSubmodule.enableEmission;
emissionIntensity = trackRendererSubmodule.emissionIntensity;
}
public override void ExecuteBM()
{
attachedElement = GameElement_BM.GetElement(attachedElementGuid);
Track track = attachedElement as Track;
track.trackRendererSubmodule = new TrackRendererSubmoduleSurface(track, enableEmission, emissionIntensity);
if (materialName.Trim() != String.Empty)
{
track.trackRendererSubmodule.ApplyMaterial(materialThemeBundleName, materialName);
}
}
public override void DuplicateBM(GameElement attached)
{
Track track = attached as Track;
track.trackRendererSubmodule = new TrackRendererSubmoduleSurface(track, enableEmission, emissionIntensity);
if (materialName.Trim() != String.Empty)
{
track.trackRendererSubmodule.ApplyMaterial(materialThemeBundleName, materialName);
}
}
}
}
#endregion
}