Browse Source

Material technique editing.

Lasse Öörni 12 years ago
parent
commit
8a94f363ee

+ 1 - 0
Bin/Data/Scripts/Editor/AttributeEditor.as

@@ -872,6 +872,7 @@ void InitResourcePicker()
     resourcePickers.Push(ResourcePicker("Image", imageFilters));
     resourcePickers.Push(ResourcePicker("Model", "*.mdl", ACTION_PICK));
     resourcePickers.Push(ResourcePicker("Material", materialFilters, ACTION_PICK | ACTION_OPEN | ACTION_EDIT));
+    resourcePickers.Push(ResourcePicker("Technique", "*.xml"));
     resourcePickers.Push(ResourcePicker("Texture2D", textureFilters));
     resourcePickers.Push(ResourcePicker("TextureCube", "*.xml"));
     resourcePickers.Push(ResourcePicker("ScriptFile", scriptFilters));

+ 206 - 7
Bin/Data/Scripts/Editor/EditorMaterial.as

@@ -28,6 +28,9 @@ void CreateMaterialEditor()
     SubscribeToEvent(materialWindow.GetChild("CloseButton", true), "Released", "HideMaterialEditor");
     SubscribeToEvent(materialWindow.GetChild("NewParameterDropDown", true), "ItemSelected", "CreateShaderParameter");
     SubscribeToEvent(materialWindow.GetChild("DeleteParameterButton", true), "Released", "DeleteShaderParameter");
+    SubscribeToEvent(materialWindow.GetChild("NewTechniqueButton", true), "Released", "NewTechnique");
+    SubscribeToEvent(materialWindow.GetChild("DeleteTechniqueButton", true), "Released", "DeleteTechnique");
+    SubscribeToEvent(materialWindow.GetChild("SortTechniquesButton", true), "Released", "SortTechniques");
 }
 
 bool ShowMaterialEditor()
@@ -71,10 +74,74 @@ void RefreshMaterialName()
     SubscribeToEvent(pickButton, "Released", "PickEditMaterial");
 }
 
-void RefreshMaterialTechniques()
+void RefreshMaterialTechniques(bool fullUpdate = true)
 {
     ListView@ list = materialWindow.GetChild("TechniqueList");
-    list.RemoveAllItems();
+
+    if (editMaterial is null)
+        return;
+
+    if (fullUpdate == true)
+    {
+        list.RemoveAllItems();
+
+        for (uint i = 0; i < editMaterial.numTechniques; ++i)
+        {
+            TechniqueEntry entry = editMaterial.techniqueEntries[i];
+    
+            UIElement@ container = UIElement();
+            container.SetLayout(LM_HORIZONTAL, 4);
+            container.SetFixedHeight(ATTR_HEIGHT);
+            list.AddItem(container);
+        
+            LineEdit@ nameEdit = CreateAttributeLineEdit(container, null, i, 0);
+            nameEdit.name = "TechniqueNameEdit" + String(i);
+
+            Button@ pickButton = CreateResourcePickerButton(container, null, i, 0, "Pick");
+            SubscribeToEvent(pickButton, "Released", "PickMaterialTechnique");
+            Button@ openButton = CreateResourcePickerButton(container, null, i, 0, "Open");
+            SubscribeToEvent(openButton, "Released", "OpenResource");
+    
+            if (entry.technique !is null)
+                nameEdit.text = entry.technique.name;
+
+            SubscribeToEvent(nameEdit, "TextFinished", "EditMaterialTechnique");
+
+            UIElement@ container2 = UIElement();
+            container2.SetLayout(LM_HORIZONTAL, 4);
+            container2.SetFixedHeight(ATTR_HEIGHT);
+            list.AddItem(container2);
+    
+            Text@ text = container2.CreateChild("Text");
+            text.style = "EditorAttributeText";
+            text.text = "Quality";
+            LineEdit@ attrEdit = CreateAttributeLineEdit(container2, null, i, 0);
+            attrEdit.text = String(entry.qualityLevel);
+            SubscribeToEvent(attrEdit, "TextChanged", "EditTechniqueQuality");
+            SubscribeToEvent(attrEdit, "TextFinished", "EditTechniqueQuality");
+    
+            text = container2.CreateChild("Text");
+            text.style = "EditorAttributeText";
+            text.text = "LOD Distance";
+            attrEdit = CreateAttributeLineEdit(container2, null, i, 0);
+            attrEdit.text = String(entry.lodDistance);
+            SubscribeToEvent(attrEdit, "TextChanged", "EditTechniqueLodDistance");
+            SubscribeToEvent(attrEdit, "TextFinished", "EditTechniqueLodDistance");
+        }
+    }
+    else
+    {
+        for (uint i = 0; i < editMaterial.numTechniques; ++i)
+        {
+            TechniqueEntry entry = editMaterial.techniqueEntries[i];
+
+            LineEdit@ nameEdit = materialWindow.GetChild("TechniqueNameEdit" + String(i), true);
+            if (nameEdit is null)
+                continue;
+
+            nameEdit.text = entry.technique !is null ? entry.technique.name : "";
+        }
+    }
 }
 
 void RefreshMaterialTextures(bool fullUpdate = true)
