Starshatter_Open
Open source Starshatter engine
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
MaterialDialog.cpp
Go to the documentation of this file.
1 /* Project Magic 2.0
2  Destroyer Studios LLC
3  Copyright © 1997-2004. All Rights Reserved.
4 
5  SUBSYSTEM: Magic.exe
6  FILE: MaterialDialog.h
7  AUTHOR: John DiCamillo
8 
9 
10  OVERVIEW
11  ========
12  Material Editor Dialog interface file
13 */
14 
15 #include "stdafx.h"
16 #include "Magic.h"
17 #include "MagicDoc.h"
18 #include "MagicView.h"
19 #include "MaterialDialog.h"
20 #include "Selection.h"
21 #include "Selector.h"
22 #include "Thumbnail.h"
23 
24 #include "Bitmap.h"
25 #include "Polygon.h"
26 #include "Solid.h"
27 #include "Video.h"
28 
29 #ifdef _DEBUG
30 #define new DEBUG_NEW
31 #undef THIS_FILE
32 static char THIS_FILE[] = __FILE__;
33 #endif
34 
35 inline int BlendModeToSelection(int mode)
36 {
37  switch (mode) {
38  case Material::MTL_SOLID: return 0;
39  case Material::MTL_TRANSLUCENT: return 1;
40  case Material::MTL_ADDITIVE: return 2;
41  }
42 
43  return 0;
44 }
45 
46 inline int SelectionToBlendMode(int sel)
47 {
48  switch (sel) {
49  case 0: return Material::MTL_SOLID;
50  case 1: return Material::MTL_TRANSLUCENT;
51  case 2: return Material::MTL_ADDITIVE;
52  }
53 
54  return Material::MTL_SOLID;
55 }
56 
57 // +--------------------------------------------------------------------+
58 // MaterialDialog dialog
59 // +--------------------------------------------------------------------+
60 
61 static Material emergency_material;
62 
64  : CDialog(MaterialDialog::IDD, pParent), solid(0), material(0), doc(0)
65 {
66  //{{AFX_DATA_INIT(MaterialDialog)
67  mAmbientValue = 0.0;
68  mBrillianceValue = 0.0;
69  mBumpValue = 0.0;
70  mDiffuseValue = 0.0;
71  mEmissiveValue = 0.0;
72  mMaterialName = _T("");
73  mPowerValue = 0.0;
74  mSpecularValue = 0.0;
75  mSpecularTexture = _T("");
76  mDiffuseTexture = _T("");
77  mBumpTexture = _T("");
78  mEmissiveTexture = _T("");
79  mMaterialShader = _T("");
80  //}}AFX_DATA_INIT
81 
82  doc = pParent->GetDocument();
83 
84  if (doc && doc->GetSolid()) {
85  solid = doc->GetSolid();
86 
87  Selection* seln = doc->GetSelection();
88 
89  if (seln->GetPolys().size() > 0) {
90  material = seln->GetPolys().first()->material;
91  }
92  }
93 }
94 
96 {
97 }
98 
99 
100 void MaterialDialog::DoDataExchange(CDataExchange* pDX)
101 {
103  //{{AFX_DATA_MAP(MaterialDialog)
104  DDX_Control(pDX, IDC_SHADOW, mShadowList);
105  DDX_Control(pDX, IDC_BLEND_MODE, mBlendModeList);
106  DDX_Control(pDX, IDC_MATERIAL_LIST, mMaterialList);
107  DDX_Control(pDX, IDC_MATERIAL_PREVIEW, mMaterialThumb);
108  DDX_Control(pDX, IDC_SPECULAR_COLOR, mSpecularColor);
109  DDX_Control(pDX, IDC_EMISSIVE_COLOR, mEmissiveColor);
110  DDX_Control(pDX, IDC_DIFFUSE_COLOR, mDiffuseColor);
111  DDX_Control(pDX, IDC_AMBIENT_COLOR, mAmbientColor);
112  DDX_Text(pDX, IDC_AMBIENT_VALUE, mAmbientValue);
113  DDX_Text(pDX, IDC_BRILLIANCE_VALUE, mBrillianceValue);
114  DDX_Text(pDX, IDC_BUMP_VALUE, mBumpValue);
115  DDX_Text(pDX, IDC_DIFFUSE_VALUE, mDiffuseValue);
116  DDX_Text(pDX, IDC_EMISSIVE_VALUE, mEmissiveValue);
117  DDX_Text(pDX, IDC_MATERIAL_NAME, mMaterialName);
118  DDX_Text(pDX, IDC_POWER_VALUE, mPowerValue);
119  DDX_Text(pDX, IDC_SPECULAR_VALUE, mSpecularValue);
120  DDX_Text(pDX, IDC_SPECULAR_TEXTURE, mSpecularTexture);
121  DDX_Text(pDX, IDC_DIFFUSE_TEXTURE, mDiffuseTexture);
122  DDX_Text(pDX, IDC_BUMP_TEXTURE, mBumpTexture);
123  DDX_Text(pDX, IDC_EMISSIVE_TEXTURE, mEmissiveTexture);
124  DDX_Text(pDX, IDC_MATERIAL_SHADER, mMaterialShader);
125  //}}AFX_DATA_MAP
126 
127  if (!pDX->m_bSaveAndValidate) {
128  if (solid && solid->GetModel()) {
129  mMaterialList.ResetContent();
130 
131  Model* model = solid->GetModel();
132  for (int i = 0; i < model->NumMaterials(); i++) {
133  Material* m = model->GetMaterials()[i];
134  mMaterialList.AddString(m->name);
135 
136  if (m == material)
137  mMaterialList.SetCurSel(i);
138  }
139  }
140 
141  if (mBlendModeList.GetSafeHwnd())
143 
144  if (mShadowList.GetSafeHwnd())
145  mShadowList.SetCurSel(material->shadow);
146  }
147 }
148 
149 
150 BEGIN_MESSAGE_MAP(MaterialDialog, CDialog)
151  //{{AFX_MSG_MAP(MaterialDialog)
152  ON_WM_PAINT()
153  ON_BN_CLICKED(IDC_AMBIENT_COLOR, OnAmbientColor)
154  ON_BN_CLICKED(IDC_DIFFUSE_COLOR, OnDiffuseColor)
155  ON_BN_CLICKED(IDC_EMISSIVE_COLOR, OnEmissiveColor)
156  ON_BN_CLICKED(IDC_SPECULAR_COLOR, OnSpecularColor)
157  ON_WM_DRAWITEM()
158  ON_EN_CHANGE(IDC_AMBIENT_VALUE, OnChangeMaterialValue)
159  ON_BN_CLICKED(IDC_FILE_DIFFUSE, OnFileDiffuse)
160  ON_BN_CLICKED(IDC_FILE_SPECULAR, OnFileSpecular)
161  ON_BN_CLICKED(IDC_FILE_EMISSIVE, OnFileEmissive)
162  ON_BN_CLICKED(IDC_FILE_BUMP, OnFileBump)
163  ON_EN_CHANGE(IDC_DIFFUSE_TEXTURE, OnChangeDiffuseTexture)
164  ON_EN_CHANGE(IDC_SPECULAR_TEXTURE, OnChangeSpecularTexture)
165  ON_EN_CHANGE(IDC_EMISSIVE_TEXTURE, OnChangeEmissiveTexture)
166  ON_EN_CHANGE(IDC_BUMP_TEXTURE, OnChangeBumpTexture)
167  ON_EN_CHANGE(IDC_MATERIAL_NAME, OnChangeMaterialName)
168  ON_LBN_SELCHANGE(IDC_MATERIAL_LIST, OnSelectMaterial)
169  ON_BN_CLICKED(IDC_SELECT_POLYS, OnSelectPolys)
170  ON_BN_CLICKED(IDC_NEW_MATERIAL, OnNewMaterial)
171  ON_BN_CLICKED(IDC_DEL_MATERIAL, OnDelMaterial)
172  ON_CBN_SELCHANGE(IDC_BLEND_MODE, OnSelectBlendMode)
173  ON_CBN_SELCHANGE(IDC_SHADOW, OnSelectShadow)
174  ON_EN_CHANGE(IDC_BRILLIANCE_VALUE, OnChangeMaterialValue)
175  ON_EN_CHANGE(IDC_BUMP_VALUE, OnChangeMaterialValue)
176  ON_EN_CHANGE(IDC_DIFFUSE_VALUE, OnChangeMaterialValue)
177  ON_EN_CHANGE(IDC_EMISSIVE_VALUE, OnChangeMaterialValue)
178  ON_EN_CHANGE(IDC_POWER_VALUE, OnChangeMaterialValue)
179  ON_EN_CHANGE(IDC_SPECULAR_VALUE, OnChangeMaterialValue)
180  ON_EN_CHANGE(IDC_MATERIAL_SHADER, OnChangeMaterialShader)
181  //}}AFX_MSG_MAP
182 END_MESSAGE_MAP()
183 
184 // +--------------------------------------------------------------------+
185 
186 void MaterialDialog::UpdateMaterial()
187 {
188  if (material) {
189  UpdateData();
190 
191  strcpy_s(material->name, mMaterialName);
192  strcpy_s(material->shader, mMaterialShader);
193 
194  material->ambient_value = mAmbientValue;
195  material->diffuse_value = mDiffuseValue;
196  material->specular_value = mSpecularValue;
197  material->emissive_value = mEmissiveValue;
198  material->power = mPowerValue;
199  material->brilliance = mBrillianceValue;
200  material->bump = mBumpValue;
201  material->blend = SelectionToBlendMode(mBlendModeList.GetCurSel());
202  material->shadow = mShadowList.GetCurSel() ? true : false;
203 
204  material->Ka = ColorValue(material->ambient_color) * material->ambient_value;
205  material->Kd = ColorValue(material->diffuse_color) * material->diffuse_value;
206  material->Ks = ColorValue(material->specular_color) * material->specular_value;
207  material->Ke = ColorValue(material->emissive_color) * material->emissive_value;
208 
209  material->CreateThumbnail();
210 
211  InvalidateRect(NULL, FALSE);
212  }
213 }
214 
215 // +--------------------------------------------------------------------+
216 // MaterialDialog message handlers
217 // +--------------------------------------------------------------------+
218 
220 {
221  if (solid && solid->GetModel() && !material) {
222  Model* model = solid->GetModel();
223 
224  if (model->NumMaterials() > 0)
225  material = model->GetMaterials().first();
226  }
227 
228  if (!material)
229  material = &emergency_material;
230 
240 
243 
246 
249 
252 
254 
255  UpdateMaterial();
256 
257  return TRUE; // return TRUE unless you set the focus to a control
258  // EXCEPTION: OCX Property Pages should return FALSE
259 }
260 
262 {
263  CPaintDC dc(this); // device context for painting
264 
265  if (material && material->thumbnail) {
267  }
268 }
269 
271 {
272  if (material) {
274  COLORREF crgb = RGB(c.Red(), c.Green(), c.Blue());
275  CColorDialog chooser(crgb);
276 
277  if (chooser.DoModal() == IDOK) {
278  crgb = chooser.GetColor();
279  material->ambient_color = Color(GetRValue(crgb), GetGValue(crgb), GetBValue(crgb));
280  UpdateMaterial();
281  }
282  }
283 }
284 
286 {
287  if (material) {
289  COLORREF crgb = RGB(c.Red(), c.Green(), c.Blue());
290  CColorDialog chooser(crgb);
291 
292  if (chooser.DoModal() == IDOK) {
293  crgb = chooser.GetColor();
294  material->diffuse_color = Color(GetRValue(crgb), GetGValue(crgb), GetBValue(crgb));
295  UpdateMaterial();
296  }
297  }
298 }
299 
301 {
302  if (material) {
304  COLORREF crgb = RGB(c.Red(), c.Green(), c.Blue());
305  CColorDialog chooser(crgb);
306 
307  if (chooser.DoModal() == IDOK) {
308  crgb = chooser.GetColor();
309  material->specular_color = Color(GetRValue(crgb), GetGValue(crgb), GetBValue(crgb));
310  UpdateMaterial();
311  }
312  }
313 }
314 
316 {
317  if (material) {
319  COLORREF crgb = RGB(c.Red(), c.Green(), c.Blue());
320  CColorDialog chooser(crgb);
321 
322  if (chooser.DoModal() == IDOK) {
323  crgb = chooser.GetColor();
324  material->emissive_color = Color(GetRValue(crgb), GetGValue(crgb), GetBValue(crgb));
325  UpdateMaterial();
326  }
327  }
328 }
329 
330 void MaterialDialog::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct)
331 {
332  CWnd* wnd = GetDlgItem(nIDCtl);
334 
335  if (material) {
336  if (wnd->GetSafeHwnd() == mAmbientColor.GetSafeHwnd())
337  c = material->ambient_color;
338 
339  else if (wnd->GetSafeHwnd() == mDiffuseColor.GetSafeHwnd())
340  c = material->diffuse_color;
341 
342  else if (wnd->GetSafeHwnd() == mSpecularColor.GetSafeHwnd())
344 
345  else if (wnd->GetSafeHwnd() == mEmissiveColor.GetSafeHwnd())
347  }
348 
349  CBrush brush(RGB(c.Red(), c.Green(), c.Blue()));
350 
351  ::FillRect(lpDrawItemStruct->hDC,
352  &lpDrawItemStruct->rcItem,
353  brush);
354 
355  CDialog::OnDrawItem(nIDCtl, lpDrawItemStruct);
356 }
357 
358 // +--------------------------------------------------------------------+
359 
361 {
362  UpdateMaterial();
363 }
364 
365 // +--------------------------------------------------------------------+
366 
368 {
369  if (!material)
370  return;
371 
372  char filename[512];
373  filename[0] = '\0';
374  CFileDialog ofd(TRUE, "pcx");
375 
376  ofd.m_ofn.lpstrFilter = "All Image Files\0*.bmp; *.dds; *.jpg; *.pcx; *.png; *.tga\0Bitmap Files (*.bmp)\0*.bmp\0JPEG Files (*.jpg)\0*.pcx\0PCX Files (*.pcx)\0*.pcx\0PNG Files (*.png)\0*.png\0Truevision Targa Files (*.tga)\0*.png\0All Files\0*.*\0\0";
377  ofd.m_ofn.lpstrFile = filename;
378  ofd.m_ofn.nMaxFile = sizeof(filename);
379 
380  if (ofd.DoModal() != IDOK)
381  return;
382 
383  char tex_name[512];
384  sprintf_s(tex_name, "%s", ofd.GetFileName().GetBuffer(0));
385 
386  ChangeFileTexture(tex_name, type);
387 }
388 
389 void MaterialDialog::ChangeFileTexture(char* fname, int type)
390 {
391  Bitmap* bmp = 0;
392 
393  LoadTexture(fname, bmp);
394 
395  if (bmp) {
396  switch (type) {
397  case 0:
398  material->tex_diffuse = bmp;
399  mDiffuseTexture = fname;
400  break;
401 
402  case 1:
403  material->tex_specular = bmp;
404  mSpecularTexture = fname;
405  break;
406 
407  case 2:
408  material->tex_emissive = bmp;
409  mEmissiveTexture = fname;
410  break;
411 
412  case 3:
413  material->tex_bumpmap = bmp;
414  mBumpTexture = fname;
415  break;
416  }
417 
418  UpdateData(FALSE);
419  UpdateMaterial();
420  }
421 }
422 
424 {
425  OnFileTexture(0);
426 }
427 
429 {
430  OnFileTexture(1);
431 }
432 
434 {
435  OnFileTexture(2);
436 }
437 
439 {
440  OnFileTexture(3);
441 }
442 
444 {
445  if (material) {
446  UpdateData();
447 
448  if (mDiffuseTexture.GetLength() < 1) {
449  material->tex_diffuse = 0;
450  UpdateMaterial();
451  return;
452  }
453 
454  char* filename = mDiffuseTexture.LockBuffer();
455  ChangeFileTexture(filename, 0);
456  mDiffuseTexture.UnlockBuffer();
457  }
458 }
459 
461 {
462  if (material) {
463  UpdateData();
464 
465  if (mSpecularTexture.GetLength() < 1) {
466  material->tex_specular = 0;
467  UpdateMaterial();
468  return;
469  }
470 
471  char* filename = mSpecularTexture.LockBuffer();
472  ChangeFileTexture(filename, 1);
473  mSpecularTexture.UnlockBuffer();
474  }
475 }
476 
478 {
479  if (material) {
480  UpdateData();
481 
482  if (mEmissiveTexture.GetLength() < 1) {
483  material->tex_emissive = 0;
484  UpdateMaterial();
485  return;
486  }
487 
488  char* filename = mEmissiveTexture.LockBuffer();
489  ChangeFileTexture(filename, 2);
490  mEmissiveTexture.UnlockBuffer();
491  }
492 }
493 
495 {
496  if (material) {
497  UpdateData();
498 
499  if (mBumpTexture.GetLength() < 1) {
500  material->tex_bumpmap = 0;
501  UpdateMaterial();
502  return;
503  }
504 
505  char* filename = mBumpTexture.LockBuffer();
506  ChangeFileTexture(filename, 3);
507  mBumpTexture.UnlockBuffer();
508  }
509 }
510 
511 // +--------------------------------------------------------------------+
512 
514 {
515  if (material) {
516  UpdateData();
517  strcpy_s(material->name, mMaterialName);
518  }
519 }
520 
522 {
523  if (material) {
524  UpdateData();
525  strcpy_s(material->shader, mMaterialShader);
526  }
527 }
528 
530 {
531  int selected = mMaterialList.GetCurSel();
532  Material* mtl = 0;
533 
534  if (solid && solid->GetModel()) {
535  Model* model = solid->GetModel();
536 
537  if (model->NumMaterials() > 0 && selected < model->NumMaterials())
538  mtl = model->GetMaterials()[selected];
539  }
540 
541  if (!mtl)
542  mtl = &emergency_material;
543 
544  if (material != mtl) {
545  material = mtl;
546 
556 
559 
562 
565 
568 
569  if (mBlendModeList.GetSafeHwnd())
571 
572  if (mShadowList.GetSafeHwnd())
573  mShadowList.SetCurSel(material->shadow);
574 
575  UpdateData(FALSE);
576  UpdateMaterial();
577  }
578 }
579 
580 // +--------------------------------------------------------------------+
581 
583 {
584  if (solid && material && material != &emergency_material) {
585  Model* model = solid->GetModel();
586  Material* mtl = new Material;
587 
588  if (model && mtl) {
589  mtl->Ka = Color::DarkGray;
590  mtl->Kd = Color::LightGray;
591  mtl->Ks = ColorValue(0.1f,0.1f,0.1f);
592  mtl->power = 10.0f;
593 
594  mtl->ambient_value = 0.2f;
596  mtl->diffuse_value = 0.8f;
598  mtl->specular_value = 0.5f;
600  strcpy_s(mtl->name, "(new)");
601 
602  model->GetMaterials().append(mtl);
603 
604  material = 0;
605  mMaterialList.AddString(mtl->name);
606  mMaterialList.SetCurSel(model->NumMaterials()-1);
607 
608  mBlendModeList.SetCurSel(0);
609  mShadowList.SetCurSel(1);
610 
612  }
613  }
614 }
615 
617 {
618  if (solid && material && material != &emergency_material) {
619  Model* model = solid->GetModel();
620 
621  // do not delete the last material:
622  if (model->NumMaterials() > 1 && model->GetMaterials().contains(material)) {
623  Material* mtl = model->GetMaterials().first();
624 
625  if (mtl == material)
626  mtl = model->GetMaterials()[1];
627 
628  // reassign the material for any polys and segments
629  // that are using the one we are about to delete:
630  ListIter<Surface> iter = model->GetSurfaces();
631 
632  while (++iter) {
633  Surface* s = iter.value();
634 
635  for (int i = 0; i < s->NumPolys(); i++) {
636  Poly* p = s->GetPolys() + i;
637 
638  if (p->material == material) {
639  p->material = mtl;
640  }
641  }
642 
643  ListIter<Segment> seg_iter = s->GetSegments();
644  while (++seg_iter) {
645  Segment* segment = seg_iter.value();
646  if (segment->material == material)
647  segment->material = mtl;
648  }
649  }
650 
651  // now delete the material:
652  model->GetMaterials().remove(material);
653  delete material;
654 
655  material = 0;
656  mMaterialList.SetCurSel(0);
658  }
659  }
660 }
661 
663 {
664  if (solid && doc && doc->GetSelector()) {
665  Selector* selector = doc->GetSelector();
666 
667  if (!material || material == &emergency_material)
668  selector->SelectMaterial(0);
669  else
670  selector->SelectMaterial(material);
671  }
672 }
673 
675 {
676  if (material)
678 }
679 
681 {
682  if (material)
683  material->shadow = mShadowList.GetCurSel() ? true : false;
684 }
685 
687 {
688  Video* video = Video::GetInstance();
689  if (video)
690  video->InvalidateCache();
691 
692  CDialog::OnOK();
693 }