mirror of
https://github.com/kevinbentley/Descent3.git
synced 2025-01-22 11:28:56 +00:00
c3b1225c6e
This function is stubbed and does nothing.
2105 lines
55 KiB
C++
2105 lines
55 KiB
C++
/*
|
|
* 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 <http://www.gnu.org/licenses/>.
|
|
|
|
--- HISTORICAL COMMENTS FOLLOW ---
|
|
|
|
* $Logfile: /DescentIII/Main/editor/TerrainDialog.cpp $
|
|
* $Revision: 1.1.1.1 $
|
|
* $Date: 2003-08-26 03:57:39 $
|
|
* $Author: kevinb $
|
|
*
|
|
* Terrain dialog implementaion
|
|
*
|
|
* $Log: not supported by cvs2svn $
|
|
*
|
|
* 75 4/29/99 3:49p Matt
|
|
* Fixed compiler warning
|
|
*
|
|
* 74 4/27/99 3:38p Jason
|
|
* fixed occlusion bug
|
|
*
|
|
* 73 4/17/99 6:15p Samir
|
|
* replaced gr.h with grdefs.h and fixed resulting compile bugs.
|
|
*
|
|
* 72 2/26/99 3:32p Jason
|
|
* made satellites clip properly
|
|
*
|
|
* 71 2/21/99 12:28p Matt
|
|
* Added terrain sound system
|
|
*
|
|
* 70 1/24/99 5:44p Jason
|
|
* added more selection choice for terrain
|
|
*
|
|
* 69 1/22/99 3:59p Jason
|
|
* added 256x256 textures to help with terrain skies
|
|
*
|
|
* 68 1/21/99 11:15p Jeff
|
|
* pulled out some structs and defines from header files and moved them
|
|
* into separate header files so that multiplayer dlls don't require major
|
|
* game headers, just those new headers. Side effect is a shorter build
|
|
* time. Also cleaned up some header file #includes that weren't needed.
|
|
* This affected polymodel.h, object.h, player.h, vecmat.h, room.h,
|
|
* manage.h and multi.h
|
|
*
|
|
* 67 1/21/99 12:31a Jason
|
|
* fixed stack bug
|
|
*
|
|
* 66 1/20/99 10:50a Jason
|
|
* added new terrain
|
|
*
|
|
* 65 1/15/99 7:52p Chris
|
|
* Updated ObjSetPos() to include a f_update_attach_children flag
|
|
*
|
|
* 64 1/05/99 4:14p Matt
|
|
* Fixed compile warning
|
|
*
|
|
* 63 11/18/98 4:30p Jason
|
|
* added some functionality to terrain fog
|
|
*
|
|
* 62 11/11/98 11:42a Jason
|
|
* added sunlight damage
|
|
*
|
|
* 61 10/14/98 2:48p Kevin
|
|
* Changed memory code to comply with mem lib
|
|
*
|
|
* 60 10/08/98 4:24p Kevin
|
|
* Changed code to comply with memory library usage. Always use mem_malloc
|
|
* , mem_free and mem_strdup
|
|
*
|
|
* 59 9/29/98 12:53p Jason
|
|
* added "force visiblity" for Luke
|
|
*
|
|
* 58 8/19/98 2:19p Jeff
|
|
* moved detail globals to a struct
|
|
*
|
|
* 57 8/13/98 1:13p Jason
|
|
* fixed terrain distance bug
|
|
*
|
|
* 56 7/20/98 12:04p Jason
|
|
* added per level satellite lighting
|
|
*
|
|
* 55 6/04/98 6:45p Jason
|
|
* made objects use the terrain occlusion system
|
|
*
|
|
* 54 6/04/98 6:16p Jason
|
|
* added terrain occlusion system
|
|
*
|
|
* 53 5/19/98 3:19p Jason
|
|
* cleaned up some texture flags
|
|
*
|
|
* 52 5/01/98 3:51p Jason
|
|
* sped up terrain rendering by precaching all megacell lod bitmaps
|
|
*
|
|
* 51 4/29/98 5:00p Matt
|
|
* Fixed stupid bug
|
|
*
|
|
* 50 4/29/98 3:58p Matt
|
|
* Made the drop terrain function take a desired height, instead of always
|
|
* moving the terrain to zero.
|
|
*
|
|
* 49 4/23/98 6:38p Jason
|
|
* made bitmaps use 1555 format
|
|
*
|
|
* 48 4/01/98 11:25a Jeff
|
|
* Added an editor bool to skip Terrain object rendering
|
|
*
|
|
* 47 3/30/98 5:43p Jason
|
|
* fixed pcx exporting
|
|
*
|
|
* 46 3/30/98 3:29p Jason
|
|
* added the ability to save a pcx version of the terrain
|
|
*
|
|
* 45 3/23/98 6:06p Matt
|
|
* Added code to "drop" the terrain so the lowest point has y==0, and to
|
|
* move the buildings, objects, & paths with it.
|
|
*
|
|
* 44 3/06/98 6:15p Jason
|
|
* Give message if no cells selected in smooth terrain
|
|
*
|
|
* 43 3/06/98 6:13p Jason
|
|
* Made terrain smoothing work on selected cells only
|
|
*
|
|
* 42 2/17/98 4:17p Jason
|
|
* fixed satellite placement
|
|
*
|
|
* 41 1/26/98 2:16p Jason
|
|
* allowed toggle of visibility to multiple cells
|
|
*
|
|
* 40 1/16/98 8:06p Jason
|
|
* added selectable halos and atmosphere blends to satellites
|
|
*
|
|
* 39 1/10/98 2:23p Jason
|
|
* fixed terrain checksum problem
|
|
*
|
|
* 38 1/07/98 4:19p Jason
|
|
* added dome to terrain sky
|
|
*
|
|
* 37 12/30/97 5:45p Jason
|
|
* added toggleable fog
|
|
*
|
|
* 36 12/17/97 5:26p Jason
|
|
* added support for selectable wraparound sky
|
|
*
|
|
* 35 12/11/97 1:41p Jason
|
|
* added terrain smoothing
|
|
*
|
|
* 34 12/02/97 5:31p Samir
|
|
* New file dialog interface implemented.
|
|
*
|
|
* 33 12/01/97 10:52a Jason
|
|
* separated satellite and star rendering flags
|
|
*
|
|
* 32 10/15/97 5:20p Jason
|
|
* did a HUGE overhaul of the bitmap system
|
|
*
|
|
* 31 10/06/97 12:16p Jason
|
|
* Ripped out old mine/terrain connection code, plus added ability to move
|
|
* satellites
|
|
*
|
|
* 30 10/02/97 6:10p Jason
|
|
* made invisible cells not be LODable
|
|
*
|
|
* 29 10/02/97 2:45p Jason
|
|
* got invisible terrain cells working
|
|
*
|
|
* 28 9/25/97 5:02p Jason
|
|
* fixed bug caused by last rev where pixelerror and terraindistance would
|
|
* be displayed
|
|
*
|
|
* 27 9/23/97 2:29p Jason
|
|
* did terrain editing enhancements
|
|
*
|
|
* 26 9/17/97 1:01p Matt
|
|
* Ripped out segment code
|
|
*
|
|
* 25 9/17/97 11:50a Jason
|
|
* ripped out segment engine
|
|
*
|
|
* 24 9/15/97 5:54p Jason
|
|
* delete room portals when deleting rooms connected to terrain
|
|
*
|
|
* 23 9/05/97 6:18p Jason
|
|
* made pixel error setable to 0
|
|
*
|
|
* 22 9/02/97 10:47a Jason
|
|
* use separate variables for game and editor LOD engine status
|
|
*
|
|
* 21 8/26/97 4:36p Jason
|
|
* added terrain radiosity
|
|
*
|
|
* 20 8/25/97 12:04p Samir
|
|
* Added scrolling capabilities for dialog.
|
|
*
|
|
* 19 8/22/97 10:17a Matt
|
|
* When adding a room to the terrain, set the current face to be the one
|
|
* opposite the portal face.
|
|
*
|
|
* $NoKeywords: $
|
|
*/
|
|
|
|
#include <algorithm>
|
|
|
|
#include "stdafx.h"
|
|
#include "editor.h"
|
|
#include "TerrainDialog.h"
|
|
#include "terrain.h"
|
|
#include "gametexture.h"
|
|
#include "bitmap.h"
|
|
#include "group.h"
|
|
#include "editor/d3edit.h"
|
|
#include "room.h"
|
|
#include "erooms.h"
|
|
#include "roomuvs.h"
|
|
#include "SelectRangeDialog.h"
|
|
#include "findintersection.h"
|
|
#include "config.h"
|
|
#include "mem.h"
|
|
#include "mono.h"
|
|
#include "gr.h"
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CTerrainDialog dialog
|
|
|
|
CTerrainDialog::CTerrainDialog(CWnd *pParent /*=NULL*/) : CKeypadDialog(CTerrainDialog::IDD, pParent) {
|
|
//{{AFX_DATA_INIT(CTerrainDialog)
|
|
// NOTE: the ClassWizard will add member initialization here
|
|
//}}AFX_DATA_INIT
|
|
|
|
cc_mode = CC_MODE_SKY;
|
|
}
|
|
|
|
void CTerrainDialog::DoDataExchange(CDataExchange *pDX) {
|
|
CDialog::DoDataExchange(pDX);
|
|
//{{AFX_DATA_MAP(CTerrainDialog)
|
|
// NOTE: the ClassWizard will add DDX and DDV calls here
|
|
//}}AFX_DATA_MAP
|
|
}
|
|
|
|
BEGIN_MESSAGE_MAP(CTerrainDialog, CDialog)
|
|
//{{AFX_MSG_MAP(CTerrainDialog)
|
|
ON_WM_SIZE()
|
|
ON_BN_CLICKED(IDC_TERRPAD_MOVE_UP, OnTerrpadMoveUp)
|
|
ON_BN_CLICKED(IDC_TERRPAD_MOVE_DOWN, OnTerrpadMoveDown)
|
|
ON_BN_CLICKED(IDC_TERRPAD_IMPORT, OnTerrpadImport)
|
|
ON_BN_CLICKED(IDC_TERRPAD_RENORMALIZE, OnTerrpadRenormalize)
|
|
ON_BN_CLICKED(IDC_TERRPAD_RAISE10, OnTerrpadRaise10)
|
|
ON_BN_CLICKED(IDC_TERRPAD_LOWER10, OnTerrpadLower10)
|
|
ON_BN_CLICKED(IDC_SKY_TEXTURE, OnSkyTexture)
|
|
ON_BN_CLICKED(IDC_TERRPAD_SELECT_NONE, OnTerrpadSelectNone)
|
|
ON_BN_CLICKED(IDC_TERRPAD_ROT_TEXTURE, OnTerrpadRotTexture)
|
|
ON_BN_CLICKED(IDC_SKY_NEARER, OnSkyNearer)
|
|
ON_BN_CLICKED(IDC_SKY_FARTHER, OnSkyFarther)
|
|
ON_BN_CLICKED(IDC_STARS_CHECK, OnStarsCheck)
|
|
ON_BN_CLICKED(IDC_FAST_TERRAIN_CHECK, OnFastTerrainCheck)
|
|
ON_BN_CLICKED(IDC_TERRPAD_FILL_AREA, OnTerrpadFillArea)
|
|
ON_BN_CLICKED(IDC_TERRPAD_REDO_TOPMAP, OnTerrpadRedoTopmap)
|
|
ON_BN_CLICKED(IDC_TERRPAD_MAKE_MAX, OnTerrpadMakeMax)
|
|
ON_BN_CLICKED(IDC_TERRPAD_MAKE_MIN, OnTerrpadMakeMin)
|
|
ON_BN_CLICKED(IDC_TERRPAD_MAKE_ZERO, OnTerrpadMakeZero)
|
|
ON_BN_CLICKED(IDC_TERRPAD_PYRAMID, OnTerrpadPyramid)
|
|
ON_BN_CLICKED(IDC_TERRPAD_HILL, OnTerrpadHill)
|
|
ON_BN_CLICKED(IDC_TERRPAD_PANCAKES, OnTerrpadPancakes)
|
|
ON_BN_CLICKED(IDC_TERR_MOVE_MOON, OnTerrMoveMoon)
|
|
ON_BN_CLICKED(IDC_TERR_RANDOMIZE_SKY, OnTerrRandomizeSky)
|
|
ON_WM_PAINT()
|
|
ON_BN_CLICKED(IDC_TERR_MORE_MOONS, OnTerrMoreMoons)
|
|
ON_BN_CLICKED(IDC_TERR_LESS_MOONS, OnTerrLessMoons)
|
|
ON_BN_CLICKED(IDC_TERR_NEXT_MOON, OnTerrNextMoon)
|
|
ON_BN_CLICKED(IDC_TERR_PREV_MOON, OnTerrPrevMoon)
|
|
ON_BN_CLICKED(IDC_SHOW_TERRAIN, OnShowTerrain)
|
|
ON_BN_CLICKED(IDC_FLAT_SHADE_TERRAIN_CHECK, OnFlatShadeTerrainCheck)
|
|
ON_WM_HELPINFO()
|
|
ON_BN_CLICKED(IDC_TERR_SELECT_ALL, OnTerrSelectAll)
|
|
ON_BN_CLICKED(IDC_TERRAIN_2D, OnTerrain2d)
|
|
ON_BN_CLICKED(IDC_TEXTURE_SKY, OnTextureSky)
|
|
ON_EN_KILLFOCUS(IDC_SKY_RED_EDIT, OnKillfocusSkyRedEdit)
|
|
ON_EN_KILLFOCUS(IDC_SKY_GREEN_EDIT, OnKillfocusSkyGreenEdit)
|
|
ON_EN_KILLFOCUS(IDC_SKY_BLUE_EDIT, OnKillfocusSkyBlueEdit)
|
|
ON_BN_CLICKED(IDC_NO_LOD_ENGINE, OnNoLodEngine)
|
|
ON_EN_KILLFOCUS(IDC_FOG_DISTANCE_EDIT, OnKillfocusFogDistanceEdit)
|
|
ON_EN_KILLFOCUS(IDC_PIXEL_ERROR_EDIT, OnKillfocusPixelErrorEdit)
|
|
ON_BN_CLICKED(IDC_TERRPAD_SELECTRANGE, OnTerrpadSelectrange)
|
|
ON_WM_VSCROLL()
|
|
ON_WM_HSCROLL()
|
|
ON_BN_CLICKED(IDC_SKY_RADIO, OnSkyRadio)
|
|
ON_BN_CLICKED(IDC_HORIZON_RADIO, OnHorizonRadio)
|
|
ON_BN_CLICKED(IDC_FOG_RADIO, OnFogRadio)
|
|
ON_BN_CLICKED(IDC_TOGGLE_VISIBILITY, OnToggleVisibility)
|
|
ON_BN_CLICKED(IDC_SHOW_INVISIBLE, OnShowInvisible)
|
|
ON_BN_CLICKED(IDC_TERR_MOVE_MOON_AWAY, OnTerrMoveMoonAway)
|
|
ON_BN_CLICKED(IDC_MOVE_SAT_UP, OnMoveSatUp)
|
|
ON_BN_CLICKED(IDC_MOVE_SAT_DOWN, OnMoveSatDown)
|
|
ON_BN_CLICKED(IDC_MOVE_SAT_LEFT, OnMoveSatLeft)
|
|
ON_BN_CLICKED(IDC_MOVE_SAT_RIGHT, OnMoveSatRight)
|
|
ON_BN_CLICKED(IDC_SATELLITE_CHECK, OnSatelliteCheck)
|
|
ON_BN_CLICKED(IDC_SMOOTH_TERRAIN, OnSmoothTerrain)
|
|
ON_BN_CLICKED(IDC_USE_FOG, OnUseFog)
|
|
ON_BN_CLICKED(IDC_USE_HALO, OnUseHalo)
|
|
ON_BN_CLICKED(IDC_USE_ATMOSPHERE, OnUseAtmosphere)
|
|
ON_BN_CLICKED(IDC_DROP_TERRAIN, OnDropTerrain)
|
|
ON_BN_CLICKED(IDC_SAVE_AS_PCX, OnSaveAsPcx)
|
|
ON_BN_CLICKED(IDC_NO_EXT_ROOMS_OBJS, OnNoExtRoomsObjs)
|
|
ON_BN_CLICKED(IDC_TERRAIN_OCCLUSION, OnTerrainOcclusion)
|
|
ON_BN_CLICKED(IDC_SATELLITE_RADIO, OnSatelliteRadio)
|
|
ON_BN_CLICKED(IDC_FORCE_VISIBLE, OnForceVisible)
|
|
ON_EN_KILLFOCUS(IDC_DAMAGE_PER_SEC_EDIT, OnKillfocusDamagePerSecEdit)
|
|
ON_EN_KILLFOCUS(IDC_FOG_SCALAR_EDIT, OnKillfocusFogScalarEdit)
|
|
ON_BN_CLICKED(IDC_ROTATE_STARS, OnRotateStars)
|
|
ON_BN_CLICKED(IDC_ROTATE_SKY, OnRotateSky)
|
|
ON_EN_KILLFOCUS(IDC_ROTATE_SPEED_EDIT, OnKillfocusRotateSpeedEdit)
|
|
ON_BN_CLICKED(IDC_TILE_MORE, OnTileMore)
|
|
ON_BN_CLICKED(IDC_TILE_LESS, OnTileLess)
|
|
ON_BN_CLICKED(IDC_TERR_SOUND, OnTerrSound)
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CTerrainDialog message handlers
|
|
|
|
void CTerrainDialog::OnSize(UINT nType, int cx, int cy) {
|
|
CKeypadDialog::OnSize(nType, cx, cy);
|
|
|
|
Current_satellite = 0;
|
|
cc_mode = CC_MODE_SKY;
|
|
}
|
|
|
|
void CTerrainDialog::DrawSwatch(int handle, int r, int g, int b) {
|
|
CWnd *texwnd;
|
|
RECT rect;
|
|
int w, h;
|
|
|
|
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, g, b);
|
|
|
|
Desktop_surf->clear(rect.left, rect.top, w, h, color);
|
|
|
|
Desktop_surf->attach_to_window(NULL);
|
|
}
|
|
|
|
void CTerrainDialog::UpdateDialog() {
|
|
CButton *bbox;
|
|
char str[20];
|
|
CEdit *ebox;
|
|
|
|
if (!m_Active)
|
|
return;
|
|
|
|
ebox = (CEdit *)GetDlgItem(IDC_DAMAGE_PER_SEC_EDIT);
|
|
sprintf(str, "%f", Terrain_sky.damage_per_second);
|
|
ebox->SetWindowText(str);
|
|
|
|
ebox = (CEdit *)GetDlgItem(IDC_FOG_SCALAR_EDIT);
|
|
sprintf(str, "%f", Terrain_sky.fog_scalar);
|
|
ebox->SetWindowText(str);
|
|
|
|
ebox = (CEdit *)GetDlgItem(IDC_FOG_DISTANCE_EDIT);
|
|
sprintf(str, "%f", Detail_settings.Terrain_render_distance / TERRAIN_SIZE);
|
|
ebox->SetWindowText(str);
|
|
|
|
ebox = (CEdit *)GetDlgItem(IDC_PIXEL_ERROR_EDIT);
|
|
sprintf(str, "%f", Detail_settings.Pixel_error);
|
|
ebox->SetWindowText(str);
|
|
|
|
ebox = (CEdit *)GetDlgItem(IDC_NUM_MOONS_STATIC);
|
|
sprintf(str, "Num of sats:%d", Terrain_sky.num_satellites);
|
|
ebox->SetWindowText(str);
|
|
|
|
ebox = (CEdit *)GetDlgItem(IDC_CUR_MOON_STATIC);
|
|
sprintf(str, "Current sat:%d", Current_satellite);
|
|
ebox->SetWindowText(str);
|
|
|
|
ebox = (CEdit *)GetDlgItem(IDC_ROTATE_SPEED_EDIT);
|
|
sprintf(str, "%f", Terrain_sky.rotate_rate);
|
|
ebox->SetWindowText(str);
|
|
|
|
CheckDlgButton(IDC_TEXTURE_SKY, Terrain_sky.textured ? 1 : 0);
|
|
CheckDlgButton(IDC_STARS_CHECK, Terrain_sky.flags & TF_STARS ? 1 : 0);
|
|
CheckDlgButton(IDC_ROTATE_STARS, Terrain_sky.flags & TF_ROTATE_STARS ? 1 : 0);
|
|
CheckDlgButton(IDC_ROTATE_SKY, Terrain_sky.flags & TF_ROTATE_SKY ? 1 : 0);
|
|
CheckDlgButton(IDC_SATELLITE_CHECK, Terrain_sky.flags & TF_SATELLITES ? 1 : 0);
|
|
CheckDlgButton(IDC_USE_FOG, Terrain_sky.flags & TF_FOG ? 1 : 0);
|
|
CheckDlgButton(IDC_USE_HALO, Terrain_sky.satellite_flags[Current_satellite] & TSF_HALO ? 1 : 0);
|
|
CheckDlgButton(IDC_USE_ATMOSPHERE, Terrain_sky.satellite_flags[Current_satellite] & TSF_ATMOSPHERE ? 1 : 0);
|
|
|
|
CheckDlgButton(IDC_FAST_TERRAIN_CHECK, Fast_terrain ? 1 : 0);
|
|
CheckDlgButton(IDC_SHOW_TERRAIN, D3EditState.terrain_dots ? 1 : 0);
|
|
CheckDlgButton(IDC_FLAT_SHADE_TERRAIN_CHECK, D3EditState.terrain_flat_shade ? 1 : 0);
|
|
CheckDlgButton(IDC_NO_LOD_ENGINE, Editor_LOD_engine_off ? 1 : 0);
|
|
CheckDlgButton(IDC_NO_EXT_ROOMS_OBJS, Terrain_render_ext_room_objs ? 0 : 1);
|
|
|
|
bbox = (CButton *)GetDlgItem(IDC_SKY_RADIO);
|
|
bbox->SetCheck(cc_mode == CC_MODE_SKY);
|
|
|
|
bbox = (CButton *)GetDlgItem(IDC_HORIZON_RADIO);
|
|
bbox->SetCheck(cc_mode == CC_MODE_HORIZON);
|
|
|
|
bbox = (CButton *)GetDlgItem(IDC_FOG_RADIO);
|
|
bbox->SetCheck(cc_mode == CC_MODE_FOG);
|
|
|
|
bbox = (CButton *)GetDlgItem(IDC_SATELLITE_RADIO);
|
|
bbox->SetCheck(cc_mode == CC_MODE_SAT);
|
|
|
|
// Draw swatches
|
|
DrawSwatch(IDC_SKY_SWATCH, GR_COLOR_RED(Terrain_sky.sky_color), GR_COLOR_GREEN(Terrain_sky.sky_color),
|
|
GR_COLOR_BLUE(Terrain_sky.sky_color));
|
|
DrawSwatch(IDC_HORIZON_SWATCH, GR_COLOR_RED(Terrain_sky.horizon_color), GR_COLOR_GREEN(Terrain_sky.horizon_color),
|
|
GR_COLOR_BLUE(Terrain_sky.horizon_color));
|
|
DrawSwatch(IDC_FOG_SWATCH, GR_COLOR_RED(Terrain_sky.fog_color), GR_COLOR_GREEN(Terrain_sky.fog_color),
|
|
GR_COLOR_BLUE(Terrain_sky.fog_color));
|
|
|
|
// Draw satellite swatch
|
|
float maxc = std::max(Terrain_sky.satellite_r[Current_satellite], Terrain_sky.satellite_g[Current_satellite]);
|
|
maxc = std::max(Terrain_sky.satellite_b[Current_satellite], maxc);
|
|
|
|
float r, g, b;
|
|
|
|
if (maxc > 1.0) {
|
|
r = Terrain_sky.satellite_r[Current_satellite] / maxc;
|
|
g = Terrain_sky.satellite_g[Current_satellite] / maxc;
|
|
b = Terrain_sky.satellite_b[Current_satellite] / maxc;
|
|
} else {
|
|
r = Terrain_sky.satellite_r[Current_satellite];
|
|
g = Terrain_sky.satellite_g[Current_satellite];
|
|
b = Terrain_sky.satellite_b[Current_satellite];
|
|
}
|
|
|
|
r *= 255.0;
|
|
g *= 255.0;
|
|
b *= 255.0;
|
|
|
|
DrawSwatch(IDC_SATELLITE_SWATCH, r, g, b);
|
|
|
|
if (cc_mode != CC_MODE_SAT) {
|
|
int r, g, b;
|
|
|
|
if (cc_mode == CC_MODE_SKY) {
|
|
r = GR_COLOR_RED(Terrain_sky.sky_color);
|
|
g = GR_COLOR_GREEN(Terrain_sky.sky_color);
|
|
b = GR_COLOR_BLUE(Terrain_sky.sky_color);
|
|
} else if (cc_mode == CC_MODE_HORIZON) {
|
|
r = GR_COLOR_RED(Terrain_sky.horizon_color);
|
|
g = GR_COLOR_GREEN(Terrain_sky.horizon_color);
|
|
b = GR_COLOR_BLUE(Terrain_sky.horizon_color);
|
|
} else {
|
|
r = GR_COLOR_RED(Terrain_sky.fog_color);
|
|
g = GR_COLOR_GREEN(Terrain_sky.fog_color);
|
|
b = GR_COLOR_BLUE(Terrain_sky.fog_color);
|
|
}
|
|
|
|
ebox = (CEdit *)GetDlgItem(IDC_SKY_RED_EDIT);
|
|
sprintf(str, "%d", r);
|
|
ebox->SetWindowText(str);
|
|
|
|
ebox = (CEdit *)GetDlgItem(IDC_SKY_GREEN_EDIT);
|
|
sprintf(str, "%d", g);
|
|
ebox->SetWindowText(str);
|
|
|
|
ebox = (CEdit *)GetDlgItem(IDC_SKY_BLUE_EDIT);
|
|
sprintf(str, "%d", b);
|
|
ebox->SetWindowText(str);
|
|
} else {
|
|
|
|
ebox = (CEdit *)GetDlgItem(IDC_SKY_RED_EDIT);
|
|
sprintf(str, "%f", Terrain_sky.satellite_r[Current_satellite]);
|
|
ebox->SetWindowText(str);
|
|
|
|
ebox = (CEdit *)GetDlgItem(IDC_SKY_GREEN_EDIT);
|
|
sprintf(str, "%f", Terrain_sky.satellite_g[Current_satellite]);
|
|
ebox->SetWindowText(str);
|
|
|
|
ebox = (CEdit *)GetDlgItem(IDC_SKY_BLUE_EDIT);
|
|
sprintf(str, "%f", Terrain_sky.satellite_b[Current_satellite]);
|
|
ebox->SetWindowText(str);
|
|
}
|
|
}
|
|
|
|
void CTerrainDialog::OnTerrpadMoveUp() {
|
|
int i;
|
|
|
|
for (i = 0; i < TERRAIN_DEPTH * TERRAIN_WIDTH; i++) {
|
|
if (TerrainSelected[i]) {
|
|
int cury = Terrain_seg[i].ypos;
|
|
if (cury <= 254) {
|
|
Terrain_seg[i].ypos++;
|
|
Terrain_seg[i].y += (float)(TERRAIN_HEIGHT_INCREMENT);
|
|
TV_changed++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CTerrainDialog::OnTerrpadMoveDown() {
|
|
for (int i = 0; i < TERRAIN_DEPTH * TERRAIN_WIDTH; i++) {
|
|
if (TerrainSelected[i]) {
|
|
int cury = Terrain_seg[i].ypos;
|
|
if (cury > 0) {
|
|
Terrain_seg[i].ypos--;
|
|
Terrain_seg[i].y -= (float)(TERRAIN_HEIGHT_INCREMENT);
|
|
TV_changed++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CTerrainDialog::RunKeypadFunction(int code) {
|
|
switch (code) {
|
|
case VK_ADD:
|
|
OnTerrpadMoveDown();
|
|
break;
|
|
case VK_SUBTRACT:
|
|
OnTerrpadMoveUp();
|
|
break;
|
|
}
|
|
}
|
|
|
|
void CTerrainDialog::OnTerrpadImport() {
|
|
char filename[255];
|
|
|
|
CString filter = "PCX files (*.pcx)|*.pcx||";
|
|
|
|
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.
|
|
LoadPCXTerrain(filename);
|
|
}
|
|
|
|
void CTerrainDialog::OnTerrpadRenormalize() {
|
|
mprintf(0, "Building terrain normals...this might take a couple of seconds.\n");
|
|
|
|
Terrain_checksum = -1;
|
|
BuildMinMaxTerrain();
|
|
BuildTerrainNormals();
|
|
State_changed = 1;
|
|
}
|
|
|
|
void CTerrainDialog::OnTerrpadRaise10() {
|
|
for (int i = 0; i < TERRAIN_DEPTH * TERRAIN_WIDTH; i++) {
|
|
if (TerrainSelected[i]) {
|
|
int cury = Terrain_seg[i].ypos;
|
|
if (cury < 255 - 10) {
|
|
Terrain_seg[i].ypos += 10;
|
|
Terrain_seg[i].y += (float)(10 * (TERRAIN_HEIGHT_INCREMENT));
|
|
TV_changed++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CTerrainDialog::OnTerrpadLower10() {
|
|
|
|
for (int i = 0; i < TERRAIN_DEPTH * TERRAIN_WIDTH; i++) {
|
|
if (TerrainSelected[i]) {
|
|
int cury = Terrain_seg[i].ypos;
|
|
if (cury > 9) {
|
|
Terrain_seg[i].ypos -= 10;
|
|
Terrain_seg[i].y -= (float)(10 * (TERRAIN_HEIGHT_INCREMENT));
|
|
TV_changed++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CTerrainDialog::OnSkyTexture() { TV_changed = 1; }
|
|
|
|
void CTerrainDialog::OnTerrpadSelectNone() {
|
|
for (int i = 0; i < TERRAIN_WIDTH * TERRAIN_DEPTH; i++)
|
|
TerrainSelected[i] = 0;
|
|
Num_terrain_selected = 0;
|
|
World_changed = 1;
|
|
}
|
|
|
|
void CTerrainDialog::OnTerrpadRotTexture() {
|
|
int i;
|
|
uint8_t touched[TERRAIN_TEX_WIDTH * TERRAIN_TEX_DEPTH];
|
|
memset(touched, 0, TERRAIN_TEX_WIDTH * TERRAIN_TEX_DEPTH);
|
|
|
|
for (i = 0; i < TERRAIN_WIDTH * TERRAIN_DEPTH; i++) {
|
|
if (TerrainSelected[i]) {
|
|
if (!touched[Terrain_seg[i].texseg_index]) {
|
|
int val = Terrain_tex_seg[Terrain_seg[i].texseg_index].rotation & 0x0F;
|
|
val++;
|
|
val %= 4;
|
|
Terrain_tex_seg[Terrain_seg[i].texseg_index].rotation &= ~0x0F;
|
|
Terrain_tex_seg[Terrain_seg[i].texseg_index].rotation |= val;
|
|
touched[Terrain_seg[i].texseg_index] = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
World_changed = 1;
|
|
TV_changed = 1;
|
|
}
|
|
|
|
void CTerrainDialog::OnSkyNearer() {
|
|
|
|
if (Terrain_sky.radius > 500) {
|
|
|
|
SetupSky(Terrain_sky.radius - 500, Terrain_sky.flags);
|
|
TV_changed = 1;
|
|
}
|
|
}
|
|
|
|
void CTerrainDialog::OnSkyFarther() {
|
|
SetupSky(Terrain_sky.radius + 500, Terrain_sky.flags);
|
|
TV_changed = 1;
|
|
}
|
|
|
|
void CTerrainDialog::OnStarsCheck() {
|
|
int c = IsDlgButtonChecked(IDC_STARS_CHECK);
|
|
|
|
if (c)
|
|
Terrain_sky.flags |= TF_STARS;
|
|
else
|
|
Terrain_sky.flags &= ~TF_STARS;
|
|
|
|
TV_changed = 1;
|
|
}
|
|
|
|
void CTerrainDialog::OnFastTerrainCheck() {
|
|
int c = IsDlgButtonChecked(IDC_FAST_TERRAIN_CHECK);
|
|
|
|
if (c)
|
|
Fast_terrain = 1;
|
|
else
|
|
Fast_terrain = 0;
|
|
|
|
TV_changed = 1;
|
|
}
|
|
|
|
void CTerrainDialog::OnTerrpadFillArea() {
|
|
int i;
|
|
|
|
for (i = 0; i < TERRAIN_WIDTH * TERRAIN_DEPTH; i++)
|
|
if (TerrainSelected[i])
|
|
Terrain_tex_seg[Terrain_seg[i].texseg_index].tex_index = D3EditState.texdlg_texture;
|
|
|
|
World_changed = 1;
|
|
}
|
|
|
|
void CTerrainDialog::OnTerrpadRedoTopmap() { World_changed = 1; }
|
|
|
|
void CTerrainDialog::OnTerrpadMakeMax() {
|
|
int max_so_far = 0, i;
|
|
|
|
for (i = 0; i < TERRAIN_WIDTH * TERRAIN_DEPTH; i++) {
|
|
if (TerrainSelected[i]) {
|
|
if (Terrain_seg[i].ypos > max_so_far)
|
|
max_so_far = Terrain_seg[i].ypos;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < TERRAIN_WIDTH * TERRAIN_DEPTH; i++) {
|
|
if (TerrainSelected[i]) {
|
|
Terrain_seg[i].ypos = max_so_far;
|
|
Terrain_seg[i].y = max_so_far * (TERRAIN_HEIGHT_INCREMENT);
|
|
}
|
|
}
|
|
|
|
World_changed = 1;
|
|
}
|
|
|
|
void CTerrainDialog::OnTerrpadMakeMin() {
|
|
int min_so_far = 9999, i;
|
|
|
|
for (i = 0; i < TERRAIN_WIDTH * TERRAIN_DEPTH; i++) {
|
|
if (TerrainSelected[i]) {
|
|
if (Terrain_seg[i].ypos < min_so_far)
|
|
min_so_far = Terrain_seg[i].ypos;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < TERRAIN_WIDTH * TERRAIN_DEPTH; i++) {
|
|
if (TerrainSelected[i]) {
|
|
Terrain_seg[i].ypos = min_so_far;
|
|
Terrain_seg[i].y = min_so_far * (TERRAIN_HEIGHT_INCREMENT);
|
|
}
|
|
}
|
|
|
|
World_changed = 1;
|
|
}
|
|
|
|
void CTerrainDialog::OnTerrpadMakeZero() {
|
|
int i;
|
|
|
|
for (i = 0; i < TERRAIN_WIDTH * TERRAIN_DEPTH; i++) {
|
|
if (TerrainSelected[i]) {
|
|
Terrain_seg[i].ypos = 0;
|
|
Terrain_seg[i].y = 0;
|
|
}
|
|
}
|
|
|
|
World_changed = 1;
|
|
}
|
|
|
|
// Makes a pyramid out of the selected region
|
|
void CTerrainDialog::OnTerrpadPyramid() {
|
|
int left = TERRAIN_WIDTH, right = 0;
|
|
int top = TERRAIN_DEPTH, bottom = 0;
|
|
|
|
int i, t, x, y;
|
|
int max_so_far = 0;
|
|
int min_so_far = 999;
|
|
|
|
// First find highest/lowest point
|
|
for (i = 0; i < TERRAIN_WIDTH * TERRAIN_DEPTH; i++) {
|
|
if (TerrainSelected[i]) {
|
|
if (Terrain_seg[i].ypos > max_so_far)
|
|
max_so_far = Terrain_seg[i].ypos;
|
|
if (Terrain_seg[i].ypos < min_so_far)
|
|
min_so_far = Terrain_seg[i].ypos;
|
|
}
|
|
}
|
|
|
|
// Now get dimensions of selection
|
|
for (i = 0; i < TERRAIN_DEPTH * TERRAIN_WIDTH; i++) {
|
|
if (TerrainSelected[i]) {
|
|
x = i % TERRAIN_WIDTH;
|
|
y = i / TERRAIN_WIDTH;
|
|
|
|
if (x > right)
|
|
right = x;
|
|
if (x < left)
|
|
left = x;
|
|
|
|
if (y > bottom)
|
|
bottom = y;
|
|
|
|
if (y < top)
|
|
top = y;
|
|
}
|
|
}
|
|
|
|
int width = (right - left);
|
|
int height = (bottom - top);
|
|
|
|
int hdiff = max_so_far - min_so_far;
|
|
|
|
if (hdiff == 0) {
|
|
MessageBox("The area you selected is flat. Pull a point up to the desired height and then retry this operation.");
|
|
return;
|
|
}
|
|
|
|
fix xstep = IntToFix(hdiff) / (width / 2);
|
|
fix ystep = IntToFix(hdiff) / (height / 2);
|
|
|
|
// upper left
|
|
for (i = 0; i <= (height / 2); i++) {
|
|
for (t = 0; t <= (width / 2); t++) {
|
|
|
|
int xa, ya, a;
|
|
|
|
xa = FixToInt(xstep * t);
|
|
ya = FixToInt(ystep * i);
|
|
|
|
a = std::max(xa, ya);
|
|
|
|
int seg = ((top + i) * TERRAIN_WIDTH) + (t + left);
|
|
|
|
Terrain_seg[seg].ypos = min_so_far + a;
|
|
Terrain_seg[seg].y = (min_so_far + a) * (TERRAIN_HEIGHT_INCREMENT);
|
|
}
|
|
}
|
|
|
|
// upper right
|
|
for (i = 0; i <= (height / 2); i++) {
|
|
for (t = 0; t <= (width / 2); t++) {
|
|
|
|
int xa, ya, a;
|
|
|
|
xa = FixToInt(xstep * t);
|
|
ya = FixToInt(ystep * i);
|
|
|
|
a = std::max(xa, ya);
|
|
|
|
int seg = ((top + i) * TERRAIN_WIDTH) + (right - t);
|
|
|
|
Terrain_seg[seg].ypos = min_so_far + a;
|
|
Terrain_seg[seg].y = (min_so_far + a) * (TERRAIN_HEIGHT_INCREMENT);
|
|
}
|
|
}
|
|
|
|
// lower left
|
|
for (i = 0; i <= (height / 2); i++) {
|
|
for (t = 0; t <= (width / 2); t++) {
|
|
|
|
int xa, ya, a;
|
|
|
|
xa = FixToInt(xstep * t);
|
|
ya = FixToInt(ystep * i);
|
|
|
|
a = std::max(xa, ya);
|
|
|
|
int seg = ((bottom - i) * TERRAIN_WIDTH) + (left + t);
|
|
|
|
Terrain_seg[seg].ypos = min_so_far + a;
|
|
Terrain_seg[seg].y = (min_so_far + a) * (TERRAIN_HEIGHT_INCREMENT);
|
|
}
|
|
}
|
|
|
|
// lower right
|
|
for (i = 0; i <= (height / 2); i++) {
|
|
for (t = 0; t <= (width / 2); t++) {
|
|
|
|
int xa, ya, a;
|
|
|
|
xa = FixToInt(xstep * t);
|
|
ya = FixToInt(ystep * i);
|
|
|
|
a = std::max(xa, ya);
|
|
|
|
int seg = ((bottom - i) * TERRAIN_WIDTH) + (right - t);
|
|
|
|
Terrain_seg[seg].ypos = min_so_far + a;
|
|
Terrain_seg[seg].y = (min_so_far + a) * (TERRAIN_HEIGHT_INCREMENT);
|
|
}
|
|
}
|
|
|
|
World_changed = 1;
|
|
}
|
|
|
|
void CTerrainDialog::OnTerrpadHill() {}
|
|
|
|
void CTerrainDialog::OnTerrpadPancakes() {
|
|
int left = TERRAIN_WIDTH, right = 0;
|
|
int top = TERRAIN_DEPTH, bottom = 0;
|
|
|
|
int i, t, x, y;
|
|
int max_so_far = 0;
|
|
int min_so_far = 999;
|
|
|
|
// First find highest/lowest point
|
|
for (i = 0; i < TERRAIN_WIDTH * TERRAIN_DEPTH; i++) {
|
|
if (TerrainSelected[i]) {
|
|
if (Terrain_seg[i].ypos > max_so_far)
|
|
max_so_far = Terrain_seg[i].ypos;
|
|
if (Terrain_seg[i].ypos < min_so_far)
|
|
min_so_far = Terrain_seg[i].ypos;
|
|
}
|
|
}
|
|
|
|
// Now get dimensions of selection
|
|
for (i = 0; i < TERRAIN_DEPTH * TERRAIN_WIDTH; i++) {
|
|
if (TerrainSelected[i]) {
|
|
x = i % TERRAIN_WIDTH;
|
|
y = i / TERRAIN_WIDTH;
|
|
|
|
if (x > right)
|
|
right = x;
|
|
if (x < left)
|
|
left = x;
|
|
|
|
if (y > bottom)
|
|
bottom = y;
|
|
|
|
if (y < top)
|
|
top = y;
|
|
}
|
|
}
|
|
|
|
int width = (right - left);
|
|
int height = (bottom - top);
|
|
|
|
int hdiff = max_so_far - min_so_far;
|
|
|
|
if (hdiff == 0) {
|
|
MessageBox("The area you selected is flat. Pull a point up to the desired height and then retry this operation.");
|
|
return;
|
|
}
|
|
|
|
fix xstep = IntToFix(hdiff) / (width / 2);
|
|
fix ystep = IntToFix(hdiff) / (height / 2);
|
|
|
|
// upper left
|
|
for (i = 0; i <= (height / 2); i++) {
|
|
for (t = 0; t <= (width / 2); t++) {
|
|
|
|
int xa, ya, a;
|
|
|
|
xa = FixToInt(xstep * t);
|
|
ya = FixToInt(ystep * i);
|
|
|
|
a = std::max(xa, ya);
|
|
|
|
int seg = ((top + i) * TERRAIN_WIDTH) + (t + left);
|
|
|
|
Terrain_seg[seg].ypos = min_so_far + a;
|
|
Terrain_seg[seg].y = (min_so_far + a) * (TERRAIN_HEIGHT_INCREMENT);
|
|
}
|
|
}
|
|
|
|
// upper right
|
|
for (i = 0; i <= (height / 2); i++) {
|
|
for (t = 0; t <= (width / 2); t++) {
|
|
|
|
int xa, ya, a;
|
|
|
|
xa = FixToInt(xstep * t);
|
|
ya = FixToInt(ystep * i);
|
|
|
|
a = std::max(xa, ya);
|
|
|
|
int seg = ((top + i) * TERRAIN_WIDTH) + (right - t);
|
|
|
|
Terrain_seg[seg].ypos = min_so_far + a;
|
|
Terrain_seg[seg].y = (min_so_far + a) * (TERRAIN_HEIGHT_INCREMENT);
|
|
}
|
|
}
|
|
|
|
// lower left
|
|
for (i = 0; i <= (height / 2); i++) {
|
|
for (t = 0; t <= (width / 2); t++) {
|
|
|
|
int xa, ya, a;
|
|
|
|
xa = FixToInt(xstep * t);
|
|
ya = FixToInt(ystep * i);
|
|
|
|
a = std::max(xa, ya);
|
|
|
|
int seg = ((bottom - i) * TERRAIN_WIDTH) + (left + t);
|
|
|
|
Terrain_seg[seg].ypos = min_so_far + a;
|
|
Terrain_seg[seg].y = (min_so_far + a) * (TERRAIN_HEIGHT_INCREMENT);
|
|
}
|
|
}
|
|
|
|
// lower right
|
|
for (i = 0; i <= (height / 2); i++) {
|
|
for (t = 0; t <= (width / 2); t++) {
|
|
|
|
int xa, ya, a;
|
|
|
|
xa = FixToInt(xstep * t);
|
|
ya = FixToInt(ystep * i);
|
|
|
|
a = std::max(xa, ya);
|
|
|
|
int seg = ((bottom - i) * TERRAIN_WIDTH) + (right - t);
|
|
|
|
Terrain_seg[seg].ypos = min_so_far + a;
|
|
Terrain_seg[seg].y = (min_so_far + a) * (TERRAIN_HEIGHT_INCREMENT);
|
|
}
|
|
}
|
|
|
|
World_changed = 1;
|
|
}
|
|
|
|
void CTerrainDialog::OnTerrMoveMoon() {
|
|
int n = Current_satellite;
|
|
|
|
Terrain_sky.satellite_size[n] *= 1.1f;
|
|
|
|
TV_changed = 1;
|
|
}
|
|
|
|
void CTerrainDialog::OnTerrRandomizeSky() {
|
|
SetupSky(Terrain_sky.radius, Terrain_sky.flags, 1);
|
|
TV_changed = 1;
|
|
}
|
|
|
|
void CTerrainDialog::OnPaint() {
|
|
CPaintDC dc(this); // device context for painting
|
|
|
|
UpdateDialog();
|
|
|
|
// Do not call CDialog::OnPaint() for painting messages
|
|
}
|
|
|
|
void CTerrainDialog::OnTerrMoreMoons() {
|
|
if (Terrain_sky.num_satellites < 5)
|
|
Terrain_sky.num_satellites++;
|
|
|
|
TV_changed = 1;
|
|
|
|
UpdateDialog();
|
|
}
|
|
|
|
void CTerrainDialog::OnTerrLessMoons() {
|
|
if (Terrain_sky.num_satellites > 0)
|
|
Terrain_sky.num_satellites--;
|
|
|
|
TV_changed = 1;
|
|
|
|
UpdateDialog();
|
|
}
|
|
|
|
void CTerrainDialog::OnTerrNextMoon() {
|
|
Current_satellite++;
|
|
|
|
Current_satellite %= 5;
|
|
|
|
UpdateDialog();
|
|
}
|
|
|
|
void CTerrainDialog::OnTerrPrevMoon() {
|
|
Current_satellite--;
|
|
if (Current_satellite < 0)
|
|
Current_satellite = 4;
|
|
|
|
UpdateDialog();
|
|
}
|
|
|
|
void CTerrainDialog::OnShowTerrain() {
|
|
int c = IsDlgButtonChecked(IDC_SHOW_TERRAIN);
|
|
|
|
D3EditState.terrain_dots = (c != 0);
|
|
|
|
State_changed = 1;
|
|
}
|
|
|
|
void CTerrainDialog::OnFlatShadeTerrainCheck() {
|
|
int c = IsDlgButtonChecked(IDC_FLAT_SHADE_TERRAIN_CHECK);
|
|
|
|
D3EditState.terrain_flat_shade = (c != 0);
|
|
|
|
if (c) {
|
|
Terrain_texture_distance = 0;
|
|
Detail_settings.Terrain_render_distance = DEFAULT_VISIBLE_TERRAIN_DISTANCE * 2;
|
|
} else {
|
|
Terrain_texture_distance = 9999999;
|
|
Detail_settings.Terrain_render_distance = DEFAULT_VISIBLE_TERRAIN_DISTANCE;
|
|
}
|
|
|
|
State_changed = 1;
|
|
}
|
|
|
|
BOOL CTerrainDialog::OnHelpInfo(HELPINFO *pHelpInfo) {
|
|
|
|
WinHelp(HID_TERRAINTAB, HELP_CONTEXT);
|
|
return TRUE;
|
|
// return CDialog::OnHelpInfo(pHelpInfo);
|
|
}
|
|
|
|
void CTerrainDialog::OnTerrSelectAll() {
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < TERRAIN_WIDTH * TERRAIN_DEPTH; i++)
|
|
TerrainSelected[i] = 1;
|
|
|
|
Num_terrain_selected = TERRAIN_WIDTH * TERRAIN_DEPTH;
|
|
World_changed = 1;
|
|
}
|
|
|
|
void CTerrainDialog::OnTerrain2d() {
|
|
int c = IsDlgButtonChecked(IDC_TERRAIN_2D);
|
|
|
|
if (c) {
|
|
Flat_terrain = 1;
|
|
} else {
|
|
Flat_terrain = 0;
|
|
}
|
|
|
|
State_changed = 1;
|
|
}
|
|
|
|
void CTerrainDialog::SetCurrentMoon(int n) {
|
|
Current_satellite = n;
|
|
UpdateDialog();
|
|
}
|
|
|
|
void CTerrainDialog::OnTextureSky() {
|
|
int c = IsDlgButtonChecked(IDC_TEXTURE_SKY);
|
|
Terrain_sky.textured = c;
|
|
|
|
World_changed = 1;
|
|
}
|
|
|
|
void CTerrainDialog::OnKillfocusSkyRedEdit() {
|
|
CEdit *ebox;
|
|
char str[20];
|
|
int r, g, b, nr;
|
|
float fv;
|
|
|
|
if (cc_mode == CC_MODE_SKY) {
|
|
r = GR_COLOR_RED(Terrain_sky.sky_color);
|
|
g = GR_COLOR_GREEN(Terrain_sky.sky_color);
|
|
b = GR_COLOR_BLUE(Terrain_sky.sky_color);
|
|
} else if (cc_mode == CC_MODE_HORIZON) {
|
|
r = GR_COLOR_RED(Terrain_sky.horizon_color);
|
|
g = GR_COLOR_GREEN(Terrain_sky.horizon_color);
|
|
b = GR_COLOR_BLUE(Terrain_sky.horizon_color);
|
|
} else {
|
|
r = GR_COLOR_RED(Terrain_sky.fog_color);
|
|
g = GR_COLOR_GREEN(Terrain_sky.fog_color);
|
|
b = GR_COLOR_BLUE(Terrain_sky.fog_color);
|
|
}
|
|
|
|
ebox = (CEdit *)GetDlgItem(IDC_SKY_RED_EDIT);
|
|
ebox->GetWindowText(str, 20);
|
|
|
|
if (cc_mode != CC_MODE_SAT) {
|
|
nr = atoi(str);
|
|
if (nr < 0)
|
|
nr = 0;
|
|
if (nr > 255)
|
|
nr = 255;
|
|
|
|
if (cc_mode == CC_MODE_SKY)
|
|
Terrain_sky.sky_color = GR_RGB(nr, g, b);
|
|
else if (cc_mode == CC_MODE_HORIZON)
|
|
Terrain_sky.horizon_color = GR_RGB(nr, g, b);
|
|
else
|
|
Terrain_sky.fog_color = GR_RGB(nr, g, b);
|
|
} else {
|
|
fv = atof(str);
|
|
if (fv < 0)
|
|
fv = 0;
|
|
|
|
Terrain_sky.satellite_r[Current_satellite] = fv;
|
|
}
|
|
|
|
World_changed = 1;
|
|
UpdateDialog();
|
|
}
|
|
|
|
void CTerrainDialog::OnKillfocusSkyGreenEdit() {
|
|
CEdit *ebox;
|
|
char str[20];
|
|
int r, g, b, nr;
|
|
float fv;
|
|
|
|
if (cc_mode == CC_MODE_SKY) {
|
|
r = GR_COLOR_RED(Terrain_sky.sky_color);
|
|
g = GR_COLOR_GREEN(Terrain_sky.sky_color);
|
|
b = GR_COLOR_BLUE(Terrain_sky.sky_color);
|
|
} else if (cc_mode == CC_MODE_HORIZON) {
|
|
r = GR_COLOR_RED(Terrain_sky.horizon_color);
|
|
g = GR_COLOR_GREEN(Terrain_sky.horizon_color);
|
|
b = GR_COLOR_BLUE(Terrain_sky.horizon_color);
|
|
} else {
|
|
r = GR_COLOR_RED(Terrain_sky.fog_color);
|
|
g = GR_COLOR_GREEN(Terrain_sky.fog_color);
|
|
b = GR_COLOR_BLUE(Terrain_sky.fog_color);
|
|
}
|
|
|
|
ebox = (CEdit *)GetDlgItem(IDC_SKY_GREEN_EDIT);
|
|
ebox->GetWindowText(str, 20);
|
|
|
|
if (cc_mode != CC_MODE_SAT) {
|
|
nr = atoi(str);
|
|
if (nr < 0)
|
|
nr = 0;
|
|
if (nr > 255)
|
|
nr = 255;
|
|
|
|
if (cc_mode == CC_MODE_SKY)
|
|
Terrain_sky.sky_color = GR_RGB(r, nr, b);
|
|
else if (cc_mode == CC_MODE_HORIZON)
|
|
Terrain_sky.horizon_color = GR_RGB(r, nr, b);
|
|
else
|
|
Terrain_sky.fog_color = GR_RGB(r, nr, b);
|
|
} else {
|
|
fv = atof(str);
|
|
if (fv < 0)
|
|
fv = 0;
|
|
|
|
Terrain_sky.satellite_g[Current_satellite] = fv;
|
|
}
|
|
|
|
World_changed = 1;
|
|
UpdateDialog();
|
|
}
|
|
|
|
void CTerrainDialog::OnKillfocusSkyBlueEdit() {
|
|
CEdit *ebox;
|
|
char str[20];
|
|
int r, g, b, nr;
|
|
float fv;
|
|
|
|
if (cc_mode == CC_MODE_SKY) {
|
|
r = GR_COLOR_RED(Terrain_sky.sky_color);
|
|
g = GR_COLOR_GREEN(Terrain_sky.sky_color);
|
|
b = GR_COLOR_BLUE(Terrain_sky.sky_color);
|
|
} else if (cc_mode == CC_MODE_HORIZON) {
|
|
r = GR_COLOR_RED(Terrain_sky.horizon_color);
|
|
g = GR_COLOR_GREEN(Terrain_sky.horizon_color);
|
|
b = GR_COLOR_BLUE(Terrain_sky.horizon_color);
|
|
} else {
|
|
r = GR_COLOR_RED(Terrain_sky.fog_color);
|
|
g = GR_COLOR_GREEN(Terrain_sky.fog_color);
|
|
b = GR_COLOR_BLUE(Terrain_sky.fog_color);
|
|
}
|
|
|
|
ebox = (CEdit *)GetDlgItem(IDC_SKY_BLUE_EDIT);
|
|
ebox->GetWindowText(str, 20);
|
|
|
|
if (cc_mode != CC_MODE_SAT) {
|
|
nr = atoi(str);
|
|
if (nr < 0)
|
|
nr = 0;
|
|
if (nr > 255)
|
|
nr = 255;
|
|
|
|
if (cc_mode == CC_MODE_SKY)
|
|
Terrain_sky.sky_color = GR_RGB(r, g, nr);
|
|
else if (cc_mode == CC_MODE_HORIZON)
|
|
Terrain_sky.horizon_color = GR_RGB(r, g, nr);
|
|
else
|
|
Terrain_sky.fog_color = GR_RGB(r, g, nr);
|
|
} else {
|
|
fv = atof(str);
|
|
if (fv < 0)
|
|
fv = 0;
|
|
|
|
Terrain_sky.satellite_b[Current_satellite] = fv;
|
|
}
|
|
|
|
World_changed = 1;
|
|
UpdateDialog();
|
|
}
|
|
|
|
void CTerrainDialog::OnNoLodEngine() {
|
|
|
|
int c = IsDlgButtonChecked(IDC_NO_LOD_ENGINE);
|
|
|
|
Editor_LOD_engine_off = c;
|
|
|
|
State_changed = 1;
|
|
}
|
|
|
|
void CTerrainDialog::OnKillfocusFogDistanceEdit() {
|
|
CEdit *ebox;
|
|
char str[20];
|
|
float predist;
|
|
float dist;
|
|
|
|
ebox = (CEdit *)GetDlgItem(IDC_FOG_DISTANCE_EDIT);
|
|
ebox->GetWindowText(str, 20);
|
|
|
|
predist = atof(str);
|
|
|
|
if (predist < 20)
|
|
predist = 20;
|
|
if (predist > 200)
|
|
predist = 200;
|
|
|
|
dist = predist * TERRAIN_SIZE;
|
|
|
|
Detail_settings.Terrain_render_distance = dist;
|
|
|
|
World_changed = 1;
|
|
UpdateDialog();
|
|
}
|
|
|
|
void CTerrainDialog::OnKillfocusPixelErrorEdit() {
|
|
CEdit *ebox;
|
|
char str[20];
|
|
float err;
|
|
|
|
ebox = (CEdit *)GetDlgItem(IDC_PIXEL_ERROR_EDIT);
|
|
ebox->GetWindowText(str, 20);
|
|
|
|
err = atof(str);
|
|
if (err < 0)
|
|
err = 0;
|
|
if (err > 64)
|
|
err = 64;
|
|
|
|
Detail_settings.Pixel_error = err;
|
|
|
|
World_changed = 1;
|
|
UpdateDialog();
|
|
}
|
|
|
|
void CTerrainDialog::OnTerrpadSelectrange() {
|
|
SelectRangeDialog dlg;
|
|
|
|
theApp.pause();
|
|
dlg.DoModal();
|
|
World_changed = 1;
|
|
theApp.resume();
|
|
}
|
|
|
|
// These functions allow the terrain keypad to scroll!!
|
|
|
|
void CTerrainDialog::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar *pScrollBar) {
|
|
// TODO: Add your message handler code here and/or call default
|
|
|
|
CKeypadDialog::OnVScroll(nSBCode, nPos, pScrollBar);
|
|
}
|
|
|
|
void CTerrainDialog::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar *pScrollBar) {
|
|
// TODO: Add your message handler code here and/or call default
|
|
|
|
CKeypadDialog::OnHScroll(nSBCode, nPos, pScrollBar);
|
|
}
|
|
|
|
void CTerrainDialog::OnSkyRadio() {
|
|
|
|
cc_mode = CC_MODE_SKY;
|
|
UpdateDialog();
|
|
}
|
|
|
|
void CTerrainDialog::OnHorizonRadio() {
|
|
|
|
cc_mode = CC_MODE_HORIZON;
|
|
UpdateDialog();
|
|
}
|
|
|
|
void CTerrainDialog::OnFogRadio() {
|
|
cc_mode = CC_MODE_FOG;
|
|
UpdateDialog();
|
|
}
|
|
|
|
void CTerrainDialog::OnToggleVisibility() {
|
|
|
|
for (int i = 0; i < TERRAIN_WIDTH * TERRAIN_DEPTH; i++) {
|
|
if (TerrainSelected[i]) {
|
|
int c = Terrain_seg[i].flags & TF_INVISIBLE;
|
|
|
|
if (c)
|
|
Terrain_seg[i].flags &= ~TF_INVISIBLE;
|
|
else
|
|
Terrain_seg[i].flags |= TF_INVISIBLE;
|
|
|
|
World_changed = 1;
|
|
}
|
|
}
|
|
|
|
if (World_changed)
|
|
GenerateLODDeltas();
|
|
}
|
|
|
|
void CTerrainDialog::OnShowInvisible() {
|
|
int c = IsDlgButtonChecked(IDC_SHOW_INVISIBLE);
|
|
|
|
Show_invisible_terrain = c;
|
|
|
|
State_changed = 1;
|
|
}
|
|
|
|
void CTerrainDialog::OnTerrMoveMoonAway() {
|
|
int n = Current_satellite;
|
|
|
|
Terrain_sky.satellite_size[n] *= .9f;
|
|
|
|
TV_changed = 1;
|
|
}
|
|
|
|
void CTerrainDialog::MoveSat(int pitch, int heading) {
|
|
int n = Current_satellite;
|
|
matrix rot_matrix, orient;
|
|
vm_AnglesToMatrix(&rot_matrix, pitch, heading, 0); // move up a little
|
|
|
|
orient = rot_matrix;
|
|
|
|
vector sat_vec = Terrain_sky.satellite_vectors[n] - Viewer_object->pos;
|
|
float mag = vm_GetMagnitude(&sat_vec);
|
|
vector rot_vec;
|
|
|
|
vm_NormalizeVector(&sat_vec);
|
|
vm_MatrixMulVector(&rot_vec, &sat_vec, &orient);
|
|
|
|
Terrain_sky.satellite_vectors[n] = Viewer_object->pos + (rot_vec * mag);
|
|
}
|
|
|
|
void CTerrainDialog::OnMoveSatUp() {
|
|
MoveSat(1500, 0);
|
|
TV_changed = 1;
|
|
}
|
|
|
|
void CTerrainDialog::OnMoveSatDown() {
|
|
MoveSat(64000, 0);
|
|
TV_changed = 1;
|
|
}
|
|
|
|
void CTerrainDialog::OnMoveSatLeft() {
|
|
MoveSat(0, 64000);
|
|
TV_changed = 1;
|
|
}
|
|
|
|
void CTerrainDialog::OnMoveSatRight() {
|
|
MoveSat(0, 1500);
|
|
TV_changed = 1;
|
|
}
|
|
|
|
void CTerrainDialog::OnSatelliteCheck() {
|
|
int c = IsDlgButtonChecked(IDC_SATELLITE_CHECK);
|
|
|
|
if (c)
|
|
Terrain_sky.flags |= TF_SATELLITES;
|
|
else
|
|
Terrain_sky.flags &= ~TF_SATELLITES;
|
|
|
|
TV_changed = 1;
|
|
}
|
|
|
|
void CTerrainDialog::OnSmoothTerrain() {
|
|
uint8_t *src_data;
|
|
int y, x;
|
|
|
|
if (Num_terrain_selected == 0) {
|
|
OutrageMessageBox("This operation works on selected cells. You have no cells selected!");
|
|
return;
|
|
}
|
|
|
|
if ((MessageBox("Are you sure you wish to smooth the terrain? This operation cannot be undone.", "Question",
|
|
MB_YESNO)) == IDNO)
|
|
return;
|
|
|
|
src_data = (uint8_t *)mem_malloc(TERRAIN_WIDTH * TERRAIN_DEPTH);
|
|
ASSERT(src_data); // Ran out of memory!
|
|
|
|
for (int i = 0; i < TERRAIN_WIDTH * TERRAIN_DEPTH; i++)
|
|
src_data[i] = Terrain_seg[i].ypos;
|
|
|
|
int w = TERRAIN_WIDTH;
|
|
int h = TERRAIN_DEPTH;
|
|
|
|
for (y = 0; y < h; y++) {
|
|
for (x = 0; x < w; x++) {
|
|
if (!TerrainSelected[y * w + x])
|
|
continue;
|
|
|
|
int total = 0;
|
|
int num = 0;
|
|
|
|
total += src_data[y * w + x];
|
|
num++;
|
|
|
|
// Left edge
|
|
if (x != 0) {
|
|
|
|
total += src_data[y * w + (x - 1)];
|
|
num++;
|
|
|
|
if (y != 0) {
|
|
total += src_data[(y - 1) * w + (x - 1)];
|
|
num++;
|
|
}
|
|
|
|
if (y != h - 1) {
|
|
total += src_data[(y + 1) * w + (x - 1)];
|
|
num++;
|
|
}
|
|
}
|
|
|
|
// Right edge
|
|
if (x != (w - 1)) {
|
|
total += src_data[(y)*w + (x + 1)];
|
|
num++;
|
|
|
|
if (y != 0) {
|
|
total += src_data[(y - 1) * w + (x + 1)];
|
|
num++;
|
|
}
|
|
|
|
if (y != h - 1) {
|
|
total += src_data[(y + 1) * w + (x + 1)];
|
|
num++;
|
|
}
|
|
}
|
|
|
|
// Center
|
|
if (y != 0) {
|
|
total += src_data[(y - 1) * w + (x)];
|
|
num++;
|
|
}
|
|
|
|
if (y != h - 1) {
|
|
total += src_data[(y + 1) * w + (x)];
|
|
num++;
|
|
}
|
|
|
|
if (num > 0) {
|
|
total /= num;
|
|
Terrain_seg[y * w + x].ypos = total;
|
|
}
|
|
}
|
|
}
|
|
|
|
mem_free(src_data);
|
|
BuildMinMaxTerrain();
|
|
OutrageMessageBox("Terrain smoothed!");
|
|
World_changed = 1;
|
|
}
|
|
|
|
void CTerrainDialog::OnUseFog() {
|
|
int c = IsDlgButtonChecked(IDC_USE_FOG);
|
|
|
|
if (c)
|
|
Terrain_sky.flags |= TF_FOG;
|
|
else
|
|
Terrain_sky.flags &= ~TF_FOG;
|
|
|
|
World_changed = 1;
|
|
}
|
|
|
|
void CTerrainDialog::OnUseHalo() {
|
|
int n = Current_satellite;
|
|
int c = IsDlgButtonChecked(IDC_USE_HALO);
|
|
|
|
if (c)
|
|
Terrain_sky.satellite_flags[n] |= TSF_HALO;
|
|
else
|
|
Terrain_sky.satellite_flags[n] &= ~TSF_HALO;
|
|
|
|
World_changed = 1;
|
|
}
|
|
|
|
void CTerrainDialog::OnUseAtmosphere() {
|
|
int n = Current_satellite;
|
|
int c = IsDlgButtonChecked(IDC_USE_ATMOSPHERE);
|
|
|
|
if (c)
|
|
Terrain_sky.satellite_flags[n] |= TSF_ATMOSPHERE;
|
|
else
|
|
Terrain_sky.satellite_flags[n] &= ~TSF_ATMOSPHERE;
|
|
|
|
World_changed = 1;
|
|
}
|
|
|
|
#include "gamepath.h"
|
|
#include "EditLineDialog.h"
|
|
|
|
void CTerrainDialog::OnDropTerrain() {
|
|
int desired_height, lowest_height, highest_height, delta_height;
|
|
int x, y;
|
|
|
|
// Find lowest & highest terrain values
|
|
for (x = 0, lowest_height = INT_MAX, highest_height = 0; x < TERRAIN_WIDTH; x++)
|
|
for (y = 0; y < TERRAIN_DEPTH; y++) {
|
|
if (Terrain_seg[x * TERRAIN_WIDTH + y].ypos < lowest_height)
|
|
lowest_height = Terrain_seg[x * TERRAIN_WIDTH + y].ypos;
|
|
if (Terrain_seg[x * TERRAIN_WIDTH + y].ypos > highest_height)
|
|
highest_height = Terrain_seg[x * TERRAIN_WIDTH + y].ypos;
|
|
}
|
|
|
|
// Get desired terrain level
|
|
get_height:;
|
|
if (!InputNumber(&desired_height, "Raise/Lower Terrain", "Enter the desired height for the lowest terrain point:"))
|
|
return;
|
|
|
|
// Check valid values
|
|
if ((desired_height < 0) || (desired_height > 255)) {
|
|
OutrageMessageBox("Invalid value: the height must be between 0 and 255, inclusive.");
|
|
goto get_height;
|
|
}
|
|
if (((highest_height - lowest_height) + desired_height) > 255) {
|
|
OutrageMessageBox("The delta height of the terrain is %d, so you cannot set the lowest point above %d.",
|
|
highest_height - lowest_height, 255 - (highest_height - lowest_height));
|
|
goto get_height;
|
|
}
|
|
|
|
// Compute delta
|
|
delta_height = desired_height - lowest_height;
|
|
|
|
// Now lower the terrain
|
|
for (x = 0; x < TERRAIN_WIDTH; x++)
|
|
for (y = 0; y < TERRAIN_DEPTH; y++)
|
|
Terrain_seg[x * TERRAIN_WIDTH + y].ypos += delta_height;
|
|
|
|
// Update stuff
|
|
BuildMinMaxTerrain();
|
|
|
|
// How much we move by
|
|
float delta_y = delta_height * TERRAIN_HEIGHT_INCREMENT;
|
|
|
|
int r, v, o, p, n;
|
|
room *rp;
|
|
|
|
// Drop all the rooms
|
|
for (r = 0, rp = Rooms; r <= Highest_room_index; r++, rp++)
|
|
if (rp->used)
|
|
for (v = 0; v < rp->num_verts; v++)
|
|
rp->verts[v].y += delta_y;
|
|
|
|
// Drop all the objects
|
|
for (o = 0; o <= Highest_object_index; o++)
|
|
if (Objects[o].type != OBJ_NONE) {
|
|
vector new_pos = Objects[o].pos;
|
|
new_pos.y += delta_y;
|
|
ObjSetPos(&Objects[o], &new_pos, Objects[o].roomnum, NULL, false);
|
|
}
|
|
|
|
// Drop all the paths
|
|
for (p = 0; p < Num_game_paths; p++)
|
|
for (n = 0; n < GamePaths[p].num_nodes; n++)
|
|
GamePaths[p].pathnodes[n].pos.y += delta_y;
|
|
|
|
// Done
|
|
EditorStatus("Terrain moved by by %d to %d", delta_height, desired_height);
|
|
World_changed = 1;
|
|
}
|
|
|
|
void CTerrainDialog::OnSaveAsPcx() {
|
|
|
|
char filename[255];
|
|
|
|
CString filter = "PCX files (*.pcx)|*.pcx||";
|
|
|
|
if (!SaveFileDialog(this, (LPCSTR)filter, filename, Current_bitmap_dir, sizeof(Current_bitmap_dir)))
|
|
return;
|
|
|
|
CFILE *outfile;
|
|
|
|
outfile = (CFILE *)cfopen(filename, "wb");
|
|
if (!outfile) {
|
|
OutrageMessageBox("Couldn't open that filename to save to!");
|
|
return;
|
|
}
|
|
|
|
// Header info
|
|
cf_WriteByte(outfile, 10);
|
|
cf_WriteByte(outfile, 5);
|
|
cf_WriteByte(outfile, 1);
|
|
cf_WriteByte(outfile, 8);
|
|
|
|
// Dimensions of image
|
|
cf_WriteShort(outfile, 0);
|
|
cf_WriteShort(outfile, 0);
|
|
cf_WriteShort(outfile, 255);
|
|
cf_WriteShort(outfile, 255);
|
|
|
|
// Display adapter dimensions (bash to 256)
|
|
cf_WriteShort(outfile, 256);
|
|
cf_WriteShort(outfile, 256);
|
|
|
|
for (int i = 0; i < 48; i++)
|
|
cf_WriteByte(outfile, 0);
|
|
|
|
cf_WriteByte(outfile, 0);
|
|
cf_WriteByte(outfile, 1);
|
|
cf_WriteShort(outfile, 256);
|
|
cf_WriteShort(outfile, 2);
|
|
|
|
for (int i = 0; i < 58; i++)
|
|
cf_WriteByte(outfile, 0);
|
|
|
|
for (int i = 0; i < TERRAIN_DEPTH; i++) {
|
|
for (int t = 0; t < TERRAIN_WIDTH; t++) {
|
|
uint8_t val = Terrain_seg[(((TERRAIN_DEPTH - 1) - i) * TERRAIN_WIDTH) + t].ypos;
|
|
uint8_t runlen = 0xc1;
|
|
|
|
cf_WriteByte(outfile, runlen);
|
|
cf_WriteByte(outfile, val);
|
|
}
|
|
}
|
|
|
|
cf_WriteByte(outfile, 12);
|
|
for (int i = 0; i < 256; i++) {
|
|
cf_WriteByte(outfile, i);
|
|
cf_WriteByte(outfile, i);
|
|
cf_WriteByte(outfile, i);
|
|
}
|
|
|
|
cfclose(outfile);
|
|
OutrageMessageBox("PCX exported!\n");
|
|
}
|
|
|
|
void CTerrainDialog::OnNoExtRoomsObjs() {
|
|
if (IsDlgButtonChecked(IDC_NO_EXT_ROOMS_OBJS)) {
|
|
Terrain_render_ext_room_objs = false;
|
|
} else {
|
|
Terrain_render_ext_room_objs = true;
|
|
}
|
|
}
|
|
|
|
#define FILL_COLOR 1
|
|
static uint8_t *Terrain_heights, *Terrain_fill;
|
|
|
|
#define PUSH_FILL(x) \
|
|
{ \
|
|
fill_stack[stack_count] = x; \
|
|
Terrain_fill[x] = 1; \
|
|
stack_count++; \
|
|
ASSERT(stack_count < 65536); \
|
|
}
|
|
#define POP_FILL() \
|
|
{ \
|
|
stack_count--; \
|
|
cell = fill_stack[stack_count]; \
|
|
}
|
|
|
|
void FillTerrainHeights(int cell) {
|
|
terrain_segment *tseg = &Terrain_seg[cell];
|
|
uint16_t fill_stack[65536];
|
|
int stack_count = 0;
|
|
|
|
ASSERT(cell >= 0 && cell < TERRAIN_WIDTH * TERRAIN_DEPTH);
|
|
|
|
memset(Terrain_fill, 0, TERRAIN_WIDTH * TERRAIN_DEPTH);
|
|
|
|
PUSH_FILL(cell);
|
|
|
|
while (stack_count > 0) {
|
|
POP_FILL();
|
|
if (Terrain_heights[cell] == 0) {
|
|
int x = cell % 256;
|
|
int z = cell / 256;
|
|
|
|
Terrain_heights[cell] = FILL_COLOR;
|
|
|
|
if (x != 0 && Terrain_fill[cell - 1] == 0)
|
|
PUSH_FILL(cell - 1);
|
|
if (x != TERRAIN_WIDTH - 1 && Terrain_fill[cell + 1] == 0)
|
|
PUSH_FILL(cell + 1);
|
|
if (z != 0 && Terrain_fill[cell - TERRAIN_WIDTH] == 0)
|
|
PUSH_FILL(cell - TERRAIN_WIDTH);
|
|
if (z != TERRAIN_DEPTH - 1 && Terrain_fill[cell + TERRAIN_WIDTH] == 0)
|
|
PUSH_FILL(cell + TERRAIN_DEPTH);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CTerrainDialog::OnTerrainOcclusion() {
|
|
// TODO: Add your control notification handler code here
|
|
if (Terrain_occlusion_checksum == (Terrain_checksum + 1)) {
|
|
OutrageMessageBox("The occlusion map is already calculated for this terrain.");
|
|
// return;
|
|
}
|
|
|
|
if ((MessageBox("Are you sure you wish to calculate terrain occlusion?", "Question", MB_YESNO)) == IDNO)
|
|
return;
|
|
|
|
mprintf(0, "Now doing occlusion tests...\n");
|
|
|
|
int count = 0;
|
|
int occlude_count = 0;
|
|
uint8_t *touch_buffer[256];
|
|
|
|
for (int i = 0; i < 256; i++) {
|
|
memset(Terrain_occlusion_map[i], 0, 32);
|
|
touch_buffer[i] = mem_rmalloc<uint8_t>(256);
|
|
ASSERT(touch_buffer[i]);
|
|
memset(touch_buffer[i], 255, 256);
|
|
}
|
|
|
|
uint8_t *save_buffer;
|
|
|
|
// Build a height map so we can flood fill
|
|
Terrain_heights = (uint8_t *)mem_malloc(TERRAIN_WIDTH * TERRAIN_DEPTH);
|
|
Terrain_fill = (uint8_t *)mem_malloc(TERRAIN_WIDTH * TERRAIN_DEPTH);
|
|
save_buffer = (uint8_t *)mem_malloc(TERRAIN_WIDTH * TERRAIN_DEPTH);
|
|
|
|
ASSERT(Terrain_heights);
|
|
ASSERT(save_buffer);
|
|
ASSERT(Terrain_fill);
|
|
|
|
memset(save_buffer, 0, TERRAIN_WIDTH * TERRAIN_DEPTH);
|
|
memset(Terrain_fill, 0, TERRAIN_WIDTH * TERRAIN_DEPTH);
|
|
|
|
for (int i = 0; i < TERRAIN_WIDTH * TERRAIN_DEPTH; i++) {
|
|
if (Terrain_seg[i].ypos == 255)
|
|
save_buffer[i] = 255;
|
|
}
|
|
|
|
for (int i = 0; i < OCCLUSION_SIZE; i++) {
|
|
for (int t = 0; t < OCCLUSION_SIZE; t++) {
|
|
int src_occlusion_index = i * OCCLUSION_SIZE + t;
|
|
int start_x = t * OCCLUSION_SIZE;
|
|
int start_z = i * OCCLUSION_SIZE;
|
|
int k, j;
|
|
int dest_x, dest_z;
|
|
|
|
for (dest_z = 0; dest_z < OCCLUSION_SIZE; dest_z++) {
|
|
for (dest_x = 0; dest_x < OCCLUSION_SIZE; dest_x++) {
|
|
int end_z = dest_z * OCCLUSION_SIZE;
|
|
int end_x = dest_x * OCCLUSION_SIZE;
|
|
int dest_occlusion_index = dest_z * OCCLUSION_SIZE + dest_x;
|
|
|
|
if (dest_occlusion_index == src_occlusion_index) {
|
|
// This is us!
|
|
int occ_byte = dest_occlusion_index / 8;
|
|
int occ_bit = dest_occlusion_index % 8;
|
|
|
|
Terrain_occlusion_map[src_occlusion_index][occ_byte] |= (1 << occ_bit);
|
|
touch_buffer[src_occlusion_index][dest_occlusion_index] = 1;
|
|
continue;
|
|
}
|
|
|
|
if (touch_buffer[dest_occlusion_index][src_occlusion_index] != 255) {
|
|
// this one has already been computed
|
|
int hit = touch_buffer[dest_occlusion_index][src_occlusion_index];
|
|
|
|
int dest_occ_byte = dest_occlusion_index / 8;
|
|
int dest_occ_bit = dest_occlusion_index % 8;
|
|
|
|
if (hit)
|
|
Terrain_occlusion_map[src_occlusion_index][dest_occ_byte] |= (1 << dest_occ_bit);
|
|
else
|
|
Terrain_occlusion_map[src_occlusion_index][dest_occ_byte] &= ~(1 << dest_occ_bit);
|
|
|
|
touch_buffer[src_occlusion_index][dest_occlusion_index] = hit;
|
|
continue;
|
|
}
|
|
|
|
// See if this ray is close enough
|
|
vector src_vec, dest_vec;
|
|
|
|
src_vec.x = start_x;
|
|
src_vec.y = 0;
|
|
src_vec.z = start_z;
|
|
|
|
dest_vec.x = end_x;
|
|
dest_vec.y = 0;
|
|
dest_vec.z = end_z;
|
|
|
|
// vector subvec=dest_vec-src_vec;
|
|
|
|
// Set our heights to max
|
|
memset(Terrain_heights, 255, TERRAIN_WIDTH * TERRAIN_DEPTH);
|
|
|
|
// Now carve out a path from the src to the dest
|
|
int x_major = 1;
|
|
if (abs(end_z - start_z) > abs(end_x - start_x))
|
|
x_major = 0;
|
|
|
|
// We're iterating over the x axis
|
|
if (x_major) {
|
|
int x_add = 1;
|
|
int limit = end_x - start_x;
|
|
if (limit < 0) {
|
|
x_add = -1;
|
|
limit = -limit;
|
|
}
|
|
|
|
int cur_x = start_x;
|
|
float cur_z = start_z;
|
|
float delta_z = (float)(end_z - start_z) / (float)limit;
|
|
|
|
for (j = 0; j < limit; j++, cur_x += x_add, cur_z += delta_z) {
|
|
for (int z = 0; z < OCCLUSION_SIZE; z++) {
|
|
for (int x = 0; x < OCCLUSION_SIZE; x++) {
|
|
int index = (cur_z + z) * TERRAIN_WIDTH;
|
|
index += (cur_x + x);
|
|
|
|
Terrain_heights[index] = 0;
|
|
}
|
|
}
|
|
}
|
|
} else // iterate over z axis
|
|
{
|
|
int z_add = 1;
|
|
int limit = end_z - start_z;
|
|
if (limit < 0) {
|
|
z_add = -1;
|
|
limit = -limit;
|
|
}
|
|
|
|
int cur_z = start_z;
|
|
float cur_x = start_x;
|
|
float delta_x = (float)(end_x - start_x) / (float)limit;
|
|
|
|
for (j = 0; j < limit; j++, cur_z += z_add, cur_x += delta_x) {
|
|
for (int z = 0; z < OCCLUSION_SIZE; z++) {
|
|
for (int x = 0; x < OCCLUSION_SIZE; x++) {
|
|
int index = (cur_z + z) * TERRAIN_WIDTH;
|
|
index += (cur_x + x);
|
|
|
|
Terrain_heights[index] = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Ok, we have a carved path
|
|
// Now put back in all the max values from our original map
|
|
for (k = 0; k < TERRAIN_WIDTH * TERRAIN_DEPTH; k++) {
|
|
if (save_buffer[k] == 255)
|
|
Terrain_heights[k] = 255;
|
|
}
|
|
|
|
// Set our src block to zero
|
|
for (k = 0; k < OCCLUSION_SIZE; k++) {
|
|
for (j = 0; j < OCCLUSION_SIZE; j++) {
|
|
Terrain_heights[((start_z + k) * TERRAIN_WIDTH) + start_x + j] = 0;
|
|
}
|
|
}
|
|
|
|
// Fill that valley
|
|
FillTerrainHeights((start_z * TERRAIN_WIDTH) + start_x);
|
|
|
|
// Check to see if we hit our destination
|
|
int seen = 0;
|
|
for (int z = 0; z < OCCLUSION_SIZE && !seen; z++) {
|
|
for (int x = 0; x < OCCLUSION_SIZE && !seen; x++) {
|
|
int index = (end_z + z) * TERRAIN_WIDTH;
|
|
index += (end_x + x);
|
|
|
|
if (Terrain_heights[index] == 1)
|
|
seen = 1;
|
|
}
|
|
}
|
|
|
|
touch_buffer[src_occlusion_index][dest_occlusion_index] = seen;
|
|
if (seen) {
|
|
int occ_byte = dest_occlusion_index / 8;
|
|
int occ_bit = dest_occlusion_index % 8;
|
|
Terrain_occlusion_map[src_occlusion_index][occ_byte] |= (1 << occ_bit);
|
|
} else {
|
|
int occ_byte = dest_occlusion_index / 8;
|
|
int occ_bit = dest_occlusion_index % 8;
|
|
Terrain_occlusion_map[src_occlusion_index][occ_byte] &= ~(1 << occ_bit);
|
|
|
|
occlude_count++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
mem_free(Terrain_heights);
|
|
mem_free(Terrain_fill);
|
|
mem_free(save_buffer);
|
|
|
|
for (int i = 0; i < 256; i++)
|
|
mem_free(touch_buffer[i]);
|
|
|
|
Terrain_occlusion_checksum = Terrain_checksum + 1;
|
|
|
|
mprintf(0, "%d cells were occluded.\n", occlude_count);
|
|
OutrageMessageBox("Occlusion checking complete. Remember to save!");
|
|
}
|
|
|
|
void CTerrainDialog::OnSatelliteRadio() {
|
|
cc_mode = CC_MODE_SAT;
|
|
UpdateDialog();
|
|
}
|
|
|
|
void CTerrainDialog::OnForceVisible() {
|
|
for (int i = 0; i < TERRAIN_WIDTH * TERRAIN_DEPTH; i++) {
|
|
if (TerrainSelected[i]) {
|
|
int c = Terrain_seg[i].flags & TF_INVISIBLE;
|
|
|
|
if (c) {
|
|
Terrain_seg[i].flags &= ~TF_INVISIBLE;
|
|
World_changed = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (World_changed)
|
|
GenerateLODDeltas();
|
|
}
|
|
|
|
void CTerrainDialog::OnKillfocusDamagePerSecEdit() {
|
|
CEdit *ebox;
|
|
char str[20];
|
|
float err;
|
|
|
|
ebox = (CEdit *)GetDlgItem(IDC_DAMAGE_PER_SEC_EDIT);
|
|
ebox->GetWindowText(str, 20);
|
|
|
|
err = atof(str);
|
|
if (err < 0)
|
|
err = 0;
|
|
if (err > 200)
|
|
err = 200;
|
|
|
|
Terrain_sky.damage_per_second = err;
|
|
|
|
World_changed = 1;
|
|
UpdateDialog();
|
|
}
|
|
|
|
void CTerrainDialog::OnKillfocusFogScalarEdit() {
|
|
CEdit *ebox;
|
|
char str[20];
|
|
float err;
|
|
|
|
ebox = (CEdit *)GetDlgItem(IDC_FOG_SCALAR_EDIT);
|
|
ebox->GetWindowText(str, 20);
|
|
|
|
err = atof(str);
|
|
if (err < .2)
|
|
err = .2f;
|
|
if (err > 1.0)
|
|
err = 1.0;
|
|
|
|
Terrain_sky.fog_scalar = err;
|
|
|
|
World_changed = 1;
|
|
UpdateDialog();
|
|
}
|
|
|
|
void CTerrainDialog::OnRotateStars() {
|
|
int c = IsDlgButtonChecked(IDC_ROTATE_STARS);
|
|
|
|
if (c)
|
|
Terrain_sky.flags |= TF_ROTATE_STARS;
|
|
else
|
|
Terrain_sky.flags &= ~TF_ROTATE_STARS;
|
|
|
|
TV_changed = 1;
|
|
}
|
|
|
|
void CTerrainDialog::OnRotateSky() {
|
|
int c = IsDlgButtonChecked(IDC_ROTATE_SKY);
|
|
|
|
if (c)
|
|
Terrain_sky.flags |= TF_ROTATE_SKY;
|
|
else
|
|
Terrain_sky.flags &= ~TF_ROTATE_SKY;
|
|
|
|
TV_changed = 1;
|
|
}
|
|
|
|
void CTerrainDialog::OnKillfocusRotateSpeedEdit() {
|
|
CEdit *ebox;
|
|
char str[20];
|
|
float err;
|
|
|
|
ebox = (CEdit *)GetDlgItem(IDC_ROTATE_SPEED_EDIT);
|
|
ebox->GetWindowText(str, 20);
|
|
|
|
err = atof(str);
|
|
if (err < 0)
|
|
err = 0;
|
|
if (err > 180)
|
|
err = 180;
|
|
|
|
Terrain_sky.rotate_rate = err;
|
|
|
|
World_changed = 1;
|
|
UpdateDialog();
|
|
}
|
|
|
|
void CTerrainDialog::OnTileMore() {
|
|
int i;
|
|
uint8_t touched[TERRAIN_TEX_WIDTH * TERRAIN_TEX_DEPTH];
|
|
memset(touched, 0, TERRAIN_TEX_WIDTH * TERRAIN_TEX_DEPTH);
|
|
|
|
for (i = 0; i < TERRAIN_WIDTH * TERRAIN_DEPTH; i++) {
|
|
if (TerrainSelected[i]) {
|
|
if (!touched[Terrain_seg[i].texseg_index]) {
|
|
int val = Terrain_tex_seg[Terrain_seg[i].texseg_index].rotation >> 4;
|
|
if (val < 8)
|
|
val++;
|
|
|
|
val <<= 4;
|
|
|
|
Terrain_tex_seg[Terrain_seg[i].texseg_index].rotation &= ~0xF0;
|
|
Terrain_tex_seg[Terrain_seg[i].texseg_index].rotation |= val;
|
|
touched[Terrain_seg[i].texseg_index] = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
World_changed = 1;
|
|
TV_changed = 1;
|
|
}
|
|
|
|
void CTerrainDialog::OnTileLess() {
|
|
int i;
|
|
uint8_t touched[TERRAIN_TEX_WIDTH * TERRAIN_TEX_DEPTH];
|
|
memset(touched, 0, TERRAIN_TEX_WIDTH * TERRAIN_TEX_DEPTH);
|
|
|
|
for (i = 0; i < TERRAIN_WIDTH * TERRAIN_DEPTH; i++) {
|
|
if (TerrainSelected[i]) {
|
|
if (!touched[Terrain_seg[i].texseg_index]) {
|
|
int val = Terrain_tex_seg[Terrain_seg[i].texseg_index].rotation >> 4;
|
|
if (val > 1)
|
|
val--;
|
|
|
|
val <<= 4;
|
|
|
|
Terrain_tex_seg[Terrain_seg[i].texseg_index].rotation &= ~0xF0;
|
|
Terrain_tex_seg[Terrain_seg[i].texseg_index].rotation |= val;
|
|
touched[Terrain_seg[i].texseg_index] = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
World_changed = 1;
|
|
TV_changed = 1;
|
|
}
|
|
|
|
#include "TerrainSoundDialog.h"
|
|
|
|
void CTerrainDialog::OnTerrSound() {
|
|
CTerrainSoundDialog dlg;
|
|
|
|
dlg.DoModal();
|
|
}
|