-
Notifications
You must be signed in to change notification settings - Fork 9
/
WorldLayerHighlightedTiles.cs
166 lines (139 loc) · 5.58 KB
/
WorldLayerHighlightedTiles.cs
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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
using System.Collections;
using System.Collections.Generic;
using RimWorld.Planet;
using UnityEngine;
using Verse;
namespace PrepareLanding.Core.Gui.World
{
public class WorldLayerHighlightedTiles : WorldLayer
{
private readonly float _blinkTick;
private readonly Material _defaultMaterial = new Material(WorldMaterials.SelectedTile);
private readonly List<Vector3> _vertices = new List<Vector3>();
private float _alpha;
private AlphaRampDirection _alphaRampDirection;
private Color _materialColor = Color.green;
/// <summary>
/// Layer constructor.
/// </summary>
/// <remarks>It is instanced by the game engine. See constructor of the <see cref="RimWorld.Planet.WorldRenderer" /> class.</remarks>
public WorldLayerHighlightedTiles()
{
_defaultMaterial.color = TileColor;
var matColor = _defaultMaterial.color;
matColor.a = 1.0f;
_defaultMaterial.color = matColor;
_blinkTick = PrepareLanding.Instance.TileHighlighter.BlinkTick;
PrepareLanding.Instance.TileHighlighter.HighlightedTilesWorldLayer = this;
PrepareLanding.Instance.GameTicks.TicksIntervalElapsed += OnTicksIntervalElapsed;
PrepareLanding.Instance.GameTicks.UpdateInterval = _blinkTick;
}
/// <summary>
/// Get or set the highlighted tile color.
/// </summary>
public Color TileColor
{
get { return _materialColor; }
set
{
_materialColor = value;
_defaultMaterial.color = _materialColor;
}
}
/// <summary>
/// Get the overall alpha value of the whole layer.
/// </summary>
protected override float Alpha => _alpha;
/// <summary>
/// Called by RimWorld's engine when generating layers.
/// </summary>
/// <returns></returns>
public override IEnumerable Regenerate()
{
foreach (var result in base.Regenerate())
yield return result;
if (PrepareLanding.Instance.TileHighlighter.HighlightedTilesIds.Count == 0)
yield break;
foreach (var tileId in PrepareLanding.Instance.TileHighlighter.HighlightedTilesIds)
{
if (tileId < 0)
continue;
var subMesh = GetSubMesh(_defaultMaterial);
Find.World.grid.GetTileVertices(tileId, _vertices);
var startVertIndex = subMesh.verts.Count;
var currentIndex = 0;
var maxCount = _vertices.Count;
while (currentIndex < maxCount)
{
if (currentIndex % 1000 == 0)
yield return null;
if (subMesh.verts.Count > 60000)
subMesh = GetSubMesh(_defaultMaterial);
subMesh.verts.Add(_vertices[currentIndex] + _vertices[currentIndex].normalized * 0.012f);
if (currentIndex < maxCount - 2)
{
subMesh.tris.Add(startVertIndex + currentIndex + 2);
subMesh.tris.Add(startVertIndex + currentIndex + 1);
subMesh.tris.Add(startVertIndex);
}
currentIndex++;
}
FinalizeMesh(MeshParts.All);
}
}
/// <summary>
/// Make the highlighted tile "breath" (blink) by changing their alpha value.
/// </summary>
protected virtual void TileBreath()
{
if (_alpha < float.Epsilon)
{
// current alpha value is near 0, so set it to 0 and now go towards 1
_alpha = 0f;
_alphaRampDirection = AlphaRampDirection.AlphaRampUp;
}
if (_alpha >= 1f)
{
// alpha as goes up to 1, now set to 1 and go down
_alpha = 1f;
_alphaRampDirection = AlphaRampDirection.AlphaRampDown;
}
// depending on the direction (towards 0 or towards 1), either add or subtract from the alpha value
if (_alphaRampDirection == AlphaRampDirection.AlphaRampDown)
_alpha -= _blinkTick;
else
_alpha += _blinkTick;
}
/// <summary>
/// Called each time an highlighting tick interval has elapsed.
/// </summary>
/// <remarks>The tick handler is managed by the <see cref="TileHighlighter" /> instance, not by the layer.</remarks>
private void OnTicksIntervalElapsed()
{
if (PrepareLanding.Instance.TileHighlighter.DisableTileHighlighting)
{
// if tile highlighting is disabled, just don't show the layer.
_alpha = 0;
return;
}
if (PrepareLanding.Instance.TileHighlighter.DisableTileBlinking)
_alpha = TileHighlighter.DefaultTileHighlightingAlphaValue;
else
TileBreath();
}
/// <summary>
/// Direction of the alpha value; either towards 0 or towards 1.
/// </summary>
private enum AlphaRampDirection
{
/// <summary>
/// Alpha value will go towards 1.
/// </summary>
AlphaRampUp,
/// <summary>
/// Alpha value will go towards 0.
/// </summary>
AlphaRampDown
}
}
}