guihandler.cpp

来自「这是整套横扫千军3D版游戏的源码」· C++ 代码 · 共 2,423 行 · 第 1/5 页

CPP
2,423
字号
#include "StdAfx.h"
// GuiHandler.cpp: implementation of the CGuiHandler class.
//
//////////////////////////////////////////////////////////////////////

#include "GuiHandler.h"
#include <map>
#include <set>
#include <list>
#include "SDL_keysym.h"
#include "SDL_mouse.h"
#include "CommandColors.h"
#include "KeyBindings.h"
#include "KeyCodes.h"
#include "LuaUI.h"
#include "MiniMap.h"
#include "MouseHandler.h"
#include "OutlineFont.h"
#include "Game/Camera.h"
#include "Game/Game.h"
#include "Game/GameHelper.h"
#include "Game/SelectedUnits.h"
#include "Map/BaseGroundDrawer.h"
#include "Map/Ground.h"
#include "Rendering/glFont.h"
#include "Rendering/GL/glExtra.h"
#include "Rendering/GL/glList.h"
#include "Rendering/GL/myGL.h"
#include "Rendering/Textures/Bitmap.h"
#include "Rendering/Textures/NamedTextures.h"
#include "Rendering/Textures/TextureHandler.h"
#include "Rendering/UnitModels/3DOParser.h"
#include "Rendering/UnitModels/UnitDrawer.h"
#include "Sim/Misc/Feature.h"
#include "Sim/Misc/LosHandler.h"
#include "Sim/Units/CommandAI/CommandAI.h"
#include "Sim/Units/CommandAI/BuilderCAI.h"
#include "Sim/Units/UnitDefHandler.h"
#include "Sim/Units/Unit.h"
#include "Sim/Units/UnitHandler.h"
#include "Sim/Units/UnitLoader.h"
#include "Sim/Weapons/WeaponDefHandler.h"
#include "Sim/Weapons/Weapon.h"
#include "System/FileSystem/SimpleParser.h"
#include "System/LogOutput.h"
#include "System/Platform/ConfigHandler.h"
#include "mmgr.h"

extern Uint8 *keys;


//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////


CGuiHandler* guihandler = NULL;


const char* CGuiHandler::luaUiFile = "gui.lua";


CGuiHandler::CGuiHandler()
: firstLayout(true),
  inCommand(-1),
  activeMousePress(false),
	forceLayoutUpdate(false),
  defaultCmdMemory(-1),
  needShift(false),
  maxPage(0),
  activePage(0),
  showingMetal(false),
  buildSpacing(0),
  buildFacing(0),
  actionOffset(0),
  luaUIClick(false),
  gatherMode(false)
{
	icons = SAFE_NEW IconInfo[16];
	iconsSize = 16;
	iconsCount = 0;

	LoadConfig("ctrlpanel.txt");

  miniMapMarker = !!configHandler.GetInt("MiniMapMarker", 1);

  invertQueueKey = !!configHandler.GetInt("InvertQueueKey", 0);

	readmap->mapDefParser.GetDef(autoShowMetal, "1", "MAP\\autoShowMetal");

	useStencil = false;
	if (GLEW_NV_depth_clamp && !!configHandler.GetInt("StencilBufferBits", 1)) {
		GLint stencilBits;
		glGetIntegerv(GL_STENCIL_BITS, &stencilBits);
		useStencil = (stencilBits >= 1);
	}
}


CGuiHandler::~CGuiHandler()
{
	CLuaUI::FreeHandler();

	delete[] icons;

	std::map<std::string, unsigned int>::iterator it;
	for (it = textureMap.begin(); it != textureMap.end(); ++it) {
		const GLuint texID = it->second;
		glDeleteTextures (1, &texID);
	}
}


bool CGuiHandler::GetQueueKeystate() const
{
	return (!invertQueueKey && keys[SDLK_LSHIFT]) ||
	       (invertQueueKey && !keys[SDLK_LSHIFT]);
}


