Browse Source

Merge branch 'dev' of git://github.com/arodic/three.js into dev

Mr.doob 12 years ago
parent
commit
34b866c862

+ 68 - 86
editor/js/Editor.js

@@ -5,11 +5,6 @@ var Editor = function ( scene ) {
   this.textures = {};
   this.objects = {};
 
-  this.geometriesCount = 0;
-  this.materialsCount = 0;
-  this.texturesCount = 0;
-  this.objectsCount = 0;
-
   this.selected = {};
   this.helpers = {};
 
@@ -50,9 +45,7 @@ Editor.prototype = {
 
   createObject: function( type, parameters, material ) {
 
-    this.objectsCount ++;
-
-    type = type ? type.toLowerCase() : null;
+    type = type ? type : 'Group';
 
     var object;
     var geometry;
@@ -61,6 +54,7 @@ Editor.prototype = {
 
     parameters = parameters ? parameters : {};
 
+    var name = parameters.name ? parameters.name : this.incrementName( type, 'object' );
     var color = parameters.color ? parameters.color : null;
     var groundColor = parameters.groundColor ? parameters.groundColor : null;
     var intensity = parameters.intensity ? parameters.intensity : null;
@@ -68,72 +62,56 @@ Editor.prototype = {
     var angle = parameters.angle ? parameters.angle : null;
     var exponent = parameters.exponent ? parameters.exponent : null;
 
-    if ( !type ) {
+    if ( type == 'Group' ) {
 
       object = new THREE.Object3D();
-      object.name = parameters.name ? parameters.name : 'Group ' + this.objectsCount;
 
-    } else if ( type == 'plane' ) {
+    } else if ( type == 'Plane' ) {
 
       geometry = this.createGeometry( type, parameters );
-
       object = new THREE.Mesh( geometry, this.defaultMaterial );
-      object.name = name ? name : type + this.objectsCount;
 
       object.rotation.x = - Math.PI/2;
 
-    } else if ( type == 'cube' ) {
+    } else if ( type == 'Cube' ) {
 
       geometry = this.createGeometry( type, parameters );
-
       object = new THREE.Mesh( geometry, this.defaultMaterial );
-      object.name = name ? name : type + this.objectsCount;
 
-    } else if ( type == 'cylinder' ) {
+    } else if ( type == 'Cylinder' ) {
 
       geometry = this.createGeometry( type, parameters );
-
       object = new THREE.Mesh( geometry, this.defaultMaterial );
-      object.name = name ? name : type + this.objectsCount;
 
-    } else if ( type == 'sphere' ) {
+    } else if ( type == 'Sphere' ) {
 
       geometry = this.createGeometry( type, parameters );
-
       object = new THREE.Mesh( geometry, this.defaultMaterial );
-      object.name = name ? name : type + this.objectsCount;
 
-    } else if ( type == 'icosahedron' ) {
+    } else if ( type == 'Icosahedron' ) {
 
       geometry = this.createGeometry( type, parameters );
-
       object = new THREE.Mesh( geometry, this.defaultMaterial );
-      object.name = name ? name : type + this.objectsCount;
 
-    } else if ( type == 'torus' ) {
+    } else if ( type == 'Torus' ) {
 
       geometry = this.createGeometry( type, parameters );
-
       object = new THREE.Mesh( geometry, this.defaultMaterial );
-      object.name = name ? name : type + this.objectsCount;
-
-    } else if ( type == 'torusknot' ) {
+      
+    } else if ( type == 'TorusKnot' ) {
 
       geometry = this.createGeometry( type, parameters );
-
       object = new THREE.Mesh( geometry, this.defaultMaterial );
-      object.name = name ? name : type + this.objectsCount;
 
-    } else if ( type == 'pointlight' ) {
+    } else if ( type == 'PointLight' ) {
 
       color = color ? color : 0xffffff;
       intensity = intensity ? intensity : 1;
       distance = distance ? distance : 0;
 
-      var object = new THREE.PointLight( color, intensity, distance );
-      object.name = name ? name : 'PointLight ' + this.objectsCount;
+      object = new THREE.PointLight( color, intensity, distance );
 
-    } else if ( type == 'spotlight' ) {
+    } else if ( type == 'SpotLight' ) {
 
       color = color ? color : 0xffffff;
       intensity = intensity ? intensity : 1;
@@ -141,44 +119,41 @@ Editor.prototype = {
       angle = angle ? angle : Math.PI * 0.1;
       exponent = exponent ? exponent : 10;
 
-      var object = new THREE.SpotLight( color, intensity, distance, angle, exponent );
-      object.name =  name ? name : 'SpotLight ' + this.objectsCount;
+      object = new THREE.SpotLight( color, intensity, distance, angle, exponent );
       object.target.name = object.name + ' Target';
 
       object.position.set( 0, 1, 0 ).multiplyScalar( 200 );
 
-    } else if ( type == 'directionallight' ) {
+    } else if ( type == 'DirectionalLight' ) {
 
       color = color ? color : 0xffffff;
       intensity = intensity ? intensity : 1;
 
-      var object = new THREE.DirectionalLight( color, intensity );
-      object.name = name ? name : 'DirectionalLight ' + this.objectsCount;
+      object = new THREE.DirectionalLight( color, intensity );
       object.target.name = object.name + ' Target';
 
       object.position.set( 1, 1, 1 ).multiplyScalar( 200 );
 
-    } else if ( type == 'hemispherelight' ) {
+    } else if ( type == 'HemisphereLight' ) {
 
       color = color ? color : 0x00aaff;
       groundColor = groundColor ? groundColor : 0xffaa00;
       intensity = intensity ? intensity : 1;
 
-      var object = new THREE.HemisphereLight( color, groundColor, intensity );
-      object.name = name ? name : 'HemisphereLight ' + this.objectsCount;
+      object = new THREE.HemisphereLight( color, groundColor, intensity );
 
       object.position.set( 1, 1, 1 ).multiplyScalar( 200 );
 
-    } else if ( type == 'ambientlight' ) {
+    } else if ( type == 'AmbientLight' ) {
 
       color = color ? color : 0x222222;
 
-      var object = new THREE.AmbientLight( color );
-      object.name = name ? name : 'AmbientLight ' + this.objectsCount;
+      object = new THREE.AmbientLight( color );
 
     }
 
-    if ( object ) this.addObject( object );
+    object.name = name;
+    this.addObject( object );
 
     return object;
 
@@ -186,12 +161,10 @@ Editor.prototype = {
 
   createGeometry: function( type, parameters ) {
 
-    this.geometriesCount ++;
-
-    type = type ? type : null;
+    type = type ? type : 'Geometry';
     parameters = parameters ? parameters : {};
 
-    var name = parameters.name ? parameters.name : type + 'Geometry ' + this.geometriesCount;
+    var name = parameters.name ? parameters.name : this.incrementName( type + 'Geometry', 'geometry' );
     var width = parameters.width ? parameters.width : null;
     var height = parameters.height ? parameters.height : null;
     var depth = parameters.depth ? parameters.depth : null;
@@ -217,11 +190,11 @@ Editor.prototype = {
 
     var geometry;
 
-    if ( !type ) {
+    if ( type == 'Geometry' ) {
 
       geometry = new THREE.Geometry();
 
-    } else if ( type == 'plane' ) {
+    } else if ( type == 'Plane' ) {
 
       width = width ? width : 200;
       height = height ? height : 200;
@@ -230,7 +203,7 @@ Editor.prototype = {
 
       geometry = new THREE.PlaneGeometry( width, height, widthSegments, heightSegments );
 
-    } else if ( type == 'cube' ) {
+    } else if ( type == 'Cube' ) {
 
       width = width ? width : 100;
       height = height ? height : 100;
@@ -241,7 +214,7 @@ Editor.prototype = {
 
       geometry = new THREE.CubeGeometry( width, height, depth, widthSegments, heightSegments, depthSegments );
 
-    } else if ( type == 'cylinder' ) {
+    } else if ( type == 'Cylinder' ) {
 
       radiusTop = radiusTop ? radiusTop : 20;
       radiusBottom = radiusBottom ? radiusBottom : 20;
@@ -252,7 +225,7 @@ Editor.prototype = {
 
       geometry = new THREE.CylinderGeometry( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded );
 
-    } else if ( type == 'sphere' ) {
+    } else if ( type == 'Sphere' ) {
 
       radius = radius ? radius : 75;
       widthSegments = widthSegments ? widthSegments : 32;
@@ -266,14 +239,14 @@ Editor.prototype = {
 
       geometry = new THREE.SphereGeometry( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength );
 
-    } else if ( type == 'icosahedron' ) {
+    } else if ( type == 'Icosahedron' ) {
 
       radius = radius ? radius : 75;
       detail = detail ? detail : 2;
 
       geometry = new THREE.IcosahedronGeometry ( radius, detail );
 
-    } else if ( type == 'torus' ) {
+    } else if ( type == 'Torus' ) {
 
       radius = radius ? radius : 100;
       tube = tube ? tube : 40;
@@ -283,7 +256,7 @@ Editor.prototype = {
 
       geometry = new THREE.TorusGeometry( radius, tube, radialSegments, tubularSegments, arc );
 
-    } else if ( type == 'torusknot' ) {
+    } else if ( type == 'TorusKnot' ) {
 
       radius = radius ? radius : 100;
       tube = tube ? tube : 40;
@@ -306,46 +279,39 @@ Editor.prototype = {
 
   createMaterial: function( type, parameters ) {
     
-    this.materialsCount ++;
-
-    type = type ? type.toLowerCase() : 'phong';
+    type = type ? type : 'MeshPhongMaterial';
 
     parameters = parameters ? parameters : {};
 
     var material;
-    var name = parameters.name ? parameters.name : null;
+    var name = parameters.name ? parameters.name : this.incrementName( type, 'material' );
 
-    if ( type == 'phong' ) {
+    if ( type == 'MeshPhongMaterial' ) {
 
       material = new THREE.MeshPhongMaterial( parameters );
-      material.name = name ? name : 'Phong Material ' + this.materialsCount;
 
-    } else if ( type == 'lambert' ) {
+    } else if ( type == 'MeshLambertMaterial' ) {
 
       material = new THREE.MeshLambertMaterial( parameters );
-      material.name = name ? name : 'Lambert Material ' + this.materialsCount;
 
-    } else if ( type == 'normal' ) {
+    } else if ( type == 'MeshNormalMaterial' ) {
 
       material = new THREE.MeshNormalMaterial( parameters );
-      material.name = name ? name : 'Normal Material ' + this.materialsCount;
 
-    } else if ( type == 'basic' ) {
+    } else if ( type == 'MeshBasicMaterial' ) {
 
       material = new THREE.MeshBasicMaterial( parameters );
-      material.name = name ? name : 'Basic Material ' + this.materialsCount;
 
     }
 
-    if ( material ) this.addMaterial( material );
+    material.name = name;
+    this.addMaterial( material );
     return material;
 
   },
 
   createTexture: function( image, parameters ) {
 
-    this.texturesCount ++;
-
     image = image ? image : '../examples/textures/ash_uvgrid01.jpg';
 
     parameters = parameters ? parameters : {};
@@ -353,7 +319,7 @@ Editor.prototype = {
     // TODO: implement parameters
 
     var texture = THREE.ImageUtils.loadTexture( image );
-    texture.name = parameters.name ? parameters.name : 'Texture ' + this.texturesCount;
+    texture.name = parameters.name ? parameters.name : this.incrementName( 'Texture', 'texture' );
 
     this.addTexture( texture );
     return texture;
@@ -424,7 +390,7 @@ Editor.prototype = {
 
       this.helpers[ object.id ] = new THREE.SpotLightHelper( object, 10 );
       this.sceneHelpers.add( this.helpers[ object.id ] );
-      this.helpers[ object.id ].lightSphere.id = object.id;
+      // this.helpers[ object.id ].lightSphere.id = object.id;
 
     } else if ( object instanceof THREE.HemisphereLight ) {
 
@@ -434,6 +400,8 @@ Editor.prototype = {
 
     }
 
+    signals.sceneChanged.dispatch( this.scene );
+
   },
 
   deleteHelper: function( object ) {
@@ -463,6 +431,7 @@ Editor.prototype = {
 
     this.materials[ material.id ] = material;
     signals.materialAdded.dispatch( material );
+    signals.sceneChanged.dispatch( this.scene );
 
   },
 
@@ -470,6 +439,7 @@ Editor.prototype = {
 
     this.textures[ texture.id ] = texture;
     signals.textureAdded.dispatch( texture );
+    signals.sceneChanged.dispatch( this.scene );
 
   },
 
@@ -935,8 +905,6 @@ Editor.prototype = {
 
     this.parent( group, parent );
 
-    console.log(group);
-
     this.parent( list, group );
 
   },
@@ -1029,25 +997,25 @@ Editor.prototype = {
     var name = geometry.name;
 
     if ( geometry instanceof THREE.PlaneGeometry )
-      geometry = this.createGeometry( 'plane', parameters );
+      geometry = this.createGeometry( 'Plane', parameters );
 
     if ( geometry instanceof THREE.CubeGeometry )
-      geometry = this.createGeometry( 'cube', parameters );
+      geometry = this.createGeometry( 'Cube', parameters );
 
     if ( geometry instanceof THREE.CylinderGeometry )
-      geometry = this.createGeometry( 'cylinder', parameters );
+      geometry = this.createGeometry( 'Cylinder', parameters );
 
     if ( geometry instanceof THREE.SphereGeometry )
-      geometry = this.createGeometry( 'sphere', parameters );
+      geometry = this.createGeometry( 'Sphere', parameters );
 
     if ( geometry instanceof THREE.IcosahedronGeometry )
-      geometry = this.createGeometry( 'icosahedron', parameters );
+      geometry = this.createGeometry( 'Icosahedron', parameters );
 
     if ( geometry instanceof THREE.TorusGeometry )
-      geometry = this.createGeometry( 'torus', parameters );
+      geometry = this.createGeometry( 'Torus', parameters );
 
     if ( geometry instanceof THREE.TorusKnotGeometry )
-      geometry = this.createGeometry( 'torusknot', parameters );
+      geometry = this.createGeometry( 'Torusknot', parameters );
 
     geometry.computeBoundingSphere();
     geometry.id = id;
@@ -1113,6 +1081,20 @@ Editor.prototype = {
     var regex = new RegExp(filter);
     return regex.test( name );
 
+  },
+
+  incrementName: function( name, type ) {
+
+    var list = this.listByName( name+'\\d+', type );
+    var lastIncrement = 0;
+
+    for ( var i in list ) {
+      var Increment = parseFloat( list[i].name.replace( name, '' ) );
+      if ( Increment > lastIncrement ) lastIncrement = Increment;
+    }
+    
+    return name + ( lastIncrement + 1 );
+
   }
 
 }

+ 20 - 20
editor/js/Menubar.Add.js

@@ -131,29 +131,29 @@ Menubar.Add = function ( signals ) {
 	} );
 	options.add( option );
 
-	// add spot light
+	// // add spot light
 
-	var option = new UI.Panel();
-	option.setClass( 'option' );
-	option.setTextContent( 'Spot light' );
-	option.onClick( function () {
+	// var option = new UI.Panel();
+	// option.setClass( 'option' );
+	// option.setTextContent( 'Spot light' );
+	// option.onClick( function () {
 
-		editor.select( editor.createObject( 'SpotLight' ) );
+	// 	editor.select( editor.createObject( 'SpotLight' ) );
 
-	} );
-	options.add( option );
+	// } );
+	// options.add( option );
 
-	// add directional light
+	// // add directional light
 
-	var option = new UI.Panel();
-	option.setClass( 'option' );
-	option.setTextContent( 'Directional light' );
-	option.onClick( function () {
+	// var option = new UI.Panel();
+	// option.setClass( 'option' );
+	// option.setTextContent( 'Directional light' );
+	// option.onClick( function () {
 
-		editor.select( editor.createObject( 'DirectionaLight' ) );
+	// 	editor.select( editor.createObject( 'DirectionalLight' ) );
 
-	} );
-	options.add( option );
+	// } );
+	// options.add( option );
 
 	// add hemisphere light
 
@@ -190,7 +190,7 @@ Menubar.Add = function ( signals ) {
 	option.setTextContent( 'Phong material' );
 	option.onClick( function () {
 
-		editor.select( editor.createMaterial( 'Phong' ) );
+		editor.select( editor.createMaterial( 'MeshPhongMaterial' ) );
 
 	} );
 	options.add( option );
@@ -200,7 +200,7 @@ Menubar.Add = function ( signals ) {
 	option.setTextContent( 'Lambert material' );
 	option.onClick( function () {
 
-		editor.select( editor.createMaterial( 'Lambert' ) );
+		editor.select( editor.createMaterial( 'MeshLambertMaterial' ) );
 
 	} );
 	options.add( option );
@@ -210,7 +210,7 @@ Menubar.Add = function ( signals ) {
 	option.setTextContent( 'Normal material' );
 	option.onClick( function () {
 
-		editor.select( editor.createMaterial( 'Normal' ) );
+		editor.select( editor.createMaterial( 'MeshNormalMaterial' ) );
 
 	} );
 	options.add( option );
@@ -220,7 +220,7 @@ Menubar.Add = function ( signals ) {
 	option.setTextContent( 'Basic material' );
 	option.onClick( function () {
 
-		editor.select( editor.createMaterial( 'Basic' ) );
+		editor.select( editor.createMaterial( 'MeshBasicMaterial' ) );
 
 	} );
 	options.add( option );

+ 307 - 149
editor/js/Sidebar.Attributes.js

@@ -1,98 +1,145 @@
 Sidebar.Attributes = function ( signals ) {
 
   var scope = this;
-  var object;
+  var model;
   var param = {};
 
-  var primaryParams = [
-    'name',
-    'parent',
-    'geometry',
-    'material',
-    'position',
-    'rotation',
-    'scale',
-    'width',
-    'height',
-    'depth',
-    'widthSegments',
-    'heightSegments',
-    'depthSegments',
-    'radialSegments',
-    'tubularSegments',
-    'radius',
-    'radiusTop',
-    'radiusBottom',
-    'phiStart',
-    'phiLength',
-    'thetaStart',
-    'thetaLength',
-    'tube',
-    'arc',
-    'detail',
-    'p',
-    'q',
-    'heightScale',
-    'openEnded',
-    'color',
-    'groundColor',
-    'ambient',
-    'emissive',
-    'specular',
-    'reflectivity',
-    'shininess',
-    'intensity',
-    'opacity',
-    'transparent',
-    'metal',
-    'wireframe',
-    'visible',
-    'userData'
-  ];
+  var primaryParams = [ 'name', 'parent', 'geometry', 'material', 'position', 'rotation', 'scale', 'width', 'height', 'depth',
+  'widthSegments', 'heightSegments', 'depthSegments', 'radialSegments', 'tubularSegments', 'radius', 'radiusTop', 'radiusBottom',
+  'phiStart', 'phiLength', 'thetaStart', 'thetaLength', 'tube', 'arc', 'detail', 'p', 'q', 'heightScale', 'openEnded',
+  'image', 'sourceFile', 'wrapS', 'wrapT', 'minFilter', 'magFilter', 'format', 'repeat', 'offset', 'flipY', 'type', 'color',
+  'groundColor', 'ambient', 'emissive', 'specular', 'reflectivity', 'shininess', 'intensity', 'opacity', 'transparent', 'metal',
+  'wireframe', 'wireframeLinewidth', 'linewidth', 'visible', 'fog', 'near', 'far', 'exponent', 'map', 'lightMap', 'bumpMap',
+  'normalMap', 'specularMap', 'envMap', 'normalScale', 'bumpScale', 'userData' ];
   
-  var secondaryParams = [
-    'castShadow',
-    'receiveShadow',
-    'useQuaternion',
-    'fog',
-    'depthTest',
-    'depthWrite',
-    'dynamic'
-  ];
-
-  var integerParams = [
-    'widthSegments',
-    'heightSegments',
-    'depthSegments',
-    'radialSegments',
-    'tubularSegments'
-  ];
+  var secondaryParams = [ 'quaternion', 'up', 'distance', 'castShadow', 'receiveShadow', 'useQuaternion', 'depthTest', 'depthWrite',
+  'dynamic', 'children', 'elements', 'vertices', 'normals', 'colors', 'faces', 'faceUvs', 'faceVertexUvs', 'boundingBox',
+  'boundingSphere', 'verticesNeedUpdate', 'elementsNeedUpdate', 'uvsNeedUpdate', 'normalsNeedUpdate', 'tangentsNeedUpdate',
+  'colorsNeedUpdate', 'lineDistancesNeedUpdate', 'buffersNeedUpdate', 'matrix', 'matrixWorld', 'blending', 'side', 'blendSrc',
+  'blendDst', 'blendEquation', 'generateMipmaps', 'premultiplyAlpha', 'needsUpdate', 'anisothropy' ];
+
+  var integerParams = [ 'widthSegments', 'heightSegments', 'depthSegments', 'radialSegments', 'tubularSegments' ];
+
+  var textureParams = [ 'map', 'lightMap', 'bumpMap', 'normalMap', 'specularMap', 'envMap' ];
+
+  var multiOptions = {
+    'blending': {
+      'NoBlending': THREE.NoBlending,
+      'NormalBlending': THREE.NormalBlending,
+      'AdditiveBlending': THREE.AdditiveBlending,
+      'SubtractiveBlending': THREE.SubtractiveBlending,
+      'MultiplyBlending': THREE.MultiplyBlending,
+      'CustomBlending': THREE.CustomBlending
+    }
+    ,
+    'side': {
+      'FrontSide': THREE.FrontSide,
+      'BackSide': THREE.BackSide,
+      'DoubleSide': THREE.DoubleSide
+    },
+    'blendSrc': {
+      'ZeroFactor': THREE.ZeroFactor,
+      'OneFactor': THREE.OneFactor,
+      'SrcAlphaFactor': THREE.SrcAlphaFactor,
+      'OneMinusSrcAlphaFactor': THREE.OneMinusSrcAlphaFactor,
+      'DstAlphaFactor': THREE.DstAlphaFactor,
+      'OneMinusDstAlphaFactor': THREE.OneMinusDstAlphaFactor,      
+      'DstColorFactor': THREE.DstColorFactor,
+      'OneMinusDstColorFactor': THREE.OneMinusDstColorFactor,
+      'SrcAlphaSaturateFactor': THREE.SrcAlphaSaturateFactor
+    },
+    'blendDst': {
+      'ZeroFactor': THREE.ZeroFactor,
+      'OneFactor': THREE.OneFactor,
+      'SrcColorFactor': THREE.SrcColorFactor,
+      'OneMinusSrcColorFactor': THREE.OneMinusSrcColorFactor,
+      'SrcAlphaFactor': THREE.SrcAlphaFactor,
+      'OneMinusSrcAlphaFactor': THREE.OneMinusSrcAlphaFactor,
+      'DstAlphaFactor': THREE.DstAlphaFactor,
+      'OneMinusDstAlphaFactor': THREE.OneMinusDstAlphaFactor
+    },
+    'blendEquation': {
+      'AddEquation': THREE.AddEquation,
+      'SubtractEquation': THREE.SubtractEquation,
+      'ReverseSubtractEquation': THREE.ReverseSubtractEquation
+    },
+    'wrapS': {
+      'RepeatWrapping': THREE.RepeatWrapping,
+      'ClampToEdgeWrapping': THREE.ClampToEdgeWrapping,
+      'MirroredRepeatWrapping': THREE.MirroredRepeatWrapping,
+    },
+    'wrapT': {
+      'RepeatWrapping': THREE.RepeatWrapping,
+      'ClampToEdgeWrapping': THREE.ClampToEdgeWrapping,
+      'MirroredRepeatWrapping': THREE.MirroredRepeatWrapping,
+    },
+    'magFilter': {
+      'NearestFilter': THREE.NearestFilter,
+      'NearestMipMapNearestFilter': THREE.NearestMipMapNearestFilter,
+      'NearestMipMapLinearFilter': THREE.NearestMipMapLinearFilter,
+      'LinearFilter': THREE.LinearFilter,
+      'LinearMipMapNearestFilter': THREE.LinearMipMapNearestFilter,
+      'LinearMipMapLinearFilter': THREE.LinearMipMapLinearFilter,
+    },
+    'minFilter': {
+      'NearestFilter': THREE.NearestFilter,
+      'NearestMipMapNearestFilter': THREE.NearestMipMapNearestFilter,
+      'NearestMipMapLinearFilter': THREE.NearestMipMapLinearFilter,
+      'LinearFilter': THREE.LinearFilter,
+      'LinearMipMapNearestFilter': THREE.LinearMipMapNearestFilter,
+      'LinearMipMapLinearFilter': THREE.LinearMipMapLinearFilter,
+    },
+    'type': {
+      'UnsignedByteType': THREE.UnsignedByteType,
+      'ByteType': THREE.ByteType,
+      'ShortType': THREE.ShortType,
+      'UnsignedShortType': THREE.UnsignedShortType,
+      'IntType': THREE.IntType,
+      'UnsignedIntType': THREE.UnsignedIntType,
+      'FloatType': THREE.FloatType
+    },
+    'format': {
+      'AlphaFormat': THREE.AlphaFormat,
+      'RGBFormat': THREE.RGBFormat,
+      'RGBAFormat': THREE.RGBAFormat,
+      'LuminanceFormat': THREE.LuminanceFormat,
+      'LuminanceAlphaFormat': THREE.LuminanceAlphaFormat,
+      'RGB_S3TC_DXT1_Format': THREE.RGB_S3TC_DXT1_Format,
+      'RGBA_S3TC_DXT1_Format': THREE.RGBA_S3TC_DXT1_Format,
+      'RGBA_S3TC_DXT3_Format': THREE.RGBA_S3TC_DXT3_Format,
+      'RGBA_S3TC_DXT5_Format': THREE.RGBA_S3TC_DXT5_Format,
+      'RGB_PVRTC_4BPPV1_Format': THREE.RGB_PVRTC_4BPPV1_Format,
+      'RGB_PVRTC_2BPPV1_Format': THREE.RGB_PVRTC_2BPPV1_Format,
+      'RGBA_PVRTC_4BPPV1_Format': THREE.RGBA_PVRTC_4BPPV1_Format,
+      'RGBA_PVRTC_2BPPV1_Format': THREE.RGBA_PVRTC_2BPPV1_Format,
+    }
+  }
 
   var container = new UI.Panel();
 
-  var group1 = new UI.Panel().setBorderTop( '1px solid #ccc' ).setPadding( '10px' );
-  var group2 = new UI.Panel().setBorderTop( '1px solid #ccc' ).setPadding( '10px' ).setOpacity( 0.5 );
-  var group3 = new UI.Panel().setBorderTop( '1px solid #ccc' ).setPadding( '10px' ).setOpacity( 0.25 );//.setDisplay( 'none' ); 
+  var group1 = new UI.Panel().setBorderTop( '1px solid #ccc' ).setPadding( '10px' ).setBackgroundColor( '#ddd' ); // Primary parameters
+  var group2 = new UI.Panel().setBorderTop( '1px solid #ccc' ).setPadding( '10px' ); // Secondary params 
+  var group3 = new UI.Panel().setBorderTop( '1px solid #ccc' ).setPadding( '10px' ).setBackgroundColor( '#ddd' ).setOpacity( 0.25 );//.setDisplay( 'none' ); // everything else
 
   container.add( group1, group2, group3 );
 
   signals.objectChanged.add( function ( changed ) {
       
-    if ( object === changed ) updateUI();
+    if ( model === changed ) updateUI();
 
   } );
 
   signals.selected.add( function ( selected ) {
       
     var selected = editor.listSelected();
-    object = ( selected.length ) ? selected[0] : null;
-
-    createUI();
-    updateUI();
+    var firstSelected = ( selected.length ) ? selected[0] : null;
+    createUI( firstSelected );
 
   } );
 
-  function createUI() {
+  function createUI( newModel ) {
+
+    model = newModel;
 
     param = {};
 
@@ -100,34 +147,106 @@ Sidebar.Attributes = function ( signals ) {
     while ( group2.dom.hasChildNodes() ) group2.dom.removeChild( group2.dom.lastChild );
     while ( group3.dom.hasChildNodes() ) group3.dom.removeChild( group3.dom.lastChild );
 
-    if ( object ) {
-
+    if ( model ) {
       for ( var i in primaryParams ) addElement( primaryParams[i], group1 );
-
       for ( var i in secondaryParams ) addElement( secondaryParams[i], group2 );
-
-      for ( var key in object ) addElement( key, group3 );
-
+      for ( var key in model ) addElement( key, group3 );
     }
 
+    updateUI();
 
   }
 
   function addElement( key, parent ) {
 
-    if ( object[ key ] !== undefined && param[ key ] === undefined ) {
+    if ( model[ key ] !== undefined && param[ key ] === undefined ) {
+
+      // Params from multiOptions
+
+      for ( var i in multiOptions ) {
+        if ( i == key ) {
+          param[ key ] = new UI.ParamSelect( key ).onChange( updateParam );
+          parent.add( param[ key ] );
+          return;
+        }
+      }
+
+      // Special params
+
+      if ( key === 'parent' ) {
+
+        param[ key ] = new UI.ParamSelect( key ).onChange( updateParam );
+        param[ key ].name.setColor( '#0080f0' ).onClick( function(){ createUI( editor.objects[ param[ key ].getValue() ] ) } );
+        parent.add( param[ key ] );
+        return;
+
+      }
+
+      if ( key === 'geometry' ) {
+
+        param[ key ] = new UI.ParamSelect( key ).onChange( updateParam );
+        param[ key ].name.setColor( '#0080f0' ).onClick( function(){  createUI( editor.geometries[ param[ key ].getValue() ] ) } );
+        parent.add( param[ key ] );
+        return;
+
+      }
+
+      if ( key == 'material' ) {
+
+        param[ key ] = new UI.ParamSelect( key ).onChange( updateParam );
+        param[ key ].name.setColor( '#0080f0' ).onClick( function(){  createUI( editor.materials[ param[ key ].getValue() ] ) } );
+        parent.add( param[ key ] );
+        return;
+
+      }
+
+      if ( key == 'userData' ) {
+
+        param[ key ] = new UI.ParamJson( key ).onChange( updateParam );
+        parent.add( param[ key ] );
+        return;
+
+      }
+
+      // Texture params
+
+      for ( var i in textureParams ) {
+
+        if ( key == textureParams[ i ] ) {
+
+          param[ key ] = new UI.ParamSelect( key ).onChange( updateParam );
+          param[ key ].name.setColor( '#0080f0' ).onClick( function(){
+
+            var value = param[ key ].getValue();
+            if ( value == 'new' ) {
+
+              var texture = editor.createTexture();
+              model[ key ] = texture;
+              createUI( texture );
+
+            } else createUI( editor.textures[ value ] )
 
-      if ( typeof object[ key ] === 'string' ) {
+          } );
+          parent.add( param[ key ] );
+          return;
+
+        }
+        
+      }
+
+      // Params by type
+
+      if ( typeof model[ key ] === 'string' ) {
 
         param[ key ] = new UI.ParamString( key ).onChange( updateParam );
         parent.add( param[ key ] );
 
-      } else if ( typeof object[ key ] === 'boolean' ) {
+      } else if ( typeof model[ key ] === 'boolean' ) {
 
         param[ key ] = new UI.ParamBool( key ).onChange( updateParam );
         parent.add( param[ key ] );
 
-      } else if ( typeof object[ key ] === 'number' ) {
+      } else if ( typeof model[ key ] === 'number' ) {
 
         if ( integerParams.indexOf( key ) != -1 )
           param[ key ] = new UI.ParamInteger( key ).onChange( updateParam );
@@ -137,39 +256,39 @@ Sidebar.Attributes = function ( signals ) {
         
         parent.add( param[ key ] );
 
-      } else if ( object[ key ] instanceof THREE.Vector3 ) {
+      } else if ( model[ key ] instanceof THREE.Vector2 ) {
 
-        var hasLock = ( key === 'scale' ) ? true : false;
-        param[ key ] = new UI.ParamVector3( key, hasLock ).onChange( updateParam );
+        param[ key ] = new UI.ParamVector2( key ).onChange( updateParam );
         parent.add( param[ key ] );
 
-      } else if ( object[ key ] instanceof THREE.Color ) {
+      } else if ( model[ key ] instanceof THREE.Vector3 ) {
 
-        param[ key ] = new UI.ParamColor( key ).onChange( updateParam );
+        param[ key ] = new UI.ParamVector3( key ).onChange( updateParam );
         parent.add( param[ key ] );
 
-      } else if ( key === 'parent' ) {
+      } else if ( model[ key ] instanceof THREE.Vector4 || model[ key ] instanceof THREE.Quaternion ) {
 
-        param[ key ] = new UI.ParamSelect( key ).onChange( updateParam );
-        param[ key ].name.setColor( '#0080f0' ).onClick( function(){  editor.select( editor.objects[ param[ key ].getValue() ] ) } );
+        param[ key ] = new UI.ParamVector4( key ).onChange( updateParam );
         parent.add( param[ key ] );
 
-      } else if ( key === 'geometry' ) {
+      } else if ( model[ key ] instanceof THREE.Color ) {
 
-        param[ key ] = new UI.ParamSelect( key ).onChange( updateParam );
-        param[ key ].name.setColor( '#0080f0' ).onClick( function(){  editor.select( editor.geometries[ param[ key ].getValue() ] ) } );
+        param[ key ] = new UI.ParamColor( key ).onChange( updateParam );
         parent.add( param[ key ] );
 
-      } else if ( key == 'material' ) {
+      } else if ( model[ key ] instanceof Array ) {
 
-        param[ key ] = new UI.ParamSelect( key ).onChange( updateParam );
-        param[ key ].name.setColor( '#0080f0' ).onClick( function(){  editor.select( editor.materials[ param[ key ].getValue() ] ) } );
-        parent.add( param[ key ] );
+        if ( model[ key ].length ) {
 
-      } else if ( key == 'userData' ) {
+          param[ key ] = new UI.Text( key ).setColor( '#0080f0' ).onClick( function(){  createUI( model[ key ] ) } );
+          parent.add( param[ key ], new UI.Break() );
+          
+        }
 
-        param[ key ] = new UI.ParamJson( key ).onChange( updateParam );
-        parent.add( param[ key ] );
+      } else if ( typeof model[ key ] !== 'function' ) {
+
+        param[ key ] = new UI.Text( key ).setColor( '#0080f0' ).onClick( function(){  createUI( model[ key ] ) } );
+        parent.add( param[ key ], new UI.Break() );
 
       }
 
@@ -179,46 +298,56 @@ Sidebar.Attributes = function ( signals ) {
 
   function updateUI() {
 
-    if ( object ) {
+    if ( model ) {
 
-      for ( var key in object ) {
+      for ( var key in model ) {
 
-        if ( typeof object[ key ] === 'string' ) param[ key ].setValue( object[ key ] );
+        // Params from multiOptions
 
-        else if ( typeof object[ key ] === 'boolean' ) param[ key ].setValue( object[ key ] );
+        for ( var i in multiOptions ) {
+          if ( i == key ) {
+            for ( var j in multiOptions[ i ] ) {
 
-        else if ( typeof object[ key ] === 'number' ) param[ key ].setValue( object[ key ] );
+              var options = {};
 
-        else if ( object[ key ] instanceof THREE.Vector3 ) param[ key ].setValue( object[ key ] );
+              for ( var j in multiOptions[ i ] ) options[ multiOptions[ i ][ j ] ] = j;
+              
+              param[ key ].setOptions( options );
+              param[ key ].setValue( model[ key ] );
+              break;
 
-        else if ( object[ key ] instanceof THREE.Color ) param[ key ].setValue( object[ key ] );
+            }
+          }
+        }
 
-        else if ( object[ key ] && key === 'parent' ) {
+        // Special params
+
+        if ( key === 'parent' ) {
 
           var options = {};
-          for ( var id in editor.objects ) if ( object.id != id ) options[ id ] = editor.objects[ id ].name;
+          for ( var id in editor.objects ) if ( model.id != id ) options[ id ] = editor.objects[ id ].name;
           param[ key ].setOptions( options );
-          if ( object.parent !== undefined ) param[ key ].setValue( object.parent.id );
+          if ( model[ key ] !== undefined ) param[ key ].setValue( model[ key ].id );
 
-        } else if ( object[ key ] && key === 'geometry' ) {
+        } else if ( key === 'geometry' ) {
 
           var options = {};
-          for ( var id in editor.geometries ) if ( object.id != id ) options[ id ] = editor.geometries[ id ].name;
+          for ( var id in editor.geometries ) options[ id ] = editor.geometries[ id ].name;
           param[ key ].setOptions( options );
-          if ( object.geometry !== undefined ) param[ key ].setValue( object.geometry.id );
+          if ( model[ key ] !== undefined ) param[ key ].setValue( model[ key ].id );
 
-        } else if ( object[ key ] && key === 'material' ) {
+        } else if ( key === 'material' ) {
 
           var options = {};
-          for ( var id in editor.materials ) if ( object.id != id ) options[ id ] = editor.materials[ id ].name;
+          for ( var id in editor.materials ) options[ id ] = editor.materials[ id ].name;
           param[ key ].setOptions( options );
-          if ( object.material !== undefined ) param[ key ].setValue( object.material.id );
+          if ( model[ key ] !== undefined ) param[ key ].setValue( model[ key ].id );
 
         } else if ( key == 'userData' ) {
 
           try {
 
-            param[ key ].setValue( JSON.stringify( object.userData, null, '  ' ) );
+            param[ key ].setValue( JSON.stringify( model.userData, null, '  ' ) );
 
           } catch ( error ) {
 
@@ -226,70 +355,99 @@ Sidebar.Attributes = function ( signals ) {
 
           }
 
-        }
+        // Texture params
 
-      }
+        } else if ( textureParams.indexOf( key ) != -1 ) {
 
-    }
+          var options = {};
+          options[ 'new' ] = 'New texture';
+          for ( var id in editor.textures ) options[ id ] = editor.textures[ id ].name;
+          param[ key ].setOptions( options );
 
-  }
+          param[ key ].setValue( 'new' );
+          if ( model[ key ] ) param[ key ].setValue( model[ key ].id );
 
-  function updateParam( event ) {
+        } 
 
-    var key = event.srcElement.name;
+        // Params by type
 
-    if ( typeof object[ key ] === 'string' ) object[ key ] = param[ key ].getValue();
+        else if ( typeof model[ key ] === 'string' ) param[ key ].setValue( model[ key ] );
 
-    else if ( typeof object[ key ] === 'boolean' ) object[ key ] = param[ key ].getValue();
+        else if ( typeof model[ key ] === 'boolean' ) param[ key ].setValue( model[ key ] );
 
-    else if ( typeof object[ key ] === 'number' ) object[ key ] = param[ key ].getValue();
+        else if ( typeof model[ key ] === 'number' ) param[ key ].setValue( model[ key ] );
 
-    else if ( object[ key ] instanceof THREE.Color ) object[ key ].setHex( param[ key ].getValue() );
+        else if ( model[ key ] instanceof THREE.Vector3 ) param[ key ].setValue( model[ key ] );
 
-    else if ( object[ key ] instanceof THREE.Vector3 ) object[ key ].copy( param[ key ].getValue() );
+        else if ( model[ key ] instanceof THREE.Color ) param[ key ].setValue( model[ key ] );
 
-    else if ( key === 'parent' ) {
+      }
 
-      if ( param[ key ].getValue() != object.id )
-        editor.parent( object, editor.objects[ param[ key ].getValue() ] );
+    }
 
-    } else if ( key === 'geometry' ) {
+  }
 
-      if ( param[ key ].getValue() != object.geometry.id )
-        object.geometry = editor.geometries[ param[ key ].getValue() ];
+  function updateParam( event ) {
 
-    } else if ( key === 'material' ) {
+    var key = event.srcElement.name;
+    var value = ( param[ key ].getValue ) ? param[ key ].getValue() : null;
 
-      if ( param[ key ].getValue() != object.material.id )
-        object.material = editor.materials[ param[ key ].getValue() ];
+    // Special params
 
-    } else if ( key === 'userData' ) {
+    if ( key === 'parent' ) editor.parent( object, editor.objects[ value ] );
 
-      try {
+    else if ( key === 'geometry' ) model[ key ] = editor.geometries[ value ];
 
-        object.userData = JSON.parse( param[ key ].getValue() );
+    else if ( key === 'material' ) model[ key ] = editor.materials[ value ];
 
+    else if ( key === 'userData' ) {
+    
+      try {
+         model[ key ] = JSON.parse( value );
       } catch ( error ) {
-
         console.log( error );
-
       }
+    
+    } else if ( textureParams.indexOf( key ) != -1 ) {
+      
+      if ( value == 'new' ) {
+
+        var texture = editor.createTexture();
+        model[ key ] = texture;
+        createUI( texture );
+
+      } else model[ key ] = editor.textures[ value ];
 
     }
 
-    if ( object instanceof THREE.Object3D ) {
+    // Params by type
+
+    else if ( typeof model[ key ] === 'string' ) model[ key ] = value;
+
+    else if ( typeof model[ key ] === 'boolean' ) model[ key ] = value;
+
+    else if ( typeof model[ key ] === 'number' ) model[ key ] = parseFloat( value );
+
+    else if ( model[ key ] instanceof THREE.Color ) model[ key ].setHex( value );
+
+    else if ( model[ key ] instanceof THREE.Vector3 ) model[ key ].copy( value );
+
+    // Post actions
+
+    if ( model instanceof THREE.Object3D ) {
 
-      signals.objectChanged.dispatch( object );
+      signals.objectChanged.dispatch( model );
 
-    } else if ( object instanceof THREE.Geometry ) {
+    } else if ( model instanceof THREE.Geometry ) {
 
       var geoParams = {};
-      for ( var i in param ) geoParams[ i ] = param[ i ].getValue();
-      editor.updateGeometry( object, geoParams );
+      for ( var i in param )
+        if ( param[ i ].getValue ) geoParams[ i ] = param[ i ].getValue();
+      editor.updateGeometry( model, geoParams );
 
-    } else if ( object instanceof THREE.Material ) {
+    } else if ( model instanceof THREE.Material ) {
 
-      signals.materialChanged.dispatch( object );
+      signals.materialChanged.dispatch( model );
 
     }
 

+ 0 - 46
editor/js/Sidebar.Outliner.Scene.js

@@ -24,42 +24,6 @@ Sidebar.Outliner.Scene = function ( signals ) {
 	fogTypeRow.add( fogType );
 	container.add( fogTypeRow );
 
-	var fogColorRow = new UI.Panel();
-	fogColorRow.setDisplay( 'none' );
-	var fogColor = new UI.Color().setValue( '#aaaaaa' ).onChange(
-		function() { editor.setFog( { color: fogColor.getHexValue() } ) }
-	);
-	fogColorRow.add( new UI.Text( 'Fog color' ).setWidth( '90px' ).setColor( '#666' ) );
-	fogColorRow.add( fogColor );
-	container.add( fogColorRow );
-
-	var fogNearRow = new UI.Panel();
-	fogNearRow.setDisplay( 'none' );
-	var fogNear = new UI.Number( 1 ).setWidth( '60px' ).setRange( 0, Infinity ).onChange(
-		function() { editor.setFog( { near: fogNear.getValue() } ) }
-	);
-	fogNearRow.add( new UI.Text( 'Fog near' ).setWidth( '90px' ).setColor( '#666' ) );
-	fogNearRow.add( fogNear );
-	container.add( fogNearRow );
-
-	var fogFarRow = new UI.Panel();
-	fogFarRow.setDisplay( 'none' );
-	var fogFar = new UI.Number( 5000 ).setWidth( '60px' ).setRange( 0, Infinity ).onChange(
-		function() { editor.setFog( { far: fogFar.getValue() } ) }
-	);
-	fogFarRow.add( new UI.Text( 'Fog far' ).setWidth( '90px' ).setColor( '#666' ) );
-	fogFarRow.add( fogFar );
-	container.add( fogFarRow );
-
-	var fogDensityRow = new UI.Panel();
-	fogDensityRow.setDisplay( 'none' );
-	var fogDensity = new UI.Number( 0.00025 ).setWidth( '60px' ).setRange( 0, 0.1 ).setPrecision( 5 ).onChange(
-		function() { editor.setFog( { density: fogDensity.getValue() } ) }
-	);
-	fogDensityRow.add( new UI.Text( 'Fog density' ).setWidth( '90px' ).setColor( '#666' ) );
-	fogDensityRow.add( fogDensity );
-	container.add( fogDensityRow );
-
 	//
 
 	var scene = null;
@@ -144,18 +108,13 @@ Sidebar.Outliner.Scene = function ( signals ) {
 
 		if ( scene.fog ) {
 
-			fogColor.setHexValue( scene.fog.color.getHex() );
-
 			if ( scene.fog instanceof THREE.Fog ) {
 
 				fogType.setValue( "Fog" );
-				fogNear.setValue( scene.fog.near );
-				fogFar.setValue( scene.fog.far );
 
 			} else if ( scene.fog instanceof THREE.FogExp2 ) {
 
 				fogType.setValue( "FogExp2" );
-				fogDensity.setValue( scene.fog.density );
 
 			}
 
@@ -167,11 +126,6 @@ Sidebar.Outliner.Scene = function ( signals ) {
 
 		var type = fogType.getValue();
 
-		fogColorRow.setDisplay( type === 'None' ? 'none' : '' );
-		fogNearRow.setDisplay( type === 'Fog' ? '' : 'none' );
-		fogFarRow.setDisplay( type === 'Fog' ? '' : 'none' );
-		fogDensityRow.setDisplay( type === 'FogExp2' ? '' : 'none' );
-
 	}
 
 	// events

+ 3 - 1
editor/js/libs/ui.js

@@ -43,7 +43,7 @@ UI.Element.prototype = {
 // properties
 
 var properties = [ 'position', 'left', 'top', 'right', 'bottom', 'width', 'height', 'border', 'borderLeft',
-'borderTop', 'borderRight', 'borderBottom', 'borderColor', 'display', 'overflow', 'margin', 'marginLeft', 'marginTop', 'marginRight', 'marginBottom', 'padding', 'paddingLeft', 'paddingTop', 'paddingRight', 'paddingBottom', 'color',
+'borderTop', 'borderRight', 'borderBottom', 'borderColor', 'boxSizing', 'display', 'overflow', 'margin', 'marginLeft', 'marginTop', 'marginRight', 'marginBottom', 'padding', 'paddingLeft', 'paddingTop', 'paddingRight', 'paddingBottom', 'color',
 'backgroundColor', 'opacity', 'fontSize', 'fontWeight', 'textTransform', 'cursor' ];
 
 properties.forEach( function ( property ) {
@@ -199,6 +199,7 @@ UI.Text = function ( text ) {
 	dom.style.cursor = 'default';
 	dom.style.display = 'inline-block';
 	dom.style.verticalAlign = 'top';
+	dom.style.overflow = 'hidden';
 
 	this.dom = dom;
 	this.setValue( text );
@@ -233,6 +234,7 @@ UI.Input = function () {
 	var dom = document.createElement( 'input' );
 	dom.className = 'Input';
 	dom.style.padding = '2px';
+	// dom.style.boxSizing = 'border-box';
 	dom.style.marginTop = '-2px';
 	dom.style.marginLeft = '-2px';
 	dom.style.border = '1px solid #ccc';

+ 145 - 50
editor/js/libs/ui.three.js

@@ -22,9 +22,9 @@ UI.ParamString = function ( name ) {
 UI.ParamString.prototype = Object.create( UI.Panel.prototype );
 
 
-UI.ParamString.prototype.setValue = function ( value ) {
+UI.ParamString.prototype.setValue = function ( model ) {
 
-	this.string.setValue( value );
+	this.string.setValue( model );
 
 };
 
@@ -58,9 +58,9 @@ UI.ParamInteger = function ( name ) {
 
 UI.ParamInteger.prototype = Object.create( UI.Panel.prototype );
 
-UI.ParamInteger.prototype.setValue = function ( value ) {
+UI.ParamInteger.prototype.setValue = function ( model ) {
 
-	this.integer.setValue( value );
+	this.integer.setValue( model );
 
 };
 
@@ -93,9 +93,9 @@ UI.ParamFloat = function ( name ) {
 
 UI.ParamFloat.prototype = Object.create( UI.Panel.prototype );
 
-UI.ParamFloat.prototype.setValue = function ( value ) {
+UI.ParamFloat.prototype.setValue = function ( model ) {
 
-	this.float.setValue( value );
+	this.float.setValue( model );
 
 };
 
@@ -115,7 +115,7 @@ UI.ParamBool = function ( name ) {
 
 	var row = new UI.Panel();
 
-	this.name = new UI.Text( name ).setWidth( '90px' ).setColor( '#666' ).setPosition( 'relative' ).setLeft( '25px' );
+	this.name = new UI.Text( name ).setWidth( 'auto' ).setColor( '#666' ).setPosition( 'relative' ).setLeft( '25px' );
 	this.bool = new UI.Checkbox().setPosition( 'absolute' ).setLeft( '10px' );
 	this.bool.dom.name = name;
 
@@ -128,9 +128,9 @@ UI.ParamBool = function ( name ) {
 
 UI.ParamBool.prototype = Object.create( UI.Panel.prototype );
 
-UI.ParamBool.prototype.setValue = function ( value ) {
+UI.ParamBool.prototype.setValue = function ( model ) {
 
-	this.bool.setValue( value );
+	this.bool.setValue( model );
 
 };
 
@@ -141,69 +141,167 @@ UI.ParamBool.prototype.getValue = function () {
 
 };
 
-// Vector3
+// Vector2
 
-UI.ParamVector3 = function ( name, scaleLock ) {
+UI.ParamVector2 = function ( name ) {
 
   UI.Panel.call( this );
 
-  scaleLock = scaleLock ? scaleLock : false;
-
 	var scope = this;
 
 	var row = new UI.Panel();
 
 	this.name = new UI.Text( name ).setWidth( '90px' ).setColor( '#666' );
 
-	this.x = new UI.Number().setWidth( '50px' ).onChange( setYZ );
-	this.y = new UI.Number().setWidth( '50px' ).onChange( setXZ );
-	this.z = new UI.Number().setWidth( '50px' ).onChange( setXY );
+	this.x = new UI.Number().setWidth( '35px' ).onChange( function( event ) { scaleProportionately( event, [ scope.y ] ) } );
+	this.y = new UI.Number().setWidth( '35px' ).onChange( function( event ) { scaleProportionately( event, [ scope.x ] ) } );
+
 	this.x.dom.name = name;
 	this.y.dom.name = name;
-	this.z.dom.name = name;
 	
-	row.add( this.name, this.x, this.y, this.z );
-
-	if ( scaleLock ) {
+	row.add( this.name, this.x, this.y );
 	
-		this.scaleLock = new UI.Checkbox().setPosition( 'absolute' ).setLeft( '75px' );
-		row.add( this.scaleLock );
-
-	}
+	this.scaleLock = new UI.Checkbox().setPosition( 'absolute' ).setRight( '10px' );
+	row.add( this.scaleLock );
 
 	this.add( row );
 
-	function setYZ( event ) {
+	function scaleProportionately( event, targets ) {
 
 		if ( scope.scaleLock && scope.scaleLock.getValue() && event.srcElement.oldValue ) {
 
 			var scale = event.srcElement.value / event.srcElement.oldValue;
-			scope.y.setValue( parseFloat(scope.y.getValue()) * scale );
-			scope.z.setValue( parseFloat(scope.z.getValue()) * scale );
+			for ( var i in targets ) {
+
+				targets[ i ].setValue( parseFloat(targets[ i ].getValue()) * scale );
+			
+			}
 
 		}
 
 	}
 
-	function setXZ( event ) {
+	return this;
+
+};
+
+UI.ParamVector2.prototype = Object.create( UI.Panel.prototype );
+
+UI.ParamVector2.prototype.setValue = function ( model ) {
+
+	this.x.setValue( model.x );
+	this.y.setValue( model.y );
+
+};
+
+UI.ParamVector2.prototype.getValue = function () {
+
+	return new THREE.Vector2( this.x.getValue(), this.y.getValue() );
+
+};
+
+// Vector3
+
+UI.ParamVector3 = function ( name ) {
+
+  UI.Panel.call( this );
+
+	var scope = this;
+
+	var row = new UI.Panel();
+
+	this.name = new UI.Text( name ).setWidth( '90px' ).setColor( '#666' );
+
+	this.x = new UI.Number().setWidth( '35px' ).onChange( function( event ) { scaleProportionately( event, [ scope.y, scope.z ] ) } );
+	this.y = new UI.Number().setWidth( '35px' ).onChange( function( event ) { scaleProportionately( event, [ scope.x, scope.z ] ) } );
+	this.z = new UI.Number().setWidth( '35px' ).onChange( function( event ) { scaleProportionately( event, [ scope.x, scope.y ] ) } );
+
+	this.x.dom.name = name;
+	this.y.dom.name = name;
+	this.z.dom.name = name;
+	
+	row.add( this.name, this.x, this.y, this.z );
+	
+	this.scaleLock = new UI.Checkbox().setPosition( 'absolute' ).setRight( '10px' );
+	row.add( this.scaleLock );
+
+
+	this.add( row );
+
+	function scaleProportionately( event, targets ) {
 
 		if ( scope.scaleLock && scope.scaleLock.getValue() && event.srcElement.oldValue ) {
 
 			var scale = event.srcElement.value / event.srcElement.oldValue;
-			scope.x.setValue( parseFloat(scope.x.getValue()) * scale );
-			scope.z.setValue( parseFloat(scope.z.getValue()) * scale );
+			for ( var i in targets ) {
+
+				targets[ i ].setValue( parseFloat(targets[ i ].getValue()) * scale );
+			
+			}
 
 		}
 
 	}
 
-	function setXY( event ) {
+	return this;
+
+};
+
+UI.ParamVector3.prototype = Object.create( UI.Panel.prototype );
+
+UI.ParamVector3.prototype.setValue = function ( model ) {
+
+	this.x.setValue( model.x );
+	this.y.setValue( model.y );
+	this.z.setValue( model.z );
+
+};
+
+UI.ParamVector3.prototype.getValue = function () {
+
+	return new THREE.Vector3( this.x.getValue(), this.y.getValue(), this.z.getValue() );
+
+};
+
+// Vector4
+
+UI.ParamVector4 = function ( name ) {
+
+  UI.Panel.call( this );
+
+	var scope = this;
+
+	var row = new UI.Panel();
+
+	this.name = new UI.Text( name ).setWidth( '90px' ).setColor( '#666' );
+
+	this.x = new UI.Number().setWidth( '35px' ).onChange( function( event ) { scaleProportionately( event, [ scope.y, scope.z, scope.w ] ) } );
+	this.y = new UI.Number().setWidth( '35px' ).onChange( function( event ) { scaleProportionately( event, [ scope.x, scope.z, scope.w ] ) } );
+	this.z = new UI.Number().setWidth( '35px' ).onChange( function( event ) { scaleProportionately( event, [ scope.x, scope.y, scope.w ] ) } );
+	this.w = new UI.Number().setWidth( '35px' ).onChange( function( event ) { scaleProportionately( event, [ scope.x, scope.y, scope.z ] ) } );
+
+	this.x.dom.name = name;
+	this.y.dom.name = name;
+	this.z.dom.name = name;
+	this.w.dom.name = name;
+	
+	row.add( this.name, this.x, this.y, this.z, this.w );
+
+	this.scaleLock = new UI.Checkbox().setPosition( 'absolute' ).setRight( '10px' );
+	row.add( this.scaleLock );
+
+	this.add( row );
+
+	function scaleProportionately( event, targets ) {
 
 		if ( scope.scaleLock && scope.scaleLock.getValue() && event.srcElement.oldValue ) {
 
 			var scale = event.srcElement.value / event.srcElement.oldValue;
-			scope.x.setValue( parseFloat(scope.x.getValue()) * scale );
-			scope.y.setValue( parseFloat(scope.y.getValue()) * scale );
+			for ( var i in targets ) {
+
+				targets[ i ].setValue( parseFloat(targets[ i ].getValue()) * scale );
+			
+			}
 
 		}
 
@@ -213,20 +311,20 @@ UI.ParamVector3 = function ( name, scaleLock ) {
 
 };
 
-UI.ParamVector3.prototype = Object.create( UI.Panel.prototype );
+UI.ParamVector4.prototype = Object.create( UI.Panel.prototype );
 
-UI.ParamVector3.prototype.setValue = function ( value ) {
+UI.ParamVector4.prototype.setValue = function ( model ) {
 
-	this.x.setValue( value.x );
-	this.y.setValue( value.y );
-	this.z.setValue( value.z );
+	this.x.setValue( model.x );
+	this.y.setValue( model.y );
+	this.z.setValue( model.z );
+	this.w.setValue( model.w );
 
 };
 
+UI.ParamVector4.prototype.getValue = function () {
 
-UI.ParamVector3.prototype.getValue = function () {
-
-	return new THREE.Vector3( this.x.getValue(), this.y.getValue(), this.z.getValue() );
+	return new THREE.Vector4( this.x.getValue(), this.y.getValue(), this.z.getValue(), this.w.getValue() );
 
 };
 
@@ -259,7 +357,6 @@ UI.ParamColor.prototype.setValue = function ( color ) {
 
 };
 
-
 UI.ParamColor.prototype.getValue = function () {
 
 	return this.color.getHexValue();
@@ -291,13 +388,12 @@ UI.ParamSelect = function ( name ) {
 
 UI.ParamSelect.prototype = Object.create( UI.Panel.prototype );
 
-UI.ParamSelect.prototype.setValue = function ( value ) {
+UI.ParamSelect.prototype.setValue = function ( model ) {
 
-	this.select.setValue( value );
+	this.select.setValue( model );
 
 };
 
-
 UI.ParamSelect.prototype.getValue = function ( value ) {
 
 	return this.select.getValue( value );
@@ -394,7 +490,7 @@ UI.Texture.prototype.getValue = function () {
 
 };
 
-UI.Texture.prototype.setValue = function ( value ) {
+UI.Texture.prototype.setValue = function ( model ) {
 
 	this.texture = value;
 
@@ -463,7 +559,7 @@ UI.CubeTexture.prototype.getValue = function () {
 
 };
 
-UI.CubeTexture.prototype.setValue = function ( value ) {
+UI.CubeTexture.prototype.setValue = function ( model ) {
 
 	this.texture = value;
 
@@ -510,13 +606,12 @@ UI.ParamJson = function ( name ) {
 
 UI.ParamJson.prototype = Object.create( UI.Panel.prototype );
 
-UI.ParamJson.prototype.setValue = function ( value ) {
+UI.ParamJson.prototype.setValue = function ( model ) {
 
-	this.json.setValue( value );
+	this.json.setValue( model );
 
 };
 
-
 UI.ParamJson.prototype.getValue = function () {
 
 	return this.json.getValue();