Skip to content
This repository has been archived by the owner on Jul 7, 2022. It is now read-only.

Commit

Permalink
Master update 3
Browse files Browse the repository at this point in the history
Fixed not loading of newly added external presets for first time
Added ability to choose animation index, in case of multiple animations in single file.
Added ability to load config file with suppressPrompts enabled.
Added ability to load bones by their hkaBone user property, in case of not being as annotation.
Added ability to load additive animations.
  • Loading branch information
PredatorCZ committed Jun 4, 2019
1 parent 275a46c commit 5b03e55
Show file tree
Hide file tree
Showing 6 changed files with 181 additions and 50 deletions.
5 changes: 1 addition & 4 deletions src/HavokExport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,7 @@ class : public ClassDesc2
ClassDesc2* GetHavokExportDesc() { return &HavokExportDesc; }

//--- HavokImp -------------------------------------------------------
HavokExport::HavokExport()
{
Rescan();
}
HavokExport::HavokExport() {}

int HavokExport::ExtCount()
{
Expand Down
156 changes: 135 additions & 21 deletions src/HavokImport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class HavokImport : public SceneImport, HavokMaxV2
virtual int DoImport(const TCHAR *name,ImpInterface *i,Interface *gi, BOOL suppressPrompts=FALSE); // Import file

void LoadSkeleton(const hkaSkeleton &skel);
void LoadAnimation(const hkaAnimation *ani);
void LoadAnimation(const hkaAnimation *ani, const hkaAnimationBinding *bind);
};

class : public ClassDesc2
Expand All @@ -63,10 +63,7 @@ class : public ClassDesc2
ClassDesc2* GetHavokImportDesc() { return &HavokImportDesc; }

//--- HavokImp -------------------------------------------------------
HavokImport::HavokImport()
{
Rescan();
}
HavokImport::HavokImport() {}

int HavokImport::ExtCount()
{
Expand Down Expand Up @@ -161,7 +158,66 @@ void HavokImport::LoadSkeleton(const hkaSkeleton &skel)
}
}

void HavokImport::LoadAnimation(const hkaAnimation *ani)
static class : public ITreeEnumProc
{
const MSTR skelNameHint = _T("hkaSkeleton");
const MSTR boneNameHint = _T("hkaBone");
const MSTR skelNameExclude = _T("ragdoll");
public:
std::vector<INode *> bones;

void RescanBones()
{
bones.clear();
GetCOREInterface7()->GetScene()->EnumTree(this);
}

INode *LookupNode(int ID)
{
for (auto &b : bones)
if (b->UserPropExists(boneNameHint))
{
int _ID;
b->GetUserPropInt(boneNameHint, _ID);

if (_ID == ID)
return b;
}

return nullptr;
}

int callback(INode *node)
{
Object *refobj = node->EvalWorldState(0).obj;

if (node->UserPropExists(skelNameHint))
{
MSTR skelName;
node->GetUserPropString(skelNameHint, skelName);
skelName.toLower();

const int skelNameExcludeSize = skelNameExclude.Length();
bool found = true;

for (int s = 0; s < skelNameExcludeSize; s++)
if (skelName[s] != skelNameExclude[s])
{
found = false;
break;
}

if (found)
return TREE_CONTINUE;

bones.push_back(node);
}

return TREE_CONTINUE;
}
}iBoneScanner;

