Browse Source

Delete Assets and Emitters

This change adds buttons to the Asset Admin to create, re-order, and delete particle emitters. It also adds a button to delete assets entirely.
Peter Robinson 4 years ago
parent
commit
454b7ba482

+ 1 - 0
editor/AssetAdmin/AssetAdmin.cs

@@ -33,6 +33,7 @@ function AssetAdmin::create(%this)
 	exec("./NewParticleAssetDialog.cs");
 	exec("./NewFontAssetDialog.cs");
 	exec("./NewAudioAssetDialog.cs");
+	exec("./DeleteAssetDialog.cs");
 	exec("./ParticleEditor/exec.cs");
 
 	%this.guiPage = EditorCore.RegisterEditor("Asset Manager", %this);

+ 24 - 16
editor/AssetAdmin/AssetDictionary.cs

@@ -85,13 +85,30 @@ function AssetDictionary::addButton(%this, %assetID)
 	ThemeManager.setProfile(%button, "tipProfile", "TooltipProfile");
 	%this.grid.add(%button);
 
+	%this.fixSize();
+
+	return %button;
+}
+
+function AssetDictionary::removeButton(%this, %assetID)
+{
+	%button = %this.getButton(%assetID);
+	if(isObject(%button))
+	{
+		%button.delete();
+		%this.fixSize();
+		return true;
+	}
+	return false;
+}
+
+function AssetDictionary::fixSize(%this)
+{
 	if(%this.getExpanded())
 	{
 		%this.setExpanded(false);
 		%this.setExpanded(true);
 	}
-
-	return %button;
 }
 
 function AssetDictionary::getButton(%this, %assetID)
@@ -115,21 +132,12 @@ function AssetDictionary::unload(%this)
 		%obj = %this.grid.getObject(%i);
 		%obj.delete();
 	}
+}
 
-	//release all the assets we loaded for this - might take them out of memory
-	// %query = new AssetQuery();
-	// AssetDatabase.findAllAssets(%query);
-	// AssetDatabase.findAssetType(%query, %this.Type, true);
-	//
-	// for(%i = 0; %i < %query.getCount(); %i++)
-	// {
-	// 	%assetID = %query.getAsset(%i);
-	// 	if(!AssetDatabase.isAssetInternal(%assetID))
-	// 	{
-	// 		AssetDatabase.releaseAsset(%assetID);
-	// 	}
-	// }
-	// %query.delete();
+function AssetDictionary::reload(%this)
+{
+	%this.unload();
+	%this.load();
 }
 
 function AssetDictionarySprite::onAnimationEnd(%this, %animationAssetID)

+ 190 - 4
editor/AssetAdmin/AssetInspector.cs

@@ -52,6 +52,36 @@ function AssetInspector::onAdd(%this)
 	ThemeManager.setProfile(%this.titleDropDown, "scrollingPanelArrowProfile", "ArrowProfile");
 	%this.titlebar.add(%this.titleDropDown);
 
+	%this.deleteAssetButton = new GuiButtonCtrl()
+	{
+		HorizSizing = "left";
+		Class = "EditorIconButton";
+		Frame = 48;
+		Position = "660 5";
+		Command = %this.getId() @ ".deleteAsset();";
+		Tooltip = "Delete Asset";
+		Visible = false;
+	};
+	ThemeManager.setProfile(%this.deleteAssetButton, "iconButtonProfile");
+	%this.add(%this.deleteAssetButton);
+
+	%this.emitterButtonBar = new GuiChainCtrl()
+	{
+		Class = "EditorButtonBar";
+		Position = "340 5";
+		Extent = "0 24";
+		ChildSpacing = 4;
+		IsVertical = false;
+		Tool = %this;
+		Visible = false;
+	};
+	ThemeManager.setProfile(%this.emitterButtonBar, "emptyProfile");
+	%this.add(%this.emitterButtonBar);
+	%this.emitterButtonBar.addButton("AddEmitter", 25, "Add Emitter", "");
+	%this.emitterButtonBar.addButton("MoveEmitterBackward", 27, "Move Emitter Backward", "getMoveEmitterBackwardEnabled");
+	%this.emitterButtonBar.addButton("MoveEmitterForward", 28, "Move Emitter Forward", "getMoveEmitterForwardEnabled");
+	%this.emitterButtonBar.addButton("RemoveEmitter", 23, "Remove Emitter", "getRemoveEmitterEnabled");
+
 	%this.tabBook = new GuiTabBookCtrl()
 	{
 		Class = AssetInspectorTabBook;
@@ -156,6 +186,15 @@ function AssetInspector::createInspector(%this)
 	return %inspector;
 }
 
