Browse Source

Working on Animation Import

Josh Engebretson 10 years ago
parent
commit
d3c94a666c

+ 14 - 14
Data/AtomicEditor/Resources/EditorData/AtomicEditor/typescript/ui/inspector/ModelInspector.ts

@@ -18,14 +18,14 @@ class ModelInspector extends InspectorWidget {
 
 
     onApply() {
     onApply() {
 
 
-      this.importer.scale = Number(this.scaleEdit.text);
-      this.importer.startTime = Number(this.startTimeEdit.text);
-      this.importer.endTime = Number(this.endTimeEdit.text);
+        this.importer.scale = Number(this.scaleEdit.text);
+        //this.importer.startTime = Number(this.startTimeEdit.text);
+        //this.importer.endTime = Number(this.endTimeEdit.text);
 
 
-      this.importer.importAnimations = this.importAnimationBox.value ? true : false;
+        this.importer.importAnimations = this.importAnimationBox.value ? true : false;
 
 
-      this.importer.import(this.asset.guid);
-      this.asset.save();
+        this.importer.import(this.asset.guid);
+        this.asset.save();
 
 
     }
     }
 
 
@@ -50,10 +50,10 @@ class ModelInspector extends InspectorWidget {
         this.importAnimationBox.value = this.importer.importAnimations ? 1 : 0;
         this.importAnimationBox.value = this.importer.importAnimations ? 1 : 0;
 
 
         this.startTimeEdit = this.createAttrEditField("Start Time", animationLayout);
         this.startTimeEdit = this.createAttrEditField("Start Time", animationLayout);
-        this.startTimeEdit.text = this.importer.startTime.toString();
+        //this.startTimeEdit.text = this.importer.startTime.toString();
 
 
         this.endTimeEdit = this.createAttrEditField("End Time", animationLayout);
         this.endTimeEdit = this.createAttrEditField("End Time", animationLayout);
-        this.endTimeEdit.text = this.importer.endTime.toString();
+        //this.endTimeEdit.text = this.importer.endTime.toString();
 
 
         // apply button
         // apply button
         rootLayout.addChild(this.createApplyButton());
         rootLayout.addChild(this.createApplyButton());
@@ -61,15 +61,15 @@ class ModelInspector extends InspectorWidget {
     }
     }
 
 
     // model
     // model
-    scaleEdit:Atomic.UIEditField;
+    scaleEdit: Atomic.UIEditField;
 
 
     // animation
     // animation
-    startTimeEdit:Atomic.UIEditField;
-    endTimeEdit:Atomic.UIEditField;
-    importAnimationBox:Atomic.UICheckBox;
+    startTimeEdit: Atomic.UIEditField;
+    endTimeEdit: Atomic.UIEditField;
+    importAnimationBox: Atomic.UICheckBox;
 
 
-    asset:ToolCore.Asset;
-    importer:ToolCore.ModelImporter;
+    asset: ToolCore.Asset;
+    importer: ToolCore.ModelImporter;
 
 
 }
 }
 
 

+ 49 - 0
Source/Atomic/Atomic3D/AnimationController.cpp

@@ -66,6 +66,8 @@ void AnimationController::RegisterObject(Context* context)
     MIXED_ACCESSOR_ATTRIBUTE("Animations", GetAnimationsAttr, SetAnimationsAttr, VariantVector, Variant::emptyVariantVector, AM_FILE | AM_NOEDIT);
     MIXED_ACCESSOR_ATTRIBUTE("Animations", GetAnimationsAttr, SetAnimationsAttr, VariantVector, Variant::emptyVariantVector, AM_FILE | AM_NOEDIT);
     ACCESSOR_ATTRIBUTE("Network Animations", GetNetAnimationsAttr, SetNetAnimationsAttr, PODVector<unsigned char>, Variant::emptyBuffer, AM_NET | AM_LATESTDATA | AM_NOEDIT);
     ACCESSOR_ATTRIBUTE("Network Animations", GetNetAnimationsAttr, SetNetAnimationsAttr, PODVector<unsigned char>, Variant::emptyBuffer, AM_NET | AM_LATESTDATA | AM_NOEDIT);
     MIXED_ACCESSOR_ATTRIBUTE("Node Animation States", GetNodeAnimationStatesAttr, SetNodeAnimationStatesAttr, VariantVector, Variant::emptyVariantVector, AM_FILE | AM_NOEDIT);
     MIXED_ACCESSOR_ATTRIBUTE("Node Animation States", GetNodeAnimationStatesAttr, SetNodeAnimationStatesAttr, VariantVector, Variant::emptyVariantVector, AM_FILE | AM_NOEDIT);