void CGuiHandler::LoadDefaults()
{
	xIcons = 2;
	yIcons = 8;

	xPos        = 0.000f;
	yPos        = 0.175f;
	xIconSize   = 0.060f;
	yIconSize   = 0.060f;
	textBorder  = 0.003f;
	iconBorder  = 0.003f;
	frameBorder = 0.003f;

	xSelectionPos = 0.018f;
	ySelectionPos = 0.127f;

	frameAlpha = -1.0f;
	textureAlpha = 0.8f;

	dropShadows = true;
	useOptionLEDs = true;

	selectGaps = true;
	selectThrough = false;

	menuName = "";

	outlineFont.Enable(false);

	attackRect = true;
	newAttackMode = true;
	invColorSelect = true;
	frontByEnds = false;
}


static bool SafeAtoF(float& var, const string& value)
{
	char* endPtr;
	const char* startPtr = value.c_str();
	const float tmp = (float)strtod(startPtr, &endPtr);
	if (endPtr == startPtr) {
		return false;
	}
	var = tmp;
	return true;
}


bool CGuiHandler::LoadConfig(const std::string& filename)
{
	LoadDefaults();

	CFileHandler ifs(filename);
	CSimpleParser parser(ifs);

	string deadStr = "";
	string prevStr = "";
	string nextStr = "";
	string fillOrderStr = "";

	while (true) {
		const string line = parser.GetCleanLine();
		if (line.empty()) {
			break;
		}

		vector<string> words = parser.Tokenize(line, 1);

		const string command = StringToLower(words[0]);

		if ((command == "dropshadows") && (words.size() > 1)) {
			dropShadows = !!atoi(words[1].c_str());
		}
		else if ((command == "useoptionleds") && (words.size() > 1)) {
			useOptionLEDs = !!atoi(words[1].c_str());
		}
		else if ((command == "selectgaps") && (words.size() > 1)) {
			selectGaps = !!atoi(words[1].c_str());
		}
		else if ((command == "selectthrough") && (words.size() > 1)) {
			selectThrough = !!atoi(words[1].c_str());
		}
		else if ((command == "deadiconslot") && (words.size() > 1)) {
			deadStr = StringToLower(words[1]);
		}
		else if ((command == "prevpageslot") && (words.size() > 1)) {
			prevStr = StringToLower(words[1]);
		}
		else if ((command == "nextpageslot") && (words.size() > 1)) {
			nextStr = StringToLower(words[1]);
		}
		else if ((command == "fillorder") && (words.size() > 1)) {
			fillOrderStr = StringToLower(words[1]);
		}
		else if ((command == "xicons") && (words.size() > 1)) {
			xIcons = atoi(words[1].c_str());
		}
		else if ((command == "yicons") && (words.size() > 1)) {
			yIcons = atoi(words[1].c_str());
		}
		else if ((command == "xiconsize") && (words.size() > 1)) {
			SafeAtoF(xIconSize, words[1]);
		}
		else if ((command == "yiconsize") && (words.size() > 1)) {
			SafeAtoF(yIconSize, words[1]);
		}
		else if ((command == "xpos") && (words.size() > 1)) {
			SafeAtoF(xPos, words[1]);
		}
		else if ((command == "ypos") && (words.size() > 1)) {
			SafeAtoF(yPos, words[1]);
		}
		else if ((command == "textborder") && (words.size() > 1)) {
			SafeAtoF(textBorder, words[1]);
		}
		else if ((command == "iconborder") && (words.size() > 1)) {
			SafeAtoF(iconBorder, words[1]);
		}
		else if ((command == "frameborder") && (words.size() > 1)) {
			SafeAtoF(frameBorder, words[1]);
		}
		else if ((command == "xselectionpos") && (words.size() > 1)) {
			SafeAtoF(xSelectionPos, words[1]);
		}
		else if ((command == "yselectionpos") && (words.size() > 1)) {
			SafeAtoF(ySelectionPos, words[1]);
		}
		else if ((command == "framealpha") && (words.size() > 1)) {
			SafeAtoF(frameAlpha, words[1]);
		}
		else if ((command == "texturealpha") && (words.size() > 1)) {
			SafeAtoF(textureAlpha, words[1]);
		}
		else if ((command == "outlinefont") && (words.size() > 1)) {
			outlineFont.Enable(!!atoi(words[1].c_str()));
		}
		else if ((command == "attackrect") && (words.size() > 1)) {
			attackRect = !!atoi(words[1].c_str());
		}
		else if ((command == "newattackmode") && (words.size() > 1)) {
			newAttackMode = !!atoi(words[1].c_str());
		}
		else if ((command == "invcolorselect") && (words.size() > 1)) {
			invColorSelect = !!atoi(words[1].c_str());
		}
		else if ((command == "frontbyends") && (words.size() > 1)) {
			frontByEnds = !!atoi(words[1].c_str());
		}
	}

	// sane clamps
	xIcons      = max(2,      xIcons);
	yIcons      = max(2,      yIcons);
	xIconSize   = max(0.010f, xIconSize);
	yIconSize   = max(0.010f, yIconSize);
	iconBorder  = max(0.0f,   iconBorder);
	frameBorder = max(0.0f,   frameBorder);

	xIconStep = xIconSize + (iconBorder * 2.0f);
	yIconStep = yIconSize + (iconBorder * 2.0f);

	iconsPerPage = (xIcons * yIcons);

	buttonBox.x1 = xPos;
	buttonBox.x2 = xPos + (frameBorder * 2.0f) + (xIcons * xIconStep);
	buttonBox.y1 = yPos;
	buttonBox.y2 = yPos + (frameBorder * 2.0f) + (yIcons * yIconStep);

	if (!deadStr.empty()) {
		deadIconSlot = ParseIconSlot(deadStr);
	}	else {
		deadIconSlot = -1;
	}

	if (!prevStr.empty() && (prevStr != "auto")) {
		if (prevStr == "none") {
			prevPageSlot = -1;
		} else {
			prevPageSlot = ParseIconSlot(prevStr);
		}
	}	else {
		prevPageSlot = iconsPerPage - 2;
	}

	if (!nextStr.empty() && (nextStr != "auto")) {
		if (nextStr == "none") {
			nextPageSlot = -1;
		} else {
			nextPageSlot = ParseIconSlot(nextStr);
		}
	}	else {
		nextPageSlot = iconsPerPage - 1;
	}

	if (deadIconSlot >= 0) {
		const float fullBorder = frameBorder + iconBorder;
		const float fx = (float)(deadIconSlot % xIcons);
		const float fy = (float)(deadIconSlot / xIcons);
		xBpos = buttonBox.x1 + (fullBorder + (0.5 * xIconSize) + (fx * xIconStep));
		yBpos = buttonBox.y2 - (fullBorder + (0.5 * yIconSize) + (fy * yIconStep));
	}
	else if ((prevPageSlot >= 0) && (nextPageSlot >= 0)) {
		// place in the middle of adjacent paging icons
		const int delta = abs(prevPageSlot - nextPageSlot);
		if ((delta == 1) || (delta == xIcons)) {
			const float fullBorder = frameBorder + iconBorder;
			const float fxp = (float)(prevPageSlot % xIcons);
			const float fyp = (float)(prevPageSlot / xIcons);
			const float fxn = (float)(nextPageSlot % xIcons);
			const float fyn = (float)(nextPageSlot / xIcons);
			const float fx = 0.5f * (fxp + fxn);
			const float fy = 0.5f * (fyp + fyn);
			xBpos = buttonBox.x1 + (fullBorder + (0.5 * xIconSize) + (fx * xIconStep));
			yBpos = buttonBox.y2 - (fullBorder + (0.5 * yIconSize) + (fy * yIconStep));
		}
		else {
			xBpos = yBpos = -1.0f; // off screen
		}
	}
	else {
		xBpos = yBpos = -1.0f; // off screen
	}

	ParseFillOrder(fillOrderStr);

	return true;
}


