diff options
Diffstat (limited to 'Magic2/MaterialDialog.cpp')
-rw-r--r-- | Magic2/MaterialDialog.cpp | 717 |
1 files changed, 717 insertions, 0 deletions
diff --git a/Magic2/MaterialDialog.cpp b/Magic2/MaterialDialog.cpp new file mode 100644 index 0000000..15d13a8 --- /dev/null +++ b/Magic2/MaterialDialog.cpp @@ -0,0 +1,717 @@ +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + SUBSYSTEM: Magic.exe + FILE: MaterialDialog.h + AUTHOR: John DiCamillo + + + OVERVIEW + ======== + Material Editor Dialog interface file +*/ + +#include "stdafx.h" +#include "Magic.h" +#include "MagicDoc.h" +#include "MagicView.h" +#include "MaterialDialog.h" +#include "Selection.h" +#include "Selector.h" +#include "Thumbnail.h" + +#include "Bitmap.h" +#include "Polygon.h" +#include "Solid.h" +#include "Video.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +inline int BlendModeToSelection(int mode) +{ + switch (mode) { + case Material::MTL_SOLID: return 0; + case Material::MTL_TRANSLUCENT: return 1; + case Material::MTL_ADDITIVE: return 2; + } + + return 0; +} + +inline int SelectionToBlendMode(int sel) +{ + switch (sel) { + case 0: return Material::MTL_SOLID; + case 1: return Material::MTL_TRANSLUCENT; + case 2: return Material::MTL_ADDITIVE; + } + + return Material::MTL_SOLID; +} + +// +--------------------------------------------------------------------+ +// MaterialDialog dialog +// +--------------------------------------------------------------------+ + +static Material emergency_material; + +MaterialDialog::MaterialDialog(MagicView* pParent /*=NULL*/) + : CDialog(MaterialDialog::IDD, pParent), solid(0), material(0), doc(0) +{ + //{{AFX_DATA_INIT(MaterialDialog) + mAmbientValue = 0.0; + mBrillianceValue = 0.0; + mBumpValue = 0.0; + mDiffuseValue = 0.0; + mEmissiveValue = 0.0; + mMaterialName = _T(""); + mPowerValue = 0.0; + mSpecularValue = 0.0; + mSpecularTexture = _T(""); + mDiffuseTexture = _T(""); + mBumpTexture = _T(""); + mEmissiveTexture = _T(""); + mMaterialShader = _T(""); + //}}AFX_DATA_INIT + + doc = pParent->GetDocument(); + + if (doc && doc->GetSolid()) { + solid = doc->GetSolid(); + + Selection* seln = doc->GetSelection(); + + if (seln->GetPolys().size() > 0) { + material = seln->GetPolys().first()->material; + } + } +} + +MaterialDialog::~MaterialDialog() +{ +} + + +void MaterialDialog::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(MaterialDialog) + DDX_Control(pDX, IDC_SHADOW, mShadowList); + DDX_Control(pDX, IDC_BLEND_MODE, mBlendModeList); + DDX_Control(pDX, IDC_MATERIAL_LIST, mMaterialList); + DDX_Control(pDX, IDC_MATERIAL_PREVIEW, mMaterialThumb); + DDX_Control(pDX, IDC_SPECULAR_COLOR, mSpecularColor); + DDX_Control(pDX, IDC_EMISSIVE_COLOR, mEmissiveColor); + DDX_Control(pDX, IDC_DIFFUSE_COLOR, mDiffuseColor); + DDX_Control(pDX, IDC_AMBIENT_COLOR, mAmbientColor); + DDX_Text(pDX, IDC_AMBIENT_VALUE, mAmbientValue); + DDX_Text(pDX, IDC_BRILLIANCE_VALUE, mBrillianceValue); + DDX_Text(pDX, IDC_BUMP_VALUE, mBumpValue); + DDX_Text(pDX, IDC_DIFFUSE_VALUE, mDiffuseValue); + DDX_Text(pDX, IDC_EMISSIVE_VALUE, mEmissiveValue); + DDX_Text(pDX, IDC_MATERIAL_NAME, mMaterialName); + DDX_Text(pDX, IDC_POWER_VALUE, mPowerValue); + DDX_Text(pDX, IDC_SPECULAR_VALUE, mSpecularValue); + DDX_Text(pDX, IDC_SPECULAR_TEXTURE, mSpecularTexture); + DDX_Text(pDX, IDC_DIFFUSE_TEXTURE, mDiffuseTexture); + DDX_Text(pDX, IDC_BUMP_TEXTURE, mBumpTexture); + DDX_Text(pDX, IDC_EMISSIVE_TEXTURE, mEmissiveTexture); + DDX_Text(pDX, IDC_MATERIAL_SHADER, mMaterialShader); + //}}AFX_DATA_MAP + + if (!pDX->m_bSaveAndValidate) { + if (solid && solid->GetModel()) { + mMaterialList.ResetContent(); + + Model* model = solid->GetModel(); + for (int i = 0; i < model->NumMaterials(); i++) { + Material* m = model->GetMaterials()[i]; + mMaterialList.AddString(m->name); + + if (m == material) + mMaterialList.SetCurSel(i); + } + } + + if (mBlendModeList.GetSafeHwnd()) + mBlendModeList.SetCurSel(BlendModeToSelection(material->blend)); + + if (mShadowList.GetSafeHwnd()) + mShadowList.SetCurSel(material->shadow); + } +} + + +BEGIN_MESSAGE_MAP(MaterialDialog, CDialog) + //{{AFX_MSG_MAP(MaterialDialog) + ON_WM_PAINT() + ON_BN_CLICKED(IDC_AMBIENT_COLOR, OnAmbientColor) + ON_BN_CLICKED(IDC_DIFFUSE_COLOR, OnDiffuseColor) + ON_BN_CLICKED(IDC_EMISSIVE_COLOR, OnEmissiveColor) + ON_BN_CLICKED(IDC_SPECULAR_COLOR, OnSpecularColor) + ON_WM_DRAWITEM() + ON_EN_CHANGE(IDC_AMBIENT_VALUE, OnChangeMaterialValue) + ON_BN_CLICKED(IDC_FILE_DIFFUSE, OnFileDiffuse) + ON_BN_CLICKED(IDC_FILE_SPECULAR, OnFileSpecular) + ON_BN_CLICKED(IDC_FILE_EMISSIVE, OnFileEmissive) + ON_BN_CLICKED(IDC_FILE_BUMP, OnFileBump) + ON_EN_CHANGE(IDC_DIFFUSE_TEXTURE, OnChangeDiffuseTexture) + ON_EN_CHANGE(IDC_SPECULAR_TEXTURE, OnChangeSpecularTexture) + ON_EN_CHANGE(IDC_EMISSIVE_TEXTURE, OnChangeEmissiveTexture) + ON_EN_CHANGE(IDC_BUMP_TEXTURE, OnChangeBumpTexture) + ON_EN_CHANGE(IDC_MATERIAL_NAME, OnChangeMaterialName) + ON_LBN_SELCHANGE(IDC_MATERIAL_LIST, OnSelectMaterial) + ON_BN_CLICKED(IDC_SELECT_POLYS, OnSelectPolys) + ON_BN_CLICKED(IDC_NEW_MATERIAL, OnNewMaterial) + ON_BN_CLICKED(IDC_DEL_MATERIAL, OnDelMaterial) + ON_CBN_SELCHANGE(IDC_BLEND_MODE, OnSelectBlendMode) + ON_CBN_SELCHANGE(IDC_SHADOW, OnSelectShadow) + ON_EN_CHANGE(IDC_BRILLIANCE_VALUE, OnChangeMaterialValue) + ON_EN_CHANGE(IDC_BUMP_VALUE, OnChangeMaterialValue) + ON_EN_CHANGE(IDC_DIFFUSE_VALUE, OnChangeMaterialValue) + ON_EN_CHANGE(IDC_EMISSIVE_VALUE, OnChangeMaterialValue) + ON_EN_CHANGE(IDC_POWER_VALUE, OnChangeMaterialValue) + ON_EN_CHANGE(IDC_SPECULAR_VALUE, OnChangeMaterialValue) + ON_EN_CHANGE(IDC_MATERIAL_SHADER, OnChangeMaterialShader) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +// +--------------------------------------------------------------------+ + +void MaterialDialog::UpdateMaterial() +{ + if (material) { + UpdateData(); + + strcpy_s(material->name, mMaterialName); + strcpy_s(material->shader, mMaterialShader); + + material->ambient_value = mAmbientValue; + material->diffuse_value = mDiffuseValue; + material->specular_value = mSpecularValue; + material->emissive_value = mEmissiveValue; + material->power = mPowerValue; + material->brilliance = mBrillianceValue; + material->bump = mBumpValue; + material->blend = SelectionToBlendMode(mBlendModeList.GetCurSel()); + material->shadow = mShadowList.GetCurSel() ? true : false; + + material->Ka = ColorValue(material->ambient_color) * material->ambient_value; + material->Kd = ColorValue(material->diffuse_color) * material->diffuse_value; + material->Ks = ColorValue(material->specular_color) * material->specular_value; + material->Ke = ColorValue(material->emissive_color) * material->emissive_value; + + material->CreateThumbnail(); + + InvalidateRect(NULL, FALSE); + } +} + +// +--------------------------------------------------------------------+ +// MaterialDialog message handlers +// +--------------------------------------------------------------------+ + +BOOL MaterialDialog::OnInitDialog() +{ + if (solid && solid->GetModel() && !material) { + Model* model = solid->GetModel(); + + if (model->NumMaterials() > 0) + material = model->GetMaterials().first(); + } + + if (!material) + material = &emergency_material; + + mMaterialName = material->name; + mMaterialShader = material->shader; + mAmbientValue = material->ambient_value; + mDiffuseValue = material->diffuse_value; + mSpecularValue = material->specular_value; + mEmissiveValue = material->emissive_value; + mPowerValue = material->power; + mBrillianceValue = material->brilliance; + mBumpValue = material->bump; + + mDiffuseTexture = material->tex_diffuse ? + material->tex_diffuse->GetFilename() : ""; + + mSpecularTexture = material->tex_specular ? + material->tex_specular->GetFilename() : ""; + + mEmissiveTexture = material->tex_emissive ? + material->tex_emissive->GetFilename() : ""; + + mBumpTexture = material->tex_bumpmap ? + material->tex_bumpmap->GetFilename() : ""; + + CDialog::OnInitDialog(); + + UpdateMaterial(); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void MaterialDialog::OnPaint() +{ + CPaintDC dc(this); // device context for painting + + if (material && material->thumbnail) { + ThumbPreview(mMaterialThumb.GetSafeHwnd(), material->thumbnail); + } +} + +void MaterialDialog::OnAmbientColor() +{ + if (material) { + Color c = material->ambient_color; + COLORREF crgb = RGB(c.Red(), c.Green(), c.Blue()); + CColorDialog chooser(crgb); + + if (chooser.DoModal() == IDOK) { + crgb = chooser.GetColor(); + material->ambient_color = Color(GetRValue(crgb), GetGValue(crgb), GetBValue(crgb)); + UpdateMaterial(); + } + } +} + +void MaterialDialog::OnDiffuseColor() +{ + if (material) { + Color c = material->diffuse_color; + COLORREF crgb = RGB(c.Red(), c.Green(), c.Blue()); + CColorDialog chooser(crgb); + + if (chooser.DoModal() == IDOK) { + crgb = chooser.GetColor(); + material->diffuse_color = Color(GetRValue(crgb), GetGValue(crgb), GetBValue(crgb)); + UpdateMaterial(); + } + } +} + +void MaterialDialog::OnSpecularColor() +{ + if (material) { + Color c = material->specular_color; + COLORREF crgb = RGB(c.Red(), c.Green(), c.Blue()); + CColorDialog chooser(crgb); + + if (chooser.DoModal() == IDOK) { + crgb = chooser.GetColor(); + material->specular_color = Color(GetRValue(crgb), GetGValue(crgb), GetBValue(crgb)); + UpdateMaterial(); + } + } +} + +void MaterialDialog::OnEmissiveColor() +{ + if (material) { + Color c = material->emissive_color; + COLORREF crgb = RGB(c.Red(), c.Green(), c.Blue()); + CColorDialog chooser(crgb); + + if (chooser.DoModal() == IDOK) { + crgb = chooser.GetColor(); + material->emissive_color = Color(GetRValue(crgb), GetGValue(crgb), GetBValue(crgb)); + UpdateMaterial(); + } + } +} + +void MaterialDialog::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct) +{ + CWnd* wnd = GetDlgItem(nIDCtl); + Color c = Color::LightGray; + + if (material) { + if (wnd->GetSafeHwnd() == mAmbientColor.GetSafeHwnd()) + c = material->ambient_color; + + else if (wnd->GetSafeHwnd() == mDiffuseColor.GetSafeHwnd()) + c = material->diffuse_color; + + else if (wnd->GetSafeHwnd() == mSpecularColor.GetSafeHwnd()) + c = material->specular_color; + + else if (wnd->GetSafeHwnd() == mEmissiveColor.GetSafeHwnd()) + c = material->emissive_color; + } + + CBrush brush(RGB(c.Red(), c.Green(), c.Blue())); + + ::FillRect(lpDrawItemStruct->hDC, + &lpDrawItemStruct->rcItem, + brush); + + CDialog::OnDrawItem(nIDCtl, lpDrawItemStruct); +} + +// +--------------------------------------------------------------------+ + +void MaterialDialog::OnChangeMaterialValue() +{ + UpdateMaterial(); +} + +// +--------------------------------------------------------------------+ + +void MaterialDialog::OnFileTexture(int type) +{ + if (!material) + return; + + char filename[512]; + filename[0] = '\0'; + CFileDialog ofd(TRUE, "pcx"); + + 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"; + ofd.m_ofn.lpstrFile = filename; + ofd.m_ofn.nMaxFile = sizeof(filename); + + if (ofd.DoModal() != IDOK) + return; + + char tex_name[512]; + sprintf_s(tex_name, "%s", ofd.GetFileName().GetBuffer(0)); + + ChangeFileTexture(tex_name, type); +} + +void MaterialDialog::ChangeFileTexture(char* fname, int type) +{ + Bitmap* bmp = 0; + + LoadTexture(fname, bmp); + + if (bmp) { + switch (type) { + case 0: + material->tex_diffuse = bmp; + mDiffuseTexture = fname; + break; + + case 1: + material->tex_specular = bmp; + mSpecularTexture = fname; + break; + + case 2: + material->tex_emissive = bmp; + mEmissiveTexture = fname; + break; + + case 3: + material->tex_bumpmap = bmp; + mBumpTexture = fname; + break; + } + + UpdateData(FALSE); + UpdateMaterial(); + } +} + +void MaterialDialog::OnFileDiffuse() +{ + OnFileTexture(0); +} + +void MaterialDialog::OnFileSpecular() +{ + OnFileTexture(1); +} + +void MaterialDialog::OnFileEmissive() +{ + OnFileTexture(2); +} + +void MaterialDialog::OnFileBump() +{ + OnFileTexture(3); +} + +void MaterialDialog::OnChangeDiffuseTexture() +{ + if (material) { + UpdateData(); + + if (mDiffuseTexture.GetLength() < 1) { + material->tex_diffuse = 0; + UpdateMaterial(); + return; + } + + char* filename = mDiffuseTexture.LockBuffer(); + ChangeFileTexture(filename, 0); + mDiffuseTexture.UnlockBuffer(); + } +} + +void MaterialDialog::OnChangeSpecularTexture() +{ + if (material) { + UpdateData(); + + if (mSpecularTexture.GetLength() < 1) { + material->tex_specular = 0; + UpdateMaterial(); + return; + } + + char* filename = mSpecularTexture.LockBuffer(); + ChangeFileTexture(filename, 1); + mSpecularTexture.UnlockBuffer(); + } +} + +void MaterialDialog::OnChangeEmissiveTexture() +{ + if (material) { + UpdateData(); + + if (mEmissiveTexture.GetLength() < 1) { + material->tex_emissive = 0; + UpdateMaterial(); + return; + } + + char* filename = mEmissiveTexture.LockBuffer(); + ChangeFileTexture(filename, 2); + mEmissiveTexture.UnlockBuffer(); + } +} + +void MaterialDialog::OnChangeBumpTexture() +{ + if (material) { + UpdateData(); + + if (mBumpTexture.GetLength() < 1) { + material->tex_bumpmap = 0; + UpdateMaterial(); + return; + } + + char* filename = mBumpTexture.LockBuffer(); + ChangeFileTexture(filename, 3); + mBumpTexture.UnlockBuffer(); + } +} + +// +--------------------------------------------------------------------+ + +void MaterialDialog::OnChangeMaterialName() +{ + if (material) { + UpdateData(); + strcpy_s(material->name, mMaterialName); + } +} + +void MaterialDialog::OnChangeMaterialShader() +{ + if (material) { + UpdateData(); + strcpy_s(material->shader, mMaterialShader); + } +} + +void MaterialDialog::OnSelectMaterial() +{ + int selected = mMaterialList.GetCurSel(); + Material* mtl = 0; + + if (solid && solid->GetModel()) { + Model* model = solid->GetModel(); + + if (model->NumMaterials() > 0 && selected < model->NumMaterials()) + mtl = model->GetMaterials()[selected]; + } + + if (!mtl) + mtl = &emergency_material; + + if (material != mtl) { + material = mtl; + + mMaterialName = material->name; + mMaterialShader = material->shader; + mAmbientValue = material->ambient_value; + mDiffuseValue = material->diffuse_value; + mSpecularValue = material->specular_value; + mEmissiveValue = material->emissive_value; + mPowerValue = material->power; + mBrillianceValue = material->brilliance; + mBumpValue = material->bump; + + mDiffuseTexture = material->tex_diffuse ? + material->tex_diffuse->GetFilename() : ""; + + mSpecularTexture = material->tex_specular ? + material->tex_specular->GetFilename() : ""; + + mEmissiveTexture = material->tex_emissive ? + material->tex_emissive->GetFilename() : ""; + + mBumpTexture = material->tex_bumpmap ? + material->tex_bumpmap->GetFilename() : ""; + + if (mBlendModeList.GetSafeHwnd()) + mBlendModeList.SetCurSel(BlendModeToSelection(material->blend)); + + if (mShadowList.GetSafeHwnd()) + mShadowList.SetCurSel(material->shadow); + + UpdateData(FALSE); + UpdateMaterial(); + } +} + +// +--------------------------------------------------------------------+ + +void MaterialDialog::OnNewMaterial() +{ + if (solid && material && material != &emergency_material) { + Model* model = solid->GetModel(); + Material* mtl = new Material; + + if (model && mtl) { + mtl->Ka = Color::DarkGray; + mtl->Kd = Color::LightGray; + mtl->Ks = ColorValue(0.1f,0.1f,0.1f); + mtl->power = 10.0f; + + mtl->ambient_value = 0.2f; + mtl->ambient_color = Color::DarkGray; + mtl->diffuse_value = 0.8f; + mtl->diffuse_color = Color::LightGray; + mtl->specular_value = 0.5f; + mtl->specular_color = Color::White; + strcpy_s(mtl->name, "(new)"); + + model->GetMaterials().append(mtl); + + material = 0; + mMaterialList.AddString(mtl->name); + mMaterialList.SetCurSel(model->NumMaterials()-1); + + mBlendModeList.SetCurSel(0); + mShadowList.SetCurSel(1); + + OnSelectMaterial(); + } + } +} + +void MaterialDialog::OnDelMaterial() +{ + if (solid && material && material != &emergency_material) { + Model* model = solid->GetModel(); + + // do not delete the last material: + if (model->NumMaterials() > 1 && model->GetMaterials().contains(material)) { + Material* mtl = model->GetMaterials().first(); + + if (mtl == material) + mtl = model->GetMaterials()[1]; + + // reassign the material for any polys and segments + // that are using the one we are about to delete: + ListIter<Surface> iter = model->GetSurfaces(); + + while (++iter) { + Surface* s = iter.value(); + + for (int i = 0; i < s->NumPolys(); i++) { + Poly* p = s->GetPolys() + i; + + if (p->material == material) { + p->material = mtl; + } + } + + ListIter<Segment> seg_iter = s->GetSegments(); + while (++seg_iter) { + Segment* segment = seg_iter.value(); + if (segment->material == material) + segment->material = mtl; + } + } + + // now delete the material: + model->GetMaterials().remove(material); + delete material; + + material = 0; + mMaterialList.SetCurSel(0); + OnSelectMaterial(); + } + } +} + +void MaterialDialog::OnSelectPolys() +{ + if (solid && doc && doc->GetSelector()) { + Selector* selector = doc->GetSelector(); + + if (!material || material == &emergency_material) + selector->SelectMaterial(0); + else + selector->SelectMaterial(material); + } +} + +void MaterialDialog::OnSelectBlendMode() +{ + if (material) + material->blend = SelectionToBlendMode(mBlendModeList.GetCurSel()); +} + +void MaterialDialog::OnSelectShadow() +{ + if (material) + material->shadow = mShadowList.GetCurSel() ? true : false; +} + +void MaterialDialog::OnOK() +{ + Video* video = Video::GetInstance(); + if (video) + video->InvalidateCache(); + + CDialog::OnOK(); +} |