UNPKG

dragonbones-runtime

Version:

the tools to build dragonbones file for diffrent framework

569 lines (568 loc) 19.9 kB
/* * Copyright (c) 2014,egret.com * All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the egret.com nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY EGRET-LABS.ORG AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL EGRET-LABS.ORG AND CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /// <reference path="../types.d.ts" /> var file = require("../FileUtil"); var xml = require("../xml/index"); var CodeUtil = require("./code_util"); var create_manifest = require("./createManifest"); var properties = {}; var stylesMap = {}; var EXMLConfig = (function () { /** * 构造函数 */ function EXMLConfig() { /** * 组件清单列表 */ this.componentDic = {}; this.idMap = {}; this.basicTypes = ["void", "any", "number", "string", "boolean", "Object", "Array", "Function"]; var exmlPath = egret.root + "/tools/lib/exml/"; exmlPath = exmlPath.split("\\").join("/"); var str = file.read(exmlPath + "egret-manifest.xml"); var manifest = xml.parse(str); this.parseManifest(manifest); str = file.read(exmlPath + "properties.json"); properties = JSON.parse(str); this.findStyles(properties); } EXMLConfig.getInstance = function () { if (!exmlConfig) { exmlConfig = new EXMLConfig(); } return exmlConfig; }; EXMLConfig.prototype.findStyles = function (properties) { var data = properties["styles"]; if (!data) { return; } for (var key in data) { var classData = properties[key]; if (!classData) { continue; } var list = data[key]; var length = list.length; for (var i = 0; i < length; i++) { var prop = list[i]; var type = classData[prop]; if (type) { stylesMap[prop] = type; } } } }; Object.defineProperty(EXMLConfig.prototype, "srcPath", { get: function () { return this._srcPath; }, set: function (value) { this._srcPath = value; this.classNameToPath = create_manifest.getClassToPathInfo(this.srcPath); this.parseModules(); }, enumerable: true, configurable: true }); EXMLConfig.prototype.parseModules = function () { this.classNameToModule = {}; for (var className in this.classNameToPath) { var index = className.lastIndexOf("."); var ns = ""; if (index != -1) { ns = className.substring(0, index); className = className.substring(index + 1); } var list = this.classNameToModule[className]; if (!list) { list = this.classNameToModule[className] = []; } if (ns && list.indexOf(ns) == -1) { list.push(ns); } } }; /** * 解析框架清单文件 */ EXMLConfig.prototype.parseManifest = function (manifest) { var children = manifest.children; var length = children.length; for (var i = 0; i < length; i++) { var item = children[i]; var component = new Component(item); this.componentDic[component.className] = component; this.idMap[component.id] = component.className; } for (var className in this.componentDic) { var component = this.componentDic[className]; if (!component.defaultProp) this.findProp(component); } }; /** * 递归查找默认属性 */ EXMLConfig.prototype.findProp = function (component) { if (component.defaultProp) return component.defaultProp; var superComp = this.componentDic[component.superClass]; if (superComp) { var prop = this.findProp(superComp); if (prop) { component.defaultProp = prop; } } return component.defaultProp; }; /** * @inheritDoc */ EXMLConfig.prototype.getClassNameById = function (id, ns) { var name = ""; if (this.basicTypes.indexOf(id) != -1) { return id; } if (ns == EXMLConfig.W) { } else if (!ns || ns == EXMLConfig.E) { name = this.idMap[id]; } else { name = ns.substring(0, ns.length - 1) + id; if (!this.classNameToPath[name]) { name = ""; } } return name; }; /** * 检查一个类名是否存在 */ EXMLConfig.prototype.checkClassName = function (className) { if (!className) { return false; } if (this.componentDic[className]) { return true; } if (this.classNameToPath[className]) { return true; } return false; }; /** * @inheritDoc */ EXMLConfig.prototype.getDefaultPropById = function (id, ns) { var className = this.getClassNameById(id, ns); var component = this.componentDic[className]; if (!component && className) { component = this.findDefaultProp(className); } if (!component) return ""; return component.defaultProp; }; EXMLConfig.prototype.findDefaultProp = function (className) { var classData = properties[className]; if (!classData) { var path = this.classNameToPath[className]; var ext = file.getExtension(path).toLowerCase(); var text = file.read(path); if (ext == "ts") { classData = this.getPropertiesFromTs(text, className, ""); } else if (ext == "exml") { classData = this.getPropertiesFromExml(text); } if (classData) { properties[className] = classData; } else { return null; } } var superClass = classData["super"]; var component = this.componentDic[superClass]; if (!component) { component = this.findDefaultProp(superClass); } return component; }; /** * 指定的属性是否为样式属性 */ EXMLConfig.prototype.isStyleProperty = function (prop, className) { var type = this.findType(className, prop); return !type && this.checkStyleProperty(prop, className); }; EXMLConfig.prototype.checkStyleProperty = function (prop, className) { return (this.isInstanceOf(className, "egret.gui.IStyleClient") && stylesMap[prop]); }; /** * 获取指定类指定属性的类型 */ EXMLConfig.prototype.getPropertyType = function (prop, className) { if (className == "Object") { return "any"; } var type = this.findType(className, prop); if (!type) { if (this.checkStyleProperty(prop, className)) { return stylesMap[prop]; } } return type; }; EXMLConfig.prototype.findType = function (className, prop) { var classData = properties[className]; if (!classData) { var path = this.classNameToPath[className]; var ext = file.getExtension(path).toLowerCase(); var text = file.read(path); if (ext == "ts") { text = CodeUtil.removeComment(text, path); classData = this.getPropertiesFromTs(text, className, ""); } else if (ext == "exml") { classData = this.getPropertiesFromExml(text); } if (classData) { properties[className] = classData; } else { return ""; } } var type = classData[prop]; if (!type) { type = this.findType(classData["super"], prop); } return type; }; /** * 读取一个exml文件引用的类列表 */ EXMLConfig.prototype.getPropertiesFromExml = function (text) { var exml = xml.parse(text); if (!exml) { return null; } var superClass = this.getClassNameById(exml.localName, exml.namespace); if (superClass) { var data = {}; data["super"] = superClass; return data; } return null; }; /** * 获取属性列表 */ EXMLConfig.prototype.getPropertiesFromTs = function (text, className, nsPrefiex) { index = className.lastIndexOf("."); var moduleName = ""; if (index != -1) { moduleName = className.substring(0, index); className = className.substring(index + 1); } var data; if (moduleName) { while (text.length > 0) { var index = CodeUtil.getFirstVariableIndex("module", text); if (index == -1) { break; } text = text.substring(index + 6); index = text.indexOf("{"); if (index == -1) { continue; } var ns = text.substring(0, index).trim(); text = text.substring(index); index = CodeUtil.getBracketEndIndex(text); if (index == -1) { break; } var block = text.substring(0, index); text = text.substring(index); if (ns == moduleName) { if (nsPrefiex) { ns = nsPrefiex + "." + moduleName; } data = this.getPropFromBlock(block, className, ns); break; } else if (moduleName.indexOf(ns) == 0 && moduleName.charAt(ns.length) == ".") { var tail = moduleName.substring(ns.length + 1); var prefix = moduleName.substring(0, ns.length); if (nsPrefiex) { prefix = nsPrefiex + "." + prefix; } data = this.getPropertiesFromTs(block, tail + "." + className, prefix); if (data) { break; } } } } else { data = this.getPropFromBlock(text, className, nsPrefiex); } return data; }; EXMLConfig.prototype.getPropFromBlock = function (block, targetClassName, ns) { var data; while (block.length > 0) { var index = CodeUtil.getFirstVariableIndex("class", block); if (index == -1) { break; } block = block.substring(index + 5); index = block.indexOf("{"); var preStr = block.substring(0, index); block = block.substring(index); var className = CodeUtil.getFirstVariable(preStr); if (className != targetClassName) { continue; } data = {}; preStr = CodeUtil.removeFirstVariable(preStr, className); var word = CodeUtil.getFirstVariable(preStr); if (word == "extends") { preStr = CodeUtil.removeFirstVariable(preStr); word = CodeUtil.getFirstWord(preStr); if (word) { word = this.getFullClassName(word, ns); data["super"] = word; } preStr = CodeUtil.removeFirstWord(preStr); word = CodeUtil.getFirstVariable(preStr); } if (word == "implements") { preStr = CodeUtil.removeFirstVariable(preStr); var arr = preStr.split(","); for (var i = arr.length - 1; i >= 0; i--) { var inter = arr[i]; inter = inter.trim(); if (inter) { inter = this.getFullClassName(inter, ns); arr[i] = inter; } else { arr.splice(i, 1); } } data["implements"] = arr; } index = CodeUtil.getBracketEndIndex(block); if (index == -1) break; var text = block.substring(0, index + 1); this.readProps(text, data, ns); break; } return data; }; /** * 根据类类短名,和这个类被引用的时所在的module名来获取完整类名。 */ EXMLConfig.prototype.getFullClassName = function (word, ns) { if (!ns || !word) { return word; } var prefix = ""; var index = word.lastIndexOf("."); var nsList; if (index == -1) { nsList = this.classNameToModule[word]; } else { prefix = word.substring(0, index); nsList = this.classNameToModule[word.substring(index + 1)]; } if (!nsList) { return word; } var length = nsList.length; var targetNs = ""; for (var k = 0; k < length; k++) { var superNs = nsList[k]; if (prefix) { var tail = superNs.substring(superNs.length - prefix.length); if (tail == prefix) { superNs = superNs.substring(0, superNs.length - prefix.length - 1); } else { continue; } } if (ns.indexOf(superNs) == 0) { if (superNs.length > targetNs.length) { targetNs = superNs; } } } if (targetNs) { word = targetNs + "." + word; } return word; }; EXMLConfig.prototype.readProps = function (text, data, ns) { var lines = text.split("\n"); var length = lines.length; for (var i = 0; i < length; i++) { var line = lines[i]; var index = CodeUtil.getFirstVariableIndex("public", line); if (index == -1) continue; line = line.substring(index + 7); var word = CodeUtil.getFirstVariable(line); if (!word || word.charAt(0) == "_") continue; if (word == "get") { continue; } else if (word == "set") { line = CodeUtil.removeFirstVariable(line); word = CodeUtil.getFirstVariable(line); if (!word || word.charAt(0) == "_") { continue; } line = CodeUtil.removeFirstVariable(line); line = line.trim(); if (line.charAt(0) == "(") { index = line.indexOf(":"); if (index != -1) { line = line.substring(index + 1); index = line.indexOf(")"); type = line.substring(0, index); index = type.indexOf("<"); if (index != -1) { type = type.substring(0, index); } type = CodeUtil.trimVariable(type); if (this.basicTypes.indexOf(type) == -1) { type = this.getFullClassName(type, ns); } data[word] = type; } else { data[word] = "any"; } } } else { line = CodeUtil.removeFirstVariable(line); line = line.trim(); var firstChar = line.charAt(0); if (firstChar == ":") { var type = CodeUtil.getFirstWord(line.substring(1)); index = type.indexOf("="); if (index != -1) { type = type.substring(0, index); } index = type.indexOf("<"); if (index != -1) { type = type.substring(0, index); } type = CodeUtil.trimVariable(type); if (this.basicTypes.indexOf(type) == -1) { type = this.getFullClassName(type, ns); } data[word] = type; } else if (!line || firstChar == ";" || firstChar == "=") { data[word] = "any"; } } } }; /** * 检查classNameA是否是classNameB的子类或classNameA实现了接口classNameB */ EXMLConfig.prototype.isInstanceOf = function (classNameA, classNameB) { if (classNameB == "any" || classNameB == "Class") { return true; } if (classNameA == classNameB) { return true; } var dataA = properties[classNameA]; if (!dataA) { return false; } var list = dataA["implements"]; if (list) { var length = list.length; for (var i = 0; i < length; i++) { if (list[i] == classNameB) { return true; } } } return this.isInstanceOf(dataA["super"], classNameB); }; return EXMLConfig; }()); /** * Egret命名空间 */ EXMLConfig.E = "http://ns.egret-labs.org/egret"; /** * Wing命名空间 */ EXMLConfig.W = "http://ns.egret-labs.org/wing"; var Component = (function () { /** * 构造函数 */ function Component(item) { /** * 父级类名 */ this.superClass = ""; /** * 默认属性 */ this.defaultProp = ""; if (item) { this.id = item.$id; this.className = item["$module"] + "." + this.id; if (item["$super"]) this.superClass = item.$super; if (item["$default"]) this.defaultProp = item.$default; } } return Component; }()); var exmlConfig; module.exports = EXMLConfig;