mousehandler.cpp

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

CPP
805
字号
#include "StdAfx.h"
// MouseHandler.cpp: implementation of the CMouseHandler class.
//
//////////////////////////////////////////////////////////////////////

#include <SDL_types.h>
#include <SDL_mouse.h>
#include <SDL_keysym.h>
#include <SDL_events.h>
#include "MouseHandler.h"
#include "Game/CameraHandler.h"
#include "Game/Camera/CameraController.h"
#include "Game/Camera.h"
#include "CommandColors.h"
#include "InputReceiver.h"
#include "GuiHandler.h"
#include "LuaUI.h"
#include "MiniMap.h"
#include "MouseCursor.h"
#include "MouseInput.h"
#include "TooltipConsole.h"
#include "ExternalAI/Group.h"
#include "Game/Game.h"
#include "Game/GameHelper.h"
#include "Game/SelectedUnits.h"
#include "Game/Team.h"
#include "Map/Ground.h"
#include "Map/MapDamage.h"
#include "Platform/ConfigHandler.h"
#include "Platform/errorhandler.h"
#include "Rendering/glFont.h"
#include "Rendering/GL/myGL.h"
#include "Rendering/InMapDraw.h"
#include "Rendering/Textures/Bitmap.h"
#include "Sim/Misc/FeatureDef.h"
#include "Sim/Misc/Feature.h"
#include "Sim/Misc/LosHandler.h"
#include "Sim/Units/UnitDef.h"
#include "Sim/Units/Unit.h"
#include "Sim/Units/UnitHandler.h"
#include "Sim/Units/UnitTracker.h"
#include "Sound.h"
#include "mmgr.h"

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

extern bool	fullscreen;
extern Uint8 *keys;


CMouseHandler* mouse = NULL;

static CInputReceiver*& activeReceiver = CInputReceiver::GetActiveReceiverRef();


CMouseHandler::CMouseHandler()
: locked(false)
{
	lastx=300;
	lasty=200;
	hide=false;

	for(int a=1;a<=NUM_BUTTONS;a++){
		buttons[a].pressed=false;
		buttons[a].lastRelease=-20;
		buttons[a].movement=0;
	}

	cursorScale = 1.0f;

	LoadCursors();

	SDL_ShowCursor(SDL_DISABLE);

	soundMultiselID = sound->GetWaveId("sounds/button9.wav");

	invertMouse=!!configHandler.GetInt("InvertMouse",1);
	doubleClickTime = (float)configHandler.GetInt("DoubleClickTime", 200) / 1000.0f;

	scrollWheelSpeed = (float)configHandler.GetInt("ScrollWheelSpeed", 25);
	scrollWheelSpeed = max(-255.0f, min(255.0f, scrollWheelSpeed));
}

CMouseHandler::~CMouseHandler()
{
	SDL_ShowCursor(SDL_ENABLE);

	std::map<std::string, CMouseCursor*>::iterator ci;
	for (ci = cursorFileMap.begin(); ci != cursorFileMap.end(); ++ci) {
		delete ci->second;
	}
}


void CMouseHandler::LoadCursors()
{
	const CMouseCursor::HotSpot mCenter  = CMouseCursor::Center;
	const CMouseCursor::HotSpot mTopLeft = CMouseCursor::TopLeft;

	AssignMouseCursor("",             "cursornormal",     mTopLeft, false);
	AssignMouseCursor("Area attack",  "cursorareaattack", mCenter,  false);
	AssignMouseCursor("Area attack",  "cursorattack",     mCenter,  false); // backup
	AssignMouseCursor("Attack",       "cursorattack",     mCenter,  false);
	AssignMouseCursor("BuildBad",     "cursorbuildbad",   mCenter,  false);
	AssignMouseCursor("BuildGood",    "cursorbuildgood",  mCenter,  false);
	AssignMouseCursor("Capture",      "cursorcapture",    mCenter,  false);
	AssignMouseCursor("Centroid",     "cursorcentroid",   mCenter,  false);
	AssignMouseCursor("DeathWait",    "cursordwatch",     mCenter,  false);
	AssignMouseCursor("DeathWait",    "cursorwait",       mCenter,  false); // backup
	AssignMouseCursor("DGun",         "cursordgun",       mCenter,  false);
	AssignMouseCursor("DGun",         "cursorattack",     mCenter,  false); // backup
	AssignMouseCursor("Fight",        "cursorfight",      mCenter,  false);
	AssignMouseCursor("Fight",        "cursorattack",     mCenter,  false); // backup
	AssignMouseCursor("GatherWait",   "cursorgather",     mCenter,  false);
	AssignMouseCursor("GatherWait",   "cursorwait",       mCenter,  false); // backup
	AssignMouseCursor("Guard",        "cursordefend",     mCenter,  false);
	AssignMouseCursor("Load units",   "cursorpickup",     mCenter,  false);
	AssignMouseCursor("Move",         "cursormove",       mCenter,  false);
	AssignMouseCursor("Patrol",       "cursorpatrol",     mCenter,  false);
	AssignMouseCursor("Reclaim",      "cursorreclamate",  mCenter,  false);
	AssignMouseCursor("Repair",       "cursorrepair",     mCenter,  false);
	AssignMouseCursor("Resurrect",    "cursorrevive",     mCenter,  false);
	AssignMouseCursor("Resurrect",    "cursorrepair",     mCenter,  false); // backup
	AssignMouseCursor("Restore",      "cursorrestore",    mCenter,  false);
	AssignMouseCursor("Restore",      "cursorrepair",     mCenter,  false); // backup
	AssignMouseCursor("SelfD",        "cursorselfd",      mCenter,  false);
	AssignMouseCursor("SquadWait",    "cursornumber",     mCenter,  false);
	AssignMouseCursor("SquadWait",    "cursorwait",       mCenter,  false); // backup
	AssignMouseCursor("TimeWait",     "cursortime",       mCenter,  false);
	AssignMouseCursor("TimeWait",     "cursorwait",       mCenter,  false); // backup
	AssignMouseCursor("Unload units", "cursorunload",     mCenter,  false);
	AssignMouseCursor("Wait",         "cursorwait",       mCenter,  false);

	// the default cursor must exist
	if (cursorCommandMap.find("") == cursorCommandMap.end()) {
		handleerror(0, "Missing default cursor", "cursornormal", 0);
	}
}


