/* <copyright> This file contains proprietary software owned by Motorola Mobility, Inc.<br/> No rights, expressed or implied, whatsoever to this software are provided by Motorola Mobility, Inc. hereunder.<br/> (c) Copyright 2011 Motorola Mobility, Inc. All Rights Reserved. </copyright> */ var MaterialsModel = require("js/models/materials-model").MaterialsModel; /////////////////////////////////////////////////////////////////////// // Class GLGeomObj // Super class for all geometry classes /////////////////////////////////////////////////////////////////////// var GeomObj = function GLGeomObj() { /////////////////////////////////////////////////////////////////////// // Constants /////////////////////////////////////////////////////////////////////// this.GEOM_TYPE_RECTANGLE = 1; this.GEOM_TYPE_CIRCLE = 2; this.GEOM_TYPE_LINE = 3; this.GEOM_TYPE_PATH = 4; this.GEOM_TYPE_CUBIC_BEZIER = 5; this.GEOM_TYPE_BRUSH_STROKE = 6; this.GEOM_TYPE_UNDEFINED = -1; // Needed for calculating dashed/dotted strokes this.DASH_LENGTH = 0.15; this.DOT_LENGTH = 0.05; this.GAP_LENGTH = 0.05; /////////////////////////////////////////////////////////////////////// // Instance variables /////////////////////////////////////////////////////////////////////// this._matrix = Matrix.I(4); this._next = undefined; this._prev = undefined; this._child = undefined; this._parent = undefined; this.m_world = null; // stroke and fill colors this._strokeColor = [0, 0, 0, 0]; this._fillColor = [0, 0, 0, 0]; // stroke and fill materials this._fillMaterial = null; this._strokeMaterial = null; // array of primitives - used in RDGE this._primArray = []; this._materialNodeArray = []; this._materialArray = []; this._materialTypeArray = []; // the transform node used by RDGE this._trNode = null; /////////////////////////////////////////////////////////////////////// // Property accessors /////////////////////////////////////////////////////////////////////// this.setWorld = function (world) { this.m_world = world; }; this.getWorld = function () { return this.m_world; }; this.getMatrix = function () { return this._matrix.slice(0); }; this.setMatrix = function (m) { this._matrix = m.slice(0); }; this.setNext = function (next) { this._next = next; }; this.getNext = function () { return this._next; }; this.setPrev = function (prev) { this._prev = prev; }; this.getPrev = function () { return this._prev; }; this.setChild = function (child) { this._child = child; }; this.getChild = function () { return this._child; }; this.setParent = function (parent) { this._parent = parent; }; this.getParent = function () { return this._parent; }; this.geomType = function () { return this.GEOM_TYPE_UNDEFINED; }; this.getPrimitiveArray = function () { return this._primArray; }; this.getMaterialNodeArray = function () { return this._materialNodeArray; }; this.getMaterialArray = function () { return this._materialArray; }; this.getTransformNode = function () { return this._trNode; }; this.setTransformNode = function (t) { this._trNode = t; }; this.setFillColor = function (c) { this.setMaterialColor(c, "fill"); }; this.setStrokeColor = function (c) { this.setMaterialColor(c, "stroke"); }; /////////////////////////////////////////////////////////////////////// // Methods /////////////////////////////////////////////////////////////////////// this.setMaterialColor = function (c, type) { var i = 0, nMats = 0; if (c) { if (c.gradientMode) { // Gradient support if (this._materialArray && this._materialTypeArray) { nMats = this._materialArray.length; } var stops = [], colors = c.color; var len = colors.length; // TODO - Current shaders only support 4 color stops if (len > 4) { len = 4; } for (var n = 0; n < len; n++) { var position = colors[n].position / 100; var cs = colors[n].value; var stop = [cs.r / 255, cs.g / 255, cs.b / 255, cs.a]; stops.push(stop); if (nMats === this._materialTypeArray.length) { for (i = 0; i < nMats; i++) { if (this._materialTypeArray[i] == type) { this._materialArray[i].setProperty("color" + (n + 1), stop.slice(0)); this._materialArray[i].setProperty("colorStop" + (n + 1), position); } } } } if (type === "fill") { this._fillColor = c; } else { this._strokeColor = c; } } else { if (type === "fill") { this._fillColor = c.slice(0); } else { this._strokeColor = c.slice(0); } if (this._materialArray && this._materialTypeArray) { nMats = this._materialArray.length; if (nMats === this._materialTypeArray.length) { for (i = 0; i < nMats; i++) { if (this._materialTypeArray[i] == type) { this._materialArray[i].setProperty("color", c.slice(0)); } } } } } } else { if (type === "fill") { this._fillColor = null; } else { this._strokeColor = null; } if (this._materialArray && this._materialTypeArray) { nMats = this._materialArray.length; if (nMats === this._materialTypeArray.length) { for (i = 0; i < nMats; i++) { if (this._materialTypeArray[i] == type) { // TODO - Not sure how to set color to null values in shaders this._materialArray[i].setProperty("color", [0, 0, 0, 0]); } } } } } var world = this.getWorld(); if (world) { world.restartRenderLoop(); } }; this.makeStrokeMaterial = function () { var strokeMaterial; if (this.getStrokeMaterial()) { strokeMaterial = this.getStrokeMaterial().dup(); } else { strokeMaterial = MaterialsModel.exportFlatMaterial(); } if (strokeMaterial) { strokeMaterial.init(this.getWorld()); } this._materialArray.push(strokeMaterial); this._materialTypeArray.push("stroke"); if (this._strokeColor) { this.setStrokeColor(this._strokeColor); } return strokeMaterial; }; this.makeFillMaterial = function () { var fillMaterial; if (this.getFillMaterial()) { fillMaterial = this.getFillMaterial().dup(); } else { fillMaterial = MaterialsModel.exportFlatMaterial(); } if (fillMaterial) { fillMaterial.init(this.getWorld()); } this._materialArray.push(fillMaterial); this._materialTypeArray.push("fill"); if (this._fillColor) { this.setFillColor(this._fillColor); } return fillMaterial; }; this.exportMaterialsJSON = function () { var jObj; if (this._materialArray && this._materialNodeArray && this.getWorld().isWebGL()) { var nMats = this._materialArray.length; if (nMats > 0) { var arr = []; for (var i = 0; i < nMats; i++) { var matObj = { 'materialNodeName':this._materialNodeArray[i].name, 'material':this._materialArray[i].exportJSON(), 'type':this._materialTypeArray[i] } arr.push(matObj); } jObj = { 'nMaterials':nMats, 'materials':arr }; } } return jObj; } this.importMaterialsJSON = function (jObj) { this._materialArray = []; this._materialTypeArray = []; if (!jObj) return; var nMaterials = jObj.nMaterials; var matArray = jObj.materials; for (var i = 0; i < nMaterials; i++) { var mat; var matObj = matArray[i].material; var shaderName = matObj.material; switch (shaderName) { case "flat": case "radialGradient": case "linearGradient": case "bumpMetal": case "uber": case "plasma": case "deform": case "water": case "paris": case "raiders": case "tunnel": case "reliefTunnel": case "squareTunnel": case "twist": case "fly": case "julia": case "mandel": case "star": case "zinvert": case "keleidoscope": case "radialBlur": case "pulse": mat = MaterialsModel.getMaterialByShader(shaderName); if (mat) mat = mat.dup(); break; default: console.log("material type: " + shaderName + " is not supported"); break; } if (mat) { mat.importJSON(matObj); this._materialArray.push(mat); this._materialTypeArray.push(matObj.type); var type = matArray[i].type; if (type == "fill") this._fillMaterial = mat; else this._strokeMaterial = mat; } } }; this.translate = function (v) { var mat = Matrix.Translation(v); //var mat2 = mat.multiply( this._matrix ); //this._matrix = mat2; glmat4.multiply(mat, this._matrix, this._matrix); }; this.transform = function (mat) { if (mat) { //this._matrix = mat.multiply( this._matrix ); glmat4.multiply(mat, this._matrix, this._matrix); } }; this.setMatrix = function (mat) { var gl = this.getWorld().getGLContext(); if (gl) { gl.uniformMatrix4fv(this.getWorld().getShaderProgram().mvMatrixUniform, false, new Float32Array(mat)); } }; this.buildBuffers = function () { // this function must be overridden by the base class alert("GLGeomObj.buildBuffers must be overridden by base class"); }; this.render = function () { alert("GLGeomObj.render method must be overridden by sub class"); }; this.collidesWithPoint = function (x, y) { alert("GLGeomObj.collidesWithPoint method must be overridden by sub class"); }; this.getNearPoint = function (pt, dir) { // the alert is not displayed. Objects may choose not to implement this method. //alert( "GLGeomObj.getNearPoint method must be overridden by sub class" ); }; this.getNearVertex = function (pt, dir) { // this should be overridden by objects (such as rectangles) that have corners }; this.containsPoint = function (pt, dir) { // the alert is not displayed. Objects may choose not to implement this method. //alert( "GLGeomObj.containsPoint method must be overridden by sub class" ); }; this.getPropertyFromString = function (prop, str) { var index = str.indexOf(prop); if (index < 0) throw new Error("property " + prop + " not found in string: " + str); var rtnStr = str.substr(index + prop.length); index = rtnStr.indexOf("\n"); if (index >= 0) { rtnStr = rtnStr.substr(0, index); } return rtnStr; }; // Gradient stops for rgba(255,0,0,1) at 0%; rgba(0,255,0,1) at 33%; rgba(0,0,255,1) at 100% will return // 255,0,0,1@0;0,255,0,1@33;0,0,255,1@100 this.gradientToString = function (colors) { var rtnStr = ""; if (colors && colors.length) { var c = colors[0], len = colors.length; rtnStr += String(c.value.r + "," + c.value.g + "," + c.value.b + "," + c.value.a + "@" + c.position); for (var i = 1; i < len; i++) { c = colors[i]; rtnStr += ";" + String(c.value.r + "," + c.value.g + "," + c.value.b + "," + c.value.a + "@" + c.position); } } return rtnStr; }; // Given a gradientStr "255,0,0,1@0;0,255,0,1@33;0,0,255,1@100" will return: // colors array [{position:0, value:{r:255, g:0, b:0, a:1}}, // {position:33, value:{r:0, g:255, b:0, a:1}}, // {position:100, value:{r:0, g:0, b:255, a:1}} // ] this.stringToGradient = function (gradientStr) { var rtnArr = []; var i, len, stops, stop, c; stops = gradientStr.split(";"); len = stops.length; for (i = 0; i < len; i++) { stop = stops[i].split("@"); c = stop[0].split(","); rtnArr.push({ position:Number(stop[1]), value:{r:Number(c[0]), g:Number(c[1]), b:Number(c[2]), a:Number(c[3])} }); } return rtnArr; }; /* this.export = function() { var rtnStr; return rtnStr; } */ }; if (typeof exports === "object") { exports.GeomObj = GeomObj; }