@@ -95,19 +162,19 @@ void RefreshMaterialTextures(bool fullUpdate = true)
     
             LineEdit@ nameEdit = CreateAttributeLineEdit(container, null, i, 0);
             nameEdit.name = "TextureNameEdit" + String(i);
-    
+
             Button@ pickButton = CreateResourcePickerButton(container, null, i, 0, "Pick");
             SubscribeToEvent(pickButton, "Released", "PickMaterialTexture");
             Button@ openButton = CreateResourcePickerButton(container, null, i, 0, "Open");
             SubscribeToEvent(openButton, "Released", "OpenResource");
-    
+
             if (editMaterial !is null)
             {
                 Texture@ texture = editMaterial.textures[i];
                 if (texture !is null)
                     nameEdit.text = texture.name;
             }
-            
+
             SubscribeToEvent(nameEdit, "TextFinished", "EditMaterialTexture");
         }
     }
@@ -118,7 +185,7 @@ void RefreshMaterialTextures(bool fullUpdate = true)
             LineEdit@ nameEdit = materialWindow.GetChild("TextureNameEdit" + String(i), true);
             if (nameEdit is null)
                 continue;
-    
+
             String textureName;
             if (editMaterial !is null)
             {
@@ -425,10 +492,142 @@ void EditMaterialTexture(StringHash eventType, VariantMap& eventData)
         editMaterial.textures[index] = texture;
     }
     else
-        editMaterial.textures[index] =null;
+        editMaterial.textures[index] = null;
+
+    EndMaterialEdit();
+}
+
+void NewTechnique()
+{
+    if (editMaterial is null)
+        return;
+        
+    BeginMaterialEdit();
+    editMaterial.numTechniques = editMaterial.numTechniques + 1;
+    EndMaterialEdit();
+    
+    RefreshMaterialTechniques();
+}
+
+void DeleteTechnique()
+{
+    if (editMaterial is null || editMaterial.numTechniques < 2)
+        return;
+
+    BeginMaterialEdit();
+    editMaterial.numTechniques = editMaterial.numTechniques - 1;
+    EndMaterialEdit();
+    
+    RefreshMaterialTechniques();
+}
+
+void PickMaterialTechnique(StringHash eventType, VariantMap& eventData)
+{
+    if (editMaterial is null)
+        return;
+
+    UIElement@ button = eventData["Element"].GetUIElement();
+    resourcePickIndex = button.vars["Index"].GetUInt();
+
+    @resourcePicker = GetResourcePicker(ShortStringHash("Technique"));
+    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", "PickMaterialTechniqueDone");
+}
+
+void PickMaterialTechniqueDone(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 && editMaterial !is null)
+    {
+        BeginMaterialEdit();
+        TechniqueEntry entry = editMaterial.techniqueEntries[resourcePickIndex];
+        editMaterial.SetTechnique(resourcePickIndex, res, entry.qualityLevel, entry.lodDistance);
+        EndMaterialEdit();
+
+        RefreshMaterialTechniques(false);
+    }
 