+function AssetInspector::hideInspector(%this)
+{
+	%this.titlebar.setText("");
+	%this.titleDropDown.visible = false;
+	%this.tabBook.Visible = false;
+	%this.emitterButtonBar.visible = false;
+	%this.deleteAssetButton.visible = false;
+}
+
 function AssetInspector::resetInspector(%this)
 {
 	%this.titlebar.setText("");
@@ -170,6 +209,9 @@ function AssetInspector::resetInspector(%this)
 	{
 		%this.tabBook.remove(%this.emitterGraphPage);
 	}
+
+	%this.emitterButtonBar.visible = false;
+	%this.deleteAssetButton.visible = true;
 }
 
 function AssetInspector::loadImageAsset(%this, %imageAsset, %assetID)
@@ -206,6 +248,14 @@ function AssetInspector::loadParticleAsset(%this, %particleAsset, %assetID)
 	%this.resetInspector();
 	%this.titleDropDown.visible = true;
 
+	%this.refreshParticleTitleDropDown(%particleAsset, 0);
+	%this.titleDropDown.Command = %this.getId() @ ".onChooseParticleAsset(" @ %particleAsset.getId() @ ");";
+
+	%this.onChooseParticleAsset(%particleAsset);
+}
+
+function AssetInspector::refreshParticleTitleDropDown(%this, %particleAsset, %index)
+{
 	%this.titleDropDown.clearItems();
 	%this.titleDropDown.addItem("Particle Asset:" SPC %particleAsset.AssetName);
 	for(%i = 0; %i < %particleAsset.getEmitterCount(); %i++)
@@ -213,11 +263,8 @@ function AssetInspector::loadParticleAsset(%this, %particleAsset, %assetID)
 		%emitter = %particleAsset.getEmitter(%i);
 		%this.titleDropDown.addItem("Emitter:" SPC %emitter.EmitterName);
 		%this.titleDropDown.setItemColor(%i + 1, ThemeManager.activeTheme.color5);
-		%this.titleDropDown.Command = %this.getId() @ ".onChooseParticleAsset(" @ %particleAsset.getId() @ ");";
 	}
-	%this.titleDropDown.setCurSel(0);
-
-	%this.onChooseParticleAsset(%particleAsset);
+	%this.titleDropDown.setCurSel(%index);
 }
 
 function AssetInspector::onChooseParticleAsset(%this, %particleAsset)
@@ -255,6 +302,9 @@ function AssetInspector::onChooseParticleAsset(%this, %particleAsset)
 	}
 	%this.tabBook.selectPage(%curSel);
 	%this.inspector.openGroupByIndex(0);
+
+	%this.emitterButtonBar.visible = true;
+	%this.emitterButtonBar.refreshEnabled();
 }
 
 function AssetInspector::loadFontAsset(%this, %fontAsset, %assetID)
@@ -298,3 +348,139 @@ function AssetInspector::loadSpineAsset(%this, %spineAsset, %assetID)
 	%this.inspector.inspect(%spineAsset);
 	%this.inspector.openGroupByIndex(0);
 }
