Panda3D

maxOptionsDialog.cxx

00001 /*
00002   maxEggExpOptions.cxx
00003   Created by Phillip Saltzman, 2/15/05
00004   Carnegie Mellon University, Entetainment Technology Center
00005 
00006   This file implements the classes that are used to choose
00007   what to export from 3D Studio max
00008   
00009   Updated by Fei Wang, Carnegie Mellon University Entertainment
00010   Technology Center student, 14Aug2009:  added enableAddCollisionChoices
00011 */
00012 
00013 #include "maxEgg.h"
00014 
00015 //Disable the forcing int to true or false performance warning
00016 #pragma warning(disable: 4800)
00017 
00018 void SetICustEdit(HWND wnd, int nIDDlgItem, char *text)
00019 { 
00020   ICustEdit *edit = GetICustEdit(GetDlgItem(wnd, nIDDlgItem));
00021   edit->SetText(text);
00022   ReleaseICustEdit(edit);
00023 }
00024 
00025 void SetICustEdit(HWND wnd, int nIDDlgItem, int n)
00026 {
00027   char text[80];
00028   sprintf(text, "%d", n);
00029   ICustEdit *edit = GetICustEdit(GetDlgItem(wnd, nIDDlgItem));
00030   edit->SetText(text);
00031   ReleaseICustEdit(edit);
00032 }
00033 
00034 char *GetICustEditT(HWND wnd)
00035 {
00036   static char buffer[2084];
00037   ICustEdit *edit = GetICustEdit(wnd);
00038   edit->GetText(buffer,2084);
00039   ReleaseICustEdit(edit);
00040   return buffer;
00041 }
00042 
00043 int GetICustEditI(HWND wnd, BOOL *valid)
00044 {
00045   ICustEdit *edit = GetICustEdit(wnd);
00046   int i = edit->GetInt(valid);
00047   ReleaseICustEdit(edit);
00048   return i;
00049 }
00050 
00051 void ChunkSave(ISave *isave, int chunkid, int value)
00052 {
00053   ULONG nb;
00054   isave->BeginChunk(chunkid);
00055   isave->Write(&value, sizeof(int), &nb);
00056   isave->EndChunk();
00057 }
00058 
00059 void ChunkSave(ISave *isave, int chunkid, ULONG value)
00060 {
00061   ULONG nb;
00062   isave->BeginChunk(chunkid);
00063   isave->Write(&value, sizeof(ULONG), &nb);
00064   isave->EndChunk();
00065 }
00066 
00067 void ChunkSave(ISave *isave, int chunkid, bool value)
00068 {
00069   ULONG nb;
00070   isave->BeginChunk(chunkid);
00071   isave->Write(&value, sizeof(bool), &nb);
00072   isave->EndChunk();
00073 }
00074 
00075 void ChunkSave(ISave *isave, int chunkid, char *value)
00076 {
00077   ULONG nb;
00078   isave->BeginChunk(chunkid);
00079   int bytes = strlen(value) + 1;
00080   isave->Write(&bytes, sizeof(int), &nb);
00081   isave->Write(value, bytes, &nb);
00082   isave->EndChunk();
00083 }
00084 
00085 char *ChunkLoadString(ILoad *iload, char *buffer, int maxBytes)
00086 {
00087   ULONG nb;
00088   int bytes;
00089   IOResult res;
00090   res = iload->Read(&bytes, sizeof(int), &nb);
00091   assert(res == IO_OK && bytes <= maxBytes);
00092   res = iload->Read(buffer, bytes, &nb);
00093   assert(res == IO_OK);
00094   return buffer;
00095 }
00096 
00097 int ChunkLoadInt(ILoad *iload)
00098 {
00099   ULONG nb;
00100   int value;
00101   IOResult res;
00102   res = iload->Read(&value, sizeof(int), &nb);
00103   assert(res == IO_OK);
00104   return value;
00105 }
00106 
00107 int ChunkLoadULONG(ILoad *iload)
00108 {
00109   ULONG nb, value;
00110   IOResult res;
00111   res = iload->Read(&value, sizeof(ULONG), &nb);
00112   assert(res == IO_OK);
00113   return value;
00114 }
00115 
00116 bool ChunkLoadBool(ILoad *iload)
00117 {
00118   ULONG nb;
00119   bool value;
00120   IOResult res;
00121   res = iload->Read(&value, sizeof(bool), &nb);
00122   assert(res == IO_OK);
00123   return value;
00124 }
00125 
00126 void showAnimControls(HWND hWnd, BOOL val) {
00127   ShowWindow(GetDlgItem(hWnd, IDC_EF_LABEL), val);
00128   ShowWindow(GetDlgItem(hWnd, IDC_EF), val);
00129   ShowWindow(GetDlgItem(hWnd, IDC_SF_LABEL), val);
00130   SetWindowText(GetDlgItem(hWnd, IDC_EXP_SEL_FRAMES),
00131                 val ? "Use Range:" : "Use Frame:");
00132 }
00133 
00134 void enableAnimControls(HWND hWnd, BOOL val) {
00135   EnableWindow(GetDlgItem(hWnd, IDC_SF_LABEL), val);
00136   EnableWindow(GetDlgItem(hWnd, IDC_SF), val);
00137   EnableWindow(GetDlgItem(hWnd, IDC_EF_LABEL), val);
00138   EnableWindow(GetDlgItem(hWnd, IDC_EF), val);
00139 }
00140 
00141 void enableChooserControls(HWND hWnd, BOOL val) {
00142   EnableWindow(GetDlgItem(hWnd, IDC_LIST_EXPORT), val);
00143   EnableWindow(GetDlgItem(hWnd, IDC_ADD_EXPORT), val);
00144   EnableWindow(GetDlgItem(hWnd, IDC_REMOVE_EXPORT), val);
00145 }
00146 
00147 
00148 #define ANIM_RAD_NONE 0
00149 #define ANIM_RAD_EXPALL 1
00150 #define ANIM_RAD_EXPSEL 2
00151 #define ANIM_RAD_ALL    3
00152 void enableAnimRadios(HWND hWnd, int mask) {
00153   EnableWindow(GetDlgItem(hWnd, IDC_EXP_ALL_FRAMES), mask & ANIM_RAD_EXPALL);
00154   EnableWindow(GetDlgItem(hWnd, IDC_EXP_SEL_FRAMES), mask & ANIM_RAD_EXPSEL);
00155 }
00156 
00157 // Handles the work of actually picking the target.
00158 class AddNodeCB : public HitByNameDlgCallback
00159 {
00160 public:
00161   MaxOptionsDialog *ph; //Pointer to the parent class
00162   HWND hWnd;            //Handle to the parent dialog
00163 
00164   AddNodeCB (MaxOptionsDialog *instance, HWND wnd) : 
00165     ph(instance), hWnd(wnd) {}
00166 
00167   virtual TCHAR *dialogTitle() {return _T("Objects to Export");}
00168   virtual TCHAR *buttonText()  {return _T("Select");}
00169   virtual int filter(INode *node);
00170   virtual void proc(INodeTab &nodeTab);
00171 };
00172 
00173 //This tells what should be in the list
00174 //Allow only triangular objects, nurbs, and joints
00175 int AddNodeCB::filter(INode *node) {
00176   if (!node) return 0;
00177   
00178   Object *obj = node->EvalWorldState(0).obj;
00179   Control *c = node->GetTMController();
00180   NURBSSet getSet;
00181   bool is_bone = (node->GetBoneNodeOnOff() ||     //True for bones
00182      (c &&                                          //True for bipeds
00183      ((c->ClassID() == BIPSLAVE_CONTROL_CLASS_ID) ||
00184      (c->ClassID() == BIPBODY_CONTROL_CLASS_ID) ||
00185      (c->ClassID() == FOOTPRINT_CLASS_ID))));
00186 
00187   
00188   if (IsDlgButtonChecked(hWnd, IDC_ANIMATION) == BST_CHECKED)
00189     return is_bone && !ph->FindNode(node->GetHandle());
00190   else
00191     return (
00192     is_bone || ((obj->SuperClassID() == HELPER_CLASS_ID && obj->ClassID() != MaxEggPlugin_CLASS_ID)) ||
00193     ((obj->SuperClassID() == GEOMOBJECT_CLASS_ID && //Allow geometrics
00194       obj->CanConvertToType(Class_ID(TRIOBJ_CLASS_ID, 0))) ||
00195      (obj->SuperClassID() == SHAPE_CLASS_ID &&      //Allow CV NURBS
00196       obj->ClassID() == EDITABLE_SURF_CLASS_ID &&
00197       GetNURBSSet(obj, 0, getSet, TRUE) &&
00198       getSet.GetNURBSObject(0)->GetType() == kNCVCurve)) &&
00199     !ph->FindNode(node->GetHandle()));             //Only allow items not already selected
00200 }
00201 
00202 //Adds all of the selected items to the list
00203 void AddNodeCB::proc(INodeTab &nodeTab) {
00204 
00205   for (int i = 0; i < nodeTab.Count(); i++)
00206     ph->AddNode(nodeTab[i]->GetHandle());
00207   ph->RefreshNodeList(hWnd);
00208 }
00209 
00210 //This callback class generates a list of nodes that have previously been selected
00211 class RemoveNodeCB : public HitByNameDlgCallback
00212 {
00213 public:
00214     MaxOptionsDialog *ph; //Pointer to the parent class
00215     HWND hWnd;            //Handle to the parent dialog
00216     
00217     RemoveNodeCB (MaxOptionsDialog *instance, HWND wnd) : 
00218         ph(instance), hWnd(wnd) {}
00219     
00220     virtual TCHAR *dialogTitle() {return _T("Objects to Remove");}
00221     virtual TCHAR *buttonText()  {return _T("Remove");}
00222     virtual int filter(INode *node) {return (node && ph->FindNode(node->GetHandle()));}
00223     virtual void proc(INodeTab &nodeTab);
00224 };
00225 
00226 
00227 //Adds all of the selected items to the list
00228 void RemoveNodeCB::proc(INodeTab &nodeTab) {
00229     for (int i = 0; i < nodeTab.Count(); i++)
00230         ph->RemoveNodeByHandle(nodeTab[i]->GetHandle());
00231     ph->RefreshNodeList(hWnd);
00232 }
00233 
00234 MaxEggOptions::MaxEggOptions() {
00235     _max_interface = NULL;
00236     _anim_type = MaxEggOptions::AT_model;
00237     _start_frame = INT_MIN;
00238     _end_frame = INT_MIN;
00239     _double_sided = false;
00240 
00241 
00242     _file_name[0]=0;
00243     _short_name[0]=0;
00244     _path_replace = new PathReplace;
00245     _path_replace->_path_store = PS_relative;
00246     _export_whole_scene = true;
00247     _export_all_frames = true;
00248     _successful = false;
00249 }
00250 
00251 INT_PTR CALLBACK MaxOptionsDialogProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ) 
00252 {
00253     char tempFilename[2048];
00254     //We pass in our plugin through the lParam variable. Let's convert it back.
00255     MaxOptionsDialog *imp = (MaxOptionsDialog*)GetWindowLongPtr(hWnd,GWLP_USERDATA); 
00256     if ( !imp && message != WM_INITDIALOG ) return FALSE;
00257 
00258     switch(message) {
00259 
00260     case WM_INITDIALOG:
00261         // this line is very necessary to pass the plugin as the lParam
00262         SetWindowLongPtr(hWnd,GWLP_USERDATA,lParam); 
00263         ((MaxOptionsDialog*)lParam)->UpdateUI(hWnd);
00264 
00265         return TRUE; break;
00266         
00267     case WM_CLOSE:
00268         EndDialog(hWnd, FALSE);
00269         return TRUE; break;
00270         
00271     case WM_COMMAND:
00272         //The modified control is found in the lower word of the wParam long.
00273         switch( LOWORD(wParam) ) {
00274         case IDC_MODEL:
00275             if (HIWORD(wParam) == BN_CLICKED) {
00276                 SetWindowText(GetDlgItem(hWnd, IDC_EXPORT_SELECTED),
00277                               "Export Meshes:");
00278                 enableAnimRadios(hWnd, ANIM_RAD_NONE);
00279                 showAnimControls(hWnd, TRUE);
00280                 enableAnimControls(hWnd, FALSE);
00281                 if (imp->_prev_type == MaxEggOptions::AT_chan) imp->ClearNodeList(hWnd);
00282                 imp->_prev_type = MaxEggOptions::AT_model;
00283 
00284                 return TRUE;
00285             }
00286             break;
00287             
00288         case IDC_ANIMATION:
00289             if (HIWORD(wParam) == BN_CLICKED) {
00290                 SetWindowText(GetDlgItem(hWnd, IDC_EXPORT_SELECTED),
00291                               "Export Bones:");
00292                 enableAnimRadios(hWnd, ANIM_RAD_ALL);
00293                 showAnimControls(hWnd, TRUE);
00294                 enableAnimControls(hWnd, IsDlgButtonChecked(hWnd, IDC_EXP_SEL_FRAMES));
00295                 if (imp->_prev_type != MaxEggOptions::AT_chan) imp->ClearNodeList(hWnd);
00296                 imp->_prev_type = MaxEggOptions::AT_chan;
00297                 CheckRadioButton(hWnd, IDC_EXP_ALL_FRAMES, IDC_EXP_SEL_FRAMES, IDC_EXP_ALL_FRAMES);
00298 
00299                 return TRUE;
00300             }
00301             break;
00302         case IDC_BOTH:
00303             if (HIWORD(wParam) == BN_CLICKED) {
00304                 SetWindowText(GetDlgItem(hWnd, IDC_EXPORT_SELECTED),
00305                               "Export Models:");
00306                 enableAnimRadios(hWnd, ANIM_RAD_ALL);
00307                 showAnimControls(hWnd, TRUE);
00308                 enableAnimControls(hWnd, IsDlgButtonChecked(hWnd, IDC_EXP_SEL_FRAMES));
00309                 if (imp->_prev_type == MaxEggOptions::AT_chan) imp->ClearNodeList(hWnd);
00310                 imp->_prev_type = MaxEggOptions::AT_both;
00311                 CheckRadioButton(hWnd, IDC_EXP_ALL_FRAMES, IDC_EXP_SEL_FRAMES, IDC_EXP_ALL_FRAMES);
00312 
00313                 return TRUE;
00314             }
00315             break;
00316         case IDC_POSE:
00317             if (HIWORD(wParam) == BN_CLICKED) {
00318                 SetWindowText(GetDlgItem(hWnd, IDC_EXPORT_SELECTED),
00319                               "Export Meshes:");
00320                 enableAnimRadios(hWnd, ANIM_RAD_EXPSEL);
00321                 showAnimControls(hWnd, FALSE);
00322                 enableAnimControls(hWnd, TRUE);
00323                 CheckRadioButton(hWnd, IDC_EXP_ALL_FRAMES, IDC_EXP_SEL_FRAMES, IDC_EXP_SEL_FRAMES);
00324                 if (imp->_prev_type == MaxEggOptions::AT_chan) imp->ClearNodeList(hWnd);
00325                 imp->_prev_type = MaxEggOptions::AT_pose;
00326 
00327                 return TRUE;
00328             }
00329             break;
00330         case IDC_EXP_ALL_FRAMES:
00331             if (HIWORD(wParam) == BN_CLICKED) {
00332                 enableAnimControls(hWnd, FALSE);
00333                 if(imp->_prev_type == MaxEggOptions::AT_chan)
00334                 {
00335                   CheckRadioButton(hWnd, IDC_MODEL, IDC_POSE, IDC_ANIMATION);
00336                 }
00337                 if(imp->_prev_type == MaxEggOptions::AT_both)
00338                 {
00339                   CheckRadioButton(hWnd, IDC_MODEL, IDC_POSE, IDC_BOTH);
00340                 }
00341                 return TRUE;
00342             }
00343             break;
00344             
00345         case IDC_EXP_SEL_FRAMES:
00346             if (HIWORD(wParam) == BN_CLICKED) {
00347                 enableAnimControls(hWnd, TRUE);
00348                 if(imp->_prev_type == MaxEggOptions::AT_chan)
00349                 {
00350                   CheckRadioButton(hWnd, IDC_MODEL, IDC_POSE, IDC_ANIMATION);
00351                 }
00352                 if(imp->_prev_type == MaxEggOptions::AT_both)
00353                 {
00354                   CheckRadioButton(hWnd, IDC_MODEL, IDC_POSE, IDC_BOTH);
00355                 }
00356                 return TRUE;
00357             }
00358             break;
00359 
00360         case IDC_EXPORT_ALL:
00361             if (HIWORD(wParam) == BN_CLICKED) {
00362                 enableChooserControls(hWnd, FALSE);
00363                 return TRUE;
00364             }
00365             break;
00366             
00367         case IDC_EXPORT_SELECTED:
00368             if (HIWORD(wParam) == BN_CLICKED) {
00369                 enableChooserControls(hWnd, TRUE);
00370                 return TRUE;
00371             }
00372             break;
00373 
00374 
00375         // deal with adding meshes
00376         case IDC_ADD_EXPORT:
00377             {
00378                 if (!imp->_choosing_nodes) {
00379                     AddNodeCB PickCB(imp, hWnd);
00380                     imp->_choosing_nodes = true;
00381                     imp->_max_interface->DoHitByNameDialog(&PickCB);
00382                     imp->_choosing_nodes = false;
00383                 }
00384             }
00385             return TRUE; break;
00386 
00387         case IDC_REMOVE_EXPORT:
00388             {
00389                 if (!imp->_choosing_nodes) {
00390                     imp->_choosing_nodes = true;
00391                     RemoveNodeCB PickCB(imp, hWnd);
00392                     imp->_max_interface->DoHitByNameDialog(&PickCB);
00393                     imp->_choosing_nodes = false;
00394                 }
00395             }
00396             return TRUE; break;
00397 
00398         case IDC_OK:
00399             if (imp->UpdateFromUI(hWnd)) EndDialog(hWnd, TRUE);
00400             return TRUE; break;
00401         case IDC_CANCEL:
00402             EndDialog(hWnd, FALSE);
00403             return TRUE; break;
00404         case IDC_BROWSE:
00405             OPENFILENAME ofn;
00406             strcpy(tempFilename, GetICustEditT(GetDlgItem(hWnd, IDC_FILENAME)));
00407             
00408             memset(&ofn, 0, sizeof(ofn));
00409             ofn.nMaxFile = 2047;
00410             ofn.lpstrFile = tempFilename;
00411             ofn.lStructSize = sizeof(ofn);
00412             ofn.hwndOwner = hWnd;
00413             ofn.Flags = OFN_HIDEREADONLY | OFN_NOREADONLYRETURN | OFN_PATHMUSTEXIST;
00414             ofn.lpstrDefExt = "egg";
00415             ofn.lpstrFilter = "Panda3D Egg Files (*.egg)\0*.egg\0All Files (*.*)\0*.*\0";
00416             
00417             SetFocus(GetDlgItem(hWnd, IDC_FILENAME));
00418             if (GetSaveFileName(&ofn))
00419                 SetICustEdit(hWnd, IDC_FILENAME, ofn.lpstrFile);
00420             //else {
00421             //  char buf[255];
00422             //  sprintf(buf, "%d", CommDlgExtendedError());
00423             //  MessageBox(hWnd, buf, "Error on GetSaveFileName", MB_OK);
00424             //}
00425             return TRUE; break;
00426         case IDC_CHECK1:
00427             if (IsDlgButtonChecked(hWnd, IDC_CHECK1))
00428                 if (MessageBox(hWnd, "Warning: Exporting double-sided polygons can severely hurt "
00429                                "performance in Panda3D.\n\nAre you sure you want to export them?",
00430                                "Panda3D Exporter", MB_YESNO | MB_ICONQUESTION) != IDYES)
00431                     CheckDlgButton(hWnd, IDC_CHECK1, BST_UNCHECKED);
00432             return TRUE; break;
00433 
00434         default:
00435             //char buf[255];
00436             //sprintf(buf, "%d", LOWORD(wParam));
00437             //MessageBox(hWnd, buf, "Unknown WParam", MB_OK);
00438             break;
00439         }
00440     }
00441     return FALSE;
00442 }
00443 
00444 void MaxOptionsDialog::SetAnimRange() {
00445     // Get the start and end frames and the animation frame rate from Max
00446     Interval anim_range = _max_interface->GetAnimRange();
00447     _min_frame = anim_range.Start()/GetTicksPerFrame();
00448     _max_frame = anim_range.End()/GetTicksPerFrame();
00449 }
00450 
00451 MaxOptionsDialog::MaxOptionsDialog() :
00452     MaxEggOptions(),
00453     _min_frame(0),
00454     _max_frame(0),
00455     _checked(true),
00456     _choosing_nodes(false),
00457     _prev_type(AT_model)
00458 {
00459 }
00460 
00461 MaxOptionsDialog::~MaxOptionsDialog ()
00462 {
00463 }
00464 
00465 
00466 void MaxOptionsDialog::UpdateUI(HWND hWnd) {
00467     int typeButton = IDC_MODEL;
00468     int anim_exp = _export_all_frames ? IDC_EXP_ALL_FRAMES : IDC_EXP_SEL_FRAMES;
00469     int model_exp = _export_whole_scene ? IDC_EXPORT_ALL : IDC_EXPORT_SELECTED;
00470     
00471     switch (_anim_type) {
00472     case MaxEggOptions::AT_chan:  typeButton = IDC_ANIMATION; break;
00473     case MaxEggOptions::AT_both:  typeButton = IDC_BOTH; break;
00474     case MaxEggOptions::AT_pose:  typeButton = IDC_POSE; break;
00475     case MaxEggOptions::AT_model: typeButton = IDC_MODEL; break;
00476     }
00477     
00478     _prev_type = _anim_type;
00479 
00480     CheckRadioButton(hWnd, IDC_MODEL, IDC_POSE, typeButton);
00481     SendMessage(hWnd, WM_COMMAND, MAKEWPARAM(typeButton, BN_CLICKED), 0);
00482     CheckRadioButton(hWnd, IDC_EXPORT_ALL, IDC_EXPORT_SELECTED, model_exp);
00483     SendMessage(hWnd, WM_COMMAND, MAKEWPARAM(model_exp, BN_CLICKED), 0);
00484     CheckRadioButton(hWnd, IDC_EXP_ALL_FRAMES, IDC_EXP_SEL_FRAMES, anim_exp);
00485     SendMessage(hWnd, WM_COMMAND, MAKEWPARAM(anim_exp, BN_CLICKED), 0);
00486     
00487     CheckDlgButton(hWnd, IDC_CHECK1,
00488                    _double_sided ? BST_CHECKED : BST_UNCHECKED);
00489 
00490     
00491     SetICustEdit(hWnd, IDC_FILENAME, _file_name);
00492     if (_start_frame != INT_MIN) {
00493         SetICustEdit(hWnd, IDC_SF, _start_frame);
00494         SetICustEdit(hWnd, IDC_EF, _end_frame);
00495     } else {
00496         SetICustEdit(hWnd, IDC_SF, _min_frame);
00497         SetICustEdit(hWnd, IDC_EF, _max_frame);
00498     }
00499     
00500     RefreshNodeList(hWnd);
00501 }
00502 
00503 void MaxOptionsDialog::ClearNodeList(HWND hWnd) {
00504     _node_list.clear();
00505     RefreshNodeList(hWnd);
00506 }
00507 
00508 void MaxOptionsDialog::RefreshNodeList(HWND hWnd) {
00509   //Clear and repopulate the node box
00510   HWND nodeLB = GetDlgItem(hWnd, IDC_LIST_EXPORT);
00511   SendMessage(nodeLB, LB_RESETCONTENT, 0, 0);
00512   for (int i = 0; i < _node_list.size(); i++) {
00513       INode *temp = _max_interface->GetINodeByHandle(_node_list[i]);
00514       TCHAR *name = _T("Unknown Node");
00515       if (temp) name = temp->GetName();
00516       SendMessage(nodeLB, LB_ADDSTRING, 0, (LPARAM)name);
00517   }
00518 }
00519 
00520 bool MaxOptionsDialog::UpdateFromUI(HWND hWnd) {
00521   BOOL valid;
00522   Anim_Type newAnimType;
00523   int newSF = INT_MIN, newEF = INT_MIN;
00524   char msg[1024];
00525 
00526   if (IsDlgButtonChecked(hWnd, IDC_MODEL))          newAnimType = MaxEggOptions::AT_model;
00527   else if (IsDlgButtonChecked(hWnd, IDC_ANIMATION)) newAnimType = MaxEggOptions::AT_chan;
00528   else if (IsDlgButtonChecked(hWnd, IDC_BOTH))      newAnimType = MaxEggOptions::AT_both;
00529   else                                              newAnimType = MaxEggOptions::AT_pose;
00530 
00531   if (newAnimType != MaxEggOptions::AT_model && IsDlgButtonChecked(hWnd, IDC_EXP_SEL_FRAMES)) {
00532       newSF = GetICustEditI(GetDlgItem(hWnd, IDC_SF), &valid);
00533       if (!valid) {
00534           MessageBox(hWnd, "Start Frame must be an integer", "Invalid Value", MB_OK | MB_ICONEXCLAMATION);
00535           return false;
00536       }
00537       if (newSF < _min_frame) {
00538           sprintf(msg, "Start Frame must be at least %d", _min_frame);
00539           MessageBox(hWnd, msg, "Invalid Value", MB_OK | MB_ICONEXCLAMATION);
00540           return false;
00541       }
00542       if (newSF > _max_frame) {
00543           sprintf(msg, "Start Frame must be at most %d", _max_frame);
00544           MessageBox(hWnd, msg, "Invalid Value", MB_OK | MB_ICONEXCLAMATION);
00545           return false;
00546       }
00547       if (newAnimType != MaxEggOptions::AT_pose) {
00548           newEF = GetICustEditI(GetDlgItem(hWnd, IDC_EF), &valid);
00549           if (!valid) {
00550               MessageBox(hWnd, "End Frame must be an integer", "Invalid Value", MB_OK | MB_ICONEXCLAMATION);
00551               return false;
00552           }
00553           if (newEF > _max_frame) {
00554               sprintf(msg, "End Frame must be at most %d", _max_frame);
00555               MessageBox(hWnd, msg, "Invalid Value", MB_OK | MB_ICONEXCLAMATION);
00556               return false;
00557           }
00558           if (newEF < newSF) {
00559               MessageBox(hWnd, "End Frame must be greater than the start frame", "Invalid Value", MB_OK | MB_ICONEXCLAMATION);
00560               return false;
00561           }
00562       }
00563   }
00564 
00565   char *temp = GetICustEditT(GetDlgItem(hWnd, IDC_FILENAME));
00566   if (!strlen(temp)) {
00567     MessageBox(hWnd, "The filename cannot be empty", "Invalid Value", MB_OK | MB_ICONEXCLAMATION);
00568     return false;
00569   }
00570 
00571   if (strlen(temp) < 4 || strncmp(".egg", temp+(strlen(temp) - 4), 4))
00572       sprintf(_file_name, "%s.egg", temp);
00573   else strcpy(_file_name, temp);
00574 
00575   temp = strrchr(_file_name, '\\');
00576   if (!temp) temp = _file_name;
00577   else temp++;
00578 
00579   if (strlen(temp) > sizeof(_short_name))
00580     sprintf(_short_name, "%.*s...", sizeof(_short_name)-4, temp);
00581   else {
00582     strcpy(_short_name, temp);
00583     _short_name[strlen(_short_name) - 4] = NULL; //Cut off the .egg
00584   }
00585   
00586   _start_frame = newSF;
00587   _end_frame = newEF;
00588   _anim_type = newAnimType;
00589   _double_sided = IsDlgButtonChecked(hWnd, IDC_CHECK1);
00590 
00591 
00592   _export_whole_scene = IsDlgButtonChecked(hWnd, IDC_EXPORT_ALL);
00593   _export_all_frames = IsDlgButtonChecked(hWnd, IDC_EXP_ALL_FRAMES);
00594 
00595   return true;
00596 }
00597 
00598 bool MaxOptionsDialog::FindNode(ULONG INodeHandle) {
00599     for (int i = 0; i < _node_list.size(); i++) 
00600         if (_node_list[i] == INodeHandle) return true;
00601     return false;
00602 }
00603 
00604 void MaxOptionsDialog::AddNode(ULONG INodeHandle) {
00605   if (FindNode(INodeHandle)) return; 
00606   _node_list.push_back(INodeHandle);
00607 }
00608 
00609 void MaxOptionsDialog::CullBadNodes() {
00610   if (!_max_interface) return;
00611   std::vector<ULONG> good;
00612   for (int i=0; i<_node_list.size(); i++) {
00613       ULONG handle = _node_list[i];
00614       if (_max_interface->GetINodeByHandle(handle)) {
00615           good.push_back(handle);
00616       }
00617   }
00618   _node_list = good;
00619 }
00620 
00621 void MaxOptionsDialog::RemoveNode(int i) {
00622     if (i >= 0 && i < _node_list.size()) {
00623         for (int j = i+1; j < _node_list.size(); j++)
00624             _node_list[i++] = _node_list[j++];
00625         _node_list.pop_back();
00626     }
00627 }
00628 
00629 void MaxOptionsDialog::RemoveNodeByHandle(ULONG INodeHandle) {
00630     for (int i = 0; i < _node_list.size(); i++) {
00631         if (_node_list[i] == INodeHandle) {
00632             RemoveNode(i);
00633             return;
00634         }
00635     }
00636 }
00637 
00638 IOResult MaxOptionsDialog::Save(ISave *isave) {
00639     isave->BeginChunk(CHUNK_EGG_EXP_OPTIONS);
00640     ChunkSave(isave, CHUNK_ANIM_TYPE, _anim_type);
00641     ChunkSave(isave, CHUNK_FILENAME, _file_name);
00642     ChunkSave(isave, CHUNK_SHORTNAME, _short_name);
00643     ChunkSave(isave, CHUNK_SF, _start_frame);
00644     ChunkSave(isave, CHUNK_EF, _end_frame);
00645     ChunkSave(isave, CHUNK_DBL_SIDED, _double_sided);
00646     ChunkSave(isave, CHUNK_EGG_CHECKED, _checked);
00647     ChunkSave(isave, CHUNK_ALL_FRAMES, _export_all_frames);
00648     ChunkSave(isave, CHUNK_EXPORT_FULL, _export_whole_scene);
00649     
00650     isave->BeginChunk(CHUNK_NODE_LIST);
00651     for (int i = 0; i < _node_list.size(); i++)
00652         ChunkSave(isave, CHUNK_NODE_HANDLE, _node_list[i]);
00653     isave->EndChunk();
00654     isave->EndChunk();
00655     return IO_OK;
00656 } 
00657 
00658 IOResult MaxOptionsDialog::Load(ILoad *iload) {
00659     IOResult res = iload->OpenChunk();
00660     
00661     while (res == IO_OK) {
00662         switch(iload->CurChunkID()) {
00663         case CHUNK_ANIM_TYPE: _anim_type = (Anim_Type)ChunkLoadInt(iload); break;
00664         case CHUNK_FILENAME: ChunkLoadString(iload, _file_name, sizeof(_file_name)); break;
00665         case CHUNK_SHORTNAME: ChunkLoadString(iload, _short_name, sizeof(_short_name)); break;
00666         case CHUNK_SF: _start_frame = ChunkLoadInt(iload); break;
00667         case CHUNK_EF: _end_frame = ChunkLoadInt(iload); break;
00668         case CHUNK_DBL_SIDED: _double_sided = ChunkLoadBool(iload); break;
00669         case CHUNK_EGG_CHECKED: _checked = ChunkLoadBool(iload); break;
00670         case CHUNK_ALL_FRAMES: _export_all_frames = ChunkLoadBool(iload); break;
00671         case CHUNK_EXPORT_FULL: _export_whole_scene = ChunkLoadBool(iload); break;
00672         
00673         case CHUNK_NODE_LIST:
00674             res = iload->OpenChunk();
00675             while (res == IO_OK) {
00676                 if (iload->CurChunkID() == CHUNK_NODE_HANDLE) AddNode(ChunkLoadULONG(iload));
00677                 iload->CloseChunk();
00678                 res = iload->OpenChunk();
00679             }
00680             break;
00681         }
00682         iload->CloseChunk();
00683         res = iload->OpenChunk();
00684     }
00685     
00686     if (res == IO_END) return IO_OK;
00687     return IO_ERROR;
00688 }
00689 
 All Classes Functions Variables Enumerations