/******************************************************************************/

void CMouseHandler::MouseMove(int x, int y)
{
	if(hide) {
		lastx = x;
		lasty = y;
		return;
	}

	const int dx = x - lastx;
	const int dy = y - lasty;
	lastx = x;
	lasty = y;

	dir=hide ? camera->forward : camera->CalcPixelDir(x,y);

	buttons[SDL_BUTTON_LEFT].movement += abs(dx) + abs(dy);
	buttons[SDL_BUTTON_RIGHT].movement += abs(dx) + abs(dy);

	if (!game->gameOver) {
		gs->players[gu->myPlayerNum]->currentStats->mousePixels+=abs(dx)+abs(dy);
	}

	if(activeReceiver){
		activeReceiver->MouseMove(x, y, dx, dy, activeButton);
	}

	if(inMapDrawer && inMapDrawer->keyPressed){
		inMapDrawer->MouseMove(x, y, dx, dy, activeButton);
	}

	if (buttons[SDL_BUTTON_MIDDLE].pressed && (activeReceiver == NULL)) {
		camCtrl->MouseMove(float3(dx, dy, invertMouse ? -1.0f : 1.0f));
		unitTracker.Disable();
		return;
	}
}


void CMouseHandler::MousePress(int x, int y, int button)
{
	if (button > NUM_BUTTONS)
		return;

	dir = hide? camera->forward: camera->CalcPixelDir(x, y);

	if (!game->gameOver)
		gs->players[gu->myPlayerNum]->currentStats->mouseClicks++;

	if (button == 4) {
		if (guihandler->buildSpacing > 0)
			guihandler->buildSpacing--;
		return;
	}
	if (button == 5) {
		guihandler->buildSpacing++;
		return;
	}

 	buttons[button].chorded = buttons[SDL_BUTTON_LEFT].pressed ||
 	                          buttons[SDL_BUTTON_RIGHT].pressed;
	buttons[button].pressed = true;
	buttons[button].time = gu->gameTime;
	buttons[button].x = x;
	buttons[button].y = y;
	buttons[button].camPos = camera->pos;
	buttons[button].dir = hide ? camera->forward : camera->CalcPixelDir(x,y);
	buttons[button].movement = 0;

	activeButton = button;

	if (activeReceiver) {
		activeReceiver->MousePress(x, y, button);
		return;
	}

	if(inMapDrawer &&  inMapDrawer->keyPressed){
		inMapDrawer->MousePress(x, y, button);
		return;
	}

	// limited receivers for MMB
	if (button == SDL_BUTTON_MIDDLE){
		if (!locked) {
			if ((minimap != NULL) && minimap->FullProxy()) {
				if (minimap->MousePress(x, y, button)) {
					activeReceiver = minimap;
					return;
				}
			}
			if (guihandler != NULL) {
				// this includes LuaUI
				if (guihandler->MousePress(x, y, button)) {
					activeReceiver = guihandler;
					return;
				}
			}
		}
		return;
	}

	std::deque<CInputReceiver*>& inputReceivers = GetInputReceivers();
	std::deque<CInputReceiver*>::iterator ri;
	if (!game->hideInterface) {
		for (ri = inputReceivers.begin(); ri != inputReceivers.end(); ++ri) {
			if ((*ri) && (*ri)->MousePress(x, y, button)) {
				activeReceiver = *ri;
				return;
			}
		}
	} else if (guihandler) {
		if (guihandler->MousePress(x,y,button)) {
			activeReceiver = guihandler; // for default (rmb) commands
		}
	}
}


