/* * Descent 3 * Copyright (C) 2024 Parallax Software * * 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 . --- HISTORICAL COMMENTS FOLLOW --- * $Logfile: /DescentIII/Main/editor/TextureDialog.cpp $ * $Revision: 1.1.1.1 $ * $Date: 2003-08-26 03:57:39 $ * $Author: kevinb $ * * Texture Dialog keypad * * $Log: not supported by cvs2svn $ * * 26 5/06/99 12:43p Matt * Fixed a bug when did a texture grab on the terrain with no cells * selected. * * 25 4/19/99 6:45p Jason * fixed satellite grabbing bug * * 24 4/08/99 5:47p Jason * added face finding function * * 23 2/23/99 3:07p Jason * added grabbing of terrain textures * * 22 12/04/98 1:14p Jason * added "Currently Used" texture flag * * 21 8/20/98 4:09p Jason * added facemap feature * * 20 8/05/98 8:44p Jason * added uniform scaling of textures * * 19 8/03/98 2:38p Matt * Changed the replace texture function to replace all instances of a * texture in the current room *or* in the whole mine, at the user's * discretion. * * 18 6/23/98 2:43p Matt * Changed calls to OutrageMessageBox() & Debug_MessageBox() to deal with * int return value (instead of bool). * * 17 6/15/98 4:00p Jason * replaced monochromatic polymodel lighting with rgb lighting * * 16 6/10/98 1:57p Samir * fixed some listbox problems. * * 15 6/10/98 12:21p Matt * Revamped system that controls what textures are displayed on the * texture tab. Should work correctly now, and will now save the settings * to the registry. Also, textures now default to no type set, not all * types set. * * 14 5/20/98 1:08p Jason * more stuff for adding bumpmaps * * 13 3/03/98 5:39p Jason * added swatch to texture tab * * 12 11/14/97 12:41p Jason * Added ReplaceTexture function * * 11 9/18/97 12:32p Samir * If currently selected texture is not in the list, default to 0 texture. * * 10 9/17/97 1:01p Matt * Ripped out segment code * * 9 9/17/97 12:06p Jason * ripped out segment engine * * 8 9/16/97 6:08p Jason * made texture names appear * * 7 9/15/97 1:18p Jason * got selectable tmap2s working * * 6 9/12/97 3:47p Matt * Fixed grab texture for room engine * * 5 8/29/97 1:52p Samir * Added bitmap buttons for Texture Keypad. * * 4 8/25/97 7:39p Samir * Using new GrListBox from old editorPictListBox * * 3 8/13/97 9:53a Matt * Show selected texture with magenta box around it. * Use new texture rotate & scale functions * * 15 6/03/97 4:55p Mark * * 15 6/3/97 4:14p Jeff * Added Context Sensitive Help * * 14 5/28/97 6:15p Samir * Fixups for missing textures in scrollbox. * * 13 5/27/97 5:29p Samir * Took out mprintf. * * 12 5/27/97 3:11p Samir * Allow 'masking' of textures to be displayed in listbox. * * 11 4/11/97 4:53p Samir * Grab texture button works for tmap 1s * * 10 3/13/97 1:42p Matt * Don't show texture 0 (the error texture) in the texture list * * 9 2/26/97 4:00p Samir * Added most keypad functions. * * 8 2/21/97 6:25p Samir * Set properly the max items for the listbox. * * 7 2/21/97 5:09p Samir * Uses new PictListBox class for texture listbox here. * * 6 2/20/97 6:05p Samir * Allow for clean activation and deactivation of surfaces in editor when * going into fullscreen mode. * * 5 2/19/97 7:29p Samir * Got scrolling texture view to work. * * 4 1/27/97 11:38a Samir * Added horizontal scrolling of keypad modeless dialog. * * $NoKeywords: $ */ #include #include "stdafx.h" #include "editor.h" #include "TextureDialog.h" #include "HTexture.h" #include "gametexture.h" #include "gr.h" #include "descent.h" #include "erooms.h" #include "mono.h" #include "room.h" #include "terrain.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CTextureDialog dialog // Initialization and Destruction of the Dialog. CTextureDialog::CTextureDialog(CWnd *pParent /*=NULL*/) : CKeypadDialog(CTextureDialog::IDD, pParent) { //{{AFX_DATA_INIT(CTextureDialog) // NOTE: the ClassWizard will add member initialization here //}}AFX_DATA_INIT } void CTextureDialog::DoDataExchange(CDataExchange *pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CTextureDialog) // NOTE: the ClassWizard will add DDX and DDV calls here //}}AFX_DATA_MAP } void CTextureDialog::RunKeypadFunction(int code) { switch (code) { case VK_NUMPAD0: OnTexpadRotate90(); break; case VK_NUMPAD1: OnTexpadRotLeft(); break; case VK_NUMPAD2: OnTexpadSlideDown(); break; case VK_NUMPAD3: OnTexpadRotRight(); break; case VK_NUMPAD4: OnTexpadSlideLeft(); break; case VK_NUMPAD5: OnTexpadSetDefault(); break; case VK_NUMPAD6: OnTexpadSlideRight(); break; case VK_NUMPAD7: OnTexpadStretchLess(); break; case VK_NUMPAD8: OnTexpadSlideUp(); break; case VK_NUMPAD9: OnTexpadStretchMore(); break; case VK_DELETE: OnTexpadNextEdge(); break; } } // selects a texture in the texture dialog void CTextureDialog::SelectTexture(int texnum) { m_TexLB.SelectItem(texnum); } BEGIN_MESSAGE_MAP(CTextureDialog, CDialog) //{{AFX_MSG_MAP(CTextureDialog) ON_WM_KEYDOWN() ON_WM_SIZE() ON_WM_VSCROLL() ON_WM_HSCROLL() ON_WM_LBUTTONDOWN() ON_WM_PAINT() ON_BN_CLICKED(IDC_TEXPAD_FLIPX, OnTexpadFlipX) ON_BN_CLICKED(IDC_TEXPAD_FLIPY, OnTexpadFlipY) ON_BN_CLICKED(IDC_TEXPAD_SLIDELEFT, OnTexpadSlideLeft) ON_BN_CLICKED(IDC_TEXPAD_SLIDERIGHT, OnTexpadSlideRight) ON_BN_CLICKED(IDC_TEXPAD_ROTLEFT, OnTexpadRotLeft) ON_BN_CLICKED(IDC_TEXPAD_ROTRIGHT, OnTexpadRotRight) ON_BN_CLICKED(IDC_TEXPAD_ROTATE90, OnTexpadRotate90) ON_BN_CLICKED(IDC_TEXPAD_STRETCHLESS, OnTexpadStretchLess) ON_BN_CLICKED(IDC_TEXPAD_STRETCHMORE, OnTexpadStretchMore) ON_BN_CLICKED(IDC_TEXPAD_SLIDEUP, OnTexpadSlideUp) ON_BN_CLICKED(IDC_TEXPAD_SLIDEDOWN, OnTexpadSlideDown) ON_BN_CLICKED(IDC_TEXPAD_SETDEFAULT, OnTexpadSetDefault) ON_BN_CLICKED(IDC_TEXPAD_NEXTEDGE, OnTexpadNextEdge) ON_BN_CLICKED(IDC_TEXPAD_GRAB, OnTexpadGrab) ON_BN_CLICKED(IDC_SHOW_MINE_TEXTURES2, OnShowMineTextures2) ON_BN_CLICKED(IDC_SHOW_OBJ_TEXTURES, OnShowObjTextures) ON_BN_CLICKED(IDC_SHOW_LIGHT_TEXTURES, OnShowLightTextures) ON_BN_CLICKED(IDC_SHOW_TERRAIN_TEXTURES, OnShowTerrainTextures) ON_WM_HELPINFO() ON_BN_CLICKED(IDC_RESET_ALL_TEXTURES, OnResetAllTextures) ON_WM_DESTROY() ON_BN_CLICKED(IDC_SHOW_TMAP2_TEXTURES, OnShowTmap2Textures) ON_BN_CLICKED(IDC_REPLACE_TEXTURE, OnReplaceTexture) ON_EN_KILLFOCUS(IDC_TEXSCALE_EDIT, OnKillfocusTexscaleEdit) ON_BN_CLICKED(IDC_TEXPAD_EXPAND_U, OnTexpadExpandU) ON_BN_CLICKED(IDC_TEXPAD_EXPAND_V, OnTexpadExpandV) ON_BN_CLICKED(IDC_TEXPAD_CONTRACT_U, OnTexpadContractU) ON_BN_CLICKED(IDC_TEXPAD_CONTRACT_V, OnTexpadContractV) ON_BN_CLICKED(IDC_FACE_MAP, OnFaceMap) ON_BN_CLICKED(IDC_CURRENT_USED, OnCurrentUsed) ON_BN_CLICKED(IDC_FIND_TEXTURE, OnFindTexture) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CTextureDialog message handlers static CDialog *ParentDialog = NULL; static CTextureDialog *ParentTextureDialog = NULL; uint8_t CurrentlyUsedTextures[MAX_TEXTURES]; bool Show_used = 0; BOOL CTextureDialog::OnInitDialog() { CDialog::OnInitDialog(); RECT rect; CWnd *wnd; CEdit *ebox; char str[20]; memset(CurrentlyUsedTextures, 0, MAX_TEXTURES); ParentDialog = this; ParentTextureDialog = this; wnd = GetDlgItem(IDC_TEXTURE_LISTBOX); wnd->GetClientRect(&rect); if (!GameTextures[D3EditState.texdlg_texture].used) D3EditState.texdlg_texture = 0; m_TexLB.Create(wnd, IDC_TEXTURE_LISTBOX, rect, 36); m_TexLB.SelectItem(D3EditState.texdlg_texture); if (D3EditState.texture_display_flags & TF_TERRAIN) ((CButton *)GetDlgItem(IDC_SHOW_TERRAIN_TEXTURES))->SetCheck(1); if (D3EditState.texture_display_flags & TF_MINE) ((CButton *)GetDlgItem(IDC_SHOW_MINE_TEXTURES2))->SetCheck(1); if (D3EditState.texture_display_flags & TF_OBJECT) ((CButton *)GetDlgItem(IDC_SHOW_OBJ_TEXTURES))->SetCheck(1); if (D3EditState.texture_display_flags & TF_TMAP2) ((CButton *)GetDlgItem(IDC_SHOW_TMAP2_TEXTURES))->SetCheck(1); if (D3EditState.texture_display_flags & TF_LIGHT) ((CButton *)GetDlgItem(IDC_SHOW_LIGHT_TEXTURES))->SetCheck(1); // Do bitmap buttons m_bmUp.LoadBitmap(IDB_NORTH); m_bmDown.LoadBitmap(IDB_SOUTH); m_bmLeft.LoadBitmap(IDB_WEST); m_bmRight.LoadBitmap(IDB_EAST); m_bmRotLeft.LoadBitmap(IDB_ROTATELEFT); m_bmRotRight.LoadBitmap(IDB_ROTATERIGHT); m_bmStretchLess.LoadBitmap(IDB_INARROW); m_bmStretchMore.LoadBitmap(IDB_OUTARROW); // Set bitmap buttons CButton *btn; btn = (CButton *)GetDlgItem(IDC_TEXPAD_SLIDEUP); btn->SetBitmap((HBITMAP)m_bmUp); btn = (CButton *)GetDlgItem(IDC_TEXPAD_SLIDEDOWN); btn->SetBitmap((HBITMAP)m_bmDown); btn = (CButton *)GetDlgItem(IDC_TEXPAD_SLIDELEFT); btn->SetBitmap((HBITMAP)m_bmLeft); btn = (CButton *)GetDlgItem(IDC_TEXPAD_SLIDERIGHT); btn->SetBitmap((HBITMAP)m_bmRight); btn = (CButton *)GetDlgItem(IDC_TEXPAD_ROTLEFT); btn->SetBitmap((HBITMAP)m_bmRotLeft); btn = (CButton *)GetDlgItem(IDC_TEXPAD_ROTRIGHT); btn->SetBitmap((HBITMAP)m_bmRotRight); btn = (CButton *)GetDlgItem(IDC_TEXPAD_STRETCHLESS); btn->SetBitmap((HBITMAP)m_bmStretchLess); btn = (CButton *)GetDlgItem(IDC_TEXPAD_STRETCHMORE); btn->SetBitmap((HBITMAP)m_bmStretchMore); ebox = (CEdit *)GetDlgItem(IDC_TEXSCALE_EDIT); sprintf(str, "%f", D3EditState.texscale); ebox->SetWindowText(str); return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE } void CTextureDialog::OnDestroy() { CDialog::OnDestroy(); // kill all bitmaps m_bmUp.DeleteObject(); m_bmDown.DeleteObject(); m_bmLeft.DeleteObject(); m_bmRight.DeleteObject(); m_bmRotLeft.DeleteObject(); m_bmRotRight.DeleteObject(); m_bmStretchLess.DeleteObject(); m_bmStretchMore.DeleteObject(); } void CTextureDialog::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) { // TODO: Add your message handler code here and/or call default CDialog::OnKeyDown(nChar, nRepCnt, nFlags); } void CTextureDialog::OnSize(UINT nType, int cx, int cy) { CKeypadDialog::OnSize(nType, cx, cy); } void CTextureDialog::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar *pScrollBar) { CKeypadDialog::OnVScroll(nSBCode, nPos, pScrollBar); } void CTextureDialog::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar *pScrollBar) { // TODO: Add your message handler code here and/or call default CKeypadDialog::OnHScroll(nSBCode, nPos, pScrollBar); } void CTextureDialog::OnLButtonDown(UINT nFlags, CPoint point) { CDialog::OnLButtonDown(nFlags, point); } void CTextureDialog::OnPaint() { CPaintDC dc(this); // device context for painting if (!m_Active) return; } // Keypad Functions!! void CTextureDialog::OnTexpadFlipX() { HTextureFlipX(); } void CTextureDialog::OnTexpadFlipY() { HTextureFlipY(); } void CTextureDialog::OnTexpadSlideLeft() { HTextureSlide(Curroomp, Curface, (float)-1.0 * D3EditState.texscale, 0.0f); } void CTextureDialog::OnTexpadSlideRight() { HTextureSlide(Curroomp, Curface, (float)1.0 * D3EditState.texscale, 0.0f); } void CTextureDialog::OnTexpadSlideUp() { HTextureSlide(Curroomp, Curface, 0.0f, (float)1.0 * D3EditState.texscale); } void CTextureDialog::OnTexpadSlideDown() { HTextureSlide(Curroomp, Curface, 0.0f, (float)-1.0 * D3EditState.texscale); } void CTextureDialog::OnTexpadRotLeft() { HTextureRotate(Curroomp, Curface, (-512 * D3EditState.texscale)); } void CTextureDialog::OnTexpadRotRight() { HTextureRotate(Curroomp, Curface, (512 * D3EditState.texscale)); } void CTextureDialog::OnTexpadRotate90() { HTextureRotate(Curroomp, Curface, 0x4000); } void CTextureDialog::OnTexpadStretchLess() { HTextureStretchLess(Curroomp, Curface, Curedge); } void CTextureDialog::OnTexpadStretchMore() { HTextureStretchMore(Curroomp, Curface, Curedge); } void CTextureDialog::OnTexpadSetDefault() { HTextureSetDefault(Curroomp); } void CTextureDialog::OnTexpadNextEdge() { HTextureNextEdge(); } void CTextureDialog::OnTexpadGrab() { int texnum = -1; if (Editor_view_mode == VM_TERRAIN) { for (int i = 0; i < TERRAIN_WIDTH * TERRAIN_DEPTH; i++) { if (TerrainSelected[i]) { if (texnum != -1) { OutrageMessageBox("Cannot grab texture: More than one terrain cell selected."); return; } texnum = Terrain_tex_seg[Terrain_seg[i].texseg_index].tex_index; } } if (texnum == -1) { OutrageMessageBox("Cannot grab texture: No terrain cell selected."); return; } } else { if (!Curroomp || Curroomp->used == 0 || Curface >= Curroomp->num_faces) return; texnum = Curroomp->faces[Curface].tmap; } CTextureDialog::SelectTexture(texnum); EditorStatus("Texture %d, \"%s\", selected.", texnum, GameTextures[texnum].name); } void CTextureDialog::OnShowMineTextures2() { D3EditState.texture_display_flags ^= TF_MINE; Invalidate(); } void CTextureDialog::OnShowObjTextures() { D3EditState.texture_display_flags ^= TF_OBJECT; Invalidate(); } void CTextureDialog::OnShowLightTextures() { D3EditState.texture_display_flags ^= TF_LIGHT; Invalidate(); } void CTextureDialog::OnShowTerrainTextures() { D3EditState.texture_display_flags ^= TF_TERRAIN; Invalidate(); } BOOL CTextureDialog::OnHelpInfo(HELPINFO *pHelpInfo) { // TODO: Add your message handler code here and/or call default WinHelp(HID_TEXTURETAB, HELP_CONTEXT); return TRUE; // return CDialog::OnHelpInfo(pHelpInfo); } extern void AssignDefaultUVsToRoom(room *rp); void CTextureDialog::OnResetAllTextures() { int answer = OutrageMessageBox( MBOX_YESNO, "Are you sure you wish to reset all textures for this room? This change cannot be undone!"); if (answer != IDYES) return; AssignDefaultUVsToRoom(Curroomp); World_changed = 1; } ///////////////////////////////////////////////////////////////////// // CGrTextureListBox implementation // enumerates items maximum in the list box. this is here to insure that any changes in // the user-managed list. int CGrTextureListBox::ListEnumerate() { int count = 0, i; for (i = 0; i < MAX_TEXTURES; i++) { bool countit = true; ; if (!GameTextures[i].used) countit = false; if (!(GameTextures[i].flags & D3EditState.texture_display_flags)) countit = false; if (Show_used && !CurrentlyUsedTextures[i]) countit = false; if (countit) count++; } return count; } // Specify the first item to be drawn in the box by DrawItem. returns the item # // return -1 if there is no first item (list is empty, maybe) int CGrTextureListBox::ListFirstItem(int firsttex) { // skip the error texture if (firsttex < 0) firsttex = 0; if (firsttex == 0) firsttex++; // find first texture that is used if the texture passed became invalid. if (!GameTextures[firsttex].used || !(GameTextures[firsttex].flags & D3EditState.texture_display_flags) || (Show_used && !CurrentlyUsedTextures[firsttex])) { int new_first = ListNextItem(firsttex); if (new_first == firsttex) return -1; else return new_first; } else return firsttex; } // Specify the next/prev item to be drawn in the box by DrawItem. // Returns the item # following or preceding the passed the item # int CGrTextureListBox::ListNextItem(int curtex) { int next_texture = -1; if (curtex >= 0) next_texture = GetNextTexture(curtex); if (next_texture <= curtex) return curtex; while ((Show_used && !CurrentlyUsedTextures[next_texture]) || !(GameTextures[next_texture].flags & D3EditState.texture_display_flags)) { next_texture = GetNextTexture(next_texture); // mprintf(0, "next_tex = %d\n", next_texture); if (next_texture == curtex) { break; } } return next_texture; } int CGrTextureListBox::ListPrevItem(int curtex) { int prev_texture = -1; if (curtex >= 0) prev_texture = GetPreviousTexture(curtex); if (prev_texture >= curtex) return curtex; while ((Show_used && !CurrentlyUsedTextures[prev_texture]) || !(GameTextures[prev_texture].flags & D3EditState.texture_display_flags)) { prev_texture = GetPreviousTexture(prev_texture); // mprintf(0, "prev_tex = %d\n", prev_texture); if (prev_texture == curtex) { break; } } return prev_texture; } // draw the item void CGrTextureListBox::DrawItem(int x, int y, grHardwareSurface *itemsurf, int item) { int bm_handle; bm_handle = GetTextureBitmap(item, 0); itemsurf->load(bm_handle); Desktop_surf->blt(x, y, itemsurf); } // if item was selected from the list box, this function is invoked. void CGrTextureListBox::OnItemSelected(int tex) { D3EditState.texdlg_texture = tex; if (ParentDialog != NULL) { PrintToDlgItem(ParentDialog, IDC_CURRENT_TEXTURE_NAME, "Texture: %s", GameTextures[tex].name); ParentTextureDialog->DrawSwatch(IDC_TEXTURE_SWATCH, GameTextures[tex].r, GameTextures[tex].g, GameTextures[tex].b); } } void CTextureDialog::OnShowTmap2Textures() { // TODO: Add your control notification handler code here D3EditState.texture_display_flags ^= TF_TMAP2; Invalidate(); } // Returns the number of changes int ReplaceTextureInRoom(room *rp, int old_tmap, int new_tmap) { int n_changes = 0; for (int i = 0; i < rp->num_faces; i++) { if (rp->faces[i].tmap == old_tmap) { rp->faces[i].tmap = new_tmap; n_changes++; } } return n_changes; } void CTextureDialog::OnReplaceTexture() { ASSERT(Curroomp != NULL); int n_changes; int answer = OutrageMessageBox( MBOX_YESNOCANCEL, "Do you wish to change this texture for the whole mine?\n\n(Answer NO to change only the current room.)"); if (answer == IDCANCEL) return; int selected_texture = Curroomp->faces[Curface].tmap; if (answer == IDYES) { n_changes = 0; for (int r = 0; r <= Highest_room_index; r++) if (Rooms[r].used) n_changes += ReplaceTextureInRoom(&Rooms[r], selected_texture, D3EditState.texdlg_texture); } else { n_changes = ReplaceTextureInRoom(Curroomp, selected_texture, D3EditState.texdlg_texture); } EditorStatus("Texture %d replaced with texture %d on %d faces.", selected_texture, D3EditState.texdlg_texture, n_changes); World_changed = 1; } void CTextureDialog::DrawSwatch(int handle, float r, float g, float b) { CWnd *texwnd; RECT rect; int w, h; float rmax = std::max(r, g); rmax = std::max(rmax, b); if (rmax >= .001) { r /= rmax; g /= rmax; b /= rmax; } texwnd = GetDlgItem(handle); texwnd->GetWindowRect(&rect); ScreenToClient(&rect); Desktop_surf->attach_to_window((unsigned)m_hWnd); w = rect.right - rect.left; h = rect.bottom - rect.top; ddgr_color color = GR_RGB(r * 255, g * 255, b * 255); Desktop_surf->clear(rect.left, rect.top, w, h, color); Desktop_surf->attach_to_window(NULL); } void CTextureDialog::OnKillfocusTexscaleEdit() { CEdit *ebox; char str[20]; float val; ebox = (CEdit *)GetDlgItem(IDC_TEXSCALE_EDIT); ebox->GetWindowText(str, 20); val = atof(str); if (val < 0) val = 0; if (val > 64) val = 64; D3EditState.texscale = val; ebox = (CEdit *)GetDlgItem(IDC_TEXSCALE_EDIT); sprintf(str, "%f", D3EditState.texscale); ebox->SetWindowText(str); } void CTextureDialog::OnTexpadExpandU() { if (Curroomp == NULL) return; face *fp = &Curroomp->faces[Curface]; int i; float mid = 0; for (i = 0; i < fp->num_verts; i++) mid += fp->face_uvls[i].u; mid /= fp->num_verts; for (i = 0; i < fp->num_verts; i++) { float diff = fp->face_uvls[i].u - mid; diff *= 1.0 / D3EditState.texscale; fp->face_uvls[i].u = mid + diff; } World_changed = 1; } void CTextureDialog::OnTexpadExpandV() { if (Curroomp == NULL) return; face *fp = &Curroomp->faces[Curface]; int i; float mid = 0; for (i = 0; i < fp->num_verts; i++) mid += fp->face_uvls[i].v; mid /= fp->num_verts; for (i = 0; i < fp->num_verts; i++) { float diff = fp->face_uvls[i].v - mid; diff *= 1.0 / D3EditState.texscale; fp->face_uvls[i].v = mid + diff; } World_changed = 1; } void CTextureDialog::OnTexpadContractU() { if (Curroomp == NULL) return; face *fp = &Curroomp->faces[Curface]; int i; float mid = 0; for (i = 0; i < fp->num_verts; i++) mid += fp->face_uvls[i].u; mid /= fp->num_verts; for (i = 0; i < fp->num_verts; i++) { float diff = fp->face_uvls[i].u - mid; diff *= D3EditState.texscale; fp->face_uvls[i].u = mid + diff; } World_changed = 1; } void CTextureDialog::OnTexpadContractV() { if (Curroomp == NULL) return; face *fp = &Curroomp->faces[Curface]; int i; float mid = 0; for (i = 0; i < fp->num_verts; i++) mid += fp->face_uvls[i].v; mid /= fp->num_verts; for (i = 0; i < fp->num_verts; i++) { float diff = fp->face_uvls[i].v - mid; diff *= D3EditState.texscale; fp->face_uvls[i].v = mid + diff; } World_changed = 1; } void CTextureDialog::OnFaceMap() { if (Curroomp == NULL) return; face *fp = &Curroomp->faces[Curface]; if (fp->num_verts != 4) { OutrageMessageBox("Face must have four vertices to use face mapping."); return; } // Simply square off this face fp->face_uvls[0].u = 0.0; fp->face_uvls[0].v = 0.0; fp->face_uvls[1].u = 1.0; fp->face_uvls[1].v = 0.0; fp->face_uvls[2].u = 1.0; fp->face_uvls[2].v = 1.0; fp->face_uvls[3].u = 0.0; fp->face_uvls[3].v = 1.0; World_changed = 1; } void CTextureDialog::OnCurrentUsed() { // TODO: Add your control notification handler code here int c = IsDlgButtonChecked(IDC_CURRENT_USED); // If we just turned this on, build a list of textures used if (c) { Show_used = 1; memset(CurrentlyUsedTextures, 0, MAX_TEXTURES); for (int i = 0; i <= Highest_room_index; i++) { room *rp = &Rooms[i]; if (!rp->used) continue; for (int t = 0; t < rp->num_faces; t++) { CurrentlyUsedTextures[rp->faces[t].tmap] = 1; } } } else Show_used = 0; Invalidate(); } void CTextureDialog::OnFindTexture() { int i, t; mprintf(0, "Searching...please wait...\n"); int found = 0, found_room, found_face; for (i = 0; i <= Highest_room_index && !found; i++) { room *rp = &Rooms[i]; if (rp->used == 0) continue; for (t = 0; t < rp->num_faces && !found; t++) { if (rp->faces[t].tmap == D3EditState.texdlg_texture) { if (rp != Curroomp || t != Curface) { found_room = i; found_face = t; found = 1; } } } } mprintf(0, "Done searching!\n"); if (found == 0) { mprintf(0, "Couldn't find another face with that texture!\n"); } else { Curroomp = &Rooms[found_room]; Curface = found_face; mprintf(0, "Found that texture in room %d face %d.\n", found_room, found_face); mprintf(0, "Press C to center on that face\n"); } }