Browse Source

added undo/redo for material values, maps, booleans

IMPORTENT: Serialization of Maps does NOT work yet!
Daniel 10 years ago
parent
commit
c1cbfc8ade

+ 4 - 0
editor/index.html

@@ -135,7 +135,11 @@
 		<script src="js/CmdAddScript.js"></script>
 		<script src="js/CmdRemoveScript.js"></script>
 		<script src="js/CmdSetScriptValue.js"></script>
+		<script src="js/CmdSetMaterial.js"></script>
 		<script src="js/CmdSetMaterialValue.js"></script>
+		<script src="js/CmdSetMaterialColor.js"></script>
+		<script src="js/CmdSetMaterialMap.js"></script>
+		<script src="js/CmdToggleBooleanMaterial.js"></script>
 		<script src="js/CmdSetScene.js"></script>
 
 		<script>

+ 24 - 147
editor/js/CmdSetMaterial.js

@@ -7,16 +7,22 @@ CmdSetMaterial = function ( object, newMaterial ) {
 	Cmd.call( this );
 
 	this.type = 'CmdSetMaterial';
-	this.updatable = true;
 
 	this.object = object;
 	this.objectUuid = object !== undefined ? object.uuid : undefined;
 
-	this.newMaterial = newMaterial;	// only needed for update(cmd)
+	this.oldMaterial = object !== undefined ? object.material : undefined;
+	this.newMaterial = newMaterial;
 
-	this.oldMaterialJSON = object !== undefined ? object.material.toJSON() : undefined;
-	this.newMaterialJSON = newMaterial !== undefined ? newMaterial.toJSON() : undefined;
+	meta = {
+		geometries: {},
+		materials: {},
+		textures: {},
+		images: {}
+	};
 
+	this.oldMaterialJSON = object !== undefined ? object.material.toJSON( meta ) : undefined;
+	this.newMaterialJSON = newMaterial !== undefined ? newMaterial.toJSON( meta ) : undefined;
 
 };
 