+
+function AssetInspector::deleteAsset(%this)
+{
+	%asset = %this.inspector.getInspectObject();
+	if(%this.titleDropDown.visible && %this.titleDropDown.getSelectedItem() != 0)
+	{
+		%asset = %asset.getOwner();
+	}
+
+	%width = 700;
+	%height = 230;
+	%dialog = new GuiControl()
+	{
+		class = "DeleteAssetDialog";
+		superclass = "EditorDialog";
+		dialogSize = (%width + 8) SPC (%height + 8);
+		dialogCanClose = true;
+		dialogText = "Delete Asset";
+		doomedAsset = %asset;
+	};
+	%dialog.init(%width, %height);
+
+	Canvas.pushDialog(%dialog);
+}
+
+function AssetInspector::addEmitter(%this)
+{
+	%asset = %this.inspector.getInspectObject();
+	if(%this.titleDropDown.getSelectedItem() != 0)
+	{
+		%asset = %asset.getOwner();
+	}
+
+	%width = 700;
+	%height = 230;
+	%dialog = new GuiControl()
+	{
+		class = "NewParticleEmitterDialog";
+		superclass = "EditorDialog";
+		dialogSize = (%width + 8) SPC (%height + 8);
+		dialogCanClose = true;
+		dialogText = "New Particle Emitter";
+		parentAsset = %asset;
+	};
+	%dialog.init(%width, %height);
+
+	Canvas.pushDialog(%dialog);
+}
+
+function AssetInspector::MoveEmitterForward(%this)
+{
+	%emitter = %this.inspector.getInspectObject();
+	%asset = %emitter.getOwner();
+	%index = %this.titleDropDown.getSelectedItem();
+	%asset.moveEmitter(%index-1, %index);
+
+	%this.refreshParticleTitleDropDown(%asset, %index+1);
+
+	%asset.refreshAsset();
+}
+
+function AssetInspector::MoveEmitterBackward(%this)
+{
+	%emitter = %this.inspector.getInspectObject();
+	%asset = %emitter.getOwner();
+	%index = %this.titleDropDown.getSelectedItem();
+	%asset.moveEmitter(%index-1, %index-2);
+
+	%this.refreshParticleTitleDropDown(%asset, %index-1);
+
+	%asset.refreshAsset();
+}
+
+function AssetInspector::RemoveEmitter(%this)
+{
+	%emitter = %this.inspector.getInspectObject();
+	%asset = %emitter.getOwner();
+	%asset.RemoveEmitter(%emitter, true);
+
+	%index = %this.titleDropDown.getSelectedItem();
+	%this.titleDropDown.deleteItem(%index);
+
+	if(%this.titleDropDown.getItemCount() <= %index)
+	{
+		%index = %this.titleDropDown.getItemCount() - 1;
+	}
+	%this.titleDropDown.setCurSel(%index);
+	%this.inspector.inspect(%asset.getEmitter(%index - 1));
+	%this.emitterGraphPage.inspect(%asset, %index - 1);
+	%this.emitterButtonBar.refreshEnabled();
+
+	%asset.refreshAsset();
+}
+
+function AssetInspector::getMoveEmitterForwardEnabled(%this)
+{
+	if(isObject(%this.titleDropDown) && %this.titleDropDown.getSelectedItem() <= 0)
+	{
+		return false;
+	}
+	if(isObject(%this.inspector))
+	{
+		%asset = %this.inspector.getInspectObject();
+		%emitterID = %this.emitterGraphPage.emitterID;
+
+		return %emitterID != (%asset.getOwner().getEmitterCount() - 1);
+	}
+	return false;
+}
+
+function AssetInspector::getMoveEmitterBackwardEnabled(%this)
+{
+	if(isObject(%this.titleDropDown) && %this.titleDropDown.getSelectedItem() <= 0)
+	{
+		return false;
+	}
+	if(isObject(%this.inspector))
+	{
+		return %this.emitterGraphPage.emitterID != 0;
+	}
+	return false;
+}
+
+function AssetInspector::getRemoveEmitterEnabled(%this)
+{
+	if(isObject(%this.titleDropDown) && %this.titleDropDown.getSelectedItem() <= 0)
+	{
+		return false;
+	}
+	if(isObject(%this.inspector))
+	{
+		%asset = %this.inspector.getInspectObject();
+		return %asset.getOwner().getEmitterCount() > 1;
+	}
+	return false;
+}

+ 105 - 0
editor/AssetAdmin/DeleteAssetDialog.cs

