From da625014860ca865040a0649152d9fa7ac925ec2 Mon Sep 17 00:00:00 2001 From: Tazpn <tazpn@users.sourceforge.net> Date: Sun, 24 Jun 2007 00:21:24 +0000 Subject: [PATCH] 0.2.14 ----- o Exporter - Fix a number of issues with bhkConvexShape and bhkRigidBody o Importer - Introduce Morph animation support --- MaxNifPlugins_Readme.txt | 7 + MaxNifTools.iss | 6 +- NifCommon/AnimKey.cpp | 8 + NifCommon/AnimKey.h | 3 + NifCommon/NifVersion.h | 6 +- NifCommon/niutils.cpp | 45 ++- NifCommon/niutils.h | 3 + NifExport/Coll.cpp | 28 +- NifExport/Exporter.h | 2 + NifExport/MtlTex.cpp | 2 +- NifExport/Util.cpp | 60 +++- NifImport/BaseImporter.h | 3 + NifImport/ImportAnimation.cpp | 500 ++++++++++++++++++++++++++++++++-- NifImport/ImportCollision.cpp | 2 +- NifImport/NIFImport.cpp | 13 +- NifImport/NIFImporter.h | 1 + 16 files changed, 637 insertions(+), 52 deletions(-) diff --git a/MaxNifPlugins_Readme.txt b/MaxNifPlugins_Readme.txt index 78d85b5..3b3a97e 100644 --- a/MaxNifPlugins_Readme.txt +++ b/MaxNifPlugins_Readme.txt @@ -33,6 +33,13 @@ Change log ---------- + 0.2.14 + ----- + o Exporter + - Fix a number of issues with bhkConvexShape and bhkRigidBody + o Importer + - Introduce Morph animation support + 0.2.13 ----- o Properties diff --git a/MaxNifTools.iss b/MaxNifTools.iss index 6d4b1d0..da1cb30 100644 --- a/MaxNifTools.iss +++ b/MaxNifTools.iss @@ -6,7 +6,7 @@ AppName=NIF Utilities for 3ds Max AppVerName=NIF Utilities {code:CurVer} for 3ds Max AppPublisher=NIF File Format Library and Tools AppCopyright=Copyright © 2007, NIF File Format Library and Tools -OutputBaseFilename=niftools-max-plugins-0.2.13.1 +OutputBaseFilename=niftools-max-plugins-0.2.14.0 DisableProgramGroupPage=yes Compression=lzma SolidCompression=yes @@ -18,7 +18,7 @@ UninstallFilesDir={win}{\}Installer\NifTools Uninstallable=yes DisableDirPage=yes ArchitecturesInstallIn64BitMode=x64 -VersionInfoVersion=0.2.13.1 +VersionInfoVersion=0.2.14.0 SourceDir=. ;UninstallDisplayIcon={app}{\}..\Oblivion.exe @@ -102,7 +102,7 @@ var sVersion: String; function InitializeSetup(): Boolean; begin - sVersion := '0.2.13'; + sVersion := '0.2.14'; Result := True; end; diff --git a/NifCommon/AnimKey.cpp b/NifCommon/AnimKey.cpp index 04342e9..2844bd8 100644 --- a/NifCommon/AnimKey.cpp +++ b/NifCommon/AnimKey.cpp @@ -475,4 +475,12 @@ bool GetTranslationKeys(Control *c, vector<Vector3Key> keys, const vector<float> return false; } +void ScaleKey(FloatKey& key, float mult) { + key.data *= mult; +} +void ScaleKeys(vector<FloatKey>&keys, float mult) { + for (int i=0, n = keys.size(); i<n; ++i) { + ScaleKey(keys[i], mult); + } +} diff --git a/NifCommon/AnimKey.h b/NifCommon/AnimKey.h index 593717f..99baf89 100644 --- a/NifCommon/AnimKey.h +++ b/NifCommon/AnimKey.h @@ -206,3 +206,6 @@ extern void JoinKeys(vector<Vector3Key>&keys, vector<FloatKey>&xkeys, vector<Flo typedef Key<string> KeyTextValue; bool GetTranslationKeys(Control *c, vector<Vector3Key> keys, const vector<float>& times, float timeOffset=0.0f); + +extern void ScaleKeys(vector<FloatKey>&keys, float mult); +extern void ScaleKey(FloatKey& key, float mult); diff --git a/NifCommon/NifVersion.h b/NifCommon/NifVersion.h index 2060d4c..2f97e84 100644 --- a/NifCommon/NifVersion.h +++ b/NifCommon/NifVersion.h @@ -18,10 +18,10 @@ HISTORY: */ #define VERSION_MAJOR_INT 0 #define VERSION_MINOR_INT 2 -#define VERSION_BUILD_INT 13 -#define VERSION_PATCH_INT 1 +#define VERSION_BUILD_INT 14 +#define VERSION_PATCH_INT 0 -#define VERSION_STRING "0, 2, 13, 1" +#define VERSION_STRING "0, 2, 14, 0" //#define DEF_VERSION_STRING(a,b,c,d) #a ", " #b ", " #c ", " #d //#define VERSION_STRING DEF_VERSION_STRING(a,b,c,d) diff --git a/NifCommon/niutils.cpp b/NifCommon/niutils.cpp index ff3669f..ade1713 100644 --- a/NifCommon/niutils.cpp +++ b/NifCommon/niutils.cpp @@ -1114,7 +1114,6 @@ void GetIniFileName(char *iniName) } } - Modifier *GetbhkCollisionModifier(INode* node) { extern Class_ID BHKRIGIDBODYMODIFIER_CLASS_ID; @@ -1184,4 +1183,46 @@ Matrix3 GetLocalTM(INode *node) { return node->GetNodeTM(0); } -} \ No newline at end of file +} + +Modifier *GetMorpherModifier(INode* node) +{ + const Class_ID MORPHERMODIFIER_CLASS_ID(0x17bb6854, 0xa5cba2a3); + + Object* pObj = node->GetObjectRef(); + if (!pObj) return NULL; + while (pObj->SuperClassID() == GEN_DERIVOB_CLASS_ID) + { + IDerivedObject* pDerObj = (IDerivedObject *)(pObj); + int Idx = 0; + while (Idx < pDerObj->NumModifiers()) + { + // Get the modifier. + Modifier* mod = pDerObj->GetModifier(Idx); + if (mod->ClassID() == MORPHERMODIFIER_CLASS_ID) + { + return mod; + } + Idx++; + } + pObj = pDerObj->GetObjRef(); + } + return NULL; +} + +Modifier *CreateMorpherModifier(INode* node) +{ + const Class_ID MORPHERMODIFIER_CLASS_ID(0x17bb6854, 0xa5cba2a3); + + Modifier *mod = GetMorpherModifier(node); + if (mod == NULL) + { + IDerivedObject *dobj = CreateDerivedObject(node->GetObjectRef()); + mod = (Modifier*) CreateInstance(OSM_CLASS_ID, MORPHERMODIFIER_CLASS_ID); + dobj->SetAFlag(A_LOCK_TARGET); + dobj->AddModifier(mod); + dobj->ClearAFlag(A_LOCK_TARGET); + node->SetObjectRef(dobj); + } + return mod; +} diff --git a/NifCommon/niutils.h b/NifCommon/niutils.h index 93e53bc..feef397 100644 --- a/NifCommon/niutils.h +++ b/NifCommon/niutils.h @@ -430,4 +430,7 @@ void GetIniFileName(char *iniName); Matrix3 GetLocalTM(INode *node); +extern Modifier *GetMorpherModifier(INode* node); +extern Modifier *CreateMorpherModifier(INode* node); + #endif // _NIUTILS_H_ \ No newline at end of file diff --git a/NifExport/Coll.cpp b/NifExport/Coll.cpp index b6810ef..22b4a49 100755 --- a/NifExport/Coll.cpp +++ b/NifExport/Coll.cpp @@ -184,9 +184,11 @@ Exporter::Result Exporter::exportCollision(NiNodeRef &parent, INode *node) Vector3 trans; Matrix33 rm; float scale; rm4.Decompose(trans, rm, scale); - QuaternionXYZW q = TOQUATXYZW(rm.AsQuaternion()); - body->SetRotation(q); - body->SetTranslation(trans / Exporter::bhkScaleFactor); + body->SetTranslation(TOVECTOR3(Point3(0.0f, 0.0f, 0.0f))); + body->SetRotation(TOQUATXYZW(Quat())); + //QuaternionXYZW q = TOQUATXYZW(rm.AsQuaternion()); + //body->SetRotation(q); + //body->SetTranslation(trans / Exporter::bhkScaleFactor); bhkShapeRef shape = makeCollisionShape(node, tm, body); if (shape) @@ -367,27 +369,31 @@ bhkConvexVerticesShapeRef Exporter::makeConvexShape(Mesh& mesh, Matrix3& tm) float radius = 0.10f; //CalcAxisAlignedSphere(mesh, center, radius); shape->SetRadius(radius); - vector<Vector3> verts, norms; - vector<float> dist; + vector<Vector3> verts; + vector<Float4> norms; int nvert = mesh.getNumVerts(); int nface = mesh.getNumFaces(); verts.resize(nvert); norms.resize(nface); - dist.resize(nface); for (int i=0; i<nvert; ++i) { - Point3 vert = mesh.getVert(i) / Exporter::bhkScaleFactor; + Point3 vert = mesh.getVert(i) / Exporter::bhkScaleFactor * tm; verts[i] = TOVECTOR3(vert); } for (int i=0; i<nface; ++i) { - norms[i] = TOVECTOR3(mesh.getFaceNormal(i)); - dist[i] = -mesh.FaceCenter(i).Length(); + Float4 &value = norms[i]; + Point3 &pt = mesh.getFaceNormal(i); + value[0] = pt.x; + value[1] = pt.y; + value[2] = pt.z; + value[3] = -mesh.FaceCenter(i).Length(); } + sortVector3(verts); + sortFloat4(norms); shape->SetVertices(verts); - shape->SetNormals(norms); - shape->SetDistToCenter(dist); + shape->SetNormalsAndDist(norms); return shape; } diff --git a/NifExport/Exporter.h b/NifExport/Exporter.h index 7b103da..b729c6d 100755 --- a/NifExport/Exporter.h +++ b/NifExport/Exporter.h @@ -282,6 +282,8 @@ public: int countNodes(INode *node); bool isSkeletonRoot(INode *node); void ApplyAllSkinOffsets( NiAVObjectRef & root ); + void sortVector3(vector<Vector3>& vector); + void sortFloat4(vector<Float4>& vector); /* Progress Bar stuff */ enum ProgressSection diff --git a/NifExport/MtlTex.cpp b/NifExport/MtlTex.cpp index c6d66b8..a9ceaae 100755 --- a/NifExport/MtlTex.cpp +++ b/NifExport/MtlTex.cpp @@ -18,7 +18,7 @@ void Exporter::makeTexture(NiAVObjectRef &parent, Mtl *mtl) if (!bmTex) return; - if (Exporter::mNifVersionInt <= VER_4_0_0_0) + if (Exporter::mNifVersionInt >= VER_4_0_0_0) { NiTexturingPropertyRef texProp = CreateNiObject<NiTexturingProperty>(); texProp->SetApplyMode(APPLY_MODULATE); diff --git a/NifExport/Util.cpp b/NifExport/Util.cpp index 7b831e5..0a1c6c0 100755 --- a/NifExport/Util.cpp +++ b/NifExport/Util.cpp @@ -551,4 +551,62 @@ void Exporter::ApplyAllSkinOffsets( NiAVObjectRef & root ) { ApplyAllSkinOffsets( children[i] ); } } -} \ No newline at end of file +} + +struct SortVectorEquivalence +{ + inline bool operator()(const Vector3& lhs, const Vector3& rhs) const + { + float diff = lhs.x - rhs.x; + if (diff < 0) + return true; + if (diff == 0) + { + diff = lhs.y - rhs.y; + if (diff < 0) + return true; + if (diff == 0) + { + diff = lhs.z - rhs.z; + if (diff < 0) + return true; + } + } + return false; + } + inline bool operator()(const Float4& lhs, const Float4& rhs) const + { + float diff = lhs[0] - rhs[0]; + if (diff < 0) + return true; + if (diff == 0) + { + diff = lhs[1] - rhs[1]; + if (diff < 0) + return true; + if (diff == 0) + { + diff = lhs[2] - rhs[2]; + if (diff < 0) + return true; + if (diff == 0) + { + diff = lhs[3] - rhs[3]; + if (diff < 0) + return true; + } + } + } + return false; + } +}; + +void Exporter::sortVector3(vector<Vector3>& vector) +{ + std::stable_sort(vector.begin(), vector.end(), SortVectorEquivalence()); +} + +void Exporter::sortFloat4(vector<Float4>& vector) +{ + std::stable_sort(vector.begin(), vector.end(), SortVectorEquivalence()); +} \ No newline at end of file diff --git a/NifImport/BaseImporter.h b/NifImport/BaseImporter.h index e4c7ded..d36b8c4 100644 --- a/NifImport/BaseImporter.h +++ b/NifImport/BaseImporter.h @@ -32,6 +32,7 @@ public: AppSettings *appSettings; TSTR webSite; TSTR wikiSite; + int nifVersion; Niflib::NiObjectRef root; @@ -71,6 +72,8 @@ public: webSite = GetIniValue<TSTR>("System", "Website", "http://www.niftools.org"); wikiSite = GetIniValue<TSTR>("System", "Wiki", "http://www.niftools.org/wiki/index.php/3ds_Max"); + nifVersion = Niflib::GetNifVersion(this->path); + // Load ini settings iniFileValid = false; LoadIniSettings(); diff --git a/NifImport/ImportAnimation.cpp b/NifImport/ImportAnimation.cpp index 54677a0..737961b 100644 --- a/NifImport/ImportAnimation.cpp +++ b/NifImport/ImportAnimation.cpp @@ -14,6 +14,7 @@ HISTORY: #if VERSION_3DSMAX >= ((7000<<16)+(15<<8)+0) // Version 7 # include <IFrameTagManager.h> #endif +#include <maxscrpt/strings.h> #include <notetrck.h> #include "MaxNifImport.h" #include "NIFImporter.h" @@ -31,6 +32,12 @@ HISTORY: #include <obj/NiKeyframeData.h> #include <obj/NiStringPalette.h> #include <obj/NiBSplineCompTransformInterpolator.h> +#include <obj/NiGeomMorpherController.h> +#include <obj/NiMorphData.h> +#include <obj/NiBSplineCompFloatInterpolator.h> +#include <obj/NiFloatInterpolator.h> +#include <obj/NiFloatData.h> +#include "niutils.h" using namespace Niflib; const Class_ID IPOS_CONTROL_CLASS_ID = Class_ID(0x118f7e02,0xffee238a); @@ -81,15 +88,27 @@ struct AnimationImport bool AddValues(Control *c, NiKeyframeDataRef data, float time); bool AddBiped(Control *c, NiKeyframeDataRef data, float time); + bool AddValues(NiInterpolatorRef interp, IParamBlock* pblock, float time); + Control* MakePosition(Control *tmCont, Class_ID clsid); Control* MakePositionXYZ(Control *tmCont, Class_ID clsid); Control* MakeRotation(Control *tmCont, Class_ID rotClsid, Class_ID rollClsid); Control* MakeScale(Control *tmCont, Class_ID clsid); + Control* MakeFloat(IParamBlock* pblock, int idx, Class_ID clsid); + Control* GetTMController(const string& name); + Control* GetTMController(NiObjectNETRef node); Matrix3 GetTM(const string& name, TimeValue t = 0); bool GetTransformData(ControllerLink& lnk, string name, NiKeyframeDataRef& outData, Point3& p, Quat& q, float& s); + + bool ImportGeoMorph(INode *n, NiGeomMorpherControllerRef ctrl, float time); + INode* CreateGeoMesh(const vector<Vector3>& verts, const vector<Triangle>& tris, Matrix3& tm, INode *parent); + + void MorpherBuildFromNode(Modifier* mod, int index, INode *target); + void MorpherSetName(Modifier* mod, int index, TSTR& name); + void MorpherRebuild(Modifier* mod, int index); }; bool NifImporter::ImportAnimation() @@ -485,26 +504,69 @@ bool KFMImporter::ImportAnimation() name = name.substr(0, name.length() - 9); } - Control *c = ai.GetTMController(name); - if (NULL == c) - continue; - - INode *n = gi->GetINodeByName(name.c_str()); - - if ((*lnk).priority_ != 0.0f) { - npSetProp(n, NP_ANM_PRI, (*lnk).priority_); - } - - NiKeyframeDataRef data; - Point3 p; Quat q; float s; - if (ai.GetTransformData(*lnk, name, data, p, q, s)) { - PosRotScaleNode(n, p, q, s, prsDefault, 0); - if (ai.AddValues(c, data, time)) { - minTime = min(minTime, start); - maxTime = max(maxTime, stop); - ok = true; - } - } + string type = (*lnk).controllerType; + if (type.empty()) { + NiStringPaletteRef strings = lnk->stringPalette; + type = strings->GetSubStr((*lnk).controllerTypeOffset); + } + if (type.empty()) + continue; + + if (strmatch(type, "NiTransformController")) + { + Control *c = ai.GetTMController(name); + if (NULL == c) + continue; + + INode *n = gi->GetINodeByName(name.c_str()); + + if ((*lnk).priority_ != 0.0f) { + npSetProp(n, NP_ANM_PRI, (*lnk).priority_); + } + + NiKeyframeDataRef data; + Point3 p; Quat q; float s; + if (ai.GetTransformData(*lnk, name, data, p, q, s)) { + PosRotScaleNode(n, p, q, s, prsDefault, 0); + if (ai.AddValues(c, data, time)) { + minTime = min(minTime, start); + maxTime = max(maxTime, stop); + ok = true; + } + } + } + else if (strmatch(type, "NiGeomMorpherController")) + { + string var2 = (*lnk).variable2; + if (var2.empty()) { + if (NiStringPaletteRef strings = lnk->stringPalette) + var2 = strings->GetSubStr((*lnk).variableOffset2); + } + if (!var2.empty()) + { + if (INode *n = gi->GetINodeByName(name.c_str())) + { + if (Modifier* mod = GetMorpherModifier(n)) + { + int idx = -1; + for (int i=1; i<=100; ++i) { + if (strmatch(var2, mod->SubAnimName(i))) { + idx = i; + break; + } + } + if (idx != -1) + { + if (ai.AddValues(lnk->interpolator, (IParamBlock*)mod->GetReference(idx), time)) { + minTime = min(minTime, start); + maxTime = max(maxTime, stop); + ok = true; + } + } + } + } + } + } } if (maxTime > minTime && maxTime > 0.0f) time += (maxTime-minTime) + FramesIncrement; @@ -578,7 +640,7 @@ bool AnimationImport::GetTransformData(ControllerLink& lnk, string name, NiKeyfr s = FloatNegINF; return true; } - } + } } return false; } @@ -597,6 +659,18 @@ Control *AnimationImport::GetTMController(const string& name) return c; } +Control *AnimationImport::GetTMController(NiObjectNETRef obj) +{ + if (obj->IsDerivedType(NiNode::TYPE)) + { + NiNodeRef node = StaticCast<NiNode>(obj); + if (INode *n = ni.GetNode(node)) { + return n->GetTMController(); + } + } + return GetTMController(obj->GetName().c_str()); +} + Matrix3 AnimationImport::GetTM(const string& name, TimeValue t) { INode *n = ni.gi->GetINodeByName(name.c_str()); @@ -628,28 +702,33 @@ bool AnimationImport::AddValues(vector<NiObjectNETRef>& nodes) bool AnimationImport::AddValues(NiObjectNETRef nref) { - Control *c = GetTMController(nref->GetName().c_str()); - if (NULL == c) - return false; - if (NiTextKeyExtraDataRef keydata = SelectFirstObjectOfType<NiTextKeyExtraData>(nref->GetExtraData())) { ni.AddNoteTracks(0.0f, string(), nref->GetName(), keydata, false); } + bool ok = false; float time = 0.0f; list< NiTimeControllerRef > clist = nref->GetControllers(); if (NiTransformControllerRef tc = SelectFirstObjectOfType<NiTransformController>(clist)) { if (NiTransformInterpolatorRef interp = tc->GetInterpolator()) { if (NiTransformDataRef data = interp->GetData()) { - return AddValues(c, data, time); + if (Control *c = GetTMController(nref)) + ok |= AddValues(c, data, time); } } } else if (NiKeyframeControllerRef kf = SelectFirstObjectOfType<NiKeyframeController>(clist)) { if (NiKeyframeDataRef kfData = kf->GetData()) { - return AddValues(c, kfData, time); + if (Control *c = GetTMController(nref)) + ok |= AddValues(c, kfData, time); } } - return false; + if (NiGeomMorpherControllerRef gmc = SelectFirstObjectOfType<NiGeomMorpherController>(clist)) { + if (INode *n = ni.GetNode(nref)) { + ok |= ImportGeoMorph(n, gmc, time); + } + } + + return ok; } bool AnimationImport::AddValues(Control *c, NiKeyframeDataRef data, float time) @@ -818,6 +897,23 @@ Control* AnimationImport::MakeScale(Control *tmCont, Class_ID clsid) } return NULL; } +Control* AnimationImport::MakeFloat(IParamBlock* pblock, int idx, Class_ID clsid) +{ + Interface *ip = ni.gi; + if (Control *c = pblock->GetController(idx)) { + if (c->ClassID()!=clsid) { + if (Control *tmpCtrl = (Control*)ip->CreateInstance(CTRL_SCALE_CLASS_ID, clsid)){ + pblock->SetController(idx, tmpCtrl); + if (pblock->GetController(idx) != tmpCtrl) + tmpCtrl->DeleteThis(); + else + c = tmpCtrl; + } + } + return c; + } + return NULL; +} Control* AnimationImport::MakePosition(Control *tmCont, Class_ID clsid) { @@ -870,4 +966,350 @@ bool AnimationImport::AddBiped(Control *c, NiKeyframeDataRef data, float time) { return false; } -#endif \ No newline at end of file +#endif + +bool AnimationImport::ImportGeoMorph(INode *n, NiGeomMorpherControllerRef ctrl, float time) +{ + NiObjectNETRef target = ctrl->GetTarget(); + if (!target->IsDerivedType(NiTriBasedGeom::TYPE)) + return false; + NiTriBasedGeomRef parentGeom = StaticCast<NiTriBasedGeom>(target); + NiMorphDataRef data = ctrl->GetData(); + if (data == NULL) + return false; + vector<NiInterpolatorRef> interpolators = ctrl->GetInterpolators(); + int nmorphs = data->GetMorphCount(); + if ((interpolators.size() > nmorphs) || nmorphs == 0) + return false; + NiGeometryDataRef geoData = parentGeom->GetData(); + int nBaseVerts = geoData->GetVertexCount(); + vector<Triangle> tris; + vector<Vector3> baseVerts; + if (geoData->IsDerivedType(NiTriShapeData::TYPE)) { + NiTriShapeDataRef triShapeData = StaticCast<NiTriShapeData>(geoData); + if (triShapeData == NULL) + return false; + tris = triShapeData->GetTriangles(); + } else if (geoData->IsDerivedType(NiTriStripsData::TYPE)) { + NiTriStripsDataRef triStripData = StaticCast<NiTriStripsData>(geoData); + if (triStripData == NULL) + return false; + tris = triStripData->GetTriangles(); + } else { + return false; + } + Matrix3 tm = TOMATRIX3(parentGeom->GetLocalTransform()); + tm.Invert(); + //tm.NoRot(); tm.NoTrans(); // Leave scale. Parent to owner mesh + + Modifier *mod = CreateMorpherModifier(n); + n->EvalWorldState(0, TRUE); + + // Create meshes for morph + for (int i=0; i<nmorphs; ++i) + { + string frameName = (ni.nifVersion >= VER_10_1_0_106) ? data->GetFrameName(i) : FormatString("Frame #%d", i); + vector<Vector3> verts = data->GetMorphVerts(i); + if (verts.size() != nBaseVerts) + continue; + + // All verts after the first index are differentials + if (i == 0) + { + baseVerts = verts; + } + else + { + for (int j=0; j<nBaseVerts; ++j) + verts[j] += baseVerts[j]; + } + + TSTR name(frameName.c_str()); + INode *geoNode = CreateGeoMesh(verts, tris, tm, n); + geoNode->SetName(FormatText("Morph: %s", name)); + + MorpherBuildFromNode(mod, i+1, geoNode); + MorpherSetName(mod, i+1, name); + n->EvalWorldState(0, TRUE); + + AddValues(interpolators[i], (IParamBlock*)mod->GetReference(i+1), time); + } + return false; +} + +bool AnimationImport::AddValues(NiInterpolatorRef interp, IParamBlock* pblock, float time) +{ + bool retval = false; + // Handle Translation + // + KeyType keyType = UNKNOWN_KEY; + vector<FloatKey> keys; + if (interp->IsDerivedType(NiFloatInterpolator::TYPE)) { + if (NiFloatDataRef data = StaticCast<NiFloatInterpolator>(interp)->GetData()) + { + keyType = data->GetKeyType(); + keys = data->GetKeys(); + } + } else if (interp->IsDerivedType(NiBSplineCompFloatInterpolator::TYPE)) { + NiBSplineCompFloatInterpolatorRef bsfi = StaticCast<NiBSplineCompFloatInterpolator>(interp); + int npoints = bsfi->GetNumControlPt(); + if (npoints > 3) { + keyType = QUADRATIC_KEY; + keys = bsfi->SampleKeys(npoints, 3); + } + } + if (keyType != UNKNOWN_KEY) + { + ScaleKeys(keys, 100.0f); + switch (keyType) + { + case LINEAR_KEY: + if (Control *subCtrl = MakeFloat(pblock, 0, Class_ID(LININTERP_FLOAT_CLASS_ID,0))) { + MergeKeys<ILinFloatKey, FloatKey>(subCtrl, keys, time); + retval |= true; + } + break; + case QUADRATIC_KEY: + case XYZ_ROTATION_KEY: + if (Control *subCtrl = MakeFloat(pblock, 0, Class_ID(HYBRIDINTERP_FLOAT_CLASS_ID,0))) { + MergeKeys<IBezFloatKey, FloatKey>(subCtrl, keys, time); + retval |= true; + } + break; + case TBC_KEY: + if (Control *subCtrl = MakeFloat(pblock, 0, Class_ID(TCBINTERP_FLOAT_CLASS_ID,0))) { + MergeKeys<ITCBFloatKey, FloatKey>(subCtrl, keys, time); + retval |= true; + } + break; + } + } + return retval; +} + +INode *AnimationImport::CreateGeoMesh( + const vector<Vector3>& verts, + const vector<Triangle>& tris, + Matrix3& tm, + INode *parent + ) +{ + INode *returnNode = NULL; + if ( ImpNode *node = ni.i->CreateNode() ) + { + TriObject *triObject = CreateNewTriObject(); + node->Reference(triObject); + + Mesh& mesh = triObject->GetMesh(); + INode *tnode = node->GetINode(); + + // Vertex info + { + int nVertices = verts.size(); + mesh.setNumVerts(nVertices); + for (int i=0; i < nVertices; ++i){ + const Vector3& v = verts[i]; + mesh.verts[i].Set(v.x, v.y, v.z); + } + } + + // Triangles and texture vertices + ni.SetTriangles(mesh, tris); + + //MNMesh mn(mesh); + //mn.OutToTri(mesh); + mesh.checkNormals(TRUE); + + // Wireframe Red color + StdMat2 *collMat = NewDefaultStdMat(); + collMat->SetDiffuse(Color(0.0f, 1.0f, 0.0f), 0); + collMat->SetWire(TRUE); + collMat->SetFaceted(TRUE); + ni.gi->GetMaterialLibrary().Add(collMat); + tnode->SetMtl(collMat); + tnode->SetRenderable(FALSE); + tnode->SetPrimaryVisibility(FALSE); + tnode->SetSecondaryVisibility(FALSE); + tnode->SetWireColor( RGB(0,255,0) ); + + returnNode = node->GetINode(); + + //PosRotScaleNode(returnNode, tm, prsDefault, 0); + if (parent != NULL) + parent->AttachChild(tnode, 1); + } + return returnNode; +} + +// CallMaxscript +// Send the string to maxscript +// +void AnimationImport::MorpherBuildFromNode(Modifier* mod, int index, INode *target) +{ + // Magic initialization stuff for maxscript. + static bool script_initialized = false; + if (!script_initialized) { + init_MAXScript(); + script_initialized = TRUE; + } + init_thread_locals(); + push_alloc_frame(); + six_value_locals(name, fn, mod, index, target, result); + save_current_frames(); + trace_back_active = FALSE; + + try { + // Create the name of the maxscript function we want. + // and look it up in the global names + vl.name = Name::intern(_T("WM3_MC_BuildFromNode")); + vl.fn = globals->get(vl.name); + + // For some reason we get a global thunk back, so lets + // check the cell which should point to the function. + // Just in case if it points to another global thunk + // try it again. + while (vl.fn != NULL && is_globalthunk(vl.fn)) + vl.fn = static_cast<GlobalThunk*>(vl.fn)->cell; + while (vl.fn != NULL && is_constglobalthunk(vl.fn)) + vl.fn = static_cast<ConstGlobalThunk*>(vl.fn)->cell; + + // Now we should have a MAXScriptFunction, which we can + // call to do the actual conversion. If we didn't + // get a MAXScriptFunction, we can't convert. + if (vl.fn != NULL && vl.fn->tag == class_tag(Primitive)) { + Value* args[3]; + + // Ok. WM3_MC_BuildFromNode takes three parameters + args[0] = vl.mod = MAXModifier::intern(mod); // The original material + args[1] = vl.index = Integer::intern(index); + args[2] = vl.target = MAXNode::intern(target); + + // Call the function and save the result. + vl.result = static_cast<Primitive*>(vl.fn)->apply(args, 3); + } + } catch (...) { + clear_error_source_data(); + restore_current_frames(); + MAXScript_signals = 0; + if (progress_bar_up) + MAXScript_interface->ProgressEnd(), progress_bar_up = FALSE; + } + + // Magic Max Script stuff to clear the frame and locals. + pop_value_locals(); + pop_alloc_frame(); +} + +void AnimationImport::MorpherSetName(Modifier* mod, int index, TSTR& name) +{ + // Magic initialization stuff for maxscript. + static bool script_initialized = false; + if (!script_initialized) { + init_MAXScript(); + script_initialized = TRUE; + } + init_thread_locals(); + push_alloc_frame(); + six_value_locals(name, fn, mod, index, value, result); + save_current_frames(); + trace_back_active = FALSE; + String* value = new String(name); + + try { + // Create the name of the maxscript function we want. + // and look it up in the global names + vl.name = Name::intern(_T("WM3_MC_SetName")); + vl.fn = globals->get(vl.name); + + // For some reason we get a global thunk back, so lets + // check the cell which should point to the function. + // Just in case if it points to another global thunk + // try it again. + while (vl.fn != NULL && is_globalthunk(vl.fn)) + vl.fn = static_cast<GlobalThunk*>(vl.fn)->cell; + while (vl.fn != NULL && is_constglobalthunk(vl.fn)) + vl.fn = static_cast<ConstGlobalThunk*>(vl.fn)->cell; + + // Now we should have a MAXScriptFunction, which we can + // call to do the actual conversion. If we didn't + // get a MAXScriptFunction, we can't convert. + // class_tag(MAXScriptFunction) + if (vl.fn != NULL && vl.fn->tag == class_tag(Primitive)) { + Value* args[3]; + + // Ok. WM3_MC_BuildFromNode takes three parameters + args[0] = vl.mod = MAXModifier::intern(mod); // The original material + args[1] = vl.index = Integer::intern(index); + args[2] = vl.value = value; + + // Call the function and save the result. + vl.result = static_cast<Primitive*>(vl.fn)->apply(args, 3); + } + } catch (...) { + value->collect(); + clear_error_source_data(); + restore_current_frames(); + MAXScript_signals = 0; + if (progress_bar_up) + MAXScript_interface->ProgressEnd(), progress_bar_up = FALSE; + } + + // Magic Max Script stuff to clear the frame and locals. + pop_value_locals(); + pop_alloc_frame(); +} + +void AnimationImport::MorpherRebuild(Modifier* mod, int index) +{ + // Magic initialization stuff for maxscript. + static bool script_initialized = false; + if (!script_initialized) { + init_MAXScript(); + script_initialized = TRUE; + } + init_thread_locals(); + push_alloc_frame(); + five_value_locals(name, fn, mod, index, result); + save_current_frames(); + trace_back_active = FALSE; + try { + // Create the name of the maxscript function we want. + // and look it up in the global names + vl.name = Name::intern(_T("WM3_MC_Rebuild")); + vl.fn = globals->get(vl.name); + + // For some reason we get a global thunk back, so lets + // check the cell which should point to the function. + // Just in case if it points to another global thunk + // try it again. + while (vl.fn != NULL && is_globalthunk(vl.fn)) + vl.fn = static_cast<GlobalThunk*>(vl.fn)->cell; + while (vl.fn != NULL && is_constglobalthunk(vl.fn)) + vl.fn = static_cast<ConstGlobalThunk*>(vl.fn)->cell; + + // Now we should have a MAXScriptFunction, which we can + // call to do the actual conversion. If we didn't + // get a MAXScriptFunction, we can't convert. + // class_tag(MAXScriptFunction) + if (vl.fn != NULL && vl.fn->tag == class_tag(Primitive)) { + Value* args[2]; + + // Ok. WM3_MC_BuildFromNode takes three parameters + args[0] = vl.mod = MAXModifier::intern(mod); // The original material + args[1] = vl.index = Integer::intern(index); + + // Call the function and save the result. + vl.result = static_cast<Primitive*>(vl.fn)->apply(args, 2); + } + } catch (...) { + clear_error_source_data(); + restore_current_frames(); + MAXScript_signals = 0; + if (progress_bar_up) + MAXScript_interface->ProgressEnd(), progress_bar_up = FALSE; + } + + // Magic Max Script stuff to clear the frame and locals. + pop_value_locals(); + pop_alloc_frame(); +} diff --git a/NifImport/ImportCollision.cpp b/NifImport/ImportCollision.cpp index d36cc4d..6400a53 100644 --- a/NifImport/ImportCollision.cpp +++ b/NifImport/ImportCollision.cpp @@ -108,7 +108,7 @@ bool NifImporter::ImportCollision(NiNodeRef node) Matrix3 tm(true); if (!ci.ImportShape(body, rbody, shape, node, tm)) { - body->Delete(0, 1); + gi->DeleteNode(body, FALSE); } } } diff --git a/NifImport/NIFImport.cpp b/NifImport/NIFImport.cpp index 53cb702..c668025 100644 --- a/NifImport/NIFImport.cpp +++ b/NifImport/NIFImport.cpp @@ -280,6 +280,17 @@ INode *NifImporter::GetNode(Niflib::NiNodeRef node) return FindNode(node); } +INode *NifImporter::GetNode(Niflib::NiObjectNETRef obj) +{ + if (obj->IsDerivedType(NiNode::TYPE)) { + NiNodeRef node = StaticCast<NiNode>(obj); + if (INode *n = GetNode(node)) { + return n; + } + } + return gi->GetINodeByName(obj->GetName().c_str()); +} + bool NifImporter::DoImport() { bool ok = true; @@ -353,7 +364,7 @@ bool NifImporter::DoImport() importedNodes.begin(), importedNodes.end(), results.begin()); for (vector<string>::iterator itr = results.begin(); itr != end; ++itr){ if (INode *node = gi->GetINodeByName((*itr).c_str())){ - node->Delete(0, TRUE); + gi->DeleteNode(node, FALSE); } } } diff --git a/NifImport/NIFImporter.h b/NifImport/NIFImporter.h index d16023b..0d36d9f 100644 --- a/NifImport/NIFImporter.h +++ b/NifImport/NIFImporter.h @@ -144,6 +144,7 @@ public: INode *FindNode(Niflib::NiObjectNETRef node); INode *GetNode(Niflib::NiNodeRef node); + INode *GetNode(Niflib::NiObjectNETRef obj); string GetSkeleton(AppSettings *appSettings); bool ShowDialog(); -- GitLab