+
+    ACCESSOR_ATTRIBUTE("Animation Resources", GetAnimationResourcesAttr, SetAnimationResourcesAttr, ResourceRefList, ResourceRefList(Animation::GetTypeStatic()), AM_FILE | AM_NOEDIT);
 }
 }
 
 
 void AnimationController::OnSetEnabled()
 void AnimationController::OnSetEnabled()
@@ -828,4 +830,51 @@ void AnimationController::HandleScenePostUpdate(StringHash eventType, VariantMap
     Update(eventData[P_TIMESTEP].GetFloat());
     Update(eventData[P_TIMESTEP].GetFloat());
 }
 }
 
 
+void AnimationController::AddAnimationResource(Animation* animation)
+{
+    if (!animation)
+        return;
+
+    SharedPtr<Animation> anim(animation);
+
+    if (!animationsResources_.Contains(anim))
+        animationsResources_.Push(anim);
+}
+
+void AnimationController::RemoveAnimationResource(Animation* animation)
+{
+    if (!animation)
+        return;
+
+    animationsResources_.Remove(SharedPtr<Animation>(animation));
+
+}
+
+void AnimationController::ClearAnimationResources()
+{
+    animationsResources_.Clear();
+}
+
+void AnimationController::SetAnimationResourcesAttr(const ResourceRefList& value)
+{
+    animationsResources_.Clear();
+
+    ResourceCache* cache = GetSubsystem<ResourceCache>();
+    for (unsigned i = 0; i < value.names_.Size(); ++i)
+    {
+        animationsResources_.Clear();
+        AddAnimationResource(cache->GetResource<Animation>(value.names_[i]));
+    }
+}
+
+const ResourceRefList& AnimationController::GetAnimationResourcesAttr() const
+{
+    animationsResourcesAttr_.names_.Resize(animationsResources_.Size());
+    for (unsigned i = 0; i < animationsResources_.Size(); ++i)
+        animationsResourcesAttr_.names_[i] = GetResourceName(animationsResources_[i]);
+
+    return animationsResourcesAttr_;
+}
+
+
 }
 }

+ 15 - 0
Source/Atomic/Atomic3D/AnimationController.h

@@ -171,6 +171,14 @@ public:
     /// Return node animation states attribute.
     /// Return node animation states attribute.
     VariantVector GetNodeAnimationStatesAttr() const;
     VariantVector GetNodeAnimationStatesAttr() const;
 
 
+    // Animation Resources
+
+    void AddAnimationResource(Animation* animation);
+    void RemoveAnimationResource(Animation* animation);
+    void ClearAnimationResources();
+    void SetAnimationResourcesAttr(const ResourceRefList& value);
+    const ResourceRefList& GetAnimationResourcesAttr() const;
+
 protected:
 protected:
     /// Handle node being assigned.
     /// Handle node being assigned.
     virtual void OnNodeSet(Node* node);
     virtual void OnNodeSet(Node* node);
@@ -191,6 +199,13 @@ private:
     Vector<SharedPtr<AnimationState> > nodeAnimationStates_;
     Vector<SharedPtr<AnimationState> > nodeAnimationStates_;
     /// Attribute buffer for network replication.
     /// Attribute buffer for network replication.
     mutable VectorBuffer attrBuffer_;
     mutable VectorBuffer attrBuffer_;
