From b8c27edc106818ff84f93ebe30ce50359a03885b Mon Sep 17 00:00:00 2001
From: Jose Antonio Marquez
Date: Mon, 7 May 2012 13:21:31 -0700
Subject: Adding webGL support for opening files

Added I/O for loading webGL on open file. I/O support for saving to come.
---
 js/document/document-html.js |  17 ++--
 js/document/models/base.js   |  13 +++
 js/document/models/html.js   | 197 ++++++++++++++++++++++++++++++++++++++++++-
 js/document/views/design.js  |  32 +++++--
 4 files changed, 242 insertions(+), 17 deletions(-)

(limited to 'js/document')

diff --git a/js/document/document-html.js b/js/document/document-html.js
index f3c135ed..79fe461b 100755
--- a/js/document/document-html.js
+++ b/js/document/document-html.js
@@ -63,7 +63,7 @@ exports.HtmlDocument = Montage.create(Component, {
 	////////////////////////////////////////////////////////////////////
 	//
     init: {
-        value:function(file, context, callback, view) {
+        value:function(file, context, callback, view, template) { //TODO: Add template support logic
         	//Storing callback data for loaded dispatch
         	this.loaded.callback = callback;
         	this.loaded.context = context;
@@ -85,16 +85,19 @@ exports.HtmlDocument = Montage.create(Component, {
             	this.model.views.design.show();
             	this.model.views.design.iframe.style.opacity = 0;
             	this.model.views.design.content = this.model.file.content;
+            	//TODO: Improve reference
+            	this.model.views.design.model = this.model;
+            	//
             	//TODO: Clean up
             	this.model.views.design.render(function () {
             		//TODO: Identify and remove usage of '_document'
             		this._document = this.model.views.design.document;
-    				//TODO: Check for needed
+    				//TODO: Remove usage, seems as not needed
             		this.documentRoot = this.model.views.design.document.body;
             		//TODO: Why is this needed?
-            		this._liveNodeList = this.documentRoot.getElementsByTagName('*');
+            		this._liveNodeList = this.model.views.design.document.body.getElementsByTagName('*');
             		//Initiliazing document model
-            		document.application.njUtils.makeElementModel(this.documentRoot, "Body", "body");
+            		document.application.njUtils.makeElementModel(this.model.views.design.document.body, "Body", "body");
             		//Adding observer to know when template is ready
             		this._observer = new WebKitMutationObserver(this.handleTemplateReady.bind(this));
         			this._observer.observe(this.model.views.design.document.head, {childList: true});
@@ -115,11 +118,7 @@ exports.HtmlDocument = Montage.create(Component, {
     	    this.loaded.callback.call(this.loaded.context, this);
     	    //Setting opacity to be viewable after load
 		   	this.model.views.design.iframe.style.opacity = 1;
-
-
-
-
-
+			//TODO: Remove, this is a temp hard-coded hack
             this.application.ninja.appModel.show3dGrid = true;
     	}
     }
diff --git a/js/document/models/base.js b/js/document/models/base.js
index 3bb69f6b..746922ad 100755
--- a/js/document/models/base.js
+++ b/js/document/models/base.js
@@ -72,6 +72,19 @@ exports.BaseDocumentModel = Montage.create(Component, {
         	//
         }
     },
+    ////////////////////////////////////////////////////////////////////
+	//
+	browserPreview: {
+        value: function (browser) {
+        	//
+        	switch (browser) {
+        		case 'chrome':
+        			break;
+        		default:
+        			break;
+        	}
+        }
+    },
     ////////////////////////////////////////////////////////////////////
 	//
 	save: {
diff --git a/js/document/models/html.js b/js/document/models/html.js
index 5eedb731..e0a18850 100755
--- a/js/document/models/html.js
+++ b/js/document/models/html.js
@@ -7,7 +7,10 @@ No rights, expressed or implied, whatsoever to this software are provided by Mot
 ////////////////////////////////////////////////////////////////////////
 //
 var Montage = 			require("montage/core/core").Montage,
-    BaseDocumentModel = require("js/document/models/base").BaseDocumentModel;
+    BaseDocumentModel = require("js/document/models/base").BaseDocumentModel,
+    MaterialsModel = 	require("js/models/materials-model").MaterialsModel,
+    NJUtils = 			require("js/lib/NJUtils").NJUtils,
+	GLWorld =			require("js/lib/drawing/world").World;
 ////////////////////////////////////////////////////////////////////////
 //	
 exports.HtmlDocumentModel = Montage.create(BaseDocumentModel, {
@@ -16,10 +19,198 @@ exports.HtmlDocumentModel = Montage.create(BaseDocumentModel, {
 	hasTemplate: {
         value: false
     },
-
+	////////////////////////////////////////////////////////////////////
+	//
     draw3DGrid: {
         value: false
-    }
+    },
+    ////////////////////////////////////////////////////////////////////
+	//
+    _glData: {
+    	value: null
+    },
+    ////////////////////////////////////////////////////////////////////
+	//
+    glData: {
+    	//
+    	get: function() {
+    		//
+			var elt = this.views.design.iframe.contentWindow.document.body;
+			//
+			if (elt) {
+				var matLib = MaterialsModel.exportMaterials();
+				this._glData = [matLib];
+				this.collectGLData(elt, this._glData );
+			} else {
+				this._glData = null
+			}
+			//	
+			return this._glData;
+		},
+		//
+        set: function(value) {
+        	//
+        	var elt = this.views.design.iframe.contentWindow.document.body;
+			//
+			if (elt) {
+				/*
+				// Use this code to test the runtime version of WebGL
+				var cdm = new NinjaCvsRt.CanvasDataManager();
+				cdm.loadGLData(elt,  value,  null );
+				*/
+
+				//
+				var i, nWorlds= value.length;
+				//
+				for (i = 0;  i < nWorlds;  i++) {
+					// get the data for the next canvas
+					var importStr = value[i], id, jObj, index = importStr.indexOf(';'), matLibStr, matLibObj, startIndex, endIndex, canvas, useWebGL, world;
+					// determine if it is the new (JSON) or old style format
+					if ((importStr[0] === 'v') && (index < 24)) {
+						// JSON format.  pull off the
+						importStr = importStr.substr(index+1);
+						jObj = JSON.parse(importStr);
+						id = jObj.id;
+					} else {
+                        // at this point the data could be either the materials library or
+                        // an old style world.  We can determine which by converting the string
+                        // to an object via JSON.parse.  That operation will fail if the string
+                        // is an old style world.
+                        matLibStr = 'materialLibrary;';
+                        index = importStr.indexOf(matLibStr);
+                        if (index == 0) {
+                            importStr = importStr.substr(matLibStr.length);
+                            matLibObj = JSON.parse(importStr);
+                            MaterialsModel.importMaterials(matLibObj);
+                        } else {
+						    startIndex = importStr.indexOf("id: ");
+						    if (startIndex >= 0) {
+							    endIndex = importStr.indexOf("\n", startIndex);
+							    if (endIndex > 0) id = importStr.substring(startIndex+4, endIndex);
+						    }
+                        }
+					}
+					//
+					if (id != null) {
+						//
+						canvas = this.findCanvasWithID(id, elt);
+						//
+						if (canvas) {
+							//
+							if (!canvas.elementModel) {
+								NJUtils.makeElementModel(canvas, "Canvas", "shape", true);
+							}
+							//
+							if (canvas.elementModel) {
+								if (canvas.elementModel.shapeModel.GLWorld) {
+									canvas.elementModel.shapeModel.GLWorld.clearTree();
+								}
+								//
+								if (jObj) {
+									useWebGL = jObj.webGL;
+									world = new GLWorld(canvas, useWebGL);
+									world.importJSON(jObj);
+								}
+								//
+								this.buildShapeModel(canvas.elementModel, world);
+							}
+						}
+					}
+				}
+			}
+		}
+    },
+    ////////////////////////////////////////////////////////////////////
+	//
+    findCanvasWithID:  {
+		value: function(id, elt)  {
+			//
+			var i, child, nKids, foundElt, cid = elt.getAttribute("data-RDGE-id");
+			//
+			if (cid == id)  return elt;
+			//
+			if (elt.children) {
+				nKids = elt.children.length;
+				for (i=0;  i<nKids;  i++) {
+					child = elt.children[i];
+					foundElt = this.findCanvasWithID( id, child );
+					if (foundElt)  return foundElt;
+				}
+			}
+		}
+	},
+    ////////////////////////////////////////////////////////////////////
+	//
+    buildShapeModel: {
+    	value: function(elementModel, world) {
+    		//
+            var shapeModel = elementModel.shapeModel, root;
+			shapeModel.shapeCount	= 1;	// for now...
+			shapeModel.useWebGl		= world._useWebGL;
+			shapeModel.GLWorld		= world;
+			//
+			root = world.getGeomRoot();
+			//
+			if (root) {
+				shapeModel.GLGeomObj			= root;
+				shapeModel.strokeSize			= root._strokeWidth;
+				shapeModel.strokeStyle			= "solid";
+				//shapeModel.strokeStyleIndex
+				switch (root.geomType()) {
+					case root.GEOM_TYPE_RECTANGLE:
+                        elementModel.selection = "Rectangle";
+                        elementModel.pi = "RectanglePi";
+						shapeModel.tlRadius = root._tlRadius;
+						shapeModel.trRadius = root._trRadius;
+						shapeModel.blRadius = root._blRadius;
+						shapeModel.brRadius = root._brRadius;
+						break;
+					case root.GEOM_TYPE_CIRCLE:
+                        elementModel.selection = "Oval";
+                        elementModel.pi = "OvalPi";
+						shapeModel.innerRadius = root._innerRadius;
+						break;
+					case root.GEOM_TYPE_LINE:
+                        elementModel.selection = "Line";
+                        elementModel.pi = "LinePi";
+						shapeModel.slope = root._slope;
+						break;
+                    case root.GEOM_TYPE_BRUSH_STROKE:
+                        elementModel.selection = "BrushStroke";
+                        elementModel.pi = "BrushStrokePi";
+						break;
+                    case root.GEOM_TYPE_CUBIC_BEZIER:
+                        elementModel.selection = "Subpath";
+                        elementModel.pi = "SubpathPi";
+                        break;
+					default:
+						console.log("geometry type not supported for file I/O, " + root.geomType());
+						break;
+				}
+			}
+		}
+	},
+	////////////////////////////////////////////////////////////////////
+	//
+	collectGLData: {
+		value: function( elt,  dataArray ) {
+			//
+			var i, data, nKids, child;
+			//
+			if (elt.elementModel && elt.elementModel.shapeModel && elt.elementModel.shapeModel.GLWorld) {
+				data = elt.elementModel.shapeModel.GLWorld.exportJSON();
+				dataArray.push(data);
+			}
+			//
+			if (elt.children) {
+				nKids = elt.children.length;
+				for (i=0;  i<nKids;  i++) {
+					child = elt.children[i];
+					this.collectGLData( child, dataArray );
+				}
+			}
+		}
+	}
 	////////////////////////////////////////////////////////////////////
 	////////////////////////////////////////////////////////////////////
 });
diff --git a/js/document/views/design.js b/js/document/views/design.js
index 6cce229c..8c6ace8e 100755
--- a/js/document/views/design.js
+++ b/js/document/views/design.js
@@ -65,7 +65,7 @@ exports.DesignDocumentView = Montage.create(BaseDocumentView, {
     ////////////////////////////////////////////////////////////////////
 	//
 	render: {
-        value: function (callback) {
+        value: function (callback, template) {//TODO: Add support for templates
         	//Storing callback for dispatch ready
         	this._callback = callback;
         	//Adding listener to know when template is loaded to then load user content
@@ -116,6 +116,8 @@ exports.DesignDocumentView = Montage.create(BaseDocumentView, {
         			this.document.head.appendChild(this._headFragment.childNodes[i]);
         		}
         	}
+        	//Garbage collection
+        	this._headFragment = null;
     	}
     },
     ////////////////////////////////////////////////////////////////////
@@ -129,13 +131,15 @@ exports.DesignDocumentView = Montage.create(BaseDocumentView, {
     		this.document.body.removeChild(this.document.getElementsByTagName('ninjaloadinghack')[0]);
    			//Getting style and link tags in document
             var stags = this.document.getElementsByTagName('style'),
-            	ltags = this.document.getElementsByTagName('link');
+            	ltags = this.document.getElementsByTagName('link'),
+            	scripttags = this.document.getElementsByTagName('script'),
+            	i, n, webgldata;
            	//Temporarily checking for disabled special case (we must enabled for Ninja to access styles)
            	this.ninjaDisableAttribute(stags);
            	this.ninjaDisableAttribute(ltags);
 			//Looping through all link tags to reload into style tags
 			if(ltags.length > 0) {
-				for (var i = 0; i < ltags.length; i++) {
+				for (i = 0; i < ltags.length; i++) {
 					//
 					if (ltags[i].href) {
 						//TODO: Verify this works for tags in body as well (working in head)
@@ -148,8 +152,26 @@ exports.DesignDocumentView = Montage.create(BaseDocumentView, {
 					}
 				}
 			}
-    		
-    		//TODO: Load webGL (blocking)
+            //Checking for webGL Data
+            for (var w in scripttags) {
+            	//
+            	webgldata = null;
+            	//
+            	if (scripttags[w].getAttribute) {
+            		if (scripttags[w].getAttribute('data-ninja-webgl') !== null) {
+            			//TODO: Add logic to handle more than one data tag
+            			webgldata = JSON.parse((scripttags[w].innerHTML.replace("(", "")).replace(")", ""));
+            		}
+            		//
+            		if (webgldata) {
+            			for (n = 0; webgldata.data[n]; n++) {
+            				webgldata.data[n] = unescape(webgldata.data[n]);
+            			}
+            			//this._templateDocument.webgl = webgldata.data;
+            			this.model.glData = webgldata.data;
+            		}
+            	}
+            }
     		
     		//TODO: Load Montage Components (blocking)
     		
-- 
cgit v1.2.3