guihandler.cpp

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

CPP
2,423
字号
		}
	}
	depth--;
}


bool CGuiHandler::AboveGui(int x, int y)
{
	if (iconsCount <= 0) {
		return false;
	}
	if (!selectThrough) {
		const float fx = MouseX(x);
		const float fy = MouseY(y);
		if ((fx > buttonBox.x1) && (fx < buttonBox.x2) &&
				(fy > buttonBox.y1) && (fy < buttonBox.y2)) {
			return true;
		}
	}
	return (IconAtPos(x,y) >= 0);
}


void CGuiHandler::CreateOptions(Command& c, bool rmb)
{
	c.options = 0;
	if (rmb) {
		c.options |= RIGHT_MOUSE_KEY;
	}
	if (GetQueueKeystate()) {
		// allow mouse button 'rocker' movements to force
		// immediate mode (when queuing is the default mode)
		if (!invertQueueKey ||
		    (!mouse->buttons[SDL_BUTTON_LEFT].pressed &&
		     !mouse->buttons[SDL_BUTTON_RIGHT].pressed)) {
			c.options |= SHIFT_KEY;
		}
	}
	if (keys[SDLK_LCTRL]) {
		c.options |= CONTROL_KEY;
	}
	if (keys[SDLK_LALT] || keys[SDLK_LMETA]) {
		c.options |= ALT_KEY;
	}
	//logOutput << (int)c.options << "\n";
}


float CGuiHandler::GetNumberInput(const CommandDescription& cd) const
{
	float minV = 0.0f;
	float maxV = 100.0f;
	if (cd.params.size() >= 1) { minV = atof(cd.params[0].c_str()); }
	if (cd.params.size() >= 2) { maxV = atof(cd.params[1].c_str()); }
	const int minX = (gu->viewSizeX * 1) / 4;
	const int maxX = (gu->viewSizeX * 3) / 4;
	const int effX = max(min(mouse->lastx, maxX), minX);
	const float factor = float(effX - minX) / float(maxX - minX);

	return (minV + (factor * (maxV - minV)));
}


int CGuiHandler::GetDefaultCommand(int x,int y) const
{
	CInputReceiver* ir = NULL;
	if (!game->hideInterface) {
		ir = GetReceiverAt(x, y);
	}

	if ((ir != NULL) && (ir != minimap)) {
		return -1;
	}

	CUnit* unit = NULL;
	CFeature* feature = NULL;

	if ((ir == minimap) && (minimap->FullProxy())) {
		unit = minimap->GetSelectUnit(minimap->GetMapPosition(x, y));
	}
	else {
		const float3 camPos = camera->pos;
		const float3 camDir = mouse->dir;
		const float viewRange = gu->viewRange*1.4f;
		const float dist = helper->GuiTraceRay(camPos, camDir, viewRange, unit, 20, true);
		const float dist2 = helper->GuiTraceRayFeature(camPos, camDir, viewRange, feature);
		const float3 hit = camPos + camDir*dist;

		// make sure the ray hit in the map
		if (unit == NULL && (hit.x < 0.f || hit.x > gs->mapx*SQUARE_SIZE
				|| hit.z < 0.f || hit.z > gs->mapy*SQUARE_SIZE))
			return -1;

		if ((dist > viewRange - 300) && (dist2 > viewRange - 300) && (unit == NULL)) {
			return -1;
		}

		if (dist > dist2) {
			unit = NULL;
		} else {
			feature = NULL;
		}
	}

	// make sure the command is currently available
	const int cmd_id = selectedUnits.GetDefaultCmd(unit, feature);
	for (int c = 0; c < (int)commands.size(); c++) {
		if (cmd_id == commands[c].id) {
			return c;
		}
	}
	return -1;
}