+
+    /// animation resources
+    Vector<SharedPtr<Animation> > animationsResources_;
+
+    /// Material list attribute.
+    mutable ResourceRefList animationsResourcesAttr_;
+    ;
 };
 };
 
 
 }
 }

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

@@ -71,6 +71,7 @@ void js_class_declare_internal(JSVM* vm, void* uniqueClassID, const char* packag
     }
     }
     else
     else
     {
     {
+        // RefCounted only supported in Atomic package
         assert(String("Atomic") == package );
         assert(String("Atomic") == package );
     }
     }
 
 

+ 1 - 1
Source/AtomicJS/Packages/ToolCore/ToolCore.json

@@ -4,7 +4,7 @@
 							 "Source/ToolCore/Import", "Source/ToolCore/Assets"],
 							 "Source/ToolCore/Import", "Source/ToolCore/Assets"],
 	"classes" : ["ToolEnvironment", "ToolSystem", "Project", "ProjectFile", "Platform", "PlatformMac", "PlatformWeb",
 	"classes" : ["ToolEnvironment", "ToolSystem", "Project", "ProjectFile", "Platform", "PlatformMac", "PlatformWeb",
 							 "PlatformWindows", "Command", "PlayCmd", "OpenAssetImporter",
 							 "PlatformWindows", "Command", "PlayCmd", "OpenAssetImporter",
-							 "Asset", "AssetDatabase", "AssetImporter", "ModelImporter"],
+							 "Asset", "AssetDatabase", "AssetImporter", "ModelImporter", "AnimationImportInfo"],
 	"typescript_decl" : {
 	"typescript_decl" : {
 
 
 		"AssetDatabase" : [
 		"AssetDatabase" : [

+ 1 - 1
Source/ToolCore/Assets/Asset.cpp

@@ -175,7 +175,7 @@ bool Asset::CreateImporter()
         // todo, externalize recognizers
         // todo, externalize recognizers
         if (ext == ".fbx")
         if (ext == ".fbx")
         {
         {
-            importer_ = new ModelImporter(context_);
+            importer_ = new ModelImporter(context_, this);
         }
         }
         else if (ext == ".scene")
         else if (ext == ".scene")
         {
         {

+ 140 - 35
Source/ToolCore/Assets/ModelImporter.cpp

@@ -1,5 +1,14 @@
 
 
+#include <Atomic/Core/ProcessUtils.h>
 #include <Atomic/IO/Log.h>
 #include <Atomic/IO/Log.h>
+#include <Atomic/IO/File.h>
+#include <Atomic/IO/FileSystem.h>
+#include <Atomic/Scene/Node.h>
+
+#include <Atomic/Atomic3D/AnimationController.h>
+#include <Atomic/Atomic3D/Animation.h>
+
+#include <Atomic/Resource/ResourceCache.h>
 
 
 #include "../Import/OpenAssetImporter.h"
 #include "../Import/OpenAssetImporter.h"
 
 
@@ -11,7 +20,8 @@ namespace ToolCore
 {
 {
 
 
 /// Node + Model (static or animated)
 /// Node + Model (static or animated)
-ModelImporter::ModelImporter(Context* context) : AssetImporter(context)
+ModelImporter::ModelImporter(Context* context, Asset *asset) : AssetImporter(context),
+    asset_(asset)
 {
 {
     SetDefaults();
     SetDefaults();
 }
 }
@@ -26,45 +36,45 @@ void ModelImporter::SetDefaults()
     AssetImporter::SetDefaults();
     AssetImporter::SetDefaults();
 
 
     scale_ = 1.0f;
     scale_ = 1.0f;
-    startTime_ = -1.0f;
-    endTime_ = -1.0f;
     importAnimations_ = false;
     importAnimations_ = false;
+    animationInfo_.Clear();
 
 
 }
 }
 
 
-bool ModelImporter::Import(const String& guid)
+bool ModelImporter::ImportModel()
 {
 {
-    AssetDatabase* db = GetSubsystem<AssetDatabase>();
-    Asset* asset = db->GetAssetByGUID(guid);
-
-    if (!asset)
-        return false;
-
     SharedPtr<OpenAssetImporter> importer(new OpenAssetImporter(context_));
     SharedPtr<OpenAssetImporter> importer(new OpenAssetImporter(context_));
 
 
     //importer->SetVerboseLog(true);
     //importer->SetVerboseLog(true);
 
 
-    bool animationsOnly = false;
-
-    String modelAssetFilename = asset->GetPath();
+    importer->SetScale(scale_);
+    importer->SetExportAnimations(false);
+    importer->SetImportNode(importNode_);
 
 
-    if (modelAssetFilename.Contains("@"))
+    if (importer->Load(asset_->GetPath()))
     {
     {
-        animationsOnly = true;
+        importer->ExportModel(asset_->GetCachePath());
+
+        return true;
     }
     }
 
 
-    importer->SetScale(scale_);
-    importer->SetStartTime(startTime_);
-    importer->SetEndTime(endTime_);
-    importer->SetExportAnimations(importAnimations_);
+    return false;
+}
 
 
-    if (importer->Load(asset->GetPath()))
-    {
-        String cachePath = db->GetCachePath();
+bool ModelImporter::ImportAnimation(const String& name, float startTime, float endTime)
+{
+    SharedPtr<OpenAssetImporter> importer(new OpenAssetImporter(context_));
 
 
-        cachePath += guid;
+    //importer->SetVerboseLog(true);
 
 
-        importer->ExportModel(cachePath, animationsOnly);
+    importer->SetScale(scale_);
+    importer->SetExportAnimations(true);
+    importer->SetStartTime(startTime);
+    importer->SetEndTime(endTime);
+
+    if (importer->Load(asset_->GetPath()))
+    {
+        importer->ExportModel(asset_->GetCachePath(), name, true);
 
 
         const Vector<OpenAssetImporter::AnimationInfo>& infos = importer->GetAnimationInfos();
         const Vector<OpenAssetImporter::AnimationInfo>& infos = importer->GetAnimationInfos();
 
 
@@ -72,14 +82,85 @@ bool ModelImporter::Import(const String& guid)
         {
         {
             const OpenAssetImporter::AnimationInfo& info = infos.At(i);
             const OpenAssetImporter::AnimationInfo& info = infos.At(i);
 
 
-            LOGINFOF("Import Info: %s : %s", info.name_.CString(), info.cacheFilename_.CString());
+            String pathName, fileName, extension;
+
+            SplitPath(info.cacheFilename_, pathName, fileName, extension);
+
+            ResourceCache* cache = GetSubsystem<ResourceCache>();
+
+            AnimationController* controller = importNode_->GetComponent<AnimationController>();
+
+            if (controller)
+            {
+                SharedPtr<Animation> animation = cache->GetTempResource<Animation>(fileName + extension);
+                if (animation)
+                    controller->AddAnimationResource(animation);
+            }
+
+            LOGINFOF("Import Info: %s : %s", info.name_.CString(), fileName.CString());
         }
         }
+
+        return true;
     }
     }
-    else
+
+    return false;
+
+}
+
+bool ModelImporter::ImportAnimations()
+{
+    if (!animationInfo_.Size())
     {
     {
+        return ImportAnimation("RootAnim");
+    }
+
+    for (unsigned i = 0; i < animationInfo_.Size(); i++)
+    {
+        const SharedPtr<AnimationImportInfo>& info = animationInfo_[i];
+        if (!ImportAnimation(info->GetName(), info->GetStartTime(), info->GetEndTime()))
+            return false;
+    }
+
+    return true;
+}
+
+bool ModelImporter::Import(const String& guid)
+{
+    AssetDatabase* db = GetSubsystem<AssetDatabase>();
+    Asset* asset = db->GetAssetByGUID(guid);
+
+    if (!asset)
         return false;
         return false;
+
+    bool animationsOnly = false;
+
+    String modelAssetFilename = asset->GetPath();
+
+    importNode_ = new Node(context_);
+
+    if (modelAssetFilename.Contains("@"))
+    {
+        animationsOnly = true;
     }
     }
 
 
+    if (!animationsOnly)
+        ImportModel();
+
+    if (importAnimations_)
+    {
+        ImportAnimations();
+    }
+
+    File outFile(context_);
+
+    if (!outFile.Open(asset_->GetCachePath(), FILE_WRITE))
+        ErrorExit("Could not open output file " + asset_->GetCachePath());
+
+    importNode_->SaveXML(outFile);
+
+    importNode_ = 0;
+
+
     return true;
     return true;
 }
 }
 
 
@@ -94,13 +175,28 @@ bool ModelImporter::LoadSettingsInternal()
 
 
     if (import.HasMember("scale"))
     if (import.HasMember("scale"))
         scale_ = import.GetFloat("scale");
         scale_ = import.GetFloat("scale");
-    if (import.HasMember("startTime"))
-        startTime_ = import.GetFloat("startTime");
-    if (import.HasMember("endTime"))
-        endTime_ = import.GetFloat("endTime");
+
     if (import.HasMember("importAnimations"))
     if (import.HasMember("importAnimations"))
         importAnimations_ = import.GetBool("importAnimations");
         importAnimations_ = import.GetBool("importAnimations");
 
 
+    if (import.HasMember("animInfo"))
+    {
+        JSONValue animInfo = import.GetChild("animInfo");
+        for (unsigned i = 0; i < animInfo.GetSize(); i++)
+        {
+            JSONValue anim = animInfo.GetChild(i);
+
+            SharedPtr<AnimationImportInfo> info(new AnimationImportInfo(context_));
+
+            info->name_ = anim.GetString("name");
+            info->SetStartTime(anim.GetFloat("startTime"));
+            info->SetEndTime(anim.GetFloat("endTime"));
+
+            animationInfo_.Push(info);
+
+        }
+    }
+
     return true;
     return true;
 }
 }
 
 
@@ -109,12 +205,21 @@ bool ModelImporter::SaveSettingsInternal()
     if (!AssetImporter::SaveSettingsInternal())
     if (!AssetImporter::SaveSettingsInternal())
         return false;
         return false;
 
 
-    JSONValue import = jsonRoot_.CreateChild("ModelImporter");
+    JSONValue save = jsonRoot_.CreateChild("ModelImporter");
+
+    save.SetFloat("scale", scale_);
+    save.SetBool("importAnimations", importAnimations_);
+
+    JSONValue animInfo = save.CreateChild("animInfo", JSON_ARRAY);
 
 
-    import.SetFloat("scale", scale_);
-    import.SetFloat("startTime", startTime_);
-    import.SetFloat("endTime", endTime_);
-    import.SetBool("importAnimations", importAnimations_);
+    for (unsigned i = 0; i < animationInfo_.Size(); i++)
+    {
+        const SharedPtr<AnimationImportInfo>& info = animationInfo_[i];
+        JSONValue jinfo = animInfo.CreateChild();
+        jinfo.SetString("name", info->GetName());
+        jinfo.SetFloat("startTime", info->GetStartTime());
+        jinfo.SetFloat("endTime", info->GetEndTime());
+    }
 
 
     return true;
     return true;
 }
 }

+ 44 - 9
Source/ToolCore/Assets/ModelImporter.h

@@ -3,9 +3,44 @@
 
 
 #include "AssetImporter.h"
 #include "AssetImporter.h"
 
 
+namespace Atomic
+{
+    class Node;
+}
+
+using namespace Atomic;
+
 namespace ToolCore
 namespace ToolCore
 {
 {
 
 
+class AnimationImportInfo : public Object
+{
+    friend class ModelImporter;
+
+public:
+
+    OBJECT(AnimationImportInfo);
+
+    AnimationImportInfo(Context* context) : Object(context), startTime_(-1.0f), endTime_(-1.0f)
+    {
+
+    }
+
+    const String& GetName() const { return name_; }
+    float GetStartTime() const { return startTime_; }
+    float GetEndTime() const { return endTime_; }
+
+    void SetStartTime(float time) { startTime_ = time; }
+    void SetEndTime(float time) { endTime_ = time; }
+
+private:
+
+    String name_;
+    float startTime_;
+    float endTime_;
+};
+
+
 class ModelImporter : public AssetImporter
 class ModelImporter : public AssetImporter
 {
 {
     OBJECT(ModelImporter);
     OBJECT(ModelImporter);
@@ -13,7 +48,7 @@ class ModelImporter : public AssetImporter
 public:
 public:
 
 
     /// Construct.
     /// Construct.
-    ModelImporter(Context* context);
+    ModelImporter(Context* context, Asset* asset);
     virtual ~ModelImporter();
     virtual ~ModelImporter();
 
 
     virtual void SetDefaults();
     virtual void SetDefaults();
@@ -21,12 +56,6 @@ public:
     float GetScale() { return scale_; }
     float GetScale() { return scale_; }
     void SetScale(float scale) {scale_ = scale; }
     void SetScale(float scale) {scale_ = scale; }
 
 
-    float GetStartTime() { return startTime_; }
-    void SetStartTime(float startTime) { startTime_ = startTime; }
-
-    float GetEndTime() { return endTime_; }
-    void SetEndTime(float endTime) { endTime_ = endTime; }
-
     bool GetImportAnimations() { return importAnimations_; }
     bool GetImportAnimations() { return importAnimations_; }
     void SetImportAnimations(bool importAnimations) { importAnimations_ = importAnimations; }
     void SetImportAnimations(bool importAnimations) { importAnimations_ = importAnimations; }
 
 
@@ -34,13 +63,19 @@ public:
 
 
 protected:
 protected:
 
 
+    bool ImportModel();
+    bool ImportAnimations();
+    bool ImportAnimation(const String& name, float startTime=-1.0f, float endTime=-1.0f);
+
     virtual bool LoadSettingsInternal();
     virtual bool LoadSettingsInternal();
     virtual bool SaveSettingsInternal();
     virtual bool SaveSettingsInternal();
 
 
+    WeakPtr<Asset> asset_;
     float scale_;
     float scale_;
-    float startTime_;
-    float endTime_;
     bool importAnimations_;
     bool importAnimations_;
+    Vector<SharedPtr<AnimationImportInfo>> animationInfo_;
+
+    SharedPtr<Node> importNode_;
 
 
 };
 };
 
 

+ 25 - 38
Source/ToolCore/Import/OpenAssetImporter.cpp

@@ -200,7 +200,7 @@ void OpenAssetImporter::ApplyScale()
 
 
 }
 }
 
 
-void OpenAssetImporter::ExportModel(const String& outName, bool animationOnly)
+void OpenAssetImporter::ExportModel(const String& outName, const String &animName, bool animationOnly)
 {
 {
     if (outName.Empty())
     if (outName.Empty())
         ErrorExit("No output file defined");
         ErrorExit("No output file defined");
@@ -219,7 +219,7 @@ void OpenAssetImporter::ExportModel(const String& outName, bool animationOnly)
     if (!noAnimations_)
     if (!noAnimations_)
     {
     {
         CollectAnimations(&model);
         CollectAnimations(&model);
-        BuildAndSaveAnimations(&model);
+        BuildAndSaveAnimations(&model, animName);
 
 
         // Save scene-global animations
         // Save scene-global animations
         // CollectAnimations();
         // CollectAnimations();
@@ -232,41 +232,28 @@ void OpenAssetImporter::ExportModel(const String& outName, bool animationOnly)
         ExportMaterials(usedTextures);
         ExportMaterials(usedTextures);
     }
     }
 
 
-    ResourceCache* cache = GetSubsystem<ResourceCache>();
+    if (importNode_.Null())
+        return;
 
 
+    ResourceCache* cache = GetSubsystem<ResourceCache>();
     Model* mdl = cache->GetResource<Model>( model.outName_);
     Model* mdl = cache->GetResource<Model>( model.outName_);
 
 
-    // Use a dummy model here?  It kind of depends on how resource layout is
-    // designed, importing, existing models, etc
-/*
-    // Create a dummy model so that the reference can be stored
+    if (!mdl)
+        return;
 
 
-    String modelName = (useSubdirs_ ? "Models/" : "") + GetFileNameAndExtension(model.outName_);
+    StaticModel* modelComponent = 0;
 
 
-    if (!cache->Exists(modelName))
+    if (!mdl->GetSkeleton().GetNumBones())
     {
     {
-        Model* dummyModel = new Model(context_);
-        dummyModel->SetName(modelName);
-        dummyModel->SetNumGeometries(model.meshes_.Size());
-        cache->AddManualResource(dummyModel);
+        modelComponent = importNode_->CreateComponent<StaticModel>();
+        modelComponent->SetModel(mdl);
+    }
+    else
+    {
+        modelComponent = importNode_->CreateComponent<AnimatedModel>();
+        importNode_->CreateComponent<AnimationController>();
+        ((AnimatedModel*)modelComponent)->SetModel(mdl, false);
     }
     }
-*/
-
-    SharedPtr<Node> node(new Node(context_));
-    node->SetName("Model");
-
-    StaticModel* modelComponent = 0;
-    /*
-    StaticModel* staticModel = node->CreateComponent<StaticModel>();
-    staticModel->SetModel(mdl);
-    */
-
-    AnimatedModel* animatedModel = node->CreateComponent<AnimatedModel>();
-    modelComponent = animatedModel;
-    animatedModel->SetModel(mdl, false);
-
-    // create animation controller
-    AnimationController* controller = node->CreateComponent<AnimationController>();
 
 
     if (!noMaterials_)
     if (!noMaterials_)
     {
     {
@@ -281,13 +268,8 @@ void OpenAssetImporter::ExportModel(const String& outName, bool animationOnly)
         }
         }
 
 
     }
     }
-
-    File outFile(context_);
-    if (!outFile.Open(outName, FILE_WRITE))
-        ErrorExit("Could not open output file " + outName);
-
-    node->SaveXML(outFile);
 }
 }
