Browse Source

Pick resource functionality in editor.
Editor script code cleanup.
Added missing functions to the script API.

Lasse Öörni 14 years ago
parent
commit
23d51b853e

+ 5 - 5
Bin/Data/Scripts/Editor/EditorImport.as

@@ -218,9 +218,9 @@ Vector3 GetVector3FromStrings(Array<String>@ coords, uint startIndex)
 
 void ProcessRef(String& ref)
 {
-    if (ref.Find("local://") == 0)
+    if (ref.StartsWith("local://"))
         ref = ref.Substring(8);
-    if (ref.Find("file://") == 0)
+    if (ref.StartsWith("file://"))
         ref = ref.Substring(7);
 }
 
@@ -254,11 +254,11 @@ void ConvertMaterial(const String&in materialName, const String&in filePath)
     while (!file.eof)
     {
         String line = file.ReadLine().Trimmed();
-        if (line.Find("alpha_rejection") == 0)
+        if (line.StartsWith("alpha_rejection"))
             mask = true;
-        if (line.Find("cull_hardware none") == 0)
+        if (line.StartsWith("cull_hardware none"))
             twoSided = true;
-        if (line.Find("texture ") == 0)
+        if (line.StartsWith("texture "))
         {
             textureName = line.Substring(8);
             ProcessRef(textureName);

+ 151 - 93
Bin/Data/Scripts/Editor/EditorNodeWindow.as

@@ -4,29 +4,35 @@ Window@ nodeWindow;
 
 const uint MAX_ATTRNAME_LENGTH = 28;
 
-class ResourceEditorData
+class ResourcePicker
 {
     String resourceType;
     String lastPath;
+    uint lastFilter;
     Array<String> filters;
 
-    ResourceEditorData(const String&in resourceType_, const String&in filter_)
+    ResourcePicker(const String&in resourceType_, const String&in filter_)
     {
         resourceType = resourceType_;
         filters.Push(filter_);
+        lastFilter = 0;
     }
 
-    ResourceEditorData(const String&in resourceType_, const Array<String>@ filters_)
+    ResourcePicker(const String&in resourceType_, const Array<String>@ filters_)
     {
         resourceType = resourceType_;
         filters = filters_;
+        lastFilter = 0;
     }
 }
 
-Array<ResourceEditorData@> resourceEditors;
+Array<ResourcePicker@> resourcePickers;
 
 bool inLoadAttributeEditor = false;
-uint resourcePickType = 0;
+uint resourcePickID = 0;
+uint resourcePickIndex = 0;
+uint resourcePickSubIndex = 0;
+ResourcePicker@ resourcePicker;
 String resourcePickEditorName;
 
 void CreateNodeWindow()
@@ -35,17 +41,17 @@ void CreateNodeWindow()
         return;
 
     // Fill resource editor data
-    resourceEditors.Push(ResourceEditorData("Model", "*.mdl"));
-    resourceEditors.Push(ResourceEditorData("Material", "*.xml"));
+    resourcePickers.Push(ResourcePicker("Model", "*.mdl"));
+    resourcePickers.Push(ResourcePicker("Material", "*.xml"));
     Array<String> textureFilters;
     textureFilters.Push("*.dds");
     textureFilters.Push("*.jpg");
     textureFilters.Push("*.png");
-    resourceEditors.Push(ResourceEditorData("Texture2D", textureFilters));
-    resourceEditors.Push(ResourceEditorData("TextureCube", "*.xml"));
-    resourceEditors.Push(ResourceEditorData("Animation", "*.ani"));
-    resourceEditors.Push(ResourceEditorData("ScriptFile", "*.as"));
-    resourceEditors.Push(ResourceEditorData("XMLFile", "*.xml"));
+    resourcePickers.Push(ResourcePicker("Texture2D", textureFilters));
+    resourcePickers.Push(ResourcePicker("TextureCube", "*.xml"));
+    resourcePickers.Push(ResourcePicker("Animation", "*.ani"));
+    resourcePickers.Push(ResourcePicker("ScriptFile", "*.as"));
+    resourcePickers.Push(ResourcePicker("XMLFile", "*.xml"));
 
     nodeWindow = ui.LoadLayout(cache.GetResource("XMLFile", "UI/EditorNodeWindow.xml"), uiStyle);
     ui.root.AddChild(nodeWindow);
@@ -163,87 +169,6 @@ void EditAttribute(StringHash eventType, VariantMap& eventData)
         UpdateSceneWindowNodeOnly(selectedNode);
 }
 
-void PickResource(StringHash eventType, VariantMap& eventData)
-{
-    if (uiFileSelector !is null)
-        return;
-
-    /*
-    UIElement@ button = eventData["Element"].GetUIElement();
-    LineEdit@ attrEdit = button.parent.children[1];
-    uint type = uint(attrEdit.vars["Type"].GetInt());
-
-    ResourceEditorData@ data = resourceEditors[type - ATTR_EDITOR_RESOURCE];
-
-    Array<String> filters;
-    filters.Push("*" + data.fileExtension);
-    String lastPath = data.lastPath;
-    if (lastPath.empty)
-        lastPath = sceneResourcePath;
-    CreateFileSelector("Pick " + data.resourceType, "OK", "Cancel", lastPath, filters, 0);
-    SubscribeToEvent(uiFileSelector, "FileSelected", "PickResourceDone");
-
-    resourcePickType = type;
-    resourcePickEditorName = attrEdit.name;
-    */
-}
-
-void OpenResource(StringHash eventType, VariantMap& eventData)
-{
-    UIElement@ button = eventData["Element"].GetUIElement();
-    LineEdit@ attrEdit = button.parent.children[1];
-    fileSystem.SystemOpen(sceneResourcePath + attrEdit.text, "");
-}
-
-void PickResourceDone(StringHash eventType, VariantMap& eventData)
-{
-    CloseFileSelector();
-
-    if (!eventData["OK"].GetBool())
-    {
-        resourcePickType = 0;
-        return;
-    }
-
-    // Check if another component was selected in the meanwhile
-    if (resourcePickType == 0)
-        return;
-
-    /*
-    ResourceEditorData@ data = resourceEditors[resourcePickType - ATTR_EDITOR_RESOURCE];
-    resourcePickType = 0;
-
-    ListView@ list = nodeWindow.GetChild("AttributeList", true);
-    LineEdit@ attrEdit = list.GetChild(resourcePickEditorName, true);
-    if (attrEdit is null)
-        return;
-
-    // Validate the resource. It must come from within the scene resource directory, and be loaded successfully
-    String resourceName = eventData["FileName"].GetString();
-    if (resourceName.find(sceneResourcePath) != 0)
-        return;
-    data.lastPath = GetPath(resourceName);
-
-    resourceName = resourceName.substr(sceneResourcePath.length());
-
-    Resource@ res = cache.GetResource(data.resourceType, resourceName);
-    if (res is null)
-        return;
-
-    attrEdit.SetText(resourceName);
-    editComponentAttribute(attrEdit, false);
-    */
-}
-
-void PickResourceCanceled()
-{
-    if (resourcePickType != 0)
-    {
-        resourcePickType = 0;
-        CloseFileSelector();
-    }
-}
-
 uint GetAttributeEditorCount(Serializable@ serializable)
 {
     uint count = 0;
@@ -730,3 +655,136 @@ void StoreAttributeEditorDirect(UIElement@ parent, Serializable@ serializable, u
     }
 }
 
+
+ResourcePicker@ GetResourcePicker(const String&in resourceType)
+{
+    for (uint i = 0; i < resourcePickers.length; ++i)
+    {
+        if (resourcePickers[i].resourceType.Compare(resourceType, false) == 0)
+            return resourcePickers[i];
+    }
+
+    return null;
+}
+
+void PickResource(StringHash eventType, VariantMap& eventData)
+{
+    if (uiFileSelector !is null)
+        return;
+
+    UIElement@ button = eventData["Element"].GetUIElement();
+    LineEdit@ attrEdit = button.parent.children[1];
+    // Note: nodes never contain resources. Therefore can assume the target is always a component
+    Component@ target = GetAttributeEditorTarget(attrEdit);
+    if (target is null)
+        return;
+
+    resourcePickIndex = attrEdit.vars["Index"].GetUInt();
+    resourcePickSubIndex = attrEdit.vars["SubIndex"].GetUInt();
+    AttributeInfo info = target.attributeInfos[resourcePickIndex];
+
+    if (info.type == VAR_RESOURCEREF)
+    {
+        String resourceType = GetTypeName(target.attributes[resourcePickIndex].GetResourceRef().type);
+        // Hack: if the resource is a light's shape texture, change resource type according to light type
+        // (TextureCube for point light)
+        if (info.name == "Light Shape Texture" && cast<Light>(target).lightType == LIGHT_POINT)
+            resourceType = "TextureCube";
+        @resourcePicker = GetResourcePicker(resourceType);
+    }
+    else if (info.type == VAR_RESOURCEREFLIST)
+    {
+        String resourceType = GetTypeName(target.attributes[resourcePickIndex].GetResourceRefList().type);
+        @resourcePicker = GetResourcePicker(resourceType);
+    }
+    else
+        @resourcePicker = null;
+
+    if (resourcePicker is null)
+        return;
+
+    resourcePickID = target.id;
+    String lastPath = resourcePicker.lastPath;
+    if (lastPath.empty)
+        lastPath = sceneResourcePath;
+    CreateFileSelector("Pick " + resourcePicker.resourceType, "OK", "Cancel", lastPath, resourcePicker.filters, resourcePicker.lastFilter);
+    SubscribeToEvent(uiFileSelector, "FileSelected", "PickResourceDone");
+}
+
+void PickResourceDone(StringHash eventType, VariantMap& eventData)
+{
+    // Store filter and directory for next time
+    if (resourcePicker !is null)
+    {
+        resourcePicker.lastPath = uiFileSelector.path;
+        resourcePicker.lastFilter = uiFileSelector.filterIndex;
+    }
+
+    CloseFileSelector();
+
+    if (!eventData["OK"].GetBool())
+    {
+        resourcePickID = 0;
+        @resourcePicker = null;
+        return;
+    }
+
+    Component@ target = editorScene.GetComponentByID(resourcePickID);
+    if (target is null || resourcePicker is null)
+        return;
+
+    // Validate the resource. It must come from within a registered resource directory, and be loaded successfully
+    String resourceName = eventData["FileName"].GetString();
+    Array<String>@ resourceDirs = cache.resourceDirs;
+    Resource@ res;
+    for (uint i = 0; i < resourceDirs.length; ++i)
+    {
+        if (!resourceName.ToLower().StartsWith(resourceDirs[i].ToLower()))
+            continue;
+        resourceName = resourceName.Substring(resourceDirs[i].length);
+        res = cache.GetResource(resourcePicker.resourceType, resourceName);
+        break;
+    }
+    if (res is null)
+        return;
+
+    AttributeInfo info = target.attributeInfos[resourcePickIndex];
+    if (info.type == VAR_RESOURCEREF)
+    {
+        ResourceRef ref = target.attributes[resourcePickIndex].GetResourceRef();
+        ref.type = ShortStringHash(resourcePicker.resourceType);
+        ref.id = StringHash(resourceName);
+        target.attributes[resourcePickIndex] = Variant(ref);
+    }
+    else if (info.type == VAR_RESOURCEREFLIST)
+    {
+        ResourceRefList refList = target.attributes[resourcePickIndex].GetResourceRefList();
+        if (resourcePickSubIndex < refList.length)
+        {
+            refList.ids[resourcePickSubIndex] = StringHash(resourceName);
+            target.attributes[resourcePickIndex] = Variant(refList);
+        }
+    }
+
+    UpdateAttributes(false);
+
+    resourcePickID = 0;
+    @resourcePicker = null;
+}
+
+void PickResourceCanceled()
+{
+    if (resourcePickID != 0)
+    {
+        resourcePickID = 0;
+        @resourcePicker = null;
+        CloseFileSelector();
+    }
+}
+
+void OpenResource(StringHash eventType, VariantMap& eventData)
+{
+    UIElement@ button = eventData["Element"].GetUIElement();
+    LineEdit@ attrEdit = button.parent.children[1];
+    fileSystem.SystemOpen(sceneResourcePath + attrEdit.text.Trimmed(), "");
+}

+ 3 - 0
Docs/ScriptAPI.dox

@@ -38,6 +38,7 @@
 - void UnsubscribeFromEvents(Object@)
 - void UnsubscribeFromAllEvents()
 - Object@ GetEventSender()
+- const String& GetTypeName(ShortStringHash)
 - void Print(const String&)
 - void Print(int)
 - void Print(uint)
@@ -223,6 +224,8 @@ Methods:<br>
 - int Find(uint8, uint arg1 = 0) const
 - int FindLast(const String&, uint arg1 = 0xffffffff) const
 - int FindLast(uint8, uint arg1 = 0xffffffff) const
+- bool StartsWith(const String&) const
+- bool EndsWith(const String&) const
 - String Substring(uint) const
 - String Substring(uint, uint) const
 - String ToUpper() const

+ 6 - 0
Engine/Engine/CoreAPI.cpp

@@ -610,6 +610,11 @@ static Object* GetEventSender()
     return GetScriptContext()->GetEventSender();
 }
 
