From afe2e577015d09c218897f2f9d3790c1dfe3b52d Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 24 Jun 2014 12:33:40 -0700 Subject: [PATCH 01/32] add a settings page to DS that uses handlebars template library --- domain-server/CMakeLists.txt | 6 ++-- .../resources/web/js/handlebars-v1.3.0.min.js | 28 +++++++++++++++++++ domain-server/resources/web/js/settings.js | 8 ++++++ .../resources/web/settings/describe.json | 10 +++++++ .../resources/web/settings/index.shtml | 13 +++++++++ domain-server/src/DomainServer.cpp | 2 +- .../src/DomainServerSettingsManager.cpp | 12 ++++++++ .../src/DomainServerSettingsManager.h | 21 ++++++++++++++ 8 files changed, 96 insertions(+), 4 deletions(-) create mode 100644 domain-server/resources/web/js/handlebars-v1.3.0.min.js create mode 100644 domain-server/resources/web/js/settings.js create mode 100644 domain-server/resources/web/settings/describe.json create mode 100644 domain-server/resources/web/settings/index.shtml create mode 100644 domain-server/src/DomainServerSettingsManager.cpp create mode 100644 domain-server/src/DomainServerSettingsManager.h diff --git a/domain-server/CMakeLists.txt b/domain-server/CMakeLists.txt index f9bbeb31fc..5650737965 100644 --- a/domain-server/CMakeLists.txt +++ b/domain-server/CMakeLists.txt @@ -25,11 +25,11 @@ setup_hifi_project(${TARGET_NAME} TRUE) # remove and then copy the files for the webserver add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND "${CMAKE_COMMAND}" -E remove_directory - $/resources/web) + $/resources) add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND "${CMAKE_COMMAND}" -E copy_directory - "${PROJECT_SOURCE_DIR}/resources/web" - $/resources/web) + "${PROJECT_SOURCE_DIR}/resources" + $/resources) # link the shared hifi library include(${MACRO_DIR}/LinkHifiLibrary.cmake) diff --git a/domain-server/resources/web/js/handlebars-v1.3.0.min.js b/domain-server/resources/web/js/handlebars-v1.3.0.min.js new file mode 100644 index 0000000000..06e9c01623 --- /dev/null +++ b/domain-server/resources/web/js/handlebars-v1.3.0.min.js @@ -0,0 +1,28 @@ +/*! + + handlebars v1.3.0 + +Copyright (C) 2011 by Yehuda Katz + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +@license +*/ +var Handlebars=function(){var a=function(){"use strict";function a(a){this.string=a}var b;return a.prototype.toString=function(){return""+this.string},b=a}(),b=function(a){"use strict";function b(a){return h[a]||"&"}function c(a,b){for(var c in b)Object.prototype.hasOwnProperty.call(b,c)&&(a[c]=b[c])}function d(a){return a instanceof g?a.toString():a||0===a?(a=""+a,j.test(a)?a.replace(i,b):a):""}function e(a){return a||0===a?m(a)&&0===a.length?!0:!1:!0}var f={},g=a,h={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},i=/[&<>"'`]/g,j=/[&<>"'`]/;f.extend=c;var k=Object.prototype.toString;f.toString=k;var l=function(a){return"function"==typeof a};l(/x/)&&(l=function(a){return"function"==typeof a&&"[object Function]"===k.call(a)});var l;f.isFunction=l;var m=Array.isArray||function(a){return a&&"object"==typeof a?"[object Array]"===k.call(a):!1};return f.isArray=m,f.escapeExpression=d,f.isEmpty=e,f}(a),c=function(){"use strict";function a(a,b){var d;b&&b.firstLine&&(d=b.firstLine,a+=" - "+d+":"+b.firstColumn);for(var e=Error.prototype.constructor.call(this,a),f=0;f0?a.helpers.each(b,c):d(this):e(b)}),a.registerHelper("each",function(a,b){var c,d=b.fn,e=b.inverse,f=0,g="";if(m(a)&&(a=a.call(this)),b.data&&(c=q(b.data)),a&&"object"==typeof a)if(l(a))for(var h=a.length;h>f;f++)c&&(c.index=f,c.first=0===f,c.last=f===a.length-1),g+=d(a[f],{data:c});else for(var i in a)a.hasOwnProperty(i)&&(c&&(c.key=i,c.index=f,c.first=0===f),g+=d(a[i],{data:c}),f++);return 0===f&&(g=e(this)),g}),a.registerHelper("if",function(a,b){return m(a)&&(a=a.call(this)),!b.hash.includeZero&&!a||g.isEmpty(a)?b.inverse(this):b.fn(this)}),a.registerHelper("unless",function(b,c){return a.helpers["if"].call(this,b,{fn:c.inverse,inverse:c.fn,hash:c.hash})}),a.registerHelper("with",function(a,b){return m(a)&&(a=a.call(this)),g.isEmpty(a)?void 0:b.fn(a)}),a.registerHelper("log",function(b,c){var d=c.data&&null!=c.data.level?parseInt(c.data.level,10):1;a.log(d,b)})}function e(a,b){p.log(a,b)}var f={},g=a,h=b,i="1.3.0";f.VERSION=i;var j=4;f.COMPILER_REVISION=j;var k={1:"<= 1.0.rc.2",2:"== 1.0.0-rc.3",3:"== 1.0.0-rc.4",4:">= 1.0.0"};f.REVISION_CHANGES=k;var l=g.isArray,m=g.isFunction,n=g.toString,o="[object Object]";f.HandlebarsEnvironment=c,c.prototype={constructor:c,logger:p,log:e,registerHelper:function(a,b,c){if(n.call(a)===o){if(c||b)throw new h("Arg not supported with multiple helpers");g.extend(this.helpers,a)}else c&&(b.not=c),this.helpers[a]=b},registerPartial:function(a,b){n.call(a)===o?g.extend(this.partials,a):this.partials[a]=b}};var p={methodMap:{0:"debug",1:"info",2:"warn",3:"error"},DEBUG:0,INFO:1,WARN:2,ERROR:3,level:3,log:function(a,b){if(p.level<=a){var c=p.methodMap[a];"undefined"!=typeof console&&console[c]&&console[c].call(console,b)}}};f.logger=p,f.log=e;var q=function(a){var b={};return g.extend(b,a),b};return f.createFrame=q,f}(b,c),e=function(a,b,c){"use strict";function d(a){var b=a&&a[0]||1,c=m;if(b!==c){if(c>b){var d=n[c],e=n[b];throw new l("Template was precompiled with an older version of Handlebars than the current runtime. Please update your precompiler to a newer version ("+d+") or downgrade your runtime to an older version ("+e+").")}throw new l("Template was precompiled with a newer version of Handlebars than the current runtime. Please update your runtime to a newer version ("+a[1]+").")}}function e(a,b){if(!b)throw new l("No environment passed to template");var c=function(a,c,d,e,f,g){var h=b.VM.invokePartial.apply(this,arguments);if(null!=h)return h;if(b.compile){var i={helpers:e,partials:f,data:g};return f[c]=b.compile(a,{data:void 0!==g},b),f[c](d,i)}throw new l("The partial "+c+" could not be compiled when running in runtime-only mode")},d={escapeExpression:k.escapeExpression,invokePartial:c,programs:[],program:function(a,b,c){var d=this.programs[a];return c?d=g(a,b,c):d||(d=this.programs[a]=g(a,b)),d},merge:function(a,b){var c=a||b;return a&&b&&a!==b&&(c={},k.extend(c,b),k.extend(c,a)),c},programWithDepth:b.VM.programWithDepth,noop:b.VM.noop,compilerInfo:null};return function(c,e){e=e||{};var f,g,h=e.partial?e:b;e.partial||(f=e.helpers,g=e.partials);var i=a.call(d,h,c,f,g,e.data);return e.partial||b.VM.checkRevision(d.compilerInfo),i}}function f(a,b,c){var d=Array.prototype.slice.call(arguments,3),e=function(a,e){return e=e||{},b.apply(this,[a,e.data||c].concat(d))};return e.program=a,e.depth=d.length,e}function g(a,b,c){var d=function(a,d){return d=d||{},b(a,d.data||c)};return d.program=a,d.depth=0,d}function h(a,b,c,d,e,f){var g={partial:!0,helpers:d,partials:e,data:f};if(void 0===a)throw new l("The partial "+b+" could not be found");return a instanceof Function?a(c,g):void 0}function i(){return""}var j={},k=a,l=b,m=c.COMPILER_REVISION,n=c.REVISION_CHANGES;return j.checkRevision=d,j.template=e,j.programWithDepth=f,j.program=g,j.invokePartial=h,j.noop=i,j}(b,c,d),f=function(a,b,c,d,e){"use strict";var f,g=a,h=b,i=c,j=d,k=e,l=function(){var a=new g.HandlebarsEnvironment;return j.extend(a,g),a.SafeString=h,a.Exception=i,a.Utils=j,a.VM=k,a.template=function(b){return k.template(b,a)},a},m=l();return m.create=l,f=m}(d,a,c,b,e),g=function(a){"use strict";function b(a){a=a||{},this.firstLine=a.first_line,this.firstColumn=a.first_column,this.lastColumn=a.last_column,this.lastLine=a.last_line}var c,d=a,e={ProgramNode:function(a,c,d,f){var g,h;3===arguments.length?(f=d,d=null):2===arguments.length&&(f=c,c=null),b.call(this,f),this.type="program",this.statements=a,this.strip={},d?(h=d[0],h?(g={first_line:h.firstLine,last_line:h.lastLine,last_column:h.lastColumn,first_column:h.firstColumn},this.inverse=new e.ProgramNode(d,c,g)):this.inverse=new e.ProgramNode(d,c),this.strip.right=c.left):c&&(this.strip.left=c.right)},MustacheNode:function(a,c,d,f,g){if(b.call(this,g),this.type="mustache",this.strip=f,null!=d&&d.charAt){var h=d.charAt(3)||d.charAt(2);this.escaped="{"!==h&&"&"!==h}else this.escaped=!!d;this.sexpr=a instanceof e.SexprNode?a:new e.SexprNode(a,c),this.sexpr.isRoot=!0,this.id=this.sexpr.id,this.params=this.sexpr.params,this.hash=this.sexpr.hash,this.eligibleHelper=this.sexpr.eligibleHelper,this.isHelper=this.sexpr.isHelper},SexprNode:function(a,c,d){b.call(this,d),this.type="sexpr",this.hash=c;var e=this.id=a[0],f=this.params=a.slice(1),g=this.eligibleHelper=e.isSimple;this.isHelper=g&&(f.length||c)},PartialNode:function(a,c,d,e){b.call(this,e),this.type="partial",this.partialName=a,this.context=c,this.strip=d},BlockNode:function(a,c,e,f,g){if(b.call(this,g),a.sexpr.id.original!==f.path.original)throw new d(a.sexpr.id.original+" doesn't match "+f.path.original,this);this.type="block",this.mustache=a,this.program=c,this.inverse=e,this.strip={left:a.strip.left,right:f.strip.right},(c||e).strip.left=a.strip.right,(e||c).strip.right=f.strip.left,e&&!c&&(this.isInverse=!0)},ContentNode:function(a,c){b.call(this,c),this.type="content",this.string=a},HashNode:function(a,c){b.call(this,c),this.type="hash",this.pairs=a},IdNode:function(a,c){b.call(this,c),this.type="ID";for(var e="",f=[],g=0,h=0,i=a.length;i>h;h++){var j=a[h].part;if(e+=(a[h].separator||"")+j,".."===j||"."===j||"this"===j){if(f.length>0)throw new d("Invalid path: "+e,this);".."===j?g++:this.isScoped=!0}else f.push(j)}this.original=e,this.parts=f,this.string=f.join("."),this.depth=g,this.isSimple=1===a.length&&!this.isScoped&&0===g,this.stringModeValue=this.string},PartialNameNode:function(a,c){b.call(this,c),this.type="PARTIAL_NAME",this.name=a.original},DataNode:function(a,c){b.call(this,c),this.type="DATA",this.id=a},StringNode:function(a,c){b.call(this,c),this.type="STRING",this.original=this.string=this.stringModeValue=a},IntegerNode:function(a,c){b.call(this,c),this.type="INTEGER",this.original=this.integer=a,this.stringModeValue=Number(a)},BooleanNode:function(a,c){b.call(this,c),this.type="BOOLEAN",this.bool=a,this.stringModeValue="true"===a},CommentNode:function(a,c){b.call(this,c),this.type="comment",this.comment=a}};return c=e}(c),h=function(){"use strict";var a,b=function(){function a(a,b){return{left:"~"===a.charAt(2),right:"~"===b.charAt(0)||"~"===b.charAt(1)}}function b(){this.yy={}}var c={trace:function(){},yy:{},symbols_:{error:2,root:3,statements:4,EOF:5,program:6,simpleInverse:7,statement:8,openInverse:9,closeBlock:10,openBlock:11,mustache:12,partial:13,CONTENT:14,COMMENT:15,OPEN_BLOCK:16,sexpr:17,CLOSE:18,OPEN_INVERSE:19,OPEN_ENDBLOCK:20,path:21,OPEN:22,OPEN_UNESCAPED:23,CLOSE_UNESCAPED:24,OPEN_PARTIAL:25,partialName:26,partial_option0:27,sexpr_repetition0:28,sexpr_option0:29,dataName:30,param:31,STRING:32,INTEGER:33,BOOLEAN:34,OPEN_SEXPR:35,CLOSE_SEXPR:36,hash:37,hash_repetition_plus0:38,hashSegment:39,ID:40,EQUALS:41,DATA:42,pathSegments:43,SEP:44,$accept:0,$end:1},terminals_:{2:"error",5:"EOF",14:"CONTENT",15:"COMMENT",16:"OPEN_BLOCK",18:"CLOSE",19:"OPEN_INVERSE",20:"OPEN_ENDBLOCK",22:"OPEN",23:"OPEN_UNESCAPED",24:"CLOSE_UNESCAPED",25:"OPEN_PARTIAL",32:"STRING",33:"INTEGER",34:"BOOLEAN",35:"OPEN_SEXPR",36:"CLOSE_SEXPR",40:"ID",41:"EQUALS",42:"DATA",44:"SEP"},productions_:[0,[3,2],[3,1],[6,2],[6,3],[6,2],[6,1],[6,1],[6,0],[4,1],[4,2],[8,3],[8,3],[8,1],[8,1],[8,1],[8,1],[11,3],[9,3],[10,3],[12,3],[12,3],[13,4],[7,2],[17,3],[17,1],[31,1],[31,1],[31,1],[31,1],[31,1],[31,3],[37,1],[39,3],[26,1],[26,1],[26,1],[30,2],[21,1],[43,3],[43,1],[27,0],[27,1],[28,0],[28,2],[29,0],[29,1],[38,1],[38,2]],performAction:function(b,c,d,e,f,g){var h=g.length-1;switch(f){case 1:return new e.ProgramNode(g[h-1],this._$);case 2:return new e.ProgramNode([],this._$);case 3:this.$=new e.ProgramNode([],g[h-1],g[h],this._$);break;case 4:this.$=new e.ProgramNode(g[h-2],g[h-1],g[h],this._$);break;case 5:this.$=new e.ProgramNode(g[h-1],g[h],[],this._$);break;case 6:this.$=new e.ProgramNode(g[h],this._$);break;case 7:this.$=new e.ProgramNode([],this._$);break;case 8:this.$=new e.ProgramNode([],this._$);break;case 9:this.$=[g[h]];break;case 10:g[h-1].push(g[h]),this.$=g[h-1];break;case 11:this.$=new e.BlockNode(g[h-2],g[h-1].inverse,g[h-1],g[h],this._$);break;case 12:this.$=new e.BlockNode(g[h-2],g[h-1],g[h-1].inverse,g[h],this._$);break;case 13:this.$=g[h];break;case 14:this.$=g[h];break;case 15:this.$=new e.ContentNode(g[h],this._$);break;case 16:this.$=new e.CommentNode(g[h],this._$);break;case 17:this.$=new e.MustacheNode(g[h-1],null,g[h-2],a(g[h-2],g[h]),this._$);break;case 18:this.$=new e.MustacheNode(g[h-1],null,g[h-2],a(g[h-2],g[h]),this._$);break;case 19:this.$={path:g[h-1],strip:a(g[h-2],g[h])};break;case 20:this.$=new e.MustacheNode(g[h-1],null,g[h-2],a(g[h-2],g[h]),this._$);break;case 21:this.$=new e.MustacheNode(g[h-1],null,g[h-2],a(g[h-2],g[h]),this._$);break;case 22:this.$=new e.PartialNode(g[h-2],g[h-1],a(g[h-3],g[h]),this._$);break;case 23:this.$=a(g[h-1],g[h]);break;case 24:this.$=new e.SexprNode([g[h-2]].concat(g[h-1]),g[h],this._$);break;case 25:this.$=new e.SexprNode([g[h]],null,this._$);break;case 26:this.$=g[h];break;case 27:this.$=new e.StringNode(g[h],this._$);break;case 28:this.$=new e.IntegerNode(g[h],this._$);break;case 29:this.$=new e.BooleanNode(g[h],this._$);break;case 30:this.$=g[h];break;case 31:g[h-1].isHelper=!0,this.$=g[h-1];break;case 32:this.$=new e.HashNode(g[h],this._$);break;case 33:this.$=[g[h-2],g[h]];break;case 34:this.$=new e.PartialNameNode(g[h],this._$);break;case 35:this.$=new e.PartialNameNode(new e.StringNode(g[h],this._$),this._$);break;case 36:this.$=new e.PartialNameNode(new e.IntegerNode(g[h],this._$));break;case 37:this.$=new e.DataNode(g[h],this._$);break;case 38:this.$=new e.IdNode(g[h],this._$);break;case 39:g[h-2].push({part:g[h],separator:g[h-1]}),this.$=g[h-2];break;case 40:this.$=[{part:g[h]}];break;case 43:this.$=[];break;case 44:g[h-1].push(g[h]);break;case 47:this.$=[g[h]];break;case 48:g[h-1].push(g[h])}},table:[{3:1,4:2,5:[1,3],8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],22:[1,13],23:[1,14],25:[1,15]},{1:[3]},{5:[1,16],8:17,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],22:[1,13],23:[1,14],25:[1,15]},{1:[2,2]},{5:[2,9],14:[2,9],15:[2,9],16:[2,9],19:[2,9],20:[2,9],22:[2,9],23:[2,9],25:[2,9]},{4:20,6:18,7:19,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,21],20:[2,8],22:[1,13],23:[1,14],25:[1,15]},{4:20,6:22,7:19,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,21],20:[2,8],22:[1,13],23:[1,14],25:[1,15]},{5:[2,13],14:[2,13],15:[2,13],16:[2,13],19:[2,13],20:[2,13],22:[2,13],23:[2,13],25:[2,13]},{5:[2,14],14:[2,14],15:[2,14],16:[2,14],19:[2,14],20:[2,14],22:[2,14],23:[2,14],25:[2,14]},{5:[2,15],14:[2,15],15:[2,15],16:[2,15],19:[2,15],20:[2,15],22:[2,15],23:[2,15],25:[2,15]},{5:[2,16],14:[2,16],15:[2,16],16:[2,16],19:[2,16],20:[2,16],22:[2,16],23:[2,16],25:[2,16]},{17:23,21:24,30:25,40:[1,28],42:[1,27],43:26},{17:29,21:24,30:25,40:[1,28],42:[1,27],43:26},{17:30,21:24,30:25,40:[1,28],42:[1,27],43:26},{17:31,21:24,30:25,40:[1,28],42:[1,27],43:26},{21:33,26:32,32:[1,34],33:[1,35],40:[1,28],43:26},{1:[2,1]},{5:[2,10],14:[2,10],15:[2,10],16:[2,10],19:[2,10],20:[2,10],22:[2,10],23:[2,10],25:[2,10]},{10:36,20:[1,37]},{4:38,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,7],22:[1,13],23:[1,14],25:[1,15]},{7:39,8:17,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,21],20:[2,6],22:[1,13],23:[1,14],25:[1,15]},{17:23,18:[1,40],21:24,30:25,40:[1,28],42:[1,27],43:26},{10:41,20:[1,37]},{18:[1,42]},{18:[2,43],24:[2,43],28:43,32:[2,43],33:[2,43],34:[2,43],35:[2,43],36:[2,43],40:[2,43],42:[2,43]},{18:[2,25],24:[2,25],36:[2,25]},{18:[2,38],24:[2,38],32:[2,38],33:[2,38],34:[2,38],35:[2,38],36:[2,38],40:[2,38],42:[2,38],44:[1,44]},{21:45,40:[1,28],43:26},{18:[2,40],24:[2,40],32:[2,40],33:[2,40],34:[2,40],35:[2,40],36:[2,40],40:[2,40],42:[2,40],44:[2,40]},{18:[1,46]},{18:[1,47]},{24:[1,48]},{18:[2,41],21:50,27:49,40:[1,28],43:26},{18:[2,34],40:[2,34]},{18:[2,35],40:[2,35]},{18:[2,36],40:[2,36]},{5:[2,11],14:[2,11],15:[2,11],16:[2,11],19:[2,11],20:[2,11],22:[2,11],23:[2,11],25:[2,11]},{21:51,40:[1,28],43:26},{8:17,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,3],22:[1,13],23:[1,14],25:[1,15]},{4:52,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,5],22:[1,13],23:[1,14],25:[1,15]},{14:[2,23],15:[2,23],16:[2,23],19:[2,23],20:[2,23],22:[2,23],23:[2,23],25:[2,23]},{5:[2,12],14:[2,12],15:[2,12],16:[2,12],19:[2,12],20:[2,12],22:[2,12],23:[2,12],25:[2,12]},{14:[2,18],15:[2,18],16:[2,18],19:[2,18],20:[2,18],22:[2,18],23:[2,18],25:[2,18]},{18:[2,45],21:56,24:[2,45],29:53,30:60,31:54,32:[1,57],33:[1,58],34:[1,59],35:[1,61],36:[2,45],37:55,38:62,39:63,40:[1,64],42:[1,27],43:26},{40:[1,65]},{18:[2,37],24:[2,37],32:[2,37],33:[2,37],34:[2,37],35:[2,37],36:[2,37],40:[2,37],42:[2,37]},{14:[2,17],15:[2,17],16:[2,17],19:[2,17],20:[2,17],22:[2,17],23:[2,17],25:[2,17]},{5:[2,20],14:[2,20],15:[2,20],16:[2,20],19:[2,20],20:[2,20],22:[2,20],23:[2,20],25:[2,20]},{5:[2,21],14:[2,21],15:[2,21],16:[2,21],19:[2,21],20:[2,21],22:[2,21],23:[2,21],25:[2,21]},{18:[1,66]},{18:[2,42]},{18:[1,67]},{8:17,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,4],22:[1,13],23:[1,14],25:[1,15]},{18:[2,24],24:[2,24],36:[2,24]},{18:[2,44],24:[2,44],32:[2,44],33:[2,44],34:[2,44],35:[2,44],36:[2,44],40:[2,44],42:[2,44]},{18:[2,46],24:[2,46],36:[2,46]},{18:[2,26],24:[2,26],32:[2,26],33:[2,26],34:[2,26],35:[2,26],36:[2,26],40:[2,26],42:[2,26]},{18:[2,27],24:[2,27],32:[2,27],33:[2,27],34:[2,27],35:[2,27],36:[2,27],40:[2,27],42:[2,27]},{18:[2,28],24:[2,28],32:[2,28],33:[2,28],34:[2,28],35:[2,28],36:[2,28],40:[2,28],42:[2,28]},{18:[2,29],24:[2,29],32:[2,29],33:[2,29],34:[2,29],35:[2,29],36:[2,29],40:[2,29],42:[2,29]},{18:[2,30],24:[2,30],32:[2,30],33:[2,30],34:[2,30],35:[2,30],36:[2,30],40:[2,30],42:[2,30]},{17:68,21:24,30:25,40:[1,28],42:[1,27],43:26},{18:[2,32],24:[2,32],36:[2,32],39:69,40:[1,70]},{18:[2,47],24:[2,47],36:[2,47],40:[2,47]},{18:[2,40],24:[2,40],32:[2,40],33:[2,40],34:[2,40],35:[2,40],36:[2,40],40:[2,40],41:[1,71],42:[2,40],44:[2,40]},{18:[2,39],24:[2,39],32:[2,39],33:[2,39],34:[2,39],35:[2,39],36:[2,39],40:[2,39],42:[2,39],44:[2,39]},{5:[2,22],14:[2,22],15:[2,22],16:[2,22],19:[2,22],20:[2,22],22:[2,22],23:[2,22],25:[2,22]},{5:[2,19],14:[2,19],15:[2,19],16:[2,19],19:[2,19],20:[2,19],22:[2,19],23:[2,19],25:[2,19]},{36:[1,72]},{18:[2,48],24:[2,48],36:[2,48],40:[2,48]},{41:[1,71]},{21:56,30:60,31:73,32:[1,57],33:[1,58],34:[1,59],35:[1,61],40:[1,28],42:[1,27],43:26},{18:[2,31],24:[2,31],32:[2,31],33:[2,31],34:[2,31],35:[2,31],36:[2,31],40:[2,31],42:[2,31]},{18:[2,33],24:[2,33],36:[2,33],40:[2,33]}],defaultActions:{3:[2,2],16:[2,1],50:[2,42]},parseError:function(a){throw new Error(a)},parse:function(a){function b(){var a;return a=c.lexer.lex()||1,"number"!=typeof a&&(a=c.symbols_[a]||a),a}var c=this,d=[0],e=[null],f=[],g=this.table,h="",i=0,j=0,k=0;this.lexer.setInput(a),this.lexer.yy=this.yy,this.yy.lexer=this.lexer,this.yy.parser=this,"undefined"==typeof this.lexer.yylloc&&(this.lexer.yylloc={});var l=this.lexer.yylloc;f.push(l);var m=this.lexer.options&&this.lexer.options.ranges;"function"==typeof this.yy.parseError&&(this.parseError=this.yy.parseError);for(var n,o,p,q,r,s,t,u,v,w={};;){if(p=d[d.length-1],this.defaultActions[p]?q=this.defaultActions[p]:((null===n||"undefined"==typeof n)&&(n=b()),q=g[p]&&g[p][n]),"undefined"==typeof q||!q.length||!q[0]){var x="";if(!k){v=[];for(s in g[p])this.terminals_[s]&&s>2&&v.push("'"+this.terminals_[s]+"'");x=this.lexer.showPosition?"Parse error on line "+(i+1)+":\n"+this.lexer.showPosition()+"\nExpecting "+v.join(", ")+", got '"+(this.terminals_[n]||n)+"'":"Parse error on line "+(i+1)+": Unexpected "+(1==n?"end of input":"'"+(this.terminals_[n]||n)+"'"),this.parseError(x,{text:this.lexer.match,token:this.terminals_[n]||n,line:this.lexer.yylineno,loc:l,expected:v})}}if(q[0]instanceof Array&&q.length>1)throw new Error("Parse Error: multiple actions possible at state: "+p+", token: "+n);switch(q[0]){case 1:d.push(n),e.push(this.lexer.yytext),f.push(this.lexer.yylloc),d.push(q[1]),n=null,o?(n=o,o=null):(j=this.lexer.yyleng,h=this.lexer.yytext,i=this.lexer.yylineno,l=this.lexer.yylloc,k>0&&k--);break;case 2:if(t=this.productions_[q[1]][1],w.$=e[e.length-t],w._$={first_line:f[f.length-(t||1)].first_line,last_line:f[f.length-1].last_line,first_column:f[f.length-(t||1)].first_column,last_column:f[f.length-1].last_column},m&&(w._$.range=[f[f.length-(t||1)].range[0],f[f.length-1].range[1]]),r=this.performAction.call(w,h,j,i,this.yy,q[1],e,f),"undefined"!=typeof r)return r;t&&(d=d.slice(0,-1*t*2),e=e.slice(0,-1*t),f=f.slice(0,-1*t)),d.push(this.productions_[q[1]][0]),e.push(w.$),f.push(w._$),u=g[d[d.length-2]][d[d.length-1]],d.push(u);break;case 3:return!0}}return!0}},d=function(){var a={EOF:1,parseError:function(a,b){if(!this.yy.parser)throw new Error(a);this.yy.parser.parseError(a,b)},setInput:function(a){return this._input=a,this._more=this._less=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var a=this._input[0];this.yytext+=a,this.yyleng++,this.offset++,this.match+=a,this.matched+=a;var b=a.match(/(?:\r\n?|\n).*/g);return b?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),a},unput:function(a){var b=a.length,c=a.split(/(?:\r\n?|\n)/g);this._input=a+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-b-1),this.offset-=b;var d=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),c.length-1&&(this.yylineno-=c.length-1);var e=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:c?(c.length===d.length?this.yylloc.first_column:0)+d[d.length-c.length].length-c[0].length:this.yylloc.first_column-b},this.options.ranges&&(this.yylloc.range=[e[0],e[0]+this.yyleng-b]),this},more:function(){return this._more=!0,this},less:function(a){this.unput(this.match.slice(a))},pastInput:function(){var a=this.matched.substr(0,this.matched.length-this.match.length);return(a.length>20?"...":"")+a.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var a=this.match;return a.length<20&&(a+=this._input.substr(0,20-a.length)),(a.substr(0,20)+(a.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var a=this.pastInput(),b=new Array(a.length+1).join("-");return a+this.upcomingInput()+"\n"+b+"^"},next:function(){if(this.done)return this.EOF;this._input||(this.done=!0);var a,b,c,d,e;this._more||(this.yytext="",this.match="");for(var f=this._currentRules(),g=0;gb[0].length)||(b=c,d=g,this.options.flex));g++);return b?(e=b[0].match(/(?:\r\n?|\n).*/g),e&&(this.yylineno+=e.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:e?e[e.length-1].length-e[e.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+b[0].length},this.yytext+=b[0],this.match+=b[0],this.matches=b,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._input=this._input.slice(b[0].length),this.matched+=b[0],a=this.performAction.call(this,this.yy,this,f[d],this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),a?a:void 0):""===this._input?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+". Unrecognized text.\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){var a=this.next();return"undefined"!=typeof a?a:this.lex()},begin:function(a){this.conditionStack.push(a)},popState:function(){return this.conditionStack.pop()},_currentRules:function(){return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules},topState:function(){return this.conditionStack[this.conditionStack.length-2]},pushState:function(a){this.begin(a)}};return a.options={},a.performAction=function(a,b,c,d){function e(a,c){return b.yytext=b.yytext.substr(a,b.yyleng-c)}switch(c){case 0:if("\\\\"===b.yytext.slice(-2)?(e(0,1),this.begin("mu")):"\\"===b.yytext.slice(-1)?(e(0,1),this.begin("emu")):this.begin("mu"),b.yytext)return 14;break;case 1:return 14;case 2:return this.popState(),14;case 3:return e(0,4),this.popState(),15;case 4:return 35;case 5:return 36;case 6:return 25;case 7:return 16;case 8:return 20;case 9:return 19;case 10:return 19;case 11:return 23;case 12:return 22;case 13:this.popState(),this.begin("com");break;case 14:return e(3,5),this.popState(),15;case 15:return 22;case 16:return 41;case 17:return 40;case 18:return 40;case 19:return 44;case 20:break;case 21:return this.popState(),24;case 22:return this.popState(),18;case 23:return b.yytext=e(1,2).replace(/\\"/g,'"'),32;case 24:return b.yytext=e(1,2).replace(/\\'/g,"'"),32;case 25:return 42;case 26:return 34;case 27:return 34;case 28:return 33;case 29:return 40;case 30:return b.yytext=e(1,2),40;case 31:return"INVALID";case 32:return 5}},a.rules=[/^(?:[^\x00]*?(?=(\{\{)))/,/^(?:[^\x00]+)/,/^(?:[^\x00]{2,}?(?=(\{\{|\\\{\{|\\\\\{\{|$)))/,/^(?:[\s\S]*?--\}\})/,/^(?:\()/,/^(?:\))/,/^(?:\{\{(~)?>)/,/^(?:\{\{(~)?#)/,/^(?:\{\{(~)?\/)/,/^(?:\{\{(~)?\^)/,/^(?:\{\{(~)?\s*else\b)/,/^(?:\{\{(~)?\{)/,/^(?:\{\{(~)?&)/,/^(?:\{\{!--)/,/^(?:\{\{![\s\S]*?\}\})/,/^(?:\{\{(~)?)/,/^(?:=)/,/^(?:\.\.)/,/^(?:\.(?=([=~}\s\/.)])))/,/^(?:[\/.])/,/^(?:\s+)/,/^(?:\}(~)?\}\})/,/^(?:(~)?\}\})/,/^(?:"(\\["]|[^"])*")/,/^(?:'(\\[']|[^'])*')/,/^(?:@)/,/^(?:true(?=([~}\s)])))/,/^(?:false(?=([~}\s)])))/,/^(?:-?[0-9]+(?=([~}\s)])))/,/^(?:([^\s!"#%-,\.\/;->@\[-\^`\{-~]+(?=([=~}\s\/.)]))))/,/^(?:\[[^\]]*\])/,/^(?:.)/,/^(?:$)/],a.conditions={mu:{rules:[4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32],inclusive:!1},emu:{rules:[2],inclusive:!1},com:{rules:[3],inclusive:!1},INITIAL:{rules:[0,1,32],inclusive:!0}},a}();return c.lexer=d,b.prototype=c,c.Parser=b,new b}();return a=b}(),i=function(a,b){"use strict";function c(a){return a.constructor===f.ProgramNode?a:(e.yy=f,e.parse(a))}var d={},e=a,f=b;return d.parser=e,d.parse=c,d}(h,g),j=function(a){"use strict";function b(){}function c(a,b,c){if(null==a||"string"!=typeof a&&a.constructor!==c.AST.ProgramNode)throw new f("You must pass a string or Handlebars AST to Handlebars.precompile. You passed "+a);b=b||{},"data"in b||(b.data=!0);var d=c.parse(a),e=(new c.Compiler).compile(d,b);return(new c.JavaScriptCompiler).compile(e,b)}function d(a,b,c){function d(){var d=c.parse(a),e=(new c.Compiler).compile(d,b),f=(new c.JavaScriptCompiler).compile(e,b,void 0,!0);return c.template(f)}if(null==a||"string"!=typeof a&&a.constructor!==c.AST.ProgramNode)throw new f("You must pass a string or Handlebars AST to Handlebars.compile. You passed "+a);b=b||{},"data"in b||(b.data=!0);var e;return function(a,b){return e||(e=d()),e.call(this,a,b)}}var e={},f=a;return e.Compiler=b,b.prototype={compiler:b,disassemble:function(){for(var a,b,c,d=this.opcodes,e=[],f=0,g=d.length;g>f;f++)if(a=d[f],"DECLARE"===a.opcode)e.push("DECLARE "+a.name+"="+a.value);else{b=[];for(var h=0;hc;c++){var d=this.opcodes[c],e=a.opcodes[c];if(d.opcode!==e.opcode||d.args.length!==e.args.length)return!1;for(var f=0;fc;c++)if(!this.children[c].equals(a.children[c]))return!1;return!0},guid:0,compile:function(a,b){this.opcodes=[],this.children=[],this.depths={list:[]},this.options=b;var c=this.options.knownHelpers;if(this.options.knownHelpers={helperMissing:!0,blockHelperMissing:!0,each:!0,"if":!0,unless:!0,"with":!0,log:!0},c)for(var d in c)this.options.knownHelpers[d]=c[d];return this.accept(a)},accept:function(a){var b,c=a.strip||{};return c.left&&this.opcode("strip"),b=this[a.type](a),c.right&&this.opcode("strip"),b},program:function(a){for(var b=a.statements,c=0,d=b.length;d>c;c++)this.accept(b[c]);return this.isSimple=1===d,this.depths.list=this.depths.list.sort(function(a,b){return a-b}),this},compileProgram:function(a){var b,c=(new this.compiler).compile(a,this.options),d=this.guid++;this.usePartial=this.usePartial||c.usePartial,this.children[d]=c;for(var e=0,f=c.depths.list.length;f>e;e++)b=c.depths.list[e],2>b||this.addDepth(b-1);return d},block:function(a){var b=a.mustache,c=a.program,d=a.inverse;c&&(c=this.compileProgram(c)),d&&(d=this.compileProgram(d));var e=b.sexpr,f=this.classifySexpr(e);"helper"===f?this.helperSexpr(e,c,d):"simple"===f?(this.simpleSexpr(e),this.opcode("pushProgram",c),this.opcode("pushProgram",d),this.opcode("emptyHash"),this.opcode("blockValue")):(this.ambiguousSexpr(e,c,d),this.opcode("pushProgram",c),this.opcode("pushProgram",d),this.opcode("emptyHash"),this.opcode("ambiguousBlockValue")),this.opcode("append")},hash:function(a){var b,c,d=a.pairs;this.opcode("pushHash");for(var e=0,f=d.length;f>e;e++)b=d[e],c=b[1],this.options.stringParams?(c.depth&&this.addDepth(c.depth),this.opcode("getContext",c.depth||0),this.opcode("pushStringParam",c.stringModeValue,c.type),"sexpr"===c.type&&this.sexpr(c)):this.accept(c),this.opcode("assignToHash",b[0]);this.opcode("popHash")},partial:function(a){var b=a.partialName;this.usePartial=!0,a.context?this.ID(a.context):this.opcode("push","depth0"),this.opcode("invokePartial",b.name),this.opcode("append")},content:function(a){this.opcode("appendContent",a.string)},mustache:function(a){this.sexpr(a.sexpr),a.escaped&&!this.options.noEscape?this.opcode("appendEscaped"):this.opcode("append")},ambiguousSexpr:function(a,b,c){var d=a.id,e=d.parts[0],f=null!=b||null!=c;this.opcode("getContext",d.depth),this.opcode("pushProgram",b),this.opcode("pushProgram",c),this.opcode("invokeAmbiguous",e,f)},simpleSexpr:function(a){var b=a.id;"DATA"===b.type?this.DATA(b):b.parts.length?this.ID(b):(this.addDepth(b.depth),this.opcode("getContext",b.depth),this.opcode("pushContext")),this.opcode("resolvePossibleLambda")},helperSexpr:function(a,b,c){var d=this.setupFullMustacheParams(a,b,c),e=a.id.parts[0];if(this.options.knownHelpers[e])this.opcode("invokeKnownHelper",d.length,e);else{if(this.options.knownHelpersOnly)throw new f("You specified knownHelpersOnly, but used the unknown helper "+e,a);this.opcode("invokeHelper",d.length,e,a.isRoot)}},sexpr:function(a){var b=this.classifySexpr(a);"simple"===b?this.simpleSexpr(a):"helper"===b?this.helperSexpr(a):this.ambiguousSexpr(a)},ID:function(a){this.addDepth(a.depth),this.opcode("getContext",a.depth);var b=a.parts[0];b?this.opcode("lookupOnContext",a.parts[0]):this.opcode("pushContext");for(var c=1,d=a.parts.length;d>c;c++)this.opcode("lookup",a.parts[c])},DATA:function(a){if(this.options.data=!0,a.id.isScoped||a.id.depth)throw new f("Scoped data references are not supported: "+a.original,a);this.opcode("lookupData");for(var b=a.id.parts,c=0,d=b.length;d>c;c++)this.opcode("lookup",b[c])},STRING:function(a){this.opcode("pushString",a.string)},INTEGER:function(a){this.opcode("pushLiteral",a.integer)},BOOLEAN:function(a){this.opcode("pushLiteral",a.bool)},comment:function(){},opcode:function(a){this.opcodes.push({opcode:a,args:[].slice.call(arguments,1)})},declare:function(a,b){this.opcodes.push({opcode:"DECLARE",name:a,value:b})},addDepth:function(a){0!==a&&(this.depths[a]||(this.depths[a]=!0,this.depths.list.push(a)))},classifySexpr:function(a){var b=a.isHelper,c=a.eligibleHelper,d=this.options;if(c&&!b){var e=a.id.parts[0];d.knownHelpers[e]?b=!0:d.knownHelpersOnly&&(c=!1)}return b?"helper":c?"ambiguous":"simple"},pushParams:function(a){for(var b,c=a.length;c--;)b=a[c],this.options.stringParams?(b.depth&&this.addDepth(b.depth),this.opcode("getContext",b.depth||0),this.opcode("pushStringParam",b.stringModeValue,b.type),"sexpr"===b.type&&this.sexpr(b)):this[b.type](b)},setupFullMustacheParams:function(a,b,c){var d=a.params;return this.pushParams(d),this.opcode("pushProgram",b),this.opcode("pushProgram",c),a.hash?this.hash(a.hash):this.opcode("emptyHash"),d}},e.precompile=c,e.compile=d,e}(c),k=function(a,b){"use strict";function c(a){this.value=a}function d(){}var e,f=a.COMPILER_REVISION,g=a.REVISION_CHANGES,h=a.log,i=b;d.prototype={nameLookup:function(a,b){var c,e;return 0===a.indexOf("depth")&&(c=!0),e=/^[0-9]+$/.test(b)?a+"["+b+"]":d.isValidJavaScriptVariableName(b)?a+"."+b:a+"['"+b+"']",c?"("+a+" && "+e+")":e},compilerInfo:function(){var a=f,b=g[a];return"this.compilerInfo = ["+a+",'"+b+"'];\n"},appendToBuffer:function(a){return this.environment.isSimple?"return "+a+";":{appendToBuffer:!0,content:a,toString:function(){return"buffer += "+a+";"}}},initializeBuffer:function(){return this.quotedString("")},namespace:"Handlebars",compile:function(a,b,c,d){this.environment=a,this.options=b||{},h("debug",this.environment.disassemble()+"\n\n"),this.name=this.environment.name,this.isChild=!!c,this.context=c||{programs:[],environments:[],aliases:{}},this.preamble(),this.stackSlot=0,this.stackVars=[],this.registers={list:[]},this.hashes=[],this.compileStack=[],this.inlineStack=[],this.compileChildren(a,b); +var e,f=a.opcodes;this.i=0;for(var g=f.length;this.ie;e++)d.push("depth"+this.environment.depths.list[e]);var g=this.mergeSource();if(this.isChild||(g=this.compilerInfo()+g),a)return d.push(g),Function.apply(this,d);var i="function "+(this.name||"")+"("+d.join(",")+") {\n "+g+"}";return h("debug",i+"\n\n"),i},mergeSource:function(){for(var a,b="",c=0,d=this.source.length;d>c;c++){var e=this.source[c];e.appendToBuffer?a=a?a+"\n + "+e.content:e.content:(a&&(b+="buffer += "+a+";\n ",a=void 0),b+=e+"\n ")}return b},blockValue:function(){this.context.aliases.blockHelperMissing="helpers.blockHelperMissing";var a=["depth0"];this.setupParams(0,a),this.replaceStack(function(b){return a.splice(1,0,b),"blockHelperMissing.call("+a.join(", ")+")"})},ambiguousBlockValue:function(){this.context.aliases.blockHelperMissing="helpers.blockHelperMissing";var a=["depth0"];this.setupParams(0,a);var b=this.topStack();a.splice(1,0,b),this.pushSource("if (!"+this.lastHelper+") { "+b+" = blockHelperMissing.call("+a.join(", ")+"); }")},appendContent:function(a){this.pendingContent&&(a=this.pendingContent+a),this.stripNext&&(a=a.replace(/^\s+/,"")),this.pendingContent=a},strip:function(){this.pendingContent&&(this.pendingContent=this.pendingContent.replace(/\s+$/,"")),this.stripNext="strip"},append:function(){this.flushInline();var a=this.popStack();this.pushSource("if("+a+" || "+a+" === 0) { "+this.appendToBuffer(a)+" }"),this.environment.isSimple&&this.pushSource("else { "+this.appendToBuffer("''")+" }")},appendEscaped:function(){this.context.aliases.escapeExpression="this.escapeExpression",this.pushSource(this.appendToBuffer("escapeExpression("+this.popStack()+")"))},getContext:function(a){this.lastContext!==a&&(this.lastContext=a)},lookupOnContext:function(a){this.push(this.nameLookup("depth"+this.lastContext,a,"context"))},pushContext:function(){this.pushStackLiteral("depth"+this.lastContext)},resolvePossibleLambda:function(){this.context.aliases.functionType='"function"',this.replaceStack(function(a){return"typeof "+a+" === functionType ? "+a+".apply(depth0) : "+a})},lookup:function(a){this.replaceStack(function(b){return b+" == null || "+b+" === false ? "+b+" : "+this.nameLookup(b,a,"context")})},lookupData:function(){this.pushStackLiteral("data")},pushStringParam:function(a,b){this.pushStackLiteral("depth"+this.lastContext),this.pushString(b),"sexpr"!==b&&("string"==typeof a?this.pushString(a):this.pushStackLiteral(a))},emptyHash:function(){this.pushStackLiteral("{}"),this.options.stringParams&&(this.push("{}"),this.push("{}"))},pushHash:function(){this.hash&&this.hashes.push(this.hash),this.hash={values:[],types:[],contexts:[]}},popHash:function(){var a=this.hash;this.hash=this.hashes.pop(),this.options.stringParams&&(this.push("{"+a.contexts.join(",")+"}"),this.push("{"+a.types.join(",")+"}")),this.push("{\n "+a.values.join(",\n ")+"\n }")},pushString:function(a){this.pushStackLiteral(this.quotedString(a))},push:function(a){return this.inlineStack.push(a),a},pushLiteral:function(a){this.pushStackLiteral(a)},pushProgram:function(a){null!=a?this.pushStackLiteral(this.programExpression(a)):this.pushStackLiteral(null)},invokeHelper:function(a,b,c){this.context.aliases.helperMissing="helpers.helperMissing",this.useRegister("helper");var d=this.lastHelper=this.setupHelper(a,b,!0),e=this.nameLookup("depth"+this.lastContext,b,"context"),f="helper = "+d.name+" || "+e;d.paramsInit&&(f+=","+d.paramsInit),this.push("("+f+",helper ? helper.call("+d.callParams+") : helperMissing.call("+d.helperMissingParams+"))"),c||this.flushInline()},invokeKnownHelper:function(a,b){var c=this.setupHelper(a,b);this.push(c.name+".call("+c.callParams+")")},invokeAmbiguous:function(a,b){this.context.aliases.functionType='"function"',this.useRegister("helper"),this.emptyHash();var c=this.setupHelper(0,a,b),d=this.lastHelper=this.nameLookup("helpers",a,"helper"),e=this.nameLookup("depth"+this.lastContext,a,"context"),f=this.nextStack();c.paramsInit&&this.pushSource(c.paramsInit),this.pushSource("if (helper = "+d+") { "+f+" = helper.call("+c.callParams+"); }"),this.pushSource("else { helper = "+e+"; "+f+" = typeof helper === functionType ? helper.call("+c.callParams+") : helper; }")},invokePartial:function(a){var b=[this.nameLookup("partials",a,"partial"),"'"+a+"'",this.popStack(),"helpers","partials"];this.options.data&&b.push("data"),this.context.aliases.self="this",this.push("self.invokePartial("+b.join(", ")+")")},assignToHash:function(a){var b,c,d=this.popStack();this.options.stringParams&&(c=this.popStack(),b=this.popStack());var e=this.hash;b&&e.contexts.push("'"+a+"': "+b),c&&e.types.push("'"+a+"': "+c),e.values.push("'"+a+"': ("+d+")")},compiler:d,compileChildren:function(a,b){for(var c,d,e=a.children,f=0,g=e.length;g>f;f++){c=e[f],d=new this.compiler;var h=this.matchExistingProgram(c);null==h?(this.context.programs.push(""),h=this.context.programs.length,c.index=h,c.name="program"+h,this.context.programs[h]=d.compile(c,b,this.context),this.context.environments[h]=c):(c.index=h,c.name="program"+h)}},matchExistingProgram:function(a){for(var b=0,c=this.context.environments.length;c>b;b++){var d=this.context.environments[b];if(d&&d.equals(a))return b}},programExpression:function(a){if(this.context.aliases.self="this",null==a)return"self.noop";for(var b,c=this.environment.children[a],d=c.depths.list,e=[c.index,c.name,"data"],f=0,g=d.length;g>f;f++)b=d[f],1===b?e.push("depth0"):e.push("depth"+(b-1));return(0===d.length?"self.program(":"self.programWithDepth(")+e.join(", ")+")"},register:function(a,b){this.useRegister(a),this.pushSource(a+" = "+b+";")},useRegister:function(a){this.registers[a]||(this.registers[a]=!0,this.registers.list.push(a))},pushStackLiteral:function(a){return this.push(new c(a))},pushSource:function(a){this.pendingContent&&(this.source.push(this.appendToBuffer(this.quotedString(this.pendingContent))),this.pendingContent=void 0),a&&this.source.push(a)},pushStack:function(a){this.flushInline();var b=this.incrStack();return a&&this.pushSource(b+" = "+a+";"),this.compileStack.push(b),b},replaceStack:function(a){var b,d,e,f="",g=this.isInline();if(g){var h=this.popStack(!0);if(h instanceof c)b=h.value,e=!0;else{d=!this.stackSlot;var i=d?this.incrStack():this.topStackName();f="("+this.push(i)+" = "+h+"),",b=this.topStack()}}else b=this.topStack();var j=a.call(this,b);return g?(e||this.popStack(),d&&this.stackSlot--,this.push("("+f+j+")")):(/^stack/.test(b)||(b=this.nextStack()),this.pushSource(b+" = ("+f+j+");")),b},nextStack:function(){return this.pushStack()},incrStack:function(){return this.stackSlot++,this.stackSlot>this.stackVars.length&&this.stackVars.push("stack"+this.stackSlot),this.topStackName()},topStackName:function(){return"stack"+this.stackSlot},flushInline:function(){var a=this.inlineStack;if(a.length){this.inlineStack=[];for(var b=0,d=a.length;d>b;b++){var e=a[b];e instanceof c?this.compileStack.push(e):this.pushStack(e)}}},isInline:function(){return this.inlineStack.length},popStack:function(a){var b=this.isInline(),d=(b?this.inlineStack:this.compileStack).pop();if(!a&&d instanceof c)return d.value;if(!b){if(!this.stackSlot)throw new i("Invalid stack pop");this.stackSlot--}return d},topStack:function(a){var b=this.isInline()?this.inlineStack:this.compileStack,d=b[b.length-1];return!a&&d instanceof c?d.value:d},quotedString:function(a){return'"'+a.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/\u2028/g,"\\u2028").replace(/\u2029/g,"\\u2029")+'"'},setupHelper:function(a,b,c){var d=[],e=this.setupParams(a,d,c),f=this.nameLookup("helpers",b,"helper");return{params:d,paramsInit:e,name:f,callParams:["depth0"].concat(d).join(", "),helperMissingParams:c&&["depth0",this.quotedString(b)].concat(d).join(", ")}},setupOptions:function(a,b){var c,d,e,f=[],g=[],h=[];f.push("hash:"+this.popStack()),this.options.stringParams&&(f.push("hashTypes:"+this.popStack()),f.push("hashContexts:"+this.popStack())),d=this.popStack(),e=this.popStack(),(e||d)&&(e||(this.context.aliases.self="this",e="self.noop"),d||(this.context.aliases.self="this",d="self.noop"),f.push("inverse:"+d),f.push("fn:"+e));for(var i=0;a>i;i++)c=this.popStack(),b.push(c),this.options.stringParams&&(h.push(this.popStack()),g.push(this.popStack()));return this.options.stringParams&&(f.push("contexts:["+g.join(",")+"]"),f.push("types:["+h.join(",")+"]")),this.options.data&&f.push("data:data"),f},setupParams:function(a,b,c){var d="{"+this.setupOptions(a,b).join(",")+"}";return c?(this.useRegister("options"),b.push("options"),"options="+d):(b.push(d),"")}};for(var j="break else new var case finally return void catch for switch while continue function this with default if throw delete in try do instanceof typeof abstract enum int short boolean export interface static byte extends long super char final native synchronized class float package throws const goto private transient debugger implements protected volatile double import public let yield".split(" "),k=d.RESERVED_WORDS={},l=0,m=j.length;m>l;l++)k[j[l]]=!0;return d.isValidJavaScriptVariableName=function(a){return!d.RESERVED_WORDS[a]&&/^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(a)?!0:!1},e=d}(d,c),l=function(a,b,c,d,e){"use strict";var f,g=a,h=b,i=c.parser,j=c.parse,k=d.Compiler,l=d.compile,m=d.precompile,n=e,o=g.create,p=function(){var a=o();return a.compile=function(b,c){return l(b,c,a)},a.precompile=function(b,c){return m(b,c,a)},a.AST=h,a.Compiler=k,a.JavaScriptCompiler=n,a.Parser=i,a.parse=j,a};return g=p(),g.create=p,f=g}(f,g,i,j,k);return l}(); \ No newline at end of file diff --git a/domain-server/resources/web/js/settings.js b/domain-server/resources/web/js/settings.js new file mode 100644 index 0000000000..b7eda97232 --- /dev/null +++ b/domain-server/resources/web/js/settings.js @@ -0,0 +1,8 @@ +$(document).ready(function(){ + $.getJSON('describe.json', function(data){ + var source = $('#template').html(); + var template = Handlebars.compile(source); + + $('#settings').html(template(data)); + }); +}); \ No newline at end of file diff --git a/domain-server/resources/web/settings/describe.json b/domain-server/resources/web/settings/describe.json new file mode 100644 index 0000000000..d48b5b64ce --- /dev/null +++ b/domain-server/resources/web/settings/describe.json @@ -0,0 +1,10 @@ +{ + "groups": { + "Audio": { + "unattenuated-zone": { + "label": "Unattenuated Zone", + "desc": "Define two axis-aligned boxes for an unattenuated zone of audio (source x, source y, source z, size x, size y, size z, listener x, listener y, listener z)" + } + } + } +} \ No newline at end of file diff --git a/domain-server/resources/web/settings/index.shtml b/domain-server/resources/web/settings/index.shtml new file mode 100644 index 0000000000..03382954b7 --- /dev/null +++ b/domain-server/resources/web/settings/index.shtml @@ -0,0 +1,13 @@ + + +
+ +
+ + + + \ No newline at end of file diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index d55a9b52ca..78032f214d 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -1162,7 +1162,7 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url } } - // didn't process the request, let the HTTPManager try and handle + // didn't process the request, let our HTTPManager handle return false; } diff --git a/domain-server/src/DomainServerSettingsManager.cpp b/domain-server/src/DomainServerSettingsManager.cpp new file mode 100644 index 0000000000..b425b7a381 --- /dev/null +++ b/domain-server/src/DomainServerSettingsManager.cpp @@ -0,0 +1,12 @@ +// +// DomainServerSettingsManager.cpp +// domain-server/src +// +// Created by Stephen Birarda on 2014-06-24. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "DomainServerSettingsManager.h" \ No newline at end of file diff --git a/domain-server/src/DomainServerSettingsManager.h b/domain-server/src/DomainServerSettingsManager.h new file mode 100644 index 0000000000..8d4afae4b9 --- /dev/null +++ b/domain-server/src/DomainServerSettingsManager.h @@ -0,0 +1,21 @@ +// +// DomainServerSettingsManager.h +// domain-server/src +// +// Created by Stephen Birarda on 2014-06-24. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_DomainServerSettingsManager_h +#define hifi_DomainServerSettingsManager_h + +#include + +class DomainServerSettingsManager { + +}; + +#endif // hifi_DomainServerSettingsManager_h \ No newline at end of file From cf0e1ab1a93bc26f9fe8e51d5481a86c5a86be20 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 24 Jun 2014 14:24:56 -0700 Subject: [PATCH 02/32] finish up handlebars template for settings --- domain-server/resources/web/css/style.css | 4 +-- domain-server/resources/web/js/settings.js | 5 ++++ .../resources/web/settings/describe.json | 12 ++++++--- .../resources/web/settings/index.shtml | 26 ++++++++++++++++--- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/domain-server/resources/web/css/style.css b/domain-server/resources/web/css/style.css index ff33cc206b..3b60ada78b 100644 --- a/domain-server/resources/web/css/style.css +++ b/domain-server/resources/web/css/style.css @@ -1,8 +1,8 @@ -#nodes-lead { +#nodes-lead, #settings-lead { color: #66CCCC; } -#nodes-lead .lead-line { +#nodes-lead .lead-line, #settings-lead .lead-line { background-color: #66CCCC; } diff --git a/domain-server/resources/web/js/settings.js b/domain-server/resources/web/js/settings.js index b7eda97232..d7d8315559 100644 --- a/domain-server/resources/web/js/settings.js +++ b/domain-server/resources/web/js/settings.js @@ -1,5 +1,10 @@ $(document).ready(function(){ $.getJSON('describe.json', function(data){ + + Handlebars.registerHelper('setKey', function(value){ + this.key = value; + }); + var source = $('#template').html(); var template = Handlebars.compile(source); diff --git a/domain-server/resources/web/settings/describe.json b/domain-server/resources/web/settings/describe.json index d48b5b64ce..763aeccdfc 100644 --- a/domain-server/resources/web/settings/describe.json +++ b/domain-server/resources/web/settings/describe.json @@ -1,9 +1,13 @@ { "groups": { - "Audio": { - "unattenuated-zone": { - "label": "Unattenuated Zone", - "desc": "Define two axis-aligned boxes for an unattenuated zone of audio (source x, source y, source z, size x, size y, size z, listener x, listener y, listener z)" + "audio": { + "label": "Audio", + "settings": { + "unattenuated-zone": { + "label": "Unattenuated Zone", + "help": "Boxes for source and listener (corner x, corner y, corner z, size x, size y, size z, corner x, corner y, corner z, size x, size y, size z)", + "placeholder": "0,0,0,20,20,20,50,50,50,10,10,10" + } } } } diff --git a/domain-server/resources/web/settings/index.shtml b/domain-server/resources/web/settings/index.shtml index 03382954b7..8d186848b6 100644 --- a/domain-server/resources/web/settings/index.shtml +++ b/domain-server/resources/web/settings/index.shtml @@ -1,12 +1,30 @@ +

