/* ** Command & Conquer Generals Zero Hour(tm) ** Copyright 2025 Electronic Arts Inc. ** ** This program is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 3 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program. If not, see . */ /*********************************************************************************************** *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S *** *********************************************************************************************** * * * Project Name : Max2W3d * * * * $Archive:: /Commando/Code/Tools/max2w3d/GameMtlDlg.cpp $* * * * Author:: Greg Hjelstrom * * * * $Modtime:: 12/07/00 5:52p $* * * * $Revision:: 12 $* * * *---------------------------------------------------------------------------------------------* * Functions: * * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #include #include #include #include #include "GameMtlDlg.h" #include "GameMtl.h" #include "GameMtlPassDlg.h" #include "dllmain.h" #include "resource.h" #include "w3d_file.h" static BOOL CALLBACK DisplacementMapDlgProc(HWND hwndDlg, UINT msg, WPARAM wPara,LPARAM lParam); static BOOL CALLBACK SurfaceTypePanelDlgProc(HWND hwndDlg, UINT msg, WPARAM wPara,LPARAM lParam); static BOOL CALLBACK PassCountPanelDlgProc(HWND hwndDlg, UINT msg, WPARAM wPara,LPARAM lParam); static BOOL CALLBACK PassCountDialogDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam,LPARAM lParam); static int _Pass_Index_To_Flag[] = { GAMEMTL_PASS0_ROLLUP_OPEN, GAMEMTL_PASS1_ROLLUP_OPEN, GAMEMTL_PASS2_ROLLUP_OPEN, GAMEMTL_PASS3_ROLLUP_OPEN, }; /*********************************************************************************************** * GameMtlDlg::GameMtlDlg -- constructor * * * * INPUT: * * hwMtlEdit - windows handle of the MAX material editor * * imp - Interface object for MAX materials and textures * * m - pointer to a GameMtl to be edited * * * * OUTPUT: * * * * WARNINGS: * * * * HISTORY: * * 06/26/1997 GH : Created. * *=============================================================================================*/ GameMtlDlg::GameMtlDlg(HWND hwMtlEdit, IMtlParams *imp, GameMtl *m) { HwndEdit = hwMtlEdit; HwndPassCount = NULL; HwndSurfaceType = NULL; HwndDisplacementMap = NULL; HpalOld = NULL; for (int i=0; iRestorePalette(hdc, HpalOld); ReleaseDC(HwndPassCount,hdc); } #ifdef WANT_DISPLACEMENT_MAPS TheMtl->Set_Flag(GAMEMTL_DISPLACEMENT_ROLLUP_OPEN,IParams->IsRollupPanelOpen(HwndDisplacementMap)); #endif //WANT_DISPLACEMENT_MAPS TheMtl->Set_Flag(GAMEMTL_SURFACE_ROLLUP_OPEN,IParams->IsRollupPanelOpen(HwndSurfaceType)); TheMtl->Set_Flag(GAMEMTL_PASSCOUNT_ROLLUP_OPEN,IParams->IsRollupPanelOpen(HwndPassCount)); TheMtl->RollScroll = IParams->GetRollupScrollPos(); IParams->UnRegisterDlgWnd(HwndSurfaceType); IParams->DeleteRollupPage(HwndSurfaceType); HwndSurfaceType = NULL; #ifdef WANT_DISPLACEMENT_MAPS IParams->UnRegisterDlgWnd(HwndDisplacementMap); IParams->DeleteRollupPage(HwndDisplacementMap); HwndDisplacementMap = NULL; #endif //#ifdef WANT_DISPLACEMENT_MAPS IParams->UnRegisterDlgWnd(HwndPassCount); IParams->DeleteRollupPage(HwndPassCount); HwndPassCount = NULL; for (int i=0; iSetParamDlg(NULL); } /*********************************************************************************************** * GameMtlDlg::ClassID -- Returns the ClassID of GameMtl * * * * INPUT: * * * * OUTPUT: * * * * WARNINGS: * * * * HISTORY: * * 06/26/1997 GH : Created. * *=============================================================================================*/ Class_ID GameMtlDlg::ClassID() { return GameMaterialClassID; } /*********************************************************************************************** * GameMtlDlg::SetThing -- Sets the material to be edited * * * * INPUT: * * * * OUTPUT: * * * * WARNINGS: * * * * HISTORY: * * 06/26/1997 GH : Created. * *=============================================================================================*/ void GameMtlDlg::SetThing(ReferenceTarget *m) { assert (m); assert (m->SuperClassID()==MATERIAL_CLASS_ID); assert ((m->ClassID()==GameMaterialClassID) || (m->ClassID()==PS2GameMaterialClassID)); assert (TheMtl); int pass; // destroy our old pass dialogs for (pass=0; passGet_Pass_Count();pass++) { delete PassDialog[pass]; PassDialog[pass] = NULL; } // install the new material TheMtl->SetParamDlg(NULL); TheMtl = (GameMtl *)m; TheMtl->SetParamDlg(this); // build a new set of pass dialogs for (pass=0; passGet_Pass_Count(); pass++) { PassDialog[pass] = new GameMtlPassDlg(HwndEdit, IParams, TheMtl, pass); } // refresh the contents of the dialogs ReloadDialog(); } /*********************************************************************************************** * GameMtlDlg::SetTime -- Sets the time value, updates the material and the dialog * * * * INPUT: * * * * OUTPUT: * * * * WARNINGS: * * * * HISTORY: * * 06/26/1997 GH : Created. * *=============================================================================================*/ void GameMtlDlg::SetTime(TimeValue t) { if (t!=CurTime) { CurTime = t; // TheMtl->Update(IParams->GetTime(),Valid); ReloadDialog(); } } /*********************************************************************************************** * GameMtlDlg::ReloadDialog -- Updates the values in all of the dialog's controls * * * * INPUT: * * * * OUTPUT: * * * * WARNINGS: * * * * HISTORY: * * 06/26/1997 GH : Created. * *=============================================================================================*/ void GameMtlDlg::ReloadDialog() { /* ** Init the pass count panel */ assert(TheMtl && HwndPassCount && HwndSurfaceType); /* ** Init the surface count panel */ ::SendMessage (HwndSurfaceType, WM_USER+101, 0, 0L); #ifdef WANT_DISPLACEMENT_MAPS ::SendMessage (HwndDisplacementMap, WM_USER+101, 0, 0L); #endif //WANT_DISPLACEMENT_MAPS /* ** Init the pass count panel */ char a[10]; sprintf(a, "%d", TheMtl->Get_Pass_Count()); SetWindowText(GetDlgItem(HwndPassCount, IDC_GAMEMTL_PASSCOUNT_STATIC), a); /* ** Init each pass panel */ for(int i = 0; i < TheMtl->Get_Pass_Count(); i++) { PassDialog[i]->ReloadDialog(); } } /*********************************************************************************************** * GameMtlDlg::ActivateDlg -- Activates and deactivates the dialog * * * * INPUT: * * * * OUTPUT: * * * * WARNINGS: * * * * HISTORY: * * 06/26/1997 GH : Created. * *=============================================================================================*/ void GameMtlDlg::ActivateDlg(BOOL onoff) { for(int i = 0; i < TheMtl->Get_Pass_Count(); i++) { assert(PassDialog[i]); PassDialog[i]->ActivateDlg(onoff); } } /*********************************************************************************************** * GameMtlDlg::Invalidate -- causes the dialog to be redrawn * * * * INPUT: * * * * OUTPUT: * * * * WARNINGS: * * * * HISTORY: * * 06/26/1997 GH : Created. * *=============================================================================================*/ void GameMtlDlg::Invalidate() { InvalidateRect(HwndSurfaceType,NULL,0); #ifdef WANT_DISPLACEMENT_MAPS InvalidateRect(HwndDisplacementMap,NULL,0); #endif //WANT_DISPLACEMENT_MAPS InvalidateRect(HwndPassCount,NULL,0); } BOOL GameMtlDlg::DisplacementMapProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_INITDIALOG: //SetupIntSpinner(hDlg, IDC_AMOUNT_SPIN, IDC_AMOUNT_EDIT, -999, 999, 0); /* no break */ case WM_USER + 101: { SetDlgItemInt (hDlg, IDC_AMOUNT_EDIT, TheMtl->Get_Displacement_Amount () * 100, TRUE); SetupIntSpinner(hDlg, IDC_AMOUNT_SPIN, IDC_AMOUNT_EDIT, -999, 999, TheMtl->Get_Displacement_Amount () * 100); Texmap *map = TheMtl->Get_Displacement_Map (); if (map != NULL) { SetDlgItemText (hDlg, IDC_TEXTURE_BUTTON, map->GetFullName ()); } } break; case CC_SPINNER_CHANGE: { ISpinnerControl *control = (ISpinnerControl *)lParam; TheMtl->Set_Displacement_Amount (((float)control->GetIVal ()) / 100.0F); } break; case WM_COMMAND: switch(LOWORD(wParam)) { case IDC_TEXTURE_BUTTON: if(HIWORD(wParam) == BN_CLICKED) { PostMessage(HwndEdit, WM_TEXMAP_BUTTON, TheMtl->Get_Displacement_Map_Index (), (LPARAM)TheMtl); } } break; } return FALSE; } BOOL GameMtlDlg::SurfaceTypeProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_INITDIALOG: { // // Fill the combobox with the names of the different surface types // for (int index = 0; index < SURFACE_TYPE_MAX; index ++) { ::SendDlgItemMessage ( hDlg, IDC_SURFACE_TYPE_COMBO, CB_ADDSTRING, 0, (LPARAM)SURFACE_TYPE_STRINGS[index]); } // // Limit the range of the static sort level spinner to 0 - MAX_SORT_LEVEL. // int sort_level = TheMtl->Get_Sort_Level(); SetupIntSpinner(hDlg, IDC_SORT_LEVEL_SPIN, IDC_SORT_LEVEL, 0, MAX_SORT_LEVEL, sort_level); // Check the checkbox if sort_level is not SORT_LEVEL_NONE. ::SendDlgItemMessage(hDlg, IDC_ENABLE_SORT_LEVEL, BM_SETCHECK, sort_level == SORT_LEVEL_NONE ? BST_UNCHECKED : BST_CHECKED, 0); } case WM_USER + 101: { // // Select the current surface type // ::SendDlgItemMessage ( hDlg, IDC_SURFACE_TYPE_COMBO, CB_SETCURSEL, (WPARAM)TheMtl->Get_Surface_Type (), 0L); // // Set the correct sort level // int sort_level = TheMtl->Get_Sort_Level(); ISpinnerControl *spinner = GetISpinner(::GetDlgItem(hDlg, IDC_SORT_LEVEL_SPIN)); assert(spinner); spinner->SetValue(sort_level, FALSE); ::SendDlgItemMessage(hDlg, IDC_ENABLE_SORT_LEVEL, BM_SETCHECK, sort_level == SORT_LEVEL_NONE ? BST_UNCHECKED : BST_CHECKED, 0); break; } case WM_COMMAND: { switch(LOWORD(wParam)) { case IDC_SURFACE_TYPE_COMBO: if(HIWORD(wParam) == CBN_SELCHANGE) { unsigned int type = ::SendDlgItemMessage (hDlg, IDC_SURFACE_TYPE_COMBO, CB_GETCURSEL, 0, 0L); TheMtl->Set_Surface_Type (type); } break; case IDC_ENABLE_SORT_LEVEL: if (HIWORD(wParam) == BN_CLICKED) { // If the 'enable' checkbox was unchecked, set the sort level to NONE. int state = ::IsDlgButtonChecked(hDlg, IDC_ENABLE_SORT_LEVEL); ISpinnerControl *spinner = GetISpinner(::GetDlgItem(hDlg, IDC_SORT_LEVEL_SPIN)); assert(spinner); if (state == BST_UNCHECKED) { spinner->SetValue(SORT_LEVEL_NONE, FALSE); TheMtl->Set_Sort_Level(SORT_LEVEL_NONE); } else if (state == BST_CHECKED) { // Sort level was enabled, so set it's level to 1 if it was NONE before. if (spinner->GetIVal() == SORT_LEVEL_NONE) { spinner->SetValue(1, FALSE); TheMtl->Set_Sort_Level(1); } } } } break; } case CC_SPINNER_CHANGE: { ISpinnerControl *spinner = (ISpinnerControl*)lParam; switch(LOWORD(wParam)) { case IDC_SORT_LEVEL_SPIN: // Check the 'enabled' checkbox if sort level != SORT_LEVEL_NONE, uncheck it otherwise. ::SendDlgItemMessage(hDlg, IDC_ENABLE_SORT_LEVEL, BM_SETCHECK, spinner->GetIVal() == SORT_LEVEL_NONE ? BST_UNCHECKED : BST_CHECKED, 0); TheMtl->Set_Sort_Level(spinner->GetIVal()); break; } break; } } return FALSE; } BOOL GameMtlDlg::PassCountProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_INITDIALOG: break; case WM_COMMAND: switch(LOWORD(wParam)) { case IDC_SETPASSCOUNT: if(HIWORD(wParam) == BN_CLICKED) { Set_Pass_Count_Dialog(); } } break; } return FALSE; } static BOOL CALLBACK DisplacementMapDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam,LPARAM lParam) { GameMtlDlg * theDlg; if (msg == WM_INITDIALOG) { theDlg = (GameMtlDlg*)lParam; theDlg->HwndDisplacementMap = hwndDlg; SetWindowLong(hwndDlg, GWL_USERDATA,lParam); } else { if ((theDlg = (GameMtlDlg *)GetWindowLong(hwndDlg, GWL_USERDATA) ) == NULL) { return FALSE; } } theDlg->IsActive = 1; BOOL res = theDlg->DisplacementMapProc(hwndDlg,msg,wParam,lParam); theDlg->IsActive = 0; return res; } static BOOL CALLBACK SurfaceTypePanelDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam,LPARAM lParam) { GameMtlDlg * theDlg; if (msg == WM_INITDIALOG) { theDlg = (GameMtlDlg*)lParam; theDlg->HwndSurfaceType = hwndDlg; SetWindowLong(hwndDlg, GWL_USERDATA,lParam); } else { if ((theDlg = (GameMtlDlg *)GetWindowLong(hwndDlg, GWL_USERDATA) ) == NULL) { return FALSE; } } theDlg->IsActive = 1; BOOL res = theDlg->SurfaceTypeProc(hwndDlg,msg,wParam,lParam); theDlg->IsActive = 0; return res; } static BOOL CALLBACK PassCountPanelDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam,LPARAM lParam) { GameMtlDlg * theDlg; if (msg == WM_INITDIALOG) { theDlg = (GameMtlDlg*)lParam; theDlg->HwndPassCount = hwndDlg; SetWindowLong(hwndDlg, GWL_USERDATA,lParam); } else { if ((theDlg = (GameMtlDlg *)GetWindowLong(hwndDlg, GWL_USERDATA) ) == NULL) { return FALSE; } } theDlg->IsActive = 1; BOOL res = theDlg->PassCountProc(hwndDlg,msg,wParam,lParam); theDlg->IsActive = 0; return res; } void GameMtlDlg::Set_Pass_Count_Dialog(void) { int res = DialogBoxParam( AppInstance, MAKEINTRESOURCE(IDD_GAMEMTL_PASS_COUNT_DIALOG), HwndPassCount, PassCountDialogDlgProc, (LPARAM)TheMtl->Get_Pass_Count()); if (res>=0) { if (res<=0) res = 1; if (res>4) res = 4; char a[10]; sprintf(a, "%d", res); SetWindowText(GetDlgItem(HwndPassCount, IDC_GAMEMTL_PASSCOUNT_STATIC), a); if(TheMtl->Get_Pass_Count() != res) { for(int i = 0; i < TheMtl->Get_Pass_Count(); i++) { delete PassDialog[i]; PassDialog[i] = NULL; } TheMtl->Set_Pass_Count(res); for(i = 0; i < TheMtl->Get_Pass_Count(); i++) { PassDialog[i] = new GameMtlPassDlg(HwndEdit, IParams, TheMtl, i); } ReloadDialog(); } } } static BOOL CALLBACK PassCountDialogDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam,LPARAM lParam) { switch (msg) { case WM_INITDIALOG: { ISpinnerControl *spin = SetupIntSpinner( hwndDlg,IDC_PASSCOUNT_SPIN, IDC_PASSCOUNT_EDIT, 1,4,(int)lParam); ReleaseISpinner(spin); CenterWindow(hwndDlg,GetParent(hwndDlg)); break; } case WM_COMMAND: switch (LOWORD(wParam)) { case IDOK: { ISpinnerControl *spin = GetISpinner(GetDlgItem(hwndDlg,IDC_PASSCOUNT_SPIN)); EndDialog(hwndDlg,spin->GetIVal()); ReleaseISpinner(spin); break; } case IDCANCEL: EndDialog(hwndDlg,-1); break; } break; default: return FALSE; } return TRUE; } /*********************************************************************************************** * GameMtlDlg::Build_Dialog -- Adds the dialog to the material editor * * * * INPUT: * * * * OUTPUT: * * * * WARNINGS: * * * * HISTORY: * * 06/26/1997 GH : Created. * *=============================================================================================*/ void GameMtlDlg::Build_Dialog() { if ((TheMtl->Flags&(GAMEMTL_ROLLUP_FLAGS))==0) { TheMtl->Set_Flag(GAMEMTL_PASS0_ROLLUP_OPEN,TRUE); } HwndSurfaceType = IParams->AddRollupPage( AppInstance, MAKEINTRESOURCE(IDD_GAMEMTL_SURFACE_TYPE), SurfaceTypePanelDlgProc, Get_String(IDS_SURFACE_TYPE), (LPARAM)this, TheMtl->Get_Flag(GAMEMTL_SURFACE_ROLLUP_OPEN) ? 0:APPENDROLL_CLOSED ); #ifdef WANT_DISPLACEMENT_MAPS HwndDisplacementMap = IParams->AddRollupPage( AppInstance, MAKEINTRESOURCE(IDD_GAMEMTL_DISPLACEMENT_MAP), DisplacementMapDlgProc, Get_String(IDS_DISPLACEMENT_MAP), (LPARAM)this, TheMtl->Get_Flag(GAMEMTL_DISPLACEMENT_ROLLUP_OPEN) ? 0:APPENDROLL_CLOSED ); #endif //WANT_DISPLACEMENT_MAPS HwndPassCount = IParams->AddRollupPage( AppInstance, MAKEINTRESOURCE(IDD_GAMEMTL_PASS_COUNT), PassCountPanelDlgProc, Get_String(IDS_PASS_COUNT), (LPARAM)this, TheMtl->Get_Flag(GAMEMTL_PASSCOUNT_ROLLUP_OPEN) ? 0:APPENDROLL_CLOSED ); for (int i=0; iGet_Pass_Count(); i++) { PassDialog[i] = new GameMtlPassDlg(HwndEdit, IParams, TheMtl, i); } IParams->SetRollupScrollPos(TheMtl->RollScroll); ReloadDialog(); }