2009-05-08 13:28:41 +00:00
|
|
|
/*
|
|
|
|
* OpenClonk, http://www.openclonk.org
|
|
|
|
*
|
2009-06-05 13:41:20 +00:00
|
|
|
* Copyright (c) 1998-2000, 2004, 2007-2008 Matthes Bender
|
2010-12-23 00:01:24 +00:00
|
|
|
* Copyright (c) 2001-2003, 2005-2010 Sven Eberhardt
|
2010-09-29 01:44:05 +00:00
|
|
|
* Copyright (c) 2001 Michael Käser
|
2010-12-23 00:01:24 +00:00
|
|
|
* Copyright (c) 2003-2005, 2007-2008 Peter Wortmann
|
2011-09-01 14:58:52 +00:00
|
|
|
* Copyright (c) 2005-2011 Günther Brammer
|
2010-12-23 00:01:24 +00:00
|
|
|
* Copyright (c) 2006, 2010 Armin Burgmeier
|
|
|
|
* Copyright (c) 2010 Tobias Zwick
|
2011-09-01 14:58:52 +00:00
|
|
|
* Copyright (c) 2010 Martin Plicht
|
|
|
|
* Copyright (c) 2011 Nicolas Hake
|
2009-05-08 13:28:41 +00:00
|
|
|
* Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de
|
|
|
|
*
|
|
|
|
* Portions might be copyrighted by other authors who have contributed
|
|
|
|
* to OpenClonk.
|
|
|
|
*
|
|
|
|
* Permission to use, copy, modify, and/or distribute this software for any
|
|
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
|
|
* copyright notice and this permission notice appear in all copies.
|
|
|
|
* See isc_license.txt for full license and disclaimer.
|
|
|
|
*
|
|
|
|
* "Clonk" is a registered trademark of Matthes Bender.
|
|
|
|
* See clonk_trademark_license.txt for full license.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* A viewport to each player */
|
|
|
|
|
|
|
|
#include <C4Include.h>
|
|
|
|
#include <C4Viewport.h>
|
|
|
|
|
2011-11-01 22:17:41 +00:00
|
|
|
#include <C4ViewportWindow.h>
|
2009-05-08 13:28:41 +00:00
|
|
|
#include <C4Console.h>
|
|
|
|
#include <C4Object.h>
|
|
|
|
#include <C4FullScreen.h>
|
|
|
|
#include <C4Stat.h>
|
|
|
|
#include <C4Player.h>
|
|
|
|
#include <C4ObjectMenu.h>
|
2009-06-05 18:00:23 +00:00
|
|
|
#include <C4MouseControl.h>
|
|
|
|
#include <C4PXS.h>
|
2009-06-05 18:12:43 +00:00
|
|
|
#include <C4GameMessage.h>
|
2009-06-12 18:52:21 +00:00
|
|
|
#include <C4GraphicsResource.h>
|
|
|
|
#include <C4GraphicsSystem.h>
|
|
|
|
#include <C4Landscape.h>
|
2009-06-12 23:09:32 +00:00
|
|
|
#include <C4PlayerList.h>
|
2009-06-15 21:47:26 +00:00
|
|
|
#include <C4GameObjects.h>
|
2009-06-15 22:06:37 +00:00
|
|
|
#include <C4Network2.h>
|
2009-05-08 13:28:41 +00:00
|
|
|
|
2010-12-06 20:31:37 +00:00
|
|
|
void C4Viewport::DropFile(const char* fileName, float x, float y)
|
|
|
|
{
|
|
|
|
Game.DropFile(fileName, ViewX+x/Zoom, ViewY+y/Zoom);
|
|
|
|
}
|
|
|
|
|
2009-08-15 18:50:32 +00:00
|
|
|
bool C4Viewport::UpdateOutputSize()
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-08-15 18:50:32 +00:00
|
|
|
if (!pWindow) return false;
|
2009-05-08 13:28:41 +00:00
|
|
|
// Output size
|
2011-03-13 19:00:03 +00:00
|
|
|
C4Rect rect;
|
2010-09-22 15:11:19 +00:00
|
|
|
|
2011-01-23 22:02:23 +00:00
|
|
|
#ifdef WITH_DEVELOPER_MODE
|
2010-09-22 15:11:19 +00:00
|
|
|
GtkAllocation allocation;
|
2012-04-08 23:15:30 +00:00
|
|
|
gtk_widget_get_allocation(GTK_WIDGET(pWindow->render_widget), &allocation);
|
2010-09-22 15:11:19 +00:00
|
|
|
|
2009-05-08 13:28:41 +00:00
|
|
|
// Use only size of drawing area without scrollbars
|
2011-03-13 19:00:03 +00:00
|
|
|
rect.x = allocation.x;
|
|
|
|
rect.y = allocation.y;
|
|
|
|
rect.Wdt = allocation.width;
|
|
|
|
rect.Hgt = allocation.height;
|
2009-05-08 13:28:41 +00:00
|
|
|
#else
|
2009-08-15 18:50:32 +00:00
|
|
|
if (!pWindow->GetSize(&rect)) return false;
|
2009-05-08 13:28:41 +00:00
|
|
|
#endif
|
2011-03-13 19:00:03 +00:00
|
|
|
OutX=rect.x; OutY=rect.y;
|
|
|
|
ViewWdt=rect.Wdt; ViewHgt=rect.Hgt;
|
2009-05-08 13:28:41 +00:00
|
|
|
// Scroll bars
|
|
|
|
ScrollBarsByViewPosition();
|
|
|
|
// Reset menus
|
2009-08-15 18:50:32 +00:00
|
|
|
ResetMenuPositions=true;
|
2009-05-08 13:28:41 +00:00
|
|
|
// update internal GL size
|
2010-03-06 14:07:30 +00:00
|
|
|
if (pWindow && pWindow->pSurface)
|
|
|
|
pWindow->pSurface->UpdateSize(ViewWdt, ViewHgt);
|
2009-05-08 13:28:41 +00:00
|
|
|
// Done
|
2009-08-15 18:50:32 +00:00
|
|
|
return true;
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
C4Viewport::C4Viewport()
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
Default();
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
C4Viewport::~C4Viewport()
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
Clear();
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
void C4Viewport::Clear()
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2010-03-06 14:07:30 +00:00
|
|
|
if (pWindow) { delete pWindow->pSurface; pWindow->Clear(); delete pWindow; pWindow = NULL; }
|
2009-05-08 13:28:41 +00:00
|
|
|
Player=NO_OWNER;
|
|
|
|
ViewX=ViewY=0;
|
|
|
|
ViewWdt=ViewHgt=0;
|
|
|
|
OutX=OutY=ViewWdt=ViewHgt=0;
|
|
|
|
DrawX=DrawY=0;
|
|
|
|
Regions.Clear();
|
2010-03-27 16:05:02 +00:00
|
|
|
ViewOffsX = ViewOffsY = 0;
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
void C4Viewport::DrawOverlay(C4TargetFacet &cgo, const ZoomData &GameZoom)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
if (!Game.C4S.Head.Film || !Game.C4S.Head.Replay)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// Player info
|
|
|
|
C4ST_STARTNEW(PInfoStat, "C4Viewport::DrawOverlay: Player Info")
|
|
|
|
DrawPlayerInfo(cgo);
|
|
|
|
C4ST_STOP(PInfoStat)
|
|
|
|
C4ST_STARTNEW(MenuStat, "C4Viewport::DrawOverlay: Menu")
|
|
|
|
DrawMenu(cgo);
|
|
|
|
C4ST_STOP(MenuStat)
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2010-02-23 11:50:14 +00:00
|
|
|
|
2010-02-23 12:05:13 +00:00
|
|
|
// Control overlays (if not film/replay)
|
|
|
|
if (!Game.C4S.Head.Film || !Game.C4S.Head.Replay)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2010-02-23 12:05:13 +00:00
|
|
|
// Mouse control
|
|
|
|
if (::MouseControl.IsViewport(this))
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2010-02-23 12:05:13 +00:00
|
|
|
C4ST_STARTNEW(MouseStat, "C4Viewport::DrawOverlay: Mouse")
|
|
|
|
::MouseControl.Draw(cgo, GameZoom);
|
|
|
|
// Draw GUI-mouse in EM if active
|
2010-10-29 23:47:50 +00:00
|
|
|
if (pWindow) ::pGUI->RenderMouse(cgo);
|
2010-02-23 12:05:13 +00:00
|
|
|
C4ST_STOP(MouseStat)
|
2010-02-23 11:50:14 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
}
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
2011-09-26 23:17:36 +00:00
|
|
|
void C4Viewport::DrawMenu(C4TargetFacet &cgo0)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// Get player
|
2009-06-12 23:09:32 +00:00
|
|
|
C4Player *pPlr = ::Players.Get(Player);
|
2009-05-08 13:28:41 +00:00
|
|
|
|
2011-09-26 23:17:36 +00:00
|
|
|
// for menus, cgo is using GUI-syntax: TargetX/Y marks the drawing offset; x/y/Wdt/Hgt marks the offset rect
|
|
|
|
C4TargetFacet cgo; cgo.Set(cgo0);
|
|
|
|
cgo.X = 0; cgo.Y = 0;
|
|
|
|
cgo.Wdt = cgo0.Wdt * cgo0.Zoom; cgo.Hgt = cgo0.Hgt * cgo0.Zoom;
|
|
|
|
cgo.TargetX = float(cgo0.X); cgo.TargetY = float(cgo0.Y);
|
|
|
|
cgo.Zoom = 1;
|
2011-10-03 14:30:18 +00:00
|
|
|
pDraw->SetZoom(cgo.X, cgo.Y, cgo.Zoom);
|
2011-09-26 23:17:36 +00:00
|
|
|
|
2009-05-08 13:28:41 +00:00
|
|
|
// Player eliminated
|
|
|
|
if (pPlr && pPlr->Eliminated)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2011-10-03 14:30:18 +00:00
|
|
|
pDraw->TextOut(FormatString(LoadResStr(pPlr->Surrendered ? "IDS_PLR_SURRENDERED" : "IDS_PLR_ELIMINATED"),pPlr->GetName()).getData(),
|
2011-09-26 23:17:36 +00:00
|
|
|
::GraphicsResource.FontRegular, 1.0, cgo.Surface,cgo.TargetX+cgo.Wdt/2,cgo.TargetY+2*cgo.Hgt/3,0xfaFF0000,ACenter);
|
2009-05-08 13:28:41 +00:00
|
|
|
return;
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
// Player cursor object menu
|
|
|
|
if (pPlr && pPlr->Cursor && pPlr->Cursor->Menu)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
if (ResetMenuPositions) pPlr->Cursor->Menu->ResetLocation();
|
|
|
|
// if mouse is dragging, make it transparent to easy construction site drag+drop
|
|
|
|
bool fDragging=false;
|
2009-06-05 15:20:07 +00:00
|
|
|
if (::MouseControl.IsDragging() && ::MouseControl.IsViewport(this))
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
fDragging = true;
|
2011-10-03 14:30:18 +00:00
|
|
|
pDraw->ActivateBlitModulation(0x4fffffff);
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
// draw menu
|
|
|
|
pPlr->Cursor->Menu->Draw(cgo);
|
|
|
|
// reset modulation for dragging
|
2011-10-03 14:30:18 +00:00
|
|
|
if (fDragging) pDraw->DeactivateBlitModulation();
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
// Player menu
|
|
|
|
if (pPlr && pPlr->Menu.IsActive())
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
if (ResetMenuPositions) pPlr->Menu.ResetLocation();
|
|
|
|
pPlr->Menu.Draw(cgo);
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
// Fullscreen menu
|
|
|
|
if (FullScreen.pMenu && FullScreen.pMenu->IsActive())
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
if (ResetMenuPositions) FullScreen.pMenu->ResetLocation();
|
|
|
|
FullScreen.pMenu->Draw(cgo);
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
// Flag done
|
2009-08-15 18:50:32 +00:00
|
|
|
ResetMenuPositions=false;
|
2009-05-08 13:28:41 +00:00
|
|
|
|
2011-09-26 23:17:36 +00:00
|
|
|
// restore Zoom
|
2011-10-03 14:30:18 +00:00
|
|
|
pDraw->SetZoom(cgo0.X, cgo0.Y, cgo0.Zoom);
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
2010-03-06 14:07:30 +00:00
|
|
|
void C4Viewport::Draw(C4TargetFacet &cgo0, bool fDrawOverlay)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
#ifdef USE_CONSOLE
|
|
|
|
// No drawing in console mode
|
|
|
|
return;
|
|
|
|
#endif
|
2010-03-06 14:07:30 +00:00
|
|
|
C4TargetFacet cgo; cgo.Set(cgo0);
|
2009-05-08 13:28:41 +00:00
|
|
|
ZoomData GameZoom;
|
|
|
|
GameZoom.X = cgo.X; GameZoom.Y = cgo.Y;
|
2010-09-25 20:52:43 +00:00
|
|
|
GameZoom.Zoom = cgo.Zoom;
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
if (fDrawOverlay)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// Draw landscape borders. Only if overlay, so complete map screenshots don't get messed up
|
2011-10-03 14:30:18 +00:00
|
|
|
if (BorderLeft) pDraw->BlitSurfaceTile(::GraphicsResource.fctBackground.Surface,cgo.Surface,DrawX,DrawY,BorderLeft,ViewHgt,-DrawX,-DrawY);
|
|
|
|
if (BorderTop) pDraw->BlitSurfaceTile(::GraphicsResource.fctBackground.Surface,cgo.Surface,DrawX+BorderLeft,DrawY,ViewWdt-BorderLeft-BorderRight,BorderTop,-DrawX-BorderLeft,-DrawY);
|
|
|
|
if (BorderRight) pDraw->BlitSurfaceTile(::GraphicsResource.fctBackground.Surface,cgo.Surface,DrawX+ViewWdt-BorderRight,DrawY,BorderRight,ViewHgt,-DrawX-ViewWdt+BorderRight,-DrawY);
|
|
|
|
if (BorderBottom)pDraw->BlitSurfaceTile(::GraphicsResource.fctBackground.Surface,cgo.Surface,DrawX+BorderLeft,DrawY+ViewHgt-BorderBottom,ViewWdt-BorderLeft-BorderRight,BorderBottom,-DrawX-BorderLeft,-DrawY-ViewHgt+BorderBottom);
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
// Set clippers
|
2010-09-25 20:52:43 +00:00
|
|
|
cgo.X += BorderLeft; cgo.Y += BorderTop; cgo.Wdt -= int(float(BorderLeft+BorderRight)/cgo.Zoom); cgo.Hgt -= int(float(BorderTop+BorderBottom)/cgo.Zoom);
|
2009-05-08 13:28:41 +00:00
|
|
|
GameZoom.X = cgo.X; GameZoom.Y = cgo.Y;
|
|
|
|
cgo.TargetX += BorderLeft/Zoom; cgo.TargetY += BorderTop/Zoom;
|
|
|
|
// Apply Zoom
|
2011-10-03 14:30:18 +00:00
|
|
|
pDraw->SetZoom(GameZoom);
|
|
|
|
pDraw->SetPrimaryClipper(cgo.X,cgo.Y,DrawX+ViewWdt-1-BorderRight,DrawY+ViewHgt-1-BorderBottom);
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-10-16 21:07:43 +00:00
|
|
|
last_game_draw_cgo = cgo;
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
// landscape mod by FoW
|
2011-09-11 20:05:29 +00:00
|
|
|
/*
|
|
|
|
Fog of war disabled until proper Shader-implementation is around
|
|
|
|
|
2009-06-12 23:09:32 +00:00
|
|
|
C4Player *pPlr=::Players.Get(Player);
|
2009-05-08 13:28:41 +00:00
|
|
|
if (pPlr && pPlr->fFogOfWar)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2010-03-21 18:34:22 +00:00
|
|
|
ClrModMap.Reset(Game.C4S.Landscape.FoWRes, Game.C4S.Landscape.FoWRes, ViewWdt, ViewHgt, int(cgo.TargetX*Zoom), int(cgo.TargetY*Zoom), 0, cgo.X-BorderLeft, cgo.Y-BorderTop, Game.FoWColor, cgo.Surface);
|
2009-05-08 13:28:41 +00:00
|
|
|
pPlr->FoW2Map(ClrModMap, int(float(cgo.X)/Zoom-cgo.TargetX), int(float(cgo.Y)/Zoom-cgo.TargetY));
|
2011-10-03 14:30:18 +00:00
|
|
|
pDraw->SetClrModMap(&ClrModMap);
|
|
|
|
pDraw->SetClrModMapEnabled(true);
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
else
|
2011-10-03 14:30:18 +00:00
|
|
|
pDraw->SetClrModMapEnabled(false);
|
2011-09-11 20:05:29 +00:00
|
|
|
*/
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
C4ST_STARTNEW(SkyStat, "C4Viewport::Draw: Sky")
|
2009-06-05 15:20:41 +00:00
|
|
|
::Landscape.Sky.Draw(cgo);
|
2009-05-08 13:28:41 +00:00
|
|
|
C4ST_STOP(SkyStat)
|
2011-02-18 23:44:54 +00:00
|
|
|
::Objects.Draw(cgo, Player, -2147483647 - 1 /* INT32_MIN */, 0);
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
// Draw Landscape
|
|
|
|
C4ST_STARTNEW(LandStat, "C4Viewport::Draw: Landscape")
|
2009-06-05 15:20:41 +00:00
|
|
|
::Landscape.Draw(cgo,Player);
|
2009-05-08 13:28:41 +00:00
|
|
|
C4ST_STOP(LandStat)
|
|
|
|
|
|
|
|
// draw PXS (unclipped!)
|
|
|
|
C4ST_STARTNEW(PXSStat, "C4Viewport::Draw: PXS")
|
2009-06-05 15:20:27 +00:00
|
|
|
::PXS.Draw(cgo);
|
2009-05-08 13:28:41 +00:00
|
|
|
C4ST_STOP(PXSStat)
|
|
|
|
|
|
|
|
// draw objects
|
|
|
|
C4ST_STARTNEW(ObjStat, "C4Viewport::Draw: Objects")
|
2011-02-18 23:44:54 +00:00
|
|
|
::Objects.Draw(cgo, Player, 1, 2147483647 /* INT32_MAX */);
|
2009-05-08 13:28:41 +00:00
|
|
|
C4ST_STOP(ObjStat)
|
|
|
|
|
|
|
|
// draw global particles
|
|
|
|
C4ST_STARTNEW(PartStat, "C4Viewport::Draw: Particles")
|
2009-06-05 15:22:28 +00:00
|
|
|
::Particles.GlobalParticles.Draw(cgo,NULL);
|
2009-05-08 13:28:41 +00:00
|
|
|
C4ST_STOP(PartStat)
|
|
|
|
|
|
|
|
// Draw PathFinder
|
2009-06-05 15:14:20 +00:00
|
|
|
if (::GraphicsSystem.ShowPathfinder) Game.PathFinder.Draw(cgo);
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
// Draw overlay
|
|
|
|
if (!Game.C4S.Head.Film || !Game.C4S.Head.Replay) Game.DrawCursors(cgo, Player);
|
|
|
|
|
2011-09-11 20:05:29 +00:00
|
|
|
/* Fog of war disabled, see above
|
2009-05-08 13:28:41 +00:00
|
|
|
// FogOfWar-mod off
|
2011-10-03 14:30:18 +00:00
|
|
|
pDraw->SetClrModMapEnabled(false);
|
2009-05-08 13:28:41 +00:00
|
|
|
|
2011-09-11 20:05:29 +00:00
|
|
|
*/
|
|
|
|
|
2009-05-08 13:28:41 +00:00
|
|
|
if (fDrawOverlay)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// Determine zoom of overlay
|
2011-08-18 17:46:51 +00:00
|
|
|
float fGUIZoom = GetGUIZoom();
|
2009-05-08 13:28:41 +00:00
|
|
|
// now restore complete cgo range for overlay drawing
|
2011-10-03 14:30:18 +00:00
|
|
|
pDraw->SetZoom(DrawX,DrawY, fGUIZoom);
|
|
|
|
pDraw->SetPrimaryClipper(DrawX,DrawY,DrawX+(ViewWdt-1),DrawY+(ViewHgt-1));
|
2010-09-25 20:52:43 +00:00
|
|
|
C4TargetFacet gui_cgo;
|
|
|
|
gui_cgo.Set(cgo0);
|
2009-05-08 13:28:41 +00:00
|
|
|
|
2010-09-25 20:52:43 +00:00
|
|
|
gui_cgo.X = DrawX; gui_cgo.Y = DrawY; gui_cgo.Zoom = fGUIZoom;
|
|
|
|
gui_cgo.Wdt = int(float(ViewWdt)/fGUIZoom); gui_cgo.Hgt = int(float(ViewHgt)/fGUIZoom);
|
|
|
|
gui_cgo.TargetX = ViewX; gui_cgo.TargetY = ViewY;
|
2010-03-16 11:10:11 +00:00
|
|
|
|
2010-09-25 20:52:43 +00:00
|
|
|
last_gui_draw_cgo = gui_cgo;
|
2009-10-16 21:07:43 +00:00
|
|
|
|
2009-05-08 13:28:41 +00:00
|
|
|
// draw custom GUI objects
|
2010-09-25 20:52:43 +00:00
|
|
|
::Objects.ForeObjects.DrawIfCategory(gui_cgo, Player, C4D_Foreground, false);
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
// Draw overlay
|
|
|
|
C4ST_STARTNEW(OvrStat, "C4Viewport::Draw: Overlay")
|
|
|
|
|
2010-09-28 18:16:33 +00:00
|
|
|
if (Application.isEditor) Console.EditCursor.Draw(cgo);
|
2009-05-08 13:28:41 +00:00
|
|
|
|
2010-09-25 20:52:43 +00:00
|
|
|
DrawOverlay(gui_cgo, GameZoom);
|
|
|
|
|
|
|
|
// Game messages
|
|
|
|
C4ST_STARTNEW(MsgStat, "C4Viewport::DrawOverlay: Messages")
|
2011-10-03 14:30:18 +00:00
|
|
|
pDraw->SetZoom(0, 0, 1.0);
|
2010-09-25 20:52:43 +00:00
|
|
|
::Messages.Draw(gui_cgo, cgo, Player);
|
|
|
|
C4ST_STOP(MsgStat)
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
// Netstats
|
2009-06-05 15:14:20 +00:00
|
|
|
if (::GraphicsSystem.ShowNetstatus)
|
2010-09-25 20:52:43 +00:00
|
|
|
::Network.DrawStatus(gui_cgo);
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
C4ST_STOP(OvrStat)
|
|
|
|
|
|
|
|
// Remove zoom n clippers
|
2011-10-03 14:30:18 +00:00
|
|
|
pDraw->SetZoom(0, 0, 1.0);
|
|
|
|
pDraw->NoPrimaryClipper();
|
2009-05-08 13:28:41 +00:00
|
|
|
}
|
|
|
|
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
|
|
|
|
2009-05-08 13:28:41 +00:00
|
|
|
void C4Viewport::BlitOutput()
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
if (pWindow)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2011-03-13 16:41:42 +00:00
|
|
|
C4Rect rtSrc,rtDst;
|
|
|
|
rtSrc.x = DrawX; rtSrc.y = DrawY; rtSrc.Wdt = ViewWdt; rtSrc.Hgt = ViewHgt;
|
|
|
|
rtDst.x = OutX; rtDst.y = OutY; rtDst.Wdt = ViewWdt; rtDst.Hgt = ViewHgt;
|
2010-03-05 21:15:25 +00:00
|
|
|
pWindow->pSurface->PageFlip(&rtSrc, &rtDst);
|
2009-05-08 13:28:41 +00:00
|
|
|
}
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
void C4Viewport::Execute()
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// Update regions
|
|
|
|
static int32_t RegionUpdate=0;
|
|
|
|
SetRegions=NULL;
|
|
|
|
RegionUpdate++;
|
|
|
|
if (RegionUpdate>=5)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
RegionUpdate=0;
|
|
|
|
Regions.Clear();
|
|
|
|
Regions.SetAdjust(-OutX,-OutY);
|
|
|
|
SetRegions=&Regions;
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
// Adjust position
|
|
|
|
AdjustPosition();
|
|
|
|
// Current graphics output
|
|
|
|
C4TargetFacet cgo;
|
2011-08-27 21:12:01 +00:00
|
|
|
C4Window * w = pWindow;
|
2010-03-06 14:07:30 +00:00
|
|
|
if (!w) w = &FullScreen;
|
2010-09-25 20:52:43 +00:00
|
|
|
cgo.Set(w->pSurface,DrawX,DrawY,int32_t(ceilf(float(ViewWdt)/Zoom)),int32_t(ceilf(float(ViewHgt)/Zoom)),ViewX,ViewY,Zoom);
|
2011-10-03 14:30:18 +00:00
|
|
|
pDraw->PrepareRendering(w->pSurface);
|
2009-05-08 13:28:41 +00:00
|
|
|
// Draw
|
|
|
|
Draw(cgo, true);
|
|
|
|
// Video record & status (developer mode, first player viewport)
|
2010-09-28 18:16:33 +00:00
|
|
|
if (Application.isEditor)
|
2010-09-29 01:44:05 +00:00
|
|
|
if (Player==0 && (this==::Viewports.GetViewport((int32_t) 0)))
|
2009-06-05 15:14:20 +00:00
|
|
|
::GraphicsSystem.Video.Execute();
|
2009-05-08 13:28:41 +00:00
|
|
|
// Blit output
|
|
|
|
BlitOutput();
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
2010-09-08 21:49:42 +00:00
|
|
|
void C4Viewport::InitZoom()
|
|
|
|
{
|
|
|
|
// player viewport: Init zoom by view range parameters
|
|
|
|
C4Player *plr = Players.Get(Player);
|
|
|
|
if (plr)
|
|
|
|
{
|
2010-12-12 21:38:19 +00:00
|
|
|
// Note this affects all viewports for this player (not just
|
|
|
|
// this one), but it is a noop for the others.
|
|
|
|
plr->ZoomLimitsToViewport(this);
|
|
|
|
plr->ZoomToViewport(this, true);
|
2010-09-08 21:49:42 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// general viewport? Default zoom parameters
|
|
|
|
ZoomTarget = Max<float>(float(ViewWdt)/GBackWdt, 1.0f);
|
|
|
|
Zoom = ZoomTarget;
|
2012-03-19 14:10:12 +00:00
|
|
|
SetZoomLimits(0.8*Min<float>(float(ViewWdt)/GBackWdt,float(ViewHgt)/GBackHgt), 12);
|
2010-09-08 21:49:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-05-08 13:28:41 +00:00
|
|
|
void C4Viewport::ChangeZoom(float by_factor)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
ZoomTarget *= by_factor;
|
2010-09-08 21:49:42 +00:00
|
|
|
if (ZoomLimitMin && ZoomTarget < ZoomLimitMin) ZoomTarget = ZoomLimitMin;
|
|
|
|
if (ZoomLimitMax && ZoomTarget > ZoomLimitMax) ZoomTarget = ZoomLimitMax;
|
|
|
|
}
|
|
|
|
|
|
|
|
void C4Viewport::SetZoom(float to_value, bool direct)
|
|
|
|
{
|
|
|
|
ZoomTarget = to_value;
|
2010-12-13 20:55:43 +00:00
|
|
|
if (Player != NO_OWNER || !::Application.isEditor)
|
|
|
|
{
|
|
|
|
if (ZoomLimitMin && ZoomTarget < ZoomLimitMin) ZoomTarget = ZoomLimitMin;
|
|
|
|
if (ZoomLimitMax && ZoomTarget > ZoomLimitMax) ZoomTarget = ZoomLimitMax;
|
|
|
|
}
|
2010-09-08 21:49:42 +00:00
|
|
|
// direct: Set zoom without scrolling to it
|
|
|
|
if (direct) Zoom = ZoomTarget;
|
|
|
|
}
|
|
|
|
|
|
|
|
void C4Viewport::SetZoomLimits(float to_min_zoom, float to_max_zoom)
|
|
|
|
{
|
|
|
|
ZoomLimitMin = to_min_zoom;
|
|
|
|
ZoomLimitMax = to_max_zoom;
|
2012-03-19 14:10:12 +00:00
|
|
|
if (ZoomLimitMax && ZoomLimitMax < ZoomLimitMin) ZoomLimitMax = ZoomLimitMin;
|
|
|
|
ChangeZoom(1); // Constrains zoom to limit.
|
2010-09-08 21:49:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
float C4Viewport::GetZoomByViewRange(int32_t size_x, int32_t size_y) const
|
|
|
|
{
|
|
|
|
// set zoom such that both size_x and size_y are guarantueed to fit into the viewport range
|
|
|
|
// determine whether zoom is to be calculated by x or by y
|
2010-09-19 15:39:00 +00:00
|
|
|
bool zoom_by_y = false;
|
2010-09-08 21:49:42 +00:00
|
|
|
if (size_x && size_y)
|
|
|
|
{
|
|
|
|
zoom_by_y = (size_y * ViewWdt > size_x * ViewHgt);
|
|
|
|
}
|
|
|
|
else if (size_y)
|
|
|
|
{
|
|
|
|
// no x size passed - zoom by y
|
|
|
|
zoom_by_y = true;
|
|
|
|
}
|
2010-09-17 12:35:24 +00:00
|
|
|
else
|
2010-09-08 21:49:42 +00:00
|
|
|
{
|
|
|
|
// 0/0 size passed - zoom to default
|
2010-09-17 12:35:24 +00:00
|
|
|
if (!size_x)
|
|
|
|
size_x = C4FOW_Def_View_RangeX * 2;
|
2010-09-08 21:49:42 +00:00
|
|
|
zoom_by_y = false;
|
|
|
|
}
|
|
|
|
// zoom calculation
|
|
|
|
if (zoom_by_y)
|
|
|
|
return float(ViewHgt) / size_y;
|
|
|
|
else
|
|
|
|
return float(ViewWdt) / size_x;
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
2010-12-06 20:32:27 +00:00
|
|
|
void C4Viewport::SetZoom(float zoomValue)
|
|
|
|
{
|
|
|
|
Zoom = zoomValue;
|
|
|
|
// also set target to prevent zoom from changing back
|
|
|
|
ZoomTarget = zoomValue;
|
|
|
|
}
|
|
|
|
|
2009-05-08 13:28:41 +00:00
|
|
|
void C4Viewport::AdjustPosition()
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2011-08-30 13:05:27 +00:00
|
|
|
if (ViewWdt == 0 || ViewHgt == 0)
|
|
|
|
{
|
|
|
|
// zero-sized viewport, possibly minimized editor window
|
|
|
|
// don't do anything then
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-05-08 13:28:41 +00:00
|
|
|
float ViewportScrollBorder = fIsNoOwnerViewport ? 0 : float(C4ViewportScrollBorder);
|
2010-04-26 23:32:45 +00:00
|
|
|
C4Player *pPlr = ::Players.Get(Player);
|
2010-09-08 21:49:42 +00:00
|
|
|
if (ZoomTarget < 0.000001f) InitZoom();
|
|
|
|
// Change Zoom
|
|
|
|
assert(Zoom>0);
|
|
|
|
assert(ZoomTarget>0);
|
|
|
|
|
2010-09-25 20:53:55 +00:00
|
|
|
float PrefViewX = ViewX + ViewWdt / (Zoom * 2) - ViewOffsX;
|
|
|
|
float PrefViewY = ViewY + ViewHgt / (Zoom * 2) - ViewOffsY;
|
|
|
|
|
2010-09-08 21:49:42 +00:00
|
|
|
if(Zoom != ZoomTarget)
|
2010-04-26 23:32:45 +00:00
|
|
|
{
|
2010-09-08 21:49:42 +00:00
|
|
|
float DeltaZoom = Zoom/ZoomTarget;
|
|
|
|
if(DeltaZoom<1) DeltaZoom = 1/DeltaZoom;
|
|
|
|
|
|
|
|
// Minimal Zoom change factor
|
|
|
|
static const float Z0 = pow(C4GFX_ZoomStep, 1.0f/8.0f);
|
|
|
|
|
|
|
|
// We change zoom based on (logarithmic) distance of current zoom
|
|
|
|
// to target zoom. The greater the distance the more we adjust the
|
|
|
|
// zoom in one frame. There is a minimal zoom change Z0 to make sure
|
|
|
|
// we reach ZoomTarget in finite time.
|
|
|
|
float ZoomAdjustFactor = Z0 * pow(DeltaZoom, 1.0f/8.0f);
|
|
|
|
|
|
|
|
if (Zoom < ZoomTarget)
|
|
|
|
Zoom = Min(Zoom * ZoomAdjustFactor, ZoomTarget);
|
|
|
|
if (Zoom > ZoomTarget)
|
|
|
|
Zoom = Max(Zoom / ZoomAdjustFactor, ZoomTarget);
|
2010-04-26 23:32:45 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
// View position
|
|
|
|
if (PlayerLock && ValidPlr(Player))
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2010-09-08 21:49:42 +00:00
|
|
|
|
2010-04-26 23:32:45 +00:00
|
|
|
float ScrollRange = Min(ViewWdt/(10*Zoom),ViewHgt/(10*Zoom));
|
|
|
|
float ExtraBoundsX = 0, ExtraBoundsY = 0;
|
2010-03-28 18:58:01 +00:00
|
|
|
if (pPlr->ViewMode == C4PVM_Scrolling)
|
|
|
|
{
|
2010-04-26 23:32:45 +00:00
|
|
|
ScrollRange=0;
|
|
|
|
ExtraBoundsX=ExtraBoundsY=ViewportScrollBorder;
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
else
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// if view is close to border, allow scrolling
|
2010-09-24 17:52:20 +00:00
|
|
|
if (fixtof(pPlr->ViewX) < ViewportScrollBorder) ExtraBoundsX = Min<float>(ViewportScrollBorder - fixtof(pPlr->ViewX), ViewportScrollBorder);
|
|
|
|
else if (fixtof(pPlr->ViewX) >= GBackWdt - ViewportScrollBorder) ExtraBoundsX = Min<float>(fixtof(pPlr->ViewX) - GBackWdt, 0) + ViewportScrollBorder;
|
|
|
|
if (fixtof(pPlr->ViewY) < ViewportScrollBorder) ExtraBoundsY = Min<float>(ViewportScrollBorder - fixtof(pPlr->ViewY), ViewportScrollBorder);
|
|
|
|
else if (fixtof(pPlr->ViewY) >= GBackHgt - ViewportScrollBorder) ExtraBoundsY = Min<float>(fixtof(pPlr->ViewY) - GBackHgt, 0) + ViewportScrollBorder;
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2010-04-26 23:32:45 +00:00
|
|
|
ExtraBoundsX = Max(ExtraBoundsX, (ViewWdt/Zoom - GBackWdt) / 2+1);
|
|
|
|
ExtraBoundsY = Max(ExtraBoundsY, (ViewHgt/Zoom - GBackHgt) / 2+1);
|
2009-05-08 13:28:41 +00:00
|
|
|
// calc target view position
|
2010-09-24 17:52:20 +00:00
|
|
|
float TargetViewX = fixtof(pPlr->ViewX) /* */;
|
|
|
|
float TargetViewY = fixtof(pPlr->ViewY) /* */;
|
2009-05-08 13:28:41 +00:00
|
|
|
// add mouse auto scroll
|
2010-03-28 18:58:01 +00:00
|
|
|
if (pPlr->MouseControl && ::MouseControl.InitCentered && Config.Controls.MouseAScroll)
|
2010-02-09 18:04:04 +00:00
|
|
|
{
|
2010-04-26 23:32:45 +00:00
|
|
|
TargetViewX += (::MouseControl.VpX - ViewWdt / 2) / Zoom;
|
|
|
|
TargetViewY += (::MouseControl.VpY - ViewHgt / 2) / Zoom;
|
2010-02-09 18:04:04 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
// scroll range
|
2010-04-26 23:32:45 +00:00
|
|
|
TargetViewX = BoundBy(PrefViewX, TargetViewX - ScrollRange, TargetViewX + ScrollRange);
|
|
|
|
TargetViewY = BoundBy(PrefViewY, TargetViewY - ScrollRange, TargetViewY + ScrollRange);
|
2009-05-08 13:28:41 +00:00
|
|
|
// bounds
|
2010-04-26 23:32:45 +00:00
|
|
|
TargetViewX = BoundBy(TargetViewX, ViewWdt / (Zoom * 2) - ExtraBoundsX, GBackWdt - ViewWdt / (Zoom * 2) + ExtraBoundsX);
|
|
|
|
TargetViewY = BoundBy(TargetViewY, ViewHgt / (Zoom * 2) - ExtraBoundsY, GBackHgt - ViewHgt / (Zoom * 2) + ExtraBoundsY);
|
2009-05-08 13:28:41 +00:00
|
|
|
// smooth
|
2010-04-26 23:32:45 +00:00
|
|
|
ViewX = PrefViewX + (TargetViewX - PrefViewX) / BoundBy<int32_t>(Config.General.ScrollSmooth, 1, 50);
|
|
|
|
ViewY = PrefViewY + (TargetViewY - PrefViewY) / BoundBy<int32_t>(Config.General.ScrollSmooth, 1, 50);
|
2009-05-08 13:28:41 +00:00
|
|
|
// apply offset
|
2010-04-26 23:32:45 +00:00
|
|
|
ViewX -= ViewWdt / (Zoom * 2) - ViewOffsX;
|
|
|
|
ViewY -= ViewHgt / (Zoom * 2) - ViewOffsY;
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
// NO_OWNER can't scroll
|
|
|
|
if (fIsNoOwnerViewport) { ViewOffsX=0; ViewOffsY=0; }
|
2010-03-27 16:05:02 +00:00
|
|
|
// clip at borders, update vars
|
2009-05-08 13:28:41 +00:00
|
|
|
UpdateViewPosition();
|
|
|
|
#ifdef WITH_DEVELOPER_MODE
|
|
|
|
//ScrollBarsByViewPosition();
|
|
|
|
#endif
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
void C4Viewport::CenterPosition()
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// center viewport position on map
|
|
|
|
// set center position
|
|
|
|
ViewX = (GBackWdt-ViewWdt/Zoom)/2;
|
|
|
|
ViewY = (GBackHgt-ViewHgt/Zoom)/2;
|
|
|
|
// clips and updates
|
|
|
|
UpdateViewPosition();
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
void C4Viewport::UpdateViewPosition()
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// no-owner viewports should not scroll outside viewing area
|
2010-03-28 18:58:01 +00:00
|
|
|
if (fIsNoOwnerViewport)
|
|
|
|
{
|
2010-09-28 18:16:33 +00:00
|
|
|
if (!Application.isEditor && GBackWdt<ViewWdt / Zoom)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
ViewX = (GBackWdt-ViewWdt / Zoom)/2;
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
else
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
ViewX = Min(ViewX, GBackWdt-ViewWdt / Zoom);
|
|
|
|
ViewX = Max(ViewX, 0.0f);
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2010-09-28 18:16:33 +00:00
|
|
|
if (!Application.isEditor && GBackHgt<ViewHgt / Zoom)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
ViewY = (GBackHgt-ViewHgt / Zoom)/2;
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
else
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
ViewY = Min(ViewY, GBackHgt-ViewHgt / Zoom);
|
|
|
|
ViewY = Max(ViewY, 0.0f);
|
|
|
|
}
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
// update borders
|
|
|
|
BorderLeft = int32_t(Max(-ViewX * Zoom, 0.0f));
|
|
|
|
BorderTop = int32_t(Max(-ViewY * Zoom, 0.0f));
|
|
|
|
BorderRight = int32_t(Max(ViewWdt - GBackWdt * Zoom + ViewX * Zoom, 0.0f));
|
|
|
|
BorderBottom = int32_t(Max(ViewHgt - GBackHgt * Zoom + ViewY * Zoom, 0.0f));
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
void C4Viewport::Default()
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
pWindow=NULL;
|
|
|
|
Player=0;
|
|
|
|
ViewX=ViewY=0;
|
|
|
|
ViewWdt=ViewHgt=0;
|
|
|
|
BorderLeft=BorderTop=BorderRight=BorderBottom=0;
|
|
|
|
OutX=OutY=ViewWdt=ViewHgt=0;
|
|
|
|
DrawX=DrawY=0;
|
|
|
|
Zoom = 1.0;
|
2010-04-26 23:32:45 +00:00
|
|
|
ZoomTarget = 0.0;
|
2010-09-08 21:49:42 +00:00
|
|
|
ZoomLimitMin=ZoomLimitMax=0; // no limit
|
2009-05-08 13:28:41 +00:00
|
|
|
Next=NULL;
|
2009-08-15 18:50:32 +00:00
|
|
|
PlayerLock=true;
|
|
|
|
ResetMenuPositions=false;
|
2009-05-08 13:28:41 +00:00
|
|
|
SetRegions=NULL;
|
|
|
|
Regions.Default();
|
|
|
|
ViewOffsX = ViewOffsY = 0;
|
|
|
|
fIsNoOwnerViewport = false;
|
2009-10-16 21:07:43 +00:00
|
|
|
last_game_draw_cgo.Default();
|
|
|
|
last_gui_draw_cgo.Default();
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
void C4Viewport::DrawPlayerInfo(C4TargetFacet &cgo)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
C4Facet ccgo;
|
|
|
|
if (!ValidPlr(Player)) return;
|
2010-07-30 20:38:21 +00:00
|
|
|
|
2009-05-08 13:28:41 +00:00
|
|
|
// Controls
|
|
|
|
DrawPlayerStartup(cgo);
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
2009-08-15 18:50:32 +00:00
|
|
|
bool C4Viewport::Init(int32_t iPlayer, bool fSetTempOnly)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// Fullscreen viewport initialization
|
|
|
|
// Set Player
|
|
|
|
if (!ValidPlr(iPlayer)) iPlayer = NO_OWNER;
|
|
|
|
Player=iPlayer;
|
|
|
|
if (!fSetTempOnly) fIsNoOwnerViewport = (iPlayer == NO_OWNER);
|
2012-03-04 21:45:00 +00:00
|
|
|
if (Application.isEditor)
|
|
|
|
{
|
|
|
|
// Console viewport initialization
|
|
|
|
// Create window
|
|
|
|
pWindow = new C4ViewportWindow(this);
|
|
|
|
if (!pWindow->Init(Player))
|
|
|
|
return false;
|
|
|
|
UpdateOutputSize();
|
|
|
|
// Disable player lock on unowned viewports
|
|
|
|
if (!ValidPlr(Player)) TogglePlayerLock();
|
|
|
|
// Draw
|
|
|
|
// Don't call Execute right away since it is not yet guaranteed that
|
|
|
|
// the Player has set this as its Viewport, and the drawing routines rely
|
|
|
|
// on that.
|
|
|
|
//Execute();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Owned viewport: clear any flash message explaining observer menu
|
|
|
|
if (ValidPlr(iPlayer)) ::GraphicsSystem.FlashMessage("");
|
|
|
|
}
|
2009-08-15 18:50:32 +00:00
|
|
|
return true;
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
extern int32_t DrawMessageOffset;
|
|
|
|
|
|
|
|
void C4Viewport::DrawPlayerStartup(C4TargetFacet &cgo)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
C4Player *pPlr;
|
2009-06-12 23:09:32 +00:00
|
|
|
if (!(pPlr = ::Players.Get(Player))) return;
|
2009-05-08 13:28:41 +00:00
|
|
|
if (!pPlr->LocalControl || !pPlr->ShowStartup) return;
|
|
|
|
int32_t iNameHgtOff=0;
|
|
|
|
|
|
|
|
// Control
|
2012-01-29 02:13:55 +00:00
|
|
|
// unnecessary with the current control sets
|
|
|
|
/* if (pPlr->MouseControl)
|
2009-05-08 13:28:41 +00:00
|
|
|
GfxR->fctMouse.Draw(cgo.Surface,
|
2010-03-28 18:58:01 +00:00
|
|
|
cgo.X+(cgo.Wdt-GfxR->fctKeyboard.Wdt)/2+55,
|
|
|
|
cgo.Y+cgo.Hgt * 2/3 - 10 + DrawMessageOffset,
|
2012-01-29 02:13:55 +00:00
|
|
|
0,0);*/
|
2009-10-14 16:46:22 +00:00
|
|
|
if (pPlr && pPlr->ControlSet)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-10-14 16:46:22 +00:00
|
|
|
C4Facet controlset_facet = pPlr->ControlSet->GetPicture();
|
|
|
|
if (controlset_facet.Wdt) controlset_facet.Draw(cgo.Surface,
|
2010-03-28 18:58:01 +00:00
|
|
|
cgo.X+(cgo.Wdt-controlset_facet.Wdt)/2,
|
|
|
|
cgo.Y+cgo.Hgt * 2/3 + DrawMessageOffset,
|
|
|
|
0,0);
|
2009-05-08 13:28:41 +00:00
|
|
|
iNameHgtOff=GfxR->fctKeyboard.Hgt;
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
// Name
|
2011-10-03 14:30:18 +00:00
|
|
|
pDraw->TextOut(pPlr->GetName(), ::GraphicsResource.FontRegular, 1.0, cgo.Surface,
|
2010-03-28 18:58:01 +00:00
|
|
|
cgo.X+cgo.Wdt/2,cgo.Y+cgo.Hgt*2/3+iNameHgtOff + DrawMessageOffset,
|
|
|
|
pPlr->ColorDw | 0xff000000, ACenter);
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
void C4Viewport::SetOutputSize(int32_t iDrawX, int32_t iDrawY, int32_t iOutX, int32_t iOutY, int32_t iOutWdt, int32_t iOutHgt)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// update view position: Remain centered at previous position
|
|
|
|
ViewX += (ViewWdt-iOutWdt)/2;
|
|
|
|
ViewY += (ViewHgt-iOutHgt)/2;
|
|
|
|
// update output parameters
|
|
|
|
DrawX=iDrawX; DrawY=iDrawY;
|
|
|
|
OutX=iOutX; OutY=iOutY;
|
|
|
|
ViewWdt=iOutWdt; ViewHgt=iOutHgt;
|
2010-09-08 21:49:42 +00:00
|
|
|
InitZoom();
|
2009-05-08 13:28:41 +00:00
|
|
|
UpdateViewPosition();
|
|
|
|
// Reset menus
|
2009-08-15 18:50:32 +00:00
|
|
|
ResetMenuPositions=true;
|
2009-05-08 13:28:41 +00:00
|
|
|
// player uses mouse control? then clip the cursor
|
|
|
|
C4Player *pPlr;
|
2010-01-25 04:00:59 +00:00
|
|
|
if ((pPlr=::Players.Get(Player)))
|
2009-05-08 13:28:41 +00:00
|
|
|
if (pPlr->MouseControl)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-06-05 15:20:07 +00:00
|
|
|
::MouseControl.UpdateClip();
|
2009-05-08 13:28:41 +00:00
|
|
|
// and inform GUI
|
2010-10-29 23:47:50 +00:00
|
|
|
::pGUI->SetPreferredDlgRect(C4Rect(iOutX, iOutY, iOutWdt, iOutHgt));
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
void C4Viewport::ClearPointers(C4Object *pObj)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
Regions.ClearPointers(pObj);
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
void C4Viewport::NextPlayer()
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
C4Player *pPlr; int32_t iPlr;
|
2009-06-12 23:09:32 +00:00
|
|
|
if (!(pPlr = ::Players.Get(Player)))
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-06-12 23:09:32 +00:00
|
|
|
if (!(pPlr = ::Players.First)) return;
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
|
|
|
else if (!(pPlr = pPlr->Next))
|
|
|
|
if (Game.C4S.Head.Film && Game.C4S.Head.Replay)
|
|
|
|
pPlr = ::Players.First; // cycle to first in film mode only; in network obs mode allow NO_OWNER-view
|
2009-05-08 13:28:41 +00:00
|
|
|
if (pPlr) iPlr = pPlr->Number; else iPlr = NO_OWNER;
|
|
|
|
if (iPlr != Player) Init(iPlr, true);
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
bool C4Viewport::IsViewportMenu(class C4Menu *pMenu)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// check all associated menus
|
|
|
|
// Get player
|
2009-06-12 23:09:32 +00:00
|
|
|
C4Player *pPlr = ::Players.Get(Player);
|
2009-05-08 13:28:41 +00:00
|
|
|
// Player eliminated: No menu
|
|
|
|
if (pPlr && pPlr->Eliminated) return false;
|
|
|
|
// Player cursor object menu
|
|
|
|
if (pPlr && pPlr->Cursor && pPlr->Cursor->Menu == pMenu) return true;
|
|
|
|
// Player menu
|
|
|
|
if (pPlr && pPlr->Menu.IsActive() && &(pPlr->Menu) == pMenu) return true;
|
|
|
|
// Fullscreen menu (if active, only one viewport can exist)
|
|
|
|
if (FullScreen.pMenu && FullScreen.pMenu->IsActive() && FullScreen.pMenu == pMenu) return true;
|
|
|
|
// no match
|
|
|
|
return false;
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2010-09-29 01:44:05 +00:00
|
|
|
|
|
|
|
// C4ViewportList
|
|
|
|
|
|
|
|
C4ViewportList Viewports;
|
|
|
|
|
|
|
|
C4ViewportList::C4ViewportList():
|
|
|
|
FirstViewport(NULL)
|
|
|
|
{
|
|
|
|
ViewportArea.Default();
|
|
|
|
}
|
|
|
|
C4ViewportList::~C4ViewportList()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
void C4ViewportList::Clear()
|
|
|
|
{
|
|
|
|
C4Viewport *next;
|
|
|
|
while (FirstViewport)
|
|
|
|
{
|
|
|
|
next=FirstViewport->Next;
|
|
|
|
delete FirstViewport;
|
|
|
|
FirstViewport=next;
|
|
|
|
}
|
|
|
|
FirstViewport=NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void C4ViewportList::Execute(bool DrawBackground)
|
|
|
|
{
|
|
|
|
// Background redraw
|
|
|
|
if (DrawBackground)
|
|
|
|
DrawFullscreenBackground();
|
|
|
|
for (C4Viewport *cvp=FirstViewport; cvp; cvp=cvp->Next)
|
2010-12-11 18:50:38 +00:00
|
|
|
{
|
|
|
|
if (cvp->GetWindow())
|
|
|
|
cvp->GetWindow()->RequestUpdate();
|
2010-12-12 14:27:48 +00:00
|
|
|
else
|
|
|
|
cvp->Execute();
|
2010-12-11 18:50:38 +00:00
|
|
|
}
|
2010-09-29 01:44:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void C4ViewportList::DrawFullscreenBackground()
|
|
|
|
{
|
|
|
|
for (int i=0, iNum=BackgroundAreas.GetCount(); i<iNum; ++i)
|
|
|
|
{
|
|
|
|
const C4Rect &rc = BackgroundAreas.Get(i);
|
2011-10-03 14:30:18 +00:00
|
|
|
pDraw->BlitSurfaceTile(::GraphicsResource.fctBackground.Surface,FullScreen.pSurface,rc.x,rc.y,rc.Wdt,rc.Hgt,-rc.x,-rc.y);
|
2010-09-29 01:44:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool C4ViewportList::CloseViewport(C4Viewport * cvp)
|
|
|
|
{
|
|
|
|
if (!cvp) return false;
|
|
|
|
/*C4Viewport *next,*prev=NULL;
|
|
|
|
for (C4Viewport *cvp2=FirstViewport; cvp2; cvp2=next)
|
|
|
|
{
|
|
|
|
next=cvp2->Next;
|
|
|
|
if (cvp2 == cvp)
|
|
|
|
{
|
|
|
|
delete cvp;
|
|
|
|
StartSoundEffect("CloseViewport");
|
|
|
|
if (prev) prev->Next=next;
|
|
|
|
else FirstViewport=next;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
prev=cvp2;
|
|
|
|
}*/
|
|
|
|
// Chop the start of the chain off
|
|
|
|
if (FirstViewport == cvp)
|
|
|
|
{
|
|
|
|
FirstViewport = cvp->Next;
|
|
|
|
delete cvp;
|
|
|
|
StartSoundEffect("CloseViewport");
|
|
|
|
}
|
|
|
|
// Take out of the chain
|
|
|
|
else for (C4Viewport * prev = FirstViewport; prev; prev = prev->Next)
|
|
|
|
{
|
|
|
|
if (prev->Next == cvp)
|
|
|
|
{
|
|
|
|
prev->Next = cvp->Next;
|
|
|
|
delete cvp;
|
|
|
|
StartSoundEffect("CloseViewport");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Recalculate viewports
|
|
|
|
RecalculateViewports();
|
|
|
|
// Done
|
|
|
|
return true;
|
|
|
|
}
|
2012-03-23 21:53:56 +00:00
|
|
|
#ifdef USE_WIN32_WINDOWS
|
2010-09-29 01:44:05 +00:00
|
|
|
C4Viewport* C4ViewportList::GetViewport(HWND hwnd)
|
|
|
|
{
|
|
|
|
for (C4Viewport *cvp=FirstViewport; cvp; cvp=cvp->Next)
|
|
|
|
if (cvp->pWindow->hWindow==hwnd)
|
|
|
|
return cvp;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
bool C4ViewportList::CreateViewport(int32_t iPlayer, bool fSilent)
|
|
|
|
{
|
|
|
|
// Create and init new viewport, add to viewport list
|
|
|
|
int32_t iLastCount = GetViewportCount();
|
|
|
|
C4Viewport *nvp = new C4Viewport;
|
2012-03-04 21:45:00 +00:00
|
|
|
bool fOkay = nvp->Init(iPlayer, false);
|
2010-09-29 01:44:05 +00:00
|
|
|
if (!fOkay) { delete nvp; return false; }
|
|
|
|
C4Viewport *pLast;
|
|
|
|
for (pLast=FirstViewport; pLast && pLast->Next; pLast=pLast->Next) {}
|
|
|
|
if (pLast) pLast->Next=nvp; else FirstViewport=nvp;
|
|
|
|
// Recalculate viewports
|
|
|
|
RecalculateViewports();
|
|
|
|
// Viewports start off at centered position
|
|
|
|
nvp->CenterPosition();
|
|
|
|
// Action sound
|
|
|
|
if (GetViewportCount()!=iLastCount) if (!fSilent)
|
|
|
|
StartSoundEffect("CloseViewport");
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void C4ViewportList::ClearPointers(C4Object *pObj)
|
|
|
|
{
|
|
|
|
for (C4Viewport *cvp=FirstViewport; cvp; cvp=cvp->Next)
|
|
|
|
cvp->ClearPointers(pObj);
|
|
|
|
}
|
|
|
|
bool C4ViewportList::CloseViewport(int32_t iPlayer, bool fSilent)
|
|
|
|
{
|
|
|
|
// Close all matching viewports
|
|
|
|
int32_t iLastCount = GetViewportCount();
|
|
|
|
C4Viewport *next,*prev=NULL;
|
|
|
|
for (C4Viewport *cvp=FirstViewport; cvp; cvp=next)
|
|
|
|
{
|
|
|
|
next=cvp->Next;
|
|
|
|
if (cvp->Player==iPlayer || (iPlayer==NO_OWNER && cvp->fIsNoOwnerViewport))
|
|
|
|
{
|
|
|
|
delete cvp;
|
|
|
|
if (prev) prev->Next=next;
|
|
|
|
else FirstViewport=next;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
prev=cvp;
|
|
|
|
}
|
2012-10-13 19:36:14 +00:00
|
|
|
// Anything was done?
|
|
|
|
if (GetViewportCount()!=iLastCount)
|
|
|
|
{
|
|
|
|
// Recalculate viewports
|
|
|
|
RecalculateViewports();
|
|
|
|
// Action sound
|
|
|
|
if (!fSilent) StartSoundEffect("CloseViewport");
|
|
|
|
}
|
2010-09-29 01:44:05 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void C4ViewportList::RecalculateViewports()
|
|
|
|
{
|
|
|
|
|
|
|
|
// Fullscreen only
|
|
|
|
if (Application.isEditor) return;
|
|
|
|
|
|
|
|
// Sort viewports
|
|
|
|
SortViewportsByPlayerControl();
|
|
|
|
|
|
|
|
// Viewport area
|
2010-10-17 19:38:56 +00:00
|
|
|
int32_t iBorderTop = 0;
|
2010-09-29 01:44:05 +00:00
|
|
|
if (Config.Graphics.UpperBoard)
|
|
|
|
iBorderTop = C4UpperBoardHeight;
|
|
|
|
ViewportArea.Set(FullScreen.pSurface,0,iBorderTop, C4GUI::GetScreenWdt(), C4GUI::GetScreenHgt()-iBorderTop);
|
|
|
|
|
|
|
|
// Redraw flag
|
|
|
|
::GraphicsSystem.InvalidateBg();
|
|
|
|
#ifdef _WIN32
|
|
|
|
// reset mouse clipping
|
|
|
|
ClipCursor(NULL);
|
|
|
|
#else
|
|
|
|
// StdWindow handles this.
|
|
|
|
#endif
|
|
|
|
// reset GUI dlg pos
|
2010-10-29 23:47:50 +00:00
|
|
|
::pGUI->SetPreferredDlgRect(C4Rect(ViewportArea.X, ViewportArea.Y, ViewportArea.Wdt, ViewportArea.Hgt));
|
2010-09-29 01:44:05 +00:00
|
|
|
|
|
|
|
// fullscreen background: First, cover all of screen
|
|
|
|
BackgroundAreas.Clear();
|
|
|
|
BackgroundAreas.AddRect(C4Rect(ViewportArea.X, ViewportArea.Y, ViewportArea.Wdt, ViewportArea.Hgt));
|
|
|
|
|
|
|
|
// Viewports
|
|
|
|
C4Viewport *cvp;
|
|
|
|
int32_t iViews = 0;
|
|
|
|
for (cvp=FirstViewport; cvp; cvp=cvp->Next) iViews++;
|
|
|
|
if (!iViews) return;
|
|
|
|
int32_t iViewsH = (int32_t) sqrt(float(iViews));
|
|
|
|
int32_t iViewsX = iViews / iViewsH;
|
|
|
|
int32_t iViewsL = iViews % iViewsH;
|
|
|
|
int32_t cViewH,cViewX,ciViewsX;
|
|
|
|
int32_t cViewWdt,cViewHgt,cOffWdt,cOffHgt,cOffX,cOffY;
|
|
|
|
cvp=FirstViewport;
|
|
|
|
for (cViewH=0; cViewH<iViewsH; cViewH++)
|
|
|
|
{
|
|
|
|
ciViewsX = iViewsX; if (cViewH<iViewsL) ciViewsX++;
|
|
|
|
for (cViewX=0; cViewX<ciViewsX; cViewX++)
|
|
|
|
{
|
|
|
|
cViewWdt = ViewportArea.Wdt/ciViewsX;
|
|
|
|
cViewHgt = ViewportArea.Hgt/iViewsH;
|
|
|
|
cOffX = ViewportArea.X;
|
|
|
|
cOffY = ViewportArea.Y;
|
|
|
|
cOffWdt = cOffHgt = 0;
|
|
|
|
if (ciViewsX * cViewWdt < ViewportArea.Wdt)
|
|
|
|
cOffX = (ViewportArea.Wdt - ciViewsX * cViewWdt) / 2;
|
|
|
|
if (iViewsH * cViewHgt < ViewportArea.Hgt)
|
|
|
|
cOffY = (ViewportArea.Hgt - iViewsH * cViewHgt) / 2 + ViewportArea.Y;
|
|
|
|
if (Config.Graphics.SplitscreenDividers)
|
|
|
|
{
|
|
|
|
if (cViewX < ciViewsX - 1) cOffWdt=4;
|
|
|
|
if (cViewH < iViewsH - 1) cOffHgt=4;
|
|
|
|
}
|
|
|
|
int32_t coViewWdt=cViewWdt-cOffWdt;
|
|
|
|
int32_t coViewHgt=cViewHgt-cOffHgt;
|
|
|
|
C4Rect rcOut(cOffX+cViewX*cViewWdt, cOffY+cViewH*cViewHgt, coViewWdt, coViewHgt);
|
|
|
|
cvp->SetOutputSize(rcOut.x,rcOut.y,rcOut.x,rcOut.y,rcOut.Wdt,rcOut.Hgt);
|
|
|
|
cvp=cvp->Next;
|
|
|
|
// clip down area avaiable for background drawing
|
|
|
|
BackgroundAreas.ClipByRect(rcOut);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t C4ViewportList::GetViewportCount()
|
|
|
|
{
|
|
|
|
int32_t iResult = 0;
|
|
|
|
for (C4Viewport *cvp=FirstViewport; cvp; cvp=cvp->Next) iResult++;
|
|
|
|
return iResult;
|
|
|
|
}
|
|
|
|
|
2010-12-12 21:38:19 +00:00
|
|
|
C4Viewport* C4ViewportList::GetViewport(int32_t iPlayer, C4Viewport* pPrev)
|
2010-09-29 01:44:05 +00:00
|
|
|
{
|
2010-12-12 21:38:19 +00:00
|
|
|
for (C4Viewport *cvp=pPrev ? pPrev->Next : FirstViewport; cvp; cvp=cvp->Next)
|
2010-09-29 01:44:05 +00:00
|
|
|
if (cvp->Player==iPlayer || (iPlayer==NO_OWNER && cvp->fIsNoOwnerViewport))
|
|
|
|
return cvp;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t C4ViewportList::GetAudibility(int32_t iX, int32_t iY, int32_t *iPan, int32_t iAudibilityRadius)
|
|
|
|
{
|
|
|
|
// default audibility radius
|
|
|
|
if (!iAudibilityRadius) iAudibilityRadius = C4AudibilityRadius;
|
|
|
|
// Accumulate audibility by viewports
|
|
|
|
int32_t iAudible=0; *iPan = 0;
|
|
|
|
for (C4Viewport *cvp=FirstViewport; cvp; cvp=cvp->Next)
|
|
|
|
{
|
|
|
|
iAudible = Max( iAudible,
|
|
|
|
BoundBy<int32_t>(100-100*Distance(cvp->ViewX+cvp->ViewWdt/2,cvp->ViewY+cvp->ViewHgt/2,iX,iY)/C4AudibilityRadius,0,100) );
|
|
|
|
*iPan += (iX-(cvp->ViewX+cvp->ViewWdt/2)) / 5;
|
|
|
|
}
|
|
|
|
*iPan = BoundBy<int32_t>(*iPan, -100, 100);
|
|
|
|
return iAudible;
|
|
|
|
}
|
|
|
|
|
|
|
|
void C4ViewportList::SortViewportsByPlayerControl()
|
|
|
|
{
|
|
|
|
|
|
|
|
// Sort
|
|
|
|
bool fSorted;
|
|
|
|
C4Player *pPlr1,*pPlr2;
|
|
|
|
C4Viewport *pView,*pNext,*pPrev;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
fSorted = true;
|
|
|
|
for (pPrev=NULL,pView=FirstViewport; pView && (pNext = pView->Next); pView=pNext)
|
|
|
|
{
|
|
|
|
// Get players
|
|
|
|
pPlr1 = ::Players.Get(pView->Player);
|
|
|
|
pPlr2 = ::Players.Get(pNext->Player);
|
|
|
|
// Swap order
|
|
|
|
if (pPlr1 && pPlr2 && pPlr1->ControlSet && pPlr2->ControlSet && ( pPlr1->ControlSet->GetLayoutOrder() > pPlr2->ControlSet->GetLayoutOrder() ))
|
|
|
|
{
|
|
|
|
if (pPrev) pPrev->Next = pNext; else FirstViewport = pNext;
|
|
|
|
pView->Next = pNext->Next;
|
|
|
|
pNext->Next = pView;
|
|
|
|
pPrev = pNext;
|
|
|
|
pNext = pView;
|
|
|
|
fSorted = false;
|
|
|
|
}
|
|
|
|
// Don't swap
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pPrev = pView;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while (!fSorted);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
bool C4ViewportList::ViewportNextPlayer()
|
|
|
|
{
|
|
|
|
// safety: switch valid?
|
|
|
|
if ((!Game.C4S.Head.Film || !Game.C4S.Head.Replay) && !GetViewport(NO_OWNER)) return false;
|
|
|
|
// do switch then
|
|
|
|
C4Viewport *vp = GetFirstViewport();
|
|
|
|
if (!vp) return false;
|
|
|
|
vp->NextPlayer();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool C4ViewportList::FreeScroll(C4Vec2D vScrollBy)
|
|
|
|
{
|
|
|
|
// safety: move valid?
|
|
|
|
if ((!Game.C4S.Head.Replay || !Game.C4S.Head.Film) && !GetViewport(NO_OWNER)) return false;
|
|
|
|
C4Viewport *vp = GetFirstViewport();
|
|
|
|
if (!vp) return false;
|
|
|
|
// move then (old static code crap...)
|
|
|
|
static int32_t vp_vx=0; static int32_t vp_vy=0; static int32_t vp_vf=0;
|
|
|
|
int32_t dx=vScrollBy.x; int32_t dy=vScrollBy.y;
|
|
|
|
if (Game.FrameCounter-vp_vf < 5)
|
|
|
|
{ dx += vp_vx; dy += vp_vy; }
|
|
|
|
vp_vx=dx; vp_vy=dy; vp_vf=Game.FrameCounter;
|
|
|
|
vp->ViewX+=dx; vp->ViewY+=dy;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool C4ViewportList::ViewportZoomOut()
|
|
|
|
{
|
|
|
|
for (C4Viewport *vp = FirstViewport; vp; vp = vp->Next) vp->ChangeZoom(1.0f/C4GFX_ZoomStep);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool C4ViewportList::ViewportZoomIn()
|
|
|
|
{
|
|
|
|
for (C4Viewport *vp = FirstViewport; vp; vp = vp->Next) vp->ChangeZoom(C4GFX_ZoomStep);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void C4ViewportList::MouseMoveToViewport(int32_t iButton, int32_t iX, int32_t iY, DWORD dwKeyParam)
|
|
|
|
{
|
|
|
|
// Pass on to mouse controlled viewport
|
|
|
|
for (C4Viewport *cvp=FirstViewport; cvp; cvp=cvp->Next)
|
|
|
|
if (::MouseControl.IsViewport(cvp))
|
|
|
|
::MouseControl.Move( iButton,
|
|
|
|
BoundBy<int32_t>(iX-cvp->OutX,0,cvp->ViewWdt-1),
|
|
|
|
BoundBy<int32_t>(iY-cvp->OutY,0,cvp->ViewHgt-1),
|
|
|
|
dwKeyParam );
|
|
|
|
}
|