ManiaMap.Godot
Procedural generation of metroidvania style maps for Godot .NET.
RoomTemplateDatabase.cs
1using Godot;
2using MPewsey.ManiaMap;
3using MPewsey.ManiaMap.Exceptions;
4using System;
5using System.Collections.Generic;
6using System.Linq;
7using System.Threading.Tasks;
8
10{
18 [GlobalClass]
19 public partial class RoomTemplateDatabase : Resource
20 {
24 [Export] public TemplateGroup[] TemplateGroups { get; set; } = Array.Empty<TemplateGroup>();
25
29 private Dictionary<int, RoomTemplateResource> RoomTemplates { get; } = new Dictionary<int, RoomTemplateResource>();
30
34 public bool IsDirty { get; private set; } = true;
35
39 public IReadOnlyDictionary<int, RoomTemplateResource> GetRoomTemplates()
40 {
42 return RoomTemplates;
43 }
44
48 public void SetDirty()
49 {
50 IsDirty = true;
51 }
52
56 private void PopulateIfDirty()
57 {
58 if (IsDirty)
59 {
61 IsDirty = false;
62 }
63 }
64
69 private void PopulateRoomTemplates()
70 {
71 RoomTemplates.Clear();
72
73 foreach (var group in TemplateGroups)
74 {
75 foreach (var entry in group.Entries)
76 {
77 var id = entry.RoomTemplate.Id;
78
79 if (!RoomTemplates.TryGetValue(id, out var template))
80 RoomTemplates.Add(id, entry.RoomTemplate);
81 else if (template != entry.RoomTemplate)
82 throw new DuplicateIdException($"Duplicate room template ID: {id}.");
83 }
84 }
85 }
86
92 {
94 return RoomTemplates[id];
95 }
96
103 {
104 var room = layoutPack.Layout.Rooms[id];
105 return GetRoomTemplate(room.Template.Id);
106 }
107
112 private async Task<Dictionary<int, PackedScene>> LoadScenesAsync(IEnumerable<Room> rooms, bool useSubThreads = false)
113 {
114 var tasks = new Dictionary<int, Task<PackedScene>>();
115
116 foreach (var room in rooms)
117 {
118 var id = room.Template.Id;
119
120 if (!tasks.ContainsKey(id))
121 tasks.Add(id, GetRoomTemplate(id).LoadSceneAsync(useSubThreads));
122 }
123
124 await Task.WhenAll(tasks.Values);
125 var result = new Dictionary<int, PackedScene>(tasks.Count);
126
127 foreach (var pair in tasks)
128 {
129 result.Add(pair.Key, pair.Value.Result);
130 }
131
132 return result;
133 }
134
141 public async Task<List<RoomNode2D>> CreateRoom2DInstancesAsync(Node parent, LayoutPack layoutPack, int? z = null, bool useSubThreads = false)
142 {
143 z ??= layoutPack.Layout.Rooms.Values.Select(x => x.Position.Z).First();
144 var rooms = layoutPack.Layout.Rooms.Values.Where(x => x.Position.Z == z).ToList();
145 var scenes = await LoadScenesAsync(rooms, useSubThreads);
146 var result = new List<RoomNode2D>(rooms.Count);
147
148 foreach (var room in rooms)
149 {
150 var scene = scenes[room.Template.Id];
151 result.Add(RoomNode2D.CreateInstance(room.Id, layoutPack, scene, parent, true));
152 }
153
154 return result;
155 }
156
162 public async Task<List<RoomNode3D>> CreateRoom3DInstancesAsync(Node parent, LayoutPack layoutPack, bool useSubThreads = false)
163 {
164 var rooms = layoutPack.Layout.Rooms.Values.ToList();
165 var scenes = await LoadScenesAsync(rooms, useSubThreads);
166 var result = new List<RoomNode3D>(rooms.Count);
167
168 foreach (var room in rooms)
169 {
170 var scene = scenes[room.Template.Id];
171 result.Add(RoomNode3D.CreateInstance(room.Id, layoutPack, scene, parent, true));
172 }
173
174 return result;
175 }
176
183 public List<RoomNode2D> CreateRoom2DInstances(Node parent, LayoutPack layoutPack, int? z = null)
184 {
185 z ??= layoutPack.Layout.Rooms.Values.Select(x => x.Position.Z).First();
186 var result = new List<RoomNode2D>();
187
188 foreach (var room in layoutPack.Layout.Rooms.Values)
189 {
190 if (room.Position.Z == z)
191 {
192 var template = GetRoomTemplate(room.Template.Id);
193 result.Add(RoomNode2D.CreateInstance(room.Id, layoutPack, template.LoadScene(), parent, true));
194 }
195 }
196
197 return result;
198 }
199
205 public List<RoomNode3D> CreateRoom3DInstances(Node parent, LayoutPack layoutPack)
206 {
207 var result = new List<RoomNode3D>();
208
209 foreach (var room in layoutPack.Layout.Rooms.Values)
210 {
211 var template = GetRoomTemplate(room.Template.Id);
212 result.Add(RoomNode3D.CreateInstance(room.Id, layoutPack, template.LoadScene(), parent, true));
213 }
214
215 return result;
216 }
217
225 public async Task<RoomNode2D> CreateRoom2DInstanceAsync(Uid id, LayoutPack layoutPack, Node parent, bool assignLayoutPosition = false, bool useSubThreads = false)
226 {
227 var scene = await GetRoomTemplate(id, layoutPack).LoadSceneAsync(useSubThreads);
228 return RoomNode2D.CreateInstance(id, layoutPack, scene, parent, assignLayoutPosition);
229 }
230
238 public async Task<RoomNode3D> CreateRoom3DInstanceAsync(Uid id, LayoutPack layoutPack, Node parent, bool assignLayoutPosition = false, bool useSubThreads = false)
239 {
240 var scene = await GetRoomTemplate(id, layoutPack).LoadSceneAsync(useSubThreads);
241 return RoomNode3D.CreateInstance(id, layoutPack, scene, parent, assignLayoutPosition);
242 }
243
251 public RoomNode2D CreateRoom2DInstance(Uid id, LayoutPack layoutPack, Node parent, bool assignLayoutPosition = false)
252 {
253 var scene = GetRoomTemplate(id, layoutPack).LoadScene();
254 return RoomNode2D.CreateInstance(id, layoutPack, scene, parent, assignLayoutPosition);
255 }
256
264 public RoomNode3D CreateRoom3DInstance(Uid id, LayoutPack layoutPack, Node parent, bool assignLayoutPosition = false)
265 {
266 var scene = GetRoomTemplate(id, layoutPack).LoadScene();
267 return RoomNode3D.CreateInstance(id, layoutPack, scene, parent, assignLayoutPosition);
268 }
269 }
270}
Holds the current Layout and LayoutState.
Definition: LayoutPack.cs:13
A node serving as the top level of a 2D room.
Definition: RoomNode2D.cs:17
static RoomNode2D CreateInstance(Uid id, LayoutPack layoutPack, PackedScene scene, Node parent, bool assignLayoutPosition=false)
Creates and initializes an instance of a room. The layout and layout state are assigned to the room b...
Definition: RoomNode2D.cs:182
A node serving as the top level of a 3D room.
Definition: RoomNode3D.cs:17
static RoomNode3D CreateInstance(Uid id, LayoutPack layoutPack, PackedScene scene, Node parent, bool assignLayoutPosition=false)
Creates and initializes an instance of a room. The layout and layout state are assigned to the room b...
Definition: RoomNode3D.cs:200
Provides lookup of RoomTemplateResource by ID and initialization methods for rooms.
List< RoomNode2D > CreateRoom2DInstances(Node parent, LayoutPack layoutPack, int? z=null)
Creates rooms at their layout positions for a layer of the current Layout. Returns a list of the inst...
async Task< RoomNode2D > CreateRoom2DInstanceAsync(Uid id, LayoutPack layoutPack, Node parent, bool assignLayoutPosition=false, bool useSubThreads=false)
Asynchronously creates a room from the current Layout. Returns the instantiated room.
RoomNode2D CreateRoom2DInstance(Uid id, LayoutPack layoutPack, Node parent, bool assignLayoutPosition=false)
Creates a room from the current Layout. Returns the instantiated room.
IReadOnlyDictionary< int, RoomTemplateResource > GetRoomTemplates()
Returns a read-only dictionary of room templates by ID.
async Task< RoomNode3D > CreateRoom3DInstanceAsync(Uid id, LayoutPack layoutPack, Node parent, bool assignLayoutPosition=false, bool useSubThreads=false)
Asynchronously creates a room from the current Layout. Returns the instantiated room.
void PopulateIfDirty()
Populates the lookup dictionary if the room is marked as dirty.
Dictionary< int, RoomTemplateResource > RoomTemplates
A dictionary of room templates by ID.
TemplateGroup[] TemplateGroups
An array of template groups containing the rooms to include in queries.
RoomTemplateResource GetRoomTemplate(Uid id, LayoutPack layoutPack)
Returns the room template for the specified room ID. This method uses the layout from the current Man...
async Task< List< RoomNode3D > > CreateRoom3DInstancesAsync(Node parent, LayoutPack layoutPack, bool useSubThreads=false)
Asynchronously creates rooms at their layout positions for the current Layout. Returns a list of the ...
List< RoomNode3D > CreateRoom3DInstances(Node parent, LayoutPack layoutPack)
Creates rooms at their layout positions for the current Layout. Returns a list of the instantiated ro...
RoomNode3D CreateRoom3DInstance(Uid id, LayoutPack layoutPack, Node parent, bool assignLayoutPosition=false)
Creates a room from the current Layout. Returns the instantiated room.
async Task< List< RoomNode2D > > CreateRoom2DInstancesAsync(Node parent, LayoutPack layoutPack, int? z=null, bool useSubThreads=false)
Asynchronously creates rooms at their layout positions for a layer of the current Layout....
async Task< Dictionary< int, PackedScene > > LoadScenesAsync(IEnumerable< Room > rooms, bool useSubThreads=false)
Loads the scenes for the specified rooms asynchronously and returns a dictionary of scenes by templat...
RoomTemplateResource GetRoomTemplate(int id)
Returns the room template for the specified ID.
void PopulateRoomTemplates()
Clears and populates the room templates dictionary.
void SetDirty()
Sets the database as dirty and requiring update.
bool IsDirty
True if the object is currently dirty and requires update.
Provides a reference to a room scene and information for the room required by the procedural generato...
PackedScene LoadScene()
Loads and returns the referenced scene.
Task< PackedScene > LoadSceneAsync(bool useSubThreads=false)
Asynchronously loads and returns the referenced scene.
A group of RoomTemplateResource and their procedural generation constraints.