+    @resourcePicker = null;
+}
+
+void EditMaterialTechnique(StringHash eventType, VariantMap& eventData)
+{
+    if (editMaterial is null)
+        return;
+
+    LineEdit@ attrEdit = eventData["Element"].GetUIElement();
+    String techniqueName = attrEdit.text.Trimmed();
+    uint index = attrEdit.vars["Index"].GetUInt();
+
+    BeginMaterialEdit();
+
+    Technique@ newTech;
+    if (!techniqueName.empty)
+        newTech = cache.GetResource("Technique", techniqueName);
+
+    TechniqueEntry entry = editMaterial.techniqueEntries[index];
+    editMaterial.SetTechnique(index, newTech, entry.qualityLevel, entry.lodDistance);
+
+    EndMaterialEdit();
+}
+
+void EditTechniqueQuality(StringHash eventType, VariantMap& eventData)
+{
+    if (editMaterial is null)
+        return;
+
+    LineEdit@ attrEdit = eventData["Element"].GetUIElement();
+    uint newQualityLevel = attrEdit.text.ToUInt();
+    uint index = attrEdit.vars["Index"].GetUInt();
+
+    BeginMaterialEdit();
+    TechniqueEntry entry = editMaterial.techniqueEntries[index];
+    editMaterial.SetTechnique(index, entry.technique, newQualityLevel, entry.lodDistance);
     EndMaterialEdit();
+}
 
+void EditTechniqueLodDistance(StringHash eventType, VariantMap& eventData)
+{
+    if (editMaterial is null)
+        return;
+
+    LineEdit@ attrEdit = eventData["Element"].GetUIElement();
+    float newLodDistance = attrEdit.text.ToFloat();
+    uint index = attrEdit.vars["Index"].GetUInt();
+
+    BeginMaterialEdit();
+    TechniqueEntry entry = editMaterial.techniqueEntries[index];
+    editMaterial.SetTechnique(index, entry.technique, entry.qualityLevel, newLodDistance);
+    EndMaterialEdit();
+}
+
+void SortTechniques()
+{
+    if (editMaterial is null)
+        return;
+        
+    BeginMaterialEdit();
+    editMaterial.SortTechniques();
+    EndMaterialEdit();
+    
+    RefreshMaterialTechniques();
 }
 
 void BeginMaterialEdit()

+ 33 - 0
Bin/Data/UI/EditorMaterialWindow.xml

@@ -31,6 +31,39 @@
     <element type="ListView">
         <attribute name="Name" value="TechniqueList" />
     </element>
+    <element>
+        <attribute name="Name" value="TechniqueButtonContainer" />
+        <attribute name="Min Size" value="0 16" />
+        <attribute name="Max Size" value="2147483647 16" />
+        <attribute name="Layout Mode" value="Horizontal" />
+        <element type="Button">
+            <attribute name="Name" value="NewTechniqueButton" />
+            <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="DeleteTechniqueButton" />
+            <attribute name="Layout Mode" value="Horizontal" />
+            <attribute name="Layout Border" value="1 1 1 1" />
+            <element type="Text">
+                <attribute name="Text" value="Del" />
+                <attribute name="Text Alignment" value="Center" />
+            </element>
+        </element>
+        <element type="Button">
+            <attribute name="Name" value="SortTechniquesButton" />
+            <attribute name="Layout Mode" value="Horizontal" />
+            <attribute name="Layout Border" value="1 1 1 1" />
+            <element type="Text">
+                <attribute name="Text" value="Sort" />
+                <attribute name="Text Alignment" value="Center" />
+            </element>
+        </element>
+    </element>
     <element type="BorderImage" style="EditorDivider" />
     <element type="Text">
         <attribute name="Text" value="Textures" />

+ 1 - 0
Docs/ScriptAPI.dox

@@ -2078,6 +2078,7 @@ Methods:<br>
 - void SetUVTransform(const Vector2&, float, const Vector2&)
 - void SetUVTransform(const Vector2&, float, float)
 - void RemoveShaderParameter(const String&)
+- void SortTechniques()
 - Material@ Clone(const String& arg0 = String ( )) const
 
 Properties:<br>

+ 15 - 0
Engine/Graphics/Material.cpp

