src/ldproject.cpp

branch
projects
changeset 938
cc8920320184
parent 937
d5a58674ccd1
child 939
9ac1042beadc
equal deleted inserted replaced
937:d5a58674ccd1 938:cc8920320184
17 */ 17 */
18 18
19 #include <archive.h> 19 #include <archive.h>
20 #include <archive_entry.h> 20 #include <archive_entry.h>
21 #include "ldproject.h" 21 #include "ldproject.h"
22 #include "ldDocument.h"
23
24 enum { CurrentBinaryVersion = 0 };
22 25
23 LDProject::LDProject() {} 26 LDProject::LDProject() {}
24 LDProject::~LDProject() {} 27 LDProject::~LDProject() {}
25 28
26 LDProjectPtr LDProject::LoadFromFile (const QString& filename) 29 LDProjectPtr LDProject::LoadFromFile (const QString& filename)
27 { 30 {
28 FILE* fp = fopen ("log.txt", "w"); 31 LDProjectPtr proj = LDProject::NewProject();
29 if (!fp) 32 LDProjectLoader (proj);
30 return LDProjectPtr(); 33 }
31 34
35 struct Xyz
36 {
37 double x, y, z;
38 Xyz (Vertex const& a) :
39 x (a.x()),
40 y (a.y()),
41 z (a.z()) {}
42 Vertex toVertex() const { return Vertex (x, y, z); }
43 };
44
45 QDataStream& operator>> (QDataStream& ds, Xyz& a)
46 {
47 return ds >> a.x >> a.y >> a.z;
48 }
49
50 QDataStream& operator<< (QDataStream& ds, const Xyz& a)
51 {
52 return ds << a.x << a.y << a.z;
53 }
54
55 struct LDProjectLoader
56 {
57 QVector<QPair<LDSubfilePtr, QString>> referenceNames;
58
59 LDProjectLoader (LDProjectPtr proj);
60 void loadDocument (const QString &name, const QByteArray &data);
61
62 };
63
64 LDProjectLoader::LDProjectLoader (LDProjectPtr proj)
65 {
32 archive* arc = archive_read_new(); 66 archive* arc = archive_read_new();
33 archive_read_support_filter_all (arc); 67 archive_read_support_filter_all (arc);
34 archive_read_support_format_zip (arc); 68 archive_read_support_format_zip (arc);
35 int result = archive_read_open_filename (arc, filename.toLocal8Bit().constData(), 0x4000); 69 int result = archive_read_open_filename (arc, filename.toLocal8Bit().constData(), 0x4000);
36 70
37 if (result != ARCHIVE_OK) 71 if (result != ARCHIVE_OK)
38 { 72 {
39 fprint (fp, "unable to open argh.pk3 (%1)\n", archive_error_string (arc)); 73 fprint (stderr, "unable to open argh.pk3 (%1)\n", archive_error_string (arc));
40 return LDProjectPtr(); 74 return LDProjectPtr();
41 } 75 }
42 76
43 for (archive_entry* arcent; archive_read_next_header(arc, &arcent) == ARCHIVE_OK;) 77 for (archive_entry* arcent; archive_read_next_header(arc, &arcent) == ARCHIVE_OK;)
44 { 78 {
48 int size = archive_read_data(arc, buffer.data(), buffer.size()); 82 int size = archive_read_data(arc, buffer.data(), buffer.size());
49 83
50 if (size >= 0) 84 if (size >= 0)
51 { 85 {
52 if (pathname.startsWith ("dat/")) 86 if (pathname.startsWith ("dat/"))
53 loadBinaryDocument (pathname.right (4), QByteArray (buffer.constData(), buffer.size())); 87 loadDocument (pathname.right (4), QByteArray (buffer.constData(), buffer.size()));
54 } 88 }
55 else 89 else
56 fprint (fp, "Unable to read %1: %2", pathname, archive_error_string (arc)); 90 fprint (stderr, "Unable to read %1: %2", pathname, archive_error_string (arc));
57 } 91 }
58 92
59 if ((result = archive_read_free(arc)) != ARCHIVE_OK) 93 if ((result = archive_read_free(arc)) != ARCHIVE_OK)
60 { 94 {
61 fprint (fp, "unable to close argh.pk3\n"); 95 fprint (stderr, "unable to close argh.pk3\n");
62 return LDProjectPtr(); 96 return LDProjectPtr();
63 } 97 }
64 98
65 return LDProjectPtr(); 99 return LDProjectPtr();
66 } 100 }
67 101
68 #include "ldDocument.h" 102 void LDProjectLoader::loadDocument (const QString &name, const QByteArray &data)
69 void LDProject::loadBinaryDocument(const QString &name, const QByteArray &data)
70 { 103 {
71 QDataStream ds (&data, QIODevice::ReadOnly); 104 QDataStream ds (&data, QIODevice::ReadOnly);
72 ds.setVersion (QDataStream::Qt_4_8); 105 ds.setVersion (QDataStream::Qt_4_8);
73 enum { CurrentVersion = 0 };
74 106
75 quint16 version; 107 quint16 version;
76 ds << version; 108 ds << version;
77 109
78 if (version > CurrentVersion) 110 if (version > CurrentBinaryVersion)
79 return; // too new 111 return; // too new
80 112
81 qint8 header; 113 qint8 header;
82 quint32 color; 114 quint32 color;
83 LDDocumentPtr doc = LDDocument::createNew(); 115 LDDocumentPtr doc = LDDocument::createNew();
116 doc->setName (name);
84 LDObjectPtr obj; 117 LDObjectPtr obj;
85 struct XYZ { double x, y, z; Vertex toVertex() const { return Vertex (x,y,z); }}; 118 Vertex vertex;
86 XYZ verts[4]; 119 Matrix matrix;
87 120
88 while ((ds << header) != -1) 121 while ((ds << header) != -1)
89 { 122 {
90 switch (header) 123 switch (header)
91 { 124 {
92 case 0: 125 case 0:
93 { 126 {
94 QString message; 127 QString message;
95 ds >> message; 128 ds >> message;
96 doc->addObject (LDSpawn<LDComment> (message)); 129 doc->addObject (LDSpawn<LDComment> (message));
130 }
131 break;
132
133 case 1:
134 {
135 LDSubfilePtr ref = LDSpawn<LDSubfile>();
136 QString name;
137 ds >> color;
138 ds >> vertex;
139
140 for (int i = 0; i < 9; ++i)
141 ds >> matrix[i];
142
143 ds >> name;
144 ref->setColor (LDColor::fromIndex (color));
145 ref->setPosition (vertex);
146 ref->setTransform (matrix);
147
148 // We leave the fileInfo null for now, references are resolved during post-process.
149 // If this object references a document that we'll parse later, finding it would
150 // yield null now.
151 referenceNames.append ({ref, name});
97 } 152 }
98 break; 153 break;
99 154
100 case 2: 155 case 2:
101 obj = LDSpawn<LDLine>(); 156 obj = LDSpawn<LDLine>();
111 166
112 case 5: 167 case 5:
113 obj = LDSpawn<LDCondLine>(); 168 obj = LDSpawn<LDCondLine>();
114 polyobject: 169 polyobject:
115 ds >> color; 170 ds >> color;
171 obj->setColor (LDColor::fromIndex (color));
172
116 for (int i = 0; i < obj->numVertices(); ++i) 173 for (int i = 0; i < obj->numVertices(); ++i)
117 { 174 {
118 XYZ v; 175 ds >> vertex;
119 ds >> v.x >> v.y >> v.z; 176 obj->setVertex (i, vertex);
120 obj->setVertex (i, Vertex (v.x, v.y, v.z));
121 } 177 }
122 178
123 doc->addObject (obj); 179 doc->addObject (obj);
124 break; 180 break;
125 } 181 }
126 } 182 }
127 183 }
184
185 struct ArchiveEntry
186 {
187 archive_entry* entry;
188 ArchiveEntry() : entry (archive_entry_new()) {}
189 ArchiveEntry (const ArchiveEntry&) = delete;
190 ~ArchiveEntry() { archive_entry_free (entry); }
191 void operator= (const ArchiveEntry&) = delete;
192 operator archive_entry*() { return entry; }
193
194 void clear() { archive_entry_clear (entry); }
195 void setSize (size_t size) { archive_entry_set_size (entry, size); }
196 void setPathName (const char* name) { archive_entry_set_pathname (entry, name); }
197 void setFileType (unsigned type) { archive_entry_set_filetype (entry, type); }
198 void setPermissions (int perms) { archive_entry_set_perm (entry, perms); }
199 };
200
201 void LDProject::saveBinaryDocuments (archive* arc)
202 {
203 ArchiveEntry ent;
204
205 for (LDDocumentPtr doc : m_documents)
206 {
207 QByteArray buffer;
208 QDataStream ds (&buffer, QIODevice::WriteOnly);
209 ds << CurrentBinaryVersion;
210
211 for (LDObjectPtr obj : doc->objects())
212 {
213 int number;
214
215 switch (obj->type())
216 {
217 case OBJ_Comment:
218 ds << 0
219 << obj.staticCast<LDCommentPtr>()->text();
220 break;
221
222 case OBJ_Subfile:
223 {
224 LDSubfilePtr ref = obj.staticCast<LDSubfilePtr>();
225 ds << 1
226 << ref->color().index()
227 << ref->position();
228
229 for (int i = 0; i < 9; ++i)
230 ds << ref->transform()[i];
231
232 ds << ref->fileInfo()->name();
233 }
234 break;
235
236 case OBJ_Line:
237 number = 2;
238 goto polyobj;
239
240 case OBJ_Triangle:
241 number = 3;
242 goto polyobj;
243
244 case OBJ_Quad:
245 number = 4;
246 goto polyobj;
247
248 case OBJ_CondLine:
249 number = 5;
250 polyobj:
251 ds << obj->color().index();
252
253 for (int i = 0; i < obj->numVertices(); ++i)
254 ds << obj->vertex (i);
255 break;
256 }
257 }
258
259 ent.clear();
260 ent.setSize (buffer.size());
261 ent.setPathName (QString ("doc/" + doc->name() + ".dat").toLocal8Bit());
262 ent.setFileType (AE_IFREG);
263 ent.setPermissions (0644);
264 archive_write_header (arc, ent);
265 archive_write_data (arc, buffer.constData(), buffer.size());
266 }
128 } 267 }
129 268
130 LDProjectPtr LDProject::NewProject() 269 LDProjectPtr LDProject::NewProject()
131 { 270 {
132 return LDProjectPtr (new LDProject()); 271 return LDProjectPtr (new LDProject());
133 } 272 }
134 273
135 bool LDProject::save (const QString &filename) 274 bool LDProject::save (const QString& filename)
136 { 275 {
137 return false; 276 QString tempname = filename;
138 } 277
139 278 if (tempname.endsWith (".ldforge"))
279 tempname.chop (strlen (".ldforge"));
280
281 if (not tempname.endsWith (".zip"))
282 tempname += ".zip";
283
284 archive* arc = archive_write_new();
285 archive_write_open_filename (arc, filename);
286 saveBinaryDocuments (arc);
287 archive_write_close (arc);
288 m_lastErrorString = archive_error_string (arc);
289 archive_write_free (arc);
290 return true;
291 }

mercurial