Files
Main/Assets/Launcher/ExternalLibs/Others/StoryScript.cs
2025-01-25 04:38:09 +08:00

735 lines
28 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.Collections;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
public class StoryScript : MonoBehaviour
{
public const string InstallPath = "install";
/// <summary>
/// 位置父节点的路径
/// </summary>
public const string PosPath = "install/[Transform]";
/// <summary>
/// 路点父节点的路径
/// </summary>
public const string PathPointPath = "install/[PathPoint]";
/// <summary>
/// TimelineNames父节点的路径
/// </summary>
public const string TimelinePath = "install/[TimelineNames]";
/// <summary>
/// TimelineNames父节点的路径
/// </summary>
public const string FormPath = "install/[FormNames]";
/// <summary>
/// 触发器盒子父节点的路径
/// </summary>
public const string TriggerBoxPath = "install/[TriggerBox]";
/// <summary>
/// 3D文字
/// </summary>
public const string Text3DPath = "install/[Text3D]";
/// <summary>
/// 触发器父节点的路径
/// </summary>
public const string TriggersPath = "triggers";
/// <summary>
/// 故事名
/// </summary>
//public string storyName;
/// <summary>
/// 故事id
/// </summary>
public int id;
/// <summary>
/// 描述
/// </summary>
public string describe;
/// <summary>
/// 需要预加载的Timeline
/// </summary>
public List<string> preLoadTimelineNames = new List<string>();
/// <summary>
/// 需要预加载的UI界面
/// </summary>
public List<string> preLoadFormNames = new List<string>();
/// <summary>
/// 位置
/// </summary>
public Dictionary<string, Transform> transforms = new Dictionary<string, Transform>();
/// <summary>
/// 路点
/// </summary>
public Dictionary<string, List<Transform>> pathPoint = new Dictionary<string, List<Transform>>();
/// <summary>
/// 触发器盒子
/// </summary>
public Dictionary<string, Transform> triggerBoxDic = new Dictionary<string, Transform>();
/// <summary>
/// 3D文字
/// </summary>
public Dictionary<string, GameObject> Text3DDic = new Dictionary<string, GameObject>();
/// <summary>
/// 触发器
/// </summary>
public List<StoryTrigger> storyTriggers = new List<StoryTrigger>();
private void CheckNode(string path)
{
//判断是否在Inspacter面板
if (transform.gameObject.activeInHierarchy)
{
var parentTf = transform.Find(path);
if (parentTf == null)
{
var strArr = path.Split('/');
var gobj = new GameObject(strArr[1]);
parentTf = gobj.transform;
parentTf.SetParent(transform.Find(strArr[0]));
#if UNITY_EDITOR
if (UnityEditor.PrefabUtility.GetPrefabObject(gameObject) != null)
{
UnityEditor.PrefabUtility.ReplacePrefab(gameObject, UnityEditor.PrefabUtility.GetPrefabParent(gameObject), UnityEditor.ReplacePrefabOptions.ConnectToPrefab);
}
#endif
}
}
}
//获取节点下所有子节点的名字
public void GetNames(List<string> list, Transform parentTf)
{
list.Clear();
//var parentTf = transform.Find(path);
int count = parentTf.childCount;
if (count > 0)
{
for (int i = 0; i < count; i++)
{
var child = parentTf.GetChild(i);
var name = child.gameObject.name;
list.Add(name);
}
}
list.Sort((a, b) =>
{
return a.CompareTo(b);
});
}
//将List中的所有string 转成Lua格式
public string GetLuaFormatByStringList(string title, List<string> stringList)
{
var count = stringList.Count;
StringBuilder sb = new StringBuilder();
sb.AppendLine(string.Format(" {0} = {{", title));
if (count > 0)
{
Dictionary<string, bool> allTimelineNameDic = new Dictionary<string, bool>();
for (int i = 0; i < count; i++)
{
if (!allTimelineNameDic.ContainsKey(stringList[i]))
{
allTimelineNameDic.Add(stringList[i], true);
}
else
{
Debug.LogError("出现了相同的名字!!! " + stringList[i]);
}
}
foreach (var item in allTimelineNameDic)
{
sb.AppendLine(string.Format(" \"{0}\",", item.Key));
}
}
sb.AppendLine(" },");
return sb.ToString();
}
//获取所有需要预加载的UIForm名字
public List<string> GetAllFormNames()
{
CheckNode(FormPath);
var parentTf = transform.Find(FormPath);
if (parentTf != null)
GetNames(preLoadFormNames, transform.Find(FormPath));
return preLoadFormNames;
}
//获取所有需要预加载的Timeline名字
public List<string> GetAllTimelineNames()
{
CheckNode(TimelinePath);
var parentTf = transform.Find(TimelinePath);
if (parentTf != null)
GetNames(preLoadTimelineNames, parentTf);
return preLoadTimelineNames;
}
//获取所有需要预加载的UIForm名字 lua格式
public string GetLuaFormatByAllFormNames()
{
return GetLuaFormatByStringList("preLoadFormNames", GetAllFormNames());
}
//获取所有需要预加载的Timeline名字 lua格式
public string GetLuaFormatByAllTimelineNames()
{
return GetLuaFormatByStringList("preLoadTimelineNames", GetAllTimelineNames());
}
//获取所有位置
public Dictionary<string, Transform> GetAllPos()
{
CheckNode(PosPath);
transforms.Clear();
var posTf = transform.Find(PosPath);
int count = posTf.childCount;
if (count > 0)
{
for (int i = 0; i < count; i++)
{
var child = posTf.GetChild(i);
var name = child.gameObject.name;
Transform tf;
if (!transforms.TryGetValue(name, out tf))
{
transforms.Add(name, child);
}
else
{
Debug.LogError("故事:" + gameObject.name + ",位置中有相同名字:" + name);
}
}
}
return transforms;
}
//获取所有位置 lua格式
public string GetLuaFormatByAllPos()
{
// transform = {
// npc10001 = { { 13,0,17},{ 0,90,0} },
// interactor10016 = { { 13,0,19},{ 1,1,0} },
// interactor10015 = { { 13,0,21},{ 1,1,1} },
// },
var allTranform = GetAllPos();
StringBuilder sb = new StringBuilder();
sb.AppendLine(" transform = {");
foreach (var item in allTranform)
{
var tf = item.Value;
var pos = tf.position;
var dir = tf.eulerAngles;
sb.AppendLine(string.Format(" {0} = {{{{{1},{2},{3}}},{{{4},{5},{6}}}}},",
item.Key, pos.x < 0.001f ? 0 : pos.x, pos.y < 0.001f ? 0 : pos.y, pos.z < 0.001f ? 0 : pos.z,
dir.x < 0.001f ? 0 : dir.x, dir.y < 0.001f ? 0 : dir.y, dir.z < 0.001f ? 0 : dir.z));
}
sb.AppendLine(" },");
return sb.ToString();
}
//获取所有路点
public Dictionary<string, List<Vector3>> GetAllPathPoint()
{
CheckNode(PathPointPath);
pathPoint.Clear();
var allPathPoint = new Dictionary<string, List<Vector3>>();
var pathPointTf = transform.Find(PathPointPath);
int count = pathPointTf.childCount;
if (count > 0)
{
for (int i = 0; i < count; i++)
{
var childTf = pathPointTf.GetChild(i);
var name = childTf.gameObject.name;
List<Vector3> pathPoints;
List<Transform> pathPointTfs;
if (!allPathPoint.TryGetValue(name, out pathPoints))
{
pathPoints = new List<Vector3>();
pathPointTfs = new List<Transform>();
int childCount = childTf.childCount;
for (int j = 0; j < childCount; j++)
{
pathPoints.Add(childTf.GetChild(j).position);
pathPointTfs.Add(childTf.GetChild(j));
}
allPathPoint.Add(name, pathPoints);
pathPoint.Add(name, pathPointTfs);
}
else
{
Debug.LogError("故事:" + gameObject.name + ",路点中有相同名字:" + name);
}
}
}
return allPathPoint;
}
//获取所有路点 lua格式
public string GetLuaFormatByPathPoint()
{
// pathPoint = {
// npc10001 = { { 1,0,1},{ 2,0,2} },
// npc10002 = { { 3,0,0},{ 4,0,4} },
// },
var allPathPoint = GetAllPathPoint();
StringBuilder sb = new StringBuilder();
sb.AppendLine(" pathPoint = {");
StringBuilder sbTemp = new StringBuilder();
foreach (var item in allPathPoint)
{
sbTemp.Remove(0, sbTemp.Length);
var pathPoints = item.Value;
for (int i = 0; i < pathPoints.Count; i++)
{
sbTemp.Append(string.Format(i == pathPoints.Count - 1 ? "{{{0},{1},{2}}}" : "{{{0},{1},{2}}},",
pathPoints[i].x < 0.001f ? 0 : pathPoints[i].x, pathPoints[i].y < 0.001f ? 0 : pathPoints[i].y, pathPoints[i].z < 0.001f ? 0 : pathPoints[i].z));
}
sb.AppendLine(string.Format(" {0} = {{{1}}},", item.Key, sbTemp.ToString()));
}
sb.AppendLine(" },");
return sb.ToString();
}
/// <summary>
/// 获取所有触发器盒子
/// </summary>
/// <returns></returns>
public Dictionary<string, Transform> GetAllTriggerBox()
{
CheckNode(TriggerBoxPath);
var parentTf = transform.Find(TriggerBoxPath);
if (parentTf == null)
return triggerBoxDic;
triggerBoxDic.Clear();
int count = parentTf.childCount;
if (count > 0)
{
for (int i = 0; i < count; i++)
{
var child = parentTf.GetChild(i);
var name = child.gameObject.name;
Transform tf;
if (!triggerBoxDic.TryGetValue(name, out tf))
{
triggerBoxDic.Add(name, child);
}
else
{
Debug.LogError("故事:" + gameObject.name + ",触发器盒子有相同名字:" + name);
}
}
}
return triggerBoxDic;
}
//获取所有触发盒子 lua格式
public string GetLuaFormatByTriggerBox()
{
// triggerBox = {
// cub_001 = {"Box",{0, 0, 0}, {1, 1, 1}},
// sphere_001 = {"Sphere",{0, 0, 0}, 3},
// },
var allTriggerBox = GetAllTriggerBox();
StringBuilder sb = new StringBuilder();
sb.AppendLine(" triggerBox = {");
StringBuilder sbTemp = new StringBuilder();
foreach (var item in allTriggerBox)
{
sbTemp.Remove(0, sbTemp.Length);
var tf = item.Value;
var boxCollider = tf.gameObject.GetComponent<BoxCollider>();
if (boxCollider != null)
{
var centerPos = tf.position;
var scale = tf.localScale * 0.5f;
sbTemp.Append(string.Format("{{\"{0}\",\"Box\", {{{1:N4}, {2:N4}, {3:N4}}}, {{{4:N4}, {5:N4}, {6:N4}}}}},", item.Key,
centerPos.x - scale.x, centerPos.y - scale.y, centerPos.z - scale.z, centerPos.x + scale.x, centerPos.y + scale.y, centerPos.z + scale.z));
}
else
{
var sphereCollider = tf.gameObject.GetComponent<SphereCollider>();
if (sphereCollider != null)
{
var centerPos = tf.position;
var radius = tf.localScale.x * 0.5f;
tf.localScale = new Vector3(radius * 2, radius * 2, radius * 2);
sbTemp.Append(string.Format("{{\"{0}\",\"Sphere\", {{{1:N4}, {2:N4}, {3:N4}}}, {4:N4}}},", item.Key, centerPos.x, centerPos.y, centerPos.z, radius));
}
}
sb.AppendLine(string.Format(" {0} = {1}", item.Key, sbTemp.ToString()));
}
sb.AppendLine(" },");
return sb.ToString();
}
/// <summary>
/// 获取所有3D文字
/// </summary>
/// <returns></returns>
public Dictionary<string, GameObject> GetAllText3D()
{
CheckNode(Text3DPath);
var parentTf = transform.Find(Text3DPath);
if (parentTf == null)
return Text3DDic;
var uiRoot = parentTf.GetComponent<UIRoot>();
//检查UIRoot组件
if (!uiRoot)
{
uiRoot = parentTf.gameObject.AddComponent<UIRoot>();
uiRoot.scalingStyle = UIRoot.Scaling.ConstrainedOnMobiles;
uiRoot.manualWidth = 1136;
uiRoot.manualHeight = 640;
uiRoot.fitWidth = true;
uiRoot.fitHeight = true;
}
var uiPanel = parentTf.GetComponent<UIPanel>();
//检查UIPanel组件
if (!uiPanel)
{
uiPanel = parentTf.gameObject.AddComponent<UIPanel>();
}
Text3DDic.Clear();
int count = parentTf.childCount;
if (count > 0)
{
for (int i = 0; i < count; i++)
{
var child = parentTf.GetChild(i).gameObject;
var name = child.name;
GameObject gobjOut;
if (!Text3DDic.TryGetValue(name, out gobjOut))
{
Text3DDic.Add(name, child);
}
else
{
Debug.LogError("故事:" + gameObject.name + ",3D文字有相同名字:" + name);
}
}
}
return Text3DDic;
}
//获取所有3D文字 lua格式
public string GetLuaFormatByText3D()
{
// triggerBox = {
// Text001 = {"Text001",{0, 0, 0}, {0, 0, 0},{"内容",18, 200, 26}},
// },
// {"名字",{posX, posY , posZ}, {rotaX, rotaY, rotaZ}, {"内容", foneSize, sizeWidth, sizeHeight}},
var allText3D = GetAllText3D();
StringBuilder sb = new StringBuilder();
sb.AppendLine(" Text3D = {");
StringBuilder sbTemp = new StringBuilder();
foreach (var item in allText3D)
{
sbTemp.Remove(0, sbTemp.Length);
var gobj = item.Value;
var tf = gobj.transform;
var pos = tf.position;
var eulerAngles = tf.eulerAngles;
var uiLabel = gobj.GetComponent<UILabel>();
sbTemp.Append(string.Format("{{\"{0}\", {{{1}, {2}, {3}}}, {{{4}, {5}, {6}}}, {{\"{7}\", {8}, {9}, {10}}}}},",
item.Key, pos.x, pos.y, pos.z, eulerAngles.x, eulerAngles.y, eulerAngles.z, uiLabel.text, uiLabel.fontSize, uiLabel.width, uiLabel.height));
sb.AppendLine(string.Format(" {0} = {1}", item.Key, sbTemp.ToString()));
}
sb.AppendLine(" },");
return sb.ToString();
}
//获取所有触发器
public List<StoryTrigger> GetAllTriggers()
{
storyTriggers.Clear();
var triggersTf = transform.Find(TriggersPath);
var count = triggersTf.childCount;
if (count > 0)
{
for (int i = 0; i < count; i++)
{
var script = triggersTf.GetChild(i).GetComponent<StoryTrigger>();
if (script != null)
{
storyTriggers.Add(script);
}
}
}
return storyTriggers;
}
//添加触发器
public StoryTrigger AddTrigger(string name, int index)
{
var triggersTf = transform.Find(TriggersPath);
var go = new GameObject(name);
go.transform.parent = triggersTf;
if (index != -1)
{
go.transform.SetSiblingIndex(index);
}
var storyTrigger = go.AddComponent<StoryTrigger>();
return storyTrigger;
}
//移除触发器
public void RemoveTrigger(int index)
{
var triggersTf = transform.Find(TriggersPath);
var go = triggersTf.GetChild(index).gameObject;
DestroyImmediate(go);
}
//获取所有触发器 lua格式
public string GetLuaFormatByTrigger()
{
var allTrigger = GetAllTriggers();
StringBuilder sb = new StringBuilder();
sb.AppendLine(" triggers = {");
var count = storyTriggers.Count;
for (int i = 0; i < count; i++)
{
var storyTrigger = storyTriggers[i];
var actions = storyTrigger.actions;
//若没有动作或动作都是None不会导出该触发器
if (actions.Count == 0)
continue;
var isNotEmpty = false;
for (int j = 0; j < actions.Count; j++)
{
isNotEmpty = isNotEmpty || actions[j].actionType != ActionType.None;
}
if (!isNotEmpty)
continue;
//触发条件
var triggerCondition = storyTrigger.triggerCondition;
var triggerConditionParames = storyTrigger.triggerConditionParames;
var triggerConditionStr = GetTriggerConditionStr(triggerCondition, triggerConditionParames);
//限制条件
var limitCondition = storyTrigger.limitCondition;
var limitConditionStr = GetLimitConditionStr(limitCondition, 0);
var actionsStr = GetActionStr(actions);
//动作
sb.AppendLine(" {");
sb.AppendLine(" ID = " + storyTrigger.id + ",");
sb.AppendLine(" isActive = true,");
sb.AppendLine(" triggerCondition = " + triggerConditionStr);
sb.AppendLine(" limitCondition = " + limitConditionStr);
sb.AppendLine(" action = " + actionsStr);
sb.AppendLine(" },");
}
sb.AppendLine(" }");
return sb.ToString();
}
//获取触发条件string lua格式
public string GetTriggerConditionStr(TriggerConditionType triggerConditionType, List<string> parames)
{
string result = "{";
switch (triggerConditionType)
{
case TriggerConditionType.Init: result += "\"init\""; break;
case TriggerConditionType.EnterMap: result += parames[0] == "" ? "\"enterMap\"" : "\"enterMap\"," + parames[0]; break;
case TriggerConditionType.TalkOver: result += parames[0] == "" ? "\"talkOver\"" : "\"talkOver\"," + parames[0]; break;
case TriggerConditionType.InteractionOver: result += parames[0] == "" ? "\"interactionOver\"" : "\"interactionOver\"," + parames[0]; break;
case TriggerConditionType.TimeLineOver: result += parames[0] == "" ? "\"timeLineOver\"" : string.Format("\"timeLineOver\",\"{0}\"", parames[0]); break;
case TriggerConditionType.Variable: result += parames[0] == "" ? "\"variable\"" : "\"variable\"," + parames[0] + ", " + parames[1] + ", " + parames[2]; break;
case TriggerConditionType.EnterTriggerArea: result += parames[0] == "None" ? "\"enterTriggerArea\"" : string.Format("\"enterTriggerArea\",\"{0}\"", parames[0]); break;
default: Debug.LogError("未添加该类型Key"); break;
}
result += "},";
return result;
}
//获取限制条件string lua格式
public string GetLimitConditionStr(LimitCondition limitConditionBase, int layer)
{
if (limitConditionBase.GetType() == typeof(LimitCondition))
{
var limitCondition = limitConditionBase as LimitCondition;
var limitConditionType = limitCondition.curLimitConditionType;
var parames = limitCondition.curLimitCoiditionParames;
var limitConditionChilds = limitCondition.limitConditionChilds;
var count = limitConditionChilds.Count;
string result = layer == 0 ? "" : GetPreStr(layer);
switch (limitConditionType)
{
case LimitConditionType.None: result += string.Format("{{\"{0}\"}},", "none"); break;
case LimitConditionType.EnterMap: result += string.Format("{{\"{0}\",{1}}},", "enterMap", parames[0]); break;
case LimitConditionType.TalkOver: result += string.Format("{{\"{0}\",{1}}},", "talkOver", parames[0]); break;
case LimitConditionType.InteractionOver: result += string.Format("{{\"{0}\",{1}}},", "interactionOver", parames[0]); break;
case LimitConditionType.TimeLineOver: result += string.Format("{{\"{0}\",\"{1}\"}},", "timeLineOver", parames[0]); break;
case LimitConditionType.Variable: result += string.Format("{{\"{0}\",\"{1}\",\"{2}\",{3}}},", "variable", parames[0], parames[1], parames[2]); break;
case LimitConditionType.EnterTriggerArea: result += string.Format("{{\"{0}\",\"{1}\"}},", "enterTriggerArea", parames[0]); break;
case LimitConditionType.And:
result += string.Format("{{\"{0}\",\n", "and");
for (int i = 0; i < count; i++)
{
result += GetLimitConditionStr(limitConditionChilds[i], layer + 1) + "\n";
}
result += GetPreStr(layer) + "},";
break;
case LimitConditionType.Or:
result += string.Format("{{\"{0}\",\n", "or");
for (int i = 0; i < count; i++)
{
result += GetLimitConditionStr(limitConditionChilds[i], layer + 1) + "\n";
}
result += GetPreStr(layer) + "},";
break;
default: Debug.LogError("未添加该类型Key"); break;
}
return result;
}
return "{},";
}
//Log,//日志 1
//SetTriggerActive,//设置触发器开关 2
//CreatNpc,//创建NPC 2
//CreatInteractor,//创建交互物 2
//SetVariable,//设置变量 2
//RemoveEntity,//移除物体 1
//SetNPCAI,//设置NPC的AI 2
//PlayTimeline,//播放Timeline 1
//LoadTimeline,//加载Timeline 1
//StartInteract,//开始交互 1
//SetPlayerTransform,//设置玩家位置和旋转 1
//SetPlayerScale,//设置玩家缩放 1
//OpenFromStoryEnd,//打开故事结束界面 1
//ChangeInteractState,//设置交互物是否可交互 2
//ShowTextTips,//显示文字提示 1
//ShowCalendar,//显示日历 2
public string GetActionStr(List<TriggerAction> triggerActions)
{
StringBuilder sb = new StringBuilder();
sb.AppendLine("{");
var count = triggerActions.Count;
if (count > 0)
{
for (int i = 0; i < count; i++)
{
var actionType = triggerActions[i].actionType;
var parames = triggerActions[i].actionParames;
string result = "";
switch (actionType)
{
case ActionType.Log:
result += string.Format("{{\"{0}\", \"{1}\"}}", "log", parames[0]);
break;
case ActionType.SetTriggerActive:
result += string.Format("{{\"{0}\", {1}, {2}}}", "setTriggerActive", parames[0], parames[1]);
break;
case ActionType.CreatNpc:
result += string.Format("{{\"{0}\", {1}, \"{2}\"}}", "creatNpc", parames[0], parames[1]);
break;
case ActionType.CreatInteractor:
result += string.Format("{{\"{0}\", {1}, \"{2}\"}}", "creatInteractor", parames[0], parames[1]);
break;
case ActionType.SetVariable:
result += string.Format("{{\"{0}\", \"{1}\", {2}}}", "setVariable", parames[0], parames[1]);
break;
case ActionType.RemoveEntity:
result += string.Format("{{\"{0}\", {1}}}", "removeEntity", parames[0]);
break;
case ActionType.SetNPCAI:
result += string.Format("{{\"{0}\", {1}, {2}}}", "setNPCAI", parames[0], parames[1]);
break;
case ActionType.PlayTimeline:
result += string.Format("{{\"{0}\", \"{1}\"}}", "playTimeline", parames[0]);
break;
case ActionType.LoadTimeline:
result += string.Format("{{\"{0}\", \"{1}\"}}", "loadTimeline", parames[0]);
break;
case ActionType.StartInteract:
result += string.Format("{{\"{0}\", {1}}}", "startInteract", parames[0]);
break;
case ActionType.SetPlayerTransform:
result += string.Format("{{\"{0}\", \"{1}\"}}", "setPlayerTransform", parames[0]);
break;
case ActionType.SetPlayerScale:
result += string.Format("{{\"{0}\", {1}}}", "setPlayerScale", parames[0]);
break;
case ActionType.OpenFromStoryEnd:
result += string.Format("{{\"{0}\", \"{1}\"}}", "openFromStoryEnd", parames[0]);
break;
case ActionType.ChangeInteractState:
result += string.Format("{{\"{0}\", {1}, {2}}}", "changeInteractState", parames[0], parames[1]);
break;
case ActionType.ShowTextTips:
result += string.Format("{{\"{0}\", \"{1}\"}}", "showTextTips", parames[0]);
break;
case ActionType.ShowCalendar:
result += string.Format("{{\"{0}\", {1}, {2}}}", "showCalendar", parames[0], parames[1]);
break;
case ActionType.AddTriggerBox:
result += string.Format("{{\"{0}\", \"{1}\"}}", "addTriggerBox", parames[0]);
break;
case ActionType.RemoveTriggerBox:
result += string.Format("{{\"{0}\", \"{1}\"}}", "removeTriggerBox", parames[0]);
break;
case ActionType.ShowText3D:
result += string.Format("{{\"{0}\", \"{1}\"}}", "showText3D", parames[0]);
break;
case ActionType.HideText3D:
result += string.Format("{{\"{0}\", \"{1}\"}}", "hideText3D", parames[0]);
break;
case ActionType.ShowProgress:
result += string.Format("{{\"{0}\", \"{1}\"}}", "showProgress", parames[0]);
break;
default:
break;
}
sb.AppendLine(string.Format(GetPreStr(1) + "{0},", result));
}
}
sb.Append(GetPreStr(0) + "},");
return sb.ToString();
}
public string GetPreStr(int layer)
{
string temp = "";
for (int i = -3; i < layer; i++)
{
temp += " ";
}
return temp;
}
}