@@ -84,6 +84,14 @@ TextureUnit ParseTextureUnitName(const String& name)
 
 static TechniqueEntry noEntry;
 
+bool CompareTechniqueEntries(const TechniqueEntry& lhs, const TechniqueEntry& rhs)
+{
+    if (lhs.lodDistance_ != rhs.lodDistance_)
+        return lhs.lodDistance_ > rhs.lodDistance_;
+    else
+        return lhs.qualityLevel_ > rhs.qualityLevel_;
+}
+
 TechniqueEntry::TechniqueEntry() :
     qualityLevel_(0),
     lodDistance_(0.0f)
@@ -176,6 +184,8 @@ bool Material::Load(const XMLElement& source)
         techniqueElem = techniqueElem.GetNext("technique");
     }
     
+    SortTechniques();
+    
     XMLElement textureElem = source.GetChild("texture");
     while (textureElem)
     {
@@ -426,6 +436,11 @@ SharedPtr<Material> Material::Clone(const String& cloneName) const
     return ret;
 }
 
+void Material::SortTechniques()
+{
+    Sort(techniques_.Begin(), techniques_.End(), CompareTechniqueEntries);
+}
+
 void Material::MarkForAuxView(unsigned frameNumber)
 {
     auxViewFrameNumber_ = frameNumber;

+ 2 - 0
Engine/Graphics/Material.h

@@ -109,6 +109,8 @@ public:
     void ReleaseShaders();
     /// Clone material.
     SharedPtr<Material> Clone(const String& cloneName = String::EMPTY) const;
+    /// Ensure that material techniques are listed in correct order.
+    void SortTechniques();
     /// Mark material for auxiliary view rendering.
     void MarkForAuxView(unsigned frameNumber);
     

+ 2 - 0
Engine/Script/GraphicsAPI.cpp

@@ -600,6 +600,7 @@ static void RegisterMaterial(asIScriptEngine* engine)
     engine->RegisterObjectBehaviour("TechniqueEntry", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(ConstructTechniqueEntry), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectBehaviour("TechniqueEntry", asBEHAVE_CONSTRUCT, "void f(const TechniqueEntry&in)", asFUNCTION(ConstructTechniqueEntry), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectBehaviour("TechniqueEntry", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(DestructTechniqueEntry), asCALL_CDECL_OBJLAST);
+    engine->RegisterObjectMethod("TechniqueEntry", "TechniqueEntry& opAssign(const TechniqueEntry&in)", asMETHOD(TechniqueEntry, operator =), asCALL_THISCALL);
     engine->RegisterObjectMethod("TechniqueEntry", "void set_technique(Technique@+)", asFUNCTION(TechniqueEntrySetTechnique), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("TechniqueEntry", "Technique@+ get_technique() const", asFUNCTION(TechniqueEntryGetTechnique), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectProperty("TechniqueEntry", "int qualityLevel", offsetof(TechniqueEntry, qualityLevel_));
@@ -612,6 +613,7 @@ static void RegisterMaterial(asIScriptEngine* engine)
     engine->RegisterObjectMethod("Material", "void SetUVTransform(const Vector2&in, float, const Vector2&in)", asMETHODPR(Material, SetUVTransform, (const Vector2&, float, const Vector2&), void), asCALL_THISCALL);
     engine->RegisterObjectMethod("Material", "void SetUVTransform(const Vector2&in, float, float)", asMETHODPR(Material, SetUVTransform, (const Vector2&, float, float), void), asCALL_THISCALL);
     engine->RegisterObjectMethod("Material", "void RemoveShaderParameter(const String&in)", asMETHOD(Material, RemoveShaderParameter), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Material", "void SortTechniques()", asMETHOD(Material, SortTechniques), asCALL_THISCALL);
     engine->RegisterObjectMethod("Material", "Material@ Clone(const String&in cloneName = String()) const", asFUNCTION(MaterialClone), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("Material", "void set_numTechniques(uint)", asMETHOD(Material, SetNumTechniques), asCALL_THISCALL);
     engine->RegisterObjectMethod("Material", "uint get_numTechniques() const", asMETHOD(Material, GetNumTechniques), asCALL_THISCALL);