using CommonLang; using CommonLang.IO; using CommonLang.Log; using CommonLang.Xml; using CommonUI.Data; using CommonUnity3D.UGUI; using CommonUnity3D.UGUIEditor.UI; using System; using System.Collections.Generic; using System.Xml; using UnityEngine; using AbstractLoader = CommonUI.Loader.AbstractLoader; using UnityImage = CommonUI_Unity3D.Impl.UnityImage; using UnityDriver = CommonUI_Unity3D.Impl.UnityDriver; using CommonUI.Display.Text; namespace CommonUnity3D.UGUIEditor { public class UIEditor : UIFactory { #region _全局设置_ public static bool GlobalUseBitmapText { get; set; } #endregion //------------------------------------------------------------------------------------------------ public delegate UIComponent UIComponentCreater(UIComponentMeta meta); public sealed class Decoder { public UIEditor editor {get;private set; } public UIComponentCreater creater { get; private set; } internal Decoder(UIEditor e, UIComponentCreater r) { this.editor = e; this.creater = r; } public UIComponent CreateFromFile(string path) { return editor.CreateFromFile(path, this); } public UIComponent CreateFromMeta(UIComponentMeta meta) { return editor.CreateFromMeta(meta, this); } public UILayout CreateLayout(UILayoutMeta e) { return editor.CreateLayout(e); } public UnityEngine.Font CreateFont(string fontName) { return editor.CreateFont(fontName); } } //------------------------------------------------------------------------------------------------ private readonly CommonLang.Log.Logger log; protected HashMap mImageMap = new HashMap(); protected HashMap mMetaMap = new HashMap(); public string ResRoot { get; private set; } public string Root { get; private set; } public UIEditor(string root) { if (!root.EndsWith("/")) { root += "/"; } this.Root = root; this.ResRoot = root + "res/"; this.log = LoggerFactory.GetLogger("UIEditor"); switch (Application.platform) { case RuntimePlatform.WindowsEditor: case RuntimePlatform.WindowsPlayer: case RuntimePlatform.WindowsWebPlayer: break; case RuntimePlatform.WP8Player: UnityDriver.UnityInstance.RedirectImage = this.RedirectImage_DXT; break; case RuntimePlatform.Android: UnityDriver.UnityInstance.RedirectImage = this.RedirectImage_ETC; break; case RuntimePlatform.IPhonePlayer: UnityDriver.UnityInstance.RedirectImage = this.RedirectImage_PVR; break; } } protected virtual UIComponent CreateComponent(UIComponentMeta meta) { switch (meta.ClassName) { case UIEditorMeta.UERoot_ClassName: return new UERoot(); case UIEditorMeta.UEButton_ClassName: return new UETextButton(); case UIEditorMeta.UEToggleButton_ClassName: return new UEToggleButton(); case UIEditorMeta.UEImageBox_ClassName: return new UEImageBox(); case UIEditorMeta.UECheckBox_ClassName: return new UECheckBox(); case UIEditorMeta.UELabel_ClassName: return new UELabel(); case UIEditorMeta.UECanvas_ClassName: return new UECanvas(); case UIEditorMeta.UEGauge_ClassName: return new UEGauge(); case UIEditorMeta.UEFileNode_ClassName: return new UEFileNode(); case UIEditorMeta.UEScrollPan_ClassName: return new UEScrollPan(); case UIEditorMeta.UETextInput_ClassName: return new UETextInput(); case UIEditorMeta.UETextInputMultiline_ClassName: return new UETextInputMultiline(); case UIEditorMeta.UETextBox_ClassName: return new UETextBox(); case UIEditorMeta.UETextBoxHtml_ClassName: return new UETextBoxHtml(); default: return new UECanvas(); } } protected virtual UIComponent CreateFromFile(string path, Decoder decoder) { UIComponentMeta meta = AddMeta(Root + FormatSubPath(path)); if (meta != null) { UIComponent ui = CreateFromMeta(meta, decoder); if (ui != null) { ui.Name = path; } return ui; } return null; } protected virtual UIComponent CreateFromMeta(UIComponentMeta meta, Decoder decoder) { UIComponent ui = null; if (decoder.creater != null) { ui = decoder.creater(meta); } if (ui == null) { ui = CreateComponent(meta); } if (ui != null) { ui.DecodeFromXML(decoder, meta); } return ui; } /// /// 从路径加载UI界面 /// /// /// 自定义构建UI节点代理 /// public virtual UIComponent CreateFromFile(string path, UIComponentCreater creater = null) { return CreateFromFile(path, new Decoder(this, creater)); } /// /// 从元数据加载UI界面 /// /// /// 自定义构建UI节点代理 /// public virtual UIComponent CreateFromMeta(UIComponentMeta meta, UIComponentCreater creater = null) { return CreateFromMeta(meta, new Decoder(this, creater)); } public virtual UILayout CreateLayout(UILayoutMeta e) { if (e == null) return null; UILayout layout = new UILayout(); layout.DecodeFromXML(this, e); return layout; } public virtual UnityEngine.Font CreateFont(string fontName) { return DefaultFont; } //------------------------------------------------------------------------------------------------------------------------------- /// /// 从字符串格式获取图片字 /// /// "^number/output/number.xml|Texts" /// /// public UGUI.ImageFontSprite ParseImageFont(string image_font, string text) { if (image_font.StartsWith("^")) { image_font = image_font.Substring(1); string[] args = image_font.Split('|'); string a_name = args[0]; string a_tg = args[1]; CommonUI.Cell.CPJAtlas mAtlas = this.GetAtlas(a_name, a_tg); if (mAtlas != null) { UGUI.ImageFontSprite ret = new UGUI.ImageFontSprite(image_font); ret.Text = text; ret.SetAtlas(mAtlas); return ret; } } return null; } /// /// 从字符串格式获取图片字 /// /// "^number/output/number.xml|Texts" /// /// /// public bool ParseImageFont(string image_font, string text, ImageFontGraphics imageFont) { if (image_font.StartsWith("^")) { image_font = image_font.Substring(1); string[] args = image_font.Split('|'); string a_name = args[0]; string a_tg = args[1]; CommonUI.Cell.CPJAtlas mAtlas = this.GetAtlas(a_name, a_tg); if (mAtlas != null) { imageFont.Text = text; imageFont.Atlas = (mAtlas); return true; } } return false; } /// /// 从字符串格式获取图片精灵 /// /// "#dynamic/effects/skill/skilllevelup.xml|skill_levelup1|21" /// /// public UGUI.ImageSprite ParseImageSpriteFromAtlas(string atlas_name, Vector2 pivot) { if (atlas_name.StartsWith("#")) { CommonUI.Gemo.Rectangle2D region; CommonUI_Unity3D.Impl.UnityImage src = ParseAtlasTile(atlas_name, out region); if (src != null) { var ret = new UGUI.ImageSprite(atlas_name); ret.SetImage(src, new Rect(region.x, region.y, region.width, region.height), pivot); ret.mTransform.sizeDelta = new Vector2(region.width, region.height); return ret; } } return null; } /// /// 从字符串格式获取图片精灵 /// /// "static/off_down.png" /// /// public UGUI.ImageSprite ParseImageSpriteFromImage(string image_name, Vector2 pivot) { if (!string.IsNullOrEmpty(image_name)) { CommonUI_Unity3D.Impl.UnityImage src = GetImage(image_name); if (src != null) { var ret = new UGUI.ImageSprite(image_name); ret.SetImage(src, new Rect(0, 0, src.Width, src.Height), pivot); ret.mTransform.sizeDelta = new Vector2(src.Width, src.Height); return ret; } } return null; } /// /// 从字符串格式获取图集 /// /// "#dynamic/effects/skill/skilllevelup.xml|skill_levelup1|21" /// /// public CommonUI_Unity3D.Impl.UnityImage ParseAtlasTile(string atlas_name, out CommonUI.Gemo.Rectangle2D outRegion) { if (atlas_name.StartsWith("#")) { atlas_name = atlas_name.Substring(1); string[] args = atlas_name.Split('|'); string a_name = args[0]; string a_tg = args[1]; int mAtlasTileID = int.Parse(args[2]); CommonUI.Cell.CPJAtlas mAtlas = this.GetAtlas(a_name, a_tg); if (mAtlas != null) { CommonUI_Unity3D.Impl.UnityImage outImage = mAtlas.GetTile(mAtlasTileID) as UnityImage; if (outImage != null) { outRegion = mAtlas.GetAtlasRegion(mAtlasTileID); return outImage; } } } outRegion = null; return null; } /// /// 从字符串格式获取图集 /// /// "#dynamic/effects/skill/skilllevelup.xml|skill_levelup1|21" /// /// public UnityEngine.Sprite ParseAtlasTile(string atlas_name, Vector2 pivot) { if (atlas_name.StartsWith("#")) { atlas_name = atlas_name.Substring(1); string[] args = atlas_name.Split('|'); string a_name = args[0]; string a_tg = args[1]; int mAtlasTileID = int.Parse(args[2]); CommonUI.Cell.CPJAtlas mAtlas = this.GetAtlas(a_name, a_tg); if (mAtlas != null) { CommonUI_Unity3D.Impl.UnityImage src = mAtlas.GetTile(mAtlasTileID) as UnityImage; if (src != null) { CommonUI.Gemo.Rectangle2D clip = mAtlas.GetAtlasRegion(mAtlasTileID); return UIUtils.CreateSprite(src, new Rect(clip.x, clip.y, clip.width, clip.height), pivot); } } } return null; } /// /// 从字符串格式获取精灵 /// /// "@actor_001010/output/actor.xml|actor_001010|001010|3" /// /// public CommonUI.Cell.Game.CSpriteMeta ParseSpriteMeta(string spr_name, out int animIndex) { if (spr_name.StartsWith("@")) { spr_name = spr_name.Substring(1); string[] args = spr_name.Split('|'); if (args.Length >= 4) { string a_xml_name = args[0]; string a_img_name = args[1]; string a_spr_name = args[2]; animIndex = int.Parse(args[3]); CommonUI.Cell.CPJResource cpj_res = GetCPJResource(a_xml_name); if (cpj_res != null) { CommonUI.Cell.Game.CSpriteMeta spr_meta = cpj_res.GetSpriteMeta(a_spr_name); return spr_meta; } } } animIndex = 0; return null; } //------------------------------------------------------------------------------------------------------------------------------- /// /// 获取 UI XML 对应的单张图片 /// /// /// public CommonUI_Unity3D.Impl.UnityImage GetImage(string image_file_name) { string full_path = ResRoot + FormatSubPath(image_file_name); var img = AddImage(full_path); return img; } /// /// 获取 UI XML 对应的CPJ的图集 /// /// /// /// public CommonUI.Cell.CPJAtlas GetAtlas(string cpj_file_name, string atlas_name) { var cpj = GetCPJResource(cpj_file_name); if (cpj != null) { return cpj.GetAtlas(atlas_name); } return null; } /// /// 获取 CPJ 资源 /// /// /// public CommonUI.Cell.CPJResource GetCPJResource(string cpj_file_name) { string full_path = ResRoot + FormatSubPath(cpj_file_name); var cpj = AddAtlas(full_path); return cpj; } public CommonUI.Cell.Game.CSpriteMeta GetSpriteMeta(string cpj_file_name, string spr_name) { CommonUI.Cell.CPJResource cpj_res = GetCPJResource(cpj_file_name); if (cpj_res != null) { CommonUI.Cell.Game.CSpriteMeta spr_meta = cpj_res.GetSpriteMeta(spr_name); return spr_meta; } return null; } public virtual UIComponentMeta GetUIMeta(string path) { return AddMeta(Root + FormatSubPath(path)); } //------------------------------------------------------------------------------------------------------------------------------- #region _富文本_ public override UGUIRichTextLayer CreateRichTextLayer(DisplayNode parent, bool use_bitmap) { return new EditorRichTextLayer(this, parent, use_bitmap); } public class EditorRichTextLayer : UGUIRichTextLayer { private readonly UIEditor mEditor; public EditorRichTextLayer(UIEditor editor, DisplayNode parent, bool use_bitmap_font) : base(parent, use_bitmap_font) { this.mEditor = editor; } protected override CommonUI.Display.Image AddImage(string file) { CommonUI.Display.Image ret = mEditor.GetImage(file); if (ret == null) { ret = base.AddImage(file); } return ret; } protected override CommonUI.Cell.CPJResource AddCPJResource(string file) { var ret = mEditor.GetCPJResource(file); if (ret == null) { ret = base.AddCPJResource(file); } return ret; } } #endregion //------------------------------------------------------------------------------------------------------------------------------- #region _图片缓冲_ protected virtual string RedirectImage_ETC(string path) { string etc = path.Substring(0, path.LastIndexOf('.')) + ".etc.m3z"; if (Resource.ExistData(etc)) { return etc; } return path; } protected virtual string RedirectImage_PVR(string path) { string pvr = path.Substring(0, path.LastIndexOf('.')) + ".pvr.m3z"; if (Resource.ExistData(pvr)) { return pvr; } return path; } protected virtual string RedirectImage_DXT(string path) { string dxt = path.Substring(0, path.LastIndexOf('.')) + ".dxt.m3z"; if (Resource.ExistData(dxt)) { return dxt; } return path; } /// /// 格式化完整路劲 /// /// /// protected virtual string FormatPath(string path) { path = path.Replace('\\', '/'); return path; } /// /// 格式化子路劲 /// /// /// protected virtual string FormatSubPath(string sub_path) { if (sub_path.StartsWith("/")) { return sub_path.Substring(1); } return sub_path; } /// /// 添加XML和二进制映射 /// /// /// protected virtual UIComponentMeta AddMeta(string path) { UIComponentMeta ret = null; try { path = FormatPath(path); if (!mMetaMap.TryGetValue(path, out ret)) { string bin_path = path.Substring(0, path.LastIndexOf(".gui.xml")) + ".gui.bin"; // 临时写法 UI全部翻皮完成之后去掉 add by haog 2017-2-6 string strTemp = bin_path; bin_path = bin_path.Replace("xml/", "xmds_ui/");// 先从新的目录读取 读取不到再去老的目录查找 if (!Resource.ExistData(bin_path)) { bin_path = strTemp; } // 临时写法 end if (Resource.ExistData(bin_path)) { var input = Resource.LoadDataAsStream(bin_path); if (input == null) { return null; } try { ret = UIEditorMeta.CreateFromStream(input); if (ret != null) { mMetaMap.Put(path, ret); return ret; } } finally { input.Dispose(); } } // 临时写法 UI全部翻皮完成之后去掉 add by haog 2017-2-6 strTemp = path; path = path.Replace("xml/", "xmds_ui/");// 先从新的目录读取 读取不到再去老的目录查找 XmlDocument xml = XmlUtil.LoadXML(path); if (xml == null) { path = strTemp; } // 临时写法 end xml = XmlUtil.LoadXML(path); if (xml != null) { ret = UIEditorMeta.CreateFromXml(xml); if (ret != null) { mMetaMap.Put(path, ret); return ret; } } } } catch (Exception err) { log.Error(err.Message, err); } return ret; } /// /// 清理XML二进制映射 /// public virtual void CleanMetaMap() { mMetaMap.Clear(); } protected virtual UnityImage AddImage(string path) { try { path = FormatPath(path); AbstractLoader temp = null; if (!mImageMap.TryGetValue(path, out temp)) { temp = new CommonUI.Editor.ImageLoader(path); mImageMap.Put(path, temp); } return temp.GetImage(path) as UnityImage; } catch (Exception err) { log.Error(err.Message, err); } return null; } protected virtual CommonUI.Cell.CPJResource AddAtlas(string path) { try { path = FormatPath(path); AbstractLoader temp = null; if (!mImageMap.TryGetValue(path, out temp)) { temp = new CommonUI.Loader.AtlasLoader(path); mImageMap.Put(path, temp); } return temp.GetAtlasResource(path); } catch (Exception err) { log.Error(err.Message, err); } return null; } /// /// 清理缓存的图片 /// public virtual void CleanImageMap() { foreach (KeyValuePair kvp in mImageMap) { kvp.Value.Dispose(); } mImageMap.Clear(); } /// /// 释放ui中标记为支持释放(默认)的UnityImage中的指定路径的Texture /// 当重新被使用时会自动重新加载 /// public void ReleaseTexture(string path) { if (string.IsNullOrEmpty(path)) return; string full_path = ResRoot + FormatSubPath(path); full_path = FormatPath(full_path); AbstractLoader temp; if (mImageMap.TryGetValue(full_path, out temp)) { temp.ReleaseTexture(); } } /// /// 释放ui中标记为支持释放(默认)的UnityImage中的Texture /// 当重新被使用时会自动重新加载 /// public void ReleaseAllTexture() { foreach (var item in mImageMap) { item.Value.ReleaseTexture(); } } #endregion } }