OpenClonk
C4MouseControl.cpp
Go to the documentation of this file.
1 /*
2  * OpenClonk, http://www.openclonk.org
3  *
4  * Copyright (c) 1998-2000, Matthes Bender
5  * Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
6  * Copyright (c) 2009-2016, The OpenClonk Team and contributors
7  *
8  * Distributed under the terms of the ISC license; see accompanying file
9  * "COPYING" for details.
10  *
11  * "Clonk" is a registered trademark of Matthes Bender, used with permission.
12  * See accompanying file "TRADEMARK" for details.
13  *
14  * To redistribute this file separately, substitute the full license texts
15  * for the above references.
16  */
17 
18 /* Mouse input */
19 
20 #include "C4Include.h"
21 #include "gui/C4MouseControl.h"
22 
23 #include "control/C4GameControl.h"
24 #include "game/C4Application.h"
25 #include "game/C4FullScreen.h"
26 #include "game/C4Viewport.h"
27 #include "graphics/C4Draw.h"
29 #include "gui/C4ChatDlg.h"
30 #include "gui/C4Gui.h"
31 #include "gui/C4ScriptGuiWindow.h"
32 #include "landscape/C4Landscape.h"
33 #include "lib/StdMesh.h"
34 #include "object/C4Def.h"
35 #include "object/C4Object.h"
36 #include "player/C4Player.h"
37 #include "player/C4PlayerList.h"
38 
39 const int32_t C4MC_Drag_None = 0,
42 
43 const int32_t C4MC_Tooltip_Delay = 20;
44 
46 {
47  Default();
48 }
49 
51 {
52  Clear();
53 }
54 
56 {
57  Active=false;
59  pPlayer=nullptr;
60  Viewport=nullptr;
61  Cursor=0;
62  Caption.Clear();
64  VpX=VpY=0;
65  DownX=DownY=0;
66  ViewX=ViewY=0;
67  GuiX=GuiY=GameX=GameY=0;
69  LeftDoubleIgnoreUp=false;
71  Visible=true;
72  InitCentered=false;
73  FogOfWar=false;
75  DragObject=nullptr;
76  KeepCaption=0;
79  TargetObject=DownTarget=nullptr;
80  ControlDown=false;
81  ShiftDown=false;
82  AltDown=false;
83  Scrolling=false;
84  ScrollSpeed=10;
85  DragImageDef=nullptr;
86  DragImageObject=nullptr;
87  fMouseOwned = true; // default mouse owned
89 }
90 
92 {
93  Active = false;
94  Selection.Clear();
95  UpdateClip(); // reset mouse clipping!
96 }
97 
99 {
100 
101  if (!Active || !fMouseOwned) return;
102 
103  // Scrolling/continuous update
104  if (Scrolling || !::Game.iTick5)
105  {
106  WORD wKeyState=0;
107  if (ControlDown) wKeyState|=MK_CONTROL;
108  if (ShiftDown) wKeyState|=MK_SHIFT;
109  if (AltDown) wKeyState|=MK_ALT;
110  Move(C4MC_Button_None, VpX, VpY, wKeyState);
111  }
112 }
113 
114 bool C4MouseControl::Init(int32_t iPlayer)
115 {
116  Clear();
117  Default();
118  Active = true;
119  Player = iPlayer;
120  InitCentered = false;
121  UpdateClip();
122  return true;
123 }
124 
126 {
127  if (TargetObject==pObj) TargetObject=nullptr;
128  if (DownTarget==pObj) DownTarget=nullptr;
129  if (DragObject==pObj)
130  {
131  DragObject=nullptr;
133  DragImageDef=nullptr;
134  DragImageObject=nullptr;
135  }
136  Selection.ClearPointers(pObj);
137 }
138 
140 {
141  return (Viewport==pViewport);
142 }
143 
145 {
146 #ifdef _DEBUG
147  // never in debug
148  return;
149 #endif
150 #ifdef USE_WIN32_WINDOWS
151  // fullscreen only
152  if (Application.isEditor) return;
153  // application or mouse control not active? remove any clips
154  if (!Active || !Application.Active || ::pGUI->HasMouseFocus()) { ClipCursor(nullptr); return; }
155  // get controlled viewport
157  if (!pVP) { ClipCursor(nullptr); return; }
158  // adjust size by viewport size
159  RECT vpRct;
160  vpRct.left=pVP->OutX; vpRct.top=pVP->OutY; vpRct.right=pVP->OutX+pVP->ViewWdt; vpRct.bottom=pVP->OutY+pVP->ViewHgt;
161  // adjust by window pos
162  RECT rtWindow;
163  if (GetWindowRect(FullScreen.hWindow, &rtWindow))
164  {
165  vpRct.left += rtWindow.left; vpRct.top += rtWindow.top;
166  vpRct.right += rtWindow.left; vpRct.bottom+= rtWindow.top;
167  }
168  ClipCursor(&vpRct);
169  // and inform GUI
170  ::pGUI->SetPreferredDlgRect(C4Rect(pVP->OutX, pVP->OutY, pVP->ViewWdt, pVP->ViewHgt));
171 #endif
172  //StdWindow manages this.
173 }
174 
175 void C4MouseControl::Move(int32_t iButton, int32_t iX, int32_t iY, DWORD dwKeyFlags, bool fCenter)
176 {
177  // Control state
178  ControlDown=false; if (dwKeyFlags & MK_CONTROL) ControlDown=true;
179  ShiftDown=false; if (dwKeyFlags & MK_SHIFT) ShiftDown=true;
180  AltDown=false; if(dwKeyFlags & MK_ALT) AltDown=true;
181  // Active
182  if (!Active || !fMouseOwned) return;
183  // Execute caption
184  if (KeepCaption) KeepCaption--; else { Caption.Clear(); CaptionBottomY=0; }
185  // Check player
186  if (Player>NO_OWNER)
187  {
189  if (!pPlayer) { Active=false; return; }
190  }
191  else
192  pPlayer = nullptr;
193  // Check viewport
194  if (!(Viewport=::Viewports.GetViewport(Player))) return;
195  // get view position
196  C4Rect rcViewport = Viewport->GetOutputRect();
197  fctViewport.Set(nullptr, rcViewport.x, rcViewport.y, rcViewport.Wdt, rcViewport.Hgt);
201  // First time viewport attachment: center mouse
202 #ifdef USE_WIN32_WINDOWS
203  if (!InitCentered || fCenter)
204  {
205  iX = Viewport->ViewWdt/2;
206  iY = Viewport->ViewHgt/2;
207  if (!Application.isEditor)
208  {
209  int32_t iMidX = Viewport->OutX + iX;
210  int32_t iMidY = Viewport->OutY + iY;
211  RECT rtWindow;
212  if (GetWindowRect(Application.pWindow->hWindow, &rtWindow))
213  {
214  iMidX += rtWindow.left; iMidY += rtWindow.top;
215  }
216  SetCursorPos(iMidX, iMidY);
217  }
218  InitCentered = true;
219  }
220 #else
221  if (!InitCentered || fCenter)
222  {
223  iX = Viewport->ViewWdt/2;
224  iY = Viewport->ViewHgt/2;
225  InitCentered = true;
226  }
227 #endif
228  // passive mode: scrolling and player buttons only
229  if (IsPassive())
230  {
231  if (iButton != C4MC_Button_Wheel)
232  {
233  VpX=iX; VpY=iY;
235  GuiX=float(VpX)/Viewport->GetGUIZoom(); GuiY=float(VpY)/Viewport->GetGUIZoom();
236  }
237  UpdateScrolling();
238  if (iButton == C4MC_Button_LeftDown) LeftDown();
239  else if (iButton == C4MC_Button_LeftUp) LeftUp();
240  else UpdateCursorTarget();
241  return;
242  }
243 
244  if (iButton != C4MC_Button_Wheel)
245  {
246  // Position
247  VpX=iX; VpY=iY;
249  GuiX=float(VpX)/Viewport->GetGUIZoom(); GuiY=float(VpY)/Viewport->GetGUIZoom();
250  // Scrolling
251  UpdateScrolling();
252  // Fog of war
253  UpdateFogOfWar();
254 
255  // Blocked by fog of war: evaluate button up, dragging and region controls only
256  if (FogOfWar && Drag == C4MC_Drag_None)
257  {
258  // Left button up
259  if (iButton==C4MC_Button_LeftUp)
260  {
261  LeftButtonDown=false;
262  // End any drag
264  }
265  // Right button up
266  if (iButton==C4MC_Button_RightUp)
267  {
268  RightButtonDown=false;
269  }
270  }
271  }
272 
273  // Move execution by button/drag status
274  switch (iButton)
275  {
276  //------------------------------------------------------------------------------------------
277  case C4MC_Button_None:
278  switch (Drag)
279  {
280  case C4MC_Drag_Unhandled: break; // nothing to do
281  case C4MC_Drag_None: DragNone(); break;
282  case C4MC_Drag_Script: DragScript(); break;
283  }
284  break;
285  //------------------------------------------------------------------------------------------
286  case C4MC_Button_LeftDown: LeftDown(); break;
287  //------------------------------------------------------------------------------------------
288  case C4MC_Button_LeftUp: LeftUp(); break;
289  //------------------------------------------------------------------------------------------
290  case C4MC_Button_LeftDouble: LeftDouble(); break;
291  //------------------------------------------------------------------------------------------
292  case C4MC_Button_RightDown: RightDown(); break;
293  //------------------------------------------------------------------------------------------
294  case C4MC_Button_RightUp: RightUp(); break;
295  //------------------------------------------------------------------------------------------
296  case C4MC_Button_Wheel: Wheel(dwKeyFlags); break;
297  }
298 
299  // are custom menus active?
300  bool menuProcessed = false;
301  if (pPlayer)
302  // adjust by viewport X/Y because the GUI windows calculate their positions (and thus check input) based on that
303  menuProcessed = ::Game.ScriptGuiRoot->MouseInput(iButton, iX, iY, dwKeyFlags);
304 
305  if (menuProcessed)
307 
308  // if not caught by a menu
309  if (!menuProcessed)
310  // script handling of mouse control for everything but regular movement (which is sent at control frame intervals only)
311  if (iButton != C4MC_Button_None)
312  // not if blocked by selection object
313  if (!TargetObject)
314  // safety (can't really happen in !IsPassive, but w/e
315  if (pPlayer && pPlayer->ControlSet)
316  if (!menuProcessed && pPlayer->ControlSet->IsMouseControlAssigned(iButton))
317  pPlayer->Control.DoMouseInput(0 /* only 1 mouse supported so far */, iButton, GameX, GameY, GuiX, GuiY, dwKeyFlags);
318 }
319 
321 {
322  // current mouse move to input queue
323  // do sanity checks
324  if (!Active || !fMouseOwned) return;
325  if (!(pPlayer=::Players.Get(Player))) return;
326  if (!pPlayer->ControlSet) return;
328  pPlayer->Control.DoMouseInput(0 /* only 1 mouse supported so far */, C4MC_Button_None, GameX, GameY, GuiX, GuiY, (ControlDown && MK_CONTROL) | (ShiftDown && MK_SHIFT) | (AltDown && MK_ALT));
329 }
330 
331 void C4MouseControl::Draw(C4TargetFacet &cgo, const ZoomData &GameZoom)
332 {
333  int32_t iOffsetX,iOffsetY;
334  float wdt = GfxR->fctMouseCursor.Wdt, hgt = GfxR->fctMouseCursor.Hgt;
335  // Cursor size relative to height - does not matter with current square graphics.
336  float zoom = Config.Graphics.MouseCursorSize / hgt;
337  hgt *= zoom;
338  wdt *= zoom;
339 
340  ZoomData GuiZoom;
341  pDraw->GetZoom(&GuiZoom);
342 
343  // Hidden
344  if (!Visible || !fMouseOwned) return;
345 
346  // Draw selection
347  if (!IsPassive())
348  {
350  }
351 
352  // Draw control
353  switch (Drag)
354  {
355  //------------------------------------------------------------------------------------------
357  // Hotspot offset: Usually, hotspot is in center
358  iOffsetX = wdt/2;
359  iOffsetY = hgt/2;
360  // calculate the hotspot for the scrolling cursors
361  switch (Cursor)
362  {
363  case C4MC_Cursor_Up: iOffsetY += -hgt/2; break;
364  case C4MC_Cursor_Down:iOffsetY += +hgt/2; break;
365  case C4MC_Cursor_Left: iOffsetX += -wdt/2; break;
366  case C4MC_Cursor_Right: iOffsetX += +wdt/2; break;
367  case C4MC_Cursor_UpLeft: iOffsetX += -wdt/2; iOffsetY += -hgt/2; break;
368  case C4MC_Cursor_UpRight: iOffsetX += +wdt/2; iOffsetY += -hgt/2; break;
369  case C4MC_Cursor_DownLeft: iOffsetX += -wdt/2; iOffsetY += +hgt/2; break;
370  case C4MC_Cursor_DownRight: iOffsetX += +wdt/2; iOffsetY += +hgt/2; break;
371  }
372  // Drag image
374  {
375  C4DefGraphics* pGfx;
376  if(DragImageObject)
377  pGfx = DragImageObject->GetGraphics();
378  else
379  pGfx = &DragImageDef->Graphics;
380 
381  // Determine image boundaries
382  float ImageWdt;
383  float ImageHgt;
384  if (pGfx->Type == C4DefGraphics::TYPE_Bitmap)
385  {
387  ImageWdt = Def->PictureRect.Wdt;
388  ImageHgt = Def->PictureRect.Hgt;
389  }
390  else if (pGfx->Type == C4DefGraphics::TYPE_Mesh)
391  {
392  // Note bounding box is in OGRE coordinate system
393  ImageWdt = pGfx->Mesh->GetBoundingBox().y2 - pGfx->Mesh->GetBoundingBox().y1;
394  ImageHgt = pGfx->Mesh->GetBoundingBox().z2 - pGfx->Mesh->GetBoundingBox().z1;
395  }
396  else
397  {
398  ImageWdt = ImageHgt = 1.0f;
399  }
400 
401  // zoom mode: Drag in GUI or Game depending on source object
402  bool fIsGameZoom = true;
404  fIsGameZoom = false;
405  // drag image in game zoom
406  float XDraw, YDraw, ZoomDraw;
407  if (fIsGameZoom)
408  {
409  pDraw->SetZoom(GameZoom);
410  XDraw = GameX; YDraw = GameY;
411  ZoomDraw = 1.0f;
412  }
413  else
414  {
415  ZoomDraw = std::min(64.0f / ImageWdt, 64.0f / ImageHgt);
416  XDraw = GuiX; YDraw = GuiY;
417  }
418 
419  iOffsetX=int(ZoomDraw*ImageWdt/2);
420  iOffsetY=int(ZoomDraw*ImageHgt/2);
421 
422  C4TargetFacet ccgo;
423  ccgo.Set(cgo.Surface, XDraw + cgo.X - iOffsetX, YDraw + cgo.Y - iOffsetY, float(ImageWdt)*ZoomDraw, float(ImageHgt)*ZoomDraw);
424 
425  if (DragImageObject)
426  {
427  uint32_t ColorMod = DragImageObject->ColorMod;
428  uint32_t BlitMode = DragImageObject->BlitMode;
429  DragImageObject->ColorMod = (Drag == C4MC_Drag_Script) ? 0x7fffffff : (/*DragImagePhase*/false ? 0x8f7f0000 : 0x1f007f00);
431 
432  DragImageObject->DrawPicture(ccgo, false, nullptr);
433 
434  DragImageObject->ColorMod = ColorMod;
435  DragImageObject->BlitMode = BlitMode;
436  }
437  else
438  {
439  // draw in special modulation mode
441  // draw DragImage in red or green, according to the phase to be used
442  pDraw->ActivateBlitModulation((Drag == C4MC_Drag_Script) ? 0x7fffffff : (/*DragImagePhase*/false ? 0x8f7f0000 : 0x1f007f00));
443 
444  DragImageDef->Draw(ccgo, false, pPlayer ? pPlayer->ColorDw : 0xff0000ff, nullptr, 0, 0, nullptr);
445 
446  // reset color
448  pDraw->SetBlitMode(0);
449  }
450 
451  if (fIsGameZoom) pDraw->SetZoom(GuiZoom);
452  // reset cursor hotspot offset for script drawing
453  iOffsetX = wdt/2;
454  iOffsetY = hgt/2;
455  }
456  // Cursor
458  {
459  GfxR->fctMouseCursor.DrawX(cgo.Surface, cgo.X+GuiX-iOffsetX, cgo.Y+GuiY-iOffsetY, wdt, hgt, Cursor);
460  }
461  break;
462  //------------------------------------------------------------------------------------------
463  }
464 
465  // Draw caption
466  if (Caption && ::pGUI)
467  {
468  C4TargetFacet cgoTip;
469  cgoTip = static_cast<const C4Facet &>(cgo);
470  C4GUI::Screen::DrawToolTip(Caption.getData(), cgoTip, cgo.X+GuiX, cgo.Y+GuiY);
471  }
472 
473 }
474 
476 {
477  C4Object* OldTargetObject = TargetObject;
478 
479  if (Scrolling)
480  {
481  // Scrolling: no other target
482  TargetObject=nullptr;
483  }
484  else
485  {
486  // Target object
489 
490  // Movement
492 
493  // Target action
494  if (TargetObject && !IsPassive())
495  {
496  // default cursor for object; also set if not in FoW
498 
499  // select custom region. Can select an object if it does not have the MD_NoClick
500  // flag set. If we are currently dragging then selection depends on it being a drop target.
501  bool CanSelect;
502  if(Drag == C4MC_Drag_Script)
504  else
506 
507  if ( (TargetObject->Category & C4D_MouseSelect) && CanSelect)
509  else
510  TargetObject = nullptr;
511  }
512 
513  // passive cursor
514  if (IsPassive())
516 
517  // update tooltip information
518  if (OldTargetObject != TargetObject)
519  {
520  C4String *newTooltip = nullptr;
522  {
523  float objX, objY;
525  objX += TargetObject->Shape.x;
526  objY += TargetObject->Shape.y - TargetObject->addtop();
528  SetTooltipText(StdStrBuf(newTooltip->GetCStr()));
529  }
530  else
531  {
532  SetTooltipRectangle(C4Rect(0, 0, 0, 0));
533  }
534  }
535 
536  if (!KeepCaption
537  && ToolTipRectangle.Wdt != 0
540  {
542 
544  {
546  }
547  }
548  else
549  {
550  // disable tooltip pop-up; whatever set it in the first place will set it again on the next mouse-enter
552  ToolTipRectangle.Wdt = 0;
553  }
554  }
555 
556  // Make a script callback if the object being hovered changes
557  if(!IsPassive() && OldTargetObject != TargetObject)
558  {
559  // TODO: This might put a heavy load on the network, depending on the number of
560  // selectable objects around. If it turns out to be a problem we might want to
561  // deduce these hover callbacks client-side instead.
562  // Or, make sure to send this at most once per control frame.
564  }
565 }
566 
568 {
569  // Set single selection if cursor on selection object (clear prior object selection)
572 
573  // Cursor has moved off single object (or target object) selection: clear selection
574  else if (Selection.GetObject())
577  Selection.Clear();
578 
579  return Selection.ObjectCount();
580 }
581 
583 {
584  // Assume no scrolling
585  Scrolling=false;
586  // No scrolling if disabled by player
587  if (pPlayer) if (pPlayer->IsViewLocked()) return;
588  // Scrolling on border
589  if (VpX==0)
591  if (VpY==0)
593  if (VpX==Viewport->ViewWdt-1)
595  if (VpY==Viewport->ViewHgt-1)
597  // Set correct cursor
598  if ((VpX==0) && (VpY==0)) Cursor=C4MC_Cursor_UpLeft;
599  if ((VpX==Viewport->ViewWdt-1) && (VpY==0)) Cursor=C4MC_Cursor_UpRight;
600  if ((VpX==0) && (VpY==Viewport->ViewHgt-1)) Cursor=C4MC_Cursor_DownLeft;
602 }
603 
605 {
606  // Set flag
607  LeftButtonDown=true;
608  // Store down values (same MoveRightDown -> use StoreDown)
611 }
612 
614 {
615  // Ignore left up after double click
616  if (LeftDoubleIgnoreUp)
617  {
618  LeftDoubleIgnoreUp=false;
619  }
620  else
621  {
622  // Evaluate by drag status
623  switch (Drag)
624  {
625  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
626  case C4MC_Drag_Unhandled: // nobreak
627  case C4MC_Drag_None: LeftUpDragNone(); break;
628  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
629  case C4MC_Drag_Script: ButtonUpDragScript(); break;
630  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
631  }
632  }
633  // Update status flag
634  LeftButtonDown=false;
635  if(!RightButtonDown) DownTarget = nullptr;
636 }
637 
639 {
640  // Cursor movement
642  // Update selection
644 
645  // Button down: begin drag
648  {
649  bool fAllowDrag = true;
650  // check if target object allows scripted dragging
651  if (fAllowDrag && DownTarget && (!FogOfWar || (DownTarget->Category & C4D_IgnoreFoW)))
652  {
653  C4Object *drag_image_obj; C4Def * drag_image_def;
654 
655  // Drag only if MD_SOURCE is set and drag image is present
657  DownTarget->GetDragImage(&drag_image_obj, &drag_image_def))
658  {
660 
661  if(drag_image_obj) DragImageObject = drag_image_obj;
662  else DragImageDef = drag_image_def;
663 
665  }
666  }
667 
668  // dragging somewhere unhandled - mark drag process so moving over a draggable object won't start a drag
669  if (Drag == C4MC_Drag_None)
670  {
672  }
673  }
674 }
675 
677 {
678  // Update status flag
679  LeftButtonDown=false;
680  // Set ignore flag for next left up
681  LeftDoubleIgnoreUp=true;
682  // Evaluate left double by drag status (can only be C4MC_Drag_None really)
683  switch (Drag)
684  {
685  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
686  case C4MC_Drag_None:
687  // Double left click (might be on a target)
688  break;
689  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
690  }
691 }
692 
694 {
695  // Update status flag
696  RightButtonDown=true;
697  // Store down values (same MoveLeftDown -> use StoreDown)
700 }
701 
703 {
704  // Evaluate by drag status
705  switch (Drag)
706  {
707  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
708  case C4MC_Drag_Unhandled: // nobreak
709  case C4MC_Drag_None: RightUpDragNone(); break;
710  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
711  case C4MC_Drag_Script: ButtonUpDragScript(); break;
712  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
713  }
714  // Update status flag
715  RightButtonDown=false;
716  if(!LeftButtonDown) DownTarget = nullptr;
717 }
718 
720 {
721 }
722 
724 {
725  // script drag should update target and selection so selection highlight on drop target is visible
726  // Cursor movement
728  // Update selection
731 }
732 
734 {
735  // might be in Drag_Unknown
737  // Single left click (might be on a target)
738  switch (Cursor)
739  {
740  case C4MC_Cursor_Select:
741  // Object selection to control queue
742  if (!IsPassive() && Selection.GetObject() == DownTarget)
744  break;
745  default:
746  // done in script
747  break;
748  }
749  // Clear selection
750  Selection.Clear();
751 }
752 
754 {
755  // Determine drag+drop targets
757  // Finish drag
760  DragImageObject = nullptr;
761  DragImageDef = nullptr;
762  C4Object *DragObject = this->DragObject;
763  this->DragObject = nullptr;
764  C4Object *DropObject = TargetObject;
765  // drag object must exist; drop object is optional
766  if (!DragObject) return;
767  if (DropObject && (~DropObject->GetPropertyInt(P_MouseDrag) & C4MC_MD_DropTarget))
768  DropObject = nullptr;
769  // no commands if player is eliminated or doesn't exist any more
770  C4Player *pPlr = ::Players.Get(Player);
771  if (!pPlr || pPlr->Eliminated) return;
772  // todo: Perform drag/drop validity check
773  // now drag/drop is handled by script
775 }
776 
778 {
779 
780  // might be in Drag_Unknown
782 
783  // Alternative object selection
786 
787  // TODO: Evaluate right click
788 
789 }
790 
792 {
793  // Assume no fog of war
794  FogOfWar=false;
795  // Check for fog of war
796  // TODO: Check C4FoWRegion... should maybe be passed as a parameter?
797  // pDraw->GetFoW() might not be current at this time.
798  if (/*(pPlayer->fFogOfWar && !pPlayer->FoWIsVisible(int32_t(GameX),int32_t(GameY))) || */GameX<0 || GameY<0 || int32_t(GameX)>=::Landscape.GetWidth() || int32_t(GameY)>=::Landscape.GetHeight())
799  {
800  FogOfWar=true;
801  // allow dragging, scrolling, region selection and manipulations of objects not affected by FoW
803  {
805  }
806  }
807 }
808 
810 {
811  Visible=true;
812 }
813 
815 {
816  Visible=false;
817 }
818 
820 {
821  return Caption.getData();
822 }
823 
825 {
826  // Set the tooltip rectangle slightly larger than originally requested.
827  // The tooltip will be removed when the cursor leaves the rectangle, so make sure that the tooltip is not already disabled when the cursor moves to the border-pixel of the GUI item
828  // in case the GUI item uses a different check for bounds (< vs <=) than the tooltip rectangle.
829  ToolTipRectangle = C4Rect(rectangle.x - 2, rectangle.y - 2, rectangle.Wdt + 4, rectangle.Hgt + 4);
831 }
832 
834 {
835  TooltipText = text;
836 }
837 
839 {
840  // find object
841  // gui object position currently wrong...will fall apart once GUIZoom is activated
843  if (!pObj) return nullptr;
844  return pObj;
845 }
846 
848 {
850 }
851 
852 void C4MouseControl::ScrollView(float iX, float iY, float ViewWdt, float ViewHgt)
853 {
854  // player assigned: scroll player view
855  if (pPlayer)
856  pPlayer->ScrollView(iX, iY, ViewWdt, ViewHgt);
857  else if (Viewport)
858  {
859  // no player: Scroll fullscreen viewport
860  Viewport->ScrollView(iX, iY);
861  }
862 
863 }
864 
866 {
867  return Active && Drag == C4MC_Drag_Script;
868 }
869 
870 bool C4MouseControl::GetLastCursorPos(int32_t *x_out_gui, int32_t *y_out_gui, int32_t *x_out_game, int32_t *y_out_game) const
871 {
872  // safety
873  if (!Active || !fMouseOwned) return false;
874  // OK; assign last known pos
875  *x_out_gui = GuiX; *y_out_gui = GuiY;
876  *x_out_game = GameX; *y_out_game = GameY;
877  return true;
878 }
C4Config Config
Definition: C4Config.cpp:930
const int NO_OWNER
Definition: C4Constants.h:137
const int32_t C4D_Foreground
Definition: C4Def.h:53
const int32_t C4D_IgnoreFoW
Definition: C4Def.h:55
const int32_t C4D_MouseSelect
Definition: C4Def.h:52
C4Draw * pDraw
Definition: C4Draw.cpp:42
C4GameControl Control
C4Game Game
Definition: C4Globals.cpp:52
C4Application Application
Definition: C4Globals.cpp:44
C4FullScreen FullScreen
Definition: C4Globals.cpp:46
#define GfxR
C4GUIScreen * pGUI
Definition: C4Gui.cpp:1191
C4Landscape Landscape
const int32_t C4MC_Drag_Unhandled
const int32_t C4MC_Drag_None
const int32_t C4MC_Tooltip_Delay
const int32_t C4MC_Drag_Script
const int32_t C4MC_Cursor_Passive
const int32_t C4MC_Cursor_Left
const int32_t C4MC_Cursor_Up
const int32_t C4MC_Button_None
const int32_t C4MC_DragSensitivity
const int32_t C4MC_Button_RightDown
const int32_t C4MC_Cursor_DownRight
const int32_t C4MC_Button_RightUp
const int32_t C4MC_Cursor_Crosshair
const int32_t C4MC_MD_DragSource
const int32_t C4MC_Cursor_DownLeft
const int32_t C4MC_Cursor_Down
const int32_t C4MC_Cursor_DragDrop
const int32_t C4MC_Button_LeftUp
const int32_t C4MC_Cursor_Select
const int32_t C4MC_Cursor_UpRight
const int32_t C4MC_Button_LeftDown
const int32_t C4MC_Button_LeftDouble
const int32_t C4MC_MD_NoClick
const int32_t C4MC_Cursor_Right
const int32_t C4MC_MD_DropTarget
const int32_t C4MC_Cursor_UpLeft
const int32_t C4MC_Button_Wheel
@ CID_PlrSelect
Definition: C4PacketBase.h:162
@ CID_PlrMouseMove
Definition: C4PacketBase.h:167
C4PlayerList Players
@ P_MouseDrag
@ P_Tooltip
#define C4GFXBLIT_MOD2
Definition: C4Surface.h:27
C4ViewportList Viewports
uint16_t WORD
uint32_t DWORD
T Abs(T val)
Definition: Standard.h:42
bool Inside(T ival, U lbound, V rbound)
Definition: Standard.h:43
bool Active
Definition: C4App.h:63
C4Window * pWindow
Definition: C4App.h:80
int32_t MouseCursorSize
Definition: C4Config.h:118
C4ConfigGraphics Graphics
Definition: C4Config.h:257
void Add(C4PacketType eType, C4ControlPacket *pCtrl)
Definition: C4Control.h:82
static C4ControlPlayerMouse * Hover(const C4Player *player, const C4Object *target, const C4Object *old_target, const C4Object *drag=nullptr)
Definition: C4Control.cpp:446
static C4ControlPlayerMouse * DragDrop(const C4Player *player, const C4Object *target, const C4Object *drag)
Definition: C4Control.cpp:459
GraphicsType Type
Definition: C4DefGraphics.h:48
Definition: C4Def.h:99
C4DefGraphics Graphics
Definition: C4Def.h:191
C4Rect PictureRect
Definition: C4Def.h:107
void Draw(C4Facet &cgo, bool fSelected=false, DWORD iColor=0, C4Object *pObj=nullptr, int32_t iPhaseX=0, int32_t iPhaseY=0, C4DrawTransform *trans=nullptr, const char *graphicsName=nullptr)
Definition: C4Def.cpp:607
void GetZoom(ZoomData *r)
Definition: C4Draw.h:197
void SetBlitMode(DWORD dwBlitMode)
Definition: C4Draw.h:191
void DeactivateBlitModulation()
Definition: C4Draw.h:189
void SetZoom(float X, float Y, float Zoom)
Definition: C4Draw.cpp:773
void ActivateBlitModulation(DWORD dwWithClr)
Definition: C4Draw.h:188
void Set(C4Surface &rSfc)
Definition: C4Facet.cpp:459
C4Surface * Surface
Definition: C4Facet.h:117
void Default()
Definition: C4Facet.cpp:31
float Y
Definition: C4Facet.h:118
float X
Definition: C4Facet.h:118
void SetPreferredDlgRect(const C4Rect &rtNewPref)
Definition: C4Gui.h:2651
static void DrawToolTip(const char *szTip, C4TargetFacet &cgo, float guix, float guiy)
Definition: C4Gui.cpp:1009
bool HasMouseFocus()
Definition: C4Gui.h:2678
bool isReplay() const
Definition: C4GameControl.h:98
std::unique_ptr< C4ScriptGuiWindow > ScriptGuiRoot
Definition: C4Game.h:234
C4Object * FindVisObject(float x, float y, int32_t player_nr, const C4Facet &viewport_game, const C4Facet &viewport_gui, float game_x, float game_y, DWORD category, float gui_x, float gui_y)
Definition: C4Game.cpp:1536
C4Control & Input
Definition: C4Game.h:82
int32_t iTick5
Definition: C4Game.h:130
static const C4ID None
Definition: C4Id.h:39
int32_t GetWidth() const
int32_t GetHeight() const
C4Viewport * Viewport
void SetTooltipText(const StdStrBuf &text)
void Draw(C4TargetFacet &cgo, const ZoomData &GameZoom)
bool IsViewport(C4Viewport *pViewport)
C4Facet fctViewport
StdCopyStrBuf Caption
C4Facet fctViewportGame
C4ObjectList Selection
C4Rect ToolTipRectangle
StdCopyStrBuf TooltipText
bool GetLastCursorPos(int32_t *x_out_gui, int32_t *y_out_gui, int32_t *x_out_game, int32_t *y_out_game) const
void ScrollView(float iX, float iY, float ViewWdt, float ViewHgt)
int32_t ScrollSpeed
const char * GetCaption()
void Move(int32_t iButton, int32_t iX, int32_t iY, DWORD dwKeyFlags, bool fCenter=false)
bool ButtonDownOnSelection
int32_t UpdateSingleSelection()
C4Object * GetTargetObject()
C4Object * TargetObject
C4Def * DragImageDef
C4Object * DownTarget
void SetTooltipRectangle(const C4Rect &rectangle)
C4Object * DragObject
C4Facet fctViewportGUI
C4Object * DragImageObject
void Wheel(DWORD dwFlags)
int32_t TimeInTooltipRectangle
bool Init(int32_t iPlayer)
void ClearPointers(C4Object *pObj)
int32_t CaptionBottomY
C4Player * pPlayer
void GetViewPos(float &riX, float &riY, float tx, float ty, const C4Facet &fctViewport) const
void DrawPicture(C4Facet &cgo, bool fSelected=false, C4DrawTransform *transform=nullptr)
int32_t Category
Definition: C4Object.h:111
bool GetDragImage(C4Object **drag_object, C4Def **drag_id) const
uint32_t BlitMode
Definition: C4Object.h:161
uint32_t ColorMod
Definition: C4Object.h:160
C4Def * Def
Definition: C4Object.h:141
int32_t addtop() const
Definition: C4Object.h:280
C4Shape Shape
Definition: C4Object.h:146
C4DefGraphics * GetGraphics() const
Definition: C4Object.h:339
virtual void Clear()
virtual void Default()
void DrawSelectMark(C4TargetFacet &cgo) const
virtual bool Add(C4Object *new_obj, SortType sort_type, C4ObjectList *sorted_list=nullptr)
int ObjectCount(C4ID id=C4ID::None) const
int ClearPointers(C4Object *obj)
C4Object * GetObject(int index=0) const
bool IsMouseControlAssigned(int32_t mouseevent) const
bool DoMouseInput(uint8_t mouse_id, int32_t mouseevent, float game_x, float game_y, float gui_x, float gui_y, DWORD flags)
int32_t Eliminated
Definition: C4Player.h:83
uint32_t ColorDw
Definition: C4Player.h:89
bool ObjectInCrew(C4Object *tobj)
Definition: C4Player.cpp:90
C4PlayerControl Control
Definition: C4Player.h:129
class C4PlayerControlAssignmentSet * ControlSet
Definition: C4Player.h:90
bool IsViewLocked() const
Definition: C4Player.h:204
void ScrollView(float iX, float iY, float ViewWdt, float ViewHgt)
Definition: C4Player.cpp:1364
C4Player * Get(int iPlayer) const
int32_t GetPropertyInt(C4PropertyName k, int32_t default_val=0) const
Definition: C4PropList.cpp:855
C4String * GetPropertyStr(C4PropertyName k) const
Definition: C4PropList.cpp:744
Definition: C4Rect.h:28
int32_t y
Definition: C4Rect.h:30
int32_t Hgt
Definition: C4Rect.h:30
int32_t Wdt
Definition: C4Rect.h:30
int32_t x
Definition: C4Rect.h:30
const char * GetCStr() const
Definition: C4StringTable.h:49
void Set(const C4Facet &cpy)
Definition: C4Facet.h:182
float Zoom
Definition: C4Viewport.h:104
C4Rect GetOutputRect()
Definition: C4Viewport.h:67
C4TargetFacet last_gui_draw_cgo
Definition: C4Viewport.h:44
int32_t ViewWdt
Definition: C4Viewport.h:36
float GetViewY()
Definition: C4Viewport.h:78
int32_t OutY
Definition: C4Viewport.h:110
int32_t OutX
Definition: C4Viewport.h:110
int32_t ViewHgt
Definition: C4Viewport.h:37
void ScrollView(float by_x, float by_y)
Definition: C4Viewport.cpp:882
C4TargetFacet last_game_draw_cgo
Definition: C4Viewport.h:43
float GetGUIZoom() const
Definition: C4Viewport.h:50
float GetViewX()
Definition: C4Viewport.h:76
C4Viewport * GetViewport(int32_t player_nr, C4Viewport *prev=nullptr)
const char * getData() const
Definition: StdBuf.h:442
void Clear()
Definition: StdBuf.h:466