@@ -0,0 +1,105 @@
+
+function DeleteAssetDialog::init(%this, %width, %height)
+{
+	//Get the dialog contents
+	%window = %this.getObject(0);
+	%content = %window.getObject(0);
+
+	%this.feedback = new GuiControl()
+	{
+		HorizSizing = "right";
+		VertSizing = "bottom";
+		Position = "12 12";
+		Extent = (%width - 24) SPC 70;
+		text = "Whoa there! Once you delete this asset, it's long gone! There's no undo. Are you sure you want to move forward?";
+		textWrap = true;
+	};
+	ThemeManager.setProfile(%this.feedback, "infoProfile");
+	%content.add(%this.feedback);
+
+	//Create the file text box
+	%form = new GuiGridCtrl()
+	{
+		class = "EditorForm";
+		extent = %width SPC %height;
+		Position = "0 80";
+		cellSizeX = %width / 2;
+		cellSizeY = 50;
+	};
+	%form.addListener(%this);
+
+	%item = %form.addFormItem("Delete Dependencies", %width SPC 30);
+	%this.deleteDependenaciesBox = %form.createCheckboxItem(%item);
+	%this.deleteDependenaciesBox.textExtent = (%width / 2) SPC "30";
+
+	%item = %form.addFormItem("Delete Loose Files", %width SPC 30);
+	%this.deleteLooseFilesBox = %form.createCheckboxItem(%item);
+	%this.deleteLooseFilesBox.textExtent = (%width / 2) SPC "30";
+
+	%content.add(%form);
+
+	%this.cancelButton = new GuiButtonCtrl()
+	{
+		HorizSizing = "right";
+		VertSizing = "bottom";
+		Position = "478 160";
+		Extent = "100 30";
+		Text = "Cancel";
+		Command = %this.getID() @ ".onClose();";
+	};
+	ThemeManager.setProfile(%this.cancelButton, "buttonProfile");
+
+	%this.deleteButton = new GuiButtonCtrl()
+	{
+		HorizSizing = "right";
+		VertSizing = "bottom";
+		Position = "588 158";
+		Extent = "100 34";
+		Text = "Delete";
+		Command = %this.getID() @ ".onDelete();";
+	};
+	ThemeManager.setProfile(%this.deleteButton, "primaryButtonProfile");
+
+	%content.add(%this.cancelButton);
+	%content.add(%this.deleteButton);
+}
+
+function DeleteAssetDialog::onClose(%this)
+{
+	Canvas.popDialog(%this);
+}
+
+function DeleteAssetDialog::onDelete(%this)
+{
+	%assetID = %this.doomedAsset.getAssetId();
+	%deleteDependants = %this.deleteDependenaciesBox.getStateOn();
+
+	//Remove the asset...
+	AssetDatabase.deleteAsset(%assetID, %this.deleteLooseFilesBox.getStateOn(), %deleteDependants);
+
+	//Remove the button, but we don't know who has it. So just try them all...
+	%killedAnImage = AssetAdmin.Dictionary["ImageAsset"].removeButton(%assetID);
+	%killedAnAnimation = AssetAdmin.Dictionary["AnimationAsset"].removeButton(%assetID);
+	AssetAdmin.Dictionary["ParticleAsset"].removeButton(%assetID);
+	AssetAdmin.Dictionary["FontAsset"].removeButton(%assetID);
+	AssetAdmin.Dictionary["AudioAsset"].removeButton(%assetID);
+
+	if(%killedAnImage && %deleteDependants)
+	{
+		AssetAdmin.Dictionary["AnimationAsset"].reload();
+		AssetAdmin.Dictionary["FontAsset"].reload();
+	}
+
+	if((%killedAnImage || %killedAnAnimation) && %deleteDependants)
+	{
+		AssetAdmin.Dictionary["ParticleAsset"].reload();
+	}
+
+	AssetAdmin.inspector.hideInspector();
+
+	AssetAdmin.AssetScene.clear(true);
+	AssetAdmin.audioPlayButtonContainer.setVisible(false);
+	AssetAdmin.AssetWindow.setVisible(false);
+
+	%this.onClose();
+}

