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