using System; using System.Collections.Generic; using System.Text; using CommonAI.Zone.Instance; using CommonAI.Zone; using CommonLang.Property; using System.Globalization; using CommonAI.Zone.Attributes; using CommonLang.Xml; using System.Xml; using CommonLang.Log; using CommonLang.IO; using CommonLang; using CommonAI.ZoneEditor; using CommonLang.IO.Attribute; using System.IO; using CommonLang.Property.Modeling; using System.Collections; using System.Reflection; using CommonLang.XCSV; using CommonLang.Concurrent; using CommonAI.Zone.Helper; using CommonAI.ZoneServer.JSGModule; using CommonLang.Vector; namespace CommonAI.Zone.ZoneEditor { public class EditorTemplatesData { readonly public TerrainDefinitionMap TerrainDefinitions; readonly public UnitActionDefinitionMap UnitActionDefinitions; readonly public HashMap Units = new HashMap(); readonly public HashMap Skills = new HashMap(); readonly public HashMap Spells = new HashMap(); readonly public HashMap Buffs = new HashMap(); readonly public HashMap Items = new HashMap(); readonly public HashMap UnitTriggers = new HashMap(); readonly public HashMap UnitEvents = new HashMap(); readonly public HashMap Scenes = new HashMap(); public EditorTemplatesData( TerrainDefinitionMap mapDefines, UnitActionDefinitionMap unitActionDefines, List units, List skills, List spells, List buffs, List items, List triggers, List events, List scenes) { this.TerrainDefinitions = mapDefines; this.UnitActionDefinitions = unitActionDefines; PutAll(this.Units, units); PutAll(this.Skills, skills); PutAll(this.Spells, spells); PutAll(this.Buffs, buffs); PutAll(this.Items, items); PutAll(this.UnitTriggers, triggers); PutAll(this.UnitEvents, events); PutAll(this.Scenes, scenes); } public int FileCount { get { return this.Units.Count + this.Skills.Count + this.Spells.Count + this.Buffs.Count + this.Items.Count + this.UnitTriggers.Count + this.UnitEvents.Count + this.Scenes.Count; } } public List AllTemplates() { ArrayList ret = new ArrayList(); ret.AddRange(Units.Values); ret.AddRange(Skills.Values); ret.AddRange(Spells.Values); ret.AddRange(Buffs.Values); ret.AddRange(Items.Values); ret.AddRange(UnitTriggers.Values); ret.AddRange(UnitEvents.Values); ret.AddRange(Scenes.Values); var list = new List(ret.Capacity); foreach (ITemplateData a in ret) { list.Add(a); } list.Sort(new TemplateDataComparer()); return list; } public bool GetObjectByType(Type type, int templateID, out object data) { data = null; if (type.IsAssignableFrom(typeof(UnitInfo))) { data = Units[templateID]; } else if (type.IsAssignableFrom(typeof(SkillTemplate))) { data = Skills[templateID]; } else if (type.IsAssignableFrom(typeof(SpellTemplate))) { data = Spells[templateID]; } else if (type.IsAssignableFrom(typeof(BuffTemplate))) { data = Buffs[templateID]; } else if (type.IsAssignableFrom(typeof(ItemTemplate))) { data = Items[templateID]; } else if (type.IsAssignableFrom(typeof(UnitTriggerTemplate))) { data = UnitTriggers[templateID]; } else if (type.IsAssignableFrom(typeof(UnitEventTemplate))) { data = UnitEvents[templateID]; } else if (type.IsAssignableFrom(typeof(SceneData))) { data = Scenes[templateID]; } return data != null; } private static void PutAll(HashMap map, List list) where T : ITemplateData { foreach (T u in list) { map[u.TemplateID] = u; } } public struct TemplateDataComparer : IComparer { public int Compare(ITemplateData ix, ITemplateData iy) { int tr = string.Compare(ix.GetType().FullName, iy.GetType().FullName); if (tr == 0) { return ix.TemplateID - iy.TemplateID; } return tr; } } } public class EditorTemplates { public static bool DEFAULT_LOAD_FROM_BIN = true; public static bool RUNTIME_IN_SERVER = true; private readonly static Logger log = LoggerFactory.GetLogger("EditorTemplates"); private readonly HashMap> loaded; private readonly HashMap scenes; private readonly HashMap mCacheScenes; private readonly string dir; private IExternalizableFactory factory; private TemplateManager templates = new TemplateManager(); private bool is_client_mode; public bool IsClientData { get { return is_client_mode; } } public string DataRoot { get { return dir; } } public TemplateManager Templates { get { return templates; } } public EditorTemplatesData AllTemplatesExcludeScenes { get { return new EditorTemplatesData( templates.TerrainDefinition, templates.UnitActionDefinition, templates.getAllUnits(), templates.getAllSkills(), templates.getAllSpells(), templates.getAllBuffs(), templates.getAllItems(), templates.getAllUnitTriggers(), templates.getAllUnitEvents(), new List()); } } public EditorTemplates(string dir, IExternalizableFactory factory, bool client_mode = false) { this.dir = dir; this.factory = factory; this.loaded = new HashMap>(); this.scenes = new HashMap(); this.mCacheScenes = new HashMap(); this.is_client_mode = client_mode; } /// /// 判断当前模板是否加载 /// /// /// /// /// public bool IsTemplateLoaded(Type type, int templateID, out object template) { HashMap map = loaded.Get(type); if (map != null && map.TryGetValue(templateID, out template)) { return true; } template = null; return false; } /// /// 加载配置 /// /// public void LoadCFG() { this.templates.CFG = LoadXmlAs(dir + "/config.xml", new Config()); this.templates.ExtConfig = LoadXmlAs(dir + "/config_ext.xml", TemplateManager.Factory.CreateCommonCFG()); this.templates.ExtConfig.init(); } public string LoadResVersion() { string md5 = Resource.LoadAllText(dir + "/ver.md5"); string[] lines = md5.Split('\n'); this.templates.ResourceVersion = lines[0].Trim(); return md5; } public void LoadTerrainDefinitionMap() { TerrainDefinitionMap td = LoadData(dir + "/terrain_definition.xml"); if (td != null) { this.templates.TerrainDefinition = td; } } public void LoadUnitActionDefinitionMap() { UnitActionDefinitionMap td = LoadData(dir + "/unit_action_definition.xml"); if (td != null) { this.templates.UnitActionDefinition = td; } } public void LoadAllCFG(byte[] dat) { LoadAllCFG(new MemoryStream(dat)); } public void LoadAllCFG(Stream stream) { var br = new BinaryReader(stream); // -- md5 var md5 = br.ReadString(); log.Debug("Eidtor Resource Version = " + md5); this.templates.ResourceVersion = md5; // -- config.xml this.templates.CFG = LoadNextXml(br, "config.xml", new Config()); // -- config_ext.xml this.templates.ExtConfig = LoadNextXml(br, "config_ext.xml", TemplateManager.Factory.CreateCommonCFG()); // -- terrain_definition.xml var td = LoadNextXml(br, "terrain_definition.xml"); if (td != null) { this.templates.TerrainDefinition = td; } // -- unit_action_definition var ud = LoadNextXml(br, "unit_action_definition.xml"); if (ud != null) { this.templates.UnitActionDefinition = ud; } } T LoadNextXml(BinaryReader br, string srcFileName, T default_value = default(T)) { try { var len = br.ReadInt32(); var dat = br.ReadBytes(len); XmlDocument xml = XmlUtil.LoadXML(dat); return (T)XmlUtil.XmlToObject(xml); } catch (Exception err) { string msg = "LoadXml Error : " + srcFileName + "\n" + err.Message; if (log != null) { log.Error(msg, err); } else { Console.WriteLine(msg + "\r\n" + err.StackTrace); } } return default_value; } public string[] LoadList(string subdir) { string base_dir = dir + subdir; List ret = new List(); string listtxt = Resource.LoadAllText(base_dir + "/.list"); foreach (string line in listtxt.Split('\n')) { string[] lv = line.Split(';'); if (lv.Length > 1) { ret.Add(base_dir + "/" + lv[lv.Length - 1].Trim() + ".xml"); } } return ret.ToArray(); } /// /// 重新读取所有模板 /// /// public void LoadAllTemplates(bool client = false, bool gameEdit = false) { try { LoadCFG(); LoadResVersion(); LoadTerrainDefinitionMap(); LoadUnitActionDefinitionMap(); if(!client && !gameEdit) { this.CacheAllScenes(); } foreach (string file in LoadList("/units")) { LoadTemplate(file); } foreach (string file in LoadList("/skills")) { LoadTemplate(file); } foreach (string file in LoadList("/spells")) { LoadTemplate(file); } foreach (string file in LoadList("/buffs")) { LoadTemplate(file); } foreach (string file in LoadList("/items")) { LoadTemplate(file); } if (!client) { foreach (string file in LoadList("/unit_triggers")) { LoadTemplate(file); } foreach (string file in LoadList("/unit_events")) { LoadTemplate(file); } } if (TemplateManager.Formula != null) { TemplateManager.Formula.InitPluginsData(this); } int sncount = templates.RehashAll(); log.Info("RehashAll : " + sncount); } catch (Exception err) { log.Error(err.Message + "\n" + err.StackTrace); throw new Exception(err.Message + "\n" + err.StackTrace); } } private object TryLoad(int templateID, Type templateType) { if (templateID == 0) { return null; } object template = null; if (!IsTemplateLoaded(templateType, templateID, out template)) { if (templateType.Equals(typeof(UnitInfo))) { template = LoadTemplate(dir + "/units/" + templateID + ".xml"); } else if (templateType.Equals(typeof(SkillTemplate))) { template = LoadTemplate(dir + "/skills/" + templateID + ".xml"); } else if (templateType.Equals(typeof(SpellTemplate))) { template = LoadTemplate(dir + "/spells/" + templateID + ".xml"); } else if (templateType.Equals(typeof(BuffTemplate))) { template = LoadTemplate(dir + "/buffs/" + templateID + ".xml"); } else if (templateType.Equals(typeof(ItemTemplate))) { template = LoadTemplate(dir + "/items/" + templateID + ".xml"); } else if (templateType.Equals(typeof(UnitTriggerTemplate))) { template = LoadTemplate(dir + "/unit_triggers/" + templateID + ".xml"); } else if (templateType.Equals(typeof(UnitEventTemplate))) { template = LoadTemplate(dir + "/unit_events/" + templateID + ".xml"); } } return template; } public T LoadTemplate(byte[] binDat) where T : class, ITemplateData { T info = LoadDataFromBin(binDat, factory); if (info != null) { TryAddTemplate(info); } return info; } public T LoadTemplate(Stream stream) where T : class, ITemplateData { T info = LoadDataFromBin(stream, factory); if (info != null) { TryAddTemplate(info); } return info; } public T LoadTemplate(string file) where T : class, ITemplateData { try { T info = LoadData(file); if (info != null) { TryAddTemplate(info); return info; } else { log.Info("LoadTemplate Error : " + file); } } catch (Exception err) { throw new Exception("LoadTemplate : " + file + "\n" + err.Message, err); } return null; } void TryAddTemplate(ITemplateData info) { if (info is UnitInfo) { templates.addUnit(info as UnitInfo); } else if (info is SkillTemplate) { templates.addSkill(info as SkillTemplate); } else if (info is SpellTemplate) { templates.addSpell(info as SpellTemplate); } else if (info is BuffTemplate) { templates.addBuff(info as BuffTemplate); } else if (info is ItemTemplate) { templates.addItem(info as ItemTemplate); } else if (info is UnitTriggerTemplate) { templates.addUnitTrigger(info as UnitTriggerTemplate); } else if (info is UnitEventTemplate) { templates.addUnitEvent(info as UnitEventTemplate); } //log.Debug("LoadTemplate : " + info.GetType() + " : " + info); HashMap map = loaded.Get(info.GetType()); if (map == null) { map = new HashMap(); loaded.Put(info.GetType(), map); } map.Put((info as ITemplateData).TemplateID, info); } public ISceneDataLoader sceneDataLoader { get; private set; } public void SetSceneDataLoader(ISceneDataLoader sdl) { this.sceneDataLoader = sdl; } /// /// 根据ID加载场景 /// /// /// 是否缓存起来(占用内存,一般服务端用) /// 是否是客户端使用 /// 是否克隆(仅cache) /// public SceneData LoadScene(int id, bool cache = true, bool client_data = false, bool clone = true) { if (client_data) { cache = false; } SceneData scene = null; if (cache) { scene = scenes.Get(id); } if (scene == null && sceneDataLoader != null) { scene = sceneDataLoader.Load(id, client_data , factory); } if (scene == null) { scene = LoadScene(dir + "/scenes/" + id + ".xml", cache, client_data); } if (scene != null) { if (cache && clone) { scene = IOUtil.CloneIExternalizable(factory, scene); } else if (client_data) { int sncount = templates.RehashScene(scene.GetSerialDatas()); log.Info("RehashScene : " + sncount); } } return scene; } /** 根据ID加载场景 */ public SceneData LoadScene_Server(int id, bool cache = true, bool clone = true) { SceneData scene = this.mCacheScenes.Get(id); if (scene == null) { scene = this.LoadScene(id, cache, false, clone); } return scene; } public SceneData CacheScene_Server(int sceneID) { SceneData scene = scenes.Get(sceneID); if (scene == null && sceneDataLoader != null) { scene = sceneDataLoader.Load(sceneID, false, factory); } if (scene == null) { scene = LoadScene(dir + "/scenes/" + sceneID + ".xml", true, false); } if (scene != null) { scene = IOUtil.CloneIExternalizable(factory, scene); } if(scene == null) { log.Error("场景数据不存在:" + sceneID); } else if (scene.ZoneData.TotalHeight >= 255 || scene.ZoneData.TotalWidth >= 255) { log.Error("场景设置过大,请设置成255*255之内:" + sceneID); } return scene; } /// /// 缓存所有场景数据,一般服务器用。消耗内存较大 /// public void CacheAllScenes() { // foreach (int scene_id in ListScenes()) // { // SceneData sceneTemp = this.CacheScene_Server(scene_id); // if(sceneTemp == null) // { // log.Error("缓存场景异常:" + scene_id); // continue; // } // this.mCacheScenes.Put(scene_id, sceneTemp); //} //List ret = new List(scenes.Values); //int sncount = templates.RehashAllScene(ret); //log.Info("RehashAllScene : " + sncount); } //检测场景单位位置合法性. 只允许内部手动调用查看结果,然后关闭 public void CheckScenePosInfo() { HashMap < int, UnitInfo > unitsTemp = this.Templates.getUnits(); HashMap allUnits = new HashMap(); allUnits.PutAll(unitsTemp); unitsTemp.Clear(); foreach (SceneData sceneData in mCacheScenes.Values) { log.Error("---------------开始检测场景位置信息:" + sceneData.TemplateID + "---------------"); InstanceZone zoneTemp = TemplateManager.Factory.CreateEditorScene(Templates, null, sceneData, null, "1000"); foreach(UnitData unitTemp in sceneData.Units) { UnitInfo unitInfo = allUnits.Get(unitTemp.UnitTemplateID); if(unitInfo == null) { log.Warn("场景单位不存在:" + unitTemp.UnitTemplateID); continue; } else if(unitInfo.UType == UnitInfo.UnitType.TYPE_NPC) { continue; } //if(unitTemp.Name.Equals("小偷")) //{ // //int i = 0; //} if (zoneTemp.TryTouchMap(null, unitTemp.X, unitTemp.Y)) { log.Error("--场景单位位置非法:" + unitTemp.Name + ", X: " + unitTemp.X + ", Y: " + unitTemp.Y); } } foreach (RegionData regionTemp in sceneData.Regions) { bool hasCheckAbility = false; foreach(RegionAbilityData abilityTemp in regionTemp.Abilities) { if(abilityTemp is PlayerStartAbilityData || abilityTemp is SpawnItemAbilityData || abilityTemp is SpawnUnitAbilityData || abilityTemp is XmdsRebirthAbility) { hasCheckAbility = true; break; } } if (!hasCheckAbility) { continue; } if(regionTemp.RegionType == RegionData.Shape.STRIP) { log.Info("跳过异性区域判定: " + regionTemp.Name); continue; } List checkPos = new List(); if (regionTemp.RegionType == RegionData.Shape.ROUND) { checkPos.Add(new Vector2(regionTemp.X - regionTemp.W / 2, regionTemp.Y)); checkPos.Add(new Vector2(regionTemp.X, regionTemp.Y + regionTemp.W / 2)); checkPos.Add(new Vector2(regionTemp.X, regionTemp.Y + regionTemp.W / 2)); checkPos.Add(new Vector2(regionTemp.X - regionTemp.W / 2, regionTemp.Y)); } else { checkPos.Add(new Vector2(regionTemp.X - regionTemp.W / 2, regionTemp.Y - regionTemp.H / 2)); checkPos.Add(new Vector2(regionTemp.X - regionTemp.W / 2, regionTemp.Y + regionTemp.H / 2)); checkPos.Add(new Vector2(regionTemp.X + regionTemp.W / 2, regionTemp.Y - regionTemp.H / 2)); checkPos.Add(new Vector2(regionTemp.X + regionTemp.W / 2, regionTemp.Y + regionTemp.H / 2)); } foreach (Vector2 posTemp in checkPos) { if (zoneTemp.TryTouchMap(null, posTemp.X, posTemp.Y)) { log.Error("--场景区域位置非法:" + regionTemp.Name + ", X: " + regionTemp.X + ", Y: " + regionTemp.Y); break; } } } zoneTemp.Dispose(); } System.Console.WriteLine("全部场景检测完毕!"); Console.ReadLine(); } /// /// 是否缓存场景 /// /// /// public bool ExistSceneInCache(int id) { return scenes.ContainsKey(id); } public SceneData GetSceneInCache(int id) { return scenes.Get(id); } public List ListScenes() { List ret = new List(); foreach (string file in LoadList("/scenes")) { try { string sub = file.Replace('\\', '/'); int begin = sub.LastIndexOf('/') + 1; int end = sub.LastIndexOf('.'); sub = sub.Substring(begin, end - begin); ret.Add(int.Parse(sub)); } catch (Exception err) { log.Error(err.Message, err); } } return ret; } public List LoadAllScenes(bool cache = true, bool client_data = false, bool clone = false) { var ret = new List(scenes.Count); foreach (var id in ListScenes()) { ret.Add(LoadScene(id, cache, client_data, clone)); } return ret; } //--------------------------------------------------------------------------------------------------- #region Loader readonly private static Encoding UTF8 = new UTF8Encoding(false); protected virtual T LoadData(string file) where T : class, IExternalizable { T info = null; if (file.EndsWith(".xml")) { if (DEFAULT_LOAD_FROM_BIN) { string bin = file + ".bin"; try { if (Resource.ExistData(bin)) { info = LoadDataFromBin(bin, factory); return info; } } catch (Exception err) { log.Error("LoadData Error : " + bin + "\n" + err.Message, err); } } info = LoadXmlAs(file, log); } return info; } protected virtual SceneData LoadScene(string file, bool cache, bool client_data) { try { if (client_data) { cache = false; } SceneData info = null; string bin_file = file + ".bin"; if (DEFAULT_LOAD_FROM_BIN && Resource.ExistData(bin_file)) { Stream stream = Resource.LoadDataAsStream(bin_file); if (stream != null) { try { InputStream input = new InputStream(stream, factory); int typeID = input.GetS32(); Type type = factory.GetType(typeID); if (typeof(SceneData).Equals(type)) { info = new SceneData(); if (!cache && client_data) { info.ReadExternalByClient(input); } else { info.ReadExternal(input); } } } finally { stream.Dispose(); } } } if (info == null) { info = LoadXmlAs(file, log); } if (info != null) { log.Debug("LoadScene : " + info.GetType() + " : " + info); if (cache) { scenes.Put(info.ID, info); } } else { log.Error("LoadScene Error : " + file); } return info; } catch (Exception err) { log.Error("LoadScene : " + file + "\n" + err.Message); throw new Exception(err.Message, err); } } public static T LoadXmlAs(string path, T default_value = default(T)) { return LoadXmlAs(path, null, default_value); } public static T LoadXmlAs(string path, Logger log, T default_value = default(T)) { try { XmlDocument xml = XmlUtil.LoadXML(path); return (T)XmlUtil.XmlToObject(xml); } catch (Exception err) { string msg = "LoadXml Error : " + path + "\n" + err.Message; if (log != null) { log.Error(msg, err); } else { Console.WriteLine(msg + "\r\n" + err.StackTrace); } } return default_value; } public static T LoadDataFromBin(byte[] dat, IExternalizableFactory factory) where T : class, IExternalizable { using (var stream = new MemoryStream(dat)) { LoadDataFromBin(stream, factory); } return null; } public static T LoadDataFromBin(Stream stream, IExternalizableFactory factory) where T : class, IExternalizable { try { InputStream input = new InputStream(stream, factory); int typeID = input.GetS32(); if (typeID != 0) { Type type = factory.GetType(typeID); if (type != null) { T any = (T)Activator.CreateInstance(type); any.ReadExternal(input); return any; } } } catch (Exception e) { log.Error(e); } return null; } public static T LoadDataFromBin(string file, IExternalizableFactory factory) where T : IExternalizable { var stream = Resource.LoadDataAsStream(file); if (stream != null) { try { InputStream input = new InputStream(stream, factory); int typeID = input.GetS32(); if (typeID != 0) { Type type = factory.GetType(typeID); if (type != null) { T any = (T)Activator.CreateInstance(type); any.ReadExternal(input); return any; } } } finally { stream.Dispose(); } } return default(T); } public static string DataToXmlText(T data) where T : IExternalizable { StringBuilder output = new StringBuilder(); try { XmlDocument doc = XmlUtil.ObjectToXml(data); XmlWriterSettings settings = new XmlWriterSettings(); settings.Indent = true; settings.Encoding = UTF8; using (XmlWriter xml = XmlWriter.Create(output, settings)) { doc.Save(xml); xml.Flush(); } } catch (Exception err) { output.AppendLine(err.Message); output.AppendLine(err.StackTrace); } return output.ToString(); } public static bool ValidateBin(T data, IExternalizableFactory factory, out string xml, out string retxml) where T : IExternalizable { try { xml = DataToXmlText(data); byte[] bin; using (MemoryStream ms = new MemoryStream(1024 * 1024)) { OutputStream output = new OutputStream(ms, factory); output.PutExt(data); ms.Flush(); bin = new byte[ms.Position]; Array.Copy(ms.GetBuffer(), bin, bin.Length); } using (MemoryStream ms = new MemoryStream(bin)) { InputStream input = new InputStream(ms, factory); T ret = (T)input.GetExtAny(); retxml = DataToXmlText(ret); if (xml.Equals(retxml)) { return true; } } } catch (Exception err) { retxml = xml = (err.Message) + "\r\n" + (err.StackTrace); } return false; } public static byte[] DataToBin(T data, IExternalizableFactory factory) where T : IExternalizable { using (MemoryStream ms = new MemoryStream(1024 * 1024)) { OutputStream output = new OutputStream(ms, factory); output.PutExt(data); ms.Flush(); byte[] bin = new byte[ms.Position]; Array.Copy(ms.GetBuffer(), bin, bin.Length); return bin; } } public static byte[] SaveDataToBin(FileInfo file, T data, IExternalizableFactory factory) where T : IExternalizable { byte[] bin = DataToBin(data, factory); File.WriteAllBytes(file.FullName, bin); return bin; } public static T DataFromXML(string text) where T : IExternalizable { XmlDocument xml = XmlUtil.FromString(text); if (xml != null) { return (T)XmlUtil.XmlToObject(xml); } return default(T); } #endregion //--------------------------------------------------------------------------------------------------- #region ResourceID /// /// 有选择的递归读取字段标识的所有相关的模板 [TemplateID] [TemplatesID] /// 返回资源标记[ResourceID]列表,提供给客户端预加载资源 /// /// /// public List SelectTemplates(object data) { HashMap resources = new HashMap(); HashMap exist = new HashMap(); SelectAllTemplates(data, resources, exist); return new List(resources.Keys); } public HashMap SelectTemplatesAsMap(object data) { HashMap resources = new HashMap(); HashMap exist = new HashMap(); SelectAllTemplates(data, resources, exist); return resources; } private void SelectAllTemplates(object data, HashMap resources, HashMap exist) { if (!exist.ContainsKey(data)) { exist.Add(data, data); // 获取所有标识为 TemplateID 字段 List templateList = new List(); PropertyUtil.CollectFieldAttributeValues(data, typeof(TemplateIDAttribute), templateList); foreach (FieldAttributeValue fa in templateList) { TemplateIDAttribute t_attr = fa.AttributeData as TemplateIDAttribute; object template = TryLoad((int)fa.FieldValue, t_attr.TemplateType); if (template != null) { SelectAllTemplates(template, resources, exist); } } // 获取所有标识为 TemplatesID 字段 List templatesList = new List(); PropertyUtil.CollectFieldAttributeValues(data, typeof(TemplatesIDAttribute), templatesList); foreach (FieldAttributeValue fa in templatesList) { TemplatesIDAttribute t_attr = fa.AttributeData as TemplatesIDAttribute; List ids = fa.FieldValue as List; foreach (int id in ids) { object template = TryLoad(id, t_attr.TemplateType); if (template != null) { SelectAllTemplates(template, resources, exist); } } } // 获取所有 ResourceID 字段 List resourceList = new List(); PropertyUtil.CollectFieldAttributeValues(data, typeof(ResourceIDAttribute), resourceList); foreach (FieldAttributeValue fa in resourceList) { if (fa.FieldValue != null) { resources.Put(fa.FieldValue as string, fa); } } } } #endregion //--------------------------------------------------------------------------------------------------- #region Localization public static string GenLocalizationCsv(EditorTemplatesData templates, AtomicFloat percent = null) { StringBuilder sb = new StringBuilder(); List list = templates.AllTemplates(); int i = 0; foreach (object obj in list) { GenLocalizationCsv(obj as ITemplateData, sb); if (percent != null) { percent.GetAndSet(((float)i) / list.Count); } i++; } return sb.ToString(); } public static void GenLocalizationCsv(ITemplateData data, StringBuilder sb) { UmlDocument uml = new UmlDocument(data); UmlValueNode node = uml.DocumentElement; GenLocalizationCsv(data, node, sb); } public static void GenLocalizationCsv(ITemplateData data, UmlValueNode node, StringBuilder sb) { if (node.IsLeaf) { if (node.Value is string && node.OwnerIndexer is FieldInfo) { FieldInfo field = node.OwnerIndexer as FieldInfo; LocalizationTextAttribute tattr = PropertyUtil.GetAttribute(field); if (tattr != null) { StringBuilder line = new StringBuilder(); { line.Append("\"," + node.Value); UmlValueNode it = node; while (!it.IsRoot) { UmlValueNode vt = it as UmlValueNode; line.Insert(0, ";"); line.Insert(0, vt.Name); if (it.ParentNode is UmlValueNode) { it = it.ParentNode as UmlValueNode; } else { break; } } line.Insert(0, "\""); } sb.Append("\"" + data.GetType().FullName + "\","); sb.Append("" + data.TemplateID + ","); sb.AppendLine(line.ToString()); } } } else { foreach (UmlValueNode sub in node.ChildNodes) { GenLocalizationCsv(data, sub, sb); } } } public static void LoadLocalizationCsv(EditorTemplatesData templates, string csv_text, AtomicInteger progress = null) { CsvTable table = new CsvTable(); table.LoadFromText(csv_text); LoadLocalizationCsv(templates, table, progress); } public static void LoadLocalizationCsv(EditorTemplatesData templates, CsvTable table, AtomicInteger progress = null) { for (int r = 0; r < table.MaxRow; r++) { if (table.Cells[r].Length >= 4) { string stype = table.GetCell(0, r); string stpid = table.GetCell(1, r); string sline = table.GetCell(2, r); string stext = table.GetCell(3, r); Type type = ReflectionUtil.GetType(stype); int templateID = int.Parse(stpid); object data; if (templates.GetObjectByType(type, templateID, out data)) { UmlDocument uml = new UmlDocument(data); UmlValueNode node = uml.DocumentElement; LoadLocalizationCsv(data as ITemplateData, node, sline, stext); } } if (progress != null) progress.IncrementAndGet(); } } public static void LoadLocalizationCsv(ITemplateData data, UmlValueNode node, string line, string value) { string[] kvs = line.Split(';'); foreach (string key in kvs) { node = node.GetChild(key) as UmlValueNode; if (node.IsLeaf) { UmlValueNode owner = node.ParentNode as UmlValueNode; owner.SetFieldValue(node, value); return; } } } #endregion //--------------------------------------------------------------------------------------------------- } }