+ 1 - 1
editor/AssetAdmin/ParticleEditor/AssetParticleGraphTool.cs

@@ -192,8 +192,8 @@ function AssetParticleGraphTool::inspect(%this, %asset, %emitterID)
 		%this.lifeGraph.graph.inspect(%asset);
 	}
 	%this.baseList.clearSelection();
-	%this.baseList.setCurSel(0);
 	%this.emitterID = %emitterID;
+	%this.baseList.setCurSel(0);
 }
 
 function AssetParticleGraphToolList::onSelect(%this, %index, %text, %id)

+ 9 - 1
editor/AssetAdmin/ParticleEditor/AssetParticleGraphUnit.cs

@@ -19,6 +19,7 @@ function AssetParticleGraphUnit::onAdd(%this)
 		Frame = 0;
 		Position = "2" SPC (%center + 13);
 		Command = %this.getId() @ ".valueZoomIn();";
+		Tooltip = "Zoom In";
 	};
 	ThemeManager.setProfile(%this.valueZoomInButton, "iconButtonProfile");
 	%this.add(%this.valueZoomInButton);
@@ -29,6 +30,7 @@ function AssetParticleGraphUnit::onAdd(%this)
 		Frame = 1;
 		Position = "2" SPC (%center - 13);
 		Command = %this.getId() @ ".valueZoomOut();";
+		Tooltip = "Zoom Out";
 	};
 	ThemeManager.setProfile(%this.valueZoomOutButton, "iconButtonProfile");
 	%this.add(%this.valueZoomOutButton);
@@ -40,6 +42,7 @@ function AssetParticleGraphUnit::onAdd(%this)
 		Frame = 2;
 		Position = "2 18";
 		Command = %this.getId() @ ".valueMoveUp();";
+		Tooltip = "Move Graph Up";
 	};
 	ThemeManager.setProfile(%this.valueMoveUpButton, "iconButtonProfile");
 	%this.add(%this.valueMoveUpButton);
@@ -50,6 +53,7 @@ function AssetParticleGraphUnit::onAdd(%this)
 		Frame = 6;
 		Position = "2" SPC (getWord(%this.extent, 1) - 66);
 		Command = %this.getId() @ ".valueMoveDown();";
+		Tooltip = "Move Graph Down";
 	};
 	ThemeManager.setProfile(%this.valueMoveDownButton, "iconButtonProfile");
 	%this.add(%this.valueMoveDownButton);
@@ -72,6 +76,7 @@ function AssetParticleGraphUnit::onAdd(%this)
 		Frame = 0;
 		Position = "0 0";
 		Command = %this.getId() @ ".timeZoomIn();";
+		Tooltip = "Zoom In";
 	};
 	ThemeManager.setProfile(%this.timeZoomInButton, "iconButtonProfile");
 	%this.timeZoomContainer.add(%this.timeZoomInButton);
@@ -82,6 +87,7 @@ function AssetParticleGraphUnit::onAdd(%this)
 		Frame = 1;
 		Position = "26 0";
 		Command = %this.getId() @ ".timeZoomOut();";
+		Tooltip = "Zoom Out";
 	};
 	ThemeManager.setProfile(%this.timeZoomOutButton, "iconButtonProfile");
 	%this.timeZoomContainer.add(%this.timeZoomOutButton);
@@ -94,6 +100,7 @@ function AssetParticleGraphUnit::onAdd(%this)
 		HorizSizing = "right";
 		Position = "30" SPC %bottom;
 		Command = %this.getId() @ ".timeMoveBack();";
+		Tooltip = "Move Graph Back";
 	};
 	ThemeManager.setProfile(%this.timeMoveBackButton, "iconButtonProfile");
 	%this.add(%this.timeMoveBackButton);
@@ -105,6 +112,7 @@ function AssetParticleGraphUnit::onAdd(%this)
 		HorizSizing = "left";
 		Position = (getWord(%this.graph.extent, 0) + 6) SPC %bottom;
 		Command = %this.getId() @ ".timeMoveForward();";
