Ticket #2414: minimapIconHover_v1.patch
File minimapIconHover_v1.patch, 13.0 KB (added by , 10 years ago) |
---|
-
binaries/data/mods/public/gui/session/session.xml
947 947 948 948 <object name="minimapOverlay" size="4 4 100%-4 100%-4" type="image" sprite="stretched:session/minimap_circle_modern.png" ghost="true"/> 949 949 950 <!-- Score Button (deactivated until function is implemented)--> 951 <object size="100%-75 0 100% 75"> 952 <object name="minimap_button[1]" size="0 0 100% 100%" type="button" ghost="true" 953 sprite="stretched:grayscale:session/icons/minimap/score_border.png" 954 sprite_over="stretched:session/icons/minimap/score_border_hover.png" 955 enabled="false"> 956 </object> 957 </object> 958 950 959 <!-- Idle Worker Button --> 951 <object size="100%-36 100%-36 100%-5 100%-5"> 952 <!-- TODO: should highlight the button if there's non-zero idle workers --> 953 <object name="idle-overlay" size="-85 -85 100% 100%" type="image" sprite="stretched:session/minimap-idle.png" ghost="true"/> 954 <!-- Since we don't support non-rectangular buttons, we approximate the area using 3 rectangles TODO: Make this cleaner --> 955 <object type="button" 956 tooltip_style="sessionToolTip" 957 tooltip="Find idle worker" 958 hotkey="selection.idleworker" 959 > 960 <action on="Press">findIdleUnit(["Female", "Trade", "FishingBoat", "CitizenSoldier", "Healer"]);</action> 960 <object size="100%-75 100%-75 100% 100%"> 961 <object name="minimap_button[2]" size="0 0 100% 100%" type="button" ghost="true" 962 sprite="stretched:session/icons/minimap/idle_border.png" 963 sprite_over="stretched:session/icons/minimap/idle_border_hover.png" 964 tooltip_style="sessionToolTip" 965 tooltip="Find idle worker" 966 hotkey="selection.idleworker"> 967 <action on="Press">findIdleUnit(["Female", "Trade", "FishingBoat", "CitizenSoldier", "Healer"]);</action> 961 968 </object> 962 <object type="button" 963 tooltip_style="sessionToolTip" 964 tooltip="Find idle worker" 965 size="15 -15 100% 0" 966 > 967 <action on="Press">findIdleUnit(["Female", "Trade", "FishingBoat", "CitizenSoldier", "Healer"]);</action> 969 </object> 970 971 <!-- Zoom Button (deactivated until function is implemented)--> 972 <object size="0 100%-75 75 100%"> 973 <object name="minimap_button[3]" size="0 0 100% 100%" type="button" ghost="true" 974 sprite="stretched:grayscale:session/icons/minimap/zoom_border.png" 975 sprite_over="stretched:session/icons/minimap/zoom_border_hover.png" 976 enabled="false"> 968 977 </object> 969 <object type="button" 970 tooltip_style="sessionToolTip" 971 tooltip="Find idle worker" 972 size="-15 15 0 100%" 973 > 974 <action on="Press">findIdleUnit(["Female", "Trade", "FishingBoat", "CitizenSoldier", "Healer"]);</action> 978 </object> 979 980 <!-- Flare Button (deactivated until function is implemented)--> 981 <object size="0 0 75 75"> 982 <object name="minimap_button[4]" size="0 0 100% 100%" type="button" ghost="true" 983 sprite="stretched:grayscale:session/icons/minimap/flare_border.png" 984 sprite_over="stretched:session/icons/minimap/flare_border_hover.png" 985 enabled="false"> 975 986 </object> 976 987 </object> 977 988 </object> -
source/gui/IGUIObject.cpp
223 223 } 224 224 } 225 225 226 void IGUIObject::UpdateMouseOverExternCall(IGUIObject * const &pMouseOver) 227 { 228 UpdateMouseOver(pMouseOver); 229 } 230 226 231 bool IGUIObject::SettingExists(const CStr& Setting) const 227 232 { 228 233 // Because GetOffsets will direct dynamically defined -
source/gui/IGUIObject.h
390 390 */ 391 391 void SetFocus(); 392 392 393 /** 394 * calls UpdateMouseOver which is protected; 395 * this should only be used in RARE cases where no other solution can be found. 396 */ 397 void UpdateMouseOverExternCall(IGUIObject * const &pMouseOver); 398 393 399 protected: 394 400 /** 395 401 * Check if object is focused. -
source/gui/MiniMap.cpp
69 69 AddSetting(GUIST_CStr, "tooltip_style"); 70 70 m_Clicking = false; 71 71 m_MouseHovering = false; 72 m_lastHoveredButton = NULL; 73 m_px = 0.5; 74 m_py = 0.5; 72 75 73 76 // Get the maximum height for unit passage in water. 74 77 CParamNode externalParamNode; … … 137 140 138 141 void CMiniMap::HandleMessage(SGUIMessage &Message) 139 142 { 143 // get scaled map coordinates 144 UpdateScaledMapCoordinates(); 145 146 // mouse position is within the circle 147 if (IsPostionInCircle(m_px, m_py)) 148 DisableMinimapButtonHovering(); 149 150 // choose what action should be performed 140 151 switch(Message.type) 141 152 { 142 153 case GUIM_MOUSE_PRESS_LEFT: … … 151 162 case GUIM_MOUSE_RELEASE_LEFT: 152 163 { 153 164 if(m_MouseHovering && m_Clicking) 154 {155 165 SetCameraPos(); 156 } 166 157 167 m_Clicking = false; 158 168 break; 159 169 } … … 160 170 case GUIM_MOUSE_DBLCLICK_LEFT: 161 171 { 162 172 if(m_MouseHovering && m_Clicking) 163 {164 173 SetCameraPos(); 165 } 174 166 175 m_Clicking = false; 167 176 break; 168 177 } … … 175 184 { 176 185 m_Clicking = false; 177 186 m_MouseHovering = false; 187 DisableMinimapButtonHovering(); 178 188 break; 179 189 } 180 190 case GUIM_MOUSE_RELEASE_RIGHT: … … 203 213 default: 204 214 break; 205 215 } // switch 216 217 // check, if mouse position starts after little spacing to the circle 218 if (m_MouseHovering && IsPostionInButtonRange(m_px, m_py)) 219 { 220 int buttonID; 221 GetNumberOfButton(m_px, m_py, buttonID); 222 if (!m_lastHoveredButton && buttonID != 0) 223 { 224 char buttonName[32]; 225 sprintf(buttonName, "minimap_button[%d]", buttonID); 226 227 // get the button and trigger hover effect 228 m_lastHoveredButton = g_GUI->FindObjectByName(buttonName); 229 if (m_lastHoveredButton) 230 m_lastHoveredButton->UpdateMouseOverExternCall(m_lastHoveredButton); 231 } 232 else if(buttonID == 0) 233 DisableMinimapButtonHovering(); 234 else 235 { 236 // let the button handle it's states by itself 237 m_lastHoveredButton->HandleMessage(Message); 238 239 // fix: after release of button hover is not there 240 if (Message.type == GUIM_MOUSE_RELEASE_LEFT || Message.type == GUIM_MOUSE_RELEASE_RIGHT) 241 { 242 // TODO: Why is this not working ?!? How does it work for a "regular" button ? 243 m_lastHoveredButton->UpdateMouseOverExternCall(NULL); 244 m_lastHoveredButton->UpdateMouseOverExternCall(m_lastHoveredButton); 245 } 246 } 247 } 206 248 } 207 249 208 void CMiniMap::Get MouseWorldCoordinates(float& x, float& z)250 void CMiniMap::GetNumberOfButton(float px, float py, int& buttonID) 209 251 { 210 // Determine X and Z according to proportion of mouse position and minimap 252 // get the clock angle 253 float angleFloat; 254 GetClockAngle(px, py, angleFloat); 255 int angle = (int) angleFloat; 256 257 // check, if any button is hit 258 int mod45 = angle % 45; 259 int mod90 = angle % 90; 260 261 // some button is hovered (approximation with angles (45° +- 16°, 135° +- 16°, ...) 262 if ((mod45 <= 16 || (mod45-45) >= -16) && !(mod90 <= 16 || (mod90-90) >= -16)) 263 buttonID = ((int) angle/90) + 1; 264 else 265 buttonID = 0; 266 } 211 267 268 void CMiniMap::DisableMinimapButtonHovering() 269 { 270 if (m_lastHoveredButton) 271 { 272 m_lastHoveredButton->UpdateMouseOverExternCall(NULL); // button is not hovered anymore 273 m_lastHoveredButton = NULL; 274 } 275 } 276 277 void CMiniMap::UpdateScaledMapCoordinates() 278 { 279 GetScaledMapCoordinates(m_px, m_py); 280 } 281 282 void CMiniMap::GetScaledMapCoordinates(float& px, float &py) 283 { 212 284 CPos mousePos = GetMousePos(); 213 285 214 float px = (mousePos.x - m_CachedActualSize.left) / m_CachedActualSize.GetWidth(); 215 float py = (m_CachedActualSize.bottom - mousePos.y) / m_CachedActualSize.GetHeight(); 286 px = (mousePos.x - m_CachedActualSize.left) / m_CachedActualSize.GetWidth(); 287 py = (m_CachedActualSize.bottom - mousePos.y) / m_CachedActualSize.GetHeight(); 288 } 216 289 217 float angle = GetAngle(); 290 void CMiniMap::GetDistanceFromCenter(float px, float py, float& distance) 291 { 292 // calculate distance from center of circle 293 float dx = px-0.5f; 294 float dy = py-0.5f; 295 296 distance = sqrt(dx*dx + dy*dy); 297 } 218 298 219 // Scale world coordinates for shrunken square map 220 x = TERRAIN_TILE_SIZE * m_MapSize * (m_MapScale * (cos(angle)*(px-0.5) - sin(angle)*(py-0.5)) + 0.5); 221 z = TERRAIN_TILE_SIZE * m_MapSize * (m_MapScale * (cos(angle)*(py-0.5) + sin(angle)*(px-0.5)) + 0.5); 299 bool CMiniMap::IsPostionInButtonRange(float px, float py) 300 { 301 float distance; 302 GetDistanceFromCenter(px, py, distance); 303 304 return (distance >= 0.55f); 222 305 } 223 306 307 bool CMiniMap::IsPostionInCircle(float px, float py) 308 { 309 float distance; 310 GetDistanceFromCenter(px, py, distance); 311 312 return (distance <= 0.5f); 313 } 314 315 void CMiniMap::GetClockAngle(float px, float py, float& angleClock) 316 { 317 // set up some points 318 CVector3D center = CVector3D(0.5f, 0.5f, 0.0f); 319 CVector3D vertical = CVector3D(0.5f, 1.0f, 0.0f); 320 CVector3D direction = CVector3D(px, py, 0.0f); 321 322 // calculate vectors 323 CVector3D vc = CVector3D(vertical.X - center.X, vertical.Y - center.Y, 0.0f); 324 CVector3D dc = CVector3D(direction.X - center.X, direction.Y - center.Y, 0.0f); 325 326 // calculate length of vectors 327 float lengthVC = sqrt(vc.X*vc.X + vc.Y*vc.Y); 328 float lengthDC = sqrt(dc.X*dc.X + dc.Y*dc.Y); 329 // calculate scalar prodcut of cectors 330 float scalar = vc.X*dc.X + vc.Y*dc.Y; 331 // calculate angle between two vectors 332 angleClock = acos(scalar / (lengthVC*lengthDC)) * 180.0f / M_PI; 333 334 // check for correct oriantation 335 if (px < 0.5f) 336 { 337 if (py > 0.5f) 338 angleClock = angleClock + 270.0f; 339 else 340 angleClock = angleClock + 90.0f; 341 } 342 } 343 344 void CMiniMap::GetMouseWorldCoordinates(float& x, float& z, int& buttonID) 345 { 346 // inside the circle 347 if (IsPostionInCircle(m_px, m_py)) 348 { 349 float angle = GetAngle(); 350 351 // Scale world coordinates for shrunken square map 352 x = TERRAIN_TILE_SIZE * m_MapSize * (m_MapScale * (cos(angle)*(m_px-0.5) - sin(angle)*(m_py-0.5)) + 0.5); 353 z = TERRAIN_TILE_SIZE * m_MapSize * (m_MapScale * (cos(angle)*(m_py-0.5) + sin(angle)*(m_px-0.5)) + 0.5); 354 buttonID = 0; // set buttonID to dummy value 355 } 356 else if(IsPostionInButtonRange(m_px, m_py)) 357 { 358 GetNumberOfButton(m_px, m_py, buttonID); 359 // set x and z to dummy values 360 x = -1; 361 z = -1; 362 } 363 } 364 224 365 void CMiniMap::SetCameraPos() 225 366 { 226 367 CTerrain* terrain = g_Game->GetWorld()->GetTerrain(); 227 368 228 369 CVector3D target; 229 GetMouseWorldCoordinates(target.X, target.Z); 230 target.Y = terrain->GetExactGroundLevel(target.X, target.Z); 231 g_Game->GetView()->MoveCameraTarget(target); 370 int buttonID; 371 GetMouseWorldCoordinates(target.X, target.Z, buttonID); 372 // click within the circle 373 if (IsPostionInCircle(m_px, m_py)) 374 { 375 target.Y = terrain->GetExactGroundLevel(target.X, target.Z); 376 g_Game->GetView()->MoveCameraTarget(target); 377 } 232 378 } 233 379 234 380 float CMiniMap::GetAngle() … … 239 385 240 386 void CMiniMap::FireWorldClickEvent(int button, int clicks) 241 387 { 388 int buttonID; 242 389 float x, z; 243 GetMouseWorldCoordinates(x, z );390 GetMouseWorldCoordinates(x, z, buttonID); 244 391 245 CScriptValRooted coords; 246 g_GUI->GetActiveGUI()->GetScriptInterface()->Eval("({})", coords); 247 g_GUI->GetActiveGUI()->GetScriptInterface()->SetProperty(coords.get(), "x", x, false); 248 g_GUI->GetActiveGUI()->GetScriptInterface()->SetProperty(coords.get(), "z", z, false); 249 ScriptEvent("worldclick", coords); 392 CScriptValRooted data; 393 g_GUI->GetActiveGUI()->GetScriptInterface()->Eval("({})", data); 394 // click within the circle 395 if (IsPostionInCircle(m_px, m_py)) 396 { 397 g_GUI->GetActiveGUI()->GetScriptInterface()->SetProperty(data.get(), "x", x, false); 398 g_GUI->GetActiveGUI()->GetScriptInterface()->SetProperty(data.get(), "z", z, false); 399 ScriptEvent("worldclick", data); // send the event 400 } 401 250 402 251 403 UNUSED2(button); 252 404 UNUSED2(clicks); -
source/gui/MiniMap.h
20 20 21 21 #include "gui/GUI.h" 22 22 #include "renderer/VertexArray.h" 23 #include <cmath> 23 24 24 25 25 class CCamera; 26 26 class CTerrain; 27 27 … … 83 83 // maximal water height to allow the passage of a unit (for underwater shallows). 84 84 float m_ShallowPassageHeight; 85 85 86 // last hovered button of the minimap 87 IGUIObject* m_lastHoveredButton; 88 89 // scaled x and y values are cached here 90 float m_px, m_py; 91 86 92 void DrawTexture(CShaderProgramPtr shader, float coordMax, float angle, float x, float y, float x2, float y2, float z); 87 93 88 94 void DrawViewRect(); 89 95 90 void GetMouseWorldCoordinates(float& x, float& z); 91 96 void GetMouseWorldCoordinates(float& x, float& z, int& buttonID); 97 void GetDistanceFromCenter(float px, float py, float& distance); 98 void UpdateScaledMapCoordinates(); 99 void GetScaledMapCoordinates(float& px, float &py); 100 bool IsPostionInCircle(float px, float py); 101 bool IsPostionInButtonRange(float px, float py); 102 void GetClockAngle(float px, float py, float& angleClock); 103 void DisableMinimapButtonHovering(); 104 void GetNumberOfButton(float px, float py, int& buttonID); 105 92 106 float GetAngle(); 93 107 94 108 VertexIndexArray m_IndexArray;