Commit cebc46fd authored by Jack Woodward's avatar Jack Woodward
Browse files

Final Project Updated Submission

Many files different, but much of the code remains the same.

-Updated simplification algorithm to no longer include unncessary
tolerance variable and made it so that the curve is automatically
simplified on first draw, hiding the buttons for simplifying the curve
(see selectCurve() method in Manager)
-Added framework for 3D audio support in Views.js
parent 6de62f36
# OS generated files #
######################
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db
#### NODE WEBKIT BUILDER
/**/build/*
/**/cache
/**/node_modules/*
####QRCODE png
WOB/qr_code.png
###Ignore save as text directory
trajAsText/**
\ No newline at end of file
# Using WebOSCBridge Application Server
This project is designed as a desktop application running a server for spatialization control interfaces.
This project is an adaption of the [interface.js][interfacejs] project by Charlie Roberts and modified.
## Build from source
If you want to build the server from source you'll need to download and install [node.js][nodejs]. After installing Node.js, open a terminal and run the following commands:
```
npm install
npm install gulp -g
gulp traj
```
This will build releases of the application.
You can configure the release in the gulpfile.js file.
[nodejs]:http://nodejs.org
[npm]:http://nodejs.org/download/
[node-webkit]:https://github.com/rogerwang/node-webkit#downloads
[interfacejs]:https://github.com/charlieroberts/interface.js
var NwBuilder = require('nw-builder');
var gulp = require('gulp');
var gutil = require('gulp-util');
gulp.task('traj', function () {
var nw = new NwBuilder({
version: '0.12.1',
macIcns: './icon-design/icon.icns',
//winIco: './icon-design/icon.ico', //can only use that on win or need WINE
appVersion:'1.0.0',
buildType: 'versioned',
//zip:'true', //if activated this prevents the traj folder to appear
files: [ './**',
'!./gulpfile.js',
'!./icon-design/**',
'!./cache/**',
'!./build/**',
//'!./node_modules/**', attempt to remove the dev packages by installing node --prodcution afterwards
'!./node_modules/gulp/**',
'!./node_modules/gulp-util/**',
'!./node_modules/nw-builder/**'],
platforms: ['osx32', 'win32', 'linux32'] // change this to 'win' for/on windows
//platforms: ['osx'] // change this to 'win' for/on windows
});
// Log stuff you want
nw.on('log', function (msg) {
gutil.log('nw-builder', msg);
});
// Build returns a promise, return it so the task isn't called in parallel
return nw.build().catch(function (err) {
gutil.log('nw-builder', err);
});
});
\ No newline at end of file
<html>
<head>
<script src="./jquery-ui-1.10.1.custom/js/jquery-1.9.1.js"></script>
<script src="jquery-ui-1.10.1.custom/js/jquery-ui-1.10.1.custom.js" type="text/javascript" charset="utf-8"></script>
<script src="mousetrap.js" type="text/javascript" charset="utf-8"></script>
<link rel="stylesheet" href="jquery-ui-1.10.1.custom/css/base/jquery.ui.theme.css" type="text/css" media="screen" title="no title" charset="utf-8">
<link rel="stylesheet" href="jquery-ui-1.10.1.custom/css/base/jquery.ui.button.css" type="text/css" media="screen" title="no title" charset="utf-8">
<link rel="stylesheet" href="jquery-ui-1.10.1.custom/css/base/jquery.ui.resizable.css" type="text/css" media="screen" title="no title" charset="utf-8">
<link rel="stylesheet" href="jquery-ui-1.10.1.custom/css/base/jquery.ui.accordion.css" type="text/css" media="screen" title="no title" charset="utf-8">
<title>Traj Server</title>
<style>
.highlightedRow { background-color: #dedede; }
body { font-family:Helvetica, sans-serif; background-color:#ededed; }
ul { list-style:none; margin:0; padding:0;}
h3 { font-size:1em; display:inline; color:#333; margin-right:3em; margin-left:1em;}
h1 { font-size:1.2em;}
td { font-size:.6em; }
.infoTable td { border:none !important; }
.infoTable td { font-size:.8em !important; }
.infoTable tr td:first-child { text-align: right; white-space: nowrap !important; width:25%; font-color:#666; font-weight:bold;}
.infoTable tr td:last-child { width:75%; padding-left: 2em; text-align:left !important; }
table { border-collapse:collapse; width: 100%; table-layout:fixed; }
#monitorTable, #serverTable, #clientsTable, th { border: 1px solid #666;}
table thead th { font-size:.8em; }
th { white-space: nowrap !important; margin: 0; padding: 5px; font-weight:normal; font-size: .8em; background:#999; color:#fff;}
.ui-widget{font-size:.7em;}
thead tr { width: 100%; }
tbody { height: 2em;}
#clientsTableBody tr td, #monitorTableBody tr td { text-align: center; border-right:1px solid #666; border-top:1px solid #666; font-size:.9em; overflow:hidden; }
#serverTableBody td { border-right:1px solid #666; border-top:1px solid #666; }
#serverTableBody td:last-child, #serverTableBody td:nth-child(2) { text-align: center; vertical-align: top; }
#monitorTable, #serverTable, #clientsTable { border:1px solid #666; margin-bottom:1.5em; }
#clientsTable tbody, #serverTable tbody { font-size:.85em; }
#monitorTable tbody { font-size:.75em;}
#newServerTable { text-align:left ; }
input[type="text"] { width: 90%; }
.interfaceHeader { line-height:1.75em !important;}
</style>
</head>
<body>
<div id='servers'>
<div class="ui-widget-header ui-corner-all interfaceHeader">
<h3>Servers</h3>
<!-- <button id="newButton">New Server</button>
<button id="deleteButton">Remove Selected Server</button> -->
</div>
<table id='serverTable'>
<thead>
<tr>
<th width='80%'>server info</th><th width='10%'>append client id</th><th width='10%'>monitor</th>
</tr>
</thead>
<tbody id="serverTableBody">
</tbody>
</table>
</div>
<div style="height:245px ; text-align: center; diplay: block; margin:auto;">
<div id='target-qrcode'></div>
<div id='target-url' style="text-align: center; font-size:2em; margin:auto;"></div>
</div>
<div id='clients'>
<div class="ui-widget-header ui-corner-all interfaceHeader">
<h3>Clients</h3>
</div>
<table id='clientsTable'>
<thead>
<tr>
<th>id #</th><th>ip address</th><th>connected to</th><th>interface</th><th>monitor</th>
</tr>
</thead>
<tbody id="clientsTableBody">
</tbody>
</table>
</div>
<div id='monitor'>
<div class="ui-widget-header ui-corner-all interfaceHeader">
<h3>Monitor</h3>
<button id="clearMonitorButton">Clear</button>
</div>
<table id='monitorTable'>
<thead>
<tr>
<th width='10%'>server</th><th width='10%'>client id</th><th width='15%'>address / type</th><th width='15%'>typetags / channel</th><th width='50%'>values</th>
</tr>
</thead>
<tbody id="monitorTableBody">
</tbody>
</table>
</div>
<input type="file" nwfile style='display:none' id='fileButton'/>
<input type="file" nwsaveas style='display:none' id='saveFileButton'/>
<script>
if(typeof global.interface === 'undefined') {
var s = $('<script src="server.js" type="text/javascript" charset="utf-8">');
$('head').append(s);
}else{
// page reloaded, remove all servers
global.interface.removeAllServers();
}
</script>
</body>
</html>
\ No newline at end of file
/**#Interface
A singleton object holding all widget constructors and a couple of other methods / properties. It is automatically created as soon as interface.js is loaded.
**/
/**###Interface.extend : method
This method deep copies all the properties and methods of one object to another.
param **destination** Object. The object that properties and methods will be inserted into.
param **source** Object. The object providing the properties and methods for copying.
**/
/**###Interface.mouseDown : property
Boolean. This property tells whether the left mouse button (in non-touch browsers) is currently pressed.
**/
/**###Interface.useTouch : property
Boolean. Whether or not a touch UI browser is being used.
**/
/**###Interface.isAndroid : property
Boolean. Whether or not the browser is running under Android. This is used to determine the range of accelerometer values generated.
**/
var Interface = {
extend : function(destination, source) {
for (var property in source) {
var keys = property.split(".");
if(source[property] instanceof Array && source[property].length < 100) { // don't copy large array buffers
destination[property] = source[property].slice(0);
} else {
destination[property] = source[property];
}
}
return destination;
},
isAndroid : (function() {
var ua = navigator.userAgent.toLowerCase();
return ua.indexOf("android") > -1;
})(),
keyCodeToChar : {8:"Backspace",9:"Tab",13:"Enter",16:"Shift",17:"Ctrl",18:"Alt",19:"Pause/Break",20:"Caps Lock",27:"Esc",32:"Space",33:"Page Up",34:"Page Down",35:"End",36:"Home",37:"Left",38:"Up",39:"Right",40:"Down",45:"Insert",46:"Delete",48:"0",49:"1",50:"2",51:"3",52:"4",53:"5",54:"6",55:"7",56:"8",57:"9",65:"A",66:"B",67:"C",68:"D",69:"E",70:"F",71:"G",72:"H",73:"I",74:"J",75:"K",76:"L",77:"M",78:"N",79:"O",80:"P",81:"Q",82:"R",83:"S",84:"T",85:"U",86:"V",87:"W",88:"X",89:"Y",90:"Z",91:"Windows",93:"Right Click",96:"Numpad 0",97:"Numpad 1",98:"Numpad 2",99:"Numpad 3",100:"Numpad 4",101:"Numpad 5",102:"Numpad 6",103:"Numpad 7",104:"Numpad 8",105:"Numpad 9",106:"Numpad *",107:"Numpad +",109:"Numpad -",110:"Numpad .",111:"Numpad /",112:"F1",113:"F2",114:"F3",115:"F4",116:"F5",117:"F6",118:"F7",119:"F8",120:"F9",121:"F10",122:"F11",123:"F12",144:"Num Lock",145:"Scroll Lock",182:"My Computer",183:"My Calculator",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'"},
panels : [],
mouseDown : false,
useTouch : 'ontouchstart' in document.documentElement,
widgets : [],
};
Interface.Presets = {
dictionary : typeof localStorage.interfacejs === 'undefined' ? {} : JSON.parse( localStorage.interfacejs ),
save : function(name) {
var preset = [];
for(var h = 0; h < Interface.panels.length; h++) {
var panel = Interface.panels[h];
preset[h] = [];
for(var i = 0; i < panel.children.length; i++) {
var widget = panel.children[i];
if(typeof widget.children === 'object') {
var children = [];
for(var j = 0; j < widget.children.length; j++) {
children[j] = widget.children[j].value;
}
preset[h][i] = children;
}else{
preset[h][i] = widget.value;
}
}
this.dictionary[ name ] = preset;
localStorage.interfacejs = JSON.stringify( this.dictionary );
}
},
load : function(name) {
var preset = this.dictionary[ name ];
for(var h = 0; h < Interface.panels.length; h++) {
var panel = Interface.panels[h];
for(var i = 0; i < panel.children.length; i++) {
var widget = panel.children[i];
if(typeof widget.children === 'object') {
for(var j = 0; j < widget.children.length; j++) {
widget.children[j].setValue( preset[h][i][j] );
}
}else{
widget.setValue( preset[h][i] );
}
}
}
},
list : function() {
return Object.keys( this.dictionary );
},
};
/**#Interface.Panel - Widget
A panel is a container for on-screen widgets. There can be multiple panels in a HTML page. Panels are the starting point for event processing in Interface.js.
**/
/**###Interface.Panel.children : property
Array. An array of all widgets displayed in the panel
**/
/**###Interface.Panel.shouldDraw : property
Boolean. Whenever the panel refreshes itself it will redraw widgets found in this array.
**/
/**###Interface.Panel.fps : property
Number. The number of times the panel should refresh itself per second.
**/
/**###Interface.Panel.useRelativeSizesAndPositions : property
Boolean. This determines whether widgets in the panel uses sizes/positions relative to the size of the panel or use absolute pixel coordinates.
**/
/**###Interface.Panel.container : property
HTMLElement. The HTMLElement (such as a div tag) containing the Panel.
**/
/**###Interface.Panel.canvas : property
HTMLElement. The canvas element that the Panel draws onto. This element is created when the panel is initialized.
**/
/**###Interface.Panel.touchEvent : method
The starting point for on-screen all touch event handling in a Panel. This method distributes events to all child widgets.
param **event** HTML Touch Event Object.
**/
/**###Interface.Panel.mouseEvent : method
The starting point for on-screen all mouse event handling in a Panel. This method distributes events to all child widgets.
param **event** HTML Mouse Event Object.
**/
/**###Interface.Panel.init : method
Initialization method called automatically when panel is instantiated.
**/
/**###Interface.Panel.x : property
Number. The x position of the panel in absolute coordinates relative to the window.
**/
/**###Interface.Panel.y : property
Number. The y position of the panel in absolute coordinates relative to the window.
**/
/**###Interface.Panel.width : property
Number. The width of the panel in pixels
**/
/**###Interface.Panel.width : property
Number. The height of the panel in pixels
**/
/**###Interface.Panel.draw : method
This method tells all 'dirty' widgets stored in the shouldDraw property to draw themselves.
**/
/**###Interface.Panel.refresh : method
Clear the entire panel and then tell all widgets to draw themselves.
**/
/**###Interface.Panel.add : method
Add a new widget to the panel
param **widget** Object. The widget to be added. Motion widgets do not need to be added to the Panel
**/
/**###Interface.Panel.setBackgroundColor : method
Set the background color the panel using a css color value.
param **cssColor** String. Any valid css color, such as 'red', '#f00', or 'rgb(255,0,0)'.
**/
/**###Interface.Panel.background : property
String. The default background color for all widgets in the panel. THIS IS NOT THE BACKGROUND COLOR FOR THE PANEL. Any valid css color, such as 'red', '#f00', or 'rgb(255,0,0)' can be assigned to this property.
**/
/**###Interface.Panel.fill : property
String. The default fill color for all widgets in the panel. Any valid css color, such as 'red', '#f00', or 'rgb(255,0,0)' can be assigned to this property.
**/
/**###Interface.Panel.stroke : property
String. The default stroke color for all widgets in the panel. Any valid css color, such as 'red', '#f00', or 'rgb(255,0,0)' can be assigned to this property.
**/
Interface.Panel = function() {
var self = this,
_container = arguments.length >= 1 ? arguments[0].container : undefined;
Interface.extend(this, {
type: 'Panel',
active: true,
children: [],
shouldDraw : [],
fps : 30,
useRelativeSizesAndPositions : true,
labelSize: '12px',
font:'normal 12px Helvetica',
serializeMe: ['fps', 'useRelativeSizesAndPositions', 'labelSize', 'font', 'background', 'fill', 'stroke', 'backgroundColor'],
container: (function() {
if(typeof _container === 'undefined') {
$('body').css({
margin : 0,
padding: 0,
});
var d = $('<div id="container">');
d.css({
width:$(window).width(),
height:$(window).height(),
display:'block',
margin:0,
padding:0,
position:'absolute',
left:0,
top:0
});
$('body').append(d);
return d;
}else{
return _container;
}
})(),
canvas: document.createElement('canvas'),
touchEvent : function(event) {
if(self.active) {
console.log( event )
if( typeof event.changedTouches === 'undefined' && event.originalEvent ) {
event.changedTouches = event.originalEvent.changedTouches
}
for (var j = 0; j < event.changedTouches.length; j++){
var touch = event.changedTouches.item(j);
for(var i = 0; i < self.children.length; i++) {
touch.x = touch.pageX - self.x;
touch.y = touch.pageY - self.y;
touch.type = event.type;
self.children[i].touchEvent(touch);
}
//var breakCheck = this.events[event.type].call(this, touch);
//if(breakCheck) break;
}
event.preventDefault(); // HTML Elements must simulate touch events in their touchEvent method
}
},
mouseEvent : function(e) {
if(self.active) {
if(e.type === 'mousedown') {
Interface.mouseDown = true;
}else if(e.type === 'mouseup') {
Interface.mouseDown = false;
}
var event = {
x : e.offsetX || (e.pageX - self.x), // pageX and pageY is for firefox compatibility
y : e.offsetY || (e.pageY - self.y),
type: e.type,
}
//console.log("MOUSE", event, self.y, e.pageY, e.layerY, e.clientY, e );
for(var i = 0; i < self.children.length; i++) {
self.children[i].mouseEvent(event);
}
}
},
init : function() {
var offset = $(this.container).offset();
this.width = $(this.container).width();
this.height = $(this.container).height();
this.x = offset.left;
this.y = offset.top;
if( isNaN(this.x) ) this.x = 0;
if( isNaN(this.y) ) this.y = 0;
$(this.canvas).attr({
'width': this.width,
'height': this.height,
});
$(this.container).css({ 'user-select': 'none', '-webkit-user-select': 'none'});
$(this.container).append(this.canvas);
this.ctx = this.canvas.getContext( '2d' );
this.ctx.translate(0.5, 0.5);
this.ctx.lineWidth = 1;
if(Interface.useTouch) {
$(this.container).on( 'touchstart', this.touchEvent );
$(this.container).on( 'touchmove', this.touchEvent );
$(this.container).on( 'touchend', this.touchEvent );
}else{
$(this.container).on( 'mousedown', this.mouseEvent );
$(this.container).on( 'mousemove', this.mouseEvent );
$(this.container).on( 'mouseup', this.mouseEvent );
}
$( this.container ).css({ outline: 'none' })
$( this.container ).attr( 'tabindex', 5 )
$( this.container ).on( 'keydown', this.keydown.bind( this ) )
$( this.container ).on( 'keyup', this.keyup.bind( this ) )
},
keydown: function(e) {
for( var i = 0; i < this.children.length; i++ ) {
if( this.children[i].onkeydown ) this.children[i].onkeydown(e)
}
},
keyup: function(e) {
for( var i = 0; i < this.children.length; i++ ) {
if( this.children[i].onkeyup ) this.children[i].onkeyup(e)
}
},
draw : function() {
if(this.active) {
for(var i = 0; i < this.shouldDraw.length; i++) {
this.shouldDraw[i].draw();
}
this.shouldDraw.length = 0;
}
},
getWidgetWithName: function( name ) {
for(var i = 0; i < this.children.length; i++) {
if( this.children[i].name === name) {
return this.children[i];
}
}
},
redoBoundaries : function() {
var offset = $(this.container).offset();
this.width = $(this.container).width();
this.height = $(this.container).height();
this.x = offset.left;
this.y = offset.top;
if( isNaN(this.x) ) this.x = 0;
if( isNaN(this.y) ) this.y = 0;
$(this.canvas).attr({
'width': this.width,
'height': this.height,
});
this.ctx.translate(0.5, 0.5);
this.ctx.lineWidth = 1;
this.refresh();
},
refresh: function() {
if(this.active) {