diff --git a/common/library.cpp b/common/library.cpp index f3226cad..bb15adde 100755 --- a/common/library.cpp +++ b/common/library.cpp @@ -736,8 +736,61 @@ void PiecesLibrary::RemoveCategory(int Index) // ============================================================================= // Pieces handling stuff +bool PiecesLibrary::DeleteAllPieces() +{ + FileDisk newbin, newidx, oldbin, oldidx; + char file1[LC_MAXPATH], file2[LC_MAXPATH], tmp[256]; + + strcpy(file1, m_LibraryPath); + strcat(file1, "pieces-b.old"); + remove(file1); + strcpy(file2, m_LibraryPath); + strcat(file2, "pieces.bin"); + rename(file2, file1); + + if ((!oldbin.Open(file1, "rb")) || + (!newbin.Open(file2, "wb"))) + return false; + + strcpy(file1, m_LibraryPath); + strcat(file1, "pieces-i.old"); + remove(file1); + strcpy(file2, m_LibraryPath); + strcat(file2, "pieces.idx"); + rename(file2, file1); + + if ((!oldidx.Open(file1, "rb")) || + (!newidx.Open(file2, "wb"))) + return false; + + oldidx.Seek(0, SEEK_SET); + oldidx.Read(tmp, 34); + newidx.Write(tmp, 34); + oldbin.Read(tmp, 32); + newbin.Write(tmp, 32); + + // list of moved pieces + lcuint16 moved = 0; + newidx.WriteShort(&moved, 1); + + // info at the end + lcuint32 binoff = newbin.GetPosition(); + newidx.WriteLong(&binoff, 1); + lcuint16 count = 0; + newidx.WriteShort(&count, 1); + + oldidx.Close(); + oldbin.Close(); + newidx.Close(); + newbin.Close(); + + m_Modified = true; + + return true; +} + // Remove pieces from the library -bool PiecesLibrary::DeletePieces (PtrArray& Pieces) +bool PiecesLibrary::DeletePieces(PtrArray& Pieces) { FileDisk newbin, newidx, oldbin, oldidx; char file1[LC_MAXPATH], file2[LC_MAXPATH], tmp[200]; @@ -793,7 +846,7 @@ bool PiecesLibrary::DeletePieces (PtrArray& Pieces) oldidx.Read(&name, LC_PIECE_NAME_LEN); for (i = 0; i < Pieces.GetSize(); i++) - if (strcmp(name, Pieces[i]->m_strName) == 0) + if (strcmp(name, Pieces[i]) == 0) break; if (i != Pieces.GetSize()) @@ -1400,7 +1453,7 @@ bool PiecesLibrary::ImportTexture (const char* Name) // ============================================================================= // LDraw support -bool PiecesLibrary::ImportLDrawPiece (const char* Filename) +bool PiecesLibrary::ImportLDrawPiece(const char* Filename, File* NewIdxFile, File* NewBinFile, File* OldIdxFile, File* OldBinFile) { LC_LDRAW_PIECE piece; @@ -1408,16 +1461,112 @@ bool PiecesLibrary::ImportLDrawPiece (const char* Filename) if (ReadLDrawPiece (Filename, &piece)) { -// if (FindPieceInfo (piece.name) != NULL) -// Sys_MessageBox ("Piece already exists in the library !"); + char* Moved = strstr(piece.description, "~Moved to "); + if (Moved) + { + lcuint16 Count; + OldIdxFile->Seek(-(2+4+2), SEEK_END); + OldIdxFile->ReadShort(&Count, 1); + lcuint32 cs = Count * 2 * LC_PIECE_NAME_LEN; + OldIdxFile->Seek(-(long)(cs+2), SEEK_CUR); - if (SaveLDrawPiece (&piece)) - Sys_MessageBox ("Piece successfully imported."); - else + lcuint32 Length = OldIdxFile->GetPosition(); + void* Buffer = malloc(Length); + OldIdxFile->Seek(0, SEEK_SET); + OldIdxFile->Read(Buffer, Length); + NewIdxFile->Seek(0, SEEK_SET); + NewIdxFile->Write(Buffer, Length); + free(Buffer); + + Buffer = malloc(cs); + OldIdxFile->Read(Buffer, cs); + char* Reference = (char*)Buffer; + + // Add piece to moved list. + if (!strchr(Moved, '\\') && !strchr(Moved, '/')) + { + Moved += strlen("~Moved to "); + _strupr(Moved); + + char* Dst = NULL; + for (int i = 0; i < Count; i++) + { + if (!strncmp(&Reference[i*2*LC_PIECE_NAME_LEN], piece.name, LC_PIECE_NAME_LEN)) + { + Dst = &Reference[i*LC_PIECE_NAME_LEN+LC_PIECE_NAME_LEN]; + memset(Dst, 0, LC_PIECE_NAME_LEN); + memcpy(Dst, Moved, strlen(Moved)); + } + } + + if (!Dst) + { + Buffer = realloc(Buffer, 2*LC_PIECE_NAME_LEN*(Count+1)); + Reference = (char*)Buffer; + memset(&Reference[Count*2*LC_PIECE_NAME_LEN], 0, 2*LC_PIECE_NAME_LEN); + memcpy(&Reference[Count*2*LC_PIECE_NAME_LEN], piece.name, strlen(piece.name)); + memcpy(&Reference[Count*2*LC_PIECE_NAME_LEN+LC_PIECE_NAME_LEN], Moved, strlen(Moved)); + Count++; + } + } + + NewIdxFile->Write(Reference, Count*2*LC_PIECE_NAME_LEN); + NewIdxFile->WriteShort(&Count, 1); + free(Buffer); + + Buffer = malloc(4+2); + OldIdxFile->Seek(-(4+2), SEEK_END); + OldIdxFile->Read(Buffer, 4+2); + NewIdxFile->Write(Buffer, 4+2); + free(Buffer); + + OldBinFile->Seek(0, SEEK_END); + Length = OldBinFile->GetPosition(); + Buffer = malloc(Length); + OldBinFile->Seek(0, SEEK_SET); + OldBinFile->Read(Buffer, Length); + NewBinFile->Seek(0, SEEK_SET); + NewBinFile->Write(Buffer, Length); + free(Buffer); + + // Delete existing piece. +// lcPtrArray Pieces; +// Pieces.Add(piece.name); +// DeletePieces(Pieces); + } + else if (!SaveLDrawPiece(&piece, NewIdxFile, NewBinFile, OldIdxFile, OldBinFile)) + { + fprintf(stderr, "Error saving library after importing %s.\n", Filename); Sys_MessageBox ("Error saving library."); + return false; + } } else + { + void* Buffer; + lcuint32 Length; + + OldBinFile->Seek(0, SEEK_END); + Length = OldBinFile->GetPosition(); + Buffer = malloc(Length); + OldBinFile->Seek(0, SEEK_SET); + OldBinFile->Read(Buffer, Length); + NewBinFile->Seek(0, SEEK_SET); + NewBinFile->Write(Buffer, Length); + free(Buffer); + + OldIdxFile->Seek(0, SEEK_END); + Length = OldIdxFile->GetPosition(); + Buffer = malloc(Length); + OldIdxFile->Seek(0, SEEK_SET); + OldIdxFile->Read(Buffer, Length); + NewIdxFile->Seek(0, SEEK_SET); + NewIdxFile->Write(Buffer, Length); + free(Buffer); + + fprintf(stderr, "Error reading file %s\n", Filename); Sys_MessageBox ("Error reading file."); + } FreeLDrawPiece(&piece); @@ -2355,64 +2504,47 @@ bool ReadLDrawPiece(const char* filename, LC_LDRAW_PIECE* piece) return true; } -bool SaveLDrawPiece(LC_LDRAW_PIECE* piece) +bool SaveLDrawPiece(LC_LDRAW_PIECE* piece, File* NewIdxFile, File* NewBinFile, File* OldIdxFile, File* OldBinFile) { - FileDisk newbin, newidx, oldbin, oldidx; - char file1[LC_MAXPATH], file2[LC_MAXPATH]; - unsigned short count, moved; - unsigned long i, j, cs, binoff = 0, delta; + lcuint16 count, moved; + lcuint32 i, j, cs, binoff = 0, delta; void* membuf; - short scale, sb[6]; + lcuint16 scale, sb[6]; PiecesLibrary *pLib = lcGetPiecesLibrary(); - strcpy(file1, pLib->GetLibraryPath()); - strcat(file1, "pieces-b.old"); - remove(file1); - strcpy(file2, pLib->GetLibraryPath()); - strcat(file2, "pieces.bin"); - rename(file2, file1); + File& NewIdx = *NewIdxFile; + File& NewBin = *NewBinFile; + File& OldIdx = *OldIdxFile; + File& OldBin = *OldBinFile; - if ((!oldbin.Open(file1, "rb")) || - (!newbin.Open(file2, "wb"))) - return false; + OldIdx.Seek(0, SEEK_SET); + OldBin.Seek(0, SEEK_SET); - strcpy(file1, pLib->GetLibraryPath()); - strcat(file1, "pieces-i.old"); - remove(file1); - strcpy(file2, pLib->GetLibraryPath()); - strcat(file2, "pieces.idx"); - rename(file2, file1); - - if ((!oldidx.Open(file1, "rb")) || - (!newidx.Open(file2, "wb"))) - return false; - - - oldidx.Seek(-2, SEEK_END); - oldidx.ReadShort(&count, 1); - oldidx.Seek(34, SEEK_SET); + OldIdx.Seek(-2, SEEK_END); + OldIdx.ReadShort(&count, 1); + OldIdx.Seek(34, SEEK_SET); for (j = 0; j < count; j++) { char name[LC_PIECE_NAME_LEN]; - oldidx.Read(name, LC_PIECE_NAME_LEN); + OldIdx.Read(name, LC_PIECE_NAME_LEN); if (strcmp(name, piece->name) == 0) { - oldidx.Seek(64+12+1+4, SEEK_CUR); - oldidx.ReadLong(&binoff, 1); - oldidx.ReadLong(&delta, 1); - oldidx.Seek(-(LC_PIECE_NAME_LEN+64+12+1+4+4+4), SEEK_CUR); + OldIdx.Seek(64+12+1+4, SEEK_CUR); + OldIdx.ReadLong(&binoff, 1); + OldIdx.ReadLong(&delta, 1); + OldIdx.Seek(-(LC_PIECE_NAME_LEN+64+12+1+4+4+4), SEEK_CUR); delta += binoff; break; } - oldidx.Seek(64+12+1+4+4+4, SEEK_CUR); + OldIdx.Seek(64+12+1+4+4+4, SEEK_CUR); } if (binoff == 0) - binoff = oldbin.GetLength(); + binoff = OldBin.GetLength(); - cs = oldidx.GetPosition(); + cs = OldIdx.GetPosition(); membuf = malloc(cs); if (membuf == NULL) { @@ -2420,9 +2552,9 @@ bool SaveLDrawPiece(LC_LDRAW_PIECE* piece) return false; } - oldidx.Seek(0, SEEK_SET); - oldidx.Read(membuf, cs); - newidx.Write(membuf, cs); + OldIdx.Seek(0, SEEK_SET); + OldIdx.Read(membuf, cs); + NewIdx.Write(membuf, cs); free(membuf); membuf = malloc (binoff); @@ -2432,9 +2564,9 @@ bool SaveLDrawPiece(LC_LDRAW_PIECE* piece) return false; } - oldbin.Seek(0, SEEK_SET); - oldbin.Read(membuf, binoff); - newbin.Write(membuf, binoff); + OldBin.Seek(0, SEEK_SET); + OldBin.Read(membuf, binoff); + NewBin.Write(membuf, binoff); free(membuf); // Save piece @@ -2553,68 +2685,68 @@ bool SaveLDrawPiece(LC_LDRAW_PIECE* piece) scale = 100; // Write the vertex data - newbin.WriteLong(&piece->verts_count, 1); + NewBin.WriteLong(&piece->verts_count, 1); for (i = 0; i < piece->verts_count; i++) { float tmp[3] = { scale*piece->verts[(i*3)], scale*piece->verts[(i*3)+1], scale*piece->verts[(i*3)+2] }; short sh[3] = { (short)tmp[0], (short)tmp[1], (short)tmp[2] }; - newbin.WriteShort(&sh, 3); + NewBin.WriteShort(&sh, 3); } // Write the connections information for (s = 0, con = piece->connections; con; con = con->next) s++; - newbin.WriteShort(&s, 1); + NewBin.WriteShort(&s, 1); for (con = piece->connections; con; con = con->next) { float tmp[3] = { scale*con->pos[0], scale*con->pos[1], scale*con->pos[2] }; short sh[3] = { (short)tmp[0], (short)tmp[1], (short)tmp[2] }; - newbin.WriteByte(&con->type, 1); - newbin.WriteShort(sh, 3); + NewBin.WriteByte(&con->type, 1); + NewBin.WriteShort(sh, 3); sh[0] = (short)(con->up[0]*(1<<14)); sh[1] = (short)(con->up[1]*(1<<14)); sh[2] = (short)(con->up[2]*(1<<14)); - newbin.WriteShort(sh, 3); + NewBin.WriteShort(sh, 3); } // Textures for (bt = 0, tex = piece->textures; tex; tex = tex->next) bt++; - newbin.WriteByte(&bt, 1); + NewBin.WriteByte(&bt, 1); for (tex = piece->textures; tex; tex = tex->next) { - newbin.WriteByte(&tex->color, 1); - newbin.Write(tex->name, 8); + NewBin.WriteByte(&tex->color, 1); + NewBin.Write(tex->name, 8); for (i = 0; i < 12; i++) { float tmp[1] = { tex->points[i]*scale }; short sh[1] = { (short)tmp[0] }; - newbin.WriteShort(sh, 1); + NewBin.WriteShort(sh, 1); } for (i = 12; i < 20; i++) { float tmp = tex->points[i]; short sh[1] = { (short)tmp }; - newbin.WriteShort(sh, 1); + NewBin.WriteShort(sh, 1); } } for (s = 0, group = piece->groups; group; group = group->next) s++; - newbin.WriteShort(&s, 1); + NewBin.WriteShort(&s, 1); for (group = piece->groups; group; group = group->next) { for (bt = 0; bt < 5; bt++) if (!group->connections[bt]) break; - newbin.WriteByte(&bt, 1); + NewBin.WriteByte(&bt, 1); for (bt = 0; bt < 5; bt++) { @@ -2624,15 +2756,15 @@ bool SaveLDrawPiece(LC_LDRAW_PIECE* piece) for (s = 0, con = piece->connections; con; con = con->next, s++) if (con == group->connections[bt]) break; - newbin.WriteShort(&s, 1); + NewBin.WriteShort(&s, 1); } // TODO: make this endian-safe - newbin.Write(group->drawinfo, group->infosize); + NewBin.Write(group->drawinfo, group->infosize); } // Now write the index - newidx.Write(piece->name, LC_PIECE_NAME_LEN); - newidx.Write(piece->description, 64); + NewIdx.Write(piece->name, LC_PIECE_NAME_LEN); + NewIdx.Write(piece->description, 64); for (i = 0; i < 6; i++) { @@ -2642,7 +2774,7 @@ bool SaveLDrawPiece(LC_LDRAW_PIECE* piece) // sb[i] = scale*box[i]; sb[i] = (short)ff; } - newidx.WriteShort(sb, 6); + NewIdx.WriteShort(sb, 6); // Calculate flags. bt = LC_PIECE_COUNT; @@ -2653,63 +2785,58 @@ bool SaveLDrawPiece(LC_LDRAW_PIECE* piece) bt |= LC_PIECE_MEDIUM; if (piece->long_info) - bt |= LC_PIECE_LONGDATA; + bt |= LC_PIECE_LONGDATA_FILE; - newidx.WriteByte(&bt, 1); + NewIdx.WriteByte(&bt, 1); i = 0;//PiecesLibrary::GetDefaultPieceGroup(piece->description); - newidx.WriteLong(&i, 1); - newidx.WriteLong(&binoff, 1); + NewIdx.WriteLong(&i, 1); + NewIdx.WriteLong(&binoff, 1); - i = newbin.GetLength() - binoff; - newidx.WriteLong(&i, 1); + i = NewBin.GetLength() - binoff; + NewIdx.WriteLong(&i, 1); // replacing a piece if (j != count) { - unsigned long d = newbin.GetPosition() - delta; - oldidx.Seek (LC_PIECE_NAME_LEN+64+12+1+4+4+4, SEEK_CUR); + unsigned long d = NewBin.GetPosition() - delta; + OldIdx.Seek (LC_PIECE_NAME_LEN+64+12+1+4+4+4, SEEK_CUR); for (j++; j < count; j++) { - unsigned long dw; + lcuint32 dw; char buf[LC_PIECE_NAME_LEN+64+12+1+4]; - oldidx.Read(buf, LC_PIECE_NAME_LEN+64+12+1+4); - oldidx.ReadLong(&dw, 1); + OldIdx.Read(buf, LC_PIECE_NAME_LEN+64+12+1+4); + OldIdx.ReadLong(&dw, 1); dw += d; - newidx.Write(buf, LC_PIECE_NAME_LEN+64+12+1+4); - newidx.WriteLong(&dw, 1); - oldidx.ReadLong(&dw, 1); - newidx.WriteLong(&dw, 1); + NewIdx.Write(buf, LC_PIECE_NAME_LEN+64+12+1+4); + NewIdx.WriteLong(&dw, 1); + OldIdx.ReadLong(&dw, 1); + NewIdx.WriteLong(&dw, 1); } - d = oldbin.GetLength()-delta; + d = OldBin.GetLength()-delta; membuf = malloc (d); - oldbin.Seek (delta, SEEK_SET); - oldbin.Read (membuf, d); - newbin.Write(membuf, d); + OldBin.Seek(delta, SEEK_SET); + OldBin.Read(membuf, d); + NewBin.Write(membuf, d); free(membuf); } else count++; // Fix the end of the index - oldidx.Seek(-(2+4+2), SEEK_END); - oldidx.ReadShort(&moved, 1); - cs = 2+(moved*16); - oldidx.Seek(-(long)cs, SEEK_CUR); + OldIdx.Seek(-(2+4+2), SEEK_END); + OldIdx.ReadShort(&moved, 1); + cs = 2+(moved*LC_PIECE_NAME_LEN*2); + OldIdx.Seek(-(long)cs, SEEK_CUR); membuf = malloc(cs); - oldidx.Read(membuf, cs); - newidx.Write(membuf, cs); + OldIdx.Read(membuf, cs); + NewIdx.Write(membuf, cs); free(membuf); - binoff = newbin.GetPosition(); - newidx.WriteLong(&binoff, 1); - newidx.WriteShort(&count, 1); - - oldidx.Close(); - oldbin.Close(); - newidx.Close(); - newbin.Close(); + binoff = NewBin.GetPosition(); + NewIdx.WriteLong(&binoff, 1); + NewIdx.WriteShort(&count, 1); return true; } diff --git a/common/library.h b/common/library.h index bf4247a8..9658e9a9 100755 --- a/common/library.h +++ b/common/library.h @@ -13,11 +13,11 @@ class PieceInfo; #define LC_CATEGORY_FILE_ID LC_FOURCC('C', 'A', 'T', 0) #define LC_CATEGORY_FILE_VERSION 0x0100 -typedef struct +struct PiecesLibraryCategory { String Name; String Keywords; -} PiecesLibraryCategory; +}; class PiecesLibrary { @@ -74,11 +74,12 @@ public: Texture* GetTexture(int index) const; // File operations. - bool DeletePieces(PtrArray& Pieces); + bool DeleteAllPieces(); + bool DeletePieces(PtrArray& Pieces); bool LoadUpdate(const char* update); bool DeleteTextures(char** Names, int NumTextures); bool ImportTexture(const char* Name); - bool ImportLDrawPiece(const char* Filename); + bool ImportLDrawPiece(const char* Filename, File* NewIdxFile, File* NewBinFile, File* OldIdxFile, File* OldBinFile); // Set when pieces are added/removed from the library. bool m_Modified; @@ -117,37 +118,37 @@ protected: // ============================================================================ // This should be cleaned and moved to the PiecesLibrary class -typedef struct connection_s +struct connection_t { unsigned char type; float pos[3]; float up[3]; - connection_s* next; -} connection_t; + connection_t* next; +}; -typedef struct group_s +struct group_t { connection_t* connections[5]; void* drawinfo; unsigned long infosize; - group_s* next; -} group_t; + group_t* next; +}; -typedef struct lineinfo_s +struct lineinfo_t { unsigned char type; unsigned char color; float points[12]; - lineinfo_s* next; -} lineinfo_t; + lineinfo_t* next; +}; -typedef struct texture_s +struct texture_t { float points[20]; unsigned char color; char name[9]; - texture_s* next; -} texture_t; + texture_t* next; +}; struct LC_LDRAW_PIECE { @@ -162,7 +163,7 @@ struct LC_LDRAW_PIECE }; bool ReadLDrawPiece(const char* filename, LC_LDRAW_PIECE* piece); -bool SaveLDrawPiece(LC_LDRAW_PIECE* piece); +bool SaveLDrawPiece(LC_LDRAW_PIECE* piece, File* NewIdxFile, File* NewBinFile, File* OldIdxFile, File* OldBinFile); void FreeLDrawPiece(LC_LDRAW_PIECE* piece); #endif // _LIBRARY_H_ diff --git a/common/piece.cpp b/common/piece.cpp index 324e6c16..2073b2d3 100644 --- a/common/piece.cpp +++ b/common/piece.cpp @@ -479,7 +479,7 @@ void Piece::MinIntersectDist(LC_CLICKLINE* pLine) float* verts = m_pPieceInfo->m_fVertexArray; - if (m_pPieceInfo->m_nFlags & LC_PIECE_LONGDATA) + if (m_pPieceInfo->m_nFlags & LC_PIECE_LONGDATA_INDICES) { lcuint32* info = (lcuint32*)m_pDrawInfo, colors, i; colors = *info; @@ -698,7 +698,7 @@ bool Piece::IntersectsVolume(const Vector4* Planes, int NumPlanes) float* verts = m_pPieceInfo->m_fVertexArray; bool ret = false; - if (m_pPieceInfo->m_nFlags & LC_PIECE_LONGDATA) + if (m_pPieceInfo->m_nFlags & LC_PIECE_LONGDATA_INDICES) { lcuint32* info = (lcuint32*)m_pDrawInfo, colors, i; colors = *info; @@ -904,7 +904,7 @@ void Piece::BuildDrawInfo() if (add) { - if (m_pPieceInfo->m_nFlags & LC_PIECE_LONGDATA) + if (m_pPieceInfo->m_nFlags & LC_PIECE_LONGDATA_INDICES) { lcuint32* p, curcol, colors; p = (lcuint32*)dg->drawinfo; @@ -956,7 +956,7 @@ void Piece::BuildDrawInfo() vert += (colcount*4)+1; // Build the info - if (m_pPieceInfo->m_nFlags & LC_PIECE_LONGDATA) + if (m_pPieceInfo->m_nFlags & LC_PIECE_LONGDATA_INDICES) { m_pDrawInfo = malloc(vert*sizeof(lcuint32)); lcuint32* drawinfo = (lcuint32*)m_pDrawInfo; @@ -1193,7 +1193,7 @@ void Piece::Render(bool bLighting, bool bEdges, unsigned char* nLastColor, bool* glDisable(GL_TEXTURE_2D); } - if (m_pPieceInfo->m_nFlags & LC_PIECE_LONGDATA) + if (m_pPieceInfo->m_nFlags & LC_PIECE_LONGDATA_INDICES) { lcuint32 colors, *info = (lcuint32*)m_pDrawInfo; colors = *info; diff --git a/common/pieceinf.cpp b/common/pieceinf.cpp index e6b79431..558d1e3b 100644 --- a/common/pieceinf.cpp +++ b/common/pieceinf.cpp @@ -427,9 +427,9 @@ void PieceInfo::LoadInformation() while (*bytes) { - if (*bytes == LC_MESH) - { - if ((fixverts > 65535) || (m_nFlags & LC_PIECE_LONGDATA)) + if (*bytes == LC_MESH) + { + if (m_nFlags & LC_PIECE_LONGDATA_FILE) { lcuint32 colors, *p; p = (lcuint32*)(bytes + 1); @@ -502,15 +502,8 @@ void PieceInfo::LoadInformation() m_fVertexArray = (float*)malloc(3*sizeof(float)*verts); m_nVertexCount = verts; - if ((verts > 65535) || (quads > 65535) || (fixquads > 65535)) - { - if ((m_nFlags & LC_PIECE_LONGDATA) == 0) - { - m_nFlags |= LC_PIECE_LONGDATA | LC_PIECE_LONGDATA_RUNTIME; - } - } - else - m_nFlags &= ~(LC_PIECE_LONGDATA | LC_PIECE_LONGDATA_RUNTIME); + if (verts > 65535 || quads > 65535) + m_nFlags |= LC_PIECE_LONGDATA_INDICES; // Copy the 'fixed' vertexes shorts = (lcint16*)(longs + 1); @@ -540,17 +533,17 @@ void PieceInfo::LoadInformation() bytes += sizeof(lcuint16); } - // Currently there's only one type of drawinfo (mesh or stud) - // per group but this will change in the future. - switch (*bytes) - { - case LC_MESH: - if ((fixverts > 65535) || (fixquads > 65535)) - { + // Currently there's only one type of drawinfo (mesh or stud) + // per group but this will change in the future. + switch (*bytes) + { + case LC_MESH: + if (m_nFlags & LC_PIECE_LONGDATA_FILE) + { lcuint32 colors, *p; bytes++; p = (lcuint32*)bytes; - *p = LCUINT32(*p); + *p = LCUINT32(*p); colors = *p; p++; @@ -608,7 +601,7 @@ void PieceInfo::LoadInformation() i = (unsigned char*)p - bytes; - if (m_nFlags & LC_PIECE_LONGDATA) + if (m_nFlags & LC_PIECE_LONGDATA_INDICES) { pGroup->drawinfo = malloc(i*sizeof(lcuint32)/sizeof(lcuint16)); longs = (lcuint32*)pGroup->drawinfo; @@ -656,7 +649,7 @@ void PieceInfo::LoadInformation() // colors + 2*num_prim + sides*prims size = 9+SIDES*11; - if (m_nFlags & LC_PIECE_LONGDATA) + if (m_nFlags & LC_PIECE_LONGDATA_INDICES) { pGroup->drawinfo = malloc(sizeof(lcuint32)*size); longs = (lcuint32*)pGroup->drawinfo; @@ -815,7 +808,7 @@ void PieceInfo::LoadInformation() // colors + 2*num_prim + sides*prims size = 9+SIDES*20; - if (m_nFlags & LC_PIECE_LONGDATA) + if (m_nFlags & LC_PIECE_LONGDATA_INDICES) { pGroup->drawinfo = malloc(sizeof(lcuint32)*size); longs = (lcuint32*)pGroup->drawinfo; @@ -1046,7 +1039,7 @@ void PieceInfo::LoadInformation() // colors + 2*num_prim + sides*prims size = 9+SIDES*11; - if (m_nFlags & LC_PIECE_LONGDATA) + if (m_nFlags & LC_PIECE_LONGDATA_INDICES) { pGroup->drawinfo = malloc(sizeof(lcuint32)*size); longs = (lcuint32*)pGroup->drawinfo; @@ -1205,7 +1198,7 @@ void PieceInfo::LoadInformation() // colors + 2*num_prim + sides*prims size = 9+SIDES*20; - if (m_nFlags & LC_PIECE_LONGDATA) + if (m_nFlags & LC_PIECE_LONGDATA_INDICES) { pGroup->drawinfo = malloc(sizeof(lcuint32)*size); longs = (lcuint32*)pGroup->drawinfo; @@ -1452,10 +1445,8 @@ void PieceInfo::FreeInformation() m_pTextures = NULL; } - if (m_nFlags & LC_PIECE_LONGDATA_RUNTIME) - { - m_nFlags &= ~(LC_PIECE_LONGDATA | LC_PIECE_LONGDATA_RUNTIME); - } + if (m_nFlags & LC_PIECE_LONGDATA_INDICES) + m_nFlags &= ~LC_PIECE_LONGDATA_INDICES; } // Zoom extents for the preview window and print catalog @@ -1656,7 +1647,7 @@ void PieceInfo::RenderPiece(int nColor) sh = m_nGroupCount; for (pGroup = m_pGroups; sh--; pGroup++) { - if (m_nFlags & LC_PIECE_LONGDATA) + if (m_nFlags & LC_PIECE_LONGDATA_INDICES) { lcuint32* info, colors; @@ -1750,7 +1741,7 @@ void PieceInfo::WriteWavefront(FILE* file, unsigned char color, unsigned long* s for (group = 0; group < m_nGroupCount; group++) { - if (m_nFlags & LC_PIECE_LONGDATA) + if (m_nFlags & LC_PIECE_LONGDATA_INDICES) { unsigned long* info = (unsigned long*)m_pGroups[group].drawinfo; unsigned long count, colors = *info; diff --git a/common/pieceinf.h b/common/pieceinf.h index d94bc801..e881b6b4 100644 --- a/common/pieceinf.h +++ b/common/pieceinf.h @@ -1,7 +1,3 @@ -// -// pieceinf.h -//////////////////////////////////////////////////// - #ifndef _PIECEINF_H_ #define _PIECEINF_H_ @@ -11,38 +7,38 @@ #endif #include "algebra.h" -#define LC_PIECE_COUNT 0x01 // Count this piece in the totals ? -#define LC_PIECE_LONGDATA 0x02 // unsigned long/short index -#define LC_PIECE_CCW 0x04 // Use back-face culling -#define LC_PIECE_SMALL 0x10 // scale = 10000 -#define LC_PIECE_MEDIUM 0x20 // scale = 1000 (otherwise = 100) -#define LC_PIECE_LONGDATA_RUNTIME 0x40 // If the original data is 16 bits but we expanded to 32 bits +#define LC_PIECE_COUNT 0x01 // Count this piece in the totals ? +#define LC_PIECE_LONGDATA_FILE 0x02 // unsigned long/short index +#define LC_PIECE_CCW 0x04 // Use back-face culling +#define LC_PIECE_SMALL 0x10 // scale = 10000 +#define LC_PIECE_MEDIUM 0x20 // scale = 1000 (otherwise = 100) +#define LC_PIECE_LONGDATA_INDICES 0x40 // unsigned long/short index #define LC_PIECE_NAME_LEN 256 class File; class Texture; -typedef struct +struct CONNECTIONINFO { unsigned char type; float center[3]; float normal[3]; -} CONNECTIONINFO; +}; -typedef struct +struct DRAWGROUP { unsigned short connections[6]; void* drawinfo; -} DRAWGROUP; +}; -typedef struct TEXTURE +struct TEXTURE { Texture* texture; unsigned char color; float vertex[4][3]; float coords[4][2]; -} TEXTURE; +}; unsigned char ConvertColor(int c); diff --git a/common/project.cpp b/common/project.cpp index 0ba08632..d11f22fa 100644 --- a/common/project.cpp +++ b/common/project.cpp @@ -4190,7 +4190,7 @@ void Project::HandleCommand(LC_COMMANDS id, unsigned long nParam) unsigned short g; for (g = 0; g < pInfo->m_nGroupCount; g++) - if (pInfo->m_nFlags & LC_PIECE_LONGDATA) + if (pInfo->m_nFlags & LC_PIECE_LONGDATA_INDICES) { unsigned long* info = (unsigned long*)pInfo->m_pGroups[g].drawinfo; unsigned long count, curcolor, colors = *info; diff --git a/common/typedefs.h b/common/typedefs.h index c5c26089..7746b809 100644 --- a/common/typedefs.h +++ b/common/typedefs.h @@ -181,32 +181,30 @@ typedef enum LC_CURSOR_COUNT } LC_CURSOR_TYPE; -// Piece connections (complicated and wastes memory but fast). - -typedef struct CONNECTION +// Piece connections. +struct CONNECTION { unsigned char type; float center[3]; float normal[3]; CONNECTION* link; Piece* owner; -} CONNECTION; +}; -typedef struct +struct CONNECTION_ENTRY { Piece* owner; CONNECTION** cons; // pointers to the structures in each piece unsigned short numcons; -} CONNECTION_ENTRY; +}; -typedef struct +struct CONNECTION_TYPE { CONNECTION_ENTRY* entries; unsigned short numentries; -} CONNECTION_TYPE; +}; // Select by Name dialog data - typedef enum { LC_SELDLG_PIECE, @@ -215,15 +213,15 @@ typedef enum LC_SELDLG_GROUP } LC_SEL_DATA_TYPE; -typedef struct +struct LC_SEL_DATA { const char* name; unsigned char type; bool selected; void* pointer; -} LC_SEL_DATA; +}; -typedef struct +struct LC_PIECE_MODIFY { Piece* piece; Vector3 Position; @@ -233,9 +231,9 @@ typedef struct int to; bool hidden; int color; -} LC_PIECE_MODIFY; +}; -typedef struct +struct LC_CAMERA_MODIFY { Camera* camera; Vector3 Eye; @@ -246,7 +244,7 @@ typedef struct float znear; float zfar; bool hidden; -} LC_CAMERA_MODIFY; +}; // Image @@ -259,7 +257,7 @@ typedef enum LC_IMAGE_AVI } LC_IMAGE_FORMATS; -typedef struct +struct LC_IMAGE_OPTS { unsigned char quality; bool interlaced; @@ -268,9 +266,9 @@ typedef struct unsigned char background[3]; float pause; unsigned int format; -} LC_IMAGE_OPTS; +}; -typedef struct +struct LC_IMAGEDLG_OPTS { char filename[LC_MAXPATH]; unsigned short from; @@ -279,7 +277,7 @@ typedef struct unsigned short width; unsigned short height; LC_IMAGE_OPTS imopts; -} LC_IMAGEDLG_OPTS; +}; typedef enum { LC_DLG_FILE_OPEN_PROJECT, @@ -287,6 +285,7 @@ typedef enum { LC_DLG_FILE_MERGE_PROJECT, LC_DLG_FILE_OPEN, LC_DLG_FILE_SAVE, + LC_DLG_DIRECTORY_BROWSE, LC_DLG_PICTURE_SAVE, LC_DLG_HTML, LC_DLG_POVRAY, @@ -312,34 +311,40 @@ typedef enum LC_FILEOPENDLG_LUP } LC_FILEOPENDLG_TYPES; -typedef struct +struct LC_FILEOPENDLG_OPTS { int type; char path[LC_MAXPATH]; int numfiles; char** filenames; -} LC_FILEOPENDLG_OPTS; +}; typedef enum { LC_FILESAVEDLG_LCF, } LC_FILESAVEDLG_TYPES; -typedef struct +struct LC_FILESAVEDLG_OPTS { int type; char path[LC_MAXPATH]; -} LC_FILESAVEDLG_OPTS; +}; -typedef struct +struct LC_DLG_DIRECTORY_BROWSE_OPTS +{ + const char* Title; + char Path[LC_MAXPATH]; +}; + +struct LC_POVRAYDLG_OPTS { bool render; char povpath[LC_MAXPATH]; char outpath[LC_MAXPATH]; char libpath[LC_MAXPATH]; -} LC_POVRAYDLG_OPTS; +}; -typedef struct +struct LC_HTMLDLG_OPTS { char path[LC_MAXPATH]; bool singlepage; @@ -350,9 +355,9 @@ typedef struct bool highlight; bool htmlext; LC_IMAGEDLG_OPTS imdlg; -} LC_HTMLDLG_OPTS; +}; -typedef struct +struct LC_ARRAYDLG_OPTS { unsigned short n1DCount; unsigned short n2DCount; @@ -362,9 +367,9 @@ typedef struct float f3D[3]; float fMove[3]; float fRotate[3]; -} LC_ARRAYDLG_OPTS; +}; -typedef struct +struct LC_PROPERTIESDLG_OPTS { char strAuthor[101]; char strDescription[101]; @@ -374,9 +379,9 @@ typedef struct char** names; unsigned short* count; int lines; -} LC_PROPERTIESDLG_OPTS; +}; -typedef struct +struct LC_GROUPEDITDLG_OPTS { int piececount; Piece** pieces; @@ -384,9 +389,9 @@ typedef struct int groupcount; Group** groups; Group** groupsgroups; -} LC_GROUPEDITDLG_OPTS; +}; -typedef struct +struct LC_PREFERENCESDLG_OPTS { int nMouse; int nSaveInterval; @@ -407,12 +412,12 @@ typedef struct float fGrad2[3]; char strFooter[256]; char strHeader[256]; -} LC_PREFERENCESDLG_OPTS; +}; -typedef struct +struct LC_CATEGORYDLG_OPTS { String Name; String Keywords; -} LC_CATEGORYDLG_OPTS; +}; #endif diff --git a/win/LeoCAD.rc b/win/LeoCAD.rc index 48373b54..8d073854 100644 --- a/win/LeoCAD.rc +++ b/win/LeoCAD.rc @@ -498,6 +498,7 @@ BEGIN MENUITEM "&Print Catalog...", ID_LIBDLG_FILE_PRINTCATALOG MENUITEM "Load &Update...", ID_LIBDLG_FILE_MERGEUPDATE MENUITEM "&Import Piece...", ID_FILE_IMPORTPIECE + MENUITEM "Import &Folder...", ID_FILE_IMPORTFOLDER MENUITEM "Te&xtures...", ID_LIBDLG_FILE_TEXTURES MENUITEM SEPARATOR MENUITEM "Close", IDOK diff --git a/win/Libdlg.cpp b/win/Libdlg.cpp index ab6f72e8..b769a517 100644 --- a/win/Libdlg.cpp +++ b/win/Libdlg.cpp @@ -137,6 +137,103 @@ BOOL CLibraryDlg::OnInitDialog() return TRUE; } +bool CLibraryDlg::ImportPieces(const ObjArray& FileList) +{ + char file1[LC_MAXPATH], file2[LC_MAXPATH]; + PiecesLibrary* Library = lcGetPiecesLibrary(); + FileDisk DiskIdx, DiskBin; + + strcpy(file1, Library->GetLibraryPath()); + strcat(file1, "pieces.idx"); + strcpy(file2, Library->GetLibraryPath()); + strcat(file2, "pieces.bin"); + + if ((!DiskIdx.Open(file1, "rb")) || (!DiskBin.Open(file2, "rb"))) + return false; + + FileMem IdxFile1, IdxFile2, BinFile1, BinFile2; + long Length; + + Length = DiskIdx.GetLength(); + IdxFile1.SetLength(Length); + DiskIdx.Read(IdxFile1.GetBuffer(), Length); + DiskIdx.Close(); + + Length = DiskBin.GetLength(); + BinFile1.SetLength(Length); + DiskBin.Read(BinFile1.GetBuffer(), Length); + DiskBin.Close(); + + FileMem* NewIdx = &IdxFile1; + FileMem* NewBin = &BinFile1; + FileMem* OldIdx = &IdxFile2; + FileMem* OldBin = &BinFile2; + + CProgressDlg Dlg("Importing pieces"); + Dlg.Create(this); + Dlg.SetRange(0, FileList.GetSize()); + + for (int i = 0; i < FileList.GetSize(); i++) + { + char* Name = FileList[i]; + char* Slash = strrchr(Name, '\\'); + if (Slash > Name) + Name = Slash+1; + + Slash = strrchr(Name, '/'); + if (Slash > Name) + Name = Slash+1; + + Dlg.SetStatus(Name); + Dlg.StepIt(); + + FileMem* TmpFile; + + TmpFile = NewBin; + NewBin = OldBin; + OldBin = TmpFile; + NewBin->SetLength(0); + + TmpFile = NewIdx; + NewIdx = OldIdx; + OldIdx = TmpFile; + NewIdx->SetLength(0); + + lcGetPiecesLibrary()->ImportLDrawPiece(FileList[i], NewIdx, NewBin, OldIdx, OldBin); + + if (Dlg.CheckCancelButton()) + if (AfxMessageBox(IDS_CANCEL_PROMPT, MB_YESNO) == IDYES) + break; + } + + if ((!DiskIdx.Open(file1, "wb")) || (!DiskBin.Open(file2, "wb"))) + return false; + + strcpy(file1, Library->GetLibraryPath()); + strcat(file1, "pieces-b.old"); + remove(file1); + strcpy(file2, Library->GetLibraryPath()); + strcat(file2, "pieces.bin"); + rename(file2, file1); + + strcpy(file1, Library->GetLibraryPath()); + strcat(file1, "pieces-i.old"); + remove(file1); + strcpy(file2, Library->GetLibraryPath()); + strcat(file2, "pieces.idx"); + rename(file2, file1); + + DiskBin.Seek(0, SEEK_SET); + DiskBin.Write(NewBin->GetBuffer(), NewBin->GetLength()); + + DiskIdx.Seek(0, SEEK_SET); + DiskIdx.Write(NewIdx->GetBuffer(), NewIdx->GetLength()); + + UpdateList(); + + return true; +} + BOOL CLibraryDlg::OnCommand(WPARAM wParam, LPARAM lParam) { switch (LOWORD(wParam)) @@ -198,13 +295,18 @@ BOOL CLibraryDlg::OnCommand(WPARAM wParam, LPARAM lParam) if (SystemDoDialog (LC_DLG_FILE_OPEN, &opts)) { + ObjArray FileList; + for (int i = 0; i < opts.numfiles; i++) { - lcGetPiecesLibrary ()->ImportLDrawPiece (opts.filenames[i]); + FileList.Add(opts.filenames[i]); free (opts.filenames[i]); } free (opts.filenames); + + ImportPieces(FileList); + Sys_ProfileSaveString ("Default", "LDraw Pieces Path", opts.path); UpdateList(); @@ -213,6 +315,61 @@ BOOL CLibraryDlg::OnCommand(WPARAM wParam, LPARAM lParam) return TRUE; } + + case ID_FILE_IMPORTFOLDER: + { + LC_DLG_DIRECTORY_BROWSE_OPTS Opts; + + Opts.Title = "Select Folder"; + strcpy(Opts.Path, Sys_ProfileLoadString ("Default", "LDraw Pieces Path", "")); + + if (!SystemDoDialog(LC_DLG_DIRECTORY_BROWSE, &Opts)) + return TRUE; + + ObjArray FileList; + + WIN32_FIND_DATA FindData; + HANDLE Find = INVALID_HANDLE_VALUE; + + int Len = strlen(Opts.Path); + + if (Opts.Path[Len-1] != '\\' && Opts.Path[Len-1] != '/') + strcat(Opts.Path, "\\"); + + char Dir[MAX_PATH]; + strcpy(Dir, Opts.Path); + strcat(Dir, "*.dat"); + + Find = FindFirstFile(Dir, &FindData); + + if (Find == INVALID_HANDLE_VALUE) + { + SystemDoMessageBox("No files found.", LC_MB_OK | LC_MB_ICONERROR); + return TRUE; + } + + do + { + if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + continue; + + char File[MAX_PATH]; + strcpy(File, Opts.Path); + strcat(File, FindData.cFileName); + FileList.Add(File); + } + while (FindNextFile(Find, &FindData) != 0); + + FindClose(Find); + + lcGetPiecesLibrary()->DeleteAllPieces(); + ImportPieces(FileList); + + Sys_ProfileSaveString("Default", "LDraw Pieces Path", Opts.Path); + + return TRUE; + } + case ID_LIBDLG_FILE_TEXTURES: { CTexturesDlg dlg; @@ -317,12 +474,15 @@ BOOL CLibraryDlg::OnCommand(WPARAM wParam, LPARAM lParam) case ID_LIBDLG_PIECE_DELETE: { - PtrArray Pieces; + PtrArray Pieces; for (int i = 0; i < m_List.GetItemCount(); i++) { if (m_List.GetItemState(i, LVIS_SELECTED)) - Pieces.Add((PieceInfo*)m_List.GetItemData(i)); + { + PieceInfo* Info = (PieceInfo*)m_List.GetItemData(i); + Pieces.Add(Info->m_strName); + } } if (Pieces.GetSize() == 0) diff --git a/win/Libdlg.h b/win/Libdlg.h index c41772cb..d4572d93 100644 --- a/win/Libdlg.h +++ b/win/Libdlg.h @@ -1,6 +1,9 @@ #ifndef _LIBDLG_H_ #define _LIBDLG_H_ +#include "array.h" +#include "str.h" + class PieceInfo; class CLibraryDlg : public CDialog @@ -33,6 +36,8 @@ public: void UpdateTree(); void UpdateList(); + bool ImportPieces(const ObjArray& FileList); + CToolBar m_wndToolBar; CImageList m_TreeImages; int m_SortColumn; diff --git a/win/System.cpp b/win/System.cpp index 70ac3a05..655f14f7 100644 --- a/win/System.cpp +++ b/win/System.cpp @@ -1315,6 +1315,47 @@ bool SystemDoDialog(int nMode, void* param) } } break; + case LC_DLG_DIRECTORY_BROWSE: + { + LC_DLG_DIRECTORY_BROWSE_OPTS* Opts = (LC_DLG_DIRECTORY_BROWSE_OPTS*)param; + + strcpy(Opts->Path, ""); + + LPMALLOC ShellMalloc; + if (SHGetMalloc(&ShellMalloc) == NOERROR) + { + BROWSEINFO bi; + LPITEMIDLIST pidl; + + if (AfxGetMainWnd()) + bi.hwndOwner = AfxGetMainWnd()->GetSafeHwnd(); + else + bi.hwndOwner = ::GetDesktopWindow(); + bi.pidlRoot = NULL; + bi.pszDisplayName = Opts->Path; + bi.lpszTitle = Opts->Title; + bi.ulFlags = BIF_RETURNFSANCESTORS | BIF_RETURNONLYFSDIRS; + bi.lpfn = NULL; + bi.lParam = 0; + + pidl = SHBrowseForFolder(&bi); + if (pidl != NULL) + { + if (SHGetPathFromIDList(pidl, Opts->Path)) + { + if (Opts->Path[strlen(Opts->Path)-1] != '\\') + strcat(Opts->Path, "\\"); + return true; + } + ShellMalloc->Free(pidl); + } + ShellMalloc->Release(); + } + + return false; + + } break; + case LC_DLG_HTML: { LC_HTMLDLG_OPTS* opts = (LC_HTMLDLG_OPTS*)param; diff --git a/win/Tools.cpp b/win/Tools.cpp index e3fa05b9..39ec6e11 100644 --- a/win/Tools.cpp +++ b/win/Tools.cpp @@ -454,7 +454,7 @@ void Export3DStudio() memset(facemats, 0, sizeof(facemats)); PieceInfo* pInfo = pPiece->GetPieceInfo(); - if (pInfo->m_nFlags & LC_PIECE_LONGDATA) + if (pInfo->m_nFlags & LC_PIECE_LONGDATA_INDICES) continue; // 3DS can't handle this // count number of faces used diff --git a/win/resource.h b/win/resource.h index 3837639a..679a9e0f 100644 --- a/win/resource.h +++ b/win/resource.h @@ -663,6 +663,7 @@ #define ID_VIEW_TOOLBARS 33175 #define ID_VIEW_SPLIT_HORIZONTALLY 33177 #define ID_TOOLBARS_PROPERTIES 33178 +#define ID_FILE_IMPORTFOLDER 33179 #define ID_VIEW_PIECES_BAR 59425 #define ID_VIEW_TOOLS_BAR 59426 #define ID_VIEW_ANIMATION_BAR 59427 @@ -676,7 +677,7 @@ #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_3D_CONTROLS 1 #define _APS_NEXT_RESOURCE_VALUE 242 -#define _APS_NEXT_COMMAND_VALUE 33179 +#define _APS_NEXT_COMMAND_VALUE 33180 #define _APS_NEXT_CONTROL_VALUE 1247 #define _APS_NEXT_SYMED_VALUE 121 #endif