+		Tooltip = "Move Graph Forward";
 	};
 	ThemeManager.setProfile(%this.timeMoveForwardButton, "iconButtonProfile");
 	%this.add(%this.timeMoveForwardButton);
@@ -196,7 +204,7 @@ function AssetParticleGraphUnit::refreshCamera(%this)
 	{
 		return;
 	}
-	
+
 	%xMin = %this.timeController.getCameraMin();
 	%xMax = %this.timeController.getCameraMax();
 	%yMin = %this.valueController.getCameraMin();

+ 174 - 0
editor/AssetAdmin/ParticleEditor/NewParticleEmitterDialog.cs

@@ -0,0 +1,174 @@
+
+function NewParticleEmitterDialog::init(%this, %width, %height)
+{
+	//Get the dialog contents
+	%window = %this.getObject(0);
+	%content = %window.getObject(0);
+
+	//Create the file text box
+	%form = new GuiGridCtrl()
+	{
+		class = "EditorForm";
+		extent = %width SPC %height;
+		cellSizeX = %width;
+		cellSizeY = 50;
+	};
+	%form.addListener(%this);
+
+	%item = %form.addFormItem("Image Asset", %width SPC 30);
+	%this.imageDropDown = %form.createDropDownItem(%item);
+	%this.populateImageDropDown();
+
+	%item = %form.addFormItem("Animation Asset", %width SPC 30);
+	%this.animationDropDown = %form.createDropDownItem(%item);
+	%this.populateAnimationDropDown();
+
+	%item = %form.addFormItem("Emitter Name", %width SPC 30);
+	%this.emitterNameBox = %form.createTextEditItem(%item);
+	%this.emitterNameBox.Command = %this.getId() @ ".Validate();";
+
+	%content.add(%form);
+
+	%this.cancelButton = new GuiButtonCtrl()
+	{
+		HorizSizing = "right";
+		VertSizing = "bottom";
+		Position = "478 160";
+		Extent = "100 30";
+		Text = "Cancel";
+		Command = %this.getID() @ ".onClose();";
+	};
+	ThemeManager.setProfile(%this.cancelButton, "buttonProfile");
+
+	%this.createButton = new GuiButtonCtrl()
+	{
+		HorizSizing = "right";
+		VertSizing = "bottom";
+		Position = "588 158";
+		Extent = "100 34";
+		Text = "Create";
+		Command = %this.getID() @ ".onCreate();";
+		Active = false;
+	};
+	ThemeManager.setProfile(%this.createButton, "primaryButtonProfile");
+
+	%content.add(%this.cancelButton);
+	%content.add(%this.createButton);
+}
+
+function NewParticleEmitterDialog::Validate(%this)
+{
+	%this.createButton.active = false;
+
+	%emitterName = %this.emitterNameBox.getText();
+
+	%imageAssetID = %this.imageDropDown.getText();
+	%animationAssetID = %this.animationDropDown.getText();
+
+	if(%emitterName !$= "" && (%imageAssetID $= "" || %animationAssetID $= ""))
+	{
+		%this.createButton.active = true;
+		return true;
+	}
+	return false;
+}
+
+function NewParticleEmitterDialog::onClose(%this)
+{
+	Canvas.popDialog(%this);
+}
+
+function NewParticleEmitterDialog::onCreate(%this)
+{
+	if(%this.validate())
+	{
+		%emitter = %this.parentAsset.createEmitter();
+		if(%emitter != 0)
+		{
+			%emitter.setEmitterName(%this.emitterNameBox.getText());
+
+			if(%this.imageDropDown.getText() !$= "")
+			{
+				%emitter.setImage(%this.imageDropDown.getText());
+			}
+			else
+			{
+				%emitter.setAnimation(%this.animationDropDown.getText());
+			}
+
+			%i = %this.parentAsset.getEmitterCount();
+			AssetAdmin.Inspector.titleDropDown.addItem("Emitter:" SPC %emitter.EmitterName);
+			AssetAdmin.Inspector.titleDropDown.setItemColor(%i, ThemeManager.activeTheme.color5);
+			AssetAdmin.Inspector.titleDropDown.setSelected(%i);
+			AssetAdmin.Inspector.onChooseParticleAsset(%this.parentAsset);
+		}
+		else
+		{
+			warn("NewParticleEmitterDialog::onCreate - No emitter created!");
+		}
+
+		%this.onClose();
+	}
+}
+
+function NewParticleEmitterDialog::onDropDownClosed(%this, %dropDown)
+{
+	if(%dropDown == %this.imageDropDown && %dropDown.getText() !$= "")
+	{
+		%this.animationDropDown.setSelected(0);
+	}
+	else if(%dropDown == %this.animationDropDown && %dropDown.getText() !$= "")
+	{
+		%this.imageDropDown.setSelected(0);
+	}
+
+	%this.validate();
+}
+
+function NewParticleEmitterDialog::populateImageDropDown(%this)
+{
+	%this.imageDropDown.clearItems();
+
+	%query = new AssetQuery();
+	AssetDatabase.findAllAssets(%query);
+	AssetDatabase.findAssetType(%query, "ImageAsset", true);
+
+	for(%i = 0; %i < %query.getCount(); %i++)
+	{
+		%assetID = %query.getAsset(%i);
+
+		if(!AssetDatabase.isAssetInternal(%assetID))
+		{
+			%this.imageDropDown.addItem(%assetID);
+		}
+	}
+	%query.delete();
+
+	%this.imageDropDown.sortByText();
+	%this.imageDropDown.insertItem(0, "");
+	%this.imageDropDown.setSelected(0);
+}
+
+function NewParticleEmitterDialog::populateAnimationDropDown(%this)
+{
+	%this.animationDropDown.clearItems();
+
+	%query = new AssetQuery();
+	AssetDatabase.findAllAssets(%query);
+	AssetDatabase.findAssetType(%query, "AnimationAsset", true);
+
+	for(%i = 0; %i < %query.getCount(); %i++)
+	{
+		%assetID = %query.getAsset(%i);
+
+		if(!AssetDatabase.isAssetInternal(%assetID))
+		{
+			%this.animationDropDown.addItem(%assetID);
+		}
+	}
+	%query.delete();
+
+	%this.animationDropDown.sortByText();
+	%this.animationDropDown.insertItem(0, "");
+	%this.animationDropDown.setSelected(0);
+}

