home *** CD-ROM | disk | FTP | other *** search
/ Xentax forum attachments archive / xentax.7z / 8090 / ModelEdit.7z / ModelEditDlg.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2006-03-08  |  174.4 KB  |  7,357 lines

  1. // ModelEditDlg.cpp : implementation file
  2. //
  3. // Changes:
  4. //
  5. // {BP 1/4/98} Switched to using DStream instead of MoFileIO
  6.  
  7. #include "precompile.h"
  8. #include "modeledit.h"
  9. #include "modeleditdlg.h"
  10. #include "renamedlg.h"
  11. #include "continuousdlg.h"
  12. #include "renderwnd.h"
  13. #include "keyframewnd.h"
  14. #include "modelinfodlg.h"
  15. #include "commandstringdlg.h"
  16. #include "model_ops.h"
  17. #include "model_cleanup.h"
  18. #include "mmsystem.h"
  19. #include "streamsim.h"
  20. #include "dimensionsdlg.h"
  21. #include "importanimation.h"
  22. #include "animframeratedlg.h"
  23. #include "keyframetimedlg.h"
  24. #include "translationdlg.h"
  25. #include "uvimportdlg.h"
  26. #include "animnumberdlg.h"
  27. #include "renamenodedlg.h"
  28. #include "rotationdlg.h"
  29. #include "aboutdlg.h"
  30. #include "stringdlg.h"
  31. #include "ltbasedefs.h"
  32. #include "addsocketdlg.h"
  33. #include "geomroutines.h"
  34. #include "transformmaker.h"
  35. #include "animmergedlg.h"
  36. #include "newgenlod.h"
  37. #include "addchildmodeldlg.h"
  38. #include "regmgr.h"
  39. #include "lteulerangles.h"
  40. #include "socketedit.h"
  41. #include "weightsetselectdlg.h"
  42. #include "ExportD3D_Dlg.h"
  43. #include "loadltadlg.h"
  44. #include <process.h>
  45. #include "importstringkeysdlg.h"
  46. #include "piecematerialdlg.h"
  47. #include "piecelodgendlg.h"
  48. #include "piecelodgen.h"
  49. #include "piecemerge.h"
  50. #include "importloddlg.h"
  51. #include "editobbdlg.h"
  52. #include "DirDialog.h"
  53. #include "ltwintreeitem.h"
  54. #include "ltwintreeitemiter.h"
  55. #include <set>
  56. #include "invalidanimdimsdlg.h"
  57.  
  58.  
  59. extern char g_szStartPath[_MAX_PATH];    // working directory at launch
  60. extern char g_szExePath[_MAX_PATH];        // path to executable
  61.  
  62.  
  63. // ------------------------------------------------------------------------
  64. /// std c++
  65. #include <fstream>
  66.  
  67. using namespace std;
  68.    
  69. /// lta parse...
  70. #include "ltaModel.h"
  71.  
  72. // ------------------------------------------------------------------------
  73.  
  74. #ifdef _DEBUG
  75. #define new DEBUG_NEW
  76. #undef THIS_FILE
  77. static char THIS_FILE[] = __FILE__;
  78. #endif
  79.  
  80. // Externs
  81. extern TCHAR szRegKeyCompany[];
  82. extern TCHAR szRegKeyApp[];
  83. extern TCHAR szRegKeyVer[];
  84.  
  85. // ------------------------------------------------------------------------
  86. // TempVarSetter
  87. // change value of variable for the life time of the class instance.
  88. //
  89. // TempVarSetter<int> tmpVal( m_IntVal, 100 );
  90. // m_IntVal is equal to 100 until tmpVal gets deconstructed. 
  91. // ------------------------------------------------------------------------
  92. template<class T>
  93. class TempVarSetter
  94. {
  95. public:
  96.             
  97.             TempVarSetter(T *pVar, T newVal)
  98.             {
  99.                 m_PrevVal = *pVar;
  100.                 m_pValue = pVar;
  101.                 *pVar = newVal;
  102.             }
  103.  
  104.             ~TempVarSetter()
  105.             {
  106.                 *m_pValue = m_PrevVal;
  107.             }
  108.              
  109. private:
  110.     T        *m_pValue;
  111.     T        m_PrevVal;
  112. };
  113.  
  114.  
  115. // Model transition time (this is a console variable in the engine)..
  116. int g_CV_ModelTransitionMS = 200;
  117.  
  118.  
  119. #define MENUCHECK(test) ((test) ? MF_CHECKED : MF_UNCHECKED)
  120.  
  121. bool g_bUpdateNodeFlags = false;
  122.  
  123. // ------------------------------------------------------------------------
  124. // IsLtaFile
  125. // does this filename have an lta extention, (case insensitive)
  126. // ------------------------------------------------------------------------
  127. static inline 
  128. int IsFilenameLTAExt( const char *filename )
  129. {
  130.     CString pathName ;
  131.  
  132.     // not enough chars in the name  
  133.     if( strlen( filename ) < 4 )
  134.         return 0;
  135.  
  136.     pathName = filename ; 
  137.     CString szFileExt = pathName.Right(4);
  138.     szFileExt.MakeLower();
  139.  
  140.     
  141.     //check for either normal or compressed extensions
  142.     if(( szFileExt == ".lta" ) || ( szFileExt == ".ltc" ))
  143.     {
  144.         return 1;
  145.     }
  146.  
  147.     else return 0;
  148.  
  149. }
  150.  
  151. // Used for socket rotation and positioning.
  152. float GetRotAngle(int delta)
  153. {
  154.     return ((delta * MATH_CIRCLE) / 360.0f) * 0.25f;
  155. }
  156.  
  157. float GetPosAmount(int delta)
  158. {
  159.     return (float)delta * (1.0f / 64.0f);
  160. }
  161.  
  162. float GetScaleAmount(int delta)
  163. {
  164.     return 1.0f + ((float)delta * (1.0f / 64.0f));
  165. }
  166.  
  167. // ------------------------------------------------------------------------
  168. // GetModelMaxLODDist
  169. // get the largest largest dist specified in any piece of a model.
  170. // ------------------------------------------------------------------------
  171. float GetModelMaxLODDist( Model *pModel )
  172. {
  173.     float max_dist = 0.0f ;
  174.  
  175.     if( !pModel )
  176.         return max_dist ;
  177.  
  178.     for( int i = 0 ;i < pModel->NumPieces() ; i++ )
  179.     {
  180.         ModelPiece *pPiece = pModel->GetPiece(i);
  181.         float max = pPiece->GetMaxDist();
  182.         if( max > max_dist )
  183.             max_dist = max ;
  184.     }
  185.     return max_dist ;
  186. }
  187. // ------------------------------------------------------------------------
  188. // AddTracker
  189. // ui thing.
  190. // ------------------------------------------------------------------------
  191. void AddTracker(CModelEditDlg *pDlg, COLORREF color, UINT ctlID, RTType type, DWORD iAxis)
  192. {
  193.     RectTracker *pTracker;
  194.     CWnd *pWnd;
  195.  
  196.     if(pTracker = new RectTracker)
  197.     {
  198.         pTracker->m_Color = color;
  199.         pTracker->m_CtlID = ctlID;
  200.  
  201.         if(pWnd = pDlg->GetDlgItem(ctlID))
  202.         {
  203.             pWnd->GetClientRect(&pTracker->m_Rect);
  204.             pWnd->ClientToScreen(&pTracker->m_Rect);
  205.             pDlg->ScreenToClient(&pTracker->m_Rect);
  206.         }
  207.  
  208.         if(pTracker->m_Wnd.Create(
  209.             NULL, 
  210.             "RectTracker", 
  211.             WS_CHILD | WS_VISIBLE, 
  212.             pTracker->m_Rect, 
  213.             pDlg, 
  214.             -1, 
  215.             NULL))
  216.         {
  217.             pTracker->m_Wnd.SetColor(color);
  218.             pTracker->m_Wnd.SetForward(TRUE);
  219.         }
  220.  
  221.         pTracker->m_Type = type;
  222.         pTracker->m_Axis = iAxis;
  223.         pDlg->m_Trackers.Append(pTracker);
  224.     }
  225. }
  226.  
  227. ///////////////////////////////////////////////////////////////////////////
  228. // ------------------------------------------------------------------------
  229. // MEAnimInfo 
  230. // ------------------------------------------------------------------------
  231.  
  232. MEAnimInfo::MEAnimInfo()
  233. {
  234.     m_bAnimPlayingForward = FALSE;
  235.     m_dwNumTagged = 0;
  236. }
  237.  
  238.  
  239. void MEAnimInfo::Reset(Model *pModel)
  240. {
  241.     m_Wnd.SetActive(FALSE);
  242.     m_Wnd.SetAnim(NULL);
  243.     m_Tracker.m_TimeRef.Init(pModel);
  244. }
  245.  
  246.  
  247. void MEAnimInfo::StartPlayback()
  248. {
  249.     StopPlayback();
  250.     m_bAnimPlayingForward = TRUE;
  251. }
  252.  
  253.  
  254. void MEAnimInfo::StopPlayback()
  255. {
  256.     m_bAnimPlayingForward = FALSE;
  257.     m_Wnd.ForceNearestKeyframe();
  258. }
  259.  
  260.  
  261. BOOL MEAnimInfo::IsValid()
  262. {
  263.     return m_Tracker.m_TimeRef.IsValid();    
  264. }
  265.  
  266.  
  267. void MEAnimInfo::SetKeyframeWindowTime()
  268. {
  269.     m_Wnd.SetTime(m_Tracker.m_TimeRef.m_Cur.m_Time);
  270. }
  271.  
  272.  
  273. ModelAnim* MEAnimInfo::PrevAnim()
  274. {
  275.     if(IsValid())
  276.         return m_Tracker.m_TimeRef.m_pModel->GetAnim(PrevAnimIndex());
  277.     else
  278.         return NULL;
  279. }
  280.  
  281.  
  282. ModelAnim* MEAnimInfo::CurAnim()
  283. {
  284.     if(IsValid())
  285.         return m_Tracker.m_TimeRef.m_pModel->GetAnim(CurAnimIndex());
  286.     else
  287.         return NULL;
  288. }
  289.  
  290.  
  291. /////////////////////////////////////////////////////////////////////////////
  292. // CModelEditDlg dialog
  293.  
  294. CModelEditDlg::CModelEditDlg(CWnd* pParent /*=NULL*/)
  295.     : CDialog(CModelEditDlg::IDD, pParent),
  296.     m_AllocCount(&g_DefAlloc),
  297.     m_pDimensionDlg(NULL)
  298. {
  299.     DWORD i;
  300.     MEAnimInfo *pInfo;
  301.     LTAnimTracker *animTrackerPointers[NUM_ANIM_INFOS];
  302.     UINT animButtonIDs[NUM_ANIM_INFOS] =
  303.     {
  304.         IDC_ANIMATION1,
  305.         IDC_ANIMATION2,
  306.         IDC_ANIMATION3,
  307.         IDC_ANIMATION4
  308.     };
  309.  
  310.     //{{AFX_DATA_INIT(CModelEditDlg)
  311.     m_bDrawSkeleton = FALSE;
  312.     //}}AFX_DATA_INIT
  313.     // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
  314.     m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
  315.     m_pModel = NULL;
  316.     m_bEndDialog = FALSE;
  317.     m_bTracking = FALSE;
  318.     m_bInStringChange = FALSE;
  319.  
  320.     m_LastIdleTime = timeGetTime();
  321.  
  322.     m_nCurrentLOD = PIECELOD_BASE;
  323.     m_CurrentLODDist = 0.0f ;
  324.  
  325.     m_bChangesMade = FALSE;
  326.     m_hAccel = NULL;
  327.  
  328.     m_RenderWnd.m_pModelEditDlg = this;
  329.     m_bFillingNodeList = FALSE;
  330.  
  331.     for(i=0; i < NUM_ANIM_INFOS; i++)
  332.     {
  333.         pInfo = GetAnimInfo(i);
  334.  
  335.         m_LastAnimActiveFlags[i] = 0;
  336.         animTrackerPointers[i] = &pInfo->m_Tracker;
  337.         pInfo->m_Tracker.m_Flags = AT_PLAYING | AT_LOOPING;
  338.         pInfo->m_AnimButtonID = animButtonIDs[i];
  339.         pInfo->m_Wnd.m_iWnd = i;
  340.     }
  341.  
  342.     m_RenderWnd.InitAnims(animTrackerPointers);
  343.  
  344.     m_RenderWnd.ResetLocator();    
  345.     
  346.     m_pImportStringKeyDlg = NULL;    
  347.  
  348.     // get the project dir
  349.         // get the dep proj dir stuff it into the model db.
  350.     CRegMgr regMgr;
  351.     if (regMgr.Init(szRegKeyCompany, szRegKeyApp, szRegKeyVer, "OpenDir", HKEY_CURRENT_USER))
  352.     {
  353.         CString csOpenDir ;
  354.         UINT32 dwSize = 256;
  355.         regMgr.Get("dep_file_location", csOpenDir.GetBufferSetLength(dwSize), dwSize);
  356.         m_szCurProjectPath =  csOpenDir ;
  357.     }
  358.  
  359.     // should we require user confirmation of the load dialog
  360.     if( regMgr.Init( szRegKeyCompany, szRegKeyApp, szRegKeyVer, "Options", HKEY_CURRENT_USER ) )
  361.     {
  362.         m_bConfirmLoadDlg = regMgr.Get( "confirm_load", 1 ) > 0;
  363.     }
  364. }
  365.  
  366.  
  367. CModelEditDlg::~CModelEditDlg()
  368. {
  369.     if (m_pImportStringKeyDlg)
  370.     {
  371.         m_pImportStringKeyDlg->DestroyWindow();
  372.         delete m_pImportStringKeyDlg;
  373.         m_pImportStringKeyDlg = NULL;
  374.     }
  375.     
  376.     for( int i = 0; i < m_Trackers; i++ )
  377.     {
  378.         delete m_Trackers[i];
  379.     }
  380.  
  381.     DeleteModel();
  382. }
  383.  
  384. void CModelEditDlg::DoDataExchange(CDataExchange* pDX)
  385. {
  386.     CDialog::DoDataExchange(pDX);
  387.     //{{AFX_DATA_MAP(CModelEditDlg)
  388.     DDX_Control(pDX, IDC_ANIMLIST, m_AnimList);
  389. //    DDX_Control(pDX, IDC_PIECES, m_PieceList);
  390.     DDX_Control(pDX, IDC_NODELIST, m_NodeList);
  391.     DDX_Control(pDX, IDC_GLOBAL_SPACE, m_GlobalSpace);
  392.     DDX_Control(pDX, IDC_SOCKETLIST, m_SocketList);
  393.     DDX_Control(pDX, IDC_FRAMETIME, m_EditFrameTime);
  394.     DDX_Control(pDX, IDC_FRAMESTRING, m_EditFrameString);
  395.     DDX_Control(pDX, IDC_CHILDMODELS, m_ChildModelList);
  396.     //}}AFX_DATA_MAP
  397. }
  398.  
  399. BEGIN_MESSAGE_MAP(CModelEditDlg, CDialog)
  400.     //{{AFX_MSG_MAP(CModelEditDlg)
  401.     ON_WM_PAINT()
  402.     ON_WM_QUERYDRAGICON()
  403.     ON_BN_CLICKED(IDC_LOADMODEL, OnLoadModel)
  404.     ON_MESSAGE(WM_STARTIDLE, OnStartIdle)
  405.     ON_BN_CLICKED(ID_HELP_ABOUT, OnHelpAbout)
  406.     ON_BN_CLICKED(IDC_FPLAY, OnPlayForward)
  407.     ON_BN_CLICKED(IDC_STOP, OnStop)
  408.     ON_BN_CLICKED(IDC_MOVEDOWN, OnAnimMoveDown)
  409.     ON_BN_CLICKED(IDC_MOVEUP, OnAnimMoveUp)
  410.     ON_BN_CLICKED(IDC_DELETE, OnAnimDelete)
  411.     ON_BN_CLICKED(IDC_NEXTKEY, OnNextKeyframe)
  412.     ON_BN_CLICKED(IDC_PREVKEY, OnPrevKeyframe)
  413.     ON_BN_CLICKED(IDC_IMPORT, OnImport)
  414.     ON_BN_CLICKED(IDC_IMPORT_LODS, OnImportLODs)
  415.     ON_BN_CLICKED(IDC_SAVE, OnSave)
  416.     ON_BN_CLICKED(IDC_SAVEAS, OnSaveAs)
  417.     ON_BN_CLICKED(IDC_CREATE_SINGLE_FRAME, OnCreateSingleFrame)
  418.     ON_BN_CLICKED(IDC_RENAME, OnRenameAnim)
  419.     ON_BN_CLICKED(IDC_WIREFRAME, OnWireframe)
  420.     ON_BN_CLICKED(IDC_CONTINUOUS, OnContinuous)
  421.     ON_BN_CLICKED(IDC_CAMERA_FOLLOW, OnCameraFollow)
  422.     ON_BN_CLICKED(IDC_DIMS, OnDims)
  423.     ON_BN_CLICKED(IDC_ANIM_BOX, OnAnimBox)
  424.     ON_WM_HSCROLL()
  425.     ON_WM_KEYDOWN()
  426.     ON_BN_CLICKED(IDC_MODELINFO, OnModelInfo)
  427.     ON_BN_CLICKED(IDC_COMMANDSTRING_BUTTON, OnCommandString)
  428.     ON_BN_CLICKED(IDC_DIMENSIONS_BUTTON, OnDimensions)
  429.     ON_BN_CLICKED(IDC_ANIMATION_FRAMERATE, OnAnimationFramerate)
  430.     ON_BN_CLICKED(IDC_ANIMATIONLENGTH, OnAnimationLength)
  431.     ON_BN_CLICKED(IDC_ANIMATIONINTERPOLAION, OnAnimationInterpolation)
  432.     ON_BN_CLICKED(IDC_TRANSLATION_BUTTON, OnTranslationButton)
  433.     ON_BN_CLICKED(IDC_ROTATION_BUTTON, OnRotationButton)
  434.     ON_BN_CLICKED(IDC_SET_PROJ_DIR, OnSetProjectDir)
  435.     ON_BN_CLICKED(IDC_XSUB, OnXsub)
  436.     ON_BN_CLICKED(IDC_XADD, OnXadd)
  437.     ON_BN_CLICKED(IDC_YSUB, OnYsub)
  438.     ON_BN_CLICKED(IDC_YADD, OnYadd)
  439.     ON_BN_CLICKED(IDC_ZSUB, OnZsub)
  440.     ON_BN_CLICKED(IDC_ZADD, OnZadd)
  441.     ON_BN_CLICKED(IDC_NUMBER, OnNumberAnim)
  442.     ON_BN_CLICKED(IDC_DUPLICATEANIM, OnDuplicateAnim)
  443.     ON_BN_CLICKED(ID_ANIMATION_CREATEANIMFROMBINDPOSE, OnCreateAnimFromBindPose)
  444.     ON_BN_CLICKED(IDC_RENAMENODE, OnRenameNode)
  445.     ON_BN_CLICKED(IDC_UNROTATE_TOP_NODE, OnUnrotateTopNode)
  446.     ON_BN_CLICKED(ID_GENERATE_VERTEX_NORMALS, OnGenerateVertexNormals)
  447.     ON_BN_CLICKED(ID_REVERSE_ANIMATION, OnReverseAnimation)
  448.     ON_BN_CLICKED(ID_SELECT_NULL_NODES, OnSelectNullNodes)
  449.     ON_BN_CLICKED(ID_MODEL_REMOVENODE, OnRemoveNode)
  450.     ON_BN_CLICKED(ID_PIECE_SET_TEXTURE, OnSetTexture)
  451.     ON_BN_CLICKED(IDC_DRAWSKELETON, OnDrawSkeleton)
  452.     ON_BN_CLICKED(ID_SHOW_SOCKETS, OnShowSockets)
  453.     ON_COMMAND(ID_SHOW_TEXTURES, OnShowTextures)
  454.     ON_BN_CLICKED(ID_SHOW_ATTACHMENTS, OnShowAttachments)
  455.     ON_BN_CLICKED(ID_SOLID_ATTACHMENTS, OnSolidAttachments)
  456.     ON_BN_CLICKED(IDC_MOVEMENT_ENCODING, OnMovementEncoding)
  457.     ON_BN_CLICKED(ID_ADDCHILDMODEL, OnAddChildModel)
  458.     ON_BN_CLICKED(ID_REMOVECHILDMODEL, OnRemoveChildModel)
  459.     ON_BN_CLICKED(ID_ADD_SOCKET, OnAddSocket)
  460.     ON_BN_CLICKED(ID_REMOVE_SOCKET, OnRemoveSocket)
  461.     ON_BN_CLICKED(ID_RENAME_SOCKET, OnRenameSocket)
  462.     ON_BN_CLICKED(ID_REBUILDCHILDMODELTREE, OnRebuildChildModelTree)
  463.     ON_BN_CLICKED(ID_SHOW_NORMALS, OnShowNormals)
  464.     ON_BN_CLICKED(ID_SHOW_NORMALREF, OnShowNormalRef)
  465.     ON_BN_CLICKED(ID_OPTIONS_PROFILE, OnProfile)
  466.     ON_WM_TIMER()
  467.     ON_WM_LBUTTONDOWN()
  468.     ON_WM_MOUSEMOVE()
  469.     ON_WM_LBUTTONUP()
  470.     ON_BN_CLICKED(ID_MODEL_MOOD, OnMood)
  471.     ON_BN_CLICKED(ID_INTERNAL_RADIUS, OnInternalRadius)
  472.     ON_BN_CLICKED(ID_CALC_INTERNAL_RADIUS, OnCalcInternalRadius)
  473.     ON_BN_CLICKED(ID_EDIT_WEIGHTS, OnEditWeights)
  474.     ON_BN_CLICKED(IDC_CALC_OBB, OnReCalcOBBExtent)
  475.     ON_BN_CLICKED(ID_PIECE_INFO, OnPieceInfo)
  476.     ON_BN_CLICKED(ID_CREATE_NULL_LOD, OnCreateNullLOD)
  477.     ON_BN_CLICKED(ID_PIECE_SELECT_NONE, OnPieceSelectNone)
  478.     ON_BN_CLICKED(ID_PIECE_REMOVE_LODS, OnPieceRemoveLODs)
  479.     ON_BN_CLICKED(ID_PIECE_BUILD_LODS, OnPieceBuildLODs)
  480.     ON_BN_CLICKED(ID_PIECE_MERGE, OnPieceMerge)
  481.     ON_COMMAND(ID_PIECEEDIT_EXPANDALL, OnPieceExpandAll)
  482.     ON_COMMAND(ID_PIECEEDIT_COLLAPSEALL, OnPieceCollapseAll)
  483.     ON_NOTIFY(LVN_ENDLABELEDIT, IDC_NODELIST, OnEndlabeleditNodeList)
  484.     ON_NOTIFY(LVN_ITEMCHANGED, IDC_NODELIST, OnItemChangedNodeList)
  485.     ON_WM_DESTROY()
  486.     ON_MESSAGE(WM_LTTREE_SELCHANGED, OnTreeSelChanged)
  487.     ON_MESSAGE(WM_LTTREE_EDITTEXT, OnTreeEditText)
  488.     ON_NOTIFY(LVN_BEGINLABELEDIT, IDC_ANIMLIST, OnBeginLabelEditAnimList)
  489.     ON_NOTIFY(LVN_ENDLABELEDIT, IDC_ANIMLIST, OnEndLabelEditAnimList)
  490.     ON_NOTIFY(LVN_ITEMCHANGING, IDC_ANIMLIST, OnItemChangingAnimList)
  491.     ON_NOTIFY(LVN_BEGINDRAG, IDC_ANIMLIST, OnBeginDragAnimList)
  492.     ON_WM_CONTEXTMENU()
  493.     ON_COMMAND(IDC_SORTANIM_NAME, OnSortAnimName)
  494.     ON_COMMAND(IDC_SORTANIM_RELATION, OnSortAnimRelation)
  495.     ON_LBN_DBLCLK(IDC_SOCKETLIST, OnDblClkSocketList)
  496.     ON_EN_CHANGE(IDC_FRAMESTRING, OnFrameStringChange)
  497.     ON_COMMAND(ID_OPTIONS_NEWBACKGROUND, OnNewBgColor)
  498.     ON_COMMAND(ID_OPTIONS_LOADCONFIRM, OnLoadConfirm)
  499.     ON_COMMAND(ID_OPTIONS_SHOWORIGINALMODEL, OnOptionsShoworiginalmodel)
  500.     ON_COMMAND(IDC_CHANGE_FOV, OnChangeFov)
  501.     ON_COMMAND(IDC_COMPILE, OnCompile)
  502.     ON_COMMAND(IDC_SAVE_AND_COMPILE, OnSaveAndCompile)
  503.     ON_COMMAND(ID_EXPORTMODELSTRINGKEYS, OnExportModelStringKeys)
  504.     ON_COMMAND(ID_IMPORTMODELSTRINGKEYS, OnImportModelStringKeys)
  505.     ON_NOTIFY(HDN_ITEMCLICK, IDC_NODELIST, OnItemclickNodelist)
  506.     ON_COMMAND(ID_OPTIONS_SHOWVERTEXWEIGHTING, OnOptionsShowVertexWeighting)
  507.     ON_COMMAND(ID_NODEEDIT_EDITOBB, OnNodeeditEditobb)
  508.     ON_COMMAND(ID_NODEEDIT_RENAME, OnNodeEditRename)
  509.     ON_COMMAND(ID_NODEEDIT_LOOKAT, OnNodeEditLookAt)
  510.     ON_COMMAND(ID_SOCKETEDIT_LOOKAT, OnSocketEditLookAt)
  511.     ON_COMMAND(IDC_DELETEANIM, OnAnimDelete)
  512.     ON_COMMAND(IDC_DUPLICATEANIM, OnDuplicateAnim)
  513.     ON_COMMAND(IDC_CHANGE_FOV, OnChangeFov)
  514.     ON_COMMAND(IDC_CHANGE_FOV, OnChangeFov)
  515.     ON_COMMAND(ID_MODEL_EXPORTWEIGHTSETS, OnExportWeightSets)
  516.     ON_COMMAND(ID_MODEL_IMPORTWEIGHTSETS, OnImportWeightSets)
  517.     //}}AFX_MSG_MAP
  518. END_MESSAGE_MAP()
  519.  
  520.  
  521. /////////////////////////////////////////////////////////////////////////////
  522. // CModelEditDlg public member functions
  523.  
  524.  
  525. ModelSocket* CModelEditDlg::GetSelectedSocket()
  526. {
  527.     int curSel;
  528.  
  529.     if (!m_pModel)
  530.         return NULL;
  531.  
  532.     curSel = m_SocketList.GetCurSel();
  533.     if (curSel >= 0 && curSel < (int)m_pModel->NumSockets())
  534.     {
  535.         return m_pModel->GetSocket((DWORD)curSel);
  536.     }
  537.     else
  538.     {
  539.         return NULL;
  540.     }
  541. }
  542.  
  543.  
  544. CButton* CModelEditDlg::GetTransformEdit(UINT id)
  545. {
  546.     CWnd *pWnd;
  547.  
  548.     pWnd = (CWnd*)GetDlgItem(id);
  549.     if (pWnd /*&& pWnd->IsKindOf(RUNTIME_CLASS(CButton))*/)
  550.         return (CButton*)pWnd;
  551.     
  552.     return NULL;
  553. }
  554.  
  555.  
  556. BOOL CModelEditDlg::IsButtonSelected(UINT id)
  557. {
  558.     CButton *pButton;
  559.  
  560.     if (pButton = GetTransformEdit(id))
  561.     {
  562.         return !!(pButton->GetState() & 0x3);
  563.     }
  564.     else
  565.     {
  566.         return FALSE;
  567.     }
  568. }
  569.  
  570.  
  571. // The about dialog
  572. void CModelEditDlg::OnHelpAbout()
  573. {
  574.     CAboutDlg dlg;
  575.     IdleChanger idle(&m_cWinIdle, IDLE_DIALOG_DELAY);      
  576.     
  577.     dlg.DoModal();
  578. }
  579.  
  580. void CModelEditDlg::InitTaggedArrays()
  581. {
  582.     uint32 i;
  583.  
  584.     for(i=0; i < NUM_ANIM_INFOS; i++)
  585.     {
  586.         InitTaggedArray(i);
  587.     }
  588. }
  589.  
  590. void CModelEditDlg::InitTaggedArray(uint32 iAnimInfo)
  591. {
  592.     GetAnimInfo(iAnimInfo)->m_Wnd.InitTaggedArray();
  593. }
  594.  
  595. void CModelEditDlg::DeleteModel()
  596. {
  597.     if (m_pModel)
  598.     {
  599.         DeleteSocketAttachments();
  600.         
  601.         m_pModel->Term(TRUE); // We want it to delete the child models.
  602.         delete m_pModel;
  603.         m_pModel = NULL;
  604.     
  605.         ResetAnimInfos();
  606.     }
  607. }
  608.  
  609.  
  610. void CModelEditDlg::DeleteSocketAttachments()
  611. {
  612.     DWORD i;
  613.     ModelSocket *pSocket;
  614.  
  615.     
  616.     if (m_pModel)
  617.     {
  618.         // Delete models attached to sockets.
  619.         for (i=0; i < m_pModel->NumSockets(); i++)
  620.         {
  621.             pSocket = m_pModel->GetSocket(i);
  622.  
  623.             if (pSocket->m_pAttachment)
  624.             {
  625.                 delete pSocket->m_pAttachment;
  626.                 pSocket->m_pAttachment = NULL;
  627.             }
  628.         }
  629.     }
  630. }
  631.  
  632.  
  633. void CModelEditDlg::GetPlaybackActiveFlags(
  634.     DWORD dwActive[NUM_ANIM_INFOS], 
  635.     BOOL bAllIfNoKeysDown)
  636. {
  637.     DWORD i, nActive;
  638.  
  639.     // First clear the flags.
  640.     for(i=0; i < NUM_ANIM_INFOS; i++)
  641.         dwActive[i] = 0;
  642.  
  643.     // See what CTRL+1.. keys they have down.
  644.     nActive = 0;
  645.     for(i=0; i < NUM_ANIM_INFOS; i++)
  646.     {
  647.         if((GetAsyncKeyState(VK_CONTROL) & 0x8000) &&
  648.             (GetAsyncKeyState('1' + i) & 0x8000))
  649.         {
  650.             dwActive[i] |= PA_ACTIVE;
  651.             ++nActive;
  652.         }
  653.     }
  654.  
  655.     // If no special keys are down, apply the command to all animations.
  656.     if(nActive == 0 && bAllIfNoKeysDown)
  657.     {
  658.         for(i=0; i < NUM_ANIM_INFOS; i++)
  659.             dwActive[i] |= PA_ACTIVE;
  660.     }
  661.  
  662.     // Set the valid flag.
  663.     for(i=0; i < NUM_ANIM_INFOS; i++)
  664.     {
  665.         if(GetAnimInfo(i)->IsValid())
  666.             dwActive[i] |= PA_VALID;
  667.     }
  668. }
  669.  
  670.  
  671. void CModelEditDlg::SetCurrentPosition(
  672.     DWORD iAnimInfo,
  673.     DWORD nKeyframe1, 
  674.     DWORD nKeyframe2, 
  675.     float nPercentBetween)
  676. {
  677.     AnimTimeRef *pRef;
  678.     MEAnimInfo *pInfo;
  679.  
  680.     
  681.     ASSERT(iAnimInfo < NUM_ANIM_INFOS);
  682.     pInfo = &m_AnimInfos[iAnimInfo];
  683.     
  684.     pRef = &pInfo->m_Tracker.m_TimeRef;
  685.     pRef->SetKeyframePosition(
  686.         pRef->m_Prev.m_iAnim,
  687.         nKeyframe1, 
  688.         nKeyframe2, 
  689.         nPercentBetween);
  690.  
  691.     if(iAnimInfo == ANIMINFO_MAIN)
  692.     {
  693.         UpdateEditFrameString( );
  694.         UpdateEditFrameTime( );
  695.     }
  696. }
  697.                     
  698.  
  699. void CModelEditDlg::SetCurrentPosition(
  700.     CKeyframeWnd *pWnd,
  701.     DWORD nKeyframe1, 
  702.     DWORD nKeyframe2, 
  703.     float nPercentBetween)
  704. {
  705.     DWORD i;
  706.  
  707.     for(i=0; i < NUM_ANIM_INFOS; i++)
  708.     {
  709.         if(&m_AnimInfos[i].m_Wnd == pWnd)
  710.         {
  711.             SetCurrentPosition(i, nKeyframe1, nKeyframe2, nPercentBetween);
  712.             break;
  713.         }
  714.     }
  715. }
  716.                     
  717.  
  718. /////////////////////////////////////////////////////////////////////////////
  719. // CModelEditDlg protected member functions
  720.  
  721. void CModelEditDlg::OnIdle()
  722. {
  723.     uint32 i;
  724.     DWORD msDelta, dwTime;
  725.     MEAnimInfo *pInfo;
  726.  
  727.  
  728.     // Update the animation playback stuff.
  729.     OnSelChangeAnimList();
  730.  
  731.     dwTime = timeGetTime();
  732.  
  733.     msDelta = dwTime - m_LastIdleTime;
  734.     //msDelta = (DWORD)( (float)msDelta * .5f ) ;
  735.     msDelta = (DWORD)( (float)msDelta ) ;
  736.     msDelta = DCLAMP(msDelta, 1, 1000);
  737.  
  738.     m_LastIdleTime = dwTime;
  739.  
  740.  
  741.     for(i=0; i < NUM_ANIM_INFOS; i++)
  742.     {
  743.         pInfo = GetAnimInfo(i);
  744.  
  745.         if (pInfo->m_bAnimPlayingForward)
  746.         {
  747.             InterpForward(i, msDelta);
  748.         }
  749.     }
  750.  
  751.     DrawActiveAnimRects(FALSE);
  752.  
  753.     m_RenderWnd.Draw();
  754. }
  755.  
  756. void CModelEditDlg::InterpForward(uint32 iAnimInfo, DWORD msDelta)
  757. {
  758.     AnimTimeRef *pTimeRef;
  759.     MEAnimInfo *pInfo;
  760.  
  761.     
  762.     pInfo = GetAnimInfo(iAnimInfo);
  763.     pTimeRef = &pInfo->m_Tracker.m_TimeRef;
  764.  
  765.     // get the current time in the animation
  766.     trk_Update(&pInfo->m_Tracker, msDelta);
  767.  
  768.     // tell the keyframe window where are are
  769.     pInfo->SetKeyframeWindowTime();
  770.     
  771.     UpdateEditFrameString();
  772.     UpdateEditFrameTime();
  773. }
  774.  
  775. // {BP 1/20/97}
  776. // Verifies that two model files are similar...
  777. BOOL CModelEditDlg::VerifyModels( Model *pModel1, Model *pModel2 )
  778. {
  779.     if ( !RecurseAndVerifyModels( pModel1->GetRootNode(), pModel2->GetRootNode() ))
  780.         return FALSE;
  781.  
  782.     return TRUE;
  783. }
  784.  
  785. BOOL CModelEditDlg::RecurseAndVerifyModels( ModelNode* pNode1, ModelNode* pNode2 )
  786. {
  787.     if ( pNode1->m_Children.GetSize() != pNode2->m_Children.GetSize())
  788.     {
  789.         // models don't match
  790.         return FALSE;
  791.     }
  792.  
  793.     for (DWORD i = 0; i < pNode1->m_Children; i++)
  794.     {
  795.         if (!RecurseAndVerifyModels(pNode1->m_Children[i], pNode2->m_Children[i]))
  796.         {
  797.             return FALSE;
  798.         }
  799.     }
  800.  
  801.     return TRUE;
  802. }
  803.  
  804.  
  805. // ------------------------------------------------------------------------
  806. // load_LTA_Using_FeedBackDialog( filename, memory-allocation-counter )
  807. // helper function to load lta files and showing the load feed-back dialog.
  808. // returns NULL if failed, the alloc'd model file if successful.
  809. // ------------------------------------------------------------------------
  810. Model* CModelEditDlg::load_LTA_Using_FeedBackDialog( const char *pFilename, bool isChildModel  )
  811. {
  812.     void LoadLTAThreadMain( void* pUser );
  813.  
  814.     m_AllocCount.ClearCounts();
  815.  
  816.     //creat the dialog that will exist on this thread to display
  817.     //the status
  818.     CLoadLTADlg LoadDlg( !m_bConfirmLoadDlg );
  819.  
  820.     //tell it that the thread will now be running
  821.     CLoadLTADlg::SetLoadThreadDone(FALSE);
  822.     CLoadLTADlg::ClearLoadLog();
  823.  
  824.  
  825.     //create the parameters for the thread
  826.     CLoadLTAThreadParams Params;
  827.     Params.m_pAllocCount    = &m_AllocCount ;
  828.     Params.m_pModel            = NULL;
  829.     Params.m_bChildLoad     = isChildModel;
  830.     Params.m_Filename       = pFilename ;
  831.  
  832.     // tell the lta translation status thingy what to call when updateing 
  833.     CLTATranslStatus::SetLoadLogCB( CLoadLTADlg::AppendLoadLog );
  834.  
  835.     //spawn the new thread to handle the loading of the LTA
  836.     unsigned long hThread = _beginthread( LoadLTAThreadMain, 0, &Params );
  837.  
  838.     if( hThread == -1 )
  839.     {
  840.         MessageBox("Failed to create thread to load LTA", "Error!");
  841.         return FALSE;
  842.     }
  843.  
  844.     //set the filename
  845.     //LoadDlg.m_sFilename = pathName;
  846.     LoadDlg.m_sFilename = pFilename ;
  847.  
  848.     //tell the dialog to take control. It will not return until
  849.     //the LTA loading thread has finished and the user has closed
  850.     //it
  851.     LoadDlg.DoModal();
  852.  
  853.     //unload the parameters that have been modified by the thread
  854.     return  Params.m_pModel;    
  855. }
  856.  
  857.  
  858. // ------------------------------------------------------------------------
  859. // 
  860. // ------------------------------------------------------------------------
  861. Model* LoadChildModel(ModelLoadRequest *pRequest, char *pBaseName, char *pChildFilename)
  862. {
  863.     char dirName[256], newFilename[256];
  864.     Model *pModel;
  865.  
  866.     
  867.     CHelpers::ExtractNames(pBaseName, dirName, NULL, NULL, NULL);
  868.     if (dirName[0] == 0)
  869.     {
  870.         sprintf(newFilename, "%s", pChildFilename);
  871.     }
  872.     else
  873.     {
  874.         sprintf(newFilename, "%s\\%s", dirName, pChildFilename);
  875.     }
  876.  
  877.     CString puff;
  878.     puff= pBaseName ;
  879.     puff+=pChildFilename ;
  880.  
  881.     int base_is_lta = IsFilenameLTAExt( pBaseName ) ;
  882.     int child_is_lta= IsFilenameLTAExt( pChildFilename );
  883.  
  884.     if( base_is_lta && child_is_lta )
  885.     {
  886.         MessageBox(NULL, "Programer Error Report this as a bug.\r\nCannot Load LTA Child Models From ME",
  887.                     "Error in ChildModel Load", MB_OK);
  888.         pModel = NULL ;
  889.         return pModel;
  890.     }
  891.  
  892.     return NULL;
  893. }
  894.  
  895.  
  896. DRESULT ME_LoadChildFn(ModelLoadRequest *pRequest, Model **ppModel)
  897. {
  898.     *ppModel = LoadChildModel(pRequest, (char*)pRequest->m_pLoadFnUserData, pRequest->m_pFilename);
  899.     if (*ppModel)
  900.         return LT_OK;
  901.     else
  902.         return LT_NOCHANGE;
  903. }
  904.  
  905.  
  906. //this is the thread main function that handles the loading of an LTA file. The parameter
  907. //is a stucture containing a handle to an ifstream, and a pointer to where the model
  908. //will be stored.
  909. void LoadLTAThreadMain( void* pUser )
  910. {
  911.     //get the parameters
  912.     CLoadLTAThreadParams* pParams = (CLoadLTAThreadParams*)pUser;
  913.  
  914.     //verify the parameters are valid
  915.     ASSERT(pParams);
  916.     ASSERT(pParams->m_pAllocCount);
  917.  
  918.     //load up the model
  919.     if( pParams->m_bChildLoad)
  920.     {
  921.         pParams->m_pModel = ltaLoadChildModel(pParams->m_Filename.c_str(), pParams->m_pAllocCount);
  922.     }
  923.     else
  924.     {
  925.         pParams->m_pModel = ltaModelLoad(pParams->m_Filename.c_str(), *(pParams->m_pAllocCount));
  926.     }
  927.  
  928.     //tell the dialog we are done, and that it can exit
  929.     CLoadLTADlg::SetLoadThreadDone(TRUE);
  930.  
  931.     return;
  932. }
  933.  
  934. // ------------------------------------------------------------------------
  935. // DoLoadModel( filenmae , bMessage )
  936. // 
  937. // ------------------------------------------------------------------------
  938. BOOL CModelEditDlg::DoLoadModel(char *pFilename, BOOL bMessage)
  939. {
  940.     CString titleText;
  941.     Model *pModel;
  942.     ModelLoadRequest request;
  943.     DWORD i;
  944.  
  945.     // Stop any animations...
  946.     StopAllPlayback();
  947.  
  948.     BeginWaitCursor();
  949.  
  950.     // check for lta file. if so call ltaModelLoad 
  951.     // else bomb out.
  952.     if( IsFilenameLTAExt(pFilename )  )
  953.     {
  954.         // zap all the textures before loading up something new.
  955.         m_RenderWnd.ReleaseAllTextures() ;
  956.  
  957.         pModel = load_LTA_Using_FeedBackDialog( pFilename  );
  958.  
  959.         if( pModel == NULL )
  960.         {
  961.             MessageBox("Failed to load lta file","load error");
  962.         }
  963.     }
  964.     else 
  965.     {
  966.         // huh? don't know that extention ...
  967.         MessageBox( "unknown extension... " , "load model error", MB_OK);
  968.         EndWaitCursor();
  969.         return FALSE;
  970.     }
  971.     
  972.     // Get rid of the old one.
  973.     if( pModel != NULL )
  974.     {
  975.         DeleteModel();
  976.         m_pModel = pModel;
  977.         m_strFilename = pFilename;
  978.     }
  979.     else
  980.         return FALSE;
  981.  
  982.     //check and make sure animation dimensions are valid now
  983.     CheckValidAnimationDims();
  984.  
  985.     // init dialog controls
  986.     FillAnimList();
  987.     FillNodeList();
  988.     FillSocketList();
  989.     FillChildModelList();
  990.     FillPieceList( &m_PieceList, m_pModel );
  991.  
  992.     m_AnimList.SetItemState(0, LVIS_SELECTED, LVIS_SELECTED);
  993.     for (i = 1; i < (DWORD)m_AnimList.GetItemCount(); i++)
  994.         m_AnimList.SetItemState((int)i, 0, LVIS_SELECTED);
  995.  
  996.     // Init animations..
  997.     OnSelChangeAnimList();
  998.  
  999.  
  1000.     m_RenderWnd.AllocSelections( m_pModel->NumPieces(), m_pModel->NumNodes());
  1001.  
  1002.     // enable appropriate windows
  1003.  
  1004.     m_btnPrevKey.EnableWindow();
  1005.     m_btnStop.EnableWindow();
  1006.     m_btnFPlay.EnableWindow();
  1007.     m_btnNextKey.EnableWindow();
  1008.     m_btnMoveUp.EnableWindow();
  1009.     m_btnMoveDown.EnableWindow();
  1010.     m_btnDelete.EnableWindow();
  1011.     m_AnimList.EnableWindow();
  1012.  
  1013.  
  1014.     m_bChangesMade = FALSE;
  1015.  
  1016.  
  1017.     titleText.FormatMessage(IDS_TITLE_TEXT, pFilename);
  1018.     SetWindowText((LPCTSTR)titleText);
  1019.  
  1020.     m_pModel->SetFilename( pFilename );
  1021.  
  1022.     DVector temp;
  1023.     float mag;
  1024.  
  1025.     if (m_pModel->m_Anims > 0)
  1026.     {
  1027.         float fov = MATH_DEGREES_TO_RADIANS(m_RenderWnd.m_DrawStruct.m_FOV);
  1028.         
  1029.         static const float kfMaxFOV = 89.99f;
  1030.  
  1031.         //make sure that we never go beyond a valid FOV
  1032.         if( m_RenderWnd.m_DrawStruct.m_FOV > kfMaxFOV )
  1033.         {
  1034.             m_RenderWnd.m_DrawStruct.m_FOV = kfMaxFOV;
  1035.         }
  1036.         
  1037.         mag = m_pModel->m_GlobalRadius ;
  1038.  
  1039.         m_RenderWnd.m_Scale = mag / 200.0f;
  1040.         m_RenderWnd.m_Camera.Reset();
  1041.         m_RenderWnd.m_Camera.m_Position.z = ((mag) / (float)tan( fov ))  ; 
  1042.         m_RenderWnd.m_Camera.m_Position.z = (m_pModel->GetAnimInfo(0)->m_vDims.Mag() * 2);
  1043.  
  1044.         m_RenderWnd.m_Camera.Update();
  1045.     }
  1046.     else
  1047.     {
  1048.         m_RenderWnd.m_Scale = 1.0f;
  1049.     }
  1050.  
  1051.     UpdateEditFrameString( );
  1052.     UpdateEditFrameTime( );
  1053.  
  1054.     ProcessCommandString();
  1055.  
  1056.     SetCurrentLOD(0.0f);
  1057.     InitTheScrollBar(GetModelMaxLODDist(m_pModel));
  1058.  
  1059.     CheckChildModels(&request);
  1060.  
  1061.     // Load the sockets that are defined in the registry
  1062.     CRegMgr regMgr;
  1063.     if (regMgr.Init(szRegKeyCompany, szRegKeyApp, szRegKeyVer, "Attachments", HKEY_CURRENT_USER))
  1064.     {
  1065.         UINT32 dwSize = 256;
  1066.         CString csAttachment;
  1067.         for (i = 0; i < m_pModel->NumSockets(); i++)
  1068.         {
  1069.             ModelSocket *pSocket = m_pModel->GetSocket(i);
  1070.             if (!pSocket)
  1071.                 continue;
  1072.             dwSize = 256;
  1073.             if (regMgr.Get(pSocket->GetName(), csAttachment.GetBufferSetLength(dwSize), dwSize) != NULL)
  1074.             {
  1075.                 csAttachment.ReleaseBuffer(-1);
  1076.  
  1077.                 if (pSocket->m_pAttachment)
  1078.                     delete pSocket->m_pAttachment;
  1079.                 pSocket->m_pAttachment = NULL;
  1080.  
  1081.                 if (!csAttachment.IsEmpty())
  1082.                 {
  1083.                     const TCHAR* filename = csAttachment ;
  1084.                     if( IsFilenameLTAExt( filename ) )
  1085.                     {
  1086.                         Model *pModel = load_LTA_Using_FeedBackDialog( filename, false  );
  1087.                         if( pModel != NULL )
  1088.                         {
  1089.                             pSocket->m_pAttachment = pModel ;
  1090.                         }
  1091.                     }
  1092.                     else 
  1093.                     {
  1094.                     // Load the attachment
  1095.                     if (request.m_pFile = streamsim_Open(csAttachment, "rb"))
  1096.                     {
  1097.                         MessageBox("SOCKET LOAD CALLED OLD STYLE", "DEPRECATED", MB_OK);
  1098.                         request.m_pFile->Release();
  1099.                     }
  1100.                     }
  1101.                 }
  1102.             }
  1103.         }
  1104.     }
  1105.     
  1106.     // get the dep proj dir stuff it into the model db.
  1107.     if (regMgr.Init(szRegKeyCompany, szRegKeyApp, szRegKeyVer, "OpenDir", HKEY_CURRENT_USER))
  1108.     {
  1109.         CString csOpenDir ;
  1110.         UINT32 dwSize = 256;
  1111.         regMgr.Get("dep_file_location", csOpenDir.GetBufferSetLength(dwSize), dwSize);
  1112.         m_pModel->m_sProjectDir = csOpenDir ;
  1113.     }
  1114.  
  1115.     {
  1116.     // Ok, now we load up the texture maps, from the tools-info node... 
  1117.     Model::CTextureIndexMapIter it = m_pModel->m_TextureIndexMap.begin();
  1118.     Model::CTextureIndexMapIter end= m_pModel->m_TextureIndexMap.end();
  1119.     // export the index to texture name list
  1120.     for(  ; it != end ;    it++ )
  1121.     {
  1122.         uint32 index = (*it).first;
  1123.         string path = m_pModel->m_sProjectDir ;
  1124.         path += (*it).second;
  1125.  
  1126.         // if we fail to load its ok, 
  1127.         SetRenderTexture( path.c_str(), index );
  1128.     }
  1129.  
  1130.     }
  1131.  
  1132.     // [TMG] Update the dimensions dialog    
  1133.     if (m_pDimensionDlg)
  1134.     {
  1135.         m_pDimensionDlg->m_pModel = m_pModel;
  1136.     }
  1137.  
  1138.     EndWaitCursor();
  1139.     
  1140.     return TRUE;// Success !!
  1141. }
  1142.  
  1143.  
  1144. void CModelEditDlg::UpdateMenuChecks()
  1145. {
  1146.     CMenu *pMenu;
  1147.  
  1148.     pMenu = GetMenu();
  1149.     if (!pMenu)
  1150.         return;
  1151.  
  1152.     // Since the submenus don't have IDs....
  1153.     pMenu = pMenu->GetSubMenu(6);
  1154.     if (!pMenu)
  1155.         return;
  1156.  //t.f important
  1157.     pMenu->CheckMenuItem(IDC_CAMERA_FOLLOW, MENUCHECK(m_RenderWnd.m_bCameraFollow));
  1158.     pMenu->CheckMenuItem(IDC_WIREFRAME, MENUCHECK(m_RenderWnd.m_DrawStruct.m_bWireframe));
  1159.     pMenu->CheckMenuItem(IDC_DIMS, MENUCHECK(m_RenderWnd.m_DrawStruct.m_bDims));
  1160.     pMenu->CheckMenuItem(IDC_ANIM_BOX, MENUCHECK(m_RenderWnd.m_DrawStruct.m_bAnimBox));
  1161.     pMenu->CheckMenuItem(IDC_DRAWSKELETON, MENUCHECK(m_RenderWnd.m_DrawStruct.m_bDrawSkeleton));
  1162.     pMenu->CheckMenuItem(ID_OPTIONS_SHOWORIGINALMODEL, MENUCHECK(m_RenderWnd.m_DrawStruct.m_bDrawOriginalModel));
  1163.  
  1164.     pMenu->CheckMenuItem(ID_SHOW_TEXTURES, MENUCHECK(m_RenderWnd.m_DrawStruct.m_bDrawTextures));
  1165.     pMenu->CheckMenuItem(ID_SHOW_SOCKETS, MENUCHECK(m_RenderWnd.m_DrawStruct.m_bDrawSockets));
  1166.     pMenu->CheckMenuItem(ID_SHOW_ATTACHMENTS, MENUCHECK(m_RenderWnd.m_DrawStruct.m_bDrawAttachments));
  1167.     pMenu->CheckMenuItem(ID_SOLID_ATTACHMENTS, MENUCHECK(m_RenderWnd.m_DrawStruct.m_bSolidAttachments));
  1168.     pMenu->CheckMenuItem(ID_SHOW_NORMALS, MENUCHECK(m_RenderWnd.m_DrawStruct.m_bNormals));
  1169.     pMenu->CheckMenuItem(ID_SHOW_NORMALREF, MENUCHECK(m_RenderWnd.m_DrawStruct.m_bShowNormalRef));
  1170.     pMenu->CheckMenuItem(ID_OPTIONS_PROFILE, MENUCHECK(m_RenderWnd.m_DrawStruct.m_bProfile));
  1171.  
  1172.     pMenu->CheckMenuItem(ID_OPTIONS_SHOWVERTEXWEIGHTING, MENUCHECK(m_RenderWnd.m_DrawStruct.m_bDrawVertexWeights));
  1173.  
  1174.     pMenu->CheckMenuItem(ID_OPTIONS_LOADCONFIRM, MENUCHECK(m_bConfirmLoadDlg));
  1175. }
  1176.  
  1177.  
  1178. void CModelEditDlg::CheckChildModels(ModelLoadRequest *pRequest)
  1179. {
  1180.     Model *pModel;
  1181.     DWORD i;
  1182.     ChildInfo *pChild;
  1183.     CString str;
  1184.  
  1185.     
  1186.     pModel = m_pModel;
  1187.     if (!pModel)
  1188.         return;
  1189.  
  1190.     // Regenerate the trees.
  1191.     if (!pRequest->m_bTreesValid)
  1192.     {
  1193.         if (DoMessageBox(IDS_TREESINVALID, MB_YESNO) == IDYES)
  1194.         {
  1195.             for (i=0; i < pModel->NumChildModels(); i++)
  1196.             {
  1197.                 pChild = pModel->GetChildModel(i);
  1198.                 
  1199.                 if (!pChild->m_bTreeValid)
  1200.                 {
  1201.                     str.FormatMessage(IDS_CANTCREATETREE, pChild->m_pFilename);
  1202.                     DoMessageBox(str, MB_OK);
  1203.                 }
  1204.             }
  1205.         }
  1206.     }
  1207.  
  1208.     // Now check to see if it's out of date with any of its child models.
  1209.     for (i=0; i < pModel->NumChildModels(); i++)
  1210.     {
  1211.         pChild = pModel->GetChildModel(i);
  1212.  
  1213.         // Was it unable to load?
  1214.         if (!pChild->m_pModel)
  1215.         {
  1216.             str.FormatMessage(IDS_CANT_LOAD_CHILD_MODEL, pChild->m_pFilename);
  1217.             DoMessageBox(str, MB_OK);
  1218.         }
  1219.  
  1220.         if (!pChild->m_bTreeValid)
  1221.             continue;
  1222.     }
  1223. }
  1224.  
  1225. // fill a piece list with a given models pieces
  1226. void CModelEditDlg::FillPieceList( CLTWinTreeMgr* tree, Model* model )
  1227. {
  1228.     DWORD i;
  1229.     char buf[256];
  1230.  
  1231.     tree->ClearSelection();
  1232.     tree->DeleteTree();
  1233.  
  1234.     if( !model )
  1235.         return;
  1236.  
  1237.     for( i = 0; i < model->NumPieces(); i++ )
  1238.     {
  1239.         // get the current piece
  1240.         ModelPiece* curPiece = model->GetPiece( i );
  1241.         if( !curPiece )
  1242.         {
  1243.             ASSERT(0);
  1244.             continue;
  1245.         }
  1246.  
  1247.         // add the parent to the tree control
  1248.         PieceListItem* item = new PieceListItem( curPiece->GetName() );
  1249.         item->m_LOD = -1;
  1250.         item->m_PieceNum = i;
  1251.         item->SetTextEditable( TRUE );
  1252.         CLTWinTreeKey parent = tree->AddItem( item, NULLITEM, FALSE );
  1253.  
  1254.         for( int j = 0; j < curPiece->NumLODs(); j++ )
  1255.         {
  1256.             sprintf( buf, "%.2f", curPiece->m_LODDists[j] );
  1257.             item = new PieceListItem( buf );
  1258.             item->m_LOD = j;
  1259.             item->m_PieceNum = i;
  1260.             item->SetTextEditable( FALSE );
  1261.             tree->AddItem( item, parent, FALSE );
  1262.         }
  1263.     }
  1264. }
  1265.  
  1266.  
  1267. void CModelEditDlg::FillNodeList()
  1268. {
  1269.     DWORD i;
  1270.     ModelNode *pNode;
  1271.  
  1272.  
  1273.     m_NodeList.DeleteAllItems();
  1274.     
  1275.     if (!m_pModel)
  1276.         return;
  1277.  
  1278.     g_bUpdateNodeFlags = false;
  1279.  
  1280.     m_bFillingNodeList = TRUE;
  1281.  
  1282.         for (i = 0; i < m_pModel->NumNodes(); i++)
  1283.         {
  1284.             pNode = m_pModel->GetNode(i);
  1285.             
  1286.             m_NodeList.InsertItem(i, pNode->GetName());
  1287.             m_NodeList.SetCheck((int)i, !!(pNode->m_Flags & MNODE_ROTATIONONLY));
  1288.         }
  1289.  
  1290.     g_bUpdateNodeFlags = true;
  1291.  
  1292.     m_bFillingNodeList = FALSE;
  1293. }
  1294.  
  1295.  
  1296. void CModelEditDlg::FillSocketList(BOOL bPreserveSel)
  1297. {
  1298.     DWORD i;
  1299.     ModelSocket *pSocket;
  1300.     int iLastSel;
  1301.  
  1302.     
  1303.     iLastSel = m_SocketList.GetCurSel();
  1304.  
  1305.     m_SocketList.ResetContent();
  1306.  
  1307.     if (!m_pModel)
  1308.         return;
  1309.  
  1310.     for (i=0; i < m_pModel->NumSockets(); i++)
  1311.     {
  1312.         pSocket = m_pModel->GetSocket(i);
  1313.  
  1314.         m_SocketList.AddString(pSocket->GetName());
  1315.     }
  1316.  
  1317.     if (bPreserveSel)
  1318.     {
  1319.         m_SocketList.SetCurSel(iLastSel);
  1320.     }
  1321.     else
  1322.     {
  1323.         m_SocketList.SetCurSel(0);
  1324.     }
  1325. }
  1326.  
  1327.  
  1328. void CModelEditDlg::FillAnimList()
  1329. {
  1330.     DWORD i;
  1331.  
  1332.     m_AnimList.DeleteAllItems();
  1333.  
  1334.     if (m_pModel)
  1335.     {
  1336.         for (i = 0; i < m_pModel->m_Anims; i++)
  1337.         {
  1338.             m_AnimList.InsertItem(i, m_pModel->GetAnim(i)->GetName());
  1339.             m_AnimList.SetCheck(i, (m_pModel->GetAnimInfo(i))->GetAnimOwner() == m_pModel);
  1340.         }
  1341.     }
  1342. }
  1343.  
  1344.  
  1345. void CModelEditDlg::FillChildModelList()
  1346. {
  1347.     ChildInfo *pChild;
  1348.     DWORD i;
  1349.  
  1350.     m_ChildModelList.ResetContent();
  1351.  
  1352.     if (m_pModel)
  1353.     {
  1354.         for (i=0; i < m_pModel->NumChildModels(); i++)
  1355.         {
  1356.             pChild = m_pModel->GetChildModel(i);
  1357.  
  1358.             if (pChild != m_pModel->GetSelfChildModel())
  1359.             {
  1360.                 m_ChildModelList.AddString(pChild->m_pFilename);
  1361.             }
  1362.         }
  1363.     }
  1364. }
  1365.  
  1366.  
  1367. void CModelEditDlg::InitTheScrollBar(float max_dist )
  1368. {
  1369.     
  1370.     m_LODSlider.m_ScrollBar       = (CScrollBar*)GetDlgItem(IDC_LOD_SCROLL);
  1371.  
  1372.     m_LODSlider.m_CurrentValue = (CMyEdit*)GetDlgItem(IDC_CURRENT_DIST);
  1373.     m_LODSlider.m_MaxDist          = GetDlgItem(IDC_MAX_DIST);
  1374.     m_LODSlider.m_MinDist          = GetDlgItem(IDC_MIN_DIST);
  1375.  
  1376.     SCROLLINFO info;
  1377.  
  1378.     if (m_LODSlider.m_ScrollBar)
  1379.     {
  1380.         info.cbSize = sizeof(info);
  1381.         info.fMask = SIF_ALL;
  1382.         info.nMin = 0;
  1383.         info.nMax = (int)max_dist ;
  1384.         info.nPage = 1;
  1385.         info.nPos = info.nTrackPos = 0;
  1386.         
  1387.         m_LODSlider.m_ScrollBar->SetScrollInfo(&info);
  1388.     }
  1389.  
  1390.     m_LODSlider.SetMinDist(0);
  1391.     m_LODSlider.SetMaxDist(max_dist);
  1392.     m_LODSlider.SetCurrentValue(0);
  1393.  
  1394. }
  1395.  
  1396.  
  1397.  
  1398. /////////////////////////////////////////////////////////////////////////////
  1399. // CModelEditDlg message handlers
  1400.  
  1401. LONG CModelEditDlg::OnStartIdle (UINT, LONG)
  1402. {
  1403.     static BOOL bFirst=TRUE;
  1404.  
  1405.     // Handle startup options (we do it in the idle handler so we can do MessageBox).
  1406.     if (bFirst)
  1407.     {
  1408.         bFirst = FALSE;
  1409.  
  1410.         if (__argc > 1)
  1411.         {
  1412.             DoLoadModel(__argv[1], FALSE);
  1413.         }
  1414.  
  1415.         if (__argc > 2)
  1416.         {
  1417.             SetRenderTexture(__argv[2]);
  1418.         }
  1419.     }
  1420.  
  1421.     MSG msg;
  1422.     if (!PeekMessage(&msg, GetSafeHwnd(), 0,0, PM_NOREMOVE))
  1423.         OnIdle();
  1424.     m_cWinIdle.NextIdle();
  1425.  
  1426.     return 0;
  1427. }
  1428.  
  1429.  
  1430. BOOL CModelEditDlg::OnInitDialog()
  1431. {
  1432.     CButton *pButton;
  1433.     UINT keyframeWndIDs[NUM_ANIM_INFOS] =
  1434.     {
  1435.         IDC_KEYFRAME1,
  1436.         IDC_KEYFRAME2,
  1437.         IDC_KEYFRAME3,
  1438.         IDC_KEYFRAME4
  1439.     };
  1440.     UINT animActiveRectIDs[NUM_ANIM_INFOS] =
  1441.     {
  1442.         IDC_ANIMACTIVE1,
  1443.         IDC_ANIMACTIVE2,
  1444.         IDC_ANIMACTIVE3,
  1445.         IDC_ANIMACTIVE4
  1446.     };
  1447.     uint32 i;
  1448.     MEAnimInfo *pInfo;
  1449.  
  1450.  
  1451.     // Run in a low-priority thread so we're friendly in the background..
  1452.     SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_LOWEST);
  1453.  
  1454.  
  1455.     CDialog::OnInitDialog();
  1456.  
  1457.     CRect rect;
  1458.  
  1459.     // Set up the node view
  1460.     m_NodeList.SetExtendedStyle(LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT);
  1461.     m_NodeList.GetWindowRect(&rect);
  1462.     m_NodeList.InsertColumn(0, "Nodes", LVCFMT_LEFT, rect.Width() -17);
  1463.  
  1464.     // Set up the piece view
  1465.     m_PieceList.SubclassDlgItem( IDC_PIECES, this );
  1466.     m_PieceList.EnableMultiSelect( TRUE );
  1467.     m_PieceList.EnableEditText( TRUE );
  1468.  
  1469.     // Set up the animation list
  1470.     m_AnimList.SetDropNotify(this, (FDragListCallback)OnDropAnimList);
  1471.     m_AnimList.SetExtendedStyle(LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT);
  1472.     m_AnimList.GetWindowRect(&rect);
  1473.     m_AnimList.InsertColumn(0, "Name", LVCFMT_LEFT, rect.Width() - 17);
  1474.  
  1475.     // Setup the trackers.
  1476.     AddTracker(this, RGB(255,0,0), IDC_SOCKETROTRIGHT, RT_ROTATION, 0);
  1477.     AddTracker(this, RGB(0,255,0), IDC_SOCKETROTUP, RT_ROTATION, 1);
  1478.     AddTracker(this, RGB(0,0,255), IDC_SOCKETROTFORWARD, RT_ROTATION, 2);
  1479.     AddTracker(this, RGB(255,0,0), IDC_SOCKETPOSRIGHT, RT_POSITION, 0);
  1480.     AddTracker(this, RGB(0,255,0), IDC_SOCKETPOSUP, RT_POSITION, 1);
  1481.     AddTracker(this, RGB(0,0,255), IDC_SOCKETPOSFORWARD, RT_POSITION, 2);
  1482.     AddTracker(this, RGB(255,0,0), IDC_SOCKETSCLRIGHT, RT_SCALE, 0);
  1483.     AddTracker(this, RGB(0,255,0), IDC_SOCKETSCLUP, RT_SCALE, 1);
  1484.     AddTracker(this, RGB(0,0,255), IDC_SOCKETSCLFORWARD, RT_SCALE, 2);
  1485.  
  1486.  
  1487.     if (pButton = GetTransformEdit(IDC_SOCKET_EDIT))
  1488.     {
  1489.         pButton->SetCheck(TRUE);
  1490.     }
  1491.  
  1492.     if (pButton = (CButton*)GetDlgItem(IDC_DIMS_EDIT))
  1493.     {
  1494.         pButton->SetCheck(TRUE);
  1495.     }
  1496.  
  1497.  
  1498.     m_hAccel = LoadAccelerators(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_ACCELERATOR1));
  1499.     SetFocus();
  1500.  
  1501.     // Set the icon for this dialog.  The framework does this automatically
  1502.     //  when the application's main window is not a dialog
  1503.     SetIcon(m_hIcon, TRUE);            // Set big icon
  1504.     SetIcon(m_hIcon, FALSE);        // Set small icon
  1505.     
  1506.     // Initialize the Bitmap Buttons
  1507.  
  1508.     m_btnPrevKey.AutoLoad (IDC_PREVKEY, this);
  1509.     m_btnStop.AutoLoad (IDC_STOP, this);
  1510.     m_btnFPlay.AutoLoad (IDC_FPLAY, this);
  1511.     m_btnNextKey.AutoLoad (IDC_NEXTKEY, this);
  1512.     m_btnMoveUp.AutoLoad (IDC_MOVEUP, this);
  1513.     m_btnMoveDown.AutoLoad (IDC_MOVEDOWN, this);
  1514.     m_btnNumber.AutoLoad (IDC_NUMBER, this);
  1515.     m_btnDelete.AutoLoad (IDC_DELETE, this);
  1516.  
  1517.     CheckDlgButton (IDC_CAMERA_FOLLOW, TRUE);
  1518.  
  1519.     // create the render window
  1520.  
  1521.     CWnd* pStaticWnd = GetDlgItem (IDC_RENDER);
  1522.     CRect rcStatic;
  1523.     pStaticWnd->GetWindowRect (rcStatic);
  1524.     ScreenToClient (rcStatic);
  1525.     if (!m_RenderWnd.Create (NULL, "Render Window", WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE, rcStatic, this, -1, NULL))
  1526.     {
  1527.         MessageBox ("Could not create render window", NULL, MB_OK);
  1528.         EndDialog (-1);
  1529.     }
  1530.  
  1531.     /*
  1532.     m_RenderWnd.SetWireframe (IsDlgButtonChecked (IDC_WIREFRAME));
  1533.     m_RenderWnd.SetCameraFollow (IsDlgButtonChecked (IDC_CAMERA_FOLLOW));
  1534.     m_RenderWnd.DrawDims (IsDlgButtonChecked (IDC_DIMS));
  1535.     m_RenderWnd.DrawModelBox (IsDlgButtonChecked (IDC_MODEL_BOX));
  1536.     m_RenderWnd.DrawAnimBox (IsDlgButtonChecked (IDC_ANIM_BOX));
  1537.     */
  1538.  
  1539.     // t.f important
  1540.     m_RenderWnd.m_bCameraFollow = TRUE;
  1541.     m_RenderWnd.m_DrawStruct.m_bWireframe = FALSE;
  1542.     m_RenderWnd.m_DrawStruct.m_bNormals = FALSE;
  1543.     m_RenderWnd.m_DrawStruct.m_bDims = FALSE;
  1544.     m_RenderWnd.m_DrawStruct.m_bAnimBox = FALSE;
  1545.     m_RenderWnd.m_DrawStruct.m_bDrawOriginalModel = FALSE;
  1546.     m_RenderWnd.m_DrawStruct.m_bDrawVertexWeights = FALSE;
  1547.     m_RenderWnd.m_DrawStruct.m_bMovementEncoding = false;
  1548.  
  1549.     m_RenderWnd.m_DrawStruct.m_bDrawTextures = TRUE;
  1550.     m_RenderWnd.m_DrawStruct.m_bDrawSockets = FALSE;
  1551.     m_RenderWnd.m_DrawStruct.m_bDrawAttachments = FALSE;
  1552.     m_RenderWnd.m_DrawStruct.m_bSolidAttachments = TRUE;
  1553.     m_RenderWnd.m_DrawStruct.m_bShowNormalRef = FALSE;
  1554.     m_RenderWnd.m_DrawStruct.m_bProfile = FALSE;
  1555.     UpdateMenuChecks();
  1556.  
  1557.     m_RenderWnd.m_DrawStruct.m_FOV = CalcFOV();
  1558.     // Update the registry with the FOV, just in case it's not there..
  1559.     SetFOV(m_RenderWnd.m_DrawStruct.m_FOV);
  1560.     
  1561.     InitTheScrollBar(0);
  1562.  
  1563.     
  1564.     
  1565.     // create the keyframe windows.
  1566.     for(i=0; i < NUM_ANIM_INFOS; i++)
  1567.     {
  1568.         pInfo = GetAnimInfo(i);
  1569.  
  1570.         // Create the keyframe window.
  1571.         if(pStaticWnd = GetDlgItem (keyframeWndIDs[i]))
  1572.         {
  1573.             pStaticWnd->GetWindowRect (rcStatic);
  1574.             ScreenToClient (rcStatic);
  1575.             if (!pInfo->m_Wnd.Create (NULL, "Keyframe Window", WS_CHILD | WS_VISIBLE, rcStatic, this, -1, NULL))
  1576.             {
  1577.                 MessageBox ("Could not create keyframe window", NULL, MB_OK);
  1578.                 EndDialog (-1);
  1579.             }
  1580.         }
  1581.  
  1582.         // Create the flags window.
  1583.         if(pStaticWnd = GetDlgItem(animActiveRectIDs[i]))
  1584.         {
  1585.             pStaticWnd->GetWindowRect (rcStatic);
  1586.             ScreenToClient (rcStatic);
  1587.             if (!pInfo->m_ActiveFlagsWnd.Create (NULL, "Anim Active Flags", WS_CHILD | WS_VISIBLE, rcStatic, this, -1, NULL))
  1588.             {
  1589.                 MessageBox ("Could not create anim flags window", NULL, MB_OK);
  1590.                 EndDialog (-1);
  1591.             }
  1592.         }    
  1593.  
  1594.         m_AnimInfos[i].m_Wnd.EnableWindow(TRUE);
  1595.     }
  1596.  
  1597.     // disable appropriate windows 
  1598.  
  1599.     m_btnPrevKey.EnableWindow (FALSE);
  1600.     m_btnStop.EnableWindow (FALSE);
  1601.     m_btnFPlay.EnableWindow (FALSE);
  1602.     m_btnNextKey.EnableWindow (FALSE);
  1603.     m_btnMoveUp.EnableWindow (FALSE);
  1604.     m_btnMoveDown.EnableWindow (FALSE);
  1605.     m_btnDelete.EnableWindow (FALSE);
  1606.     m_AnimList.EnableWindow (FALSE);
  1607.  
  1608.     // Start the idle loop (Note : It is currently set to not idle more quickly than every 20ms)
  1609.     m_cWinIdle.StartIdle(GetSafeHwnd(), WM_STARTIDLE, 0,0, 20);
  1610.     m_cWinIdle.NextIdle();
  1611.  
  1612.     UpdateEditFrameString( );
  1613.     UpdateEditFrameTime( );
  1614.  
  1615.     // Create the import string keys dialog
  1616.  
  1617.     m_pImportStringKeyDlg = new CImportStringKeysDlg;
  1618.     m_pImportStringKeyDlg->Create(IDD_IMPSTRINGKEYS, this);    
  1619.  
  1620.     return TRUE;  // return TRUE  unless you set the focus to a control
  1621. }
  1622.  
  1623.  
  1624. // If you add a minimize button to your dialog, you will need the code below
  1625. //  to draw the icon.  For MFC applications using the document/view model,
  1626. //  this is automatically done for you by the framework.
  1627.  
  1628. void CModelEditDlg::OnPaint() 
  1629. {
  1630.     CRect rect;
  1631.     CBrush brush;
  1632.     CPaintDC dc(this); // device context for painting
  1633.  
  1634.  
  1635.     if (IsIconic())
  1636.     {
  1637.         SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
  1638.  
  1639.         // Center icon in client rectangle
  1640.         int cxIcon = GetSystemMetrics(SM_CXICON);
  1641.         int cyIcon = GetSystemMetrics(SM_CYICON);
  1642.         CRect rect;
  1643.         GetClientRect(&rect);
  1644.         int x = (rect.Width() - cxIcon + 1) / 2;
  1645.         int y = (rect.Height() - cyIcon + 1) / 2;
  1646.  
  1647.         // Draw the icon
  1648.         dc.DrawIcon(x, y, m_hIcon);
  1649.     }
  1650.     else
  1651.     {
  1652.         CDialog::OnPaint();
  1653.     }
  1654. }
  1655.  
  1656. // The system calls this to obtain the cursor to display while the user drags
  1657. //  the minimized window.
  1658. HCURSOR CModelEditDlg::OnQueryDragIcon()
  1659. {
  1660.     return (HCURSOR) m_hIcon;
  1661. }
  1662.  
  1663.  
  1664. void CModelEditDlg::OnLoadModel() 
  1665. {
  1666.     IdleChanger idle(&m_cWinIdle, IDLE_DIALOG_DELAY);      
  1667.  
  1668.     // Look up the open directory in the registry
  1669.     CRegMgr regMgr;
  1670.     CString csOpenDir;
  1671.     if (regMgr.Init(szRegKeyCompany, szRegKeyApp, szRegKeyVer, "OpenDir", HKEY_CURRENT_USER))
  1672.     {
  1673.         UINT32 dwSize = 256;
  1674.         regMgr.Get("Model", csOpenDir.GetBufferSetLength(dwSize), dwSize);
  1675.         csOpenDir.ReleaseBuffer(-1);
  1676.     }
  1677.  
  1678.     csOpenDir += "*.lta;*.ltc";
  1679.  
  1680.     // get the filename
  1681.     CString sFilter;
  1682.     sFilter.LoadString(IDS_LOADMODELFILTER);
  1683.  
  1684.     CFileDialog dlg (TRUE, "lta", (csOpenDir.GetLength()) ? (LPCTSTR)csOpenDir : NULL, OFN_FILEMUSTEXIST | OFN_HIDEREADONLY, sFilter, this);
  1685.  
  1686.     if (dlg.DoModal() != IDOK)
  1687.     { 
  1688.         return;
  1689.     }
  1690.  
  1691.     // Store the open directory in the registry
  1692.     csOpenDir = dlg.GetPathName();
  1693.     csOpenDir = csOpenDir.Left(csOpenDir.GetLength() - dlg.GetFileName().GetLength());
  1694.     regMgr.Set("Model", (LPCTSTR)csOpenDir);
  1695.     
  1696.     CString pathName = dlg.GetPathName() ;
  1697.  
  1698.     m_sModelPath = pathName;
  1699.     DoLoadModel((char*)(LPCTSTR)pathName);
  1700. }
  1701.  
  1702.  
  1703. // import custom lods from another model file
  1704. void CModelEditDlg::OnImportLODs()
  1705. {
  1706.     if( !m_pModel )
  1707.     {
  1708.         DoMessageBox( "A model must be loaded before attempting to import LODs.", MB_OK|MB_ICONERROR );
  1709.         return;
  1710.     }
  1711.  
  1712.     IdleChanger idle( &m_cWinIdle, IDLE_DIALOG_DELAY );
  1713.  
  1714.     // Look up the open directory in the registry
  1715.     CRegMgr regMgr;
  1716.     CString openDir;
  1717.     if( regMgr.Init( szRegKeyCompany, szRegKeyApp, szRegKeyVer, "OpenDir", HKEY_CURRENT_USER ) )
  1718.     {
  1719.         UINT32 dwSize = 256;
  1720.         regMgr.Get( "Model", openDir.GetBufferSetLength( dwSize ), dwSize );
  1721.         openDir.ReleaseBuffer( -1 );
  1722.     }
  1723.     openDir += "*.lta;*.ltc";
  1724.  
  1725.     // get the filename
  1726.     CString filter;
  1727.     filter.LoadString(IDS_LOADMODELFILTER);
  1728.     CFileDialog fileDlg( TRUE, "lta", (openDir.GetLength()) ? (LPCTSTR)openDir : NULL, OFN_FILEMUSTEXIST | OFN_HIDEREADONLY, filter, this );
  1729.     if( fileDlg.DoModal() != IDOK )
  1730.         return;
  1731.     CString pathName = fileDlg.GetPathName() ;
  1732.  
  1733.     // load the model
  1734.     Model* model;
  1735.     CLTAReader inFile;
  1736.  
  1737.     BeginWaitCursor();
  1738.  
  1739.     inFile.Open( (char*)(LPCSTR)pathName, CLTAUtil::IsFileCompressed( (char*)(LPCSTR)pathName ) );
  1740.     
  1741.     if( inFile.IsValid() )
  1742.     {
  1743.         model = ltaModelLoad( inFile, m_AllocCount, false );
  1744.  
  1745.         if( !model )
  1746.         {
  1747.             DoMessageBox( "Error loading model.", MB_OK|MB_ICONERROR );
  1748.             return;
  1749.         }
  1750.     }
  1751.  
  1752.     EndWaitCursor();
  1753.  
  1754.     // launch the import lods dialog
  1755.     CImportLODDlg dlg;
  1756.  
  1757.     dlg.m_ImportModel = model;
  1758.     dlg.m_CurrentModel = m_pModel;
  1759.     dlg.m_ModelEditDlg = this;
  1760.  
  1761.     if( dlg.DoModal() != IDOK )
  1762.     {
  1763.         delete model;
  1764.         return;
  1765.     }
  1766.  
  1767.     // process the selected import LODs
  1768.     const vector<PieceLODInfo>& selection = dlg.m_Selection;
  1769.     int numSelected = selection.size();
  1770.  
  1771.     int numGoodAdds = 0;        // number of imported LODs that were added successfully
  1772.     int numBadMatches = 0;        // number of imported LODs that don't match an existing piece by name
  1773.     int numBadVA = 0;            // number of imported LODs that don't match piece types (VA->Skel/Skel->VA)
  1774.     int numBadNodes = 0;        // number of imported LODs that failed to find matching nodes
  1775.     int numBadAdds = 0;            // number of imported LODs that failed to import for some other reason
  1776.  
  1777.     for( int i = 0; i < numSelected; i++ )
  1778.     {
  1779.         ASSERT( selection[i].m_ModelPiece && selection[i].m_PieceLOD );
  1780.  
  1781.         // find the matching piece by name
  1782.         char* pieceName = selection[i].m_ModelPiece->GetName();
  1783.         ModelPiece* curPiece = m_pModel->FindPiece( pieceName );
  1784.  
  1785.         // didn't find a matching piece by name
  1786.         if( !curPiece )
  1787.         {
  1788.             numBadMatches++;
  1789.             continue;
  1790.         }
  1791.  
  1792.         // pieces don't match animation types
  1793.         if( curPiece->m_isVA != selection[i].m_ModelPiece->m_isVA )
  1794.         {
  1795.             numBadVA++;
  1796.             continue;
  1797.         }
  1798.  
  1799.         // create a new LOD and isolate its vertex weights
  1800.         PieceLOD newLOD;
  1801.         newLOD = *(selection[i].m_PieceLOD);
  1802.  
  1803.         for( int curVert = 0; curVert < newLOD.m_Verts; curVert++ )
  1804.         {
  1805.             int numWeights = newLOD.m_Verts[curVert].m_nWeights;
  1806.  
  1807.             if( numWeights > 0 )
  1808.             {
  1809.                 newLOD.m_Verts[curVert].m_Weights = new NewVertexWeight[numWeights];
  1810.                 for( int curWeight = 0; curWeight < numWeights; curWeight++ )
  1811.                 {
  1812.                     newLOD.m_Verts[curVert].m_Weights[curWeight] = selection[i].m_PieceLOD->m_Verts[curVert].m_Weights[curWeight];
  1813.                 }
  1814.             }
  1815.         }
  1816.  
  1817.         // attemp to remap the node indices on the imported LOD
  1818.         if( !newLOD.RemapNodeIndices( m_pModel ) )
  1819.         {
  1820.             numBadNodes++;
  1821.             continue;
  1822.         }
  1823.  
  1824.         newLOD.m_pModel = m_pModel;
  1825.  
  1826.         // attempt to add the LOD
  1827.         float dist = selection[i].m_ModelPiece->GetLODDist( selection[i].m_LODNum );
  1828.  
  1829.         uint32 addSuccess = curPiece->AddLOD( newLOD, dist );
  1830.  
  1831.         if( addSuccess == 0 )
  1832.         {
  1833.             numBadAdds++;
  1834.             continue;
  1835.         }
  1836.  
  1837.         numGoodAdds++;
  1838.     }
  1839.  
  1840.     delete model;
  1841.  
  1842.     if( numSelected == 0 )
  1843.         return;
  1844.  
  1845.     // report on the import operation
  1846.     CString importReport;
  1847.     CString tmpReport;
  1848.  
  1849.     tmpReport.Format( "Successfully added %d Piece LOD%s to the model.", numGoodAdds, (numGoodAdds == 1) ? "" : "s" );
  1850.     importReport += tmpReport;
  1851.  
  1852.     if( numBadMatches > 0 )
  1853.     {
  1854.         tmpReport.Format( "\nFailed to add %d Piece LOD%s because no pieces matched by name.", numBadMatches, (numBadMatches == 1) ? "" : "s" );
  1855.         importReport += tmpReport;
  1856.     }
  1857.  
  1858.     if( numBadVA > 0 )
  1859.     {
  1860.         tmpReport.Format( "\nFailed to add %d Piece LOD%s because they didn't have matching animation types.", numBadVA, (numBadVA == 1) ? "" : "s" );
  1861.         importReport += tmpReport;
  1862.     }
  1863.  
  1864.     if( numBadNodes > 0 )
  1865.     {
  1866.         tmpReport.Format( "\nFailed to add %d Piece LOD%s because matching nodes couldn't be found.", numBadNodes, (numBadNodes == 1) ? "" : "s" );
  1867.         importReport += tmpReport;
  1868.     }
  1869.  
  1870.     if( numBadAdds > 0 )
  1871.     {
  1872.         ASSERT(0);
  1873.         tmpReport.Format( "\nFailed to add %d Piece LOD%s for an unknown reason.", numBadAdds, (numBadAdds == 1) ? "" : "s" );
  1874.         importReport += tmpReport;
  1875.     }
  1876.  
  1877.     // update the piece list if any LODs were added
  1878.     if( numGoodAdds > 0 )
  1879.     {
  1880.         // reload the piece tree
  1881.         FillPieceList( &m_PieceList, m_pModel);
  1882.  
  1883.         // adjust the LOD slider
  1884.         float maxLODDist = GetModelMaxLODDist( m_pModel );
  1885.         InitTheScrollBar( maxLODDist );
  1886.         SetCurrentLOD( 0.0f );
  1887.  
  1888.         SetChangesMade();
  1889.     }
  1890.  
  1891.     DoMessageBox( importReport, MB_OK );
  1892. }
  1893.  
  1894.  
  1895. // ------------------------------------------------------------------------
  1896. // OnImport stuff from other data files.
  1897. // The lta part could be vastly improved by accessing the parts of the
  1898. // lta that are needed instead of loading up the whole model and tossing 
  1899. // unwanted stuff out. For now this will stand
  1900. // ------------------------------------------------------------------------
  1901. void CModelEditDlg::OnImport() 
  1902. {
  1903.     IdleChanger idle(&m_cWinIdle, IDLE_DIALOG_DELAY);      
  1904.     UVImportDlg uvImportDlg;
  1905.     char msg[256];
  1906.     DWORD i, nFound;
  1907.     uint32 j;
  1908.     ModelAnim *pNewAnim, *pImportAnim;
  1909.     ModelLoadRequest request;
  1910.     AnimInfo *pAnimInfo, *pOtherAnimInfo;
  1911.     ModelSocket *pSocket, *pOtherSocket;
  1912.     WeightSet *pWeightSet, *pOtherWeightSet;
  1913.     uint32 iWeightSetIndex;
  1914.     BuildLODRequest LODRequest;
  1915. //    LODRequestInfo LODInfo;
  1916.  
  1917.     // Make sure we have a model loaded
  1918.  
  1919.     if (!m_pModel)
  1920.     {
  1921.         int nRet = AfxMessageBox("No model currently loaded, load one ?", MB_YESNO | MB_ICONEXCLAMATION);
  1922.         if (nRet == IDYES)
  1923.         {
  1924.             // Let the user load a model
  1925.             
  1926.             OnLoadModel();
  1927.  
  1928.             if (!m_pModel)
  1929.             {
  1930.                 // No model loaded
  1931.                 
  1932.                 return;
  1933.             }
  1934.  
  1935.             AfxMessageBox("Model loaded, continuing to Import");
  1936.         }
  1937.         else
  1938.         {
  1939.             return;
  1940.         }
  1941.     }
  1942.  
  1943.     // Look up the open directory in the registry
  1944.     CRegMgr regMgr;
  1945.     CString csOpenDir;
  1946.     if (regMgr.Init(szRegKeyCompany, szRegKeyApp, szRegKeyVer, "OpenDir", HKEY_CURRENT_USER))
  1947.     {
  1948.         UINT32 dwSize = 256;
  1949.         regMgr.Get("Model", csOpenDir.GetBufferSetLength(dwSize), dwSize);
  1950.         csOpenDir.ReleaseBuffer(-1);
  1951.     }
  1952.  
  1953.     //load strings needed for the open file dialog
  1954.     CString sImportFilter;
  1955.     sImportFilter.LoadString(IDS_IMPORTFILTER);
  1956.  
  1957.     CString sImportDefExt;
  1958.     sImportDefExt.LoadString(IDS_IMPORTDEFEXT);
  1959.  
  1960.     // Strip the extension...
  1961.     char* pExt = _tcsrchr(csOpenDir,'.'); 
  1962.     if (pExt) 
  1963.     { 
  1964.         csOpenDir.TrimRight(pExt); 
  1965.     }
  1966.     csOpenDir += "*.lta;*.ltc";
  1967.  
  1968.     // get the filename
  1969.  
  1970.     CImportAnimation dlg(TRUE, sImportDefExt, (csOpenDir.GetLength()) ? (LPCTSTR)csOpenDir : NULL, OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_ALLOWMULTISELECT, sImportFilter, this);
  1971.     if (dlg.DoModal() != IDOK)
  1972.     {
  1973.         return;
  1974.     }
  1975.  
  1976.     POSITION startPos = dlg.GetStartPosition();
  1977.  
  1978.     if (m_pImportStringKeyDlg)
  1979.     {
  1980.         m_pImportStringKeyDlg->Clear();
  1981.         m_pImportStringKeyDlg->ShowWindow(SW_SHOW);
  1982.     }
  1983.  
  1984.     // Store the open directory in the registry
  1985.     csOpenDir = dlg.GetPathName();
  1986.     csOpenDir = csOpenDir.Left( csOpenDir.GetLength() - dlg.GetFileName().GetLength() );
  1987.     regMgr.Set("Model", (LPCTSTR)csOpenDir);
  1988.  
  1989.     while (startPos)
  1990.     {
  1991. //        Model import;
  1992.         Model *pModel ;            
  1993.  
  1994.         bool bSuccessfulLoad = false;
  1995.  
  1996.         CString sFileName = dlg.GetNextPathName(startPos);
  1997.  
  1998.         m_pImportStringKeyDlg->AddMsg("----------------------------------------\r\n", 128, 0, 0);
  1999.         CString sMsg;
  2000.         sMsg.Format("Loading %s\r\n", (char *)(LPCSTR)sFileName);
  2001.         m_pImportStringKeyDlg->AddMsg(sMsg, 0, 0, 0);
  2002.         
  2003.         // Test to see whether file is an LTA.
  2004.  
  2005.         if (IsFilenameLTAExt(sFileName))
  2006.         {        
  2007.             CLTAReader InFile;
  2008.             InFile.Open((char *)(LPCSTR)sFileName, CLTAUtil::IsFileCompressed((char *)(LPCSTR)sFileName));
  2009.  
  2010.             if (InFile.IsValid())
  2011.             {
  2012.                 pModel = ltaModelLoad(InFile, m_AllocCount, false);
  2013.  
  2014.                 //pModel = ltaModelLoad("", NULL);
  2015.                 if (pModel)
  2016.                 {
  2017.                     bSuccessfulLoad = true;
  2018.                     //pModel = load_LTA_Using_FeedBackDialog((char*)(LPCTSTR)sFileName);
  2019.             //        import.CopyModel( pModel );
  2020.             //        delete pModel;
  2021.                 }
  2022.             }
  2023.         }
  2024.         else  
  2025.         {
  2026.             // Load the ABC
  2027.             MessageBox("ABC LOAD ATTEMPTED IN ON_IMPORT()", "ERROR " , MB_OK );    
  2028.         }
  2029.         
  2030.         if (bSuccessfulLoad)
  2031.         {
  2032.             Model& import = *pModel;
  2033.  
  2034.             // these import options require matching models
  2035.             if( !VerifyModels( m_pModel, &import ) )
  2036.             {
  2037.                 if (m_pImportStringKeyDlg)
  2038.                 {
  2039.                     CString sMsg;
  2040.                     sMsg.Format("%s model geometry does not match, cannot import.\r\n");
  2041.                     m_pImportStringKeyDlg->AddMsg(msg, 0, 0, 0);
  2042.                 }
  2043.  
  2044.                 //MessageBox ("Model geometry does not match.  Cannot import from model.", "Error", MB_OK | MB_ICONEXCLAMATION);
  2045.                 //return;
  2046.             }
  2047.             else
  2048.             {
  2049.                 // now allocate new array for anims
  2050.                 if ( dlg.m_bImportAnimations )
  2051.                 {
  2052.                     for (i=0; i < import.m_Anims; i++)
  2053.                     {
  2054.                         pNewAnim = new ModelAnim(m_pModel);
  2055.                         pImportAnim = import.GetAnim(i);
  2056.  
  2057.                         pNewAnim->CopyAnim(pImportAnim);
  2058.                         m_pModel->AddAnimToSelf(pNewAnim);
  2059.                     }
  2060.  
  2061.  
  2062.                     // add the animations to the listbox
  2063.                     FillAnimList();
  2064.  
  2065.  
  2066.                     // re-allocate the tagged array
  2067.                     InitTaggedArrays();
  2068.  
  2069.                     // let the user know
  2070.  
  2071. //                    if (import.m_Anims > 1)
  2072. //                    {
  2073. //                        MessageBox ("New animations have been added to end of listbox", "Model Editor", MB_OK | MB_ICONINFORMATION);
  2074. //                    }
  2075. //                    else
  2076. //                    {
  2077. //                        MessageBox ("New animation has been added to end of listbox", "Model Editor", MB_OK | MB_ICONINFORMATION);
  2078. //                    }
  2079.  
  2080.                     if (m_pImportStringKeyDlg)
  2081.                     {
  2082.                         CString sMsg;
  2083.                         sMsg.Format("Anims from %s imported\r\n", (char *)(LPCSTR)sFileName);
  2084.                         m_pImportStringKeyDlg->AddMsg(sMsg, 0, 0, 0);
  2085.                     }
  2086.  
  2087.                     m_bChangesMade = TRUE;
  2088.                 }
  2089.  
  2090.                 if ( dlg.m_bUseUVCoords )
  2091.                 {
  2092.                     if (m_pModel->CopyUVs(&import))
  2093.                     {
  2094.                         if (m_pImportStringKeyDlg)
  2095.                         {
  2096.                             CString sMsg;
  2097.                             sMsg.Format("UV's from %s imported\r\n", (char *)(LPCSTR)sFileName);
  2098.                             m_pImportStringKeyDlg->AddMsg(sMsg, 0, 0, 0);
  2099.                         }
  2100.  
  2101. //                        MessageBox ("UV Coordinates imported.", "Model Editor", MB_OK | MB_ICONINFORMATION);
  2102.                     }
  2103.                     else
  2104.                     {
  2105.                         if (m_pImportStringKeyDlg)
  2106.                         {
  2107.                             m_pImportStringKeyDlg->AddMsg("Geometry does not match, cannot import UV's\r\n", 0, 0, 0);
  2108.                         }
  2109.  
  2110. //                        MessageBox ("Model geometry does not match.  Cannot import UV coords.", "Error", MB_OK | MB_ICONEXCLAMATION);
  2111.                     }
  2112.                 }
  2113.  
  2114.                 if (dlg.m_bImportTranslations)
  2115.                 {
  2116.                     BeginWaitCursor();
  2117.  
  2118.                     nFound = 0;
  2119.                     for (i=0; i < import.m_Anims; i++)
  2120.                     {
  2121.                         pAnimInfo = import.GetAnimInfo(i);
  2122.                         pOtherAnimInfo = m_pModel->FindAnimInfo(pAnimInfo->m_pAnim->GetName(), m_pModel);
  2123.  
  2124.                         if (pOtherAnimInfo)
  2125.                         {
  2126.                             ++nFound;
  2127.                             pOtherAnimInfo->m_vTranslation = pAnimInfo->m_vTranslation;
  2128.                         }
  2129.                     }
  2130.  
  2131.                     sprintf(msg, "Imported translations from %d animations.\r\n", nFound);
  2132. //                    MessageBox(msg, "ModelEdit", MB_OK);
  2133.                     if (m_pImportStringKeyDlg)
  2134.                     {
  2135.                         m_pImportStringKeyDlg->AddMsg(msg, 0, 0, 0);
  2136.                     }
  2137.  
  2138.                     EndWaitCursor();
  2139.                 }
  2140.  
  2141.                 // Import the weight sets
  2142.                 if (dlg.m_bImportWeightSets)
  2143.                 {
  2144.                     BeginWaitCursor();
  2145.                     nFound = 0;
  2146.                     for (i=0; i < import.NumWeightSets(); i++)
  2147.                     {
  2148.                         pWeightSet = import.GetWeightSet(i);
  2149.                         pOtherWeightSet = m_pModel->FindWeightSet(pWeightSet->GetName(), &iWeightSetIndex);
  2150.  
  2151.                         if (pOtherWeightSet)
  2152.                             m_pModel->RemoveWeightSet(iWeightSetIndex);
  2153.                         pOtherWeightSet = new WeightSet(m_pModel);
  2154.                         if (!pOtherWeightSet)
  2155.                             continue;
  2156.                         pOtherWeightSet->SetName(pWeightSet->GetName());
  2157.                         if (!(pOtherWeightSet->m_Weights.CopyArray(pWeightSet->m_Weights)))
  2158.                         {
  2159.                             delete pOtherWeightSet;
  2160.                             continue;
  2161.                         }
  2162.                         if (!m_pModel->AddWeightSet(pOtherWeightSet))
  2163.                         {
  2164.                             delete pOtherWeightSet;
  2165.                             continue;
  2166.                         }
  2167.                         ++nFound;
  2168.                     }
  2169.  
  2170.                     sprintf(msg, "Imported %d weight sets.\r\n", nFound);
  2171.                     if (m_pImportStringKeyDlg)
  2172.                     {
  2173.                         m_pImportStringKeyDlg->AddMsg(msg, 0, 0, 0);
  2174.                     }
  2175. //                    MessageBox(msg, "ModelEdit", MB_OK);
  2176.                     
  2177.                     EndWaitCursor();
  2178.                 }
  2179.             }
  2180.  
  2181.             // Import user dims (doesn't matter if models don't match).
  2182.             if (dlg.m_bImportUserDims)
  2183.             {
  2184.                 BeginWaitCursor();
  2185.  
  2186.                 nFound = 0;
  2187.                 for (i=0; i < import.m_Anims; i++)
  2188.                 {
  2189.                     pAnimInfo = import.GetAnimInfo(i);
  2190.                     pOtherAnimInfo = m_pModel->FindAnimInfo(pAnimInfo->m_pAnim->GetName(), m_pModel);
  2191.  
  2192.                     if (pOtherAnimInfo)
  2193.                     {
  2194.                         ++nFound;
  2195.                         pOtherAnimInfo->m_vDims = pAnimInfo->m_vDims;
  2196.                     }
  2197.                 }
  2198.  
  2199.                 sprintf(msg, "Imported user dims from %d animations.\r\n", nFound);
  2200.                 if (m_pImportStringKeyDlg)
  2201.                 {
  2202.                     m_pImportStringKeyDlg->AddMsg(msg, 0, 0, 0);
  2203.                 }
  2204. //                MessageBox(msg, "ModelEdit", MB_OK);
  2205.  
  2206.                 EndWaitCursor();
  2207.             }
  2208.  
  2209.             // Import sockets (doesn't matter if models don't match)
  2210.             if (dlg.m_bImportSockets)
  2211.             {
  2212.                 BeginWaitCursor();
  2213.                 nFound = 0;
  2214.                 for (i=0; i < import.NumSockets(); i++)
  2215.                 {
  2216.                     pSocket = import.GetSocket(i);
  2217.                     pOtherSocket = m_pModel->FindSocket(pSocket->GetName());
  2218.                     
  2219.                     if (pOtherSocket)
  2220.                     {
  2221.                         ++nFound;
  2222.                         pOtherSocket->m_Pos = pSocket->m_Pos;
  2223.                         pOtherSocket->m_Rot = pSocket->m_Rot;
  2224.                     }
  2225.                     else if (m_pModel->FindNode(import.GetNode(pSocket->m_iNode)->GetName(), &j))
  2226.                     {
  2227.                         pOtherSocket = new ModelSocket;
  2228.                         pOtherSocket->m_iNode = j;
  2229.                         pOtherSocket->SetName(pSocket->GetName());
  2230.                         pOtherSocket->m_Pos = pSocket->m_Pos;
  2231.                         pOtherSocket->m_Rot = pSocket->m_Rot;
  2232.                         if (m_pModel->AddSocket(pOtherSocket))
  2233.                             ++nFound;
  2234.                         else
  2235.                             delete pOtherSocket;                                            
  2236.                     }
  2237.                 }
  2238.                 if (nFound)
  2239.                     FillSocketList(TRUE);
  2240.                 sprintf(msg, "Imported %d sockets.\r\n", nFound);
  2241.                 if (m_pImportStringKeyDlg)
  2242.                 {
  2243.                     m_pImportStringKeyDlg->AddMsg(msg, 0, 0, 0);
  2244.                 }
  2245. //                MessageBox(msg, "ModelEdit", MB_OK);
  2246.  
  2247.                 EndWaitCursor();
  2248.             }
  2249.  
  2250.             delete pModel;
  2251.         }
  2252.     }
  2253. }
  2254.  
  2255.  
  2256.  
  2257. // ------------------------------------------------------------------------
  2258. // OnSetProjectDir
  2259. // user asked to change the project dir.
  2260. // set the new project dir in the registry for later.
  2261. // ------------------------------------------------------------------------
  2262. void CModelEditDlg::OnSetProjectDir()
  2263. {
  2264.     IdleChanger idle(&m_cWinIdle, IDLE_DIALOG_DELAY);      
  2265. //
  2266.     //// Look up the open directory in the registry
  2267.     CRegMgr regMgr;
  2268.     CString csOpenDir;
  2269. //    
  2270.     if (regMgr.Init(szRegKeyCompany, szRegKeyApp, szRegKeyVer, "OpenDir", HKEY_CURRENT_USER)) 
  2271.     {
  2272.         UINT32 dwSize = 256;
  2273.         regMgr.Get("dep_file_location", csOpenDir.GetBufferSetLength(dwSize), dwSize);
  2274.         csOpenDir.ReleaseBuffer(-1); 
  2275.  
  2276.     }
  2277.  
  2278.     CDirDialog dlg;
  2279.  
  2280.     dlg.m_strTitle = "Select Project Directory";
  2281.     dlg.m_strSelDir = csOpenDir ;
  2282.  
  2283.     if( dlg.DoBrowse() )
  2284.     {
  2285.         csOpenDir = dlg.m_strPath ;
  2286.         // make sure the project path ends with a backslash
  2287.         if( csOpenDir.GetLength() )
  2288.         {
  2289.             if( csOpenDir[csOpenDir.GetLength()-1] != '\\' )
  2290.                 csOpenDir += '\\';
  2291.         }
  2292.         regMgr.Set("dep_file_location", csOpenDir );
  2293.         m_szCurProjectPath = csOpenDir;
  2294.  
  2295.         // change the window title.. 
  2296.         CString titleText;
  2297.         if( m_pModel )
  2298.         titleText.FormatMessage("ModelEdit: %1!s! %2!s!", m_pModel->GetFilename(),m_szCurProjectPath);
  2299.         else{
  2300.         titleText.FormatMessage("ModelEdit - %1!s! ",m_szCurProjectPath);
  2301.         }
  2302.         SetWindowText((LPCTSTR)titleText);
  2303.     }
  2304.     else// canceled..
  2305.     {
  2306.         // just set it what's in the registry
  2307.         m_szCurProjectPath = csOpenDir;
  2308.     }
  2309. }
  2310.  
  2311.  
  2312. // ------------------------------------------------------------------------
  2313. // Save, then call external packer with d3d bound args
  2314. // ------------------------------------------------------------------------
  2315. void CModelEditDlg::OnSaveAndCompile()
  2316. {
  2317.     CompileD3D( true );
  2318. }
  2319.  
  2320. // ------------------------------------------------------------------------
  2321. // Call external packer with d3d bound args
  2322. // ------------------------------------------------------------------------
  2323. void CModelEditDlg::OnCompile()
  2324. {
  2325.     CompileD3D( false );
  2326. }
  2327.  
  2328.  
  2329.  
  2330.  
  2331. void CModelEditDlg::CompileD3D( bool saveBeforeCompile )
  2332. {
  2333.     IdleChanger idle(&m_cWinIdle, IDLE_DIALOG_DELAY);      
  2334.     
  2335.     bool    bForceCustomTransform = false;
  2336.     uint32    iMaxBonesPerVert = 4;
  2337.     uint32    iMaxBonesPerTri  = 4;
  2338.     float fMinBoneWeight;
  2339.  
  2340.     // default to the currently opened models filename with an .ltb extension
  2341.     CString csOpenDir = m_strFilename;
  2342.     int extPos = csOpenDir.ReverseFind( '.' );
  2343.     if( extPos >= 0 )
  2344.         csOpenDir = csOpenDir.Left( extPos ) + ".ltb";
  2345.  
  2346.     // Get the filename
  2347.     char szFilter[] = "LTB Files (*.ltb)|*.ltb|All Files (*.*)|*.*||";
  2348.     CExportD3D_Dlg dlg (FALSE, "ltb", (csOpenDir.GetLength()) ? (LPCTSTR)csOpenDir : NULL, OFN_FILEMUSTEXIST | OFN_HIDEREADONLY, szFilter, this);
  2349.     
  2350.     
  2351.     dlg.m_bUseMatrixPalettes    = bForceCustomTransform;
  2352.     dlg.m_iMaxBonesPerVert        = iMaxBonesPerVert;
  2353.     dlg.m_bMaxBonesPerVert        = true;
  2354.     dlg.m_iMaxBonesPerTri        = iMaxBonesPerTri;
  2355.     dlg.m_bMaxBonesPerTri        = false;
  2356.     dlg.m_fMinBoneWeight        = 0.05f;
  2357.     dlg.m_bPauseAfterCompile    = false;
  2358.     // get the next values from the model database.
  2359.     dlg.m_bExcludeGeometry      = (m_pModel)?m_pModel->m_bExcludeGeom:false;
  2360.     dlg.m_CompressionType      = (CExportD3D_Dlg::EAnimCompressionType)((m_pModel)?m_pModel->m_CompressionType:2);
  2361.     
  2362.     if (dlg.DoModal() != IDOK) 
  2363.         { return; }
  2364.  
  2365.     // get user input.
  2366.     if(m_pModel)
  2367.     {
  2368.         m_pModel->m_CompressionType = dlg.m_CompressionType ;
  2369.         m_pModel->m_bExcludeGeom    = dlg.m_bExcludeGeometry;
  2370.     }
  2371.  
  2372.     if( saveBeforeCompile )
  2373.         OnSave();
  2374.  
  2375.     
  2376.     bForceCustomTransform                    = dlg.m_bUseMatrixPalettes;
  2377.     
  2378.     iMaxBonesPerVert                        = dlg.m_iMaxBonesPerVert;
  2379.     if (!dlg.m_bMaxBonesPerVert) 
  2380.         iMaxBonesPerVert = 99;
  2381.     
  2382.     iMaxBonesPerTri                            = dlg.m_iMaxBonesPerTri;
  2383.     if (!dlg.m_bMaxBonesPerTri)  
  2384.         iMaxBonesPerTri = 99;
  2385.  
  2386.     fMinBoneWeight        = dlg.m_fMinBoneWeight;
  2387.  
  2388.     // get the path from the dialog
  2389.     csOpenDir = dlg.GetPathName();
  2390.     csOpenDir = csOpenDir.Left( csOpenDir.GetLength() - dlg.GetFileName().GetLength() );
  2391.     
  2392.     // Export the file...
  2393.     LithTry {
  2394.         // Save off a TEMP LTA File...
  2395.         CString szTmpFileName = csOpenDir; 
  2396.  
  2397.         //make sure it has a trailing slash
  2398.         if(!szTmpFileName.IsEmpty() && (szTmpFileName[szTmpFileName.GetLength() - 1] != '\\'))
  2399.             szTmpFileName += '\\';
  2400.  
  2401.         szTmpFileName += "TMP_ModelEditLTAFile.lta";
  2402.         if( !DoSave(szTmpFileName) )
  2403.         {
  2404.             MessageBox( "Error: Could not save intermediate lta file", "File Error", MB_OK | MB_ICONEXCLAMATION );
  2405.             return;
  2406.         }
  2407.  
  2408.         // check for a model_packer in the launch directory
  2409.         CString szRun = g_szStartPath;
  2410.         szRun += "\\Model_Packer.exe";
  2411.         CFileStatus fileStatus;
  2412.         if( !CFile::GetStatus( szRun, fileStatus ) )
  2413.         {
  2414.             // couldn't find it there, check the directory that modeledit is in
  2415.             szRun = g_szExePath;
  2416.             szRun += "\\Model_Packer.exe";
  2417.             if( !CFile::GetStatus( szRun, fileStatus ) )
  2418.             {
  2419.                 MessageBox( "Error: Could not locate Model_Packer.exe\nCheck that Model_Packer.exe is located in\nthe ModelEdit launch dir,\nor in the same directory as ModelEdit.exe", "File Error", MB_OK | MB_ICONEXCLAMATION );
  2420.                 return;
  2421.             }
  2422.         }
  2423.  
  2424.         // Call the Model_Packer to convert it to LTB...
  2425.         CString szProcessCmd = "d3d";
  2426.         CString szInput1  = "-input";
  2427.         CString szInput2  = '\"' + szTmpFileName + '\"';
  2428.         CString szOutput1 = "-output";
  2429.         CString szOutput2 = '\"' + csOpenDir + dlg.GetFileName() + '\"';
  2430.         CString szMaxBonesPerVert1 = "-MaxBonesPerVert";
  2431.         CString szVerbose = "-verbose";
  2432.         char szMaxBonesPerVert2[8]; sprintf(szMaxBonesPerVert2,"%d",iMaxBonesPerVert);
  2433.         CString szMaxBonesPerTri1  = "-MaxBonesPerTri";
  2434.         char szMaxBonesPerTri2[8];  sprintf(szMaxBonesPerTri2,"%d",iMaxBonesPerTri);
  2435.         CString szForceCustomTransform1 = "-UseMatrixPalettes";
  2436.         char szForceCustomTransform2[8]; sprintf(szForceCustomTransform2,"%d",bForceCustomTransform?1:0);
  2437.         CString szStall = "";
  2438.         if( dlg.m_bPauseAfterCompile )
  2439.             szStall = "-stall";
  2440.         CString szNoGeom = "";
  2441.         if( dlg.m_bExcludeGeometry )
  2442.             szNoGeom = "-nogeom";
  2443.  
  2444.         // [TMG] [10/31/2000] Added min bone weight
  2445.         
  2446.         CString szMinBoneWeight1 = "-MinBoneWeight";
  2447.         char szMinBoneWeight2[16];
  2448.         sprintf(szMinBoneWeight2, "%4.4f", fMinBoneWeight);
  2449.  
  2450.         CString szCompressionType ;
  2451.         switch(dlg.m_CompressionType){
  2452.             case CExportD3D_Dlg::NONE : szCompressionType = "-ac0"; break;
  2453.             case CExportD3D_Dlg::RELEVANT : szCompressionType = "-ac1" ; break ;
  2454.             case CExportD3D_Dlg::RELEVANT_16bit : szCompressionType = "-ac2" ; break ;
  2455.             case CExportD3D_Dlg::REL_PV16 : szCompressionType = "-acpv" ; break ;
  2456.             default : szCompressionType =  "-ac0" ;
  2457.         }
  2458.  
  2459.         char szStream0OptionsBuffer[256];
  2460.         memset(szStream0OptionsBuffer, 0, 256);
  2461.  
  2462.         if(dlg.m_bStreamOptionsPosition)
  2463.         {
  2464.             strcat(szStream0OptionsBuffer, "position ");
  2465.         }
  2466.  
  2467.         if(dlg.m_bStreamOptionsNormal)
  2468.         {
  2469.             strcat(szStream0OptionsBuffer, "normal ");
  2470.         }
  2471.  
  2472.         if(dlg.m_bStreamOptionsColor)
  2473.         {
  2474.             strcat(szStream0OptionsBuffer, "color ");
  2475.         }
  2476.  
  2477.         if(dlg.m_bStreamOptionsTangent)
  2478.         {
  2479.             strcat(szStream0OptionsBuffer, "basisvectors ");
  2480.         }
  2481.  
  2482.         if(dlg.m_bStreamOptionsUV1)
  2483.         {
  2484.             strcat(szStream0OptionsBuffer, "uv1 ");
  2485.         }
  2486.     
  2487.         if(dlg.m_bStreamOptionsUV2)
  2488.         {
  2489.             strcat(szStream0OptionsBuffer, "uv2 ");
  2490.         }
  2491.  
  2492.         if(dlg.m_bStreamOptionsUV3)
  2493.         {
  2494.             strcat(szStream0OptionsBuffer, "uv3 ");
  2495.         }
  2496.  
  2497.         if(dlg.m_bStreamOptionsUV4)
  2498.         {
  2499.             strcat(szStream0OptionsBuffer, "uv4 ");
  2500.         }
  2501.  
  2502.         char szStream0Options[512];
  2503.  
  2504.         if(szStream0OptionsBuffer[0] != '\0')
  2505.         {
  2506.  
  2507.             sprintf(szStream0Options, "-stream0 %s", szStream0OptionsBuffer);
  2508.  
  2509.         }
  2510.  
  2511.  
  2512.         if (_spawnl(_P_WAIT,szRun,"Model_Packer.exe",
  2513.                     szProcessCmd,
  2514.                     szInput1,
  2515.                     szInput2,
  2516.                     szOutput1,
  2517.                     szOutput2,
  2518.                     szMaxBonesPerVert1,
  2519.                     szMaxBonesPerVert2,
  2520.                     szMaxBonesPerTri1,
  2521.                     szMaxBonesPerTri2,
  2522.                     szForceCustomTransform1,
  2523.                     szForceCustomTransform2,
  2524.                     szMinBoneWeight1,
  2525.                     szMinBoneWeight2,
  2526.                     szVerbose,
  2527.                     szCompressionType,
  2528.                     szNoGeom,
  2529.                     szStream0Options,
  2530.                     szStall,
  2531.                     
  2532.                     NULL) < 0) 
  2533.         {
  2534.             MessageBox ("Error: Could not launch Model_Packer.exe", "File Error", MB_OK | MB_ICONEXCLAMATION);
  2535.             return; 
  2536.         } 
  2537.  
  2538.     
  2539.  
  2540.         DeleteFile(szTmpFileName);            // Delete that temp LTA file...
  2541.     }
  2542.     LithCatch(CLithException &exception) {
  2543.         exception = exception;
  2544.         MessageBox ("Error: Could not export file", "File Error", MB_OK | MB_ICONEXCLAMATION);
  2545.         return; }
  2546.  
  2547. }
  2548.  
  2549.  
  2550. int CModelEditDlg::DoMessageBox(UINT idString, int style)
  2551. {
  2552.     CString str, caption;
  2553.  
  2554.     str.LoadString(idString);
  2555.     caption.LoadString(IDS_MODELEDIT_CAPTION);
  2556.     return MessageBox(str, caption, style);
  2557. }
  2558.  
  2559.  
  2560. int CModelEditDlg::DoMessageBox(LPCTSTR pStr, int style)
  2561. {
  2562.     CString caption;
  2563.  
  2564.     caption.LoadString(IDS_MODELEDIT_CAPTION);
  2565.     return MessageBox(pStr, caption, style);
  2566. }
  2567.  
  2568.  
  2569. BOOL CModelEditDlg::GetEditAnimInfo(DWORD *pAnimIndex, DWORD *pKeyframeIndex, bool bAllowChildAnims)
  2570. {
  2571.     DWORD iAnim, iKeyframe;
  2572.  
  2573.     if(!m_pModel)
  2574.         return FALSE;
  2575.  
  2576.     iAnim = m_AnimInfos[0].CurAnimIndex();
  2577.     if(iAnim >= m_pModel->NumAnims())
  2578.         return FALSE;
  2579.  
  2580.     if(!bAllowChildAnims && !m_pModel->GetAnimInfo(iAnim)->IsParentModel())
  2581.         return FALSE;
  2582.  
  2583.     iKeyframe = m_AnimInfos[0].CurKeyframe();
  2584.     if(iKeyframe >= m_pModel->GetAnim(iAnim)->NumKeyframes())
  2585.         return FALSE;
  2586.  
  2587.     if(pAnimIndex)
  2588.         *pAnimIndex = iAnim;
  2589.  
  2590.     if(pKeyframeIndex)
  2591.         *pKeyframeIndex = iKeyframe;
  2592.  
  2593.     return TRUE;
  2594. }
  2595.  
  2596. // ------------------------------------------------------------------------
  2597. // DoSave( filename )
  2598. // save out file 
  2599. // ------------------------------------------------------------------------
  2600. bool CModelEditDlg::DoSave(const char *pFilename)
  2601. {
  2602.     DWORD i, j, nParentAnims;
  2603.     ModelAnim *pAnim, *pTest;
  2604. //    DStream *pStream;
  2605.     CString str;
  2606.     int ret;
  2607.  
  2608.     if (!m_pModel)
  2609.         return false;
  2610.  
  2611.     //make sure that the artists have valid dimensions
  2612.     CheckValidAnimationDims();
  2613.  
  2614.     // Look for duplicate animation names. These can cause problems.
  2615.     m_pModel->ForceAnimOrder();
  2616.     
  2617.     nParentAnims = m_pModel->CalcNumParentAnims();
  2618.     for(i=0; i < nParentAnims; i++)
  2619.     {
  2620.         pAnim = m_pModel->GetAnimInfo(i)->m_pAnim;
  2621.  
  2622.         for(j=0; j < nParentAnims; j++)
  2623.         {
  2624.             if(i == j)
  2625.                 continue;
  2626.  
  2627.             pTest = m_pModel->GetAnimInfo(j)->m_pAnim;
  2628.  
  2629.             if(strcmp(pAnim->GetName(), pTest->GetName()) == 0)
  2630.             {
  2631.                 str.FormatMessage(IDS_DUPLICATE_ANIM_NAME, pAnim->GetName());
  2632.                 ret = DoMessageBox(str, MB_YESNOCANCEL);
  2633.                 if(ret == IDCANCEL)
  2634.                 {
  2635.                     return false;
  2636.                 }
  2637.                 else if(ret == IDYES)
  2638.                 {
  2639.                     DoRenameAnim(i);
  2640.                 }
  2641.             }
  2642.         }
  2643.     }
  2644.  
  2645.     extern bool ltaSave( const char *, Model *, CLTATranslStatus &);
  2646.  
  2647.     // check if we are trying to save an lta type file...
  2648.     if( pFilename )
  2649.     {
  2650.         if( IsFilenameLTAExt( pFilename ) )
  2651.         {
  2652.             BeginWaitCursor();
  2653.             CLTATranslStatus status ;
  2654.             m_pModel->m_sProjectDir = m_szCurProjectPath;
  2655.             bool retVal = ltaSave( pFilename, m_pModel, status );
  2656.  
  2657.             //make sure that the file saved correctly. If not, odds are it was
  2658.             //a read only file, and we should inform the user of it -JohnO
  2659.             if(status != CLTATranslStatus::OK)
  2660.             {
  2661.                 char pszError[128];
  2662.                 sprintf(pszError, "Error opening %s, The file may be read only", pFilename);
  2663.                 status.OnError(pszError);
  2664.             }
  2665.  
  2666.             EndWaitCursor();
  2667.  
  2668.             return retVal;
  2669.         }
  2670.         else
  2671.         {
  2672.             DoMessageBox( "Unrecognized file extension.  Save failed.", MB_OK );
  2673.             return false;
  2674.         }
  2675.     }
  2676.  
  2677.     return false;
  2678. }
  2679.  
  2680.  
  2681. void CModelEditDlg::OnSave() 
  2682. {
  2683.     if( DoSave(m_strFilename) )
  2684.         m_bChangesMade = false;
  2685. }
  2686.  
  2687. // ------------------------------------------------------------------------
  2688. // Event Handler: OnSaveAs
  2689. // ------------------------------------------------------------------------
  2690. void CModelEditDlg::OnSaveAs() 
  2691. {
  2692.     IdleChanger idle(&m_cWinIdle, IDLE_DIALOG_DELAY);      
  2693.  
  2694.     // Look up the model directory in the registry
  2695.     CRegMgr regMgr;
  2696.     CString csOpenDir;
  2697.     if (regMgr.Init(szRegKeyCompany, szRegKeyApp, szRegKeyVer, "OpenDir", HKEY_CURRENT_USER))
  2698.     {
  2699.         UINT32 dwSize = 256;
  2700.         regMgr.Get("Model", csOpenDir.GetBufferSetLength(dwSize), dwSize);
  2701.         csOpenDir.ReleaseBuffer(-1);
  2702.     }
  2703.     // Strip the extension...
  2704.     char* pExt = _tcsrchr(csOpenDir,'.'); 
  2705.     if (pExt) { csOpenDir.TrimRight(pExt); }
  2706.     csOpenDir += "*.lta";
  2707.  
  2708.     // get a filename from the user
  2709.     CString sFilter;
  2710.     sFilter.LoadString(IDS_SAVEASFILTER);
  2711.  
  2712.     CFileDialog dlg (FALSE, "lta", (csOpenDir.GetLength()) ? (LPCTSTR)csOpenDir : NULL, OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY, sFilter, this);
  2713.     if (dlg.DoModal() != IDOK)
  2714.     {
  2715.         return;
  2716.     }
  2717.     
  2718.     // Store the model directory in the registry
  2719.     csOpenDir = dlg.GetPathName();
  2720.     csOpenDir = csOpenDir.Left(csOpenDir.GetLength() - dlg.GetFileName().GetLength());
  2721.     regMgr.Set("Model", (LPCTSTR)csOpenDir);
  2722.     
  2723.     if( DoSave( dlg.GetPathName() ) )
  2724.     {
  2725.         m_strFilename = dlg.GetPathName();
  2726.         CString titleText;
  2727.         titleText.FormatMessage( IDS_TITLE_TEXT, m_strFilename );
  2728.         SetWindowText( (LPCTSTR)titleText );
  2729.         m_pModel->SetFilename( m_strFilename );
  2730.         m_bChangesMade = false;
  2731.     }
  2732. }
  2733.  
  2734. // ------------------------------------------------------------------------
  2735. // Event Handler: OnCancel 
  2736. // ------------------------------------------------------------------------
  2737. void CModelEditDlg::OnCancel() 
  2738. {
  2739.     if (m_bChangesMade)
  2740.     {
  2741.         int nAnswer = MessageBox ("Save changes before exiting?", "Model Editor", MB_YESNOCANCEL | MB_ICONQUESTION);
  2742.         
  2743.         //determine if the user wanted to not exit
  2744.         if(nAnswer == IDCANCEL)
  2745.         {
  2746.             return;
  2747.         }
  2748.  
  2749.         //see if they wanted to save
  2750.         if (nAnswer == IDYES)
  2751.         {
  2752.             OnSave();
  2753.         }
  2754.     }
  2755.  
  2756.     m_bEndDialog = TRUE;
  2757.     CDialog::OnCancel();
  2758. }
  2759.  
  2760.  
  2761. void CModelEditDlg::OnStop() 
  2762. {
  2763.     uint32 i;
  2764.     MEAnimInfo *pInfo;
  2765.     DWORD dwActive[NUM_ANIM_INFOS];
  2766.  
  2767.  
  2768.     GetPlaybackActiveFlags(dwActive);
  2769.  
  2770.     // Apply the cm
  2771.     for(i=0; i < NUM_ANIM_INFOS; i++)
  2772.     {
  2773.         pInfo = GetAnimInfo(i);
  2774.  
  2775.         if(dwActive[i] & PA_ACTIVE)
  2776.         {
  2777.             GetAnimInfo(i)->StopPlayback();
  2778.         }
  2779.     }
  2780. }
  2781.  
  2782. void CModelEditDlg::OnPlayForward() 
  2783. {
  2784.     uint32 i;
  2785.     MEAnimInfo *pInfo;
  2786.     DWORD dwActive[NUM_ANIM_INFOS];
  2787.  
  2788.  
  2789.     GetPlaybackActiveFlags(dwActive);
  2790.  
  2791.  
  2792.     for(i=0; i < NUM_ANIM_INFOS; i++)
  2793.     {
  2794.         pInfo = GetAnimInfo(i);
  2795.  
  2796.         if(dwActive[i])
  2797.         {
  2798.             GetAnimInfo(i)->StartPlayback();
  2799.         }
  2800.     }
  2801.  
  2802.     UpdateEditFrameString( );
  2803.     UpdateEditFrameTime( );
  2804. }
  2805.  
  2806. void CModelEditDlg::OnNextKeyframe() 
  2807. {
  2808.     IncKeyframe(TRUE);
  2809. }
  2810.  
  2811.  
  2812. void CModelEditDlg::OnPrevKeyframe() 
  2813. {
  2814.     IncKeyframe(FALSE);
  2815. }
  2816.  
  2817. int CModelEditDlg::GetSelectedParentAnims(int *pItems, int maxItems)
  2818. {
  2819.     int i, nRetItems;
  2820.  
  2821.     if (!m_pModel)
  2822.         return -1;
  2823.  
  2824.     nRetItems = 0;
  2825.     for (i=0; i < m_AnimList.GetItemCount(); i++)
  2826.     {
  2827.         if ((i > (int)m_pModel->m_Anims.GetSize()) || (nRetItems >= maxItems))
  2828.             break;
  2829.         if ((!m_pModel->GetAnimIfOwner(i)) || (m_AnimList.GetItemState(i, LVIS_SELECTED) == 0))
  2830.             continue;
  2831.  
  2832.         pItems[nRetItems] = i;
  2833.         nRetItems++;
  2834.     }
  2835.     
  2836.     return nRetItems;            
  2837. }
  2838.  
  2839.  
  2840. BOOL CModelEditDlg::HandleButtonDown(int iButton, CPoint point)
  2841. {
  2842.     m_RenderWnd.ClientToScreen(&point);
  2843.     ScreenToClient(&point);
  2844.     
  2845.     if (GetAsyncKeyState('C') & 0x8000)
  2846.     {
  2847.         StartTracker(iButton, point);
  2848.         return TRUE;
  2849.     }
  2850.     else if (GetAsyncKeyState('V') & 0x8000)
  2851.     {
  2852.         StartTracker(iButton+3, point);
  2853.         return TRUE;
  2854.     }
  2855.  
  2856.     return FALSE;
  2857. }
  2858.  
  2859.  
  2860. BOOL CModelEditDlg::HandleButtonUp(int iButton)
  2861. {
  2862.     if (m_bTracking)
  2863.     {
  2864.         SetWindowText(m_OldWindowText);
  2865.         ShowCursor(TRUE);
  2866.         ReleaseCapture();
  2867.         m_bTracking = FALSE;
  2868.         SetChangesMade();
  2869.         return TRUE;
  2870.     }
  2871.  
  2872.     return FALSE;
  2873. }
  2874.  
  2875.  
  2876. void CModelEditDlg::StartTracker(uint32 iTracker, CPoint centerPt)
  2877. {
  2878.     if (iTracker >= m_Trackers.GetSize())
  2879.         return;
  2880.  
  2881.     m_TotalDelta = 0;
  2882.     GetWindowText(m_OldWindowText);
  2883.     ShowCursor(FALSE);
  2884.     m_bTracking = TRUE;
  2885.     m_iCurTracker = iTracker;
  2886.     m_LastCursorPos = centerPt;
  2887.     m_TrackerCenterPt = centerPt;
  2888.     SetCapture();
  2889. }
  2890.  
  2891.  
  2892. // Moves selected animations up or down, depending on dir.
  2893. void CModelEditDlg::MoveAnims(int dir)
  2894. {
  2895.     int i, j, iTemp, nItems, items[100], nSelection, nDest;
  2896.     CString strSelection;
  2897.     AnimInfo temp;
  2898.     BOOL bChecked;
  2899.     
  2900.     if ((!m_pModel) || (!dir))
  2901.         return;
  2902.         
  2903.     nItems = GetSelectedParentAnims(items, 100);
  2904.     if (nItems == -1)
  2905.         return;
  2906.  
  2907.     // So we don't have animations pointing at bad data.
  2908.     ResetAnimInfos();
  2909.  
  2910.     // Process in reverse order for positive directions
  2911.     if (dir > 0)
  2912.     {
  2913.         for (i=0; i < (nItems / 2); i++)
  2914.         {
  2915.             iTemp = items[i];
  2916.             items[i] = items[nItems - (i + 1)];
  2917.             items[nItems - (i + 1)] = iTemp;
  2918.         }
  2919.     }
  2920.  
  2921.     for (i=0; i < nItems; i++)
  2922.     {
  2923.         nSelection = items[i];
  2924.         nDest = max(min(nSelection + dir, (int)m_pModel->m_Anims.GetSize() - 1), 0);
  2925.  
  2926.         if (nSelection == nDest)
  2927.             continue;
  2928.  
  2929.         // move the actual anim in the model
  2930.         temp = m_pModel->m_Anims[nSelection];
  2931.         if (nDest < nSelection)
  2932.         {
  2933.             for (j=nSelection; j > nDest; j--)
  2934.                 m_pModel->m_Anims[j] = m_pModel->m_Anims[j - 1];
  2935.         }
  2936.         else
  2937.         {
  2938.             for (j=nSelection; j < nDest; j++)
  2939.                 m_pModel->m_Anims[j] = m_pModel->m_Anims[j + 1];
  2940.         }
  2941.         m_pModel->m_Anims[nDest] = temp;
  2942.  
  2943.         // Move the item in the list
  2944.         strSelection = m_AnimList.GetItemText(nSelection, 0);
  2945.         bChecked = m_AnimList.GetCheck(nSelection);
  2946.         m_AnimList.DeleteItem(nSelection);
  2947.         m_AnimList.InsertItem(nDest, strSelection);
  2948.         m_AnimList.SetItemState(nDest, LVIS_SELECTED, LVIS_SELECTED);
  2949.         m_AnimList.SetCheck(nDest, bChecked);
  2950.  
  2951.         m_bChangesMade = TRUE;
  2952.     }
  2953. }
  2954.  
  2955. void CModelEditDlg::OnAnimMoveDown() 
  2956. {
  2957.     MoveAnims(1);
  2958. }
  2959.  
  2960. void CModelEditDlg::OnAnimMoveUp() 
  2961. {
  2962.     MoveAnims(-1);
  2963. }
  2964.  
  2965. void CModelEditDlg::OnAnimDelete() 
  2966. {
  2967.     int i, nItems, items[100], iTemp;
  2968.  
  2969.     if (!m_pModel) 
  2970.         return;
  2971.  
  2972.     if (!GetAnimList(items, sizeof(items), nItems))
  2973.         return;
  2974.  
  2975.     // Sort in descending order.
  2976.     for (i=0; i < (nItems-1); i++)
  2977.     {
  2978.         if (items[i] < items[i+1])
  2979.         {
  2980.             iTemp = items[i];
  2981.             items[i] = items[i+1];
  2982.             items[i+1] = iTemp;
  2983.  
  2984.             if (i == 0)
  2985.                 i -= 1;
  2986.             else
  2987.                 i -= 2;
  2988.         }
  2989.     }
  2990.  
  2991.     // Make sure we're not deleting them all.
  2992.     if (nItems == (int)m_pModel->m_Anims.GetSize())
  2993.     {
  2994.         MessageBox ("Cannot remove all animations from a model file.", "Delete Animation", MB_OK | MB_ICONINFORMATION);
  2995.         return;
  2996.     }
  2997.  
  2998.     // make sure they really want to delete it
  2999.  
  3000.     int nAnswer = MessageBox ("Are you sure you want to remove these animations from the model file?", "Delete Animation", MB_YESNO | MB_ICONQUESTION);
  3001.     if (nAnswer == IDNO)
  3002.     {
  3003.         return;
  3004.     }
  3005.  
  3006.     for (i=0; i < nItems; i++)
  3007.     {
  3008.         m_AnimList.DeleteItem(items[i]);
  3009.         // Delete the animation
  3010.         ModelAnim *pAnim = m_pModel->GetAnim(items[i]);
  3011.         if (pAnim)
  3012.             delete pAnim;
  3013.         // Remove it from the list
  3014.         m_pModel->m_Anims.Remove(items[i]);
  3015.         // Update the child models
  3016.         for (DWORD j=0; j < m_pModel->NumChildModels(); j++)
  3017.         {
  3018.             ChildInfo *pChild = m_pModel->GetChildModel(j);
  3019.             if ((DWORD)items[i] < pChild->m_AnimOffset)
  3020.                 pChild->m_AnimOffset--;
  3021.         }
  3022.     }
  3023.  
  3024.     // Select the first item.
  3025.     m_AnimList.SetItemState(0, LVIS_SELECTED, LVIS_SELECTED);
  3026.     for (i = 1; i < m_AnimList.GetItemCount(); i++)
  3027.         m_AnimList.SetItemState(i, 0, LVIS_SELECTED);
  3028.  
  3029.     ResetAnimInfos();
  3030.     
  3031.     SetChangesMade();
  3032. }
  3033.  
  3034.  
  3035.  
  3036. void CModelEditDlg::OnCreateSingleFrame() 
  3037. {
  3038.     DWORD nAnimation = m_AnimInfos[0].CurAnimIndex();
  3039.     DWORD nKeyframe = m_AnimInfos[0].CurKeyframe();
  3040.     DWORD i;
  3041.     char testName[100];
  3042.     IdleChanger idle(&m_cWinIdle, IDLE_DIALOG_DELAY);      
  3043.  
  3044.  
  3045.     if (!m_pModel)
  3046.         return;
  3047.  
  3048.  
  3049.     StopAllPlayback();
  3050.  
  3051.  
  3052.     // get a name for the new model
  3053.  
  3054.     CRenameDlg dlg (this);
  3055.  
  3056.     // Get a default name.
  3057.     for (i=0; i < 1000; i++)
  3058.     {
  3059.         if (i == 0)
  3060.             sprintf(testName, "static_model");
  3061.         else
  3062.             sprintf(testName, "static_model%d", i);
  3063.         
  3064.         if (!m_pModel->FindAnim(testName))
  3065.         {
  3066.             dlg.m_strName = testName;
  3067.             break;
  3068.         }
  3069.     }
  3070.  
  3071.     if (dlg.DoModal() == IDCANCEL)
  3072.     {
  3073.         return;
  3074.     }
  3075.  
  3076.  
  3077.     // Make a copy of the current anim and strip out all keyframes but the one we want.
  3078.     ModelAnim *pAnim;
  3079.     ModelAnim *pCopyFrom = m_pModel->GetAnim(nAnimation);
  3080.     ChildInfo *pChildInfo = m_pModel->GetAnimInfo(nAnimation)->m_pChildInfo;
  3081.  
  3082.     pAnim = new ModelAnim(m_pModel);
  3083.     if (!pAnim)
  3084.         return;
  3085.  
  3086.     if(!pAnim->CopyAnim(pCopyFrom))
  3087.         return;
  3088.     
  3089.     AnimInfo* pNewInfo = m_pModel->AddAnim(pAnim, pChildInfo);
  3090.  
  3091.     if (!pNewInfo)
  3092.         return;
  3093.     
  3094.     // Set its name.
  3095.     pAnim->SetName((char*)(LPCTSTR)dlg.m_strName);
  3096.  
  3097.     //copy over the dimensions
  3098.     pNewInfo->m_vDims = m_pModel->GetAnimInfo(nAnimation)->m_vDims;
  3099.  
  3100.     // Remove the keyframes leading up.
  3101.     for (i=0; i < nKeyframe; i++)
  3102.     {
  3103.         pAnim->RemoveKeyFrame(0);
  3104.     }
  3105.  
  3106.     // Copy the first keyframe....
  3107.  
  3108.     ModelAnim *pFrame = pAnim->CopyKeyFrame(0);
  3109.     pAnim->PasteKeyFrame(pFrame, 1);
  3110.  
  3111.     // Remove the ones after.
  3112.     while(pAnim->NumKeyFrames() > 2)
  3113.     {
  3114.         pAnim->RemoveKeyFrame(pAnim->NumKeyFrames() - 1);
  3115.     }
  3116.     pAnim->m_KeyFrames[0].m_Time = 0;
  3117.     pAnim->m_KeyFrames[1].m_Time = 200;
  3118.  
  3119.     // add the new anim to the list box and select it
  3120.     InitTaggedArrays();
  3121.  
  3122.     FillAnimList();
  3123.     for (i = 0; i < (DWORD)m_AnimList.GetItemCount(); i++)
  3124.         m_AnimList.SetItemState((int)i, 0, LVIS_SELECTED);
  3125.     m_AnimList.SetItemState(m_pModel->m_Anims - 1, LVIS_SELECTED, LVIS_SELECTED);
  3126.  
  3127.     OnSelChangeAnimList();
  3128.  
  3129.     SetChangesMade();
  3130. }
  3131.  
  3132.  
  3133. void CModelEditDlg::DoRenameAnim(DWORD iAnim)
  3134. {
  3135.     ModelAnim *pAnim;
  3136.     char *pNewName;
  3137.     CString str;
  3138.     IdleChanger idle(&m_cWinIdle, IDLE_DIALOG_DELAY);      
  3139.  
  3140.     
  3141.     if (!m_pModel || 
  3142.         iAnim >= m_pModel->NumAnims() ||
  3143.         !m_pModel->GetAnimInfo(iAnim)->IsParentModel())
  3144.         return;                                         
  3145.  
  3146.     pAnim = m_pModel->GetAnim(iAnim);
  3147.  
  3148.     // make sure the animation is stopped
  3149.  
  3150.     OnStop();
  3151.  
  3152.     // get the new name
  3153.  
  3154.     CRenameDlg dlg (this);
  3155.     
  3156.     while(1)
  3157.     {
  3158.         dlg.m_strName = pAnim->GetName();
  3159.         if (dlg.DoModal() == IDCANCEL)
  3160.         {
  3161.             return;
  3162.         }
  3163.  
  3164.         pNewName = (char*)(LPCTSTR)dlg.m_strName;
  3165.         if (m_pModel->FindAnim(pNewName))
  3166.         {
  3167.             str.FormatMessage(IDS_ENTER_UNIQUE_ANIM_NAME, pNewName);
  3168.             if (DoMessageBox(str, MB_YESNO) == IDNO)
  3169.             {
  3170.                 return;
  3171.             }
  3172.         }
  3173.         else
  3174.         {
  3175.             break;
  3176.         }
  3177.     }
  3178.  
  3179.     // set the new name in the animation
  3180.     pAnim->SetName((char*)(LPCTSTR)dlg.m_strName);
  3181.  
  3182.     // set the new name in the listbox
  3183.  
  3184.     m_AnimList.SetItemText(iAnim, 0, pAnim->GetName());
  3185.  
  3186.     SetChangesMade();
  3187. }
  3188.  
  3189.  
  3190. void CModelEditDlg::OnRenameAnim() 
  3191. {
  3192.     DoRenameAnim(m_AnimInfos[0].CurAnimIndex());
  3193. }
  3194.  
  3195. void CModelEditDlg::OnContinuous() 
  3196. {
  3197.     CContinuousDlg dlg;
  3198.     ModelAnim *pCurAnim, *pFrame;
  3199.     DWORD nKeyframes, oldLastTime;
  3200.     DWORD iAnim;
  3201.     IdleChanger idle(&m_cWinIdle, IDLE_DIALOG_DELAY);      
  3202.  
  3203.     iAnim = m_AnimInfos[0].CurAnimIndex();
  3204.     if (!m_pModel || 
  3205.         iAnim >= m_pModel->NumAnims() ||
  3206.         !m_pModel->GetAnimInfo(iAnim)->IsParentModel())
  3207.         return;
  3208.  
  3209.     // make sure the animation is stopped
  3210.     StopAllPlayback();
  3211.  
  3212.     // get the delay
  3213.     if (dlg.DoModal() == IDCANCEL) 
  3214.         return;
  3215.  
  3216.     pCurAnim = m_pModel->GetAnim(iAnim);
  3217.     if (pCurAnim->m_KeyFrames == 0)
  3218.         return;
  3219.  
  3220.     nKeyframes = pCurAnim->NumKeyFrames();
  3221.     oldLastTime = pCurAnim->m_KeyFrames.Last().m_Time;
  3222.  
  3223.     // Copy and paste it..
  3224.     pFrame = pCurAnim->CopyKeyFrame(0);
  3225.     if (!pFrame)
  3226.         return;
  3227.  
  3228.     if (!pCurAnim->PasteKeyFrame(pFrame, pCurAnim->NumKeyFrames()))
  3229.     {
  3230.         delete pFrame;
  3231.         return;
  3232.     }
  3233.  
  3234.     delete pFrame;
  3235.  
  3236.     // Adjust its time.
  3237.     pCurAnim->m_KeyFrames.Last().m_Time = oldLastTime + dlg.m_nDelay;
  3238.  
  3239.     // now add an extra tagged array member
  3240.     InitTaggedArrays();
  3241.  
  3242.     // update the ui
  3243.     ResetAnimInfos();
  3244.     OnSelChangeAnimList();
  3245.     UpdateEditFrameTime();
  3246.  
  3247.     m_bChangesMade = TRUE;
  3248. }
  3249.  
  3250. void CModelEditDlg::OnDrawSkeleton() 
  3251. {
  3252.     m_RenderWnd.m_DrawStruct.m_bDrawSkeleton = !m_RenderWnd.m_DrawStruct.m_bDrawSkeleton;    
  3253.     UpdateMenuChecks();
  3254. }
  3255.  
  3256. void CModelEditDlg::OnWireframe() 
  3257. {
  3258.      m_RenderWnd.m_DrawStruct.m_bWireframe = !m_RenderWnd.m_DrawStruct.m_bWireframe;
  3259.     UpdateMenuChecks();
  3260. }
  3261.  
  3262. void CModelEditDlg::OnCameraFollow() 
  3263. {
  3264.       m_RenderWnd.m_bCameraFollow = !m_RenderWnd.m_bCameraFollow;
  3265.     UpdateMenuChecks();
  3266. }
  3267.  
  3268. void CModelEditDlg::OnDims() 
  3269. {
  3270.      m_RenderWnd.m_DrawStruct.m_bDims = !m_RenderWnd.m_DrawStruct.m_bDims;
  3271.     UpdateMenuChecks();
  3272. }
  3273.  
  3274. void CModelEditDlg::OnAnimBox() 
  3275. {
  3276.      m_RenderWnd.m_DrawStruct.m_bAnimBox = !m_RenderWnd.m_DrawStruct.m_bAnimBox;
  3277.     UpdateMenuChecks();
  3278. }
  3279.  
  3280.  
  3281. void CModelEditDlg::OnShowSockets() 
  3282. {
  3283.      m_RenderWnd.m_DrawStruct.m_bDrawSockets = !m_RenderWnd.m_DrawStruct.m_bDrawSockets;
  3284.     UpdateMenuChecks();
  3285. }
  3286.  
  3287.  
  3288. void CModelEditDlg::OnShowTextures()
  3289. {
  3290.      m_RenderWnd.m_DrawStruct.m_bDrawTextures = !m_RenderWnd.m_DrawStruct.m_bDrawTextures;
  3291.     UpdateMenuChecks();
  3292. }
  3293.  
  3294.  
  3295. void CModelEditDlg::OnShowAttachments() 
  3296. {
  3297.      m_RenderWnd.m_DrawStruct.m_bDrawAttachments = !m_RenderWnd.m_DrawStruct.m_bDrawAttachments;
  3298.     UpdateMenuChecks();
  3299. }
  3300.  
  3301.  
  3302. void CModelEditDlg::OnSolidAttachments() 
  3303. {
  3304.      m_RenderWnd.m_DrawStruct.m_bSolidAttachments = !m_RenderWnd.m_DrawStruct.m_bSolidAttachments;
  3305.     UpdateMenuChecks();
  3306. }
  3307.  
  3308.  
  3309. void CModelEditDlg::OnShowNormals()
  3310. {
  3311.     m_RenderWnd.m_DrawStruct.m_bNormals = !m_RenderWnd.m_DrawStruct.m_bNormals;
  3312.     UpdateMenuChecks();
  3313. }
  3314.  
  3315.  
  3316. void CModelEditDlg::OnShowNormalRef()
  3317. {
  3318.      m_RenderWnd.m_DrawStruct.m_bShowNormalRef = !m_RenderWnd.m_DrawStruct.m_bShowNormalRef;
  3319.     UpdateMenuChecks();
  3320. }
  3321.  
  3322.  
  3323. void CModelEditDlg::OnProfile()
  3324. {
  3325.      m_RenderWnd.m_DrawStruct.m_bProfile = !m_RenderWnd.m_DrawStruct.m_bProfile;
  3326.     UpdateMenuChecks();
  3327. }
  3328.  
  3329.  
  3330. void CModelEditDlg::OnMovementEncoding()
  3331. {
  3332.     CButton* checkBox = (CButton*)GetDlgItem( IDC_MOVEMENT_ENCODING );
  3333.      m_RenderWnd.m_DrawStruct.m_bMovementEncoding = checkBox->GetCheck() != 0;
  3334. }
  3335.  
  3336.  
  3337. void CModelEditDlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
  3338. {
  3339.     CScrollBar *pItem;
  3340.     int pos;
  3341.     DWORD newLOD;
  3342.  
  3343.     uint32 max_dist = 1000 ;
  3344.  
  3345.     if (!m_pModel)
  3346.         return;
  3347.  
  3348.     if (nSBCode != SB_ENDSCROLL)
  3349.     {
  3350.         pos = pScrollBar->GetScrollPos();
  3351.         
  3352.         pItem = (CScrollBar*)GetDlgItem(IDC_LOD_SCROLL);
  3353.         if (pItem && (pScrollBar==pItem) && m_pModel)
  3354.         {
  3355.             if (nSBCode == SB_PAGELEFT || nSBCode == SB_LINELEFT)
  3356.             {
  3357.                 pos = CLAMP(pScrollBar->GetScrollPos() - 1, 0, (int)(max_dist - 1));
  3358.             }
  3359.             else if (nSBCode == SB_PAGERIGHT || nSBCode == SB_LINERIGHT)
  3360.             {
  3361.                 pos = CLAMP(pScrollBar->GetScrollPos() + 1, 0, (int)(max_dist - 1));
  3362.             }
  3363.             else
  3364.             {
  3365.                 pos = nPos;
  3366.             }
  3367.  
  3368.             pScrollBar->SetScrollPos(pos);
  3369.  
  3370.             newLOD = pos;
  3371.             //if (newLOD != m_nCurrentLOD)
  3372.             {
  3373.                 m_LODSlider.SetCurrentValue((float)newLOD);
  3374.                 SetCurrentLOD((float)newLOD);
  3375.                 m_RenderWnd.Draw();
  3376.             }
  3377.         }
  3378.     }
  3379.     
  3380.     CDialog::OnHScroll(nSBCode, nPos, pScrollBar);
  3381. }
  3382.  
  3383.  
  3384. void CModelEditDlg::SetLODText(int nLOD)
  3385. {
  3386.     char str[256];
  3387.     CWnd *pWnd;
  3388.  
  3389.     sprintf(str, "LOD: %d", nLOD);
  3390.     if (pWnd = GetDlgItem(IDC_LOD_TEXT))
  3391.         pWnd->SetWindowText(str);
  3392. }
  3393.  
  3394.  
  3395. void SetGNModelText(char *pText)
  3396. {
  3397. }
  3398.  
  3399.  
  3400. void CModelEditDlg::OnPieceRemoveLODs()
  3401. {
  3402.     unsigned numNotRemoved = 0;
  3403.  
  3404.     vector<PieceLODInfo> selection;
  3405.     int numSelected = GetSelectedPieceLODs( &m_PieceList, m_pModel, selection );
  3406.  
  3407.     if( !numSelected || (DoMessageBox( "Are you sure you wish to delete the selected LODs?", MB_OKCANCEL ) != IDOK) )
  3408.         return;
  3409.  
  3410.     // go over list back to front to make sure we never remove the highest lod
  3411.     for( int i = selection.size() - 1; i >= 0; i-- )
  3412.     {
  3413.         // don't remove any LODs from a piece that has only one LOD left
  3414.         if( selection[i].m_ModelPiece->NumLODs() <= 1 )
  3415.         {
  3416.             numNotRemoved++;
  3417.             continue;
  3418.         }
  3419.  
  3420.         bool removeSuccess = selection[i].m_ModelPiece->RemoveLOD( selection[i].m_LODNum );
  3421.         ASSERT( removeSuccess );
  3422.     }
  3423.  
  3424.     if( numNotRemoved > 0 )
  3425.     {
  3426.         CString notRemovedStr;
  3427.         notRemovedStr.Format( "%d LODs not removed as they are the only LODs in a piece.", numNotRemoved );
  3428.         DoMessageBox( notRemovedStr, MB_OK );
  3429.     }
  3430.  
  3431.     // reload the piece tree
  3432.     FillPieceList( &m_PieceList, m_pModel);
  3433.  
  3434.     // adjust the LOD slider
  3435.     float maxLODDist = GetModelMaxLODDist( m_pModel );
  3436.     InitTheScrollBar( maxLODDist );
  3437.     SetCurrentLOD( 0.0f );
  3438.  
  3439.     SetChangesMade();
  3440. }
  3441.  
  3442.  
  3443. void CModelEditDlg::OnPieceBuildLODs() 
  3444. {
  3445.     IdleChanger idle(&m_cWinIdle, IDLE_DIALOG_DELAY);      
  3446.     CPieceLODGenDlg dlg;
  3447.     CRegMgr regMgr;
  3448.  
  3449.     // default values
  3450.     CString distance = "100.0";
  3451.     CString maxEdgeLen = "1000.0";
  3452.     CString percent = "50.0";
  3453.     unsigned minNumTris = 8;
  3454.  
  3455.     // get the current piece lod selections
  3456.     vector<PieceLODInfo> selection;
  3457.     int numSelected = GetSelectedPieceLODs( &m_PieceList, m_pModel, selection, true );
  3458.     if( !numSelected )
  3459.     {
  3460.         MessageBox( "At least one piece LOD needs to be selected.", MB_OK );
  3461.         return;
  3462.     }
  3463.  
  3464.     // get the lod settings from the registry
  3465.     if( regMgr.Init( szRegKeyCompany, szRegKeyApp, szRegKeyVer, "LODGeneration", HKEY_CURRENT_USER ) )
  3466.     {
  3467.         unsigned bufSize = 256;
  3468.         regMgr.Get( "Distance", distance.GetBufferSetLength( bufSize ), bufSize );
  3469.         distance.ReleaseBuffer();
  3470.         dlg.m_Distance = (float)atof( distance );
  3471.  
  3472.         bufSize = 256;
  3473.         regMgr.Get( "MaxEdgeLen", maxEdgeLen.GetBufferSetLength( bufSize ), bufSize );
  3474.         maxEdgeLen.ReleaseBuffer();
  3475.         dlg.m_MaxEdgeLen = (float)atof( maxEdgeLen );
  3476.  
  3477.         bufSize = 256;
  3478.         regMgr.Get( "Percent", percent.GetBufferSetLength( bufSize ), bufSize );
  3479.         percent.ReleaseBuffer();
  3480.         dlg.m_Percent = (float)atof( percent );
  3481.  
  3482.         dlg.m_MinNumTris = regMgr.Get( "MinNumTris", minNumTris );
  3483.     }
  3484.  
  3485.     if( dlg.DoModal() != IDOK )
  3486.         return;
  3487.  
  3488.     // store the lod settings in the registry
  3489.     if( regMgr.Init( szRegKeyCompany, szRegKeyApp, szRegKeyVer, "LODGeneration", HKEY_CURRENT_USER ) )
  3490.     {
  3491.         distance.Format( "%f", dlg.m_Distance );
  3492.         regMgr.Set( "Distance", distance );
  3493.  
  3494.         maxEdgeLen.Format( "%f", dlg.m_MaxEdgeLen );
  3495.         regMgr.Set( "MaxEdgeLen", maxEdgeLen );
  3496.  
  3497.         percent.Format( "%f", dlg.m_Percent );
  3498.         regMgr.Set( "Percent", percent );
  3499.  
  3500.         regMgr.Set( "MinNumTris", dlg.m_MinNumTris );
  3501.     }
  3502.  
  3503.     // initialize the piece LOD builder
  3504.     int numBadLODs = 0;
  3505.     int numBadLODsVA = 0;
  3506.  
  3507.     BeginWaitCursor();
  3508.  
  3509.     // loop through each selected source piece LOD
  3510.     for( int i = 0; i < selection.size(); i++ )
  3511.     {
  3512.         // can't generate LODs for vertex animated pieces
  3513.         if( selection[i].m_ModelPiece->m_isVA )
  3514.         {
  3515.             numBadLODs++;
  3516.             numBadLODsVA++;
  3517.             continue;
  3518.         }
  3519.  
  3520.         CBuildPieceLOD* buildLOD = new CBuildPieceLOD;
  3521.  
  3522.         buildLOD->m_Distance = dlg.m_Distance;
  3523.         buildLOD->m_MaxEdgeLen = dlg.m_MaxEdgeLen;
  3524.         buildLOD->m_Percent = dlg.m_Percent;
  3525.         buildLOD->m_MinNumTris = dlg.m_MinNumTris;
  3526.  
  3527.         buildLOD->m_Model = m_pModel;
  3528.         buildLOD->m_ModelPiece = selection[i].m_ModelPiece;
  3529.         buildLOD->m_LODNum = selection[i].m_LODNum;
  3530.         // the lod pointer may be bogus after adding LODs to a piece, so get a fresh one
  3531.         buildLOD->m_PieceLOD = buildLOD->m_ModelPiece->GetLOD( (unsigned)selection[i].m_LODNum );
  3532.  
  3533.         // generate new piece LOD from currend piece LOD
  3534.         if( !buildLOD->BuildLOD() )
  3535.             numBadLODs++;
  3536.  
  3537.         delete buildLOD;
  3538.     }
  3539.  
  3540.     EndWaitCursor();
  3541.  
  3542.     // sort the piece lods
  3543.     for( i = 0; i < m_pModel->NumPieces(); i++ )
  3544.     {
  3545.         // get the current piece
  3546.         ModelPiece* curPiece = m_pModel->GetPiece( i );
  3547.         if( !curPiece )
  3548.         {
  3549.             ASSERT(0);
  3550.             continue;
  3551.         }
  3552.         curPiece->SortLODs();
  3553.     }
  3554.  
  3555.     // reload the piece tree
  3556.     FillPieceList( &m_PieceList, m_pModel );
  3557.  
  3558.     // adjust the LOD slider
  3559.     float maxLODDist = GetModelMaxLODDist( m_pModel );
  3560.     InitTheScrollBar( maxLODDist );
  3561.     SetCurrentLOD( 0.0f );
  3562.  
  3563.     SetChangesMade();
  3564.  
  3565.     // inform the user of errors
  3566.     if( numBadLODs || numBadLODsVA )
  3567.     {
  3568.         CString errMessage;
  3569.         errMessage.Format( "%d LODs didn't generate correctly.\n%d of these failed due to being vertex animated.", numBadLODs, numBadLODsVA );
  3570.         DoMessageBox( errMessage, MB_OK | MB_ICONERROR );
  3571.     }
  3572. }
  3573.  
  3574.  
  3575. void CModelEditDlg::OnPieceMerge( void )
  3576. {
  3577.     // get the selected pieces
  3578.     vector<ModelPiece*> selection;
  3579.     int numSelected = GetSelectedPieces( &m_PieceList, m_pModel, selection );
  3580.     int numNewPieces = 0;
  3581.  
  3582.     BeginWaitCursor();
  3583.  
  3584.     // merge the pieces if possible
  3585.     CPieceMerge mergePieces( m_pModel, selection );
  3586.     numNewPieces = mergePieces.Merge();
  3587.  
  3588.     EndWaitCursor();
  3589.  
  3590.     // set the dirty bit if anything actually happened
  3591.     ASSERT( numNewPieces <= numSelected );
  3592.     if( numNewPieces != numSelected )
  3593.         SetChangesMade();
  3594.  
  3595.     // reload the piece tree
  3596.     FillPieceList( &m_PieceList, m_pModel );
  3597.     m_RenderWnd.AllocSelections( m_pModel->NumPieces(), m_pModel->NumNodes());
  3598.  
  3599.     // tell the user what happened
  3600.     CString completedMessage;
  3601.     completedMessage.Format( "Merged %d pieces into %d pieces.", numSelected, numNewPieces );
  3602.     DoMessageBox( completedMessage, MB_OK );
  3603. }
  3604.  
  3605.  
  3606. void CModelEditDlg::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
  3607. {
  3608.     CDialog::OnKeyDown(nChar, nRepCnt, nFlags);
  3609. }
  3610.  
  3611.  
  3612. void CModelEditDlg::OnModelInfo()
  3613. {
  3614.     CModelInfoDlg dlg;
  3615.     IdleChanger idle(&m_cWinIdle, IDLE_DIALOG_DELAY);      
  3616.  
  3617.     if (m_pModel)
  3618.     {
  3619.         dlg.m_pModel = m_pModel;
  3620.         dlg.DoModal();
  3621.     }
  3622. }
  3623.  
  3624.  
  3625.  
  3626. void CModelEditDlg::OnCommandString() 
  3627. {
  3628.     CCommandStringDlg dlg;
  3629.     IdleChanger idle(&m_cWinIdle, IDLE_DIALOG_DELAY);      
  3630.     
  3631.     if (m_pModel)
  3632.     {
  3633.         dlg.m_pModel = m_pModel;
  3634.         dlg.DoModal();
  3635.         ProcessCommandString();
  3636.         SetChangesMade();
  3637.     }
  3638. }
  3639.  
  3640. void CModelEditDlg::OnDimensions() 
  3641. {
  3642.     IdleChanger idle(&m_cWinIdle, IDLE_DIALOG_DELAY);      
  3643.     
  3644.     if (!m_pModel)
  3645.         return;
  3646.  
  3647.     if(m_pDimensionDlg == NULL)
  3648.     {
  3649.         m_pDimensionDlg = new CDimensionsDlg( this );
  3650.         
  3651.         //make sure the memory was allocated properly
  3652.         if(m_pDimensionDlg == NULL)
  3653.         {
  3654.             return;
  3655.         }
  3656.  
  3657.         //load the list of animations into the dialog
  3658.         if (!GetAnimList(    m_pDimensionDlg->m_Anims, 
  3659.                             sizeof(m_pDimensionDlg->m_Anims), 
  3660.                             m_pDimensionDlg->m_nAnims, FALSE))
  3661.         {
  3662.             return;        
  3663.         }
  3664.  
  3665.         m_pDimensionDlg->m_pModel = m_pModel;
  3666.  
  3667.         //create the dialog
  3668.         m_pDimensionDlg->Create(CDimensionsDlg::IDD,this);
  3669.         
  3670.         m_pDimensionDlg->ShowWindow(SW_SHOW);
  3671.     }
  3672.     else
  3673.     {
  3674.         //load the list of animations into the dialog
  3675.         if (!GetAnimList(    m_pDimensionDlg->m_Anims, 
  3676.                             sizeof(m_pDimensionDlg->m_Anims), 
  3677.                             m_pDimensionDlg->m_nAnims, FALSE))
  3678.         {
  3679.             return;        
  3680.         }
  3681.         m_pDimensionDlg->ShowWindow(SW_SHOW);
  3682.     }
  3683. }
  3684.  
  3685. //this will run through each animation in the model, looking for animations that have the X and Z
  3686. //dimensions of the animation not equal. It will then prompt them for how to fix.
  3687. void CModelEditDlg::CheckValidAnimationDims()
  3688. {
  3689.     //we need a model
  3690.     if(!m_pModel)
  3691.         return;
  3692.  
  3693.     //now run through all animations and for each, make sure that they match
  3694.     for(uint32 nCurrAnim = 0; nCurrAnim < m_pModel->m_Anims.GetSize(); nCurrAnim++)
  3695.     {
  3696.         AnimInfo* pCurrAnim = &m_pModel->m_Anims[nCurrAnim];
  3697.  
  3698.         if(pCurrAnim->IsParentModel() && fabs(pCurrAnim->m_vDims.x - pCurrAnim->m_vDims.z) > 0.1f)
  3699.         {
  3700.             //we have a descrepincy here, have the user resolve it
  3701.             CInvalidAnimDimsDlg Dlg(this);
  3702.             Dlg.m_pAnimInfo = pCurrAnim;
  3703.             if(Dlg.DoModal() == IDOK)
  3704.             {
  3705.                 //this should set a modified flag some how
  3706.             }
  3707.  
  3708.         }
  3709.     }
  3710. }
  3711.  
  3712.  
  3713. void CModelEditDlg::OnAnimationFramerate() 
  3714. {
  3715.     CAnimFramerateDlg dlg;
  3716.     char str[20];
  3717.     DWORD i, iAnim;
  3718.     float theRate;
  3719.     IdleChanger idle(&m_cWinIdle, IDLE_DIALOG_DELAY);      
  3720.     
  3721.     if (m_pModel)
  3722.     {
  3723.         sprintf(str, "%d", 10);
  3724.         dlg.m_FramerateString = str;
  3725.         dlg.m_bAllAnimations = FALSE;
  3726.         
  3727.         if (dlg.DoModal() == IDOK)
  3728.         {
  3729.             // Grab the currently playing animation index
  3730.             iAnim = m_AnimInfos[0].CurAnimIndex();
  3731.  
  3732.             // grab the tagged keyframes
  3733.             CMoArray<BOOL>& taggedKeysOrig = m_AnimInfos[0].m_Wnd.m_Tagged;
  3734.             vector<bool> taggedKeys( taggedKeysOrig );
  3735.             for( i = 0; i < taggedKeysOrig; i++ )
  3736.             {
  3737.                 taggedKeys[i] = !!(taggedKeysOrig[i]);
  3738.             }
  3739.  
  3740.             // Stop playing
  3741.             ResetAnimInfos();
  3742.  
  3743.             theRate = (float)atof(dlg.m_FramerateString);
  3744.             
  3745.             if (dlg.m_bAllAnimations)
  3746.             {
  3747.                 for (i=0; i < m_pModel->m_Anims; i++)
  3748.                 {
  3749.                     model_SetAnimFramerate(m_pModel, i, (float)(1.0f / theRate), NULL);
  3750.                 }
  3751.             }
  3752.             else
  3753.             {
  3754.                 if (iAnim < m_pModel->m_Anims && 
  3755.                     m_pModel->GetAnimInfo(iAnim)->IsParentModel())
  3756.                 {
  3757.                     model_SetAnimFramerate(m_pModel, iAnim, (float)(1.0f / theRate), &taggedKeys);
  3758.                 }
  3759.             }
  3760.         
  3761.             SetChangesMade();
  3762.  
  3763.             // Update the animation list
  3764.             OnSelChangeAnimList();
  3765.         }
  3766.     }
  3767. }
  3768.  
  3769. void CModelEditDlg::OnAnimationLength() 
  3770. {
  3771.     CKeyframeTimeDlg dlg;
  3772.     DWORD i, nKeyframes, dwNewKeyframeTime, iAnim;
  3773.     float fPosition;
  3774.     ModelAnim *pAnim;
  3775.     IdleChanger idle(&m_cWinIdle, IDLE_DIALOG_DELAY);      
  3776.     
  3777.     
  3778.     iAnim = m_AnimInfos[0].CurAnimIndex();    
  3779.     if(!m_pModel ||
  3780.         iAnim >= m_pModel->NumAnims() ||
  3781.         !m_pModel->GetAnimInfo(iAnim)->IsParentModel())
  3782.     {
  3783.         return;
  3784.     }
  3785.  
  3786.     pAnim = m_pModel->GetAnim(iAnim);
  3787.     nKeyframes = pAnim->m_KeyFrames.GetSize();
  3788.     dlg.m_nCurrentTime = pAnim->GetAnimTime();
  3789.     dlg.m_nNewTime = dlg.m_nCurrentTime;
  3790.     dlg.m_sCaption = "Animation Length";
  3791.     
  3792.     if (dlg.DoModal() == IDCANCEL || dlg.m_nNewTime == dlg.m_nCurrentTime)
  3793.     {
  3794.         return;
  3795.     }
  3796.  
  3797.     // Do all the frames except first and last...
  3798.     for ( i = 1; i < nKeyframes - 1; i++ )
  3799.     {
  3800.         fPosition = ( float )pAnim->m_KeyFrames[i].m_Time / ( float )pAnim->GetAnimTime();
  3801.         dwNewKeyframeTime = ( DWORD )((( float )dlg.m_nNewTime * fPosition ) + 0.5f );
  3802.         pAnim->m_KeyFrames[i].m_Time = dwNewKeyframeTime;
  3803.     }
  3804.  
  3805.     // Make sure the last frame is exactly the full time...
  3806.     pAnim->m_KeyFrames[nKeyframes - 1].m_Time = dlg.m_nNewTime;
  3807.     
  3808.     SetChangesMade();
  3809. }
  3810.  
  3811. void CModelEditDlg::OnAnimationInterpolation() 
  3812. {
  3813.     CKeyframeTimeDlg dlg;
  3814.     DWORD iAnim;
  3815.     ModelAnim *pAnim;
  3816.     IdleChanger idle(&m_cWinIdle, IDLE_DIALOG_DELAY);      
  3817.     
  3818.     
  3819.     iAnim = m_AnimInfos[0].CurAnimIndex();    
  3820.     if(!m_pModel ||
  3821.         iAnim >= m_pModel->NumAnims() ||
  3822.         !m_pModel->GetAnimInfo(iAnim)->IsParentModel())
  3823.     {
  3824.         return;
  3825.     }
  3826.  
  3827.     pAnim = m_pModel->GetAnim(iAnim);
  3828.  
  3829.     dlg.m_nCurrentTime = pAnim->m_InterpolationMS;
  3830.     dlg.m_nNewTime = pAnim->m_InterpolationMS;
  3831.     dlg.m_sCaption = "Animation Interpolation";
  3832.     
  3833.     if (dlg.DoModal() == IDCANCEL || dlg.m_nNewTime == dlg.m_nCurrentTime)
  3834.     {
  3835.         return;
  3836.     }
  3837.  
  3838.     pAnim->m_InterpolationMS = dlg.m_nNewTime;
  3839.  
  3840.     SetChangesMade();
  3841. }
  3842.  
  3843. void CModelEditDlg::UpdateEditFrameTime( )
  3844. {
  3845.     MEAnimInfo *pInfo;
  3846.     
  3847.     UpdateEditFrameTimeEnabled();
  3848.  
  3849.     if(!m_pModel)
  3850.     {
  3851.         return;
  3852.     }
  3853.  
  3854.     // The edit frame string can only be changed from anim 0.
  3855.     pInfo = GetAnimInfo(ANIMINFO_MAIN);
  3856.     
  3857.     TempVarSetter<BOOL> setter(&m_bInStringChange, TRUE);
  3858.     SetDlgItemInt( IDC_FRAMETIME, pInfo->CurAnimTime(), FALSE );
  3859. }
  3860.  
  3861. void CModelEditDlg::UpdateEditFrameTimeEnabled()
  3862. {
  3863.     bool bEnabled = true;
  3864.  
  3865.     if( !m_pModel ||
  3866.         m_AnimInfos[ANIMINFO_MAIN].IsAnimPlaying() ||
  3867.         (m_SelectedAnims.GetSize() != 1) ||
  3868.         (m_pModel->GetAnim(m_SelectedAnims[0])->GetModel() != m_pModel))
  3869.     {
  3870.         bEnabled = false;
  3871.     }
  3872.  
  3873.     m_EditFrameTime.EnableWindow( bEnabled );
  3874. }
  3875.  
  3876. void CModelEditDlg::UpdateEditFrameStringEnabled()
  3877. {
  3878.     bool bEnabled = true;
  3879.  
  3880.     if( !m_pModel ||
  3881.         m_AnimInfos[ANIMINFO_MAIN].IsAnimPlaying() ||
  3882.         (m_SelectedAnims.GetSize() != 1) ||
  3883.         (m_pModel->GetAnim(m_SelectedAnims[0])->GetModel() != m_pModel))
  3884.     {
  3885.         bEnabled = false;
  3886.     }
  3887.  
  3888.     m_EditFrameString.EnableWindow( bEnabled );
  3889. }
  3890.  
  3891. void CModelEditDlg::UpdateEditFrameString( )
  3892. {
  3893.     DWORD iAnim, iKeyframe;
  3894.     char *pStr;
  3895.  
  3896.     UpdateEditFrameStringEnabled();
  3897.  
  3898.     if(!GetEditAnimInfo(&iAnim, &iKeyframe, true))
  3899.         return;
  3900.  
  3901.     pStr = m_pModel->GetAnim(iAnim)->m_KeyFrames[iKeyframe].m_pString;
  3902.     
  3903.     TempVarSetter<BOOL> setter(&m_bInStringChange, TRUE);
  3904.     SetDlgItemText( IDC_FRAMESTRING, pStr );
  3905. }
  3906.  
  3907. void CModelEditDlg::SetEditFrameTime() 
  3908. {
  3909.     DWORD dwNewKeyframeTime = GetDlgItemInt( IDC_FRAMETIME, NULL, FALSE );
  3910.     DWORD nKeyframe = m_AnimInfos[ANIMINFO_MAIN].m_Wnd.ForceNearestKeyframe();
  3911.     m_AnimInfos[ANIMINFO_MAIN].m_Wnd.DoEditKeyframeTime( nKeyframe, dwNewKeyframeTime );
  3912.     UpdateEditFrameTime( );
  3913. }
  3914.  
  3915.  
  3916. void CModelEditDlg::SetEditFrameString()
  3917. {
  3918.     CString sFrameString;
  3919.     DWORD nKeyframe;
  3920.  
  3921.     GetDlgItemText( IDC_FRAMESTRING, sFrameString );
  3922.     nKeyframe = m_AnimInfos[ANIMINFO_MAIN].m_Wnd.ForceNearestKeyframe();
  3923.     m_AnimInfos[ANIMINFO_MAIN].m_Wnd.DoEditKeyframeString( nKeyframe, sFrameString );
  3924. }
  3925.  
  3926.  
  3927. void CModelEditDlg::SetCurrentAnimTime( uint32 iAnimInfo, DWORD dwAnimTime )
  3928. {
  3929.     Model *pModel;
  3930.     MEAnimInfo *pInfo;
  3931.  
  3932.     if(iAnimInfo >= NUM_ANIM_INFOS)
  3933.         return;
  3934.  
  3935.     pInfo = &m_AnimInfos[iAnimInfo];
  3936.     pModel = pInfo->GetModel();
  3937.     if(!pModel)
  3938.         return;
  3939.  
  3940.     trk_SetCurTime(&m_AnimInfos[iAnimInfo].m_Tracker, dwAnimTime, FALSE);
  3941.     UpdateEditFrameTime( );
  3942. }
  3943.  
  3944.  
  3945. BOOL CModelEditDlg::SetRenderTexture(const char *pFilename, DWORD nTexture)
  3946. {
  3947.     DStream *pStream;
  3948.     TextureData *pTexture;
  3949.     BOOL bRet;
  3950.     DRESULT dResult;
  3951.  
  3952.  
  3953.     bRet = FALSE;
  3954.     pStream = streamsim_Open(pFilename, "rb");
  3955.     if (pStream)
  3956.     {
  3957.         dResult = dtx_Create(pStream, &pTexture, TRUE);
  3958.         if (dResult == LT_OK)
  3959.         {
  3960.             bRet = m_RenderWnd.SetTexture( pTexture , nTexture );
  3961.             //bRet = SetGLMTexture(m_RenderWnd.GetContext(), pTexture, nTexture);
  3962.             if (bRet)
  3963.             {
  3964.                 //m_RenderWnd.m_DrawStruct.m_bDrawBright = TRUE;
  3965.             }
  3966.  
  3967.             dtx_Destroy(pTexture);
  3968.  
  3969.             // if we've sucessfuly gotten the picture we keep its name/index values.
  3970.             m_pModel->AddTextureName( nTexture, pFilename );
  3971.         }
  3972.  
  3973.         pStream->Release();
  3974.     }
  3975.  
  3976.  
  3977.  
  3978.  
  3979.     return bRet;
  3980. }
  3981.  
  3982.  
  3983. BOOL CModelEditDlg::CheckModifyAnims(int *pAnims, int nAnims, BOOL bParentOnly, BOOL bMessage)
  3984. {
  3985.     int i, iAnim;
  3986.     CString str;
  3987.     AnimInfo *pAnimInfo;
  3988.  
  3989.     if (!m_pModel)
  3990.         return FALSE;
  3991.  
  3992.     for (i=0; i < nAnims; i++)
  3993.     {
  3994.         iAnim = pAnims[i];
  3995.  
  3996.         if (iAnim < 0 || iAnim >= (int)m_pModel->NumAnims())
  3997.         {
  3998.             if (bMessage)
  3999.             {
  4000.                 str.FormatMessage(IDS_INVALIDANIMINDEX);
  4001.                 DoMessageBox(str, MB_OK);
  4002.             }
  4003.  
  4004.             return FALSE;
  4005.         }
  4006.  
  4007.         if (bParentOnly)
  4008.         {
  4009.             pAnimInfo = m_pModel->GetAnimInfo(iAnim);
  4010.             if (pAnimInfo->GetAnimOwner() != m_pModel)
  4011.             {
  4012.                 if (bMessage)
  4013.                 {
  4014.                     str.FormatMessage(IDS_CANTEDITBASEMODEL, pAnimInfo->m_pAnim->GetName());
  4015.                     DoMessageBox(str, MB_OK);
  4016.                 }
  4017.  
  4018.                 return FALSE;
  4019.             }
  4020.         }
  4021.     }
  4022.  
  4023.     return TRUE;
  4024. }
  4025.  
  4026.  
  4027. BOOL CModelEditDlg::GetAnimList(int *pAnims, int listSizeBytes, int &nAnims, BOOL bParentOnly, BOOL bMessage)
  4028. {
  4029.     if ((!m_pModel) || (!pAnims))
  4030.         return FALSE;
  4031.  
  4032.     nAnims = 0;
  4033.     int listSize = listSizeBytes / sizeof(int);
  4034.     for (int i = 0; (i < m_AnimList.GetItemCount()) && (nAnims < listSize); i++)
  4035.     {
  4036.         if (m_AnimList.GetItemState(i, LVIS_SELECTED) != 0)
  4037.         {
  4038.             pAnims[nAnims] = i;
  4039.             nAnims++;
  4040.         }
  4041.     }
  4042.     if (nAnims == 0)
  4043.         return FALSE;
  4044.  
  4045.     return CheckModifyAnims(pAnims, nAnims, bParentOnly, bMessage);
  4046. }
  4047.  
  4048.  
  4049. void CModelEditDlg::ProcessCommandString()
  4050. {
  4051.     ConParse parse;
  4052.     ModelLoadRequest request;
  4053.     ModelSocket *pSocket;
  4054.     DWORD nTexture = 0;
  4055.     DDWORD nToken = 1;
  4056.  
  4057.     if (!m_pModel)
  4058.         return;
  4059.     
  4060.     // Set its skins.
  4061.     /*** DEPRECATED T.F 
  4062.     parse.Init(m_pModel->m_CommandString);
  4063.     while (parse.ParseFind("ModelEditTexture", FALSE, nToken))
  4064.     {
  4065.         if (parse.m_nArgs > 2)
  4066.             nTexture = atoi(parse.m_Args[2]);
  4067.         else
  4068.             nTexture = 0;
  4069.         SetRenderTexture(parse.m_Args[1], nTexture);
  4070.         nToken++;
  4071.     }
  4072.     ***/ 
  4073.  
  4074.     // Setup socket attachment models.
  4075.     DeleteSocketAttachments();
  4076.  
  4077.     CRegMgr regMgr;
  4078.     regMgr.Init(szRegKeyCompany, szRegKeyApp, szRegKeyVer, "Attachments", HKEY_CURRENT_USER);
  4079.  
  4080.     parse.Init(m_pModel->m_CommandString);
  4081.     while(parse.ParseFind("SocketModel", FALSE, 2))
  4082.     {
  4083.         if (pSocket = m_pModel->FindSocket(parse.m_Args[1]))
  4084.         {
  4085.             char *filename = parse.m_Args[2];
  4086.             
  4087.             if( IsFilenameLTAExt( filename ) )
  4088.             {
  4089.  
  4090.                     Model *pModel = load_LTA_Using_FeedBackDialog( filename, false  );
  4091.                     if( pModel != NULL )
  4092.                     {
  4093.                         pSocket->m_pAttachment = pModel ;
  4094.                         // Save this attachment in the registry
  4095.                         regMgr.Set(pSocket->GetName(), parse.m_Args[2]);
  4096.                     }
  4097.             }
  4098.             else
  4099.             {
  4100.                 MessageBox("ProcessCommandString error, trying to load bin abc file", "ERROR",MB_OK);
  4101.             
  4102.             }
  4103.         }
  4104.     }
  4105. }
  4106.  
  4107.  
  4108. void CModelEditDlg::OffsetTrans(DVector vec)
  4109. {
  4110.     int i;
  4111.  
  4112.     if (!m_pModel)
  4113.         return;
  4114.  
  4115.     for (i=0; (i < m_AnimList.GetItemCount()) && (i < (int)m_pModel->m_Anims.GetSize()); i++)
  4116.     {
  4117.         if (m_AnimList.GetItemState(i, LVIS_SELECTED) == 0)
  4118.             continue;
  4119.         m_pModel->GetAnimInfo(i)->m_vTranslation += vec;
  4120.     }
  4121.  
  4122.     SetChangesMade();
  4123. }
  4124.  
  4125.  
  4126. void CModelEditDlg::OffsetDims(DVector vec)
  4127. {
  4128.     int i;
  4129.  
  4130.     for (i=0; (i < m_AnimList.GetItemCount()) && (i < (int)m_pModel->m_Anims.GetSize()); i++)
  4131.     {
  4132.         if (m_AnimList.GetItemState(i, LVIS_SELECTED) == 0)
  4133.             continue;
  4134.         m_pModel->GetAnimInfo(i)->m_vDims += vec;
  4135.     }
  4136.  
  4137.     if( m_pDimensionDlg )
  4138.         m_pDimensionDlg->UpdateControls();
  4139.  
  4140.     SetChangesMade();
  4141. }
  4142.  
  4143.  
  4144. void CModelEditDlg::DoAnimEdit(DVector vec)
  4145. {
  4146.     if (IsButtonSelected(IDC_DIMS_EDIT))
  4147.         OffsetDims(vec);
  4148.     else
  4149.         OffsetTrans(vec);
  4150. }
  4151.  
  4152.  
  4153. void CModelEditDlg::OnTranslationButton() 
  4154. {
  4155.     TranslationDlg dlg;
  4156.     char tempStr[32];
  4157.     ModelAnim *pAnim;
  4158.     AnimInfo *pAnimInfo;
  4159.     NodeKeyFrame *pKeyframe;
  4160.     DVector newTrans, offset;
  4161.     int items[100], i, iAnim, nItems;
  4162.     DWORD iEditAnim;
  4163.     IdleChanger idle(&m_cWinIdle, IDLE_DIALOG_DELAY);      
  4164.     
  4165.  
  4166.  
  4167.     if(!GetEditAnimInfo(&iEditAnim, NULL, false))
  4168.         return;
  4169.  
  4170.     if (!GetAnimList(items, sizeof(items), nItems, FALSE))
  4171.         return;
  4172.         
  4173.     pAnim = m_pModel->GetAnim(iEditAnim);
  4174.     pAnimInfo = m_pModel->GetAnimInfo(iEditAnim);
  4175.  
  4176.     pKeyframe = &pAnim->GetRootNode()->m_KeyFrames[0];
  4177.     
  4178.     sprintf(tempStr, "%.3f", pAnimInfo->m_vTranslation.x);
  4179.     dlg.m_xTrans = tempStr;
  4180.  
  4181.     sprintf(tempStr, "%.3f", pAnimInfo->m_vTranslation.y);
  4182.     dlg.m_yTrans = tempStr;
  4183.  
  4184.     sprintf(tempStr, "%.3f", pAnimInfo->m_vTranslation.z);
  4185.     dlg.m_zTrans = tempStr;
  4186.  
  4187.     if (dlg.DoModal() == IDOK)
  4188.     {
  4189.         newTrans.x = (float)atof(dlg.m_xTrans);
  4190.         newTrans.y = (float)atof(dlg.m_yTrans);
  4191.         newTrans.z = (float)atof(dlg.m_zTrans);
  4192.  
  4193.         for (i=0; i < nItems; i++)
  4194.         {
  4195.             iAnim = items[i];
  4196.  
  4197.             pAnimInfo = m_pModel->GetAnimInfo(iAnim);
  4198.             pAnimInfo->m_vTranslation = newTrans;
  4199.         }
  4200.     }
  4201. }
  4202.  
  4203.  
  4204. void CModelEditDlg::OnRotationButton() 
  4205. {
  4206.     RotationDlg dlg;
  4207.     DVector vRot;
  4208.     int items[100], i, iAnim, nItems;
  4209.     IdleChanger idle(&m_cWinIdle, IDLE_DIALOG_DELAY);      
  4210.     
  4211.     
  4212.     if (!m_pModel)
  4213.         return;
  4214.  
  4215.     if (!GetAnimList(items, sizeof(items), nItems))
  4216.         return;
  4217.  
  4218.     dlg.m_sRotX = dlg.m_sRotY = dlg.m_sRotZ = "0.0";
  4219.  
  4220.     if (dlg.DoModal() == IDOK)
  4221.     {
  4222.         vRot.x = MATH_DEGREES_TO_RADIANS(( float )atof( dlg.m_sRotX ));
  4223.         vRot.y = MATH_DEGREES_TO_RADIANS(( float )atof( dlg.m_sRotY ));
  4224.         vRot.z = MATH_DEGREES_TO_RADIANS(( float )atof( dlg.m_sRotZ ));
  4225.  
  4226.         for (i=0; i < nItems; i++)
  4227.         {
  4228.             iAnim = items[i];
  4229.  
  4230.             model_RotateAnim(m_pModel, iAnim, &vRot);
  4231.         }
  4232.  
  4233.         m_bChangesMade = TRUE;
  4234.     }
  4235. }
  4236.  
  4237.  
  4238. void CModelEditDlg::OnXsub() 
  4239. {
  4240.     DoAnimEdit(DVector(-1.0f, 0.0f, 0.0f));
  4241. }
  4242.  
  4243. void CModelEditDlg::OnXadd() 
  4244. {
  4245.     DoAnimEdit(DVector(1.0f, 0.0f, 0.0f));
  4246. }
  4247.  
  4248. void CModelEditDlg::OnYsub() 
  4249. {
  4250.     DoAnimEdit(DVector(0.0f, -1.0f, 0.0f));
  4251. }
  4252.  
  4253. void CModelEditDlg::OnYadd() 
  4254. {
  4255.     DoAnimEdit(DVector(0.0f, 1.0f, 0.0f));
  4256. }
  4257.  
  4258. void CModelEditDlg::OnZsub() 
  4259. {
  4260.     DoAnimEdit(DVector(0.0f, 0.0f, -1.0f));
  4261. }
  4262.  
  4263. void CModelEditDlg::OnZadd() 
  4264. {
  4265.     DoAnimEdit(DVector(0.0f, 0.0f, 1.0f));
  4266. }
  4267.  
  4268. void CModelEditDlg::OnNumberAnim() 
  4269. {
  4270.     int i, nItems, items[100], iTemp, nSelection;
  4271.     DWORD insertAt, nTempAnims, nListItems;
  4272.     IdleChanger idle(&m_cWinIdle, IDLE_DIALOG_DELAY);      
  4273.  
  4274.  
  4275.     if (!m_pModel)
  4276.         return;
  4277.  
  4278.     if (!GetAnimList(items, sizeof(items), nItems))
  4279.         return;
  4280.     
  4281.     AnimNumberDlg dlg(this, m_pModel->m_Anims - nItems);
  4282.  
  4283.     if (dlg.DoModal() == IDOK)
  4284.     {    
  4285.         // Sort in descending order.
  4286.         for (i=0; i < (nItems-1); i++)
  4287.         {
  4288.             if (items[i] < items[i+1])
  4289.             {
  4290.                 iTemp = items[i];
  4291.                 items[i] = items[i+1];
  4292.                 items[i+1] = iTemp;
  4293.  
  4294.                 if (i == 0)
  4295.                     i -= 1;
  4296.                 else
  4297.                     i -= 2;
  4298.             }
  4299.         }
  4300.  
  4301.         // Remove them all from the listbox.
  4302.         for (i=0; i < nItems; i++)
  4303.         {
  4304.             nSelection = items[i];
  4305.  
  4306.             if (nSelection < 0 || nSelection >= (int)m_pModel->m_Anims.GetSize())
  4307.                 continue;
  4308.  
  4309.             m_AnimList.DeleteItem(nSelection);
  4310.         }
  4311.     
  4312.         for (i=0; i < m_AnimList.GetItemCount(); i++)
  4313.             m_AnimList.SetItemState(i, 0, LVIS_SELECTED);
  4314.  
  4315.         // Add them back in order.
  4316.         nListItems = m_pModel->m_Anims - nItems;
  4317.         insertAt = MIN(nListItems, (DWORD)dlg.m_MoveNumber);
  4318.         for (i=0; i < nItems; i++)
  4319.         {
  4320.             m_AnimList.InsertItem(insertAt, m_pModel->GetAnim(items[i])->GetName());
  4321.             m_AnimList.SetItemState(insertAt, LVIS_SELECTED, LVIS_SELECTED);
  4322.         }
  4323.  
  4324.         
  4325.         // Now rearrange the model's list.
  4326.         CMoArray<AnimInfo, NoCache> tempAnims;
  4327.         tempAnims.CopyArray(m_pModel->m_Anims);
  4328.         nTempAnims = m_pModel->m_Anims;
  4329.  
  4330.         for (i=0; i < nItems; i++)
  4331.         {
  4332.             m_pModel->m_Anims.Remove(items[i]);
  4333.         }
  4334.  
  4335.         insertAt = MIN(m_pModel->m_Anims.GetSize(), (DWORD)dlg.m_MoveNumber);
  4336.         for (i=0; i < nItems; i++)
  4337.         {
  4338.             m_pModel->m_Anims.Insert(insertAt, tempAnims[items[i]]);
  4339.         }
  4340.         
  4341.  
  4342.         // process the change
  4343.         StopAllPlayback();
  4344.         m_AnimInfos[ANIMINFO_MAIN].m_Tracker.m_TimeRef.Init(
  4345.             m_pModel,
  4346.             dlg.m_MoveNumber, 0,
  4347.             dlg.m_MoveNumber, 0);
  4348.  
  4349.         SetChangesMade();
  4350.     }
  4351. }
  4352.  
  4353.  
  4354. void CModelEditDlg::OnDuplicateAnim() 
  4355. {
  4356.     int nItems;
  4357.     DWORD i;
  4358.     ModelAnim *pNewAnim;
  4359.     char newName[300];
  4360.     AnimInfo *pSrcAnimInfo, *pAnimInfo;
  4361.     DVector srcDims;
  4362.     DVector srcTranslation;
  4363.  
  4364.     nItems = m_AnimList.GetItemCount();
  4365.     if (!nItems)
  4366.         return;
  4367.  
  4368.     // allocate a vector that will store the animation indices of duplicated animations
  4369.     std::vector<int> duplicatedIndices;
  4370.     duplicatedIndices.reserve( nItems );
  4371.  
  4372.     // the number of animations that originally existed
  4373.     int numOriginalAnimations = m_pModel->CalcNumParentAnims();
  4374.  
  4375.     // Add the duplicated ones.
  4376.     for (i=0; i < (DWORD)nItems; i++)
  4377.     {
  4378.         if (m_AnimList.GetItemState(i, LVIS_SELECTED) == 0)
  4379.             continue;
  4380.  
  4381.         pSrcAnimInfo = m_pModel->GetAnimInfo(i);
  4382.     
  4383.         // if the file version between the child and parent are different quit operation.
  4384.         // right now, if file versions are different ModelEdit will crash.
  4385.         if( m_pModel->GetFileVersion() != pSrcAnimInfo->m_pAnim->GetModel()->GetFileVersion() ) 
  4386.         {
  4387.             int iChildFileVersion       = pSrcAnimInfo->m_pAnim->GetModel()->GetFileVersion();
  4388.             const char *childFileName   = pSrcAnimInfo->m_pChildInfo->m_pFilename ;
  4389.             const char *parentName      = m_pModel->GetFilename() ;
  4390.  
  4391.             char msg[2048];
  4392.             sprintf(msg, "%s\nParent %s version : %d\nChild (%s) version : %d\n",
  4393.                     "Cannot Copy Animations from Child Models of Different Version",
  4394.                     parentName, m_pModel->GetFileVersion(),        
  4395.                     childFileName,iChildFileVersion);        
  4396.  
  4397.             MessageBox(msg, "Anim Copy Error", MB_OK|MB_ICONEXCLAMATION);
  4398.             return ;
  4399.         }
  4400.         
  4401.         srcDims = pSrcAnimInfo->m_vDims;
  4402.         srcTranslation = pSrcAnimInfo->m_vTranslation;
  4403.  
  4404.         sprintf(newName, "%s_copy", pSrcAnimInfo->m_pAnim->GetName());
  4405.  
  4406.         pNewAnim = new ModelAnim(m_pModel);
  4407.         if (!pNewAnim)
  4408.             return;
  4409.  
  4410.         if (!pNewAnim->CopyAnim(m_pModel->GetAnim(i)) || 
  4411.             !(pAnimInfo = m_pModel->AddAnimToSelf(pNewAnim)))
  4412.         {
  4413.             delete pNewAnim;
  4414.             return;
  4415.         }
  4416.  
  4417.         pAnimInfo->m_vDims = srcDims;
  4418.         pAnimInfo->m_vTranslation = srcTranslation;
  4419.  
  4420.         pNewAnim->SetName(newName);
  4421.  
  4422.         duplicatedIndices.push_back( i );
  4423.     }
  4424.  
  4425.     // move the duplicated animations immediately below their original
  4426.     int curIndex = 0;
  4427.     for( std::vector<int>::iterator it = duplicatedIndices.begin(); it != duplicatedIndices.end(); it++ )
  4428.     {
  4429.         // stop moving animations if they are in child models
  4430.         if( *it >= numOriginalAnimations )
  4431.             break;
  4432.  
  4433.         AnimInfo curAnimInfo = m_pModel->m_Anims[numOriginalAnimations + curIndex];
  4434.  
  4435.         for( i = numOriginalAnimations + curIndex; i > (*it + curIndex); i-- )
  4436.         {
  4437.             m_pModel->m_Anims[i] = m_pModel->m_Anims[i-1];
  4438.         }
  4439.  
  4440.         m_pModel->m_Anims[*it+1+curIndex] = curAnimInfo;
  4441.  
  4442.         curIndex++;
  4443.     }
  4444.  
  4445.     InitTaggedArrays();
  4446.     FillAnimList();
  4447.     SetChangesMade();
  4448. }
  4449.  
  4450. // ------------------------------------------------------------------------
  4451. // FillAnimDataFromTransformNodeData()
  4452. // basically take the bind pose and put it in the animation hierarchy.
  4453. // ------------------------------------------------------------------------
  4454. static void FillAnimDataFromTransformNodeData( AnimNode *pAnimNode )
  4455. {
  4456.     ModelNode *pNode = pAnimNode->m_pNode ;
  4457.     LTMatrix mat ;
  4458.     LTVector pos;
  4459.     LTRotation rot ;
  4460.     
  4461.     mat = pNode->GetLocalTransform();
  4462.  
  4463.     // get components
  4464.     mat.GetTranslation(pos);
  4465.     quat_ConvertFromMatrix( rot.m_Quat, mat.m );
  4466.     
  4467.     // pass it to anim data.
  4468.     for( int kfcnt = 0 ; kfcnt < pAnimNode->m_KeyFrames.GetSize() ;kfcnt++) 
  4469.     {
  4470.         pAnimNode->m_KeyFrames[kfcnt].m_Translation = pos ;
  4471.         pAnimNode->m_KeyFrames[kfcnt].m_Quaternion  = rot ;    
  4472.     }
  4473.  
  4474.     // recurse through the heirarchy.
  4475.     for( int childcnt = 0 ; childcnt < pAnimNode->m_Children.GetSize() ; childcnt++)
  4476.     {
  4477.         FillAnimDataFromTransformNodeData( pAnimNode->m_Children[childcnt]);
  4478.     }
  4479. }
  4480.  
  4481.  
  4482. // ------------------------------------------------------------------------
  4483. // create an animation from the bind pose 
  4484. // ------------------------------------------------------------------------
  4485. void CModelEditDlg::OnCreateAnimFromBindPose()
  4486. {
  4487.     char *szAnimName = "bind_pose";
  4488.  
  4489.     m_pModel->AddDummyAnimation( szAnimName );
  4490.  
  4491.     AnimInfo* pInfo;
  4492.     uint32 nAnimIndex;
  4493.     ModelAnim *pAnim = m_pModel->FindAnim( szAnimName, &nAnimIndex, &pInfo );
  4494.  
  4495.     if( pAnim )
  4496.     {
  4497.         for( int kfcnt = 0 ; kfcnt < pAnim->m_KeyFrames.GetSize() ;kfcnt++) 
  4498.             pAnim->m_KeyFrames[kfcnt].m_pString = pAnim->GetModel()->AddString("");
  4499.         
  4500.         // fill anim. got down model hierarchy & anim 
  4501.         FillAnimDataFromTransformNodeData( pAnim->GetRootNode());
  4502.  
  4503.         // setup the dims for the binding pose
  4504.         if(pInfo)
  4505.         {
  4506.             LTVector vDims;
  4507.             if(CDimensionsDlg::FindAnimDims(m_pModel, nAnimIndex, 0, vDims))
  4508.                 pInfo->m_vDims = vDims;
  4509.         }
  4510.  
  4511.         // tell model edit about it.
  4512.         FillAnimList();
  4513.     }
  4514. }
  4515.  
  4516. void CModelEditDlg::OnRenameNode() 
  4517. {
  4518.     RenameNodeDlg dlg;
  4519.     DWORD i;
  4520.     char msg[200];
  4521.     IdleChanger idle(&m_cWinIdle, IDLE_DIALOG_DELAY);      
  4522.  
  4523.     if (!m_pModel)
  4524.         return;
  4525.     
  4526.     if (dlg.DoModal() == IDOK)
  4527.     {
  4528.         for (i=0; i < m_pModel->m_FlatNodeList; i++)
  4529.         {
  4530.             if (strcmp(m_pModel->m_FlatNodeList[i]->GetName(), dlg.m_OldName) == 0)
  4531.             {
  4532.                 m_pModel->m_FlatNodeList[i]->SetName((char*)(LPCTSTR)dlg.m_NewName);
  4533.  
  4534.                 sprintf(msg, "'%s' has been renamed to '%s'.", dlg.m_OldName, (char*)(LPCTSTR)dlg.m_NewName);
  4535.                 MessageBox(msg, "ModelEdit", MB_OK);
  4536.                 SetChangesMade();
  4537.  
  4538.                 // Redo the node list.
  4539.                 FillNodeList();
  4540.                 return;
  4541.             }
  4542.         }
  4543.     
  4544.         sprintf(msg, "Couldn't find node: '%s'.", dlg.m_OldName);
  4545.         MessageBox(msg, "ModelEdit", MB_OK);
  4546.     }
  4547. }
  4548.  
  4549.  
  4550.  
  4551. void UnrotateNodes(Model *pModel, DWORD transformIndex, int *items, int nItems, int nLevels)
  4552. {
  4553.     int i;
  4554.     DWORD j, iAnim;
  4555.     ModelAnim *pAnim;
  4556.     ModelNode *pNode;
  4557.  
  4558.  
  4559.     pNode = pModel->m_FlatNodeList[transformIndex];
  4560.     for (i=0; i < nItems; i++)
  4561.     {
  4562.         iAnim = (DWORD)items[i];
  4563.         pAnim = pModel->GetAnim(iAnim);
  4564.  
  4565.         pModel->UnrotateAnimNode(pAnim, pAnim->m_AnimNodes[transformIndex]);
  4566.     }
  4567.  
  4568.     // Do the child nodes too?
  4569.     --nLevels;
  4570.     if (nLevels > 0)
  4571.     {
  4572.         for (j=0; j < pNode->m_Children; j++)
  4573.         {
  4574.             UnrotateNodes(pModel, pNode->m_Children[j]->GetNodeIndex(), items, nItems, nLevels);
  4575.         }
  4576.     }
  4577. }
  4578.  
  4579.  
  4580. void CModelEditDlg::OnUnrotateTopNode() 
  4581. {
  4582.     int status, nLevels, nItems, items[100];
  4583.     char msg[256];
  4584.  
  4585.  
  4586.     if (!m_pModel || !GetAnimList(items, sizeof(items), nItems))
  4587.         return;
  4588.  
  4589.     nLevels = 1;
  4590.     if (nLevels > 1)
  4591.     {
  4592.         sprintf(msg, "There are %d levels of top-level nulls.  Unrotate them all?", nLevels);
  4593.         status = MessageBox(msg, "ModelEdit", MB_YESNOCANCEL);
  4594.         if (status == IDCANCEL)
  4595.             return;
  4596.         else if (status == IDNO)
  4597.             nLevels = 1;
  4598.     }
  4599.  
  4600.     if (nLevels == 0)
  4601.         nLevels = 1;
  4602.  
  4603.     UnrotateNodes(m_pModel, m_pModel->GetRootNode()->GetNodeIndex(), items, nItems, nLevels);
  4604.     SetChangesMade();
  4605. }
  4606.  
  4607.  
  4608. BOOL CModelEditDlg::PreTranslateMessage(MSG* pMsg) 
  4609. {
  4610.     // check if the user is editing something in a tree control
  4611.     // see knowledge base Q167960 for an explanation (basically, tree controls and dialogs don't mix)
  4612.     if( pMsg->message == WM_KEYDOWN && (pMsg->wParam == VK_RETURN || pMsg->wParam == VK_ESCAPE) )
  4613.     {
  4614.         // check the piece list
  4615.         CEdit* edit = m_PieceList.GetEditControl();
  4616.         if( edit )
  4617.         {
  4618.             edit->SendMessage( WM_KEYDOWN, pMsg->wParam, pMsg->lParam );
  4619.             return TRUE;
  4620.         }
  4621.     }
  4622.  
  4623.     TranslateAccelerator(m_hWnd, m_hAccel, pMsg);
  4624.     
  4625.     return CDialog::PreTranslateMessage(pMsg);
  4626. }
  4627.  
  4628.  
  4629. void CModelEditDlg::OnGenerateVertexNormals()
  4630. {
  4631.     if (!m_pModel)
  4632.         return;
  4633.  
  4634.     gn_BuildModelVertexNormals(m_pModel);
  4635.     SetChangesMade();
  4636. }
  4637.  
  4638.  
  4639. void CModelEditDlg::OnReverseAnimation()
  4640. {
  4641.     int items[100], nItems, i, j;
  4642.     ModelAnim *pAnim, *pFrame1, *pFrame2;
  4643.     DWORD nKeyFrames, iKeyframe1, iKeyframe2, oldAnimTime;
  4644.  
  4645.  
  4646.     if (!m_pModel || !GetAnimList(items, sizeof(items), nItems))
  4647.         return;
  4648.  
  4649.     for (i=0; i < nItems; i++)
  4650.     {
  4651.         if (items[i] >= (int)m_pModel->m_Anims.GetSize())
  4652.             continue;
  4653.  
  4654.         pAnim = m_pModel->GetAnim(items[i]);
  4655.         oldAnimTime = pAnim->GetAnimTime();
  4656.  
  4657.         nKeyFrames = pAnim->m_KeyFrames.GetSize();
  4658.         for (j=0; j < (int)(nKeyFrames/2); j++)
  4659.         {
  4660.             iKeyframe1 = j;
  4661.             iKeyframe2 = nKeyFrames - j - 1;
  4662.  
  4663.             pFrame1 = pAnim->CopyKeyFrame(iKeyframe1);
  4664.             pFrame2 = pAnim->CopyKeyFrame(iKeyframe2);
  4665.  
  4666.             if (!pFrame1 || !pFrame2)
  4667.             {
  4668.                 if (pFrame1)
  4669.                     delete pFrame1;
  4670.  
  4671.                 if (pFrame2)
  4672.                     delete pFrame2;
  4673.  
  4674.                 MessageBox("Error copying frames.", "ModelEdit", MB_OK);
  4675.                 return;
  4676.             }
  4677.             
  4678.             if (!pAnim->PasteKeyFrame(pFrame2, iKeyframe1))
  4679.             {
  4680.                 MessageBox("Error pasting keyframe.");
  4681.                 return;
  4682.             }
  4683.             pAnim->RemoveKeyFrame(iKeyframe1+1);
  4684.  
  4685.             if (!pAnim->PasteKeyFrame(pFrame1, iKeyframe2))
  4686.             {
  4687.                 MessageBox("Error pasting keyframe.");
  4688.                 return;
  4689.             }
  4690.             pAnim->RemoveKeyFrame(iKeyframe2+1);
  4691.  
  4692.             delete pFrame1;
  4693.             delete pFrame2;
  4694.         }
  4695.  
  4696.         // Reverse the keyframe times.
  4697.         for (i=0; i < (int)pAnim->m_KeyFrames; i++)
  4698.         {
  4699.             pAnim->m_KeyFrames[i].m_Time = oldAnimTime - pAnim->m_KeyFrames[i].m_Time;
  4700.         }
  4701.     }
  4702. }
  4703.  
  4704.  
  4705. void CModelEditDlg::OnSelectNullNodes()
  4706. {
  4707. }
  4708.  
  4709.  
  4710. void CModelEditDlg::OnRemoveNode()
  4711. {
  4712.     int iIndex;
  4713.                              
  4714.     if (!m_pModel)
  4715.         return;
  4716.  
  4717.     iIndex = m_NodeList.GetSelectionMark();
  4718.     if (iIndex < 0)
  4719.         return;
  4720.  
  4721.     if ((DWORD)iIndex < m_pModel->NumNodes())
  4722.     {
  4723.         m_pModel->RemoveNode(m_pModel->GetNode((DWORD)iIndex));
  4724.     }
  4725.  
  4726.     FillNodeList();
  4727. }
  4728.  
  4729.  
  4730. void CModelEditDlg::OnSetTexture()
  4731. {
  4732.     IdleChanger idle(&m_cWinIdle, IDLE_DIALOG_DELAY);      
  4733.     DWORD nTexture = 0;
  4734.  
  4735.     // if we don't have a model loaded bomb out.
  4736.     if( m_pModel == NULL )
  4737.     {
  4738.         MessageBox("Must have a model to set textures.","WARNING", MB_ICONWARNING);
  4739.         return ;
  4740.     }
  4741.  
  4742.     // Look up the open directory in the registry
  4743.     CRegMgr regMgr;
  4744.     CString csOpenDir;
  4745.     if (regMgr.Init(szRegKeyCompany, szRegKeyApp, szRegKeyVer, "OpenDir", HKEY_CURRENT_USER))
  4746.     {
  4747.         UINT32 dwSize = 256;
  4748.         regMgr.Get("Texture", csOpenDir.GetBufferSetLength(dwSize), dwSize);
  4749.         csOpenDir.ReleaseBuffer(-1);
  4750.     }
  4751.  
  4752.     // Strip the extension...
  4753.     char* pExt = _tcsrchr(csOpenDir,'.'); 
  4754.     if (pExt) { csOpenDir.TrimRight(pExt); }
  4755.     csOpenDir += "*.dtx";
  4756.  
  4757.     char szFilter[] = "Texture Files (*.dtx)|*.dtx|All Files (*.*)|*.*||";
  4758.     CFileDialog dlg (TRUE, "dtx", (csOpenDir.GetLength()) ? (LPCTSTR)csOpenDir : NULL, OFN_FILEMUSTEXIST | OFN_HIDEREADONLY, szFilter, this);
  4759.     if (dlg.DoModal() != IDOK)
  4760.     {
  4761.         return;
  4762.     }
  4763.  
  4764.     // Store the open directory in the registry
  4765.     csOpenDir = dlg.GetPathName();
  4766.     csOpenDir = csOpenDir.Left(csOpenDir.GetLength() - dlg.GetFileName().GetLength());
  4767.     regMgr.Set("Texture", (LPCTSTR)csOpenDir);
  4768.  
  4769.     //  checking for errors while setting the texture
  4770.     bool textureSetSuccessful = true;
  4771.  
  4772.     // Find the selected texture in the piece list
  4773.     if (m_pModel)
  4774.     {
  4775.         vector<PieceLODInfo> selection;
  4776.         int numSelected = GetSelectedPieceLODs( &m_PieceList, m_pModel, selection );
  4777.  
  4778.         // grab the indices we need to set
  4779.         set<int> indices;
  4780.         indices.clear();
  4781.  
  4782.         for( int i = 0; i < selection.size(); i++ )
  4783.         {
  4784.             indices.insert( selection[i].m_PieceLOD->m_iTextures[0] );
  4785.         }
  4786.  
  4787.         // set the texture indices
  4788.         set<int>::iterator it;
  4789.  
  4790.         for( it = indices.begin(); it != indices.end(); it++ )
  4791.         {
  4792.             if( !SetRenderTexture( dlg.GetPathName(), *it ) )
  4793.                 textureSetSuccessful = false;
  4794.         }
  4795.     }
  4796.  
  4797.     if( !textureSetSuccessful )
  4798.     {
  4799.         MessageBox( "Unable to load or set texture", "ModelEdit", MB_OK );
  4800.     }
  4801.     /*
  4802.     IdleChanger idle(&m_cWinIdle, IDLE_DIALOG_DELAY);      
  4803.     DWORD nTexture = 0;
  4804.  
  4805.     // if we don't have a model loaded bomb out.
  4806.     if( m_pModel == NULL )
  4807.     {
  4808.         MessageBox("Must have a model to set textures.","WARNING", MB_ICONWARNING);
  4809.         return ;
  4810.     }
  4811.  
  4812.     // if we don't have a model loaded bomb out.
  4813.     if( m_pModel == NULL )
  4814.     {
  4815.         MessageBox("Must have a model to set textures.","WARNING", MB_ICONWARNING);
  4816.         return ;
  4817.     }
  4818.  
  4819.     // Look up the open directory in the registry
  4820.     CRegMgr regMgr;
  4821.     CString csOpenDir;
  4822.     if (regMgr.Init(szRegKeyCompany, szRegKeyApp, szRegKeyVer, "OpenDir", HKEY_CURRENT_USER))
  4823.     {
  4824.         UINT32 dwSize = 256;
  4825.         regMgr.Get("Texture", csOpenDir.GetBufferSetLength(dwSize), dwSize);
  4826.         csOpenDir.ReleaseBuffer(-1);
  4827.     }
  4828.  
  4829.     // Strip the extension...
  4830.     char* pExt = _tcsrchr(csOpenDir,'.'); 
  4831.     if (pExt) { csOpenDir.TrimRight(pExt); }
  4832.     csOpenDir += "*.dtx";
  4833.  
  4834.     char szFilter[] = "Texture Files (*.dtx)|*.dtx|All Files (*.*)|*.*||";
  4835.     CFileDialog dlg (TRUE, "dtx", (csOpenDir.GetLength()) ? (LPCTSTR)csOpenDir : NULL, OFN_FILEMUSTEXIST | OFN_HIDEREADONLY, szFilter, this);
  4836.     if (dlg.DoModal() != IDOK)
  4837.     {
  4838.         return;
  4839.     }
  4840.  
  4841.     // Store the open directory in the registry
  4842.     csOpenDir = dlg.GetPathName();
  4843.     csOpenDir = csOpenDir.Left(csOpenDir.GetLength() - dlg.GetFileName().GetLength());
  4844.     regMgr.Set("Texture", (LPCTSTR)csOpenDir);
  4845.  
  4846.     //  checking for errors while setting the texture
  4847.     bool textureSetSuccessful = true;
  4848.  
  4849.     // Find the selected texture in the piece list
  4850.     
  4851.     for (i = 0; i < (DWORD)m_PieceList.GetItemCount(); i++)
  4852.     {
  4853.         vector<PieceLODInfo> selection;
  4854.         int numSelected = GetSelectedPieceLODs( &m_PieceList, m_pModel, selection );
  4855.  
  4856.         // grab the indices we need to set
  4857.         set<int> indices;
  4858.         indices.clear();
  4859.  
  4860.         for( int i = 0; i < selection.size(); i++ )
  4861.         {
  4862.             indices.insert( selection[i].m_PieceLOD->m_iTextures[0] );
  4863.         }
  4864.  
  4865.         // set the texture indices
  4866.         set<int>::iterator it;
  4867.  
  4868.         for( it = indices.begin(); it != indices.end(); it++ )
  4869.         {
  4870.             if( !SetRenderTexture( dlg.GetPathName(), *it ) )
  4871.                 textureSetSuccessful = false;
  4872.         }
  4873.     }
  4874.  
  4875.     if( !textureSetSuccessful )
  4876.     {
  4877.         MessageBox( "Unable to load or set texture", "ModelEdit", MB_OK );
  4878.     }
  4879.     */
  4880. }
  4881.  
  4882.  
  4883. void CModelEditDlg::OnAddChildModel()
  4884. {
  4885.     CString sDefExtension;
  4886.     sDefExtension.LoadString(IDS_ADDCHILDMODELEXT);
  4887.     CString sDefFilter;
  4888.     sDefFilter.LoadString(IDS_ADDCHILDMODELFILTER);
  4889.  
  4890.     CAddChildModelDlg dlg(TRUE, sDefExtension, NULL, OFN_FILEMUSTEXIST, sDefFilter);
  4891.  
  4892.     CString curFilename, str;
  4893.     ModelLoadRequest request;
  4894.     Model *pChild = NULL;
  4895.     ChildInfo *pInfo;
  4896.     char errStr[2048];
  4897.     IdleChanger idle(&m_cWinIdle, IDLE_DIALOG_DELAY);      
  4898.  
  4899.  
  4900.     if (!m_pModel)
  4901.         return;
  4902.  
  4903.     if (dlg.DoModal() == IDOK)
  4904.     {
  4905.         if (m_pModel->FindChildModelByFilename((char*)(LPCTSTR)dlg.GetFileName()))
  4906.         {
  4907.             DoMessageBox(IDS_NODUPLICATECHILDMODELNAMES, MB_OK);
  4908.         }
  4909.         else
  4910.         {
  4911.             char dirName[1024];
  4912.             char newFilename[2048];
  4913.  
  4914.  
  4915.             request.m_bLoadChildModels = FALSE;
  4916.         //    pChild = LoadChildModel(&request, (char*)(LPCTSTR)m_strFilename, pChildFilename);
  4917.  
  4918.             // begin ----------------------------------------------------
  4919.             // I'm inlining the child model loading here.
  4920.             // we need the current alloc from the model and other data that's relevant.
  4921.             
  4922.             
  4923.  
  4924.             CString sFilepath = dlg.GetPathName();
  4925.  
  4926.             CHelpers::ExtractNames(m_strFilename, dirName, NULL, NULL, NULL);
  4927.             if (dirName[0] == 0)
  4928.             {
  4929.                 sprintf(newFilename, "%s", (LPCTSTR)dlg.GetFileName());
  4930.             }
  4931.             else
  4932.             {
  4933.                 sprintf(newFilename, "%s\\%s", dirName, (LPCTSTR)dlg.GetFileName());
  4934.             }
  4935.  
  4936.             sprintf(newFilename, "%s", sFilepath);
  4937.     
  4938.             int base_is_lta = IsFilenameLTAExt( m_strFilename ) ;
  4939.             int child_is_lta= IsFilenameLTAExt( (LPCTSTR)dlg.GetFileName() );
  4940.  
  4941.             if( base_is_lta && child_is_lta )
  4942.             {
  4943.                 // Load up the shared anims.
  4944.  
  4945.                 pChild = load_LTA_Using_FeedBackDialog( newFilename, true );
  4946.                 //pChild = ltaLoadChildModel( newFilename , (LAllocCount*)m_pModel->GetAlloc() );            
  4947.  
  4948.             }
  4949.             else 
  4950.             {
  4951.                 MessageBox("ABC LOAD ATTEMPT IN  ON_ADD_CHILD_MODEL", "ERROR", MB_OK);
  4952.  
  4953.             }
  4954.  
  4955.             // end -------------------------------------------------------
  4956.  
  4957.             if (!pChild)
  4958.             {
  4959.                  str.FormatMessage(IDS_CANTLOADCHILDMODEL, (LPCTSTR)dlg.GetFileName());
  4960.                 DoMessageBox(str, MB_OK);
  4961.                 return;
  4962.             }
  4963.  
  4964.             // Build the correct filename right here people....
  4965.  
  4966.             char sSrc1[1024];
  4967.             char sSrc2[1024];
  4968.  
  4969.             char *sSrc, *sDst;
  4970.  
  4971.             sprintf(sSrc1, "%s", m_strFilename);
  4972.             sprintf(sSrc2, "%s", (char *)(LPCSTR)dlg.GetPathName());
  4973.  
  4974.             // Compare strings until they differ....
  4975.  
  4976.             int szSrc1 = strlen(sSrc1);
  4977.             int szSrc2 = strlen(sSrc2);
  4978.             char sDstFilename[1024];
  4979.             memset(sDstFilename, 0, 1024);
  4980.  
  4981.             bool bUseNewFilename = false;
  4982.             
  4983.             if (szSrc1 && szSrc2)
  4984.             {            
  4985.                 int nCount = 0;
  4986.                 int nSize = szSrc1 > szSrc2 ? szSrc1 : szSrc2;
  4987.  
  4988.                 while (nCount < nSize)
  4989.                 {
  4990.                     if ((sSrc1[nCount] != sSrc2[nCount]) && (nCount))
  4991.                     {
  4992.                         // This is where the change occurs, last character should be a 
  4993.                         // backslash
  4994.  
  4995.                         if (sSrc1[nCount - 1] == '\\')
  4996.                         {
  4997.                             sSrc = sSrc1 + nCount;
  4998.                             sDst = sSrc2 + nCount;
  4999.  
  5000.                             // Now, count how many backslashes there are....
  5001.  
  5002.                             int nSave = nCount;
  5003.                             int nBackSlashes = 0;
  5004.                             
  5005.                             while (nCount < szSrc1)
  5006.                             {
  5007.                                 if (sSrc1[nCount] == '\\')
  5008.                                 {
  5009.                                     nBackSlashes ++;
  5010.                                 }
  5011.  
  5012.                                 nCount ++;
  5013.                             }
  5014.  
  5015.                             nCount = nSave;
  5016.  
  5017.                             for (int i = 0; i < nBackSlashes; i ++)
  5018.                             {
  5019.                                 strcat(sDstFilename, "..\\");
  5020.                             }
  5021.  
  5022.                             char *sOut = sSrc2 + nCount;
  5023.  
  5024.                             strcat(sDstFilename, sOut);
  5025.                             strcat(sDstFilename, "\0");
  5026.  
  5027.                             nCount = nSize;
  5028.                             bUseNewFilename = true;
  5029.                         }
  5030.                     }
  5031.  
  5032.                     nCount ++;
  5033.                 }
  5034.             }
  5035.  
  5036.             CString sFileName = bUseNewFilename ? sDstFilename : (char *)(LPCSTR)dlg.GetFileName();
  5037. //            if (pInfo = m_pModel->AddChildModel(pChild, (char*)((LPCTSTR)dlg.GetFileName()), errStr, dlg.m_bScaleSkeleton))
  5038.             if (pInfo = m_pModel->AddChildModel(pChild, (char *)(LPCSTR)sFileName, errStr, dlg.m_bScaleSkeleton ? true : false))
  5039.             {
  5040.                 // Update bounding radii.
  5041.                 pInfo->m_SaveIndex = pChild->GetSaveIndex();
  5042.  
  5043.                 // Update other stuff.
  5044.                 str.FormatMessage(IDS_ADDEDCHILDSUCCESSFULLY, (LPCTSTR)dlg.GetFileName());
  5045.                 DoMessageBox(str, MB_OK);
  5046.  
  5047.                 FillChildModelList();
  5048.                 FillAnimList();
  5049.                 InitTaggedArrays();
  5050.  
  5051.                 SetChangesMade();
  5052.             }
  5053.             else
  5054.             {
  5055.                 delete pChild;
  5056.                 str.FormatMessage(IDS_CANTADDCHILDMODEL, errStr);
  5057.                 DoMessageBox(str, MB_OK);
  5058.             }
  5059.         }
  5060.     }
  5061. }
  5062.  
  5063.  
  5064. void CModelEditDlg::OnRemoveChildModel()
  5065. {
  5066.     int iCurSel;
  5067.     uint32 itemIndex;
  5068.     CString curFilename, itemText;
  5069.                              
  5070.     if (!m_pModel)
  5071.         return;
  5072.  
  5073.     iCurSel = m_ChildModelList.GetCurSel();
  5074.     if (iCurSel != LB_ERR)
  5075.     {
  5076.         m_ChildModelList.GetText(iCurSel, itemText);
  5077.         if (m_pModel->FindChildModelByFilename((char*)(LPCTSTR)itemText, &itemIndex))
  5078.         {
  5079.  
  5080.             if (m_pModel->RemoveChildModel(itemIndex))
  5081.             {
  5082.                 StopAllPlayback();
  5083.                 m_AnimInfos[ANIMINFO_MAIN].m_Tracker.m_TimeRef.Init(m_pModel);
  5084.  
  5085.                 FillChildModelList();
  5086.                 FillAnimList();
  5087.                 InitTaggedArrays();
  5088.  
  5089.                 SetChangesMade();
  5090.             }
  5091.         }
  5092.     }
  5093. }
  5094.  
  5095.  
  5096. void CModelEditDlg::OnRebuildChildModelTree()
  5097. {
  5098. }
  5099.  
  5100.  
  5101. void CModelEditDlg::OnTimer(UINT nIDEvent) 
  5102. {
  5103.     static BOOL bFirst=TRUE;
  5104.  
  5105.     // Handle startup options (we do it in the timer so we can do MessageBox).
  5106.     if (bFirst)
  5107.     {
  5108.         bFirst = FALSE;
  5109.  
  5110.         if (__argc > 1)
  5111.         {
  5112.             DoLoadModel(__argv[1], FALSE);
  5113.         }
  5114.  
  5115.         if (__argc > 2)
  5116.         {
  5117.             SetRenderTexture(__argv[2]);
  5118.         }
  5119.     }
  5120.  
  5121.     CDialog::OnTimer(nIDEvent);
  5122. }
  5123.  
  5124.  
  5125. void CModelEditDlg::OnAddSocket()
  5126. {
  5127.     DWORD i;
  5128.     uint32 nodeIndex;
  5129.     int curSel;
  5130.     AddSocketDlg dlg;
  5131.     char testName[256];
  5132.     ModelSocket *pSocket;
  5133.     DVector nodePos, parentPos, forwardVec;
  5134.     DVector vecs[3];
  5135.     ModelNode *pNode, *pParent;
  5136.     DMatrix mat, fullTransform, *pNodeTransform, *pParentTransform;
  5137.     TransformMaker tMaker;
  5138.     IdleChanger idle(&m_cWinIdle, IDLE_DIALOG_DELAY);      
  5139.  
  5140.  
  5141.     if (!m_pModel)
  5142.         return;
  5143.  
  5144.     curSel = m_NodeList.GetSelectionMark();
  5145.     if ((DWORD)curSel < m_pModel->NumNodes())
  5146.     {
  5147.         dlg.m_NodeName = m_pModel->GetNode((DWORD)curSel)->GetName();
  5148.     }
  5149.  
  5150.     // Fill in a unique name.
  5151.     for (i=0; i < m_pModel->NumSockets()+1; i++)
  5152.     {
  5153.         sprintf(testName, "Socket%d", i);
  5154.         if (!m_pModel->FindSocket(testName))
  5155.         {
  5156.             dlg.m_SocketName = testName;
  5157.             break;
  5158.         }
  5159.     }
  5160.  
  5161.     dlg.m_pDlg = this;
  5162.     if (dlg.DoModal() == IDOK)
  5163.     {
  5164.         // No duplicate names..
  5165.         if (m_pModel->FindSocket((LPCTSTR)dlg.m_SocketName))
  5166.             return;
  5167.  
  5168.         // Node must exist.
  5169.         if (!m_pModel->FindNode((LPCTSTR)dlg.m_NodeName, &nodeIndex))
  5170.             return;
  5171.  
  5172.         if (pSocket = new ModelSocket)
  5173.         {
  5174.             pSocket->SetName((LPCTSTR)dlg.m_SocketName);
  5175.             pSocket->m_iNode = nodeIndex;
  5176.             
  5177.             // Set it up facing down the bone.
  5178.             pNode = m_pModel->GetNode(nodeIndex);
  5179.             if (pParent = m_pModel->FindParent(m_pModel->GetNode(nodeIndex), m_pModel->GetRootNode()))
  5180.             {
  5181.                 if (m_pModel->NumAnims() > 0)
  5182.                 {
  5183.                     tMaker.m_Anims[0].Init(m_pModel, 0, 0, 0, 0, 0.0f);
  5184.                     tMaker.m_nAnims = 1;
  5185.                     if (tMaker.SetupTransforms())
  5186.                     {
  5187.                         pNodeTransform = m_pModel->GetTransform(pNode->GetNodeIndex());
  5188.                         pParentTransform = m_pModel->GetTransform(pParent->GetNodeIndex());
  5189.  
  5190.                         Mat_GetTranslation(*pNodeTransform, nodePos);
  5191.                         Mat_GetTranslation(*pParentTransform, parentPos);
  5192.                     
  5193.                         forwardVec = nodePos - parentPos;
  5194.                         forwardVec.Norm();
  5195.  
  5196.                         gr_BuildFrameOfReference(&forwardVec, NULL, &vecs[0], &vecs[1], &vecs[2]);
  5197.                         Mat_Identity(&mat);
  5198.                         
  5199.                         Mat_SetBasisVectors(&mat, &vecs[0], &vecs[1], &vecs[2]);
  5200.  
  5201.                         fullTransform = pNodeTransform->MakeInverseTransform() * mat;
  5202.                         pSocket->m_Rot.ConvertFromMatrix(fullTransform);
  5203.                     }
  5204.                 }
  5205.             }
  5206.             
  5207.             if (m_pModel->AddSocket(pSocket))
  5208.             {
  5209.                 SetChangesMade();
  5210.                 FillSocketList();
  5211.                 m_SocketList.SetCurSel((int)(m_pModel->NumSockets() - 1));
  5212.             }
  5213.             else
  5214.             {
  5215.                 delete pSocket;
  5216.             }
  5217.         }
  5218.     }
  5219. }
  5220.  
  5221.  
  5222. void CModelEditDlg::OnRemoveSocket()
  5223. {
  5224.     int curSel;
  5225.  
  5226.     if (!m_pModel)
  5227.         return;
  5228.  
  5229.     curSel = m_SocketList.GetCurSel();
  5230.     if (curSel != LB_ERR && curSel < (int)m_pModel->NumSockets())
  5231.     {
  5232.         m_pModel->RemoveSocket((DWORD)curSel);
  5233.         FillSocketList();
  5234.     }
  5235. }
  5236.  
  5237.  
  5238. void CModelEditDlg::OnRenameSocket()
  5239. {
  5240.     int curSel;
  5241.     CStringDlg dlg;
  5242.     LPCTSTR pName;
  5243.     ModelSocket *pSocket;
  5244.     IdleChanger idle(&m_cWinIdle, IDLE_DIALOG_DELAY);      
  5245.  
  5246.     if (!m_pModel)
  5247.         return;
  5248.  
  5249.     curSel = m_SocketList.GetCurSel();
  5250.     if (curSel != LB_ERR && curSel < (int)m_pModel->NumSockets())
  5251.     {
  5252.         pSocket = m_pModel->GetSocket((DWORD)curSel);
  5253.  
  5254.         dlg.m_bAllowLetters = TRUE;
  5255.         dlg.m_bAllowNumbers = TRUE;
  5256.         dlg.m_bAllowOthers = TRUE;
  5257.         dlg.m_EnteredText = pSocket->GetName();
  5258.  
  5259.         if (dlg.DoModal(IDS_MODELEDIT_CAPTION, IDS_ENTER_SOCKETNAME) == IDOK)
  5260.         {
  5261.             pName = (LPCTSTR)dlg.m_EnteredText;
  5262.             if (strlen(pName) == 0 || m_pModel->FindSocket(pName))
  5263.             {
  5264.                 DoMessageBox(IDS_DUPLICATESOCKETNAME, MB_OK);
  5265.             }
  5266.             else
  5267.             {
  5268.                 pSocket->SetName(pName);
  5269.                 FillSocketList(TRUE);
  5270.             }
  5271.         }
  5272.     }
  5273. }
  5274.  
  5275.  
  5276. void CModelEditDlg::OnLButtonDown(UINT nFlags, CPoint point) 
  5277. {
  5278.     DWORD i;
  5279.  
  5280.     CDialog::OnLButtonDown(nFlags, point);
  5281.  
  5282.     // See if it's in a tracker.
  5283.     for (i=0; i < m_Trackers; i++)
  5284.     {
  5285.         if (m_Trackers[i]->m_Rect.PtInRect(point))
  5286.         {
  5287.             StartTracker(i, point);
  5288.         }
  5289.     }
  5290. }
  5291.  
  5292.  
  5293. void CModelEditDlg::OnMouseMove(UINT nFlags, CPoint point) 
  5294. {
  5295.     RectTracker *pTracker;
  5296.     CPoint delta, center;
  5297.     float rotAngle;
  5298.     ModelSocket *pSocket;
  5299.     LTMatrix mNewTransform, mOldTransform,mOffset, mFinal, mSocket, mBasis;
  5300.     LTVector vecs[3], vOffset, vTrans;
  5301.     char buf[512];
  5302.     int i;
  5303.     DWORD iNode;
  5304.     
  5305.     AnimInfo *pAnimInfo;
  5306.     ChildInfo *pChildInfo;
  5307.     CIRelation *pRelation;
  5308.     ModelNode *pNode, *pParent;
  5309.     TransformMaker tMaker;
  5310.     BOOL bGlobal;
  5311.  
  5312.     
  5313.     if (!m_pModel || !m_bTracking || m_iCurTracker >= m_Trackers.GetSize())
  5314.         return;
  5315.  
  5316.     pTracker = m_Trackers[m_iCurTracker];
  5317.     bGlobal = !!m_GlobalSpace.GetCheck();
  5318.  
  5319.     vecs[0].Init(1.0f, 0.0f, 0.0f);
  5320.     vecs[1].Init(0.0f, 1.0f, 0.0f);
  5321.     vecs[2].Init(0.0f, 0.0f, 1.0f);
  5322.  
  5323.     delta = point - m_LastCursorPos;
  5324.     if (delta.x == 0)
  5325.         return;
  5326.  
  5327.     m_TotalDelta += delta.x;
  5328.  
  5329.     // Generate some feedback to window's text field
  5330.     switch( pTracker->m_Type )
  5331.     {
  5332.     case RT_ROTATION:
  5333.         // rotate x degrees for every pixel
  5334.         rotAngle = GetRotAngle( delta.x );
  5335.         sprintf( buf, "Rotation: %.1f", (GetRotAngle(m_TotalDelta) * 360.0f) / MATH_CIRCLE );
  5336.         break;
  5337.     case RT_POSITION:
  5338.         sprintf( buf, "Translation: %.1f", GetPosAmount(m_TotalDelta) );
  5339.         break;
  5340.     case RT_SCALE:
  5341.         if( IsButtonSelected(IDC_SOCKET_EDIT) && GetSelectedSocket() )
  5342.             sprintf( buf, "Scale: %.2f", GetScaleAmount(m_TotalDelta) );
  5343.         else
  5344.             sprintf( buf, "Scale not supported on transforms." );
  5345.         break;
  5346.     }
  5347.  
  5348.     // Do socket/relation specific stuff.
  5349.     // note: this includes scale, but we treat scale separately.
  5350.     if (IsButtonSelected(IDC_SOCKET_EDIT) && (pSocket = GetSelectedSocket()))
  5351.     {
  5352.         pSocket->ConvertToMatrixNoScale(mSocket);
  5353.  
  5354.         // Setup the transforms..
  5355.         if(!m_RenderWnd.SetupTransformMaker(&tMaker))
  5356.             return;
  5357.  
  5358.         if (!tMaker.SetupTransforms())
  5359.             return;
  5360.  
  5361.         mOldTransform = m_pModel->m_Transforms[pSocket->m_iNode];
  5362.         mNewTransform = mOldTransform * mSocket;
  5363.             
  5364.         mOffset.Identity();
  5365.  
  5366.         switch( pTracker->m_Type )
  5367.         {
  5368.         case RT_ROTATION:
  5369.             Mat_SetupRot( &mOffset, &vecs[pTracker->m_Axis], rotAngle );
  5370.             break;
  5371.         case RT_POSITION:
  5372.             vOffset.Init();
  5373.             vOffset[pTracker->m_Axis] = GetPosAmount( delta.x );
  5374.             mOffset.SetTranslation( vOffset );
  5375.             break;
  5376.         }
  5377.  
  5378.         // Put the offset in local space.
  5379.         if (bGlobal)
  5380.         {
  5381.             mBasis.Identity();
  5382.             mNewTransform.GetTranslation(vTrans);
  5383.             mBasis.SetTranslation(vTrans);
  5384.         }
  5385.         else
  5386.         {
  5387.             mBasis = mNewTransform;
  5388.         }
  5389.  
  5390.         // Put the offset into the right basis.
  5391.         mOffset = mBasis * mOffset * ~mBasis;
  5392.  
  5393.         mFinal = ~mOldTransform * (mOffset * mNewTransform);
  5394.  
  5395.         pSocket->ConvertFromMatrixNoScale(mFinal);
  5396.  
  5397.         // scale is a special case: we don't want to include it in the other transforms...
  5398.         if( pTracker->m_Type == RT_SCALE )
  5399.         {
  5400.             pSocket->m_Scale[pTracker->m_Axis] = GetScaleAmount(m_TotalDelta );
  5401.         }
  5402.     }
  5403.     else if( pTracker->m_Type != RT_SCALE )// else change the transformation (if it isn't a scale)
  5404.     {
  5405.         // Find the first selected animation
  5406.         pAnimInfo = NULL;
  5407.         for (i=0; (i < m_AnimList.GetItemCount()) && (!pAnimInfo); i++)
  5408.         {
  5409.             if (m_AnimList.GetItemState(i, LVIS_SELECTED) != 0)
  5410.                 pAnimInfo = m_pModel->GetAnimInfo(i);
  5411.         }
  5412.         if (pAnimInfo)
  5413.         {
  5414.             pChildInfo = pAnimInfo->m_pChildInfo;
  5415.  
  5416.             // Change the weights on the selected nodes.
  5417.             for (i=0; i < m_NodeList.GetItemCount(); i++)
  5418.             {
  5419.                 // Skip over items that aren't selected
  5420.                 if (!m_NodeList.GetItemState(i, LVIS_SELECTED))
  5421.                     continue;
  5422.  
  5423.                 iNode = (DWORD)i;
  5424.                 if (iNode >= pChildInfo->m_Relation.GetSize())
  5425.                     continue;
  5426.  
  5427.                 pNode = m_pModel->GetNode(iNode);
  5428.                 pParent = m_pModel->FindParent(pNode, m_pModel->GetRootNode());
  5429.                 if (!pParent)
  5430.                     continue;
  5431.  
  5432.                 pRelation = &pChildInfo->m_Relation[iNode];
  5433.                 
  5434.                 // Get the old and new (using the relation) node transforms (so we can setup the relation).
  5435.                 if(!m_RenderWnd.SetupTransformMaker(&tMaker))
  5436.                     return;
  5437.  
  5438.                 if (!tMaker.SetupTransforms())
  5439.                     return;
  5440.  
  5441.                 mNewTransform = m_pModel->m_Transforms[iNode];
  5442.                 
  5443.                 pRelation->m_Pos.Init();
  5444.                 pRelation->m_Rot.Init();
  5445.                 if (!tMaker.SetupTransforms())
  5446.                     return;
  5447.  
  5448.                 mOldTransform = m_pModel->m_Transforms[iNode];
  5449.  
  5450.                 
  5451.                 // Make an offset.
  5452.                 mOffset.Identity();
  5453.                 if (pTracker->m_Type == RT_ROTATION)
  5454.                 {
  5455.                     Mat_SetupRot(&mOffset, &vecs[pTracker->m_Axis], rotAngle);
  5456.                 }
  5457.                 else
  5458.                 {
  5459.                     vOffset.Init();
  5460.                     vOffset[pTracker->m_Axis] = GetPosAmount(delta.x);
  5461.                     mOffset.SetTranslation(vOffset);
  5462.                 }
  5463.  
  5464.                 
  5465.                 // Put the offset into the node's local space.
  5466.                 if (bGlobal)
  5467.                 {
  5468.                     mBasis.Identity();
  5469.                     mNewTransform.GetTranslation(vTrans);
  5470.                     mBasis.SetTranslation(vTrans);
  5471.                 }
  5472.                 else
  5473.                 {
  5474.                     mBasis = mNewTransform;
  5475.                 }
  5476.  
  5477.                 // Figure out the relation (~old * offset * new... ie: (offset*new) - old)
  5478.                 mOffset = mBasis * (mOffset * ~mBasis);
  5479.                 mFinal = ~mOldTransform * (mOffset * mNewTransform);
  5480.                 pRelation->ConvertFromMatrix(mFinal);
  5481.             }
  5482.         }
  5483.     }
  5484.  
  5485.     SetWindowText(buf);
  5486.  
  5487.     // Center the cursor.
  5488.     center = m_TrackerCenterPt;
  5489.     m_LastCursorPos = center;
  5490.     ClientToScreen(¢er);
  5491.     SetCursorPos(center.x, center.y);
  5492.  
  5493.     m_RenderWnd.Draw();
  5494.     
  5495.     CDialog::OnMouseMove(nFlags, point);
  5496. }
  5497.  
  5498.  
  5499. void CModelEditDlg::OnLButtonUp(UINT nFlags, CPoint point) 
  5500. {
  5501.     HandleButtonUp(0);
  5502.     CDialog::OnLButtonUp(nFlags, point);
  5503. }
  5504.  
  5505.  
  5506.  
  5507. LRESULT CModelEditDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) 
  5508. {
  5509.     if (message == WM_MBUTTONUP)
  5510.     {
  5511.         HandleButtonUp(1);
  5512.     }
  5513.     else if (message == WM_RBUTTONUP)
  5514.     {
  5515.         HandleButtonUp(2);
  5516.     }
  5517.     
  5518.     return CDialog::WindowProc(message, wParam, lParam);
  5519. }
  5520.  
  5521.  
  5522. void CModelEditDlg::OnMood()
  5523. {
  5524.  
  5525. }
  5526.  
  5527.  
  5528. void CModelEditDlg::OnInternalRadius()
  5529. {
  5530.     CStringDlg dlg;
  5531.     char tempBuf[64];
  5532.     IdleChanger idle(&m_cWinIdle, IDLE_DIALOG_DELAY);      
  5533.  
  5534.     if (!m_pModel)
  5535.         return;
  5536.  
  5537.     dlg.m_bAllowLetters = FALSE;
  5538.     dlg.m_bAllowNumbers = TRUE;
  5539.     dlg.m_bAllowOthers = FALSE;
  5540.     
  5541.     sprintf(tempBuf, "%.3f", m_pModel->m_GlobalRadius);
  5542.     dlg.m_EnteredText = tempBuf;
  5543.  
  5544.     if (dlg.DoModal(IDS_MODELEDIT_CAPTION, IDS_ENTER_GLOBAL_RADIUS) == IDOK)
  5545.     {
  5546.         m_pModel->m_GlobalRadius = (float)atof(dlg.m_EnteredText);
  5547.         SetChangesMade();
  5548.     }
  5549. }
  5550.  
  5551.  
  5552. void CModelEditDlg::OnCalcInternalRadius()
  5553. {
  5554.     if( !m_pModel )
  5555.     {
  5556.         MessageBox( "No model loaded.", "Error", MB_OK | MB_ICONERROR );
  5557.         return;
  5558.     }
  5559.  
  5560.     if( MessageBox( "This operation can take a while.  Do you wish to proceed?", "Do you really want to do this?", MB_OKCANCEL ) != IDOK )
  5561.         return;
  5562.  
  5563.     HCURSOR oldCursor = SetCursor( LoadCursor( NULL, IDC_WAIT ) );
  5564.  
  5565.     // calculate the estimated internal radius
  5566.  
  5567.     // turn on render distance checking
  5568.     // t.f important
  5569.     m_RenderWnd.m_bCalcRadius = true;
  5570.  
  5571.     // get our main anim info
  5572.     MEAnimInfo* pAnimInfo = GetAnimInfo( 0 );
  5573.  
  5574.     // save our current animation state
  5575.     AnimTimeRef oldTracker = pAnimInfo->m_Tracker.m_TimeRef;
  5576.     ModelAnim* pOldAnim = pAnimInfo->CurAnim();
  5577.  
  5578.     // initialize the maximums
  5579.     float fNewRadius = 0.0f;
  5580.     char* pAnimName = NULL;
  5581.  
  5582.     // for each animation
  5583.     for( uint32 nAnimLoop = 0; nAnimLoop < m_pModel->NumAnims(); ++nAnimLoop )
  5584.     {
  5585.         // get the animation
  5586.         ModelAnim* pAnim = m_pModel->GetAnim( nAnimLoop );
  5587.         if( !pAnim )
  5588.             continue;
  5589.         // switch to that animation
  5590.         pAnimInfo->m_Wnd.SetAnim( pAnim );
  5591.         trk_Init( &pAnimInfo->m_Tracker, m_pModel, nAnimLoop );
  5592.  
  5593.         // resert the maximum radius
  5594.         float fAnimRadius = 0.0f;
  5595.  
  5596.         // for each keyframe
  5597.         for( uint32 nKeyframeLoop = 0; nKeyframeLoop < pAnim->NumKeyFrames(); ++nKeyframeLoop )
  5598.         {
  5599.             // move to this keyframe
  5600.             SetCurrentPosition( (DWORD)0, nKeyframeLoop, nKeyframeLoop, 0.0f );
  5601.             // only draw the first frame
  5602.             // t.f important
  5603.              m_RenderWnd.m_bCalcAndDraw = (nKeyframeLoop == 0);
  5604.             // draw the model
  5605.             m_RenderWnd.Draw();
  5606.             // get the maximum of the animation and this frame's radii
  5607.             // t.f important            
  5608.             fAnimRadius = LTMAX( fAnimRadius, m_RenderWnd.m_fCurRadius );
  5609.         }
  5610.  
  5611.         // new maximum distance
  5612.         if( fAnimRadius > fNewRadius )
  5613.         {
  5614.             // save distance and animation name
  5615.             fNewRadius = fAnimRadius;
  5616.             pAnimName = m_pModel->GetAnim( nAnimLoop )->GetName();
  5617.         }
  5618.     }
  5619.  
  5620.     // turn off render distance checking
  5621.     // t.f important
  5622.     m_RenderWnd.m_bCalcRadius = false;
  5623.  
  5624.     // add a fudge factor to the distance
  5625.     fNewRadius *= 1.01f;
  5626.  
  5627.     // restore the old animation state
  5628.     pAnimInfo->m_Wnd.SetAnim( pOldAnim );
  5629.     pAnimInfo->m_Tracker.m_TimeRef = oldTracker;
  5630.  
  5631.     // restore non-wait cursor
  5632.     SetCursor( oldCursor );
  5633.  
  5634.     // display distance and largest animation and ask user to confirm
  5635.     char results[2048];
  5636.     sprintf( results, "Results:\n"
  5637.                       "\tOld Dimensions: %f\n"
  5638.                       "\tNew Dimensions: %f\n"
  5639.                       "\tBiggest Animation: %s\n"
  5640.                       "\nUse these results?", m_pModel->m_GlobalRadius, fNewRadius, pAnimName );
  5641.     if( MessageBox( results, "Is that better?", MB_YESNO ) != IDYES )
  5642.         return;
  5643.  
  5644.     // save the new distance
  5645.     m_pModel->m_GlobalRadius = fNewRadius;
  5646.  
  5647.     SetChangesMade();
  5648. }
  5649.  
  5650. void CModelEditDlg::OnReCalcOBBExtent()
  5651. {
  5652.     if(!m_pModel)
  5653.         return ;
  5654.  
  5655.     
  5656.     void model_CreateDefaultOBB(Model*);
  5657.     model_CreateDefaultOBB(    m_pModel );
  5658.  
  5659. }
  5660.  
  5661.  
  5662. void CModelEditDlg::OnEditWeights()
  5663. {
  5664.     WeightEditDlg dlg;
  5665.     IdleChanger idle(&m_cWinIdle, IDLE_DIALOG_DELAY);      
  5666.     
  5667.     if (!m_pModel)
  5668.         return;
  5669.  
  5670.     dlg.m_pDlg = this;
  5671.     dlg.m_pModel = m_pModel;
  5672.     dlg.DoModal();
  5673.     if (dlg.m_bChangesMade)
  5674.         SetChangesMade();
  5675. }
  5676.  
  5677.  
  5678. void CModelEditDlg::SetCurrentLOD(float fLOD)
  5679. {
  5680.     m_CurrentLODDist = fLOD;
  5681.     m_RenderWnd.SetLOD(fLOD);
  5682. }
  5683.  
  5684. //this will create a NULL piece LOD at the specified distance from the camera
  5685. void CModelEditDlg::OnCreateNullLOD()
  5686. {
  5687.     // grab the selected piece LODs
  5688.     vector<ModelPiece*> selection;
  5689.     int numSelected = GetSelectedPieces( &m_PieceList, m_pModel, selection );
  5690.  
  5691.     if( !numSelected )
  5692.         return;
  5693.  
  5694.     CStringDlg Dlg;
  5695.     Dlg.m_bAllowNumbers = TRUE;
  5696.  
  5697.     if(Dlg.DoModal(IDS_ENTER_NULL_LOD_DISTANCE_CAPTION, IDS_ENTER_NULL_LOD_DISTANCE) != IDOK)
  5698.     {
  5699.         return;
  5700.     }
  5701.  
  5702.     float fDist = (float)atof(Dlg.m_EnteredText);
  5703.  
  5704.     //alright, time to create the NULL lod at the specified distance
  5705.     for(uint32 nCurrSel = 0; nCurrSel < selection.size(); nCurrSel++)
  5706.     {
  5707.     
  5708.         //add it to the piece
  5709.         ModelPiece* pPiece = selection[nCurrSel];
  5710.  
  5711.         //sanity check
  5712.         assert(pPiece);
  5713.  
  5714.         //add this LOD to the list
  5715.         pPiece->AddNullLOD(fDist);
  5716.     }
  5717.     
  5718.     // reload the piece tree
  5719.     FillPieceList( &m_PieceList, m_pModel );
  5720.  
  5721.     // adjust the LOD slider
  5722.     float maxLODDist = GetModelMaxLODDist( m_pModel );
  5723.     InitTheScrollBar( maxLODDist );
  5724.     SetCurrentLOD( 0.0f );
  5725.  
  5726.     //flag changes for save
  5727.     SetChangesMade();
  5728. }
  5729.  
  5730.  
  5731. void CModelEditDlg::OnPieceInfo()
  5732. {
  5733.     int i;
  5734.     IdleChanger idle(&m_cWinIdle, IDLE_DIALOG_DELAY);      
  5735.  
  5736.     // grab the selected piece LODs
  5737.     vector<PieceLODInfo> selection;
  5738.  
  5739.     int numSelected = GetSelectedPieceLODs( &m_PieceList, m_pModel, selection );
  5740.  
  5741.     if( !numSelected )
  5742.         return;
  5743.  
  5744.     // launch the piece info dialog
  5745.     CPieceMaterialDlg dlg( selection );
  5746.     if( dlg.DoModal() == IDOK )
  5747.     {
  5748.         // check if any lod dists changed
  5749.         if( dlg.m_LODDistChanged )
  5750.         {
  5751.             // sort the piece lods
  5752.             for( i = 0; i < m_pModel->NumPieces(); i++ )
  5753.             {
  5754.                 // get the current piece
  5755.                 ModelPiece* curPiece = m_pModel->GetPiece( i );
  5756.                 if( !curPiece )
  5757.                 {
  5758.                     ASSERT(0);
  5759.                     continue;
  5760.                 }
  5761.                 curPiece->SortLODs();
  5762.             }
  5763.  
  5764.             // reload the piece tree
  5765.             FillPieceList( &m_PieceList, m_pModel );
  5766.  
  5767.             // adjust the LOD slider
  5768.             float maxLODDist = GetModelMaxLODDist( m_pModel );
  5769.             InitTheScrollBar( maxLODDist );
  5770.             SetCurrentLOD( 0.0f );
  5771.         }
  5772.  
  5773.         SetChangesMade();
  5774.     }
  5775. }
  5776.  
  5777.  
  5778. void CModelEditDlg::OnPieceSelectNone( void )
  5779. {
  5780.     m_PieceList.ClearSelection();
  5781. }
  5782.  
  5783.  
  5784. void CModelEditDlg::OnPieceExpandAll( void )
  5785. {
  5786.     m_PieceList.ExpandAll();
  5787. }
  5788.  
  5789.  
  5790. void CModelEditDlg::OnPieceCollapseAll( void )
  5791. {
  5792.     m_PieceList.CollapseAll();
  5793.     m_PieceList.ClearSelection();
  5794. }
  5795.  
  5796.  
  5797. void CModelEditDlg::OnEndlabeleditNodeList(NMHDR* pNMHDR, LRESULT* pResult) 
  5798. {
  5799.     LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
  5800.  
  5801.     // Update the node's name
  5802.     if ((pDispInfo->item.mask & LVIF_TEXT) != 0)
  5803.         m_pModel->GetNode(pDispInfo->item.iItem)->SetName(pDispInfo->item.pszText);
  5804.     
  5805.     SetChangesMade();
  5806.  
  5807.     *pResult = TRUE;
  5808. }
  5809.  
  5810. void CModelEditDlg::OnItemChangedNodeList(NMHDR* pNMHDR, LRESULT* pResult) 
  5811. {
  5812.     NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
  5813.     ModelNode *pNode;
  5814.     unsigned char newFlags;
  5815.  
  5816.     // Refresh the selection state array entry
  5817.     // t.f important    
  5818.     
  5819.     if (m_pModel && m_RenderWnd.GetSelectedNodesSize() ) //m_SelectedNodes)
  5820.     {
  5821.         DWORD iIndex = (DWORD)pNMListView->iItem;
  5822.  
  5823.         if (m_NodeList.GetItemState((int)iIndex, LVIS_SELECTED))
  5824.         {
  5825.             int bSelect = m_NodeList.GetCheck((int)iIndex) ? true : false;
  5826.  
  5827.             m_RenderWnd.m_SelectedNodes[iIndex] = TRUE;
  5828.  
  5829.             for (int nCount = 0; nCount < m_NodeList.GetItemCount(); nCount ++)
  5830.             {
  5831.                 if (m_NodeList.GetItemState((int)nCount, LVIS_SELECTED))
  5832.                 {
  5833.                     m_NodeList.SetCheck(nCount, bSelect);
  5834.  
  5835.                     pNode = m_pModel->GetNode(iIndex);
  5836.  
  5837.                     if (g_bUpdateNodeFlags)
  5838.                     {
  5839.                         newFlags = pNode->m_Flags;
  5840.  
  5841.                         if (m_NodeList.GetCheck(nCount))
  5842.                             newFlags |= MNODE_ROTATIONONLY;
  5843.                         else
  5844.                             newFlags &= ~MNODE_ROTATIONONLY;
  5845.  
  5846.                         if (newFlags != pNode->m_Flags)
  5847.                         {
  5848.                             pNode->m_Flags = newFlags;
  5849.                         }            
  5850.                     }
  5851.  
  5852.                     SetChangesMade();
  5853.                 }
  5854.             }
  5855.         }
  5856.         else
  5857.         {
  5858.  
  5859.             DWORD iIndex = (DWORD)pNMListView->iItem;
  5860.             if ((iIndex < (DWORD)m_NodeList.GetItemCount()) && (iIndex < m_RenderWnd.GetSelectedNodesSize()))
  5861.                 m_RenderWnd.m_SelectedNodes[iIndex] = m_NodeList.GetItemState((int)iIndex, LVIS_SELECTED) != 0;
  5862.  
  5863.             pNode = m_pModel->GetNode(iIndex);
  5864.  
  5865.             if (g_bUpdateNodeFlags)
  5866.             {
  5867.                 newFlags = pNode->m_Flags;
  5868.  
  5869.                 if (m_NodeList.GetCheck(pNMListView->iItem))
  5870.                     newFlags |= MNODE_ROTATIONONLY;
  5871.                 else
  5872.                     newFlags &= ~MNODE_ROTATIONONLY;
  5873.  
  5874.                 if (newFlags != pNode->m_Flags)
  5875.                 {
  5876.                     pNode->m_Flags = newFlags;
  5877.                 
  5878.                 }
  5879.             }
  5880.              SetChangesMade();
  5881.         }
  5882.     }
  5883.     
  5884.     *pResult = 0;
  5885. }
  5886.  
  5887. void CModelEditDlg::OnDestroy() 
  5888. {
  5889.     // Stop the idling thread
  5890.     m_cWinIdle.EndIdle();
  5891.  
  5892.     CDialog::OnDestroy();
  5893. }
  5894.  
  5895. // one of the tree controls has had its selection changed
  5896. LRESULT CModelEditDlg::OnTreeSelChanged( WPARAM wParam, LPARAM lParam )
  5897. {
  5898.     CLTWinTreeMgr* tree = (CLTWinTreeMgr*)wParam;
  5899.  
  5900.     switch( tree->GetDlgCtrlID() )
  5901.     {
  5902.     case IDC_PIECES:        // handle the piece tree control
  5903.         PieceSelChanged( tree );
  5904.         break;
  5905.     default:
  5906.         ASSERT(0);            // unhandled tree control
  5907.         break;
  5908.     }
  5909.  
  5910.     return 0;
  5911. }
  5912.  
  5913. // a new piece has been selected
  5914. void CModelEditDlg::PieceSelChanged( CLTWinTreeMgr* tree )
  5915. {
  5916.     // t.f important    
  5917.     
  5918.     if( !m_pModel || !m_RenderWnd.GetSelectedPiecesSize() )
  5919.         return;
  5920.  
  5921.     PieceListItem* item;
  5922.  
  5923.     // get the root iterator
  5924.     CLTWinTreeItemIter* iter = tree->CreateIter();
  5925.     if( !iter )
  5926.         return;
  5927.  
  5928.     // visit each piece
  5929.     for( ; iter->IsMore(); iter->Next() )
  5930.     {
  5931.         item = (PieceListItem*)iter->Current();
  5932.         int curPiece = item->m_PieceNum;
  5933.  
  5934.         bool selected = item->IsSelected() != 0;
  5935.  
  5936.         // check the children if the parent isn't selected
  5937.         if( !selected )
  5938.         {
  5939.             CLTWinTreeItemIter* childIter = item->CreateChildIter();
  5940.  
  5941.             for( ; !selected && childIter->IsMore(); childIter->Next() )
  5942.             {
  5943.                 item = (PieceListItem*)childIter->Current();
  5944.                 selected = item->IsSelected() != 0;
  5945.             }
  5946.  
  5947.             delete childIter;
  5948.         }
  5949.  
  5950.         if( curPiece < m_RenderWnd.GetSelectedPiecesSize() )
  5951.         {
  5952.             m_RenderWnd.m_SelectedPieces[curPiece] = selected;
  5953.         }
  5954.         else
  5955.             ASSERT(0);
  5956.     }
  5957.  
  5958.     delete iter;
  5959.     
  5960. }
  5961.  
  5962. // one of the tree controls has had its selection edited
  5963. LRESULT CModelEditDlg::OnTreeEditText( WPARAM wParam, LPARAM lParam )
  5964. {
  5965.     CLTWinTreeMgr* tree = (CLTWinTreeMgr*)wParam;
  5966.     PieceListItem* item = (PieceListItem*)lParam;
  5967.  
  5968.     switch( tree->GetDlgCtrlID() )
  5969.     {
  5970.     case IDC_PIECES:        // handle the piece tree control
  5971.         PieceEditText( tree, item );
  5972.         break;
  5973.     default:
  5974.         ASSERT(0);            // unhandled tree control
  5975.         break;
  5976.     }
  5977.  
  5978.     return 0;
  5979. }
  5980.  
  5981. // a piece has had its name changed
  5982. void CModelEditDlg::PieceEditText( CLTWinTreeMgr* tree, PieceListItem* item )
  5983. {
  5984.     m_pModel->GetPiece( item->m_PieceNum )->SetName( item->GetText() );
  5985.  
  5986.     SetChangesMade();
  5987. }
  5988.  
  5989.  
  5990. // retrieve a list of the selected pieces (returns number of selected pieces)
  5991. // this does not iterate through children, the piece itself must be explicitly selected in order to be returned
  5992. int CModelEditDlg::GetSelectedPieces( CLTWinTreeMgr* tree, Model* model, vector<ModelPiece*>& selection )
  5993. {
  5994.     int numSelected = 0;
  5995.     selection.clear();
  5996.  
  5997.     if( !model )
  5998.         return numSelected;
  5999.  
  6000.     // get the root iterator
  6001.     CLTWinTreeItemIter* iter = tree->CreateIter();
  6002.     if( !iter )
  6003.         return numSelected;
  6004.  
  6005.     // visit each piece
  6006.     for( ; iter->IsMore(); iter->Next() )
  6007.     {
  6008.         PieceListItem* item = (PieceListItem*)iter->Current();
  6009.  
  6010.         if( item->IsSelected() )
  6011.         {
  6012.             ModelPiece* curPiece = model->GetPiece( item->m_PieceNum );
  6013.             ASSERT( curPiece );
  6014.             selection.push_back( curPiece );
  6015.             numSelected++;
  6016.         }
  6017.     }
  6018.  
  6019.     delete iter;
  6020.  
  6021.     return numSelected;
  6022. }
  6023.  
  6024.  
  6025. // retrieve a list of the selected piece LODs (returns number of selected LODs)
  6026. // if firstIfParentOnly is true, then only the 0th lod will be returned if only the parent piece is selected
  6027. // otherwise all lods will be returned for the selected piece
  6028. int CModelEditDlg::GetSelectedPieceLODs( CLTWinTreeMgr* tree, Model* model, vector<PieceLODInfo>& selection, bool firstIfParentOnly )
  6029. {
  6030.     PieceLODInfo pieceLOD;
  6031.     int numSelected = 0;
  6032.     selection.clear();
  6033.  
  6034.     if( !model )
  6035.         return numSelected;
  6036.  
  6037.     // get the root iterator
  6038.     CLTWinTreeItemIter* iter = tree->CreateIter();
  6039.     if( !iter )
  6040.         return numSelected;
  6041.  
  6042.     // visit each piece
  6043.     for( ; iter->IsMore(); iter->Next() )
  6044.     {
  6045.         PieceListItem* item = (PieceListItem*)iter->Current();
  6046.         int curPiece = item->m_PieceNum;
  6047.  
  6048.         // check if any children are selected first
  6049.         bool childSelected = false;
  6050.  
  6051.         CLTWinTreeItemIter* childIter = item->CreateChildIter();
  6052.  
  6053.         for( ; childIter->IsMore(); childIter->Next() )
  6054.         {
  6055.             PieceListItem* childItem = (PieceListItem*)childIter->Current();
  6056.             if( childItem->IsSelected() )
  6057.             {
  6058.                 // found a selected pieceLOD, add it to the selection list
  6059.                 childSelected = true;
  6060.                 pieceLOD.m_ModelPiece = model->GetPiece( curPiece );
  6061.                 pieceLOD.m_LODNum = childItem->m_LOD;
  6062.                 pieceLOD.m_PieceLOD = pieceLOD.m_ModelPiece->GetLOD( (uint32)pieceLOD.m_LODNum );
  6063.                 ASSERT( pieceLOD.m_PieceLOD );
  6064.                 selection.push_back( pieceLOD );
  6065.                 numSelected++;
  6066.             }
  6067.         }
  6068.  
  6069.         // no children are selected, check if the parent is selected
  6070.         if( !childSelected )
  6071.         {
  6072.             if( item->IsSelected() )
  6073.             {
  6074.                 ModelPiece* mainPiece = model->GetPiece( curPiece );
  6075.  
  6076.                 // parent is selected
  6077.                 if( firstIfParentOnly )
  6078.                 {
  6079.                     // add only the first child LOD to selection
  6080.                     pieceLOD.m_ModelPiece = mainPiece;
  6081.                     pieceLOD.m_LODNum = 0;
  6082.                     pieceLOD.m_PieceLOD = mainPiece->GetLOD( (unsigned)0 );
  6083.                     ASSERT( pieceLOD.m_PieceLOD );
  6084.                     selection.push_back( pieceLOD );
  6085.                     numSelected++;
  6086.                 }
  6087.                 else
  6088.                 {
  6089.                     // add all child LODs to selection
  6090.                     for( uint32 i = 0; i < mainPiece->NumLODs(); i++ )
  6091.                     {
  6092.                         pieceLOD.m_ModelPiece = mainPiece;
  6093.                         pieceLOD.m_LODNum = i;
  6094.                         pieceLOD.m_PieceLOD = mainPiece->GetLOD( i );
  6095.                         ASSERT( pieceLOD.m_PieceLOD );
  6096.                         selection.push_back( pieceLOD );
  6097.                         numSelected++;
  6098.                     }
  6099.                 }
  6100.             }
  6101.         }
  6102.  
  6103.         delete childIter;
  6104.     }
  6105.  
  6106.     delete iter;
  6107.  
  6108.     return numSelected;
  6109. }
  6110.  
  6111. BOOL CModelEditDlg::UpdateSelectedAnimList()
  6112. {
  6113.     DWORD i, index;
  6114.  
  6115.     
  6116.     // Get rid of them all if the model isn't there.
  6117.     if(!m_pModel)
  6118.     {
  6119.         m_SelectedAnims.Term();
  6120.         return TRUE;
  6121.     }
  6122.  
  6123.     // Get rid of invalid ones.
  6124.     for(i=0; i < m_SelectedAnims; i++)
  6125.     {
  6126.         if(m_SelectedAnims[i] >= m_pModel->NumAnims())
  6127.         {
  6128.             m_SelectedAnims.Remove(i);
  6129.             --i;
  6130.         }
  6131.     }
  6132.  
  6133.     // Add new selections and remove old ones.
  6134.     for(i=0; i < (DWORD)m_AnimList.GetItemCount(); i++)
  6135.     {
  6136.         if(m_AnimList.GetItemState((DWORD)i, LVIS_SELECTED) == 0)
  6137.         {
  6138.             index = m_SelectedAnims.FindElement(i);
  6139.             if(index != BAD_INDEX)
  6140.             {
  6141.                 m_SelectedAnims.Remove(index);
  6142.             }
  6143.         }
  6144.         else
  6145.         {
  6146.             if(m_SelectedAnims.FindElement(i) == BAD_INDEX)
  6147.             {
  6148.                 m_SelectedAnims.Append(i);
  6149.             }
  6150.         }
  6151.     }
  6152.  
  6153.     return TRUE;
  6154. }
  6155.  
  6156. void CModelEditDlg::OnSelChangeAnimList()
  6157. {
  6158.     DWORD i;
  6159.     MEAnimInfo *pInfo;
  6160.     
  6161.     if(!m_pModel)
  6162.         return;
  6163.  
  6164.  
  6165.     UpdateSelectedAnimList();
  6166.  
  6167.     
  6168.     // Activate/deactivate the animations.
  6169.     for(i=0; i < NUM_ANIM_INFOS; i++)
  6170.     {
  6171.         pInfo = &m_AnimInfos[i];
  6172.  
  6173.         if(i >= m_SelectedAnims.GetSize())
  6174.         {
  6175.             pInfo->Reset(NULL);
  6176.         }
  6177.     }
  6178.  
  6179.     
  6180.     // Activate any new ones and change the animation for any existing ones.
  6181.     for(i=0; i < m_SelectedAnims.GetSize(); i++)
  6182.     {
  6183.         if(i >= NUM_ANIM_INFOS)
  6184.             break;
  6185.     
  6186.         pInfo = &m_AnimInfos[i];
  6187.         if(!pInfo->m_Wnd.IsActive())
  6188.         {
  6189.             pInfo->m_Wnd.SetActive(TRUE);
  6190.             pInfo->m_Wnd.SetAnim(m_pModel->GetAnim(m_SelectedAnims[i]));
  6191.             trk_Init(&pInfo->m_Tracker, m_pModel, m_SelectedAnims[i]);
  6192.         }
  6193.         else if(m_SelectedAnims[i] != pInfo->m_Tracker.m_TimeRef.m_Cur.m_iAnim)
  6194.         {
  6195.             pInfo->m_Wnd.SetAnim(m_pModel->GetAnim(m_SelectedAnims[i]));
  6196.             trk_SetCurAnim(&pInfo->m_Tracker, m_SelectedAnims[i], pInfo->IsAnimPlaying() ? true : false);
  6197.  
  6198.             // Update the frame string and time....
  6199.  
  6200.             UpdateEditFrameString();
  6201.             UpdateEditFrameTime();
  6202.         }
  6203.  
  6204.         ModelAnim *pAnim = pInfo->CurAnim();
  6205.  
  6206.         pInfo->m_Tracker.m_TimeRef.m_iWeightSet = pAnim ? (pAnim->m_ModelEditWeightSet) : 0;
  6207.     }
  6208.  
  6209.     if(m_SelectedAnims.GetSize() == 0)
  6210.     {
  6211.         UpdateEditFrameString();
  6212.         UpdateEditFrameTime();
  6213.     }
  6214.  
  6215.  
  6216.  
  6217.     // Set button labels.
  6218.     for(i=0; i < NUM_ANIM_INFOS; i++)
  6219.     {
  6220.         pInfo = &m_AnimInfos[i];
  6221.         
  6222.         ModelAnim *pAnim = pInfo->CurAnim();
  6223.  
  6224.         if (pAnim)
  6225.         {
  6226.             if(pInfo->m_Wnd.IsActive())
  6227.             {
  6228.                 ::EnableWindow(::GetDlgItem(m_hWnd, pInfo->m_AnimButtonID), TRUE);
  6229.                 SetDlgItemText(pInfo->m_AnimButtonID, pAnim->GetName());
  6230.             }
  6231.             else
  6232.             {
  6233.                 ::EnableWindow(::GetDlgItem(m_hWnd, pInfo->m_AnimButtonID), FALSE);
  6234.                 SetDlgItemText(pInfo->m_AnimButtonID, "NONE");
  6235.             }
  6236.         }
  6237.     }
  6238.  
  6239.     UpdateEditFrameStringEnabled();
  6240.     UpdateEditFrameTimeEnabled();
  6241. }
  6242.  
  6243.  
  6244. void CModelEditDlg::OnBeginLabelEditAnimList(NMHDR* pNMHDR, LRESULT* pResult) 
  6245. {
  6246.     LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
  6247.  
  6248.     *pResult = ((m_pModel->GetAnimInfo(pDispInfo->item.iItem))->GetAnimOwner() != m_pModel);
  6249. }
  6250.  
  6251. void CModelEditDlg::OnEndLabelEditAnimList(NMHDR* pNMHDR, LRESULT* pResult) 
  6252. {
  6253.     LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
  6254.  
  6255.     if ((pDispInfo->item.mask & LVIF_TEXT) != 0)
  6256.         (m_pModel->GetAnim(pDispInfo->item.iItem))->SetName(pDispInfo->item.pszText);
  6257.     
  6258.     SetChangesMade();
  6259.  
  6260.     *pResult = TRUE;
  6261. }
  6262.  
  6263.  
  6264. void CModelEditDlg::OnItemChangingAnimList(NMHDR* pNMHDR, LRESULT* pResult) 
  6265. {
  6266.     NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
  6267.  
  6268.     if ((pNMListView->uOldState & 0x3000) == 0)
  6269.         *pResult = 0;
  6270.     // Make sure the checkbox state is correct.  (Note : I have no idea what constant value this mask associates with..)
  6271.     else if ((m_pModel->GetAnimInfo(pNMListView->iItem))->GetAnimOwner() == m_pModel)
  6272.         *pResult = (pNMListView->uNewState & 0x2000) == 0;
  6273.     else
  6274.         *pResult = (pNMListView->uNewState & 0x1000) == 0;
  6275. }
  6276.  
  6277. void CModelEditDlg::OnBeginDragAnimList(NMHDR* pNMHDR, LRESULT* pResult) 
  6278. {
  6279.     NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
  6280.     // TODO: Add your control notification handler code here
  6281.     
  6282.     *pResult = 0;
  6283. }
  6284.  
  6285. void CModelEditDlg::OnDropAnimList(int iItem)
  6286. {
  6287.     // Handle rearrangement of the animation list
  6288.     if (iItem != m_AnimList.GetDragIndex())
  6289.     {
  6290.         // Adjust for post-insertion instead of pre-insertion
  6291.         iItem = min(iItem, m_AnimList.GetItemCount() - 1);
  6292.         MoveAnims(iItem - m_AnimList.GetDragIndex());
  6293.     }
  6294. }
  6295.  
  6296. // ------------------------------------------------------------------------
  6297. // when the right button is clicked on one of our controls, see 
  6298. // get the menu for it.
  6299. // ------------------------------------------------------------------------
  6300. void CModelEditDlg::OnContextMenu(CWnd* pWnd, CPoint point) 
  6301. {
  6302.     CMenu menu;
  6303.     
  6304.     if (pWnd->m_hWnd == m_AnimList.m_hWnd)
  6305.     {
  6306.         VERIFY(menu.LoadMenu(IDR_MENU_ANIMLIST));
  6307.     }
  6308.     else if( pWnd->m_hWnd == m_NodeList.m_hWnd )
  6309.     {
  6310.         VERIFY(menu.LoadMenu(IDR_NODE_EDIT));
  6311.     }
  6312.     else if( pWnd->m_hWnd == m_PieceList.m_hWnd )
  6313.     {
  6314.         VERIFY(menu.LoadMenu(IDR_PIECE_EDIT));
  6315.     }
  6316.     else if( pWnd->m_hWnd == m_SocketList.m_hWnd )
  6317.     {
  6318.         VERIFY(menu.LoadMenu(IDR_SOCKET_EDIT));
  6319.     }
  6320.     else return;
  6321.  
  6322.     CMenu* pPopup = menu.GetSubMenu(0);
  6323.     ASSERT(pPopup != NULL);
  6324.  
  6325.     pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this);    
  6326. }
  6327.  
  6328.  
  6329. void CModelEditDlg::OnSortAnimName() 
  6330. {
  6331.     // Make sure this is valid...
  6332.     if ((!m_pModel) || (m_pModel->NumAnims() < 2))
  6333.         return;
  6334.  
  6335.     // Sort the animation list
  6336.     AnimInfo temp;
  6337.     DWORD i,j;
  6338.  
  6339.     for (i = 0; i < m_pModel->NumAnims() - 1; i++)
  6340.         for (j = i + 1; j < m_pModel->NumAnims(); j++)
  6341.         {
  6342.             if (stricmp(m_pModel->GetAnim(i)->GetName(), m_pModel->GetAnim(j)->GetName()) > 0)
  6343.             {
  6344.                 temp = m_pModel->m_Anims[i];
  6345.                 m_pModel->m_Anims[i] = m_pModel->m_Anims[j];
  6346.                 m_pModel->m_Anims[j] = temp;
  6347.             }
  6348.         }
  6349.  
  6350.     SetChangesMade();
  6351.  
  6352.     // Re-display the animation list
  6353.     FillAnimList();
  6354. }
  6355.  
  6356. void CModelEditDlg::OnSortAnimRelation() 
  6357. {
  6358.     // Make sure this is valid...
  6359.     if ((!m_pModel) || (m_pModel->NumAnims() < 2))
  6360.         return;
  6361.  
  6362.     // Sort the animation list
  6363.     AnimInfo temp;
  6364.     DWORD i,j;
  6365.  
  6366.     for (i = 0; i < m_pModel->NumAnims() - 1; i++)
  6367.         for (j = i + 1; j < m_pModel->NumAnims(); j++)
  6368.         {
  6369.             int iDiffi = (int)(m_pModel->GetAnimInfo(i)->GetAnimOwner() - m_pModel);
  6370.             int iDiffj = (int)(m_pModel->GetAnimInfo(j)->GetAnimOwner() - m_pModel);
  6371.             if (iDiffi > iDiffj)
  6372.             {
  6373.                 temp = m_pModel->m_Anims[i];
  6374.                 m_pModel->m_Anims[i] = m_pModel->m_Anims[j];
  6375.                 m_pModel->m_Anims[j] = temp;
  6376.             }
  6377.         }
  6378.  
  6379.     SetChangesMade();
  6380.  
  6381.     // Re-display the animation list
  6382.     FillAnimList();
  6383. }
  6384.  
  6385. void CModelEditDlg::OnDblClkSocketList() 
  6386. {
  6387.     ModelSocket *pSocket;
  6388.     int iSocket;
  6389.     EulerAngles angles;
  6390.  
  6391.     if (!m_pModel)
  6392.         return;
  6393.  
  6394.     // Get the selected socket
  6395.     iSocket = m_SocketList.GetCurSel();
  6396.  
  6397.     // This should never happen
  6398.     if ((iSocket < 0) || (iSocket >= (int)m_pModel->NumSockets()))
  6399.         return;
  6400.  
  6401.     pSocket = m_pModel->GetSocket(iSocket);
  6402.     
  6403.     // Get the attachment from the registry
  6404.     CString csAttachment("");
  6405.  
  6406.     CRegMgr regMgr;
  6407.     if (regMgr.Init(szRegKeyCompany, szRegKeyApp, szRegKeyVer, "Attachments", HKEY_CURRENT_USER))
  6408.     {
  6409.         UINT32 dwSize = 256;
  6410.         regMgr.Get(pSocket->GetName(), csAttachment.GetBufferSetLength(dwSize), dwSize);
  6411.         csAttachment.ReleaseBuffer(-1);
  6412.     }
  6413.  
  6414.     CSocketEdit dlg;
  6415.  
  6416.     int dlgResult = IDOK;
  6417.     do
  6418.     {
  6419.         // Convert the rotation to euler angles
  6420.         angles = Eul_FromQuat(pSocket->m_Rot, EulOrdXYZs);
  6421.  
  6422.         // Set up the dialog
  6423.         dlg.m_Name = pSocket->GetName();
  6424.         dlg.m_NodeName= m_pModel->GetNode( pSocket->m_iNode )->GetName();
  6425.         dlg.m_PosX = pSocket->m_Pos.x;
  6426.         dlg.m_PosY = pSocket->m_Pos.y;
  6427.         dlg.m_PosZ = pSocket->m_Pos.z;
  6428.         dlg.m_RotX = angles.x * 180.0f / MATH_PI;
  6429.         dlg.m_RotY = angles.y * 180.0f / MATH_PI;
  6430.         dlg.m_RotZ = angles.z * 180.0f / MATH_PI;
  6431.         dlg.m_SclX = pSocket->m_Scale.x ;
  6432.         dlg.m_SclY = pSocket->m_Scale.y ;
  6433.         dlg.m_SclZ = pSocket->m_Scale.z ;
  6434.  
  6435.         dlg.m_Attachment = csAttachment;
  6436.  
  6437.         // Edit the socket
  6438.         dlgResult = dlg.DoModal();
  6439.         if (dlgResult == IDCANCEL)
  6440.             return;
  6441.  
  6442.         // Change the position
  6443.         pSocket->m_Pos.x = dlg.m_PosX;
  6444.         pSocket->m_Pos.y = dlg.m_PosY;
  6445.         pSocket->m_Pos.z = dlg.m_PosZ;
  6446.  
  6447.         // Change the rotation
  6448.         angles.x = dlg.m_RotX * MATH_PI / 180.0f;
  6449.         angles.y = dlg.m_RotY * MATH_PI / 180.0f;
  6450.         angles.z = dlg.m_RotZ * MATH_PI / 180.0f;
  6451.         pSocket->m_Rot = Eul_ToQuat(angles);
  6452.  
  6453.         // Change the scale 
  6454.         pSocket->m_Scale.Init( dlg.m_SclX, dlg.m_SclY, dlg.m_SclZ);
  6455.  
  6456.         // Change the name
  6457.         if (dlg.m_Name.CompareNoCase(pSocket->GetName()) != 0)
  6458.         {
  6459.             pSocket->SetName(dlg.m_Name);
  6460.             FillSocketList(TRUE);
  6461.             // Make sure the attachment tries to change to the new value
  6462.             csAttachment = _T("");
  6463.         }
  6464.  
  6465.         // Change the attachment
  6466.         if (dlg.m_Attachment.CompareNoCase(csAttachment) != 0)
  6467.         {
  6468.             // Clear out the old attachment
  6469.             if (pSocket->m_pAttachment)
  6470.                 delete pSocket->m_pAttachment;
  6471.             pSocket->m_pAttachment = NULL;
  6472.  
  6473.             if (dlg.m_Attachment.GetLength())
  6474.             {
  6475.                 if( IsFilenameLTAExt( dlg.m_Attachment ) )
  6476.                 {
  6477.                     
  6478.                     char *str = dlg.m_Attachment.LockBuffer();
  6479.                     dlg.m_Attachment.UnlockBuffer();
  6480.                     Model *pModel = load_LTA_Using_FeedBackDialog( str, false  );
  6481.  
  6482.                     if( pModel == NULL )
  6483.                     {
  6484.                         MessageBox("Failed to load lta file","load error");
  6485.                         dlg.m_Attachment = csAttachment ;
  6486.                     
  6487.                     }else // success !!
  6488.                     {
  6489.                         pSocket->m_pAttachment = pModel ;
  6490.                     }
  6491.                 }
  6492.                 else // else we're loading abcs
  6493.                 {
  6494.                     MessageBox("OnDblClkSocketList error, trying to load bin abc file", "ERROR",MB_OK);
  6495.  
  6496.                 }
  6497.             
  6498.             }
  6499.  
  6500.             // Store the attachment in the registry if it didn't fail loading
  6501.             if (dlg.m_Attachment.CompareNoCase(csAttachment) != 0)
  6502.                 regMgr.Set(pSocket->GetName(), (LPCTSTR)dlg.m_Attachment);
  6503.  
  6504.             // Save the string for the next go-round
  6505.             csAttachment = dlg.m_Attachment;
  6506.         }
  6507.  
  6508.         SetChangesMade();
  6509.  
  6510.     } while (dlgResult != IDOK);
  6511. }
  6512.  
  6513. float CModelEditDlg::CalcFOV()
  6514. {
  6515.     CRegMgr regMgr;
  6516.     CString csFOV;
  6517.     if (regMgr.Init(szRegKeyCompany, szRegKeyApp, szRegKeyVer, "Render", HKEY_CURRENT_USER))
  6518.     {
  6519.         UINT32 dwSize = 256;
  6520.         csFOV = "90";
  6521.         regMgr.Get("FOV", csFOV.GetBufferSetLength(dwSize), dwSize);
  6522.         csFOV.ReleaseBuffer(-1);
  6523.         return max((float)atof(csFOV), 10.0f);
  6524.     }
  6525.     else
  6526.         return 90.0f;
  6527. }
  6528.  
  6529. void CModelEditDlg::SetFOV(float FOV)
  6530. {
  6531.     CRegMgr regMgr;
  6532.     CString csFOV;
  6533.     if (regMgr.Init(szRegKeyCompany, szRegKeyApp, szRegKeyVer, "Render", HKEY_CURRENT_USER))
  6534.     {
  6535.         csFOV.Format("%f", FOV);
  6536.         regMgr.Set("FOV", csFOV);
  6537.     }
  6538. }
  6539.  
  6540.  
  6541. MEAnimInfo* CModelEditDlg::GetAnimInfo(uint32 iAnimInfo)
  6542. {
  6543.     ASSERT(iAnimInfo < NUM_ANIM_INFOS);
  6544.     return &m_AnimInfos[iAnimInfo];
  6545. }
  6546.  
  6547.  
  6548. void CModelEditDlg::StopAllPlayback()
  6549. {
  6550.     uint32 i;
  6551.  
  6552.     for(i=0; i < NUM_ANIM_INFOS; i++)
  6553.     {
  6554.         m_AnimInfos[i].StopPlayback();
  6555.     }
  6556. }
  6557.  
  6558.  
  6559. void CModelEditDlg::ResetAnimInfos()
  6560. {
  6561.     uint32 i;
  6562.  
  6563.     for(i=0; i < NUM_ANIM_INFOS; i++)
  6564.     {
  6565.         GetAnimInfo(i)->Reset();
  6566.     }
  6567. }
  6568.  
  6569.  
  6570. void CModelEditDlg::DrawActiveAnimRects(BOOL bForce)
  6571. {
  6572.     DWORD dwActive[NUM_ANIM_INFOS];
  6573.     DWORD i;
  6574.     CDC *pDC;
  6575.  
  6576.     
  6577.     // Get the key state.
  6578.     GetPlaybackActiveFlags(dwActive, FALSE);
  6579.  
  6580.     // Redraw if necessary.    
  6581.     for(i=0; i < NUM_ANIM_INFOS; i++)
  6582.     {
  6583.         if((dwActive[i] & PA_ACTIVE) != (m_LastAnimActiveFlags[i] & PA_ACTIVE) || 
  6584.             bForce)
  6585.         {
  6586.             pDC = GetDC();
  6587.                 
  6588.                 if(dwActive[i] & PA_ACTIVE)
  6589.                     m_AnimInfos[i].m_ActiveFlagsWnd.SetColor(RGB(255,0,0));
  6590.                 else
  6591.                     m_AnimInfos[i].m_ActiveFlagsWnd.SetColor(RGB(0,0,0));
  6592.             
  6593.             ReleaseDC(pDC);
  6594.         }
  6595.     }
  6596.     
  6597.     // Remember the last state..
  6598.     for(i=0; i < NUM_ANIM_INFOS; i++)
  6599.     {
  6600.         m_LastAnimActiveFlags[i] = dwActive[i];
  6601.     }
  6602. }
  6603.  
  6604. // ------------------------------------------------------------------------
  6605. // IncKeyframe( bForward )
  6606. // increment the frame forward (or backwards...).
  6607. // ------------------------------------------------------------------------
  6608. void CModelEditDlg::IncKeyframe(BOOL bForward)
  6609. {
  6610.     DWORD dwActive[NUM_ANIM_INFOS];
  6611.     DWORD i, iKeyframe;
  6612.     MEAnimInfo *pInfo;
  6613.  
  6614.     // determine which anims are active & valid
  6615.     GetPlaybackActiveFlags(dwActive);
  6616.  
  6617.  
  6618.     for(i=0; i < NUM_ANIM_INFOS; i++)
  6619.     {
  6620.         pInfo = GetAnimInfo(i);
  6621.  
  6622.         // if the animation slot is active AND valid 
  6623.         if( (dwActive[i] & (PA_ACTIVE | PA_VALID)) == (PA_ACTIVE | PA_VALID ))
  6624.         {
  6625.             if(bForward)
  6626.             {
  6627.                 iKeyframe = (pInfo->m_Tracker.m_TimeRef.m_Cur.m_iFrame + 1) % pInfo->CurAnim()->NumKeyframes();
  6628.             }
  6629.             else
  6630.             {
  6631.                 if(pInfo->m_Tracker.m_TimeRef.m_Cur.m_iFrame == 0)
  6632.                 {
  6633.                     if( pInfo->CurAnim()->NumKeyFrames() == 0 )
  6634.                         iKeyframe = 0 ;
  6635.                     else {
  6636.                         iKeyframe = (int)(pInfo->CurAnim()->NumKeyframes() - 1);
  6637.                     }
  6638.                     //iKeyframe = pInfo->CurAnim()->NumKeyframes() == 0 ? 0 : (int)(pInfo->CurAnim()->NumKeyframes() - 1);
  6639.                 }else
  6640.                     iKeyframe = (int)(pInfo->m_Tracker.m_TimeRef.m_Cur.m_iFrame - 1);
  6641.             }
  6642.  
  6643.             SetCurrentPosition(i, (DWORD)iKeyframe, (DWORD)iKeyframe, 0.0f);
  6644.             pInfo->SetKeyframeWindowTime();
  6645.         }
  6646.     }
  6647. }
  6648.  
  6649.  
  6650. void CModelEditDlg::OnOK()
  6651. {
  6652.     // Forward the enter key to the two edit controls on the dialog 
  6653.     //    (Note: Gross hack because MFC uses the enter key for "OK" in dialog-based apps)
  6654.     if (GetFocus() == &m_EditFrameTime)
  6655.         SetEditFrameTime( );
  6656.     if (GetFocus() == &m_EditFrameString)
  6657.         SetEditFrameString( );
  6658. }
  6659.  
  6660.  
  6661. BOOL CModelEditDlg::OnCommand(WPARAM wParam, LPARAM lParam) 
  6662. {
  6663.     DWORD i;
  6664.     MEAnimInfo *pInfo;
  6665.     ModelAnim *pAnim;
  6666.  
  6667.  
  6668.     if(m_pModel)
  6669.     {
  6670.         for(i=0; i < NUM_ANIM_INFOS; i++)
  6671.         {
  6672.             pInfo = GetAnimInfo(i);
  6673.  
  6674.             if(LOWORD(wParam) == pInfo->m_AnimButtonID)
  6675.             {
  6676.                 if(pInfo->m_Wnd.IsActive())
  6677.                 {
  6678.                     WeightSetSelectDlg dlg(m_pModel, pInfo->CurAnim()->m_ModelEditWeightSet);
  6679.  
  6680.                     if(dlg.DoModal() == IDOK)
  6681.                     {
  6682.                         // Set it up..
  6683.                         if(pAnim = pInfo->CurAnim())
  6684.                         {
  6685.                             if(pAnim->m_ModelEditWeightSet != dlg.m_SelectedSet)
  6686.                             {
  6687.                                 pAnim->m_ModelEditWeightSet = dlg.m_SelectedSet;
  6688.                                 SetChangesMade();
  6689.                             }
  6690.                         }
  6691.  
  6692.                         // Make it update the trackers..
  6693.                         OnSelChangeAnimList();
  6694.                     }
  6695.                 }
  6696.                 
  6697.                 break;
  6698.             }
  6699.         }
  6700.     }
  6701.  
  6702.     return CDialog::OnCommand(wParam, lParam);
  6703. }
  6704.  
  6705.  
  6706. void CModelEditDlg::OnFrameStringChange()
  6707. {
  6708.     if(m_bInStringChange)
  6709.         return;
  6710.  
  6711.     TempVarSetter<BOOL> setter(&m_bInStringChange, TRUE);
  6712.  
  6713.     SetEditFrameString();
  6714. }
  6715.  
  6716.  
  6717. void CModelEditDlg::OnFrameTimeChange()
  6718. {
  6719.     if(m_bInStringChange)
  6720.         return;
  6721.  
  6722.     TempVarSetter<BOOL> setter(&m_bInStringChange, TRUE);
  6723.  
  6724.     SetEditFrameTime();
  6725. }
  6726.  
  6727.  
  6728. void CModelEditDlg::OnNewBgColor() 
  6729. {
  6730.     extern void SetGLMBackgroundColor( GLM_CONTEXT hContext, COLORREF win_color );
  6731.  
  6732.     // TODO: Add your command handler code here
  6733.         // TODO: Add your command handler code here
  6734.     CColorDialog colorPicker ;
  6735.     colorPicker.DoModal();
  6736.     COLORREF ms_color = colorPicker.GetColor();
  6737.  
  6738.     CRegMgr regMgr;
  6739.     if (regMgr.Init(szRegKeyCompany, szRegKeyApp, szRegKeyVer, "Render", HKEY_CURRENT_USER))
  6740.     {
  6741.         UINT32 dwSize = sizeof(float)*3;
  6742.         unsigned char *pColDecomp = (unsigned char*)&ms_color;
  6743.         float bgColor[3];
  6744.         // unitize
  6745.         bgColor[0] = pColDecomp[0]/256.0f;
  6746.         bgColor[1] = pColDecomp[1]/256.0f;
  6747.         bgColor[2] = pColDecomp[2]/256.0f;
  6748.         regMgr.Set("bgColor",bgColor , dwSize);
  6749.  
  6750.     }
  6751.     // set the bg color for m_RenderWnd->GLMContext.
  6752.     m_RenderWnd.SetBackgroundColor( ms_color );
  6753. }
  6754.  
  6755.  
  6756. void CModelEditDlg::OnLoadConfirm()
  6757. {
  6758.     m_bConfirmLoadDlg = !m_bConfirmLoadDlg;
  6759.  
  6760.     // store this setting in the registry
  6761.     CRegMgr regMgr;
  6762.     if( regMgr.Init( szRegKeyCompany, szRegKeyApp, szRegKeyVer, "Options", HKEY_CURRENT_USER ) )
  6763.     {
  6764.         regMgr.Set( "confirm_load", m_bConfirmLoadDlg ? 1 : 0 );
  6765.     }
  6766.  
  6767.     UpdateMenuChecks();
  6768. }
  6769.  
  6770.  
  6771. void CModelEditDlg::OnOptionsShoworiginalmodel() 
  6772. {
  6773.         m_RenderWnd.m_DrawStruct.m_bDrawOriginalModel = !m_RenderWnd.m_DrawStruct.m_bDrawOriginalModel ;
  6774.     UpdateMenuChecks();    
  6775. }
  6776.  
  6777.  
  6778. void CModelEditDlg::OnChangeFov() 
  6779. {
  6780.     // TODO: Add your command handler code here
  6781.     m_RenderWnd.OpenFOVDlg();    
  6782. }
  6783.  
  6784. //------------------------------------------------------------------
  6785. //
  6786. //   FUNCTION : OnExportModelStringKeys()
  6787. //
  6788. //   PURPOSE  : Exports string keys from a given model
  6789. //
  6790. //------------------------------------------------------------------
  6791.  
  6792. void CModelEditDlg::OnExportModelStringKeys()
  6793. {
  6794.     if (!m_pModel)
  6795.     {
  6796.         AfxMessageBox("No model currently loaded !!");
  6797.  
  6798.         return;
  6799.     }
  6800.  
  6801.     char szFilter[] = "MSK Files (*.msk)|*.msk|All Files (*.*)|*.*||";
  6802.     CFileDialog dlg(FALSE, "msk", NULL, OFN_OVERWRITEPROMPT | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY, szFilter, this);
  6803.  
  6804.     if (dlg.DoModal() == IDOK)
  6805.     {
  6806.         CString sFile = dlg.GetPathName();
  6807.  
  6808.         FILE *fp = fopen(sFile, "wb");
  6809.         if (!fp)
  6810.         {
  6811.             CString sError;
  6812.             sError.Format("Error opening/creating %s", sFile);
  6813.             AfxMessageBox(sError, MB_ICONEXCLAMATION);
  6814.  
  6815.             return;
  6816.         }
  6817.  
  6818.         // Write out the user radius for this model
  6819.  
  6820.         float fRadius = m_pModel->m_GlobalRadius;
  6821.         fwrite(&fRadius, sizeof(float), 1, fp);
  6822.  
  6823.         // Write out the number of animations
  6824.  
  6825.         int nAnims = m_pModel->NumAnims();
  6826.         fwrite(&nAnims, sizeof(int), 1, fp);
  6827.         
  6828.         for (int i = 0; i < nAnims; i ++)
  6829.         {
  6830.             ModelAnim *pAnim = m_pModel->GetAnim(i);
  6831.  
  6832.             // Write out the name of the animation
  6833.             
  6834.             char *sName = pAnim->GetName();                
  6835.             int nLen = strlen(sName);
  6836.  
  6837.             // Write out the total length of the animation
  6838.  
  6839.             uint32 nAnimLen = pAnim->GetAnimTime();
  6840.             float fRatio = 1.0f;
  6841.             if (nAnimLen)
  6842.             {
  6843.                 fRatio = 1.0f / (float)nAnimLen;
  6844.             }
  6845.             
  6846.             fwrite(&nLen, sizeof(int), 1, fp);
  6847.             fwrite(sName, nLen, 1, fp);
  6848.  
  6849.             // Write out the dims of the animation
  6850.  
  6851.             AnimInfo *pInfo = m_pModel->GetAnimInfo(i);
  6852.             float fDimsX = pInfo->m_vDims.x;
  6853.             float fDimsY = pInfo->m_vDims.y;
  6854.             float fDimsZ = pInfo->m_vDims.z;
  6855.  
  6856.             fwrite(&fDimsX, sizeof(float), 1, fp);
  6857.             fwrite(&fDimsY, sizeof(float), 1, fp);
  6858.             fwrite(&fDimsZ, sizeof(float), 1, fp);
  6859.  
  6860.             
  6861.             // Write out all the string keys
  6862.  
  6863.             for (int j = 0; j < (int)pAnim->NumKeyFrames(); j ++)
  6864.             {
  6865.                 AnimKeyFrame *pKey = &pAnim->m_KeyFrames[j];
  6866.  
  6867.                 if ((pKey->m_pString) && (strcmp(pKey->m_pString, "")))
  6868.                 {
  6869.                     // Write out marker
  6870.                     
  6871.                     char bMarker = 1;
  6872.                     fwrite(&bMarker, sizeof(char), 1, fp);
  6873.  
  6874.                     // Write out time at which this string occurs
  6875.  
  6876.                     float fTime = (float)pKey->m_Time * fRatio;
  6877.                     fwrite(&fTime, sizeof(uint32), 1, fp);
  6878.  
  6879.                     // Write out the string itself
  6880.  
  6881.                     nLen = strlen(pKey->m_pString);
  6882.                     fwrite(&nLen, sizeof(int), 1, fp);
  6883.                     fwrite(pKey->m_pString, nLen, 1, fp);
  6884.                 }
  6885.             }
  6886.  
  6887.             // Write out the end marker
  6888.  
  6889.             char nDone = -1;
  6890.             fwrite(&nDone, sizeof(char), 1, fp);
  6891.         }
  6892.  
  6893.         fclose(fp);
  6894.     }
  6895. }
  6896.  
  6897. //------------------------------------------------------------------
  6898. //
  6899. //   FUNCTION : OnImportModelStringKeys()
  6900. //
  6901. //   PURPOSE  : Imports model string keys from a .msk file
  6902. //
  6903. //------------------------------------------------------------------
  6904. void CModelEditDlg::OnImportModelStringKeys()
  6905. {
  6906.     if (!m_pModel)
  6907.     {
  6908.         AfxMessageBox("No model currently loaded !!");
  6909.  
  6910.         return;
  6911.     }
  6912.  
  6913.     char szFilter[] = "MSK Files (*.msk)|*.msk|All Files (*.*)|*.*||";
  6914.     CFileDialog dlg(TRUE, "msk", NULL, OFN_FILEMUSTEXIST | OFN_HIDEREADONLY, szFilter, this);
  6915.  
  6916.     if (dlg.DoModal() == IDOK)
  6917.     {
  6918.         CString sFile = dlg.GetPathName();
  6919.  
  6920.         char sTmp[1024];
  6921.         
  6922.         FILE *fp = fopen(sFile, "rb");
  6923.         if (!fp)
  6924.         {
  6925.             CString sError;
  6926.             sError.Format("Error opening/creating %s", sFile);
  6927.             AfxMessageBox(sError, MB_ICONEXCLAMATION);
  6928.  
  6929.             return;
  6930.         }
  6931.  
  6932.         CEdit *pEdit = (CEdit *)m_pImportStringKeyDlg->GetDlgItem(IDC_PROGRESS);
  6933.         pEdit->SetWindowText("");
  6934.         m_pImportStringKeyDlg->ShowWindow(SW_SHOW);
  6935.  
  6936.         // Read in the global radius
  6937.  
  6938.         float fRadius;
  6939.         fread(&fRadius, sizeof(float), 1, fp);
  6940.  
  6941.         sprintf(sTmp, "Setting Global Radius to %4.2f\n", fRadius);
  6942.         m_pImportStringKeyDlg->AddMsg(sTmp, 255, 0, 0);
  6943.  
  6944.         m_pModel->m_GlobalRadius = fRadius;
  6945.  
  6946.         // Read in the number of animations....
  6947.  
  6948.         int nAnims;
  6949.         fread(&nAnims, sizeof(int), 1, fp);
  6950.  
  6951.         for (int i = 0; i < nAnims; i ++)
  6952.         {
  6953.             // Read in the name of this animation....
  6954.  
  6955.             int nLen;
  6956.             char sAnimName[4096];
  6957.  
  6958.             fread(&nLen, sizeof(int), 1, fp);
  6959.             fread(sAnimName, nLen, 1, fp);
  6960.             sAnimName[nLen] = 0;
  6961.  
  6962.             // Read in the dims of the animation
  6963.  
  6964.             float fDimsX;
  6965.             float fDimsY;
  6966.             float fDimsZ;
  6967.  
  6968.             fread(&fDimsX, sizeof(float), 1, fp);
  6969.             fread(&fDimsY, sizeof(float), 1, fp);
  6970.             fread(&fDimsZ, sizeof(float), 1, fp);
  6971.             
  6972.             // Attempt to locate this animation....
  6973.  
  6974.             ModelAnim *pAnim = m_pModel->FindAnim(sAnimName);
  6975.             if (pAnim)
  6976.             {
  6977.                 unsigned int dwIndex;
  6978.                 AnimInfo *pInfo = m_pModel->FindAnimInfo(sAnimName, m_pModel, &dwIndex);
  6979.  
  6980.                 if (pInfo)
  6981.                 {
  6982.                     sprintf(sTmp, "Setting Animation [%s] Dims to [%f4.2, %f4.2, %f4.2]\n", sAnimName, fDimsX, fDimsY, fDimsZ);
  6983.                     m_pImportStringKeyDlg->AddMsg(sTmp, 255, 0, 0);
  6984.  
  6985.                     // Set the dims...
  6986.  
  6987.                     pInfo->m_vDims.x = fDimsX;
  6988.                     pInfo->m_vDims.y = fDimsY;
  6989.                     pInfo->m_vDims.z = fDimsZ;
  6990.                 }
  6991.             }
  6992.  
  6993.             // Read the model keys....
  6994.  
  6995.             bool bReading = true;
  6996.  
  6997.             while (bReading)
  6998.             {
  6999.                 char bMarker;
  7000.                 fread(&bMarker, sizeof(char), 1, fp);
  7001.  
  7002.                 if (bMarker == -1)
  7003.                 {
  7004.                     // End of animation marker
  7005.                     
  7006.                     bReading = false;
  7007.                 }
  7008.                 else
  7009.                 {
  7010.                     char sName[2048];
  7011.  
  7012.                     // Read the keyframe time...
  7013.  
  7014.                     float fTime;
  7015.                     fread(&fTime, sizeof(uint32), 1, fp);
  7016.                     
  7017.                     // Read the string key...
  7018.                     
  7019.                     fread(&nLen, sizeof(int), 1, fp);
  7020.                     fread(sName, nLen, 1, fp);
  7021.                     sName[nLen] = 0;
  7022.  
  7023.                     if (pAnim)
  7024.                     {
  7025.                         int nTime = (int)(fTime * (float)pAnim->GetAnimTime());
  7026.  
  7027.                         // Attempt to locate the correct keyframe....
  7028.  
  7029.                         for (int j = 0; j < (int)pAnim->NumKeyFrames(); j ++)
  7030.                         {
  7031.                             AnimKeyFrame *pKey = &pAnim->m_KeyFrames[j];
  7032.  
  7033.                             if (pKey->m_Time >= (uint32)nTime)
  7034.                             {
  7035.                                 char sTmp[2048];
  7036.  
  7037.                                 if (pKey->m_Time - nTime < 5)
  7038.                                 {
  7039.                                     sprintf(sTmp, "SUCCESS !! Anim [%s] - Added \"%s\" at exactly %d ms\r\n", pAnim->GetName(), sName, nTime);
  7040.                                     m_pImportStringKeyDlg->AddMsg(sTmp, 0, 0, 0);
  7041.                                 }
  7042.                                 else
  7043.                                 {
  7044.                                     sprintf(sTmp, "WARNING !! Anim [%s] - Added \"%s\" at time %d ms (out by %d ms, could not locate exact keyframe)\r\n", pAnim->GetName(), sName, pKey->m_Time, pKey->m_Time - nTime);
  7045.                                     m_pImportStringKeyDlg->AddMsg(sTmp, 0, 0, 0);
  7046.                                 }
  7047.                                 
  7048.                                 // This is the key, fill out the string....
  7049.  
  7050.                                 pKey->m_pString = m_pModel->AddString(sName);
  7051.  
  7052.                                 j = pAnim->NumKeyFrames();
  7053.                             }
  7054.                         }
  7055.                     }
  7056.                     else
  7057.                     {
  7058.                         sprintf(sTmp, "ERROR !! Anim %s missing for string key \"%s\"\r\n", sAnimName, sName);
  7059.                         m_pImportStringKeyDlg->AddMsg(sTmp, 0, 0, 0);
  7060.                     }
  7061.                 }
  7062.             }
  7063.         }
  7064.  
  7065.         // Close file...
  7066.  
  7067.         fclose(fp);
  7068.  
  7069.         ModelAnim *pAnim = m_AnimInfos[0].CurAnim();
  7070.         if (pAnim)
  7071.         {
  7072.             int nKeyFrame = m_AnimInfos[0].m_Wnd.ForceNearestKeyframe();
  7073.  
  7074.             if (nKeyFrame < (int)pAnim->NumKeyFrames())
  7075.             {
  7076.                 char *sTitle = pAnim->m_KeyFrames[nKeyFrame].m_pString;
  7077.  
  7078.                 GetDlgItem(IDC_FRAMESTRING)->SetWindowText(sTitle);
  7079.             }
  7080.         }
  7081.     }
  7082. }
  7083.  
  7084. void CModelEditDlg::OnItemclickNodelist(NMHDR* pNMHDR, LRESULT* pResult) 
  7085. {
  7086.     HD_NOTIFY *phdn = (HD_NOTIFY *) pNMHDR;
  7087.     // TODO: Add your control notification handler code here
  7088.     
  7089.     *pResult = 0;
  7090. }
  7091.  
  7092. void CModelEditDlg::OnOptionsShowVertexWeighting() 
  7093. {
  7094.         m_RenderWnd.m_DrawStruct.m_bDrawVertexWeights = !m_RenderWnd.m_DrawStruct.m_bDrawVertexWeights;
  7095.     UpdateMenuChecks();
  7096. }
  7097.  
  7098. void CModelEditDlg::OnNodeeditEditobb() 
  7099. {
  7100.     // find the first selected node 
  7101.     if (!m_pModel)
  7102.         return;
  7103.  
  7104.     int selection = m_NodeList.GetSelectionMark();
  7105.  
  7106.     if( selection > -1 )
  7107.     {
  7108.         ModelNode *pNode = m_pModel->m_FlatNodeList[selection];
  7109.         CEditOBBDlg dlg(pNode);
  7110.  
  7111.         dlg.DoModal();    
  7112.     }
  7113. }
  7114.  
  7115. void CModelEditDlg::OnNodeEditRename() 
  7116. {
  7117.     OnRenameNode();
  7118. }
  7119.  
  7120. void CModelEditDlg::OnNodeEditLookAt()
  7121. {
  7122.     if( !m_pModel )
  7123.         return;
  7124.  
  7125.     int selection = m_NodeList.GetSelectionMark();
  7126.  
  7127.     if( selection <= -1 )
  7128.         return;
  7129.  
  7130.     LTMatrix* mat = m_pModel->GetTransform( selection );
  7131.     ASSERT( mat );
  7132.  
  7133.     LTVector pos;
  7134.     mat->GetTranslation( pos );
  7135.     pos.z *= -1.0f;
  7136.  
  7137.     m_RenderWnd.m_Camera.LookAtPoint( pos );
  7138. }
  7139.  
  7140. void CModelEditDlg::OnSocketEditLookAt()
  7141. {
  7142.     if( !m_pModel )
  7143.         return;
  7144.  
  7145.     int selection = m_SocketList.GetCurSel();
  7146.  
  7147.     if( (selection < 0) || (selection >= (int)m_pModel->NumSockets()) )
  7148.         return;
  7149.  
  7150.     LTMatrix xform;
  7151.     ModelSocket* socket = m_pModel->GetSocket( selection );    
  7152.     if( !m_pModel->GetSocketTransform( socket, &xform ) )
  7153.     {
  7154.         ASSERT( 0 );
  7155.         return;
  7156.     }
  7157.  
  7158.     LTVector pos;
  7159.     xform.GetTranslation( pos );
  7160.     pos.z *= -1.0f;
  7161.  
  7162.     m_RenderWnd.m_Camera.LookAtPoint( pos );
  7163. }
  7164.  
  7165.  
  7166. //------------------------------------------------------------------
  7167. //
  7168. //   FUNCTION : OnExportWeightSets()
  7169. //
  7170. //   PURPOSE  : Exports weight sets for this model
  7171. //
  7172. //------------------------------------------------------------------
  7173.  
  7174. void CModelEditDlg::OnExportWeightSets() 
  7175. {
  7176.     if (!m_pModel) return;
  7177.  
  7178.     CFileDialog dlg(FALSE, "", "*.wst");
  7179.  
  7180.     if (dlg.DoModal() == IDOK)
  7181.     {
  7182.         CString sFile = dlg.GetPathName();
  7183.  
  7184.         // Create the file and export the weight sets
  7185.  
  7186.         CLTAWriter writer;
  7187.         CString sName = dlg.GetPathName();
  7188.  
  7189.         if (writer.Open(dlg.GetPathName(), false))
  7190.         {
  7191.             writer.BeginNode();
  7192.  
  7193.             for (int i = 0; i < m_pModel->NumWeightSets(); i ++)
  7194.             {
  7195.                 WeightSet *pSet = m_pModel->GetWeightSet(i);
  7196.  
  7197.                 // Write the weight set
  7198.  
  7199.                 writer.BeginNode();
  7200.  
  7201.                 writer.Write(pSet->GetName());
  7202.  
  7203.                 writer.BeginNode();
  7204.  
  7205.                 for (int j = 0; j < pSet->m_Weights.GetSize(); j ++)
  7206.                 {
  7207.                     CString sTxt;
  7208.                     sTxt.Format("%4.2f", pSet->m_Weights[j]);
  7209.  
  7210.                     writer.Write(sTxt);
  7211.                     writer.BreakLine();
  7212.                 }
  7213.  
  7214.                 writer.EndNode();
  7215.  
  7216.                 writer.EndNode();
  7217.             }
  7218.  
  7219.             writer.EndNode();
  7220.         
  7221.             writer.Close();
  7222.         }
  7223.     }
  7224. }
  7225.  
  7226. //------------------------------------------------------------------
  7227. //
  7228. //   FUNCTION : OnImportWeightSets()
  7229. //
  7230. //   PURPOSE  : Imports weight sets for this model
  7231. //
  7232. //------------------------------------------------------------------
  7233.  
  7234. void CModelEditDlg::OnImportWeightSets() 
  7235. {
  7236.     if (!m_pModel) return;
  7237.  
  7238.     CFileDialog dlg(TRUE, "*.wst");
  7239.  
  7240.     if (dlg.DoModal() == IDOK)
  7241.     {
  7242.         CLTADefaultAlloc *pAlloc = new CLTADefaultAlloc;
  7243.  
  7244.         CLTANode *pRoot = pAlloc->AllocateNode();
  7245.  
  7246.         CString sFile = dlg.GetPathName();
  7247.  
  7248.         if (CLTANodeReader::LoadEntireFile(sFile, false, pRoot, pAlloc))
  7249.         {
  7250.             // Read in the weight sets
  7251.  
  7252.             if (pRoot->IsList())
  7253.             {
  7254.                 for (int i = 0; i < pRoot->GetNumElements(); i ++)
  7255.                 {
  7256.                     CLTANode *pWeightSet = pRoot->GetElement(i);
  7257.  
  7258.                     for (int k = 0; k < pWeightSet->GetNumElements(); k ++)
  7259.                     {
  7260.                         WeightSet *pSet = new WeightSet(m_pModel);
  7261.                         bool bRead = false;
  7262.  
  7263.                         // Name should be the first child
  7264.                         
  7265.                         CLTANode *pChild = pWeightSet->GetElement(k);
  7266.  
  7267.                         if (pChild->IsList())
  7268.                         {
  7269.                             int nChildren = pChild->GetNumElements();
  7270.                             
  7271.                             if (nChildren == 2)
  7272.                             {
  7273.                                 CLTANode *pName = pChild->GetElement(0);
  7274.                                 if (pName->IsAtom())
  7275.                                 {
  7276.                                     CString sName = pName->GetValue();
  7277.  
  7278.                                     strcpy(pSet->m_Name, (char *)(LPCSTR)sName);
  7279.  
  7280.                                     CLTANode *pWeightList = pChild->GetElement(1);
  7281.  
  7282.                                     if (pWeightList->IsList())
  7283.                                     {
  7284.                                         int nElem = pWeightList->GetNumElements();
  7285.  
  7286.                                         if (nElem != m_pModel->NumNodes())
  7287.                                         {
  7288.                                             // Error....
  7289.  
  7290.                                             AfxMessageBox("Weight list doesn't correspond to node list, cannot import", MB_ICONEXCLAMATION);
  7291.  
  7292.                                             delete pSet;
  7293.  
  7294.                                             pAlloc->FreeNode(pRoot);
  7295.  
  7296.                                             delete pAlloc;
  7297.  
  7298.                                             return;
  7299.                                         }
  7300.                                         
  7301.                                         // Read the weights
  7302.  
  7303.                                         for (int j = 0; j < pWeightList->GetNumElements(); j ++)
  7304.                                         {
  7305.                                             CLTANode *pWeight = pWeightList->GetElement(j);
  7306.  
  7307.                                             if (pWeight->IsAtom())
  7308.                                             {
  7309.                                                 float fWeight = (float)atof(pWeight->GetValue());
  7310.  
  7311.                                                 // Add the weight to the list
  7312.  
  7313.                                                 pSet->m_Weights.Add(fWeight);
  7314.  
  7315.                                                 bRead = true;
  7316.                                             }
  7317.                                         }
  7318.                                     }
  7319.                                 }
  7320.                             }
  7321.                         }
  7322.                     
  7323.                         if (!bRead)
  7324.                         {
  7325.                             delete pSet;
  7326.                         }
  7327.                         else
  7328.                         {
  7329.                             m_pModel->AddWeightSet(pSet);
  7330.                             SetChangesMade();
  7331.                         }                    
  7332.                     }                
  7333.                 }
  7334.             }
  7335.         }
  7336.  
  7337.         pAlloc->FreeNode(pRoot);
  7338.  
  7339.         delete pAlloc;
  7340.     }
  7341. }
  7342.  
  7343.  
  7344. // Hook Stdlith's base allocators.
  7345. void* DefStdlithAlloc(uint32 size)
  7346. {
  7347.         return malloc(size);
  7348. }
  7349.  
  7350. void DefStdlithFree(void *ptr)
  7351. {
  7352.         free(ptr);
  7353. }
  7354.  
  7355.  
  7356.  
  7357.