推进同化RScript
This commit is contained in:
@@ -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<string, float> TimePointDelta = new();
|
||||
public static Dictionary<string, float> TimePoints = new();
|
||||
|
||||
/// <summary>
|
||||
/// 重设指定时间线
|
||||
/// </summary>
|
||||
/// <param name="id">时间线ID,若不存在则创建</param>
|
||||
/// <param name="delta">当每次调用NextTimePoint函数时使用的单位值</param>
|
||||
/// <param name="value">初始化时间</param>
|
||||
[Convention.RScript.Variable.Attr.Method]
|
||||
public void ResetTimePoint(string id, float delta, float value)
|
||||
{
|
||||
TimePointDelta[id] = delta;
|
||||
TimePoints[id] = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 推动时间线前进
|
||||
/// </summary>
|
||||
/// <param name="id">时间线ID</param>
|
||||
/// <param name="times">前进次数,最终时间的增量为前进次数乘该时间线的单位值</param>
|
||||
[Convention.RScript.Variable.Attr.Method]
|
||||
public void NextTimePoint(string id, float times)
|
||||
{
|
||||
TimePoints[id] += TimePointDelta[id] * times;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置时间线的值
|
||||
/// </summary>
|
||||
/// <param name="id">时间线ID</param>
|
||||
/// <param name="value">次数,时间线的值将被设置为次数乘该时间线的单位值</param>
|
||||
[Convention.RScript.Variable.Attr.Method]
|
||||
public void SetTimePoint(string id, float value)
|
||||
{
|
||||
TimePoints[id] = TimePointDelta[id] * value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 上下文系统
|
||||
/// </summary>
|
||||
public partial class ScriptableObject
|
||||
{
|
||||
[Content] public Dictionary<string, float> 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<string, float> context)
|
||||
{
|
||||
var current = this;
|
||||
while (current != null)
|
||||
{
|
||||
foreach (var key in current.ScriptContextSpace.Keys)
|
||||
{
|
||||
context[key] = current.ScriptContextSpace[key];
|
||||
}
|
||||
current = current.Parent;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置局部上下文变量,将会传递给子物体使用
|
||||
/// </summary>
|
||||
/// <param name="name">字符串</param>
|
||||
/// <param name="value">浮点数</param>
|
||||
[Convention.RScript.Variable.Attr.Method]
|
||||
public void SetContext(string name, float value)
|
||||
{
|
||||
ScriptContextSpace[name] = value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 数值解析工具
|
||||
/// </summary>
|
||||
public partial class ScriptableObject
|
||||
{
|
||||
private ExpressionContext ExpressionParserCreater()
|
||||
{
|
||||
ExpressionContext context = new();
|
||||
context.Imports.AddType(typeof(Mathf));
|
||||
Dictionary<string, float> vars = new();
|
||||
GetCompleteScriptContext(ref vars);
|
||||
foreach (var item in vars)
|
||||
{
|
||||
context.Variables[item.Key] = item.Value;
|
||||
}
|
||||
return context;
|
||||
}
|
||||
public static float OneBarTime = 1;
|
||||
|
||||
/// <summary>
|
||||
/// 从字符串解析为浮点数
|
||||
/// <list type="bullet">从时间点列表<see cref="TimePoints"/>中获取</list>
|
||||
/// <list type="bullet">或是从上下文变量<see cref="GetCompleteScriptContext"/>中获取</list>
|
||||
/// <list type="bullet">或是从数据驱动对象<see cref="DDT"/>中获取</list>
|
||||
/// <list type="bullet">或是通过计算表达式值获取</list>
|
||||
/// <list type="bullet">或是直接调用<see cref="float.Parse(string)"/></list>
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
[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<float>(value).Evaluate();
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
throw new FormatException($"{value} is not support any Parser", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected T ConvertValue<T>(string str)
|
||||
{
|
||||
return ConventionUtility.convert_xvalue<T>(str);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 先天支持的工具函数
|
||||
/// 初始化与对象设置
|
||||
/// </summary>
|
||||
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;
|
||||
|
||||
/// <summary>
|
||||
/// 设置坐标
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// UpdatePerFrame相关
|
||||
/// </summary>
|
||||
public partial class ScriptableObject
|
||||
{
|
||||
[Content] public int UpdatePerFrame = 1;
|
||||
|
||||
/// <summary>
|
||||
/// 指定多少个<see cref="TickType.Update"/>状态的<see cref="UpdateTicks(float, float, TickType)"/>执行一次更新,不会影响到子物体
|
||||
/// 属于性能优化的高级选项
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// EnableScript相关
|
||||
/// 跨脚本上下文变量
|
||||
/// </summary>
|
||||
public partial class ScriptableObject
|
||||
{
|
||||
public Dictionary<string, object> 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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 基础信息, 父子关系与EnableScript
|
||||
/// </summary>
|
||||
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<ScriptableObject> Childs = new();
|
||||
|
||||
public PropertiesWindow.ItemEntry MyHierarchyItem;
|
||||
public static PropertiesWindow.ItemEntry AllScriptableObjectCounterHierarchyItem;
|
||||
/// <summary>
|
||||
/// 获取根脚本对象
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[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<Editor.UI.RightClick>().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
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -396,115 +296,55 @@ namespace Demo
|
||||
|
||||
#region LoadSubScript
|
||||
|
||||
private static ScriptableObject LastLoadedScriptableObject;
|
||||
|
||||
public IEnumerator DoLoadSubScriptAsync([In] string type, [In] string path, [Opt] Action<ScriptableObject> 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<ScriptableObject> 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<ScriptableObject> 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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建无初始化脚本且无启动的子脚本对象
|
||||
/// 创建基于子脚本的实例对象
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
[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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建不基于子脚本的实例对象
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
[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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将无初始化创建的脚本对象确认完全加载并设置为最后添加的脚本对象
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[Convention.RScript.Variable.Attr.Method]
|
||||
public ScriptableObject ApplyLoad()
|
||||
{
|
||||
// Load Child Script
|
||||
ConventionUtility.StartCoroutine(this.LoadScript(""));
|
||||
|
||||
LastLoadedScriptableObject = this;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建不需要脚本语句的子脚本对象
|
||||
/// </summary>
|
||||
/// <param name="type">指定类型</param>
|
||||
[Convention.RScript.Variable.Attr.Method]
|
||||
public ScriptableObject NewSubScript([In] string type, [In] string name)
|
||||
{
|
||||
return DoGenerateSubScript(type, name, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建不需要脚本语句的子脚本对象
|
||||
/// </summary>
|
||||
/// <param name="type">指定类型</param>
|
||||
[Convention.RScript.Variable.Attr.Method]
|
||||
public ScriptableObject NewSubScript([In] string type)
|
||||
{
|
||||
return NewSubScript(type, $"New {type}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加载子脚本
|
||||
/// </summary>
|
||||
/// <param name="type">指定类型</param>
|
||||
/// <param name="path">指定脚本,可用决定路径或与当前脚本目录的相对路径</param>
|
||||
[Convention.RScript.Variable.Attr.Method]
|
||||
public IEnumerator LoadSubScript([In] string type, [In] string path)
|
||||
{
|
||||
return DoLoadSubScriptAsync(type, path, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取已加载的脚本对象
|
||||
/// </summary>
|
||||
@@ -590,19 +386,9 @@ namespace Demo
|
||||
return Parent;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取上一个加载的脚本对象
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[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
|
||||
/// </summary>
|
||||
public partial class ScriptableObject : SerializedMonoBehaviour, IHierarchyItemClickEventListener
|
||||
{
|
||||
|
||||
public static bool IsAutoPlay = false;
|
||||
|
||||
public ScriptableObject Parent;
|
||||
|
||||
/// <summary>
|
||||
/// 获取根脚本对象
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[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<ScriptableObject> 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<Editor.UI.TimelineItem>();
|
||||
yield return base.LoadScript(script);
|
||||
yield return base.DoSomethingDuringApplyScript();
|
||||
if(MyTimelineEntry==null)
|
||||
{
|
||||
MyTimelineEntry = TimelineWindow.CreateRootItemEntries(1)[0];
|
||||
MyTimelineItem = MyTimelineEntry.ref_value.GetComponent<Editor.UI.TimelineItem>();
|
||||
}
|
||||
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<ScriptableObject> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user