+ 1 - 0
editor/AssetAdmin/ParticleEditor/exec.cs

@@ -1,3 +1,4 @@
 exec("./AssetParticleGraphTool.cs");
 exec("./AssetParticleGraphUnit.cs");
 exec("./ParticleGraphCameraController.cs");
+exec("./NewParticleEmitterDialog.cs");

+ 38 - 0
editor/EditorCore/EditorButtonBar.cs

@@ -0,0 +1,38 @@
+
+function EditorButtonBar::addButton(%this, %click, %frame, %tooltip, %enabled)
+{
+	if(!isObject(%this.tool))
+	{
+		warn("EditorButtonBar::addButton: Cannot add a button without a tool to handle callback.");
+		return;
+	}
+
+	%button = new GuiButtonCtrl()
+	{
+		Class = "EditorIconButton";
+		Frame = %frame;
+		Position = "0 0";
+		Command = %this.tool.getId() @ "." @ %click @ "();";
+		Tooltip = %tooltip;
+		EnabledFunction = %enabled;
+	};
+	ThemeManager.setProfile(%button, "iconButtonProfile");
+	%this.add(%button);
+
+	if(%enabled !$= "")
+	{
+		%button.setActive(%this.tool.call(%enabled));
+	}
+}
+
+function EditorButtonBar::refreshEnabled(%this)
+{
+	for(%i = 0; %i < %this.getCount(); %i++)
+	{
+		%button = %this.getObject(%i);
+		if(%button.EnabledFunction !$= "")
+		{
+			%button.setActive(%this.tool.call(%button.EnabledFunction));
+		}
+	}
+}

+ 1 - 0
editor/EditorCore/EditorCore.cs

@@ -26,6 +26,7 @@ function EditorCore::create( %this )
 	exec("./EditorDialog.cs");
 	exec("./EditorForm.cs");
 	exec("./EditorIconButton.cs");
