using Microsoft.SqlServer.Server; using QFramework; using System.Collections.Generic; using System.Linq; using System.Xml.Linq; namespace XMLTool { public class AppData { public PreLoad preLoad; public List Modules { get; set; } } public class PreLoad { public Action action; } public class Module { public string type { get; set; } public string Scene { get; set; } public string ModuleName { get; set; } public List Operations { get; set; } public List Devices { get; set; } public Dictionary FSM = new Dictionary(); public Dictionary ActionDict { get; set; } public Score score; } public class Device { public string Name { get; set; } public string Icon { get; set; } public string HighColor { get; set; } public string Path { get; set; } public string Tip { get; set; } public string BoxColliderSize { get; set; } public string BoxColliderCenter { get; set; } public bool MeshCollider { get; set; } } public class Score { public List scores; } public class ScoreStep { public string step; public string name; public string sum; public string bind; public float value; } public class ActionItem { public string Name { get; set; } public string Type { get; set; } public string Value { get; set; } public List SubActions { get; set; } } public class Action : ActionItem { } public class Condition : ActionItem { } public class FSM { public string Name { get; set; } public List Transisions { get; set; } public Dictionary StateDict { get; set; } } public class State { public string Name { get; set; } public StatePart Enter { get; set; } public StatePart Exit { get; set; } } public class StatePart { public Action Action { get; set; } } public class Transision { public string Name { get; set; } public string From { get; set; } public string To { get; set; } public Condition Action { get; set; } } public class Operation { public string moduleType { get; set; } public bool freeStep { get; set; } public List Steps { get; set; } } public class Step { public Step Parent { get; set; } public string Name { get; set; } public Action Reset { get; set; } public Action Start { get; set; } public Action Finished { get; set; } public bool isFinished = false; public List SubSteps { get; set; } } public class XmlParser { public static AppData ParseXml(string xmlString) { // 加载XML XDocument doc = XDocument.Parse(xmlString); // 获取根元素 XElement appDataElement = doc.Root; // 初始化AppData对象 AppData appData = new AppData { Modules = new List(), }; // 解析预加载动作 var preLoadElement = appDataElement.Element("PreLoad"); if (preLoadElement != null) { appData.preLoad = new PreLoad(); foreach (XElement actionElement in preLoadElement.Elements("Action")) { var action = ParseAction(actionElement); appData.preLoad.action = action; } } // 加载模块数据 LoadModules(appDataElement, appData); return appData; } public static void LoadModules(XElement appDataElement, AppData appData) { foreach (XElement moduleElement in appDataElement.Elements("Module")) { LoadModule(moduleElement, appData); } } public static void LoadModule(XElement moduleElement, AppData appData) { if (moduleElement != null) { Module module = new Module() { Devices = new List(), ActionDict = new Dictionary(), Operations = new List(), }; appData.Modules.Add(module); // 解析模块名称 module.type = moduleElement.Element("Type")?.Value; module.ModuleName = moduleElement.Element("Name")?.Value; module.Scene = moduleElement.Element("Scene")?.Value; // 解析设备 foreach (XElement deviceElement in moduleElement.Elements("Device")) { Device device = new Device { Name = deviceElement.Element("Name")?.Value, Icon = deviceElement.Element("Icon")?.Value, HighColor = deviceElement.Element("HighLight")?.Attribute("color")?.Value, Path = deviceElement.Element("Path")?.Value, Tip = deviceElement.Element("Tip")?.Value, MeshCollider = deviceElement.Element("MeshCollider") != null, BoxColliderCenter = deviceElement.Element("BoxCollider")?.Attribute("center")?.Value, BoxColliderSize = deviceElement.Element("BoxCollider")?.Attribute("size")?.Value, }; module.Devices.Add(device); } // 解析动作 foreach (XElement actionElement in moduleElement.Elements("Action")) { var action = ParseAction(actionElement); // 解析动作 module.ActionDict.Add(action.Name, action); } // 解析状态机 foreach (XElement fsmElement in moduleElement.Elements("FSM")) { FSM fsm = new FSM() { Name = fsmElement.Attribute("name")?.Value, StateDict = new Dictionary(), Transisions = new List(), }; // 解析状态 foreach (var stateNode in fsmElement.Elements("State")) { State state = new State() { Name = stateNode.Attribute("name")?.Value, }; fsm.StateDict.Add(state.Name, state); XElement enterElement = stateNode.Element("Enter"); XElement exitElement = stateNode.Element("Exit"); if (enterElement != null) { state.Enter = new StatePart(); state.Enter.Action = ParseAction(enterElement.Element("Action")); } if (exitElement != null) { state.Exit = new StatePart(); state.Exit.Action = ParseAction(exitElement.Element("Action")); } } // 解析状态转换 foreach (var transNode in fsmElement.Elements("Transision")) { Transision trans = new Transision() { Name = transNode.Attribute("name")?.Value, From = transNode.Attribute("from")?.Value, To = transNode.Attribute("to")?.Value, }; trans.Action = ParseCondition(transNode.Element("Condition")); fsm.Transisions.Add(trans); } module.FSM.Add(fsm.Name, fsm); } foreach (var operationNode in moduleElement.Elements("Operation")) { //module.Operations // 解析操作步骤 var op = new Operation() { Steps = new List(), }; op.moduleType = operationNode.Attribute("moduleType")?.Value; var free = operationNode.Attribute("freeStep"); bool isFree = true; if (free != null) { bool.TryParse(free.Value, out isFree); } op.freeStep = isFree; foreach (XElement stepNode in operationNode.Elements("Step")) { op.Steps.Add(ParserStep(stepNode, null)); } module.Operations.Add(op); } XElement scoreNode = moduleElement.Element("Score"); if (scoreNode != null) { module.score = new Score() { scores = new List() }; foreach (var item in scoreNode.Elements("Item")) { module.score.scores.Add( new ScoreStep() { step = item.Attribute("step")?.Value, name = item.Attribute("name")?.Value, sum = item.Attribute("sum")?.Value, bind = item.Attribute("bind")?.Value, }); } } } } public static Step ParserStep(XElement stepNode, Step parent) { Step step = new Step(); step.Name = stepNode.Attribute("name")?.Value; step.Reset = ParseAction(stepNode.Element("Reset")?.Element("Action")); step.Start = ParseAction(stepNode.Element("Start")?.Element("Action")); step.Finished = ParseAction(stepNode.Element("Finished")?.Element("Action")); step.SubSteps = ParserSteps(stepNode, step); step.Parent = parent; return step; } public static List ParserSteps(XElement step, Step parent) { List steps = new List(); if (step.Elements("Step").Any()) { foreach (var item in step.Elements("Step")) { steps.Add(ParserStep(item, parent)); } } return steps; } public static Action ParseAction(XElement action) { if (action == null) { return null; } string type = action.Attribute("type").Value; Action newAction = null; // 这里是用于扩展Action的字段 switch (type) { case "Move": case "Rotate": case "Scale": { var act = new MoveOrAction(); act.to = Utility.GetVector3FromStrArray(action.Attribute("to").Value); act.time = float.Parse(action.Attribute("time").Value); newAction = act; } break; case "Anim": { var act = new DictionaryAction(); var animName = action.Attribute("animName"); if (animName != null) { act.args.Add("animName",animName.Value); } var frame = action.Attribute("frame"); if (frame != null) { act.args.Add("frame", frame.Value); } var speed = action.Attribute("speed"); if (speed != null) { act.args.Add("speed", speed.Value); } var deviceName = action.Attribute("deviceName"); if (deviceName != null) { act.args.Add("deviceName", deviceName.Value); } newAction = act; } break; case "UITools": { var act = new StringListAction(); act.args.Add(action.Attribute("devices").Value); act.args.Add(action.Attribute("answers").Value); var setActive = action.Attribute("setActive"); if (setActive != null) { act.args.Add(setActive.Value); } else { act.args.Add("true"); } var rightLabel = action.Attribute("rightLabel"); if (rightLabel != null) { act.args.Add(rightLabel.Value); } else { act.args.Add(""); } var wrongLabel = action.Attribute("wrongLabel"); if (wrongLabel != null) { act.args.Add(wrongLabel.Value); } else { act.args.Add(""); } var rightEvent = action.Attribute("rightEvent"); if (rightEvent != null) { act.args.Add(rightEvent.Value); } else { act.args.Add(""); } var wrongEvent = action.Attribute("wrongEvent"); if (wrongEvent != null) { act.args.Add(wrongEvent.Value); } else { act.args.Add(""); } var rightScore = action.Attribute("rightScore"); if (rightScore != null) { act.args.Add(rightScore.Value); } else { act.args.Add(""); } var wrongScore = action.Attribute("wrongScore"); if (wrongScore != null) { act.args.Add(wrongScore.Value); } else { act.args.Add(""); } var scoreStepName = action.Attribute("scoreStepName"); if (scoreStepName != null) { act.args.Add(scoreStepName.Value); } else { act.args.Add(""); } newAction = act; } break; case "TextQuestion": { var act = new DictionaryAction(); XAttribute title = action.Attribute("title"); if (title != null) { act.args.Add("title", title.Value); } XAttribute options = action.Attribute("options"); if (options != null) { act.args.Add("options", options.Value); } XAttribute answers = action.Attribute("answers"); if (answers != null) { act.args.Add("answers", answers.Value); } XAttribute btns = action.Attribute("btns"); if (btns != null) { act.args.Add("btns", btns.Value); } XAttribute wait = action.Attribute("wait"); if (wait != null) { act.args.Add("wait", wait.Value); } XAttribute showAnswer = action.Attribute("showAnswer"); if (showAnswer != null) { act.args.Add("showAnswer", showAnswer.Value); } XAttribute rightScore = action.Attribute("rightScore"); if (rightScore != null) { act.args.Add("rightScore", rightScore.Value); } XAttribute errorScore = action.Attribute("wrongScore"); if (errorScore != null) { act.args.Add("errorScore", errorScore.Value); } XAttribute scoreName = action.Attribute("scoreName"); if (scoreName != null) { act.args.Add("scoreName", scoreName.Value); } XAttribute absolutely = action.Attribute("absolutely"); if (absolutely != null) { act.args.Add("absolutely", absolutely.Value); } XAttribute format = action.Attribute("format"); if (format != null) { act.args.Add("format", format.Value); } XAttribute finishedEvent = action.Attribute("finishedEvent"); if (finishedEvent != null) { act.args.Add("finishedEvent", finishedEvent.Value); } newAction = act; } break; case "UIShow": { var act = new StringListAction(); XAttribute isShow = action.Attribute("isShow"); if (isShow == null) { act.args.Add("true"); } else { act.args.Add(isShow.Value); } newAction = act; } break; case "Hint": { var act = new StringListAction(); XAttribute time = action.Attribute("time"); if (time != null) { act.args.Add(time.Value); } else { act.args.Add("-1"); } XAttribute icon = action.Attribute("icon"); if (icon != null) { act.args.Add(icon.Value); } else { act.args.Add("true"); } XAttribute audio = action.Attribute("audio"); if (audio != null) { act.args.Add(audio.Value); } else { act.args.Add(""); } newAction = act; } break; case "Show": { var act = new DictionaryAction(); XAttribute isShow = action.Attribute("isShow"); if (isShow != null) { act.args.Add("isShow",isShow.Value); } XAttribute isDevice = action.Attribute("isDevice"); if (isDevice != null) { act.args.Add("isDevice", isDevice.Value); } XAttribute deviceName = action.Attribute("deviceName"); if (deviceName != null) { act.args.Add("deviceName", deviceName.Value); } XAttribute isRoot = action.Attribute("isRoot"); if (isRoot != null) { act.args.Add("isRoot", isRoot.Value); } newAction = act; } break; case "CameraSwitch": { var act = new DictionaryAction(); XAttribute nearDevice = action.Attribute("nearDevice"); if (nearDevice != null) { act.args.Add("nearDevice", nearDevice.Value); } else { XAttribute nearPos = action.Attribute("nearPos"); if (nearPos != null) { act.args.Add("nearPos", nearPos.Value); } XAttribute nearRot = action.Attribute("nearRot"); if (nearRot != null) { act.args.Add("nearRot", nearRot.Value); } } XAttribute normalDevice = action.Attribute("normalDevice"); if (normalDevice != null) { act.args.Add("normalDevice", normalDevice.Value); } else { XAttribute normalPos = action.Attribute("normalPos"); if (normalPos != null) { act.args.Add("normalPos", normalPos.Value); } XAttribute normalRot = action.Attribute("normalRot"); if (normalRot != null) { act.args.Add("normalRot", normalRot.Value); } } XAttribute nearTime = action.Attribute("nearTime"); if (nearTime != null) { act.args.Add("nearTime", nearTime.Value); } else { act.args.Add("nearTime", "0"); } XAttribute normalTime = action.Attribute("normalTime"); if (normalTime != null) { act.args.Add("normalTime", normalTime.Value); } else { act.args.Add("normalTime", "0"); } newAction = act; } break; case "CameraLock": { var act = new StringListAction(); XAttribute isMove = action.Attribute("isMove"); if (isMove != null) { act.args.Add(isMove.Value); } else { act.args.Add("true"); } XAttribute isRotate = action.Attribute("isRotate"); if (isRotate != null) { act.args.Add(isRotate.Value); } else { act.args.Add("true"); } newAction = act; } break; case "TextTip": { var act = new StringListAction(); XAttribute audio = action.Attribute("audio"); if (audio != null) { act.args.Add(audio.Value); } else { act.args.Add(""); } XAttribute btns = action.Attribute("btns"); if (btns != null) { act.args.Add(btns.Value); } else { act.args.Add(""); } newAction = act; } break; case "Video": { var act = new StringListAction(); XAttribute size = action.Attribute("size"); if (size != null) { act.args.Add(size.Value); } else { act.args.Add("792,458"); } XAttribute offset = action.Attribute("offset"); if (offset != null) { act.args.Add(offset.Value); } else { act.args.Add("0,0"); } XAttribute finishedEvent = action.Attribute("finishedEvent"); if (finishedEvent != null) { act.args.Add(finishedEvent.Value); } else { act.args.Add(""); } XAttribute closeEvent = action.Attribute("closeEvent"); if (closeEvent != null) { act.args.Add(closeEvent.Value); } else { act.args.Add(""); } newAction = act; } break; case "HighLight": { var act = new DictionaryAction(); XAttribute isHigh = action.Attribute("isHigh"); if (isHigh != null) { act.args.Add("isHigh", isHigh.Value); } XAttribute color = action.Attribute("color"); if (color != null) { act.args.Add("color", color.Value); } XAttribute deviceName = action.Attribute("deviceName"); if (deviceName != null) { act.args.Add("deviceName", deviceName.Value); } newAction = act; } break; case "LoadRes": { var act = new StringListAction(); XAttribute resType = action.Attribute("resType"); if (resType != null) { act.args.Add(resType.Value); } else { act.args.Add(""); } newAction = act; } break; case "Audio": { //string path, string audioType, string loop, string finishedEvent, string volume, var act = new StringListAction(); XAttribute audioType = action.Attribute("audioType"); if (audioType != null) { act.args.Add(audioType.Value); } else { act.args.Add("Sound"); } XAttribute loop = action.Attribute("loop"); if (loop != null) { act.args.Add(loop.Value); } else { act.args.Add("false"); } XAttribute waitFinished = action.Attribute("waitFinished"); if (waitFinished != null) { act.args.Add(waitFinished.Value); } else { act.args.Add(""); } XAttribute volume = action.Attribute("volume"); if (volume != null) { act.args.Add(volume.Value); } else { act.args.Add(""); } XAttribute isPlay = action.Attribute("isPlay"); if (isPlay != null) { act.args.Add(isPlay.Value); } else { act.args.Add("true"); } newAction = act; } break; case "Line": { var act = new StringListAction(); XAttribute color = action.Attribute("color"); if (color != null) { act.args.Add(color.Value); } else { act.args.Add(""); } XAttribute width = action.Attribute("width"); if (width != null) { act.args.Add(width.Value); } else { act.args.Add("0.1"); } XAttribute lineScale = action.Attribute("lineScale"); if (lineScale != null) { act.args.Add(lineScale.Value); } else { act.args.Add("1,1"); } newAction = act; } break; case "ResultTip": { var act = new StringListAction(); XAttribute isRight = action.Attribute("isRight"); if (isRight != null) { act.args.Add(isRight.Value); } else { act.args.Add("false"); } XAttribute finishedEvent = action.Attribute("finishedEvent"); if (finishedEvent != null) { act.args.Add(finishedEvent.Value); } else { act.args.Add(""); } newAction = act; } break; case "Led": { var act = new StringListAction(); XAttribute number = action.Attribute("number"); if (number != null) { act.args.Add(number.Value); } else { act.args.Add("0"); } XAttribute color = action.Attribute("color"); if (color != null) { act.args.Add(color.Value); } else { act.args.Add("255,255,255,255"); } newAction = act; } break; case "Script": { var act = new StringListAction(); XAttribute finishedEvent = action.Attribute("finishedEvent"); if (finishedEvent != null) { act.args.Add(finishedEvent.Value); } else { act.args.Add(""); } newAction = act; } break; case "Collider": { var act = new StringListAction(); XAttribute deviceName = action.Attribute("deviceName"); if (deviceName != null) { act.args.Add(deviceName.Value); } else { act.args.Add(""); } XAttribute colliderType = action.Attribute("colliderType"); if (colliderType != null) { act.args.Add(colliderType.Value); } else { act.args.Add("空"); } XAttribute arg = action.Attribute("args"); if (arg != null) { act.args.Add(arg.Value); } else { act.args.Add(""); } newAction = act; } break; case "TimeTip": { var act = new DictionaryAction(); XAttribute time = action.Attribute("time"); if (time != null) { act.args.Add("time", time.Value); } else { act.args.Add("time", "0"); } XAttribute values = action.Attribute("values"); if (values != null) { act.args.Add("values", values.Value); } XAttribute format = action.Attribute("format"); if (format != null) { act.args.Add("format", format.Value); } XAttribute finishedEvent = action.Attribute("finishedEvent"); if (finishedEvent != null) { act.args.Add("finishedEvent", finishedEvent.Value); } XAttribute needClick = action.Attribute("needClick"); if (needClick != null) { act.args.Add("needClick", needClick.Value); } XAttribute reverse = action.Attribute("reverse"); if (reverse != null) { act.args.Add("reverse", reverse.Value); } newAction = act; } break; case "SkinnedBake": { var act = new DictionaryAction(); XAttribute deviceName = action.Attribute("deviceName"); if (deviceName != null) { act.args.Add("deviceName", deviceName.Value); } newAction = act; } break; case "TimeLine": { var act = new DictionaryAction(); XAttribute deviceName = action.Attribute("deviceName"); if (deviceName != null) { act.args.Add("deviceName", deviceName.Value); } XAttribute isShow = action.Attribute("isShow"); if (isShow != null) { act.args.Add("isShow", isShow.Value); } XAttribute finishedEvent = action.Attribute("finishedEvent"); if (finishedEvent != null) { act.args.Add("finishedEvent", finishedEvent.Value); } XAttribute isWait = action.Attribute("isWait"); if (isWait != null) { act.args.Add("isWait", isWait.Value); } XAttribute frame = action.Attribute("frame"); if (frame != null) { act.args.Add("frame", frame.Value); } XAttribute endFrame = action.Attribute("endFrame"); if (endFrame != null) { act.args.Add("endFrame", endFrame.Value); } newAction = act; } break; default: newAction = new Action(); break; } newAction.Type = action.Attribute("type")?.Value; newAction.Name = action.Attribute("name")?.Value; newAction.Value = action.Attribute("value")?.Value; newAction.SubActions = ParseActions(action); return newAction; } public static Condition ParseCondition(XElement action) { Condition newAction = null; string type = action.Attribute("type")?.Value; switch (type) { case "ObjClick": var act = new DictionaryCondition(); XAttribute deviceName = action.Attribute("deviceName"); if (deviceName != null) { act.args.Add("deviceName", deviceName.Value); } XAttribute isRight = action.Attribute("isRight"); if (isRight != null) { act.args.Add("isRight", isRight.Value); } newAction = act; break; default: newAction = new Condition(); break; } newAction.Type = type; newAction.Name = action.Attribute("name")?.Value; newAction.Value = action.Attribute("value")?.Value; newAction.SubActions = ParseActions(action); return newAction; } public static ActionItem ParserActionItem(XElement element) { ActionItem actItem = null; switch (element.Name.LocalName) { case "Action": actItem = ParseAction(element); break; case "Condition": actItem = ParseCondition(element); break; } return actItem; } private static List ParseActions(XElement actionElement) { List actions = new List(); foreach (XElement action in actionElement.Elements()) { actions.Add(ParserActionItem(action)); } return actions; } } }