leocad/common/project.cpp

3776 lines
92 KiB
C++
Raw Normal View History

#include "lc_global.h"
2012-03-29 03:10:55 +02:00
#include "lc_math.h"
#include "lc_mesh.h"
2011-09-07 23:06:51 +02:00
#include <locale.h>
#include "opengl.h"
#include "pieceinf.h"
2012-10-12 01:55:55 +02:00
#include "lc_texture.h"
2011-09-07 23:06:51 +02:00
#include "piece.h"
#include "camera.h"
#include "light.h"
#include "group.h"
#include "project.h"
#include "image.h"
#include "system.h"
#include "minifig.h"
2013-08-16 03:25:51 +02:00
#include "lc_mainwindow.h"
2011-09-07 23:06:51 +02:00
#include "view.h"
2012-10-02 03:23:44 +02:00
#include "lc_library.h"
2011-09-07 23:06:51 +02:00
#include "texfont.h"
#include "debug.h"
#include "lc_application.h"
2013-08-09 06:57:18 +02:00
#include "lc_profile.h"
2014-04-14 05:20:16 +02:00
#include "lc_context.h"
#include "preview.h"
2011-09-07 23:06:51 +02:00
Project::Project()
{
}
Project::~Project()
{
}
void Project::UpdateInterface()
{
// Update all user interface elements.
2014-07-03 21:10:04 +02:00
gMainWindow->UpdateUndoRedo(mUndoHistory.GetSize() > 1 ? mUndoHistory[0]->Description : NULL, !mRedoHistory.IsEmpty() ? mRedoHistory[0]->Description : NULL);
2013-08-09 06:57:18 +02:00
gMainWindow->UpdatePaste(g_App->mClipboard != NULL);
gMainWindow->UpdateCategories();
gMainWindow->UpdateTitle(m_strTitle, IsModified());
2014-05-23 02:02:21 +02:00
gMainWindow->SetTool(gMainWindow->GetTool());
2011-09-07 23:06:51 +02:00
2013-08-09 06:57:18 +02:00
gMainWindow->UpdateFocusObject(GetFocusObject());
2014-08-27 18:17:09 +02:00
gMainWindow->SetTransformType(gMainWindow->GetTransformType());
2014-10-05 07:21:51 +02:00
gMainWindow->UpdateLockSnap();
2013-08-09 06:57:18 +02:00
gMainWindow->UpdateSnap();
2014-05-03 23:16:48 +02:00
gMainWindow->UpdateCameraMenu();
gMainWindow->UpdatePerspective();
2014-07-06 08:04:09 +02:00
gMainWindow->UpdateCurrentStep();
2011-09-07 23:06:51 +02:00
UpdateSelection();
}
2013-08-09 06:57:18 +02:00
void Project::SetTitle(const char* Title)
2011-09-07 23:06:51 +02:00
{
2013-08-09 06:57:18 +02:00
strcpy(m_strTitle, Title);
2011-09-07 23:06:51 +02:00
gMainWindow->UpdateTitle(m_strTitle, IsModified());
2011-09-07 23:06:51 +02:00
}
2014-10-05 07:21:51 +02:00
void Project::LoadDefaults()
2011-09-07 23:06:51 +02:00
{
mProperties.LoadDefaults();
2011-09-07 23:06:51 +02:00
2013-08-09 06:57:18 +02:00
gMainWindow->SetColorIndex(lcGetColorIndex(4));
2014-05-23 02:02:21 +02:00
gMainWindow->SetTool(LC_TOOL_SELECT);
2014-05-21 00:15:42 +02:00
gMainWindow->SetAddKeys(false);
2013-08-09 06:57:18 +02:00
gMainWindow->UpdateUndoRedo(NULL, NULL);
2014-10-05 07:21:51 +02:00
gMainWindow->UpdateLockSnap();
2013-08-09 06:57:18 +02:00
gMainWindow->UpdateSnap();
2014-07-06 08:04:09 +02:00
mCurrentStep = 1;
gMainWindow->UpdateCurrentStep();
2011-09-07 23:06:51 +02:00
2014-10-05 07:21:51 +02:00
const lcArray<View*>& Views = gMainWindow->GetViews();
for (int i = 0; i < Views.GetSize(); i++)
if (!Views[i]->mCamera->IsSimple())
Views[i]->SetDefaultCamera();
2011-09-07 23:06:51 +02:00
2014-10-05 07:21:51 +02:00
gMainWindow->UpdateCameraMenu();
2012-12-13 01:20:40 +01:00
2011-09-07 23:06:51 +02:00
UpdateSelection();
2013-08-09 06:57:18 +02:00
gMainWindow->UpdateFocusObject(NULL);
2011-09-07 23:06:51 +02:00
}
2012-03-23 00:44:56 +01:00
bool Project::FileLoad(lcFile* file, bool bUndo, bool bMerge)
2011-09-07 23:06:51 +02:00
{
2012-03-23 00:44:56 +01:00
lcint32 i, count;
2011-09-07 23:06:51 +02:00
char id[32];
2012-03-23 00:44:56 +01:00
lcuint32 rgb;
2011-09-07 23:06:51 +02:00
float fv = 0.4f;
2014-05-23 02:02:21 +02:00
lcuint8 ch;
2012-03-23 00:44:56 +01:00
lcuint16 sh;
2011-09-07 23:06:51 +02:00
file->Seek(0, SEEK_SET);
2012-03-23 00:44:56 +01:00
file->ReadBuffer(id, 32);
2011-09-07 23:06:51 +02:00
sscanf(&id[7], "%f", &fv);
// Fix the ugly floating point reading on computers with different decimal points.
if (fv == 0.0f)
{
lconv *loc = localeconv();
id[8] = loc->decimal_point[0];
sscanf(&id[7], "%f", &fv);
if (fv == 0.0f)
return false;
}
if (fv > 0.4f)
2012-03-23 00:44:56 +01:00
file->ReadFloats(&fv, 1);
2011-09-07 23:06:51 +02:00
2012-03-23 00:44:56 +01:00
file->ReadU32(&rgb, 1);
2011-09-07 23:06:51 +02:00
if (!bMerge)
{
mProperties.mBackgroundSolidColor[0] = (float)((unsigned char) (rgb))/255;
mProperties.mBackgroundSolidColor[1] = (float)((unsigned char) (((unsigned short) (rgb)) >> 8))/255;
mProperties.mBackgroundSolidColor[2] = (float)((unsigned char) ((rgb) >> 16))/255;
2011-09-07 23:06:51 +02:00
}
if (fv < 0.6f) // old view
{
double eye[3], target[3];
2012-03-23 00:44:56 +01:00
file->ReadDoubles(eye, 3);
file->ReadDoubles(target, 3);
2011-09-07 23:06:51 +02:00
}
if (bMerge)
file->Seek(32, SEEK_CUR);
else
{
2014-10-05 07:21:51 +02:00
file->Seek(28, SEEK_CUR);
file->ReadS32(&i, 1);
mCurrentStep = i;
2011-09-07 23:06:51 +02:00
}
if (fv > 0.8f)
file->ReadU32();//m_nScene
2011-09-07 23:06:51 +02:00
2012-03-23 00:44:56 +01:00
file->ReadS32(&count, 1);
2012-11-09 01:07:53 +01:00
lcPiecesLibrary* Library = lcGetPiecesLibrary();
Library->OpenCache();
2011-09-07 23:06:51 +02:00
int FirstNewPiece = mPieces.GetSize();
2013-12-19 14:41:49 +01:00
2011-09-07 23:06:51 +02:00
while (count--)
2013-01-06 20:24:25 +01:00
{
2011-09-07 23:06:51 +02:00
if (fv > 0.4f)
{
2014-08-07 17:22:33 +02:00
lcPiece* pPiece = new lcPiece(NULL);
2013-08-09 06:57:18 +02:00
pPiece->FileLoad(*file);
2011-09-07 23:06:51 +02:00
2012-11-09 01:07:53 +01:00
if (bMerge)
for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++)
if (strcmp(mPieces[PieceIdx]->GetName(), pPiece->GetName()) == 0)
2012-11-09 01:07:53 +01:00
{
pPiece->CreateName(mPieces);
2012-11-09 01:07:53 +01:00
break;
}
2011-09-07 23:06:51 +02:00
2012-11-09 01:07:53 +01:00
if (strlen(pPiece->GetName()) == 0)
pPiece->CreateName(mPieces);
2011-09-07 23:06:51 +02:00
mPieces.Add(pPiece);
2011-09-07 23:06:51 +02:00
}
else
{
char name[LC_PIECE_NAME_LEN];
2014-08-31 02:53:12 +02:00
lcVector3 pos, rot;
2012-03-23 00:44:56 +01:00
lcuint8 color, step, group;
2013-01-06 20:24:25 +01:00
2012-03-23 00:44:56 +01:00
file->ReadFloats(pos, 3);
file->ReadFloats(rot, 3);
file->ReadU8(&color, 1);
2012-07-02 01:38:53 +02:00
file->ReadBuffer(name, 9);
2012-03-23 00:44:56 +01:00
file->ReadU8(&step, 1);
file->ReadU8(&group, 1);
2011-09-07 23:06:51 +02:00
2014-08-31 02:53:12 +02:00
pos *= 25.0f;
lcMatrix44 ModelWorld = lcMul(lcMatrix44RotationZ(rot[2] * LC_DTOR), lcMul(lcMatrix44RotationY(rot[1] * LC_DTOR), lcMatrix44RotationX(rot[0] * LC_DTOR)));
lcVector4 AxisAngle = lcMatrix44ToAxisAngle(ModelWorld);
AxisAngle[3] *= LC_RTOD;
2012-11-09 01:07:53 +01:00
PieceInfo* pInfo = Library->FindPiece(name, true);
2014-08-07 17:22:33 +02:00
lcPiece* pPiece = new lcPiece(pInfo);
2011-09-07 23:06:51 +02:00
2014-08-31 02:53:12 +02:00
pPiece->Initialize(pos, AxisAngle, step);
2012-11-09 01:07:53 +01:00
pPiece->SetColorCode(lcGetColorCodeFromOriginalColor(color));
pPiece->CreateName(mPieces);
mPieces.Add(pPiece);
2013-01-06 20:24:25 +01:00
2014-08-07 17:22:33 +02:00
// pPiece->SetGroup((lcGroup*)group);
2011-09-07 23:06:51 +02:00
}
}
2012-11-09 01:07:53 +01:00
Library->CloseCache();
2011-09-07 23:06:51 +02:00
if (!bMerge)
{
if (fv >= 0.4f)
{
2012-03-23 00:44:56 +01:00
file->ReadBuffer(&ch, 1);
if (ch == 0xFF) file->ReadU16(&sh, 1); else sh = ch;
2011-09-07 23:06:51 +02:00
if (sh > 100)
file->Seek(sh, SEEK_CUR);
else
{
2014-09-06 03:34:03 +02:00
String Author;
file->ReadBuffer(Author.GetBuffer(sh), sh);
Author.Buffer()[sh] = 0;
mProperties.mAuthor = QString::fromUtf8(Author.Buffer());
}
2011-09-07 23:06:51 +02:00
2012-03-23 00:44:56 +01:00
file->ReadBuffer(&ch, 1);
if (ch == 0xFF) file->ReadU16(&sh, 1); else sh = ch;
2011-09-07 23:06:51 +02:00
if (sh > 100)
file->Seek(sh, SEEK_CUR);
else
{
2014-09-06 03:34:03 +02:00
String Description;
file->ReadBuffer(Description.GetBuffer(sh), sh);
Description.Buffer()[sh] = 0;
mProperties.mDescription = QString::fromUtf8(Description.Buffer());
}
2011-09-07 23:06:51 +02:00
2012-03-23 00:44:56 +01:00
file->ReadBuffer(&ch, 1);
if (ch == 0xFF && fv < 1.3f) file->ReadU16(&sh, 1); else sh = ch;
2011-09-07 23:06:51 +02:00
if (sh > 255)
file->Seek(sh, SEEK_CUR);
else
{
2014-09-06 03:34:03 +02:00
String Comments;
file->ReadBuffer(Comments.GetBuffer(sh), sh);
Comments.Buffer()[sh] = 0;
mProperties.mComments = QString::fromUtf8(Comments.Buffer());
mProperties.mComments.replace(QLatin1String("\r\n"), QLatin1String("\n"));
}
2011-09-07 23:06:51 +02:00
}
}
else
{
if (fv >= 0.4f)
{
2012-03-23 00:44:56 +01:00
file->ReadBuffer(&ch, 1);
if (ch == 0xFF) file->ReadU16(&sh, 1); else sh = ch;
2011-09-07 23:06:51 +02:00
file->Seek (sh, SEEK_CUR);
2012-03-23 00:44:56 +01:00
file->ReadBuffer(&ch, 1);
if (ch == 0xFF) file->ReadU16(&sh, 1); else sh = ch;
2011-09-07 23:06:51 +02:00
file->Seek (sh, SEEK_CUR);
2012-03-23 00:44:56 +01:00
file->ReadBuffer(&ch, 1);
if (ch == 0xFF && fv < 1.3f) file->ReadU16(&sh, 1); else sh = ch;
2011-09-07 23:06:51 +02:00
file->Seek (sh, SEEK_CUR);
}
}
if (fv >= 0.5f)
{
2014-05-25 03:45:19 +02:00
int NumGroups = mGroups.GetSize();
2011-09-07 23:06:51 +02:00
2014-05-25 03:45:19 +02:00
file->ReadS32(&count, 1);
2011-09-07 23:06:51 +02:00
for (i = 0; i < count; i++)
2014-05-25 03:45:19 +02:00
mGroups.Add(new lcGroup());
2011-09-07 23:06:51 +02:00
2014-05-25 03:45:19 +02:00
for (int GroupIdx = NumGroups; GroupIdx < mGroups.GetSize(); GroupIdx++)
2011-09-07 23:06:51 +02:00
{
2014-05-25 03:45:19 +02:00
lcGroup* Group = mGroups[GroupIdx];
2011-09-07 23:06:51 +02:00
if (fv < 1.0f)
{
2014-05-25 03:45:19 +02:00
file->ReadBuffer(Group->m_strName, 65);
2012-03-23 00:44:56 +01:00
file->ReadBuffer(&ch, 1);
2014-05-25 03:45:19 +02:00
Group->mGroup = (lcGroup*)-1;
2011-09-07 23:06:51 +02:00
}
else
2014-05-25 03:45:19 +02:00
Group->FileLoad(file);
2013-12-19 14:41:49 +01:00
if (bMerge)
{
// Ensure a unique group name
int max = -1;
String baseName;
2014-05-25 03:45:19 +02:00
for (int Existing = 0; Existing < GroupIdx; Existing++)
max = lcMax(max, InstanceOfName(mGroups[Existing]->m_strName, Group->m_strName, baseName));
2013-12-19 14:41:49 +01:00
if (max > -1)
{
2014-05-25 03:45:19 +02:00
int baseReserve = sizeof(Group->m_strName) - 5; // space, #, 2-digits, and terminating 0
2013-12-19 14:41:49 +01:00
for (int num = max; (num > 99); num /= 10) { baseReserve--; }
2014-05-25 03:45:19 +02:00
sprintf(Group->m_strName, "%s #%.2d", (const char*)(baseName.Left(baseReserve)), max+1);
2013-12-19 14:41:49 +01:00
}
}
2011-09-07 23:06:51 +02:00
}
2014-05-25 03:45:19 +02:00
for (int GroupIdx = NumGroups; GroupIdx < mGroups.GetSize(); GroupIdx++)
2011-09-07 23:06:51 +02:00
{
2014-05-25 03:45:19 +02:00
lcGroup* Group = mGroups[GroupIdx];
i = LC_POINTER_TO_INT(Group->mGroup);
Group->mGroup = NULL;
2011-09-07 23:06:51 +02:00
if (i > 0xFFFF || i == -1)
continue;
2014-05-25 03:45:19 +02:00
Group->mGroup = mGroups[NumGroups + i];
2011-09-07 23:06:51 +02:00
}
for (int PieceIdx = FirstNewPiece; PieceIdx < mPieces.GetSize(); PieceIdx++)
2011-09-07 23:06:51 +02:00
{
2014-08-07 17:22:33 +02:00
lcPiece* Piece = mPieces[PieceIdx];
i = LC_POINTER_TO_INT(Piece->GetGroup());
Piece->SetGroup(NULL);
2011-09-07 23:06:51 +02:00
if (i > 0xFFFF || i == -1)
continue;
2014-05-25 03:45:19 +02:00
Piece->SetGroup(mGroups[NumGroups + i]);
2011-09-07 23:06:51 +02:00
}
RemoveEmptyGroups();
}
if (!bMerge)
{
if (fv >= 0.6f)
{
if (fv < 1.0f)
2014-09-14 02:45:45 +02:00
file->Seek(4, SEEK_CUR);
2011-09-07 23:06:51 +02:00
else
2014-09-14 02:45:45 +02:00
file->Seek(2, SEEK_CUR);
2011-09-07 23:06:51 +02:00
2012-03-23 00:44:56 +01:00
file->ReadS32(&count, 1);
2011-09-07 23:06:51 +02:00
for (i = 0; i < count; i++)
2014-08-07 17:22:33 +02:00
mCameras.Add(new lcCamera(false));
2011-09-07 23:06:51 +02:00
if (count < 7)
{
2014-08-07 17:22:33 +02:00
lcCamera* pCam = new lcCamera(false);
2011-09-07 23:06:51 +02:00
for (i = 0; i < count; i++)
pCam->FileLoad(*file);
delete pCam;
}
else
2012-08-22 03:13:32 +02:00
{
for (int CameraIdx = 0; CameraIdx < mCameras.GetSize(); CameraIdx++)
mCameras[CameraIdx]->FileLoad(*file);
}
2011-09-07 23:06:51 +02:00
}
if (fv >= 0.7f)
{
2014-09-14 02:45:45 +02:00
file->Seek(16, SEEK_CUR);
2011-09-07 23:06:51 +02:00
2012-03-23 00:44:56 +01:00
file->ReadU32(&rgb, 1);
mProperties.mFogColor[0] = (float)((unsigned char) (rgb))/255;
mProperties.mFogColor[1] = (float)((unsigned char) (((unsigned short) (rgb)) >> 8))/255;
mProperties.mFogColor[2] = (float)((unsigned char) ((rgb) >> 16))/255;
2011-09-07 23:06:51 +02:00
if (fv < 1.0f)
{
2012-03-23 00:44:56 +01:00
file->ReadU32(&rgb, 1);
mProperties.mFogDensity = (float)rgb/100;
2011-09-07 23:06:51 +02:00
}
else
file->ReadFloats(&mProperties.mFogDensity, 1);
2011-09-07 23:06:51 +02:00
if (fv < 1.3f)
{
2012-03-23 00:44:56 +01:00
file->ReadU8(&ch, 1);
2011-09-07 23:06:51 +02:00
if (ch == 0xFF)
2012-03-23 00:44:56 +01:00
file->ReadU16(&sh, 1);
2011-09-07 23:06:51 +02:00
sh = ch;
}
else
2012-03-23 00:44:56 +01:00
file->ReadU16(&sh, 1);
2011-09-07 23:06:51 +02:00
if (sh < LC_MAXPATH)
2014-04-16 02:35:55 +02:00
{
char Background[LC_MAXPATH];
file->ReadBuffer(Background, sh);
mProperties.mBackgroundImage = Background;
}
2011-09-07 23:06:51 +02:00
else
2014-10-05 07:21:51 +02:00
file->Seek(sh, SEEK_CUR);
2011-09-07 23:06:51 +02:00
}
if (fv >= 0.8f)
{
2012-03-23 00:44:56 +01:00
file->ReadBuffer(&ch, 1);
2014-10-05 07:21:51 +02:00
file->Seek(ch, SEEK_CUR);
2012-03-23 00:44:56 +01:00
file->ReadBuffer(&ch, 1);
2014-10-05 07:21:51 +02:00
file->Seek(ch, SEEK_CUR);
2011-09-07 23:06:51 +02:00
}
if (fv > 0.9f)
{
2012-03-23 00:44:56 +01:00
file->ReadU32(&rgb, 1);
mProperties.mAmbientColor[0] = (float)((unsigned char) (rgb))/255;
mProperties.mAmbientColor[1] = (float)((unsigned char) (((unsigned short) (rgb)) >> 8))/255;
mProperties.mAmbientColor[2] = (float)((unsigned char) ((rgb) >> 16))/255;
2011-09-07 23:06:51 +02:00
if (fv < 1.3f)
2014-09-14 02:45:45 +02:00
file->Seek(23, SEEK_CUR);
2011-09-07 23:06:51 +02:00
else
2014-09-14 02:45:45 +02:00
file->Seek(11, SEEK_CUR);
2011-09-07 23:06:51 +02:00
}
2013-01-06 20:24:25 +01:00
2011-09-07 23:06:51 +02:00
if (fv > 1.0f)
{
2012-03-23 00:44:56 +01:00
file->ReadU32(&rgb, 1);
mProperties.mBackgroundGradientColor1[0] = (float)((unsigned char) (rgb))/255;
mProperties.mBackgroundGradientColor1[1] = (float)((unsigned char) (((unsigned short) (rgb)) >> 8))/255;
mProperties.mBackgroundGradientColor1[2] = (float)((unsigned char) ((rgb) >> 16))/255;
2012-03-23 00:44:56 +01:00
file->ReadU32(&rgb, 1);
mProperties.mBackgroundGradientColor2[0] = (float)((unsigned char) (rgb))/255;
mProperties.mBackgroundGradientColor2[1] = (float)((unsigned char) (((unsigned short) (rgb)) >> 8))/255;
mProperties.mBackgroundGradientColor2[2] = (float)((unsigned char) ((rgb) >> 16))/255;
2011-09-07 23:06:51 +02:00
}
}
2014-10-05 07:21:51 +02:00
UpdateBackgroundTexture();
2011-09-07 23:06:51 +02:00
CalculateStep();
2012-12-13 01:20:40 +01:00
2011-09-07 23:06:51 +02:00
if (!bUndo)
2014-08-17 22:44:12 +02:00
ClearSelection(false);
2012-12-13 01:20:40 +01:00
2011-09-07 23:06:51 +02:00
if (!bMerge)
2013-08-09 06:57:18 +02:00
gMainWindow->UpdateFocusObject(GetFocusObject());
2012-12-13 01:20:40 +01:00
if (!bMerge)
{
2014-10-05 07:21:51 +02:00
const lcArray<View*>& Views = gMainWindow->GetViews();
2014-05-03 23:16:48 +02:00
for (int ViewIdx = 0; ViewIdx < Views.GetSize(); ViewIdx++)
2012-12-13 01:20:40 +01:00
{
2014-05-03 23:16:48 +02:00
View* view = Views[ViewIdx];
2012-12-13 01:20:40 +01:00
if (!view->mCamera->IsSimple())
view->SetDefaultCamera();
}
if (!bUndo)
2014-05-03 23:16:48 +02:00
ZoomExtents(0, Views.GetSize());
2012-12-13 01:20:40 +01:00
}
2014-10-05 07:21:51 +02:00
gMainWindow->UpdateLockSnap();
2013-08-09 06:57:18 +02:00
gMainWindow->UpdateSnap();
2014-05-03 23:16:48 +02:00
gMainWindow->UpdateCameraMenu();
2011-09-07 23:06:51 +02:00
UpdateSelection();
2014-07-06 08:04:09 +02:00
gMainWindow->UpdateCurrentStep();
2014-05-03 23:16:48 +02:00
gMainWindow->UpdateAllViews();
2011-09-07 23:06:51 +02:00
return true;
}
2013-08-16 01:43:18 +02:00
void Project::FileReadMPD(lcFile& MPD, lcArray<LC_FILEENTRY*>& FileArray) const
2011-09-07 23:06:51 +02:00
{
2012-03-23 00:44:56 +01:00
LC_FILEENTRY* CurFile = NULL;
2011-09-07 23:06:51 +02:00
char Buf[1024];
while (MPD.ReadLine(Buf, 1024))
2012-03-23 00:44:56 +01:00
{
String Line(Buf);
2011-09-07 23:06:51 +02:00
2012-03-23 00:44:56 +01:00
Line.TrimLeft();
2011-09-07 23:06:51 +02:00
2012-03-23 00:44:56 +01:00
if (Line[0] != '0')
{
// Copy current line.
if (CurFile != NULL)
CurFile->File.WriteBuffer(Buf, strlen(Buf));
2011-09-07 23:06:51 +02:00
2012-03-23 00:44:56 +01:00
continue;
}
2011-09-07 23:06:51 +02:00
2012-03-23 00:44:56 +01:00
Line.TrimRight();
Line = Line.Right(Line.GetLength() - 1);
Line.TrimLeft();
2011-09-07 23:06:51 +02:00
2012-03-23 00:44:56 +01:00
// Find where a subfile starts.
if (Line.CompareNoCase("FILE", 4) == 0)
{
Line = Line.Right(Line.GetLength() - 4);
Line.TrimLeft();
2011-09-07 23:06:51 +02:00
2012-03-23 00:44:56 +01:00
// Create a new file.
CurFile = new LC_FILEENTRY();
strncpy(CurFile->FileName, Line, sizeof(CurFile->FileName));
FileArray.Add(CurFile);
}
else if (Line.CompareNoCase("ENDFILE", 7) == 0)
{
// File ends here.
CurFile = NULL;
}
else if (CurFile != NULL)
{
// Copy current line.
CurFile->File.WriteBuffer(Buf, strlen(Buf));
}
}
2011-09-07 23:06:51 +02:00
}
2013-08-16 01:43:18 +02:00
void Project::FileReadLDraw(lcFile* file, const lcMatrix44& CurrentTransform, int* nOk, int DefColor, int* nStep, lcArray<LC_FILEENTRY*>& FileArray)
2011-09-07 23:06:51 +02:00
{
char Line[1024];
2011-09-07 23:06:51 +02:00
// Save file offset.
lcuint32 Offset = file->GetPosition();
file->Seek(0, SEEK_SET);
2011-09-07 23:06:51 +02:00
while (file->ReadLine(Line, 1024))
2011-09-07 23:06:51 +02:00
{
bool read = true;
char* Ptr = Line;
char* Tokens[15];
2011-09-07 23:06:51 +02:00
for (int TokenIdx = 0; TokenIdx < 15; TokenIdx++)
{
Tokens[TokenIdx] = 0;
2011-09-07 23:06:51 +02:00
while (*Ptr && *Ptr <= 32)
{
*Ptr = 0;
Ptr++;
}
2012-10-18 20:57:21 +02:00
Tokens[TokenIdx] = Ptr;
2011-09-07 23:06:51 +02:00
while (*Ptr > 32)
Ptr++;
}
2011-09-07 23:06:51 +02:00
if (!Tokens[0])
continue;
2011-09-07 23:06:51 +02:00
int LineType = atoi(Tokens[0]);
2011-09-07 23:06:51 +02:00
if (LineType == 0)
{
if (Tokens[1])
2011-09-07 23:06:51 +02:00
{
strupr(Tokens[1]);
2011-09-07 23:06:51 +02:00
if (!strcmp(Tokens[1], "STEP"))
(*nStep)++;
2011-09-07 23:06:51 +02:00
}
continue;
}
if (LineType != 1)
continue;
bool Error = false;
for (int TokenIdx = 1; TokenIdx < 15; TokenIdx++)
{
if (!Tokens[TokenIdx])
{
Error = true;
break;
}
}
if (Error)
continue;
2011-09-07 23:06:51 +02:00
int ColorCode = atoi(Tokens[1]);
float Matrix[12];
for (int TokenIdx = 2; TokenIdx < 14; TokenIdx++)
Matrix[TokenIdx - 2] = atof(Tokens[TokenIdx]);
lcMatrix44 IncludeTransform(lcVector4(Matrix[3], Matrix[6], Matrix[9], 0.0f), lcVector4(Matrix[4], Matrix[7], Matrix[10], 0.0f),
lcVector4(Matrix[5], Matrix[8], Matrix[11], 0.0f), lcVector4(Matrix[0], Matrix[1], Matrix[2], 1.0f));
IncludeTransform = lcMul(IncludeTransform, CurrentTransform);
if (ColorCode == 16)
ColorCode = DefColor;
char* IncludeName = Tokens[14];
for (Ptr = IncludeName; *Ptr; Ptr++)
if (*Ptr == '\r' || *Ptr == '\n')
*Ptr = 0;
// See if it's a piece in the library
if (strlen(IncludeName) < LC_PIECE_NAME_LEN)
{
char name[LC_PIECE_NAME_LEN];
strcpy(name, IncludeName);
strupr(name);
Ptr = strrchr(name, '.');
if (Ptr != NULL)
*Ptr = 0;
PieceInfo* pInfo = lcGetPiecesLibrary()->FindPiece(name, false);
if (pInfo != NULL)
{
2014-08-07 17:22:33 +02:00
lcPiece* pPiece = new lcPiece(pInfo);
read = false;
float* Matrix = IncludeTransform;
lcMatrix44 Transform(lcVector4(Matrix[0], Matrix[2], -Matrix[1], 0.0f), lcVector4(Matrix[8], Matrix[10], -Matrix[9], 0.0f),
lcVector4(-Matrix[4], -Matrix[6], Matrix[5], 0.0f), lcVector4(0.0f, 0.0f, 0.0f, 1.0f));
lcVector4 AxisAngle = lcMatrix44ToAxisAngle(Transform);
2012-10-18 20:57:21 +02:00
AxisAngle[3] *= LC_RTOD;
2014-08-31 02:53:12 +02:00
pPiece->Initialize(lcVector3(IncludeTransform[3].x, IncludeTransform[3].z, -IncludeTransform[3].y), AxisAngle, *nStep);
pPiece->SetColorCode(ColorCode);
pPiece->CreateName(mPieces);
mPieces.Add(pPiece);
(*nOk)++;
2011-09-07 23:06:51 +02:00
}
}
// Check for MPD files first.
if (read)
{
for (int i = 0; i < FileArray.GetSize(); i++)
{
if (stricmp(FileArray[i]->FileName, IncludeName) == 0)
{
FileReadLDraw(&FileArray[i]->File, IncludeTransform, nOk, ColorCode, nStep, FileArray);
read = false;
break;
}
}
}
// Try to read the file from disk.
if (read)
{
lcDiskFile tf;
if (tf.Open(IncludeName, "rt"))
{
FileReadLDraw(&tf, IncludeTransform, nOk, ColorCode, nStep, FileArray);
read = false;
}
}
if (read)
{
// Create a placeholder.
char name[LC_PIECE_NAME_LEN];
strcpy(name, IncludeName);
strupr(name);
Ptr = strrchr(name, '.');
if (Ptr != NULL)
*Ptr = 0;
PieceInfo* Info = lcGetPiecesLibrary()->CreatePlaceholder(name);
2014-08-07 17:22:33 +02:00
lcPiece* pPiece = new lcPiece(Info);
read = false;
float* Matrix = IncludeTransform;
lcMatrix44 Transform(lcVector4(Matrix[0], Matrix[2], -Matrix[1], 0.0f), lcVector4(Matrix[8], Matrix[10], -Matrix[9], 0.0f),
lcVector4(-Matrix[4], -Matrix[6], Matrix[5], 0.0f), lcVector4(0.0f, 0.0f, 0.0f, 1.0f));
lcVector4 AxisAngle = lcMatrix44ToAxisAngle(Transform);
AxisAngle[3] *= LC_RTOD;
2014-08-31 02:53:12 +02:00
pPiece->Initialize(lcVector3(IncludeTransform[3].x, IncludeTransform[3].z, -IncludeTransform[3].y), AxisAngle, *nStep);
pPiece->SetColorCode(ColorCode);
pPiece->CreateName(mPieces);
mPieces.Add(pPiece);
(*nOk)++;
}
2011-09-07 23:06:51 +02:00
}
// Restore file offset.
file->Seek(Offset, SEEK_SET);
2011-09-07 23:06:51 +02:00
}
2013-08-09 06:57:18 +02:00
bool Project::DoSave(const char* FileName)
2011-09-07 23:06:51 +02:00
{
2013-08-09 06:57:18 +02:00
char SaveFileName[LC_MAXPATH];
if (FileName && FileName[0])
strcpy(SaveFileName, FileName);
else
2011-09-07 23:06:51 +02:00
{
2013-08-09 06:57:18 +02:00
if (m_strPathName[0])
strcpy(SaveFileName, m_strPathName);
2014-09-14 02:45:45 +02:00
else
{
2013-08-09 06:57:18 +02:00
strcpy(SaveFileName, lcGetProfileString(LC_PROFILE_PROJECTS_PATH));
2011-09-07 23:06:51 +02:00
2013-08-09 06:57:18 +02:00
int Length = strlen(SaveFileName);
if (Length && (SaveFileName[Length - 1] != '/' && SaveFileName[Length - 1] != '\\'))
strcat(SaveFileName, "/");
2011-09-07 23:06:51 +02:00
2013-08-09 06:57:18 +02:00
strcat(SaveFileName, m_strTitle);
2011-09-07 23:06:51 +02:00
// check for dubious filename
2013-08-09 06:57:18 +02:00
int iBad = strcspn(SaveFileName, " #%;/\\");
2011-09-07 23:06:51 +02:00
if (iBad != -1)
2013-08-09 06:57:18 +02:00
SaveFileName[iBad] = 0;
2011-09-07 23:06:51 +02:00
2014-09-14 02:45:45 +02:00
strcat(SaveFileName, ".ldr");
2011-09-07 23:06:51 +02:00
}
2013-08-09 06:57:18 +02:00
if (!gMainWindow->DoDialog(LC_DIALOG_SAVE_PROJECT, SaveFileName))
return false;
2011-09-07 23:06:51 +02:00
}
2014-09-14 02:45:45 +02:00
if (QFileInfo(SaveFileName).suffix().toLower() == QLatin1String("lcd"))
2011-09-07 23:06:51 +02:00
{
2014-09-14 02:45:45 +02:00
QMessageBox::warning(gMainWindow->mHandle, tr("Error"), tr("Saving files in LCD format is no longer supported, please use the LDR format instead."));
return false;
2011-09-07 23:06:51 +02:00
}
2014-09-14 02:45:45 +02:00
QFile File(SaveFileName);
2014-09-05 02:24:28 +02:00
2014-09-14 02:45:45 +02:00
if (!File.open(QIODevice::WriteOnly))
2014-09-05 02:24:28 +02:00
{
2014-09-14 02:45:45 +02:00
QMessageBox::warning(gMainWindow->mHandle, tr("Error"), tr("Error writing to file '%1':\n%2").arg(SaveFileName, File.errorString()));
return false;
2014-09-05 02:24:28 +02:00
}
2011-09-07 23:06:51 +02:00
2014-09-14 02:45:45 +02:00
QTextStream Stream(&File);
SaveLDraw(Stream);
mSavedHistory = mUndoHistory[0];
2011-09-07 23:06:51 +02:00
// reset the title and change the document name
2013-08-09 06:57:18 +02:00
SetPathName(SaveFileName, true);
2011-09-07 23:06:51 +02:00
return true; // success
}
// return true if ok to continue
bool Project::SaveModified()
{
if (!IsModified())
return true; // ok to continue
// get name/title of document
char name[LC_MAXPATH];
if (strlen(m_strPathName) == 0)
{
// get name based on caption
strcpy(name, m_strTitle);
if (strlen(name) == 0)
strcpy(name, "Untitled");
}
else
{
// get name based on file title of path name
char* p;
p = strrchr(m_strPathName, '\\');
if (!p)
p = strrchr(m_strPathName, '/');
if (p)
strcpy(name, ++p);
else
strcpy(name, m_strPathName);
}
char prompt[512];
sprintf(prompt, "Save changes to %s ?", name);
2013-08-09 06:57:18 +02:00
switch (gMainWindow->DoMessageBox(prompt, LC_MB_YESNOCANCEL))
2011-09-07 23:06:51 +02:00
{
case LC_CANCEL:
return false; // don't continue
case LC_YES:
// If so, either Save or Update, as appropriate
2013-08-09 06:57:18 +02:00
if (!DoSave(m_strPathName))
return false;
2011-09-07 23:06:51 +02:00
break;
case LC_NO:
// If not saving changes, revert the document
break;
}
return true; // keep going
}
bool Project::OnNewDocument()
{
2014-10-05 07:21:51 +02:00
memset(m_strPathName, 0, sizeof(m_strPathName));
DeleteModel();
DeleteHistory();
LoadDefaults();
2011-09-07 23:06:51 +02:00
CheckPoint("");
2014-09-15 01:32:58 +02:00
mSavedHistory = mUndoHistory[0];
SetTitle("Untitled");
2011-09-07 23:06:51 +02:00
return true;
}
bool Project::OpenProject(const char* FileName)
{
if (!SaveModified())
return false;
2011-09-07 23:06:51 +02:00
if (!OnOpenDocument(FileName))
return false;
2011-09-07 23:06:51 +02:00
SetPathName(FileName, true);
return true;
}
bool Project::OnOpenDocument(const char* lpszPathName)
2011-09-07 23:06:51 +02:00
{
2012-03-23 00:44:56 +01:00
lcDiskFile file;
2011-09-07 23:06:51 +02:00
bool bSuccess = false;
if (!file.Open(lpszPathName, "rb"))
{
// MessageBox("Failed to open file.");
return false;
}
char ext[4];
const char *ptr;
memset(ext, 0, 4);
ptr = strrchr(lpszPathName, '.');
if (ptr != NULL)
{
strncpy(ext, ptr+1, 3);
strlwr(ext);
}
bool datfile = false;
bool mpdfile = false;
// Find out what file type we're loading.
if ((strcmp(ext, "dat") == 0) || (strcmp(ext, "ldr") == 0))
datfile = true;
else if (strcmp(ext, "mpd") == 0)
mpdfile = true;
2014-10-05 07:21:51 +02:00
DeleteModel();
DeleteHistory();
LoadDefaults();
2011-09-07 23:06:51 +02:00
if (file.GetLength() != 0)
{
2013-08-16 01:43:18 +02:00
lcArray<LC_FILEENTRY*> FileArray;
2011-09-07 23:06:51 +02:00
// Unpack the MPD file.
if (mpdfile)
{
FileReadMPD(file, FileArray);
if (FileArray.GetSize() == 0)
{
file.Seek(0, SEEK_SET);
mpdfile = false;
datfile = true;
}
}
if (datfile || mpdfile)
{
int ok = 0, step = 1;
2012-10-18 20:57:21 +02:00
lcMatrix44 mat = lcMatrix44Identity();
2011-09-07 23:06:51 +02:00
if (mpdfile)
2012-10-18 20:57:21 +02:00
FileReadLDraw(&FileArray[0]->File, mat, &ok, 16, &step, FileArray);
2011-09-07 23:06:51 +02:00
else
// FileReadLDraw(&file, mat, &ok, 16, &step, FileArray);
{
QFile File(lpszPathName);
2014-09-08 21:42:20 +02:00
if (!File.open(QIODevice::ReadOnly))
{
2014-09-14 02:45:45 +02:00
QMessageBox::warning(gMainWindow->mHandle, tr("Error"), tr("Error reading file '%1':\n%2").arg(lpszPathName, File.errorString()));
2014-09-08 21:42:20 +02:00
return false;
}
2014-09-08 21:42:20 +02:00
2014-09-16 01:41:46 +02:00
QTextStream Stream(&File);
LoadLDraw(Stream);
}
2011-09-07 23:06:51 +02:00
2014-07-06 08:04:09 +02:00
mCurrentStep = step;
gMainWindow->UpdateCurrentStep();
2013-08-09 06:57:18 +02:00
gMainWindow->UpdateFocusObject(GetFocusObject());
2011-09-07 23:06:51 +02:00
UpdateSelection();
2012-12-11 00:30:28 +01:00
2014-05-03 23:16:48 +02:00
ZoomExtents(0, gMainWindow->GetViews().GetSize());
gMainWindow->UpdateAllViews();
2011-09-07 23:06:51 +02:00
bSuccess = true;
}
else
{
// Load a LeoCAD file.
bSuccess = FileLoad(&file, false, false);
}
FileArray.DeleteAll();
2011-09-07 23:06:51 +02:00
}
file.Close();
if (bSuccess == false)
{
OnNewDocument();
2011-09-07 23:06:51 +02:00
// MessageBox("Failed to load.");
return false;
}
CheckPoint("");
2014-09-15 01:32:58 +02:00
mSavedHistory = mUndoHistory[0];
2011-09-07 23:06:51 +02:00
return true;
}
2012-01-28 02:05:23 +01:00
void Project::SetPathName(const char* PathName, bool bAddToMRU)
2011-09-07 23:06:51 +02:00
{
2012-01-28 02:05:23 +01:00
strcpy(m_strPathName, PathName);
2011-09-07 23:06:51 +02:00
// always capture the complete file name including extension (if present)
2012-01-28 02:05:23 +01:00
const char* lpszTemp = PathName;
for (const char* lpsz = PathName; *lpsz != '\0'; lpsz++)
2011-09-07 23:06:51 +02:00
{
// remember last directory/drive separator
if (*lpsz == '\\' || *lpsz == '/' || *lpsz == ':')
lpszTemp = lpsz + 1;
}
// set the document title based on path name
SetTitle(lpszTemp);
// add it to the file MRU list
if (bAddToMRU)
2013-08-09 06:57:18 +02:00
gMainWindow->AddRecentFile(m_strPathName);
2011-09-07 23:06:51 +02:00
}
2014-07-03 21:10:04 +02:00
void Project::CheckPoint(const char* Description)
2011-09-07 23:06:51 +02:00
{
2014-09-15 01:32:58 +02:00
SaveCheckpoint(Description);
2011-09-07 23:06:51 +02:00
}
// Only this function should be called.
2014-04-16 02:29:54 +02:00
void Project::Render(View* View, bool ToMemory)
2011-09-07 23:06:51 +02:00
{
2014-04-16 02:29:54 +02:00
View->mContext->SetDefaultState();
glViewport(0, 0, View->mWidth, View->mHeight);
2014-04-16 02:29:54 +02:00
RenderBackground(View);
2014-04-20 03:50:41 +02:00
RenderScenePieces(View, !ToMemory);
2012-01-28 02:05:23 +01:00
if (!ToMemory)
{
2014-04-16 02:29:54 +02:00
RenderSceneObjects(View);
}
}
2014-04-16 02:29:54 +02:00
void Project::RenderBackground(View* View)
{
2014-04-16 02:29:54 +02:00
lcContext* Context = View->mContext;
if (mProperties.mBackgroundType == LC_BACKGROUND_SOLID)
{
glClearColor(mProperties.mBackgroundSolidColor[0], mProperties.mBackgroundSolidColor[1], mProperties.mBackgroundSolidColor[2], 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2011-09-07 23:06:51 +02:00
return;
}
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2011-09-07 23:06:51 +02:00
glDepthMask(GL_FALSE);
glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
2011-09-07 23:06:51 +02:00
2014-04-16 02:29:54 +02:00
float ViewWidth = (float)View->mWidth;
float ViewHeight = (float)View->mHeight;
2011-09-07 23:06:51 +02:00
2014-04-16 02:29:54 +02:00
Context->SetProjectionMatrix(lcMatrix44Ortho(0.0f, ViewWidth, 0.0f, ViewHeight, -1.0f, 1.0f));
Context->SetWorldViewMatrix(lcMatrix44Translation(lcVector3(0.375f, 0.375f, 0.0f)));
2011-09-07 23:06:51 +02:00
if (mProperties.mBackgroundType == LC_BACKGROUND_GRADIENT)
{
glShadeModel(GL_SMOOTH);
2011-09-07 23:06:51 +02:00
2014-04-16 02:29:54 +02:00
const lcVector3& Color1 = mProperties.mBackgroundGradientColor1;
const lcVector3& Color2 = mProperties.mBackgroundGradientColor2;
2011-09-07 23:06:51 +02:00
2014-04-16 02:29:54 +02:00
float Verts[] =
{
ViewWidth, ViewHeight, Color1[0], Color1[1], Color1[2], 1.0f,
0.0f, ViewHeight, Color1[0], Color1[1], Color1[2], 1.0f,
0.0f, 0.0f, Color2[0], Color2[1], Color2[2], 1.0f,
ViewWidth, 0.0f, Color2[0], Color2[1], Color2[2], 1.0f
};
2014-04-16 02:29:54 +02:00
glVertexPointer(2, GL_FLOAT, 6 * sizeof(float), Verts);
glEnableClientState(GL_COLOR_ARRAY);
glColorPointer(4, GL_FLOAT, 6 * sizeof(float), Verts + 2);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glDisableClientState(GL_COLOR_ARRAY);
glShadeModel(GL_FLAT);
}
if (mProperties.mBackgroundType == LC_BACKGROUND_IMAGE)
{
glEnable(GL_TEXTURE_2D);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
2014-10-05 07:21:51 +02:00
glBindTexture(GL_TEXTURE_2D, mBackgroundTexture->mTexture);
2014-04-16 02:29:54 +02:00
float TileWidth = 1.0f, TileHeight = 1.0f;
if (mProperties.mBackgroundImageTile)
{
2014-10-05 07:21:51 +02:00
TileWidth = ViewWidth / mBackgroundTexture->mWidth;
TileHeight = ViewHeight / mBackgroundTexture->mHeight;
}
2014-04-16 02:29:54 +02:00
float Verts[] =
{
0.0f, ViewHeight, 0.0f, 0.0f,
ViewWidth, ViewHeight, TileWidth, 0.0f,
ViewWidth, 0.0f, TileWidth, TileHeight,
0.0f, 0.0f, 0.0f, TileHeight
};
glVertexPointer(2, GL_FLOAT, 4 * sizeof(float), Verts);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 4 * sizeof(float), Verts + 2);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_2D);
}
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
2011-09-07 23:06:51 +02:00
}
2014-04-20 03:50:41 +02:00
void Project::RenderScenePieces(View* view, bool DrawInterface)
2011-09-07 23:06:51 +02:00
{
const lcPreferences& Preferences = lcGetPreferences();
2014-05-03 03:22:24 +02:00
lcContext* Context = view->mContext;
2014-05-03 03:22:24 +02:00
Context->SetProjectionMatrix(view->GetProjectionMatrix());
2013-12-17 03:43:16 +01:00
if (Preferences.mLightingMode != LC_LIGHTING_FLAT)
2011-09-07 23:06:51 +02:00
{
2013-08-09 06:57:18 +02:00
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
glEnable(GL_COLOR_MATERIAL);
glShadeModel(GL_SMOOTH);
GLfloat mat_translucent[] = { (GLfloat)0.8, (GLfloat)0.8, (GLfloat)0.8, (GLfloat)1.0 };
GLfloat mat_opaque[] = { (GLfloat)0.8, (GLfloat)0.8, (GLfloat)0.8, (GLfloat)1.0 };
GLfloat medium_shininess[] = { (GLfloat)64.0 };
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, medium_shininess);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_opaque);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_translucent);
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lcVector4(mProperties.mAmbientColor, 1.0f));
2013-08-09 06:57:18 +02:00
for (int LightIdx = 0; LightIdx < mLights.GetSize(); LightIdx++)
mLights[LightIdx]->Setup(LightIdx);
2011-09-07 23:06:51 +02:00
2012-01-28 02:05:23 +01:00
glEnable(GL_LIGHTING);
}
2013-08-09 06:57:18 +02:00
else
{
glDisable(GL_LIGHTING);
glDisable(GL_COLOR_MATERIAL);
glShadeModel(GL_FLAT);
}
2012-01-28 02:05:23 +01:00
if (mProperties.mFogEnabled)
2013-08-09 06:57:18 +02:00
{
glFogi(GL_FOG_MODE, GL_EXP);
glFogf(GL_FOG_DENSITY, mProperties.mFogDensity);
glFogfv(GL_FOG_COLOR, lcVector4(mProperties.mFogColor, 1.0f));
2012-01-28 02:05:23 +01:00
glEnable(GL_FOG);
2013-08-09 06:57:18 +02:00
}
2011-09-07 23:06:51 +02:00
2014-04-20 03:50:41 +02:00
lcArray<lcRenderMesh> OpaqueMeshes(mPieces.GetSize());
lcArray<lcRenderMesh> TranslucentMeshes;
2014-02-16 08:23:55 +01:00
const lcMatrix44& ViewMatrix = view->mCamera->mWorldView;
2014-04-20 03:50:41 +02:00
Context->SetLineWidth(Preferences.mLineWidth);
2011-09-07 23:06:51 +02:00
for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++)
2012-01-28 02:05:23 +01:00
{
2014-08-07 17:22:33 +02:00
lcPiece* Piece = mPieces[PieceIdx];
2014-07-06 08:04:09 +02:00
if (!Piece->IsVisible(mCurrentStep))
2012-01-28 02:05:23 +01:00
continue;
2011-09-07 23:06:51 +02:00
PieceInfo* Info = Piece->mPieceInfo;
2014-04-23 16:53:43 +02:00
bool Focused, Selected;
2014-04-20 03:50:41 +02:00
if (DrawInterface)
{
2014-04-23 16:53:43 +02:00
Focused = Piece->IsFocused();
Selected = Piece->IsSelected();
2014-04-20 03:50:41 +02:00
}
else
{
2014-04-23 16:53:43 +02:00
Focused = false;
Selected = false;
2014-04-20 03:50:41 +02:00
}
2014-04-23 16:53:43 +02:00
Info->AddRenderMeshes(ViewMatrix, &Piece->mModelWorld, Piece->mColorIndex, Focused, Selected, OpaqueMeshes, TranslucentMeshes);
}
2014-04-20 03:50:41 +02:00
OpaqueMeshes.Sort(lcOpaqueRenderMeshCompare);
Context->DrawOpaqueMeshes(ViewMatrix, OpaqueMeshes);
2014-04-20 03:50:41 +02:00
TranslucentMeshes.Sort(lcTranslucentRenderMeshCompare);
Context->DrawTranslucentMeshes(ViewMatrix, TranslucentMeshes);
Context->UnbindMesh(); // context remove
if (Preferences.mLightingMode != LC_LIGHTING_FLAT)
{
2014-04-20 03:50:41 +02:00
glDisable(GL_LIGHTING);
glDisable(GL_COLOR_MATERIAL);
glShadeModel(GL_FLAT);
}
2014-04-20 03:50:41 +02:00
if (mProperties.mFogEnabled)
glDisable(GL_FOG);
2014-04-20 03:50:41 +02:00
if (DrawInterface)
{
Context->SetLineWidth(2.0f * Preferences.mLineWidth);
for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++)
{
2014-08-07 17:22:33 +02:00
lcPiece* Piece = mPieces[PieceIdx];
2014-07-06 08:04:09 +02:00
if (!Piece->IsVisible(mCurrentStep) || !Piece->IsSelected())
2014-04-20 03:50:41 +02:00
continue;
2014-04-20 03:50:41 +02:00
PieceInfo* PieceInfo = Piece->mPieceInfo;
2014-04-20 03:50:41 +02:00
lcVector3 Min(PieceInfo->m_fDimensions[3], PieceInfo->m_fDimensions[4], PieceInfo->m_fDimensions[5]);
lcVector3 Max(PieceInfo->m_fDimensions[0], PieceInfo->m_fDimensions[1], PieceInfo->m_fDimensions[2]);
lcVector3 Edge((Max - Min) * 0.33f);
float Verts[48][3] =
{
2014-04-20 03:50:41 +02:00
{ Max[0], Max[1], Max[2] }, { Max[0] - Edge[0], Max[1], Max[2] },
{ Max[0], Max[1], Max[2] }, { Max[0], Max[1] - Edge[1], Max[2] },
{ Max[0], Max[1], Max[2] }, { Max[0], Max[1], Max[2] - Edge[2] },
2014-04-20 03:50:41 +02:00
{ Min[0], Max[1], Max[2] }, { Min[0] + Edge[0], Max[1], Max[2] },
{ Min[0], Max[1], Max[2] }, { Min[0], Max[1] - Edge[1], Max[2] },
{ Min[0], Max[1], Max[2] }, { Min[0], Max[1], Max[2] - Edge[2] },
2011-09-07 23:06:51 +02:00
2014-04-20 03:50:41 +02:00
{ Max[0], Min[1], Max[2] }, { Max[0] - Edge[0], Min[1], Max[2] },
{ Max[0], Min[1], Max[2] }, { Max[0], Min[1] + Edge[1], Max[2] },
{ Max[0], Min[1], Max[2] }, { Max[0], Min[1], Max[2] - Edge[2] },
2011-09-07 23:06:51 +02:00
2014-04-20 03:50:41 +02:00
{ Min[0], Min[1], Max[2] }, { Min[0] + Edge[0], Min[1], Max[2] },
{ Min[0], Min[1], Max[2] }, { Min[0], Min[1] + Edge[1], Max[2] },
{ Min[0], Min[1], Max[2] }, { Min[0], Min[1], Max[2] - Edge[2] },
2014-04-20 03:50:41 +02:00
{ Max[0], Max[1], Min[2] }, { Max[0] - Edge[0], Max[1], Min[2] },
{ Max[0], Max[1], Min[2] }, { Max[0], Max[1] - Edge[1], Min[2] },
{ Max[0], Max[1], Min[2] }, { Max[0], Max[1], Min[2] + Edge[2] },
2014-04-20 03:50:41 +02:00
{ Min[0], Max[1], Min[2] }, { Min[0] + Edge[0], Max[1], Min[2] },
{ Min[0], Max[1], Min[2] }, { Min[0], Max[1] - Edge[1], Min[2] },
{ Min[0], Max[1], Min[2] }, { Min[0], Max[1], Min[2] + Edge[2] },
2014-04-20 03:50:41 +02:00
{ Max[0], Min[1], Min[2] }, { Max[0] - Edge[0], Min[1], Min[2] },
{ Max[0], Min[1], Min[2] }, { Max[0], Min[1] + Edge[1], Min[2] },
{ Max[0], Min[1], Min[2] }, { Max[0], Min[1], Min[2] + Edge[2] },
2014-04-20 03:50:41 +02:00
{ Min[0], Min[1], Min[2] }, { Min[0] + Edge[0], Min[1], Min[2] },
{ Min[0], Min[1], Min[2] }, { Min[0], Min[1] + Edge[1], Min[2] },
{ Min[0], Min[1], Min[2] }, { Min[0], Min[1], Min[2] + Edge[2] },
};
2014-04-20 03:50:41 +02:00
Context->SetWorldViewMatrix(lcMul(Piece->mModelWorld, ViewMatrix));
2014-04-20 03:50:41 +02:00
if (Piece->IsFocused())
lcSetColorFocused();
else
lcSetColorSelected();
2014-04-20 03:50:41 +02:00
glVertexPointer(3, GL_FLOAT, 0, Verts);
glDrawArrays(GL_LINES, 0, 48);
}
2014-04-20 03:50:41 +02:00
Context->SetLineWidth(Preferences.mLineWidth); // context remove
}
2012-01-28 02:05:23 +01:00
}
2011-09-07 23:06:51 +02:00
2012-01-28 02:05:23 +01:00
void Project::RenderSceneObjects(View* view)
{
const lcPreferences& Preferences = lcGetPreferences();
2014-02-16 08:23:55 +01:00
const lcMatrix44& ViewMatrix = view->mCamera->mWorldView;
2014-04-14 05:20:16 +02:00
lcContext* Context = view->mContext;
2014-05-03 03:22:24 +02:00
Context->SetProjectionMatrix(view->GetProjectionMatrix());
2011-09-07 23:06:51 +02:00
#ifdef LC_DEBUG
2012-01-28 02:05:23 +01:00
RenderDebugPrimitives();
2011-09-07 23:06:51 +02:00
#endif
2014-05-27 00:58:08 +02:00
if (view->mTrackTool == LC_TRACKTOOL_INSERT)
2012-01-28 02:05:23 +01:00
{
2014-02-16 08:23:55 +01:00
lcVector3 Position;
lcVector4 Rotation;
2014-05-03 18:59:57 +02:00
GetPieceInsertPosition(view, Position, Rotation);
2012-01-28 02:05:23 +01:00
2014-02-16 08:23:55 +01:00
lcMatrix44 WorldMatrix = lcMatrix44FromAxisAngle(lcVector3(Rotation[0], Rotation[1], Rotation[2]), Rotation[3] * LC_DTOR);
WorldMatrix.SetTranslation(Position);
2014-05-03 03:22:24 +02:00
Context->SetWorldViewMatrix(lcMul(WorldMatrix, ViewMatrix));
2014-02-16 08:23:55 +01:00
2014-04-14 05:20:16 +02:00
Context->SetLineWidth(2.0f * Preferences.mLineWidth);
2014-10-08 01:02:52 +02:00
gMainWindow->mPreviewWidget->GetCurrentPiece()->RenderPiece(gMainWindow->mColorIndex);
2012-01-28 02:05:23 +01:00
}
2011-09-07 23:06:51 +02:00
if (Preferences.mLightingMode != LC_LIGHTING_FLAT)
2014-05-27 00:58:08 +02:00
glDisable(GL_LIGHTING);
2013-01-06 20:24:25 +01:00
2012-08-22 03:13:32 +02:00
for (int CameraIdx = 0; CameraIdx < mCameras.GetSize(); CameraIdx++)
2012-01-28 02:05:23 +01:00
{
2014-08-07 17:22:33 +02:00
lcCamera* pCamera = mCameras[CameraIdx];
2012-08-22 03:13:32 +02:00
2012-08-20 06:05:56 +02:00
if ((pCamera == view->mCamera) || !pCamera->IsVisible())
2012-01-28 02:05:23 +01:00
continue;
2012-08-20 06:05:56 +02:00
2014-04-14 05:20:16 +02:00
pCamera->Render(view);
2012-01-28 02:05:23 +01:00
}
2011-09-07 23:06:51 +02:00
for (int LightIdx = 0; LightIdx < mLights.GetSize(); LightIdx++)
if (mLights[LightIdx]->IsVisible())
2014-04-14 05:20:16 +02:00
mLights[LightIdx]->Render(view);
Context->SetLineWidth(Preferences.mLineWidth); // context remove
2011-09-07 23:06:51 +02:00
}
void Project::ZoomExtents(int FirstView, int LastView)
{
float BoundingBox[6];
2011-09-07 23:06:51 +02:00
if (!GetPiecesBoundingBox(BoundingBox))
return;
2011-09-07 23:06:51 +02:00
lcVector3 Center((BoundingBox[0] + BoundingBox[3]) / 2, (BoundingBox[1] + BoundingBox[4]) / 2, (BoundingBox[2] + BoundingBox[5]) / 2);
2011-09-07 23:06:51 +02:00
lcVector3 Points[8] =
{
lcVector3(BoundingBox[0], BoundingBox[1], BoundingBox[5]),
lcVector3(BoundingBox[3], BoundingBox[1], BoundingBox[5]),
lcVector3(BoundingBox[0], BoundingBox[1], BoundingBox[2]),
lcVector3(BoundingBox[3], BoundingBox[4], BoundingBox[5]),
lcVector3(BoundingBox[3], BoundingBox[4], BoundingBox[2]),
lcVector3(BoundingBox[0], BoundingBox[4], BoundingBox[2]),
lcVector3(BoundingBox[0], BoundingBox[4], BoundingBox[5]),
lcVector3(BoundingBox[3], BoundingBox[1], BoundingBox[2])
};
2011-09-07 23:06:51 +02:00
const lcArray<View*> Views = gMainWindow->GetViews();
for (int vp = FirstView; vp < LastView; vp++)
{
View* view = Views[vp];
2012-08-09 00:11:23 +02:00
2014-07-06 08:04:09 +02:00
view->mCamera->ZoomExtents(view, Center, Points, 8, mCurrentStep, gMainWindow->GetAddKeys());
}
2012-08-09 00:11:23 +02:00
gMainWindow->UpdateFocusObject(GetFocusObject());
gMainWindow->UpdateAllViews();
}
2012-08-09 00:11:23 +02:00
2014-10-12 01:26:23 +02:00
void Project::SaveImage()
{
2014-10-12 01:26:23 +02:00
lcImageDialogOptions Options;
lcStep LastStep = GetLastStep();
Options.Width = lcGetProfileInt(LC_PROFILE_IMAGE_WIDTH);
Options.Height = lcGetProfileInt(LC_PROFILE_IMAGE_HEIGHT);
Options.Start = mCurrentStep;
Options.End = LastStep;
if (m_strPathName[0])
{
Options.FileName = m_strPathName;
QString Extension = QFileInfo(Options.FileName).suffix();
Options.FileName = Options.FileName.mid(0, Options.FileName.length() - Extension.length());
}
else
Options.FileName = QLatin1String("image");
Options.FileName += lcGetProfileString(LC_PROFILE_IMAGE_EXTENSION);
if (!gMainWindow->DoDialog(LC_DIALOG_SAVE_IMAGE, &Options))
return;
QString Extension = QFileInfo(Options.FileName).suffix();
if (!Extension.isEmpty())
lcSetProfileString(LC_PROFILE_IMAGE_EXTENSION, Options.FileName.right(Extension.length() + 1));
lcSetProfileInt(LC_PROFILE_IMAGE_WIDTH, Options.Width);
lcSetProfileInt(LC_PROFILE_IMAGE_HEIGHT, Options.Height);
if (Options.Start != Options.End)
Options.FileName = Options.FileName.insert(Options.FileName.length() - Extension.length() - 1, QLatin1String("%1"));
SaveStepImages(Options.FileName, Options.Width, Options.Height, Options.Start, Options.End);
}
void Project::SaveStepImages(const QString& BaseName, int Width, int Height, lcStep Start, lcStep End)
{
gMainWindow->mPreviewWidget->MakeCurrent();
lcContext* Context = gMainWindow->mPreviewWidget->mContext;
if (!Context->BeginRenderToTexture(Width, Height))
2011-09-07 23:06:51 +02:00
{
gMainWindow->DoMessageBox("Error creating images.", LC_MB_ICONERROR | LC_MB_OK);
return;
}
2011-09-07 23:06:51 +02:00
2014-07-06 08:04:09 +02:00
lcStep CurrentStep = mCurrentStep;
2011-09-07 23:06:51 +02:00
2014-10-12 01:26:23 +02:00
View View(this);
View.SetCamera(gMainWindow->GetActiveView()->mCamera, false);
View.mWidth = Width;
View.mHeight = Height;
View.SetContext(Context);
2011-09-07 23:06:51 +02:00
2014-10-12 01:26:23 +02:00
for (lcStep Step = Start; Step <= End; Step++)
{
2014-10-12 01:26:23 +02:00
SetCurrentStep(Step);
Render(&View, true);
2011-09-07 23:06:51 +02:00
2014-10-12 01:26:23 +02:00
QString FileName = BaseName.arg(Step, 2, 10, QLatin1Char('0'));
if (!Context->GetRenderToTextureImage(Width, Height).save(FileName))
2011-09-07 23:06:51 +02:00
{
2014-10-12 01:26:23 +02:00
QMessageBox::warning(gMainWindow->mHandle, tr("Error"), tr("Error saving '%1'.").arg(FileName));
break;
2011-09-07 23:06:51 +02:00
}
}
2014-07-06 08:04:09 +02:00
SetCurrentStep(CurrentStep);
2011-09-07 23:06:51 +02:00
2014-10-12 01:26:23 +02:00
Context->EndRenderToTexture();
2011-09-07 23:06:51 +02:00
}
2014-07-06 08:04:09 +02:00
void Project::CreateHTMLPieceList(FILE* f, lcStep Step, bool bImages, const char* ext)
2011-09-07 23:06:51 +02:00
{
int* ColorsUsed = new int[gColorList.GetSize()];
memset(ColorsUsed, 0, sizeof(ColorsUsed[0]) * gColorList.GetSize());
int* PiecesUsed = new int[gColorList.GetSize()];
int NumColors = 0;
2011-09-07 23:06:51 +02:00
for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++)
{
2014-08-07 17:22:33 +02:00
lcPiece* Piece = mPieces[PieceIdx];
2011-09-07 23:06:51 +02:00
2014-07-06 08:04:09 +02:00
if ((Piece->GetStepShow() == Step) || (Step == 0))
ColorsUsed[Piece->mColorIndex]++;
}
2011-09-07 23:06:51 +02:00
fputs("<br><table border=1><tr><td><center>Piece</center></td>\n",f);
2011-09-07 23:06:51 +02:00
for (int ColorIdx = 0; ColorIdx < gColorList.GetSize(); ColorIdx++)
{
if (ColorsUsed[ColorIdx])
2011-09-07 23:06:51 +02:00
{
ColorsUsed[ColorIdx] = NumColors;
NumColors++;
fprintf(f, "<td><center>%s</center></td>\n", gColorList[ColorIdx].Name);
2011-09-07 23:06:51 +02:00
}
}
NumColors++;
fputs("</tr>\n",f);
2011-09-07 23:06:51 +02:00
PieceInfo* pInfo;
for (int j = 0; j < lcGetPiecesLibrary()->mPieces.GetSize(); j++)
2011-09-07 23:06:51 +02:00
{
bool Add = false;
memset(PiecesUsed, 0, sizeof(PiecesUsed[0]) * gColorList.GetSize());
pInfo = lcGetPiecesLibrary()->mPieces[j];
for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++)
{
2014-08-07 17:22:33 +02:00
lcPiece* Piece = mPieces[PieceIdx];
2014-07-06 08:04:09 +02:00
if ((Piece->mPieceInfo == pInfo) && ((Piece->GetStepShow() == Step) || (Step == 0)))
{
PiecesUsed[Piece->mColorIndex]++;
Add = true;
}
}
if (Add)
{
if (bImages)
fprintf(f, "<tr><td><IMG SRC=\"%s%s\" ALT=\"%s\"></td>\n", pInfo->m_strName, ext, pInfo->m_strDescription);
else
fprintf(f, "<tr><td>%s</td>\n", pInfo->m_strDescription);
int curcol = 1;
for (int ColorIdx = 0; ColorIdx < gColorList.GetSize(); ColorIdx++)
{
if (PiecesUsed[ColorIdx])
{
while (curcol != ColorsUsed[ColorIdx] + 1)
{
fputs("<td><center>-</center></td>\n", f);
curcol++;
}
fprintf(f, "<td><center>%d</center></td>\n", PiecesUsed[ColorIdx]);
curcol++;
}
}
while (curcol != NumColors)
{
fputs("<td><center>-</center></td>\n", f);
curcol++;
}
fputs("</tr>\n", f);
}
2011-09-07 23:06:51 +02:00
}
fputs("</table>\n<br>", f);
2011-09-07 23:06:51 +02:00
delete[] PiecesUsed;
delete[] ColorsUsed;
}
2011-09-07 23:06:51 +02:00
void Project::HandleCommand(LC_COMMANDS id)
{
switch (id)
{
case LC_FILE_NEW:
{
if (!SaveModified())
return; // leave the original one
2013-08-09 06:57:18 +02:00
OnNewDocument();
gMainWindow->UpdateAllViews();
} break;
2013-08-09 06:57:18 +02:00
case LC_FILE_OPEN:
{
char FileName[LC_MAXPATH];
2013-08-09 06:57:18 +02:00
if (m_strPathName[0])
strcpy(FileName, m_strPathName);
else
strcpy(FileName, lcGetProfileString(LC_PROFILE_PROJECTS_PATH));
2013-08-09 06:57:18 +02:00
if (gMainWindow->DoDialog(LC_DIALOG_OPEN_PROJECT, FileName))
OpenProject(FileName);
} break;
2013-08-09 06:57:18 +02:00
case LC_FILE_MERGE:
{
char FileName[LC_MAXPATH];
2013-08-09 06:57:18 +02:00
if (m_strPathName[0])
strcpy(FileName, m_strPathName);
else
strcpy(FileName, lcGetProfileString(LC_PROFILE_PROJECTS_PATH));
2013-08-09 06:57:18 +02:00
if (gMainWindow->DoDialog(LC_DIALOG_MERGE_PROJECT, FileName))
2013-08-09 06:57:18 +02:00
{
lcDiskFile file;
if (file.Open(FileName, "rb"))
{
if (file.GetLength() != 0)
{
FileLoad(&file, false, true);
CheckPoint("Merging");
}
file.Close();
}
2013-08-09 06:57:18 +02:00
}
} break;
2013-08-09 06:57:18 +02:00
2014-10-08 01:02:52 +02:00
case LC_FILE_SAVE:
DoSave(m_strPathName);
break;
2013-08-09 06:57:18 +02:00
2014-10-08 01:02:52 +02:00
case LC_FILE_SAVEAS:
DoSave(NULL);
break;
2013-08-09 06:57:18 +02:00
2014-10-12 01:26:23 +02:00
case LC_FILE_SAVE_IMAGE:
SaveImage();
break;
2013-08-09 06:57:18 +02:00
2014-10-12 01:26:23 +02:00
case LC_FILE_EXPORT_3DS:
Export3DStudio();
break;
2013-08-09 06:57:18 +02:00
case LC_FILE_EXPORT_HTML:
2013-08-09 06:57:18 +02:00
{
lcHTMLDialogOptions Options;
strcpy(Options.PathName, m_strPathName);
if (Options.PathName[0] != 0)
{
char* Slash = strrchr(Options.PathName, '/');
if (Slash == NULL)
Slash = strrchr(Options.PathName, '\\');
if (Slash)
{
Slash++;
*Slash = 0;
}
}
2013-08-09 06:57:18 +02:00
int ImageOptions = lcGetProfileInt(LC_PROFILE_HTML_IMAGE_OPTIONS);
int HTMLOptions = lcGetProfileInt(LC_PROFILE_HTML_OPTIONS);
2013-08-09 06:57:18 +02:00
Options.ImageFormat = (LC_IMAGE_FORMAT)(ImageOptions & ~(LC_IMAGE_MASK));
Options.TransparentImages = (ImageOptions & LC_IMAGE_TRANSPARENT) != 0;
Options.SinglePage = (HTMLOptions & LC_HTML_SINGLEPAGE) != 0;
Options.IndexPage = (HTMLOptions & LC_HTML_INDEX) != 0;
Options.StepImagesWidth = lcGetProfileInt(LC_PROFILE_HTML_IMAGE_WIDTH);
Options.StepImagesHeight = lcGetProfileInt(LC_PROFILE_HTML_IMAGE_HEIGHT);
Options.HighlightNewParts = (HTMLOptions & LC_HTML_HIGHLIGHT) != 0;
Options.PartsListStep = (HTMLOptions & LC_HTML_LISTSTEP) != 0;
Options.PartsListEnd = (HTMLOptions & LC_HTML_LISTEND) != 0;
Options.PartsListImages = (HTMLOptions & LC_HTML_IMAGES) != 0;
Options.PartImagesColor = lcGetColorIndex(lcGetProfileInt(LC_PROFILE_HTML_PARTS_COLOR));
Options.PartImagesWidth = lcGetProfileInt(LC_PROFILE_HTML_PARTS_WIDTH);
Options.PartImagesHeight = lcGetProfileInt(LC_PROFILE_HTML_PARTS_HEIGHT);
2013-08-09 06:57:18 +02:00
if (!gMainWindow->DoDialog(LC_DIALOG_EXPORT_HTML, &Options))
break;
2013-08-09 06:57:18 +02:00
HTMLOptions = 0;
2013-08-09 06:57:18 +02:00
if (Options.SinglePage)
HTMLOptions |= LC_HTML_SINGLEPAGE;
if (Options.IndexPage)
HTMLOptions |= LC_HTML_INDEX;
if (Options.HighlightNewParts)
HTMLOptions |= LC_HTML_HIGHLIGHT;
if (Options.PartsListStep)
HTMLOptions |= LC_HTML_LISTSTEP;
if (Options.PartsListEnd)
HTMLOptions |= LC_HTML_LISTEND;
if (Options.PartsListImages)
HTMLOptions |= LC_HTML_IMAGES;
2013-08-09 06:57:18 +02:00
ImageOptions = Options.ImageFormat;
if (Options.TransparentImages)
ImageOptions |= LC_IMAGE_TRANSPARENT;
lcSetProfileInt(LC_PROFILE_HTML_IMAGE_OPTIONS, ImageOptions);
lcSetProfileInt(LC_PROFILE_HTML_OPTIONS, HTMLOptions);
lcSetProfileInt(LC_PROFILE_HTML_IMAGE_WIDTH, Options.StepImagesWidth);
lcSetProfileInt(LC_PROFILE_HTML_IMAGE_HEIGHT, Options.StepImagesHeight);
lcSetProfileInt(LC_PROFILE_HTML_PARTS_COLOR, lcGetColorCode(Options.PartImagesColor));
lcSetProfileInt(LC_PROFILE_HTML_PARTS_WIDTH, Options.PartImagesWidth);
lcSetProfileInt(LC_PROFILE_HTML_PARTS_HEIGHT, Options.PartImagesHeight);
int PathLength = strlen(Options.PathName);
if (PathLength && Options.PathName[PathLength] != '/' && Options.PathName[PathLength] != '\\')
strcat(Options.PathName, "/");
// TODO: create directory
2013-08-09 06:57:18 +02:00
// TODO: Move to its own function
{
FILE* f;
const char *ext, *htmlext;
char fn[LC_MAXPATH];
2014-07-06 08:04:09 +02:00
lcStep LastStep = GetLastStep();
switch (Options.ImageFormat)
{
case LC_IMAGE_BMP: ext = ".bmp";
break;
case LC_IMAGE_JPG: ext = ".jpg";
break;
default:
case LC_IMAGE_PNG: ext = ".png";
break;
}
htmlext = ".html";
2013-08-09 06:57:18 +02:00
if (Options.SinglePage)
{
strcpy(fn, Options.PathName);
strcat(fn, m_strTitle);
strcat(fn, htmlext);
f = fopen (fn, "wt");
2013-08-09 06:57:18 +02:00
if (!f)
{
gMainWindow->DoMessageBox("Could not open file for writing.", LC_MB_OK | LC_MB_ICONERROR);
break;
}
2013-08-09 06:57:18 +02:00
fprintf (f, "<HTML>\n<HEAD>\n<TITLE>Instructions for %s</TITLE>\n</HEAD>\n<BR>\n<CENTER>\n", m_strTitle);
2014-07-06 08:04:09 +02:00
for (lcStep Step = 1; Step <= LastStep; Step++)
{
fprintf(f, "<IMG SRC=\"%s-%02d%s\" ALT=\"Step %02d\" WIDTH=%d HEIGHT=%d><BR><BR>\n",
2014-07-06 08:04:09 +02:00
m_strTitle, Step, ext, Step, Options.StepImagesWidth, Options.StepImagesHeight);
if (Options.PartsListStep)
2014-07-06 08:04:09 +02:00
CreateHTMLPieceList(f, Step, Options.PartsListImages, ext);
}
if (Options.PartsListEnd)
CreateHTMLPieceList(f, 0, Options.PartsListImages, ext);
fputs("</CENTER>\n<BR><HR><BR><B><I>Created by <A HREF=\"http://www.leocad.org\">LeoCAD</A></B></I><BR></HTML>\n", f);
fclose(f);
}
else
{
if (Options.IndexPage)
{
strcpy(fn, Options.PathName);
strcat (fn, m_strTitle);
strcat (fn, "-index");
strcat (fn, htmlext);
f = fopen (fn, "wt");
if (!f)
{
gMainWindow->DoMessageBox("Could not open file for writing.", LC_MB_OK | LC_MB_ICONERROR);
break;
}
fprintf(f, "<HTML>\n<HEAD>\n<TITLE>Instructions for %s</TITLE>\n</HEAD>\n<BR>\n<CENTER>\n", m_strTitle);
2014-07-06 08:04:09 +02:00
for (lcStep Step = 1; Step <= LastStep; Step++)
fprintf(f, "<A HREF=\"%s-%02d%s\">Step %d<BR>\n</A>", m_strTitle, Step, htmlext, Step);
if (Options.PartsListEnd)
fprintf(f, "<A HREF=\"%s-pieces%s\">Pieces Used</A><BR>\n", m_strTitle, htmlext);
fputs("</CENTER>\n<BR><HR><BR><B><I>Created by <A HREF=\"http://www.leocad.org\">LeoCAD</A></B></I><BR></HTML>\n", f);
fclose(f);
}
// Create each step
2014-07-06 08:04:09 +02:00
for (lcStep Step = 1; Step <= LastStep; Step++)
{
2014-07-06 08:04:09 +02:00
sprintf(fn, "%s%s-%02d%s", Options.PathName, m_strTitle, Step, htmlext);
f = fopen(fn, "wt");
if (!f)
{
gMainWindow->DoMessageBox("Could not open file for writing.", LC_MB_OK | LC_MB_ICONERROR);
break;
}
2014-07-06 08:04:09 +02:00
fprintf(f, "<HTML>\n<HEAD>\n<TITLE>%s - Step %02d</TITLE>\n</HEAD>\n<BR>\n<CENTER>\n", m_strTitle, Step);
fprintf(f, "<IMG SRC=\"%s-%02d%s\" ALT=\"Step %02d\" WIDTH=%d HEIGHT=%d><BR><BR>\n",
2014-07-06 08:04:09 +02:00
m_strTitle, Step, ext, Step, Options.StepImagesWidth, Options.StepImagesHeight);
if (Options.PartsListStep)
2014-07-06 08:04:09 +02:00
CreateHTMLPieceList(f, Step, Options.PartsListImages, ext);
fputs("</CENTER>\n<BR><HR><BR>", f);
2014-07-06 08:04:09 +02:00
if (Step != 1)
fprintf(f, "<A HREF=\"%s-%02d%s\">Previous</A> ", m_strTitle, Step - 1, htmlext);
if (Options.IndexPage)
fprintf(f, "<A HREF=\"%s-index%s\">Index</A> ", m_strTitle, htmlext);
2014-07-06 08:04:09 +02:00
if (Step != LastStep)
fprintf(f, "<A HREF=\"%s-%02d%s\">Next</A>", m_strTitle, Step + 1, htmlext);
else if (Options.PartsListEnd)
fprintf(f, "<A HREF=\"%s-pieces%s\">Pieces Used</A>", m_strTitle, htmlext);
fputs("<BR></HTML>\n",f);
fclose(f);
}
if (Options.PartsListEnd)
{
strcpy(fn, Options.PathName);
strcat (fn, m_strTitle);
strcat (fn, "-pieces");
strcat (fn, htmlext);
f = fopen (fn, "wt");
2013-08-09 06:57:18 +02:00
if (!f)
{
gMainWindow->DoMessageBox("Could not open file for writing.", LC_MB_OK | LC_MB_ICONERROR);
break;
}
2013-08-09 06:57:18 +02:00
fprintf (f, "<HTML>\n<HEAD>\n<TITLE>Pieces used by %s</TITLE>\n</HEAD>\n<BR>\n<CENTER>\n", m_strTitle);
2011-09-07 23:06:51 +02:00
CreateHTMLPieceList(f, 0, Options.PartsListImages, ext);
2013-01-06 20:24:25 +01:00
fputs("</CENTER>\n<BR><HR><BR>", f);
2014-07-06 08:04:09 +02:00
fprintf(f, "<A HREF=\"%s-%02d%s\">Previous</A> ", m_strTitle, LastStep, htmlext);
2011-09-07 23:06:51 +02:00
if (Options.IndexPage)
fprintf(f, "<A HREF=\"%s-index%s\">Index</A> ", m_strTitle, htmlext);
2013-08-09 06:57:18 +02:00
fputs("<BR></HTML>\n",f);
fclose(f);
}
}
2013-01-06 20:24:25 +01:00
2014-10-12 01:26:23 +02:00
sprintf(fn, "%s%s-%%1%s", Options.PathName, m_strTitle, ext);
SaveStepImages(fn, Options.StepImagesWidth, Options.StepImagesHeight, 1, LastStep);
2013-08-09 06:57:18 +02:00
if (Options.PartsListImages)
2011-09-07 23:06:51 +02:00
{
2014-10-12 01:26:23 +02:00
gMainWindow->mPreviewWidget->MakeCurrent();
lcContext* Context = gMainWindow->mPreviewWidget->mContext;
int cx = Options.PartImagesWidth;
int cy = Options.PartImagesHeight;
if (!Context->BeginRenderToTexture(cx, cy))
2011-09-07 23:06:51 +02:00
{
gMainWindow->DoMessageBox("Error creating images.", LC_MB_ICONERROR | LC_MB_OK);
break;
2011-09-07 23:06:51 +02:00
}
float aspect = (float)cx/(float)cy;
glViewport(0, 0, cx, cy);
2011-09-07 23:06:51 +02:00
for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++)
{
2014-08-07 17:22:33 +02:00
lcPiece* Piece = mPieces[PieceIdx];
2014-10-12 01:26:23 +02:00
bool Skip = false;
PieceInfo* Info = Piece->mPieceInfo;
for (int CheckIdx = 0; CheckIdx < PieceIdx; CheckIdx++)
{
2014-10-12 01:26:23 +02:00
if (mPieces[CheckIdx]->mPieceInfo == Info)
{
2014-10-12 01:26:23 +02:00
Skip = true;
break;
}
}
2014-10-12 01:26:23 +02:00
if (Skip)
continue;
glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2014-10-12 01:26:23 +02:00
Info->ZoomExtents(30.0f, aspect);
Info->RenderPiece(Options.PartImagesColor);
glFinish();
2014-10-12 01:26:23 +02:00
sprintf(fn, "%s%s%s", Options.PathName, Info->m_strName, ext);
if (!Context->GetRenderToTextureImage(cx, cy).save(fn))
{
QMessageBox::warning(gMainWindow->mHandle, tr("Error"), tr("Error saving '%1'.").arg(fn));
break;
}
}
2014-10-12 01:26:23 +02:00
Context->EndRenderToTexture();
}
}
2011-09-07 23:06:51 +02:00
} break;
2014-10-11 01:53:08 +02:00
case LC_FILE_EXPORT_BRICKLINK:
ExportBrickLink();
break;
2011-09-07 23:06:51 +02:00
2014-10-11 01:53:08 +02:00
case LC_FILE_EXPORT_CSV:
ExportCSV();
break;
2013-01-06 20:24:25 +01:00
2014-10-11 01:53:08 +02:00
case LC_FILE_EXPORT_POVRAY:
ExportPOVRay();
break;
2011-09-07 23:06:51 +02:00
2014-10-11 01:53:08 +02:00
case LC_FILE_EXPORT_WAVEFRONT:
ExportWavefront();
break;
2011-09-07 23:06:51 +02:00
case LC_FILE_PROPERTIES:
{
lcPropertiesDialogOptions Options;
2011-09-07 23:06:51 +02:00
Options.Properties = mProperties;
Options.Title = m_strTitle;
Options.SetDefault = false;
2014-10-11 01:53:08 +02:00
GetPartsList(Options.PartsList);
2011-09-07 23:06:51 +02:00
if (!gMainWindow->DoDialog(LC_DIALOG_PROPERTIES, &Options))
break;
2011-09-07 23:06:51 +02:00
if (Options.SetDefault)
Options.Properties.SaveDefaults();
2011-09-07 23:06:51 +02:00
if (mProperties == Options.Properties)
break;
2011-09-07 23:06:51 +02:00
mProperties = Options.Properties;
2011-09-07 23:06:51 +02:00
2014-10-05 07:21:51 +02:00
UpdateBackgroundTexture();
CheckPoint("Properties");
} break;
2013-01-06 20:24:25 +01:00
case LC_FILE_PRINT_PREVIEW:
gMainWindow->TogglePrintPreview();
break;
2011-09-07 23:06:51 +02:00
case LC_FILE_PRINT:
gMainWindow->DoDialog(LC_DIALOG_PRINT, NULL);
break;
2011-09-07 23:06:51 +02:00
// TODO: printing
case LC_FILE_PRINT_BOM:
break;
2011-09-07 23:06:51 +02:00
2014-07-03 21:10:04 +02:00
case LC_FILE_RECENT1:
case LC_FILE_RECENT2:
case LC_FILE_RECENT3:
case LC_FILE_RECENT4:
if (!OpenProject(gMainWindow->mRecentFiles[id - LC_FILE_RECENT1]))
gMainWindow->RemoveRecentFile(id - LC_FILE_RECENT1);
break;
2013-01-06 20:24:25 +01:00
2014-07-03 21:10:04 +02:00
case LC_FILE_EXIT:
gMainWindow->Close();
break;
2011-09-07 23:06:51 +02:00
2014-07-03 21:10:04 +02:00
case LC_EDIT_UNDO:
{
2014-07-03 21:10:04 +02:00
if (mUndoHistory.GetSize() < 2)
break;
2011-09-07 23:06:51 +02:00
2014-07-03 21:10:04 +02:00
lcModelHistoryEntry* Undo = mUndoHistory[0];
mUndoHistory.RemoveIndex(0);
mRedoHistory.InsertAt(0, Undo);
2011-09-07 23:06:51 +02:00
2014-09-14 02:45:45 +02:00
LoadCheckPoint(mUndoHistory[0]);
2011-09-07 23:06:51 +02:00
gMainWindow->UpdateModified(IsModified());
2014-07-03 21:10:04 +02:00
gMainWindow->UpdateUndoRedo(mUndoHistory.GetSize() > 1 ? mUndoHistory[0]->Description : NULL, !mRedoHistory.IsEmpty() ? mRedoHistory[0]->Description : NULL);
}
break;
2011-09-07 23:06:51 +02:00
2014-07-03 21:10:04 +02:00
case LC_EDIT_REDO:
{
if (mRedoHistory.IsEmpty())
break;
2011-09-07 23:06:51 +02:00
2014-07-03 21:10:04 +02:00
lcModelHistoryEntry* Redo = mRedoHistory[0];
mRedoHistory.RemoveIndex(0);
mUndoHistory.InsertAt(0, Redo);
2011-09-07 23:06:51 +02:00
2014-09-14 02:45:45 +02:00
LoadCheckPoint(Redo);
2011-09-07 23:06:51 +02:00
gMainWindow->UpdateModified(IsModified());
2014-07-03 21:10:04 +02:00
gMainWindow->UpdateUndoRedo(mUndoHistory.GetSize() > 1 ? mUndoHistory[0]->Description : NULL, !mRedoHistory.IsEmpty() ? mRedoHistory[0]->Description : NULL);
}
break;
2011-09-07 23:06:51 +02:00
2014-07-03 21:10:04 +02:00
case LC_EDIT_CUT:
case LC_EDIT_COPY:
2013-01-25 00:54:10 +01:00
{
lcMemFile* Clipboard = new lcMemFile();
2013-01-26 00:22:24 +01:00
int i = 0;
2014-08-07 17:22:33 +02:00
// lcLight* pLight;
2013-01-25 00:54:10 +01:00
for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++)
if (mPieces[PieceIdx]->IsSelected())
i++;
Clipboard->WriteBuffer(&i, sizeof(i));
2013-01-25 00:54:10 +01:00
for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++)
2013-01-25 00:54:10 +01:00
{
2014-08-07 17:22:33 +02:00
lcPiece* Piece = mPieces[PieceIdx];
2013-01-25 00:54:10 +01:00
if (Piece->IsSelected())
Piece->FileSave(*Clipboard);
}
2013-01-25 00:54:10 +01:00
2014-05-25 03:45:19 +02:00
i = mGroups.GetSize();
Clipboard->WriteBuffer(&i, sizeof(i));
2013-01-25 00:54:10 +01:00
2014-05-25 03:45:19 +02:00
for (int GroupIdx = 0; GroupIdx < mGroups.GetSize(); GroupIdx++)
mGroups[GroupIdx]->FileSave(Clipboard, mGroups);
2013-01-25 00:54:10 +01:00
i = 0;
for (int CameraIdx = 0; CameraIdx < mCameras.GetSize(); CameraIdx++)
if (mCameras[CameraIdx]->IsSelected())
i++;
Clipboard->WriteBuffer(&i, sizeof(i));
2013-01-25 00:54:10 +01:00
for (int CameraIdx = 0; CameraIdx < mCameras.GetSize(); CameraIdx++)
{
2014-08-07 17:22:33 +02:00
lcCamera* pCamera = mCameras[CameraIdx];
2013-01-25 00:54:10 +01:00
if (pCamera->IsSelected())
pCamera->FileSave(*Clipboard);
2013-01-25 00:54:10 +01:00
}
/*
for (i = 0, pLight = m_pLights; pLight; pLight = pLight->m_pNext)
if (pLight->IsSelected())
i++;
Clipboard->Write(&i, sizeof(i));
2013-01-25 00:54:10 +01:00
for (pLight = m_pLights; pLight; pLight = pLight->m_pNext)
if (pLight->IsSelected())
pLight->FileSave(Clipboard);
*/
if (id == LC_EDIT_CUT)
2013-08-09 06:57:18 +02:00
{
RemoveSelectedObjects();
gMainWindow->UpdateFocusObject(GetFocusObject());
UpdateSelection();
gMainWindow->UpdateAllViews();
CheckPoint("Cutting");
2013-08-09 06:57:18 +02:00
}
g_App->ExportClipboard(Clipboard);
} break;
2013-08-09 06:57:18 +02:00
case LC_EDIT_PASTE:
{
lcFile* file = g_App->mClipboard;
if (file == NULL)
2013-08-09 06:57:18 +02:00
break;
file->Seek(0, SEEK_SET);
2014-08-17 22:44:12 +02:00
ClearSelection(false);
2013-08-09 06:57:18 +02:00
2014-08-07 17:22:33 +02:00
lcArray<lcPiece*> PastedPieces;
2014-05-25 03:45:19 +02:00
int NumPieces;
file->ReadBuffer(&NumPieces, sizeof(NumPieces));
while (NumPieces--)
2013-08-09 06:57:18 +02:00
{
2014-05-25 03:45:19 +02:00
lcPiece* Piece = new lcPiece(NULL);
Piece->FileLoad(*file);
PastedPieces.Add(Piece);
2013-08-09 06:57:18 +02:00
}
2014-05-25 03:45:19 +02:00
lcArray<lcGroup*> Groups;
int NumGroups;
file->ReadBuffer(&NumGroups, sizeof(NumGroups));
while (NumGroups--)
2013-08-09 06:57:18 +02:00
{
2014-05-25 03:45:19 +02:00
lcGroup* Group = new lcGroup();
Group->FileLoad(file);
Groups.Add(Group);
2013-08-09 06:57:18 +02:00
}
for (int PieceIdx = 0; PieceIdx < PastedPieces.GetSize(); PieceIdx++)
{
2014-05-25 03:45:19 +02:00
lcPiece* Piece = PastedPieces[PieceIdx];
Piece->CreateName(mPieces);
2014-07-06 08:04:09 +02:00
Piece->SetStepShow(mCurrentStep);
mPieces.Add(Piece);
Piece->SetSelected(true);
2013-08-09 06:57:18 +02:00
2014-05-25 03:45:19 +02:00
int GroupIndex = LC_POINTER_TO_INT(Piece->GetGroup());
if (GroupIndex != -1)
Piece->SetGroup(Groups[GroupIndex]);
else
2014-05-25 20:23:09 +02:00
Piece->SetGroup(NULL);
}
2014-05-25 03:45:19 +02:00
for (int GroupIdx = 0; GroupIdx < Groups.GetSize(); GroupIdx++)
{
2014-05-25 03:45:19 +02:00
lcGroup* Group = Groups[GroupIdx];
int GroupIndex = LC_POINTER_TO_INT(Group->mGroup);
Group->mGroup = (GroupIndex != -1) ? Groups[GroupIndex] : NULL;
}
2014-05-25 03:45:19 +02:00
for (int GroupIdx = 0; GroupIdx < Groups.GetSize(); GroupIdx++)
2011-09-07 23:06:51 +02:00
{
2014-05-25 03:45:19 +02:00
lcGroup* Group = Groups[GroupIdx];
bool Add = false;
2012-03-09 23:47:05 +01:00
2014-05-25 03:45:19 +02:00
for (int PieceIdx = 0; PieceIdx < PastedPieces.GetSize(); PieceIdx++)
{
lcPiece* Piece = PastedPieces[PieceIdx];
for (lcGroup* PieceGroup = Piece->GetGroup(); PieceGroup; PieceGroup = PieceGroup->mGroup)
{
if (PieceGroup == Group)
{
2014-05-25 03:45:19 +02:00
Add = true;
break;
}
2014-05-25 03:45:19 +02:00
}
2012-03-09 23:47:05 +01:00
2014-05-25 03:45:19 +02:00
if (Add)
break;
2012-03-09 23:47:05 +01:00
}
2013-08-17 01:17:25 +02:00
2014-05-25 03:45:19 +02:00
if (Add)
{
int a, max = 0;
2014-05-25 03:45:19 +02:00
for (int SearchGroupIdx = 0; SearchGroupIdx < mGroups.GetSize(); SearchGroupIdx++)
{
lcGroup* SearchGroup = mGroups[SearchGroupIdx];
if (strncmp("Pasted Group #", SearchGroup ->m_strName, 14) == 0)
if (sscanf(SearchGroup ->m_strName + 14, "%d", &a) == 1)
if (a > max)
max = a;
2014-05-25 03:45:19 +02:00
}
2011-09-07 23:06:51 +02:00
2014-05-25 03:45:19 +02:00
sprintf(Group->m_strName, "Pasted Group #%.2d", max+1);
mGroups.Add(Group);
}
2011-09-07 23:06:51 +02:00
else
2014-05-25 03:45:19 +02:00
delete Group;
2011-09-07 23:06:51 +02:00
}
2014-05-25 03:45:19 +02:00
int NumCameras;
file->ReadBuffer(&NumCameras, sizeof(NumCameras));
2014-05-25 03:45:19 +02:00
while (NumCameras--)
{
2014-08-07 17:22:33 +02:00
lcCamera* pCamera = new lcCamera(false);
pCamera->FileLoad(*file);
pCamera->CreateName(mCameras);
pCamera->SetSelected(true);
mCameras.Add(pCamera);
}
2011-09-07 23:06:51 +02:00
// TODO: lights
CalculateStep();
CheckPoint("Pasting");
gMainWindow->UpdateFocusObject(GetFocusObject());
UpdateSelection();
gMainWindow->UpdateAllViews();
} break;
2011-09-07 23:06:51 +02:00
case LC_EDIT_FIND:
2014-09-21 03:31:01 +02:00
if (gMainWindow->DoDialog(LC_DIALOG_FIND, &gMainWindow->mSearchOptions))
FindPiece(true, true);
break;
2011-09-07 23:06:51 +02:00
case LC_EDIT_FIND_NEXT:
FindPiece(false, true);
break;
2011-09-07 23:06:51 +02:00
case LC_EDIT_FIND_PREVIOUS:
FindPiece(false, false);
break;
2011-09-07 23:06:51 +02:00
case LC_EDIT_SELECT_ALL:
{
for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++)
2011-09-07 23:06:51 +02:00
{
2014-08-07 17:22:33 +02:00
lcPiece* Piece = mPieces[PieceIdx];
2014-07-06 08:04:09 +02:00
if (Piece->IsVisible(mCurrentStep))
Piece->SetSelected(true);
2011-09-07 23:06:51 +02:00
}
UpdateSelection();
gMainWindow->UpdateAllViews();
} break;
case LC_EDIT_SELECT_NONE:
{
2014-08-17 22:44:12 +02:00
ClearSelection(true);
} break;
case LC_EDIT_SELECT_INVERT:
{
for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++)
2011-09-07 23:06:51 +02:00
{
2014-08-07 17:22:33 +02:00
lcPiece* Piece = mPieces[PieceIdx];
2013-01-06 20:24:25 +01:00
2014-07-06 08:04:09 +02:00
if (Piece->IsVisible(mCurrentStep))
Piece->SetSelected(!Piece->IsSelected());
2011-09-07 23:06:51 +02:00
}
gMainWindow->UpdateFocusObject(GetFocusObject());
UpdateSelection();
gMainWindow->UpdateAllViews();
2011-09-07 23:06:51 +02:00
} break;
case LC_EDIT_SELECT_BY_NAME:
2011-09-07 23:06:51 +02:00
{
lcSelectDialogOptions Options;
2013-08-09 06:57:18 +02:00
for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++)
Options.Selection.Add(mPieces[PieceIdx]->IsSelected());
2013-08-09 06:57:18 +02:00
for (int CameraIdx = 0; CameraIdx < mCameras.GetSize(); CameraIdx++)
if (mCameras[CameraIdx]->IsVisible())
Options.Selection.Add(mCameras[CameraIdx]->IsSelected());
2011-09-07 23:06:51 +02:00
for (int LightIdx = 0; LightIdx < mLights.GetSize(); LightIdx++)
if (mLights[LightIdx]->IsVisible())
Options.Selection.Add(mLights[LightIdx]->IsSelected());
2013-08-09 06:57:18 +02:00
if (Options.Selection.GetSize() == 0)
{
gMainWindow->DoMessageBox("Nothing to select.", LC_MB_OK | LC_MB_ICONINFORMATION);
break;
}
2013-08-09 06:57:18 +02:00
if (!gMainWindow->DoDialog(LC_DIALOG_SELECT_BY_NAME, &Options))
break;
2011-09-07 23:06:51 +02:00
2014-08-17 22:44:12 +02:00
ClearSelection(false);
2011-09-07 23:06:51 +02:00
int ObjectIndex = 0;
for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++, ObjectIndex++)
if (Options.Selection[ObjectIndex])
mPieces[PieceIdx]->SetSelected(true);
for (int CameraIdx = 0; CameraIdx < mCameras.GetSize(); CameraIdx++, ObjectIndex++)
if (Options.Selection[ObjectIndex])
mCameras[CameraIdx]->SetSelected(true);
for (int LightIdx = 0; LightIdx < mLights.GetSize(); LightIdx++)
if (Options.Selection[ObjectIndex])
mLights[LightIdx]->SetSelected(true);
UpdateSelection();
gMainWindow->UpdateAllViews();
gMainWindow->UpdateFocusObject(GetFocusObject());
2011-09-07 23:06:51 +02:00
} break;
case LC_VIEW_SPLIT_HORIZONTAL:
gMainWindow->SplitHorizontal();
2013-08-09 06:57:18 +02:00
break;
case LC_VIEW_SPLIT_VERTICAL:
gMainWindow->SplitVertical();
2013-08-09 06:57:18 +02:00
break;
case LC_VIEW_REMOVE_VIEW:
gMainWindow->RemoveView();
2013-08-09 06:57:18 +02:00
break;
case LC_VIEW_RESET_VIEWS:
gMainWindow->ResetViews();
break;
2011-09-07 23:06:51 +02:00
case LC_VIEW_FULLSCREEN:
gMainWindow->ToggleFullScreen();
break;
2011-09-07 23:06:51 +02:00
case LC_VIEW_PROJECTION_PERSPECTIVE:
2011-09-07 23:06:51 +02:00
{
View* ActiveView = gMainWindow->GetActiveView();
lcCamera* Camera = ActiveView->mCamera;
2011-09-07 23:06:51 +02:00
Camera->SetOrtho(false);
2011-09-07 23:06:51 +02:00
if (Camera->IsFocused())
gMainWindow->UpdateFocusObject(Camera);
gMainWindow->UpdateAllViews();
gMainWindow->UpdatePerspective();
}
break;
2013-01-06 20:24:25 +01:00
case LC_VIEW_PROJECTION_ORTHO:
{
View* ActiveView = gMainWindow->GetActiveView();
lcCamera* Camera = ActiveView->mCamera;
2013-01-06 20:24:25 +01:00
Camera->SetOrtho(true);
2013-01-06 20:24:25 +01:00
if (Camera->IsFocused())
gMainWindow->UpdateFocusObject(Camera);
gMainWindow->UpdateAllViews();
gMainWindow->UpdatePerspective();
}
break;
2011-09-07 23:06:51 +02:00
case LC_VIEW_PROJECTION_CYCLE:
{
View* ActiveView = gMainWindow->GetActiveView();
lcCamera* Camera = ActiveView->mCamera;
2011-09-07 23:06:51 +02:00
Camera->SetOrtho(!Camera->IsOrtho());
2011-09-07 23:06:51 +02:00
gMainWindow->UpdateAllViews();
gMainWindow->UpdatePerspective();
}
break;
2011-09-07 23:06:51 +02:00
case LC_VIEW_PROJECTION_FOCUS:
2011-09-07 23:06:51 +02:00
{
lcVector3 FocusVector;
GetSelectionCenter(FocusVector);
2014-07-06 08:04:09 +02:00
gMainWindow->GetActiveView()->mCamera->SetFocalPoint(FocusVector, mCurrentStep, gMainWindow->GetAddKeys());
gMainWindow->UpdateAllViews();
}
break;
2011-09-07 23:06:51 +02:00
case LC_PIECE_INSERT:
{
2014-10-08 01:02:52 +02:00
PieceInfo* CurPiece = gMainWindow->mPreviewWidget->GetCurrentPiece();
if (!CurPiece)
break;
2014-10-08 01:02:52 +02:00
2014-08-07 17:22:33 +02:00
lcPiece* Last = mPieces.IsEmpty() ? NULL : mPieces[mPieces.GetSize() - 1];
2014-10-08 01:02:52 +02:00
lcPiece* pPiece = new lcPiece(CurPiece);
2011-09-07 23:06:51 +02:00
for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++)
{
2014-08-07 17:22:33 +02:00
lcPiece* Piece = mPieces[PieceIdx];
if (Piece->IsFocused())
{
Last = Piece;
break;
}
}
2011-09-07 23:06:51 +02:00
if (Last != NULL)
{
lcVector3 Pos;
lcVector4 Rot;
2011-09-07 23:06:51 +02:00
GetPieceInsertPosition(Last, Pos, Rot);
2011-09-07 23:06:51 +02:00
2014-08-31 02:53:12 +02:00
pPiece->Initialize(Pos, Rot, mCurrentStep);
2014-07-06 08:04:09 +02:00
pPiece->UpdatePosition(mCurrentStep);
2012-08-22 03:13:32 +02:00
}
else
2014-08-31 02:53:12 +02:00
pPiece->Initialize(lcVector3(0, 0, 0), lcVector4(0, 0, 1, 0), mCurrentStep);
2011-09-07 23:06:51 +02:00
pPiece->SetColorIndex(gMainWindow->mColorIndex);
pPiece->CreateName(mPieces);
mPieces.Add(pPiece);
ClearSelectionAndSetFocus(pPiece, LC_PIECE_SECTION_POSITION);
CheckPoint("Inserting");
} break;
case LC_PIECE_DELETE:
{
if (RemoveSelectedObjects())
2011-09-07 23:06:51 +02:00
{
gMainWindow->UpdateFocusObject(NULL);
2011-09-07 23:06:51 +02:00
UpdateSelection();
2014-05-03 23:16:48 +02:00
gMainWindow->UpdateAllViews();
CheckPoint("Deleting");
2011-09-07 23:06:51 +02:00
}
} break;
2013-08-09 06:57:18 +02:00
case LC_PIECE_MOVE_PLUSX:
case LC_PIECE_MOVE_MINUSX:
case LC_PIECE_MOVE_PLUSY:
case LC_PIECE_MOVE_MINUSY:
case LC_PIECE_MOVE_PLUSZ:
case LC_PIECE_MOVE_MINUSZ:
case LC_PIECE_ROTATE_PLUSX:
case LC_PIECE_ROTATE_MINUSX:
case LC_PIECE_ROTATE_PLUSY:
case LC_PIECE_ROTATE_MINUSY:
case LC_PIECE_ROTATE_PLUSZ:
case LC_PIECE_ROTATE_MINUSZ:
2011-09-07 23:06:51 +02:00
{
lcVector3 axis;
bool Rotate = id >= LC_PIECE_ROTATE_PLUSX && id <= LC_PIECE_ROTATE_MINUSZ;
2011-09-07 23:06:51 +02:00
if (Rotate)
2011-09-07 23:06:51 +02:00
{
2014-10-05 07:21:51 +02:00
axis[0] = axis[1] = axis[2] = lcMax(gMainWindow->GetAngleSnap(), 1);
}
else
2011-09-07 23:06:51 +02:00
{
2014-10-05 07:21:51 +02:00
axis[0] = axis[1] = gMainWindow->GetMoveXYSnap();
axis[2] = gMainWindow->GetMoveZSnap();
2011-09-07 23:06:51 +02:00
2014-10-05 07:21:51 +02:00
if (!axis[0])// || bControl)
axis[0] = 0.01f;
2014-10-05 07:21:51 +02:00
if (!axis[1])// || bControl)
axis[1] = 0.01f;
2014-10-05 07:21:51 +02:00
if (!axis[2])// || bControl)
axis[2] = 0.01f;
2011-09-07 23:06:51 +02:00
}
2014-10-08 01:02:52 +02:00
if (id == LC_PIECE_MOVE_PLUSX || id == LC_PIECE_ROTATE_PLUSX)
axis = lcVector3(axis[0], 0, 0);
else if (id == LC_PIECE_MOVE_MINUSX || id == LC_PIECE_ROTATE_MINUSX)
axis = lcVector3(-axis[0], 0, 0);
else if (id == LC_PIECE_MOVE_PLUSY || id == LC_PIECE_ROTATE_PLUSY)
axis = lcVector3(0, axis[1], 0);
else if (id == LC_PIECE_MOVE_MINUSY || id == LC_PIECE_ROTATE_MINUSY)
axis = lcVector3(0, -axis[1], 0);
else if (id == LC_PIECE_MOVE_PLUSZ || id == LC_PIECE_ROTATE_PLUSZ)
axis = lcVector3(0, 0, axis[2]);
else if (id == LC_PIECE_MOVE_MINUSZ || id == LC_PIECE_ROTATE_MINUSZ)
axis = lcVector3(0, 0, -axis[2]);
2011-09-07 23:06:51 +02:00
2014-10-05 07:21:51 +02:00
if (!lcGetPreferences().mFixedAxes)
2011-09-07 23:06:51 +02:00
{
// TODO: rewrite this
lcVector3 Pts[3] = { lcVector3(5.0f, 5.0f, 0.1f), lcVector3(10.0f, 5.0f, 0.1f), lcVector3(5.0f, 10.0f, 0.1f) };
gMainWindow->GetActiveView()->UnprojectPoints(Pts, 3);
float ax, ay;
lcVector3 vx((Pts[1][0] - Pts[0][0]), (Pts[1][1] - Pts[0][1]), 0);//Pts[1][2] - Pts[0][2] };
vx.Normalize();
lcVector3 x(1, 0, 0);
ax = acosf(lcDot(vx, x));
2011-09-07 23:06:51 +02:00
lcVector3 vy((Pts[2][0] - Pts[0][0]), (Pts[2][1] - Pts[0][1]), 0);//Pts[2][2] - Pts[0][2] };
vy.Normalize();
lcVector3 y(0, -1, 0);
ay = acosf(lcDot(vy, y));
2011-09-07 23:06:51 +02:00
if (ax > 135)
axis[0] = -axis[0];
2011-09-07 23:06:51 +02:00
if (ay < 45)
axis[1] = -axis[1];
2011-09-07 23:06:51 +02:00
if (ax >= 45 && ax <= 135)
{
float tmp = axis[0];
ax = acosf(lcDot(vx, y));
if (ax > 90)
{
axis[0] = -axis[1];
axis[1] = tmp;
}
else
{
axis[0] = axis[1];
axis[1] = -tmp;
}
2011-09-07 23:06:51 +02:00
}
}
2013-01-06 20:24:25 +01:00
if (Rotate)
2014-10-05 07:21:51 +02:00
RotateSelectedPieces(axis);
else
2014-10-05 07:21:51 +02:00
MoveSelectedObjects(axis, axis);
2011-09-07 23:06:51 +02:00
gMainWindow->UpdateAllViews();
CheckPoint(Rotate ? "Rotating" : "Moving");
2013-08-09 06:57:18 +02:00
gMainWindow->UpdateFocusObject(GetFocusObject());
2011-09-07 23:06:51 +02:00
} break;
case LC_PIECE_MINIFIG_WIZARD:
{
lcMinifig Minifig;
int i;
2013-08-09 06:57:18 +02:00
if (!gMainWindow->DoDialog(LC_DIALOG_MINIFIG, &Minifig))
break;
2013-08-09 06:57:18 +02:00
2014-08-17 22:44:12 +02:00
ClearSelection(false);
2013-08-09 06:57:18 +02:00
for (i = 0; i < LC_MFW_NUMITEMS; i++)
{
if (Minifig.Parts[i] == NULL)
continue;
2014-08-07 17:22:33 +02:00
lcPiece* pPiece = new lcPiece(Minifig.Parts[i]);
2014-08-31 02:53:12 +02:00
lcVector3 Position(Minifig.Matrices[i][3][0], Minifig.Matrices[i][3][1], Minifig.Matrices[i][3][2]);
lcVector4 Rotation = lcMatrix44ToAxisAngle(Minifig.Matrices[i]);
Rotation[3] *= LC_RTOD;
2014-08-31 02:53:12 +02:00
pPiece->Initialize(Position, Rotation, mCurrentStep);
pPiece->SetColorIndex(Minifig.Colors[i]);
pPiece->CreateName(mPieces);
mPieces.Add(pPiece);
pPiece->SetSelected(true);
2014-07-06 08:04:09 +02:00
pPiece->UpdatePosition(mCurrentStep);
}
2011-09-07 23:06:51 +02:00
2014-05-25 03:45:19 +02:00
int Max = 0;
2013-01-06 20:24:25 +01:00
2014-05-25 03:45:19 +02:00
for (int GroupIdx = 0; GroupIdx < mGroups.GetSize(); GroupIdx++)
{
lcGroup* Group = mGroups[GroupIdx];
if (strncmp(Group->m_strName, "Minifig #", 9) == 0)
if (sscanf(Group->m_strName, "Minifig #%d", &i) == 1)
if (i > Max)
Max = i;
}
2014-05-25 03:45:19 +02:00
lcGroup* Group = AddGroup(NULL);
sprintf(Group->m_strName, "Minifig #%.2d", Max+1);
2013-01-06 20:24:25 +01:00
for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++)
{
2014-08-07 17:22:33 +02:00
lcPiece* Piece = mPieces[PieceIdx];
if (Piece->IsSelected())
2014-05-25 03:45:19 +02:00
Piece->SetGroup(Group);
}
2011-09-07 23:06:51 +02:00
2013-08-09 06:57:18 +02:00
gMainWindow->UpdateFocusObject(GetFocusObject());
2011-09-07 23:06:51 +02:00
UpdateSelection();
2014-05-03 23:16:48 +02:00
gMainWindow->UpdateAllViews();
CheckPoint("Minifig");
2011-09-07 23:06:51 +02:00
} break;
case LC_PIECE_ARRAY:
2011-09-07 23:06:51 +02:00
{
float bs[6] = { 10000, 10000, 10000, -10000, -10000, -10000 };
int sel = 0;
2011-09-07 23:06:51 +02:00
for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++)
{
2014-08-07 17:22:33 +02:00
lcPiece* Piece = mPieces[PieceIdx];
2011-09-07 23:06:51 +02:00
if (Piece->IsSelected())
{
Piece->CompareBoundingBox(bs);
sel++;
}
}
2011-09-07 23:06:51 +02:00
if (!sel)
2011-09-07 23:06:51 +02:00
{
gMainWindow->DoMessageBox("No pieces selected.", LC_MB_OK | LC_MB_ICONINFORMATION);
2011-09-07 23:06:51 +02:00
break;
}
lcArrayDialogOptions Options;
2011-09-07 23:06:51 +02:00
memset(&Options, 0, sizeof(Options));
Options.Counts[0] = 10;
Options.Counts[1] = 1;
Options.Counts[2] = 1;
2011-09-07 23:06:51 +02:00
if (!gMainWindow->DoDialog(LC_DIALOG_PIECE_ARRAY, &Options))
break;
2011-09-07 23:06:51 +02:00
if (Options.Counts[0] * Options.Counts[1] * Options.Counts[2] < 2)
{
gMainWindow->DoMessageBox("Array only has 1 element or less, no pieces added.", LC_MB_OK | LC_MB_ICONINFORMATION);
break;
}
2011-09-07 23:06:51 +02:00
2014-08-17 22:44:12 +02:00
lcArray<lcObjectSection> NewPieces;
2011-09-07 23:06:51 +02:00
for (int Step1 = 0; Step1 < Options.Counts[0]; Step1++)
{
for (int Step2 = 0; Step2 < Options.Counts[1]; Step2++)
{
for (int Step3 = 0; Step3 < Options.Counts[2]; Step3++)
{
if (Step1 == 0 && Step2 == 0 && Step3 == 0)
continue;
2011-09-07 23:06:51 +02:00
lcMatrix44 ModelWorld;
lcVector3 Position;
2011-09-07 23:06:51 +02:00
lcVector3 RotationAngles = Options.Rotations[0] * Step1 + Options.Rotations[1] * Step2 + Options.Rotations[2] * Step3;
lcVector3 Offset = Options.Offsets[0] * Step1 + Options.Offsets[1] * Step2 + Options.Offsets[2] * Step3;
2011-09-07 23:06:51 +02:00
for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++)
{
2014-08-07 17:22:33 +02:00
lcPiece* pPiece = mPieces[PieceIdx];
2011-09-07 23:06:51 +02:00
if (!pPiece->IsSelected())
continue;
2013-12-17 03:43:16 +01:00
if (sel == 1)
{
ModelWorld = lcMul(pPiece->mModelWorld, lcMatrix44RotationX(RotationAngles[0] * LC_DTOR));
ModelWorld = lcMul(ModelWorld, lcMatrix44RotationY(RotationAngles[1] * LC_DTOR));
ModelWorld = lcMul(ModelWorld, lcMatrix44RotationZ(RotationAngles[2] * LC_DTOR));
2013-12-17 03:43:16 +01:00
Position = pPiece->mPosition;
}
else
{
lcVector4 Center((bs[0] + bs[3]) / 2, (bs[1] + bs[4]) / 2, (bs[2] + bs[5]) / 2, 0.0f);
ModelWorld = pPiece->mModelWorld;
2014-05-03 23:16:48 +02:00
ModelWorld.r[3] -= Center;
ModelWorld = lcMul(ModelWorld, lcMatrix44RotationX(RotationAngles[0] * LC_DTOR));
ModelWorld = lcMul(ModelWorld, lcMatrix44RotationY(RotationAngles[1] * LC_DTOR));
ModelWorld = lcMul(ModelWorld, lcMatrix44RotationZ(RotationAngles[2] * LC_DTOR));
ModelWorld.r[3] += Center;
2014-05-03 23:16:48 +02:00
Position = lcVector3(ModelWorld.r[3].x, ModelWorld.r[3].y, ModelWorld.r[3].z);
}
2014-05-03 23:16:48 +02:00
lcVector4 AxisAngle = lcMatrix44ToAxisAngle(ModelWorld);
AxisAngle[3] *= LC_RTOD;
2014-05-03 23:16:48 +02:00
2014-08-07 17:22:33 +02:00
lcPiece* NewPiece = new lcPiece(pPiece->mPieceInfo);
2014-08-31 02:53:12 +02:00
NewPiece->Initialize(Position + Offset, AxisAngle, mCurrentStep);
NewPiece->SetColorIndex(pPiece->mColorIndex);
2014-08-17 22:44:12 +02:00
lcObjectSection ObjectSection;
ObjectSection.Object = NewPiece;
ObjectSection.Section = LC_PIECE_SECTION_POSITION;
NewPieces.Add(ObjectSection);
}
}
}
}
2014-05-03 23:16:48 +02:00
for (int PieceIdx = 0; PieceIdx < NewPieces.GetSize(); PieceIdx++)
{
2014-08-17 22:44:12 +02:00
lcPiece* Piece = (lcPiece*)NewPieces[PieceIdx].Object;
Piece->CreateName(mPieces);
2014-07-06 08:04:09 +02:00
Piece->UpdatePosition(mCurrentStep);
mPieces.Add(Piece);
}
2013-12-17 03:43:16 +01:00
2014-08-17 22:44:12 +02:00
AddToSelection(NewPieces);
CheckPoint("Array");
} break;
2013-12-17 03:43:16 +01:00
case LC_PIECE_GROUP:
2011-09-07 23:06:51 +02:00
{
2014-05-25 03:45:19 +02:00
int i, Max = 0;
char name[65];
int Selected = 0;
2011-09-07 23:06:51 +02:00
for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++)
{
if (mPieces[PieceIdx]->IsSelected())
{
Selected++;
if (Selected > 1)
break;
}
}
2011-09-07 23:06:51 +02:00
if (!Selected)
2011-09-07 23:06:51 +02:00
{
gMainWindow->DoMessageBox("No pieces selected.", LC_MB_OK | LC_MB_ICONINFORMATION);
break;
}
2011-09-07 23:06:51 +02:00
2014-05-25 03:45:19 +02:00
for (int GroupIdx = 0; GroupIdx < mGroups.GetSize(); GroupIdx++)
{
lcGroup* Group = mGroups[GroupIdx];
if (strncmp(Group->m_strName, "Group #", 7) == 0)
if (sscanf(Group->m_strName, "Group #%d", &i) == 1)
if (i > Max)
Max = i;
}
sprintf(name, "Group #%.2d", Max + 1);
2011-09-07 23:06:51 +02:00
if (!gMainWindow->DoDialog(LC_DIALOG_PIECE_GROUP, name))
break;
2011-09-07 23:06:51 +02:00
2014-05-25 20:23:09 +02:00
lcGroup* NewGroup = new lcGroup();
strcpy(NewGroup->m_strName, name);
mGroups.Add(NewGroup);
2011-09-07 23:06:51 +02:00
2014-05-25 03:45:19 +02:00
for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++)
{
2014-08-07 17:22:33 +02:00
lcPiece* Piece = mPieces[PieceIdx];
2011-09-07 23:06:51 +02:00
2014-05-25 03:45:19 +02:00
if (Piece->IsSelected())
2014-05-25 20:23:09 +02:00
{
lcGroup* Group = Piece->GetTopGroup();
if (!Group)
Piece->SetGroup(NewGroup);
else if (Group != NewGroup)
Group->mGroup = NewGroup;
}
2014-05-25 03:45:19 +02:00
}
2014-05-25 03:45:19 +02:00
RemoveEmptyGroups();
CheckPoint("Grouping");
2011-09-07 23:06:51 +02:00
} break;
case LC_PIECE_UNGROUP:
2011-09-07 23:06:51 +02:00
{
2014-05-25 03:45:19 +02:00
lcArray<lcGroup*> Groups;
2013-08-09 06:57:18 +02:00
for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++)
{
2014-05-25 03:45:19 +02:00
lcPiece* Piece = mPieces[PieceIdx];
2013-08-09 06:57:18 +02:00
if (Piece->IsSelected())
{
2014-05-25 03:45:19 +02:00
lcGroup* Group = Piece->GetTopGroup();
2013-08-09 06:57:18 +02:00
2014-05-25 03:45:19 +02:00
if (Groups.FindIndex(Group) == -1)
{
2014-05-25 03:45:19 +02:00
mGroups.Remove(Group);
Groups.Add(Group);
2013-08-09 06:57:18 +02:00
}
}
}
2014-05-25 03:45:19 +02:00
for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++)
{
2014-05-25 03:45:19 +02:00
lcPiece* Piece = mPieces[PieceIdx];
lcGroup* Group = Piece->GetGroup();
2014-05-25 03:45:19 +02:00
if (Groups.FindIndex(Group) != -1)
Piece->SetGroup(NULL);
}
2014-05-25 03:45:19 +02:00
for (int GroupIdx = 0; GroupIdx < mGroups.GetSize(); GroupIdx++)
{
lcGroup* Group = mGroups[GroupIdx];
if (Groups.FindIndex(Group->mGroup) != -1)
Group->mGroup = NULL;
2013-08-09 06:57:18 +02:00
}
2014-05-25 03:45:19 +02:00
Groups.DeleteAll();
RemoveEmptyGroups();
CheckPoint("Ungrouping");
2013-08-09 06:57:18 +02:00
} break;
case LC_PIECE_GROUP_ADD:
2013-08-09 06:57:18 +02:00
{
2014-08-07 17:22:33 +02:00
lcGroup* pGroup = NULL;
2011-09-07 23:06:51 +02:00
for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++)
{
2014-08-07 17:22:33 +02:00
lcPiece* Piece = mPieces[PieceIdx];
2011-09-07 23:06:51 +02:00
if (Piece->IsSelected())
{
pGroup = Piece->GetTopGroup();
if (pGroup != NULL)
break;
}
}
2011-09-07 23:06:51 +02:00
if (pGroup != NULL)
{
for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++)
{
2014-08-07 17:22:33 +02:00
lcPiece* Piece = mPieces[PieceIdx];
2011-09-07 23:06:51 +02:00
if (Piece->IsFocused())
{
Piece->SetGroup(pGroup);
break;
}
}
}
2011-09-07 23:06:51 +02:00
RemoveEmptyGroups();
CheckPoint("Grouping");
} break;
2011-09-07 23:06:51 +02:00
case LC_PIECE_GROUP_REMOVE:
{
for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++)
{
2014-08-07 17:22:33 +02:00
lcPiece* Piece = mPieces[PieceIdx];
if (Piece->IsFocused())
{
2014-05-25 20:23:09 +02:00
Piece->SetGroup(NULL);
break;
}
}
2011-09-07 23:06:51 +02:00
RemoveEmptyGroups();
CheckPoint("Ungrouping");
} break;
case LC_PIECE_GROUP_EDIT:
{
lcEditGroupsDialogOptions Options;
for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++)
Options.PieceParents.Add(mPieces[PieceIdx]->GetGroup());
2014-05-25 03:45:19 +02:00
for (int GroupIdx = 0; GroupIdx < mGroups.GetSize(); GroupIdx++)
Options.GroupParents.Add(mGroups[GroupIdx]->mGroup);
2011-09-07 23:06:51 +02:00
if (!gMainWindow->DoDialog(LC_DIALOG_EDIT_GROUPS, &Options))
break;
for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++)
mPieces[PieceIdx]->SetGroup(Options.PieceParents[PieceIdx]);
2014-05-25 03:45:19 +02:00
for (int GroupIdx = 0; GroupIdx < mGroups.GetSize(); GroupIdx++)
mGroups[GroupIdx]->mGroup = Options.GroupParents[GroupIdx];
RemoveEmptyGroups();
2014-08-17 22:44:12 +02:00
ClearSelection(true);
CheckPoint("Editing");
2011-09-07 23:06:51 +02:00
} break;
case LC_PIECE_HIDE_SELECTED:
2011-09-07 23:06:51 +02:00
{
for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++)
2011-09-07 23:06:51 +02:00
{
2014-08-07 17:22:33 +02:00
lcPiece* Piece = mPieces[PieceIdx];
if (Piece->IsSelected())
2014-01-30 04:13:34 +01:00
{
Piece->SetHidden(true);
Piece->SetSelected(false);
2013-08-09 06:57:18 +02:00
}
}
2011-09-07 23:06:51 +02:00
UpdateSelection();
gMainWindow->UpdateFocusObject(NULL);
gMainWindow->UpdateAllViews();
} break;
case LC_PIECE_HIDE_UNSELECTED:
{
for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++)
2014-01-30 04:13:34 +01:00
{
2014-08-07 17:22:33 +02:00
lcPiece* Piece = mPieces[PieceIdx];
2011-09-07 23:06:51 +02:00
if (!Piece->IsSelected())
Piece->SetHidden(true);
}
2013-08-09 06:57:18 +02:00
UpdateSelection();
gMainWindow->UpdateAllViews();
} break;
2013-08-09 06:57:18 +02:00
case LC_PIECE_UNHIDE_ALL:
{
for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++)
mPieces[PieceIdx]->SetHidden(false);
2014-01-30 04:13:34 +01:00
UpdateSelection();
2014-05-03 23:16:48 +02:00
gMainWindow->UpdateAllViews();
2011-09-07 23:06:51 +02:00
} break;
case LC_PIECE_SHOW_EARLIER:
2011-09-07 23:06:51 +02:00
{
2014-07-06 08:04:09 +02:00
bool Redraw = false;
2013-08-09 06:57:18 +02:00
for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++)
2013-08-09 06:57:18 +02:00
{
2014-08-07 17:22:33 +02:00
lcPiece* Piece = mPieces[PieceIdx];
2011-09-07 23:06:51 +02:00
if (Piece->IsSelected())
{
2014-07-06 08:04:09 +02:00
lcStep Step = Piece->GetStepShow();
if (Step > 1)
2011-09-07 23:06:51 +02:00
{
2014-07-06 08:04:09 +02:00
Redraw = true;
Piece->SetStepShow(Step - 1);
2011-09-07 23:06:51 +02:00
}
}
}
2013-01-06 20:24:25 +01:00
2014-07-06 08:04:09 +02:00
if (Redraw)
{
CheckPoint("Modifying");
gMainWindow->UpdateAllViews();
2014-07-06 08:04:09 +02:00
UpdateSelection();
}
2011-09-07 23:06:51 +02:00
} break;
case LC_PIECE_SHOW_LATER:
2011-09-07 23:06:51 +02:00
{
2014-07-06 08:04:09 +02:00
bool Redraw = false;
2011-09-07 23:06:51 +02:00
for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++)
{
2014-08-07 17:22:33 +02:00
lcPiece* Piece = mPieces[PieceIdx];
if (Piece->IsSelected())
2011-09-07 23:06:51 +02:00
{
2014-07-06 08:04:09 +02:00
lcStep Step = Piece->GetStepShow();
if (Step < LC_STEP_MAX)
2011-09-07 23:06:51 +02:00
{
2014-07-06 08:04:09 +02:00
Step++;
Redraw = true;
Piece->SetStepShow(Step);
2011-09-07 23:06:51 +02:00
2014-07-06 08:04:09 +02:00
if (Step > mCurrentStep)
Piece->SetSelected(false);
2011-09-07 23:06:51 +02:00
}
}
}
2011-09-07 23:06:51 +02:00
2014-07-06 08:04:09 +02:00
if (Redraw)
2011-09-07 23:06:51 +02:00
{
CheckPoint("Modifying");
gMainWindow->UpdateAllViews();
2014-07-06 08:04:09 +02:00
UpdateSelection();
}
} break;
case LC_VIEW_PREFERENCES:
g_App->ShowPreferencesDialog();
break;
2011-09-07 23:06:51 +02:00
case LC_VIEW_ZOOM_IN:
{
ZoomActiveView(-1);
2011-09-07 23:06:51 +02:00
} break;
case LC_VIEW_ZOOM_OUT:
2011-09-07 23:06:51 +02:00
{
ZoomActiveView(1);
} break;
2011-09-07 23:06:51 +02:00
case LC_VIEW_ZOOM_EXTENTS:
{
int FirstView, LastView;
// TODO: Find a way to let users zoom extents all views
// if (Sys_KeyDown(KEY_CONTROL))
// {
// FirstView = 0;
// LastView = m_ViewList.GetSize();
// }
// else
{
FirstView = gMainWindow->GetViews().FindIndex(gMainWindow->GetActiveView());
LastView = FirstView + 1;
}
2011-09-07 23:06:51 +02:00
ZoomExtents(FirstView, LastView);
} break;
case LC_VIEW_LOOK_AT:
{
lcVector3 Center;
if (!GetSelectionCenter(Center))
2011-09-07 23:06:51 +02:00
{
float BoundingBox[6];
2013-12-17 23:23:41 +01:00
if (GetPiecesBoundingBox(BoundingBox))
Center = lcVector3((BoundingBox[0] + BoundingBox[3]) / 2, (BoundingBox[1] + BoundingBox[4]) / 2, (BoundingBox[2] + BoundingBox[5]) / 2);
else
Center = lcVector3(0.0f, 0.0f, 0.0f);
2013-12-17 23:23:41 +01:00
}
2014-07-06 08:04:09 +02:00
gMainWindow->GetActiveView()->mCamera->Center(Center, mCurrentStep, gMainWindow->GetAddKeys());
2014-05-03 23:16:48 +02:00
gMainWindow->UpdateAllViews();
2013-12-17 23:23:41 +01:00
break;
}
2013-08-09 06:57:18 +02:00
case LC_VIEW_TIME_NEXT:
2011-09-07 23:06:51 +02:00
{
2014-07-06 08:04:09 +02:00
if (mCurrentStep == LC_STEP_MAX)
break;
mCurrentStep++;
2011-09-07 23:06:51 +02:00
CalculateStep();
UpdateSelection();
2013-08-09 06:57:18 +02:00
gMainWindow->UpdateFocusObject(GetFocusObject());
2014-05-03 23:16:48 +02:00
gMainWindow->UpdateAllViews();
2014-07-06 08:04:09 +02:00
gMainWindow->UpdateCurrentStep();
2011-09-07 23:06:51 +02:00
} break;
2013-01-06 20:24:25 +01:00
2013-08-09 06:57:18 +02:00
case LC_VIEW_TIME_PREVIOUS:
2011-09-07 23:06:51 +02:00
{
2014-07-06 08:04:09 +02:00
if (mCurrentStep == 1)
break;
mCurrentStep--;
2011-09-07 23:06:51 +02:00
CalculateStep();
UpdateSelection();
2013-08-09 06:57:18 +02:00
gMainWindow->UpdateFocusObject(GetFocusObject());
2014-05-03 23:16:48 +02:00
gMainWindow->UpdateAllViews();
2014-07-06 08:04:09 +02:00
gMainWindow->UpdateCurrentStep();
2011-09-07 23:06:51 +02:00
} break;
2013-01-06 20:24:25 +01:00
2013-08-09 06:57:18 +02:00
case LC_VIEW_TIME_FIRST:
2011-09-07 23:06:51 +02:00
{
2014-07-06 08:04:09 +02:00
mCurrentStep = 1;
2011-09-07 23:06:51 +02:00
CalculateStep();
UpdateSelection();
2013-08-09 06:57:18 +02:00
gMainWindow->UpdateFocusObject(GetFocusObject());
2014-05-03 23:16:48 +02:00
gMainWindow->UpdateAllViews();
2014-07-06 08:04:09 +02:00
gMainWindow->UpdateCurrentStep();
2011-09-07 23:06:51 +02:00
} break;
2013-08-09 06:57:18 +02:00
case LC_VIEW_TIME_LAST:
2011-09-07 23:06:51 +02:00
{
2014-07-06 08:04:09 +02:00
mCurrentStep = GetLastStep();
2011-09-07 23:06:51 +02:00
CalculateStep();
UpdateSelection();
2013-08-09 06:57:18 +02:00
gMainWindow->UpdateFocusObject(GetFocusObject());
2014-05-03 23:16:48 +02:00
gMainWindow->UpdateAllViews();
2014-07-06 08:04:09 +02:00
gMainWindow->UpdateCurrentStep();
2011-09-07 23:06:51 +02:00
} break;
2013-08-09 06:57:18 +02:00
case LC_VIEW_TIME_INSERT:
2012-08-22 03:13:32 +02:00
{
for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++)
{
2014-08-07 17:22:33 +02:00
lcPiece* Piece = mPieces[PieceIdx];
2014-07-06 08:04:09 +02:00
Piece->InsertTime(mCurrentStep, 1);
if (Piece->IsSelected() && !Piece->IsVisible(mCurrentStep))
Piece->SetSelected(false);
}
2011-09-07 23:06:51 +02:00
2012-08-22 03:13:32 +02:00
for (int CameraIdx = 0; CameraIdx < mCameras.GetSize(); CameraIdx++)
2014-07-06 08:04:09 +02:00
mCameras[CameraIdx]->InsertTime(mCurrentStep, 1);
2011-09-07 23:06:51 +02:00
for (int LightIdx = 0; LightIdx < mLights.GetSize(); LightIdx++)
2014-07-06 08:04:09 +02:00
mLights[LightIdx]->InsertTime(mCurrentStep, 1);
2011-09-07 23:06:51 +02:00
2014-01-30 04:13:34 +01:00
CheckPoint("Adding Step");
2012-08-22 03:13:32 +02:00
CalculateStep();
gMainWindow->UpdateFocusObject(GetFocusObject());
2014-05-03 23:16:48 +02:00
gMainWindow->UpdateAllViews();
2012-08-22 03:13:32 +02:00
UpdateSelection();
} break;
2011-09-07 23:06:51 +02:00
2013-08-09 06:57:18 +02:00
case LC_VIEW_TIME_DELETE:
2012-08-22 03:13:32 +02:00
{
for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++)
{
2014-08-07 17:22:33 +02:00
lcPiece* Piece = mPieces[PieceIdx];
2014-07-06 08:04:09 +02:00
Piece->RemoveTime(mCurrentStep, 1);
if (Piece->IsSelected() && !Piece->IsVisible(mCurrentStep))
Piece->SetSelected(false);
}
2011-09-07 23:06:51 +02:00
2012-08-22 03:13:32 +02:00
for (int CameraIdx = 0; CameraIdx < mCameras.GetSize(); CameraIdx++)
2014-07-06 08:04:09 +02:00
mCameras[CameraIdx]->RemoveTime(mCurrentStep, 1);
2011-09-07 23:06:51 +02:00
for (int LightIdx = 0; LightIdx < mLights.GetSize(); LightIdx++)
2014-07-06 08:04:09 +02:00
mLights[LightIdx]->RemoveTime(mCurrentStep, 1);
2011-09-07 23:06:51 +02:00
2014-01-30 04:13:34 +01:00
CheckPoint("Removing Step");
2012-08-22 03:13:32 +02:00
CalculateStep();
gMainWindow->UpdateFocusObject(GetFocusObject());
2014-05-03 23:16:48 +02:00
gMainWindow->UpdateAllViews();
2012-08-22 03:13:32 +02:00
UpdateSelection();
} break;
2011-09-07 23:06:51 +02:00
2012-08-20 06:05:56 +02:00
case LC_VIEW_VIEWPOINT_FRONT:
2011-09-07 23:06:51 +02:00
{
2014-07-06 08:04:09 +02:00
gMainWindow->GetActiveView()->mCamera->SetViewpoint(LC_VIEWPOINT_FRONT, mCurrentStep, gMainWindow->GetAddKeys());
2013-08-09 06:57:18 +02:00
HandleCommand(LC_VIEW_ZOOM_EXTENTS);
gMainWindow->UpdateAllViews();
2011-09-07 23:06:51 +02:00
} break;
2012-08-20 06:05:56 +02:00
case LC_VIEW_VIEWPOINT_BACK:
2011-09-07 23:06:51 +02:00
{
2014-07-06 08:04:09 +02:00
gMainWindow->GetActiveView()->mCamera->SetViewpoint(LC_VIEWPOINT_BACK, mCurrentStep, gMainWindow->GetAddKeys());
2013-08-09 06:57:18 +02:00
HandleCommand(LC_VIEW_ZOOM_EXTENTS);
gMainWindow->UpdateAllViews();
2011-09-07 23:06:51 +02:00
} break;
2012-08-20 06:05:56 +02:00
case LC_VIEW_VIEWPOINT_TOP:
2011-09-07 23:06:51 +02:00
{
2014-07-06 08:04:09 +02:00
gMainWindow->GetActiveView()->mCamera->SetViewpoint(LC_VIEWPOINT_TOP, mCurrentStep, gMainWindow->GetAddKeys());
2013-08-09 06:57:18 +02:00
HandleCommand(LC_VIEW_ZOOM_EXTENTS);
gMainWindow->UpdateAllViews();
2011-09-07 23:06:51 +02:00
} break;
2012-08-20 06:05:56 +02:00
case LC_VIEW_VIEWPOINT_BOTTOM:
2011-09-07 23:06:51 +02:00
{
2014-07-06 08:04:09 +02:00
gMainWindow->GetActiveView()->mCamera->SetViewpoint(LC_VIEWPOINT_BOTTOM, mCurrentStep, gMainWindow->GetAddKeys());
2013-08-09 06:57:18 +02:00
HandleCommand(LC_VIEW_ZOOM_EXTENTS);
gMainWindow->UpdateAllViews();
2011-09-07 23:06:51 +02:00
} break;
2012-08-20 06:05:56 +02:00
case LC_VIEW_VIEWPOINT_LEFT:
2011-09-07 23:06:51 +02:00
{
2014-07-06 08:04:09 +02:00
gMainWindow->GetActiveView()->mCamera->SetViewpoint(LC_VIEWPOINT_LEFT, mCurrentStep, gMainWindow->GetAddKeys());
2013-08-09 06:57:18 +02:00
HandleCommand(LC_VIEW_ZOOM_EXTENTS);
gMainWindow->UpdateAllViews();
2011-09-07 23:06:51 +02:00
} break;
2012-08-20 06:05:56 +02:00
case LC_VIEW_VIEWPOINT_RIGHT:
2011-09-07 23:06:51 +02:00
{
2014-07-06 08:04:09 +02:00
gMainWindow->GetActiveView()->mCamera->SetViewpoint(LC_VIEWPOINT_RIGHT, mCurrentStep, gMainWindow->GetAddKeys());
2013-08-09 06:57:18 +02:00
HandleCommand(LC_VIEW_ZOOM_EXTENTS);
gMainWindow->UpdateAllViews();
2011-09-07 23:06:51 +02:00
} break;
2012-08-20 06:05:56 +02:00
case LC_VIEW_VIEWPOINT_HOME:
2011-09-07 23:06:51 +02:00
{
2014-07-06 08:04:09 +02:00
gMainWindow->GetActiveView()->mCamera->SetViewpoint(LC_VIEWPOINT_HOME, mCurrentStep, gMainWindow->GetAddKeys());
2013-08-09 06:57:18 +02:00
HandleCommand(LC_VIEW_ZOOM_EXTENTS);
gMainWindow->UpdateAllViews();
2011-09-07 23:06:51 +02:00
} break;
2013-08-09 06:57:18 +02:00
case LC_VIEW_CAMERA_NONE:
case LC_VIEW_CAMERA1:
case LC_VIEW_CAMERA2:
case LC_VIEW_CAMERA3:
case LC_VIEW_CAMERA4:
case LC_VIEW_CAMERA5:
case LC_VIEW_CAMERA6:
case LC_VIEW_CAMERA7:
case LC_VIEW_CAMERA8:
case LC_VIEW_CAMERA9:
case LC_VIEW_CAMERA10:
case LC_VIEW_CAMERA11:
case LC_VIEW_CAMERA12:
case LC_VIEW_CAMERA13:
case LC_VIEW_CAMERA14:
case LC_VIEW_CAMERA15:
case LC_VIEW_CAMERA16:
2011-09-07 23:06:51 +02:00
{
2014-05-03 23:16:48 +02:00
View* ActiveView = gMainWindow->GetActiveView();
lcCamera* Camera = NULL;
2012-11-15 02:14:35 +01:00
2013-08-09 06:57:18 +02:00
if (id == LC_VIEW_CAMERA_NONE)
2012-11-15 02:14:35 +01:00
{
2014-05-03 23:16:48 +02:00
Camera = ActiveView->mCamera;
2012-11-15 02:14:35 +01:00
2014-05-03 23:16:48 +02:00
if (!Camera->IsSimple())
2012-11-15 02:14:35 +01:00
{
2014-05-03 23:16:48 +02:00
ActiveView->SetCamera(Camera, true);
Camera = ActiveView->mCamera;
2012-11-15 02:14:35 +01:00
}
}
else
{
2013-08-09 06:57:18 +02:00
if (id - LC_VIEW_CAMERA1 < mCameras.GetSize())
{
2014-05-03 23:16:48 +02:00
Camera = mCameras[id - LC_VIEW_CAMERA1];
ActiveView->SetCamera(Camera, false);
2013-08-09 06:57:18 +02:00
}
else
break;
2012-11-15 02:14:35 +01:00
}
2011-09-07 23:06:51 +02:00
2014-05-03 23:16:48 +02:00
gMainWindow->UpdateCurrentCamera(mCameras.FindIndex(ActiveView->mCamera));
gMainWindow->UpdateAllViews();
2011-09-07 23:06:51 +02:00
} break;
case LC_VIEW_CAMERA_RESET:
{
2014-05-03 23:16:48 +02:00
const lcArray<View*> Views = gMainWindow->GetViews();
for (int ViewIdx = 0; ViewIdx < Views.GetSize(); ViewIdx++)
Views[ViewIdx]->SetDefaultCamera();
2012-02-05 03:50:57 +01:00
2012-08-22 03:13:32 +02:00
for (int CameraIdx = 0; CameraIdx < mCameras.GetSize(); CameraIdx++)
delete mCameras[CameraIdx];
mCameras.RemoveAll();
2014-05-03 23:16:48 +02:00
gMainWindow->UpdateCameraMenu();
2013-08-09 06:57:18 +02:00
gMainWindow->UpdateFocusObject(GetFocusObject());
2014-05-03 23:16:48 +02:00
gMainWindow->UpdateAllViews();
2011-09-07 23:06:51 +02:00
} break;
2013-08-09 06:57:18 +02:00
case LC_HELP_HOMEPAGE:
g_App->OpenURL("http://www.leocad.org/");
break;
case LC_HELP_EMAIL:
g_App->OpenURL("mailto:leozide@gmail.com?subject=LeoCAD");
break;
case LC_HELP_UPDATES:
gMainWindow->DoDialog(LC_DIALOG_CHECK_UPDATES, NULL);
break;
2011-09-07 23:06:51 +02:00
case LC_HELP_ABOUT:
{
2013-08-09 06:57:18 +02:00
String Info;
char Text[256];
2014-05-03 23:16:48 +02:00
gMainWindow->GetActiveView()->MakeCurrent();
2013-08-09 06:57:18 +02:00
GLint Red, Green, Blue, Alpha, Depth, Stencil;
GLboolean DoubleBuffer, RGBA;
glGetIntegerv(GL_RED_BITS, &Red);
glGetIntegerv(GL_GREEN_BITS, &Green);
glGetIntegerv(GL_BLUE_BITS, &Blue);
glGetIntegerv(GL_ALPHA_BITS, &Alpha);
glGetIntegerv(GL_DEPTH_BITS, &Depth);
glGetIntegerv(GL_STENCIL_BITS, &Stencil);
glGetBooleanv(GL_DOUBLEBUFFER, &DoubleBuffer);
glGetBooleanv(GL_RGBA_MODE, &RGBA);
Info = "OpenGL Version ";
Info += (const char*)glGetString(GL_VERSION);
Info += "\n";
Info += (const char*)glGetString(GL_RENDERER);
Info += " - ";
Info += (const char*)glGetString(GL_VENDOR);
sprintf(Text, "\n\nColor Buffer: %d bits %s %s", Red + Green + Blue + Alpha, RGBA ? "RGBA" : "indexed", DoubleBuffer ? "double buffered" : "");
Info += Text;
sprintf(Text, "\nDepth Buffer: %d bits", Depth);
Info += Text;
sprintf(Text, "\nStencil Buffer: %d bits", Stencil);
Info += Text;
Info += "\nGL_ARB_vertex_buffer_object extension: ";
Info += GL_HasVertexBufferObject() ? "supported" : "not supported";
Info += "\nGL_ARB_framebuffer_object extension: ";
Info += GL_HasFramebufferObjectARB() ? "supported" : "not supported";
Info += "\nGL_EXT_framebuffer_object extension: ";
Info += GL_HasFramebufferObjectEXT() ? "supported" : "not supported";
Info += "\nGL_EXT_texture_filter_anisotropic extension: ";
if (GL_SupportsAnisotropic)
{
sprintf(Text, "supported (max %d)", (int)GL_MaxAnisotropy);
Info += Text;
}
else
Info += "not supported";
2013-08-09 06:57:18 +02:00
gMainWindow->DoDialog(LC_DIALOG_ABOUT, (char*)Info);
2011-09-07 23:06:51 +02:00
} break;
2013-08-09 06:57:18 +02:00
case LC_VIEW_TIME_ADD_KEYS:
2014-05-21 00:15:42 +02:00
gMainWindow->SetAddKeys(!gMainWindow->GetAddKeys());
break;
2011-09-07 23:06:51 +02:00
2014-10-05 07:21:51 +02:00
case LC_EDIT_SNAP_RELATIVE:
{
lcPreferences& Preferences = lcGetPreferences();
Preferences.SetForceGlobalTransforms(!Preferences.mForceGlobalTransforms);
} break;
2013-08-09 06:57:18 +02:00
2014-10-05 07:21:51 +02:00
case LC_EDIT_LOCK_X:
gMainWindow->SetLockX(!gMainWindow->GetLockX());
break;
2013-08-09 06:57:18 +02:00
2014-10-05 07:21:51 +02:00
case LC_EDIT_LOCK_Y:
gMainWindow->SetLockY(!gMainWindow->GetLockY());
break;
2013-08-09 06:57:18 +02:00
2014-10-05 07:21:51 +02:00
case LC_EDIT_LOCK_Z:
gMainWindow->SetLockZ(!gMainWindow->GetLockZ());
break;
2011-09-07 23:06:51 +02:00
2014-10-05 07:21:51 +02:00
case LC_EDIT_LOCK_NONE:
gMainWindow->SetLockX(false);
gMainWindow->SetLockY(false);
gMainWindow->SetLockZ(false);
break;
2011-09-07 23:06:51 +02:00
2014-10-05 07:21:51 +02:00
case LC_EDIT_SNAP_MOVE_XY0:
case LC_EDIT_SNAP_MOVE_XY1:
case LC_EDIT_SNAP_MOVE_XY2:
case LC_EDIT_SNAP_MOVE_XY3:
case LC_EDIT_SNAP_MOVE_XY4:
case LC_EDIT_SNAP_MOVE_XY5:
case LC_EDIT_SNAP_MOVE_XY6:
case LC_EDIT_SNAP_MOVE_XY7:
case LC_EDIT_SNAP_MOVE_XY8:
case LC_EDIT_SNAP_MOVE_XY9:
gMainWindow->SetMoveXYSnapIndex(id - LC_EDIT_SNAP_MOVE_XY0);
break;
2011-09-07 23:06:51 +02:00
2014-10-05 07:21:51 +02:00
case LC_EDIT_SNAP_MOVE_Z0:
case LC_EDIT_SNAP_MOVE_Z1:
case LC_EDIT_SNAP_MOVE_Z2:
case LC_EDIT_SNAP_MOVE_Z3:
case LC_EDIT_SNAP_MOVE_Z4:
case LC_EDIT_SNAP_MOVE_Z5:
case LC_EDIT_SNAP_MOVE_Z6:
case LC_EDIT_SNAP_MOVE_Z7:
case LC_EDIT_SNAP_MOVE_Z8:
case LC_EDIT_SNAP_MOVE_Z9:
gMainWindow->SetMoveZSnapIndex(id - LC_EDIT_SNAP_MOVE_Z0);
break;
2013-08-09 06:57:18 +02:00
2014-10-05 07:21:51 +02:00
case LC_EDIT_SNAP_ANGLE0:
case LC_EDIT_SNAP_ANGLE1:
case LC_EDIT_SNAP_ANGLE2:
case LC_EDIT_SNAP_ANGLE3:
case LC_EDIT_SNAP_ANGLE4:
case LC_EDIT_SNAP_ANGLE5:
case LC_EDIT_SNAP_ANGLE6:
case LC_EDIT_SNAP_ANGLE7:
case LC_EDIT_SNAP_ANGLE8:
case LC_EDIT_SNAP_ANGLE9:
gMainWindow->SetAngleSnapIndex(id - LC_EDIT_SNAP_ANGLE0);
break;
2011-09-07 23:06:51 +02:00
2013-08-09 06:57:18 +02:00
case LC_EDIT_TRANSFORM:
2014-08-27 18:17:09 +02:00
TransformSelectedObjects(gMainWindow->GetTransformType(), gMainWindow->GetTransformAmount());
2013-08-09 06:57:18 +02:00
break;
case LC_EDIT_TRANSFORM_ABSOLUTE_TRANSLATION:
case LC_EDIT_TRANSFORM_RELATIVE_TRANSLATION:
case LC_EDIT_TRANSFORM_ABSOLUTE_ROTATION:
case LC_EDIT_TRANSFORM_RELATIVE_ROTATION:
2014-08-27 18:17:09 +02:00
gMainWindow->SetTransformType((lcTransformType)(id - LC_EDIT_TRANSFORM_ABSOLUTE_TRANSLATION));
2013-08-09 06:57:18 +02:00
break;
2011-09-07 23:06:51 +02:00
case LC_EDIT_ACTION_SELECT:
2014-05-23 02:02:21 +02:00
gMainWindow->SetTool(LC_TOOL_SELECT);
break;
2011-09-07 23:06:51 +02:00
case LC_EDIT_ACTION_INSERT:
2014-05-23 02:02:21 +02:00
gMainWindow->SetTool(LC_TOOL_INSERT);
break;
2011-09-07 23:06:51 +02:00
case LC_EDIT_ACTION_LIGHT:
2014-05-23 02:02:21 +02:00
gMainWindow->SetTool(LC_TOOL_LIGHT);
break;
2011-09-07 23:06:51 +02:00
case LC_EDIT_ACTION_SPOTLIGHT:
2014-05-23 02:02:21 +02:00
gMainWindow->SetTool(LC_TOOL_SPOTLIGHT);
break;
2011-09-07 23:06:51 +02:00
case LC_EDIT_ACTION_CAMERA:
2014-05-23 02:02:21 +02:00
gMainWindow->SetTool(LC_TOOL_CAMERA);
break;
2011-09-07 23:06:51 +02:00
case LC_EDIT_ACTION_MOVE:
2014-05-23 02:02:21 +02:00
gMainWindow->SetTool(LC_TOOL_MOVE);
break;
2011-09-07 23:06:51 +02:00
case LC_EDIT_ACTION_ROTATE:
2014-05-23 02:02:21 +02:00
gMainWindow->SetTool(LC_TOOL_ROTATE);
break;
2011-09-07 23:06:51 +02:00
case LC_EDIT_ACTION_DELETE:
2014-05-23 02:02:21 +02:00
gMainWindow->SetTool(LC_TOOL_ERASER);
break;
2011-09-07 23:06:51 +02:00
case LC_EDIT_ACTION_PAINT:
2014-05-23 02:02:21 +02:00
gMainWindow->SetTool(LC_TOOL_PAINT);
break;
case LC_EDIT_ACTION_ZOOM:
2014-05-23 02:02:21 +02:00
gMainWindow->SetTool(LC_TOOL_ZOOM);
break;
2011-09-07 23:06:51 +02:00
case LC_EDIT_ACTION_ZOOM_REGION:
2014-05-23 02:02:21 +02:00
gMainWindow->SetTool(LC_TOOL_ZOOM_REGION);
break;
2011-09-07 23:06:51 +02:00
case LC_EDIT_ACTION_PAN:
2014-05-23 02:02:21 +02:00
gMainWindow->SetTool(LC_TOOL_PAN);
break;
2011-09-07 23:06:51 +02:00
case LC_EDIT_ACTION_ROTATE_VIEW:
2014-05-23 02:02:21 +02:00
gMainWindow->SetTool(LC_TOOL_ROTATE_VIEW);
break;
2011-09-07 23:06:51 +02:00
case LC_EDIT_ACTION_ROLL:
2014-05-23 02:02:21 +02:00
gMainWindow->SetTool(LC_TOOL_ROLL);
break;
2011-09-07 23:06:51 +02:00
case LC_EDIT_CANCEL:
{
2014-05-27 00:58:08 +02:00
View* ActiveView = gMainWindow->GetActiveView();
if (ActiveView && ActiveView->mTrackButton != LC_TRACKBUTTON_NONE)
ActiveView->StopTracking(false);
2011-09-07 23:06:51 +02:00
else
2014-08-17 22:44:12 +02:00
ClearSelection(true);
} break;
2011-09-07 23:06:51 +02:00
case LC_NUM_COMMANDS:
break;
}
}
2011-09-07 23:06:51 +02:00
2014-05-25 03:45:19 +02:00
lcGroup* Project::AddGroup(lcGroup* Parent)
{
2014-05-25 03:45:19 +02:00
lcGroup* NewGroup = new lcGroup();
2014-05-25 03:45:19 +02:00
int i, Max = 0;
2014-05-25 03:45:19 +02:00
for (int GroupIdx = 0; GroupIdx < mGroups.GetSize(); GroupIdx++)
{
lcGroup* Group = mGroups[GroupIdx];
2014-05-25 03:45:19 +02:00
if (strncmp(Group->m_strName, "Group #", 7) == 0)
if (sscanf(Group->m_strName, "Group #%d", &i) == 1)
if (i > Max)
Max = i;
}
2014-05-25 03:45:19 +02:00
sprintf(NewGroup->m_strName, "Group #%.2d", Max + 1);
mGroups.Add(NewGroup);
2014-05-25 03:45:19 +02:00
NewGroup->mGroup = Parent;
2014-05-25 03:45:19 +02:00
return NewGroup;
}
2012-08-22 03:13:32 +02:00
// Find a good starting position/orientation relative to an existing piece.
2014-08-07 17:22:33 +02:00
void Project::GetPieceInsertPosition(lcPiece* OffsetPiece, lcVector3& Position, lcVector4& Rotation)
{
2014-10-08 01:02:52 +02:00
PieceInfo* CurPiece = gMainWindow->mPreviewWidget->GetCurrentPiece();
lcVector3 Dist(0, 0, OffsetPiece->mPieceInfo->m_fDimensions[2] - CurPiece->m_fDimensions[5]);
2014-10-05 07:42:38 +02:00
Dist = SnapPosition(Dist);
2013-08-09 06:57:18 +02:00
Position = lcMul31(Dist, OffsetPiece->mModelWorld);
Rotation = OffsetPiece->mRotation;
}
2011-09-07 23:06:51 +02:00
// Try to find a good starting position/orientation for a new piece.
void Project::GetPieceInsertPosition(View* view, lcVector3& Position, lcVector4& Rotation)
{
// Check if the mouse is over a piece.
2014-08-07 17:22:33 +02:00
lcPiece* HitPiece = (lcPiece*)view->FindObjectUnderPointer(true).Object;
2011-09-07 23:06:51 +02:00
if (HitPiece)
{
GetPieceInsertPosition(HitPiece, Position, Rotation);
return;
}
2011-09-07 23:06:51 +02:00
// Try to hit the base grid.
lcVector3 ClickPoints[2] = { lcVector3((float)view->mInputState.x, (float)view->mInputState.y, 0.0f), lcVector3((float)view->mInputState.x, (float)view->mInputState.y, 1.0f) };
view->UnprojectPoints(ClickPoints, 2);
2013-08-09 06:57:18 +02:00
2014-10-08 01:02:52 +02:00
PieceInfo* CurPiece = gMainWindow->mPreviewWidget->GetCurrentPiece();
lcVector3 Intersection;
2014-10-08 01:02:52 +02:00
if (lcLinePlaneIntersection(&Intersection, ClickPoints[0], ClickPoints[1], lcVector4(0, 0, 1, CurPiece->m_fDimensions[5])))
{
2014-10-05 07:42:38 +02:00
Intersection = SnapPosition(Intersection);
Position = Intersection;
Rotation = lcVector4(0, 0, 1, 0);
return;
}
2013-08-09 06:57:18 +02:00
// Couldn't find a good position, so just place the piece somewhere near the camera.
2014-10-08 01:02:52 +02:00
Position = view->UnprojectPoint(lcVector3((float)view->mInputState.x, (float)view->mInputState.y, 0.9f));
Rotation = lcVector4(0, 0, 1, 0);
}
2011-09-07 23:06:51 +02:00
2014-08-27 18:17:09 +02:00
void Project::TransformSelectedObjects(lcTransformType Type, const lcVector3& Transform)
{
switch (Type)
2011-09-07 23:06:51 +02:00
{
case LC_TRANSFORM_ABSOLUTE_TRANSLATION:
2011-09-07 23:06:51 +02:00
{
float bs[6] = { 10000, 10000, 10000, -10000, -10000, -10000 };
lcVector3 Center;
int nSel = 0;
2014-08-07 17:22:33 +02:00
lcPiece* pFocus = NULL;
2011-09-07 23:06:51 +02:00
for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++)
2013-04-10 02:56:51 +02:00
{
2014-08-07 17:22:33 +02:00
lcPiece* Piece = mPieces[PieceIdx];
2011-09-07 23:06:51 +02:00
if (Piece->IsSelected())
{
if (Piece->IsFocused())
pFocus = Piece;
2011-09-07 23:06:51 +02:00
Piece->CompareBoundingBox(bs);
nSel++;
}
2011-09-07 23:06:51 +02:00
}
if (pFocus != NULL)
Center = pFocus->mPosition;
else
Center = lcVector3((bs[0]+bs[3])/2, (bs[1]+bs[4])/2, (bs[2]+bs[5])/2);
2013-01-06 20:24:25 +01:00
lcVector3 Offset = Transform - Center;
2011-09-07 23:06:51 +02:00
for (int CameraIdx = 0; CameraIdx < mCameras.GetSize(); CameraIdx++)
{
2014-08-07 17:22:33 +02:00
lcCamera* pCamera = mCameras[CameraIdx];
2011-09-07 23:06:51 +02:00
if (pCamera->IsSelected())
{
2014-07-06 08:04:09 +02:00
pCamera->Move(mCurrentStep, gMainWindow->GetAddKeys(), Offset);
pCamera->UpdatePosition(mCurrentStep);
}
}
2011-09-07 23:06:51 +02:00
for (int LightIdx = 0; LightIdx < mLights.GetSize(); LightIdx++)
{
2014-08-07 17:22:33 +02:00
lcLight* pLight = mLights[LightIdx];
2011-09-07 23:06:51 +02:00
if (pLight->IsSelected())
{
2014-07-06 08:04:09 +02:00
pLight->Move(mCurrentStep, gMainWindow->GetAddKeys(), Offset);
pLight->UpdatePosition (mCurrentStep);
}
}
2013-01-06 20:24:25 +01:00
for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++)
{
2014-08-07 17:22:33 +02:00
lcPiece* Piece = mPieces[PieceIdx];
2011-09-07 23:06:51 +02:00
if (Piece->IsSelected())
{
2014-07-06 08:04:09 +02:00
Piece->Move(mCurrentStep, gMainWindow->GetAddKeys(), Offset);
Piece->UpdatePosition(mCurrentStep);
}
}
2011-09-07 23:06:51 +02:00
if (nSel)
{
gMainWindow->UpdateAllViews();
CheckPoint("Moving");
gMainWindow->UpdateFocusObject(GetFocusObject());
}
2011-09-07 23:06:51 +02:00
} break;
case LC_TRANSFORM_RELATIVE_TRANSLATION:
2011-09-07 23:06:51 +02:00
{
2014-10-05 07:21:51 +02:00
/* lcVector3 Move(Transform);
2011-09-07 23:06:51 +02:00
2014-10-05 07:21:51 +02:00
if (MoveSelectedObjects(Move, false, false))
2011-09-07 23:06:51 +02:00
{
gMainWindow->UpdateAllViews();
CheckPoint("Moving");
gMainWindow->UpdateFocusObject(GetFocusObject());
2014-10-05 07:21:51 +02:00
}*/
} break;
2011-09-07 23:06:51 +02:00
case LC_TRANSFORM_ABSOLUTE_ROTATION:
{
// Create the rotation matrix.
lcVector4 RotationQuaternion(0, 0, 0, 1);
2011-09-07 23:06:51 +02:00
if (Transform[0] != 0.0f)
{
lcVector4 q = lcQuaternionRotationX(Transform[0] * LC_DTOR);
RotationQuaternion = lcQuaternionMultiply(q, RotationQuaternion);
}
2011-09-07 23:06:51 +02:00
if (Transform[1] != 0.0f)
{
lcVector4 q = lcQuaternionRotationY(Transform[1] * LC_DTOR);
RotationQuaternion = lcQuaternionMultiply(q, RotationQuaternion);
}
2011-09-07 23:06:51 +02:00
if (Transform[2] != 0.0f)
{
lcVector4 q = lcQuaternionRotationZ(Transform[2] * LC_DTOR);
RotationQuaternion = lcQuaternionMultiply(q, RotationQuaternion);
}
2011-09-07 23:06:51 +02:00
lcVector4 NewRotation = lcQuaternionToAxisAngle(RotationQuaternion);
NewRotation[3] *= LC_RTOD;
2011-09-07 23:06:51 +02:00
int nSel = 0;
2011-09-07 23:06:51 +02:00
for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++)
{
2014-08-07 17:22:33 +02:00
lcPiece* Piece = mPieces[PieceIdx];
2011-09-07 23:06:51 +02:00
if (Piece->IsSelected())
2011-09-07 23:06:51 +02:00
{
2014-08-31 02:53:12 +02:00
Piece->SetRotation(NewRotation, mCurrentStep, gMainWindow->GetAddKeys());
2014-07-06 08:04:09 +02:00
Piece->UpdatePosition(mCurrentStep);
nSel++;
2011-09-07 23:06:51 +02:00
}
}
if (nSel)
{
gMainWindow->UpdateAllViews();
CheckPoint("Rotating");
gMainWindow->UpdateFocusObject(GetFocusObject());
}
} break;
2011-09-07 23:06:51 +02:00
case LC_TRANSFORM_RELATIVE_ROTATION:
{
2014-10-05 07:21:51 +02:00
lcVector3 Rotate(Transform);
2011-09-07 23:06:51 +02:00
2014-10-05 07:21:51 +02:00
if (RotateSelectedPieces(Rotate))
{
gMainWindow->UpdateAllViews();
CheckPoint("Rotating");
gMainWindow->UpdateFocusObject(GetFocusObject());
}
} break;
}
}
2011-09-07 23:06:51 +02:00
2014-08-07 17:22:33 +02:00
void Project::ModifyObject(lcObject* Object, lcObjectProperty Property, void* Value)
{
const char* CheckPointString = NULL;
2011-09-07 23:06:51 +02:00
switch (Property)
{
case LC_PIECE_PROPERTY_POSITION:
{
const lcVector3& Position = *(lcVector3*)Value;
2014-08-31 02:53:12 +02:00
lcPiece* Piece = (lcPiece*)Object;
2011-09-07 23:06:51 +02:00
2014-08-31 02:53:12 +02:00
if (Piece->mPosition != Position)
2014-05-21 00:15:42 +02:00
{
2014-08-31 02:53:12 +02:00
Piece->SetPosition(Position, mCurrentStep, gMainWindow->GetAddKeys());
Piece->UpdatePosition(mCurrentStep);
2011-09-07 23:06:51 +02:00
CheckPointString = "Moving";
2011-09-07 23:06:51 +02:00
}
} break;
2011-09-07 23:06:51 +02:00
case LC_PIECE_PROPERTY_ROTATION:
{
const lcVector4& Rotation = *(lcVector4*)Value;
2014-08-31 02:53:12 +02:00
lcPiece* Piece = (lcPiece*)Object;
2014-08-31 02:53:12 +02:00
if (Rotation != Piece->mRotation)
2014-05-21 00:15:42 +02:00
{
2014-08-31 02:53:12 +02:00
Piece->SetRotation(Rotation, mCurrentStep, gMainWindow->GetAddKeys());
Piece->UpdatePosition(mCurrentStep);
CheckPointString = "Rotating";
}
2011-09-07 23:06:51 +02:00
} break;
2013-01-06 20:24:25 +01:00
case LC_PIECE_PROPERTY_SHOW:
2011-09-07 23:06:51 +02:00
{
2014-07-06 08:04:09 +02:00
lcStep Step = *(lcStep*)Value;
2014-08-07 17:22:33 +02:00
lcPiece* Part = (lcPiece*)Object;
2011-09-07 23:06:51 +02:00
2014-07-06 08:04:09 +02:00
if (Step != Part->GetStepShow())
2011-09-07 23:06:51 +02:00
{
2014-07-06 08:04:09 +02:00
Part->SetStepShow(Step);
if (Part->IsSelected() && !Part->IsVisible(mCurrentStep))
Part->SetSelected(false);
2011-09-07 23:06:51 +02:00
CheckPointString = "Show";
}
} break;
2011-09-07 23:06:51 +02:00
case LC_PIECE_PROPERTY_HIDE:
{
2014-07-06 08:04:09 +02:00
lcStep Step = *(lcuint32*)Value;
2014-08-07 17:22:33 +02:00
lcPiece* Part = (lcPiece*)Object;
2011-09-07 23:06:51 +02:00
2014-07-06 08:04:09 +02:00
if (Step != Part->GetStepHide())
{
2014-07-06 08:04:09 +02:00
Part->SetStepHide(Step);
2011-09-07 23:06:51 +02:00
CheckPointString = "Hide";
}
} break;
2011-09-07 23:06:51 +02:00
case LC_PIECE_PROPERTY_COLOR:
{
int ColorIndex = *(int*)Value;
2014-08-07 17:22:33 +02:00
lcPiece* Part = (lcPiece*)Object;
2011-09-07 23:06:51 +02:00
if (ColorIndex != Part->mColorIndex)
{
Part->SetColorIndex(ColorIndex);
2011-09-07 23:06:51 +02:00
CheckPointString = "Color";
}
} break;
2011-09-07 23:06:51 +02:00
case LC_PIECE_PROPERTY_ID:
{
2014-08-07 17:22:33 +02:00
lcPiece* Part = (lcPiece*)Object;
PieceInfo* Info = (PieceInfo*)Value;
2011-09-07 23:06:51 +02:00
if (Info != Part->mPieceInfo)
{
Part->mPieceInfo->Release();
Part->mPieceInfo = Info;
Part->mPieceInfo->AddRef();
2011-09-07 23:06:51 +02:00
CheckPointString = "Part";
2011-09-07 23:06:51 +02:00
}
} break;
case LC_CAMERA_PROPERTY_POSITION:
2014-08-31 02:53:12 +02:00
{
const lcVector3& Position = *(lcVector3*)Value;
2014-08-31 02:53:12 +02:00
lcCamera* Camera = (lcCamera*)Object;
2011-09-07 23:06:51 +02:00
2014-08-31 02:53:12 +02:00
if (Camera->mPosition != Position)
{
2014-08-31 02:53:12 +02:00
Camera->SetPosition(Position, mCurrentStep, gMainWindow->GetAddKeys());
Camera->UpdatePosition(mCurrentStep);
2011-09-07 23:06:51 +02:00
CheckPointString = "Camera";
}
} break;
2011-09-07 23:06:51 +02:00
case LC_CAMERA_PROPERTY_TARGET:
{
const lcVector3& TargetPosition = *(lcVector3*)Value;
2014-08-31 02:53:12 +02:00
lcCamera* Camera = (lcCamera*)Object;
2011-09-07 23:06:51 +02:00
2014-08-31 02:53:12 +02:00
if (Camera->mTargetPosition != TargetPosition)
{
2014-08-31 02:53:12 +02:00
Camera->SetTargetPosition(TargetPosition, mCurrentStep, gMainWindow->GetAddKeys());
Camera->UpdatePosition(mCurrentStep);
2011-09-07 23:06:51 +02:00
CheckPointString = "Camera";
}
} break;
2011-09-07 23:06:51 +02:00
case LC_CAMERA_PROPERTY_UPVECTOR:
{
const lcVector3& Up = *(lcVector3*)Value;
2014-08-31 02:53:12 +02:00
lcCamera* Camera = (lcCamera*)Object;
2011-09-07 23:06:51 +02:00
2014-08-31 02:53:12 +02:00
if (Camera->mUpVector != Up)
{
2014-08-31 02:53:12 +02:00
Camera->SetUpVector(Up, mCurrentStep, gMainWindow->GetAddKeys());
Camera->UpdatePosition(mCurrentStep);
2011-09-07 23:06:51 +02:00
CheckPointString = "Camera";
2011-09-07 23:06:51 +02:00
}
} break;
case LC_CAMERA_PROPERTY_ORTHO:
2011-09-07 23:06:51 +02:00
{
bool Ortho = *(bool*)Value;
2014-08-07 17:22:33 +02:00
lcCamera* camera = (lcCamera*)Object;
2011-09-07 23:06:51 +02:00
if (camera->IsOrtho() != Ortho)
{
camera->SetOrtho(Ortho);
2014-07-06 08:04:09 +02:00
camera->UpdatePosition(mCurrentStep);
CheckPointString = "Camera";
}
2011-09-07 23:06:51 +02:00
} break;
case LC_CAMERA_PROPERTY_FOV:
2011-09-07 23:06:51 +02:00
{
float FOV = *(float*)Value;
2014-08-07 17:22:33 +02:00
lcCamera* camera = (lcCamera*)Object;
2011-09-07 23:06:51 +02:00
if (camera->m_fovy != FOV)
{
camera->m_fovy = FOV;
2014-07-06 08:04:09 +02:00
camera->UpdatePosition(mCurrentStep);
CheckPointString = "Camera";
}
2011-09-07 23:06:51 +02:00
} break;
case LC_CAMERA_PROPERTY_NEAR:
2011-09-07 23:06:51 +02:00
{
float Near = *(float*)Value;
2014-08-07 17:22:33 +02:00
lcCamera* camera = (lcCamera*)Object;
2011-09-07 23:06:51 +02:00
if (camera->m_zNear != Near)
{
camera->m_zNear= Near;
2014-07-06 08:04:09 +02:00
camera->UpdatePosition(mCurrentStep);
2013-01-06 20:24:25 +01:00
CheckPointString = "Camera";
}
} break;
2011-09-07 23:06:51 +02:00
case LC_CAMERA_PROPERTY_FAR:
{
float Far = *(float*)Value;
2014-08-07 17:22:33 +02:00
lcCamera* camera = (lcCamera*)Object;
if (camera->m_zFar != Far)
{
camera->m_zFar = Far;
2014-07-06 08:04:09 +02:00
camera->UpdatePosition(mCurrentStep);
CheckPointString = "Camera";
}
} break;
case LC_CAMERA_PROPERTY_NAME:
{
const char* Name = (const char*)Value;
2014-08-07 17:22:33 +02:00
lcCamera* camera = (lcCamera*)Object;
2011-09-07 23:06:51 +02:00
if (strcmp(camera->m_strName, Name))
2011-09-07 23:06:51 +02:00
{
strncpy(camera->m_strName, Name, sizeof(camera->m_strName));
camera->m_strName[sizeof(camera->m_strName) - 1] = 0;
2011-09-07 23:06:51 +02:00
gMainWindow->UpdateCameraMenu();
2011-09-07 23:06:51 +02:00
CheckPointString = "Camera";
2011-09-07 23:06:51 +02:00
}
}
}
2011-09-07 23:06:51 +02:00
if (CheckPointString)
{
CheckPoint(CheckPointString);
gMainWindow->UpdateFocusObject(GetFocusObject());
gMainWindow->UpdateAllViews();
2011-09-07 23:06:51 +02:00
}
}
void Project::ZoomActiveView(int Amount)
2013-01-28 20:57:33 +01:00
{
float ScaledAmount = 2.0f * Amount / (21 - lcGetProfileInt(LC_PROFILE_MOUSE_SENSITIVITY));
2014-07-06 08:04:09 +02:00
gMainWindow->GetActiveView()->mCamera->Zoom(ScaledAmount, mCurrentStep, gMainWindow->GetAddKeys());
gMainWindow->UpdateFocusObject(GetFocusObject());
gMainWindow->UpdateAllViews();
2013-01-28 20:57:33 +01:00
}
2013-12-19 14:41:49 +01:00
// Indicates if the existing string represents an instance of the candidate
// string in the form "<basename> (#<instance>)".
//
// Returns:
// -1 if existing is not an instance of candidate.
// 0 if existing is an instance but not numbered.
// >= 1 indicates the existing instance number.
//
2014-01-26 00:38:03 +01:00
int Project::InstanceOfName(const String& existingString, const String& candidateString, String& baseNameOut)
2013-12-19 14:41:49 +01:00
{
int einst = 0;
String estr = existingString;
estr.TrimLeft();
estr.TrimRight();
int div = estr.ReverseFind('#');
if (-1 != div)
{
char* endptr;
einst = strtol(estr.Mid(div + 1), &endptr, 10);
if (!*endptr)
{
estr = estr.Left(div);
estr.TrimRight();
}
}
String cstr = candidateString;
cstr.TrimLeft();
cstr.TrimRight();
div = cstr.ReverseFind('#');
if (-1 != div)
{
char* endptr;
2014-01-26 00:38:03 +01:00
int Value = strtol(cstr.Mid(div + 1), &endptr, 10);
(void)Value;
2013-12-19 14:41:49 +01:00
if (!*endptr)
{
cstr = cstr.Left(div);
cstr.TrimRight();
}
}
if (estr.CompareNoCase(cstr))
return -1;
baseNameOut = estr;
return einst;
}