void HavokImport::LoadAnimation(const hkaAnimation *ani, const hkaAnimationBinding *bind)
{
if (!ani)
{
Expand All @@ -175,6 +231,8 @@ void HavokImport::LoadAnimation(const hkaAnimation *ani)
return;
}

iBoneScanner.RescanBones();

TimeValue numTicks = SecToTicks(ani->GetDuration());
TimeValue ticksPerFrame = GetTicksPerFrame();
TimeValue overlappingTicks = numTicks % ticksPerFrame;
Expand All @@ -192,18 +250,72 @@ void HavokImport::LoadAnimation(const hkaAnimation *ani)
for (TimeValue v = 0; v <= aniRange.End(); v += GetTicksPerFrame())
frameTimes.push_back(TicksToSec(v));

int curBone = 0;
ani->ComputeFrameRate();

for (auto &a : ani->Annotations())
const int numBones = ani->GetNumOfTransformTracks();
const bool additiveAnimation = bind ? bind->GetBlendHint() != BlendHint::NORMAL : false;

std::vector<Matrix3> addTMs(numBones, { {1.0f, 0.0f, 0.0f} ,{0.0f, 1.0f, 0.0f} ,{0.0f, 0.0f, 1.0f} ,{0.0f, 0.0f, 0.0f} });

if (additiveAnimation)
for (int curBone = 0; curBone < numBones; curBone++)
{
INode *node = nullptr;
TSTRING boneName;

if (ani->GetNumAnnotations())
{
hkaAnnotationTrackPtr annot = ani->GetAnnotation(curBone);
boneName = esStringConvert<TCHAR>(annot.get()->GetName());
node = GetCOREInterface()->GetINodeByName(boneName.c_str());
}

if (!node && bind)
node = iBoneScanner.LookupNode(bind->GetTransformTrackToBoneIndex(curBone));

if (!node)
continue;

Matrix3 inPacket = node->GetNodeTM(0);

if (!node->GetParentNode()->IsRootNode())
{
Matrix3 parentTM = node->GetParentTM(0);
parentTM.Invert();
inPacket *= parentTM;
}

addTMs[curBone] = inPacket;
}

for (int curBone = 0; curBone < numBones; curBone++)
{
TSTRING boneName = esStringConvert<TCHAR>(a.get()->GetName());
INode *node = GetCOREInterface()->GetINodeByName(boneName.c_str());
INode *node = nullptr;
TSTRING boneName;

if (ani->GetNumAnnotations())
{
hkaAnnotationTrackPtr annot = ani->GetAnnotation(curBone);
boneName = esStringConvert<TCHAR>(annot.get()->GetName());
node = GetCOREInterface()->GetINodeByName(boneName.c_str());
}

if (!node && bind)
{
node = iBoneScanner.LookupNode(bind->GetTransformTrackToBoneIndex(curBone));
}

if (!node)
{
printwarning("[Havok] Couldn't find bone: ", << boneName);
curBone++;
if (boneName.length())
{
printwarning("[Havok] Couldn't find bone: ", << boneName);
}
else
{
printwarning("[Havok] Couldn't find hkaBone: ", << curBone);
}

continue;
}

Expand Down Expand Up @@ -243,6 +355,9 @@ void HavokImport::LoadAnimation(const hkaAnimation *ani)
cMat.Translate(fracPos * nScale);
}

if (additiveAnimation)
cMat *= addTMs[curBone];

SetXFormPacket packet(cMat);

cnt->SetValue(SecToTicks(t), &packet);
Expand All @@ -254,21 +369,14 @@ void HavokImport::LoadAnimation(const hkaAnimation *ani)
rotControl->Copy(cnt->GetRotationController());
cnt->GetRotationController()->Copy(rotControl);

curBone++;
}
}



int HavokImport::DoImport(const TCHAR*fileName, ImpInterface* /*importerInt*/, Interface* /*ip*/, BOOL suppressPrompts)
{
char *oldLocale = setlocale(LC_NUMERIC, NULL);
setlocale(LC_NUMERIC, "en-US");

if (!suppressPrompts)
if (!SpawnImportDialog())
return TRUE;

std::wstring _filename = esString(fileName);
IhkPackFile *pFile = IhkPackFile::Create(_filename.c_str());

Expand All @@ -282,11 +390,17 @@ int HavokImport::DoImport(const TCHAR*fileName, ImpInterface* /*importerInt*/, I
{
const hkaAnimationContainer *_cont = v;

numAnimations = _cont->GetNumAnimations();

if (!suppressPrompts)
if (!SpawnImportDialog())
return TRUE;

for (auto &s : _cont->Skeletons())
LoadSkeleton(s);

if (_cont->GetNumAnimations())
LoadAnimation(_cont->GetAnimation(0));
if (numAnimations)
LoadAnimation(_cont->GetAnimation(IDC_EDIT_MOTIONID_index), _cont->GetBinding(IDC_EDIT_MOTIONID_index));
}

delete pFile;
Expand Down
16 changes: 15 additions & 1 deletion src/HavokMax.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ static HBITMAP bitmapGreen,
#define CATTEDTEXT(...) StaticFor(QUOTE, __VA_ARGS__)

const TCHAR _name[] = _T("Havok Tool");
const TCHAR _info[] = _T(CATTEDTEXT(\nCopyright(C) 2016-2019 Lukas Cone\nVersion, HAVOKMAX_VERSION));
const TCHAR _info[] = _T(CATTEDTEXT(\nCopyright(C) 2016-2019 Lukas Cone\nVersion\x20, HAVOKMAX_VERSION));
const TCHAR _license[] = _T("Havok Tool uses HavokLib, Copyright(C) 2016-2019 Lukas Cone.");
const TCHAR _homePage[] = _T("https://lukascone.wordpress.com/2019/03/21/havok-3ds-max-plugin");

Expand Down Expand Up @@ -188,6 +188,16 @@ HavokMax::HavokMax() :

IDConfigIndex(IDC_EDIT_ANISTART) = aniRange.Start() / GetTicksPerFrame();
IDConfigIndex(IDC_EDIT_ANIEND) = aniRange.End() / GetTicksPerFrame();

Rescan();
LoadCFG();

for (auto &p : presets)
if (!p->name.compare(currentPresetName))
{
corMat = p->corMat;
IDC_EDIT_SCALE_value = p->scale;
}
}

void HavokMax::BuildCFG()
Expand Down Expand Up @@ -545,6 +555,9 @@ INT_PTR CALLBACK DialogCallbacksMain(HWND hWnd, UINT message, WPARAM wParam, LPA
case IDC_SPIN_ANIEND:
imp->IDC_EDIT_ANIEND_index= reinterpret_cast<ISpinnerControl *>(lParam)->GetIVal();
break;
case IDC_SPIN_MOTIONID:
imp->IDC_EDIT_MOTIONID_index = reinterpret_cast<ISpinnerControl *>(lParam)->GetIVal();
break;
}
}
return (INT_PTR)FALSE;
Expand Down Expand Up @@ -855,6 +868,7 @@ void HavokMaxV2::UpdatePresetUI(PresetData *data)
IDC_EDIT_SCALE_value = data->scale;