+
 void OpenAssetImporter::BuildAndSaveModel(OutModel& model)
 void OpenAssetImporter::BuildAndSaveModel(OutModel& model)
 {
 {
     if (!model.rootNode_)
     if (!model.rootNode_)
@@ -862,7 +844,7 @@ void OpenAssetImporter::BuildBoneCollisionInfo(OutModel& model)
     }
     }
 }
 }
 
 
-void OpenAssetImporter::BuildAndSaveAnimations(OutModel* model)
+void OpenAssetImporter::BuildAndSaveAnimations(OutModel* model, const String &animNameOverride)
 {
 {
     const PODVector<aiAnimation*>& animations = model ? model->animations_ : sceneAnimations_;
     const PODVector<aiAnimation*>& animations = model ? model->animations_ : sceneAnimations_;
 
 
@@ -881,6 +863,11 @@ void OpenAssetImporter::BuildAndSaveAnimations(OutModel* model)
         else
         else
             animOutName = outPath_ + SanitateAssetName(animName) + ".ani";
             animOutName = outPath_ + SanitateAssetName(animName) + ".ani";
 
 
+        if (animNameOverride.Length())
+        {
+            animOutName = GetPath(model->outName_) + GetFileName(model->outName_) + "_" + animNameOverride + ".ani";
+        }
+
         float ticksPerSecond = (float)anim->mTicksPerSecond;
         float ticksPerSecond = (float)anim->mTicksPerSecond;
         // If ticks per second not specified, it's probably a .X file. In this case use the default tick rate
         // If ticks per second not specified, it's probably a .X file. In this case use the default tick rate
         if (ticksPerSecond < M_EPSILON)
         if (ticksPerSecond < M_EPSILON)
@@ -914,7 +901,7 @@ void OpenAssetImporter::BuildAndSaveAnimations(OutModel* model)
         }
         }
 
 
         SharedPtr<Animation> outAnim(new Animation(context_));
         SharedPtr<Animation> outAnim(new Animation(context_));
