14
14
#include < algorithm>
15
15
16
16
#include " ../ResourceSystem.h"
17
- #include " ../entity/Entity.h"
18
17
19
18
namespace Siege
20
19
{
@@ -27,73 +26,155 @@ void SceneFile::RegisterSerialisable(const String& name,
27
26
28
27
bool SceneFile::Serialise (const std::vector<Entity*>& entities)
29
28
{
30
- return FileSystem::Save (MakeScenePath (sceneName), SerialiseToString (entities));
29
+ // Create the required scene file directory
30
+ FileSystem::CreateDirectoryRecursive (MakeScenePath (sceneName));
31
+
32
+ // Flush any removed entities from disk
33
+ for (const auto & pair : entityPaths)
34
+ {
35
+ if (!pair.first ) FileSystem::Remove (pair.second );
36
+ }
37
+
38
+ bool succeeded = true ;
39
+ for (auto & entity : entities)
40
+ {
41
+ String fileData;
42
+ bool result = SerialiseToString (entity, fileData);
43
+
44
+ if (!result)
45
+ {
46
+ succeeded = false ;
47
+ continue ;
48
+ }
49
+
50
+ String filepath = GetOrCreateEntityFilepath (entity);
51
+ FileSystem::Save (filepath, fileData);
52
+ entityPaths[EntityPtr (entity)] = filepath;
53
+ }
54
+ return succeeded;
31
55
}
32
56
33
- String SceneFile::SerialiseToString (const std::vector< Entity*>& entities )
57
+ bool SceneFile::SerialiseToString (Entity* entity, String& fileData )
34
58
{
35
59
// Iterate over each entity in the scene
36
- String fileData;
37
60
auto & serialisables = GetSerialisables ();
38
- for (auto & entity : entities)
61
+
62
+ // Only serialise entities that register a serialisable interface
63
+ auto it = serialisables.find (entity->GetName ());
64
+ if (it == serialisables.end ()) return false ;
65
+
66
+ // Serialise the general entity information
67
+ fileData += (entity->GetName () + LINE_SEP);
68
+ fileData += DefineField (" POSITION" , ToString (entity->GetPosition ()));
69
+ fileData += DefineField (" ROTATION" , String::FromFloat (entity->GetRotation ().y ));
70
+ fileData += DefineField (" Z-INDEX" , String::FromInt (entity->GetZIndex ()));
71
+
72
+ // Apply its serialiser if it
73
+ Serialiser serialiser = it->second .first ;
74
+ if (serialiser) fileData += serialiser (entity);
75
+
76
+ return true ;
77
+ }
78
+
79
+ bool SceneFile::Deserialise (std::vector<Entity*>& entities)
80
+ {
81
+ // Clear out the held entity paths before repopulating
82
+ entityPaths.clear ();
83
+
84
+ bool succeeded = true ;
85
+ auto deserialiseEntity = [this , &entities, &succeeded](const std::filesystem::path& path) {
86
+ if (path.extension () != ENTITY_FILE_EXT) return ;
87
+
88
+ String fileData = FileSystem::Read (path.c_str ());
89
+ Entity* newEntity = DeserialiseFromString (fileData);
90
+
91
+ if (!newEntity)
92
+ {
93
+ succeeded = false ;
94
+ return ;
95
+ }
96
+
97
+ entities.push_back (newEntity);
98
+ entityPaths[EntityPtr (newEntity)] = path.c_str ();
99
+ };
100
+ bool result = FileSystem::ForEachFileInDir (MakeScenePath (sceneName), deserialiseEntity);
101
+ return succeeded && result;
102
+ }
103
+
104
+ Entity* SceneFile::DeserialiseFromString (const String& fileData)
105
+ {
106
+ if (fileData.IsEmpty ())
39
107
{
40
- // Only serialise entities that register a serialisable interface
41
- auto it = serialisables.find (entity->GetName ());
42
- if (it == serialisables.end ()) continue ;
43
-
44
- // Serialise the general entity information
45
- fileData += (entity->GetName () + SEP);
46
- fileData += DefineField (" POSITION" , ToString (entity->GetPosition ()));
47
- fileData += DefineField (" ROTATION" , String::FromFloat (entity->GetRotation ().y ));
48
- fileData += DefineField (" Z-INDEX" , String::FromInt (entity->GetZIndex ()));
49
-
50
- // Apply its serialiser if it
51
- Serialiser serialiser = it->second .first ;
52
- if (serialiser) fileData += serialiser (entity);
53
-
54
- // End the serialisation entry
55
- fileData += " \n " ;
108
+ CC_LOG_WARNING (" Found empty entity during deserialisation" );
109
+ return nullptr ;
56
110
}
57
- return fileData;
111
+
112
+ // Split the file into arguments and strip the labels from each item
113
+ std::vector<String> args = fileData.Split (LINE_SEP);
114
+ for (String& arg : args) arg = arg.SubString ((int ) arg.Find (NAME_SEP) + 1 );
115
+
116
+ // Get the standard entity fields
117
+ EntityData data;
118
+ if (!(args.size () >= 4 && args[ENTITY_ROT].GetFloat (data.rotation ) &&
119
+ args[ENTITY_Z_IDX].GetInt (data.zIndex ) && FromString (data.position , args[ENTITY_POS])))
120
+ {
121
+ CC_LOG_WARNING (" Failed to deserialise fields for entity \" {}\" " , args[ENTITY_NAME]);
122
+ }
123
+
124
+ // Check if the entity has a relevant serialisable interface registered
125
+ auto & serialisables = GetSerialisables ();
126
+ auto it = serialisables.find (args[ENTITY_NAME]);
127
+ if (it != serialisables.end ())
128
+ {
129
+ // Apply its deserialiser
130
+ Deserialiser deserialiser = it->second .second ;
131
+ if (deserialiser) return deserialiser (data, args);
132
+ }
133
+ else CC_LOG_WARNING (" \" {}\" has no deserialisation protocols defined" , args[ENTITY_NAME]);
134
+ return nullptr ;
58
135
}
59
136
60
- bool SceneFile::Deserialise (std::vector<Entity*>& entities )
137
+ const String& SceneFile::GetSceneName ( )
61
138
{
62
- // Iterate over each line of the file
63
- String lines = FileSystem::Read (MakeScenePath (sceneName));
64
- if (!lines) return false ;
65
- DeserialiseLines (lines.Split (' \n ' ), entities);
66
- return true ;
139
+ return sceneName;
140
+ }
141
+
142
+ void SceneFile::SetSceneName (const String& name)
143
+ {
144
+ sceneName = name;
67
145
}
68
146
69
- void SceneFile::DeserialiseLines ( const std::vector<String>& lines, std::vector<Entity*>& entities )
147
+ void SceneFile::InitialiseEntityPathMappings ( )
70
148
{
71
- for (const String& line : lines )
149
+ for (std::pair<EntityPtr<Entity>, String> pair : entityPaths )
72
150
{
73
- // Split the line into arguments and strip the labels from each item
74
- std::vector<String> args = line.Split (SEP);
75
- for (String& arg : args) arg = arg.SubString ((int ) arg.Find (NAME_SEP) + 1 );
76
-
77
- // Get the standard entity fields
78
- EntityData data;
79
- if (!(args.size () >= 4 && args[ENTITY_ROT].GetFloat (data.rotation ) &&
80
- args[ENTITY_Z_IDX].GetInt (data.zIndex ) &&
81
- FromString (data.position , args[ENTITY_POS])))
82
- {
83
- CC_LOG_WARNING (" Failed to deserialise fields for entity \" {}\" " , args[ENTITY_NAME]);
84
- }
151
+ pair.first .InitialiseIndex ();
152
+ }
153
+ }
154
+
155
+ String SceneFile::GetOrCreateEntityFilepath (Entity* entity)
156
+ {
157
+ // Try to find the entity path amongst the deserialised
158
+ auto it = entityPaths.find (EntityPtr (entity));
159
+ if (it != entityPaths.end ()) return it->second ;
85
160
86
- // Check if the entity has a relevant serialisable interface registered
87
- auto & serialisables = GetSerialisables ();
88
- auto it = serialisables.find (args[ENTITY_NAME]);
89
- if (it != serialisables.end ())
161
+ // Search through the scene file for the next available file index
162
+ int newFileIndex = 1 ;
163
+ auto findNextFileIndex = [&newFileIndex](const std::filesystem::path& path) {
164
+ if (path.extension () != ENTITY_FILE_EXT) return ;
165
+ std::vector<String> filename = String (path.filename ().c_str ()).Split (' .' );
166
+
167
+ int nameIndex;
168
+ if (filename[1 ].GetInt (nameIndex) && nameIndex >= newFileIndex)
90
169
{
91
- // Apply its deserialiser
92
- Deserialiser deserialiser = it->second .second ;
93
- if (deserialiser) entities.push_back (deserialiser (data, args));
170
+ newFileIndex = nameIndex + 1 ;
94
171
}
95
- else CC_LOG_WARNING (" \" {}\" has no deserialisation protocols defined" , args[ENTITY_NAME]);
96
- }
172
+ };
173
+ bool result = FileSystem::ForEachFileInDir (MakeScenePath (sceneName), findNextFileIndex);
174
+
175
+ // Failed attempts to find a file index are serialised as 0
176
+ String index = result ? String::FromInt (newFileIndex) : " 0" ;
177
+ return MakeScenePath (sceneName) + ' /' + entity->GetName () + ' .' + index + ENTITY_FILE_EXT;
97
178
}
98
179
99
180
String SceneFile::MakeScenePath (const String& sceneName)
0 commit comments