@@ -24,29 +30,15 @@ CmdSetMaterial.prototype = {
 
 	execute: function () {
 
-		this.object.geometry.dispose();
-		this.object.geometry = this.parseGeometry( this.newMaterialJSON );
-		this.object.geometry.computeBoundingSphere();
-
-		this.editor.signals.geometryChanged.dispatch( this.object );
-		this.editor.signals.sceneGraphChanged.dispatch();
+		this.object.material = this.newMaterial;
+		this.editor.signals.materialChanged.dispatch( this.newMaterial );
 
 	},
 
 	undo: function () {
 
-		this.object.geometry.dispose();
-		this.object.geometry = this.parseGeometry( this.oldMaterialJSON );
-		this.object.geometry.computeBoundingSphere();
-
-		this.editor.signals.geometryChanged.dispatch( this.object );
-		this.editor.signals.sceneGraphChanged.dispatch();
-
-	},
-
-	update: function ( cmd ) {
-
-		this.newMaterialJSON = cmd.newGeometry.toJSON();
+		this.object.material = this.oldMaterial;
+		this.editor.signals.materialChanged.dispatch( this.oldMaterial );
 
 	},
 
@@ -55,8 +47,8 @@ CmdSetMaterial.prototype = {
 		var output = Cmd.prototype.toJSON.call( this );
 
 		output.objectUuid = this.objectUuid;
-		output.oldMaterialJSON = this.oldMaterialJSON;
-		output.newMaterialJSON = this.newMaterialJSON;
+		output.oldMaterial = this.oldMaterialJSON;
+		output.newMaterial = this.newMaterialJSON;
 
 		return output;
 
@@ -69,133 +61,18 @@ CmdSetMaterial.prototype = {
 		this.object = this.editor.objectByUuid( json.objectUuid );
 		this.objectUuid = json.objectUuid;
 
-		this.oldMaterialJSON = json.oldMaterialJSON;
-		this.newMaterialJSON = json.newMaterialJSON;
-
-	},
-
-	parseGeometry: function ( data ) {
-
-		var geometryLoader = new THREE.JSONLoader();
-		var bufferGeometryLoader = new THREE.BufferGeometryLoader();
-
-		var geometry;
-
-		switch ( data.type ) {
-
-			case 'PlaneGeometry':
-			case 'PlaneBufferGeometry':
-
-				geometry = new THREE[ data.type ](
-					data.width,
-					data.height,
-					data.widthSegments,
-					data.heightSegments
-				);
-
-				break;
-
-			case 'BoxGeometry':
-			case 'CubeGeometry': // backwards compatible
-
-				geometry = new THREE.BoxGeometry(
-					data.width,
-					data.height,
-					data.depth,
-					data.widthSegments,
-					data.heightSegments,
-					data.depthSegments
-				);
-
-				break;
-
-			case 'CircleGeometry':
-
-				geometry = new THREE.CircleGeometry(
-					data.radius,
-					data.segments
-				);
+		this.oldMaterial = this.parseMaterial( json.oldMaterial );
+		this.newMaterial = this.parseMaterial( json.newMaterial );
 
-				break;
+		this.oldMaterialJSON = json.oldMaterial;
+		this.newMaterialJSON = json.newMaterial;
 
-			case 'CylinderGeometry':
-
-				geometry = new THREE.CylinderGeometry(
-					data.radiusTop,
-					data.radiusBottom,
-					data.height,
-					data.radialSegments,
-					data.heightSegments,
-					data.openEnded
-				);
-
-				break;
-
-			case 'SphereGeometry':
-
-				geometry = new THREE.SphereGeometry(
-					data.radius,
-					data.widthSegments,
-					data.heightSegments,
-					data.phiStart,
-					data.phiLength,
-					data.thetaStart,
-					data.thetaLength
-				);
-
-				break;
-
-			case 'IcosahedronGeometry':
-
-				geometry = new THREE.IcosahedronGeometry(
-					data.radius,
-					data.detail
-				);
-
-				break;
-
-			case 'TorusGeometry':
-
-				geometry = new THREE.TorusGeometry(
-					data.radius,
-					data.tube,
-					data.radialSegments,
-					data.tubularSegments,
-					data.arc
-				);
-
-				break;
-
-			case 'TorusKnotGeometry':
-
-				geometry = new THREE.TorusKnotGeometry(
-					data.radius,
-					data.tube,
-					data.radialSegments,
-					data.tubularSegments,
-					data.p,
-					data.q,
-					data.heightScale
-				);
-
-				break;
-
-			case 'BufferGeometry':
-
-				geometry = bufferGeometryLoader.parse( data );
-
-				break;
-
-			case 'Geometry':
-
-				geometry = geometryLoader.parse( data.data ).geometry;
+	},
 
-				break;
+	parseMaterial: function ( data ) {
 
-		}
-		geometry.uuid = data.uuid;
-		geometry.name = data.name !== undefined ? data.name : '';
-		return geometry;
+		var loader = new THREE.ObjectLoader();
+		return loader.parseMaterials( [ data ] )[ data.uuid ];
 
 	}
 

+ 67 - 0
editor/js/CmdSetMaterialColor.js

@@ -0,0 +1,67 @@
+/**
+ * Created by Daniel on 21.07.15.
+ */
+
+CmdSetMaterialColor = function ( object, attributeName, newValue ) {
+
+	Cmd.call( this );
+
+	this.type = 'CmdSetMaterialColor';
+	this.updatable = true;
+
+	this.object = object;
+	this.objectUuid = object !== undefined ? object.uuid : undefined;
+	this.attributeName = attributeName;
+	this.oldValue = object !== undefined ? this.object.material[ this.attributeName ].getHex() : undefined;
+	this.newValue = newValue;
+
+};
+
+CmdSetMaterialColor.prototype = {
+
+	execute: function () {
+
+		this.object.material[ this.attributeName ].setHex( this.newValue );
+		this.editor.signals.materialChanged.dispatch( this.object.material );
+
+	},
+
+	undo: function () {
+
+		this.object.material[ this.attributeName ].setHex( this.oldValue );
+		this.editor.signals.materialChanged.dispatch( this.object.material );
+
+	},
+
+	update: function ( cmd ) {
+
+		this.newValue = cmd.newValue;
+
+	},
+
+	toJSON: function () {
+
+		var output = Cmd.prototype.toJSON.call( this );
+
+		output.objectUuid = this.objectUuid;
+		output.attributeName = this.attributeName;
+		output.oldValue = this.oldValue;
+		output.newValue = this.newValue;
+
+		return output;
+
+	},
+
+	fromJSON: function ( json ) {
+
+		Cmd.prototype.fromJSON.call( this, json );
+
+		this.object = this.editor.objectByUuid( json.objectUuid );
+		this.objectUuid = json.objectUuid;
+		this.attributeName = json.attributeName;
+		this.oldValue = json.oldValue;
+		this.newValue = json.newValue;
+
+	}
+
+};

+ 95 - 0
editor/js/CmdSetMaterialMap.js

@@ -0,0 +1,95 @@
+/**
+ * Created by Daniel on 21.07.15.
+ */
+
+CmdSetMaterialMap = function ( object, mapName, newMap ) {
+
+	Cmd.call( this );
+
+	this.type = 'CmdSetMaterialMap';
+
+	this.object = object;
+	this.mapName = mapName;
+	this.oldMap = object !== undefined ? object.material[ mapName ] : undefined;
+	this.newMap = newMap;
+	this.objectUuid = object !== undefined ? object.uuid : undefined;
+/*
+	if ( object !== undefined ) {
+
+		meta = {
+			geometries: {},
+			materials: {},
+			textures: {},
+			images: {}
+		};
+
+		this.newMapJSON = newMap.toJSON( meta );
+		this.newMapJSON.images = [ newMap.image.toJSON( meta ) ];
+
+		if ( object.material[ mapName ] !== null ) {
+
+			this.oldMapJSON = object.material[ mapName ].toJSON( meta );
+			this.oldMapJSON.textures = [ object.material[ mapName ].texture.toJSON( meta ) ];
+		}
+
+	}
+*/
+
+};
+
+CmdSetMaterialMap.prototype = {
+
+	execute: function () {
+
+		this.object.material[ this.mapName ] = this.newMap;
+		this.object.material.needsUpdate = true;
+		this.editor.signals.materialChanged.dispatch( this.object.material );
+
+	},
+
+	undo: function () {
+
+		this.object.material[ this.mapName ] = this.oldMap;
+		this.object.material.needsUpdate = true;
+		this.editor.signals.materialChanged.dispatch( this.object.material );
+
+	},
+
+	toJSON: function () {
+
+		var output = Cmd.prototype.toJSON.call( this );
+
+		output.objectUuid = this.objectUuid;
+		output.mapName = this.mapName;
+
+		output.oldMap = this.oldMapJSON;
+		output.newMap = this.newMapJSON;
+
+		return output;
+
+	},
+
+	fromJSON: function ( json ) {
+
+		Cmd.prototype.fromJSON.call( this, json );
+
+		this.objectUuid = json.objectUuid;
+		this.mapName = json.mapName;
+		this.object = this.editor.objectByUuid( json.objectUuid );
+
+		this.oldMap = this.parseTexture( json.oldMap );
+		this.newMap = this.parseTexture( json.newMap );
+
+		this.oldMapJSON = json.oldMap;
+		this.newMapJSON = json.newMap;
+
+	},
+
+	parseTexture: function ( data, images ) {
+
+		var loader = new THREE.ObjectLoader();
+		return loader.parseTextures( [ data ] )[ data.uuid ];
+
+	}
+
+};

+ 112 - 47
editor/js/Sidebar.Material.js

@@ -388,7 +388,7 @@ Sidebar.Material = function ( editor ) {
 
 			if ( material.uuid !== undefined && material.uuid !== materialUUID.getValue() ) {
 
-				editor.execute( new CmdSetMaterialValue( editor.selected, 'uuid', materialUUID.getValue() ) );
+				editor.execute( new CmdSetMaterialValue( currentObject, 'uuid', materialUUID.getValue() ) );
 
 			}
 
@@ -396,7 +396,7 @@ Sidebar.Material = function ( editor ) {
 
 				material = new THREE[ materialClass.getValue() ]();
 
-				object.material = material;
+				editor.execute( new CmdSetMaterial( currentObject, material ) );
 				// TODO Copy other references in the scene graph
 				// keeping name and UUID then.
 				// Also there should be means to create a unique
@@ -405,27 +405,27 @@ Sidebar.Material = function ( editor ) {
 
 			}
 
-			if ( material.color !== undefined ) {
+			if ( material.color !== undefined && material.color.getHex() !== materialColor.getHexValue() ) {
 
-				material.color.setHex( materialColor.getHexValue() );
+				editor.execute( new CmdSetMaterialColor( currentObject, 'color', materialColor.getHexValue() ) );
 
 			}
 
-			if ( material.emissive !== undefined ) {
+			if ( material.emissive !== undefined && material.emissive.getHex() !== materialEmissive.getHexValue() ) {
 
-				material.emissive.setHex( materialEmissive.getHexValue() );
+				editor.execute( new CmdSetMaterialColor( currentObject, 'emissive', materialEmissive.getHexValue() ) );
 
 			}
 
-			if ( material.specular !== undefined ) {
+			if ( material.specular !== undefined && material.specular.getHex() !== materialSpecular.getHexValue() ) {
 
-				material.specular.setHex( materialSpecular.getHexValue() );
+				editor.execute( new CmdSetMaterialColor( currentObject, 'specular', materialSpecular.getHexValue() ) );
 
 			}
 
-			if ( material.shininess !== undefined ) {
+			if ( material.shininess !== undefined && Math.abs( material.shininess - materialShininess.getValue() ) >= 0.01 ) {
 
-				material.shininess = materialShininess.getValue();
+				editor.execute( new CmdSetMaterialValue( currentObject, 'shininess', materialShininess.getValue() ) );
 
 			}
 
@@ -435,16 +435,15 @@ Sidebar.Material = function ( editor ) {
 
 				if ( material.vertexColors !== vertexColors ) {
 
-					material.vertexColors = vertexColors;
-					material.needsUpdate = true;
+					editor.execute( new CmdSetMaterialValue( currentObject, 'vertexColors', vertexColors ) );
 
 				}
 
 			}
 
-			if ( material.skinning !== undefined ) {
+			if ( material.skinning !== undefined && material.skinning !== materialSkinning.getValue() ) {
 
-				material.skinning = materialSkinning.getValue();
+				editor.execute( new CmdToggleBooleanMaterial( currentObject, 'skinning' ) );
 
 			}
 
@@ -454,8 +453,12 @@ Sidebar.Material = function ( editor ) {
 
 				if ( objectHasUvs ) {
 
-					material.map = mapEnabled ? materialMap.getValue() : null;
-					material.needsUpdate = true;
+					var map = mapEnabled ? materialMap.getValue() : null;
+					if ( material.map !== map ) {
+
+						editor.execute( new CmdSetMaterialMap( currentObject, 'map', map ) );
+
+					}
 
 				} else {
 
@@ -471,8 +474,12 @@ Sidebar.Material = function ( editor ) {
 
 				if ( objectHasUvs ) {
 
-					material.alphaMap = mapEnabled ? materialAlphaMap.getValue() : null;
-					material.needsUpdate = true;
+					var alphaMap = mapEnabled ? materialAlphaMap.getValue() : null;
+					if ( material.alphaMap !== alphaMap ) {
+
+						editor.execute( new CmdSetMaterialMap( currentObject, 'alphaMap', alphaMap ) );
+
+					}
 
 				} else {
 
@@ -488,9 +495,18 @@ Sidebar.Material = function ( editor ) {
 
 				if ( objectHasUvs ) {
 
-					material.bumpMap = bumpMapEnabled ? materialBumpMap.getValue() : null;
-					material.bumpScale = materialBumpScale.getValue();
-					material.needsUpdate = true;
+					var bumpMap = bumpMapEnabled ? materialBumpMap.getValue() : null;
+					if ( material.bumpMap !== bumpMap ) {
+
+						editor.execute( new CmdSetMaterialMap( currentObject, 'bumpMap', bumpMap ) );
+
+					}
+
+					if ( material.bumpScale !== materialBumpScale.getValue() ) {
+
+						editor.execute( new CmdSetMaterialValue( currentObject, 'bumpScale', materialBumpScale.getValue() ) );
+
+					}
 
 				} else {
 
@@ -506,8 +522,12 @@ Sidebar.Material = function ( editor ) {
 
 				if ( objectHasUvs ) {
 
-					material.normalMap = normalMapEnabled ? materialNormalMap.getValue() : null;
-					material.needsUpdate = true;
+					var normalMap = normalMapEnabled ? materialNormalMap.getValue() : null;
+					if ( material.normalMap !== normalMap ) {
+
+						editor.execute( new CmdSetMaterialMap( currentObject, 'normalMap', normalMap ) );
+
+					}
 
 				} else {
 
@@ -523,8 +543,12 @@ Sidebar.Material = function ( editor ) {
 
 				if ( objectHasUvs ) {
 
-					material.specularMap = specularMapEnabled ? materialSpecularMap.getValue() : null;
-					material.needsUpdate = true;
+					var specularMap = specularMapEnabled ? materialSpecularMap.getValue() : null;
+					if ( material.specularMap !== normalMap ) {
+
+						editor.execute( new CmdSetMaterialMap( currentObject, 'specularMap', specularMap ) );
+
+					}
 
 				} else {
 
@@ -538,12 +562,21 @@ Sidebar.Material = function ( editor ) {
 
 				var envMapEnabled = materialEnvMapEnabled.getValue() === true;
 
-				material.envMap = envMapEnabled ? materialEnvMap.getValue() : null;
-				material.reflectivity = materialReflectivity.getValue();
-				material.needsUpdate = true;
+				var envMap = envMapEnabled ? materialEnvMap.getValue() : null;
 
-			}
+				if ( material.envMap !== envMap ) {
+
+					editor.execute( new CmdSetMaterialMap( currentObject, 'envMap', envMap ) );
+
+				}
+
+				if ( material.reflectivity !== materialReflectivity.getValue() ) {
+
+					editor.execute( new CmdSetMaterialValue( currentObject, 'reflectivity', materialReflectivity.getValue() ) );
+
+				}
 
+			}
 
 			if ( material.lightMap !== undefined ) {
 
@@ -551,8 +584,12 @@ Sidebar.Material = function ( editor ) {
 
 				if ( objectHasUvs ) {
 
-					material.lightMap = specularMapEnabled ? materialLightMap.getValue() : null;
-					material.needsUpdate = true;
+					var lightMap = specularMapEnabled ? materialLightMap.getValue() : null;
+					if ( material.lightMap !== lightMap ) {
+
+						editor.execute( new CmdSetMaterialMap( currentObject, 'lightMap', lightMap ) );
+
+					}
 
 				} else {
 
@@ -568,9 +605,18 @@ Sidebar.Material = function ( editor ) {
 
 				if ( objectHasUvs ) {
 
-					material.aoMap = aoMapEnabled ? materialAOMap.getValue() : null;
-					material.aoMapIntensity = materialAOScale.getValue();
-					material.needsUpdate = true;
+					var aoMap = aoMapEnabled ? materialAOMap.getValue() : null;
+					if ( material.aoMap !== aoMap ) {
+
+						editor.execute( new CmdSetMaterialMap( currentObject, 'aoMap', aoMap ) );
+
+					}
+
+					if ( material.aoMapIntensity !== materialAOScale.getValue() ) {
+
+						editor.execute( new CmdSetMaterialValue( currentObject, 'aoMapIntensity', materialAOScale.getValue() ) );
+
+					}
 
 				} else {
 
@@ -582,49 +628,65 @@ Sidebar.Material = function ( editor ) {
 
 			if ( material.side !== undefined ) {
 
-				material.side = parseInt( materialSide.getValue() );
+				var side = parseInt( materialSide.getValue() );
+				if ( material.side !== side ) {
+
+					editor.execute( new CmdSetMaterialValue( currentObject, 'side', side ) );
+
+				}
+
 
 			}
 
 			if ( material.shading !== undefined ) {
 
-				material.shading = parseInt( materialShading.getValue() );
+				var shading = parseInt( materialShading.getValue() );
+				if ( material.shading !== shading ) {
+
+					editor.execute( new CmdSetMaterialValue( currentObject, 'shading', shading ) );
+
+				}
 
 			}
 
 			if ( material.blending !== undefined ) {
 
-				material.blending = parseInt( materialBlending.getValue() );
+				var blending = parseInt( materialBlending.getValue() );
+				if ( material.blending !== blending ) {
+
+					editor.execute( new CmdSetMaterialValue( currentObject, 'blending', blending ) );
+
+				}
 
 			}
 
-			if ( material.opacity !== undefined ) {
+			if ( material.opacity !== undefined && Math.abs( material.opacity - materialOpacity.getValue() ) >= 0.01 ) {
 
-				material.opacity = materialOpacity.getValue();
+				editor.execute( new CmdSetMaterialValue( currentObject, 'opacity', materialOpacity.getValue() ) );
 
 			}
 
-			if ( material.transparent !== undefined ) {
+			if ( material.transparent !== undefined && material.transparent !== materialTransparent.getValue() ) {
 
-				material.transparent = materialTransparent.getValue();
+				editor.execute( new CmdToggleBooleanMaterial( currentObject, 'transparent' ) );
 
 			}
 
-			if ( material.alphaTest !== undefined ) {
+			if ( material.alphaTest !== undefined && Math.abs( material.alphaTest - materialAlphaTest.getValue() ) >= 0.01 ) {
 
-				material.alphaTest = materialAlphaTest.getValue();
+				editor.execute( new CmdSetMaterialValue( currentObject, 'alphaTest', materialAlphaTest.getValue() ) );
 
 			}
 
-			if ( material.wireframe !== undefined ) {
+			if ( material.wireframe !== undefined && material.wireframe !== materialWireframe.getValue() ) {
 
-				material.wireframe = materialWireframe.getValue();
+				editor.execute( new CmdToggleBooleanMaterial( currentObject, 'wireframe' ) );
 
 			}
 
-			if ( material.wireframeLinewidth !== undefined ) {
+			if ( material.wireframeLinewidth !== undefined && Math.abs( material.wireframeLinewidth - materialWireframeLinewidth.getValue() ) >= 0.01 ) {
 
-				material.wireframeLinewidth = materialWireframeLinewidth.getValue();
+				editor.execute( new CmdSetMaterialValue( currentObject, 'wireframeLinewidth', materialWireframeLinewidth.getValue() ) );
 
 			}
 
@@ -685,6 +747,8 @@ Sidebar.Material = function ( editor ) {
 
 	function refreshUi(resetTextureSelectors) {
 
+		if ( !currentObject ) return;
+
 		var material = currentObject.material;
 
 		if ( material.uuid !== undefined ) {
@@ -912,6 +976,7 @@ Sidebar.Material = function ( editor ) {
 
 	} );
 
+	signals.materialChanged.add( function () { refreshUi() } );
 	return container;
 
 }