+	exec("./EditorButtonBar.cs");
 
 	new ScriptObject(ThemeManager);
 

+ 14 - 0
editor/EditorCore/EditorForm.cs

@@ -164,6 +164,20 @@ function EditorForm::createDropDownItem(%this, %label)
 	return %dropDown;
 }
 
+function EditorForm::createCheckboxItem(%this, %label)
+{
+	%box = new GuiCheckBoxCtrl()
+	{
+		Position = "10 16";
+		Extent = (getWord(%label.extent, 0) - 24) SPC 30;
+		Text = %label.text;
+	};
+	ThemeManager.setProfile(%box, "checkboxProfile");
+	%label.add(%box);
+	%label.text = "";
+	return %box;
+}
+
 function EditorFormDropDown::onClose(%this)
 {
 	%this.form.postEvent("DropDownClosed", %this);

+ 5 - 0
editor/EditorCore/EditorIconButton.cs

@@ -16,11 +16,16 @@ function EditorIconButton::onAdd(%this)
 		ImageSize = "18 18";
 		ImageColor = ThemeManager.activeTheme.iconButtonProfile.FontColor;
 		Frame = %this.frame;
+		Tooltip = %this.Tooltip;
 	};
 	ThemeManager.setProfile(%this.icon, "spriteProfile");
 	%this.add(%this.icon);
 
 	%this.startListening(ThemeManager);
+	if(%this.Tooltip !$= "")
+	{
+		ThemeManager.setProfile(%this, "tipProfile", "TooltipProfile");
+	}
 }
 
 function EditorIconButton::onTouchEnter(%this)

+ 5 - 2
engine/source/2d/assets/ParticleAssetEmitter.cc

@@ -395,8 +395,11 @@ void ParticleAssetEmitter::setEmitterName( const char* pEmitterName )
 
 void ParticleAssetEmitter::setOwner( ParticleAsset* pParticleAsset )
 {
-    // Sanity!
-    AssertFatal( mOwner == NULL, "ParticleAssetEmitter::setOwner() - Cannot set an owner when one is already assigned." );
+	if(pParticleAsset != NULL)
+	{
+		// Sanity!
+		AssertFatal( mOwner == NULL, "ParticleAssetEmitter::setOwner() - Cannot set an owner when one is already assigned." );
+	}
 
     // Set owner.
     mOwner = pParticleAsset;

+ 5 - 0
engine/source/gui/buttons/guiDropDownCtrl.cc

@@ -56,6 +56,11 @@ void GuiDropDownListBoxCtrl::addSelection(LBItem *item, S32 index)
 void GuiDropDownListBoxCtrl::setCurSel(S32 index)
 {
 	Parent::setCurSel(index);
+}
+
+void GuiDropDownListBoxCtrl::onTouchUp(const GuiEvent &event)
+{
+	Parent::onTouchUp(event);
 	mDropDownCtrl->closeDropDown();
 }
 #pragma endregion

+ 1 - 0
engine/source/gui/buttons/guiDropDownCtrl.h

@@ -57,6 +57,7 @@ public:
 	GuiDropDownListBoxCtrl(GuiDropDownCtrl *ctrl);
 	void addSelection(LBItem *item, S32 index);
 	void setCurSel(S32 index);
+	void onTouchUp(const GuiEvent &event);
 };
 
 class GuiDropDownCtrl : public GuiButtonCtrl

+ 5 - 0
engine/source/gui/editor/guiParticleGraphInspector.cc

@@ -119,6 +119,11 @@ ParticleAssetField* GuiParticleGraphInspector::getTargetField()
 
 	if (field == NULL)
 	{
+		if (mEmitterIndex >= mTargetAsset->getEmitterCount())
+		{
+			mEmitterIndex = mTargetAsset->getEmitterCount() - 1;
+		}
+
 		ParticleAssetEmitter* emitter = mTargetAsset->getEmitter(mEmitterIndex);
 		ParticleAssetFieldCollection &emitterCollection = emitter->getParticleFields();
 		field = emitterCollection.findField(mTargetField);