UNPKG

dragonbones-runtime

Version:

the tools to build dragonbones file for diffrent framework

614 lines (577 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" /> import file = require("../FileUtil"); import xml = require("../xml/index"); import CodeUtil = require("./code_util"); import create_manifest = require("./createManifest"); var properties = {}; var stylesMap = {}; class EXMLConfig{ /** * Egret命名空间 */ public static E:string = "http://ns.egret-labs.org/egret"; /** * Wing命名空间 */ public static W:string = "http://ns.egret-labs.org/wing"; /** * 构造函数 */ public constructor() { var exmlPath: string = egret.root + "/tools/lib/exml/"; exmlPath = exmlPath.split("\\").join("/"); var str:string = file.read(exmlPath+"egret-manifest.xml"); var manifest:any = xml.parse(str); this.parseManifest(manifest); str = file.read(exmlPath+"properties.json"); properties = JSON.parse(str); this.findStyles(properties); } public static getInstance():EXMLConfig { if (!exmlConfig) { exmlConfig = new EXMLConfig(); } return exmlConfig; } private findStyles(properties:any):void{ var data:any = properties["styles"]; if(!data){ return; } for(var key in data){ var classData:any = properties[key]; if(!classData){ continue; } var list:Array<string> = data[key]; var length:number = list.length; for(var i:number=0;i<length;i++){ var prop:string = list[i]; var type:string = classData[prop]; if(type){ stylesMap[prop] = type; } } } } private _srcPath:string; public get srcPath():string{ return this._srcPath; } public set srcPath(value:string){ this._srcPath = value; this.classNameToPath = create_manifest.getClassToPathInfo(this.srcPath); this.parseModules(); } private classNameToPath:any; private classNameToModule:any; /** * 组件清单列表 */ public componentDic:any = {}; public idMap:any = {}; private parseModules():void{ this.classNameToModule = {}; for(var className in this.classNameToPath){ var index:number = className.lastIndexOf("."); var ns:string = ""; if(index!=-1){ ns = className.substring(0,index); className = className.substring(index+1); } var list:Array<string> = this.classNameToModule[className]; if(!list){ list = this.classNameToModule[className] = []; } if(ns&&list.indexOf(ns)==-1){ list.push(ns); } } } /** * 解析框架清单文件 */ public parseManifest(manifest:any):void{ var children:Array<any> = manifest.children; var length:number = children.length; for(var i:number=0;i<length;i++){ var item:any = children[i]; var component:Component = new Component(item); this.componentDic[component.className] = component; this.idMap[component.id] = component.className; } for(var className in this.componentDic){ var component:Component = this.componentDic[className]; if(!component.defaultProp) this.findProp(component); } } /** * 递归查找默认属性 */ private findProp(component:Component):string{ if(component.defaultProp) return component.defaultProp; var superComp:Component = this.componentDic[component.superClass]; if(superComp){ var prop:string = this.findProp(superComp); if(prop){ component.defaultProp = prop; } } return component.defaultProp; } /** * @inheritDoc */ public getClassNameById(id:string, ns:string):string{ var name:string = ""; 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; } /** * 检查一个类名是否存在 */ public checkClassName(className:string):boolean{ if(!className){ return false; } if(this.componentDic[className]){ return true; } if(this.classNameToPath[className]){ return true; } return false; } /** * @inheritDoc */ public getDefaultPropById(id:string, ns:string):string{ var className:string = this.getClassNameById(id,ns); var component:Component = this.componentDic[className]; if(!component&&className){ component = this.findDefaultProp(className); } if(!component) return ""; return component.defaultProp; } private findDefaultProp(className:string):Component{ var classData:any = properties[className]; if(!classData){ var path:string = this.classNameToPath[className]; var ext:string = file.getExtension(path).toLowerCase(); var text:string = 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:string = classData["super"]; var component:Component = this.componentDic[superClass]; if(!component){ component = this.findDefaultProp(superClass); } return component; } /** * 指定的属性是否为样式属性 */ public isStyleProperty(prop:string,className:string):boolean { var type:String = this.findType(className,prop); return !type&&this.checkStyleProperty(prop,className); } private checkStyleProperty(prop:string,className:string):boolean { return (this.isInstanceOf(className,"egret.gui.IStyleClient")&&stylesMap[prop]); } /** * 获取指定类指定属性的类型 */ public getPropertyType(prop:string,className:string):string{ if(className=="Object"){ return "any"; } var type:string = this.findType(className,prop); if(!type){ if(this.checkStyleProperty(prop,className)){ return stylesMap[prop]; } } return type; } private findType(className:string,prop:string):string{ var classData:any = properties[className]; if(!classData){ var path:string = this.classNameToPath[className]; var ext:string = file.getExtension(path).toLowerCase(); var text:string = 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:string = classData[prop]; if(!type){ type = this.findType(classData["super"],prop); } return type; } /** * 读取一个exml文件引用的类列表 */ private getPropertiesFromExml(text:string):any{ var exml:any = xml.parse(text); if(!exml){ return null; } var superClass:string = this.getClassNameById(exml.localName,exml.namespace); if(superClass){ var data:any = {}; data["super"] = superClass; return data; } return null; } /** * 获取属性列表 */ private getPropertiesFromTs(text:string,className:string,nsPrefiex:string):any { index = className.lastIndexOf("."); var moduleName:string = ""; if (index != -1) { moduleName = className.substring(0, index); className = className.substring(index+1); } var data:any; if(moduleName){ while(text.length>0){ var index:number = CodeUtil.getFirstVariableIndex("module",text); if(index==-1){ break; } text = text.substring(index+6); index = text.indexOf("{"); if(index==-1){ continue; } var ns:string = text.substring(0,index).trim(); text = text.substring(index); index = CodeUtil.getBracketEndIndex(text); if(index==-1) { break; } var block:string = 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:string = moduleName.substring(ns.length+1); var prefix:string = 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; } private getPropFromBlock(block:string,targetClassName:string,ns:string):any{ var data:any; while(block.length>0){ var index:number = CodeUtil.getFirstVariableIndex("class",block); if(index==-1){ break; } block = block.substring(index+5); index = block.indexOf("{"); var preStr:string = block.substring(0,index); block = block.substring(index); var className:string = CodeUtil.getFirstVariable(preStr); if(className!=targetClassName){ continue; } data = {}; preStr = CodeUtil.removeFirstVariable(preStr,className); var word:string = 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:Array<any> = preStr.split(","); for(var i:number = arr.length-1;i>=0;i--){ var inter:string = 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:string = block.substring(0,index+1); this.readProps(text,data,ns); break; } return data; } /** * 根据类类短名,和这个类被引用的时所在的module名来获取完整类名。 */ private getFullClassName(word:string,ns:string):string { if (!ns||!word) { return word; } var prefix:string = ""; var index:number = 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:string = 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; } private basicTypes:Array<any> = ["void","any","number","string","boolean","Object","Array","Function"]; private readProps(text:string,data:any,ns:string):void{ var lines:Array<any> = text.split("\n"); var length:number = lines.length; for(var i:number=0;i<length;i++){ var line:string = lines[i]; var index:number = CodeUtil.getFirstVariableIndex("public",line); if(index==-1) continue; line = line.substring(index+7); var word:string = 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:string = line.charAt(0); if(firstChar==":"){ var type:string = 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 */ public isInstanceOf(classNameA:string,classNameB:string):boolean{ if(classNameB=="any"||classNameB=="Class"){ return true; } if(classNameA==classNameB){ return true; } var dataA:any = properties[classNameA]; if(!dataA){ return false; } var list:Array<string> = dataA["implements"]; if(list){ var length:number = list.length; for(var i:number=0;i<length;i++){ if(list[i]==classNameB){ return true; } } } return this.isInstanceOf(dataA["super"],classNameB); } } class Component{ /** * 构造函数 */ public constructor(item?:any){ 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; } } /** * 短名ID */ public id:string; /** * 完整类名 */ public className:string; /** * 父级类名 */ public superClass:string = ""; /** * 默认属性 */ public defaultProp:string = ""; } var exmlConfig:EXMLConfig; export = EXMLConfig;