Panda3D
 All Classes Functions Variables Enumerations
maxEgg.cxx
1 /*
2  MaxEgg.cpp
3  Created by Steven "Sauce" Osman, 01/??/03
4  Modified by Ken Strickland, 02/25/03
5  Carnegie Mellon University, Entertainment Technology Center
6 
7  This file implements the classes that are used in the Panda 3D file
8  exporter for 3D Studio Max.
9 */
10 
11 #include "maxEgg.h"
12 
13 
14 const double meshVerts[252][3] = {
15  {0.729464, -0.919852, 0.714986},
16  {0.466137, -0.594656, 0.160201},
17  {-0.265897, -1.14704, 0.714986},
18  {0.466137, -0.594656, 0.160201},
19  {-0.177333, -0.741523, 0.160201},
20  {-0.265897, -1.14704, 0.714986},
21  {-0.265897, -1.14704, 0.714986},
22  {-0.177333, -0.741523, 0.160201},
23  {-1.06411, -0.510479, 0.714986},
24  {-0.177333, -0.741523, 0.160201},
25  {-0.693356, -0.330009, 0.160201},
26  {-1.06411, -0.510479, 0.714986},
27  {-1.06411, 0.510479, 0.714986},
28  {-1.06411, -0.510479, 0.714986},
29  {-0.693356, 0.330009, 0.160201},
30  {-0.693356, -0.330009, 0.160201},
31  {-0.693356, 0.330009, 0.160201},
32  {-1.06411, -0.510479, 0.714986},
33  {-0.265897, 1.14704, 0.714986},
34  {-1.06411, 0.510479, 0.714986},
35  {-0.177333, 0.741523, 0.160201},
36  {-0.693356, 0.330009, 0.160201},
37  {-0.177333, 0.741523, 0.160201},
38  {-1.06411, 0.510479, 0.714986},
39  {0.729464, 0.919852, 0.714986},
40  {-0.265897, 1.14704, 0.714986},
41  {0.466137, 0.594656, 0.160201},
42  {-0.177333, 0.741523, 0.160201},
43  {0.466137, 0.594656, 0.160201},
44  {-0.265897, 1.14704, 0.714986},
45  {1.17244, 0.0, 0.714986},
46  {0.729464, 0.919852, 0.714986},
47  {0.752508, 0.0, 0.160201},
48  {0.466137, 0.594656, 0.160201},
49  {0.752508, 0.0, 0.160201},
50  {0.729464, 0.919852, 0.714986},
51  {0.729464, -0.919852, 0.714986},
52  {1.17244, 0.0, 0.714986},
53  {0.466137, -0.594656, 0.160201},
54  {0.752508, 0.0, 0.160201},
55  {0.466137, -0.594656, 0.160201},
56  {1.17244, 0.0, 0.714986},
57  {-0.286334, -1.26822, 1.44995},
58  {0.814187, -1.01703, 1.44995},
59  {-0.265897, -1.14704, 0.714986},
60  {0.729464, -0.919852, 0.714986},
61  {-0.265897, -1.14704, 0.714986},
62  {0.814187, -1.01703, 1.44995},
63  {-1.16888, -0.564412, 1.44995},
64  {-0.286334, -1.26822, 1.44995},
65  {-1.06411, -0.510479, 0.714986},
66  {-0.265897, -1.14704, 0.714986},
67  {-1.06411, -0.510479, 0.714986},
68  {-0.286334, -1.26822, 1.44995},
69  {-1.16888, 0.564411, 1.44995},
70  {-1.16888, -0.564412, 1.44995},
71  {-1.06411, 0.510479, 0.714986},
72  {-1.06411, -0.510479, 0.714986},
73  {-1.06411, 0.510479, 0.714986},
74  {-1.16888, -0.564412, 1.44995},
75  {-1.16888, 0.564411, 1.44995},
76  {-1.06411, 0.510479, 0.714986},
77  {-0.286334, 1.26822, 1.44995},
78  {-1.06411, 0.510479, 0.714986},
79  {-0.265897, 1.14704, 0.714986},
80  {-0.286334, 1.26822, 1.44995},
81  {-0.286334, 1.26822, 1.44995},
82  {-0.265897, 1.14704, 0.714986},
83  {0.814187, 1.01703, 1.44995},
84  {-0.265897, 1.14704, 0.714986},
85  {0.729464, 0.919852, 0.714986},
86  {0.814187, 1.01703, 1.44995},
87  {1.30396, 0.0, 1.44995},
88  {0.814187, 1.01703, 1.44995},
89  {1.17244, 0.0, 0.714986},
90  {0.729464, 0.919852, 0.714986},
91  {1.17244, 0.0, 0.714986},
92  {0.814187, 1.01703, 1.44995},
93  {1.30396, 0.0, 1.44995},
94  {1.17244, 0.0, 0.714986},
95  {0.814187, -1.01703, 1.44995},
96  {1.17244, 0.0, 0.714986},
97  {0.729464, -0.919852, 0.714986},
98  {0.814187, -1.01703, 1.44995},
99  {-0.286334, -1.26822, 1.44995},
100  {-0.227573, -1.05763, 2.16723},
101  {0.814187, -1.01703, 1.44995},
102  {0.814187, -1.01703, 1.44995},
103  {-0.227573, -1.05763, 2.16723},
104  {0.690208, -0.848157, 2.16723},
105  {-1.16888, -0.564412, 1.44995},
106  {-0.963577, -0.470692, 2.16723},
107  {-0.286334, -1.26822, 1.44995},
108  {-0.286334, -1.26822, 1.44995},
109  {-0.963577, -0.470692, 2.16723},
110  {-0.227573, -1.05763, 2.16723},
111  {-1.16888, -0.564412, 1.44995},
112  {-1.16888, 0.564411, 1.44995},
113  {-0.963577, -0.470692, 2.16723},
114  {-1.16888, 0.564411, 1.44995},
115  {-0.963577, 0.470692, 2.16723},
116  {-0.963577, -0.470692, 2.16723},
117  {-1.16888, 0.564411, 1.44995},
118  {-0.286334, 1.26822, 1.44995},
119  {-0.963577, 0.470692, 2.16723},
120  {-0.286334, 1.26822, 1.44995},
121  {-0.227574, 1.05763, 2.16723},
122  {-0.963577, 0.470692, 2.16723},
123  {-0.286334, 1.26822, 1.44995},
124  {0.814187, 1.01703, 1.44995},
125  {-0.227574, 1.05763, 2.16723},
126  {0.814187, 1.01703, 1.44995},
127  {0.690208, 0.848157, 2.16723},
128  {-0.227574, 1.05763, 2.16723},
129  {0.814187, 1.01703, 1.44995},
130  {1.30396, 0.0, 1.44995},
131  {0.690208, 0.848157, 2.16723},
132  {1.30396, 0.0, 1.44995},
133  {1.09866, 0.0, 2.16723},
134  {0.690208, 0.848157, 2.16723},
135  {0.814187, -1.01703, 1.44995},
136  {0.690208, -0.848157, 2.16723},
137  {1.30396, 0.0, 1.44995},
138  {1.30396, 0.0, 1.44995},
139  {0.690208, -0.848157, 2.16723},
140  {1.09866, 0.0, 2.16723},
141  {-0.227573, -1.05763, 2.16723},
142  {-0.154893, -0.759032, 2.72566},
143  {0.690208, -0.848157, 2.16723},
144  {0.690208, -0.848157, 2.16723},
145  {-0.154893, -0.759032, 2.72566},
146  {0.50377, -0.608696, 2.72566},
147  {-0.963577, -0.470692, 2.16723},
148  {-0.683099, -0.337801, 2.72566},
149  {-0.227573, -1.05763, 2.16723},
150  {-0.227573, -1.05763, 2.16723},
151  {-0.683099, -0.337801, 2.72566},
152  {-0.154893, -0.759032, 2.72566},
153  {-0.963577, -0.470692, 2.16723},
154  {-0.963577, 0.470692, 2.16723},
155  {-0.683099, -0.337801, 2.72566},
156  {-0.963577, 0.470692, 2.16723},
157  {-0.683099, 0.337801, 2.72566},
158  {-0.683099, -0.337801, 2.72566},
159  {-0.963577, 0.470692, 2.16723},
160  {-0.227574, 1.05763, 2.16723},
161  {-0.683099, 0.337801, 2.72566},
162  {-0.227574, 1.05763, 2.16723},
163  {-0.154893, 0.759032, 2.72566},
164  {-0.683099, 0.337801, 2.72566},
165  {-0.227574, 1.05763, 2.16723},
166  {0.690208, 0.848157, 2.16723},
167  {-0.154893, 0.759032, 2.72566},
168  {0.690208, 0.848157, 2.16723},
169  {0.50377, 0.608696, 2.72566},
170  {-0.154893, 0.759032, 2.72566},
171  {0.690208, 0.848157, 2.16723},
172  {1.09866, 0.0, 2.16723},
173  {0.50377, 0.608696, 2.72566},
174  {1.09866, 0.0, 2.16723},
175  {0.796903, 0.0, 2.72566},
176  {0.50377, 0.608696, 2.72566},
177  {1.09866, 0.0, 2.16723},
178  {0.690208, -0.848157, 2.16723},
179  {0.796903, 0.0, 2.72566},
180  {0.690208, -0.848157, 2.16723},
181  {0.50377, -0.608696, 2.72566},
182  {0.796903, 0.0, 2.72566},
183  {0.50377, -0.608696, 2.72566},
184  {-0.154893, -0.759032, 2.72566},
185  {0.259722, -0.299638, 3.11175},
186  {-0.154893, -0.759032, 2.72566},
187  {-0.0645132, -0.373643, 3.11175},
188  {0.259722, -0.299638, 3.11175},
189  {-0.154893, -0.759032, 2.72566},
190  {-0.683099, -0.337801, 2.72566},
191  {-0.0645132, -0.373643, 3.11175},
192  {-0.683099, -0.337801, 2.72566},
193  {-0.324529, -0.166287, 3.11175},
194  {-0.0645132, -0.373643, 3.11175},
195  {-0.683099, -0.337801, 2.72566},
196  {-0.683099, 0.337801, 2.72566},
197  {-0.324529, -0.166287, 3.11175},
198  {-0.683099, 0.337801, 2.72566},
199  {-0.324529, 0.166287, 3.11175},
200  {-0.324529, -0.166287, 3.11175},
201  {-0.683099, 0.337801, 2.72566},
202  {-0.154893, 0.759032, 2.72566},
203  {-0.324529, 0.166287, 3.11175},
204  {-0.154893, 0.759032, 2.72566},
205  {-0.0645132, 0.373642, 3.11175},
206  {-0.324529, 0.166287, 3.11175},
207  {-0.154893, 0.759032, 2.72566},
208  {0.50377, 0.608696, 2.72566},
209  {-0.0645132, 0.373642, 3.11175},
210  {0.50377, 0.608696, 2.72566},
211  {0.259722, 0.299638, 3.11175},
212  {-0.0645132, 0.373642, 3.11175},
213  {0.50377, 0.608696, 2.72566},
214  {0.796903, 0.0, 2.72566},
215  {0.259722, 0.299638, 3.11175},
216  {0.796903, 0.0, 2.72566},
217  {0.40402, 0.0, 3.11175},
218  {0.259722, 0.299638, 3.11175},
219  {0.796903, 0.0, 2.72566},
220  {0.50377, -0.608696, 2.72566},
221  {0.40402, 0.0, 3.11175},
222  {0.50377, -0.608696, 2.72566},
223  {0.259722, -0.299638, 3.11175},
224  {0.40402, 0.0, 3.11175},
225  {-0.177333, -0.741523, 0.160201},
226  {0.466137, -0.594656, 0.160201},
227  {-0.00334214, 0.0, 0.00443203},
228  {-0.693356, -0.330009, 0.160201},
229  {-0.177333, -0.741523, 0.160201},
230  {-0.00334214, 0.0, 0.00443203},
231  {-0.693356, 0.330009, 0.160201},
232  {-0.693356, -0.330009, 0.160201},
233  {-0.00334214, 0.0, 0.00443203},
234  {-0.177333, 0.741523, 0.160201},
235  {-0.693356, 0.330009, 0.160201},
236  {-0.00334214, 0.0, 0.00443203},
237  {0.466137, 0.594656, 0.160201},
238  {-0.177333, 0.741523, 0.160201},
239  {-0.00334214, 0.0, 0.00443203},
240  {0.752508, 0.0, 0.160201},
241  {0.466137, 0.594656, 0.160201},
242  {-0.00334214, 0.0, 0.00443203},
243  {0.466137, -0.594656, 0.160201},
244  {0.752508, 0.0, 0.160201},
245  {-0.00334214, 0.0, 0.00443203},
246  {0.259722, -0.299638, 3.11175},
247  {-0.0645132, -0.373643, 3.11175},
248  {0.0207683, 0.0, 3.20912},
249  {-0.0645132, -0.373643, 3.11175},
250  {-0.324529, -0.166287, 3.11175},
251  {0.0207683, 0.0, 3.20912},
252  {-0.324529, -0.166287, 3.11175},
253  {-0.324529, 0.166287, 3.11175},
254  {0.0207683, 0.0, 3.20912},
255  {-0.324529, 0.166287, 3.11175},
256  {-0.0645132, 0.373642, 3.11175},
257  {0.0207683, 0.0, 3.20912},
258  {-0.0645132, 0.373642, 3.11175},
259  {0.259722, 0.299638, 3.11175},
260  {0.0207683, 0.0, 3.20912},
261  {0.259722, 0.299638, 3.11175},
262  {0.40402, 0.0, 3.11175},
263  {0.0207683, 0.0, 3.20912},
264  {0.40402, 0.0, 3.11175},
265  {0.259722, -0.299638, 3.11175},
266  {0.0207683, 0.0, 3.20912}
267 };
268 
269 
270 //Disable the forcing int to true or false performance warning
271 #pragma warning(disable: 4800)
272 
273 /* MaxEggPluginClassDesc - A class that describes 3DS Plugin support.
274  This basically says "Yes, I am a helper object!"
275 */
276 
277 class MaxEggPluginClassDesc : public ClassDesc
278 {
279 public:
280  int IsPublic() { return TRUE; }
281  void *Create(BOOL loading = FALSE) { return new MaxEggPlugin(); }
282  const TCHAR *ClassName() { return GetString(IDS_CLASS_NAME); }
283  SClass_ID SuperClassID() { return HELPER_CLASS_ID; }
284  Class_ID ClassID() { return MaxEggPlugin_CLASS_ID; }
285  const TCHAR *Category() { return GetString(IDS_CATEGORY); }
286  // returns fixed parsable name (scripter-visible name)
287  const TCHAR *InternalName() { return _T("MaxEggPlugin"); }
288 };
289 
290 // Our private global instance of the above class
291 static MaxEggPluginClassDesc MaxEggPluginDesc;
292 
293 // Called by LibClassDesc to find out what the plugin is
294 ClassDesc* GetMaxEggPluginDesc() { return &MaxEggPluginDesc; }
295 
296 // Initialize class-static variables
297 Mesh MaxEggPlugin::mesh;
298 short MaxEggPlugin::meshBuilt=0;
299 HWND MaxEggPlugin::hMaxEggParams = NULL;
300 IObjParam *MaxEggPlugin::iObjParams;
301 
302 /* MaxEggPluginOptionsDlgProc() - This is the callback function for the
303  dialog box that appears at the beginning of the conversion process.
304  */
305 
306 INT_PTR CALLBACK MaxEggPluginOptionsDlgProc( HWND hWnd, UINT message,
307  WPARAM wParam, LPARAM lParam )
308 {
309  MaxOptionsDialog *tempEgg;
310  int sel, res;
311 
312  //We pass in our plugin through the lParam variable. Let's convert it back.
313  MaxEggPlugin *imp = (MaxEggPlugin*)GetWindowLongPtr(hWnd,GWLP_USERDATA);
314  if ( !imp && message != WM_INITDIALOG ) return FALSE;
315 
316  switch(message)
317  {
318  // When we start, center the window.
319  case WM_INITDIALOG:
320  // this line is very necessary to pass the plugin as the lParam
321  SetWindowLongPtr(hWnd,GWLP_USERDATA,lParam);
322  SetDlgFont( hWnd, imp->iObjParams->GetAppHFont() );
323  MaxEggPlugin::hMaxEggParams = hWnd;
324  return TRUE; break;
325 
326  case WM_MOUSEACTIVATE:
327  imp->iObjParams->RealizeParamPanel();
328  return TRUE; break;
329 
330  case WM_LBUTTONDOWN:
331  case WM_LBUTTONUP:
332  case WM_MOUSEMOVE:
333  imp->iObjParams->RollupMouseMessage(hWnd,message,wParam,lParam);
334  return TRUE; break;
335 
336  // A control was modified
337  case WM_COMMAND:
338  //The modified control is found in the lower word of the wParam long.
339  switch( LOWORD(wParam) ) {
340  case IDC_OVERWRITE_CHECK:
341  imp->autoOverwrite =
342  (IsDlgButtonChecked(hWnd, IDC_OVERWRITE_CHECK) == BST_CHECKED);
343  return TRUE; break;
344  case IDC_PVIEW_CHECK:
345  imp->pview =
346  (IsDlgButtonChecked(hWnd, IDC_PVIEW_CHECK) == BST_CHECKED);
347  return TRUE; break;
348  case IDC_LOGGING:
349  imp->logOutput =
350  (IsDlgButtonChecked(hWnd, IDC_LOGGING) == BST_CHECKED);
351  return TRUE; break;
352  case IDC_ADD_EGG:
353  tempEgg = new MaxOptionsDialog();
354  tempEgg->SetMaxInterface(imp->iObjParams);
355  tempEgg->SetAnimRange();
356  res = DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_EGG_DETAILS),
357  hWnd, MaxOptionsDialogProc, (LPARAM)tempEgg);
358  if (res == TRUE) {
359  imp->SaveCheckState();
360  imp->AddEgg(tempEgg);
361  imp->UpdateUI();
362  }
363  else delete tempEgg;
364  return TRUE; break;
365  case IDC_EDIT_EGG:
366  sel = ListView_GetSelectionMark(GetDlgItem(hWnd, IDC_LIST_EGGS));
367  if (sel != -1) {
368  MaxOptionsDialog *tempEgg = imp->GetEgg(sel);
369  if (tempEgg) {
370  tempEgg->SetAnimRange();
371  tempEgg->CullBadNodes();
372  DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_EGG_DETAILS),
373  hWnd, MaxOptionsDialogProc, (LPARAM)tempEgg);
374  }
375  imp->SaveCheckState();
376  imp->UpdateUI();
377  }
378  return TRUE; break;
379  case IDC_REMOVE_EGG:
380  sel = ListView_GetSelectionMark(GetDlgItem(hWnd, IDC_LIST_EGGS));
381  if (sel != -1) {
382  imp->SaveCheckState();
383  imp->RemoveEgg(sel);
384  imp->UpdateUI();
385  }
386  return TRUE; break;
387  case IDC_EXPORT:
388  imp->DoExport();
389  return TRUE; break;
390  }
391  }
392  return FALSE;
393 }
394 
395 MaxEggPlugin::MaxEggPlugin() :
396 autoOverwrite(false), pview(true), logOutput(false), numEggs(0), maxEggs(5)
397 {
398  eggList = new MaxOptionsDialog*[maxEggs];
399  BuildMesh();
400 }
401 
402 MaxEggPlugin::~MaxEggPlugin() {
403  for (int i = 0; i < numEggs; i++) delete eggList[i];
404  delete [] eggList;
405 }
406 
407 void MaxEggPlugin::AddEgg(MaxOptionsDialog *newEgg) {
408  if (numEggs >= maxEggs) {
409  MaxOptionsDialog **newList;
410  maxEggs *= 2;
411  newList = new MaxOptionsDialog*[maxEggs];
412  for (int i = 0; i < numEggs; i++) newList[i] = eggList[i];
413  delete [] eggList;
414  eggList = newList;
415  }
416 
417  eggList[numEggs++] = newEgg;
418 }
419 
420 void MaxEggPlugin::RemoveEgg(int i) {
421  if (i >= 0 && i < numEggs) {
422  delete eggList[i];
423  for (int j = i+1; j < numEggs;) eggList[i++] = eggList[j++];
424  --numEggs;
425  }
426 }
427 
428 void MaxEggPlugin::BeginEditParams( IObjParam *ip, ULONG flags,Animatable *prev )
429 {
430  iObjParams = ip;
431  for (int i=0; i<numEggs; i++) {
432  eggList[i]->SetMaxInterface(ip);
433  }
434 
435  if ( !hMaxEggParams ) {
436  hMaxEggParams = ip->AddRollupPage(hInstance,
437  MAKEINTRESOURCE(IDD_PANEL),
438  MaxEggPluginOptionsDlgProc,
439  GetString(IDS_PARAMS),
440  (LPARAM)this );
441  ip->RegisterDlgWnd(hMaxEggParams);
442  } else {
443  SetWindowLongPtr( hMaxEggParams, GWLP_USERDATA, (LPARAM)this );
444  }
445 
446  UpdateUI();
447 }
448 
449 void MaxEggPlugin::EndEditParams( IObjParam *ip, ULONG flags,Animatable *prev)
450 {
451  SaveCheckState();
452  if ( flags&END_EDIT_REMOVEUI ) {
453  ip->UnRegisterDlgWnd(hMaxEggParams);
454  ip->DeleteRollupPage(hMaxEggParams);
455  hMaxEggParams = NULL;
456  } else {
457  SetWindowLongPtr( hMaxEggParams, GWLP_USERDATA, NULL );
458  }
459 }
460 
461 void MaxEggPlugin::SaveCheckState() {
462  if (!hMaxEggParams) return;
463  HWND lv = GetDlgItem(hMaxEggParams, IDC_LIST_EGGS);
464  for (int i = 0; i < numEggs; i++)
465  eggList[i]->_checked = ListView_GetCheckState(lv, i);
466 }
467 
468 void MaxEggPlugin::UpdateUI() {
469  HWND lv = GetDlgItem(hMaxEggParams, IDC_LIST_EGGS);
470  LV_COLUMN pCol;
471 
472  if (ListView_GetColumnWidth(lv, 1) <= 0 || ListView_GetColumnWidth(lv, 1) > 10000) {
473  // Columns have not been setup, so initialize the control
474  ListView_SetExtendedListViewStyleEx(lv, LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT,
475  LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT);
476 
477  pCol.fmt = LVCFMT_LEFT;
478  pCol.cx = 96;
479  pCol.pszText = _T("Filename");
480  pCol.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
481  pCol.iSubItem = 0;
482  ListView_InsertColumn(lv, 0, &pCol);
483 
484  pCol.cx = 44;
485  pCol.pszText = _T("Type");
486  ListView_InsertColumn(lv, 1, &pCol);
487  }
488 
489  // Add the eggs to the list
490  ListView_DeleteAllItems(lv);
491  LV_ITEM Item;
492  Item.mask = LVIF_TEXT;
493 
494  for (int i = 0; i < numEggs; i++) {
495  Item.iItem = i;
496  Item.iSubItem = 0;
497  Item.pszText = eggList[i]->_short_name;
498  ListView_InsertItem(lv, &Item);
499  Item.iSubItem = 1;
500  switch(eggList[i]->_anim_type) {
501  case MaxEggOptions::AT_chan: Item.pszText = _T("Animation"); break;
502  case MaxEggOptions::AT_both: Item.pszText = _T("Both"); break;
503  case MaxEggOptions::AT_pose: Item.pszText = _T("Static"); break;
504  case MaxEggOptions::AT_model: Item.pszText = _T("Model"); break;
505  default: Item.pszText = _T("Model"); break;
506  }
507  ListView_SetItem(lv, &Item);
508  ListView_SetCheckState(lv, i, eggList[i]->_checked);
509  }
510 
511  // Set the "Overwrite Existing Files" and "Pview" checkboxes
512  CheckDlgButton(hMaxEggParams, IDC_OVERWRITE_CHECK,
513  autoOverwrite ? BST_CHECKED : BST_UNCHECKED);
514  CheckDlgButton(hMaxEggParams, IDC_PVIEW_CHECK,
515  pview ? BST_CHECKED : BST_UNCHECKED);
516  CheckDlgButton(hMaxEggParams, IDC_LOGGING,
517  logOutput ? BST_CHECKED : BST_UNCHECKED);
518 }
519 
520 void MaxEggPlugin::DoExport() {
521  int good = 0, bad = 0;
522 
523  std::basic_stringstream<TCHAR> status;
524 
525  SaveCheckState();
526 
527  for (int i = 0; i < numEggs; i++) {
528  if (eggList[i]->_checked) {
529  // If "auto overwrite" was not checked and the file exists,
530  // ask if the user wishes to overwrite the file
531  bool do_write = true;
532 
533  if (!autoOverwrite && GetFileAttributes(eggList[i]->_file_name) != INVALID_FILE_ATTRIBUTES) {
534  TCHAR msg[1024];
535  _stprintf(msg, _T("Overwrite file \"%s.egg\"?"), eggList[i]->_short_name);
536  do_write = (MessageBox(hMaxEggParams, msg, _T("Panda3D Exporter"), MB_YESNO | MB_ICONQUESTION) == IDYES);
537  }
538  if (do_write) {
539  MaxToEggConverter converter;
540  if (converter.convert((MaxEggOptions*)eggList[i])) {
541  good += 1;
542  status << _T("Successfully created ") << eggList[i]->_short_name << _T(".egg\n");
543  } else {
544  bad += 1;
545  status << _T("Could not export ") << eggList[i]->_short_name << _T(".egg\n");
546  }
547  } else {
548  bad += 1;
549  status << _T("Skipped file ") << eggList[i]->_short_name << _T(".egg\n");
550  }
551  }
552  }
553 
554  UINT mask = MB_OK;
555 
556  if (good == 0 && bad == 0) {
557  mask |= MB_ICONEXCLAMATION;
558  MessageBox(hMaxEggParams, _T("Nothing to export!"), _T("Panda3D Export results"), mask);
559  } else {
560  if (bad > 0) mask |= MB_ICONEXCLAMATION;
561  else mask |= MB_ICONINFORMATION;
562  MessageBox(hMaxEggParams, status.str().c_str(), _T("Panda3D Export results"), mask);
563  }
564 
565  int pviewed = 0;
566  if (pview && good > 0) {
567  for (i = 0; i < numEggs; i++) {
568  if (eggList[i]->_checked && eggList[i]->_successful) {
569  if (eggList[i]->_anim_type != MaxEggOptions::AT_chan) {
570  PROCESS_INFORMATION pi;
571  STARTUPINFO si;
572 
573  memset(&si, 0, sizeof(si));
574  si.cb = sizeof(si);
575 
576  TCHAR cmdLine[2048];
577  // If we have just one model and animation file, pview them both
578  if (numEggs == 2 && eggList[i]->_anim_type == MaxEggOptions::AT_model &&
579  eggList[1-i]->_checked && eggList[1-i]->_successful &&
580  eggList[1-i]->_anim_type == MaxEggOptions::AT_chan) {
581  _stprintf(cmdLine, _T("pview \"%s\" \"%s\""), eggList[i]->_file_name, eggList[1-i]->_file_name);
582  } else {
583  _stprintf(cmdLine, _T("pview \"%s\""), eggList[i]->_file_name);
584  }
585  CreateProcess(NULL, cmdLine, NULL, NULL, FALSE, CREATE_NEW_CONSOLE,
586  NULL, NULL, &si, &pi);
587  pviewed += 1;
588  }
589  }
590  }
591  }
592 }
593 
594 
595 void MaxEggPlugin::BuildMesh()
596 {
597  int i;
598  if(meshBuilt) return;
599 
600  mesh.setNumVerts(252);
601  mesh.setNumFaces(84);
602  mesh.setSmoothFlags(0);
603  mesh.setNumTVerts (0);
604  mesh.setNumTVFaces (0);
605 
606  for (i=0; i<252; i++)
607  mesh.setVert(i, meshVerts[i][0]*10, meshVerts[i][1]*10, meshVerts[i][2]*10);
608  for (i=0; i<84; i++) {
609  mesh.faces[i].setEdgeVisFlags(1, 1, 0);
610  mesh.faces[i].setSmGroup(0);
611  mesh.faces[i].setVerts(i*3, i*3+1, i*3+2);
612  }
613 
614  mesh.InvalidateGeomCache();
615  mesh.BuildStripsAndEdges();
616 
617  meshBuilt = TRUE;
618 }
619 
620 ///////////////////////////////////////////////////////////////////////////////////////////////////////
621 // The creation callback - sets the initial position of the helper in the scene.
622 ///////////////////////////////////////////////////////////////////////////////////////////////////////
623 
624 class MaxEggPluginCreateMouseCallBack: public CreateMouseCallBack
625 {
626 public:
627  int proc( ViewExp *vpt,int msg, int point, int flags, IPoint2 m, Matrix3& mat );
628 };
629 
630 int MaxEggPluginCreateMouseCallBack::proc(ViewExp *vpt,int msg, int point, int flags, IPoint2 m, Matrix3& mat )
631 {
632  if (msg==MOUSE_POINT||msg==MOUSE_MOVE) {
633  switch(point) {
634  case 0:
635  mat.SetTrans(vpt->SnapPoint(m,m,NULL,SNAP_IN_PLANE));
636  break;
637  case 1:
638  mat.SetTrans(vpt->SnapPoint(m,m,NULL,SNAP_IN_PLANE));
639  if (msg==MOUSE_POINT) return CREATE_STOP;
640  break;
641  }
642  } else if (msg == MOUSE_ABORT) {
643  return CREATE_ABORT;
644  }
645  return CREATE_CONTINUE;
646 }
647 
648 static MaxEggPluginCreateMouseCallBack MaxEggCreateMouseCB;
649 
650 CreateMouseCallBack* MaxEggPlugin::GetCreateMouseCallBack()
651 { return &MaxEggCreateMouseCB; }
652 
653 ///////////////////////////////////////////////////////////////////////////////////////////////////////
654 //Boilerplate functions for dealing with the display of the plugin
655 ///////////////////////////////////////////////////////////////////////////////////////////////////////
656 
657 void MaxEggPlugin::GetMat(TimeValue t, INode* inode, ViewExp* vpt, Matrix3& tm)
658 {
659  tm = inode->GetObjectTM(t);
660  tm.NoScale();
661  PN_stdfloat scaleFactor = vpt->NonScalingObjectSize()*vpt->GetVPWorldWidth(tm.GetTrans())/(PN_stdfloat)360.0;
662  tm.Scale(Point3(scaleFactor,scaleFactor,scaleFactor));
663 }
664 
665 void MaxEggPlugin::GetDeformBBox(TimeValue t, Box3& box, Matrix3 *tm, BOOL useSel )
666 {
667  box = mesh.getBoundingBox(tm);
668 }
669 
670 void MaxEggPlugin::GetLocalBoundBox(TimeValue t, INode* inode, ViewExp* vpt, Box3& box )
671 {
672  Matrix3 m = inode->GetObjectTM(t);
673  Point3 pt;
674  Point3 q[4];
675  PN_stdfloat scaleFactor = vpt->GetVPWorldWidth(m.GetTrans())/360.0f;
676  box = mesh.getBoundingBox();
677  box.Scale(scaleFactor);
678 }
679 
680 void MaxEggPlugin::GetWorldBoundBox(TimeValue t, INode* inode, ViewExp* vpt, Box3& box )
681 {
682  int i, nv; Matrix3 tm; Point3 pt;
683  GetMat(t,inode,vpt,tm);
684  nv = mesh.getNumVerts();
685  box.Init();
686  for (i=0; i<nv; i++)
687  box += tm*mesh.getVert(i);
688 }
689 
690 int MaxEggPlugin::HitTest(TimeValue t, INode *inode, int type, int crossing, int flags, IPoint2 *p, ViewExp *vpt)
691 {
692  HitRegion hitRegion;
693  DWORD savedLimits;
694  Matrix3 m;
695  GraphicsWindow *gw = vpt->getGW();
696  Material *mtl = gw->getMaterial();
697  MakeHitRegion(hitRegion,type,crossing,4,p);
698  gw->setRndLimits(((savedLimits = gw->getRndLimits()) | GW_PICK) & ~GW_ILLUM);
699  GetMat(t,inode,vpt,m);
700  gw->setTransform(m);
701  gw->clearHitCode();
702  if (mesh.select( gw, mtl, &hitRegion, flags & HIT_ABORTONHIT ))
703  return TRUE;
704  return FALSE;
705 }
706 
707 int MaxEggPlugin::Display(TimeValue t, INode* inode, ViewExp *vpt, int flags)
708 {
709  Matrix3 m;
710  GraphicsWindow *gw = vpt->getGW();
711  Material *mtl = gw->getMaterial();
712 
713  GetMat(t,inode,vpt,m);
714  gw->setTransform(m);
715  DWORD rlim = gw->getRndLimits();
716  gw->setRndLimits(GW_WIREFRAME|GW_BACKCULL);
717  if (inode->Selected())
718  gw->setColor( LINE_COLOR, GetSelColor());
719  else if(!inode->IsFrozen())
720  gw->setColor( LINE_COLOR, GetUIColor(COLOR_TAPE_OBJ));
721  mesh.render( gw, mtl, NULL, COMP_ALL);
722  return 0;
723 }
724 
725 RefResult MaxEggPlugin::NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget, PartID& partID, RefMessage message )
726 {
727  UpdateUI();
728  return REF_SUCCEED;
729 }
730 
731 ObjectState MaxEggPlugin::Eval(TimeValue time)
732 {
733  return ObjectState(this);
734 }
735 
736 Interval MaxEggPlugin::ObjectValidity(TimeValue t)
737 {
738  Interval ivalid;
739  ivalid.SetInfinite();
740  return ivalid;
741 }
742 
743 RefTargetHandle MaxEggPlugin::Clone(RemapDir& remap)
744 {
745  MaxEggPlugin* newob = new MaxEggPlugin();
746  return(newob);
747 }
748 
749 ///////////////////////////////////////////////////////////
750 // Loading and saving the plugin
751 ///////////////////////////////////////////////////////////
752 
753 IOResult MaxEggPlugin::Save(ISave *isave) {
754  SaveCheckState();
755  for (int i = 0; i < numEggs; i++)
756  eggList[i]->Save(isave);
757  ChunkSave(isave, CHUNK_OVERWRITE_FLAG, autoOverwrite);
758  ChunkSave(isave, CHUNK_PVIEW_FLAG, pview);
759  ChunkSave(isave, CHUNK_LOG_OUTPUT, logOutput);
760 
761  return IO_OK;
762 }
763 
764 IOResult MaxEggPlugin::Load(ILoad *iload) {
765  IOResult res = iload->OpenChunk();
766  MaxOptionsDialog *temp;
767 
768  while (res == IO_OK) {
769  switch(iload->CurChunkID()) {
770  case CHUNK_OVERWRITE_FLAG: autoOverwrite = ChunkLoadBool(iload); break;
771  case CHUNK_PVIEW_FLAG: pview = ChunkLoadBool(iload); break;
772  case CHUNK_LOG_OUTPUT: logOutput = ChunkLoadBool(iload); break;
773  case CHUNK_EGG_EXP_OPTIONS:
774  temp = new MaxOptionsDialog();
775  temp->SetMaxInterface(iObjParams);
776  temp->Load(iload);
777  AddEgg(temp);
778  break;
779  }
780  iload->CloseChunk();
781  res = iload->OpenChunk();
782  }
783 
784  return IO_OK;
785 }
786 
787 /**********************************************************************
788  *
789  * DLL Initialization
790  *
791  **********************************************************************/
792 
793 extern ClassDesc* GetMaxEggPluginDesc();
794 
795 HINSTANCE hInstance;
796 int controlsInit = FALSE;
797 
798 // This function is called by Windows when the DLL is loaded. This
799 // function may also be called many times during time critical operations
800 // like rendering. Therefore developers need to be careful what they
801 // do inside this function. In the code below, note how after the DLL is
802 // loaded the first time only a few statements are executed.
803 
804 BOOL WINAPI DllMain(HINSTANCE hinstDLL,ULONG fdwReason,LPVOID lpvReserved)
805 {
806  hInstance = hinstDLL; // Hang on to this DLL's instance handle.
807 
808  if (!controlsInit) {
809  controlsInit = TRUE;
810 
811 #if MAX_VERSION_MAJOR < 14
812  // It appears that InitCustomControls is deprecated in 2012.
813  // I'm not sure if we can just remove it like this, but
814  // I've heard that it seems to work, so let's do it like this.
815  InitCustomControls(hInstance); // Initialize MAX's custom controls
816 #endif
817  InitCommonControls(); // Initialize Win95 controls
818  }
819 
820  return (TRUE);
821 }
822 
823 // This function returns a string that describes the DLL and where the user
824 // could purchase the DLL if they don't have it.
825 __declspec( dllexport ) const TCHAR* LibDescription()
826 {
827  return GetString(IDS_LIBDESCRIPTION);
828 }
829 
830 // This function returns the number of plug-in classes this DLL operates on.
831 //TODO: Must change this number when adding a new class
832 __declspec( dllexport ) int LibNumberClasses()
833 {
834  return 1;
835 }
836 
837 // This function returns the descriptions of the plug-in classes this DLL operates on.
838 __declspec( dllexport ) ClassDesc* LibClassDesc(int i)
839 {
840  switch(i) {
841  case 0: return GetMaxEggPluginDesc();
842  default: return NULL;
843  }
844 }
845 
846 // This function returns a pre-defined constant indicating the version of
847 // the system under which it was compiled. It is used to allow the system
848 // to catch obsolete DLLs.
849 __declspec( dllexport ) ULONG LibVersion()
850 {
851  return VERSION_3DSMAX;
852 }
853 
854 TCHAR *GetString(int id)
855 {
856  static TCHAR buf[256];
857 
858  if (hInstance)
859  return LoadString(hInstance, id, buf, sizeof(buf)) ? buf : NULL;
860  return NULL;
861 }
862 
bool convert(MaxEggOptions *options)
Fills up the egg_data structure according to the global Max model data.
A window, fullscreen or on a desktop, into which a graphics device sends its output for interactive d...
Defines the way an object appears in the presence of lighting.
Definition: material.h:34
This class supervises the construction of an EggData structure from a Max model.