Settings

+
-
- -
+ +
From 11f23ca6f616f9faef084d92addf0ee134b63e3d Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 24 Jun 2014 15:56:53 -0700 Subject: [PATCH 03/32] add POSTing of settings to DS via form2js --- domain-server/resources/web/js/form2js.min.js | 26 ++++++++++ domain-server/resources/web/js/settings.js | 51 +++++++++++++++---- .../resources/web/settings/index.shtml | 12 +++-- 3 files changed, 74 insertions(+), 15 deletions(-) create mode 100755 domain-server/resources/web/js/form2js.min.js diff --git a/domain-server/resources/web/js/form2js.min.js b/domain-server/resources/web/js/form2js.min.js new file mode 100755 index 0000000000..f1e610f7c3 --- /dev/null +++ b/domain-server/resources/web/js/form2js.min.js @@ -0,0 +1,26 @@ +/** + * Copyright (c) 2010 Maxim Vasiliev + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author Maxim Vasiliev + * Date: 09.09.2010 + * Time: 19:02:33 + */ +(function(e,t){if(typeof define==="function"&&define.amd){define(t)}else{e.form2js=t()}})(this,function(){"use strict";function e(e,r,i,s,o,u){u=u?true:false;if(typeof i=="undefined"||i==null)i=true;if(typeof r=="undefined"||r==null)r=".";if(arguments.length<5)o=false;e=typeof e=="string"?document.getElementById(e):e;var a=[],f,l=0;if(e.constructor==Array||typeof NodeList!="undefined"&&e.constructor==NodeList){while(f=e[l++]){a=a.concat(n(f,s,o,u))}}else{a=n(e,s,o,u)}return t(a,i,r)}function t(e,t,n){var r={},i={},s,o,u,a,f,l,c,h,p,d,v,m,g;for(s=0;s1){for(u=0;u-1&&o==l.length-1){p=v.substr(0,v.indexOf("["));h+=p;if(!c[p])c[p]=[];c[p].push(f)}else if(v.indexOf("[")>-1){p=v.substr(0,v.indexOf("["));d=v.replace(/(^([a-z_]+)?\[)|(\]$)/gi,"");h+="_"+p+"_"+d;if(!i[h])i[h]={};if(p!=""&&!c[p])c[p]=[];if(o==l.length-1){if(p==""){c.push(f);i[h][d]=c[c.length-1]}else{c[p].push(f);i[h][d]=c[p][c[p].length-1]}}else{if(!i[h][d]){if(/^[0-9a-z_]+\[?/i.test(l[o+1]))c[p].push({});else c[p].push([]);i[h][d]=c[p][c[p].length-1]}}c=i[h][d]}else{h+=v;if(o0?o:r(e,t,n,s)}function r(e,t,n,r){var s=[],o=e.firstChild;while(o){s=s.concat(i(o,t,n,r));o=o.nextSibling}return s}function i(e,t,n,i){if(e.disabled&&!i)return[];var u,a,f,l=s(e,n);u=t&&t(e);if(u&&u.name){f=[u]}else if(l!=""&&e.nodeName.match(/INPUT|TEXTAREA/i)){a=o(e,i);if(null===a){f=[]}else{f=[{name:l,value:a}]}}else if(l!=""&&e.nodeName.match(/SELECT/i)){a=o(e,i);f=[{name:l.replace(/\[\]$/,""),value:a}]}else{f=r(e,t,n,i)}return f}function s(e,t){if(e.name&&e.name!="")return e.name;else if(t&&e.id&&e.id!="")return e.id;else return""}function o(e,t){if(e.disabled&&!t)return null;switch(e.nodeName){case"INPUT":case"TEXTAREA":switch(e.type.toLowerCase()){case"radio":if(e.checked&&e.value==="false")return false;case"checkbox":if(e.checked&&e.value==="true")return true;if(!e.checked&&e.value==="true")return false;if(e.checked)return e.value;break;case"button":case"reset":case"submit":case"image":return"";break;default:return e.value;break}break;case"SELECT":return u(e);break;default:break}return null}function u(e){var t=e.multiple,n=[],r,i,s;if(!t)return e.value;for(r=e.getElementsByTagName("option"),i=0,s=r.length;i

Settings

+ +
+
+
+ + \ No newline at end of file From 9a6f144da902110ca3d1f4dcc1efcab4654645f8 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 24 Jun 2014 18:21:57 -0700 Subject: [PATCH 04/32] Added sitting points metadata for fst --- libraries/fbx/src/FBXReader.cpp | 15 ++++++++++++++- libraries/fbx/src/FBXReader.h | 10 ++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 9aeb81a2a3..36773ec8bd 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -1897,7 +1897,20 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) } geometry.attachments.append(attachment); } - + + // Add sitting points + QVariantHash sittingPoints = mapping.value("sit").toHash(); + for (QVariantHash::const_iterator it = sittingPoints.constBegin(); it != sittingPoints.constEnd(); it++) { + SittingPoint sittingPoint; + sittingPoint.name = it.key(); + + QVariantList properties = it->toList(); + sittingPoint.position = parseVec3(properties.at(0).toString()); + sittingPoint.rotation = glm::quat(glm::radians(parseVec3(properties.at(1).toString()))); + + geometry.sittingPoints.append(sittingPoint); + } + return geometry; } diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h index 4c93f3dc5e..c336252574 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXReader.h @@ -182,6 +182,14 @@ public: glm::vec3 scale; }; +/// A point where an avatar can sit +class SittingPoint { +public: + QString name; + glm::vec3 position; // relative postion + glm::quat rotation; // relative orientation +}; + /// A set of meshes extracted from an FBX document. class FBXGeometry { public: @@ -209,6 +217,8 @@ public: glm::vec3 palmDirection; + QVector sittingPoints; + glm::vec3 neckPivot; Extents bindExtents; From f8dccad6eca0149c576edabf7264106a4184ac3c Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 25 Jun 2014 11:20:09 -0700 Subject: [PATCH 05/32] enable persisting of posted settings to a JSON file --- .../resources/web/settings/describe.json | 16 ++-- .../resources/web/settings/index.shtml | 2 +- domain-server/src/DomainServer.cpp | 7 +- domain-server/src/DomainServer.h | 3 + .../src/DomainServerSettingsManager.cpp | 89 ++++++++++++++++++- .../src/DomainServerSettingsManager.h | 14 ++- 6 files changed, 116 insertions(+), 15 deletions(-) diff --git a/domain-server/resources/web/settings/describe.json b/domain-server/resources/web/settings/describe.json index 763aeccdfc..b111018a30 100644 --- a/domain-server/resources/web/settings/describe.json +++ b/domain-server/resources/web/settings/describe.json @@ -1,13 +1,11 @@ { - "groups": { - "audio": { - "label": "Audio", - "settings": { - "unattenuated-zone": { - "label": "Unattenuated Zone", - "help": "Boxes for source and listener (corner x, corner y, corner z, size x, size y, size z, corner x, corner y, corner z, size x, size y, size z)", - "placeholder": "0,0,0,20,20,20,50,50,50,10,10,10" - } + "audio": { + "label": "Audio", + "settings": { + "unattenuated-zone": { + "label": "Unattenuated Zone", + "help": "Boxes for source and listener (corner x, corner y, corner z, size x, size y, size z, corner x, corner y, corner z, size x, size y, size z)", + "placeholder": "0,0,0,20,20,20,50,50,50,10,10,10" } } } diff --git a/domain-server/resources/web/settings/index.shtml b/domain-server/resources/web/settings/index.shtml index ee44442547..7d8a50f5b7 100644 --- a/domain-server/resources/web/settings/index.shtml +++ b/domain-server/resources/web/settings/index.shtml @@ -5,7 +5,7 @@
@@ -31,5 +38,5 @@ - + \ No newline at end of file From 5cd2dc594fff6f168c29b3f84844619e3530751e Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 26 Jun 2014 08:45:12 -0700 Subject: [PATCH 13/32] only post changed values to settings.json, fix for bool values --- domain-server/resources/web/js/settings.js | 27 +++++++++++++++++-- .../resources/web/settings/describe.json | 2 +- .../resources/web/settings/index.shtml | 8 +++--- .../src/DomainServerSettingsManager.cpp | 7 ++--- 4 files changed, 35 insertions(+), 9 deletions(-) diff --git a/domain-server/resources/web/js/settings.js b/domain-server/resources/web/js/settings.js index 293ccce36d..487ec5b296 100644 --- a/domain-server/resources/web/js/settings.js +++ b/domain-server/resources/web/js/settings.js @@ -15,9 +15,19 @@ function reloadSettings() { var SETTINGS_ERROR_MESSAGE = "There was a problem saving domain settings. Please try again!"; -$('#settings').on('click', 'button', function(e){ +$('#settings').on('click', 'button', function(e){ + // disable any inputs not changed + $("input:not([data-changed])").each(function(){ + $(this).prop('disabled', true); + }); + // grab a JSON representation of the form via form2js - var formJSON = form2js('settings-form', ".", false, null, true); + var formJSON = form2js('settings-form', ".", false, cleanupFormValues, true); + + // re-enable all inputs + $("input").each(function(){ + $(this).prop('disabled', false); + }); // POST the form JSON to the domain-server settings.json endpoint so the settings are saved $.ajax('/settings.json', { @@ -40,6 +50,19 @@ $('#settings').on('click', 'button', function(e){ return false; }); +$('#settings').on('change', 'input', function(){ + // this input was changed, add the changed data attribute to it + $(this).attr('data-changed', true); +}); + +function cleanupFormValues(node) { + if (node.type && node.type === 'checkbox') { + return { name: node.id, value: node.checked ? true : false }; + } else { + return false; + } +} + function showAlertMessage(message, isSuccess) { var alertBox = $('.alert'); alertBox.attr('class', 'alert'); diff --git a/domain-server/resources/web/settings/describe.json b/domain-server/resources/web/settings/describe.json index 5e810baa12..2c0440ac01 100644 --- a/domain-server/resources/web/settings/describe.json +++ b/domain-server/resources/web/settings/describe.json @@ -13,7 +13,7 @@ "type": "checkbox", "label": "Dynamic Jitter Buffers", "help": "Dynamically buffer client audio based on perceived jitter in packet receipt timing", - "default": "false" + "default": false } } } diff --git a/domain-server/resources/web/settings/index.shtml b/domain-server/resources/web/settings/index.shtml index d95bd65d44..15ce842f30 100644 --- a/domain-server/resources/web/settings/index.shtml +++ b/domain-server/resources/web/settings/index.shtml @@ -13,13 +13,15 @@
<% _.each(group.settings, function(setting, setting_key){ %>
- + <% var setting_id = group_key + "." + setting_key %> +
<% if(setting.type) %> <% if (setting.type === "checkbox") { %> - + <% var checked_box = (_.isUndefined(values[group_key][setting_key]) ? setting.default : values[group_key][setting_key]) %> + > <% } else { %> - + <% } %>
diff --git a/domain-server/src/DomainServerSettingsManager.cpp b/domain-server/src/DomainServerSettingsManager.cpp index fabd26c8e0..4229e45191 100644 --- a/domain-server/src/DomainServerSettingsManager.cpp +++ b/domain-server/src/DomainServerSettingsManager.cpp @@ -81,10 +81,11 @@ void DomainServerSettingsManager::recurseJSONObjectAndOverwriteSettings(const QJ // we don't continue if this key is not present in our descriptionObject if (descriptionObject.contains(key)) { if (rootValue.isString()) { - // if this is a string then just set it in our settingsVariant settingsVariant[key] = rootValue.toString(); + } else if (rootValue.isBool()) { + settingsVariant[key] = rootValue.toBool(); } else if (rootValue.isObject()) { - + // there's a JSON Object to explore, so attempt to recurse into it QJsonObject nextDescriptionObject = descriptionObject[key].toObject(); if (nextDescriptionObject.contains(DESCRIPTION_SETTINGS_KEY)) { @@ -93,7 +94,7 @@ void DomainServerSettingsManager::recurseJSONObjectAndOverwriteSettings(const QJ settingsVariant[key] = QVariantMap(); } - // there's a JSON Object to explore, so recurse into it + recurseJSONObjectAndOverwriteSettings(rootValue.toObject(), *reinterpret_cast(settingsVariant[key].data()), nextDescriptionObject[DESCRIPTION_SETTINGS_KEY].toObject()); From e56f4aba0a7b93b4b9060d25103d01f4fa2657f1 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 26 Jun 2014 15:40:10 -0700 Subject: [PATCH 14/32] use underscorejs for nodes table template --- domain-server/resources/web/index.shtml | 16 +++++++++++++++- domain-server/resources/web/js/tables.js | 24 ++++-------------------- 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/domain-server/resources/web/index.shtml b/domain-server/resources/web/index.shtml index b6ba8f67db..9d5ee93857 100644 --- a/domain-server/resources/web/index.shtml +++ b/domain-server/resources/web/index.shtml @@ -18,7 +18,20 @@ - +

Queued Assignments

@@ -35,4 +48,5 @@ + \ No newline at end of file diff --git a/domain-server/resources/web/js/tables.js b/domain-server/resources/web/js/tables.js index b564d9392f..28e54b3773 100644 --- a/domain-server/resources/web/js/tables.js +++ b/domain-server/resources/web/js/tables.js @@ -1,4 +1,7 @@ $(document).ready(function(){ + // setup the underscore templates + var nodeTemplate = _.template($('#nodes-template').html()); + // setup a function to grab the assignments function getNodesAndAssignments() { $.getJSON("nodes.json", function(json){ @@ -29,26 +32,7 @@ $(document).ready(function(){ } }); - nodesTableBody = ""; - - $.each(json.nodes, function(index, data) { - nodesTableBody += ""; - nodesTableBody += "" + data.type + ""; - nodesTableBody += "" + data.uuid + ""; - nodesTableBody += "" + (data.pool ? data.pool : "") + ""; - nodesTableBody += "" + data.public.ip + ":" + data.public.port + ""; - nodesTableBody += "" + data.local.ip + ":" + data.local.port + ""; - - var uptimeSeconds = (Date.now() - data.wake_timestamp) / 1000; - nodesTableBody += "" + uptimeSeconds.toLocaleString() + ""; - - nodesTableBody += "" + (typeof data.pending_credits == 'number' ? data.pending_credits.toLocaleString() : 'N/A') + ""; - - nodesTableBody += ""; - nodesTableBody += ""; - }); - - $('#nodes-table tbody').html(nodesTableBody); + $('#nodes-table tbody').html(nodeTemplate(json)); }); $.getJSON("assignments.json", function(json){ From ab50432ead5d0ec74cf07c24b501880863ef2689 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 26 Jun 2014 15:45:31 -0700 Subject: [PATCH 15/32] use underscorejs templating for queued assignments --- domain-server/resources/web/index.shtml | 9 +++++++++ domain-server/resources/web/js/tables.js | 13 ++----------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/domain-server/resources/web/index.shtml b/domain-server/resources/web/index.shtml index 9d5ee93857..f0315a113f 100644 --- a/domain-server/resources/web/index.shtml +++ b/domain-server/resources/web/index.shtml @@ -44,6 +44,15 @@ + diff --git a/domain-server/resources/web/js/tables.js b/domain-server/resources/web/js/tables.js index 28e54b3773..0b29d4e6c9 100644 --- a/domain-server/resources/web/js/tables.js +++ b/domain-server/resources/web/js/tables.js @@ -1,6 +1,7 @@ $(document).ready(function(){ // setup the underscore templates var nodeTemplate = _.template($('#nodes-template').html()); + var queuedTemplate = _.template($('#queued-template').html()); // setup a function to grab the assignments function getNodesAndAssignments() { @@ -36,17 +37,7 @@ $(document).ready(function(){ }); $.getJSON("assignments.json", function(json){ - queuedTableBody = ""; - - $.each(json.queued, function (uuid, data) { - queuedTableBody += ""; - queuedTableBody += "" + data.type + ""; - queuedTableBody += "" + uuid + ""; - queuedTableBody += "" + (data.pool ? data.pool : "") + ""; - queuedTableBody += ""; - }); - - $('#assignments-table tbody').html(queuedTableBody); + $('#assignments-table tbody').html(queuedTemplate(json)); }); } From 731690e3588958095d3f7216b9cd54c0edfdeff0 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 26 Jun 2014 16:29:44 -0700 Subject: [PATCH 16/32] add querying for settings that affect a specific type --- .../resources/web/settings/describe.json | 2 +- .../resources/web/settings/index.shtml | 6 +- .../src/DomainServerSettingsManager.cpp | 76 +++++++++++++++++-- 3 files changed, 73 insertions(+), 11 deletions(-) diff --git a/domain-server/resources/web/settings/describe.json b/domain-server/resources/web/settings/describe.json index 2c0440ac01..227b6bf0cd 100644 --- a/domain-server/resources/web/settings/describe.json +++ b/domain-server/resources/web/settings/describe.json @@ -1,7 +1,7 @@ { "audio": { "label": "Audio", - "types": [0], + "assignment-types": [0], "settings": { "unattenuated-zone": { "label": "Unattenuated Zone", diff --git a/domain-server/resources/web/settings/index.shtml b/domain-server/resources/web/settings/index.shtml index 15ce842f30..3bb669b32e 100644 --- a/domain-server/resources/web/settings/index.shtml +++ b/domain-server/resources/web/settings/index.shtml @@ -18,10 +18,12 @@
<% if(setting.type) %> <% if (setting.type === "checkbox") { %> - <% var checked_box = (_.isUndefined(values[group_key][setting_key]) ? setting.default : values[group_key][setting_key]) %> + <% var checked_box = (values[group_key] || {})[setting_key] || setting.default %> > <% } else { %> - + <% } %>
diff --git a/domain-server/src/DomainServerSettingsManager.cpp b/domain-server/src/DomainServerSettingsManager.cpp index 4229e45191..d7e2e05ca8 100644 --- a/domain-server/src/DomainServerSettingsManager.cpp +++ b/domain-server/src/DomainServerSettingsManager.cpp @@ -11,9 +11,12 @@ #include #include +#include #include #include +#include +#include #include #include "DomainServerSettingsManager.h" @@ -38,6 +41,9 @@ DomainServerSettingsManager::DomainServerSettingsManager() : _settingsMap = QJsonDocument::fromJson(configFile.readAll()).toVariant().toMap(); } +const QString DESCRIPTION_SETTINGS_KEY = "settings"; +const QString SETTING_DEFAULT_KEY = "default"; + bool DomainServerSettingsManager::handleHTTPRequest(HTTPConnection* connection, const QUrl &url) { if (connection->requestOperation() == QNetworkAccessManager::PostOperation && url.path() == "/settings.json") { // this is a POST operation to change one or more settings @@ -57,20 +63,75 @@ bool DomainServerSettingsManager::handleHTTPRequest(HTTPConnection* connection, return true; } else if (connection->requestOperation() == QNetworkAccessManager::GetOperation && url.path() == "/settings.json") { // this is a GET operation for our settings - // combine the description object and our current settings map - QJsonObject combinedObject; - combinedObject["descriptions"] = _descriptionObject; - combinedObject["values"] = QJsonDocument::fromVariant(_settingsMap).object(); - connection->respond(HTTPConnection::StatusCode200, QJsonDocument(combinedObject).toJson(), "application/json"); + // check if there is a query parameter for settings affecting a particular type of assignment + const QString SETTINGS_TYPE_QUERY_KEY = "type"; + QUrlQuery settingsQuery(url); + QString typeValue = settingsQuery.queryItemValue(SETTINGS_TYPE_QUERY_KEY); + + QJsonObject responseObject; + + if (typeValue.isEmpty()) { + // combine the description object and our current settings map + responseObject["descriptions"] = _descriptionObject; + responseObject["values"] = QJsonDocument::fromVariant(_settingsMap).object(); + } else { + // convert the string type value to a QJsonValue + QJsonValue queryType = QJsonValue(typeValue.toInt()); + + const QString AFFECTED_TYPES_JSON_KEY = "assignment-types"; + + // enumerate the groups in the description object to find which settings to pass + foreach(const QString& group, _descriptionObject.keys()) { + QJsonObject groupObject = _descriptionObject[group].toObject(); + QJsonObject groupSettingsObject = groupObject[DESCRIPTION_SETTINGS_KEY].toObject(); + + QJsonObject groupResponseObject; + + + foreach(const QString& settingKey, groupSettingsObject.keys()) { + QJsonObject settingObject = groupSettingsObject[settingKey].toObject(); + + QJsonArray affectedTypesArray = settingObject[AFFECTED_TYPES_JSON_KEY].toArray(); + if (affectedTypesArray.isEmpty()) { + affectedTypesArray = groupObject[AFFECTED_TYPES_JSON_KEY].toArray(); + } + + if (affectedTypesArray.contains(queryType)) { + // this is a setting we should include in the responseObject + + // we need to check if the settings map has a value for this setting + QVariant variantValue; + QVariant settingsMapGroupValue = _settingsMap.value(group); + + if (!settingsMapGroupValue.isNull()) { + variantValue = settingsMapGroupValue.toMap().value(settingKey); + } + + if (variantValue.isNull()) { + // no value for this setting, pass the default + groupResponseObject[settingKey] = settingObject[SETTING_DEFAULT_KEY]; + } else { + groupResponseObject[settingKey] = QJsonValue::fromVariant(variantValue); + } + } + } + + if (!groupResponseObject.isEmpty()) { + // set this group's object to the constructed object + responseObject[group] = groupResponseObject; + } + } + + } + + connection->respond(HTTPConnection::StatusCode200, QJsonDocument(responseObject).toJson(), "application/json"); return true; } return false; } -const QString DESCRIPTION_SETTINGS_KEY = "settings"; - void DomainServerSettingsManager::recurseJSONObjectAndOverwriteSettings(const QJsonObject& postedObject, QVariantMap& settingsVariant, QJsonObject descriptionObject) { @@ -94,7 +155,6 @@ void DomainServerSettingsManager::recurseJSONObjectAndOverwriteSettings(const QJ settingsVariant[key] = QVariantMap(); } - recurseJSONObjectAndOverwriteSettings(rootValue.toObject(), *reinterpret_cast(settingsVariant[key].data()), nextDescriptionObject[DESCRIPTION_SETTINGS_KEY].toObject()); From e41d3f407b4c8cd036f36ed95c5a24e0628cc303 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 26 Jun 2014 16:40:59 -0700 Subject: [PATCH 17/32] Removed nested lock --- libraries/models/src/ModelsScriptingInterface.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/libraries/models/src/ModelsScriptingInterface.cpp b/libraries/models/src/ModelsScriptingInterface.cpp index 7e08571fe5..bac1213071 100644 --- a/libraries/models/src/ModelsScriptingInterface.cpp +++ b/libraries/models/src/ModelsScriptingInterface.cpp @@ -160,10 +160,8 @@ ModelItemID ModelsScriptingInterface::findClosestModel(const glm::vec3& center, QVector ModelsScriptingInterface::findModels(const glm::vec3& center, float radius) const { QVector result; if (_modelTree) { - _modelTree->lockForRead(); QVector models; _modelTree->findModels(center/(float)TREE_SCALE, radius/(float)TREE_SCALE, models); - _modelTree->unlock(); foreach (const ModelItem* model, models) { ModelItemID thisModelItemID(model->getID(), UNKNOWN_MODEL_TOKEN, true); From 95d266b30598082057302fdd128edae4cca09d6c Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 26 Jun 2014 16:55:22 -0700 Subject: [PATCH 18/32] initial setup of settings request from domain-server --- assignment-client/src/Agent.cpp | 2 - assignment-client/src/audio/AudioMixer.cpp | 39 +++++++++++++++++++ .../src/DomainServerSettingsManager.cpp | 2 +- 3 files changed, 40 insertions(+), 3 deletions(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index fcc2288356..e6c14d06da 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -213,8 +213,6 @@ void Agent::run() { loop.exec(); - - // let the AvatarData and ResourceCache classes use our QNetworkAccessManager AvatarData::setNetworkAccessManager(networkManager); ResourceCache::setNetworkAccessManager(networkManager); diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 8e4ce04f0b..83e6c10c02 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -38,6 +38,9 @@ #include #include #include +#include +#include +#include #include #include @@ -478,6 +481,42 @@ void AudioMixer::run() { nodeList->linkedDataCreateCallback = attachNewBufferToNode; + // setup a QNetworkAccessManager to ask the domain-server for our settings + QNetworkAccessManager *networkManager = new QNetworkAccessManager(this); + + QUrl settingsJSONURL; + settingsJSONURL.setScheme("http"); + settingsJSONURL.setHost(nodeList->getDomainHandler().getHostname()); + settingsJSONURL.setPort(DOMAIN_SERVER_HTTP_PORT); + settingsJSONURL.setPath("/settings.json/"); + settingsJSONURL.setQuery("type=" + QString(_type)); + + QNetworkReply *reply = NULL; + + int failedAttempts = 0; + const int MAX_SETTINGS_REQUEST_FAILED_ATTEMPTS = 5; + + qDebug() << "Requesting settings for assignment from domain-server at" << settingsJSONURL.toString(); + + while (!reply || reply->error() != QNetworkReply::NoError) { + reply = networkManager->get(QNetworkRequest(settingsJSONURL)); + + QEventLoop loop; + QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit())); + + loop.exec(); + ++failedAttempts; + + if (failedAttempts == MAX_SETTINGS_REQUEST_FAILED_ATTEMPTS) { + qDebug() << "Failed to get settings from domain-server. Bailing on assignment."; + setFinished(true); + return; + } + } + + QJsonDocument settingsJSON = QJsonDocument::fromJson(reply->readAll()); + qDebug() << settingsJSON; + // check the payload to see if we have any unattenuated zones const QString UNATTENUATED_ZONE_REGEX_STRING = "--unattenuated-zone ([\\d.,-]+)"; QRegExp unattenuatedZoneMatch(UNATTENUATED_ZONE_REGEX_STRING); diff --git a/domain-server/src/DomainServerSettingsManager.cpp b/domain-server/src/DomainServerSettingsManager.cpp index d7e2e05ca8..f3315e8324 100644 --- a/domain-server/src/DomainServerSettingsManager.cpp +++ b/domain-server/src/DomainServerSettingsManager.cpp @@ -61,7 +61,7 @@ bool DomainServerSettingsManager::handleHTTPRequest(HTTPConnection* connection, connection->respond(HTTPConnection::StatusCode200, jsonSuccess.toUtf8(), "application/json"); return true; - } else if (connection->requestOperation() == QNetworkAccessManager::GetOperation && url.path() == "/settings.json") { + } else if (connection->requestOperation() == QNetworkAccessManager::GetOperation && url.path() == "/settingz.json") { // this is a GET operation for our settings // check if there is a query parameter for settings affecting a particular type of assignment From 3f70402e63eca22f5fbea9795de52a32be55a315 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 26 Jun 2014 16:58:51 -0700 Subject: [PATCH 19/32] fix odd encoding in settings URL --- assignment-client/src/audio/AudioMixer.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 83e6c10c02..9e52e895d3 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -489,7 +489,7 @@ void AudioMixer::run() { settingsJSONURL.setHost(nodeList->getDomainHandler().getHostname()); settingsJSONURL.setPort(DOMAIN_SERVER_HTTP_PORT); settingsJSONURL.setPath("/settings.json/"); - settingsJSONURL.setQuery("type=" + QString(_type)); + settingsJSONURL.setQuery(QString("type=%1").arg(_type)); QNetworkReply *reply = NULL; @@ -515,7 +515,6 @@ void AudioMixer::run() { } QJsonDocument settingsJSON = QJsonDocument::fromJson(reply->readAll()); - qDebug() << settingsJSON; // check the payload to see if we have any unattenuated zones const QString UNATTENUATED_ZONE_REGEX_STRING = "--unattenuated-zone ([\\d.,-]+)"; From 3ae46bc60d0cd0db3f3c67b50810a234c022ef74 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 26 Jun 2014 17:32:56 -0700 Subject: [PATCH 20/32] switch audio-mixer to pull settings from domain-server via JSON request --- assignment-client/src/audio/AudioMixer.cpp | 68 ++++++++++--------- .../src/DomainServerSettingsManager.cpp | 2 +- 2 files changed, 38 insertions(+), 32 deletions(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 9e52e895d3..407a4413d5 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -488,7 +488,7 @@ void AudioMixer::run() { settingsJSONURL.setScheme("http"); settingsJSONURL.setHost(nodeList->getDomainHandler().getHostname()); settingsJSONURL.setPort(DOMAIN_SERVER_HTTP_PORT); - settingsJSONURL.setPath("/settings.json/"); + settingsJSONURL.setPath("/settings.json"); settingsJSONURL.setQuery(QString("type=%1").arg(_type)); QNetworkReply *reply = NULL; @@ -505,6 +505,7 @@ void AudioMixer::run() { QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit())); loop.exec(); + ++failedAttempts; if (failedAttempts == MAX_SETTINGS_REQUEST_FAILED_ATTEMPTS) { @@ -514,42 +515,47 @@ void AudioMixer::run() { } } - QJsonDocument settingsJSON = QJsonDocument::fromJson(reply->readAll()); + QJsonObject settingsObject = QJsonDocument::fromJson(reply->readAll()).object(); - // check the payload to see if we have any unattenuated zones - const QString UNATTENUATED_ZONE_REGEX_STRING = "--unattenuated-zone ([\\d.,-]+)"; - QRegExp unattenuatedZoneMatch(UNATTENUATED_ZONE_REGEX_STRING); + // check the settings object to see if we have anything we can parse out + const QString AUDIO_GROUP_KEY = "audio"; - if (unattenuatedZoneMatch.indexIn(_payload) != -1) { - QString unattenuatedZoneString = unattenuatedZoneMatch.cap(1); - QStringList zoneStringList = unattenuatedZoneString.split(','); + if (settingsObject.contains(AUDIO_GROUP_KEY)) { + QJsonObject audioGroupObject = settingsObject[AUDIO_GROUP_KEY].toObject(); - glm::vec3 sourceCorner(zoneStringList[0].toFloat(), zoneStringList[1].toFloat(), zoneStringList[2].toFloat()); - glm::vec3 sourceDimensions(zoneStringList[3].toFloat(), zoneStringList[4].toFloat(), zoneStringList[5].toFloat()); - - glm::vec3 listenerCorner(zoneStringList[6].toFloat(), zoneStringList[7].toFloat(), zoneStringList[8].toFloat()); - glm::vec3 listenerDimensions(zoneStringList[9].toFloat(), zoneStringList[10].toFloat(), zoneStringList[11].toFloat()); + const QString UNATTENUATED_ZONE_KEY = "unattenuated-zone"; - _sourceUnattenuatedZone = new AABox(sourceCorner, sourceDimensions); - _listenerUnattenuatedZone = new AABox(listenerCorner, listenerDimensions); - - glm::vec3 sourceCenter = _sourceUnattenuatedZone->calcCenter(); - glm::vec3 destinationCenter = _listenerUnattenuatedZone->calcCenter(); - - qDebug() << "There is an unattenuated zone with source center at" + QString unattenuatedZoneString = audioGroupObject[UNATTENUATED_ZONE_KEY].toString(); + if (!unattenuatedZoneString.isEmpty()) { + QStringList zoneStringList = unattenuatedZoneString.split(','); + + glm::vec3 sourceCorner(zoneStringList[0].toFloat(), zoneStringList[1].toFloat(), zoneStringList[2].toFloat()); + glm::vec3 sourceDimensions(zoneStringList[3].toFloat(), zoneStringList[4].toFloat(), zoneStringList[5].toFloat()); + + glm::vec3 listenerCorner(zoneStringList[6].toFloat(), zoneStringList[7].toFloat(), zoneStringList[8].toFloat()); + glm::vec3 listenerDimensions(zoneStringList[9].toFloat(), zoneStringList[10].toFloat(), zoneStringList[11].toFloat()); + + _sourceUnattenuatedZone = new AABox(sourceCorner, sourceDimensions); + _listenerUnattenuatedZone = new AABox(listenerCorner, listenerDimensions); + + glm::vec3 sourceCenter = _sourceUnattenuatedZone->calcCenter(); + glm::vec3 destinationCenter = _listenerUnattenuatedZone->calcCenter(); + + qDebug() << "There is an unattenuated zone with source center at" << QString("%1, %2, %3").arg(sourceCenter.x).arg(sourceCenter.y).arg(sourceCenter.z); - qDebug() << "Buffers inside this zone will not be attenuated inside a box with center at" + qDebug() << "Buffers inside this zone will not be attenuated inside a box with center at" << QString("%1, %2, %3").arg(destinationCenter.x).arg(destinationCenter.y).arg(destinationCenter.z); - } - - // check the payload to see if we have asked for dynamicJitterBuffer support - const QString DYNAMIC_JITTER_BUFFER_REGEX_STRING = "--dynamicJitterBuffer"; - QRegExp dynamicJitterBufferMatch(DYNAMIC_JITTER_BUFFER_REGEX_STRING); - if (dynamicJitterBufferMatch.indexIn(_payload) != -1) { - qDebug() << "Enable dynamic jitter buffers."; - _useDynamicJitterBuffers = true; - } else { - qDebug() << "Dynamic jitter buffers disabled, using old behavior."; + } + + // check the payload to see if we have asked for dynamicJitterBuffer support + const QString DYNAMIC_JITTER_BUFFER_JSON_KEY = "dynamic-jitter-buffer"; + bool shouldUseDynamicJitterBuffers = audioGroupObject[DYNAMIC_JITTER_BUFFER_JSON_KEY].toBool(); + if (shouldUseDynamicJitterBuffers) { + qDebug() << "Enable dynamic jitter buffers."; + _useDynamicJitterBuffers = true; + } else { + qDebug() << "Dynamic jitter buffers disabled, using old behavior."; + } } int nextFrame = 0; diff --git a/domain-server/src/DomainServerSettingsManager.cpp b/domain-server/src/DomainServerSettingsManager.cpp index f3315e8324..d7e2e05ca8 100644 --- a/domain-server/src/DomainServerSettingsManager.cpp +++ b/domain-server/src/DomainServerSettingsManager.cpp @@ -61,7 +61,7 @@ bool DomainServerSettingsManager::handleHTTPRequest(HTTPConnection* connection, connection->respond(HTTPConnection::StatusCode200, jsonSuccess.toUtf8(), "application/json"); return true; - } else if (connection->requestOperation() == QNetworkAccessManager::GetOperation && url.path() == "/settingz.json") { + } else if (connection->requestOperation() == QNetworkAccessManager::GetOperation && url.path() == "/settings.json") { // this is a GET operation for our settings // check if there is a query parameter for settings affecting a particular type of assignment From bb44d8b478c72f7657028a59c38c94411a17af25 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 27 Jun 2014 09:36:47 -0700 Subject: [PATCH 21/32] fix place lookup for new APIs --- interface/src/location/LocationManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/location/LocationManager.cpp b/interface/src/location/LocationManager.cpp index 1d783cc8e7..32172d6e38 100644 --- a/interface/src/location/LocationManager.cpp +++ b/interface/src/location/LocationManager.cpp @@ -15,7 +15,7 @@ #include "LocationManager.h" const QString GET_USER_ADDRESS = "/api/v1/users/%1/address"; -const QString GET_PLACE_ADDRESS = "/api/v1/places/%1/address"; +const QString GET_PLACE_ADDRESS = "/api/v1/places/%1"; const QString GET_ADDRESSES = "/api/v1/addresses/%1"; const QString POST_PLACE_CREATE = "/api/v1/places/"; From aad666be62a49a52c58d0063028013a26551ce3e Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 27 Jun 2014 09:48:27 -0700 Subject: [PATCH 22/32] more sitting work --- examples/sit.js | 184 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 177 insertions(+), 7 deletions(-) diff --git a/examples/sit.js b/examples/sit.js index 77a626c63f..576b17dcf5 100644 --- a/examples/sit.js +++ b/examples/sit.js @@ -38,9 +38,14 @@ var standUpButton = Overlays.addOverlay("image", { var passedTime = 0.0; var startPosition = null; +var startRotation = null; var animationLenght = 2.0; -var sitting = false; +var avatarOldPosition = { x: 0, y: 0, z: 0 }; + +var sitting = false; + +var seat = new Object(); // This is the pose we would like to end up var pose = [ @@ -83,7 +88,7 @@ var sittingDownAnimation = function(deltaTime) { } } -var standingUpAnimation = function(deltaTime){ +var standingUpAnimation = function(deltaTime) { passedTime += deltaTime; var factor = 1 - passedTime/animationLenght; @@ -97,6 +102,23 @@ var standingUpAnimation = function(deltaTime){ } } +var goToSeatAnimation = function(deltaTime) { + passedTime += deltaTime; + var factor = passedTime/animationLenght; + + if (passedTime <= animationLenght) { + var targetPosition = Vec3.sum(seat.position, { x: 0.3, y: 0.5, z: 0 }); + MyAvatar.position = Vec3.sum(Vec3.multiply(startPosition, 1 - factor), Vec3.multiply(targetPosition, factor)); + } else if (passedTime <= 2 * animationLenght) { + Quat.print("MyAvatar: ", MyAvatar.orientation); + Quat.print("Seat: ", seat.rotation); + MyAvatar.orientation = Quat.mix(startRotation, seat.rotation, factor - 1); + } else { + Script.update.disconnect(goToSeatAnimation); + sitDown(); + } +} + function sitDown() { sitting = true; passedTime = 0.0; @@ -124,15 +146,104 @@ function standUp() { Overlays.editOverlay(sitDownButton, { visible: true }); } -Controller.mousePressEvent.connect(function(event){ +var models = new Object(); +function SeatIndicator(modelProperties, seatIndex) { + this.position = Vec3.sum(modelProperties.position, + Vec3.multiply(Vec3.multiplyQbyV(modelProperties.modelRotation, + modelProperties.sittingPoints[seatIndex].position), + modelProperties.radius)); + + this.orientation = Quat.multiply(modelProperties.modelRotation, + modelProperties.sittingPoints[seatIndex].rotation); + this.scale = MyAvatar.scale / 12; + + this.sphere = Overlays.addOverlay("sphere", { + position: this.position, + size: this.scale, + solid: true, + color: { red: 0, green: 0, blue: 255 }, + alpha: 1, + visible: true + }); + + this.show = function(doShow) { + Overlays.editOverlay(this.sphere, { visible: doShow }); + } + + this.update = function() { + Overlays.editOverlay(this.sphere, { + position: this.position, + size: this.scale + }); + } + + this.cleanup = function() { + Overlays.deleteOverlay(this.sphere); + } +} +Controller.mousePressEvent.connect(function(event) { var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); if (clickedOverlay == sitDownButton) { sitDown(); } else if (clickedOverlay == standUpButton) { standUp(); - } + } else { + var pickRay = Camera.computePickRay(event.x, event.y); + + var clickedOnSeat = false; + + for (index in models) { + var model = models[index]; + + for (var i = 0; i < model.properties.sittingPoints.length; ++i) { + if (raySphereIntersection(pickRay.origin, + pickRay.direction, + model.properties.sittingPoints[i].indicator.position, + model.properties.sittingPoints[i].indicator.scale / 2)) { + clickedOnSeat = true; + seat.position = model.properties.sittingPoints[i].indicator.position; + seat.rotation = model.properties.sittingPoints[i].indicator.orientation; + } + } + } + if (clickedOnSeat) { + passedTime = 0.0; + startPosition = MyAvatar.position; + startRotation = MyAvatar.orientation; + try{ Script.update.disconnect(standingUpAnimation); } catch(e){} + try{ Script.update.disconnect(sittingDownAnimation); } catch(e){} + Script.update.connect(goToSeatAnimation); + } + + + + return; + var intersection = Models.findRayIntersection(pickRay); + + if (intersection.accurate && intersection.intersects && false) { + var properties = intersection.modelProperties; + print("Intersecting with model, let's check for seats."); + + if (properties.sittingPoints.length > 0) { + print("Available seats, going to the first one: " + properties.sittingPoints[0].name); + seat.position = Vec3.sum(properties.position, Vec3.multiplyQbyV(properties.modelRotation, properties.sittingPoints[0].position)); + Vec3.print("Seat position: ", seat.position); + seat.rotation = Quat.multiply(properties.modelRotation, properties.sittingPoints[0].rotation); + Quat.print("Seat rotation: ", seat.rotation); + + passedTime = 0.0; + startPosition = MyAvatar.position; + startRotation = MyAvatar.orientation; + try{ Script.update.disconnect(standingUpAnimation); } catch(e){} + try{ Script.update.disconnect(sittingDownAnimation); } catch(e){} + Script.update.connect(goToSeatAnimation); + } else { + print ("Sorry, no seats here."); + } + } + } }) function update(deltaTime){ @@ -143,7 +254,62 @@ function update(deltaTime){ var newY = (windowDimensions.y - buttonHeight) / 2 ; Overlays.editOverlay( standUpButton, {x: newX, y: newY} ); Overlays.editOverlay( sitDownButton, {x: newX, y: newY} ); - } + } + + if (MyAvatar.position.x != avatarOldPosition.x && + MyAvatar.position.y != avatarOldPosition.y && + MyAvatar.position.z != avatarOldPosition.z) { + avatarOldPosition = MyAvatar.position; + + var SEARCH_RADIUS = 5; + var foundModels = Models.findModels(MyAvatar.position, SEARCH_RADIUS); + // Let's remove indicator that got out of radius + for (model in models) { + if (Vec3.distance(models[model].properties.position, MyAvatar.position) > SEARCH_RADIUS) { + removeIndicators(models[model]); + } + } + + // Let's add indicators to new seats in radius + for (var i = 0; i < foundModels.length; ++i) { + var model = foundModels[i]; + if (typeof(models[model.id]) == "undefined") { + addIndicators(model); + } + } + } +} + +function addIndicators(modelID) { + modelID.properties = Models.getModelProperties(modelID); + if (modelID.properties.sittingPoints.length > 0) { + for (var i = 0; i < modelID.properties.sittingPoints.length; ++i) { + modelID.properties.sittingPoints[i].indicator = new SeatIndicator(modelID.properties, i); + } + + models[modelID.id] = modelID; + } else { + Models.editModel(modelID, { glowLevel: 0.0 }); + } +} + +function removeIndicators(modelID) { + for (var i = 0; i < modelID.properties.sittingPoints.length; ++i) { + modelID.properties.sittingPoints[i].indicator.cleanup(); + } + delete models[modelID.id]; +} + +function raySphereIntersection(origin, direction, center, radius) { + var A = origin; + var B = Vec3.normalize(direction); + var P = center; + + var x = Vec3.dot(Vec3.subtract(P, A), B); + var X = Vec3.sum(A, Vec3.multiply(B, x)); + var d = Vec3.length(Vec3.subtract(P, X)); + + return (x > 0 && d <= radius); } function keyPressEvent(event) { @@ -161,11 +327,15 @@ Script.update.connect(update); Controller.keyPressEvent.connect(keyPressEvent); Script.scriptEnding.connect(function() { - for (var i = 0; i < pose.length; i++){ MyAvatar.clearJointData(pose[i].joint); - } + } Overlays.deleteOverlay(sitDownButton); Overlays.deleteOverlay(standUpButton); + for (model in models){ + for (var i = 0; i < models[model].properties.sittingPoints.length; ++i) { + models[model].properties.sittingPoints[i].indicator.cleanup(); + } + } }); From baf4a82269fc528bbd39b0922a4ea5fd33561527 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 27 Jun 2014 09:56:03 -0700 Subject: [PATCH 23/32] Fix crash occuring when geometry not yet available --- libraries/models/src/ModelTreeElement.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libraries/models/src/ModelTreeElement.cpp b/libraries/models/src/ModelTreeElement.cpp index c9e5f0f309..960d1dd4cb 100644 --- a/libraries/models/src/ModelTreeElement.cpp +++ b/libraries/models/src/ModelTreeElement.cpp @@ -330,7 +330,9 @@ bool ModelTreeElement::updateModel(const ModelItemID& modelID, const ModelItemPr } if (found) { thisModel.setProperties(properties); - thisModel.setSittingPoints(_myTree->getGeometryForModel(thisModel)->sittingPoints); + if (_myTree->getGeometryForModel(thisModel)) { + thisModel.setSittingPoints(_myTree->getGeometryForModel(thisModel)->sittingPoints); + } markWithChangedTime(); // mark our element as changed.. const bool wantDebug = false; if (wantDebug) { From 4281168fe99e06dcf6fd77854fce326385231731 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 27 Jun 2014 10:03:50 -0700 Subject: [PATCH 24/32] Hide seat once you are seated --- examples/sit.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/examples/sit.js b/examples/sit.js index 576b17dcf5..57828afc52 100644 --- a/examples/sit.js +++ b/examples/sit.js @@ -46,6 +46,7 @@ var avatarOldPosition = { x: 0, y: 0, z: 0 }; var sitting = false; var seat = new Object(); +var hiddingSeats = false; // This is the pose we would like to end up var pose = [ @@ -116,6 +117,7 @@ var goToSeatAnimation = function(deltaTime) { } else { Script.update.disconnect(goToSeatAnimation); sitDown(); + showIndicators(false); } } @@ -277,6 +279,10 @@ function update(deltaTime){ addIndicators(model); } } + + if (hiddingSeats && passedTime >= animationLenght) { + showIndicators(true); + } } } @@ -300,6 +306,16 @@ function removeIndicators(modelID) { delete models[modelID.id]; } +function showIndicators(doShow) { + for (model in models) { + var modelID = models[model]; + for (var i = 0; i < modelID.properties.sittingPoints.length; ++i) { + modelID.properties.sittingPoints[i].indicator.show(doShow); + } + } + hiddingSeats = !doShow; +} + function raySphereIntersection(origin, direction, center, radius) { var A = origin; var B = Vec3.normalize(direction); From 8edc4bf9d177abc147a976389c14106c5b4b0ab9 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 27 Jun 2014 10:38:39 -0700 Subject: [PATCH 25/32] add HTTPS request debugged to domain-server --- domain-server/src/DomainServer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index fcfe1ff582..7a2d5f4f99 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -1169,6 +1169,7 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url bool DomainServer::handleHTTPSRequest(HTTPSConnection* connection, const QUrl &url) { const QString URI_OAUTH = "/oauth"; + qDebug() << "HTTPS request received at" << url.toString(); if (url.path() == URI_OAUTH) { QUrlQuery codeURLQuery(url); From 5bea267cd25dd4b1fe954ef8c8f4bb34551d9abf Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 27 Jun 2014 10:54:57 -0700 Subject: [PATCH 26/32] make sitting points semi transparent --- examples/sit.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/sit.js b/examples/sit.js index 57828afc52..056a65fbf1 100644 --- a/examples/sit.js +++ b/examples/sit.js @@ -164,7 +164,7 @@ function SeatIndicator(modelProperties, seatIndex) { size: this.scale, solid: true, color: { red: 0, green: 0, blue: 255 }, - alpha: 1, + alpha: 0.3, visible: true }); From 21b839a8b5d3301a7b4354916f0ecad92eab5e1c Mon Sep 17 00:00:00 2001 From: Leonardo Murillo Date: Fri, 27 Jun 2014 11:08:24 -0700 Subject: [PATCH 27/32] Updating concertCamera script --- examples/concertCamera.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/examples/concertCamera.js b/examples/concertCamera.js index 7280958bc6..03908d0b57 100644 --- a/examples/concertCamera.js +++ b/examples/concertCamera.js @@ -16,8 +16,8 @@ var avatarPosition; var cameraNumber = 0; var freeCamera = false; -var cameraLocations = [ {x: 7972.2, y: 241.6, z: 7304.1}, {x: 7973.0, y: 241.6, z: 7304.1}, {x: 7975.5, y: 241.6, z: 7304.1}, {x: 7972.3, y: 241.6, z: 7303.3}, {x: 7971.4, y: 241.6, z: 7304.3}, {x: 7973.5, y: 240.6, z: 7302.5} ]; -var cameraLookAts = [ {x: 7971.1, y: 241.6, z: 7304.1}, {x: 7972.1, y: 241.6, z: 7304.1}, {x: 7972.1, y: 241.6, z: 7304.1}, {x: 7972.1, y: 241.6, z: 7304.1}, {x: 7972.1, y: 241.6, z: 7304.1}, {x: 7972.1, y: 241., z: 7304.1} ]; +var cameraLocations = [ {x: 7971.9, y: 241.3, z: 7304.1}, {x: 7973.0, y: 241.3, z: 7304.1}, {x: 7975.5, y: 241.3, z: 7304.1}, {x: 7972.3, y: 241.3, z: 7303.3}, {x: 7971.0, y: 241.3, z: 7304.3}, {x: 7973.5, y: 240.7, z: 7302.5} ]; +var cameraLookAts = [ {x: 7971.1, y: 241.3, z: 7304.1}, {x: 7972.1, y: 241.3, z: 7304.1}, {x: 7972.1, y: 241.3, z: 7304.1}, {x: 7972.1, y: 241.3, z: 7304.1}, {x: 7972.1, y: 241.3, z: 7304.1}, {x: 7971.3, y: 241.3, z: 7304.2} ]; function saveCameraState() { oldMode = Camera.getMode(); @@ -56,6 +56,11 @@ function keyPressEvent(event) { Camera.setPosition(cameraLocations[choice - 1]); Camera.keepLookingAt(cameraLookAts[choice - 1]); } + if (event.text == "ESC") { + cameraNumber = 0; + freeCamera = false; + restoreCameraState(); + } if (event.text == "0") { // Show camera location in log var cameraLocation = Camera.getPosition(); From 657bf6b3d5f8d22c234adcf2c3cfe777a8bce39b Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 27 Jun 2014 11:41:35 -0700 Subject: [PATCH 28/32] repairs so OAuth flow doesn't get stuck after an error --- interface/src/ui/OAuthWebViewHandler.cpp | 11 +++++++++++ interface/src/ui/OAuthWebViewHandler.h | 1 + 2 files changed, 12 insertions(+) diff --git a/interface/src/ui/OAuthWebViewHandler.cpp b/interface/src/ui/OAuthWebViewHandler.cpp index 5b4431bd0f..8ec415584d 100644 --- a/interface/src/ui/OAuthWebViewHandler.cpp +++ b/interface/src/ui/OAuthWebViewHandler.cpp @@ -109,6 +109,8 @@ void OAuthWebViewHandler::displayWebviewForAuthorizationURL(const QUrl& authoriz connect(_activeWebView->page()->networkAccessManager(), &QNetworkAccessManager::sslErrors, this, &OAuthWebViewHandler::handleSSLErrors); + connect(_activeWebView->page()->networkAccessManager(), &QNetworkAccessManager::finished, + this, &OAuthWebViewHandler::handleReplyFinished); connect(_activeWebView.data(), &QWebView::loadFinished, this, &OAuthWebViewHandler::handleLoadFinished); // connect to the destroyed signal so after the web view closes we can start a timer @@ -132,6 +134,14 @@ void OAuthWebViewHandler::handleLoadFinished(bool success) { NodeList::getInstance()->setSessionUUID(QUuid(authQuery.queryItemValue(AUTH_STATE_QUERY_KEY))); _activeWebView->close(); + _activeWebView = NULL; + } +} + +void OAuthWebViewHandler::handleReplyFinished(QNetworkReply* reply) { + if (_activeWebView && reply->error() != QNetworkReply::NoError) { + qDebug() << "Error loading" << reply->url() << "-" << reply->errorString(); + _activeWebView->close(); } } @@ -148,6 +158,7 @@ void OAuthWebViewHandler::handleURLChanged(const QUrl& url) { _activeWebView->show(); } else if (url.toString() == DEFAULT_NODE_AUTH_URL.toString() + "/login") { // this is a login request - we're going to close the webview and signal the AccountManager that we need a login + qDebug() << "data-server replied with login request. Signalling that login is required to proceed with OAuth."; _activeWebView->close(); AccountManager::getInstance().checkAndSignalForAccessToken(); } diff --git a/interface/src/ui/OAuthWebViewHandler.h b/interface/src/ui/OAuthWebViewHandler.h index 8f0c01c90d..1a95f17dfd 100644 --- a/interface/src/ui/OAuthWebViewHandler.h +++ b/interface/src/ui/OAuthWebViewHandler.h @@ -31,6 +31,7 @@ public slots: private slots: void handleSSLErrors(QNetworkReply* networkReply, const QList& errorList); void handleLoadFinished(bool success); + void handleReplyFinished(QNetworkReply* reply); void handleWebViewDestroyed(QObject* destroyedObject); void handleURLChanged(const QUrl& url); private: From 1bc2f214a563d16fca20ac2b903514ebb471bb64 Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Fri, 27 Jun 2014 22:18:38 +0200 Subject: [PATCH 29/32] Compiler warning fixes. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes all warnings that I got while compiling with g++ 4.7.2: In file included from interface/src/Application.h:53:0, from interface/src/Menu.cpp:36: interface/src/Menu.h: In constructor ‘Menu::Menu()’: interface/src/Menu.h:292:13: warning: ‘Menu::_scriptsLocation’ will be initialized after [-Wreorder] interface/src/Menu.h:289:27: warning: ‘QPointer Menu::_loginDialog’ [-Wreorder] interface/src/Menu.cpp:82:1: warning: when initialized here [-Wreorder] libraries/audio/src/AudioRingBuffer.cpp: In member function ‘qint64 AudioRingBuffer::writeData(const char*, qint64)’: libraries/audio/src/AudioRingBuffer.cpp:126:75: warning: comparison between signed and unsigned integer expressions [-Wsign-compare] libraries/audio/src/PositionalAudioRingBuffer.cpp: In member function ‘bool PositionalAudioRingBuffer::shouldBeAddedToMix()’: libraries/audio/src/PositionalAudioRingBuffer.cpp:212:37: warning: comparison between signed and unsigned integer expressions [-Wsign-compare] interface/ui/preferencesDialog.ui: Warning: The name 'horizontalLayout_11' (QHBoxLayout) is already in use, defaulting to 'horizontalLayout_111'. interface/ui/preferencesDialog.ui: Warning: The name 'horizontalSpacer_11' (QSpacerItem) is already in use, defaulting to 'horizontalSpacer_111'. interface/src/avatar/Avatar.cpp: In member function ‘void Avatar::initializeHair()’: interface/src/avatar/Avatar.cpp:587:21: warning: name lookup of ‘link’ changed [enabled by default] interface/src/avatar/Avatar.cpp:574:18: warning: matches this ‘link’ under ISO standard rules [enabled by default] interface/src/avatar/Avatar.cpp:577:22: warning: matches this ‘link’ under old rules [enabled by default] interface/src/ui/ApplicationOverlay.cpp: In member function ‘void ApplicationOverlay::renderControllerPointers()’: interface/src/ui/ApplicationOverlay.cpp:379:59: warning: comparison between signed and unsigned integer expressions [-Wsign-compare] In file included from interface/src/ui/RunningScriptsWidget.cpp:14:0: interface/src/ui/RunningScriptsWidget.h: In constructor ‘RunningScriptsWidget::RunningScriptsWidget(QWidget*)’: interface/src/ui/RunningScriptsWidget.h:61:18: warning: ‘RunningScriptsWidget::_scriptsModel’ will be initialized after [-Wreorder] interface/src/ui/RunningScriptsWidget.h:60:27: warning: ‘QSortFilterProxyModel RunningScriptsWidget::_proxyModel’ [-Wreorder] interface/src/ui/RunningScriptsWidget.cpp:27:1: warning: when initialized here [-Wreorder] --- interface/src/Menu.cpp | 4 ++-- interface/src/avatar/Avatar.cpp | 4 ++-- interface/src/ui/ApplicationOverlay.cpp | 2 +- interface/src/ui/RunningScriptsWidget.cpp | 4 ++-- interface/ui/preferencesDialog.ui | 4 ++-- libraries/audio/src/AudioRingBuffer.cpp | 2 +- libraries/audio/src/PositionalAudioRingBuffer.cpp | 2 +- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 6269d4a8c0..9357ba2004 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -108,9 +108,9 @@ Menu::Menu() : _fastFPSAverage(ONE_SECOND_OF_FRAMES), _loginAction(NULL), _preferencesDialog(NULL), - _scriptsLocation(), _loginDialog(NULL), - _snapshotsLocation() + _snapshotsLocation(), + _scriptsLocation() { Application *appInstance = Application::getInstance(); diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 5a294bb2a5..9b136980f4 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -574,8 +574,8 @@ void Avatar::initializeHair() { for (int link = 0; link < HAIR_LINKS; link++) { int vertexIndex = strand * HAIR_LINKS + link; // Clear constraints - for (int link = 0; link < HAIR_MAX_CONSTRAINTS; link++) { - _hairConstraints[vertexIndex * HAIR_MAX_CONSTRAINTS + link] = -1; + for (int link2 = 0; link2 < HAIR_MAX_CONSTRAINTS; link2++) { + _hairConstraints[vertexIndex * HAIR_MAX_CONSTRAINTS + link2] = -1; } if (vertexIndex % HAIR_LINKS == 0) { // start of strand diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 342a145953..77e8986297 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -376,7 +376,7 @@ void ApplicationOverlay::renderControllerPointers() { //then disable it. const int MAX_BUTTON_PRESS_TIME = 250 * MSECS_TO_USECS; - if (usecTimestampNow() - pressedTime[index] < MAX_BUTTON_PRESS_TIME) { + if (usecTimestampNow() < pressedTime[index] + MAX_BUTTON_PRESS_TIME) { _magActive[index] = !stateWhenPressed[index]; } } diff --git a/interface/src/ui/RunningScriptsWidget.cpp b/interface/src/ui/RunningScriptsWidget.cpp index 136d0a2d38..8a7ebcbfd4 100644 --- a/interface/src/ui/RunningScriptsWidget.cpp +++ b/interface/src/ui/RunningScriptsWidget.cpp @@ -28,8 +28,8 @@ RunningScriptsWidget::RunningScriptsWidget(QWidget* parent) : FramelessDialog(parent, 0, POSITION_LEFT), ui(new Ui::RunningScriptsWidget), _signalMapper(this), - _scriptsModel(this), - _proxyModel(this) { + _proxyModel(this), + _scriptsModel(this) { ui->setupUi(this); setAttribute(Qt::WA_DeleteOnClose, false); diff --git a/interface/ui/preferencesDialog.ui b/interface/ui/preferencesDialog.ui index a75c2bdec2..95678bf6f8 100644 --- a/interface/ui/preferencesDialog.ui +++ b/interface/ui/preferencesDialog.ui @@ -902,7 +902,7 @@ padding: 10px;margin-top:10px - + 0 @@ -937,7 +937,7 @@ padding: 10px;margin-top:10px - + Arial diff --git a/libraries/audio/src/AudioRingBuffer.cpp b/libraries/audio/src/AudioRingBuffer.cpp index ee4027841b..a2d3715462 100644 --- a/libraries/audio/src/AudioRingBuffer.cpp +++ b/libraries/audio/src/AudioRingBuffer.cpp @@ -121,7 +121,7 @@ qint64 AudioRingBuffer::writeData(const char* data, qint64 maxSize) { // make sure we have enough bytes left for this to be the right amount of audio // otherwise we should not copy that data, and leave the buffer pointers where they are - int samplesToCopy = std::min((quint64)(maxSize / sizeof(int16_t)), (quint64)_sampleCapacity); + quint64 samplesToCopy = std::min((quint64)(maxSize / sizeof(int16_t)), (quint64)_sampleCapacity); if (_hasStarted && samplesToCopy > _sampleCapacity - samplesAvailable()) { // this read will cross the next output, so call us starved and reset the buffer diff --git a/libraries/audio/src/PositionalAudioRingBuffer.cpp b/libraries/audio/src/PositionalAudioRingBuffer.cpp index 23e258fe87..acd688bdc0 100644 --- a/libraries/audio/src/PositionalAudioRingBuffer.cpp +++ b/libraries/audio/src/PositionalAudioRingBuffer.cpp @@ -209,7 +209,7 @@ bool PositionalAudioRingBuffer::shouldBeAddedToMix() { } return false; - } else if (samplesAvailable() < samplesPerFrame) { + } else if (samplesAvailable() < (unsigned int)samplesPerFrame) { // if the buffer doesn't have a full frame of samples to take for mixing, it is starved _isStarved = true; From f33728b6152076f8ac90cc338672ceb639464fa5 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 30 Jun 2014 09:13:42 -0700 Subject: [PATCH 30/32] guarantee that ragdoll is clear before initialized --- interface/src/avatar/SkeletonModel.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index e9328d32ca..763aa27f00 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -505,8 +505,7 @@ void SkeletonModel::renderRagdoll() { // virtual void SkeletonModel::initRagdollPoints() { - assert(_ragdollPoints.size() == 0); - assert(_ragdollConstraints.size() == 0); + clearRagdollConstraintsAndPoints(); // one point for each joint int numJoints = _jointStates.size(); From 57c17eb972f92eaf3ff110426c7f7d6a5230b15c Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 30 Jun 2014 09:18:31 -0700 Subject: [PATCH 31/32] remove unecessary clearRagdollConstraintsAndPoints() --- interface/src/avatar/SkeletonModel.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 763aa27f00..3b09a1a2ba 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -39,7 +39,6 @@ void SkeletonModel::setJointStates(QVector states) { } clearShapes(); - clearRagdollConstraintsAndPoints(); if (_enableShapes) { buildShapes(); } From 146cd2b59d7cee3e7c25cf5388ef0afe8622b0e3 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 30 Jun 2014 12:23:33 -0700 Subject: [PATCH 32/32] update BUILD.md to remove zlib requirement --- BUILD.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BUILD.md b/BUILD.md index b8bc1cd14c..674f0d24cc 100644 --- a/BUILD.md +++ b/BUILD.md @@ -63,7 +63,7 @@ If `libgnutls28-dev` 3.2.12 or higher is available via your package manager, it [Homebrew](http://brew.sh/) is an excellent package manager for OS X. It makes install of all hifi dependencies very simple. brew tap highfidelity/homebrew-formulas - brew install cmake glm zlib gnutls + brew install cmake glm gnutls brew install highfidelity/formulas/qt5 brew link qt5 --force brew install highfidelity/formulas/qxmpp