void CGuiHandler::ParseFillOrder(const std::string& text)
{
	// setup the default order
	fillOrder.clear();
	for (int i = 0; i < iconsPerPage; i++) {
		fillOrder.push_back(i);
	}

	// split the string into slot names
	std::vector<std::string> slotNames = CSimpleParser::Tokenize(text, 0);
	if ((int)slotNames.size() != iconsPerPage) {
		return;
	}

	std::set<int>    slotSet;
	std::vector<int> slotVec;
	for (int s = 0; s < iconsPerPage; s++) {
		const int slotNumber = ParseIconSlot(slotNames[s]);
		if ((slotNumber < 0) || (slotNumber >= iconsPerPage) ||
				(slotSet.find(slotNumber) != slotSet.end())) {
			return;
		}
		slotSet.insert(slotNumber);
		slotVec.push_back(slotNumber);
	}

	fillOrder = slotVec;
}


int CGuiHandler::ParseIconSlot(const std::string& text) const
{
	const char rowLetter = tolower(text[0]);
	if ((rowLetter < 'a') || (rowLetter > 'z')) {
		return -1;
	}
	const int row = rowLetter - 'a';
	if (row >= yIcons) {
		return -1;
	}

	char* endPtr;
	const char* startPtr = text.c_str() + 1;
	int column = strtol(startPtr, &endPtr, 10);
	if ((endPtr == startPtr) || (column < 0) || (column >= xIcons)) {
		return -1;
	}

	return (row * xIcons) + column;
}


