1 [
ComponentEditorProps(
category:
"GameScripted/Editor", description:
"Manager of preview entity. Works only with SCR_EditorBaseEntity!", icon:
"WBData/ComponentEditorProps/componentEditor.png")]
15 private ResourceName m_PreviewEntityPrefab;
18 private ResourceName m_WaitingEntityPrefab;
20 [
Attribute(
category:
"Preview",
params:
"emat", uiwidget: UIWidgets.ResourcePickerThumbnail,
desc:
"Preview entity material when confirmation is allowed.")]
21 private ResourceName m_PreviewMaterial;
23 [
Attribute(
category:
"Preview",
params:
"emat", uiwidget: UIWidgets.ResourcePickerThumbnail,
desc:
"Preview entity material when confirmation is not allowed.")]
24 private ResourceName m_DisabledPreviewMaterial;
27 private ResourceName m_WaitingPreviewMaterial;
30 private ResourceName m_WarningPreviewMaterial;
33 private float m_fPreviewTranslationInertia;
36 private float m_fPreviewRotationInertia;
38 [
Attribute(
category:
"Preview", defvalue:
"1 1 1 0.2",
desc:
"Color of height indicator helper object.")]
39 protected ref Color m_HeightIndicatorColor;
48 private bool m_bIsVerticalSnap;
51 private float m_fVerticalSnapLimit;
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;
56 [
Attribute(
category:
"Settings", defvalue:
"EditorPreviewContext",
desc:
"Action context activated all the time.")]
57 protected string m_sActionContext;
59 private vector m_vTransform[4] = {vector.Right, vector.Up, vector.Forward, vector.Zero};
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;
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;
87 private ResourceName m_SlotPrefab;
88 private vector m_aLocalOffset[4];
94 private ref ScriptInvoker Event_OnPreviewCreate =
new ScriptInvoker;
96 private ref ScriptInvoker Event_OnPreviewDelete =
new ScriptInvoker;
98 private ref ScriptInvoker Event_OnPreviewChange =
new ScriptInvoker;
100 private ref ScriptInvoker Event_OnTargetChange =
new ScriptInvoker;
102 private ref ScriptInvoker Event_OnWaitingPreviewCreate =
new ScriptInvoker;
104 private ref ScriptInvoker Event_OnVerticalModeChange =
new ScriptInvoker;
106 private ref ScriptInvoker Event_OnVerticalSnapChange =
new ScriptInvoker;
108 protected const float VERTICAL_TRACE_OFFSET = 0.01;
123 ResetPreviewTransform();
129 vector cameraTransform[4];
130 m_World.GetCurrentCamera(cameraTransform);
131 vector cameraPos = cameraTransform[3];
137 vector targetTransform[4];
138 if (
m_Target.GetTransform(targetTransform))
143 case (m_fTargetRotationStep == -1):
145 transform = targetTransform;
149 case (m_fTargetRotationStep != 0):
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);
161 if (!m_bInstantTransformation)
163 vector angles = Math3D.MatrixToAngles(transform);
164 if (!m_bInstantTransformation && !instant) LerpAngles(
m_PreviewEntity.GetAngles(), angles, timeSlice);
165 Math3D.AnglesToMatrix(angles, transform);
169 transform[3] = targetTransform[3];
170 if (!m_bInstantTransformation && !instant) transform[3] = LerpTranslation(
m_PreviewEntity.GetOrigin(), transform[3], timeSlice);
172 Math3D.MatrixMultiply4(transform, m_aLocalOffset, transform);
179 if (!m_bInstantTransformation && !instant)
181 vector transformCurrent[4];
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);
190 transform[3] = LerpTranslation(
m_PreviewEntity.GetOrigin(), transform[3], timeSlice);
196 trace =
new TraceParam();
204 trace.Start = matrix[3];
217 m_bInstantTransformation =
false;
218 m_VerticalModeReal = verticalMode;
219 Event_OnPreviewChange.Invoke(transform,
true);
222 if (!m_bIsHeightSet) SetPreviewHeight(transform[3]);
225 float indicatorHeight = m_fHeightTerrain - m_aLocalOffset[3][1];
226 if (indicatorHeight > 0.025)
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);
236 void ResetPreviewTransform()
241 bool isChange = m_bIsChange;
250 Event_OnPreviewChange.Invoke(transform, m_bIsChange);
257 bool GetPreviewTransform(out vector transform[4])
269 bool GetPreviewTransformOrigin(out vector transform[4])
272 Math3D.MatrixCopy(m_vTransform, transform);
280 void SetPreviewHeight(vector pos)
283 m_fHeightSea = pos[1];
289 pos[1] = pos[1] + VERTICAL_TRACE_OFFSET;
291 trace =
new TraceParam();
298 m_fHeightTerrain = m_fHeightSea;
300 m_bIsHeightSet =
true;
305 void ResetPreviewHeight()
308 m_fHeightTerrain = 0;
314 float GetPreviewHeightAboveTerrain()
316 return m_fHeightTerrain;
322 float GetPreviewHeightAboveSea()
329 vector GetLocalOffset()
331 return m_aLocalOffset[3];
339 if (mode == m_VerticalMode || !
SCR_Enum.HasFlag(m_AllowedVerticalModes, mode))
342 m_VerticalMode = mode;
343 DiagMenu.SetValue(
SCR_DebugMenuID.DEBUGUI_EDITOR_TRANSFORM_VERTICAL_MODE, m_VerticalMode >> 1);
344 Event_OnVerticalModeChange.Invoke(m_VerticalMode);
352 return m_VerticalMode;
361 return m_VerticalModeReal;
367 void SetVerticalSnap(
bool enabled)
369 if (enabled == m_bIsVerticalSnap)
372 m_bIsVerticalSnap = enabled;
373 DiagMenu.SetValue(
SCR_DebugMenuID.DEBUGUI_EDITOR_TRANSFORM_VERTICAL_SNAP, m_bIsVerticalSnap);
374 Event_OnVerticalSnapChange.Invoke(m_bIsVerticalSnap);
380 bool IsVerticalSnap()
382 return m_bIsVerticalSnap;
389 vector SnapVertically(vector pos)
391 float baseSnapHeight = GetSnapBaseHeight(pos, GetVerticalMode());
392 float delta = pos[1] - baseSnapHeight;
393 if (delta < m_fVerticalSnapLimit)
394 pos[1] = baseSnapHeight;
402 bool IsSnappedVertically()
408 float baseSnapHeight = GetSnapBaseHeight(pos, GetVerticalMode());
409 float delta = pos[1] - baseSnapHeight;
410 return Math.AbsFloat(delta) < m_fVerticalSnapLimit;
417 bool CanUnsnap(
float verticalDelta)
419 if (!IsSnappedVertically())
424 return verticalDelta > 0;
430 switch (verticalMode)
438 trace =
new TraceParam();
444 return m_aLocalOffset[3][1];
451 return m_bCanMoveInRoot;
457 void ShowAsDisabled(
bool disable =
true)
459 if (disable == m_bPreviewDisabled)
462 m_bPreviewDisabled = disable;
464 ResourceName material = m_PreviewMaterial;
466 material = m_DisabledPreviewMaterial;
477 if (m_LastPreviewState == state)
480 ResourceName material;
485 material = m_PreviewMaterial;
491 material = m_DisabledPreviewMaterial;
497 material = m_WarningPreviewMaterial;
512 m_LastPreviewState = state;
527 if (target ==
m_Target && isDelegate == m_bTargetDelegate)
533 if (!CanInteractWith(target, targetSnap, targetInteraction, isDelegate))
540 m_bTargetSnap = targetSnap;
541 m_TargetInteraction = targetInteraction;
542 m_bTargetDelegate = isDelegate;
548 m_fTargetRotationStep = slotEntity.GetRotationStep();
550 m_fTargetRotationStep = -1;
559 m_TargetInteraction = 0;
561 Event_OnTargetChange.Invoke(target);
578 bool isTargetDestroyed = target.IsDestroyed();
581 if (m_LayerManager && m_LayerManager.IsEditingLayersEnabled())
590 if (m_bORInteraction)
601 if (!isTargetDestroyed && (!editableChild || !editableChild.IsDestroyed()))
607 if (!editableChild || editableChild.GetPlayerID() == 0)
610 if (m_StateManager && m_StateManager.GetState() ==
EEditorState.PLACING)
613 if (m_Interaction.CanSetParent(target, interactionFlags))
631 if (!isTargetDestroyed && (!editableChild || !editableChild.IsDestroyed()))
637 if (!editableChild || editableChild.GetPlayerID() == 0)
640 if (m_StateManager && m_StateManager.GetState() ==
EEditorState.PLACING)
643 if (!m_Interaction.CanSetParent(target, interactionFlags))
667 return m_TargetInteraction;
673 bool IsSnappedToTarget()
675 return m_bTargetSnap;
689 string GetActionContext()
691 return m_sActionContext;
707 return m_bIsChange || m_bIsFixedPosition ||
m_Target;
715 return m_bIsRotating;
721 bool IsFixedPosition()
723 return m_bIsFixedPosition;
729 ResourceName GetSlotPrefab()
737 void SetIsMovingVertically(
bool isMovingVertically)
739 m_bIsMovingVertically = isMovingVertically;
745 bool IsMovingVertically()
747 return m_bIsMovingVertically;
753 void SetIsRotating(
bool isRotating)
755 m_bIsRotating = isRotating;
770 array<IEntity> GetExcludeArray()
781 ScriptInvoker GetOnPreviewCreate()
783 return Event_OnPreviewCreate;
789 ScriptInvoker GetOnPreviewDelete()
791 return Event_OnPreviewDelete;
797 ScriptInvoker GetOnPreviewChange()
799 return Event_OnPreviewChange;
805 ScriptInvoker GetOnTargetChange()
807 return Event_OnTargetChange;
813 ScriptInvoker GetOnWaitingPreviewCreate()
815 return Event_OnWaitingPreviewCreate;
821 ScriptInvoker GetOnVerticalModeChange()
823 return Event_OnVerticalModeChange;
829 ScriptInvoker GetOnVerticalSnapChange()
831 return Event_OnVerticalSnapChange;
834 void InitTransform(vector transform[4])
836 m_vTransform = transform;
839 Math3D.MatrixNormalize(m_vTransform);
841 SetPreviewHeight(transform[3]);
861 EntitySpawnParams spawnParams =
new EntitySpawnParams();
862 Math3D.MatrixCopy(m_vTransform, spawnParams.Transform);
864 m_bInstantTransformation =
true;
866 m_EntityType = pivot.GetEntityType();
867 m_Interaction = pivot.GetEntityInteraction();
877 vector localOffsetPos = m_aLocalOffset[3];
878 if (pivot.GetPos(localOffsetPos))
880 vector pivotTransform[4];
881 pivot.GetOwner().GetWorldTransform(pivotTransform);
882 Math3D.MatrixInvMultiply4(m_vTransform, pivotTransform, pivotTransform);
883 m_aLocalOffset[3] = -pivotTransform[3];
889 SetPreviewHeight(m_vTransform[3]);
890 ResetPreviewTransform();
901 SCR_BasePreviewEntity CreatePreview(ResourceName prefab, notnull array<vector> offsets, vector initTransform[4] = {})
907 Resource prefabResource = Resource.Load(prefab);
908 EntitySpawnParams spawnParams =
new EntitySpawnParams();;
918 if (m_bIsFixedPosition)
922 entitySource.Get(
"coords", coords);
923 if (coords.LengthSq() != 0)
925 spawnParams.Transform[3] = coords;
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;
933 else if (initTransform[3] == vector.Zero)
936 vector angles = Vector(Math3D.MatrixToAngles(m_vTransform)[0], 0, 0);
937 Math3D.AnglesToMatrix(angles, m_vTransform);
938 m_vTransform[3] = vector.Zero;
939 spawnParams.Transform = m_vTransform;
943 spawnParams.Transform = initTransform;
946 if (offsets.Count() > 1)
952 for (
int i = 0, count = offsets.Count(); i < count; i++)
961 entry.CopyFrom(sourceEntry);
962 entries.Insert(entry);
964 entry.m_vPosition = offsets[i];
975 m_fHeightTerrain = 0;
991 previewEntity.GetWorldTransform(m_vTransform);
993 Event_OnTargetChange.Invoke(
null);
995 Event_OnPreviewDelete.Invoke(previewEntity);
996 delete previewEntity;
999 m_bIsHeightSet =
false;
1000 m_bIsFixedPosition =
false;
1001 m_bIsRotating =
false;
1002 m_bPreviewDisabled =
false;
1004 m_TargetInteraction = 0;
1006 m_aLocalOffset[3] = vector.Zero;
1016 Resource previewResource = Resource.Load(m_WaitingEntityPrefab);
1017 if (!previewResource || !previewResource.IsValid())
1020 EntitySpawnParams spawnParams =
new EntitySpawnParams();
1023 Event_OnWaitingPreviewCreate.Invoke(previewEntity);
1024 return previewEntity;
1027 protected vector LerpTranslation(vector currentPos, vector targetPos,
float timeSlice)
1029 return vector.Lerp(currentPos, targetPos, Math.Min(timeSlice * m_fPreviewTranslationInertia, 1));
1031 protected void LerpAngles(vector currentAngles, out vector targetAngles,
float timeSlice)
1034 targetAngles[0] =
SCR_Math.LerpAngle(currentAngles[1], targetAngles[0], Math.Min(timeSlice * m_fPreviewRotationInertia, 1));
1037 protected void OnUserSettingsChanged()
1039 BaseContainer editorSettings =
GetGame().GetGameUserSettings().GetModule(
"SCR_EditorSettings");
1040 if (!editorSettings)
1044 editorSettings.Get(
"m_PreviewVerticalSnap", value);
1045 SetVerticalSnap(value);
1046 editorSettings.Get(
"m_PreviewVerticleMode", value);
1047 SetVerticalMode(value);
1051 override void EOnEditorDebug(array<string> debugTexts)
1055 debugTexts.Insert(
"Vertical Snap: " + m_bIsVerticalSnap);
1056 debugTexts.Insert(
"Height ASL: " + m_fHeightSea);
1057 debugTexts.Insert(
"Height ATL: " + m_fHeightTerrain);
1061 debugTexts.Insert(
string.Format(
"Preview Target: %1",
m_Target));
1062 debugTexts.Insert(
string.Format(
"Preview Target Interaction: %1",
typename.EnumToString(
EEditableEntityInteraction, m_TargetInteraction)));
1065 override void EOnFrame(IEntity owner,
float timeSlice)
1068 int verticalMode = 1 << DiagMenu.GetValue(
SCR_DebugMenuID.DEBUGUI_EDITOR_TRANSFORM_VERTICAL_MODE);
1069 if (verticalMode != m_VerticalMode)
1071 SetVerticalMode(verticalMode);
1073 if (DiagMenu.GetValue(
SCR_DebugMenuID.DEBUGUI_EDITOR_TRANSFORM_VERTICAL_SNAP) != m_bIsVerticalSnap)
1075 SetVerticalSnap(DiagMenu.GetValue(
SCR_DebugMenuID.DEBUGUI_EDITOR_TRANSFORM_VERTICAL_SNAP));
1079 override void EOnEditorActivate()
1081 SetEventMask(
GetOwner(), EntityEvent.FRAME);
1083 ArmaReforgerScripted game =
GetGame();
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);
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);
1099 override void EOnEditorDeactivate()
1103 override void EOnEditorInit()
1105 ArmaReforgerScripted game =
GetGame();
1109 GenericWorldEntity worldEntity = game.GetWorldEntity();
1113 m_bHasTerrain = worldEntity.GetTerrain(0, 0) !=
null;
1115 m_fPreviewTranslationInertia = 1 / Math.Max(m_fPreviewTranslationInertia, 0.001);
1116 m_fPreviewRotationInertia = 1 / Math.Max(m_fPreviewRotationInertia, 0.001);
1118 BaseContainer editorSettings =
GetGame().GetGameUserSettings().GetModule(
"SCR_EditorSettings");
1122 OnUserSettingsChanged();
1123 GetGame().OnUserSettingsChangedInvoker().Insert(OnUserSettingsChanged);
1126 m_iHeightIndicatorColor = m_HeightIndicatorColor.PackToInt();
1128 Math3D.MatrixIdentity3(m_aLocalOffset);
1131 override void OnDelete(IEntity owner)
1134 GetGame().OnUserSettingsChangedInvoker().Remove(OnUserSettingsChanged);