Tanoda
ConveyorBeltManager.cs
Go to the documentation of this file.
1using System;
2using System.Collections;
3using System.Collections.Generic;
4using System.Globalization;
5using System.Runtime.Serialization;
6using GILES;
7using GILES.Interface;
8using NaughtyAttributes;
9using UnityEngine;
10using UnityEngine.UI;
11#if !UNITY_WEBGL
12using Valve.VR.InteractionSystem;
13#endif
14using Random = UnityEngine.Random;
15
16public class ConveyorBeltManager : pb_MonoBehaviourSingleton<ConveyorBeltManager>, ISerializable
17{
18 public GameObject conveyorBelt;
19 [HideInInspector]
20 public bool isEnabled = false;
21 public bool started = false;
22 public RawImage goodImage, badImage;
23 public Material beltEndMaterial;
24 public GameObject BeltStart, BeltEnd;
25 public float speed = 1.0f;
26 [Range(0, 0.99f)]
27 public float SpeedFalloff = 0.5f;
28 public float StopInterval = 4.0f;
29 public float StopTime = 2.0f;
30 [MinValue(0.2f)]
31 [Range(0.2f, 10.0f)]
32 [OnValueChanged("EditorBeltLengthChanged")]
33 public float BeltLength = 1.0f;
34
35 [MinValue(0.1f)]
36 [Range(0.1f, 1.0f)]
37 [OnValueChanged("EditorBeltWidthChanged")]
38 public float BeltWidth = 0.1f;
39
40 public Transform SpawnPoint;
41 public GameObject SpawnGood;
42 [SerializeField]
43 private List<GameObject> SpawnBad;
44 public float SpawnPercent, SpawnInterval = 3f;
45 public InputField InputPercent, InputInterval;
46
47 private float spawnInterval = 3.0f;
48 private float stopInterval = 4.0f;
49 private float stopTime = 2.0f;
50 private float currentSpeed = 0.0f;
51 private float defaultSpeed = 1.0f;
52 [SerializeField] internal int repeatTimes = 10;
53 private Material beltMaterial;
54 private System.Random r = new System.Random();
55 private GameObject canvasSelector;
56 internal GameObject finishBtn, inspector, canvas, stageManagerWindow;
57 [SerializeField] private bool spawnNow = true;
58 private bool lastSpawnGood = true;
59 private StartAction cachedStart;
60 private GameObject stopTrigger;
61 private GameObject spawn;
62 [SerializeField] internal bool cookieQuality = false;
63
64 internal void LoadCBM(ConveyorBeltManager cbm)
65 {
66 if (conveyorBelt == null) return;
67 isEnabled = cbm.isEnabled;
68 speed = cbm.speed;
71 StopTime = cbm.StopTime;
73 BeltWidth = cbm.BeltWidth;
76 repeatTimes = cbm.repeatTimes;
77 if (isEnabled || SavedUser.instance.isQuality)
78 {
79 conveyorBelt.SetActive(true);
80 FindObjectOfType<StartAction>()?.ShowQualityConnections();
81 SavedUser.instance.courseType = SavedUser.CourseType.Quality;
82 }
83 else
84 {
85 FindObjectOfType<StartAction>()?.HideQualityConnections();
86 }
89 try
90 {
91 if (SpawnGood)
92 {
93 var sgs = FindObjectsOfType<pb_PrefabBrowserItemButton>(true);
94 foreach (var sg in sgs)
95 {
96 if (sg.asset == SpawnGood)
97 {
98 if (sg.previewImg != null)
99 {
100 goodImage.texture = sg.previewImg.texture;
101 }
102 else
103 {
104 goodImage.texture = sg.GetComponentInChildren<RawImage>().texture;
105
106 }
107 break;
108 }
109 }
110 }
111 if (SpawnBad != null && SpawnBad.Count > 0)
112 {
113 var sgs = FindObjectsOfType<pb_PrefabBrowserItemButton>(true);
114
115 foreach (var sg in sgs)
116 {
117 if (sg.asset == SpawnBad[0])
118 {
119 if (sg.previewImg != null)
120 badImage.texture = sg.previewImg.texture;
121 else
122 badImage.texture = sg.GetComponentInChildren<RawImage>().texture;
123
124 break;
125 }
126 }
127 }
128 }
129 catch (Exception)
130 {
131 // ignored
132 }
133
134 try
135 {
136 InputPercent.text = cbm.SpawnPercent.ToString("P");
137 InputInterval.text = cbm.SpawnInterval.ToString("F1");
138 }
139 catch (Exception)
140 {
141 // ignored
142 }
143 }
144
145 private new void Awake()
146 {
147 if (SpawnBad == null)
148 {
149 SpawnBad = new List<GameObject>();
150 }
151 base.Awake();
152 conveyorBelt?.SetActive(SavedUser.instance.isQuality);
153 if (repeatTimes == 0) repeatTimes = 10;
154 cookieQuality = HttpCookie.GetCookie("courseModulTypeId") == "2";
155 }
156
157 public void BeltUsageChanged()
158 {
159 isEnabled = conveyorBelt.activeInHierarchy;
160 if (isEnabled)
161 {
162 FindObjectOfType<StartAction>()?.ShowQualityConnections();
163 SavedUser.instance.courseType = SavedUser.CourseType.Quality;
164 }
165 else
166 {
167 FindObjectOfType<StartAction>()?.HideQualityConnections();
168 SavedUser.instance.courseType = SavedUser.CourseType.Normal;
169 }
170 }
171
172 public void AddBad(GameObject go) => SpawnBad.Add(go);
173 public void ClearBad() => SpawnBad.Clear();
174
175 // Start is called before the first frame update
176 void Start()
177 {
178 if (conveyorBelt == null) return;
179 stopInterval = StopInterval;
180 spawnInterval = SpawnInterval;
181 stopTime = StopTime;
182 defaultSpeed = speed;
183 beltMaterial = GetComponent<Renderer>().material;
184 if (r == null)
185 r = new System.Random();
186
187 stageManagerWindow = GameObject.Find("StageManager Window");
188 canvasSelector = GameObject.Find("Canvas_selector");
189
190 // find inactive finish btn
191 canvas = GameObject.Find("Canvas");
192 var trs = canvas.GetComponentsInChildren<Transform>(true); // true: get inactive as well
193 foreach (var t in trs)
194 if (t.name == "Inspector")
195 inspector = t.gameObject;
196
197 trs = inspector.GetComponentsInChildren<Transform>(true);
198 foreach (var t in trs)
199 if (t.name == "FinishToolPos_Btn")
200 finishBtn = t.gameObject;
201
202 stopTrigger = FindObjectOfType<ConveyorTrigger>().gameObject;
203 }
204
205 public void SelectGoodModel()
206 {
207 GameObject.Find("Btn_StageMgr").GetComponent<Button>().onClick.Invoke();
208 pb_Selection.AddOnRemovedFromSelectionListener(OnRemovedFromSelection);
209
210 finishBtn.GetComponent<Button>().onClick.RemoveAllListeners();
211 finishBtn.GetComponent<Button>().onClick.AddListener(OnFinishGood);
212 ShowFinishBtn();
213 }
214 public void SelectBadModel()
215 {
216 GameObject.Find("Btn_StageMgr").GetComponent<Button>().onClick.Invoke();
217 pb_Selection.AddOnRemovedFromSelectionListener(OnRemovedFromSelection);
218
219 finishBtn.GetComponent<Button>().onClick.RemoveAllListeners();
220 finishBtn.GetComponent<Button>().onClick.AddListener(OnFinishBad);
221 ShowFinishBtn();
222 }
223
224 void OnRemovedFromSelection(IEnumerable<GameObject> selection)
225 {
226 // turn on, unless already on
227 if (stageManagerWindow.GetComponent<CanvasGroup>().alpha == 0)
228 GameObject.Find("Btn_StageMgr").GetComponent<Button>().onClick.Invoke();
229
230 pb_Selection.instance.OnRemovedFromSelection -= OnRemovedFromSelection;
231 HideFinishBtn();
232 }
233
234 void OnFinishGood()
235 {
236 var selection = pb_Selection.gameObjects;
237
238 SpawnGood = selection[0];
239
240 // turn on, unless already on
241 if (stageManagerWindow.GetComponent<CanvasGroup>().alpha == 0)
242 GameObject.Find("Btn_StageMgr").GetComponent<Button>().onClick.Invoke();
243
244 pb_Selection.instance.OnRemovedFromSelection -= OnRemovedFromSelection;
245 HideFinishBtn();
246 }
247 void OnFinishBad()
248 {
249 var selection = pb_Selection.gameObjects;
250
251 SpawnBad.Add(selection[0]);
252
253 // turn on, unless already on
254 if (stageManagerWindow.GetComponent<CanvasGroup>().alpha == 0)
255 GameObject.Find("Btn_StageMgr").GetComponent<Button>().onClick.Invoke();
256
257 pb_Selection.instance.OnRemovedFromSelection -= OnRemovedFromSelection;
258 HideFinishBtn();
259 }
260
261 public void OnRepeatTimesEdited(string value)
262 {
263 var rt = (int)Macro.StoF(value);
264 if (rt > 0)
265 {
266 repeatTimes = rt;
267 }
268 }
269
270 void ShowFinishBtn()
271 {
272 if (!inspector.activeSelf)
273 inspector.SetActive(true);
274
275 var btnOffset = finishBtn.transform.parent.GetComponent<RectTransform>().rect.width;
276 var spacing = 5f;
277 finishBtn.GetComponent<RectTransform>().anchoredPosition = new Vector2(-(btnOffset + spacing), 0);
278
279 finishBtn.SetActive(true);
280 }
281
282 void HideFinishBtn()
283 {
284 finishBtn.SetActive(false);
286 }
287
288 // Update is called once per frame
289 void Update()
290 {
291 if (!started)
292 return;
293 if (SpawnGood && SpawnBad.Count > 0)
294 {
295 if (cookieQuality)
296 {
297
298 if (spawnInterval > 0)
299 {
300 spawnInterval -= Time.deltaTime;
301 if (spawnInterval <= 0)
302 {
303 if (r == null)
304 r = new System.Random();
305 spawnInterval = SpawnInterval;
306 var randomBadIndex = r.Next(SpawnBad.Count);
307 //Debug.Log($"bad index = {randomBadIndex}");
308 var spawn = Random.value > SpawnPercent ? SpawnGood : SpawnBad[randomBadIndex];
309 var item = Instantiate(spawn, SpawnPoint.position, Quaternion.identity);
310 item.AddComponent<Rigidbody>();
311#if !UNITY_WEBGL
312 item.AddComponent<VelocityEstimator>();
313 item.AddComponent<Interactable>();
314 item.AddComponent<ThrowableCanDisable>();
315#endif
316 item.AddComponent<ReferenceSaver>().Reference = spawn;
317 }
318 }
319 }
320 else
321 {
322 if (spawnNow)
323 {
324 if (r == null)
325 r = new System.Random();
326
327 var randomBadIndex = r.Next(SpawnBad.Count);
328 var isGood = Random.value > SpawnPercent;
329 spawn = isGood ? SpawnGood : SpawnBad[randomBadIndex];
330
331 ResetItems();
332 spawn.transform.SetPositionAndRotation(SpawnPoint.position, Quaternion.identity);
333 spawn.SetActive(true);
334 spawn.GetComponent<Rigidbody>().isKinematic = false;
335#if !UNITY_WEBGL
336 spawn.GetComponent<ThrowableCanDisable>().onItemReseted = (() => CanSpawnNext());
337#endif
338 lastSpawnGood = isGood;
339 stopTrigger.SetActive(true);
340 spawnNow = false;
341 }
342
343
344 }
345 }
346
347 if (cookieQuality)
348 {
349 if (stopInterval > 0)
350 {
351 stopInterval -= Time.deltaTime;
352 if (stopInterval <= 0)
353 {
354 speed = 0;
355 }
356 }
357 currentSpeed = Mathf.Lerp(speed, currentSpeed, SpeedFalloff);
358 if (Math.Abs(currentSpeed) < 0.001f)
359 {
360 if (stopTime > 0)
361 {
362 stopTime -= Time.deltaTime;
363 if (stopTime <= 0)
364 {
365 stopTime = StopTime;
366 speed = defaultSpeed;
367 stopInterval = StopInterval;
368 }
369 }
370 }
371 }
372#if !UNITY_EDITOR
373 beltMaterial.mainTextureScale = new Vector2(transform.localScale.x * 10, transform.localScale.z * 10);
374 beltMaterial.mainTextureOffset += Vector2.up * speed * 0.1f;
375 if (beltEndMaterial)
376 {
377 beltEndMaterial.mainTextureOffset += Vector2.up * speed * 0.1f;
378 }
379#endif
380 }
381
382 public void InitItems()
383 {
384 if (cookieQuality) return;
385
386 cachedStart = FindObjectOfType<StartAction>();
387 if (cachedStart == null)
388 {
389 cookieQuality = true;
390 return;
391 }
392 var goodModel = cachedStart.GetInputGood();
393 if (goodModel == null)
394 {
395 cookieQuality = true;
396 return;
397 }
398 SpawnGood = goodModel;
399 SpawnBad = cachedStart.GetInputsBad();
400 if (!SpawnGood)
401 {
402 return;
403 }
405 SpawnGood.SetActive(false);
406 foreach (var item in SpawnBad)
407 {
409 item.SetActive(false);
410 }
411 spawnNow = true;
412 currentSpeed = 1;
413 }
414
415 public void StopItem()
416 {
417 if (cookieQuality) return;
418 if (lastSpawnGood)
419 {
420 cachedStart.StartGood();
421 }
422 else
423 {
424 cachedStart.StartBad();
425 }
426 currentSpeed = 0;
427 }
428
429 void ResetItems()
430 {
431 if (cookieQuality) return;
432#if !UNITY_WEBGL
433 SpawnGood.SetActive(false);
434 SpawnGood.GetComponent<ThrowableCanDisable>().ResetPosition(true);
435 foreach (var bad in SpawnBad)
436 {
437 bad.SetActive(false);
438 bad.GetComponent<ThrowableCanDisable>().ResetPosition(true);
439 }
440#endif
441
442 spawnNow = true;
443 }
444 public void Continue()
445 {
446 if (cookieQuality) return;
447 currentSpeed = 1;
448 Macro.SetInteractable(spawn);
449 spawn.GetComponent<Rigidbody>().isKinematic = false;
450#if !UNITY_WEBGL
451 spawn.GetComponent<ThrowableCanDisable>().onItemReseted = (() => CanSpawnNext());
452
453 var allPosAction = FindObjectsOfType<PositionAction>();
454 foreach (var pa in allPosAction)
455 {
456 pa.Reactivate();
457 }
458
459#endif
460 }
461
462 public void CanSpawnNext()
463 {
464 if (cookieQuality) return;
465 spawn.SetActive(false);
466 spawnNow = true;
467 }
468
469 private void EditorBeltLengthChanged()
470 {
472 }
473
474 private void EditorBeltWidthChanged()
475 {
477 }
478
479 public void SelectBelt()
480 {
483 pb_SelectionHandle.instance.SetTool(Tool.Position);
484 }
485
486 public void SetSpeed(float value)
487 {
488 speed = value;
489 defaultSpeed = speed;
490 }
491
492 public void SetSpawnRate(string value)
493 {
494 SpawnInterval = string.IsNullOrEmpty(value) ? 3 : Macro.StoF(value);
495 }
496
497 public void SetSpawnPercent(string value)
498 {
499 SpawnPercent = string.IsNullOrEmpty(value) ? 0.2f : Macro.StoF(value) / 100f;
500 }
501
502 public void SetStopTime(string value)
503 {
504 var ci = CultureInfo.CurrentCulture;
505 var nfi = ci.NumberFormat;
506 value = value.Replace(',', nfi.CurrencyDecimalSeparator[0]);
507 value = value.Replace('.', nfi.CurrencyDecimalSeparator[0]);
508 var single = Convert.ToSingle(value, ci);
509
510 stopTime = StopTime = single;
511 }
512
513 public void SetStopInterval(string value)
514 {
515 var ci = CultureInfo.CurrentCulture;
516 var nfi = ci.NumberFormat;
517 value = value.Replace(',', nfi.CurrencyDecimalSeparator[0]);
518 value = value.Replace('.', nfi.CurrencyDecimalSeparator[0]);
519 var single = Convert.ToSingle(value, ci);
520
521 stopInterval = StopInterval = single;
522 }
523
524 public void SetBeltLength(float size)
525 {
526 transform.localScale = new Vector3(transform.localScale.x, transform.localScale.y, size);
527 BeltStart.transform.localPosition = new Vector3(0, -0.105f, -size*10/2-0.085f);
528 BeltEnd.transform.localPosition = new Vector3(0, -0.105f, size*10/2+0.085f);
529 BeltLength = size;
530 }
531
532 public void SetBeltWidth(float size)
533 {
534 transform.localScale = new Vector3(size, transform.localScale.y, transform.localScale.z);
535 BeltStart.transform.localScale = new Vector3(1, 1, size*10);
536 BeltEnd.transform.localScale = new Vector3(1, -1, size*10);
537 BeltWidth = size;
538 }
539
540 void OnTriggerStay(Collider col)
541 {
542 if (col.GetComponent<ThrowableCanDisable>())
543 {
544#if !UNITY_WEBGL
545
546 if (col.GetComponent<ThrowableCanDisable>().interactable.attachedToHand)
547 {
548 return;
549 }
550#endif
551 }
552 col.GetComponentInParent<Rigidbody>().transform.position += transform.forward * currentSpeed * Time.deltaTime;
553
554 }
555
556 private void OnTriggerExit(Collider other)
557 {
558 try
559 {
560 other.GetComponent<Rigidbody>().AddForce(transform.forward * currentSpeed, ForceMode.Impulse);
561 }
562 catch (Exception)
563 {
564 // ignored
565 }
566 if (currentSpeed != 0)
567 {
568 other.GetComponentInParent<Rigidbody>().isKinematic = false;
569 }
570 }
571
572 private void OnDestroy()
573 {
574#if !UNITY_EDITOR
575 try
576 {
577 beltMaterial.mainTextureOffset = Vector2.zero;
578 beltEndMaterial.mainTextureOffset = Vector2.zero;
579 }
580 catch (Exception)
581 {
582 // ignored
583 }
584#endif
585 }
586
587 public void GetObjectData(SerializationInfo info, StreamingContext context)
588 {
589 info.AddValue("isEnabled", isEnabled);
590 info.AddValue("speed", speed);
591 info.AddValue("SpeedFalloff", SpeedFalloff);
592 info.AddValue("StopInterval", StopInterval);
593 info.AddValue("StopTime", StopTime);
594 info.AddValue("BeltLength", BeltLength);
595 info.AddValue("BeltWidth", BeltWidth);
596 info.AddValue("SpawnPercent", SpawnPercent);
597 info.AddValue("SpawnInterval", SpawnInterval);
598 info.AddValue("repeatTimes", repeatTimes);
599 if (SpawnGood && SpawnBad.Count > 0)
600 {
601 info.AddValue("SpawnGood", SpawnGood.name);
602 var save = "";
603 foreach (var o in SpawnBad)
604 {
605 if (o != null)
606 save += o.name + ";";
607 }
608 info.AddValue("SpawnBad", save);
609 }
610 info.AddValue("position", conveyorBelt.transform.position, typeof(Vector3));
611 info.AddValue("rotation", conveyorBelt.transform.rotation, typeof(Quaternion));
612 }
613
614
615 public ConveyorBeltManager(SerializationInfo info, StreamingContext context)
616 {
617 isEnabled = info.GetBoolean("isEnabled");
618 speed = info.GetSingle("speed");
619 SpeedFalloff = info.GetSingle("SpeedFalloff");
620 StopInterval = info.GetSingle("StopInterval");
621 StopTime = info.GetSingle("StopTime");
622 BeltLength = info.GetSingle("BeltLength");
623 BeltWidth = info.GetSingle("BeltWidth");
624 try
625 {
626 instance.conveyorBelt.transform.position = (Vector3)info.GetValue("position", typeof(Vector3));
627 instance.conveyorBelt.transform.rotation = (Quaternion)info.GetValue("rotation", typeof(Quaternion));
628
629 FileDragAndDrop.instance.GetUploadedGOFromName(info.GetString("SpawnGood"), out instance.SpawnGood);
630 var badString = info.GetString("SpawnBad").Split(';');
631 if (SpawnBad == null)
632 SpawnBad = new List<GameObject>();
633 foreach (var s in badString)
634 {
635 if (string.IsNullOrEmpty(s)) continue;
637 ConveyorBeltManager.instance.AddBad(sbad);
638 }
639 }
640 catch (Exception)
641 {
642 // ignored, backward compatible
643 }
644
645 try
646 {
647 SpawnPercent = info.GetSingle("SpawnPercent");
648 SpawnInterval = info.GetSingle("SpawnInterval");
649
650 repeatTimes = info.GetInt32("repeatTimes");
651 }
652 catch (Exception )
653 {
654 // ignored, backward compatible
655 repeatTimes = 10;
656 }
657 }
658}
Es.InkPainter.Math Math
Definition: PaintTest.cs:7
UnityEngine.UI.Button Button
Definition: Pointer.cs:7
UnityEngine.Random Random
void SetBeltLength(float size)
void SetStopTime(string value)
ConveyorBeltManager(SerializationInfo info, StreamingContext context)
void GetObjectData(SerializationInfo info, StreamingContext context)
void SetStopInterval(string value)
void SetSpawnRate(string value)
void SetBeltWidth(float size)
void AddBad(GameObject go)
void OnRepeatTimesEdited(string value)
void SetSpawnPercent(string value)
void SetSpeed(float value)
bool GetUploadedGOFromName(string value, out GameObject retval)
static FileDragAndDrop instance
static List< GameObject > gameObjects
A list of the currently selected GameObjects.
Definition: pb_Selection.cs:56
static void AddOnRemovedFromSelectionListener(Callback< IEnumerable< GameObject > > del)
Definition: pb_Selection.cs:45
static void AddToSelection(GameObject go)
static void Clear()
Definition: pb_Selection.cs:61
Definition: Macro.cs:12
static void SetInteractable(GameObject go, bool isKinematic=true)
Definition: Macro.cs:439
static float StoF(string value)
Definition: Macro.cs:24
void StartBad()
Definition: StartAction.cs:115
void StartGood()
Definition: StartAction.cs:111
Tool
Definition: pb_Enum.cs:24