Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
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")]
5
8
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.")]
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;
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;
84
89 private ResourceName m_SlotPrefab;
90 private vector m_aLocalOffset[4];
91 private SCR_EditableEntityComponent m_Entity;
92 private EEditableEntityType m_EntityType;
94
95 // OnPreviewCreate(SCR_BasePreviewEntity previewEntity)
96 private ref ScriptInvoker Event_OnPreviewCreate = new ScriptInvoker;
97 // OnPreviewDelete(SCR_BasePreviewEntity previewEntity)
98 private ref ScriptInvoker Event_OnPreviewDelete = new ScriptInvoker;
99 // OnPreviewChange(vector transform[4], bool isChange)
100 private ref ScriptInvoker Event_OnPreviewChange = new ScriptInvoker;
101 // OnTargetChange(SCR_EditableEntityComponent target)
102 private ref ScriptInvoker Event_OnTargetChange = new ScriptInvoker;
103 // OnWaitingPreviewCreate(SCR_BasePreviewEntity previewEntity)
104 private ref ScriptInvoker Event_OnWaitingPreviewCreate = new ScriptInvoker;
105 // OnVerticalModeChange(EEditorTransformVertical verticalMode)
106 private ref ScriptInvoker Event_OnVerticalModeChange = new ScriptInvoker;
107 // OnVerticalModeChange(EEditorTransformSnap verticalSnap)
108 private ref ScriptInvoker Event_OnVerticalSnapChange = new ScriptInvoker;
109
110 protected const float VERTICAL_TRACE_OFFSET = 0.01; //--- Vertical offset of trace start to make sure it does not start inside geometry.
111
112 //------------------------------------------------------------------------------------------------
117
123 void SetPreviewTransform(vector transform[4], float timeSlice = 1, bool instant = false, EEditorTransformVertical verticalMode = EEditorTransformVertical.TERRAIN)
124 {
125 if (!m_PreviewEntity || m_bIsFixedPosition)
126 return;
127
128 //--- 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)
129 if (m_Target && !m_bTargetSnap)
130 {
132 return;
133 }
134
135 instant = true;
136
137 vector cameraTransform[4];
138 m_World.GetCurrentCamera(cameraTransform);
139 vector cameraPos = cameraTransform[3];
140 m_bIsUnderwater = cameraPos[1] < m_World.GetOceanBaseHeight();
141
142 if (m_Target && m_bTargetSnap)
143 {
144 //--- Attached to a target, override input transformation
145 vector targetTransform[4];
146 if (m_Target.GetTransform(targetTransform))
147 {
148 switch (true)
149 {
150 //--- Disabled rotation
151 case (m_fTargetRotationStep == -1):
152 {
153 transform = targetTransform;
154 break;
155 }
156 //--- Stepped rotation
157 case (m_fTargetRotationStep != 0):
158 {
159 vector targetAngles = Math3D.MatrixToAngles(targetTransform);
160 vector angles = Math3D.MatrixToAngles(transform);
161 angles[0] = targetAngles[0] + Math.Round((angles[0] - targetAngles[0]) / m_fTargetRotationStep) * m_fTargetRotationStep;
162 if (!m_bInstantTransformation && !instant) LerpAngles(m_PreviewEntity.GetAngles(), angles, timeSlice);
163 Math3D.AnglesToMatrix(angles, transform);
164 break;
165 }
166 //--- Free rotation (do not modify incoming dir)
167 default:
168 {
169 if (!m_bInstantTransformation)
170 {
171 vector angles = Math3D.MatrixToAngles(transform);
172 if (!m_bInstantTransformation && !instant) LerpAngles(m_PreviewEntity.GetAngles(), angles, timeSlice);
173 Math3D.AnglesToMatrix(angles, transform);
174 }
175 }
176 }
177 transform[3] = targetTransform[3];
178 if (!m_bInstantTransformation && !instant) transform[3] = LerpTranslation(m_PreviewEntity.GetOrigin(), transform[3], timeSlice);
179
180 Math3D.MatrixMultiply4(transform, m_aLocalOffset, transform); //--- Counter local offset to make sure that preview's center is snapped to slot
181 m_PreviewEntity.SetPreviewTransform(transform, verticalMode, m_fHeightTerrain, m_bIsUnderwater);
182 }
183 }
184 else
185 {
186 //--- Free transformation
187 if (!m_bInstantTransformation && !instant)
188 {
189 vector transformCurrent[4];
190 m_PreviewEntity.GetWorldTransform(transformCurrent);
191
192 float quat[4], quatCurrent[4];
193 Math3D.MatrixToQuat(transform, quat);
194 Math3D.MatrixToQuat(transformCurrent, quatCurrent);
195 Math3D.QuatLerp(quatCurrent, quat, quat, timeSlice);
196 Math3D.QuatToMatrix(quat, transform);
197
198 transform[3] = LerpTranslation(m_PreviewEntity.GetOrigin(), transform[3], timeSlice);
199 }
200
201 TraceParam trace;
202 if (verticalMode == EEditorTransformVertical.GEOMETRY)
203 {
204 trace = new TraceParam();
205 trace.ExcludeArray = m_PreviewEntity.GetExcludeArray();
206
207 //--- When the preview represents a composition, trace surface from camera height, not cursor intersection height, as child entities could be below it.
208 if (m_PreviewEntity.HasMultipleEditableEntities())
209 {
210 vector matrix[4];
211 m_PreviewEntity.GetWorld().GetCurrentCamera(matrix);
212 trace.Start = matrix[3];
213 }
214 }
215
216 m_PreviewEntity.SetPreviewTransform(transform, verticalMode, m_fHeightTerrain, m_bIsUnderwater, trace);
217 }
218
219 if (!m_bIsChange)
220 {
221 m_PreviewEntity.SetFlags(EntityFlags.VISIBLE, true);
222 }
223
224 m_bIsChange = true;
225 m_bInstantTransformation = false;
226 m_VerticalModeReal = verticalMode;
227 Event_OnPreviewChange.Invoke(transform, true);
228
229 //--- Height not defined yet, set it now
230 if (!m_bIsHeightSet) SetPreviewHeight(transform[3]);
231
232 //--- Placeholder vertical indicator. ToDo: Replace
233 float indicatorHeight = m_fHeightTerrain - m_aLocalOffset[3][1];
234 if (indicatorHeight > 0.025)
235 {
236 vector indicatorPos = transform[3] - Vector(0, indicatorHeight * 0.5 + m_aLocalOffset[3][1], 0);
237 Shape.CreateCylinder(m_iHeightIndicatorColor, ShapeFlags.TRANSP | ShapeFlags.ONCE | ShapeFlags.NOOUTLINE, indicatorPos, 0.05, indicatorHeight);
238 Shape.CreateCylinder(m_iHeightIndicatorColor, ShapeFlags.TRANSP | ShapeFlags.ONCE | ShapeFlags.NOOUTLINE | ShapeFlags.NOZBUFFER, indicatorPos, 0.01, indicatorHeight);
239 }
240 }
241
245 {
246 if (!m_PreviewEntity || !m_bIsChange)
247 return;
248
249 bool isChange = m_bIsChange;
250 m_bIsChange = false;
251 if (isChange)
252 {
253 //--- Hide the preview
254 m_PreviewEntity.ClearFlags(EntityFlags.VISIBLE, true);
255
256 vector transform[4];
257 m_PreviewEntity.GetWorldTransform(transform);
258 Event_OnPreviewChange.Invoke(transform, m_bIsChange);
259 }
260 }
261
265 bool GetPreviewTransform(out vector transform[4])
266 {
267 if (!m_PreviewEntity)
268 return false;
269
270 m_PreviewEntity.GetWorldTransform(transform);
271 return true;
272 }
273
277 bool GetPreviewTransformOrigin(out vector transform[4])
278 {
279 if (!m_PreviewEntity) return false;
280 Math3D.MatrixCopy(m_vTransform, transform);
281 return true;
282 }
283
289 {
290 if (!m_PreviewEntity || !m_World) return;
291 m_fHeightSea = pos[1];
292
293 TraceParam trace;
294 if (m_VerticalModeReal == EEditorTransformVertical.GEOMETRY)
295 {
296 //--- When snapping to ground, offset a bit up so prevent the trace from starting below surface
297 pos[1] = pos[1] + VERTICAL_TRACE_OFFSET;
298
299 trace = new TraceParam();
300 trace.ExcludeArray = m_PreviewEntity.GetExcludeArray();
301 }
302
303 if (m_bHasTerrain)
304 m_fHeightTerrain = pos[1] - SCR_TerrainHelper.GetTerrainY(pos, m_World, !m_bIsUnderwater, trace);
305 else
306 m_fHeightTerrain = m_fHeightSea;
307
308 m_bIsHeightSet = true;
309 }
310
314 {
315 m_fHeightSea = 0;
316 m_fHeightTerrain = 0;
317 }
318
323 {
324 return m_fHeightTerrain;
325 }
326
331 {
332 return m_fHeightSea;
333 }
334
338 {
339 return m_aLocalOffset[3];
340 }
341
346 {
347 if (mode == m_VerticalMode || !SCR_Enum.HasFlag(m_AllowedVerticalModes, mode))
348 return;
349
350 m_VerticalMode = mode;
351 DiagMenu.SetValue(SCR_DebugMenuID.DEBUGUI_EDITOR_TRANSFORM_VERTICAL_MODE, m_VerticalMode >> 1);
352 Event_OnVerticalModeChange.Invoke(m_VerticalMode);
353 }
354
359 {
360 return m_VerticalMode;
361 }
362
368 {
369 return m_VerticalModeReal;
370 }
371
375 void SetVerticalSnap(bool enabled)
376 {
377 if (enabled == m_bIsVerticalSnap)
378 return;
379
380 m_bIsVerticalSnap = enabled;
381 DiagMenu.SetValue(SCR_DebugMenuID.DEBUGUI_EDITOR_TRANSFORM_VERTICAL_SNAP, m_bIsVerticalSnap);
382 Event_OnVerticalSnapChange.Invoke(m_bIsVerticalSnap);
383 }
384
389 {
390 return m_bIsVerticalSnap;
391 }
392
398 {
399 float baseSnapHeight = GetSnapBaseHeight(pos, GetVerticalMode());
400 float delta = pos[1] - baseSnapHeight;
401 if (delta < m_fVerticalSnapLimit)
402 pos[1] = baseSnapHeight;
403
404 return pos;
405 }
406
411 {
412 if (!m_PreviewEntity)
413 return false;
414
415 vector pos = m_PreviewEntity.GetTransformAxis(3);
416 float baseSnapHeight = GetSnapBaseHeight(pos, GetVerticalMode());
417 float delta = pos[1] - baseSnapHeight;
418 return Math.AbsFloat(delta) < m_fVerticalSnapLimit;
419 }
420
425 bool CanUnsnap(float verticalDelta)
426 {
427 if (!IsSnappedVertically())
428 return false;
429
430 if (m_VerticalMode == EEditorTransformVertical.TERRAIN)
431 {
432 return verticalDelta > 0; //--- Cannot go below terrain
433 }
434 return false;
435 }
436 protected float GetSnapBaseHeight(vector pos, EEditorTransformVertical verticalMode)
437 {
438 switch (verticalMode)
439 {
440 case EEditorTransformVertical.GEOMETRY:
441 case EEditorTransformVertical.TERRAIN:
442 {
443 TraceParam trace;
444 if (verticalMode == EEditorTransformVertical.GEOMETRY)
445 {
446 trace = new TraceParam();
447 trace.ExcludeArray = m_PreviewEntity.GetExcludeArray();
448 }
449 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
450 }
451 }
452 return m_aLocalOffset[3][1];
453 }
454
458 {
459 return m_bCanMoveInRoot;
460 }
461
465 void ShowAsDisabled(bool disable = true)
466 {
467 if (disable == m_bPreviewDisabled)
468 return;
469
470 m_bPreviewDisabled = disable;
471
472 ResourceName material = m_PreviewMaterial;
473 if (disable)
474 material = m_DisabledPreviewMaterial;
475
477 }
478
484 {
485 if (m_LastPreviewState == state)
486 return;
487
488 ResourceName material;
489 switch (state)
490 {
491 case SCR_EPreviewState.PLACEABLE:
492 {
493 material = m_PreviewMaterial;
494 m_LastPreviewState = SCR_EPreviewState.PLACEABLE;
495 break;
496 }
497 case SCR_EPreviewState.BLOCKED:
498 {
499 material = m_DisabledPreviewMaterial;
500 m_LastPreviewState = SCR_EPreviewState.BLOCKED;
501 break;
502 }
503 case SCR_EPreviewState.WARNING:
504 {
505 material = m_WarningPreviewMaterial;
506 m_LastPreviewState = SCR_EPreviewState.WARNING;
507 break;
508 }
509 }
510
512 }
513
519 {
520 m_LastPreviewState = state;
521 }
522
528 bool SetTarget(SCR_EditableEntityComponent target, bool isDelegate = false)
529 {
530 if (!m_PreviewEntity)
531 return false;
532
533 if (target)
534 {
535 if (target == m_Target && isDelegate == m_bTargetDelegate)
536 return false;
537
538 //--- Check if the preview can interact with the target
539 bool targetSnap;
540 EEditableEntityInteraction targetInteraction;
541 if (!CanInteractWith(target, targetSnap, targetInteraction, isDelegate))
542 {
543 if (m_Target) SetTarget(null);
544 return true;
545 }
546
547 m_Target = target;
548 m_bTargetSnap = targetSnap;
549 m_TargetInteraction = targetInteraction;
550 m_bTargetDelegate = isDelegate;
551
552 if (m_bTargetSnap)
553 {
554 SCR_SiteSlotEntity slotEntity = SCR_SiteSlotEntity.Cast(target.GetOwner());
555 if (slotEntity)
556 m_fTargetRotationStep = slotEntity.GetRotationStep();
557 else
558 m_fTargetRotationStep = -1;
559 }
560 }
561 else
562 {
563 //--- Remove
564 if (!m_Target) return false;
565
566 m_Target = null;
567 m_TargetInteraction = 0;
568 }
569 Event_OnTargetChange.Invoke(target);
570 return true;
571 }
572 protected bool CanInteractWith(SCR_EditableEntityComponent target, out bool snap, out EEditableEntityInteraction interaction, bool isDelegate)
573 {
574 //--- Cannot interact with itself
575 if (target == m_Entity)
576 return false;
577
578 //--- Snap to compatible slot
579 if (target.HasEntityState(EEditableEntityState.COMPATIBLE_SLOT))
580 {
581 interaction = EEditableEntityInteraction.SLOT;
582 snap = true;
583 return true;
584 }
585
586 bool isTargetDestroyed = target.IsDestroyed();
587
588 EEditableEntityInteractionFlag defaultInteractionFlags;
589 if (m_LayerManager && m_LayerManager.IsEditingLayersEnabled())
590 defaultInteractionFlags |= EEditableEntityInteractionFlag.LAYER_EDITING;
591
592 //--- Check interaction of all edited entities
594 //SCR_EditablePreviewEntity editableChild;
595 SCR_EditableEntityComponent editableChild;
596 if (core)
597 {
598 if (m_bORInteraction)
599 {
600 //--- At least one entity must be compatible
601 foreach (SCR_BasePreviewEntity child: m_PreviewEntity.GetPreviewChildren())
602 {
603 if (!m_Interaction)
604 continue;
605
606 EEditableEntityInteractionFlag interactionFlags = defaultInteractionFlags;
607
608 editableChild = SCR_EditableEntityComponent.GetEditableEntity(child.GetSourceEntity());
609 if (!isTargetDestroyed && (!editableChild || !editableChild.IsDestroyed()))
610 interactionFlags |= EEditableEntityInteractionFlag.ALIVE;
611
612 if (isDelegate)
613 interactionFlags |= EEditableEntityInteractionFlag.DELEGATE;
614
615 if (!editableChild || editableChild.GetPlayerID() == 0)
616 interactionFlags |= EEditableEntityInteractionFlag.NON_PLAYABLE;
617
618 if (m_StateManager && m_StateManager.GetState() == EEditorState.PLACING)
619 interactionFlags |= EEditableEntityInteractionFlag.PLACING;
620
621 if (m_Interaction.CanSetParent(target, interactionFlags))
622 {
623 interaction = EEditableEntityInteraction.LAYER;
624 return true;
625 }
626 }
627 }
628 else
629 {
630 //--- All entities must be compatible
631 foreach (SCR_BasePreviewEntity child: m_PreviewEntity.GetPreviewChildren())
632 {
633 if (!m_Interaction)
634 return false;
635
636 EEditableEntityInteractionFlag interactionFlags = defaultInteractionFlags;
637
638 editableChild = SCR_EditableEntityComponent.GetEditableEntity(child.GetSourceEntity());
639 if (!isTargetDestroyed && (!editableChild || !editableChild.IsDestroyed()))
640 interactionFlags |= EEditableEntityInteractionFlag.ALIVE;
641
642 if (isDelegate)
643 interactionFlags |= EEditableEntityInteractionFlag.DELEGATE;
644
645 if (!editableChild || editableChild.GetPlayerID() == 0)
646 interactionFlags |= EEditableEntityInteractionFlag.NON_PLAYABLE;
647
648 if (m_StateManager && m_StateManager.GetState() == EEditorState.PLACING)
649 interactionFlags |= EEditableEntityInteractionFlag.PLACING;
650
651 if (!m_Interaction.CanSetParent(target, interactionFlags))
652 return false;
653 }
654 interaction = EEditableEntityInteraction.LAYER;
655 return true;
656 }
657 }
658 return false;
659 }
660
666 {
667 return m_Target;
668 }
669
674 {
675 return m_TargetInteraction;
676 }
677
682 {
683 return m_bTargetSnap;
684 }
685
693
694 //------------------------------------------------------------------------------------------------
701
707 {
708 return m_sActionContext;
709 }
710
715 {
716 return m_PreviewEntity != null;
717 }
718
722 bool IsChange()
723 {
724 return m_bIsChange || m_bIsFixedPosition || m_Target;
725 }
726
731 {
732 return m_bIsRotating;
733 }
734
739 {
740 return m_bIsFixedPosition;
741 }
742
747 {
748 return m_SlotPrefab;
749 }
750
754 void SetIsMovingVertically(bool isMovingVertically)
755 {
756 m_bIsMovingVertically = isMovingVertically;
757 }
758
763 {
764 return m_bIsMovingVertically;
765 }
766
770 void SetIsRotating(bool isRotating)
771 {
772 m_bIsRotating = isRotating;
773 }
774
779 {
780 return m_bIsUnderwater;
781 }
782
787 array<IEntity> GetExcludeArray()
788 {
789 if (m_PreviewEntity)
790 return m_PreviewEntity.GetExcludeArray();
791 else
792 return null;
793 }
794
799 {
800 return Event_OnPreviewCreate;
801 }
802
807 {
808 return Event_OnPreviewDelete;
809 }
810
815 {
816 return Event_OnPreviewChange;
817 }
818
823 {
824 return Event_OnTargetChange;
825 }
826
831 {
832 return Event_OnWaitingPreviewCreate;
833 }
834
839 {
840 return Event_OnVerticalModeChange;
841 }
842
847 {
848 return Event_OnVerticalSnapChange;
849 }
850
851 void InitTransform(vector transform[4])
852 {
853 m_vTransform = transform;
854
855 //--- Normalize transformation matrix, so it does not affect scale even when pivot entity is scaled up or down
856 Math3D.MatrixNormalize(m_vTransform);
857
858 SetPreviewHeight(transform[3]);
859 }
860
867 SCR_BasePreviewEntity CreatePreview(SCR_EditableEntityComponent pivot, set<SCR_EditableEntityComponent> entities)
868 {
870
872 if (m_bIsUnderwater)
873 flags |= EPreviewEntityFlag.UNDERWATER;
874
875 if (m_VerticalMode == EEditorTransformVertical.GEOMETRY)
876 flags |= EPreviewEntityFlag.GEOMETRY;
877
878 EntitySpawnParams spawnParams = new EntitySpawnParams();
879 Math3D.MatrixCopy(m_vTransform, spawnParams.Transform);
880 m_PreviewEntity = SCR_EditablePreviewEntity.Cast(SCR_EditablePreviewEntity.SpawnPreviewFromEditableEntities(entities, m_PreviewEntityPrefab, GetOwner().GetWorld(), spawnParams, m_PreviewMaterial, flags));
881 m_bInstantTransformation = true;
882 m_Entity = pivot;
883 m_EntityType = pivot.GetEntityType();
886
888 if (info)
889 m_SlotPrefab = info.GetSlotPrefab();
890 else
891 m_SlotPrefab = ResourceName.Empty;
892
893 //--- Get local offset for slotting
894 vector localOffsetPos = m_aLocalOffset[3];
895 if (pivot.GetPos(localOffsetPos))
896 {
897 vector pivotTransform[4];
898 pivot.GetOwner().GetWorldTransform(pivotTransform);
899 Math3D.MatrixInvMultiply4(m_vTransform, pivotTransform, pivotTransform);
900 m_aLocalOffset[3] = -pivotTransform[3];// pivot.GetOwner().CoordToLocal(m_vTransform[3]); //--- Cannot use CoordToLocal, doesn't take m_vTransform rotation into effect
901 }
902
903 Event_OnPreviewCreate.Invoke(m_PreviewEntity);
904
905 //--- Reset position. Without it, moving entity vertically on client (where there's a delay) would cause vertical offset
906 SetPreviewHeight(m_vTransform[3]);
908
909 return m_PreviewEntity;
910 }
911
918 SCR_BasePreviewEntity CreatePreview(ResourceName prefab, notnull array<vector> offsets, vector initTransform[4] = {})
919 {
921
922 if (prefab)
923 {
924 Resource prefabResource = Resource.Load(prefab);
925 EntitySpawnParams spawnParams = new EntitySpawnParams();
926
927 IEntitySource entitySource = SCR_BaseContainerTools.FindEntitySource(prefabResource);
928 IEntityComponentSource entityComponent = SCR_BaseContainerTools.FindComponentSource(entitySource, SCR_EditableEntityComponent);
929 m_EntityType = SCR_EditableEntityComponentClass.GetEntityType(entityComponent);
932 m_bIsFixedPosition = SCR_EditableEntityComponentClass.HasFlag(entityComponent, EEditableEntityFlag.STATIC_POSITION);
934 m_sPreviewPrefab = prefab;
935
936 if (m_bIsFixedPosition)
937 {
938 //--- Get coordinates of the prefab itself when it's intended only for one position
940 entitySource.Get("coords", coords);
941 if (coords.LengthSq() != 0)
942 {
943 spawnParams.Transform[3] = coords;
944 }
945 else
946 {
947 Print(string.Format("Prefab '%1' is flagged as STATIC_POSITION, but its position is <0,0,0>!", prefab.GetPath()), LogLevel.WARNING);
948 m_bIsFixedPosition = false;
949 }
950 }
951 else if (initTransform[3] == vector.Zero)
952 {
953 //--- Restore previous yaw (don't apply full rotation, would cause problems on uneven terrain; ToDo: Use rotation relativer to terrain?)
954 vector angles = Vector(Math3D.MatrixToAngles(m_vTransform)[0], 0, 0);
955 Math3D.AnglesToMatrix(angles, m_vTransform);
956 m_vTransform[3] = vector.Zero; //--- Reset position to prevent waypoint appearing in the air
957 spawnParams.Transform = m_vTransform;
958 }
959 else
960 {
961 spawnParams.Transform = initTransform;
962 }
963
964 if (offsets.Count() > 1)
965 {
966 //--- Create as many previews as there are selected entities (e.g., for waypoins or tasks)
967 array<ref SCR_BasePreviewEntry> entries = SCR_PrefabPreviewEntity.GetPreviewEntriesFromPrefab(prefabResource);
968 SCR_BasePreviewEntry sourceEntry = entries[0];
969 SCR_BasePreviewEntry entry;
970 for (int i = 0, count = offsets.Count(); i < count; i++)
971 {
972 if (i == 0)
973 {
974 entry = entries[i];
975 }
976 else
977 {
978 entry = new SCR_BasePreviewEntry();
979 entry.CopyFrom(sourceEntry);
980 entries.Insert(entry);
981 }
982 entry.m_vPosition = offsets[i];
983 }
984 m_PreviewEntity = SCR_EditablePreviewEntity.Cast(SCR_PrefabPreviewEntity.SpawnPreview(entries, m_PreviewEntityPrefab, spawnParams: spawnParams, material: m_PreviewMaterial));
985 }
986 else
987 {
988 //--- Create preview directly
989 m_PreviewEntity = SCR_EditablePreviewEntity.Cast(SCR_PrefabPreviewEntity.SpawnPreviewFromPrefab(prefabResource, m_PreviewEntityPrefab, spawnParams: spawnParams, material: m_PreviewMaterial));
990 }
991 if (m_PreviewEntity)
992 {
993 m_fHeightTerrain = 0;
994 Event_OnPreviewCreate.Invoke(m_PreviewEntity);
995 }
996 }
997 return m_PreviewEntity;
998 }
999
1003 {
1004 if (m_PreviewEntity)
1005 {
1006 SCR_BasePreviewEntity previewEntity = m_PreviewEntity;
1007 m_PreviewEntity = null;
1008 m_sPreviewPrefab = string.Empty;
1009
1010 previewEntity.GetWorldTransform(m_vTransform);
1011 if (m_Target)
1012 Event_OnTargetChange.Invoke(null);
1013
1014 Event_OnPreviewDelete.Invoke(previewEntity);
1015 delete previewEntity;
1016 }
1017 m_bIsChange = false;
1018 m_bIsHeightSet = false;
1019 m_bIsFixedPosition = false;
1020 m_bIsRotating = false;
1021 m_bPreviewDisabled = false;
1022 m_Target = null;
1023 m_TargetInteraction = 0;
1024 m_Entity = null;
1025 m_aLocalOffset[3] = vector.Zero;
1026 }
1027
1031 {
1032 if (!m_PreviewEntity)
1033 return null;
1034
1035 Resource previewResource = Resource.Load(m_WaitingEntityPrefab);
1036 if (!previewResource || !previewResource.IsValid())
1037 return null;
1038
1039 EntitySpawnParams spawnParams = new EntitySpawnParams();
1040 m_PreviewEntity.GetWorldTransform(spawnParams.Transform);
1041 SCR_BasePreviewEntity previewEntity = SCR_EditablePreviewEntity.SpawnPreviewFromEditableOwner(m_PreviewEntity, m_WaitingEntityPrefab, m_PreviewEntity.GetWorld(), spawnParams, m_WaitingPreviewMaterial);
1042 Event_OnWaitingPreviewCreate.Invoke(previewEntity);
1043 return previewEntity;
1044 }
1045
1046 protected vector LerpTranslation(vector currentPos, vector targetPos, float timeSlice)
1047 {
1048 return vector.Lerp(currentPos, targetPos, Math.Min(timeSlice * m_fPreviewTranslationInertia, 1));
1049 }
1050 protected void LerpAngles(vector currentAngles, out vector targetAngles, float timeSlice)
1051 {
1052 //--- currentAngles vector has different order than targetAngles vector, because it's filled by GetAngles()
1053 targetAngles[0] = SCR_Math.LerpAngle(currentAngles[1], targetAngles[0], Math.Min(timeSlice * m_fPreviewRotationInertia, 1));
1054 }
1055
1056 protected void OnUserSettingsChanged()
1057 {
1058 BaseContainer editorSettings = GetGame().GetGameUserSettings().GetModule("SCR_EditorSettings");
1059 if (!editorSettings)
1060 return;
1061
1062 int value;
1063 editorSettings.Get("m_PreviewVerticalSnap", value);
1064 SetVerticalSnap(value);
1065 editorSettings.Get("m_PreviewVerticleMode", value);
1066 SetVerticalMode(value);
1067 }
1068
1069
1070 override void EOnEditorDebug(array<string> debugTexts)
1071 {
1072 debugTexts.Insert("Vertical Mode: " + Type().EnumToString(EEditorTransformVertical, m_VerticalMode));
1073 debugTexts.Insert("Vertical Mode (Real): " + Type().EnumToString(EEditorTransformVertical, m_VerticalModeReal));
1074 debugTexts.Insert("Vertical Snap: " + m_bIsVerticalSnap);
1075 debugTexts.Insert("Height ASL: " + m_fHeightSea);
1076 debugTexts.Insert("Height ATL: " + m_fHeightTerrain);
1077
1078 if (m_PreviewEntity)
1079 {
1080 debugTexts.Insert(string.Format("Preview Target: %1", m_Target));
1081 debugTexts.Insert(string.Format("Preview Target Interaction: %1", typename.EnumToString(EEditableEntityInteraction, m_TargetInteraction)));
1082 }
1083 }
1084 override void EOnFrame(IEntity owner, float timeSlice)
1085 {
1086#ifdef ENABLE_DIAG
1087 int verticalMode = 1 << DiagMenu.GetValue(SCR_DebugMenuID.DEBUGUI_EDITOR_TRANSFORM_VERTICAL_MODE);
1088 if (verticalMode != m_VerticalMode)
1089 {
1090 SetVerticalMode(verticalMode);
1091 }
1092 if (DiagMenu.GetValue(SCR_DebugMenuID.DEBUGUI_EDITOR_TRANSFORM_VERTICAL_SNAP) != m_bIsVerticalSnap)
1093 {
1094 SetVerticalSnap(DiagMenu.GetValue(SCR_DebugMenuID.DEBUGUI_EDITOR_TRANSFORM_VERTICAL_SNAP));
1095 }
1096#endif
1097 }
1098 override void EOnEditorActivate()
1099 {
1101
1102 ArmaReforgerScripted game = GetGame();
1103 if (!game) return;
1104
1105 m_World = game.GetWorld();
1108
1109#ifdef ENABLE_DIAG
1110 typename enumVerticalMode = EEditorTransformVertical;
1111 DiagMenu.RegisterRange(SCR_DebugMenuID.DEBUGUI_EDITOR_TRANSFORM_VERTICAL_MODE, "", "Vertical Mode", "Transforming", string.Format("0 %1 0 1", enumVerticalMode.GetVariableCount() - 1));
1112 DiagMenu.SetValue(SCR_DebugMenuID.DEBUGUI_EDITOR_TRANSFORM_VERTICAL_MODE, m_VerticalMode >> 1);
1113
1114 DiagMenu.RegisterBool(SCR_DebugMenuID.DEBUGUI_EDITOR_TRANSFORM_VERTICAL_SNAP, "", "Vertical Snap", "Transforming");
1115 DiagMenu.SetValue(SCR_DebugMenuID.DEBUGUI_EDITOR_TRANSFORM_VERTICAL_SNAP, m_bIsVerticalSnap);
1116#endif
1117 }
1118 override void EOnEditorDeactivate()
1119 {
1120 DeletePreview();
1121 }
1122 override void EOnEditorInit()
1123 {
1124 ArmaReforgerScripted game = GetGame();
1125 if (!game)
1126 return;
1127
1128 GenericWorldEntity worldEntity = game.GetWorldEntity();
1129 if (!worldEntity)
1130 return;
1131
1132 // only this context has input that allows for adjusting vertical position
1133 m_bCanAdjustVerticalPosition = m_sActionContext == "EditorPreviewContext";
1134
1135 m_bHasTerrain = worldEntity.GetTerrain(0, 0) != null;
1136
1137 m_fPreviewTranslationInertia = 1 / Math.Max(m_fPreviewTranslationInertia, 0.001);
1138 m_fPreviewRotationInertia = 1 / Math.Max(m_fPreviewRotationInertia, 0.001);
1139
1140 BaseContainer editorSettings = GetGame().GetGameUserSettings().GetModule("SCR_EditorSettings");
1141 if (editorSettings)
1142 {
1143 //Init values from options
1145 GetGame().OnUserSettingsChangedInvoker().Insert(OnUserSettingsChanged);
1146 }
1147
1148 m_iHeightIndicatorColor = m_HeightIndicatorColor.PackToInt();
1149
1150 Math3D.MatrixIdentity3(m_aLocalOffset); //--- Initialize offset matrix angles
1151 }
1152
1153 override void OnDelete(IEntity owner)
1154 {
1155 if (GetGame())
1156 GetGame().OnUserSettingsChangedInvoker().Remove(OnUserSettingsChanged);
1157 }
1158};
1159
SCR_EAIThreatSectorFlags flags
ref DSGameConfig game
Definition DSConfig.c:81
SCR_DebugMenuID
This enum contains all IDs for DiagMenu entries added in script.
Definition DebugMenuID.c:4
EPreviewEntityFlag
ArmaReforgerScripted GetGame()
Definition game.c:1398
ref array< string > coords
ref array< string > angles
class SCR_AIPolar m_Target
enum EAIGroupCombatMode ComponentEditorProps(category:"GameScripted/AI", description:"Component for utility AI system for groups")
@ BLOCKED
User has this asset blocked so it should not be possible to interact with it until unblocked.
ResourceName m_SlotPrefab
@ PLACEABLE
Default value, composition is pacable.
UI Textures DeployMenu Briefing conflict_HintBanner_1_UI desc
int Type
Definition Color.c:13
Diagnostic and developer menu system.
Definition DiagMenu.c:18
proto external int SetEventMask(notnull IEntity owner, int mask)
Definition Math.c:13
Object holding reference to resource. In destructor release the resource.
Definition Resource.c:25
void SCR_BaseEditorComponent(IEntityComponentSource src, IEntity ent, IEntity parent)
static ResourceName GetSlotPrefab(IEntityComponentSource componentSource)
static bool HasFlag(IEntityComponentSource componentSource, EEditableEntityFlag flag)
SCR_EditableEntityInteraction GetEntityInteraction()
bool HasEntityState(EEditableEntityState state)
static SCR_EditableEntityComponent GetEditableEntity(IEntity owner)
EEditableEntityType GetEntityType(IEntity owner=null)
SCR_EditableEntityInteraction GetEntityInteraction(IEntity owner=null)
SCR_UIInfo GetInfo(IEntity owner=null)
sealed bool CanSetParent(SCR_EditableEntityComponent parentEntity, EEditableEntityInteractionFlag interactionFlags=int.MAX)
static SCR_BasePreviewEntity SpawnPreviewFromEditableOwner(IEntity entity, ResourceName previewPrefab, BaseWorld world=null, EntitySpawnParams spawnParams=null, ResourceName material=ResourceName.Empty, EPreviewEntityFlag flags=0)
static SCR_BasePreviewEntity SpawnPreviewFromEditableEntities(notnull set< SCR_EditableEntityComponent > entities, ResourceName previewPrefab, BaseWorld world=null, EntitySpawnParams spawnParams=null, ResourceName material=ResourceName.Empty, EPreviewEntityFlag flags=0)
static void SetMaterial(IEntity entity, ResourceName material, bool recursively=true)
Definition Functions.c:1793
static float LerpAngle(float a, float b, float t)
Definition SCR_Math.c:128
bool SetTarget(SCR_EditableEntityComponent target, bool isDelegate=false)
bool GetPreviewTransformOrigin(out vector transform[4])
void SetVerticalMode(EEditorTransformVertical mode)
float GetSnapBaseHeight(vector pos, EEditorTransformVertical verticalMode)
SCR_BasePreviewEntity CreatePreview(SCR_EditableEntityComponent pivot, set< SCR_EditableEntityComponent > entities)
void LerpAngles(vector currentAngles, out vector targetAngles, float timeSlice)
bool CanInteractWith(SCR_EditableEntityComponent target, out bool snap, out EEditableEntityInteraction interaction, bool isDelegate)
void SetPreviewTransform(vector transform[4], float timeSlice=1, bool instant=false, EEditorTransformVertical verticalMode=EEditorTransformVertical.TERRAIN)
override void EOnEditorDebug(array< string > debugTexts)
void SetIsMovingVertically(bool isMovingVertically)
ref SCR_EditableEntityInteraction m_Interaction
vector LerpTranslation(vector currentPos, vector targetPos, float timeSlice)
override void EOnFrame(IEntity owner, float timeSlice)
SCR_BasePreviewEntity CreatePreview(ResourceName prefab, notnull array< vector > offsets, vector initTransform[4]={})
static float GetTerrainY(vector pos, BaseWorld world=null, bool noUnderwater=false, TraceParam trace=null)
proto external GenericEntity GetOwner()
Get owner entity.
Instance of created debug visualizer.
Definition Shape.c:14
void EntitySpawnParams()
Definition gameLib.c:130
proto void Print(void var, LogLevel level=LogLevel.NORMAL)
Prints content of variable to console/log.
LogLevel
Enum with severity of the logging message.
Definition LogLevel.c:14
ShapeFlags
Definition ShapeFlags.c:13
@ NONE
When Shape is created and not initialized yet.
Definition ShapeType.c:15
@ WARNING
Definition LogLevel.c:19
EEditableEntityType
Defines type of SCR_EditableEntityComponent. Assigned automatically based on IEntity inheritance.
EEditableEntityFlag
Unique flags of the entity.
EEditableEntityState
SCR_FieldOfViewSettings Attribute
EEditorTransformVertical
Vertical transformation mode.
EEditorState
Unique editor state.
Definition EEditorState.c:6
EEditableEntityInteraction
Type of suggested interaction when hovering edited entity on top of another entity.
EEditableEntityInteractionFlag
Details of entity interaction.
EntityEvent
Various entity events.
Definition EntityEvent.c:14
EntityFlags
Various entity flags.
Definition EntityFlags.c:14
proto native vector Vector(float x, float y, float z)
ScriptInvokerBase< func > ScriptInvoker
Definition tools.c:134