From 2e0d16db491d3321a199926e9061ac4ca12f2ac2 Mon Sep 17 00:00:00 2001 From: ninemine <1371605831@qq.com> Date: Mon, 24 Nov 2025 18:02:57 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8E=A8=E8=BF=9B=E5=90=8C=E5=8C=96RScript?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Assets/Convention | 2 +- Assets/Scripts/Framework/CameraObject.cs | 75 +- Assets/Scripts/Framework/DDT.cs | 31 - .../Framework/GameContent/GameController.cs | 5 +- Assets/Scripts/Framework/RootObject.cs | 29 +- Assets/Scripts/Framework/ScriptableObject.cs | 750 +++++------------- Assets/Scripts/Framework/SubWorld.cs | 35 +- Assets/Scripts/Framework/Updatement.cs | 35 +- Assets/Scripts/LookAtAnchor.cs | 31 +- Assets/Scripts/MaterialUpdatement.cs | 28 +- .../Scripts/MoreSpline/BasicSplineRenderer.cs | 82 +- Assets/Scripts/MoreSpline/SplineAnchor.cs | 24 +- Assets/Scripts/MoreSpline/SplineCore.cs | 88 +- Assets/Scripts/MoreSpline/SplineNode.cs | 25 +- Assets/Scripts/TickMovement.cs | 8 +- Assets/Scripts/TickRotation.cs | 8 +- Assets/Scripts/TickScaling.cs | 8 +- 17 files changed, 400 insertions(+), 864 deletions(-) diff --git a/Assets/Convention b/Assets/Convention index bf81df9..1afdb95 160000 --- a/Assets/Convention +++ b/Assets/Convention @@ -1 +1 @@ -Subproject commit bf81df9581e34fcfc0c118f5f5aaabdcebbad46a +Subproject commit 1afdb95231ec60d04198a1c802f183372af9ced1 diff --git a/Assets/Scripts/Framework/CameraObject.cs b/Assets/Scripts/Framework/CameraObject.cs index d8dc430..4bc3b6c 100644 --- a/Assets/Scripts/Framework/CameraObject.cs +++ b/Assets/Scripts/Framework/CameraObject.cs @@ -30,11 +30,6 @@ namespace Demo.Game VirtualCamera = GetComponent(); } - public override IEnumerator LoadScript(string script) - { - yield return base.LoadScript(script); - } - public override IEnumerator UnloadScript() { yield return base.UnloadScript(); @@ -44,89 +39,73 @@ namespace Demo.Game /// /// 设置是否为正交相机 /// - /// [Convention.RScript.Variable.Attr.Method] - public void SetOrthographic(string arg) + public void SetOrthographic(bool orthographic) { - MainCamera.orthographic = ConvertValue(arg); + MainCamera.orthographic = orthographic; } /// /// 设置相机视野角度 /// - /// [Convention.RScript.Variable.Attr.Method] - public void SetFieldOfView(string arg) + public void SetFieldOfView(float fieldOfView) { - MainCamera.fieldOfView = Parse(arg); + MainCamera.fieldOfView = fieldOfView; } /// /// 设置正交相机的尺寸 /// - /// [Convention.RScript.Variable.Attr.Method] - public void SetOrthographicSize(string arg) + public void SetOrthographicSize(float orthographicSize) { - MainCamera.orthographicSize = Parse(arg); + MainCamera.orthographicSize = orthographicSize; } /// /// 设置近裁剪面距离 /// - /// [Convention.RScript.Variable.Attr.Method] - public void SetNearClipPlane(string arg) + public void SetNearClipPlane(float nearClipPlane) { - MainCamera.nearClipPlane = Parse(arg); + MainCamera.nearClipPlane = nearClipPlane; } /// /// 设置远裁剪面距离 /// - /// [Convention.RScript.Variable.Attr.Method] - public void SetFarClipPlane(string arg) + public void SetFarClipPlane(float farClipPlane) { - MainCamera.farClipPlane = Parse(arg); + MainCamera.farClipPlane = farClipPlane; } /// /// 设置相机深度 /// - /// [Convention.RScript.Variable.Attr.Method] - public void SetDepth(string arg) + public void SetDepth(float depth) { - MainCamera.depth = Parse(arg); + MainCamera.depth = depth; } /// /// 设置虚拟相机跟随目标 /// - /// 对象相对路径 [Convention.RScript.Variable.Attr.Method] - public void SetVirtualCameraFollow(string targetName) + public void SetVirtualCameraFollow(ScriptableObject target) { - var target = FindWithPath(targetName, false); - if (target != null) - { - VirtualCamera.Follow = target.transform; - } + VirtualCamera.Follow = target.transform; } /// /// 设置虚拟相机观察目标 /// - /// 对象相对路径 [Convention.RScript.Variable.Attr.Method] - public void SetVirtualCameraLookAt(string targetName) + public void SetVirtualCameraLookAt(ScriptableObject target) { - var target = FindWithPath(targetName, false); - if (target != null) - { - VirtualCamera.LookAt = target.transform; - } + VirtualCamera.LookAt = target.transform; } /// @@ -136,16 +115,12 @@ namespace Demo.Game /// Y轴偏移 /// Z轴偏移 [Convention.RScript.Variable.Attr.Method] - public void SetVirtualCameraFollowOffset(string x, string y, string z) + public void SetVirtualCameraFollowOffset(float x, float y, float z) { var body = VirtualCamera.GetCinemachineComponent(); if (body != null) { - body.m_FollowOffset = new Vector3( - Parse(x), - Parse(y), - Parse(z) - ); + body.m_FollowOffset = new Vector3(x, y, z); } } @@ -156,14 +131,14 @@ namespace Demo.Game /// Y轴阻尼 /// Z轴阻尼 [Convention.RScript.Variable.Attr.Method] - public void SetVirtualCameraFollowDamping(string x, string y, string z) + public void SetVirtualCameraFollowDamping(float x, float y, float z) { var body = VirtualCamera.GetCinemachineComponent(); if (body != null) { - body.m_XDamping = Parse(x); - body.m_YDamping = Parse(y); - body.m_ZDamping = Parse(z); + body.m_XDamping = x; + body.m_YDamping = y; + body.m_ZDamping = z; } } @@ -174,13 +149,13 @@ namespace Demo.Game /// Y轴阻尼 /// Z轴阻尼 [Convention.RScript.Variable.Attr.Method] - public void SetVirtualCameraLookAtDamping(string x, string y, string z) + public void SetVirtualCameraLookAtDamping(float x, float y, float z) { var aim = VirtualCamera.GetCinemachineComponent(); if (aim != null) { - aim.m_HorizontalDamping = Parse(x); - aim.m_VerticalDamping = Parse(y); + aim.m_HorizontalDamping = x; + aim.m_VerticalDamping = y; } } } diff --git a/Assets/Scripts/Framework/DDT.cs b/Assets/Scripts/Framework/DDT.cs index f5e40db..c4a2e52 100644 --- a/Assets/Scripts/Framework/DDT.cs +++ b/Assets/Scripts/Framework/DDT.cs @@ -6,8 +6,6 @@ namespace Demo.Game { public class DDT : ScriptableObject { - public string BindingDataJson => $"{ScriptPath}.json"; - public static DDT Make() { return new GameObject().AddComponent(); @@ -15,12 +13,6 @@ namespace Demo.Game public List Datas = new(); - [Convention.RScript.Variable.Attr.Method] - public void Add(string value) - { - Datas.Add(Parse(value)); - } - [Convention.RScript.Variable.Attr.Method] public void Add(float value) { @@ -32,28 +24,5 @@ namespace Demo.Game { Datas.Add((barCount + tickCount / (float)barSplitTimes) * OneBarTime); } - - /// - /// 从特定的json中读取数据, 并调用 - /// - [Convention.RScript.Variable.Attr.Method] - public void Load() - { - var file = new ToolFile(BindingDataJson); - if (file.Exists() == false) - { - file.MustExistsPath() - .SaveAsJson>(new()); - Datas.Clear(); - } - else - { - Datas.Clear(); - foreach (var item in file.LoadAsJson>()) - { - Add(item); - } - } - } } } diff --git a/Assets/Scripts/Framework/GameContent/GameController.cs b/Assets/Scripts/Framework/GameContent/GameController.cs index 22e9e02..e9574ac 100644 --- a/Assets/Scripts/Framework/GameContent/GameController.cs +++ b/Assets/Scripts/Framework/GameContent/GameController.cs @@ -205,10 +205,11 @@ namespace Demo.Game rootGameObject.transform.SetParent(transform); rootGameObject.ScriptName = rootObject.GetName(true); rootGameObject.audioSystem = MainAudio; - rootGameObject.EnableScript(content.RootSourceDir, rootObject.GetFullPath(), this); + rootGameObject.EnableScript(content.RootSourceDir, this); try { - yield return rootGameObject.LoadScript(rootObject.LoadAsText()); + yield return rootGameObject.ParseScript2Expr(rootObject.LoadAsText()); + yield return rootGameObject.ApplyScript(); } finally { diff --git a/Assets/Scripts/Framework/RootObject.cs b/Assets/Scripts/Framework/RootObject.cs index f6508d8..21fbefd 100644 --- a/Assets/Scripts/Framework/RootObject.cs +++ b/Assets/Scripts/Framework/RootObject.cs @@ -1,10 +1,8 @@ +using Convention; +using Convention.WindowsUI.Variant; using System; using System.Collections; using System.Collections.Generic; -using Convention; -using Convention.VFX; -using Convention.WindowsUI.Variant; -using Demo.Editor.UI; using UnityEngine; using UnityEngine.InputSystem; @@ -16,19 +14,15 @@ namespace Demo.Game [Content] public GameController RootGameController; - public override IEnumerator LoadScript(string script) + public string SourcePath; + + protected override IEnumerator DoSomethingDuringApplyScript() { - try + yield return base.DoSomethingDuringApplyScript(); + ScriptUpdate(RootGameController.SongOffset, 0.01f, TickType.Reset); + if (RootGameController.IsMain) { - yield return base.LoadScript(script); - } - finally - { - ScriptUpdate(RootGameController.SongOffset, 0.01f, TickType.Start); - if (RootGameController.IsMain) - { - Keyboard.current.onTextInput += InputCatchChar; - } + Keyboard.current.onTextInput += InputCatchChar; } } @@ -41,14 +35,15 @@ namespace Demo.Game yield return base.UnloadScript(); } - public void EnableScript(string sourcePath, string scriptPath, GameController parent) + public void EnableScript(string sourcePath, GameController parent) { AllScriptableObjectCounter = 0; if (AllScriptableObjectCounterHierarchyItem == null) { AllScriptableObjectCounterHierarchyItem = HierarchyWindow.instance.CreateRootItemEntryWithBinders(typeof(ScriptableObject))[0]; } - base.EnableScript(sourcePath, scriptPath, nameof(RootObject), null); + SourcePath = sourcePath; + base.EnableScript(null); RootGameController = parent; } diff --git a/Assets/Scripts/Framework/ScriptableObject.cs b/Assets/Scripts/Framework/ScriptableObject.cs index e8459a1..6ff5cbb 100644 --- a/Assets/Scripts/Framework/ScriptableObject.cs +++ b/Assets/Scripts/Framework/ScriptableObject.cs @@ -1,3 +1,9 @@ +using Convention; +using Convention.RScript; +using Convention.WindowsUI.Variant; +using Demo.Game; +using Flee.PublicTypes; +using Sirenix.OdinInspector; using System; using System.Collections; using System.Collections.Generic; @@ -6,35 +12,11 @@ using System.IO; using System.Linq; using System.Reflection; using System.Text.RegularExpressions; -using Convention; -using Convention.RScript; -using Convention.WindowsUI.Variant; -using Demo.Game; -using Flee.PublicTypes; -using Sirenix.OdinInspector; using Unity.Profiling; using UnityEngine; namespace Demo { - public static class ScriptUtility - { - public static void OpenScriptFile(ScriptableObject so) - { - string path = so.ScriptPath; - var ScriptEditor = so.GetRoot().RootGameController.WhichOpenScript; - try - { - System.Diagnostics.Process.Start(string.Format($"{ScriptEditor}", $"\"{path}\"")); - } - catch (Exception ex) - { - Debug.LogError($"Cannt open {path}: {string.Format($"{ScriptEditor}", $"\"{path}\"")}", so); - Debug.LogException(ex, so); - } - } - } - public interface IScriptableObject { ScriptableObject SharedInterfaceScriptObject { get; } @@ -50,191 +32,8 @@ namespace Demo public ScriptableObject SharedInterfaceScriptObject => this; } - public partial class ScriptableObject - { - // 时间点系统 - - public static Dictionary TimePointDelta = new(); - public static Dictionary TimePoints = new(); - - /// - /// 重设指定时间线 - /// - /// 时间线ID,若不存在则创建 - /// 当每次调用NextTimePoint函数时使用的单位值 - /// 初始化时间 - [Convention.RScript.Variable.Attr.Method] - public void ResetTimePoint(string id, float delta, float value) - { - TimePointDelta[id] = delta; - TimePoints[id] = value; - } - - /// - /// 推动时间线前进 - /// - /// 时间线ID - /// 前进次数,最终时间的增量为前进次数乘该时间线的单位值 - [Convention.RScript.Variable.Attr.Method] - public void NextTimePoint(string id, float times) - { - TimePoints[id] += TimePointDelta[id] * times; - } - - /// - /// 设置时间线的值 - /// - /// 时间线ID - /// 次数,时间线的值将被设置为次数乘该时间线的单位值 - [Convention.RScript.Variable.Attr.Method] - public void SetTimePoint(string id, float value) - { - TimePoints[id] = TimePointDelta[id] * value; - } - } - /// - /// 上下文系统 - /// - public partial class ScriptableObject - { - [Content] public Dictionary ScriptContextSpace = new(); - - public bool GetCompleteScriptContext(string key, out float value) - { - if (ScriptContextSpace.TryGetValue(key, out value) == false) - { - if (Parent == null) - return false; - return Parent.GetCompleteScriptContext(key, out value); - } - return true; - } - - public void GetCompleteScriptContext(ref Dictionary context) - { - var current = this; - while (current != null) - { - foreach (var key in current.ScriptContextSpace.Keys) - { - context[key] = current.ScriptContextSpace[key]; - } - current = current.Parent; - } - } - - /// - /// 设置局部上下文变量,将会传递给子物体使用 - /// - /// 字符串 - /// 浮点数 - [Convention.RScript.Variable.Attr.Method] - public void SetContext(string name, float value) - { - ScriptContextSpace[name] = value; - } - - } - - /// - /// 数值解析工具 - /// - public partial class ScriptableObject - { - private ExpressionContext ExpressionParserCreater() - { - ExpressionContext context = new(); - context.Imports.AddType(typeof(Mathf)); - Dictionary vars = new(); - GetCompleteScriptContext(ref vars); - foreach (var item in vars) - { - context.Variables[item.Key] = item.Value; - } - return context; - } - public static float OneBarTime = 1; - - /// - /// 从字符串解析为浮点数 - /// 从时间点列表中获取 - /// 或是从上下文变量中获取 - /// 或是从数据驱动对象中获取 - /// 或是通过计算表达式值获取 - /// 或是直接调用 - /// - /// - /// - [Convention.RScript.Variable.Attr.Method] - public float Parse(string value) - { - value = value.Trim(); - if(value.StartsWith("\"")&&value.EndsWith("\"")) - { - value = value[1..^1]; - } - if (TimePoints.TryGetValue(value, out var result)) - return result; - if (GetCompleteScriptContext(value, out result)) - return result; - if(value.EndsWith(']')) - { - { - Regex regex = new(@"^(.+)\[(.+)\]$"); - var match = regex.Match(value); - if (match.Success) - { - return (FindWithPath(match.Groups[1].Value) as DDT).Datas[(int)this.Parse(match.Groups[2].Value)]; - } - } - { - Regex regex = new(@"^(.+)\[\]$"); - var match = regex.Match(value); - if (match.Success) - { - return (FindWithPath(match.Groups[1].Value) as DDT).Datas.Count; - } - } - throw new ArgumentException("value is end by ']' but not match on any invlid parse"); - } - if (value.EndsWith('}')) - { - { - Regex regex = new(@"^\{\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\}$"); - var match = regex.Match(value); - if (match.Success) - { - int barSplitTimes = int.Parse(match.Groups[1].Value); - int barCount = int.Parse(match.Groups[2].Value); - int tickCount = int.Parse(match.Groups[3].Value); - return (barCount + tickCount / (float)barSplitTimes) * OneBarTime; - } - } - throw new ArgumentException("value is end by '}' but not match on any invlid parse"); - } - try - { - if (float.TryParse(value, out var _result)) - return _result; - else - return ExpressionParserCreater().CompileGeneric(value).Evaluate(); - } - catch(Exception ex) - { - throw new FormatException($"{value} is not support any Parser", ex); - } - } - - - protected T ConvertValue(string str) - { - return ConventionUtility.convert_xvalue(str); - } - } - - /// - /// 先天支持的工具函数 + /// 初始化与对象设置 /// public partial class ScriptableObject { @@ -243,6 +42,7 @@ namespace Demo EnterGameEulerAngles = Vector3.zero, EnterGameLocalScaling = Vector3.one; [Content, SerializeField] private bool IsSetObjectDisable = false; + [Content] public int UpdatePerFrame = 1; /// /// 设置坐标 @@ -288,25 +88,6 @@ namespace Demo IsSetObjectDisable = true; } - private void ResetScriptableObjectEnterGameStatus() - { - transform.localPosition = EnterGameLocalPosition; - transform.localEulerAngles = EnterGameEulerAngles; - transform.localScale = EnterGameLocalScaling; - if (IsSetObjectDisable) - { - gameObject.SetActive(false); - } - } - } - - /// - /// UpdatePerFrame相关 - /// - public partial class ScriptableObject - { - [Content] public int UpdatePerFrame = 1; - /// /// 指定多少个状态的执行一次更新,不会影响到子物体 /// 属于性能优化的高级选项 @@ -317,26 +98,144 @@ namespace Demo { UpdatePerFrame = Mathf.Max(1, frame); } + + private void ScriptableObjectDoReset() + { + transform.localPosition = EnterGameLocalPosition; + transform.localEulerAngles = EnterGameEulerAngles; + transform.localScale = EnterGameLocalScaling; + gameObject.SetActive(IsSetObjectDisable == false); + } } /// - /// EnableScript相关 + /// 跨脚本上下文变量 /// public partial class ScriptableObject { + public Dictionary ScriptableObjectContents = new(); + + public object GetContent(string key) + { + if (ScriptableObjectContents.TryGetValue(key, out var result)) + { + return result; + } + if (Parent != null) + { + return Parent.GetContent(key); + } + return null; + } + + public void SetContent(string key, object value) + { + ScriptableObjectContents[key] = value; + } + } + + /// + /// 基础信息, 父子关系与EnableScript + /// + public partial class ScriptableObject + { + public static bool IsAutoPlay = false; + public static float OneBarTime = 60; + private bool isEnableScript = false; - - public string SourcePath = ""; public string ScriptName = ""; - public string ScriptPath; - public string ScriptTypename; - // Hierarchy + public ScriptableObject Parent; + public List Childs = new(); - public PropertiesWindow.ItemEntry MyHierarchyItem; - public static PropertiesWindow.ItemEntry AllScriptableObjectCounterHierarchyItem; + /// + /// 获取根脚本对象 + /// + /// + [Convention.RScript.Variable.Attr.Method] + public RootObject GetRoot() + { + if (Parent == null) + return this as RootObject; + if (Parent is RootObject result) + return result; + else + return Parent.GetRoot(); + } - public void EnableScript(string sourcePath, string scriptPath, string scriptType, ScriptableObject parent) + + public const string RootObjectQuickPath = "project/"; + + public ScriptableObject FindWithPath(string path, bool isMustExist = true) + { + if (string.IsNullOrEmpty(path)) + { + if (isMustExist) + throw new Exception("path is null or empty"); + else + return null; + } + + // GetParent + ScriptableObject result = Parent; + if (path.Replace('\\', '/').ToLower().StartsWith(RootObjectQuickPath)) + { + result = GetRoot(); + path = path[RootObjectQuickPath.Length..]; + } + + if (Parent == null) + { + throw new InvalidOperationException($"Root is nosupport to {nameof(FindWithPath)}"); + } + + // Find + var components = path.Split('/', '\\'); + components[^1] = new ToolFile(components[^1]).GetFilename(true); + foreach (var component in components) + { + if (component == "..") + result = result.Parent; + else if (component == "." || string.IsNullOrEmpty(component)) + continue; + else + { + int index = 0; + string targetScriptObjectPath = component; + Regex regex = new(@"^(.*)\[(\d*)\]$"); + var match = regex.Match(component); + if (match.Success) + { + targetScriptObjectPath = match.Groups[1].Value; + index = int.Parse(match.Groups[2].Value); + } + var target = result.Childs.FirstOrDefault(x => + { + bool stats = x.ScriptName == targetScriptObjectPath; + if (index == 0) + return stats; + else if (stats) + index--; + return false; + }); + if (target != null) + result = target; + else + { + if (isMustExist) + throw new Exception($"{component} in {path} is not found"); + else + { + Debug.Log($"{component} in {path} is not found", this); + return null; + } + } + } + } + return result; + } + + public void EnableScript(ScriptableObject parent) { #if UNITY_EDITOR||Using_ProfilerMarker s_PreparePerfMarker = new(ScriptName); @@ -346,9 +245,6 @@ namespace Demo Debug.LogError($"ScriptableObject is currently enableScript, start coroutine {nameof(UnloadScript)} to disable", this); return; } - this.SourcePath = sourcePath; - this.ScriptPath = scriptPath; - this.ScriptTypename = scriptType; this.Parent = parent; this.name = ScriptName; @@ -363,14 +259,16 @@ namespace Demo { MyHierarchyItem = HierarchyWindow.instance.CreateRootItemEntryWithBinders(1)[0]; } - MyHierarchyItem.GetHierarchyItem().title = this.ScriptName + $"<{scriptType}>"; + MyHierarchyItem.GetHierarchyItem().title = this.ScriptName + $"<{this.GetType()}>"; MyHierarchyItem.GetHierarchyItem().target = this; MyHierarchyItem.GetHierarchyItem().ButtonGameObject.GetComponent().ScriptObjectMenu = OnHierarchyItemRightClick; - //var parentHierarchyItem = MyHierarchyItem.GetParent(); - //if (parentHierarchyItem != null) - // parentHierarchyItem.GetPropertyListItem().RefreshChilds(); } + #region Hierarchy + + public PropertiesWindow.ItemEntry MyHierarchyItem; + public static PropertiesWindow.ItemEntry AllScriptableObjectCounterHierarchyItem; + public bool EnsureEnableScript() { if (isEnableScript == false) @@ -379,6 +277,8 @@ namespace Demo } return isEnableScript; } + + #endregion } /// @@ -396,115 +296,55 @@ namespace Demo #region LoadSubScript - private static ScriptableObject LastLoadedScriptableObject; - - public IEnumerator DoLoadSubScriptAsync([In] string type, [In] string path, [Opt] Action callback) - { - // 判断类型是否合法 - if (DefaultInstantiate.GetScriptableObjectInstantiate().TryGetValue(type, out var creater) == false) - { - Debug.LogError($"{type} is not exist or {type}'s Instantiater is not valid", this); - callback?.Invoke(null); - yield break; - } - // 生成对象 - var child = creater(); - // 路径预处理 - if (path.Replace('\\', '/').ToLower().StartsWith(RootObjectQuickPath)) - path = $"{new ToolFile(GetRoot().SourcePath) | path[RootObjectQuickPath.Length..]}"; - // 获取文件 - ToolFile file; - if (File.Exists(path)) - file = new(path); - else - file = new ToolFile(SourcePath) | path; - // 找不到脚本 - if (file.Exists() == false) - { - Debug.LogError($"{file}<{path}> is not found", this); - callback?.Invoke(null); - yield break; - } - child.ScriptName = file.GetName(true); - child.transform.SetParent(this.transform); - child.transform.SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity); - child.transform.localScale = Vector3.one; - child.EnableScript(file.GetCurrentDirName(), Path.Combine(file.GetCurrentDirName(), file.GetName(false)), type, this); - - // Add Child - Childs.Add(child); - - // Load Child Script - yield return child.LoadScript(file.LoadAsText()); - - LastLoadedScriptableObject = child; - callback?.Invoke(child); - } - - public IEnumerator DoGenerateSubScriptAsync([In] string type, string name, [Opt] Action callback) - { - // 判断类型是否合法 - if (DefaultInstantiate.GetScriptableObjectInstantiate().TryGetValue(type, out var creater) == false) - { - Debug.LogError($"{type} is not exist or {type}'s Instantiater is not valid", this); - callback?.Invoke(null); - yield break; - } - // 生成对象 - var child = creater(); - child.ScriptName = name; - child.transform.SetParent(this.transform); - child.transform.SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity); - child.transform.localScale = Vector3.one; - child.EnableScript("", "", type, this); - - // Add Child - Childs.Add(child); - - // Load Child Script - yield return child.LoadScript(""); - - LastLoadedScriptableObject = child; - callback?.Invoke(child); - } - - public ScriptableObject DoGenerateSubScript([In] string type, string name, [Opt] Action callback) - { - // 判断类型是否合法 - if (DefaultInstantiate.GetScriptableObjectInstantiate().TryGetValue(type, out var creater) == false) - { - Debug.LogError($"{type} is not exist or {type}'s Instantiater is not valid", this); - callback?.Invoke(null); - return null; - } - // 生成对象 - var child = creater(); - child.ScriptName = name; - child.transform.SetParent(this.transform); - child.transform.SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity); - child.transform.localScale = Vector3.one; - child.EnableScript("", "", type, this); - - // Add Child - Childs.Add(child); - - // Load Child Script - ConventionUtility.StartCoroutine(child.LoadScript("")); - - LastLoadedScriptableObject = child; - callback?.Invoke(child); - - return child; - } - /// - /// 创建无初始化脚本且无启动的子脚本对象 + /// 创建基于子脚本的实例对象 /// /// /// /// [Convention.RScript.Variable.Attr.Method] - public ScriptableObject NewSubScriptWithoutInit([In] string type, [In]string name) + public ScriptableObject NewSubScript([In] string type, [In] string name, [In] string path) + { + // 判断类型是否合法 + if (DefaultInstantiate.GetScriptableObjectInstantiate().TryGetValue(type, out var creater) == false) + { + Debug.LogError($"{type} is not exist or {type}'s Instantiater is not valid", this); + return null; + } + // 生成对象 + var child = creater(); + // 获取文件 + var file = new ToolFile(GetRoot().SourcePath); + file = file | path; + // 找不到脚本 + if (file.Exists() == false) + { + Debug.LogError($"{file}<{path}> is not found", this); + return null; + } + child.ScriptName = name; + child.transform.SetParent(this.transform); + child.transform.SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity); + child.transform.localScale = Vector3.one; + child.EnableScript(this); + + // Add Child + Childs.Add(child); + + // Load Child Script + ConventionUtility.StartCoroutine(child.ParseScript2Expr(file.LoadAsText())); + + return child; + } + + /// + /// 创建不基于子脚本的实例对象 + /// + /// + /// + /// + [Convention.RScript.Variable.Attr.Method] + public ScriptableObject NewSubScript([In] string type, string name) { // 判断类型是否合法 if (DefaultInstantiate.GetScriptableObjectInstantiate().TryGetValue(type, out var creater) == false) @@ -518,58 +358,14 @@ namespace Demo child.transform.SetParent(this.transform); child.transform.SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity); child.transform.localScale = Vector3.one; - child.EnableScript("", "", type, this); + child.EnableScript(this); + // Add Child Childs.Add(child); + return child; } - /// - /// 将无初始化创建的脚本对象确认完全加载并设置为最后添加的脚本对象 - /// - /// - [Convention.RScript.Variable.Attr.Method] - public ScriptableObject ApplyLoad() - { - // Load Child Script - ConventionUtility.StartCoroutine(this.LoadScript("")); - - LastLoadedScriptableObject = this; - - return this; - } - - /// - /// 创建不需要脚本语句的子脚本对象 - /// - /// 指定类型 - [Convention.RScript.Variable.Attr.Method] - public ScriptableObject NewSubScript([In] string type, [In] string name) - { - return DoGenerateSubScript(type, name, null); - } - - /// - /// 创建不需要脚本语句的子脚本对象 - /// - /// 指定类型 - [Convention.RScript.Variable.Attr.Method] - public ScriptableObject NewSubScript([In] string type) - { - return NewSubScript(type, $"New {type}"); - } - - /// - /// 加载子脚本 - /// - /// 指定类型 - /// 指定脚本,可用决定路径或与当前脚本目录的相对路径 - [Convention.RScript.Variable.Attr.Method] - public IEnumerator LoadSubScript([In] string type, [In] string path) - { - return DoLoadSubScriptAsync(type, path, null); - } - /// /// 获取已加载的脚本对象 /// @@ -590,19 +386,9 @@ namespace Demo return Parent; } - /// - /// 获取上一个加载的脚本对象 - /// - /// - [Convention.RScript.Variable.Attr.Method] - public ScriptableObject GetLastLoadedScriptableObject() - { - return LastLoadedScriptableObject; - } - #endregion - private IEnumerator ParseScript2Expr(string script) + public IEnumerator ParseScript2Expr(string script) { RScriptEngine engine = new(); RScriptImportClass importClass = new() @@ -674,123 +460,26 @@ namespace Demo /// public partial class ScriptableObject : SerializedMonoBehaviour, IHierarchyItemClickEventListener { - - public static bool IsAutoPlay = false; - - public ScriptableObject Parent; - - /// - /// 获取根脚本对象 - /// - /// - [Convention.RScript.Variable.Attr.Method] - public RootObject GetRoot() + protected virtual IEnumerator DoSomethingDuringApplyScript() { - if (Parent == null) - return this as RootObject; - if (Parent is RootObject result) - return result; - else - return Parent.GetRoot(); + yield break; } - public List Childs = new(); - - - // Cache - - public const string RootObjectQuickPath = "project/"; - - public ScriptableObject FindWithPath(string path, bool isMustExist = true) - { - if (string.IsNullOrEmpty(path)) - { - if (isMustExist) - throw new Exception("path is null or empty"); - else - return null; - } - - // GetParent - ScriptableObject result = Parent; - if (path.Replace('\\','/').ToLower().StartsWith(RootObjectQuickPath)) - { - result = GetRoot(); - path = path[RootObjectQuickPath.Length..]; - } - - if (Parent == null) - { - throw new InvalidOperationException($"Root is nosupport to {nameof(FindWithPath)}"); - } - - // Find - var components = path.Split('/', '\\'); - components[^1] = new ToolFile(components[^1]).GetFilename(true); - foreach (var component in components) - { - if (component == "..") - result = result.Parent; - else if (component == "." || string.IsNullOrEmpty(component)) - continue; - else - { - int index = 0; - string targetScriptObjectPath = component; - Regex regex = new(@"^(.*)\[(\d*)\]$"); - var match = regex.Match(component); - if (match.Success) - { - targetScriptObjectPath = match.Groups[1].Value; - index = int.Parse(match.Groups[2].Value); - } - var target = result.Childs.FirstOrDefault(x => - { - bool stats = x.ScriptName == targetScriptObjectPath; - if (index == 0) - return stats; - else if (stats) - index--; - return false; - }); - if (target != null) - result = target; - else - { - if (isMustExist) - throw new Exception($"{component} in {path} is not found"); - else - { - Debug.Log($"{component} in {path} is not found", this); - return null; - } - } - } - } - return result; - } - - - public virtual IEnumerator LoadScript(string script) + public IEnumerator ApplyScript() { if (EnsureEnableScript() == false) { yield break; } + yield return DoSomethingDuringApplyScript(); // 增数 { AllScriptableObjectCounter++; AllScriptableObjectCounterHierarchyItem.GetHierarchyItem().text = $"ScriptableObjectCount: {AllScriptableObjectCounter}"; } - yield return ParseScript2Expr(script); IsEnableUpdate = true; } - private void Reset() - { - StartCoroutine(UnloadScript()); - } - public virtual IEnumerator UnloadScript() { if (EnsureEnableScript()) @@ -827,7 +516,7 @@ namespace Demo public virtual void ResetEnterGameStatus() { - ResetScriptableObjectEnterGameStatus(); + ScriptableObjectDoReset(); } public virtual void OnHierarchyItemRightClick(RectTransform item) @@ -956,14 +645,18 @@ namespace Demo private static UnityEngine.UI.Image CacheLastFocusImage; private static Color CacheLastFocusImageOriginColor = new(1, 1, 1, 0.01f); - private static Color FocusImageColor = new Color(1f, 47f / 51f, 0.0156862754f, 0.1f); + private static Color FocusImageColor = new(1f, 47f / 51f, 0.0156862754f, 0.1f); - public override IEnumerator LoadScript(string script) + protected override IEnumerator DoSomethingDuringApplyScript() { - MyTimelineEntry = TimelineWindow.CreateRootItemEntries(1)[0]; - MyTimelineItem = MyTimelineEntry.ref_value.GetComponent(); - yield return base.LoadScript(script); + yield return base.DoSomethingDuringApplyScript(); + if(MyTimelineEntry==null) + { + MyTimelineEntry = TimelineWindow.CreateRootItemEntries(1)[0]; + MyTimelineItem = MyTimelineEntry.ref_value.GetComponent(); + } MyTimelineItem.title = ScriptName; + MyTimelineItem.RawButton.onClick.RemoveAllListeners(); MyTimelineItem.AddListener(() => { HierarchyWindow.instance.MakeFocusOn(MyHierarchyItem.GetHierarchyItem()); @@ -979,28 +672,20 @@ namespace Demo } } + public override IEnumerator UnloadScript() + { + yield return base.UnloadScript(); + MyTimelineItem.RawButton.onClick.RemoveAllListeners(); + MyTimelineEntry.Release(); + MyTimelineEntry = null; + MyTimelineItem = null; + } + public override void OnHierarchyItemClick(HierarchyItem item) { } - //protected virtual void ShowTimelineItemWithChilds() - //{ - // ScriptableObject parent = this; - // List childs = this.Childs; - // if (parent is TimelineScriptObject ptso) - // { - // ptso.IsTimelineItemShow = true; - // } - // foreach (var child in childs) - // { - // if (child is TimelineScriptObject tso) - // { - // tso.IsTimelineItemShow = true; - // } - // } - //} - protected override void UpdateTicks(float currentTime, float deltaTime, TickType tickType) { base.UpdateTicks(currentTime, deltaTime, tickType); @@ -1025,14 +710,5 @@ namespace Demo var color = new Vector3(Foo(a1), Foo(a2), Foo(a3)).normalized; return new(color.x, color.y, color.z); } - - public override IEnumerator UnloadScript() - { - yield return base.UnloadScript(); - MyTimelineItem.RawButton.onClick.RemoveAllListeners(); - MyTimelineEntry.Release(); - MyTimelineEntry = null; - MyTimelineItem = null; - } } } diff --git a/Assets/Scripts/Framework/SubWorld.cs b/Assets/Scripts/Framework/SubWorld.cs index ad93e2e..b3a92be 100644 --- a/Assets/Scripts/Framework/SubWorld.cs +++ b/Assets/Scripts/Framework/SubWorld.cs @@ -17,46 +17,17 @@ namespace Demo.Game [Content, SerializeField] private string project; [Content, SerializeField] private GameController SubWorldGameController; - public override IEnumerator LoadScript(string script) + protected override IEnumerator DoSomethingDuringApplyScript() { - yield return base.LoadScript(script); - /* - // Load - var content = GameContent.instance; - // Always - content.IsCreateNewProject = false; - // Push Content - var oldContentRootSourceDir = content.RootSourceDir; - var oldSetupSongDuration = content.SetupSongDuration; - var oldSetSongCurrentTime = content.SetSongCurrentTime; - // Setting New - content.RootSourceDir = Path.Combine(PlatformIndicator.StreamingAssetsPath, project) + "/"; - content.SetupSongDuration = (x, y) => { }; - content.SetSongCurrentTime = x => { }; + yield return base.DoSomethingDuringApplyScript(); var ir = SceneManager.LoadSceneAsync(Editor.EditorController.SceneName, LoadSceneMode.Additive); ir.completed += x => { SubWorldGameController = (from controller in FindObjectsOfType() where controller.RootSourcePath == project select controller).First(); + ConventionUtility.StartCoroutine(SubWorldGameController.GameInitBySubWorld(GetRoot().InputCatch)); }; - yield return ir; - // Pull Content - content.RootSourceDir = oldContentRootSourceDir; - content.SetupSongDuration = oldSetupSongDuration; - content.SetSongCurrentTime = oldSetSongCurrentTime; - */ - var ir = SceneManager.LoadSceneAsync(Editor.EditorController.SceneName, LoadSceneMode.Additive); - IEnumerator after = null; - ir.completed += x => - { - SubWorldGameController = (from controller in FindObjectsOfType() - where controller.RootSourcePath == project - select controller).First(); - after = SubWorldGameController.GameInitBySubWorld(GetRoot().InputCatch); - }; - yield return ir; - yield return after; } public override IEnumerator UnloadScript() diff --git a/Assets/Scripts/Framework/Updatement.cs b/Assets/Scripts/Framework/Updatement.cs index 5e2add9..aa0af56 100644 --- a/Assets/Scripts/Framework/Updatement.cs +++ b/Assets/Scripts/Framework/Updatement.cs @@ -20,7 +20,7 @@ namespace Demo.Game } public int Content = 0; - public List Entries = new(); + public readonly List Entries = new(); protected abstract void UpdateData(DataType data); protected abstract DataType Lerp(DataType begin, DataType end, float t); @@ -40,26 +40,15 @@ namespace Demo.Game }); } - /// - /// 添加数据 - /// - /// - /// - /// - public void ManualAddEntry(string time, DataType position, MathExtension.EaseCurveType curveType) - { - ManualAddEntry(time, position, curveType); - } - private void UpdateEntry(int start, float percent) { UpdatementEntry head = Entries[start], tail = Entries[Mathf.Min(start + 1, Entries.Count - 1)]; UpdateData(Lerp(head.Position, tail.Position, MathExtension.Evaluate(Mathf.Clamp01(percent), head.easeCurveType))); } - public override IEnumerator LoadScript(string script) + protected override IEnumerator DoSomethingDuringApplyScript() { - yield return base.LoadScript(script); + yield return base.DoSomethingDuringApplyScript(); Entries.Sort((x, y) => x.TimePoint.CompareTo(y.TimePoint)); if (UpdateTarget == null) { @@ -76,9 +65,10 @@ namespace Demo.Game public override IEnumerator UnloadScript() { Content = 0; - Entries = new(); + Entries.Clear(); yield return base.UnloadScript(); } + protected override void UpdateTicks(float currentTime, float deltaTime, TickType tickType) { base.UpdateTicks(currentTime, deltaTime, tickType); @@ -140,16 +130,12 @@ namespace Demo.Game /// /// 设置更新对象 /// - /// 脚本的相对路径 [Convention.RScript.Variable.Attr.Method] - public void SetUpdateTarget(string path) + public void SetUpdateTarget(ScriptableObject target) { - var temp = FindWithPath(path); - if (temp != null) - UpdateTarget = temp.gameObject; - else - Debug.LogWarning($"{path}' is not found", this); + UpdateTarget = target.gameObject; } + /// /// /// @@ -165,7 +151,6 @@ namespace Demo.Game public interface ILocalUpdatement: IScriptableObject { - int Content { get; set; } public List> Entries { get; set; } void UpdateData(DataType data); @@ -182,11 +167,11 @@ namespace Demo.Game public MathExtension.EaseCurveType easeCurveType = MathExtension.EaseCurveType.Linear; } - public static void AddEntry(this ILocalUpdatement self, string time, DataType position, MathExtension.EaseCurveType curveType) + public static void AddEntry(this ILocalUpdatement self, float time, DataType position, MathExtension.EaseCurveType curveType) { self.Entries.Add(new() { - TimePoint = self.SharedInterfaceScriptObject.Parse(time), + TimePoint = time, Position = position, easeCurveType = curveType }); diff --git a/Assets/Scripts/LookAtAnchor.cs b/Assets/Scripts/LookAtAnchor.cs index 1b701f9..2c11c1d 100644 --- a/Assets/Scripts/LookAtAnchor.cs +++ b/Assets/Scripts/LookAtAnchor.cs @@ -5,55 +5,40 @@ using UnityEngine; namespace Demo.Game { - public class LookAtAnchor : Updatement + public class LookAtAnchor : Updatement { public static LookAtAnchor Make() { return new GameObject().AddComponent(); } - protected override string Lerp(string begin, string end, float t) + protected override ScriptableObject Lerp(ScriptableObject begin, ScriptableObject end, float t) { return begin; } - [Content, SerializeField] private string Cache; [Content] public ScriptableObject LookAtObject; [Content] public bool IsEnableUpdateEveryTick = false; - protected override void UpdateData(string data) + protected override void UpdateData(ScriptableObject data) { - if (Cache != data) + if (data != LookAtObject) { - LookAtObject = FindWithPath(data, false); - Cache = data; - Foo(); + LookAtObject = data; + transform.LookAt(LookAtObject.transform); } - if (IsEnableUpdateEveryTick) - { - Foo(); - } - - void Foo() + else if (IsEnableUpdateEveryTick) { if (LookAtObject != null) transform.LookAt(LookAtObject.transform); } } - public override IEnumerator UnloadScript() - { - Cache = null; - yield return base.UnloadScript(); - } - /// /// 在指定时刻切换面向的物体,并尝试一次更新 /// - /// - /// 对象相对路径,不存在时将解除锁定 [Convention.RScript.Variable.Attr.Method] - public void Add(string time, string target) + public void Add(float time, ScriptableObject target) { ManualAddEntry(time, target, default); } diff --git a/Assets/Scripts/MaterialUpdatement.cs b/Assets/Scripts/MaterialUpdatement.cs index 901a6ff..e7d2c29 100644 --- a/Assets/Scripts/MaterialUpdatement.cs +++ b/Assets/Scripts/MaterialUpdatement.cs @@ -5,30 +5,30 @@ using UnityEngine; namespace Demo.Game { - public class MaterialUpdatement : Updatement, IAssetBundleLoader + public class MaterialUpdatement : Updatement, IAssetBundleLoader { public static MaterialUpdatement Make() { return new GameObject().AddComponent(); } - public string MaterialAssetBundlePath; - public AssetBundle MaterialAssetBundle; + public string MaterialAssetBundlePath = null; + public AssetBundle MaterialAssetBundle = null; - protected override string Lerp(string begin, string end, float t) + protected override Material Lerp(Material begin, Material end, float t) { return begin; } - [Content, SerializeField] private string Cache; + [Content, SerializeField] private Material Cache; - protected override void UpdateData(string data) + protected override void UpdateData(Material data) { if (string.IsNullOrEmpty(MaterialAssetBundlePath)) return; if (Cache != data && Parent.TryGetComponent(out var meshRenderer)) { - meshRenderer.material = MaterialAssetBundle.LoadAsset(data); + meshRenderer.material = data; Cache = data; } } @@ -38,7 +38,7 @@ namespace Demo.Game Cache = null; if (string.IsNullOrEmpty(MaterialAssetBundlePath) == false) yield return this.UnloadAssetBundle(MaterialAssetBundlePath); - MaterialAssetBundlePath = ""; + MaterialAssetBundlePath = null; yield return base.UnloadScript(); } @@ -59,12 +59,16 @@ namespace Demo.Game /// /// 在指定时刻切换父物体上的MeshRenderer.material /// - /// - /// [Convention.RScript.Variable.Attr.Method] - public void Add(string time, string material) + public IEnumerator Add(float time, string material) { - ManualAddEntry(time, material, default); + var ir = MaterialAssetBundle.LoadAssetAsync(material); + ir.completed += x => + { + var mat = ir.asset as Material; + ManualAddEntry(time, mat, default); + }; + yield return ir; } } } diff --git a/Assets/Scripts/MoreSpline/BasicSplineRenderer.cs b/Assets/Scripts/MoreSpline/BasicSplineRenderer.cs index 6d164fa..0c53acd 100644 --- a/Assets/Scripts/MoreSpline/BasicSplineRenderer.cs +++ b/Assets/Scripts/MoreSpline/BasicSplineRenderer.cs @@ -22,12 +22,37 @@ namespace Demo.Game public abstract class BasicSplineRenderer : Updatement, IAssetBundleLoader, IDependOnSplineCore { [Content] public SplineCore MySplineCore { get; set; } - [Content] public MeshRenderer MyMeshRenderer; + [Content] private MeshFilter m_MeshFilter; + [Content] private MeshRenderer m_MyMeshRenderer; [Header("LineRenderer.Material")] [Content] public string LinesAssetBundlePath; [Content] public AssetBundle LinesAssetBundle; - [Content] public string LineMaterial; - [Content] public Material MyLineMaterial; + [Content] public Material LineDefaultMaterial; + + public override void ResetEnterGameStatus() + { + base.ResetEnterGameStatus(); + MyMeshRenderer.material = LineDefaultMaterial; + } + + public MeshFilter MyMeshFilter + { + get + { + if (m_MeshFilter == null) + m_MeshFilter = this.GetOrAddComponent(); + return m_MeshFilter; + } + } + public MeshRenderer MyMeshRenderer + { + get + { + if (m_MyMeshRenderer == null) + m_MyMeshRenderer = this.GetOrAddComponent(); + return m_MyMeshRenderer; + } + } public abstract Vector3 EvaluateClipFromPosition(float time); @@ -37,26 +62,6 @@ namespace Demo.Game public abstract SplineSample EvaluateClipTo(float time); - public override IEnumerator LoadScript(string script) - { - yield return base.LoadScript(script); - // Bind and Init Spline - var splineGameObject = MySplineCore.gameObject; - this.GetOrAddComponent(); - MyMeshRenderer = this.GetOrAddComponent(); - MyMeshRenderer.enabled = true; - if (string.IsNullOrEmpty(LinesAssetBundlePath) == false) - { - var ir = LinesAssetBundle.LoadAssetAsync(LineMaterial); - ir.completed += x => - { - MyLineMaterial = ir.asset as Material; - }; - yield return ir; - } - MyMeshRenderer.material = MyLineMaterial; - } - public override IEnumerator UnloadScript() { if (string.IsNullOrEmpty(LinesAssetBundlePath) == false) @@ -73,15 +78,15 @@ namespace Demo.Game /// /// 可取值为30种缓动曲线 [Convention.RScript.Variable.Attr.Method] - public void Add(string time, float from, float to, string curveType) + public void Add(float time, float from, float to, string curveType) { ManualAddEntry(time, new(from, to), Enum.Parse(curveType)); } [Convention.RScript.Variable.Attr.Method] - public IEnumerator LoadSpline(string path) + public void LoadSpline(string path) { - yield return this.LoadSplineTool(path); + this.LoadSplineTool(path); } @@ -97,14 +102,15 @@ namespace Demo.Game /// /// [Convention.RScript.Variable.Attr.Method] - public IEnumerator LoadMaterial(string ab, string material) + public void LoadMaterial(string ab, string material) { - yield return this.LoadAssetBundle(ab, x => - { - LinesAssetBundlePath = ab; - LinesAssetBundle = x; - LineMaterial = material; - }); + MyMeshRenderer.enabled = true; + LinesAssetBundlePath = ab; + this.LoadAssetBundle(ab, x => + { + LinesAssetBundle = x; + LineDefaultMaterial = LinesAssetBundle.LoadAsset(material); + }); } protected override SplineClipDuration Lerp(SplineClipDuration begin, SplineClipDuration end, float t) @@ -117,11 +123,9 @@ namespace Demo.Game { [Content] public TMeshGenerator MyMeshGenerator; - public override IEnumerator LoadScript(string script) + protected override IEnumerator DoSomethingDuringApplyScript() { - yield return base.LoadScript(script); - // Setup Mesh Generater - MyMeshRenderer.material = MyLineMaterial; + yield return base.DoSomethingDuringApplyScript(); MyMeshGenerator = this.GetOrAddComponent(); MyMeshGenerator.spline = MySplineCore.MySplineComputer; SetupMeshGenerator(MyMeshGenerator); @@ -142,9 +146,9 @@ namespace Demo.Game /// /// Clip, UniformClip, Clamp, UniformClamp [Convention.RScript.Variable.Attr.Method] - public void SetUVMode(string mode) + public void SetUVMode(MeshGenerator.UVMode mode) { - MyUVMode = Enum.Parse(mode); + MyUVMode = mode; } #endregion diff --git a/Assets/Scripts/MoreSpline/SplineAnchor.cs b/Assets/Scripts/MoreSpline/SplineAnchor.cs index cd9709b..088ba14 100644 --- a/Assets/Scripts/MoreSpline/SplineAnchor.cs +++ b/Assets/Scripts/MoreSpline/SplineAnchor.cs @@ -27,37 +27,37 @@ namespace Demo.Game /// /// 对象路径, 不存在时则立刻加载 [Convention.RScript.Variable.Attr.Method] - public IEnumerator LoadSpline(string path) + public void LoadSpline(string path) { - yield return this.LoadSplineTool(path); + this.LoadSplineTool(path); } /// /// 必须先执行LoadSpline加载样条线 /// - /// 百分比所在位置,取值范围是[0,1] + /// 百分比所在位置,取值范围是[0,1] [Convention.RScript.Variable.Attr.Method] - public void EvaluatePosition(string value) + public void EvaluatePosition(float offset) { - MySplineOffset = Parse(value); + MySplineOffset = offset; Updater = () => transform.position = MySplineCore.MySplineComputer.EvaluatePosition(MySplineOffset); } /// - /// 绑定到样条线渲染器上(必须已经加载), + /// 绑定到样条线渲染器上 /// 并设置跟随指定时间的时刻渲染器所生成的头部 /// - /// 对象路径, 不存在时则立刻加载 + /// 样条线渲染器对象 /// 时刻 /// 是否跟随位置, 默认开启 /// 是否跟随旋转, 默认开启 [Convention.RScript.Variable.Attr.Method] - public void LoadSplineRenderer(string path, string time, string isFollowPosition = "true", string isFollowRotation = "true") + public void LoadSplineRenderer(BasicSplineRenderer splineRenderer, float time, bool isFollowPosition = true, bool isFollowRotation = true) { - MySplineRenderer = this.LoadSplineRendererTool(path); - MySplineOffset = Parse(time); - bool bIsFollowPosition = ConvertValue(isFollowPosition); - bool bIsFollowRotation = ConvertValue(isFollowRotation); + MySplineRenderer = splineRenderer; + MySplineOffset = time; + bool bIsFollowPosition = isFollowPosition; + bool bIsFollowRotation = isFollowRotation; if (bIsFollowPosition && bIsFollowRotation) { Updater = () => diff --git a/Assets/Scripts/MoreSpline/SplineCore.cs b/Assets/Scripts/MoreSpline/SplineCore.cs index 3f1bd20..95a1d42 100644 --- a/Assets/Scripts/MoreSpline/SplineCore.cs +++ b/Assets/Scripts/MoreSpline/SplineCore.cs @@ -22,7 +22,7 @@ namespace Demo.Game public interface IDependOnSplineCore : IScriptableObject { SplineCore MySplineCore { get; set; } - IEnumerator LoadSpline(string path); + void LoadSpline(string path); } public static class DependOnSplineCoreUtility @@ -38,19 +38,13 @@ namespace Demo.Game /// 加载并绑定到新样条线 /// /// 对象相对路径,若对象不存在则作为脚本相对路径加载 - public static IEnumerator LoadSplineTool(this IDependOnSplineCore self, string path) + public static SplineCore LoadSplineTool(this IDependOnSplineCore self, string path) { var spline = self.SharedInterfaceScriptObject.FindWithPath(path, false); if (spline == null) - yield return self.SharedInterfaceScriptObject.DoLoadSubScriptAsync(nameof(SplineCore), path, x => spline = x); - if (spline is SplineCore sc) - { - self.MySplineCore = sc; - } - else - { - Debug.LogWarning($"{path} is not a SplineCore", self.SharedInterfaceScriptObject); - } + spline = self.SharedInterfaceScriptObject.NewSubScript(nameof(SplineCore), new ToolFile(path).GetFilename(true), path); + self.MySplineCore = (SplineCore)spline; + return self.MySplineCore; } } @@ -61,18 +55,31 @@ namespace Demo.Game return new GameObject("", typeof(SplineComputer)).AddComponent(); } - [Content] public SplineComputer MySplineComputer; + [Content] private SplineComputer m_MySplineComputer; [Content] public int NodeContent = 0; - [Content] public List MySplineNodes = new(); + [Content] public readonly List MySplineNodes = new(); [Content] public SplineComputer.SampleMode MySampleMode = default; [Content] public Spline.Type MyType = default; public bool IsClose = false; - public override IEnumerator LoadScript(string script) + public SplineComputer MySplineComputer + { + get + { + if(m_MySplineComputer==null) + m_MySplineComputer= GetComponent(); + return m_MySplineComputer; + } + } + + /// + /// 需要在子都添加后再应用脚本才能使得节点生效 + /// + /// + protected override IEnumerator DoSomethingDuringApplyScript() { - MySplineComputer = GetComponent(); - yield return base.LoadScript(script); + yield return base.DoSomethingDuringApplyScript(); NodeContent = 0; MySplineComputer.SetPoints(new SplinePoint[MySplineNodes.Count]); foreach (SplineNode node in MySplineNodes) @@ -86,13 +93,12 @@ namespace Demo.Game MySplineComputer.Break(); MySplineComputer.sampleMode = MySampleMode; MySplineComputer.type = MyType; - yield return null; MySplineComputer.Rebuild(); } protected override void UpdateTicks(float currentTime, float deltaTime, TickType tickType) { - if (tickType == TickType.Start || tickType == TickType.Reset) + if (tickType != TickType.Update) MySplineComputer.Rebuild(); } @@ -109,9 +115,9 @@ namespace Demo.Game /// /// CatmullRom, BSpline, Bezier, Linear [Convention.RScript.Variable.Attr.Method] - public void SetType(string mode) + public void SetType(Spline.Type mode) { - MyType = Enum.Parse(mode); + MyType = mode; } /// @@ -119,9 +125,9 @@ namespace Demo.Game /// /// Default, Uniform, Optimized [Convention.RScript.Variable.Attr.Method] - public void SetSampleMode(string mode) + public void SetSampleMode(SplineComputer.SampleMode mode) { - MySampleMode = Enum.Parse(mode); + MySampleMode = mode; } @@ -135,47 +141,13 @@ namespace Demo.Game } /// - /// 加载并加入新节点 + /// 加入节点或者添加节点组件后加入节点 /// /// 脚本位置 [Convention.RScript.Variable.Attr.Method] - public IEnumerator LoadNode(string path) - { - yield return DoLoadSubScriptAsync(nameof(SplineNode), path, node => - { - if (node is SplineNode _node) - { - MySplineNodes.Add(_node); - } - else - { - Debug.LogError($"{path} is not {nameof(SplineNode)}", this); - } - }); - } - - /// - /// 加入节点脚本对象 - /// - [Convention.RScript.Variable.Attr.Method] - public void AddNode(ScriptableObject node) + public void LoadNode(ScriptableObject node) { MySplineNodes.Add(node.GetOrAddComponent()); } - - /// - /// 加入已加载的节点,如果目标脚本不是SplineNode, - /// 那么为其添加SplineNode组件 - /// - /// 脚本位置 - [Convention.RScript.Variable.Attr.Method] - public void AddNode(string path) - { - var node = FindWithPath(path); - if (node != null) - { - AddNode(node); - } - } } } diff --git a/Assets/Scripts/MoreSpline/SplineNode.cs b/Assets/Scripts/MoreSpline/SplineNode.cs index 708a239..a38eae7 100644 --- a/Assets/Scripts/MoreSpline/SplineNode.cs +++ b/Assets/Scripts/MoreSpline/SplineNode.cs @@ -11,17 +11,22 @@ namespace Demo.Game return new GameObject("", typeof(Node)).AddComponent(); } - public Node MyNode; + private Node m_MyNode; public float NodeSize = 1; public Color NodeColor = Color.white; public bool IsSetupNodeRotation = false; public Vector3 NodeRotation = Vector3.zero; public int MyNodeContent = 0; - public override IEnumerator LoadScript(string script) + + public Node MyNode { - MyNode = GetComponent(); - yield return base.LoadScript(script); + get + { + if (m_MyNode == null) + m_MyNode = GetComponent(); + return m_MyNode; + } } public void AddTo(SplineCore core) @@ -38,9 +43,9 @@ namespace Demo.Game /// /// [Convention.RScript.Variable.Attr.Method] - public void SetNodeSize(string size) + public void SetNodeSize(float size) { - NodeSize = Parse(size); + NodeSize = size; } /// @@ -51,9 +56,9 @@ namespace Demo.Game /// /// [Convention.RScript.Variable.Attr.Method] - public void SetNodeColor(string r, string g, string b, string a) + public void SetNodeColor(float r, float g, float b, float a) { - NodeColor = new(Parse(r), Parse(g), Parse(b), Parse(a)); + NodeColor = new(r, g, b, a); } /// @@ -63,10 +68,10 @@ namespace Demo.Game /// /// [Convention.RScript.Variable.Attr.Method] - public void SetNodeRotation(string x, string y, string z) + public void SetNodeRotation(float x, float y, float z) { IsSetupNodeRotation = true; - this.transform.localEulerAngles = NodeRotation = new(Parse(x), Parse(y), Parse(z)); + this.transform.localEulerAngles = NodeRotation = new(x, y, z); } } } diff --git a/Assets/Scripts/TickMovement.cs b/Assets/Scripts/TickMovement.cs index 00d70e3..8c63a0b 100644 --- a/Assets/Scripts/TickMovement.cs +++ b/Assets/Scripts/TickMovement.cs @@ -31,13 +31,11 @@ namespace Demo.Game /// x /// y /// z - /// 可取值为30种缓动曲线 + /// 缓动曲线 [Convention.RScript.Variable.Attr.Method] - public void Add(string time, string x, string y, string z, string curveType) + public void Add(float time, float x, float y, float z, MathExtension.EaseCurveType curveType) { - ManualAddEntry(time, - new(float.Parse(x), float.Parse(y), float.Parse(z)), - Enum.Parse(curveType)); + ManualAddEntry(time, new(x, y, z), curveType); } } } diff --git a/Assets/Scripts/TickRotation.cs b/Assets/Scripts/TickRotation.cs index 3eee130..951daf1 100644 --- a/Assets/Scripts/TickRotation.cs +++ b/Assets/Scripts/TickRotation.cs @@ -28,13 +28,11 @@ namespace Demo.Game /// x /// y /// z - /// 可取值为30种缓动曲线 + /// 缓动曲线 [Convention.RScript.Variable.Attr.Method] - public void Add(string time, string x, string y, string z, string curveType) + public void Add(float time, float x, float y, float z, MathExtension.EaseCurveType curveType) { - ManualAddEntry(time, - new(float.Parse(x), float.Parse(y), float.Parse(z)), - Enum.Parse(curveType)); + ManualAddEntry(time, new(x, y, z), curveType); } } } diff --git a/Assets/Scripts/TickScaling.cs b/Assets/Scripts/TickScaling.cs index b605923..e824b4a 100644 --- a/Assets/Scripts/TickScaling.cs +++ b/Assets/Scripts/TickScaling.cs @@ -28,13 +28,11 @@ namespace Demo.Game /// x /// y /// z - /// 可取值为30种缓动曲线 + /// 缓动曲线 [Convention.RScript.Variable.Attr.Method] - public void Add(string time, string x, string y, string z, string curveType) + public void Add(float time, float x, float y, float z, MathExtension.EaseCurveType curveType) { - ManualAddEntry(time, - new(float.Parse(x), float.Parse(y), float.Parse(z)), - Enum.Parse(curveType)); + ManualAddEntry(time, new(x, y, z), curveType); } } }