Mon, 18 Mar 2013 12:20:48 +0200
Renamed io.cpp to file.cpp, draw.cpp to gldraw.cpp
bbox.cpp | file | annotate | diff | comparison | revisions | |
draw.cpp | file | annotate | diff | comparison | revisions | |
draw.h | file | annotate | diff | comparison | revisions | |
file.cpp | file | annotate | diff | comparison | revisions | |
file.h | file | annotate | diff | comparison | revisions | |
gldraw.cpp | file | annotate | diff | comparison | revisions | |
gldraw.h | file | annotate | diff | comparison | revisions | |
gui.cpp | file | annotate | diff | comparison | revisions | |
gui.h | file | annotate | diff | comparison | revisions | |
io.cpp | file | annotate | diff | comparison | revisions | |
io.h | file | annotate | diff | comparison | revisions | |
ldtypes.cpp | file | annotate | diff | comparison | revisions | |
main.cpp | file | annotate | diff | comparison | revisions | |
zz_setContentsDialog.cpp | file | annotate | diff | comparison | revisions |
--- a/bbox.cpp Mon Mar 18 12:15:23 2013 +0200 +++ b/bbox.cpp Mon Mar 18 12:20:48 2013 +0200 @@ -1,7 +1,7 @@ #include "common.h" #include "bbox.h" #include "ldtypes.h" -#include "io.h" +#include "file.h" void bbox::calculate () { if (!g_CurrentFile)
--- a/draw.cpp Mon Mar 18 12:15:23 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,158 +0,0 @@ -#include <QtGui> -#include <QGLWidget> -#include "common.h" -#include "io.h" -#include "draw.h" -#include "bbox.h" - -renderer::renderer (QWidget* parent) { - parent = parent; // shhh, GCC - fRotX = fRotY = fRotZ = 0.0; - fZoom = 1.0; -} - -void renderer::initializeGL () { - glLoadIdentity(); - glMatrixMode (GL_MODELVIEW); - glClearColor (0.8f, 0.8f, 0.85f, 1.0f); - glEnable (GL_DEPTH_TEST); - glShadeModel (GL_SMOOTH); - glEnable (GL_MULTISAMPLE); - - CompileObjects (); -} - -void renderer::hardRefresh () { - CompileObjects (); - paintGL (); -} - -void renderer::resizeGL (int w, int h) { - glViewport (0, 0, w, h); -} - -void renderer::paintGL () { - glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glPushMatrix (); - glTranslatef ( - (g_BBox.v0.x + g_BBox.v1.x) / -2.0, - (g_BBox.v0.y + g_BBox.v1.y) / -2.0, - (g_BBox.v0.z + g_BBox.v1.z) / -2.0 - ); - - // glTranslatef (0.0f, 0.0f, -5.0f); - glTranslatef (0.0f, 0.0f, fZoom); - - // glScalef (0.75f, 1.15f, 0.0f); - glRotatef (fRotX, 1.0f, 0.0f, 0.0f); - glRotatef (fRotY, 0.0f, 1.0f, 0.0f); - glRotatef (fRotZ, 0.0f, 0.0f, 1.0f); - - glMatrixMode (GL_MODELVIEW); - - glCallList (objlist); - glColor3f (0.0, 0.5, 1.0); - glPopMatrix (); -} - -void renderer::CompileObjects () { - printf ("compile all objects\n"); - - objlist = glGenLists (1); - glNewList (objlist, GL_COMPILE); - - if (!g_CurrentFile) { - printf ("renderer: no files loaded, cannot compile anything\n"); - return; - } - - for (ulong i = 0; i < g_CurrentFile->objects.size(); i++) - CompileOneObject (g_CurrentFile->objects[i]); - - glEndList (); -} - -#define GL_VERTEX(V) \ - glVertex3d (V.x, V.y, V.z); - -void renderer::CompileOneObject (LDObject* obj) { - if (!obj) - return; - - switch (obj->getType ()) { - case OBJ_CondLine: // For now, treat condlines like normal lines. - case OBJ_Line: - { - glColor3f (0.0f, 0.0f, 0.0f); // Draw all lines black for now - // draw lines - LDLine* line = static_cast<LDLine*> (obj); - glBegin (GL_LINES); - for (short i = 0; i < 2; ++i) - GL_VERTEX (line->vaCoords[i]) - glEnd (); - } - break; - - case OBJ_Triangle: - { - LDTriangle* tri = static_cast<LDTriangle*> (obj); - glColor3f (0.5f, 0.5f, 0.5f); // Draw all polygons gray for now - glBegin (GL_TRIANGLES); - for (short i = 0; i < 3; ++i) - GL_VERTEX (tri->vaCoords[i]) - glEnd (); - } - break; - - case OBJ_Quad: - { - LDQuad* quad = static_cast<LDQuad*> (obj); - glColor3f (0.5f, 0.5f, 0.5f); - glBegin (GL_QUADS); - for (short i = 0; i < 4; ++i) - GL_VERTEX (quad->vaCoords[i]) - glEnd (); - } - break; - - default: - break; - } -} - -void renderer::ClampAngle (double& fAngle) { - while (fAngle < 0) - fAngle += 360.0; - while (fAngle > 360.0) - fAngle -= 360.0; -} - -void renderer::mouseMoveEvent (QMouseEvent *event) { - int dx = event->x () - lastPos.x (); - int dy = event->y () - lastPos.y (); - - if (event->buttons () & Qt::LeftButton) { - fRotX = fRotX + (dy); - fRotY = fRotY + (dx); - ClampAngle (fRotX); - ClampAngle (fRotY); - } - - if (event->buttons () & Qt::RightButton) { - fRotX = fRotX + (dy); - fRotZ = fRotZ + (dx); - ClampAngle (fRotX); - ClampAngle (fRotZ); - } - - if (event->buttons () & Qt::MidButton) { - fZoom += (dy / 100.0); - fZoom = clamp (fZoom, 0.1, 10.0); - } - - printf ("%.3f %.3f %.3f %.3f\n", - fRotX, fRotY, fRotZ, fZoom); - lastPos = event->pos(); - updateGL (); -} \ No newline at end of file
--- a/draw.h Mon Mar 18 12:15:23 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,32 +0,0 @@ -#ifndef __REND_H__ -#define __REND_H__ - -#include <QGLWidget> -#include "common.h" -#include "ldtypes.h" - -class renderer : public QGLWidget { - Q_OBJECT - -public: - renderer(QWidget* parent = NULL); - void hardRefresh (); - void CompileObjects (); - double fRotX, fRotY, fRotZ; - QPoint lastPos; - double fZoom; - -protected: - void initializeGL (); - void resizeGL (int w, int h); - void paintGL (); - - void mouseMoveEvent (QMouseEvent *event); - -private: - GLuint objlist; - void CompileOneObject (LDObject* obj); - void ClampAngle (double& fAngle); -}; - -#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/file.cpp Mon Mar 18 12:20:48 2013 +0200 @@ -0,0 +1,312 @@ +#include <vector> + +#include "common.h" +#include "file.h" +#include "misc.h" +#include "bbox.h" +#include "gui.h" + +vector<str> g_zaFileLoadPaths; + +// ============================================================================= +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +// ============================================================================= +OpenFile* findLoadedFile (str name) { + for (ulong i = 0; i < g_LoadedFiles.size(); i++) { + OpenFile* const file = g_LoadedFiles[i]; + if (file->zFileName == name) + return file; + } + + return nullptr; +} + +// ============================================================================= +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +// ============================================================================= +OpenFile* openDATFile (str path) { + logf ("Opening %s...\n", path.chars()); + + FILE* fp = fopen (path.chars (), "r"); + + if (!fp) { + for (ushort i = 0; i < g_zaFileLoadPaths.size(); ++i) { + str zFilePath = str::mkfmt ("%s/%s", g_zaFileLoadPaths[i].chars(), path.chars()); + fp = fopen (zFilePath.chars (), "r"); + + if (fp) + break; + } + } + + if (!fp) { + logf (LOG_Error, "Couldn't open %s: %s\n", path.chars (), strerror (errno)); + return nullptr; + } + + OpenFile* load = new OpenFile; + ulong numWarnings = 0; + + load->zFileName = path; + + vector<str> lines; + + { + char line[1024]; + while (fgets (line, sizeof line, fp)) { + // Trim the trailing newline + str zLine = line; + while (zLine[~zLine - 1] == '\n' || zLine[~zLine - 1] == '\r') + zLine -= 1; + + lines.push_back (zLine); + } + } + + fclose (fp); + + for (ulong i = 0; i < lines.size(); ++i) { + LDObject* obj = parseLine (lines[i]); + load->objects.push_back (obj); + + // Check for parse errors and warn abotu tthem + if (obj->getType() == OBJ_Gibberish) { + logf (LOG_Warning, "Couldn't parse line #%lu: %s\n", + i, static_cast<LDGibberish*> (obj)->zReason.chars()); + logf (LOG_Warning, "- Line was: %s\n", lines[i].chars()); + numWarnings++; + } + } + + g_LoadedFiles.push_back (load); + + logf (LOG_Success, "File %s parsed successfully (%lu warning%s).\n", + path.chars(), numWarnings, PLURAL (numWarnings)); + + return load; +} + +// ============================================================================= +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +// ============================================================================= +// Clear everything from the model +void OpenFile::close () { + for (ulong j = 0; j < objects.size(); ++j) + delete objects[j]; + + delete this; +} + +// ============================================================================= +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +// ============================================================================= +void closeAll () { + if (!g_LoadedFiles.size()) + return; + + // Remove all loaded files and the objects they contain + for (ushort i = 0; i < g_LoadedFiles.size(); i++) { + OpenFile* f = g_LoadedFiles[i]; + f->close (); + } + + // Clear the array + g_LoadedFiles.clear(); + g_CurrentFile = NULL; + + g_qWindow->R->hardRefresh(); +} + +// ============================================================================= +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +// ============================================================================= +void newFile () { + // Create a new anonymous file and set it to our current + closeAll (); + + OpenFile* f = new OpenFile; + f->zFileName = ""; + g_LoadedFiles.push_back (f); + g_CurrentFile = f; + + g_BBox.calculate(); + g_qWindow->buildObjList (); + g_qWindow->R->hardRefresh(); +} + +// ============================================================================= +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +// ============================================================================= +void openMainFile (str zPath) { + closeAll (); + + OpenFile* pFile = openDATFile (zPath); + g_CurrentFile = pFile; + + // Recalculate the bounding box + g_BBox.calculate(); + + // Rebuild the object tree view now. + g_qWindow->buildObjList (); + g_qWindow->setTitle (); +} + +// ============================================================================= +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +// ============================================================================= +void OpenFile::save (str zPath) { + if (!~zPath) + zPath = zFileName; + + FILE* fp = fopen (zPath, "w"); + if (!fp) + return; + + // Write all entries now + for (ulong i = 0; i < objects.size(); ++i) { + LDObject* obj = objects[i]; + + // LDraw requires lines to have DOS line endings + str zLine = str::mkfmt ("%s\r\n",obj->getContents ().chars ()); + + fwrite (zLine.chars(), 1, ~zLine, fp); + } + + fclose (fp); +} + +// ============================================================================= +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +// ============================================================================= +#define CHECK_TOKEN_COUNT(N) \ + if (tokens.size() != N) \ + return new LDGibberish (zLine, "Bad amount of tokens"); + +#define CHECK_TOKEN_NUMBERS(MIN,MAX) \ + for (ushort i = MIN; i <= MAX; ++i) \ + if (!isNumber (tokens[i])) \ + return new LDGibberish (zLine, str::mkfmt ("Token #%u was `%s`, expected a number", \ + (i + 1), tokens[i].chars())); + +LDObject* parseLine (str zLine) { + str zNoWhitespace = zLine; + stripWhitespace (zNoWhitespace); + if (!~zNoWhitespace) { + // Line was empty, or only consisted of whitespace + return new LDEmpty; + } + + vector<str> tokens = zLine / " "; + + // Rid leading all-whitespace tokens + while (tokens.size() && !(~tokens[0])) + tokens.erase (tokens.begin()); + + if (~tokens[0] != 1) + return new LDGibberish (zLine, "Illogical line code"); + + char const c = tokens[0][0]; + switch (c - '0') { + case 0: + { + // Comment + LDComment* obj = new LDComment; + obj->zText = zLine.substr (2, -1); + return obj; + } + + case 1: + { + // Subfile + CHECK_TOKEN_COUNT (15) + CHECK_TOKEN_NUMBERS (1, 13) + +#ifndef WIN32 + tokens[14].replace ("\\", "/"); +#endif // WIN32 + + // Try open the file + OpenFile* pFile = findLoadedFile (tokens[14]); + if (!pFile) + pFile = openDATFile (tokens[14]); + + // If we cannot open the file, mark it an error + if (!pFile) + return new LDGibberish (zLine, "Could not open referred file"); + + LDSubfile* obj = new LDSubfile; + obj->dColor = atoi (tokens[1]); + obj->vPosition = parseVertex (zLine, 2); // 2 - 4 + + for (short i = 0; i < 9; ++i) + obj->faMatrix[i] = atof (tokens[i + 5]); // 5 - 13 + + obj->zFileName = tokens[14]; + obj->pFile = pFile; + return obj; + } + + case 2: + { + CHECK_TOKEN_COUNT (8) + CHECK_TOKEN_NUMBERS (1, 7) + + // Line + LDLine* obj = new LDLine; + obj->dColor = getWordInt (zLine, 1); + for (short i = 0; i < 2; ++i) + obj->vaCoords[i] = parseVertex (zLine, 2 + (i * 3)); // 2 - 7 + return obj; + } + + case 3: + { + CHECK_TOKEN_COUNT (11) + CHECK_TOKEN_NUMBERS (1, 10) + + // Triangle + LDTriangle* obj = new LDTriangle; + obj->dColor = getWordInt (zLine, 1); + + for (short i = 0; i < 3; ++i) + obj->vaCoords[i] = parseVertex (zLine, 2 + (i * 3)); // 2 - 10 + + return obj; + } + + case 4: + { + CHECK_TOKEN_COUNT (14) + CHECK_TOKEN_NUMBERS (1, 13) + + // Quadrilateral + LDQuad* obj = new LDQuad; + obj->dColor = getWordInt (zLine, 1); + + for (short i = 0; i < 4; ++i) + obj->vaCoords[i] = parseVertex (zLine, 2 + (i * 3)); // 2 - 13 + + return obj; + } + + case 5: + { + CHECK_TOKEN_COUNT (14) + CHECK_TOKEN_NUMBERS (1, 13) + + // Conditional line + LDCondLine* obj = new LDCondLine; + obj->dColor = getWordInt (zLine, 1); + + for (short i = 0; i < 2; ++i) + obj->vaCoords[i] = parseVertex (zLine, 2 + (i * 3)); // 2 - 7 + + for (short i = 0; i < 2; ++i) + obj->vaControl[i] = parseVertex (zLine, 8 + (i * 3)); // 8 - 13 + return obj; + } + + default: // Strange line we couldn't parse + return new LDGibberish (zLine, "Unknown line code number"); + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/file.h Mon Mar 18 12:20:48 2013 +0200 @@ -0,0 +1,48 @@ +#ifndef __FILE_H__ +#define __FILE_H__ + +#include "common.h" +#include "ldtypes.h" +#include "str.h" + +// ============================================================================= +// OpenFile +// +// The OpenFile class stores a file opened in LDForge either as a editable file +// for the user or for subfile caching. Its methods handle file input and output. +// ============================================================================= +class OpenFile { +public: + str zFileName, zTitle; + vector<LDObject*> objects; + + // Closes this OpenFile. The object is deleted in the process. + void close (); + + // Saves this file to disk. + void save (str zPath = ""); +}; + +// Close all current loaded files and start off blank. +void newFile (); + +// Opens the given file as the main file. Everything is closed first. +void openMainFile (str zPath); + +// Finds an OpenFile by name or nullptr if not open +OpenFile* findLoadedFile (str name); + +// Opens the given file and parses the LDraw code within. Returns a pointer +// to the opened file or nullptr on error. +OpenFile* openDATFile (str path); + +// Close all open files, whether user-opened or subfile caches. +void closeAll (); + +// Parses a string line containing an LDraw object and returns the object parsed. +LDObject* parseLine (str zLine); + +extern vector<str> g_zaFileLoadPaths; +extern vector<OpenFile*> g_LoadedFiles; + +#endif // __FILE_H__ \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gldraw.cpp Mon Mar 18 12:20:48 2013 +0200 @@ -0,0 +1,158 @@ +#include <QtGui> +#include <QGLWidget> +#include "common.h" +#include "file.h" +#include "gldraw.h" +#include "bbox.h" + +renderer::renderer (QWidget* parent) { + parent = parent; // shhh, GCC + fRotX = fRotY = fRotZ = 0.0; + fZoom = 1.0; +} + +void renderer::initializeGL () { + glLoadIdentity(); + glMatrixMode (GL_MODELVIEW); + glClearColor (0.8f, 0.8f, 0.85f, 1.0f); + glEnable (GL_DEPTH_TEST); + glShadeModel (GL_SMOOTH); + glEnable (GL_MULTISAMPLE); + + CompileObjects (); +} + +void renderer::hardRefresh () { + CompileObjects (); + paintGL (); +} + +void renderer::resizeGL (int w, int h) { + glViewport (0, 0, w, h); +} + +void renderer::paintGL () { + glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glPushMatrix (); + glTranslatef ( + (g_BBox.v0.x + g_BBox.v1.x) / -2.0, + (g_BBox.v0.y + g_BBox.v1.y) / -2.0, + (g_BBox.v0.z + g_BBox.v1.z) / -2.0 + ); + + // glTranslatef (0.0f, 0.0f, -5.0f); + glTranslatef (0.0f, 0.0f, fZoom); + + // glScalef (0.75f, 1.15f, 0.0f); + glRotatef (fRotX, 1.0f, 0.0f, 0.0f); + glRotatef (fRotY, 0.0f, 1.0f, 0.0f); + glRotatef (fRotZ, 0.0f, 0.0f, 1.0f); + + glMatrixMode (GL_MODELVIEW); + + glCallList (objlist); + glColor3f (0.0, 0.5, 1.0); + glPopMatrix (); +} + +void renderer::CompileObjects () { + printf ("compile all objects\n"); + + objlist = glGenLists (1); + glNewList (objlist, GL_COMPILE); + + if (!g_CurrentFile) { + printf ("renderer: no files loaded, cannot compile anything\n"); + return; + } + + for (ulong i = 0; i < g_CurrentFile->objects.size(); i++) + CompileOneObject (g_CurrentFile->objects[i]); + + glEndList (); +} + +#define GL_VERTEX(V) \ + glVertex3d (V.x, V.y, V.z); + +void renderer::CompileOneObject (LDObject* obj) { + if (!obj) + return; + + switch (obj->getType ()) { + case OBJ_CondLine: // For now, treat condlines like normal lines. + case OBJ_Line: + { + glColor3f (0.0f, 0.0f, 0.0f); // Draw all lines black for now + // draw lines + LDLine* line = static_cast<LDLine*> (obj); + glBegin (GL_LINES); + for (short i = 0; i < 2; ++i) + GL_VERTEX (line->vaCoords[i]) + glEnd (); + } + break; + + case OBJ_Triangle: + { + LDTriangle* tri = static_cast<LDTriangle*> (obj); + glColor3f (0.5f, 0.5f, 0.5f); // Draw all polygons gray for now + glBegin (GL_TRIANGLES); + for (short i = 0; i < 3; ++i) + GL_VERTEX (tri->vaCoords[i]) + glEnd (); + } + break; + + case OBJ_Quad: + { + LDQuad* quad = static_cast<LDQuad*> (obj); + glColor3f (0.5f, 0.5f, 0.5f); + glBegin (GL_QUADS); + for (short i = 0; i < 4; ++i) + GL_VERTEX (quad->vaCoords[i]) + glEnd (); + } + break; + + default: + break; + } +} + +void renderer::ClampAngle (double& fAngle) { + while (fAngle < 0) + fAngle += 360.0; + while (fAngle > 360.0) + fAngle -= 360.0; +} + +void renderer::mouseMoveEvent (QMouseEvent *event) { + int dx = event->x () - lastPos.x (); + int dy = event->y () - lastPos.y (); + + if (event->buttons () & Qt::LeftButton) { + fRotX = fRotX + (dy); + fRotY = fRotY + (dx); + ClampAngle (fRotX); + ClampAngle (fRotY); + } + + if (event->buttons () & Qt::RightButton) { + fRotX = fRotX + (dy); + fRotZ = fRotZ + (dx); + ClampAngle (fRotX); + ClampAngle (fRotZ); + } + + if (event->buttons () & Qt::MidButton) { + fZoom += (dy / 100.0); + fZoom = clamp (fZoom, 0.1, 10.0); + } + + printf ("%.3f %.3f %.3f %.3f\n", + fRotX, fRotY, fRotZ, fZoom); + lastPos = event->pos(); + updateGL (); +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gldraw.h Mon Mar 18 12:20:48 2013 +0200 @@ -0,0 +1,32 @@ +#ifndef __GLDRAW_H__ +#define __GLDRAW_H__ + +#include <QGLWidget> +#include "common.h" +#include "ldtypes.h" + +class renderer : public QGLWidget { + Q_OBJECT + +public: + renderer(QWidget* parent = NULL); + void hardRefresh (); + void CompileObjects (); + double fRotX, fRotY, fRotZ; + QPoint lastPos; + double fZoom; + +protected: + void initializeGL (); + void resizeGL (int w, int h); + void paintGL (); + + void mouseMoveEvent (QMouseEvent *event); + +private: + GLuint objlist; + void CompileOneObject (LDObject* obj); + void ClampAngle (double& fAngle); +}; + +#endif // __GLDRAW_H__ \ No newline at end of file
--- a/gui.cpp Mon Mar 18 12:15:23 2013 +0200 +++ b/gui.cpp Mon Mar 18 12:20:48 2013 +0200 @@ -1,9 +1,9 @@ #include <QtGui> #include "common.h" -#include "draw.h" +#include "gldraw.h" #include "gui.h" -#include "io.h" +#include "file.h" #include "zz_setContentsDialog.h"
--- a/gui.h Mon Mar 18 12:15:23 2013 +0200 +++ b/gui.h Mon Mar 18 12:20:48 2013 +0200 @@ -8,7 +8,7 @@ #include <QTreeWidget> #include <QToolBar> #include <QTextEdit> -#include "draw.h" +#include "gldraw.h" class ForgeWindow : public QMainWindow { Q_OBJECT
--- a/io.cpp Mon Mar 18 12:15:23 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,312 +0,0 @@ -#include <vector> - -#include "common.h" -#include "io.h" -#include "misc.h" -#include "bbox.h" -#include "gui.h" - -vector<str> g_zaFileLoadPaths; - -// ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= -OpenFile* findLoadedFile (str name) { - for (ulong i = 0; i < g_LoadedFiles.size(); i++) { - OpenFile* const file = g_LoadedFiles[i]; - if (file->zFileName == name) - return file; - } - - return nullptr; -} - -// ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= -OpenFile* openDATFile (str path) { - logf ("Opening %s...\n", path.chars()); - - FILE* fp = fopen (path.chars (), "r"); - - if (!fp) { - for (ushort i = 0; i < g_zaFileLoadPaths.size(); ++i) { - str zFilePath = str::mkfmt ("%s/%s", g_zaFileLoadPaths[i].chars(), path.chars()); - fp = fopen (zFilePath.chars (), "r"); - - if (fp) - break; - } - } - - if (!fp) { - logf (LOG_Error, "Couldn't open %s: %s\n", path.chars (), strerror (errno)); - return nullptr; - } - - OpenFile* load = new OpenFile; - ulong numWarnings = 0; - - load->zFileName = path; - - vector<str> lines; - - { - char line[1024]; - while (fgets (line, sizeof line, fp)) { - // Trim the trailing newline - str zLine = line; - while (zLine[~zLine - 1] == '\n' || zLine[~zLine - 1] == '\r') - zLine -= 1; - - lines.push_back (zLine); - } - } - - fclose (fp); - - for (ulong i = 0; i < lines.size(); ++i) { - LDObject* obj = parseLine (lines[i]); - load->objects.push_back (obj); - - // Check for parse errors and warn abotu tthem - if (obj->getType() == OBJ_Gibberish) { - logf (LOG_Warning, "Couldn't parse line #%lu: %s\n", - i, static_cast<LDGibberish*> (obj)->zReason.chars()); - logf (LOG_Warning, "- Line was: %s\n", lines[i].chars()); - numWarnings++; - } - } - - g_LoadedFiles.push_back (load); - - logf (LOG_Success, "File %s parsed successfully (%lu warning%s).\n", - path.chars(), numWarnings, PLURAL (numWarnings)); - - return load; -} - -// ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= -// Clear everything from the model -void OpenFile::close () { - for (ulong j = 0; j < objects.size(); ++j) - delete objects[j]; - - delete this; -} - -// ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= -void closeAll () { - if (!g_LoadedFiles.size()) - return; - - // Remove all loaded files and the objects they contain - for (ushort i = 0; i < g_LoadedFiles.size(); i++) { - OpenFile* f = g_LoadedFiles[i]; - f->close (); - } - - // Clear the array - g_LoadedFiles.clear(); - g_CurrentFile = NULL; - - g_qWindow->R->hardRefresh(); -} - -// ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= -void newFile () { - // Create a new anonymous file and set it to our current - closeAll (); - - OpenFile* f = new OpenFile; - f->zFileName = ""; - g_LoadedFiles.push_back (f); - g_CurrentFile = f; - - g_BBox.calculate(); - g_qWindow->buildObjList (); - g_qWindow->R->hardRefresh(); -} - -// ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= -void openMainFile (str zPath) { - closeAll (); - - OpenFile* pFile = openDATFile (zPath); - g_CurrentFile = pFile; - - // Recalculate the bounding box - g_BBox.calculate(); - - // Rebuild the object tree view now. - g_qWindow->buildObjList (); - g_qWindow->setTitle (); -} - -// ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= -void OpenFile::save (str zPath) { - if (!~zPath) - zPath = zFileName; - - FILE* fp = fopen (zPath, "w"); - if (!fp) - return; - - // Write all entries now - for (ulong i = 0; i < objects.size(); ++i) { - LDObject* obj = objects[i]; - - // LDraw requires lines to have DOS line endings - str zLine = str::mkfmt ("%s\r\n",obj->getContents ().chars ()); - - fwrite (zLine.chars(), 1, ~zLine, fp); - } - - fclose (fp); -} - -// ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= -#define CHECK_TOKEN_COUNT(N) \ - if (tokens.size() != N) \ - return new LDGibberish (zLine, "Bad amount of tokens"); - -#define CHECK_TOKEN_NUMBERS(MIN,MAX) \ - for (ushort i = MIN; i <= MAX; ++i) \ - if (!isNumber (tokens[i])) \ - return new LDGibberish (zLine, str::mkfmt ("Token #%u was `%s`, expected a number", \ - (i + 1), tokens[i].chars())); - -LDObject* parseLine (str zLine) { - str zNoWhitespace = zLine; - stripWhitespace (zNoWhitespace); - if (!~zNoWhitespace) { - // Line was empty, or only consisted of whitespace - return new LDEmpty; - } - - vector<str> tokens = zLine / " "; - - // Rid leading all-whitespace tokens - while (tokens.size() && !(~tokens[0])) - tokens.erase (tokens.begin()); - - if (~tokens[0] != 1) - return new LDGibberish (zLine, "Illogical line code"); - - char const c = tokens[0][0]; - switch (c - '0') { - case 0: - { - // Comment - LDComment* obj = new LDComment; - obj->zText = zLine.substr (2, -1); - return obj; - } - - case 1: - { - // Subfile - CHECK_TOKEN_COUNT (15) - CHECK_TOKEN_NUMBERS (1, 13) - -#ifndef WIN32 - tokens[14].replace ("\\", "/"); -#endif // WIN32 - - // Try open the file - OpenFile* pFile = findLoadedFile (tokens[14]); - if (!pFile) - pFile = openDATFile (tokens[14]); - - // If we cannot open the file, mark it an error - if (!pFile) - return new LDGibberish (zLine, "Could not open referred file"); - - LDSubfile* obj = new LDSubfile; - obj->dColor = atoi (tokens[1]); - obj->vPosition = parseVertex (zLine, 2); // 2 - 4 - - for (short i = 0; i < 9; ++i) - obj->faMatrix[i] = atof (tokens[i + 5]); // 5 - 13 - - obj->zFileName = tokens[14]; - obj->pFile = pFile; - return obj; - } - - case 2: - { - CHECK_TOKEN_COUNT (8) - CHECK_TOKEN_NUMBERS (1, 7) - - // Line - LDLine* obj = new LDLine; - obj->dColor = getWordInt (zLine, 1); - for (short i = 0; i < 2; ++i) - obj->vaCoords[i] = parseVertex (zLine, 2 + (i * 3)); // 2 - 7 - return obj; - } - - case 3: - { - CHECK_TOKEN_COUNT (11) - CHECK_TOKEN_NUMBERS (1, 10) - - // Triangle - LDTriangle* obj = new LDTriangle; - obj->dColor = getWordInt (zLine, 1); - - for (short i = 0; i < 3; ++i) - obj->vaCoords[i] = parseVertex (zLine, 2 + (i * 3)); // 2 - 10 - - return obj; - } - - case 4: - { - CHECK_TOKEN_COUNT (14) - CHECK_TOKEN_NUMBERS (1, 13) - - // Quadrilateral - LDQuad* obj = new LDQuad; - obj->dColor = getWordInt (zLine, 1); - - for (short i = 0; i < 4; ++i) - obj->vaCoords[i] = parseVertex (zLine, 2 + (i * 3)); // 2 - 13 - - return obj; - } - - case 5: - { - CHECK_TOKEN_COUNT (14) - CHECK_TOKEN_NUMBERS (1, 13) - - // Conditional line - LDCondLine* obj = new LDCondLine; - obj->dColor = getWordInt (zLine, 1); - - for (short i = 0; i < 2; ++i) - obj->vaCoords[i] = parseVertex (zLine, 2 + (i * 3)); // 2 - 7 - - for (short i = 0; i < 2; ++i) - obj->vaControl[i] = parseVertex (zLine, 8 + (i * 3)); // 8 - 13 - return obj; - } - - default: // Strange line we couldn't parse - return new LDGibberish (zLine, "Unknown line code number"); - } -} \ No newline at end of file
--- a/io.h Mon Mar 18 12:15:23 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -#ifndef __IO_H__ -#define __IO_H__ - -#include "common.h" -#include "ldtypes.h" -#include "str.h" - -// ============================================================================= -// OpenFile -// -// The OpenFile class stores a file opened in LDForge either as a editable file -// for the user or for subfile caching. Its methods handle file input and output. -// ============================================================================= -class OpenFile { -public: - str zFileName, zTitle; - vector<LDObject*> objects; - - // Closes this OpenFile. The object is deleted in the process. - void close (); - - // Saves this file to disk. - void save (str zPath = ""); -}; - -// Close all current loaded files and start off blank. -void newFile (); - -// Opens the given file as the main file. Everything is closed first. -void openMainFile (str zPath); - -// Finds an OpenFile by name or nullptr if not open -OpenFile* findLoadedFile (str name); - -// Opens the given file and parses the LDraw code within. Returns a pointer -// to the opened file or nullptr on error. -OpenFile* openDATFile (str path); - -// Close all open files, whether user-opened or subfile caches. -void closeAll (); - -// Parses a string line containing an LDraw object and returns the object parsed. -LDObject* parseLine (str zLine); - -extern vector<str> g_zaFileLoadPaths; -extern vector<OpenFile*> g_LoadedFiles; - -#endif \ No newline at end of file
--- a/ldtypes.cpp Mon Mar 18 12:15:23 2013 +0200 +++ b/ldtypes.cpp Mon Mar 18 12:20:48 2013 +0200 @@ -1,6 +1,6 @@ #include "common.h" #include "ldtypes.h" -#include "io.h" +#include "file.h" #include "misc.h" const char* g_saObjTypeNames[] = {
--- a/main.cpp Mon Mar 18 12:15:23 2013 +0200 +++ b/main.cpp Mon Mar 18 12:20:48 2013 +0200 @@ -1,6 +1,6 @@ #include <QApplication> #include "gui.h" -#include "io.h" +#include "file.h" #include "bbox.h" #include "misc.h"
--- a/zz_setContentsDialog.cpp Mon Mar 18 12:15:23 2013 +0200 +++ b/zz_setContentsDialog.cpp Mon Mar 18 12:20:48 2013 +0200 @@ -1,7 +1,7 @@ #include <QAbstractButton> #include <qboxlayout.h> #include "zz_setContentsDialog.h" -#include "io.h" +#include "file.h" #include "gui.h" // =============================================================================