Serious-Engine/Sources/WorldEditor/TerrainInterface.cpp

2565 lines
74 KiB
C++
Raw Normal View History

2016-03-12 01:20:51 +01:00
/* 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. */
2016-03-11 14:57:17 +01:00
// 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;
}