+static const String& GetTypeName(ShortStringHash type)
+{
+    return GetScriptContext()->GetTypeName(type);
+}
+
 void RegisterObject(asIScriptEngine* engine)
 {
     engine->RegisterObjectType("AttributeInfo", sizeof(AttributeInfo), asOBJ_VALUE | asOBJ_APP_CLASS_CDA);
@@ -634,6 +639,7 @@ void RegisterObject(asIScriptEngine* engine)
     engine->RegisterGlobalFunction("void UnsubscribeFromEvents(Object@+)", asFUNCTION(UnsubscribeFromSenderEvents), asCALL_CDECL);
     engine->RegisterGlobalFunction("void UnsubscribeFromAllEvents()", asFUNCTION(UnsubscribeFromAllEvents), asCALL_CDECL);
     engine->RegisterGlobalFunction("Object@+ GetEventSender()", asFUNCTION(GetEventSender), asCALL_CDECL);
+    engine->RegisterGlobalFunction("const String& GetTypeName(ShortStringHash)", asFUNCTION(GetTypeName), asCALL_CDECL);
 }
 
 void RegisterCoreAPI(asIScriptEngine* engine)

+ 10 - 8
Engine/Script/Addons.cpp

@@ -738,13 +738,13 @@ void RegisterString(asIScriptEngine *engine)
     engine->RegisterObjectType("String", sizeof(String), asOBJ_VALUE | asOBJ_APP_CLASS_CDA);
     engine->RegisterStringFactory("String", asFUNCTION(StringFactory), asCALL_CDECL);
     engine->RegisterObjectBehaviour("String", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(ConstructString), asCALL_CDECL_OBJLAST);