SetupFloatSpinner(hWnd, IDC_SPIN_SCALE, IDC_EDIT_SCALE, 0, 5000, IDC_EDIT_SCALE_value);
SetupIntSpinner(hWnd, IDC_SPIN_MOTIONID, IDC_EDIT_MOTIONID, 0, numAnimations - 1, IDC_EDIT_MOTIONID_index);

int curIndex = 0;

Expand Down
6 changes: 4 additions & 2 deletions src/HavokMax.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@
#include <vector>
#include "HavokXMLApi.hpp"

#define HAVOKMAX_VERSION 1.4
#define HAVOKMAX_VERSIONINT 140
#define HAVOKMAX_VERSION 1.5
#define HAVOKMAX_VERSIONINT 150

extern TCHAR *GetString(int id);
extern HINSTANCE hInstance;
Expand Down Expand Up @@ -72,6 +72,8 @@ class HavokMax
TSTRING cfgpath;
esFlags<char> sanityCheck;
const TCHAR *CFGFile;
int numAnimations;
NewIDConfigIndex(IDC_EDIT_MOTIONID);
NewIDConfigValue(IDC_EDIT_SCALE);
NewIDConfigIndex(IDC_CB_TOOLSET);
NewIDConfigIndex(IDC_EDIT_ANIEND);
Expand Down
45 changes: 24 additions & 21 deletions src/HavokMax.rc
Original file line number Diff line number Diff line change
Expand Up @@ -193,33 +193,36 @@ BEGIN
LTEXT "Toolset:",IDC_STATIC,7,9,26,8
END

