Browse Source

A functional particle editor for the Urho Editor, however saving/reverting, undoing/redoing, and displaying loaded attributes doesn't work yet

hdunderscore 11 years ago
parent
commit
5cce464c03

+ 2 - 1
Bin/Data/Scripts/Editor.as

@@ -7,6 +7,7 @@
 #include "Scripts/Editor/EditorUIElement.as"
 #include "Scripts/Editor/EditorUIElement.as"
 #include "Scripts/Editor/EditorGizmo.as"
 #include "Scripts/Editor/EditorGizmo.as"
 #include "Scripts/Editor/EditorMaterial.as"
 #include "Scripts/Editor/EditorMaterial.as"
+#include "Scripts/Editor/EditorParticleEffect.as"
 #include "Scripts/Editor/EditorSettings.as"
 #include "Scripts/Editor/EditorSettings.as"
 #include "Scripts/Editor/EditorPreferences.as"
 #include "Scripts/Editor/EditorPreferences.as"
 #include "Scripts/Editor/EditorToolBar.as"
 #include "Scripts/Editor/EditorToolBar.as"
@@ -350,4 +351,4 @@ void RemoveBackup(bool success, const String&in fileName)
 {
 {
     if (success)
     if (success)
         fileSystem.Delete(fileName + ".old");
         fileSystem.Delete(fileName + ".old");
-}
+}

+ 45 - 2
Bin/Data/Scripts/Editor/EditorActions.as

@@ -758,13 +758,13 @@ class EditMaterialAction : EditAction
     XMLFile@ oldState;
     XMLFile@ oldState;
     XMLFile@ newState;
     XMLFile@ newState;
     WeakHandle material;
     WeakHandle material;
-    
+
     void Define(Material@ material_, XMLFile@ oldState_)
     void Define(Material@ material_, XMLFile@ oldState_)
     {
     {
         material = material_;
         material = material_;
         oldState = oldState_;
         oldState = oldState_;
         newState = XMLFile();
         newState = XMLFile();
-        
+
         XMLElement materialElem = newState.CreateRoot("material");
         XMLElement materialElem = newState.CreateRoot("material");
         material_.Save(materialElem);
         material_.Save(materialElem);
     }
     }
@@ -790,6 +790,49 @@ class EditMaterialAction : EditAction
     }
     }
 }
 }
 
 
