#VRML V2.0 utf8 EXTERNPROTO MouseSensor[ eventIn SFBool eventsProcessed exposedField SFBool enabled eventOut SFVec2f client eventOut SFVec2f position eventOut SFBool lButton eventOut SFBool mButton eventOut SFBool rButton eventOut SFFloat mouseWheel eventOut SFBool isActive ] ["urn:inet:blaxxun.com:node:MouseSensor", "http://www.blaxxun.com/vrml/protos/nodes.wrl#MouseSensor", ] EXTERNPROTO ButtonBar [ eventIn SFFloat endTransparency ]"dossier-buttonbar.wrl#ButtonBar" EXTERNPROTO SearchBox [ eventIn MFNode setNodes eventOut SFString clickedID eventOut SFBool ready eventIn SFFloat endTransparency ]"dossier-searchBox.wrl#SearchBox" EXTERNPROTO LineElement[ exposedField MFNode line ]"dossier-text.wrl#LineElement" EXTERNPROTO TextElement[ exposedField SFString text exposedField SFString email exposedField SFString webpage exposedField SFString uri exposedField SFString style exposedField SFString color ]"dossier-text.wrl#TextElement" EXTERNPROTO Content[ eventIn SFNode infoObject eventIn SFInt32 pos eventOut SFNode clicked eventOut MFNode shape ]"dossier-PresentationButtons.wrl#Content" EXTERNPROTO TextLineElement[ exposedField MFString text exposedField SFVec3f translation field SFString textFont field SFString linkFont field SFString style field MFString family field SFFloat fontSize eventIn SFString uri eventIn SFString email eventIn SFString webpage eventIn SFNode addURLHandler eventIn SFFloat setYPos eventOut SFString myURI ] "dossier-text.wrl#TextLineElement" EXTERNPROTO PresentationButtons [ eventOut SFString clickedOnNode eventOut SFBool ready eventOut SFString close eventIn MFNode setNodes eventIn SFString show eventOut MFNode indexNodesOut eventOut SFNode contentLeft eventOut SFNode contentMiddle eventOut SFNode contentRight ] "dossier-PresentationButtons.wrl#PresentationButtons" EXTERNPROTO ConnectionConceptGraph [ eventIn SFNode setParent eventIn SFVec3f setTranslationChild eventIn SFFloat endTransparency eventIn SFBool update eventIn SFColor setColor eventIn SFNode node1 eventIn SFNode node2 eventIn SFNode setRemoveAddScript eventIn SFNode me eventIn SFBool start eventOut SFNode node1Out eventOut SFNode node2Out ] "dossier-ConceptGraph8.wrl#ConnectionConceptGraph" EXTERNPROTO ConceptGraphNode [ eventIn MFNode connectedNodes eventIn SFBool getRadiusWithChildren eventIn SFBool getRadiusWithGrandChildren eventIn MFNode drawChildNodes2Deep eventIn SFNode me eventIn SFVec3f endTranslation eventIn SFFloat endTransparency eventIn SFBool start eventIn MFNode drawConnections2Deep eventIn MFNode setDrawnNodes eventIn SFNode addConnection eventIn SFNode setRemoveAddScript eventIn SFNode removeConnection eventIn SFBool clickedOnNode eventIn MFNode setModel eventIn SFNode setInfoObject eventIn SFFloat setRotation eventIn SFNode setParent eventIn SFFloat endScale eventIn SFFloat setMaxRadius eventIn SFBool deactivateClicking eventOut SFVec3f translation eventOut SFFloat radiusWithChildren eventOut SFFloat radiusWithGrandChildren eventOut MFNode nodesToBeDrawnList eventOut MFNode drawnNodesListToParent eventOut SFBool canBeRemoved eventOut MFNode addNewConnection eventOut SFVec3f endTranslationOut eventOut SFNode isSelected eventOut SFFloat radiusWithText eventOut MFNode connectionToBeAddedOut eventOut MFNode connectionListToParent eventOut SFNode infoObject eventOut SFNode infoToDescription eventOut SFVec3f scaledSize exposedField SFColor diffuseColor field SFString ID field SFVec3f scale ] "dossier-ConceptGraph8.wrl#Node" EXTERNPROTO NodePresentationGraph [ eventIn MFNode connectedNodes eventIn SFNode setInfoObject field SFString ID eventOut SFNode infoObject eventOut MFNode connectedNodesOut ] "dossier-Environment.wrl#NodePresentationGraph" EXTERNPROTO Environment [ eventIn SFString showNodeConceptGraph eventIn MFNode setConceptGraphNodes eventIn MFNode setPresentationGraphNodes eventIn SFString text eventOut SFBool ready eventOut SFBool conceptGraphReady eventOut SFBool presentationGraphReady eventOut SFBool historyReady eventIn SFBool prepare eventOut SFFloat endTransparencyCGButtons eventOut SFBool presentationEnvironmentReady eventIn SFString showNodePresentation eventIn SFNode contentLeft eventIn SFNode contentMiddle eventIn SFNode contentRight eventIn SFString setActiveLink eventIn SFInt32 placeActiveLinkOnPane ]"dossier-Environment.wrl#Environment" # Object to store Nodes temporarly, used in combination with createVRMLFromURL PROTO NodeContainer [ exposedField MFNode nodes [] ]{} # Object to store information in. This are the objects that are used in the presentation environment PROTO IndexObject [ eventIn SFNode addObject field SFString ID "" field SFString longName "" eventOut MFNode infoObjects ]{ Script { eventIn SFNode addObject IS addObject eventOut MFNode infoObjects IS infoObjects field SFBool initialized FALSE url "javascript: function addObject(value) { if (!initialized) { infoObjects = new MFNode(); initialized = true; } infoObjects[infoObjects.length] = value; } " } } # Object to store models temporarly, used to load models with createVRMLFromURL PROTO modelContainer [ eventIn MFNode setModel eventOut MFNode modelOut ]{ Script { eventIn MFNode setModel IS setModel eventOut MFNode modelOut IS modelOut url "javascript: function setModel(value) { if (value.length != 0) modelOut = value; } " } } # Navigation info disables all modes of navigation ##NavigationInfo { ## type "NONE" ## headlight TRUE ##} ##Background { ## ##skyColor 50 50 50 ## skyColor 0 0 0 ## ##} #places viewpoint 38 units to the back ##Viewpoint { ## position 0 0 38 ##} PROTO Dossier [ exposedField SFString data "dossier-music-data.wrl" ]{ DEF environmentTransform Transform { children [ Transform { translation -20 0 0 children [ DEF searchBox SearchBox {} ] } #draw environment DEF environment Environment {} Transform { children [ DEF buttonbar ButtonBar {} ] } DEF loadingTextSW Switch { whichChoice 0 choice [ Transform { children [ Shape { geometry Text { string ["Application loading, please wait..."] fontStyle FontStyle { justify "MIDDLE" size 1 family "Verdana" } } appearance Appearance { material Material { diffuseColor 1 .85 0 specularColor .87 .25 .25 ambientIntensity .157 shininess 1 } } } ] } ] } ] } DEF timer TimeSensor { enabled TRUE loop TRUE cycleInterval 2 } DEF mouseSensor MouseSensor {} # chanes the x & y scale of the environment to correct for different display aspect ratios # default ration is 1.7028 # the blaxxun plugin always puts the things that are in a square around the center on the screen # the application requires a rectangle (with aspect ration 1.7) # if the aspect ration becomes smaller than this, the x and y are scaled down proportionaly so # everything fits on the screen. # When the aspect ration < 1 then the computation of the scaling is done with aspect = 1, because # because the blaxxun plugin scales down when scale < 1, so futher "manual" scaling is not necessary DEF envScaleScript Script { field SFFloat correctAspect 1.7028 eventOut SFVec3f scale eventIn SFTime time url "javascript: function time() { aspect = Browser.getWindowAspect(); //print (aspect); if (aspect < correctAspect ) { if (aspect < 1) aspect = 1; scale = new SFVec3f(aspect/ correctAspect , aspect/correctAspect, 1);//aspect/correctAspect } else scale = new SFVec3f(1,1,1); } " } # node containers for node template loading and configuration loading DEF nodeContainer NodeContainer {} DEF configContainer NodeContainer {} # timer that is used for testing if template loading is finished and to check if the environments are ready DEF startTimer TimeSensor { enabled TRUE loop TRUE } DEF startScript Script { eventIn SFBool nodeCreationReady eventIn SFTime time field SFNode environment USE environment field SFNode startTimer USE startTimer field SFNode searchBox USE searchBox eventOut SFBool run url "javascript: function time() { //check if environment, concept graph, presentation graph (now presentation buttons), history, nodeTemplate. search box and presentation environment are ready if (nodeCreationReady&&environment.ready&&environment.conceptGraphReady&&environment.presentationGraphReady&&environment.historyReady&&searchBox.ready&&environment.presentationEnvironmentReady) { Browser.deleteRoute(startTimer,'time',Browser.getScript(),'time'); //Browser.setNavigationMode('NONE'); // <- TEMP FIX (Why is navigation enabled without this??) -TimV run = true; } } " } DEF NodeCreationScript Script { eventIn SFBool run eventIn SFTime time eventOut MFNode conceptGraphNodes eventOut MFNode presentationGraphNodes eventOut SFBool ready field SFNode nodeContainer USE nodeContainer # field SFNode modelContainer USE modelContainer field SFNode startTimer USE startTimer field MFNode allModels [] field MFNode nodeListPresentationGraph [] field SFNode configContainer USE configContainer eventOut SFInt32 setLoadingText field SFString filename IS data directOutput TRUE url "javascript: // initializes loading of nodeTemplate and configuration file // note that currently nothing is done with the configuration information function initialize() { Browser.createVrmlFromURL(filename,nodeContainer,'nodes'); //nodeTemplate.wrl //Browser.createVrmlFromURL('dossier-nodeTemplate.wrl',nodeContainer,'nodes'); //nodeTemplate.wrl Browser.createVrmlFromURL('dossier-configuration.wrl',configContainer,'nodes'); } function time(value) { // checks every time frame if loading of node template has finised, if so: an event ready is sent if (checkIfDataLoaded()) { Browser.deleteRoute(startTimer,'time',Browser.getScript(),'time'); //removes route to stop making of events ready = true; // is send to start script } } // checks each element of the node container (the container into which the data from the node template is loaded with createVRMLFROMURL) // if the element is ready. function checkIfDataLoaded() { for (i = 0; i < nodeContainer.nodes.length; i ++) { if (nodeContainer.nodes[i].isReady && configContainer.nodes[0].isReady) { //print('data Loaded'); return true; } } return false; } // if event run is received(environments are ready and template has loaded) the nodes for the concept graph and presentation environment are created function run() { createNodes(); setLoadingText = -1; } // check which node of the nodeContainer contains the Information object (the element of the nodeTemplate that contains the actual info) // application does not support more than one Information object in the node template function createNodes() { for (i = 0; i < nodeContainer.nodes.length; i ++) { if (nodeContainer.nodes[i].getType() == 'Information') { getAllModels(nodeContainer.nodes[i].informationNodes); buildNodes(nodeContainer.nodes[i].informationNodes); return; } } //print('No information object found!'); } // creates nodes for both the presentation graph as the concept graph function buildNodes(infoNodes) { buildNodesPresentationGraph(infoNodes); buildNodesConceptGraph(infoNodes); } // creates for all models a modelContainer to store its model in. // Information types have a standard model linked to them // if the information type cannot be found, a default model is used function getAllModels(nodes) { for (i = 0; i < nodes.length; i ++) { allModels[i] = Browser.createVrmlFromString('modelContainer{}')[0]; //print('model ID: ' + nodes[i].ID); if (nodes[i].getType() == 'GroupNode') Browser.createVrmlFromURL(new MFString(nodes[i].urlModel),allModels[i],'setModel'); else if (nodes[i].getType() == 'Picture') Browser.createVrmlFromURL(new MFString('models/modelPicture.wrl'),allModels[i],'setModel'); else if (nodes[i].getType() == 'Video') Browser.createVrmlFromURL(new MFString('models/modelVideo.wrl'),allModels[i],'setModel'); else if (nodes[i].getType() == 'VideoInterview') Browser.createVrmlFromURL(new MFString('models/modelVideoInterview.wrl'),allModels[i],'setModel'); else if (nodes[i].getType() == 'TextItem') Browser.createVrmlFromURL(new MFString('models/modelText.wrl'),allModels[i],'setModel'); else if (nodes[i].getType() == 'Audio') Browser.createVrmlFromURL(new MFString('models/conceptGraph/audio/modelAudio.wrl'),allModels[i],'setModel'); else if (nodes[i].getType() == 'Artwork') Browser.createVrmlFromURL(new MFString('models/artworks/artwork.wrl'),allModels[i],'setModel'); else if (nodes[i].getType() == 'Artwork_no_content') Browser.createVrmlFromURL(new MFString('models/artworks/artwork_no_content.wrl'),allModels[i],'setModel'); else if (nodes[i].getType() == 'MaterialItem') Browser.createVrmlFromURL(new MFString('models/modelMaterial.wrl'),allModels[i],'setModel'); else Browser.createVrmlFromURL(new MFString('models/bol2.wrl'),allModels[i],'setModel'); } } /* WEIRD BUG: When create vrml from url is used after a proto is used in createvrmlfromstring the field of the instance appear not being changable. Work around: create all models first using create vrml from url, then create all vrml from string */ // creates concept graph node object for every info element (input nodes: dataelements from nodetemplate) and puts them in a list // after all nodes have been loaded the connections between the nodes are created. // after that the nodeslist is send to the concept graph function buildNodesConceptGraph(nodes) { var nodeList = new MFNode(); //print('getting all info'); for (i = 0; i < nodes.length; i ++) { nodeList[i] = loadNode(nodes[i],i); //else print('No load method for node type: ' + type); } getConnectionsRight(nodeList); conceptGraphNodes = nodeList; } // creates a concept graph node for an information object // currently, scale is assumed to be always 1. // diffuse color is no longer used, because every node has a model // if the model for the node has not been loaded yet, a rout is created // from the modelContainer to node for adding the model to it. function loadNode(infoNode,i) { var graphNode; color = new SFColor(Math.random(), Math.random(),Math.random()); radius = 1; vrmlstring = 'ConceptGraphNode {'; vrmlstring += ' ID ' + infoNode.ID; vrmlstring += ' scale ' + radius + ' ' + radius + ' ' + radius; vrmlstring += ' diffuseColor '+ color; vrmlstring += '}'; graphNode = Browser.createVrmlFromString(vrmlstring)[0]; graphNode.me = graphNode; graphNode.setInfoObject = infoNode; if (allModels[i].modelOut.length != 0) graphNode.setModel = allModels[i].modelOut; else Browser.addRoute(allModels[i],'modelOut',graphNode,'setModel'); return graphNode; } // assigns the (references to the) connected nodes to each node function getConnectionsRight(nodes) { for (i = 0; i < nodes.length; i ++) { nodes[i].connectedNodes = getConnectedNodes(nodes[i].infoObject.connectedNodesIDs,nodes); } } // finds all references for the nodes in the list nodeIDs and stores them in a list function getConnectedNodes(nodeIDs,nodes) { var connectedNodes = new MFNode(); for (i = 0; i < nodeIDs.length; i ++) { connectedNodes[i] = getNode(nodeIDs[i],nodes); } return connectedNodes; } // returns the node with nodeID from the nodes array function getNode(nodeID,nodes) { for (i = 0; i < nodes.length; i ++) { if (nodes[i].ID == nodeID) return nodes[i]; } print('Error in node template: Node not found: ' + nodeID); } // returns the info object with nodeID from the objects array function getInfoObject(nodeID,objects) { for (i = 0; i < objects.length; i ++) { if (objects[i].ID == nodeID) return objects[i]; } print('Error in node template: Node not found: ' + nodeID); } // tests if objectID is in IDs array function objectIsInArray(ID,IDs) { for (i = 0; i < IDs.length; i ++) { if (IDs[i] == ID) return true; } return false; } // creates for every ifno object a presesentation object = NodePresentationGraph, these nodes are added to the nodeListpresentationGraph // later, for each object, indexobjects are created for the connected nodes // this way of data represntation is not efficient and is a relic from a graph in the presentation environment where each objects had its own graph with connected nodes // for the current sitution it would be better to create the objects when needed (i.e. when looking at an object). function buildNodesPresentationGraph(infoObjects) { var nodeList = new MFNode(); for (i = 0; i < infoObjects.length; i ++) { nodeListPresentationGraph[nodeListPresentationGraph.length] = createMiddleNodePresentationGraph(infoObjects[i],i); } nodeList = createAllIndexObjects(infoObjects); presentationGraphNodes = nodeListPresentationGraph; } // for each element of the nodeListPresentationGraph a set of indexObjects is created: this are the index objects of its connected nodes // those elements are added to the presentation graph too, so they can be drawn function createAllIndexObjects(infoObjects) { var indexNodes = new MFNode(); var tempNodes; var lengthNodeList = nodeListPresentationGraph.length; for (i = 0; i < lengthNodeList; i ++) { tempNodes = createIndexNodesForNode(nodeListPresentationGraph[i].infoObject.connectedNodesIDs,infoObjects,nodeListPresentationGraph[i].ID); nodeListPresentationGraph[i].connectedNodes = tempNodes; for (j = 0; j < tempNodes.length; j ++) { nodeListPresentationGraph[nodeListPresentationGraph.length] = tempNodes[j]; } } } // creates a presentation graph node, the node has an infoObject which contains the actual information function createMiddleNodePresentationGraph(infoObject,i) { var graphNode; color = new SFColor(Math.random(), Math.random(),Math.random()); radius = 3; vrmlstring = 'NodePresentationGraph {'; vrmlstring += ' ID ' + infoObject.ID; vrmlstring += '}'; graphNode = Browser.createVrmlFromString(vrmlstring)[0]; graphNode.setInfoObject = infoObject; return graphNode; } // creates the index objects for a node: // every infoObject that is connected (those in nodeIDs) are stored: // an indexObject is created for every information type that is found // first: the infoObject is found // then: it is checked if this type is already exisitig: // if this is not so: index < 0 then: a new indexObject is created for that type and the infoObject is // added to that indexObject // else: the infoObject is added to the indexObject with index index. function createIndexNodesForNode(nodeIDs,infoObjects,ID) { var indexNodes = new MFNode(); var connectedObject; var indexObject; var index = 0; var type = ''; for (i = 0; i < nodeIDs.length; i ++) { connectedObject = getInfoObject(nodeIDs[i],infoObjects); if (connectedObject.ID != null) { if (!objectIsInArray(ID,connectedObject.connectedNodesIDs)) print('Warning: connection not symmetric, node ' + ID + ' not in connectednodes of node ' + connectedObject.ID + '\n'); type = connectedObject.getType(); index = getIndexNodeIndex(type,indexNodes); if (index < 0) { indexObject = createIndexNode(connectedObject,ID + '_' + indexNodes.length); indexNodes[indexNodes.length] = indexObject; } else { indexNodes[index].addObject = connectedObject; } } } return indexNodes; } // creates a new index object for storing info objects, extra info is added to the ID function createIndexNode(infoObject,ID) { var graphNode; var nodeID = 'INDEX_FOR' + ID; indexObject = createIndexObject(infoObject,nodeID); return indexObject; } // creates a new index object for storing info objects function createIndexObject(infoObject,ID) { indexObject = Browser.createVrmlFromString('IndexObject { ID ' + ID + ' longName \"Index of all ' + infoObject.getType() + 's\" }')[0]; // indexObject.addObject = infoObject; //print('Nieuw index object aangemaakt'); return indexObject; } // finds the index number of the indexObject that contains infoObjects with type type. // if not found: returns -1 function getIndexNodeIndex(type,indexNodes) { for (i = 0; i < indexNodes.length; i ++) { if (indexNodes[i].infoObjects[0].getType() == type) return i; } return -1; } " } DEF mouseScript Script # for advanced mouse interaction { directOutput TRUE eventIn SFFloat mouseWheel eventIn SFBool rButton eventIn SFBool lButton field SFInt32 scrollSpeed 3 field SFBool buttonDownOnNode FALSE field SFNode buttonDownOnChair NULL field SFNode buttonDownOnBox NULL field SFNode mouseSensor USE mouseSensor field SFNode environment USE environment url "javascript: function mouseWheel(value) { var lines=value/-Math.abs(value)*scrollSpeed; var rayHitInfo=Browser.mouseSelect(mouseSensor.position); if(rayHitInfo==null) return; var path=rayHitInfo.hitPath; for(var i=0;i< path.length;i++) { if(path[i].getType()=='ScrollPane') { path[i].scrollText=lines; mouseSensor.eventsProcessed=true; return; } } } function lButton(buttonDown) { var rayHitInfo=Browser.mouseSelect(mouseSensor.position); if(rayHitInfo==null) { if(!buttonDown) { // clear dragged items if dropped in void buttonDownOnBox=null; environment.setActiveLink=''; } return; } var path=rayHitInfo.hitPath; if(buttonDown) { for(var i=0;i< path.length;i++) { var type=path[i].getType(); if(type=='presentationBox') { buttonDownOnBox=path[i]; //print('mousedown on '+path[i].currentIndexObject.ID); } } } else if(buttonDownOnBox.getType()!='undefined') { for(var i=0;i< path.length;i++) { var type=path[i].getType(); if(type=='presentationBox') { //print('mouseup on '+path[i].currentIndexObject.ID); if(path[i].currentIndexObject.ID!=buttonDownOnBox.currentIndexObject.ID) { var pane1=buttonDownOnBox; var pane2=path[i]; var indexObject1=pane1.currentIndexObject.copy(); setIndexObjectToPane(pane1.parentPlaneID,pane2.currentIndexObject); setIndexObjectToPane(pane2.parentPlaneID,indexObject1); } } } buttonDownOnBox=null; } else { for(var i=0;i< path.length;i++) { var type=path[i].getType(); if(type=='presentationBox') { environment.placeActiveLinkOnPane=path[i].parentPlaneID; } } environment.setActiveLink=''; } } function setIndexObjectToPane(paneID,indexObject) { if(paneID==0) environment.contentLeft=indexObject; else if(paneID==1) environment.contentMiddle=indexObject; else if(paneID==2) environment.contentRight=indexObject; } function rButton(buttonDown) { if(!buttonDown && buttonDownOnNode) { buttonDownOnNode=false; mouseSensor.eventsProcessed=true; return; } else if(!buttonDown && buttonDownOnChair.getType()!='undefined') { buttonDownOnChair.rotate=false; buttonDownOnChair=null; mouseSensor.eventsProcessed=true; return; } var rayHitInfo=Browser.mouseSelect(mouseSensor.position); if(rayHitInfo==null) return; var path=rayHitInfo.hitPath; for(var i=0;i< path.length;i++) { var type=path[i].getType(); if(type=='ConceptGraphNode') { if(buttonDown) { buttonDownOnNode=true; path[i].clickedOnNode = true; path[i].clickedOnNode = true; } mouseSensor.eventsProcessed=true; return; } else if(buttonDown && (type=='male_chair' || type=='female_chair')) { path[i].rotate=true; buttonDownOnChair=path[i]; } } }" } DEF introScript Script { eventOut SFInt32 layerWhichChoice eventIn SFBool clicked url "javascript: //disable navigation modes on start function initialize() { Browser.setNavigationMode('NONE'); } function clicked(value) { if (value) layerWhichChoice = 0; } " } ROUTE envScaleScript.scale TO environmentTransform.scale ROUTE timer.cycleTime TO envScaleScript.time ROUTE mouseSensor.mouseWheel TO mouseScript.mouseWheel ROUTE mouseSensor.lButton TO mouseScript.lButton ROUTE mouseSensor.rButton TO mouseScript.rButton ROUTE startScript.run TO environment.prepare ROUTE NodeCreationScript.conceptGraphNodes TO environment.setConceptGraphNodes ROUTE NodeCreationScript.presentationGraphNodes TO environment.setPresentationGraphNodes ROUTE NodeCreationScript.conceptGraphNodes TO searchBox.setNodes ROUTE startScript.run TO NodeCreationScript.run ROUTE startTimer.time TO NodeCreationScript.time ROUTE startTimer.time TO startScript.time ROUTE NodeCreationScript.ready TO startScript.nodeCreationReady ROUTE searchBox.clickedID TO environment.showNodeConceptGraph ROUTE environment.endTransparencyCGButtons TO searchBox.endTransparency ROUTE environment.endTransparencyCGButtons TO buttonbar.endTransparency ROUTE NodeCreationScript.setLoadingText TO loadingTextSW.whichChoice } PROTO MyDossier [ ]{ Dossier { data "dossier-nodeTemplate.wrl" } } ##