Browse Source

Merge branch 'master' of https://github.com/AtomicGameEngine/AtomicGameEngine into RED-ATOMIC-HAXE

rsredsq 10 years ago
parent
commit
41d2bb7bc0

+ 15 - 5
Script/AtomicEditor/ui/frames/ProjectFrame.ts

@@ -254,12 +254,22 @@ class ProjectFrame extends ScriptWidget {
         if (dragObject.object && dragObject.object.typeName == "Node") {
 
             var node = <Atomic.Node> dragObject.object;
-            var destFilename = Atomic.addTrailingSlash(asset.path);
-            destFilename += node.name + ".prefab";
 
-            var file = new Atomic.File(destFilename, Atomic.FILE_WRITE);
-            node.saveXML(file);
-            file.close();
+            var prefabComponent = <Atomic.PrefabComponent> node.getComponent("PrefabComponent");
+
+            if (prefabComponent) {
+
+              prefabComponent.savePrefab();
+
+            }
+            else {
+                var destFilename = Atomic.addTrailingSlash(asset.path);
+                destFilename += node.name + ".prefab";
+
+                var file = new Atomic.File(destFilename, Atomic.FILE_WRITE);
+                node.saveXML(file);
+                file.close();
+            }
 
             this.rescan(asset);
 

+ 3 - 161
Script/AtomicEditor/ui/frames/inspector/ComponentInspector.ts

@@ -123,7 +123,8 @@ class ComponentInspector extends Atomic.UISection {
 
 
         if (component.typeName == "JSComponent") {
-            this.addJSComponentUI(attrsVerticalLayout);
+            // auto expand JSComponents
+            this.value = 1;
         }
 
         if (component.typeName == "TileMap2D") {
@@ -135,10 +136,6 @@ class ComponentInspector extends Atomic.UISection {
             this.addModelUI(attrsVerticalLayout, component.typeName);
         }
 
-        if (component.typeName == "SoundSource" || component.typeName == "SoundSource3D") {
-            this.addSoundSourceUI(attrsVerticalLayout, component.typeName);
-        }
-
         if (component.typeName == "StaticSprite2D" || component.typeName == "AnimatedSprite2D") {
             this.addSpriteUI(attrsVerticalLayout, component.typeName);
         }
@@ -255,176 +252,21 @@ class ComponentInspector extends Atomic.UISection {
     addModelUI(layout: Atomic.UILayout, typeName: string) {
 
         var staticModel = <Atomic.StaticModel> this.component;
-        var cacheModel = staticModel.model;
-
-        var o = InspectorUtils.createAttrEditFieldWithSelectButton("Model", layout);
-        var field = o.editField;
-        field.readOnly = true;
-
-        var select = o.selectButton;
-
-        select.onClick = () => {
-
-            EditorUI.getModelOps().showResourceSelection("Select Model", "ModelImporter", function(asset: ToolCore.Asset) {
-
-                staticModel.model = <Atomic.Model> Atomic.cache.getResource("Model", asset.cachePath + ".mdl");
-                field.text = asset.name;
-
-            });
-
-        }
-
-        if (cacheModel) {
-
-            var asset = ToolCore.assetDatabase.getAssetByCachePath(cacheModel.name);
-
-            if (asset) {
-
-                field.text = asset.name;
-
-            }
-
-        }
-
-        // handle dropping of model on field
-        field.subscribeToEvent(field, "DragEnded", (ev: Atomic.DragEndedEvent) => {
-
-            if (ev.target == field) {
-
-                var importer = this.acceptAssetDrag("ModelImporter", ev);
-
-                if (importer) {
-
-                    var modelImporter = <ToolCore.ModelImporter> importer;
-                    var asset = modelImporter.asset;
-
-                    // the model itself, not the node XML
-                    var model = <Atomic.Model> Atomic.cache.getResource("Model", asset.cachePath + ".mdl");
-
-                    if (model) {
-
-                        staticModel.model = model;
-                        ev.target.text = asset.name;
-
-                    }
-                }
-            }
-
-        });
 
         var numGeometries = staticModel.numGeometries;
         if (typeName == "Skybox") {
             numGeometries = 1;
         }
 
-        for (var x = 0; x < staticModel.numGeometries; x++) {
+        for (var x = 0; x < numGeometries; x++) {
 
             this.createMaterialClosure(layout, staticModel, x);
 
-
         }
 
 
     }
 
-    addJSComponentUI(layout: Atomic.UILayout) {
-
-        var js = <Atomic.JSComponent> this.component;
-
-        // expand prefab
-        this.value = 1;
-
-        var o = InspectorUtils.createAttrEditFieldWithSelectButton("Script", layout);
-        var field = o.editField;
-        field.readOnly = true;
-        field.text = js.componentFile ? js.componentFile.name : "";
-
-        var select = o.selectButton;
-
-        select.onClick = () => {
-
-            EditorUI.getModelOps().showResourceSelection("Select JSComponent Script", "JavascriptImporter", function(asset: ToolCore.Asset) {
-
-                js.componentFile = <Atomic.JSComponentFile> Atomic.cache.getResource("JSComponentFile", asset.path);
-
-                if (js.componentFile)
-                    field.text = js.componentFile.name;
-
-            });
-
-        }
-
-        // handle dropping of component on field
-        field.subscribeToEvent(field, "DragEnded", (ev: Atomic.DragEndedEvent) => {
-
-            if (ev.target == field) {
-
-                var importer = this.acceptAssetDrag("JavascriptImporter", ev);
-
-                if (importer) {
-
-                    var jsImporter = <ToolCore.JavascriptImporter> importer;
-
-                    if (jsImporter.isComponentFile()) {
-
-                        js.componentFile = <Atomic.JSComponentFile> Atomic.cache.getResource("JSComponentFile", importer.asset.path);
-                        if (js.componentFile)
-                            ev.target.text = js.componentFile.name;
-
-                    }
-
-                }
-            }
-
-        });
-
-
-    }
-
-
-    addSoundSourceUI(layout: Atomic.UILayout, typeName: string) {
-
-        var sndSource = <Atomic.SoundSource> this.component;
-
-        var o = InspectorUtils.createAttrEditFieldWithSelectButton("Sound", layout);
-        var field = o.editField;
-        field.readOnly = true;
-        field.text = sndSource.sound ? sndSource.sound.name : "";
-
-        var select = o.selectButton;
-
-        select.onClick = () => {
-
-            EditorUI.getModelOps().showResourceSelection("Select Sound", "AudioImporter", function(asset: ToolCore.Asset) {
-
-                sndSource.sound = <Atomic.Sound> Atomic.cache.getResource("Sound", asset.path);
-                if (sndSource.sound)
-                    field.text = sndSource.sound.name;
-
-            });
-
-        }
-
-        // handle dropping of component on field
-        field.subscribeToEvent(field, "DragEnded", (ev: Atomic.DragEndedEvent) => {
-
-            if (ev.target == field) {
-
-                var importer = this.acceptAssetDrag("AudioImporter", ev);
-
-                if (importer) {
-
-                    sndSource.sound = <Atomic.Sound> Atomic.cache.getResource("Sound", importer.asset.path);
-                    if (sndSource.sound)
-                        field.text = sndSource.sound.name;
-
-                }
-            }
-
-        });
-
-
-    }
 
     addSpriteUI(layout: Atomic.UILayout, typeName: string) {
 

+ 107 - 0
Script/AtomicEditor/ui/frames/inspector/DataBinding.ts

@@ -1,3 +1,6 @@
+import InspectorUtils = require("./InspectorUtils");
+import EditorUI = require("ui/EditorUI");
+
 class DataBinding {
 
     constructor(object: Atomic.Serializable, attrInfo: Atomic.AttributeInfo, widget: Atomic.UIWidget) {
@@ -145,6 +148,95 @@ class DataBinding {
                 layout.addChild(select);
             }
 
+        } else if (attrInfo.type == Atomic.VAR_RESOURCEREF && attrInfo.resourceTypeName) {
+
+            var importerName = ToolCore.assetDatabase.getResourceImporterName(attrInfo.resourceTypeName);
+
+            if (importerName) {
+
+                var parent = new Atomic.UILayout();
+                var o = InspectorUtils.createAttrEditFieldWithSelectButton("", parent);
+
+                parent.layoutSize = Atomic.UI_LAYOUT_SIZE_AVAILABLE;
+                parent.gravity = Atomic.UI_GRAVITY_LEFT_RIGHT;
+                parent.layoutDistribution = Atomic.UI_LAYOUT_DISTRIBUTION_GRAVITY;
+
+
+                var lp = new Atomic.UILayoutParams();
+                lp.width = 140;
+                o.editField.layoutParams = lp;
+                o.editField.readOnly = true;
+
+                // stuff editfield in so can be reference
+                parent["editField"] = o.editField;
+
+                var selectButton = o.selectButton;
+
+                selectButton.onClick = () => {
+
+                    EditorUI.getModelOps().showResourceSelection("Select " + attrInfo.resourceTypeName + " Resource", importerName, function(asset: ToolCore.Asset) {
+
+                        var resource = asset.resource;
+
+                        object.setAttribute(attrInfo.name, resource);
+
+                        if (resource) {
+
+                            // use the asset name instead of the cache name
+                            if (asset.importer.requiresCacheFile())
+                                o.editField.text = asset.name;
+                            else
+                                o.editField.text = resource.name;
+                        }
+                        else
+                            o.editField.text = "";
+
+
+                    });
+
+                }
+
+                // handle dropping of component on field
+                o.editField.subscribeToEvent(o.editField, "DragEnded", (ev: Atomic.DragEndedEvent) => {
+
+                    if (ev.target == o.editField) {
+
+                        var dragObject = ev.dragObject;
+
+                        var importer;
+
+                        if (dragObject.object && dragObject.object.typeName == "Asset") {
+
+                            var asset = <ToolCore.Asset> dragObject.object;
+
+                            if (asset.importerTypeName == importerName) {
+                                importer = asset.importer;
+                            }
+
+                        }
+
+                        if (importer) {
+
+                            var resource = asset.resource;
+                            object.setAttribute(attrInfo.name, resource);
+                            if (resource) {
+                                // use the asset name instead of the cache name
+                                if (asset.importer.requiresCacheFile())
+                                    o.editField.text = asset.name;
+                                else
+                                    o.editField.text = resource.name;
+                            }
+                            else
+                                o.editField.text = "";
+
+                        }
+                    }
+
+                });
+
+                widget = parent;
+            }
+
         }
 
         if (widget) {
@@ -238,6 +330,20 @@ class DataBinding {
                     select.value = value[i];
             }
 
+        } else if (attrInfo.type == Atomic.VAR_RESOURCEREF && attrInfo.resourceTypeName) {
+
+            // for cached resources, use the asset name, otherwise use the resource path name
+            var resource = <Atomic.Resource> object.getAttribute(attrInfo.name);
+            var text = "";
+            if (resource) {
+                text = resource.name;
+                var asset = ToolCore.assetDatabase.getAssetByCachePath(resource.name);
+                if (asset)
+                  text = asset.name;
+            }
+
+            widget["editField"].text = text;
+
         }
 
         this.widgetLocked = false;
@@ -332,6 +438,7 @@ class DataBinding {
 
     }
 
+
     handleWidgetEvent(ev: Atomic.UIWidgetEvent): boolean {
 
         if (this.objectLocked)

+ 4 - 2
Script/AtomicEditor/ui/frames/inspector/InspectorUtils.ts

@@ -84,8 +84,10 @@ class InspectorUtils {
     var attrLayout = new Atomic.UILayout();
     attrLayout.layoutDistribution = Atomic.UI_LAYOUT_DISTRIBUTION_POSITION_LEFT_TOP;
 
-    var _name = InspectorUtils.createAttrName(name);
-    attrLayout.addChild(_name);
+    if (name) {
+      var _name = InspectorUtils.createAttrName(name);
+      attrLayout.addChild(_name);
+    }
 
     var fieldLayout = new Atomic.UILayout();
     fieldLayout.layoutDistribution = Atomic.UI_LAYOUT_DISTRIBUTION_POSITION_LEFT_TOP;

+ 1 - 0
Script/TypeScript/AtomicWork.d.ts

@@ -160,6 +160,7 @@ declare module Atomic {
         mode: number; // AM_*
         defaultValue: string;
         enumNames: string[];
+        resourceTypeName: string;
 
     }
 

+ 10 - 0
Script/TypeScript/ToolCore.d.ts

@@ -245,6 +245,7 @@ declare module ToolCore {
       extension: string;
       relativePath: string;
       cachePath: string;
+      resource: Atomic.Resource;
       importerType: string;
       importerTypeName: string;
       importer: AssetImporter;
@@ -266,6 +267,7 @@ declare module ToolCore {
       // Get the path relative to project
       getRelativePath(): string;
       getCachePath(): string;
+      getResource(): Atomic.Resource;
       getImporterType(): string;
       getImporterTypeName(): string;
       getImporter(): AssetImporter;
@@ -299,6 +301,7 @@ declare module ToolCore {
       getCachePath(): string;
       deleteAsset(asset: Asset): void;
       scan(): void;
+      getResourceImporterName(resourceTypeName: string): string;
       getDotAssetFilename(path: string): string;
       getFolderAssets(folder:string):ToolCore.Asset[];
       getAssetsByImporterType(type:string):ToolCore.Asset[];
@@ -308,6 +311,7 @@ declare module ToolCore {
    export class AssetImporter extends Atomic.AObject {
 
       asset: Asset;
+      resource: Atomic.Resource;
 
       // Construct.
       constructor(asset: Asset);
@@ -315,6 +319,7 @@ declare module ToolCore {
       setDefaults(): void;
       preload(): boolean;
       getAsset(): Asset;
+      getResource(): Atomic.Resource;
       requiresCacheFile(): boolean;
 
    }
@@ -330,11 +335,14 @@ declare module ToolCore {
 
    export class JavascriptImporter extends AssetImporter {
 
+      resource: Atomic.Resource;
+
       // Construct.
       constructor(asset: Asset);
 
       setDefaults(): void;
       isComponentFile(): boolean;
+      getResource(): Atomic.Resource;
 
    }
 
@@ -370,6 +378,7 @@ declare module ToolCore {
       scale: number;
       importAnimations: boolean;
       animationCount: number;
+      resource: Atomic.Resource;
 
       // Construct.
       constructor(asset: Asset);
@@ -381,6 +390,7 @@ declare module ToolCore {
       setImportAnimations(importAnimations: boolean): void;
       getAnimationCount(): number;
       setAnimationCount(count: number): void;
+      getResource(): Atomic.Resource;
       getAnimationInfo(index: number): AnimationImportInfo;
 
    }

+ 1 - 1
Source/Atomic/Atomic2D/CollisionShape2D.cpp

@@ -285,7 +285,7 @@ void CollisionShape2D::OnNodeSet(Node* node)
             rigidBody_->AddCollisionShape2D(this);
         }
         else
-            LOGERROR("No right body component in node, can not create collision shape");
+            LOGERROR("No rigid body component in node, can not create collision shape");
     }
 }
 

+ 1 - 1
Source/Atomic/Atomic2D/Constraint2D.cpp

@@ -130,7 +130,7 @@ void Constraint2D::OnNodeSet(Node* node)
         ownerBody_ = node->GetComponent<RigidBody2D>();
         if (!ownerBody_)
         {
-            LOGERROR("No right body component in node, can not create constraint");
+            LOGERROR("No rigid body component in node, can not create constraint");
             return;
         }
     }

+ 15 - 1
Source/Atomic/Scene/PrefabComponent.cpp

@@ -6,6 +6,7 @@
 #include <Atomic/Resource/ResourceEvents.h>
 
 #include <Atomic/Physics/RigidBody.h>
+#include <Atomic/Atomic2D/AnimatedSprite2D.h>
 
 #include "PrefabEvents.h"
 #include "PrefabComponent.h"
@@ -114,18 +115,31 @@ void PrefabComponent::BreakPrefab()
     // flip temporary root children and components to break prefab
     const Vector<SharedPtr<Component>>& rootComponents = node_->GetComponents();
     const Vector<SharedPtr<Node> >& children = node_->GetChildren();
+    PODVector<Node*> filterNodes;
 
     for (unsigned i = 0; i < rootComponents.Size(); i++)
     {
         if (rootComponents[i]->IsTemporary())
         {
             rootComponents[i]->SetTemporary(false);
+
+            // Animated sprites contain a temporary node we don't want to save in the prefab
+            // it would be nice if this was general purpose because have to test this when
+            // saving a prefab as well
+
+            if (rootComponents[i]->GetType() == AnimatedSprite2D::GetTypeStatic())
+            {
+                AnimatedSprite2D* asprite = (AnimatedSprite2D*) rootComponents[i].Get();
+                if (asprite->GetRootNode())
+                    filterNodes.Push(asprite->GetRootNode());
+            }
+
         }
     }
 
     for (unsigned i = 0; i < children.Size(); i++)
     {
-        if (children[i]->IsTemporary())
+        if (children[i]->IsTemporary() && !filterNodes.Contains(children[i].Get()))
         {
             children[i]->SetTemporary(false);
         }

+ 23 - 0
Source/AtomicJS/Javascript/JSAPI.cpp

@@ -2,6 +2,9 @@
 // Please see LICENSE.md in repository root for license information
 // https://github.com/AtomicGameEngine/AtomicGameEngine
 
+#include <Atomic/Core/Context.h>
+#include <Atomic/Resource/ResourceCache.h>
+
 #include "JSAPI.h"
 #include "JSVM.h"
 
@@ -292,6 +295,16 @@ void js_to_variant(duk_context* ctx, int variantIdx, Variant &v)
         return;
     }
 
+    // object check after array
+    if (duk_is_object(ctx, variantIdx))
+    {
+        RefCounted* o = js_to_class_instance<RefCounted>(ctx, variantIdx, 0);
+        if (o)
+            v = o;
+        return;
+    }
+
+
 }
 
 
@@ -380,6 +393,9 @@ void js_push_variant(duk_context *ctx, const Variant& v)
     Vector3 vector3 = Vector3::ZERO;
     Vector4 vector4 = Vector4::ZERO;
     Color color = Color::BLACK;
+    Resource* resource = NULL;
+    ResourceCache* cache = NULL;
+    ResourceRef resourceRef;
 
     switch (type)
     {
@@ -419,6 +435,13 @@ void js_push_variant(duk_context *ctx, const Variant& v)
 
         break;
 
+    case VAR_RESOURCEREF:
+        resourceRef = v.GetResourceRef();
+        cache = JSVM::GetJSVM(ctx)->GetContext()->GetSubsystem<ResourceCache>();
+        resource = cache->GetResource(resourceRef.type_, resourceRef.name_);
+        js_push_class_object_instance(ctx, resource);
+        break;
+
     case VAR_BOOL:
         duk_push_boolean(ctx, v.GetBool() ? 1 : 0);
         break;

+ 48 - 17
Source/AtomicJS/Javascript/JSComponentFile.cpp

@@ -203,8 +203,8 @@ bool JSComponentFile::BeginLoad(Deserializer& source)
     if (!InitModule())
         return false;
 
-    // TODO: cache these for player builds
-    // FIXME: this won't work with obfusication or minimization
+    // TODO: move the inspector field parsing to the JavascriptImporter
+    // which will work with obfusication, minimization, or bytecode dumps
 
     unsigned dataSize = source.GetSize();
     if (!dataSize && !source.GetName().Empty())
@@ -234,7 +234,7 @@ bool JSComponentFile::BeginLoad(Deserializer& source)
 
             if (line.StartsWith("inspectorFields"))
             {
-                eval = line;
+                eval = line + "\n";
                 if (line.Contains("}"))
                 {
                     valid = true;
@@ -243,7 +243,7 @@ bool JSComponentFile::BeginLoad(Deserializer& source)
             }
             else if (line.StartsWith("this.inspectorFields"))
             {
-                eval = line.Substring(5);
+                eval = line.Substring(5) + "\n";
                 if (line.Contains("}"))
                 {
                     valid = true;
@@ -252,7 +252,7 @@ bool JSComponentFile::BeginLoad(Deserializer& source)
             }
             else if (line.StartsWith("var inspectorFields"))
             {
-                eval = line.Substring(4);
+                eval = line.Substring(4) + "\n";
                 if (line.Contains("}"))
                 {
                     valid = true;
@@ -263,7 +263,7 @@ bool JSComponentFile::BeginLoad(Deserializer& source)
         }
         else
         {
-            eval += line;
+            eval += line + "\n";
         }
 
         if (line.Contains("}") && eval.Length())
@@ -321,23 +321,54 @@ bool JSComponentFile::BeginLoad(Deserializer& source)
                     }
                     else if (duk_is_array(ctx, -1))
                     {
-                        if (duk_get_length(ctx, -1) > 0)
+                        int length = duk_get_length(ctx, -1);
+
+                        if (length > 0)
                         {
+
                             duk_get_prop_index(ctx, -1, 0);
 
-                            // TODO: class types
-                            variantType = (VariantType) ((int)duk_require_number(ctx, -1));
+                            // resource ref detection
+                            if (duk_is_string(ctx, -1))
+                            {
+                                const char* classname = duk_to_string(ctx, -1);
 
-                            duk_pop(ctx);
-                        }
+                                duk_pop(ctx);
 
-                        if (duk_get_length(ctx, -1) > 1)
-                        {
-                            duk_get_prop_index(ctx, -1, 1);
-                            // default value
-                            js_to_variant(ctx, -1, defaultValue);
+                                const char* name = NULL;
+
+                                if (length > 1)
+                                {
+                                    duk_get_prop_index(ctx, -1, 1);
+                                    name = duk_require_string(ctx, -1);
+                                    duk_pop(ctx);
+
+                                }
+
+                                ResourceRef resourceRef(classname);
+                                if (name)
+                                    resourceRef.name_ = name;
+
+                                variantType = VAR_RESOURCEREF;
+                                defaultValue = resourceRef;
+
+                            }
+                            else
+                            {
+                                variantType = (VariantType) ((int)duk_require_number(ctx, -1));
+
+                                duk_pop(ctx);
+
+                                if (length > 1)
+                                {
+                                    duk_get_prop_index(ctx, -1, 1);
+                                    // default value
+                                    js_to_variant(ctx, -1, defaultValue);
+                                    duk_pop(ctx);
+                                }
+
+                            }
 
-                            duk_pop(ctx);
                         }
 
                     }

+ 1 - 0
Source/AtomicJS/Javascript/JSComponentFile.h

@@ -44,6 +44,7 @@ public:
     static void RegisterObject(Context* context);
 
     const HashMap<String, VariantType>& GetFields() const { return fields_; }
+    const VariantMap& GetDefaultFieldValues() const { return defaultFieldValues_; }
 
     /// Load resource from stream. May be called from a worker thread. Return true if successful.
     virtual bool BeginLoad(Deserializer& source);

+ 4 - 1
Source/AtomicJS/Javascript/JSScene.cpp

@@ -222,11 +222,14 @@ static int Node_CreateChildPrefab(duk_context* ctx)
     duk_push_this(ctx);
     Node* parent = js_to_class_instance<Node>(ctx, -1, 0);
 
-    Node* node = parent->CreateChild(childName);
+    Node* node = parent->CreateChild();
 
     PrefabComponent* prefabComponent = node->CreateComponent<PrefabComponent>();
     prefabComponent->SetPrefabGUID(prefabName);
 
+    // override what node name is in prefab
+    node->SetName(childName);
+
     js_push_class_object_instance(ctx, node, "Node");
 
     return 1;

+ 69 - 0
Source/AtomicJS/Javascript/JSSceneSerializable.cpp

@@ -108,6 +108,22 @@ static int Serializable_SetAttribute(duk_context* ctx)
     {
         v = (int) v.GetFloat();
     }
+    else if (variantType == VAR_RESOURCEREF)
+    {
+        RefCounted* ref = v.GetPtr();
+
+        if (ref && ref->IsObject())
+        {
+            Object* o = (Object*) ref;
+
+            // TODO: calling code must ensure we are a resource, can this be done here?
+            Resource* resource = (Resource*) o;
+
+            v = ResourceRef(resource->GetType(), resource->GetName());
+
+        }
+
+    }
 
     if (isAttr)
     {
@@ -182,6 +198,25 @@ static int Serializable_GetAttribute(duk_context* ctx)
     return 1;
 }
 
+static const String& GetResourceRefClassName(Context* context, const ResourceRef& ref)
+{
+    const HashMap<StringHash, SharedPtr<ObjectFactory>>& factories = context->GetObjectFactories();
+
+    HashMap<StringHash, SharedPtr<ObjectFactory>>::ConstIterator itr = factories.Begin();
+
+    while (itr != factories.End())
+    {
+        if (itr->first_ == ref.type_)
+        {
+            return itr->second_->GetTypeName();
+        }
+
+        itr++;
+    }
+
+    return String::EMPTY;
+}
+
 
 static int Serializable_GetAttributes(duk_context* ctx)
 {
@@ -218,6 +253,22 @@ static int Serializable_GetAttributes(duk_context* ctx)
             duk_push_number(ctx, (double) attr->type_);
             duk_put_prop_string(ctx, -2, "type");
 
+            if (attr->type_ == VAR_RESOURCEREF)
+            {
+                if (attr->defaultValue_.GetType() == VAR_RESOURCEREF)
+                {
+                    const ResourceRef& ref = attr->defaultValue_.GetResourceRef();
+                    const String& typeName = GetResourceRefClassName(serial->GetContext(), ref);
+
+                    if (typeName.Length())
+                    {
+                        duk_push_string(ctx, typeName.CString());
+                        duk_put_prop_string(ctx, -2, "resourceTypeName");
+
+                    }
+                }
+            }
+
             duk_push_string(ctx, attr->name_.CString());
             duk_put_prop_string(ctx, -2, "name");
 
@@ -260,6 +311,8 @@ static int Serializable_GetAttributes(duk_context* ctx)
 
         if (file)
         {
+
+            const VariantMap& defaultFieldValues = file->GetDefaultFieldValues();
             const HashMap<String, VariantType>& fields =  file->GetFields();
 
             if (fields.Size())
@@ -272,6 +325,22 @@ static int Serializable_GetAttributes(duk_context* ctx)
                     duk_push_number(ctx, (double) itr->second_);
                     duk_put_prop_string(ctx, -2, "type");
 
+                    if (itr->second_ == VAR_RESOURCEREF && defaultFieldValues.Contains(itr->first_))
+                    {
+                        if (defaultFieldValues[itr->first_]->GetType() == VAR_RESOURCEREF)
+                        {
+                            const ResourceRef& ref = defaultFieldValues[itr->first_]->GetResourceRef();
+                            const String& typeName = GetResourceRefClassName(serial->GetContext(), ref);
+
+                            if (typeName.Length())
+                            {
+                                duk_push_string(ctx, typeName.CString());
+                                duk_put_prop_string(ctx, -2, "resourceTypeName");
+
+                            }
+                        }
+                    }
+
                     duk_push_string(ctx, itr->first_.CString());
                     duk_put_prop_string(ctx, -2, "name");
 

+ 8 - 0
Source/ToolCore/Assets/Asset.cpp

@@ -343,4 +343,12 @@ bool Asset::SetPath(const String& path)
 
 }
 
+Resource* Asset::GetResource()
+{
+    if (importer_)
+        return importer_->GetResource();
+
+    return 0;
+}
+
 }

+ 3 - 0
Source/ToolCore/Assets/Asset.h

@@ -2,6 +2,7 @@
 #pragma once
 
 #include <Atomic/Core/Object.h>
+#include <Atomic/Resource/Resource.h>
 
 #include "AssetImporter.h"
 
@@ -37,6 +38,8 @@ public:
     String GetRelativePath();
     String GetCachePath() const;
 
+    Resource* GetResource();
+
     const StringHash GetImporterType() { return importer_.Null() ? String::EMPTY : importer_->GetType(); }
     const String& GetImporterTypeName() { return importer_.Null() ? String::EMPTY : importer_->GetTypeName(); }
 

+ 22 - 0
Source/ToolCore/Assets/AssetDatabase.cpp

@@ -92,6 +92,9 @@ Asset* AssetDatabase::GetAssetByCachePath(const String& cachePath)
 {
     List<SharedPtr<Asset>>::ConstIterator itr = assets_.Begin();
 
+    if (!cachePath.StartsWith("Cache/"))
+        return 0;
+
     String cacheFilename = GetFileName(cachePath);
 
     while (itr != assets_.End())
@@ -478,5 +481,24 @@ void AssetDatabase::HandleFileChanged(StringHash eventType, VariantMap& eventDat
     }
 }
 
+String AssetDatabase::GetResourceImporterName(const String& resourceTypeName)
+{
+    // TODO: have resource type register themselves
+    if (resourceTypeToImporterType_.Empty())
+    {
+        resourceTypeToImporterType_["Sound"] = "AudioImporter";
+        resourceTypeToImporterType_["Model"] = "ModelImporter";
+        resourceTypeToImporterType_["JSComponentFile"] = "JavascriptImporter";
+
+
+    }
+
+    if (!resourceTypeToImporterType_.Contains(resourceTypeName))
+        return String::EMPTY;
+
+    return resourceTypeToImporterType_[resourceTypeName];
+
+}
+
 
 }

+ 4 - 0
Source/ToolCore/Assets/AssetDatabase.h

@@ -36,6 +36,8 @@ public:
 
     void GetFolderAssets(String folder, PODVector<Asset*>& assets) const;
 
+    String GetResourceImporterName(const String& resourceTypeName);
+
     void GetAssetsByImporterType(StringHash type, PODVector<Asset*>& assets) const;
 
     void GetDirtyAssets(PODVector<Asset*>& assets);
@@ -60,6 +62,8 @@ private:
     SharedPtr<Project> project_;
     List<SharedPtr<Asset>> assets_;
 
+    HashMap<StringHash, String> resourceTypeToImporterType_;
+
     Vector<String> usedGUID_;
 
 };

+ 2 - 0
Source/ToolCore/Assets/AssetImporter.h

@@ -34,6 +34,8 @@ public:
 
     Asset* GetAsset() { return asset_; }
 
+    virtual Resource* GetResource() { return 0; }
+
     bool RequiresCacheFile() const { return requiresCacheFile_; }
 
 protected:

+ 17 - 0
Source/ToolCore/Assets/JavascriptImporter.cpp

@@ -4,10 +4,13 @@
 #include <Atomic/Resource/ResourceCache.h>
 #include <Atomic/Resource/Image.h>
 
+#include <AtomicJS/Javascript/JSComponentFile.h>
+
 #include "Asset.h"
 #include "AssetDatabase.h"
 #include "JavascriptImporter.h"
 
+
 namespace ToolCore
 {
 
@@ -76,5 +79,19 @@ bool JavascriptImporter::SaveSettingsInternal()
     return true;
 }
 
+Resource* JavascriptImporter::GetResource()
+{
+    if (!isComponentFile_)
+        return 0;
+
+    ResourceCache* cache = GetSubsystem<ResourceCache>();
+
+    JSComponentFile* jsc = cache->GetResource<JSComponentFile>(asset_->GetPath());
+
+    return jsc;
+
+}
+
+
 
 }

+ 2 - 0
Source/ToolCore/Assets/JavascriptImporter.h

@@ -19,6 +19,8 @@ public:
 
     bool IsComponentFile() { return isComponentFile_; }
 
+    Resource* GetResource();
+
 protected:
 
     bool Import();

+ 11 - 0
Source/ToolCore/Assets/ModelImporter.cpp

@@ -7,6 +7,7 @@
 
 #include <Atomic/Atomic3D/AnimationController.h>
 #include <Atomic/Atomic3D/Animation.h>
+#include <Atomic/Atomic3D/Model.h>
 
 #include <Atomic/Resource/ResourceCache.h>
 
@@ -294,5 +295,15 @@ bool ModelImporter::SaveSettingsInternal()
     return true;
 }
 
+Resource* ModelImporter::GetResource()
+{
+    ResourceCache* cache = GetSubsystem<ResourceCache>();
+
+    Model* model = cache->GetResource<Model>(asset_->GetCachePath() + ".mdl");
+
+    return model;
+
+}
+
 
 }

+ 2 - 0
Source/ToolCore/Assets/ModelImporter.h

@@ -63,6 +63,8 @@ public:
     unsigned GetAnimationCount();
     void SetAnimationCount(unsigned count);
 
+    Resource* GetResource();
+
     AnimationImportInfo* GetAnimationInfo(unsigned index) { return animationInfo_[index]; }
 
 protected:

+ 19 - 3
Source/ToolCore/Assets/PrefabImporter.cpp

@@ -4,6 +4,7 @@
 #include <Atomic/Scene/Scene.h>
 #include <Atomic/Scene/PrefabEvents.h>
 #include <Atomic/Scene/PrefabComponent.h>
+#include <Atomic/Atomic2D/AnimatedSprite2D.h>
 #include <Atomic/IO/FileSystem.h>
 
 #include "Asset.h"
@@ -58,8 +59,9 @@ void PrefabImporter::HandlePrefabSave(StringHash eventType, VariantMap& eventDat
     const Vector<SharedPtr<Component>>& rootComponents = node->GetComponents();
     const Vector<SharedPtr<Node> >& children = node->GetChildren();
 
-    Vector<SharedPtr<Component>> tempComponents;
-    Vector<SharedPtr<Node>> tempChildren;
+    PODVector<Component*> tempComponents;
+    PODVector<Node*> tempChildren;
+    PODVector<Node*> filterNodes;
 
     for (unsigned i = 0; i < rootComponents.Size(); i++)
     {
@@ -67,15 +69,29 @@ void PrefabImporter::HandlePrefabSave(StringHash eventType, VariantMap& eventDat
         {
             rootComponents[i]->SetTemporary(false);
             tempComponents.Push(rootComponents[i]);
+
+            // Animated sprites contain a temporary node we don't want to save in the prefab
+            // it would be nice if this was general purpose because have to test this when
+            // breaking node as well
+            if (rootComponents[i]->GetType() == AnimatedSprite2D::GetTypeStatic())
+            {
+                AnimatedSprite2D* asprite = (AnimatedSprite2D*) rootComponents[i].Get();
+                if (asprite->GetRootNode())
+                    filterNodes.Push(asprite->GetRootNode());
+            }
+
         }
     }
 
     for (unsigned i = 0; i < children.Size(); i++)
     {
+        if (filterNodes.Contains(children[i].Get()))
+            continue;
+
         if (children[i]->IsTemporary())
         {
             children[i]->SetTemporary(false);
-            tempChildren.Push(children);
+            tempChildren.Push(children[i]);
         }
     }