Panda3D
Loading...
Searching...
No Matches
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
15const 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
278class MaxEggPluginClassDesc : public ClassDesc
279{
280public:
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
292static MaxEggPluginClassDesc MaxEggPluginDesc;
293
294// Called by LibClassDesc to find out what the plugin is
295ClassDesc* GetMaxEggPluginDesc() { return &MaxEggPluginDesc; }
296
297// Initialize class-static variables
298Mesh MaxEggPlugin::mesh;
299short MaxEggPlugin::meshBuilt=0;
300HWND MaxEggPlugin::hMaxEggParams = nullptr;
301IObjParam *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
307INT_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
397MaxEggPlugin::MaxEggPlugin() :
398autoOverwrite(false), pview(true), logOutput(false), numEggs(0), maxEggs(5)
399{
400 eggList = new MaxOptionsDialog*[maxEggs];
401 BuildMesh();
402}
403
404MaxEggPlugin::~MaxEggPlugin() {
405 for (int i = 0; i < numEggs; i++) delete eggList[i];
406 delete [] eggList;
407}
408
409void 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
422void 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
430void 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
451void 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
463void 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
470void 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
522void 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
598void 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
626class MaxEggPluginCreateMouseCallBack: public CreateMouseCallBack
627{
628public:
629 int proc( ViewExp *vpt,int msg, int point, int flags, IPoint2 m, Matrix3& mat );
630};
631
632int 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
650static MaxEggPluginCreateMouseCallBack MaxEggCreateMouseCB;
651
652CreateMouseCallBack* MaxEggPlugin::GetCreateMouseCallBack()
653{ return &MaxEggCreateMouseCB; }
654
655// Boilerplate functions for dealing with the display of the plugin
656
657void 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
665void MaxEggPlugin::GetDeformBBox(TimeValue t, Box3& box, Matrix3 *tm, BOOL useSel )
666{
667 box = mesh.getBoundingBox(tm);
668}
669
670void 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
680void 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
690int 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
707int 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
725RefResult MaxEggPlugin::NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget, PartID& partID, RefMessage message )
726{
727 UpdateUI();
728 return REF_SUCCEED;
729}
730
731ObjectState MaxEggPlugin::Eval(TimeValue time)
732{
733 return ObjectState(this);
734}
735
736Interval MaxEggPlugin::ObjectValidity(TimeValue t)
737{
738 Interval ivalid;
739 ivalid.SetInfinite();
740 return ivalid;
741}
742
743RefTargetHandle MaxEggPlugin::Clone(RemapDir& remap)
744{
745 MaxEggPlugin* newob = new MaxEggPlugin();
746 return(newob);
747}
748
749// Loading and saving the plugin
750
751IOResult 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
762IOResult 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
791extern ClassDesc* GetMaxEggPluginDesc();
792
793HINSTANCE hInstance;
794int 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
802BOOL 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
853TCHAR *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}
A window, fullscreen or on a desktop, into which a graphics device sends its output for interactive d...
Encodes a string name in a hash table, mapping it to a pointer.
Defines the way an object appears in the presence of lighting.
Definition material.h:43
This class supervises the construction of an EggData structure from a Max model.
bool convert(MaxEggOptions *options)
Fills up the egg_data structure according to the global Max model data.