-        outAnim->SetAnimationName(animName);
+        outAnim->SetAnimationName(!animNameOverride.Length() ? animName : animNameOverride);
         outAnim->SetLength(duration * tickConversion);
         outAnim->SetLength(duration * tickConversion);
 
 
         //PrintLine("Writing animation " + animName + " length " + String(outAnim->GetLength()));
         //PrintLine("Writing animation " + animName + " length " + String(outAnim->GetLength()));

+ 7 - 3
Source/ToolCore/Import/OpenAssetImporter.h

@@ -29,6 +29,7 @@
 #include "OpenAssetUtils.h"
 #include "OpenAssetUtils.h"
 
 
 #include <Atomic/Core/Object.h>
 #include <Atomic/Core/Object.h>
+#include <Atomic/Scene/Node.h>
 
 
 using namespace Atomic;
 using namespace Atomic;
 
 
@@ -52,8 +53,9 @@ public:
 
 
     bool Load(const String& assetPath);
     bool Load(const String& assetPath);
 
 
-    void ExportModel(const String& outName, bool animationOnly = false);
+    void ExportModel(const String& outName, const String& animName = String::EMPTY, bool animationOnly = false);
 
 
+    void SetImportNode(Node* node) { importNode_ = node; }
     void SetStartTime(float startTime) { startTime_ = startTime; }
     void SetStartTime(float startTime) { startTime_ = startTime; }
     void SetEndTime(float endTime) { endTime_ = endTime; }
     void SetEndTime(float endTime) { endTime_ = endTime; }
     void SetScale(float scale) { scale_ = scale; }
     void SetScale(float scale) { scale_ = scale; }
