UNPKG

dreemgl

Version:

DreemGL is an open-source multi-screen prototyping framework for mediated environments, with a visual editor and shader styling for webGL and DALi runtimes written in JavaScript. As a toolkit for gpu-accelerated multiscreen development, DreemGL includes

1,010 lines (894 loc) 32.1 kB
/* DreemGL is a collaboration between Teeming Society & Samsung Electronics, sponsored by Samsung and others. Copyright 2015-2016 Teeming Society. Licensed under the Apache License, Version 2.0 (the "License"); You may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.*/ define.class('$ui/view', function(require, $ui$, view, icon, treeview, cadgrid, foldcontainer, label, button, scrollbar, textbox, numberbox, splitcontainer, menubar, $widgets$, palette, propviewer, searchbox, jseditor, $server$, sourceset, dataset, $system$parse$, astscanner, $$, aboutdialog, docviewerdialog, newcompositiondialog, opencompositiondialog, renamedialog, library, dockpanel, block, connection) { this.name = 'flowgraph' this.flex = 1 this.clearcolor = "#565656" this.bgcolor = "#565656" this.flexdirection = "column" this.attributes = { sourceset:{}, inspect:Config({type:Object}) } define.class(this, "selectorrect", view, function() { this.bordercolorfn = function(pos) { var check = (int(mod(0.20 * (gl_FragCoord.x + gl_FragCoord.y + time * 40.),2.)) == 1)? 1.0: 0.0 return vec4(check * vec3(0.8), 1) } this.bordercolor = vec4(1, 1, 1, 0.4) this.borderwidth = 2 this.bgcolor = vec4(1, 1, 1, 0.07) this.borderradius = 2 this.position = "absolute" this.visible = false }) this.addToSelection = function(obj) { var f = this.currentselection.indexOf(obj) if (f == -1) this.currentselection.push(obj) else return this.updateSelectedItems() if (this.currentselection.length > 1) return false return true } this.removeFromSelection = function(obj) { if (this.currentblock == obj) { this.currentblock = undefined this.updatePopupUIPosition() } var f = this.currentselection.indexOf(obj) if (f > -1) this.currentselection.splice(f,1) this.updateSelectedItems() } this.updateSelectedItems = function() { for (var a in this.allblocks) { var obj = this.allblocks[a] var f = this.currentselection.indexOf(obj) var newval = 0 if (f > -1) newval = 1 if (obj._inselection != newval) obj.inselection = newval } for (var a in this.allconnections) { var obj = this.allconnections[a] var f = this.currentselection.indexOf(obj) var newval = 0 if (f > -1) newval = 1 if (obj._inselection != newval) obj.inselection = newval } this.updatePopupUIPosition() } this.inSelection = function(obj) { var f = this.currentselection.indexOf(obj) if (f > -1) return true return false } this.setupSelectionMove = function() { for (var a in this.currentselection) { var obj = this.currentselection[a] obj.setupMove() } } this.moveSelected = function(dx, dy, store) { var snap = 1 for (var a in this.currentselection) { var obj = this.currentselection[a] obj.updateMove(dx, dy, snap) } if (store) { this.sourceset.fork(function() { for (var a in this.currentselection) { var obj = this.currentselection[a] if (!(obj instanceof block)) continue var flowdata = obj.flowdata flowdata.x = obj.pos[0] flowdata.y = obj.pos[1] this.sourceset.setFlowData(obj.name, flowdata) } }.bind(this)) } this.updateConnections() this.updatePopupUIPosition() } this.clearSelection = function(update) { this.currentblock = undefined this.currentconnection = undefined this.currentselection = [] if (update) this.updateSelectedItems() } this.addBlock = function(folder, blockname) { this.sourceset.fork(function() { this.sourceset.addBlock(undefined, blockname) }.bind(this)) } this.removeBlock = function (block) { if (block == undefined) block = this.currentblock if (block) { this.sourceset.fork(function() { this.sourceset.removeBlock(block.name) }.bind(this)) this.removeFromSelection(block) this.setActiveBlock(undefined) this.updateSelectedItems() this.updatePopupUIPosition() } } this.removeConnection = function (conn) { if (conn == undefined) conn = this.currentconnection if (conn) { this.sourceset.fork(function() { this.sourceset.deleteWire( conn.from, conn.fromoutput, conn.to, conn.toinput ) }.bind(this)) this.removeFromSelection(conn) this.setActiveConnection(undefined) this.updateSelectedItems() this.updatePopupUIPosition() } } this.updatePopupUIPosition = function() { var bg = this.findChild("blockui") var cg = this.findChild("connectionui") var gg = this.findChild("groupui") var gbg = this.findChild("groupbg") gbg.visible =false gg.visible = false bg.visible = false return // TODO - decide if the group UI is needed at all.. if (this.currentselection.length == 1) { gg.visible = false gbg.visible = false this.currentblock = undefined this.currentconnection = undefined var b = this.currentselection[0] if (b instanceof block) this.currentblock = b if (b instanceof connection) this.currentconnection = b if (this.currentblock) { bg.x = this.currentblock.pos[0] bg.y = this.currentblock.pos[1]-bg.layout.height - 3 bg.visible = true } else { bg.visible = false } if (this.currentconnection) { cg.x = (this.currentconnection.frompos[0] + this.currentconnection.topos[0])/2 cg.y = (this.currentconnection.frompos[1] + this.currentconnection.topos[1])/2 cg.visible = true } else { cg.visible = false } } else { cg.visible = false bg.visible = false if (this.currentselection.length > 1) { gg.visible = true gbg.visible = true var minx = 10000 var maxx = -10000 var miny = 10000 var maxy = -10000 var cx = 0 var cy = 0 var n = 0 for (var a in this.currentselection) { var bl = this.currentselection[a] if (bl instanceof block) { n++ if (bl.pos[0] < minx) minx = bl.pos[0];else if (bl.pos[0]>maxx) maxx = bl.pos[0] if (bl.pos[1] < miny) miny = bl.pos[1];else if (bl.pos[1]>maxy) maxy = bl.pos[1] var x2 = bl.pos[0] + bl.layout.width var y2 = bl.pos[1] + bl.layout.height if (x2 < minx) minx = x2; else if (x2 > maxx) maxx = x2 if (y2 < miny) miny = y2; else if (y2 > maxy) maxy = y2 cx += bl.pos[0] + bl.layout.width/2 cy += bl.pos[1] + bl.layout.height/2 } else { if (bl instanceof connection) { var ax = bl.frompos[0] var ay = bl.frompos[1] var bx = bl.topos[0] var by = bl.topos[1] if (ax > maxx) maxx = ax; else if (ax < minx) minx = ax if (bx > maxx) maxx = bx; else if (bx < minx) minx = bx if (ay > maxy) maxy = ay; else if (ay < miny) miny = ay if (by > maxy) maxy = by; else if (by < miny) miny = by cx += (ax + bx) / 2 cy += (ay + by) / 2 n++ } } } cx /= n cy /= n gg.pos = vec2(cx - cg.layout.width/2, cy - cg.layout.height/2) gbg.pos = vec2(minx-20,miny-20) gbg.size = vec2(maxx-minx + 40, maxy-miny+ 40) } else { gg.visible = false gbg.visible = false } } } this.setActiveBlock = function(block) { this.currentblock = block if (block) { this.currentconnection = undefined this.addToSelection(block) } this.updatePopupUIPosition() } this.setActiveConnection = function(conn) { this.currentconnection = conn if (conn) { this.currentblock = undefined this.addToSelection(conn) } this.updatePopupUIPosition() } this.updateConnections = function() { var cl = this.find("connectionlayer") for (var a in cl.children) { cl.children[a].calculateposition() //cl.children[a].layout = 1 } } this.init = function() { this.screen.onstatus = function() { var menu = this.find("themenu") if (menu) { menu.statustext = this.screen.status } } this.currentselection = [] this.currentblock = undefined this.currentconnection = undefined this.allblocks = [] this.allconnections = [] this.newconnection = {} this.model = dataset({ children:[ {name:"Role"}, {name:"Server"} ], name:"Composition" }) this.librarydata = dataset({children:[]}) this.sourceset = sourceset() //this.rpc.fileio.readFlowLibrary(['@/\\.','.git', '.gitignore']).then(function(result) { // var tree = result.value // tree.name = 'Library' // tree.collapsed = false // // var lib = this.find('thelibrary') // if (lib) { // lib.dataset = this.librarydata = dataset(tree) // } else { // this.librarydata = dataset(tree) // } //}.bind(this)) this.rpc.fileio.readFlowLibrary(['@/\\.','.git', '.gitignore']).then(function(result) { }.bind(this)) this.screen.locationhash = function(event) { if (event.value.composition) { // ok lets put it in define.js require.async(event.value.composition).then(function(result) { define.ignore_reload[define.expandVariables(event.value.composition)] = true this.sourceset.parse(result) // console.log('>>', this.sourceset.ast) // write it back to disk this.sourceset.onchange = function() { this.rpc.fileio.saveComposition(event.value.composition, this.sourceset.last_source) }.bind(this) var viewer = this.find('jsviewer') if (viewer) { viewer.sourceset = this.sourceset } var lib = this.find('thelibrary') if (lib) { var children = []; var defs = this.sourceset.ast.steps[0].params; var category; for (var i=0;i<defs.length;i++) { var def = defs[i]; var name = def.id.name; if (name[name.length - 1] === '$') { category = { name:name,//.substring(1, name.length).replace(/\$/g, "/"), children:[] }; children.push(category); } else if (category) { category.children.push({name:name + ".js"}) } } lib.dataset = this.librarydata = dataset({children:children}) } }.bind(this)) } }.bind(this) this.rpc.fileio.readAllPaths(['resources','server.js','resources','cache','@/\\.','.git', '.gitignore']).then(function(result) { var filetree = this.find('filetree') var tree = result.value tree.collapsed = false // lets make a dataset }.bind(this)) } // right before the recalculateMatrix call this.atMatrix = function() { this.updateConnections() } this.updateZoom = function(z) {} this.gridDrag = function(event) { var cg = this.find("centralconstructiongrid") var fg = this.find("flowgraph") var sq = this.findChild("selectorrect") var min = cg.globalToLocal(event.min) var max = cg.globalToLocal(event.max) if (sq) { sq.visible = true sq.redraw() sq.pos = vec2(min[0],min[1]) sq.size = vec3(max[0] - min[0], max[1] - min[1], 1) fg.dragselectset = [] for (var a in fg.allblocks) { var bl = fg.allblocks[a] cx = bl.pos[0] + bl.layout.width/2 cy = bl.pos[1] + bl.layout.height/2 if (cx >= min[0] && cx <= max[0] && cy >= min[1] && cy <=max[1]) { bl.inselection = 1 fg.dragselectset.push(bl) } else { if (fg.originalselection.indexOf(bl) >-1) { bl.inselection = 1 } else { bl.inselection = 0 } } } for (var a in fg.allconnections) { var con = fg.allconnections[a] ax = con.frompos[0] ay = con.frompos[1] bx = con.topos[0] by = con.topos[1] cx = (ax+bx)/2 cy = (ay+by)/2 if ( (ax >= min[0] && ax <= max[0] && ay >= min[1] && ay <=max[1]) || (bx >= min[0] && bx <= max[0] && by >= min[1] && by <=max[1]) || (cx >= min[0] && cx <= max[0] && cy >= min[1] && cy <=max[1]) ) { con.inselection = 1 fg.dragselectset.push(con) } else { if (fg.originalselection.indexOf(con) >-1) { con.inselection = 1 } else { con.inselection = 0 } } } } } this.gridDragStart = function() { this.cancelConnection() this.startDragSelect() } this.gridDragEnd = function() { var sq = this.findChild("selectorrect") if (sq) { sq.visible = false sq.redraw() } this.find("flowgraph").commitdragselect() } this.updateConnector = function(ev) { var connectingconnection = this.find("openconnector") if (connectingconnection && connectingconnection.ready) { connectingconnection.visible = true if (connectingconnection.to === "undefined") { connectingconnection.topos = this.find("centralconstructiongrid").globalToLocal(ev.position); } else if (connectingconnection.from === "undefined") { connectingconnection.frompos = this.find("centralconstructiongrid").globalToLocal(ev.position); } connectingconnection.redraw(); } } this.makeNewConnection = function() { this.sourceset.fork(function(src) { var inserted; if (this.newconnection.targettype === "Array") { src.deleteWire( this.newconnection.sourceblock, this.newconnection.sourceoutput, this.newconnection.targetblock, this.newconnection.targetinput ) inserted = src.insertWire(this.newconnection.sourceblock, this.newconnection.sourceoutput, this.newconnection.sourcetype, this.newconnection.targetblock, this.newconnection.targetinput); } else if (this.newconnection.targettype === "Object") { inserted = src.mergeWire(this.newconnection.sourceblock, this.newconnection.sourceoutput, this.newconnection.sourcetype, this.newconnection.targetblock, this.newconnection.targetinput) } if (!inserted) { src.deleteWire( null, null, this.newconnection.targetblock, this.newconnection.targetinput ) src.createWire( this.newconnection.sourceblock, this.newconnection.sourceoutput, this.newconnection.targetblock, this.newconnection.targetinput ) } }.bind(this)) this.cancelConnection() } this.setBlockName = function(block, newname) { //TODO fix all the wires that will break when you do this! this.sourceset.fork(function(src) { var ast = new astscanner(block.nodeprops,[{type:"Property", name:"name"}]) var value; if (ast.atindex > -1 && ast.atparent && ast.atparent.keys) { var found = ast.atparent.keys[ast.atindex] if (found && found.value) { value = found.value; value.raw = '"' + newname + '"'; value.value = newname } } else { ast.at.keys.push({ key:{ type:"Property", name:"name" }, value:{ type:"Value", kind:"string", raw:'"' + newname + '"', value: newname }}) } }) } this.cancelConnection = function() { this.newconnection = {} var connectingconnection = this.find("openconnector") if (connectingconnection && (connectingconnection.ready || connectingconnection.visible)) { connectingconnection.from = undefined connectingconnection.fromoutput = undefined connectingconnection.to = undefined connectingconnection.toinput = undefined connectingconnection.visible = false connectingconnection.ready = false connectingconnection.calculateposition() connectingconnection.redraw() } } this.setupConnectionPointerMove = function() { console.log("setting up new connection drag...") var connectingconnection = this.find("openconnector") if (connectingconnection) { connectingconnection.ready = true; connectingconnection.visible = true; connectingconnection.from = this.newconnection.sourceblock connectingconnection.fromoutput = this.newconnection.sourceoutput connectingconnection.to = this.newconnection.targetblock connectingconnection.toinput = this.newconnection.targetinput //console.log(this.newconnection.targetblock,this.newconnection.sourceoutput,this.newconnection.targetblock,this.newconnection.targetinput) if (connectingconnection.to && connectingconnection.to !== "undefined" && connectingconnection.to.length > 0) { //console.log("setting to??", connectingconnection.to) var b = this.find(connectingconnection.to) if (b) { var ball = b.findChild(connectingconnection.toinput) connectingconnection.bgcolor = ball.bgcolor } } else { if (connectingconnection.from && connectingconnection.from !== "undefined"&& connectingconnection.from.length > 0) { //console.log(connectingconnection.from) var b = this.find(connectingconnection.from) if (b) { var ball = b.findChild(connectingconnection.fromoutput) connectingconnection.bgcolor = ball.bgcolor } } } connectingconnection.calculateposition() } } this.setConnectionStartpoint = function(sourceblockname, outputname, sourcetype) { this.newconnection.sourceblock = sourceblockname this.newconnection.sourceoutput = outputname this.newconnection.sourcetype = sourcetype if (this.newconnection.targetblock && this.newconnection.targetblock !== "undefined" ) { this.makeNewConnection() } else { this.setupConnectionPointerMove() } } this.setConnectionEndpoint = function(targetblockname, inputname, targettype) { //console.log(targetblockname, inputname) this.newconnection.targetblock = targetblockname this.newconnection.targetinput = inputname this.newconnection.targettype = targettype if (this.newconnection.sourceblock && this.newconnection.sourceblock !== "undefined" ) { this.makeNewConnection() } else { this.setupConnectionPointerMove() } } this.startDragSelect = function() { this.dragselectset = [] if (!this.screen.keyboard.shift) { this.clearSelection(true) } this.originalselection =[] for (var i in this.currentselection) { this.originalselection.push(this.currentselection[i]) } } this.renderConnections = function() { if (!this.sourceset) return if (!this.sourceset.data) return var res = [] for (var i = 0; i < this.sourceset.data.children.length; i++) { var node = this.sourceset.data.children[i] // block({name:"e", title:"block E", x:450, y:600}) if (node.wires) { for (var j = 0; j < node.wires.length; j++) { var w = node.wires[j]; // check to make sure the other wire recognizes this as a flow-visible attribute var found = false; for (var k=0;k<node.inputs.length;k++) { var input = node.inputs[k]; if (w.input === input.name) { found = true; break; } } if (found) { res.push(connection({ from:w.from, fromoutput:w.output, to:node.name, toinput:w.input, stripe:!!(w.multi) })) } else { // console.log("Not rendering", w, "for", node.name) } } } } return res } function uppercaseFirst (inp) { if (!inp || inp.length == 0) return inp return inp.charAt(0).toUpperCase() + inp.slice(1) } this.renderBlocks = function() { var res = [] if (!this.sourceset) return if (!this.sourceset.data) return for (var i = 0; i < this.sourceset.data.children.length; i++) { var node = this.sourceset.data.children[i] // block({name:"e", title:"block E", x:450, y:600}) var fd = node.flowdata if (!fd) { fd = {x:0, y:0} } if (fd.visible !== false) { res.push( block({ flowdata:fd, pos:vec3(fd.x, fd.y, 0), name:node.name, title:uppercaseFirst(node.classname + ': ' + node.name), nodeindex:i, nodeprops:node.propobj, editables:node.editables, inputs:node.inputs, outputs:node.outputs, showscreenbutton:!!(fd.screen) }) ) } } return res } this.commitdragselect = function() { for (var i in this.dragselectset) { var bl = this.dragselectset[i] this.addToSelection(bl) } this.updatePopupUIPosition() } this.getCompositionName = function() { // todo: get actual name from here.. return "somename.js" } this.openComposition = function() { this.screen.closeModal(false) this.screen.openModal(function() { return opencompositiondialog({width:this.screen.size[0],height:this.screen.size[1], position:"absolute", blur: function() { this.screen.closeModal(false) } }) }.bind(this)).then(function(res) { if (res) { console.log(res) this.screen.locationhash = { composition:"$compositions/"+ res } } console.log(" opencomp result: " , res) }.bind(this)) } this.newComposition = function() { this.screen.closeModal(false) this.screen.openModal(function() { return newcompositiondialog({width:this.screen.size[0],height:this.screen.size[1], position:"absolute", blur: function() { this.screen.closeModal(false) }} ) }).then(function(res) { if (res) { this.rpc.fileio.newComposition(res).then(function(result) { console.log(result) // switch to new thing this.screen.locationhash = { composition:result.value } }.bind(this)) } console.log(" newcomp result: " , res) }.bind(this)) } this.renameComposition = function() { this.screen.closeModal(false) this.screen.openModal(function() { return renamedialog({width:this.screen.size[0],height:this.screen.size[1], position:"absolute", blur: function() { this.screen.closeModal(false) } }) }.bind(this)).then(function(res) { console.log(" rename composition result: " , res) }) } this.helpAbout = function() { this.screen.openModal(function() { return aboutdialog({width:this.screen.size[0],height:this.screen.size[1], position:"absolute", blur: function() { this.screen.closeModal(false) } }) }.bind(this)).then(function(res) {}) } this.helpReference = function() { this.screen.openModal(function() { return docviewerdialog({width:this.screen.size[0],height:this.screen.size[1], position:"absolute", title:"Reference", blur: function() { this.screen.closeModal(false) } }) }.bind(this)).then(function(res) {}) } this.helpGettingStarted = function() { this.screen.openModal(function() { return docviewerdialog({width:this.screen.size[0],height:this.screen.size[1], position:"absolute", title:"Getting started", blur: function() { this.screen.closeModal(false) } }) }.bind(this)).then(function(res) {}) } this.undo = function() { this.sourceset.undo() } this.redo = function() { this.sourceset.redo() } this.render = function() { //return [ // // cadgrid({name: "centralconstructiongrid", // pointerstart: this.gridDragStart.bind(this), // pointermove: this.gridDrag.bind(this), // pointerend: this.gridDragEnd.bind(this), // overflow: "scroll" ,bgcolor: "#4e4e4e",gridsize: 5,majorevery: 5, majorline: "#575757", minorline: "#484848", zoom: function() {this.updateZoom(this.zoom)}.bind(this)} // ,view({name: "underlayer", bgcolor: NaN} // ,view({name: "groupbg",visible: false, bgcolor: vec4(1,1,1,0.08) , borderradius: 8, borderwidth: 0, bordercolor: vec4(0,0,0.5,0.9),position: "absolute", flexdirection: "column"}) // ) // ,view({name: "connectionlayer", bgcolor: NaN, dataset: this.sourceset, render: function() { // return this.renderConnections() // }.bind(this)} // ) // ,view({bgcolor: NaN}, connection({name: "openconnector", hasball: false, visible: false})) // ,view({name: "blocklayer", bgcolor: NaN, dataset: this.sourceset, render: function() { // return this.renderBlocks() // }.bind(this)}) // // ,view({name: "popuplayer", bgcolor: NaN}, // view({name: "connectionui",visible: false,bgcolor: vec4(0.2,0.2,0.2,0.5),padding: 5, borderradius: vec4(1,14,14,14), borderwidth: 1, bordercolor: "black",position: "absolute", flexdirection: "column"}, // label({text: "Connection", bgcolor: NaN, margin: 4}) // ,button({padding: 0, borderwidth: 0, click: function() {this.removeConnection(undefined)}.bind(this), icon: "remove",text: "delete", margin: 4, fgcolor: "white", bgcolor: NaN}) // ) // ,view({name: "blockui",visible: false, bgcolor: vec4(0.2,0.2,0.2,0.5),padding: 5, borderradius: vec4(10,10,10,1), borderwidth: 2, bordercolor: "black",position: "absolute", flexdirection: "column"}, // //,view({name: "blockui",x: -200,bg: 1,clearcolor: vec4(0,0,0,0),bgcolor: vec4(0,0,0,0),position: "absolute"}, // label({text: "Block", bgcolor: NaN, margin: 4}) // ,button({padding: 0,borderwidth: 0, click: function() {this.removeBlock(undefined)}.bind(this),fgcolor: "white", icon: "remove",text: "delete", margin: 4, fgcolor: "white", bgcolor: NaN}) // ) // // ,view({name: "groupui",visible: false, bgcolor: vec4(0.2,0.2,0.2,0.5),borderradius: 8, borderwidth: 2, bordercolor: "black",position: "absolute", flexdirection: "column"}, // //,view({name: "blockui",x: -200,bg: 1,clearcolor: vec4(0,0,0,0),bgcolor: vec4(0,0,0,0),position: "absolute"}, // label({text: "Group", bgcolor: NaN, margin: 4}) // ,button({padding: 0,borderwidth: 0, click: function() {this.removeBlock(undefined)}.bind(this),fgcolor: "white", icon: "remove",text: "delete", margin: 4, fgcolor: "white", bgcolor: NaN}) // ) // ,this.selectorrect({name: "selectorrect"}) // ,view({bgcolor: NaN}, connection({name: "openconnector", hasball: false, visible: false})) // ) // ) //] return [ //menubar({flex: 0, height: 20, viewport: '2d', name: "themenu", menus: [ // {name: "File", commands: [ // {name: "Open composition", clickaction: function() {this.openComposition();return true;}.bind(this)}, // {name: "New composition", clickaction: function() {this.newComposition();return true;}.bind(this)}, // {name: "Rename composition", clickaction: function() {this.renameComposition();return true;}.bind(this), enabled: false} // ]} // , //{name: "Edit", commands: [ // {name: "Undo", icon: "undo", clickaction: function() {this.undo();}.bind(this)}, // {name: "Redo",icon: "redo", clickaction: function() {this.redo();}.bind(this)} // //]} // , //{name: "Help", commands: [ // {name: "About Flowgraph", clickaction: function() {this.helpAbout();return true;}.bind(this)}, // {name: "Getting started", clickaction: function() {this.helpGettingStarted();return true;}.bind(this)}, // {name: "Reference", clickaction: function() {this.helpReference();return true;}.bind(this)} //]} // ]}) //, splitcontainer({} ,splitcontainer({flex: 0.2, flexdirection: "column", direction: "horizontal"} ,dockpanel({title: "Composition", icon:"code", flex: 0.2, click:function(e){ var comp = this.screen.locationhash.composition; if (comp) { var location = define.expandVariables(comp) window.open(location,'_blank'); } }.bind(this)} //,searchbox() ,treeview({flex: 1, dataset: this.sourceset}) ) ,dockpanel({title: "Library", viewport: "2D" } //,searchbox() ,library({name: "thelibrary", dataset: this.librarydata}) ) //,dockpanel({title:"Inspector", visible:false}, // propviewer({ // name:"inspector", // target:this.inspect, // flex:1, // overflow:"scroll", // bgcolor:"#4e4e4e", // callback:function(val, editor, commit) { // console.log("callback>>", val, editor, commit) // if (editor && editor.target && editor.propertyname) { // var t = editor.target; // if (typeof(t) === 'string') { // t = editor.find(t); // } // // if (t) { // if (commit === "file") { // var formData = new FormData(); // var fileobjname; // for (var i = 0; i < val.length; i++) { // var file = val[i]; // fileobjname = file.name; // formData.append('file', file); // } // if (fileobjname) { // var xhr = new XMLHttpRequest(); // xhr.open('POST', window.location.pathname, true); // xhr.onload = function() { // if (xhr.status === 200) { // var compfile = t.screen.composition.constructor.module.filename; // var compdir = compfile.substring(0, compfile.lastIndexOf('/')); // var filename = compdir + "/" + fileobjname; // // console.log("oops have to write here", t, editor.propertyname, filename) // // // } else { // console.log('Oops, upload failed', xhr, val); // } // }.bind(this); // xhr.send(formData); // } // } else { // console.log("oops have to write here", t, editor.propertyname, val) // } // } // } // }.bind(this) // }) // ) ) ,splitcontainer({flexdirection: "column", direction: "horizontal"} ,cadgrid({name: "centralconstructiongrid", pointerstart: this.gridDragStart.bind(this), pointermove: this.gridDrag.bind(this), pointerend: this.gridDragEnd.bind(this), pointerhover: this.updateConnector.bind(this), overflow: "scroll" ,bgcolor: "#4e4e4e",gridsize: 5,majorevery: 5, majorline: "#575757", minorline: "#484848", zoom: function() {this.updateZoom(this.zoom)}.bind(this)} ,view({name: "underlayer", bgcolor: NaN} ,view({name: "groupbg",visible: false, bgcolor: vec4(1,1,1,0.08) , borderradius: 8, borderwidth: 0, bordercolor: vec4(0,0,0.5,0.9),position: "absolute", flexdirection: "column"}) ) ,view({name: "connectionlayer", bgcolor: NaN, dataset: this.sourceset, render: function() { return this.renderConnections() }.bind(this)} ) ,view({bgcolor: NaN}, connection({name: "openconnector", hasball: false})) ,view({name: "blocklayer", bgcolor: NaN, dataset: this.sourceset, render: function() { return this.renderBlocks() }.bind(this)}) ,view({name: "popuplayer", bgcolor: NaN}, view({name: "connectionui",visible: false,bgcolor: vec4(0.2,0.2,0.2,0.5),padding: 5, borderradius: vec4(1,14,14,14), borderwidth: 1, bordercolor: "black",position: "absolute", flexdirection: "column"}, label({text: "Connection", bgcolor: NaN, margin: 4}) ,button({padding: 0, borderwidth: 0, click: function() {this.removeConnection(undefined)}.bind(this), icon: "remove",text: "delete", margin: 4, fgcolor: "white", bgcolor: NaN}) ) ,view({name: "blockui",visible: false, bgcolor: vec4(0.2,0.2,0.2,0.5),padding: 5, borderradius: vec4(10,10,10,1), borderwidth: 2, bordercolor: "black",position: "absolute", flexdirection: "column"}, //,view({name: "blockui",x: -200,bg: 1,clearcolor: vec4(0,0,0,0),bgcolor: vec4(0,0,0,0),position: "absolute"}, label({text: "Block", bgcolor: NaN, margin: 4}) ,button({padding: 0,borderwidth: 0, click: function() {this.removeBlock(undefined)}.bind(this),fgcolor: "white", icon: "remove",text: "delete", margin: 4, fgcolor: "white", bgcolor: NaN}) ) ,view({name: "groupui",visible: false, bgcolor: vec4(0.2,0.2,0.2,0.5),borderradius: 8, borderwidth: 2, bordercolor: "black",position: "absolute", flexdirection: "column"}, //,view({name: "blockui",x: -200,bg: 1,clearcolor: vec4(0,0,0,0),bgcolor: vec4(0,0,0,0),position: "absolute"}, label({text: "Group", bgcolor: NaN, margin: 4}) ,button({padding: 0,borderwidth: 0, click: function() {this.removeBlock(undefined)}.bind(this),fgcolor: "white", icon: "remove",text: "delete", margin: 4, fgcolor: "white", bgcolor: NaN}) ) ,this.selectorrect({name: "selectorrect"}) // ,view({bgcolor: NaN}, connection({name: "openconnector", hasball: false, visible: false})) ) ) // ,jseditor({name: 'jsviewer', fontsize: 14,sourceset: this.sourceset, overflow: 'scroll', flex: 0.1}) ) ) ] } })