فهرست منبع

Editor: Automatically remove unused materials from material browser.

Mugen87 5 سال پیش
والد
کامیت
63e8dfc5ff
3فایلهای تغییر یافته به همراه87 افزوده شده و 17 حذف شده
  1. 50 8
      editor/js/Editor.js
  2. 12 0
      editor/js/Sidebar.Material.js
  3. 25 9
      editor/js/Sidebar.Project.js

+ 50 - 8
editor/js/Editor.js

@@ -102,6 +102,8 @@ var Editor = function () {
 	this.textures = {};
 	this.scripts = {};
 
+	this.materialsRefCounter = new Map(); // tracks how often is a material used by a 3D object
+
 	this.animations = {};
 	this.mixer = new THREE.AnimationMixer( this.scene );
 
@@ -216,6 +218,8 @@ Editor.prototype = {
 			scope.removeCamera( child );
 			scope.removeHelper( child );
 
+			if ( child.material !== undefined ) scope.removeMaterial( child.material );
+
 		} );
 
 		object.parent.remove( object );
@@ -244,15 +248,13 @@ Editor.prototype = {
 
 			for ( var i = 0, l = material.length; i < l; i ++ ) {
 
-				if ( material[ i ].uuid in this.materials ) return;
-				this.materials[ material[ i ].uuid ] = material[ i ];
+				this.addMaterialToRefCounter( material[ i ] );
 
 			}
 
 		} else {
 
-			if ( material.uuid in this.materials ) return;
-			this.materials[ material.uuid ] = material;
+			this.addMaterialToRefCounter( material );
 
 		}
 
@@ -260,19 +262,39 @@ Editor.prototype = {
 
 	},
 
+	addMaterialToRefCounter: function ( material ) {
+
+		var materialsRefCounter = this.materialsRefCounter;
+
+		var count = materialsRefCounter.get( material );
+
+		if ( count === undefined ) {
+
+			materialsRefCounter.set( material, 1 );
+			this.materials[ material.uuid ] = material;
+
+		} else {
+
+			count ++;
+			materialsRefCounter.set( material, count );
+
+		}
+
+	},
+
 	removeMaterial: function ( material ) {
 
 		if ( Array.isArray( material ) ) {
 
 			for ( var i = 0, l = material.length; i < l; i ++ ) {
 
-				delete this.materials[ material[ i ].uuid ];
+				this.removeMaterialFromRefCounter( material[ i ] );
 
 			}
 
 		} else {
 
-			delete this.materials[ material.uuid ];
+			this.removeMaterialFromRefCounter( material );
 
 		}
 
@@ -280,6 +302,26 @@ Editor.prototype = {
 
 	},
 
+	removeMaterialFromRefCounter: function ( material ) {
+
+		var materialsRefCounter = this.materialsRefCounter;
+
+		var count = materialsRefCounter.get( material );
+		count --;
+
+		if ( count === 0 ) {
+
+			materialsRefCounter.delete( material );
+			delete this.materials[ material.uuid ];
+
+		} else {
+
+			materialsRefCounter.set( material, count );
+
+		}
+
+	},
+
 	getMaterialById: function ( id ) {
 
 		var material;
@@ -456,7 +498,7 @@ Editor.prototype = {
 
 		var material = object.material;
 
-		if ( Array.isArray( material ) ) {
+		if ( Array.isArray( material ) && slot !== undefined ) {
 
 			material = material[ slot ];
 
@@ -468,7 +510,7 @@ Editor.prototype = {
 
 	setObjectMaterial: function ( object, slot, newMaterial ) {
 
-		if ( Array.isArray( object.material ) ) {
+		if ( Array.isArray( object.material ) && slot !== undefined ) {
 
 			object.material[ slot ] = newMaterial;
 

+ 12 - 0
editor/js/Sidebar.Material.js

@@ -609,6 +609,18 @@ var SidebarMaterial = function ( editor ) {
 
 				}
 
+				if ( Array.isArray( currentObject.material ) ) {
+
+					// don't remove the entire multi-material. just the material of the selected slot
+
+					editor.removeMaterial( currentObject.material[ currentMaterialSlot ] );
+
+				} else {
+
+					editor.removeMaterial( currentObject.material );
+
+				}
+
 				editor.execute( new SetMaterialCommand( editor, currentObject, material, currentMaterialSlot ), 'New Material: ' + materialClass.getValue() );
 				editor.addMaterial( material );
 				// TODO Copy other references in the scene graph

+ 25 - 9
editor/js/Sidebar.Project.js

@@ -112,11 +112,6 @@ var SidebarProject = function ( editor ) {
 	materials.add( headerRow );
 
 	var listbox = new UIListbox();
-	signals.materialAdded.add( function () {
-
-		listbox.setItems( Object.values( editor.materials ) );
-
-	} );
 	materials.add( listbox );
 
 	var buttonsRow = new UIRow();
@@ -136,13 +131,25 @@ var SidebarProject = function ( editor ) {
 	var assignMaterial = new UIButton().setLabel( strings.getKey( 'sidebar/project/Assign' ) ).setMargin( '0px 5px' );
 	assignMaterial.onClick( function () {
 
-		if ( editor.selected !== null ) {
+		var selectedObject = editor.selected;
+
+		if ( selectedObject !== null ) {
+
+			var oldMaterial = selectedObject.material;
+
+			// only assing materials to objects with a material property (e.g. avoid assigning material to THREE.Group)
+
+			if ( oldMaterial !== undefined ) {
 
-			var material = editor.getMaterialById( parseInt( listbox.getValue() ) );
+				var material = editor.getMaterialById( parseInt( listbox.getValue() ) );
 
-			if ( material !== undefined ) {
+				if ( material !== undefined ) {
 
-				editor.execute( new SetMaterialCommand( editor, editor.selected, material ) );
+					editor.removeMaterial( oldMaterial );
+					editor.execute( new SetMaterialCommand( editor, selectedObject, material ) );
+					editor.addMaterial( material );
+
+				}
 
 			}
 
@@ -166,6 +173,15 @@ var SidebarProject = function ( editor ) {
 
 	} );
 
+	signals.materialAdded.add( refreshMaterialBrowserUI );
+	signals.materialRemoved.add( refreshMaterialBrowserUI );
+
+	function refreshMaterialBrowserUI() {
+
+		listbox.setItems( Object.values( editor.materials ) );
+
+	}
+
 	return container;
 
 };