bool CGuiHandler::ProcessLocalActions(const CKeyBindings::Action& action)
{
	// do not process these actions if the control panel is not visible
	if (iconsCount <= 0) {
		return false;
	}

	// only process the build options while building
	// (conserve the keybinding space where we can)
	if ((inCommand >= 0) && (inCommand < commands.size()) &&
			(commands[inCommand].type == CMDTYPE_ICON_BUILDING)) {
		if (ProcessBuildActions(action)) {
			return true;
		}
	}

	if (action.command == "buildiconsfirst") {
		activePage = 0;
		selectedUnits.SetCommandPage(activePage);
		selectedUnits.ToggleBuildIconsFirst();
		LayoutIcons(false);
		return true;
	}
	else if (action.command == "firstmenu") {
		activePage = 0;
		selectedUnits.SetCommandPage(activePage);
		return true;
	}
	else if (action.command == "hotbind") {
		const int iconPos = IconAtPos(mouse->lastx, mouse->lasty);
		const int iconCmd = (iconPos >= 0) ? icons[iconPos].commandsID : -1;
		if ((iconCmd >= 0) && (iconCmd < commands.size())) {
			game->SetHotBinding(commands[iconCmd].action);
		}
		return true;
	}
	else if (action.command == "hotunbind") {
		const int iconPos = IconAtPos(mouse->lastx, mouse->lasty);
		const int iconCmd = (iconPos >= 0) ? icons[iconPos].commandsID : -1;
		if ((iconCmd >= 0) && (iconCmd < commands.size())) {
			string cmd = "unbindaction " + commands[iconCmd].action;
			keyBindings->Command(cmd);
			logOutput.Print("%s", cmd.c_str());
		}
		return true;
	}
	else if (action.command == "showcommands") {
		// bonus command for debugging
		logOutput.Print("Available Commands:\n");
		for(int i = 0; i < commands.size(); ++i){
			logOutput.Print("  command: %i, id = %i, action = %s\n",
						 i, commands[i].id, commands[i].action.c_str());
		}
		// show the icon/command linkage
		logOutput.Print("Icon Linkage:\n");
		for(int ii = 0; ii < iconsCount; ++ii){
			logOutput.Print("  icon: %i, commandsID = %i\n",
			                ii, icons[ii].commandsID);
		}
		logOutput.Print("maxPage         = %i\n", maxPage);
		logOutput.Print("activePage      = %i\n", activePage);
		logOutput.Print("iconsSize       = %i\n", iconsSize);
		logOutput.Print("iconsCount      = %i\n", iconsCount);
		logOutput.Print("commands.size() = %i\n", commands.size());
		return true;
	}
	else if (action.command == "luaui") {
		RunLayoutCommand(action.extra);
		return true;
	}
	else if (action.command == "invqueuekey") {
		if (action.extra.empty()) {
			invertQueueKey = !invertQueueKey;
		} else {
			invertQueueKey = !!atoi(action.extra.c_str());
		}
		needShift = false;
		configHandler.SetInt("InvertQueueKey", invertQueueKey ? 1 : 0);
		return true;
	}

	return false;
}


void CGuiHandler::RunLayoutCommand(const string& command)
{
	if (command.find("reload") == 0) {
		if (CLuaHandle::GetActiveHandle() != NULL) {
			// NOTE: causes a SEGV through RunCallIn()
			logOutput.Print("Can not reload from within LuaUI, yet");
			return;
		}
		if (luaUI == NULL) {
			logOutput.Print("Loading: \"%s\"\n", luaUiFile);
			CLuaUI::LoadHandler();
			if (luaUI == NULL) {
				LoadConfig("ctrlpanel.txt");
				logOutput.Print("Loading failed\n");
			}
		} else {
			logOutput.Print("Reloading: \"%s\"\n", luaUiFile);
			CLuaUI::FreeHandler();
			CLuaUI::LoadHandler();
			if (luaUI == NULL) {
				LoadConfig("ctrlpanel.txt");
				logOutput.Print("Reloading failed\n");
			}
		}
	}
	else if (command == "disable") {
		if (CLuaHandle::GetActiveHandle() != NULL) {
			// NOTE: might cause a SEGV through RunCallIn()
			logOutput.Print("Can not disable from within LuaUI, yet");
			return;
		}
		if (luaUI != NULL) {
			CLuaUI::FreeHandler();
			LoadConfig("ctrlpanel.txt");
			logOutput.Print("Disabled LuaUI\n");
		}
	}
	else {
		if (luaUI != NULL) {
			luaUI->ConfigCommand(command);
		} else {
			logOutput.Print("LuaUI is not loaded\n");
		}
	}

	LayoutIcons(false);

	return;
}