IDD_IMPORT_NEW DIALOGEX 0, 0, 123, 144
IDD_IMPORT_NEW DIALOGEX 0, 0, 123, 159
STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_TOOLWINDOW
FONT 8, "MS Sans Serif", 400, 0, 0xEE
BEGIN
CONTROL "",IDC_EDIT_SCALE,"CustEdit",WS_TABSTOP,45,6,35,10
CONTROL "",IDC_SPIN_SCALE,"SpinnerControl",0x0,81,6,7,10
LTEXT "Scale:",IDC_STATIC,9,6,21,8
COMBOBOX IDC_CB_PRESET,6,99,111,150,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
PUSHBUTTON "Save",IDC_BT_SAVEPRESET,51,81,39,14,NOT WS_VISIBLE
PUSHBUTTON "+",IDC_BT_ADDPRESET,9,81,18,14
PUSHBUTTON "Import",IDC_BT_DONE,6,123,45,14
PUSHBUTTON "Cancel",IDC_BT_CANCEL,72,123,45,14
PUSHBUTTON "?",IDC_BT_ABOUT,54,123,15,14
PUSHBUTTON "-",IDC_BT_DELETEPRESET,30,81,18,14
CONTROL IDB_BITMAP2,IDC_STATIC,"Static",SS_BITMAP,9,40,24,31
CONTROL "Invert Top",IDC_CH_INVERT_TOP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,9,31,44,10
GROUPBOX "Coords setup",IDC_STATIC,3,20,114,60
CONTROL IDB_BITMAP3,IDC_PC_INVERT_ERROR,"Static",SS_BITMAP | NOT WS_VISIBLE,56,29,3,10
CONTROL IDB_BITMAP3,IDC_PC_REMAP_ERROR2,"Static",SS_BITMAP | NOT WS_VISIBLE,110,46,3,10
CONTROL IDB_BITMAP3,IDC_PC_REMAP_ERROR1,"Static",SS_BITMAP | NOT WS_VISIBLE,110,65,3,10
COMBOBOX IDC_CB_BACK,72,44,36,50,CBS_DROPDOWNLIST | WS_TABSTOP
LTEXT "Back:",IDC_STATIC,36,47,20,8
LTEXT "Right:",IDC_STATIC,36,65,20,8
COMBOBOX IDC_CB_RIGHT,72,62,36,50,CBS_DROPDOWNLIST | WS_TABSTOP
CONTROL "-",IDC_CH_INVERT_BACK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,57,47,15,8
CONTROL "-",IDC_CH_INVERT_RIGHT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,57,66,15,8
COMBOBOX IDC_CB_PRESET,6,115,111,150,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
PUSHBUTTON "Save",IDC_BT_SAVEPRESET,51,97,39,14,NOT WS_VISIBLE
PUSHBUTTON "+",IDC_BT_ADDPRESET,9,97,18,14
PUSHBUTTON "Import",IDC_BT_DONE,6,139,45,14
PUSHBUTTON "Cancel",IDC_BT_CANCEL,72,139,45,14
PUSHBUTTON "?",IDC_BT_ABOUT,54,139,15,14
PUSHBUTTON "-",IDC_BT_DELETEPRESET,30,97,18,14
CONTROL IDB_BITMAP2,IDC_STATIC,"Static",SS_BITMAP,9,56,24,31
CONTROL "Invert Top",IDC_CH_INVERT_TOP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,9,47,44,10
GROUPBOX "Coords setup",IDC_STATIC,3,36,114,60
CONTROL IDB_BITMAP3,IDC_PC_INVERT_ERROR,"Static",SS_BITMAP | NOT WS_VISIBLE,56,45,3,10
CONTROL IDB_BITMAP3,IDC_PC_REMAP_ERROR2,"Static",SS_BITMAP | NOT WS_VISIBLE,110,62,3,10
CONTROL IDB_BITMAP3,IDC_PC_REMAP_ERROR1,"Static",SS_BITMAP | NOT WS_VISIBLE,110,81,3,10
COMBOBOX IDC_CB_BACK,72,60,36,50,CBS_DROPDOWNLIST | WS_TABSTOP
LTEXT "Back:",IDC_STATIC,36,63,20,8
LTEXT "Right:",IDC_STATIC,36,81,20,8
COMBOBOX IDC_CB_RIGHT,72,78,36,50,CBS_DROPDOWNLIST | WS_TABSTOP
CONTROL "-",IDC_CH_INVERT_BACK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,57,63,15,8
CONTROL "-",IDC_CH_INVERT_RIGHT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,57,82,15,8
CONTROL "",IDC_EDIT_MOTIONID,"CustEdit",WS_TABSTOP,45,20,35,10
CONTROL "",IDC_SPIN_MOTIONID,"SpinnerControl",0x0,81,20,7,10
LTEXT "Motion ID:",IDC_STATIC,9,20,34,8
END

IDD_EXPORT_NEW DIALOGEX 0, 0, 229, 159
Expand Down Expand Up @@ -297,7 +300,7 @@ BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 116
TOPMARGIN, 7
BOTTOMMARGIN, 137
BOTTOMMARGIN, 152
END

IDD_EXPORT_NEW, DIALOG
Expand Down
3 changes: 2 additions & 1 deletion src/resource.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,18 +52,19 @@
#define IDC_CB_TOOLSET 1037
#define IDC_CH_ANIMATION 1038
#define IDC_CH_ANISKELETON 1039
#define IDC_CHECK3 1040
#define IDC_CH_ANIOPTIMIZE 1040
#define IDC_CH_INVERT_RIGHT2 1041
#define IDC_COLOR 1456
#define IDC_EDIT 1490
#define IDC_EDIT_SCALE 1490
#define IDC_EDIT_CAPTUREFRAME 1491
#define IDC_EDIT_MOTIONID 1501
#define IDC_EDIT_ANISTART 1492
#define IDC_EDIT_ANIEND 1493
#define IDC_SPIN 1496
#define IDC_SPIN_SCALE 1496
#define IDC_SPIN_CAPTUREFRAME 1497
#define IDC_SPIN_MOTIONID 1500
#define IDC_SPIN_ANISTART 1498
#define IDC_SPIN_ANIEND 1499

Expand Down

0 comments on commit 5b03e55

Please sign in to comment.