Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
SCR_JointBaseEntity.c
Go to the documentation of this file.
1[EntityEditorProps(category: "GameBase/Joints", description: "Physics joint base", sizeMin: "-0.05 -0.05 -0.05", sizeMax: "0.05 0.05 0.05", color: "0 0 255 255")]
2class SCR_JointBaseEntityClass: GenericEntityClass
3{
4};
5
6//------------------------------------------------------------------------------------------------
10//------------------------------------------------------------------------------------------------
11class SCR_JointBaseEntity: GenericEntity
12{
13 [Attribute("-1", UIWidgets.ComboBox, "Snap joint to bone in parent (one-time)", "")]
14 int SNAP_TO_PARENT_BONE;
15 //[Attribute("-1", UIWidgets.ComboBox, "Snap child to joint by bone in child (one-time)", "")]
16 //int SNAP_CHILD_BY_JOINT;
17 [Attribute("1", UIWidgets.CheckBox, "Whether to create collision blocker between parent and child" )]
18 bool m_CollisionBlocker;
19
20 IEntity m_JointParent = null;
21 IEntity m_JointChild = null;
22 SCR_JointDummyHolderEntity m_JointDummy = null;
23
24 PhysicsJoint m_Joint = null;
25
26 // TODO:
27 // - Do stress and breakage (in engine)
28 // - SNAP_CHILD_BY_JOINT does not work! After setting of the property, child is NULL!
29
30 //------------------------------------------------------------------------------------------------
31 void MoveJointToParentBone()
32 {
33 if (!m_JointParent)
34 return;
35
36 if (SNAP_TO_PARENT_BONE <= 0)
37 return;
38
39 vector boneMat[4];
40
41 m_JointParent.GetAnimation().GetBoneMatrix(SNAP_TO_PARENT_BONE, boneMat);
42
43 vector angles = Math3D.MatrixToAngles(boneMat);
44 vector pos = boneMat[3];
45
46 // TODO: Deselect or at least reselect joint after doing following steps
47 #ifdef WORKBENCH
48 WorldEditorAPI worldEditorAPI = _WB_GetEditorAPI();
49 worldEditorAPI.BeginEntityAction("Move to parent bone", "");
50 worldEditorAPI.ClearEntitySelection();
51
52 IEntitySource src = _WB_GetEditorAPI().EntityToSource(this);
53 worldEditorAPI.SetVariableValue(src, null, "coords", pos.ToString(false));
54 worldEditorAPI.SetVariableValue(src, null, "angles", string.Format("%1 %2 %3", angles[1], angles[0], angles[2]));
55 worldEditorAPI.SetVariableValue(src, null, "SNAP_TO_PARENT_BONE", "-1");
56 worldEditorAPI.EndEntityAction("Move to parent bone");
57 #endif
58 }
59
60 //------------------------------------------------------------------------------------------------
61 /*void MoveChildToJointByBone()
62 {
63 Print(m_JointChild);
64 if (!m_JointChild)
65 return;
66
67 if (SNAP_CHILD_BY_JOINT <= 0)
68 return;
69
70 WorldEditorAPI worldEditorAPI = _WB_GetEditorAPI();
71
72 // Special case (origin)
73 if (SNAP_CHILD_BY_JOINT == 999999)
74 {
75 // TODO: Deselect or at least reselect joint after doing following steps
76 worldEditorAPI.BeginEntityAction("Move child to joint by bone", "");
77 worldEditorAPI.ClearEntitySelection();
78 worldEditorAPI.SetVariableValue(m_JointChild, null, "coords", "0 0 0");
79 worldEditorAPI.SetVariableValue(m_JointChild, null, "angles", "0 0 0");
80 worldEditorAPI.SetVariableValue(this, null, "SNAP_CHILD_BY_JOINT", "-1");
81 worldEditorAPI.EndEntityAction("Move child to joint by bone");
82 }
83 else
84 {
85 vector boneMat[4], baseMat[4], endBoneMat[4];
86
87 GetBoneMatrix(m_JointChild, SNAP_CHILD_BY_JOINT, boneMat);
88 Math3D.MatrixIdentity4(baseMat);
89 Math3D.MatrixInvMultiply4(baseMat, boneMat, endBoneMat);
90
91
92 vector angles = Math3D.MatrixToAngles(endBoneMat);
93 vector pos = endBoneMat[3];
94
95 // TODO: Deselect or at least reselect joint after doing following steps
96 worldEditorAPI.BeginEntityAction("Move child to joint by bone", "");
97 worldEditorAPI.ClearEntitySelection();
98 worldEditorAPI.SetVariableValue(m_JointChild, null, "coords", pos.ToString(false));
99 worldEditorAPI.SetVariableValue(m_JointChild, null, "angles", string.Format("%1 %2 %3", angles[1], angles[0], angles[2]));
100 worldEditorAPI.SetVariableValue(this, null, "SNAP_CHILD_BY_JOINT", "-1");
101 worldEditorAPI.EndEntityAction("Move child to joint by bone");
102 }
103 }*/
104
105 //------------------------------------------------------------------------------------------------
106 #ifdef WORKBENCH
107 //------------------------------------------------------------------------------------------------
108 override array<ref ParamEnum> _WB_GetUserEnums(string varName, IEntitySource src)
109 {
110 if (varName == "SNAP_TO_PARENT_BONE" && m_JointParent)
111 return SCR_Global.GetBonesAsParamEnums(m_JointParent);
112 /*if (varName == "SNAP_CHILD_BY_JOINT" && m_JointChild)
113 {
114 array<ref ParamEnum> retEnums = SCR_Global.GetBonesAsParamEnums(m_JointChild);
115 retEnums.Insert(new ParamEnum("ORIGIN", "999999", "")); // Always have ORIGIN as an option
116 return retEnums;
117 }*/
118
119 return null;
120 }
121
122 //------------------------------------------------------------------------------------------------
124 {
125 return EEntityFrameUpdateSpecs.CALL_WHEN_ENTITY_VISIBLE;
126 }
127
128 //------------------------------------------------------------------------------------------------
129 override void _WB_AfterWorldUpdate(float timeSlice)
130 {
131 if (m_JointParent)
132 Shape.CreateArrow(m_JointParent.GetOrigin(), GetOrigin(), 0.05, ARGB(255, 128, 128, 0), ShapeFlags.ONCE|ShapeFlags.NOZBUFFER);
133 if (m_JointChild)
134 Shape.CreateArrow(GetOrigin(), m_JointChild.GetOrigin(), 0.05, ARGB(255, 128, 128, 0), ShapeFlags.ONCE|ShapeFlags.NOZBUFFER);
135 DebugDisplay();
136 }
137 #endif
138
139 //------------------------------------------------------------------------------------------------
140 void DestroyJoint()
141 {
142 if (m_Joint)
143 {
144 // TODO: Remove this once deletion of joints is ensured before physics scene deletion
145 if (m_JointParent || m_JointChild)
146 m_Joint.Destroy();
147 }
148 m_Joint = null;
149
150 if (m_JointDummy)
151 delete m_JointDummy;
152 m_JointDummy = null;
153 }
154
155 //------------------------------------------------------------------------------------------------
156 void TryCreateJoint(bool showErrors)
157 {
158 DestroyJoint();
159
160 if (!m_JointParent && !m_JointChild)
161 {
162 if (showErrors)
163 {
164 Print("JointHingeEntity::CreateJoint: ERROR - cannot create joint, no parent and no child!");
165 CreateFailedJointDebug(128, 255, 0, 0);
166 }
167 return;
168 }
169
170 Physics parentPhysics = null;
171 Physics childPhysics = null;
172 if (m_JointParent)
173 parentPhysics = m_JointParent.GetPhysics();
174 if (m_JointChild)
175 childPhysics = m_JointChild.GetPhysics();
176 if (!parentPhysics && !childPhysics)
177 {
178 if (showErrors)
179 {
180 Print("JointHingeEntity::CreateJoint: ERROR - cannot create joint, neither parent nor child have physics!");
181 CreateFailedJointDebug(128, 255, 0, 0);
182 }
183 return;
184 }
185
186 if (parentPhysics && childPhysics && !parentPhysics.IsDynamic() && !childPhysics.IsDynamic())
187 {
188 if (showErrors)
189 {
190 Print("JointHingeEntity::CreateJoint: ERROR - cannot create joint, neither parent nor child are dynamic!");
191 CreateFailedJointDebug(128, 255, 0, 0);
192 }
193 return;
194 }
195
196 IEntity parent = m_JointParent;
197 IEntity child = m_JointChild;
198
199 // Nullify parent
200 if (parent && parentPhysics && !parentPhysics.IsDynamic())
201 parent = null;
202 if (child && childPhysics && !childPhysics.IsDynamic())
203 child = null;
204
205 if (showErrors && !parent && !child)
206 {
207 Print("JointHingeEntity::CreateJoint: ERROR - cannot create joint, no connected dynamic entities!");
208 CreateFailedJointDebug(128, 255, 128, 0);
209 }
210
211 if (!parent || !child) // We have no parent or child, so create a dummy joint attachment point
212 {
214
215 vector jointDummyMat[4];
216 GetTransform(jointDummyMat);
217 m_JointDummy.SetDummyTransform(jointDummyMat);
218
219 float mass = 0;
220 if (parent)
221 mass = parentPhysics.GetMass();
222 else
223 mass = childPhysics.GetMass();
224
225 m_JointDummy.GetPhysics().SetMass(mass * 1000);
226
227
228 // Link the static dummy point
229 if (parent)
230 child = m_JointDummy;
231 else
232 parent = m_JointDummy;
233 }
234
235 // Ensure static entity is the child (must be 'ent2' for the API)
236 if (!parentPhysics || !parentPhysics.IsDynamic())
237 {
238 IEntity tmp = parent;
239 parent = child;
240 child = tmp;
241 }
242
243 // First get matrices of parent, child and joint
244 vector parentMat[4], childMat[4], jointMat[4];
245 parent.GetTransform(parentMat);
246 child.GetTransform(childMat);
247 GetTransform(jointMat);
248
249 // Rotate the joint if necessary (inout function)
250 RotateJoint(jointMat);
251
252 // Now get local matrices of parent and child relative to joint
253 vector jointMatParentLocal[4], jointMatChildLocal[4];
254 Math3D.MatrixInvMultiply4(parentMat, jointMat, jointMatParentLocal);
255 Math3D.MatrixInvMultiply4(childMat, jointMat, jointMatChildLocal);
256
257 // Subtract center of mass positions
258 if (parentPhysics)
259 jointMatParentLocal[3] = jointMatParentLocal[3] - parentPhysics.GetCenterOfMass();
260 else
261 jointMatParentLocal[3] = jointMatParentLocal[3];
262 if (childPhysics)
263 jointMatChildLocal[3] = jointMatChildLocal[3] - childPhysics.GetCenterOfMass();
264 else
265 jointMatChildLocal[3] = jointMatChildLocal[3];
266
267 // Create the joint
268 CreateJoint(parent, child, jointMatParentLocal, jointMatChildLocal);
269 }
270
271 //------------------------------------------------------------------------------------------------
272 void RotateJoint(inout vector jointMat[4])
273 {
274 }
275
276 //------------------------------------------------------------------------------------------------
277 void CreateJoint(IEntity parent, IEntity child, vector jointMat1[4], vector jointMat2[4])
278 {
279 }
280
281 //------------------------------------------------------------------------------------------------
282 void CreateFailedJointDebug(int a, int r, int g, int b)
283 {
284 int color = ARGB(a, r, g, b);
285 vector myPos = GetOrigin();
286 Shape.Create(ShapeType.BBOX, color, ShapeFlags.NOOUTLINE|ShapeFlags.NOZBUFFER|ShapeFlags.TRANSP, "-0.1 0.2 -0.1" + myPos, "0.1 1.2 0.1" + myPos);
287 Shape.Create(ShapeType.BBOX, color, ShapeFlags.NOOUTLINE|ShapeFlags.NOZBUFFER|ShapeFlags.TRANSP, "-0.1 -0.1 -0.1" + myPos, "0.1 0.1 0.1" + myPos);
288 }
289
290 //------------------------------------------------------------------------------------------------
291 void DebugDisplay()
292 {
293 }
294
295 //------------------------------------------------------------------------------------------------
296 override event void EOnInit(IEntity owner)
297 {
298 m_JointChild = GetChildren();
299
300 TryCreateJoint(GetGame().GetGameStarted());
301
302 MoveJointToParentBone();
303 //MoveChildToJointByBone();
304 }
305
306 //------------------------------------------------------------------------------------------------
307 void SCR_JointBaseEntity(IEntitySource src, IEntity parent)
308 {
309 m_JointParent = parent;
310
312 }
313
314 //------------------------------------------------------------------------------------------------
315 void ~SCR_JointBaseEntity()
316 {
317 DestroyJoint();
318 }
319};
bool GetGameStarted()
Definition game.c:477
ArmaReforgerScripted GetGame()
Definition game.c:1398
ref array< string > angles
IEntity SpawnEntity(ResourceName entityResourceName, notnull IEntity slotOwner)
enum SCR_ECompassType EntityEditorProps(category:"GameScripted/Gadgets", description:"Compass", color:"0 0 255 255")
Prefab data class for compass component.
event void _WB_AfterWorldUpdate(float timeSlice)
Called after updating world in Workbench. The entity must be visible in frustum, selected or named....
proto external WorldEditorAPI _WB_GetEditorAPI()
This returns world editor API, which is safe to use from editor events bellow.
event int _WB_GetAfterWorldUpdateSpecs(IEntitySource src)
Called after _WB_OnInit or also later when editor needs to know whether _WB_AfterWorldUpdate needs to...
event array< ref ParamEnum > _WB_GetUserEnums(string varName, IEntitySource src)
Possibility to get variable value choices dynamically. Do not call editor API here!
void IEntity(IEntitySource src, IEntity parent)
protected script Constructor
proto external EntityEvent SetEventMask(EntityEvent e)
proto external vector GetOrigin()
proto external IEntity GetChildren()
proto external void GetTransform(out vector mat[])
Instance of created debug visualizer.
Definition Shape.c:14
proto void Print(void var, LogLevel level=LogLevel.NORMAL)
Prints content of variable to console/log.
ShapeType
Definition ShapeType.c:13
ShapeFlags
Definition ShapeFlags.c:13
SCR_FieldOfViewSettings Attribute
EntityEvent
Various entity events.
Definition EntityEvent.c:14
proto int ARGB(int a, int r, int g, int b)