bool CGuiHandler::ProcessBuildActions(const CKeyBindings::Action& action)
{
	const string arg = StringToLower(action.extra);
	if (action.command == "buildspacing") {
		if (arg == "inc") {
			buildSpacing++;
			return true;
		}
		else if (arg == "dec") {
			if (buildSpacing > 0) {
				buildSpacing--;
			}
			return true;
		}
	}
	else if (action.command == "buildfacing") {
		const char* buildFaceDirs[] = { "South", "East", "North", "West" };
		if (arg == "inc") {
			buildFacing++;
			if (buildFacing > 3) {
				buildFacing = 0;
			}
			logOutput.Print("Buildings set to face %s", buildFaceDirs[buildFacing]);
			return true;
		}
		else if (arg == "dec") {
			buildFacing--;
			if (buildFacing < 0) {
				buildFacing = 3;
			}
			logOutput.Print("Buildings set to face %s", buildFaceDirs[buildFacing]);
			return true;
		}
		else if (arg == "south") {
			buildFacing = 0;
			logOutput.Print("Buildings set to face South");
			return true;
		}
		else if (arg == "east") {
			buildFacing = 1;
			logOutput.Print("Buildings set to face East");
			return true;
		}
		else if (arg == "north") {
			buildFacing = 2;
			logOutput.Print("Buildings set to face North");
			return true;
		}
		else if (arg == "west") {
			buildFacing = 3;
			logOutput.Print("Buildings set to face West");
			return true;
		}
	}
	return false;
}


int CGuiHandler::GetIconPosCommand(int slot) const
{
	if (slot < 0) {
		return -1;
	}
	const int iconPos = slot + (activePage * iconsPerPage);
	if (iconPos < iconsCount) {
		return icons[iconPos].commandsID;
	}
	return -1;
}


bool CGuiHandler::KeyPressed(unsigned short key, bool isRepeat)
{
	if (luaUI != NULL) {
		if (luaUI->KeyPress(key, isRepeat)) {
			return true;
		}
	}

	if (key == SDLK_ESCAPE && activeMousePress) {
		activeMousePress = false;
		inCommand = -1;
		SetShowingMetal(false);
		return true;
	}
	if (key == SDLK_ESCAPE && inCommand > 0) {
		inCommand=-1;
		SetShowingMetal(false);
		return true;
	}

	CKeySet ks(key, false);
	const CKeyBindings::ActionList& al = keyBindings->GetActionList(ks);

	// setup actionOffset
	int tmpActionOffset = actionOffset;
	if ((inCommand < 0) || (lastKeySet.Key() < 0)){
		actionOffset = 0;
		tmpActionOffset = 0;
		lastKeySet.Reset();
	}
	else if (!keyCodes->IsModifier(ks.Key()) &&
	         (ks.Key() != keyBindings->GetFakeMetaKey())) {
		// not a modifier
		if ((ks == lastKeySet) && (ks.Key() >= 0)) {
			actionOffset++;
			tmpActionOffset = actionOffset;
		} else {
			tmpActionOffset = 0;
		}
	}

	for (int ali = 0; ali < (int)al.size(); ++ali) {
		const int actionIndex = (ali + tmpActionOffset) % (int)al.size();
		const CKeyBindings::Action& action = al[actionIndex];
		if (SetActiveCommand(action, ks, actionIndex)) {
			return true;
		}
	}

	return false;
}