+class EditParticleEffectAction : EditAction
+{
+    WeakHandle particleEffect;
+    File@ oldEffect;
+    File@ newEffect;
+
+    void Define(ParticleEffect@ particleEffect_, XMLFile@ oldEffect_)
+    {
+        /*particleEffect = particleEffect_;
+        oldEffect = oldEffect_;
+        newEffect = File();
+
+        XMLElement effectElem = newEffect.CreateRoot("particleemitter");
+        particleEffect.Save(newEffect);*/
+    }
+
+    void Undo()
+    {
+        /*ParticleEmitter@ particleEmitter_ = particleEmitter.Get();
+        if (particleEmitter_ is null)
+            return;
+
+        ParticleEffect@ effect = cache.GetResource("ParticleEffect", oldEffect);
+        if (effect is null)
+            return;
+        particleEmitter_.effect = effect;*/
+        RefreshParticleEffectEditor();
+    }
+
+    void Redo()
+    {
+        /*ParticleEmitter@ particleEmitter_ = particleEmitter.Get();
+        if (particleEmitter_ is null)
+            return;
+
+        ParticleEffect@ effect = cache.GetResource("ParticleEffect", newEffect);
+        if (effect is null)
+            return;
+        particleEmitter_.effect = effect;*/
+        RefreshParticleEffectEditor();
+    }
+}
+
 class AssignMaterialAction : EditAction
 class AssignMaterialAction : EditAction
 {
 {
     WeakHandle model;
     WeakHandle model;

+ 619 - 0
Bin/Data/Scripts/Editor/EditorParticleEffect.as

@@ -0,0 +1,619 @@
+// Urho3D material editor
+
+Window@ particleEffectWindow;
+ParticleEffect@ editParticleEffect;
+XMLFile@ oldParticleEffectState;
+bool inParticleEffectRefresh = true;
+View3D@ particleEffectPreview;
+Scene@ particlePreviewScene;
+Node@ particleEffectPreviewNode;
+Node@ particlePreviewCameraNode;
+Node@ particlePreviewLightNode;
+Light@ particlePreviewLight;
+ParticleEmitter@ particleEffectEmitter;
+
+void CreateParticleEffectEditor()
+{
+    if (particleEffectWindow !is null)
+        return;
+
+    particleEffectWindow = ui.LoadLayout(cache.GetResource("XMLFile", "UI/EditorParticleEffectWindow.xml"));
+    ui.root.AddChild(particleEffectWindow);
+    particleEffectWindow.opacity = uiMaxOpacity;
+
+    InitParticleEffectPreview();
+    RefreshParticleEffectEditor();
+
+    int height = Min(ui.root.height - 60, 500);
+    particleEffectWindow.SetSize(300, height);
+    CenterDialog(particleEffectWindow);
+
+    HideParticleEffectEditor();
+
+    SubscribeToEvent(particleEffectWindow.GetChild("NewButton", true), "Released", "NewParticleEffect");
+    SubscribeToEvent(particleEffectWindow.GetChild("RevertButton", true), "Released", "RevertParticleEffect");
+    SubscribeToEvent(particleEffectWindow.GetChild("SaveButton", true), "Released", "SaveParticleEffect");
+    SubscribeToEvent(particleEffectWindow.GetChild("SaveAsButton", true), "Released", "SaveParticleEffectAs");
+    SubscribeToEvent(particleEffectWindow.GetChild("CloseButton", true), "Released", "HideParticleEffectEditor");
+    SubscribeToEvent(particleEffectWindow.GetChild("ConstantForceX", true), "TextChanged", "EditParticleEffectConstantForce");
+    SubscribeToEvent(particleEffectWindow.GetChild("ConstantForceY", true), "TextChanged", "EditParticleEffectConstantForce");
+    SubscribeToEvent(particleEffectWindow.GetChild("ConstantForceZ", true), "TextChanged", "EditParticleEffectConstantForce");
+    SubscribeToEvent(particleEffectWindow.GetChild("DirectionMinX", true), "TextChanged", "EditParticleEffectDirection");
+    SubscribeToEvent(particleEffectWindow.GetChild("DirectionMinY", true), "TextChanged", "EditParticleEffectDirection");
+    SubscribeToEvent(particleEffectWindow.GetChild("DirectionMinZ", true), "TextChanged", "EditParticleEffectDirection");
+    SubscribeToEvent(particleEffectWindow.GetChild("DirectionMaxX", true), "TextChanged", "EditParticleEffectDirection");
+    SubscribeToEvent(particleEffectWindow.GetChild("DirectionMaxY", true), "TextChanged", "EditParticleEffectDirection");
+    SubscribeToEvent(particleEffectWindow.GetChild("DirectionMaxZ", true), "TextChanged", "EditParticleEffectDirection");
+    SubscribeToEvent(particleEffectWindow.GetChild("DampingForce", true), "TextChanged", "EditParticleEffectDampingForce");
+    SubscribeToEvent(particleEffectWindow.GetChild("ActiveTime", true), "TextChanged", "EditParticleEffectActiveTime");
+    SubscribeToEvent(particleEffectWindow.GetChild("InactiveTime", true), "TextChanged", "EditParticleEffectInactiveTime");
+    SubscribeToEvent(particleEffectWindow.GetChild("ParticleSizeMinX", true), "TextChanged", "EditParticleEffectParticleSize");
+    SubscribeToEvent(particleEffectWindow.GetChild("ParticleSizeMinY", true), "TextChanged", "EditParticleEffectParticleSize");
+    SubscribeToEvent(particleEffectWindow.GetChild("ParticleSizeMaxX", true), "TextChanged", "EditParticleEffectParticleSize");
+    SubscribeToEvent(particleEffectWindow.GetChild("ParticleSizeMaxY", true), "TextChanged", "EditParticleEffectParticleSize");
+    SubscribeToEvent(particleEffectWindow.GetChild("TimeToLiveMin", true), "TextChanged", "EditParticleEffectTimeToLive");
+    SubscribeToEvent(particleEffectWindow.GetChild("TimeToLiveMax", true), "TextChanged", "EditParticleEffectTimeToLive");
+    SubscribeToEvent(particleEffectWindow.GetChild("VelocityMin", true), "TextChanged", "EditParticleEffectVelocity");
+    SubscribeToEvent(particleEffectWindow.GetChild("VelocityMax", true), "TextChanged", "EditParticleEffectVelocity");
+    SubscribeToEvent(particleEffectWindow.GetChild("RotationMin", true), "TextChanged", "EditParticleEffectRotation");
+    SubscribeToEvent(particleEffectWindow.GetChild("RotationMax", true), "TextChanged", "EditParticleEffectRotation");
+    SubscribeToEvent(particleEffectWindow.GetChild("RotationSpeedMin", true), "TextChanged", "EditParticleEffectRotationSpeed");
+    SubscribeToEvent(particleEffectWindow.GetChild("RotationSpeedMax", true), "TextChanged", "EditParticleEffectRotationSpeed");
+    SubscribeToEvent(particleEffectWindow.GetChild("SizeAdd", true), "TextChanged", "EditParticleEffectSizeAdd");
+    SubscribeToEvent(particleEffectWindow.GetChild("SizeMultiply", true), "TextChanged", "EditParticleEffectSizeMultiply");
+    SubscribeToEvent(particleEffectWindow.GetChild("AnimationLodBias", true), "TextChanged", "EditParticleEffectAnimationLodBias");
+    SubscribeToEvent(particleEffectWindow.GetChild("NumParticles", true), "TextChanged", "EditParticleEffectNumParticles");
+    SubscribeToEvent(particleEffectWindow.GetChild("EmitterSizeX", true), "TextChanged", "EditParticleEffectEmitterSize");
+    SubscribeToEvent(particleEffectWindow.GetChild("EmitterSizeY", true), "TextChanged", "EditParticleEffectEmitterSize");
+    SubscribeToEvent(particleEffectWindow.GetChild("EmitterSizeZ", true), "TextChanged", "EditParticleEffectEmitterSize");
+    SubscribeToEvent(particleEffectWindow.GetChild("EmissionRateMin", true), "TextChanged", "EditParticleEffectEmissionRate");
+    SubscribeToEvent(particleEffectWindow.GetChild("EmissionRateMax", true), "TextChanged", "EditParticleEffectEmissionRate");
+    SubscribeToEvent(particleEffectWindow.GetChild("EmitterShape", true), "ItemSelected", "EditParticleEffectEmitterShape");
+    SubscribeToEvent(particleEffectWindow.GetChild("Scaled", true), "Toggled", "EditParticleEffectScaled");
+    SubscribeToEvent(particleEffectWindow.GetChild("Sorted", true), "Toggled", "EditParticleEffectSorted");
+    SubscribeToEvent(particleEffectWindow.GetChild("Relative", true), "Toggled", "EditParticleEffectRelative");
+
+}
+
+void EditParticleEffectConstantForce(StringHash eventType, VariantMap& eventData)
+{
+    LineEdit@ element = eventData["Element"].GetPtr();
+
+    Vector3 v = editParticleEffect.constantForce;
+
+    if (element.name == "ConstantForceX")
+        editParticleEffect.constantForce = Vector3(element.text.ToFloat(), v.y, v.z);
+
+    if (element.name == "ConstantForceY")
+        editParticleEffect.constantForce = Vector3(v.x, element.text.ToFloat(), v.z);
+
+    if (element.name == "ConstantForceZ")
+        editParticleEffect.constantForce = Vector3(v.x, v.y, element.text.ToFloat());
+}
+
+void EditParticleEffectDirection(StringHash eventType, VariantMap& eventData)
+{
+    LineEdit@ element = eventData["Element"].GetPtr();
+
+    Vector3 vMin = editParticleEffect.minDirection;
+    Vector3 vMax = editParticleEffect.maxDirection;
+
+    if (element.name == "DirectionMinX")
+        editParticleEffect.minDirection = Vector3(element.text.ToFloat(), vMin.y, vMin.z);
+
+    if (element.name == "DirectionMinY")
+        editParticleEffect.minDirection = Vector3(vMin.x, element.text.ToFloat(), vMin.z);
+
+    if (element.name == "DirectionMinZ")
+        editParticleEffect.minDirection = Vector3(vMin.x, vMin.y, element.text.ToFloat());
+
+    if (element.name == "DirectionMaxX")
+        editParticleEffect.maxDirection = Vector3(element.text.ToFloat(), vMax.y, vMax.z);
+
+    if (element.name == "DirectionMaxY")
+        editParticleEffect.maxDirection = Vector3(vMax.x, element.text.ToFloat(), vMax.z);
+
+    if (element.name == "DirectionMaxZ")
+        editParticleEffect.maxDirection = Vector3(vMax.x, vMax.y, element.text.ToFloat());
+}
+
+void EditParticleEffectDampingForce(StringHash eventType, VariantMap& eventData)
+{
+    LineEdit@ element = eventData["Element"].GetPtr();
+
+    editParticleEffect.dampingForce = element.text.ToFloat();
+}
+
+void EditParticleEffectActiveTime(StringHash eventType, VariantMap& eventData)
+{
+    LineEdit@ element = eventData["Element"].GetPtr();
+
+    editParticleEffect.activeTime = element.text.ToFloat();
+    particleEffectEmitter.Reset();
+}
+
+void EditParticleEffectInactiveTime(StringHash eventType, VariantMap& eventData)
+{
+    LineEdit@ element = eventData["Element"].GetPtr();
+
+    editParticleEffect.inactiveTime = element.text.ToFloat();
+    particleEffectEmitter.Reset();
+}
+
+void EditParticleEffectParticleSize(StringHash eventType, VariantMap& eventData)
+{
+    LineEdit@ element = eventData["Element"].GetPtr();
+
+    Vector2 vMin = editParticleEffect.minParticleSize;
+    Vector2 vMax = editParticleEffect.maxParticleSize;
+
+    if (element.name == "ParticleSizeMinX")
+        editParticleEffect.minParticleSize = Vector2(element.text.ToFloat(), vMin.y);
+
+    if (element.name == "ParticleSizeMinY")
+        editParticleEffect.minParticleSize = Vector2(vMin.x, element.text.ToFloat());
+
+    if (element.name == "ParticleSizeMaxX")
+        editParticleEffect.maxParticleSize = Vector2(element.text.ToFloat(), vMax.y);
+
+    if (element.name == "ParticleSizeMaxY")
+        editParticleEffect.maxParticleSize = Vector2(vMax.x, element.text.ToFloat());
+}
+
+void EditParticleEffectTimeToLive(StringHash eventType, VariantMap& eventData)
+{
+    LineEdit@ element = eventData["Element"].GetPtr();
+
+    float vMin = editParticleEffect.minTimeToLive;
+    float vMax = editParticleEffect.maxTimeToLive;
+
+    if (element.name == "TimeToLiveMin")
+        editParticleEffect.minTimeToLive = element.text.ToFloat();
+
+    if (element.name == "TimeToLiveMax")
+        editParticleEffect.maxTimeToLive = element.text.ToFloat();
+}
+
+void EditParticleEffectVelocity(StringHash eventType, VariantMap& eventData)
+{
+    LineEdit@ element = eventData["Element"].GetPtr();
+
+    float vMin = editParticleEffect.minVelocity;
+    float vMax = editParticleEffect.maxVelocity;
+
+    if (element.name == "VelocityMin")
+        editParticleEffect.minVelocity = element.text.ToFloat();
+
+    if (element.name == "VelocityMax")
+        editParticleEffect.maxVelocity = element.text.ToFloat();
+}
+
+void EditParticleEffectRotation(StringHash eventType, VariantMap& eventData)
+{
+    LineEdit@ element = eventData["Element"].GetPtr();
+
+    float vMin = editParticleEffect.minRotation;
+    float vMax = editParticleEffect.maxRotation;
+
+    if (element.name == "RotationMin")
+        editParticleEffect.minRotation = element.text.ToFloat();
+
+    if (element.name == "RotationMax")
+        editParticleEffect.maxRotation = element.text.ToFloat();
+}
+
+void EditParticleEffectRotationSpeed(StringHash eventType, VariantMap& eventData)
+{
+    LineEdit@ element = eventData["Element"].GetPtr();
+
+    float vMin = editParticleEffect.minRotationSpeed;
+    float vMax = editParticleEffect.maxRotationSpeed;
+
+    if (element.name == "RotationSpeedMin")
+        editParticleEffect.minRotationSpeed = element.text.ToFloat();
+
+    if (element.name == "RotationSpeedMax")
+        editParticleEffect.maxRotationSpeed = element.text.ToFloat();
+}
+
+void EditParticleEffectSizeAdd(StringHash eventType, VariantMap& eventData)
+{
+    LineEdit@ element = eventData["Element"].GetPtr();
+
+    editParticleEffect.sizeAdd = element.text.ToFloat();
+}
+
+void EditParticleEffectSizeMultiply(StringHash eventType, VariantMap& eventData)
+{
+    LineEdit@ element = eventData["Element"].GetPtr();
+
+    editParticleEffect.sizeMul = element.text.ToFloat();
+}
+
+void EditParticleEffectAnimationLodBias(StringHash eventType, VariantMap& eventData)
+{
+    LineEdit@ element = eventData["Element"].GetPtr();
+
+    editParticleEffect.animationLodBias = element.text.ToFloat();
+}
+
+void EditParticleEffectNumParticles(StringHash eventType, VariantMap& eventData)
+{
+    LineEdit@ element = eventData["Element"].GetPtr();
+
+    editParticleEffect.numParticles = element.text.ToInt();
+    particleEffectEmitter.ApplyEffect();
+}
+
+void EditParticleEffectEmitterSize(StringHash eventType, VariantMap& eventData)
+{
+    LineEdit@ element = eventData["Element"].GetPtr();
+
+    Vector3 v = editParticleEffect.emitterSize;
+
+    if (element.name == "EmitterSizeX")
+        editParticleEffect.emitterSize = Vector3(element.text.ToFloat(), v.y, v.z);
+
+    if (element.name == "EmitterSizeY")
+        editParticleEffect.emitterSize = Vector3(v.x, element.text.ToFloat(), v.z);
+
+    if (element.name == "EmitterSizeZ")
+        editParticleEffect.emitterSize = Vector3(v.x, v.y, element.text.ToFloat());
+}
+
+void EditParticleEffectEmissionRate(StringHash eventType, VariantMap& eventData)
+{
+    LineEdit@ element = eventData["Element"].GetPtr();
+
+    if (element.name == "EmissionRateMin")
+        editParticleEffect.minEmissionRate = element.text.ToFloat();
+
+    if (element.name == "EmissionRateMax")
+        editParticleEffect.maxEmissionRate = element.text.ToFloat();
+}
+
+void EditParticleEffectEmitterShape(StringHash eventType, VariantMap& eventData)
+{
+    DropDownList@ element = eventData["Element"].GetPtr();
+
+    switch (element.selection)
+    {
+        case 0:
+            editParticleEffect.emitterType = EMITTER_BOX;
+            break;
+
+        case 1:
+            editParticleEffect.emitterType = EMITTER_SPHERE;
+            break;
+    }
+}
+
+void EditParticleEffectMaterial(StringHash eventType, VariantMap& eventData)
+{
+    LineEdit@ element = eventData["Element"].GetPtr();
+    
+    editParticleEffect.material = cache.GetResource("Material", element.text);
+    particleEffectEmitter.ApplyEffect();
+}
+
+void PickEditParticleEffectMaterial(StringHash eventType, VariantMap& eventData)
+{
+    
+}
+
+void EditParticleEffectScaled(StringHash eventType, VariantMap& eventData)
+{
+    CheckBox@ element = eventData["Element"].GetPtr();
+
+    editParticleEffect.scaled = element.checked;
+    particleEffectEmitter.ApplyEffect();
+}
+
+void EditParticleEffectSorted(StringHash eventType, VariantMap& eventData)
+{
+    CheckBox@ element = eventData["Element"].GetPtr();
+
+    editParticleEffect.sorted = element.checked;
+    particleEffectEmitter.ApplyEffect();
+}
+
+void EditParticleEffectRelative(StringHash eventType, VariantMap& eventData)
+{
+    CheckBox@ element = eventData["Element"].GetPtr();
+
+    editParticleEffect.relative = element.checked;
+    particleEffectEmitter.ApplyEffect();
+}
+
+bool ShowParticleEffectEditor()
+{
+    RefreshParticleEffectEditor();
+    particleEffectWindow.visible = true;
+    particleEffectWindow.BringToFront();
+    return true;
+}
+
+void HideParticleEffectEditor()
+{
+    particleEffectWindow.visible = false;
+}
+
+void InitParticleEffectPreview()
+{
+    particlePreviewScene = Scene("particlePreviewScene");
+    particlePreviewScene.CreateComponent("Octree");
+
+    Node@ zoneNode = particlePreviewScene.CreateChild("Zone");
+    Zone@ zone = zoneNode.CreateComponent("Zone");
+    zone.boundingBox = BoundingBox(-1000, 1000);
+    zone.ambientColor = Color(0.15, 0.15, 0.15);
+    zone.fogColor = Color(0, 0, 0);
+    zone.fogStart = 10.0;
+    zone.fogEnd = 100.0;
+
+    particlePreviewCameraNode = particlePreviewScene.CreateChild("PreviewCamera");
+    particlePreviewCameraNode.position = Vector3(0, 0, -2.5);
+    Camera@ camera = particlePreviewCameraNode.CreateComponent("Camera");
+    camera.nearClip = 0.1f;
+    camera.farClip = 100.0f;
+
+    particlePreviewLightNode = particlePreviewScene.CreateChild("particlePreviewLight");
+    particlePreviewLightNode.direction = Vector3(0.5, -0.5, 0.5);
+    particlePreviewLight = particlePreviewLightNode.CreateComponent("Light");
+    particlePreviewLight.lightType = LIGHT_DIRECTIONAL;
+    particlePreviewLight.specularIntensity = 0.5;
+
+    particleEffectPreviewNode = particlePreviewScene.CreateChild("PreviewEmitter");
+    particleEffectPreviewNode.rotation = Quaternion(0, 0, 0);
+    StaticModel@ gizmo = particleEffectPreviewNode.CreateComponent("StaticModel");
+    gizmo.model = cache.GetResource("Model", "Models/Editor/Axes.mdl");
+    gizmo.materials[0] = cache.GetResource("Material", "Materials/Editor/RedUnlit.xml");
+    gizmo.materials[1] = cache.GetResource("Material", "Materials/Editor/GreenUnlit.xml");
+    gizmo.materials[2] = cache.GetResource("Material", "Materials/Editor/BlueUnlit.xml");
+    gizmo.occludee = false;
+
+    particleEffectEmitter = particleEffectPreviewNode.CreateComponent("ParticleEmitter");
+    editParticleEffect = cache.GetResource("ParticleEffect", "Particle/SnowExplosion.xml");
+    editParticleEffect.activeTime = 0;
+    particleEffectEmitter.effect = editParticleEffect;
+
+    SubscribeToEvent(particleEffectPreviewNode, "Update", "HandleParticleEffectUpdate");
+
+    particleEffectPreview = particleEffectWindow.GetChild("ParticleEffectPreview", true);
+    particleEffectPreview.SetFixedHeight(100);
+    particleEffectPreview.SetView(particlePreviewScene, camera);
+    //particleEffectPreview.autoUpdate = true;
+
+    SubscribeToEvent(particleEffectPreview, "DragMove", "RotateParticleEffectPreview");
+}
+
+void HandleParticleEffectUpdate(StringHash eventType, VariantMap& eventData)
+{
+    log.Info("ASDSA");
+    if (!particleEffectEmitter.emitting)
+    {
+        log.Info("Reset emitter");
+        particleEffectEmitter.Reset();
+    }
+}
+
+void EditParticleEffect(ParticleEffect@ effect)
+{
+    if (editParticleEffect !is null)
+        UnsubscribeFromEvent(editParticleEffect, "ReloadFinished");
+
+    editParticleEffect = effect;
+    effect.activeTime = 0;
+
+    if (editParticleEffect !is null)
+        SubscribeToEvent(editParticleEffect, "ReloadFinished", "RefreshParticleEffectEditor");
+
+    ShowParticleEffectEditor();
+}
+
+void RefreshParticleEffectEditor()
+{
+    RefreshParticleEffectPreview();
+    RefreshParticleEffectName();
+    //RefreshParticleEffectInitial();
+    RefreshParticleEffectMaterial();
+}
+
+void RefreshParticleEffectPreview()
+{
+    particleEffectEmitter.effect = editParticleEffect;
+    particleEffectPreview.QueueUpdate();
+}
+
+void RefreshParticleEffectName()
+{
+    UIElement@ container = particleEffectWindow.GetChild("NameContainer", true);
+    container.RemoveAllChildren();
+
+    LineEdit@ nameEdit = CreateAttributeLineEdit(container, null, 0, 0);
+    if (editParticleEffect !is null)
+        nameEdit.text = editParticleEffect.name;
+    SubscribeToEvent(nameEdit, "TextFinished", "EditParticleEffectName");
+
+    Button@ pickButton = CreateResourcePickerButton(container, null, 0, 0, "Pick");
+    SubscribeToEvent(pickButton, "Released", "PickEditParticleEffect");
+}
+
+void RefreshParticleEffectMaterial()
+{
+    UIElement@ container = particleEffectWindow.GetChild("ParticleMaterialContainer", true);
+    container.RemoveAllChildren();
+
+    LineEdit@ nameEdit = CreateAttributeLineEdit(container, null, 0, 0);
+    if (editParticleEffect !is null)
+        nameEdit.text = editParticleEffect.material.name;
+
+    SubscribeToEvent(nameEdit, "TextFinished", "EditParticleEffectMaterial");
+
+    Button@ pickButton = CreateResourcePickerButton(container, null, 0, 0, "Pick");
+    SubscribeToEvent(pickButton, "Released", "PickEditParticleEffectMaterial");
+}
+
+void RotateParticleEffectPreview(StringHash eventType, VariantMap& eventData)
+{
+    int elemX = eventData["ElementX"].GetInt();
+    int elemY = eventData["ElementY"].GetInt();
+    
+    if (particleEffectPreview.height > 0 && particleEffectPreview.width > 0)
+    {
+        float yaw = ((particleEffectPreview.height / 2) - elemY) * (90.0 / particleEffectPreview.height);
+        float pitch = ((particleEffectPreview.width / 2) - elemX) * (90.0 / particleEffectPreview.width);
+
+        particleEffectPreviewNode.rotation = particleEffectPreviewNode.rotation.Slerp(Quaternion(yaw, pitch, 0), 0.1);
+        particleEffectPreview.QueueUpdate();
+    }
+}
+
+void EditParticleEffectName(StringHash eventType, VariantMap& eventData)
+{
+    LineEdit@ nameEdit = eventData["Element"].GetPtr();
+    String newParticleEffectName = nameEdit.text.Trimmed();
+    if (!newParticleEffectName.empty)
+    {
+        ParticleEffect@ newParticleEffect = cache.GetResource("ParticleEffect", newParticleEffectName);
+        if (newParticleEffect !is null)
+            EditParticleEffect(newParticleEffect);
+    }
+}
+
+void PickEditParticleEffect()
+{
+    @resourcePicker = GetResourcePicker(StringHash("ParticleEffect"));
+    if (resourcePicker is null)
+        return;
+
+    String lastPath = resourcePicker.lastPath;
+    if (lastPath.empty)
+        lastPath = sceneResourcePath;
+    CreateFileSelector("Pick " + resourcePicker.typeName, "OK", "Cancel", lastPath, resourcePicker.filters, resourcePicker.lastFilter);
+    SubscribeToEvent(uiFileSelector, "FileSelected", "PickEditParticleEffectDone");
+}
+
+void PickEditParticleEffectDone(StringHash eventType, VariantMap& eventData)
+{
+    StoreResourcePickerPath();
+    CloseFileSelector();
+
+    if (!eventData["OK"].GetBool())
+    {
+        @resourcePicker = null;
+        return;
+    }
+
+    String resourceName = eventData["FileName"].GetString();
+    Resource@ res = GetPickedResource(resourceName);
+
+    if (res !is null)
+        EditParticleEffect(cast<ParticleEffect>(res));
+
+    @resourcePicker = null;
+}
+
+void NewParticleEffect()
+{
+    EditParticleEffect(ParticleEffect());
+}
+
+void RevertParticleEffect()
+{
+    if (editParticleEffect is null)
+        return;
+
+    BeginParticleEffectEdit();
+    cache.ReloadResource(editParticleEffect);
+    EndParticleEffectEdit();
+    
+    RefreshParticleEffectEditor();
+}
+
+void SaveParticleEffect()
+{
+    if (editParticleEffect is null || editParticleEffect.name.empty)
+        return;
+
+    String fullName = cache.GetResourceFileName(editParticleEffect.name);
+    if (fullName.empty)
+        return;
+
+    File saveFile(fullName, FILE_WRITE);
+    editParticleEffect.Save(saveFile);
+}
+
+void SaveParticleEffectAs()
+{
+    if (editParticleEffect is null)
+        return;
+
+    @resourcePicker = GetResourcePicker(StringHash("ParticleEffect"));
+    if (resourcePicker is null)
+        return;
+
+    String lastPath = resourcePicker.lastPath;
+    if (lastPath.empty)
+        lastPath = sceneResourcePath;
+    CreateFileSelector("Save material as", "Save", "Cancel", lastPath, resourcePicker.filters, resourcePicker.lastFilter);
+    SubscribeToEvent(uiFileSelector, "FileSelected", "SaveParticleEffectAsDone");
+}
+
+void SaveParticleEffectAsDone(StringHash eventType, VariantMap& eventData)
+{
+    StoreResourcePickerPath();
+    CloseFileSelector();
+    @resourcePicker = null;
+
+    if (editParticleEffect is null)
+        return;
+
+    if (!eventData["OK"].GetBool())
+    {
+        @resourcePicker = null;
+        return;
+    }
+
+    String fullName = eventData["FileName"].GetString();
+
+    // Add default extension for saving if not specified
+    String filter = eventData["Filter"].GetString();
+    if (GetExtension(fullName).empty && filter != "*.*")
+        fullName = fullName + filter.Substring(1);
+
+    File saveFile(fullName, FILE_WRITE);
+    if (editParticleEffect.Save(saveFile))
+    {
+        saveFile.Close();
+
+        // Load the new resource to update the name in the editor
+        ParticleEffect@ newEffect = cache.GetResource("ParticleEffect", GetResourceNameFromFullName(fullName));
+        if (newEffect !is null)
+            EditParticleEffect(newEffect);
+    }
+}
+
+void BeginParticleEffectEdit()
+{
+    if (editParticleEffect is null)
+        return;
+
+    oldParticleEffectState = XMLFile();
+    XMLElement particleEffectElem = oldParticleEffectState.CreateRoot("particleemitter");
+    //editParticleEffect.Save(particleEffectElem);
+}
+
+void EndParticleEffectEdit()
+{
+    if (editParticleEffect is null)
+        return;
+    if (!dragEditAttribute)
+    {
+        EditParticleEffectAction@ action = EditParticleEffectAction();
+        action.Define(editParticleEffect, oldParticleEffectState);
+        SaveEditAction(action);
+    }
+    
+    particleEffectPreview.QueueUpdate();
+}

+ 2 - 0
Bin/Data/Scripts/Editor/EditorUI.as

@@ -75,6 +75,7 @@ void CreateUI()
     CreateEditorSettingsDialog();
     CreateEditorSettingsDialog();
     CreateEditorPreferencesDialog();
     CreateEditorPreferencesDialog();
     CreateMaterialEditor();
     CreateMaterialEditor();
+    CreateParticleEffectEditor();
     CreateSpawnEditor();
     CreateSpawnEditor();
     CreateStatsBar();
     CreateStatsBar();
     CreateConsole();
     CreateConsole();
@@ -413,6 +414,7 @@ void CreateMenuBar()
         popup.AddChild(CreateMenuItem("Attribute inspector", @ShowAttributeInspectorWindow, 'I', QUAL_CTRL));
         popup.AddChild(CreateMenuItem("Attribute inspector", @ShowAttributeInspectorWindow, 'I', QUAL_CTRL));
         popup.AddChild(CreateMenuItem("Resource browser", @ShowResourceBrowserWindow, 'B', QUAL_CTRL));
         popup.AddChild(CreateMenuItem("Resource browser", @ShowResourceBrowserWindow, 'B', QUAL_CTRL));
         popup.AddChild(CreateMenuItem("Material editor", @ShowMaterialEditor));
         popup.AddChild(CreateMenuItem("Material editor", @ShowMaterialEditor));
+        popup.AddChild(CreateMenuItem("Particle editor", @ShowParticleEffectEditor));
         popup.AddChild(CreateMenuItem("Spawn editor", @ShowSpawnEditor));
         popup.AddChild(CreateMenuItem("Spawn editor", @ShowSpawnEditor));
         popup.AddChild(CreateMenuItem("Editor settings", @ShowEditorSettingsDialog));
         popup.AddChild(CreateMenuItem("Editor settings", @ShowEditorSettingsDialog));
         popup.AddChild(CreateMenuItem("Editor preferences", @ShowEditorPreferencesDialog));
         popup.AddChild(CreateMenuItem("Editor preferences", @ShowEditorPreferencesDialog));

+ 702 - 0
Bin/Data/UI/EditorParticleEffectWindow.xml

@@ -0,0 +1,702 @@
+<element type="Window">
+    <attribute name="Name" value="ParticleEffectWindow" />
+    <attribute name="Is Movable" value="true" />
+    <attribute name="Is Resizable" value="true" />
+    <attribute name="Resize Border" value="6 6 6 6" />
+    <attribute name="Layout Mode" value="Vertical" />
+    <attribute name="Layout Spacing" value="4" />
+    <attribute name="Layout Border" value="6 6 6 6" />
+    <element>
+        <attribute name="Min Size" value="0 16" />
+        <attribute name="Max Size" value="2147483647 16" />
+        <attribute name="Layout Mode" value="Horizontal" />
+        <element type="Text">
+            <attribute name="Text" value="Particle editor" />
+        </element>
+        <element type="Button" style="CloseButton">
+            <attribute name="Name" value="CloseButton" />
+        </element>
+    </element>
+    <element type="BorderImage" style="EditorDivider" />
+    <element type="View3D">
+        <attribute name="Name" value="ParticleEffectPreview" />
+        <attribute name="Texture" value="Texture2D;" />
+        <attribute name="Use Derived Opacity" value="false" />
+        <attribute name="Is Resizable" value="true" />
+        <attribute name="Fixed Height Resizing" value="true" />
+        <attribute name="Resize Border" value="0 6 0 6" />
+    </element>
+    <element type="BorderImage" style="EditorDivider" />
+    <element>
+        <attribute name="Min Size" value="0 16" />
+        <attribute name="Max Size" value="2147483647 16" />
+        <attribute name="Layout Mode" value="Horizontal" />
+        <attribute name="Name" value="NameContainer" />
+    </element>
+    <element type="BorderImage" style="EditorDivider" />
+    <element type="ListView" style="PanelView">
+        <attribute name="Min Size" value="0 60" />
+        <element type="BorderImage" internal="true">
+            <element internal="true">
+                <element style="Panel">
+                    <element type="Text">
+                        <attribute name="Text" value="Initial" />
+                    </element>
+                </element>
+                <element style="Panel">
+                 <!-- Initial Attributes -->
+                    <element>
+                        <!-- Constant Force -->
+                        <attribute name="Min Size" value="0 16" />
+                        <attribute name="Max Size" value="2147483647 16" />
+                        <attribute name="Layout Mode" value="Horizontal" />
+                        <attribute name="Layout Spacing" value="10" />
+                        <element type="Text" style="EditorAttributeText">
+                            <attribute name="Text" value="Constant Force" />
+                        </element>
+                        <element>
+                            <attribute name="Min Size" value="0 16" />
+                            <attribute name="Max Size" value="2147483647 16" />
+                            <attribute name="Layout Mode" value="Horizontal" />
+                            <attribute name="Layout Spacing" value="1" />
+                            <element type="LineEdit">
+                                <attribute name="Name" value="ConstantForceX" />
+                            </element>
+                            <element type="LineEdit">
+                                <attribute name="Name" value="ConstantForceY" />
+                            </element>
+                            <element type="LineEdit">
+                                <attribute name="Name" value="ConstantForceZ" />
+                            </element>
+                        </element>
+                    </element>
+                    <element>
+                        <!-- Direction Min -->
+                        <attribute name="Min Size" value="0 16" />
+                        <attribute name="Max Size" value="2147483647 16" />
+                        <attribute name="Layout Mode" value="Horizontal" />
+                        <attribute name="Layout Spacing" value="10" />
+                        <element type="Text" style="EditorAttributeText">
+                            <attribute name="Text" value="Direction (min)" />
+                        </element>
+                        <element>
+                            <attribute name="Min Size" value="0 16" />
+                            <attribute name="Max Size" value="2147483647 16" />
+                            <attribute name="Layout Mode" value="Horizontal" />
+                            <attribute name="Layout Spacing" value="1" />
+                            <element type="LineEdit">
+                                <attribute name="Name" value="DirectionMinX" />
+                            </element>
+                            <element type="LineEdit">
+                                <attribute name="Name" value="DirectionMinY" />
+                            </element>
+                            <element type="LineEdit">
+                                <attribute name="Name" value="DirectionMinZ" />
+                            </element>
+                        </element>
+                    </element>
+                    <element>
+                        <!-- Direction Max -->
+                        <attribute name="Min Size" value="0 16" />
+                        <attribute name="Max Size" value="2147483647 16" />
+                        <attribute name="Layout Mode" value="Horizontal" />
+                        <attribute name="Layout Spacing" value="10" />
+                        <element type="Text" style="EditorAttributeText">
+                            <attribute name="Text" value="Direction (max)" />
+                        </element>
+                        <element>
+                            <attribute name="Min Size" value="0 16" />
+                            <attribute name="Max Size" value="2147483647 16" />
+                            <attribute name="Layout Mode" value="Horizontal" />
+                            <attribute name="Layout Spacing" value="1" />
+                            <element type="LineEdit">
+                                <attribute name="Name" value="DirectionMaxX" />
+                            </element>
+                            <element type="LineEdit">
+                                <attribute name="Name" value="DirectionMaxY" />
+                            </element>
+                            <element type="LineEdit">
+                                <attribute name="Name" value="DirectionMaxZ" />
+                            </element>
+                        </element>
+                    </element>
+                    <element>
+                        <!-- Damping Force -->
+                        <attribute name="Min Size" value="0 16" />
+                        <attribute name="Max Size" value="2147483647 16" />
+                        <attribute name="Layout Mode" value="Horizontal" />
+                        <attribute name="Layout Spacing" value="10" />
+                        <element type="Text" style="EditorAttributeText">
+                            <attribute name="Text" value="Damping Force" />
+                        </element>
+                        <element>
+                            <attribute name="Min Size" value="0 16" />
+                            <attribute name="Max Size" value="2147483647 16" />
+                            <attribute name="Layout Mode" value="Horizontal" />
+                            <attribute name="Layout Spacing" value="1" />
+                            <element type="LineEdit">
+                                <attribute name="Name" value="DampingForce" />
+                            </element>
+                        </element>
+                    </element>
+                    <element>
+                        <!-- Active Time -->
+                        <attribute name="Min Size" value="0 16" />
+                        <attribute name="Max Size" value="2147483647 16" />
+                        <attribute name="Layout Mode" value="Horizontal" />
+                        <attribute name="Layout Spacing" value="10" />
+                        <element type="Text" style="EditorAttributeText">
+                            <attribute name="Text" value="Active Time" />
+                        </element>
+                        <element>
+                            <attribute name="Min Size" value="0 16" />
+                            <attribute name="Max Size" value="2147483647 16" />
+                            <attribute name="Layout Mode" value="Horizontal" />
+                            <attribute name="Layout Spacing" value="1" />
+                            <element type="LineEdit">
+                                <attribute name="Name" value="ActiveTime" />
+                            </element>
+                        </element>
+                    </element>
+                    <element>
+                        <!-- Inactive Time -->
+                        <attribute name="Min Size" value="0 16" />
+                        <attribute name="Max Size" value="2147483647 16" />
+                        <attribute name="Layout Mode" value="Horizontal" />
+                        <attribute name="Layout Spacing" value="10" />
+                        <element type="Text" style="EditorAttributeText">
+                            <attribute name="Text" value="Inactive Time" />
+                        </element>
+                        <element>
+                            <attribute name="Min Size" value="0 16" />
+                            <attribute name="Max Size" value="2147483647 16" />
+                            <attribute name="Layout Mode" value="Horizontal" />
+                            <attribute name="Layout Spacing" value="1" />
+                            <element type="LineEdit">
+                                <attribute name="Name" value="InactiveTime" />
+                            </element>
+                        </element>
+                    </element>
+                    <element>
+                        <!-- Min Particle Size -->
+                        <attribute name="Min Size" value="0 16" />
+                        <attribute name="Max Size" value="2147483647 16" />
+                        <attribute name="Layout Mode" value="Horizontal" />
+                        <attribute name="Layout Spacing" value="10" />
+                        <element type="Text" style="EditorAttributeText">
+                            <attribute name="Text" value="Particle Size (min)" />
+                        </element>
+                        <element>
+                            <attribute name="Min Size" value="0 16" />
+                            <attribute name="Max Size" value="2147483647 16" />
+                            <attribute name="Layout Mode" value="Horizontal" />
+                            <attribute name="Layout Spacing" value="1" />
+                            <element type="LineEdit">
+                                <attribute name="Name" value="ParticleSizeMinX" />
+                            </element>
+                            <element type="LineEdit">
+                                <attribute name="Name" value="ParticleSizeMinY" />
+                            </element>
+                        </element>
+                    </element>
+                    <element>
+                        <!-- Max Particle Size -->
+                        <attribute name="Min Size" value="0 16" />
+                        <attribute name="Max Size" value="2147483647 16" />
+                        <attribute name="Layout Mode" value="Horizontal" />
+                        <attribute name="Layout Spacing" value="10" />
+                        <element type="Text" style="EditorAttributeText">
+                            <attribute name="Text" value="Particle Size (max)" />
+                        </element>
+                        <element>
+                            <attribute name="Min Size" value="0 16" />
+                            <attribute name="Max Size" value="2147483647 16" />
+                            <attribute name="Layout Mode" value="Horizontal" />
+                            <attribute name="Layout Spacing" value="1" />
+                            <element type="LineEdit">
+                                <attribute name="Name" value="ParticleSizeMaxX" />
+                            </element>
+                            <element type="LineEdit">
+                                <attribute name="Name" value="ParticleSizeMaxY" />
+                            </element>
+                        </element>
+                    </element>
+                    <element>
+                        <!-- Time To Live -->
+                        <attribute name="Min Size" value="0 16" />
+                        <attribute name="Max Size" value="2147483647 16" />
+                        <attribute name="Layout Mode" value="Horizontal" />
+                        <attribute name="Layout Spacing" value="10" />
+                        <element type="Text" style="EditorAttributeText">
+                            <attribute name="Text" value="Time To Live" />
+                        </element>
+                        <element>
+                            <attribute name="Min Size" value="0 16" />
+                            <attribute name="Max Size" value="2147483647 16" />
+                            <attribute name="Layout Mode" value="Horizontal" />
+                            <attribute name="Layout Spacing" value="1" />
+                            <element type="LineEdit">
+                                <attribute name="Name" value="TimeToLiveMin" />
+                            </element>
+                            <element type="LineEdit">
+                                <attribute name="Name" value="TimeToLiveMax" />
+                            </element>
+                        </element>
+                    </element>
+                    <element>
+                        <!-- Velocity -->
+                        <attribute name="Min Size" value="0 16" />
+                        <attribute name="Max Size" value="2147483647 16" />
+                        <attribute name="Layout Mode" value="Horizontal" />
+                        <attribute name="Layout Spacing" value="10" />
+                        <element type="Text" style="EditorAttributeText">
+                            <attribute name="Text" value="Velocity" />
+                        </element>
+                        <element>
+                            <attribute name="Min Size" value="0 16" />
+                            <attribute name="Max Size" value="2147483647 16" />
+                            <attribute name="Layout Mode" value="Horizontal" />
+                            <attribute name="Layout Spacing" value="1" />
+                            <element type="LineEdit">
+                                <attribute name="Name" value="VelocityMin" />
+                            </element>
+                            <element type="LineEdit">
+                                <attribute name="Name" value="VelocityMax" />
+                            </element>
+                        </element>
+                    </element>
+                    <element>
+                        <!-- Rotation -->
+                        <attribute name="Min Size" value="0 16" />
+                        <attribute name="Max Size" value="2147483647 16" />
+                        <attribute name="Layout Mode" value="Horizontal" />
+                        <attribute name="Layout Spacing" value="10" />
+                        <element type="Text" style="EditorAttributeText">
+                            <attribute name="Text" value="Rotation" />
+                        </element>
+                        <element>
+                            <attribute name="Min Size" value="0 16" />
+                            <attribute name="Max Size" value="2147483647 16" />
+                            <attribute name="Layout Mode" value="Horizontal" />
+                            <attribute name="Layout Spacing" value="1" />
+                            <element type="LineEdit">
+                                <attribute name="Name" value="RotationMin" />
+                            </element>
+                            <element type="LineEdit">
+                                <attribute name="Name" value="RotationMax" />
+                            </element>
+                        </element>
+                    </element>
+                    <element>
+                        <!-- Rotation Speed -->
+                        <attribute name="Min Size" value="0 16" />
+                        <attribute name="Max Size" value="2147483647 16" />
+                        <attribute name="Layout Mode" value="Horizontal" />
+                        <attribute name="Layout Spacing" value="10" />
+                        <element type="Text" style="EditorAttributeText">
+                            <attribute name="Text" value="Rotation Speed" />
+                        </element>
+                        <element>
+                            <attribute name="Min Size" value="0 16" />
+                            <attribute name="Max Size" value="2147483647 16" />
+                            <attribute name="Layout Mode" value="Horizontal" />
+                            <attribute name="Layout Spacing" value="1" />
+                            <element type="LineEdit">
+                                <attribute name="Name" value="RotationSpeedMin" />
+                            </element>
+                            <element type="LineEdit">
+                                <attribute name="Name" value="RotationSpeedMax" />
+                            </element>
+                        </element>
+                    </element>
+                    <!-- End of Initial Attributes -->
+                </element>
+                <element type="BorderImage" style="EditorDivider" />
+                <element style="Panel">
+                    <element type="Text">
+                        <attribute name="Text" value="Variation" />
+                    </element>
+                </element>
+                <element style="Panel">
+                 <!-- Variation Attributes -->
+                    <element>
+                        <!-- Size Addition -->
+                        <attribute name="Min Size" value="0 16" />
+                        <attribute name="Max Size" value="2147483647 16" />
+                        <attribute name="Layout Mode" value="Horizontal" />
+                        <attribute name="Layout Spacing" value="10" />
+                        <element type="Text" style="EditorAttributeText">
+                            <attribute name="Text" value="Size (add)" />
+                        </element>
+                        <element>
+                            <attribute name="Min Size" value="0 16" />
+                            <attribute name="Max Size" value="2147483647 16" />
+                            <attribute name="Layout Mode" value="Horizontal" />
+                            <attribute name="Layout Spacing" value="1" />
+                            <element type="LineEdit">
+                                <attribute name="Name" value="SizeAdd" />
+                            </element>
+                        </element>
+                    </element>
+                    <element>
+                        <!-- Size Multiplication -->
+                        <attribute name="Min Size" value="0 16" />
+                        <attribute name="Max Size" value="2147483647 16" />
+                        <attribute name="Layout Mode" value="Horizontal" />
+                        <attribute name="Layout Spacing" value="10" />
+                        <element type="Text" style="EditorAttributeText">
+                            <attribute name="Text" value="Size (multiply)" />
+                        </element>
+                        <element>
+                            <attribute name="Min Size" value="0 16" />
+                            <attribute name="Max Size" value="2147483647 16" />
+                            <attribute name="Layout Mode" value="Horizontal" />
+                            <attribute name="Layout Spacing" value="1" />
+                            <element type="LineEdit">
+                                <attribute name="Name" value="SizeMultiply" />
+                            </element>
+                        </element>
+                    </element>
+                    <element>
+                        <!-- Color Frames -->
+                        <attribute name="Min Size" value="0 16" />
+                        <attribute name="Max Size" value="2147483647 16" />
+                        <attribute name="Layout Mode" value="Horizontal" />
+                        <attribute name="Layout Spacing" value="10" />
+                        <element type="Text" style="EditorAttributeText">
+                            <attribute name="Text" value="Color Frames" />
+                        </element>
+                    </element>
+                    <element type="ListView" style="PanelView">
+                        <attribute name="Name" value="ColorFrameListView" />
+                        <attribute name="Min Size" value="0 60" />
+                    </element>
+                    <element>
+                        <attribute name="Name" value="ColorFrameButtonContainer" />
+                        <attribute name="Min Size" value="0 16" />
+                        <attribute name="Max Size" value="2147483647 16" />
+                        <attribute name="Layout Mode" value="Horizontal" />
+                        <attribute name="Layout Spacing" value="4" />
+
+                        <element type="Button">
+                            <attribute name="Name" value="NewColorFrame" />
+                            <attribute name="Layout Mode" value="Horizontal" />
+                            <attribute name="Layout Border" value="1 1 1 1" />
+                            <element type="Text">
+                                <attribute name="Text" value="New" />
+                                <attribute name="Text Alignment" value="Center" />
+                            </element>
+                        </element>
+                        <element type="Button">
+                            <attribute name="Name" value="RemoveColorFrame" />
+                            <attribute name="Layout Mode" value="Horizontal" />
+                            <attribute name="Layout Border" value="1 1 1 1" />
+                            <element type="Text">
+                                <attribute name="Text" value="Remove" />
+                                <attribute name="Text Alignment" value="Center" />
+                            </element>
+                        </element>
+                    </element>
+                    <element>
+                        <!-- Texture Frames -->
+                        <attribute name="Min Size" value="0 16" />
+                        <attribute name="Max Size" value="2147483647 16" />
+                        <attribute name="Layout Mode" value="Horizontal" />
+                        <attribute name="Layout Spacing" value="10" />
+                        <element type="Text" style="EditorAttributeText">
+                            <attribute name="Text" value="Texture Frames" />
+                        </element>
+                    </element>
+                    <element type="ListView" style="PanelView">
+                        <attribute name="Name" value="TextureFrameListView" />
+                        <attribute name="Min Size" value="0 60" />
+                    </element>
+                    <element>
+                        <attribute name="Name" value="TextureFrameButtonContainer" />
+                        <attribute name="Min Size" value="0 16" />
+                        <attribute name="Max Size" value="2147483647 16" />
+                        <attribute name="Layout Mode" value="Horizontal" />
+                        <attribute name="Layout Spacing" value="4" />
+
+                        <element type="Button">
+                            <attribute name="Name" value="NewTextureFrame" />
+                            <attribute name="Layout Mode" value="Horizontal" />
+                            <attribute name="Layout Border" value="1 1 1 1" />
+                            <element type="Text">
+                                <attribute name="Text" value="New" />
+                                <attribute name="Text Alignment" value="Center" />
+                            </element>
+                        </element>
+                        <element type="Button">
+                            <attribute name="Name" value="RemoveTextureFrame" />
+                            <attribute name="Layout Mode" value="Horizontal" />
+                            <attribute name="Layout Border" value="1 1 1 1" />
+                            <element type="Text">
+                                <attribute name="Text" value="Remove" />
+                                <attribute name="Text Alignment" value="Center" />
+                            </element>
+                        </element>
+                    </element>
+                    <element>
+                        <!-- Animation LOD bias -->
+                        <attribute name="Min Size" value="0 16" />
+                        <attribute name="Max Size" value="2147483647 16" />
+                        <attribute name="Layout Mode" value="Horizontal" />
+                        <attribute name="Layout Spacing" value="10" />
+                        <element type="Text" style="EditorAttributeText">
+                            <attribute name="Text" value="Animation LOD bias" />
+                        </element>
+                        <element>
+                            <attribute name="Min Size" value="0 16" />
+                            <attribute name="Max Size" value="2147483647 16" />
+                            <attribute name="Layout Mode" value="Horizontal" />
+                            <attribute name="Layout Spacing" value="1" />
+                            <element type="LineEdit">
+                                <attribute name="Name" value="AnimationLodBias" />
+                            </element>
+                        </element>
+                    </element>
+
+                    <!-- End of Variation Attributes -->
+                </element>
+                <element type="BorderImage" style="EditorDivider" />
+                <element style="Panel">
+                    <element type="Text">
+                        <attribute name="Text" value="Emitter" />
+                    </element>
+                </element>
+                <element style="Panel">
+                 <!-- Emitter Attributes -->
+                    <element>
+                        <!-- Num Particles -->
+                        <attribute name="Min Size" value="0 16" />
+                        <attribute name="Max Size" value="2147483647 16" />
+                        <attribute name="Layout Mode" value="Horizontal" />
+                        <attribute name="Layout Spacing" value="10" />
+                        <element type="Text" style="EditorAttributeText">
+                            <attribute name="Text" value="Number of Particles" />
+                        </element>
+                        <element>
+                            <attribute name="Min Size" value="0 16" />
+                            <attribute name="Max Size" value="2147483647 16" />
+                            <attribute name="Layout Mode" value="Horizontal" />
+                            <attribute name="Layout Spacing" value="1" />
+                            <element type="LineEdit">
+                                <attribute name="Name" value="NumParticles" />
+                            </element>
+                        </element>
+                    </element>
+                    <element>
+                        <!-- Emitter Size -->
+                        <attribute name="Min Size" value="0 16" />
+                        <attribute name="Max Size" value="2147483647 16" />
+                        <attribute name="Layout Mode" value="Horizontal" />
+                        <attribute name="Layout Spacing" value="10" />
+                        <element type="Text" style="EditorAttributeText">
+                            <attribute name="Text" value="Emitter Size" />
+                        </element>
+                        <element>
+                            <attribute name="Min Size" value="0 16" />
+                            <attribute name="Max Size" value="2147483647 16" />
+                            <attribute name="Layout Mode" value="Horizontal" />
+                            <attribute name="Layout Spacing" value="1" />
+                            <element type="LineEdit">
+                                <attribute name="Name" value="EmitterSizeX" />
+                            </element>
+                            <element type="LineEdit">
+                                <attribute name="Name" value="EmitterSizeY" />
+                            </element>
+                            <element type="LineEdit">
+                                <attribute name="Name" value="EmitterSizeZ" />
+                            </element>
+                        </element>
+                    </element>
+                    <element>
+                        <!-- Emission Rate -->
+                        <attribute name="Min Size" value="0 16" />
+                        <attribute name="Max Size" value="2147483647 16" />
+                        <attribute name="Layout Mode" value="Horizontal" />
+                        <attribute name="Layout Spacing" value="10" />
+                        <element type="Text" style="EditorAttributeText">
+                            <attribute name="Text" value="Emission Rate" />
+                        </element>
+                        <element>
+                            <attribute name="Min Size" value="0 16" />
+                            <attribute name="Max Size" value="2147483647 16" />
+                            <attribute name="Layout Mode" value="Horizontal" />
+                            <attribute name="Layout Spacing" value="1" />
+                            <element type="LineEdit">
+                                <attribute name="Name" value="EmissionRateMin" />
+                            </element>
+                            <element type="LineEdit">
+                                <attribute name="Name" value="EmissionRateMax" />
+                            </element>
+                        </element>
+                    </element>
+                    <element>
+                        <!-- Emitter Shape -->
+                        <attribute name="Min Size" value="0 16" />
+                        <attribute name="Max Size" value="2147483647 16" />
+                        <attribute name="Layout Mode" value="Horizontal" />
+                        <attribute name="Layout Spacing" value="10" />
+                        <element type="Text" style="EditorAttributeText">
+                            <attribute name="Text" value="Emitter Shape" />
+                        </element>
+                        <element type="DropDownList">
+                            <attribute name="Name" value="EmitterShape" />
+                            <attribute name="Resize Popup" value="true" />
+                            <!-- Skip style processing as the purpose of below tags is to populate the content element -->
+                            <element type="Window" internal="true" popup="true" style="none">
+                                <element type="ListView" internal="true" style="none">
+                                    <element type="BorderImage" internal="true" style="none">
+                                        <element internal="true" style="none">
+                                            <element type="Text" style="FileSelectorFilterText">
+                                                <attribute name="Text" value="Box" />
+                                            </element>
+                                            <element type="Text" style="FileSelectorFilterText">
+                                                <attribute name="Text" value="Sphere" />
+                                            </element>
+                                        </element>
+                                    </element>
+                                </element>
+                            </element>
+                        </element>
+                    </element>
+
+                    <!-- End of Renderer Attributes -->
+                </element>
+                <element type="BorderImage" style="EditorDivider" />
+                <element style="Panel">
+                    <element type="Text">
+                        <attribute name="Text" value="Renderer" />
+                    </element>
+                </element>
+                <element style="Panel">
+                 <!-- Emitter Attributes -->
+                    <element>
+                        <!-- Material -->
+                        <attribute name="Min Size" value="0 16" />
+                        <attribute name="Max Size" value="2147483647 16" />
+                        <attribute name="Layout Mode" value="Horizontal" />
+                        <attribute name="Layout Spacing" value="10" />
+                        <element type="Text" style="EditorAttributeText">
+                            <attribute name="Text" value="Material" />
+                        </element>
+                        <element>
+                            <attribute name="Name" value="ParticleMaterialContainer" />
+                            <attribute name="Min Size" value="0 16" />
+                            <attribute name="Max Size" value="2147483647 16" />
+                            <attribute name="Layout Mode" value="Horizontal" />
+                            <attribute name="Layout Spacing" value="1" />
+                        </element>
+                    </element>
+                    <element>
+                        <!-- Scaled -->
+                        <attribute name="Min Size" value="0 16" />
+                        <attribute name="Max Size" value="2147483647 16" />
+                        <attribute name="Layout Mode" value="Horizontal" />
+                        <attribute name="Layout Spacing" value="10" />
+                        <element type="Text" style="EditorAttributeText">
+                            <attribute name="Text" value="Scaled" />
+                        </element>
+                        <element>
+                            <attribute name="Min Size" value="0 16" />
+                            <attribute name="Max Size" value="2147483647 16" />
+                            <attribute name="Layout Mode" value="Horizontal" />
+                            <attribute name="Layout Spacing" value="1" />
+                            <element type="CheckBox">
+                                <attribute name="Name" value="Scaled" />
+                            </element>
+                        </element>
+                    </element>
+                    <element>
+                        <!-- Sorted -->
+                        <attribute name="Min Size" value="0 16" />
+                        <attribute name="Max Size" value="2147483647 16" />
+                        <attribute name="Layout Mode" value="Horizontal" />
+                        <attribute name="Layout Spacing" value="10" />
+                        <element type="Text" style="EditorAttributeText">
+                            <attribute name="Text" value="Sorted" />
+                        </element>
+                        <element>
+                            <attribute name="Min Size" value="0 16" />
+                            <attribute name="Max Size" value="2147483647 16" />
+                            <attribute name="Layout Mode" value="Horizontal" />
+                            <attribute name="Layout Spacing" value="1" />
+                            <element type="CheckBox">
+                                <attribute name="Name" value="Sorted" />
+                            </element>
+                        </element>
+                    </element>
+                    <element>
+                        <!-- Relative -->
+                        <attribute name="Min Size" value="0 16" />
+                        <attribute name="Max Size" value="2147483647 16" />
+                        <attribute name="Layout Mode" value="Horizontal" />
+                        <attribute name="Layout Spacing" value="10" />
+                        <element type="Text" style="EditorAttributeText">
+                            <attribute name="Text" value="Relative Transform" />
+                        </element>
+                        <element>
+                            <attribute name="Min Size" value="0 16" />
+                            <attribute name="Max Size" value="2147483647 16" />
+                            <attribute name="Layout Mode" value="Horizontal" />
+                            <attribute name="Layout Spacing" value="1" />
+                            <element type="CheckBox">
+                                <attribute name="Name" value="Relative" />
+                            </element>
+                        </element>
+                    </element>
+
+                    <!-- End of Renderer Attributes -->
+                </element>
+
+            </element>
+        </element>
+    </element>
+    <element type="BorderImage" style="EditorDivider" />
+    <element>
+        <attribute name="Name" value="ButtonContainer" />
+        <attribute name="Min Size" value="0 16" />
+        <attribute name="Max Size" value="2147483647 16" />
+        <attribute name="Layout Mode" value="Horizontal" />
+        <attribute name="Layout Spacing" value="4" />
+        <element type="Button">
+            <attribute name="Name" value="NewButton" />
+            <attribute name="Layout Mode" value="Horizontal" />
+            <attribute name="Layout Border" value="1 1 1 1" />
+            <element type="Text">
+                <attribute name="Text" value="New" />
+                <attribute name="Text Alignment" value="Center" />
+            </element>
+        </element>
+        <element type="Button">
+            <attribute name="Name" value="RevertButton" />
+            <attribute name="Layout Mode" value="Horizontal" />
+            <attribute name="Layout Border" value="1 1 1 1" />
+            <element type="Text">
+                <attribute name="Text" value="Revert" />
+                <attribute name="Text Alignment" value="Center" />
+            </element>
+        </element>
+        <element type="Button">
+            <attribute name="Name" value="SaveButton" />
+            <attribute name="Layout Mode" value="Horizontal" />
+            <attribute name="Layout Border" value="1 1 1 1" />
+            <element type="Text">
+                <attribute name="Text" value="Save" />
+                <attribute name="Text Alignment" value="Center" />
+            </element>
+        </element>
+        <element type="Button">
+            <attribute name="Name" value="SaveAsButton" />
+            <attribute name="Layout Mode" value="Horizontal" />
+            <attribute name="Layout Border" value="1 1 1 1" />
+            <element type="Text">
+                <attribute name="Text" value="Save as" />
+                <attribute name="Text Alignment" value="Center" />
+            </element>
+        </element>
+    </element>
+    <element type="BorderImage" style="EditorDivider" />
+</element>

+ 1 - 1
Source/Engine/Script/GraphicsAPI.cpp

@@ -1123,7 +1123,7 @@ static void RegisterParticleEffect(asIScriptEngine* engine)
     engine->RegisterObjectMethod("ParticleEffect", "void set_minParticleSize(const Vector2&in)", asMETHOD(ParticleEffect, SetMinParticleSize), asCALL_THISCALL);
     engine->RegisterObjectMethod("ParticleEffect", "void set_minParticleSize(const Vector2&in)", asMETHOD(ParticleEffect, SetMinParticleSize), asCALL_THISCALL);
     engine->RegisterObjectMethod("ParticleEffect", "void set_maxParticleSize(const Vector2&in)", asMETHOD(ParticleEffect, SetMaxParticleSize), asCALL_THISCALL);
     engine->RegisterObjectMethod("ParticleEffect", "void set_maxParticleSize(const Vector2&in)", asMETHOD(ParticleEffect, SetMaxParticleSize), asCALL_THISCALL);
     engine->RegisterObjectMethod("ParticleEffect", "const Vector2& get_minParticleSize() const", asMETHOD(ParticleEffect, GetMinParticleSize), asCALL_THISCALL);
     engine->RegisterObjectMethod("ParticleEffect", "const Vector2& get_minParticleSize() const", asMETHOD(ParticleEffect, GetMinParticleSize), asCALL_THISCALL);
-    engine->RegisterObjectMethod("ParticleEffect", "const Vector3& get_maxParticleSize() const", asMETHOD(ParticleEffect, GetMaxParticleSize), asCALL_THISCALL);
+    engine->RegisterObjectMethod("ParticleEffect", "const Vector2& get_maxParticleSize() const", asMETHOD(ParticleEffect, GetMaxParticleSize), asCALL_THISCALL);
     engine->RegisterObjectMethod("ParticleEffect", "void set_minTimeToLive(float)", asMETHOD(ParticleEffect, SetMinTimeToLive), asCALL_THISCALL);
     engine->RegisterObjectMethod("ParticleEffect", "void set_minTimeToLive(float)", asMETHOD(ParticleEffect, SetMinTimeToLive), asCALL_THISCALL);
     engine->RegisterObjectMethod("ParticleEffect", "void set_maxTimeToLive(float)", asMETHOD(ParticleEffect, SetMaxTimeToLive), asCALL_THISCALL);
     engine->RegisterObjectMethod("ParticleEffect", "void set_maxTimeToLive(float)", asMETHOD(ParticleEffect, SetMaxTimeToLive), asCALL_THISCALL);
     engine->RegisterObjectMethod("ParticleEffect", "float get_minTimeToLive() const", asMETHOD(ParticleEffect, GetMinTimeToLive), asCALL_THISCALL);
     engine->RegisterObjectMethod("ParticleEffect", "float get_minTimeToLive() const", asMETHOD(ParticleEffect, GetMinTimeToLive), asCALL_THISCALL);