Repository navigation
Expand file tree
/
Copy pathPlatformModule.cs
More file actions
113 lines (89 loc) · 3.64 KB
/
Copy pathPlatformModule.cs
File metadata and controls
113 lines (89 loc) · 3.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
using System.Collections.Generic;
using UnityEngine;
using FairPlay.Core;
using FairPlay.Menu;
using FairPlay.Utils;
namespace FairPlay.Modules
{
/// <summary>
/// Spawns a solid pad under whichever hand pulls its trigger.
///
/// The pads are plain local GameObjects. Nothing is instantiated over the network, so nobody
/// else sees them or can stand on them - which is exactly the point: this is a movement aid for
/// you, not terrain you impose on the lobby.
///
/// Two limits keep the scene clean: a budget that recycles the oldest pad, and an optional
/// lifetime. Both are in the config file.
/// </summary>
public sealed class PlatformModule : Module
{
public override string Name => "Platforms";
public override string Description => "Trigger spawns a pad at your hand";
public override ModuleCategory Category => ModuleCategory.Builder;
private const float Size = 0.55f;
private const float Thickness = 0.05f;
private const float Cooldown = 0.22f;
private readonly Queue<GameObject> _pads = new Queue<GameObject>();
private readonly Dictionary<GameObject, float> _born = new Dictionary<GameObject, float>();
/// <summary>One material for every pad; a fresh one per spawn is a leak by the dozen.</summary>
private Material _padMaterial;
private float _nextSpawnLeft;
private float _nextSpawnRight;
public override void Tick()
{
XRInput.Sample();
TrySpawn(true, ref _nextSpawnLeft);
TrySpawn(false, ref _nextSpawnRight);
Expire();
}
private void TrySpawn(bool leftHand, ref float nextAllowed)
{
if (!XRInput.For(leftHand).TriggerHeld) return;
if (Time.unscaledTime < nextAllowed) return;
Transform hand = GameRefs.Hand(leftHand);
if (hand == null) return;
nextAllowed = Time.unscaledTime + Cooldown;
Spawn(hand.position + Vector3.down * 0.12f);
if (Settings.Haptics.Value) GameRefs.Vibrate(leftHand, 0.35f, 0.04f);
}
private void Spawn(Vector3 position)
{
var pad = GameObject.CreatePrimitive(PrimitiveType.Cube);
pad.name = "FairPlayPad";
pad.transform.position = position;
pad.transform.localScale = new Vector3(Size, Thickness, Size);
if (_padMaterial == null) _padMaterial = Draw.Flat(MenuTheme.Accent);
var renderer = pad.GetComponent<Renderer>();
renderer.sharedMaterial = _padMaterial;
renderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
_pads.Enqueue(pad);
_born[pad] = Time.unscaledTime;
while (_pads.Count > Settings.PlatformBudget.Value) DestroyOldest();
}
private void Expire()
{
float life = Settings.PlatformLife.Value;
if (life <= 0f) return;
while (_pads.Count > 0)
{
GameObject oldest = _pads.Peek();
if (oldest != null && _born.TryGetValue(oldest, out float born) &&
Time.unscaledTime - born < life)
break;
DestroyOldest();
}
}
private void DestroyOldest()
{
if (_pads.Count == 0) return;
GameObject pad = _pads.Dequeue();
_born.Remove(pad);
if (pad != null) Object.Destroy(pad);
}
public override void Revert()
{
while (_pads.Count > 0) DestroyOldest();
_born.Clear();
}
}
}