2011-09-07 23:06:51 +02:00
|
|
|
// Everything that is a part of a LeoCAD project goes here.
|
|
|
|
//
|
|
|
|
|
2012-03-20 01:57:42 +01:00
|
|
|
#include "lc_global.h"
|
2012-03-29 03:10:55 +02:00
|
|
|
#include "lc_math.h"
|
2012-04-14 04:20:27 +02:00
|
|
|
#include "lc_mesh.h"
|
2011-09-07 23:06:51 +02:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <float.h>
|
|
|
|
#include <math.h>
|
|
|
|
#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 "terrain.h"
|
|
|
|
#include "project.h"
|
|
|
|
#include "image.h"
|
|
|
|
#include "system.h"
|
|
|
|
#include "minifig.h"
|
|
|
|
#include "curve.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"
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Project construction/destruction
|
|
|
|
|
|
|
|
Project::Project()
|
|
|
|
{
|
2011-09-17 01:59:55 +02:00
|
|
|
m_ActiveView = NULL;
|
2011-09-07 23:06:51 +02:00
|
|
|
m_bModified = false;
|
|
|
|
m_bTrackCancel = false;
|
|
|
|
m_nTracking = LC_TRACK_NONE;
|
2013-04-10 02:56:51 +02:00
|
|
|
m_OverlayMode = LC_OVERLAY_NONE;
|
2013-08-09 06:57:18 +02:00
|
|
|
mDropPiece = NULL;
|
2011-09-07 23:06:51 +02:00
|
|
|
m_pPieces = NULL;
|
|
|
|
m_pLights = NULL;
|
|
|
|
m_pGroups = NULL;
|
|
|
|
m_pUndoList = NULL;
|
|
|
|
m_pRedoList = NULL;
|
|
|
|
m_nGridList = 0;
|
2011-09-17 01:59:55 +02:00
|
|
|
m_pTrackFile = NULL;
|
2011-09-07 23:06:51 +02:00
|
|
|
m_nCurAction = 0;
|
2013-08-09 06:57:18 +02:00
|
|
|
mTransformType = LC_TRANSFORM_RELATIVE_TRANSLATION;
|
2011-09-07 23:06:51 +02:00
|
|
|
m_pTerrain = new Terrain();
|
2012-10-12 20:21:45 +02:00
|
|
|
m_pBackground = new lcTexture();
|
2013-08-09 06:57:18 +02:00
|
|
|
m_nAutosave = lcGetProfileInt(LC_PROFILE_AUTOSAVE_INTERVAL);
|
|
|
|
m_nMouse = lcGetProfileInt(LC_PROFILE_MOUSE_SENSITIVITY);
|
2013-07-08 20:09:44 +02:00
|
|
|
m_nDownX = 0;
|
|
|
|
m_nDownY = 0;
|
2013-08-09 06:57:18 +02:00
|
|
|
memset(&mSearchOptions, 0, sizeof(mSearchOptions));
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
m_pScreenFont = new TexFont();
|
|
|
|
}
|
|
|
|
|
|
|
|
Project::~Project()
|
|
|
|
{
|
|
|
|
DeleteContents(false);
|
|
|
|
|
|
|
|
delete m_pTrackFile;
|
|
|
|
delete m_pTerrain;
|
|
|
|
delete m_pBackground;
|
|
|
|
delete m_pScreenFont;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Project attributes, general services
|
|
|
|
|
|
|
|
void Project::UpdateInterface()
|
|
|
|
{
|
|
|
|
// Update all user interface elements.
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateUndoRedo(m_pUndoList->pNext ? m_pUndoList->strText : NULL, m_pRedoList ? m_pRedoList->strText : NULL);
|
|
|
|
gMainWindow->UpdatePaste(g_App->mClipboard != NULL);
|
2011-09-07 23:06:51 +02:00
|
|
|
SystemUpdatePlay(true, false);
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateCategories();
|
|
|
|
gMainWindow->UpdateTitle(m_strTitle, m_bModified);
|
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
|
|
|
SetAction(m_nCurAction);
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateTransformType(mTransformType);
|
|
|
|
gMainWindow->UpdateAnimation(m_bAnimation, m_bAddKeys);
|
|
|
|
gMainWindow->UpdateLockSnap(m_nSnap);
|
|
|
|
gMainWindow->UpdateSnap();
|
|
|
|
gMainWindow->UpdateCameraMenu(mCameras, m_ActiveView ? m_ActiveView->mCamera : NULL);
|
2011-09-07 23:06:51 +02:00
|
|
|
UpdateSelection();
|
|
|
|
if (m_bAnimation)
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateTime(m_bAnimation, m_nCurFrame, m_nTotalFrames);
|
2011-09-07 23:06:51 +02:00
|
|
|
else
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateTime(m_bAnimation, m_nCurStep, 255);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
for (int i = 0; i < m_ViewList.GetSize(); i++)
|
|
|
|
{
|
|
|
|
m_ViewList[i]->MakeCurrent();
|
|
|
|
RenderInitialize();
|
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateTitle(m_strTitle, m_bModified);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Project::DeleteContents(bool bUndo)
|
|
|
|
{
|
|
|
|
Piece* pPiece;
|
|
|
|
Light* pLight;
|
|
|
|
Group* pGroup;
|
|
|
|
|
|
|
|
memset(m_strAuthor, 0, sizeof(m_strAuthor));
|
|
|
|
memset(m_strDescription, 0, sizeof(m_strDescription));
|
|
|
|
memset(m_strComments, 0, sizeof(m_strComments));
|
|
|
|
|
|
|
|
if (!bUndo)
|
|
|
|
{
|
|
|
|
LC_UNDOINFO* pUndo;
|
|
|
|
|
|
|
|
while (m_pUndoList)
|
|
|
|
{
|
|
|
|
pUndo = m_pUndoList;
|
|
|
|
m_pUndoList = m_pUndoList->pNext;
|
|
|
|
delete pUndo;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (m_pRedoList)
|
|
|
|
{
|
|
|
|
pUndo = m_pRedoList;
|
|
|
|
m_pRedoList = m_pRedoList->pNext;
|
|
|
|
delete pUndo;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_pRedoList = NULL;
|
|
|
|
m_pUndoList = NULL;
|
|
|
|
|
|
|
|
m_pBackground->Unload();
|
2011-09-20 01:03:28 +02:00
|
|
|
m_pTerrain->LoadDefaults(true);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
while (m_pPieces)
|
|
|
|
{
|
|
|
|
pPiece = m_pPieces;
|
|
|
|
m_pPieces = m_pPieces->m_pNext;
|
|
|
|
delete pPiece;
|
|
|
|
}
|
|
|
|
|
2012-12-13 01:20:40 +01:00
|
|
|
if (!bUndo)
|
|
|
|
{
|
|
|
|
for (int ViewIdx = 0; ViewIdx < m_ViewList.GetSize(); ViewIdx++)
|
|
|
|
{
|
|
|
|
View* view = m_ViewList[ViewIdx];
|
|
|
|
|
|
|
|
if (!view->mCamera->IsSimple())
|
|
|
|
view->SetDefaultCamera();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-22 03:13:32 +02:00
|
|
|
for (int CameraIdx = 0; CameraIdx < mCameras.GetSize(); CameraIdx++)
|
|
|
|
delete mCameras[CameraIdx];
|
|
|
|
mCameras.RemoveAll();
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
while (m_pLights)
|
|
|
|
{
|
|
|
|
pLight = m_pLights;
|
|
|
|
m_pLights = m_pLights->m_pNext;
|
|
|
|
delete pLight;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (m_pGroups)
|
|
|
|
{
|
|
|
|
pGroup = m_pGroups;
|
|
|
|
m_pGroups = m_pGroups->m_pNext;
|
|
|
|
delete pGroup;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
if (!m_strTempFile.IsEmpty())
|
|
|
|
{
|
|
|
|
DeleteFile (m_strTempFile);
|
|
|
|
m_strTempFile.Empty();
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
|
|
|
// Only call after DeleteContents()
|
|
|
|
void Project::LoadDefaults(bool cameras)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
unsigned long rgb;
|
|
|
|
|
|
|
|
// Default values
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->SetColorIndex(lcGetColorIndex(4));
|
|
|
|
SetAction(LC_ACTION_SELECT);
|
2011-09-07 23:06:51 +02:00
|
|
|
m_bAnimation = false;
|
|
|
|
m_bAddKeys = false;
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateAnimation(m_bAnimation, m_bAddKeys);
|
2011-09-07 23:06:51 +02:00
|
|
|
m_bUndoOriginal = true;
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateUndoRedo(NULL, NULL);
|
|
|
|
m_nDetail = lcGetProfileInt(LC_PROFILE_DETAIL);
|
|
|
|
m_nAngleSnap = (unsigned short)lcGetProfileInt(LC_PROFILE_ANGLE_SNAP);
|
|
|
|
m_nSnap = lcGetProfileInt(LC_PROFILE_SNAP);
|
|
|
|
gMainWindow->UpdateLockSnap(m_nSnap);
|
2011-09-07 23:06:51 +02:00
|
|
|
m_nMoveSnap = 0x0304;
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateSnap();
|
|
|
|
m_fLineWidth = (float)lcGetProfileFloat(LC_PROFILE_LINE_WIDTH);
|
|
|
|
m_fFogDensity = (float)lcGetProfileFloat(LC_PROFILE_DEFAULT_FOG_DENSITY);
|
|
|
|
rgb = lcGetProfileInt(LC_PROFILE_DEFAULT_FOG_COLOR);
|
2011-09-07 23:06:51 +02:00
|
|
|
m_fFogColor[0] = (float)((unsigned char) (rgb))/255;
|
|
|
|
m_fFogColor[1] = (float)((unsigned char) (((unsigned short) (rgb)) >> 8))/255;
|
|
|
|
m_fFogColor[2] = (float)((unsigned char) ((rgb) >> 16))/255;
|
|
|
|
m_fFogColor[3] = 1.0f;
|
2013-08-09 06:57:18 +02:00
|
|
|
m_nGridSize = (unsigned short)lcGetProfileInt(LC_PROFILE_GRID_SIZE);
|
|
|
|
rgb = lcGetProfileInt(LC_PROFILE_DEFAULT_AMBIENT_COLOR);
|
2011-09-07 23:06:51 +02:00
|
|
|
m_fAmbient[0] = (float)((unsigned char) (rgb))/255;
|
|
|
|
m_fAmbient[1] = (float)((unsigned char) (((unsigned short) (rgb)) >> 8))/255;
|
|
|
|
m_fAmbient[2] = (float)((unsigned char) ((rgb) >> 16))/255;
|
|
|
|
m_fAmbient[3] = 1.0f;
|
2013-08-09 06:57:18 +02:00
|
|
|
rgb = lcGetProfileInt(LC_PROFILE_DEFAULT_BACKGROUND_COLOR);
|
2011-09-07 23:06:51 +02:00
|
|
|
m_fBackground[0] = (float)((unsigned char) (rgb))/255;
|
|
|
|
m_fBackground[1] = (float)((unsigned char) (((unsigned short) (rgb)) >> 8))/255;
|
|
|
|
m_fBackground[2] = (float)((unsigned char) ((rgb) >> 16))/255;
|
|
|
|
m_fBackground[3] = 1.0f;
|
2013-08-09 06:57:18 +02:00
|
|
|
rgb = lcGetProfileInt(LC_PROFILE_DEFAULT_GRADIENT_COLOR1);
|
2011-09-07 23:06:51 +02:00
|
|
|
m_fGradient1[0] = (float)((unsigned char) (rgb))/255;
|
|
|
|
m_fGradient1[1] = (float)((unsigned char) (((unsigned short) (rgb)) >> 8))/255;
|
|
|
|
m_fGradient1[2] = (float)((unsigned char) ((rgb) >> 16))/255;
|
2013-08-09 06:57:18 +02:00
|
|
|
rgb = lcGetProfileInt(LC_PROFILE_DEFAULT_GRADIENT_COLOR2);
|
2011-09-07 23:06:51 +02:00
|
|
|
m_fGradient2[0] = (float)((unsigned char) (rgb))/255;
|
|
|
|
m_fGradient2[1] = (float)((unsigned char) (((unsigned short) (rgb)) >> 8))/255;
|
|
|
|
m_fGradient2[2] = (float)((unsigned char) ((rgb) >> 16))/255;
|
2013-08-09 06:57:18 +02:00
|
|
|
m_nFPS = 24;
|
2011-09-07 23:06:51 +02:00
|
|
|
m_nCurStep = 1;
|
|
|
|
m_nCurFrame = 1;
|
|
|
|
m_nTotalFrames = 100;
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateTime(false, 1, 255);
|
|
|
|
m_nScene = lcGetProfileInt(LC_PROFILE_DEFAULT_SCENE);
|
2011-09-07 23:06:51 +02:00
|
|
|
m_nSaveTimer = 0;
|
2013-08-09 06:57:18 +02:00
|
|
|
strcpy(m_strHeader, "");
|
|
|
|
strcpy(m_strFooter, "Page &P");
|
|
|
|
strcpy(m_strBackground, lcGetProfileString(LC_PROFILE_DEFAULT_BACKGROUND_TEXTURE));
|
2011-09-20 01:03:28 +02:00
|
|
|
m_pTerrain->LoadDefaults(true);
|
2011-09-07 23:06:51 +02:00
|
|
|
m_OverlayActive = false;
|
|
|
|
|
|
|
|
for (i = 0; i < m_ViewList.GetSize (); i++)
|
|
|
|
{
|
2012-08-20 06:05:56 +02:00
|
|
|
m_ViewList[i]->MakeCurrent();
|
2011-09-07 23:06:51 +02:00
|
|
|
RenderInitialize();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cameras)
|
|
|
|
{
|
2012-08-20 06:05:56 +02:00
|
|
|
for (i = 0; i < m_ViewList.GetSize(); i++)
|
2012-12-13 01:20:40 +01:00
|
|
|
if (!m_ViewList[i]->mCamera->IsSimple())
|
|
|
|
m_ViewList[i]->SetDefaultCamera();
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateCameraMenu(mCameras, m_ActiveView ? m_ActiveView->mCamera : NULL);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
2012-12-13 01:20:40 +01:00
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
SystemPieceComboAdd(NULL);
|
|
|
|
UpdateSelection();
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateFocusObject(NULL);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Standard file menu commands
|
|
|
|
|
|
|
|
// Read a .lcd file
|
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;
|
2012-03-23 00:44:56 +01:00
|
|
|
lcuint8 ch, action = m_nCurAction;
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
m_fBackground[0] = (float)((unsigned char) (rgb))/255;
|
|
|
|
m_fBackground[1] = (float)((unsigned char) (((unsigned short) (rgb)) >> 8))/255;
|
|
|
|
m_fBackground[2] = (float)((unsigned char) ((rgb) >> 16))/255;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fv < 0.6f) // old view
|
|
|
|
{
|
2012-08-23 20:47:37 +02:00
|
|
|
Camera* pCam = new Camera(false);
|
2012-08-22 03:13:32 +02:00
|
|
|
pCam->CreateName(mCameras);
|
|
|
|
mCameras.Add(pCam);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
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
|
|
|
float tmp[3] = { (float)eye[0], (float)eye[1], (float)eye[2] };
|
|
|
|
pCam->ChangeKey(1, false, false, tmp, LC_CK_EYE);
|
|
|
|
pCam->ChangeKey(1, true, false, tmp, LC_CK_EYE);
|
|
|
|
tmp[0] = (float)target[0]; tmp[1] = (float)target[1]; tmp[2] = (float)target[2];
|
|
|
|
pCam->ChangeKey(1, false, false, tmp, LC_CK_TARGET);
|
|
|
|
pCam->ChangeKey(1, true, false, tmp, LC_CK_TARGET);
|
|
|
|
|
|
|
|
// Create up vector
|
2012-03-29 03:10:55 +02:00
|
|
|
lcVector3 UpVector(0, 0, 1), FrontVector((float)(eye[0] - target[0]), (float)(eye[1] - target[1]), (float)(eye[2] - target[2])), SideVector;
|
|
|
|
FrontVector.Normalize();
|
|
|
|
if (FrontVector == UpVector)
|
|
|
|
SideVector = lcVector3(1, 0, 0);
|
2011-09-07 23:06:51 +02:00
|
|
|
else
|
2012-03-29 03:10:55 +02:00
|
|
|
SideVector = lcCross(FrontVector, UpVector);
|
|
|
|
UpVector = lcNormalize(lcCross(SideVector, FrontVector));
|
|
|
|
pCam->ChangeKey(1, false, false, UpVector, LC_CK_UP);
|
|
|
|
pCam->ChangeKey(1, true, false, UpVector, LC_CK_UP);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (bMerge)
|
|
|
|
file->Seek(32, SEEK_CUR);
|
|
|
|
else
|
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
lcuint32 u;
|
2012-03-23 00:44:56 +01:00
|
|
|
file->ReadS32(&i, 1); m_nAngleSnap = i;
|
2013-08-09 06:57:18 +02:00
|
|
|
file->ReadU32(&u, 1); //m_nSnap
|
2012-03-23 00:44:56 +01:00
|
|
|
file->ReadFloats(&m_fLineWidth, 1);
|
2013-08-09 06:57:18 +02:00
|
|
|
file->ReadU32(&u, 1); //m_nDetail
|
2012-03-23 00:44:56 +01:00
|
|
|
file->ReadS32(&i, 1); //m_nCurGroup = i;
|
2013-08-09 06:57:18 +02:00
|
|
|
file->ReadS32(&i, 1); //m_nCurColor = i;
|
2012-03-23 00:44:56 +01:00
|
|
|
file->ReadS32(&i, 1); action = i;
|
|
|
|
file->ReadS32(&i, 1); m_nCurStep = i;
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (fv > 0.8f)
|
2012-03-23 00:44:56 +01:00
|
|
|
file->ReadU32(&m_nScene, 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-03-23 00:44:56 +01:00
|
|
|
file->ReadS32(&count, 1);
|
2013-08-09 06:57:18 +02:00
|
|
|
// SystemStartProgressBar(0, count, 1, "Loading project...");
|
2012-11-09 01:07:53 +01:00
|
|
|
lcPiecesLibrary* Library = lcGetPiecesLibrary();
|
|
|
|
Library->OpenCache();
|
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)
|
|
|
|
{
|
|
|
|
Piece* pPiece = new Piece(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 (Piece* p = m_pPieces; p; p = p->m_pNext)
|
|
|
|
if (strcmp(p->GetName(), pPiece->GetName()) == 0)
|
|
|
|
{
|
|
|
|
pPiece->CreateName(m_pPieces);
|
|
|
|
break;
|
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-11-09 01:07:53 +01:00
|
|
|
if (strlen(pPiece->GetName()) == 0)
|
|
|
|
pPiece->CreateName(m_pPieces);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-11-09 01:07:53 +01:00
|
|
|
AddPiece(pPiece);
|
|
|
|
if (!bUndo)
|
2013-08-09 06:57:18 +02:00
|
|
|
SystemPieceComboAdd(pPiece->mPieceInfo->m_strDescription);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
char name[LC_PIECE_NAME_LEN];
|
2012-10-18 20:57:21 +02:00
|
|
|
float pos[3], rot[3];
|
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
|
|
|
|
2012-11-09 01:07:53 +01:00
|
|
|
PieceInfo* pInfo = Library->FindPiece(name, true);
|
|
|
|
Piece* pPiece = new Piece(pInfo);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-11-09 01:07:53 +01:00
|
|
|
pPiece->Initialize(pos[0], pos[1], pos[2], step, 1);
|
|
|
|
pPiece->SetColorCode(lcGetColorCodeFromOriginalColor(color));
|
|
|
|
pPiece->CreateName(m_pPieces);
|
|
|
|
AddPiece(pPiece);
|
2013-01-06 20:24:25 +01:00
|
|
|
|
2012-11-09 01:07:53 +01:00
|
|
|
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;
|
|
|
|
|
|
|
|
pPiece->ChangeKey(1, false, false, AxisAngle, LC_PK_ROTATION);
|
|
|
|
pPiece->ChangeKey(1, true, false, AxisAngle, LC_PK_ROTATION);
|
|
|
|
// pPiece->SetGroup((Group*)group);
|
|
|
|
SystemPieceComboAdd(pInfo->m_strDescription);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
2012-11-09 01:07:53 +01:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
// SytemStepProgressBar();
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
2012-11-09 01:07:53 +01:00
|
|
|
|
|
|
|
Library->CloseCache();
|
2013-08-09 06:57:18 +02:00
|
|
|
// SytemEndProgressBar();
|
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
|
2012-03-23 00:44:56 +01:00
|
|
|
file->ReadBuffer(m_strAuthor, sh);
|
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
|
2012-03-23 00:44:56 +01:00
|
|
|
file->ReadBuffer(m_strDescription, sh);
|
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
|
2012-03-23 00:44:56 +01:00
|
|
|
file->ReadBuffer(m_strComments, sh);
|
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)
|
|
|
|
{
|
2012-03-23 00:44:56 +01:00
|
|
|
file->ReadS32(&count, 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
Group* pGroup;
|
|
|
|
Group* pLastGroup = NULL;
|
|
|
|
for (pGroup = m_pGroups; pGroup; pGroup = pGroup->m_pNext)
|
|
|
|
pLastGroup = pGroup;
|
|
|
|
|
|
|
|
pGroup = pLastGroup;
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
{
|
|
|
|
if (pGroup)
|
|
|
|
{
|
|
|
|
pGroup->m_pNext = new Group();
|
|
|
|
pGroup = pGroup->m_pNext;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
m_pGroups = pGroup = new Group();
|
|
|
|
}
|
|
|
|
pLastGroup = pLastGroup ? pLastGroup->m_pNext : m_pGroups;
|
|
|
|
|
|
|
|
for (pGroup = pLastGroup; pGroup; pGroup = pGroup->m_pNext)
|
|
|
|
{
|
|
|
|
if (fv < 1.0f)
|
|
|
|
{
|
2012-03-23 00:44:56 +01:00
|
|
|
file->ReadBuffer(pGroup->m_strName, 65);
|
|
|
|
file->ReadBuffer(&ch, 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
pGroup->m_fCenter[0] = 0;
|
|
|
|
pGroup->m_fCenter[1] = 0;
|
|
|
|
pGroup->m_fCenter[2] = 0;
|
|
|
|
pGroup->m_pGroup = (Group*)-1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
pGroup->FileLoad(file);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (pGroup = pLastGroup; pGroup; pGroup = pGroup->m_pNext)
|
|
|
|
{
|
|
|
|
i = LC_POINTER_TO_INT(pGroup->m_pGroup);
|
|
|
|
pGroup->m_pGroup = NULL;
|
|
|
|
|
|
|
|
if (i > 0xFFFF || i == -1)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
for (Group* g2 = pLastGroup; g2; g2 = g2->m_pNext)
|
|
|
|
{
|
|
|
|
if (i == 0)
|
|
|
|
{
|
|
|
|
pGroup->m_pGroup = g2;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
i--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Piece* pPiece;
|
|
|
|
for (pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
|
|
|
{
|
|
|
|
i = LC_POINTER_TO_INT(pPiece->GetGroup());
|
|
|
|
pPiece->SetGroup(NULL);
|
|
|
|
|
|
|
|
if (i > 0xFFFF || i == -1)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
for (pGroup = pLastGroup; pGroup; pGroup = pGroup->m_pNext)
|
|
|
|
{
|
|
|
|
if (i == 0)
|
|
|
|
{
|
|
|
|
pPiece->SetGroup(pGroup);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
i--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
RemoveEmptyGroups();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!bMerge)
|
|
|
|
{
|
|
|
|
if (fv >= 0.6f)
|
|
|
|
{
|
|
|
|
if (fv < 1.0f)
|
|
|
|
{
|
2012-03-23 00:44:56 +01:00
|
|
|
lcuint32 ViewportMode;
|
|
|
|
file->ReadU32(&ViewportMode, 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-02-05 03:50:57 +01:00
|
|
|
lcuint8 ViewportMode, ActiveViewport;
|
2012-03-23 00:44:56 +01:00
|
|
|
file->ReadU8(&ViewportMode, 1);
|
|
|
|
file->ReadU8(&ActiveViewport, 1);
|
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++)
|
2012-08-23 20:47:37 +02:00
|
|
|
mCameras.Add(new Camera(false));
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
if (count < 7)
|
|
|
|
{
|
2012-08-23 20:47:37 +02:00
|
|
|
Camera* pCam = new Camera(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)
|
|
|
|
{
|
|
|
|
for (count = 0; count < 4; count++)
|
|
|
|
{
|
2012-03-23 00:44:56 +01:00
|
|
|
file->ReadS32(&i, 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-07-02 01:38:53 +02:00
|
|
|
// Camera* pCam = m_pCameras;
|
|
|
|
// while (i--)
|
|
|
|
// pCam = pCam->m_pNext;
|
2012-02-05 03:50:57 +01:00
|
|
|
// m_pViewCameras[count] = pCam;
|
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
|
|
|
m_fFogColor[0] = (float)((unsigned char) (rgb))/255;
|
|
|
|
m_fFogColor[1] = (float)((unsigned char) (((unsigned short) (rgb)) >> 8))/255;
|
|
|
|
m_fFogColor[2] = (float)((unsigned char) ((rgb) >> 16))/255;
|
|
|
|
|
|
|
|
if (fv < 1.0f)
|
|
|
|
{
|
2012-03-23 00:44:56 +01:00
|
|
|
file->ReadU32(&rgb, 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
m_fFogDensity = (float)rgb/100;
|
|
|
|
}
|
|
|
|
else
|
2012-03-23 00:44:56 +01:00
|
|
|
file->ReadFloats(&m_fFogDensity, 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)
|
2012-03-23 00:44:56 +01:00
|
|
|
file->ReadBuffer(m_strBackground, sh);
|
2011-09-07 23:06:51 +02:00
|
|
|
else
|
|
|
|
file->Seek (sh, SEEK_CUR);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fv >= 0.8f)
|
|
|
|
{
|
2012-03-23 00:44:56 +01:00
|
|
|
file->ReadBuffer(&ch, 1);
|
|
|
|
file->ReadBuffer(m_strHeader, ch);
|
|
|
|
file->ReadBuffer(&ch, 1);
|
|
|
|
file->ReadBuffer(m_strFooter, ch);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (fv > 0.9f)
|
|
|
|
{
|
2012-03-23 00:44:56 +01:00
|
|
|
file->ReadU32(&rgb, 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
m_fAmbient[0] = (float)((unsigned char) (rgb))/255;
|
|
|
|
m_fAmbient[1] = (float)((unsigned char) (((unsigned short) (rgb)) >> 8))/255;
|
|
|
|
m_fAmbient[2] = (float)((unsigned char) ((rgb) >> 16))/255;
|
|
|
|
|
|
|
|
if (fv < 1.3f)
|
|
|
|
{
|
2012-03-23 00:44:56 +01:00
|
|
|
file->ReadS32(&i, 1); m_bAnimation = (i != 0);
|
|
|
|
file->ReadS32(&i, 1); m_bAddKeys = (i != 0);
|
|
|
|
file->ReadU8(&m_nFPS, 1);
|
|
|
|
file->ReadS32(&i, 1); m_nCurFrame = i;
|
|
|
|
file->ReadU16(&m_nTotalFrames, 1);
|
|
|
|
file->ReadS32(&i, 1); m_nGridSize = i;
|
|
|
|
file->ReadS32(&i, 1); //m_nMoveSnap = i;
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-03-23 00:44:56 +01:00
|
|
|
file->ReadU8(&ch, 1); m_bAnimation = (ch != 0);
|
|
|
|
file->ReadU8(&ch, 1); m_bAddKeys = (ch != 0);
|
|
|
|
file->ReadU8(&m_nFPS, 1);
|
|
|
|
file->ReadU16(&m_nCurFrame, 1);
|
|
|
|
file->ReadU16(&m_nTotalFrames, 1);
|
|
|
|
file->ReadU16(&m_nGridSize, 1);
|
|
|
|
file->ReadU16(&sh, 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
if (fv >= 1.4f)
|
|
|
|
m_nMoveSnap = sh;
|
|
|
|
}
|
|
|
|
}
|
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);
|
2011-09-07 23:06:51 +02:00
|
|
|
m_fGradient1[0] = (float)((unsigned char) (rgb))/255;
|
|
|
|
m_fGradient1[1] = (float)((unsigned char) (((unsigned short) (rgb)) >> 8))/255;
|
|
|
|
m_fGradient1[2] = (float)((unsigned char) ((rgb) >> 16))/255;
|
2012-03-23 00:44:56 +01:00
|
|
|
file->ReadU32(&rgb, 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
m_fGradient2[0] = (float)((unsigned char) (rgb))/255;
|
|
|
|
m_fGradient2[1] = (float)((unsigned char) (((unsigned short) (rgb)) >> 8))/255;
|
|
|
|
m_fGradient2[2] = (float)((unsigned char) ((rgb) >> 16))/255;
|
2013-01-06 20:24:25 +01:00
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
if (fv > 1.1f)
|
|
|
|
m_pTerrain->FileLoad (file);
|
|
|
|
else
|
|
|
|
{
|
2012-03-23 00:44:56 +01:00
|
|
|
file->Seek(4, SEEK_CUR);
|
|
|
|
file->ReadBuffer(&ch, 1);
|
|
|
|
file->Seek(ch, SEEK_CUR);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < m_ViewList.GetSize (); i++)
|
|
|
|
{
|
2012-02-05 06:03:59 +01:00
|
|
|
m_ViewList[i]->MakeCurrent();
|
2011-09-07 23:06:51 +02:00
|
|
|
RenderInitialize();
|
|
|
|
}
|
2012-12-13 01:20:40 +01:00
|
|
|
|
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)
|
|
|
|
SelectAndFocusNone(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)
|
|
|
|
{
|
|
|
|
for (int ViewIdx = 0; ViewIdx < m_ViewList.GetSize(); ViewIdx++)
|
|
|
|
{
|
|
|
|
View* view = m_ViewList[ViewIdx];
|
|
|
|
|
|
|
|
if (!view->mCamera->IsSimple())
|
|
|
|
view->SetDefaultCamera();
|
|
|
|
}
|
|
|
|
|
2012-12-14 00:58:03 +01:00
|
|
|
if (!bUndo)
|
|
|
|
ZoomExtents(0, m_ViewList.GetSize());
|
2012-12-13 01:20:40 +01:00
|
|
|
}
|
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
SetAction(action);
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateAnimation(m_bAnimation, m_bAddKeys);
|
|
|
|
gMainWindow->UpdateLockSnap(m_nSnap);
|
|
|
|
gMainWindow->UpdateSnap();
|
|
|
|
gMainWindow->UpdateCameraMenu(mCameras, m_ActiveView ? m_ActiveView->mCamera : NULL);
|
2011-09-07 23:06:51 +02:00
|
|
|
UpdateSelection();
|
|
|
|
if (m_bAnimation)
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateTime(m_bAnimation, m_nCurFrame, m_nTotalFrames);
|
2011-09-07 23:06:51 +02:00
|
|
|
else
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateTime(m_bAnimation, m_nCurStep, 255);
|
2011-09-07 23:06:51 +02:00
|
|
|
UpdateAllViews ();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-03-23 00:44:56 +01:00
|
|
|
void Project::FileSave(lcFile* file, bool bUndo)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
|
|
|
float ver_flt = 1.4f; // LeoCAD 0.75 - (and this should have been an integer).
|
2012-03-23 00:44:56 +01:00
|
|
|
lcuint32 rgb;
|
|
|
|
lcuint8 ch;
|
|
|
|
lcuint16 sh;
|
2011-09-07 23:06:51 +02:00
|
|
|
int i, j;
|
|
|
|
|
2013-08-17 00:39:47 +02:00
|
|
|
const char LC_STR_VERSION[32] = "LeoCAD 0.7 Project\0\0";
|
|
|
|
|
2012-03-23 00:44:56 +01:00
|
|
|
file->Seek(0, SEEK_SET);
|
|
|
|
file->WriteBuffer(LC_STR_VERSION, 32);
|
|
|
|
file->WriteFloats(&ver_flt, 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
rgb = LC_FLOATRGB(m_fBackground);
|
2012-03-23 00:44:56 +01:00
|
|
|
file->WriteU32(&rgb, 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-03-23 00:44:56 +01:00
|
|
|
i = m_nAngleSnap; file->WriteS32(&i, 1);
|
|
|
|
file->WriteU32(&m_nSnap, 1);
|
|
|
|
file->WriteFloats(&m_fLineWidth, 1);
|
|
|
|
file->WriteU32(&m_nDetail, 1);
|
2013-08-09 06:57:18 +02:00
|
|
|
i = 0;//i = m_nCurGroup;
|
|
|
|
file->WriteS32(&i, 1);
|
|
|
|
i = 0;//i = m_nCurColor;
|
2012-03-23 00:44:56 +01:00
|
|
|
file->WriteS32(&i, 1);
|
|
|
|
i = m_nCurAction; file->WriteS32(&i, 1);
|
|
|
|
i = m_nCurStep; file->WriteS32(&i, 1);
|
|
|
|
file->WriteU32(&m_nScene, 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
Piece* pPiece;
|
|
|
|
for (i = 0, pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
|
|
|
i++;
|
2012-03-23 00:44:56 +01:00
|
|
|
file->WriteS32(&i, 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
for (pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
2013-08-09 06:57:18 +02:00
|
|
|
pPiece->FileSave(*file);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
ch = strlen(m_strAuthor);
|
2012-03-23 00:44:56 +01:00
|
|
|
file->WriteBuffer(&ch, 1);
|
|
|
|
file->WriteBuffer(m_strAuthor, ch);
|
2011-09-07 23:06:51 +02:00
|
|
|
ch = strlen(m_strDescription);
|
2012-03-23 00:44:56 +01:00
|
|
|
file->WriteBuffer(&ch, 1);
|
|
|
|
file->WriteBuffer(m_strDescription, ch);
|
2011-09-07 23:06:51 +02:00
|
|
|
ch = strlen(m_strComments);
|
2012-03-23 00:44:56 +01:00
|
|
|
file->WriteBuffer(&ch, 1);
|
|
|
|
file->WriteBuffer(m_strComments, ch);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
Group* pGroup;
|
|
|
|
for (i = 0, pGroup = m_pGroups; pGroup; pGroup = pGroup->m_pNext)
|
|
|
|
i++;
|
2012-03-23 00:44:56 +01:00
|
|
|
file->WriteS32(&i, 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
for (pGroup = m_pGroups; pGroup; pGroup = pGroup->m_pNext)
|
|
|
|
pGroup->FileSave(file, m_pGroups);
|
|
|
|
|
2012-02-05 03:50:57 +01:00
|
|
|
lcuint8 ViewportMode = 0, ActiveViewport = 0;
|
2012-03-23 00:44:56 +01:00
|
|
|
file->WriteU8(&ViewportMode, 1);
|
|
|
|
file->WriteU8(&ActiveViewport, 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-08-22 03:13:32 +02:00
|
|
|
i = mCameras.GetSize();
|
2012-03-23 00:44:56 +01:00
|
|
|
file->WriteS32(&i, 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-08-22 03:13:32 +02:00
|
|
|
for (int CameraIdx = 0; CameraIdx < mCameras.GetSize(); CameraIdx++)
|
|
|
|
mCameras[CameraIdx]->FileSave(*file);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
for (j = 0; j < 4; j++)
|
|
|
|
{
|
2012-02-05 03:50:57 +01:00
|
|
|
i = 0;
|
|
|
|
// for (i = 0, pCamera = m_pCameras; pCamera; pCamera = pCamera->m_pNext)
|
|
|
|
// if (pCamera == m_pViewCameras[j])
|
|
|
|
// break;
|
|
|
|
// else
|
|
|
|
// i++;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-03-23 00:44:56 +01:00
|
|
|
file->WriteS32(&i, 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
rgb = LC_FLOATRGB(m_fFogColor);
|
2012-03-23 00:44:56 +01:00
|
|
|
file->WriteU32(&rgb, 1);
|
|
|
|
file->WriteFloats(&m_fFogDensity, 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
sh = strlen(m_strBackground);
|
2012-03-23 00:44:56 +01:00
|
|
|
file->WriteU16(&sh, 1);
|
|
|
|
file->WriteBuffer(m_strBackground, sh);
|
2011-09-07 23:06:51 +02:00
|
|
|
ch = strlen(m_strHeader);
|
2012-03-23 00:44:56 +01:00
|
|
|
file->WriteBuffer(&ch, 1);
|
|
|
|
file->WriteBuffer(m_strHeader, ch);
|
2011-09-07 23:06:51 +02:00
|
|
|
ch = strlen(m_strFooter);
|
2012-03-23 00:44:56 +01:00
|
|
|
file->WriteBuffer(&ch, 1);
|
|
|
|
file->WriteBuffer(m_strFooter, ch);
|
2011-09-07 23:06:51 +02:00
|
|
|
// 0.60 (1.0)
|
2013-08-09 06:57:18 +02:00
|
|
|
rgb = LC_FLOATRGB(m_fAmbient);
|
2012-03-23 00:44:56 +01:00
|
|
|
file->WriteU32(&rgb, 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
ch = m_bAnimation;
|
2012-03-23 00:44:56 +01:00
|
|
|
file->WriteBuffer(&ch, 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
ch = m_bAddKeys;
|
2012-03-23 00:44:56 +01:00
|
|
|
file->WriteU8(&ch, 1);
|
|
|
|
file->WriteU8 (&m_nFPS, 1);
|
|
|
|
file->WriteU16(&m_nCurFrame, 1);
|
|
|
|
file->WriteU16(&m_nTotalFrames, 1);
|
|
|
|
file->WriteU16(&m_nGridSize, 1);
|
|
|
|
file->WriteU16(&m_nMoveSnap, 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
// 0.62 (1.1)
|
2013-08-09 06:57:18 +02:00
|
|
|
rgb = LC_FLOATRGB(m_fGradient1);
|
2012-03-23 00:44:56 +01:00
|
|
|
file->WriteU32(&rgb, 1);
|
2013-08-09 06:57:18 +02:00
|
|
|
rgb = LC_FLOATRGB(m_fGradient2);
|
2012-03-23 00:44:56 +01:00
|
|
|
file->WriteU32(&rgb, 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
// 0.64 (1.2)
|
|
|
|
m_pTerrain->FileSave(file);
|
|
|
|
|
|
|
|
if (!bUndo)
|
|
|
|
{
|
2012-03-23 00:44:56 +01:00
|
|
|
lcuint32 pos = 0;
|
2013-08-09 06:57:18 +02:00
|
|
|
/*
|
|
|
|
// TODO: add file preview
|
|
|
|
i = lcGetProfileValue("Default", "Save Preview", 0);
|
2013-01-06 20:24:25 +01:00
|
|
|
if (i != 0)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
|
|
|
pos = file->GetPosition();
|
|
|
|
|
2012-03-23 00:44:56 +01:00
|
|
|
Image* image = new Image[1];
|
2011-09-07 23:06:51 +02:00
|
|
|
LC_IMAGE_OPTS opts;
|
|
|
|
opts.interlaced = false;
|
|
|
|
opts.transparent = false;
|
|
|
|
opts.format = LC_IMAGE_GIF;
|
|
|
|
|
|
|
|
i = m_bAnimation ? m_nCurFrame : m_nCurStep;
|
|
|
|
CreateImages(image, 120, 100, i, i, false);
|
|
|
|
image[0].FileSave (*file, &opts);
|
|
|
|
delete []image;
|
|
|
|
}
|
2013-08-09 06:57:18 +02:00
|
|
|
*/
|
2012-03-23 00:44:56 +01:00
|
|
|
file->WriteU32(&pos, 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
m_nSaveTimer = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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
|
|
|
{
|
2013-08-16 18:16:45 +02:00
|
|
|
char Line[1024];
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-02-05 06:03:59 +01:00
|
|
|
// Save file offset.
|
|
|
|
lcuint32 Offset = file->GetPosition();
|
|
|
|
file->Seek(0, SEEK_SET);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-16 18:16:45 +02:00
|
|
|
while (file->ReadLine(Line, 1024))
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
|
|
|
bool read = true;
|
2013-08-16 18:16:45 +02:00
|
|
|
char* Ptr = Line;
|
|
|
|
char* Tokens[15];
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-16 18:16:45 +02:00
|
|
|
for (int TokenIdx = 0; TokenIdx < 15; TokenIdx++)
|
|
|
|
{
|
|
|
|
Tokens[TokenIdx] = 0;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-16 18:16:45 +02:00
|
|
|
while (*Ptr && *Ptr <= 32)
|
|
|
|
{
|
|
|
|
*Ptr = 0;
|
|
|
|
Ptr++;
|
|
|
|
}
|
2012-10-18 20:57:21 +02:00
|
|
|
|
2013-08-16 18:16:45 +02:00
|
|
|
Tokens[TokenIdx] = Ptr;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-16 18:16:45 +02:00
|
|
|
while (*Ptr > 32)
|
|
|
|
Ptr++;
|
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-16 18:16:45 +02:00
|
|
|
if (!Tokens[0])
|
|
|
|
continue;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-16 18:16:45 +02:00
|
|
|
int LineType = atoi(Tokens[0]);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-16 18:16:45 +02:00
|
|
|
if (LineType == 0)
|
|
|
|
{
|
|
|
|
if (Tokens[1])
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-16 18:16:45 +02:00
|
|
|
strupr(Tokens[1]);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-16 18:16:45 +02:00
|
|
|
if (!strcmp(Tokens[1], "STEP"))
|
|
|
|
(*nStep)++;
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
2013-08-16 18:16:45 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (LineType != 1)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
bool Error = false;
|
|
|
|
for (int TokenIdx = 1; TokenIdx < 15; TokenIdx++)
|
|
|
|
{
|
|
|
|
if (!Tokens[TokenIdx])
|
2012-02-05 06:03:59 +01:00
|
|
|
{
|
2013-08-16 18:16:45 +02:00
|
|
|
Error = true;
|
|
|
|
break;
|
2012-02-05 06:03:59 +01:00
|
|
|
}
|
2013-08-16 18:16:45 +02:00
|
|
|
}
|
2012-02-05 06:03:59 +01:00
|
|
|
|
2013-08-16 18:16:45 +02:00
|
|
|
if (Error)
|
|
|
|
continue;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-16 18:16:45 +02:00
|
|
|
int ColorCode = atoi(Tokens[1]);
|
2012-02-05 06:03:59 +01:00
|
|
|
|
2013-08-16 18:16:45 +02:00
|
|
|
float Matrix[12];
|
|
|
|
for (int TokenIdx = 2; TokenIdx < 14; TokenIdx++)
|
|
|
|
Matrix[TokenIdx - 2] = atof(Tokens[TokenIdx]);
|
|
|
|
|
|
|
|
lcMatrix44 IncludeTransform(lcVector4(Matrix[3], Matrix[9], -Matrix[6], 0.0f), lcVector4(Matrix[5], Matrix[11], -Matrix[8], 0.0f),
|
|
|
|
lcVector4(-Matrix[4], -Matrix[10], Matrix[7], 0.0f), lcVector4(Matrix[0], Matrix[2], -Matrix[1], 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;
|
2012-02-05 06:03:59 +01:00
|
|
|
|
2013-08-16 18:16:45 +02:00
|
|
|
PieceInfo* pInfo = lcGetPiecesLibrary()->FindPiece(name, false);
|
|
|
|
if (pInfo != NULL)
|
|
|
|
{
|
|
|
|
Piece* pPiece = new Piece(pInfo);
|
2012-02-05 06:03:59 +01:00
|
|
|
read = false;
|
|
|
|
|
2012-10-18 20:57:21 +02:00
|
|
|
lcVector4 AxisAngle = lcMatrix44ToAxisAngle(IncludeTransform);
|
|
|
|
AxisAngle[3] *= LC_RTOD;
|
|
|
|
|
2013-08-16 18:16:45 +02:00
|
|
|
pPiece->Initialize(IncludeTransform[3].x / 25.0f, IncludeTransform[3].y / 25.0f, IncludeTransform[3].z / 25.0f, *nStep, 1);
|
|
|
|
pPiece->SetColorCode(ColorCode);
|
2012-02-05 06:03:59 +01:00
|
|
|
pPiece->CreateName(m_pPieces);
|
|
|
|
AddPiece(pPiece);
|
2012-10-18 20:57:21 +02:00
|
|
|
pPiece->ChangeKey(1, false, false, AxisAngle, LC_PK_ROTATION);
|
|
|
|
pPiece->ChangeKey(1, true, false, AxisAngle, LC_PK_ROTATION);
|
2013-08-16 18:16:45 +02:00
|
|
|
SystemPieceComboAdd(pInfo->m_strDescription);
|
2012-02-05 06:03:59 +01:00
|
|
|
(*nOk)++;
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
}
|
2013-08-16 18:16:45 +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);
|
|
|
|
|
|
|
|
Piece* pPiece = new Piece(Info);
|
|
|
|
read = false;
|
|
|
|
|
|
|
|
lcVector4 AxisAngle = lcMatrix44ToAxisAngle(IncludeTransform);
|
|
|
|
AxisAngle[3] *= LC_RTOD;
|
|
|
|
|
|
|
|
pPiece->Initialize(IncludeTransform[3].x, IncludeTransform[3].y, IncludeTransform[3].z, *nStep, 1);
|
|
|
|
pPiece->SetColorCode(ColorCode);
|
|
|
|
pPiece->CreateName(m_pPieces);
|
|
|
|
AddPiece(pPiece);
|
|
|
|
pPiece->ChangeKey(1, false, false, AxisAngle, LC_PK_ROTATION);
|
|
|
|
pPiece->ChangeKey(1, true, false, AxisAngle, LC_PK_ROTATION);
|
|
|
|
SystemPieceComboAdd(Info->m_strDescription);
|
|
|
|
(*nOk)++;
|
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
2012-02-05 06:03:59 +01: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);
|
2011-09-07 23:06:51 +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
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
strcat(SaveFileName, ".lcd");
|
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
|
|
|
}
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
lcDiskFile file;
|
|
|
|
if (!file.Open(SaveFileName, "wb"))
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
|
|
|
// MessageBox("Failed to save.");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
char ext[4];
|
2011-09-07 23:06:51 +02:00
|
|
|
memset(ext, 0, 4);
|
2013-08-09 06:57:18 +02:00
|
|
|
const char* ptr = strrchr(SaveFileName, '.');
|
2011-09-07 23:06:51 +02:00
|
|
|
if (ptr != NULL)
|
|
|
|
{
|
|
|
|
strncpy(ext, ptr+1, 3);
|
|
|
|
strlwr(ext);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((strcmp(ext, "dat") == 0) || (strcmp(ext, "ldr") == 0))
|
|
|
|
{
|
|
|
|
Piece* pPiece;
|
|
|
|
int i, steps = GetLastStep();
|
2013-02-13 00:36:30 +01:00
|
|
|
char buf[256];
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
ptr = strrchr(m_strPathName, '\\');
|
|
|
|
if (ptr == NULL)
|
|
|
|
ptr = strrchr(m_strPathName, '/');
|
|
|
|
if (ptr == NULL)
|
|
|
|
ptr = m_strPathName;
|
|
|
|
else
|
|
|
|
ptr++;
|
|
|
|
|
|
|
|
sprintf(buf, "0 Model exported from LeoCAD\r\n"
|
|
|
|
"0 Original name: %s\r\n", ptr);
|
|
|
|
if (strlen(m_strAuthor) != 0)
|
|
|
|
{
|
|
|
|
strcat(buf, "0 Author: ");
|
|
|
|
strcat(buf, m_strAuthor);
|
|
|
|
strcat(buf, "\r\n");
|
|
|
|
}
|
|
|
|
strcat(buf, "\r\n");
|
2012-03-23 00:44:56 +01:00
|
|
|
file.WriteBuffer(buf, strlen(buf));
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-02-08 23:48:51 +01:00
|
|
|
const char* OldLocale = setlocale(LC_NUMERIC, "C");
|
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
for (i = 1; i <= steps; i++)
|
|
|
|
{
|
|
|
|
for (pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
|
|
|
{
|
|
|
|
if ((pPiece->IsVisible(i, false)) && (pPiece->GetStepShow() == i))
|
|
|
|
{
|
2012-10-18 20:57:21 +02:00
|
|
|
const float* f = pPiece->mModelWorld;
|
2011-09-07 23:06:51 +02:00
|
|
|
sprintf (buf, " 1 %d %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %s.DAT\r\n",
|
2012-10-18 20:57:21 +02:00
|
|
|
pPiece->mColorCode, f[12] * 25.0f, -f[14] * 25.0f, f[13] *25.0f, f[0], -f[8], f[4], -f[2], f[10], -f[6], f[1], -f[9], f[5], pPiece->mPieceInfo->m_strName);
|
2012-03-23 00:44:56 +01:00
|
|
|
file.WriteBuffer(buf, strlen(buf));
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (i != steps)
|
2012-03-23 00:44:56 +01:00
|
|
|
file.WriteBuffer("0 STEP\r\n", 8);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
2012-03-23 00:44:56 +01:00
|
|
|
file.WriteBuffer("0\r\n", 3);
|
2012-02-08 23:48:51 +01:00
|
|
|
|
|
|
|
setlocale(LC_NUMERIC, OldLocale);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
FileSave(&file, false); // save me
|
2012-02-08 23:48:51 +01:00
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
file.Close();
|
|
|
|
|
|
|
|
SetModifiedFlag(false); // back to unmodified
|
|
|
|
|
|
|
|
// 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
|
|
|
|
}
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
void Project::SetModifiedFlag(bool Modified)
|
|
|
|
{
|
|
|
|
if (m_bModified != Modified)
|
|
|
|
{
|
|
|
|
m_bModified = Modified;
|
|
|
|
gMainWindow->UpdateModified(m_bModified);
|
|
|
|
}
|
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// File operations
|
|
|
|
|
|
|
|
bool Project::OnNewDocument()
|
|
|
|
{
|
|
|
|
SetTitle("Untitled");
|
|
|
|
DeleteContents(false);
|
|
|
|
memset(m_strPathName, 0, sizeof(m_strPathName)); // no path name yet
|
2013-08-09 06:57:18 +02:00
|
|
|
strcpy(m_strAuthor, lcGetProfileString(LC_PROFILE_DEFAULT_AUTHOR_NAME));
|
2011-09-07 23:06:51 +02:00
|
|
|
SetModifiedFlag(false); // make clean
|
|
|
|
LoadDefaults(true);
|
|
|
|
CheckPoint("");
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Project::OpenProject(const char* FileName)
|
|
|
|
{
|
|
|
|
if (!SaveModified())
|
|
|
|
return false; // Leave the original one
|
|
|
|
|
|
|
|
bool WasModified = IsModified();
|
|
|
|
SetModifiedFlag(false); // Not dirty for open
|
|
|
|
|
|
|
|
if (!OnOpenDocument(FileName))
|
|
|
|
{
|
|
|
|
// Check if we corrupted the original document
|
|
|
|
if (!IsModified())
|
|
|
|
SetModifiedFlag(WasModified);
|
|
|
|
else
|
|
|
|
OnNewDocument();
|
|
|
|
|
|
|
|
return false; // Open failed
|
|
|
|
}
|
|
|
|
|
|
|
|
SetPathName(FileName, true);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Project::OnOpenDocument (const char* lpszPathName)
|
|
|
|
{
|
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;
|
|
|
|
|
|
|
|
// Delete the current project.
|
|
|
|
DeleteContents(false);
|
|
|
|
LoadDefaults(datfile || mpdfile);
|
|
|
|
SetModifiedFlag(true); // dirty during loading
|
|
|
|
|
|
|
|
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
|
2012-10-18 20:57:21 +02:00
|
|
|
FileReadLDraw(&file, mat, &ok, 16, &step, FileArray);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
m_nCurStep = step;
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateTime(false, m_nCurStep, 255);
|
|
|
|
gMainWindow->UpdateFocusObject(GetFocusObject());
|
2011-09-07 23:06:51 +02:00
|
|
|
UpdateSelection();
|
|
|
|
CalculateStep();
|
2012-12-11 00:30:28 +01:00
|
|
|
|
2012-12-13 01:20:40 +01:00
|
|
|
ZoomExtents(0, m_ViewList.GetSize());
|
2012-12-11 00:30:28 +01:00
|
|
|
UpdateAllViews();
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
bSuccess = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Load a LeoCAD file.
|
|
|
|
bSuccess = FileLoad(&file, false, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Clean up.
|
|
|
|
if (mpdfile)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < FileArray.GetSize(); i++)
|
|
|
|
delete FileArray[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
file.Close();
|
|
|
|
|
|
|
|
if (bSuccess == false)
|
|
|
|
{
|
|
|
|
// MessageBox("Failed to load.");
|
|
|
|
DeleteContents(false); // remove failed contents
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
CheckPoint("");
|
|
|
|
m_nSaveTimer = 0;
|
|
|
|
|
|
|
|
SetModifiedFlag(false); // start off with unmodified
|
|
|
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Undo/Redo support
|
|
|
|
|
|
|
|
// Save current state.
|
|
|
|
void Project::CheckPoint (const char* text)
|
|
|
|
{
|
|
|
|
LC_UNDOINFO* pTmp;
|
|
|
|
LC_UNDOINFO* pUndo = new LC_UNDOINFO;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
strcpy(pUndo->strText, text);
|
|
|
|
FileSave(&pUndo->file, true);
|
|
|
|
|
|
|
|
for (pTmp = m_pUndoList, i = 0; pTmp; pTmp = pTmp->pNext, i++)
|
|
|
|
if ((i == 30) && (pTmp->pNext != NULL))
|
|
|
|
{
|
|
|
|
delete pTmp->pNext;
|
|
|
|
pTmp->pNext = NULL;
|
|
|
|
m_bUndoOriginal = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
pUndo->pNext = m_pUndoList;
|
|
|
|
m_pUndoList = pUndo;
|
|
|
|
|
|
|
|
while (m_pRedoList)
|
|
|
|
{
|
|
|
|
pUndo = m_pRedoList;
|
|
|
|
m_pRedoList = m_pRedoList->pNext;
|
|
|
|
delete pUndo;
|
|
|
|
}
|
|
|
|
m_pRedoList = NULL;
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateUndoRedo(m_pUndoList->pNext ? m_pUndoList->strText : NULL, NULL);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
2013-08-16 18:16:45 +02:00
|
|
|
void Project::AddView (View* pView)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2011-09-17 01:59:55 +02:00
|
|
|
m_ViewList.Add (pView);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2011-09-17 01:59:55 +02:00
|
|
|
pView->MakeCurrent ();
|
|
|
|
RenderInitialize ();
|
2012-02-02 04:30:26 +01:00
|
|
|
|
|
|
|
if (!m_ActiveView)
|
|
|
|
m_ActiveView = pView;
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
2013-08-16 18:16:45 +02:00
|
|
|
void Project::RemoveView (View* pView)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2011-09-17 01:59:55 +02:00
|
|
|
if (pView == m_ActiveView)
|
|
|
|
m_ActiveView = NULL;
|
|
|
|
|
2013-08-16 01:43:18 +02:00
|
|
|
m_ViewList.Remove(pView);
|
2011-09-17 01:59:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Project::UpdateAllViews()
|
|
|
|
{
|
|
|
|
for (int i = 0; i < m_ViewList.GetSize (); i++)
|
|
|
|
m_ViewList[i]->Redraw ();
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
2011-09-20 03:26:31 +02:00
|
|
|
// Returns true if the active view changed.
|
|
|
|
bool Project::SetActiveView(View* view)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2012-01-22 04:52:33 +01:00
|
|
|
m_ActiveView = view;
|
|
|
|
return false;
|
|
|
|
/*
|
2011-09-17 01:59:55 +02:00
|
|
|
if (view == m_ActiveView)
|
2011-09-20 03:26:31 +02:00
|
|
|
return false;
|
2011-09-17 01:59:55 +02:00
|
|
|
|
|
|
|
// Camera* OldCamera = NULL;
|
|
|
|
View* OldView = m_ActiveView;
|
|
|
|
m_ActiveView = view;
|
|
|
|
|
|
|
|
if (OldView)
|
|
|
|
{
|
|
|
|
OldView->Redraw();
|
|
|
|
// OldCamera = OldView->GetCamera();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (view)
|
|
|
|
{
|
|
|
|
view->Redraw();
|
|
|
|
// SystemUpdateCurrentCamera(OldCamera, m_ActiveView->GetCamera(), m_ActiveModel->m_Cameras);
|
|
|
|
}
|
2011-09-20 03:26:31 +02:00
|
|
|
|
|
|
|
return true;
|
2012-01-22 04:52:33 +01:00
|
|
|
*/
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Project rendering
|
|
|
|
|
|
|
|
// Only this function should be called.
|
2011-09-20 03:26:31 +02:00
|
|
|
void Project::Render(View* view, bool ToMemory)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
glViewport(0, 0, view->mWidth, view->mHeight);
|
2011-09-20 03:26:31 +02:00
|
|
|
|
|
|
|
RenderBackground(view);
|
|
|
|
|
|
|
|
// Setup the projection and camera matrices.
|
2013-08-09 06:57:18 +02:00
|
|
|
float ratio = (float)view->mWidth / (float)view->mHeight;
|
2012-08-20 06:05:56 +02:00
|
|
|
view->mCamera->LoadProjection(ratio);
|
2011-09-20 03:26:31 +02:00
|
|
|
|
|
|
|
if (ToMemory)
|
2012-01-28 02:05:23 +01:00
|
|
|
RenderScenePieces(view);
|
2011-09-20 03:26:31 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
if ((m_nDetail & LC_DET_FAST) && (m_nTracking != LC_TRACK_NONE))
|
2012-01-28 02:05:23 +01:00
|
|
|
RenderSceneBoxes(view);
|
2011-09-20 03:26:31 +02:00
|
|
|
else
|
2012-01-28 02:05:23 +01:00
|
|
|
RenderScenePieces(view);
|
|
|
|
|
|
|
|
RenderSceneObjects(view);
|
|
|
|
|
2012-01-30 08:31:29 +01:00
|
|
|
if (m_OverlayActive || ((m_nCurAction == LC_ACTION_SELECT) && (m_nTracking == LC_TRACK_LEFT) && (m_ActiveView == view)))
|
2012-01-28 02:05:23 +01:00
|
|
|
RenderOverlays(view);
|
|
|
|
|
|
|
|
RenderViewports(view);
|
2011-09-20 03:26:31 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Project::RenderBackground(View* view)
|
|
|
|
{
|
2012-01-28 02:05:23 +01:00
|
|
|
if ((m_nScene & (LC_SCENE_GRADIENT | LC_SCENE_BG)) == 0)
|
2011-09-20 03:26:31 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
glClearColor(m_fBackground[0], m_fBackground[1], m_fBackground[2], 0.0f);
|
2011-09-20 03:26:31 +02:00
|
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
2011-09-07 23:06:51 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-09-20 03:26:31 +02:00
|
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2011-09-20 03:26:31 +02:00
|
|
|
glDepthMask(GL_FALSE);
|
|
|
|
glDisable(GL_DEPTH_TEST);
|
|
|
|
glDisable(GL_LIGHTING);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
float ViewWidth = (float)view->mWidth;
|
|
|
|
float ViewHeight = (float)view->mHeight;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2011-09-20 03:26:31 +02:00
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glLoadIdentity();
|
|
|
|
glOrtho(0.0f, ViewWidth, 0.0f, ViewHeight, -1.0f, 1.0f);
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glLoadIdentity();
|
|
|
|
glTranslatef(0.375f, 0.375f, 0.0f);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2011-09-20 03:26:31 +02:00
|
|
|
// Draw gradient quad.
|
|
|
|
if (m_nScene & LC_SCENE_GRADIENT)
|
|
|
|
{
|
|
|
|
glShadeModel(GL_SMOOTH);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2011-09-20 03:26:31 +02:00
|
|
|
float Verts[4][2];
|
|
|
|
float Colors[4][4];
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2011-09-20 03:26:31 +02:00
|
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
|
|
glVertexPointer(2, GL_FLOAT, 0, Verts);
|
|
|
|
glEnableClientState(GL_COLOR_ARRAY);
|
|
|
|
glColorPointer(4, GL_FLOAT, 0, Colors);
|
|
|
|
|
|
|
|
Colors[0][0] = m_fGradient1[0]; Colors[0][1] = m_fGradient1[1]; Colors[0][2] = m_fGradient1[2]; Colors[0][3] = 1.0f;
|
|
|
|
Verts[0][0] = ViewWidth; Verts[0][1] = ViewHeight;
|
|
|
|
Colors[1][0] = m_fGradient1[0]; Colors[1][1] = m_fGradient1[1]; Colors[1][2] = m_fGradient1[2]; Colors[1][3] = 1.0f;
|
|
|
|
Verts[1][0] = 0; Verts[1][1] = ViewHeight;
|
|
|
|
Colors[2][0] = m_fGradient2[0]; Colors[2][1] = m_fGradient2[1]; Colors[2][2] = m_fGradient2[2]; Colors[2][3] = 1.0f;
|
|
|
|
Verts[2][0] = 0; Verts[2][1] = 0;
|
|
|
|
Colors[3][0] = m_fGradient2[0]; Colors[3][1] = m_fGradient2[1]; Colors[3][2] = m_fGradient2[2]; Colors[3][3] = 1.0f;
|
|
|
|
Verts[3][0] = ViewWidth; Verts[3][1] = 0;
|
|
|
|
|
|
|
|
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
|
|
|
|
|
|
|
glDisableClientState(GL_VERTEX_ARRAY);
|
|
|
|
glDisableClientState(GL_COLOR_ARRAY);
|
|
|
|
|
|
|
|
glShadeModel(GL_FLAT);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Draw the background picture.
|
|
|
|
if (m_nScene & LC_SCENE_BG)
|
|
|
|
{
|
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
2012-10-12 20:21:45 +02:00
|
|
|
glBindTexture(GL_TEXTURE_2D, m_pBackground->mTexture);
|
2011-09-20 03:26:31 +02:00
|
|
|
|
|
|
|
float Verts[4][2];
|
|
|
|
float Coords[4][2];
|
|
|
|
|
|
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
|
|
glVertexPointer(2, GL_FLOAT, 0, Verts);
|
|
|
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
|
|
glTexCoordPointer(2, GL_FLOAT, 0, Coords);
|
|
|
|
|
|
|
|
float tw = 1.0f, th = 1.0f;
|
|
|
|
if (m_nScene & LC_SCENE_BG_TILE)
|
|
|
|
{
|
2012-10-12 20:21:45 +02:00
|
|
|
tw = ViewWidth / m_pBackground->mWidth;
|
|
|
|
th = ViewHeight / m_pBackground->mHeight;
|
2011-09-20 03:26:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Coords[0][0] = 0; Coords[0][1] = 0;
|
|
|
|
Verts[0][0] = 0; Verts[0][1] = ViewHeight;
|
|
|
|
Coords[1][0] = tw; Coords[1][1] = 0;
|
|
|
|
Verts[1][0] = ViewWidth; Verts[1][1] = ViewHeight;
|
2013-01-06 20:24:25 +01:00
|
|
|
Coords[2][0] = tw; Coords[2][1] = th;
|
2011-09-20 03:26:31 +02:00
|
|
|
Verts[2][0] = ViewWidth; Verts[2][1] = 0;
|
|
|
|
Coords[3][0] = 0; Coords[3][1] = th;
|
|
|
|
Verts[3][0] = 0; Verts[3][1] = 0;
|
|
|
|
|
|
|
|
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
|
|
|
|
|
|
|
glDisableClientState(GL_VERTEX_ARRAY);
|
|
|
|
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
|
|
|
|
|
|
glDisable(GL_TEXTURE_2D);
|
|
|
|
}
|
|
|
|
|
|
|
|
glEnable(GL_DEPTH_TEST);
|
|
|
|
glDepthMask(GL_TRUE);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
2012-05-17 01:48:16 +02:00
|
|
|
struct lcTranslucentRenderSection
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2012-05-17 01:48:16 +02:00
|
|
|
float Distance;
|
2011-09-07 23:06:51 +02:00
|
|
|
Piece* piece;
|
2012-05-17 01:48:16 +02:00
|
|
|
};
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-16 01:43:18 +02:00
|
|
|
int lcTranslucentRenderCompare(const lcTranslucentRenderSection& a, const lcTranslucentRenderSection& b)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2012-05-17 01:48:16 +02:00
|
|
|
if (a.Distance > b.Distance)
|
|
|
|
return 1;
|
2011-09-07 23:06:51 +02:00
|
|
|
else
|
2012-05-17 01:48:16 +02:00
|
|
|
return -1;
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
2013-08-16 01:43:18 +02:00
|
|
|
int lcOpaqueRenderCompare(Piece* const& a, Piece* const& b)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2012-05-17 23:52:20 +02:00
|
|
|
if (a->mPieceInfo > b->mPieceInfo)
|
2012-05-17 01:48:16 +02:00
|
|
|
return 1;
|
2011-09-07 23:06:51 +02:00
|
|
|
else
|
2012-05-17 01:48:16 +02:00
|
|
|
return -1;
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
2012-01-28 02:05:23 +01:00
|
|
|
void Project::RenderScenePieces(View* view)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
float AspectRatio = (float)view->mWidth / (float)view->mHeight;
|
2012-08-20 06:05:56 +02:00
|
|
|
view->mCamera->LoadProjection(AspectRatio);
|
2012-01-28 02:05:23 +01:00
|
|
|
|
|
|
|
if (m_nSnap & LC_DRAW_GRID)
|
|
|
|
{
|
2012-09-10 01:42:57 +02:00
|
|
|
glColor4f(1.0f - m_fBackground[0], 1.0f - m_fBackground[1], 1.0f - m_fBackground[2], 1.0f);
|
2012-01-28 02:05:23 +01:00
|
|
|
glCallList (m_nGridList);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
2012-01-28 02:05:23 +01:00
|
|
|
if (m_nDetail & LC_DET_LIGHTING)
|
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, m_fAmbient);
|
|
|
|
|
2012-01-28 02:05:23 +01:00
|
|
|
int index = 0;
|
|
|
|
Light *pLight;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-01-28 02:05:23 +01:00
|
|
|
for (pLight = m_pLights; pLight; pLight = pLight->m_pNext, index++)
|
|
|
|
pLight->Setup (index);
|
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 (m_nScene & LC_SCENE_FOG)
|
2013-08-09 06:57:18 +02:00
|
|
|
{
|
|
|
|
glFogi(GL_FOG_MODE, GL_EXP);
|
|
|
|
glFogf(GL_FOG_DENSITY, m_fFogDensity);
|
|
|
|
glFogfv(GL_FOG_COLOR, m_fFogColor);
|
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
|
|
|
|
2012-01-28 02:05:23 +01:00
|
|
|
if (m_nScene & LC_SCENE_FLOOR)
|
2012-08-20 06:05:56 +02:00
|
|
|
m_pTerrain->Render(view->mCamera, AspectRatio);
|
2012-01-28 02:05:23 +01:00
|
|
|
|
2013-08-16 01:43:18 +02:00
|
|
|
lcArray<Piece*> OpaquePieces(512);
|
|
|
|
lcArray<lcTranslucentRenderSection> TranslucentSections(512);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-08-20 06:05:56 +02:00
|
|
|
const lcMatrix44& WorldView = view->mCamera->mWorldView;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-05-17 01:48:16 +02:00
|
|
|
for (Piece* pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
2012-01-28 02:05:23 +01:00
|
|
|
{
|
|
|
|
if (!pPiece->IsVisible(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation))
|
|
|
|
continue;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-05-17 01:48:16 +02:00
|
|
|
bool Translucent = lcIsColorTranslucent(pPiece->mColorIndex);
|
2012-05-17 23:52:20 +02:00
|
|
|
PieceInfo* Info = pPiece->mPieceInfo;
|
2012-05-17 01:48:16 +02:00
|
|
|
|
2012-10-03 00:16:36 +02:00
|
|
|
if ((Info->mFlags & (LC_PIECE_HAS_SOLID | LC_PIECE_HAS_LINES)) || ((Info->mFlags & LC_PIECE_HAS_DEFAULT) && !Translucent))
|
2013-08-16 01:43:18 +02:00
|
|
|
OpaquePieces.AddSorted(pPiece, lcOpaqueRenderCompare);
|
2012-05-17 01:48:16 +02:00
|
|
|
|
2012-10-03 00:16:36 +02:00
|
|
|
if ((Info->mFlags & LC_PIECE_HAS_TRANSLUCENT) || ((Info->mFlags & LC_PIECE_HAS_DEFAULT) && Translucent))
|
2012-05-17 01:48:16 +02:00
|
|
|
{
|
2012-05-29 01:33:22 +02:00
|
|
|
lcVector3 Pos = lcMul31(pPiece->mPosition, WorldView);
|
2012-05-17 01:48:16 +02:00
|
|
|
|
|
|
|
lcTranslucentRenderSection RenderSection;
|
|
|
|
|
|
|
|
RenderSection.Distance = Pos[2];
|
|
|
|
RenderSection.piece = pPiece;
|
|
|
|
|
2013-08-16 01:43:18 +02:00
|
|
|
TranslucentSections.AddSorted(RenderSection, lcTranslucentRenderCompare);
|
2012-05-17 01:48:16 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
lcMesh* PreviousMesh = NULL;
|
|
|
|
bool PreviousSelected = false;
|
2012-10-12 01:55:55 +02:00
|
|
|
lcTexture* PreviousTexture = NULL;
|
2012-06-22 00:03:30 +02:00
|
|
|
char* ElementsOffset = NULL;
|
2012-10-12 01:55:55 +02:00
|
|
|
char* BaseBufferOffset = NULL;
|
2012-11-02 02:17:42 +01:00
|
|
|
char* PreviousOffset = (char*)(~0);
|
2012-05-17 01:48:16 +02:00
|
|
|
|
|
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
|
|
|
|
|
|
for (int PieceIdx = 0; PieceIdx < OpaquePieces.GetSize(); PieceIdx++)
|
|
|
|
{
|
|
|
|
Piece* piece = OpaquePieces[PieceIdx];
|
2012-05-17 23:52:20 +02:00
|
|
|
lcMesh* Mesh = piece->mPieceInfo->mMesh;
|
2012-05-17 01:48:16 +02:00
|
|
|
|
|
|
|
glPushMatrix();
|
2012-05-17 23:52:20 +02:00
|
|
|
glMultMatrixf(piece->mModelWorld);
|
2012-05-17 01:48:16 +02:00
|
|
|
|
|
|
|
if (PreviousMesh != Mesh)
|
2012-01-28 02:05:23 +01:00
|
|
|
{
|
2012-05-17 01:48:16 +02:00
|
|
|
if (GL_HasVertexBufferObject())
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
glBindBuffer(GL_ARRAY_BUFFER_ARB, Mesh->mVertexBuffer.mBuffer);
|
2012-10-12 01:55:55 +02:00
|
|
|
BaseBufferOffset = NULL;
|
2013-08-09 06:57:18 +02:00
|
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, Mesh->mIndexBuffer.mBuffer);
|
2012-05-17 01:48:16 +02:00
|
|
|
ElementsOffset = NULL;
|
2012-01-28 02:05:23 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-10-12 01:55:55 +02:00
|
|
|
BaseBufferOffset = (char*)Mesh->mVertexBuffer.mData;
|
2012-05-17 01:48:16 +02:00
|
|
|
ElementsOffset = (char*)Mesh->mIndexBuffer.mData;
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
2012-05-17 01:48:16 +02:00
|
|
|
PreviousMesh = Mesh;
|
2012-11-09 01:07:53 +01:00
|
|
|
PreviousOffset = (char*)(~0);
|
2012-05-17 01:48:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (piece->IsSelected())
|
|
|
|
{
|
|
|
|
if (!PreviousSelected)
|
|
|
|
glLineWidth(2.0f * m_fLineWidth);
|
|
|
|
|
|
|
|
PreviousSelected = true;
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
2012-01-28 02:05:23 +01:00
|
|
|
else
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2012-05-17 01:48:16 +02:00
|
|
|
if (PreviousSelected)
|
|
|
|
glLineWidth(m_fLineWidth);
|
|
|
|
|
|
|
|
PreviousSelected = false;
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
2012-05-17 01:48:16 +02:00
|
|
|
|
|
|
|
for (int SectionIdx = 0; SectionIdx < Mesh->mNumSections; SectionIdx++)
|
|
|
|
{
|
|
|
|
lcMeshSection* Section = &Mesh->mSections[SectionIdx];
|
|
|
|
int ColorIdx = Section->ColorIndex;
|
|
|
|
|
|
|
|
if (Section->PrimitiveType == GL_TRIANGLES)
|
|
|
|
{
|
|
|
|
if (ColorIdx == gDefaultColor)
|
|
|
|
ColorIdx = piece->mColorIndex;
|
|
|
|
|
|
|
|
if (lcIsColorTranslucent(ColorIdx))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
lcSetColor(ColorIdx);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (piece->IsFocused())
|
|
|
|
lcSetColorFocused();
|
|
|
|
else if (piece->IsSelected())
|
|
|
|
lcSetColorSelected();
|
|
|
|
else if (ColorIdx == gEdgeColor)
|
|
|
|
lcSetEdgeColor(piece->mColorIndex);
|
|
|
|
else
|
|
|
|
lcSetColor(ColorIdx);
|
|
|
|
}
|
|
|
|
|
2012-10-12 01:55:55 +02:00
|
|
|
char* BufferOffset = BaseBufferOffset;
|
|
|
|
lcTexture* Texture = Section->Texture;
|
|
|
|
|
|
|
|
if (!Texture)
|
|
|
|
{
|
|
|
|
if (PreviousTexture)
|
|
|
|
{
|
|
|
|
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
|
|
glDisable(GL_TEXTURE_2D);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
BufferOffset += Mesh->mNumVertices * sizeof(lcVertex);
|
|
|
|
|
|
|
|
if (Texture != PreviousTexture)
|
|
|
|
{
|
|
|
|
glBindTexture(GL_TEXTURE_2D, Section->Texture->mTexture);
|
|
|
|
|
|
|
|
if (!PreviousTexture)
|
|
|
|
{
|
|
|
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
2012-10-12 20:21:45 +02:00
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
|
2012-10-12 01:55:55 +02:00
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
PreviousTexture = Texture;
|
|
|
|
|
|
|
|
if (PreviousOffset != BufferOffset)
|
|
|
|
{
|
|
|
|
if (!Texture)
|
|
|
|
glVertexPointer(3, GL_FLOAT, 0, BufferOffset);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
glVertexPointer(3, GL_FLOAT, sizeof(lcVertexTextured), BufferOffset);
|
|
|
|
glTexCoordPointer(2, GL_FLOAT, sizeof(lcVertexTextured), BufferOffset + sizeof(lcVector3));
|
|
|
|
}
|
|
|
|
|
|
|
|
PreviousOffset = BufferOffset;
|
|
|
|
}
|
|
|
|
|
2012-05-17 01:48:16 +02:00
|
|
|
glDrawElements(Section->PrimitiveType, Section->NumIndices, Mesh->mIndexType, ElementsOffset + Section->IndexOffset);
|
|
|
|
}
|
|
|
|
|
|
|
|
glPopMatrix();
|
2012-01-28 02:05:23 +01:00
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-05-17 01:48:16 +02:00
|
|
|
if (PreviousSelected)
|
|
|
|
glLineWidth(m_fLineWidth);
|
|
|
|
|
|
|
|
if (TranslucentSections.GetSize())
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2012-05-17 01:48:16 +02:00
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
glEnable(GL_BLEND);
|
|
|
|
glDepthMask(GL_FALSE);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-05-17 01:48:16 +02:00
|
|
|
for (int PieceIdx = 0; PieceIdx < TranslucentSections.GetSize(); PieceIdx++)
|
|
|
|
{
|
|
|
|
Piece* piece = TranslucentSections[PieceIdx].piece;
|
2012-05-17 23:52:20 +02:00
|
|
|
lcMesh* Mesh = piece->mPieceInfo->mMesh;
|
2012-05-17 01:48:16 +02:00
|
|
|
|
|
|
|
glPushMatrix();
|
2012-05-17 23:52:20 +02:00
|
|
|
glMultMatrixf(piece->mModelWorld);
|
2012-05-17 01:48:16 +02:00
|
|
|
|
|
|
|
if (PreviousMesh != Mesh)
|
|
|
|
{
|
|
|
|
if (GL_HasVertexBufferObject())
|
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
glBindBuffer(GL_ARRAY_BUFFER_ARB, Mesh->mVertexBuffer.mBuffer);
|
2012-10-12 01:55:55 +02:00
|
|
|
BaseBufferOffset = NULL;
|
2013-08-09 06:57:18 +02:00
|
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, Mesh->mIndexBuffer.mBuffer);
|
2012-05-17 01:48:16 +02:00
|
|
|
ElementsOffset = NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-10-12 01:55:55 +02:00
|
|
|
BaseBufferOffset = (char*)Mesh->mVertexBuffer.mData;
|
2012-05-17 01:48:16 +02:00
|
|
|
ElementsOffset = (char*)Mesh->mIndexBuffer.mData;
|
|
|
|
}
|
|
|
|
|
|
|
|
PreviousMesh = Mesh;
|
2012-12-23 01:48:22 +01:00
|
|
|
PreviousOffset = (char*)(~0);
|
2012-05-17 01:48:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
for (int SectionIdx = 0; SectionIdx < Mesh->mNumSections; SectionIdx++)
|
|
|
|
{
|
|
|
|
lcMeshSection* Section = &Mesh->mSections[SectionIdx];
|
|
|
|
int ColorIdx = Section->ColorIndex;
|
|
|
|
|
|
|
|
if (Section->PrimitiveType != GL_TRIANGLES)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (ColorIdx == gDefaultColor)
|
|
|
|
ColorIdx = piece->mColorIndex;
|
|
|
|
|
|
|
|
if (!lcIsColorTranslucent(ColorIdx))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
lcSetColor(ColorIdx);
|
|
|
|
|
2012-10-12 01:55:55 +02:00
|
|
|
char* BufferOffset = BaseBufferOffset;
|
|
|
|
lcTexture* Texture = Section->Texture;
|
|
|
|
|
|
|
|
if (!Texture)
|
|
|
|
{
|
|
|
|
if (PreviousTexture)
|
|
|
|
{
|
|
|
|
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
|
|
glDisable(GL_TEXTURE_2D);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
BufferOffset += Mesh->mNumVertices * sizeof(lcVertex);
|
|
|
|
|
|
|
|
if (Texture != PreviousTexture)
|
|
|
|
{
|
|
|
|
glBindTexture(GL_TEXTURE_2D, Section->Texture->mTexture);
|
|
|
|
|
|
|
|
if (!PreviousTexture)
|
|
|
|
{
|
|
|
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
2012-10-12 20:21:45 +02:00
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
|
2012-10-12 01:55:55 +02:00
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
PreviousTexture = Texture;
|
|
|
|
|
|
|
|
if (PreviousOffset != BufferOffset)
|
|
|
|
{
|
|
|
|
if (!Texture)
|
|
|
|
glVertexPointer(3, GL_FLOAT, 0, BufferOffset);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
glVertexPointer(3, GL_FLOAT, sizeof(lcVertexTextured), BufferOffset);
|
|
|
|
glTexCoordPointer(2, GL_FLOAT, sizeof(lcVertexTextured), BufferOffset + sizeof(lcVector3));
|
|
|
|
}
|
|
|
|
|
|
|
|
PreviousOffset = BufferOffset;
|
|
|
|
}
|
|
|
|
|
2012-05-17 01:48:16 +02:00
|
|
|
glDrawElements(Section->PrimitiveType, Section->NumIndices, Mesh->mIndexType, ElementsOffset + Section->IndexOffset);
|
|
|
|
}
|
|
|
|
|
|
|
|
glPopMatrix();
|
|
|
|
}
|
|
|
|
|
|
|
|
glDepthMask(GL_TRUE);
|
|
|
|
glDisable(GL_BLEND);
|
|
|
|
}
|
|
|
|
|
2012-10-12 01:55:55 +02:00
|
|
|
glDisableClientState(GL_VERTEX_ARRAY);
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
if (m_nDetail & LC_DET_LIGHTING)
|
|
|
|
{
|
|
|
|
glDisable(GL_LIGHTING);
|
|
|
|
glDisable(GL_COLOR_MATERIAL);
|
|
|
|
glShadeModel(GL_FLAT);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_nScene & LC_SCENE_FOG)
|
|
|
|
glDisable(GL_FOG);
|
|
|
|
|
2012-10-12 01:55:55 +02:00
|
|
|
if (PreviousTexture)
|
|
|
|
{
|
|
|
|
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
|
|
glDisable(GL_TEXTURE_2D);
|
|
|
|
}
|
|
|
|
|
2012-05-17 01:48:16 +02:00
|
|
|
if (GL_HasVertexBufferObject())
|
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
glBindBuffer(GL_ARRAY_BUFFER_ARB, 0);
|
|
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
|
2012-05-17 01:48:16 +02:00
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-10-12 01:55:55 +02:00
|
|
|
glVertexPointer(3, GL_FLOAT, 0, NULL);
|
|
|
|
glTexCoordPointer(2, GL_FLOAT, 0, NULL);
|
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::RenderSceneBoxes(View* view)
|
|
|
|
{
|
|
|
|
Piece* pPiece;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-01-28 02:05:23 +01:00
|
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-01-28 02:05:23 +01:00
|
|
|
for (pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
|
|
|
if (pPiece->IsVisible(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation))
|
|
|
|
pPiece->RenderBox(true, m_fLineWidth);
|
2011-09-20 01:03:28 +02:00
|
|
|
|
2012-01-28 02:05:23 +01:00
|
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-01-28 02:05:23 +01:00
|
|
|
void Project::RenderSceneObjects(View* view)
|
|
|
|
{
|
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
|
|
|
|
|
2012-01-28 02:05:23 +01:00
|
|
|
// Draw cameras & lights
|
2013-08-09 06:57:18 +02:00
|
|
|
if (m_nCurAction == LC_ACTION_INSERT || mDropPiece)
|
2012-01-28 02:05:23 +01:00
|
|
|
{
|
2012-06-16 02:17:52 +02:00
|
|
|
lcVector3 Pos;
|
|
|
|
lcVector4 Rot;
|
2012-01-28 02:05:23 +01:00
|
|
|
GetPieceInsertPosition(view, m_nDownX, m_nDownY, Pos, Rot);
|
2013-08-09 06:57:18 +02:00
|
|
|
PieceInfo* PreviewPiece = mDropPiece ? mDropPiece : m_pCurPiece;
|
2012-01-28 02:05:23 +01:00
|
|
|
|
|
|
|
glPushMatrix();
|
|
|
|
glTranslatef(Pos[0], Pos[1], Pos[2]);
|
|
|
|
glRotatef(Rot[3], Rot[0], Rot[1], Rot[2]);
|
|
|
|
glLineWidth(2*m_fLineWidth);
|
2013-08-09 06:57:18 +02:00
|
|
|
PreviewPiece->RenderPiece(gMainWindow->mColorIndex);
|
2012-01-28 02:05:23 +01:00
|
|
|
glLineWidth(m_fLineWidth);
|
|
|
|
glPopMatrix();
|
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-01-28 02:05:23 +01:00
|
|
|
if (m_nDetail & LC_DET_LIGHTING)
|
|
|
|
{
|
|
|
|
glDisable (GL_LIGHTING);
|
|
|
|
int index = 0;
|
|
|
|
Light *pLight;
|
2013-01-06 20:24:25 +01:00
|
|
|
|
2012-01-28 02:05:23 +01:00
|
|
|
for (pLight = m_pLights; pLight; pLight = pLight->m_pNext, index++)
|
|
|
|
glDisable ((GLenum)(GL_LIGHT0+index));
|
|
|
|
}
|
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
|
|
|
{
|
2012-08-22 03:13:32 +02:00
|
|
|
Camera* pCamera = mCameras[CameraIdx];
|
|
|
|
|
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
|
|
|
|
2012-01-28 02:05:23 +01:00
|
|
|
pCamera->Render(m_fLineWidth);
|
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-01-28 02:05:23 +01:00
|
|
|
for (Light* pLight = m_pLights; pLight; pLight = pLight->m_pNext)
|
|
|
|
if (pLight->IsVisible ())
|
|
|
|
pLight->Render(m_fLineWidth);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-01-28 02:05:23 +01:00
|
|
|
// Draw axis icon
|
|
|
|
if (m_nSnap & LC_DRAW_AXIS)
|
|
|
|
{
|
|
|
|
// glClear(GL_DEPTH_BUFFER_BIT);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-06-16 02:17:52 +02:00
|
|
|
lcMatrix44 Mats[3];
|
2012-08-20 06:05:56 +02:00
|
|
|
Mats[0] = view->mCamera->mWorldView;
|
2012-06-16 02:17:52 +02:00
|
|
|
Mats[0].SetTranslation(lcVector3(0, 0, 0));
|
|
|
|
Mats[1] = lcMul(lcMatrix44(lcVector4(0, 1, 0, 0), lcVector4(1, 0, 0, 0), lcVector4(0, 0, 1, 0), lcVector4(0, 0, 0, 1)), Mats[0]);
|
|
|
|
Mats[2] = lcMul(lcMatrix44(lcVector4(0, 0, 1, 0), lcVector4(0, 1, 0, 0), lcVector4(1, 0, 0, 0), lcVector4(0, 0, 0, 1)), Mats[0]);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-01-06 20:24:25 +01:00
|
|
|
lcVector3 pts[3] =
|
2012-06-16 02:17:52 +02:00
|
|
|
{
|
|
|
|
lcMul30(lcVector3(20, 0, 0), Mats[0]),
|
|
|
|
lcMul30(lcVector3(0, 20, 0), Mats[0]),
|
|
|
|
lcMul30(lcVector3(0, 0, 20), Mats[0]),
|
|
|
|
};
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-01-28 02:05:23 +01:00
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glLoadIdentity();
|
2013-08-09 06:57:18 +02:00
|
|
|
glOrtho(0, view->mWidth, 0, view->mHeight, -50, 50);
|
2012-01-28 02:05:23 +01:00
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glLoadIdentity();
|
|
|
|
glTranslatef(25.375f, 25.375f, 0.0f);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-01-28 02:05:23 +01:00
|
|
|
// Draw the arrows.
|
2012-09-10 01:42:57 +02:00
|
|
|
lcVector3 Verts[11];
|
|
|
|
Verts[0] = lcVector3(0.0f, 0.0f, 0.0f);
|
|
|
|
|
|
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
|
|
glVertexPointer(3, GL_FLOAT, 0, Verts);
|
|
|
|
|
2012-01-28 02:05:23 +01:00
|
|
|
for (int i = 0; i < 3; i++)
|
|
|
|
{
|
|
|
|
switch (i)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
glColor4f(0.8f, 0.0f, 0.0f, 1.0f);
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
glColor4f(0.0f, 0.8f, 0.0f, 1.0f);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
glColor4f(0.0f, 0.0f, 0.8f, 1.0f);
|
|
|
|
break;
|
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-09-10 01:42:57 +02:00
|
|
|
Verts[1] = pts[i];
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-01-28 02:05:23 +01:00
|
|
|
for (int j = 0; j < 9; j++)
|
2012-09-10 01:42:57 +02:00
|
|
|
Verts[j+2] = lcMul30(lcVector3(12.0f, cosf(LC_2PI * j / 8) * 3.0f, sinf(LC_2PI * j / 8) * 3.0f), Mats[i]);
|
|
|
|
|
|
|
|
glDrawArrays(GL_LINES, 0, 2);
|
|
|
|
glDrawArrays(GL_TRIANGLE_FAN, 1, 10);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
2012-09-10 01:42:57 +02:00
|
|
|
glDisableClientState(GL_VERTEX_ARRAY);
|
|
|
|
|
2012-01-28 02:05:23 +01:00
|
|
|
// Draw the text.
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
|
|
|
m_pScreenFont->MakeCurrent();
|
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
glEnable(GL_ALPHA_TEST);
|
|
|
|
|
|
|
|
glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
|
|
|
|
m_pScreenFont->PrintText(pts[0][0], pts[0][1], 40.0f, "X");
|
|
|
|
m_pScreenFont->PrintText(pts[1][0], pts[1][1], 40.0f, "Y");
|
|
|
|
m_pScreenFont->PrintText(pts[2][0], pts[2][1], 40.0f, "Z");
|
|
|
|
|
|
|
|
glDisable(GL_TEXTURE_2D);
|
|
|
|
glDisable(GL_ALPHA_TEST);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-28 02:05:23 +01:00
|
|
|
void Project::RenderOverlays(View* view)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
if (mDropPiece)
|
|
|
|
return;
|
|
|
|
|
2013-04-10 02:52:06 +02:00
|
|
|
if (((m_nCurAction == LC_ACTION_SELECT) && (m_nTracking == LC_TRACK_LEFT) && (m_ActiveView == view) && (m_OverlayMode == LC_OVERLAY_NONE)) ||
|
|
|
|
(m_nCurAction == LC_ACTION_ZOOM_REGION))
|
2012-01-28 02:05:23 +01:00
|
|
|
{
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glLoadIdentity();
|
2013-08-09 06:57:18 +02:00
|
|
|
glOrtho(0.0f, view->mWidth, 0.0f, view->mHeight, -1.0f, 1.0f);
|
2012-01-28 02:05:23 +01:00
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glLoadIdentity();
|
|
|
|
glTranslatef(0.375f, 0.375f, 0.0f);
|
|
|
|
|
|
|
|
glDisable(GL_DEPTH_TEST);
|
|
|
|
|
|
|
|
float pt1x = (float)m_nDownX;
|
|
|
|
float pt1y = (float)m_nDownY;
|
2013-04-10 02:52:06 +02:00
|
|
|
float pt2x, pt2y;
|
|
|
|
|
|
|
|
if (m_nCurAction == LC_ACTION_ZOOM_REGION)
|
|
|
|
{
|
|
|
|
pt2x = m_OverlayTrackStart[0];
|
|
|
|
pt2y = m_OverlayTrackStart[1];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pt2x = m_fTrack[0];
|
|
|
|
pt2y = m_fTrack[1];
|
|
|
|
}
|
|
|
|
|
|
|
|
float Left, Right, Bottom, Top;
|
2012-01-28 02:05:23 +01:00
|
|
|
|
2013-04-10 02:52:06 +02:00
|
|
|
if (pt1x < pt2x)
|
|
|
|
{
|
|
|
|
Left = pt1x;
|
|
|
|
Right = pt2x;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Left = pt2x;
|
|
|
|
Right = pt1x;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pt1y < pt2y)
|
|
|
|
{
|
|
|
|
Bottom = pt1y;
|
|
|
|
Top = pt2y;
|
|
|
|
}
|
|
|
|
else
|
2012-09-10 01:42:57 +02:00
|
|
|
{
|
2013-04-10 02:52:06 +02:00
|
|
|
Bottom = pt2y;
|
|
|
|
Top = pt1y;
|
|
|
|
}
|
|
|
|
|
|
|
|
float BorderX = lcMin(2.0f, Right - Left);
|
|
|
|
float BorderY = lcMin(2.0f, Top - Bottom);
|
|
|
|
|
|
|
|
float Verts[14][2] =
|
|
|
|
{
|
|
|
|
{ Left, Bottom },
|
|
|
|
{ Left + BorderX, Bottom + BorderY },
|
|
|
|
{ Right, Bottom },
|
|
|
|
{ Right - BorderX, Bottom + BorderY },
|
|
|
|
{ Right, Top },
|
|
|
|
{ Right - BorderX, Top - BorderY },
|
|
|
|
{ Left, Top },
|
|
|
|
{ Left + BorderX, Top - BorderY },
|
|
|
|
{ Left, Bottom },
|
|
|
|
{ Left + BorderX, Bottom + BorderY },
|
|
|
|
{ Left + BorderX, Bottom + BorderY },
|
|
|
|
{ Right - BorderX, Bottom + BorderY },
|
|
|
|
{ Left + BorderX, Top - BorderY },
|
|
|
|
{ Right - BorderX, Top - BorderY },
|
2012-09-10 01:42:57 +02:00
|
|
|
};
|
|
|
|
|
2013-04-10 02:52:06 +02:00
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
glEnable(GL_BLEND);
|
|
|
|
|
2012-09-10 01:42:57 +02:00
|
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
2013-04-10 02:52:06 +02:00
|
|
|
glVertexPointer(2, GL_FLOAT, 0, Verts);
|
|
|
|
|
|
|
|
glColor4f(0.25f, 0.25f, 1.0f, 1.0f);
|
|
|
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, 10);
|
|
|
|
|
|
|
|
glColor4f(0.25f, 0.25f, 1.0f, 0.25f);
|
|
|
|
glDrawArrays(GL_TRIANGLE_STRIP, 10, 4);
|
|
|
|
|
2012-09-10 01:42:57 +02:00
|
|
|
glDisableClientState(GL_VERTEX_ARRAY);
|
2012-01-28 02:05:23 +01:00
|
|
|
|
2013-04-10 02:52:06 +02:00
|
|
|
glDisable(GL_BLEND);
|
2012-01-28 02:05:23 +01:00
|
|
|
glEnable(GL_DEPTH_TEST);
|
|
|
|
}
|
|
|
|
|
2012-02-05 03:50:57 +01:00
|
|
|
const float OverlayScale = view->m_OverlayScale;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-07-31 07:27:40 +02:00
|
|
|
if ((m_nCurAction == LC_ACTION_MOVE || m_nCurAction == LC_ACTION_SELECT) && (m_OverlayMode >= LC_OVERLAY_NONE && m_OverlayMode <= LC_OVERLAY_ROTATE_XYZ))
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2012-07-31 07:27:40 +02:00
|
|
|
const float OverlayMovePlaneSize = 0.5f * OverlayScale;
|
|
|
|
const float OverlayMoveArrowSize = 1.5f * OverlayScale;
|
|
|
|
const float OverlayMoveArrowCapSize = 0.9f * OverlayScale;
|
|
|
|
const float OverlayMoveArrowCapRadius = 0.1f * OverlayScale;
|
2012-08-10 23:51:07 +02:00
|
|
|
const float OverlayMoveArrowBodyRadius = 0.05f * OverlayScale;
|
2012-07-31 07:27:40 +02:00
|
|
|
const float OverlayRotateArrowStart = 1.0f * OverlayScale;
|
|
|
|
const float OverlayRotateArrowEnd = 1.5f * OverlayScale;
|
2012-08-02 23:14:26 +02:00
|
|
|
const float OverlayRotateArrowCenter = 1.2f * OverlayScale;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
glDisable(GL_DEPTH_TEST);
|
|
|
|
|
|
|
|
// Find the rotation from the focused piece if relative snap is enabled.
|
|
|
|
Object* Focus = NULL;
|
2012-06-22 00:03:30 +02:00
|
|
|
lcVector4 Rot(0, 0, 1, 0);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
if ((m_nSnap & LC_DRAW_GLOBAL_SNAP) == 0)
|
|
|
|
{
|
|
|
|
Focus = GetFocusObject();
|
|
|
|
|
|
|
|
if ((Focus != NULL) && Focus->IsPiece())
|
2012-06-16 02:17:52 +02:00
|
|
|
Rot = ((Piece*)Focus)->mRotation;
|
2011-09-07 23:06:51 +02:00
|
|
|
else
|
|
|
|
Focus = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Draw a quad if we're moving on a plane.
|
2012-07-31 07:27:40 +02:00
|
|
|
if ((m_OverlayMode == LC_OVERLAY_MOVE_XY) || (m_OverlayMode == LC_OVERLAY_MOVE_XZ) || (m_OverlayMode == LC_OVERLAY_MOVE_YZ))
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
|
|
|
glPushMatrix();
|
|
|
|
glTranslatef(m_OverlayCenter[0], m_OverlayCenter[1], m_OverlayCenter[2]);
|
|
|
|
|
|
|
|
if (Focus)
|
|
|
|
glRotatef(Rot[3], Rot[0], Rot[1], Rot[2]);
|
|
|
|
|
2012-07-31 07:27:40 +02:00
|
|
|
if (m_OverlayMode == LC_OVERLAY_MOVE_XZ)
|
2011-09-07 23:06:51 +02:00
|
|
|
glRotatef(90.0f, 0.0f, 0.0f, -1.0f);
|
2012-07-31 07:27:40 +02:00
|
|
|
else if (m_OverlayMode == LC_OVERLAY_MOVE_XY)
|
2011-09-07 23:06:51 +02:00
|
|
|
glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
|
|
|
|
|
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
glEnable(GL_BLEND);
|
|
|
|
|
|
|
|
glColor4f(0.8f, 0.8f, 0.0f, 0.3f);
|
2012-09-10 01:42:57 +02:00
|
|
|
|
|
|
|
float Verts[4][3] =
|
|
|
|
{
|
|
|
|
{ 0.0f, 0.0f, 0.0f },
|
|
|
|
{ 0.0f, OverlayMovePlaneSize, 0.0f },
|
|
|
|
{ 0.0f, OverlayMovePlaneSize, OverlayMovePlaneSize },
|
|
|
|
{ 0.0f, 0.0f, OverlayMovePlaneSize }
|
|
|
|
};
|
|
|
|
|
|
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
|
|
glVertexPointer(3, GL_FLOAT, 0, Verts);
|
|
|
|
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
|
|
|
glDisableClientState(GL_VERTEX_ARRAY);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
glDisable(GL_BLEND);
|
|
|
|
|
|
|
|
glPopMatrix();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Draw the arrows.
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
|
|
{
|
|
|
|
switch (i)
|
|
|
|
{
|
|
|
|
case 0:
|
2012-07-31 07:27:40 +02:00
|
|
|
if ((m_OverlayMode == LC_OVERLAY_MOVE_X) || (m_OverlayMode == LC_OVERLAY_MOVE_XY) || (m_OverlayMode == LC_OVERLAY_MOVE_XZ))
|
2012-01-28 02:05:23 +01:00
|
|
|
glColor4f(0.8f, 0.8f, 0.0f, 1.0f);
|
2011-09-07 23:06:51 +02:00
|
|
|
else
|
2012-01-28 02:05:23 +01:00
|
|
|
glColor4f(0.8f, 0.0f, 0.0f, 1.0f);
|
2011-09-07 23:06:51 +02:00
|
|
|
break;
|
|
|
|
case 1:
|
2012-07-31 07:27:40 +02:00
|
|
|
if ((m_OverlayMode == LC_OVERLAY_MOVE_Y) || (m_OverlayMode == LC_OVERLAY_MOVE_XY) || (m_OverlayMode == LC_OVERLAY_MOVE_YZ))
|
2012-01-28 02:05:23 +01:00
|
|
|
glColor4f(0.8f, 0.8f, 0.0f, 1.0f);
|
2011-09-07 23:06:51 +02:00
|
|
|
else
|
2012-01-28 02:05:23 +01:00
|
|
|
glColor4f(0.0f, 0.8f, 0.0f, 1.0f);
|
2011-09-07 23:06:51 +02:00
|
|
|
break;
|
|
|
|
case 2:
|
2012-07-31 07:27:40 +02:00
|
|
|
if ((m_OverlayMode == LC_OVERLAY_MOVE_Z) || (m_OverlayMode == LC_OVERLAY_MOVE_XZ) || (m_OverlayMode == LC_OVERLAY_MOVE_YZ))
|
2012-01-28 02:05:23 +01:00
|
|
|
glColor4f(0.8f, 0.8f, 0.0f, 1.0f);
|
2011-09-07 23:06:51 +02:00
|
|
|
else
|
2012-01-28 02:05:23 +01:00
|
|
|
glColor4f(0.0f, 0.0f, 0.8f, 1.0f);
|
2011-09-07 23:06:51 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
glPushMatrix();
|
|
|
|
glTranslatef(m_OverlayCenter[0], m_OverlayCenter[1], m_OverlayCenter[2]);
|
|
|
|
|
|
|
|
if (Focus)
|
|
|
|
glRotatef(Rot[3], Rot[0], Rot[1], Rot[2]);
|
|
|
|
|
|
|
|
if (i == 1)
|
2012-07-31 07:27:40 +02:00
|
|
|
glMultMatrixf(lcMatrix44(lcVector4(0, 1, 0, 0), lcVector4(1, 0, 0, 0), lcVector4(0, 0, 1, 0), lcVector4(0, 0, 0, 1)));
|
2011-09-07 23:06:51 +02:00
|
|
|
else if (i == 2)
|
2012-07-31 07:27:40 +02:00
|
|
|
glMultMatrixf(lcMatrix44(lcVector4(0, 0, 1, 0), lcVector4(0, 1, 0, 0), lcVector4(1, 0, 0, 0), lcVector4(0, 0, 0, 1)));
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-08-09 00:11:23 +02:00
|
|
|
// Translation arrows.
|
|
|
|
if (m_nTracking == LC_TRACK_NONE || (m_OverlayMode >= LC_OVERLAY_NONE && m_OverlayMode <= LC_OVERLAY_MOVE_XYZ))
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-01-11 22:02:55 +01:00
|
|
|
lcVector3 Verts[11];
|
|
|
|
|
|
|
|
Verts[0] = lcVector3(0.0f, 0.0f, 0.0f);
|
|
|
|
Verts[1] = lcVector3(OverlayMoveArrowSize, 0.0f, 0.0f);
|
2012-08-09 00:11:23 +02:00
|
|
|
|
|
|
|
for (int j = 0; j < 9; j++)
|
|
|
|
{
|
|
|
|
float y = cosf(LC_2PI * j / 8) * OverlayMoveArrowCapRadius;
|
|
|
|
float z = sinf(LC_2PI * j / 8) * OverlayMoveArrowCapRadius;
|
2013-01-11 22:02:55 +01:00
|
|
|
Verts[j + 2] = lcVector3(OverlayMoveArrowCapSize, y, z);
|
2012-08-09 00:11:23 +02:00
|
|
|
}
|
2013-01-11 22:02:55 +01:00
|
|
|
|
|
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
|
|
glVertexPointer(3, GL_FLOAT, 0, Verts);
|
|
|
|
glDrawArrays(GL_LINES, 0, 2);
|
|
|
|
glDrawArrays(GL_TRIANGLE_FAN, 1, 10);
|
|
|
|
glDisableClientState(GL_VERTEX_ARRAY);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
2012-08-09 00:11:23 +02:00
|
|
|
// Rotation arrows.
|
|
|
|
if (m_nCurAction == LC_ACTION_SELECT && m_nTracking == LC_TRACK_NONE)
|
2012-07-31 07:27:40 +02:00
|
|
|
{
|
|
|
|
switch (i)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
if (m_OverlayMode == LC_OVERLAY_ROTATE_X)
|
|
|
|
glColor4f(0.8f, 0.8f, 0.0f, 1.0f);
|
|
|
|
else
|
|
|
|
glColor4f(0.8f, 0.0f, 0.0f, 1.0f);
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
if (m_OverlayMode == LC_OVERLAY_ROTATE_Y)
|
|
|
|
glColor4f(0.8f, 0.8f, 0.0f, 1.0f);
|
|
|
|
else
|
|
|
|
glColor4f(0.0f, 0.8f, 0.0f, 1.0f);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
if (m_OverlayMode == LC_OVERLAY_ROTATE_Z)
|
|
|
|
glColor4f(0.8f, 0.8f, 0.0f, 1.0f);
|
|
|
|
else
|
|
|
|
glColor4f(0.0f, 0.0f, 0.8f, 1.0f);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2013-01-11 22:02:55 +01:00
|
|
|
lcVector3 Verts[18];
|
|
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
|
|
glVertexPointer(3, GL_FLOAT, 0, Verts);
|
2012-08-10 23:51:07 +02:00
|
|
|
|
|
|
|
for (int j = 0; j < 9; j++)
|
|
|
|
{
|
|
|
|
const float Radius1 = OverlayRotateArrowEnd - OverlayMoveArrowCapRadius - OverlayRotateArrowCenter - OverlayMoveArrowBodyRadius;
|
|
|
|
const float Radius2 = OverlayRotateArrowEnd - OverlayMoveArrowCapRadius - OverlayRotateArrowCenter + OverlayMoveArrowBodyRadius;
|
|
|
|
float x = cosf(LC_2PI / 4 * j / 8);
|
|
|
|
float y = sinf(LC_2PI / 4 * j / 8);
|
|
|
|
|
2013-01-11 22:02:55 +01:00
|
|
|
Verts[j * 2 + 0] = lcVector3(0.0f, OverlayRotateArrowCenter + x * Radius1, OverlayRotateArrowCenter + y * Radius1);
|
|
|
|
Verts[j * 2 + 1] = lcVector3(0.0f, OverlayRotateArrowCenter + x * Radius2, OverlayRotateArrowCenter + y * Radius2);
|
2012-08-10 23:51:07 +02:00
|
|
|
}
|
|
|
|
|
2013-01-11 22:02:55 +01:00
|
|
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, 18);
|
2012-08-02 23:14:26 +02:00
|
|
|
|
|
|
|
for (int j = 0; j < 9; j++)
|
|
|
|
{
|
|
|
|
const float Radius = OverlayRotateArrowEnd - OverlayMoveArrowCapRadius - OverlayRotateArrowCenter;
|
2012-08-10 23:51:07 +02:00
|
|
|
float x = cosf(LC_2PI / 4 * j / 8);
|
|
|
|
float y = sinf(LC_2PI / 4 * j / 8);
|
|
|
|
|
2013-01-11 22:02:55 +01:00
|
|
|
Verts[j * 2 + 0] = lcVector3(-OverlayMoveArrowBodyRadius, OverlayRotateArrowCenter + x * Radius, OverlayRotateArrowCenter + y * Radius);
|
|
|
|
Verts[j * 2 + 1] = lcVector3( OverlayMoveArrowBodyRadius, OverlayRotateArrowCenter + x * Radius, OverlayRotateArrowCenter + y * Radius);
|
2012-08-02 23:14:26 +02:00
|
|
|
}
|
|
|
|
|
2013-01-11 22:02:55 +01:00
|
|
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, 18);
|
2012-08-02 23:14:26 +02:00
|
|
|
|
2013-01-11 22:02:55 +01:00
|
|
|
Verts[0] = lcVector3(0.0f, OverlayRotateArrowEnd - OverlayMoveArrowCapRadius, OverlayRotateArrowStart);
|
2012-08-02 23:14:26 +02:00
|
|
|
|
|
|
|
for (int j = 0; j < 9; j++)
|
|
|
|
{
|
|
|
|
float x = cosf(LC_2PI * j / 8) * OverlayMoveArrowCapRadius;
|
|
|
|
float y = sinf(LC_2PI * j / 8) * OverlayMoveArrowCapRadius;
|
2013-01-11 22:02:55 +01:00
|
|
|
Verts[j + 1] = lcVector3(x, OverlayRotateArrowEnd - OverlayMoveArrowCapRadius + y, OverlayRotateArrowCenter);
|
2012-08-02 23:14:26 +02:00
|
|
|
}
|
|
|
|
|
2013-01-11 22:02:55 +01:00
|
|
|
glDrawArrays(GL_TRIANGLE_FAN, 0, 10);
|
2012-08-02 23:14:26 +02:00
|
|
|
|
2013-01-11 22:02:55 +01:00
|
|
|
Verts[0] = lcVector3(0.0f, OverlayRotateArrowStart, OverlayRotateArrowEnd - OverlayMoveArrowCapRadius);
|
2012-08-02 23:14:26 +02:00
|
|
|
|
|
|
|
for (int j = 0; j < 9; j++)
|
|
|
|
{
|
|
|
|
float x = cosf(LC_2PI * j / 8) * OverlayMoveArrowCapRadius;
|
|
|
|
float y = sinf(LC_2PI * j / 8) * OverlayMoveArrowCapRadius;
|
2013-01-11 22:02:55 +01:00
|
|
|
Verts[j + 1] = lcVector3(x, OverlayRotateArrowCenter, OverlayRotateArrowEnd - OverlayMoveArrowCapRadius + y);
|
2012-08-02 23:14:26 +02:00
|
|
|
}
|
|
|
|
|
2013-01-11 22:02:55 +01:00
|
|
|
glDrawArrays(GL_TRIANGLE_FAN, 0, 10);
|
|
|
|
|
|
|
|
glDisableClientState(GL_VERTEX_ARRAY);
|
2012-07-31 07:27:40 +02:00
|
|
|
}
|
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
glPopMatrix();
|
|
|
|
}
|
|
|
|
|
|
|
|
glEnable(GL_DEPTH_TEST);
|
|
|
|
}
|
2013-01-06 20:24:25 +01:00
|
|
|
|
2012-08-09 00:11:23 +02:00
|
|
|
if (m_nCurAction == LC_ACTION_ROTATE || (m_nCurAction == LC_ACTION_SELECT && m_nTracking != LC_TRACK_NONE && m_OverlayMode >= LC_OVERLAY_ROTATE_X && m_OverlayMode <= LC_OVERLAY_ROTATE_XYZ))
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
|
|
|
const float OverlayRotateRadius = 2.0f;
|
|
|
|
|
|
|
|
glDisable(GL_DEPTH_TEST);
|
|
|
|
|
2012-08-20 06:05:56 +02:00
|
|
|
Camera* Cam = view->mCamera;
|
2011-09-07 23:06:51 +02:00
|
|
|
int j;
|
|
|
|
|
|
|
|
// Find the rotation from the focused piece if relative snap is enabled.
|
|
|
|
Object* Focus = NULL;
|
2012-06-22 00:03:30 +02:00
|
|
|
lcVector4 Rot(0, 0, 1, 0);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
if ((m_nSnap & LC_DRAW_GLOBAL_SNAP) == 0)
|
|
|
|
{
|
|
|
|
Focus = GetFocusObject();
|
|
|
|
|
|
|
|
if ((Focus != NULL) && Focus->IsPiece())
|
2012-06-16 02:17:52 +02:00
|
|
|
Rot = ((Piece*)Focus)->mRotation;
|
2011-09-07 23:06:51 +02:00
|
|
|
else
|
|
|
|
Focus = NULL;
|
|
|
|
}
|
|
|
|
|
2012-08-09 00:11:23 +02:00
|
|
|
bool HasAngle = false;
|
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
// Draw a disc showing the rotation amount.
|
|
|
|
if (m_MouseTotalDelta.LengthSquared() != 0.0f && (m_nTracking != LC_TRACK_NONE))
|
|
|
|
{
|
2012-06-16 02:17:52 +02:00
|
|
|
lcVector4 Rotation;
|
2011-09-07 23:06:51 +02:00
|
|
|
float Angle, Step;
|
|
|
|
|
2012-08-09 00:11:23 +02:00
|
|
|
HasAngle = true;
|
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
switch (m_OverlayMode)
|
|
|
|
{
|
2012-07-31 07:27:40 +02:00
|
|
|
case LC_OVERLAY_ROTATE_X:
|
2011-09-07 23:06:51 +02:00
|
|
|
glColor4f(0.8f, 0.0f, 0.0f, 0.3f);
|
|
|
|
Angle = m_MouseTotalDelta[0];
|
2012-08-09 00:11:23 +02:00
|
|
|
Rotation = lcVector4(0.0f, 0.0f, 0.0f, 1.0f);
|
2011-09-07 23:06:51 +02:00
|
|
|
break;
|
2012-07-31 07:27:40 +02:00
|
|
|
case LC_OVERLAY_ROTATE_Y:
|
2011-09-07 23:06:51 +02:00
|
|
|
glColor4f(0.0f, 0.8f, 0.0f, 0.3f);
|
|
|
|
Angle = m_MouseTotalDelta[1];
|
2012-06-16 02:17:52 +02:00
|
|
|
Rotation = lcVector4(90.0f, 0.0f, 0.0f, 1.0f);
|
2011-09-07 23:06:51 +02:00
|
|
|
break;
|
2012-07-31 07:27:40 +02:00
|
|
|
case LC_OVERLAY_ROTATE_Z:
|
2011-09-07 23:06:51 +02:00
|
|
|
glColor4f(0.0f, 0.0f, 0.8f, 0.3f);
|
|
|
|
Angle = m_MouseTotalDelta[2];
|
2012-06-16 02:17:52 +02:00
|
|
|
Rotation = lcVector4(90.0f, 0.0f, -1.0f, 0.0f);
|
2011-09-07 23:06:51 +02:00
|
|
|
break;
|
|
|
|
default:
|
2012-08-09 00:11:23 +02:00
|
|
|
Rotation = lcVector4(0.0f, 0.0f, 0.0f, 1.0f);
|
2011-09-07 23:06:51 +02:00
|
|
|
Angle = 0.0f;
|
|
|
|
break;
|
|
|
|
};
|
|
|
|
|
|
|
|
if (Angle > 0.0f)
|
|
|
|
{
|
|
|
|
Step = 360.0f / 32;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Angle = -Angle;
|
|
|
|
Step = -360.0f / 32;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fabsf(Angle) >= fabsf(Step))
|
|
|
|
{
|
|
|
|
glPushMatrix();
|
|
|
|
glTranslatef(m_OverlayCenter[0], m_OverlayCenter[1], m_OverlayCenter[2]);
|
|
|
|
|
|
|
|
if (Focus)
|
|
|
|
glRotatef(Rot[3], Rot[0], Rot[1], Rot[2]);
|
|
|
|
|
|
|
|
glRotatef(Rotation[0], Rotation[1], Rotation[2], Rotation[3]);
|
|
|
|
|
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
glEnable(GL_BLEND);
|
|
|
|
|
2013-01-11 22:02:55 +01:00
|
|
|
lcVector3 Verts[33];
|
|
|
|
Verts[0] = lcVector3(0.0f, 0.0f, 0.0f);
|
|
|
|
int NumVerts = 1;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-01-11 22:02:55 +01:00
|
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
|
|
glVertexPointer(3, GL_FLOAT, 0, Verts);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
float StartAngle;
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
if (Step < 0)
|
|
|
|
StartAngle = -Angle;
|
|
|
|
else
|
|
|
|
StartAngle = Angle;
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
2012-06-30 01:50:29 +02:00
|
|
|
float x = cosf((Step * i - StartAngle) * LC_DTOR) * OverlayRotateRadius * OverlayScale;
|
|
|
|
float y = sinf((Step * i - StartAngle) * LC_DTOR) * OverlayRotateRadius * OverlayScale;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-01-11 22:02:55 +01:00
|
|
|
Verts[NumVerts++] = lcVector3(0.0f, x, y);
|
|
|
|
|
|
|
|
if (NumVerts == 33)
|
|
|
|
{
|
|
|
|
glDrawArrays(GL_TRIANGLE_FAN, 0, NumVerts);
|
|
|
|
Verts[1] = Verts[32];
|
|
|
|
NumVerts = 2;
|
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
i++;
|
|
|
|
if (Step > 0)
|
|
|
|
Angle -= Step;
|
|
|
|
else
|
|
|
|
Angle += Step;
|
|
|
|
|
|
|
|
} while (Angle >= 0.0f);
|
|
|
|
|
2013-01-11 22:02:55 +01:00
|
|
|
if (NumVerts > 2)
|
|
|
|
glDrawArrays(GL_TRIANGLE_FAN, 0, NumVerts);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-01-11 22:02:55 +01:00
|
|
|
glDisableClientState(GL_VERTEX_ARRAY);
|
2011-09-07 23:06:51 +02:00
|
|
|
glDisable(GL_BLEND);
|
|
|
|
|
|
|
|
glPopMatrix();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-09 00:11:23 +02:00
|
|
|
glPushMatrix();
|
|
|
|
|
2012-06-13 04:41:16 +02:00
|
|
|
lcMatrix44 Mat = lcMatrix44AffineInverse(Cam->mWorldView);
|
2011-09-07 23:06:51 +02:00
|
|
|
Mat.SetTranslation(m_OverlayCenter);
|
|
|
|
|
|
|
|
// Draw the circles.
|
2012-08-09 00:11:23 +02:00
|
|
|
if (m_nCurAction == LC_ACTION_ROTATE && !HasAngle && m_nTracking == LC_TRACK_NONE)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-01-11 22:02:55 +01:00
|
|
|
lcVector3 Verts[32];
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-08-09 00:11:23 +02:00
|
|
|
for (j = 0; j < 32; j++)
|
|
|
|
{
|
|
|
|
lcVector3 Pt;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-08-09 00:11:23 +02:00
|
|
|
Pt[0] = cosf(LC_2PI * j / 32) * OverlayRotateRadius * OverlayScale;
|
|
|
|
Pt[1] = sinf(LC_2PI * j / 32) * OverlayRotateRadius * OverlayScale;
|
|
|
|
Pt[2] = 0.0f;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-01-11 22:02:55 +01:00
|
|
|
Verts[j] = lcMul31(Pt, Mat);
|
2012-08-09 00:11:23 +02:00
|
|
|
}
|
|
|
|
|
2013-01-11 22:02:55 +01:00
|
|
|
glColor4f(0.1f, 0.1f, 0.1f, 1.0f);
|
|
|
|
|
|
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
|
|
glVertexPointer(3, GL_FLOAT, 0, Verts);
|
|
|
|
glDrawArrays(GL_LINE_LOOP, 0, 32);
|
|
|
|
glDisableClientState(GL_VERTEX_ARRAY);
|
2012-08-09 00:11:23 +02:00
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-05-29 01:33:22 +02:00
|
|
|
lcVector3 ViewDir = Cam->mTargetPosition - Cam->mPosition;
|
2011-09-07 23:06:51 +02:00
|
|
|
ViewDir.Normalize();
|
|
|
|
|
|
|
|
// Transform ViewDir to local space.
|
|
|
|
if (Focus)
|
|
|
|
{
|
2012-05-29 01:33:22 +02:00
|
|
|
lcMatrix44 RotMat = lcMatrix44FromAxisAngle(lcVector3(Rot[0], Rot[1], Rot[2]), -Rot[3] * LC_DTOR);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-05-29 01:33:22 +02:00
|
|
|
ViewDir = lcMul30(ViewDir, RotMat);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
glTranslatef(m_OverlayCenter[0], m_OverlayCenter[1], m_OverlayCenter[2]);
|
|
|
|
|
|
|
|
if (Focus)
|
|
|
|
glRotatef(Rot[3], Rot[0], Rot[1], Rot[2]);
|
|
|
|
|
|
|
|
// Draw each axis circle.
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
|
|
{
|
2012-07-31 07:27:40 +02:00
|
|
|
if (m_OverlayMode == LC_OVERLAY_ROTATE_X + i)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2012-01-28 02:05:23 +01:00
|
|
|
glColor4f(0.8f, 0.8f, 0.0f, 1.0f);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-08-09 00:11:23 +02:00
|
|
|
if (m_nCurAction != LC_ACTION_ROTATE || HasAngle || m_nTracking != LC_TRACK_NONE)
|
|
|
|
continue;
|
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
switch (i)
|
|
|
|
{
|
|
|
|
case 0:
|
2012-01-28 02:05:23 +01:00
|
|
|
glColor4f(0.8f, 0.0f, 0.0f, 1.0f);
|
2011-09-07 23:06:51 +02:00
|
|
|
break;
|
|
|
|
case 1:
|
2012-01-28 02:05:23 +01:00
|
|
|
glColor4f(0.0f, 0.8f, 0.0f, 1.0f);
|
2011-09-07 23:06:51 +02:00
|
|
|
break;
|
|
|
|
case 2:
|
2012-01-28 02:05:23 +01:00
|
|
|
glColor4f(0.0f, 0.0f, 0.8f, 1.0f);
|
2011-09-07 23:06:51 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-11 22:02:55 +01:00
|
|
|
lcVector3 Verts[64];
|
|
|
|
int NumVerts = 0;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-02-13 00:36:30 +01:00
|
|
|
for (j = 0; j < 32; j++)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2012-05-29 01:33:22 +02:00
|
|
|
lcVector3 v1, v2;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
switch (i)
|
|
|
|
{
|
|
|
|
case 0:
|
2012-05-29 01:33:22 +02:00
|
|
|
v1 = lcVector3(0.0f, cosf(LC_2PI * j / 32), sinf(LC_2PI * j / 32));
|
|
|
|
v2 = lcVector3(0.0f, cosf(LC_2PI * (j + 1) / 32), sinf(LC_2PI * (j + 1) / 32));
|
2011-09-07 23:06:51 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 1:
|
2012-05-29 01:33:22 +02:00
|
|
|
v1 = lcVector3(cosf(LC_2PI * j / 32), 0.0f, sinf(LC_2PI * j / 32));
|
|
|
|
v2 = lcVector3(cosf(LC_2PI * (j + 1) / 32), 0.0f, sinf(LC_2PI * (j + 1) / 32));
|
2011-09-07 23:06:51 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
2012-05-29 01:33:22 +02:00
|
|
|
v1 = lcVector3(cosf(LC_2PI * j / 32), sinf(LC_2PI * j / 32), 0.0f);
|
|
|
|
v2 = lcVector3(cosf(LC_2PI * (j + 1) / 32), sinf(LC_2PI * (j + 1) / 32), 0.0f);
|
2011-09-07 23:06:51 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2012-08-09 00:11:23 +02:00
|
|
|
if (m_nCurAction != LC_ACTION_ROTATE || HasAngle || m_nTracking != LC_TRACK_NONE || lcDot(ViewDir, v1 + v2) <= 0.0f)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-01-11 22:02:55 +01:00
|
|
|
Verts[NumVerts++] = v1 * (OverlayRotateRadius * OverlayScale);
|
|
|
|
Verts[NumVerts++] = v2 * (OverlayRotateRadius * OverlayScale);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-11 22:02:55 +01:00
|
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
|
|
glVertexPointer(3, GL_FLOAT, 0, Verts);
|
|
|
|
glDrawArrays(GL_LINES, 0, NumVerts);
|
|
|
|
glDisableClientState(GL_VERTEX_ARRAY);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
2012-08-09 00:11:23 +02:00
|
|
|
glPopMatrix();
|
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
// Draw tangent vector.
|
|
|
|
if (m_nTracking != LC_TRACK_NONE)
|
|
|
|
{
|
2012-07-31 07:27:40 +02:00
|
|
|
if ((m_OverlayMode == LC_OVERLAY_ROTATE_X) || (m_OverlayMode == LC_OVERLAY_ROTATE_Y) || (m_OverlayMode == LC_OVERLAY_ROTATE_Z))
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2012-08-09 00:11:23 +02:00
|
|
|
const float OverlayRotateArrowSize = 1.5f;
|
|
|
|
const float OverlayRotateArrowCapSize = 0.25f;
|
|
|
|
|
|
|
|
lcVector4 Rotation;
|
2011-09-07 23:06:51 +02:00
|
|
|
float Angle;
|
|
|
|
|
|
|
|
switch (m_OverlayMode)
|
|
|
|
{
|
2012-07-31 07:27:40 +02:00
|
|
|
case LC_OVERLAY_ROTATE_X:
|
2011-09-07 23:06:51 +02:00
|
|
|
Angle = m_MouseTotalDelta[0];
|
2012-08-09 00:11:23 +02:00
|
|
|
Rotation = lcVector4(0.0f, 0.0f, 0.0f, 1.0f);
|
2011-09-07 23:06:51 +02:00
|
|
|
break;
|
2012-07-31 07:27:40 +02:00
|
|
|
case LC_OVERLAY_ROTATE_Y:
|
2011-09-07 23:06:51 +02:00
|
|
|
Angle = m_MouseTotalDelta[1];
|
2012-08-09 00:11:23 +02:00
|
|
|
Rotation = lcVector4(90.0f, 0.0f, 0.0f, 1.0f);
|
2011-09-07 23:06:51 +02:00
|
|
|
break;
|
2012-07-31 07:27:40 +02:00
|
|
|
case LC_OVERLAY_ROTATE_Z:
|
2011-09-07 23:06:51 +02:00
|
|
|
Angle = m_MouseTotalDelta[2];
|
2012-08-09 00:11:23 +02:00
|
|
|
Rotation = lcVector4(90.0f, 0.0f, -1.0f, 0.0f);
|
2011-09-07 23:06:51 +02:00
|
|
|
break;
|
2012-06-22 00:03:30 +02:00
|
|
|
default:
|
2013-08-09 06:57:18 +02:00
|
|
|
Angle = 0.0f;
|
2012-08-09 00:11:23 +02:00
|
|
|
Rotation = lcVector4(0.0f, 0.0f, 1.0f, 0.0f);
|
2012-06-22 00:03:30 +02:00
|
|
|
break;
|
2012-08-09 00:11:23 +02:00
|
|
|
};
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-08-09 00:11:23 +02:00
|
|
|
glPushMatrix();
|
|
|
|
glTranslatef(m_OverlayCenter[0], m_OverlayCenter[1], m_OverlayCenter[2]);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-08-09 00:11:23 +02:00
|
|
|
if (Focus)
|
|
|
|
glRotatef(Rot[3], Rot[0], Rot[1], Rot[2]);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-08-09 00:11:23 +02:00
|
|
|
glRotatef(Rotation[0], Rotation[1], Rotation[2], Rotation[3]);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-09-10 01:42:57 +02:00
|
|
|
glColor4f(0.8f, 0.8f, 0.0f, 1.0f);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-08-09 00:11:23 +02:00
|
|
|
if (HasAngle)
|
|
|
|
{
|
|
|
|
float StartY = OverlayScale * OverlayRotateRadius;
|
|
|
|
float EndZ = (Angle > 0.0f) ? OverlayScale * OverlayRotateArrowSize : -OverlayScale * OverlayRotateArrowSize;
|
|
|
|
float TipZ = (Angle > 0.0f) ? -OverlayScale * OverlayRotateArrowCapSize : OverlayScale * OverlayRotateArrowCapSize;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-01-11 22:02:55 +01:00
|
|
|
lcVector3 Verts[6];
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-01-11 22:02:55 +01:00
|
|
|
Verts[0] = lcVector3(0.0f, StartY, 0.0f);
|
|
|
|
Verts[1] = lcVector3(0.0f, StartY, EndZ);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-01-11 22:02:55 +01:00
|
|
|
Verts[2] = lcVector3(0.0f, StartY, EndZ);
|
|
|
|
Verts[3] = lcVector3(0.0f, StartY + OverlayScale * OverlayRotateArrowCapSize, EndZ + TipZ);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-01-11 22:02:55 +01:00
|
|
|
Verts[4] = lcVector3(0.0f, StartY, EndZ);
|
|
|
|
Verts[5] = lcVector3(0.0f, StartY - OverlayScale * OverlayRotateArrowCapSize, EndZ + TipZ);
|
2012-08-09 00:11:23 +02:00
|
|
|
|
2013-01-11 22:02:55 +01:00
|
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
|
|
glVertexPointer(3, GL_FLOAT, 0, Verts);
|
|
|
|
glDrawArrays(GL_LINES, 0, 6);
|
|
|
|
glDisableClientState(GL_VERTEX_ARRAY);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
2013-01-11 22:02:55 +01:00
|
|
|
glPopMatrix();
|
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
// Draw text.
|
2013-08-09 06:57:18 +02:00
|
|
|
int Viewport[4] = { 0, 0, view->mWidth, view->mHeight };
|
2012-08-09 00:11:23 +02:00
|
|
|
float Aspect = (float)Viewport[2]/(float)Viewport[3];
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-08-09 00:11:23 +02:00
|
|
|
const lcMatrix44& ModelView = Cam->mWorldView;
|
|
|
|
lcMatrix44 Projection = lcMatrix44Perspective(Cam->m_fovy, Aspect, Cam->m_zNear, Cam->m_zFar);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-02-22 21:01:36 +01:00
|
|
|
lcVector3 ScreenPos = lcProjectPoint(m_OverlayCenter, ModelView, Projection, Viewport);
|
2012-08-09 00:11:23 +02:00
|
|
|
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glPushMatrix();
|
|
|
|
glLoadIdentity();
|
|
|
|
glOrtho(0, Viewport[2], 0, Viewport[3], -1, 1);
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glPushMatrix();
|
|
|
|
glLoadIdentity();
|
|
|
|
glTranslatef(0.375, 0.375, 0.0);
|
|
|
|
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
|
|
|
m_pScreenFont->MakeCurrent();
|
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
glEnable(GL_ALPHA_TEST);
|
|
|
|
|
|
|
|
char buf[32];
|
|
|
|
sprintf(buf, "[%.2f]", fabsf(Angle));
|
|
|
|
|
|
|
|
int cx, cy;
|
|
|
|
m_pScreenFont->GetStringDimensions(&cx, &cy, buf);
|
|
|
|
|
2012-09-10 01:42:57 +02:00
|
|
|
glColor4f(0.8f, 0.8f, 0.0f, 1.0f);
|
2013-02-22 21:01:36 +01:00
|
|
|
m_pScreenFont->PrintText(ScreenPos[0] - Viewport[0] - (cx / 2), ScreenPos[1] - Viewport[1] + (cy / 2), 0.0f, buf);
|
2012-08-09 00:11:23 +02:00
|
|
|
|
|
|
|
glDisable(GL_TEXTURE_2D);
|
|
|
|
glDisable(GL_ALPHA_TEST);
|
|
|
|
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glPopMatrix();
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glPopMatrix();
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
glEnable(GL_DEPTH_TEST);
|
|
|
|
}
|
|
|
|
else if (m_nCurAction == LC_ACTION_ROTATE_VIEW)
|
|
|
|
{
|
|
|
|
int x, y, w, h;
|
|
|
|
|
2012-01-28 02:05:23 +01:00
|
|
|
x = 0;
|
|
|
|
y = 0;
|
2013-08-09 06:57:18 +02:00
|
|
|
w = view->mWidth;
|
|
|
|
h = view->mHeight;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glLoadIdentity();
|
2012-01-28 02:05:23 +01:00
|
|
|
glOrtho(0, w, 0, h, -1, 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glLoadIdentity();
|
|
|
|
glTranslatef(0.375f, 0.375f, 0.0f);
|
|
|
|
|
|
|
|
glDisable(GL_DEPTH_TEST);
|
2012-01-28 02:05:23 +01:00
|
|
|
glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
// Draw circle.
|
2012-09-10 01:42:57 +02:00
|
|
|
float verts[32][2];
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-07-06 03:18:55 +02:00
|
|
|
float r = lcMin(w, h) * 0.35f;
|
2011-09-07 23:06:51 +02:00
|
|
|
float cx = x + w / 2.0f;
|
|
|
|
float cy = y + h / 2.0f;
|
|
|
|
|
|
|
|
for (int i = 0; i < 32; i++)
|
|
|
|
{
|
2012-09-10 01:42:57 +02:00
|
|
|
verts[i][0] = cosf((float)i / 32.0f * (2.0f * LC_PI)) * r + cx;
|
|
|
|
verts[i][1] = sinf((float)i / 32.0f * (2.0f * LC_PI)) * r + cy;
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
2012-09-10 01:42:57 +02:00
|
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
|
|
glVertexPointer(2, GL_FLOAT, 0, verts);
|
|
|
|
glDrawArrays(GL_LINE_LOOP, 0, 32);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-07-06 03:18:55 +02:00
|
|
|
const float OverlayCameraSquareSize = lcMax(8.0f, (w+h)/200);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
// Draw squares.
|
2012-09-10 01:42:57 +02:00
|
|
|
float Squares[16][2] =
|
|
|
|
{
|
|
|
|
{ cx + OverlayCameraSquareSize, cy + r + OverlayCameraSquareSize },
|
|
|
|
{ cx - OverlayCameraSquareSize, cy + r + OverlayCameraSquareSize },
|
|
|
|
{ cx - OverlayCameraSquareSize, cy + r - OverlayCameraSquareSize },
|
|
|
|
{ cx + OverlayCameraSquareSize, cy + r - OverlayCameraSquareSize },
|
|
|
|
{ cx + OverlayCameraSquareSize, cy - r + OverlayCameraSquareSize },
|
|
|
|
{ cx - OverlayCameraSquareSize, cy - r + OverlayCameraSquareSize },
|
|
|
|
{ cx - OverlayCameraSquareSize, cy - r - OverlayCameraSquareSize },
|
|
|
|
{ cx + OverlayCameraSquareSize, cy - r - OverlayCameraSquareSize },
|
|
|
|
{ cx + r + OverlayCameraSquareSize, cy + OverlayCameraSquareSize },
|
|
|
|
{ cx + r - OverlayCameraSquareSize, cy + OverlayCameraSquareSize },
|
|
|
|
{ cx + r - OverlayCameraSquareSize, cy - OverlayCameraSquareSize },
|
|
|
|
{ cx + r + OverlayCameraSquareSize, cy - OverlayCameraSquareSize },
|
|
|
|
{ cx - r + OverlayCameraSquareSize, cy + OverlayCameraSquareSize },
|
|
|
|
{ cx - r - OverlayCameraSquareSize, cy + OverlayCameraSquareSize },
|
|
|
|
{ cx - r - OverlayCameraSquareSize, cy - OverlayCameraSquareSize },
|
|
|
|
{ cx - r + OverlayCameraSquareSize, cy - OverlayCameraSquareSize }
|
|
|
|
};
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-09-10 01:42:57 +02:00
|
|
|
glVertexPointer(2, GL_FLOAT, 0, Squares);
|
|
|
|
glDrawArrays(GL_LINE_LOOP, 0, 4);
|
|
|
|
glDrawArrays(GL_LINE_LOOP, 4, 4);
|
|
|
|
glDrawArrays(GL_LINE_LOOP, 8, 4);
|
|
|
|
glDrawArrays(GL_LINE_LOOP, 12, 4);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-09-10 01:42:57 +02:00
|
|
|
glDisableClientState(GL_VERTEX_ARRAY);
|
2011-09-07 23:06:51 +02:00
|
|
|
glEnable(GL_DEPTH_TEST);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-28 02:05:23 +01:00
|
|
|
void Project::RenderViewports(View* view)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glLoadIdentity();
|
2013-08-09 06:57:18 +02:00
|
|
|
glOrtho(0.0f, view->mWidth, 0.0f, view->mHeight, -1.0f, 1.0f);
|
2011-09-07 23:06:51 +02:00
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glLoadIdentity();
|
2012-01-22 04:52:33 +01:00
|
|
|
glTranslatef(0.375f, 0.375f, 0.0f);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-01-28 02:05:23 +01:00
|
|
|
glDepthMask(GL_FALSE);
|
|
|
|
glDisable(GL_DEPTH_TEST);
|
|
|
|
glDisable(GL_LIGHTING);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-01-28 02:05:23 +01:00
|
|
|
// Draw camera name
|
2012-09-10 01:42:57 +02:00
|
|
|
glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
|
2012-01-28 02:05:23 +01:00
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
|
|
|
m_pScreenFont->MakeCurrent();
|
|
|
|
glEnable(GL_ALPHA_TEST);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
m_pScreenFont->PrintText(3.0f, (float)view->mHeight - 1.0f - 6.0f, 0.0f, view->mCamera->GetName());
|
2013-01-06 20:24:25 +01:00
|
|
|
|
2012-01-28 02:05:23 +01:00
|
|
|
glDisable(GL_ALPHA_TEST);
|
|
|
|
glDisable(GL_TEXTURE_2D);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-01-28 02:05:23 +01:00
|
|
|
glDepthMask(GL_TRUE);
|
|
|
|
glEnable(GL_DEPTH_TEST);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Initialize OpenGL
|
|
|
|
void Project::RenderInitialize()
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
glEnable(GL_POLYGON_OFFSET_FILL);
|
|
|
|
glPolygonOffset(0.5f, 0.1f);
|
|
|
|
|
|
|
|
glEnable(GL_DEPTH_TEST);
|
|
|
|
glDepthFunc(GL_LEQUAL);
|
|
|
|
glDepthMask(GL_TRUE);
|
|
|
|
|
|
|
|
// Load font
|
2011-09-20 01:03:28 +02:00
|
|
|
if (!m_pScreenFont->IsLoaded())
|
2012-04-02 07:52:22 +02:00
|
|
|
m_pScreenFont->Initialize();
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
glAlphaFunc(GL_GREATER, 0.0625);
|
|
|
|
|
|
|
|
if (m_nScene & LC_SCENE_FLOOR)
|
2012-10-12 20:21:45 +02:00
|
|
|
m_pTerrain->LoadTexture();
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
if (m_nScene & LC_SCENE_BG)
|
2012-10-12 20:21:45 +02:00
|
|
|
if (!m_pBackground->Load(m_strBackground, LC_TEXTURE_WRAPU | LC_TEXTURE_WRAPV))
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
|
|
|
m_nScene &= ~LC_SCENE_BG;
|
|
|
|
// AfxMessageBox ("Could not load background");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Grid display list
|
|
|
|
if (m_nGridList == 0)
|
|
|
|
m_nGridList = glGenLists(1);
|
|
|
|
glNewList (m_nGridList, GL_COMPILE);
|
|
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
|
|
i = 2*(4*m_nGridSize+2); // verts needed (2*lines)
|
|
|
|
float *grid = (float*)malloc(i*sizeof(float[3]));
|
|
|
|
float x = m_nGridSize*0.8f;
|
|
|
|
|
|
|
|
for (int j = 0; j <= m_nGridSize*2; j++)
|
|
|
|
{
|
|
|
|
grid[j*12] = x;
|
|
|
|
grid[j*12+1] = m_nGridSize*0.8f;
|
|
|
|
grid[j*12+2] = 0;
|
|
|
|
grid[j*12+3] = x;
|
|
|
|
grid[j*12+4] = -m_nGridSize*0.8f;
|
|
|
|
grid[j*12+5] = 0;
|
|
|
|
grid[j*12+6] = m_nGridSize*0.8f;
|
|
|
|
grid[j*12+7] = x;
|
|
|
|
grid[j*12+8] = 0;
|
|
|
|
grid[j*12+9] = -m_nGridSize*0.8f;
|
|
|
|
grid[j*12+10] = x;
|
|
|
|
grid[j*12+11] = 0;
|
|
|
|
x -= 0.8f;
|
|
|
|
}
|
|
|
|
glVertexPointer(3, GL_FLOAT, 0, grid);
|
|
|
|
glDrawArrays(GL_LINES, 0, i);
|
|
|
|
glEndList();
|
|
|
|
free(grid);
|
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Project functions
|
|
|
|
|
|
|
|
void Project::AddPiece(Piece* pPiece)
|
|
|
|
{
|
|
|
|
if (m_pPieces != NULL)
|
|
|
|
{
|
|
|
|
pPiece->m_pNext = m_pPieces;
|
|
|
|
m_pPieces = pPiece;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_pPieces = pPiece;
|
|
|
|
pPiece->m_pNext = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Project::RemovePiece(Piece* pPiece)
|
|
|
|
{
|
|
|
|
Piece* pTemp, *pLast;
|
|
|
|
pLast = NULL;
|
|
|
|
|
|
|
|
for (pTemp = m_pPieces; pTemp; pLast = pTemp, pTemp = pTemp->m_pNext)
|
|
|
|
if (pTemp == pPiece)
|
|
|
|
{
|
|
|
|
if (pLast != NULL)
|
|
|
|
pLast->m_pNext = pTemp->m_pNext;
|
|
|
|
else
|
|
|
|
m_pPieces = pTemp->m_pNext;
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Project::CalculateStep()
|
|
|
|
{
|
|
|
|
Piece* pPiece;
|
|
|
|
Light* pLight;
|
|
|
|
|
|
|
|
for (pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
|
|
|
pPiece->UpdatePosition(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation);
|
|
|
|
|
2012-08-22 03:13:32 +02:00
|
|
|
for (int CameraIdx = 0; CameraIdx < mCameras.GetSize(); CameraIdx++)
|
|
|
|
mCameras[CameraIdx]->UpdatePosition(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
for (pLight = m_pLights; pLight; pLight = pLight->m_pNext)
|
|
|
|
pLight->UpdatePosition(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Returns true if anything was removed (used by cut and del)
|
|
|
|
bool Project::RemoveSelectedObjects()
|
|
|
|
{
|
|
|
|
Piece* pPiece;
|
|
|
|
Light* pLight;
|
|
|
|
void* pPrev;
|
2013-02-12 23:07:52 +01:00
|
|
|
bool RemovedPiece = false;
|
|
|
|
bool RemovedCamera = false;
|
|
|
|
bool RemovedLight = false;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
pPiece = m_pPieces;
|
|
|
|
while (pPiece)
|
|
|
|
{
|
|
|
|
if (pPiece->IsSelected())
|
|
|
|
{
|
|
|
|
Piece* pTemp;
|
|
|
|
pTemp = pPiece->m_pNext;
|
|
|
|
|
2013-02-12 23:07:52 +01:00
|
|
|
RemovedPiece = true;
|
2011-09-07 23:06:51 +02:00
|
|
|
RemovePiece(pPiece);
|
|
|
|
delete pPiece;
|
|
|
|
pPiece = pTemp;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
pPiece = pPiece->m_pNext;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Cameras can't be removed while being used or default
|
2012-08-22 03:13:32 +02:00
|
|
|
for (int CameraIdx = 0; CameraIdx < mCameras.GetSize(); CameraIdx++)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2012-08-22 03:13:32 +02:00
|
|
|
Camera* pCamera = mCameras[CameraIdx];
|
|
|
|
|
|
|
|
if (!pCamera->IsSelected())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
bool CanDelete = true;
|
2012-02-05 03:50:57 +01:00
|
|
|
|
|
|
|
for (int ViewIdx = 0; ViewIdx < m_ViewList.GetSize(); ViewIdx++)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2012-08-20 06:05:56 +02:00
|
|
|
if (pCamera == m_ViewList[ViewIdx]->mCamera)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2012-08-22 03:13:32 +02:00
|
|
|
CanDelete = false;
|
2011-09-07 23:06:51 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-22 03:13:32 +02:00
|
|
|
if (!CanDelete)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
mCameras.RemoveIndex(CameraIdx);
|
|
|
|
CameraIdx--;
|
|
|
|
delete pCamera;
|
2013-01-06 20:24:25 +01:00
|
|
|
|
2013-02-12 23:07:52 +01:00
|
|
|
RemovedCamera = true;
|
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-02-12 23:07:52 +01:00
|
|
|
if (RemovedCamera)
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateCameraMenu(mCameras, m_ActiveView ? m_ActiveView->mCamera : NULL);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
for (pPrev = NULL, pLight = m_pLights; pLight; )
|
|
|
|
{
|
|
|
|
if (pLight->IsSelected())
|
|
|
|
{
|
|
|
|
if (pPrev)
|
|
|
|
{
|
|
|
|
((Light*)pPrev)->m_pNext = pLight->m_pNext;
|
|
|
|
delete pLight;
|
|
|
|
pLight = ((Light*)pPrev)->m_pNext;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_pLights = m_pLights->m_pNext;
|
|
|
|
delete pLight;
|
|
|
|
pLight = m_pLights;
|
|
|
|
}
|
|
|
|
|
2013-02-12 23:07:52 +01:00
|
|
|
RemovedLight = true;
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pPrev = pLight;
|
|
|
|
pLight = pLight->m_pNext;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
RemoveEmptyGroups();
|
|
|
|
// CalculateStep();
|
|
|
|
// AfxGetMainWnd()->PostMessage(WM_LC_UPDATE_INFO, NULL, OT_PIECE);
|
|
|
|
|
2013-02-12 23:07:52 +01:00
|
|
|
return RemovedPiece || RemovedCamera || RemovedLight;
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Project::UpdateSelection()
|
|
|
|
{
|
|
|
|
unsigned long flags = 0;
|
|
|
|
int SelectedCount = 0;
|
|
|
|
Object* Focus = NULL;
|
|
|
|
|
|
|
|
if (m_pPieces == NULL)
|
|
|
|
flags |= LC_SEL_NO_PIECES;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Piece* pPiece;
|
|
|
|
Group* pGroup = NULL;
|
|
|
|
bool first = true;
|
|
|
|
|
|
|
|
for (pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
|
|
|
{
|
|
|
|
if (pPiece->IsSelected())
|
|
|
|
{
|
|
|
|
SelectedCount++;
|
|
|
|
|
|
|
|
if (pPiece->IsFocused())
|
|
|
|
Focus = pPiece;
|
|
|
|
|
|
|
|
if (flags & LC_SEL_PIECE)
|
|
|
|
flags |= LC_SEL_MULTIPLE;
|
|
|
|
else
|
|
|
|
flags |= LC_SEL_PIECE;
|
|
|
|
|
|
|
|
if (pPiece->GetGroup() != NULL)
|
|
|
|
{
|
|
|
|
flags |= LC_SEL_GROUP;
|
|
|
|
if (pPiece->IsFocused())
|
|
|
|
flags |= LC_SEL_FOCUSGROUP;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (first)
|
|
|
|
{
|
|
|
|
pGroup = pPiece->GetGroup();
|
|
|
|
first = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (pGroup != pPiece->GetGroup())
|
|
|
|
flags |= LC_SEL_CANGROUP;
|
|
|
|
else
|
|
|
|
if (pGroup == NULL)
|
|
|
|
flags |= LC_SEL_CANGROUP;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
flags |= LC_SEL_UNSELECTED;
|
|
|
|
|
|
|
|
if (pPiece->IsHidden())
|
|
|
|
flags |= LC_SEL_HIDDEN;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-22 03:13:32 +02:00
|
|
|
for (int CameraIdx = 0; CameraIdx < mCameras.GetSize(); CameraIdx++)
|
|
|
|
{
|
|
|
|
Camera* pCamera = mCameras[CameraIdx];
|
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
if (pCamera->IsSelected())
|
|
|
|
{
|
|
|
|
flags |= LC_SEL_CAMERA;
|
|
|
|
SelectedCount++;
|
|
|
|
|
|
|
|
if (pCamera->IsEyeFocused() || pCamera->IsTargetFocused())
|
|
|
|
Focus = pCamera;
|
|
|
|
}
|
2012-08-22 03:13:32 +02:00
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
for (Light* pLight = m_pLights; pLight; pLight = pLight->m_pNext)
|
|
|
|
if (pLight->IsSelected())
|
|
|
|
{
|
|
|
|
flags |= LC_SEL_LIGHT;
|
|
|
|
SelectedCount++;
|
|
|
|
|
|
|
|
if (pLight->IsEyeFocused() || pLight->IsTargetFocused())
|
|
|
|
Focus = pLight;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_nTracking == LC_TRACK_NONE)
|
|
|
|
{
|
2012-07-31 07:27:40 +02:00
|
|
|
ActivateOverlay(m_ActiveView, m_nCurAction, LC_OVERLAY_NONE);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateSelectedObjects(flags, SelectedCount, Focus);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Project::CheckAutoSave()
|
|
|
|
{
|
2013-08-17 00:39:47 +02:00
|
|
|
/*
|
2011-09-07 23:06:51 +02:00
|
|
|
m_nSaveTimer += 5;
|
|
|
|
if (m_nAutosave & LC_AUTOSAVE_FLAG)
|
|
|
|
{
|
2012-11-02 02:17:42 +01:00
|
|
|
// int nInterval;
|
|
|
|
// nInterval = m_nAutosave & ~LC_AUTOSAVE_FLAG;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
if (m_nSaveTimer >= (m_nAutosave*60))
|
|
|
|
{
|
|
|
|
m_nSaveTimer = 0;
|
2013-08-17 00:39:47 +02:00
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
if (m_strTempFile.IsEmpty())
|
|
|
|
{
|
|
|
|
char tmpFile[_MAX_PATH], out[_MAX_PATH];
|
|
|
|
GetTempPath (_MAX_PATH, out);
|
|
|
|
GetTempFileName (out, "~LC", 0, tmpFile);
|
|
|
|
DeleteFile (tmpFile);
|
|
|
|
if (char *ptr = strchr(tmpFile, '.')) *ptr = 0;
|
|
|
|
strcat (tmpFile, ".lcd");
|
|
|
|
m_strTempFile = tmpFile;
|
|
|
|
}
|
|
|
|
|
|
|
|
CFile file (m_strTempFile, CFile::modeCreate|CFile::modeWrite|CFile::typeBinary);
|
|
|
|
m_bUndo = TRUE;
|
|
|
|
file.SeekToBegin();
|
|
|
|
CArchive ar(&file, CArchive::store);
|
2013-01-06 20:24:25 +01:00
|
|
|
Serialize(ar);
|
2011-09-07 23:06:51 +02:00
|
|
|
ar.Close();
|
|
|
|
m_bUndo = FALSE;
|
2013-08-17 00:39:47 +02:00
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
2013-08-17 00:39:47 +02:00
|
|
|
*/
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
unsigned char Project::GetLastStep()
|
|
|
|
{
|
|
|
|
unsigned char last = 1;
|
|
|
|
for (Piece* pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
2012-07-06 03:18:55 +02:00
|
|
|
last = lcMax(last, pPiece->GetStepShow());
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
return last;
|
|
|
|
}
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
void Project::FindPiece(bool FindFirst, bool SearchForward)
|
|
|
|
{
|
|
|
|
if (!m_pPieces)
|
|
|
|
return;
|
|
|
|
|
|
|
|
Piece* Start = NULL;
|
|
|
|
if (!FindFirst)
|
|
|
|
{
|
|
|
|
for (Start = m_pPieces; Start; Start = Start->m_pNext)
|
|
|
|
if (Start->IsFocused())
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (Start && !Start->IsVisible(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation))
|
|
|
|
Start = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
SelectAndFocusNone(false);
|
|
|
|
|
|
|
|
Piece* Current = Start;
|
|
|
|
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
if (SearchForward)
|
|
|
|
{
|
|
|
|
Current = Current ? Current->m_pNext : m_pPieces;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (Current == m_pPieces)
|
|
|
|
Current = NULL;
|
|
|
|
|
|
|
|
for (Piece* piece = m_pPieces; piece; piece = piece->m_pNext)
|
|
|
|
{
|
|
|
|
if (piece->m_pNext == Current)
|
|
|
|
{
|
|
|
|
Current = piece;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Current == Start)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (!Current)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!Current->IsVisible(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if ((!mSearchOptions.MatchInfo || Current->mPieceInfo == mSearchOptions.Info) &&
|
|
|
|
(!mSearchOptions.MatchColor || Current->mColorIndex == mSearchOptions.ColorIndex) &&
|
|
|
|
(!mSearchOptions.MatchName || strcasestr(Current->GetName(), mSearchOptions.Name)))
|
|
|
|
{
|
|
|
|
Current->Select(true, true, false);
|
|
|
|
Group* TopGroup = Current->GetTopGroup();
|
|
|
|
if (TopGroup)
|
|
|
|
{
|
|
|
|
for (Piece* piece = m_pPieces; piece; piece = piece->m_pNext)
|
|
|
|
if ((piece->IsVisible(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation)) &&
|
|
|
|
(piece->GetTopGroup() == TopGroup))
|
|
|
|
piece->Select (true, false, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
UpdateSelection();
|
|
|
|
UpdateAllViews();
|
|
|
|
gMainWindow->UpdateFocusObject(Current);
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-13 01:20:40 +01:00
|
|
|
void Project::ZoomExtents(int FirstView, int LastView)
|
|
|
|
{
|
|
|
|
if (!m_pPieces)
|
|
|
|
return;
|
|
|
|
|
|
|
|
float bs[6] = { 10000, 10000, 10000, -10000, -10000, -10000 };
|
|
|
|
|
|
|
|
for (Piece* pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
|
|
|
if (pPiece->IsVisible(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation))
|
|
|
|
pPiece->CompareBoundingBox(bs);
|
|
|
|
|
|
|
|
lcVector3 Center((bs[0] + bs[3]) / 2, (bs[1] + bs[4]) / 2, (bs[2] + bs[5]) / 2);
|
|
|
|
|
|
|
|
lcVector3 Points[8] =
|
|
|
|
{
|
|
|
|
lcVector3(bs[0], bs[1], bs[5]),
|
|
|
|
lcVector3(bs[3], bs[1], bs[5]),
|
|
|
|
lcVector3(bs[0], bs[1], bs[2]),
|
|
|
|
lcVector3(bs[3], bs[4], bs[5]),
|
|
|
|
lcVector3(bs[3], bs[4], bs[2]),
|
|
|
|
lcVector3(bs[0], bs[4], bs[2]),
|
|
|
|
lcVector3(bs[0], bs[4], bs[5]),
|
|
|
|
lcVector3(bs[3], bs[1], bs[2])
|
|
|
|
};
|
|
|
|
|
|
|
|
for (int vp = FirstView; vp < LastView; vp++)
|
|
|
|
{
|
|
|
|
View* view = m_ViewList[vp];
|
|
|
|
|
|
|
|
view->mCamera->ZoomExtents(view, Center, Points, 8, m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation, m_bAddKeys);
|
|
|
|
}
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateFocusObject(GetFocusObject());
|
2012-12-13 01:20:40 +01:00
|
|
|
UpdateOverlayScale();
|
|
|
|
UpdateAllViews();
|
|
|
|
}
|
|
|
|
|
2013-08-16 01:43:18 +02:00
|
|
|
void Project::GetPiecesUsed(lcArray<lcPiecesUsedEntry>& PiecesUsed) const
|
2013-01-24 00:56:34 +01:00
|
|
|
{
|
|
|
|
for (Piece* Piece = m_pPieces; Piece; Piece = Piece->m_pNext)
|
|
|
|
{
|
|
|
|
if (Piece->mPieceInfo->m_strDescription[0] == '~')
|
|
|
|
continue;
|
|
|
|
|
|
|
|
int PieceIdx;
|
|
|
|
|
|
|
|
for (PieceIdx = 0; PieceIdx < PiecesUsed.GetSize(); PieceIdx++)
|
|
|
|
{
|
|
|
|
if (PiecesUsed[PieceIdx].Info != Piece->mPieceInfo || PiecesUsed[PieceIdx].ColorIndex != Piece->mColorIndex)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
PiecesUsed[PieceIdx].Count++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (PieceIdx == PiecesUsed.GetSize())
|
|
|
|
{
|
|
|
|
lcPiecesUsedEntry& Entry = PiecesUsed.Add();
|
|
|
|
|
|
|
|
Entry.Info = Piece->mPieceInfo;
|
|
|
|
Entry.ColorIndex = Piece->mColorIndex;
|
|
|
|
Entry.Count = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
// Create a series of pictures
|
2012-08-20 06:05:56 +02:00
|
|
|
void Project::CreateImages(Image* images, int width, int height, unsigned short from, unsigned short to, bool hilite)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
if (!GL_BeginRenderToTexture(width, height))
|
|
|
|
{
|
|
|
|
gMainWindow->DoMessageBox("Error creating images.", LC_MB_ICONERROR | LC_MB_OK);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
unsigned short oldtime;
|
|
|
|
unsigned char* buf = (unsigned char*)malloc (width*height*3);
|
|
|
|
oldtime = m_bAnimation ? m_nCurFrame : m_nCurStep;
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
View view(this);
|
2012-11-15 02:14:35 +01:00
|
|
|
view.SetCamera(m_ActiveView->mCamera, false);
|
2013-08-09 06:57:18 +02:00
|
|
|
view.mWidth = width;
|
|
|
|
view.mHeight = height;
|
2011-09-20 03:26:31 +02:00
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
if (!hilite)
|
|
|
|
SelectAndFocusNone(false);
|
|
|
|
|
|
|
|
RenderInitialize();
|
|
|
|
|
|
|
|
for (int i = from; i <= to; i++)
|
|
|
|
{
|
|
|
|
if (m_bAnimation)
|
|
|
|
m_nCurFrame = i;
|
|
|
|
else
|
|
|
|
m_nCurStep = i;
|
|
|
|
|
|
|
|
if (hilite)
|
|
|
|
{
|
|
|
|
for (Piece* pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
|
|
|
{
|
2012-02-05 03:50:57 +01:00
|
|
|
if ((m_bAnimation && pPiece->GetFrameShow() == i) ||
|
|
|
|
(!m_bAnimation && pPiece->GetStepShow() == i))
|
|
|
|
pPiece->Select (true, false, false);
|
|
|
|
else
|
|
|
|
pPiece->Select (false, false, false);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CalculateStep();
|
2011-09-20 03:26:31 +02:00
|
|
|
Render(&view, true);
|
2012-02-05 03:50:57 +01:00
|
|
|
images[i-from].FromOpenGL (width, height);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
2012-02-05 03:50:57 +01:00
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
if (m_bAnimation)
|
|
|
|
m_nCurFrame = oldtime;
|
|
|
|
else
|
|
|
|
m_nCurStep = (unsigned char)oldtime;
|
|
|
|
CalculateStep();
|
|
|
|
free (buf);
|
2013-08-09 06:57:18 +02:00
|
|
|
|
|
|
|
GL_EndRenderToTexture();
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
void Project::CreateHTMLPieceList(FILE* f, int nStep, bool bImages, const char* ext)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2012-04-21 01:27:12 +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;
|
|
|
|
|
|
|
|
for (Piece* pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
|
|
|
if ((pPiece->GetStepShow() == nStep) || (nStep == 0))
|
2012-04-21 01:27:12 +02:00
|
|
|
ColorsUsed[pPiece->mColorIndex]++;
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
2012-04-21 01:27:12 +02:00
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
fputs("<br><table border=1><tr><td><center>Piece</center></td>\n",f);
|
|
|
|
|
2012-04-21 01:27:12 +02:00
|
|
|
for (int ColorIdx = 0; ColorIdx < gColorList.GetSize(); ColorIdx++)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2012-04-21 01:27:12 +02:00
|
|
|
if (ColorsUsed[ColorIdx])
|
|
|
|
{
|
|
|
|
ColorsUsed[ColorIdx] = NumColors;
|
|
|
|
NumColors++;
|
|
|
|
fprintf(f, "<td><center>%s</center></td>\n", gColorList[ColorIdx].Name);
|
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
2012-04-21 01:27:12 +02:00
|
|
|
NumColors++;
|
2011-09-07 23:06:51 +02:00
|
|
|
fputs("</tr>\n",f);
|
|
|
|
|
|
|
|
PieceInfo* pInfo;
|
2012-10-02 03:23:44 +02:00
|
|
|
for (int j = 0; j < lcGetPiecesLibrary()->mPieces.GetSize(); j++)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
|
|
|
bool Add = false;
|
2012-04-21 01:27:12 +02:00
|
|
|
memset(PiecesUsed, 0, sizeof(PiecesUsed[0]) * gColorList.GetSize());
|
2012-10-02 03:23:44 +02:00
|
|
|
pInfo = lcGetPiecesLibrary()->mPieces[j];
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-04-21 01:27:12 +02:00
|
|
|
for (Piece* pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2012-05-17 23:52:20 +02:00
|
|
|
if ((pPiece->mPieceInfo == pInfo) && ((pPiece->GetStepShow() == nStep) || (nStep == 0)))
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2012-04-21 01:27:12 +02:00
|
|
|
PiecesUsed[pPiece->mColorIndex]++;
|
2011-09-07 23:06:51 +02:00
|
|
|
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
|
2013-01-26 03:23:49 +01:00
|
|
|
fprintf(f, "<tr><td>%s</td>\n", pInfo->m_strDescription);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
int curcol = 1;
|
2012-04-21 01:27:12 +02:00
|
|
|
for (int ColorIdx = 0; ColorIdx < gColorList.GetSize(); ColorIdx++)
|
|
|
|
{
|
|
|
|
if (PiecesUsed[ColorIdx])
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2012-04-21 01:27:12 +02:00
|
|
|
while (curcol != ColorsUsed[ColorIdx] + 1)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
|
|
|
fputs("<td><center>-</center></td>\n", f);
|
|
|
|
curcol++;
|
|
|
|
}
|
|
|
|
|
2012-04-21 01:27:12 +02:00
|
|
|
fprintf(f, "<td><center>%d</center></td>\n", PiecesUsed[ColorIdx]);
|
2011-09-07 23:06:51 +02:00
|
|
|
curcol++;
|
|
|
|
}
|
2012-04-21 01:27:12 +02:00
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-04-21 01:27:12 +02:00
|
|
|
while (curcol != NumColors)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
|
|
|
fputs("<td><center>-</center></td>\n", f);
|
|
|
|
curcol++;
|
|
|
|
}
|
|
|
|
|
|
|
|
fputs("</tr>\n", f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fputs("</table>\n<br>", f);
|
2012-04-21 01:27:12 +02:00
|
|
|
|
|
|
|
delete[] PiecesUsed;
|
|
|
|
delete[] ColorsUsed;
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
void Project::Export3DStudio()
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
if (!m_pPieces)
|
2013-08-17 03:35:02 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->DoMessageBox("Nothing to export.", LC_MB_OK | LC_MB_ICONINFORMATION);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
char FileName[LC_MAXPATH];
|
|
|
|
memset(FileName, 0, sizeof(FileName));
|
|
|
|
|
|
|
|
if (!gMainWindow->DoDialog(LC_DIALOG_EXPORT_3DSTUDIO, FileName))
|
|
|
|
return;
|
|
|
|
|
|
|
|
lcDiskFile File;
|
|
|
|
|
|
|
|
if (!File.Open(FileName, "wb"))
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->DoMessageBox("Could not open file for writing.", LC_MB_OK | LC_MB_ICONERROR);
|
|
|
|
return;
|
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
long M3DStart = File.GetPosition();
|
|
|
|
File.WriteU16(0x4D4D); // CHK_M3DMAGIC
|
|
|
|
File.WriteU32(0);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
File.WriteU16(0x0002); // CHK_M3D_VERSION
|
|
|
|
File.WriteU32(10);
|
|
|
|
File.WriteU32(3);
|
|
|
|
|
|
|
|
long MDataStart = File.GetPosition();
|
|
|
|
File.WriteU16(0x3D3D); // CHK_MDATA
|
|
|
|
File.WriteU32(0);
|
|
|
|
|
|
|
|
File.WriteU16(0x3D3E); // CHK_MESH_VERSION
|
|
|
|
File.WriteU32(10);
|
|
|
|
File.WriteU32(3);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
const int MaterialNameLength = 11;
|
|
|
|
char MaterialName[32];
|
|
|
|
|
|
|
|
for (int ColorIdx = 0; ColorIdx < gColorList.GetSize(); ColorIdx++)
|
2013-08-17 03:35:02 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
lcColor* Color = &gColorList[ColorIdx];
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
sprintf(MaterialName, "Material%03d", ColorIdx);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
long MaterialStart = File.GetPosition();
|
|
|
|
File.WriteU16(0xAFFF); // CHK_MAT_ENTRY
|
|
|
|
File.WriteU32(0);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
File.WriteU16(0xA000); // CHK_MAT_NAME
|
|
|
|
File.WriteU32(6 + MaterialNameLength + 1);
|
|
|
|
File.WriteBuffer(MaterialName, MaterialNameLength + 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
File.WriteU16(0xA010); // CHK_MAT_AMBIENT
|
|
|
|
File.WriteU32(24);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
File.WriteU16(0x0011); // CHK_COLOR_24
|
|
|
|
File.WriteU32(9);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
File.WriteU8(floor(255.0 * Color->Value[0] + 0.5));
|
|
|
|
File.WriteU8(floor(255.0 * Color->Value[1] + 0.5));
|
|
|
|
File.WriteU8(floor(255.0 * Color->Value[2] + 0.5));
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
File.WriteU16(0x0012); // CHK_LIN_COLOR_24
|
|
|
|
File.WriteU32(9);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
File.WriteU8(floor(255.0 * Color->Value[0] + 0.5));
|
|
|
|
File.WriteU8(floor(255.0 * Color->Value[1] + 0.5));
|
|
|
|
File.WriteU8(floor(255.0 * Color->Value[2] + 0.5));
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
File.WriteU16(0xA020); // CHK_MAT_AMBIENT
|
|
|
|
File.WriteU32(24);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
File.WriteU16(0x0011); // CHK_COLOR_24
|
|
|
|
File.WriteU32(9);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
File.WriteU8(floor(255.0 * Color->Value[0] + 0.5));
|
|
|
|
File.WriteU8(floor(255.0 * Color->Value[1] + 0.5));
|
|
|
|
File.WriteU8(floor(255.0 * Color->Value[2] + 0.5));
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
File.WriteU16(0x0012); // CHK_LIN_COLOR_24
|
|
|
|
File.WriteU32(9);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
File.WriteU8(floor(255.0 * Color->Value[0] + 0.5));
|
|
|
|
File.WriteU8(floor(255.0 * Color->Value[1] + 0.5));
|
|
|
|
File.WriteU8(floor(255.0 * Color->Value[2] + 0.5));
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
File.WriteU16(0xA030); // CHK_MAT_SPECULAR
|
|
|
|
File.WriteU32(24);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
File.WriteU16(0x0011); // CHK_COLOR_24
|
|
|
|
File.WriteU32(9);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
File.WriteU8(floor(255.0 * 0.9f + 0.5));
|
|
|
|
File.WriteU8(floor(255.0 * 0.9f + 0.5));
|
|
|
|
File.WriteU8(floor(255.0 * 0.9f + 0.5));
|
|
|
|
|
|
|
|
File.WriteU16(0x0012); // CHK_LIN_COLOR_24
|
|
|
|
File.WriteU32(9);
|
|
|
|
|
|
|
|
File.WriteU8(floor(255.0 * 0.9f + 0.5));
|
|
|
|
File.WriteU8(floor(255.0 * 0.9f + 0.5));
|
|
|
|
File.WriteU8(floor(255.0 * 0.9f + 0.5));
|
|
|
|
|
|
|
|
File.WriteU16(0xA040); // CHK_MAT_SHININESS
|
|
|
|
File.WriteU32(14);
|
|
|
|
|
|
|
|
File.WriteU16(0x0030); // CHK_INT_PERCENTAGE
|
|
|
|
File.WriteU32(8);
|
|
|
|
|
|
|
|
File.WriteS16((lcuint8)floor(100.0 * 0.25 + 0.5));
|
|
|
|
|
|
|
|
File.WriteU16(0xA041); // CHK_MAT_SHIN2PCT
|
|
|
|
File.WriteU32(14);
|
|
|
|
|
|
|
|
File.WriteU16(0x0030); // CHK_INT_PERCENTAGE
|
|
|
|
File.WriteU32(8);
|
|
|
|
|
|
|
|
File.WriteS16((lcuint8)floor(100.0 * 0.05 + 0.5));
|
|
|
|
|
|
|
|
File.WriteU16(0xA050); // CHK_MAT_TRANSPARENCY
|
|
|
|
File.WriteU32(14);
|
|
|
|
|
|
|
|
File.WriteU16(0x0030); // CHK_INT_PERCENTAGE
|
|
|
|
File.WriteU32(8);
|
|
|
|
|
|
|
|
File.WriteS16((lcuint8)floor(100.0 * (1.0f - Color->Value[3]) + 0.5));
|
|
|
|
|
|
|
|
File.WriteU16(0xA052); // CHK_MAT_XPFALL
|
|
|
|
File.WriteU32(14);
|
|
|
|
|
|
|
|
File.WriteU16(0x0030); // CHK_INT_PERCENTAGE
|
|
|
|
File.WriteU32(8);
|
|
|
|
|
|
|
|
File.WriteS16((lcuint8)floor(100.0 * 0.0 + 0.5));
|
|
|
|
|
2013-08-29 08:51:36 +02:00
|
|
|
File.WriteU16(0xA053); // CHK_MAT_REFBLUR
|
|
|
|
File.WriteU32(14);
|
|
|
|
|
|
|
|
File.WriteU16(0x0030); // CHK_INT_PERCENTAGE
|
|
|
|
File.WriteU32(8);
|
|
|
|
|
|
|
|
File.WriteS16((lcuint8)floor(100.0 * 0.2 + 0.5));
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
File.WriteU16(0xA100); // CHK_MAT_SHADING
|
|
|
|
File.WriteU32(8);
|
|
|
|
|
|
|
|
File.WriteS16(3);
|
|
|
|
|
2013-08-29 08:51:36 +02:00
|
|
|
File.WriteU16(0xA084); // CHK_MAT_SELF_ILPCT
|
2013-08-09 06:57:18 +02:00
|
|
|
File.WriteU32(14);
|
|
|
|
|
|
|
|
File.WriteU16(0x0030); // CHK_INT_PERCENTAGE
|
|
|
|
File.WriteU32(8);
|
|
|
|
|
2013-08-29 08:51:36 +02:00
|
|
|
File.WriteS16((lcuint8)floor(100.0 * 0.0 + 0.5));
|
2013-08-09 06:57:18 +02:00
|
|
|
|
|
|
|
File.WriteU16(0xA081); // CHK_MAT_TWO_SIDE
|
|
|
|
File.WriteU32(6);
|
|
|
|
|
|
|
|
File.WriteU16(0xA087); // CHK_MAT_WIRE_SIZE
|
|
|
|
File.WriteU32(10);
|
|
|
|
|
|
|
|
File.WriteFloat(1.0f);
|
|
|
|
|
|
|
|
long MaterialEnd = File.GetPosition();
|
|
|
|
File.Seek(MaterialStart + 2, SEEK_SET);
|
|
|
|
File.WriteU32(MaterialEnd - MaterialStart);
|
|
|
|
File.Seek(MaterialEnd, SEEK_SET);
|
|
|
|
}
|
|
|
|
|
2013-08-29 08:51:36 +02:00
|
|
|
File.WriteU16(0x0100); // CHK_MASTER_SCALE
|
|
|
|
File.WriteU32(10);
|
|
|
|
|
|
|
|
File.WriteFloat(1.0f);
|
|
|
|
|
|
|
|
File.WriteU16(0x1400); // CHK_LO_SHADOW_BIAS
|
|
|
|
File.WriteU32(10);
|
|
|
|
|
|
|
|
File.WriteFloat(1.0f);
|
|
|
|
|
|
|
|
File.WriteU16(0x1420); // CHK_SHADOW_MAP_SIZE
|
|
|
|
File.WriteU32(8);
|
|
|
|
|
|
|
|
File.WriteS16(512);
|
|
|
|
|
|
|
|
File.WriteU16(0x1450); // CHK_SHADOW_FILTER
|
|
|
|
File.WriteU32(10);
|
|
|
|
|
|
|
|
File.WriteFloat(3.0f);
|
|
|
|
|
|
|
|
File.WriteU16(0x1460); // CHK_RAY_BIAS
|
|
|
|
File.WriteU32(10);
|
|
|
|
|
|
|
|
File.WriteFloat(1.0f);
|
|
|
|
|
|
|
|
File.WriteU16(0x1500); // CHK_O_CONSTS
|
|
|
|
File.WriteU32(18);
|
|
|
|
|
|
|
|
File.WriteFloat(0.0f);
|
|
|
|
File.WriteFloat(0.0f);
|
|
|
|
File.WriteFloat(0.0f);
|
|
|
|
|
|
|
|
File.WriteU16(0x2100); // CHK_AMBIENT_LIGHT
|
|
|
|
File.WriteU32(42);
|
|
|
|
|
|
|
|
File.WriteU16(0x0010); // CHK_COLOR_F
|
|
|
|
File.WriteU32(18);
|
|
|
|
|
|
|
|
File.WriteFloat(m_fAmbient[0]);
|
|
|
|
File.WriteFloat(m_fAmbient[1]);
|
|
|
|
File.WriteFloat(m_fAmbient[2]);
|
|
|
|
|
|
|
|
File.WriteU16(0x0013); // CHK_LIN_COLOR_F
|
|
|
|
File.WriteU32(18);
|
|
|
|
|
|
|
|
File.WriteFloat(m_fAmbient[0]);
|
|
|
|
File.WriteFloat(m_fAmbient[1]);
|
|
|
|
File.WriteFloat(m_fAmbient[2]);
|
|
|
|
|
|
|
|
File.WriteU16(0x1200); // CHK_SOLID_BGND
|
|
|
|
File.WriteU32(42);
|
|
|
|
|
|
|
|
File.WriteU16(0x0010); // CHK_COLOR_F
|
|
|
|
File.WriteU32(18);
|
|
|
|
|
|
|
|
File.WriteFloat(m_fBackground[0]);
|
|
|
|
File.WriteFloat(m_fBackground[1]);
|
|
|
|
File.WriteFloat(m_fBackground[2]);
|
|
|
|
|
|
|
|
File.WriteU16(0x0013); // CHK_LIN_COLOR_F
|
|
|
|
File.WriteU32(18);
|
|
|
|
|
|
|
|
File.WriteFloat(m_fBackground[0]);
|
|
|
|
File.WriteFloat(m_fBackground[1]);
|
|
|
|
File.WriteFloat(m_fBackground[2]);
|
|
|
|
|
|
|
|
File.WriteU16(0x1100); // CHK_BIT_MAP
|
|
|
|
File.WriteU32(6 + 1 + strlen(m_strBackground));
|
|
|
|
File.WriteBuffer(m_strBackground, strlen(m_strBackground) + 1);
|
|
|
|
|
|
|
|
File.WriteU16(0x1300); // CHK_V_GRADIENT
|
|
|
|
File.WriteU32(118);
|
|
|
|
|
|
|
|
File.WriteFloat(1.0f);
|
|
|
|
|
|
|
|
File.WriteU16(0x0010); // CHK_COLOR_F
|
|
|
|
File.WriteU32(18);
|
|
|
|
|
|
|
|
File.WriteFloat(m_fGradient1[0]);
|
|
|
|
File.WriteFloat(m_fGradient1[1]);
|
|
|
|
File.WriteFloat(m_fGradient1[2]);
|
|
|
|
|
|
|
|
File.WriteU16(0x0013); // CHK_LIN_COLOR_F
|
|
|
|
File.WriteU32(18);
|
|
|
|
|
|
|
|
File.WriteFloat(m_fGradient1[0]);
|
|
|
|
File.WriteFloat(m_fGradient1[1]);
|
|
|
|
File.WriteFloat(m_fGradient1[2]);
|
|
|
|
|
|
|
|
File.WriteU16(0x0010); // CHK_COLOR_F
|
|
|
|
File.WriteU32(18);
|
|
|
|
|
|
|
|
File.WriteFloat((m_fGradient1[0] + m_fGradient2[0]) / 2.0f);
|
|
|
|
File.WriteFloat((m_fGradient1[1] + m_fGradient2[1]) / 2.0f);
|
|
|
|
File.WriteFloat((m_fGradient1[2] + m_fGradient2[2]) / 2.0f);
|
|
|
|
|
|
|
|
File.WriteU16(0x0013); // CHK_LIN_COLOR_F
|
|
|
|
File.WriteU32(18);
|
|
|
|
|
|
|
|
File.WriteFloat((m_fGradient1[0] + m_fGradient2[0]) / 2.0f);
|
|
|
|
File.WriteFloat((m_fGradient1[1] + m_fGradient2[1]) / 2.0f);
|
|
|
|
File.WriteFloat((m_fGradient1[2] + m_fGradient2[2]) / 2.0f);
|
|
|
|
|
|
|
|
File.WriteU16(0x0010); // CHK_COLOR_F
|
|
|
|
File.WriteU32(18);
|
|
|
|
|
|
|
|
File.WriteFloat(m_fGradient2[0]);
|
|
|
|
File.WriteFloat(m_fGradient2[1]);
|
|
|
|
File.WriteFloat(m_fGradient2[2]);
|
|
|
|
|
|
|
|
File.WriteU16(0x0013); // CHK_LIN_COLOR_F
|
|
|
|
File.WriteU32(18);
|
|
|
|
|
|
|
|
File.WriteFloat(m_fGradient2[0]);
|
|
|
|
File.WriteFloat(m_fGradient2[1]);
|
|
|
|
File.WriteFloat(m_fGradient2[2]);
|
|
|
|
|
|
|
|
if (m_nScene & LC_SCENE_GRADIENT)
|
|
|
|
{
|
|
|
|
File.WriteU16(0x1301); // LIB3DS_USE_V_GRADIENT
|
|
|
|
File.WriteU32(6);
|
|
|
|
}
|
|
|
|
else if (m_nScene & LC_SCENE_BG)
|
|
|
|
{
|
|
|
|
File.WriteU16(0x1101); // LIB3DS_USE_BIT_MAP
|
|
|
|
File.WriteU32(6);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
File.WriteU16(0x1201); // LIB3DS_USE_SOLID_BGND
|
|
|
|
File.WriteU32(6);
|
|
|
|
}
|
|
|
|
|
|
|
|
File.WriteU16(0x2200); // CHK_FOG
|
|
|
|
File.WriteU32(46);
|
|
|
|
|
|
|
|
File.WriteFloat(0.0f);
|
|
|
|
File.WriteFloat(0.0f);
|
|
|
|
File.WriteFloat(1000.0f);
|
|
|
|
File.WriteFloat(100.0f);
|
|
|
|
|
|
|
|
File.WriteU16(0x0010); // CHK_COLOR_F
|
|
|
|
File.WriteU32(18);
|
|
|
|
|
|
|
|
File.WriteFloat(m_fFogColor[0]);
|
|
|
|
File.WriteFloat(m_fFogColor[1]);
|
|
|
|
File.WriteFloat(m_fFogColor[2]);
|
|
|
|
|
|
|
|
File.WriteU16(0x2210); // CHK_FOG_BGND
|
|
|
|
File.WriteU32(6);
|
|
|
|
|
|
|
|
File.WriteU16(0x2302); // CHK_LAYER_FOG
|
|
|
|
File.WriteU32(40);
|
|
|
|
|
|
|
|
File.WriteFloat(0.0f);
|
|
|
|
File.WriteFloat(100.0f);
|
|
|
|
File.WriteFloat(50.0f);
|
|
|
|
File.WriteU32(0x00100000);
|
|
|
|
|
|
|
|
File.WriteU16(0x0010); // CHK_COLOR_F
|
|
|
|
File.WriteU32(18);
|
|
|
|
|
|
|
|
File.WriteFloat(m_fFogColor[0]);
|
|
|
|
File.WriteFloat(m_fFogColor[1]);
|
|
|
|
File.WriteFloat(m_fFogColor[2]);
|
|
|
|
|
|
|
|
File.WriteU16(0x2300); // CHK_DISTANCE_CUE
|
|
|
|
File.WriteU32(28);
|
|
|
|
|
|
|
|
File.WriteFloat(0.0f);
|
|
|
|
File.WriteFloat(0.0f);
|
|
|
|
File.WriteFloat(1000.0f);
|
|
|
|
File.WriteFloat(100.0f);
|
|
|
|
|
|
|
|
File.WriteU16(0x2310); // CHK_DICHK_DCUE_BGNDSTANCE_CUE
|
|
|
|
File.WriteU32(6);
|
|
|
|
|
|
|
|
int NumPieces = 0;
|
2013-08-09 06:57:18 +02:00
|
|
|
for (Piece* piece = m_pPieces; piece; piece = piece->m_pNext)
|
2013-08-17 03:35:02 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
PieceInfo* Info = piece->mPieceInfo;
|
|
|
|
lcMesh* Mesh = Info->mMesh;
|
|
|
|
|
|
|
|
if (Mesh->mIndexType == GL_UNSIGNED_INT)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
long NamedObjectStart = File.GetPosition();
|
|
|
|
File.WriteU16(0x4000); // CHK_NAMED_OBJECT
|
|
|
|
File.WriteU32(0);
|
|
|
|
|
2013-08-29 08:51:36 +02:00
|
|
|
char Name[32];
|
|
|
|
sprintf(Name, "Piece%.3d", NumPieces);
|
|
|
|
NumPieces++;
|
|
|
|
File.WriteBuffer(Name, strlen(Name) + 1);
|
2013-08-09 06:57:18 +02:00
|
|
|
|
|
|
|
long TriObjectStart = File.GetPosition();
|
|
|
|
File.WriteU16(0x4100); // CHK_N_TRI_OBJECT
|
|
|
|
File.WriteU32(0);
|
|
|
|
|
|
|
|
File.WriteU16(0x4110); // CHK_POINT_ARRAY
|
|
|
|
File.WriteU32(8 + 12 * Mesh->mNumVertices);
|
|
|
|
|
|
|
|
File.WriteU16(Mesh->mNumVertices);
|
|
|
|
|
|
|
|
float* Verts = (float*)Mesh->mVertexBuffer.mData;
|
|
|
|
const lcMatrix44& ModelWorld = piece->mModelWorld;
|
|
|
|
|
|
|
|
for (int VertexIdx = 0; VertexIdx < Mesh->mNumVertices; VertexIdx++)
|
|
|
|
{
|
|
|
|
lcVector3 Pos(Verts[VertexIdx * 3], Verts[VertexIdx * 3 + 1], Verts[VertexIdx * 3 + 2]);
|
|
|
|
Pos = lcMul31(Pos, ModelWorld);
|
|
|
|
File.WriteFloat(Pos[0]);
|
|
|
|
File.WriteFloat(Pos[1]);
|
|
|
|
File.WriteFloat(Pos[2]);
|
|
|
|
}
|
|
|
|
|
|
|
|
File.WriteU16(0x4160); // CHK_MESH_MATRIX
|
|
|
|
File.WriteU32(54);
|
|
|
|
|
|
|
|
lcMatrix44 Matrix = lcMatrix44Identity();
|
|
|
|
File.WriteFloats(Matrix[0], 3);
|
|
|
|
File.WriteFloats(Matrix[1], 3);
|
|
|
|
File.WriteFloats(Matrix[2], 3);
|
|
|
|
File.WriteFloats(Matrix[3], 3);
|
|
|
|
|
2013-08-29 08:51:36 +02:00
|
|
|
File.WriteU16(0x4165); // CHK_MESH_COLOR
|
|
|
|
File.WriteU32(7);
|
|
|
|
|
|
|
|
File.WriteU8(0);
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
long FaceArrayStart = File.GetPosition();
|
|
|
|
File.WriteU16(0x4120); // CHK_FACE_ARRAY
|
|
|
|
File.WriteU32(0);
|
|
|
|
|
|
|
|
int NumTriangles = 0;
|
|
|
|
|
|
|
|
for (int SectionIdx = 0; SectionIdx < Mesh->mNumSections; SectionIdx++)
|
2013-08-17 03:35:02 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
lcMeshSection* Section = &Mesh->mSections[SectionIdx];
|
|
|
|
|
|
|
|
if (Section->PrimitiveType != GL_TRIANGLES)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
NumTriangles += Section->NumIndices / 3;
|
2013-08-17 03:35:02 +02:00
|
|
|
}
|
2013-08-09 06:57:18 +02:00
|
|
|
|
|
|
|
File.WriteU16(NumTriangles);
|
|
|
|
|
|
|
|
for (int SectionIdx = 0; SectionIdx < Mesh->mNumSections; SectionIdx++)
|
|
|
|
{
|
|
|
|
lcMeshSection* Section = &Mesh->mSections[SectionIdx];
|
|
|
|
|
|
|
|
if (Section->PrimitiveType != GL_TRIANGLES)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
lcuint16* Indices = (lcuint16*)Mesh->mIndexBuffer.mData + Section->IndexOffset / sizeof(lcuint16);
|
|
|
|
|
|
|
|
for (int IndexIdx = 0; IndexIdx < Section->NumIndices; IndexIdx += 3)
|
|
|
|
{
|
|
|
|
File.WriteU16(Indices[IndexIdx + 0]);
|
|
|
|
File.WriteU16(Indices[IndexIdx + 1]);
|
|
|
|
File.WriteU16(Indices[IndexIdx + 2]);
|
|
|
|
File.WriteU16(7);
|
|
|
|
}
|
2013-08-17 03:35:02 +02:00
|
|
|
}
|
2013-08-09 06:57:18 +02:00
|
|
|
|
|
|
|
NumTriangles = 0;
|
|
|
|
|
|
|
|
for (int SectionIdx = 0; SectionIdx < Mesh->mNumSections; SectionIdx++)
|
2013-08-17 03:35:02 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
lcMeshSection* Section = &Mesh->mSections[SectionIdx];
|
|
|
|
|
|
|
|
if (Section->PrimitiveType != GL_TRIANGLES)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
int MaterialIndex = Section->ColorIndex == gDefaultColor ? piece->mColorIndex : Section->ColorIndex;
|
|
|
|
|
|
|
|
File.WriteU16(0x4130); // CHK_MSH_MAT_GROUP
|
|
|
|
File.WriteU32(6 + MaterialNameLength + 1 + 2 + 2 * Section->NumIndices / 3);
|
|
|
|
|
|
|
|
sprintf(MaterialName, "Material%03d", MaterialIndex);
|
|
|
|
File.WriteBuffer(MaterialName, MaterialNameLength + 1);
|
|
|
|
|
|
|
|
File.WriteU16(Section->NumIndices / 3);
|
|
|
|
|
|
|
|
for (int IndexIdx = 0; IndexIdx < Section->NumIndices; IndexIdx += 3)
|
|
|
|
File.WriteU16(NumTriangles++);
|
|
|
|
}
|
|
|
|
|
|
|
|
long FaceArrayEnd = File.GetPosition();
|
|
|
|
File.Seek(FaceArrayStart + 2, SEEK_SET);
|
|
|
|
File.WriteU32(FaceArrayEnd - FaceArrayStart);
|
|
|
|
File.Seek(FaceArrayEnd, SEEK_SET);
|
|
|
|
|
|
|
|
long TriObjectEnd = File.GetPosition();
|
|
|
|
File.Seek(TriObjectStart + 2, SEEK_SET);
|
|
|
|
File.WriteU32(TriObjectEnd - TriObjectStart);
|
|
|
|
File.Seek(TriObjectEnd, SEEK_SET);
|
|
|
|
|
|
|
|
long NamedObjectEnd = File.GetPosition();
|
|
|
|
File.Seek(NamedObjectStart + 2, SEEK_SET);
|
|
|
|
File.WriteU32(NamedObjectEnd - NamedObjectStart);
|
|
|
|
File.Seek(NamedObjectEnd, SEEK_SET);
|
2013-08-17 03:35:02 +02:00
|
|
|
}
|
2013-08-09 06:57:18 +02:00
|
|
|
|
|
|
|
long MDataEnd = File.GetPosition();
|
|
|
|
File.Seek(MDataStart + 2, SEEK_SET);
|
|
|
|
File.WriteU32(MDataEnd - MDataStart);
|
|
|
|
File.Seek(MDataEnd, SEEK_SET);
|
|
|
|
|
|
|
|
long KFDataStart = File.GetPosition();
|
|
|
|
File.WriteU16(0xB000); // CHK_KFDATA
|
|
|
|
File.WriteU32(0);
|
|
|
|
|
|
|
|
File.WriteU16(0xB00A); // LIB3DS_KFHDR
|
2013-08-29 08:51:36 +02:00
|
|
|
File.WriteU32(6 + 2 + 1 + 4);
|
2013-08-09 06:57:18 +02:00
|
|
|
|
|
|
|
File.WriteS16(5);
|
2013-08-29 08:51:36 +02:00
|
|
|
File.WriteU8(0);
|
2013-08-09 06:57:18 +02:00
|
|
|
File.WriteS32(100);
|
|
|
|
|
|
|
|
long KFDataEnd = File.GetPosition();
|
|
|
|
File.Seek(KFDataStart + 2, SEEK_SET);
|
|
|
|
File.WriteU32(KFDataEnd - KFDataStart);
|
|
|
|
File.Seek(KFDataEnd, SEEK_SET);
|
|
|
|
|
|
|
|
long M3DEnd = File.GetPosition();
|
|
|
|
File.Seek(M3DStart + 2, SEEK_SET);
|
|
|
|
File.WriteU32(M3DEnd - M3DStart);
|
|
|
|
File.Seek(M3DEnd, SEEK_SET);
|
2013-08-17 03:35:02 +02:00
|
|
|
}
|
2013-08-09 06:57:18 +02:00
|
|
|
|
2013-08-17 03:35:02 +02:00
|
|
|
void Project::ExportPOVRay(lcFile& POVFile)
|
|
|
|
{
|
|
|
|
char Line[1024];
|
2013-08-09 06:57:18 +02:00
|
|
|
|
2013-08-17 03:35:02 +02:00
|
|
|
lcPiecesLibrary* Library = lcGetPiecesLibrary();
|
|
|
|
char* PieceTable = new char[Library->mPieces.GetSize() * LC_PIECE_NAME_LEN];
|
|
|
|
int* PieceFlags = new int[Library->mPieces.GetSize()];
|
|
|
|
int NumColors = gColorList.GetSize();
|
|
|
|
char* ColorTable = new char[NumColors * LC_MAX_COLOR_NAME];
|
2013-08-09 06:57:18 +02:00
|
|
|
|
2013-08-17 03:35:02 +02:00
|
|
|
memset(PieceTable, 0, Library->mPieces.GetSize() * LC_PIECE_NAME_LEN);
|
|
|
|
memset(PieceFlags, 0, Library->mPieces.GetSize() * sizeof(int));
|
|
|
|
memset(ColorTable, 0, NumColors * LC_MAX_COLOR_NAME);
|
2013-08-09 06:57:18 +02:00
|
|
|
|
2013-08-17 03:35:02 +02:00
|
|
|
enum
|
|
|
|
{
|
|
|
|
LGEO_PIECE_LGEO = 0x01,
|
|
|
|
LGEO_PIECE_AR = 0x02,
|
|
|
|
LGEO_PIECE_SLOPE = 0x04
|
|
|
|
};
|
2013-08-09 06:57:18 +02:00
|
|
|
|
2013-08-17 03:35:02 +02:00
|
|
|
enum
|
|
|
|
{
|
|
|
|
LGEO_COLOR_SOLID = 0x01,
|
|
|
|
LGEO_COLOR_TRANSPARENT = 0x02,
|
|
|
|
LGEO_COLOR_CHROME = 0x04,
|
|
|
|
LGEO_COLOR_PEARL = 0x08,
|
|
|
|
LGEO_COLOR_METALLIC = 0x10,
|
|
|
|
LGEO_COLOR_RUBBER = 0x20,
|
|
|
|
LGEO_COLOR_GLITTER = 0x40
|
|
|
|
};
|
2013-08-09 06:57:18 +02:00
|
|
|
|
2013-08-17 03:35:02 +02:00
|
|
|
char LGEOPath[LC_MAXPATH];
|
|
|
|
strcpy(LGEOPath, lcGetProfileString(LC_PROFILE_POVRAY_LGEO_PATH));
|
2013-08-09 06:57:18 +02:00
|
|
|
|
2013-08-17 03:35:02 +02:00
|
|
|
// Parse LGEO tables.
|
|
|
|
if (LGEOPath[0])
|
2013-08-09 06:57:18 +02:00
|
|
|
{
|
2013-08-17 03:35:02 +02:00
|
|
|
lcDiskFile TableFile, ColorFile;
|
|
|
|
char Filename[LC_MAXPATH];
|
2013-08-09 06:57:18 +02:00
|
|
|
|
2013-08-17 03:35:02 +02:00
|
|
|
int Length = strlen(LGEOPath);
|
2013-08-09 06:57:18 +02:00
|
|
|
|
2013-08-17 03:35:02 +02:00
|
|
|
if ((LGEOPath[Length - 1] != '\\') && (LGEOPath[Length - 1] != '/'))
|
|
|
|
strcat(LGEOPath, "/");
|
2013-08-09 06:57:18 +02:00
|
|
|
|
2013-08-17 03:35:02 +02:00
|
|
|
strcpy(Filename, LGEOPath);
|
|
|
|
strcat(Filename, "lg_elements.lst");
|
2013-08-09 06:57:18 +02:00
|
|
|
|
2013-08-17 03:35:02 +02:00
|
|
|
if (!TableFile.Open(Filename, "rt"))
|
2013-08-09 06:57:18 +02:00
|
|
|
{
|
2013-08-17 03:35:02 +02:00
|
|
|
delete[] PieceTable;
|
|
|
|
delete[] PieceFlags;
|
|
|
|
gMainWindow->DoMessageBox("Could not find LGEO files.", LC_MB_OK | LC_MB_ICONERROR);
|
|
|
|
return;
|
2013-08-09 06:57:18 +02:00
|
|
|
}
|
|
|
|
|
2013-08-17 03:35:02 +02:00
|
|
|
while (TableFile.ReadLine(Line, sizeof(Line)))
|
2013-08-09 06:57:18 +02:00
|
|
|
{
|
2013-08-17 03:35:02 +02:00
|
|
|
char Src[1024], Dst[1024], Flags[1024];
|
2013-08-09 06:57:18 +02:00
|
|
|
|
2013-08-17 03:35:02 +02:00
|
|
|
if (*Line == ';')
|
2013-08-09 06:57:18 +02:00
|
|
|
continue;
|
|
|
|
|
2013-08-17 03:35:02 +02:00
|
|
|
if (sscanf(Line,"%s%s%s", Src, Dst, Flags) != 3)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
strupr(Src);
|
|
|
|
|
|
|
|
PieceInfo* Info = Library->FindPiece(Src, false);
|
|
|
|
if (!Info)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
int Index = Library->mPieces.FindIndex(Info);
|
|
|
|
|
|
|
|
if (strchr(Flags, 'L'))
|
|
|
|
{
|
|
|
|
PieceFlags[Index] |= LGEO_PIECE_LGEO;
|
|
|
|
sprintf(PieceTable + Index * LC_PIECE_NAME_LEN, "lg_%s", Dst);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (strchr(Flags, 'A'))
|
|
|
|
{
|
|
|
|
PieceFlags[Index] |= LGEO_PIECE_AR;
|
|
|
|
sprintf(PieceTable + Index * LC_PIECE_NAME_LEN, "ar_%s", Dst);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (strchr(Flags, 'S'))
|
|
|
|
PieceFlags[Index] |= LGEO_PIECE_SLOPE;
|
2013-08-09 06:57:18 +02:00
|
|
|
}
|
|
|
|
|
2013-08-17 03:35:02 +02:00
|
|
|
strcpy(Filename, LGEOPath);
|
|
|
|
strcat(Filename, "lg_colors.lst");
|
2013-08-09 06:57:18 +02:00
|
|
|
|
2013-08-17 03:35:02 +02:00
|
|
|
if (!ColorFile.Open(Filename, "rt"))
|
|
|
|
{
|
|
|
|
delete[] PieceTable;
|
|
|
|
delete[] PieceFlags;
|
|
|
|
gMainWindow->DoMessageBox("Could not find LGEO files.", LC_MB_OK | LC_MB_ICONERROR);
|
|
|
|
return;
|
|
|
|
}
|
2013-08-09 06:57:18 +02:00
|
|
|
|
2013-08-17 03:35:02 +02:00
|
|
|
while (ColorFile.ReadLine(Line, sizeof(Line)))
|
2013-08-09 06:57:18 +02:00
|
|
|
{
|
2013-08-17 03:35:02 +02:00
|
|
|
char Name[1024], Flags[1024];
|
|
|
|
int Code;
|
2013-08-09 06:57:18 +02:00
|
|
|
|
2013-08-17 03:35:02 +02:00
|
|
|
if (*Line == ';')
|
2013-08-09 06:57:18 +02:00
|
|
|
continue;
|
|
|
|
|
2013-08-17 03:35:02 +02:00
|
|
|
if (sscanf(Line,"%d%s%s", &Code, Name, Flags) != 3)
|
|
|
|
continue;
|
2013-08-09 06:57:18 +02:00
|
|
|
|
2013-08-17 03:35:02 +02:00
|
|
|
int Color = lcGetColorIndex(Code);
|
|
|
|
if (Color >= NumColors)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
strcpy(&ColorTable[Color * LC_MAX_COLOR_NAME], Name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const char* OldLocale = setlocale(LC_NUMERIC, "C");
|
|
|
|
|
|
|
|
// Add includes.
|
|
|
|
if (LGEOPath[0])
|
|
|
|
{
|
|
|
|
POVFile.WriteLine("#include \"lg_defs.inc\"\n#include \"lg_color.inc\"\n\n");
|
|
|
|
|
|
|
|
for (Piece* piece = m_pPieces; piece; piece = piece->m_pNext)
|
2013-08-09 06:57:18 +02:00
|
|
|
{
|
2013-08-17 03:35:02 +02:00
|
|
|
PieceInfo* Info = piece->mPieceInfo;
|
2013-08-09 06:57:18 +02:00
|
|
|
|
2013-08-17 03:35:02 +02:00
|
|
|
for (Piece* FirstPiece = m_pPieces; FirstPiece; FirstPiece = FirstPiece->m_pNext)
|
|
|
|
{
|
|
|
|
if (FirstPiece->mPieceInfo != Info)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (FirstPiece != piece)
|
|
|
|
break;
|
|
|
|
|
|
|
|
int Index = Library->mPieces.FindIndex(Info);
|
|
|
|
|
|
|
|
if (PieceTable[Index * LC_PIECE_NAME_LEN])
|
|
|
|
{
|
|
|
|
sprintf(Line, "#include \"%s.inc\"\n", PieceTable + Index * LC_PIECE_NAME_LEN);
|
|
|
|
POVFile.WriteLine(Line);
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
2013-08-09 06:57:18 +02:00
|
|
|
}
|
2013-08-17 03:35:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
POVFile.WriteLine("\n");
|
2013-08-09 06:57:18 +02:00
|
|
|
}
|
2013-08-17 03:35:02 +02:00
|
|
|
else
|
|
|
|
POVFile.WriteLine("#include \"colors.inc\"\n\n");
|
2013-08-09 06:57:18 +02:00
|
|
|
|
2013-08-17 03:35:02 +02:00
|
|
|
// Add color definitions.
|
|
|
|
for (int ColorIdx = 0; ColorIdx < gColorList.GetSize(); ColorIdx++)
|
|
|
|
{
|
|
|
|
lcColor* Color = &gColorList[ColorIdx];
|
2013-08-09 06:57:18 +02:00
|
|
|
|
2013-08-17 03:35:02 +02:00
|
|
|
if (lcIsColorTranslucent(ColorIdx))
|
|
|
|
{
|
|
|
|
sprintf(Line, "#declare lc_%s = texture { pigment { rgb <%f, %f, %f> filter 0.9 } finish { ambient 0.3 diffuse 0.2 reflection 0.25 phong 0.3 phong_size 60 } }\n",
|
|
|
|
Color->SafeName, Color->Value[0], Color->Value[1], Color->Value[2]);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sprintf(Line, "#declare lc_%s = texture { pigment { rgb <%f, %f, %f> } finish { ambient 0.1 phong 0.2 phong_size 20 } }\n",
|
|
|
|
Color->SafeName, Color->Value[0], Color->Value[1], Color->Value[2]);
|
|
|
|
}
|
2013-08-09 06:57:18 +02:00
|
|
|
|
2013-08-17 03:35:02 +02:00
|
|
|
POVFile.WriteLine(Line);
|
|
|
|
|
|
|
|
if (!ColorTable[ColorIdx * LC_MAX_COLOR_NAME])
|
|
|
|
sprintf(&ColorTable[ColorIdx * LC_MAX_COLOR_NAME], "lc_%s", Color->SafeName);
|
|
|
|
}
|
|
|
|
|
|
|
|
POVFile.WriteLine("\n");
|
|
|
|
|
|
|
|
// Add pieces not included in LGEO.
|
|
|
|
for (Piece* piece = m_pPieces; piece; piece = piece->m_pNext)
|
|
|
|
{
|
|
|
|
PieceInfo* Info = piece->mPieceInfo;
|
|
|
|
int Index = Library->mPieces.FindIndex(Info);
|
|
|
|
|
|
|
|
if (PieceTable[Index * LC_PIECE_NAME_LEN])
|
|
|
|
continue;
|
|
|
|
|
|
|
|
char Name[LC_PIECE_NAME_LEN];
|
|
|
|
char* Ptr;
|
|
|
|
|
|
|
|
strcpy(Name, Info->m_strName);
|
|
|
|
while ((Ptr = strchr(Name, '-')))
|
|
|
|
*Ptr = '_';
|
|
|
|
|
|
|
|
sprintf(PieceTable + Index * LC_PIECE_NAME_LEN, "lc_%s", Name);
|
|
|
|
|
|
|
|
Info->mMesh->ExportPOVRay(POVFile, Name, ColorTable);
|
|
|
|
|
|
|
|
POVFile.WriteLine("}\n\n");
|
|
|
|
|
|
|
|
sprintf(Line, "#declare lc_%s_clear = lc_%s\n\n", Name, Name);
|
|
|
|
POVFile.WriteLine(Line);
|
|
|
|
}
|
|
|
|
|
|
|
|
const lcVector3& Position = m_ActiveView->mCamera->mPosition;
|
|
|
|
const lcVector3& Target = m_ActiveView->mCamera->mTargetPosition;
|
|
|
|
const lcVector3& Up = m_ActiveView->mCamera->mUpVector;
|
|
|
|
|
|
|
|
sprintf(Line, "camera {\n sky<%1g,%1g,%1g>\n location <%1g, %1g, %1g>\n look_at <%1g, %1g, %1g>\n angle %.0f\n}\n\n",
|
|
|
|
Up[0], Up[1], Up[2], Position[1], Position[0], Position[2], Target[1], Target[0], Target[2], m_ActiveView->mCamera->m_fovy);
|
|
|
|
POVFile.WriteLine(Line);
|
|
|
|
sprintf(Line, "background { color rgb <%1g, %1g, %1g> }\n\nlight_source { <0, 0, 20> White shadowless }\n\n",
|
|
|
|
m_fBackground[0], m_fBackground[1], m_fBackground[2]);
|
|
|
|
POVFile.WriteLine(Line);
|
|
|
|
|
|
|
|
for (Piece* piece = m_pPieces; piece; piece = piece->m_pNext)
|
|
|
|
{
|
|
|
|
int Index = Library->mPieces.FindIndex(piece->mPieceInfo);
|
|
|
|
int Color;
|
|
|
|
|
|
|
|
Color = piece->mColorIndex;
|
|
|
|
const char* Suffix = lcIsColorTranslucent(Color) ? "_clear" : "";
|
|
|
|
|
|
|
|
const float* f = piece->mModelWorld;
|
|
|
|
|
|
|
|
if (PieceFlags[Index] & LGEO_PIECE_SLOPE)
|
|
|
|
{
|
|
|
|
sprintf(Line, "merge {\n object {\n %s%s\n texture { %s }\n }\n"
|
|
|
|
" object {\n %s_slope\n texture { %s normal { bumps 0.3 scale 0.02 } }\n }\n"
|
|
|
|
" matrix <%.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f>\n}\n",
|
|
|
|
PieceTable + Index * LC_PIECE_NAME_LEN, Suffix, &ColorTable[Color * LC_MAX_COLOR_NAME], PieceTable + Index * LC_PIECE_NAME_LEN, &ColorTable[Color * LC_MAX_COLOR_NAME],
|
|
|
|
-f[5], -f[4], -f[6], -f[1], -f[0], -f[2], f[9], f[8], f[10], f[13], f[12], f[14]);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sprintf(Line, "object {\n %s%s\n texture { %s }\n matrix <%.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f>\n}\n",
|
|
|
|
PieceTable + Index * LC_PIECE_NAME_LEN, Suffix, &ColorTable[Color * LC_MAX_COLOR_NAME], -f[5], -f[4], -f[6], -f[1], -f[0], -f[2], f[9], f[8], f[10], f[13], f[12], f[14]);
|
|
|
|
}
|
|
|
|
|
|
|
|
POVFile.WriteLine(Line);
|
|
|
|
}
|
|
|
|
|
|
|
|
delete[] PieceTable;
|
|
|
|
delete[] PieceFlags;
|
|
|
|
setlocale(LC_NUMERIC, OldLocale);
|
|
|
|
POVFile.Close();
|
2013-08-09 06:57:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Special notifications.
|
|
|
|
void Project::HandleNotify(LC_NOTIFY id, unsigned long param)
|
|
|
|
{
|
|
|
|
switch (id)
|
|
|
|
{
|
|
|
|
case LC_CAPTURE_LOST:
|
|
|
|
{
|
|
|
|
if (m_nTracking != LC_TRACK_NONE)
|
|
|
|
StopTracking(false);
|
|
|
|
} break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Project::HandleCommand(LC_COMMANDS id)
|
|
|
|
{
|
|
|
|
switch (id)
|
|
|
|
{
|
2011-09-07 23:06:51 +02:00
|
|
|
case LC_FILE_NEW:
|
|
|
|
{
|
|
|
|
if (!SaveModified())
|
|
|
|
return; // leave the original one
|
|
|
|
|
|
|
|
OnNewDocument();
|
|
|
|
UpdateAllViews ();
|
|
|
|
} break;
|
2013-01-06 20:24:25 +01:00
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
case LC_FILE_OPEN:
|
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
char FileName[LC_MAXPATH];
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
if (m_strPathName[0])
|
|
|
|
strcpy(FileName, m_strPathName);
|
|
|
|
else
|
|
|
|
strcpy(FileName, lcGetProfileString(LC_PROFILE_PROJECTS_PATH));
|
|
|
|
|
|
|
|
if (gMainWindow->DoDialog(LC_DIALOG_OPEN_PROJECT, FileName))
|
|
|
|
OpenProject(FileName);
|
2011-09-07 23:06:51 +02:00
|
|
|
} break;
|
2013-01-06 20:24:25 +01:00
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
case LC_FILE_MERGE:
|
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
char FileName[LC_MAXPATH];
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
if (m_strPathName[0])
|
|
|
|
strcpy(FileName, m_strPathName);
|
|
|
|
else
|
|
|
|
strcpy(FileName, lcGetProfileString(LC_PROFILE_PROJECTS_PATH));
|
|
|
|
|
|
|
|
if (gMainWindow->DoDialog(LC_DIALOG_MERGE_PROJECT, FileName))
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2012-03-23 00:44:56 +01:00
|
|
|
lcDiskFile file;
|
2013-08-09 06:57:18 +02:00
|
|
|
if (file.Open(FileName, "rb"))
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
|
|
|
if (file.GetLength() != 0)
|
|
|
|
{
|
|
|
|
FileLoad(&file, false, true);
|
|
|
|
CheckPoint("Merging");
|
|
|
|
}
|
|
|
|
file.Close();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_FILE_SAVE:
|
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
DoSave(m_strPathName);
|
2011-09-07 23:06:51 +02:00
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_FILE_SAVEAS:
|
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
DoSave(NULL);
|
2011-09-07 23:06:51 +02:00
|
|
|
} break;
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
case LC_FILE_SAVE_IMAGE:
|
|
|
|
{
|
|
|
|
lcImageDialogOptions Options;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-14 00:17:25 +02:00
|
|
|
int ImageOptions = lcGetProfileInt(LC_PROFILE_IMAGE_OPTIONS);
|
|
|
|
|
|
|
|
Options.Format = (LC_IMAGE_FORMAT)(ImageOptions & ~(LC_IMAGE_MASK));
|
|
|
|
Options.Transparent = (ImageOptions & LC_IMAGE_TRANSPARENT) != 0;
|
|
|
|
Options.Width = lcGetProfileInt(LC_PROFILE_IMAGE_WIDTH);
|
|
|
|
Options.Height = lcGetProfileInt(LC_PROFILE_IMAGE_HEIGHT);
|
|
|
|
|
2012-12-13 03:51:12 +01:00
|
|
|
if (m_strPathName[0])
|
2013-08-09 06:57:18 +02:00
|
|
|
strcpy(Options.FileName, m_strPathName);
|
2012-12-13 03:51:12 +01:00
|
|
|
else if (m_strTitle[0])
|
2013-08-09 06:57:18 +02:00
|
|
|
strcpy(Options.FileName, m_strTitle);
|
2012-12-13 03:51:12 +01:00
|
|
|
else
|
2013-08-09 06:57:18 +02:00
|
|
|
strcpy(Options.FileName, "Image");
|
2012-12-13 03:51:12 +01:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
if (Options.FileName[0])
|
2012-12-13 03:51:12 +01:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
char* ext = strrchr(Options.FileName, '.');
|
2012-12-13 03:51:12 +01:00
|
|
|
|
|
|
|
if (ext && (!stricmp(ext, ".lcd") || !stricmp(ext, ".dat") || !stricmp(ext, ".ldr")))
|
|
|
|
*ext = 0;
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
switch (Options.Format)
|
2012-12-13 03:51:12 +01:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
case LC_IMAGE_BMP: strcat(Options.FileName, ".bmp");
|
|
|
|
break;
|
|
|
|
case LC_IMAGE_JPG: strcat(Options.FileName, ".jpg");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
case LC_IMAGE_PNG: strcat(Options.FileName, ".png");
|
|
|
|
break;
|
2012-12-13 03:51:12 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
if (m_bAnimation)
|
|
|
|
{
|
|
|
|
Options.Start = 1;
|
|
|
|
Options.End = m_nTotalFrames;
|
|
|
|
}
|
|
|
|
else
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
Options.Start = m_nCurStep;
|
|
|
|
Options.End = m_nCurStep;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!gMainWindow->DoDialog(LC_DIALOG_SAVE_IMAGE, &Options))
|
|
|
|
break;
|
|
|
|
|
|
|
|
ImageOptions = Options.Format;
|
2012-12-13 03:51:12 +01:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
if (Options.Transparent)
|
|
|
|
ImageOptions |= LC_IMAGE_TRANSPARENT;
|
2012-12-13 03:51:12 +01:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
lcSetProfileInt(LC_PROFILE_IMAGE_OPTIONS, ImageOptions);
|
|
|
|
lcSetProfileInt(LC_PROFILE_IMAGE_WIDTH, Options.Width);
|
|
|
|
lcSetProfileInt(LC_PROFILE_IMAGE_HEIGHT, Options.Height);
|
2012-12-13 03:51:12 +01:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
if (!Options.FileName[0])
|
|
|
|
strcpy(Options.FileName, "Image");
|
2012-12-13 03:51:12 +01:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
char* Ext = strrchr(Options.FileName, '.');
|
2013-08-14 00:17:25 +02:00
|
|
|
if (Ext)
|
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
if (!strcmp(Ext, ".jpg") || !strcmp(Ext, ".jpeg") || !strcmp(Ext, ".bmp") || !strcmp(Ext, ".png"))
|
2013-08-14 00:17:25 +02:00
|
|
|
*Ext = 0;
|
|
|
|
}
|
2012-12-13 03:51:12 +01:00
|
|
|
|
2013-08-14 00:17:25 +02:00
|
|
|
const char* ext;
|
2013-08-09 06:57:18 +02:00
|
|
|
switch (Options.Format)
|
2013-08-14 00:17:25 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
case LC_IMAGE_BMP: ext = ".bmp";
|
|
|
|
break;
|
|
|
|
case LC_IMAGE_JPG: ext = ".jpg";
|
|
|
|
break;
|
2013-08-14 00:17:25 +02:00
|
|
|
default:
|
2013-08-09 06:57:18 +02:00
|
|
|
case LC_IMAGE_PNG: ext = ".png";
|
|
|
|
break;
|
2013-08-14 00:17:25 +02:00
|
|
|
}
|
2012-12-13 03:51:12 +01:00
|
|
|
|
2013-08-14 00:17:25 +02:00
|
|
|
if (m_bAnimation)
|
2013-08-09 06:57:18 +02:00
|
|
|
Options.End = lcMin(Options.End, m_nTotalFrames);
|
2013-08-14 00:17:25 +02:00
|
|
|
else
|
2013-08-09 06:57:18 +02:00
|
|
|
Options.End = lcMin(Options.End, 255);
|
|
|
|
Options.Start = lcMax(1, Options.Start);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
if (Options.Start > Options.End)
|
2013-08-14 00:17:25 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
if (Options.Start > Options.End)
|
2013-08-14 00:17:25 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
int Temp = Options.Start;
|
|
|
|
Options.Start = Options.End;
|
|
|
|
Options.End = Temp;
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
2013-08-14 00:17:25 +02:00
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
Image* images = new Image[Options.End - Options.Start + 1];
|
|
|
|
CreateImages(images, Options.Width, Options.Height, Options.Start, Options.End, false);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
for (int i = 0; i <= Options.End - Options.Start; i++)
|
2013-08-14 00:17:25 +02:00
|
|
|
{
|
|
|
|
char filename[LC_MAXPATH];
|
2012-12-13 03:51:12 +01:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
if (Options.Start != Options.End)
|
2013-08-14 00:17:25 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
sprintf(filename, "%s%02d%s", Options.FileName, i+1, ext);
|
2013-08-14 00:17:25 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
strcat(Options.FileName, ext);
|
|
|
|
strcpy(filename, Options.FileName);
|
2013-08-14 00:17:25 +02:00
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
images[i].FileSave(filename, Options.Format, Options.Transparent);
|
2013-08-14 00:17:25 +02:00
|
|
|
}
|
|
|
|
delete []images;
|
2011-09-07 23:06:51 +02:00
|
|
|
} break;
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
case LC_FILE_EXPORT_3DS:
|
2011-09-07 23:06:51 +02:00
|
|
|
Export3DStudio();
|
2013-08-09 06:57:18 +02:00
|
|
|
break;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
case LC_FILE_EXPORT_HTML:
|
2012-12-13 03:51:12 +01:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
lcHTMLDialogOptions Options;
|
|
|
|
|
|
|
|
strcpy(Options.PathName, m_strPathName);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
if (Options.PathName[0] != 0)
|
2012-12-13 03:51:12 +01:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
char* Slash = strrchr(Options.PathName, '/');
|
|
|
|
|
|
|
|
if (Slash == NULL)
|
|
|
|
Slash = strrchr(Options.PathName, '\\');
|
|
|
|
|
|
|
|
if (Slash)
|
2012-12-13 03:51:12 +01:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
Slash++;
|
|
|
|
*Slash = 0;
|
2012-12-13 03:51:12 +01:00
|
|
|
}
|
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
int ImageOptions = lcGetProfileInt(LC_PROFILE_HTML_IMAGE_OPTIONS);
|
|
|
|
int HTMLOptions = lcGetProfileInt(LC_PROFILE_HTML_OPTIONS);
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
if (!gMainWindow->DoDialog(LC_DIALOG_EXPORT_HTML, &Options))
|
|
|
|
break;
|
|
|
|
|
|
|
|
HTMLOptions = 0;
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
// TODO: Move to its own function
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
|
|
|
FILE* f;
|
|
|
|
const char *ext, *htmlext;
|
|
|
|
char fn[LC_MAXPATH];
|
|
|
|
int i;
|
|
|
|
unsigned short last = GetLastStep();
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
switch (Options.ImageFormat)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
case LC_IMAGE_BMP: ext = ".bmp";
|
|
|
|
break;
|
|
|
|
case LC_IMAGE_JPG: ext = ".jpg";
|
|
|
|
break;
|
2012-12-13 03:51:12 +01:00
|
|
|
default:
|
2013-08-09 06:57:18 +02:00
|
|
|
case LC_IMAGE_PNG: ext = ".png";
|
|
|
|
break;
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
2012-12-13 03:51:12 +01:00
|
|
|
htmlext = ".html";
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
if (Options.SinglePage)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
strcpy(fn, Options.PathName);
|
2012-12-13 03:51:12 +01:00
|
|
|
strcat(fn, m_strTitle);
|
|
|
|
strcat(fn, htmlext);
|
2011-09-07 23:06:51 +02:00
|
|
|
f = fopen (fn, "wt");
|
2013-01-26 02:20:34 +01:00
|
|
|
|
|
|
|
if (!f)
|
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->DoMessageBox("Could not open file for writing.", LC_MB_OK | LC_MB_ICONERROR);
|
2013-01-26 02:20:34 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
fprintf (f, "<HTML>\n<HEAD>\n<TITLE>Instructions for %s</TITLE>\n</HEAD>\n<BR>\n<CENTER>\n", m_strTitle);
|
|
|
|
|
|
|
|
for (i = 1; i <= last; i++)
|
|
|
|
{
|
2013-01-06 20:24:25 +01:00
|
|
|
fprintf(f, "<IMG SRC=\"%s-%02d%s\" ALT=\"Step %02d\" WIDTH=%d HEIGHT=%d><BR><BR>\n",
|
2013-08-09 06:57:18 +02:00
|
|
|
m_strTitle, i, ext, i, Options.StepImagesWidth, Options.StepImagesHeight);
|
2013-01-06 20:24:25 +01:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
if (Options.PartsListStep)
|
|
|
|
CreateHTMLPieceList(f, i, Options.PartsListImages, ext);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
if (Options.PartsListEnd)
|
|
|
|
CreateHTMLPieceList(f, 0, Options.PartsListImages, ext);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
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
|
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
if (Options.IndexPage)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
strcpy(fn, Options.PathName);
|
2011-09-07 23:06:51 +02:00
|
|
|
strcat (fn, m_strTitle);
|
|
|
|
strcat (fn, "-index");
|
2012-12-13 03:51:12 +01:00
|
|
|
strcat (fn, htmlext);
|
2011-09-07 23:06:51 +02:00
|
|
|
f = fopen (fn, "wt");
|
|
|
|
|
2013-01-26 02:20:34 +01:00
|
|
|
if (!f)
|
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->DoMessageBox("Could not open file for writing.", LC_MB_OK | LC_MB_ICONERROR);
|
2013-01-26 02:20:34 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
fprintf(f, "<HTML>\n<HEAD>\n<TITLE>Instructions for %s</TITLE>\n</HEAD>\n<BR>\n<CENTER>\n", m_strTitle);
|
|
|
|
|
|
|
|
for (i = 1; i <= last; i++)
|
|
|
|
fprintf(f, "<A HREF=\"%s-%02d%s\">Step %d<BR>\n</A>", m_strTitle, i, htmlext, i);
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
if (Options.PartsListEnd)
|
2011-09-07 23:06:51 +02:00
|
|
|
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
|
|
|
|
for (i = 1; i <= last; i++)
|
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
sprintf(fn, "%s%s-%02d%s", Options.PathName, m_strTitle, i, htmlext);
|
2011-09-07 23:06:51 +02:00
|
|
|
f = fopen(fn, "wt");
|
|
|
|
|
2013-01-26 02:20:34 +01:00
|
|
|
if (!f)
|
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->DoMessageBox("Could not open file for writing.", LC_MB_OK | LC_MB_ICONERROR);
|
2013-01-26 02:20:34 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
fprintf(f, "<HTML>\n<HEAD>\n<TITLE>%s - Step %02d</TITLE>\n</HEAD>\n<BR>\n<CENTER>\n", m_strTitle, i);
|
2013-01-06 20:24:25 +01:00
|
|
|
fprintf(f, "<IMG SRC=\"%s-%02d%s\" ALT=\"Step %02d\" WIDTH=%d HEIGHT=%d><BR><BR>\n",
|
2013-08-09 06:57:18 +02:00
|
|
|
m_strTitle, i, ext, i, Options.StepImagesWidth, Options.StepImagesHeight);
|
2013-01-06 20:24:25 +01:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
if (Options.PartsListStep)
|
|
|
|
CreateHTMLPieceList(f, i, Options.PartsListImages, ext);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
fputs("</CENTER>\n<BR><HR><BR>", f);
|
|
|
|
if (i != 1)
|
|
|
|
fprintf(f, "<A HREF=\"%s-%02d%s\">Previous</A> ", m_strTitle, i-1, htmlext);
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
if (Options.IndexPage)
|
2011-09-07 23:06:51 +02:00
|
|
|
fprintf(f, "<A HREF=\"%s-index%s\">Index</A> ", m_strTitle, htmlext);
|
|
|
|
|
|
|
|
if (i != last)
|
|
|
|
fprintf(f, "<A HREF=\"%s-%02d%s\">Next</A>", m_strTitle, i+1, htmlext);
|
2013-08-09 06:57:18 +02:00
|
|
|
else if (Options.PartsListEnd)
|
2011-09-07 23:06:51 +02:00
|
|
|
fprintf(f, "<A HREF=\"%s-pieces%s\">Pieces Used</A>", m_strTitle, htmlext);
|
|
|
|
|
|
|
|
fputs("<BR></HTML>\n",f);
|
|
|
|
fclose(f);
|
|
|
|
}
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
if (Options.PartsListEnd)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
strcpy(fn, Options.PathName);
|
2011-09-07 23:06:51 +02:00
|
|
|
strcat (fn, m_strTitle);
|
|
|
|
strcat (fn, "-pieces");
|
2012-12-13 03:51:12 +01:00
|
|
|
strcat (fn, htmlext);
|
2011-09-07 23:06:51 +02:00
|
|
|
f = fopen (fn, "wt");
|
2013-01-26 02:20:34 +01:00
|
|
|
|
|
|
|
if (!f)
|
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->DoMessageBox("Could not open file for writing.", LC_MB_OK | LC_MB_ICONERROR);
|
2013-01-26 02:20:34 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
fprintf (f, "<HTML>\n<HEAD>\n<TITLE>Pieces used by %s</TITLE>\n</HEAD>\n<BR>\n<CENTER>\n", m_strTitle);
|
2013-01-06 20:24:25 +01:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
CreateHTMLPieceList(f, 0, Options.PartsListImages, ext);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
fputs("</CENTER>\n<BR><HR><BR>", f);
|
|
|
|
fprintf(f, "<A HREF=\"%s-%02d%s\">Previous</A> ", m_strTitle, i-1, htmlext);
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
if (Options.IndexPage)
|
2011-09-07 23:06:51 +02:00
|
|
|
fprintf(f, "<A HREF=\"%s-index%s\">Index</A> ", m_strTitle, htmlext);
|
|
|
|
|
|
|
|
fputs("<BR></HTML>\n",f);
|
|
|
|
fclose(f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Save step pictures
|
|
|
|
Image* images = new Image[last];
|
2013-08-09 06:57:18 +02:00
|
|
|
CreateImages(images, Options.StepImagesWidth, Options.StepImagesHeight, 1, last, Options.HighlightNewParts);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
for (i = 0; i < last; i++)
|
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
sprintf(fn, "%s%s-%02d%s", Options.PathName, m_strTitle, i+1, ext);
|
|
|
|
images[i].FileSave(fn, Options.ImageFormat, Options.TransparentImages);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
delete []images;
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
if (Options.PartsListImages)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
int cx = Options.PartImagesWidth, cy = Options.PartImagesHeight;
|
|
|
|
if (!GL_BeginRenderToTexture(cx, cy))
|
|
|
|
{
|
|
|
|
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);
|
|
|
|
|
|
|
|
Piece *p1, *p2;
|
|
|
|
PieceInfo* pInfo;
|
|
|
|
for (p1 = m_pPieces; p1; p1 = p1->m_pNext)
|
|
|
|
{
|
|
|
|
bool bSkip = false;
|
2012-05-17 23:52:20 +02:00
|
|
|
pInfo = p1->mPieceInfo;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
for (p2 = m_pPieces; p2; p2 = p2->m_pNext)
|
|
|
|
{
|
|
|
|
if (p2 == p1)
|
|
|
|
break;
|
|
|
|
|
2012-05-17 23:52:20 +02:00
|
|
|
if (p2->mPieceInfo == pInfo)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
|
|
|
bSkip = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bSkip)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
glDepthFunc(GL_LEQUAL);
|
2013-01-26 03:23:49 +01:00
|
|
|
glEnable(GL_DEPTH_TEST);
|
|
|
|
glEnable(GL_POLYGON_OFFSET_FILL);
|
|
|
|
glPolygonOffset(0.5f, 0.1f);
|
2013-08-09 06:57:18 +02:00
|
|
|
glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
|
2011-09-07 23:06:51 +02:00
|
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
|
|
pInfo->ZoomExtents(30.0f, aspect);
|
2013-08-09 06:57:18 +02:00
|
|
|
pInfo->RenderPiece(Options.PartImagesColor);
|
2011-09-07 23:06:51 +02:00
|
|
|
glFinish();
|
|
|
|
|
|
|
|
Image image;
|
2012-03-07 23:59:06 +01:00
|
|
|
image.FromOpenGL (cx, cy);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
sprintf(fn, "%s%s%s", Options.PathName, pInfo->m_strName, ext);
|
|
|
|
image.FileSave(fn, Options.ImageFormat, Options.TransparentImages);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
2013-08-09 06:57:18 +02:00
|
|
|
GL_EndRenderToTexture();
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
case LC_FILE_EXPORT_BRICKLINK:
|
2013-01-25 00:54:10 +01:00
|
|
|
{
|
|
|
|
if (!m_pPieces)
|
2013-01-26 00:22:24 +01:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->DoMessageBox("Nothing to export.", LC_MB_OK | LC_MB_ICONINFORMATION);
|
2013-01-26 00:22:24 +01:00
|
|
|
break;
|
|
|
|
}
|
2013-01-25 00:54:10 +01:00
|
|
|
|
|
|
|
char FileName[LC_MAXPATH];
|
2013-01-26 00:22:24 +01:00
|
|
|
memset(FileName, 0, sizeof(FileName));
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
if (!gMainWindow->DoDialog(LC_DIALOG_EXPORT_BRICKLINK, FileName))
|
2013-01-25 00:54:10 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
lcDiskFile BrickLinkFile;
|
|
|
|
char Line[1024];
|
|
|
|
|
|
|
|
if (!BrickLinkFile.Open(FileName, "wt"))
|
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->DoMessageBox("Could not open file for writing.", LC_MB_OK | LC_MB_ICONERROR);
|
2013-01-25 00:54:10 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2013-08-16 01:43:18 +02:00
|
|
|
lcArray<lcPiecesUsedEntry> PiecesUsed;
|
2013-01-25 00:54:10 +01:00
|
|
|
GetPiecesUsed(PiecesUsed);
|
|
|
|
|
|
|
|
const char* OldLocale = setlocale(LC_NUMERIC, "C");
|
|
|
|
BrickLinkFile.WriteLine("<INVENTORY>\n");
|
|
|
|
|
|
|
|
for (int PieceIdx = 0; PieceIdx < PiecesUsed.GetSize(); PieceIdx++)
|
|
|
|
{
|
|
|
|
BrickLinkFile.WriteLine(" <ITEM>\n");
|
|
|
|
BrickLinkFile.WriteLine(" <ITEMTYPE>P</ITEMTYPE>\n");
|
|
|
|
|
|
|
|
sprintf(Line, " <ITEMID>%s</ITEMID>\n", PiecesUsed[PieceIdx].Info->m_strName);
|
|
|
|
BrickLinkFile.WriteLine(Line);
|
|
|
|
|
|
|
|
int Count = PiecesUsed[PieceIdx].Count;
|
|
|
|
if (Count > 1)
|
|
|
|
{
|
|
|
|
sprintf(Line, " <MINQTY>%d</MINQTY>\n", Count);
|
|
|
|
BrickLinkFile.WriteLine(Line);
|
|
|
|
}
|
|
|
|
|
|
|
|
int Color = lcGetBrickLinkColor(PiecesUsed[PieceIdx].ColorIndex);
|
|
|
|
if (Color)
|
|
|
|
{
|
|
|
|
sprintf(Line, " <COLOR>%d</COLOR>\n", Color);
|
|
|
|
BrickLinkFile.WriteLine(Line);
|
|
|
|
}
|
|
|
|
|
|
|
|
BrickLinkFile.WriteLine(" </ITEM>\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
BrickLinkFile.WriteLine("</INVENTORY>\n");
|
|
|
|
|
|
|
|
setlocale(LC_NUMERIC, OldLocale);
|
|
|
|
} break;
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
case LC_FILE_EXPORT_CSV:
|
|
|
|
{
|
|
|
|
if (!m_pPieces)
|
|
|
|
{
|
|
|
|
gMainWindow->DoMessageBox("Nothing to export.", LC_MB_OK | LC_MB_ICONINFORMATION);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
char FileName[LC_MAXPATH];
|
|
|
|
memset(FileName, 0, sizeof(FileName));
|
|
|
|
|
|
|
|
if (!gMainWindow->DoDialog(LC_DIALOG_EXPORT_CSV, FileName))
|
|
|
|
break;
|
|
|
|
|
|
|
|
lcDiskFile CSVFile;
|
|
|
|
char Line[1024];
|
|
|
|
|
|
|
|
if (!CSVFile.Open(FileName, "wt"))
|
|
|
|
{
|
|
|
|
gMainWindow->DoMessageBox("Could not open file for writing.", LC_MB_OK | LC_MB_ICONERROR);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2013-08-16 01:43:18 +02:00
|
|
|
lcArray<lcPiecesUsedEntry> PiecesUsed;
|
2013-08-09 06:57:18 +02:00
|
|
|
GetPiecesUsed(PiecesUsed);
|
|
|
|
|
|
|
|
const char* OldLocale = setlocale(LC_NUMERIC, "C");
|
|
|
|
CSVFile.WriteLine("Part Name,Color,Quantity,Part ID,Color Code\n");
|
|
|
|
|
|
|
|
for (int PieceIdx = 0; PieceIdx < PiecesUsed.GetSize(); PieceIdx++)
|
|
|
|
{
|
|
|
|
sprintf(Line, "\"%s\",\"%s\",%d,%s,%d\n", PiecesUsed[PieceIdx].Info->m_strDescription, gColorList[PiecesUsed[PieceIdx].ColorIndex].Name,
|
|
|
|
PiecesUsed[PieceIdx].Count, PiecesUsed[PieceIdx].Info->m_strName, gColorList[PiecesUsed[PieceIdx].ColorIndex].Code);
|
|
|
|
CSVFile.WriteLine(Line);
|
|
|
|
}
|
|
|
|
|
|
|
|
setlocale(LC_NUMERIC, OldLocale);
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_FILE_EXPORT_POVRAY:
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
lcPOVRayDialogOptions Options;
|
2012-03-07 23:59:06 +01:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
memset(Options.FileName, 0, sizeof(Options.FileName));
|
|
|
|
strcpy(Options.POVRayPath, lcGetProfileString(LC_PROFILE_POVRAY_PATH));
|
|
|
|
strcpy(Options.LGEOPath, lcGetProfileString(LC_PROFILE_POVRAY_LGEO_PATH));
|
|
|
|
Options.Render = lcGetProfileInt(LC_PROFILE_POVRAY_RENDER);
|
|
|
|
|
|
|
|
if (!gMainWindow->DoDialog(LC_DIALOG_EXPORT_POVRAY, &Options))
|
2011-09-07 23:06:51 +02:00
|
|
|
break;
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
lcSetProfileString(LC_PROFILE_POVRAY_PATH, Options.POVRayPath);
|
|
|
|
lcSetProfileString(LC_PROFILE_POVRAY_LGEO_PATH, Options.LGEOPath);
|
|
|
|
lcSetProfileInt(LC_PROFILE_POVRAY_RENDER, Options.Render);
|
|
|
|
|
2012-03-23 00:44:56 +01:00
|
|
|
lcDiskFile POVFile;
|
2012-03-07 23:59:06 +01:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
if (!POVFile.Open(Options.FileName, "wt"))
|
2012-03-07 23:59:06 +01:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->DoMessageBox("Could not open file for writing.", LC_MB_OK|LC_MB_ICONERROR);
|
2012-03-07 23:59:06 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2013-08-17 03:35:02 +02:00
|
|
|
ExportPOVRay(POVFile);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
if (Options.Render)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-17 01:17:25 +02:00
|
|
|
lcArray<String> Arguments;
|
|
|
|
char Argument[LC_MAXPATH + 32];
|
2013-08-09 06:57:18 +02:00
|
|
|
|
2013-08-17 01:17:25 +02:00
|
|
|
sprintf(Argument, "+I%s", Options.FileName);
|
|
|
|
Arguments.Add(Argument);
|
2012-03-08 01:16:29 +01:00
|
|
|
|
2013-08-17 01:17:25 +02:00
|
|
|
if (Options.LGEOPath[0])
|
2012-03-09 23:47:05 +01:00
|
|
|
{
|
2013-08-17 01:17:25 +02:00
|
|
|
sprintf(Argument, "+L%slg/", Options.LGEOPath);
|
|
|
|
Arguments.Add(Argument);
|
|
|
|
sprintf(Argument, "+L%sar/", Options.LGEOPath);
|
|
|
|
Arguments.Add(Argument);
|
|
|
|
}
|
2012-03-09 23:47:05 +01:00
|
|
|
|
2013-08-17 01:17:25 +02:00
|
|
|
sprintf(Argument, "+o%s", Options.FileName);
|
|
|
|
char* Slash1 = strrchr(Argument, '\\');
|
|
|
|
char* Slash2 = strrchr(Argument, '/');
|
|
|
|
if (Slash1 || Slash2)
|
|
|
|
{
|
|
|
|
if (Slash1 > Slash2)
|
|
|
|
*(Slash1 + 1) = 0;
|
2012-03-09 23:47:05 +01:00
|
|
|
else
|
2013-08-17 01:17:25 +02:00
|
|
|
*(Slash2 + 1) = 0;
|
2012-03-09 23:47:05 +01:00
|
|
|
|
2013-08-17 01:17:25 +02:00
|
|
|
Arguments.Add(Argument);
|
2012-03-09 23:47:05 +01:00
|
|
|
}
|
2013-08-17 01:17:25 +02:00
|
|
|
|
|
|
|
g_App->RunProcess(Options.POVRayPath, Arguments);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
case LC_FILE_EXPORT_WAVEFRONT:
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
char FileName[LC_MAXPATH];
|
|
|
|
memset(FileName, 0, sizeof(FileName));
|
2013-01-26 00:22:24 +01:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
if (!gMainWindow->DoDialog(LC_DIALOG_EXPORT_WAVEFRONT, FileName))
|
2011-09-07 23:06:51 +02:00
|
|
|
break;
|
|
|
|
|
2012-04-14 04:20:27 +02:00
|
|
|
lcDiskFile OBJFile;
|
|
|
|
char Line[1024];
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
if (!OBJFile.Open(FileName, "wt"))
|
2012-04-14 04:20:27 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->DoMessageBox("Could not open file for writing.", LC_MB_OK|LC_MB_ICONERROR);
|
2012-04-14 04:20:27 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
char buf[LC_MAXPATH], *ptr;
|
2012-04-14 19:05:55 +02:00
|
|
|
lcuint32 vert = 1;
|
2011-09-07 23:06:51 +02:00
|
|
|
Piece* pPiece;
|
|
|
|
|
2012-04-11 06:58:40 +02:00
|
|
|
const char* OldLocale = setlocale(LC_NUMERIC, "C");
|
2011-09-07 23:06:51 +02:00
|
|
|
strcpy(buf, m_strPathName);
|
|
|
|
ptr = strrchr(buf, '\\');
|
|
|
|
if (ptr)
|
|
|
|
ptr++;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ptr = strrchr(buf, '/');
|
|
|
|
if (ptr)
|
|
|
|
ptr++;
|
|
|
|
else
|
|
|
|
ptr = buf;
|
|
|
|
}
|
2012-04-14 04:20:27 +02:00
|
|
|
|
|
|
|
OBJFile.WriteLine("# Model exported from LeoCAD\n");
|
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
if (strlen(buf) != 0)
|
2012-04-14 04:20:27 +02:00
|
|
|
{
|
|
|
|
sprintf(Line, "# Original name: %s\n", ptr);
|
|
|
|
OBJFile.WriteLine(Line);
|
|
|
|
}
|
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
if (strlen(m_strAuthor))
|
2012-04-14 04:20:27 +02:00
|
|
|
{
|
|
|
|
sprintf(Line, "# Author: %s\n", m_strAuthor);
|
|
|
|
OBJFile.WriteLine(Line);
|
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
strcpy(buf, FileName);
|
2011-09-07 23:06:51 +02:00
|
|
|
ptr = strrchr(buf, '.');
|
|
|
|
if (ptr)
|
|
|
|
*ptr = 0;
|
|
|
|
|
|
|
|
strcat(buf, ".mtl");
|
|
|
|
ptr = strrchr(buf, '\\');
|
|
|
|
if (ptr)
|
|
|
|
ptr++;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ptr = strrchr(buf, '/');
|
|
|
|
if (ptr)
|
|
|
|
ptr++;
|
|
|
|
else
|
|
|
|
ptr = buf;
|
|
|
|
}
|
|
|
|
|
2012-04-14 04:20:27 +02:00
|
|
|
sprintf(Line, "#\n\nmtllib %s\n\n", ptr);
|
|
|
|
OBJFile.WriteLine(Line);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
FILE* mat = fopen(buf, "wt");
|
|
|
|
fputs("# Colors used by LeoCAD\n# You need to add transparency values\n#\n\n", mat);
|
2012-04-19 03:11:24 +02:00
|
|
|
for (int ColorIdx = 0; ColorIdx < gColorList.GetSize(); ColorIdx++)
|
|
|
|
{
|
|
|
|
lcColor* Color = &gColorList[ColorIdx];
|
|
|
|
fprintf(mat, "newmtl %s\nKd %.2f %.2f %.2f\n\n", Color->SafeName, Color->Value[0], Color->Value[1], Color->Value[2]);
|
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
fclose(mat);
|
|
|
|
|
|
|
|
for (pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
|
|
|
{
|
2012-10-18 20:57:21 +02:00
|
|
|
const lcMatrix44& ModelWorld = pPiece->mModelWorld;
|
2012-05-17 23:52:20 +02:00
|
|
|
PieceInfo* pInfo = pPiece->mPieceInfo;
|
2012-04-14 04:20:27 +02:00
|
|
|
float* Verts = (float*)pInfo->mMesh->mVertexBuffer.mData;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-04-14 19:05:55 +02:00
|
|
|
for (int i = 0; i < pInfo->mMesh->mNumVertices * 3; i += 3)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2012-10-18 20:57:21 +02:00
|
|
|
lcVector3 Vertex = lcMul31(lcVector3(Verts[i], Verts[i+1], Verts[i+2]), ModelWorld);
|
|
|
|
sprintf(Line, "v %.2f %.2f %.2f\n", Vertex[0], Vertex[1], Vertex[2]);
|
2012-04-14 04:20:27 +02:00
|
|
|
OBJFile.WriteLine(Line);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
2012-04-14 04:20:27 +02:00
|
|
|
|
|
|
|
OBJFile.WriteLine("#\n\n");
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
for (pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
|
|
|
{
|
2012-05-17 23:52:20 +02:00
|
|
|
PieceInfo* Info = pPiece->mPieceInfo;
|
2012-04-14 04:20:27 +02:00
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
strcpy(buf, pPiece->GetName());
|
2012-04-14 19:05:55 +02:00
|
|
|
for (unsigned int i = 0; i < strlen(buf); i++)
|
2011-09-07 23:06:51 +02:00
|
|
|
if ((buf[i] == '#') || (buf[i] == ' '))
|
|
|
|
buf[i] = '_';
|
|
|
|
|
2012-04-14 04:20:27 +02:00
|
|
|
sprintf(Line, "g %s\n", buf);
|
|
|
|
OBJFile.WriteLine(Line);
|
2013-01-06 20:24:25 +01:00
|
|
|
|
2012-04-14 04:20:27 +02:00
|
|
|
Info->mMesh->ExportWavefrontIndices(OBJFile, pPiece->mColorCode, vert);
|
2012-04-14 19:05:55 +02:00
|
|
|
vert += Info->mMesh->mNumVertices;
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
2012-04-11 06:58:40 +02:00
|
|
|
setlocale(LC_NUMERIC, OldLocale);
|
2011-09-07 23:06:51 +02:00
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_FILE_PROPERTIES:
|
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
lcPropertiesDialogOptions Options;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
Options.Title = m_strTitle;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
strcpy(Options.Author, m_strAuthor);
|
|
|
|
strcpy(Options.Description, m_strDescription);
|
|
|
|
strcpy(Options.Comments, m_strComments);
|
2012-04-21 01:27:12 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
if (m_nScene & LC_SCENE_BG)
|
|
|
|
Options.BackgroundType = 2;
|
|
|
|
else if (m_nScene & LC_SCENE_GRADIENT)
|
|
|
|
Options.BackgroundType = 1;
|
|
|
|
else
|
|
|
|
Options.BackgroundType = 0;
|
|
|
|
|
|
|
|
Options.SolidColor = lcVector3(m_fBackground[0], m_fBackground[1], m_fBackground[2]);
|
|
|
|
Options.GradientColor1 = lcVector3(m_fGradient1[0], m_fGradient1[1], m_fGradient1[2]);
|
|
|
|
Options.GradientColor2 = lcVector3(m_fGradient2[0], m_fGradient2[1], m_fGradient2[2]);
|
|
|
|
strcpy(Options.BackgroundFileName, m_strBackground);
|
|
|
|
Options.BackgroundTile = (m_nScene & LC_SCENE_BG_TILE) != 0;
|
|
|
|
Options.FogEnabled = (m_nScene & LC_SCENE_FOG) != 0;
|
|
|
|
Options.FogDensity = m_fFogDensity * 100.0f;
|
|
|
|
Options.FogColor = lcVector3(m_fFogColor[0], m_fFogColor[1], m_fFogColor[2]);
|
|
|
|
Options.AmbientColor = lcVector3(m_fAmbient[0], m_fAmbient[1], m_fAmbient[2]);
|
|
|
|
Options.DrawFloor = (m_nScene & LC_SCENE_FLOOR) != 0;
|
|
|
|
Options.SetDefault = false;
|
|
|
|
|
|
|
|
GetPiecesUsed(Options.PartsUsed);
|
|
|
|
|
|
|
|
if (!gMainWindow->DoDialog(LC_DIALOG_PROPERTIES, &Options))
|
|
|
|
break;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
bool Modified = false;
|
|
|
|
|
|
|
|
if (strcmp(m_strAuthor, Options.Author))
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
strcpy(m_strAuthor, Options.Author);
|
|
|
|
Modified = true;
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
if (strcmp(m_strDescription, Options.Description))
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
strcpy(m_strDescription, Options.Description);
|
|
|
|
Modified = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (strcmp(m_strComments, Options.Comments))
|
|
|
|
{
|
|
|
|
strcpy(m_strComments, Options.Comments);
|
|
|
|
Modified = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
lcuint32 Scene = 0;
|
|
|
|
|
|
|
|
if (Options.BackgroundType == 2)
|
|
|
|
Scene |= LC_SCENE_BG;
|
|
|
|
else if (Options.BackgroundType == 1)
|
|
|
|
Scene |= LC_SCENE_GRADIENT;
|
|
|
|
|
|
|
|
if (Options.BackgroundTile)
|
|
|
|
Scene |= LC_SCENE_BG_TILE;
|
|
|
|
|
|
|
|
if (Options.FogEnabled)
|
|
|
|
Scene |= LC_SCENE_FOG;
|
|
|
|
|
|
|
|
if (Options.DrawFloor)
|
|
|
|
Scene |= LC_SCENE_FLOOR;
|
|
|
|
|
|
|
|
if (m_nScene != Scene)
|
|
|
|
{
|
|
|
|
m_nScene = Scene;
|
|
|
|
Modified = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (strcmp(m_strBackground, Options.BackgroundFileName))
|
|
|
|
{
|
|
|
|
strcpy(m_strBackground, Options.BackgroundFileName);
|
|
|
|
Modified = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_fFogDensity * 100.0f != Options.FogDensity)
|
|
|
|
{
|
|
|
|
m_fFogDensity = Options.FogDensity / 100.0f;
|
|
|
|
Modified = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (memcmp(m_fBackground, Options.SolidColor, sizeof(Options.SolidColor)))
|
|
|
|
{
|
|
|
|
memcpy(m_fBackground, Options.SolidColor, sizeof(Options.SolidColor));
|
|
|
|
Modified = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (memcmp(m_fGradient1, Options.GradientColor1, sizeof(Options.GradientColor1)))
|
|
|
|
{
|
|
|
|
memcpy(m_fGradient1, Options.GradientColor1, sizeof(Options.GradientColor1));
|
|
|
|
Modified = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (memcmp(m_fGradient2, Options.GradientColor2, sizeof(Options.GradientColor2)))
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
memcpy(m_fGradient2, Options.GradientColor2, sizeof(Options.GradientColor2));
|
|
|
|
Modified = true;
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
2013-08-09 06:57:18 +02:00
|
|
|
|
|
|
|
if (memcmp(m_fFogColor, Options.FogColor, sizeof(Options.FogColor)))
|
|
|
|
{
|
|
|
|
memcpy(m_fFogColor, Options.FogColor, sizeof(Options.FogColor));
|
|
|
|
Modified = true;
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
if (memcmp(m_fAmbient, Options.AmbientColor, sizeof(Options.AmbientColor)))
|
|
|
|
{
|
|
|
|
memcpy(m_fAmbient, Options.AmbientColor, sizeof(Options.AmbientColor));
|
|
|
|
Modified = true;
|
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
if (Options.SetDefault)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
lcSetProfileInt(LC_PROFILE_DEFAULT_SCENE, Scene);
|
|
|
|
lcSetProfileFloat(LC_PROFILE_DEFAULT_FOG_DENSITY, Options.FogDensity);
|
|
|
|
lcSetProfileString(LC_PROFILE_DEFAULT_BACKGROUND_TEXTURE, Options.BackgroundFileName);
|
|
|
|
lcSetProfileInt(LC_PROFILE_DEFAULT_BACKGROUND_COLOR, LC_RGB(Options.SolidColor[0] * 255, Options.SolidColor[1] * 255, Options.SolidColor[2] * 255));
|
|
|
|
lcSetProfileInt(LC_PROFILE_DEFAULT_FOG_COLOR, LC_RGB(Options.FogColor[0] * 255, Options.FogColor[1] * 255, Options.FogColor[2] * 255));
|
|
|
|
lcSetProfileInt(LC_PROFILE_DEFAULT_AMBIENT_COLOR, LC_RGB(Options.AmbientColor[0] * 255, Options.AmbientColor[1] * 255, Options.AmbientColor[2] * 255));
|
|
|
|
lcSetProfileInt(LC_PROFILE_DEFAULT_GRADIENT_COLOR1, LC_RGB(Options.GradientColor1[0] * 255, Options.GradientColor1[1] * 255, Options.GradientColor1[2] * 255));
|
|
|
|
lcSetProfileInt(LC_PROFILE_DEFAULT_GRADIENT_COLOR2, LC_RGB(Options.GradientColor2[0] * 255, Options.GradientColor1[1] * 255, Options.GradientColor1[2] * 255));
|
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
if (Modified)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
for (int i = 0; i < m_ViewList.GetSize (); i++)
|
|
|
|
{
|
|
|
|
m_ViewList[i]->MakeCurrent();
|
|
|
|
RenderInitialize();
|
|
|
|
}
|
|
|
|
|
|
|
|
SetModifiedFlag(true);
|
|
|
|
CheckPoint("Properties");
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
case LC_FILE_PRINT_PREVIEW:
|
|
|
|
gMainWindow->TogglePrintPreview();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LC_FILE_PRINT:
|
|
|
|
gMainWindow->DoDialog(LC_DIALOG_PRINT, NULL);
|
|
|
|
break;
|
|
|
|
|
|
|
|
// TODO: printing
|
|
|
|
case LC_FILE_PRINT_BOM:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LC_FILE_TERRAIN_EDITOR:
|
|
|
|
{
|
|
|
|
// TODO: decide what to do with the terrain editor
|
|
|
|
// Terrain temp = *m_pTerrain;
|
|
|
|
|
|
|
|
// if (SystemDoDialog(LC_DLG_TERRAIN, temp))
|
|
|
|
// {
|
|
|
|
// *m_pTerrain = temp;
|
|
|
|
// m_pTerrain->LoadTexture();
|
|
|
|
// }
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_FILE_RECENT1:
|
|
|
|
case LC_FILE_RECENT2:
|
|
|
|
case LC_FILE_RECENT3:
|
|
|
|
case LC_FILE_RECENT4:
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
if (!OpenProject(gMainWindow->mRecentFiles[id - LC_FILE_RECENT1]))
|
|
|
|
gMainWindow->RemoveRecentFile(id - LC_FILE_RECENT1);
|
2011-09-07 23:06:51 +02:00
|
|
|
} break;
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
case LC_FILE_EXIT:
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->Close();
|
2011-09-07 23:06:51 +02:00
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_EDIT_UNDO:
|
|
|
|
case LC_EDIT_REDO:
|
|
|
|
{
|
|
|
|
LC_UNDOINFO *pUndo, *pTmp;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (id == LC_EDIT_UNDO)
|
|
|
|
{
|
|
|
|
if ((m_pUndoList != NULL) && (m_pUndoList->pNext != NULL))
|
|
|
|
{
|
|
|
|
// Remove the first item from the undo list.
|
|
|
|
pUndo = m_pUndoList;
|
|
|
|
m_pUndoList = pUndo->pNext;
|
|
|
|
|
|
|
|
// Check if we need to delete the last redo info.
|
|
|
|
for (pTmp = m_pRedoList, i = 0; pTmp; pTmp = pTmp->pNext, i++)
|
|
|
|
if ((i == 29) && (pTmp->pNext != NULL))
|
|
|
|
{
|
|
|
|
delete pTmp->pNext;
|
|
|
|
pTmp->pNext = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
pUndo->pNext = m_pRedoList;
|
|
|
|
m_pRedoList = pUndo;
|
2013-01-06 20:24:25 +01:00
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
pUndo = m_pUndoList;
|
|
|
|
DeleteContents(true);
|
|
|
|
FileLoad(&pUndo->file, true, false);
|
|
|
|
}
|
2013-01-06 20:24:25 +01:00
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
if (m_bUndoOriginal && (m_pUndoList != NULL) && (m_pUndoList->pNext == NULL))
|
|
|
|
SetModifiedFlag(false);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (m_pRedoList != NULL)
|
|
|
|
{
|
|
|
|
// Remove the first element from the redo list.
|
|
|
|
pUndo = m_pRedoList;
|
|
|
|
m_pRedoList = pUndo->pNext;
|
2013-01-06 20:24:25 +01:00
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
// Check if we can delete the last undo info.
|
|
|
|
for (pTmp = m_pUndoList, i = 0; pTmp; pTmp = pTmp->pNext, i++)
|
|
|
|
if ((i == 30) && (pTmp->pNext != NULL))
|
|
|
|
{
|
|
|
|
delete pTmp->pNext;
|
|
|
|
pTmp->pNext = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add info to the start of the undo list.
|
|
|
|
pUndo->pNext = m_pUndoList;
|
|
|
|
m_pUndoList = pUndo;
|
|
|
|
|
|
|
|
// Load state.
|
|
|
|
DeleteContents(true);
|
|
|
|
FileLoad(&pUndo->file, true, false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateUndoRedo(m_pUndoList->pNext ? m_pUndoList->strText : NULL, m_pRedoList ? m_pRedoList->strText : NULL);
|
2011-09-07 23:06:51 +02:00
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_EDIT_CUT:
|
|
|
|
case LC_EDIT_COPY:
|
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
lcMemFile* Clipboard = new lcMemFile();
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
int i = 0;
|
|
|
|
Piece* pPiece;
|
|
|
|
Group* pGroup;
|
|
|
|
// Light* pLight;
|
|
|
|
|
|
|
|
for (pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
|
|
|
if (pPiece->IsSelected())
|
|
|
|
i++;
|
2013-08-09 06:57:18 +02:00
|
|
|
Clipboard->WriteBuffer(&i, sizeof(i));
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
for (pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
|
|
|
if (pPiece->IsSelected())
|
2013-08-09 06:57:18 +02:00
|
|
|
pPiece->FileSave(*Clipboard);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
for (i = 0, pGroup = m_pGroups; pGroup; pGroup = pGroup->m_pNext)
|
|
|
|
i++;
|
2013-08-09 06:57:18 +02:00
|
|
|
Clipboard->WriteBuffer(&i, sizeof(i));
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
for (pGroup = m_pGroups; pGroup; pGroup = pGroup->m_pNext)
|
2013-08-09 06:57:18 +02:00
|
|
|
pGroup->FileSave(Clipboard, m_pGroups);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-02-12 23:12:50 +01:00
|
|
|
i = 0;
|
|
|
|
for (int CameraIdx = 0; CameraIdx < mCameras.GetSize(); CameraIdx++)
|
2012-08-22 03:13:32 +02:00
|
|
|
if (mCameras[CameraIdx]->IsSelected())
|
2011-09-07 23:06:51 +02:00
|
|
|
i++;
|
2013-08-09 06:57:18 +02:00
|
|
|
Clipboard->WriteBuffer(&i, sizeof(i));
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-08-22 03:13:32 +02:00
|
|
|
for (int CameraIdx = 0; CameraIdx < mCameras.GetSize(); CameraIdx++)
|
|
|
|
{
|
|
|
|
Camera* pCamera = mCameras[CameraIdx];
|
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
if (pCamera->IsSelected())
|
2013-08-09 06:57:18 +02:00
|
|
|
pCamera->FileSave(*Clipboard);
|
2012-08-22 03:13:32 +02:00
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
/*
|
|
|
|
for (i = 0, pLight = m_pLights; pLight; pLight = pLight->m_pNext)
|
|
|
|
if (pLight->IsSelected())
|
|
|
|
i++;
|
2013-08-09 06:57:18 +02:00
|
|
|
Clipboard->Write(&i, sizeof(i));
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
for (pLight = m_pLights; pLight; pLight = pLight->m_pNext)
|
|
|
|
if (pLight->IsSelected())
|
2013-08-09 06:57:18 +02:00
|
|
|
pLight->FileSave(Clipboard);
|
2011-09-07 23:06:51 +02:00
|
|
|
*/
|
|
|
|
if (id == LC_EDIT_CUT)
|
|
|
|
{
|
|
|
|
RemoveSelectedObjects();
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateFocusObject(GetFocusObject());
|
2011-09-07 23:06:51 +02:00
|
|
|
UpdateSelection();
|
|
|
|
UpdateAllViews ();
|
|
|
|
SetModifiedFlag(true);
|
|
|
|
CheckPoint("Cutting");
|
|
|
|
}
|
2013-08-09 06:57:18 +02:00
|
|
|
|
|
|
|
g_App->ExportClipboard(Clipboard);
|
2011-09-07 23:06:51 +02:00
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_EDIT_PASTE:
|
|
|
|
{
|
|
|
|
int i, j;
|
|
|
|
Piece* pPasted = NULL;
|
2013-08-09 06:57:18 +02:00
|
|
|
lcFile* file = g_App->mClipboard;
|
2011-09-07 23:06:51 +02:00
|
|
|
if (file == NULL)
|
|
|
|
break;
|
|
|
|
file->Seek(0, SEEK_SET);
|
|
|
|
SelectAndFocusNone(false);
|
|
|
|
|
2012-03-23 00:44:56 +01:00
|
|
|
file->ReadBuffer(&i, sizeof(i));
|
2011-09-07 23:06:51 +02:00
|
|
|
while (i--)
|
|
|
|
{
|
|
|
|
Piece* pPiece = new Piece(NULL);
|
2013-08-09 06:57:18 +02:00
|
|
|
pPiece->FileLoad(*file);
|
2011-09-07 23:06:51 +02:00
|
|
|
pPiece->m_pNext = pPasted;
|
|
|
|
pPasted = pPiece;
|
|
|
|
}
|
|
|
|
|
2012-03-23 00:44:56 +01:00
|
|
|
file->ReadBuffer(&i, sizeof(i));
|
2011-09-07 23:06:51 +02:00
|
|
|
Piece* pPiece;
|
|
|
|
Group** groups = (Group**)malloc(i*sizeof(Group**));
|
|
|
|
for (j = 0; j < i; j++)
|
|
|
|
{
|
|
|
|
groups[j] = new Group();
|
|
|
|
groups[j]->FileLoad(file);
|
|
|
|
}
|
|
|
|
|
|
|
|
while (pPasted)
|
|
|
|
{
|
|
|
|
pPiece = pPasted;
|
|
|
|
pPasted = pPasted->m_pNext;
|
|
|
|
pPiece->CreateName(m_pPieces);
|
|
|
|
pPiece->SetFrameShow(m_nCurFrame);
|
|
|
|
pPiece->SetStepShow(m_nCurStep);
|
|
|
|
AddPiece(pPiece);
|
|
|
|
pPiece->Select(true, false, false);
|
|
|
|
|
|
|
|
j = LC_POINTER_TO_INT(pPiece->GetGroup());
|
|
|
|
if (j != -1)
|
|
|
|
pPiece->SetGroup(groups[j]);
|
|
|
|
else
|
|
|
|
pPiece->UnGroup(NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (j = 0; j < i; j++)
|
|
|
|
{
|
|
|
|
int g = LC_POINTER_TO_INT(groups[j]->m_pGroup);
|
|
|
|
groups[j]->m_pGroup = (g != -1) ? groups[g] : NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (j = 0; j < i; j++)
|
|
|
|
{
|
|
|
|
Group* pGroup;
|
|
|
|
bool add = false;
|
|
|
|
for (pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
|
|
|
{
|
|
|
|
for (pGroup = pPiece->GetGroup(); pGroup; pGroup = pGroup->m_pGroup)
|
|
|
|
if (pGroup == groups[j])
|
|
|
|
{
|
|
|
|
add = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (add)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (add)
|
|
|
|
{
|
|
|
|
int a, max = 0;
|
|
|
|
|
|
|
|
for (pGroup = m_pGroups; pGroup; pGroup = pGroup->m_pNext)
|
|
|
|
if (strncmp("Pasted Group #", pGroup->m_strName, 14) == 0)
|
|
|
|
if (sscanf(pGroup->m_strName + 14, "%d", &a) == 1)
|
2013-01-06 20:24:25 +01:00
|
|
|
if (a > max)
|
2011-09-07 23:06:51 +02:00
|
|
|
max = a;
|
|
|
|
|
|
|
|
sprintf(groups[j]->m_strName, "Pasted Group #%.2d", max+1);
|
|
|
|
groups[j]->m_pNext = m_pGroups;
|
|
|
|
m_pGroups = groups[j];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
delete groups[j];
|
|
|
|
}
|
2013-01-06 20:24:25 +01:00
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
free(groups);
|
|
|
|
|
2012-03-23 00:44:56 +01:00
|
|
|
file->ReadBuffer(&i, sizeof(i));
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
while (i--)
|
|
|
|
{
|
2012-08-23 20:47:37 +02:00
|
|
|
Camera* pCamera = new Camera(false);
|
2011-09-07 23:06:51 +02:00
|
|
|
pCamera->FileLoad(*file);
|
2012-08-22 03:13:32 +02:00
|
|
|
pCamera->CreateName(mCameras);
|
2011-09-07 23:06:51 +02:00
|
|
|
pCamera->Select(true, false, false);
|
2012-08-22 03:13:32 +02:00
|
|
|
pCamera->GetTarget()->Select(true, false, false);
|
|
|
|
mCameras.Add(pCamera);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: lights
|
|
|
|
CalculateStep();
|
|
|
|
SetModifiedFlag(true);
|
|
|
|
CheckPoint("Pasting");
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateFocusObject(GetFocusObject());
|
2011-09-07 23:06:51 +02:00
|
|
|
UpdateSelection();
|
|
|
|
UpdateAllViews ();
|
|
|
|
} break;
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
case LC_EDIT_FIND:
|
|
|
|
if (gMainWindow->DoDialog(LC_DIALOG_FIND, &mSearchOptions))
|
|
|
|
FindPiece(true, true);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LC_EDIT_FIND_NEXT:
|
|
|
|
FindPiece(false, true);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LC_EDIT_FIND_PREVIOUS:
|
|
|
|
FindPiece(false, false);
|
|
|
|
break;
|
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
case LC_EDIT_SELECT_ALL:
|
|
|
|
{
|
|
|
|
Piece* pPiece;
|
|
|
|
for (pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
|
|
|
if (pPiece->IsVisible(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation))
|
|
|
|
pPiece->Select(true, false, false);
|
|
|
|
|
|
|
|
// pFrame->UpdateInfo();
|
|
|
|
UpdateSelection();
|
|
|
|
UpdateAllViews ();
|
|
|
|
} break;
|
2013-01-06 20:24:25 +01:00
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
case LC_EDIT_SELECT_NONE:
|
|
|
|
{
|
|
|
|
SelectAndFocusNone(false);
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateFocusObject(NULL);
|
2011-09-07 23:06:51 +02:00
|
|
|
UpdateSelection();
|
|
|
|
UpdateAllViews();
|
|
|
|
} break;
|
2013-01-06 20:24:25 +01:00
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
case LC_EDIT_SELECT_INVERT:
|
|
|
|
{
|
|
|
|
Piece* pPiece;
|
|
|
|
for (pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
|
|
|
if (pPiece->IsVisible(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation))
|
|
|
|
{
|
|
|
|
if (pPiece->IsSelected())
|
|
|
|
pPiece->Select(false, false, false);
|
|
|
|
else
|
|
|
|
pPiece->Select(true, false, false);
|
|
|
|
}
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateFocusObject(GetFocusObject());
|
2011-09-07 23:06:51 +02:00
|
|
|
UpdateSelection();
|
|
|
|
UpdateAllViews();
|
|
|
|
} break;
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
case LC_EDIT_SELECT_BY_NAME:
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
lcSelectDialogOptions Options;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
for (Piece* pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
|
|
|
Options.Selection.Add(pPiece->IsSelected());
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-08-22 03:13:32 +02:00
|
|
|
for (int CameraIdx = 0; CameraIdx < mCameras.GetSize(); CameraIdx++)
|
2013-08-09 06:57:18 +02:00
|
|
|
if (mCameras[CameraIdx]->IsVisible())
|
|
|
|
Options.Selection.Add(mCameras[CameraIdx]->IsSelected());
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
for (Light* pLight = m_pLights; pLight; pLight = pLight->m_pNext)
|
2011-09-07 23:06:51 +02:00
|
|
|
if (pLight->IsVisible())
|
2013-08-09 06:57:18 +02:00
|
|
|
Options.Selection.Add(pLight->IsSelected());
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
if (Options.Selection.GetSize() == 0)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->DoMessageBox("Nothing to select.", LC_MB_OK | LC_MB_ICONINFORMATION);
|
2011-09-07 23:06:51 +02:00
|
|
|
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
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
SelectAndFocusNone(false);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
int ObjectIndex = 0;
|
|
|
|
for (Piece* pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext, ObjectIndex++)
|
|
|
|
if (Options.Selection[ObjectIndex])
|
|
|
|
pPiece->Select(true, false, false);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
for (int CameraIdx = 0; CameraIdx < mCameras.GetSize(); CameraIdx++, ObjectIndex++)
|
|
|
|
if (Options.Selection[ObjectIndex])
|
|
|
|
mCameras[CameraIdx]->Select(true, false, false);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
for (Light* pLight = m_pLights; pLight; pLight = pLight->m_pNext, ObjectIndex++)
|
|
|
|
if (Options.Selection[ObjectIndex])
|
|
|
|
pLight->Select(true, false, false);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
UpdateSelection();
|
|
|
|
UpdateAllViews();
|
|
|
|
// pFrame->UpdateInfo();
|
2011-09-07 23:06:51 +02:00
|
|
|
} break;
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
case LC_VIEW_SPLIT_HORIZONTAL:
|
|
|
|
gMainWindow->SplitHorizontal();
|
|
|
|
break;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
case LC_VIEW_SPLIT_VERTICAL:
|
|
|
|
gMainWindow->SplitVertical();
|
|
|
|
break;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
case LC_VIEW_REMOVE_VIEW:
|
|
|
|
gMainWindow->RemoveView();
|
|
|
|
break;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
case LC_VIEW_RESET_VIEWS:
|
|
|
|
gMainWindow->ResetViews();
|
|
|
|
break;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
case LC_VIEW_FULLSCREEN:
|
|
|
|
gMainWindow->ToggleFullScreen();
|
|
|
|
break;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
case LC_PIECE_INSERT:
|
|
|
|
{
|
|
|
|
if (m_pCurPiece == NULL)
|
|
|
|
break;
|
|
|
|
Piece* pLast = NULL;
|
|
|
|
Piece* pPiece = new Piece(m_pCurPiece);
|
|
|
|
|
|
|
|
for (pLast = m_pPieces; pLast; pLast = pLast->m_pNext)
|
|
|
|
if ((pLast->IsFocused()) || (pLast->m_pNext == NULL))
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (pLast != NULL)
|
|
|
|
{
|
2012-06-16 02:17:52 +02:00
|
|
|
lcVector3 Pos;
|
|
|
|
lcVector4 Rot;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
GetPieceInsertPosition(pLast, Pos, Rot);
|
|
|
|
|
2012-03-28 03:07:18 +02:00
|
|
|
pPiece->Initialize(Pos[0], Pos[1], Pos[2], m_nCurStep, m_nCurFrame);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
pPiece->ChangeKey(m_nCurStep, false, false, Rot, LC_PK_ROTATION);
|
|
|
|
pPiece->ChangeKey(m_nCurFrame, true, false, Rot, LC_PK_ROTATION);
|
|
|
|
pPiece->UpdatePosition(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation);
|
|
|
|
}
|
|
|
|
else
|
2012-03-28 03:07:18 +02:00
|
|
|
pPiece->Initialize(0, 0, 0, m_nCurStep, m_nCurFrame);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
SelectAndFocusNone(false);
|
2013-08-09 06:57:18 +02:00
|
|
|
pPiece->SetColorIndex(gMainWindow->mColorIndex);
|
2011-09-07 23:06:51 +02:00
|
|
|
pPiece->CreateName(m_pPieces);
|
|
|
|
AddPiece(pPiece);
|
|
|
|
pPiece->Select (true, true, false);
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateFocusObject(pPiece);
|
2011-09-07 23:06:51 +02:00
|
|
|
UpdateSelection();
|
|
|
|
SystemPieceComboAdd(m_pCurPiece->m_strDescription);
|
|
|
|
|
|
|
|
// AfxGetMainWnd()->PostMessage(WM_LC_UPDATE_INFO, (WPARAM)pNew, OT_PIECE);
|
|
|
|
UpdateAllViews();
|
|
|
|
SetModifiedFlag(true);
|
|
|
|
CheckPoint("Inserting");
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_PIECE_DELETE:
|
|
|
|
{
|
|
|
|
if (RemoveSelectedObjects())
|
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateFocusObject(NULL);
|
2011-09-07 23:06:51 +02:00
|
|
|
UpdateSelection();
|
|
|
|
UpdateAllViews();
|
|
|
|
SetModifiedFlag(true);
|
|
|
|
CheckPoint("Deleting");
|
|
|
|
}
|
|
|
|
} 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
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
lcVector3 axis;
|
|
|
|
bool Rotate = id >= LC_PIECE_ROTATE_PLUSX && id <= LC_PIECE_ROTATE_MINUSZ;
|
|
|
|
|
|
|
|
if (Rotate)
|
|
|
|
{
|
|
|
|
if (m_nSnap & LC_DRAW_SNAP_A)
|
|
|
|
axis[0] = axis[1] = axis[2] = m_nAngleSnap;
|
|
|
|
else
|
|
|
|
axis[0] = axis[1] = axis[2] = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
float xy, z;
|
|
|
|
GetSnapDistance(&xy, &z);
|
|
|
|
|
|
|
|
axis[0] = axis[1] = xy;
|
|
|
|
axis[2] = z;
|
|
|
|
|
|
|
|
if ((m_nSnap & LC_DRAW_SNAP_X) == 0)// || bControl)
|
|
|
|
axis[0] = 0.01f;
|
|
|
|
if ((m_nSnap & LC_DRAW_SNAP_Y) == 0)// || bControl)
|
|
|
|
axis[1] = 0.01f;
|
|
|
|
if ((m_nSnap & LC_DRAW_SNAP_Z) == 0)// || bControl)
|
|
|
|
axis[2] = 0.01f;
|
|
|
|
}
|
|
|
|
|
|
|
|
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]);
|
|
|
|
|
|
|
|
if ((m_nSnap & LC_DRAW_MOVEAXIS) == 0)
|
|
|
|
{
|
|
|
|
// TODO: rewrite this
|
|
|
|
|
|
|
|
int Viewport[4] = { 0, 0, m_ActiveView->mWidth, m_ActiveView->mHeight };
|
|
|
|
float Aspect = (float)Viewport[2]/(float)Viewport[3];
|
|
|
|
Camera* Cam = m_ActiveView->mCamera;
|
|
|
|
|
|
|
|
const lcMatrix44& ModelView = Cam->mWorldView;
|
|
|
|
lcMatrix44 Projection = lcMatrix44Perspective(Cam->m_fovy, Aspect, Cam->m_zNear, Cam->m_zFar);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
lcVector3 Pts[3] = { lcVector3(5.0f, 5.0f, 0.1f), lcVector3(10.0f, 5.0f, 0.1f), lcVector3(5.0f, 10.0f, 0.1f) };
|
|
|
|
lcUnprojectPoints(Pts, 3, ModelView, Projection, Viewport);
|
|
|
|
|
|
|
|
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));
|
|
|
|
|
|
|
|
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));
|
|
|
|
|
|
|
|
if (ax > 135)
|
|
|
|
axis[0] = -axis[0];
|
|
|
|
|
|
|
|
if (ay < 45)
|
|
|
|
axis[1] = -axis[1];
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Rotate)
|
|
|
|
{
|
|
|
|
lcVector3 tmp;
|
|
|
|
RotateSelectedObjects(axis, tmp, true, true);
|
|
|
|
}
|
|
|
|
else
|
2012-02-08 23:48:51 +01:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
lcVector3 tmp;
|
|
|
|
MoveSelectedObjects(axis, tmp, false, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
UpdateOverlayScale();
|
|
|
|
UpdateAllViews();
|
|
|
|
SetModifiedFlag(true);
|
|
|
|
CheckPoint(Rotate ? "Rotating" : "Moving");
|
|
|
|
gMainWindow->UpdateFocusObject(GetFocusObject());
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_PIECE_MINIFIG_WIZARD:
|
|
|
|
{
|
|
|
|
lcMinifig Minifig;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (!gMainWindow->DoDialog(LC_DIALOG_MINIFIG, &Minifig))
|
|
|
|
break;
|
|
|
|
|
2012-02-08 23:48:51 +01:00
|
|
|
SelectAndFocusNone(false);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-02-08 23:48:51 +01:00
|
|
|
for (i = 0; i < LC_MFW_NUMITEMS; i++)
|
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
if (Minifig.Parts[i] == NULL)
|
2012-02-08 23:48:51 +01:00
|
|
|
continue;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
Piece* pPiece = new Piece(Minifig.Parts[i]);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
lcVector4& Position = Minifig.Matrices[i][3];
|
|
|
|
lcVector4 Rotation = lcMatrix44ToAxisAngle(Minifig.Matrices[i]);
|
2012-02-08 23:48:51 +01:00
|
|
|
Rotation[3] *= LC_RTOD;
|
2012-03-28 03:07:18 +02:00
|
|
|
pPiece->Initialize(Position[0], Position[1], Position[2], m_nCurStep, m_nCurFrame);
|
2013-08-09 06:57:18 +02:00
|
|
|
pPiece->SetColorIndex(Minifig.Colors[i]);
|
2012-02-08 23:48:51 +01:00
|
|
|
pPiece->CreateName(m_pPieces);
|
|
|
|
AddPiece(pPiece);
|
|
|
|
pPiece->Select(true, false, false);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-02-08 23:48:51 +01:00
|
|
|
pPiece->ChangeKey(1, false, false, Rotation, LC_PK_ROTATION);
|
|
|
|
pPiece->ChangeKey(1, true, false, Rotation, LC_PK_ROTATION);
|
|
|
|
pPiece->UpdatePosition(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
SystemPieceComboAdd(Minifig.Parts[i]->m_strDescription);
|
2012-02-08 23:48:51 +01:00
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
float bs[6] = { 10000, 10000, 10000, -10000, -10000, -10000 };
|
|
|
|
int max = 0;
|
|
|
|
|
|
|
|
Group* pGroup;
|
|
|
|
for (pGroup = m_pGroups; pGroup; pGroup = pGroup->m_pNext)
|
|
|
|
if (strncmp (pGroup->m_strName, "Minifig #", 9) == 0)
|
|
|
|
if (sscanf(pGroup->m_strName, "Minifig #%d", &i) == 1)
|
|
|
|
if (i > max)
|
|
|
|
max = i;
|
|
|
|
pGroup = new Group;
|
|
|
|
sprintf(pGroup->m_strName, "Minifig #%.2d", max+1);
|
|
|
|
|
|
|
|
pGroup->m_pNext = m_pGroups;
|
|
|
|
m_pGroups = pGroup;
|
|
|
|
|
|
|
|
for (Piece* pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
|
|
|
if (pPiece->IsSelected())
|
|
|
|
{
|
|
|
|
pPiece->SetGroup(pGroup);
|
|
|
|
pPiece->CompareBoundingBox(bs);
|
|
|
|
}
|
|
|
|
|
|
|
|
pGroup->m_fCenter[0] = (bs[0]+bs[3])/2;
|
|
|
|
pGroup->m_fCenter[1] = (bs[1]+bs[4])/2;
|
|
|
|
pGroup->m_fCenter[2] = (bs[2]+bs[5])/2;
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateFocusObject(GetFocusObject());
|
2011-09-07 23:06:51 +02:00
|
|
|
UpdateSelection();
|
|
|
|
UpdateAllViews();
|
|
|
|
SetModifiedFlag(true);
|
|
|
|
CheckPoint("Minifig");
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_PIECE_ARRAY:
|
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
Piece *pPiece, *pFirst = NULL, *pLast = NULL;
|
|
|
|
float bs[6] = { 10000, 10000, 10000, -10000, -10000, -10000 };
|
|
|
|
int sel = 0;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
for (pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
if (pPiece->IsSelected())
|
|
|
|
{
|
|
|
|
pPiece->CompareBoundingBox(bs);
|
|
|
|
sel++;
|
|
|
|
}
|
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
if (!sel)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->DoMessageBox("No pieces selected.", LC_MB_OK | LC_MB_ICONINFORMATION);
|
2011-09-07 23:06:51 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
lcArrayDialogOptions Options;
|
|
|
|
|
|
|
|
memset(&Options, 0, sizeof(Options));
|
|
|
|
Options.Counts[0] = 10;
|
|
|
|
Options.Counts[1] = 1;
|
|
|
|
Options.Counts[2] = 1;
|
|
|
|
|
|
|
|
if (!gMainWindow->DoDialog(LC_DIALOG_PIECE_ARRAY, &Options))
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (Options.Counts[0] * Options.Counts[1] * Options.Counts[2] < 2)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
ConvertFromUserUnits(Options.Offsets[0]);
|
|
|
|
ConvertFromUserUnits(Options.Offsets[1]);
|
|
|
|
ConvertFromUserUnits(Options.Offsets[2]);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +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++)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
if (Step1 == 0 && Step2 == 0 && Step3 == 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
lcMatrix44 ModelWorld;
|
|
|
|
lcVector3 Position;
|
|
|
|
|
|
|
|
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 (pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
|
|
|
{
|
|
|
|
if (!pPiece->IsSelected())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (sel == 1)
|
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
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));
|
2012-10-18 20:57:21 +02:00
|
|
|
|
|
|
|
Position = pPiece->mPosition;
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-10-18 20:57:21 +02:00
|
|
|
lcVector4 Center((bs[0] + bs[3]) / 2, (bs[1] + bs[4]) / 2, (bs[2] + bs[5]) / 2, 0.0f);
|
|
|
|
ModelWorld = pPiece->mModelWorld;
|
|
|
|
|
|
|
|
ModelWorld.r[3] -= Center;
|
2013-08-09 06:57:18 +02:00
|
|
|
ModelWorld = lcMul(ModelWorld, lcMatrix44RotationX(RotationAngles[0] * LC_DTOR));
|
|
|
|
ModelWorld = lcMul(ModelWorld, lcMatrix44RotationY(RotationAngles[1] * LC_DTOR));
|
|
|
|
ModelWorld = lcMul(ModelWorld, lcMatrix44RotationZ(RotationAngles[2] * LC_DTOR));
|
2012-10-18 20:57:21 +02:00
|
|
|
ModelWorld.r[3] += Center;
|
|
|
|
|
|
|
|
Position = lcVector3(ModelWorld.r[3].x, ModelWorld.r[3].y, ModelWorld.r[3].z);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
2012-10-18 20:57:21 +02:00
|
|
|
|
|
|
|
lcVector4 AxisAngle = lcMatrix44ToAxisAngle(ModelWorld);
|
|
|
|
AxisAngle[3] *= LC_RTOD;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
if (pLast)
|
|
|
|
{
|
2012-05-17 23:52:20 +02:00
|
|
|
pLast->m_pNext = new Piece(pPiece->mPieceInfo);
|
2011-09-07 23:06:51 +02:00
|
|
|
pLast = pLast->m_pNext;
|
|
|
|
}
|
|
|
|
else
|
2012-05-17 23:52:20 +02:00
|
|
|
pLast = pFirst = new Piece(pPiece->mPieceInfo);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
pLast->Initialize(Position[0] + Offset[0], Position[1] + Offset[1], Position[2] + Offset[2], m_nCurStep, m_nCurFrame);
|
2012-03-28 03:07:18 +02:00
|
|
|
pLast->SetColorIndex(pPiece->mColorIndex);
|
2012-10-18 20:57:21 +02:00
|
|
|
pLast->ChangeKey(1, false, false, AxisAngle, LC_PK_ROTATION);
|
|
|
|
pLast->ChangeKey(1, true, false, AxisAngle, LC_PK_ROTATION);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
while (pFirst)
|
|
|
|
{
|
|
|
|
pPiece = pFirst->m_pNext;
|
|
|
|
pFirst->CreateName(m_pPieces);
|
|
|
|
pFirst->UpdatePosition(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation);
|
|
|
|
AddPiece(pFirst);
|
|
|
|
pFirst = pPiece;
|
|
|
|
}
|
|
|
|
|
|
|
|
SelectAndFocusNone(true);
|
2013-08-09 06:57:18 +02:00
|
|
|
// gMainWindow->UpdateFocusObject(GetFocusObject());
|
2011-09-07 23:06:51 +02:00
|
|
|
UpdateSelection();
|
|
|
|
UpdateAllViews();
|
|
|
|
SetModifiedFlag(true);
|
|
|
|
CheckPoint("Array");
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_PIECE_GROUP:
|
|
|
|
{
|
|
|
|
Group* pGroup;
|
|
|
|
int i, max = 0;
|
|
|
|
char name[65];
|
2013-08-09 06:57:18 +02:00
|
|
|
int Selected = 0;
|
|
|
|
|
|
|
|
for (Piece* pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
|
|
|
{
|
|
|
|
if (pPiece->IsSelected())
|
|
|
|
{
|
|
|
|
Selected++;
|
|
|
|
|
|
|
|
if (Selected > 1)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!Selected)
|
|
|
|
{
|
|
|
|
gMainWindow->DoMessageBox("No pieces selected.", LC_MB_OK | LC_MB_ICONINFORMATION);
|
|
|
|
break;
|
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
for (pGroup = m_pGroups; pGroup; pGroup = pGroup->m_pNext)
|
|
|
|
if (strncmp (pGroup->m_strName, "Group #", 7) == 0)
|
|
|
|
if (sscanf(pGroup->m_strName, "Group #%d", &i) == 1)
|
|
|
|
if (i > max)
|
|
|
|
max = i;
|
|
|
|
sprintf(name, "Group #%.2d", max+1);
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
if (!gMainWindow->DoDialog(LC_DIALOG_PIECE_GROUP, name))
|
|
|
|
break;
|
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
pGroup = new Group();
|
|
|
|
strcpy(pGroup->m_strName, name);
|
|
|
|
pGroup->m_pNext = m_pGroups;
|
|
|
|
m_pGroups = pGroup;
|
|
|
|
float bs[6] = { 10000, 10000, 10000, -10000, -10000, -10000 };
|
|
|
|
|
|
|
|
for (Piece* pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
|
|
|
if (pPiece->IsSelected())
|
|
|
|
{
|
|
|
|
pPiece->DoGroup(pGroup);
|
|
|
|
pPiece->CompareBoundingBox(bs);
|
|
|
|
}
|
2013-01-06 20:24:25 +01:00
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
pGroup->m_fCenter[0] = (bs[0]+bs[3])/2;
|
|
|
|
pGroup->m_fCenter[1] = (bs[1]+bs[4])/2;
|
|
|
|
pGroup->m_fCenter[2] = (bs[2]+bs[5])/2;
|
|
|
|
|
|
|
|
RemoveEmptyGroups();
|
|
|
|
SetModifiedFlag(true);
|
|
|
|
CheckPoint("Grouping");
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_PIECE_UNGROUP:
|
|
|
|
{
|
|
|
|
Group* pList = NULL;
|
|
|
|
Group* pGroup;
|
|
|
|
Group* tmp;
|
|
|
|
Piece* pPiece;
|
|
|
|
|
|
|
|
for (pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
|
|
|
if (pPiece->IsSelected())
|
|
|
|
{
|
|
|
|
pGroup = pPiece->GetTopGroup();
|
|
|
|
|
|
|
|
// Check if we already removed the group
|
|
|
|
for (tmp = pList; tmp; tmp = tmp->m_pNext)
|
|
|
|
if (pGroup == tmp)
|
|
|
|
pGroup = NULL;
|
|
|
|
|
|
|
|
if (pGroup != NULL)
|
|
|
|
{
|
|
|
|
// First remove the group from the array
|
|
|
|
for (tmp = m_pGroups; tmp->m_pNext; tmp = tmp->m_pNext)
|
|
|
|
if (tmp->m_pNext == pGroup)
|
|
|
|
{
|
|
|
|
tmp->m_pNext = pGroup->m_pNext;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pGroup == m_pGroups)
|
|
|
|
m_pGroups = pGroup->m_pNext;
|
|
|
|
|
|
|
|
// Now add it to the list of top groups
|
|
|
|
pGroup->m_pNext = pList;
|
|
|
|
pList = pGroup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
while (pList)
|
|
|
|
{
|
|
|
|
for (pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
|
|
|
if (pPiece->IsSelected())
|
|
|
|
pPiece->UnGroup(pList);
|
|
|
|
|
|
|
|
pGroup = pList;
|
|
|
|
pList = pList->m_pNext;
|
|
|
|
delete pGroup;
|
|
|
|
}
|
|
|
|
|
|
|
|
RemoveEmptyGroups();
|
|
|
|
SetModifiedFlag(true);
|
|
|
|
CheckPoint("Ungrouping");
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_PIECE_GROUP_ADD:
|
|
|
|
{
|
|
|
|
Group* pGroup = NULL;
|
|
|
|
Piece* pPiece;
|
|
|
|
|
|
|
|
for (pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
|
|
|
if (pPiece->IsSelected())
|
|
|
|
{
|
|
|
|
pGroup = pPiece->GetTopGroup();
|
|
|
|
if (pGroup != NULL)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pGroup != NULL)
|
|
|
|
{
|
|
|
|
for (pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
|
|
|
if (pPiece->IsFocused())
|
|
|
|
{
|
|
|
|
pPiece->SetGroup(pGroup);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
RemoveEmptyGroups();
|
|
|
|
SetModifiedFlag(true);
|
|
|
|
CheckPoint("Grouping");
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_PIECE_GROUP_REMOVE:
|
|
|
|
{
|
|
|
|
Piece* pPiece;
|
|
|
|
|
|
|
|
for (pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
|
|
|
if (pPiece->IsFocused())
|
|
|
|
{
|
|
|
|
pPiece->UnGroup(NULL);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
RemoveEmptyGroups();
|
|
|
|
SetModifiedFlag(true);
|
|
|
|
CheckPoint("Ungrouping");
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_PIECE_GROUP_EDIT:
|
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
lcEditGroupsDialogOptions Options;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
for (Piece* pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
|
|
|
Options.PieceParents.Add(pPiece->GetGroup());
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
for (Group* pGroup = m_pGroups; pGroup; pGroup = pGroup->m_pNext)
|
|
|
|
Options.GroupParents.Add(pGroup->m_pGroup);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
if (!gMainWindow->DoDialog(LC_DIALOG_EDIT_GROUPS, &Options))
|
|
|
|
break;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
int PieceIdx = 0;
|
|
|
|
for (Piece* pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
|
|
|
pPiece->SetGroup(Options.PieceParents[PieceIdx++]);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
int GroupIdx = 0;
|
|
|
|
for (Group* pGroup = m_pGroups; pGroup; pGroup = pGroup->m_pNext)
|
|
|
|
pGroup->m_pGroup = Options.GroupParents[GroupIdx++];
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
RemoveEmptyGroups();
|
|
|
|
SelectAndFocusNone(false);
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateFocusObject(GetFocusObject());
|
2011-09-07 23:06:51 +02:00
|
|
|
UpdateSelection();
|
|
|
|
UpdateAllViews();
|
|
|
|
SetModifiedFlag(true);
|
|
|
|
CheckPoint("Editing");
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_PIECE_HIDE_SELECTED:
|
|
|
|
{
|
|
|
|
Piece* pPiece;
|
|
|
|
for (pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
|
|
|
if (pPiece->IsSelected())
|
|
|
|
pPiece->Hide();
|
|
|
|
UpdateSelection();
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateFocusObject(NULL);
|
2011-09-07 23:06:51 +02:00
|
|
|
UpdateAllViews();
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_PIECE_HIDE_UNSELECTED:
|
|
|
|
{
|
|
|
|
Piece* pPiece;
|
|
|
|
for (pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
|
|
|
if (!pPiece->IsSelected())
|
|
|
|
pPiece->Hide();
|
|
|
|
UpdateSelection();
|
|
|
|
UpdateAllViews();
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_PIECE_UNHIDE_ALL:
|
|
|
|
{
|
|
|
|
Piece* pPiece;
|
|
|
|
for (pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
|
|
|
pPiece->UnHide();
|
|
|
|
UpdateSelection();
|
|
|
|
UpdateAllViews();
|
|
|
|
} break;
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
case LC_PIECE_SHOW_EARLIER:
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
|
|
|
bool redraw = false;
|
|
|
|
|
|
|
|
for (Piece* pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
|
|
|
if (pPiece->IsSelected())
|
|
|
|
{
|
|
|
|
if (m_bAnimation)
|
|
|
|
{
|
|
|
|
unsigned short t = pPiece->GetFrameShow();
|
|
|
|
if (t > 1)
|
|
|
|
{
|
|
|
|
redraw = true;
|
|
|
|
pPiece->SetFrameShow(t-1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
unsigned char t = pPiece->GetStepShow();
|
|
|
|
if (t > 1)
|
|
|
|
{
|
|
|
|
redraw = true;
|
|
|
|
pPiece->SetStepShow(t-1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (redraw)
|
|
|
|
{
|
|
|
|
SetModifiedFlag(true);
|
|
|
|
CheckPoint("Modifying");
|
|
|
|
UpdateAllViews();
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
case LC_PIECE_SHOW_LATER:
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
|
|
|
bool redraw = false;
|
|
|
|
|
|
|
|
for (Piece* pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
|
|
|
if (pPiece->IsSelected())
|
|
|
|
{
|
|
|
|
if (m_bAnimation)
|
|
|
|
{
|
|
|
|
unsigned short t = pPiece->GetFrameShow();
|
|
|
|
if (t < m_nTotalFrames)
|
|
|
|
{
|
|
|
|
redraw = true;
|
|
|
|
pPiece->SetFrameShow(t+1);
|
|
|
|
|
|
|
|
if (pPiece->IsSelected () && t == m_nCurFrame)
|
|
|
|
pPiece->Select (false, false, false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
unsigned char t = pPiece->GetStepShow();
|
|
|
|
if (t < 255)
|
|
|
|
{
|
|
|
|
redraw = true;
|
|
|
|
pPiece->SetStepShow(t+1);
|
|
|
|
|
|
|
|
if (pPiece->IsSelected () && t == m_nCurStep)
|
|
|
|
pPiece->Select (false, false, false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (redraw)
|
|
|
|
{
|
|
|
|
SetModifiedFlag(true);
|
|
|
|
CheckPoint("Modifying");
|
|
|
|
UpdateAllViews();
|
|
|
|
UpdateSelection ();
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_VIEW_PREFERENCES:
|
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
lcPreferencesDialogOptions Options;
|
|
|
|
int CurrentAASamples = lcGetProfileInt(LC_PROFILE_ANTIALIASING_SAMPLES);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
strcpy(Options.DefaultAuthor, lcGetProfileString(LC_PROFILE_DEFAULT_AUTHOR_NAME));
|
|
|
|
strcpy(Options.ProjectsPath, lcGetProfileString(LC_PROFILE_PROJECTS_PATH));
|
|
|
|
strcpy(Options.LibraryPath, lcGetProfileString(LC_PROFILE_PARTS_LIBRARY));
|
2013-08-17 03:17:23 +02:00
|
|
|
strcpy(Options.POVRayPath, lcGetProfileString(LC_PROFILE_POVRAY_PATH));
|
|
|
|
strcpy(Options.LGEOPath, lcGetProfileString(LC_PROFILE_POVRAY_LGEO_PATH));
|
2013-08-09 06:57:18 +02:00
|
|
|
Options.MouseSensitivity = m_nMouse;
|
|
|
|
Options.CheckForUpdates = lcGetProfileInt(LC_PROFILE_CHECK_UPDATES);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
Options.Detail = m_nDetail;
|
|
|
|
Options.Snap = m_nSnap;
|
|
|
|
Options.LineWidth = m_fLineWidth;
|
|
|
|
Options.AASamples = CurrentAASamples;
|
|
|
|
Options.GridSize = m_nGridSize;
|
|
|
|
|
|
|
|
Options.Categories = gCategories;
|
|
|
|
Options.CategoriesModified = false;
|
|
|
|
Options.CategoriesDefault = false;
|
|
|
|
|
|
|
|
Options.KeyboardShortcuts = gKeyboardShortcuts;
|
|
|
|
Options.ShortcutsModified = false;
|
|
|
|
Options.ShortcutsDefault = false;
|
|
|
|
|
|
|
|
if (!gMainWindow->DoDialog(LC_DIALOG_PREFERENCES, &Options))
|
|
|
|
break;
|
|
|
|
|
|
|
|
bool LibraryChanged = strcmp(Options.LibraryPath, lcGetProfileString(LC_PROFILE_PARTS_LIBRARY));
|
|
|
|
bool AAChanged = CurrentAASamples != Options.AASamples;
|
|
|
|
|
|
|
|
m_nMouse = Options.MouseSensitivity;
|
|
|
|
m_nSnap = Options.Snap;
|
|
|
|
m_nDetail = Options.Detail;
|
|
|
|
m_fLineWidth = Options.LineWidth;
|
|
|
|
m_nGridSize = Options.GridSize;
|
|
|
|
|
|
|
|
lcSetProfileString(LC_PROFILE_DEFAULT_AUTHOR_NAME, Options.DefaultAuthor);
|
|
|
|
lcSetProfileString(LC_PROFILE_PROJECTS_PATH, Options.ProjectsPath);
|
|
|
|
lcSetProfileString(LC_PROFILE_PARTS_LIBRARY, Options.LibraryPath);
|
2013-08-17 03:17:23 +02:00
|
|
|
lcSetProfileString(LC_PROFILE_POVRAY_PATH, Options.POVRayPath);
|
|
|
|
lcSetProfileString(LC_PROFILE_POVRAY_LGEO_PATH, Options.LGEOPath);
|
2013-08-09 06:57:18 +02:00
|
|
|
lcSetProfileInt(LC_PROFILE_MOUSE_SENSITIVITY, m_nMouse);
|
|
|
|
lcSetProfileInt(LC_PROFILE_CHECK_UPDATES, Options.CheckForUpdates);
|
|
|
|
lcSetProfileInt(LC_PROFILE_SNAP, Options.Snap);
|
|
|
|
lcSetProfileInt(LC_PROFILE_DETAIL, Options.Detail);
|
|
|
|
lcSetProfileInt(LC_PROFILE_GRID_SIZE, Options.GridSize);
|
|
|
|
lcSetProfileFloat(LC_PROFILE_LINE_WIDTH, Options.LineWidth);
|
|
|
|
lcSetProfileInt(LC_PROFILE_ANTIALIASING_SAMPLES, Options.AASamples);
|
|
|
|
|
|
|
|
if (LibraryChanged && AAChanged)
|
|
|
|
gMainWindow->DoMessageBox("Parts library and Anti-aliasing changes will only take effect the next time you start LeoCAD.", LC_MB_OK);
|
|
|
|
else if (LibraryChanged)
|
|
|
|
gMainWindow->DoMessageBox("Parts library changes will only take effect the next time you start LeoCAD.", LC_MB_OK);
|
|
|
|
else if (AAChanged)
|
|
|
|
gMainWindow->DoMessageBox("Anti-aliasing changes will only take effect the next time you start LeoCAD.", LC_MB_OK);
|
|
|
|
|
|
|
|
if (Options.CategoriesModified)
|
|
|
|
{
|
|
|
|
if (Options.CategoriesDefault)
|
|
|
|
lcResetDefaultCategories();
|
|
|
|
else
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
gCategories = Options.Categories;
|
|
|
|
lcSaveDefaultCategories();
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateCategories();
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
if (Options.ShortcutsModified)
|
|
|
|
{
|
|
|
|
if (Options.ShortcutsDefault)
|
|
|
|
lcResetDefaultKeyboardShortcuts();
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gKeyboardShortcuts = Options.KeyboardShortcuts;
|
|
|
|
lcSaveDefaultKeyboardShortcuts();
|
|
|
|
}
|
|
|
|
|
|
|
|
gMainWindow->UpdateShortcuts();
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: printing preferences
|
|
|
|
/*
|
|
|
|
strcpy(opts.strFooter, m_strFooter);
|
|
|
|
strcpy(opts.strHeader, m_strHeader);
|
|
|
|
*/
|
|
|
|
|
|
|
|
for (int i = 0; i < m_ViewList.GetSize (); i++)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
m_ViewList[i]->MakeCurrent();
|
|
|
|
RenderInitialize(); // TODO: get rid of RenderInitialize(), most of it can be done once per frame
|
|
|
|
}
|
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
UpdateAllViews();
|
|
|
|
} break;
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
case LC_VIEW_ZOOM_IN:
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
ZoomActiveView(-1);
|
2011-09-07 23:06:51 +02:00
|
|
|
} break;
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
case LC_VIEW_ZOOM_OUT:
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
ZoomActiveView(1);
|
2011-09-07 23:06:51 +02:00
|
|
|
} break;
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
case LC_VIEW_ZOOM_EXTENTS:
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2012-02-02 04:30:26 +01:00
|
|
|
int FirstView, LastView;
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
// TODO: Find a way to let users zoom extents all views
|
|
|
|
// if (Sys_KeyDown(KEY_CONTROL))
|
|
|
|
// {
|
|
|
|
// FirstView = 0;
|
|
|
|
// LastView = m_ViewList.GetSize();
|
|
|
|
// }
|
|
|
|
// else
|
2012-02-02 04:30:26 +01:00
|
|
|
{
|
|
|
|
FirstView = m_ViewList.FindIndex(m_ActiveView);
|
|
|
|
LastView = FirstView + 1;
|
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-12-13 01:20:40 +01:00
|
|
|
ZoomExtents(FirstView, LastView);
|
2011-09-07 23:06:51 +02:00
|
|
|
} break;
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
case LC_VIEW_TIME_NEXT:
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
|
|
|
if (m_bAnimation)
|
|
|
|
m_nCurFrame++;
|
|
|
|
else
|
|
|
|
m_nCurStep++;
|
|
|
|
|
|
|
|
CalculateStep();
|
|
|
|
UpdateSelection();
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateFocusObject(GetFocusObject());
|
2011-09-07 23:06:51 +02:00
|
|
|
UpdateAllViews();
|
|
|
|
|
|
|
|
if (m_bAnimation)
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateTime(m_bAnimation, m_nCurFrame, m_nTotalFrames);
|
2011-09-07 23:06:51 +02:00
|
|
|
else
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateTime(m_bAnimation, m_nCurStep, 255);
|
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
|
|
|
{
|
|
|
|
if (m_bAnimation)
|
|
|
|
m_nCurFrame--;
|
|
|
|
else
|
|
|
|
m_nCurStep--;
|
|
|
|
|
|
|
|
CalculateStep();
|
|
|
|
UpdateSelection();
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateFocusObject(GetFocusObject());
|
2011-09-07 23:06:51 +02:00
|
|
|
UpdateAllViews();
|
|
|
|
|
|
|
|
if (m_bAnimation)
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateTime(m_bAnimation, m_nCurFrame, m_nTotalFrames);
|
2011-09-07 23:06:51 +02:00
|
|
|
else
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateTime(m_bAnimation, m_nCurStep, 255);
|
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
|
|
|
{
|
|
|
|
if (m_bAnimation)
|
|
|
|
m_nCurFrame = 1;
|
|
|
|
else
|
|
|
|
m_nCurStep = 1;
|
|
|
|
|
|
|
|
CalculateStep();
|
|
|
|
UpdateSelection();
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateFocusObject(GetFocusObject());
|
2011-09-07 23:06:51 +02:00
|
|
|
UpdateAllViews();
|
|
|
|
|
|
|
|
if (m_bAnimation)
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateTime(m_bAnimation, m_nCurFrame, m_nTotalFrames);
|
2011-09-07 23:06:51 +02:00
|
|
|
else
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateTime(m_bAnimation, m_nCurStep, 255);
|
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
|
|
|
{
|
|
|
|
if (m_bAnimation)
|
|
|
|
m_nCurFrame = m_nTotalFrames;
|
|
|
|
else
|
|
|
|
m_nCurStep = GetLastStep ();
|
|
|
|
|
|
|
|
CalculateStep();
|
|
|
|
UpdateSelection();
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateFocusObject(GetFocusObject());
|
2011-09-07 23:06:51 +02:00
|
|
|
UpdateAllViews();
|
|
|
|
|
|
|
|
if (m_bAnimation)
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateTime(m_bAnimation, m_nCurFrame, m_nTotalFrames);
|
2011-09-07 23:06:51 +02:00
|
|
|
else
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateTime(m_bAnimation, m_nCurStep, 255);
|
2011-09-07 23:06:51 +02:00
|
|
|
} break;
|
2013-08-09 06:57:18 +02:00
|
|
|
/*
|
2011-09-07 23:06:51 +02:00
|
|
|
case LC_VIEW_STEP_SET:
|
|
|
|
{
|
|
|
|
if (m_bAnimation)
|
|
|
|
m_nCurFrame = (nParam < m_nTotalFrames) ? (unsigned short)nParam : m_nTotalFrames;
|
|
|
|
else
|
|
|
|
m_nCurStep = (nParam < 255) ? (unsigned char)nParam : 255;
|
|
|
|
|
|
|
|
CalculateStep();
|
|
|
|
UpdateSelection();
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateFocusObject(GetFocusObject());
|
2011-09-07 23:06:51 +02:00
|
|
|
UpdateAllViews();
|
|
|
|
|
|
|
|
if (m_bAnimation)
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateTime(m_bAnimation, m_nCurFrame, m_nTotalFrames);
|
2011-09-07 23:06:51 +02:00
|
|
|
else
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateTime(m_bAnimation, m_nCurStep, 255);
|
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 (Piece* pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
|
|
|
pPiece->InsertTime(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation, 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-08-22 03:13:32 +02:00
|
|
|
for (int CameraIdx = 0; CameraIdx < mCameras.GetSize(); CameraIdx++)
|
|
|
|
mCameras[CameraIdx]->InsertTime(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation, 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-08-22 03:13:32 +02:00
|
|
|
for (Light* pLight = m_pLights; pLight; pLight = pLight->m_pNext)
|
|
|
|
pLight->InsertTime(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation, 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-08-22 03:13:32 +02:00
|
|
|
SetModifiedFlag(true);
|
|
|
|
if (m_bAnimation)
|
|
|
|
CheckPoint("Adding Frame");
|
|
|
|
else
|
|
|
|
CheckPoint("Adding Step");
|
|
|
|
CalculateStep();
|
|
|
|
UpdateAllViews();
|
|
|
|
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 (Piece* pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
|
|
|
pPiece->RemoveTime(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation, 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-08-22 03:13:32 +02:00
|
|
|
for (int CameraIdx = 0; CameraIdx < mCameras.GetSize(); CameraIdx++)
|
|
|
|
mCameras[CameraIdx]->RemoveTime(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation, 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-08-22 03:13:32 +02:00
|
|
|
for (Light* pLight = m_pLights; pLight; pLight = pLight->m_pNext)
|
|
|
|
pLight->RemoveTime(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation, 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-08-22 03:13:32 +02:00
|
|
|
SetModifiedFlag (true);
|
|
|
|
if (m_bAnimation)
|
|
|
|
CheckPoint("Removing Frame");
|
|
|
|
else
|
|
|
|
CheckPoint("Removing Step");
|
|
|
|
CalculateStep();
|
|
|
|
UpdateAllViews();
|
|
|
|
UpdateSelection();
|
|
|
|
} break;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
case LC_VIEW_TIME_STOP:
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
|
|
|
m_bStopRender = true;
|
|
|
|
} break;
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
case LC_VIEW_TIME_PLAY:
|
2013-01-06 20:24:25 +01:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
// TODO: Rewrite animation playback by posting events, not looping here
|
|
|
|
/*
|
2011-09-07 23:06:51 +02:00
|
|
|
SelectAndFocusNone(false);
|
|
|
|
UpdateSelection();
|
|
|
|
m_bStopRender = false;
|
|
|
|
SystemUpdatePlay(false, true);
|
|
|
|
long time = SystemGetTicks();
|
|
|
|
unsigned short tics;
|
|
|
|
float rate = 1000.0f/m_nFPS;
|
|
|
|
|
|
|
|
while (!m_bStopRender)
|
|
|
|
{
|
|
|
|
tics = (unsigned short)(SystemGetTicks() - time);
|
|
|
|
if (tics < rate)
|
|
|
|
continue; // nothing to do
|
|
|
|
|
|
|
|
time = SystemGetTicks();
|
|
|
|
m_nCurFrame += (unsigned short)((float)tics/rate);
|
|
|
|
while (m_nCurFrame > m_nTotalFrames)
|
|
|
|
m_nCurFrame -= m_nTotalFrames;
|
|
|
|
CalculateStep();
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateTime(true, m_nCurFrame, m_nTotalFrames);
|
2011-09-20 03:26:31 +02:00
|
|
|
UpdateAllViews();
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
SystemUpdatePlay(true, false);
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateFocusObject(GetFocusObject());
|
|
|
|
*/
|
2011-09-07 23:06:51 +02:00
|
|
|
} break;
|
|
|
|
|
2012-08-20 06:05:56 +02:00
|
|
|
case LC_VIEW_VIEWPOINT_FRONT:
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2012-08-20 06:05:56 +02:00
|
|
|
m_ActiveView->mCamera->SetViewpoint(LC_VIEWPOINT_FRONT, m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation, m_bAddKeys);
|
2013-08-09 06:57:18 +02:00
|
|
|
HandleCommand(LC_VIEW_ZOOM_EXTENTS);
|
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
|
|
|
{
|
2012-08-20 06:05:56 +02:00
|
|
|
m_ActiveView->mCamera->SetViewpoint(LC_VIEWPOINT_BACK, m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation, m_bAddKeys);
|
2013-08-09 06:57:18 +02:00
|
|
|
HandleCommand(LC_VIEW_ZOOM_EXTENTS);
|
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
|
|
|
{
|
2012-08-20 06:05:56 +02:00
|
|
|
m_ActiveView->mCamera->SetViewpoint(LC_VIEWPOINT_TOP, m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation, m_bAddKeys);
|
2013-08-09 06:57:18 +02:00
|
|
|
HandleCommand(LC_VIEW_ZOOM_EXTENTS);
|
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
|
|
|
{
|
2012-08-22 03:13:32 +02:00
|
|
|
m_ActiveView->mCamera->SetViewpoint(LC_VIEWPOINT_BOTTOM, m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation, m_bAddKeys);
|
2013-08-09 06:57:18 +02:00
|
|
|
HandleCommand(LC_VIEW_ZOOM_EXTENTS);
|
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
|
|
|
{
|
2012-08-20 06:05:56 +02:00
|
|
|
m_ActiveView->mCamera->SetViewpoint(LC_VIEWPOINT_LEFT, m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation, m_bAddKeys);
|
2013-08-09 06:57:18 +02:00
|
|
|
HandleCommand(LC_VIEW_ZOOM_EXTENTS);
|
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
|
|
|
{
|
2012-08-20 06:05:56 +02:00
|
|
|
m_ActiveView->mCamera->SetViewpoint(LC_VIEWPOINT_RIGHT, m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation, m_bAddKeys);
|
2013-08-09 06:57:18 +02:00
|
|
|
HandleCommand(LC_VIEW_ZOOM_EXTENTS);
|
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
|
|
|
{
|
2012-08-20 06:05:56 +02:00
|
|
|
m_ActiveView->mCamera->SetViewpoint(LC_VIEWPOINT_HOME, m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation, m_bAddKeys);
|
2013-08-09 06:57:18 +02:00
|
|
|
HandleCommand(LC_VIEW_ZOOM_EXTENTS);
|
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
|
|
|
{
|
2012-11-15 02:14:35 +01:00
|
|
|
Camera* pCamera = NULL;
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
if (id == LC_VIEW_CAMERA_NONE)
|
2012-11-15 02:14:35 +01:00
|
|
|
{
|
|
|
|
pCamera = m_ActiveView->mCamera;
|
|
|
|
|
|
|
|
if (!pCamera->IsSimple())
|
|
|
|
{
|
|
|
|
m_ActiveView->SetCamera(pCamera, true);
|
|
|
|
pCamera = m_ActiveView->mCamera;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
if (id - LC_VIEW_CAMERA1 < mCameras.GetSize())
|
|
|
|
{
|
|
|
|
pCamera = mCameras[id - LC_VIEW_CAMERA1];
|
|
|
|
m_ActiveView->SetCamera(pCamera, false);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
break;
|
2012-11-15 02:14:35 +01:00
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateCurrentCamera(mCameras.FindIndex(m_ActiveView->mCamera));
|
2011-09-07 23:06:51 +02:00
|
|
|
UpdateOverlayScale();
|
|
|
|
UpdateAllViews();
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_VIEW_CAMERA_RESET:
|
|
|
|
{
|
2012-02-05 03:50:57 +01:00
|
|
|
for (int ViewIdx = 0; ViewIdx < m_ViewList.GetSize(); ViewIdx++)
|
2012-08-20 06:05:56 +02:00
|
|
|
m_ViewList[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();
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateCameraMenu(mCameras, m_ActiveView ? m_ActiveView->mCamera : NULL);
|
|
|
|
gMainWindow->UpdateFocusObject(GetFocusObject());
|
2011-09-07 23:06:51 +02:00
|
|
|
UpdateOverlayScale();
|
|
|
|
UpdateAllViews();
|
|
|
|
SetModifiedFlag(true);
|
|
|
|
CheckPoint("Reset Cameras");
|
|
|
|
} 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];
|
|
|
|
|
|
|
|
m_ActiveView->MakeCurrent();
|
|
|
|
|
|
|
|
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_HasFramebufferObject() ? "supported" : "not supported";
|
|
|
|
|
|
|
|
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_ANIMATION:
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
|
|
|
m_bAnimation = !m_bAnimation;
|
|
|
|
|
|
|
|
CalculateStep();
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateFocusObject(GetFocusObject());
|
2011-09-07 23:06:51 +02:00
|
|
|
UpdateAllViews();
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateAnimation(m_bAnimation, m_bAddKeys);
|
2011-09-07 23:06:51 +02:00
|
|
|
if (m_bAnimation)
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateTime(m_bAnimation, m_nCurFrame, m_nTotalFrames);
|
2011-09-07 23:06:51 +02:00
|
|
|
else
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateTime(m_bAnimation, m_nCurStep, 255);
|
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_ADD_KEYS:
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
|
|
|
m_bAddKeys = !m_bAddKeys;
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateAnimation(m_bAnimation, m_bAddKeys);
|
2011-09-07 23:06:51 +02:00
|
|
|
} break;
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
case LC_EDIT_SNAP_X:
|
2011-09-07 23:06:51 +02:00
|
|
|
if (m_nSnap & LC_DRAW_SNAP_X)
|
|
|
|
m_nSnap &= ~LC_DRAW_SNAP_X;
|
|
|
|
else
|
|
|
|
m_nSnap |= LC_DRAW_SNAP_X;
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateLockSnap(m_nSnap);
|
2011-09-07 23:06:51 +02:00
|
|
|
break;
|
2013-08-09 06:57:18 +02:00
|
|
|
|
|
|
|
case LC_EDIT_SNAP_Y:
|
2011-09-07 23:06:51 +02:00
|
|
|
if (m_nSnap & LC_DRAW_SNAP_Y)
|
|
|
|
m_nSnap &= ~LC_DRAW_SNAP_Y;
|
|
|
|
else
|
|
|
|
m_nSnap |= LC_DRAW_SNAP_Y;
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateLockSnap(m_nSnap);
|
2011-09-07 23:06:51 +02:00
|
|
|
break;
|
2013-08-09 06:57:18 +02:00
|
|
|
|
|
|
|
case LC_EDIT_SNAP_Z:
|
2011-09-07 23:06:51 +02:00
|
|
|
if (m_nSnap & LC_DRAW_SNAP_Z)
|
|
|
|
m_nSnap &= ~LC_DRAW_SNAP_Z;
|
|
|
|
else
|
|
|
|
m_nSnap |= LC_DRAW_SNAP_Z;
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateLockSnap(m_nSnap);
|
2011-09-07 23:06:51 +02:00
|
|
|
break;
|
2013-08-09 06:57:18 +02:00
|
|
|
|
|
|
|
case LC_EDIT_SNAP_ALL:
|
2012-02-10 00:51:14 +01:00
|
|
|
m_nSnap |= LC_DRAW_SNAP_XYZ;
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateLockSnap(m_nSnap);
|
2011-09-07 23:06:51 +02:00
|
|
|
break;
|
2013-08-09 06:57:18 +02:00
|
|
|
|
|
|
|
case LC_EDIT_SNAP_NONE:
|
2011-09-07 23:06:51 +02:00
|
|
|
m_nSnap &= ~LC_DRAW_SNAP_XYZ;
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateLockSnap(m_nSnap);
|
2011-09-07 23:06:51 +02:00
|
|
|
break;
|
2013-08-09 06:57:18 +02:00
|
|
|
|
|
|
|
case LC_EDIT_SNAP_TOGGLE:
|
2012-02-10 00:51:14 +01:00
|
|
|
if ((m_nSnap & LC_DRAW_SNAP_XYZ) == LC_DRAW_SNAP_XYZ)
|
|
|
|
m_nSnap &= ~LC_DRAW_SNAP_XYZ;
|
|
|
|
else
|
|
|
|
m_nSnap |= LC_DRAW_SNAP_XYZ;
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateLockSnap(m_nSnap);
|
2012-02-10 00:51:14 +01:00
|
|
|
break;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
case LC_EDIT_LOCK_X:
|
2011-09-07 23:06:51 +02:00
|
|
|
if (m_nSnap & LC_DRAW_LOCK_X)
|
|
|
|
m_nSnap &= ~LC_DRAW_LOCK_X;
|
|
|
|
else
|
|
|
|
m_nSnap |= LC_DRAW_LOCK_X;
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateLockSnap(m_nSnap);
|
2011-09-07 23:06:51 +02:00
|
|
|
break;
|
2013-08-09 06:57:18 +02:00
|
|
|
|
|
|
|
case LC_EDIT_LOCK_Y:
|
2011-09-07 23:06:51 +02:00
|
|
|
if (m_nSnap & LC_DRAW_LOCK_Y)
|
|
|
|
m_nSnap &= ~LC_DRAW_LOCK_Y;
|
|
|
|
else
|
|
|
|
m_nSnap |= LC_DRAW_LOCK_Y;
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateLockSnap(m_nSnap);
|
2011-09-07 23:06:51 +02:00
|
|
|
break;
|
2013-08-09 06:57:18 +02:00
|
|
|
|
|
|
|
case LC_EDIT_LOCK_Z:
|
2011-09-07 23:06:51 +02:00
|
|
|
if (m_nSnap & LC_DRAW_LOCK_Z)
|
|
|
|
m_nSnap &= ~LC_DRAW_LOCK_Z;
|
|
|
|
else
|
|
|
|
m_nSnap |= LC_DRAW_LOCK_Z;
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateLockSnap(m_nSnap);
|
2011-09-07 23:06:51 +02:00
|
|
|
break;
|
2013-08-09 06:57:18 +02:00
|
|
|
|
|
|
|
case LC_EDIT_LOCK_NONE:
|
2011-09-07 23:06:51 +02:00
|
|
|
m_nSnap &= ~LC_DRAW_LOCK_XYZ;
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateLockSnap(m_nSnap);
|
2011-09-07 23:06:51 +02:00
|
|
|
break;
|
2013-08-09 06:57:18 +02:00
|
|
|
|
|
|
|
case LC_EDIT_LOCK_TOGGLE:
|
2012-02-10 00:51:14 +01:00
|
|
|
if ((m_nSnap & LC_DRAW_LOCK_XYZ) == LC_DRAW_LOCK_XYZ)
|
|
|
|
m_nSnap &= ~LC_DRAW_LOCK_XYZ;
|
|
|
|
else
|
|
|
|
m_nSnap |= LC_DRAW_LOCK_XYZ;
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateLockSnap(m_nSnap);
|
2012-02-10 00:51:14 +01:00
|
|
|
break;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +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:
|
|
|
|
{
|
|
|
|
m_nMoveSnap = (id - LC_EDIT_SNAP_MOVE_XY0) | (m_nMoveSnap & ~0xff);
|
|
|
|
if (id != LC_EDIT_SNAP_MOVE_XY0)
|
2012-02-10 00:51:14 +01:00
|
|
|
m_nSnap |= LC_DRAW_SNAP_X | LC_DRAW_SNAP_Y;
|
|
|
|
else
|
|
|
|
m_nSnap &= ~(LC_DRAW_SNAP_X | LC_DRAW_SNAP_Y);
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateSnap();
|
2011-09-07 23:06:51 +02:00
|
|
|
} break;
|
|
|
|
|
2013-08-09 06:57:18 +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:
|
|
|
|
{
|
|
|
|
m_nMoveSnap = (((id - LC_EDIT_SNAP_MOVE_Z0) << 8) | (m_nMoveSnap & ~0xff00));
|
|
|
|
if (id != LC_EDIT_SNAP_MOVE_Z0)
|
2012-02-10 00:51:14 +01:00
|
|
|
m_nSnap |= LC_DRAW_SNAP_Z;
|
|
|
|
else
|
|
|
|
m_nSnap &= ~LC_DRAW_SNAP_Z;
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateSnap();
|
2011-09-07 23:06:51 +02:00
|
|
|
} break;
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
case LC_EDIT_SNAP_ANGLE:
|
|
|
|
if (m_nSnap & LC_DRAW_SNAP_A)
|
|
|
|
m_nSnap &= ~LC_DRAW_SNAP_A;
|
|
|
|
else
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2012-02-10 00:51:14 +01:00
|
|
|
m_nSnap |= LC_DRAW_SNAP_A;
|
2013-08-09 06:57:18 +02:00
|
|
|
m_nAngleSnap = lcMax(1, m_nAngleSnap);
|
|
|
|
}
|
|
|
|
gMainWindow->UpdateSnap();
|
|
|
|
break;
|
|
|
|
|
|
|
|
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:
|
|
|
|
{
|
|
|
|
const int Angles[] = { 0, 1, 5, 10, 15, 30, 45, 60, 90, 180 };
|
|
|
|
|
|
|
|
if (id == LC_EDIT_SNAP_ANGLE0)
|
2012-02-10 00:51:14 +01:00
|
|
|
m_nSnap &= ~LC_DRAW_SNAP_A;
|
2013-08-09 06:57:18 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
m_nSnap |= LC_DRAW_SNAP_A;
|
|
|
|
m_nAngleSnap = Angles[id - LC_EDIT_SNAP_ANGLE0];
|
|
|
|
}
|
|
|
|
gMainWindow->UpdateSnap();
|
2011-09-07 23:06:51 +02:00
|
|
|
} break;
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
case LC_EDIT_TRANSFORM:
|
|
|
|
TransformSelectedObjects((LC_TRANSFORM_TYPE)mTransformType, gMainWindow->GetTransformAmount());
|
|
|
|
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:
|
|
|
|
mTransformType = id - LC_EDIT_TRANSFORM_ABSOLUTE_TRANSLATION;
|
|
|
|
gMainWindow->UpdateTransformType(mTransformType);
|
|
|
|
break;
|
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
case LC_EDIT_ACTION_SELECT:
|
|
|
|
{
|
|
|
|
SetAction(LC_ACTION_SELECT);
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_EDIT_ACTION_INSERT:
|
|
|
|
{
|
|
|
|
SetAction(LC_ACTION_INSERT);
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_EDIT_ACTION_LIGHT:
|
|
|
|
{
|
|
|
|
SetAction(LC_ACTION_LIGHT);
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_EDIT_ACTION_SPOTLIGHT:
|
|
|
|
{
|
|
|
|
SetAction(LC_ACTION_SPOTLIGHT);
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_EDIT_ACTION_CAMERA:
|
|
|
|
{
|
|
|
|
SetAction(LC_ACTION_CAMERA);
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_EDIT_ACTION_MOVE:
|
|
|
|
{
|
|
|
|
SetAction(LC_ACTION_MOVE);
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_EDIT_ACTION_ROTATE:
|
|
|
|
{
|
|
|
|
SetAction(LC_ACTION_ROTATE);
|
|
|
|
} break;
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
case LC_EDIT_ACTION_DELETE:
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
|
|
|
SetAction(LC_ACTION_ERASER);
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_EDIT_ACTION_PAINT:
|
|
|
|
{
|
|
|
|
SetAction(LC_ACTION_PAINT);
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_EDIT_ACTION_ZOOM:
|
|
|
|
{
|
|
|
|
SetAction(LC_ACTION_ZOOM);
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_EDIT_ACTION_ZOOM_REGION:
|
|
|
|
{
|
|
|
|
SetAction(LC_ACTION_ZOOM_REGION);
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_EDIT_ACTION_PAN:
|
|
|
|
{
|
|
|
|
SetAction(LC_ACTION_PAN);
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_EDIT_ACTION_ROTATE_VIEW:
|
|
|
|
{
|
|
|
|
SetAction(LC_ACTION_ROTATE_VIEW);
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_EDIT_ACTION_ROLL:
|
|
|
|
{
|
|
|
|
SetAction(LC_ACTION_ROLL);
|
|
|
|
} break;
|
2013-08-09 06:57:18 +02:00
|
|
|
|
|
|
|
case LC_EDIT_CANCEL:
|
|
|
|
{
|
|
|
|
if (m_nTracking != LC_TRACK_NONE)
|
|
|
|
StopTracking(false);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SelectAndFocusNone(false);
|
|
|
|
UpdateSelection();
|
|
|
|
UpdateAllViews();
|
|
|
|
gMainWindow->UpdateFocusObject(NULL);
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_NUM_COMMANDS:
|
|
|
|
break;
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Project::SetAction(int nAction)
|
|
|
|
{
|
|
|
|
m_nCurAction = nAction;
|
2013-08-09 06:57:18 +02:00
|
|
|
|
|
|
|
gMainWindow->UpdateAction(m_nCurAction);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-07-31 07:27:40 +02:00
|
|
|
ActivateOverlay(m_ActiveView, m_nCurAction, LC_OVERLAY_NONE);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-07-31 07:27:40 +02:00
|
|
|
UpdateAllViews();
|
|
|
|
}
|
|
|
|
|
|
|
|
int Project::GetAction() const
|
|
|
|
{
|
|
|
|
int Action = m_nCurAction;
|
|
|
|
|
|
|
|
if (m_OverlayActive)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2012-07-31 07:27:40 +02:00
|
|
|
switch (m_OverlayMode)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2012-07-31 07:27:40 +02:00
|
|
|
case LC_OVERLAY_NONE:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LC_OVERLAY_MOVE_X:
|
|
|
|
case LC_OVERLAY_MOVE_Y:
|
|
|
|
case LC_OVERLAY_MOVE_Z:
|
|
|
|
case LC_OVERLAY_MOVE_XY:
|
|
|
|
case LC_OVERLAY_MOVE_XZ:
|
|
|
|
case LC_OVERLAY_MOVE_YZ:
|
|
|
|
case LC_OVERLAY_MOVE_XYZ:
|
|
|
|
Action = LC_ACTION_MOVE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LC_OVERLAY_ROTATE_X:
|
|
|
|
case LC_OVERLAY_ROTATE_Y:
|
|
|
|
case LC_OVERLAY_ROTATE_Z:
|
|
|
|
case LC_OVERLAY_ROTATE_XY:
|
|
|
|
case LC_OVERLAY_ROTATE_XZ:
|
|
|
|
case LC_OVERLAY_ROTATE_YZ:
|
|
|
|
case LC_OVERLAY_ROTATE_XYZ:
|
|
|
|
Action = LC_ACTION_ROTATE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LC_OVERLAY_ZOOM:
|
|
|
|
Action = LC_ACTION_ZOOM;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LC_OVERLAY_PAN:
|
|
|
|
Action = LC_ACTION_PAN;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LC_OVERLAY_ROTATE_VIEW_X:
|
|
|
|
case LC_OVERLAY_ROTATE_VIEW_Y:
|
|
|
|
case LC_OVERLAY_ROTATE_VIEW_Z:
|
|
|
|
case LC_OVERLAY_ROTATE_VIEW_XYZ:
|
|
|
|
Action = LC_ACTION_ROTATE_VIEW;
|
|
|
|
break;
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-31 07:27:40 +02:00
|
|
|
return Action;
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Remove unused groups
|
|
|
|
void Project::RemoveEmptyGroups()
|
|
|
|
{
|
|
|
|
bool recurse = false;
|
|
|
|
Group *g1, *g2;
|
|
|
|
Piece* pPiece;
|
|
|
|
int ref;
|
|
|
|
|
|
|
|
for (g1 = m_pGroups; g1;)
|
|
|
|
{
|
|
|
|
ref = 0;
|
|
|
|
|
|
|
|
for (pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
|
|
|
if (pPiece->GetGroup() == g1)
|
|
|
|
ref++;
|
|
|
|
|
|
|
|
for (g2 = m_pGroups; g2; g2 = g2->m_pNext)
|
|
|
|
if (g2->m_pGroup == g1)
|
|
|
|
ref++;
|
|
|
|
|
|
|
|
if (ref < 2)
|
|
|
|
{
|
|
|
|
if (ref != 0)
|
|
|
|
{
|
|
|
|
for (pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
|
|
|
if (pPiece->GetGroup() == g1)
|
|
|
|
pPiece->SetGroup(g1->m_pGroup);
|
|
|
|
|
|
|
|
for (g2 = m_pGroups; g2; g2 = g2->m_pNext)
|
|
|
|
if (g2->m_pGroup == g1)
|
|
|
|
g2->m_pGroup = g1->m_pGroup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (g1 == m_pGroups)
|
|
|
|
{
|
|
|
|
m_pGroups = g1->m_pNext;
|
|
|
|
delete g1;
|
|
|
|
g1 = m_pGroups;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (g2 = m_pGroups; g2; g2 = g2->m_pNext)
|
|
|
|
if (g2->m_pNext == g1)
|
|
|
|
{
|
|
|
|
g2->m_pNext = g1->m_pNext;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
delete g1;
|
|
|
|
g1 = g2->m_pNext;
|
|
|
|
}
|
|
|
|
|
|
|
|
recurse = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
g1 = g1->m_pNext;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (recurse)
|
|
|
|
RemoveEmptyGroups();
|
|
|
|
}
|
|
|
|
|
|
|
|
Group* Project::AddGroup (const char* name, Group* pParent, float x, float y, float z)
|
|
|
|
{
|
|
|
|
Group *pNewGroup = new Group();
|
|
|
|
|
|
|
|
if (name == NULL)
|
|
|
|
{
|
|
|
|
int i, max = 0;
|
|
|
|
char str[65];
|
|
|
|
|
|
|
|
for (Group *pGroup = m_pGroups; pGroup; pGroup = pGroup->m_pNext)
|
|
|
|
if (strncmp (pGroup->m_strName, "Group #", 7) == 0)
|
|
|
|
if (sscanf(pGroup->m_strName, "Group #%d", &i) == 1)
|
|
|
|
if (i > max)
|
|
|
|
max = i;
|
|
|
|
sprintf (str, "Group #%.2d", max+1);
|
|
|
|
|
|
|
|
strcpy (pNewGroup->m_strName, str);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
strcpy (pNewGroup->m_strName, name);
|
|
|
|
|
|
|
|
pNewGroup->m_pNext = m_pGroups;
|
|
|
|
m_pGroups = pNewGroup;
|
|
|
|
|
|
|
|
pNewGroup->m_fCenter[0] = x;
|
|
|
|
pNewGroup->m_fCenter[1] = y;
|
|
|
|
pNewGroup->m_fCenter[2] = z;
|
|
|
|
pNewGroup->m_pGroup = pParent;
|
|
|
|
|
|
|
|
return pNewGroup;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Project::SelectAndFocusNone(bool bFocusOnly)
|
|
|
|
{
|
2012-08-22 03:13:32 +02:00
|
|
|
Piece* pPiece;
|
|
|
|
Light* pLight;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-08-22 03:13:32 +02:00
|
|
|
for (pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
|
|
|
pPiece->Select(false, bFocusOnly, 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++)
|
|
|
|
{
|
|
|
|
Camera* pCamera = mCameras[CameraIdx];
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-08-22 03:13:32 +02:00
|
|
|
pCamera->Select (false, bFocusOnly, false);
|
|
|
|
pCamera->GetTarget()->Select (false, bFocusOnly, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (pLight = m_pLights; pLight; pLight = pLight->m_pNext)
|
|
|
|
{
|
|
|
|
pLight->Select(false, bFocusOnly, false);
|
|
|
|
if (pLight->GetTarget())
|
|
|
|
pLight->GetTarget()->Select (false, bFocusOnly, false);
|
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
// AfxGetMainWnd()->PostMessage(WM_LC_UPDATE_INFO, NULL, OT_PIECE);
|
|
|
|
}
|
|
|
|
|
2012-05-29 01:33:22 +02:00
|
|
|
bool Project::GetSelectionCenter(lcVector3& Center) const
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
|
|
|
float bs[6] = { 10000, 10000, 10000, -10000, -10000, -10000 };
|
|
|
|
bool Selected = false;
|
|
|
|
|
|
|
|
for (Piece* pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
|
|
|
{
|
|
|
|
if (pPiece->IsSelected())
|
|
|
|
{
|
|
|
|
pPiece->CompareBoundingBox(bs);
|
|
|
|
Selected = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-05-29 01:33:22 +02:00
|
|
|
Center = lcVector3((bs[0] + bs[3]) * 0.5f, (bs[1] + bs[4]) * 0.5f, (bs[2] + bs[5]) * 0.5f);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
return Selected;
|
|
|
|
}
|
|
|
|
|
2012-05-29 01:33:22 +02:00
|
|
|
void Project::ConvertToUserUnits(lcVector3& Value) const
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
|
|
|
if ((m_nSnap & LC_DRAW_CM_UNITS) == 0)
|
2012-02-23 20:19:08 +01:00
|
|
|
Value /= 0.04f;
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
2012-05-29 01:33:22 +02:00
|
|
|
void Project::ConvertFromUserUnits(lcVector3& Value) const
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
|
|
|
if ((m_nSnap & LC_DRAW_CM_UNITS) == 0)
|
2012-02-23 20:19:08 +01:00
|
|
|
Value *= 0.04f;
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
2012-05-29 01:33:22 +02:00
|
|
|
bool Project::GetFocusPosition(lcVector3& Position) const
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
|
|
|
Piece* pPiece;
|
|
|
|
|
|
|
|
for (pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
|
|
|
if (pPiece->IsFocused())
|
|
|
|
{
|
2012-05-29 01:33:22 +02:00
|
|
|
Position = pPiece->mPosition;
|
2011-09-07 23:06:51 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-08-22 03:13:32 +02:00
|
|
|
for (int CameraIdx = 0; CameraIdx < mCameras.GetSize(); CameraIdx++)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2012-08-22 03:13:32 +02:00
|
|
|
Camera* pCamera = mCameras[CameraIdx];
|
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
if (pCamera->IsEyeFocused())
|
|
|
|
{
|
2012-05-29 01:33:22 +02:00
|
|
|
Position = pCamera->mPosition;
|
2011-09-07 23:06:51 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pCamera->IsTargetFocused())
|
|
|
|
{
|
2012-05-29 01:33:22 +02:00
|
|
|
Position = pCamera->mTargetPosition;
|
2011-09-07 23:06:51 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: light
|
|
|
|
|
2012-05-29 01:33:22 +02:00
|
|
|
Position = lcVector3(0.0f, 0.0f, 0.0f);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Returns the object that currently has focus.
|
|
|
|
Object* Project::GetFocusObject() const
|
|
|
|
{
|
|
|
|
for (Piece* pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
|
|
|
{
|
|
|
|
if (pPiece->IsFocused())
|
|
|
|
return pPiece;
|
|
|
|
}
|
|
|
|
|
2012-08-22 03:13:32 +02:00
|
|
|
for (int CameraIdx = 0; CameraIdx < mCameras.GetSize(); CameraIdx++)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2012-08-22 03:13:32 +02:00
|
|
|
Camera* pCamera = mCameras[CameraIdx];
|
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
if (pCamera->IsEyeFocused() || pCamera->IsTargetFocused())
|
|
|
|
return pCamera;
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: light
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Find a good starting position/orientation relative to an existing piece.
|
2012-06-16 02:17:52 +02:00
|
|
|
void Project::GetPieceInsertPosition(Piece* OffsetPiece, lcVector3& Position, lcVector4& Rotation)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2012-06-16 02:17:52 +02:00
|
|
|
lcVector3 Dist(0, 0, OffsetPiece->mPieceInfo->m_fDimensions[2] - m_pCurPiece->m_fDimensions[5]);
|
2011-09-07 23:06:51 +02:00
|
|
|
SnapVector(Dist);
|
|
|
|
|
2012-10-18 20:57:21 +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.
|
2012-06-16 02:17:52 +02:00
|
|
|
void Project::GetPieceInsertPosition(View* view, int MouseX, int MouseY, lcVector3& Position, lcVector4& Rotation)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2012-01-30 08:31:29 +01:00
|
|
|
// Check if the mouse is over a piece.
|
|
|
|
Piece* HitPiece = (Piece*)FindObjectFromPoint(view, MouseX, MouseY, true);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
if (HitPiece)
|
|
|
|
{
|
|
|
|
GetPieceInsertPosition(HitPiece, Position, Rotation);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Try to hit the base grid.
|
2013-08-09 06:57:18 +02:00
|
|
|
int Viewport[4] = { 0, 0, view->mWidth, view->mHeight };
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
float Aspect = (float)Viewport[2]/(float)Viewport[3];
|
2012-08-20 06:05:56 +02:00
|
|
|
Camera* Cam = view->mCamera;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-05-29 01:33:22 +02:00
|
|
|
const lcMatrix44& ModelView = Cam->mWorldView;
|
|
|
|
lcMatrix44 Projection = lcMatrix44Perspective(Cam->m_fovy, Aspect, Cam->m_zNear, Cam->m_zFar);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-05-29 01:33:22 +02:00
|
|
|
lcVector3 ClickPoints[2] = { lcVector3((float)m_nDownX, (float)m_nDownY, 0.0f), lcVector3((float)m_nDownX, (float)m_nDownY, 1.0f) };
|
|
|
|
lcUnprojectPoints(ClickPoints, 2, ModelView, Projection, Viewport);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-06-16 02:17:52 +02:00
|
|
|
lcVector3 Intersection;
|
2012-07-12 06:18:10 +02:00
|
|
|
if (lcLinePlaneIntersection(&Intersection, ClickPoints[0], ClickPoints[1], lcVector4(0, 0, 1, 0)))
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
|
|
|
SnapVector(Intersection);
|
|
|
|
Position = Intersection;
|
2012-06-16 02:17:52 +02:00
|
|
|
Rotation = lcVector4(0, 0, 1, 0);
|
2011-09-07 23:06:51 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Couldn't find a good position, so just place the piece somewhere near the camera.
|
2012-06-16 02:17:52 +02:00
|
|
|
Position = lcUnprojectPoint(lcVector3((float)m_nDownX, (float)m_nDownY, 0.9f), ModelView, Projection, Viewport);
|
|
|
|
Rotation = lcVector4(0, 0, 1, 0);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
2012-01-30 08:31:29 +01:00
|
|
|
Object* Project::FindObjectFromPoint(View* view, int x, int y, bool PiecesOnly)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
int Viewport[4] = { 0, 0, view->mWidth, view->mHeight };
|
2012-01-30 08:31:29 +01:00
|
|
|
float Aspect = (float)Viewport[2]/(float)Viewport[3];
|
2012-08-20 06:05:56 +02:00
|
|
|
Camera* Cam = view->mCamera;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-05-29 01:33:22 +02:00
|
|
|
const lcMatrix44& ModelView = Cam->mWorldView;
|
|
|
|
lcMatrix44 Projection = lcMatrix44Perspective(Cam->m_fovy, Aspect, Cam->m_zNear, Cam->m_zFar);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-05-29 01:33:22 +02:00
|
|
|
lcVector3 Start = lcUnprojectPoint(lcVector3((float)x, (float)y, 0.0f), ModelView, Projection, Viewport);
|
|
|
|
lcVector3 End = lcUnprojectPoint(lcVector3((float)x, (float)y, 1.0f), ModelView, Projection, Viewport);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-08-17 01:50:40 +02:00
|
|
|
lcClickLine ClickLine;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-08-17 01:50:40 +02:00
|
|
|
ClickLine.Start = Start;
|
|
|
|
ClickLine.End = End;
|
|
|
|
ClickLine.MinDist = FLT_MAX;
|
|
|
|
ClickLine.Closest = NULL;
|
2012-01-30 08:31:29 +01:00
|
|
|
|
|
|
|
for (Piece* pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
2011-09-07 23:06:51 +02:00
|
|
|
if (pPiece->IsVisible(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation))
|
2012-01-30 08:31:29 +01:00
|
|
|
pPiece->MinIntersectDist(&ClickLine);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
if (!PiecesOnly)
|
|
|
|
{
|
2012-08-22 03:13:32 +02:00
|
|
|
for (int CameraIdx = 0; CameraIdx < mCameras.GetSize(); CameraIdx++)
|
|
|
|
{
|
|
|
|
Camera* pCamera = mCameras[CameraIdx];
|
|
|
|
|
2012-08-20 06:05:56 +02:00
|
|
|
if (pCamera != view->mCamera && pCamera->IsVisible())
|
2012-01-30 08:31:29 +01:00
|
|
|
pCamera->MinIntersectDist(&ClickLine);
|
2012-08-22 03:13:32 +02:00
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-01-30 08:31:29 +01:00
|
|
|
for (Light* pLight = m_pLights; pLight; pLight = pLight->m_pNext)
|
2012-08-17 01:50:40 +02:00
|
|
|
if (pLight->IsVisible())
|
|
|
|
pLight->MinIntersectDist(&ClickLine);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
2012-01-30 08:31:29 +01:00
|
|
|
|
2012-08-17 01:50:40 +02:00
|
|
|
return ClickLine.Closest;
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
2013-08-16 01:43:18 +02:00
|
|
|
void Project::FindObjectsInBox(float x1, float y1, float x2, float y2, lcArray<Object*>& Objects)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
int Viewport[4] = { 0, 0, m_ActiveView->mWidth, m_ActiveView->mHeight };
|
2011-09-07 23:06:51 +02:00
|
|
|
float Aspect = (float)Viewport[2]/(float)Viewport[3];
|
2012-08-20 06:05:56 +02:00
|
|
|
Camera* Cam = m_ActiveView->mCamera;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-05-29 01:33:22 +02:00
|
|
|
const lcMatrix44& ModelView = Cam->mWorldView;
|
|
|
|
lcMatrix44 Projection = lcMatrix44Perspective(Cam->m_fovy, Aspect, Cam->m_zNear, Cam->m_zFar);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
// Find out the top-left and bottom-right corners in screen coordinates.
|
|
|
|
float Left, Top, Bottom, Right;
|
|
|
|
|
|
|
|
if (x1 < x2)
|
|
|
|
{
|
|
|
|
Left = x1;
|
|
|
|
Right = x2;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Left = x2;
|
|
|
|
Right = x1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (y1 > y2)
|
|
|
|
{
|
|
|
|
Top = y1;
|
|
|
|
Bottom = y2;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Top = y2;
|
|
|
|
Bottom = y1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Unproject 6 points to world space.
|
2012-05-29 01:33:22 +02:00
|
|
|
lcVector3 Corners[6] =
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2012-05-29 01:33:22 +02:00
|
|
|
lcVector3(Left, Top, 0), lcVector3(Left, Bottom, 0), lcVector3(Right, Bottom, 0),
|
|
|
|
lcVector3(Right, Top, 0), lcVector3(Left, Top, 1), lcVector3(Right, Bottom, 1)
|
2011-09-07 23:06:51 +02:00
|
|
|
};
|
|
|
|
|
2012-05-29 01:33:22 +02:00
|
|
|
lcUnprojectPoints(Corners, 6, ModelView, Projection, Viewport);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
// Build the box planes.
|
2012-05-29 01:33:22 +02:00
|
|
|
lcVector3 PlaneNormals[6];
|
|
|
|
|
|
|
|
PlaneNormals[0] = lcNormalize(lcCross(Corners[4] - Corners[0], Corners[1] - Corners[0])); // Left
|
|
|
|
PlaneNormals[1] = lcNormalize(lcCross(Corners[5] - Corners[2], Corners[3] - Corners[2])); // Right
|
|
|
|
PlaneNormals[2] = lcNormalize(lcCross(Corners[3] - Corners[0], Corners[4] - Corners[0])); // Top
|
|
|
|
PlaneNormals[3] = lcNormalize(lcCross(Corners[1] - Corners[2], Corners[5] - Corners[2])); // Bottom
|
|
|
|
PlaneNormals[4] = lcNormalize(lcCross(Corners[1] - Corners[0], Corners[3] - Corners[0])); // Front
|
|
|
|
PlaneNormals[5] = lcNormalize(lcCross(Corners[1] - Corners[2], Corners[3] - Corners[2])); // Back
|
|
|
|
|
|
|
|
lcVector4 Planes[6];
|
|
|
|
Planes[0] = lcVector4(PlaneNormals[0], -lcDot(PlaneNormals[0], Corners[0]));
|
|
|
|
Planes[1] = lcVector4(PlaneNormals[1], -lcDot(PlaneNormals[1], Corners[5]));
|
|
|
|
Planes[2] = lcVector4(PlaneNormals[2], -lcDot(PlaneNormals[2], Corners[0]));
|
|
|
|
Planes[3] = lcVector4(PlaneNormals[3], -lcDot(PlaneNormals[3], Corners[5]));
|
|
|
|
Planes[4] = lcVector4(PlaneNormals[4], -lcDot(PlaneNormals[4], Corners[0]));
|
|
|
|
Planes[5] = lcVector4(PlaneNormals[5], -lcDot(PlaneNormals[5], Corners[5]));
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
// Check if any objects are inside the volume.
|
|
|
|
for (Piece* piece = m_pPieces; piece != NULL; piece = piece->m_pNext)
|
|
|
|
{
|
|
|
|
if (piece->IsVisible(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation))
|
|
|
|
{
|
2012-07-04 00:56:05 +02:00
|
|
|
if (piece->IntersectsVolume(Planes))
|
2011-09-07 23:06:51 +02:00
|
|
|
Objects.Add(piece);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-23 20:47:37 +02:00
|
|
|
for (int CameraIdx = 0; CameraIdx < mCameras.GetSize(); CameraIdx++)
|
|
|
|
{
|
|
|
|
Camera* pCamera = mCameras[CameraIdx];
|
|
|
|
|
|
|
|
if (!pCamera->IsVisible() || pCamera == Cam)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (pCamera->IntersectsVolume(Planes))
|
|
|
|
Objects.Add(pCamera);
|
|
|
|
|
|
|
|
if (pCamera->GetTarget()->IntersectsVolume(Planes))
|
|
|
|
Objects.Add(pCamera->GetTarget());
|
|
|
|
}
|
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
// TODO: lights and cameras.
|
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Mouse handling
|
|
|
|
|
|
|
|
// Returns true if the mouse was being tracked.
|
|
|
|
bool Project::StopTracking(bool bAccept)
|
|
|
|
{
|
|
|
|
if (m_nTracking == LC_TRACK_NONE)
|
|
|
|
return false;
|
|
|
|
|
2012-07-31 07:27:40 +02:00
|
|
|
int Action = GetAction();
|
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
if ((m_nTracking == LC_TRACK_START_LEFT) || (m_nTracking == LC_TRACK_START_RIGHT))
|
|
|
|
{
|
|
|
|
if (m_pTrackFile)
|
|
|
|
{
|
|
|
|
delete m_pTrackFile;
|
|
|
|
m_pTrackFile = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_nTracking = LC_TRACK_NONE;
|
2013-08-09 06:57:18 +02:00
|
|
|
m_ActiveView->ReleaseMouse();
|
2011-09-07 23:06:51 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_bTrackCancel = true;
|
|
|
|
m_nTracking = LC_TRACK_NONE;
|
2013-08-09 06:57:18 +02:00
|
|
|
m_ActiveView->ReleaseMouse();
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
// Reset the mouse overlay.
|
|
|
|
if (m_OverlayActive)
|
|
|
|
{
|
2012-07-31 07:27:40 +02:00
|
|
|
ActivateOverlay(m_ActiveView, m_nCurAction, LC_OVERLAY_NONE);
|
2011-09-07 23:06:51 +02:00
|
|
|
UpdateAllViews();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bAccept)
|
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
if (mDropPiece)
|
|
|
|
{
|
|
|
|
int x = m_nDownX;
|
|
|
|
int y = m_nDownY;
|
|
|
|
|
|
|
|
if ((x > 0) && (x < m_ActiveView->mWidth) && (y > 0) && (y < m_ActiveView->mHeight))
|
|
|
|
{
|
|
|
|
lcVector3 Pos;
|
|
|
|
lcVector4 Rot;
|
|
|
|
|
|
|
|
GetPieceInsertPosition(m_ActiveView, x, y, Pos, Rot);
|
|
|
|
|
|
|
|
Piece* pPiece = new Piece(mDropPiece);
|
|
|
|
pPiece->Initialize(Pos[0], Pos[1], Pos[2], m_nCurStep, m_nCurFrame);
|
|
|
|
pPiece->SetColorIndex(gMainWindow->mColorIndex);
|
|
|
|
|
|
|
|
pPiece->ChangeKey(m_nCurStep, false, false, Rot, LC_PK_ROTATION);
|
|
|
|
pPiece->ChangeKey(m_nCurFrame, true, false, Rot, LC_PK_ROTATION);
|
|
|
|
pPiece->UpdatePosition(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation);
|
|
|
|
|
|
|
|
SelectAndFocusNone(false);
|
|
|
|
pPiece->CreateName(m_pPieces);
|
|
|
|
AddPiece(pPiece);
|
|
|
|
SystemPieceComboAdd(mDropPiece->m_strDescription);
|
|
|
|
pPiece->Select (true, true, false);
|
|
|
|
|
|
|
|
if (mDropPiece)
|
|
|
|
{
|
|
|
|
mDropPiece->Release();
|
|
|
|
mDropPiece = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
UpdateSelection();
|
|
|
|
UpdateAllViews();
|
|
|
|
gMainWindow->UpdateFocusObject(pPiece);
|
|
|
|
|
|
|
|
SetModifiedFlag(true);
|
|
|
|
CheckPoint("Inserting");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-07-31 07:27:40 +02:00
|
|
|
switch (Action)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
|
|
|
case LC_ACTION_SELECT:
|
|
|
|
{
|
|
|
|
if (((float)m_nDownX != m_fTrack[0]) && ((float)m_nDownY != m_fTrack[1]))
|
|
|
|
{
|
|
|
|
// Find objects inside the rectangle.
|
2013-08-16 01:43:18 +02:00
|
|
|
lcArray<Object*> Objects;
|
2011-09-07 23:06:51 +02:00
|
|
|
FindObjectsInBox((float)m_nDownX, (float)m_nDownY, m_fTrack[0], m_fTrack[1], Objects);
|
|
|
|
|
|
|
|
// Deselect old pieces.
|
2013-08-09 06:57:18 +02:00
|
|
|
bool Control = m_ActiveView->mInputState.Control;
|
2011-09-07 23:06:51 +02:00
|
|
|
SelectAndFocusNone(Control);
|
|
|
|
|
|
|
|
// Select new pieces.
|
|
|
|
for (int i = 0; i < Objects.GetSize(); i++)
|
|
|
|
{
|
|
|
|
if (Objects[i]->GetType() == LC_OBJECT_PIECE)
|
|
|
|
{
|
|
|
|
Group* pGroup = ((Piece*)Objects[i])->GetTopGroup();
|
|
|
|
if (pGroup != NULL)
|
|
|
|
{
|
|
|
|
for (Piece* pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
|
|
|
if ((pPiece->IsVisible(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation)) &&
|
|
|
|
(pPiece->GetTopGroup() == pGroup))
|
|
|
|
pPiece->Select (true, false, false);
|
|
|
|
}
|
|
|
|
else
|
2012-08-23 20:47:37 +02:00
|
|
|
Objects[i]->Select(true, false, true);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
else
|
2012-08-23 20:47:37 +02:00
|
|
|
Objects[i]->Select(true, false, true);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update screen and UI.
|
|
|
|
UpdateSelection();
|
|
|
|
UpdateAllViews();
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateFocusObject(GetFocusObject());
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_ACTION_MOVE:
|
|
|
|
{
|
|
|
|
SetModifiedFlag(true);
|
|
|
|
CheckPoint("Moving");
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_ACTION_ROTATE:
|
|
|
|
{
|
|
|
|
SetModifiedFlag(true);
|
|
|
|
CheckPoint("Rotating");
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_ACTION_CAMERA:
|
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateCameraMenu(mCameras, m_ActiveView ? m_ActiveView->mCamera : NULL);
|
2011-09-07 23:06:51 +02:00
|
|
|
SetModifiedFlag(true);
|
|
|
|
CheckPoint("Inserting");
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_ACTION_SPOTLIGHT:
|
|
|
|
{
|
|
|
|
SetModifiedFlag(true);
|
|
|
|
CheckPoint("Inserting");
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_ACTION_ZOOM:
|
|
|
|
case LC_ACTION_PAN:
|
|
|
|
case LC_ACTION_ROTATE_VIEW:
|
|
|
|
case LC_ACTION_ROLL:
|
|
|
|
{
|
|
|
|
// For some reason the scene doesn't get redrawn when changing a camera but it does
|
|
|
|
// when moving things around, so manually get the full scene rendered again.
|
|
|
|
if (m_nDetail & LC_DET_FAST)
|
|
|
|
UpdateAllViews();
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_ACTION_ZOOM_REGION:
|
|
|
|
{
|
2013-04-10 02:52:06 +02:00
|
|
|
// Find the top-left and bottom-right corners in screen coordinates.
|
2011-09-07 23:06:51 +02:00
|
|
|
float Left, Top, Bottom, Right;
|
|
|
|
|
|
|
|
if (m_OverlayTrackStart[0] < m_nDownX)
|
|
|
|
{
|
|
|
|
Left = m_OverlayTrackStart[0];
|
|
|
|
Right = (float)m_nDownX;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Left = (float)m_nDownX;
|
|
|
|
Right = m_OverlayTrackStart[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_OverlayTrackStart[1] > m_nDownY)
|
|
|
|
{
|
|
|
|
Top = m_OverlayTrackStart[1];
|
|
|
|
Bottom = (float)m_nDownY;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Top = (float)m_nDownY;
|
|
|
|
Bottom = m_OverlayTrackStart[1];
|
|
|
|
}
|
|
|
|
|
2013-04-10 02:52:06 +02:00
|
|
|
m_ActiveView->mCamera->ZoomRegion(m_ActiveView, Left, Right, Bottom, Top, m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation, m_bAddKeys);
|
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
|
|
|
UpdateAllViews();
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_ACTION_INSERT:
|
|
|
|
case LC_ACTION_LIGHT:
|
|
|
|
case LC_ACTION_ERASER:
|
|
|
|
case LC_ACTION_PAINT:
|
|
|
|
break;
|
|
|
|
}
|
2012-01-28 03:10:19 +01:00
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
else if (m_pTrackFile != NULL)
|
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
if ((Action == LC_ACTION_SELECT) || (Action == LC_ACTION_ZOOM_REGION))
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
|
|
|
UpdateAllViews();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DeleteContents (true);
|
|
|
|
FileLoad (m_pTrackFile, true, false);
|
|
|
|
delete m_pTrackFile;
|
|
|
|
m_pTrackFile = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
if (mDropPiece)
|
|
|
|
{
|
|
|
|
mDropPiece->Release();
|
|
|
|
mDropPiece = NULL;
|
|
|
|
}
|
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Project::StartTracking(int mode)
|
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
m_ActiveView->CaptureMouse();
|
2011-09-07 23:06:51 +02:00
|
|
|
m_nTracking = mode;
|
|
|
|
|
|
|
|
if (m_pTrackFile != NULL)
|
|
|
|
m_pTrackFile->SetLength (0);
|
|
|
|
else
|
2012-03-23 00:44:56 +01:00
|
|
|
m_pTrackFile = new lcMemFile;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
FileSave(m_pTrackFile, true);
|
|
|
|
}
|
|
|
|
|
2012-02-10 00:51:14 +01:00
|
|
|
void Project::GetSnapIndex(int* SnapXY, int* SnapZ, int* SnapAngle) const
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2012-02-10 00:51:14 +01:00
|
|
|
if (SnapXY)
|
|
|
|
*SnapXY = (m_nMoveSnap & 0xff);
|
|
|
|
|
|
|
|
if (SnapZ)
|
|
|
|
*SnapZ = ((m_nMoveSnap >> 8) & 0xff);
|
|
|
|
|
|
|
|
if (SnapAngle)
|
|
|
|
{
|
|
|
|
if (m_nSnap & LC_DRAW_SNAP_A)
|
|
|
|
{
|
|
|
|
int Angles[] = { 0, 1, 5, 10, 15, 30, 45, 60, 90, 180 };
|
|
|
|
*SnapAngle = -1;
|
|
|
|
|
2012-06-22 00:03:30 +02:00
|
|
|
for (unsigned int i = 0; i < sizeof(Angles)/sizeof(Angles[0]); i++)
|
2012-02-10 00:51:14 +01:00
|
|
|
{
|
|
|
|
if (m_nAngleSnap == Angles[i])
|
|
|
|
{
|
|
|
|
*SnapAngle = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2013-08-09 06:57:18 +02:00
|
|
|
*SnapAngle = 0;
|
2012-02-10 00:51:14 +01:00
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Project::GetSnapDistance(float* SnapXY, float* SnapZ) const
|
|
|
|
{
|
|
|
|
const float SnapXYTable[] = { 0.01f, 0.04f, 0.2f, 0.32f, 0.4f, 0.8f, 1.6f, 2.4f, 3.2f, 6.4f };
|
|
|
|
const float SnapZTable[] = { 0.01f, 0.04f, 0.2f, 0.32f, 0.4f, 0.8f, 0.96f, 1.92f, 3.84f, 7.68f };
|
|
|
|
|
|
|
|
int SXY, SZ;
|
2012-02-10 00:51:14 +01:00
|
|
|
GetSnapIndex(&SXY, &SZ, NULL);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-07-06 03:18:55 +02:00
|
|
|
SXY = lcMin(SXY, 9);
|
|
|
|
SZ = lcMin(SZ, 9);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
*SnapXY = SnapXYTable[SXY];
|
|
|
|
*SnapZ = SnapZTable[SZ];
|
|
|
|
}
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
void Project::GetSnapText(char* SnapXY, char* SnapZ, char* SnapAngle) const
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
|
|
|
if (m_nSnap & LC_DRAW_CM_UNITS)
|
|
|
|
{
|
|
|
|
float xy, z;
|
|
|
|
|
|
|
|
GetSnapDistance(&xy, &z);
|
|
|
|
|
|
|
|
sprintf(SnapXY, "%.2f", xy);
|
|
|
|
sprintf(SnapZ, "%.2f", z);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
const char* SnapXYText[] = { "0", "1/20S", "1/4S", "1F", "1/2S", "1S", "2S", "3S", "4S", "8S" };
|
|
|
|
const char* SnapZText[] = { "0", "1/20S", "1/4S", "1F", "1/2S", "1S", "1B", "2B", "4B", "8B" };
|
2013-08-09 06:57:18 +02:00
|
|
|
const char* SnapAngleText[] = { "0", "1", "5", "10", "15", "30", "45", "60", "90", "180" };
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
int SXY, SZ, SA;
|
|
|
|
GetSnapIndex(&SXY, &SZ, &SA);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-07-06 03:18:55 +02:00
|
|
|
SXY = lcMin(SXY, 9);
|
|
|
|
SZ = lcMin(SZ, 9);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
strcpy(SnapXY, SnapXYText[SXY]);
|
|
|
|
strcpy(SnapZ, SnapZText[SZ]);
|
2013-08-09 06:57:18 +02:00
|
|
|
strcpy(SnapAngle, SnapAngleText[SA]);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-06-16 02:17:52 +02:00
|
|
|
void Project::SnapVector(lcVector3& Delta, lcVector3& Leftover) const
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
|
|
|
float SnapXY, SnapZ;
|
|
|
|
GetSnapDistance(&SnapXY, &SnapZ);
|
|
|
|
|
|
|
|
if (m_nSnap & LC_DRAW_SNAP_X)
|
|
|
|
{
|
|
|
|
int i = (int)(Delta[0] / SnapXY);
|
|
|
|
Leftover[0] = Delta[0] - (SnapXY * i);
|
|
|
|
|
|
|
|
if (Leftover[0] > SnapXY / 2)
|
|
|
|
{
|
|
|
|
Leftover[0] -= SnapXY;
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
else if (Leftover[0] < -SnapXY / 2)
|
|
|
|
{
|
|
|
|
Leftover[0] += SnapXY;
|
|
|
|
i--;
|
|
|
|
}
|
|
|
|
|
|
|
|
Delta[0] = SnapXY * i;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_nSnap & LC_DRAW_SNAP_Y)
|
|
|
|
{
|
|
|
|
int i = (int)(Delta[1] / SnapXY);
|
|
|
|
Leftover[1] = Delta[1] - (SnapXY * i);
|
|
|
|
|
|
|
|
if (Leftover[1] > SnapXY / 2)
|
|
|
|
{
|
|
|
|
Leftover[1] -= SnapXY;
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
else if (Leftover[1] < -SnapXY / 2)
|
|
|
|
{
|
|
|
|
Leftover[1] += SnapXY;
|
|
|
|
i--;
|
|
|
|
}
|
|
|
|
|
|
|
|
Delta[1] = SnapXY * i;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_nSnap & LC_DRAW_SNAP_Z)
|
|
|
|
{
|
|
|
|
int i = (int)(Delta[2] / SnapZ);
|
|
|
|
Leftover[2] = Delta[2] - (SnapZ * i);
|
|
|
|
|
|
|
|
if (Leftover[2] > SnapZ / 2)
|
|
|
|
{
|
|
|
|
Leftover[2] -= SnapZ;
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
else if (Leftover[2] < -SnapZ / 2)
|
|
|
|
{
|
|
|
|
Leftover[2] += SnapZ;
|
|
|
|
i--;
|
|
|
|
}
|
|
|
|
|
|
|
|
Delta[2] = SnapZ * i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-06-16 02:17:52 +02:00
|
|
|
void Project::SnapRotationVector(lcVector3& Delta, lcVector3& Leftover) const
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
|
|
|
if (m_nSnap & LC_DRAW_SNAP_A)
|
|
|
|
{
|
|
|
|
int Snap[3];
|
|
|
|
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
|
|
{
|
|
|
|
Snap[i] = (int)(Delta[i] / (float)m_nAngleSnap);
|
|
|
|
}
|
|
|
|
|
2012-06-16 02:17:52 +02:00
|
|
|
lcVector3 NewDelta((float)(m_nAngleSnap * Snap[0]), (float)(m_nAngleSnap * Snap[1]), (float)(m_nAngleSnap * Snap[2]));
|
2011-09-07 23:06:51 +02:00
|
|
|
Leftover = Delta - NewDelta;
|
|
|
|
Delta = NewDelta;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-13 02:28:35 +02:00
|
|
|
bool Project::MoveSelectedObjects(lcVector3& Move, lcVector3& Remainder, bool Snap, bool Lock)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
|
|
|
// Don't move along locked directions.
|
2012-08-13 02:28:35 +02:00
|
|
|
if (Lock)
|
|
|
|
{
|
|
|
|
if (m_nSnap & LC_DRAW_LOCK_X)
|
|
|
|
Move[0] = 0;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-08-13 02:28:35 +02:00
|
|
|
if (m_nSnap & LC_DRAW_LOCK_Y)
|
|
|
|
Move[1] = 0;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-08-13 02:28:35 +02:00
|
|
|
if (m_nSnap & LC_DRAW_LOCK_Z)
|
|
|
|
Move[2] = 0;
|
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
// Snap.
|
|
|
|
if (Snap)
|
|
|
|
{
|
|
|
|
SnapVector(Move, Remainder);
|
|
|
|
|
|
|
|
if (Move.LengthSquared() < 0.001f)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Transform the translation if we're in relative mode.
|
|
|
|
if ((m_nSnap & LC_DRAW_GLOBAL_SNAP) == 0)
|
|
|
|
{
|
|
|
|
Object* Focus = GetFocusObject();
|
|
|
|
|
|
|
|
if ((Focus != NULL) && Focus->IsPiece())
|
2012-06-16 02:17:52 +02:00
|
|
|
Move = lcMul30(Move, ((Piece*)Focus)->mModelWorld);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Piece* pPiece;
|
|
|
|
Light* pLight;
|
|
|
|
float x = Move[0], y = Move[1], z = Move[2];
|
|
|
|
|
2012-08-22 03:13:32 +02:00
|
|
|
for (int CameraIdx = 0; CameraIdx < mCameras.GetSize(); CameraIdx++)
|
|
|
|
{
|
|
|
|
Camera* pCamera = mCameras[CameraIdx];
|
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
if (pCamera->IsSelected())
|
|
|
|
{
|
|
|
|
pCamera->Move(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation, m_bAddKeys, x, y, z);
|
|
|
|
pCamera->UpdatePosition(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation);
|
|
|
|
}
|
2012-08-22 03:13:32 +02:00
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
for (pLight = m_pLights; pLight; pLight = pLight->m_pNext)
|
2012-08-22 03:13:32 +02:00
|
|
|
if (pLight->IsSelected())
|
|
|
|
{
|
|
|
|
pLight->Move (m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation, m_bAddKeys, x, y, z);
|
|
|
|
pLight->UpdatePosition (m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation);
|
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
for (pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
|
|
|
if (pPiece->IsSelected())
|
|
|
|
{
|
|
|
|
pPiece->Move(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation, m_bAddKeys, x, y, z);
|
|
|
|
pPiece->UpdatePosition(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation);
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: move group centers
|
|
|
|
|
|
|
|
if (m_OverlayActive)
|
|
|
|
{
|
|
|
|
if (!GetFocusPosition(m_OverlayCenter))
|
|
|
|
GetSelectionCenter(m_OverlayCenter);
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-08-13 02:28:35 +02:00
|
|
|
bool Project::RotateSelectedObjects(lcVector3& Delta, lcVector3& Remainder, bool Snap, bool Lock)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
|
|
|
// Don't move along locked directions.
|
2012-08-13 02:28:35 +02:00
|
|
|
if (Lock)
|
|
|
|
{
|
|
|
|
if (m_nSnap & LC_DRAW_LOCK_X)
|
|
|
|
Delta[0] = 0;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-08-13 02:28:35 +02:00
|
|
|
if (m_nSnap & LC_DRAW_LOCK_Y)
|
|
|
|
Delta[1] = 0;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-08-13 02:28:35 +02:00
|
|
|
if (m_nSnap & LC_DRAW_LOCK_Z)
|
|
|
|
Delta[2] = 0;
|
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
// Snap.
|
2012-08-13 02:28:35 +02:00
|
|
|
if (Snap)
|
|
|
|
SnapRotationVector(Delta, Remainder);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
if (Delta.LengthSquared() < 0.001f)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
float bs[6] = { 10000, 10000, 10000, -10000, -10000, -10000 };
|
2012-06-16 02:17:52 +02:00
|
|
|
lcVector3 pos;
|
|
|
|
lcVector4 rot;
|
2011-09-07 23:06:51 +02:00
|
|
|
int nSel = 0;
|
|
|
|
Piece *pPiece, *pFocus = NULL;
|
|
|
|
|
|
|
|
for (pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
|
|
|
{
|
|
|
|
if (pPiece->IsSelected())
|
|
|
|
{
|
|
|
|
if (pPiece->IsFocused())
|
|
|
|
pFocus = pPiece;
|
|
|
|
|
|
|
|
pPiece->CompareBoundingBox(bs);
|
|
|
|
nSel++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pFocus != NULL)
|
|
|
|
{
|
2012-06-16 02:17:52 +02:00
|
|
|
pos = pFocus->mPosition;
|
2011-09-07 23:06:51 +02:00
|
|
|
bs[0] = bs[3] = pos[0];
|
|
|
|
bs[1] = bs[4] = pos[1];
|
|
|
|
bs[2] = bs[5] = pos[2];
|
|
|
|
}
|
|
|
|
|
2012-07-12 06:18:10 +02:00
|
|
|
lcVector3 Center((bs[0]+bs[3])/2, (bs[1]+bs[4])/2, (bs[2]+bs[5])/2);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
// Create the rotation matrix.
|
2012-07-12 06:18:10 +02:00
|
|
|
lcVector4 RotationQuaternion(0, 0, 0, 1);
|
|
|
|
lcVector4 WorldToFocusQuaternion, FocusToWorldQuaternion;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
if (!(m_nSnap & LC_DRAW_LOCK_X) && (Delta[0] != 0.0f))
|
|
|
|
{
|
2012-07-12 06:18:10 +02:00
|
|
|
lcVector4 q = lcQuaternionRotationX(Delta[0] * LC_DTOR);
|
|
|
|
RotationQuaternion = lcQuaternionMultiply(q, RotationQuaternion);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!(m_nSnap & LC_DRAW_LOCK_Y) && (Delta[1] != 0.0f))
|
|
|
|
{
|
2012-07-12 06:18:10 +02:00
|
|
|
lcVector4 q = lcQuaternionRotationY(Delta[1] * LC_DTOR);
|
|
|
|
RotationQuaternion = lcQuaternionMultiply(q, RotationQuaternion);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!(m_nSnap & LC_DRAW_LOCK_Z) && (Delta[2] != 0.0f))
|
|
|
|
{
|
2012-07-12 06:18:10 +02:00
|
|
|
lcVector4 q = lcQuaternionRotationZ(Delta[2] * LC_DTOR);
|
|
|
|
RotationQuaternion = lcQuaternionMultiply(q, RotationQuaternion);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Transform the rotation relative to the focused piece.
|
|
|
|
if (m_nSnap & LC_DRAW_GLOBAL_SNAP)
|
|
|
|
pFocus = NULL;
|
|
|
|
|
|
|
|
if (pFocus != NULL)
|
|
|
|
{
|
2012-06-16 02:17:52 +02:00
|
|
|
lcVector4 Rot;
|
|
|
|
Rot = ((Piece*)pFocus)->mRotation;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-07-12 06:18:10 +02:00
|
|
|
WorldToFocusQuaternion = lcQuaternionFromAxisAngle(lcVector4(Rot[0], Rot[1], Rot[2], -Rot[3] * LC_DTOR));
|
|
|
|
FocusToWorldQuaternion = lcQuaternionFromAxisAngle(lcVector4(Rot[0], Rot[1], Rot[2], Rot[3] * LC_DTOR));
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-07-12 06:18:10 +02:00
|
|
|
RotationQuaternion = lcQuaternionMultiply(FocusToWorldQuaternion, RotationQuaternion);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
for (pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
|
|
|
{
|
|
|
|
if (!pPiece->IsSelected())
|
|
|
|
continue;
|
|
|
|
|
2012-06-16 02:17:52 +02:00
|
|
|
pos = pPiece->mPosition;
|
|
|
|
rot = pPiece->mRotation;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-07-12 06:18:10 +02:00
|
|
|
lcVector4 NewRotation;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
if ((nSel == 1) && (pFocus == pPiece))
|
|
|
|
{
|
2012-07-12 06:18:10 +02:00
|
|
|
lcVector4 LocalToWorldQuaternion;
|
|
|
|
LocalToWorldQuaternion = lcQuaternionFromAxisAngle(lcVector4(rot[0], rot[1], rot[2], rot[3] * LC_DTOR));
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-07-12 06:18:10 +02:00
|
|
|
lcVector4 NewLocalToWorldQuaternion;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
if (pFocus != NULL)
|
|
|
|
{
|
2012-07-12 06:18:10 +02:00
|
|
|
lcVector4 LocalToFocusQuaternion = lcQuaternionMultiply(WorldToFocusQuaternion, LocalToWorldQuaternion);
|
|
|
|
NewLocalToWorldQuaternion = lcQuaternionMultiply(LocalToFocusQuaternion, RotationQuaternion);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-07-12 06:18:10 +02:00
|
|
|
NewLocalToWorldQuaternion = lcQuaternionMultiply(RotationQuaternion, LocalToWorldQuaternion);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
2012-07-12 06:18:10 +02:00
|
|
|
NewRotation = lcQuaternionToAxisAngle(NewLocalToWorldQuaternion);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-07-12 06:18:10 +02:00
|
|
|
lcVector3 Distance = lcVector3(pos[0], pos[1], pos[2]) - Center;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-07-12 06:18:10 +02:00
|
|
|
lcVector4 LocalToWorldQuaternion = lcQuaternionFromAxisAngle(lcVector4(rot[0], rot[1], rot[2], rot[3] * LC_DTOR));
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-07-12 06:18:10 +02:00
|
|
|
lcVector4 NewLocalToWorldQuaternion;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
if (pFocus != NULL)
|
|
|
|
{
|
2012-07-12 06:18:10 +02:00
|
|
|
lcVector4 LocalToFocusQuaternion = lcQuaternionMultiply(WorldToFocusQuaternion, LocalToWorldQuaternion);
|
|
|
|
NewLocalToWorldQuaternion = lcQuaternionMultiply(RotationQuaternion, LocalToFocusQuaternion);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-07-12 06:18:10 +02:00
|
|
|
lcVector4 WorldToLocalQuaternion = lcQuaternionFromAxisAngle(lcVector4(rot[0], rot[1], rot[2], -rot[3] * LC_DTOR));
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-07-12 06:18:10 +02:00
|
|
|
Distance = lcQuaternionMul(Distance, WorldToLocalQuaternion);
|
|
|
|
Distance = lcQuaternionMul(Distance, NewLocalToWorldQuaternion);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-07-12 06:18:10 +02:00
|
|
|
NewLocalToWorldQuaternion = lcQuaternionMultiply(RotationQuaternion, LocalToWorldQuaternion);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-07-12 06:18:10 +02:00
|
|
|
Distance = lcQuaternionMul(Distance, RotationQuaternion);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
2012-07-12 06:18:10 +02:00
|
|
|
NewRotation = lcQuaternionToAxisAngle(NewLocalToWorldQuaternion);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
pos[0] = Center[0] + Distance[0];
|
|
|
|
pos[1] = Center[1] + Distance[1];
|
|
|
|
pos[2] = Center[2] + Distance[2];
|
|
|
|
|
|
|
|
pPiece->ChangeKey(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation, m_bAddKeys, pos, LC_PK_POSITION);
|
|
|
|
}
|
|
|
|
|
|
|
|
rot[0] = NewRotation[0];
|
|
|
|
rot[1] = NewRotation[1];
|
|
|
|
rot[2] = NewRotation[2];
|
|
|
|
rot[3] = NewRotation[3] * LC_RTOD;
|
|
|
|
|
|
|
|
pPiece->ChangeKey(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation, m_bAddKeys, rot, LC_PK_ROTATION);
|
|
|
|
pPiece->UpdatePosition(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_OverlayActive)
|
|
|
|
{
|
|
|
|
if (!GetFocusPosition(m_OverlayCenter))
|
|
|
|
GetSelectionCenter(m_OverlayCenter);
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-08-13 02:28:35 +02:00
|
|
|
void Project::TransformSelectedObjects(LC_TRANSFORM_TYPE Type, const lcVector3& Transform)
|
|
|
|
{
|
|
|
|
switch (Type)
|
|
|
|
{
|
|
|
|
case LC_TRANSFORM_ABSOLUTE_TRANSLATION:
|
|
|
|
{
|
|
|
|
float bs[6] = { 10000, 10000, 10000, -10000, -10000, -10000 };
|
|
|
|
lcVector3 Center;
|
|
|
|
int nSel = 0;
|
|
|
|
Piece *pPiece, *pFocus = NULL;
|
|
|
|
|
|
|
|
for (pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
|
|
|
{
|
|
|
|
if (pPiece->IsSelected())
|
|
|
|
{
|
|
|
|
if (pPiece->IsFocused())
|
|
|
|
pFocus = pPiece;
|
|
|
|
|
|
|
|
pPiece->CompareBoundingBox(bs);
|
|
|
|
nSel++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pFocus != NULL)
|
|
|
|
Center = pFocus->mPosition;
|
|
|
|
else
|
|
|
|
Center = lcVector3((bs[0]+bs[3])/2, (bs[1]+bs[4])/2, (bs[2]+bs[5])/2);
|
|
|
|
|
|
|
|
lcVector3 Offset = Transform - Center;
|
|
|
|
|
|
|
|
Light* pLight;
|
|
|
|
|
2012-08-22 03:13:32 +02:00
|
|
|
for (int CameraIdx = 0; CameraIdx < mCameras.GetSize(); CameraIdx++)
|
2012-08-13 02:28:35 +02:00
|
|
|
{
|
2012-08-22 03:13:32 +02:00
|
|
|
Camera* pCamera = mCameras[CameraIdx];
|
|
|
|
|
2012-08-13 02:28:35 +02:00
|
|
|
if (pCamera->IsSelected())
|
|
|
|
{
|
|
|
|
pCamera->Move(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation, m_bAddKeys, Offset.x, Offset.y, Offset.z);
|
|
|
|
pCamera->UpdatePosition(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (pLight = m_pLights; pLight; pLight = pLight->m_pNext)
|
|
|
|
{
|
|
|
|
if (pLight->IsSelected())
|
|
|
|
{
|
|
|
|
pLight->Move(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation, m_bAddKeys, Offset.x, Offset.y, Offset.z);
|
|
|
|
pLight->UpdatePosition (m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
|
|
|
{
|
|
|
|
if (pPiece->IsSelected())
|
|
|
|
{
|
|
|
|
pPiece->Move(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation, m_bAddKeys, Offset.x, Offset.y, Offset.z);
|
|
|
|
pPiece->UpdatePosition(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_OverlayActive)
|
|
|
|
{
|
|
|
|
if (!GetFocusPosition(m_OverlayCenter))
|
|
|
|
GetSelectionCenter(m_OverlayCenter);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (nSel)
|
|
|
|
{
|
|
|
|
UpdateOverlayScale();
|
|
|
|
UpdateAllViews();
|
|
|
|
SetModifiedFlag(true);
|
|
|
|
CheckPoint("Moving");
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateFocusObject(GetFocusObject());
|
2012-08-13 02:28:35 +02:00
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_TRANSFORM_RELATIVE_TRANSLATION:
|
|
|
|
{
|
|
|
|
lcVector3 Move(Transform), Remainder;
|
|
|
|
|
|
|
|
if (MoveSelectedObjects(Move, Remainder, false, false))
|
|
|
|
{
|
|
|
|
UpdateOverlayScale();
|
|
|
|
UpdateAllViews();
|
|
|
|
SetModifiedFlag(true);
|
|
|
|
CheckPoint("Moving");
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateFocusObject(GetFocusObject());
|
2012-08-13 02:28:35 +02:00
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_TRANSFORM_ABSOLUTE_ROTATION:
|
|
|
|
{
|
|
|
|
// Create the rotation matrix.
|
|
|
|
lcVector4 RotationQuaternion(0, 0, 0, 1);
|
|
|
|
|
|
|
|
if (Transform[0] != 0.0f)
|
|
|
|
{
|
|
|
|
lcVector4 q = lcQuaternionRotationX(Transform[0] * LC_DTOR);
|
|
|
|
RotationQuaternion = lcQuaternionMultiply(q, RotationQuaternion);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Transform[1] != 0.0f)
|
|
|
|
{
|
|
|
|
lcVector4 q = lcQuaternionRotationY(Transform[1] * LC_DTOR);
|
|
|
|
RotationQuaternion = lcQuaternionMultiply(q, RotationQuaternion);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Transform[2] != 0.0f)
|
|
|
|
{
|
|
|
|
lcVector4 q = lcQuaternionRotationZ(Transform[2] * LC_DTOR);
|
|
|
|
RotationQuaternion = lcQuaternionMultiply(q, RotationQuaternion);
|
|
|
|
}
|
|
|
|
|
|
|
|
lcVector4 NewRotation = lcQuaternionToAxisAngle(RotationQuaternion);
|
|
|
|
NewRotation[3] *= LC_RTOD;
|
|
|
|
|
|
|
|
Piece *pPiece;
|
|
|
|
int nSel = 0;
|
|
|
|
|
|
|
|
for (pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
|
|
|
{
|
|
|
|
if (pPiece->IsSelected())
|
|
|
|
{
|
|
|
|
pPiece->ChangeKey(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation, m_bAddKeys, NewRotation, LC_PK_ROTATION);
|
|
|
|
pPiece->UpdatePosition(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation);
|
|
|
|
nSel++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_OverlayActive)
|
|
|
|
{
|
|
|
|
if (!GetFocusPosition(m_OverlayCenter))
|
|
|
|
GetSelectionCenter(m_OverlayCenter);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (nSel)
|
|
|
|
{
|
|
|
|
UpdateOverlayScale();
|
|
|
|
UpdateAllViews();
|
|
|
|
SetModifiedFlag(true);
|
|
|
|
CheckPoint("Rotating");
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateFocusObject(GetFocusObject());
|
2012-08-13 02:28:35 +02:00
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_TRANSFORM_RELATIVE_ROTATION:
|
|
|
|
{
|
|
|
|
lcVector3 Rotate(Transform), Remainder;
|
|
|
|
|
|
|
|
if (RotateSelectedObjects(Rotate, Remainder, false, false))
|
|
|
|
{
|
|
|
|
UpdateOverlayScale();
|
|
|
|
UpdateAllViews();
|
|
|
|
SetModifiedFlag(true);
|
|
|
|
CheckPoint("Rotating");
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateFocusObject(GetFocusObject());
|
2012-08-13 02:28:35 +02:00
|
|
|
}
|
|
|
|
} break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
void Project::ModifyObject(Object* Object, lcObjectProperty Property, void* Value)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
const char* CheckPointString = NULL;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
switch (Property)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
case LC_PART_POSITION:
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
const lcVector3& Position = *(lcVector3*)Value;
|
|
|
|
Piece* Part = (Piece*)Object;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
if (Part->mPosition != Position)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
Part->ChangeKey(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation, m_bAddKeys, Position, LC_PK_POSITION);
|
|
|
|
Part->UpdatePosition(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
CheckPointString = "Moving";
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
case LC_PART_ROTATION:
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
const lcVector4& Rotation = *(lcVector4*)Value;
|
|
|
|
Piece* Part = (Piece*)Object;
|
2013-01-06 20:24:25 +01:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
if (Rotation != Part->mRotation)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
Part->ChangeKey(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation, m_bAddKeys, Rotation, LC_PK_ROTATION);
|
|
|
|
Part->UpdatePosition(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
CheckPointString = "Rotating";
|
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
} break;
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
case LC_PART_SHOW:
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
lcuint32 Show = *(lcuint32*)Value;
|
|
|
|
Piece* Part = (Piece*)Object;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
if (m_bAnimation)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
if (Show != Part->GetFrameShow())
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
Part->SetFrameShow(Show);
|
|
|
|
|
|
|
|
CheckPointString = "Show";
|
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
if (Show != Part->GetStepShow())
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
Part->SetStepShow(Show);
|
|
|
|
|
|
|
|
CheckPointString = "Show";
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
}
|
2013-08-09 06:57:18 +02:00
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_PART_HIDE:
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
lcuint32 Hide = *(lcuint32*)Value;
|
|
|
|
Piece* Part = (Piece*)Object;
|
|
|
|
|
|
|
|
if (m_bAnimation)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
if (Hide != Part->GetFrameHide())
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
Part->SetFrameHide(Hide);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
CheckPointString = "Hide";
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
if (Hide != Part->GetStepHide())
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
Part->SetStepHide(Hide);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
CheckPointString = "Hide";
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
}
|
2013-08-09 06:57:18 +02:00
|
|
|
} break;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
case LC_PART_COLOR:
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
int ColorIndex = *(int*)Value;
|
|
|
|
Piece* Part = (Piece*)Object;
|
|
|
|
|
|
|
|
if (ColorIndex != Part->mColorIndex)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
Part->SetColorIndex(ColorIndex);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
CheckPointString = "Color";
|
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
} break;
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
case LC_PART_ID:
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
Piece* Part = (Piece*)Object;
|
|
|
|
PieceInfo* Info = (PieceInfo*)Value;
|
|
|
|
|
|
|
|
if (Info != Part->mPieceInfo)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
Part->mPieceInfo->Release();
|
|
|
|
Part->mPieceInfo = Info;
|
|
|
|
Part->mPieceInfo->AddRef();
|
|
|
|
|
|
|
|
CheckPointString = "Part";
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
2013-08-09 06:57:18 +02:00
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_CAMERA_POSITION:
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
const lcVector3& Position = *(lcVector3*)Value;
|
|
|
|
Camera* camera = (Camera*)Object;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
if (camera->mPosition != Position)
|
|
|
|
{
|
|
|
|
camera->ChangeKey(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation, m_bAddKeys, Position, LC_CK_EYE);
|
|
|
|
camera->UpdatePosition(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
CheckPointString = "Camera";
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
2013-08-09 06:57:18 +02:00
|
|
|
} break;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
case LC_CAMERA_TARGET:
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
const lcVector3& TargetPosition = *(lcVector3*)Value;
|
|
|
|
Camera* camera = (Camera*)Object;
|
|
|
|
|
|
|
|
if (camera->mTargetPosition != TargetPosition)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
camera->ChangeKey(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation, m_bAddKeys, TargetPosition, LC_CK_TARGET);
|
|
|
|
camera->UpdatePosition(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation);
|
|
|
|
|
|
|
|
CheckPointString = "Camera";
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
2013-08-09 06:57:18 +02:00
|
|
|
} break;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
case LC_CAMERA_UP:
|
2012-02-01 03:08:30 +01:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
const lcVector3& Up = *(lcVector3*)Value;
|
|
|
|
Camera* camera = (Camera*)Object;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
if (camera->mUpVector != Up)
|
2012-02-01 03:08:30 +01:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
camera->ChangeKey(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation, m_bAddKeys, Up, LC_CK_UP);
|
|
|
|
camera->UpdatePosition(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
CheckPointString = "Camera";
|
|
|
|
}
|
|
|
|
} break;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
case LC_CAMERA_FOV:
|
|
|
|
{
|
|
|
|
float FOV = *(float*)Value;
|
|
|
|
Camera* camera = (Camera*)Object;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
if (camera->m_fovy != FOV)
|
|
|
|
{
|
|
|
|
camera->m_fovy = FOV;
|
|
|
|
camera->UpdatePosition(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
CheckPointString = "Camera";
|
2012-02-01 03:08:30 +01:00
|
|
|
}
|
2013-08-09 06:57:18 +02:00
|
|
|
} break;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
case LC_CAMERA_NEAR:
|
2012-02-01 03:08:30 +01:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
float Near = *(float*)Value;
|
|
|
|
Camera* camera = (Camera*)Object;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
if (camera->m_zNear != Near)
|
|
|
|
{
|
|
|
|
camera->m_zNear= Near;
|
|
|
|
camera->UpdatePosition(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
CheckPointString = "Camera";
|
2012-02-01 03:08:30 +01:00
|
|
|
}
|
2013-08-09 06:57:18 +02:00
|
|
|
} break;
|
2012-02-01 03:08:30 +01:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
case LC_CAMERA_FAR:
|
|
|
|
{
|
|
|
|
float Far = *(float*)Value;
|
|
|
|
Camera* camera = (Camera*)Object;
|
2012-02-01 03:08:30 +01:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
if (camera->m_zFar != Far)
|
|
|
|
{
|
|
|
|
camera->m_zFar = Far;
|
|
|
|
camera->UpdatePosition(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation);
|
2012-02-01 03:08:30 +01:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
CheckPointString = "Camera";
|
|
|
|
}
|
|
|
|
} break;
|
2012-02-01 03:08:30 +01:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
case LC_CAMERA_NAME:
|
|
|
|
{
|
|
|
|
const char* Name = (const char*)Value;
|
|
|
|
Camera* camera = (Camera*)Object;
|
2012-02-01 03:08:30 +01:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
if (strcmp(camera->m_strName, Name))
|
|
|
|
{
|
|
|
|
strncpy(camera->m_strName, Name, sizeof(camera->m_strName));
|
|
|
|
camera->m_strName[sizeof(camera->m_strName) - 1] = 0;
|
2012-02-01 03:08:30 +01:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateCameraMenu(mCameras, m_ActiveView ? m_ActiveView->mCamera : NULL);
|
2012-02-01 03:08:30 +01:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
CheckPointString = "Camera";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-02-01 03:08:30 +01:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
if (CheckPointString)
|
2012-02-01 03:08:30 +01:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
SetModifiedFlag(true);
|
|
|
|
CheckPoint(CheckPointString);
|
|
|
|
gMainWindow->UpdateFocusObject(GetFocusObject());
|
|
|
|
ActivateOverlay(m_ActiveView, m_nCurAction, LC_OVERLAY_NONE);
|
|
|
|
UpdateAllViews();
|
|
|
|
}
|
|
|
|
}
|
2012-02-01 03:08:30 +01:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
void Project::ZoomActiveView(int Amount)
|
2012-02-01 03:08:30 +01:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
m_ActiveView->mCamera->DoZoom(Amount, m_nMouse, m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation, m_bAddKeys);
|
|
|
|
gMainWindow->UpdateFocusObject(GetFocusObject());
|
|
|
|
UpdateOverlayScale();
|
|
|
|
UpdateAllViews();
|
2012-02-01 03:08:30 +01:00
|
|
|
}
|
2013-08-09 06:57:18 +02:00
|
|
|
|
|
|
|
void Project::BeginPieceDrop(PieceInfo* Info)
|
2012-02-01 03:08:30 +01:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
StartTracking(LC_TRACK_LEFT);
|
|
|
|
|
|
|
|
mDropPiece = Info;
|
|
|
|
mDropPiece->AddRef();
|
2012-02-01 03:08:30 +01:00
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
void Project::OnPieceDropMove(int x, int y)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
if (!mDropPiece)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (m_nDownX != x || m_nDownY != y)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
m_nDownX = x;
|
|
|
|
m_nDownY = y;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
UpdateAllViews();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
void Project::EndPieceDrop(bool Accept)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
StopTracking(Accept);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
if (!Accept)
|
|
|
|
UpdateAllViews();
|
2012-01-28 03:10:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void Project::BeginColorDrop()
|
|
|
|
{
|
|
|
|
StartTracking(LC_TRACK_LEFT);
|
|
|
|
SetAction(LC_ACTION_PAINT);
|
2013-08-09 06:57:18 +02:00
|
|
|
// m_RestoreAction = true;
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
void Project::OnLeftButtonDown(View* view)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
|
|
|
if (m_nTracking != LC_TRACK_NONE)
|
|
|
|
if (StopTracking(false))
|
|
|
|
return;
|
|
|
|
|
2011-09-20 03:26:31 +02:00
|
|
|
if (SetActiveView(view))
|
2011-09-07 23:06:51 +02:00
|
|
|
return;
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
int x = view->mInputState.x;
|
|
|
|
int y = view->mInputState.y;
|
|
|
|
bool Control = view->mInputState.Control;
|
|
|
|
bool Alt = view->mInputState.Alt;
|
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
m_bTrackCancel = false;
|
|
|
|
m_nDownX = x;
|
|
|
|
m_nDownY = y;
|
2012-06-16 02:17:52 +02:00
|
|
|
m_MouseTotalDelta = lcVector3(0, 0, 0);
|
|
|
|
m_MouseSnapLeftover = lcVector3(0, 0, 0);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
int Viewport[4] = { 0, 0, view->mWidth, view->mHeight };
|
2012-01-30 08:31:29 +01:00
|
|
|
float Aspect = (float)Viewport[2]/(float)Viewport[3];
|
2012-08-20 06:05:56 +02:00
|
|
|
Camera* Cam = view->mCamera;
|
2012-01-30 08:31:29 +01:00
|
|
|
|
2012-05-29 01:33:22 +02:00
|
|
|
const lcMatrix44& ModelView = Cam->mWorldView;
|
|
|
|
lcMatrix44 Projection = lcMatrix44Perspective(Cam->m_fovy, Aspect, Cam->m_zNear, Cam->m_zFar);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-05-29 01:33:22 +02:00
|
|
|
lcVector3 point = lcUnprojectPoint(lcVector3((float)x, (float)y, 0.9f), ModelView, Projection, Viewport);
|
2012-01-30 08:31:29 +01:00
|
|
|
m_fTrack[0] = point[0]; m_fTrack[1] = point[1]; m_fTrack[2] = point[2];
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
if (Alt)
|
2012-07-31 07:27:40 +02:00
|
|
|
ActivateOverlay(view, LC_ACTION_ROTATE_VIEW, LC_OVERLAY_ROTATE_VIEW_XYZ);
|
|
|
|
|
|
|
|
int Action = GetAction();
|
2012-01-28 03:10:19 +01:00
|
|
|
|
2012-07-31 07:27:40 +02:00
|
|
|
switch (Action)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
|
|
|
case LC_ACTION_SELECT:
|
|
|
|
case LC_ACTION_ERASER:
|
|
|
|
case LC_ACTION_PAINT:
|
|
|
|
{
|
2012-01-30 08:31:29 +01:00
|
|
|
Object* Closest = FindObjectFromPoint(view, x, y);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-01-06 20:24:25 +01:00
|
|
|
if (Action == LC_ACTION_SELECT)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2012-01-30 08:31:29 +01:00
|
|
|
if (Closest != NULL)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2012-01-30 08:31:29 +01:00
|
|
|
switch (Closest->GetType ())
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
|
|
|
case LC_OBJECT_PIECE:
|
|
|
|
{
|
2012-01-30 08:31:29 +01:00
|
|
|
Piece* pPiece = (Piece*)Closest;
|
2011-09-07 23:06:51 +02:00
|
|
|
Group* pGroup = pPiece->GetTopGroup();
|
|
|
|
bool bFocus = pPiece->IsFocused ();
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
SelectAndFocusNone(Control);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
// if a piece has focus deselect it, otherwise set the focus
|
|
|
|
pPiece->Select (!bFocus, !bFocus, false);
|
|
|
|
|
|
|
|
if (pGroup != NULL)
|
|
|
|
for (pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
|
|
|
if (pPiece->GetTopGroup() == pGroup)
|
|
|
|
pPiece->Select (!bFocus, false, false);
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_OBJECT_CAMERA:
|
|
|
|
case LC_OBJECT_CAMERA_TARGET:
|
|
|
|
case LC_OBJECT_LIGHT:
|
|
|
|
case LC_OBJECT_LIGHT_TARGET:
|
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
SelectAndFocusNone(Control);
|
|
|
|
Closest->Select(true, true, Control);
|
2011-09-07 23:06:51 +02:00
|
|
|
} break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2013-08-09 06:57:18 +02:00
|
|
|
SelectAndFocusNone(Control);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
UpdateSelection();
|
|
|
|
UpdateAllViews();
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateFocusObject(Closest);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
StartTracking(LC_TRACK_START_LEFT);
|
|
|
|
}
|
|
|
|
|
2012-07-31 07:27:40 +02:00
|
|
|
if ((Action == LC_ACTION_ERASER) && (Closest != NULL))
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2012-01-30 08:31:29 +01:00
|
|
|
switch (Closest->GetType ())
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
|
|
|
case LC_OBJECT_PIECE:
|
|
|
|
{
|
2012-01-30 08:31:29 +01:00
|
|
|
Piece* pPiece = (Piece*)Closest;
|
2011-09-07 23:06:51 +02:00
|
|
|
RemovePiece(pPiece);
|
|
|
|
delete pPiece;
|
|
|
|
// CalculateStep();
|
|
|
|
RemoveEmptyGroups();
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_OBJECT_CAMERA:
|
|
|
|
case LC_OBJECT_CAMERA_TARGET:
|
|
|
|
{
|
|
|
|
Camera* pCamera;
|
2012-08-22 03:13:32 +02:00
|
|
|
if (Closest->GetType() == LC_OBJECT_CAMERA)
|
2012-01-30 08:31:29 +01:00
|
|
|
pCamera = (Camera*)Closest;
|
2011-09-07 23:06:51 +02:00
|
|
|
else
|
2012-01-30 08:31:29 +01:00
|
|
|
pCamera = ((CameraTarget*)Closest)->GetParent();
|
2012-02-05 03:50:57 +01:00
|
|
|
|
2012-08-22 03:13:32 +02:00
|
|
|
bool CanDelete = true;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-08-22 03:13:32 +02:00
|
|
|
for (int ViewIdx = 0; ViewIdx < m_ViewList.GetSize() && CanDelete; ViewIdx++)
|
|
|
|
CanDelete = pCamera != m_ViewList[ViewIdx]->mCamera;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-08-22 03:13:32 +02:00
|
|
|
if (CanDelete)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-16 01:43:18 +02:00
|
|
|
mCameras.Remove(pCamera);
|
2012-08-22 03:13:32 +02:00
|
|
|
delete pCamera;
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateCameraMenu(mCameras, m_ActiveView ? m_ActiveView->mCamera : NULL);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_OBJECT_LIGHT:
|
|
|
|
case LC_OBJECT_LIGHT_TARGET:
|
|
|
|
{
|
|
|
|
// pos = m_Lights.Find(pObject->m_pParent);
|
|
|
|
// m_Lights.RemoveAt(pos);
|
|
|
|
// delete pObject->m_pParent;
|
|
|
|
} break;
|
|
|
|
}
|
|
|
|
|
|
|
|
UpdateSelection();
|
|
|
|
UpdateAllViews();
|
|
|
|
SetModifiedFlag(true);
|
|
|
|
CheckPoint("Deleting");
|
|
|
|
// AfxGetMainWnd()->PostMessage(WM_LC_UPDATE_INFO, NULL, OT_PIECE);
|
|
|
|
}
|
|
|
|
|
2012-07-31 07:27:40 +02:00
|
|
|
if ((Action == LC_ACTION_PAINT) && (Closest != NULL) && (Closest->GetType() == LC_OBJECT_PIECE))
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2012-01-30 08:31:29 +01:00
|
|
|
Piece* pPiece = (Piece*)Closest;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
if (pPiece->mColorIndex != gMainWindow->mColorIndex)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
pPiece->SetColorIndex(gMainWindow->mColorIndex);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
SetModifiedFlag(true);
|
|
|
|
CheckPoint("Painting");
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateFocusObject(GetFocusObject());
|
2011-09-07 23:06:51 +02:00
|
|
|
UpdateAllViews();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_ACTION_INSERT:
|
|
|
|
case LC_ACTION_LIGHT:
|
|
|
|
{
|
2012-07-31 07:27:40 +02:00
|
|
|
if (Action == LC_ACTION_INSERT)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2012-06-16 02:17:52 +02:00
|
|
|
lcVector3 Pos;
|
|
|
|
lcVector4 Rot;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-01-28 02:05:23 +01:00
|
|
|
GetPieceInsertPosition(view, x, y, Pos, Rot);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
Piece* pPiece = new Piece(m_pCurPiece);
|
2012-03-28 03:07:18 +02:00
|
|
|
pPiece->Initialize(Pos[0], Pos[1], Pos[2], m_nCurStep, m_nCurFrame);
|
2013-08-09 06:57:18 +02:00
|
|
|
pPiece->SetColorIndex(gMainWindow->mColorIndex);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
pPiece->ChangeKey(m_nCurStep, false, false, Rot, LC_PK_ROTATION);
|
|
|
|
pPiece->ChangeKey(m_nCurFrame, true, false, Rot, LC_PK_ROTATION);
|
|
|
|
pPiece->UpdatePosition(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation);
|
|
|
|
|
|
|
|
SelectAndFocusNone(false);
|
|
|
|
pPiece->CreateName(m_pPieces);
|
|
|
|
AddPiece(pPiece);
|
|
|
|
pPiece->Select (true, true, false);
|
|
|
|
UpdateSelection();
|
|
|
|
SystemPieceComboAdd(m_pCurPiece->m_strDescription);
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateFocusObject(pPiece);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
if (!Control)
|
2012-08-13 02:38:57 +02:00
|
|
|
SetAction(LC_ACTION_SELECT);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
2012-07-31 07:27:40 +02:00
|
|
|
else if (Action == LC_ACTION_LIGHT)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
|
|
|
GLint max;
|
|
|
|
int count = 0;
|
|
|
|
Light *pLight;
|
|
|
|
|
|
|
|
glGetIntegerv (GL_MAX_LIGHTS, &max);
|
|
|
|
for (pLight = m_pLights; pLight; pLight = pLight->m_pNext)
|
|
|
|
count++;
|
|
|
|
|
|
|
|
if (count == max)
|
|
|
|
break;
|
|
|
|
|
|
|
|
pLight = new Light (m_fTrack[0], m_fTrack[1], m_fTrack[2]);
|
|
|
|
|
|
|
|
SelectAndFocusNone (false);
|
|
|
|
|
|
|
|
pLight->CreateName(m_pLights);
|
|
|
|
pLight->m_pNext = m_pLights;
|
|
|
|
m_pLights = pLight;
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateFocusObject(pLight);
|
2011-09-07 23:06:51 +02:00
|
|
|
pLight->Select (true, true, false);
|
|
|
|
UpdateSelection ();
|
|
|
|
}
|
|
|
|
|
|
|
|
// AfxGetMainWnd()->PostMessage(WM_LC_UPDATE_INFO, (WPARAM)pNew, OT_PIECE);
|
|
|
|
UpdateSelection();
|
|
|
|
UpdateAllViews();
|
|
|
|
SetModifiedFlag(true);
|
|
|
|
CheckPoint("Inserting");
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_ACTION_SPOTLIGHT:
|
|
|
|
{
|
|
|
|
GLint max;
|
|
|
|
int count = 0;
|
|
|
|
Light *pLight;
|
|
|
|
|
|
|
|
glGetIntegerv (GL_MAX_LIGHTS, &max);
|
|
|
|
for (pLight = m_pLights; pLight; pLight = pLight->m_pNext)
|
|
|
|
count++;
|
|
|
|
|
|
|
|
if (count == max)
|
|
|
|
break;
|
|
|
|
|
2012-05-29 01:33:22 +02:00
|
|
|
lcVector3 tmp = lcUnprojectPoint(lcVector3(x+1.0f, y-1.0f, 0.9f), ModelView, Projection, Viewport);
|
2011-09-07 23:06:51 +02:00
|
|
|
SelectAndFocusNone(false);
|
|
|
|
StartTracking(LC_TRACK_START_LEFT);
|
2012-01-30 08:31:29 +01:00
|
|
|
pLight = new Light (m_fTrack[0], m_fTrack[1], m_fTrack[2], tmp[0], tmp[1], tmp[2]);
|
2011-09-07 23:06:51 +02:00
|
|
|
pLight->GetTarget ()->Select (true, true, false);
|
|
|
|
pLight->m_pNext = m_pLights;
|
|
|
|
m_pLights = pLight;
|
|
|
|
UpdateSelection();
|
|
|
|
UpdateAllViews();
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateFocusObject(pLight);
|
2011-09-07 23:06:51 +02:00
|
|
|
} break;
|
|
|
|
|
2012-08-22 03:13:32 +02:00
|
|
|
case LC_ACTION_CAMERA:
|
|
|
|
{
|
|
|
|
lcVector3 tmp = lcUnprojectPoint(lcVector3(x+1.0f, y-1.0f, 0.9f), ModelView, Projection, Viewport);
|
|
|
|
SelectAndFocusNone(false);
|
|
|
|
StartTracking(LC_TRACK_START_LEFT);
|
|
|
|
|
|
|
|
Camera* NewCamera = new Camera(m_fTrack[0], m_fTrack[1], m_fTrack[2], tmp[0], tmp[1], tmp[2]);
|
|
|
|
NewCamera->GetTarget()->Select (true, true, false);
|
|
|
|
NewCamera->CreateName(mCameras);
|
|
|
|
mCameras.Add(NewCamera);
|
|
|
|
|
|
|
|
UpdateSelection();
|
|
|
|
UpdateAllViews();
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateFocusObject(NewCamera);
|
2012-08-22 03:13:32 +02:00
|
|
|
} break;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
case LC_ACTION_MOVE:
|
|
|
|
{
|
|
|
|
bool sel = false;
|
|
|
|
|
|
|
|
for (Piece* pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
|
|
|
{
|
|
|
|
if (pPiece->IsSelected())
|
|
|
|
{
|
|
|
|
sel = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-22 03:13:32 +02:00
|
|
|
for (int CameraIdx = 0; CameraIdx < mCameras.GetSize() && !sel; CameraIdx++)
|
|
|
|
sel = mCameras[CameraIdx]->IsSelected();
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
if (!sel)
|
|
|
|
{
|
|
|
|
for (Light* pLight = m_pLights; pLight; pLight = pLight->m_pNext)
|
|
|
|
{
|
|
|
|
if (pLight->IsSelected())
|
|
|
|
{
|
|
|
|
sel = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sel)
|
|
|
|
{
|
|
|
|
StartTracking(LC_TRACK_START_LEFT);
|
2012-05-29 01:33:22 +02:00
|
|
|
m_OverlayDelta = lcVector3(0.0f, 0.0f, 0.0f);
|
2012-06-16 02:17:52 +02:00
|
|
|
m_MouseSnapLeftover = lcVector3(0.0f, 0.0f, 0.0f);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_ACTION_ROTATE:
|
|
|
|
{
|
|
|
|
Piece* pPiece;
|
|
|
|
|
|
|
|
for (pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
|
|
|
{
|
|
|
|
if (pPiece->IsSelected())
|
|
|
|
{
|
|
|
|
StartTracking(LC_TRACK_START_LEFT);
|
2012-05-29 01:33:22 +02:00
|
|
|
m_OverlayDelta = lcVector3(0.0f, 0.0f, 0.0f);
|
2011-09-07 23:06:51 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_ACTION_ZOOM_REGION:
|
|
|
|
{
|
|
|
|
m_OverlayTrackStart[0] = (float)x;
|
|
|
|
m_OverlayTrackStart[1] = (float)y;
|
|
|
|
StartTracking(LC_TRACK_START_LEFT);
|
2012-07-31 07:27:40 +02:00
|
|
|
ActivateOverlay(view, m_nCurAction, LC_OVERLAY_NONE);
|
2011-09-07 23:06:51 +02:00
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_ACTION_ZOOM:
|
|
|
|
case LC_ACTION_ROLL:
|
|
|
|
case LC_ACTION_PAN:
|
|
|
|
case LC_ACTION_ROTATE_VIEW:
|
|
|
|
{
|
|
|
|
StartTracking(LC_TRACK_START_LEFT);
|
|
|
|
} break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
void Project::OnLeftButtonDoubleClick(View* view)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2011-09-20 03:26:31 +02:00
|
|
|
if (SetActiveView(view))
|
|
|
|
return;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
int x = view->mInputState.x;
|
|
|
|
int y = view->mInputState.y;
|
|
|
|
bool Control = view->mInputState.Control;
|
|
|
|
|
|
|
|
int Viewport[4] = { 0, 0, view->mWidth, view->mHeight };
|
2012-01-30 08:31:29 +01:00
|
|
|
float Aspect = (float)Viewport[2]/(float)Viewport[3];
|
2012-08-20 06:05:56 +02:00
|
|
|
Camera* Cam = view->mCamera;
|
2012-01-30 08:31:29 +01:00
|
|
|
|
2012-05-29 01:33:22 +02:00
|
|
|
const lcMatrix44& ModelView = Cam->mWorldView;
|
|
|
|
lcMatrix44 Projection = lcMatrix44Perspective(Cam->m_fovy, Aspect, Cam->m_zNear, Cam->m_zFar);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-05-29 01:33:22 +02:00
|
|
|
lcVector3 point = lcUnprojectPoint(lcVector3((float)x, (float)y, 0.9f), ModelView, Projection, Viewport);
|
2012-01-30 08:31:29 +01:00
|
|
|
m_fTrack[0] = point[0]; m_fTrack[1] = point[1]; m_fTrack[2] = point[2];
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-01-30 08:31:29 +01:00
|
|
|
Object* Closest = FindObjectFromPoint(view, x, y);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-01-06 20:24:25 +01:00
|
|
|
// if (m_nCurAction == LC_ACTION_SELECT)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
SelectAndFocusNone(Control);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-01-30 08:31:29 +01:00
|
|
|
if (Closest != NULL)
|
|
|
|
switch (Closest->GetType ())
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
|
|
|
case LC_OBJECT_PIECE:
|
|
|
|
{
|
2012-01-30 08:31:29 +01:00
|
|
|
Piece* pPiece = (Piece*)Closest;
|
2011-09-07 23:06:51 +02:00
|
|
|
pPiece->Select (true, true, false);
|
|
|
|
Group* pGroup = pPiece->GetTopGroup();
|
|
|
|
|
|
|
|
if (pGroup != NULL)
|
|
|
|
for (pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
|
|
|
if (pPiece->GetTopGroup() == pGroup)
|
|
|
|
pPiece->Select (true, false, false);
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_OBJECT_CAMERA:
|
|
|
|
case LC_OBJECT_CAMERA_TARGET:
|
|
|
|
case LC_OBJECT_LIGHT:
|
|
|
|
case LC_OBJECT_LIGHT_TARGET:
|
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
Closest->Select (true, true, Control);
|
2011-09-07 23:06:51 +02:00
|
|
|
} break;
|
|
|
|
}
|
|
|
|
|
|
|
|
UpdateSelection();
|
|
|
|
UpdateAllViews();
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateFocusObject(Closest);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
void Project::OnLeftButtonUp(View* view)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2012-01-28 02:05:23 +01:00
|
|
|
StopTracking(true);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
void Project::OnMiddleButtonDown(View* view)
|
2012-01-28 03:10:19 +01:00
|
|
|
{
|
|
|
|
if (StopTracking(false))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (SetActiveView(view))
|
|
|
|
return;
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
int x = view->mInputState.x;
|
|
|
|
int y = view->mInputState.y;
|
|
|
|
bool Alt = view->mInputState.Alt;
|
|
|
|
|
2012-01-28 03:10:19 +01:00
|
|
|
m_nDownX = x;
|
|
|
|
m_nDownY = y;
|
|
|
|
m_bTrackCancel = false;
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
int Viewport[4] = { 0, 0, view->mWidth, view->mHeight };
|
2012-01-30 08:31:29 +01:00
|
|
|
float Aspect = (float)Viewport[2]/(float)Viewport[3];
|
2012-08-20 06:05:56 +02:00
|
|
|
Camera* Cam = view->mCamera;
|
2012-01-28 03:10:19 +01:00
|
|
|
|
2012-05-29 01:33:22 +02:00
|
|
|
const lcMatrix44& ModelView = Cam->mWorldView;
|
|
|
|
lcMatrix44 Projection = lcMatrix44Perspective(Cam->m_fovy, Aspect, Cam->m_zNear, Cam->m_zFar);
|
2012-01-30 08:31:29 +01:00
|
|
|
|
2012-05-29 01:33:22 +02:00
|
|
|
lcVector3 point = lcUnprojectPoint(lcVector3((float)x, (float)y, 0.9f), ModelView, Projection, Viewport);
|
2012-01-30 08:31:29 +01:00
|
|
|
m_fTrack[0] = point[0]; m_fTrack[1] = point[1]; m_fTrack[2] = point[2];
|
2012-01-28 03:10:19 +01:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
if (Alt)
|
2012-07-31 07:27:40 +02:00
|
|
|
ActivateOverlay(view, LC_ACTION_PAN, LC_OVERLAY_PAN);
|
2012-01-28 03:10:19 +01:00
|
|
|
|
2012-07-31 07:27:40 +02:00
|
|
|
switch (GetAction())
|
2012-01-28 03:10:19 +01:00
|
|
|
{
|
|
|
|
case LC_ACTION_PAN:
|
|
|
|
{
|
|
|
|
StartTracking(LC_TRACK_START_RIGHT);
|
|
|
|
} break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
void Project::OnMiddleButtonUp(View* view)
|
2012-01-28 03:10:19 +01:00
|
|
|
{
|
|
|
|
StopTracking(true);
|
|
|
|
}
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
void Project::OnRightButtonDown(View* view)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
|
|
|
if (StopTracking(false))
|
|
|
|
return;
|
2011-09-20 03:26:31 +02:00
|
|
|
|
|
|
|
if (SetActiveView(view))
|
2011-09-07 23:06:51 +02:00
|
|
|
return;
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
int x = view->mInputState.x;
|
|
|
|
int y = view->mInputState.y;
|
|
|
|
bool Alt = view->mInputState.Alt;
|
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
m_nDownX = x;
|
|
|
|
m_nDownY = y;
|
|
|
|
m_bTrackCancel = false;
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
int Viewport[4] = { 0, 0, view->mWidth, view->mHeight };
|
2012-01-30 08:31:29 +01:00
|
|
|
float Aspect = (float)Viewport[2]/(float)Viewport[3];
|
2012-08-20 06:05:56 +02:00
|
|
|
Camera* Cam = view->mCamera;
|
2012-01-30 08:31:29 +01:00
|
|
|
|
2012-05-29 01:33:22 +02:00
|
|
|
const lcMatrix44& ModelView = Cam->mWorldView;
|
|
|
|
lcMatrix44 Projection = lcMatrix44Perspective(Cam->m_fovy, Aspect, Cam->m_zNear, Cam->m_zFar);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-05-29 01:33:22 +02:00
|
|
|
lcVector3 point = lcUnprojectPoint(lcVector3((float)x, (float)y, 0.9f), ModelView, Projection, Viewport);
|
2012-01-30 08:31:29 +01:00
|
|
|
m_fTrack[0] = point[0]; m_fTrack[1] = point[1]; m_fTrack[2] = point[2];
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
if (Alt)
|
2012-07-31 07:27:40 +02:00
|
|
|
ActivateOverlay(view, LC_ACTION_ZOOM, LC_OVERLAY_ZOOM);
|
2012-01-28 03:10:19 +01:00
|
|
|
|
2012-07-31 07:27:40 +02:00
|
|
|
switch (GetAction())
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
|
|
|
case LC_ACTION_MOVE:
|
|
|
|
{
|
|
|
|
bool sel = false;
|
|
|
|
|
|
|
|
for (Piece* pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
|
|
|
if (pPiece->IsSelected())
|
|
|
|
{
|
|
|
|
sel = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2012-08-22 03:13:32 +02:00
|
|
|
for (int CameraIdx = 0; CameraIdx < mCameras.GetSize() && !sel; CameraIdx++)
|
|
|
|
sel = mCameras[CameraIdx]->IsSelected();
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
if (!sel)
|
|
|
|
for (Light* pLight = m_pLights; pLight; pLight = pLight->m_pNext)
|
|
|
|
if (pLight->IsSelected())
|
|
|
|
{
|
|
|
|
sel = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sel)
|
2012-08-22 03:13:32 +02:00
|
|
|
{
|
2011-09-07 23:06:51 +02:00
|
|
|
StartTracking(LC_TRACK_START_RIGHT);
|
2012-08-22 03:13:32 +02:00
|
|
|
m_fTrack[0] = m_fTrack[1] = m_fTrack[2] = 0.0f;
|
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_ACTION_ROTATE:
|
|
|
|
{
|
|
|
|
Piece* pPiece;
|
|
|
|
|
|
|
|
for (pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
|
|
|
if (pPiece->IsSelected())
|
|
|
|
{
|
|
|
|
StartTracking(LC_TRACK_START_RIGHT);
|
2012-08-22 03:13:32 +02:00
|
|
|
m_fTrack[0] = m_fTrack[1] = m_fTrack[2] = 0.0f;
|
2011-09-07 23:06:51 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
} break;
|
2012-01-28 03:10:19 +01:00
|
|
|
|
|
|
|
case LC_ACTION_ZOOM:
|
|
|
|
{
|
|
|
|
StartTracking(LC_TRACK_START_RIGHT);
|
|
|
|
} break;
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
void Project::OnRightButtonUp(View* view)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
|
|
|
if (!StopTracking(true) && !m_bTrackCancel)
|
2013-08-09 06:57:18 +02:00
|
|
|
view->ShowPopupMenu();
|
2011-09-07 23:06:51 +02:00
|
|
|
m_bTrackCancel = false;
|
|
|
|
}
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
void Project::OnMouseMove(View* view)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
int x = view->mInputState.x;
|
|
|
|
int y = view->mInputState.y;
|
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
if ((m_nTracking == LC_TRACK_NONE) && (m_nCurAction != LC_ACTION_INSERT))
|
|
|
|
{
|
|
|
|
if (m_OverlayActive)
|
2012-02-01 03:08:30 +01:00
|
|
|
MouseUpdateOverlays(view, x, y);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_nTracking == LC_TRACK_START_RIGHT)
|
|
|
|
m_nTracking = LC_TRACK_RIGHT;
|
|
|
|
|
|
|
|
if (m_nTracking == LC_TRACK_START_LEFT)
|
|
|
|
m_nTracking = LC_TRACK_LEFT;
|
|
|
|
|
|
|
|
float ptx, pty, ptz;
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
int Viewport[4] = { 0, 0, view->mWidth, view->mHeight };
|
2012-01-30 08:31:29 +01:00
|
|
|
float Aspect = (float)Viewport[2]/(float)Viewport[3];
|
2012-08-20 06:05:56 +02:00
|
|
|
Camera* Cam = view->mCamera;
|
2012-01-30 08:31:29 +01:00
|
|
|
|
2012-05-29 01:33:22 +02:00
|
|
|
const lcMatrix44& ModelView = Cam->mWorldView;
|
|
|
|
lcMatrix44 Projection = lcMatrix44Perspective(Cam->m_fovy, Aspect, Cam->m_zNear, Cam->m_zFar);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-05-29 01:33:22 +02:00
|
|
|
lcVector3 tmp = lcUnprojectPoint(lcVector3((float)x, (float)y, 0.9f), ModelView, Projection, Viewport);
|
2012-01-30 08:31:29 +01:00
|
|
|
ptx = tmp[0]; pty = tmp[1]; ptz = tmp[2];
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-07-31 07:27:40 +02:00
|
|
|
switch (GetAction())
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
|
|
|
case LC_ACTION_SELECT:
|
|
|
|
{
|
2013-02-13 00:36:30 +01:00
|
|
|
int ClampX = x, ClampY = y;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-02-13 00:36:30 +01:00
|
|
|
if (ClampX >= Viewport[0] + Viewport[2])
|
|
|
|
ClampX = Viewport[0] + Viewport[2] - 1;
|
|
|
|
else if (ClampX <= Viewport[0])
|
|
|
|
ClampX = Viewport[0] + 1;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-02-13 00:36:30 +01:00
|
|
|
if (ClampY >= Viewport[1] + Viewport[3])
|
|
|
|
ClampY = Viewport[1] + Viewport[3] - 1;
|
|
|
|
else if (ClampY <= Viewport[1])
|
|
|
|
ClampY = Viewport[1] + 1;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-02-13 00:36:30 +01:00
|
|
|
m_fTrack[0] = (float)ClampX;
|
|
|
|
m_fTrack[1] = (float)ClampY;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-07-31 07:27:40 +02:00
|
|
|
if (m_nTracking != LC_TRACK_NONE)
|
2013-04-10 02:56:51 +02:00
|
|
|
{
|
|
|
|
ActivateOverlay(view, m_nCurAction, LC_OVERLAY_NONE);
|
2012-07-31 07:27:40 +02:00
|
|
|
UpdateOverlayScale();
|
2013-04-10 02:56:51 +02:00
|
|
|
}
|
2012-07-31 07:27:40 +02:00
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
UpdateAllViews();
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_ACTION_INSERT:
|
|
|
|
{
|
|
|
|
if (m_nDownX != x || m_nDownY != y)
|
|
|
|
{
|
|
|
|
m_nDownX = x;
|
|
|
|
m_nDownY = y;
|
|
|
|
|
|
|
|
UpdateAllViews();
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_ACTION_SPOTLIGHT:
|
|
|
|
{
|
|
|
|
float mouse = 10.0f/(21 - m_nMouse);
|
|
|
|
float delta[3] = { (ptx - m_fTrack[0])*mouse,
|
|
|
|
(pty - m_fTrack[1])*mouse, (ptz - m_fTrack[2])*mouse };
|
|
|
|
|
|
|
|
m_fTrack[0] = ptx;
|
|
|
|
m_fTrack[1] = pty;
|
|
|
|
m_fTrack[2] = ptz;
|
2013-01-06 20:24:25 +01:00
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
Light* pLight = m_pLights;
|
|
|
|
|
|
|
|
pLight->Move (1, m_bAnimation, false, delta[0], delta[1], delta[2]);
|
|
|
|
pLight->UpdatePosition (1, m_bAnimation);
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateFocusObject(pLight);
|
2011-09-07 23:06:51 +02:00
|
|
|
UpdateAllViews();
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_ACTION_CAMERA:
|
|
|
|
{
|
|
|
|
float mouse = 10.0f/(21 - m_nMouse);
|
|
|
|
float delta[3] = { (ptx - m_fTrack[0])*mouse,
|
|
|
|
(pty - m_fTrack[1])*mouse, (ptz - m_fTrack[2])*mouse };
|
|
|
|
|
|
|
|
m_fTrack[0] = ptx;
|
|
|
|
m_fTrack[1] = pty;
|
|
|
|
m_fTrack[2] = ptz;
|
2013-01-06 20:24:25 +01:00
|
|
|
|
2012-08-22 03:13:32 +02:00
|
|
|
Camera* pCamera = mCameras[mCameras.GetSize() - 1];
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-08-22 03:13:32 +02:00
|
|
|
pCamera->Move(1, m_bAnimation, false, delta[0], delta[1], delta[2]);
|
2011-09-07 23:06:51 +02:00
|
|
|
pCamera->UpdatePosition(1, m_bAnimation);
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateFocusObject(pCamera);
|
2011-09-07 23:06:51 +02:00
|
|
|
UpdateAllViews();
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_ACTION_MOVE:
|
|
|
|
{
|
|
|
|
// Check if the mouse moved since the last update.
|
|
|
|
if ((x == m_nDownX) && (y == m_nDownY))
|
|
|
|
break;
|
|
|
|
|
2012-08-20 06:05:56 +02:00
|
|
|
Camera* Camera = view->mCamera;
|
2011-09-07 23:06:51 +02:00
|
|
|
bool Redraw;
|
|
|
|
|
2012-07-31 07:27:40 +02:00
|
|
|
if ((m_OverlayActive && (m_OverlayMode != LC_OVERLAY_MOVE_XYZ)) || (!Camera->IsSide()))
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2012-06-16 02:17:52 +02:00
|
|
|
lcVector3 ScreenX = lcNormalize(lcCross(Camera->mTargetPosition - Camera->mPosition, Camera->mUpVector));
|
|
|
|
lcVector3 ScreenY = Camera->mUpVector;
|
2012-11-02 02:17:42 +01:00
|
|
|
lcVector3 Dir1(0.0f, 0.0f, 0.0f), Dir2(0.0f, 0.0f, 0.0f);
|
2011-09-07 23:06:51 +02:00
|
|
|
bool SingleDir = true;
|
|
|
|
|
|
|
|
int OverlayMode;
|
|
|
|
|
2012-07-31 07:27:40 +02:00
|
|
|
if (m_OverlayActive && (m_OverlayMode != LC_OVERLAY_MOVE_XYZ))
|
2011-09-07 23:06:51 +02:00
|
|
|
OverlayMode = m_OverlayMode;
|
|
|
|
else if (m_nTracking == LC_TRACK_LEFT)
|
2012-07-31 07:27:40 +02:00
|
|
|
OverlayMode = LC_OVERLAY_MOVE_XY;
|
2011-09-07 23:06:51 +02:00
|
|
|
else
|
2012-07-31 07:27:40 +02:00
|
|
|
OverlayMode = LC_OVERLAY_MOVE_Z;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
switch (OverlayMode)
|
|
|
|
{
|
2012-07-31 07:27:40 +02:00
|
|
|
case LC_OVERLAY_MOVE_X:
|
2012-06-16 02:17:52 +02:00
|
|
|
Dir1 = lcVector3(1, 0, 0);
|
2011-09-07 23:06:51 +02:00
|
|
|
break;
|
2012-07-31 07:27:40 +02:00
|
|
|
case LC_OVERLAY_MOVE_Y:
|
2012-06-16 02:17:52 +02:00
|
|
|
Dir1 = lcVector3(0, 1, 0);
|
2011-09-07 23:06:51 +02:00
|
|
|
break;
|
2012-07-31 07:27:40 +02:00
|
|
|
case LC_OVERLAY_MOVE_Z:
|
2012-06-16 02:17:52 +02:00
|
|
|
Dir1 = lcVector3(0, 0, 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
break;
|
2012-07-31 07:27:40 +02:00
|
|
|
case LC_OVERLAY_MOVE_XY:
|
2012-06-16 02:17:52 +02:00
|
|
|
Dir1 = lcVector3(1, 0, 0);
|
|
|
|
Dir2 = lcVector3(0, 1, 0);
|
2011-09-07 23:06:51 +02:00
|
|
|
SingleDir = false;
|
|
|
|
break;
|
2012-07-31 07:27:40 +02:00
|
|
|
case LC_OVERLAY_MOVE_XZ:
|
2012-06-16 02:17:52 +02:00
|
|
|
Dir1 = lcVector3(1, 0, 0);
|
|
|
|
Dir2 = lcVector3(0, 0, 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
SingleDir = false;
|
|
|
|
break;
|
2012-07-31 07:27:40 +02:00
|
|
|
case LC_OVERLAY_MOVE_YZ:
|
2012-06-16 02:17:52 +02:00
|
|
|
Dir1 = lcVector3(0, 1, 0);
|
|
|
|
Dir2 = lcVector3(0, 0, 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
SingleDir = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Transform the translation axis.
|
2012-06-16 02:17:52 +02:00
|
|
|
lcVector3 Axis1 = Dir1;
|
|
|
|
lcVector3 Axis2 = Dir2;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
if ((m_nSnap & LC_DRAW_GLOBAL_SNAP) == 0)
|
|
|
|
{
|
|
|
|
Object* Focus = GetFocusObject();
|
|
|
|
|
|
|
|
if ((Focus != NULL) && Focus->IsPiece())
|
|
|
|
{
|
2012-06-16 02:17:52 +02:00
|
|
|
const lcMatrix44& ModelWorld = ((Piece*)Focus)->mModelWorld;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-06-16 02:17:52 +02:00
|
|
|
Axis1 = lcMul30(Dir1, ModelWorld);
|
|
|
|
Axis2 = lcMul30(Dir2, ModelWorld);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Find out what direction the mouse is going to move stuff.
|
2012-06-16 02:17:52 +02:00
|
|
|
lcVector3 MoveX, MoveY;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
if (SingleDir)
|
|
|
|
{
|
2012-06-16 02:17:52 +02:00
|
|
|
float dx1 = lcDot(ScreenX, Axis1);
|
|
|
|
float dy1 = lcDot(ScreenY, Axis1);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
if (fabsf(dx1) > fabsf(dy1))
|
|
|
|
{
|
|
|
|
if (dx1 >= 0.0f)
|
|
|
|
MoveX = Dir1;
|
|
|
|
else
|
|
|
|
MoveX = -Dir1;
|
|
|
|
|
2012-06-16 02:17:52 +02:00
|
|
|
MoveY = lcVector3(0, 0, 0);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-06-16 02:17:52 +02:00
|
|
|
MoveX = lcVector3(0, 0, 0);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
if (dy1 > 0.0f)
|
|
|
|
MoveY = Dir1;
|
|
|
|
else
|
|
|
|
MoveY = -Dir1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-06-16 02:17:52 +02:00
|
|
|
float dx1 = lcDot(ScreenX, Axis1);
|
|
|
|
float dy1 = lcDot(ScreenY, Axis1);
|
|
|
|
float dx2 = lcDot(ScreenX, Axis2);
|
|
|
|
float dy2 = lcDot(ScreenY, Axis2);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
if (fabsf(dx1) > fabsf(dx2))
|
|
|
|
{
|
|
|
|
if (dx1 >= 0.0f)
|
|
|
|
MoveX = Dir1;
|
|
|
|
else
|
|
|
|
MoveX = -Dir1;
|
|
|
|
|
|
|
|
if (dy2 >= 0.0f)
|
|
|
|
MoveY = Dir2;
|
|
|
|
else
|
|
|
|
MoveY = -Dir2;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (dx2 >= 0.0f)
|
|
|
|
MoveX = Dir2;
|
|
|
|
else
|
|
|
|
MoveX = -Dir2;
|
|
|
|
|
|
|
|
if (dy1 > 0.0f)
|
|
|
|
MoveY = Dir1;
|
|
|
|
else
|
|
|
|
MoveY = -Dir1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
MoveX *= (float)(x - m_nDownX) * 0.25f / (21 - m_nMouse);
|
|
|
|
MoveY *= (float)(y - m_nDownY) * 0.25f / (21 - m_nMouse);
|
|
|
|
|
|
|
|
m_nDownX = x;
|
|
|
|
m_nDownY = y;
|
|
|
|
|
2012-06-16 02:17:52 +02:00
|
|
|
lcVector3 Delta = MoveX + MoveY + m_MouseSnapLeftover;
|
2012-08-13 02:28:35 +02:00
|
|
|
Redraw = MoveSelectedObjects(Delta, m_MouseSnapLeftover, true, true);
|
2011-09-07 23:06:51 +02:00
|
|
|
m_MouseTotalDelta += Delta;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// 3D movement.
|
2012-06-16 02:17:52 +02:00
|
|
|
lcVector3 ScreenZ = lcNormalize(Camera->mTargetPosition - Camera->mPosition);
|
|
|
|
lcVector3 ScreenX = lcCross(ScreenZ, Camera->mUpVector);
|
|
|
|
lcVector3 ScreenY = Camera->mUpVector;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-06-16 02:17:52 +02:00
|
|
|
lcVector3 TotalMove;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
if (m_nTracking == LC_TRACK_LEFT)
|
|
|
|
{
|
2012-06-16 02:17:52 +02:00
|
|
|
lcVector3 MoveX, MoveY;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
MoveX = ScreenX * (float)(x - m_nDownX) * 0.25f / (float)(21 - m_nMouse);
|
|
|
|
MoveY = ScreenY * (float)(y - m_nDownY) * 0.25f / (float)(21 - m_nMouse);
|
|
|
|
|
|
|
|
TotalMove = MoveX + MoveY + m_MouseSnapLeftover;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-06-16 02:17:52 +02:00
|
|
|
lcVector3 MoveZ;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
MoveZ = ScreenZ * (float)(y - m_nDownY) * 0.25f / (float)(21 - m_nMouse);
|
|
|
|
|
|
|
|
TotalMove = MoveZ + m_MouseSnapLeftover;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_nDownX = x;
|
|
|
|
m_nDownY = y;
|
|
|
|
|
2012-08-13 02:28:35 +02:00
|
|
|
Redraw = MoveSelectedObjects(TotalMove, m_MouseSnapLeftover, true, true);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateFocusObject(GetFocusObject());
|
2012-07-31 07:27:40 +02:00
|
|
|
|
|
|
|
if (m_nTracking != LC_TRACK_NONE)
|
|
|
|
UpdateOverlayScale();
|
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
if (Redraw)
|
|
|
|
UpdateAllViews();
|
|
|
|
} break;
|
2013-01-06 20:24:25 +01:00
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
case LC_ACTION_ROTATE:
|
|
|
|
{
|
2012-08-20 06:05:56 +02:00
|
|
|
Camera* Camera = m_ActiveView->mCamera;
|
2011-09-07 23:06:51 +02:00
|
|
|
bool Redraw;
|
|
|
|
|
2012-07-31 07:27:40 +02:00
|
|
|
if ((m_OverlayActive && (m_OverlayMode != LC_OVERLAY_ROTATE_XYZ)) || (!Camera->IsSide()))
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2012-06-16 02:17:52 +02:00
|
|
|
lcVector3 ScreenX = lcNormalize(lcCross(Camera->mTargetPosition - Camera->mPosition, Camera->mUpVector));
|
|
|
|
lcVector3 ScreenY = Camera->mUpVector;
|
|
|
|
lcVector3 Dir1, Dir2;
|
2011-09-07 23:06:51 +02:00
|
|
|
bool SingleDir = true;
|
|
|
|
|
|
|
|
int OverlayMode;
|
|
|
|
|
2012-07-31 07:27:40 +02:00
|
|
|
if (m_OverlayActive && (m_OverlayMode != LC_OVERLAY_ROTATE_XYZ))
|
2011-09-07 23:06:51 +02:00
|
|
|
OverlayMode = m_OverlayMode;
|
|
|
|
else if (m_nTracking == LC_TRACK_LEFT)
|
2012-07-31 07:27:40 +02:00
|
|
|
OverlayMode = LC_OVERLAY_ROTATE_XY;
|
2011-09-07 23:06:51 +02:00
|
|
|
else
|
2012-07-31 07:27:40 +02:00
|
|
|
OverlayMode = LC_OVERLAY_ROTATE_Z;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
switch (OverlayMode)
|
|
|
|
{
|
2012-07-31 07:27:40 +02:00
|
|
|
case LC_OVERLAY_ROTATE_X:
|
2012-06-16 02:17:52 +02:00
|
|
|
Dir1 = lcVector3(1, 0, 0);
|
2011-09-07 23:06:51 +02:00
|
|
|
break;
|
2012-07-31 07:27:40 +02:00
|
|
|
case LC_OVERLAY_ROTATE_Y:
|
2012-06-16 02:17:52 +02:00
|
|
|
Dir1 = lcVector3(0, 1, 0);
|
2011-09-07 23:06:51 +02:00
|
|
|
break;
|
2012-07-31 07:27:40 +02:00
|
|
|
case LC_OVERLAY_ROTATE_Z:
|
2012-06-16 02:17:52 +02:00
|
|
|
Dir1 = lcVector3(0, 0, 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
break;
|
2012-07-31 07:27:40 +02:00
|
|
|
case LC_OVERLAY_ROTATE_XY:
|
2012-06-16 02:17:52 +02:00
|
|
|
Dir1 = lcVector3(1, 0, 0);
|
|
|
|
Dir2 = lcVector3(0, 1, 0);
|
2011-09-07 23:06:51 +02:00
|
|
|
SingleDir = false;
|
|
|
|
break;
|
2012-07-31 07:27:40 +02:00
|
|
|
case LC_OVERLAY_ROTATE_XZ:
|
2012-06-16 02:17:52 +02:00
|
|
|
Dir1 = lcVector3(1, 0, 0);
|
|
|
|
Dir2 = lcVector3(0, 0, 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
SingleDir = false;
|
|
|
|
break;
|
2012-07-31 07:27:40 +02:00
|
|
|
case LC_OVERLAY_ROTATE_YZ:
|
2012-06-16 02:17:52 +02:00
|
|
|
Dir1 = lcVector3(0, 1, 0);
|
|
|
|
Dir2 = lcVector3(0, 0, 1);
|
2011-09-07 23:06:51 +02:00
|
|
|
SingleDir = false;
|
|
|
|
break;
|
2012-06-22 00:03:30 +02:00
|
|
|
default:
|
|
|
|
Dir1 = lcVector3(1, 0, 0);
|
|
|
|
break;
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Find out what direction the mouse is going to move stuff.
|
2012-06-16 02:17:52 +02:00
|
|
|
lcVector3 MoveX, MoveY;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
if (SingleDir)
|
|
|
|
{
|
2012-06-16 02:17:52 +02:00
|
|
|
float dx1 = lcDot(ScreenX, Dir1);
|
|
|
|
float dy1 = lcDot(ScreenY, Dir1);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
if (fabsf(dx1) > fabsf(dy1))
|
|
|
|
{
|
|
|
|
if (dx1 >= 0.0f)
|
|
|
|
MoveX = Dir1;
|
|
|
|
else
|
|
|
|
MoveX = -Dir1;
|
|
|
|
|
2012-06-16 02:17:52 +02:00
|
|
|
MoveY = lcVector3(0, 0, 0);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-06-16 02:17:52 +02:00
|
|
|
MoveX = lcVector3(0, 0, 0);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
if (dy1 > 0.0f)
|
|
|
|
MoveY = Dir1;
|
|
|
|
else
|
|
|
|
MoveY = -Dir1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-06-16 02:17:52 +02:00
|
|
|
float dx1 = lcDot(ScreenX, Dir1);
|
|
|
|
float dy1 = lcDot(ScreenY, Dir1);
|
|
|
|
float dx2 = lcDot(ScreenX, Dir2);
|
|
|
|
float dy2 = lcDot(ScreenY, Dir2);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
if (fabsf(dx1) > fabsf(dx2))
|
|
|
|
{
|
|
|
|
if (dx1 >= 0.0f)
|
|
|
|
MoveX = Dir1;
|
|
|
|
else
|
|
|
|
MoveX = -Dir1;
|
|
|
|
|
|
|
|
if (dy2 >= 0.0f)
|
|
|
|
MoveY = Dir2;
|
|
|
|
else
|
|
|
|
MoveY = -Dir2;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (dx2 >= 0.0f)
|
|
|
|
MoveX = Dir2;
|
|
|
|
else
|
|
|
|
MoveX = -Dir2;
|
|
|
|
|
|
|
|
if (dy1 > 0.0f)
|
|
|
|
MoveY = Dir1;
|
|
|
|
else
|
|
|
|
MoveY = -Dir1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
MoveX *= (float)(x - m_nDownX) * 36.0f / (21 - m_nMouse);
|
|
|
|
MoveY *= (float)(y - m_nDownY) * 36.0f / (21 - m_nMouse);
|
|
|
|
|
|
|
|
m_nDownX = x;
|
|
|
|
m_nDownY = y;
|
|
|
|
|
2012-06-16 02:17:52 +02:00
|
|
|
lcVector3 Delta = MoveX + MoveY + m_MouseSnapLeftover;
|
2012-08-13 02:28:35 +02:00
|
|
|
Redraw = RotateSelectedObjects(Delta, m_MouseSnapLeftover, true, true);
|
2011-09-07 23:06:51 +02:00
|
|
|
m_MouseTotalDelta += Delta;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// 3D movement.
|
2012-06-16 02:17:52 +02:00
|
|
|
lcVector3 ScreenZ = lcNormalize(Camera->mTargetPosition - Camera->mPosition);
|
|
|
|
lcVector3 ScreenX = lcCross(ScreenZ, Camera->mUpVector);
|
|
|
|
lcVector3 ScreenY = Camera->mUpVector;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-06-16 02:17:52 +02:00
|
|
|
lcVector3 Delta;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
if (m_nTracking == LC_TRACK_LEFT)
|
|
|
|
{
|
2012-06-16 02:17:52 +02:00
|
|
|
lcVector3 MoveX, MoveY;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
MoveX = ScreenX * (float)(x - m_nDownX) * 36.0f / (float)(21 - m_nMouse);
|
|
|
|
MoveY = ScreenY * (float)(y - m_nDownY) * 36.0f / (float)(21 - m_nMouse);
|
|
|
|
|
|
|
|
Delta = MoveX + MoveY + m_MouseSnapLeftover;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-06-16 02:17:52 +02:00
|
|
|
lcVector3 MoveZ;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
MoveZ = ScreenZ * (float)(y - m_nDownY) * 36.0f / (float)(21 - m_nMouse);
|
|
|
|
|
|
|
|
Delta = MoveZ + m_MouseSnapLeftover;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_nDownX = x;
|
|
|
|
m_nDownY = y;
|
|
|
|
|
2012-08-13 02:28:35 +02:00
|
|
|
Redraw = RotateSelectedObjects(Delta, m_MouseSnapLeftover, true, true);
|
2011-09-07 23:06:51 +02:00
|
|
|
m_MouseTotalDelta += Delta;
|
|
|
|
}
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateFocusObject(GetFocusObject());
|
2011-09-07 23:06:51 +02:00
|
|
|
if (Redraw)
|
|
|
|
UpdateAllViews();
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_ACTION_ZOOM:
|
|
|
|
{
|
|
|
|
if (m_nDownY == y)
|
|
|
|
break;
|
|
|
|
|
2012-08-20 06:05:56 +02:00
|
|
|
m_ActiveView->mCamera->DoZoom(y - m_nDownY, m_nMouse, m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation, m_bAddKeys);
|
2011-09-07 23:06:51 +02:00
|
|
|
m_nDownY = y;
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateFocusObject(GetFocusObject());
|
2011-09-07 23:06:51 +02:00
|
|
|
UpdateAllViews();
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_ACTION_ZOOM_REGION:
|
|
|
|
{
|
|
|
|
if ((m_nDownY == y) && (m_nDownX == x))
|
|
|
|
break;
|
|
|
|
|
|
|
|
m_nDownX = x;
|
|
|
|
m_nDownY = y;
|
|
|
|
UpdateAllViews();
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case LC_ACTION_PAN:
|
|
|
|
{
|
|
|
|
if ((m_nDownY == y) && (m_nDownX == x))
|
|
|
|
break;
|
|
|
|
|
2012-08-20 06:05:56 +02:00
|
|
|
m_ActiveView->mCamera->DoPan(x - m_nDownX, y - m_nDownY, m_nMouse, m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation, m_bAddKeys);
|
2011-09-07 23:06:51 +02:00
|
|
|
m_nDownX = x;
|
|
|
|
m_nDownY = y;
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateFocusObject(GetFocusObject());
|
2011-09-07 23:06:51 +02:00
|
|
|
UpdateAllViews();
|
|
|
|
} break;
|
2013-01-06 20:24:25 +01:00
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
case LC_ACTION_ROTATE_VIEW:
|
|
|
|
{
|
|
|
|
if ((m_nDownY == y) && (m_nDownX == x))
|
|
|
|
break;
|
|
|
|
|
|
|
|
float bs[6] = { 10000, 10000, 10000, -10000, -10000, -10000 };
|
|
|
|
for (Piece* pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
|
|
|
if (pPiece->IsSelected())
|
|
|
|
pPiece->CompareBoundingBox(bs);
|
|
|
|
bs[0] = (bs[0]+bs[3])/2;
|
|
|
|
bs[1] = (bs[1]+bs[4])/2;
|
|
|
|
bs[2] = (bs[2]+bs[5])/2;
|
|
|
|
|
|
|
|
switch (m_OverlayMode)
|
|
|
|
{
|
2012-07-31 07:27:40 +02:00
|
|
|
case LC_OVERLAY_ROTATE_VIEW_XYZ:
|
2012-08-20 06:05:56 +02:00
|
|
|
m_ActiveView->mCamera->DoRotate(x - m_nDownX, y - m_nDownY, m_nMouse, m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation, m_bAddKeys, bs);
|
2011-09-07 23:06:51 +02:00
|
|
|
break;
|
|
|
|
|
2012-07-31 07:27:40 +02:00
|
|
|
case LC_OVERLAY_ROTATE_VIEW_X:
|
2012-08-20 06:05:56 +02:00
|
|
|
m_ActiveView->mCamera->DoRotate(x - m_nDownX, 0, m_nMouse, m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation, m_bAddKeys, bs);
|
2011-09-07 23:06:51 +02:00
|
|
|
break;
|
|
|
|
|
2012-07-31 07:27:40 +02:00
|
|
|
case LC_OVERLAY_ROTATE_VIEW_Y:
|
2012-08-20 06:05:56 +02:00
|
|
|
m_ActiveView->mCamera->DoRotate(0, y - m_nDownY, m_nMouse, m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation, m_bAddKeys, bs);
|
2011-09-07 23:06:51 +02:00
|
|
|
break;
|
|
|
|
|
2012-07-31 07:27:40 +02:00
|
|
|
case LC_OVERLAY_ROTATE_VIEW_Z:
|
2012-08-20 06:05:56 +02:00
|
|
|
m_ActiveView->mCamera->DoRoll(x - m_nDownX, m_nMouse, m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation, m_bAddKeys);
|
2011-09-07 23:06:51 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_nDownX = x;
|
|
|
|
m_nDownY = y;
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateFocusObject(GetFocusObject());
|
2011-09-07 23:06:51 +02:00
|
|
|
UpdateAllViews();
|
|
|
|
} break;
|
2013-01-06 20:24:25 +01:00
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
case LC_ACTION_ROLL:
|
|
|
|
{
|
|
|
|
if (m_nDownX == x)
|
|
|
|
break;
|
|
|
|
|
2012-08-20 06:05:56 +02:00
|
|
|
m_ActiveView->mCamera->DoRoll(x - m_nDownX, m_nMouse, m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation, m_bAddKeys);
|
2011-09-07 23:06:51 +02:00
|
|
|
m_nDownX = x;
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateFocusObject(GetFocusObject());
|
2011-09-07 23:06:51 +02:00
|
|
|
UpdateAllViews();
|
|
|
|
} break;
|
|
|
|
/*
|
|
|
|
case LC_ACTION_CURVE:
|
|
|
|
{
|
|
|
|
float mouse = 10.0f/(21 - m_nMouse);
|
|
|
|
float dx = (ptx - m_fTrack[0])*mouse;
|
|
|
|
float dy = (pty - m_fTrack[1])*mouse;
|
|
|
|
float dz = (ptz - m_fTrack[2])*mouse;
|
|
|
|
Object *pObj = NULL;
|
|
|
|
Curve *pCurve;
|
|
|
|
|
|
|
|
m_fTrack[0] = ptx;
|
|
|
|
m_fTrack[1] = pty;
|
|
|
|
m_fTrack[2] = ptz;
|
|
|
|
|
|
|
|
for (pObj = m_pObjects; pObj != NULL; pObj = pObj->m_pNext)
|
|
|
|
if (pObj->IsSelected ())
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (pObj == NULL)
|
|
|
|
break;
|
|
|
|
pCurve = (Curve*)pObj;
|
|
|
|
|
|
|
|
pCurve->Move (1, m_bAnimation, false, dx, dy, dz);
|
|
|
|
pCurve->UpdatePosition(1, m_bAnimation);
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
gMainWindow->UpdateFocusObject(GetFocusObject());
|
2011-09-07 23:06:51 +02:00
|
|
|
UpdateAllViews();
|
|
|
|
} break;
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
void Project::OnMouseWheel(View* view, float Direction)
|
2013-01-28 20:57:33 +01:00
|
|
|
{
|
2013-08-09 06:57:18 +02:00
|
|
|
ZoomActiveView((int)(10 * Direction));
|
2013-01-28 20:57:33 +01:00
|
|
|
}
|
|
|
|
|
2011-09-07 23:06:51 +02:00
|
|
|
// Check if the mouse is over a different area of the overlay and redraw it.
|
2012-02-01 03:08:30 +01:00
|
|
|
void Project::MouseUpdateOverlays(View* view, int x, int y)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2012-02-05 03:50:57 +01:00
|
|
|
const float OverlayScale = view->m_OverlayScale;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-07-31 07:27:40 +02:00
|
|
|
if (m_nCurAction == LC_ACTION_SELECT || m_nCurAction == LC_ACTION_MOVE)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2012-07-31 07:27:40 +02:00
|
|
|
const float OverlayMovePlaneSize = 0.5f * OverlayScale;
|
|
|
|
const float OverlayMoveArrowSize = 1.5f * OverlayScale;
|
|
|
|
const float OverlayMoveArrowCapRadius = 0.1f * OverlayScale;
|
|
|
|
const float OverlayRotateArrowStart = 1.0f * OverlayScale;
|
|
|
|
const float OverlayRotateArrowEnd = 1.5f * OverlayScale;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-08-09 06:57:18 +02:00
|
|
|
int Viewport[4] = { 0, 0, view->mWidth, view->mHeight };
|
2012-02-01 03:13:58 +01:00
|
|
|
float Aspect = (float)Viewport[2]/(float)Viewport[3];
|
2012-08-20 06:05:56 +02:00
|
|
|
Camera* Cam = view->mCamera;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-05-29 01:33:22 +02:00
|
|
|
const lcMatrix44& ModelView = Cam->mWorldView;
|
|
|
|
lcMatrix44 Projection = lcMatrix44Perspective(Cam->m_fovy, Aspect, Cam->m_zNear, Cam->m_zFar);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-07-31 07:27:40 +02:00
|
|
|
// Intersect the mouse with the 3 planes.
|
|
|
|
lcVector3 PlaneNormals[3] =
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2012-07-31 07:27:40 +02:00
|
|
|
lcVector3(1.0f, 0.0f, 0.0f),
|
|
|
|
lcVector3(0.0f, 1.0f, 0.0f),
|
|
|
|
lcVector3(0.0f, 0.0f, 1.0f),
|
2011-09-07 23:06:51 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
// Find the rotation from the focused piece if relative snap is enabled.
|
|
|
|
if ((m_nSnap & LC_DRAW_GLOBAL_SNAP) == 0)
|
|
|
|
{
|
|
|
|
Object* Focus = GetFocusObject();
|
|
|
|
|
|
|
|
if ((Focus != NULL) && Focus->IsPiece())
|
|
|
|
{
|
2012-05-29 01:33:22 +02:00
|
|
|
const lcMatrix44& RotMat = ((Piece*)Focus)->mModelWorld;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-07-31 07:27:40 +02:00
|
|
|
for (int i = 0; i < 3; i++)
|
|
|
|
PlaneNormals[i] = lcMul30(PlaneNormals[i], RotMat);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-31 07:27:40 +02:00
|
|
|
int Mode = (m_nCurAction == LC_ACTION_MOVE) ? LC_OVERLAY_MOVE_XYZ : LC_OVERLAY_NONE;
|
|
|
|
lcVector3 Start = lcUnprojectPoint(lcVector3((float)x, (float)y, 0.0f), ModelView, Projection, Viewport);
|
|
|
|
lcVector3 End = lcUnprojectPoint(lcVector3((float)x, (float)y, 1.0f), ModelView, Projection, Viewport);
|
|
|
|
float ClosestIntersectionDistance = FLT_MAX;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-07-31 07:27:40 +02:00
|
|
|
for (int AxisIndex = 0; AxisIndex < 3; AxisIndex++)
|
2012-05-29 01:33:22 +02:00
|
|
|
{
|
2012-07-31 07:27:40 +02:00
|
|
|
lcVector4 Plane(PlaneNormals[AxisIndex], -lcDot(PlaneNormals[AxisIndex], m_OverlayCenter));
|
|
|
|
lcVector3 Intersection;
|
2012-07-21 01:15:53 +02:00
|
|
|
|
2012-07-31 07:27:40 +02:00
|
|
|
if (!lcLinePlaneIntersection(&Intersection, Start, End, Plane))
|
|
|
|
continue;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-07-31 07:27:40 +02:00
|
|
|
float IntersectionDistance = lcLengthSquared(Intersection - Start);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-07-31 07:27:40 +02:00
|
|
|
if (IntersectionDistance > ClosestIntersectionDistance)
|
2011-09-07 23:06:51 +02:00
|
|
|
continue;
|
|
|
|
|
2012-07-31 07:27:40 +02:00
|
|
|
lcVector3 Dir(Intersection - m_OverlayCenter);
|
|
|
|
|
|
|
|
float Proj1 = lcDot(Dir, PlaneNormals[(AxisIndex + 1) % 3]);
|
|
|
|
float Proj2 = lcDot(Dir, PlaneNormals[(AxisIndex + 2) % 3]);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-07-31 07:27:40 +02:00
|
|
|
if (Proj1 > 0.0f && Proj1 < OverlayMovePlaneSize && Proj2 > 0.0f && Proj2 < OverlayMovePlaneSize)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2012-07-31 07:27:40 +02:00
|
|
|
LC_OVERLAY_MODES PlaneModes[] = { LC_OVERLAY_MOVE_YZ, LC_OVERLAY_MOVE_XZ, LC_OVERLAY_MOVE_XY };
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-07-31 07:27:40 +02:00
|
|
|
Mode = PlaneModes[AxisIndex];
|
|
|
|
|
|
|
|
ClosestIntersectionDistance = IntersectionDistance;
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
2012-07-31 07:27:40 +02:00
|
|
|
if (Proj1 > OverlayRotateArrowStart && Proj1 < OverlayRotateArrowEnd && Proj2 > OverlayRotateArrowStart && Proj2 < OverlayRotateArrowEnd)
|
|
|
|
{
|
|
|
|
LC_OVERLAY_MODES PlaneModes[] = { LC_OVERLAY_ROTATE_X, LC_OVERLAY_ROTATE_Y, LC_OVERLAY_ROTATE_Z };
|
|
|
|
|
|
|
|
Mode = PlaneModes[AxisIndex];
|
|
|
|
|
|
|
|
ClosestIntersectionDistance = IntersectionDistance;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fabs(Proj1) < OverlayMoveArrowCapRadius && Proj2 > 0.0f && Proj2 < OverlayMoveArrowSize)
|
|
|
|
{
|
|
|
|
LC_OVERLAY_MODES DirModes[] = { LC_OVERLAY_MOVE_Z, LC_OVERLAY_MOVE_X, LC_OVERLAY_MOVE_Y };
|
|
|
|
|
|
|
|
Mode = DirModes[AxisIndex];
|
|
|
|
|
|
|
|
ClosestIntersectionDistance = IntersectionDistance;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fabs(Proj2) < OverlayMoveArrowCapRadius && Proj1 > 0.0f && Proj1 < OverlayMoveArrowSize)
|
|
|
|
{
|
|
|
|
LC_OVERLAY_MODES DirModes[] = { LC_OVERLAY_MOVE_Y, LC_OVERLAY_MOVE_Z, LC_OVERLAY_MOVE_X };
|
|
|
|
|
|
|
|
Mode = DirModes[AxisIndex];
|
|
|
|
|
|
|
|
ClosestIntersectionDistance = IntersectionDistance;
|
|
|
|
}
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (Mode != m_OverlayMode)
|
|
|
|
{
|
|
|
|
m_OverlayMode = Mode;
|
|
|
|
UpdateAllViews();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (m_nCurAction == LC_ACTION_ROTATE)
|
|
|
|
{
|
|
|
|
const float OverlayRotateRadius = 2.0f;
|
|
|
|
|
|
|
|
// Calculate the distance from the mouse pointer to the center of the sphere.
|
2013-08-09 06:57:18 +02:00
|
|
|
int Viewport[4] = { 0, 0, view->mWidth, view->mHeight };
|
2012-02-01 03:08:30 +01:00
|
|
|
float Aspect = (float)Viewport[2]/(float)Viewport[3];
|
2012-08-20 06:05:56 +02:00
|
|
|
Camera* Cam = view->mCamera;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-05-29 01:33:22 +02:00
|
|
|
const lcMatrix44& ModelView = Cam->mWorldView;
|
|
|
|
lcMatrix44 Projection = lcMatrix44Perspective(Cam->m_fovy, Aspect, Cam->m_zNear, Cam->m_zFar);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
// Unproject the mouse point against both the front and the back clipping planes.
|
2012-05-29 01:33:22 +02:00
|
|
|
lcVector3 SegStart = lcUnprojectPoint(lcVector3((float)x, (float)y, 0.0f), ModelView, Projection, Viewport);
|
|
|
|
lcVector3 SegEnd = lcUnprojectPoint(lcVector3((float)x, (float)y, 1.0f), ModelView, Projection, Viewport);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-05-29 01:33:22 +02:00
|
|
|
lcVector3 Center(m_OverlayCenter);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-05-29 01:33:22 +02:00
|
|
|
lcVector3 Line = SegEnd - SegStart;
|
|
|
|
lcVector3 Vec = Center - SegStart;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-05-29 01:33:22 +02:00
|
|
|
float u = lcDot(Vec, Line) / Line.LengthSquared();
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
// Closest point in the line to the mouse.
|
2012-05-29 01:33:22 +02:00
|
|
|
lcVector3 Closest = SegStart + Line * u;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
int Mode = -1;
|
|
|
|
float Distance = (Closest - Center).Length();
|
|
|
|
const float Epsilon = 0.25f * OverlayScale;
|
|
|
|
|
|
|
|
if (Distance > (OverlayRotateRadius * OverlayScale + Epsilon))
|
|
|
|
{
|
2012-07-31 07:27:40 +02:00
|
|
|
Mode = LC_OVERLAY_ROTATE_XYZ;
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
else if (Distance < (OverlayRotateRadius * OverlayScale + Epsilon))
|
|
|
|
{
|
|
|
|
// 3D rotation unless we're over one of the axis circles.
|
2012-07-31 07:27:40 +02:00
|
|
|
Mode = LC_OVERLAY_ROTATE_XYZ;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
// Point P on a line defined by two points P1 and P2 is described by P = P1 + u (P2 - P1)
|
2013-01-06 20:24:25 +01:00
|
|
|
// A sphere centered at P3 with radius r is described by (x - x3)^2 + (y - y3)^2 + (z - z3)^2 = r^2
|
2011-09-07 23:06:51 +02:00
|
|
|
// Substituting the equation of the line into the sphere gives a quadratic equation where:
|
2013-01-06 20:24:25 +01:00
|
|
|
// a = (x2 - x1)^2 + (y2 - y1)^2 + (z2 - z1)^2
|
|
|
|
// b = 2[ (x2 - x1) (x1 - x3) + (y2 - y1) (y1 - y3) + (z2 - z1) (z1 - z3) ]
|
|
|
|
// c = x32 + y32 + z32 + x12 + y12 + z12 - 2[x3 x1 + y3 y1 + z3 z1] - r2
|
2011-09-07 23:06:51 +02:00
|
|
|
// The solutions to this quadratic are described by: (-b +- sqrt(b^2 - 4 a c) / 2 a
|
|
|
|
// The exact behavior is determined by b^2 - 4 a c:
|
2013-01-06 20:24:25 +01:00
|
|
|
// If this is less than 0 then the line does not intersect the sphere.
|
2011-09-07 23:06:51 +02:00
|
|
|
// If it equals 0 then the line is a tangent to the sphere intersecting it at one point
|
2013-01-06 20:24:25 +01:00
|
|
|
// If it is greater then 0 the line intersects the sphere at two points.
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-02-01 03:08:30 +01:00
|
|
|
float x1 = SegStart[0], y1 = SegStart[1], z1 = SegStart[2];
|
|
|
|
float x2 = SegEnd[0], y2 = SegEnd[1], z2 = SegEnd[2];
|
2011-09-07 23:06:51 +02:00
|
|
|
float x3 = m_OverlayCenter[0], y3 = m_OverlayCenter[1], z3 = m_OverlayCenter[2];
|
|
|
|
float r = OverlayRotateRadius * OverlayScale;
|
|
|
|
|
|
|
|
// TODO: rewrite using vectors.
|
|
|
|
float a = (x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1) + (z2 - z1)*(z2 - z1);
|
|
|
|
float b = 2 * ((x2 - x1)*(x1 - x3) + (y2 - y1)*(y1 - y3) + (z2 - z1)*(z1 - z3));
|
|
|
|
float c = x3*x3 + y3*y3 + z3*z3 + x1*x1 + y1*y1 + z1*z1 - 2*(x3*x1 + y3*y1 + z3*z1) - r*r;
|
|
|
|
float f = b * b - 4 * a * c;
|
|
|
|
|
|
|
|
if (f >= 0.0f)
|
|
|
|
{
|
2012-05-29 01:33:22 +02:00
|
|
|
lcVector3 ViewDir(Cam->mTargetPosition - Cam->mPosition);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
float u1 = (-b + sqrtf(f)) / (2*a);
|
|
|
|
float u2 = (-b - sqrtf(f)) / (2*a);
|
|
|
|
|
2012-05-29 01:33:22 +02:00
|
|
|
lcVector3 Intersections[2] =
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2012-05-29 01:33:22 +02:00
|
|
|
lcVector3(x1 + u1*(x2-x1), y1 + u1*(y2-y1), z1 + u1*(z2-z1)),
|
|
|
|
lcVector3(x1 + u2*(x2-x1), y1 + u2*(y2-y1), z1 + u2*(z2-z1))
|
2011-09-07 23:06:51 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
for (int i = 0; i < 2; i++)
|
|
|
|
{
|
2012-05-29 01:33:22 +02:00
|
|
|
lcVector3 Dist = Intersections[i] - Center;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-05-29 01:33:22 +02:00
|
|
|
if (lcDot(ViewDir, Dist) > 0.0f)
|
2011-09-07 23:06:51 +02:00
|
|
|
continue;
|
|
|
|
|
|
|
|
// Find the rotation from the focused piece if relative snap is enabled.
|
|
|
|
if ((m_nSnap & LC_DRAW_GLOBAL_SNAP) == 0)
|
|
|
|
{
|
|
|
|
Object* Focus = GetFocusObject();
|
|
|
|
|
|
|
|
if ((Focus != NULL) && Focus->IsPiece())
|
|
|
|
{
|
2012-05-29 01:33:22 +02:00
|
|
|
const lcVector4& Rot = ((Piece*)Focus)->mRotation;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-05-29 01:33:22 +02:00
|
|
|
lcMatrix44 RotMat = lcMatrix44FromAxisAngle(lcVector3(Rot[0], Rot[1], Rot[2]), -Rot[3] * LC_DTOR);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-05-29 01:33:22 +02:00
|
|
|
Dist = lcMul30(Dist, RotMat);
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check if we're close enough to one of the axis.
|
|
|
|
Dist.Normalize();
|
|
|
|
|
|
|
|
float dx = fabsf(Dist[0]);
|
|
|
|
float dy = fabsf(Dist[1]);
|
|
|
|
float dz = fabsf(Dist[2]);
|
|
|
|
|
|
|
|
if (dx < dy)
|
|
|
|
{
|
|
|
|
if (dx < dz)
|
|
|
|
{
|
|
|
|
if (dx < Epsilon)
|
2012-07-31 07:27:40 +02:00
|
|
|
Mode = LC_OVERLAY_ROTATE_X;
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (dz < Epsilon)
|
2012-07-31 07:27:40 +02:00
|
|
|
Mode = LC_OVERLAY_ROTATE_Z;
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (dy < dz)
|
|
|
|
{
|
|
|
|
if (dy < Epsilon)
|
2012-07-31 07:27:40 +02:00
|
|
|
Mode = LC_OVERLAY_ROTATE_Y;
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (dz < Epsilon)
|
2012-07-31 07:27:40 +02:00
|
|
|
Mode = LC_OVERLAY_ROTATE_Z;
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-31 07:27:40 +02:00
|
|
|
if (Mode != LC_OVERLAY_ROTATE_XYZ)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
|
|
|
switch (Mode)
|
|
|
|
{
|
2012-07-31 07:27:40 +02:00
|
|
|
case LC_OVERLAY_ROTATE_X:
|
2011-09-07 23:06:51 +02:00
|
|
|
Dist[0] = 0.0f;
|
|
|
|
break;
|
2012-07-31 07:27:40 +02:00
|
|
|
case LC_OVERLAY_ROTATE_Y:
|
2011-09-07 23:06:51 +02:00
|
|
|
Dist[1] = 0.0f;
|
|
|
|
break;
|
2012-07-31 07:27:40 +02:00
|
|
|
case LC_OVERLAY_ROTATE_Z:
|
2011-09-07 23:06:51 +02:00
|
|
|
Dist[2] = 0.0f;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
Dist *= r;
|
|
|
|
|
|
|
|
m_OverlayTrackStart = Center + Dist;
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Mode != m_OverlayMode)
|
|
|
|
{
|
|
|
|
m_OverlayMode = Mode;
|
|
|
|
UpdateAllViews();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (m_nCurAction == LC_ACTION_ROTATE_VIEW)
|
|
|
|
{
|
|
|
|
int vx, vy, vw, vh;
|
2012-02-01 03:08:30 +01:00
|
|
|
|
|
|
|
vx = 0;
|
|
|
|
vy = 0;
|
2013-08-09 06:57:18 +02:00
|
|
|
vw = view->mWidth;
|
|
|
|
vh = view->mHeight;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
int cx = vx + vw / 2;
|
|
|
|
int cy = vy + vh / 2;
|
|
|
|
|
|
|
|
float d = sqrtf((float)((cx - x) * (cx - x) + (cy - y) * (cy - y)));
|
2012-07-06 03:18:55 +02:00
|
|
|
float r = lcMin(vw, vh) * 0.35f;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-07-06 03:18:55 +02:00
|
|
|
const float SquareSize = lcMax(8.0f, (vw+vh)/200);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
if ((d < r + SquareSize) && (d > r - SquareSize))
|
|
|
|
{
|
|
|
|
if ((cx - x < SquareSize) && (cx - x > -SquareSize))
|
2012-07-31 07:27:40 +02:00
|
|
|
m_OverlayMode = LC_OVERLAY_ROTATE_VIEW_Y;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
|
|
|
if ((cy - y < SquareSize) && (cy - y > -SquareSize))
|
2012-07-31 07:27:40 +02:00
|
|
|
m_OverlayMode = LC_OVERLAY_ROTATE_VIEW_X;
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (d < r)
|
2012-07-31 07:27:40 +02:00
|
|
|
m_OverlayMode = LC_OVERLAY_ROTATE_VIEW_XYZ;
|
2011-09-07 23:06:51 +02:00
|
|
|
else
|
2012-07-31 07:27:40 +02:00
|
|
|
m_OverlayMode = LC_OVERLAY_ROTATE_VIEW_Z;
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
}
|
2012-07-31 07:27:40 +02:00
|
|
|
|
|
|
|
view->SetCursor(view->GetCursor());
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
2012-07-31 07:27:40 +02:00
|
|
|
void Project::ActivateOverlay(View* view, int Action, int OverlayMode)
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
2012-07-31 07:27:40 +02:00
|
|
|
if ((Action == LC_ACTION_SELECT) || (Action == LC_ACTION_MOVE) || (Action == LC_ACTION_ROTATE))
|
2011-09-07 23:06:51 +02:00
|
|
|
{
|
|
|
|
if (GetFocusPosition(m_OverlayCenter))
|
|
|
|
m_OverlayActive = true;
|
|
|
|
else if (GetSelectionCenter(m_OverlayCenter))
|
|
|
|
m_OverlayActive = true;
|
|
|
|
else
|
|
|
|
m_OverlayActive = false;
|
|
|
|
}
|
2012-07-31 07:27:40 +02:00
|
|
|
else if ((Action == LC_ACTION_ZOOM_REGION) && (m_nTracking == LC_TRACK_START_LEFT))
|
2011-09-07 23:06:51 +02:00
|
|
|
m_OverlayActive = true;
|
2012-07-31 07:27:40 +02:00
|
|
|
else if (Action == LC_ACTION_ZOOM || Action == LC_ACTION_PAN || Action == LC_ACTION_ROTATE_VIEW)
|
2011-09-07 23:06:51 +02:00
|
|
|
m_OverlayActive = true;
|
|
|
|
else
|
|
|
|
m_OverlayActive = false;
|
|
|
|
|
|
|
|
if (m_OverlayActive)
|
|
|
|
{
|
2012-07-31 07:27:40 +02:00
|
|
|
m_OverlayMode = OverlayMode;
|
2011-09-07 23:06:51 +02:00
|
|
|
UpdateOverlayScale();
|
|
|
|
}
|
2012-07-31 07:27:40 +02:00
|
|
|
|
|
|
|
if (view)
|
|
|
|
view->SetCursor(view->GetCursor());
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Project::UpdateOverlayScale()
|
|
|
|
{
|
2012-02-01 03:08:30 +01:00
|
|
|
// TODO: This is not needed, draw the overlays using an ortho matrix.
|
2011-09-07 23:06:51 +02:00
|
|
|
if (m_OverlayActive)
|
|
|
|
{
|
2012-02-01 03:08:30 +01:00
|
|
|
// Calculate the scaling factor by projecting the center to the front plane then
|
|
|
|
// projecting a point close to it back.
|
2013-08-09 06:57:18 +02:00
|
|
|
int Viewport[4] = { 0, 0, m_ActiveView->mWidth, m_ActiveView->mHeight };
|
2012-02-01 03:08:30 +01:00
|
|
|
float Aspect = (float)Viewport[2]/(float)Viewport[3];
|
2012-08-20 06:05:56 +02:00
|
|
|
Camera* Cam = m_ActiveView->mCamera;
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-05-29 01:33:22 +02:00
|
|
|
const lcMatrix44& ModelView = Cam->mWorldView;
|
|
|
|
lcMatrix44 Projection = lcMatrix44Perspective(Cam->m_fovy, Aspect, Cam->m_zNear, Cam->m_zFar);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2013-02-22 21:01:36 +01:00
|
|
|
lcVector3 ScreenPos = lcProjectPoint(m_OverlayCenter, ModelView, Projection, Viewport);
|
|
|
|
ScreenPos[0] += 10.0f;
|
|
|
|
lcVector3 Point = lcUnprojectPoint(ScreenPos, ModelView, Projection, Viewport);
|
2011-09-07 23:06:51 +02:00
|
|
|
|
2012-05-29 01:33:22 +02:00
|
|
|
lcVector3 Dist(Point - m_OverlayCenter);
|
2012-02-05 03:50:57 +01:00
|
|
|
m_ActiveView->m_OverlayScale = Dist.Length() * 5.0f;
|
2011-09-07 23:06:51 +02:00
|
|
|
}
|
|
|
|
}
|