OpenClonk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros
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  Move(C4MC_Button_None, VpX, VpY, wKeyState);
110  }
111 }
112 
113 bool C4MouseControl::Init(int32_t iPlayer)
114 {
115  Clear();
116  Default();
117  Active = true;
118  Player = iPlayer;
119  InitCentered = false;
120  UpdateClip();
121  return true;
122 }
123 
125 {
126  if (TargetObject==pObj) TargetObject=nullptr;
127  if (DownTarget==pObj) DownTarget=nullptr;
128  if (DragObject==pObj)
129  {
130  DragObject=nullptr;
132  DragImageDef=nullptr;
133  DragImageObject=nullptr;
134  }
135  Selection.ClearPointers(pObj);
136 }
137 
139 {
140  return (Viewport==pViewport);
141 }
142 
144 {
145 #ifdef _DEBUG
146  // never in debug
147  return;
148 #endif
149 #ifdef USE_WIN32_WINDOWS
150  // fullscreen only
151  if (Application.isEditor) return;
152  // application or mouse control not active? remove any clips
153  if (!Active || !Application.Active || ::pGUI->HasMouseFocus()) { ClipCursor(nullptr); return; }
154  // get controlled viewport
156  if (!pVP) { ClipCursor(nullptr); return; }
157  // adjust size by viewport size
158  RECT vpRct;
159  vpRct.left=pVP->OutX; vpRct.top=pVP->OutY; vpRct.right=pVP->OutX+pVP->ViewWdt; vpRct.bottom=pVP->OutY+pVP->ViewHgt;
160  // adjust by window pos
161  RECT rtWindow;
162  if (GetWindowRect(FullScreen.hWindow, &rtWindow))
163  {
164  vpRct.left += rtWindow.left; vpRct.top += rtWindow.top;
165  vpRct.right += rtWindow.left; vpRct.bottom+= rtWindow.top;
166  }
167  ClipCursor(&vpRct);
168  // and inform GUI
169  ::pGUI->SetPreferredDlgRect(C4Rect(pVP->OutX, pVP->OutY, pVP->ViewWdt, pVP->ViewHgt));
170 #endif
171  //StdWindow manages this.
172 }
173 
174 void C4MouseControl::Move(int32_t iButton, int32_t iX, int32_t iY, DWORD dwKeyFlags, bool fCenter)
175 {
176  // Control state
177  ControlDown=false; if (dwKeyFlags & MK_CONTROL) ControlDown=true;
178  ShiftDown=false; if (dwKeyFlags & MK_SHIFT) ShiftDown=true;
179  AltDown=false; if(dwKeyFlags & MK_ALT) AltDown=true;
180  // Active
181  if (!Active || !fMouseOwned) return;
182  // Execute caption
183  if (KeepCaption) KeepCaption--; else { Caption.Clear(); CaptionBottomY=0; }
184  // Check player
185  if (Player>NO_OWNER)
186  {
188  if (!pPlayer) { Active=false; return; }
189  }
190  else
191  pPlayer = nullptr;
192  // Check viewport
193  if (!(Viewport=::Viewports.GetViewport(Player))) return;
194  // get view position
195  C4Rect rcViewport = Viewport->GetOutputRect();
196  fctViewport.Set(nullptr, rcViewport.x, rcViewport.y, rcViewport.Wdt, rcViewport.Hgt);
200  // First time viewport attachment: center mouse
201 #ifdef USE_WIN32_WINDOWS
202  if (!InitCentered || fCenter)
203  {
204  iX = Viewport->ViewWdt/2;
205  iY = Viewport->ViewHgt/2;
206  if (!Application.isEditor)
207  {
208  int32_t iMidX = Viewport->OutX + iX;
209  int32_t iMidY = Viewport->OutY + iY;
210  RECT rtWindow;
211  if (GetWindowRect(Application.pWindow->hWindow, &rtWindow))
212  {
213  iMidX += rtWindow.left; iMidY += rtWindow.top;
214  }
215  SetCursorPos(iMidX, iMidY);
216  }
217  InitCentered = true;
218  }
219 #else
220  if (!InitCentered || fCenter)
221  {
222  iX = Viewport->ViewWdt/2;
223  iY = Viewport->ViewHgt/2;
224  InitCentered = true;
225  }
226 #endif
227  // passive mode: scrolling and player buttons only
228  if (IsPassive())
229  {
230  if (iButton != C4MC_Button_Wheel)
231  {
232  VpX=iX; VpY=iY;
234  GuiX=float(VpX)/Viewport->GetGUIZoom(); GuiY=float(VpY)/Viewport->GetGUIZoom();
235  }
236  UpdateScrolling();
237  if (iButton == C4MC_Button_LeftDown) LeftDown();
238  else if (iButton == C4MC_Button_LeftUp) LeftUp();
239  else UpdateCursorTarget();
240  return;
241  }
242 
243  if (iButton != C4MC_Button_Wheel)
244  {
245  // Position
246  VpX=iX; VpY=iY;
248  GuiX=float(VpX)/Viewport->GetGUIZoom(); GuiY=float(VpY)/Viewport->GetGUIZoom();
249  // Scrolling
250  UpdateScrolling();
251  // Fog of war
252  UpdateFogOfWar();
253 
254  // Blocked by fog of war: evaluate button up, dragging and region controls only
255  if (FogOfWar && Drag == C4MC_Drag_None)
256  {
257  // Left button up
258  if (iButton==C4MC_Button_LeftUp)
259  {
260  LeftButtonDown=false;
261  // End any drag
263  }
264  // Right button up
265  if (iButton==C4MC_Button_RightUp)
266  {
267  RightButtonDown=false;
268  }
269  }
270  }
271 
272  // Move execution by button/drag status
273  switch (iButton)
274  {
275  //------------------------------------------------------------------------------------------
276  case C4MC_Button_None:
277  switch (Drag)
278  {
279  case C4MC_Drag_Unhandled: break; // nothing to do
280  case C4MC_Drag_None: DragNone(); break;
281  case C4MC_Drag_Script: DragScript(); break;
282  }
283  break;
284  //------------------------------------------------------------------------------------------
285  case C4MC_Button_LeftDown: LeftDown(); break;
286  //------------------------------------------------------------------------------------------
287  case C4MC_Button_LeftUp: LeftUp(); break;
288  //------------------------------------------------------------------------------------------
289  case C4MC_Button_LeftDouble: LeftDouble(); break;
290  //------------------------------------------------------------------------------------------
291  case C4MC_Button_RightDown: RightDown(); break;
292  //------------------------------------------------------------------------------------------
293  case C4MC_Button_RightUp: RightUp(); break;
294  //------------------------------------------------------------------------------------------
295  case C4MC_Button_Wheel: Wheel(dwKeyFlags); break;
296  }
297 
298  // are custom menus active?
299  bool menuProcessed = false;
300  if (pPlayer)
301  // adjust by viewport X/Y because the GUI windows calculate their positions (and thus check input) based on that
302  menuProcessed = ::Game.ScriptGuiRoot->MouseInput(iButton, iX, iY, dwKeyFlags);
303 
304  if (menuProcessed)
306 
307  // if not caught by a menu
308  if (!menuProcessed)
309  // script handling of mouse control for everything but regular movement (which is sent at control frame intervals only)
310  if (iButton != C4MC_Button_None)
311  // not if blocked by selection object
312  if (!TargetObject)
313  // safety (can't really happen in !IsPassive, but w/e
314  if (pPlayer && pPlayer->ControlSet)
315  {
316  if (!menuProcessed && pPlayer->ControlSet->IsMouseControlAssigned(iButton))
317  {
318  int wheel_dir = 0;
319  if (iButton == C4MC_Button_Wheel) wheel_dir = (short)(dwKeyFlags >> 16);
320  pPlayer->Control.DoMouseInput(0 /* only 1 mouse supported so far */, iButton, GameX, GameY, GuiX, GuiY, (dwKeyFlags & MK_CONTROL) != 0, (dwKeyFlags & MK_SHIFT) != 0, (dwKeyFlags & MK_ALT) != 0, wheel_dir);
321  }
322  }
323 }
324 
326 {
327  // current mouse move to input queue
328  // do sanity checks
329  if (!Active || !fMouseOwned) return;
330  if (!(pPlayer=::Players.Get(Player))) return;
331  if (!pPlayer->ControlSet) return;
333  pPlayer->Control.DoMouseInput(0 /* only 1 mouse supported so far */, C4MC_Button_None, GameX, GameY, GuiX, GuiY, ControlDown, ShiftDown, AltDown, 0);
334 }
335 
336 void C4MouseControl::Draw(C4TargetFacet &cgo, const ZoomData &GameZoom)
337 {
338  int32_t iOffsetX,iOffsetY;
339  float wdt = GfxR->fctMouseCursor.Wdt, hgt = GfxR->fctMouseCursor.Hgt;
340  // Cursor size relative to height - does not matter with current square graphics.
341  float zoom = Config.Graphics.MouseCursorSize / hgt;
342  hgt *= zoom;
343  wdt *= zoom;
344 
345  ZoomData GuiZoom;
346  pDraw->GetZoom(&GuiZoom);
347 
348  // Hidden
349  if (!Visible || !fMouseOwned) return;
350 
351  // Draw selection
352  if (!IsPassive())
353  {
355  }
356 
357  // Draw control
358  switch (Drag)
359  {
360  //------------------------------------------------------------------------------------------
362  // Hotspot offset: Usually, hotspot is in center
363  iOffsetX = wdt/2;
364  iOffsetY = hgt/2;
365  // calculate the hotspot for the scrolling cursors
366  switch (Cursor)
367  {
368  case C4MC_Cursor_Up: iOffsetY += -hgt/2; break;
369  case C4MC_Cursor_Down:iOffsetY += +hgt/2; break;
370  case C4MC_Cursor_Left: iOffsetX += -wdt/2; break;
371  case C4MC_Cursor_Right: iOffsetX += +wdt/2; break;
372  case C4MC_Cursor_UpLeft: iOffsetX += -wdt/2; iOffsetY += -hgt/2; break;
373  case C4MC_Cursor_UpRight: iOffsetX += +wdt/2; iOffsetY += -hgt/2; break;
374  case C4MC_Cursor_DownLeft: iOffsetX += -wdt/2; iOffsetY += +hgt/2; break;
375  case C4MC_Cursor_DownRight: iOffsetX += +wdt/2; iOffsetY += +hgt/2; break;
376  }
377  // Drag image
379  {
380  C4DefGraphics* pGfx;
381  if(DragImageObject)
382  pGfx = DragImageObject->GetGraphics();
383  else
384  pGfx = &DragImageDef->Graphics;
385 
386  // Determine image boundaries
387  float ImageWdt;
388  float ImageHgt;
389  if (pGfx->Type == C4DefGraphics::TYPE_Bitmap)
390  {
392  ImageWdt = Def->PictureRect.Wdt;
393  ImageHgt = Def->PictureRect.Hgt;
394  }
395  else if (pGfx->Type == C4DefGraphics::TYPE_Mesh)
396  {
397  // Note bounding box is in OGRE coordinate system
398  ImageWdt = pGfx->Mesh->GetBoundingBox().y2 - pGfx->Mesh->GetBoundingBox().y1;
399  ImageHgt = pGfx->Mesh->GetBoundingBox().z2 - pGfx->Mesh->GetBoundingBox().z1;
400  }
401  else
402  {
403  ImageWdt = ImageHgt = 1.0f;
404  }
405 
406  // zoom mode: Drag in GUI or Game depending on source object
407  bool fIsGameZoom = true;
409  fIsGameZoom = false;
410  // drag image in game zoom
411  float XDraw, YDraw, ZoomDraw;
412  if (fIsGameZoom)
413  {
414  pDraw->SetZoom(GameZoom);
415  XDraw = GameX; YDraw = GameY;
416  ZoomDraw = 1.0f;
417  }
418  else
419  {
420  ZoomDraw = std::min(64.0f / ImageWdt, 64.0f / ImageHgt);
421  XDraw = GuiX; YDraw = GuiY;
422  }
423 
424  iOffsetX=int(ZoomDraw*ImageWdt/2);
425  iOffsetY=int(ZoomDraw*ImageHgt/2);
426 
427  C4TargetFacet ccgo;
428  ccgo.Set(cgo.Surface, XDraw + cgo.X - iOffsetX, YDraw + cgo.Y - iOffsetY, float(ImageWdt)*ZoomDraw, float(ImageHgt)*ZoomDraw);
429 
430  if (DragImageObject)
431  {
432  uint32_t ColorMod = DragImageObject->ColorMod;
433  uint32_t BlitMode = DragImageObject->BlitMode;
434  DragImageObject->ColorMod = (Drag == C4MC_Drag_Script) ? 0x7fffffff : (/*DragImagePhase*/false ? 0x8f7f0000 : 0x1f007f00);
436 
437  DragImageObject->DrawPicture(ccgo, false, nullptr);
438 
439  DragImageObject->ColorMod = ColorMod;
440  DragImageObject->BlitMode = BlitMode;
441  }
442  else
443  {
444  // draw in special modulation mode
446  // draw DragImage in red or green, according to the phase to be used
447  pDraw->ActivateBlitModulation((Drag == C4MC_Drag_Script) ? 0x7fffffff : (/*DragImagePhase*/false ? 0x8f7f0000 : 0x1f007f00));
448 
449  DragImageDef->Draw(ccgo, false, pPlayer ? pPlayer->ColorDw : 0xff0000ff, nullptr, 0, 0, nullptr);
450 
451  // reset color
453  pDraw->SetBlitMode(0);
454  }
455 
456  if (fIsGameZoom) pDraw->SetZoom(GuiZoom);
457  // reset cursor hotspot offset for script drawing
458  iOffsetX = wdt/2;
459  iOffsetY = hgt/2;
460  }
461  // Cursor
463  {
464  GfxR->fctMouseCursor.DrawX(cgo.Surface, cgo.X+GuiX-iOffsetX, cgo.Y+GuiY-iOffsetY, wdt, hgt, Cursor);
465  }
466  break;
467  //------------------------------------------------------------------------------------------
468  }
469 
470  // Draw caption
471  if (Caption && ::pGUI)
472  {
473  C4TargetFacet cgoTip;
474  cgoTip = static_cast<const C4Facet &>(cgo);
475  C4GUI::Screen::DrawToolTip(Caption.getData(), cgoTip, cgo.X+GuiX, cgo.Y+GuiY);
476  }
477 
478 }
479 
481 {
482  C4Object* OldTargetObject = TargetObject;
483 
484  if (Scrolling)
485  {
486  // Scrolling: no other target
487  TargetObject=nullptr;
488  }
489  else
490  {
491  // Target object
494 
495  // Movement
497 
498  // Target action
499  if (TargetObject && !IsPassive())
500  {
501  // default cursor for object; also set if not in FoW
503 
504  // select custom region. Can select an object if it does not have the MD_NoClick
505  // flag set. If we are currently dragging then selection depends on it being a drop target.
506  bool CanSelect;
507  if(Drag == C4MC_Drag_Script)
509  else
511 
512  if ( (TargetObject->Category & C4D_MouseSelect) && CanSelect)
514  else
515  TargetObject = nullptr;
516  }
517 
518  // passive cursor
519  if (IsPassive())
521 
522  // update tooltip information
523  if (OldTargetObject != TargetObject)
524  {
525  C4String *newTooltip = nullptr;
527  {
528  float objX, objY;
530  objX += TargetObject->Shape.x;
531  objY += TargetObject->Shape.y - TargetObject->addtop();
533  SetTooltipText(StdStrBuf(newTooltip->GetCStr()));
534  }
535  else
536  {
537  SetTooltipRectangle(C4Rect(0, 0, 0, 0));
538  }
539  }
540 
541  if (!KeepCaption
542  && ToolTipRectangle.Wdt != 0
545  {
547 
549  {
551  }
552  }
553  else
554  {
555  // disable tooltip pop-up; whatever set it in the first place will set it again on the next mouse-enter
557  ToolTipRectangle.Wdt = 0;
558  }
559  }
560 
561  // Make a script callback if the object being hovered changes
562  if(!IsPassive() && OldTargetObject != TargetObject)
563  {
564  // TODO: This might put a heavy load on the network, depending on the number of
565  // selectable objects around. If it turns out to be a problem we might want to
566  // deduce these hover callbacks client-side instead.
567  // Or, make sure to send this at most once per control frame.
569  }
570 }
571 
573 {
574  // Set single selection if cursor on selection object (clear prior object selection)
577 
578  // Cursor has moved off single object (or target object) selection: clear selection
579  else if (Selection.GetObject())
582  Selection.Clear();
583 
584  return Selection.ObjectCount();
585 }
586 
588 {
589  // Assume no scrolling
590  Scrolling=false;
591  // No scrolling if disabled by player
592  if (pPlayer) if (pPlayer->IsViewLocked()) return;
593  // Scrolling on border
594  if (VpX==0)
596  if (VpY==0)
598  if (VpX==Viewport->ViewWdt-1)
600  if (VpY==Viewport->ViewHgt-1)
602  // Set correct cursor
603  if ((VpX==0) && (VpY==0)) Cursor=C4MC_Cursor_UpLeft;
604  if ((VpX==Viewport->ViewWdt-1) && (VpY==0)) Cursor=C4MC_Cursor_UpRight;
605  if ((VpX==0) && (VpY==Viewport->ViewHgt-1)) Cursor=C4MC_Cursor_DownLeft;
607 }
608 
610 {
611  // Set flag
612  LeftButtonDown=true;
613  // Store down values (same MoveRightDown -> use StoreDown)
616 }
617 
619 {
620  // Ignore left up after double click
621  if (LeftDoubleIgnoreUp)
622  {
623  LeftDoubleIgnoreUp=false;
624  }
625  else
626  {
627  // Evaluate by drag status
628  switch (Drag)
629  {
630  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
631  case C4MC_Drag_Unhandled: // nobreak
632  case C4MC_Drag_None: LeftUpDragNone(); break;
633  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
634  case C4MC_Drag_Script: ButtonUpDragScript(); break;
635  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
636  }
637  }
638  // Update status flag
639  LeftButtonDown=false;
640  if(!RightButtonDown) DownTarget = nullptr;
641 }
642 
644 {
645  // Cursor movement
647  // Update selection
649 
650  // Button down: begin drag
653  {
654  bool fAllowDrag = true;
655  // check if target object allows scripted dragging
656  if (fAllowDrag && DownTarget && (!FogOfWar || (DownTarget->Category & C4D_IgnoreFoW)))
657  {
658  C4Object *drag_image_obj; C4Def * drag_image_def;
659 
660  // Drag only if MD_SOURCE is set and drag image is present
662  DownTarget->GetDragImage(&drag_image_obj, &drag_image_def))
663  {
665 
666  if(drag_image_obj) DragImageObject = drag_image_obj;
667  else DragImageDef = drag_image_def;
668 
670  }
671  }
672 
673  // dragging somewhere unhandled - mark drag process so moving over a draggable object won't start a drag
674  if (Drag == C4MC_Drag_None)
675  {
677  }
678  }
679 }
680 
682 {
683  // Update status flag
684  LeftButtonDown=false;
685  // Set ignore flag for next left up
686  LeftDoubleIgnoreUp=true;
687  // Evaluate left double by drag status (can only be C4MC_Drag_None really)
688  switch (Drag)
689  {
690  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
691  case C4MC_Drag_None:
692  // Double left click (might be on a target)
693  break;
694  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
695  }
696 }
697 
699 {
700  // Update status flag
701  RightButtonDown=true;
702  // Store down values (same MoveLeftDown -> use StoreDown)
705 }
706 
708 {
709  // Evaluate by drag status
710  switch (Drag)
711  {
712  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
713  case C4MC_Drag_Unhandled: // nobreak
714  case C4MC_Drag_None: RightUpDragNone(); break;
715  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
716  case C4MC_Drag_Script: ButtonUpDragScript(); break;
717  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
718  }
719  // Update status flag
720  RightButtonDown=false;
721  if(!LeftButtonDown) DownTarget = nullptr;
722 }
723 
725 {
726 }
727 
729 {
730  // script drag should update target and selection so selection highlight on drop target is visible
731  // Cursor movement
733  // Update selection
736 }
737 
739 {
740  // might be in Drag_Unknown
742  // Single left click (might be on a target)
743  switch (Cursor)
744  {
745  case C4MC_Cursor_Select:
746  // Object selection to control queue
747  if (!IsPassive() && Selection.GetObject() == DownTarget)
749  break;
750  default:
751  // done in script
752  break;
753  }
754  // Clear selection
755  Selection.Clear();
756 }
757 
759 {
760  // Determine drag+drop targets
762  // Finish drag
765  DragImageObject = nullptr;
766  DragImageDef = nullptr;
767  C4Object *DragObject = this->DragObject;
768  this->DragObject = nullptr;
769  C4Object *DropObject = TargetObject;
770  // drag object must exist; drop object is optional
771  if (!DragObject) return;
772  if (DropObject && (~DropObject->GetPropertyInt(P_MouseDrag) & C4MC_MD_DropTarget))
773  DropObject = nullptr;
774  // no commands if player is eliminated or doesn't exist any more
775  C4Player *pPlr = ::Players.Get(Player);
776  if (!pPlr || pPlr->Eliminated) return;
777  // todo: Perform drag/drop validity check
778  // now drag/drop is handled by script
780 }
781 
783 {
784 
785  // might be in Drag_Unknown
787 
788  // Alternative object selection
791 
792  // TODO: Evaluate right click
793 
794 }
795 
797 {
798  // Assume no fog of war
799  FogOfWar=false;
800  // Check for fog of war
801  // TODO: Check C4FoWRegion... should maybe be passed as a parameter?
802  // pDraw->GetFoW() might not be current at this time.
803  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())
804  {
805  FogOfWar=true;
806  // allow dragging, scrolling, region selection and manipulations of objects not affected by FoW
808  {
810  }
811  }
812 }
813 
815 {
816  Visible=true;
817 }
818 
820 {
821  Visible=false;
822 }
823 
825 {
826  return Caption.getData();
827 }
828 
830 {
831  // Set the tooltip rectangle slightly larger than originally requested.
832  // 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
833  // in case the GUI item uses a different check for bounds (< vs <=) than the tooltip rectangle.
834  ToolTipRectangle = C4Rect(rectangle.x - 2, rectangle.y - 2, rectangle.Wdt + 4, rectangle.Hgt + 4);
836 }
837 
839 {
840  TooltipText = text;
841 }
842 
844 {
845  // find object
846  // gui object position currently wrong...will fall apart once GUIZoom is activated
848  if (!pObj) return nullptr;
849  return pObj;
850 }
851 
853 {
855 }
856 
857 void C4MouseControl::ScrollView(float iX, float iY, float ViewWdt, float ViewHgt)
858 {
859  // player assigned: scroll player view
860  if (pPlayer)
861  pPlayer->ScrollView(iX, iY, ViewWdt, ViewHgt);
862  else if (Viewport)
863  {
864  // no player: Scroll fullscreen viewport
865  Viewport->ScrollView(iX, iY);
866  }
867 
868 }
869 
871 {
872  return Active && Drag == C4MC_Drag_Script;
873 }
874 
875 bool C4MouseControl::GetLastCursorPos(int32_t *x_out_gui, int32_t *y_out_gui, int32_t *x_out_game, int32_t *y_out_game) const
876 {
877  // safety
878  if (!Active || !fMouseOwned) return false;
879  // OK; assign last known pos
880  *x_out_gui = GuiX; *y_out_gui = GuiY;
881  *x_out_game = GameX; *y_out_game = GameY;
882  return true;
883 }
const char * getData() const
Definition: StdBuf.h:442
void SetTooltipRectangle(const C4Rect &rectangle)
int32_t OutX
Definition: C4Viewport.h:107
C4ObjectList Selection
C4Config Config
Definition: C4Config.cpp:833
const int32_t C4MC_Button_LeftDown
int32_t OutY
Definition: C4Viewport.h:107
float Y
Definition: C4Facet.h:118
C4Rect ToolTipRectangle
#define C4GFXBLIT_MOD2
Definition: C4Surface.h:27
#define GfxR
virtual bool Add(C4Object *nObj, SortType eSort, C4ObjectList *pLstSorted=nullptr)
C4Player * pPlayer
int32_t iTick5
Definition: C4Game.h:129
const int32_t C4MC_Drag_Script
C4Game Game
Definition: C4Globals.cpp:52
int32_t TimeInTooltipRectangle
void GetViewPos(float &riX, float &riY, float tx, float ty, const C4Facet &fctViewport) const
Definition: C4Object.cpp:4326
C4Rect PictureRect
Definition: C4Def.h:107
const int32_t C4MC_Cursor_Right
void Clear()
Definition: StdBuf.h:466
bool GetDragImage(C4Object **drag_object, C4Def **drag_id) const
Definition: C4Object.cpp:4284
void DrawPicture(C4Facet &cgo, bool fSelected=false, C4DrawTransform *transform=nullptr)
Definition: C4Object.cpp:2337
const int32_t C4MC_Cursor_Passive
StdCopyStrBuf TooltipText
const int32_t C4MC_Cursor_DragDrop
C4Object * DragImageObject
const char * GetCStr() const
Definition: C4StringTable.h:49
int32_t UpdateSingleSelection()
void Add(C4PacketType eType, C4ControlPacket *pCtrl)
Definition: C4Control.h:82
const int32_t C4MC_DragSensitivity
C4FullScreen FullScreen
Definition: C4Globals.cpp:46
const int32_t C4MC_Button_RightUp
Definition: C4Rect.h:27
C4Object * DownTarget
int32_t MouseCursorSize
Definition: C4Config.h:118
bool ButtonDownOnSelection
C4Viewport * GetViewport(int32_t iPlayer, C4Viewport *pPrev=nullptr)
const int32_t C4MC_Cursor_Down
C4PlayerControl Control
Definition: C4Player.h:129
bool IsViewLocked() const
Definition: C4Player.h:204
void SetPreferredDlgRect(const C4Rect &rtNewPref)
Definition: C4Gui.h:2648
C4Object * TargetObject
bool GetLastCursorPos(int32_t *x_out_gui, int32_t *y_out_gui, int32_t *x_out_game, int32_t *y_out_game) const
void Set(C4Surface &rSfc)
Definition: C4Facet.cpp:459
static void DrawToolTip(const char *szTip, C4TargetFacet &cgo, float guix, float guiy)
Definition: C4Gui.cpp:1009
void ScrollView(float iX, float iY, float ViewWdt, float ViewHgt)
C4TargetFacet last_gui_draw_cgo
Definition: C4Viewport.h:41
const int32_t C4MC_MD_NoClick
void SetBlitMode(DWORD dwBlitMode)
Definition: C4Draw.h:191
const int32_t C4MC_MD_DropTarget
C4Facet fctViewportGame
const int32_t C4MC_Button_LeftDouble
uint32_t ColorDw
Definition: C4Player.h:89
int32_t ViewHgt
Definition: C4Viewport.h:36
C4ConfigGraphics Graphics
Definition: C4Config.h:253
int32_t Wdt
Definition: C4Rect.h:30
bool DoMouseInput(uint8_t mouse_id, int32_t mouseevent, float game_x, float game_y, float gui_x, float gui_y, bool is_ctrl_down, bool is_shift_down, bool is_alt_down, int wheel_dir)
const int32_t C4D_IgnoreFoW
Definition: C4Def.h:55
void SetTooltipText(const StdStrBuf &text)
const int32_t C4D_MouseSelect
Definition: C4Def.h:52
void Draw(C4TargetFacet &cgo, const ZoomData &GameZoom)
C4Player * Get(int iPlayer) const
const int32_t C4MC_Drag_None
C4GUIScreen * pGUI
Definition: C4Gui.cpp:1191
class C4PlayerControlAssignmentSet * ControlSet
Definition: C4Player.h:90
const int32_t C4MC_Button_LeftUp
C4Def * Def
Definition: C4Object.h:143
bool Active
Definition: C4App.h:63
int32_t ViewWdt
Definition: C4Viewport.h:36
void ScrollView(float iX, float iY, float ViewWdt, float ViewHgt)
Definition: C4Player.cpp:1364
int32_t y
Definition: C4Rect.h:30
bool IsViewport(C4Viewport *pViewport)
void Default()
Definition: C4Facet.cpp:31
C4GameControl Control
void Move(int32_t iButton, int32_t iX, int32_t iY, DWORD dwKeyFlags, bool fCenter=false)
C4Landscape Landscape
StdCopyStrBuf Caption
const int32_t C4MC_Cursor_Left
C4DefGraphics * GetGraphics() const
Definition: C4Object.h:340
int32_t ScrollSpeed
static const C4ID None
Definition: C4Id.h:39
const int32_t C4MC_Cursor_DownLeft
void Set(const C4Facet &cpy)
Definition: C4Facet.h:182
C4Object * DragObject
void ScrollView(float byX, float byY)
Definition: C4Viewport.cpp:734
C4PlayerList Players
const int32_t C4MC_Tooltip_Delay
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:597
Definition: C4Def.h:98
const int NO_OWNER
Definition: C4Constants.h:137
int32_t CaptionBottomY
C4Rect GetOutputRect()
Definition: C4Viewport.h:64
C4Draw * pDraw
Definition: C4Draw.cpp:42
const int32_t C4MC_Cursor_Select
C4Object * GetObject(int Index=0) const
C4Viewport * Viewport
C4Def * DragImageDef
int32_t Eliminated
Definition: C4Player.h:83
bool IsMouseControlAssigned(int32_t mouseevent) const
static C4ControlPlayerMouse * Hover(const C4Player *player, const C4Object *target, const C4Object *old_target, const C4Object *drag=nullptr)
Definition: C4Control.cpp:446
float Zoom
Definition: C4Viewport.h:101
C4Facet fctViewportGUI
const int32_t C4MC_Button_RightDown
int32_t Category
Definition: C4Object.h:113
C4Control & Input
Definition: C4Game.h:82
C4TargetFacet last_game_draw_cgo
Definition: C4Viewport.h:41
int32_t x
Definition: C4Rect.h:30
const int32_t C4MC_Cursor_Up
int32_t GetHeight() const
void Wheel(DWORD dwFlags)
const int32_t C4MC_Button_Wheel
int ObjectCount(C4ID id=C4ID::None) const
const int32_t C4MC_Drag_Unhandled
C4ViewportList Viewports
Definition: C4Viewport.cpp:841
float GetViewY()
Definition: C4Viewport.h:75
bool HasMouseFocus()
Definition: C4Gui.h:2675
uint32_t ColorMod
Definition: C4Object.h:161
void GetZoom(ZoomData *r)
Definition: C4Draw.h:197
const int32_t C4MC_Cursor_UpLeft
const int32_t C4MC_MD_DragSource
GraphicsType Type
Definition: C4DefGraphics.h:48
bool isReplay() const
Definition: C4GameControl.h:98
bool Init(int32_t iPlayer)
const int32_t C4MC_Button_None
float GetGUIZoom() const
Definition: C4Viewport.h:47
C4Facet fctViewport
void DeactivateBlitModulation()
Definition: C4Draw.h:189
int32_t GetPropertyInt(C4PropertyName k, int32_t default_val=0) const
Definition: C4PropList.cpp:886
int ClearPointers(C4Object *pObj)
virtual void Default()
void DrawSelectMark(C4TargetFacet &cgo) const
uint32_t BlitMode
Definition: C4Object.h:162
const int32_t C4MC_Cursor_DownRight
void ActivateBlitModulation(DWORD dwWithClr)
Definition: C4Draw.h:188
int32_t Hgt
Definition: C4Rect.h:30
T Abs(T val)
Definition: Standard.h:42
virtual void Clear()
std::unique_ptr< C4ScriptGuiWindow > ScriptGuiRoot
Definition: C4Game.h:233
C4Shape Shape
Definition: C4Object.h:148
const int32_t C4MC_Cursor_UpRight
C4Surface * Surface
Definition: C4Facet.h:117
C4Object * FindVisObject(float tx, float ty, int32_t iPlr, const C4Facet &fctViewportGame, const C4Facet &fctViewportGUI, float iX, float iY, DWORD category, float gui_x, float gui_y)
Definition: C4Game.cpp:1225
static C4ControlPlayerMouse * DragDrop(const C4Player *player, const C4Object *target, const C4Object *drag)
Definition: C4Control.cpp:459
C4Object * GetTargetObject()
uint32_t DWORD
float GetViewX()
Definition: C4Viewport.h:73
bool ObjectInCrew(C4Object *tobj)
Definition: C4Player.cpp:90
const char * GetCaption()
void SetZoom(float X, float Y, float Zoom)
Definition: C4Draw.cpp:779
C4String * GetPropertyStr(C4PropertyName k) const
Definition: C4PropList.cpp:775
void ClearPointers(C4Object *pObj)
C4DefGraphics Graphics
Definition: C4Def.h:191
bool Inside(T ival, U lbound, V rbound)
Definition: Standard.h:43
float X
Definition: C4Facet.h:118
C4Window * pWindow
Definition: C4App.h:80
C4Application Application
Definition: C4Globals.cpp:44
const int32_t C4MC_Cursor_Crosshair
uint16_t WORD
const int32_t C4D_Foreground
Definition: C4Def.h:53
int32_t addtop() const
Definition: C4Object.h:281
int32_t GetWidth() const