@@ -69,7 +71,7 @@ private:
     void ApplyScale(aiNode* node);
     void ApplyScale(aiNode* node);
 
 
     void BuildAndSaveModel(OutModel& model);
     void BuildAndSaveModel(OutModel& model);
-    void BuildAndSaveAnimations(OutModel* model = 0);
+    void BuildAndSaveAnimations(OutModel* model = 0, const String& animNameOverride = String::EMPTY);
 
 
     void ExportMaterials(HashSet<String>& usedTextures);
     void ExportMaterials(HashSet<String>& usedTextures);
     void BuildAndSaveMaterial(aiMaterial* material, HashSet<String>& usedTextures);
     void BuildAndSaveMaterial(aiMaterial* material, HashSet<String>& usedTextures);
@@ -83,7 +85,7 @@ private:
     String GetMeshMaterialName(aiMesh* mesh);
     String GetMeshMaterialName(aiMesh* mesh);
     String GenerateMaterialName(aiMaterial* material);
     String GenerateMaterialName(aiMaterial* material);
     String GetMaterialTextureName(const String& nameIn);
     String GetMaterialTextureName(const String& nameIn);
-    String GenerateTextureName(unsigned texIndex);    
+    String GenerateTextureName(unsigned texIndex);
 
 
     // TODO: See AssetImporter
     // TODO: See AssetImporter
     // void CombineLods(const PODVector<float>& lodDistances, const Vector<String>& modelNames, const String& outName)
     // void CombineLods(const PODVector<float>& lodDistances, const Vector<String>& modelNames, const String& outName)
@@ -129,6 +131,8 @@ private:
 
 
     Vector<AnimationInfo> animationInfos_;
     Vector<AnimationInfo> animationInfos_;
 
 
+    SharedPtr<Node> importNode_;
+
     float defaultTicksPerSecond_;
     float defaultTicksPerSecond_;
 
 
     float startTime_;
     float startTime_;