/* * 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 . */ // MegacellDialog.cpp : implementation file // #include #include "stdafx.h" #include "editor.h" #include "MegacellDialog.h" #include "WorldTexturesDialog.h" #include "megapage.h" #include "megacell.h" #include "manage.h" #include "gametexture.h" #include "vclip.h" #include "texpage.h" #include "bitmap.h" #include "ddio.h" #include "mem.h" #include "EditLineDialog.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif static megacell m_CopyMegacell; ///////////////////////////////////////////////////////////////////////////// // CMegacellDialog dialog CMegacellDialog::CMegacellDialog(CWnd *pParent /*=NULL*/) : CDialog(CMegacellDialog::IDD, pParent) { //{{AFX_DATA_INIT(CMegacellDialog) // NOTE: the ClassWizard will add member initialization here //}}AFX_DATA_INIT m_TexStart = 0; m_TexListPos = 0; m_RedrawListbox = 0; m_TexPageLen = 0; m_CheckForTextureList = 0; m_CheckX = m_CheckY = 0; memset(&m_CopyMegacell, 0, sizeof(megacell)); } void CMegacellDialog::DoDataExchange(CDataExchange *pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CMegacellDialog) // NOTE: the ClassWizard will add DDX and DDV calls here //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CMegacellDialog, CDialog) //{{AFX_MSG_MAP(CMegacellDialog) ON_BN_CLICKED(IDC_NEW_MEGACELL, OnNewMegacell) ON_BN_CLICKED(IDC_LOCK_MEGACELL, OnLockMegacell) ON_BN_CLICKED(IDC_CHECKIN_MEGACELL, OnCheckinMegacell) ON_BN_CLICKED(IDC_DELETE_MEGACELL, OnDeleteMegacell) ON_BN_CLICKED(IDC_NEXT_MEGACELL, OnNextMegacell) ON_BN_CLICKED(IDC_PREVIOUS_MEGACELL, OnPreviousMegacell) ON_CBN_SELENDOK(IDC_MEGACELL_PULLDOWN, OnSelendokMegacellPulldown) ON_BN_CLICKED(IDC_MEGACELLS_OUT, OnMegacellsOut) ON_EN_KILLFOCUS(IDC_MEGACELL_NAME_EDIT, OnKillfocusMegacellNameEdit) ON_EN_KILLFOCUS(IDC_MEGA_WIDTH_EDIT, OnKillfocusMegaWidthEdit) ON_EN_KILLFOCUS(IDC_MEGA_HEIGHT_EDIT, OnKillfocusMegaHeightEdit) ON_WM_LBUTTONDOWN() ON_WM_VSCROLL() ON_WM_PAINT() ON_BN_CLICKED(IDC_REMAP_MEGACELL, OnRemapMegacell) ON_BN_CLICKED(IDC_ROTATE_MEGACELL, OnRotateMegacell) ON_BN_CLICKED(IDC_COPY_MEGACELL, OnCopyMegacell) ON_BN_CLICKED(IDC_PASTE_MEGACELL, OnPasteMegacell) ON_BN_CLICKED(IDC_IMPORT_TINY, OnImportTiny) ON_WM_HELPINFO() ON_BN_CLICKED(IDC_IMPORT_SKY, OnImportSky) ON_BN_CLICKED(IDC_IMPORT_SKY_BAND, OnImportSkyBand) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CMegacellDialog message handlers void CMegacellDialog::OnNewMegacell() { char filename[255]; char cur_name[100]; int cell_handle; int c = 1, finding_name = 1; if (!Network_up) { OutrageMessageBox("Sorry babe, the network is down. This action is a no-no.\n"); return; } // Get megacell name CEditLineDialog dlg("Enter megacell name", this); int ret = dlg.DoModal(); if (ret == IDCANCEL) return; strcpy(filename, (char *)dlg.GetText()); // Alloc a megacell and give a name not already taken by some other cell cell_handle = AllocMegacell(); while (finding_name) { sprintf(cur_name, "%s%d", filename, c); if (FindMegacellName(cur_name) != -1) c++; else finding_name = 0; } strcpy(Megacells[cell_handle].name, cur_name); mng_AllocTrackLock(cur_name, PAGETYPE_MEGACELL); D3EditState.current_megacell = cell_handle; UpdateDialog(); } void CMegacellDialog::OnLockMegacell() { int n = D3EditState.current_megacell; mngs_Pagelock temp_pl; mngs_megacell_page megacellpage; int r; if (Num_megacells < 1) return; if (!mng_MakeLocker()) return; // Make sure it can be locked strcpy(temp_pl.name, Megacells[n].name); temp_pl.pagetype = PAGETYPE_MEGACELL; r = mng_CheckIfPageLocked(&temp_pl); if (r == 2) { int answer; answer = OutrageMessageBox(MBOX_YESNO, "This page is not even in the table file, or the database maybe corrupt. " "Override to 'Unlocked'? (Select NO if you don't know what you're doing)"); if (answer == IDYES) { strcpy(temp_pl.holder, "UNLOCKED"); if (!mng_ReplacePagelock(temp_pl.name, &temp_pl)) MessageBox(ErrorString, "Error!"); } } else if (r < 0) OutrageMessageBox(ErrorString); else if (r == 1) OutrageMessageBox(InfoString); else { // Everything is ok. Tell the network we're locking it and get a copy to // our local drive strcpy(temp_pl.holder, TableUser); if (!mng_ReplacePagelock(temp_pl.name, &temp_pl)) { MessageBox(ErrorString, "Error!"); mng_EraseLocker(); return; } else { // Search thru the net pagefile and get a new copy in RAM in case anyone // changed it since we started the editor if (mng_FindSpecificMegacellPage(temp_pl.name, &megacellpage, 0)) { if (mng_AssignMegacellPageToMegacell(&megacellpage, n)) { if (!mng_ReplacePage(Megacells[n].name, Megacells[n].name, n, PAGETYPE_MEGACELL, 1)) { OutrageMessageBox("There was problem writing that page locally!"); mng_EraseLocker(); return; } OutrageMessageBox("Megacell locked."); } else OutrageMessageBox("There was a problem loading this megacell. You might encounter problems in dealing with " "it. Good luck!"); mng_AllocTrackLock(Megacells[n].name, PAGETYPE_MEGACELL); UpdateDialog(); } else OutrageMessageBox("Couldn't find that megacell in the table file!"); } } mng_EraseLocker(); } void CMegacellDialog::OnCheckinMegacell() { int n = D3EditState.current_megacell; mngs_Pagelock temp_pl; int r; int i; if (Num_megacells < 1) return; if (!mng_MakeLocker()) return; // Make sure we own this megacell strcpy(temp_pl.name, Megacells[n].name); temp_pl.pagetype = PAGETYPE_MEGACELL; r = mng_CheckIfPageOwned(&temp_pl, TableUser); if (r < 0) OutrageMessageBox(ErrorString); else if (r == 0) OutrageMessageBox(InfoString); else { // Change the pagelock state to UNLOCKED strcpy(temp_pl.holder, "UNLOCKED"); if (!mng_ReplacePagelock(temp_pl.name, &temp_pl)) { MessageBox(ErrorString, "Error!"); mng_EraseLocker(); return; } else { // Now actually replace the copy on the net with our local one int answer = MessageBox("Do you wish to check in all the textures associated with this megacell (if any)?", Megacells[n].name, MB_YESNO); if (answer == IDYES) { // Check in all these textures for (i = 0; i < MAX_MEGACELL_WIDTH * MAX_MEGACELL_HEIGHT; i++) { int mx = i % MAX_MEGACELL_WIDTH; int my = i / MAX_MEGACELL_WIDTH; if (mx >= Megacells[n].width || my >= Megacells[n].height) continue; int index = Megacells[n].texture_handles[i]; if (!GameTextures[index].used || index == 0) continue; int tl; if ((tl = mng_FindTrackLock(GameTextures[index].name, PAGETYPE_TEXTURE)) != -1) CheckinTexture(index, tl); } } if (!mng_ReplacePage(Megacells[n].name, Megacells[n].name, n, PAGETYPE_MEGACELL, 0)) OutrageMessageBox(ErrorString); else { OutrageMessageBox("Megacell checked in."); // Delete it from local pagefile if its there int dret = mng_DeletePage(Megacells[n].name, PAGETYPE_MEGACELL, 1); ASSERT(dret == 1); mng_EraseLocker(); // Free the tracklock int p = mng_FindTrackLock(Megacells[n].name, PAGETYPE_MEGACELL); ASSERT(p != -1); mng_FreeTrackLock(p); UpdateDialog(); } } } } extern int TlockState; extern int AutoChecking; void CMegacellDialog::OnDeleteMegacell() { int answer, tl; mngs_Pagelock pl; CWorldTexturesDialog texdlg; int n = D3EditState.current_megacell; int i; if (Num_megacells < 1) return; // Check to see if we even have it locked if ((tl = mng_FindTrackLock(Megacells[n].name, PAGETYPE_MEGACELL)) == -1) { OutrageMessageBox("This megacell is not yours to delete. Lock first."); return; } // Make sure its to be deleted answer = MessageBox("Are you sure you want to delete this megacell?", Megacells[n].name, MB_YESNO); if (answer == IDNO) return; answer = MessageBox("Do you wish to delete all the textures associated with this megacell?", Megacells[n].name, MB_YESNO); if (!mng_MakeLocker()) return; strcpy(pl.name, Megacells[n].name); pl.pagetype = PAGETYPE_MEGACELL; // Check to see if this is a local megacell only. If so, only delete it locally if (mng_CheckIfPageOwned(&pl, TableUser) != 1) { mng_FreeTrackLock(tl); if (!mng_DeletePage(Megacells[n].name, PAGETYPE_MEGACELL, 1)) { mprintf(0, ErrorString); Int3(); } } else // if its network, delete it from both the net and local drives { mng_FreeTrackLock(tl); mng_DeletePage(Megacells[n].name, PAGETYPE_MEGACELL, 0); mng_DeletePage(Megacells[n].name, PAGETYPE_MEGACELL, 1); mng_DeletePagelock(Megacells[n].name, PAGETYPE_MEGACELL); } // Advance to the next megacell D3EditState.current_megacell = GetNextMegacell(n); // Now delete those textures if need be if (answer == IDYES) { uint8_t can_delete[MAX_MEGACELL_WIDTH * MAX_MEGACELL_HEIGHT]; memset(can_delete, 0, MAX_MEGACELL_WIDTH * MAX_MEGACELL_HEIGHT); for (i = 0; i < MAX_MEGACELL_WIDTH * MAX_MEGACELL_HEIGHT; i++) { int mx = i % MAX_MEGACELL_WIDTH; int my = i / MAX_MEGACELL_WIDTH; if (mx >= Megacells[n].width || my >= Megacells[n].height) continue; int index = Megacells[n].texture_handles[i]; if (index == 0 || index == 1) continue; int tl; tl = mng_FindTrackLock(GameTextures[index].name, PAGETYPE_TEXTURE); if (tl == -1) { // We need to lock this texture AutoChecking = 2; D3EditState.texdlg_texture = index; texdlg.OnLock(); if (!TlockState) continue; tl = mng_FindTrackLock(GameTextures[index].name, PAGETYPE_TEXTURE); can_delete[i] = 1; } else { can_delete[i] = 1; } } int num_to_delete = 0; char *texnames[MAX_MEGACELL_WIDTH * MAX_MEGACELL_HEIGHT]; uint16_t texindices[MAX_MEGACELL_WIDTH * MAX_MEGACELL_HEIGHT]; for (i = 0; i < MAX_MEGACELL_WIDTH * MAX_MEGACELL_HEIGHT; i++) { texnames[i] = (char *)mem_malloc(PAGENAME_LEN); ASSERT(texnames[i]); if (!can_delete[i]) continue; int index = Megacells[n].texture_handles[i]; int duplicate = 0; for (int k = 0; k < num_to_delete && !duplicate; k++) { if (texindices[k] == index) duplicate = 1; } if (duplicate) continue; strcpy(texnames[num_to_delete], GameTextures[index].name); texindices[num_to_delete] = index; num_to_delete++; } mng_DeleteTexPageSeries(texnames, num_to_delete, 0); mng_DeleteTexPageSeries(texnames, num_to_delete, 1); mng_DeletePagelockSeries(texnames, num_to_delete, PAGETYPE_TEXTURE); // Now free all pagelocks and textures for (i = 0; i < num_to_delete; i++) { tl = mng_FindTrackLock(GameTextures[texindices[i]].name, PAGETYPE_TEXTURE); if (tl != -1) mng_FreeTrackLock(tl); if (GameTextures[texindices[i]].flags & TF_ANIMATED) FreeVClip(GameTextures[texindices[i]].bm_handle); else bm_FreeBitmap(GameTextures[texindices[i]].bm_handle); FreeTexture(texindices[i]); } for (i = 0; i < MAX_MEGACELL_WIDTH * MAX_MEGACELL_HEIGHT; i++) mem_free(texnames[i]); } AutoChecking = 0; FreeMegacell(n); mng_EraseLocker(); OutrageMessageBox("Megacell deleted."); UpdateDialog(); } void CMegacellDialog::OnNextMegacell() { D3EditState.current_megacell = GetNextMegacell(D3EditState.current_megacell); UpdateDialog(); } void CMegacellDialog::OnPreviousMegacell() { D3EditState.current_megacell = GetPrevMegacell(D3EditState.current_megacell); UpdateDialog(); } void CMegacellDialog::OnSelendokMegacellPulldown() { int i, cur; char name[200]; cur = SendDlgItemMessage(IDC_MEGACELL_PULLDOWN, CB_GETCURSEL, 0, 0); SendDlgItemMessage(IDC_MEGACELL_PULLDOWN, CB_GETLBTEXT, cur, (LPARAM)(LPCTSTR)name); i = FindMegacellName(name); if (i == -1) { mprintf(0, "Possible corrupted megacell list, but probably nothing."); UpdateDialog(); } D3EditState.current_megacell = i; UpdateDialog(); } void CMegacellDialog::OnMegacellsOut() {} void CMegacellDialog::OnKillfocusMegacellNameEdit() { CEdit *ebox; int n = D3EditState.current_megacell; char name[PAGENAME_LEN]; mngs_Pagelock pl; // Make sure we have this megacell locked, if not reset name and bail int p = mng_FindTrackLock(Megacells[n].name, PAGETYPE_MEGACELL); if (p == -1) { OutrageMessageBox("You must lock this megacell if you wish to change its name."); CEdit *ebox = (CEdit *)GetDlgItem(IDC_MEGACELL_NAME_EDIT); ebox->SetWindowText(Megacells[n].name); return; } // Get the new name ebox = (CEdit *)GetDlgItem(IDC_MEGACELL_NAME_EDIT); ebox->GetWindowText(name, PAGENAME_LEN); // Check to see if there is already a cell with this name. If so, reset and bail if (FindMegacellName(name) != -1) { OutrageMessageBox("There already is a cell with that name...choose another name."); CEdit *ebox = (CEdit *)GetDlgItem(IDC_MEGACELL_NAME_EDIT); ebox->SetWindowText(Megacells[n].name); return; } if (!mng_MakeLocker()) return; // Check to see if this page exists on the network. If so, we have to // rename it so we can prevent havoc strcpy(pl.name, Megacells[n].name); pl.pagetype = PAGETYPE_MEGACELL; int ret = mng_CheckIfPageOwned(&pl, TableUser); if (ret < 0) OutrageMessageBox(ErrorString); else if (ret == 1) mng_RenamePage(Megacells[n].name, name, PAGETYPE_MEGACELL); else if (ret == 2) { // This page has never been checked in, replace only local copy char oldname[PAGENAME_LEN]; strcpy(oldname, Megacells[n].name); strcpy(Megacells[n].name, name); mng_ReplacePage(oldname, Megacells[n].name, n, PAGETYPE_MEGACELL, 1); } else if (ret == 0) { OutrageMessageBox("You don't own this page. Get Jason now!"); mng_FreeTrackLock(p); return; } // Finally, copy our new name to the appropriate arrays strcpy(GlobalTrackLocks[p].name, name); strcpy(Megacells[n].name, name); mng_EraseLocker(); UpdateDialog(); } void CMegacellDialog::OnKillfocusMegaWidthEdit() { CEdit *ebox; char name[20]; int n = D3EditState.current_megacell; int width; ebox = (CEdit *)GetDlgItem(IDC_MEGA_WIDTH_EDIT); ebox->GetWindowText(name, 20); width = atoi(name); if (width < 0) width = 2; if (width > 8) width = 8; Megacells[n].width = width; UpdateDialog(); } void CMegacellDialog::OnKillfocusMegaHeightEdit() { CEdit *ebox; char name[20]; int n = D3EditState.current_megacell; int height; ebox = (CEdit *)GetDlgItem(IDC_MEGA_HEIGHT_EDIT); ebox->GetWindowText(name, 20); height = atoi(name); if (height < 0) height = 2; if (height > 8) height = 8; Megacells[n].height = height; UpdateDialog(); } BOOL CMegacellDialog::DestroyWindow() { SaveMegacellsOnClose(); return CDialog::DestroyWindow(); } BOOL CMegacellDialog::OnInitDialog() { static int first_time = 1; CDialog::OnInitDialog(); mngs_megacell_page megacellpage; // Remap all megacells if (Network_up && first_time) { for (int i = 0; i < MAX_MEGACELLS; i++) { if (Megacells[i].used) { if (Megacells[i].texture_handles[0] > 0) continue; if (mng_FindSpecificMegacellPage(Megacells[i].name, &megacellpage, 1)) { if (!mng_AssignMegacellPageToMegacell(&megacellpage, i)) Int3(); // Get Jason } else if (mng_FindSpecificMegacellPage(Megacells[i].name, &megacellpage, 0)) { if (!mng_AssignMegacellPageToMegacell(&megacellpage, i)) Int3(); // Get Jason } } } } first_time = 0; UpdateDialog(); return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE } void CMegacellDialog::SaveMegacellsOnClose() { int i, t; if (!Network_up) return; // don't save a damn thing if the network is down for (i = 0; i < MAX_TRACKLOCKS; i++) { if (GlobalTrackLocks[i].used == 1 && GlobalTrackLocks[i].pagetype == PAGETYPE_TEXTURE) { t = FindTextureName(GlobalTrackLocks[i].name); ASSERT(t != -1); mng_ReplacePage(GameTextures[t].name, GameTextures[t].name, t, PAGETYPE_TEXTURE, 1); } if (GlobalTrackLocks[i].used == 1 && GlobalTrackLocks[i].pagetype == PAGETYPE_MEGACELL) { t = FindMegacellName(GlobalTrackLocks[i].name); mng_DeletePage(Megacells[t].name, PAGETYPE_MEGACELL, 1); ASSERT(t != -1); mng_ReplacePage(Megacells[t].name, Megacells[t].name, t, PAGETYPE_MEGACELL, 1); } } } void CMegacellDialog::OnLButtonDown(UINT nFlags, CPoint point) { m_CheckForTextureList = 1; m_CheckX = point.x; m_CheckY = point.y; CDialog::OnLButtonDown(nFlags, point); UpdateDialog(); CDialog::OnLButtonDown(nFlags, point); } void CMegacellDialog::UpdateDialog() { CEdit *ebox; CButton *bbox; int n = D3EditState.current_megacell; char str[50]; UpdateTextureView(); if (Num_megacells < 1) { bbox = (CButton *)GetDlgItem(IDC_NEXT_MEGACELL); bbox->EnableWindow(FALSE); bbox = (CButton *)GetDlgItem(IDC_PREVIOUS_MEGACELL); bbox->EnableWindow(FALSE); m_CheckForTextureList = 0; return; } else { bbox = (CButton *)GetDlgItem(IDC_NEXT_MEGACELL); bbox->EnableWindow(TRUE); bbox = (CButton *)GetDlgItem(IDC_PREVIOUS_MEGACELL); bbox->EnableWindow(TRUE); } if (!Megacells[n].used) n = D3EditState.current_megacell = GetNextMegacell(n); ebox = (CEdit *)GetDlgItem(IDC_MEGACELL_NAME_EDIT); ebox->SetWindowText(Megacells[n].name); ebox = (CEdit *)GetDlgItem(IDC_MEGA_WIDTH_EDIT); sprintf(str, "%d", Megacells[n].width); ebox->SetWindowText(str); ebox = (CEdit *)GetDlgItem(IDC_MEGA_HEIGHT_EDIT); sprintf(str, "%d", Megacells[n].height); ebox->SetWindowText(str); bbox = (CButton *)GetDlgItem(IDC_CHECKIN_MEGACELL); if (mng_FindTrackLock(Megacells[n].name, PAGETYPE_MEGACELL) == -1) { bbox->EnableWindow(FALSE); bbox = (CButton *)GetDlgItem(IDC_LOCK_MEGACELL); bbox->EnableWindow(TRUE); } else { bbox->EnableWindow(TRUE); bbox = (CButton *)GetDlgItem(IDC_LOCK_MEGACELL); bbox->EnableWindow(FALSE); } SendDlgItemMessage(IDC_MEGACELL_PULLDOWN, CB_RESETCONTENT, 0, 0); for (int i = 0; i < MAX_MEGACELLS; i++) { if (Megacells[i].used) SendDlgItemMessage(IDC_MEGACELL_PULLDOWN, CB_ADDSTRING, 0, (LPARAM)(LPCTSTR)Megacells[i].name); } SendDlgItemMessage(IDC_MEGACELL_PULLDOWN, CB_SELECTSTRING, 0, (LPARAM)(LPCTSTR)Megacells[n].name); UpdateMegacellView(); } #define TEXTURES_PER_ROW 4 void CMegacellDialog::UpdateTextureView() { int n = D3EditState.texdlg_texture; CWnd *texwnd; RECT rect; int x, y, bm_handle, w, h; int update_listbox = 1; Desktop_surf->attach_to_window((unsigned)m_hWnd); if (1 || update_listbox) { texwnd = GetDlgItem(IDC_TEXTURE_LISTBOX); texwnd->GetWindowRect(&rect); ScreenToClient(&rect); w = rect.right - rect.left; h = rect.bottom - rect.top; int texwidth = (w - 1) / 4; int texheight = (h - 1) / 8; Desktop_surf->clear(rect.left, rect.top, w, h); int texnum = m_TexStart; int count = 0, done = 0; while (!done) { m_TextureSurf.create(texwidth, texheight, BPP_16); bm_handle = GetTextureBitmap(texnum, 0); m_TextureSurf.load(bm_handle); x = 1 + rect.left + ((count % TEXTURES_PER_ROW) * texwidth); y = 1 + rect.top + ((count / TEXTURES_PER_ROW) * texheight); if (m_CheckForTextureList) { if (m_CheckX >= x && m_CheckX <= (x + texwidth) && m_CheckY >= y && m_CheckY <= (y + texheight)) { m_CheckForTextureList = 0; D3EditState.texdlg_texture = texnum; m_TextureSurf.free(); Desktop_surf->attach_to_window((unsigned)NULL); UpdateDialog(); return; } } if (texnum == n) // draw a white box if this is the current texture { grViewport *vport = new grViewport(&m_TextureSurf); int x = 0, y = 0; vport->lock(); vport->line(GR_RGB(255, 255, 255), x, y, x + vport->width() - 1, y); vport->line(GR_RGB(255, 255, 255), x + vport->width() - 1, y, x + vport->width() - 1, y + vport->height() - 1); vport->line(GR_RGB(255, 255, 255), x + vport->width() - 1, y + vport->height() - 1, x, y + vport->height() - 1); vport->line(GR_RGB(255, 255, 255), x, y + vport->height() - 1, x, y); vport->unlock(); delete vport; } Desktop_surf->blt(x, y, &m_TextureSurf); texnum = GetNextTexture(texnum); m_TextureSurf.free(); count++; if (count == TEXTURES_PER_ROW * 8) done = 1; if (texnum <= m_TexStart) done = 1; } // must define the vertical scroll bar dimensions CScrollBar *bar = (CScrollBar *)GetDlgItem(IDC_TEXLIST_VERT); SCROLLINFO si; m_TexPageLen = (count / TEXTURES_PER_ROW) + ((count % TEXTURES_PER_ROW) ? 1 : 0); m_TexListPos = bar->GetScrollPos(); si.cbSize = sizeof(si); si.fMask = SIF_ALL; si.nMin = 0; si.nMax = (Num_textures / TEXTURES_PER_ROW) + ((Num_textures % TEXTURES_PER_ROW) ? 1 : 0) - 1; si.nPos = m_TexListPos; si.nPage = m_TexPageLen; bar->SetScrollInfo(&si); bar->ShowScrollBar(TRUE); } Desktop_surf->attach_to_window((unsigned)NULL); } void CMegacellDialog::TextureListUp(int rows) { int old = m_TexStart; int done = 0, count = 0; while ((count < (TEXTURES_PER_ROW * rows)) && !done) { m_TexStart = GetPreviousTexture(m_TexStart); if (old <= m_TexStart) { m_TexStart = old; done = 1; } else count++; } m_RedrawListbox = 1; UpdateDialog(); } void CMegacellDialog::TextureListDown(int rows) { int old = m_TexStart; int done = 0, count = 0; while ((count < (TEXTURES_PER_ROW * rows)) && !done) { m_TexStart = GetNextTexture(m_TexStart); if (old >= m_TexStart) { m_TexStart = old; done = 1; } else count++; } m_RedrawListbox = 1; UpdateDialog(); } void CMegacellDialog::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar *pScrollBar) { int id = -1, min, max; int new_pos = 0; if (pScrollBar) { id = pScrollBar->GetDlgCtrlID(); pScrollBar->GetScrollRange(&min, &max); } switch (id) { case IDC_TEXLIST_VERT: // vertically scroll the texture list box switch (nSBCode) { case SB_LINEDOWN: new_pos = m_TexListPos + 1; break; case SB_LINEUP: new_pos = m_TexListPos - 1; break; case SB_THUMBPOSITION: new_pos = nPos; break; case SB_THUMBTRACK: new_pos = nPos; break; case SB_PAGEDOWN: new_pos = m_TexListPos + m_TexPageLen; break; case SB_PAGEUP: new_pos = m_TexListPos - m_TexPageLen; break; default: new_pos = m_TexListPos; } if (new_pos < 0) new_pos = 0; if (new_pos > (max - m_TexPageLen)) new_pos = (max - m_TexPageLen) + 1; if (new_pos != m_TexListPos) { // ok, new_pos will be an index into the listbox, NOT the texture list. // so we will get the number of texture rows we went up or down and change // tex_start accordingly. mprintf(0, "scroll new_pos = %d. original_pos = %d\n", new_pos, m_TexListPos); if (new_pos < m_TexListPos) TextureListUp(abs(m_TexListPos - new_pos)); if (new_pos > m_TexListPos) TextureListDown(abs(new_pos - m_TexListPos)); m_TexListPos = new_pos; SCROLLINFO si; si.cbSize = sizeof(si); si.fMask = SIF_POS; si.nPos = m_TexListPos; pScrollBar->SetScrollInfo(&si); } break; default: Int3(); // WHAT THE FUCK!! } CDialog::OnVScroll(nSBCode, nPos, pScrollBar); } void CMegacellDialog::UpdateMegacellView() { int n = D3EditState.current_megacell; CWnd *texwnd; RECT rect; int x, y, bm_handle, w, h; int megawidth = Megacells[n].width; int megaheight = Megacells[n].height; int i, t; Desktop_surf->attach_to_window((unsigned)m_hWnd); texwnd = GetDlgItem(IDC_MEGACELL_VIEW); texwnd->GetWindowRect(&rect); ScreenToClient(&rect); w = rect.right - rect.left; h = rect.bottom - rect.top; int texwidth = w / megawidth; int texheight = h / megaheight; // Don't have to clear if we're overwriting the whole area! // if (megawidth<8 || megaheight<8) // Desktop_surf->clear(rect.left,rect.top,w,h); for (i = 0; i < megaheight; i++) { for (t = 0; t < megawidth; t++) { m_TextureSurf.create(texwidth, texheight, BPP_16); bm_handle = GetTextureBitmap(Megacells[n].texture_handles[i * MAX_MEGACELL_WIDTH + t], 0); m_TextureSurf.load(bm_handle); x = 1 + rect.left + (t * texwidth); y = 1 + rect.top + (i * texheight); if (m_CheckForTextureList) { if (m_CheckX >= x && m_CheckX <= (x + texwidth) && m_CheckY >= y && m_CheckY <= (y + texheight)) { m_CheckForTextureList = 0; Megacells[n].texture_handles[i * MAX_MEGACELL_WIDTH + t] = D3EditState.texdlg_texture; m_TextureSurf.free(); Desktop_surf->attach_to_window((unsigned)NULL); UpdateDialog(); return; } } // Draw a separation line on the right and bottom side { grViewport *vport = new grViewport(&m_TextureSurf); int x = 0, y = 0; vport->lock(); vport->line(GR_RGB(0, 0, 0), 0, vport->height() - 1, vport->width() - 1, vport->height() - 1); vport->line(GR_RGB(0, 0, 0), vport->width() - 1, 0, vport->width() - 1, vport->height() - 1); vport->unlock(); delete vport; } Desktop_surf->blt(x, y, &m_TextureSurf); m_TextureSurf.free(); } } m_CheckForTextureList = 0; Desktop_surf->attach_to_window((unsigned)NULL); } void CMegacellDialog::OnPaint() { CPaintDC dc(this); // device context for painting UpdateDialog(); // Do not call CDialog::OnPaint() for painting messages } void CMegacellDialog::OnRemapMegacell() { int n = D3EditState.current_megacell; mngs_megacell_page megacellpage; if (mng_FindSpecificMegacellPage(Megacells[n].name, &megacellpage, 1)) { if (!mng_AssignMegacellPageToMegacell(&megacellpage, n)) Int3(); // Get Jason } else if (mng_FindSpecificMegacellPage(Megacells[n].name, &megacellpage, 0)) { if (!mng_AssignMegacellPageToMegacell(&megacellpage, n)) Int3(); // Get Jason } else OutrageMessageBox("This megacell was not found in the local table file."); UpdateDialog(); } void CMegacellDialog::OnRotateMegacell() { int n = D3EditState.current_megacell; int buffer[MAX_MEGACELL_WIDTH * MAX_MEGACELL_HEIGHT]; int i; if (!Megacells[n].used) return; for (i = 0; i < MAX_MEGACELL_WIDTH * MAX_MEGACELL_HEIGHT; i++) buffer[i] = 0; int oldwidth = Megacells[n].width; int oldheight = Megacells[n].height; for (i = 0; i < MAX_MEGACELL_HEIGHT; i++) { for (int t = 0; t < MAX_MEGACELL_WIDTH; t++) { buffer[((MAX_MEGACELL_HEIGHT - 1) - t) * MAX_MEGACELL_WIDTH + i] = Megacells[n].texture_handles[i * MAX_MEGACELL_WIDTH + t]; } } for (i = 0; i < MAX_MEGACELL_WIDTH * MAX_MEGACELL_HEIGHT; i++) Megacells[n].texture_handles[i] = buffer[i]; Megacells[n].width = oldheight; Megacells[n].height = oldwidth; UpdateDialog(); } void CMegacellDialog::OnCopyMegacell() { int n = D3EditState.current_megacell; int i; if (!Megacells[n].used) return; m_CopyMegacell.width = Megacells[n].width; m_CopyMegacell.height = Megacells[n].height; for (i = 0; i < MAX_MEGACELL_WIDTH * MAX_MEGACELL_HEIGHT; i++) m_CopyMegacell.texture_handles[i] = Megacells[n].texture_handles[i]; mprintf(0, "Megacell copied.\n"); } void CMegacellDialog::OnPasteMegacell() { int n = D3EditState.current_megacell; int i; if (!Megacells[n].used) return; Megacells[n].width = m_CopyMegacell.width; Megacells[n].height = m_CopyMegacell.height; for (i = 0; i < MAX_MEGACELL_WIDTH * MAX_MEGACELL_HEIGHT; i++) Megacells[n].texture_handles[i] = m_CopyMegacell.texture_handles[i]; UpdateDialog(); } void CMegacellDialog::CheckinTexture(int n, int tracklock_num) { mngs_Pagelock temp_pl; int r; if (!GameTextures[n].used) { mprintf(0, "Whoa, trying to save non-used texture %s!\n", GameTextures[n].name); return; } strcpy(temp_pl.name, GameTextures[n].name); temp_pl.pagetype = PAGETYPE_TEXTURE; r = mng_CheckIfPageOwned(&temp_pl, TableUser); if (r < 0) OutrageMessageBox(ErrorString); else if (r == 0) OutrageMessageBox(InfoString); else { strcpy(temp_pl.holder, "UNLOCKED"); if (!mng_ReplacePagelock(temp_pl.name, &temp_pl)) { OutrageMessageBox(ErrorString, "Error!"); mng_EraseLocker(); return; } else { if (!mng_ReplacePage(GameTextures[n].name, GameTextures[n].name, n, PAGETYPE_TEXTURE, 0)) OutrageMessageBox(ErrorString); else { // Save this textures bitmap to the network for all std::filesystem::path fname; if (GameTextures[n].flags & TF_ANIMATED) { fname = ManageGraphicsDir / GameVClips[GameTextures[n].bm_handle].name; SaveVClip(fname, GameTextures[n].bm_handle); fname = LocalManageGraphicsDir / GameVClips[GameTextures[n].bm_handle].name; SaveVClip(fname, GameTextures[n].bm_handle); } else { fname = ManageGraphicsDir / GameBitmaps[GameTextures[n].bm_handle].name; bm_SaveFileBitmap(fname, GameTextures[n].bm_handle); fname = LocalManageGraphicsDir / GameBitmaps[GameTextures[n].bm_handle].name; bm_SaveFileBitmap(fname, GameTextures[n].bm_handle); } mprintf(0, "%s texture checked in.\n", GameTextures[n].name); int dret = mng_DeletePage(GameTextures[n].name, PAGETYPE_TEXTURE, 1); ASSERT(dret == 1); mng_FreeTrackLock(tracklock_num); } } } } void CMegacellDialog::OnImportTiny() { char filename[255]; int n = D3EditState.current_megacell; int megawidth = Megacells[n].width; int megaheight = Megacells[n].height; int src_handle; int count = 0; int i, t; if (!Network_up) { OutrageMessageBox("Sorry babe, the network is down. This action is a no-no.\n"); return; } if (Num_megacells < 1) { OutrageMessageBox("You must first create a megacell before using this feature."); return; } if ((mng_FindTrackLock(Megacells[n].name, PAGETYPE_MEGACELL)) == -1) { OutrageMessageBox("You must have this megacell locked before you can import!"); return; } CString filter = "Descent III files (*.tga,*.bbm,*.lbm,*.ogf,*.pcx)|*.pcx;*.tga;*.bbm;*.lbm;*.ogf;||"; if (!OpenFileDialog(this, (LPCSTR)filter, filename, Current_bitmap_dir, sizeof(Current_bitmap_dir))) return; // Okay, we selected a file. Lets do what needs to be done here. src_handle = bm_AllocLoadFileBitmap(filename, 0); if (src_handle < 0) { OutrageMessageBox("Couldn't read that bitmap!"); return; } int w = bm_w(src_handle, 0); int h = bm_h(src_handle, 0); float width_per_cell = (float)w / (float)megawidth; float height_per_cell = (float)h / (float)megaheight; for (i = 0; i < megaheight; i++) { for (t = 0; t < megawidth; t++) { float startx = width_per_cell * t; float starty = height_per_cell * i; float u = startx; float v = starty; float du = width_per_cell / 32.0; float dv = height_per_cell / 32.0; int bm_handle = bm_AllocBitmap(32, 32, 0); ASSERT(bm_handle >= 0); uint16_t *dest_data = bm_data(bm_handle, 0); uint16_t *src_data = bm_data(src_handle, 0); for (int ty = 0; ty < 32; ty++, u = startx, v += dv) { for (int tx = 0; tx < 32; tx++, u += du) { int cu = u; int cv = v; uint16_t pix = src_data[cv * w + cu]; dest_data[ty * 32 + tx] = pix; } } // Alloc a texture and assign it this bitmap handle int tex_handle; tex_handle = AllocTexture(); ASSERT(tex_handle > 0); GameTextures[tex_handle].flags &= ~(TF_TEXTURE_TYPES); GameTextures[tex_handle].flags |= TF_TEXTURE_32; GameTextures[tex_handle].flags |= TF_TERRAIN; GameTextures[tex_handle].bm_handle = bm_handle; Megacells[n].texture_handles[i * MAX_MEGACELL_WIDTH + t] = tex_handle; // Find a unique name for this texture int finding_name = 1; char cur_name[255]; while (finding_name) { sprintf(cur_name, "%s%d", Megacells[n].name, count); if (FindTextureName(cur_name) != -1) count++; else finding_name = 0; } strcpy(GameTextures[tex_handle].name, cur_name); bm_ChangeEndName(Megacells[n].name, filename); strcpy(GameBitmaps[bm_handle].name, filename); // Save this textures image locally sprintf(filename, "%s\\%s", LocalManageGraphicsDir.u8string().c_str(), GameBitmaps[GameTextures[tex_handle].bm_handle].name); mprintf(0, "Saving bitmap %s from megacell!\n", GameBitmaps[bm_handle].name); bm_SaveFileBitmap(filename, GameTextures[tex_handle].bm_handle); // Allocate a track lock for this texture mng_AllocTrackLock(cur_name, PAGETYPE_TEXTURE); } } bm_FreeBitmap(src_handle); UpdateDialog(); } BOOL CMegacellDialog::OnHelpInfo(HELPINFO *pHelpInfo) { // TODO: Add your message handler code here and/or call default WinHelp(HID_MEGACELLDLG, HELP_CONTEXT); return TRUE; // return CDialog::OnHelpInfo(pHelpInfo); } #define SKY_TEXTURE_SIZE 128 void CMegacellDialog::OnImportSky() { char filename[255]; int n = D3EditState.current_megacell; int megawidth = Megacells[n].width; int megaheight = Megacells[n].height; int src_handle; int count = 0; int i, t; if (!Network_up) { OutrageMessageBox("Sorry babe, the network is down. This action is a no-no.\n"); return; } if (Num_megacells < 1) { OutrageMessageBox("You must first create a megacell before using this feature."); return; } if (megawidth != 2 || megaheight != 2) { OutrageMessageBox("All sky dome megacells must be 2x2 in dimensions!"); return; } if ((mng_FindTrackLock(Megacells[n].name, PAGETYPE_MEGACELL)) == -1) { OutrageMessageBox("You must have this megacell locked before you can import!"); return; } CString filter = "Descent III files (*.tga,*.bbm,*.lbm,*.ogf,*.pcx)|*.pcx;*.tga;*.bbm;*.lbm;*.ogf;||"; if (!OpenFileDialog(this, (LPCSTR)filter, filename, Current_bitmap_dir, sizeof(Current_bitmap_dir))) return; // Okay, we selected a file. Lets do what needs to be done here. src_handle = bm_AllocLoadFileBitmap(filename, 0); if (src_handle < 0) { OutrageMessageBox("Couldn't read that bitmap!"); return; } int w = bm_w(src_handle, 0); int h = bm_h(src_handle, 0); float width_per_cell = (float)w / (float)megawidth; float height_per_cell = (float)h / (float)megaheight; for (i = 0; i < megaheight; i++) { for (t = 0; t < megawidth; t++) { float startx = width_per_cell * t; float starty = height_per_cell * i; float u = startx; float v = starty; float du = width_per_cell / (float)SKY_TEXTURE_SIZE; float dv = height_per_cell / (float)SKY_TEXTURE_SIZE; int bm_handle = bm_AllocBitmap(SKY_TEXTURE_SIZE, SKY_TEXTURE_SIZE, 0); ASSERT(bm_handle >= 0); uint16_t *dest_data = bm_data(bm_handle, 0); uint16_t *src_data = bm_data(src_handle, 0); for (int ty = 0; ty < SKY_TEXTURE_SIZE; ty++, u = startx, v += dv) { for (int tx = 0; tx < SKY_TEXTURE_SIZE; tx++, u += du) { int cu = u; int cv = v; uint16_t pix = src_data[cv * w + cu]; dest_data[ty * SKY_TEXTURE_SIZE + tx] = pix; } } // Alloc a texture and assign it this bitmap handle int tex_handle; tex_handle = AllocTexture(); ASSERT(tex_handle > 0); GameTextures[tex_handle].flags |= TF_TERRAIN; GameTextures[tex_handle].bm_handle = bm_handle; Megacells[n].texture_handles[i * MAX_MEGACELL_WIDTH + t] = tex_handle; // Find a unique name for this texture int finding_name = 1; char cur_name[255]; while (finding_name) { sprintf(cur_name, "%s%d", Megacells[n].name, count); if (FindTextureName(cur_name) != -1) count++; else finding_name = 0; } strcpy(GameTextures[tex_handle].name, cur_name); bm_ChangeEndName(Megacells[n].name, filename); strcpy(GameBitmaps[bm_handle].name, filename); // Save this textures image locally sprintf(filename, "%s\\%s", LocalManageGraphicsDir.u8string().c_str(), GameBitmaps[GameTextures[tex_handle].bm_handle].name); mprintf(0, "Saving bitmap %s from megacell!\n", GameBitmaps[bm_handle].name); bm_SaveFileBitmap(filename, GameTextures[tex_handle].bm_handle); // Allocate a track lock for this texture mng_AllocTrackLock(cur_name, PAGETYPE_TEXTURE); } } bm_FreeBitmap(src_handle); UpdateDialog(); } #define SKY_BAND_SIZE 64 void CMegacellDialog::OnImportSkyBand() { char filename[255]; int n = D3EditState.current_megacell; int megawidth = Megacells[n].width; int megaheight = Megacells[n].height; int src_handle; int count = 0; int t; if (!Network_up) { OutrageMessageBox("Sorry babe, the network is down. This action is a no-no.\n"); return; } if (Num_megacells < 1) { OutrageMessageBox("You must first create a megacell before using this feature."); return; } if (megawidth != 8 || megaheight != 2) { OutrageMessageBox("All sky band megacells must be 8x2 in dimensions!"); return; } if ((mng_FindTrackLock(Megacells[n].name, PAGETYPE_MEGACELL)) == -1) { OutrageMessageBox("You must have this megacell locked before you can import!"); return; } CString filter = "Descent III files (*.tga,*.bbm,*.lbm,*.ogf,*.pcx)|*.pcx;*.tga;*.bbm;*.lbm;*.ogf;||"; if (!OpenFileDialog(this, (LPCSTR)filter, filename, Current_bitmap_dir, sizeof(Current_bitmap_dir))) return; // Okay, we selected a file. Lets do what needs to be done here. src_handle = bm_AllocLoadFileBitmap(filename, 0); if (src_handle < 0) { OutrageMessageBox("Couldn't read that bitmap!"); return; } int w = bm_w(src_handle, 0); int h = bm_h(src_handle, 0); float width_per_cell = (float)w / (float)16; float height_per_cell = (float)h / (float)1; for (t = 0; t < 16; t++) { float startx = width_per_cell * t; float starty = 0; float u = startx; float v = starty; float du = width_per_cell / (float)SKY_BAND_SIZE; float dv = height_per_cell / (float)SKY_BAND_SIZE; int bm_handle = bm_AllocBitmap(SKY_BAND_SIZE, SKY_BAND_SIZE, 0); ASSERT(bm_handle >= 0); uint16_t *dest_data = bm_data(bm_handle, 0); uint16_t *src_data = bm_data(src_handle, 0); for (int ty = 0; ty < SKY_BAND_SIZE; ty++, u = startx, v += dv) { for (int tx = 0; tx < SKY_BAND_SIZE; tx++, u += du) { int cu = u; int cv = v; uint16_t pix = src_data[cv * w + cu]; dest_data[ty * SKY_BAND_SIZE + tx] = pix; } } // Alloc a texture and assign it this bitmap handle int tex_handle; tex_handle = AllocTexture(); ASSERT(tex_handle > 0); GameTextures[tex_handle].flags &= ~(TF_TEXTURE_TYPES); GameTextures[tex_handle].flags |= (TF_TERRAIN | TF_TEXTURE_64); GameTextures[tex_handle].bm_handle = bm_handle; int row = t / MAX_MEGACELL_WIDTH; int column = t % MAX_MEGACELL_WIDTH; Megacells[n].texture_handles[row * MAX_MEGACELL_WIDTH + column] = tex_handle; // Find a unique name for this texture int finding_name = 1; char cur_name[255]; while (finding_name) { sprintf(cur_name, "%s%d", Megacells[n].name, count); if (FindTextureName(cur_name) != -1) count++; else finding_name = 0; } strcpy(GameTextures[tex_handle].name, cur_name); bm_ChangeEndName(Megacells[n].name, filename); strcpy(GameBitmaps[bm_handle].name, filename); // Save this textures image locally sprintf(filename, "%s\\%s", LocalManageGraphicsDir.u8string().c_str(), GameBitmaps[GameTextures[tex_handle].bm_handle].name); mprintf(0, "Saving bitmap %s from megacell!\n", GameBitmaps[bm_handle].name); bm_SaveFileBitmap(filename, GameTextures[tex_handle].bm_handle); // Allocate a track lock for this texture mng_AllocTrackLock(cur_name, PAGETYPE_TEXTURE); } bm_FreeBitmap(src_handle); UpdateDialog(); }