guihandler.cpp
来自「这是整套横扫千军3D版游戏的源码」· C++ 代码 · 共 2,423 行 · 第 1/5 页
CPP
2,423 行
if (!game->hideInterface) {
ir = GetReceiverAt(mouse->lastx, mouse->lasty);
}
if ((ir != NULL) && (ir != minimap)) {
return;
}
if (ir == minimap) {
mouse->cursorScale = minimap->CursorScale();
}
const bool useMinimap =
(minimap->ProxyMode() || ((activeReceiver != this) && (ir == minimap)));
if ((inCommand >= 0) && (inCommand<commands.size())) {
const CommandDescription& cmdDesc = commands[inCommand];
if (!cmdDesc.mouseicon.empty()) {
mouse->cursorText = cmdDesc.mouseicon;
} else {
mouse->cursorText = cmdDesc.name;
}
if (useMinimap && (cmdDesc.id < 0)) {
BuildInfo bi;
bi.pos = minimap->GetMapPosition(mouse->lastx, mouse->lasty);
bi.buildFacing = bi.buildFacing;
bi.def = unitDefHandler->GetUnitByID(-cmdDesc.id);
bi.pos = helper->Pos2BuildPos(bi);
// if an unit (enemy), is not in LOS, then TestUnitBuildSquare()
// does not consider it when checking for position blocking
CFeature* feature;
if(!uh->TestUnitBuildSquare(bi, feature, gu->myAllyTeam)) {
mouse->cursorText = "BuildBad";
} else {
mouse->cursorText = "BuildGood";
}
}
}
else if (!useMinimap || minimap->FullProxy()) {
int defcmd;
if (mouse->buttons[SDL_BUTTON_RIGHT].pressed &&
((activeReceiver == this) || (minimap->ProxyMode()))) {
defcmd = defaultCmdMemory;
} else {
defcmd = GetDefaultCommand(mouse->lastx, mouse->lasty);
}
if ((defcmd >= 0) && (defcmd < commands.size())) {
const CommandDescription& cmdDesc = commands[defcmd];
if (!cmdDesc.mouseicon.empty()) {
mouse->cursorText = cmdDesc.mouseicon;
} else {
mouse->cursorText = cmdDesc.name;
}
}
}
if (gatherMode && (mouse->cursorText == "Move")) {
mouse->cursorText = "GatherWait";
}
}
bool CGuiHandler::MousePress(int x, int y, int button)
{
if (luaUI != NULL) {
luaUIClick = luaUI->MousePress(x, y, button);
if (luaUIClick) {
return true;
}
}
if (button == SDL_BUTTON_MIDDLE) {
return false;
}
if (button < 0) {
// proxied click from the minimap
button = -button;
activeMousePress=true;
}
else if (AboveGui(x,y)) {
activeMousePress = true;
return true;
}
else if (minimap && minimap->IsAbove(x, y)) {
return false; // let the minimap do its job
}
if (inCommand >= 0) {
if (invertQueueKey && (button == SDL_BUTTON_RIGHT) &&
!mouse->buttons[SDL_BUTTON_LEFT].pressed) { // for rocker gestures
SetShowingMetal(false);
inCommand = -1;
needShift = false;
return false;
}
activeMousePress = true;
return true;
}
if (button == SDL_BUTTON_RIGHT) {
activeMousePress = true;
defaultCmdMemory = GetDefaultCommand(x, y);
return true;
}
return false;
}
void CGuiHandler::MouseMove(int x, int y, int dx, int dy, int button)
{
if (luaUI != NULL) {
luaUI->MouseMove(x, y, dx, dy, button);
}
}
void CGuiHandler::MouseRelease(int x, int y, int button)
{
int iconCmd = -1;
if (luaUIClick) {
luaUIClick = false;
if (luaUI != NULL) {
iconCmd = luaUI->MouseRelease(x, y, button);
}
if ((iconCmd < 0) || (iconCmd >= commands.size())) {
return;
} else {
activeMousePress = true;
}
}
if (activeMousePress) {
activeMousePress=false;
} else {
return;
}
if (!invertQueueKey && needShift && !keys[SDLK_LSHIFT]) {
SetShowingMetal(false);
inCommand=-1;
needShift=false;
}
if (button < 0) {
button = -button; // proxied click from the minimap
} else {
// setup iconCmd
if ((iconCmd < 0) && !game->hideInterface) {
const int iconPos = IconAtPos(x, y);
if (iconPos >= 0) {
iconCmd = icons[iconPos].commandsID;
}
}
}
if ((button == SDL_BUTTON_RIGHT) && (iconCmd == -1)) {
// right click -> set the default cmd
inCommand = defaultCmdMemory;
defaultCmdMemory = -1;
}
if ((iconCmd >= 0) && (iconCmd < commands.size())) {
const bool rmb = (button == SDL_BUTTON_LEFT) ? false : true;
SetActiveCommand(iconCmd, rmb);
return;
}
// not over a button, try to execute a command
Command c = GetCommand(x, y, button, false);
// if cmd_stop is returned it indicates that no good command could be found
if (c.id != CMD_STOP) {
GiveCommand(c);
lastKeySet.Reset();
}
FinishCommand(button);
}
bool CGuiHandler::SetActiveCommand(int cmdIndex, bool rmb)
{
if (cmdIndex >= (int)commands.size()) {
return false;
}
else if (cmdIndex < 0) {
// cancel the current command
inCommand = -1;
defaultCmdMemory = -1;
needShift = false;
activeMousePress = false;
SetShowingMetal(false);
return true;
}
CommandDescription& cd = commands[cmdIndex];
if (cd.disabled) {
return false;
}
lastKeySet.Reset();
switch (cd.type) {
case CMDTYPE_ICON: {
Command c;
c.id = cd.id;
if (c.id != CMD_STOP) {
CreateOptions(c, rmb);
if (invertQueueKey && ((c.id < 0) || (c.id == CMD_STOCKPILE))) {
c.options = c.options ^ SHIFT_KEY;
}
}
GiveCommand(c);
break;
}
case CMDTYPE_ICON_MODE: {
int newMode = atoi(cd.params[0].c_str()) + 1;
if (newMode > cd.params.size()-2) {
newMode = 0;
}
// not really required
char t[10];
SNPRINTF(t, 10, "%d", newMode);
cd.params[0] = t;
Command c;
c.id = cd.id;
c.params.push_back(newMode);
CreateOptions(c, rmb);
GiveCommand(c);
forceLayoutUpdate = true;
break;
}
case CMDTYPE_NUMBER:
case CMDTYPE_ICON_MAP:
case CMDTYPE_ICON_AREA:
case CMDTYPE_ICON_UNIT:
case CMDTYPE_ICON_UNIT_OR_MAP:
case CMDTYPE_ICON_FRONT:
case CMDTYPE_ICON_UNIT_OR_AREA:
case CMDTYPE_ICON_UNIT_OR_RECTANGLE:
case CMDTYPE_ICON_UNIT_FEATURE_OR_AREA: {
inCommand = cmdIndex;
SetShowingMetal(false);
activeMousePress = false;
break;
}
case CMDTYPE_ICON_BUILDING: {
const UnitDef* ud = unitDefHandler->GetUnitByID(-cd.id);
inCommand = cmdIndex;
SetShowingMetal(ud->extractsMetal > 0);
activeMousePress = false;
break;
}
case CMDTYPE_COMBO_BOX: {
if (GetInputReceivers().empty() ||
dynamic_cast<CglList*>(GetInputReceivers().front()) == NULL) {
inCommand = cmdIndex;
SetShowingMetal(false);
list = SAFE_NEW CglList(cd.name.c_str(), MenuSelection);
list->cancelPlace = 0;
list->tooltip =
"Choose the AI you want to assign to this group.\n"
"Select \"None\" to cancel or \"default\" to create a group without an AI\n"
"assigned.";
vector<string>::const_iterator pi;
for (pi = ++cd.params.begin(); pi != cd.params.end(); ++pi) {
list->AddItem(pi->c_str(),"");
}
list->place=atoi(cd.params[0].c_str());
} else {
inCommand = -1;
SetShowingMetal(false);
}
activeMousePress = false;
break;
}
case CMDTYPE_NEXT: {
++activePage;
if (activePage > maxPage) {
activePage = 0;
}
selectedUnits.SetCommandPage(activePage);
break;
}
case CMDTYPE_PREV: {
--activePage;
if (activePage < 0) {
activePage=maxPage;
}
selectedUnits.SetCommandPage(activePage);
break;
}
case CMDTYPE_CUSTOM: {
RunCustomCommands(cd.params, rmb);
break;
}
default:
break;
}
return true;
}
bool CGuiHandler::SetActiveCommand(int cmdIndex, int button,
bool lmb, bool rmb,
bool alt, bool ctrl, bool meta, bool shift)
{
// use the button value instead of rmb
const bool effectiveRMB = (button == SDL_BUTTON_LEFT) ? false : true;
// setup the mouse and key states
const bool prevLMB = mouse->buttons[SDL_BUTTON_LEFT].pressed;
const bool prevRMB = mouse->buttons[SDL_BUTTON_RIGHT].pressed;
const Uint8 prevAlt = keys[SDLK_LALT];
const Uint8 prevCtrl = keys[SDLK_LCTRL];
const Uint8 prevMeta = keys[SDLK_LMETA];
const Uint8 prevShift = keys[SDLK_LSHIFT];
mouse->buttons[SDL_BUTTON_LEFT].pressed = lmb;
mouse->buttons[SDL_BUTTON_RIGHT].pressed = rmb;
keys[SDLK_LALT] = alt;
keys[SDLK_LCTRL] = ctrl;
keys[SDLK_LMETA] = meta;
keys[SDLK_LSHIFT] = shift;
const bool retval = SetActiveCommand(cmdIndex, effectiveRMB);
// revert the mouse and key states
keys[SDLK_LSHIFT] = prevShift;
keys[SDLK_LMETA] = prevMeta;
keys[SDLK_LCTRL] = prevCtrl;
keys[SDLK_LALT] = prevAlt;
mouse->buttons[SDL_BUTTON_RIGHT].pressed = prevRMB;
mouse->buttons[SDL_BUTTON_LEFT].pressed = prevLMB;
return retval;
}
int CGuiHandler::IconAtPos(int x, int y)
{
const float fx = MouseX(x);
const float fy = MouseY(y);
if ((fx < buttonBox.x1) || (fx > buttonBox.x2) ||
(fy < buttonBox.y1) || (fy > buttonBox.y2)) {
return -1;
}
int xSlot = int((fx - (buttonBox.x1 + frameBorder)) / xIconStep);
int ySlot = int(((buttonBox.y2 - frameBorder) - fy) / yIconStep);
xSlot = min(max(xSlot, 0), xIcons - 1);
ySlot = min(max(ySlot, 0), yIcons - 1);
const int ii = (activePage * iconsPerPage) + (ySlot * xIcons) + xSlot;
if ((ii >= 0) && (ii < iconsCount)) {
if ((fx > icons[ii].selection.x1) && (fx < icons[ii].selection.x2) &&
(fy > icons[ii].selection.y2) && (fy < icons[ii].selection.y1)) {
return ii;
}
}
return -1;
}
/******************************************************************************/
enum ModState {
DontCare, Required, Forbidden
};
struct ModGroup {
ModGroup()
: alt(DontCare),
ctrl(DontCare),
meta(DontCare),
shift(DontCare),
right(DontCare) {}
ModState alt, ctrl, meta, shift, right;
};
static bool ParseCustomCmdMods(string& cmd, ModGroup& in, ModGroup& out)
{
const char* c = cmd.c_str();
if (*c != '@') {
return false;
}
c++;
bool neg = false;
while ((*c != 0) && (*c != '@')) {
char ch = *c;
if (ch == '-') {
neg = true;
}
else if (ch == '+') {
neg = false;
}
else if (ch == 'a') { in.alt = neg ? Forbidden : Required; neg = false; }
else if (ch == 'c') { in.ctrl = neg ? Forbidden : Required; neg = false; }
else if (ch == 'm') { in.meta = neg ? Forbidden : Required; neg = false; }
else if (ch == 's') { in.shift = neg ? Forbidden : Required; neg = false; }
else if (ch == 'r') { in.right = neg ? Forbidden : Required; neg = false; }
else if (ch == 'A') { out.alt = neg ? Forbidden : Required; neg = false; }
else if (ch == 'C') { out.ctrl = neg ? Forbidden : Required; neg = false; }
else if (ch == 'M') { out.meta = neg ? Forbidden : Required; neg = false; }
else if (ch == 'S') { out.shift = neg ? Forbidden : Required; neg = false; }
else if (ch == 'R') { out.right = neg ? Forbidden : Required; neg = false; }
c++;
}
if (*c == 0) {
return false;
}
cmd = cmd.substr((c + 1) - cmd.c_str());
return true;
}
static bool CheckCustomCmdMods(bool rmb, ModGroup& inMods)
{
if (((inMods.alt == Required) && !keys[SDLK_LALT]) ||
((inMods.alt == Forbidden) && keys[SDLK_LALT]) ||
((inMods.ctrl == Required) && !keys[SDLK_LCTRL]) ||
((inMods.ctrl == Forbidden) && keys[SDLK_LCTRL]) ||
((inMods.meta == Required) && !keys[SDLK_LMETA]) ||
((inMods.meta == Forbidden) && keys[SDLK_LMETA]) ||
((inMods.shift == Required) && !keys[SDLK_LSHIFT]) ||
((inMods.shift == Forbidden) && keys[SDLK_LSHIFT]) ||
((inMods.right == Required) && !rmb) ||
((inMods.right == Forbidden) && rmb)) {
return false;
}
return true;
}
void CGuiHandler::RunCustomCommands(const vector<string>& cmds, bool rmb)
{
static int depth = 0;
if (depth > 8) {
return; // recursion protection
}
depth++;
for (int p = 0; p < (int)cmds.size(); p++) {
string copy = cmds[p];
ModGroup inMods; // must match for the action to execute
ModGroup outMods; // controls the state of the modifiers (ex: "group1")
if (ParseCustomCmdMods(copy, inMods, outMods)) {
if (CheckCustomCmdMods(rmb, inMods)) {
const bool tmpAlt = !!keys[SDLK_LALT];
const bool tmpCtrl = !!keys[SDLK_LCTRL];
const bool tmpMeta = !!keys[SDLK_LMETA];
const bool tmpShift = !!keys[SDLK_LSHIFT];
if (outMods.alt == Required) { keys[SDLK_LALT] = 1; }
if (outMods.alt == Forbidden) { keys[SDLK_LALT] = 0; }
if (outMods.ctrl == Required) { keys[SDLK_LCTRL] = 1; }
if (outMods.ctrl == Forbidden) { keys[SDLK_LCTRL] = 0; }
if (outMods.meta == Required) { keys[SDLK_LMETA] = 1; }
if (outMods.meta == Forbidden) { keys[SDLK_LMETA] = 0; }
if (outMods.shift == Required) { keys[SDLK_LSHIFT] = 1; }
if (outMods.shift == Forbidden) { keys[SDLK_LSHIFT] = 0; }
CKeyBindings::Action action(copy);
if (!ProcessLocalActions(action)) {
CKeySet ks;
game->ActionPressed(action, ks, false /*isRepeat*/);
}
keys[SDLK_LALT] = tmpAlt;
keys[SDLK_LCTRL] = tmpCtrl;
keys[SDLK_LMETA] = tmpMeta;
keys[SDLK_LSHIFT] = tmpShift;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?