-    engine->RegisterObjectBehaviour("String", asBEHAVE_CONSTRUCT, "void f(const String& in)", asFUNCTION(ConstructStringCopy), asCALL_CDECL_OBJLAST);
+    engine->RegisterObjectBehaviour("String", asBEHAVE_CONSTRUCT, "void f(const String&in)", asFUNCTION(ConstructStringCopy), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectBehaviour("String", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(DestructString), asCALL_CDECL_OBJLAST);
-    engine->RegisterObjectMethod("String", "String& opAssign(const String& in)", asMETHODPR(String, operator =, (const String&), String&), asCALL_THISCALL);
-    engine->RegisterObjectMethod("String", "String& opAddAssign(const String& in)", asMETHODPR(String, operator +=, (const String&), String&), asCALL_THISCALL);
-    engine->RegisterObjectMethod("String", "bool opEquals(const String& in) const", asMETHODPR(String, operator ==, (const String&) const, bool), asCALL_THISCALL);
-    engine->RegisterObjectMethod("String", "int opCmp(const String& in) const", asFUNCTION(StringCmp), asCALL_CDECL_OBJFIRST);
-    engine->RegisterObjectMethod("String", "String opAdd(const String& in) const", asMETHODPR(String, operator +, (const String&) const, String), asCALL_THISCALL);
+    engine->RegisterObjectMethod("String", "String& opAssign(const String&in)", asMETHODPR(String, operator =, (const String&), String&), asCALL_THISCALL);
+    engine->RegisterObjectMethod("String", "String& opAddAssign(const String&in)", asMETHODPR(String, operator +=, (const String&), String&), asCALL_THISCALL);
+    engine->RegisterObjectMethod("String", "bool opEquals(const String&in) const", asMETHODPR(String, operator ==, (const String&) const, bool), asCALL_THISCALL);
+    engine->RegisterObjectMethod("String", "int opCmp(const String&in) const", asFUNCTION(StringCmp), asCALL_CDECL_OBJFIRST);
+    engine->RegisterObjectMethod("String", "String opAdd(const String&in) const", asMETHODPR(String, operator +, (const String&) const, String), asCALL_THISCALL);
     engine->RegisterObjectMethod("String", "uint8 &opIndex(uint)", asFUNCTION(StringCharAt), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("String", "const uint8 &opIndex(uint) const", asFUNCTION(StringCharAt), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("String", "void Replace(uint8, uint8)", asMETHODPR(String, Replace, (char, char), void), asCALL_THISCALL);
@@ -752,10 +752,12 @@ void RegisterString(asIScriptEngine *engine)
     engine->RegisterObjectMethod("String", "String Replaced(uint8, uint8) const", asMETHODPR(String, Replaced, (char, char) const, String), asCALL_THISCALL);
     engine->RegisterObjectMethod("String", "String Replaced(const String&in, const String&in) const", asMETHODPR(String, Replaced, (const String&, const String&) const, String), asCALL_THISCALL);
     engine->RegisterObjectMethod("String", "void Resize(uint)", asFUNCTION(StringResize), asCALL_CDECL_OBJLAST);
-    engine->RegisterObjectMethod("String", "int Find(const String& in, uint start = 0) const", asMETHODPR(String, Find, (const String&, unsigned) const, unsigned), asCALL_THISCALL);
+    engine->RegisterObjectMethod("String", "int Find(const String&in, uint start = 0) const", asMETHODPR(String, Find, (const String&, unsigned) const, unsigned), asCALL_THISCALL);
     engine->RegisterObjectMethod("String", "int Find(uint8, uint start = 0) const", asMETHODPR(String, Find, (char, unsigned) const, unsigned), asCALL_THISCALL);
-    engine->RegisterObjectMethod("String", "int FindLast(const String& in, uint start = 0xffffffff) const", asMETHODPR(String, FindLast, (const String&, unsigned) const, unsigned), asCALL_THISCALL);
+    engine->RegisterObjectMethod("String", "int FindLast(const String&in, uint start = 0xffffffff) const", asMETHODPR(String, FindLast, (const String&, unsigned) const, unsigned), asCALL_THISCALL);
     engine->RegisterObjectMethod("String", "int FindLast(uint8, uint start = 0xffffffff) const", asMETHODPR(String, FindLast, (char, unsigned) const, unsigned), asCALL_THISCALL);
+    engine->RegisterObjectMethod("String", "bool StartsWith(const String&in) const", asMETHOD(String, StartsWith), asCALL_THISCALL);
+    engine->RegisterObjectMethod("String", "bool EndsWith(const String&in) const", asMETHOD(String, EndsWith), asCALL_THISCALL);
     engine->RegisterObjectMethod("String", "String Substring(uint) const", asMETHODPR(String, Substring, (unsigned) const, String), asCALL_THISCALL);
     engine->RegisterObjectMethod("String", "String Substring(uint, uint) const", asMETHODPR(String, Substring, (unsigned, unsigned) const, String), asCALL_THISCALL);
     engine->RegisterObjectMethod("String", "String ToUpper() const", asMETHOD(String, ToUpper), asCALL_THISCALL);