void CMouseHandler::MouseRelease(int x, int y, int button)
{
	if (button > NUM_BUTTONS)
		return;

	dir = hide? camera->forward: camera->CalcPixelDir(x, y);
	buttons[button].pressed=false;

	if (inMapDrawer && inMapDrawer->keyPressed){
		inMapDrawer->MouseRelease(x, y, button);
		return;
	}

	if (activeReceiver) {
		activeReceiver->MouseRelease(x, y, button);
		int x, y;
		const Uint8 buttons = SDL_GetMouseState(&x, &y);
		const Uint8 mask = (SDL_BUTTON_LMASK | SDL_BUTTON_MMASK | SDL_BUTTON_RMASK);
		if ((buttons & mask) == 0) {
			activeReceiver = NULL;
		}
		return;
	}

	// Switch camera mode on a middle click that wasn't a middle mouse drag scroll.
	// (the latter is determined by the time the mouse was held down:
	//  <= 0.3 s means a camera mode switch, > 0.3 s means a drag scroll)
	if (button == SDL_BUTTON_MIDDLE) {
		if (buttons[SDL_BUTTON_MIDDLE].time > (gu->gameTime - 0.3f)) {
			if (keys[SDLK_LSHIFT] || keys[SDLK_LCTRL])
				camHandler->ToggleState();
			else
				ToggleState();
		}
		return;
	}

#ifdef DIRECT_CONTROL_ALLOWED
	if (gu->directControl) {
		return;
	}
#endif

	if ((button == SDL_BUTTON_LEFT) && !buttons[button].chorded) {
		if (!keys[SDLK_LSHIFT] && !keys[SDLK_LCTRL]) {
			selectedUnits.ClearSelected();
		}

		if (buttons[SDL_BUTTON_LEFT].movement > 4) {
			// select box
			float dist=ground->LineGroundCol(buttons[SDL_BUTTON_LEFT].camPos,buttons[SDL_BUTTON_LEFT].camPos+buttons[SDL_BUTTON_LEFT].dir*gu->viewRange*1.4f);
			if(dist<0)
				dist=gu->viewRange*1.4f;
			float3 pos1=buttons[SDL_BUTTON_LEFT].camPos+buttons[SDL_BUTTON_LEFT].dir*dist;

			dist=ground->LineGroundCol(camera->pos,camera->pos+dir*gu->viewRange*1.4f);
			if(dist<0)
				dist=gu->viewRange*1.4f;
			float3 pos2=camera->pos+dir*dist;

			float3 dir1=pos1-camera->pos;
			dir1.Normalize();
			float3 dir2=pos2-camera->pos;
			dir2.Normalize();

			float rl1=(dir1.dot(camera->right))/dir1.dot(camera->forward);
			float ul1=(dir1.dot(camera->up))/dir1.dot(camera->forward);

			float rl2=(dir2.dot(camera->right))/dir2.dot(camera->forward);
			float ul2=(dir2.dot(camera->up))/dir2.dot(camera->forward);

			if(rl1<rl2){
				float t=rl1;
				rl1=rl2;
				rl2=t;
			}
			if(ul1<ul2){
				float t=ul1;
				ul1=ul2;
				ul2=t;
			}

			float3 norm1,norm2,norm3,norm4;

			if(ul1>0)
				norm1=-camera->forward+camera->up/fabs(ul1);
			else if(ul1<0)
				norm1=camera->forward+camera->up/fabs(ul1);
			else
				norm1=camera->up;

			if(ul2>0)
				norm2=camera->forward-camera->up/fabs(ul2);
			else if(ul2<0)
				norm2=-camera->forward-camera->up/fabs(ul2);
			else
				norm2=-camera->up;

			if(rl1>0)
				norm3=-camera->forward+camera->right/fabs(rl1);
			else if(rl1<0)
				norm3=camera->forward+camera->right/fabs(rl1);
			else
				norm3=camera->right;

			if(rl2>0)
				norm4=camera->forward-camera->right/fabs(rl2);
			else if(rl2<0)
				norm4=-camera->forward-camera->right/fabs(rl2);
			else
				norm4=-camera->right;

			CUnitSet::iterator ui;
			CUnit* unit = NULL;
			int addedunits=0;
			int team, lastTeam;
			if (gu->spectatingFullSelect) {
				team = 0;
				lastTeam = gs->activeTeams - 1;
			} else {
				team = gu->myTeam;
				lastTeam = gu->myTeam;
			}
			for (; team <= lastTeam; team++) {
				for(ui=gs->Team(team)->units.begin();ui!=gs->Team(team)->units.end();++ui){
					float3 vec=(*ui)->midPos-camera->pos;
					if(vec.dot(norm1)<0 && vec.dot(norm2)<0 && vec.dot(norm3)<0 && vec.dot(norm4)<0){
						if (keys[SDLK_LCTRL] && selectedUnits.selectedUnits.find(*ui) != selectedUnits.selectedUnits.end()) {
							selectedUnits.RemoveUnit(*ui);
						} else {
							selectedUnits.AddUnit(*ui);
							unit = *ui;
							addedunits++;
						}
					}
				}
			}
			if (addedunits == 1) {
				int soundIdx = unit->unitDef->sounds.select.getRandomIdx();
				if (soundIdx >= 0) {
					sound->PlayUnitReply(
						unit->unitDef->sounds.select.getID(soundIdx), unit,

⌨️ 快捷键说明

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