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 + -
显示快捷键?