Arma Reforger Explorer  1.1.0.42
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
SCR_MapEntity.c
Go to the documentation of this file.
2 {
3 };
4 
5 //------------------------------------------------------------------------------------------------
6 // invoker typedefs
7 void MapConfigurationInvoker(MapConfiguration config);
9 
10 void MapItemInvoker(MapItem mapItem);
12 
13 void ScriptInvokerFloat2Bool(float f1, float f2, bool b1);
15 
16 
17 //------------------------------------------------------------------------------------------------
19 [EntityEditorProps(category: "GameScripted/Map", description: "Map entity, handles displaying of map etc", sizeMin: "-5 -5 -5", sizeMax: "5 5 5", color: "255 255 200 0", dynamicBox: true)]
20 class SCR_MapEntity: MapEntity
21 {
22  const int FRAME_DELAY = 1;
23  protected int m_iDelayCounter = FRAME_DELAY; // used to delay the map logic by set amount of frames to give the map widget time to properly init
24 
25  // generic
26  protected bool m_bIsOpen; // is open flag
27  protected bool m_bDoReload; // mark whether map config changed in order to reload modules/components
28  protected bool m_bDoUpdate; // mark whether user setting changed, update zoom & position
29  protected bool m_bIsDebugMode; // variable debug mode
30  protected int m_iMapSizeX; // map size X in meters/units
31  protected int m_iMapSizeY; // map size Y in meters/units
32  protected vector m_vVisibleFrameMin; // cache visible frame min point for use elsewhere
33  protected vector m_vVisibleFrameMax; // cache visible frame max point for use elsewhere
34  protected EMapEntityMode m_eLastMapMode; // cached mode of last map for reload check
35  protected Widget m_wMapRoot; // map menu root widget
36  protected CanvasWidget m_MapWidget; // map widget
37  protected WorkspaceWidget m_Workspace;
38  protected ref MapConfiguration m_ActiveMapCfg; // map config
39  protected static SCR_MapEntity s_MapInstance; // map entity instance
40 
41  protected MapItem m_HoveredMapItem; // currently hovered map item
42 
43  // zoom
44  protected bool m_bIsZoomInterp; // is currently zoom animating
45  protected float m_fZoomPPU = 1; // current zoom PixelPerUnit value
46  protected float m_fStartPPU; // zoom start PixelPerUnit
47  protected float m_fTargetPPU = 1; // zoom target PixelPerUnit
48  protected float m_fZoomTimeModif; // zoom anim speed modifier
49  protected float m_fZoomSlice; // zoom anim timeslce
50  protected float m_fMinZoom = 1; // minimal zoom PixelPerUnit
51  protected float m_fMaxZoom; // maximal zoom PixelPerUnit
52 
53  // pan
54  protected bool m_bIsPanInterp; // is currently pan animating
55  protected int m_iPanX = 0; // current horizontal pan offset - UNSCALED value in px
56  protected int m_iPanY = 0; // current vertical pan offset - UNSCALED value in px
57  protected int m_aStartPan[2]; // pan start coords - UNSCALED value in px
58  protected int m_aTargetPan[2]; // pan target coords - UNSCALED value in px
59  protected float m_fPanTimeModif; // pan anim speed modifier
60  protected float m_fPanSlice; // pan anim timeslce
61 
62  // modules & components
63  protected ref array<ref SCR_MapModuleBase> m_aActiveModules = {};
64  protected ref array<ref SCR_MapModuleBase> m_aLoadedModules = {};
65  protected ref array<ref SCR_MapUIBaseComponent> m_aActiveComponents = {};
66  protected ref array<ref SCR_MapUIBaseComponent> m_aLoadedComponents = {};
67 
68  // invokers
69  protected static ref ScriptInvokerBase<MapConfigurationInvoker> s_OnMapInit = new ScriptInvokerBase<MapConfigurationInvoker>(); // map init, called straight after opening the map
70  protected static ref ScriptInvokerBase<MapConfigurationInvoker> s_OnMapOpen = new ScriptInvokerBase<MapConfigurationInvoker>(); // map open, called after map is properly initialized
71  protected static ref ScriptInvokerBase<MapConfigurationInvoker> s_OnMapClose = new ScriptInvokerBase<MapConfigurationInvoker>();// map close
72  protected static ref ScriptInvokerBase<ScriptInvokerFloat2Bool> s_OnMapPan = new ScriptInvokerBase<ScriptInvokerFloat2Bool>; // map pan, passes UNSCALED x & y
73  protected static ref ScriptInvokerFloat2 s_OnMapPanEnd = new ScriptInvokerFloat2(); // map pan interpolated end
74  protected static ref ScriptInvokerFloat s_OnMapZoom = new ScriptInvokerFloat(); // map zoom
75  protected static ref ScriptInvokerFloat s_OnMapZoomEnd = new ScriptInvokerFloat(); // map zoom interpolated end
76  protected static ref ScriptInvokerVector s_OnSelection = new ScriptInvokerVector(); // any click/selection on map
77  protected static ref ScriptInvokerInt s_OnLayerChanged = new ScriptInvokerInt(); // map layer changed
78  protected static ref ScriptInvokerBase<MapItemInvoker> s_OnSelectionChanged = new ScriptInvokerBase<MapItemInvoker>(); // map items de/selected
79  protected static ref ScriptInvokerBase<MapItemInvoker> s_OnHoverItem = new ScriptInvokerBase<MapItemInvoker>(); // map item hovered
80  protected static ref ScriptInvokerBase<MapItemInvoker> s_OnHoverEnd = new ScriptInvokerBase<MapItemInvoker>(); // map item hover end
81 
82  //------------------------------------------------------------------------------------------------
83  // GETTERS / SETTERS
84  //------------------------------------------------------------------------------------------------
86  static ScriptInvokerBase<MapConfigurationInvoker> GetOnMapInit() { return s_OnMapInit; }
88  static ScriptInvokerBase<MapConfigurationInvoker> GetOnMapOpen() { return s_OnMapOpen; }
90  static ScriptInvokerBase<MapConfigurationInvoker> GetOnMapClose() { return s_OnMapClose; }
92  static ScriptInvokerBase<ScriptInvokerFloat2Bool> GetOnMapPan() { return s_OnMapPan; }
94  static ScriptInvokerFloat2 GetOnMapPanEnd() { return s_OnMapPanEnd; }
96  static ScriptInvokerFloat GetOnMapZoom() { return s_OnMapZoom; }
98  static ScriptInvokerFloat GetOnMapZoomEnd() { return s_OnMapZoomEnd; }
100  static ScriptInvokerBase<MapItemInvoker> GetOnSelectionChanged() { return s_OnSelectionChanged; }
102  static ScriptInvokerVector GetOnSelection() { return s_OnSelection; }
104  static ScriptInvokerBase<MapItemInvoker> GetOnHoverItem() { return s_OnHoverItem; }
106  static ScriptInvokerBase<MapItemInvoker> GetOnHoverEnd() { return s_OnHoverEnd; }
108  static ScriptInvokerInt GetOnLayerChanged() { return s_OnLayerChanged; }
110  static SCR_MapEntity GetMapInstance() { return s_MapInstance; }
111 
112  //------------------------------------------------------------------------------------------------
114  MapConfiguration GetMapConfig()
115  {
116  return m_ActiveMapCfg;
117  }
118 
119  //------------------------------------------------------------------------------------------------
121  bool IsOpen()
122  {
123  return m_bIsOpen;
124  }
125 
126  //------------------------------------------------------------------------------------------------
128  int GetMapSizeX()
129  {
130  return m_iMapSizeX;
131  }
132 
133  //------------------------------------------------------------------------------------------------
135  int GetMapSizeY()
136  {
137  return m_iMapSizeY;
138  }
139 
140  //------------------------------------------------------------------------------------------------
142  float GetMaxZoom()
143  {
144  return m_fMaxZoom;
145  }
146 
147  //------------------------------------------------------------------------------------------------
149  float GetMinZoom()
150  {
151  return m_fMinZoom;
152  }
153 
154  //------------------------------------------------------------------------------------------------
156  float GetTargetZoomPPU()
157  {
158  return m_fTargetPPU;
159  }
160 
161  //------------------------------------------------------------------------------------------------
163  bool IsZooming()
164  {
165  return m_bIsZoomInterp;
166  }
167 
168  //------------------------------------------------------------------------------------------------
170  vector GetCurrentPan()
171  {
172  return { m_Workspace.DPIScale(m_iPanX), m_Workspace.DPIScale(m_iPanY), 0 };
173  }
174 
175  //------------------------------------------------------------------------------------------------
177  CanvasWidget GetMapWidget()
178  {
179  return m_MapWidget;
180  }
181 
182  //------------------------------------------------------------------------------------------------
184  Widget GetMapMenuRoot()
185  {
186  return m_wMapRoot;
187  }
188 
189  //------------------------------------------------------------------------------------------------
191  void SetMapWidget(Widget mapW)
192  {
193  m_MapWidget = CanvasWidget.Cast(mapW);
194  }
195 
196  //------------------------------------------------------------------------------------------------
198  MapItem GetHoveredItem()
199  {
200  return m_HoveredMapItem;
201  }
202 
203  //------------------------------------------------------------------------------------------------
205  void GetMapVisibleFrame(out vector min, out vector max)
206  {
207  min = m_vVisibleFrameMin;
208  max = m_vVisibleFrameMax;
209  }
210 
211  //------------------------------------------------------------------------------------------------
214  float GetCurrentZoom()
215  {
216  return m_fZoomPPU;
217  }
218 
219  //------------------------------------------------------------------------------------------------
223  void GetMapCursorWorldPosition(out float worldX, out float worldY)
224  {
225  ScreenToWorld(m_Workspace.DPIScale(SCR_MapCursorInfo.x), m_Workspace.DPIScale(SCR_MapCursorInfo.y), worldX, worldY);
226  }
227 
228  //------------------------------------------------------------------------------------------------
232  void GetMapCenterWorldPosition(out float worldX, out float worldY)
233  {
234  float screenX, screenY;
235  m_MapWidget.GetScreenSize(screenX, screenY);
236 
237  ScreenToWorld(screenX/2, screenY/2, worldX, worldY);
238  }
239 
240  //------------------------------------------------------------------------------------------------
244  SCR_MapModuleBase GetMapModule(typename moduleType)
245  {
246  foreach ( SCR_MapModuleBase module : m_aActiveModules )
247  {
248  if ( module.IsInherited(moduleType) )
249  return module;
250  }
251 
252  return null;
253  }
254 
255  //------------------------------------------------------------------------------------------------
259  SCR_MapUIBaseComponent GetMapUIComponent(typename componentType)
260  {
261  foreach ( SCR_MapUIBaseComponent comp : m_aActiveComponents )
262  {
263  if ( comp.IsInherited(componentType) )
264  return comp;
265  }
266 
267  return null;
268  }
269 
270  //------------------------------------------------------------------------------------------------
271  // OPEN / CLOSE
272  //------------------------------------------------------------------------------------------------
275  void OpenMap(MapConfiguration config)
276  {
277  if (!config)
278  return;
279 
280  if (m_bIsOpen)
281  {
282  Print("SCR_MapEntity: Attempted opening a map while it is already open", LogLevel.WARNING);
283  CloseMap();
284  }
285 
286  if (config.MapEntityMode != m_eLastMapMode)
287  m_bDoReload = true;
288 
289  m_eLastMapMode = config.MapEntityMode;
290  m_ActiveMapCfg = config;
291  m_Workspace = GetGame().GetWorkspace();
292  m_wMapRoot = config.RootWidgetRef;
293 
294  SetMapWidget(config.RootWidgetRef.FindAnyWidget(SCR_MapConstants.MAP_WIDGET_NAME));
295 
296  if (config.MapEntityMode == EMapEntityMode.FULLSCREEN)
297  {
298  ChimeraCharacter char = ChimeraCharacter.Cast(GetGame().GetPlayerController().GetControlledEntity());
299  if (char)
300  SCR_CharacterControllerComponent.Cast(char.GetCharacterController()).m_OnLifeStateChanged.Insert(OnLifeStateChanged);
301 
303  if (gameMode)
304  gameMode.GetOnPlayerDeleted().Insert(OnPlayerDeleted);
305  }
306 
307  InitLayers(config);
308 
309  SetFrame(Vector(0, 0, 0), Vector(0, 0, 0)); // Gamecode starts rendering stuff like descriptors straight away instead of waiting a frame - this is a hack to display nothing, avoiding the "blink" of icons
310 
311  m_bIsOpen = true;
312 
313  s_OnMapInit.Invoke(config);
314 
315  PlayerController plc = GetGame().GetPlayerController();
316  if (plc && GetGame().GetCameraManager().CurrentCamera() == plc.GetPlayerCamera())
317  plc.SetCharacterCameraRenderActive(false);
318  }
319 
320  //------------------------------------------------------------------------------------------------
322  void CloseMap()
323  {
324  if (!m_bIsOpen)
325  return;
326 
327  OnMapClose();
328 
329  m_bIsOpen = false;
330  m_iDelayCounter = FRAME_DELAY;
331  auto plc = GetGame().GetPlayerController();
332  if (plc)
333  plc.SetCharacterCameraRenderActive(true);
334  }
335 
336  //------------------------------------------------------------------------------------------------
339  protected void OnMapOpen(MapConfiguration config)
340  {
341  // init zoom & layers
342  m_MapWidget.SetSizeInUnits(Vector(m_iMapSizeX, m_iMapSizeY, 0)); // unit size to meters
343  UpdateZoomBounds();
344  AssignViewLayer(true);
345 
346  if (m_bDoUpdate) // when resolution changes, zoom to the same PPU to update zoom and pos
347  {
348  ZoomSmooth(m_fZoomPPU, reinitZoom: true);
349  m_bDoUpdate = false;
350  }
351 
352  // activate modules & components
353  ActivateModules(config.Modules);
354  ActivateComponents(config.Components);
355  ActivateOtherComponents(config.OtherComponents);
356 
357  m_bDoReload = false;
358 
359  if (s_OnMapOpen)
360  s_OnMapOpen.Invoke(config);
361 
362  if (config.MapEntityMode == EMapEntityMode.FULLSCREEN)
363  SCR_UISoundEntity.SoundEvent(SCR_SoundEvent.SOUND_HUD_MAP_OPEN);
364 
365  EnableVisualisation(true);
366  }
367 
368  //------------------------------------------------------------------------------------------------
370  protected void OnMapClose()
371  {
372  if (s_OnMapClose)
373  s_OnMapClose.Invoke(m_ActiveMapCfg);
374 
375  if (m_ActiveMapCfg.MapEntityMode == EMapEntityMode.FULLSCREEN)
376  {
377  SCR_UISoundEntity.SoundEvent(SCR_SoundEvent.SOUND_HUD_MAP_CLOSE);
378 
379  PlayerController controller = GetGame().GetPlayerController();
380  if (controller)
381  {
382  ChimeraCharacter char = ChimeraCharacter.Cast(controller.GetControlledEntity());
383  if (char)
384  SCR_CharacterControllerComponent.Cast(char.GetCharacterController()).m_OnLifeStateChanged.Insert(OnLifeStateChanged);
385  }
386 
388  if (gameMode)
389  gameMode.GetOnPlayerDeleted().Remove(OnPlayerDeleted);
390  }
391 
392  if ( m_ActiveMapCfg.OtherComponents & EMapOtherComponents.LEGEND_SCALE)
393  EnableLegend(false);
394 
395  EnableVisualisation(false);
396 
397  Cleanup();
398  }
399 
400  //------------------------------------------------------------------------------------------------
403  protected void OnLifeStateChanged(ECharacterLifeState previousLifeState, ECharacterLifeState newLifeState)
404  {
405  if (newLifeState == ECharacterLifeState.ALIVE)
406  return;
407 
409  if (!gadgetMgr)
410  return;
411 
412  IEntity mapGadget = gadgetMgr.GetGadgetByType(EGadgetType.MAP);
413  if (!mapGadget)
414  return;
415 
416  SCR_MapGadgetComponent mapComp = SCR_MapGadgetComponent.Cast(mapGadget.FindComponent(SCR_MapGadgetComponent));
417  mapComp.SetMapMode(false);
418  }
419 
420  //------------------------------------------------------------------------------------------------
423  protected void OnPlayerDeleted(int playerId, IEntity player)
424  {
425  if (playerId != GetGame().GetPlayerController().GetPlayerId())
426  return;
427 
428  MenuManager menuManager = g_Game.GetMenuManager();
429  menuManager.CloseMenuByPreset(ChimeraMenuPreset.MapMenu);
430  }
431 
432  //------------------------------------------------------------------------------------------------
434  protected void OnUserSettingsChanged()
435  {
436  UpdateTexts();
437 
438  if (m_bIsOpen)
439  {
440  UpdateZoomBounds();
441  ZoomSmooth(m_fZoomPPU, reinitZoom: true);
442  }
443  else
444  m_bDoUpdate = true;
445  }
446 
447  //------------------------------------------------------------------------------------------------
449  protected void OnWindowResized(int width, int heigth, bool windowed)
450  {
451  OnUserSettingsChanged();
452  }
453 
454  //------------------------------------------------------------------------------------------------
455  // MAP SETUP
456  //------------------------------------------------------------------------------------------------
461  MapConfiguration SetupMapConfig(EMapEntityMode mapMode, ResourceName configPath, Widget rootWidget)
462  {
463  if (mapMode == m_eLastMapMode)
464  {
465  m_ActiveMapCfg.RootWidgetRef = rootWidget;
466  return m_ActiveMapCfg;
467  }
468 
469  // clear loaded compas and modules
470  m_aLoadedComponents.Clear();
471  m_aLoadedModules.Clear();
472 
473  // Load config
474  Resource container = BaseContainerTools.LoadContainer(configPath);
475  if (!container)
476  return null;
477 
478  SCR_MapConfig mapConfig = SCR_MapConfig.Cast( BaseContainerTools.CreateInstanceFromContainer( container.GetResource().ToBaseContainer() ) );
479  MapConfiguration configObject = new MapConfiguration();
480 
481  // basic
482  configObject.RootWidgetRef = rootWidget;
483  configObject.MapEntityMode = mapConfig.m_iMapMode;
484 
485  // modules & componentss
486  configObject.Modules = mapConfig.m_aModules;
487  configObject.Components = mapConfig.m_aUIComponents;
488 
489  if (mapConfig.m_bEnableLegendScale == true)
490  configObject.OtherComponents |= EMapOtherComponents.LEGEND_SCALE;
491 
492  if (mapConfig.m_bEnableGrid == true)
493  configObject.OtherComponents |= EMapOtherComponents.GRID;
494 
495  SetupLayersAndProps(configObject, mapConfig);
496  SetupDescriptorTypes(mapConfig.m_DescriptorDefaultsConfig);
497 
498  return configObject;
499  }
500 
501  //------------------------------------------------------------------------------------------------
505  protected void SetupLayersAndProps(inout MapConfiguration configObject, SCR_MapConfig mapCfg)
506  {
507  SCR_MapLayersBase layersCfg = mapCfg.m_LayersConfig; // layers
508  if (!layersCfg) // use default if above fails
509  {
510  Resource containerDefs = BaseContainerTools.LoadContainer(SCR_MapConstants.CFG_LAYERS_DEFAULT);
511  layersCfg = SCR_MapLayersBase.Cast( BaseContainerTools.CreateInstanceFromContainer( containerDefs.GetResource().ToBaseContainer() ) );
512  }
513 
514  configObject.LayerConfig = layersCfg;
515 
516  if (layersCfg.m_aLayers.IsEmpty())
517  configObject.LayerCount = 0;
518  else
519  configObject.LayerCount = layersCfg.m_aLayers.Count();
520 
521  SCR_MapPropsBase propsCfg = mapCfg.m_MapPropsConfig; // map properties
522  if (!propsCfg) // use default if above fails
523  {
524  Resource containerDefs = BaseContainerTools.LoadContainer(SCR_MapConstants.CFG_PROPS_DEFAULT);
525  propsCfg = SCR_MapPropsBase.Cast( BaseContainerTools.CreateInstanceFromContainer( containerDefs.GetResource().ToBaseContainer() ) );
526  }
527 
528  configObject.MapPropsConfig = propsCfg;
529 
530  SCR_MapDescriptorVisibilityBase descriptorViewCfg = mapCfg.m_DescriptorVisibilityConfig; // descriptors visibility within layers
531  if (!descriptorViewCfg) // use default if above fails
532  {
533  Resource containerDefs = BaseContainerTools.LoadContainer(SCR_MapConstants.CFG_DESCVIEW_DEFAULT);
534  descriptorViewCfg = SCR_MapDescriptorVisibilityBase.Cast( BaseContainerTools.CreateInstanceFromContainer( containerDefs.GetResource().ToBaseContainer() ) );
535  }
536 
537  configObject.DescriptorVisibilityConfig = descriptorViewCfg;
538 
539 
540  SCR_MapDescriptorDefaults descriptorDefaults = mapCfg.m_DescriptorDefaultsConfig;
541  if (!descriptorDefaults)
542  {
543  Resource containerDefs = BaseContainerTools.LoadContainer(SCR_MapConstants.CFG_DESCTYPES_DEFAULT);
544  descriptorDefaults = SCR_MapDescriptorDefaults.Cast( BaseContainerTools.CreateInstanceFromContainer( containerDefs.GetResource().ToBaseContainer() ) );
545  }
546 
547  configObject.DescriptorDefsConfig = descriptorDefaults;
548  }
549 
550  //------------------------------------------------------------------------------------------------
554  protected void SetupDescriptorTypes(SCR_MapDescriptorDefaults descriptorDefaultsConfig)
555  {
556  array<int> imagesetIndices = {};
557 
558  if (!descriptorDefaultsConfig.m_aDescriptorDefaults.IsEmpty())
559  {
560  for (int i = 0; i < EMapDescriptorType.MDT_COUNT; ++i)
561  {
562  imagesetIndices.Insert(-1);
563  }
564 
565  foreach (SCR_DescriptorDefaultsBase descriptorDefs : descriptorDefaultsConfig.m_aDescriptorDefaults)
566  {
567  imagesetIndices[descriptorDefs.m_iDescriptorType] = descriptorDefs.m_iImageSetIndex;
568  }
569 
570  SetImagesetMapping(imagesetIndices);
571  }
572  }
573 
574  //------------------------------------------------------------------------------------------------
575  // MAP CONTROL METHODS
576  //------------------------------------------------------------------------------------------------
578  void CenterMap()
579  {
580  if (m_iDelayCounter > 0)
581  {
582  Print("SCR_MapEntity: Attempt to call CenterMap before map init is completed", LogLevel.WARNING);
583  return;
584  }
585 
587  int x, y;
588  WorldToScreen(GetMapSizeX() / 2, GetMapSizeY() / 2, x, y);
589 
590  SetPan(x, y);
591  }
592 
593  //------------------------------------------------------------------------------------------------
595  void ZoomOut()
596  {
597  SetZoom(m_fMinZoom, true);
598  CenterMap();
599  }
600 
601  //------------------------------------------------------------------------------------------------
603  void ShowScriptDebug()
604  {
605  m_bIsDebugMode = !m_bIsDebugMode;
606  }
607 
608  //------------------------------------------------------------------------------------------------
612  void SetZoom(float targetPPU, bool instant = false)
613  {
614  if (m_iDelayCounter > 0)
615  {
616  Print("SCR_MapEntity: Attempt to call SetZoom before map init is completed", LogLevel.NORMAL);
617  return;
618  }
619 
620  targetPPU = Math.Clamp(targetPPU, m_fMinZoom, m_fMaxZoom);
621 
622  m_fZoomPPU = targetPPU;
623  AssignViewLayer(false);
624  ZoomChange(targetPPU / m_MapWidget.PixelPerUnit()); // contours
625 
626  if (instant)
627  m_fTargetPPU = m_fZoomPPU;
628 
629  s_OnMapZoom.Invoke(targetPPU);
630  }
631 
632  //------------------------------------------------------------------------------------------------
638  void ZoomSmooth(float targetPixPerUnit, float zoomTime = 0.25, bool zoomToCenter = true, bool reinitZoom = false)
639  {
640  if (m_iDelayCounter > 0)
641  {
642  Print("SCR_MapEntity: Attempt to call ZoomSmooth before map init is completed", LogLevel.NORMAL);
643  return;
644  }
645 
646  if (zoomTime <= 0)
647  zoomTime = 0.1;
648 
649  targetPixPerUnit = Math.Clamp(targetPixPerUnit, m_fMinZoom, m_fMaxZoom);
650  if (!reinitZoom && targetPixPerUnit == m_fZoomPPU)
651  return;
652 
653  m_fStartPPU = m_fZoomPPU;
654  m_fTargetPPU = targetPixPerUnit;
655  m_fZoomTimeModif = 1/zoomTime;
656  m_fZoomSlice = 1.0;
657  m_bIsZoomInterp = true;
658 
659  float screenX, screenY, worldX, worldY, targetScreenX, targetScreenY;
660  m_MapWidget.GetScreenSize(screenX, screenY);
661 
662  if (zoomToCenter)
663  {
664  // zoom according to the current screen center
665  GetMapCenterWorldPosition(worldX, worldY);
666  WorldToScreenCustom( worldX, worldY, targetScreenX, targetScreenY, targetPixPerUnit, false );
667  PanSmooth( targetScreenX, targetScreenY, zoomTime );
668  }
669  else
670  {
671  // Calculate target pan position in a way which makes cursor stay on the same world pos while zooming
672  float diffX = screenX/2 - m_Workspace.DPIScale(SCR_MapCursorInfo.x); // difference in pixels between screen center and cursor
673  float diffY = screenY/2 - m_Workspace.DPIScale(SCR_MapCursorInfo.y);
674 
675  GetMapCursorWorldPosition(worldX, worldY); // current cursor world pos, relative anchor of zoom
676  WorldToScreenCustom( worldX, worldY, targetScreenX, targetScreenY, targetPixPerUnit, false ); // target screen pos of cursor with zoom applied
677  PanSmooth( targetScreenX + diffX, targetScreenY + diffY, zoomTime ); // offset the target position by the pix diference from screen center
678  }
679  }
680 
681  //------------------------------------------------------------------------------------------------
687  void ZoomPanSmooth(float targetPixPerUnit, float worldX, float worldY, float zoomTime = 0.25)
688  {
689  if (m_iDelayCounter > 0)
690  {
691  Print("SCR_MapEntity: Attempt to call ZoomPanSmooth before map init is completed", LogLevel.NORMAL);
692  return;
693  }
694 
695  if (zoomTime <= 0)
696  zoomTime = 0.1;
697 
698  if (targetPixPerUnit > m_fMaxZoom)
699  targetPixPerUnit = m_fMaxZoom;
700  else if (targetPixPerUnit < m_fMinZoom)
701  targetPixPerUnit = m_fMinZoom;
702 
703  m_fStartPPU = m_fZoomPPU;
704  m_fTargetPPU = targetPixPerUnit;
705  m_fZoomTimeModif = 1/zoomTime;
706  m_fZoomSlice = 1.0;
707  m_bIsZoomInterp = true;
708 
709  float screenX, screenY, targetScreenX, targetScreenY;
710  m_MapWidget.GetScreenSize(screenX, screenY);
711 
712  WorldToScreenCustom( worldX, worldY, targetScreenX, targetScreenY, targetPixPerUnit, false ); // target pos with zoom applied
713  PanSmooth( targetScreenX, targetScreenY, zoomTime );
714  }
715 
716  //------------------------------------------------------------------------------------------------
722  void SetPan(float x, float y, bool isPanEnd = true, bool center = true)
723  {
724  if (m_iDelayCounter > 0)
725  {
726  Print("SCR_MapEntity: Attempt to call SetPan before map init is completed", LogLevel.NORMAL);
727  return;
728  }
729 
730  bool adjustedPan = false;
731 
732  // test bounds
733  if (!FitPanBounds(x, y, center))
734  adjustedPan = true;
735 
736  // save current pan
737  m_iPanX = x;
738  m_iPanY = y;
739 
740  PosChange(m_Workspace.DPIScale(m_iPanX), m_Workspace.DPIScale(m_iPanY));
741 
742  if (isPanEnd)
743  SCR_MapCursorInfo.startPos = {0, 0};
744 
745  s_OnMapPan.Invoke(m_iPanX, m_iPanY, adjustedPan);
746  }
747 
748  //------------------------------------------------------------------------------------------------
752  void Pan(EMapPanMode panMode, float panValue = 0)
753  {
754  if (m_iDelayCounter > 0)
755  {
756  Print("SCR_MapEntity: Attempt to call Pan before map init is completed", LogLevel.NORMAL);
757  return;
758  }
759 
760  float panX, panY;
761 
762  // panning mode
763  if (panMode == EMapPanMode.DRAG)
764  {
765  // begin drag
766  if (SCR_MapCursorInfo.startPos[0] == 0 && SCR_MapCursorInfo.startPos[1] == 0)
768 
769  // mouse position difference
770  int diffX = SCR_MapCursorInfo.x - SCR_MapCursorInfo.startPos[0];
771  int diffY = SCR_MapCursorInfo.y - SCR_MapCursorInfo.startPos[1];
772 
773  panX = m_iPanX + diffX;
774  panY = m_iPanY + diffY;
775 
776  SCR_MapCursorInfo.startPos[0] = SCR_MapCursorInfo.x;
777  SCR_MapCursorInfo.startPos[1] = SCR_MapCursorInfo.y;
778  }
779  else if (panMode == EMapPanMode.HORIZONTAL)
780  {
781  panX = m_iPanX + panValue;
782  panY = m_iPanY;
783  }
784  else if (panMode == EMapPanMode.VERTICAL)
785  {
786  panX = m_iPanX;
787  panY = m_iPanY + panValue;
788  }
789 
790  // Pan
791  SetPan(panX, panY, false, false);
792  s_OnMapPanEnd.Invoke(panX, panY);
793  }
794 
795  //------------------------------------------------------------------------------------------------
800  void PanSmooth(float panX, float panY, float panTime = 0.25)
801  {
802  if (m_iDelayCounter > 0)
803  {
804  Print("SCR_MapEntity: Attempt to call PanSmooth before map init is completed", LogLevel.NORMAL);
805  return;
806  }
807 
808  float screenWidth, screenHeight;
809  m_MapWidget.GetScreenSize(screenWidth, screenHeight);
810 
811  if (panTime <= 0)
812  panTime = 0.1;
813 
814  // un-center to get direct pan pos
815  m_aStartPan = { m_Workspace.DPIUnscale(screenWidth/2) - m_iPanX, m_Workspace.DPIUnscale(screenHeight/2) - m_iPanY };
816  m_aTargetPan = { m_Workspace.DPIUnscale(panX), m_Workspace.DPIUnscale(panY) };
817  m_fPanTimeModif = 1/panTime;
818  m_fPanSlice = 1.0;
819  m_bIsPanInterp = true;
820  }
821 
822  //------------------------------------------------------------------------------------------------
825  void InvokeOnSelect(vector selectionPos)
826  {
827  s_OnSelection.Invoke(selectionPos);
828  }
829 
832  void SelectItem(MapItem item)
833  {
834  item.Select(true);
835  item.SetHighlighted(true);
836 
837 
838  s_OnSelectionChanged.Invoke(item);
839  }
840 
841  //------------------------------------------------------------------------------------------------
844  void HoverItem(MapItem item)
845  {
846  item.SetHovering(true);
847  m_HoveredMapItem = item;
848 
849  s_OnHoverItem.Invoke(item);
850  }
851 
852  //------------------------------------------------------------------------------------------------
854  void ClearSelection()
855  {
856  ResetSelected();
858 
859  s_OnSelectionChanged.Invoke(null);
860  }
861 
862  //------------------------------------------------------------------------------------------------
864  void ClearHover()
865  {
866  ResetHovering();
867 
868  s_OnHoverEnd.Invoke(m_HoveredMapItem);
869  m_HoveredMapItem = null;
870  }
871 
872  //------------------------------------------------------------------------------------------------
873  // CONVERSION METHODS
874  //------------------------------------------------------------------------------------------------
876  // \param worldX is world x
877  // \param worldY is world y
878  // \param screenPosX is screen x
879  // \param screenPosY is screen y
880  // \param withPan determines whether current pan is added to the result
881  void WorldToScreen(float worldX, float worldY, out int screenPosX, out int screenPosY, bool withPan = false)
882  {
883  worldY = m_iMapSizeY - worldY; // fix Y axis which is reversed between screen and world
884 
885  if (withPan)
886  {
887  screenPosX = (worldX * m_fZoomPPU) + m_Workspace.DPIScale(m_iPanX);
888  screenPosY = (worldY * m_fZoomPPU) + m_Workspace.DPIScale(m_iPanY);
889  }
890  else
891  {
892  screenPosX = worldX * m_fZoomPPU;
893  screenPosY = worldY * m_fZoomPPU;
894  }
895  }
896 
897  //------------------------------------------------------------------------------------------------
899  // \param worldX is world x
900  // \param worldY is world y
901  // \param screenPosX is screen x
902  // \param screenPosY is screen y
903  // \param withPan determines whether current pan is added to the result
904  // \param targetPPU sets PixelPerUnit used for the calculation (useful for precalculating)
905  void WorldToScreenCustom(float worldX, float worldY, out int screenPosX, out int screenPosY, float targetPPU, bool withPan = false)
906  {
907  worldY = m_iMapSizeY - worldY;
908 
909  if (withPan)
910  {
911  screenPosX = (worldX * targetPPU) + m_Workspace.DPIScale(m_iPanX);
912  screenPosY = (worldY * targetPPU) + m_Workspace.DPIScale(m_iPanY);
913  }
914  else
915  {
916  screenPosX = worldX * targetPPU;
917  screenPosY = worldY * targetPPU;
918  }
919  }
920 
921  //------------------------------------------------------------------------------------------------
923  // \param screenPosX is screen x
924  // \param screenPosY is screen y
925  // \param worldX is world x
926  // \param worldY is world y
927  void ScreenToWorld(int screenPosX, int screenPosY, out float worldX, out float worldY)
928  {
929  worldX = (screenPosX - m_Workspace.DPIScale(m_iPanX)) / m_fZoomPPU;
930  worldY = (screenPosY - m_Workspace.DPIScale(m_iPanY)) / m_fZoomPPU;
931  worldY = m_iMapSizeY - worldY; // fix Y axis which is reversed between screen and world
932  }
933 
934  //------------------------------------------------------------------------------------------------
936  // \param screenPosX is screen x
937  // \param screenPosY is screen y
938  // \param worldX is world x
939  // \param worldY is world y
940  void ScreenToWorldNoFlip(int screenPosX, int screenPosY, out float worldX, out float worldY)
941  {
942  worldX = (screenPosX - m_Workspace.DPIScale(m_iPanX)) / m_fZoomPPU;
943  worldY = (screenPosY - m_Workspace.DPIScale(m_iPanY)) / m_fZoomPPU;
944  }
945 
954  //--- ToDo: Use grid sizes configured in layers in case someone will define non-metric grid
955  static string GetGridLabel(vector pos, int resMin = 2, int resMax = 4, string delimiter = " ")
956  {
957  int gridX, gridZ;
958  GetGridPos(pos, gridX, gridZ, resMin, resMax);
959  return gridX.ToString() + delimiter + gridZ.ToString();
960  }
961 
969  static void GetGridPos(vector pos, out int gridX, out int gridZ, int resMin = 2, int resMax = 4)
970  {
971  //--- Convert to int so we can use native mod operator %
972  int posX = pos[0];
973  int posZ = pos[2];
974 
975  for (int i = resMax; i >= resMin; i--)
976  {
977  int mod = Math.Pow(10, i);
978  int modX = posX - posX % mod;
979  int modZ = posZ - posZ % mod;
980  gridX = gridX * 10 + (modX / mod);
981  gridZ = gridZ * 10 + (modZ / mod);
982  posX -= modX;
983  posZ -= modZ;
984  }
985  }
986 
987  //------------------------------------------------------------------------------------------------
988  // SUPPORT METHODS
989  //------------------------------------------------------------------------------------------------
994  protected bool FitPanBounds(inout float panX, inout float panY, bool center)
995  {
996  float windowWidth, windowHeight;
997  m_MapWidget.GetScreenSize(windowWidth, windowHeight);
998 
999  windowWidth = m_Workspace.DPIUnscale(windowWidth);
1000  windowHeight = m_Workspace.DPIUnscale(windowHeight);
1001 
1002  // center to coords
1003  if (center)
1004  {
1005  panX = windowWidth/2 - panX;
1006  panY = windowHeight/2 - panY;
1007  }
1008 
1009  int width = m_iMapSizeX * m_fZoomPPU;
1010  int height = m_iMapSizeY * m_fZoomPPU;
1011 
1012  // center of the screen can travel everywhere within map
1013  int minCoordX = windowWidth/2 - m_Workspace.DPIUnscale(width);
1014  int minCoordY = windowHeight/2 - m_Workspace.DPIUnscale(height);
1015  int maxCoordX = windowWidth/2;
1016  int maxCoordY = windowHeight/2;
1017 
1018  // cannot pan outside of map bounds
1019  /*int minCoordX = windowWidth - width;
1020  int minCoordY = windowHeight - height;
1021  int maxCoordX = 0;
1022  int maxCoordY = 0;*/
1023 
1024  bool adjusted = false;
1025 
1026  // stop when over min/max
1027  if (panX < minCoordX)
1028  {
1029  panX = minCoordX;
1030  adjusted = true;
1031  }
1032 
1033  if (panX > maxCoordX)
1034  {
1035  panX = maxCoordX;
1036  adjusted = true;
1037  }
1038 
1039  if (panY < minCoordY)
1040  {
1041  panY = minCoordY;
1042  adjusted = true;
1043  }
1044 
1045  if (panY > maxCoordY)
1046  {
1047  panY = maxCoordY;
1048  adjusted = true;
1049  }
1050 
1051  if (adjusted)
1052  return false;
1053 
1054  return true;
1055  }
1056 
1057  //------------------------------------------------------------------------------------------------
1060  bool UpdateZoomBounds()
1061  {
1062  float screenWidth, screenHeight;
1063  m_MapWidget.GetScreenSize(screenWidth, screenHeight);
1064 
1065  float maxUnitsPerScreen = screenHeight / m_MapWidget.PixelPerUnit();
1066  m_fMinZoom = (maxUnitsPerScreen / m_iMapSizeY) * m_MapWidget.PixelPerUnit();
1067  m_fMaxZoom = SCR_MapConstants.MAX_PIX_PER_METER;
1068 
1069  return true;
1070  }
1071 
1072  //------------------------------------------------------------------------------------------------
1074  protected void AssignViewLayer(bool isInit)
1075  {
1076  int count = LayerCount();
1077  if (count == 0) // No layers to change to
1078  return;
1079 
1080  for ( int layerID = 0; layerID < count; layerID++ )
1081  {
1082  if ( GetCurrentZoom() >= GetLayer(layerID).GetCeiling() )
1083  {
1084  if (isInit || layerID != GetLayerIndex())
1085  {
1086  SetLayer(layerID);
1087  s_OnLayerChanged.Invoke(layerID);
1088  }
1089 
1090  break;
1091  }
1092  }
1093  }
1094 
1095  //------------------------------------------------------------------------------------------------
1096  // INIT / CLEANUP METHODS
1097  //------------------------------------------------------------------------------------------------
1099  protected void InitLayers(MapConfiguration mapConfig)
1100  {
1101  SCR_MapLayersBase layerConfig = mapConfig.LayerConfig;
1102 
1103  int layerCount = mapConfig.LayerCount;
1104  InitializeLayers(layerCount);
1105 
1106  if (layerCount < 1)
1107  return;
1108 
1109  for (int i = 0; i < layerCount; i++) // per layer configuration
1110  {
1111  MapLayer layer = GetLayer(i);
1112  if (layer)
1113  {
1114  // setr ceiling vals
1115  layerConfig.m_aLayers[i].SetLayerProps(layer);
1116 
1117  // props configs
1118  foreach ( SCR_MapPropsConfig propsCfg : mapConfig.MapPropsConfig.m_aMapPropConfigs)
1119  {
1120  propsCfg.SetDefaults(layer);
1121  }
1122 
1123  // descriptor configuration init
1124  InitDescriptors(i, layer, layerConfig.m_aLayers[i], mapConfig);
1125  }
1126  }
1127  }
1128 
1129  //------------------------------------------------------------------------------------------------
1134  protected void InitDescriptors(int layerID, MapLayer layer, SCR_LayerConfiguration layerConfig, MapConfiguration mapConfig)
1135  {
1136  // create descriptor visiiblity map
1137  map<int, int> descriptorVisibility = new map<int, int>;
1138 
1139  // descriptor visibility configuration
1140  foreach (SCR_DescriptorViewLayer descConfig : mapConfig.DescriptorVisibilityConfig.m_aDescriptorViewLayers)
1141  {
1142  if (descConfig.m_iViewLayer >= layerID + 1)
1143  descriptorVisibility.Set(descConfig.m_iDescriptorType, layerID); // match descriptor type with visibility
1144  }
1145 
1146  foreach (SCR_DescriptorDefaultsBase descriptorType : mapConfig.DescriptorDefsConfig.m_aDescriptorDefaults)
1147  {
1148  // visible in the current layer
1149  if ( descriptorVisibility.Get(descriptorType.m_iDescriptorType) >= layerID )
1150  {
1151  MapDescriptorProps props;
1152 
1153  // is using faction based configuration
1154  if (descriptorType.m_bUseFactionColors)
1155  {
1156  foreach (SCR_FactionColorDefaults factionDefaults : mapConfig.DescriptorDefsConfig.m_aFactionColors)
1157  {
1158  props = layer.GetPropsFor(factionDefaults.m_iFaction, descriptorType.m_iDescriptorType);
1159  if (props)
1160  {
1161  descriptorType.SetDefaults(props);
1162  factionDefaults.SetColors(props);
1163  }
1164  }
1165  }
1166  else
1167  {
1168  props = layer.GetPropsFor(EFactionMapID.UNKNOWN, descriptorType.m_iDescriptorType);
1169  if (props)
1170  {
1171  descriptorType.SetDefaults(props);
1172  descriptorType.SetColors(props);
1173  }
1174  }
1175  }
1176  // not visible in the current layer
1177  else
1178  {
1179  MapDescriptorProps props;
1180 
1181  // is using faction based configuration
1182  if (descriptorType.m_bUseFactionColors)
1183  {
1184  foreach (SCR_FactionColorDefaults factionDefaults : mapConfig.DescriptorDefsConfig.m_aFactionColors)
1185  {
1186  props = layer.GetPropsFor(factionDefaults.m_iFaction, descriptorType.m_iDescriptorType);
1187  if (props)
1188  props.SetVisible(false);
1189  }
1190  }
1191  else
1192  {
1193  props = layer.GetPropsFor(EFactionMapID.UNKNOWN, descriptorType.m_iDescriptorType);
1194  if (props)
1195  props.SetVisible(false);
1196  }
1197  }
1198  }
1199  }
1200 
1201  //------------------------------------------------------------------------------------------------
1204  //------------------------------------------------------------------------------------------------
1205  protected void ActivateModules( array<ref SCR_MapModuleBase> modules )
1206  {
1207  if (modules.IsEmpty())
1208  return;
1209 
1210  array<SCR_MapModuleBase> modulesToInit = new array<SCR_MapModuleBase>();
1211 
1212  foreach ( SCR_MapModuleBase module : modules )
1213  {
1214  // load new module
1215  if (m_bDoReload)
1216  {
1217  if (module.IsConfigDisabled())
1218  continue;
1219 
1220  m_aLoadedModules.Insert(module);
1221  modulesToInit.Insert(module);
1222  m_aActiveModules.Insert(module);
1223  module.SetActive(true);
1224  }
1225  // activate modules
1226  else
1227  {
1228  int count = m_aLoadedModules.Count();
1229  for (int i = 0; i < count; i++)
1230  {
1231  if (!m_aLoadedModules[i].IsInherited(module.Type()))
1232  continue;
1233 
1234  // is module active
1235  if (m_aActiveModules.Find(m_aLoadedModules[i]) == -1)
1236  {
1237  m_aActiveModules.Insert(m_aLoadedModules[i]);
1238  m_aLoadedModules[i].SetActive(true);
1239  break;
1240  }
1241  }
1242  }
1243  }
1244 
1245  foreach ( SCR_MapModuleBase module : modulesToInit )
1246  {
1247  module.Init();
1248  }
1249  }
1250 
1251  //------------------------------------------------------------------------------------------------
1254  protected void ActivateComponents( array<ref SCR_MapUIBaseComponent> components )
1255  {
1256  if (components.IsEmpty())
1257  return;
1258 
1259  array<SCR_MapUIBaseComponent> componentsToInit = new array<SCR_MapUIBaseComponent>();
1260 
1261  foreach ( SCR_MapUIBaseComponent component : components )
1262  {
1263  // load new component
1264  if (m_bDoReload)
1265  {
1266  if (component.IsConfigDisabled())
1267  continue;
1268 
1269  m_aLoadedComponents.Insert(component);
1270  componentsToInit.Insert(component);
1271  m_aActiveComponents.Insert(component);
1272  component.SetActive(true);
1273  }
1274  // activate components
1275  else
1276  {
1277  int count = m_aLoadedComponents.Count();
1278  for (int i = 0; i < count; i++)
1279  {
1280  if (!m_aLoadedComponents[i].IsInherited(component.Type()))
1281  continue;
1282 
1283  // is component active
1284  if (m_aActiveComponents.Find(m_aLoadedComponents[i]) == -1)
1285  {
1286  m_aActiveComponents.Insert(m_aLoadedComponents[i]);
1287  m_aLoadedComponents[i].SetActive(true);
1288  break;
1289  }
1290  }
1291  }
1292  }
1293 
1294  foreach ( SCR_MapUIBaseComponent component : componentsToInit )
1295  {
1296  component.Init();
1297  }
1298 
1299  }
1300 
1301  //------------------------------------------------------------------------------------------------
1304  protected void ActivateOtherComponents(EMapOtherComponents componentFlags)
1305  {
1306  if (componentFlags & EMapOtherComponents.LEGEND_SCALE)
1307  EnableLegend(true);
1308  else
1309  EnableLegend(false);
1310 
1311  if (componentFlags & EMapOtherComponents.GRID)
1312  EnableGrid(true);
1313  else
1314  EnableGrid(false);
1315 
1316  }
1317 
1318  //------------------------------------------------------------------------------------------------
1320  void DeactivateModule(SCR_MapModuleBase module)
1321  {
1322  m_aActiveModules.RemoveItem(module);
1323  m_aLoadedModules.RemoveItem(module);
1324  }
1325 
1326  //------------------------------------------------------------------------------------------------
1328  void DeactivateComponent(SCR_MapUIBaseComponent component)
1329  {
1330  m_aActiveComponents.RemoveItem(component);
1331  m_aLoadedComponents.RemoveItem(component);
1332  }
1333 
1334  //------------------------------------------------------------------------------------------------
1336  protected void Cleanup()
1337  {
1338  // deactivate components & modules
1339  foreach (SCR_MapUIBaseComponent component : m_aActiveComponents )
1340  {
1341  component.SetActive(false, true);
1342  }
1343  m_aActiveComponents.Clear();
1344 
1345  foreach (SCR_MapModuleBase module : m_aActiveModules )
1346  {
1347  module.SetActive(false, true);
1348  }
1349  m_aActiveModules.Clear();
1350 
1351  m_bIsDebugMode = false;
1352  }
1353 
1354  //------------------------------------------------------------------------------------------------
1355  // UPDATE METHODS
1356  //------------------------------------------------------------------------------------------------
1358  void UpdateViewPort()
1359  {
1360  float screenWidth, screenHeight;
1361  m_MapWidget.GetScreenSize(screenWidth, screenHeight);
1362 
1363  float minCoordX, minCoordY, maxCoordX, maxCoordY;
1364 
1365  ScreenToWorld(screenWidth, 0, maxCoordX, maxCoordY);
1366  ScreenToWorld(0, screenHeight, minCoordX, minCoordY);
1367 
1368  m_vVisibleFrameMin = Vector(minCoordX, 0, minCoordY);
1369  m_vVisibleFrameMax = Vector(maxCoordX, 0, maxCoordY);
1371  }
1372 
1373  //------------------------------------------------------------------------------------------------
1376  protected void PanUpdate(float timeSlice)
1377  {
1378  m_fPanSlice -= timeSlice * m_fPanTimeModif;
1379 
1380  // End interpolation
1381  if (m_fPanSlice <= 0)
1382  {
1383  m_bIsPanInterp = false;
1384  SetPan(m_aTargetPan[0], m_aTargetPan[1]);
1385  s_OnMapPanEnd.Invoke(m_aTargetPan[0], m_aTargetPan[1]);
1386  }
1387  else
1388  {
1389  int panX = Math.Lerp(m_aStartPan[0], m_aTargetPan[0], 1 - m_fPanSlice);
1390  int panY = Math.Lerp(m_aStartPan[1], m_aTargetPan[1], 1 - m_fPanSlice);
1391  SetPan(panX, panY, false);
1392  }
1393  }
1394 
1395  //------------------------------------------------------------------------------------------------
1398  protected void ZoomUpdate(float timeSlice)
1399  {
1400  m_fZoomSlice -= timeSlice * m_fZoomTimeModif;
1401 
1402  // End interpolation
1403  if (m_fZoomSlice <= 0)
1404  {
1405  SetZoom(m_fTargetPPU);
1406  s_OnMapZoomEnd.Invoke(m_fTargetPPU);
1407  m_bIsZoomInterp = false;
1408  }
1409  else
1410  {
1411  float zoom = Math.Lerp(m_fStartPPU, m_fTargetPPU, 1 - m_fZoomSlice);
1412  SetZoom(zoom);
1413  }
1414  }
1415 
1416  //------------------------------------------------------------------------------------------------
1418  protected void UpdateDebug()
1419  {
1420  float wX, wY;
1421  float x = m_Workspace.DPIScale(SCR_MapCursorInfo.x);
1422  float y = m_Workspace.DPIScale(SCR_MapCursorInfo.y);
1423  ScreenToWorld(x, y, wX, wY);
1424 
1425  vector pan = GetCurrentPan();
1426  array<MapItem> outItems = {};
1427  GetSelected(outItems);
1428 
1429  DbgUI.Begin("Map debug");
1430  string dbg1 = "CURSOR SCREEN POS: x: %1 y: %2";
1431  DbgUI.Text( string.Format( dbg1, x, y ) );
1432  string dbg2 = "CURSOR WORLD POS: x: %1 y: %2";
1433  DbgUI.Text( string.Format( dbg2, wX, wY ) );
1434  string dbg3 = "PAN OFFSET: x: %1 y: %2 ";
1435  DbgUI.Text( string.Format( dbg3, pan[0], pan[1] ) );
1436  string dbg4 = "ZOOM: min: %1 max: %2 | pixPerUnit: %3";
1437  DbgUI.Text( string.Format( dbg4, GetMinZoom(), GetMaxZoom(), GetCurrentZoom() ) );
1438  string dbg5 = "LAYER: current: %1 | pixPerUnit ceiling: %2";
1439  DbgUI.Text( string.Format( dbg5, GetLayerIndex(), GetLayer(GetLayerIndex()).GetCeiling() ) );
1440  string dbg6 = "MODULES: loaded: %1 | active: %2 | list: %3 ";
1441  DbgUI.Text( string.Format( dbg6, m_aLoadedModules.Count(), m_aActiveModules.Count(), m_aActiveModules ) );
1442  string dbg7 = "COMPONENTS: loaded: %1 | active: %2 | list: %3 ";
1443  DbgUI.Text( string.Format( dbg7, m_aLoadedComponents.Count(), m_aActiveComponents.Count(), m_aActiveComponents ) );
1444  string dbg8 = "MAPITEMS: selected: %1 | hovered: %2 ";
1445  DbgUI.Text( string.Format( dbg8, outItems, m_HoveredMapItem ) );
1446  DbgUI.End();
1447  }
1448 
1449  //------------------------------------------------------------------------------------------------
1452  protected void UpdateMap(float timeSlice)
1453  {
1454  // update modules
1455  foreach ( SCR_MapModuleBase module : m_aActiveModules)
1456  {
1457  module.Update(timeSlice);
1458  }
1459 
1460  //update components
1461  foreach ( SCR_MapUIBaseComponent component : m_aActiveComponents)
1462  {
1463  component.Update(timeSlice);
1464  }
1465 
1466  // interpolation update
1467  if (m_bIsZoomInterp)
1468  ZoomUpdate(timeSlice);
1469 
1470  if (m_bIsPanInterp)
1471  PanUpdate(timeSlice);
1472  }
1473 
1474 #ifndef DISABLE_GADGETS
1475  //------------------------------------------------------------------------------------------------
1476  override void EOnFrame(IEntity owner, float timeSlice)
1477  {
1478  if (IsOpen())
1479  {
1480  // delayed init -> This is here so the MapWidget has time to initiate its size & PixelPerUnit calculation
1481  if (m_iDelayCounter >= 0)
1482  {
1483  if (m_iDelayCounter == 0)
1484  {
1485  m_iDelayCounter--;
1486  OnMapOpen(m_ActiveMapCfg);
1487  }
1488  else
1489  {
1490  m_iDelayCounter--;
1491  return;
1492  }
1493  }
1494 
1495  UpdateMap(timeSlice);
1496 
1497  if (m_bIsDebugMode)
1498  UpdateDebug();
1499 
1500  UpdateViewPort();
1501  }
1502  }
1503 
1504  //------------------------------------------------------------------------------------------------
1505  override void EOnInit(IEntity owner)
1506  {
1507  // Save size
1508  m_iMapSizeX = Size()[0];
1509  m_iMapSizeY = Size()[2];
1510 
1511  if (m_iMapSizeX == 0 || m_iMapSizeY == 0)
1512  {
1513  Print("SCR_MapEntity: Cannot get the size from terrain. Using default.", LogLevel.WARNING);
1514  m_iMapSizeX = 1024;
1515  m_iMapSizeY = 1024;
1516  }
1517 
1518  ChimeraWorld world = GetGame().GetWorld();
1519  if (world)
1520  world.RegisterEntityToBeUpdatedWhileGameIsPaused(this);
1521  }
1522 
1523  //------------------------------------------------------------------------------------------------
1524  void SCR_MapEntity(IEntitySource src, IEntity parent)
1525  {
1526  SetEventMask(EntityEvent.INIT | EntityEvent.FRAME);
1527 
1528  s_MapInstance = this;
1529 
1530  DiagMenu.RegisterBool(SCR_DebugMenuID.DEBUGUI_UI_MAP_DEBUG_OPTIONS, "", "Enable map debug menu", "UI");
1531 
1532  GetGame().OnUserSettingsChangedInvoker().Insert(OnUserSettingsChanged);
1533  GetGame().OnWindowResizeInvoker().Insert(OnWindowResized);
1534  }
1535 
1536  //------------------------------------------------------------------------------------------------
1537  void ~SCR_MapEntity()
1538  {
1539  if (m_bIsOpen)
1540  CloseMap();
1541 
1542  ChimeraWorld world = GetGame().GetWorld();
1543  if (world)
1544  world.UnregisterEntityToBeUpdatedWhileGameIsPaused(this);
1545 
1546  s_OnMapInit.Clear();
1547  s_OnMapOpen.Clear();
1548  s_OnMapClose.Clear();
1549  s_OnMapPan.Clear();
1550  s_OnMapPanEnd.Clear();
1551  s_OnMapZoom.Clear();
1552  s_OnMapZoomEnd.Clear();
1553  s_OnSelectionChanged.Clear();
1554  s_OnSelection.Clear();
1555  s_OnHoverItem.Clear();
1556  s_OnHoverEnd.Clear();
1557  s_OnLayerChanged.Clear();
1558 
1559  DiagMenu.Unregister(SCR_DebugMenuID.DEBUGUI_UI_MAP_DEBUG_OPTIONS);
1560 
1561  s_MapInstance = null;
1562  }
1563 
1564 #endif
1565 };
ChimeraWorld
Definition: ChimeraWorld.c:12
SCR_BaseGameMode
Definition: SCR_BaseGameMode.c:137
GetLayer
proto external MapLayer GetLayer(int index)
Get layer by Index.
GetCharacterController
protected SCR_CharacterControllerComponent GetCharacterController(IEntity from)
Definition: SCR_ItemPlacementComponent.c:50
ZoomChange
proto external void ZoomChange(float level)
Set new zoom.
SCR_MapPropsBase
Map props root.
Definition: SCR_MapConfig.c:99
SCR_LayerConfiguration
Definition: SCR_MapConfig.c:62
SCR_MapConfig
Map config root.
Definition: SCR_MapConfig.c:4
EMapPanMode
EMapPanMode
Panning modes.
Definition: SCR_MapConstants.c:19
EntityEditorProps
enum EQueryType EntityEditorProps(category:"GameScripted/Sound", description:"THIS IS THE SCRIPT DESCRIPTION.", color:"0 0 255 255")
Definition: SCR_AmbientSoundsComponent.c:12
SCR_MapEntityClass
Definition: SCR_MapEntity.c:1
ECharacterLifeState
ECharacterLifeState
Definition: ECharacterLifeState.c:12
ScriptInvokerInt
ScriptInvokerBase< ScriptInvokerIntMethod > ScriptInvokerInt
Definition: SCR_ScriptInvokerHelper.c:24
SetImagesetMapping
proto external void SetImagesetMapping(notnull array< int > values)
Sets corresponding multiple imageset indices for MapDescriptors usage.
SCR_MapDescriptorDefaults
Config for default values set per descriptor type.
Definition: SCR_MapDescriptorDefaults.c:4
ResetHighlighted
proto external void ResetHighlighted()
Reset all entity highlighted tag.
SCR_UISoundEntity
Definition: SCR_UISoundEntity.c:7
ScriptInvokerFloat2
ScriptInvokerBase< ScriptInvokerFloat2Method > ScriptInvokerFloat2
Definition: SCR_ScriptInvokerHelper.c:59
EnableLegend
proto external protected void EnableLegend(bool bValue)
Enable/ Disable legend.
GetGame
ArmaReforgerScripted GetGame()
Definition: game.c:1424
GetSelected
proto external int GetSelected(out notnull array< MapItem > outItems)
Get all selected entities.
SCR_MapPropsConfig
Property type base.
Definition: SCR_MapPropsConfig.c:4
SCR_GadgetManagerComponent
Definition: SCR_GadgetManagerComponent.c:138
SCR_SoundEvent
Definition: SCR_SoundEvent.c:1
InitializeLayers
proto external void InitializeLayers(int count, int factionSize=4)
Clear layer setup + set new layer count.
UpdateTexts
MapEntityClass GenericEntityClass UpdateTexts()
func
func
Definition: SCR_AIThreatSystem.c:5
EnableVisualisation
proto external void EnableVisualisation(bool bValue)
Enable/ Disable visualisation.
SCR_CharacterControllerComponent
Definition: SCR_CharacterControllerComponent.c:35
GetPlayerController
proto external PlayerController GetPlayerController()
Definition: SCR_PlayerDeployMenuHandlerComponent.c:307
SCR_MapDescriptorVisibilityBase
Descriptor visibility config root.
Definition: SCR_MapConfig.c:117
SCR_FactionColorDefaults
Configuration of descriptor defaults.
Definition: SCR_MapDescriptorDefaults.c:28
GetGameMode
SCR_BaseGameMode GetGameMode()
Definition: SCR_BaseGameModeComponent.c:15
LayerCount
proto external int LayerCount()
Get layer count.
MapConfigurationInvoker
func MapConfigurationInvoker
Definition: SCR_MapEntity.c:8
m_vVisibleFrameMin
protected vector m_vVisibleFrameMin
Definition: SCR_MapMarkerManagerComponent.c:20
MapDescriptorProps
Definition: MapDescriptorProps.c:12
MapItem
Definition: MapItem.c:12
ScriptInvokerFloat
ScriptInvokerBase< ScriptInvokerFloatMethod > ScriptInvokerFloat
Definition: SCR_ScriptInvokerHelper.c:58
IsInherited
bool IsInherited(string factionKey)
Definition: SCR_Faction.c:227
MapEntityClass
Definition: MapEntity.c:12
m_Workspace
protected WorkspaceWidget m_Workspace
Definition: SCR_EntitiesEditorUIComponent.c:13
SCR_MapEntity
Map entity.
Definition: SCR_MapEntity.c:20
MapItemInvoker
func MapItemInvoker
Definition: SCR_MapEntity.c:11
GetControlledEntity
SCR_EditableEntityComponent GetControlledEntity()
Returns the controlled entity or null if none.
Definition: SCR_EditablePlayerDelegateComponent.c:86
ScriptInvokerVector
ScriptInvokerBase< ScriptInvokerVectorMethod > ScriptInvokerVector
Definition: SCR_ScriptInvokerHelper.c:101
GetLayerIndex
proto external int GetLayerIndex()
Returns -1 if no valid index previously set.
ScriptInvokerFloat2Bool
func ScriptInvokerFloat2Bool
Definition: SCR_MapEntity.c:14
SCR_MapModuleBase
Map module base class.
Definition: SCR_MapModuleBase.c:4
EMapOtherComponents
EMapOtherComponents
Map components which are not part of the component system.
Definition: SCR_MapConstants.c:80
CurrentCamera
CameraManagerClass GenericEntityClass CurrentCamera()
Returns the current camera.
EMapDescriptorType
EMapDescriptorType
Definition: EMapDescriptorType.c:15
ChimeraMenuPreset
ChimeraMenuPreset
Menu presets.
Definition: ChimeraMenuBase.c:3
SetLayer
proto external void SetLayer(int index)
Set active layer.
SCR_MapCursorInfo
Cursor data.
Definition: SCR_MapCursorModule.c:3
ResetHovering
proto external void ResetHovering()
Reset all entity hovering tag.
SCR_DescriptorDefaultsBase
Configuration of descriptor defaults.
Definition: SCR_MapDescriptorDefaults.c:51
SCR_MapConstants
Definition: SCR_MapConstants.c:2
EMapEntityMode
EMapEntityMode
Mode of the map.
Definition: SCR_MapConstants.c:28
SCR_DebugMenuID
SCR_DebugMenuID
This enum contains all IDs for DiagMenu entries added in script.
Definition: DebugMenuID.c:3
m_vVisibleFrameMax
protected vector m_vVisibleFrameMax
Definition: SCR_MapMarkerManagerComponent.c:21
SCR_DescriptorViewLayer
Configuration of visibility in layers per descriptor type.
Definition: SCR_MapConfig.c:36
ResetSelected
proto external void ResetSelected()
Reset all entity selection.
SCR_MapUIBaseComponent
Definition: SCR_MapUIBaseComponent.c:3
PosChange
proto external void PosChange(float x, float y)
Set new pos of map.
MapLayer
Definition: MapLayer.c:12
SCR_MapLayersBase
Layer config root.
Definition: SCR_MapConfig.c:108
GetPlayerId
proto external int GetPlayerId()
Definition: SCR_SpawnRequestComponent.c:39
SetFrame
proto external void SetFrame(vector start, vector end)
Set frame to visualise (from -> to)
EnableGrid
proto external void EnableGrid(bool bValue)
Enable/ Disable grid visibility.
category
params category
Definition: SCR_VehicleDamageManagerComponent.c:180
Size
proto external vector Size()
Terrain dimensions (x, height = maxElevation-minElevation, z)