mirror of
https://github.com/electronicarts/CNC_TS_and_RA2_Mission_Editor.git
synced 2025-04-30 09:01:41 -04:00
Switching screen mode (from or to full screen) with FA2 open and loaded with map, when you get back, the program haulted and killed immediately. This PR fix the device lost issue, and get the right surface .
6515 lines
173 KiB
C++
6515 lines
173 KiB
C++
/*
|
||
FinalSun/FinalAlert 2 Mission Editor
|
||
|
||
Copyright (C) 1999-2024 Electronic Arts, Inc.
|
||
Authored by Matthias Wagner
|
||
|
||
This program is free software: you can redistribute it and/or modify
|
||
it under the terms of the GNU General Public License as published by
|
||
the Free Software Foundation, either version 3 of the License, or
|
||
(at your option) any later version.
|
||
|
||
This program is distributed in the hope that it will be useful,
|
||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
GNU General Public License for more details.
|
||
|
||
You should have received a copy of the GNU General Public License
|
||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||
*/
|
||
|
||
/*
|
||
ISOVIEW.CPP
|
||
Implementation of the isometric view.
|
||
*/
|
||
|
||
#include "stdafx.h"
|
||
|
||
|
||
#ifdef _DEBUG
|
||
#define new DEBUG_NEW
|
||
#undef THIS_FILE
|
||
static char THIS_FILE[] = __FILE__;
|
||
#endif
|
||
|
||
/* Includes */
|
||
#include "FinalSun.h"
|
||
#include "IsoView.h"
|
||
#include "DynamicGraphDlg.h"
|
||
#include "infantry.h"
|
||
#include "building.h"
|
||
#include "unit.h"
|
||
#include "aircraft.h"
|
||
#include "waypointid.h"
|
||
#include "celltag.h"
|
||
#include "MyViewframe.h"
|
||
#include "inlines.h"
|
||
#include "macros.h"
|
||
#include "FinalSunDlg.h"
|
||
#include "loading.h"
|
||
#include "Structs.h"
|
||
#include "frontcliffmodifier.h"
|
||
#include "backcliffmodifier.h"
|
||
#include "LineDrawer.h"
|
||
#include "MapTool.h"
|
||
#include <format>
|
||
#include <chrono>
|
||
#include <algorithm>
|
||
#include "TextDrawer.h"
|
||
|
||
/* -------- */
|
||
|
||
/* Externals */
|
||
extern ACTIONDATA AD;
|
||
void GetNodeName(CString& name, int n);
|
||
/* --------- */
|
||
|
||
/* Overlay picture table (maximum overlay count=0xFF) */
|
||
PICDATA* ovrlpics[0x1000][max_ovrl_img];
|
||
|
||
// cancel draw flag
|
||
BOOL bCancelDraw = FALSE;
|
||
BOOL bNoDraw = FALSE;
|
||
|
||
|
||
// this variable will be set to TRUE when the window has lost focus
|
||
// once the mouse is moved in the isoview again WITHOUT pressed button, it is set to FALSE again
|
||
BOOL bDoNotAllowScroll = FALSE;
|
||
|
||
|
||
|
||
/////////////////////////////////////////////////////////////////////////////
|
||
// CIsoView
|
||
|
||
IMPLEMENT_DYNCREATE(CIsoView, CScrollView)
|
||
|
||
BOOL bNoThreadDraw = FALSE;
|
||
BOOL bDrawStats = TRUE;
|
||
|
||
/*UINT PaintThreadProc( LPVOID pParam )
|
||
{
|
||
while(!bNoThreadDraw)
|
||
{
|
||
if(((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview!=NULL) ((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview->UpdateWindow();
|
||
}
|
||
|
||
return 0; // Thread erfolgreich ausgeführt
|
||
}
|
||
*/
|
||
|
||
class SurfaceLocker
|
||
{
|
||
public:
|
||
SurfaceLocker(IDirectDrawSurface4* pDDS, LPRECT rect = nullptr) :
|
||
SurfaceLocker()
|
||
{
|
||
m_hasRect = rect != nullptr;
|
||
if (rect)
|
||
m_rect = *rect;
|
||
m_pDDS = pDDS;
|
||
m_ddsd.dwSize = sizeof(DDSURFACEDESC2);
|
||
m_ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
|
||
}
|
||
|
||
DDSURFACEDESC2* ensure_locked()
|
||
{
|
||
if (m_locked)
|
||
return &m_ddsd;
|
||
|
||
if (m_pDDS->GetSurfaceDesc(&m_ddsd) != DD_OK)
|
||
return nullptr;
|
||
|
||
if (m_pDDS->Lock(m_hasRect ? &m_rect : nullptr, &m_ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT | DDLOCK_NOSYSLOCK, NULL) != DD_OK)
|
||
return nullptr;
|
||
|
||
m_locked = true;
|
||
|
||
if (!m_ddsd.lpSurface)
|
||
return nullptr; // probably does not happen in reality
|
||
|
||
return &m_ddsd;
|
||
}
|
||
|
||
void ensure_unlocked()
|
||
{
|
||
if (m_locked) {
|
||
m_pDDS->Unlock(m_hasRect ? &m_rect : nullptr);
|
||
}
|
||
m_locked = false;
|
||
}
|
||
|
||
~SurfaceLocker()
|
||
{
|
||
ensure_unlocked();
|
||
}
|
||
|
||
SurfaceLocker(const SurfaceLocker& other) = delete;
|
||
SurfaceLocker& operator=(const SurfaceLocker& other) = delete;
|
||
|
||
private:
|
||
SurfaceLocker() = default;
|
||
|
||
private:
|
||
IDirectDrawSurface4* m_pDDS = nullptr;
|
||
DDSURFACEDESC2 m_ddsd = { 0 };
|
||
RECT m_rect = { 0 };
|
||
bool m_hasRect = false;
|
||
bool m_locked = false;
|
||
};
|
||
|
||
|
||
CIsoView::CIsoView()
|
||
{
|
||
srand(GetTickCount());
|
||
m_bAltCliff = FALSE;
|
||
m_NoMove = FALSE;
|
||
b_IsLoading = FALSE;
|
||
m_viewOffset = ProjectedVec(0, 0);
|
||
dd = NULL;
|
||
dd_1 = NULL;
|
||
lpds = NULL;
|
||
lpdsBack = NULL;
|
||
lpdsBackHighRes = nullptr;
|
||
lpdsTemp = NULL;
|
||
pf = DDPIXELFORMAT{ 0 };
|
||
line.left = 0;
|
||
line.top = 0;
|
||
line.right = 0;
|
||
line.bottom = 0;
|
||
m_menu.LoadMenu(IDR_MAPVIEW);
|
||
m_drag = FALSE;
|
||
// _map=NULL;
|
||
AD.reset();
|
||
m_BrushSize_x = 1;
|
||
m_BrushSize_y = 1;
|
||
rscroll = FALSE;
|
||
m_zooming = false;
|
||
bThreadPainting = TRUE;
|
||
m_viewScale = Vec2<CSProjected, float>(1.0f, 1.0f);
|
||
m_viewScaleControl = 1.0f;
|
||
updateFontScaled();
|
||
//m_paintthread=new(CIsoPaintThread);
|
||
//m_paintthread->CreateThread();
|
||
|
||
}
|
||
|
||
CIsoView::~CIsoView()
|
||
{
|
||
// if(_map!=NULL) delete[] _map;
|
||
// _map=NULL;
|
||
//delete m_paintthread;
|
||
bNoThreadDraw = TRUE;
|
||
}
|
||
|
||
BOOL CIsoView::RecreateSurfaces()
|
||
{
|
||
last_succeeded_operation = 7;
|
||
|
||
errstream << "\n\nDirectDrawCreate() will be called now\n";
|
||
errstream.flush();
|
||
|
||
CIsoView& isoView = *this;
|
||
if (DirectDrawCreate(NULL, &isoView.dd_1, NULL) != DD_OK) {
|
||
errstream << "DirectDrawCreate() failed\n";
|
||
errstream.flush();
|
||
ShowWindow(SW_HIDE);
|
||
MessageBox("DirectDraw could not be initialized! Quitting...");
|
||
exit(-1);
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
errstream << "DirectDrawCreate() successful\n\n";
|
||
errstream.flush();
|
||
|
||
errstream << "Now querying the DirectX 7 or 6 interface\n";
|
||
errstream.flush();
|
||
|
||
if (isoView.dd_1->QueryInterface(IID_IDirectDraw7, (void**)&isoView.dd) != DD_OK) {
|
||
errstream << "QueryInterface() failed -> Using DirectX 6.0\n";
|
||
errstream.flush();
|
||
//ShowWindow(SW_HIDE);
|
||
//MessageBox("You don´t have DirectX 6.0 but an older version. Quitting...");
|
||
//exit(-1);
|
||
|
||
//return FALSE;
|
||
|
||
if (isoView.dd_1->QueryInterface(IID_IDirectDraw4, (void**)&isoView.dd) != DD_OK) {
|
||
MessageBox("You need at least DirectX 6.0 to run this program", "Error");
|
||
exit(-1);
|
||
return FALSE;
|
||
}
|
||
}
|
||
|
||
errstream << "QueryInterface() successful\n\nNow setting cooperative level\n";
|
||
errstream.flush();
|
||
|
||
if (isoView.dd->SetCooperativeLevel(isoView.m_hWnd, DDSCL_NORMAL | DDSCL_NOWINDOWCHANGES) != DD_OK) {
|
||
errstream << "SetCooperativeLevel() failed\n";
|
||
errstream.flush();
|
||
ShowWindow(SW_HIDE);
|
||
MessageBox("Cooperative Level could not be set! Quitting...");
|
||
isoView.dd->Release();
|
||
isoView.dd = NULL;
|
||
exit(-2);
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
errstream << "SetCooperativeLevel() successful\n\nCreating primary surface\n";
|
||
errstream.flush();
|
||
|
||
DDSURFACEDESC2 ddsd;
|
||
|
||
|
||
memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
|
||
ddsd.dwSize = sizeof(DDSURFACEDESC2);
|
||
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
|
||
ddsd.dwFlags = DDSD_CAPS;
|
||
|
||
|
||
|
||
int res = 0;
|
||
int trycount = 0;
|
||
do {
|
||
res = isoView.dd->CreateSurface(&ddsd, &isoView.lpds, NULL);
|
||
errstream << "Return code: " << res << endl;
|
||
errstream.flush();
|
||
|
||
//if(res!=DD_OK && (res!=DDERR_PRIMARYSURFACEALREADYEXISTS || trycount>100))
|
||
if (res != DD_OK && trycount >= 300) {
|
||
|
||
errstream << "CreateSurface() failed\n";
|
||
|
||
errstream.flush();
|
||
ShowWindow(SW_HIDE);
|
||
MessageBox("Primary surface could not be initialized! Quitting...");
|
||
isoView.dd->Release();
|
||
isoView.dd = NULL;
|
||
exit(-3);
|
||
|
||
return FALSE;
|
||
}
|
||
trycount++;
|
||
if (res != DD_OK) {
|
||
Sleep(50);
|
||
}
|
||
|
||
|
||
} while (res != DD_OK);
|
||
|
||
#ifdef NOSURFACES
|
||
DDPIXELFORMAT pf;
|
||
memset(&pf, 0, sizeof(DDPIXELFORMAT));
|
||
pf.dwSize = sizeof(DDPIXELFORMAT);
|
||
|
||
isoView.lpds->GetPixelFormat(&pf);
|
||
|
||
if (!pf.dwBBitMask || !pf.dwRBitMask || !pf.dwGBitMask) {
|
||
ShowWindow(SW_HIDE);
|
||
MessageBox("You must not use a palette color mode like 8 bit in order to run FinalSun/FinalAlert 2. Please check readme.txt", "Error", MB_OK);
|
||
|
||
isoView.lpds->Release();
|
||
isoView.lpds = NULL;
|
||
isoView.dd->Release();
|
||
isoView.dd = NULL;
|
||
exit(-3);
|
||
return FALSE;
|
||
}
|
||
bpp = (pf.dwRGBBitCount + 7) / 8;
|
||
#endif
|
||
|
||
|
||
errstream << "CreateSurface() successful\n\nCreating backbuffer surface\n";
|
||
errstream.flush();
|
||
|
||
memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
|
||
ddsd.dwSize = sizeof(DDSURFACEDESC2);
|
||
ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
|
||
isoView.lpds->GetSurfaceDesc(&ddsd);
|
||
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
|
||
|
||
|
||
ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
|
||
|
||
|
||
if (isoView.dd->CreateSurface(&ddsd, &isoView.lpdsBack, NULL) != DD_OK) {
|
||
errstream << "CreateSurface() failed\n";
|
||
errstream.flush();
|
||
ShowWindow(SW_HIDE);
|
||
MessageBox("Backbuffer surface could not be initialized! Quitting...");
|
||
isoView.lpds->Release();
|
||
isoView.lpds = NULL;
|
||
isoView.dd->Release();
|
||
isoView.dd = NULL;
|
||
exit(-4);
|
||
|
||
return FALSE;
|
||
}
|
||
if (theApp.m_Options.bHighResUI && isoView.dd->CreateSurface(&ddsd, &isoView.lpdsBackHighRes, NULL) != DD_OK) {
|
||
errstream << "CreateSurface() failed\n";
|
||
errstream.flush();
|
||
ShowWindow(SW_HIDE);
|
||
MessageBox("Highres Backbuffer surface could not be initialized! Quitting...");
|
||
isoView.lpdsBack->Release();
|
||
isoView.lpdsBack = NULL;
|
||
isoView.lpds->Release();
|
||
isoView.lpds = NULL;
|
||
isoView.dd->Release();
|
||
isoView.dd = NULL;
|
||
exit(-4);
|
||
|
||
return FALSE;
|
||
}
|
||
if (isoView.dd->CreateSurface(&ddsd, &isoView.lpdsTemp, NULL) != DD_OK) {
|
||
errstream << "CreateSurface() failed\n";
|
||
errstream.flush();
|
||
ShowWindow(SW_HIDE);
|
||
MessageBox("Tempbuffer surface could not be initialized! Quitting...");
|
||
isoView.lpdsBack->Release();
|
||
isoView.lpdsBack = NULL;
|
||
if (isoView.lpdsBackHighRes)
|
||
isoView.lpdsBackHighRes->Release();
|
||
isoView.lpdsBackHighRes = nullptr;
|
||
isoView.lpds->Release();
|
||
isoView.lpds = NULL;
|
||
isoView.dd->Release();
|
||
isoView.dd = NULL;
|
||
exit(-4);
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
errstream << "CreateSurface() successful\n\nNow creating clipper\n";
|
||
errstream.flush();
|
||
|
||
LPDIRECTDRAWCLIPPER ddc;
|
||
if (isoView.dd->CreateClipper(0, &ddc, NULL) != DD_OK) {
|
||
errstream << "CreateClipper() failed\n";
|
||
errstream.flush();
|
||
ShowWindow(SW_HIDE);
|
||
MessageBox("Clipper could not be created! Quitting...");
|
||
isoView.lpdsTemp->Release();
|
||
isoView.lpdsTemp = NULL;
|
||
isoView.lpdsBack->Release();
|
||
isoView.lpdsBack = NULL;
|
||
if (isoView.lpdsBackHighRes)
|
||
isoView.lpdsBackHighRes->Release();
|
||
isoView.lpdsBackHighRes = nullptr;
|
||
isoView.lpds->Release();
|
||
isoView.lpds = NULL;
|
||
isoView.dd->Release();
|
||
isoView.dd = NULL;
|
||
exit(-6);
|
||
}
|
||
|
||
errstream << "CreateClipper() successful\n\n";
|
||
errstream.flush();
|
||
|
||
isoView.lpds->SetClipper(ddc);
|
||
|
||
ddc->SetHWnd(0, isoView.m_hWnd);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
BEGIN_MESSAGE_MAP(CIsoView, CView)
|
||
//{{AFX_MSG_MAP(CIsoView)
|
||
ON_WM_SYSCOMMAND()
|
||
ON_WM_VSCROLL()
|
||
ON_WM_HSCROLL()
|
||
ON_WM_MOUSEMOVE()
|
||
ON_WM_RBUTTONUP()
|
||
ON_WM_LBUTTONDBLCLK()
|
||
ON_WM_LBUTTONDOWN()
|
||
ON_WM_LBUTTONUP()
|
||
ON_WM_MOVE()
|
||
ON_WM_SIZE()
|
||
ON_WM_CHAR()
|
||
ON_WM_DEADCHAR()
|
||
ON_WM_KEYDOWN()
|
||
ON_WM_KEYUP()
|
||
ON_WM_TIMER()
|
||
ON_WM_RBUTTONDOWN()
|
||
ON_WM_KILLFOCUS()
|
||
ON_WM_MOUSEWHEEL()
|
||
//}}AFX_MSG_MAP
|
||
ON_WM_MBUTTONDOWN()
|
||
ON_WM_MBUTTONUP()
|
||
END_MESSAGE_MAP()
|
||
|
||
/////////////////////////////////////////////////////////////////////////////
|
||
// Zeichnung CIsoView
|
||
|
||
void CIsoView::OnInitialUpdate()
|
||
{
|
||
CView::OnInitialUpdate();
|
||
}
|
||
|
||
|
||
struct CHANGEHEIGHTDATA
|
||
{
|
||
int pos;
|
||
BOOL bNonMorpheable;
|
||
DWORD toHeight;
|
||
};
|
||
|
||
|
||
DWORD WINAPI ChangeHeightThread(
|
||
LPVOID lpParameter // thread data
|
||
)
|
||
{
|
||
CHANGEHEIGHTDATA* p = (CHANGEHEIGHTDATA*)lpParameter;
|
||
|
||
((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview->ChangeTileHeight(p->pos, p->toHeight, p->bNonMorpheable);
|
||
|
||
return 0;
|
||
}
|
||
|
||
/*
|
||
dst must be surface data, src must be a 8 bit palette image
|
||
*/
|
||
#ifdef NOSURFACES
|
||
|
||
struct BlitRect
|
||
{
|
||
short left;
|
||
short top;
|
||
short right;
|
||
short bottom;
|
||
};
|
||
|
||
struct DDBoundary
|
||
{
|
||
unsigned dwWidth{};
|
||
unsigned dwHeight{};
|
||
long dpitch{};
|
||
};
|
||
|
||
__forceinline void BlitTerrain(void* dst, int x, int y, int dleft, int dtop, const DDBoundary& boundary, int dright, int dbottom, const SUBTILE& st)//BYTE* src, int swidth, int sheight)
|
||
{
|
||
BYTE* src = st.pic;
|
||
const unsigned short swidth = st.wWidth;
|
||
const unsigned short sheight = st.wHeight;
|
||
|
||
|
||
if (src == NULL || dst == NULL) {
|
||
return;
|
||
}
|
||
|
||
//x += 1;
|
||
//y += 1;
|
||
//y -= f_y;
|
||
|
||
if (x + swidth < dleft || y + sheight < dtop) {
|
||
return;
|
||
}
|
||
if (x >= dright || y >= dbottom) {
|
||
return;
|
||
}
|
||
|
||
BlitRect blrect;
|
||
BlitRect srcRect;
|
||
srcRect.left = 0;
|
||
srcRect.top = 0;
|
||
srcRect.right = swidth;
|
||
srcRect.bottom = sheight;
|
||
blrect.left = x;
|
||
|
||
|
||
if (blrect.left < 0) {
|
||
srcRect.left = 1 - blrect.left;
|
||
blrect.left = 1;
|
||
}
|
||
blrect.top = y;
|
||
if (blrect.top < 0) {
|
||
srcRect.top = 1 - blrect.top;
|
||
blrect.top = 1;
|
||
}
|
||
blrect.right = (x + swidth);
|
||
if (x + swidth > dright) {
|
||
srcRect.right = dright - x;//swidth-((x+swidth)-dright);
|
||
blrect.right = dright;
|
||
}
|
||
blrect.bottom = (y + sheight);
|
||
if (y + sheight > dbottom) {
|
||
srcRect.bottom = dbottom - y;//sheight-((y+sheight)-dbottom);
|
||
blrect.bottom = dbottom;
|
||
}
|
||
|
||
|
||
short i, e;
|
||
|
||
|
||
auto const surfaceEnd = (BYTE*)dst + boundary.dpitch * boundary.dwHeight;
|
||
|
||
if (!st.bNotExtracted) {
|
||
#ifdef NOSURFACES_EXTRACT
|
||
int pos = 0;
|
||
for (e = srcRect.top; e < srcRect.bottom; e++) {
|
||
short left = st.vborder[e].left;
|
||
short right = st.vborder[e].right;
|
||
|
||
short realright = right;
|
||
//short realleft=left;
|
||
//short addx_s=0;
|
||
|
||
if (right >= srcRect.right) {
|
||
right = srcRect.right - 1;
|
||
}
|
||
if (srcRect.left > 0) {
|
||
pos += (realright - left + 1) * bpp;
|
||
continue; // just cancel. this area is used by object browser. saves some performance
|
||
//addx_s=srcRect.left;
|
||
//left=max(left, srcRect.left);
|
||
//left=//addx=left-srcRect.left;
|
||
}
|
||
|
||
|
||
|
||
if (realright >= left) {
|
||
if (/*left<srcRect.left ||*/ left >= srcRect.right) {
|
||
pos += (realright - left + 1) * bpp;
|
||
continue;
|
||
}
|
||
|
||
|
||
auto dest = ((BYTE*)dst + (blrect.left + left) * bpp + (blrect.top + e) * boundary.dpitch);
|
||
if (dest + bpp * (right - left + 1) < surfaceEnd) {
|
||
memcpy(dest, &st.pic[pos], bpp * (right - left + 1));
|
||
}
|
||
pos += (realright - left + 1) * bpp;
|
||
}
|
||
}
|
||
#endif
|
||
} else {
|
||
for (e = srcRect.top; e < srcRect.bottom; e++) {
|
||
short& left = st.vborder[e].left;
|
||
short& right = st.vborder[e].right;
|
||
|
||
auto l = std::max(left, srcRect.left);
|
||
auto r = std::min(right, static_cast<short>(srcRect.right - 1));
|
||
for (i = l; i <= r; i++) {
|
||
BYTE& val = src[i + e * swidth];
|
||
if (val) {
|
||
auto dest = ((BYTE*)dst + (blrect.left + i) * bpp + (blrect.top + e) * boundary.dpitch);
|
||
if (dest < surfaceEnd) {
|
||
memcpy(dest, &iPalIso[val], bpp);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
__forceinline void BlitTerrainHalfTransp(void* dst, int x, int y, int dleft, int dtop, const DDBoundary& boundary, int dright, int dbottom, const SUBTILE& st)//BYTE* src, int swidth, int sheight)
|
||
{
|
||
BYTE* src = st.pic;
|
||
const unsigned short swidth = st.wWidth;
|
||
const unsigned short sheight = st.wHeight;
|
||
|
||
|
||
if (src == NULL || dst == NULL) {
|
||
return;
|
||
}
|
||
|
||
//x += 1;
|
||
//y += 1;
|
||
//y -= f_y;
|
||
|
||
if (x + swidth < dleft || y + sheight < dtop) {
|
||
return;
|
||
}
|
||
if (x >= dright || y >= dbottom) {
|
||
return;
|
||
}
|
||
|
||
|
||
BlitRect blrect;
|
||
BlitRect srcRect;
|
||
srcRect.left = 0;
|
||
srcRect.top = 0;
|
||
srcRect.right = swidth;
|
||
srcRect.bottom = sheight;
|
||
blrect.left = x;
|
||
|
||
|
||
if (blrect.left < 0) {
|
||
srcRect.left = 1 - blrect.left;
|
||
blrect.left = 1;
|
||
}
|
||
blrect.top = y;
|
||
if (blrect.top < 0) {
|
||
srcRect.top = 1 - blrect.top;
|
||
blrect.top = 1;
|
||
}
|
||
blrect.right = (x + swidth);
|
||
if (x + swidth > dright) {
|
||
srcRect.right = dright - x;//swidth-((x+swidth)-dright);
|
||
blrect.right = dright;
|
||
}
|
||
blrect.bottom = (y + sheight);
|
||
if (y + sheight > dbottom) {
|
||
srcRect.bottom = dbottom - y;//sheight-((y+sheight)-dbottom);
|
||
blrect.bottom = dbottom;
|
||
}
|
||
|
||
|
||
short i, e;
|
||
|
||
|
||
auto const surfaceEnd = (BYTE*)dst + boundary.dpitch * boundary.dwHeight;
|
||
if (!st.bNotExtracted) {
|
||
#ifdef NOSURFACES_EXTRACT
|
||
int pos = 0;
|
||
int a = 0;
|
||
for (e = srcRect.top; e < srcRect.bottom; e += 1) {
|
||
short left = st.vborder[e].left;
|
||
short right = st.vborder[e].right;
|
||
|
||
short realright = right;
|
||
|
||
if (right >= srcRect.right) right = srcRect.right - 1;
|
||
if (srcRect.left > 0) {
|
||
pos += (realright - left + 1) * bpp;
|
||
continue; // just cancel. this area is used by object browser. saves some performance
|
||
}
|
||
|
||
a++;
|
||
|
||
if (realright >= left) {
|
||
if (/*left<srcRect.left ||*/ left >= srcRect.right) {
|
||
pos += (realright - left + 1) * bpp;
|
||
continue;
|
||
}
|
||
|
||
|
||
auto dest = ((BYTE*)dst + (blrect.left + left) * bpp + (blrect.top + e) * boundary.dpitch);
|
||
|
||
//memcpy(dest, &st.pic[pos], bpp*(right-left+1));
|
||
//pos+=(right-left+1)*bpp;
|
||
|
||
for (i = left + a % 2; i <= right; i += 2) {
|
||
if (i < srcRect.left || i >= srcRect.right) {
|
||
//dest+=bpp;
|
||
} else {
|
||
|
||
//BYTE& val=st.pic[pos+i*bpp];
|
||
//if(val)
|
||
{
|
||
void* dest2 = (BYTE*)dest + (i - left) * bpp; //((BYTE*)dst+(blrect.left+i)*bpp+(blrect.top+e)*dpitch);
|
||
if (dest2 < surfaceEnd) {
|
||
memcpy(dest2, &st.pic[pos + (i - left) * bpp], bpp);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
pos += (realright - left + 1) * bpp;
|
||
}
|
||
}
|
||
#endif
|
||
} else {
|
||
int a = 0;
|
||
for (e = srcRect.top; e < srcRect.bottom; e++) {
|
||
short& left = st.vborder[e].left;
|
||
short& right = st.vborder[e].right;
|
||
|
||
|
||
a++;
|
||
|
||
for (i = left + a % 2; i <= right; i += 2) {
|
||
if (i < srcRect.left || i >= srcRect.right) {
|
||
//dest+=bpp;
|
||
} else {
|
||
|
||
BYTE& val = src[i + e * swidth];
|
||
if (val) {
|
||
void* dest = ((BYTE*)dst + (blrect.left + i) * bpp + (blrect.top + e) * boundary.dpitch);
|
||
if (dest < surfaceEnd) {
|
||
memcpy(dest, &iPalIso[val], bpp);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
const int houseColorMin = 0x10;
|
||
const int houseColorMax = 0x1f;
|
||
const int houseColorRelMax = houseColorMax - houseColorMin;
|
||
|
||
inline void CalculateHouseColorPalette(int house_pal[houseColorRelMax + 1], const int* default_pal, const int* color = NULL)
|
||
{
|
||
if (color) {
|
||
if (bpp == 4) {
|
||
for (int n = 0; n <= houseColorRelMax; ++n) {
|
||
const int v = (houseColorRelMax - n);
|
||
auto src = reinterpret_cast<const BYTE*>(color);
|
||
auto bdest = reinterpret_cast<BYTE*>(&house_pal[n]);
|
||
bdest[0] = src[0] * v / houseColorRelMax;
|
||
bdest[1] = src[1] * v / houseColorRelMax;
|
||
bdest[2] = src[2] * v / houseColorRelMax;
|
||
bdest[3] = src[3];
|
||
}
|
||
} else {
|
||
// nowadays only 32 bit rendering should be used, so we take a shortcut here
|
||
for (int n = 0; n <= houseColorRelMax; ++n) {
|
||
house_pal[n] = *color;
|
||
}
|
||
}
|
||
} else {
|
||
for (int n = 0; n <= houseColorRelMax; ++n) {
|
||
house_pal[n] = default_pal[n + houseColorMin];
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
/*
|
||
There is no need for newpal
|
||
*/
|
||
__forceinline void BlitPic(void* dst, int x, int y, int dleft, int dtop, const DDBoundary& boundary, int dright, int dbottom,
|
||
PICDATA& pd, int* color = NULL, const int* newPal = NULL)//BYTE* src, int swidth, int sheight)
|
||
{
|
||
ASSERT(pd.bType != PICDATA_TYPE_BMP);
|
||
|
||
if (newPal == NULL) {
|
||
newPal = pd.pal;
|
||
}
|
||
|
||
BYTE* src = (BYTE*)pd.pic;
|
||
int swidth = pd.wMaxWidth;
|
||
int sheight = pd.wMaxHeight;
|
||
|
||
if (src == NULL || dst == NULL) {
|
||
return;
|
||
}
|
||
|
||
//x += 1;
|
||
//y += 1;
|
||
//y -= f_y;
|
||
|
||
if (x + swidth < dleft || y + sheight < dtop) {
|
||
return;
|
||
}
|
||
if (x >= dright || y >= dbottom) {
|
||
return;
|
||
}
|
||
|
||
|
||
RECT blrect;
|
||
RECT srcRect;
|
||
srcRect.left = 0;
|
||
srcRect.top = 0;
|
||
srcRect.right = swidth;
|
||
srcRect.bottom = sheight;
|
||
blrect.left = x;
|
||
if (blrect.left < 0) {
|
||
srcRect.left = 1 - blrect.left;
|
||
//blrect.left=1;
|
||
}
|
||
blrect.top = y;
|
||
if (blrect.top < 0) {
|
||
srcRect.top = 1 - blrect.top;
|
||
//blrect.top=1;
|
||
}
|
||
blrect.right = (x + swidth);
|
||
if (x + swidth > dright) {
|
||
srcRect.right = swidth - ((x + swidth) - dright);
|
||
blrect.right = dright;
|
||
}
|
||
blrect.bottom = (y + sheight);
|
||
if (y + sheight > dbottom) {
|
||
srcRect.bottom = sheight - ((y + sheight) - dbottom);
|
||
blrect.bottom = dbottom;
|
||
}
|
||
|
||
|
||
int i, e;
|
||
|
||
// calculate a palette for given color for values 0x10 to 0x1f - we might move this outside
|
||
const int houseColorMin = 0x10;
|
||
const int houseColorMax = 0x1f;
|
||
const int houseColorRelMax = houseColorMax - houseColorMin;
|
||
int houseColors[houseColorRelMax + 1] = { 0 };
|
||
CalculateHouseColorPalette(houseColors, newPal, color);
|
||
const BYTE* const pLighting = (bpp == 4 && pd.lighting && !pd.lighting->empty()) ? pd.lighting->data() : nullptr;
|
||
|
||
auto getHouseColor = std::function([](BYTE idx, BYTE houseColorMinIdx) -> int {
|
||
return idx - houseColorMinIdx;
|
||
});
|
||
|
||
if (g_data["Debug"].GetBool("RenderPlainHouseColor")) {
|
||
getHouseColor = [](BYTE idx, BYTE houseColorMinIdx) -> int {
|
||
return 0;
|
||
};
|
||
}
|
||
|
||
auto const surfaceEnd = (BYTE*)dst + boundary.dpitch * boundary.dwHeight;
|
||
|
||
for (e = srcRect.top; e < srcRect.bottom; e++) {
|
||
int left = pd.vborder[e].left;
|
||
int right = pd.vborder[e].right;
|
||
|
||
if (left < srcRect.left) {
|
||
left = srcRect.left;
|
||
}
|
||
if (right >= srcRect.right) {
|
||
right = srcRect.right - 1;
|
||
}
|
||
|
||
for (i = left; i <= right; i++) {
|
||
if (blrect.left + i < 0) {
|
||
continue;
|
||
}
|
||
|
||
const int spos = i + e * swidth;
|
||
BYTE val = src[spos];
|
||
|
||
if (val) {
|
||
auto dest = ((BYTE*)dst + (blrect.left + i) * bpp + (blrect.top + e) * boundary.dpitch);
|
||
|
||
if (dest >= dst) {
|
||
int c;
|
||
if (!color || !pd.bHouseColor || val < houseColorMin || val > houseColorMax) {
|
||
c = newPal[val];
|
||
} else {
|
||
// Replace the original palette color with the house color
|
||
ASSERT(val >= houseColorMin && val <= houseColorMax);
|
||
const int v = getHouseColor(val, houseColorMin);
|
||
c = houseColors[v];
|
||
}
|
||
if (pLighting) {
|
||
// bpp == 4
|
||
ASSERT(bpp == 4);
|
||
int l = pLighting[spos];
|
||
BYTE* bc = reinterpret_cast<BYTE*>(&c);
|
||
for (int i = 0; i < 4; ++i)
|
||
bc[i] = std::min(255, bc[i] * (200 + l * 300 / 255) / 255); // game seems to overbrighten and have a lot of ambient - if you change this, also change Loading.cpp shp lighting value so that shp light stays at 1.0
|
||
//bc[i] = min(255, bc[i] * (0 + l * (255 - 0) / 255) / 255);
|
||
}
|
||
if (dest + bpp < surfaceEnd) {
|
||
memcpy(dest, &c, bpp);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
__forceinline void BlitPicHalfTransp(void* dst, int x, int y, int dleft, int dtop, const DDBoundary& boundary, int dright, int dbottom, PICDATA& pd, int* color = NULL, const int* newPal = NULL)//BYTE* src, int swidth, int sheight)
|
||
{
|
||
ASSERT(pd.bType != PICDATA_TYPE_BMP);
|
||
|
||
if (newPal == NULL) {
|
||
newPal = pd.pal;
|
||
}
|
||
|
||
BYTE* src = (BYTE*)pd.pic;
|
||
int swidth = pd.wMaxWidth;
|
||
int sheight = pd.wMaxHeight;
|
||
|
||
if (src == NULL || dst == NULL) {
|
||
return;
|
||
}
|
||
|
||
//x += 1;
|
||
//y += 1;
|
||
//y -= f_y;
|
||
|
||
if (x + swidth < dleft || y + sheight < dtop) {
|
||
return;
|
||
}
|
||
if (x >= dright || y >= dbottom) {
|
||
return;
|
||
}
|
||
|
||
|
||
RECT blrect;
|
||
RECT srcRect;
|
||
srcRect.left = 0;
|
||
srcRect.top = 0;
|
||
srcRect.right = swidth;
|
||
srcRect.bottom = sheight;
|
||
blrect.left = x;
|
||
if (blrect.left < 0) {
|
||
srcRect.left = 1 - blrect.left;
|
||
//blrect.left=1;
|
||
}
|
||
blrect.top = y;
|
||
if (blrect.top < 0) {
|
||
srcRect.top = 1 - blrect.top;
|
||
//blrect.top=1;
|
||
}
|
||
blrect.right = (x + swidth);
|
||
if (x + swidth > dright) {
|
||
srcRect.right = swidth - ((x + swidth) - dright);
|
||
blrect.right = dright;
|
||
}
|
||
blrect.bottom = (y + sheight);
|
||
if (y + sheight > dbottom) {
|
||
srcRect.bottom = sheight - ((y + sheight) - dbottom);
|
||
blrect.bottom = dbottom;
|
||
}
|
||
|
||
|
||
int i, e;
|
||
auto const surfaceEnd = (BYTE*)dst + boundary.dpitch * boundary.dwHeight;
|
||
|
||
for (e = srcRect.top; e < srcRect.bottom; e++) {
|
||
|
||
|
||
int left = pd.vborder[e].left;
|
||
int right = pd.vborder[e].right;
|
||
if (left < srcRect.left) left = srcRect.left;
|
||
if (right >= srcRect.right) right = srcRect.right - 1;
|
||
|
||
int a = e % 2 + left % 2;
|
||
|
||
for (i = left + a; i <= right; i += 2) {
|
||
//a++;
|
||
|
||
if (blrect.left + i < 0) {
|
||
continue;
|
||
}
|
||
//if(a%2) continue;
|
||
|
||
BYTE& val = src[i + e * swidth];
|
||
//0x10-0x1f,
|
||
if (val) {
|
||
void* dest = ((BYTE*)dst + (blrect.left + i) * bpp + (blrect.top + e) * boundary.dpitch);
|
||
if (dest < surfaceEnd) {
|
||
//*dest=newPal[val];
|
||
if (dest >= dst) {
|
||
if (!color || !pd.bHouseColor || val < 0x10 || val>0x1f) {
|
||
memcpy(dest, &newPal[val], bpp);
|
||
} else {
|
||
//int col=0;
|
||
memcpy(dest, color, bpp);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
#endif
|
||
|
||
|
||
|
||
|
||
/////////////////////////////////////////////////////////////////////////////
|
||
// Diagnose CIsoView
|
||
|
||
#ifdef _DEBUG
|
||
void CIsoView::AssertValid() const
|
||
{
|
||
CView::AssertValid();
|
||
}
|
||
|
||
void CIsoView::Dump(CDumpContext& dc) const
|
||
{
|
||
CView::Dump(dc);
|
||
}
|
||
#endif //_DEBUG
|
||
|
||
/////////////updateFontScaled////////////////////////////////////////////////////////////////
|
||
// Behandlungsroutinen für Nachrichten CIsoView
|
||
|
||
void CIsoView::updateFontScaled()
|
||
{
|
||
auto dc = CDC::FromHandle(::GetDC(NULL));
|
||
m_fontDefaultHeight = -MulDiv(12, dc->GetDeviceCaps(LOGPIXELSY), 72);
|
||
m_Font9Height = -MulDiv(9, dc->GetDeviceCaps(LOGPIXELSY), 72);
|
||
|
||
if (dd) {
|
||
m_textDefault.reset(new TextDrawer(dd, m_fontDefaultHeight, RGB(0, 0, 0), RGB(255, 255, 255)));
|
||
m_text9.reset(new TextDrawer(dd, m_Font9Height, RGB(0, 0, 0), RGB(255, 255, 255)));
|
||
m_textScaled.reset(new TextDrawer(dd, m_fontDefaultHeight / m_viewScale.y, RGB(0, 0, 0), RGB(255, 255, 255)));
|
||
m_text9Scaled.reset(new TextDrawer(dd, m_Font9Height / m_viewScale.y, RGB(0, 0, 0), RGB(255, 255, 255)));
|
||
m_textBlue.reset(new TextDrawer(dd, m_fontDefaultHeight, RGB(0, 0, 255), RGB(255, 255, 255)));
|
||
m_textBlueScaled.reset(new TextDrawer(dd, m_fontDefaultHeight / m_viewScale.y, RGB(0, 0, 255), RGB(255, 255, 255)));
|
||
m_textBlue9.reset(new TextDrawer(dd, m_Font9Height, RGB(0, 0, 255), RGB(255, 255, 255)));
|
||
m_textBlue9Scaled.reset(new TextDrawer(dd, m_Font9Height / m_viewScale.y, RGB(0, 0, 255), RGB(255, 255, 255)));
|
||
}
|
||
}
|
||
|
||
BOOL CIsoView::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext)
|
||
{
|
||
|
||
BOOL r = CWnd::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext);
|
||
|
||
this->SetScrollRange(SB_HORZ, 0, 1, TRUE);
|
||
this->SetScrollRange(SB_VERT, 0, 1, TRUE);
|
||
|
||
// AfxBeginThread(PaintThreadProc, 0, 0, 0xFFFF);
|
||
|
||
return r;
|
||
}
|
||
|
||
void CIsoView::OnSysCommand(UINT nID, LPARAM lParam)
|
||
{
|
||
// TODO: Code für die Behandlungsroutine für Nachrichten hier einfügen und/oder Standard aufrufen
|
||
if (nID == SC_CLOSE) {
|
||
// ok now just hide the window
|
||
ShowWindow(SW_HIDE);
|
||
return;
|
||
}
|
||
|
||
CView::OnSysCommand(nID, lParam);
|
||
}
|
||
|
||
inline int GetScrPos(CWnd* pOwner, UINT nSB, UINT nSBCode, UINT& nPos)
|
||
{
|
||
SCROLLINFO scr;
|
||
scr.cbSize = sizeof(SCROLLINFO);
|
||
scr.fMask = SIF_ALL;
|
||
|
||
pOwner->GetScrollInfo(nSB, &scr);
|
||
|
||
switch (nSBCode) {
|
||
case SB_LEFT:
|
||
{
|
||
nPos = scr.nMin;
|
||
break;
|
||
}
|
||
case SB_RIGHT:
|
||
{
|
||
nPos = scr.nMax;
|
||
break;
|
||
}
|
||
case SB_THUMBTRACK:
|
||
case SB_THUMBPOSITION:
|
||
{
|
||
break;
|
||
}
|
||
case SB_LINELEFT:
|
||
{
|
||
nPos = scr.nPos - 1;
|
||
break;
|
||
}
|
||
case SB_LINERIGHT:
|
||
{
|
||
nPos = scr.nPos + 1;
|
||
break;
|
||
}
|
||
case SB_PAGELEFT:
|
||
{
|
||
nPos = scr.nPos - 5;
|
||
break;
|
||
}
|
||
case SB_PAGERIGHT:
|
||
{
|
||
nPos = scr.nPos + 5;
|
||
break;
|
||
}
|
||
}
|
||
|
||
return nPos;
|
||
|
||
}
|
||
|
||
void CIsoView::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
|
||
{
|
||
if (nSBCode == SB_ENDSCROLL || nSBCode == SB_THUMBTRACK) return;
|
||
|
||
|
||
nPos = GetScrPos(this, SB_VERT, nSBCode, nPos);
|
||
|
||
this->SetScrollPos(SB_VERT, nPos, TRUE);
|
||
|
||
m_viewOffset.y = (nPos + Map->GetWidth() / 2 - 4) * f_y;
|
||
|
||
RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
|
||
CMyViewFrame& dlg = *(CMyViewFrame*)owner;
|
||
dlg.m_minimap.RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
}
|
||
|
||
void CIsoView::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
|
||
{
|
||
if (nSBCode == SB_ENDSCROLL || nSBCode == SB_THUMBTRACK) return;
|
||
|
||
|
||
|
||
nPos = GetScrPos(this, SB_HORZ, nSBCode, nPos);
|
||
|
||
RECT r;
|
||
GetWindowRect(&r);
|
||
m_viewOffset.x = (nPos + Map->GetHeight() / 2 - 1) * f_x;
|
||
|
||
this->SetScrollPos(SB_HORZ, nPos, TRUE);
|
||
|
||
RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
|
||
CMyViewFrame& dlg = *(CMyViewFrame*)owner;
|
||
dlg.m_minimap.RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
}
|
||
|
||
/*
|
||
This function is called when any data has been changed in another dialog.
|
||
It is used to initialize and update the dialog.
|
||
*/
|
||
void CIsoView::UpdateDialog(BOOL bRepos)
|
||
{
|
||
OutputDebugString("Isoview updated\n");
|
||
|
||
UpdateOverlayPictures();
|
||
|
||
|
||
if (bRepos && Map->GetIsoSize() != 0) {
|
||
m_viewScale = Vec2<CSProjected, float>(1.0f, 1.0f);
|
||
m_viewScaleControl = 1.0f;
|
||
auto r = GetScaledDisplayRect();
|
||
UpdateScrollRanges();
|
||
SetScroll((Map->GetIsoSize() / 2 - r.right / f_x / 2) * f_x, (Map->GetIsoSize() / 2 - r.bottom / f_y / 2) * f_y);
|
||
}
|
||
|
||
RedrawWindow(NULL, NULL, RDW_INVALIDATE);
|
||
|
||
}
|
||
|
||
void CIsoView::UpdateScrollRanges()
|
||
{
|
||
auto r = GetScaledDisplayRect();
|
||
SetScrollRange(SB_HORZ, 0, Map->GetWidth() - r.right / f_x + 4, TRUE);
|
||
SetScrollRange(SB_VERT, 0, Map->GetHeight() - r.bottom / f_y + 6, TRUE);
|
||
}
|
||
|
||
BOOL CIsoView::PreCreateWindow(CREATESTRUCT& cs)
|
||
{
|
||
// we overwrite that, because in debug version its necessary that a view is a child window!
|
||
|
||
// save the old style and let CView::PreCreateWindow() think we are using a child window, then restore old style.
|
||
int ostyle = cs.style;
|
||
cs.style |= WS_CHILD | WS_VSCROLL | WS_HSCROLL;
|
||
|
||
BOOL bres = CView::PreCreateWindow(cs);
|
||
cs.style = ostyle;
|
||
|
||
return bres;
|
||
|
||
}
|
||
|
||
|
||
void CIsoView::OnMouseMove(UINT nFlags, CPoint point)
|
||
{
|
||
if (b_IsLoading) return;
|
||
|
||
static BOOL isMoving = FALSE;
|
||
|
||
CIniFile& ini = Map->GetIniFile();
|
||
|
||
cur_x_mouse = point.x;
|
||
cur_y_mouse = point.y;
|
||
|
||
if (!(nFlags & MK_RBUTTON)) bDoNotAllowScroll = FALSE;
|
||
|
||
if (rscroll) {
|
||
if (!(nFlags & MK_RBUTTON)) {
|
||
ReleaseCapture();
|
||
KillTimer(11);
|
||
rscroll = FALSE;
|
||
ShowCursor(TRUE);
|
||
|
||
CMyViewFrame& dlg = *(CMyViewFrame*)owner;
|
||
dlg.m_minimap.RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
|
||
} else {
|
||
|
||
isMoving = FALSE;
|
||
return;
|
||
}
|
||
}
|
||
|
||
if (!bDoNotAllowScroll && (nFlags & MK_RBUTTON) && !rscroll) // check if scroll should start
|
||
{
|
||
if (abs(point.x - rclick_x) > 2 || abs(point.y - rclick_y) > 2) {
|
||
// yes, begin scrolling!
|
||
|
||
rscroll = TRUE;
|
||
SetTimer(11, 25, NULL);
|
||
SetCapture();
|
||
//while(ShowCursor(FALSE)>0);
|
||
isMoving = FALSE;
|
||
return;
|
||
}
|
||
}
|
||
|
||
if ((nFlags & MK_MBUTTON) == 0)
|
||
m_zooming = false;
|
||
|
||
if (!bDoNotAllowScroll && m_zooming) {
|
||
if ((nFlags & MK_MBUTTON) == MK_MBUTTON) {
|
||
auto diff = point - m_MButtonMoveZooming;
|
||
m_MButtonMoveZooming = point;
|
||
Zoom(m_MButtonDown, -diff.cy / 1000.0f);
|
||
RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
return;
|
||
}
|
||
}
|
||
|
||
m_moved = TRUE;
|
||
|
||
if (b_IsLoading == TRUE) return;
|
||
if (Map->GetIsoSize() == 0 || isMoving == TRUE || m_zooming) return;
|
||
|
||
isMoving = TRUE;
|
||
|
||
// SetError(TranslateStringACP("Ready"));
|
||
|
||
RECT r;
|
||
//GetClientRect(&r);
|
||
//ClientToScreen(&r);
|
||
GetWindowRect(&r);
|
||
|
||
const auto viewOffsetWR = m_viewOffset + ProjectedVec(r.left, r.top);
|
||
const auto projCoords = GetProjectedCoordinatesFromClientCoordinates(point);
|
||
const MapCoords mapCoords = GetMapCoordinatesFromClientCoordinates(point, (nFlags & MK_CONTROL) == MK_CONTROL);
|
||
m_cellCursor = MapCoords(-1, -1);
|
||
const int x = mapCoords.x; // compat
|
||
const int y = mapCoords.y;
|
||
|
||
int mapwidth = Map->GetWidth();
|
||
int mapheight = Map->GetHeight();
|
||
|
||
BOOL bOutside = FALSE;
|
||
|
||
if (AD.mode != ACTIONMODE_COPY && AD.mode != ACTIONMODE_PASTE) {
|
||
if (x < 1 || y < 1 || x + y<mapwidth + 1 || x + y>mapwidth + mapheight * 2 || (y + 1 > mapwidth && x - 1 < y - mapwidth) || (x + 1 > mapwidth && y + mapwidth - 1 < x)) {
|
||
isMoving = FALSE;
|
||
return;
|
||
}
|
||
} else {
|
||
if (x < 1 || y < 1 || x >= mapwidth + mapheight - 1 || y >= mapwidth + mapheight - 1) {
|
||
bOutside = TRUE;
|
||
if (AD.mode == ACTIONMODE_COPY || AD.mode == ACTIONMODE_PASTE) {
|
||
isMoving = FALSE;
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
|
||
if (lpdsBack)
|
||
// reset back buffer to last DrawMap()
|
||
lpdsBack->BltFast(0, 0, lpdsTemp, NULL, DDBLTFAST_WAIT);
|
||
//lpdsBack->Blt(NULL, lpdsTemp, NULL, 0, 0);
|
||
|
||
//int cell_x = x;
|
||
//int cell_y = y;
|
||
|
||
{
|
||
// Preview rendering
|
||
if (AD.mode == ACTIONMODE_SETTILE && !((nFlags & MK_LBUTTON) && !(nFlags & MK_CONTROL) && (nFlags & MK_SHIFT))) {
|
||
// No placement, just preview
|
||
|
||
bCancelDraw = TRUE;
|
||
|
||
int i, e, f, n;
|
||
int p = 0;
|
||
//FIELDDATA oldData[36][36][10][10];
|
||
int width = (*tiledata)[AD.type].cx;
|
||
int height = (*tiledata)[AD.type].cy;
|
||
int pos = x - width + 1 + (y - height + 1) * Map->GetIsoSize();
|
||
int startheight = Map->GetHeightAt(x + y * Map->GetIsoSize()) + AD.z_data;
|
||
int ground = (Map->GetFielddataAt(x + y * Map->GetIsoSize()))->wGround;
|
||
if (ground == 0xFFFF) ground = 0;
|
||
startheight -= (*tiledata)[ground].tiles[Map->GetFielddataAt(x + y * Map->GetIsoSize())->bSubTile].bZHeight;
|
||
TILEDATA td = (*tiledata)[AD.type];
|
||
|
||
Map->TakeSnapshot(TRUE, x - width - 4, y - height - 4, x - width + m_BrushSize_x * width + 7, y - height + m_BrushSize_y * height + 7);
|
||
int cur_pos = pos;
|
||
int isosize = Map->GetIsoSize();
|
||
int height_add = height * isosize;
|
||
char c[50];
|
||
itoa(AD.data, c, 10);
|
||
for (f = 0; f < m_BrushSize_x; f++) {
|
||
for (n = 0; n < m_BrushSize_y; n++) {
|
||
|
||
int tile = AD.type;
|
||
|
||
if (AD.data == 1) {
|
||
int n = rand() * 5 / RAND_MAX;
|
||
tile += n;
|
||
}
|
||
|
||
|
||
|
||
cur_pos = pos + f * width + n * height_add;
|
||
p = 0;
|
||
for (i = 0; i < td.cx; i++) {
|
||
for (e = 0; e < td.cy; e++) {
|
||
if (x - width + 1 + f * width + i >= Map->GetIsoSize() ||
|
||
y - height + 1 + n * height + e >= Map->GetIsoSize()) {
|
||
} else
|
||
if (td.tiles[p].pic != NULL) {
|
||
int mypos = cur_pos + i + e * isosize;
|
||
|
||
Map->SetHeightAt(mypos, startheight + td.tiles[p].bZHeight);
|
||
Map->SetTileAt(mypos, tile, p);
|
||
|
||
|
||
|
||
}
|
||
p++;
|
||
|
||
}
|
||
}
|
||
|
||
|
||
}
|
||
}
|
||
|
||
if (!((nFlags & MK_CONTROL) && (nFlags & MK_SHIFT))) {
|
||
if (!theApp.m_Options.bDisableAutoShore) Map->CreateShore(x - width - 2, y - height - 2, x - width + td.cx * m_BrushSize_x + 5, y - height + td.cy * m_BrushSize_y + 5, FALSE);
|
||
|
||
for (f = 0; f < m_BrushSize_x; f++) {
|
||
for (n = 0; n < m_BrushSize_y; n++) {
|
||
cur_pos = pos + f * width + n * height_add;
|
||
p = 0;
|
||
for (i = -1; i < td.cx + 1; i++) {
|
||
for (e = -1; e < td.cy + 1; e++) {
|
||
Map->SmoothAllAt(cur_pos + i + (e)*isosize);
|
||
}
|
||
}
|
||
|
||
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
|
||
bCancelDraw = FALSE;
|
||
DrawMap();
|
||
|
||
|
||
Map->Undo();
|
||
|
||
m_drag = FALSE;
|
||
|
||
} else if (m_drag && AD.mode == ACTIONMODE_CLIFFFRONT) {
|
||
RECT affect;
|
||
if (m_mapx < x) affect.left = m_mapx - 2; else affect.left = x - 2;
|
||
if (m_mapx < x) affect.right = x + 2; else affect.right = m_mapx + 2;
|
||
if (m_mapy < y) affect.top = m_mapy - 2; else affect.top = y - 2;
|
||
if (m_mapy < y) affect.bottom = y + 2; else affect.bottom = m_mapy + 2;
|
||
|
||
//Map->TakeSnapshot();
|
||
Map->TakeSnapshot(TRUE, affect.left, affect.top, affect.right, affect.bottom);
|
||
CFrontCliffModifier f;
|
||
BOOL bAlt = FALSE;
|
||
if (Map->GetTheater() == THEATER3 && m_bAltCliff)
|
||
bAlt = TRUE;
|
||
f.PlaceCliff(m_mapx, m_mapy, x, y, bAlt);
|
||
RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
//Map->TakeSnapshot();
|
||
Map->TakeSnapshot(TRUE, affect.left, affect.top, affect.right, affect.bottom);
|
||
Map->Undo();
|
||
Map->Undo();
|
||
} else if (m_drag && AD.mode == ACTIONMODE_CLIFFBACK) {
|
||
RECT affect;
|
||
if (m_mapx < x) affect.left = m_mapx - 2; else affect.left = x - 2;
|
||
if (m_mapx < x) affect.right = x + 2; else affect.right = m_mapx + 2;
|
||
if (m_mapy < y) affect.top = m_mapy - 2; else affect.top = y - 2;
|
||
if (m_mapy < y) affect.bottom = y + 2; else affect.bottom = m_mapy + 2;
|
||
|
||
//Map->TakeSnapshot();
|
||
Map->TakeSnapshot(TRUE, affect.left, affect.top, affect.right, affect.bottom);
|
||
CBackCliffModifier f;
|
||
BOOL bAlt = FALSE;
|
||
if (Map->GetTheater() == THEATER3 && m_bAltCliff)
|
||
bAlt = TRUE;
|
||
f.PlaceCliff(m_mapx, m_mapy, x, y);
|
||
RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
//Map->TakeSnapshot();
|
||
Map->TakeSnapshot(TRUE, affect.left, affect.top, affect.right, affect.bottom);
|
||
Map->Undo();
|
||
Map->Undo();
|
||
} else if (AD.mode == ACTIONMODE_COPY && m_drag) {
|
||
last_succeeded_operation = 80301; //bugtracing once more
|
||
|
||
int x1, x2, y1, y2;
|
||
if (m_mapx < x) {
|
||
x1 = m_mapx;
|
||
x2 = x;
|
||
} else {
|
||
x1 = x;
|
||
x2 = m_mapx;
|
||
}
|
||
if (m_mapy < y) {
|
||
y1 = m_mapy;
|
||
y2 = y;
|
||
} else {
|
||
y1 = y;
|
||
y2 = m_mapy;
|
||
}
|
||
|
||
DDSURFACEDESC2 ddsd;
|
||
ZeroMemory(&ddsd, sizeof(ddsd));
|
||
ddsd.dwSize = sizeof(DDSURFACEDESC2);
|
||
ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
|
||
|
||
lpdsBack->GetSurfaceDesc(&ddsd);
|
||
|
||
|
||
lpdsBack->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT | DDLOCK_NOSYSLOCK, NULL);
|
||
|
||
int i, e;
|
||
int isosize = Map->GetIsoSize();
|
||
for (i = 0; i < x2 - x1 + 1; i++) {
|
||
for (e = 0; e < y2 - y1 + 1; e++) {
|
||
last_succeeded_operation = 80302;
|
||
int x_s = x1 + i;
|
||
int y_s = y1 + e;
|
||
|
||
if (x_s < 0 || y_s < 0 || x_s >= isosize || y_s >= isosize) continue;
|
||
|
||
if (theApp.m_Options.bFlat) ToPhys(&x_s, &y_s); else ToPhys3d(&x_s, &y_s);
|
||
x_s -= m_viewOffset.x;
|
||
y_s -= m_viewOffset.y;
|
||
|
||
last_succeeded_operation = 80305;
|
||
DrawCell(ddsd.lpSurface, ddsd.dwWidth, ddsd.dwHeight, ddsd.lPitch, x_s, y_s, 1, 1, m_color_converter->GetColor(255, 0, 0));
|
||
last_succeeded_operation = 80303;
|
||
}
|
||
}
|
||
|
||
lpdsBack->Unlock(NULL);
|
||
|
||
BlitBackbufferToHighRes();
|
||
RenderUIOverlay();
|
||
FlipHighResBuffer();
|
||
last_succeeded_operation = 80304;
|
||
} else if (AD.mode == ACTIONMODE_PASTE) {
|
||
Map->TakeSnapshot();
|
||
Map->Paste(x, y, AD.z_data);
|
||
RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
Map->Undo();
|
||
} else if ((AD.mode == ACTIONMODE_PLACE || AD.mode == ACTIONMODE_RANDOMTERRAIN) && (nFlags & ~MK_CONTROL) == 0 && AD.type != 7 && (AD.type != 6 || (AD.type == 6 && ((AD.data >= 30 && AD.data <= 33) || AD.data == 2 || AD.data == 3)))) // everything placing but not overlay!
|
||
{
|
||
FIELDDATA oldData[32][32];
|
||
INFANTRY infData[SUBPOS_COUNT][32][32];
|
||
int i, e;
|
||
|
||
//if(AD.type!=1 || Map->GetInfantryCountAt(x+y*Map->GetIsoSize())==0)
|
||
{
|
||
for (i = 0; i < 32; i++) {
|
||
for (e = 0; e < 32; e++) {
|
||
oldData[i][e] = *Map->GetFielddataAt(i + x + (e + y) * Map->GetIsoSize());
|
||
int z;
|
||
for (z = 0; z < SUBPOS_COUNT; z++)
|
||
if (oldData[i][e].infantry[z] > -1)
|
||
Map->GetInfantryData(oldData[i][e].infantry[z], &infData[z][i][e]);
|
||
}
|
||
}
|
||
|
||
PlaceCurrentObjectAt(x, y);
|
||
RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
|
||
for (i = 0; i < 32; i++) {
|
||
for (e = 0; e < 32; e++) {
|
||
DWORD dwPos = i + x + (e + y) * Map->GetIsoSize();
|
||
FIELDDATA cur_field;
|
||
cur_field = *Map->GetFielddataAt(dwPos);
|
||
|
||
if (cur_field.aircraft != oldData[i][e].aircraft)
|
||
Map->DeleteAircraft(cur_field.aircraft);
|
||
int z;
|
||
for (z = 0; z < SUBPOS_COUNT; z++)
|
||
if (cur_field.infantry[z] != oldData[i][e].infantry[z]) {
|
||
Map->DeleteInfantry(cur_field.infantry[z]);
|
||
}
|
||
|
||
if (cur_field.node.index != oldData[i][e].node.index) {
|
||
CString house;
|
||
int id = Map->GetNodeAt(dwPos, house);
|
||
Map->DeleteNode(house, id);
|
||
}
|
||
if (cur_field.structure != oldData[i][e].structure)
|
||
Map->DeleteStructure(cur_field.structure);
|
||
if (cur_field.terrain != oldData[i][e].terrain)
|
||
Map->DeleteTerrain(cur_field.terrain);
|
||
#ifdef SMUDGE_SUPP
|
||
if (cur_field.smudge != oldData[i][e].smudge)
|
||
Map->DeleteSmudge(cur_field.smudge);
|
||
#endif
|
||
if (cur_field.unit != oldData[i][e].unit)
|
||
Map->DeleteUnit(cur_field.unit);
|
||
|
||
if (cur_field.overlay != oldData[i][e].overlay)
|
||
Map->SetOverlayAt(dwPos, oldData[i][e].overlay);
|
||
if (cur_field.overlaydata != oldData[i][e].overlaydata)
|
||
Map->SetOverlayDataAt(dwPos, oldData[i][e].overlaydata);
|
||
|
||
Map->SetFielddataAt(dwPos, &oldData[i][e]);
|
||
}
|
||
}
|
||
}
|
||
//else
|
||
// RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
|
||
} else {
|
||
|
||
SurfaceLocker locker(lpdsBack);
|
||
auto desc = locker.ensure_locked();
|
||
if (desc)
|
||
DrawCellCursor(mapCoords, *desc);
|
||
m_cellCursor = mapCoords;
|
||
//RedrawWindow(NULL, NULL, RDW_INVALIDATE);
|
||
locker.ensure_unlocked();
|
||
|
||
BlitBackbufferToHighRes();
|
||
RenderUIOverlay();
|
||
FlipHighResBuffer();
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
// display the coordinates
|
||
char c[50];
|
||
CString cap;
|
||
itoa(x, c, 10);
|
||
cap += c;
|
||
cap += " / ";
|
||
itoa(y, c, 10);
|
||
cap += c;
|
||
cap += " - ";
|
||
itoa(Map->GetHeightAt(x + y * Map->GetIsoSize()), c, 10);
|
||
cap += c;
|
||
|
||
CStatusBarCtrl& stat = ((CMyViewFrame*)owner)->m_statbar.GetStatusBarCtrl();
|
||
stat.SetText(cap, 1, 0);
|
||
|
||
|
||
// drag
|
||
if (m_drag && AD.mode == 0) {
|
||
RedrawWindow(NULL, NULL, RDW_INVALIDATE);
|
||
|
||
CPaintDC dc(this);
|
||
dc.SetROP2(R2_NOT);
|
||
|
||
const auto renderOffset = CPoint(f_x / 2 / m_viewScale.x, f_y / 2 / m_viewScale.y);
|
||
const auto from = GetClientCoordinates(MapCoords(m_mapx, m_mapy)) + renderOffset;
|
||
const auto to = GetClientCoordinates(mapCoords) + renderOffset;
|
||
|
||
dc.MoveTo(from.x, from.y);
|
||
dc.LineTo(to.x, to.y);
|
||
} else if (AD.mode == ACTIONMODE_SETTILE && (nFlags & MK_LBUTTON) && ((nFlags & MK_SHIFT) || Map->hasLat(AD.type)) && !(nFlags & MK_CONTROL)) {
|
||
// Sound(SOUND_LAYDOWNTILE); // too many sounds
|
||
|
||
PlaceTile(x, y, nFlags);
|
||
RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
isMoving = FALSE;
|
||
return;
|
||
} else if ((nFlags & MK_LBUTTON) && (nFlags & MK_SHIFT) && AD.mode == ACTIONMODE_HEIGHTEN) {
|
||
OnLButtonDown(nFlags, point);
|
||
isMoving = FALSE;
|
||
return;
|
||
} else if ((nFlags & MK_LBUTTON) && (nFlags & MK_SHIFT) && AD.mode == ACTIONMODE_LOWER) {
|
||
OnLButtonDown(nFlags, point);
|
||
isMoving = FALSE;
|
||
return;
|
||
}
|
||
|
||
else if ((nFlags == MK_LBUTTON) && AD.mode == ACTIONMODE_FLATTENGROUND) {
|
||
m_TileChangeCount = 0;
|
||
|
||
// if(abs(m_FlattenLastX-x)<2 && abs(m_FlattenLastY-y)<2) //ReachableFrom(x+y*Map->GetIsoSize(), m_mapx+m_mapy*Map->GetIsoSize()))
|
||
int ground = Map->GetFielddataAt(x + (y)*Map->GetIsoSize())->wGround;
|
||
if (ground == 0xFFFF) {
|
||
ground = 0;
|
||
}
|
||
|
||
//if((*tiledata)[ground].bMorphable)
|
||
{
|
||
|
||
int left = -m_BrushSize_x / 2;
|
||
int right = m_BrushSize_x / 2 + 1;
|
||
int top = -m_BrushSize_y / 2;
|
||
int bottom = m_BrushSize_y / 2 + 1;
|
||
|
||
BOOL doNotSave = FALSE;
|
||
int n, m;
|
||
int isosize = Map->GetIsoSize();
|
||
|
||
for (m = left; m < right; m++) {
|
||
for (n = top; n < bottom; n++) {
|
||
int pos = x + m + (y + n) * isosize;
|
||
int ground = Map->GetFielddataAt(pos)->wGround;
|
||
if (ground == 0xFFFF) {
|
||
ground = 0;
|
||
}
|
||
/*int ground1=Map->GetFielddataAt(pos-m)->wGround;
|
||
if(ground1==0xFFFF) ground=0;
|
||
int ground2=Map->GetFielddataAt(pos-n*isosize)->wGround;
|
||
if(ground2==0xFFFF) ground=0;*/
|
||
if (!(*tiledata)[ground].bMorphable) {
|
||
|
||
{
|
||
if (n <= 0 /*&& !(*tiledata)[ground1].bMorphable*/) {
|
||
top = n + 1;
|
||
}
|
||
if (m <= 0 /*&& !(*tiledata)[ground2].bMorphable*/) {
|
||
left = m + 1;
|
||
}
|
||
if (n > 0 /*&& !(*tiledata)[ground1].bMorphable*/) {
|
||
bottom = n;
|
||
}
|
||
if (m > 0 /*&& !(*tiledata)[ground2].bMorphable*/) {
|
||
right = m;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (n < top) {
|
||
m = left;
|
||
n = top;
|
||
}
|
||
if (m < left) {
|
||
n = top;
|
||
m = left;
|
||
}
|
||
}
|
||
}
|
||
|
||
m_funcRect.left = x;
|
||
m_funcRect.top = y;
|
||
m_funcRect.bottom = y;
|
||
m_funcRect.right = x;
|
||
|
||
for (m = left; m < right; m++) {
|
||
for (n = top; n < bottom; n++) {
|
||
int ground = Map->GetFielddataAt(x + m + (y + n) * Map->GetIsoSize())->wGround;
|
||
if (ground == 0xFFFF) {
|
||
ground = 0;
|
||
}
|
||
|
||
if ((*tiledata)[ground].bMorphable) {
|
||
int i;
|
||
int max = isosize * isosize;
|
||
for (i = 0; i < max; i++) {
|
||
Map->SetReserved(i, 0);
|
||
}
|
||
// do not make any slopes yet, we do this once we´re finished with the whole area!
|
||
// helps to speed up performance!
|
||
ChangeTileHeight(x + m + (y + n) * isosize, m_FlattenHeight, FALSE, FALSE, TRUE);
|
||
} else {
|
||
if (n == 0 && m == 0) {
|
||
doNotSave = TRUE;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/*
|
||
Some trick for improving performance is using the m_funcRect parameter to get
|
||
the area that any ChangeTileHeight() calls affected.
|
||
*/
|
||
ASSERT(m_funcRect.left <= m_funcRect.right);
|
||
ASSERT(m_funcRect.top <= m_funcRect.bottom);
|
||
for (m = m_funcRect.left - 1; m <= m_funcRect.right + 1; m++) {
|
||
for (n = m_funcRect.top - 1; n <= m_funcRect.bottom + 1; n++) {
|
||
Map->CreateSlopesAt(m + n * isosize);
|
||
}
|
||
}
|
||
|
||
RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
if (!doNotSave) {
|
||
m_FlattenLastX = x;
|
||
m_FlattenLastY = y;
|
||
}
|
||
}
|
||
} else if ((nFlags & MK_LBUTTON) && (nFlags & MK_SHIFT) && AD.mode == ACTIONMODE_HEIGHTENTILE) {
|
||
OnLButtonDown(nFlags, point);
|
||
} else if ((nFlags & MK_LBUTTON) && (nFlags & MK_SHIFT) && AD.mode == ACTIONMODE_LOWERTILE) {
|
||
OnLButtonDown(nFlags, point);
|
||
} else if ((nFlags == MK_LBUTTON) && AD.mode == ACTIONMODE_WAYPOINT) { // waypoints
|
||
if (AD.type == 1) {
|
||
//delete waypoint
|
||
int w = Map->GetWaypointAt(x + y * Map->GetIsoSize());
|
||
if (w < 0) {
|
||
isMoving = FALSE;
|
||
return;
|
||
}
|
||
|
||
Map->DeleteWaypoint(w);
|
||
RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
} else if (AD.type == 0) {
|
||
int n = Map->GetWaypointAt(x + y * Map->GetIsoSize());
|
||
if (n >= 0) {
|
||
isMoving = FALSE;
|
||
return;
|
||
}
|
||
|
||
Map->AddWaypoint("", x + y * Map->GetIsoSize());
|
||
|
||
RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
} else if (AD.type >= 3) {
|
||
int n = Map->GetWaypointAt(x + y * Map->GetIsoSize());
|
||
if (n >= 0) {
|
||
isMoving = FALSE;
|
||
return;
|
||
}
|
||
|
||
char c[50];
|
||
int max = AD.type - 3;
|
||
|
||
// MW April 8th: place waypoints before selected one if they are not there!
|
||
// makes the user aware that he is doing something he should not do.
|
||
// he should not skip starting locations
|
||
// this logic is here to make sure there are no random starting points.
|
||
// I do not want to change this when saving the map, as triggers may rely on the
|
||
// actual starting position!
|
||
int i;
|
||
int e;
|
||
int notfound = -1;
|
||
for (e = 0; e < max; e++) {
|
||
BOOL bFound = FALSE;
|
||
|
||
for (i = 0; i < Map->GetWaypointCount(); i++) {
|
||
CString id;
|
||
DWORD pos;
|
||
Map->GetNthWaypointData(i, &id, &pos);
|
||
if (atoi(id) == e) bFound = TRUE;
|
||
if (bFound) break;
|
||
}
|
||
if (!bFound) {
|
||
notfound = e;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (notfound >= 0) max = notfound;
|
||
|
||
AD.type = 3 + max;
|
||
|
||
itoa(max, c, 10);
|
||
|
||
if (!Map->IsMultiplayer()) {
|
||
Map->AddWaypoint("99", x + (y + 1) * Map->GetIsoSize());
|
||
Map->AddWaypoint("98", x + (y)*Map->GetIsoSize());
|
||
} else {
|
||
Map->AddWaypoint(c, x + y * Map->GetIsoSize());
|
||
}
|
||
|
||
RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
}
|
||
|
||
} else if ((nFlags == MK_LBUTTON) && AD.mode == ACTIONMODE_CELLTAG) // celltags
|
||
{
|
||
if (AD.type == 1) {
|
||
int n = Map->GetCelltagAt(x + y * Map->GetIsoSize());
|
||
if (n < 0) {
|
||
isMoving = FALSE;
|
||
return;
|
||
}
|
||
Map->DeleteCelltag(n);
|
||
|
||
RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
} else if (AD.type == 4) {
|
||
Map->AddCelltag(AD.data_s, x + y * Map->GetIsoSize());
|
||
RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
}
|
||
} else if ((nFlags == MK_LBUTTON) && AD.mode == ACTIONMODE_NODE) // nodes
|
||
{
|
||
if (AD.type == 1) // create node, delete building
|
||
{
|
||
int n = Map->GetStructureAt(x + y * Map->GetIsoSize());
|
||
if (n < 0) {
|
||
isMoving = FALSE;
|
||
return;
|
||
}
|
||
|
||
STDOBJECTDATA sod;
|
||
Map->GetStdStructureData(n, &sod);
|
||
|
||
CString tmp;
|
||
if (Map->GetNodeAt(atoi(sod.x) + atoi(sod.y) * Map->GetIsoSize(), tmp) >= 0) {
|
||
SetError("You cannot place a node on another node");
|
||
{
|
||
isMoving = FALSE;
|
||
return;
|
||
};
|
||
}
|
||
|
||
Map->DeleteStructure(n);
|
||
|
||
NODE node;
|
||
node.x = sod.x;
|
||
node.y = sod.y;
|
||
node.house = sod.house;
|
||
node.type = sod.type;
|
||
|
||
Map->AddNode(&node, 0);
|
||
RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
|
||
} else if (AD.type == 0) // create node, don´t delete building
|
||
{
|
||
int n = Map->GetStructureAt(x + y * Map->GetIsoSize());
|
||
if (n < 0) {
|
||
isMoving = FALSE;
|
||
return;
|
||
}
|
||
|
||
STDOBJECTDATA sod;
|
||
Map->GetStdStructureData(n, &sod);
|
||
|
||
CString tmp;
|
||
if (Map->GetNodeAt(atoi(sod.x) + atoi(sod.y) * Map->GetIsoSize(), tmp) >= 0) {
|
||
SetError("You cannot place a node on another node");
|
||
{
|
||
isMoving = FALSE;
|
||
return;
|
||
};
|
||
}
|
||
|
||
NODE node;
|
||
node.x = sod.x;
|
||
node.y = sod.y;
|
||
node.type = sod.type;
|
||
node.house = sod.house;
|
||
|
||
Map->AddNode(&node, 0);
|
||
RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
|
||
} else if (AD.type == 2) // delete node
|
||
{
|
||
CString owner;
|
||
int n = Map->GetNodeAt(x + y * Map->GetIsoSize(), owner);
|
||
if (n < 0) {
|
||
isMoving = FALSE;
|
||
return;
|
||
}
|
||
Map->DeleteNode(owner, n);
|
||
|
||
RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
|
||
}
|
||
} else if ((nFlags == MK_LBUTTON) && AD.mode == ACTIONMODE_ERASEFIELD) {
|
||
int h;
|
||
DWORD dwPos = x + y * Map->GetIsoSize();
|
||
h = Map->GetInfantryAt(dwPos);
|
||
if (h > -1) {
|
||
Map->DeleteInfantry(h);
|
||
}
|
||
|
||
h = Map->GetUnitAt(dwPos);
|
||
if (h > -1) {
|
||
Map->DeleteUnit(h);
|
||
}
|
||
|
||
h = Map->GetStructureAt(dwPos);
|
||
if (h > -1) {
|
||
Map->DeleteStructure(h);
|
||
}
|
||
|
||
h = Map->GetAirAt(dwPos);
|
||
if (h > -1) {
|
||
Map->DeleteAircraft(h);
|
||
}
|
||
|
||
h = Map->GetTerrainAt(dwPos);
|
||
if (h > -1) {
|
||
Map->DeleteTerrain(h);
|
||
}
|
||
|
||
#ifdef SMUDGE_SUPP
|
||
const FIELDDATA& fd = *Map->GetFielddataAt(dwPos);
|
||
h = fd.smudge;
|
||
if (h > -1) {
|
||
Map->DeleteSmudge(h);
|
||
}
|
||
#endif
|
||
|
||
RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
|
||
} else if (AD.mode == ACTIONMODE_MAPTOOL) {
|
||
if (AD.tool)
|
||
AD.tool->onMouseMove(projCoords, mapCoords, MapToolMouseFlagsFromWin32(nFlags));
|
||
} else if ((nFlags & MK_LBUTTON) == MK_LBUTTON && (AD.mode == ACTIONMODE_PLACE || AD.mode == ACTIONMODE_RANDOMTERRAIN)) {
|
||
// ADD OBJECTS
|
||
|
||
if (AD.mode == ACTIONMODE_PLACE && AD.type == 6) Map->TakeSnapshot();
|
||
|
||
if (AD.mode == ACTIONMODE_PLACE && AD.type == 6 && AD.data == 5) // bridges
|
||
{
|
||
|
||
|
||
// calculate the x and y value...
|
||
int x = mapCoords.x;
|
||
int y = mapCoords.y;
|
||
|
||
if (abs(x - m_mapx) >= abs(y - m_mapy)) {
|
||
// it´s from bottom left to top right
|
||
y = m_mapy;
|
||
} else {
|
||
// from bottom right to top left
|
||
x = m_mapx;
|
||
}
|
||
|
||
// draw a line
|
||
|
||
int px1, py1, px2, py2;
|
||
px1 = m_mapx;
|
||
py1 = m_mapy;
|
||
px2 = x;
|
||
py2 = y;
|
||
if (theApp.m_Options.bFlat)
|
||
ToPhys(&px1, &py1);
|
||
else
|
||
ToPhys3d(&px1, &py1);
|
||
if (theApp.m_Options.bFlat)
|
||
ToPhys(&px2, &py2);
|
||
else
|
||
ToPhys3d(&px2, &py2);
|
||
px1 += f_x / 2 - m_viewOffset.x - r.left;
|
||
py1 += f_y / 2 - m_viewOffset.y - r.top;
|
||
px2 += f_x / 2 - m_viewOffset.x - r.left;
|
||
py2 += f_y / 2 - m_viewOffset.y - r.top;
|
||
|
||
CRect r;
|
||
GetWindowRect(r);
|
||
px1 += r.left;
|
||
px2 += r.left;
|
||
py1 += r.top;
|
||
py2 += r.top;
|
||
|
||
|
||
HDC dc;
|
||
lpdsBack->GetDC(&dc);
|
||
|
||
POINT p;
|
||
MoveToEx(dc, px1, py1, &p);
|
||
LineTo(dc, px2, py2);
|
||
|
||
lpdsBack->ReleaseDC(dc);
|
||
|
||
BlitBackbufferToHighRes();
|
||
RenderUIOverlay();
|
||
FlipHighResBuffer();
|
||
//lpds->Blt(NULL, lpdsBack, NULL, 0, 0);
|
||
|
||
} else {
|
||
PlaceCurrentObjectAt(x, y);
|
||
RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
}
|
||
|
||
|
||
if (AD.mode == ACTIONMODE_PLACE && AD.type == 6) {
|
||
Map->TakeSnapshot();
|
||
Map->Undo();
|
||
}
|
||
|
||
|
||
}
|
||
|
||
UpdateStatusBar(x, y);
|
||
|
||
|
||
isMoving = FALSE;
|
||
|
||
|
||
|
||
CView::OnMouseMove(nFlags, point);
|
||
}
|
||
|
||
|
||
|
||
void CIsoView::DrawCellCursor(const MapCoords& mapCoords, const DDSURFACEDESC2& desc)
|
||
{
|
||
ProjectedVec drawOffset(0 * 4, 0 * 3);
|
||
ProjectedCoords drawCoords2d = GetRenderTargetCoordinates(mapCoords, 0) + drawOffset;
|
||
ProjectedCoords drawCoords = GetRenderTargetCoordinates(mapCoords) + drawOffset;
|
||
|
||
static const COLORREF _cell_hilight_colors[16] = {
|
||
RGB(255, 255, 255), // level 0
|
||
RGB(170, 0, 170), // level 1
|
||
RGB(0, 170, 170), // level 2
|
||
RGB(0, 170, 0), // level 3
|
||
RGB(90, 255, 90), // level 4
|
||
RGB(255, 255, 90), // level 5
|
||
RGB(255, 50, 50), // level 6
|
||
RGB(170, 85, 0), // level 7
|
||
RGB(170, 0, 0), // level 8
|
||
RGB(85, 255, 255), // level 9
|
||
RGB(80, 80, 255), // level 10
|
||
RGB(0, 0, 170), // level 11
|
||
RGB(0, 0, 0), // level 12
|
||
RGB(85,85 ,85), // level 13
|
||
RGB(170, 170, 170), // level 14
|
||
RGB(255, 255, 255) // level 15
|
||
};
|
||
|
||
const FIELDDATA& m = *Map->GetFielddataAt(mapCoords.x + mapCoords.y * Map->GetIsoSize());
|
||
int tileheight = m.bHeight;
|
||
int new_tileheight = std::clamp(tileheight, 0, 16);
|
||
|
||
DrawCell(desc.lpSurface, desc.dwWidth, desc.dwHeight, desc.lPitch, drawCoords.x, drawCoords.y, 1, 1, m_color_converter->GetColor(_cell_hilight_colors[new_tileheight]), false, true, m_color_converter->GetColor(60, 60, 255));
|
||
|
||
LineDrawer l(desc.lpSurface, bpp, desc.dwWidth, desc.dwHeight, desc.lPitch);
|
||
|
||
POINT p1, p2, p3, p4;
|
||
p2.x = drawCoords2d.x + 1 * f_x / 2 + f_x / 2;
|
||
p2.y = drawCoords2d.y + 1 * f_y / 2;
|
||
p3.x = drawCoords2d.x + 1 * f_x / 2 - 1 * f_x / 2 + f_x / 2 - 1;
|
||
p3.y = drawCoords2d.y + 1 * f_y / 2 + 1 * f_y / 2 - 1;
|
||
p4.x = drawCoords2d.x - 1 * f_x / 2 + f_x / 2 - 1;
|
||
p4.y = drawCoords2d.y + 1 * f_y / 2 - 1;
|
||
|
||
POINT p5, p6, p7, p8;
|
||
p6.x = drawCoords.x + 1 * f_x / 2 + f_x / 2;
|
||
p6.y = drawCoords.y + 1 * f_y / 2;
|
||
p7.x = drawCoords.x + 1 * f_x / 2 - 1 * f_x / 2 + f_x / 2 - 1;
|
||
p7.y = drawCoords.y + 1 * f_y / 2 + 1 * f_y / 2 - 1;
|
||
p8.x = drawCoords.x - 1 * f_x / 2 + f_x / 2 - 1;
|
||
p8.y = drawCoords.y + 1 * f_y / 2 - 1;
|
||
|
||
auto col = m_color_converter->GetColor(60, 60, 60);
|
||
if (drawCoords2d != drawCoords) {
|
||
for (int y = 0; y < 2; ++y) {
|
||
l.MoveTo(p2.x + 1, p2.y + y);
|
||
l.LineTo(p6.x + 1, p6.y + y, col, LineStyle::Dotted_4);
|
||
l.MoveTo(p3.x, p3.y + 1 + y);
|
||
l.LineTo(p7.x, p7.y + 1 + y, col, LineStyle::Dotted_4);
|
||
l.MoveTo(p4.x - 1, p4.y + y);
|
||
l.LineTo(p8.x - 1, p8.y + y, col, LineStyle::Dotted_4);
|
||
|
||
l.MoveTo(p2.x, p2.y + y);
|
||
l.LineTo(p6.x, p6.y + y, col, LineStyle::Dotted_4);
|
||
l.MoveTo(p3.x + 1, p3.y + 1 + y);
|
||
l.LineTo(p7.x + 1, p7.y + 1 + y, col, LineStyle::Dotted_4);
|
||
l.MoveTo(p4.x, p4.y + y);
|
||
l.LineTo(p8.x, p8.y + y, col, LineStyle::Dotted_4);
|
||
}
|
||
}
|
||
}
|
||
|
||
const int valadded = 10000;
|
||
|
||
|
||
void CIsoView::OnRButtonUp(UINT nFlags, CPoint point)
|
||
{
|
||
if (rscroll) {
|
||
if (b_IsLoading) return;
|
||
|
||
ReleaseCapture();
|
||
KillTimer(11);
|
||
ShowCursor(TRUE);
|
||
CMyViewFrame& dlg = *(CMyViewFrame*)owner;
|
||
dlg.m_minimap.RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
|
||
}
|
||
|
||
|
||
if (nFlags == 0 && point.x == 0 && point.y == 0) {
|
||
m_drag = FALSE; return;
|
||
}
|
||
|
||
CIniFile& ini = Map->GetIniFile();
|
||
|
||
RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
|
||
if (!rscroll) m_drag = FALSE;
|
||
|
||
const auto projCoords = GetProjectedCoordinatesFromClientCoordinates(point);
|
||
const MapCoords mapCoords = GetMapCoordinatesFromClientCoordinates(point, (nFlags & MK_CONTROL) == MK_CONTROL);
|
||
|
||
const int x = mapCoords.x; // compat
|
||
const int y = mapCoords.y;
|
||
|
||
// context menu
|
||
if (AD.mode != 0 && !rscroll) {
|
||
bool ignoreClick = false;
|
||
if (AD.mode == ACTIONMODE_MAPTOOL) {
|
||
if (AD.tool)
|
||
ignoreClick = AD.tool->onRButtonUp(projCoords, mapCoords, MapToolMouseFlagsFromWin32(nFlags));
|
||
}
|
||
|
||
if (!ignoreClick) {
|
||
AD.reset();
|
||
|
||
CMyViewFrame& frame = *((CMyViewFrame*)owner);
|
||
frame.m_objectview->GetTreeCtrl().Select(frame.m_objectview->GetTreeCtrl().GetRootItem(), TVGN_CARET);
|
||
}
|
||
return;
|
||
}
|
||
|
||
rscroll = FALSE;
|
||
|
||
return;
|
||
|
||
|
||
|
||
|
||
CView::OnRButtonUp(nFlags, point);
|
||
}
|
||
|
||
// from old (popup menu) interface, taken over and used by OnLButtonDblClick
|
||
BOOL CIsoView::OnCommand(WPARAM wParam, LPARAM lParam)
|
||
{
|
||
int wNotifyCode = HIWORD(wParam); // notification code
|
||
int wID = LOWORD(wParam); // item, control, or accelerator identifier
|
||
HWND hwndCtl = (HWND)lParam; // handle of control
|
||
|
||
CIniFile& ini = Map->GetIniFile();
|
||
|
||
|
||
if (wID < valadded) {
|
||
// a standard menu, no popup!
|
||
|
||
switch (wID) {
|
||
case 4:
|
||
{
|
||
last_succeeded_operation = 54310;
|
||
//get the number
|
||
if (Map->GetAirAt(m_mapx + m_mapy * Map->GetIsoSize()) != -1) {
|
||
HandleProperties(Map->GetAirAt(m_mapx + m_mapy * Map->GetIsoSize()), 2);
|
||
} else if (Map->GetInfantryAt(m_mapx + m_mapy * Map->GetIsoSize()) != -1) {
|
||
last_succeeded_operation = 54311;
|
||
int z;
|
||
for (z = 0; z < SUBPOS_COUNT; z++)
|
||
if (Map->GetInfantryAt(m_mapx + m_mapy * Map->GetIsoSize(), z) != -1) HandleProperties(Map->GetInfantryAt(m_mapx + m_mapy * Map->GetIsoSize(), z), 0);
|
||
} else if (Map->GetUnitAt(m_mapx + m_mapy * Map->GetIsoSize()) != -1) {
|
||
HandleProperties(Map->GetUnitAt(m_mapx + m_mapy * Map->GetIsoSize()), 3);
|
||
} else if (Map->GetStructureAt(m_mapx + m_mapy * Map->GetIsoSize()) != -1) {
|
||
HandleProperties(Map->GetStructureAt(m_mapx + m_mapy * Map->GetIsoSize()), 1);
|
||
}
|
||
|
||
|
||
break;
|
||
}
|
||
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
return CView::OnCommand(wParam, lParam);
|
||
}
|
||
|
||
void CIsoView::HandleProperties(int n, int type)
|
||
{
|
||
CIniFile& ini = Map->GetIniFile();
|
||
|
||
if (n < 0) return;
|
||
switch (type) {
|
||
case 0:
|
||
{
|
||
last_succeeded_operation = 54312;
|
||
|
||
// infantry
|
||
|
||
INFANTRY data;
|
||
|
||
Map->GetInfantryData(n, &data);
|
||
|
||
last_succeeded_operation = 54313;
|
||
|
||
|
||
CInfantrie dlg(this);
|
||
char tmp[255];
|
||
dlg.Init((LPCTSTR)data.house, (LPCTSTR)data.strength, (LPCTSTR)data.action,
|
||
(LPCTSTR)data.direction, (LPCTSTR)data.tag, (LPCTSTR)data.flag1,
|
||
(LPCTSTR)data.group, (LPCTSTR)data.flag3, (LPCTSTR)data.flag4, (LPCTSTR)data.flag5);
|
||
|
||
int res = dlg.DoModal();
|
||
if (res == IDCANCEL) return;
|
||
|
||
data.action = dlg.m_action;
|
||
data.strength = dlg.m_strength;
|
||
data.tag = dlg.m_tag;
|
||
data.direction = dlg.m_direction;
|
||
data.house = dlg.m_house;
|
||
data.flag1 = dlg.m_flag1;
|
||
data.group = dlg.m_group;
|
||
data.flag3 = dlg.m_flag3;
|
||
data.flag4 = dlg.m_flag4;
|
||
data.flag5 = dlg.m_flag5;
|
||
|
||
|
||
Map->DeleteInfantry(n);
|
||
Map->AddInfantry(&data);
|
||
|
||
RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
break;
|
||
}
|
||
case 1:
|
||
{
|
||
// building
|
||
|
||
STRUCTURE data;
|
||
Map->GetStructureData(n, &data);
|
||
|
||
|
||
CBuilding dlg(this);
|
||
char tmp[255];
|
||
dlg.Init((LPCTSTR)data.house, (LPCTSTR)data.strength, (LPCTSTR)data.direction, (LPCTSTR)data.tag,
|
||
(LPCTSTR)data.flag1, (LPCTSTR)data.flag2, (LPCTSTR)data.energy,
|
||
(LPCTSTR)data.upgradecount, (LPCTSTR)data.spotlight, (LPCTSTR)data.upgrade1, (LPCTSTR)data.upgrade2,
|
||
(LPCTSTR)data.upgrade3, (LPCTSTR)data.flag3, (LPCTSTR)data.flag4);
|
||
dlg.m_type = data.type;
|
||
|
||
int res = dlg.DoModal();
|
||
if (res == IDCANCEL) return;
|
||
|
||
data.strength = dlg.m_strength;
|
||
data.tag = dlg.m_tag;
|
||
data.direction = dlg.m_direction;
|
||
data.house = dlg.m_house;
|
||
data.spotlight = dlg.m_spotlight;
|
||
data.flag1 = dlg.m_flag1;
|
||
data.flag2 = dlg.m_flag2;
|
||
data.flag3 = dlg.m_flag3;
|
||
data.flag4 = dlg.m_flag4;
|
||
data.energy = dlg.m_energy;
|
||
data.upgradecount = dlg.m_upgradecount;
|
||
data.upgrade1 = dlg.m_upgrade1;
|
||
data.upgrade2 = dlg.m_upgrade2;
|
||
data.upgrade3 = dlg.m_upgrade3;
|
||
|
||
|
||
|
||
Map->DeleteStructure(n);
|
||
Map->AddStructure(&data);
|
||
|
||
RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
break;
|
||
|
||
}
|
||
case 2:
|
||
{
|
||
// aircraft
|
||
|
||
AIRCRAFT data;
|
||
Map->GetAircraftData(n, &data);
|
||
|
||
|
||
CAircraft dlg(this);
|
||
char tmp[255];
|
||
dlg.Init(data.house, data.strength, data.direction, data.action,
|
||
data.tag, data.flag1, data.group, data.flag3, data.flag4);
|
||
|
||
int res = dlg.DoModal();
|
||
if (res == IDCANCEL) return;
|
||
|
||
data.action = dlg.m_action;
|
||
data.strength = dlg.m_strength;
|
||
data.tag = dlg.m_tag;
|
||
data.direction = dlg.m_direction;
|
||
data.house = dlg.m_house;
|
||
data.flag1 = dlg.m_flag1;
|
||
data.group = dlg.m_group;
|
||
data.flag3 = dlg.m_flag3;
|
||
data.flag4 = dlg.m_flag4;
|
||
|
||
|
||
Map->DeleteAircraft(n);
|
||
Map->AddAircraft(&data);
|
||
|
||
RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
break;
|
||
}
|
||
case 3:
|
||
{
|
||
// vehicle
|
||
|
||
UNIT data;
|
||
Map->GetUnitData(n, &data);
|
||
|
||
|
||
CUnit dlg(this);
|
||
char tmp[255];
|
||
dlg.Init(data.house, data.strength, data.direction, data.action,
|
||
data.tag, data.flag1, data.group, data.flag3, data.flag4, data.flag5, data.flag6);
|
||
|
||
int res = dlg.DoModal();
|
||
if (res == IDCANCEL) return;
|
||
|
||
data.action = dlg.m_action;
|
||
data.strength = dlg.m_strength;
|
||
data.tag = dlg.m_tag;
|
||
data.direction = dlg.m_direction;
|
||
data.house = dlg.m_house;
|
||
data.flag1 = dlg.m_flag1;
|
||
data.group = dlg.m_group;
|
||
data.flag3 = dlg.m_flag3;
|
||
data.flag4 = dlg.m_flag4;
|
||
data.flag5 = dlg.m_flag5;
|
||
data.flag6 = dlg.m_flag6;
|
||
|
||
Map->DeleteUnit(n);
|
||
Map->AddUnit(&data);
|
||
|
||
RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
break;
|
||
|
||
|
||
}
|
||
}
|
||
}
|
||
|
||
void CIsoView::OnLButtonDblClk(UINT nFlags, CPoint point)
|
||
{
|
||
|
||
|
||
if (b_IsLoading == TRUE) return;
|
||
|
||
m_NoMove = TRUE;
|
||
m_drag = FALSE;
|
||
|
||
const auto projCoords = GetProjectedCoordinatesFromClientCoordinates(point);
|
||
const MapCoords mapCoords = GetMapCoordinatesFromClientCoordinates(point, (nFlags & MK_CONTROL) == MK_CONTROL);
|
||
|
||
if (AD.mode == ACTIONMODE_MAPTOOL) {
|
||
if (AD.tool)
|
||
AD.tool->onLButtonDblClick(projCoords, mapCoords, MapToolMouseFlagsFromWin32(nFlags));
|
||
} else {
|
||
if (!Map->isInside(mapCoords))
|
||
return;
|
||
|
||
m_mapx = mapCoords.x;
|
||
m_mapy = mapCoords.y;
|
||
|
||
int pos = m_mapx + m_mapy * Map->GetIsoSize();
|
||
if (Map->GetCelltagAt(pos) < 0) {
|
||
OnCommand(4, 0);
|
||
} else
|
||
OnCommand(9, 0);
|
||
}
|
||
|
||
m_NoMove = FALSE;
|
||
|
||
CView::OnLButtonDblClk(nFlags, point);
|
||
}
|
||
|
||
void CIsoView::OnLButtonDown(UINT nFlags, CPoint point)
|
||
{
|
||
if (Map->GetIsoSize() == 0) return;
|
||
if (b_IsLoading == TRUE) return;
|
||
|
||
|
||
CIniFile& ini = Map->GetIniFile();
|
||
|
||
const auto projCoords = GetProjectedCoordinatesFromClientCoordinates(point);
|
||
const MapCoords mapCoords = GetMapCoordinatesFromClientCoordinates(point, (nFlags & MK_CONTROL) == MK_CONTROL);
|
||
|
||
|
||
|
||
const int x = mapCoords.x; // compat
|
||
const int y = mapCoords.y;
|
||
|
||
|
||
int mapwidth = Map->GetWidth();
|
||
int mapheight = Map->GetHeight();
|
||
//if(x>=Map->GetIsoSize() || y>=Map->GetIsoSize() || x<0 || y<0) return;
|
||
if (AD.mode != ACTIONMODE_COPY && AD.mode != ACTIONMODE_PASTE && AD.mode != ACTIONMODE_MAPTOOL) {
|
||
if (!Map->isInside(mapCoords))
|
||
return;
|
||
if (x < 1 || y < 1 || x + y<mapwidth + 1 || x + y>mapwidth + mapheight * 2 || (y + 1 > mapwidth && x - 1 < y - mapwidth) || (x + 1 > mapwidth && y + mapwidth - 1 < x))
|
||
return;
|
||
}
|
||
|
||
int px = m_mapx;
|
||
int py = m_mapy;
|
||
|
||
m_mapx = x;
|
||
m_mapy = y;
|
||
|
||
CStatusBarCtrl& stat = ((CMyViewFrame*)owner)->m_statbar.GetStatusBarCtrl();
|
||
|
||
if (AD.mode == ACTIONMODE_CLIFFFRONT || AD.mode == ACTIONMODE_CLIFFBACK) {
|
||
m_drag = TRUE;
|
||
} else if (AD.mode == ACTIONMODE_PASTE) {
|
||
Map->TakeSnapshot();
|
||
Map->Paste(m_mapx, m_mapy, AD.z_data);
|
||
Map->TakeSnapshot();
|
||
Map->Undo();
|
||
RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
} else if (AD.mode == ACTIONMODE_COPY) {
|
||
if (!m_drag) {
|
||
m_drag = TRUE;
|
||
} else // 2nd click
|
||
{
|
||
int x1, x2, y1, y2;
|
||
if (px < x) {
|
||
x1 = px;
|
||
x2 = x;
|
||
} else {
|
||
x1 = x;
|
||
x2 = px;
|
||
}
|
||
if (py < y) {
|
||
y1 = py;
|
||
y2 = y;
|
||
} else {
|
||
y1 = y;
|
||
y2 = py;
|
||
}
|
||
|
||
|
||
Map->Copy(x1, y1, x2 + 1, y2 + 1);
|
||
|
||
m_drag = FALSE;
|
||
}
|
||
} else if (Map->IsGroundObjectAt(m_mapx + m_mapy * Map->GetIsoSize()) && AD.mode == 0 && m_NoMove == FALSE) {
|
||
m_drag = TRUE;
|
||
m_moved = FALSE;
|
||
m_id = Map->GetInfantryAt(m_mapx + m_mapy * Map->GetIsoSize());
|
||
m_type = 0;
|
||
if (m_id < 0) {
|
||
m_id = Map->GetUnitAt(m_mapx + m_mapy * Map->GetIsoSize());
|
||
m_type = 3;
|
||
}
|
||
if (m_id < 0) {
|
||
m_id = Map->GetAirAt(m_mapx + m_mapy * Map->GetIsoSize());
|
||
m_type = 2;
|
||
}
|
||
if (m_id < 0) {
|
||
m_id = Map->GetTerrainAt(m_mapx + m_mapy * Map->GetIsoSize());
|
||
m_type = 4;
|
||
}
|
||
if (m_id < 0) {
|
||
m_id = Map->GetStructureAt(m_mapx + m_mapy * Map->GetIsoSize());
|
||
|
||
STDOBJECTDATA sod;
|
||
Map->GetStdStructureData(m_id, &sod);
|
||
m_mapx = atoi(sod.x);
|
||
m_mapy = atoi(sod.y);
|
||
|
||
m_type = 1;
|
||
}
|
||
|
||
} else if (AD.mode == ACTIONMODE_SETTILE) {
|
||
|
||
|
||
if ((nFlags & MK_CONTROL) && !(nFlags & MK_SHIFT)) {
|
||
// Fill the whole area
|
||
Sound(SOUND_LAYDOWNTILE);
|
||
|
||
Map->TakeSnapshot();
|
||
int i;
|
||
for (i = 0; i < Map->GetIsoSize() * Map->GetIsoSize(); i++)
|
||
Map->SetReserved(i, 0);
|
||
|
||
FillArea(x, y, AD.type, 0);
|
||
Map->TakeSnapshot();
|
||
Map->Undo();
|
||
} else {
|
||
// just place a single tile
|
||
|
||
if (!(nFlags & MK_SHIFT)) {
|
||
Sound(SOUND_LAYDOWNTILE);
|
||
}
|
||
|
||
PlaceTile(x, y, nFlags);
|
||
}
|
||
|
||
|
||
|
||
|
||
RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
} else if (AD.mode == ACTIONMODE_HIDETILESET) {
|
||
int ground = Map->GetFielddataAt(x + (y)*Map->GetIsoSize())->wGround;
|
||
if (ground == 0xFFFF) ground = 0;
|
||
|
||
//if(ground!=0)
|
||
HideTileSet((*tiledata)[ground].wTileSet);
|
||
RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
} else if (AD.mode == ACTIONMODE_HIDEFIELD) {
|
||
Map->HideField(x + y * Map->GetIsoSize(), TRUE);
|
||
RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
} else if (AD.mode == ACTIONMODE_HEIGHTEN) {
|
||
Map->TakeSnapshot();
|
||
|
||
m_TileChangeCount = 0;
|
||
//if(x==m_mapx && y==m_mapy)
|
||
//try
|
||
{
|
||
int ground = Map->GetFielddataAt(x + (y)*Map->GetIsoSize())->wGround;
|
||
if (ground == 0xFFFF) ground = 0;
|
||
|
||
if ((nFlags & MK_CONTROL) && !(*tiledata)[ground].bMorphable) {
|
||
SetError("Applying non-morphable terrain height change, please wait...");
|
||
stat.RedrawWindow();
|
||
stat.UpdateWindow();
|
||
}
|
||
|
||
m_funcRect.left = x;
|
||
m_funcRect.top = y;
|
||
m_funcRect.bottom = y;
|
||
m_funcRect.right = x;
|
||
|
||
if ((*tiledata)[ground].bMorphable) {
|
||
int f, n;
|
||
int oheight = Map->GetHeightAt(x + y * Map->GetIsoSize());
|
||
for (f = -m_BrushSize_x / 2; f < m_BrushSize_x / 2 + 1; f++) {
|
||
for (n = -m_BrushSize_y / 2; n < m_BrushSize_y / 2 + 1; n++) {
|
||
int pos = x + f + (y + n) * Map->GetIsoSize();
|
||
int ground = Map->GetFielddataAt(pos)->wGround;
|
||
if (ground == 0xFFFF) ground = 0;
|
||
|
||
if ((*tiledata)[ground].bMorphable && Map->GetHeightAt(pos) == oheight) {
|
||
Map->SetHeightAt(pos, oheight + 1);
|
||
}
|
||
}
|
||
}
|
||
for (f = -m_BrushSize_x / 2; f < m_BrushSize_x / 2 + 1; f++) {
|
||
for (n = -m_BrushSize_y / 2; n < m_BrushSize_y / 2 + 1; n++) {
|
||
int pos = x + f + (y + n) * Map->GetIsoSize();
|
||
int ground = Map->GetFielddataAt(pos)->wGround;
|
||
if (ground == 0xFFFF) ground = 0;
|
||
|
||
if ((*tiledata)[ground].bMorphable && Map->GetHeightAt(x + f + (y + n) * Map->GetIsoSize()) == oheight + 1) {
|
||
int i;
|
||
for (i = 0; i < Map->GetIsoSize() * Map->GetIsoSize(); i++)
|
||
Map->SetReserved(i, 0);
|
||
|
||
ChangeTileHeight(x + f + (y + n) * Map->GetIsoSize(), oheight + 1, FALSE, (nFlags & MK_CONTROL), TRUE);
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
int i;
|
||
for (i = 0; i < Map->GetIsoSize() * Map->GetIsoSize(); i++)
|
||
Map->SetReserved(i, 0);
|
||
|
||
// TODO: replace recursion, otherwise be aware of stack issues!
|
||
try {
|
||
ChangeTileHeight(x + (y)*Map->GetIsoSize(), Map->GetHeightAt(x + y * Map->GetIsoSize()) + 1, FALSE, !(nFlags & MK_CONTROL));
|
||
} catch (...) {
|
||
MessageBox("Stack is too small to complete operation!", "Error");
|
||
}
|
||
}
|
||
|
||
int f, n;
|
||
for (f = m_funcRect.left - 1; f <= m_funcRect.right + 1; f++) {
|
||
for (n = m_funcRect.top - 1; n <= m_funcRect.bottom + 1; n++) {
|
||
int pos = f + (n)*Map->GetIsoSize();
|
||
Map->CreateSlopesAt(pos);
|
||
}
|
||
}
|
||
|
||
|
||
/*CHANGEHEIGHTDATA d;
|
||
d.pos=x+y*Map->GetIsoSize();
|
||
d.bNonMorpheable=FALSE;
|
||
d.toHeight=Map->GetHeightAt(x+y*Map->GetIsoSize())+1;
|
||
DWORD id;
|
||
HANDLE hThread=CreateThread(NULL, 4000000, ChangeHeightThread, &d, NULL, &id);
|
||
SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL);
|
||
WaitForSingleObjectEx(hThread, INFINITE, FALSE);*/
|
||
|
||
|
||
|
||
RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
Map->TakeSnapshot();
|
||
Map->Undo();
|
||
}
|
||
//catch(...)
|
||
{
|
||
// MessageBox("Error occured","Error");
|
||
}
|
||
} else if (AD.mode == ACTIONMODE_LOWER) {
|
||
Map->TakeSnapshot();
|
||
|
||
m_TileChangeCount = 0;
|
||
//if(x==m_mapx && y==m_mapy)
|
||
//try
|
||
{
|
||
int ground = Map->GetFielddataAt(x + (y)*Map->GetIsoSize())->wGround;
|
||
if (ground == 0xFFFF) ground = 0;
|
||
|
||
if ((nFlags & MK_CONTROL) && !(*tiledata)[ground].bMorphable) {
|
||
SetError("Applying non-morphable terrain height change, please wait...");
|
||
stat.RedrawWindow();
|
||
stat.UpdateWindow();
|
||
}
|
||
|
||
int i;
|
||
|
||
m_funcRect.left = x;
|
||
m_funcRect.top = y;
|
||
m_funcRect.bottom = y;
|
||
m_funcRect.right = x;
|
||
|
||
if ((*tiledata)[ground].bMorphable) {
|
||
int f, n;
|
||
int oheight = Map->GetHeightAt(x + y * Map->GetIsoSize());
|
||
for (f = -m_BrushSize_x / 2; f < m_BrushSize_x / 2 + 1; f++) {
|
||
for (n = -m_BrushSize_y / 2; n < m_BrushSize_y / 2 + 1; n++) {
|
||
int pos = x + f + (y + n) * Map->GetIsoSize();
|
||
int ground = Map->GetFielddataAt(pos)->wGround;
|
||
if (ground == 0xFFFF) ground = 0;
|
||
|
||
if ((*tiledata)[ground].bMorphable && Map->GetHeightAt(pos) == oheight) {
|
||
Map->SetHeightAt(pos, oheight - 1);
|
||
}
|
||
}
|
||
}
|
||
for (f = -m_BrushSize_x / 2; f < m_BrushSize_x / 2 + 1; f++) {
|
||
for (n = -m_BrushSize_y / 2; n < m_BrushSize_y / 2 + 1; n++) {
|
||
int pos = x + f + (y + n) * Map->GetIsoSize();
|
||
int ground = Map->GetFielddataAt(pos)->wGround;
|
||
if (ground == 0xFFFF) ground = 0;
|
||
|
||
if ((*tiledata)[ground].bMorphable && Map->GetHeightAt(x + f + (y + n) * Map->GetIsoSize()) == oheight - 1) {
|
||
for (i = 0; i < Map->GetIsoSize() * Map->GetIsoSize(); i++)
|
||
Map->SetReserved(i, 0);
|
||
|
||
ChangeTileHeight(x + f + (y + n) * Map->GetIsoSize(), oheight - 1, FALSE, (nFlags & MK_CONTROL), TRUE);
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
for (i = 0; i < Map->GetIsoSize() * Map->GetIsoSize(); i++)
|
||
Map->SetReserved(i, 0);
|
||
|
||
try {
|
||
ChangeTileHeight(x + (y)*Map->GetIsoSize(), Map->GetHeightAt(x + y * Map->GetIsoSize()) - 1, FALSE, !(nFlags & MK_CONTROL));
|
||
} catch (...) {
|
||
MessageBox("Stack is too small to complete operation!", "Error");
|
||
}
|
||
}
|
||
|
||
int f, n;
|
||
for (f = m_funcRect.left - 1; f <= m_funcRect.right + 1; f++) {
|
||
for (n = m_funcRect.top - 1; n <= m_funcRect.bottom + 1; n++) {
|
||
int pos = f + (n)*Map->GetIsoSize();
|
||
Map->CreateSlopesAt(pos);
|
||
}
|
||
}
|
||
|
||
/*CHANGEHEIGHTDATA d;
|
||
d.pos=x+y*Map->GetIsoSize();
|
||
d.bNonMorpheable=FALSE;
|
||
d.toHeight=Map->GetHeightAt(x+y*Map->GetIsoSize())-1;
|
||
DWORD id;
|
||
HANDLE hThread=CreateThread(NULL, 4000000, ChangeHeightThread, &d, NULL, &id);
|
||
SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL);
|
||
WaitForSingleObjectEx(hThread, INFINITE, FALSE);*/
|
||
|
||
RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
}
|
||
//catch(...)
|
||
{
|
||
// MessageBox("Error occured","Error");
|
||
}
|
||
|
||
Map->TakeSnapshot();
|
||
Map->Undo();
|
||
} else if (AD.mode == ACTIONMODE_HEIGHTENTILE) {
|
||
Map->TakeSnapshot();
|
||
|
||
int n, m;
|
||
for (m = -m_BrushSize_x / 2; m < m_BrushSize_x / 2 + 1; m++) {
|
||
for (n = -m_BrushSize_y / 2; n < m_BrushSize_y / 2 + 1; n++) {
|
||
Map->SetHeightAt(x + m + (y + n) * Map->GetIsoSize(), Map->GetHeightAt(x + m + (y + n) * Map->GetIsoSize()) + 1);
|
||
}
|
||
}
|
||
|
||
if (nFlags & MK_CONTROL)
|
||
for (m = -m_BrushSize_x / 2 - 1; m < m_BrushSize_x / 2 + 2; m++) {
|
||
for (n = -m_BrushSize_y / 2 - 1; n < m_BrushSize_y / 2 + 2; n++) {
|
||
Map->CreateSlopesAt(x + m + (y + n) * Map->GetIsoSize());
|
||
}
|
||
}
|
||
|
||
Map->TakeSnapshot();
|
||
Map->Undo();
|
||
|
||
RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
} else if (AD.mode == ACTIONMODE_LOWERTILE) {
|
||
Map->TakeSnapshot();
|
||
|
||
int n, m;
|
||
for (m = -m_BrushSize_x / 2; m < m_BrushSize_x / 2 + 1; m++) {
|
||
for (n = -m_BrushSize_y / 2; n < m_BrushSize_y / 2 + 1; n++) {
|
||
Map->SetHeightAt(x + m + (y + n) * Map->GetIsoSize(), Map->GetHeightAt(x + m + (y + n) * Map->GetIsoSize()) - 1);
|
||
}
|
||
}
|
||
|
||
if (nFlags & MK_CONTROL)
|
||
for (m = -m_BrushSize_x / 2 - 1; m < m_BrushSize_x / 2 + 2; m++) {
|
||
for (n = -m_BrushSize_y / 2 - 1; n < m_BrushSize_y / 2 + 2; n++) {
|
||
Map->CreateSlopesAt(x + m + (y + n) * Map->GetIsoSize());
|
||
}
|
||
}
|
||
|
||
Map->TakeSnapshot();
|
||
Map->Undo();
|
||
|
||
RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
} else if (AD.mode == ACTIONMODE_FLATTENGROUND) {
|
||
Map->TakeSnapshot();
|
||
|
||
m_FlattenHeight = Map->GetHeightAt(x + y * Map->GetIsoSize());
|
||
m_FlattenLastX = x;
|
||
m_FlattenLastY = y;
|
||
|
||
Map->TakeSnapshot();
|
||
Map->Undo();
|
||
} else if (Map->GetWaypointAt(m_mapx + m_mapy * Map->GetIsoSize()) >= 0 && AD.mode == 0) {
|
||
m_drag = TRUE;
|
||
m_id = Map->GetWaypointAt(m_mapx + m_mapy * Map->GetIsoSize());
|
||
m_type = 6;
|
||
} else if (Map->GetCelltagAt(m_mapx + m_mapy * Map->GetIsoSize()) >= 0 && AD.mode == 0) {
|
||
m_drag = TRUE;
|
||
m_id = Map->GetCelltagAt(m_mapx + m_mapy * Map->GetIsoSize());
|
||
m_type = 5;
|
||
} else if ((AD.mode < 3 || AD.mode>4) || (AD.mode == 3 && AD.type == 0) || (AD.mode >= 3 && AD.mode <= 4 && AD.type == 1)) {
|
||
OnMouseMove(nFlags, point);
|
||
} else if (AD.mode == 3) {
|
||
if (AD.type == 2) {
|
||
// create waypoint
|
||
CWaypointID w(this);
|
||
if (w.DoModal() != IDCANCEL) {
|
||
int n = w.m_value;
|
||
|
||
char id[50];
|
||
itoa(n, id, 10);
|
||
Map->AddWaypoint(id, x + y * Map->GetIsoSize());
|
||
RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
}
|
||
}
|
||
if (AD.type >= 3) OnMouseMove(nFlags, point);
|
||
|
||
}
|
||
|
||
else if (AD.mode == 4) {
|
||
if (AD.type == 0) {
|
||
// create celltag
|
||
CCellTag w(this);
|
||
if (w.DoModal() != IDCANCEL) {
|
||
Map->AddCelltag(w.m_tag, x + y * Map->GetIsoSize());
|
||
|
||
RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
}
|
||
}
|
||
if (AD.type == 2) {
|
||
// change celltag properties
|
||
int n = Map->GetCelltagAt(x + y * Map->GetIsoSize());
|
||
if (n < 0) return;
|
||
|
||
DWORD dwPos;
|
||
CString tag;
|
||
|
||
Map->GetCelltagData(n, &tag, &dwPos);
|
||
|
||
|
||
|
||
CCellTag dlg(this);
|
||
|
||
dlg.m_tag = tag;
|
||
dlg.m_tag += " (";
|
||
dlg.m_tag += GetParam(Map->GetIniFile().GetString("Tags", tag), 1);
|
||
dlg.m_tag += ")";
|
||
|
||
if (dlg.DoModal() == IDCANCEL) return;
|
||
|
||
Map->DeleteCelltag(n);
|
||
|
||
Map->AddCelltag(dlg.m_tag, dwPos);
|
||
|
||
RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
}
|
||
|
||
}
|
||
|
||
|
||
|
||
CView::OnLButtonDown(nFlags, point);
|
||
}
|
||
|
||
void CIsoView::PlaceTile(const int x, const int y, const UINT nMouseFlags)
|
||
{
|
||
Map->TakeSnapshot(TRUE, x - 6, y - 6, x + (*tiledata)[AD.type].cx * m_BrushSize_x + 7, y + (*tiledata)[AD.type].cy * m_BrushSize_y + 7);
|
||
int i, e, f, n;
|
||
int p = 0;
|
||
int width = (*tiledata)[AD.type].cx;
|
||
int height = (*tiledata)[AD.type].cy;
|
||
int pos = x - width + 1 + (y - height + 1) * Map->GetIsoSize();
|
||
int startheight = Map->GetHeightAt(x + y * Map->GetIsoSize()) + AD.z_data;
|
||
int ground = Map->GetFielddataAt(x + y * Map->GetIsoSize())->wGround;
|
||
if (ground == 0xFFFF) ground = 0;
|
||
startheight -= (*tiledata)[ground].tiles[Map->GetFielddataAt(x + y * Map->GetIsoSize())->bSubTile].bZHeight;
|
||
for (f = 0; f < m_BrushSize_x; f++) {
|
||
for (n = 0; n < m_BrushSize_y; n++) {
|
||
int tile = AD.type;
|
||
if (AD.data == 1) {
|
||
int n = rand() * 5 / RAND_MAX;
|
||
tile += n;
|
||
|
||
}
|
||
p = 0;
|
||
for (i = 0; i < (*tiledata)[AD.type].cx; i++) {
|
||
for (e = 0; e < (*tiledata)[AD.type].cy; e++) {
|
||
|
||
if (x - width + 1 + f * width + i >= Map->GetIsoSize() ||
|
||
y - height + 1 + n * height + e >= Map->GetIsoSize()) {
|
||
|
||
} else
|
||
if ((*tiledata)[AD.type].tiles[p].pic != NULL) {
|
||
Map->SetHeightAt(pos + i + f * width + (e + n * height) * Map->GetIsoSize(), startheight + (*tiledata)[AD.type].tiles[p].bZHeight);
|
||
Map->SetTileAt(pos + i + f * width + (e + n * height) * Map->GetIsoSize(), tile, p);
|
||
|
||
}
|
||
p++;
|
||
}
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
if (!((nMouseFlags & MK_CONTROL) && (nMouseFlags & MK_SHIFT))) {
|
||
if (!theApp.m_Options.bDisableAutoShore) Map->CreateShore(x - 5, y - 5, x + (*tiledata)[AD.type].cx * m_BrushSize_x + 5, y + (*tiledata)[AD.type].cy * m_BrushSize_y + 5, FALSE);
|
||
//Map->CreateShore(0,0,Map->GetIsoSize(), Map->GetIsoSize());
|
||
|
||
for (f = 0; f < m_BrushSize_x; f++) {
|
||
for (n = 0; n < m_BrushSize_y; n++) {
|
||
p = 0;
|
||
for (i = -1; i < (*tiledata)[AD.type].cx + 1; i++) {
|
||
for (e = -1; e < (*tiledata)[AD.type].cy + 1; e++) {
|
||
|
||
Map->SmoothAllAt(pos + i + f * width + (e + n * height) * Map->GetIsoSize());
|
||
|
||
p++;
|
||
}
|
||
}
|
||
|
||
}
|
||
}
|
||
}
|
||
|
||
// now make current tiles available for redo
|
||
Map->TakeSnapshot(TRUE, x - 6, y - 6, x + (*tiledata)[AD.type].cx * m_BrushSize_x + 6, y + (*tiledata)[AD.type].cy * m_BrushSize_y + 6);
|
||
Map->Undo();
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
void CIsoView::OnLButtonUp(UINT nFlags, CPoint point)
|
||
{
|
||
if (b_IsLoading == TRUE) return;
|
||
|
||
CIniFile& ini = Map->GetIniFile();
|
||
|
||
const auto projCoords = GetProjectedCoordinatesFromClientCoordinates(point);
|
||
const MapCoords mapCoords = GetMapCoordinatesFromClientCoordinates(point, (nFlags & MK_CONTROL) == MK_CONTROL);
|
||
|
||
const int dx = mapCoords.x; // compat
|
||
const int dy = mapCoords.y;
|
||
|
||
|
||
//if(dx>=Map->GetIsoSize() || dy>=Map->GetIsoSize() || dx<0 || dy<0) return;
|
||
int mapwidth = Map->GetWidth();
|
||
int mapheight = Map->GetHeight();
|
||
if (AD.mode != ACTIONMODE_COPY && AD.mode != ACTIONMODE_PASTE && AD.mode != ACTIONMODE_MAPTOOL) {
|
||
if (!Map->isInside(mapCoords))
|
||
return;
|
||
if (dx < 1 || dy < 1 || dx + dy<mapwidth + 1 || dx + dy>mapwidth + mapheight * 2 || (dy + 1 > mapwidth && dx - 1 < dy - mapwidth) || (dx + 1 > mapwidth && dy + mapwidth - 1 < dx))
|
||
return;
|
||
}
|
||
|
||
|
||
char fx[50], fy[50];
|
||
itoa(dx, fx, 10);
|
||
itoa(dy, fy, 10);
|
||
|
||
int x, y;
|
||
x = dx;
|
||
y = dy;
|
||
|
||
// check if user did select something else than 0 in object browser
|
||
if (AD.mode != 0 && AD.mode != ACTIONMODE_COPY) {
|
||
if (m_moved)
|
||
m_drag = FALSE;
|
||
m_moved = FALSE;
|
||
}
|
||
|
||
if (AD.mode == ACTIONMODE_FLATTENGROUND) {
|
||
Map->TakeSnapshot();
|
||
Map->Undo();
|
||
}
|
||
if (AD.mode == ACTIONMODE_CLIFFFRONT || AD.mode == ACTIONMODE_CLIFFBACK) {
|
||
m_drag = FALSE;
|
||
Map->Redo();
|
||
/*Map->TakeSnapshot();
|
||
|
||
if(AD.mode==ACTIONMODE_CLIFFFRONT)
|
||
{
|
||
CFrontCliffModifier f;
|
||
f.PlaceCliff(m_mapx, m_mapy, x, y);
|
||
}
|
||
else if(AD.mode==ACTIONMODE_CLIFFBACK)
|
||
{
|
||
CBackCliffModifier f;
|
||
f.PlaceCliff(m_mapx, m_mapy, x, y);
|
||
}*/
|
||
|
||
RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
}
|
||
|
||
if (AD.mode == ACTIONMODE_COPY && m_drag) {
|
||
/*m_drag=FALSE;
|
||
|
||
int x1, x2, y1, y2;
|
||
if(m_mapx<x) { x1=m_mapx; x2=x; } else { x1=x; x2=m_mapx; }
|
||
if(m_mapy<y) { y1=m_mapy; y2=y; } else { y1=y; y2=m_mapy; }
|
||
|
||
|
||
Map->Copy(x1, y1, x2+1, y2+1);*/
|
||
m_moved = FALSE;
|
||
}
|
||
|
||
if (m_drag && m_moved) {
|
||
m_moved = FALSE;
|
||
|
||
// ok, drag the object at m_mapx/m_mapy to x/y
|
||
int x = dx, y = dy;
|
||
char strX[15], strY[15];
|
||
itoa(x, strX, 10);
|
||
itoa(y, strY, 10);
|
||
switch (m_type) {
|
||
case 0: // drag infantry
|
||
{
|
||
INFANTRY infantry;
|
||
Map->GetInfantryData(m_id, &infantry);
|
||
infantry.x = strX;
|
||
infantry.y = strY;
|
||
infantry.pos = "-1";
|
||
|
||
if ((nFlags != MK_SHIFT)) {
|
||
Map->DeleteInfantry(m_id);
|
||
}
|
||
|
||
Map->AddInfantry(&infantry);
|
||
|
||
break;
|
||
}
|
||
case 1: // drag structure
|
||
{
|
||
STRUCTURE structure;
|
||
Map->GetStructureData(m_id, &structure);
|
||
structure.x = strX;
|
||
structure.y = strY;
|
||
|
||
if ((nFlags != MK_SHIFT)) {
|
||
Map->DeleteStructure(m_id);
|
||
}
|
||
|
||
Map->AddStructure(&structure);
|
||
|
||
break;
|
||
}
|
||
case 2: // drag aircraft
|
||
{
|
||
AIRCRAFT aircraft;
|
||
Map->GetAircraftData(m_id, &aircraft);
|
||
aircraft.x = strX;
|
||
aircraft.y = strY;
|
||
|
||
|
||
if ((nFlags != MK_SHIFT)) {
|
||
Map->DeleteAircraft(m_id);
|
||
}
|
||
|
||
Map->AddAircraft(&aircraft);
|
||
|
||
break;
|
||
}
|
||
case 3: // drag vehicles
|
||
{
|
||
UNIT unit;
|
||
Map->GetUnitData(m_id, &unit);
|
||
unit.x = strX;
|
||
unit.y = strY;
|
||
|
||
if (!(nFlags == MK_SHIFT)) {
|
||
Map->DeleteUnit(m_id);
|
||
}
|
||
|
||
Map->AddUnit(&unit);
|
||
|
||
break;
|
||
}
|
||
case 4: // drag terrain
|
||
{
|
||
CString type;
|
||
|
||
Map->GetTerrainData(m_id, &type);
|
||
|
||
if ((nFlags != MK_SHIFT)) {
|
||
Map->DeleteTerrain(m_id);
|
||
}
|
||
|
||
Map->AddTerrain(type, x + y * Map->GetIsoSize());
|
||
break;
|
||
}
|
||
|
||
case 5: // drag celltag
|
||
{
|
||
CString tag;
|
||
DWORD dwPos;
|
||
Map->GetCelltagData(m_id, &tag, &dwPos);
|
||
|
||
if ((nFlags != MK_SHIFT)) {
|
||
Map->DeleteCelltag(m_id);
|
||
}
|
||
|
||
Map->AddCelltag(tag, x + y * Map->GetIsoSize());
|
||
break;
|
||
}
|
||
case 6: // drag waypoint
|
||
{
|
||
CString ID;
|
||
DWORD dwPos;
|
||
|
||
Map->GetWaypointData(m_id, &ID, &dwPos);
|
||
|
||
if (!(nFlags == MK_SHIFT)) {
|
||
Map->DeleteWaypoint(m_id);
|
||
}
|
||
|
||
Map->AddWaypoint(ID, x + y * Map->GetIsoSize());
|
||
break;
|
||
}
|
||
}
|
||
|
||
|
||
|
||
m_drag = FALSE;
|
||
line.left = 0;
|
||
line.top = 0;
|
||
line.right = 0;
|
||
line.bottom = 0;
|
||
|
||
RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
} else if (AD.mode == ACTIONMODE_MAPTOOL) {
|
||
if (AD.tool)
|
||
AD.tool->onLButtonUp(projCoords, mapCoords, MapToolMouseFlagsFromWin32(nFlags));
|
||
} else if (AD.mode == ACTIONMODE_PLACE) // painting stuff
|
||
{
|
||
m_moved = FALSE;
|
||
if (AD.type == 6) // Overlay
|
||
{
|
||
if (AD.data == 5) // birdges
|
||
{
|
||
if (x == m_mapx && y == m_mapy) return;
|
||
|
||
int ovrltype = 0x18;
|
||
if (abs(x - m_mapx) >= abs(y - m_mapy)) {
|
||
// it´s from bottom left to top right
|
||
y = m_mapy;
|
||
ovrltype = 0x19;
|
||
} else {
|
||
// from bottom right to top left
|
||
x = m_mapx;
|
||
ovrltype = 0x18;
|
||
}
|
||
|
||
int tmp;
|
||
|
||
if (x < m_mapx) {
|
||
tmp = m_mapx;
|
||
m_mapx = x;
|
||
x = tmp;
|
||
}
|
||
if (y < m_mapy) {
|
||
tmp = m_mapy;
|
||
m_mapy = y;
|
||
y = tmp;
|
||
}
|
||
|
||
// okay, now we can do it...
|
||
int i;
|
||
if (AD.data2 == 0) // big bridge
|
||
{
|
||
int startheight = Map->GetFielddataAt(m_mapx + m_mapy * Map->GetIsoSize())->bHeight;
|
||
|
||
if (y == m_mapy) {
|
||
for (i = m_mapx; i <= x; i++) {
|
||
if (Map->GetFielddataAt(i + m_mapy * Map->GetIsoSize())->bHeight == startheight - 4) {
|
||
startheight = Map->GetFielddataAt(i + m_mapy * Map->GetIsoSize())->bHeight;
|
||
break;
|
||
}
|
||
}
|
||
} else {
|
||
for (i = m_mapy; i <= y; i++) {
|
||
if (Map->GetFielddataAt(m_mapx + i * Map->GetIsoSize())->bHeight == startheight - 4) {
|
||
startheight = Map->GetFielddataAt(m_mapx + i * Map->GetIsoSize())->bHeight;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (y == m_mapy) {
|
||
for (i = m_mapx; i <= x; i++) {
|
||
if (Map->GetFielddataAt(i + m_mapy * Map->GetIsoSize())->bHeight == startheight) {
|
||
Map->SetOverlayAt(i + m_mapy * Map->GetIsoSize(), ovrltype);
|
||
Map->SetOverlayDataAt(i + m_mapy * Map->GetIsoSize(), 0x9);
|
||
}
|
||
}
|
||
} else {
|
||
for (i = m_mapy; i <= y; i++) {
|
||
if (Map->GetFielddataAt(m_mapx + i * Map->GetIsoSize())->bHeight == startheight) {
|
||
Map->SetOverlayAt(m_mapx + i * Map->GetIsoSize(), ovrltype);
|
||
Map->SetOverlayDataAt(m_mapx + i * Map->GetIsoSize(), 0x0);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if (AD.data2 == 2) // big track bridge
|
||
{
|
||
int startheight = Map->GetFielddataAt(m_mapx + m_mapy * Map->GetIsoSize())->bHeight;
|
||
|
||
if (y == m_mapy) {
|
||
for (i = m_mapx; i <= x; i++) {
|
||
if (Map->GetFielddataAt(i + m_mapy * Map->GetIsoSize())->bHeight == startheight - 4) {
|
||
startheight = Map->GetFielddataAt(i + m_mapy * Map->GetIsoSize())->bHeight;
|
||
break;
|
||
}
|
||
}
|
||
} else {
|
||
for (i = m_mapy; i <= y; i++) {
|
||
if (Map->GetFielddataAt(m_mapx + i * Map->GetIsoSize())->bHeight == startheight - 4) {
|
||
startheight = Map->GetFielddataAt(m_mapx + i * Map->GetIsoSize())->bHeight;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (y == m_mapy) {
|
||
for (i = m_mapx; i <= x; i++) {
|
||
if (Map->GetFielddataAt(i + m_mapy * Map->GetIsoSize())->bHeight == startheight) {
|
||
|
||
Map->SetOverlayAt(i + m_mapy * Map->GetIsoSize(), 0x3c);
|
||
#ifdef RA2_MODE
|
||
Map->SetOverlayAt(i + m_mapy * Map->GetIsoSize(), 0xee);
|
||
#endif
|
||
Map->SetOverlayDataAt(i + m_mapy * Map->GetIsoSize(), 0x9);
|
||
}
|
||
}
|
||
} else {
|
||
for (i = m_mapy; i <= y; i++) {
|
||
if (Map->GetFielddataAt(m_mapx + i * Map->GetIsoSize())->bHeight == startheight) {
|
||
Map->SetOverlayAt(m_mapx + i * Map->GetIsoSize(), 0x3b);
|
||
#ifdef RA2_MODE
|
||
Map->SetOverlayAt(m_mapx + i * Map->GetIsoSize(), 0xed);
|
||
#endif
|
||
Map->SetOverlayDataAt(m_mapx + i * Map->GetIsoSize(), 0x0);
|
||
}
|
||
}
|
||
}
|
||
|
||
/*if(y==m_mapy)
|
||
{
|
||
for(i=m_mapx;i<=x;i++)
|
||
{
|
||
Map->SetOverlayAt(i+m_mapy*Map->GetIsoSize(), 0x3b);
|
||
Map->SetOverlayDataAt(i+m_mapy*Map->GetIsoSize(), 0x9);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
for(i=m_mapy;i<=y;i++)
|
||
{
|
||
Map->SetOverlayAt(m_mapx+i*Map->GetIsoSize(), 0x3b);
|
||
Map->SetOverlayDataAt(m_mapx+i*Map->GetIsoSize(), 0x0);
|
||
}
|
||
}*/
|
||
} else if (AD.data2 == 1 || AD.data2 == 3) // small bridge
|
||
{
|
||
int start = 0x4a;
|
||
if (AD.data2 == 3) start = 0xcd;
|
||
|
||
if (y == m_mapy) {
|
||
srand((unsigned)time(NULL));
|
||
for (i = m_mapx + 1; i <= x - 1; i++) {
|
||
|
||
int v2 = ((float)rand() / (float)RAND_MAX) * 4;
|
||
|
||
Map->SetOverlayAt(i + (m_mapy - 1) * Map->GetIsoSize(), start + 9 + v2);
|
||
Map->SetOverlayDataAt(i + (m_mapy - 1) * Map->GetIsoSize(), 0x0);
|
||
Map->SetOverlayAt(i + (m_mapy + 0) * Map->GetIsoSize(), start + 9 + v2);
|
||
Map->SetOverlayDataAt(i + (m_mapy + 0) * Map->GetIsoSize(), 0x1);
|
||
Map->SetOverlayAt(i + (m_mapy + 1) * Map->GetIsoSize(), start + 9 + v2);
|
||
Map->SetOverlayDataAt(i + (m_mapy + 1) * Map->GetIsoSize(), 0x2);
|
||
}
|
||
Map->SetOverlayAt(m_mapx + (m_mapy - 1) * Map->GetIsoSize(), start + 22);
|
||
Map->SetOverlayAt(m_mapx + (m_mapy - 0) * Map->GetIsoSize(), start + 22);
|
||
Map->SetOverlayAt(m_mapx + (m_mapy + 1) * Map->GetIsoSize(), start + 22);
|
||
Map->SetOverlayDataAt(m_mapx + (m_mapy - 1) * Map->GetIsoSize(), 0x0);
|
||
Map->SetOverlayDataAt(m_mapx + (m_mapy - 0) * Map->GetIsoSize(), 0x1);
|
||
Map->SetOverlayDataAt(m_mapx + (m_mapy + 1) * Map->GetIsoSize(), 0x2);
|
||
|
||
Map->SetOverlayAt(x + (m_mapy - 1) * Map->GetIsoSize(), start + 24);
|
||
Map->SetOverlayAt(x + (m_mapy - 0) * Map->GetIsoSize(), start + 24);
|
||
Map->SetOverlayAt(x + (m_mapy + 1) * Map->GetIsoSize(), start + 24);
|
||
Map->SetOverlayDataAt(x + (m_mapy - 1) * Map->GetIsoSize(), 0x0);
|
||
Map->SetOverlayDataAt(x + (m_mapy - 0) * Map->GetIsoSize(), 0x1);
|
||
Map->SetOverlayDataAt(x + (m_mapy + 1) * Map->GetIsoSize(), 0x2);
|
||
|
||
|
||
} else {
|
||
srand((unsigned)time(NULL));
|
||
|
||
for (i = m_mapy + 1; i <= y - 1; i++) {
|
||
|
||
int v2 = ((float)rand() / (float)RAND_MAX) * 4;
|
||
|
||
Map->SetOverlayAt((m_mapx - 1) + i * Map->GetIsoSize(), start + v2);
|
||
Map->SetOverlayDataAt((m_mapx - 1) + i * Map->GetIsoSize(), 0x0);
|
||
Map->SetOverlayAt((m_mapx - 0) + i * Map->GetIsoSize(), start + v2);
|
||
Map->SetOverlayDataAt((m_mapx - 0) + i * Map->GetIsoSize(), 0x1);
|
||
Map->SetOverlayAt((m_mapx + 1) + i * Map->GetIsoSize(), start + v2);
|
||
Map->SetOverlayDataAt((m_mapx + 1) + i * Map->GetIsoSize(), 0x2);
|
||
}
|
||
Map->SetOverlayAt((m_mapx - 1) + m_mapy * Map->GetIsoSize(), start + 20);
|
||
Map->SetOverlayAt((m_mapx - 0) + m_mapy * Map->GetIsoSize(), start + 20);
|
||
Map->SetOverlayAt((m_mapx + 1) + m_mapy * Map->GetIsoSize(), start + 20);
|
||
Map->SetOverlayDataAt((m_mapx - 1) + m_mapy * Map->GetIsoSize(), 0x0);
|
||
Map->SetOverlayDataAt((m_mapx - 0) + m_mapy * Map->GetIsoSize(), 0x1);
|
||
Map->SetOverlayDataAt((m_mapx + 1) + m_mapy * Map->GetIsoSize(), 0x2);
|
||
|
||
Map->SetOverlayAt((m_mapx - 1) + y * Map->GetIsoSize(), start + 18);
|
||
Map->SetOverlayAt((m_mapx - 0) + y * Map->GetIsoSize(), start + 18);
|
||
Map->SetOverlayAt((m_mapx + 1) + y * Map->GetIsoSize(), start + 18);
|
||
Map->SetOverlayDataAt((m_mapx - 1) + y * Map->GetIsoSize(), 0x0);
|
||
Map->SetOverlayDataAt((m_mapx + 0) + y * Map->GetIsoSize(), 0x1);
|
||
Map->SetOverlayDataAt((m_mapx + 1) + y * Map->GetIsoSize(), 0x2);
|
||
|
||
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
//UpdateMap();
|
||
RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
}
|
||
}
|
||
}
|
||
|
||
CFinalSunDlg& dlg = *(CFinalSunDlg*)theApp.m_pMainWnd;
|
||
dlg.m_view.m_minimap.RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
|
||
m_moved = FALSE;
|
||
|
||
CView::OnLButtonUp(nFlags, point);
|
||
}
|
||
|
||
|
||
|
||
|
||
void CIsoView::TextOut(int x, int y, const char* text, COLORREF col)
|
||
{
|
||
HDC hdc;
|
||
lpdsBack->GetDC(&hdc);
|
||
|
||
SetTextColor(hdc, col);
|
||
SetBkMode(hdc, TRANSPARENT);
|
||
::TextOut(hdc, x, y, text, strlen(text));
|
||
|
||
|
||
lpdsBack->ReleaseDC(hdc);
|
||
}
|
||
|
||
void CIsoView::TextOut(HDC hDC, int x, int y, const char* text, COLORREF col)
|
||
{
|
||
SetTextColor(hDC, col);
|
||
SetBkMode(hDC, TRANSPARENT);
|
||
::TextOut(hDC, x, y, text, strlen(text));
|
||
}
|
||
|
||
|
||
|
||
void CIsoView::OnMove(int x, int y)
|
||
{
|
||
CView::OnMove(x, y);
|
||
|
||
if (lpds == NULL) return;
|
||
LPDIRECTDRAWCLIPPER ddc;
|
||
|
||
lpds->GetClipper(&ddc);
|
||
ddc->SetHWnd(0, m_hWnd);
|
||
updateFontScaled();
|
||
|
||
RedrawWindow();
|
||
}
|
||
|
||
void CIsoView::OnSize(UINT nType, int cx, int cy)
|
||
{
|
||
// CView::OnSize(nType, cx, cy);
|
||
if (lpds == NULL) return;
|
||
|
||
LPDIRECTDRAWCLIPPER ddc;
|
||
|
||
lpds->GetClipper(&ddc);
|
||
ddc->SetHWnd(0, m_hWnd);
|
||
updateFontScaled();
|
||
|
||
CMyViewFrame& dlg = *(CMyViewFrame*)owner;
|
||
dlg.m_minimap.RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
|
||
UpdateScrollRanges();
|
||
|
||
GetWindowRect(&m_myRect);
|
||
}
|
||
|
||
COLORREF CIsoView::GetColor(const char* house, const char* vcolor)
|
||
{
|
||
|
||
COLORREF neutral = RGB(120, 120, 120);
|
||
COLORREF GDI = RGB(170, 170, 0);
|
||
COLORREF Nod = RGB(255, 0, 0);
|
||
COLORREF other = RGB(255, 255, 0);
|
||
|
||
CString color;
|
||
CString colorValues;
|
||
CIniFile& ini = Map->GetIniFile();
|
||
if (house && strlen(house)) {
|
||
color = rules.GetString(house, "Color");
|
||
color = ini.GetStringOr(house, "Color", color);//override
|
||
}
|
||
|
||
if (vcolor) {
|
||
colorValues = vcolor;
|
||
} else if (!color.IsEmpty()) {
|
||
colorValues = rules.GetString("Colors", color);
|
||
colorValues = ini.GetStringOr("Colors", color, colorValues);
|
||
}
|
||
auto colorArray = SplitParams(colorValues);
|
||
|
||
if (colorArray.size() == 3) {
|
||
unsigned char hsv[3] = { static_cast<unsigned char>(std::atoi(colorArray[0])), static_cast<unsigned char>(std::atoi(colorArray[1])), static_cast<unsigned char>(std::atoi(colorArray[2])) };
|
||
unsigned char rgb[3];
|
||
HSVToRGB(hsv, rgb);
|
||
return RGB(rgb[0], rgb[1], rgb[2]);
|
||
}
|
||
|
||
#ifndef RA2_MODE
|
||
if (strstr(house, houses[0].name) != NULL) {
|
||
return GDI;
|
||
} else if (strstr(house, houses[1].name) != NULL) {
|
||
return Nod;
|
||
} else if (strstr(house, houses[2].name) != NULL) {
|
||
return neutral;
|
||
} else {
|
||
if (isIncluded(color, "darkred") != NULL) {
|
||
return Nod;
|
||
}
|
||
if (isIncluded(color, "grey") != NULL) {
|
||
return RGB(120, 120, 120);
|
||
}
|
||
if (isIncluded(color, "gold") != NULL) {
|
||
return GDI;
|
||
}
|
||
|
||
|
||
return other;
|
||
}
|
||
#else
|
||
if (isIncluded(color, "darkred") != NULL) {
|
||
return RGB(130, 20, 20);
|
||
}
|
||
if (isIncluded(color, "grey") != NULL) {
|
||
return RGB(120, 120, 120);
|
||
}
|
||
if (isIncluded(color, "red") != NULL) {
|
||
return RGB(240, 20, 20);
|
||
}
|
||
if (isIncluded(color, "lightgold") != NULL) {
|
||
return RGB(220, 220, 150);
|
||
}
|
||
if (isIncluded(color, "yellow") != NULL) {
|
||
return RGB(240, 240, 0);
|
||
}
|
||
if (isIncluded(color, "gold") != NULL) {
|
||
return RGB(230, 200, 0);
|
||
}
|
||
if (isIncluded(color, "darkgreen") != NULL) {
|
||
return RGB(50, 160, 70);
|
||
}
|
||
if (isIncluded(color, "neongreen") != NULL) {
|
||
return RGB(10, 255, 10);
|
||
}
|
||
if (isIncluded(color, "green") != NULL) {
|
||
return RGB(50, 200, 70);
|
||
}
|
||
if (isIncluded(color, "darkblue") != NULL) {
|
||
return RGB(30, 30, 150);
|
||
}
|
||
if (isIncluded(color, "lightblue") != NULL) {
|
||
return RGB(100, 100, 200);
|
||
}
|
||
if (isIncluded(color, "neonblue") != NULL) {
|
||
return RGB(35, 205, 255);
|
||
}
|
||
|
||
{
|
||
return other;
|
||
}
|
||
|
||
#endif
|
||
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
/*
|
||
GetOverlayPic(BYTE ovrl, BYTE ovrldata);
|
||
|
||
Returns the picture that should be used to draw the overlay tile.
|
||
First checks if a explicite bitmap exists for this tile, if not
|
||
checks if it can be displayed by a standard bitmap.
|
||
For bridges, it also needs the overlaydata.
|
||
*/
|
||
inline PICDATA* GetOverlayPic(BYTE ovrl, BYTE ovrldata)
|
||
{
|
||
|
||
char c[50];
|
||
char d[50];
|
||
itoa(ovrl, c, 10);
|
||
itoa(ovrldata, d, 10);
|
||
|
||
CString fname = (CString)"OVRL" + c + "_" + d;
|
||
|
||
// MessageBox(0,fname,"",0);
|
||
|
||
if (pics.find(fname) != pics.end()) {
|
||
return &pics[fname];
|
||
}
|
||
|
||
//errstream << "pic " << (LPCSTR)fname << " not found" << endl;
|
||
|
||
|
||
return NULL;
|
||
}
|
||
|
||
|
||
|
||
|
||
void CIsoView::OnDraw(CDC* pDC)
|
||
{
|
||
DrawMap();
|
||
}
|
||
|
||
|
||
void CIsoView::ReInitializeDDraw()
|
||
{
|
||
b_IsLoading = TRUE;
|
||
ReleaseCapture();
|
||
KillTimer(11);
|
||
// rscroll=FALSE;
|
||
|
||
|
||
|
||
#ifdef NOSURFACES
|
||
while ((GetDeviceCaps(::GetDC(::GetDesktopWindow()), BITSPIXEL) <= 8)) {
|
||
if (MessageBox("You currently only have 8 bit color mode enabled. FinalAlert 2 does not work in 8 bit color mode. Please change the color mode and then click on OK. Click Cancel to quit (and save the map as backup.map).", "Error", MB_OKCANCEL) == IDCANCEL) {
|
||
((CFinalSunDlg*)theApp.m_pMainWnd)->SaveMap((u8AppDataPath + "\\backup.map").c_str());
|
||
PostQuitMessage(0);
|
||
return;
|
||
}
|
||
}
|
||
#endif
|
||
|
||
|
||
CDynamicGraphDlg dlg;
|
||
|
||
dlg.ShowWindow(SW_SHOW);
|
||
dlg.UpdateWindow();
|
||
|
||
dd->RestoreAllSurfaces();
|
||
|
||
updateFontScaled();
|
||
|
||
|
||
missingimages.clear();
|
||
|
||
theApp.m_loading->FreeAll();
|
||
theApp.m_loading->InitDirectDraw();
|
||
theApp.m_loading->InitPics();
|
||
theApp.m_loading->InitTMPs(&dlg.m_Progress);
|
||
|
||
memset(ovrlpics, 0, max_ovrl_img * 0xFF * sizeof(LPDIRECTDRAWSURFACE4));
|
||
//UpdateOverlayPictures(-1);
|
||
//Map->UpdateIniFile(MAPDATA_UPDATE_FROM_INI);
|
||
Map->UpdateBuildingInfo();
|
||
Map->UpdateTreeInfo();
|
||
#ifdef SMUDGE_SUPP
|
||
Map->UpdateSmudgeInfo();
|
||
#endif
|
||
|
||
|
||
|
||
b_IsLoading = FALSE;
|
||
|
||
//Sleep(2500);
|
||
|
||
|
||
|
||
dlg.DestroyWindow();
|
||
|
||
|
||
|
||
|
||
|
||
RedrawWindow();
|
||
|
||
|
||
|
||
/*
|
||
|
||
CString CommandLine;
|
||
|
||
if(res==IDYES)
|
||
{
|
||
CFileDialog dlg(FALSE, ".mpr", "noname.mpr", OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, "TS maps|*.mpr;*.map|TS multi maps|*.mpr|TS single maps|*.map|");
|
||
do
|
||
{
|
||
|
||
|
||
char cuPath[MAX_PATH];
|
||
|
||
GetCurrentDirectory(MAX_PATH, cuPath);
|
||
dlg.m_ofn.lpstrInitialDir=cuPath;
|
||
|
||
if(theApp.m_Options.TSExe.GetLength()) dlg.m_ofn.lpstrInitialDir=(char*)(LPCTSTR)theApp.m_Options.TSExe;
|
||
|
||
}while(dlg.DoModal()==IDCANCEL) ;
|
||
|
||
CommandLine=dlg.GetPathName();
|
||
|
||
((CFinalSunDlg*)theApp.m_pMainWnd)->SaveMap(dlg.GetPathName());
|
||
}
|
||
|
||
if(res==IDNO || res==IDYES)
|
||
{
|
||
PROCESS_INFORMATION pi;
|
||
STARTUPINFO si;
|
||
memset(&si, 0, sizeof(STARTUPINFO));
|
||
si.cb=sizeof(STARTUPINFO);
|
||
|
||
char myExe[MAX_PATH];
|
||
GetModuleFileName(NULL, myExe, MAX_PATH);
|
||
|
||
BOOL success=CreateProcess(myExe,
|
||
(LPTSTR)(LPCTSTR)CommandLine,
|
||
NULL,
|
||
NULL,
|
||
FALSE,
|
||
NORMAL_PRIORITY_CLASS,
|
||
NULL,
|
||
AppPath,
|
||
&si,
|
||
&pi);
|
||
}
|
||
|
||
theApp.m_pMainWnd->DestroyWindow();*/
|
||
|
||
|
||
|
||
|
||
|
||
/*CLoading load;
|
||
load.InitDirectDraw();
|
||
load.InitMixFiles();
|
||
load.InitPics();
|
||
|
||
|
||
|
||
RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
|
||
b_IsLoading=FALSE;*/
|
||
|
||
|
||
}
|
||
|
||
void CIsoView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
|
||
{
|
||
|
||
|
||
CView::OnChar(nChar, nRepCnt, nFlags);
|
||
}
|
||
|
||
void CIsoView::OnDeadChar(UINT nChar, UINT nRepCnt, UINT nFlags)
|
||
{
|
||
|
||
CView::OnDeadChar(nChar, nRepCnt, nFlags);
|
||
}
|
||
|
||
void CIsoView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
|
||
{
|
||
int nPos;
|
||
|
||
|
||
|
||
if (nChar == 68) // D key
|
||
{
|
||
theApp.m_Options.bFlat = !theApp.m_Options.bFlat;
|
||
RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
}
|
||
if (nChar == 65)
|
||
m_bAltCliff = !m_bAltCliff;
|
||
|
||
CView::OnKeyDown(nChar, nRepCnt, nFlags);
|
||
}
|
||
|
||
void CIsoView::SetError(const char* text)
|
||
{
|
||
CMyViewFrame& v = *((CMyViewFrame*)owner);
|
||
v.m_statbar.GetStatusBarCtrl().SetText(text, 0, 0);
|
||
}
|
||
|
||
|
||
|
||
|
||
int CIsoView::GetOverlayDirection(int x, int y)
|
||
{
|
||
DWORD dwIsoSize = Map->GetIsoSize();
|
||
int p = -1;
|
||
int type = Map->GetOverlayAt(x + y * dwIsoSize);
|
||
|
||
BOOL isTrail = FALSE;
|
||
int i;
|
||
for (i = 0; i < overlay_count; i++)
|
||
if (overlay_number[i] == type)
|
||
if (overlay_trail[i]) isTrail = TRUE;
|
||
|
||
if (isTrack(type)) // handling a train track
|
||
{
|
||
|
||
|
||
if (isTrack(Map->GetOverlayAt((x - 1) + (y - 1) * dwIsoSize)) && isTrack(Map->GetOverlayAt((x + 1) + (y + 1) * dwIsoSize)))
|
||
return 0;
|
||
if (isTrack(Map->GetOverlayAt((x + 1) + (y - 1) * dwIsoSize)) && isTrack(Map->GetOverlayAt((x - 1) + (y + 1) * dwIsoSize)))
|
||
return 1;
|
||
if (isTrack(Map->GetOverlayAt((x - 1) + (y - 0) * dwIsoSize)) && isTrack(Map->GetOverlayAt((x + 1) + (y + 0) * dwIsoSize)))
|
||
return 2;
|
||
if (isTrack(Map->GetOverlayAt((x - 0) + (y - 1) * dwIsoSize)) && isTrack(Map->GetOverlayAt((x + 0) + (y + 1) * dwIsoSize)))
|
||
return 3;
|
||
if (isTrack(Map->GetOverlayAt((x - 1) + (y - 0) * dwIsoSize)) && isTrack(Map->GetOverlayAt((x + 1) + (y + 1) * dwIsoSize)))
|
||
return 4;
|
||
if (isTrack(Map->GetOverlayAt((x - 0) + (y - 1) * dwIsoSize)) && isTrack(Map->GetOverlayAt((x + 1) + (y + 1) * dwIsoSize)))
|
||
return 5;
|
||
if (isTrack(Map->GetOverlayAt((x - 1) + (y - 1) * dwIsoSize)) && isTrack(Map->GetOverlayAt((x - 0) + (y + 1) * dwIsoSize)))
|
||
return 6;
|
||
if (isTrack(Map->GetOverlayAt((x - 1) + (y - 1) * dwIsoSize)) && isTrack(Map->GetOverlayAt((x + 1) + (y + 0) * dwIsoSize)))
|
||
return 7;
|
||
if (isTrack(Map->GetOverlayAt((x - 1) + (y - 0) * dwIsoSize)) && isTrack(Map->GetOverlayAt((x + 1) + (y - 1) * dwIsoSize)))
|
||
return 8;
|
||
if (isTrack(Map->GetOverlayAt((x + 0) + (y + 1) * dwIsoSize)) && isTrack(Map->GetOverlayAt((x + 1) + (y - 1) * dwIsoSize)))
|
||
return 9;
|
||
if (isTrack(Map->GetOverlayAt((x - 0) + (y - 1) * dwIsoSize)) && isTrack(Map->GetOverlayAt((x - 1) + (y + 1) * dwIsoSize)))
|
||
return 10;
|
||
if (isTrack(Map->GetOverlayAt((x - 1) + (y + 1) * dwIsoSize)) && isTrack(Map->GetOverlayAt((x + 1) + (y + 0) * dwIsoSize)))
|
||
return 11;
|
||
if (isTrack(Map->GetOverlayAt((x - 1) + (y - 1) * dwIsoSize)))
|
||
return 0;
|
||
if (isTrack(Map->GetOverlayAt((x - 1) + (y + 1) * dwIsoSize)))
|
||
return 1;
|
||
if (isTrack(Map->GetOverlayAt((x - 1) + (y - 0) * dwIsoSize)))
|
||
return 2;
|
||
if (isTrack(Map->GetOverlayAt((x - 0) + (y - 1) * dwIsoSize)))
|
||
return 3;
|
||
if (isTrack(Map->GetOverlayAt((x + 1) + (y + 1) * dwIsoSize)))
|
||
return 0;
|
||
if (isTrack(Map->GetOverlayAt((x + 1) + (y - 1) * dwIsoSize)))
|
||
return 1;
|
||
if (isTrack(Map->GetOverlayAt((x + 1) + (y + 0) * dwIsoSize)))
|
||
return 2;
|
||
if (isTrack(Map->GetOverlayAt((x + 0) + (y + 1) * dwIsoSize)))
|
||
return 3;
|
||
|
||
return 0;
|
||
} else if (isTrail) // handling something like a sandbag
|
||
{
|
||
p = 0;
|
||
if (Map->GetOverlayAt(x - 1 + (y - 0) * dwIsoSize) == type) p |= 0x1;
|
||
if (Map->GetOverlayAt(x + (y + 1) * dwIsoSize) == type) p |= 0x2;
|
||
if (Map->GetOverlayAt(x + 1 + (y + 0) * dwIsoSize) == type) p |= 0x4;
|
||
if (Map->GetOverlayAt(x + (y - 1) * dwIsoSize) == type) p |= 0x8;
|
||
}
|
||
|
||
return p;
|
||
|
||
}
|
||
|
||
void CIsoView::HandleTrail(int x, int y)
|
||
{
|
||
int i, e;
|
||
int type = Map->GetOverlayAt(x + y * Map->GetIsoSize());
|
||
|
||
if (isTrack(type)) // is a track (overlay must be changed)
|
||
{
|
||
|
||
for (i = x - 2; i <= x + 2; i++) {
|
||
for (e = y - 1; e <= y + 1; e++) {
|
||
if (isTrack(Map->GetOverlayAt(i + e * Map->GetIsoSize())))
|
||
Map->SetOverlayAt(i + e * Map->GetIsoSize(), 0x27 + GetOverlayDirection(i, e));
|
||
}
|
||
}
|
||
} else // something like a sandbag (overlaydata must be changed)
|
||
{
|
||
|
||
for (i = x - 2; i <= x + 2; i++) {
|
||
for (e = y - 1; e <= y + 1; e++) {
|
||
if (Map->GetOverlayAt(i + e * Map->GetIsoSize()) == type) {
|
||
int dir = GetOverlayDirection(i, e);
|
||
if (dir >= 0) Map->SetOverlayDataAt(i + e * Map->GetIsoSize(), dir);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
|
||
/*
|
||
DrawCell(int x, int y, int w, int h, COLORREF col)
|
||
|
||
Draws a frame around one or more cells.
|
||
w is the width, h is the height (in cells).
|
||
x and y are pixel coordinates.
|
||
col specifies the color.
|
||
*/
|
||
void CIsoView::DrawCell(int x, int y, int w, int h, COLORREF col, BOOL dotted, HDC hDC_)
|
||
{
|
||
|
||
|
||
// correct the y value:
|
||
//y -= f_y;
|
||
|
||
POINT p1, p2, p3, p4;
|
||
p1.x = x + f_x / 2;
|
||
p1.y = y;
|
||
p2.x = x + w * f_x / 2 + f_x / 2;
|
||
p2.y = y + w * f_y / 2;
|
||
p3.x = x + w * f_x / 2 - h * f_x / 2 + f_x / 2 - 1;
|
||
p3.y = y + h * f_y / 2 + w * f_y / 2 - 1;
|
||
p4.x = x - h * f_x / 2 + f_x / 2 - 1;
|
||
p4.y = y + h * f_y / 2 - 1;
|
||
|
||
HDC hDC = hDC_;
|
||
if (!hDC)
|
||
while (lpdsBack->GetDC(&hDC) == DDERR_WASSTILLDRAWING);
|
||
|
||
HPEN p;
|
||
int width = 1;
|
||
#ifdef RA2_MODE
|
||
width = 2;
|
||
#endif
|
||
if (!dotted) p = CreatePen(PS_SOLID, width, col);
|
||
else p = CreatePen(PS_DOT, 0, col);
|
||
|
||
SelectObject(hDC, p);
|
||
|
||
if (dotted) {
|
||
SetBkMode(hDC, TRANSPARENT);
|
||
MoveToEx(hDC, p1.x, p1.y - 1, NULL);
|
||
LineTo(hDC, p2.x + 1, p2.y);
|
||
LineTo(hDC, p3.x, p3.y + 1);
|
||
LineTo(hDC, p4.x - 1, p4.y);
|
||
LineTo(hDC, p1.x, p1.y - 1);
|
||
}
|
||
|
||
if (!dotted) {
|
||
MoveToEx(hDC, p1.x, p1.y, NULL);
|
||
LineTo(hDC, p2.x, p2.y);
|
||
LineTo(hDC, p3.x, p3.y);
|
||
LineTo(hDC, p4.x, p4.y);
|
||
LineTo(hDC, p1.x, p1.y);
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
if (!hDC_)
|
||
lpdsBack->ReleaseDC(hDC);
|
||
|
||
DeleteObject(p);
|
||
}
|
||
|
||
void CIsoView::DrawCell(void* dest, int dest_width, int dest_height, int dest_pitch, int drawx, int drawy, int w, int h, int col, bool dotted, bool touchNeighbours, int colNeighbour) const
|
||
{
|
||
if (colNeighbour == CLR_INVALID)
|
||
colNeighbour = col;
|
||
|
||
// correct the y value:
|
||
//y -= f_y;
|
||
|
||
POINT p1, p2, p3, p4;
|
||
p1.x = drawx + f_x / 2;
|
||
p1.y = drawy;
|
||
p2.x = drawx + w * f_x / 2 + f_x / 2;
|
||
p2.y = drawy + w * f_y / 2;
|
||
p3.x = drawx + w * f_x / 2 - h * f_x / 2 + f_x / 2;
|
||
p3.y = drawy + h * f_y / 2 + w * f_y / 2;
|
||
p4.x = drawx - h * f_x / 2 + f_x / 2;
|
||
p4.y = drawy + h * f_y / 2;
|
||
|
||
LineDrawer drawer(dest, bpp, dest_width, dest_height, dest_pitch);
|
||
|
||
const LineStyle style = dotted ? LineStyle::Dotted_4 : LineStyle::Standard;
|
||
|
||
for (int x = 0; x < 1; ++x) // you could use this loop for more thickness
|
||
{
|
||
for (int y = 0; y < 1; ++y) {
|
||
// inside the MM tile
|
||
drawer.MoveTo(p1.x + x + 1, p1.y + y + 1);
|
||
drawer.LineTo(p2.x + x - 2, p2.y + y - 1, col, style);
|
||
drawer.LineTo(p3.x + x + 1, p3.y + y - 3, col, style);
|
||
drawer.LineTo(p3.x + x, p3.y + y - 3, col, style);
|
||
drawer.LineTo(p4.x + x + 3, p4.y + y - 1, col, style);
|
||
drawer.LineTo(p4.x + x + 2, p4.y + y - 1, col, style);
|
||
drawer.MoveTo(p4.x + x + 3, p4.y + y - 1);
|
||
drawer.LineTo(p1.x + x, p1.y + y + 1, col, style);
|
||
drawer.LineTo(p1.x + x + 1, p1.y + y + 1, col, style);
|
||
|
||
// on inner pixels of MM tile boundary
|
||
drawer.MoveTo(p1.x + x + 1, p1.y + y);
|
||
drawer.LineTo(p2.x + x, p2.y + y - 1, col, style);
|
||
drawer.LineTo(p3.x + x + 1, p3.y + y - 2, col, style);
|
||
drawer.LineTo(p3.x + x, p3.y + y - 2, col, style);
|
||
drawer.LineTo(p4.x + x + 1, p4.y + y - 1, col, style);
|
||
drawer.LineTo(p1.x + x, p1.y + y, col, style);
|
||
drawer.LineTo(p1.x + x + 1, p1.y + y, col, style);
|
||
}
|
||
}
|
||
|
||
// pixels of neighboured MM tiles boundary
|
||
if (touchNeighbours) {
|
||
for (int x = 0; x < 1; ++x) // you could use this loop for more thickness
|
||
{
|
||
for (int y = 0; y < 1; ++y) {
|
||
drawer.MoveTo(p1.x + x + 1, p1.y + y - 1);
|
||
drawer.LineTo(p2.x + x - 2, p2.y + y - 3, colNeighbour, style);
|
||
drawer.MoveTo(p2.x + x - 2, p2.y + y - 2);
|
||
drawer.LineTo(p2.x + x - 1, p2.y + y, colNeighbour, style);
|
||
drawer.LineTo(p2.x + x, p2.y + y, colNeighbour, style);
|
||
drawer.LineTo(p3.x + x + 1, p3.y + y - 1, colNeighbour, style);
|
||
drawer.LineTo(p3.x + x, p3.y + y - 1, colNeighbour, style);
|
||
drawer.LineTo(p4.x + x + 1, p4.y + y, colNeighbour, style);
|
||
drawer.LineTo(p4.x + x, p4.y + y - 1, colNeighbour, style);
|
||
drawer.LineTo(p1.x + x, p1.y + y - 1, colNeighbour, style);
|
||
drawer.LineTo(p1.x + x + 1, p1.y + y - 1, colNeighbour, style);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
void CIsoView::DrawTube(const CTube& tube, const DDSURFACEDESC2* lockedDDSD, const COLORREF* color) const
|
||
{
|
||
SurfaceLocker locker(lpdsBack);
|
||
|
||
if (!lockedDDSD || !lockedDDSD->lpSurface) {
|
||
lockedDDSD = locker.ensure_locked();
|
||
}
|
||
if (!lockedDDSD)
|
||
return;
|
||
|
||
// TODO: culling if required
|
||
|
||
// find out if we are tube #1 or #2 for bidirectional tubes
|
||
bool type0 = tube.getStartX() == tube.getEndX() ? (tube.getStartY() < tube.getEndY()) : (tube.getStartX() < tube.getEndX());
|
||
const auto col = color ? m_color_converter->GetColor(*color) : (type0 ? m_color_converter->GetColor(255, 0, 0) : m_color_converter->GetColor(0, 0, 255));
|
||
ProjectedVec lineOffset = type0 ? ProjectedVec() : ProjectedVec(1, 1);
|
||
|
||
int lowestHeight = std::min(Map->GetHeightAt(tube.getStartCoords()), Map->GetHeightAt(tube.getEndCoords()));
|
||
LineDrawer ld(lockedDDSD->lpSurface, bpp, lockedDDSD->dwWidth, lockedDDSD->dwHeight, lockedDDSD->lPitch);
|
||
auto startDraw = GetRenderTargetCoordinates(tube.getStartCoords(), lowestHeight);
|
||
ld.MoveTo(startDraw.x + f_x / 2 + lineOffset.x, startDraw.y + f_y / 2 + lineOffset.y);
|
||
|
||
|
||
tube.walk([this, &tube, lockedDDSD, &ld, lowestHeight, col, lineOffset](const auto& wi) {
|
||
auto draw = GetRenderTargetCoordinates(wi.pos, lowestHeight);
|
||
if (wi.pos == tube.getEndCoords()) {
|
||
// end coordinates are drawn as cross
|
||
LineDrawer startLD(lockedDDSD->lpSurface, bpp, lockedDDSD->dwWidth, lockedDDSD->dwHeight, lockedDDSD->lPitch);
|
||
ProjectedVec off(7, 4);
|
||
startLD.DrawLine(draw.x + off.x, draw.y + f_y / 2, draw.x + f_x - off.x, draw.y + f_y / 2, col);
|
||
startLD.DrawLine(draw.x + f_x / 2 - 1, draw.y + off.y, draw.x + f_x / 2 - 1, draw.y + f_y - off.y, col);
|
||
}
|
||
if (wi.pos == tube.getStartCoords()) {
|
||
// Start coordinates are drawn as cell
|
||
DrawCell(lockedDDSD->lpSurface, lockedDDSD->dwWidth, lockedDDSD->dwHeight, lockedDDSD->lPitch, draw.x, draw.y, 1, 1, col, true);
|
||
}
|
||
ld.LineTo(draw.x + f_x / 2 + lineOffset.x, draw.y + f_y / 2 + lineOffset.y, col);
|
||
return true;
|
||
});
|
||
}
|
||
|
||
MapCoords CIsoView::GetMapCoordinates(const ProjectedCoords& projCoords, bool bAllowAccessBehindCliffs, bool ignoreHideFlagsAndOutside) const
|
||
{
|
||
return theApp.m_Options.bFlat ? Map->ToMapCoords(projCoords) : Map->ToMapCoords3d(projCoords, bAllowAccessBehindCliffs, ignoreHideFlagsAndOutside);
|
||
}
|
||
|
||
MapCoords CIsoView::GetMapCoordinatesFromRenderTargetCoordinates(const ProjectedCoords& projCoords, bool bAllowAccessBehindCliffs, bool ignoreHideFlagsAndOutside) const
|
||
{
|
||
return GetMapCoordinates(projCoords + m_viewOffset, bAllowAccessBehindCliffs, ignoreHideFlagsAndOutside);
|
||
}
|
||
|
||
MapCoords CIsoView::GetMapCoordinatesFromClientCoordinates(const CPoint& clientPt, bool bAllowAccessBehindCliffs, bool ignoreHideFlagsAndOutside) const
|
||
{
|
||
return GetMapCoordinates(GetProjectedCoordinatesFromClientCoordinates(clientPt), bAllowAccessBehindCliffs, ignoreHideFlagsAndOutside);
|
||
}
|
||
|
||
ProjectedCoords CIsoView::GetProjectedCoordinatesFromClientCoordinates(const CPoint& clientPt) const
|
||
{
|
||
RECT r;
|
||
GetWindowRect(&r);
|
||
const auto viewOffsetWR = m_viewOffset + ProjectedVec(r.left, r.top);
|
||
const auto projCoords = ProjectedCoords(clientPt.x * m_viewScale.x, clientPt.y * m_viewScale.y) + viewOffsetWR;
|
||
return projCoords;
|
||
}
|
||
|
||
ProjectedCoords CIsoView::GetProjectedCoordinates(const MapCoords& mapCoords) const
|
||
{
|
||
return theApp.m_Options.bFlat ? Map->ProjectCoords(mapCoords) : Map->ProjectCoords3d(mapCoords);
|
||
}
|
||
|
||
ProjectedCoords CIsoView::GetProjectedCoordinates(const MapCoords& mapCoords, int mapZ) const
|
||
{
|
||
return Map->ProjectCoords3d(mapCoords, mapZ);
|
||
}
|
||
|
||
ProjectedCoords CIsoView::GetRenderTargetCoordinates(const MapCoords& mapCoords) const
|
||
{
|
||
// Draw coordinates are display coordinates
|
||
return GetProjectedCoordinates(mapCoords) - m_viewOffset;
|
||
}
|
||
|
||
ProjectedCoords CIsoView::GetRenderTargetCoordinates(const MapCoords& mapCoords, int mapZ) const
|
||
{
|
||
return GetProjectedCoordinates(mapCoords, mapZ) - m_viewOffset;
|
||
}
|
||
|
||
CPoint CIsoView::GetClientCoordinates(const MapCoords& mapCoords) const
|
||
{
|
||
RECT r;
|
||
GetWindowRect(&r);
|
||
const auto windowPos = ProjectedVec(r.left, r.top);
|
||
//const auto p = ScaleBackToFrontBuffer(GetRenderTargetCoordinates(mapCoords)) - windowPos;
|
||
const auto rtc = GetRenderTargetCoordinates(mapCoords);
|
||
const auto p = ((ProjectedCoords(rtc.x, rtc.y) - windowPos) / m_viewScale).convertT<std::int32_t>();
|
||
return CPoint(p.x, p.y);
|
||
}
|
||
|
||
CPoint CIsoView::GetClientCoordinatesFromWorld(const ProjectedCoords& projectedCoords) const
|
||
{
|
||
RECT r;
|
||
GetWindowRect(&r);
|
||
const auto windowPos = ProjectedVec(r.left, r.top);
|
||
//const auto p = ScaleBackToFrontBuffer(GetRenderTargetCoordinates(mapCoords)) - windowPos;
|
||
const auto rtc = projectedCoords - m_viewOffset;
|
||
const auto p = ((ProjectedCoords(rtc.x, rtc.y)) / m_viewScale).convertT<std::int32_t>();
|
||
return CPoint(p.x, p.y);
|
||
}
|
||
|
||
ProjectedCoords CIsoView::ScaleBackToFrontBuffer(const ProjectedCoords& backBufferCoords) const
|
||
{
|
||
RECT r;
|
||
GetWindowRect(&r);
|
||
const auto windowPos = ProjectedVec(r.left, r.top);
|
||
return ((ProjectedCoords(backBufferCoords.x, backBufferCoords.y) - windowPos) / m_viewScale).convertT<std::int32_t>() + windowPos;
|
||
}
|
||
|
||
|
||
void CIsoView::UpdateStatusBar(int x, int y)
|
||
{
|
||
CString statusbar;//=TranslateStringACP("Ready");
|
||
|
||
FIELDDATA m = *Map->GetFielddataAt(x + y * Map->GetIsoSize());
|
||
if (m.wGround == 0xFFFF) m.wGround = 0;
|
||
|
||
if (m.wGround < (*tiledata_count) && m.bSubTile < (*tiledata)[m.wGround].wTileCount) {
|
||
statusbar = "Terrain type: 0x";
|
||
char c[50];
|
||
itoa((*tiledata)[m.wGround].tiles[m.bSubTile].bTerrainType, c, 16);
|
||
statusbar += c;
|
||
statusbar += ", height: ";
|
||
itoa(m.bHeight, c, 10);
|
||
statusbar += c;
|
||
statusbar += " / ";
|
||
}
|
||
|
||
|
||
if (Map->GetOverlayAt(x + y * Map->GetIsoSize()) != 0xFF) {
|
||
char ov[50];
|
||
itoa(Map->GetOverlayAt(x + y * Map->GetIsoSize()), ov, 16);
|
||
|
||
int i;
|
||
CString name;
|
||
name = "0x";
|
||
name += ov;
|
||
for (i = 0; i < overlay_count; i++) {
|
||
if (overlay_number[i] == Map->GetOverlayAt(x + y * Map->GetIsoSize()))
|
||
name = overlay_name[i];
|
||
}
|
||
|
||
|
||
itoa(Map->GetOverlayDataAt(x + y * Map->GetIsoSize()), ov, 16);
|
||
|
||
statusbar += GetLanguageStringACP("OvrlStatus");
|
||
statusbar += TranslateStringACP(name);
|
||
statusbar += ", OverlayData: 0x";
|
||
statusbar += ov;
|
||
}
|
||
|
||
STDOBJECTDATA sod;
|
||
sod.type = "";
|
||
|
||
int n = Map->GetStructureAt(x + y * Map->GetIsoSize());
|
||
int on = -1;
|
||
if (n >= 0) {
|
||
|
||
Map->GetStdStructureData(n, &sod);
|
||
statusbar = GetLanguageStringACP("StructStatus");
|
||
on = n;
|
||
}
|
||
|
||
n = Map->GetUnitAt(x + y * Map->GetIsoSize());
|
||
if (n >= 0) {
|
||
|
||
Map->GetStdUnitData(n, &sod);
|
||
statusbar = GetLanguageStringACP("UnitStatus");
|
||
on = n;
|
||
|
||
}
|
||
|
||
n = Map->GetAirAt(x + y * Map->GetIsoSize());
|
||
if (n >= 0) {
|
||
|
||
Map->GetStdAircraftData(n, &sod);
|
||
statusbar = GetLanguageStringACP("AirStatus");
|
||
on = n;
|
||
}
|
||
|
||
n = Map->GetInfantryAt(x + y * Map->GetIsoSize());
|
||
if (n >= 0) {
|
||
Map->GetStdInfantryData(n, &sod);
|
||
statusbar = GetLanguageStringACP("InfStatus");
|
||
on = n;
|
||
}
|
||
|
||
if (sod.type.GetLength() > 0) {
|
||
char c[50];
|
||
itoa(on, c, 10);
|
||
statusbar += "ID ";
|
||
statusbar += c;
|
||
statusbar += ", ";
|
||
|
||
statusbar += TranslateStringACP(Map->GetUnitName(sod.type));
|
||
statusbar += " (";
|
||
|
||
statusbar += TranslateHouse(sod.house, TRUE);
|
||
statusbar += ", ";
|
||
statusbar += sod.type;
|
||
statusbar += ")";
|
||
}
|
||
|
||
/*
|
||
// activate this code to display information about the mappack!
|
||
|
||
statusbar="MAPPACK: ";
|
||
int i;
|
||
FIELDDATA td=Map->GetFielddataAt(x+y*Map->GetIsoSize());
|
||
char c[50];
|
||
itoa(td.wGround, c, 10);
|
||
statusbar+="tile: ";
|
||
statusbar+=c;
|
||
statusbar+=" ";
|
||
for(i=0;i<3;i++)
|
||
{
|
||
itoa(td.bMapData[i], c, 10);
|
||
statusbar+=c;
|
||
statusbar+=" ";
|
||
}
|
||
|
||
statusbar+=" height: ";
|
||
itoa(td.bHeight, c, 10);
|
||
statusbar+=c;
|
||
statusbar+=" ";
|
||
itoa(td.bMapData2[0],c,10);
|
||
statusbar+=c;*/
|
||
|
||
|
||
n = Map->GetCelltagAt(x + y * Map->GetIsoSize());
|
||
if (n >= 0) {
|
||
CString type;
|
||
CString name;
|
||
DWORD pos;
|
||
Map->GetCelltagData(n, &type, &pos);
|
||
CIniFile& ini = Map->GetIniFile();
|
||
auto const tagStr = ini.GetString("Tags", type);
|
||
if (!tagStr.IsEmpty()) {
|
||
name = GetParam(tagStr, 1);
|
||
}
|
||
|
||
statusbar += GetLanguageStringACP("CellTagStatus");
|
||
statusbar += name;
|
||
statusbar += " (";
|
||
statusbar += type;
|
||
statusbar += ")";
|
||
}
|
||
|
||
if (AD.mode == ACTIONMODE_SETTILE) {
|
||
statusbar = GetLanguageStringACP("TilePlaceStatus");
|
||
}
|
||
|
||
if (AD.mode == ACTIONMODE_COPY)
|
||
statusbar = GetLanguageStringACP("CopyHelp");
|
||
|
||
if (statusbar.GetLength() > 0)
|
||
SetError(statusbar);
|
||
|
||
}
|
||
|
||
void CIsoView::UpdateOverlayPictures(int id)
|
||
{
|
||
if (id < 0) {
|
||
memset(ovrlpics, 0, max_ovrl_img * 0xFF * sizeof(LPDIRECTDRAWSURFACE4));
|
||
|
||
int i, e;
|
||
for (i = 0; i < 0xFF; i++) {
|
||
for (e = 0; e < max_ovrl_img; e++) {
|
||
/*PICDATA& p=GetOverlayPic(i, e);
|
||
if(p.pic!=NULL) ovrlpics[i][e]=&p;
|
||
else
|
||
ovrlpics[i][e]=NULL;*/
|
||
ovrlpics[i][e] = GetOverlayPic(i, e);
|
||
}
|
||
}
|
||
} else {
|
||
int e;
|
||
for (e = 0; e < max_ovrl_img; e++) {
|
||
ovrlpics[id][e] = GetOverlayPic(id, e);
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
__forceinline void FixTileHeight(DWORD dwPos, int x, int y)
|
||
{
|
||
return; // we use CMapData::CreateSlopes() to fix slopes now
|
||
|
||
int oheight = Map->GetHeightAt(dwPos);
|
||
int isosize = Map->GetIsoSize();
|
||
|
||
char bHeightDiff[9];
|
||
|
||
int i, e;
|
||
for (i = -1; i < 2; i++) {
|
||
for (e = -1; e < 2; e++) {
|
||
if (x + i < 0 || y + e < 0 || x + i >= isosize || y + e >= isosize) bHeightDiff[i + 1 + (e + 1) * 3] = 0;
|
||
else
|
||
bHeightDiff[i + 1 + (e + 1) * 3] = oheight - Map->GetHeightAt(dwPos + i + e * isosize);
|
||
}
|
||
}
|
||
|
||
if (bHeightDiff[1] < 0 && bHeightDiff[7] < 0) {
|
||
Map->SetHeightAt(dwPos, oheight + 1);
|
||
return;
|
||
}
|
||
if (bHeightDiff[3] < 0 && bHeightDiff[5] < 0) {
|
||
Map->SetHeightAt(dwPos, oheight + 1);
|
||
return;
|
||
}
|
||
|
||
if (
|
||
(bHeightDiff[1] < 0 && bHeightDiff[6] < 0) ||
|
||
(bHeightDiff[1] < 0 && bHeightDiff[8] < 0) /*||
|
||
(bHeightDiff[3]<0 && bHeightDiff[2]<0) ||
|
||
(bHeightDiff[3]<0 && bHeightDiff[8]<0) ||
|
||
(bHeightDiff[5]<0 && bHeightDiff[0]<0) ||
|
||
(bHeightDiff[5]<0 && bHeightDiff[6]<0) ||
|
||
(bHeightDiff[7]<0 && bHeightDiff[0]<0) ||
|
||
(bHeightDiff[7]<0 && bHeightDiff[2]<0) */
|
||
) {
|
||
Map->SetHeightAt(dwPos, oheight + 1);
|
||
return;
|
||
}
|
||
}
|
||
|
||
|
||
/*
|
||
ChangeTileHeight();
|
||
|
||
General routine for changing the height of a tile.
|
||
Warning: This routine calls itself if necessary, and therefore may be quite performance hungry!
|
||
*/
|
||
void __fastcall CIsoView::ChangeTileHeight(DWORD dwPos, DWORD dwNewHeight, BOOL bNonMorpheableMove, BOOL bOnlyThisTile, BOOL bNoSlopes)
|
||
{
|
||
int isosize = Map->GetIsoSize();
|
||
int mapsize = isosize * isosize;
|
||
int mapwidth = Map->GetWidth();
|
||
int mapheight = Map->GetHeight();
|
||
|
||
int dwX = dwPos % isosize;
|
||
int dwY = dwPos / isosize;
|
||
|
||
//if(dwX==0 || dwY==0 || dwX+dwY<mapwidth || dwX+dwY>mapwidth+mapheight*2 || (dwY>mapwidth && dwX<dwY-mapwidth) || (dwX>mapwidth && dwY+mapwidth<dwX)) return;
|
||
//if( dwX<2|| dwY<2 || dwX+dwY<mapwidth+2 || dwX+dwY+2>mapwidth+mapheight*2 || (dwY+2>mapwidth && dwX-2<dwY-mapwidth) || (dwX+2>mapwidth && dwY+mapwidth-2<dwX)) return;
|
||
if (dwX < 1 || dwY < 1 || dwX + dwY<mapwidth + 1 || dwX + dwY>mapwidth + mapheight * 2
|
||
|| (dwY + 1 > mapwidth && dwX - 1 < dwY - mapwidth)
|
||
|| (dwX + 1 > mapwidth && dwY + mapwidth - 1 < dwX)) {
|
||
return;
|
||
}
|
||
|
||
FIELDDATA orig_fd = *Map->GetFielddataAt(dwPos);
|
||
|
||
//if(bOnlyHeighten && dwNewHeight<orig_fd.bHeight) return;
|
||
|
||
if (orig_fd.wGround == 0xFFFF) {
|
||
orig_fd.wGround = 0;
|
||
}
|
||
int orig_ground = orig_fd.wGround;
|
||
|
||
if (orig_fd.bReserved) {
|
||
return;
|
||
}
|
||
|
||
if (dwX < m_funcRect.left) {
|
||
m_funcRect.left = dwX;
|
||
}
|
||
if (dwY < m_funcRect.top) {
|
||
m_funcRect.top = dwY;
|
||
}
|
||
if (dwX > m_funcRect.right) {
|
||
m_funcRect.right = dwX;
|
||
}
|
||
if (dwY > m_funcRect.bottom) {
|
||
m_funcRect.bottom = dwY;
|
||
}
|
||
|
||
BOOL bCliffNext = FALSE;
|
||
/*if(bOnlyHeighten)
|
||
{
|
||
bCliffNext=FALSE;
|
||
/*int i;
|
||
int e;
|
||
for(i=-1;i<2;i++)
|
||
{
|
||
for(e=-1;e<2;e++)
|
||
{
|
||
int pos=dwPos+i+(e)*isosize;
|
||
|
||
FIELDDATA fd=*Map->GetFielddataAt(pos);
|
||
if(fd.wGround==0xFFFF) fd.wGround=0;
|
||
|
||
if((*tiledata)[fd.wGround].wTileSet==cliffset || fd.bCliffHack)
|
||
{
|
||
bCliffNext=TRUE;
|
||
break;
|
||
}
|
||
}
|
||
if(bCliffNext) break;
|
||
}*//*
|
||
|
||
}*/
|
||
|
||
Map->SetReserved(dwPos, 1);
|
||
|
||
|
||
if (!(*tiledata)[orig_ground].bMorphable) {
|
||
bNonMorpheableMove = TRUE;
|
||
}
|
||
Map->SetHeightAt(dwPos, dwNewHeight);
|
||
|
||
int i, e;
|
||
for (i = -1; i < 2; i++) {
|
||
for (e = -1; e < 2; e++) {
|
||
|
||
int pos = dwPos + i + (e)*isosize;
|
||
|
||
FIELDDATA fd = *Map->GetFielddataAt(pos);
|
||
if (fd.wGround == 0xFFFF) {
|
||
fd.wGround = 0;
|
||
}
|
||
|
||
BOOL bAllowed = TRUE;
|
||
|
||
if (dwX == 0 && i == -1) {
|
||
bAllowed = FALSE;
|
||
} else if (dwY == 0 && e == -1) {
|
||
bAllowed = FALSE;
|
||
} else if (dwX == isosize - 1 && i == 1) {
|
||
bAllowed = FALSE;
|
||
} else if (dwY == isosize - 1 && e == 1) {
|
||
bAllowed = FALSE;
|
||
}
|
||
if (bOnlyThisTile) {
|
||
if (fd.wGround != orig_fd.wGround) {
|
||
bAllowed = FALSE; // was another tile
|
||
} else {
|
||
// we now need to check if it is really the same tile or just the same tile type (!)
|
||
int of = orig_fd.bSubTile;
|
||
int f = fd.bSubTile;
|
||
int width = (*tiledata)[orig_ground].cy;
|
||
int height = (*tiledata)[orig_ground].cx;
|
||
int ox = of / width;
|
||
int oy = of % width;
|
||
int x = f / width;
|
||
int y = f % width;
|
||
if (x - ox != i || y - oy != e) {
|
||
bAllowed = FALSE;
|
||
}
|
||
}
|
||
}
|
||
|
||
int ground = fd.wGround;
|
||
|
||
if (bAllowed && !fd.bReserved && pos > 0 && pos < mapsize) {
|
||
BOOL bDestMorphable = (*tiledata)[fd.wGround].bMorphable;
|
||
TILEDATA destTile = (*tiledata)[fd.wGround];
|
||
TILEDATA sourceTile = (*tiledata)[orig_fd.wGround];
|
||
|
||
if (bAllowed && (!bNonMorpheableMove || bDestMorphable)) {
|
||
if (e == 1 && i == 1) {
|
||
int leftGround = Map->GetFielddataAt(dwPos + 1)->wGround;
|
||
int rightGround = Map->GetFielddataAt(dwPos + isosize)->wGround;
|
||
if (leftGround == 0xFFFF) {
|
||
leftGround = 0;
|
||
}
|
||
if (rightGround == 0xFFFF) {
|
||
rightGround = 0;
|
||
}
|
||
if (!(*tiledata)[leftGround].bMorphable && !(*tiledata)[rightGround].bMorphable) {
|
||
bAllowed = FALSE;
|
||
}
|
||
}
|
||
if (e == -1 && i == -1) {
|
||
int leftGround = Map->GetFielddataAt(dwPos - 1)->wGround;
|
||
int rightGround = Map->GetFielddataAt(dwPos - isosize)->wGround;
|
||
if (leftGround == 0xFFFF) {
|
||
leftGround = 0;
|
||
}
|
||
if (rightGround == 0xFFFF) {
|
||
rightGround = 0;
|
||
}
|
||
if (!(*tiledata)[leftGround].bMorphable && !(*tiledata)[rightGround].bMorphable) {
|
||
bAllowed = FALSE;
|
||
}
|
||
}
|
||
if (e == -1 && i == 1) {
|
||
int leftGround = Map->GetFielddataAt(dwPos - 1)->wGround;
|
||
int rightGround = Map->GetFielddataAt(dwPos + isosize)->wGround;
|
||
if (leftGround == 0xFFFF) {
|
||
leftGround = 0;
|
||
}
|
||
if (rightGround == 0xFFFF) {
|
||
rightGround = 0;
|
||
}
|
||
if (!(*tiledata)[leftGround].bMorphable && !(*tiledata)[rightGround].bMorphable) {
|
||
bAllowed = FALSE;
|
||
}
|
||
}
|
||
if (e == 1 && i == -1) {
|
||
int leftGround = Map->GetFielddataAt(dwPos + 1)->wGround;
|
||
int rightGround = Map->GetFielddataAt(dwPos - isosize)->wGround;
|
||
if (leftGround == 0xFFFF) {
|
||
leftGround = 0;
|
||
}
|
||
if (rightGround == 0xFFFF) {
|
||
rightGround = 0;
|
||
}
|
||
if (!(*tiledata)[leftGround].bMorphable && !(*tiledata)[rightGround].bMorphable) {
|
||
bAllowed = FALSE;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (/*(*tiledata)[ground].bMorphable &&*/ bAllowed) {
|
||
int need_diff = (*tiledata)[ground].tiles[fd.bSubTile].bZHeight - (*tiledata)[orig_ground].tiles[orig_fd.bSubTile].bZHeight;
|
||
//if(Map->GetHeightAt(pos)-dwNewHeight!=need_diff || !bNonMorpheableMove)
|
||
{
|
||
int diff = fd.bHeight - dwNewHeight;
|
||
/*
|
||
Activate this code to use the huge slopes
|
||
Removed because it did look worse than the normal slopes
|
||
*/
|
||
/*
|
||
if(i && abs(i)==abs(e))
|
||
{
|
||
if(diff<-1) diff++;
|
||
if(diff>1) diff--;
|
||
}*/
|
||
if (!bNonMorpheableMove && bDestMorphable) {
|
||
//if(!bOnlyHeighten)//!bCliffNext)
|
||
{
|
||
if (diff < -1) {
|
||
ChangeTileHeight(pos, dwNewHeight - 1, bNonMorpheableMove, bOnlyThisTile, bNoSlopes);
|
||
}
|
||
if (diff > 1) {
|
||
ChangeTileHeight(pos, dwNewHeight + 1, bNonMorpheableMove, bOnlyThisTile, bNoSlopes);
|
||
}
|
||
}
|
||
/*else
|
||
{
|
||
ChangeTileHeight(pos, dwNewHeight, bNonMorpheableMove, bOnlyThisTile, bOnlyHeighten);
|
||
}*/
|
||
} else if (bNonMorpheableMove) {
|
||
if (!bDestMorphable /*&& (*tiledata)[fd.wGround].wTileSet==(*tiledata)[orig_fd.wGround].wTileSet*/ /*&& need_diff!=fd.bHeight-orig_fd.bHeight*/) {
|
||
if (destTile.tiles[fd.bSubTile].bTerrainType == sourceTile.tiles[orig_fd.bSubTile].bTerrainType || destTile.wTileSet == sourceTile.wTileSet) {
|
||
ChangeTileHeight(pos, dwNewHeight + need_diff, TRUE, bOnlyThisTile, bNoSlopes);
|
||
}
|
||
} else if (bDestMorphable /*&& need_diff!=fd.bHeight-orig_fd.bHeight*/) {
|
||
//diff-=need_diff;
|
||
|
||
if ((sourceTile.cx > 1 && sourceTile.cy > 1 && (e < 0 && i < 0)) || ((sourceTile.cx < 2 || sourceTile.cy < 2) && (e > 0 && i > 0))) {
|
||
ChangeTileHeight(pos, dwNewHeight, FALSE, bOnlyThisTile, bNoSlopes);
|
||
} else {
|
||
if (diff - need_diff > 0)
|
||
ChangeTileHeight(pos, dwNewHeight + need_diff, FALSE, bOnlyThisTile, bNoSlopes);
|
||
else if (diff - need_diff < 0)
|
||
ChangeTileHeight(pos, dwNewHeight + need_diff, FALSE, bOnlyThisTile, bNoSlopes);
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/*for(i=-1;i<2;i++)
|
||
{
|
||
for(e=-1;e<2;e++)
|
||
{
|
||
FixTileHeight(dwPos+i+e*isosize, dwX+i, dwY+e);
|
||
}
|
||
}*/
|
||
|
||
if (!bNoSlopes) {
|
||
for (i = -1; i < 2; i++) {
|
||
for (e = -1; e < 2; e++) {
|
||
int pos = dwPos + i + (e)*isosize;
|
||
if (pos > 0 && pos < mapsize)
|
||
Map->CreateSlopesAt(pos);
|
||
}
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
BOOL CIsoView::ReachableFrom(DWORD dwStart, DWORD dwEnd)
|
||
{
|
||
FIELDDATA orig_fd = *Map->GetFielddataAt(dwStart);
|
||
if (orig_fd.wGround == 0xFF) orig_fd.wGround = 0;
|
||
int orig_ground = orig_fd.wGround;
|
||
|
||
if (orig_fd.bReserved) return FALSE;
|
||
orig_fd.bReserved = 1;
|
||
|
||
if (dwStart == dwEnd) return TRUE;
|
||
|
||
|
||
int i, e;
|
||
for (i = -1; i < 2; i++) {
|
||
for (e = -1; e < 2; e++) {
|
||
int new_ground = orig_fd.wGround;
|
||
if (new_ground == 0xFFFF) new_ground = 0;
|
||
|
||
if (!(*tiledata)[new_ground].bMorphable && ReachableFrom(dwStart + i + e * Map->GetIsoSize(), dwEnd))
|
||
return TRUE;
|
||
}
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
void CIsoView::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
|
||
{
|
||
CView::OnKeyUp(nChar, nRepCnt, nFlags);
|
||
}
|
||
|
||
void CIsoView::HideTileSet(DWORD dwTileSet)
|
||
{
|
||
int i;
|
||
for (i = 0; i < *tiledata_count; i++) {
|
||
if ((*tiledata)[i].wTileSet == dwTileSet) (*tiledata)[i].bHide = TRUE;
|
||
}
|
||
}
|
||
|
||
void CIsoView::BlitBackbufferToHighRes()
|
||
{
|
||
// MW:
|
||
// the primary buffer and the (optional) high-res buffer cover the whole screen (Windows automatic high DPI scaling does not change this)
|
||
// the backbuffer also has the size of the whole screen, however we don't render to the whole screen
|
||
// we only render to the visible window rectangle (which IS affected by Windows' automatic DPI scaling features)
|
||
// Additionally, we have a user-controlled scale factor.
|
||
// If the user zooms in, we only render to a smaller part of the backbuffer and stretch it to the window rectangle (which may then again be stretched by Windows DPI if enabled in the Windows settings).
|
||
// the rectangle we render to has the same left/top border but a lower value for right/bottom.
|
||
//
|
||
// This is a simple scaling and also scales any text that has already been rendered to the backbuffer (which is why we're usually rendering text afterwards to the HighRes backbuffer).
|
||
// Altogether it'd probably be best to move from DirectDraw to Direct3D, support high DPI awareness and do the scaling right when initially drawing the map.
|
||
|
||
|
||
if (m_viewScale != Vec2<CSProjected, float>(1.0f, 1.0f) && lpdsBackHighRes) {
|
||
// copy scene backbuffer to the high-res buffer that will receive text rendering
|
||
RECT dr;
|
||
GetWindowRect(&dr);
|
||
auto cr = GetScaledDisplayRect();
|
||
lpdsBackHighRes->Blt(&dr, lpdsBack, &cr, DDBLT_WAIT, 0);
|
||
} else {
|
||
// do nothing, backbuffer will receive additional text rendering as text doesn't have to be scaled
|
||
}
|
||
}
|
||
|
||
void CIsoView::FlipHighResBuffer()
|
||
{
|
||
if (m_viewScale != Vec2<CSProjected, float>(1.0f, 1.0f) && lpdsBackHighRes) {
|
||
// This flip copies the high-res backbuffer to the front buffer
|
||
RECT dr;
|
||
GetWindowRect(&dr);
|
||
lpds->Blt(&dr, lpdsBackHighRes, &dr, DDBLT_WAIT, 0);
|
||
} else {
|
||
// copy scene backbuffer to the front buffer that will receive text/gdi rendering
|
||
RECT dr;
|
||
GetWindowRect(&dr);
|
||
auto cr = GetScaledDisplayRect();
|
||
lpds->Blt(&dr, lpdsBack, &cr, DDBLT_WAIT, 0);
|
||
}
|
||
}
|
||
|
||
void CIsoView::ShowAllTileSets()
|
||
{
|
||
int i;
|
||
for (i = 0; i < *tiledata_count; i++) {
|
||
(*tiledata)[i].bHide = FALSE;
|
||
}
|
||
}
|
||
|
||
|
||
|
||
void CIsoView::PlaceCurrentObjectAt(int x, int y)
|
||
{
|
||
if (AD.mode == ACTIONMODE_RANDOMTERRAIN) {
|
||
if (Map->GetTerrainAt(x + y * Map->GetIsoSize()) >= 0) {
|
||
return;
|
||
}
|
||
|
||
CString s;
|
||
|
||
int n = rand() * rndterrainsrc.size() / RAND_MAX;
|
||
|
||
// safety checks...
|
||
if (n >= rndterrainsrc.size()) n = rndterrainsrc.size() - 1;
|
||
if (n < 0) n = 0;
|
||
|
||
s = rndterrainsrc[n];
|
||
|
||
Map->AddTerrain(s, x + y * Map->GetIsoSize());
|
||
|
||
return;
|
||
}
|
||
|
||
if (AD.type == 1) // ADD INFANTRY
|
||
{
|
||
if (Map->GetInfantryCountAt(x + y * Map->GetIsoSize()) >= SUBPOS_COUNT) {
|
||
return;
|
||
}
|
||
|
||
Map->AddInfantry(NULL, AD.data_s, currentOwner, x + y * Map->GetIsoSize());
|
||
//RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
} else if (AD.type == 2) // add structure
|
||
{
|
||
int n = Map->GetStructureAt(x + y * Map->GetIsoSize());
|
||
if (n >= 0) {
|
||
STDOBJECTDATA sod;
|
||
Map->GetStdStructureData(n, &sod);
|
||
if (strcmp(sod.type, "GAPAVE") != NULL) {
|
||
//isMoving=FALSE;
|
||
return;
|
||
}
|
||
}
|
||
|
||
|
||
Map->AddStructure(NULL, AD.data_s, currentOwner, x + y * Map->GetIsoSize());
|
||
//RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
} else if (AD.type == 3) // add aircraft
|
||
{
|
||
|
||
if (Map->GetAirAt(x + y * Map->GetIsoSize()) >= 0) {
|
||
return;
|
||
}
|
||
|
||
Map->AddAircraft(NULL, AD.data_s, currentOwner, x + y * Map->GetIsoSize());
|
||
|
||
//RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
} else if (AD.type == 4) // add vehicle
|
||
{
|
||
if (Map->GetUnitAt(x + y * Map->GetIsoSize()) >= 0) {
|
||
return;
|
||
}
|
||
|
||
Map->AddUnit(NULL, AD.data_s, currentOwner, x + y * Map->GetIsoSize());
|
||
|
||
//RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
} else if (AD.type == 5) // add terrain
|
||
{
|
||
if (Map->GetTerrainAt(x + y * Map->GetIsoSize()) >= 0) {
|
||
return;
|
||
}
|
||
|
||
Map->AddTerrain(AD.data_s, x + y * Map->GetIsoSize());
|
||
|
||
//RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
} else if (AD.type == 6) {
|
||
// Overlay
|
||
|
||
|
||
|
||
DWORD dwPos = x + y * Map->GetIsoSize();
|
||
|
||
FIELDDATA m = *Map->GetFielddataAt(dwPos);
|
||
if (m.wGround == 0xFFFF) m.wGround = 0;
|
||
|
||
BYTE oldOverlay = Map->GetOverlayAt(dwPos);
|
||
BYTE oldOverlayData = Map->GetOverlayDataAt(dwPos);
|
||
|
||
if (AD.data == 1) // delete overlay
|
||
{
|
||
int gx, gy;
|
||
for (gx = x - AD.data2; gx <= x + AD.data2; gx++) {
|
||
for (gy = y - AD.data2; gy <= y + AD.data2; gy++) {
|
||
Map->SetOverlayDataAt(gx + gy * Map->GetIsoSize(), 0xFF);
|
||
Map->SetOverlayAt(gx + gy * Map->GetIsoSize(), 0xFF);
|
||
|
||
|
||
HandleTrail(gx - 1, gy - 1);
|
||
HandleTrail(gx + 1, gy - 1);
|
||
HandleTrail(gx - 1, gy + 1);
|
||
HandleTrail(gx + 1, gy + 1);
|
||
HandleTrail(gx - 0, gy - 1);
|
||
HandleTrail(gx + 0, gy + 1);
|
||
HandleTrail(gx - 1, gy + 0);
|
||
HandleTrail(gx + 1, gy + 0);
|
||
}
|
||
}
|
||
|
||
|
||
} else if (AD.data == 2) // green tiberium mode
|
||
{
|
||
|
||
{
|
||
if (AD.data2 == 0) {
|
||
int i, e;
|
||
for (i = 0; i < m_BrushSize_x; i++) {
|
||
for (e = 0; e < m_BrushSize_y; e++) {
|
||
int curground = Map->GetFielddataAt(dwPos + i + e * Map->GetIsoSize())->wGround;
|
||
if (curground == 0xFFFF) curground = 0;
|
||
|
||
if ((*tiledata)[curground].bAllowTiberium) {
|
||
//srand( GetTickCount()+i+e*5 );
|
||
int v1 = ((float)rand() / (float)RAND_MAX) * 8.0f + 0x68;
|
||
int v2 = ((float)rand() / (float)RAND_MAX) * 8.0f + 1;
|
||
Map->SetOverlayAt(dwPos + i + e * Map->GetIsoSize(), v1);
|
||
Map->SetOverlayDataAt(dwPos + i + e * Map->GetIsoSize(), v2);
|
||
}
|
||
}
|
||
}
|
||
} else if (AD.data2 == 10) {
|
||
int i, e;
|
||
for (i = 0; i < m_BrushSize_x; i++) {
|
||
for (e = 0; e < m_BrushSize_y; e++) {
|
||
int curground = Map->GetFielddataAt(dwPos + i + e * Map->GetIsoSize())->wGround;
|
||
if (curground == 0xFFFF) curground = 0;
|
||
|
||
if ((*tiledata)[curground].bAllowTiberium) {
|
||
Map->SetOverlayAt(dwPos + i + e * Map->GetIsoSize(), 0x70);
|
||
Map->SetOverlayDataAt(dwPos + i + e * Map->GetIsoSize(), 0x5);
|
||
}
|
||
}
|
||
}
|
||
} else if (AD.data2 == 20) {
|
||
int i, e;
|
||
for (i = 0; i < m_BrushSize_x; i++) {
|
||
for (e = 0; e < m_BrushSize_y; e++) {
|
||
int ovrl = Map->GetOverlayAt(dwPos + i + e * Map->GetIsoSize());
|
||
if (ovrl > 0x65 && ovrl < 0x72) {
|
||
if (Map->GetOverlayDataAt(i + e * Map->GetIsoSize() + dwPos) < 9) Map->SetOverlayDataAt(dwPos + i + e * Map->GetIsoSize(), Map->GetOverlayDataAt(dwPos + i + e * Map->GetIsoSize()) + 1);
|
||
}
|
||
}
|
||
}
|
||
} else if (AD.data2 == 21) {
|
||
|
||
int i, e;
|
||
for (i = 0; i < m_BrushSize_x; i++) {
|
||
for (e = 0; e < m_BrushSize_y; e++) {
|
||
int ovrl = Map->GetOverlayAt(dwPos + i + e * Map->GetIsoSize());
|
||
if (ovrl > 0x65 && ovrl < 0x72) {
|
||
if (Map->GetOverlayDataAt(dwPos + i + e * Map->GetIsoSize()) > 0) Map->SetOverlayDataAt(dwPos + i + e * Map->GetIsoSize(), Map->GetOverlayDataAt(dwPos + i + e * Map->GetIsoSize()) - 1);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
} else if (AD.data == 3) // blue tiberium mode
|
||
{
|
||
int o = 0x7f;
|
||
#ifdef RA2_MODE
|
||
o = 0x1e;
|
||
#endif
|
||
//if((*tiledata)[m.wGround].bAllowTiberium)
|
||
{
|
||
if (AD.data2 == 0) {
|
||
|
||
int i, e;
|
||
for (i = 0; i < m_BrushSize_x; i++) {
|
||
for (e = 0; e < m_BrushSize_y; e++) {
|
||
int curground = Map->GetFielddataAt(dwPos + i + e * Map->GetIsoSize())->wGround;
|
||
if (curground == 0xFFFF) curground = 0;
|
||
|
||
if ((*tiledata)[curground].bAllowTiberium) {
|
||
|
||
int v2 = ((float)rand() / (float)RAND_MAX) * 8 + 1;
|
||
Map->SetOverlayAt(dwPos + i + e * Map->GetIsoSize(), o);
|
||
Map->SetOverlayDataAt(dwPos + i + e * Map->GetIsoSize(), v2);
|
||
}
|
||
}
|
||
}
|
||
|
||
} else if (AD.data2 == 10) {
|
||
int i, e;
|
||
for (i = 0; i < m_BrushSize_x; i++) {
|
||
for (e = 0; e < m_BrushSize_y; e++) {
|
||
int curground = Map->GetFielddataAt(dwPos + i + e * Map->GetIsoSize())->wGround;
|
||
if (curground == 0xFFFF) curground = 0;
|
||
|
||
if ((*tiledata)[curground].bAllowTiberium) {
|
||
Map->SetOverlayAt(dwPos + i + e * Map->GetIsoSize(), o);
|
||
Map->SetOverlayDataAt(dwPos + i + e * Map->GetIsoSize(), 0x5);
|
||
}
|
||
}
|
||
}
|
||
} else if (AD.data2 == 20) {
|
||
int i, e;
|
||
for (i = 0; i < m_BrushSize_x; i++) {
|
||
for (e = 0; e < m_BrushSize_y; e++) {
|
||
int ovrl = Map->GetOverlayAt(dwPos + i + e * Map->GetIsoSize());
|
||
if (ovrl == o) {
|
||
if (Map->GetOverlayDataAt(dwPos + i + e * Map->GetIsoSize()) < 9) Map->SetOverlayDataAt(dwPos + i + e * Map->GetIsoSize(), Map->GetOverlayDataAt(dwPos + i + e * Map->GetIsoSize()) + 1);
|
||
}
|
||
}
|
||
}
|
||
} else if (AD.data2 == 21) {
|
||
int i, e;
|
||
for (i = 0; i < m_BrushSize_x; i++) {
|
||
for (e = 0; e < m_BrushSize_y; e++) {
|
||
int ovrl = Map->GetOverlayAt(dwPos + i + e * Map->GetIsoSize());
|
||
if (ovrl == o) {
|
||
if (Map->GetOverlayDataAt(dwPos + i + e * Map->GetIsoSize()) > 0) Map->SetOverlayDataAt(dwPos + i + e * Map->GetIsoSize(), Map->GetOverlayDataAt(dwPos + i + e * Map->GetIsoSize()) - 1);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
} else if (AD.data == 4) // veinhole stuff mode
|
||
{
|
||
if (AD.data2 == 0) // Set veinhole!
|
||
{
|
||
int gx, gy;
|
||
for (gx = x - 1; gx <= x + 1; gx++) {
|
||
for (gy = y - 1; gy <= y + 1; gy++) {
|
||
Map->SetOverlayAt(gx + gy * Map->GetIsoSize(), OVRL_VEINHOLEBORDER);
|
||
Map->SetOverlayDataAt(gx + gy * Map->GetIsoSize(), 0x0);
|
||
}
|
||
}
|
||
Map->SetOverlayAt(dwPos, OVRL_VEINHOLE);
|
||
Map->SetOverlayDataAt(dwPos, 0x0);
|
||
Map->SetHeightAt(dwPos, Map->GetHeightAt(dwPos) - 1);
|
||
} else if (AD.data2 == 1) // set veins
|
||
{
|
||
Map->SetOverlayAt(dwPos, OVRL_VEINS);
|
||
Map->SetOverlayDataAt(dwPos, 0x30);
|
||
}
|
||
|
||
} else if (AD.data == 30) // any overlay
|
||
{
|
||
Map->SetOverlayAt(dwPos, AD.data2);
|
||
Map->SetOverlayDataAt(dwPos, 0);
|
||
int i;
|
||
for (i = 0; i < overlay_count; i++) {
|
||
if (overlay_number[i] == AD.data2) {
|
||
if (overlay_trail[i]) {
|
||
// handle trail stuff!
|
||
HandleTrail(x, y);
|
||
}
|
||
}
|
||
}
|
||
} else if (AD.data == 33) {
|
||
int i, e;
|
||
for (i = 0; i < m_BrushSize_x; i++) {
|
||
for (e = 0; e < m_BrushSize_y; e++) {
|
||
Map->SetOverlayAt(dwPos + i + e * Map->GetIsoSize(), AD.data2);
|
||
Map->SetOverlayDataAt(dwPos + i + e * Map->GetIsoSize(), AD.data3);
|
||
}
|
||
}
|
||
}
|
||
|
||
else if (AD.data == 31) {
|
||
Map->SetOverlayAt(dwPos, AD.data2);
|
||
} else if (AD.data == 32) {
|
||
Map->SetOverlayDataAt(dwPos, AD.data2);
|
||
}
|
||
|
||
// RedrawWindow(NULL,NULL,RDW_INVALIDATE | RDW_UPDATENOW);
|
||
} else if (AD.type == 7) {
|
||
// set owner!
|
||
BOOL bchanged = FALSE;
|
||
|
||
int t = Map->GetStructureAt(x + y * Map->GetIsoSize());
|
||
if (t >= 0) {
|
||
STRUCTURE structure;
|
||
Map->GetStructureData(t, &structure);
|
||
Map->DeleteStructure(t);
|
||
structure.house = AD.data_s;
|
||
Map->AddStructure(&structure);
|
||
bchanged = TRUE;
|
||
}
|
||
t = Map->GetUnitAt(x + y * Map->GetIsoSize());
|
||
if (t >= 0) {
|
||
UNIT unit;
|
||
Map->GetUnitData(t, &unit);
|
||
Map->DeleteUnit(t);
|
||
unit.house = AD.data_s;
|
||
Map->AddUnit(&unit);
|
||
bchanged = TRUE;
|
||
}
|
||
t = Map->GetAirAt(x + y * Map->GetIsoSize());
|
||
if (t >= 0) {
|
||
AIRCRAFT aircraft;
|
||
Map->GetAircraftData(t, &aircraft);
|
||
Map->DeleteAircraft(t);
|
||
aircraft.house = AD.data_s;
|
||
Map->AddAircraft(&aircraft);
|
||
bchanged = TRUE;
|
||
}
|
||
int z;
|
||
for (z = 0; z < SUBPOS_COUNT; z++) {
|
||
t = Map->GetInfantryAt(x + y * Map->GetIsoSize(), z);
|
||
if (t >= 0) {
|
||
INFANTRY infantry;
|
||
Map->GetInfantryData(t, &infantry);
|
||
Map->DeleteInfantry(t);
|
||
infantry.house = AD.data_s;
|
||
Map->AddInfantry(&infantry);
|
||
bchanged = TRUE;
|
||
}
|
||
}
|
||
|
||
if (bchanged) {
|
||
//RedrawWindow(NULL,NULL,RDW_INVALIDATE | RDW_UPDATENOW);
|
||
}
|
||
|
||
|
||
}
|
||
#ifdef SMUDGE_SUPP
|
||
else if (AD.type == 8) // add smudge
|
||
{
|
||
|
||
if (Map->GetFielddataAt(x + y * Map->GetIsoSize())->smudge >= 0) {
|
||
return;
|
||
}
|
||
|
||
SMUDGE s;
|
||
s.type = AD.data_s;
|
||
s.x = x;
|
||
s.y = y;
|
||
s.deleted = 0;
|
||
Map->AddSmudge(&s);
|
||
|
||
//RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
}
|
||
#endif
|
||
|
||
}
|
||
|
||
void CIsoView::OnTimer(UINT_PTR nIDEvent)
|
||
{
|
||
// theApp.m_loading->FreeAll();
|
||
// theApp.m_loading->InitPics();
|
||
|
||
last_succeeded_operation = 1000000;
|
||
|
||
|
||
if (nIDEvent == 11) {
|
||
// BUGSEARCH
|
||
//if(b_IsLoading) return;
|
||
//
|
||
m_viewOffset += ProjectedVec((cur_x_mouse - rclick_x) / 2, (cur_y_mouse - rclick_y) / 2);
|
||
|
||
SetScroll(m_viewOffset.x, m_viewOffset.y);
|
||
|
||
InvalidateRect(NULL, FALSE);
|
||
} else {
|
||
errstream << "Timer calls InitTMPs()" << std::endl;
|
||
errstream.flush();
|
||
|
||
theApp.m_loading->InitTMPs();
|
||
|
||
CView::OnTimer(nIDEvent);
|
||
|
||
KillTimer(nIDEvent);
|
||
|
||
b_IsLoading = FALSE;
|
||
RedrawWindow();
|
||
}
|
||
}
|
||
|
||
void CIsoView::FillArea(DWORD dwX, DWORD dwY, DWORD dwID, BYTE bSubTile)
|
||
{
|
||
if ((*tiledata)[dwID].cx != 1 || (*tiledata)[dwID].cy != 1) {
|
||
MessageBox("You can only use 1x1 tiles to fill areas.");
|
||
return;
|
||
}
|
||
|
||
FIELDDATA* f = Map->GetFielddataAt(dwX + dwY * Map->GetIsoSize());
|
||
f->bReserved = TRUE;
|
||
|
||
int mapwidth, mapheight;
|
||
mapwidth = Map->GetWidth();
|
||
mapheight = Map->GetHeight();
|
||
|
||
int i, e;
|
||
for (i = -1; i < 2; i++) {
|
||
for (e = -1; e < 2; e++) {
|
||
if (abs(i) == abs(e)) continue;
|
||
int cur_x, cur_y;
|
||
cur_x = dwX + i;
|
||
cur_y = dwY + e;
|
||
if (cur_x < 1 || cur_y < 1 || cur_x + cur_y<mapwidth + 1 || cur_x + cur_y>mapwidth + mapheight * 2 || (cur_y + 1 > mapwidth && cur_x - 1 < cur_y - mapwidth) || (cur_x + 1 > mapwidth && cur_y + mapwidth - 1 < cur_x)) continue;
|
||
|
||
FIELDDATA* f2 = Map->GetFielddataAt(cur_x + cur_y * Map->GetIsoSize());
|
||
|
||
if (f2->bReserved) continue;
|
||
|
||
|
||
|
||
if (f2->wGround != dwID && f2->wGround == f->wGround && f2->bSubTile == f->bSubTile) {
|
||
FillArea(cur_x, cur_y, dwID, bSubTile);
|
||
}
|
||
|
||
}
|
||
}
|
||
f->wGround = dwID;
|
||
f->bSubTile = bSubTile;
|
||
}
|
||
|
||
void CIsoView::AutoLevel()
|
||
{
|
||
Map->TakeSnapshot();
|
||
|
||
|
||
|
||
int mapsize = Map->GetIsoSize() * Map->GetIsoSize();
|
||
int mapedge = Map->GetIsoSize();
|
||
|
||
if (mapsize == 0) return;
|
||
|
||
BOOL* bChanged;
|
||
bChanged = new(BOOL[mapsize]);
|
||
memset(bChanged, 0, mapsize);
|
||
|
||
int iCliffStart = -1; //, iSlopeSetStart = -1;
|
||
|
||
int i;
|
||
|
||
for (i = 0; i < *tiledata_count; i++) {
|
||
if ((*tiledata)[i].wTileSet == cliffset) {
|
||
iCliffStart = i;
|
||
break;
|
||
|
||
}
|
||
}
|
||
|
||
if (iCliffStart < 0)
|
||
return;
|
||
|
||
/*for (i = 0;i<*tiledata_count;i++)
|
||
{
|
||
if((*tiledata)[i].wTileSet==slopesetpiecesset)
|
||
{
|
||
iSlopeSetStart=i;
|
||
break;
|
||
}
|
||
}*/
|
||
|
||
/*int count=atoi(g_data.sections["SlopeSetPiecesDirections"].values["Count"]);
|
||
BYTE* bXLeftSearch=new(BYTE[count]);
|
||
BYTE* bXRightSearch=new(BYTE[count]);
|
||
BYTE* bYTopSearch=new(BYTE[count]);
|
||
BYTE* bYBottomSearch=new(BYTE[count]);
|
||
|
||
for(i=0;i<count;i++)
|
||
{
|
||
char c[50];
|
||
itoa(i,c,10);
|
||
CString s=*g_data.sections["SlopeSetPiecesDirections"].GetValue(i);
|
||
if(s=="Right_1") { bXLeftSearch=0; bXRightSearch=1; b
|
||
else if(s=="Left_1") bDirections[i]=1;
|
||
else if(s=="Bottom_1") bDirections[i]=2;
|
||
else if(s=="Top_1") bDirections[i]=3;
|
||
else if(s=="Right_2") bDirections[i]=4;
|
||
else if(s=="Left_2") bDirections[i]=5;
|
||
else if(s=="Bottom_2") bDirections[i]=6;
|
||
else if(s=="Top_2") bDirections[i]=7;
|
||
}*/
|
||
|
||
for (i = 0; i < mapsize; i++) {
|
||
FIELDDATA* f1 = Map->GetFielddataAt(i);
|
||
int o_ground = f1->wGround;
|
||
if (o_ground == 0xFFFF) o_ground = 0;
|
||
int o_width = (*tiledata)[o_ground].cx;
|
||
int o_height = (*tiledata)[o_ground].cy;
|
||
|
||
int ox, oy;
|
||
ox = i % mapedge;
|
||
oy = i / mapedge;
|
||
|
||
|
||
int x, y;
|
||
for (x = -1; x < 2; x++) {
|
||
for (y = -1; y < 2; y++) {
|
||
if (x == -1 && y == -1) continue;
|
||
if (x == 1 && y == 1) continue;
|
||
if (x == 1 && y == -1) continue;
|
||
if (x == -1 && y == 1) continue;
|
||
|
||
int count = 0;
|
||
int p, k;
|
||
int heights[32][32];
|
||
memset(heights, 0, 32 * 32 * sizeof(int));
|
||
|
||
for (p = 0; p < o_width; p++) {
|
||
for (k = 0; k < o_height; k++) {
|
||
count++;
|
||
heights[p][k] = (*tiledata)[o_ground].tiles[p + k * o_width].bZHeight;
|
||
}
|
||
}
|
||
|
||
|
||
|
||
if (o_ground < 8 + iCliffStart || o_ground>13 + iCliffStart) {
|
||
if (count < 4 || count>4) {
|
||
if (x < 0 || y < 0) continue;
|
||
}
|
||
|
||
|
||
|
||
|
||
if (heights[0][0] && !heights[1][1]) {
|
||
if (heights[1][0] && heights[0][1]) {
|
||
|
||
if (x < 0 || y < 0) continue;
|
||
|
||
}
|
||
}
|
||
|
||
if (heights[0][0] && heights[1][1]) {
|
||
if (x < 0 || y>0) continue;
|
||
}
|
||
|
||
if (!heights[0][0] && heights[1][0] && heights[0][1] && heights[1][1]) {
|
||
if (x < 0 || y < 0) continue;
|
||
}
|
||
} else {
|
||
if (x > 0 || y > 0) continue;
|
||
}
|
||
|
||
if (x + ox > mapedge || x + ox<0 || y + oy>mapedge || y + oy < 0)
|
||
continue;
|
||
|
||
FIELDDATA* cur_f = Map->GetFielddataAt(i + x + y * mapedge);
|
||
|
||
int cur_ground = cur_f->wGround;
|
||
if (cur_ground == 0xFFFF) cur_ground = 0;
|
||
int cur_set;
|
||
if ((*tiledata)[cur_ground].wTileSet != (*tiledata)[o_ground].wTileSet) {
|
||
|
||
if (((*tiledata)[o_ground].wTileSet == cliffset || (*tiledata)[o_ground].wTileSet == slopesetpiecesset) && (*tiledata)[cur_ground].bMorphable) {
|
||
int height_diff = f1->bHeight - cur_f->bHeight;
|
||
if (o_ground >= 8 + iCliffStart && o_ground <= 13 + iCliffStart && (*tiledata)[o_ground].tiles[cur_f->bSubTile].bZHeight == 0) height_diff += 4;
|
||
int need_diff = height_diff;//(*tiledata)[o_ground].tiles[f1->bSubTile].bZHeight-(*tiledata)[cur_ground].tiles[cur_f->bSubTile].bZHeight;
|
||
//if((*tiledata)[o_ground].tiles[f1->bSubTile].bZ
|
||
if (abs(height_diff) > 1) {
|
||
//ChangeTileHeight(i+x+y*mapedge,f1->bHeight,FALSE, FALSE);
|
||
int height = f1->bHeight;
|
||
if (o_ground >= 8 + iCliffStart && o_ground <= 13 + iCliffStart && (*tiledata)[o_ground].tiles[cur_f->bSubTile].bZHeight == 0) height = f1->bHeight + 4;
|
||
Map->SetHeightAt(i + x + y * mapedge, height);
|
||
bChanged[i + x + y * mapedge] = TRUE;
|
||
} else if (height_diff)
|
||
Map->CreateSlopesAt(i + x + y * mapedge);
|
||
//bChanged[i+x+y*mapedge]=TRUE;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
for (i = 0; i < mapsize; i++) {
|
||
|
||
if (bChanged[i]) {
|
||
int e;
|
||
for (e = 0; e < Map->GetIsoSize() * Map->GetIsoSize(); e++)
|
||
Map->SetReserved(e, 0);
|
||
ChangeTileHeight(i, Map->GetHeightAt(i), FALSE, FALSE);
|
||
}
|
||
|
||
}
|
||
|
||
/* delete[] bXSearch;
|
||
delete[] bYSearch;*/
|
||
|
||
if (bChanged) delete[] bChanged;
|
||
|
||
RedrawWindow();
|
||
|
||
Map->TakeSnapshot();
|
||
Map->Undo();
|
||
}
|
||
|
||
inline void ToIso3d_NoAccessCheck(int* x, int* y)
|
||
{
|
||
int cx = *x, cy = *y;
|
||
|
||
ToIso(&cx, &cy);
|
||
|
||
int i, e = 0;
|
||
|
||
|
||
for (i = 15; i >= 0; i--) {
|
||
for (e = 0; e < 3; e++) {
|
||
int a;
|
||
|
||
|
||
int m, n;
|
||
int px, py;
|
||
m = cx + i;
|
||
n = cy + i;
|
||
|
||
if (e == 1) m -= 1;
|
||
if (e == 2) n -= 1;
|
||
|
||
px = m;
|
||
py = n;
|
||
|
||
if (m >= 0 && n >= 0 && m < Map->GetIsoSize() && n < Map->GetIsoSize()) {
|
||
FIELDDATA mfd = *Map->GetFielddataAt(px + py * Map->GetIsoSize());
|
||
int ground = mfd.wGround;
|
||
if (ground == 0xFFFF) ground = 0;
|
||
//if(mfd.bHide==FALSE && !(*tiledata)[ground].bHide)
|
||
{
|
||
|
||
ToPhys3d(&m, &n);
|
||
|
||
// now m and n hold the pixel coordinates for the current field...
|
||
// we now need to check if cx and cy are in this field
|
||
//if(*x >= m && *x<= m+f_x && *y>=n && *y<=n+f_y)
|
||
{
|
||
int dx = *x - m;
|
||
int dy = *y - n - f_y / 2;//-f_y/2;
|
||
int dx1 = dx;
|
||
int dy1 = dy;
|
||
|
||
dx = ((float)dy1) / ((float)f_y) - ((float)dx1) / ((float)f_x) + 1.0f;//+ 1 + (float)0.5 +1;
|
||
dy = ((float)dx1) / ((float)f_x) + ((float)dy1) / ((float)f_y) + 0.0f;//- 1-(float)0.5 +1;
|
||
|
||
if (((dx == 0 && dy == 0) || (!bAllowAccessBehindCliffs && *y - n > f_y))) {
|
||
*x = px - 0;
|
||
*y = py + 0;
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/*
|
||
for(i=15;i>=0;i--)
|
||
{
|
||
for(e=0;e<3;e++)
|
||
{
|
||
int a;
|
||
|
||
|
||
int m,n;
|
||
int px,py;
|
||
m=cx+i;
|
||
n=cy+i;
|
||
|
||
if(e==1) m-=1;
|
||
if(e==2) n-=1;
|
||
|
||
px=m;
|
||
py=n;
|
||
|
||
if(m>=0 && n>=0 && m< Map->GetIsoSize() && n<Map->GetIsoSize())
|
||
{
|
||
|
||
ToPhys3d(&m, &n);
|
||
|
||
// just find at least one tile if possible...
|
||
|
||
if(*x>m && *y>n)
|
||
{
|
||
*x=px;
|
||
*y=py;
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
}*/
|
||
|
||
|
||
* x = cx;//-1;
|
||
*y = cy;//-1;
|
||
}
|
||
|
||
|
||
|
||
void CIsoView::DrawMap()
|
||
{
|
||
const CMapData* const Map = ::Map;
|
||
|
||
if (bNoDraw) return;
|
||
|
||
if (bCancelDraw) {
|
||
bCancelDraw = FALSE;
|
||
return;
|
||
}
|
||
|
||
last_succeeded_operation = 100;
|
||
|
||
if (lpds == NULL || b_IsLoading || tiledata == NULL || (*tiledata) == NULL || (*tiledata_count == 0)) return; // just to make sure...
|
||
|
||
if (lpds->IsLost() != DD_OK) {
|
||
// we lost our surfaces, we need to reinitialize directdraw and all associated objects
|
||
ReInitializeDDraw();
|
||
return;
|
||
}
|
||
|
||
|
||
|
||
if (Map->GetIsoSize() == 0) return;
|
||
|
||
auto startTime = std::chrono::steady_clock::now();
|
||
|
||
// draw a white background
|
||
DDBLTFX fx;
|
||
memset(&fx, 0, sizeof(DDBLTFX));
|
||
fx.dwSize = sizeof(DDBLTFX);
|
||
fx.dwFillColor = RGB(255, 255, 255);
|
||
lpdsBack->Blt(NULL, NULL, NULL, DDBLT_COLORFILL, &fx);
|
||
|
||
|
||
// get the window rect
|
||
|
||
RECT r = GetScaledDisplayRect();
|
||
|
||
// the code here draws the coordinate system
|
||
int i;
|
||
|
||
|
||
// now, we draw all the objects
|
||
|
||
|
||
int left, right, top, bottom;
|
||
|
||
{
|
||
RECT cr;
|
||
GetClientRect(&cr);
|
||
auto topLeft = GetMapCoordinatesFromClientCoordinates(CPoint(0, 0), false, true);
|
||
auto topRight = GetMapCoordinatesFromClientCoordinates(CPoint(cr.right, 0), false, true);
|
||
auto bottomLeft = GetMapCoordinatesFromClientCoordinates(CPoint(0, cr.bottom), false, true);
|
||
auto bottomRight = GetMapCoordinatesFromClientCoordinates(CPoint(cr.right, cr.bottom), false, true);
|
||
left = std::min(topLeft.x, topRight.x);
|
||
top = std::min(topLeft.y, topRight.y);
|
||
right = std::max(bottomLeft.x, bottomRight.x);
|
||
bottom = std::max(bottomLeft.y, bottomRight.y);
|
||
}
|
||
|
||
// some large buildings may be out of reach:
|
||
left -= 2;
|
||
top -= 2;
|
||
right += 7;
|
||
bottom += 7;
|
||
|
||
|
||
|
||
// validate the coordinates
|
||
if (left < 0) left = 0;
|
||
if (bottom >= Map->GetIsoSize() || bottom < top) bottom = Map->GetIsoSize();
|
||
if (right >= Map->GetIsoSize() || right < left) right = Map->GetIsoSize();
|
||
if (top < 0) top = 0;
|
||
|
||
|
||
BOOL bMarbleHeight = TRUE;
|
||
//if(Map->GetTheater()==THEATER4 || Map->GetTheater()==THEATER3) bMarbleHeight=FALSE;
|
||
|
||
// Now left, right, top & bottom contain the needed values
|
||
|
||
DWORD MM_heightstart = tilesets_start[atoi((*tiles).GetString("General", "HeightBase"))];
|
||
|
||
// now draw everything
|
||
int u, v, z;
|
||
int mapwidth, mapheight;
|
||
mapwidth = Map->GetWidth();
|
||
mapheight = Map->GetHeight();
|
||
|
||
DDSURFACEDESC2 ddsd;
|
||
ZeroMemory(&ddsd, sizeof(ddsd));
|
||
ddsd.dwSize = sizeof(DDSURFACEDESC2);
|
||
ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
|
||
|
||
lpdsBack->GetSurfaceDesc(&ddsd);
|
||
|
||
|
||
#ifdef NOSURFACES
|
||
lpdsBack->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT | DDLOCK_NOSYSLOCK, NULL);
|
||
#endif
|
||
|
||
// we render texts and waypoints last as they should be always visible anyway and because text rendering is currently done using GDI -> getting a DC for every text is too slow nowadays
|
||
m_texts_to_render.clear();
|
||
m_waypoints_to_render.clear();
|
||
|
||
for (u = left; u < right; u++) {
|
||
for (v = top; v < bottom; v++) {
|
||
const MapCoords mapCoords(u, v);
|
||
if (bCancelDraw) {
|
||
bCancelDraw = FALSE;
|
||
}
|
||
|
||
if (u < 1 || v < 1 || u + v<mapwidth + 1 || u + v>mapwidth + mapheight * 2 || (v + 1 > mapwidth && u - 1 < v - mapwidth) || (u + 1 > mapwidth && v + mapwidth - 1 < u))
|
||
continue;
|
||
|
||
|
||
FIELDDATA m = *Map->GetFielddataAt(mapCoords);
|
||
const auto drawCoords = GetRenderTargetCoordinates(mapCoords);
|
||
|
||
// draw terrain
|
||
if (m.wGround >= (*tiledata_count))
|
||
m.wGround = 0;
|
||
|
||
DWORD dwOrigGround = m.wGround;
|
||
|
||
if (theApp.m_Options.bMarbleMadness) {
|
||
if ((*tiledata)[m.wGround].wMarbleGround != 0xFFFF) {
|
||
|
||
m.wGround = (*tiledata)[m.wGround].wMarbleGround;
|
||
} else if (bMarbleHeight) {
|
||
//drawy+=f_y*m.bHeight;
|
||
|
||
m.wGround = MM_heightstart + m.bHeight;
|
||
m.bSubTile = 0;
|
||
}
|
||
}
|
||
|
||
if (!m.bRedrawTerrain) {
|
||
|
||
TILEDATA* td = &(*tiledata)[m.wGround];
|
||
if (td->bReplacementCount) {
|
||
if (m.bRNDImage > 0) {
|
||
m.bRNDImage <= td->bReplacementCount ? td = &td->lpReplacements[m.bRNDImage - 1] : td = &td->lpReplacements[td->bReplacementCount - 1];
|
||
}
|
||
}
|
||
|
||
if (m.bSubTile < td->wTileCount && td->tiles[m.bSubTile].pic != NULL) {
|
||
const SUBTILE& st = td->tiles[m.bSubTile];
|
||
const auto stDrawCoords = drawCoords + st.drawOffset();
|
||
|
||
|
||
if (!m.bHide && (*tiledata)[dwOrigGround].bHide == FALSE) {
|
||
#ifndef NOSURFACES
|
||
Blit(st.pic, stDrawCoords.x, stDrawCoords.y, st.wWidth, st.wHeight);
|
||
#else
|
||
BlitTerrain(ddsd.lpSurface, stDrawCoords.x, stDrawCoords.y,
|
||
r.left, r.top,
|
||
DDBoundary{ ddsd.dwWidth, ddsd.dwHeight, ddsd.lPitch },
|
||
r.right, r.bottom,
|
||
st);
|
||
#endif
|
||
} else {// draw soemthing representing the tile
|
||
#ifndef NOSURFACES
|
||
DrawCell(stDrawCoords.x, stDrawCoords.y, 1, 1, RGB(0, 140, 0), FALSE, FALSE);
|
||
#else
|
||
BlitTerrainHalfTransp(ddsd.lpSurface, stDrawCoords.x, stDrawCoords.y,
|
||
r.left, r.top,
|
||
DDBoundary{ ddsd.dwWidth, ddsd.dwHeight, ddsd.lPitch },
|
||
r.right, r.bottom,
|
||
st);
|
||
#endif
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
|
||
for (u = left; u < right; u++) {
|
||
for (v = top; v < bottom; v++) {
|
||
const MapCoords mapCoords(u, v);
|
||
if (bCancelDraw) {
|
||
bCancelDraw = FALSE;
|
||
}
|
||
|
||
if (u < 1 || v < 1 || u + v<mapwidth + 1 || u + v>mapwidth + mapheight * 2 || (v + 1 > mapwidth && u - 1 < v - mapwidth) || (u + 1 > mapwidth && v + mapwidth - 1 < u)) {
|
||
continue;
|
||
}
|
||
|
||
FIELDDATA m = *Map->GetFielddataAt(mapCoords); // copy
|
||
const auto drawCoords = GetRenderTargetCoordinates(mapCoords);
|
||
|
||
if (m.wGround == 0xFFFF)
|
||
m.wGround = 0;
|
||
|
||
DWORD dwOrigGround = m.wGround;
|
||
|
||
if (theApp.m_Options.bMarbleMadness) {
|
||
if ((*tiledata)[m.wGround].wMarbleGround != 0xFFFF) {
|
||
m.wGround = (*tiledata)[m.wGround].wMarbleGround;
|
||
} else if (bMarbleHeight) {
|
||
//y+=f_y*m.bHeight;
|
||
m.wGround = MM_heightstart + m.bHeight;
|
||
m.bSubTile = 0;
|
||
}
|
||
}
|
||
|
||
if (m.bRedrawTerrain) {
|
||
// draw cliff again to hide buildings behind
|
||
|
||
if (m.wGround < *tiledata_count) {
|
||
TILEDATA* td = &(*tiledata)[m.wGround];
|
||
if (td->bReplacementCount) {
|
||
if (m.bRNDImage > 0) {
|
||
m.bRNDImage <= td->bReplacementCount ? td = &td->lpReplacements[m.bRNDImage - 1] : td = &td->lpReplacements[td->bReplacementCount - 1];
|
||
}
|
||
}
|
||
|
||
if (m.bSubTile < td->wTileCount && td->tiles[m.bSubTile].pic != NULL) {
|
||
const SUBTILE& st = td->tiles[m.bSubTile];
|
||
const auto stDrawCoords = drawCoords + st.drawOffset();
|
||
|
||
|
||
if (!m.bHide && (*tiledata)[dwOrigGround].bHide == FALSE) {
|
||
#ifndef NOSURFACES
|
||
Blit(st.pic, stDrawCoords.x, stDrawCoords.y, st.wWidth, st.wHeight);
|
||
#else
|
||
BlitTerrain(ddsd.lpSurface,
|
||
stDrawCoords.x, stDrawCoords.y,
|
||
r.left, r.top,
|
||
DDBoundary{ ddsd.dwWidth, ddsd.dwHeight, ddsd.lPitch },
|
||
r.right, r.bottom, st);
|
||
|
||
if (st.anim) {
|
||
const auto animDrawCoords = drawCoords + ProjectedVec(f_x / 2 - st.anim->wMaxWidth / 2, f_y / 2 - st.anim->wMaxHeight / 2) + st.anim->drawOffset();
|
||
BlitPic(ddsd.lpSurface, animDrawCoords.x, animDrawCoords.y, r.left, r.top, DDBoundary{ ddsd.dwWidth, ddsd.dwHeight, ddsd.lPitch }, r.right, r.bottom, *st.anim);
|
||
}
|
||
#endif
|
||
|
||
} else {
|
||
#ifndef NOSURFACES // draw soemthing representing the tile
|
||
DrawCell(stDrawCoords.x, stDrawCoords.y, 1, 1, RGB(0, 140, 0), FALSE, FALSE);
|
||
#else
|
||
BlitTerrainHalfTransp(ddsd.lpSurface, stDrawCoords.x, stDrawCoords.y, r.left, r.top, DDBoundary{ ddsd.dwWidth, ddsd.dwHeight, ddsd.lPitch }, r.right, r.bottom, st);
|
||
#endif
|
||
|
||
}
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
// draw terrain animation (tunnel tops, waterfalls)
|
||
// tunnel tops might be repainted later so that units do not appear on top - this probably could be done in CLoading so that instead of a back tile a front tile is responsible for drawing the animation
|
||
{
|
||
if (m.wGround < *tiledata_count) {
|
||
TILEDATA* td = &(*tiledata)[m.wGround];
|
||
|
||
if (m.bSubTile < td->wTileCount) {
|
||
const SUBTILE& st = td->tiles[m.bSubTile];
|
||
|
||
if (!m.bHide && (*tiledata)[dwOrigGround].bHide == FALSE && st.anim) {
|
||
#ifndef NOSURFACES
|
||
#else
|
||
const auto animDrawCoords = drawCoords + ProjectedVec(f_x / 2 - st.anim->wMaxWidth / 2, f_y / 2 - st.anim->wMaxHeight / 2) + st.anim->drawOffset();
|
||
BlitPic(ddsd.lpSurface, animDrawCoords.x, animDrawCoords.y, r.left, r.top, DDBoundary{ ddsd.dwWidth, ddsd.dwHeight, ddsd.lPitch }, r.right, r.bottom, *st.anim);
|
||
#endif
|
||
}
|
||
|
||
}
|
||
}
|
||
}
|
||
|
||
// draw overlay
|
||
if (m.overlay != 0xFF) {
|
||
PICDATA pic;
|
||
pic.pic = NULL;
|
||
|
||
if (ovrlpics[m.overlay][m.overlaydata] != NULL) {
|
||
pic = *ovrlpics[m.overlay][m.overlaydata];
|
||
}
|
||
|
||
|
||
if (pic.pic == NULL) {
|
||
if (!pic.bTried) {
|
||
auto const& overlayId = rules.GetSection("OverlayTypes").Nth(m.overlay).second;
|
||
if (!overlayId.IsEmpty()) {
|
||
SetError("Loading graphics");
|
||
theApp.m_loading->LoadOverlayGraphic(overlayId, m.overlay);
|
||
UpdateOverlayPictures(m.overlay);
|
||
if (ovrlpics[m.overlay][m.overlaydata] != NULL) {
|
||
pic = *ovrlpics[m.overlay][m.overlaydata];
|
||
}
|
||
}
|
||
}
|
||
|
||
if (pic.pic == NULL) {
|
||
if (!(m.overlay >= 0x4a && m.overlay <= 0x65) && !(m.overlay >= 0xcd && m.overlay <= 0xec)) {
|
||
char cd[50];
|
||
cd[0] = '0';
|
||
cd[1] = 'x';
|
||
itoa(m.overlay, cd + 2, 16);
|
||
|
||
m_texts_to_render.push_back({ cd, drawCoords.x + f_x / 2, drawCoords.y + f_y / 2, RGB(0,0,0), false, true, true });
|
||
// TextOut(drawx,drawy, cd, RGB(0,0,0));
|
||
}
|
||
}
|
||
}
|
||
|
||
if (pic.pic != NULL) {
|
||
ProjectedVec offset(f_x / 2 - pic.wMaxWidth / 2, -pic.wMaxHeight / 2);
|
||
|
||
if (m.overlay == OVRL_VEINHOLE) // veinhole, big, special case
|
||
{
|
||
offset.y -= f_y * 3 / 2;
|
||
} else if (isBigBridge(m.overlay)) // bridge special case
|
||
{
|
||
// drawy-=f_y;
|
||
if (m.overlaydata >= 0x09 && m.overlaydata <= 0x11) {
|
||
offset.y -= f_y / 2;
|
||
}
|
||
|
||
offset.x -= 1; // hmm... strange, but this is needed
|
||
|
||
} else if (isTrack(m.overlay))
|
||
offset.y += f_y / 2;
|
||
|
||
if (m.overlay >= 0x4a && m.overlay <= 0x65) {
|
||
offset.y += f_y / 2;
|
||
}
|
||
if (m.overlay >= 0xcd && m.overlay <= 0xec) {
|
||
offset.y += f_y / 2;
|
||
}
|
||
|
||
const auto drawCoordsOvrl = drawCoords + offset;
|
||
|
||
#ifndef NOSURFACES
|
||
Blit(pic.pic, drawCoordsOvrl.x, drawCoordsOvrl.y);
|
||
#else
|
||
|
||
#ifdef RA2_MODE
|
||
BlitPic(ddsd.lpSurface, drawCoordsOvrl.x, drawCoordsOvrl.y, r.left, r.top, DDBoundary{ ddsd.dwWidth, ddsd.dwHeight, ddsd.lPitch }, r.right, r.bottom, pic);
|
||
#endif
|
||
#ifdef TS_MODE
|
||
if (!isGreenTiberium(m.overlay) && !(m.overlay == 0x7f)) // no tib
|
||
BlitPic(ddsd.lpSurface, drawCoordsOvrl.x, drawCoordsOvrl.y, r.left, r.top, ddsd.lPitch, r.right, r.bottom, pic);
|
||
else if (m.overlay == 0x7f) // blue tib
|
||
{
|
||
int n = RGB(200, 0, 0);
|
||
BlitPic(ddsd.lpSurface, drawCoordsOvrl.x, drawCoordsOvrl.y, r.left, r.top, ddsd.lPitch, r.right, r.bottom, pic, &n);
|
||
} else {
|
||
int n = RGB(0, 200, 0);
|
||
BlitPic(ddsd.lpSurface, drawCoordsOvrl.x, drawCoordsOvrl.y, r.left, r.top, ddsd.lPitch, r.right, r.bottom, pic, &n);
|
||
}
|
||
#endif
|
||
|
||
#endif
|
||
|
||
}
|
||
}
|
||
|
||
if (m.structure != -1) {
|
||
last_succeeded_operation = 10101;
|
||
|
||
// for structures we need to check if they weren´t drawn earlier
|
||
// (every field that this building achieves has this building as .structure)
|
||
auto const leftStructureIdx = Map->GetStructureAt(mapCoords - MapVec(-1, 0));
|
||
auto const rightStructureIdx = Map->GetStructureAt(mapCoords - MapVec(0, -1));
|
||
bool shouldDraw = true;
|
||
|
||
if (leftStructureIdx == m.structure || rightStructureIdx == m.structure) {
|
||
shouldDraw = false;
|
||
}
|
||
if (mapCoords.x >= Map->GetWidth() || mapCoords.y >= Map->GetHeight()) {
|
||
shouldDraw = true;
|
||
}
|
||
|
||
if (shouldDraw) {
|
||
|
||
STRUCTUREPAINT objp;
|
||
Map->GetStructurePaint(m.structure, &objp);
|
||
|
||
const auto drawCoordsBld = GetRenderTargetCoordinates(MapCoords(objp.x, objp.y));
|
||
int id = m.structuretype;
|
||
|
||
|
||
int w = 1, h = 1;
|
||
PICDATA pic;
|
||
if (id > -1 && id < buildingInfoCapacity) {
|
||
w = buildinginfo[id].w;
|
||
h = buildinginfo[id].h;
|
||
int dir = objp.direction / 32;
|
||
|
||
// MW April 13th 2001: fix for building direction
|
||
dir = (7 - dir) % 8;
|
||
|
||
pic = buildinginfo[id].pic[dir];
|
||
if (pic.pic == NULL) {
|
||
pic = buildinginfo[id].pic[0];
|
||
}
|
||
}
|
||
|
||
#ifndef NOSURFACES
|
||
DrawCell(drawCoordsBld.x, drawCoordsBld.y, w, h, colorref_conv[objp.col]);
|
||
#else
|
||
// MW 07/19/01: Paint cell if user chose so...
|
||
if (theApp.m_Options.bShowCells) {
|
||
DrawCell(ddsd.lpSurface, ddsd.dwWidth, ddsd.dwHeight, ddsd.lPitch, drawCoordsBld.x, drawCoordsBld.y, w, h, colorref_conv[objp.col]);
|
||
}
|
||
#endif
|
||
if (pic.pic == NULL) {
|
||
if (!missingimages[objp.type]) {
|
||
SetError("Loading graphics");
|
||
theApp.m_loading->LoadUnitGraphic(objp.type);
|
||
::Map->UpdateBuildingInfo(&objp.type);
|
||
int dir = (7 - objp.direction / 32) % 8;
|
||
pic = buildinginfo[id].pic[dir];
|
||
if (pic.pic == NULL) {
|
||
pic = buildinginfo[id].pic[0];
|
||
}
|
||
}
|
||
if (pic.pic == NULL) {
|
||
#ifndef NOSURFACES
|
||
Blit(pics["HOUSE"].pic, drawCoordsBld.x, drawCoordsBld.y - 19); // draw a ugly house
|
||
#endif
|
||
missingimages[objp.type] = TRUE;
|
||
}
|
||
}
|
||
|
||
if (pic.pic) // picture
|
||
{
|
||
|
||
// it was that easy! just center on top end!!!
|
||
const auto drawCoordsBldShp = drawCoordsBld + ProjectedVec(f_x / 2 - pic.wMaxWidth / 2, -pic.wMaxHeight / 2);
|
||
|
||
#ifndef NOSURFACES
|
||
Blit(pic.pic, drawCoordsBldShp.x, drawCoordsBldShp.y, pic.wMaxWidth, pic.wMaxHeight);
|
||
#else
|
||
|
||
BlitPic(ddsd.lpSurface, drawCoordsBldShp.x, drawCoordsBldShp.y, r.left, r.top, DDBoundary{ ddsd.dwWidth, ddsd.dwHeight, ddsd.lPitch }, r.right, r.bottom, pic, &colorref_conv[objp.col]);
|
||
#endif
|
||
|
||
for (int upgrade = 0; upgrade < objp.upradecount; ++upgrade) {
|
||
const auto& upg = upgrade == 0 ? objp.upgrade1 : (upgrade == 1 ? objp.upgrade2 : objp.upgrade3);
|
||
if (upg.GetLength() == 0) {
|
||
continue;
|
||
}
|
||
|
||
PICDATA pic;
|
||
int dir = 0;
|
||
if (rules.GetBool(upg, "Turret")) {
|
||
dir = (7 - objp.direction / 32) % 8;
|
||
}
|
||
auto const picName = GetUnitPictureFilename(upg, dir);
|
||
|
||
if (!picName.IsEmpty()) {
|
||
pic = pics[picName];
|
||
}
|
||
|
||
if (pic.pic == NULL && !missingimages[upg]) {
|
||
SetError("Loading graphics");
|
||
theApp.m_loading->LoadUnitGraphic(upg);
|
||
::Map->UpdateBuildingInfo(&upg);
|
||
auto picNameAfterLoad = GetUnitPictureFilename(upg, dir);
|
||
if (picNameAfterLoad.IsEmpty()) {
|
||
picNameAfterLoad = GetUnitPictureFilename(upg, 0);
|
||
}
|
||
if (!picNameAfterLoad.IsEmpty()) {
|
||
pic = pics[picNameAfterLoad];
|
||
}
|
||
if (pic.pic == NULL) {
|
||
missingimages[upg] = TRUE;
|
||
}
|
||
}
|
||
|
||
if (pic.pic != NULL) {
|
||
static const CString LocLookup[3][2] = { {"PowerUp1LocXX", "PowerUp1LocYY"}, {"PowerUp2LocXX", "PowerUp2LocYY"}, {"PowerUp3LocXX", "PowerUp3LocYY"} };
|
||
const auto drawCoordsPowerUp = drawCoordsBld + ProjectedVec(f_x / 2 - pic.wMaxWidth / 2, -pic.wMaxHeight / 2) + ProjectedVec(
|
||
atoi(art.GetString(objp.type, LocLookup[upgrade][0])),
|
||
atoi(art.GetString(objp.type, LocLookup[upgrade][1]))
|
||
);
|
||
// py-=atoi(art.sections[obj.type].values["PowerUp1LocZZ"]);
|
||
#ifndef NOSURFACES
|
||
Blit(pic.pic, drawCoordsPowerUp.x, drawCoordsPowerUp.y);
|
||
#else
|
||
BlitPic(ddsd.lpSurface, drawCoordsPowerUp.x, drawCoordsPowerUp.y, r.left, r.top, DDBoundary{ ddsd.dwWidth, ddsd.dwHeight, ddsd.lPitch }, r.right, r.bottom, pic, &colorref_conv[objp.col]);
|
||
#endif
|
||
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
|
||
if (m.node.type >= 0) {
|
||
last_succeeded_operation = 10102;
|
||
|
||
CString house = m.node.house;
|
||
CString tmp;
|
||
|
||
bool shouldDraw = true;
|
||
auto const leftNodeIdx = Map->GetNodeAt(mapCoords + MapVec(-1, 0), tmp);
|
||
auto const rightNodeIdx = Map->GetNodeAt(mapCoords + MapVec(0, -1), tmp);
|
||
if (leftNodeIdx == m.node.index || rightNodeIdx == m.node.index) {
|
||
shouldDraw = false;
|
||
}
|
||
|
||
if (shouldDraw) {
|
||
const auto drawCoordsBld = GetRenderTargetCoordinates(mapCoords);
|
||
|
||
COLORREF c;
|
||
c = GetColor(house);
|
||
|
||
|
||
int id = m.node.type;
|
||
int w = 1, h = 1;
|
||
PICDATA pic;
|
||
if (id > -1 && id < buildingInfoCapacity) {
|
||
w = buildinginfo[id].w;
|
||
h = buildinginfo[id].h;
|
||
pic = buildinginfo[id].pic[0];
|
||
}
|
||
|
||
|
||
//#ifndef NOSURFACES
|
||
#ifdef NOSURFACES
|
||
if (m.structure >= 0) // only paint cell if we have a structure preplaced, as we have a half transparent image
|
||
{
|
||
#endif
|
||
// place it 2 pixels lower so that user can see the dotted lines even if the building itself has the cells drawn
|
||
DrawCell(ddsd.lpSurface, ddsd.dwWidth, ddsd.dwHeight, ddsd.lPitch, drawCoordsBld.x, drawCoordsBld.y + 3, w, h, colorref_conv[c], true);
|
||
|
||
#ifdef NOSURFACES
|
||
}
|
||
#endif
|
||
//#endif
|
||
|
||
if (pic.pic == NULL) {
|
||
auto const& buildingId = rules.GetSection("BuildingTypes").Nth(m.node.type).second;
|
||
if (!buildingId.IsEmpty() && !missingimages[buildingId]) {
|
||
SetError("Loading graphics");
|
||
theApp.m_loading->LoadUnitGraphic(buildingId);
|
||
::Map->UpdateBuildingInfo(&buildingId);
|
||
|
||
pic = buildinginfo[id].pic[0];
|
||
}
|
||
if (pic.pic == NULL) {
|
||
#ifndef NOSURFACES
|
||
Blit(pics["HOUSE"].pic, drawCoordsBld.x, drawCoordsBld.y - 19);
|
||
#endif
|
||
missingimages[buildingId] = TRUE;
|
||
}
|
||
}
|
||
|
||
|
||
if (pic.pic) // picture
|
||
{
|
||
const auto drawCoordsBldShp = drawCoordsBld + ProjectedVec(f_x / 2 - pic.wMaxWidth / 2, -pic.wMaxHeight / 2);
|
||
|
||
#ifndef NOSURFACES
|
||
Blit(pic.pic, drawCoordsBldShp.x, drawCoordsBldShp.y);
|
||
#else
|
||
BlitPicHalfTransp(ddsd.lpSurface, drawCoordsBldShp.x, drawCoordsBldShp.y,
|
||
r.left, r.top,
|
||
DDBoundary{ ddsd.dwWidth, ddsd.dwHeight, ddsd.lPitch },
|
||
r.right, r.bottom, pic, &colorref_conv[c]);
|
||
#endif
|
||
}
|
||
}
|
||
}
|
||
if (m.unit != -1) {
|
||
|
||
UNIT obj;
|
||
Map->GetUnitData(m.unit, &obj);
|
||
|
||
COLORREF c = GetColor(obj.house);
|
||
|
||
auto const facing = atoi(obj.direction) / 32;
|
||
auto const imageId = theApp.m_loading->GetArtID(obj.type);
|
||
CString lpPicFile = GetUnitPictureFilename(imageId, facing);
|
||
|
||
#ifndef NOSURFACES
|
||
DrawCell(drawCoords.x, drawCoords.y, 1, 1, c);
|
||
#endif
|
||
PICDATA p;
|
||
if (!lpPicFile.IsEmpty()) {
|
||
p = pics[lpPicFile];
|
||
}
|
||
|
||
if (p.pic == NULL || lpPicFile.GetLength() == 0) {
|
||
if (!missingimages[obj.type]) {
|
||
SetError("Loading graphics");
|
||
theApp.m_loading->LoadUnitGraphic(obj.type);
|
||
lpPicFile = GetUnitPictureFilename(imageId, facing);
|
||
if (!lpPicFile.IsEmpty()) {
|
||
p = pics[lpPicFile];
|
||
}
|
||
}
|
||
|
||
if (p.pic == NULL) {
|
||
#ifndef NOSURFACES
|
||
Blit(pics["TANK"].pic, drawCoords.x, drawCoords.y);
|
||
// TextOut(drawx+f_x/4,drawy+f_y/4, obj.type,c);
|
||
m_texts_to_render.push_back({ obj.type, drawCoords.x + f_x / 4, drawCoords.y + f_y / 4, m_color_converter->GetColor(c) });
|
||
#endif
|
||
missingimages[obj.type] = TRUE;
|
||
}
|
||
}
|
||
|
||
if (p.pic)// we have a picture!
|
||
{
|
||
const auto drawCoordsOffset = (p.bType == PICDATA_TYPE_BMP) ? ProjectedVec((f_y / 4) + p.x, (f_y - p.wHeight) + p.y) - p.drawOffset() :
|
||
(p.bType == PICDATA_TYPE_SHP) ? ProjectedVec(f_x / 2 - (p.wMaxWidth / 2), f_y / 2 - (p.wMaxHeight / 2)) : ProjectedVec(f_x / 2, f_y / 2) + p.drawOffset();
|
||
auto drawCoordsUnit = drawCoords + drawCoordsOffset;
|
||
|
||
#ifndef NOSURFACES
|
||
Blit(p.pic, drawCoordsUnit.x, drawCoordsUnit.y);
|
||
#else
|
||
BlitPic(ddsd.lpSurface, drawCoordsUnit.x, drawCoordsUnit.y, r.left, r.top, DDBoundary{ ddsd.dwWidth, ddsd.dwHeight, ddsd.lPitch }, r.right, r.bottom, p, &colorref_conv[c]);
|
||
#endif
|
||
}
|
||
}
|
||
if (m.aircraft != -1) {
|
||
last_succeeded_operation = 10102;
|
||
|
||
AIRCRAFT obj;
|
||
Map->GetAircraftData(m.aircraft, &obj);
|
||
|
||
COLORREF c = GetColor(obj.house);
|
||
|
||
auto const facing = atoi(obj.direction) / 32;
|
||
CString lpPicFile = GetUnitPictureFilename(theApp.m_loading->GetArtID(obj.type), facing);
|
||
|
||
#ifndef NOSURFACES
|
||
DrawCell(drawCoords.x, drawCoords.y, 1, 1, c);
|
||
#endif
|
||
PICDATA p;
|
||
if (!lpPicFile.IsEmpty()) {
|
||
p = pics[lpPicFile];
|
||
}
|
||
|
||
if (p.pic == NULL) {
|
||
if (!missingimages[obj.type]) {
|
||
SetError("Loading graphics");
|
||
theApp.m_loading->LoadUnitGraphic(obj.type);
|
||
lpPicFile = GetUnitPictureFilename(theApp.m_loading->GetArtID(obj.type), facing);
|
||
if (!lpPicFile.IsEmpty()) {
|
||
p = pics[lpPicFile];
|
||
}
|
||
}
|
||
|
||
if (p.pic == NULL) {
|
||
#ifndef NOSURFACES
|
||
Blit(pics["TANK"].pic, drawCoords.x, drawCoords.y);
|
||
//TextOut(drawx+f_x/4,drawy+f_y/4, obj.type,c);
|
||
m_texts_to_render.push_back({ obj.type, drawCoords.x + f_x / 4, drawCoords.y + f_y / 4, m_color_converter->GetColor(c) });
|
||
#endif
|
||
missingimages[obj.type] = TRUE;
|
||
}
|
||
}
|
||
|
||
if (p.pic)// we have a picture!
|
||
{
|
||
const auto drawCoordsOffset = (p.bType == PICDATA_TYPE_BMP) ? ProjectedVec(f_x / 2 - p.wWidth / 2, f_y - p.wHeight) - p.drawOffset() :
|
||
(p.bType == PICDATA_TYPE_SHP) ? ProjectedVec(f_x / 2 - (p.wMaxWidth / 2), f_y / 2 - (p.wMaxHeight / 2)) : ProjectedVec(f_x / 2, f_y / 2) + p.drawOffset();
|
||
auto drawCoordsAir = drawCoords + drawCoordsOffset;
|
||
|
||
#ifndef NOSURFACES
|
||
Blit(p.pic, drawCoordsAir.x, drawCoordsAir.y);
|
||
#else
|
||
BlitPic(ddsd.lpSurface, drawCoordsAir.x, drawCoordsAir.y, r.left, r.top, DDBoundary{ ddsd.dwWidth, ddsd.dwHeight, ddsd.lPitch }, r.right, r.bottom, p, &colorref_conv[c]);
|
||
#endif
|
||
}
|
||
}
|
||
int ic;
|
||
for (ic = 0; ic < SUBPOS_COUNT; ic++) {
|
||
if (m.infantry[ic] != -1) {
|
||
last_succeeded_operation = 10103;
|
||
|
||
//errstream << "GetInfantryData()" << endl;
|
||
//errstream.flush();
|
||
|
||
INFANTRY obj;
|
||
Map->GetInfantryData(m.infantry[ic], &obj);
|
||
|
||
//errstream << "Done " << (LPCSTR)obj.type << endl;
|
||
//errstream.flush();
|
||
|
||
|
||
COLORREF c = GetColor(obj.house);
|
||
|
||
int dir = (7 - atoi(obj.direction) / 32) % 8;
|
||
|
||
auto const imageId = theApp.m_loading->GetArtID(obj.type);
|
||
CString lpPicFile = GetUnitPictureFilename(imageId, dir);
|
||
#ifndef NOSURFACES
|
||
DrawCell(drawCoords.x, drawCoords.y, 1, 1, c);
|
||
#endif
|
||
|
||
static const ProjectedVec subPosLookup[5] = { ProjectedVec(0, -f_y / 4), ProjectedVec(f_x / 4 , 0), ProjectedVec(-f_x / 4, 0), ProjectedVec(0, f_y / 4), ProjectedVec() };
|
||
auto drawCoordsInf = drawCoords + subPosLookup[ic > 4 ? 4 : ic];
|
||
|
||
PICDATA p;
|
||
|
||
if (!lpPicFile.IsEmpty()) {
|
||
p = pics[lpPicFile];
|
||
}
|
||
|
||
if (p.pic == NULL) {
|
||
if (!missingimages[obj.type]) {
|
||
SetError("Loading graphics");
|
||
theApp.m_loading->LoadUnitGraphic(obj.type);
|
||
lpPicFile = GetUnitPictureFilename(imageId, dir);
|
||
if (!lpPicFile.IsEmpty()) {
|
||
p = pics[lpPicFile];
|
||
}
|
||
}
|
||
|
||
if (p.pic == NULL) {
|
||
#ifndef NOSURFACES
|
||
Blit(pics["MAN"].pic, drawCoordsInf.x, drawCoordsInf.y);
|
||
// TextOut(drawx+f_x/4,drawy+f_y/4, obj.type,c);
|
||
m_texts_to_render.push_back({ obj.type, drawCoordsInf.x + f_x / 4, drawCoordsInf.y + f_y / 4, RGB(0,0,0) });
|
||
#endif
|
||
missingimages[obj.type] = TRUE;
|
||
}
|
||
}
|
||
|
||
|
||
|
||
if (p.pic)// we have a picture!
|
||
{
|
||
auto drawCoordsInfShp = drawCoordsInf + ProjectedVec(f_x / 2 - (p.wMaxWidth / 2), f_y / 2 - (p.wMaxHeight / 2));
|
||
|
||
#ifndef NOSURFACES
|
||
Blit(p.pic, drawCoordsInfShp.x, drawCoordsInfShp.y, p.wWidth, p.wHeight);
|
||
#else
|
||
BlitPic(ddsd.lpSurface, drawCoordsInfShp.x, drawCoordsInfShp.y, r.left, r.top, DDBoundary{ ddsd.dwWidth, ddsd.dwHeight, ddsd.lPitch }, r.right, r.bottom, p, &colorref_conv[c]);
|
||
#endif
|
||
|
||
}
|
||
|
||
}
|
||
}
|
||
if (m.terrain != -1) {
|
||
last_succeeded_operation = 10104;
|
||
|
||
|
||
int id = m.terraintype;
|
||
int w = 1, h = 1;
|
||
PICDATA pic;
|
||
if (id > -1 && id < buildingInfoCapacity) {
|
||
w = treeinfo[id].w;
|
||
h = treeinfo[id].h;
|
||
pic = treeinfo[id].pic;
|
||
}
|
||
|
||
//CString lpPicFile=GetUnitPictureFilename(type, 0);
|
||
|
||
if (pic.pic == NULL) {
|
||
CString type;
|
||
Map->GetTerrainData(m.terrain, &type);
|
||
|
||
if (missingimages.find(type) == missingimages.end()) {
|
||
SetError("Loading graphics");
|
||
theApp.m_loading->LoadUnitGraphic(type);
|
||
::Map->UpdateTreeInfo(&type);
|
||
pic = treeinfo[id].pic;
|
||
}
|
||
if (pic.pic == NULL) {
|
||
#ifndef NOSURFACES
|
||
Blit(pics["TREE"].pic, drawCoords.x, drawCoords.y - 19);
|
||
#endif
|
||
missingimages[type] = TRUE;
|
||
}
|
||
}
|
||
|
||
if (pic.pic) {
|
||
|
||
auto drawCoordsTerrain = drawCoords + ProjectedVec(f_x / 2 - (pic.wMaxWidth / 2), f_y / 2 - 3 - (pic.wMaxHeight / 2));
|
||
|
||
#ifndef NOSURFACES
|
||
Blit(pic.pic, drawCoordsTerrain.x, drawCoordsTerrain.y);
|
||
#else
|
||
BlitPic(ddsd.lpSurface, drawCoordsTerrain.x, drawCoordsTerrain.y, r.left, r.top, DDBoundary{ ddsd.dwWidth, ddsd.dwHeight, ddsd.lPitch }, r.right, r.bottom, pic);
|
||
|
||
#endif
|
||
|
||
|
||
}
|
||
|
||
}
|
||
|
||
|
||
#ifdef SMUDGE_SUPP
|
||
if (m.smudge != -1) {
|
||
last_succeeded_operation = 10104;
|
||
|
||
|
||
int id = m.smudgetype;
|
||
|
||
PICDATA pic;
|
||
if (id > -1 && id < buildingInfoCapacity) {
|
||
pic = smudgeinfo[id].pic;
|
||
}
|
||
|
||
if (pic.pic == NULL) {
|
||
SMUDGE data;
|
||
CString& type = data.type;
|
||
Map->GetSmudgeData(m.smudge, &data);
|
||
|
||
if (missingimages.find(type) == missingimages.end()) {
|
||
SetError("Loading graphics");
|
||
theApp.m_loading->LoadUnitGraphic(type);
|
||
::Map->UpdateSmudgeInfo(type);
|
||
pic = smudgeinfo[id].pic;
|
||
}
|
||
if (pic.pic == NULL) {
|
||
#ifndef NOSURFACES
|
||
// Blit(pics["TREE"].pic,drawCoords.x,drawCoords.y-19);
|
||
#endif
|
||
missingimages[type] = TRUE;
|
||
}
|
||
}
|
||
|
||
if (pic.pic) {
|
||
auto drawCoordsSmudge = drawCoords + ProjectedVec(f_x / 2 - (pic.wMaxWidth / 2), /*f_y / 2 - 3*/ -(pic.wMaxHeight / 2));
|
||
|
||
#ifndef NOSURFACES
|
||
Blit(pic.pic, drawCoordsSmudge.x, drawCoordsSmudge.y);
|
||
#else
|
||
BlitPic(ddsd.lpSurface, drawCoordsSmudge.x, drawCoordsSmudge.y, r.left, r.top, DDBoundary{ ddsd.dwWidth, ddsd.dwHeight, ddsd.lPitch }, r.right, r.bottom, pic);
|
||
|
||
#endif
|
||
|
||
|
||
}
|
||
|
||
}
|
||
#endif
|
||
|
||
|
||
if (m.celltag != -1) {
|
||
|
||
#ifdef NOSURFACES
|
||
lpdsBack->Unlock(NULL);
|
||
#endif
|
||
Blit((LPDIRECTDRAWSURFACE4)pics["CELLTAG"].pic, drawCoords.x - 1, drawCoords.y - 1);
|
||
|
||
#ifdef NOSURFACES
|
||
lpdsBack->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT | DDLOCK_NOSYSLOCK, NULL);
|
||
#endif
|
||
}
|
||
|
||
if (m.waypoint != -1) {
|
||
|
||
DWORD dwPos;
|
||
CString ID;
|
||
Map->GetWaypointData(m.waypoint, &ID, &dwPos);
|
||
|
||
|
||
#ifdef NOSURFACES
|
||
lpdsBack->Unlock(NULL);
|
||
#endif
|
||
|
||
// move the graphic and text into place
|
||
#ifdef RA2_MODE
|
||
int image_fudge_x = 4;
|
||
int image_fudge_y = -20;
|
||
int text_fudge_x = 12;
|
||
int text_fudge_y = -24;
|
||
#else
|
||
int image_fudge_x = 4;
|
||
int image_fudge_y = -15;
|
||
int text_fudge_x = 9;
|
||
int text_fudge_y = -17;
|
||
#endif
|
||
|
||
const ProjectedVec waypointImageOffset(image_fudge_x, image_fudge_y);
|
||
const ProjectedVec waypointTextOffset((f_x / 2) + text_fudge_x, (f_y / 2) + text_fudge_y);
|
||
#ifdef RA2_MODE
|
||
bool useFont9 = false;
|
||
#else
|
||
bool useFont9 = true;
|
||
#endif
|
||
const auto waypointImageCoords = ProjectedCoords({ drawCoords.x, drawCoords.y }) + waypointImageOffset;
|
||
const auto waypointTextCoords = ProjectedCoords({ drawCoords.x, drawCoords.y }) + waypointTextOffset;
|
||
m_waypoints_to_render.push_back({ waypointImageCoords.x, waypointImageCoords.y });
|
||
m_texts_to_render.push_back({ ID.GetString(), waypointTextCoords.x, waypointTextCoords.y, RGB(0,0,255), false, useFont9, true });
|
||
#ifdef NOSURFACES
|
||
lpdsBack->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT | DDLOCK_NOSYSLOCK, NULL);
|
||
#endif
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
|
||
for (const auto& tube : Map->GetTubes()) {
|
||
DrawTube(*tube, &ddsd);
|
||
}
|
||
|
||
#ifdef NOSURFACES
|
||
lpdsBack->Unlock(NULL);
|
||
#endif
|
||
|
||
// delayed waypoint rendering
|
||
for (const auto& wp : m_waypoints_to_render) {
|
||
Blit((LPDIRECTDRAWSURFACE4)pics["FLAG"].pic, wp.drawx, wp.drawy);
|
||
}
|
||
|
||
// map tool rendering
|
||
if (AD.mode == ACTIONMODE_MAPTOOL) {
|
||
if (AD.tool)
|
||
AD.tool->render();
|
||
}
|
||
|
||
lpdsTemp->Blt(NULL, lpdsBack, NULL, 0, 0); // lpdsTemp always holds the scene drawn above, unscaled to the window
|
||
|
||
if (m_cellCursor != MapCoords(-1, -1)) {
|
||
SurfaceLocker locker(lpdsBack);
|
||
auto desc = locker.ensure_locked();
|
||
if (desc)
|
||
DrawCellCursor(m_cellCursor, *desc);
|
||
}
|
||
|
||
auto renderDuration = std::chrono::duration_cast<std::chrono::duration<float>>(std::chrono::steady_clock::now() - startTime); // not including text output, ReleaseDC, waitForVerticalBlank etc below
|
||
|
||
if (bDrawStats) {
|
||
if (theApp.m_Options.bShowStats) {
|
||
auto systemStats = std::format("ms: {0} Left: {1} Top: {2} Right: {3} Bottom: {4}", renderDuration.count(), left, top, right, bottom);
|
||
m_texts_to_render.push_back({ systemStats.c_str(), r.left + 10, r.top + 10 + (-m_fontDefaultHeight) * 3 / 2, RGB(0,0,0), true });
|
||
}
|
||
|
||
auto moneyStr = std::format("Credits on map: {0}", Map->GetMoneyOnMap());
|
||
m_texts_to_render.push_back({ moneyStr.c_str(), r.left + 10, r.top + 10, RGB(0,0,0), true });
|
||
}
|
||
|
||
if (rscroll) {
|
||
const auto& sc = pics["SCROLLCURSOR"];
|
||
Blit((LPDIRECTDRAWSURFACE4)sc.pic, rclick_x * m_viewScale.x + r.left - sc.wWidth / 2, rclick_y * m_viewScale.y + r.top - sc.wHeight / 2);
|
||
}
|
||
|
||
BlitBackbufferToHighRes(); // lpdsBackHighRes contains the same graphic, but scaled to the whole window
|
||
|
||
RenderUIOverlay();
|
||
if (theApp.m_Options.bVSync)
|
||
dd->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, NULL);
|
||
FlipHighResBuffer();
|
||
last_succeeded_operation = 10100;
|
||
|
||
}
|
||
|
||
std::tuple<DDSURFACEDESC2, LPDIRECTDRAWSURFACE4, bool> CIsoView::getDDDesc(bool recreated)
|
||
{
|
||
LPDIRECTDRAWSURFACE4 dds = lpdsBack;
|
||
bool useHighRes = false;
|
||
if (m_viewScale != Vec2<CSProjected, float>(1.0f, 1.0f) && lpdsBackHighRes) {
|
||
dds = lpdsBackHighRes;
|
||
useHighRes = true;
|
||
}
|
||
|
||
DDSURFACEDESC2 ddsd;
|
||
ZeroMemory(&ddsd, sizeof(ddsd));
|
||
ddsd.dwSize = sizeof(DDSURFACEDESC2);
|
||
ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
|
||
|
||
dds->GetSurfaceDesc(&ddsd);
|
||
|
||
auto const lockRet = dds->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT | DDLOCK_NOSYSLOCK, NULL);
|
||
|
||
if (lockRet == DDERR_SURFACELOST && !recreated) {
|
||
ReInitializeDDraw();
|
||
return getDDDesc(true);
|
||
}
|
||
|
||
ASSERT(lockRet == S_OK);
|
||
ASSERT(ddsd.lpSurface != nullptr);
|
||
|
||
return { ddsd, dds, useHighRes };
|
||
}
|
||
|
||
void CIsoView::RenderUIOverlay()
|
||
{
|
||
if (!m_textDefault) {
|
||
updateFontScaled();
|
||
}
|
||
|
||
auto const [ddsd, dds, useHighRes] = getDDDesc(false);
|
||
|
||
LineDrawer d(ddsd.lpSurface, bpp, ddsd.dwWidth, ddsd.dwHeight, ddsd.lPitch);
|
||
|
||
int lr, lt, ll, lb;
|
||
|
||
ll = Map->GetWidth();
|
||
lt = 1;
|
||
lr = Map->GetHeight();
|
||
lb = Map->GetIsoSize() - 1;
|
||
|
||
int h_lefttop = 0;//Map->GetHeightAt(ll+lt*Map->GetIsoSize());
|
||
int h_leftbottom = 0;//Map->GetHeightAt(lr+lb*Map->GetIsoSize());
|
||
|
||
ToPhys((int*)&ll, (int*)<);
|
||
ToPhys((int*)&lr, (int*)&lb);
|
||
ll -= m_viewOffset.x - f_x / 2;
|
||
lt -= m_viewOffset.y - f_y / 2;
|
||
lr -= m_viewOffset.x - f_x / 2;
|
||
lb -= m_viewOffset.y - f_y / 2;
|
||
|
||
lt -= h_lefttop * f_y / 2;
|
||
lb -= h_leftbottom * f_y / 2;
|
||
|
||
auto sllt = useHighRes ? ScaleBackToFrontBuffer(ProjectedCoords(ll, lt)) : ProjectedCoords(ll, lt);
|
||
auto slbr = useHighRes ? ScaleBackToFrontBuffer(ProjectedCoords(lr, lb)) : ProjectedCoords(lr, lb);
|
||
|
||
RECT ls;
|
||
Map->GetLocalSize(&ls);
|
||
ProjectedCoords l_lt(
|
||
ll + ls.left * f_x - f_x / 2,
|
||
lt + (ls.top - 4) * f_y
|
||
);
|
||
ProjectedCoords l_br(
|
||
ll + ls.left * f_x + ls.right * f_x - f_x / 2,
|
||
lt + (ls.top - 4 + 4) * f_y + ls.bottom * f_y
|
||
);
|
||
auto ls_lt = useHighRes ? ScaleBackToFrontBuffer(l_lt) : l_lt;
|
||
auto ls_br = useHighRes ? ScaleBackToFrontBuffer(l_br) : l_br;
|
||
|
||
auto red = m_color_converter->GetColor(255, 0, 0);
|
||
auto blue = m_color_converter->GetColor(0, 0, 255);
|
||
d.Rectangle(sllt.x, sllt.y, slbr.x, slbr.y, red);
|
||
d.Rectangle(sllt.x - 1, sllt.y - 1, slbr.x + 1, slbr.y + 1, red);
|
||
d.Rectangle(ls_lt.x, ls_lt.y, ls_br.x, ls_br.y, blue);
|
||
d.Rectangle(ls_lt.x + 1, ls_lt.y + 1, ls_br.x - 1, ls_br.y - 1, blue);
|
||
|
||
dds->Unlock(NULL);
|
||
|
||
RECT r;
|
||
GetWindowRect(&r);
|
||
|
||
for (const auto& s : m_texts_to_render) {
|
||
const bool blue = s.color == RGB(0, 0, 255); // TODO: TextRenderer should support setting the color at render time
|
||
if (s.fixedScreenPos || !useHighRes) {
|
||
auto textRenderer = s.useFont9 ? (blue ? *m_textBlue9 : *m_text9) : (blue ? *m_textBlue : *m_textDefault);
|
||
textRenderer.RenderText(dds, s.drawx, s.drawy, s.text, s.centered);
|
||
} else {
|
||
auto textRenderer = s.useFont9 ? (blue ? *m_textBlue9Scaled : *m_text9Scaled) : (blue ? *m_textBlueScaled : *m_textScaled);
|
||
textRenderer.RenderText(dds, r.left + (s.drawx - r.left) / m_viewScale.x, r.top + (s.drawy - r.top) / m_viewScale.y, s.text, s.centered);
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
void CIsoView::OnRButtonDown(UINT nFlags, CPoint point)
|
||
{
|
||
rclick_x = point.x;
|
||
rclick_y = point.y;
|
||
rscroll = FALSE;
|
||
|
||
CView::OnRButtonDown(nFlags, point);
|
||
}
|
||
|
||
void CIsoView::SetScroll(int xscroll, int yscroll)
|
||
{
|
||
RECT r;
|
||
GetWindowRect(&r);
|
||
|
||
m_viewOffset = ProjectedVec(xscroll, yscroll);
|
||
|
||
|
||
if (m_viewOffset.x < (Map->GetHeight() / 2 - 14 - r.left / f_x) * f_x)
|
||
m_viewOffset.x = (Map->GetHeight() / 2 - 14 - r.left / f_x) * f_x;
|
||
if (m_viewOffset.x + r.right * m_viewScale.x > (Map->GetHeight() / 2 + Map->GetWidth() + 14) * f_x)
|
||
m_viewOffset.x = (Map->GetHeight() / 2 + Map->GetWidth() + 14) * f_x - r.right * m_viewScale.x;
|
||
if (m_viewOffset.y < (Map->GetWidth() / 2 - 14 - r.top / f_y) * f_y)
|
||
m_viewOffset.y = (Map->GetWidth() / 2 - 14 - r.top / f_y) * f_y;
|
||
if (m_viewOffset.y + r.bottom * m_viewScale.y > (Map->GetWidth() / 2 + Map->GetHeight() + 4) * f_y)
|
||
m_viewOffset.y = (Map->GetWidth() / 2 + Map->GetHeight() + 4) * f_y - r.bottom * m_viewScale.y;
|
||
|
||
SetScrollPos(SB_VERT, (m_viewOffset.y / f_y - Map->GetWidth() / 2 + 4), TRUE);
|
||
SetScrollPos(SB_HORZ, (m_viewOffset.x / f_x - Map->GetHeight() / 2 + 1), TRUE);
|
||
|
||
}
|
||
|
||
RECT CIsoView::GetScaledDisplayRect() const
|
||
{
|
||
RECT r;
|
||
GetWindowRect(&r);
|
||
r.right = r.right - (r.right - r.left) * (1.0f - m_viewScale.x);
|
||
r.bottom = r.bottom - (r.bottom - r.top) * (1.0f - m_viewScale.y);
|
||
return r; // RVO
|
||
}
|
||
|
||
void CIsoView::GetScroll(int& xscroll, int& yscroll) const
|
||
{
|
||
xscroll = m_viewOffset.x;
|
||
yscroll = m_viewOffset.y;
|
||
}
|
||
|
||
void CIsoView::OnKillFocus(CWnd* pNewWnd)
|
||
{
|
||
CView::OnKillFocus(pNewWnd);
|
||
|
||
if (rscroll) {
|
||
errstream << "Killing scroll" << std::endl;
|
||
errstream.flush();
|
||
|
||
ReleaseCapture();
|
||
KillTimer(11);
|
||
ShowCursor(TRUE);
|
||
rscroll = FALSE;
|
||
bDoNotAllowScroll = TRUE;
|
||
}
|
||
|
||
}
|
||
|
||
// takes an index, not an waypoint id!
|
||
void CIsoView::FocusWaypoint(int index)
|
||
{
|
||
int x, y;
|
||
|
||
DWORD dwPos;
|
||
|
||
Map->GetNthWaypointData(index, NULL, &dwPos);
|
||
|
||
x = dwPos % Map->GetIsoSize();
|
||
y = dwPos / Map->GetIsoSize();
|
||
|
||
ToPhys3d(&x, &y);
|
||
|
||
RECT r;
|
||
GetWindowRect(&r);
|
||
|
||
auto pos = ProjectedVec((x - (r.right - r.left) / 2 * m_viewScale.x) - r.left, (y - (r.bottom - r.top) / 2 * m_viewScale.y) - r.top);
|
||
SetScroll(pos.x, pos.y);
|
||
|
||
RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
}
|
||
|
||
|
||
BOOL CIsoView::OnMouseWheel(UINT nFlags, short zDelta, CPoint ptScreen)
|
||
{
|
||
CPoint pt = ptScreen;
|
||
ScreenToClient(&pt); // Attention: MouseWheel event has screen coordinates in contrast to e.g. MouseMove
|
||
|
||
float smoothF = float(zDelta) / std::numeric_limits<short>::max();
|
||
float fixedF = zDelta > 0 ? std::numeric_limits<short>::max() : std::numeric_limits<short>::min();
|
||
|
||
Zoom(pt, theApp.m_Options.viewScaleUseSteps ? fixedF : smoothF);
|
||
|
||
RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
CMyViewFrame& dlg = *(CMyViewFrame*)owner;
|
||
dlg.m_minimap.RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||
|
||
return CView::OnMouseWheel(nFlags, zDelta, pt);
|
||
}
|
||
|
||
void CIsoView::Zoom(CPoint& pt, float f)
|
||
{
|
||
auto oldScaledMPos = GetProjectedCoordinatesFromClientCoordinates(pt);
|
||
|
||
auto oldScale = m_viewScale;
|
||
|
||
auto oldViewScaleControl = m_viewScaleControl;
|
||
m_viewScaleControl *= (1.0f - f * theApp.m_Options.viewScaleSpeed);
|
||
if (m_viewScaleControl > 1.0f)
|
||
m_viewScaleControl = 1.0f;
|
||
if (m_viewScaleControl < 0.1f)
|
||
m_viewScaleControl = 0.1f;
|
||
|
||
if (!theApp.m_Options.viewScaleUseSteps)
|
||
m_viewScale.set(m_viewScaleControl, m_viewScaleControl);
|
||
else {
|
||
// find previous step
|
||
auto prevStepIt = std::find_if(theApp.m_Options.viewScaleSteps.rbegin(), theApp.m_Options.viewScaleSteps.rend(), [oldScale](auto f) {return f >= oldScale.x; });
|
||
auto stepIt = std::find_if(theApp.m_Options.viewScaleSteps.rbegin(), theApp.m_Options.viewScaleSteps.rend(), [this](auto f) {return f >= m_viewScaleControl; });
|
||
if (stepIt > prevStepIt)
|
||
stepIt = prevStepIt + 1;
|
||
if (stepIt < prevStepIt)
|
||
stepIt = prevStepIt - 1;
|
||
auto nextScale = stepIt == theApp.m_Options.viewScaleSteps.rend() ? 1.0f : *stepIt;
|
||
m_viewScale.set(nextScale, nextScale);
|
||
}
|
||
|
||
auto newScaledMPos = GetProjectedCoordinatesFromClientCoordinates(pt);
|
||
|
||
m_viewOffset = m_viewOffset + ((oldScaledMPos - newScaledMPos)).convertT<std::int32_t>(); // this lets the mouse cursor pixel stay constant
|
||
|
||
UpdateScrollRanges();
|
||
SetScroll(m_viewOffset.x, m_viewOffset.y);
|
||
updateFontScaled();
|
||
}
|
||
|
||
|
||
void CIsoView::OnMButtonDown(UINT nFlags, CPoint point)
|
||
{
|
||
// TODO: Fügen Sie hier Ihren Meldungshandlercode ein, und/oder benutzen Sie den Standard.
|
||
m_MButtonDown = point;
|
||
m_MButtonMoveZooming = point;
|
||
m_zooming = true;
|
||
CView::OnMButtonDown(nFlags, point);
|
||
}
|
||
|
||
|
||
void CIsoView::OnMButtonUp(UINT nFlags, CPoint point)
|
||
{
|
||
// TODO: Fügen Sie hier Ihren Meldungshandlercode ein, und/oder benutzen Sie den Standard.
|
||
m_zooming = false;
|
||
CView::OnMButtonUp(nFlags, point);
|
||
}
|