bool CGuiHandler::ReloadConfig(const string& filename)
{
	LoadConfig(filename);
	activePage = 0;
	selectedUnits.SetCommandPage(activePage);
	LayoutIcons(false);
	return true;
}


void CGuiHandler::ResizeIconArray(unsigned int size)
{
	int minIconsSize = iconsSize;
	while (minIconsSize < size) {
		minIconsSize *= 2;
	}
	if (iconsSize < minIconsSize) {
		iconsSize = minIconsSize;
		delete[] icons;
		icons = SAFE_NEW IconInfo[iconsSize];
	}
}


void CGuiHandler::AppendPrevAndNext(vector<CommandDescription>& cmds)
{
	CommandDescription cd;

	cd.id=CMD_INTERNAL;
	cd.action="prevmenu";
	cd.type=CMDTYPE_PREV;
	cd.name="";
	cd.tooltip = "Previous menu";
	cmds.push_back(cd);

	cd.id=CMD_INTERNAL;
	cd.action="nextmenu";
	cd.type=CMDTYPE_NEXT;
	cd.name="";
	cd.tooltip = "Next menu";
	cmds.push_back(cd);
}


int CGuiHandler::FindInCommandPage()
{
	if ((inCommand < 0) || (inCommand >= commands.size())) {
		return -1;
	}
	for (int ii = 0; ii < iconsCount; ii++) {
		const IconInfo& icon = icons[ii];
		if (icon.commandsID == inCommand) {
			return (ii / iconsPerPage);
		}
	}
	return -1;
}


void CGuiHandler::RevertToCmdDesc(const CommandDescription& cmdDesc,
                                  bool defaultCommand, bool samePage)
{
	for (int a = 0; a < commands.size(); ++a) {
		if (commands[a].id == cmdDesc.id) {
			if (defaultCommand) {
				defaultCmdMemory = a;
				return;
			}
			inCommand = a;
			if (commands[a].type == CMDTYPE_ICON_BUILDING) {
				const UnitDef* ud = unitDefHandler->GetUnitByID(-commands[a].id);
				SetShowingMetal(ud->extractsMetal > 0);
			} else {
				SetShowingMetal(false);
			}
			if (samePage) {
				for (int ii = 0; ii < iconsCount; ii++) {
					if (inCommand == icons[ii].commandsID) {
						activePage = min(maxPage, (ii / iconsPerPage));;
						selectedUnits.SetCommandPage(activePage);
					}
				}
			}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?