Tanoda
MoveAction.cs
Go to the documentation of this file.
1using System;
2using System.Collections;
3using System.Globalization;
4using System.Linq;
5using System.Runtime.Serialization;
6using JetBrains.Annotations;
7using NaughtyAttributes;
8
9using UnityEngine;
10using UnityEngine.UI;
11
12#if !UNITY_WEBGL
13using Valve.VR.InteractionSystem;
14
15#endif
16
17public class MoveAction : ActionObject, ISerializable
18{
19#if !UNITY_WEBGL
20 private Hand[] playerHands;
21 private OffsetHolder offsetHolder;
22 private GameObject handGO;
23 private float minDistance;
24 private float prevDistance;
25 private bool onTheLine;
26#endif
27 public InputField[] posInputs = new InputField[3];
28 public InputField[] rotInputs = new InputField[3];
29 public InputField ttmInput;
31 public float timeToMove = 1.0f;
32 public Toggle toggle;
33 internal bool HandMove;
34 protected GameObject cachedGO;
35
36#if !UNITY_WEBGL
37 public new void Update()
38 {
39 base.Update();
40 if (base.isInFieldOfView(cachedGO)) base.actionRecognized = true;
41 if (Player.instance == null) return;
42
43 playerHands = Player.instance.hands;
44 if (playerHands != null)
45 {
46 //if (cachedGO.GetComponent<OffsetHolder>())
47 //{
48 // offsetHolder = cachedGO.GetComponent<OffsetHolder>();
49 //}
50 //else
51 //{
52 if (cachedGO != null)
53 {
54 offsetHolder = cachedGO.GetComponentInParent<OffsetHolder>();
55 }
56
57 //}
58 float d = float.MaxValue;
59 float handInteractDistance = 0.1f;
60 if (offsetHolder != null)
61 {
62 foreach (var hand in playerHands)
63 {
64 var currentDistance = Vector3.Distance(hand.transform.position, offsetHolder.transform.TransformPoint(offsetHolder.Offset));
65 if (currentDistance < d && currentDistance <= handInteractDistance)
66 {
67 d = currentDistance;
68 handPosition = hand.transform.position;
69 handGO = hand.objectAttachmentPoint.gameObject;
70 }
71
72 }
73 }
74
75 }
76
77 }
78#endif
79 public override void Triggered(string id)
80 {
81 if (id == GetInput()) return;
82 base.Triggered(id);
83 cachedGO = GetInputGO();
84 var lerp = true;
85
86 if (timeToMove == 0.0f)
87 if (ttmInput != null)
88 {
90 }
91 if (timeToMove == 0.0f)
92 {
93 timeToMove = 0.1f;
94 }
95#if !UNITY_WEBGL
96 if (HandMove)
97 {
98 //PreviewHand.Instance.EnterOffsetEditor(cachedGO, action, targetPosition, targetRotation);
99
100 StartCoroutine(SimpleFollowHand());
101 //PROMO:
102 //StartCoroutine(csítesMoveAzAMTSre());
103 }
104 else
105#endif
106 {
107 if (lerp)
108 StartCoroutine(LerpPos());
109 else
111 }
112
113
114 if (!lerp)
115 TriggerOutput(outPuts[0].name);
116#if !UNITY_WEBGL
117 statusImg.color = Color.green;
118#endif
119 }
120
121 public void MoveWithHand(bool newValue)
122 {
123 HandMove = newValue;
124 }
125
126 private IEnumerator LerpPos()
127 {
128 var lh = 0.0f;
129 while (lh < timeToMove)
130 {
131 lh += Time.deltaTime;
132 yield return new WaitForEndOfFrame();
133 if (!cachedGO)
134 cachedGO = GetInputGO();
135 cachedGO.transform.localPosition = Vector3.Lerp(originalPosition, targetPosition, lh / timeToMove);
136 cachedGO.transform.localEulerAngles = Vector3.Lerp(Macro.ClampAngle(originalRotation),
138 }
139
140 TriggerOutput(outPuts[0].name);
141 yield return null;
142 }
143
144 [Button]
145 private void Teszt()
146 {
147 var target = Quaternion.Angle(Quaternion.Euler(originalRotation), Quaternion.Euler(targetRotation));
148 Debug.Log(target);
149 }
150
151#if !UNITY_WEBGL
152
153//PROMO
154 private IEnumerator csítesMoveAzAMTSre()
155 {
156 var dist = 0.1f;
157 if (name == "0c4ac7d9-ed60-458a-a249-0a1833f8b1ee" || name == "a5c19db4-6286-4e8a-b735-781a1daeea35" || name == "134044ab-e1be-4597-be1d-6345633424ab")
158 {
159 dist = 0.75f;
160 }
161 Vector3 handStartPos = default;
162 var startLocalRot = cachedGO.transform.localEulerAngles;
163 var startLocalPos = cachedGO.transform.localPosition;
164 while (true)
165 {
166 if (Player.instance != null && handStartPos == default)
167 {
168 float d = float.MaxValue;
169 foreach (var hand in playerHands)
170 {
171 if (!hand.objectAttachmentPoint) continue;
172 if (!hand.gameObject.activeInHierarchy) continue;
173 var currentDistance = Vector3.Distance(hand.objectAttachmentPoint.position, cachedGO.transform.position);
174 if (currentDistance < d)
175 {
176 d = currentDistance;
177 handGO = hand.objectAttachmentPoint.gameObject;
178 }
179 }
180 if (handStartPos == default && handGO != null)
181 {
182 handStartPos = handGO.transform.position;
183 }
184 }
185 if (!handGO)
186 {
187 yield return null;
188 continue;
189 }
190 var handdistance = Vector3.Distance(handGO.transform.position, handStartPos);
191 var percent = handdistance / dist;
192 //if (percent > 1) percent = 1 + (1 - percent);
193
194 cachedGO.transform.localPosition = Vector3.Lerp(startLocalPos, targetPosition, percent);
195 cachedGO.transform.localEulerAngles = Vector3.Lerp(Macro.ClampAngle(startLocalRot),
197 yield return null;
198 if (percent >= 1)
199 {
201 TriggerOutput(outPuts[0].name);
202 yield break;
203 }
204 }
205 }
206//ENDPROMO
207
208
209 private IEnumerator SimpleFollowHand()
210 {
211 Transform OriginalParent = cachedGO.transform.parent;
212 Vector3 targetWorldPos = OriginalParent.TransformPoint(targetPosition);
213 var startPos = cachedGO.transform.position;
214 var startLocalPos = cachedGO.transform.localPosition;
215 var startRot = cachedGO.transform.rotation;
216 var startLocalRot = cachedGO.transform.localEulerAngles;
217 Vector3 handStartPos = default;
219 {
220 while (Mathf.Abs(Vector3.Distance(cachedGO.transform.localPosition, targetPosition)) > 0.02)
221 {
222 if (Player.instance != null)
223 {
224 float d = float.MaxValue;
225 foreach (var hand in playerHands)
226 {
227 if (!hand.objectAttachmentPoint) continue;
228 if (!hand.gameObject.activeInHierarchy) continue;
229 var currentDistance = Vector3.Distance(hand.objectAttachmentPoint.position, cachedGO.transform.position);
230 if (currentDistance < d)
231 {
232 d = currentDistance;
233 handGO = hand.objectAttachmentPoint.gameObject;
234 }
235 }
236 if (handStartPos == default && handGO != null)
237 {
238 handStartPos = handGO.transform.position;
239 }
240 }
241 if (!handGO)
242 {
243 yield return null;
244 continue;
245 }
246 var handdistance = Vector3.Distance(handGO.transform.position, handStartPos) * 0.5f;
247 var dist = Vector3.Distance(startPos, targetWorldPos);
248
249 var percent = handdistance / dist;
250 if (percent > 1) percent = 1 + (1 - percent);
251
252 cachedGO.transform.localPosition = Vector3.Lerp(startLocalPos, targetPosition, percent);
253 cachedGO.transform.localEulerAngles = Vector3.Lerp(Macro.ClampAngle(startLocalRot),
255 yield return null;
256 }
257 }
259 {
260 var target = Quaternion.Angle(Quaternion.Euler(startLocalRot), Quaternion.Euler(targetRotation));
261 var current = 0f;
262 var startHandRot = Quaternion.identity;
263 var firstSave = true;
264
265 GameObject helper = new GameObject();
266 helper.transform.position = cachedGO.transform.position;
267 helper.transform.rotation = cachedGO.transform.rotation;
268
269 while (Mathf.Abs(target - current) > 3) //TODO offsetholderer positionból számítás
270 {
271 if (Player.instance != null)
272 {
273 float d = float.MaxValue;
274 foreach (var hand in playerHands)
275 {
276
277 if (!hand.objectAttachmentPoint) continue;
278 if (!hand.gameObject.activeInHierarchy) continue;
279 var currentDistance = Vector3.Distance(hand.objectAttachmentPoint.position, cachedGO.transform.position);
280 if (currentDistance < d)
281 {
282 d = currentDistance;
283 handGO = hand.objectAttachmentPoint.gameObject;
284 }
285 }
286 if (handStartPos == default && handGO != null)
287 {
288 handStartPos = handGO.transform.position;
289 }
290 }
291 if (!handGO)
292 {
293 yield return null;
294 continue;
295 }
296 helper.transform.LookAt(handGO.transform);
297 if (firstSave || startHandRot.eulerAngles == Vector3.zero)
298 {
299 startHandRot = helper.transform.rotation;
300 firstSave = false;
301 }
302 current = Quaternion.Angle(startHandRot, helper.transform.rotation);
303 current *= 0.99f;
304
305 //Debug.LogError($"startHandRot: {startHandRot.eulerAngles}, helper: {helper.transform.eulerAngles}%, current: {current}");
306
307 var percent = current / target;
308 if (percent > 1) percent = 1 + (1 - percent);
309
310 //Debug.LogError($"target: {target}, current: {current}, percent: {percent}%");
311 cachedGO.transform.localPosition = Vector3.Lerp(startLocalPos, targetPosition, percent);
312 cachedGO.transform.localEulerAngles = Vector3.Lerp(Macro.ClampAngle(startLocalRot),
314
315 yield return null;
316 }
317 Destroy(helper);
318 }
319 cachedGO.transform.SetParent(OriginalParent, true);
321 TriggerOutput(outPuts[0].name);
322 }
323
324 public IEnumerator FollowHand()
325 {
326 Vector3 targetWorldPos = GILES.pb_Scene.instance.transform.TransformPoint(targetPosition);
327 GameObject helper = new GameObject();
328 Transform OriginalParent = cachedGO.transform.parent;
330 {
331 yield return null;
332 helper.transform.SetParent(cachedGO.transform, true);
333 yield return null;
334 helper.transform.localPosition = Vector3.zero;
335 yield return null;
336 helper.transform.forward = (targetPosition - originalPosition).normalized;
337 yield return null;
338 helper.transform.SetParent(cachedGO.transform.parent, true);
339 yield return null;
340 cachedGO.transform.SetParent(helper.transform, true);
341 yield return null;
342
343 var origLocal = helper.transform.localPosition;
344 while (Mathf.Abs(Vector3.Distance(cachedGO.transform.position, targetWorldPos)) > 0.02)
345 {
346 helper.transform.position = handPosition;
347 origLocal.z = helper.transform.localPosition.z;
348 helper.transform.localPosition = origLocal;
349 if (!IsPointBetween(originalPosition, targetPosition, origLocal))
350 {
351 var ap = Vector3.Distance(targetPosition, origLocal);
352 var bp = Vector3.Distance(originalPosition, origLocal);
353 helper.transform.localPosition = ap < bp ? targetPosition : originalPosition;
354 }
355 yield return null;
356 }
357 }
359 {
360 var target = Quaternion.Angle(Quaternion.Euler(originalRotation), Quaternion.Euler(targetRotation));
361 helper.transform.position = cachedGO.transform.position;
362 helper.transform.rotation = cachedGO.transform.rotation;
363 var current = Quaternion.Angle(Quaternion.Euler(originalRotation), helper.transform.rotation);
364
365
366 while (Mathf.Abs(target - current) > 1) //TODO offsetholderer positionból számítás
367 {
368 var worldOffsetPos = offsetHolder.transform.TransformPoint(offsetHolder.Offset);
369 helper.transform.LookAt(handGO.transform);
370 current = Quaternion.Angle(Quaternion.Euler(originalRotation), helper.transform.rotation);
371 }
372
373 }
374
375 cachedGO.transform.SetParent(OriginalParent, true);
376 Destroy(helper);
378 TriggerOutput(outPuts[0].name);
379
380 }
381
382 bool IsOnTheLine(Vector3 XPoint, Vector3 YPoint, Vector3 handPoint)
383 {
384
385 if (Macro.DistancePointLine(handPoint, XPoint, YPoint) < 0.1f/* && Mathf.Abs(Vector3.Distance(XPoint, handPoint)) <= Mathf.Abs(Vector3.Distance(XPoint, YPoint)) && Mathf.Abs(Vector3.Distance(YPoint, handPoint)) <= Mathf.Abs(Vector3.Distance(XPoint, YPoint))*/)
386 {
387 onTheLine = true;
388 }
389 else
390 {
391 onTheLine = false;
392 }
393 return onTheLine;
394 }
395 bool IsCBetweenAB(Vector3 A, Vector3 B, Vector3 C)
396 {
397 return Vector3.Dot((B - A).normalized, (C - B).normalized) < 0f && Vector3.Dot((A - B).normalized, (C - A).normalized) < 0f;
398 }
399 bool IsPointBetween(Vector3 a, Vector3 b, Vector3 point)
400 {
401 var ap = Vector3.Distance(point, a);
402 var bp = Vector3.Distance(point, b);
403 var ab = Vector3.Distance(a, b);
404 return Mathf.Approximately(ap + bp, ab);
405 }
406 float distanceFromLine(Vector3 A, Vector3 B, Vector3 C)
407 {
408 Ray ray = new Ray(A, B);
409 float distance = Vector3.Cross(ray.direction, C - ray.origin).magnitude;
410
411
412 return distance;
413 }
414
415
416#endif
417 public void onTtmChanged(string value)
418 {
419 try
420 {
421 var ci = CultureInfo.CurrentCulture;
422 var nfi = ci.NumberFormat;
423 ttmInput.text = ttmInput.text.Replace(',', nfi.CurrencyDecimalSeparator[0]);
424 ttmInput.text = ttmInput.text.Replace('.', nfi.CurrencyDecimalSeparator[0]);
425 var single = Convert.ToSingle(ttmInput.text, ci);
426 ttmInput.text = single.ToString("F2");
427 timeToMove = single;
428 }
429 catch (Exception)
430 {
431 Debug.LogWarning("not parsable number(?) in timeToMove inputfield!");
432
433 // restore last valid numbers
434 ttmInput.text = timeToMove.ToString("F2");
435 }
436 }
437
438 public void StartPosition()
439 {
440 if (!cachedGO)
441 cachedGO = GetInputGO();
442 if (!cachedGO) return;
443
444 cachedGO.transform.localPosition = originalPosition;
445 cachedGO.transform.localEulerAngles = originalRotation;
446 }
447
448 public void FinalPosition()
449 {
450 if (!cachedGO)
451 cachedGO = GetInputGO();
452 if (!cachedGO) return;
453
454 cachedGO.transform.localPosition = targetPosition;
455 cachedGO.transform.localEulerAngles = targetRotation;
456 }
457
459 {
460 if (!cachedGO)
461 cachedGO = GetInputGO();
462 if (!cachedGO) return;
463
464 posInputs[0].text = cachedGO.transform.localPosition[0].ToString("F5");
465 posInputs[1].text = cachedGO.transform.localPosition[1].ToString("F5");
466 posInputs[2].text = cachedGO.transform.localPosition[2].ToString("F5");
467
468
469 rotInputs[0].text = cachedGO.transform.localEulerAngles[0].ToString("F2");
470 rotInputs[1].text = cachedGO.transform.localEulerAngles[1].ToString("F2");
471 rotInputs[2].text = cachedGO.transform.localEulerAngles[2].ToString("F2");
472
473 onPosChanged("");
474 onRotChanged("");
475 }
476
477 public void onPosChanged(string value)
478 {
479 try
480 {
481 // X
482 var ci = CultureInfo.CurrentCulture;
483 var nfi = ci.NumberFormat;
484 posInputs[0].text = posInputs[0].text.Replace(',', nfi.CurrencyDecimalSeparator[0]);
485 posInputs[0].text = posInputs[0].text.Replace('.', nfi.CurrencyDecimalSeparator[0]);
486 var single = Convert.ToSingle(posInputs[0].text, ci);
487 posInputs[0].text = single.ToString("F1");
488 targetPosition.x = single;
489
490 // Y
491 posInputs[1].text = posInputs[1].text.Replace(',', nfi.CurrencyDecimalSeparator[0]);
492 posInputs[1].text = posInputs[1].text.Replace('.', nfi.CurrencyDecimalSeparator[0]);
493 single = Convert.ToSingle(posInputs[1].text, ci);
494 posInputs[1].text = single.ToString("F1");
495 targetPosition.y = single;
496
497 // Z
498 posInputs[2].text = posInputs[2].text.Replace(',', nfi.CurrencyDecimalSeparator[0]);
499 posInputs[2].text = posInputs[2].text.Replace('.', nfi.CurrencyDecimalSeparator[0]);
500 single = Convert.ToSingle(posInputs[2].text, ci);
501 posInputs[2].text = single.ToString("F1");
502 targetPosition.z = single;
503 }
504 catch (Exception)
505 {
506 Debug.LogWarning("not parsable number(?) in Position inputfields!");
507
508 // restore last valid numbers
509 posInputs[0].text = targetPosition[0].ToString("F1");
510 posInputs[1].text = targetPosition[1].ToString("F1");
511 posInputs[2].text = targetPosition[2].ToString("F1");
512 }
513 }
514
515 public void onRotChanged(string value)
516 {
517 try
518 {
519 // X
520 var ci = CultureInfo.CurrentCulture;
521 var nfi = ci.NumberFormat;
522 rotInputs[0].text = rotInputs[0].text.Replace(',', nfi.CurrencyDecimalSeparator[0]);
523 rotInputs[0].text = rotInputs[0].text.Replace('.', nfi.CurrencyDecimalSeparator[0]);
524 var single = Convert.ToSingle(rotInputs[0].text, ci);
525 rotInputs[0].text = single.ToString("F0");
526 targetRotation.x = single;
527
528 // Y
529 rotInputs[1].text = rotInputs[1].text.Replace(',', nfi.CurrencyDecimalSeparator[0]);
530 rotInputs[1].text = rotInputs[1].text.Replace('.', nfi.CurrencyDecimalSeparator[0]);
531 single = Convert.ToSingle(rotInputs[1].text, ci);
532 rotInputs[1].text = single.ToString("F0");
533 targetRotation.y = single;
534
535 // Z
536 rotInputs[2].text = rotInputs[2].text.Replace(',', nfi.CurrencyDecimalSeparator[0]);
537 rotInputs[2].text = rotInputs[2].text.Replace('.', nfi.CurrencyDecimalSeparator[0]);
538 single = Convert.ToSingle(rotInputs[2].text, ci);
539 rotInputs[2].text = single.ToString("F0");
540 targetRotation.z = single;
541 }
542 catch (Exception)
543 {
544 Debug.LogWarning("not parsable number(?) in Position inputfields!");
545
546 // restore last valid numbers
547 rotInputs[0].text = targetRotation[0].ToString("F0");
548 rotInputs[1].text = targetRotation[1].ToString("F0");
549 rotInputs[2].text = targetRotation[2].ToString("F0");
550 }
551 }
552
554 {
555 posInputs[0].text = targetPosition[0].ToString("F1");
556 posInputs[1].text = targetPosition[1].ToString("F1");
557 posInputs[2].text = targetPosition[2].ToString("F1");
558
559 rotInputs[0].text = targetRotation[0].ToString("F0");
560 rotInputs[1].text = targetRotation[1].ToString("F0");
561 rotInputs[2].text = targetRotation[2].ToString("F0");
562
563 toggle.isOn = HandMove;
564
565 }
566
567 [Button]
568 [CanBeNull]
569 internal GameObject GetInputGO()
570 {
571 try
572 {
574 var action = Controller.Instance.GetActionByInOut(connection.fromId);
575 GameObject retval = null;
576 if (action is GameObjectAction objectAction) retval = objectAction.GetGameObject();
577 if (action is WeldAction weldAction) retval = weldAction.GetGameObject();
578 if (action is ToolAction toolAction) retval = toolAction.GetGameObject();
579
580 originalPosition = retval.transform.localPosition;
581 originalRotation = retval.transform.localEulerAngles;
582
583 Debug.Log($"Mover requested: \"{retval}\"");
584
585 return retval;
586 }
587 catch (Exception)
588 {
589 return null;
590 }
591 }
592
593 [CanBeNull]
594 public string GetInput()
595 {
596 try
597 {
598 return inIDs.Keys.ToList()[0];
599 }
600 catch (Exception)
601 {
602 return null;
603 }
604 }
605
606
607 public new void GetObjectData(SerializationInfo info, StreamingContext context)
608 {
609 base.GetObjectData(info, context);
610 var convertOldSave = false;
611 if (convertOldSave) targetPosition = targetPosition - new Vector3(0.4815754f, -0.324203f, -0.0164394f);
612 info.AddValue("targetPosition", targetPosition, typeof(Vector3));
613 info.AddValue("targetRotation", targetRotation, typeof(Vector3));
614 info.AddValue("timeToMove", timeToMove, typeof(float));
615 info.AddValue("HandMove", HandMove, typeof(bool));
616 }
617
618 public MoveAction(SerializationInfo info, StreamingContext context) : base(info, context)
619 {
620 targetPosition = (Vector3)info.GetValue("targetPosition", typeof(Vector3));
621 targetRotation = (Vector3)info.GetValue("targetRotation", typeof(Vector3));
622 try
623 {
624 timeToMove = info.GetSingle("timeToMove");
625 }
626 catch (Exception)
627 {
628 timeToMove = 1.0f;
629 }
630 try
631 {
632 HandMove = info.GetBoolean("HandMove");
633
634 }
635 catch (Exception)
636 {
637 HandMove = false;
638 }
639 }
640}
UnityEngine.UI.Button Button
Definition: Pointer.cs:7
UnityEngine.Debug Debug
Definition: TanodaServer.cs:19
UnityEngine.Color Color
Definition: TestScript.cs:32
Image statusImg
Definition: ActionObject.cs:21
void TriggerOutput(string id)
string action
Definition: ActionObject.cs:32
List< GameObject > outPuts
Definition: ActionObject.cs:19
Connection GetConnectionByEndPointId(string id)
Definition: Controller.cs:857
ActionObject GetActionByInOut(string id)
Definition: Controller.cs:925
static Controller Instance
Definition: Controller.cs:16
Definition: Macro.cs:12
static float DistancePointLine(Vector3 point, Vector3 lineStart, Vector3 lineEnd)
Definition: Macro.cs:935
static float StoF(string value)
Definition: Macro.cs:24
static Vector3 ClampAngle(Vector3 value)
Definition: Macro.cs:303
Vector3 originalRotation
Definition: MoveAction.cs:30
Vector3 handPosition
Definition: MoveAction.cs:30
Vector3 targetPosition
Definition: MoveAction.cs:30
override void Triggered(string id)
Definition: MoveAction.cs:79
MoveAction(SerializationInfo info, StreamingContext context)
Definition: MoveAction.cs:618
void FillCurrentTransform()
Definition: MoveAction.cs:458
IEnumerator FollowHand()
Definition: MoveAction.cs:324
float timeToMove
Definition: MoveAction.cs:31
Vector3 originalPosition
Definition: MoveAction.cs:30
Toggle toggle
Definition: MoveAction.cs:32
void onPosChanged(string value)
Definition: MoveAction.cs:477
string GetInput()
Definition: MoveAction.cs:594
void RefreshTargetDisplay()
Definition: MoveAction.cs:553
void onRotChanged(string value)
Definition: MoveAction.cs:515
Vector3 handLocal
Definition: MoveAction.cs:30
new void GetObjectData(SerializationInfo info, StreamingContext context)
Definition: MoveAction.cs:607
void onTtmChanged(string value)
Definition: MoveAction.cs:417
new void Update()
Definition: MoveAction.cs:37
InputField[] rotInputs
Definition: MoveAction.cs:28
InputField ttmInput
Definition: MoveAction.cs:29
Vector3 targetRotation
Definition: MoveAction.cs:30
void FinalPosition()
Definition: MoveAction.cs:448
void MoveWithHand(bool newValue)
Definition: MoveAction.cs:121
void StartPosition()
Definition: MoveAction.cs:438
InputField[] posInputs
Definition: MoveAction.cs:27
GameObject cachedGO
Definition: MoveAction.cs:34
Vector3 Offset
Definition: OffsetHolder.cs:7