You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
443 lines
12 KiB
443 lines
12 KiB
/*==LICENSE==* |
|
|
|
CyanWorlds.com Engine - MMOG client, server and tools |
|
Copyright (C) 2011 Cyan Worlds, Inc. |
|
|
|
This program is free software: you can redistribute it and/or modify |
|
it under the terms of the GNU General Public License as published by |
|
the Free Software Foundation, either version 3 of the License, or |
|
(at your option) any later version. |
|
|
|
This program is distributed in the hope that it will be useful, |
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
GNU General Public License for more details. |
|
|
|
You should have received a copy of the GNU General Public License |
|
along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
|
|
Additional permissions under GNU GPL version 3 section 7 |
|
|
|
If you modify this Program, or any covered work, by linking or |
|
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK, |
|
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent |
|
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK |
|
(or a modified version of those libraries), |
|
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA, |
|
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG |
|
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the |
|
licensors of this Program grant you additional |
|
permission to convey the resulting work. Corresponding Source for a |
|
non-source form of such a combination shall include the source code for |
|
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered |
|
work. |
|
|
|
You can contact Cyan Worlds, Inc. by email legal@cyan.com |
|
or by snail mail at: |
|
Cyan Worlds, Inc. |
|
14617 N Newport Hwy |
|
Mead, WA 99021 |
|
|
|
*==LICENSE==*/ |
|
|
|
#include "plAnimComponent.h" |
|
#include "plComponentBase.h" |
|
#include "MaxMain/plMaxNode.h" |
|
|
|
#include <iparamm2.h> |
|
#include <set> |
|
#pragma hdrstop |
|
|
|
#include "plAnimCompProc.h" |
|
|
|
#include "plPickNode.h" |
|
#include "plPickNodeBase.h" |
|
#include "plNotetrackAnim.h" |
|
#include "plInterp/plAnimEaseTypes.h" |
|
|
|
#include "plPickMaterialMap.h" |
|
#include "MaxMain/plMtlCollector.h" |
|
|
|
plAnimCompProc::plAnimCompProc() : |
|
fCompButtonID(0), |
|
fCompParamID(0), |
|
fNodeButtonID(0), |
|
fNodeParamID(0) |
|
{ |
|
} |
|
|
|
BOOL plAnimCompProc::DlgProc(TimeValue t, IParamMap2* pm, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) |
|
{ |
|
switch (msg) |
|
{ |
|
case WM_INITDIALOG: |
|
{ |
|
IParamBlock2* pb = pm->GetParamBlock(); |
|
|
|
IUpdateNodeButton(hWnd, pb); |
|
IUpdateCompButton(hWnd, pb); |
|
|
|
ILoadUser(hWnd, pb); |
|
} |
|
return TRUE; |
|
|
|
case WM_COMMAND: |
|
{ |
|
int cmd = HIWORD(wParam); |
|
int resID = LOWORD(wParam); |
|
|
|
if (cmd == BN_CLICKED && resID == fCompButtonID) |
|
{ |
|
ICompButtonPress(hWnd, pm->GetParamBlock()); |
|
return TRUE; |
|
} |
|
else if (cmd == BN_CLICKED && resID == fNodeButtonID) |
|
{ |
|
INodeButtonPress(hWnd, pm->GetParamBlock()); |
|
return TRUE; |
|
} |
|
else if (IUserCommand(hWnd, pm->GetParamBlock(), cmd, resID)) |
|
return TRUE; |
|
|
|
} |
|
break; |
|
} |
|
return FALSE; |
|
} |
|
|
|
void plAnimCompProc::ICompButtonPress(HWND hWnd, IParamBlock2* pb) |
|
{ |
|
IPickComponent(pb); |
|
|
|
IUpdateCompButton(hWnd, pb); |
|
IUpdateNodeButton(hWnd, pb); |
|
|
|
ILoadUser(hWnd, pb); |
|
} |
|
|
|
void plAnimCompProc::IPickNode(IParamBlock2* pb, plComponentBase* comp) |
|
{ |
|
plPick::CompTargets(pb, fNodeParamID, comp); |
|
} |
|
|
|
void plAnimCompProc::INodeButtonPress(HWND hWnd, IParamBlock2* pb) |
|
{ |
|
plComponentBase* comp = IGetComp(pb); |
|
if (comp) |
|
IPickNode(pb, comp); |
|
|
|
IUpdateNodeButton(hWnd, pb); |
|
ILoadUser(hWnd, pb); |
|
} |
|
|
|
void plAnimCompProc::IUpdateNodeButton(HWND hWnd, IParamBlock2* pb) |
|
{ |
|
HWND hButton = GetDlgItem(hWnd, fNodeButtonID); |
|
|
|
plComponentBase* comp = IGetComp(pb); |
|
if (!comp) |
|
{ |
|
SetWindowText(hButton, "(none)"); |
|
EnableWindow(hButton, FALSE); |
|
return; |
|
} |
|
|
|
// If this is an anim grouped component you can't pick a target |
|
if (comp->ClassID() == ANIM_GROUP_COMP_CID) |
|
{ |
|
IClearNode(pb); |
|
SetWindowText(hButton, "(none)"); |
|
EnableWindow(hButton, FALSE); |
|
return; |
|
} |
|
|
|
EnableWindow(hButton, TRUE); |
|
|
|
// Make sure the node is actually in the components target list |
|
plMaxNode* node = IGetNode(pb); |
|
if (comp->IsTarget((plMaxNodeBase*)node)) |
|
SetWindowText(hButton, node->GetName()); |
|
else |
|
SetWindowText(hButton, "(none)"); |
|
} |
|
|
|
void plAnimCompProc::IUpdateCompButton(HWND hWnd, IParamBlock2* pb) |
|
{ |
|
HWND hAnim = GetDlgItem(hWnd, fCompButtonID); |
|
|
|
plComponentBase* comp = IGetComp(pb); |
|
if (comp) |
|
SetWindowText(hAnim, comp->GetINode()->GetName()); |
|
else |
|
SetWindowText(hAnim, "(none)"); |
|
} |
|
|
|
plComponentBase* plAnimCompProc::IGetComp(IParamBlock2* pb) |
|
{ |
|
plMaxNode* node = nil; |
|
if (pb->GetParameterType(fCompParamID) == TYPE_REFTARG) |
|
node = (plMaxNode*)pb->GetReferenceTarget(fCompParamID); |
|
else |
|
node = (plMaxNode*)pb->GetINode(fCompParamID); |
|
|
|
if (node) |
|
return node->ConvertToComponent(); |
|
|
|
return nil; |
|
} |
|
|
|
plMaxNode* plAnimCompProc::IGetNode(IParamBlock2* pb) |
|
{ |
|
if (pb->GetParameterType(fNodeParamID) == TYPE_REFTARG) |
|
return (plMaxNode*)pb->GetReferenceTarget(fNodeParamID); |
|
else |
|
return (plMaxNode*)pb->GetINode(fNodeParamID); |
|
} |
|
|
|
void plAnimCompProc::IClearNode(IParamBlock2* pb) |
|
{ |
|
if (pb->GetParameterType(fNodeParamID) == TYPE_REFTARG) |
|
pb->SetValue(fNodeParamID, 0, (ReferenceTarget*)nil); |
|
else |
|
pb->SetValue(fNodeParamID, 0, (INode*)nil); |
|
} |
|
|
|
bool plAnimCompProc::GetCompAndNode(IParamBlock2* pb, plComponentBase*& comp, plMaxNode*& node) |
|
{ |
|
comp = IGetComp(pb); |
|
if (comp) |
|
{ |
|
node = IGetNode(pb); |
|
|
|
// If it's an anim group component (don't need a node), or we have a node |
|
// and the component is attached to it, we're ok. |
|
if (comp->ClassID() == ANIM_GROUP_COMP_CID || |
|
(node && comp->IsTarget((plMaxNodeBase*)node))) |
|
return true; |
|
} |
|
|
|
return false; |
|
} |
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
plMtlAnimProc::plMtlAnimProc() : |
|
fMtlButtonID(0), |
|
fMtlParamID(0), |
|
fNodeButtonID(0), |
|
fNodeParamID(0), |
|
fAnimComboID(0), |
|
fAnimParamID(0) |
|
{ |
|
} |
|
|
|
BOOL plMtlAnimProc::DlgProc(TimeValue t, IParamMap2* pm, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) |
|
{ |
|
switch (msg) |
|
{ |
|
case WM_INITDIALOG: |
|
{ |
|
IParamBlock2* pb = pm->GetParamBlock(); |
|
|
|
IOnInitDlg(hWnd, pb); |
|
|
|
IUpdateMtlButton(hWnd, pb); |
|
} |
|
return TRUE; |
|
|
|
case WM_COMMAND: |
|
{ |
|
int cmd = HIWORD(wParam); |
|
int resID = LOWORD(wParam); |
|
|
|
IParamBlock2* pb = pm->GetParamBlock(); |
|
|
|
if (cmd == BN_CLICKED && resID == fMtlButtonID) |
|
{ |
|
IMtlButtonPress(hWnd, pb); |
|
return TRUE; |
|
} |
|
else if (cmd == BN_CLICKED && resID == fNodeButtonID) |
|
{ |
|
INodeButtonPress(hWnd, pb); |
|
return TRUE; |
|
} |
|
else if (cmd == CBN_SELCHANGE && resID == fAnimComboID) |
|
{ |
|
IAnimComboChanged(hWnd, pb); |
|
return TRUE; |
|
} |
|
else if (IUserCommand(hWnd, pb, cmd, resID)) |
|
return TRUE; |
|
} |
|
break; |
|
} |
|
|
|
return FALSE; |
|
} |
|
|
|
void plMtlAnimProc::IUpdateMtlButton(HWND hWnd, IParamBlock2* pb) |
|
{ |
|
HWND hMtl = GetDlgItem(hWnd, fMtlButtonID); |
|
|
|
// Get the saved material |
|
Mtl *savedMtl = IGetMtl(pb); |
|
|
|
if (savedMtl) |
|
SetWindowText(hMtl, savedMtl->GetName()); |
|
else |
|
SetWindowText(hMtl, "(none)"); |
|
|
|
// Enable the node button if a material is selected |
|
EnableWindow(GetDlgItem(hWnd, fNodeButtonID), (savedMtl != nil)); |
|
|
|
// Update the dependencies of this |
|
IUpdateNodeButton(hWnd, pb); |
|
} |
|
|
|
void plMtlAnimProc::IUpdateNodeButton(HWND hWnd, IParamBlock2* pb) |
|
{ |
|
ISetNodeButtonText(hWnd, pb); |
|
|
|
// Update the dependencies of this |
|
ILoadAnimCombo(hWnd, pb); |
|
} |
|
|
|
void plMtlAnimProc::ILoadAnimCombo(HWND hWnd, IParamBlock2* pb) |
|
{ |
|
HWND hAnim = GetDlgItem(hWnd, fAnimComboID); |
|
|
|
ComboBox_ResetContent(hAnim); |
|
int sel = ComboBox_AddString(hAnim, ENTIRE_ANIMATION_NAME); |
|
ComboBox_SetCurSel(hAnim, sel); |
|
|
|
const char* savedName = pb->GetStr(fAnimParamID); |
|
if (!savedName) |
|
savedName = ""; |
|
|
|
Mtl* mtl = IGetMtl(pb); |
|
if (mtl) |
|
{ |
|
plNotetrackAnim anim(mtl, nil); |
|
plString animName; |
|
while (!(animName = anim.GetNextAnimName()).IsNull()) |
|
{ |
|
int idx = ComboBox_AddString(hAnim, animName.c_str()); |
|
ComboBox_SetItemData(hAnim, idx, 1); |
|
if (!animName.Compare(savedName)) |
|
ComboBox_SetCurSel(hAnim, idx); |
|
} |
|
|
|
EnableWindow(hAnim, TRUE); |
|
} |
|
else |
|
EnableWindow(hAnim, FALSE); |
|
|
|
// Update the dependencies of this |
|
ILoadUser(hWnd, pb); |
|
} |
|
|
|
void plMtlAnimProc::IMtlButtonPress(HWND hWnd, IParamBlock2* pb) |
|
{ |
|
// Let the user pick a new material |
|
Mtl* pickedMtl = plPickMaterialMap::PickMaterial(plMtlCollector::kUsedOnly | |
|
plMtlCollector::kPlasmaOnly); |
|
|
|
// Save the mtl in the pb and update the interface |
|
if (pickedMtl != nil) |
|
{ |
|
if (pb->GetParameterType(fMtlParamID) == TYPE_REFTARG) |
|
pb->SetValue(fMtlParamID, 0, (ReferenceTarget*)pickedMtl); |
|
else |
|
pb->SetValue(fMtlParamID, 0, pickedMtl); |
|
} |
|
|
|
|
|
// Make sure the current node has the selected material on it (clear it otherwise) |
|
INode* node = pb->GetINode(fNodeParamID); |
|
if (!pickedMtl || !node || node->GetMtl() != pickedMtl) |
|
pb->SetValue(fNodeParamID, 0, (INode*)nil); |
|
|
|
IUpdateMtlButton(hWnd, pb); |
|
} |
|
|
|
void plMtlAnimProc::INodeButtonPress(HWND hWnd, IParamBlock2* pb) |
|
{ |
|
IPickNode(pb); |
|
|
|
IUpdateNodeButton(hWnd, pb); |
|
} |
|
|
|
void plMtlAnimProc::IAnimComboChanged(HWND hWnd, IParamBlock2* pb) |
|
{ |
|
HWND hCombo = GetDlgItem(hWnd, fAnimComboID); |
|
int idx = ComboBox_GetCurSel(hCombo); |
|
|
|
if (idx != CB_ERR) |
|
{ |
|
if (ComboBox_GetItemData(hCombo, idx) == 0) |
|
pb->SetValue(fAnimParamID, 0, ""); |
|
else |
|
{ |
|
// Get the name of the animation and save it |
|
char buf[256]; |
|
ComboBox_GetText(hCombo, buf, sizeof(buf)); |
|
pb->SetValue(fAnimParamID, 0, buf); |
|
} |
|
} |
|
|
|
// Update the dependencies of this |
|
ILoadUser(hWnd, pb); |
|
} |
|
|
|
Mtl* plMtlAnimProc::IGetMtl(IParamBlock2* pb) |
|
{ |
|
if (pb->GetParameterType(fMtlParamID) == TYPE_REFTARG) |
|
return (Mtl*)pb->GetReferenceTarget(fMtlParamID); |
|
else |
|
return pb->GetMtl(fMtlParamID); |
|
} |
|
|
|
static const char* kUserTypeAll = "(All)"; |
|
|
|
class plPickAllMtlNode : public plPickMtlNode |
|
{ |
|
protected: |
|
void IAddUserType(HWND hList) |
|
{ |
|
int idx = ListBox_AddString(hList, kUserTypeAll); |
|
if (!fPB->GetINode(fNodeParamID)) |
|
ListBox_SetCurSel(hList, idx); |
|
} |
|
|
|
void ISetUserType(plMaxNode* node, const char* userType) |
|
{ |
|
if (strcmp(userType, kUserTypeAll) == 0) |
|
ISetNodeValue(nil); |
|
} |
|
|
|
public: |
|
plPickAllMtlNode(IParamBlock2* pb, int nodeParamID, Mtl* mtl) : |
|
plPickMtlNode(pb, nodeParamID, mtl) |
|
{ |
|
} |
|
}; |
|
|
|
void plMtlAnimProc::IPickNode(IParamBlock2* pb) |
|
{ |
|
plPickAllMtlNode pick(pb, fNodeParamID, IGetMtl(pb)); |
|
pick.DoPick(); |
|
} |
|
|
|
void plMtlAnimProc::ISetNodeButtonText(HWND hWnd, IParamBlock2* pb) |
|
{ |
|
HWND hNode = GetDlgItem(hWnd, fNodeButtonID); |
|
|
|
INode* node = pb->GetINode(fNodeParamID); |
|
if (node) |
|
SetWindowText(hNode, node->GetName()); |
|
else |
|
SetWindowText(hNode, kUserTypeAll); |
|
} |
|
|
|
|