Panda3D
maxOptionsDialog.cxx
1 /*
2  maxEggExpOptions.cxx
3  Created by Phillip Saltzman, 2/15/05
4  Carnegie Mellon University, Entetainment Technology Center
5 
6  This file implements the classes that are used to choose
7  what to export from 3D Studio max
8 
9  Updated by Fei Wang, Carnegie Mellon University Entertainment
10  Technology Center student, 14Aug2009: added enableAddCollisionChoices
11 */
12 
13 #include "maxEgg.h"
14 
15 // Disable the forcing int to true or false performance warning
16 #pragma warning(disable: 4800)
17 
18 void SetICustEdit(HWND wnd, int nIDDlgItem, TCHAR *text)
19 {
20  ICustEdit *edit = GetICustEdit(GetDlgItem(wnd, nIDDlgItem));
21  edit->SetText(text);
22  ReleaseICustEdit(edit);
23 }
24 
25 void SetICustEdit(HWND wnd, int nIDDlgItem, int n)
26 {
27  TCHAR text[80];
28  _stprintf(text, _T("%d"), n);
29  ICustEdit *edit = GetICustEdit(GetDlgItem(wnd, nIDDlgItem));
30  edit->SetText(text);
31  ReleaseICustEdit(edit);
32 }
33 
34 TCHAR *GetICustEditT(HWND wnd)
35 {
36  static TCHAR buffer[2084];
37  ICustEdit *edit = GetICustEdit(wnd);
38  edit->GetText(buffer, 2084);
39  ReleaseICustEdit(edit);
40  return buffer;
41 }
42 
43 int GetICustEditI(HWND wnd, BOOL *valid)
44 {
45  ICustEdit *edit = GetICustEdit(wnd);
46  int i = edit->GetInt(valid);
47  ReleaseICustEdit(edit);
48  return i;
49 }
50 
51 void ChunkSave(ISave *isave, int chunkid, int value)
52 {
53  ULONG nb;
54  isave->BeginChunk(chunkid);
55  isave->Write(&value, sizeof(int), &nb);
56  isave->EndChunk();
57 }
58 
59 void ChunkSave(ISave *isave, int chunkid, ULONG value)
60 {
61  ULONG nb;
62  isave->BeginChunk(chunkid);
63  isave->Write(&value, sizeof(ULONG), &nb);
64  isave->EndChunk();
65 }
66 
67 void ChunkSave(ISave *isave, int chunkid, bool value)
68 {
69  ULONG nb;
70  isave->BeginChunk(chunkid);
71  isave->Write(&value, sizeof(bool), &nb);
72  isave->EndChunk();
73 }
74 
75 void ChunkSave(ISave *isave, int chunkid, TCHAR *value)
76 {
77  ULONG nb;
78  isave->BeginChunk(chunkid);
79  int length = _tcslen(value) + 1;
80  isave->Write(&length, sizeof(int), &nb);
81  isave->Write(value, length * sizeof(TCHAR), &nb);
82  isave->EndChunk();
83 }
84 
85 TCHAR *ChunkLoadString(ILoad *iload, TCHAR *buffer, int maxLength)
86 {
87  ULONG nb;
88  int length;
89  IOResult res;
90  res = iload->Read(&length, sizeof(int), &nb);
91  assert(res == IO_OK && length <= maxLength);
92  res = iload->Read(buffer, length * sizeof(TCHAR), &nb);
93  assert(res == IO_OK);
94  return buffer;
95 }
96 
97 int ChunkLoadInt(ILoad *iload)
98 {
99  ULONG nb;
100  int value;
101  IOResult res;
102  res = iload->Read(&value, sizeof(int), &nb);
103  assert(res == IO_OK);
104  return value;
105 }
106 
107 int ChunkLoadULONG(ILoad *iload)
108 {
109  ULONG nb, value;
110  IOResult res;
111  res = iload->Read(&value, sizeof(ULONG), &nb);
112  assert(res == IO_OK);
113  return value;
114 }
115 
116 bool ChunkLoadBool(ILoad *iload)
117 {
118  ULONG nb;
119  bool value;
120  IOResult res;
121  res = iload->Read(&value, sizeof(bool), &nb);
122  assert(res == IO_OK);
123  return value;
124 }
125 
126 void showAnimControls(HWND hWnd, BOOL val) {
127  ShowWindow(GetDlgItem(hWnd, IDC_EF_LABEL), val);
128  ShowWindow(GetDlgItem(hWnd, IDC_EF), val);
129  ShowWindow(GetDlgItem(hWnd, IDC_SF_LABEL), val);
130  SetWindowText(GetDlgItem(hWnd, IDC_EXP_SEL_FRAMES),
131  val ? _T("Use Range:") : _T("Use Frame:"));
132 }
133 
134 void enableAnimControls(HWND hWnd, BOOL val) {
135  EnableWindow(GetDlgItem(hWnd, IDC_SF_LABEL), val);
136  EnableWindow(GetDlgItem(hWnd, IDC_SF), val);
137  EnableWindow(GetDlgItem(hWnd, IDC_EF_LABEL), val);
138  EnableWindow(GetDlgItem(hWnd, IDC_EF), val);
139 }
140 
141 void enableChooserControls(HWND hWnd, BOOL val) {
142  EnableWindow(GetDlgItem(hWnd, IDC_LIST_EXPORT), val);
143  EnableWindow(GetDlgItem(hWnd, IDC_ADD_EXPORT), val);
144  EnableWindow(GetDlgItem(hWnd, IDC_REMOVE_EXPORT), val);
145 }
146 
147 
148 #define ANIM_RAD_NONE 0
149 #define ANIM_RAD_EXPALL 1
150 #define ANIM_RAD_EXPSEL 2
151 #define ANIM_RAD_ALL 3
152 void enableAnimRadios(HWND hWnd, int mask) {
153  EnableWindow(GetDlgItem(hWnd, IDC_EXP_ALL_FRAMES), mask & ANIM_RAD_EXPALL);
154  EnableWindow(GetDlgItem(hWnd, IDC_EXP_SEL_FRAMES), mask & ANIM_RAD_EXPSEL);
155 }
156 
157 // Handles the work of actually picking the target.
158 class AddNodeCB : public HitByNameDlgCallback
159 {
160 public:
161  MaxOptionsDialog *ph; //Pointer to the parent class
162  HWND hWnd; //Handle to the parent dialog
163 
164  AddNodeCB (MaxOptionsDialog *instance, HWND wnd) :
165  ph(instance), hWnd(wnd) {}
166 
167 #if MAX_VERSION_MAJOR < 15
168  virtual TCHAR *dialogTitle() {return _T("Objects to Export");}
169  virtual TCHAR *buttonText() {return _T("Select");}
170 #else
171  virtual const MCHAR *dialogTitle() {return _M("Objects to Export");}
172  virtual const MCHAR *buttonText() {return _M("Select");}
173 #endif
174 
175  virtual int filter(INode *node);
176  virtual void proc(INodeTab &nodeTab);
177 };
178 
179 // This tells what should be in the list Allow only triangular objects, nurbs,
180 // and joints
181 int AddNodeCB::filter(INode *node) {
182  if (!node) return 0;
183 
184  Object *obj = node->EvalWorldState(0).obj;
185  Control *c = node->GetTMController();
186  NURBSSet getSet;
187  bool is_bone = (node->GetBoneNodeOnOff() || //True for bones
188  (c && //True for bipeds
189  ((c->ClassID() == BIPSLAVE_CONTROL_CLASS_ID) ||
190  (c->ClassID() == BIPBODY_CONTROL_CLASS_ID) ||
191  (c->ClassID() == FOOTPRINT_CLASS_ID))));
192 
193 
194  if (IsDlgButtonChecked(hWnd, IDC_ANIMATION) == BST_CHECKED)
195  return is_bone && !ph->FindNode(node->GetHandle());
196  else
197  return (
198  is_bone || ((obj->SuperClassID() == HELPER_CLASS_ID && obj->ClassID() != MaxEggPlugin_CLASS_ID)) ||
199  ((obj->SuperClassID() == GEOMOBJECT_CLASS_ID && //Allow geometrics
200  obj->CanConvertToType(Class_ID(TRIOBJ_CLASS_ID, 0))) ||
201  (obj->SuperClassID() == SHAPE_CLASS_ID && //Allow CV NURBS
202  obj->ClassID() == EDITABLE_SURF_CLASS_ID &&
203  GetNURBSSet(obj, 0, getSet, TRUE) &&
204  getSet.GetNURBSObject(0)->GetType() == kNCVCurve)) &&
205  !ph->FindNode(node->GetHandle())); //Only allow items not already selected
206 }
207 
208 // Adds all of the selected items to the list
209 void AddNodeCB::proc(INodeTab &nodeTab) {
210 
211  for (int i = 0; i < nodeTab.Count(); i++)
212  ph->AddNode(nodeTab[i]->GetHandle());
213  ph->RefreshNodeList(hWnd);
214 }
215 
216 // This callback class generates a list of nodes that have previously been
217 // selected
218 class RemoveNodeCB : public HitByNameDlgCallback
219 {
220 public:
221  MaxOptionsDialog *ph; //Pointer to the parent class
222  HWND hWnd; //Handle to the parent dialog
223 
224  RemoveNodeCB (MaxOptionsDialog *instance, HWND wnd) :
225  ph(instance), hWnd(wnd) {}
226 
227 #if MAX_VERSION_MAJOR < 15
228  virtual TCHAR *dialogTitle() {return _T("Objects to Remove");}
229  virtual TCHAR *buttonText() {return _T("Remove");}
230 #else
231  virtual const MCHAR *dialogTitle() {return _M("Objects to Remove");}
232  virtual const MCHAR *buttonText() {return _M("Remove");}
233 #endif
234 
235  virtual int filter(INode *node) {return (node && ph->FindNode(node->GetHandle()));}
236  virtual void proc(INodeTab &nodeTab);
237 };
238 
239 
240 // Adds all of the selected items to the list
241 void RemoveNodeCB::proc(INodeTab &nodeTab) {
242  for (int i = 0; i < nodeTab.Count(); i++)
243  ph->RemoveNodeByHandle(nodeTab[i]->GetHandle());
244  ph->RefreshNodeList(hWnd);
245 }
246 
247 MaxEggOptions::MaxEggOptions() {
248  _max_interface = nullptr;
249  _anim_type = MaxEggOptions::AT_model;
250  _start_frame = INT_MIN;
251  _end_frame = INT_MIN;
252  _double_sided = false;
253 
254 
255  _file_name[0]=0;
256  _short_name[0]=0;
257  _path_replace = new PathReplace;
258  _path_replace->_path_store = PS_relative;
259  _export_whole_scene = true;
260  _export_all_frames = true;
261  _successful = false;
262 }
263 
264 INT_PTR CALLBACK MaxOptionsDialogProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
265 {
266  TCHAR tempFilename[2048];
267  // We pass in our plugin through the lParam variable. Let's convert it
268  // back.
269  MaxOptionsDialog *imp = (MaxOptionsDialog*)GetWindowLongPtr(hWnd,GWLP_USERDATA);
270  if ( !imp && message != WM_INITDIALOG ) return FALSE;
271 
272  switch(message) {
273 
274  case WM_INITDIALOG:
275  // this line is very necessary to pass the plugin as the lParam
276  SetWindowLongPtr(hWnd,GWLP_USERDATA,lParam);
277  ((MaxOptionsDialog*)lParam)->UpdateUI(hWnd);
278 
279  return TRUE; break;
280 
281  case WM_CLOSE:
282  EndDialog(hWnd, FALSE);
283  return TRUE; break;
284 
285  case WM_COMMAND:
286  // The modified control is found in the lower word of the wParam long.
287  switch( LOWORD(wParam) ) {
288  case IDC_MODEL:
289  if (HIWORD(wParam) == BN_CLICKED) {
290  SetWindowText(GetDlgItem(hWnd, IDC_EXPORT_SELECTED),
291  _T("Export Meshes:"));
292  enableAnimRadios(hWnd, ANIM_RAD_NONE);
293  showAnimControls(hWnd, TRUE);
294  enableAnimControls(hWnd, FALSE);
295  if (imp->_prev_type == MaxEggOptions::AT_chan) imp->ClearNodeList(hWnd);
296  imp->_prev_type = MaxEggOptions::AT_model;
297 
298  return TRUE;
299  }
300  break;
301 
302  case IDC_ANIMATION:
303  if (HIWORD(wParam) == BN_CLICKED) {
304  SetWindowText(GetDlgItem(hWnd, IDC_EXPORT_SELECTED),
305  _T("Export Bones:"));
306  enableAnimRadios(hWnd, ANIM_RAD_ALL);
307  showAnimControls(hWnd, TRUE);
308  enableAnimControls(hWnd, IsDlgButtonChecked(hWnd, IDC_EXP_SEL_FRAMES));
309  if (imp->_prev_type != MaxEggOptions::AT_chan) imp->ClearNodeList(hWnd);
310  imp->_prev_type = MaxEggOptions::AT_chan;
311  CheckRadioButton(hWnd, IDC_EXP_ALL_FRAMES, IDC_EXP_SEL_FRAMES, IDC_EXP_ALL_FRAMES);
312 
313  return TRUE;
314  }
315  break;
316  case IDC_BOTH:
317  if (HIWORD(wParam) == BN_CLICKED) {
318  SetWindowText(GetDlgItem(hWnd, IDC_EXPORT_SELECTED),
319  _T("Export Models:"));
320  enableAnimRadios(hWnd, ANIM_RAD_ALL);
321  showAnimControls(hWnd, TRUE);
322  enableAnimControls(hWnd, IsDlgButtonChecked(hWnd, IDC_EXP_SEL_FRAMES));
323  if (imp->_prev_type == MaxEggOptions::AT_chan) imp->ClearNodeList(hWnd);
324  imp->_prev_type = MaxEggOptions::AT_both;
325  CheckRadioButton(hWnd, IDC_EXP_ALL_FRAMES, IDC_EXP_SEL_FRAMES, IDC_EXP_ALL_FRAMES);
326 
327  return TRUE;
328  }
329  break;
330  case IDC_POSE:
331  if (HIWORD(wParam) == BN_CLICKED) {
332  SetWindowText(GetDlgItem(hWnd, IDC_EXPORT_SELECTED),
333  _T("Export Meshes:"));
334  enableAnimRadios(hWnd, ANIM_RAD_EXPSEL);
335  showAnimControls(hWnd, FALSE);
336  enableAnimControls(hWnd, TRUE);
337  CheckRadioButton(hWnd, IDC_EXP_ALL_FRAMES, IDC_EXP_SEL_FRAMES, IDC_EXP_SEL_FRAMES);
338  if (imp->_prev_type == MaxEggOptions::AT_chan) imp->ClearNodeList(hWnd);
339  imp->_prev_type = MaxEggOptions::AT_pose;
340 
341  return TRUE;
342  }
343  break;
344  case IDC_EXP_ALL_FRAMES:
345  if (HIWORD(wParam) == BN_CLICKED) {
346  enableAnimControls(hWnd, FALSE);
347  if(imp->_prev_type == MaxEggOptions::AT_chan)
348  {
349  CheckRadioButton(hWnd, IDC_MODEL, IDC_POSE, IDC_ANIMATION);
350  }
351  if(imp->_prev_type == MaxEggOptions::AT_both)
352  {
353  CheckRadioButton(hWnd, IDC_MODEL, IDC_POSE, IDC_BOTH);
354  }
355  return TRUE;
356  }
357  break;
358 
359  case IDC_EXP_SEL_FRAMES:
360  if (HIWORD(wParam) == BN_CLICKED) {
361  enableAnimControls(hWnd, TRUE);
362  if(imp->_prev_type == MaxEggOptions::AT_chan)
363  {
364  CheckRadioButton(hWnd, IDC_MODEL, IDC_POSE, IDC_ANIMATION);
365  }
366  if(imp->_prev_type == MaxEggOptions::AT_both)
367  {
368  CheckRadioButton(hWnd, IDC_MODEL, IDC_POSE, IDC_BOTH);
369  }
370  return TRUE;
371  }
372  break;
373 
374  case IDC_EXPORT_ALL:
375  if (HIWORD(wParam) == BN_CLICKED) {
376  enableChooserControls(hWnd, FALSE);
377  return TRUE;
378  }
379  break;
380 
381  case IDC_EXPORT_SELECTED:
382  if (HIWORD(wParam) == BN_CLICKED) {
383  enableChooserControls(hWnd, TRUE);
384  return TRUE;
385  }
386  break;
387 
388 
389  // deal with adding meshes
390  case IDC_ADD_EXPORT:
391  {
392  if (!imp->_choosing_nodes) {
393  AddNodeCB PickCB(imp, hWnd);
394  imp->_choosing_nodes = true;
395  imp->_max_interface->DoHitByNameDialog(&PickCB);
396  imp->_choosing_nodes = false;
397  }
398  }
399  return TRUE; break;
400 
401  case IDC_REMOVE_EXPORT:
402  {
403  if (!imp->_choosing_nodes) {
404  imp->_choosing_nodes = true;
405  RemoveNodeCB PickCB(imp, hWnd);
406  imp->_max_interface->DoHitByNameDialog(&PickCB);
407  imp->_choosing_nodes = false;
408  }
409  }
410  return TRUE; break;
411 
412  case IDC_OK:
413  if (imp->UpdateFromUI(hWnd)) EndDialog(hWnd, TRUE);
414  return TRUE; break;
415  case IDC_CANCEL:
416  EndDialog(hWnd, FALSE);
417  return TRUE; break;
418  case IDC_BROWSE:
419  OPENFILENAME ofn;
420  _tcscpy(tempFilename, GetICustEditT(GetDlgItem(hWnd, IDC_FILENAME)));
421 
422  memset(&ofn, 0, sizeof(ofn));
423  ofn.nMaxFile = 2047;
424  ofn.lpstrFile = tempFilename;
425  ofn.lStructSize = sizeof(ofn);
426  ofn.hwndOwner = hWnd;
427  ofn.Flags = OFN_HIDEREADONLY | OFN_NOREADONLYRETURN | OFN_PATHMUSTEXIST;
428  ofn.lpstrDefExt = _T("egg");
429  ofn.lpstrFilter = _T("Panda3D Egg Files (*.egg)\0*.egg\0All Files (*.*)\0*.*\0");
430 
431  SetFocus(GetDlgItem(hWnd, IDC_FILENAME));
432  if (GetSaveFileName(&ofn))
433  SetICustEdit(hWnd, IDC_FILENAME, ofn.lpstrFile);
434  // else { char buf[255]; sprintf(buf, "%d",
435  // CommDlgExtendedError()); MessageBox(hWnd, buf, "Error on
436  // GetSaveFileName", MB_OK); }
437  return TRUE; break;
438  case IDC_CHECK1:
439  if (IsDlgButtonChecked(hWnd, IDC_CHECK1))
440  if (MessageBox(hWnd, _T("Warning: Exporting double-sided polygons can severely hurt ")
441  _T("performance in Panda3D.\n\nAre you sure you want to export them?"),
442  _T("Panda3D Exporter"), MB_YESNO | MB_ICONQUESTION) != IDYES)
443  CheckDlgButton(hWnd, IDC_CHECK1, BST_UNCHECKED);
444  return TRUE; break;
445 
446  default:
447  // char buf[255]; sprintf(buf, "%d", LOWORD(wParam));
448  // MessageBox(hWnd, buf, "Unknown WParam", MB_OK);
449  break;
450  }
451  }
452  return FALSE;
453 }
454 
455 void MaxOptionsDialog::SetAnimRange() {
456  // Get the start and end frames and the animation frame rate from Max
457  Interval anim_range = _max_interface->GetAnimRange();
458  _min_frame = anim_range.Start()/GetTicksPerFrame();
459  _max_frame = anim_range.End()/GetTicksPerFrame();
460 }
461 
462 MaxOptionsDialog::MaxOptionsDialog() :
463  MaxEggOptions(),
464  _min_frame(0),
465  _max_frame(0),
466  _checked(true),
467  _choosing_nodes(false),
468  _prev_type(AT_model)
469 {
470 }
471 
472 MaxOptionsDialog::~MaxOptionsDialog ()
473 {
474 }
475 
476 
477 void MaxOptionsDialog::UpdateUI(HWND hWnd) {
478  int typeButton = IDC_MODEL;
479  int anim_exp = _export_all_frames ? IDC_EXP_ALL_FRAMES : IDC_EXP_SEL_FRAMES;
480  int model_exp = _export_whole_scene ? IDC_EXPORT_ALL : IDC_EXPORT_SELECTED;
481 
482  switch (_anim_type) {
483  case MaxEggOptions::AT_chan: typeButton = IDC_ANIMATION; break;
484  case MaxEggOptions::AT_both: typeButton = IDC_BOTH; break;
485  case MaxEggOptions::AT_pose: typeButton = IDC_POSE; break;
486  case MaxEggOptions::AT_model: typeButton = IDC_MODEL; break;
487  }
488 
489  _prev_type = _anim_type;
490 
491  CheckRadioButton(hWnd, IDC_MODEL, IDC_POSE, typeButton);
492  SendMessage(hWnd, WM_COMMAND, MAKEWPARAM(typeButton, BN_CLICKED), 0);
493  CheckRadioButton(hWnd, IDC_EXPORT_ALL, IDC_EXPORT_SELECTED, model_exp);
494  SendMessage(hWnd, WM_COMMAND, MAKEWPARAM(model_exp, BN_CLICKED), 0);
495  CheckRadioButton(hWnd, IDC_EXP_ALL_FRAMES, IDC_EXP_SEL_FRAMES, anim_exp);
496  SendMessage(hWnd, WM_COMMAND, MAKEWPARAM(anim_exp, BN_CLICKED), 0);
497 
498  CheckDlgButton(hWnd, IDC_CHECK1,
499  _double_sided ? BST_CHECKED : BST_UNCHECKED);
500 
501 
502  SetICustEdit(hWnd, IDC_FILENAME, _file_name);
503  if (_start_frame != INT_MIN) {
504  SetICustEdit(hWnd, IDC_SF, _start_frame);
505  SetICustEdit(hWnd, IDC_EF, _end_frame);
506  } else {
507  SetICustEdit(hWnd, IDC_SF, _min_frame);
508  SetICustEdit(hWnd, IDC_EF, _max_frame);
509  }
510 
511  RefreshNodeList(hWnd);
512 }
513 
514 void MaxOptionsDialog::ClearNodeList(HWND hWnd) {
515  _node_list.clear();
516  RefreshNodeList(hWnd);
517 }
518 
519 void MaxOptionsDialog::RefreshNodeList(HWND hWnd) {
520  // Clear and repopulate the node box
521  HWND nodeLB = GetDlgItem(hWnd, IDC_LIST_EXPORT);
522  SendMessage(nodeLB, LB_RESETCONTENT, 0, 0);
523  for (int i = 0; i < _node_list.size(); i++) {
524  INode *temp = _max_interface->GetINodeByHandle(_node_list[i]);
525  const TCHAR *name = _T("Unknown Node");
526  if (temp) name = temp->GetName();
527  SendMessage(nodeLB, LB_ADDSTRING, 0, (LPARAM)name);
528  }
529 }
530 
531 bool MaxOptionsDialog::UpdateFromUI(HWND hWnd) {
532  BOOL valid;
533  Anim_Type newAnimType;
534  int newSF = INT_MIN, newEF = INT_MIN;
535  TCHAR msg[1024];
536 
537  if (IsDlgButtonChecked(hWnd, IDC_MODEL)) newAnimType = MaxEggOptions::AT_model;
538  else if (IsDlgButtonChecked(hWnd, IDC_ANIMATION)) newAnimType = MaxEggOptions::AT_chan;
539  else if (IsDlgButtonChecked(hWnd, IDC_BOTH)) newAnimType = MaxEggOptions::AT_both;
540  else newAnimType = MaxEggOptions::AT_pose;
541 
542  if (newAnimType != MaxEggOptions::AT_model && IsDlgButtonChecked(hWnd, IDC_EXP_SEL_FRAMES)) {
543  newSF = GetICustEditI(GetDlgItem(hWnd, IDC_SF), &valid);
544  if (!valid) {
545  MessageBox(hWnd, _T("Start Frame must be an integer"), _T("Invalid Value"), MB_OK | MB_ICONEXCLAMATION);
546  return false;
547  }
548  if (newSF < _min_frame) {
549  _stprintf(msg, _T("Start Frame must be at least %d"), _min_frame);
550  MessageBox(hWnd, msg, _T("Invalid Value"), MB_OK | MB_ICONEXCLAMATION);
551  return false;
552  }
553  if (newSF > _max_frame) {
554  _stprintf(msg, _T("Start Frame must be at most %d"), _max_frame);
555  MessageBox(hWnd, msg, _T("Invalid Value"), MB_OK | MB_ICONEXCLAMATION);
556  return false;
557  }
558  if (newAnimType != MaxEggOptions::AT_pose) {
559  newEF = GetICustEditI(GetDlgItem(hWnd, IDC_EF), &valid);
560  if (!valid) {
561  MessageBox(hWnd, _T("End Frame must be an integer"), _T("Invalid Value"), MB_OK | MB_ICONEXCLAMATION);
562  return false;
563  }
564  if (newEF > _max_frame) {
565  _stprintf(msg, _T("End Frame must be at most %d"), _max_frame);
566  MessageBox(hWnd, msg, _T("Invalid Value"), MB_OK | MB_ICONEXCLAMATION);
567  return false;
568  }
569  if (newEF < newSF) {
570  MessageBox(hWnd, _T("End Frame must be greater than the start frame"), _T("Invalid Value"), MB_OK | MB_ICONEXCLAMATION);
571  return false;
572  }
573  }
574  }
575 
576  TCHAR *temp = GetICustEditT(GetDlgItem(hWnd, IDC_FILENAME));
577  if (!_tcslen(temp)) {
578  MessageBox(hWnd, _T("The filename cannot be empty"), _T("Invalid Value"), MB_OK | MB_ICONEXCLAMATION);
579  return false;
580  }
581 
582  if (_tcslen(temp) < 4 || _tcsncmp(_T(".egg"), temp+(_tcslen(temp) - 4), 4)) {
583  _stprintf(_file_name, _T("%s.egg"), temp);
584  } else {
585  _tcscpy(_file_name, temp);
586  }
587 
588  temp = _tcsrchr(_file_name, '\\');
589  if (!temp) temp = _file_name;
590  else temp++;
591 
592  if (_tcslen(temp) > sizeof(_short_name))
593  _stprintf(_short_name, _T("%.*s..."), sizeof(_short_name)-4, temp);
594  else {
595  _tcscpy(_short_name, temp);
596  _short_name[_tcslen(_short_name) - 4] = 0; //Cut off the .egg
597  }
598 
599  _start_frame = newSF;
600  _end_frame = newEF;
601  _anim_type = newAnimType;
602  _double_sided = IsDlgButtonChecked(hWnd, IDC_CHECK1);
603 
604 
605  _export_whole_scene = IsDlgButtonChecked(hWnd, IDC_EXPORT_ALL);
606  _export_all_frames = IsDlgButtonChecked(hWnd, IDC_EXP_ALL_FRAMES);
607 
608  return true;
609 }
610 
611 bool MaxOptionsDialog::FindNode(ULONG INodeHandle) {
612  for (int i = 0; i < _node_list.size(); i++)
613  if (_node_list[i] == INodeHandle) return true;
614  return false;
615 }
616 
617 void MaxOptionsDialog::AddNode(ULONG INodeHandle) {
618  if (FindNode(INodeHandle)) return;
619  _node_list.push_back(INodeHandle);
620 }
621 
622 void MaxOptionsDialog::CullBadNodes() {
623  if (!_max_interface) return;
624  std::vector<ULONG> good;
625  for (int i=0; i<_node_list.size(); i++) {
626  ULONG handle = _node_list[i];
627  if (_max_interface->GetINodeByHandle(handle)) {
628  good.push_back(handle);
629  }
630  }
631  _node_list = good;
632 }
633 
634 void MaxOptionsDialog::RemoveNode(int i) {
635  if (i >= 0 && i < _node_list.size()) {
636  for (int j = i+1; j < _node_list.size(); j++)
637  _node_list[i++] = _node_list[j++];
638  _node_list.pop_back();
639  }
640 }
641 
642 void MaxOptionsDialog::RemoveNodeByHandle(ULONG INodeHandle) {
643  for (int i = 0; i < _node_list.size(); i++) {
644  if (_node_list[i] == INodeHandle) {
645  RemoveNode(i);
646  return;
647  }
648  }
649 }
650 
651 IOResult MaxOptionsDialog::Save(ISave *isave) {
652  isave->BeginChunk(CHUNK_EGG_EXP_OPTIONS);
653  ChunkSave(isave, CHUNK_ANIM_TYPE, _anim_type);
654  ChunkSave(isave, CHUNK_FILENAME, _file_name);
655  ChunkSave(isave, CHUNK_SHORTNAME, _short_name);
656  ChunkSave(isave, CHUNK_SF, _start_frame);
657  ChunkSave(isave, CHUNK_EF, _end_frame);
658  ChunkSave(isave, CHUNK_DBL_SIDED, _double_sided);
659  ChunkSave(isave, CHUNK_EGG_CHECKED, _checked);
660  ChunkSave(isave, CHUNK_ALL_FRAMES, _export_all_frames);
661  ChunkSave(isave, CHUNK_EXPORT_FULL, _export_whole_scene);
662 
663  isave->BeginChunk(CHUNK_NODE_LIST);
664  for (int i = 0; i < _node_list.size(); i++)
665  ChunkSave(isave, CHUNK_NODE_HANDLE, _node_list[i]);
666  isave->EndChunk();
667  isave->EndChunk();
668  return IO_OK;
669 }
670 
671 IOResult MaxOptionsDialog::Load(ILoad *iload) {
672  IOResult res = iload->OpenChunk();
673 
674  while (res == IO_OK) {
675  switch(iload->CurChunkID()) {
676  case CHUNK_ANIM_TYPE: _anim_type = (Anim_Type)ChunkLoadInt(iload); break;
677  case CHUNK_FILENAME: ChunkLoadString(iload, _file_name, sizeof(_file_name)); break;
678  case CHUNK_SHORTNAME: ChunkLoadString(iload, _short_name, sizeof(_short_name)); break;
679  case CHUNK_SF: _start_frame = ChunkLoadInt(iload); break;
680  case CHUNK_EF: _end_frame = ChunkLoadInt(iload); break;
681  case CHUNK_DBL_SIDED: _double_sided = ChunkLoadBool(iload); break;
682  case CHUNK_EGG_CHECKED: _checked = ChunkLoadBool(iload); break;
683  case CHUNK_ALL_FRAMES: _export_all_frames = ChunkLoadBool(iload); break;
684  case CHUNK_EXPORT_FULL: _export_whole_scene = ChunkLoadBool(iload); break;
685 
686  case CHUNK_NODE_LIST:
687  res = iload->OpenChunk();
688  while (res == IO_OK) {
689  if (iload->CurChunkID() == CHUNK_NODE_HANDLE) AddNode(ChunkLoadULONG(iload));
690  iload->CloseChunk();
691  res = iload->OpenChunk();
692  }
693  break;
694  }
695  iload->CloseChunk();
696  res = iload->OpenChunk();
697  }
698 
699  if (res == IO_END) return IO_OK;
700  return IO_ERROR;
701 }
This encapsulates the user's command-line request to replace existing, incorrect pathnames to models ...
Definition: pathReplace.h:36