Arma Reforger Explorer  1.1.0.42
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
SCR_PreviewEntityEditorComponent.c
Go to the documentation of this file.
1 [ComponentEditorProps(category: "GameScripted/Editor", description: "Manager of preview entity. Works only with SCR_EditorBaseEntity!", icon: "WBData/ComponentEditorProps/componentEditor.png")]
3 {
4 };
5 
13 {
14  [Attribute(category: "Preview", params: "et", desc: "Default ghost preview entity.")]
15  private ResourceName m_PreviewEntityPrefab;
16 
17  [Attribute(category: "Preview", params: "et", desc: "Ghost preview used when waiting for server callback.")]
18  private ResourceName m_WaitingEntityPrefab;
19 
20  [Attribute(category: "Preview", params: "emat", uiwidget: UIWidgets.ResourcePickerThumbnail, desc: "Preview entity material when confirmation is allowed.")]
21  private ResourceName m_PreviewMaterial;
22 
23  [Attribute(category: "Preview", params: "emat", uiwidget: UIWidgets.ResourcePickerThumbnail, desc: "Preview entity material when confirmation is not allowed.")]
24  private ResourceName m_DisabledPreviewMaterial;
25 
26  [Attribute(category: "Preview", params: "emat", uiwidget: UIWidgets.ResourcePickerThumbnail)]
27  private ResourceName m_WaitingPreviewMaterial;
28 
29  [Attribute(category: "Preview", params: "emat", uiwidget: UIWidgets.ResourcePickerThumbnail)]
30  private ResourceName m_WarningPreviewMaterial;
31 
32  [Attribute(category: "Preview", defvalue: "0.02")]
33  private float m_fPreviewTranslationInertia;
34 
35  [Attribute(category: "Preview", defvalue: "0.05")]
36  private float m_fPreviewRotationInertia;
37 
38  [Attribute(category: "Preview", defvalue: "1 1 1 0.2", desc: "Color of height indicator helper object.")]
39  protected ref Color m_HeightIndicatorColor;
40 
41  [Attribute(category: "Settings", defvalue: EEditorTransformVertical.GEOMETRY.ToString(), uiwidget: UIWidgets.ComboBox, enums: ParamEnumArray.FromEnum(EEditorTransformVertical))]
42  private EEditorTransformVertical m_VerticalMode;
43 
44  [Attribute(category: "Settings", defvalue: SCR_Enum.GetFlagValues(EEditorTransformVertical).ToString(), uiwidget: UIWidgets.Flags, enums: ParamEnumArray.FromEnum(EEditorTransformVertical))]
45  private EEditorTransformVertical m_AllowedVerticalModes;
46 
47  [Attribute(category: "Settings", defvalue: "1")]
48  private bool m_bIsVerticalSnap;
49 
50  [Attribute(category: "Settings", defvalue: "0.25")]
51  private float m_fVerticalSnapLimit;
52 
53  [Attribute(category: "Settings", desc: "When true, interaction between entities passes when at least one edited entity meets the criteria.\nWhen false, all edited entities must be compatible.")]
54  private bool m_bORInteraction;
55 
56  [Attribute(category: "Settings", defvalue: "EditorPreviewContext", desc: "Action context activated all the time.")]
57  protected string m_sActionContext;
58 
59  private vector m_vTransform[4] = {vector.Right, vector.Up, vector.Forward, vector.Zero};
60  //private vector m_vTransformBackup[4];
61  private EEditorTransformVertical m_VerticalModeReal;
62  private SCR_EPreviewState m_LastPreviewState = SCR_EPreviewState.NONE;
63  private float m_fHeightTerrain;
64  private float m_fHeightSea;
65  private bool m_bIsHeightSet;
66  private bool m_bIsChange;
67  private BaseWorld m_World;
68  private bool m_bHasTerrain;
69  private SCR_EditableEntityComponent m_Target;
70  private bool m_bTargetSnap;
71  private bool m_bTargetDelegate;
72  private EEditableEntityInteraction m_TargetInteraction;
73  private float m_fTargetRotationStep;
74  private bool m_bInstantTransformation;
75  private bool m_bIsFixedPosition;
76  private bool m_bIsRotating;
77  private bool m_bIsMovingVertically;
78  private bool m_bHasSpecialInteraction;
79  private bool m_bIsUnderwater;
80  private int m_iHeightIndicatorColor;
81  private bool m_bPreviewDisabled;
82  protected bool m_bCanMoveInRoot;
83 
84  protected SCR_LayersEditorComponent m_LayerManager;
85  protected SCR_StatesEditorComponent m_StateManager;
86  protected SCR_EditablePreviewEntity m_PreviewEntity;
87  private ResourceName m_SlotPrefab;
88  private vector m_aLocalOffset[4];
89  private SCR_EditableEntityComponent m_Entity;
90  private EEditableEntityType m_EntityType;
91  protected ref SCR_EditableEntityInteraction m_Interaction;
92 
93  // OnPreviewCreate(SCR_BasePreviewEntity previewEntity)
94  private ref ScriptInvoker Event_OnPreviewCreate = new ScriptInvoker;
95  // OnPreviewDelete(SCR_BasePreviewEntity previewEntity)
96  private ref ScriptInvoker Event_OnPreviewDelete = new ScriptInvoker;
97  // OnPreviewChange(vector transform[4], bool isChange)
98  private ref ScriptInvoker Event_OnPreviewChange = new ScriptInvoker;
99  // OnTargetChange(SCR_EditableEntityComponent target)
100  private ref ScriptInvoker Event_OnTargetChange = new ScriptInvoker;
101  // OnWaitingPreviewCreate(SCR_BasePreviewEntity previewEntity)
102  private ref ScriptInvoker Event_OnWaitingPreviewCreate = new ScriptInvoker;
103  // OnVerticalModeChange(EEditorTransformVertical verticalMode)
104  private ref ScriptInvoker Event_OnVerticalModeChange = new ScriptInvoker;
105  // OnVerticalModeChange(EEditorTransformSnap verticalSnap)
106  private ref ScriptInvoker Event_OnVerticalSnapChange = new ScriptInvoker;
107 
108  protected const float VERTICAL_TRACE_OFFSET = 0.01; //--- Vertical offset of trace start to make sure it does not start inside geometry.
109 
115  void SetPreviewTransform(vector transform[4], float timeSlice = 1, bool instant = false, EEditorTransformVertical verticalMode = EEditorTransformVertical.TERRAIN)
116  {
117  if (!m_PreviewEntity || m_bIsFixedPosition)
118  return;
119 
120  //--- When on non-snappable entity, hide the preview, as the interaction may not place the entity where the preview is (e.g., moving a character into vehicle)
121  if (m_Target && !m_bTargetSnap)
122  {
123  ResetPreviewTransform();
124  return;
125  }
126 
127  instant = true;
128 
129  vector cameraTransform[4];
130  m_World.GetCurrentCamera(cameraTransform);
131  vector cameraPos = cameraTransform[3];
132  m_bIsUnderwater = cameraPos[1] < m_World.GetOceanBaseHeight();
133 
134  if (m_Target && m_bTargetSnap)
135  {
136  //--- Attached to a target, override input transformation
137  vector targetTransform[4];
138  if (m_Target.GetTransform(targetTransform))
139  {
140  switch (true)
141  {
142  //--- Disabled rotation
143  case (m_fTargetRotationStep == -1):
144  {
145  transform = targetTransform;
146  break;
147  }
148  //--- Stepped rotation
149  case (m_fTargetRotationStep != 0):
150  {
151  vector targetAngles = Math3D.MatrixToAngles(targetTransform);
152  vector angles = Math3D.MatrixToAngles(transform);
153  angles[0] = targetAngles[0] + Math.Round((angles[0] - targetAngles[0]) / m_fTargetRotationStep) * m_fTargetRotationStep;
154  if (!m_bInstantTransformation && !instant) LerpAngles(m_PreviewEntity.GetAngles(), angles, timeSlice);
155  Math3D.AnglesToMatrix(angles, transform);
156  break;
157  }
158  //--- Free rotation (do not modify incoming dir)
159  default:
160  {
161  if (!m_bInstantTransformation)
162  {
163  vector angles = Math3D.MatrixToAngles(transform);
164  if (!m_bInstantTransformation && !instant) LerpAngles(m_PreviewEntity.GetAngles(), angles, timeSlice);
165  Math3D.AnglesToMatrix(angles, transform);
166  }
167  }
168  }
169  transform[3] = targetTransform[3];
170  if (!m_bInstantTransformation && !instant) transform[3] = LerpTranslation(m_PreviewEntity.GetOrigin(), transform[3], timeSlice);
171 
172  Math3D.MatrixMultiply4(transform, m_aLocalOffset, transform); //--- Counter local offset to make sure that preview's center is snapped to slot
173  m_PreviewEntity.SetPreviewTransform(transform, verticalMode, m_fHeightTerrain, m_bIsUnderwater);
174  }
175  }
176  else
177  {
178  //--- Free transformation
179  if (!m_bInstantTransformation && !instant)
180  {
181  vector transformCurrent[4];
182  m_PreviewEntity.GetWorldTransform(transformCurrent);
183 
184  float quat[4], quatCurrent[4];
185  Math3D.MatrixToQuat(transform, quat);
186  Math3D.MatrixToQuat(transformCurrent, quatCurrent);
187  Math3D.QuatLerp(quatCurrent, quat, quat, timeSlice);
188  Math3D.QuatToMatrix(quat, transform);
189 
190  transform[3] = LerpTranslation(m_PreviewEntity.GetOrigin(), transform[3], timeSlice);
191  }
192 
193  TraceParam trace;
194  if (verticalMode == EEditorTransformVertical.GEOMETRY)
195  {
196  trace = new TraceParam();
197  trace.ExcludeArray = m_PreviewEntity.GetExcludeArray();
198 
199  //--- When the preview represents a composition, trace surface from camera height, not cursor intersection height, as child entities could be below it.
200  if (m_PreviewEntity.HasMultipleEditableEntities())
201  {
202  vector matrix[4];
203  m_PreviewEntity.GetWorld().GetCurrentCamera(matrix);
204  trace.Start = matrix[3];
205  }
206  }
207 
208  m_PreviewEntity.SetPreviewTransform(transform, verticalMode, m_fHeightTerrain, m_bIsUnderwater, trace);
209  }
210 
211  if (!m_bIsChange)
212  {
213  m_PreviewEntity.SetFlags(EntityFlags.VISIBLE, true);
214  }
215 
216  m_bIsChange = true;
217  m_bInstantTransformation = false;
218  m_VerticalModeReal = verticalMode;
219  Event_OnPreviewChange.Invoke(transform, true);
220 
221  //--- Height not defined yet, set it now
222  if (!m_bIsHeightSet) SetPreviewHeight(transform[3]);
223 
224  //--- Placeholder vertical indicator. ToDo: Replace
225  float indicatorHeight = m_fHeightTerrain - m_aLocalOffset[3][1];
226  if (indicatorHeight > 0.025)
227  {
228  vector indicatorPos = transform[3] - Vector(0, indicatorHeight * 0.5 + m_aLocalOffset[3][1], 0);
229  Shape.CreateCylinder(m_iHeightIndicatorColor, ShapeFlags.TRANSP | ShapeFlags.ONCE | ShapeFlags.NOOUTLINE, indicatorPos, 0.05, indicatorHeight);
230  Shape.CreateCylinder(m_iHeightIndicatorColor, ShapeFlags.TRANSP | ShapeFlags.ONCE | ShapeFlags.NOOUTLINE | ShapeFlags.NOZBUFFER, indicatorPos, 0.01, indicatorHeight);
231  }
232  }
236  void ResetPreviewTransform()
237  {
238  if (!m_PreviewEntity || !m_bIsChange)
239  return;
240 
241  bool isChange = m_bIsChange;
242  m_bIsChange = false;
243  if (isChange)
244  {
245  //--- Hide the preview
246  m_PreviewEntity.ClearFlags(EntityFlags.VISIBLE, true);
247 
248  vector transform[4];
249  m_PreviewEntity.GetWorldTransform(transform);
250  Event_OnPreviewChange.Invoke(transform, m_bIsChange);
251  }
252  }
257  bool GetPreviewTransform(out vector transform[4])
258  {
259  if (!m_PreviewEntity)
260  return false;
261 
262  m_PreviewEntity.GetWorldTransform(transform);
263  return true;
264  }
269  bool GetPreviewTransformOrigin(out vector transform[4])
270  {
271  if (!m_PreviewEntity) return false;
272  Math3D.MatrixCopy(m_vTransform, transform);
273  return true;
274  }
280  void SetPreviewHeight(vector pos)
281  {
282  if (!m_PreviewEntity || !m_World) return;
283  m_fHeightSea = pos[1];
284 
285  TraceParam trace;
286  if (m_VerticalModeReal == EEditorTransformVertical.GEOMETRY)
287  {
288  //--- When snapping to ground, offset a bit up so prevent the trace from starting below surface
289  pos[1] = pos[1] + VERTICAL_TRACE_OFFSET;
290 
291  trace = new TraceParam();
292  trace.ExcludeArray = m_PreviewEntity.GetExcludeArray();
293  }
294 
295  if (m_bHasTerrain)
296  m_fHeightTerrain = pos[1] - SCR_TerrainHelper.GetTerrainY(pos, m_World, !m_bIsUnderwater, trace);
297  else
298  m_fHeightTerrain = m_fHeightSea;
299 
300  m_bIsHeightSet = true;
301  }
305  void ResetPreviewHeight()
306  {
307  m_fHeightSea = 0;
308  m_fHeightTerrain = 0;
309  }
314  float GetPreviewHeightAboveTerrain()
315  {
316  return m_fHeightTerrain;
317  }
322  float GetPreviewHeightAboveSea()
323  {
324  return m_fHeightSea;
325  }
329  vector GetLocalOffset()
330  {
331  return m_aLocalOffset[3];
332  }
337  void SetVerticalMode(EEditorTransformVertical mode)
338  {
339  if (mode == m_VerticalMode || !SCR_Enum.HasFlag(m_AllowedVerticalModes, mode))
340  return;
341 
342  m_VerticalMode = mode;
343  DiagMenu.SetValue(SCR_DebugMenuID.DEBUGUI_EDITOR_TRANSFORM_VERTICAL_MODE, m_VerticalMode >> 1);
344  Event_OnVerticalModeChange.Invoke(m_VerticalMode);
345  }
350  EEditorTransformVertical GetVerticalMode()
351  {
352  return m_VerticalMode;
353  }
359  EEditorTransformVertical GetVerticalModeReal()
360  {
361  return m_VerticalModeReal;
362  }
367  void SetVerticalSnap(bool enabled)
368  {
369  if (enabled == m_bIsVerticalSnap)
370  return;
371 
372  m_bIsVerticalSnap = enabled;
373  DiagMenu.SetValue(SCR_DebugMenuID.DEBUGUI_EDITOR_TRANSFORM_VERTICAL_SNAP, m_bIsVerticalSnap);
374  Event_OnVerticalSnapChange.Invoke(m_bIsVerticalSnap);
375  }
380  bool IsVerticalSnap()
381  {
382  return m_bIsVerticalSnap;
383  }
389  vector SnapVertically(vector pos)
390  {
391  float baseSnapHeight = GetSnapBaseHeight(pos, GetVerticalMode());
392  float delta = pos[1] - baseSnapHeight;
393  if (delta < m_fVerticalSnapLimit)
394  pos[1] = baseSnapHeight;
395 
396  return pos;
397  }
402  bool IsSnappedVertically()
403  {
404  if (!m_PreviewEntity)
405  return false;
406 
407  vector pos = m_PreviewEntity.GetTransformAxis(3);
408  float baseSnapHeight = GetSnapBaseHeight(pos, GetVerticalMode());
409  float delta = pos[1] - baseSnapHeight;
410  return Math.AbsFloat(delta) < m_fVerticalSnapLimit;
411  }
417  bool CanUnsnap(float verticalDelta)
418  {
419  if (!IsSnappedVertically())
420  return false;
421 
422  if (m_VerticalMode == EEditorTransformVertical.TERRAIN)
423  {
424  return verticalDelta > 0; //--- Cannot go below terrain
425  }
426  return false;
427  }
428  protected float GetSnapBaseHeight(vector pos, EEditorTransformVertical verticalMode)
429  {
430  switch (verticalMode)
431  {
432  case EEditorTransformVertical.GEOMETRY:
433  case EEditorTransformVertical.TERRAIN:
434  {
435  TraceParam trace;
436  if (verticalMode == EEditorTransformVertical.GEOMETRY)
437  {
438  trace = new TraceParam();
439  trace.ExcludeArray = m_PreviewEntity.GetExcludeArray();
440  }
441  return SCR_TerrainHelper.GetTerrainY(pos, m_World, !m_bIsUnderwater, trace) + m_aLocalOffset[3][1] + VERTICAL_TRACE_OFFSET; //--- Offset a bit to make sure the position is not under surface
442  }
443  }
444  return m_aLocalOffset[3][1];
445  }
449  bool CanMoveInRoot()
450  {
451  return m_bCanMoveInRoot;
452  }
457  void ShowAsDisabled(bool disable = true)
458  {
459  if (disable == m_bPreviewDisabled)
460  return;
461 
462  m_bPreviewDisabled = disable;
463 
464  ResourceName material = m_PreviewMaterial;
465  if (disable)
466  material = m_DisabledPreviewMaterial;
467 
468  SCR_Global.SetMaterial(m_PreviewEntity, material);
469  }
470 
475  void SetPreviewState(SCR_EPreviewState state)
476  {
477  if (m_LastPreviewState == state)
478  return;
479 
480  ResourceName material;
481  switch (state)
482  {
483  case SCR_EPreviewState.PLACEABLE:
484  {
485  material = m_PreviewMaterial;
486  m_LastPreviewState = SCR_EPreviewState.PLACEABLE;
487  break;
488  }
489  case SCR_EPreviewState.BLOCKED:
490  {
491  material = m_DisabledPreviewMaterial;
492  m_LastPreviewState = SCR_EPreviewState.BLOCKED;
493  break;
494  }
495  case SCR_EPreviewState.WARNING:
496  {
497  material = m_WarningPreviewMaterial;
498  m_LastPreviewState = SCR_EPreviewState.WARNING;
499  break;
500  }
501  }
502 
503  SCR_Global.SetMaterial(m_PreviewEntity, material);
504  }
505 
510  void SetLastPreviewState(SCR_EPreviewState state)
511  {
512  m_LastPreviewState = state;
513  }
514 
520  bool SetTarget(SCR_EditableEntityComponent target, bool isDelegate = false)
521  {
522  if (!m_PreviewEntity)
523  return false;
524 
525  if (target)
526  {
527  if (target == m_Target && isDelegate == m_bTargetDelegate)
528  return false;
529 
530  //--- Check if the preview can interact with the target
531  bool targetSnap;
532  EEditableEntityInteraction targetInteraction;
533  if (!CanInteractWith(target, targetSnap, targetInteraction, isDelegate))
534  {
535  if (m_Target) SetTarget(null);
536  return true;
537  }
538 
539  m_Target = target;
540  m_bTargetSnap = targetSnap;
541  m_TargetInteraction = targetInteraction;
542  m_bTargetDelegate = isDelegate;
543 
544  if (m_bTargetSnap)
545  {
546  SCR_SiteSlotEntity slotEntity = SCR_SiteSlotEntity.Cast(target.GetOwner());
547  if (slotEntity)
548  m_fTargetRotationStep = slotEntity.GetRotationStep();
549  else
550  m_fTargetRotationStep = -1;
551  }
552  }
553  else
554  {
555  //--- Remove
556  if (!m_Target) return false;
557 
558  m_Target = null;
559  m_TargetInteraction = 0;
560  }
561  Event_OnTargetChange.Invoke(target);
562  return true;
563  }
564  protected bool CanInteractWith(SCR_EditableEntityComponent target, out bool snap, out EEditableEntityInteraction interaction, bool isDelegate)
565  {
566  //--- Cannot interact with itself
567  if (target == m_Entity)
568  return false;
569 
570  //--- Snap to compatible slot
571  if (target.HasEntityState(EEditableEntityState.COMPATIBLE_SLOT))
572  {
573  interaction = EEditableEntityInteraction.SLOT;
574  snap = true;
575  return true;
576  }
577 
578  bool isTargetDestroyed = target.IsDestroyed();
579 
580  EEditableEntityInteractionFlag defaultInteractionFlags;
581  if (m_LayerManager && m_LayerManager.IsEditingLayersEnabled())
582  defaultInteractionFlags |= EEditableEntityInteractionFlag.LAYER_EDITING;
583 
584  //--- Check interaction of all edited entities
586  //SCR_EditablePreviewEntity editableChild;
587  SCR_EditableEntityComponent editableChild;
588  if (core)
589  {
590  if (m_bORInteraction)
591  {
592  //--- At least one entity must be compatible
593  foreach (SCR_BasePreviewEntity child: m_PreviewEntity.GetPreviewChildren())
594  {
595  if (!m_Interaction)
596  continue;
597 
598  EEditableEntityInteractionFlag interactionFlags = defaultInteractionFlags;
599 
600  editableChild = SCR_EditableEntityComponent.GetEditableEntity(child.GetSourceEntity());
601  if (!isTargetDestroyed && (!editableChild || !editableChild.IsDestroyed()))
602  interactionFlags |= EEditableEntityInteractionFlag.ALIVE;
603 
604  if (isDelegate)
605  interactionFlags |= EEditableEntityInteractionFlag.DELEGATE;
606 
607  if (!editableChild || editableChild.GetPlayerID() == 0)
608  interactionFlags |= EEditableEntityInteractionFlag.NON_PLAYABLE;
609 
610  if (m_StateManager && m_StateManager.GetState() == EEditorState.PLACING)
611  interactionFlags |= EEditableEntityInteractionFlag.PLACING;
612 
613  if (m_Interaction.CanSetParent(target, interactionFlags))
614  {
615  interaction = EEditableEntityInteraction.LAYER;
616  return true;
617  }
618  }
619  }
620  else
621  {
622  //--- All entities must be compatible
623  foreach (SCR_BasePreviewEntity child: m_PreviewEntity.GetPreviewChildren())
624  {
625  if (!m_Interaction)
626  return false;
627 
628  EEditableEntityInteractionFlag interactionFlags = defaultInteractionFlags;
629 
630  editableChild = SCR_EditableEntityComponent.GetEditableEntity(child.GetSourceEntity());
631  if (!isTargetDestroyed && (!editableChild || !editableChild.IsDestroyed()))
632  interactionFlags |= EEditableEntityInteractionFlag.ALIVE;
633 
634  if (isDelegate)
635  interactionFlags |= EEditableEntityInteractionFlag.DELEGATE;
636 
637  if (!editableChild || editableChild.GetPlayerID() == 0)
638  interactionFlags |= EEditableEntityInteractionFlag.NON_PLAYABLE;
639 
640  if (m_StateManager && m_StateManager.GetState() == EEditorState.PLACING)
641  interactionFlags |= EEditableEntityInteractionFlag.PLACING;
642 
643  if (!m_Interaction.CanSetParent(target, interactionFlags))
644  return false;
645  }
646  interaction = EEditableEntityInteraction.LAYER;
647  return true;
648  }
649  }
650  return false;
651  }
652 
657  SCR_EditableEntityComponent GetTarget()
658  {
659  return m_Target;
660  }
665  EEditableEntityInteraction GetTargetInteraction()
666  {
667  return m_TargetInteraction;
668  }
673  bool IsSnappedToTarget()
674  {
675  return m_bTargetSnap;
676  }
681  SCR_EditablePreviewEntity GetPreviewEntity()
682  {
683  return m_PreviewEntity;
684  }
689  string GetActionContext()
690  {
691  return m_sActionContext;
692  }
697  bool IsEditing()
698  {
699  return m_PreviewEntity != null;
700  }
705  bool IsChange()
706  {
707  return m_bIsChange || m_bIsFixedPosition || m_Target;
708  }
713  bool IsRotating()
714  {
715  return m_bIsRotating;
716  }
721  bool IsFixedPosition()
722  {
723  return m_bIsFixedPosition;
724  }
729  ResourceName GetSlotPrefab()
730  {
731  return m_SlotPrefab;
732  }
737  void SetIsMovingVertically(bool isMovingVertically)
738  {
739  m_bIsMovingVertically = isMovingVertically;
740  }
745  bool IsMovingVertically()
746  {
747  return m_bIsMovingVertically;
748  }
753  void SetIsRotating(bool isRotating)
754  {
755  m_bIsRotating = isRotating;
756  }
761  bool IsUnderwater()
762  {
763  return m_bIsUnderwater;
764  }
770  array<IEntity> GetExcludeArray()
771  {
772  if (m_PreviewEntity)
773  return m_PreviewEntity.GetExcludeArray();
774  else
775  return null;
776  }
781  ScriptInvoker GetOnPreviewCreate()
782  {
783  return Event_OnPreviewCreate;
784  }
789  ScriptInvoker GetOnPreviewDelete()
790  {
791  return Event_OnPreviewDelete;
792  }
797  ScriptInvoker GetOnPreviewChange()
798  {
799  return Event_OnPreviewChange;
800  }
805  ScriptInvoker GetOnTargetChange()
806  {
807  return Event_OnTargetChange;
808  }
813  ScriptInvoker GetOnWaitingPreviewCreate()
814  {
815  return Event_OnWaitingPreviewCreate;
816  }
821  ScriptInvoker GetOnVerticalModeChange()
822  {
823  return Event_OnVerticalModeChange;
824  }
829  ScriptInvoker GetOnVerticalSnapChange()
830  {
831  return Event_OnVerticalSnapChange;
832  }
833 
834  void InitTransform(vector transform[4])
835  {
836  m_vTransform = transform;
837 
838  //--- Normalize transformation matrix, so it does not affect scale even when pivot entity is scaled up or down
839  Math3D.MatrixNormalize(m_vTransform);
840 
841  SetPreviewHeight(transform[3]);
842  }
843 
850  SCR_BasePreviewEntity CreatePreview(SCR_EditableEntityComponent pivot, set<SCR_EditableEntityComponent> entities)
851  {
852  DeletePreview();
853 
854  EPreviewEntityFlag flags;
855  if (m_bIsUnderwater)
856  flags |= EPreviewEntityFlag.UNDERWATER;
857 
858  if (m_VerticalMode == EEditorTransformVertical.GEOMETRY)
859  flags |= EPreviewEntityFlag.GEOMETRY;
860 
861  EntitySpawnParams spawnParams = new EntitySpawnParams();
862  Math3D.MatrixCopy(m_vTransform, spawnParams.Transform);
863  m_PreviewEntity = SCR_EditablePreviewEntity.Cast(SCR_EditablePreviewEntity.SpawnPreviewFromEditableEntities(entities, m_PreviewEntityPrefab, GetOwner().GetWorld(), spawnParams, m_PreviewMaterial, flags));
864  m_bInstantTransformation = true;
865  m_Entity = pivot;
866  m_EntityType = pivot.GetEntityType();
867  m_Interaction = pivot.GetEntityInteraction();
868  m_bCanMoveInRoot = !m_Interaction || m_Interaction.CanSetParent(SCR_EditableEntityInteraction.ROOT, 0);
869 
870  SCR_EditableEntityUIInfo info = SCR_EditableEntityUIInfo.Cast(pivot.GetInfo());
871  if (info)
872  m_SlotPrefab = info.GetSlotPrefab();
873  else
874  m_SlotPrefab = ResourceName.Empty;
875 
876  //--- Get local offset for slotting
877  vector localOffsetPos = m_aLocalOffset[3];
878  if (pivot.GetPos(localOffsetPos))
879  {
880  vector pivotTransform[4];
881  pivot.GetOwner().GetWorldTransform(pivotTransform);
882  Math3D.MatrixInvMultiply4(m_vTransform, pivotTransform, pivotTransform);
883  m_aLocalOffset[3] = -pivotTransform[3];// pivot.GetOwner().CoordToLocal(m_vTransform[3]); //--- Cannot use CoordToLocal, doesn't take m_vTransform rotation into effect
884  }
885 
886  Event_OnPreviewCreate.Invoke(m_PreviewEntity);
887 
888  //--- Reset position. Without it, moving entity vertically on client (where there's a delay) would cause vertical offset
889  SetPreviewHeight(m_vTransform[3]);
890  ResetPreviewTransform();
891 
892  return m_PreviewEntity;
893  }
901  SCR_BasePreviewEntity CreatePreview(ResourceName prefab, notnull array<vector> offsets, vector initTransform[4] = {})
902  {
903  DeletePreview();
904 
905  if (prefab)
906  {
907  Resource prefabResource = Resource.Load(prefab);
908  EntitySpawnParams spawnParams = new EntitySpawnParams();;
909 
910  IEntitySource entitySource = SCR_BaseContainerTools.FindEntitySource(prefabResource);
911  IEntityComponentSource entityComponent = SCR_BaseContainerTools.FindComponentSource(entitySource, SCR_EditableEntityComponent);
912  m_EntityType = SCR_EditableEntityComponentClass.GetEntityType(entityComponent);
913  m_Interaction = SCR_EditableEntityComponentClass.GetEntityInteraction(entityComponent);
914  m_SlotPrefab = SCR_EditableEntityComponentClass.GetSlotPrefab(entityComponent);
915  m_bIsFixedPosition = SCR_EditableEntityComponentClass.HasFlag(entityComponent, EEditableEntityFlag.STATIC_POSITION);
916  m_bCanMoveInRoot = !m_Interaction || m_Interaction.CanSetParent(SCR_EditableEntityInteraction.ROOT, 0);
917 
918  if (m_bIsFixedPosition)
919  {
920  //--- Get coordinates of the prefab itself when it's intended only for one position
921  vector coords;
922  entitySource.Get("coords", coords);
923  if (coords.LengthSq() != 0)
924  {
925  spawnParams.Transform[3] = coords;
926  }
927  else
928  {
929  Print(string.Format("Prefab '%1' is flagged as STATIC_POSITION, but its position is <0,0,0>!", prefab.GetPath()), LogLevel.WARNING);
930  m_bIsFixedPosition = false;
931  }
932  }
933  else if (initTransform[3] == vector.Zero)
934  {
935  //--- Restore previous yaw (don't apply full rotation, would cause problems on uneven terrain; ToDo: Use rotation relativer to terrain?)
936  vector angles = Vector(Math3D.MatrixToAngles(m_vTransform)[0], 0, 0);
937  Math3D.AnglesToMatrix(angles, m_vTransform);
938  m_vTransform[3] = vector.Zero; //--- Reset position to prevent waypoint appearing in the air
939  spawnParams.Transform = m_vTransform;
940  }
941  else
942  {
943  spawnParams.Transform = initTransform;
944  }
945 
946  if (offsets.Count() > 1)
947  {
948  //--- Create as many previews as there are selected entities (e.g., for waypoins or tasks)
949  array<ref SCR_BasePreviewEntry> entries = SCR_PrefabPreviewEntity.GetPreviewEntriesFromPrefab(prefabResource);
950  SCR_BasePreviewEntry sourceEntry = entries[0];
951  SCR_BasePreviewEntry entry;
952  for (int i = 0, count = offsets.Count(); i < count; i++)
953  {
954  if (i == 0)
955  {
956  entry = entries[i];
957  }
958  else
959  {
960  entry = new SCR_BasePreviewEntry();
961  entry.CopyFrom(sourceEntry);
962  entries.Insert(entry);
963  }
964  entry.m_vPosition = offsets[i];
965  }
966  m_PreviewEntity = SCR_EditablePreviewEntity.Cast(SCR_PrefabPreviewEntity.SpawnPreview(entries, m_PreviewEntityPrefab, spawnParams: spawnParams, material: m_PreviewMaterial));
967  }
968  else
969  {
970  //--- Create preview directly
971  m_PreviewEntity = SCR_EditablePreviewEntity.Cast(SCR_PrefabPreviewEntity.SpawnPreviewFromPrefab(prefabResource, m_PreviewEntityPrefab, spawnParams: spawnParams, material: m_PreviewMaterial));
972  }
973  if (m_PreviewEntity)
974  {
975  m_fHeightTerrain = 0;
976  Event_OnPreviewCreate.Invoke(m_PreviewEntity);
977  }
978  }
979  return m_PreviewEntity;
980  }
984  void DeletePreview()
985  {
986  if (m_PreviewEntity)
987  {
988  SCR_BasePreviewEntity previewEntity = m_PreviewEntity;
989  m_PreviewEntity = null;
990 
991  previewEntity.GetWorldTransform(m_vTransform);
992  if (m_Target)
993  Event_OnTargetChange.Invoke(null);
994 
995  Event_OnPreviewDelete.Invoke(previewEntity);
996  delete previewEntity;
997  }
998  m_bIsChange = false;
999  m_bIsHeightSet = false;
1000  m_bIsFixedPosition = false;
1001  m_bIsRotating = false;
1002  m_bPreviewDisabled = false;
1003  m_Target = null;
1004  m_TargetInteraction = 0;
1005  m_Entity = null;
1006  m_aLocalOffset[3] = vector.Zero;
1007  }
1011  SCR_BasePreviewEntity CreateWaitingPreview()
1012  {
1013  if (!m_PreviewEntity)
1014  return null;
1015 
1016  Resource previewResource = Resource.Load(m_WaitingEntityPrefab);
1017  if (!previewResource || !previewResource.IsValid())
1018  return null;
1019 
1020  EntitySpawnParams spawnParams = new EntitySpawnParams();
1021  m_PreviewEntity.GetWorldTransform(spawnParams.Transform);
1022  SCR_BasePreviewEntity previewEntity = SCR_EditablePreviewEntity.SpawnPreviewFromEditableOwner(m_PreviewEntity, m_WaitingEntityPrefab, m_PreviewEntity.GetWorld(), spawnParams, m_WaitingPreviewMaterial);
1023  Event_OnWaitingPreviewCreate.Invoke(previewEntity);
1024  return previewEntity;
1025  }
1026 
1027  protected vector LerpTranslation(vector currentPos, vector targetPos, float timeSlice)
1028  {
1029  return vector.Lerp(currentPos, targetPos, Math.Min(timeSlice * m_fPreviewTranslationInertia, 1));
1030  }
1031  protected void LerpAngles(vector currentAngles, out vector targetAngles, float timeSlice)
1032  {
1033  //--- currentAngles vector has different order than targetAngles vector, because it's filled by GetAngles()
1034  targetAngles[0] = SCR_Math.LerpAngle(currentAngles[1], targetAngles[0], Math.Min(timeSlice * m_fPreviewRotationInertia, 1));
1035  }
1036 
1037  protected void OnUserSettingsChanged()
1038  {
1039  BaseContainer editorSettings = GetGame().GetGameUserSettings().GetModule("SCR_EditorSettings");
1040  if (!editorSettings)
1041  return;
1042 
1043  int value;
1044  editorSettings.Get("m_PreviewVerticalSnap", value);
1045  SetVerticalSnap(value);
1046  editorSettings.Get("m_PreviewVerticleMode", value);
1047  SetVerticalMode(value);
1048  }
1049 
1050 
1051  override void EOnEditorDebug(array<string> debugTexts)
1052  {
1053  debugTexts.Insert("Vertical Mode: " + Type().EnumToString(EEditorTransformVertical, m_VerticalMode));
1054  debugTexts.Insert("Vertical Mode (Real): " + Type().EnumToString(EEditorTransformVertical, m_VerticalModeReal));
1055  debugTexts.Insert("Vertical Snap: " + m_bIsVerticalSnap);
1056  debugTexts.Insert("Height ASL: " + m_fHeightSea);
1057  debugTexts.Insert("Height ATL: " + m_fHeightTerrain);
1058 
1059  if (m_PreviewEntity)
1060  {
1061  debugTexts.Insert(string.Format("Preview Target: %1", m_Target));
1062  debugTexts.Insert(string.Format("Preview Target Interaction: %1", typename.EnumToString(EEditableEntityInteraction, m_TargetInteraction)));
1063  }
1064  }
1065  override void EOnFrame(IEntity owner, float timeSlice)
1066  {
1067 #ifdef ENABLE_DIAG
1068  int verticalMode = 1 << DiagMenu.GetValue(SCR_DebugMenuID.DEBUGUI_EDITOR_TRANSFORM_VERTICAL_MODE);
1069  if (verticalMode != m_VerticalMode)
1070  {
1071  SetVerticalMode(verticalMode);
1072  }
1073  if (DiagMenu.GetValue(SCR_DebugMenuID.DEBUGUI_EDITOR_TRANSFORM_VERTICAL_SNAP) != m_bIsVerticalSnap)
1074  {
1075  SetVerticalSnap(DiagMenu.GetValue(SCR_DebugMenuID.DEBUGUI_EDITOR_TRANSFORM_VERTICAL_SNAP));
1076  }
1077 #endif
1078  }
1079  override void EOnEditorActivate()
1080  {
1081  SetEventMask(GetOwner(), EntityEvent.FRAME);
1082 
1083  ArmaReforgerScripted game = GetGame();
1084  if (!game) return;
1085 
1086  m_World = game.GetWorld();
1089 
1090 #ifdef ENABLE_DIAG
1091  typename enumVerticalMode = EEditorTransformVertical;
1092  DiagMenu.RegisterRange(SCR_DebugMenuID.DEBUGUI_EDITOR_TRANSFORM_VERTICAL_MODE, "", "Vertical Mode", "Transforming", string.Format("0 %1 0 1", enumVerticalMode.GetVariableCount() - 1));
1093  DiagMenu.SetValue(SCR_DebugMenuID.DEBUGUI_EDITOR_TRANSFORM_VERTICAL_MODE, m_VerticalMode >> 1);
1094 
1095  DiagMenu.RegisterBool(SCR_DebugMenuID.DEBUGUI_EDITOR_TRANSFORM_VERTICAL_SNAP, "", "Vertical Snap", "Transforming");
1096  DiagMenu.SetValue(SCR_DebugMenuID.DEBUGUI_EDITOR_TRANSFORM_VERTICAL_SNAP, m_bIsVerticalSnap);
1097 #endif
1098  }
1099  override void EOnEditorDeactivate()
1100  {
1101  DeletePreview();
1102  }
1103  override void EOnEditorInit()
1104  {
1105  ArmaReforgerScripted game = GetGame();
1106  if (!game)
1107  return;
1108 
1109  GenericWorldEntity worldEntity = game.GetWorldEntity();
1110  if (!worldEntity)
1111  return;
1112 
1113  m_bHasTerrain = worldEntity.GetTerrain(0, 0) != null;
1114 
1115  m_fPreviewTranslationInertia = 1 / Math.Max(m_fPreviewTranslationInertia, 0.001);
1116  m_fPreviewRotationInertia = 1 / Math.Max(m_fPreviewRotationInertia, 0.001);
1117 
1118  BaseContainer editorSettings = GetGame().GetGameUserSettings().GetModule("SCR_EditorSettings");
1119  if (editorSettings)
1120  {
1121  //Init values from options
1122  OnUserSettingsChanged();
1123  GetGame().OnUserSettingsChangedInvoker().Insert(OnUserSettingsChanged);
1124  }
1125 
1126  m_iHeightIndicatorColor = m_HeightIndicatorColor.PackToInt();
1127 
1128  Math3D.MatrixIdentity3(m_aLocalOffset); //--- Initialize offset matrix angles
1129  }
1130 
1131  override void OnDelete(IEntity owner)
1132  {
1133  if (GetGame())
1134  GetGame().OnUserSettingsChangedInvoker().Remove(OnUserSettingsChanged);
1135  }
1136 };
1137 
1139 {
1144 };
SCR_TerrainHelper
Definition: SCR_TerrainHelper.c:1
ComponentEditorProps
SCR_FragmentEntityClass ComponentEditorProps
EEditableEntityState
EEditableEntityState
Definition: EEditableEntityState.c:37
EEditableEntityInteraction
EEditableEntityInteraction
Type of suggested interaction when hovering edited entity on top of another entity.
Definition: EEditableEntityInteraction.c:5
EEditableEntityFlag
EEditableEntityFlag
Unique flags of the entity.
Definition: EEditableEntityFlag.c:5
SCR_EditableEntityCore
Definition: SCR_EditableEntityCore.c:10
SCR_Enum
Definition: SCR_Enum.c:1
SCR_BasePreviewEntry
Definition: SCR_BasePreviewEntry.c:2
SCR_EditablePreviewEntity
Definition: SCR_EditablePreviewEntity.c:8
EEditorState
EEditorState
Unique editor state.
Definition: EEditorState.c:5
GetGame
ArmaReforgerScripted GetGame()
Definition: game.c:1424
m_Target
class SCR_AIPolar m_Target
SCR_EditableEntityUIInfo
Definition: SCR_EditableEntityUIInfo.c:2
BLOCKED
@ BLOCKED
Placing of the preview is blocked.
Definition: SCR_PreviewEntityEditorComponent.c:1142
SCR_BasePreviewEntity
Definition: SCR_BasePreviewEntity.c:9
desc
UI Textures DeployMenu Briefing conflict_HintBanner_1_UI desc
Definition: SCR_RespawnBriefingComponent.c:17
m_Entity
enum EAITargetInfoCategory m_Entity
SCR_EPreviewState
SCR_EPreviewState
Definition: SCR_PreviewEntityEditorComponent.c:1138
m_PreviewEntity
protected IEntity m_PreviewEntity
Definition: SCR_ItemPlacementComponent.c:23
SCR_Math
Definition: SCR_Math.c:1
PLACEABLE
@ PLACEABLE
Default value, composition is pacable.
Definition: SCR_PreviewEntityEditorComponent.c:1141
EPreviewEntityFlag
EPreviewEntityFlag
Definition: EPreviewEntityFlag.c:1
m_SlotPrefab
protected ResourceName m_SlotPrefab
Definition: SCR_EntitiesEditorUIComponent.c:9
NONE
@ NONE
Definition: SCR_PreviewEntityEditorComponent.c:1140
EEditorTransformVertical
EEditorTransformVertical
Vertical transformation mode.
Definition: EEditorTransformVertical.c:5
SCR_BaseEditorComponent
Definition: SCR_BaseEditorComponent.c:119
Attribute
typedef Attribute
Post-process effect of scripted camera.
SCR_PreviewEntityEditorComponentClass
Definition: SCR_PreviewEntityEditorComponent.c:2
EEditableEntityType
EEditableEntityType
Defines type of SCR_EditableEntityComponent. Assigned automatically based on IEntity inheritance.
Definition: EEditableEntityType.c:5
m_bIsUnderwater
protected bool m_bIsUnderwater
Definition: SCR_MotorExhaustEffectGeneralComponent.c:21
SCR_PrefabPreviewEntity
Definition: SCR_PrefabPreviewEntity.c:8
m_World
protected BaseWorld m_World
Definition: SCR_PreviewEntityEditorUIComponent.c:46
WARNING
@ WARNING
Composition is in not a good position, still placeable.
Definition: SCR_PreviewEntityEditorComponent.c:1143
GetOwner
IEntity GetOwner()
Owner entity of the fuel tank.
Definition: SCR_FuelNode.c:128
EEditableEntityInteractionFlag
EEditableEntityInteractionFlag
Details of entity interaction.
Definition: EEditableEntityInteractionFlag.c:5
SCR_BaseEditorComponentClass
Definition: SCR_BaseEditorComponent.c:2
SCR_EditableEntityComponent
Definition: SCR_EditableEntityComponent.c:13
SCR_BaseContainerTools
Definition: SCR_BaseContainerTools.c:3
SCR_LayersEditorComponent
Definition: SCR_LayersEditorManager.c:11
SCR_Global
Definition: Functions.c:6
SCR_SiteSlotEntity
Definition: SCR_SiteSlotEntity.c:26
params
Configs ServerBrowser KickDialogs params
Definition: SCR_NotificationSenderComponent.c:24
SCR_StatesEditorComponent
Definition: SCR_StatesEditorComponent.c:9
SCR_EditableEntityInteraction
Definition: SCR_EditableEntityInteraction.c:2
SCR_EditableEntityComponentClass
Definition: SCR_EditableEntityComponentClass.c:2
SCR_DebugMenuID
SCR_DebugMenuID
This enum contains all IDs for DiagMenu entries added in script.
Definition: DebugMenuID.c:3
SCR_PreviewEntityEditorComponent
Definition: SCR_PreviewEntityEditorComponent.c:12
category
params category
Definition: SCR_VehicleDamageManagerComponent.c:180