Index: binaries/data/mods/public/gui/session/input.js =================================================================== --- binaries/data/mods/public/gui/session/input.js +++ binaries/data/mods/public/gui/session/input.js @@ -1243,25 +1243,39 @@ return true; } -function handleMinimapEvent(target) +function handleMinimapEvent(data) { - // Partly duplicated from handleInputAfterGui(), but with the input being - // world coordinates instead of screen coordinates. + switch(data.type) + { + case "mouserightrelease": + case "mouserightdoubleclick": + // Partly duplicated from handleInputAfterGui(), but with the input being + // world coordinates instead of screen coordinates. - if (inputState != INPUT_NORMAL) - return false; + if (inputState != INPUT_NORMAL) + return false; - var fromMinimap = true; - var action = determineAction(undefined, undefined, fromMinimap); - if (!action) - return false; + var fromMinimap = true; + var action = determineAction(undefined, undefined, fromMinimap); + if (!action) + return false; - var selection = g_Selection.toList(); + var selection = g_Selection.toList(); - var queued = Engine.HotkeyIsPressed("session.queue"); - if (g_UnitActions[action.type] && g_UnitActions[action.type].execute) - return g_UnitActions[action.type].execute(target, action, selection, queued); - error("Invalid action.type " + action.type); + var queued = Engine.HotkeyIsPressed("session.queue"); + if (g_UnitActions[action.type] && g_UnitActions[action.type].execute) + return g_UnitActions[action.type].execute(data.target, action, selection, queued); + error("Invalid action.type " + action.type); + break; + case "mousemiddlerelease": + case "mousemiddledoubleclick": + DisplayMapPing(data.target); + Engine.PostNetworkCommand({ + "type": "map-ping", + "target": data.target + }); + break; + } return false; } Index: binaries/data/mods/public/gui/session/messages.js =================================================================== --- binaries/data/mods/public/gui/session/messages.js +++ binaries/data/mods/public/gui/session/messages.js @@ -470,7 +470,7 @@ g_Selection.reset(); g_Selection.addList(selection, false, cmd.type == "gather"); }, - "play-tracks": function (notification, player) + "play-tracks": function(notification, player) { if (notification.lock) { @@ -479,6 +479,12 @@ } global.music.setLocked(notification.lock); + }, + "map-ping": function(notification, player) + { + // Don't display for the player that did the ping because he will see it immediately + if (player != Engine.GetPlayerID() && g_Players[player].isMutualAlly[Engine.GetPlayerID()]) + DisplayMapPing(notification.target); } }; Index: binaries/data/mods/public/gui/session/minimap_panel.xml =================================================================== --- binaries/data/mods/public/gui/session/minimap_panel.xml +++ binaries/data/mods/public/gui/session/minimap_panel.xml @@ -6,7 +6,7 @@ sprite="mapPanel" > - + handleMinimapEvent(arguments[0]); ::GetSetting(this, "ping", doPing); + if (doPing) + { + GUI::SetSetting(this, "ping", false); + float pingX; + GUI::GetSetting(this, "ping_x", pingX); + float pingZ; + GUI::GetSetting(this, "ping_z", pingZ); + CPos pos = GetMapCoordinates(pingX, pingZ); + m_MapPing = pos; + } + } + break; default: break; } @@ -218,6 +243,14 @@ z = TERRAIN_TILE_SIZE * m_MapSize * (m_MapScale * (cos(angle)*(py-0.5) + sin(angle)*(px-0.5)) + 0.5); } +CPos CMiniMap::GetMapCoordinates(float x, float z) +{ + const float width = m_CachedActualSize.GetWidth(); + const float height = m_CachedActualSize.GetHeight(); + const float invTileMapSize = 1.0f / float(TERRAIN_TILE_SIZE * m_MapSize); + return CPos(width * x * invTileMapSize, height * z * invTileMapSize); +} + void CMiniMap::SetCameraPos() { CTerrain* terrain = g_Game->GetWorld()->GetTerrain(); @@ -234,7 +267,7 @@ return -atan2(cameraIn.X, cameraIn.Z); } -void CMiniMap::FireWorldClickEvent(int UNUSED(button), int UNUSED(clicks)) +void CMiniMap::FireWorldClickEvent(const CStr& eventType) { JSContext* cx = g_GUI->GetActiveGUI()->GetScriptInterface()->GetContext(); JSAutoRequest rq(cx); @@ -242,11 +275,15 @@ float x, z; GetMouseWorldCoordinates(x, z); - JS::RootedValue coords(cx); - g_GUI->GetActiveGUI()->GetScriptInterface()->Eval("({})", &coords); - g_GUI->GetActiveGUI()->GetScriptInterface()->SetProperty(coords, "x", x, false); - g_GUI->GetActiveGUI()->GetScriptInterface()->SetProperty(coords, "z", z, false); - ScriptEvent("worldclick", coords); + JS::RootedValue target(cx); + g_GUI->GetActiveGUI()->GetScriptInterface()->Eval("({})", &target); + g_GUI->GetActiveGUI()->GetScriptInterface()->SetProperty(target, "x", x, false); + g_GUI->GetActiveGUI()->GetScriptInterface()->SetProperty(target, "z", z, false); + JS::RootedValue data(cx); + g_GUI->GetActiveGUI()->GetScriptInterface()->Eval("({})", &data); + g_GUI->GetActiveGUI()->GetScriptInterface()->SetProperty(data, "target", target, false); + g_GUI->GetActiveGUI()->GetScriptInterface()->SetProperty(data, "type", eventType, false); + ScriptEvent("worldclick", data); } // This sets up and draws the rectangle on the minimap @@ -258,7 +295,6 @@ float h = g_Renderer.GetWaterManager()->m_WaterHeight; const float width = m_CachedActualSize.GetWidth(); const float height = m_CachedActualSize.GetHeight(); - const float invTileMapSize = 1.0f / float(TERRAIN_TILE_SIZE * m_MapSize); CVector3D hitPt[4]; hitPt[0] = m_Camera->GetWorldCoordinates(0, g_Renderer.GetHeight(), h); @@ -266,19 +302,17 @@ hitPt[2] = m_Camera->GetWorldCoordinates(g_Renderer.GetWidth(), 0, h); hitPt[3] = m_Camera->GetWorldCoordinates(0, 0, h); - float ViewRect[4][2]; + CPos ViewRect[4]; for (int i = 0; i < 4; ++i) - { // convert to minimap space - ViewRect[i][0] = (width * hitPt[i].X * invTileMapSize); - ViewRect[i][1] = (height * hitPt[i].Z * invTileMapSize); - } + ViewRect[i] = GetMapCoordinates(hitPt[i].X, hitPt[i].Z); + float viewVerts[] = { - ViewRect[0][0], -ViewRect[0][1], - ViewRect[1][0], -ViewRect[1][1], - ViewRect[2][0], -ViewRect[2][1], - ViewRect[3][0], -ViewRect[3][1] + ViewRect[0].x, -ViewRect[0].y, + ViewRect[1].x, -ViewRect[1].y, + ViewRect[2].x, -ViewRect[2].y, + ViewRect[3].x, -ViewRect[3].y }; // Enable Scissoring to restrict the rectangle to only the minimap. @@ -310,6 +344,46 @@ glDisable(GL_SCISSOR_TEST); } +// TODO: Hacky and ugly copypasta +void CMiniMap::DrawPing(CMatrix3D transform) +{ + const float width = m_CachedActualSize.GetWidth(); + const float height = m_CachedActualSize.GetHeight(); +float viewVerts[] = { + m_MapPing.x + 3, -m_MapPing.y-3, + m_MapPing.x - 3, -m_MapPing.y-3, + m_MapPing.x - 3, -m_MapPing.y+3, + m_MapPing.x + 3, -m_MapPing.y+3 + }; + // Enable Scissoring to restrict the rectangle to only the minimap. + glScissor( + m_CachedActualSize.left * g_GuiScale, + g_Renderer.GetHeight() - m_CachedActualSize.bottom * g_GuiScale, + width * g_GuiScale, + height * g_GuiScale); + glEnable(GL_SCISSOR_TEST); + glLineWidth(2.0f); + + CShaderDefines lineDefines; + lineDefines.Add(str_MINIMAP_LINE, str_1); + CShaderTechniquePtr tech = g_Renderer.GetShaderManager().LoadEffect(str_minimap, g_Renderer.GetSystemShaderDefines(), lineDefines); + tech->BeginPass(); + CShaderProgramPtr shader = tech->GetShader(); + shader->Uniform(str_transform, transform); + shader->Uniform(str_color, 1.0f, 0.3f, 1.0f, 1.0f); + + shader->VertexPointer(2, GL_FLOAT, 0, viewVerts); + shader->AssertPointersBound(); + + if (!g_Renderer.m_SkipSubmit) + glDrawArrays(GL_LINE_LOOP, 0, 4); + + tech->EndPass(); + + glLineWidth(1.0f); + glDisable(GL_SCISSOR_TEST); +} + struct MinimapUnitVertex { u8 r, g, b, a; @@ -598,6 +672,8 @@ tech->EndPass(); DrawViewRect(unitMatrix); + if (m_MapPing.x != 0.0 || m_MapPing.y != 0.0) + DrawPing(unitMatrix); PROFILE_END("minimap units");