minimap.cpp
来自「这是整套横扫千军3D版游戏的源码」· C++ 代码 · 共 1,537 行 · 第 1/3 页
CPP
1,537 行
// MiniMap.cpp: implementation of the CMiniMap class.
//
//////////////////////////////////////////////////////////////////////
#include "StdAfx.h"
#include <SDL_keysym.h>
#include <SDL_mouse.h>
#include <SDL_types.h>
#include "CommandColors.h"
#include "CursorIcons.h"
#include "ExternalAI/Group.h"
#include "Game/Camera/CameraController.h"
#include "Game/Camera.h"
#include "Game/CameraHandler.h"
#include "Game/GameHelper.h"
#include "Game/Player.h"
#include "Game/SelectedUnits.h"
#include "Game/Team.h"
#include "GuiHandler.h"
#include "Lua/LuaCallInHandler.h"
#include "Lua/LuaUnsyncedCtrl.h"
#include "Map/BaseGroundDrawer.h"
#include "Map/Ground.h"
#include "Map/MapDamage.h"
#include "Map/MetalMap.h"
#include "Map/ReadMap.h"
#include "MiniMap.h"
#include "MouseHandler.h"
#include "Platform/ConfigHandler.h"
#include "Rendering/GL/glExtra.h"
#include "Rendering/GL/myGL.h"
#include "Rendering/IconHandler.h"
#include "Rendering/Textures/Bitmap.h"
#include "Sim/Misc/LosHandler.h"
#include "Sim/Misc/RadarHandler.h"
#include "Sim/Projectiles/PieceProjectile.h"
#include "Sim/Projectiles/Projectile.h"
#include "Sim/Projectiles/ProjectileHandler.h"
#include "Sim/Projectiles/Unsynced/GeoThermSmokeProjectile.h"
#include "Sim/Projectiles/Unsynced/GfxProjectile.h"
#include "Sim/Projectiles/Unsynced/WreckProjectile.h"
#include "Sim/Projectiles/WeaponProjectiles/BeamLaserProjectile.h"
#include "Sim/Projectiles/WeaponProjectiles/LargeBeamLaserProjectile.h"
#include "Sim/Projectiles/WeaponProjectiles/LightingProjectile.h"
#include "Sim/Projectiles/WeaponProjectiles/WeaponProjectile.h"
#include "Sim/Units/CommandAI/CommandAI.h"
#include "Sim/Units/CommandAI/LineDrawer.h"
#include "Sim/Units/Unit.h"
#include "Sim/Units/UnitHandler.h"
#include "Sim/Units/UnitTracker.h"
#include "Sim/Weapons/WeaponDefHandler.h"
#include "Sim/Weapons/Weapon.h"
#include "System/FileSystem/SimpleParser.h"
#include "System/Sound.h"
#include "TimeProfiler.h"
#include "TooltipConsole.h"
#include "mmgr.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CMiniMap* minimap = NULL;
extern Uint8* keys;
CMiniMap::CMiniMap()
: CInputReceiver(BACK),
fullProxy(false),
proxyMode(false),
selecting(false),
mouseMove(false),
mouseResize(false),
mouseLook(false),
maxspect(false),
maximized(false),
minimized(false),
showButtons(false),
useIcons(true),
slaveDrawMode(false)
{
lastWindowSizeX = gu->viewSizeX;
lastWindowSizeY = gu->viewSizeY;
if (gu->dualScreenMode) {
width = gu->viewSizeX;
height = gu->viewSizeY;
xpos = (gu->viewSizeX - gu->viewPosX);
ypos = 0;
}
else {
const std::string geodef = "2 2 200 200";
const std::string geo = configHandler.GetString("MiniMapGeometry", geodef);
ParseGeometry(geo);
}
fullProxy = !!configHandler.GetInt("MiniMapFullProxy", 1);
buttonSize = configHandler.GetInt("MiniMapButtonSize", 16);
unitBaseSize =
atof(configHandler.GetString("MiniMapUnitSize", "2.5").c_str());
unitBaseSize = max(0.0f, unitBaseSize);
unitExponent =
atof(configHandler.GetString("MiniMapUnitExp", "0.25").c_str());
cursorScale =
atof(configHandler.GetString("MiniMapCursorScale", "-0.5").c_str());
useIcons = !!configHandler.GetInt("MiniMapIcons", 1);
drawCommands = max(0, configHandler.GetInt("MiniMapDrawCommands", 1));
simpleColors = !!configHandler.GetInt("SimpleMiniMapColors", 0);
myColor[0] = (unsigned char)(0.2f * 255);
myColor[1] = (unsigned char)(0.9f * 255);
myColor[2] = (unsigned char)(0.2f * 255);
myColor[3] = (unsigned char)(1.0f * 255);
allyColor[0] = (unsigned char)(0.3f * 255);
allyColor[1] = (unsigned char)(0.3f * 255);
allyColor[2] = (unsigned char)(0.9f * 255);
allyColor[3] = (unsigned char)(1.0f * 255);
enemyColor[0] = (unsigned char)(0.9f * 255);
enemyColor[1] = (unsigned char)(0.2f * 255);
enemyColor[2] = (unsigned char)(0.2f * 255);
enemyColor[3] = (unsigned char)(1.0f * 255);
UpdateGeometry();
circleLists = glGenLists(circleListsCount);
for (int cl = 0; cl < circleListsCount; cl++) {
glNewList(circleLists + cl, GL_COMPILE);
glBegin(GL_LINE_LOOP);
const int divs = (1 << (cl + 3));
for (int d = 0; d < divs; d++) {
const float rads = float(2.0 * PI) * float(d) / float(divs);
glVertex3f(sin(rads), 0.0f, cos(rads));
}
glEnd();
glEndList();
}
// setup the buttons' texture and texture coordinates
buttonsTexture = 0;
CBitmap bitmap;
bool unfiltered = false;
if (bitmap.Load("bitmaps/minimapbuttons.png")) {
if ((bitmap.ysize == buttonSize) && (bitmap.xsize == (buttonSize * 4))) {
unfiltered = true;
}
glGenTextures(1, &buttonsTexture);
glBindTexture(GL_TEXTURE_2D, buttonsTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8,
bitmap.xsize, bitmap.ysize, 0,
GL_RGBA, GL_UNSIGNED_BYTE, bitmap.mem);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
if (unfiltered) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
} else {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}
glBindTexture(GL_TEXTURE_2D, 0);
}
const float xshift = unfiltered ? 0.0f : (0.5f / bitmap.xsize);
const float yshift = unfiltered ? 0.0f : (0.5f / bitmap.ysize);
moveBox.xminTx = 0.50f + xshift;
moveBox.xmaxTx = 0.75f - xshift;
resizeBox.xminTx = 0.75f + xshift;
resizeBox.xmaxTx = 1.00f - xshift;
minimizeBox.xminTx = 0.00f + xshift;
minimizeBox.xmaxTx = 0.25f - xshift;
maximizeBox.xminTx = 0.25f + xshift;
maximizeBox.xmaxTx = 0.50f - xshift;
moveBox.yminTx = 1.00f - yshift;
resizeBox.yminTx = 1.00f - yshift;
minimizeBox.yminTx = 1.00f - yshift;
maximizeBox.yminTx = 1.00f - yshift;
moveBox.ymaxTx = 0.00f + yshift;
resizeBox.ymaxTx = 0.00f + yshift;
minimizeBox.ymaxTx = 0.00f + yshift;
maximizeBox.ymaxTx = 0.00f + yshift;
}
CMiniMap::~CMiniMap()
{
glDeleteLists(circleLists, circleListsCount);
}
void CMiniMap::ParseGeometry(const string& geostr)
{
const std::string geodef = "2 2 200 200";
const int scanned = sscanf(geostr.c_str(), "%i %i %i %i",
&xpos, &ypos, &width, &height);
const bool userGeo = ((scanned != 4) || (geostr != geodef));
if (!userGeo) {
xpos = 2;
ypos = 2;
width = -200;
height = -200;
} else {
if (width <= 0) {
width = -200;
}
if (height <= 0) {
height = -200;
}
}
if ((width <= 0) && (height <= 0)) {
const float hw = sqrt(float(gs->mapx) / float(gs->mapy));
width = (int)(-width * hw);
height = (int)(-height / hw);
}
else if (width <= 0) {
width = (int)(float(height) * float(gs->mapx) / float(gs->mapy));
}
else if (height <= 0) {
height = (int)(float(width) * float(gs->mapy) / float(gs->mapx));
}
// convert to GL coords with a top-left corner affinity
ypos = gu->viewSizeY - height - ypos;
}
void CMiniMap::ToggleMaximized(bool _maxspect)
{
if (maximized) {
xpos = oldxpos;
ypos = oldypos;
width = oldwidth;
height = oldheight;
}
else {
oldxpos = xpos;
oldypos = ypos;
oldwidth = width;
oldheight = height;
maxspect = _maxspect;
SetMaximizedGeometry();
}
maximized = !maximized;
UpdateGeometry();
}
void CMiniMap::SetMaximizedGeometry()
{
if (!maxspect) {
height = gu->viewSizeY;
width = height;
xpos = (gu->viewSizeX - gu->viewSizeY) / 2;
ypos = 0;
}
else {
const float mapRatio = (float)gs->mapx / (float)gs->mapy;
const float viewRatio = (float)gu->viewSizeX / (float)gu->viewSizeY;
if (mapRatio > viewRatio) {
xpos = 0;
width = gu->viewSizeX;
height = int((float)gu->viewSizeX / mapRatio);
ypos = (gu->viewSizeY - height) / 2;
} else {
ypos = 0;
height = gu->viewSizeY;
width = int((float)gu->viewSizeY * mapRatio);
xpos = (gu->viewSizeX - width) / 2;
}
}
}
/******************************************************************************/
void CMiniMap::SetSlaveMode(bool newMode)
{
if (newMode) {
proxyMode = false;
selecting = false;
maxspect = false;
maximized = false;
minimized = false;
mouseLook = false;
mouseMove = false;
mouseResize = false;
}
static int oldButtonSize = 16;
if (newMode != slaveDrawMode) {
if (newMode) {
oldButtonSize = buttonSize;
buttonSize = 0;
} else {
buttonSize = oldButtonSize;
}
}
slaveDrawMode = newMode;
UpdateGeometry();
}
void CMiniMap::ConfigCommand(const std::string& line)
{
const vector<string> words = CSimpleParser::Tokenize(line, 1);
if (words.empty()) {
return;
}
const string command = StringToLower(words[0]);
if (command == "fullproxy") {
if (words.size() >= 2) {
fullProxy = !!atoi(words[1].c_str());
} else {
fullProxy = !fullProxy;
}
}
else if (command == "icons") {
if (words.size() >= 2) {
useIcons = !!atoi(words[1].c_str());
} else {
useIcons = !useIcons;
}
}
else if (command == "unitexp") {
if (words.size() >= 2) {
unitExponent = atof(words[1].c_str());
}
UpdateGeometry();
}
else if (command == "unitsize") {
if (words.size() >= 2) {
unitBaseSize = atof(words[1].c_str());
}
unitBaseSize = max(0.0f, unitBaseSize);
UpdateGeometry();
}
else if (command == "drawcommands") {
if (words.size() >= 2) {
drawCommands = max(0, atoi(words[1].c_str()));
} else {
drawCommands = (drawCommands > 0) ? 0 : 1;
}
}
else if (command == "simplecolors") {
if (words.size() >= 2) {
simpleColors = !!atoi(words[1].c_str());
} else {
simpleColors = !simpleColors;
}
}
// the following commands can not be used in dualscreen mode
if (gu->dualScreenMode) {
return;
}
if ((command == "geo") || (command == "geometry")) {
if (words.size() < 2) {
return;
}
ParseGeometry(words[1]);
UpdateGeometry();
}
else if ((command == "min") || (command == "minimize")) {
if (words.size() >= 2) {
minimized = !!atoi(words[1].c_str());
} else {
minimized = !minimized;
}
}
else if ((command == "max") ||
(command == "maximize") || (command == "maxspect")) {
bool newMax = maximized;
if (words.size() >= 2) {
newMax = !!atoi(words[1].c_str());
} else {
newMax = !newMax;
}
if (newMax != maximized) {
ToggleMaximized(command == "maxspect");
}
}
}
/******************************************************************************/
bool CMiniMap::MousePress(int x, int y, int button)
{
if (minimized) {
if ((x < buttonSize) && (y < buttonSize)) {
minimized = false;
return true;
} else {
return false;
}
}
const bool inMap = mapBox.Inside(x, y);
const bool inButtons = buttonBox.Inside(x, y);
if (!inMap && !inButtons) {
return false;
}
if (button == SDL_BUTTON_LEFT) {
if (inMap && (guihandler->inCommand >= 0)) {
proxyMode = true;
ProxyMousePress(x, y, button);
return true;
}
if (showButtons && inButtons) {
if (moveBox.Inside(x, y)) {
mouseMove = true;
return true;
}
else if (resizeBox.Inside(x, y)) {
mouseResize = true;
return true;
}
else if (minimizeBox.Inside(x, y) ||
maximizeBox.Inside(x, y)) {
return true;
}
}
if (inMap && !mouse->buttons[SDL_BUTTON_LEFT].chorded) {
selecting = true;
return true;
}
}
else if (inMap) {
if ((fullProxy && (button == SDL_BUTTON_MIDDLE)) ||
(!fullProxy && (button == SDL_BUTTON_RIGHT))) {
MoveView(x, y);
mouseLook = true;
return true;
}
else if (fullProxy && (button == SDL_BUTTON_RIGHT)) {
proxyMode = true;
ProxyMousePress(x, y, button);
return true;
}
}
return false;
}
void CMiniMap::MouseMove(int x, int y, int dx, int dy, int button)
{
if (mouseMove) {
xpos += dx;
ypos -= dy;
xpos = max(0, xpos);
if (gu->dualScreenMode) {
xpos = min((2 * gu->viewSizeX) - width, xpos);
} else {
xpos = min(gu->viewSizeX - width, xpos);
}
ypos = max(5, min(gu->viewSizeY - height, ypos));
UpdateGeometry();
return;
}
if (mouseResize) {
ypos -= dy;
width += dx;
height += dy;
height = min(gu->viewSizeY, height);
if (gu->dualScreenMode) {
width = min(2 * gu->viewSizeX, width);
} else {
width = min(gu->viewSizeX, width);
}
if (keys[SDLK_LSHIFT]) {
width = (height * gs->mapx) / gs->mapy;
}
width = max(5, width);
height = max(5, height);
ypos = min(gu->viewSizeY - height, ypos);
UpdateGeometry();
return;
}
if (mouseLook && mapBox.Inside(x, y)) {
MoveView(x,y);
return;
}
}
void CMiniMap::MouseRelease(int x, int y, int button)
{
if (mouseMove || mouseResize || mouseLook) {
mouseMove = false;
mouseResize = false;
mouseLook = false;
proxyMode = false;
return;
}
if (proxyMode) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?