mirror of
https://github.com/ptitSeb/Serious-Engine
synced 2024-12-01 14:15:53 +01:00
2565 lines
74 KiB
C++
2565 lines
74 KiB
C++
/* Copyright (c) 2002-2012 Croteam Ltd.
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of version 2 of the GNU General Public License as published by
|
|
the Free Software Foundation
|
|
|
|
|
|
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, write to the Free Software Foundation, Inc.,
|
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
|
|
|
|
// TerrainInterface.cpp : implementation file
|
|
//
|
|
|
|
#include "stdafx.h"
|
|
#include "WorldEditor.h"
|
|
#include "TerrainInterface.h"
|
|
#include <Engine/Templates/Stock_CTextureData.h>
|
|
|
|
#ifdef _DEBUG
|
|
#undef new
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
#define RENDERED_BRUSH_SIZE_IN_METERS 32.0f
|
|
#define CHANGE_ANGLE_SENSITIVITY (1.0f/1.0f)
|
|
#define CHANGE_INDEX_SENSITIVITY (1.0f/16.0f)
|
|
#define CHANGE_NORMALIZED_SENSITIVITY (1.0f/100.0f)
|
|
#define CHANGE_PREASSURE_SENSITIVITY (1.0f)
|
|
#define CHANGE_OFFSET_SENSITIVITY 0.1f
|
|
#define CHANGE_STRETCH_SENSITIVITY 1.0f
|
|
#define LAYER_START_X 48
|
|
#define LAYER_HEIGHT 48
|
|
#define LAYER_SPACING_V PIX(4)
|
|
#define COL_ODD_LAYERS (RGBToColor(25,25,30)|CT_OPAQUE)
|
|
#define COL_EVEN_LAYERS (RGBToColor(40,40,50)|CT_OPAQUE)
|
|
COLOR _colSelectedLayerBcg=0x500000FF;
|
|
#define COL_SELECTED_LAYER _colSelectedLayerBcg
|
|
#define SLIDER_WIDTH 12
|
|
#define SLIDER_HOLDER_HEIGHT 32
|
|
|
|
#define COL_DEFAULT_ITEM (C_YELLOW|CT_OPAQUE)
|
|
#define COL_SETTINGS (C_vlBLUE|CT_OPAQUE)
|
|
#define COL_SEPARATOR (C_WHITE|CT_OPAQUE)
|
|
|
|
static FLOAT _fScrollLayers=0;
|
|
INDEX _iGenerateForLayer;
|
|
Rect _rectInvalid;
|
|
CUpdateableRT _udAutoGenerateDistribution;
|
|
CChangeableRT _chAutoGenerateDistribution;
|
|
CTerrain *_ptrLastEditedTerrain=NULL;
|
|
|
|
CTerrainEditBrush atebDefaultEditBrushValues[]=
|
|
{
|
|
{0,1}, {0,2}, {0,4}, {0,6},
|
|
{0,8}, {0,12}, {0,16}, {0,24},
|
|
{0,32}, {0,40}, {0,52}, {0,63},
|
|
|
|
{1,1}, {2,2}, {4,4}, {6,6},
|
|
{8,8}, {12,12}, {16,16}, {24,24},
|
|
{32,32}, {40,40}, {52,52}, {63,63},
|
|
|
|
{2,4}, {3,6}, {4,8}, {6,12},
|
|
{8,16}, {12,24}, {16,32}, {32,63},
|
|
};
|
|
CTerrainEditBrush atebCustomEditBrushes[CT_BRUSHES];
|
|
static CTextureObject _toIcons;
|
|
static CDynamicContainer<CTIButton> dcButtons;
|
|
|
|
void GenerateTerrainBrushTexture( INDEX iBrush, FLOAT fHotSpot, FLOAT fFallOff);
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CTerrainInterface
|
|
|
|
static CTString _strToolTip;
|
|
static void GetToolTipText(void *pTerrainInterface, char *pToolTipText)
|
|
{
|
|
pToolTipText+= sprintf(pToolTipText, "%s", _strToolTip);
|
|
}
|
|
|
|
CTFileName GetBrushTextureName(INDEX iBrush)
|
|
{
|
|
CTString strBrushFile;
|
|
strBrushFile.PrintF("Textures\\Editor\\TerrainBrush%02d.tex", iBrush);
|
|
return strBrushFile;
|
|
}
|
|
|
|
void CTerrainInterface::HideCursor(void)
|
|
{
|
|
RECT rect;
|
|
GetClientRect( &rect);
|
|
ClientToScreen( &rect);
|
|
ClipCursor(&rect);
|
|
while (ShowCursor(FALSE)>=0);
|
|
}
|
|
|
|
void CTerrainInterface::UnhideCursor(void)
|
|
{
|
|
ClipCursor(NULL);
|
|
while (ShowCursor(TRUE)<0);
|
|
}
|
|
|
|
void GetButtonOffset(CTIButton &tib, PIX &pixOffsetX, PIX &pixOffsetY)
|
|
{
|
|
if(tib.tib_iLayer!=-1)
|
|
{
|
|
CTerrain *ptrTerrain=GetTerrain();
|
|
if( ptrTerrain==NULL) return;
|
|
|
|
pixOffsetX=LAYER_START_X;
|
|
pixOffsetY=(ptrTerrain->tr_atlLayers.Count()-1-tib.tib_iLayer)*LAYER_HEIGHT-_fScrollLayers;
|
|
}
|
|
}
|
|
|
|
#define TERRAIN_SURFACE_VER "V002"
|
|
void LoadSurface(CTFileName fnSurface)
|
|
{
|
|
CTerrain *ptrTerrain=GetTerrain();
|
|
if( ptrTerrain==NULL) return;
|
|
|
|
try
|
|
{
|
|
CTFileStream strmFile;
|
|
strmFile.Open_t( fnSurface);
|
|
|
|
strmFile.ExpectID_t( CChunkID( "TRSF")); // terrain surface
|
|
// check version number
|
|
if( !( CChunkID(TERRAIN_SURFACE_VER) == strmFile.GetID_t()) )
|
|
{
|
|
throw( "Invalid version of terrain surface file. Unable to load");
|
|
}
|
|
|
|
INDEX ctLayers=ptrTerrain->tr_atlLayers.Count();
|
|
for(INDEX iDelLayer=0; iDelLayer<ctLayers-1; iDelLayer++)
|
|
{
|
|
ptrTerrain->RemoveLayer(0, FALSE);
|
|
}
|
|
ptrTerrain->tr_atlLayers[0].ResetLayerMask(0xFF);
|
|
|
|
ctLayers=0;
|
|
strmFile>>ctLayers;
|
|
|
|
for( INDEX iLayer=0; iLayer<ctLayers; iLayer++)
|
|
{
|
|
CTFileName fnTexture;
|
|
strmFile>>fnTexture;
|
|
// check if texture exists
|
|
if(!FileExists( fnTexture))
|
|
{
|
|
fnTexture=CTFILENAME("Textures\\Editor\\Default.tex");
|
|
}
|
|
|
|
CTerrainLayer *ptlLayer=&ptrTerrain->tr_atlLayers[0];
|
|
if( iLayer!=0)
|
|
{
|
|
ptlLayer=&ptrTerrain->AddLayer_t(fnTexture, LT_NORMAL, FALSE);
|
|
}
|
|
else
|
|
{
|
|
ptlLayer->SetLayerTexture_t(fnTexture);
|
|
}
|
|
|
|
// load surface
|
|
strmFile>>ptlLayer->tl_fRotateX;
|
|
strmFile>>ptlLayer->tl_fRotateY;
|
|
strmFile>>ptlLayer->tl_fStretchX;
|
|
strmFile>>ptlLayer->tl_fStretchY;
|
|
strmFile>>ptlLayer->tl_fOffsetX;
|
|
strmFile>>ptlLayer->tl_fOffsetY;
|
|
|
|
strmFile>>ptlLayer->tl_bAutoRegenerated;
|
|
strmFile>>ptlLayer->tl_fCoverage;
|
|
strmFile>>ptlLayer->tl_fCoverageNoise;
|
|
strmFile>>ptlLayer->tl_fCoverageRandom;
|
|
|
|
strmFile>>ptlLayer->tl_bApplyMinAltitude;
|
|
strmFile>>ptlLayer->tl_fMinAltitude;
|
|
strmFile>>ptlLayer->tl_fMinAltitudeFade;
|
|
strmFile>>ptlLayer->tl_fMinAltitudeNoise;
|
|
strmFile>>ptlLayer->tl_fMinAltitudeRandom;
|
|
|
|
strmFile>>ptlLayer->tl_bApplyMaxAltitude;
|
|
strmFile>>ptlLayer->tl_fMaxAltitude;
|
|
strmFile>>ptlLayer->tl_fMaxAltitudeFade;
|
|
strmFile>>ptlLayer->tl_fMaxAltitudeNoise;
|
|
strmFile>>ptlLayer->tl_fMaxAltitudeRandom;
|
|
|
|
strmFile>>ptlLayer->tl_bApplyMinSlope;
|
|
strmFile>>ptlLayer->tl_fMinSlope;
|
|
strmFile>>ptlLayer->tl_fMinSlopeFade;
|
|
strmFile>>ptlLayer->tl_fMinSlopeNoise;
|
|
strmFile>>ptlLayer->tl_fMinSlopeRandom;
|
|
|
|
strmFile>>ptlLayer->tl_bApplyMaxSlope;
|
|
strmFile>>ptlLayer->tl_fMaxSlope;
|
|
strmFile>>ptlLayer->tl_fMaxSlopeFade;
|
|
strmFile>>ptlLayer->tl_fMaxSlopeNoise;
|
|
strmFile>>ptlLayer->tl_fMaxSlopeRandom;
|
|
|
|
strmFile>>ptlLayer->tl_colMultiply;
|
|
}
|
|
|
|
strmFile.Close();
|
|
}
|
|
catch( char *strError)
|
|
{
|
|
WarningMessage(strError);
|
|
return;
|
|
}
|
|
|
|
GenerateLayerDistribution(-1);
|
|
theApp.m_ctTerrainPage.MarkChanged();
|
|
ptrTerrain->RefreshTerrain();
|
|
}
|
|
|
|
void SaveSurface(CTFileName fnSurface)
|
|
{
|
|
CTerrain *ptrTerrain=GetTerrain();
|
|
if( ptrTerrain==NULL) return;
|
|
|
|
try
|
|
{
|
|
CTFileStream strmFile;
|
|
strmFile.Create_t( fnSurface);
|
|
|
|
strmFile.WriteID_t( CChunkID( "TRSF")); // terrain surface
|
|
// write version number
|
|
strmFile.WriteID_t(TERRAIN_SURFACE_VER);
|
|
|
|
INDEX ctLayers=ptrTerrain->tr_atlLayers.Count();
|
|
strmFile<<ctLayers;
|
|
|
|
for( INDEX iLayer=0; iLayer<ctLayers; iLayer++)
|
|
{
|
|
CTerrainLayer *ptlLayer=&ptrTerrain->tr_atlLayers[iLayer];
|
|
|
|
if(ptlLayer->tl_ptdTexture==NULL) continue;
|
|
CTFileName fnTexture=ptlLayer->tl_ptdTexture->GetName();
|
|
|
|
strmFile<<fnTexture;
|
|
|
|
// save surface
|
|
strmFile<<ptlLayer->tl_fRotateX;
|
|
strmFile<<ptlLayer->tl_fRotateY;
|
|
strmFile<<ptlLayer->tl_fStretchX;
|
|
strmFile<<ptlLayer->tl_fStretchY;
|
|
strmFile<<ptlLayer->tl_fOffsetX;
|
|
strmFile<<ptlLayer->tl_fOffsetY;
|
|
|
|
strmFile<<ptlLayer->tl_bAutoRegenerated;
|
|
strmFile<<ptlLayer->tl_fCoverage;
|
|
strmFile<<ptlLayer->tl_fCoverageNoise;
|
|
strmFile<<ptlLayer->tl_fCoverageRandom;
|
|
|
|
strmFile<<ptlLayer->tl_bApplyMinAltitude;
|
|
strmFile<<ptlLayer->tl_fMinAltitude;
|
|
strmFile<<ptlLayer->tl_fMinAltitudeFade;
|
|
strmFile<<ptlLayer->tl_fMinAltitudeNoise;
|
|
strmFile<<ptlLayer->tl_fMinAltitudeRandom;
|
|
|
|
strmFile<<ptlLayer->tl_bApplyMaxAltitude;
|
|
strmFile<<ptlLayer->tl_fMaxAltitude;
|
|
strmFile<<ptlLayer->tl_fMaxAltitudeFade;
|
|
strmFile<<ptlLayer->tl_fMaxAltitudeNoise;
|
|
strmFile<<ptlLayer->tl_fMaxAltitudeRandom;
|
|
|
|
strmFile<<ptlLayer->tl_bApplyMinSlope;
|
|
strmFile<<ptlLayer->tl_fMinSlope;
|
|
strmFile<<ptlLayer->tl_fMinSlopeFade;
|
|
strmFile<<ptlLayer->tl_fMinSlopeNoise;
|
|
strmFile<<ptlLayer->tl_fMinSlopeRandom;
|
|
|
|
strmFile<<ptlLayer->tl_bApplyMaxSlope;
|
|
strmFile<<ptlLayer->tl_fMaxSlope;
|
|
strmFile<<ptlLayer->tl_fMaxSlopeFade;
|
|
strmFile<<ptlLayer->tl_fMaxSlopeNoise;
|
|
strmFile<<ptlLayer->tl_fMaxSlopeRandom;
|
|
|
|
strmFile<<ptlLayer->tl_colMultiply;
|
|
}
|
|
|
|
strmFile.Close();
|
|
}
|
|
catch( char *strError)
|
|
{
|
|
WarningMessage(strError);
|
|
return;
|
|
}
|
|
}
|
|
|
|
void PointToIconSpace(CPoint &pt, CTIButton *ptib)
|
|
{
|
|
PIX pixOffsetX=0;
|
|
PIX pixOffsetY=0;
|
|
GetButtonOffset(*ptib, pixOffsetX, pixOffsetY);
|
|
PIX x=ptib->tib_fx+pixOffsetX;
|
|
PIX y=ptib->tib_fy+pixOffsetY;
|
|
pt.x=Clamp(pt.x-x, INDEX(0), INDEX(ptib->tib_fdx));
|
|
pt.y=Clamp(pt.y-y, INDEX(0), INDEX(ptib->tib_fdy));
|
|
}
|
|
|
|
void PointToScreenSpace(CPoint &pt, CDrawPort *pdp)
|
|
{
|
|
HWND hWnd=pdp->dp_Raster->ra_pvpViewPort->vp_hWnd;
|
|
ClientToScreen(hWnd, &pt);
|
|
}
|
|
|
|
PIXaabbox2D GetButtonScreenBox(CTIButton &tib)
|
|
{
|
|
PIX pixOffsetX=0;
|
|
PIX pixOffsetY=0;
|
|
GetButtonOffset(tib, pixOffsetX, pixOffsetY);
|
|
PIX x=tib.tib_fx+pixOffsetX;
|
|
PIX y=tib.tib_fy+pixOffsetY;
|
|
PIX dx=tib.tib_fdx;
|
|
PIX dy=tib.tib_fdy;
|
|
PIXaabbox2D boxScreen=PIXaabbox2D( PIX2D(x,y), PIX2D(x+dx, y+dy));
|
|
return boxScreen;
|
|
}
|
|
|
|
void GenerateDefaultBrush(INDEX iBrush)
|
|
{
|
|
atebCustomEditBrushes[iBrush].teb_fHotSpot=atebDefaultEditBrushValues[iBrush].teb_fHotSpot;
|
|
atebCustomEditBrushes[iBrush].teb_fFallOff=atebDefaultEditBrushValues[iBrush].teb_fFallOff;
|
|
GenerateTerrainBrushTexture( iBrush,
|
|
atebCustomEditBrushes[iBrush].teb_fHotSpot-0.1f, atebCustomEditBrushes[iBrush].teb_fFallOff-0.1f);
|
|
}
|
|
|
|
void SetDefaultEditBrushes(void)
|
|
{
|
|
for(INDEX iBrush=0; iBrush<CT_BRUSHES; iBrush++)
|
|
{
|
|
GenerateDefaultBrush(iBrush);
|
|
}
|
|
}
|
|
|
|
void GenerateNonExistingTerrainEditBrushes(void)
|
|
{
|
|
for(INDEX iBrush=0; iBrush<CT_BRUSHES; iBrush++)
|
|
{
|
|
// copy default values as custom ones
|
|
atebCustomEditBrushes[iBrush].teb_fHotSpot=atebDefaultEditBrushValues[iBrush].teb_fHotSpot;
|
|
atebCustomEditBrushes[iBrush].teb_fFallOff=atebDefaultEditBrushValues[iBrush].teb_fFallOff;
|
|
|
|
CTFileName fnBrush=GetBrushTextureName(iBrush);
|
|
if(!FileExists(fnBrush))
|
|
{
|
|
GenerateDefaultBrush(iBrush);
|
|
}
|
|
else
|
|
{
|
|
// precache existing brushes
|
|
try
|
|
{
|
|
_pTextureStock->Obtain_t(fnBrush);
|
|
}
|
|
catch(char *strError)
|
|
{
|
|
(void) strError;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
CTerrainInterface::CTerrainInterface()
|
|
{
|
|
m_pDrawPort = NULL;
|
|
m_pViewPort = NULL;
|
|
_fScrollLayers=0;
|
|
_udAutoGenerateDistribution.MarkUpdated();
|
|
}
|
|
|
|
CTerrainInterface::~CTerrainInterface()
|
|
{
|
|
}
|
|
|
|
|
|
BEGIN_MESSAGE_MAP(CTerrainInterface, CWnd)
|
|
//{{AFX_MSG_MAP(CTerrainInterface)
|
|
ON_WM_PAINT()
|
|
ON_WM_DESTROY()
|
|
ON_WM_LBUTTONDOWN()
|
|
ON_WM_MOUSEMOVE()
|
|
ON_WM_LBUTTONUP()
|
|
ON_WM_RBUTTONDOWN()
|
|
ON_WM_RBUTTONUP()
|
|
ON_WM_LBUTTONDBLCLK()
|
|
ON_WM_DROPFILES()
|
|
ON_WM_CREATE()
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CTerrainInterface message handlers
|
|
|
|
void CTerrainInterface::OnPaint()
|
|
{
|
|
#if ALLOW_TERRAINS
|
|
{
|
|
CPaintDC dc(this);
|
|
}
|
|
|
|
if( (m_pViewPort == NULL) && (m_pDrawPort == NULL) )
|
|
{
|
|
// initialize canvas for active texture button
|
|
_pGfx->CreateWindowCanvas( m_hWnd, &m_pViewPort, &m_pDrawPort);
|
|
}
|
|
|
|
// if there is a valid drawport, and the drawport can be locked
|
|
if( (m_pDrawPort != NULL) && (m_pDrawPort->Lock()) )
|
|
{
|
|
if(dcButtons.Count()==0 || GetTerrain()!=_ptrLastEditedTerrain)
|
|
{
|
|
InitializeInterface(m_pDrawPort);
|
|
_ptrLastEditedTerrain=GetTerrain();
|
|
}
|
|
|
|
PIXaabbox2D rectPict;
|
|
rectPict = PIXaabbox2D( PIX2D(0, 0),
|
|
PIX2D(m_pDrawPort->GetWidth(), m_pDrawPort->GetHeight()));
|
|
// clear texture area to black
|
|
m_pDrawPort->Fill( C_BLACK | CT_OPAQUE);
|
|
// erase z-buffer
|
|
m_pDrawPort->FillZBuffer(ZBUF_BACK);
|
|
|
|
RenderInterface(m_pDrawPort);
|
|
|
|
// unlock the drawport
|
|
m_pDrawPort->Unlock();
|
|
|
|
if (m_pViewPort!=NULL)
|
|
{
|
|
m_pViewPort->SwapBuffers();
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void CTerrainInterface::RenderInterface(CDrawPort *pdp)
|
|
{
|
|
#if ALLOW_TERRAINS
|
|
// render terrain interface buttons
|
|
FOREACHINDYNAMICCONTAINER( dcButtons, CTIButton, ittib)
|
|
{
|
|
CTIButton &tib=*ittib;
|
|
PIX pixOffsetX=0;
|
|
PIX pixOffsetY=0;
|
|
GetButtonOffset(tib, pixOffsetX, pixOffsetY);
|
|
if( tib.tib_pPreRender!=NULL) tib.tib_pPreRender(&tib, pdp);
|
|
|
|
PIX x=tib.tib_fx+pixOffsetX;
|
|
PIX y=tib.tib_fy+pixOffsetY;
|
|
PIX dx=tib.tib_fdx;
|
|
PIX dy=tib.tib_fdy;
|
|
|
|
// bcg icon fill
|
|
if( tib.tib_colFill&0xFF)
|
|
{
|
|
if(pdp->Lock())
|
|
{
|
|
pdp->Fill(x,y,dx,dy, tib.tib_colFill);
|
|
pdp->Unlock();
|
|
}
|
|
}
|
|
|
|
// icon texture
|
|
if( tib.tib_iIcon!=-1)
|
|
{
|
|
PIXaabbox2D boxScreen=PIXaabbox2D( PIX2D(x,y), PIX2D(x+dx, y+dy));
|
|
MEXaabbox2D boxTexture=MEXaabbox2D( MEX2D(16*tib.tib_iIcon,0), MEX2D(16*tib.tib_iIcon+16,16));
|
|
COLOR colMultiply=C_WHITE|CT_OPAQUE;
|
|
if(tib.tib_pIsEnabled!=NULL && !tib.tib_pIsEnabled(&tib))
|
|
{
|
|
colMultiply=C_dGRAY|CT_OPAQUE;
|
|
}
|
|
pdp->PutTexture( &_toIcons, boxScreen, boxTexture, colMultiply);
|
|
}
|
|
|
|
// custom render
|
|
if(tib.tib_pOnRender!=NULL) tib.tib_pOnRender(&tib, pdp);
|
|
|
|
// icon border
|
|
if( tib.tib_colBorderColor&0xFF)
|
|
{
|
|
if(pdp->Lock())
|
|
{
|
|
pdp->DrawBorder(x,y,dx,dy, tib.tib_colBorderColor);
|
|
pdp->Unlock();
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
PIXaabbox2D GetLayersBox(CDrawPort *pdp)
|
|
{
|
|
return PIXaabbox2D( PIX2D(LAYER_START_X,0), PIX2D(pdp->GetWidth()-LAYER_START_X, pdp->GetHeight()));
|
|
}
|
|
|
|
PIX2D GetLayerSize(CDrawPort *pdp)
|
|
{
|
|
return PIX2D(pdp->GetWidth()-LAYER_START_X, LAYER_HEIGHT);
|
|
}
|
|
|
|
void CTerrainInterface::OnDestroy()
|
|
{
|
|
CWnd::OnDestroy();
|
|
|
|
if( m_pViewPort != NULL)
|
|
{
|
|
_pGfx->DestroyWindowCanvas( m_pViewPort);
|
|
m_pViewPort = NULL;
|
|
}
|
|
|
|
m_pViewPort = NULL;
|
|
m_pDrawPort = NULL;
|
|
}
|
|
|
|
void GenerateTerrainBrushTexture( INDEX iBrush, FLOAT fHotSpot, FLOAT fFallOff)
|
|
{
|
|
#if ALLOW_TERRAINS
|
|
INDEX iLog2=INDEX(ceil(Log2(fFallOff*2+2)));
|
|
PIX pixSize=1UL<<(iLog2+1);
|
|
FLOAT fcx=pixSize/2.0f;
|
|
FLOAT fcy=pixSize/2.0f;
|
|
CImageInfo ii;
|
|
ii.ii_Width=pixSize;
|
|
ii.ii_Height=pixSize;
|
|
ii.ii_BitsPerPixel=32;
|
|
ii.ii_Picture=(UBYTE*) AllocMemory(ii.ii_Width*ii.ii_Height*ii.ii_BitsPerPixel/8);
|
|
COLOR *pcol=(COLOR *)ii.ii_Picture;
|
|
|
|
for(INDEX iy=0; iy<ii.ii_Height; iy++)
|
|
{
|
|
for(INDEX ix=0; ix<ii.ii_Width; ix++)
|
|
{
|
|
FLOAT fDist=sqrt((fcx-ix)*(fcx-ix)+(fcy-iy)*(fcy-iy));
|
|
FLOAT fcolPower=1.0f;
|
|
if(fDist>fFallOff) fcolPower=0.0f;
|
|
else if(fDist>fHotSpot)
|
|
{
|
|
fcolPower=CalculateRatio(fDist, fHotSpot, fFallOff, 0.0f, 1.0f);
|
|
fcolPower=1.0f-(1.0f-fcolPower)*(1.0f-fcolPower);
|
|
}
|
|
UBYTE ubCol=fcolPower*255.0f;
|
|
COLOR col=RGBToColor(ubCol,ubCol,ubCol)|CT_OPAQUE;
|
|
*pcol=ByteSwap(col);
|
|
pcol++;
|
|
}
|
|
}
|
|
CTextureData tdBrush;
|
|
try
|
|
{
|
|
tdBrush.Create_t( &ii, pixSize, 16, TRUE);
|
|
CTString strBrushFile;
|
|
strBrushFile.PrintF("Textures\\Editor\\TerrainBrush%02d.tex", iBrush);
|
|
tdBrush.Save_t( strBrushFile);
|
|
tdBrush.Reload();
|
|
}
|
|
catch( char *strError)
|
|
{
|
|
(void) strError;
|
|
WarningMessage("Unable to create terrain brush texture!");
|
|
}
|
|
#endif
|
|
}
|
|
|
|
CTIButton::CTIButton()
|
|
{
|
|
tib_fx=0.0f;
|
|
tib_fy=0.0f;
|
|
tib_fdx=0.0f;
|
|
tib_fdy=0.0f;
|
|
tib_iIcon=-1;
|
|
tib_colBorderColor=0;
|
|
tib_fDataMin=0.0f;
|
|
tib_fDataMax=0.0f;
|
|
tib_bWrapData=TRUE;
|
|
tib_fDataDelta=0.0f;
|
|
tib_pfData1=NULL;
|
|
tib_pfData2=NULL;
|
|
tib_iLayer=-1;
|
|
tib_strToolTip="Unknown tool tip";
|
|
tib_pPreRender=NULL;
|
|
tib_pOnRender=NULL;
|
|
tib_pOnLeftClick=NULL;
|
|
tib_pOnLeftClickMove=NULL;
|
|
tib_pOnRightClick=NULL;
|
|
tib_pOnRightClickMove=NULL;
|
|
tib_pOnDropFiles=NULL;
|
|
tib_pGetClickMoveData=NULL;
|
|
tib_pIsEnabled=NULL;
|
|
|
|
tib_bMouseTrapForMove=TRUE;
|
|
tib_bContinueTesting=FALSE;
|
|
}
|
|
|
|
CTIButton *AddButton(CDynamicContainer<CTIButton> &dc, FLOAT x, FLOAT y, FLOAT dx, FLOAT dy, INDEX iLayer, INDEX iIcon,
|
|
CTString strToolTip, COLOR colBorder=C_RED|CT_TRANSPARENT, COLOR colFill=C_BLACK|CT_TRANSPARENT)
|
|
{
|
|
CTIButton &tib=*(new CTIButton);
|
|
tib.tib_fx=x;
|
|
tib.tib_fy=y;
|
|
tib.tib_fdx=dx;
|
|
tib.tib_fdy=dy;
|
|
tib.tib_iLayer=iLayer;
|
|
tib.tib_iIcon=iIcon;
|
|
tib.tib_strToolTip=strToolTip;
|
|
tib.tib_colBorderColor=colBorder;
|
|
tib.tib_colFill=colFill;
|
|
dc.Add(&tib);
|
|
return &tib;
|
|
}
|
|
|
|
void CTIButton::SetData( FLOAT fDataMin, FLOAT fDataMax, FLOAT fDataDelta, BOOL bWrap/*=FALSE*/, FLOAT *pfData1/*=NULL*/, FLOAT *pfData2/*=NULL*/)
|
|
{
|
|
tib_fDataMin=fDataMin;
|
|
tib_fDataMax=fDataMax;
|
|
tib_fDataDelta=fDataDelta;
|
|
tib_bWrapData=bWrap;
|
|
tib_pfData1=pfData1;
|
|
tib_pfData2=pfData2;
|
|
}
|
|
|
|
void CTIButton::SetFunctions(
|
|
void (*pOnRender)(CTIButton *ptib, CDrawPort *pdp)/*=NULL*/,
|
|
void (*pOnLeftClick)(CTIButton *ptib, CPoint pt, CDrawPort *pdp)/*=NULL*/,
|
|
void (*pOnLeftClickMove)(CTIButton *ptib, FLOAT fdx, FLOAT fdy, CDrawPort *pdp)/*=NULL*/,
|
|
void (*pOnRightClick)(CTIButton *ptib, CPoint pt, CDrawPort *pdp)/*=NULL*/,
|
|
void (*pOnRightClickMove)(CTIButton *ptib, FLOAT fdx, FLOAT fdy, CDrawPort *pdp)/*=NULL*/,
|
|
void (*pPreRender)(CTIButton *ptib, CDrawPort *pdp)/*=NULL*/)
|
|
{
|
|
tib_pOnRender=pOnRender;
|
|
tib_pOnLeftClick=pOnLeftClick;
|
|
tib_pOnLeftClickMove=pOnLeftClickMove;
|
|
tib_pOnRightClick=pOnRightClick;
|
|
tib_pOnRightClickMove=pOnRightClickMove;
|
|
tib_pPreRender=pPreRender;
|
|
}
|
|
|
|
void RenderBrushNo(CTIButton *ptib, CDrawPort *pdp)
|
|
{
|
|
pdp->SetFont( _pfdConsoleFont);
|
|
pdp->SetTextAspect( 1.0f);
|
|
pdp->SetTextScaling( 1.0f);
|
|
CTString strText;
|
|
strText.PrintF("%d", INDEX(theApp.m_fCurrentTerrainBrush));
|
|
pdp->PutTextC( strText, ptib->tib_fx+ptib->tib_fdx/2, ptib->tib_fy+4, C_YELLOW|CT_OPAQUE);
|
|
}
|
|
|
|
void RenderBrushShape( INDEX iBrush, PIXaabbox2D rect, CDrawPort *pdp)
|
|
{
|
|
CDrawPort dpBrush=CDrawPort(pdp, rect);
|
|
CTextureObject to;
|
|
CTString strBrushFile;
|
|
strBrushFile.PrintF("Textures\\Editor\\TerrainBrush%02d.tex", iBrush);
|
|
try
|
|
{
|
|
to.SetData_t(strBrushFile);
|
|
CTextureData *ptd=(CTextureData *)to.GetData();
|
|
if( dpBrush.Lock())
|
|
{
|
|
dpBrush.Fill(C_BLACK|CT_OPAQUE);
|
|
PIX pixTexW=ptd->GetPixWidth();
|
|
PIX pixTexH=ptd->GetPixHeight();
|
|
|
|
FLOAT fScreenW=dpBrush.GetWidth()*pixTexW/RENDERED_BRUSH_SIZE_IN_METERS;
|
|
FLOAT fScreenH=dpBrush.GetHeight()*pixTexH/RENDERED_BRUSH_SIZE_IN_METERS;
|
|
|
|
PIXaabbox2D rectPic;
|
|
rectPic = PIXaabbox2D(
|
|
PIX2D(dpBrush.GetWidth()/2.0f-fScreenW/2.0f, dpBrush.GetHeight()/2.0f-fScreenH/2.0f),
|
|
PIX2D(dpBrush.GetWidth()/2.0f-fScreenW/2.0f+fScreenW, dpBrush.GetHeight()/2.0f-fScreenH/2.0f+fScreenH));
|
|
dpBrush.PutTexture( &to, rectPic);
|
|
dpBrush.Unlock();
|
|
}
|
|
}
|
|
catch( char *strError)
|
|
{
|
|
(void) strError;
|
|
}
|
|
}
|
|
|
|
void RenderBrushShape(CTIButton *ptib, CDrawPort *pdp)
|
|
{
|
|
INDEX iBrush=INDEX(theApp.m_fCurrentTerrainBrush);
|
|
CTerrainEditBrush &teb=atebCustomEditBrushes[iBrush];
|
|
PIXaabbox2D rectButton = PIXaabbox2D(
|
|
PIX2D(ptib->tib_fx, ptib->tib_fy),
|
|
PIX2D(ptib->tib_fx+ptib->tib_fdx, ptib->tib_fy+ptib->tib_fdy));
|
|
RenderBrushShape(iBrush,rectButton,pdp);
|
|
}
|
|
|
|
void RenderBrushPressure(CTIButton *ptib, CDrawPort *pdp)
|
|
{
|
|
pdp->SetFont( _pfdConsoleFont);
|
|
pdp->SetTextAspect( 1.0f);
|
|
pdp->SetTextScaling( 1.0f);
|
|
CTString strText;
|
|
strText.PrintF("%d%%", INDEX(theApp.m_fTerrainBrushPressure/1024.0f*100.0f));
|
|
pdp->PutTextC( strText, ptib->tib_fx+ptib->tib_fdx/2, ptib->tib_fy, C_YELLOW|CT_OPAQUE);
|
|
}
|
|
|
|
void RenderLayerTexture(CTIButton *ptib, CDrawPort *pdp)
|
|
{
|
|
INDEX iLayer=ptib->tib_iLayer;
|
|
CTerrainLayer *ptlLayer=GetLayer(iLayer);
|
|
if(ptlLayer!=NULL && ptlLayer->tl_ptdTexture!=NULL)
|
|
{
|
|
CTextureObject to;
|
|
to.SetData(ptlLayer->tl_ptdTexture);
|
|
PIXaabbox2D boxScreen=GetButtonScreenBox(*ptib);
|
|
pdp->PutTexture( &to, boxScreen);
|
|
}
|
|
}
|
|
|
|
void RenderLayerBcg(CTIButton *ptib, CDrawPort *pdp)
|
|
{
|
|
INDEX iLayer=ptib->tib_iLayer;
|
|
|
|
CTIButton &tib=*ptib;
|
|
PIX pixOffsetX=0;
|
|
PIX pixOffsetY=0;
|
|
GetButtonOffset(tib, pixOffsetX, pixOffsetY);
|
|
if( tib.tib_pPreRender!=NULL) tib.tib_pPreRender(&tib, pdp);
|
|
|
|
PIX x=tib.tib_fx+pixOffsetX;
|
|
PIX y=tib.tib_fy+pixOffsetY;
|
|
PIX dx=tib.tib_fdx;
|
|
PIX dy=tib.tib_fdy;
|
|
|
|
COLOR colBcg=C_WHITE|CT_OPAQUE;
|
|
if( tib.tib_iLayer==GetLayerIndex()) colBcg=COL_SELECTED_LAYER;
|
|
else if( iLayer&1) colBcg=COL_ODD_LAYERS;
|
|
else colBcg=COL_EVEN_LAYERS;
|
|
|
|
if(pdp->Lock())
|
|
{
|
|
pdp->Fill(x,y,dx,dy, colBcg);
|
|
pdp->Unlock();
|
|
}
|
|
}
|
|
|
|
void RenderLayerMask(CTIButton *ptib, CDrawPort *pdp)
|
|
{
|
|
INDEX iLayer=ptib->tib_iLayer;
|
|
CTerrainLayer *ptlLayer=GetLayer(iLayer);
|
|
if(ptlLayer!=NULL && ptlLayer->tl_ptdTexture!=NULL)
|
|
{
|
|
CTextureObject to;
|
|
CTextureData *ptd=ptlLayer->GetThumbnail(64,64);
|
|
to.SetData(ptd);
|
|
PIXaabbox2D boxScreen=GetButtonScreenBox(*ptib);
|
|
pdp->PutTexture( &to, boxScreen);
|
|
}
|
|
}
|
|
|
|
void GetBrushModeInfo(INDEX iMode, INDEX &iIcon, CTString &strText)
|
|
{
|
|
strText="Unknown";
|
|
iIcon=0;
|
|
switch(INDEX (iMode))
|
|
{
|
|
case TBM_PAINT:
|
|
{
|
|
strText="Paint (J)";
|
|
if(INDEX(theApp.m_iTerrainEditMode)==TEM_HEIGHTMAP) iIcon=12;
|
|
else iIcon=8;
|
|
break;
|
|
}
|
|
case TBM_SMOOTH: strText="Smooth tool (O)"; iIcon=10; break;
|
|
case TBM_FILTER: strText="Filter tool (F)"; iIcon=30; break;
|
|
case TBM_MINIMUM: strText="Limit down (M)"; iIcon=27; break;
|
|
case TBM_MAXIMUM: strText="Limit up (X)"; iIcon=11; break;
|
|
case TBM_FLATTEN: strText="Flatten (=)"; iIcon=18; break;
|
|
case TBM_POSTERIZE: strText="Posterize (;)"; iIcon=28; break;
|
|
case TBM_RND_NOISE: strText="Random noise (K)"; iIcon=21; break;
|
|
case TBM_CONTINOUS_NOISE: strText="Texture noise (Y)"; iIcon=31; break;
|
|
case TBM_ERASE: strText="Erase (D)"; iIcon=9; break;
|
|
}
|
|
}
|
|
|
|
void UpdateEditModeIcon(CTIButton *ptib, CDrawPort *pdp)
|
|
{
|
|
if(INDEX(theApp.m_iTerrainEditMode)==TEM_HEIGHTMAP) ptib->tib_iIcon=20;
|
|
else ptib->tib_iIcon=19;
|
|
}
|
|
|
|
void UpdateBrushModeIcon(CTIButton *ptib, CDrawPort *pdp)
|
|
{
|
|
INDEX iIcon;
|
|
CTString strText;
|
|
GetBrushModeInfo(INDEX(theApp.m_iTerrainBrushMode), iIcon, strText);
|
|
ptib->tib_iIcon=iIcon;
|
|
}
|
|
|
|
void UpdateLayerVisibleFlag(CTIButton *ptib, CDrawPort *pdp)
|
|
{
|
|
INDEX iLayer=ptib->tib_iLayer;
|
|
CTerrainLayer *ptlLayer=GetLayer(iLayer);
|
|
if(ptlLayer!=NULL)
|
|
{
|
|
if( ptlLayer->tl_bVisible) ptib->tib_iIcon=3;
|
|
else ptib->tib_iIcon=4;
|
|
}
|
|
}
|
|
|
|
void UpdatePressure(CTIButton *ptib, CDrawPort *pdp)
|
|
{
|
|
if(theApp.m_fTerrainBrushPressureEnum>=0)
|
|
{
|
|
theApp.m_fTerrainBrushPressure=(theApp.m_fTerrainBrushPressureEnum+1)/10.0f*1024.0f+1;
|
|
theApp.m_fTerrainBrushPressureEnum=-1;
|
|
}
|
|
}
|
|
|
|
void SetAsActiveLayer(CTIButton *ptib, CPoint pt, CDrawPort *pdp)
|
|
{
|
|
SelectLayer(ptib->tib_iLayer);
|
|
CWorldEditorDoc* pDoc = theApp.GetActiveDocument();
|
|
if(pDoc!=NULL)
|
|
{
|
|
pDoc->m_chSelections.MarkChanged();
|
|
}
|
|
}
|
|
|
|
|
|
void ApplyLayerCommand(INDEX iSelectedItem)
|
|
{
|
|
CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
|
|
CTerrain *ptrTerrain=GetTerrain();
|
|
if( ptrTerrain==NULL) return;
|
|
CTerrainLayer *ptlLayer=GetLayer();
|
|
INDEX iLayer=GetLayerIndex();
|
|
if(ptlLayer!=NULL)
|
|
{
|
|
switch( iSelectedItem)
|
|
{
|
|
case 0: // "Delete layer"
|
|
{
|
|
if(ptrTerrain->tr_atlLayers.Count()>1)
|
|
{
|
|
if( ::MessageBoxA( pMainFrame->m_hWnd, "Are you sure that you want to delete this layer?",
|
|
"Warning !", MB_YESNO | MB_ICONWARNING | MB_DEFBUTTON1| MB_SYSTEMMODAL | MB_TOPMOST) == IDYES)
|
|
{
|
|
ptrTerrain->RemoveLayer(iLayer);
|
|
if(GetLayerIndex()>=ptrTerrain->tr_atlLayers.Count())
|
|
{
|
|
SelectLayer(ptrTerrain->tr_atlLayers.Count()-1);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case 1: // "Insert texture layer"
|
|
{
|
|
try
|
|
{
|
|
ptrTerrain->AddLayer_t( CTFILENAME("Textures\\Editor\\Default.tex"));
|
|
SelectLayer( ptrTerrain->tr_atlLayers.Count()-1);
|
|
}
|
|
catch(char *strError)
|
|
{
|
|
WarningMessage("Unable to obtain default texture for new texture layer!\nError: %s", strError);
|
|
}
|
|
break;
|
|
}
|
|
case 4: // "Insert tile layer"
|
|
{
|
|
try
|
|
{
|
|
ptrTerrain->AddLayer_t( CTFILENAME("Textures\\Editor\\Default.tex"), LT_TILE);
|
|
SelectLayer( ptrTerrain->tr_atlLayers.Count()-1);
|
|
}
|
|
catch(char *strError)
|
|
{
|
|
WarningMessage("Unable to obtain default texture for new tile layer!\nError: %s", strError);
|
|
}
|
|
break;
|
|
}
|
|
case 2: // "Move up"
|
|
{
|
|
if(iLayer<ptrTerrain->tr_atlLayers.Count()-1)
|
|
{
|
|
ptrTerrain->SetLayerIndex( iLayer, iLayer+1);
|
|
SelectLayer(iLayer+1);
|
|
}
|
|
break;
|
|
}
|
|
case 3: // "Move down"
|
|
{
|
|
if(iLayer>0)
|
|
{
|
|
ptrTerrain->SetLayerIndex( iLayer, iLayer-1);
|
|
SelectLayer(iLayer-1);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
theApp.m_ctTerrainPage.MarkChanged();
|
|
}
|
|
|
|
void DisplayLayerTexture(INDEX iLayer)
|
|
{
|
|
CWndDisplayTexture *pDisplay=new CWndDisplayTexture;
|
|
|
|
CTerrainLayer *ptlLayer=GetLayer(iLayer);
|
|
if(ptlLayer!=NULL && ptlLayer->tl_ptdTexture!=NULL)
|
|
{
|
|
POINT pt;
|
|
GetCursorPos(&pt);
|
|
CTString strText1=ptlLayer->tl_ptdTexture->GetName();
|
|
CTString strText2=ptlLayer->tl_ptdTexture->GetDescription();
|
|
pDisplay->Initialize(pt.x, pt.y, ptlLayer->tl_ptdTexture, strText1, strText2);
|
|
}
|
|
}
|
|
|
|
void ApplyLayerTextureCommand(INDEX iSelectedItem)
|
|
{
|
|
CTerrain *ptrTerrain=GetTerrain();
|
|
if( ptrTerrain==NULL) return;
|
|
CTerrainLayer *ptlLayer=GetLayer();
|
|
INDEX iLayer=GetLayerIndex();
|
|
if(ptlLayer!=NULL)
|
|
{
|
|
switch( iSelectedItem)
|
|
{
|
|
case 0: // "Create izohipse textutre"
|
|
{
|
|
CTFileName fnGradient=_EngineGUI.FileRequester(
|
|
"Select izohipse gradient", FILTER_TEX FILTER_ALL FILTER_END,
|
|
"Texture directory", "Textures\\");
|
|
if( fnGradient=="") return;
|
|
|
|
CTextureData *ptdGradient;
|
|
try
|
|
{
|
|
ptdGradient=_pTextureStock->Obtain_t( fnGradient);
|
|
ptdGradient->Force(TEX_STATIC|TEX_CONSTANT);
|
|
}
|
|
catch( char *strError)
|
|
{
|
|
(void) strError;
|
|
WarningMessage("Unable to obtain izohipse gradient texture!");
|
|
return;
|
|
}
|
|
|
|
CTFileName fnIzohipseTexture=_EngineGUI.FileRequester(
|
|
"Choose name for izohipse texture", FILTER_TEX FILTER_ALL FILTER_END,
|
|
"Texture directory", "Textures\\");
|
|
if( fnIzohipseTexture=="") return;
|
|
|
|
INDEX iHMWidth=ptrTerrain->tr_pixHeightMapWidth;
|
|
INDEX iHMHeight=ptrTerrain->tr_pixHeightMapHeight;
|
|
CImageInfo ii;
|
|
ii.ii_Width=iHMWidth-1;
|
|
ii.ii_Height=iHMHeight-1;
|
|
ii.ii_BitsPerPixel=32;
|
|
ii.ii_Picture=(UBYTE*) AllocMemory(ii.ii_Width*ii.ii_Height*ii.ii_BitsPerPixel/8);
|
|
COLOR *pcol=(COLOR *)ii.ii_Picture;
|
|
|
|
INDEX iGradientHeight=ptdGradient->GetPixHeight();
|
|
UWORD *puw=ptrTerrain->tr_auwHeightMap;
|
|
if(puw==NULL) return;
|
|
for( INDEX iy=0; iy<ii.ii_Height; iy++)
|
|
{
|
|
for( INDEX ix=0; ix<ii.ii_Width; ix++)
|
|
{
|
|
UWORD uwHeight=*(puw+iy*iHMWidth+ix);
|
|
FLOAT fHeightRatio=uwHeight/65535.0f;
|
|
INDEX iGradPix1=iGradientHeight*fHeightRatio;
|
|
INDEX iGradPix2=ClampUp(iGradPix1+1,iGradientHeight-1);
|
|
COLOR colPix1=ptdGradient->GetTexel(0,iGradPix1);
|
|
COLOR colPix2=ptdGradient->GetTexel(0,iGradPix2);
|
|
FLOAT fLerpFactor=iGradientHeight*fHeightRatio-INDEX(iGradientHeight*fHeightRatio);
|
|
COLOR colResult=LerpColor(colPix1,colPix2,fLerpFactor);
|
|
*(pcol+iy*ii.ii_Width+ix)=ByteSwap(colResult);
|
|
}
|
|
}
|
|
_pTextureStock->Release(ptdGradient);
|
|
|
|
CTextureData tdIzohipse;
|
|
try
|
|
{
|
|
tdIzohipse.Create_t( &ii, 1024, 16, TRUE);
|
|
tdIzohipse.Save_t( fnIzohipseTexture);
|
|
ptlLayer->SetLayerTexture_t(fnIzohipseTexture);
|
|
ptlLayer->tl_fStretchX=1.0f/ptrTerrain->tr_vTerrainSize(1);
|
|
ptlLayer->tl_fStretchY=1.0f/ptrTerrain->tr_vTerrainSize(2);
|
|
}
|
|
catch( char *strError)
|
|
{
|
|
(void) strError;
|
|
WarningMessage("Unable to save izohipse texture!");
|
|
return;
|
|
}
|
|
ptrTerrain->RefreshTerrain();
|
|
theApp.m_ctTerrainPage.MarkChanged();
|
|
break;
|
|
}
|
|
case 1: // "Browse texture"
|
|
{
|
|
CTFileName fnTexture=_EngineGUI.FileRequester(
|
|
"Browse texture", FILTER_TEX FILTER_ALL FILTER_END,
|
|
"Texture directory", "Textures\\");
|
|
if( fnTexture=="") return;
|
|
|
|
try
|
|
{
|
|
ptlLayer->SetLayerTexture_t(fnTexture);
|
|
theApp.m_ctTerrainPageCanvas.MarkChanged();
|
|
ptrTerrain->RefreshTerrain();
|
|
}
|
|
catch(char *strError)
|
|
{
|
|
(void) strError;
|
|
}
|
|
break;
|
|
}
|
|
case 2: // "View layer texture"
|
|
{
|
|
DisplayLayerTexture(iLayer);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void DisplayLayerMask(INDEX iLayer)
|
|
{
|
|
CWndDisplayTexture *pDisplay=new CWndDisplayTexture;
|
|
|
|
CTerrainLayer *ptlLayer=GetLayer(iLayer);
|
|
if(ptlLayer!=NULL && ptlLayer->tl_ptdTexture!=NULL)
|
|
{
|
|
CTextureData *ptd=ptlLayer->GetThumbnail(ptlLayer->tl_iMaskWidth-1,ptlLayer->tl_iMaskHeight-1);
|
|
|
|
POINT pt;
|
|
GetCursorPos(&pt);
|
|
|
|
CTString strText1;
|
|
strText1.PrintF("%dx%d",ptlLayer->tl_iMaskWidth-1, ptlLayer->tl_iMaskHeight-1);
|
|
pDisplay->Initialize(pt.x, pt.y, ptd, strText1);
|
|
}
|
|
}
|
|
|
|
void ApplyLayerMaskCommand(INDEX iSelectedItem)
|
|
{
|
|
CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
|
|
CTerrain *ptrTerrain=GetTerrain();
|
|
if( ptrTerrain==NULL) return;
|
|
CTerrainLayer *ptlLayer=GetLayer();
|
|
INDEX iLayer=GetLayerIndex();
|
|
if(ptlLayer!=NULL)
|
|
{
|
|
switch( iSelectedItem)
|
|
{
|
|
case 0: // "Fill mask"
|
|
{
|
|
if( ::MessageBoxA( pMainFrame->m_hWnd, "Are you sure that you want to fill this layer's mask?",
|
|
"Warning !", MB_YESNO | MB_ICONWARNING | MB_DEFBUTTON1| MB_SYSTEMMODAL | MB_TOPMOST) == IDYES)
|
|
{
|
|
EditTerrain(NULL, FLOAT3D(0,0,0), 1.0f, TE_FILL_LAYER_MASK);
|
|
}
|
|
break;
|
|
}
|
|
case 1: // "Clear mask"
|
|
{
|
|
if( ::MessageBoxA( pMainFrame->m_hWnd, "Are you sure that you want to clear this layer's mask?",
|
|
"Warning !", MB_YESNO | MB_ICONWARNING | MB_DEFBUTTON1| MB_SYSTEMMODAL | MB_TOPMOST) == IDYES)
|
|
{
|
|
EditTerrain(NULL, FLOAT3D(0,0,0), 1.0f, TE_CLEAR_LAYER_MASK);
|
|
}
|
|
break;
|
|
}
|
|
case 2: // "Import mask"
|
|
{
|
|
CTFileName fnMaskMap=_EngineGUI.FileRequester(
|
|
"Import layer mask", FILTER_TGA FILTER_PCX FILTER_ALL FILTER_END,
|
|
"Layer mask directory", "Textures\\");
|
|
if( fnMaskMap=="") return;
|
|
try
|
|
{
|
|
ptlLayer->ImportLayerMask_t(fnMaskMap);
|
|
ptrTerrain->RefreshTerrain();
|
|
pMainFrame->Invalidate(FALSE);
|
|
theApp.GetActiveDocument()->SetModifiedFlag( TRUE);
|
|
}
|
|
catch(char *strError)
|
|
{
|
|
AfxMessageBox( CString(strError));
|
|
}
|
|
break;
|
|
}
|
|
case 3: // "Export mask"
|
|
{
|
|
CTFileName fnMaskMap=_EngineGUI.FileRequester(
|
|
"Export layer mask", FILTER_TGA FILTER_PCX FILTER_ALL FILTER_END,
|
|
"Layer mask directory", "Textures\\");
|
|
if( fnMaskMap=="") return;
|
|
try
|
|
{
|
|
ptlLayer->ExportLayerMask_t(fnMaskMap);
|
|
ptrTerrain->RefreshTerrain();
|
|
pMainFrame->Invalidate(FALSE);
|
|
}
|
|
catch(char *strError)
|
|
{
|
|
AfxMessageBox( CString(strError));
|
|
}
|
|
break;
|
|
}
|
|
case 4: // noise
|
|
{
|
|
EditTerrain(NULL, FLOAT3D(0,0,0), 1.0f, TE_LAYER_RND_NOISE);
|
|
break;
|
|
}
|
|
case 5: // "View mask"
|
|
{
|
|
DisplayLayerMask(iLayer);
|
|
}
|
|
}
|
|
theApp.m_ctTerrainPageCanvas.MarkChanged();
|
|
}
|
|
}
|
|
|
|
void PickLayerColor(CTIButton *ptib, CPoint pt, CDrawPort *pdp)
|
|
{
|
|
INDEX iLayer=ptib->tib_iLayer;
|
|
CTerrainLayer *ptlLayer=GetLayer(iLayer);
|
|
if(ptlLayer==NULL) return;
|
|
|
|
CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
|
|
COLORREF colMfc=CLRF_CLR( ptlLayer->tl_colMultiply);
|
|
if( MyChooseColor( colMfc, *pMainFrame))
|
|
{
|
|
ptlLayer->tl_colMultiply=CLR_CLRF( colMfc) | ptlLayer->tl_colMultiply&0x000000FF;
|
|
}
|
|
}
|
|
|
|
void NumericAlpha(CTIButton *ptib, CPoint pt, CDrawPort *pdp)
|
|
{
|
|
INDEX iLayer=ptib->tib_iLayer;
|
|
CTerrainLayer *ptlLayer=GetLayer(iLayer);
|
|
if(ptlLayer==NULL) return;
|
|
|
|
CDlgNumericAlpha dlgNumericAlpha( ptlLayer->tl_colMultiply&0xFF);
|
|
if( dlgNumericAlpha.DoModal() == IDOK)
|
|
{
|
|
ptlLayer->tl_colMultiply&=0xFFFFFF00;
|
|
ptlLayer->tl_colMultiply|=(dlgNumericAlpha.m_iAlpha&0xFF);
|
|
}
|
|
}
|
|
|
|
void InvokeLayerOptions(CTIButton *ptib, CPoint pt, CDrawPort *pdp)
|
|
{
|
|
INDEX iLayer=ptib->tib_iLayer;
|
|
if(iLayer==-1) return;
|
|
|
|
CDlgEditTerrainLayer dlg;
|
|
if( dlg.DoModal()==IDOK)
|
|
{
|
|
GenerateLayerDistribution(iLayer);
|
|
}
|
|
}
|
|
|
|
void PickSelectedLayerBcgColor(CTIButton *ptib, CPoint pt, CDrawPort *pdp)
|
|
{
|
|
PointToScreenSpace(pt, pdp);
|
|
CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
|
|
pMainFrame->CustomColorPicker( pt.x-50, pt.y);
|
|
|
|
COLORREF TmpColor = CLRF_CLR( _colSelectedLayerBcg);
|
|
if( MyChooseColor( TmpColor, *pMainFrame))
|
|
{
|
|
_colSelectedLayerBcg = CLR_CLRF( TmpColor)|CT_OPAQUE;
|
|
}
|
|
theApp.m_ctTerrainPageCanvas.MarkChanged();
|
|
}
|
|
|
|
INDEX InsertItemMacro( CCustomComboWnd *pCC, CTString strText, INDEX iIcon=-1, INDEX iValue=-1, COLOR col=COL_DEFAULT_ITEM)
|
|
{
|
|
INDEX iItem;
|
|
if(iIcon!=-1)
|
|
{
|
|
MEXaabbox2D boxIcon=MEXaabbox2D( MEX2D(16*iIcon,0), MEX2D(16*iIcon+16,16));
|
|
DECLARE_CTFILENAME( fnTerrainEditIcons, "Textures\\Editor\\TerrainEditingIcons.tex");
|
|
iItem=pCC->InsertItem( strText, fnTerrainEditIcons, boxIcon);
|
|
}
|
|
else
|
|
{
|
|
iItem=pCC->InsertItem( strText);
|
|
}
|
|
|
|
if(iValue!=-1)
|
|
{
|
|
pCC->SetItemValue(iItem, iValue);
|
|
}
|
|
|
|
pCC->SetItemColor( iItem, col);
|
|
return iItem;
|
|
}
|
|
|
|
void InvokeLayerPopup(CTIButton *ptib, CPoint pt, CDrawPort *pdp)
|
|
{
|
|
CTerrain *ptrTerrain=GetTerrain();
|
|
if( ptrTerrain==NULL) return;
|
|
|
|
CCustomComboWnd *pCombo=new CCustomComboWnd;
|
|
InsertItemMacro( pCombo, "Delete layer", -1, 0);
|
|
InsertItemMacro( pCombo, "Insert texture layer", -1, 1);
|
|
InsertItemMacro( pCombo, "Insert tile layer", -1, 4);
|
|
InsertItemMacro( pCombo, "Move up", -1, 2);
|
|
InsertItemMacro( pCombo, "Move down", -1, 3);
|
|
|
|
PointToScreenSpace(pt, pdp);
|
|
pCombo->Initialize(NULL, ApplyLayerCommand, pt.x, pt.y);
|
|
}
|
|
|
|
void InvokeLayerTexturePopup(CTIButton *ptib, CPoint pt, CDrawPort *pdp)
|
|
{
|
|
CTerrain *ptrTerrain=GetTerrain();
|
|
if( ptrTerrain==NULL) return;
|
|
|
|
CCustomComboWnd *pCombo=new CCustomComboWnd;
|
|
InsertItemMacro( pCombo, "Create izohipse texture", 22, 0);
|
|
InsertItemMacro( pCombo, "Browse texture", 22, 1);
|
|
InsertItemMacro( pCombo, "View layer texture", 3, 2);
|
|
PointToScreenSpace(pt, pdp);
|
|
pCombo->Initialize(NULL, ApplyLayerTextureCommand, pt.x, pt.y);
|
|
}
|
|
|
|
void InvokeLayerMaskPopup(CTIButton *ptib, CPoint pt, CDrawPort *pdp)
|
|
{
|
|
CTerrain *ptrTerrain=GetTerrain();
|
|
if( ptrTerrain==NULL) return;
|
|
|
|
CCustomComboWnd *pCombo=new CCustomComboWnd;
|
|
InsertItemMacro( pCombo, "Fill mask", 17, 0);
|
|
InsertItemMacro( pCombo, "Clear mask", 9, 1);
|
|
InsertItemMacro( pCombo, "Noise", 12, 4);
|
|
InsertItemMacro( pCombo, "--------------",-1,-1);
|
|
InsertItemMacro( pCombo, "Import mask", 22, 2);
|
|
InsertItemMacro( pCombo, "Export mask", 22, 3);
|
|
InsertItemMacro( pCombo, "--------------",-1,-1);
|
|
InsertItemMacro( pCombo, "View mask", 3, 5);
|
|
|
|
PointToScreenSpace(pt, pdp);
|
|
pCombo->Initialize(NULL, ApplyLayerMaskCommand, pt.x, pt.y);
|
|
}
|
|
|
|
CTString GetStretchInfo(CTIButton *ptib, CPoint pt, CDrawPort *pdp, BOOL bLmb)
|
|
{
|
|
CTString strInfo;
|
|
INDEX iLayer=ptib->tib_iLayer;
|
|
if( iLayer!=-1)
|
|
{
|
|
CTerrainLayer *ptlLayer=GetLayer(iLayer);
|
|
CTerrain *ptrTerrain=GetTerrain();
|
|
if(ptlLayer!=NULL && ptrTerrain!=NULL)
|
|
{
|
|
strInfo.PrintF("Texture stretch: %g", ptlLayer->tl_fStretchX);
|
|
return strInfo;
|
|
}
|
|
}
|
|
return strInfo;
|
|
}
|
|
|
|
CTString GetEditedData(CTIButton *ptib, CPoint pt, CDrawPort *pdp, BOOL bLmb)
|
|
{
|
|
CTString strInfo;
|
|
if(ptib->tib_pfData1!=NULL) strInfo.PrintF("%f", ptib->tib_pfData1);
|
|
return strInfo;
|
|
}
|
|
|
|
void OnDropIntoLayerTexture(CTIButton *ptib, CPoint pt, CDrawPort *pdp, CTFileName fnDropped)
|
|
{
|
|
// if it is not texture, report error
|
|
if( fnDropped.FileExt() != ".tex" )
|
|
{
|
|
AfxMessageBox( L"You can only drop textures here.");
|
|
return;
|
|
}
|
|
|
|
INDEX iLayer=ptib->tib_iLayer;
|
|
CTerrainLayer *ptlLayer=GetLayer(iLayer);
|
|
CTerrain *ptrTerrain=GetTerrain();
|
|
if(ptlLayer!=NULL && ptrTerrain!=NULL)
|
|
{
|
|
ASSERT(ptlLayer->tl_ptdTexture!=NULL);
|
|
CTFileName fnOldTexture=CTFILENAME("Textures\\Editor\\Default.tex");
|
|
if(ptlLayer->tl_ptdTexture!=NULL)
|
|
{
|
|
fnOldTexture=ptlLayer->tl_ptdTexture->GetName();
|
|
}
|
|
BOOL bSetOldTexture=TRUE;
|
|
try
|
|
{
|
|
fnDropped.RemoveApplicationPath_t();
|
|
ptlLayer->SetLayerTexture_t(fnDropped);
|
|
bSetOldTexture=FALSE;
|
|
theApp.m_ctTerrainPageCanvas.MarkChanged();
|
|
ptrTerrain->RefreshTerrain();
|
|
}
|
|
catch(char *strError)
|
|
{
|
|
(void) strError;
|
|
}
|
|
|
|
// if should restore old texture
|
|
if(bSetOldTexture)
|
|
{
|
|
try
|
|
{
|
|
ptlLayer->SetLayerTexture_t(fnOldTexture);
|
|
}
|
|
catch(char *strError)
|
|
{
|
|
(void) strError;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void ToggleLayerVisibleFlag(CTIButton *ptib, CPoint pt, CDrawPort *pdp)
|
|
{
|
|
INDEX iLayer=ptib->tib_iLayer;
|
|
if( iLayer!=-1)
|
|
{
|
|
CTerrainLayer *ptlLayer=GetLayer(iLayer);
|
|
if(ptlLayer!=NULL)
|
|
{
|
|
ptlLayer->tl_bVisible=!ptlLayer->tl_bVisible;
|
|
CTerrain *ptrTerrain=GetTerrain();
|
|
ptrTerrain->RefreshTerrain();
|
|
}
|
|
}
|
|
}
|
|
|
|
void ToggleFlag(CTIButton *ptib, CPoint pt, CDrawPort *pdp)
|
|
{
|
|
INDEX iLayer=ptib->tib_iLayer;
|
|
if( iLayer!=-1)
|
|
{
|
|
CTerrainLayer *ptlLayer=GetLayer(iLayer);
|
|
if(ptlLayer!=NULL)
|
|
{
|
|
BOOL bOldValue=*(BOOL*)((UBYTE*)ptlLayer+(ULONG)ptib->tib_pfData1);
|
|
bOldValue=!bOldValue;
|
|
*(BOOL*)((UBYTE*)ptlLayer+(ULONG)ptib->tib_pfData1)=bOldValue;
|
|
}
|
|
}
|
|
}
|
|
|
|
BOOL DisableIfNoTerrainSelected(CTIButton *ptib)
|
|
{
|
|
CTerrain *ptrTerrain=GetTerrain();
|
|
return ptrTerrain!=NULL;
|
|
}
|
|
|
|
CTString GetNormalizedPercentageInfo(CTIButton *ptib, CPoint pt, CDrawPort *pdp, BOOL bLmb)
|
|
{
|
|
CTString strInfo;
|
|
INDEX iLayer=ptib->tib_iLayer;
|
|
if( iLayer!=-1)
|
|
{
|
|
CTerrainLayer *ptlLayer=GetLayer(iLayer);
|
|
if(ptlLayer!=NULL)
|
|
{
|
|
FLOAT *pfNormalized=(FLOAT *)((UBYTE*)ptlLayer+(ULONG)ptib->tib_pfData1);
|
|
FLOAT fValue=*pfNormalized;
|
|
strInfo.PrintF("%s: %d%%", ptib->tib_strToolTip, INDEX(floor(fValue*100.0f+0.5f)));
|
|
return strInfo;
|
|
}
|
|
}
|
|
return strInfo;
|
|
}
|
|
|
|
void ChangeLayerDistributionData(CTIButton *ptib, FLOAT fdx, FLOAT fdy, CDrawPort *pdp)
|
|
{
|
|
if( ptib->tib_pfData1==NULL) return;
|
|
INDEX iLayer=ptib->tib_iLayer;
|
|
if( iLayer==-1) return;
|
|
CTerrainLayer *ptlLayer=GetLayer(iLayer);
|
|
if(ptlLayer==NULL) return;
|
|
|
|
FLOAT *pfNormalized=(FLOAT *)((UBYTE*)ptlLayer+(ULONG)ptib->tib_pfData1);
|
|
FLOAT fOldValue=*pfNormalized;
|
|
FLOAT fAddX=ptib->tib_fDataDelta*fdx;
|
|
FLOAT fNewValue=Clamp( fOldValue+fAddX, 0.0f, 1.0f);
|
|
*pfNormalized=fNewValue;
|
|
|
|
_iGenerateForLayer=iLayer;
|
|
_chAutoGenerateDistribution.MarkChanged();
|
|
}
|
|
|
|
void ChangeData(CTIButton *ptib, FLOAT fdx, FLOAT fdy, CDrawPort *pdp)
|
|
{
|
|
if( ptib->tib_pfData1!=NULL)
|
|
{
|
|
FLOAT fData=*ptib->tib_pfData1;
|
|
FLOAT fAdd=ptib->tib_fDataDelta*fdx;
|
|
if((fData+fAdd)>=ptib->tib_fDataMax)
|
|
{
|
|
if(ptib->tib_bWrapData)
|
|
{
|
|
fData=ptib->tib_fDataMin+((fData+fAdd)-ptib->tib_fDataMax);
|
|
}
|
|
else
|
|
{
|
|
fData=ptib->tib_fDataMax;
|
|
}
|
|
}
|
|
else if((fData+fAdd)<=ptib->tib_fDataMin)
|
|
{
|
|
if(ptib->tib_bWrapData)
|
|
{
|
|
fData=ptib->tib_fDataMax+(fData+fAdd);
|
|
}
|
|
else
|
|
{
|
|
fData=ptib->tib_fDataMin;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fData=fData+fAdd;
|
|
}
|
|
*ptib->tib_pfData1=fData;
|
|
}
|
|
}
|
|
|
|
void ChangeTextureRotation(CTIButton *ptib, FLOAT fdx, FLOAT fdy, CDrawPort *pdp)
|
|
{
|
|
INDEX iLayer=ptib->tib_iLayer;
|
|
if( iLayer!=-1)
|
|
{
|
|
CTerrainLayer *ptlLayer=GetLayer(iLayer);
|
|
if(ptlLayer!=NULL)
|
|
{
|
|
FLOAT fAdd=CHANGE_ANGLE_SENSITIVITY*fdx;
|
|
ptlLayer->tl_fRotateX+=fAdd;
|
|
ptlLayer->tl_fRotateY+=fAdd;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ChangeTextureOffset(CTIButton *ptib, FLOAT fdx, FLOAT fdy, CDrawPort *pdp)
|
|
{
|
|
INDEX iLayer=ptib->tib_iLayer;
|
|
if( iLayer!=-1)
|
|
{
|
|
CTerrainLayer *ptlLayer=GetLayer(iLayer);
|
|
if(ptlLayer!=NULL)
|
|
{
|
|
FLOAT fAddX=CHANGE_OFFSET_SENSITIVITY*fdx;
|
|
FLOAT fAddY=CHANGE_OFFSET_SENSITIVITY*fdy;
|
|
ptlLayer->tl_fOffsetX+=fAddX;
|
|
ptlLayer->tl_fOffsetY+=fAddY;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ChangeTextureStretch(CTIButton *ptib, FLOAT fdx, FLOAT fdy, CDrawPort *pdp)
|
|
{
|
|
INDEX iLayer=ptib->tib_iLayer;
|
|
if( iLayer!=-1)
|
|
{
|
|
CTerrainLayer *ptlLayer=GetLayer(iLayer);
|
|
CTerrain *ptrTerrain=GetTerrain();
|
|
if(ptlLayer!=NULL && ptrTerrain!=NULL)
|
|
{
|
|
if(fdx>=CHANGE_STRETCH_SENSITIVITY)
|
|
{
|
|
ptlLayer->tl_fStretchX/=2;
|
|
ptlLayer->tl_fStretchY/=2;
|
|
ptrTerrain->RefreshTerrain();
|
|
}
|
|
else if(fdx<=-CHANGE_STRETCH_SENSITIVITY)
|
|
{
|
|
ptlLayer->tl_fStretchX*=2;
|
|
ptlLayer->tl_fStretchY*=2;
|
|
ptrTerrain->RefreshTerrain();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void OnSelectBrush(INDEX iSelectedItem)
|
|
{
|
|
if( iSelectedItem>=0 && iSelectedItem<CT_BRUSH_MODES)
|
|
{
|
|
theApp.m_iTerrainBrushMode=iSelectedItem;
|
|
theApp.m_ctTerrainPageCanvas.MarkChanged();
|
|
theApp.GetDocument()->SetStatusLineModeInfoMessage();
|
|
}
|
|
else if(iSelectedItem==-1)
|
|
{
|
|
CTerrain *ptrTerrain=GetTerrain();
|
|
if( ptrTerrain==NULL) return;
|
|
|
|
CDlgEditFloat dlg;
|
|
dlg.m_fEditFloat=theApp.m_fPosterizeStep;
|
|
dlg.m_strVarName = "Posterize step (m)";
|
|
dlg.m_strTitle = "Enter posterize step";
|
|
if(dlg.DoModal()!=IDOK) return;
|
|
theApp.m_fPosterizeStep=dlg.m_fEditFloat;
|
|
}
|
|
// auto update terrain distribution flag
|
|
else if(iSelectedItem==50)
|
|
{
|
|
theApp.m_Preferences.ap_bAutoUpdateTerrainDistribution=!theApp.m_Preferences.ap_bAutoUpdateTerrainDistribution;
|
|
}
|
|
// settings
|
|
else if(iSelectedItem==100)
|
|
{
|
|
CDlgTEOperationSettings dlg;
|
|
dlg.DoModal();
|
|
}
|
|
}
|
|
|
|
void InvokeBrushModeCombo(CTIButton *ptib, CPoint pt, CDrawPort *pdp)
|
|
{
|
|
PointToScreenSpace(pt, pdp);
|
|
CCustomComboWnd *pCombo=new CCustomComboWnd;
|
|
INDEX iFlag=6;
|
|
if(theApp.m_Preferences.ap_bAutoUpdateTerrainDistribution)
|
|
{
|
|
iFlag=7;
|
|
}
|
|
InsertItemMacro( pCombo, "Auto update layer distribution", iFlag, 50, COL_SETTINGS);
|
|
InsertItemMacro( pCombo, "---------------------------------", -1, -1, COL_SEPARATOR);
|
|
for(INDEX iMode=0; iMode<CT_BRUSH_MODES; iMode++)
|
|
{
|
|
INDEX iIcon;
|
|
CTString strText;
|
|
GetBrushModeInfo(iMode, iIcon, strText);
|
|
InsertItemMacro( pCombo, strText, iIcon, iMode);
|
|
}
|
|
|
|
InsertItemMacro( pCombo, "---------------------------------", -1, -1, COL_SEPARATOR);
|
|
InsertItemMacro( pCombo, "Operation settings (Ctrl+Shift+P)", 26, 100, COL_SETTINGS);
|
|
|
|
pCombo->Initialize(NULL, OnSelectBrush, pt.x, pt.y);
|
|
}
|
|
|
|
void InvokePercentageCombo(CTIButton *ptib, CPoint pt, CDrawPort *pdp)
|
|
{
|
|
PointToScreenSpace(pt, pdp);
|
|
CCustomComboWnd *pCombo=new CCustomComboWnd;
|
|
for( INDEX i=1; i<11; i++)
|
|
{
|
|
CTString strText;
|
|
strText.PrintF("%d", i*10);
|
|
pCombo->InsertItem( strText);
|
|
}
|
|
pCombo->Initialize(&theApp.m_fTerrainBrushPressureEnum, NULL, pt.x, pt.y);
|
|
}
|
|
|
|
void InvokeEditModeCombo(CTIButton *ptib, CPoint pt, CDrawPort *pdp)
|
|
{
|
|
PointToScreenSpace(pt, pdp);
|
|
CCustomComboWnd *pCombo=new CCustomComboWnd;
|
|
InsertItemMacro( pCombo, "Altitude (U)", 20);
|
|
InsertItemMacro( pCombo, "Texture (L)", 19);
|
|
pCombo->Initialize(&theApp.m_iTerrainEditMode, NULL, pt.x, pt.y);
|
|
}
|
|
|
|
void NextEnum(CTIButton *ptib, CPoint pt)
|
|
{
|
|
ChangeData(ptib, 1, 0, NULL);
|
|
}
|
|
|
|
FLOAT GetMaxSliderPos(CDrawPort *pdp)
|
|
{
|
|
CTerrain *ptrTerrain=GetTerrain();
|
|
if( ptrTerrain==NULL) return 0;
|
|
FLOAT fMaxPos=ClampDn(ptrTerrain->tr_atlLayers.Count()*LAYER_HEIGHT-pdp->GetHeight(),PIX(0));
|
|
return fMaxPos;
|
|
}
|
|
|
|
void OnSliderArrowUp(CTIButton *ptib, CPoint pt, CDrawPort *pdp)
|
|
{
|
|
_fScrollLayers=ClampDn(_fScrollLayers-PIX(LAYER_HEIGHT),0.0f);
|
|
}
|
|
|
|
void OnSliderArrowDown(CTIButton *ptib, CPoint pt, CDrawPort *pdp)
|
|
{
|
|
_fScrollLayers=ClampUp(_fScrollLayers+PIX(LAYER_HEIGHT),GetMaxSliderPos(pdp));
|
|
}
|
|
|
|
void RenderLayerColor(CTIButton *ptib, CDrawPort *pdp)
|
|
{
|
|
INDEX iLayer=ptib->tib_iLayer;
|
|
CTerrainLayer *ptlLayer=GetLayer(iLayer);
|
|
if(ptlLayer==NULL) return;
|
|
|
|
PIXaabbox2D box=GetButtonScreenBox(*ptib);
|
|
pdp->Fill(box.Min()(1), box.Min()(2), box.Size()(1), box.Size()(2), ptlLayer->tl_colMultiply);
|
|
}
|
|
|
|
void RenderSlider(CTIButton *ptib, CDrawPort *pdp)
|
|
{
|
|
FLOAT fMaxPos=GetMaxSliderPos(pdp);
|
|
PIX pixSliderY=FLOAT(ptib->tib_fdy-SLIDER_HOLDER_HEIGHT/2)/fMaxPos*_fScrollLayers;
|
|
pixSliderY=ClampDn<PIX>(pixSliderY-SLIDER_HOLDER_HEIGHT/2, 0);
|
|
pdp->Fill(ptib->tib_fx, ptib->tib_fy+pixSliderY, ptib->tib_fdx-2, SLIDER_HOLDER_HEIGHT, C_mlGRAY|CT_OPAQUE);
|
|
}
|
|
|
|
void OnSliderClick(CTIButton *ptib, CPoint pt, CDrawPort *pdp)
|
|
{
|
|
FLOAT fMaxPos=GetMaxSliderPos(pdp);
|
|
PointToIconSpace(pt, ptib);
|
|
pt.y=ClampUp( pt.y, INDEX(ptib->tib_fdy-SLIDER_HOLDER_HEIGHT/2));
|
|
if(pt.y<SLIDER_HOLDER_HEIGHT/2) pt.y=0;
|
|
FLOAT fRemapFactor=fMaxPos/(ptib->tib_fdy-SLIDER_HOLDER_HEIGHT);
|
|
FLOAT fSetPos=pt.y*fRemapFactor;
|
|
_fScrollLayers=ClampUp(fSetPos,fMaxPos);
|
|
}
|
|
|
|
void DragSlider(CTIButton *ptib, FLOAT fdx, FLOAT fdy, CDrawPort *pdp/*=NULL*/)
|
|
{
|
|
FLOAT fMaxPos=GetMaxSliderPos(pdp);
|
|
FLOAT fRemapFactor=FLOAT(fMaxPos)/(ptib->tib_fdy-SLIDER_HOLDER_HEIGHT);
|
|
FLOAT fNewPos=_fScrollLayers+fdy*fRemapFactor;
|
|
_fScrollLayers=Clamp( fNewPos, 0.0f, fMaxPos);
|
|
}
|
|
|
|
void RecalculateShadows(CTIButton *ptib, CPoint pt, CDrawPort *pdp)
|
|
{
|
|
RecalculateShadows();
|
|
}
|
|
|
|
void DisplayHeightMap(CTIButton *ptib, CPoint pt, CDrawPort *pdp)
|
|
{
|
|
PointToScreenSpace(pt, pdp);
|
|
DisplayHeightMapWindow( pt);
|
|
}
|
|
|
|
void ApplyTerrainOptions(INDEX iSelectedItem)
|
|
{
|
|
CTerrain *ptrTerrain=GetTerrain();
|
|
if( ptrTerrain==NULL) return;
|
|
|
|
switch(iSelectedItem)
|
|
{
|
|
// invoke properties
|
|
case 0:
|
|
{
|
|
CDlgTerrainProperties dlg;
|
|
dlg.DoModal();
|
|
break;
|
|
}
|
|
// generate terrain
|
|
case 3:
|
|
{
|
|
ApplyGenerateTerrain();
|
|
break;
|
|
}
|
|
// smooth
|
|
case 4:
|
|
{
|
|
ApplySmoothOntoTerrain();
|
|
break;
|
|
}
|
|
// filter
|
|
case 5:
|
|
{
|
|
ApplyFilterOntoTerrain();
|
|
break;
|
|
}
|
|
// add noise
|
|
case 6:
|
|
{
|
|
ApplyRndNoiseOntoTerrain();
|
|
break;
|
|
}
|
|
// equalize
|
|
case 7:
|
|
{
|
|
ApplyEqualizeOntoTerrain();
|
|
break;
|
|
}
|
|
// operation settings
|
|
case 8:
|
|
{
|
|
// option settings
|
|
CDlgTEOperationSettings dlg;
|
|
dlg.DoModal();
|
|
break;
|
|
}
|
|
// posterize
|
|
case 9:
|
|
{
|
|
ApplyPosterizeOntoTerrain();
|
|
break;
|
|
}
|
|
// add continous noise
|
|
case 11:
|
|
{
|
|
ApplyContinousNoiseOntoTerrain();
|
|
break;
|
|
}
|
|
// limit down
|
|
case 12:
|
|
{
|
|
ApplyMinimumOntoTerrain();
|
|
break;
|
|
}
|
|
// limit up
|
|
case 13:
|
|
{
|
|
ApplyMaximumOntoTerrain();
|
|
break;
|
|
}
|
|
// flatten
|
|
case 14:
|
|
{
|
|
ApplyFlattenOntoTerrain();
|
|
break;
|
|
}
|
|
// recalcualte shadows
|
|
case 15:
|
|
{
|
|
ptrTerrain->UpdateShadowMap();
|
|
}
|
|
// generate layer distribution
|
|
case 16:
|
|
{
|
|
GenerateLayerDistribution(-1);
|
|
}
|
|
// optimize layers
|
|
case 17:
|
|
{
|
|
OptimizeLayers();
|
|
}
|
|
// view heightmap
|
|
case 50:
|
|
{
|
|
CPoint pt;
|
|
GetCursorPos( &pt);
|
|
DisplayHeightMapWindow( pt);
|
|
}
|
|
}
|
|
}
|
|
|
|
void InvokeTerrainOptions(CTIButton *ptib, CPoint pt, CDrawPort *pdp)
|
|
{
|
|
CTerrain *ptrTerrain=GetTerrain();
|
|
if( ptrTerrain==NULL) return;
|
|
|
|
CCustomComboWnd *pCombo=new CCustomComboWnd;
|
|
INDEX iItem=0;
|
|
InsertItemMacro( pCombo, "Terrain properties (Ctrl+Shift+T)",2,0);
|
|
InsertItemMacro( pCombo, "------------------------------------", -1, -1, COL_SEPARATOR);
|
|
InsertItemMacro( pCombo, "Generate terrain (Ctrl+Shift+G)",25, 3);
|
|
InsertItemMacro( pCombo, "Equalize (Ctrl+Shift+E)",1,7);
|
|
InsertItemMacro( pCombo, "------------------------------------", -1, -1, COL_SEPARATOR);
|
|
InsertItemMacro( pCombo, "Recalculate shadows (Ctrl+Shift+R)",5, 15);
|
|
InsertItemMacro( pCombo, "Generate layer distribution (Ctrl+G)",19, 16);
|
|
InsertItemMacro( pCombo, "Optimize layers (Ctrl+Shift+Z)",25, 17);
|
|
InsertItemMacro( pCombo, "------------------------------------", -1, -1, COL_SEPARATOR);
|
|
InsertItemMacro( pCombo, "Smooth (Ctrl+Shift+O)",10,4);
|
|
InsertItemMacro( pCombo, "Filter (Ctrl+Shift+F)",30,5);
|
|
InsertItemMacro( pCombo, "Limit down (Ctrl+Shift+M)",27,12);
|
|
InsertItemMacro( pCombo, "Limit up (Ctrl+Shift+X)",11,13);
|
|
InsertItemMacro( pCombo, "Flatten (Ctrl+Shift+N)",18,14);
|
|
InsertItemMacro( pCombo, "Posterize",28,9);
|
|
InsertItemMacro( pCombo, "Random noise (Ctrl+Shift+K)",21,6);
|
|
InsertItemMacro( pCombo, "Texture noise (Ctrl+Shift+Y)",31,11);
|
|
InsertItemMacro( pCombo, "------------------------------------", -1, -1,COL_SEPARATOR);
|
|
InsertItemMacro( pCombo, "View height map ", 26, 50);
|
|
InsertItemMacro( pCombo, "Operation settings (Ctrl+Shift+P)", 26, 8, COL_SETTINGS);
|
|
PointToScreenSpace(pt, pdp);
|
|
pCombo->Initialize(NULL, ApplyTerrainOptions, pt.x, pt.y);
|
|
}
|
|
|
|
void DisplayHeightMapWindow(CPoint pt)
|
|
{
|
|
CTextureData tdHeightMap;
|
|
CImageInfo ii;
|
|
|
|
CTerrain *ptrTerrain=GetTerrain();
|
|
if( ptrTerrain==NULL) return;
|
|
|
|
PIX pixW=ptrTerrain->tr_pixHeightMapWidth;
|
|
PIX pixH=ptrTerrain->tr_pixHeightMapHeight;
|
|
if(ptrTerrain->tr_auwHeightMap==NULL) return;
|
|
ii.ii_BitsPerPixel=32;
|
|
ii.ii_Width=pixW-1;
|
|
ii.ii_Height=pixH-1;
|
|
ii.ii_Picture=(UBYTE*)AllocMemory((pixW-1)*(pixH-1)*sizeof(COLOR));
|
|
COLOR *pcol=(COLOR *)ii.ii_Picture;
|
|
|
|
for( INDEX iy=0; iy<pixH-1; iy++)
|
|
{
|
|
for( INDEX ix=0; ix<pixW-1; ix++)
|
|
{
|
|
UWORD *pdest=ptrTerrain->tr_auwHeightMap+iy*pixW+ix;
|
|
UWORD uw=*pdest;
|
|
FLOAT fPix=uw/256.0f;
|
|
UBYTE ubR=UBYTE(fPix);
|
|
COLOR col=RGBToColor(ubR,ubR,ubR)|CT_OPAQUE;
|
|
col=RGBToColor(ubR,ubR,ubR)|CT_OPAQUE;
|
|
*(pcol+iy*(pixW-1)+ix)=ByteSwap(col);
|
|
}
|
|
}
|
|
|
|
try
|
|
{
|
|
tdHeightMap.Create_t( &ii, pixW-1, 16, TRUE);
|
|
CTString strHeightMap="Temp\\ViewHeightMap.tex";
|
|
tdHeightMap.Save_t( strHeightMap);
|
|
|
|
CTextureData *ptd;
|
|
ptd=_pTextureStock->Obtain_t( strHeightMap);
|
|
ptd->Reload();
|
|
CWndDisplayTexture *pDisplay=new CWndDisplayTexture;
|
|
pDisplay->Initialize(pt.x, pt.y, ptd);
|
|
}
|
|
catch( char *strError)
|
|
{
|
|
(void) strError;
|
|
WarningMessage("Unable to display height map!");
|
|
}
|
|
}
|
|
|
|
void OnSelectLoadSave(INDEX iSelectedItem)
|
|
{
|
|
switch( iSelectedItem)
|
|
{
|
|
case 0:
|
|
case 1:
|
|
case 2:
|
|
case 3:
|
|
{
|
|
ApplyImportExport(iSelectedItem);
|
|
}
|
|
case 4: // "Load surface"
|
|
{
|
|
CTFileName fnSurface=_EngineGUI.FileRequester(
|
|
"Load surface", "Surfaces (*.sfc)\0*.sfc\0" FILTER_ALL FILTER_END,
|
|
"Surface directory", "Surfaces\\");
|
|
if( fnSurface=="") return;
|
|
LoadSurface(fnSurface);
|
|
break;
|
|
}
|
|
case 5: // "Save surface"
|
|
{
|
|
CTFileName fnSurface=_EngineGUI.FileRequester(
|
|
"Save surface", "Surfaces (*.sfc)\0*.sfc\0" FILTER_ALL FILTER_END,
|
|
"Surface directory", "Surfaces\\");
|
|
if( fnSurface=="") return;
|
|
SaveSurface(fnSurface);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ApplyImportExport(INDEX iOperation)
|
|
{
|
|
CTerrain *ptrTerrain=GetTerrain();
|
|
if( ptrTerrain==NULL) return;
|
|
|
|
CTFileName fnHeightmap;
|
|
if(iOperation<2)
|
|
{
|
|
fnHeightmap=_EngineGUI.FileRequester(
|
|
"Import heightmap", FILTER_TGA FILTER_PCX FILTER_ALL FILTER_END,
|
|
"Terrain heightmap directory", "Textures\\");
|
|
if( fnHeightmap=="") return;
|
|
}
|
|
else
|
|
{
|
|
fnHeightmap=_EngineGUI.FileRequester(
|
|
"Export heightmap", FILTER_TGA FILTER_PCX FILTER_ALL FILTER_END,
|
|
"Terrain heightmap directory", "Textures\\");
|
|
if( fnHeightmap=="") return;
|
|
}
|
|
|
|
try
|
|
{
|
|
switch( iOperation)
|
|
{
|
|
// import 8 bit
|
|
case 0:
|
|
{
|
|
ptrTerrain->ImportHeightMap_t(fnHeightmap, FALSE);
|
|
theApp.m_ctTerrainPage.MarkChanged();
|
|
break;
|
|
}
|
|
// import 16 bit
|
|
case 1:
|
|
{
|
|
ptrTerrain->ImportHeightMap_t(fnHeightmap, TRUE);
|
|
theApp.m_ctTerrainPage.MarkChanged();
|
|
break;
|
|
}
|
|
// export 8 bit
|
|
case 2:
|
|
{
|
|
ptrTerrain->ExportHeightMap_t(fnHeightmap, FALSE);
|
|
break;
|
|
}
|
|
// export 16 bit
|
|
case 3:
|
|
{
|
|
ptrTerrain->ExportHeightMap_t(fnHeightmap, TRUE);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
catch(char *strError)
|
|
{
|
|
AfxMessageBox( CString(strError));
|
|
}
|
|
}
|
|
|
|
void GenerateLayerDistribution(CTIButton *ptib, CPoint pt, CDrawPort *pdp)
|
|
{
|
|
GenerateLayerDistribution(-1);
|
|
}
|
|
|
|
void InvokeImportExportCombo(CTIButton *ptib, CPoint pt, CDrawPort *pdp)
|
|
{
|
|
CTerrain *ptrTerrain=GetTerrain();
|
|
if( ptrTerrain==NULL) return;
|
|
|
|
CCustomComboWnd *pCombo=new CCustomComboWnd;
|
|
InsertItemMacro( pCombo, "Import 8-bit", 22, 0);
|
|
InsertItemMacro( pCombo, "Import 16-bit", 22, 1);
|
|
InsertItemMacro( pCombo, "Export 8-bit", 22, 2);
|
|
InsertItemMacro( pCombo, "Export 16-bit", 22, 3);
|
|
InsertItemMacro( pCombo, "----------------", -1, -1, COL_SEPARATOR);
|
|
InsertItemMacro( pCombo, "Load surface", 22, 4);
|
|
InsertItemMacro( pCombo, "Save surface", 22, 5);
|
|
PointToScreenSpace(pt, pdp);
|
|
pCombo->Initialize(NULL, OnSelectLoadSave, pt.x, pt.y);
|
|
}
|
|
|
|
void InvokeTerrainTilePalette( PIX pixX, PIX pixY)
|
|
{
|
|
CWndTerrainTilePalette *pDisplay=new CWndTerrainTilePalette;
|
|
CTerrainLayer *ptlLayer=GetLayer();
|
|
if(ptlLayer!=NULL && ptlLayer->tl_ptdTexture!=NULL)
|
|
{
|
|
pDisplay->Initialize(pixX, pixY, ptlLayer->tl_ptdTexture, TRUE);
|
|
}
|
|
}
|
|
|
|
CBrushPaletteWnd *_pBrushPalette=NULL;
|
|
void InvokeTerrainBrushPalette( PIX pixX, PIX pixY)
|
|
{
|
|
// calculate palette window's rectangle
|
|
CRect rectWindow;
|
|
rectWindow.left = pixX;
|
|
rectWindow.bottom = pixY;
|
|
rectWindow.right = rectWindow.left + BRUSH_PALETTE_WIDTH;
|
|
rectWindow.top = rectWindow.bottom - BRUSH_PALETTE_HEIGHT;
|
|
|
|
if( _pBrushPalette == NULL)
|
|
{
|
|
// instantiate new choose color palette window
|
|
_pBrushPalette = new CBrushPaletteWnd;
|
|
// create window
|
|
CMainFrame* pMainFrame = STATIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
|
|
BOOL bResult = _pBrushPalette->CreateEx( WS_EX_TOOLWINDOW,
|
|
NULL, L"Brush palette", WS_CHILD|WS_POPUP|WS_VISIBLE,
|
|
rectWindow.left, rectWindow.top, rectWindow.Width(), rectWindow.Height(),
|
|
pMainFrame->m_hWnd, NULL, NULL);
|
|
_pBrushPalette->SetFocus();
|
|
if( !bResult)
|
|
{
|
|
AfxMessageBox( L"Error: Failed to create brush palette");
|
|
return;
|
|
}
|
|
// initialize canvas for active texture button
|
|
_pGfx->CreateWindowCanvas( _pBrushPalette->m_hWnd, &_pBrushPalette->m_pViewPort,
|
|
&_pBrushPalette->m_pDrawPort);
|
|
}
|
|
else
|
|
{
|
|
_pBrushPalette->ShowWindow(SW_SHOW);
|
|
_pBrushPalette->SetFocus();
|
|
}
|
|
}
|
|
|
|
void InvokeBrushPalette(CTIButton *ptib, CPoint pt, CDrawPort *pdp)
|
|
{
|
|
PointToScreenSpace(pt, pdp);
|
|
InvokeTerrainBrushPalette( pt.x, pt.y);
|
|
}
|
|
|
|
BOOL CTerrainInterface::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext)
|
|
{
|
|
return CWnd::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext);
|
|
}
|
|
|
|
BOOL CTerrainInterface::IsClicked(CTIButton &tib, CPoint pt) const
|
|
{
|
|
PIX pixOffsetX=0;
|
|
PIX pixOffsetY=0;
|
|
GetButtonOffset(tib, pixOffsetX, pixOffsetY);
|
|
|
|
PIX x=tib.tib_fx+pixOffsetX;
|
|
PIX y=tib.tib_fy+pixOffsetY;
|
|
PIX dx=tib.tib_fdx;
|
|
PIX dy=tib.tib_fdy;
|
|
|
|
return( (pt.x>x) && (pt.x<x+dx) && (pt.y>y) && (pt.y<y+dy) );
|
|
}
|
|
|
|
BOOL _bDummyMouseMove=FALSE;
|
|
BOOL _bMouseTrapInProgress=FALSE;
|
|
void CTerrainInterface::OnLButtonDown(UINT nFlags, CPoint point)
|
|
{
|
|
CWnd::OnLButtonDown(nFlags, point);
|
|
SetFocus();
|
|
|
|
m_ptMouseDown=point;
|
|
m_ptMouse=point;
|
|
m_ptMouseDownScreen=point;
|
|
ClientToScreen(&m_ptMouseDownScreen);
|
|
|
|
FOREACHINDYNAMICCONTAINER( dcButtons, CTIButton, ittib)
|
|
{
|
|
CTIButton &tib=*ittib;
|
|
|
|
if( IsClicked(tib, point))
|
|
{
|
|
if(tib.tib_pOnLeftClick!=NULL)
|
|
{
|
|
tib.tib_pOnLeftClick(&tib, m_ptMouse, m_pDrawPort);
|
|
_bMouseTrapInProgress=FALSE;
|
|
UnhideCursor();
|
|
Invalidate(FALSE);
|
|
if(!tib.tib_bContinueTesting) break;
|
|
}
|
|
if(tib.tib_pOnLeftClickMove!=NULL)
|
|
{
|
|
// display tool tip
|
|
if( tib.tib_pGetClickMoveData!=NULL)
|
|
{
|
|
CTString strInfo=tib.tib_pGetClickMoveData(&tib, point, m_pDrawPort, TRUE);
|
|
_strToolTip=strInfo;
|
|
SetCapture();
|
|
theApp.m_cttToolTips.ManualOn( m_ptMouseDownScreen.x, m_ptMouseDownScreen.y, &::GetToolTipText, this);
|
|
}
|
|
// if should trap the mouse
|
|
if(tib.tib_bMouseTrapForMove)
|
|
{
|
|
m_ptMouseCenter.x=m_pDrawPort->GetWidth()/2;
|
|
m_ptMouseCenter.y=m_pDrawPort->GetHeight()/2;
|
|
m_ptMouseCenterScreen=m_ptMouseCenter;
|
|
ClientToScreen(&m_ptMouseCenterScreen);
|
|
_bDummyMouseMove=TRUE;
|
|
SetCursorPos(m_ptMouseCenterScreen.x, m_ptMouseCenterScreen.y);
|
|
HideCursor();
|
|
_bMouseTrapInProgress=TRUE;
|
|
}
|
|
if(!tib.tib_bContinueTesting) break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CTerrainInterface::OnLButtonDblClk(UINT nFlags, CPoint point)
|
|
{
|
|
OnLButtonDown(nFlags, point);
|
|
}
|
|
|
|
void CTerrainInterface::OnMouseMove(UINT nFlags, CPoint point)
|
|
{
|
|
theApp.m_cttToolTips.MouseMoveNotify( m_hWnd, 500, &::GetToolTipText, this);
|
|
|
|
BOOL bLMB = nFlags & MK_LBUTTON;
|
|
BOOL bRMB = nFlags & MK_RBUTTON;
|
|
FLOAT fdx=point.x-m_ptMouseCenter.x;
|
|
FLOAT fdy=point.y-m_ptMouseCenter.y;
|
|
|
|
FLOAT fdxNotLocked=point.x-m_ptMouse.x;
|
|
FLOAT fdyNotLocked=point.y-m_ptMouse.y;
|
|
|
|
fdx=fdxNotLocked;
|
|
fdy=fdyNotLocked;
|
|
|
|
m_ptMouse=point;
|
|
|
|
if( _bDummyMouseMove)
|
|
{
|
|
_bDummyMouseMove=FALSE;
|
|
return;
|
|
}
|
|
|
|
if( bLMB)
|
|
{
|
|
FOREACHINDYNAMICCONTAINER( dcButtons, CTIButton, ittib)
|
|
{
|
|
CTIButton &tib=*ittib;
|
|
|
|
if( IsClicked(tib, m_ptMouseDown) && tib.tib_pOnLeftClickMove!=NULL)
|
|
{
|
|
if(tib.tib_bMouseTrapForMove)
|
|
{
|
|
tib.tib_pOnLeftClickMove(&tib, fdx, fdy, m_pDrawPort);
|
|
_bDummyMouseMove=TRUE;
|
|
SetCursorPos(m_ptMouseCenterScreen.x, m_ptMouseCenterScreen.y);
|
|
}
|
|
else
|
|
{
|
|
tib.tib_pOnLeftClickMove(&tib, fdxNotLocked, fdyNotLocked, m_pDrawPort);
|
|
}
|
|
Invalidate(FALSE);
|
|
|
|
// update tool tip
|
|
if( tib.tib_pGetClickMoveData!=NULL)
|
|
{
|
|
_strToolTip=tib.tib_pGetClickMoveData(&tib, point, m_pDrawPort, TRUE);
|
|
theApp.m_cttToolTips.ManualUpdate();
|
|
}
|
|
|
|
if(!tib.tib_bContinueTesting) break;
|
|
}
|
|
}
|
|
}
|
|
else if( bRMB)
|
|
{
|
|
FOREACHINDYNAMICCONTAINER( dcButtons, CTIButton, ittib)
|
|
{
|
|
CTIButton &tib=*ittib;
|
|
|
|
if( IsClicked(tib, m_ptMouseDown) && tib.tib_pOnRightClickMove!=NULL)
|
|
{
|
|
if(tib.tib_bMouseTrapForMove)
|
|
{
|
|
tib.tib_pOnRightClickMove(&tib, fdx, fdy, m_pDrawPort);
|
|
_bDummyMouseMove=TRUE;
|
|
SetCursorPos(m_ptMouseCenterScreen.x, m_ptMouseCenterScreen.y);
|
|
}
|
|
else
|
|
{
|
|
tib.tib_pOnRightClickMove(&tib, fdxNotLocked, fdyNotLocked, m_pDrawPort);
|
|
}
|
|
Invalidate(FALSE);
|
|
|
|
// update tool tip
|
|
if( tib.tib_pGetClickMoveData!=NULL)
|
|
{
|
|
_strToolTip=tib.tib_pGetClickMoveData(&tib, point, m_pDrawPort, FALSE);
|
|
theApp.m_cttToolTips.ManualUpdate();
|
|
}
|
|
|
|
if(!tib.tib_bContinueTesting) break;
|
|
}
|
|
}
|
|
}
|
|
|
|
CWnd::OnMouseMove(nFlags, point);
|
|
}
|
|
|
|
void CTerrainInterface::OnLButtonUp(UINT nFlags, CPoint point)
|
|
{
|
|
theApp.m_cttToolTips.ManualOff();
|
|
ReleaseCapture();
|
|
_bDummyMouseMove=TRUE;
|
|
if( _bMouseTrapInProgress)
|
|
{
|
|
SetCursorPos(m_ptMouseDownScreen.x, m_ptMouseDownScreen.y);
|
|
_bMouseTrapInProgress=FALSE;
|
|
UnhideCursor();
|
|
m_ptMouseDown.x=-1;
|
|
m_ptMouseDown.y=-1;
|
|
}
|
|
CWnd::OnLButtonUp(nFlags, point);
|
|
}
|
|
|
|
BOOL CTerrainInterface::PreTranslateMessage(MSG* pMsg)
|
|
{
|
|
return CWnd::PreTranslateMessage(pMsg);
|
|
}
|
|
|
|
void CTerrainInterface::OnRButtonDown(UINT nFlags, CPoint point)
|
|
{
|
|
CWnd::OnRButtonDown(nFlags, point);
|
|
SetFocus();
|
|
|
|
m_ptMouseDown=point;
|
|
m_ptMouse=point;
|
|
m_ptMouseDownScreen=point;
|
|
ClientToScreen(&m_ptMouseDownScreen);
|
|
|
|
FOREACHINDYNAMICCONTAINER( dcButtons, CTIButton, ittib)
|
|
{
|
|
CTIButton &tib=*ittib;
|
|
|
|
if( IsClicked(tib, point))
|
|
{
|
|
if(tib.tib_pOnRightClick!=NULL)
|
|
{
|
|
tib.tib_pOnRightClick(&tib, m_ptMouse, m_pDrawPort);
|
|
_bMouseTrapInProgress=FALSE;
|
|
UnhideCursor();
|
|
Invalidate(FALSE);
|
|
if(!tib.tib_bContinueTesting) break;
|
|
}
|
|
if(tib.tib_pOnRightClickMove!=NULL)
|
|
{
|
|
// display tool tip
|
|
if( tib.tib_pGetClickMoveData!=NULL)
|
|
{
|
|
CTString strInfo=tib.tib_pGetClickMoveData(&tib, point, m_pDrawPort, TRUE);
|
|
_strToolTip=strInfo;
|
|
theApp.m_cttToolTips.ManualOn( m_ptMouseDownScreen.x, m_ptMouseDownScreen.y, &::GetToolTipText, this);
|
|
SetCapture();
|
|
}
|
|
// if should trap the mouse
|
|
if(tib.tib_bMouseTrapForMove)
|
|
{
|
|
m_ptMouseCenter.x=m_pDrawPort->GetWidth()/2;
|
|
m_ptMouseCenter.y=m_pDrawPort->GetHeight()/2;
|
|
m_ptMouseCenterScreen=m_ptMouseCenter;
|
|
ClientToScreen(&m_ptMouseCenterScreen);
|
|
_bDummyMouseMove=TRUE;
|
|
SetCursorPos(m_ptMouseCenterScreen.x, m_ptMouseCenterScreen.y);
|
|
HideCursor();
|
|
_bMouseTrapInProgress=TRUE;
|
|
}
|
|
if(!tib.tib_bContinueTesting) break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CTerrainInterface::OnRButtonUp(UINT nFlags, CPoint point)
|
|
{
|
|
theApp.m_cttToolTips.ManualOff();
|
|
ReleaseCapture();
|
|
_bDummyMouseMove=TRUE;
|
|
if( _bMouseTrapInProgress)
|
|
{
|
|
SetCursorPos(m_ptMouseDownScreen.x, m_ptMouseDownScreen.y);
|
|
_bMouseTrapInProgress=FALSE;
|
|
UnhideCursor();
|
|
m_ptMouseDown.x=-1;
|
|
m_ptMouseDown.y=-1;
|
|
}
|
|
CWnd::OnRButtonUp(nFlags, point);
|
|
}
|
|
|
|
void CTerrainInterface::OnIdle(void)
|
|
{
|
|
CWorldEditorDoc *pDoc = theApp.GetDocument();
|
|
|
|
if(!_chAutoGenerateDistribution.IsUpToDate( _udAutoGenerateDistribution))
|
|
{
|
|
GenerateLayerDistribution(_iGenerateForLayer);
|
|
_udAutoGenerateDistribution.MarkUpdated();
|
|
}
|
|
|
|
CTerrain *ptrTerrain=GetTerrain();
|
|
if(ptrTerrain!=NULL)
|
|
{
|
|
if(GetLayerIndex()>=ptrTerrain->tr_atlLayers.Count())
|
|
{
|
|
SelectLayer(0);
|
|
}
|
|
}
|
|
BOOL bLMB = (GetKeyState( VK_LBUTTON)&0x8000) != 0;
|
|
BOOL bRMB = (GetKeyState( VK_RBUTTON)&0x8000) != 0;
|
|
if(!bLMB && !bRMB && _bMouseTrapInProgress)
|
|
{
|
|
_bMouseTrapInProgress=FALSE;
|
|
UnhideCursor();
|
|
theApp.m_cttToolTips.ManualOff();
|
|
}
|
|
|
|
// if should re-initialize interface
|
|
if(pDoc!=NULL && !pDoc->m_chSelections.IsUpToDate( m_udTerrainPage) ||
|
|
!theApp.m_ctTerrainPage.IsUpToDate( m_udTerrainPage) )
|
|
{
|
|
if(m_pDrawPort!=NULL)
|
|
{
|
|
InitializeInterface(m_pDrawPort);
|
|
Invalidate(FALSE);
|
|
m_udTerrainPage.MarkUpdated();
|
|
}
|
|
}
|
|
|
|
// if should just redraw interface
|
|
if(!theApp.m_ctTerrainPageCanvas.IsUpToDate( m_udTerrainPageCanvas) )
|
|
{
|
|
Invalidate(FALSE);
|
|
m_udTerrainPageCanvas.MarkUpdated();
|
|
}
|
|
}
|
|
|
|
|
|
void CTerrainInterface::OnDropFiles(HDROP hDropInfo)
|
|
{
|
|
INDEX iNoOfFiles = DragQueryFile( hDropInfo, 0xFFFFFFFF, NULL, 0);
|
|
|
|
if( iNoOfFiles != 1)
|
|
{
|
|
AfxMessageBox( L"You can drop only one file at a time.");
|
|
return;
|
|
}
|
|
|
|
// buffer for dropped file name
|
|
wchar_t chrFile[ 256];
|
|
// place dropped file name into buffer
|
|
DragQueryFile( hDropInfo, 0, chrFile, 256);
|
|
// create file name from buffer
|
|
CTFileName fnDropped = CTString(CStringA(chrFile));
|
|
|
|
CPoint ptMouse;
|
|
GetCursorPos( &ptMouse);
|
|
ScreenToClient(&ptMouse);
|
|
|
|
FOREACHINDYNAMICCONTAINER( dcButtons, CTIButton, ittib)
|
|
{
|
|
CTIButton &tib=*ittib;
|
|
if( IsClicked(tib, ptMouse) && tib.tib_pOnDropFiles!=NULL)
|
|
{
|
|
tib.tib_pOnDropFiles(&tib, ptMouse, m_pDrawPort, fnDropped);
|
|
}
|
|
}
|
|
CWnd::OnDropFiles(hDropInfo);
|
|
}
|
|
|
|
int CTerrainInterface::OnCreate(LPCREATESTRUCT lpCreateStruct)
|
|
{
|
|
if (CWnd::OnCreate(lpCreateStruct) == -1)
|
|
return -1;
|
|
DragAcceptFiles();
|
|
EnableToolTips( TRUE);
|
|
return 0;
|
|
}
|
|
|
|
int CTerrainInterface::OnToolHitTest( CPoint point, TOOLINFO* pTI ) const
|
|
{
|
|
FOREACHINDYNAMICCONTAINER( dcButtons, CTIButton, ittib)
|
|
{
|
|
CTIButton &tib=*ittib;
|
|
|
|
_strToolTip="";
|
|
if( IsClicked(tib, point))
|
|
{
|
|
if( tib.tib_strToolTip!="" && tib.tib_strToolTip[0]!='_')
|
|
{
|
|
_strToolTip=tib.tib_strToolTip;
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void CTerrainInterface::InitializeInterface(CDrawPort *pdp)
|
|
{
|
|
try
|
|
{
|
|
DECLARE_CTFILENAME( fnTerrainEditIcons, "Textures\\Editor\\TerrainEditingIcons.tex");
|
|
_toIcons.SetData_t(fnTerrainEditIcons);
|
|
}
|
|
catch(char *strError)
|
|
{
|
|
(void)strError;
|
|
return;
|
|
}
|
|
|
|
FOREACHINDYNAMICCONTAINER( dcButtons, CTIButton, ittib)
|
|
{
|
|
delete &*ittib;
|
|
}
|
|
dcButtons.Clear();
|
|
CTIButton *ptib;
|
|
|
|
COLOR colBcg=RGBToColor(45,45,60)|CT_OPAQUE;
|
|
ptib=AddButton(dcButtons,0,0,LAYER_START_X,pdp->GetHeight(),-1,-1, "_Terrain options area fill", C_dGRAY|CT_TRANSPARENT, colBcg);
|
|
|
|
ptib=AddButton(dcButtons,1,1,45,45,-1,-1, "Current brush (\\)", C_lGRAY|CT_OPAQUE);
|
|
ptib->SetData(0, CT_BRUSHES, CHANGE_INDEX_SENSITIVITY, FALSE, &theApp.m_fCurrentTerrainBrush, NULL);
|
|
ptib->SetFunctions( RenderBrushShape, NULL, ChangeData, InvokeBrushPalette);
|
|
|
|
ptib=AddButton(dcButtons,0,52,LAYER_START_X,8,-1,-1, "Brush pressure (keys 0-10)");
|
|
ptib->SetData(0, 1024.0f, CHANGE_PREASSURE_SENSITIVITY, FALSE, &theApp.m_fTerrainBrushPressure, NULL);
|
|
ptib->SetFunctions( RenderBrushPressure, NULL, ChangeData, InvokePercentageCombo, NULL, UpdatePressure);
|
|
|
|
ptib=AddButton(dcButtons,6,64,16,16,-1,19, "Edit mode");
|
|
ptib->SetData(0, CT_EDIT_MODES, CHANGE_INDEX_SENSITIVITY, FALSE, &theApp.m_iTerrainEditMode, NULL);
|
|
UpdateEditModeIcon(ptib, NULL);
|
|
ptib->SetFunctions( NULL, NULL, ChangeData, InvokeEditModeCombo, NULL, UpdateEditModeIcon);
|
|
|
|
ptib=AddButton(dcButtons,28,64,16,16,-1,-1, "Brush mode");
|
|
ptib->SetData(0, CT_BRUSH_MODES-0.5f, CHANGE_INDEX_SENSITIVITY, FALSE, &theApp.m_iTerrainBrushMode, NULL);
|
|
UpdateBrushModeIcon(ptib, NULL);
|
|
ptib->SetFunctions( NULL, NULL, ChangeData, InvokeBrushModeCombo, NULL, UpdateBrushModeIcon);
|
|
|
|
/*
|
|
ptib=AddButton(dcButtons,6,84,16,16,-1,5, "Recalculate shadows (Ctrl+R)");
|
|
ptib->SetFunctions( NULL, RecalculateShadows);
|
|
ptib->tib_pIsEnabled=DisableIfNoTerrainSelected;
|
|
*/
|
|
|
|
ptib=AddButton(dcButtons,28,84,16,16,-1,25, "Terrain options");
|
|
ptib->SetFunctions( NULL, NULL, NULL, InvokeTerrainOptions);
|
|
ptib->tib_pIsEnabled=DisableIfNoTerrainSelected;
|
|
|
|
/*
|
|
ptib=AddButton(dcButtons,6,104,16,16,-1,6, "Generate layer distribution (Ctrl+G)");
|
|
ptib->SetFunctions( NULL, GenerateLayerDistribution);
|
|
ptib->tib_pIsEnabled=DisableIfNoTerrainSelected;
|
|
*/
|
|
|
|
ptib=AddButton(dcButtons,6,84,16,16,-1,22, "Import/Export");
|
|
ptib->SetFunctions( NULL, NULL, NULL, InvokeImportExportCombo);
|
|
ptib->tib_pIsEnabled=DisableIfNoTerrainSelected;
|
|
|
|
CTerrain *ptrTerrain=GetTerrain();
|
|
if( ptrTerrain!=NULL)
|
|
{
|
|
for(INDEX iLayer=0; iLayer<ptrTerrain->tr_atlLayers.Count(); iLayer++)
|
|
{
|
|
CTerrainLayer &tlLayer=ptrTerrain->tr_atlLayers[iLayer];
|
|
|
|
ptib=AddButton(dcButtons,0,0,GetLayerSize(pdp)(1)-SLIDER_WIDTH,
|
|
GetLayerSize(pdp)(2),iLayer,-1, "_Layer options area bcg");
|
|
ptib->SetFunctions( RenderLayerBcg, SetAsActiveLayer, NULL, SetAsActiveLayer);
|
|
ptib->tib_bContinueTesting=TRUE;
|
|
|
|
ptib=AddButton(dcButtons,
|
|
LAYER_SPACING_V/2, LAYER_SPACING_V/2,
|
|
LAYER_HEIGHT-LAYER_SPACING_V/2-1, LAYER_HEIGHT-LAYER_SPACING_V/2-1, iLayer,-1, "Layer texture",
|
|
C_BLACK|CT_OPAQUE);
|
|
ptib->SetFunctions( RenderLayerTexture, NULL, NULL, InvokeLayerTexturePopup);
|
|
ptib->tib_pOnDropFiles=OnDropIntoLayerTexture;
|
|
|
|
ptib=AddButton(dcButtons, LAYER_SPACING_V/2, LAYER_SPACING_V/2, 16, 16, iLayer, -1, "Layer visibility");
|
|
UpdateLayerVisibleFlag(ptib, NULL);
|
|
ptib->tib_pfData1=(FLOAT*)offsetof(CTerrainLayer, tl_bVisible);
|
|
ptib->SetFunctions( NULL, ToggleLayerVisibleFlag, NULL, NULL, NULL, UpdateLayerVisibleFlag);
|
|
|
|
ptib=AddButton(dcButtons,
|
|
LAYER_HEIGHT, LAYER_SPACING_V/2,
|
|
LAYER_HEIGHT-LAYER_SPACING_V/2-1, LAYER_HEIGHT-LAYER_SPACING_V/2-1, iLayer,-1, "Layer mask",
|
|
C_BLACK|CT_OPAQUE);
|
|
ptib->SetFunctions( RenderLayerMask, NULL, NULL, InvokeLayerMaskPopup);
|
|
|
|
if(tlLayer.tl_ltType==LT_NORMAL)
|
|
{
|
|
ptib=AddButton(dcButtons, LAYER_HEIGHT*2,2,16,16,iLayer,0, "Rotate texture");
|
|
ptib->SetFunctions( NULL, NULL, ChangeTextureRotation);
|
|
|
|
ptib=AddButton(dcButtons, LAYER_HEIGHT*2,16,16,16,iLayer,2, "Stretch texture");
|
|
ptib->SetFunctions( NULL, NULL, ChangeTextureStretch);
|
|
ptib->tib_pGetClickMoveData=GetStretchInfo;
|
|
|
|
ptib=AddButton(dcButtons, LAYER_HEIGHT*2,30,16,16,iLayer,1, "Offset texture");
|
|
ptib->SetFunctions( NULL, NULL, ChangeTextureOffset);
|
|
|
|
#define ICON_COVERAGE_X (LAYER_HEIGHT*2+16)
|
|
#define ICON_FILTER_X (LAYER_HEIGHT*2+40)
|
|
#define ICON_FADE_X (ICON_FILTER_X+16)
|
|
#define ICON_NOISE_X (ICON_FADE_X+16)
|
|
#define ICON_SLOPE_OFFSET 56
|
|
#define ICON_LINE1_Y 6
|
|
#define ICON_LINE2_Y 26
|
|
|
|
ptib=AddButton(dcButtons, ICON_COVERAGE_X,ICON_LINE1_Y,16,16,iLayer,17, "Layer coverage");
|
|
ptib->SetData(0, 1, CHANGE_NORMALIZED_SENSITIVITY, FALSE, (FLOAT*)offsetof(CTerrainLayer, tl_fCoverage));
|
|
ptib->SetFunctions( NULL, NULL, ChangeLayerDistributionData);
|
|
ptib->tib_pGetClickMoveData=GetNormalizedPercentageInfo;
|
|
ptib=AddButton(dcButtons, ICON_COVERAGE_X,ICON_LINE2_Y,16,16,iLayer,21, "Layer coverage noise");
|
|
ptib->SetData(0, 1, CHANGE_NORMALIZED_SENSITIVITY, FALSE, (FLOAT*)offsetof(CTerrainLayer, tl_fCoverageNoise));
|
|
ptib->SetFunctions( NULL, NULL, ChangeLayerDistributionData);
|
|
ptib->tib_pGetClickMoveData=GetNormalizedPercentageInfo;
|
|
|
|
ptib=AddButton(dcButtons, ICON_FILTER_X, ICON_LINE1_Y,16,16,iLayer,14, "Max altitude");
|
|
ptib->SetData(0, 1, CHANGE_NORMALIZED_SENSITIVITY, FALSE, (FLOAT*)offsetof(CTerrainLayer, tl_fMaxAltitude));
|
|
ptib->SetFunctions( NULL, NULL, ChangeLayerDistributionData);
|
|
ptib->tib_pGetClickMoveData=GetNormalizedPercentageInfo;
|
|
ptib=AddButton(dcButtons, ICON_FADE_X, ICON_LINE1_Y,16,16,iLayer,29, "Max altitude fade");
|
|
ptib->SetFunctions( NULL, NULL, ChangeLayerDistributionData);
|
|
ptib->tib_pGetClickMoveData=GetNormalizedPercentageInfo;
|
|
ptib->SetData(0, 1, CHANGE_NORMALIZED_SENSITIVITY, FALSE, (FLOAT*)offsetof(CTerrainLayer, tl_fMaxAltitudeFade));
|
|
ptib=AddButton(dcButtons, ICON_NOISE_X, ICON_LINE1_Y,16,16,iLayer,21, "Max altitude noise");
|
|
ptib->SetData(0, 1, CHANGE_NORMALIZED_SENSITIVITY, FALSE, (FLOAT*)offsetof(CTerrainLayer, tl_fMaxAltitudeNoise));
|
|
ptib->SetFunctions( NULL, NULL, ChangeLayerDistributionData);
|
|
ptib->tib_pGetClickMoveData=GetNormalizedPercentageInfo;
|
|
|
|
ptib=AddButton(dcButtons, ICON_FILTER_X, ICON_LINE2_Y,16,16,iLayer,13, "Min altitude");
|
|
ptib->SetData(0, 1, CHANGE_NORMALIZED_SENSITIVITY, FALSE, (FLOAT*)offsetof(CTerrainLayer, tl_fMinAltitude));
|
|
ptib->SetFunctions( NULL, NULL, ChangeLayerDistributionData);
|
|
ptib->tib_pGetClickMoveData=GetNormalizedPercentageInfo;
|
|
ptib=AddButton(dcButtons, ICON_FADE_X, ICON_LINE2_Y,16,16,iLayer,29, "Min altitude fade");
|
|
ptib->SetData(0, 1, CHANGE_NORMALIZED_SENSITIVITY, FALSE, (FLOAT*)offsetof(CTerrainLayer, tl_fMinAltitudeFade));
|
|
ptib->SetFunctions( NULL, NULL, ChangeLayerDistributionData);
|
|
ptib->tib_pGetClickMoveData=GetNormalizedPercentageInfo;
|
|
ptib=AddButton(dcButtons, ICON_NOISE_X, ICON_LINE2_Y,16,16,iLayer,21, "Min altitude noise");
|
|
ptib->SetData(0, 1, CHANGE_NORMALIZED_SENSITIVITY, FALSE, (FLOAT*)offsetof(CTerrainLayer, tl_fMinAltitudeNoise));
|
|
ptib->SetFunctions( NULL, NULL, ChangeLayerDistributionData);
|
|
ptib->tib_pGetClickMoveData=GetNormalizedPercentageInfo;
|
|
|
|
ptib=AddButton(dcButtons, ICON_FILTER_X+ICON_SLOPE_OFFSET, ICON_LINE1_Y,16,16,iLayer,16, "Max slope");
|
|
ptib->SetData(0, 1, CHANGE_NORMALIZED_SENSITIVITY, FALSE, (FLOAT*)offsetof(CTerrainLayer, tl_fMaxSlope));
|
|
ptib->SetFunctions( NULL, NULL, ChangeLayerDistributionData);
|
|
ptib->tib_pGetClickMoveData=GetNormalizedPercentageInfo;
|
|
ptib=AddButton(dcButtons, ICON_FADE_X+ICON_SLOPE_OFFSET, ICON_LINE1_Y,16,16,iLayer,29, "Max slope fade");
|
|
ptib->SetData(0, 1, CHANGE_NORMALIZED_SENSITIVITY, FALSE, (FLOAT*)offsetof(CTerrainLayer, tl_fMaxSlopeFade));
|
|
ptib->SetFunctions( NULL, NULL, ChangeLayerDistributionData);
|
|
ptib->tib_pGetClickMoveData=GetNormalizedPercentageInfo;
|
|
ptib=AddButton(dcButtons, ICON_NOISE_X+ICON_SLOPE_OFFSET, ICON_LINE1_Y,16,16,iLayer,21, "Max slope noise");
|
|
ptib->SetData(0, 1, CHANGE_NORMALIZED_SENSITIVITY, FALSE, (FLOAT*)offsetof(CTerrainLayer, tl_fMaxSlopeNoise));
|
|
ptib->SetFunctions( NULL, NULL, ChangeLayerDistributionData);
|
|
ptib->tib_pGetClickMoveData=GetNormalizedPercentageInfo;
|
|
|
|
ptib=AddButton(dcButtons, ICON_FILTER_X+ICON_SLOPE_OFFSET, ICON_LINE2_Y,16,16,iLayer,15, "Min slope");
|
|
ptib->SetData(0, 1, CHANGE_NORMALIZED_SENSITIVITY, FALSE, (FLOAT*)offsetof(CTerrainLayer, tl_fMinSlope));
|
|
ptib->SetFunctions( NULL, NULL, ChangeLayerDistributionData);
|
|
ptib->tib_pGetClickMoveData=GetNormalizedPercentageInfo;
|
|
ptib=AddButton(dcButtons, ICON_FADE_X+ICON_SLOPE_OFFSET, ICON_LINE2_Y,16,16,iLayer,29, "Min slope fade");
|
|
ptib->SetData(0, 1, CHANGE_NORMALIZED_SENSITIVITY, FALSE, (FLOAT*)offsetof(CTerrainLayer, tl_fMinSlopeFade));
|
|
ptib->SetFunctions( NULL, NULL, ChangeLayerDistributionData);
|
|
ptib->tib_pGetClickMoveData=GetNormalizedPercentageInfo;
|
|
ptib=AddButton(dcButtons, ICON_NOISE_X+ICON_SLOPE_OFFSET, ICON_LINE2_Y,16,16,iLayer,21, "Min slope noise");
|
|
ptib->SetData(0, 1, CHANGE_NORMALIZED_SENSITIVITY, FALSE, (FLOAT*)offsetof(CTerrainLayer, tl_fMinSlopeFade));
|
|
ptib->SetFunctions( NULL, NULL, ChangeLayerDistributionData);
|
|
ptib->tib_pGetClickMoveData=GetNormalizedPercentageInfo;
|
|
|
|
ptib=AddButton(dcButtons, GetLayerSize(pdp)(1)-12-SLIDER_WIDTH-1-2,2,12,12,iLayer,-1, "Multiply color", C_BLACK|CT_OPAQUE);
|
|
ptib->SetFunctions( RenderLayerColor, PickLayerColor, NULL, NumericAlpha);
|
|
|
|
ptib=AddButton(dcButtons, GetLayerSize(pdp)(1)-16-SLIDER_WIDTH-1,GetLayerSize(pdp)(2)-20,16,16,iLayer,26, "Layer options (Ctrl+Shift+L)");
|
|
ptib->SetFunctions( NULL, InvokeLayerOptions);
|
|
}
|
|
else if(tlLayer.tl_ltType==LT_TILE)
|
|
{
|
|
}
|
|
|
|
ptib=AddButton(dcButtons,0,0,GetLayerSize(pdp)(1)-SLIDER_WIDTH-1,GetLayerSize(pdp)(2),iLayer,-1, "_Layer options area border", C_GRAY|CT_OPAQUE);
|
|
|
|
// _Layer click detector
|
|
ptib=AddButton(dcButtons,0,0,GetLayerSize(pdp)(1)-SLIDER_WIDTH,
|
|
GetLayerSize(pdp)(2),iLayer,-1, "_Layer click detector");
|
|
ptib->SetFunctions( NULL, NULL, NULL, InvokeLayerPopup);
|
|
}
|
|
}
|
|
|
|
//slider
|
|
ptib=AddButton(dcButtons,pdp->GetWidth()-SLIDER_WIDTH, 0, SLIDER_WIDTH, SLIDER_WIDTH, -1, 23, "_Slider arrow up", C_GRAY|CT_OPAQUE, C_mdGRAY|CT_OPAQUE);
|
|
ptib->SetFunctions(NULL,OnSliderArrowUp);
|
|
ptib=AddButton(dcButtons,pdp->GetWidth()-SLIDER_WIDTH, pdp->GetHeight()-SLIDER_WIDTH, SLIDER_WIDTH, SLIDER_WIDTH, -1, 24, "_Slider arrow down", C_GRAY|CT_OPAQUE, C_mdGRAY|CT_OPAQUE);
|
|
ptib->SetFunctions(NULL,OnSliderArrowDown);
|
|
ptib=AddButton(dcButtons,pdp->GetWidth()-SLIDER_WIDTH, SLIDER_WIDTH, SLIDER_WIDTH, pdp->GetHeight()-SLIDER_WIDTH*2, -1,-1, "_Slider rect", C_dGRAY|CT_OPAQUE, colBcg);
|
|
ptib->SetFunctions(RenderSlider,OnSliderClick, DragSlider);
|
|
ptib->tib_bMouseTrapForMove=FALSE;
|
|
}
|