bool CGuiHandler::SetActiveCommand(const CKeyBindings::Action& action,
                                   const CKeySet& ks, int actionIndex)
{
	if (ProcessLocalActions(action)) {
		return true;
	}

	// See if we have a positional icon command
	int iconCmd = -1;
	if (!action.extra.empty() && (action.command == "iconpos")) {
		const int iconSlot = ParseIconSlot(action.extra);
		iconCmd = GetIconPosCommand(iconSlot);
	}

	for (int a = 0; a < commands.size(); ++a) {

		CommandDescription& cmdDesc = commands[a];

		if ((a != iconCmd) && (cmdDesc.action != action.command)) {
			continue; // not a match
		}

		if (cmdDesc.disabled) {
			continue; // can not use this command
		}

		const int cmdType = cmdDesc.type;

		// set the activePage
		if (!cmdDesc.onlyKey &&
				(((cmdType == CMDTYPE_ICON) &&
					 ((cmdDesc.id < 0) ||
						(cmdDesc.id == CMD_STOCKPILE))) ||
				 (cmdType == CMDTYPE_ICON_MODE) ||
				 (cmdType == CMDTYPE_ICON_BUILDING))) {
			for (int ii = 0; ii < iconsCount; ii++) {
				if (icons[ii].commandsID == a) {
					activePage = min(maxPage, (ii / iconsPerPage));
					selectedUnits.SetCommandPage(activePage);
				}
			}
		}

		switch (cmdType) {
			case CMDTYPE_ICON:{
				Command c;
				c.options = 0;
				c.id = cmdDesc.id;
				if ((c.id < 0) || (c.id == CMD_STOCKPILE)) {
					if (action.extra == "+5") {
						c.options = SHIFT_KEY;
					} else if (action.extra == "+20") {
						c.options = CONTROL_KEY;
					} else if (action.extra == "+100") {
						c.options = SHIFT_KEY | CONTROL_KEY;
					} else if (action.extra == "-1") {
						c.options = RIGHT_MOUSE_KEY;
					} else if (action.extra == "-5") {
						c.options = RIGHT_MOUSE_KEY | SHIFT_KEY;
					} else if (action.extra == "-20") {
						c.options = RIGHT_MOUSE_KEY | CONTROL_KEY;
					} else if (action.extra == "-100") {
						c.options = RIGHT_MOUSE_KEY | SHIFT_KEY | CONTROL_KEY;
					}
				}
				else if ((c.id == CMD_WAIT) || (c.id == CMD_SELFD)) {
					if (action.extra.find("queued") != string::npos) {
						c.options |= SHIFT_KEY;
					}
				}
				GiveCommand(c);
				break;
			}
			case CMDTYPE_ICON_MODE: {
				int newMode;

				if (!action.extra.empty() && (iconCmd < 0)) {
					newMode = atoi(action.extra.c_str());
				} else {
					newMode = atoi(cmdDesc.params[0].c_str()) + 1;
				}

				if ((newMode < 0) || (newMode > (cmdDesc.params.size() - 2))) {
					newMode = 0;
				}

				// not really required
				char t[10];
				SNPRINTF(t, 10, "%d", newMode);
				cmdDesc.params[0] = t;

				Command c;
				c.options = 0;
				c.id = cmdDesc.id;
				c.params.push_back(newMode);
				GiveCommand(c);
				forceLayoutUpdate = true;
				break;
			}
			case CMDTYPE_NUMBER:{
				if (!action.extra.empty()) {
					const CommandDescription& cd = cmdDesc;
					float value = atof(action.extra.c_str());
					float minV = 0.0f;
					float maxV = 100.0f;
					if (cd.params.size() >= 1) { minV = atof(cd.params[0].c_str()); }
					if (cd.params.size() >= 2) { maxV = atof(cd.params[1].c_str()); }
					value = max(min(value, maxV), minV);
					Command c;
					c.options = 0;

⌨️ 快捷键说明

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