2016-10-05 23:28:52 +02:00
# include "lc_global.h"
# include "lc_model.h"
# include <locale.h>
# include "piece.h"
# include "camera.h"
# include "light.h"
# include "group.h"
# include "lc_mainwindow.h"
# include "lc_profile.h"
# include "lc_library.h"
# include "lc_texture.h"
# include "lc_synth.h"
# include "lc_file.h"
# include "pieceinf.h"
# include "view.h"
# include "minifig.h"
# include "lc_qarraydialog.h"
# include "lc_qselectdialog.h"
# include "lc_qminifigdialog.h"
# include "lc_qgroupdialog.h"
# include "lc_qeditgroupsdialog.h"
2017-02-17 07:57:11 +01:00
# include "lc_selectbycolordialog.h"
2017-12-11 03:12:31 +01:00
# include "lc_qpropertiesdialog.h"
2016-10-05 23:28:52 +02:00
# include "lc_qutils.h"
2017-06-26 03:20:34 +02:00
# include "lc_lxf.h"
2020-01-21 00:39:20 +01:00
# if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
# include <QtConcurrent>
# endif
2016-10-05 23:28:52 +02:00
void lcModelProperties : : LoadDefaults ( )
{
mAuthor = lcGetProfileString ( LC_PROFILE_DEFAULT_AUTHOR_NAME ) ;
mBackgroundType = ( lcBackgroundType ) lcGetProfileInt ( LC_PROFILE_DEFAULT_BACKGROUND_TYPE ) ;
mBackgroundSolidColor = lcVector3FromColor ( lcGetProfileInt ( LC_PROFILE_DEFAULT_BACKGROUND_COLOR ) ) ;
mBackgroundGradientColor1 = lcVector3FromColor ( lcGetProfileInt ( LC_PROFILE_DEFAULT_GRADIENT_COLOR1 ) ) ;
mBackgroundGradientColor2 = lcVector3FromColor ( lcGetProfileInt ( LC_PROFILE_DEFAULT_GRADIENT_COLOR2 ) ) ;
mBackgroundImage = lcGetProfileString ( LC_PROFILE_DEFAULT_BACKGROUND_TEXTURE ) ;
mBackgroundImageTile = lcGetProfileInt ( LC_PROFILE_DEFAULT_BACKGROUND_TILE ) ;
mAmbientColor = lcVector3FromColor ( lcGetProfileInt ( LC_PROFILE_DEFAULT_AMBIENT_COLOR ) ) ;
}
void lcModelProperties : : SaveDefaults ( )
{
lcSetProfileInt ( LC_PROFILE_DEFAULT_BACKGROUND_TYPE , mBackgroundType ) ;
lcSetProfileInt ( LC_PROFILE_DEFAULT_BACKGROUND_COLOR , lcColorFromVector3 ( mBackgroundSolidColor ) ) ;
lcSetProfileInt ( LC_PROFILE_DEFAULT_GRADIENT_COLOR1 , lcColorFromVector3 ( mBackgroundGradientColor1 ) ) ;
lcSetProfileInt ( LC_PROFILE_DEFAULT_GRADIENT_COLOR2 , lcColorFromVector3 ( mBackgroundGradientColor2 ) ) ;
lcSetProfileString ( LC_PROFILE_DEFAULT_BACKGROUND_TEXTURE , mBackgroundImage ) ;
lcSetProfileInt ( LC_PROFILE_DEFAULT_BACKGROUND_TILE , mBackgroundImageTile ) ;
lcSetProfileInt ( LC_PROFILE_DEFAULT_AMBIENT_COLOR , lcColorFromVector3 ( mAmbientColor ) ) ;
}
void lcModelProperties : : SaveLDraw ( QTextStream & Stream ) const
{
QLatin1String LineEnding ( " \r \n " ) ;
2020-05-03 21:11:51 +02:00
Stream < < QLatin1String ( " 0 " ) < < mDescription < < LineEnding ;
Stream < < QLatin1String ( " 0 Name: " ) < < mModelName < < LineEnding ;
Stream < < QLatin1String ( " 0 Author: " ) < < mAuthor < < LineEnding ;
2016-10-05 23:28:52 +02:00
if ( ! mComments . isEmpty ( ) )
{
QStringList Comments = mComments . split ( ' \n ' ) ;
2018-02-22 01:12:18 +01:00
for ( const QString & Comment : Comments )
2016-10-05 23:28:52 +02:00
Stream < < QLatin1String ( " 0 !LEOCAD MODEL COMMENT " ) < < Comment < < LineEnding ;
}
bool TypeChanged = ( mBackgroundType ! = lcGetDefaultProfileInt ( LC_PROFILE_DEFAULT_BACKGROUND_TYPE ) ) ;
switch ( mBackgroundType )
{
case LC_BACKGROUND_SOLID :
if ( mBackgroundSolidColor ! = lcVector3FromColor ( lcGetDefaultProfileInt ( LC_PROFILE_DEFAULT_BACKGROUND_COLOR ) ) | | TypeChanged )
Stream < < QLatin1String ( " 0 !LEOCAD MODEL BACKGROUND COLOR " ) < < mBackgroundSolidColor [ 0 ] < < ' ' < < mBackgroundSolidColor [ 1 ] < < ' ' < < mBackgroundSolidColor [ 2 ] < < LineEnding ;
break ;
case LC_BACKGROUND_GRADIENT :
if ( mBackgroundGradientColor1 ! = lcVector3FromColor ( lcGetProfileInt ( LC_PROFILE_DEFAULT_GRADIENT_COLOR1 ) ) | |
mBackgroundGradientColor2 ! = lcVector3FromColor ( lcGetProfileInt ( LC_PROFILE_DEFAULT_GRADIENT_COLOR2 ) ) | | TypeChanged )
Stream < < QLatin1String ( " 0 !LEOCAD MODEL BACKGROUND GRADIENT " ) < < mBackgroundGradientColor1 [ 0 ] < < ' ' < < mBackgroundGradientColor1 [ 1 ] < < ' ' < < mBackgroundGradientColor1 [ 2 ] < < ' ' < < mBackgroundGradientColor2 [ 0 ] < < ' ' < < mBackgroundGradientColor2 [ 1 ] < < ' ' < < mBackgroundGradientColor2 [ 2 ] < < LineEnding ;
break ;
case LC_BACKGROUND_IMAGE :
if ( ! mBackgroundImage . isEmpty ( ) )
{
Stream < < QLatin1String ( " 0 !LEOCAD MODEL BACKGROUND IMAGE " ) ;
if ( mBackgroundImageTile )
Stream < < QLatin1String ( " TILE " ) ;
Stream < < QLatin1String ( " NAME " ) < < mBackgroundImage < < LineEnding ;
}
break ;
}
// lcVector3 mAmbientColor;
}
2020-05-03 21:11:51 +02:00
bool lcModelProperties : : ParseLDrawHeader ( QString Line , bool FirstLine )
{
QTextStream LineStream ( & Line , QIODevice : : ReadOnly ) ;
QString Token ;
LineStream > > Token ;
int StartPos = LineStream . pos ( ) ;
LineStream > > Token ;
if ( Token = = QLatin1String ( " !LEOCAD " ) )
return false ;
if ( FirstLine )
{
LineStream . seek ( StartPos ) ;
mDescription = LineStream . readLine ( ) . mid ( 1 ) ;
return true ;
}
if ( Token = = QLatin1String ( " Name: " ) )
{
mModelName = LineStream . readLine ( ) . mid ( 1 ) ;
return true ;
}
if ( Token = = QLatin1String ( " Author: " ) )
{
mAuthor = LineStream . readLine ( ) . mid ( 1 ) ;
return true ;
}
return false ;
}
2016-10-05 23:28:52 +02:00
void lcModelProperties : : ParseLDrawLine ( QTextStream & Stream )
{
QString Token ;
Stream > > Token ;
if ( Token = = QLatin1String ( " AUTHOR " ) )
mAuthor = Stream . readLine ( ) . mid ( 1 ) ;
else if ( Token = = QLatin1String ( " DESCRIPTION " ) )
mDescription = Stream . readLine ( ) . mid ( 1 ) ;
else if ( Token = = QLatin1String ( " COMMENT " ) )
{
QString Comment = Stream . readLine ( ) . mid ( 1 ) ;
if ( ! mComments . isEmpty ( ) )
mComments + = ' \n ' ;
mComments + = Comment ;
}
else if ( Token = = QLatin1String ( " BACKGROUND " ) )
{
Stream > > Token ;
if ( Token = = QLatin1String ( " COLOR " ) )
{
mBackgroundType = LC_BACKGROUND_SOLID ;
Stream > > mBackgroundSolidColor [ 0 ] > > mBackgroundSolidColor [ 1 ] > > mBackgroundSolidColor [ 2 ] ;
}
else if ( Token = = QLatin1String ( " GRADIENT " ) )
{
mBackgroundType = LC_BACKGROUND_GRADIENT ;
Stream > > mBackgroundGradientColor1 [ 0 ] > > mBackgroundGradientColor1 [ 1 ] > > mBackgroundGradientColor1 [ 2 ] > > mBackgroundGradientColor2 [ 0 ] > > mBackgroundGradientColor2 [ 1 ] > > mBackgroundGradientColor2 [ 2 ] ;
}
else if ( Token = = QLatin1String ( " IMAGE " ) )
{
Stream > > Token ;
if ( Token = = QLatin1String ( " TILE " ) )
{
mBackgroundImageTile = true ;
Stream > > Token ;
}
if ( Token = = QLatin1String ( " NAME " ) )
2017-03-26 19:28:58 +02:00
{
2016-10-05 23:28:52 +02:00
mBackgroundImage = Stream . readLine ( ) . trimmed ( ) ;
2017-03-26 19:28:58 +02:00
mBackgroundType = LC_BACKGROUND_IMAGE ;
}
2016-10-05 23:28:52 +02:00
}
}
}
2020-05-03 21:11:51 +02:00
lcModel : : lcModel ( const QString & FileName )
2016-10-05 23:28:52 +02:00
{
2020-05-03 21:11:51 +02:00
mProperties . mModelName = FileName ;
mProperties . mFileName = FileName ;
2016-10-05 23:28:52 +02:00
mProperties . LoadDefaults ( ) ;
mActive = false ;
mCurrentStep = 1 ;
2017-04-14 02:26:40 +02:00
mBackgroundTexture = nullptr ;
mPieceInfo = nullptr ;
2016-10-05 23:28:52 +02:00
}
lcModel : : ~ lcModel ( )
{
if ( mPieceInfo )
{
2016-12-16 18:14:19 +01:00
if ( gMainWindow & & gMainWindow - > GetCurrentPieceInfo ( ) = = mPieceInfo )
2017-04-14 02:26:40 +02:00
gMainWindow - > SetCurrentPieceInfo ( nullptr ) ;
2016-10-05 23:28:52 +02:00
if ( mPieceInfo - > GetModel ( ) = = this )
mPieceInfo - > SetPlaceholder ( ) ;
2017-01-23 04:28:05 +01:00
lcPiecesLibrary * Library = lcGetPiecesLibrary ( ) ;
Library - > ReleasePieceInfo ( mPieceInfo ) ;
2016-10-05 23:28:52 +02:00
}
DeleteModel ( ) ;
DeleteHistory ( ) ;
}
2018-03-29 19:20:36 +02:00
bool lcModel : : GetPieceWorldMatrix ( lcPiece * Piece , lcMatrix44 & ParentWorldMatrix ) const
{
for ( lcPiece * ModelPiece : mPieces )
{
if ( ModelPiece = = Piece )
{
ParentWorldMatrix = lcMul ( ModelPiece - > mModelWorld , ParentWorldMatrix ) ;
return true ;
}
PieceInfo * Info = ModelPiece - > mPieceInfo ;
if ( Info - > IsModel ( ) )
{
lcMatrix44 WorldMatrix = lcMul ( ModelPiece - > mModelWorld , ParentWorldMatrix ) ;
if ( Info - > GetPieceWorldMatrix ( Piece , WorldMatrix ) )
{
ParentWorldMatrix = WorldMatrix ;
return true ;
}
}
}
return false ;
}
2016-10-05 23:28:52 +02:00
bool lcModel : : IncludesModel ( const lcModel * Model ) const
{
if ( Model = = this )
return true ;
2019-03-09 18:50:34 +01:00
for ( lcPiece * Piece : mPieces )
if ( Piece - > mPieceInfo - > IncludesModel ( Model ) )
2016-10-05 23:28:52 +02:00
return true ;
return false ;
}
void lcModel : : DeleteHistory ( )
{
2019-06-24 03:28:14 +02:00
for ( lcModelHistoryEntry * Entry : mUndoHistory )
delete Entry ;
mUndoHistory . clear ( ) ;
for ( lcModelHistoryEntry * Entry : mRedoHistory )
delete Entry ;
mRedoHistory . clear ( ) ;
2016-10-05 23:28:52 +02:00
}
void lcModel : : DeleteModel ( )
{
lcReleaseTexture ( mBackgroundTexture ) ;
2017-04-14 02:26:40 +02:00
mBackgroundTexture = nullptr ;
2016-10-05 23:28:52 +02:00
if ( gMainWindow )
{
const lcArray < View * > * Views = gMainWindow - > GetViewsForModel ( this ) ;
// TODO: this is only needed to avoid a dangling pointer during undo/redo if a camera is set to a view but we should find a better solution instead
if ( Views )
{
for ( int ViewIdx = 0 ; ViewIdx < Views - > GetSize ( ) ; ViewIdx + + )
{
View * View = ( * Views ) [ ViewIdx ] ;
lcCamera * Camera = View - > mCamera ;
if ( ! Camera - > IsSimple ( ) & & mCameras . FindIndex ( Camera ) ! = - 1 )
View - > SetCamera ( Camera , true ) ;
}
}
}
mPieces . DeleteAll ( ) ;
mCameras . DeleteAll ( ) ;
mLights . DeleteAll ( ) ;
mGroups . DeleteAll ( ) ;
mFileLines . clear ( ) ;
}
void lcModel : : CreatePieceInfo ( Project * Project )
{
2017-01-23 04:28:05 +01:00
lcPiecesLibrary * Library = lcGetPiecesLibrary ( ) ;
2020-05-03 21:11:51 +02:00
mPieceInfo = Library - > FindPiece ( mProperties . mFileName . toLatin1 ( ) . constData ( ) , Project , true , false ) ;
2017-07-02 02:12:09 +02:00
mPieceInfo - > SetModel ( this , true , Project , true ) ;
2017-01-23 04:28:05 +01:00
Library - > LoadPieceInfo ( mPieceInfo , true , true ) ;
2016-10-05 23:28:52 +02:00
}
2018-02-07 07:07:35 +01:00
void lcModel : : UpdateMesh ( )
{
mPieceInfo - > SetModel ( this , true , nullptr , false ) ;
}
2019-03-17 21:27:57 +01:00
void lcModel : : UpdatePieceInfo ( std : : vector < lcModel * > & UpdatedModels )
2016-10-05 23:28:52 +02:00
{
2019-03-17 21:27:57 +01:00
if ( std : : find ( UpdatedModels . begin ( ) , UpdatedModels . end ( ) , this ) ! = UpdatedModels . end ( ) )
2016-10-05 23:28:52 +02:00
return ;
2017-07-02 02:12:09 +02:00
mPieceInfo - > SetModel ( this , false , nullptr , false ) ;
2019-03-17 21:27:57 +01:00
UpdatedModels . push_back ( this ) ;
2016-10-05 23:28:52 +02:00
lcMesh * Mesh = mPieceInfo - > GetMesh ( ) ;
if ( mPieces . IsEmpty ( ) & & ! Mesh )
{
mPieceInfo - > SetBoundingBox ( lcVector3 ( 0.0f , 0.0f , 0.0f ) , lcVector3 ( 0.0f , 0.0f , 0.0f ) ) ;
return ;
}
lcVector3 Min ( FLT_MAX , FLT_MAX , FLT_MAX ) , Max ( - FLT_MAX , - FLT_MAX , - FLT_MAX ) ;
2019-03-09 18:50:34 +01:00
for ( lcPiece * Piece : mPieces )
2016-10-05 23:28:52 +02:00
{
2019-03-13 03:51:04 +01:00
if ( Piece - > IsVisibleInSubModel ( ) )
2016-10-05 23:28:52 +02:00
{
Piece - > mPieceInfo - > UpdateBoundingBox ( UpdatedModels ) ;
Piece - > CompareBoundingBox ( Min , Max ) ;
}
}
if ( Mesh )
{
Min = lcMin ( Min , Mesh - > mBoundingBox . Min ) ;
Max = lcMax ( Max , Mesh - > mBoundingBox . Max ) ;
}
mPieceInfo - > SetBoundingBox ( Min , Max ) ;
}
void lcModel : : SaveLDraw ( QTextStream & Stream , bool SelectedOnly ) const
{
QLatin1String LineEnding ( " \r \n " ) ;
mProperties . SaveLDraw ( Stream ) ;
lcArray < lcGroup * > CurrentGroups ;
lcStep Step = 1 ;
int CurrentLine = 0 ;
2017-03-19 01:42:34 +01:00
int AddedSteps = 0 ;
2016-10-05 23:28:52 +02:00
2019-03-09 18:50:34 +01:00
for ( lcPiece * Piece : mPieces )
2016-10-05 23:28:52 +02:00
{
if ( SelectedOnly & & ! Piece - > IsSelected ( ) )
continue ;
while ( Piece - > GetFileLine ( ) > CurrentLine & & CurrentLine < mFileLines . size ( ) )
{
QString Line = mFileLines [ CurrentLine ] ;
QTextStream LineStream ( & Line , QIODevice : : ReadOnly ) ;
QString Token ;
LineStream > > Token ;
bool Skip = false ;
if ( Token = = QLatin1String ( " 0 " ) )
{
LineStream > > Token ;
if ( Token = = QLatin1String ( " STEP " ) )
{
if ( Piece - > GetStepShow ( ) > Step )
Step + + ;
else
Skip = true ;
}
}
if ( ! Skip )
2017-03-19 01:42:34 +01:00
{
2016-10-05 23:28:52 +02:00
Stream < < mFileLines [ CurrentLine ] ;
2017-03-19 01:42:34 +01:00
if ( AddedSteps > 0 )
AddedSteps - - ;
}
2016-10-05 23:28:52 +02:00
CurrentLine + + ;
}
while ( Piece - > GetStepShow ( ) > Step )
{
Stream < < QLatin1String ( " 0 STEP \r \n " ) ;
2017-03-19 01:42:34 +01:00
AddedSteps + + ;
2016-10-05 23:28:52 +02:00
Step + + ;
}
lcGroup * PieceGroup = Piece - > GetGroup ( ) ;
if ( PieceGroup )
{
if ( CurrentGroups . IsEmpty ( ) | | ( ! CurrentGroups . IsEmpty ( ) & & PieceGroup ! = CurrentGroups [ CurrentGroups . GetSize ( ) - 1 ] ) )
{
lcArray < lcGroup * > PieceParents ;
for ( lcGroup * Group = PieceGroup ; Group ; Group = Group - > mGroup )
PieceParents . InsertAt ( 0 , Group ) ;
int FoundParent = - 1 ;
while ( ! CurrentGroups . IsEmpty ( ) )
{
lcGroup * Group = CurrentGroups [ CurrentGroups . GetSize ( ) - 1 ] ;
int Index = PieceParents . FindIndex ( Group ) ;
if ( Index = = - 1 )
{
CurrentGroups . RemoveIndex ( CurrentGroups . GetSize ( ) - 1 ) ;
Stream < < QLatin1String ( " 0 !LEOCAD GROUP END \r \n " ) ;
}
else
{
FoundParent = Index ;
break ;
}
}
for ( int ParentIdx = FoundParent + 1 ; ParentIdx < PieceParents . GetSize ( ) ; ParentIdx + + )
{
lcGroup * Group = PieceParents [ ParentIdx ] ;
CurrentGroups . Add ( Group ) ;
Stream < < QLatin1String ( " 0 !LEOCAD GROUP BEGIN " ) < < Group - > mName < < LineEnding ;
}
}
}
else
{
while ( CurrentGroups . GetSize ( ) )
{
CurrentGroups . RemoveIndex ( CurrentGroups . GetSize ( ) - 1 ) ;
Stream < < QLatin1String ( " 0 !LEOCAD GROUP END \r \n " ) ;
}
}
if ( Piece - > mPieceInfo - > GetSynthInfo ( ) )
{
Stream < < QLatin1String ( " 0 !LEOCAD SYNTH BEGIN \r \n " ) ;
const lcArray < lcPieceControlPoint > & ControlPoints = Piece - > GetControlPoints ( ) ;
for ( int ControlPointIdx = 0 ; ControlPointIdx < ControlPoints . GetSize ( ) ; ControlPointIdx + + )
{
const lcPieceControlPoint & ControlPoint = ControlPoints [ ControlPointIdx ] ;
Stream < < QLatin1String ( " 0 !LEOCAD SYNTH CONTROL_POINT " ) ;
const float * FloatMatrix = ControlPoint . Transform ;
float Numbers [ 13 ] = { FloatMatrix [ 12 ] , - FloatMatrix [ 14 ] , FloatMatrix [ 13 ] , FloatMatrix [ 0 ] , - FloatMatrix [ 8 ] , FloatMatrix [ 4 ] , - FloatMatrix [ 2 ] , FloatMatrix [ 10 ] , - FloatMatrix [ 6 ] , FloatMatrix [ 1 ] , - FloatMatrix [ 9 ] , FloatMatrix [ 5 ] , ControlPoint . Scale } ;
for ( int NumberIdx = 0 ; NumberIdx < 13 ; NumberIdx + + )
2017-07-27 02:34:25 +02:00
Stream < < ' ' < < lcFormatValue ( Numbers [ NumberIdx ] , NumberIdx < 3 ? 4 : 6 ) ;
2016-10-05 23:28:52 +02:00
Stream < < LineEnding ;
}
}
Piece - > SaveLDraw ( Stream ) ;
if ( Piece - > mPieceInfo - > GetSynthInfo ( ) )
Stream < < QLatin1String ( " 0 !LEOCAD SYNTH END \r \n " ) ;
}
while ( CurrentLine < mFileLines . size ( ) )
{
2017-03-19 01:42:34 +01:00
QString Line = mFileLines [ CurrentLine ] ;
QTextStream LineStream ( & Line , QIODevice : : ReadOnly ) ;
QString Token ;
LineStream > > Token ;
bool Skip = false ;
if ( Token = = QLatin1String ( " 0 " ) )
{
LineStream > > Token ;
if ( Token = = QLatin1String ( " STEP " ) & & AddedSteps - - > 0 )
Skip = true ;
}
if ( ! Skip )
Stream < < mFileLines [ CurrentLine ] ;
2016-10-05 23:28:52 +02:00
CurrentLine + + ;
}
while ( CurrentGroups . GetSize ( ) )
{
CurrentGroups . RemoveIndex ( CurrentGroups . GetSize ( ) - 1 ) ;
Stream < < QLatin1String ( " 0 !LEOCAD GROUP END \r \n " ) ;
}
2019-03-09 18:50:34 +01:00
for ( lcCamera * Camera : mCameras )
2016-10-05 23:28:52 +02:00
if ( ! SelectedOnly | | Camera - > IsSelected ( ) )
Camera - > SaveLDraw ( Stream ) ;
2019-03-09 18:50:34 +01:00
for ( lcLight * Light : mLights )
2016-10-05 23:28:52 +02:00
if ( ! SelectedOnly | | Light - > IsSelected ( ) )
Light - > SaveLDraw ( Stream ) ;
Stream . flush ( ) ;
}
2019-11-26 21:13:22 +01:00
int lcModel : : SplitMPD ( QIODevice & Device )
2016-11-26 02:12:19 +01:00
{
2019-11-26 21:13:22 +01:00
qint64 ModelPos = Device . pos ( ) ;
2016-11-26 02:12:19 +01:00
while ( ! Device . atEnd ( ) )
{
qint64 Pos = Device . pos ( ) ;
QString OriginalLine = Device . readLine ( ) ;
QString Line = OriginalLine . trimmed ( ) ;
QTextStream LineStream ( & Line , QIODevice : : ReadOnly ) ;
QString Token ;
LineStream > > Token ;
if ( Token = = QLatin1String ( " 0 " ) )
{
LineStream > > Token ;
if ( Token = = QLatin1String ( " FILE " ) )
{
2020-05-03 21:11:51 +02:00
if ( ! mProperties . mFileName . isEmpty ( ) )
2016-11-26 02:12:19 +01:00
{
Device . seek ( Pos ) ;
break ;
}
2020-05-03 21:11:51 +02:00
SetFileName ( LineStream . readAll ( ) . trimmed ( ) ) ;
2019-11-26 21:13:22 +01:00
ModelPos = Pos ;
2016-11-26 02:12:19 +01:00
}
else if ( Token = = QLatin1String ( " NOFILE " ) )
{
break ;
}
}
}
2019-11-26 21:13:22 +01:00
return ModelPos ;
2016-11-26 02:12:19 +01:00
}
2016-10-05 23:28:52 +02:00
void lcModel : : LoadLDraw ( QIODevice & Device , Project * Project )
{
2017-04-14 02:26:40 +02:00
lcPiece * Piece = nullptr ;
lcCamera * Camera = nullptr ;
lcLight * Light = nullptr ;
2016-10-05 23:28:52 +02:00
lcArray < lcGroup * > CurrentGroups ;
lcArray < lcPieceControlPoint > ControlPoints ;
int CurrentStep = 1 ;
2017-01-23 04:28:05 +01:00
lcPiecesLibrary * Library = lcGetPiecesLibrary ( ) ;
2016-10-05 23:28:52 +02:00
mProperties . mAuthor . clear ( ) ;
2018-08-01 23:05:01 +02:00
mProperties . mDescription . clear ( ) ;
mProperties . mComments . clear ( ) ;
2020-05-03 21:11:51 +02:00
bool ReadingHeader = true ;
bool FirstLine = true ;
2016-10-05 23:28:52 +02:00
while ( ! Device . atEnd ( ) )
{
qint64 Pos = Device . pos ( ) ;
QString OriginalLine = Device . readLine ( ) ;
QString Line = OriginalLine . trimmed ( ) ;
QTextStream LineStream ( & Line , QIODevice : : ReadOnly ) ;
QString Token ;
LineStream > > Token ;
if ( Token = = QLatin1String ( " 0 " ) )
{
LineStream > > Token ;
if ( Token = = QLatin1String ( " FILE " ) )
{
2016-12-05 03:12:39 +01:00
QString Name = LineStream . readAll ( ) . trimmed ( ) ;
2020-05-03 21:11:51 +02:00
if ( mProperties . mFileName ! = Name )
2016-10-05 23:28:52 +02:00
{
Device . seek ( Pos ) ;
break ;
}
continue ;
}
else if ( Token = = QLatin1String ( " NOFILE " ) )
{
break ;
}
2020-05-03 21:11:51 +02:00
if ( ReadingHeader )
{
ReadingHeader = mProperties . ParseLDrawHeader ( Line , FirstLine ) ;
FirstLine = false ;
if ( ReadingHeader )
continue ;
}
if ( Token = = QLatin1String ( " STEP " ) )
2016-10-05 23:28:52 +02:00
{
CurrentStep + + ;
mFileLines . append ( OriginalLine ) ;
continue ;
}
if ( Token ! = QLatin1String ( " !LEOCAD " ) )
{
mFileLines . append ( OriginalLine ) ;
continue ;
}
LineStream > > Token ;
if ( Token = = QLatin1String ( " MODEL " ) )
{
mProperties . ParseLDrawLine ( LineStream ) ;
}
else if ( Token = = QLatin1String ( " PIECE " ) )
{
if ( ! Piece )
2017-04-14 02:26:40 +02:00
Piece = new lcPiece ( nullptr ) ;
2016-10-05 23:28:52 +02:00
Piece - > ParseLDrawLine ( LineStream ) ;
}
else if ( Token = = QLatin1String ( " CAMERA " ) )
{
if ( ! Camera )
Camera = new lcCamera ( false ) ;
if ( Camera - > ParseLDrawLine ( LineStream ) )
{
Camera - > CreateName ( mCameras ) ;
mCameras . Add ( Camera ) ;
2017-04-14 02:26:40 +02:00
Camera = nullptr ;
2016-10-05 23:28:52 +02:00
}
}
else if ( Token = = QLatin1String ( " LIGHT " ) )
{
}
else if ( Token = = QLatin1String ( " GROUP " ) )
{
LineStream > > Token ;
if ( Token = = QLatin1String ( " BEGIN " ) )
{
QString Name = LineStream . readAll ( ) . trimmed ( ) ;
2019-03-08 14:43:40 +01:00
lcGroup * Group = GetGroup ( Name , true ) ;
2016-10-05 23:28:52 +02:00
if ( ! CurrentGroups . IsEmpty ( ) )
Group - > mGroup = CurrentGroups [ CurrentGroups . GetSize ( ) - 1 ] ;
else
2017-04-14 02:26:40 +02:00
Group - > mGroup = nullptr ;
2016-10-05 23:28:52 +02:00
CurrentGroups . Add ( Group ) ;
}
else if ( Token = = QLatin1String ( " END " ) )
{
if ( ! CurrentGroups . IsEmpty ( ) )
CurrentGroups . RemoveIndex ( CurrentGroups . GetSize ( ) - 1 ) ;
}
}
else if ( Token = = QLatin1String ( " SYNTH " ) )
{
LineStream > > Token ;
if ( Token = = QLatin1String ( " BEGIN " ) )
{
ControlPoints . RemoveAll ( ) ;
}
else if ( Token = = QLatin1String ( " END " ) )
{
ControlPoints . RemoveAll ( ) ;
}
else if ( Token = = QLatin1String ( " CONTROL_POINT " ) )
{
float Numbers [ 13 ] ;
for ( int TokenIdx = 0 ; TokenIdx < 13 ; TokenIdx + + )
LineStream > > Numbers [ TokenIdx ] ;
lcPieceControlPoint & PieceControlPoint = ControlPoints . Add ( ) ;
PieceControlPoint . Transform = lcMatrix44 ( lcVector4 ( Numbers [ 3 ] , Numbers [ 9 ] , - Numbers [ 6 ] , 0.0f ) , lcVector4 ( Numbers [ 5 ] , Numbers [ 11 ] , - Numbers [ 8 ] , 0.0f ) ,
lcVector4 ( - Numbers [ 4 ] , - Numbers [ 10 ] , Numbers [ 7 ] , 0.0f ) , lcVector4 ( Numbers [ 0 ] , Numbers [ 2 ] , - Numbers [ 1 ] , 1.0f ) ) ;
PieceControlPoint . Scale = Numbers [ 12 ] ;
}
}
continue ;
}
else if ( Token = = QLatin1String ( " 1 " ) )
{
2020-05-03 21:11:51 +02:00
ReadingHeader = false ;
2016-10-05 23:28:52 +02:00
int ColorCode ;
LineStream > > ColorCode ;
float IncludeMatrix [ 12 ] ;
for ( int TokenIdx = 0 ; TokenIdx < 12 ; TokenIdx + + )
LineStream > > IncludeMatrix [ TokenIdx ] ;
lcMatrix44 IncludeTransform ( lcVector4 ( IncludeMatrix [ 3 ] , IncludeMatrix [ 6 ] , IncludeMatrix [ 9 ] , 0.0f ) , lcVector4 ( IncludeMatrix [ 4 ] , IncludeMatrix [ 7 ] , IncludeMatrix [ 10 ] , 0.0f ) ,
lcVector4 ( IncludeMatrix [ 5 ] , IncludeMatrix [ 8 ] , IncludeMatrix [ 11 ] , 0.0f ) , lcVector4 ( IncludeMatrix [ 0 ] , IncludeMatrix [ 1 ] , IncludeMatrix [ 2 ] , 1.0f ) ) ;
2018-03-24 03:03:16 +01:00
QString PartId = LineStream . readAll ( ) . trimmed ( ) ;
2019-12-31 22:07:45 +01:00
if ( PartId . isEmpty ( ) )
continue ;
2018-03-24 03:03:16 +01:00
QByteArray CleanId = PartId . toLatin1 ( ) . toUpper ( ) . replace ( ' \\ ' , ' / ' ) ;
2016-10-05 23:28:52 +02:00
2018-03-24 03:03:16 +01:00
if ( Library - > IsPrimitive ( CleanId . constData ( ) ) )
2016-10-05 23:28:52 +02:00
{
mFileLines . append ( OriginalLine ) ;
}
else
{
if ( ! Piece )
2017-04-14 02:26:40 +02:00
Piece = new lcPiece ( nullptr ) ;
2016-10-05 23:28:52 +02:00
if ( ! CurrentGroups . IsEmpty ( ) )
Piece - > SetGroup ( CurrentGroups [ CurrentGroups . GetSize ( ) - 1 ] ) ;
2019-02-28 01:34:56 +01:00
PieceInfo * Info = Library - > FindPiece ( PartId . toLatin1 ( ) . constData ( ) , Project , true , true ) ;
2016-10-05 23:28:52 +02:00
float * Matrix = IncludeTransform ;
lcMatrix44 Transform ( lcVector4 ( Matrix [ 0 ] , Matrix [ 2 ] , - Matrix [ 1 ] , 0.0f ) , lcVector4 ( Matrix [ 8 ] , Matrix [ 10 ] , - Matrix [ 9 ] , 0.0f ) ,
lcVector4 ( - Matrix [ 4 ] , - Matrix [ 6 ] , Matrix [ 5 ] , 0.0f ) , lcVector4 ( Matrix [ 12 ] , Matrix [ 14 ] , - Matrix [ 13 ] , 1.0f ) ) ;
Piece - > SetFileLine ( mFileLines . size ( ) ) ;
2018-03-24 03:03:16 +01:00
Piece - > SetPieceInfo ( Info , PartId , false ) ;
2016-10-05 23:28:52 +02:00
Piece - > Initialize ( Transform , CurrentStep ) ;
Piece - > SetColorCode ( ColorCode ) ;
2020-03-30 21:17:08 +02:00
Piece - > VerifyControlPoints ( ControlPoints ) ;
2016-10-05 23:28:52 +02:00
Piece - > SetControlPoints ( ControlPoints ) ;
AddPiece ( Piece ) ;
2017-04-14 02:26:40 +02:00
Piece = nullptr ;
2016-10-05 23:28:52 +02:00
}
}
else
2020-05-03 21:11:51 +02:00
{
ReadingHeader = false ;
mFileLines . append ( OriginalLine ) ;
}
FirstLine = false ;
2016-10-05 23:28:52 +02:00
}
mCurrentStep = CurrentStep ;
CalculateStep ( mCurrentStep ) ;
UpdateBackgroundTexture ( ) ;
2017-01-23 04:28:05 +01:00
Library - > WaitForLoadQueue ( ) ;
Library - > mBuffersDirty = true ;
Library - > UnloadUnusedParts ( ) ;
2016-10-05 23:28:52 +02:00
delete Piece ;
delete Camera ;
delete Light ;
}
bool lcModel : : LoadBinary ( lcFile * file )
{
2017-12-02 21:22:04 +01:00
qint32 i , count ;
2016-10-05 23:28:52 +02:00
char id [ 32 ] ;
2017-12-02 21:22:04 +01:00
quint32 rgb ;
2016-10-05 23:28:52 +02:00
float fv = 0.4f ;
2017-12-02 21:22:04 +01:00
quint8 ch ;
quint16 sh ;
2016-10-05 23:28:52 +02:00
file - > Seek ( 0 , SEEK_SET ) ;
file - > ReadBuffer ( id , 32 ) ;
sscanf ( & id [ 7 ] , " %f " , & fv ) ;
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 )
file - > ReadFloats ( & fv , 1 ) ;
file - > ReadU32 ( & rgb , 1 ) ;
mProperties . mBackgroundSolidColor [ 0 ] = ( float ) ( ( unsigned char ) ( rgb ) ) / 255 ;
mProperties . mBackgroundSolidColor [ 1 ] = ( float ) ( ( unsigned char ) ( ( ( unsigned short ) ( rgb ) ) > > 8 ) ) / 255 ;
mProperties . mBackgroundSolidColor [ 2 ] = ( float ) ( ( unsigned char ) ( ( rgb ) > > 16 ) ) / 255 ;
if ( fv < 0.6f ) // old view
{
double eye [ 3 ] , target [ 3 ] ;
file - > ReadDoubles ( eye , 3 ) ;
file - > ReadDoubles ( target , 3 ) ;
}
file - > Seek ( 28 , SEEK_CUR ) ;
file - > ReadS32 ( & i , 1 ) ;
mCurrentStep = i ;
if ( fv > 0.8f )
file - > ReadU32 ( ) ; //m_nScene
file - > ReadS32 ( & count , 1 ) ;
lcPiecesLibrary * Library = lcGetPiecesLibrary ( ) ;
int FirstNewPiece = mPieces . GetSize ( ) ;
while ( count - - )
{
if ( fv > 0.4f )
{
2017-04-14 02:26:40 +02:00
lcPiece * pPiece = new lcPiece ( nullptr ) ;
2016-10-05 23:28:52 +02:00
pPiece - > FileLoad ( * file ) ;
AddPiece ( pPiece ) ;
}
else
{
char name [ LC_PIECE_NAME_LEN ] ;
lcVector3 pos , rot ;
2017-12-02 21:22:04 +01:00
quint8 color , step , group ;
2016-10-05 23:28:52 +02:00
file - > ReadFloats ( pos , 3 ) ;
file - > ReadFloats ( rot , 3 ) ;
file - > ReadU8 ( & color , 1 ) ;
file - > ReadBuffer ( name , 9 ) ;
2017-07-27 18:21:55 +02:00
strcat ( name , " .dat " ) ;
2016-10-05 23:28:52 +02:00
file - > ReadU8 ( & step , 1 ) ;
file - > ReadU8 ( & group , 1 ) ;
pos * = 25.0f ;
lcMatrix44 WorldMatrix = lcMul ( lcMatrix44RotationZ ( rot [ 2 ] * LC_DTOR ) , lcMul ( lcMatrix44RotationY ( rot [ 1 ] * LC_DTOR ) , lcMatrix44RotationX ( rot [ 0 ] * LC_DTOR ) ) ) ;
WorldMatrix . SetTranslation ( pos ) ;
2017-04-14 02:26:40 +02:00
PieceInfo * pInfo = Library - > FindPiece ( name , nullptr , true , false ) ;
2016-10-05 23:28:52 +02:00
lcPiece * pPiece = new lcPiece ( pInfo ) ;
pPiece - > Initialize ( WorldMatrix , step ) ;
pPiece - > SetColorCode ( lcGetColorCodeFromOriginalColor ( color ) ) ;
AddPiece ( pPiece ) ;
// pPiece->SetGroup((lcGroup*)group);
}
}
if ( fv > = 0.4f )
{
file - > ReadBuffer ( & ch , 1 ) ;
if ( ch = = 0xFF ) file - > ReadU16 ( & sh , 1 ) ; else sh = ch ;
if ( sh > 100 )
file - > Seek ( sh , SEEK_CUR ) ;
else
{
2017-02-07 18:35:11 +01:00
QByteArray Author ;
Author . resize ( sh + 1 ) ;
file - > ReadBuffer ( Author . data ( ) , sh ) ;
Author [ sh ] = 0 ;
mProperties . mAuthor = QString : : fromUtf8 ( Author ) ;
2016-10-05 23:28:52 +02:00
}
file - > ReadBuffer ( & ch , 1 ) ;
if ( ch = = 0xFF ) file - > ReadU16 ( & sh , 1 ) ; else sh = ch ;
if ( sh > 100 )
file - > Seek ( sh , SEEK_CUR ) ;
else
{
2017-02-07 18:35:11 +01:00
QByteArray Description ;
Description . resize ( sh + 1 ) ;
file - > ReadBuffer ( Description . data ( ) , sh ) ;
Description [ sh ] = 0 ;
mProperties . mDescription = QString : : fromUtf8 ( Description ) ;
2016-10-05 23:28:52 +02:00
}
file - > ReadBuffer ( & ch , 1 ) ;
if ( ch = = 0xFF & & fv < 1.3f ) file - > ReadU16 ( & sh , 1 ) ; else sh = ch ;
if ( sh > 255 )
file - > Seek ( sh , SEEK_CUR ) ;
else
{
2017-02-07 18:35:11 +01:00
QByteArray Comments ;
Comments . resize ( sh + 1 ) ;
file - > ReadBuffer ( Comments . data ( ) , sh ) ;
Comments [ sh ] = 0 ;
mProperties . mComments = QString : : fromUtf8 ( Comments ) ;
2016-10-05 23:28:52 +02:00
mProperties . mComments . replace ( QLatin1String ( " \r \n " ) , QLatin1String ( " \n " ) ) ;
}
}
if ( fv > = 0.5f )
{
int NumGroups = mGroups . GetSize ( ) ;
file - > ReadS32 ( & count , 1 ) ;
for ( i = 0 ; i < count ; i + + )
mGroups . Add ( new lcGroup ( ) ) ;
for ( int GroupIdx = NumGroups ; GroupIdx < mGroups . GetSize ( ) ; GroupIdx + + )
{
lcGroup * Group = mGroups [ GroupIdx ] ;
if ( fv < 1.0f )
{
char Name [ LC_MAX_GROUP_NAME + 1 ] ;
file - > ReadBuffer ( Name , sizeof ( Name ) ) ;
Group - > mName = QString : : fromUtf8 ( Name ) ;
file - > ReadBuffer ( & ch , 1 ) ;
Group - > mGroup = ( lcGroup * ) - 1 ;
}
else
Group - > FileLoad ( file ) ;
}
for ( int GroupIdx = NumGroups ; GroupIdx < mGroups . GetSize ( ) ; GroupIdx + + )
{
lcGroup * Group = mGroups [ GroupIdx ] ;
2017-12-02 21:33:28 +01:00
i = ( qint32 ) ( quintptr ) ( Group - > mGroup ) ;
2017-04-14 02:26:40 +02:00
Group - > mGroup = nullptr ;
2016-10-05 23:28:52 +02:00
if ( i > 0xFFFF | | i = = - 1 )
continue ;
Group - > mGroup = mGroups [ NumGroups + i ] ;
}
for ( int PieceIdx = FirstNewPiece ; PieceIdx < mPieces . GetSize ( ) ; PieceIdx + + )
{
lcPiece * Piece = mPieces [ PieceIdx ] ;
2017-12-02 21:33:28 +01:00
i = ( qint32 ) ( quintptr ) ( Piece - > GetGroup ( ) ) ;
2017-04-14 02:26:40 +02:00
Piece - > SetGroup ( nullptr ) ;
2016-10-05 23:28:52 +02:00
if ( i > 0xFFFF | | i = = - 1 )
continue ;
Piece - > SetGroup ( mGroups [ NumGroups + i ] ) ;
}
RemoveEmptyGroups ( ) ;
}
if ( fv > = 0.6f )
{
if ( fv < 1.0f )
file - > Seek ( 4 , SEEK_CUR ) ;
else
file - > Seek ( 2 , SEEK_CUR ) ;
file - > ReadS32 ( & count , 1 ) ;
for ( i = 0 ; i < count ; i + + )
mCameras . Add ( new lcCamera ( false ) ) ;
if ( count < 7 )
{
lcCamera * pCam = new lcCamera ( false ) ;
for ( i = 0 ; i < count ; i + + )
pCam - > FileLoad ( * file ) ;
delete pCam ;
}
else
{
2019-03-09 18:50:34 +01:00
for ( lcCamera * Camera : mCameras )
Camera - > FileLoad ( * file ) ;
2016-10-05 23:28:52 +02:00
}
}
if ( fv > = 0.7f )
{
2017-04-21 23:17:03 +02:00
file - > Seek ( 24 , SEEK_CUR ) ;
2016-10-05 23:28:52 +02:00
if ( fv < 1.3f )
{
file - > ReadU8 ( & ch , 1 ) ;
if ( ch = = 0xFF )
file - > ReadU16 ( & sh , 1 ) ;
sh = ch ;
}
else
file - > ReadU16 ( & sh , 1 ) ;
if ( sh < LC_MAXPATH )
{
char Background [ LC_MAXPATH ] ;
file - > ReadBuffer ( Background , sh ) ;
mProperties . mBackgroundImage = Background ;
}
else
file - > Seek ( sh , SEEK_CUR ) ;
}
if ( fv > = 0.8f )
{
file - > ReadBuffer ( & ch , 1 ) ;
file - > Seek ( ch , SEEK_CUR ) ;
file - > ReadBuffer ( & ch , 1 ) ;
file - > Seek ( ch , SEEK_CUR ) ;
}
if ( fv > 0.9f )
{
file - > ReadU32 ( & rgb , 1 ) ;
mProperties . mAmbientColor [ 0 ] = ( float ) ( ( unsigned char ) ( rgb ) ) / 255 ;
mProperties . mAmbientColor [ 1 ] = ( float ) ( ( unsigned char ) ( ( ( unsigned short ) ( rgb ) ) > > 8 ) ) / 255 ;
mProperties . mAmbientColor [ 2 ] = ( float ) ( ( unsigned char ) ( ( rgb ) > > 16 ) ) / 255 ;
if ( fv < 1.3f )
file - > Seek ( 23 , SEEK_CUR ) ;
else
file - > Seek ( 11 , SEEK_CUR ) ;
}
if ( fv > 1.0f )
{
file - > ReadU32 ( & rgb , 1 ) ;
mProperties . mBackgroundGradientColor1 [ 0 ] = ( float ) ( ( unsigned char ) ( rgb ) ) / 255 ;
mProperties . mBackgroundGradientColor1 [ 1 ] = ( float ) ( ( unsigned char ) ( ( ( unsigned short ) ( rgb ) ) > > 8 ) ) / 255 ;
mProperties . mBackgroundGradientColor1 [ 2 ] = ( float ) ( ( unsigned char ) ( ( rgb ) > > 16 ) ) / 255 ;
file - > ReadU32 ( & rgb , 1 ) ;
mProperties . mBackgroundGradientColor2 [ 0 ] = ( float ) ( ( unsigned char ) ( rgb ) ) / 255 ;
mProperties . mBackgroundGradientColor2 [ 1 ] = ( float ) ( ( unsigned char ) ( ( ( unsigned short ) ( rgb ) ) > > 8 ) ) / 255 ;
mProperties . mBackgroundGradientColor2 [ 2 ] = ( float ) ( ( unsigned char ) ( ( rgb ) > > 16 ) ) / 255 ;
}
UpdateBackgroundTexture ( ) ;
CalculateStep ( mCurrentStep ) ;
lcGetPiecesLibrary ( ) - > UnloadUnusedParts ( ) ;
return true ;
}
2017-06-26 03:20:34 +02:00
bool lcModel : : LoadLDD ( const QString & FileData )
{
2020-04-19 04:38:29 +02:00
std : : vector < lcPiece * > Pieces ;
std : : vector < std : : vector < lcPiece * > > Groups ;
2017-06-26 03:20:34 +02:00
2017-07-08 18:29:35 +02:00
if ( ! lcImportLXFMLFile ( FileData , Pieces , Groups ) )
2017-06-26 03:20:34 +02:00
return false ;
for ( lcPiece * Piece : Pieces )
AddPiece ( Piece ) ;
2020-04-19 04:38:29 +02:00
for ( const std : : vector < lcPiece * > & Group : Groups )
2017-06-26 03:20:34 +02:00
{
lcGroup * NewGroup = AddGroup ( tr ( " Group # " ) , nullptr ) ;
for ( lcPiece * Piece : Group )
Piece - > SetGroup ( NewGroup ) ;
}
lcPiecesLibrary * Library = lcGetPiecesLibrary ( ) ;
CalculateStep ( mCurrentStep ) ;
Library - > WaitForLoadQueue ( ) ;
Library - > mBuffersDirty = true ;
Library - > UnloadUnusedParts ( ) ;
return true ;
}
2017-08-20 22:47:53 +02:00
bool lcModel : : LoadInventory ( const QByteArray & Inventory )
{
2017-08-20 23:06:13 +02:00
# if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
2017-08-20 22:47:53 +02:00
QJsonDocument Document = QJsonDocument : : fromJson ( Inventory ) ;
QJsonObject Root = Document . object ( ) ;
QJsonArray Parts = Root [ " results " ] . toArray ( ) ;
lcPiecesLibrary * Library = lcGetPiecesLibrary ( ) ;
for ( const QJsonValue & Part : Parts )
{
QJsonObject PartObject = Part . toObject ( ) ;
QByteArray PartID = PartObject [ " part " ] . toObject ( ) [ " part_num " ] . toString ( ) . toLatin1 ( ) ;
2017-09-15 23:52:05 +02:00
QJsonArray PartIDArray = PartObject [ " part " ] . toObject ( ) [ " external_ids " ] . toObject ( ) [ " LDraw " ] . toArray ( ) ;
if ( ! PartIDArray . isEmpty ( ) )
PartID = PartIDArray . first ( ) . toString ( ) . toLatin1 ( ) ;
2017-08-20 22:47:53 +02:00
int Quantity = PartObject [ " quantity " ] . toInt ( ) ;
int ColorCode = 16 ;
QJsonArray ColorArray = PartObject [ " color " ] . toObject ( ) [ " external_ids " ] . toObject ( ) [ " LDraw " ] . toObject ( ) [ " ext_ids " ] . toArray ( ) ;
if ( ! ColorArray . isEmpty ( ) )
ColorCode = ColorArray . first ( ) . toInt ( ) ;
PieceInfo * Info = Library - > FindPiece ( PartID + " .dat " , nullptr , true , false ) ;
while ( Quantity - - )
{
lcPiece * Piece = new lcPiece ( nullptr ) ;
Piece - > SetPieceInfo ( Info , QString ( ) , false ) ;
Piece - > Initialize ( lcMatrix44Identity ( ) , 1 ) ;
Piece - > SetColorCode ( ColorCode ) ;
AddPiece ( Piece ) ;
}
}
2017-08-27 00:49:46 +02:00
if ( mPieces . IsEmpty ( ) )
return false ;
2017-08-20 22:47:53 +02:00
Library - > WaitForLoadQueue ( ) ;
Library - > mBuffersDirty = true ;
Library - > UnloadUnusedParts ( ) ;
2017-08-27 00:49:46 +02:00
auto RoundBounds = [ ] ( float & Value )
{
Value = ( ( Value < 0.0f ) ? floor ( ( Value - 5.0f ) / 10.0f ) : ceil ( ( Value + 5.0f ) / 10.0f ) ) * 10.0f ;
} ;
const float TargetHeight = 800.0f ;
float CurrentX = 0.0f ;
float CurrentY = 0.0f ;
float ColumnWidth = 0.0f ;
for ( lcPiece * Piece : mPieces )
{
lcBoundingBox BoundingBox = Piece - > mPieceInfo - > GetBoundingBox ( ) ;
RoundBounds ( BoundingBox . Min . x ) ;
RoundBounds ( BoundingBox . Min . y ) ;
RoundBounds ( BoundingBox . Max . x ) ;
RoundBounds ( BoundingBox . Max . y ) ;
float PieceWidth = BoundingBox . Max . x - BoundingBox . Min . x ;
float PieceHeight = BoundingBox . Max . y - BoundingBox . Min . y ;
if ( CurrentY + PieceHeight > TargetHeight )
{
CurrentY = 0.0f ;
CurrentX + = ColumnWidth ;
ColumnWidth = 0.0f ;
}
Piece - > SetPosition ( lcVector3 ( CurrentX + PieceWidth / 2.0f , CurrentY + PieceHeight / 2.0f , 0.0f ) , 1 , false ) ;
CurrentY + = PieceHeight ;
ColumnWidth = qMax ( ColumnWidth , PieceWidth ) ;
}
CalculateStep ( mCurrentStep ) ;
2017-08-20 22:47:53 +02:00
return true ;
2017-08-20 23:06:13 +02:00
# else
return false ;
# endif
2017-08-20 22:47:53 +02:00
}
2016-10-05 23:28:52 +02:00
void lcModel : : Merge ( lcModel * Other )
{
for ( int PieceIdx = 0 ; PieceIdx < Other - > mPieces . GetSize ( ) ; PieceIdx + + )
{
lcPiece * Piece = Other - > mPieces [ PieceIdx ] ;
Piece - > SetFileLine ( - 1 ) ;
AddPiece ( Piece ) ;
}
Other - > mPieces . RemoveAll ( ) ;
for ( int CameraIdx = 0 ; CameraIdx < Other - > mCameras . GetSize ( ) ; CameraIdx + + )
{
lcCamera * Camera = Other - > mCameras [ CameraIdx ] ;
Camera - > CreateName ( mCameras ) ;
mCameras . Add ( Camera ) ;
}
Other - > mCameras . RemoveAll ( ) ;
for ( int LightIdx = 0 ; LightIdx < Other - > mLights . GetSize ( ) ; LightIdx + + )
{
lcLight * Light = Other - > mLights [ LightIdx ] ;
Light - > CreateName ( mLights ) ;
mLights . Add ( Light ) ;
}
Other - > mLights . RemoveAll ( ) ;
for ( int GroupIdx = 0 ; GroupIdx < Other - > mGroups . GetSize ( ) ; GroupIdx + + )
{
lcGroup * Group = Other - > mGroups [ GroupIdx ] ;
Group - > CreateName ( mGroups ) ;
mGroups . Add ( Group ) ;
}
Other - > mGroups . RemoveAll ( ) ;
delete Other ;
gMainWindow - > UpdateTimeline ( false , false ) ;
}
void lcModel : : Cut ( )
{
Copy ( ) ;
if ( RemoveSelectedObjects ( ) )
{
gMainWindow - > UpdateTimeline ( false , false ) ;
gMainWindow - > UpdateSelectedObjects ( true ) ;
gMainWindow - > UpdateAllViews ( ) ;
2017-03-09 00:49:57 +01:00
SaveCheckpoint ( tr ( " Cutting " ) ) ;
2016-10-05 23:28:52 +02:00
}
}
void lcModel : : Copy ( )
{
QByteArray File ;
QTextStream Stream ( & File , QIODevice : : WriteOnly ) ;
SaveLDraw ( Stream , true ) ;
2017-12-03 04:42:42 +01:00
gApplication - > ExportClipboard ( File ) ;
2016-10-05 23:28:52 +02:00
}
void lcModel : : Paste ( )
{
2017-12-03 04:42:42 +01:00
if ( gApplication - > mClipboard . isEmpty ( ) )
2016-10-05 23:28:52 +02:00
return ;
lcModel * Model = new lcModel ( QString ( ) ) ;
2017-12-03 04:42:42 +01:00
QBuffer Buffer ( & gApplication - > mClipboard ) ;
2016-10-05 23:28:52 +02:00
Buffer . open ( QIODevice : : ReadOnly ) ;
Model - > LoadLDraw ( Buffer , lcGetActiveProject ( ) ) ;
const lcArray < lcPiece * > & PastedPieces = Model - > mPieces ;
lcArray < lcObject * > SelectedObjects ;
SelectedObjects . AllocGrow ( PastedPieces . GetSize ( ) ) ;
2020-04-12 22:01:28 +02:00
for ( lcPiece * Piece : PastedPieces )
2016-10-05 23:28:52 +02:00
{
2017-03-19 01:42:34 +01:00
Piece - > SetFileLine ( - 1 ) ;
2020-04-12 22:01:28 +02:00
Piece - > SetStepShow ( mCurrentStep ) ;
2016-10-05 23:28:52 +02:00
SelectedObjects . Add ( Piece ) ;
}
Merge ( Model ) ;
SaveCheckpoint ( tr ( " Pasting " ) ) ;
2016-12-31 15:36:49 +01:00
if ( SelectedObjects . GetSize ( ) = = 1 )
2017-11-22 02:58:36 +01:00
ClearSelectionAndSetFocus ( SelectedObjects [ 0 ] , LC_PIECE_SECTION_POSITION , false ) ;
2016-10-05 23:28:52 +02:00
else
2017-11-22 07:54:49 +01:00
SetSelectionAndFocus ( SelectedObjects , nullptr , 0 , false ) ;
2016-10-05 23:28:52 +02:00
CalculateStep ( mCurrentStep ) ;
gMainWindow - > UpdateTimeline ( false , false ) ;
gMainWindow - > UpdateAllViews ( ) ;
}
2017-03-09 00:49:57 +01:00
void lcModel : : DuplicateSelectedPieces ( )
{
lcArray < lcObject * > NewPieces ;
2017-11-03 19:38:47 +01:00
lcPiece * Focus = nullptr ;
2018-02-20 04:12:32 +01:00
std : : map < lcGroup * , lcGroup * > GroupMap ;
std : : function < lcGroup * ( lcGroup * ) > GetNewGroup = [ this , & GroupMap , & GetNewGroup ] ( lcGroup * Group )
{
const auto GroupIt = GroupMap . find ( Group ) ;
if ( GroupIt ! = GroupMap . end ( ) )
return GroupIt - > second ;
else
{
lcGroup * Parent = Group - > mGroup ? GetNewGroup ( Group - > mGroup ) : nullptr ;
QString GroupName = Group - > mName ;
while ( ! GroupName . isEmpty ( ) )
{
QCharRef Last = GroupName [ GroupName . size ( ) - 1 ] ;
if ( Last . isDigit ( ) )
GroupName . chop ( 1 ) ;
else
break ;
}
if ( GroupName . isEmpty ( ) )
GroupName = Group - > mName ;
lcGroup * NewGroup = AddGroup ( GroupName , Parent ) ;
GroupMap [ Group ] = NewGroup ;
return NewGroup ;
}
} ;
2017-03-09 00:49:57 +01:00
for ( int PieceIdx = 0 ; PieceIdx < mPieces . GetSize ( ) ; PieceIdx + + )
{
lcPiece * Piece = mPieces [ PieceIdx ] ;
if ( ! Piece - > IsSelected ( ) )
continue ;
lcPiece * NewPiece = new lcPiece ( * Piece ) ;
NewPiece - > UpdatePosition ( mCurrentStep ) ;
NewPieces . Add ( NewPiece ) ;
2017-11-03 19:38:47 +01:00
if ( Piece - > IsFocused ( ) )
Focus = NewPiece ;
2017-03-09 00:49:57 +01:00
PieceIdx + + ;
InsertPiece ( NewPiece , PieceIdx ) ;
2018-02-20 04:12:32 +01:00
lcGroup * Group = Piece - > GetGroup ( ) ;
if ( Group )
Piece - > SetGroup ( GetNewGroup ( Group ) ) ;
2017-03-09 00:49:57 +01:00
}
if ( NewPieces . IsEmpty ( ) )
return ;
gMainWindow - > UpdateTimeline ( false , false ) ;
2017-11-22 07:54:49 +01:00
SetSelectionAndFocus ( NewPieces , Focus , LC_PIECE_SECTION_POSITION , false ) ;
2017-03-09 00:49:57 +01:00
SaveCheckpoint ( tr ( " Duplicating Pieces " ) ) ;
}
2020-01-02 02:06:17 +01:00
void lcModel : : GetScene ( lcScene & Scene , lcCamera * ViewCamera , bool AllowHighlight , bool AllowFade ) const
2016-10-05 23:28:52 +02:00
{
mPieceInfo - > AddRenderMesh ( Scene ) ;
2020-01-02 02:06:17 +01:00
for ( const lcPiece * Piece : mPieces )
{
2016-10-05 23:28:52 +02:00
if ( Piece - > IsVisible ( mCurrentStep ) )
2020-01-02 02:06:17 +01:00
{
lcStep StepShow = Piece - > GetStepShow ( ) ;
Piece - > AddMainModelRenderMeshes ( Scene , AllowHighlight & & StepShow = = mCurrentStep , AllowFade & & StepShow < mCurrentStep ) ;
}
}
2016-10-05 23:28:52 +02:00
2019-11-30 21:19:13 +01:00
if ( Scene . GetDrawInterface ( ) & & ! Scene . GetActiveSubmodelInstance ( ) )
2016-10-05 23:28:52 +02:00
{
2019-03-09 18:50:34 +01:00
for ( lcCamera * Camera : mCameras )
2016-10-05 23:28:52 +02:00
if ( Camera ! = ViewCamera & & Camera - > IsVisible ( ) )
2017-04-02 01:53:54 +02:00
Scene . AddInterfaceObject ( Camera ) ;
2016-10-05 23:28:52 +02:00
2019-03-09 18:50:34 +01:00
for ( lcLight * Light : mLights )
2016-10-05 23:28:52 +02:00
if ( Light - > IsVisible ( ) )
2017-04-02 01:53:54 +02:00
Scene . AddInterfaceObject ( Light ) ;
2016-10-05 23:28:52 +02:00
}
}
2018-04-07 20:45:00 +02:00
void lcModel : : AddSubModelRenderMeshes ( lcScene & Scene , const lcMatrix44 & WorldMatrix , int DefaultColorIndex , lcRenderMeshState RenderMeshState , bool ParentActive ) const
2016-10-05 23:28:52 +02:00
{
2018-03-29 19:20:36 +02:00
for ( lcPiece * Piece : mPieces )
2019-03-13 03:51:04 +01:00
if ( Piece - > IsVisibleInSubModel ( ) )
2018-04-07 20:45:00 +02:00
Piece - > AddSubModelRenderMeshes ( Scene , WorldMatrix , DefaultColorIndex , RenderMeshState , ParentActive ) ;
2016-10-05 23:28:52 +02:00
}
2017-01-30 04:31:30 +01:00
void lcModel : : DrawBackground ( lcGLWidget * Widget )
2016-10-05 23:28:52 +02:00
{
if ( mProperties . mBackgroundType = = LC_BACKGROUND_SOLID )
{
glClearColor ( mProperties . mBackgroundSolidColor [ 0 ] , mProperties . mBackgroundSolidColor [ 1 ] , mProperties . mBackgroundSolidColor [ 2 ] , 0.0f ) ;
glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ;
return ;
}
2019-11-10 03:11:25 +01:00
lcContext * Context = Widget - > mContext ;
2016-10-05 23:28:52 +02:00
glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ;
2019-11-10 03:11:25 +01:00
Context - > SetDepthWrite ( false ) ;
2016-10-05 23:28:52 +02:00
glDisable ( GL_DEPTH_TEST ) ;
2017-01-30 04:31:30 +01:00
float ViewWidth = ( float ) Widget - > mWidth ;
float ViewHeight = ( float ) Widget - > mHeight ;
2016-10-05 23:28:52 +02:00
Context - > SetWorldMatrix ( lcMatrix44Identity ( ) ) ;
Context - > SetViewMatrix ( lcMatrix44Translation ( lcVector3 ( 0.375 , 0.375 , 0.0 ) ) ) ;
Context - > SetProjectionMatrix ( lcMatrix44Ortho ( 0.0f , ViewWidth , 0.0f , ViewHeight , - 1.0f , 1.0f ) ) ;
if ( mProperties . mBackgroundType = = LC_BACKGROUND_GRADIENT )
{
2017-04-27 07:24:54 +02:00
Context - > SetSmoothShading ( true ) ;
2016-10-05 23:28:52 +02:00
const lcVector3 & Color1 = mProperties . mBackgroundGradientColor1 ;
const lcVector3 & Color2 = mProperties . mBackgroundGradientColor2 ;
float Verts [ ] =
{
ViewWidth , ViewHeight , Color1 [ 0 ] , Color1 [ 1 ] , Color1 [ 2 ] , 1.0f ,
0.0f , ViewHeight , Color1 [ 0 ] , Color1 [ 1 ] , Color1 [ 2 ] , 1.0f ,
0.0f , 0.0f , Color2 [ 0 ] , Color2 [ 1 ] , Color2 [ 2 ] , 1.0f ,
ViewWidth , 0.0f , Color2 [ 0 ] , Color2 [ 1 ] , Color2 [ 2 ] , 1.0f
} ;
2020-03-22 21:44:20 +01:00
Context - > SetMaterial ( lcMaterialType : : UnlitVertexColor ) ;
2016-10-05 23:28:52 +02:00
Context - > SetVertexBufferPointer ( Verts ) ;
2017-03-24 17:34:53 +01:00
Context - > SetVertexFormat ( 0 , 2 , 0 , 0 , 4 , false ) ;
2016-10-05 23:28:52 +02:00
Context - > DrawPrimitives ( GL_TRIANGLE_FAN , 0 , 4 ) ;
2017-04-27 07:24:54 +02:00
Context - > SetSmoothShading ( false ) ;
2016-10-05 23:28:52 +02:00
}
else if ( mProperties . mBackgroundType = = LC_BACKGROUND_IMAGE )
{
2017-12-26 19:19:20 +01:00
Context - > BindTexture2D ( mBackgroundTexture - > mTexture ) ;
2016-10-05 23:28:52 +02:00
float TileWidth = 1.0f , TileHeight = 1.0f ;
if ( mProperties . mBackgroundImageTile )
{
TileWidth = ViewWidth / mBackgroundTexture - > mWidth ;
TileHeight = ViewHeight / mBackgroundTexture - > mHeight ;
}
float Verts [ ] =
{
0.0f , ViewHeight , 0.0f , 0.0f ,
ViewWidth , ViewHeight , TileWidth , 0.0f ,
ViewWidth , 0.0f , TileWidth , TileHeight ,
0.0f , 0.0f , 0.0f , TileHeight
} ;
2017-03-12 21:51:14 +01:00
Context - > SetColor ( 1.0f , 1.0f , 1.0f , 1.0f ) ;
2020-03-22 21:44:20 +01:00
Context - > SetMaterial ( lcMaterialType : : UnlitTextureDecal ) ;
2016-10-05 23:28:52 +02:00
Context - > SetVertexBufferPointer ( Verts ) ;
2017-03-24 17:34:53 +01:00
Context - > SetVertexFormat ( 0 , 2 , 0 , 2 , 0 , false ) ;
2016-10-05 23:28:52 +02:00
Context - > DrawPrimitives ( GL_TRIANGLE_FAN , 0 , 4 ) ;
}
glEnable ( GL_DEPTH_TEST ) ;
2019-11-10 03:11:25 +01:00
Context - > SetDepthWrite ( true ) ;
2016-10-05 23:28:52 +02:00
}
2020-04-25 20:36:28 +02:00
QImage lcModel : : GetStepImage ( bool Zoom , int Width , int Height , lcStep Step )
2016-10-05 23:28:52 +02:00
{
2016-12-28 22:30:31 +01:00
View * ActiveView = gMainWindow - > GetActiveView ( ) ;
ActiveView - > MakeCurrent ( ) ;
lcContext * Context = ActiveView - > mContext ;
2016-10-05 23:28:52 +02:00
lcStep CurrentStep = mCurrentStep ;
2019-12-31 01:04:58 +01:00
lcCamera * Camera = ActiveView - > mCamera ;
2016-12-08 06:57:53 +01:00
if ( Zoom )
ZoomExtents ( Camera , ( float ) Width / ( float ) Height ) ;
2016-10-05 23:28:52 +02:00
View View ( this ) ;
2016-12-08 06:57:53 +01:00
View . SetCamera ( Camera , false ) ;
2016-10-05 23:28:52 +02:00
View . SetContext ( Context ) ;
2017-07-30 23:18:57 +02:00
if ( ! View . BeginRenderToImage ( Width , Height ) )
{
QMessageBox : : warning ( gMainWindow , tr ( " LeoCAD " ) , tr ( " Error creating images. " ) ) ;
2019-12-31 01:04:58 +01:00
return QImage ( ) ;
2017-07-30 23:18:57 +02:00
}
2019-12-31 01:04:58 +01:00
SetTemporaryStep ( Step ) ;
View . OnDraw ( ) ;
QImage Image = View . GetRenderImage ( ) ;
View . EndRenderToImage ( ) ;
Context - > ClearResources ( ) ;
SetTemporaryStep ( CurrentStep ) ;
if ( ! mActive )
CalculateStep ( LC_STEP_MAX ) ;
return Image ;
}
2020-01-21 00:39:20 +01:00
QImage lcModel : : GetPartsListImage ( int MaxWidth , lcStep Step ) const
{
lcPartsList PartsList ;
if ( Step = = 0 )
GetPartsList ( gDefaultColor , true , false , PartsList ) ;
else
GetPartsListForStep ( Step , gDefaultColor , PartsList ) ;
if ( PartsList . empty ( ) )
return QImage ( ) ;
struct lcPartsListImage
{
QImage Thumbnail ;
const PieceInfo * Info ;
int ColorIndex ;
int Count ;
QRect Bounds ;
QPoint Position ;
} ;
std : : vector < lcPartsListImage > Images ;
for ( const auto & PartIt : PartsList )
{
for ( const auto & ColorIt : PartIt . second )
{
Images . push_back ( lcPartsListImage ( ) ) ;
lcPartsListImage & Image = Images . back ( ) ;
Image . Info = PartIt . first ;
Image . ColorIndex = ColorIt . first ;
Image . Count = ColorIt . second ;
}
}
auto ImageCompare = [ ] ( const lcPartsListImage & Image1 , const lcPartsListImage & Image2 )
{
if ( Image1 . ColorIndex ! = Image2 . ColorIndex )
return Image1 . ColorIndex < Image2 . ColorIndex ;
return strcmp ( Image1 . Info - > m_strDescription , Image2 . Info - > m_strDescription ) < 0 ;
} ;
std : : sort ( Images . begin ( ) , Images . end ( ) , ImageCompare ) ;
View * View = gMainWindow - > GetActiveView ( ) ;
View - > MakeCurrent ( ) ;
lcContext * Context = View - > mContext ;
const int ThumbnailSize = qMin ( MaxWidth , 512 ) ;
std : : pair < lcFramebuffer , lcFramebuffer > RenderFramebuffer = Context - > CreateRenderFramebuffer ( ThumbnailSize , ThumbnailSize ) ;
if ( ! RenderFramebuffer . first . IsValid ( ) )
{
QMessageBox : : warning ( gMainWindow , tr ( " LeoCAD " ) , tr ( " Error creating images. " ) ) ;
return QImage ( ) ;
}
Context - > BindFramebuffer ( RenderFramebuffer . first ) ;
float OrthoSize = 200.0f ;
lcMatrix44 ProjectionMatrix = lcMatrix44Ortho ( - OrthoSize , OrthoSize , - OrthoSize , OrthoSize , - 5000.0f , 5000.0f ) ;
lcMatrix44 ViewMatrix = lcMatrix44LookAt ( lcVector3 ( - 100.0f , - 100.0f , 75.0f ) , lcVector3 ( 0.0f , 0.0f , 0.0f ) , lcVector3 ( 0.0f , 0.0f , 1.0f ) ) ;
const int Viewport [ 4 ] = { 0 , 0 , ThumbnailSize , ThumbnailSize } ;
float ExtraPixels = 0.0f ;
for ( lcPartsListImage & Image : Images )
{
const PieceInfo * Info = Image . Info ;
const lcBoundingBox & BoundingBox = Info - > GetBoundingBox ( ) ;
lcVector3 Points [ 8 ] ;
lcGetBoxCorners ( BoundingBox . Min , BoundingBox . Max , Points ) ;
for ( lcVector3 & Point : Points )
{
Point = lcProjectPoint ( Point , ViewMatrix , ProjectionMatrix , Viewport ) ;
ExtraPixels = qMax ( ExtraPixels , - Point . x ) ;
ExtraPixels = qMax ( ExtraPixels , Point . x - ThumbnailSize ) ;
ExtraPixels = qMax ( ExtraPixels , - Point . y ) ;
ExtraPixels = qMax ( ExtraPixels , Point . y - ThumbnailSize ) ;
}
}
if ( ExtraPixels )
{
OrthoSize + = ExtraPixels * ( 2.0f * OrthoSize / ThumbnailSize ) ;
ProjectionMatrix = lcMatrix44Ortho ( - OrthoSize , OrthoSize , - OrthoSize , OrthoSize , - 5000.0f , 5000.0f ) ;
}
Context - > SetViewport ( 0 , 0 , ThumbnailSize , ThumbnailSize ) ;
Context - > SetDefaultState ( ) ;
Context - > SetProjectionMatrix ( ProjectionMatrix ) ;
for ( lcPartsListImage & Image : Images )
{
glClearColor ( 1.0f , 1.0f , 1.0f , 0.0f ) ;
glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ;
lcScene Scene ;
Scene . SetAllowWireframe ( false ) ;
Scene . SetAllowLOD ( false ) ;
Scene . Begin ( ViewMatrix ) ;
Image . Info - > AddRenderMeshes ( Scene , lcMatrix44Identity ( ) , Image . ColorIndex , lcRenderMeshState : : Default , true ) ;
Scene . End ( ) ;
Scene . Draw ( Context ) ;
Image . Thumbnail = Context - > GetRenderFramebufferImage ( RenderFramebuffer ) ;
}
Context - > ClearFramebuffer ( ) ;
Context - > DestroyRenderFramebuffer ( RenderFramebuffer ) ;
Context - > ClearResources ( ) ;
auto CalculateImageBounds = [ ] ( lcPartsListImage & Image )
{
QImage & Thumbnail = Image . Thumbnail ;
int Width = Thumbnail . width ( ) ;
int Height = Thumbnail . height ( ) ;
int MinX = Width ;
int MinY = Height ;
int MaxX = 0 ;
int MaxY = 0 ;
for ( int x = 0 ; x < Width ; x + + )
{
for ( int y = 0 ; y < Height ; y + + )
{
if ( qAlpha ( Thumbnail . pixel ( x , y ) ) )
{
MinX = qMin ( x , MinX ) ;
MinY = qMin ( y , MinY ) ;
MaxX = qMax ( x , MaxX ) ;
MaxY = qMax ( y , MaxY ) ;
}
}
}
Image . Bounds = QRect ( QPoint ( MinX , MinY ) , QPoint ( MaxX , MaxY ) ) ;
} ;
QtConcurrent : : blockingMap ( Images , CalculateImageBounds ) ;
QImage DummyImage ( 16 , 16 , QImage : : Format_ARGB32 ) ;
QPainter DummyPainter ( & DummyImage ) ;
QFont Font ( " helvetica " , 20 , QFont : : Bold ) ;
DummyPainter . setFont ( Font ) ;
QFontMetrics FontMetrics = DummyPainter . fontMetrics ( ) ;
int Ascent = FontMetrics . ascent ( ) ;
int CurrentHeight = 0 ;
int ImageWidth = MaxWidth ;
for ( lcPartsListImage & Image : Images )
CurrentHeight = qMax ( Image . Bounds . height ( ) + Ascent , CurrentHeight ) ;
for ( ; ; )
{
int CurrentWidth = 0 ;
int CurrentX = 0 ;
int CurrentY = 0 ;
int ColumnWidth = 0 ;
int Spacing = 20 ;
int NextHeightIncrease = INT_MAX ;
for ( lcPartsListImage & Image : Images )
{
if ( CurrentY + Image . Bounds . height ( ) + Ascent > CurrentHeight )
{
int NeededSpace = Image . Bounds . height ( ) + Ascent - ( CurrentHeight - CurrentY ) ;
NextHeightIncrease = qMin ( NeededSpace , NextHeightIncrease ) ;
CurrentY = 0 ;
CurrentX + = ColumnWidth + Spacing ;
ColumnWidth = 0 ;
}
Image . Position = QPoint ( CurrentX , CurrentY ) ;
CurrentY + = Image . Bounds . height ( ) + Ascent + Spacing ;
CurrentWidth = qMax ( CurrentWidth , CurrentX + Image . Bounds . width ( ) ) ;
ColumnWidth = qMax ( ColumnWidth , Image . Bounds . width ( ) ) ;
}
if ( CurrentWidth < MaxWidth )
{
ImageWidth = CurrentWidth ;
break ;
}
CurrentHeight + = NextHeightIncrease ;
}
QImage PainterImage ( ImageWidth + 40 , CurrentHeight + 40 , QImage : : Format_ARGB32 ) ;
PainterImage . fill ( QColor ( 255 , 255 , 255 , 0 ) ) ;
QPainter Painter ( & PainterImage ) ;
Painter . setFont ( Font ) ;
for ( lcPartsListImage & Image : Images )
{
QPoint Position = Image . Position + QPoint ( 20 , 20 ) ;
Painter . drawImage ( Position , Image . Thumbnail , Image . Bounds ) ;
Painter . drawText ( QPoint ( Position . x ( ) , Position . y ( ) + Image . Bounds . height ( ) + Ascent ) , QString : : number ( Image . Count ) + ' x ' ) ;
}
Painter . end ( ) ;
return PainterImage ;
}
2020-04-25 20:36:28 +02:00
void lcModel : : SaveStepImages ( const QString & BaseName , bool AddStepSuffix , bool Zoom , int Width , int Height , lcStep Start , lcStep End )
2019-12-31 01:04:58 +01:00
{
2016-10-05 23:28:52 +02:00
for ( lcStep Step = Start ; Step < = End ; Step + + )
{
2016-12-07 18:08:23 +01:00
QString FileName ;
if ( AddStepSuffix )
FileName = BaseName . arg ( Step , 2 , 10 , QLatin1Char ( ' 0 ' ) ) ;
else
FileName = BaseName ;
2016-10-05 23:28:52 +02:00
2017-07-30 23:18:57 +02:00
QImageWriter Writer ( FileName ) ;
2017-11-24 20:48:46 +01:00
if ( Writer . format ( ) . isEmpty ( ) )
Writer . setFormat ( " png " ) ;
2020-04-25 20:36:28 +02:00
QImage Image = GetStepImage ( Zoom , Width , Height , Step ) ;
2019-12-31 01:04:58 +01:00
if ( ! Writer . write ( Image ) )
2017-07-30 23:18:57 +02:00
{
QMessageBox : : information ( gMainWindow , tr ( " Error " ) , tr ( " Error writing to file '%1': \n %2 " ) . arg ( FileName , Writer . errorString ( ) ) ) ;
2016-10-05 23:28:52 +02:00
break ;
2017-07-30 23:18:57 +02:00
}
2016-10-05 23:28:52 +02:00
}
2019-12-31 01:04:58 +01:00
}
2016-10-05 23:28:52 +02:00
2020-06-01 03:46:36 +02:00
std : : vector < lcInstructionsPageLayout > lcModel : : GetPageLayouts ( std : : vector < const lcModel * > & AddedModels )
2019-12-31 01:04:58 +01:00
{
2020-06-01 03:46:36 +02:00
std : : vector < lcInstructionsPageLayout > PageLayouts ;
2016-10-05 23:28:52 +02:00
2019-12-31 01:04:58 +01:00
if ( std : : find ( AddedModels . begin ( ) , AddedModels . end ( ) , this ) ! = AddedModels . end ( ) )
return PageLayouts ;
2016-10-05 23:28:52 +02:00
2019-12-31 01:04:58 +01:00
AddedModels . push_back ( this ) ;
std : : map < lcStep , std : : vector < lcPiece * > > StepPieces ;
for ( lcPiece * Piece : mPieces )
if ( ! Piece - > IsHidden ( ) )
StepPieces [ Piece - > GetStepShow ( ) ] . push_back ( Piece ) ;
lcStep CurrentStep = 1 ;
for ( const std : : pair < lcStep , std : : vector < lcPiece * > > & StepIt : StepPieces )
{
while ( StepIt . first > CurrentStep )
{
2020-06-01 03:46:36 +02:00
PageLayouts . emplace_back ( lcInstructionsPageLayout { this , CurrentStep } ) ;
2019-12-31 01:04:58 +01:00
CurrentStep + + ;
}
for ( lcPiece * Piece : StepIt . second )
{
if ( Piece - > mPieceInfo - > IsModel ( ) )
{
lcModel * SubModel = Piece - > mPieceInfo - > GetModel ( ) ;
2020-06-01 03:46:36 +02:00
std : : vector < lcInstructionsPageLayout > SubModelLayouts = SubModel - > GetPageLayouts ( AddedModels ) ;
2019-12-31 01:04:58 +01:00
PageLayouts . insert ( PageLayouts . end ( ) , std : : make_move_iterator ( SubModelLayouts . begin ( ) ) , std : : make_move_iterator ( SubModelLayouts . end ( ) ) ) ;
}
}
2020-06-01 03:46:36 +02:00
PageLayouts . emplace_back ( lcInstructionsPageLayout { this , CurrentStep } ) ;
2019-12-31 01:04:58 +01:00
CurrentStep + + ;
}
return PageLayouts ;
2016-10-05 23:28:52 +02:00
}
void lcModel : : UpdateBackgroundTexture ( )
{
lcReleaseTexture ( mBackgroundTexture ) ;
2017-04-14 02:26:40 +02:00
mBackgroundTexture = nullptr ;
2016-10-05 23:28:52 +02:00
if ( mProperties . mBackgroundType = = LC_BACKGROUND_IMAGE )
{
mBackgroundTexture = lcLoadTexture ( mProperties . mBackgroundImage , LC_TEXTURE_WRAPU | LC_TEXTURE_WRAPV ) ;
if ( ! mBackgroundTexture )
mProperties . mBackgroundType = LC_BACKGROUND_SOLID ;
}
}
void lcModel : : RayTest ( lcObjectRayTest & ObjectRayTest ) const
{
2017-11-13 04:38:07 +01:00
for ( lcPiece * Piece : mPieces )
if ( Piece - > IsVisible ( mCurrentStep ) & & ( ! ObjectRayTest . IgnoreSelected | | ! Piece - > IsSelected ( ) ) )
2016-10-05 23:28:52 +02:00
Piece - > RayTest ( ObjectRayTest ) ;
if ( ObjectRayTest . PiecesOnly )
return ;
2017-11-13 04:38:07 +01:00
for ( lcCamera * Camera : mCameras )
if ( Camera ! = ObjectRayTest . ViewCamera & & Camera - > IsVisible ( ) & & ( ! ObjectRayTest . IgnoreSelected | | ! Camera - > IsSelected ( ) ) )
2016-10-05 23:28:52 +02:00
Camera - > RayTest ( ObjectRayTest ) ;
2017-11-13 04:38:07 +01:00
for ( lcLight * Light : mLights )
if ( Light - > IsVisible ( ) & & ( ! ObjectRayTest . IgnoreSelected | | ! Light - > IsSelected ( ) ) )
Light - > RayTest ( ObjectRayTest ) ;
2016-10-05 23:28:52 +02:00
}
void lcModel : : BoxTest ( lcObjectBoxTest & ObjectBoxTest ) const
{
2019-03-09 18:50:34 +01:00
for ( lcPiece * Piece : mPieces )
2016-10-05 23:28:52 +02:00
if ( Piece - > IsVisible ( mCurrentStep ) )
Piece - > BoxTest ( ObjectBoxTest ) ;
2019-03-09 18:50:34 +01:00
for ( lcCamera * Camera : mCameras )
2016-10-05 23:28:52 +02:00
if ( Camera ! = ObjectBoxTest . ViewCamera & & Camera - > IsVisible ( ) )
Camera - > BoxTest ( ObjectBoxTest ) ;
2019-03-09 18:50:34 +01:00
for ( lcLight * Light : mLights )
if ( Light - > IsVisible ( ) )
Light - > BoxTest ( ObjectBoxTest ) ;
2016-10-05 23:28:52 +02:00
}
bool lcModel : : SubModelMinIntersectDist ( const lcVector3 & WorldStart , const lcVector3 & WorldEnd , float & MinDistance ) const
{
bool MinIntersect = false ;
2019-03-09 18:50:34 +01:00
for ( lcPiece * Piece : mPieces )
2016-10-05 23:28:52 +02:00
{
lcMatrix44 InverseWorldMatrix = lcMatrix44AffineInverse ( Piece - > mModelWorld ) ;
lcVector3 Start = lcMul31 ( WorldStart , InverseWorldMatrix ) ;
lcVector3 End = lcMul31 ( WorldEnd , InverseWorldMatrix ) ;
2019-03-13 03:51:04 +01:00
if ( Piece - > IsVisibleInSubModel ( ) & & Piece - > mPieceInfo - > MinIntersectDist ( Start , End , MinDistance ) ) // todo: this should check for piece->mMesh first
2016-10-05 23:28:52 +02:00
MinIntersect = true ;
}
return MinIntersect ;
}
bool lcModel : : SubModelBoxTest ( const lcVector4 Planes [ 6 ] ) const
{
2019-03-09 18:50:34 +01:00
for ( lcPiece * Piece : mPieces )
2019-03-13 03:51:04 +01:00
if ( Piece - > IsVisibleInSubModel ( ) & & Piece - > mPieceInfo - > BoxTest ( Piece - > mModelWorld , Planes ) )
2016-10-05 23:28:52 +02:00
return true ;
return false ;
}
2020-04-11 20:04:27 +02:00
void lcModel : : SubModelCompareBoundingBox ( const lcMatrix44 & WorldMatrix , lcVector3 & Min , lcVector3 & Max ) const
{
for ( lcPiece * Piece : mPieces )
if ( Piece - > IsVisibleInSubModel ( ) )
Piece - > SubmodelCompareBoundingBox ( WorldMatrix , Min , Max ) ;
}
2016-10-05 23:28:52 +02:00
void lcModel : : SaveCheckpoint ( const QString & Description )
{
lcModelHistoryEntry * ModelHistoryEntry = new lcModelHistoryEntry ( ) ;
ModelHistoryEntry - > Description = Description ;
QTextStream Stream ( & ModelHistoryEntry - > File ) ;
SaveLDraw ( Stream , false ) ;
2019-06-24 03:28:14 +02:00
mUndoHistory . insert ( mUndoHistory . begin ( ) , ModelHistoryEntry ) ;
for ( lcModelHistoryEntry * Entry : mRedoHistory )
delete Entry ;
mRedoHistory . clear ( ) ;
2016-10-05 23:28:52 +02:00
if ( ! Description . isEmpty ( ) )
{
gMainWindow - > UpdateModified ( IsModified ( ) ) ;
2019-06-24 03:28:14 +02:00
gMainWindow - > UpdateUndoRedo ( mUndoHistory . size ( ) > 1 ? mUndoHistory [ 0 ] - > Description : QString ( ) , ! mRedoHistory . empty ( ) ? mRedoHistory [ 0 ] - > Description : QString ( ) ) ;
2016-10-05 23:28:52 +02:00
}
}
void lcModel : : LoadCheckPoint ( lcModelHistoryEntry * CheckPoint )
{
2017-01-23 04:28:05 +01:00
lcPiecesLibrary * Library = lcGetPiecesLibrary ( ) ;
2019-07-05 02:06:26 +02:00
std : : vector < PieceInfo * > LoadedInfos ;
2016-11-26 02:12:19 +01:00
2019-03-09 18:50:34 +01:00
for ( lcPiece * Piece : mPieces )
2016-11-26 02:12:19 +01:00
{
2019-03-09 18:50:34 +01:00
PieceInfo * Info = Piece - > mPieceInfo ;
2017-01-23 04:28:05 +01:00
Library - > LoadPieceInfo ( Info , true , true ) ;
2019-07-05 02:06:26 +02:00
LoadedInfos . push_back ( Info ) ;
2016-11-26 02:12:19 +01:00
}
2016-10-05 23:28:52 +02:00
DeleteModel ( ) ;
QBuffer Buffer ( & CheckPoint - > File ) ;
Buffer . open ( QIODevice : : ReadOnly ) ;
LoadLDraw ( Buffer , lcGetActiveProject ( ) ) ;
gMainWindow - > UpdateTimeline ( true , false ) ;
gMainWindow - > UpdateCameraMenu ( ) ;
gMainWindow - > UpdateCurrentStep ( ) ;
gMainWindow - > UpdateSelectedObjects ( true ) ;
gMainWindow - > UpdateAllViews ( ) ;
2016-11-26 02:12:19 +01:00
2019-07-05 02:06:26 +02:00
for ( PieceInfo * Info : LoadedInfos )
Library - > ReleasePieceInfo ( Info ) ;
2016-10-05 23:28:52 +02:00
}
void lcModel : : SetActive ( bool Active )
{
2017-07-27 18:21:55 +02:00
CalculateStep ( Active ? mCurrentStep : LC_STEP_MAX ) ;
2016-10-05 23:28:52 +02:00
mActive = Active ;
}
void lcModel : : CalculateStep ( lcStep Step )
{
2019-03-09 18:50:34 +01:00
for ( lcPiece * Piece : mPieces )
2016-10-05 23:28:52 +02:00
{
Piece - > UpdatePosition ( Step ) ;
if ( Piece - > IsSelected ( ) )
{
if ( ! Piece - > IsVisible ( Step ) )
Piece - > SetSelected ( false ) ;
else
SelectGroup ( Piece - > GetTopGroup ( ) , true ) ;
}
}
2019-03-09 18:50:34 +01:00
for ( lcCamera * Camera : mCameras )
Camera - > UpdatePosition ( Step ) ;
2016-10-05 23:28:52 +02:00
2019-03-09 18:50:34 +01:00
for ( lcLight * Light : mLights )
Light - > UpdatePosition ( Step ) ;
2016-10-05 23:28:52 +02:00
}
void lcModel : : SetCurrentStep ( lcStep Step )
{
mCurrentStep = Step ;
CalculateStep ( Step ) ;
gMainWindow - > UpdateTimeline ( false , false ) ;
gMainWindow - > UpdateSelectedObjects ( true ) ;
gMainWindow - > UpdateAllViews ( ) ;
gMainWindow - > UpdateCurrentStep ( ) ;
}
void lcModel : : ShowFirstStep ( )
{
if ( mCurrentStep = = 1 )
return ;
SetCurrentStep ( 1 ) ;
}
void lcModel : : ShowLastStep ( )
{
lcStep LastStep = GetLastStep ( ) ;
if ( mCurrentStep = = LastStep )
return ;
SetCurrentStep ( LastStep ) ;
}
void lcModel : : ShowPreviousStep ( )
{
if ( mCurrentStep = = 1 )
return ;
SetCurrentStep ( mCurrentStep - 1 ) ;
}
void lcModel : : ShowNextStep ( )
{
if ( mCurrentStep = = LC_STEP_MAX )
return ;
SetCurrentStep ( mCurrentStep + 1 ) ;
}
lcStep lcModel : : GetLastStep ( ) const
{
lcStep Step = 1 ;
2019-03-09 18:50:34 +01:00
for ( lcPiece * Piece : mPieces )
Step = lcMax ( Step , Piece - > GetStepShow ( ) ) ;
2016-10-05 23:28:52 +02:00
return Step ;
}
void lcModel : : InsertStep ( lcStep Step )
{
2019-03-09 18:50:34 +01:00
for ( lcPiece * Piece : mPieces )
2016-10-05 23:28:52 +02:00
{
Piece - > InsertTime ( Step , 1 ) ;
if ( Piece - > IsSelected ( ) & & ! Piece - > IsVisible ( mCurrentStep ) )
Piece - > SetSelected ( false ) ;
}
2019-03-09 18:50:34 +01:00
for ( lcCamera * Camera : mCameras )
Camera - > InsertTime ( Step , 1 ) ;
2016-10-05 23:28:52 +02:00
2019-03-09 18:50:34 +01:00
for ( lcLight * Light : mLights )
Light - > InsertTime ( Step , 1 ) ;
2016-10-05 23:28:52 +02:00
SaveCheckpoint ( tr ( " Inserting Step " ) ) ;
SetCurrentStep ( mCurrentStep ) ;
}
void lcModel : : RemoveStep ( lcStep Step )
{
2019-03-09 18:50:34 +01:00
for ( lcPiece * Piece : mPieces )
2016-10-05 23:28:52 +02:00
{
Piece - > RemoveTime ( Step , 1 ) ;
if ( Piece - > IsSelected ( ) & & ! Piece - > IsVisible ( mCurrentStep ) )
Piece - > SetSelected ( false ) ;
}
2019-03-09 18:50:34 +01:00
for ( lcCamera * Camera : mCameras )
Camera - > RemoveTime ( Step , 1 ) ;
2016-10-05 23:28:52 +02:00
2019-03-09 18:50:34 +01:00
for ( lcLight * Light : mLights )
Light - > RemoveTime ( Step , 1 ) ;
2016-10-05 23:28:52 +02:00
SaveCheckpoint ( tr ( " Removing Step " ) ) ;
SetCurrentStep ( mCurrentStep ) ;
}
lcGroup * lcModel : : AddGroup ( const QString & Prefix , lcGroup * Parent )
{
lcGroup * Group = new lcGroup ( ) ;
mGroups . Add ( Group ) ;
Group - > mName = GetGroupName ( Prefix ) ;
Group - > mGroup = Parent ;
return Group ;
}
lcGroup * lcModel : : GetGroup ( const QString & Name , bool CreateIfMissing )
{
2019-03-09 18:50:34 +01:00
for ( lcGroup * Group : mGroups )
2016-10-05 23:28:52 +02:00
if ( Group - > mName = = Name )
return Group ;
if ( CreateIfMissing )
{
lcGroup * Group = new lcGroup ( ) ;
Group - > mName = Name ;
mGroups . Add ( Group ) ;
return Group ;
}
2017-04-14 02:26:40 +02:00
return nullptr ;
2016-10-05 23:28:52 +02:00
}
void lcModel : : RemoveGroup ( lcGroup * Group )
{
mGroups . Remove ( Group ) ;
delete Group ;
}
void lcModel : : GroupSelection ( )
{
if ( ! AnyPiecesSelected ( ) )
{
QMessageBox : : information ( gMainWindow , tr ( " LeoCAD " ) , tr ( " No pieces selected. " ) ) ;
return ;
}
lcQGroupDialog Dialog ( gMainWindow , GetGroupName ( tr ( " Group # " ) ) ) ;
if ( Dialog . exec ( ) ! = QDialog : : Accepted )
return ;
lcGroup * NewGroup = GetGroup ( Dialog . mName , true ) ;
2019-03-09 18:50:34 +01:00
for ( lcPiece * Piece : mPieces )
2016-10-05 23:28:52 +02:00
{
if ( Piece - > IsSelected ( ) )
{
lcGroup * Group = Piece - > GetTopGroup ( ) ;
if ( ! Group )
Piece - > SetGroup ( NewGroup ) ;
else if ( Group ! = NewGroup )
Group - > mGroup = NewGroup ;
}
}
SaveCheckpoint ( tr ( " Grouping " ) ) ;
}
void lcModel : : UngroupSelection ( )
{
lcArray < lcGroup * > SelectedGroups ;
2019-03-09 18:50:34 +01:00
for ( lcPiece * Piece : mPieces )
2016-10-05 23:28:52 +02:00
{
if ( Piece - > IsSelected ( ) )
{
lcGroup * Group = Piece - > GetTopGroup ( ) ;
if ( SelectedGroups . FindIndex ( Group ) = = - 1 )
{
mGroups . Remove ( Group ) ;
SelectedGroups . Add ( Group ) ;
}
}
}
2019-03-09 18:50:34 +01:00
for ( lcPiece * Piece : mPieces )
2016-10-05 23:28:52 +02:00
{
lcGroup * Group = Piece - > GetGroup ( ) ;
if ( SelectedGroups . FindIndex ( Group ) ! = - 1 )
2017-04-14 02:26:40 +02:00
Piece - > SetGroup ( nullptr ) ;
2016-10-05 23:28:52 +02:00
}
2019-03-09 18:50:34 +01:00
for ( lcGroup * Group : mGroups )
2016-10-05 23:28:52 +02:00
if ( SelectedGroups . FindIndex ( Group - > mGroup ) ! = - 1 )
2017-04-14 02:26:40 +02:00
Group - > mGroup = nullptr ;
2016-10-05 23:28:52 +02:00
SelectedGroups . DeleteAll ( ) ;
RemoveEmptyGroups ( ) ;
SaveCheckpoint ( tr ( " Ungrouping " ) ) ;
}
void lcModel : : AddSelectedPiecesToGroup ( )
{
2017-04-14 02:26:40 +02:00
lcGroup * Group = nullptr ;
2016-10-05 23:28:52 +02:00
2019-03-09 18:50:34 +01:00
for ( lcPiece * Piece : mPieces )
2016-10-05 23:28:52 +02:00
{
if ( Piece - > IsSelected ( ) )
{
Group = Piece - > GetTopGroup ( ) ;
if ( Group )
break ;
}
}
if ( Group )
{
2019-03-09 18:50:34 +01:00
for ( lcPiece * Piece : mPieces )
2016-10-05 23:28:52 +02:00
{
if ( Piece - > IsFocused ( ) )
{
Piece - > SetGroup ( Group ) ;
break ;
}
}
}
RemoveEmptyGroups ( ) ;
SaveCheckpoint ( tr ( " Grouping " ) ) ;
}
void lcModel : : RemoveFocusPieceFromGroup ( )
{
2019-03-09 18:50:34 +01:00
for ( lcPiece * Piece : mPieces )
2016-10-05 23:28:52 +02:00
{
if ( Piece - > IsFocused ( ) )
{
2017-04-14 02:26:40 +02:00
Piece - > SetGroup ( nullptr ) ;
2016-10-05 23:28:52 +02:00
break ;
}
}
RemoveEmptyGroups ( ) ;
SaveCheckpoint ( tr ( " Ungrouping " ) ) ;
}
void lcModel : : ShowEditGroupsDialog ( )
{
QMap < lcPiece * , lcGroup * > PieceParents ;
QMap < lcGroup * , lcGroup * > GroupParents ;
2019-03-09 18:50:34 +01:00
for ( lcPiece * Piece : mPieces )
2016-10-05 23:28:52 +02:00
PieceParents [ Piece ] = Piece - > GetGroup ( ) ;
2019-03-09 18:50:34 +01:00
for ( lcGroup * Group : mGroups )
2016-10-05 23:28:52 +02:00
GroupParents [ Group ] = Group - > mGroup ;
2018-04-17 03:29:42 +02:00
lcQEditGroupsDialog Dialog ( gMainWindow , PieceParents , GroupParents , this ) ;
2016-10-05 23:28:52 +02:00
if ( Dialog . exec ( ) ! = QDialog : : Accepted )
return ;
bool Modified = Dialog . mNewGroups . isEmpty ( ) ;
2019-03-09 18:50:34 +01:00
for ( lcPiece * Piece : mPieces )
2016-10-05 23:28:52 +02:00
{
lcGroup * ParentGroup = Dialog . mPieceParents . value ( Piece ) ;
if ( ParentGroup ! = Piece - > GetGroup ( ) )
{
2019-03-09 18:50:34 +01:00
Piece - > SetGroup ( ParentGroup ) ;
2016-10-05 23:28:52 +02:00
Modified = true ;
}
}
2019-03-09 18:50:34 +01:00
for ( lcGroup * Group : mGroups )
2016-10-05 23:28:52 +02:00
{
lcGroup * ParentGroup = Dialog . mGroupParents . value ( Group ) ;
if ( ParentGroup ! = Group - > mGroup )
{
Group - > mGroup = ParentGroup ;
Modified = true ;
}
}
if ( Modified )
{
ClearSelection ( true ) ;
SaveCheckpoint ( tr ( " Editing Groups " ) ) ;
}
}
QString lcModel : : GetGroupName ( const QString & Prefix )
{
int Length = Prefix . length ( ) ;
int Max = 0 ;
2019-03-09 18:50:34 +01:00
for ( lcGroup * Group : mGroups )
2016-10-05 23:28:52 +02:00
{
2019-03-09 18:50:34 +01:00
const QString & Name = Group - > mName ;
2016-10-05 23:28:52 +02:00
if ( Name . startsWith ( Prefix ) )
{
bool Ok = false ;
2017-04-21 03:56:35 +02:00
int GroupNumber = Name . mid ( Length ) . toInt ( & Ok ) ;
2016-10-05 23:28:52 +02:00
if ( Ok & & GroupNumber > Max )
Max = GroupNumber ;
}
}
return Prefix + QString : : number ( Max + 1 ) ;
}
void lcModel : : RemoveEmptyGroups ( )
{
bool Removed ;
do
{
Removed = false ;
for ( int GroupIdx = 0 ; GroupIdx < mGroups . GetSize ( ) ; )
{
lcGroup * Group = mGroups [ GroupIdx ] ;
int Ref = 0 ;
2019-03-09 18:50:34 +01:00
for ( lcPiece * Piece : mPieces )
if ( Piece - > GetGroup ( ) = = Group )
2016-10-05 23:28:52 +02:00
Ref + + ;
for ( int ParentIdx = 0 ; ParentIdx < mGroups . GetSize ( ) ; ParentIdx + + )
if ( mGroups [ ParentIdx ] - > mGroup = = Group )
Ref + + ;
if ( Ref > 1 )
{
GroupIdx + + ;
continue ;
}
if ( Ref ! = 0 )
{
2019-03-09 18:50:34 +01:00
for ( lcPiece * Piece : mPieces )
2016-10-05 23:28:52 +02:00
{
if ( Piece - > GetGroup ( ) = = Group )
{
Piece - > SetGroup ( Group - > mGroup ) ;
break ;
}
}
for ( int ParentIdx = 0 ; ParentIdx < mGroups . GetSize ( ) ; ParentIdx + + )
{
if ( mGroups [ ParentIdx ] - > mGroup = = Group )
{
mGroups [ ParentIdx ] - > mGroup = Group - > mGroup ;
break ;
}
}
}
mGroups . RemoveIndex ( GroupIdx ) ;
delete Group ;
Removed = true ;
}
}
while ( Removed ) ;
}
lcVector3 lcModel : : SnapPosition ( const lcVector3 & Distance ) const
{
lcVector3 NewDistance ( Distance ) ;
float SnapXY = gMainWindow - > GetMoveXYSnap ( ) ;
if ( SnapXY ! = 0.0f )
{
int i = ( int ) ( NewDistance [ 0 ] / SnapXY ) ;
float Leftover = NewDistance [ 0 ] - ( SnapXY * i ) ;
if ( Leftover > SnapXY / 2 )
i + + ;
else if ( Leftover < - SnapXY / 2 )
i - - ;
NewDistance [ 0 ] = SnapXY * i ;
i = ( int ) ( NewDistance [ 1 ] / SnapXY ) ;
Leftover = NewDistance [ 1 ] - ( SnapXY * i ) ;
if ( Leftover > SnapXY / 2 )
i + + ;
else if ( Leftover < - SnapXY / 2 )
i - - ;
NewDistance [ 1 ] = SnapXY * i ;
}
float SnapZ = gMainWindow - > GetMoveZSnap ( ) ;
if ( SnapZ ! = 0.0f )
{
int i = ( int ) ( NewDistance [ 2 ] / SnapZ ) ;
float Leftover = NewDistance [ 2 ] - ( SnapZ * i ) ;
if ( Leftover > SnapZ / 2 )
i + + ;
else if ( Leftover < - SnapZ / 2 )
i - - ;
NewDistance [ 2 ] = SnapZ * i ;
}
return NewDistance ;
}
lcVector3 lcModel : : SnapRotation ( const lcVector3 & Angles ) const
{
2017-11-21 01:16:41 +01:00
float AngleSnap = gMainWindow - > GetAngleSnap ( ) ;
2016-10-05 23:28:52 +02:00
lcVector3 NewAngles ( Angles ) ;
2017-11-21 01:16:41 +01:00
if ( AngleSnap ! = 0.0f )
2016-10-05 23:28:52 +02:00
{
int Snap [ 3 ] ;
for ( int i = 0 ; i < 3 ; i + + )
2017-11-21 01:16:41 +01:00
Snap [ i ] = ( int ) ( Angles [ i ] / AngleSnap ) ;
2016-10-05 23:28:52 +02:00
NewAngles = lcVector3 ( ( float ) ( AngleSnap * Snap [ 0 ] ) , ( float ) ( AngleSnap * Snap [ 1 ] ) , ( float ) ( AngleSnap * Snap [ 2 ] ) ) ;
}
return NewAngles ;
}
lcMatrix33 lcModel : : GetRelativeRotation ( ) const
{
if ( gMainWindow - > GetRelativeTransform ( ) )
{
lcObject * Focus = GetFocusObject ( ) ;
if ( Focus & & Focus - > IsPiece ( ) )
return ( ( lcPiece * ) Focus ) - > GetRelativeRotation ( ) ;
}
return lcMatrix33Identity ( ) ;
}
void lcModel : : AddPiece ( )
{
2016-12-16 18:14:19 +01:00
PieceInfo * CurPiece = gMainWindow - > GetCurrentPieceInfo ( ) ;
2016-10-05 23:28:52 +02:00
if ( ! CurPiece )
return ;
2017-04-14 02:26:40 +02:00
lcPiece * Last = mPieces . IsEmpty ( ) ? nullptr : mPieces [ mPieces . GetSize ( ) - 1 ] ;
2016-10-05 23:28:52 +02:00
2019-03-09 18:50:34 +01:00
for ( lcPiece * Piece : mPieces )
2016-10-05 23:28:52 +02:00
{
if ( Piece - > IsFocused ( ) )
{
Last = Piece ;
break ;
}
}
lcMatrix44 WorldMatrix ;
if ( Last )
{
const lcBoundingBox & BoundingBox = Last - > GetBoundingBox ( ) ;
lcVector3 Dist ( 0 , 0 , BoundingBox . Max . z - BoundingBox . Min . z ) ;
Dist = SnapPosition ( Dist ) ;
WorldMatrix = Last - > mModelWorld ;
WorldMatrix . SetTranslation ( lcMul31 ( Dist , Last - > mModelWorld ) ) ;
}
else
{
const lcBoundingBox & BoundingBox = CurPiece - > GetBoundingBox ( ) ;
WorldMatrix = lcMatrix44Translation ( lcVector3 ( 0.0f , 0.0f , - BoundingBox . Min . z ) ) ;
}
lcPiece * Piece = new lcPiece ( CurPiece ) ;
Piece - > Initialize ( WorldMatrix , mCurrentStep ) ;
Piece - > SetColorIndex ( gMainWindow - > mColorIndex ) ;
AddPiece ( Piece ) ;
gMainWindow - > UpdateTimeline ( false , false ) ;
2017-11-22 02:58:36 +01:00
ClearSelectionAndSetFocus ( Piece , LC_PIECE_SECTION_POSITION , false ) ;
2016-10-05 23:28:52 +02:00
2017-03-09 00:49:57 +01:00
SaveCheckpoint ( tr ( " Adding Piece " ) ) ;
2016-10-05 23:28:52 +02:00
}
void lcModel : : AddPiece ( lcPiece * Piece )
{
for ( int PieceIdx = 0 ; PieceIdx < mPieces . GetSize ( ) ; PieceIdx + + )
{
if ( mPieces [ PieceIdx ] - > GetStepShow ( ) > Piece - > GetStepShow ( ) )
{
InsertPiece ( Piece , PieceIdx ) ;
return ;
}
}
InsertPiece ( Piece , mPieces . GetSize ( ) ) ;
}
void lcModel : : InsertPiece ( lcPiece * Piece , int Index )
{
PieceInfo * Info = Piece - > mPieceInfo ;
if ( ! Info - > IsModel ( ) )
{
lcMesh * Mesh = Info - > IsTemporary ( ) ? gPlaceholderMesh : Info - > GetMesh ( ) ;
2017-01-23 04:28:05 +01:00
if ( Mesh & & Mesh - > mVertexCacheOffset = = - 1 )
2016-10-05 23:28:52 +02:00
lcGetPiecesLibrary ( ) - > mBuffersDirty = true ;
}
mPieces . InsertAt ( Index , Piece ) ;
}
void lcModel : : DeleteAllCameras ( )
{
if ( mCameras . IsEmpty ( ) )
return ;
mCameras . DeleteAll ( ) ;
gMainWindow - > UpdateCameraMenu ( ) ;
gMainWindow - > UpdateSelectedObjects ( true ) ;
gMainWindow - > UpdateAllViews ( ) ;
2018-02-28 23:07:24 +01:00
SaveCheckpoint ( tr ( " Resetting Cameras " ) ) ;
2016-10-05 23:28:52 +02:00
}
void lcModel : : DeleteSelectedObjects ( )
{
if ( RemoveSelectedObjects ( ) )
{
gMainWindow - > UpdateTimeline ( false , false ) ;
gMainWindow - > UpdateSelectedObjects ( true ) ;
gMainWindow - > UpdateAllViews ( ) ;
2017-03-09 00:49:57 +01:00
SaveCheckpoint ( tr ( " Deleting " ) ) ;
2016-10-05 23:28:52 +02:00
}
}
void lcModel : : ResetSelectedPiecesPivotPoint ( )
{
2019-03-09 18:50:34 +01:00
for ( lcPiece * Piece : mPieces )
2016-10-05 23:28:52 +02:00
if ( Piece - > IsSelected ( ) )
Piece - > ResetPivotPoint ( ) ;
gMainWindow - > UpdateAllViews ( ) ;
}
2018-02-24 21:47:19 +01:00
void lcModel : : RemoveSelectedPiecesKeyFrames ( )
{
for ( lcPiece * Piece : mPieces )
if ( Piece - > IsSelected ( ) )
Piece - > RemoveKeyFrames ( ) ;
for ( lcCamera * Camera : mCameras )
if ( Camera - > IsSelected ( ) )
Camera - > RemoveKeyFrames ( ) ;
for ( lcLight * Light : mLights )
if ( Light - > IsSelected ( ) )
Light - > RemoveKeyFrames ( ) ;
gMainWindow - > UpdateAllViews ( ) ;
SaveCheckpoint ( tr ( " Removing Key Frames " ) ) ;
}
2016-10-05 23:28:52 +02:00
void lcModel : : InsertControlPoint ( )
{
lcObject * Focus = GetFocusObject ( ) ;
if ( ! Focus | | ! Focus - > IsPiece ( ) )
return ;
lcPiece * Piece = ( lcPiece * ) Focus ;
lcVector3 Start , End ;
gMainWindow - > GetActiveView ( ) - > GetRayUnderPointer ( Start , End ) ;
if ( Piece - > InsertControlPoint ( Start , End ) )
{
2017-03-09 00:49:57 +01:00
SaveCheckpoint ( tr ( " Modifying " ) ) ;
2016-10-05 23:28:52 +02:00
gMainWindow - > UpdateSelectedObjects ( true ) ;
gMainWindow - > UpdateAllViews ( ) ;
}
}
void lcModel : : RemoveFocusedControlPoint ( )
{
lcObject * Focus = GetFocusObject ( ) ;
if ( ! Focus | | ! Focus - > IsPiece ( ) )
return ;
lcPiece * Piece = ( lcPiece * ) Focus ;
if ( Piece - > RemoveFocusedControlPoint ( ) )
{
2017-03-09 00:49:57 +01:00
SaveCheckpoint ( tr ( " Modifying " ) ) ;
2016-10-05 23:28:52 +02:00
gMainWindow - > UpdateSelectedObjects ( true ) ;
gMainWindow - > UpdateAllViews ( ) ;
}
}
void lcModel : : ShowSelectedPiecesEarlier ( )
{
lcArray < lcPiece * > MovedPieces ;
for ( int PieceIdx = 0 ; PieceIdx < mPieces . GetSize ( ) ; )
{
lcPiece * Piece = mPieces [ PieceIdx ] ;
if ( Piece - > IsSelected ( ) )
{
lcStep Step = Piece - > GetStepShow ( ) ;
if ( Step > 1 )
{
Step - - ;
Piece - > SetStepShow ( Step ) ;
MovedPieces . Add ( Piece ) ;
mPieces . RemoveIndex ( PieceIdx ) ;
continue ;
}
}
PieceIdx + + ;
}
if ( MovedPieces . IsEmpty ( ) )
return ;
for ( int PieceIdx = 0 ; PieceIdx < MovedPieces . GetSize ( ) ; PieceIdx + + )
{
lcPiece * Piece = MovedPieces [ PieceIdx ] ;
Piece - > SetFileLine ( - 1 ) ;
AddPiece ( Piece ) ;
}
2017-03-09 00:49:57 +01:00
SaveCheckpoint ( tr ( " Modifying " ) ) ;
2016-10-05 23:28:52 +02:00
gMainWindow - > UpdateTimeline ( false , false ) ;
gMainWindow - > UpdateSelectedObjects ( true ) ;
gMainWindow - > UpdateAllViews ( ) ;
}
void lcModel : : ShowSelectedPiecesLater ( )
{
lcArray < lcPiece * > MovedPieces ;
for ( int PieceIdx = 0 ; PieceIdx < mPieces . GetSize ( ) ; )
{
lcPiece * Piece = mPieces [ PieceIdx ] ;
if ( Piece - > IsSelected ( ) )
{
lcStep Step = Piece - > GetStepShow ( ) ;
if ( Step < LC_STEP_MAX )
{
Step + + ;
Piece - > SetStepShow ( Step ) ;
if ( ! Piece - > IsVisible ( mCurrentStep ) )
Piece - > SetSelected ( false ) ;
MovedPieces . Add ( Piece ) ;
mPieces . RemoveIndex ( PieceIdx ) ;
continue ;
}
}
PieceIdx + + ;
}
if ( MovedPieces . IsEmpty ( ) )
return ;
for ( int PieceIdx = 0 ; PieceIdx < MovedPieces . GetSize ( ) ; PieceIdx + + )
{
lcPiece * Piece = MovedPieces [ PieceIdx ] ;
Piece - > SetFileLine ( - 1 ) ;
AddPiece ( Piece ) ;
}
2017-03-09 00:49:57 +01:00
SaveCheckpoint ( tr ( " Modifying " ) ) ;
2016-10-05 23:28:52 +02:00
gMainWindow - > UpdateTimeline ( false , false ) ;
gMainWindow - > UpdateSelectedObjects ( true ) ;
gMainWindow - > UpdateAllViews ( ) ;
}
void lcModel : : SetPieceSteps ( const QList < QPair < lcPiece * , lcStep > > & PieceSteps )
{
if ( PieceSteps . size ( ) ! = mPieces . GetSize ( ) )
return ;
bool Modified = false ;
for ( int PieceIdx = 0 ; PieceIdx < PieceSteps . size ( ) ; PieceIdx + + )
{
const QPair < lcPiece * , lcStep > & PieceStep = PieceSteps [ PieceIdx ] ;
lcPiece * Piece = mPieces [ PieceIdx ] ;
if ( Piece ! = PieceStep . first | | Piece - > GetStepShow ( ) ! = PieceStep . second )
{
Piece = PieceStep . first ;
lcStep Step = PieceStep . second ;
mPieces [ PieceIdx ] = Piece ;
Piece - > SetStepShow ( Step ) ;
if ( ! Piece - > IsVisible ( mCurrentStep ) )
Piece - > SetSelected ( false ) ;
Modified = true ;
}
}
if ( Modified )
{
2017-03-09 00:49:57 +01:00
SaveCheckpoint ( tr ( " Modifying " ) ) ;
2016-10-05 23:28:52 +02:00
gMainWindow - > UpdateAllViews ( ) ;
gMainWindow - > UpdateTimeline ( false , false ) ;
gMainWindow - > UpdateSelectedObjects ( true ) ;
}
}
2017-07-24 04:35:18 +02:00
void lcModel : : RenamePiece ( PieceInfo * Info )
{
for ( lcPiece * Piece : mPieces )
if ( Piece - > mPieceInfo = = Info )
Piece - > UpdateID ( ) ;
}
2016-10-05 23:28:52 +02:00
void lcModel : : MoveSelectionToModel ( lcModel * Model )
{
if ( ! Model )
return ;
lcArray < lcPiece * > Pieces ;
2017-04-14 02:26:40 +02:00
lcPiece * ModelPiece = nullptr ;
2017-03-03 21:14:32 +01:00
lcStep FirstStep = LC_STEP_MAX ;
2019-03-10 01:16:02 +01:00
lcVector3 Min ( FLT_MAX , FLT_MAX , FLT_MAX ) , Max ( - FLT_MAX , - FLT_MAX , - FLT_MAX ) ;
2016-10-05 23:28:52 +02:00
for ( int PieceIdx = 0 ; PieceIdx < mPieces . GetSize ( ) ; )
{
lcPiece * Piece = mPieces [ PieceIdx ] ;
if ( Piece - > IsSelected ( ) )
{
2019-03-10 01:16:02 +01:00
Piece - > CompareBoundingBox ( Min , Max ) ;
2016-10-05 23:28:52 +02:00
mPieces . RemoveIndex ( PieceIdx ) ;
2017-04-14 02:26:40 +02:00
Piece - > SetGroup ( nullptr ) ; // todo: copy groups
2016-10-05 23:28:52 +02:00
Pieces . Add ( Piece ) ;
2017-03-03 21:14:32 +01:00
FirstStep = qMin ( FirstStep , Piece - > GetStepShow ( ) ) ;
2016-10-05 23:28:52 +02:00
if ( ! ModelPiece )
{
ModelPiece = new lcPiece ( Model - > mPieceInfo ) ;
ModelPiece - > SetColorIndex ( gDefaultColor ) ;
InsertPiece ( ModelPiece , PieceIdx ) ;
PieceIdx + + ;
}
}
else
PieceIdx + + ;
}
2019-03-10 01:16:02 +01:00
lcVector3 ModelCenter = ( Min + Max ) / 2.0f ;
ModelCenter . z + = ( Min . z - Max . z ) / 2.0f ;
2016-10-05 23:28:52 +02:00
for ( int PieceIdx = 0 ; PieceIdx < Pieces . GetSize ( ) ; PieceIdx + + )
2017-03-03 21:14:32 +01:00
{
lcPiece * Piece = Pieces [ PieceIdx ] ;
2017-03-19 01:42:34 +01:00
Piece - > SetFileLine ( - 1 ) ;
2017-03-03 21:14:32 +01:00
Piece - > SetStepShow ( Piece - > GetStepShow ( ) - FirstStep + 1 ) ;
2019-03-10 01:16:02 +01:00
Piece - > MoveSelected ( Piece - > GetStepShow ( ) , false , - ModelCenter ) ;
2017-03-03 21:14:32 +01:00
Model - > AddPiece ( Piece ) ;
}
2016-10-05 23:28:52 +02:00
2019-03-17 21:27:57 +01:00
std : : vector < lcModel * > UpdatedModels ;
2016-10-05 23:28:52 +02:00
Model - > UpdatePieceInfo ( UpdatedModels ) ;
2019-03-10 22:06:01 +01:00
if ( ModelPiece )
{
2019-03-10 01:16:02 +01:00
ModelPiece - > Initialize ( lcMatrix44Translation ( ModelCenter ) , FirstStep ) ;
2017-02-13 03:05:20 +01:00
ModelPiece - > UpdatePosition ( mCurrentStep ) ;
2019-03-10 01:16:02 +01:00
}
2016-10-05 23:28:52 +02:00
2017-03-09 00:49:57 +01:00
SaveCheckpoint ( tr ( " New Model " ) ) ;
2016-10-05 23:28:52 +02:00
gMainWindow - > UpdateTimeline ( false , false ) ;
2017-11-22 02:58:36 +01:00
ClearSelectionAndSetFocus ( ModelPiece , LC_PIECE_SECTION_POSITION , false ) ;
2016-10-05 23:28:52 +02:00
}
void lcModel : : InlineSelectedModels ( )
{
lcArray < lcObject * > NewPieces ;
for ( int PieceIdx = 0 ; PieceIdx < mPieces . GetSize ( ) ; )
{
lcPiece * Piece = mPieces [ PieceIdx ] ;
if ( ! Piece - > IsSelected ( ) | | ! Piece - > mPieceInfo - > IsModel ( ) )
{
PieceIdx + + ;
continue ;
}
mPieces . RemoveIndex ( PieceIdx ) ;
2017-07-23 05:54:33 +02:00
lcModel * Model = Piece - > mPieceInfo - > GetModel ( ) ;
2016-10-05 23:28:52 +02:00
2017-07-23 05:54:33 +02:00
for ( const lcPiece * ModelPiece : Model - > mPieces )
2016-10-05 23:28:52 +02:00
{
2017-07-23 05:54:33 +02:00
lcPiece * NewPiece = new lcPiece ( nullptr ) ;
2016-10-05 23:28:52 +02:00
// todo: recreate in groups in the current model
2017-07-23 05:54:33 +02:00
int ColorIndex = ModelPiece - > mColorIndex ;
if ( ColorIndex = = gDefaultColor )
ColorIndex = Piece - > mColorIndex ;
NewPiece - > SetPieceInfo ( ModelPiece - > mPieceInfo , ModelPiece - > GetID ( ) , true ) ;
NewPiece - > Initialize ( lcMul ( ModelPiece - > mModelWorld , Piece - > mModelWorld ) , Piece - > GetStepShow ( ) ) ;
NewPiece - > SetColorIndex ( ColorIndex ) ;
2016-10-05 23:28:52 +02:00
NewPiece - > UpdatePosition ( mCurrentStep ) ;
NewPieces . Add ( NewPiece ) ;
InsertPiece ( NewPiece , PieceIdx ) ;
PieceIdx + + ;
}
delete Piece ;
}
if ( ! NewPieces . GetSize ( ) )
{
QMessageBox : : information ( gMainWindow , tr ( " LeoCAD " ) , tr ( " No models selected. " ) ) ;
return ;
}
2017-03-09 00:49:57 +01:00
SaveCheckpoint ( tr ( " Inlining " ) ) ;
2016-10-05 23:28:52 +02:00
gMainWindow - > UpdateTimeline ( false , false ) ;
2017-11-22 07:54:49 +01:00
SetSelectionAndFocus ( NewPieces , nullptr , 0 , false ) ;
2016-10-05 23:28:52 +02:00
}
bool lcModel : : RemoveSelectedObjects ( )
{
bool RemovedPiece = false ;
bool RemovedCamera = false ;
bool RemovedLight = false ;
for ( int PieceIdx = 0 ; PieceIdx < mPieces . GetSize ( ) ; )
{
lcPiece * Piece = mPieces [ PieceIdx ] ;
if ( Piece - > IsSelected ( ) )
{
RemovedPiece = true ;
mPieces . Remove ( Piece ) ;
delete Piece ;
}
else
PieceIdx + + ;
}
for ( int CameraIdx = 0 ; CameraIdx < mCameras . GetSize ( ) ; )
{
lcCamera * Camera = mCameras [ CameraIdx ] ;
if ( Camera - > IsSelected ( ) )
{
const lcArray < View * > * Views = gMainWindow - > GetViewsForModel ( this ) ;
for ( int ViewIdx = 0 ; ViewIdx < Views - > GetSize ( ) ; ViewIdx + + )
{
View * View = ( * Views ) [ ViewIdx ] ;
if ( Camera = = View - > mCamera )
View - > SetCamera ( Camera , true ) ;
}
RemovedCamera = true ;
mCameras . RemoveIndex ( CameraIdx ) ;
delete Camera ;
}
else
CameraIdx + + ;
}
if ( RemovedCamera )
gMainWindow - > UpdateCameraMenu ( ) ;
for ( int LightIdx = 0 ; LightIdx < mLights . GetSize ( ) ; )
{
lcLight * Light = mLights [ LightIdx ] ;
if ( Light - > IsSelected ( ) )
{
RemovedLight = true ;
mLights . RemoveIndex ( LightIdx ) ;
delete Light ;
}
else
LightIdx + + ;
}
RemoveEmptyGroups ( ) ;
return RemovedPiece | | RemovedCamera | | RemovedLight ;
}
void lcModel : : MoveSelectedObjects ( const lcVector3 & PieceDistance , const lcVector3 & ObjectDistance , bool Relative , bool AlternateButtonDrag , bool Update , bool Checkpoint )
{
bool Moved = false ;
lcMatrix33 RelativeRotation ;
if ( Relative )
RelativeRotation = GetRelativeRotation ( ) ;
else
RelativeRotation = lcMatrix33Identity ( ) ;
if ( PieceDistance . LengthSquared ( ) > = 0.001f )
{
lcVector3 TransformedPieceDistance = lcMul ( PieceDistance , RelativeRotation ) ;
if ( AlternateButtonDrag )
{
2019-03-09 18:50:34 +01:00
for ( lcPiece * Piece : mPieces )
2016-10-05 23:28:52 +02:00
{
if ( Piece - > IsFocused ( ) )
{
Piece - > MovePivotPoint ( TransformedPieceDistance ) ;
Moved = true ;
break ;
}
}
}
else
{
2019-03-09 18:50:34 +01:00
for ( lcPiece * Piece : mPieces )
2016-10-05 23:28:52 +02:00
{
if ( Piece - > IsSelected ( ) )
{
2020-05-09 02:53:53 +02:00
if ( gMainWindow - > GetLocalTransform ( ) )
TransformedPieceDistance = lcMul ( PieceDistance , Piece - > GetRelativeRotation ( ) ) ;
2018-01-15 20:35:15 +01:00
Piece - > MoveSelected ( mCurrentStep , gMainWindow - > GetAddKeys ( ) , TransformedPieceDistance ) ;
2016-10-05 23:28:52 +02:00
Piece - > UpdatePosition ( mCurrentStep ) ;
Moved = true ;
}
}
}
}
if ( ObjectDistance . LengthSquared ( ) > = 0.001f & & ! AlternateButtonDrag )
{
lcVector3 TransformedObjectDistance = lcMul ( ObjectDistance , RelativeRotation ) ;
2019-03-09 18:50:34 +01:00
for ( lcCamera * Camera : mCameras )
2016-10-05 23:28:52 +02:00
{
if ( Camera - > IsSelected ( ) )
{
2018-01-15 20:35:15 +01:00
Camera - > MoveSelected ( mCurrentStep , gMainWindow - > GetAddKeys ( ) , TransformedObjectDistance ) ;
2016-10-05 23:28:52 +02:00
Camera - > UpdatePosition ( mCurrentStep ) ;
Moved = true ;
}
}
2019-03-09 18:50:34 +01:00
for ( lcLight * Light : mLights )
2016-10-05 23:28:52 +02:00
{
if ( Light - > IsSelected ( ) )
{
2018-01-15 20:35:15 +01:00
Light - > MoveSelected ( mCurrentStep , gMainWindow - > GetAddKeys ( ) , TransformedObjectDistance ) ;
2016-10-05 23:28:52 +02:00
Light - > UpdatePosition ( mCurrentStep ) ;
Moved = true ;
}
}
}
if ( Moved & & Update )
{
gMainWindow - > UpdateAllViews ( ) ;
if ( Checkpoint )
2017-03-09 00:49:57 +01:00
SaveCheckpoint ( tr ( " Moving " ) ) ;
2016-10-05 23:28:52 +02:00
gMainWindow - > UpdateSelectedObjects ( false ) ;
}
}
2020-04-27 05:01:35 +02:00
void lcModel : : RotateSelectedPieces ( const lcVector3 & Angles , bool Relative , bool RotatePivotPoint , bool Update , bool Checkpoint )
2016-10-05 23:28:52 +02:00
{
if ( Angles . LengthSquared ( ) < 0.001f )
return ;
lcMatrix33 RotationMatrix = lcMatrix33Identity ( ) ;
bool Rotated = false ;
if ( Angles [ 0 ] ! = 0.0f )
RotationMatrix = lcMul ( lcMatrix33RotationX ( Angles [ 0 ] * LC_DTOR ) , RotationMatrix ) ;
if ( Angles [ 1 ] ! = 0.0f )
RotationMatrix = lcMul ( lcMatrix33RotationY ( Angles [ 1 ] * LC_DTOR ) , RotationMatrix ) ;
if ( Angles [ 2 ] ! = 0.0f )
RotationMatrix = lcMul ( lcMatrix33RotationZ ( Angles [ 2 ] * LC_DTOR ) , RotationMatrix ) ;
2020-04-27 05:01:35 +02:00
if ( RotatePivotPoint )
2016-10-05 23:28:52 +02:00
{
lcObject * Focus = GetFocusObject ( ) ;
if ( Focus & & Focus - > IsPiece ( ) )
{
( ( lcPiece * ) Focus ) - > RotatePivotPoint ( RotationMatrix ) ;
Rotated = true ;
}
}
else
{
2020-04-27 05:01:35 +02:00
if ( ! gMainWindow - > GetLocalTransform ( ) )
{
lcVector3 Center ;
lcMatrix33 RelativeRotation ;
2016-10-05 23:28:52 +02:00
2020-04-27 05:01:35 +02:00
GetMoveRotateTransform ( Center , RelativeRotation ) ;
2016-10-05 23:28:52 +02:00
2020-04-27 05:01:35 +02:00
lcMatrix33 WorldToFocusMatrix ;
2016-10-05 23:28:52 +02:00
2020-04-27 05:01:35 +02:00
if ( Relative )
{
WorldToFocusMatrix = lcMatrix33AffineInverse ( RelativeRotation ) ;
RotationMatrix = lcMul ( RotationMatrix , RelativeRotation ) ;
}
else
WorldToFocusMatrix = lcMatrix33Identity ( ) ;
for ( lcPiece * Piece : mPieces )
{
if ( ! Piece - > IsSelected ( ) )
continue ;
Piece - > Rotate ( mCurrentStep , gMainWindow - > GetAddKeys ( ) , RotationMatrix , Center , WorldToFocusMatrix ) ;
Piece - > UpdatePosition ( mCurrentStep ) ;
Rotated = true ;
}
2016-10-05 23:28:52 +02:00
}
else
{
2020-04-27 05:01:35 +02:00
for ( lcPiece * Piece : mPieces )
{
if ( ! Piece - > IsSelected ( ) )
continue ;
2016-10-05 23:28:52 +02:00
2020-04-27 05:01:35 +02:00
const lcVector3 Center = Piece - > GetRotationCenter ( ) ;
lcMatrix33 WorldToFocusMatrix ;
lcMatrix33 RelativeRotationMatrix ;
if ( Relative )
{
lcMatrix33 RelativeRotation = Piece - > GetRelativeRotation ( ) ;
WorldToFocusMatrix = lcMatrix33AffineInverse ( RelativeRotation ) ;
RelativeRotationMatrix = lcMul ( RotationMatrix , RelativeRotation ) ;
}
else
{
WorldToFocusMatrix = lcMatrix33Identity ( ) ;
RelativeRotationMatrix = RotationMatrix ;
}
Piece - > Rotate ( mCurrentStep , gMainWindow - > GetAddKeys ( ) , RelativeRotationMatrix , Center , WorldToFocusMatrix ) ;
Piece - > UpdatePosition ( mCurrentStep ) ;
Rotated = true ;
}
2016-10-05 23:28:52 +02:00
}
}
if ( Rotated & & Update )
{
gMainWindow - > UpdateAllViews ( ) ;
if ( Checkpoint )
2017-03-09 00:49:57 +01:00
SaveCheckpoint ( tr ( " Rotating " ) ) ;
2016-10-05 23:28:52 +02:00
gMainWindow - > UpdateSelectedObjects ( false ) ;
}
}
void lcModel : : ScaleSelectedPieces ( const float Scale , bool Update , bool Checkpoint )
{
if ( Scale < 0.001f )
return ;
lcObject * Focus = GetFocusObject ( ) ;
if ( ! Focus | | ! Focus - > IsPiece ( ) )
return ;
lcPiece * Piece = ( lcPiece * ) Focus ;
2017-12-02 21:22:04 +01:00
quint32 Section = Piece - > GetFocusSection ( ) ;
2016-10-05 23:28:52 +02:00
2020-03-22 19:12:15 +01:00
if ( Section > = LC_PIECE_SECTION_CONTROL_POINT_FIRST & & Section < = LC_PIECE_SECTION_CONTROL_POINT_LAST )
2016-10-05 23:28:52 +02:00
{
2020-03-22 19:12:15 +01:00
int ControlPointIndex = Section - LC_PIECE_SECTION_CONTROL_POINT_FIRST ;
2016-10-05 23:28:52 +02:00
Piece - > SetControlPointScale ( ControlPointIndex , Scale ) ;
if ( Update )
{
gMainWindow - > UpdateAllViews ( ) ;
if ( Checkpoint )
2017-03-09 00:49:57 +01:00
SaveCheckpoint ( tr ( " Scaling " ) ) ;
2016-10-05 23:28:52 +02:00
gMainWindow - > UpdateSelectedObjects ( false ) ;
}
}
}
void lcModel : : TransformSelectedObjects ( lcTransformType TransformType , const lcVector3 & Transform )
{
switch ( TransformType )
{
2020-05-03 22:04:40 +02:00
case lcTransformType : : AbsoluteTranslation :
2016-10-05 23:28:52 +02:00
MoveSelectedObjects ( Transform , false , false , true , true ) ;
break ;
2020-05-03 22:04:40 +02:00
case lcTransformType : : RelativeTranslation :
2016-10-05 23:28:52 +02:00
MoveSelectedObjects ( Transform , true , false , true , true ) ;
break ;
2020-05-03 22:04:40 +02:00
case lcTransformType : : AbsoluteRotation :
2016-10-05 23:28:52 +02:00
RotateSelectedPieces ( Transform , false , false , true , true ) ;
break ;
2020-05-03 22:04:40 +02:00
case lcTransformType : : RelativeRotation :
2016-10-05 23:28:52 +02:00
RotateSelectedPieces ( Transform , true , false , true , true ) ;
break ;
2020-06-01 21:29:30 +02:00
case lcTransformType : : Count :
break ;
2016-10-05 23:28:52 +02:00
}
}
void lcModel : : SetSelectedPiecesColorIndex ( int ColorIndex )
{
bool Modified = false ;
2019-03-09 18:50:34 +01:00
for ( lcPiece * Piece : mPieces )
2016-10-05 23:28:52 +02:00
{
if ( Piece - > IsSelected ( ) & & Piece - > mColorIndex ! = ColorIndex )
{
Piece - > SetColorIndex ( ColorIndex ) ;
Modified = true ;
}
}
if ( Modified )
{
SaveCheckpoint ( tr ( " Painting " ) ) ;
gMainWindow - > UpdateSelectedObjects ( false ) ;
gMainWindow - > UpdateAllViews ( ) ;
gMainWindow - > UpdateTimeline ( false , true ) ;
}
}
void lcModel : : SetSelectedPiecesPieceInfo ( PieceInfo * Info )
{
bool Modified = false ;
2019-03-09 18:50:34 +01:00
for ( lcPiece * Piece : mPieces )
2016-10-05 23:28:52 +02:00
{
if ( Piece - > IsSelected ( ) & & Piece - > mPieceInfo ! = Info )
{
2017-01-23 04:28:05 +01:00
lcPiecesLibrary * Library = lcGetPiecesLibrary ( ) ;
Library - > ReleasePieceInfo ( Piece - > mPieceInfo ) ;
2017-07-23 05:54:33 +02:00
Piece - > SetPieceInfo ( Info , QString ( ) , true ) ;
2016-10-05 23:28:52 +02:00
Modified = true ;
}
}
if ( Modified )
{
SaveCheckpoint ( tr ( " Setting Part " ) ) ;
gMainWindow - > UpdateSelectedObjects ( false ) ;
gMainWindow - > UpdateAllViews ( ) ;
gMainWindow - > UpdateTimeline ( false , true ) ;
}
}
void lcModel : : SetSelectedPiecesStepShow ( lcStep Step )
{
bool Modified = false ;
bool SelectionChanged = false ;
2019-03-09 18:50:34 +01:00
for ( lcPiece * Piece : mPieces )
2016-10-05 23:28:52 +02:00
{
if ( Piece - > IsSelected ( ) & & Piece - > GetStepShow ( ) ! = Step )
{
Piece - > SetStepShow ( Step ) ;
if ( ! Piece - > IsVisible ( mCurrentStep ) )
{
Piece - > SetSelected ( false ) ;
SelectionChanged = true ;
}
Modified = true ;
}
}
if ( Modified )
{
SaveCheckpoint ( tr ( " Showing Pieces " ) ) ;
gMainWindow - > UpdateAllViews ( ) ;
gMainWindow - > UpdateTimeline ( false , false ) ;
gMainWindow - > UpdateSelectedObjects ( SelectionChanged ) ;
}
}
void lcModel : : SetSelectedPiecesStepHide ( lcStep Step )
{
bool Modified = false ;
bool SelectionChanged = false ;
2019-03-09 18:50:34 +01:00
for ( lcPiece * Piece : mPieces )
2016-10-05 23:28:52 +02:00
{
if ( Piece - > IsSelected ( ) & & Piece - > GetStepHide ( ) ! = Step )
{
Piece - > SetStepHide ( Step ) ;
if ( ! Piece - > IsVisible ( mCurrentStep ) )
{
Piece - > SetSelected ( false ) ;
SelectionChanged = true ;
}
Modified = true ;
}
}
if ( Modified )
{
SaveCheckpoint ( tr ( " Hiding Pieces " ) ) ;
gMainWindow - > UpdateAllViews ( ) ;
gMainWindow - > UpdateTimeline ( false , false ) ;
gMainWindow - > UpdateSelectedObjects ( SelectionChanged ) ;
}
}
void lcModel : : SetCameraOrthographic ( lcCamera * Camera , bool Ortho )
{
if ( Camera - > IsOrtho ( ) = = Ortho )
return ;
Camera - > SetOrtho ( Ortho ) ;
Camera - > UpdatePosition ( mCurrentStep ) ;
SaveCheckpoint ( tr ( " Editing Camera " ) ) ;
gMainWindow - > UpdateAllViews ( ) ;
gMainWindow - > UpdatePerspective ( ) ;
}
void lcModel : : SetCameraFOV ( lcCamera * Camera , float FOV )
{
if ( Camera - > m_fovy = = FOV )
return ;
Camera - > m_fovy = FOV ;
Camera - > UpdatePosition ( mCurrentStep ) ;
SaveCheckpoint ( tr ( " Changing FOV " ) ) ;
gMainWindow - > UpdateAllViews ( ) ;
}
void lcModel : : SetCameraZNear ( lcCamera * Camera , float ZNear )
{
if ( Camera - > m_zNear = = ZNear )
return ;
Camera - > m_zNear = ZNear ;
Camera - > UpdatePosition ( mCurrentStep ) ;
SaveCheckpoint ( tr ( " Editing Camera " ) ) ;
gMainWindow - > UpdateAllViews ( ) ;
}
void lcModel : : SetCameraZFar ( lcCamera * Camera , float ZFar )
{
if ( Camera - > m_zFar = = ZFar )
return ;
Camera - > m_zFar = ZFar ;
Camera - > UpdatePosition ( mCurrentStep ) ;
SaveCheckpoint ( tr ( " Editing Camera " ) ) ;
gMainWindow - > UpdateAllViews ( ) ;
}
void lcModel : : SetCameraName ( lcCamera * Camera , const char * Name )
{
if ( ! strcmp ( Camera - > m_strName , Name ) )
return ;
strncpy ( Camera - > m_strName , Name , sizeof ( Camera - > m_strName ) ) ;
Camera - > m_strName [ sizeof ( Camera - > m_strName ) - 1 ] = 0 ;
SaveCheckpoint ( tr ( " Renaming Camera " ) ) ;
gMainWindow - > UpdateSelectedObjects ( false ) ;
gMainWindow - > UpdateAllViews ( ) ;
gMainWindow - > UpdateCameraMenu ( ) ;
}
bool lcModel : : AnyPiecesSelected ( ) const
{
2019-03-09 18:50:34 +01:00
for ( lcPiece * Piece : mPieces )
if ( Piece - > IsSelected ( ) )
2016-10-05 23:28:52 +02:00
return true ;
return false ;
}
bool lcModel : : AnyObjectsSelected ( ) const
{
2019-03-09 18:50:34 +01:00
for ( lcPiece * Piece : mPieces )
if ( Piece - > IsSelected ( ) )
2016-10-05 23:28:52 +02:00
return true ;
2019-03-09 18:50:34 +01:00
for ( lcCamera * Camera : mCameras )
if ( Camera - > IsSelected ( ) )
2016-10-05 23:28:52 +02:00
return true ;
2019-03-09 18:50:34 +01:00
for ( lcLight * Light : mLights )
if ( Light - > IsSelected ( ) )
2016-10-05 23:28:52 +02:00
return true ;
return false ;
}
lcObject * lcModel : : GetFocusObject ( ) const
{
2019-03-09 18:50:34 +01:00
for ( lcPiece * Piece : mPieces )
2016-10-05 23:28:52 +02:00
if ( Piece - > IsFocused ( ) )
return Piece ;
2019-03-09 18:50:34 +01:00
for ( lcCamera * Camera : mCameras )
2016-10-05 23:28:52 +02:00
if ( Camera - > IsFocused ( ) )
return Camera ;
2019-03-09 18:50:34 +01:00
for ( lcLight * Light : mLights )
2016-10-05 23:28:52 +02:00
if ( Light - > IsFocused ( ) )
return Light ;
2017-04-14 02:26:40 +02:00
return nullptr ;
2016-10-05 23:28:52 +02:00
}
lcModel * lcModel : : GetFirstSelectedSubmodel ( ) const
{
2019-03-09 18:50:34 +01:00
for ( lcPiece * Piece : mPieces )
2016-10-05 23:28:52 +02:00
if ( Piece - > IsSelected ( ) & & Piece - > mPieceInfo - > IsModel ( ) )
return Piece - > mPieceInfo - > GetModel ( ) ;
2017-04-14 02:26:40 +02:00
return nullptr ;
2016-10-05 23:28:52 +02:00
}
2020-01-11 21:45:36 +01:00
void lcModel : : GetSubModels ( lcArray < lcModel * > & SubModels ) const
2016-10-05 23:28:52 +02:00
{
2019-03-09 18:50:34 +01:00
for ( lcPiece * Piece : mPieces )
2016-10-05 23:28:52 +02:00
{
if ( Piece - > mPieceInfo - > IsModel ( ) )
{
lcModel * SubModel = Piece - > mPieceInfo - > GetModel ( ) ;
2020-01-11 21:45:36 +01:00
if ( SubModels . FindIndex ( SubModel ) = = - 1 )
2016-10-05 23:28:52 +02:00
SubModels . Add ( SubModel ) ;
}
}
}
bool lcModel : : GetMoveRotateTransform ( lcVector3 & Center , lcMatrix33 & RelativeRotation ) const
{
bool Relative = gMainWindow - > GetRelativeTransform ( ) ;
int NumSelected = 0 ;
Center = lcVector3 ( 0.0f , 0.0f , 0.0f ) ;
RelativeRotation = lcMatrix33Identity ( ) ;
2019-03-09 18:50:34 +01:00
for ( lcPiece * Piece : mPieces )
2016-10-05 23:28:52 +02:00
{
if ( ! Piece - > IsSelected ( ) )
continue ;
if ( Piece - > IsFocused ( ) & & Relative )
{
Center = Piece - > GetRotationCenter ( ) ;
RelativeRotation = Piece - > GetRelativeRotation ( ) ;
return true ;
}
Center + = Piece - > mModelWorld . GetTranslation ( ) ;
NumSelected + + ;
}
2019-03-09 18:50:34 +01:00
for ( lcCamera * Camera : mCameras )
2016-10-05 23:28:52 +02:00
{
if ( ! Camera - > IsSelected ( ) )
continue ;
if ( Camera - > IsFocused ( ) & & Relative )
{
Center = Camera - > GetSectionPosition ( Camera - > GetFocusSection ( ) ) ;
// RelativeRotation = Piece->GetRelativeRotation();
return true ;
}
Center + = Camera - > GetSectionPosition ( LC_CAMERA_SECTION_POSITION ) ;
Center + = Camera - > GetSectionPosition ( LC_CAMERA_SECTION_TARGET ) ;
Center + = Camera - > GetSectionPosition ( LC_CAMERA_SECTION_UPVECTOR ) ;
NumSelected + = 3 ;
}
2019-03-09 18:50:34 +01:00
for ( lcLight * Light : mLights )
2016-10-05 23:28:52 +02:00
{
if ( ! Light - > IsSelected ( ) )
continue ;
if ( Light - > IsFocused ( ) & & Relative )
{
Center = Light - > GetSectionPosition ( Light - > GetFocusSection ( ) ) ;
// RelativeRotation = Piece->GetRelativeRotation();
return true ;
}
Center + = Light - > GetSectionPosition ( LC_LIGHT_SECTION_POSITION ) ;
NumSelected + + ;
if ( Light - > IsSpotLight ( ) | | Light - > IsDirectionalLight ( ) )
{
Center + = Light - > GetSectionPosition ( LC_LIGHT_SECTION_TARGET ) ;
NumSelected + + ;
}
}
if ( NumSelected )
{
Center / = NumSelected ;
return true ;
}
return false ;
}
bool lcModel : : GetPieceFocusOrSelectionCenter ( lcVector3 & Center ) const
{
lcVector3 Min ( FLT_MAX , FLT_MAX , FLT_MAX ) , Max ( - FLT_MAX , - FLT_MAX , - FLT_MAX ) ;
2017-04-14 02:26:40 +02:00
lcPiece * Selected = nullptr ;
2016-10-05 23:28:52 +02:00
int NumSelected = 0 ;
2019-03-09 18:50:34 +01:00
for ( lcPiece * Piece : mPieces )
2016-10-05 23:28:52 +02:00
{
if ( Piece - > IsFocused ( ) )
{
Center = Piece - > mModelWorld . GetTranslation ( ) ;
return true ;
}
if ( Piece - > IsSelected ( ) )
{
Piece - > CompareBoundingBox ( Min , Max ) ;
Selected = Piece ;
NumSelected + + ;
}
}
if ( NumSelected = = 1 )
Center = Selected - > mModelWorld . GetTranslation ( ) ;
else if ( NumSelected )
Center = ( Min + Max ) / 2.0f ;
else
Center = lcVector3 ( 0.0f , 0.0f , 0.0f ) ;
return NumSelected ! = 0 ;
}
lcVector3 lcModel : : GetSelectionOrModelCenter ( ) const
{
lcVector3 Center ;
if ( ! GetSelectionCenter ( Center ) )
{
lcVector3 Min ( FLT_MAX , FLT_MAX , FLT_MAX ) , Max ( - FLT_MAX , - FLT_MAX , - FLT_MAX ) ;
if ( GetPiecesBoundingBox ( Min , Max ) )
Center = ( Min + Max ) / 2.0f ;
else
Center = lcVector3 ( 0.0f , 0.0f , 0.0f ) ;
}
return Center ;
}
bool lcModel : : GetFocusPosition ( lcVector3 & Position ) const
{
lcObject * FocusObject = GetFocusObject ( ) ;
if ( FocusObject )
{
Position = FocusObject - > GetSectionPosition ( FocusObject - > GetFocusSection ( ) ) ;
return true ;
}
else
{
Position = lcVector3 ( 0.0f , 0.0f , 0.0f ) ;
return false ;
}
}
bool lcModel : : GetSelectionCenter ( lcVector3 & Center ) const
{
lcVector3 Min ( FLT_MAX , FLT_MAX , FLT_MAX ) , Max ( - FLT_MAX , - FLT_MAX , - FLT_MAX ) ;
2017-04-14 02:26:40 +02:00
lcPiece * SelectedPiece = nullptr ;
2016-10-05 23:28:52 +02:00
bool SinglePieceSelected = true ;
bool Selected = false ;
2019-03-09 18:50:34 +01:00
for ( lcPiece * Piece : mPieces )
2016-10-05 23:28:52 +02:00
{
if ( Piece - > IsSelected ( ) )
{
Piece - > CompareBoundingBox ( Min , Max ) ;
Selected = true ;
if ( ! SelectedPiece )
SelectedPiece = Piece ;
else
SinglePieceSelected = false ;
}
}
2019-03-09 18:50:34 +01:00
for ( lcCamera * Camera : mCameras )
2016-10-05 23:28:52 +02:00
{
if ( Camera - > IsSelected ( ) )
{
Camera - > CompareBoundingBox ( Min , Max ) ;
Selected = true ;
SinglePieceSelected = false ;
}
}
2019-03-09 18:50:34 +01:00
for ( lcLight * Light : mLights )
2016-10-05 23:28:52 +02:00
{
if ( Light - > IsSelected ( ) )
{
Light - > CompareBoundingBox ( Min , Max ) ;
Selected = true ;
SinglePieceSelected = false ;
}
}
if ( SelectedPiece & & SinglePieceSelected )
Center = SelectedPiece - > GetSectionPosition ( LC_PIECE_SECTION_POSITION ) ;
else if ( Selected )
Center = ( Min + Max ) / 2.0f ;
else
Center = lcVector3 ( 0.0f , 0.0f , 0.0f ) ;
return Selected ;
}
bool lcModel : : GetPiecesBoundingBox ( lcVector3 & Min , lcVector3 & Max ) const
{
2017-03-03 21:01:49 +01:00
bool Valid = false ;
2016-10-05 23:28:52 +02:00
Min = lcVector3 ( FLT_MAX , FLT_MAX , FLT_MAX ) ;
Max = lcVector3 ( - FLT_MAX , - FLT_MAX , - FLT_MAX ) ;
2019-03-09 18:50:34 +01:00
for ( lcPiece * Piece : mPieces )
2016-10-05 23:28:52 +02:00
{
if ( Piece - > IsVisible ( mCurrentStep ) )
2017-03-03 21:01:49 +01:00
{
2016-10-05 23:28:52 +02:00
Piece - > CompareBoundingBox ( Min , Max ) ;
2017-03-03 21:01:49 +01:00
Valid = true ;
}
2016-10-05 23:28:52 +02:00
}
2017-03-03 21:01:49 +01:00
return Valid ;
2016-10-05 23:28:52 +02:00
}
2020-01-11 21:45:36 +01:00
void lcModel : : GetPartsList ( int DefaultColorIndex , bool ScanSubModels , bool AddSubModels , lcPartsList & PartsList ) const
2016-10-05 23:28:52 +02:00
{
2019-03-09 18:50:34 +01:00
for ( lcPiece * Piece : mPieces )
2016-10-05 23:28:52 +02:00
{
2019-03-13 22:36:40 +01:00
if ( ! Piece - > IsVisibleInSubModel ( ) )
continue ;
2016-10-05 23:28:52 +02:00
int ColorIndex = Piece - > mColorIndex ;
if ( ColorIndex = = gDefaultColor )
ColorIndex = DefaultColorIndex ;
2020-01-11 21:45:36 +01:00
Piece - > mPieceInfo - > GetPartsList ( ColorIndex , ScanSubModels , AddSubModels , PartsList ) ;
2016-10-05 23:28:52 +02:00
}
}
2016-11-16 23:53:41 +01:00
void lcModel : : GetPartsListForStep ( lcStep Step , int DefaultColorIndex , lcPartsList & PartsList ) const
2016-10-05 23:28:52 +02:00
{
2019-03-09 18:50:34 +01:00
for ( lcPiece * Piece : mPieces )
2016-10-05 23:28:52 +02:00
{
2019-03-13 22:36:40 +01:00
if ( Piece - > GetStepShow ( ) ! = Step | | Piece - > IsHidden ( ) )
2016-10-05 23:28:52 +02:00
continue ;
int ColorIndex = Piece - > mColorIndex ;
if ( ColorIndex = = gDefaultColor )
ColorIndex = DefaultColorIndex ;
2020-01-11 21:45:36 +01:00
Piece - > mPieceInfo - > GetPartsList ( ColorIndex , false , true , PartsList ) ;
2016-10-05 23:28:52 +02:00
}
}
2019-05-28 01:39:51 +02:00
void lcModel : : GetModelParts ( const lcMatrix44 & WorldMatrix , int DefaultColorIndex , std : : vector < lcModelPartsEntry > & ModelParts ) const
2016-10-05 23:28:52 +02:00
{
2019-03-09 18:50:34 +01:00
for ( lcPiece * Piece : mPieces )
2019-05-26 20:08:47 +02:00
Piece - > GetModelParts ( WorldMatrix , DefaultColorIndex , ModelParts ) ;
2016-10-05 23:28:52 +02:00
}
void lcModel : : GetSelectionInformation ( int * Flags , lcArray < lcObject * > & Selection , lcObject * * Focus ) const
{
* Flags = 0 ;
2017-04-14 02:26:40 +02:00
* Focus = nullptr ;
2016-10-05 23:28:52 +02:00
if ( mPieces . IsEmpty ( ) )
* Flags | = LC_SEL_NO_PIECES ;
else
{
2017-04-14 02:26:40 +02:00
lcGroup * Group = nullptr ;
2016-10-05 23:28:52 +02:00
bool First = true ;
2019-03-09 18:50:34 +01:00
for ( lcPiece * Piece : mPieces )
2016-10-05 23:28:52 +02:00
{
if ( Piece - > IsSelected ( ) )
{
Selection . Add ( Piece ) ;
if ( Piece - > IsFocused ( ) )
* Focus = Piece ;
if ( Piece - > mPieceInfo - > IsModel ( ) )
* Flags | = LC_SEL_MODEL_SELECTED ;
if ( Piece - > IsHidden ( ) )
* Flags | = LC_SEL_HIDDEN | LC_SEL_HIDDEN_SELECTED ;
else
* Flags | = LC_SEL_VISIBLE_SELECTED ;
* Flags | = LC_SEL_PIECE | LC_SEL_SELECTED ;
2020-03-22 19:12:15 +01:00
if ( Piece - > CanAddControlPoint ( ) )
2016-10-05 23:28:52 +02:00
* Flags | = LC_SEL_CAN_ADD_CONTROL_POINT ;
2020-03-22 19:12:15 +01:00
if ( Piece - > CanRemoveControlPoint ( ) )
* Flags | = LC_SEL_CAN_REMOVE_CONTROL_POINT ;
2016-10-05 23:28:52 +02:00
2017-04-14 02:26:40 +02:00
if ( Piece - > GetGroup ( ) ! = nullptr )
2016-10-05 23:28:52 +02:00
{
* Flags | = LC_SEL_GROUPED ;
if ( Piece - > IsFocused ( ) )
* Flags | = LC_SEL_FOCUS_GROUPED ;
}
if ( First )
{
Group = Piece - > GetGroup ( ) ;
First = false ;
}
else
{
if ( Group ! = Piece - > GetGroup ( ) )
* Flags | = LC_SEL_CAN_GROUP ;
else
2017-04-14 02:26:40 +02:00
if ( Group = = nullptr )
2016-10-05 23:28:52 +02:00
* Flags | = LC_SEL_CAN_GROUP ;
}
}
else
{
* Flags | = LC_SEL_UNSELECTED ;
if ( Piece - > IsHidden ( ) )
* Flags | = LC_SEL_HIDDEN ;
}
}
}
2019-03-09 18:50:34 +01:00
for ( lcCamera * Camera : mCameras )
2016-10-05 23:28:52 +02:00
{
if ( Camera - > IsSelected ( ) )
{
Selection . Add ( Camera ) ;
* Flags | = LC_SEL_SELECTED ;
if ( Camera - > IsFocused ( ) )
* Focus = Camera ;
}
}
2019-03-09 18:50:34 +01:00
for ( lcLight * Light : mLights )
2016-10-05 23:28:52 +02:00
{
if ( Light - > IsSelected ( ) )
{
Selection . Add ( Light ) ;
* Flags | = LC_SEL_SELECTED ;
if ( Light - > IsFocused ( ) )
* Focus = Light ;
}
}
}
2017-11-22 02:58:36 +01:00
lcArray < lcObject * > lcModel : : GetSelectionModePieces ( lcPiece * SelectedPiece ) const
{
PieceInfo * Info = SelectedPiece - > mPieceInfo ;
int ColorIndex = SelectedPiece - > mColorIndex ;
lcArray < lcObject * > Pieces ;
switch ( gMainWindow - > GetSelectionMode ( ) )
{
2020-05-03 22:04:40 +02:00
case lcSelectionMode : : Single :
2017-11-22 02:58:36 +01:00
break ;
2020-05-03 22:04:40 +02:00
case lcSelectionMode : : Piece :
2017-11-22 02:58:36 +01:00
for ( lcPiece * Piece : mPieces )
if ( Piece - > IsVisible ( mCurrentStep ) & & Piece - > mPieceInfo = = Info & & Piece ! = SelectedPiece )
Pieces . Add ( Piece ) ;
break ;
2020-05-03 22:04:40 +02:00
case lcSelectionMode : : Color :
2017-11-22 02:58:36 +01:00
for ( lcPiece * Piece : mPieces )
if ( Piece - > IsVisible ( mCurrentStep ) & & Piece - > mColorIndex = = ColorIndex & & Piece ! = SelectedPiece )
Pieces . Add ( Piece ) ;
break ;
2020-05-03 22:04:40 +02:00
case lcSelectionMode : : PieceColor :
2017-11-22 02:58:36 +01:00
for ( lcPiece * Piece : mPieces )
if ( Piece - > IsVisible ( mCurrentStep ) & & Piece - > mPieceInfo = = Info & & Piece - > mColorIndex = = ColorIndex & & Piece ! = SelectedPiece )
Pieces . Add ( Piece ) ;
break ;
}
return Pieces ;
}
2016-10-05 23:28:52 +02:00
void lcModel : : ClearSelection ( bool UpdateInterface )
{
2019-03-09 18:50:34 +01:00
for ( lcPiece * Piece : mPieces )
Piece - > SetSelected ( false ) ;
2016-10-05 23:28:52 +02:00
2019-03-09 18:50:34 +01:00
for ( lcCamera * Camera : mCameras )
Camera - > SetSelected ( false ) ;
2016-10-05 23:28:52 +02:00
2019-03-09 18:50:34 +01:00
for ( lcLight * Light : mLights )
Light - > SetSelected ( false ) ;
2016-10-05 23:28:52 +02:00
if ( UpdateInterface )
{
gMainWindow - > UpdateSelectedObjects ( true ) ;
gMainWindow - > UpdateAllViews ( ) ;
}
}
void lcModel : : SelectGroup ( lcGroup * TopGroup , bool Select )
{
if ( ! TopGroup )
return ;
2019-03-09 18:50:34 +01:00
for ( lcPiece * Piece : mPieces )
2016-10-05 23:28:52 +02:00
if ( ! Piece - > IsSelected ( ) & & Piece - > IsVisible ( mCurrentStep ) & & ( Piece - > GetTopGroup ( ) = = TopGroup ) )
Piece - > SetSelected ( Select ) ;
}
void lcModel : : FocusOrDeselectObject ( const lcObjectSection & ObjectSection )
{
lcObject * FocusObject = GetFocusObject ( ) ;
lcObject * Object = ObjectSection . Object ;
2017-12-02 21:22:04 +01:00
quint32 Section = ObjectSection . Section ;
2016-10-05 23:28:52 +02:00
if ( Object )
{
bool WasSelected = Object - > IsSelected ( ) ;
if ( ! Object - > IsFocused ( Section ) )
{
if ( FocusObject )
FocusObject - > SetFocused ( FocusObject - > GetFocusSection ( ) , false ) ;
Object - > SetFocused ( Section , true ) ;
}
else
2017-11-21 00:12:00 +01:00
Object - > SetFocused ( Section , false ) ;
2016-10-05 23:28:52 +02:00
bool IsSelected = Object - > IsSelected ( ) ;
if ( Object - > IsPiece ( ) & & ( WasSelected ! = IsSelected ) )
2017-11-22 02:58:36 +01:00
{
lcPiece * Piece = ( lcPiece * ) Object ;
2020-05-03 22:04:40 +02:00
if ( gMainWindow - > GetSelectionMode ( ) = = lcSelectionMode : : Single )
2017-11-22 02:58:36 +01:00
SelectGroup ( Piece - > GetTopGroup ( ) , IsSelected ) ;
else
{
lcArray < lcObject * > Pieces = GetSelectionModePieces ( Piece ) ;
2017-11-22 07:54:49 +01:00
AddToSelection ( Pieces , false , false ) ;
2017-11-22 02:58:36 +01:00
}
}
2016-10-05 23:28:52 +02:00
}
else
{
if ( FocusObject )
FocusObject - > SetFocused ( FocusObject - > GetFocusSection ( ) , false ) ;
}
gMainWindow - > UpdateSelectedObjects ( true ) ;
gMainWindow - > UpdateAllViews ( ) ;
}
2017-12-02 21:22:04 +01:00
void lcModel : : ClearSelectionAndSetFocus ( lcObject * Object , quint32 Section , bool EnableSelectionMode )
2016-10-05 23:28:52 +02:00
{
ClearSelection ( false ) ;
if ( Object )
{
Object - > SetFocused ( Section , true ) ;
if ( Object - > IsPiece ( ) )
2017-11-22 07:54:49 +01:00
{
2016-10-05 23:28:52 +02:00
SelectGroup ( ( ( lcPiece * ) Object ) - > GetTopGroup ( ) , true ) ;
2017-11-22 02:58:36 +01:00
2017-11-22 07:54:49 +01:00
if ( EnableSelectionMode )
{
lcArray < lcObject * > Pieces = GetSelectionModePieces ( ( lcPiece * ) Object ) ;
AddToSelection ( Pieces , false , false ) ;
}
2017-11-22 02:58:36 +01:00
}
2016-10-05 23:28:52 +02:00
}
gMainWindow - > UpdateSelectedObjects ( true ) ;
gMainWindow - > UpdateAllViews ( ) ;
}
2017-11-22 02:58:36 +01:00
void lcModel : : ClearSelectionAndSetFocus ( const lcObjectSection & ObjectSection , bool EnableSelectionMode )
2016-10-05 23:28:52 +02:00
{
2017-11-22 02:58:36 +01:00
ClearSelectionAndSetFocus ( ObjectSection . Object , ObjectSection . Section , EnableSelectionMode ) ;
2016-10-05 23:28:52 +02:00
}
2017-12-02 21:22:04 +01:00
void lcModel : : SetSelectionAndFocus ( const lcArray < lcObject * > & Selection , lcObject * Focus , quint32 Section , bool EnableSelectionMode )
2016-10-05 23:28:52 +02:00
{
ClearSelection ( false ) ;
if ( Focus )
{
Focus - > SetFocused ( Section , true ) ;
if ( Focus - > IsPiece ( ) )
2017-11-22 07:54:49 +01:00
{
2016-10-05 23:28:52 +02:00
SelectGroup ( ( ( lcPiece * ) Focus ) - > GetTopGroup ( ) , true ) ;
2017-11-22 07:54:49 +01:00
if ( EnableSelectionMode )
{
lcArray < lcObject * > Pieces = GetSelectionModePieces ( ( lcPiece * ) Focus ) ;
AddToSelection ( Pieces , false , false ) ;
}
}
2016-10-05 23:28:52 +02:00
}
2017-11-22 07:54:49 +01:00
AddToSelection ( Selection , EnableSelectionMode , true ) ;
2016-10-05 23:28:52 +02:00
}
2017-11-22 07:54:49 +01:00
void lcModel : : AddToSelection ( const lcArray < lcObject * > & Objects , bool EnableSelectionMode , bool UpdateInterface )
2016-10-05 23:28:52 +02:00
{
2017-11-22 07:54:49 +01:00
for ( lcObject * Object : Objects )
2016-10-05 23:28:52 +02:00
{
bool WasSelected = Object - > IsSelected ( ) ;
2017-11-21 00:12:00 +01:00
Object - > SetSelected ( true ) ;
2016-10-05 23:28:52 +02:00
2017-11-22 07:54:49 +01:00
if ( Object - > IsPiece ( ) )
{
if ( ! WasSelected )
SelectGroup ( ( ( lcPiece * ) Object ) - > GetTopGroup ( ) , true ) ;
if ( EnableSelectionMode )
{
lcArray < lcObject * > Pieces = GetSelectionModePieces ( ( lcPiece * ) Object ) ;
AddToSelection ( Pieces , false , false ) ;
}
}
2016-10-05 23:28:52 +02:00
}
2017-11-22 02:58:36 +01:00
if ( UpdateInterface )
{
gMainWindow - > UpdateSelectedObjects ( true ) ;
gMainWindow - > UpdateAllViews ( ) ;
}
2016-10-05 23:28:52 +02:00
}
2017-11-21 00:12:00 +01:00
void lcModel : : RemoveFromSelection ( const lcArray < lcObject * > & Objects )
{
2017-11-22 07:54:49 +01:00
for ( lcObject * SelectedObject : Objects )
2017-11-21 00:12:00 +01:00
{
2017-11-22 07:54:49 +01:00
bool WasSelected = SelectedObject - > IsSelected ( ) ;
SelectedObject - > SetSelected ( false ) ;
if ( WasSelected & & SelectedObject - > IsPiece ( ) )
{
lcPiece * Piece = ( lcPiece * ) SelectedObject ;
2017-11-21 00:12:00 +01:00
2020-05-03 22:04:40 +02:00
if ( gMainWindow - > GetSelectionMode ( ) = = lcSelectionMode : : Single )
2017-11-22 07:54:49 +01:00
SelectGroup ( Piece - > GetTopGroup ( ) , false ) ;
else
{
lcArray < lcObject * > Pieces = GetSelectionModePieces ( Piece ) ;
for ( lcObject * Object : Pieces )
{
if ( Object - > IsSelected ( ) )
{
Object - > SetSelected ( false ) ;
SelectGroup ( ( ( lcPiece * ) Object ) - > GetTopGroup ( ) , false ) ;
}
}
}
}
2017-11-21 00:12:00 +01:00
}
gMainWindow - > UpdateSelectedObjects ( true ) ;
gMainWindow - > UpdateAllViews ( ) ;
}
void lcModel : : RemoveFromSelection ( const lcObjectSection & ObjectSection )
{
2017-11-22 07:54:49 +01:00
lcObject * SelectedObject = ObjectSection . Object ;
2017-11-21 00:12:00 +01:00
2017-11-22 07:54:49 +01:00
if ( ! SelectedObject )
2017-11-21 00:12:00 +01:00
return ;
2017-11-22 07:54:49 +01:00
bool WasSelected = SelectedObject - > IsSelected ( ) ;
2017-11-22 02:58:36 +01:00
2017-11-22 07:54:49 +01:00
if ( SelectedObject - > IsFocused ( ObjectSection . Section ) )
SelectedObject - > SetSelected ( ObjectSection . Section , false ) ;
2017-11-21 00:12:00 +01:00
else
2017-11-22 07:54:49 +01:00
SelectedObject - > SetSelected ( false ) ;
2017-11-21 00:12:00 +01:00
2017-11-22 07:54:49 +01:00
if ( SelectedObject - > IsPiece ( ) & & WasSelected )
{
lcPiece * Piece = ( lcPiece * ) SelectedObject ;
2020-05-03 22:04:40 +02:00
if ( gMainWindow - > GetSelectionMode ( ) = = lcSelectionMode : : Single )
2017-11-22 07:54:49 +01:00
SelectGroup ( Piece - > GetTopGroup ( ) , false ) ;
else
{
lcArray < lcObject * > Pieces = GetSelectionModePieces ( Piece ) ;
for ( lcObject * Object : Pieces )
{
if ( Object - > IsSelected ( ) )
{
Object - > SetSelected ( false ) ;
SelectGroup ( ( ( lcPiece * ) Object ) - > GetTopGroup ( ) , false ) ;
}
}
}
}
2017-11-22 02:58:36 +01:00
2017-11-21 00:12:00 +01:00
gMainWindow - > UpdateSelectedObjects ( true ) ;
gMainWindow - > UpdateAllViews ( ) ;
}
2016-10-05 23:28:52 +02:00
void lcModel : : SelectAllPieces ( )
{
2018-09-02 19:31:57 +02:00
for ( lcPiece * Piece : mPieces )
2016-10-05 23:28:52 +02:00
if ( Piece - > IsVisible ( mCurrentStep ) )
Piece - > SetSelected ( true ) ;
gMainWindow - > UpdateSelectedObjects ( true ) ;
gMainWindow - > UpdateAllViews ( ) ;
}
void lcModel : : InvertSelection ( )
{
2018-09-02 19:31:57 +02:00
for ( lcPiece * Piece : mPieces )
2016-10-05 23:28:52 +02:00
if ( Piece - > IsVisible ( mCurrentStep ) )
Piece - > SetSelected ( ! Piece - > IsSelected ( ) ) ;
gMainWindow - > UpdateSelectedObjects ( true ) ;
gMainWindow - > UpdateAllViews ( ) ;
}
void lcModel : : HideSelectedPieces ( )
{
2018-09-02 19:31:57 +02:00
bool Modified = false ;
2016-10-05 23:28:52 +02:00
2018-09-02 19:31:57 +02:00
for ( lcPiece * Piece : mPieces )
{
2016-10-05 23:28:52 +02:00
if ( Piece - > IsSelected ( ) )
{
Piece - > SetHidden ( true ) ;
Piece - > SetSelected ( false ) ;
2018-09-02 19:31:57 +02:00
Modified = true ;
2016-10-05 23:28:52 +02:00
}
}
2018-09-02 19:31:57 +02:00
if ( ! Modified )
return ;
2016-10-05 23:28:52 +02:00
gMainWindow - > UpdateTimeline ( false , true ) ;
gMainWindow - > UpdateSelectedObjects ( true ) ;
gMainWindow - > UpdateAllViews ( ) ;
2018-09-02 19:31:57 +02:00
SaveCheckpoint ( tr ( " Hide " ) ) ;
2016-10-05 23:28:52 +02:00
}
void lcModel : : HideUnselectedPieces ( )
{
2018-09-02 19:31:57 +02:00
bool Modified = false ;
2016-10-05 23:28:52 +02:00
2018-09-02 19:31:57 +02:00
for ( lcPiece * Piece : mPieces )
{
2016-10-05 23:28:52 +02:00
if ( ! Piece - > IsSelected ( ) )
2018-09-02 19:31:57 +02:00
{
2016-10-05 23:28:52 +02:00
Piece - > SetHidden ( true ) ;
2018-09-02 19:31:57 +02:00
Modified = true ;
}
2016-10-05 23:28:52 +02:00
}
2018-09-02 19:31:57 +02:00
if ( ! Modified )
return ;
2016-10-05 23:28:52 +02:00
gMainWindow - > UpdateTimeline ( false , true ) ;
gMainWindow - > UpdateSelectedObjects ( true ) ;
gMainWindow - > UpdateAllViews ( ) ;
2018-09-02 19:31:57 +02:00
SaveCheckpoint ( tr ( " Hide " ) ) ;
2016-10-05 23:28:52 +02:00
}
void lcModel : : UnhideSelectedPieces ( )
{
2018-09-02 19:31:57 +02:00
bool Modified = false ;
2016-10-05 23:28:52 +02:00
2018-09-02 19:31:57 +02:00
for ( lcPiece * Piece : mPieces )
{
if ( Piece - > IsSelected ( ) & & Piece - > IsHidden ( ) )
{
2016-10-05 23:28:52 +02:00
Piece - > SetHidden ( false ) ;
2018-09-02 19:31:57 +02:00
Modified = true ;
}
2016-10-05 23:28:52 +02:00
}
2018-09-02 19:31:57 +02:00
if ( ! Modified )
return ;
2016-10-05 23:28:52 +02:00
gMainWindow - > UpdateTimeline ( false , true ) ;
gMainWindow - > UpdateSelectedObjects ( true ) ;
gMainWindow - > UpdateAllViews ( ) ;
2018-09-02 19:31:57 +02:00
SaveCheckpoint ( tr ( " Unhide " ) ) ;
2016-10-05 23:28:52 +02:00
}
void lcModel : : UnhideAllPieces ( )
{
2018-09-02 19:31:57 +02:00
bool Modified = false ;
for ( lcPiece * Piece : mPieces )
{
if ( Piece - > IsHidden ( ) )
{
Piece - > SetHidden ( false ) ;
Modified = true ;
}
}
if ( ! Modified )
return ;
2016-10-05 23:28:52 +02:00
gMainWindow - > UpdateTimeline ( false , true ) ;
gMainWindow - > UpdateSelectedObjects ( true ) ;
gMainWindow - > UpdateAllViews ( ) ;
2018-09-02 19:31:57 +02:00
SaveCheckpoint ( tr ( " Unhide " ) ) ;
2016-10-05 23:28:52 +02:00
}
void lcModel : : FindPiece ( bool FindFirst , bool SearchForward )
{
if ( mPieces . IsEmpty ( ) )
return ;
int StartIdx = mPieces . GetSize ( ) - 1 ;
if ( ! FindFirst )
{
for ( int PieceIdx = 0 ; PieceIdx < mPieces . GetSize ( ) ; PieceIdx + + )
{
lcPiece * Piece = mPieces [ PieceIdx ] ;
if ( Piece - > IsFocused ( ) & & Piece - > IsVisible ( mCurrentStep ) )
{
StartIdx = PieceIdx ;
break ;
}
}
}
int CurrentIdx = StartIdx ;
2017-04-14 02:26:40 +02:00
lcObject * Focus = nullptr ;
2016-10-05 23:28:52 +02:00
const lcSearchOptions & SearchOptions = gMainWindow - > mSearchOptions ;
for ( ; ; )
{
if ( SearchForward )
CurrentIdx + + ;
else
CurrentIdx - - ;
if ( CurrentIdx < 0 )
CurrentIdx = mPieces . GetSize ( ) - 1 ;
else if ( CurrentIdx > = mPieces . GetSize ( ) )
CurrentIdx = 0 ;
if ( CurrentIdx = = StartIdx )
break ;
lcPiece * Current = mPieces [ CurrentIdx ] ;
if ( ! Current - > IsVisible ( mCurrentStep ) )
continue ;
if ( ( ! SearchOptions . MatchInfo | | Current - > mPieceInfo = = SearchOptions . Info ) & &
( ! SearchOptions . MatchColor | | Current - > mColorIndex = = SearchOptions . ColorIndex ) & &
( ! SearchOptions . MatchName | | strcasestr ( Current - > GetName ( ) , SearchOptions . Name ) ) )
{
Focus = Current ;
break ;
}
}
2017-11-22 02:58:36 +01:00
ClearSelectionAndSetFocus ( Focus , LC_PIECE_SECTION_POSITION , false ) ;
2016-10-05 23:28:52 +02:00
}
void lcModel : : UndoAction ( )
{
2019-06-24 03:28:14 +02:00
if ( mUndoHistory . size ( ) < 2 )
2016-10-05 23:28:52 +02:00
return ;
2019-06-24 03:28:14 +02:00
lcModelHistoryEntry * Undo = mUndoHistory . front ( ) ;
mUndoHistory . erase ( mUndoHistory . begin ( ) ) ;
mRedoHistory . insert ( mRedoHistory . begin ( ) , Undo ) ;
2016-10-05 23:28:52 +02:00
LoadCheckPoint ( mUndoHistory [ 0 ] ) ;
gMainWindow - > UpdateModified ( IsModified ( ) ) ;
2019-06-24 03:28:14 +02:00
gMainWindow - > UpdateUndoRedo ( mUndoHistory . size ( ) > 1 ? mUndoHistory [ 0 ] - > Description : nullptr , ! mRedoHistory . empty ( ) ? mRedoHistory [ 0 ] - > Description : nullptr ) ;
2016-10-05 23:28:52 +02:00
}
void lcModel : : RedoAction ( )
{
2019-06-24 03:28:14 +02:00
if ( mRedoHistory . empty ( ) )
2016-10-05 23:28:52 +02:00
return ;
2019-06-24 03:28:14 +02:00
lcModelHistoryEntry * Redo = mRedoHistory . front ( ) ;
mRedoHistory . erase ( mRedoHistory . begin ( ) ) ;
mUndoHistory . insert ( mUndoHistory . begin ( ) , Redo ) ;
2016-10-05 23:28:52 +02:00
LoadCheckPoint ( Redo ) ;
gMainWindow - > UpdateModified ( IsModified ( ) ) ;
2019-06-24 03:28:14 +02:00
gMainWindow - > UpdateUndoRedo ( mUndoHistory . size ( ) > 1 ? mUndoHistory [ 0 ] - > Description : nullptr , ! mRedoHistory . empty ( ) ? mRedoHistory [ 0 ] - > Description : nullptr ) ;
2016-10-05 23:28:52 +02:00
}
void lcModel : : BeginMouseTool ( )
{
mMouseToolDistance = lcVector3 ( 0.0f , 0.0f , 0.0f ) ;
}
void lcModel : : EndMouseTool ( lcTool Tool , bool Accept )
{
if ( ! Accept )
{
LoadCheckPoint ( mUndoHistory [ 0 ] ) ;
return ;
}
switch ( Tool )
{
case LC_TOOL_INSERT :
case LC_TOOL_LIGHT :
break ;
case LC_TOOL_SPOTLIGHT :
SaveCheckpoint ( tr ( " New SpotLight " ) ) ;
break ;
case LC_TOOL_CAMERA :
gMainWindow - > UpdateCameraMenu ( ) ;
SaveCheckpoint ( tr ( " New Camera " ) ) ;
break ;
case LC_TOOL_SELECT :
break ;
case LC_TOOL_MOVE :
SaveCheckpoint ( tr ( " Move " ) ) ;
break ;
case LC_TOOL_ROTATE :
SaveCheckpoint ( tr ( " Rotate " ) ) ;
break ;
case LC_TOOL_ERASER :
case LC_TOOL_PAINT :
2020-02-24 23:31:08 +01:00
case LC_TOOL_COLOR_PICKER :
2016-10-05 23:28:52 +02:00
break ;
case LC_TOOL_ZOOM :
if ( ! gMainWindow - > GetActiveView ( ) - > mCamera - > IsSimple ( ) )
SaveCheckpoint ( tr ( " Zoom " ) ) ;
break ;
case LC_TOOL_PAN :
if ( ! gMainWindow - > GetActiveView ( ) - > mCamera - > IsSimple ( ) )
SaveCheckpoint ( tr ( " Pan " ) ) ;
break ;
case LC_TOOL_ROTATE_VIEW :
if ( ! gMainWindow - > GetActiveView ( ) - > mCamera - > IsSimple ( ) )
SaveCheckpoint ( tr ( " Orbit " ) ) ;
break ;
case LC_TOOL_ROLL :
if ( ! gMainWindow - > GetActiveView ( ) - > mCamera - > IsSimple ( ) )
SaveCheckpoint ( tr ( " Roll " ) ) ;
break ;
case LC_TOOL_ZOOM_REGION :
break ;
case LC_NUM_TOOLS :
break ;
}
}
void lcModel : : InsertPieceToolClicked ( const lcMatrix44 & WorldMatrix )
{
2016-12-16 18:14:19 +01:00
lcPiece * Piece = new lcPiece ( gMainWindow - > GetCurrentPieceInfo ( ) ) ;
2016-10-05 23:28:52 +02:00
Piece - > Initialize ( WorldMatrix , mCurrentStep ) ;
Piece - > SetColorIndex ( gMainWindow - > mColorIndex ) ;
Piece - > UpdatePosition ( mCurrentStep ) ;
AddPiece ( Piece ) ;
gMainWindow - > UpdateTimeline ( false , false ) ;
2017-11-22 02:58:36 +01:00
ClearSelectionAndSetFocus ( Piece , LC_PIECE_SECTION_POSITION , false ) ;
2016-10-05 23:28:52 +02:00
SaveCheckpoint ( tr ( " Insert " ) ) ;
}
void lcModel : : PointLightToolClicked ( const lcVector3 & Position )
{
lcLight * Light = new lcLight ( Position [ 0 ] , Position [ 1 ] , Position [ 2 ] ) ;
Light - > CreateName ( mLights ) ;
mLights . Add ( Light ) ;
2017-11-22 02:58:36 +01:00
ClearSelectionAndSetFocus ( Light , LC_LIGHT_SECTION_POSITION , false ) ;
2016-10-05 23:28:52 +02:00
SaveCheckpoint ( tr ( " New Light " ) ) ;
}
void lcModel : : BeginSpotLightTool ( const lcVector3 & Position , const lcVector3 & Target )
{
lcLight * Light = new lcLight ( Position [ 0 ] , Position [ 1 ] , Position [ 2 ] , Target [ 0 ] , Target [ 1 ] , Target [ 2 ] ) ;
mLights . Add ( Light ) ;
mMouseToolDistance = Target ;
2017-11-22 02:58:36 +01:00
ClearSelectionAndSetFocus ( Light , LC_LIGHT_SECTION_TARGET , false ) ;
2016-10-05 23:28:52 +02:00
}
void lcModel : : UpdateSpotLightTool ( const lcVector3 & Position )
{
lcLight * Light = mLights [ mLights . GetSize ( ) - 1 ] ;
2018-01-15 20:35:15 +01:00
Light - > MoveSelected ( 1 , false , Position - mMouseToolDistance ) ;
2016-10-05 23:28:52 +02:00
Light - > UpdatePosition ( 1 ) ;
mMouseToolDistance = Position ;
gMainWindow - > UpdateSelectedObjects ( false ) ;
gMainWindow - > UpdateAllViews ( ) ;
}
void lcModel : : BeginCameraTool ( const lcVector3 & Position , const lcVector3 & Target )
{
lcCamera * Camera = new lcCamera ( Position [ 0 ] , Position [ 1 ] , Position [ 2 ] , Target [ 0 ] , Target [ 1 ] , Target [ 2 ] ) ;
Camera - > CreateName ( mCameras ) ;
mCameras . Add ( Camera ) ;
mMouseToolDistance = Position ;
2017-11-22 02:58:36 +01:00
ClearSelectionAndSetFocus ( Camera , LC_CAMERA_SECTION_TARGET , false ) ;
2016-10-05 23:28:52 +02:00
}
void lcModel : : UpdateCameraTool ( const lcVector3 & Position )
{
lcCamera * Camera = mCameras [ mCameras . GetSize ( ) - 1 ] ;
2018-01-15 20:35:15 +01:00
Camera - > MoveSelected ( 1 , false , Position - mMouseToolDistance ) ;
2016-10-05 23:28:52 +02:00
Camera - > UpdatePosition ( 1 ) ;
mMouseToolDistance = Position ;
gMainWindow - > UpdateSelectedObjects ( false ) ;
gMainWindow - > UpdateAllViews ( ) ;
}
void lcModel : : UpdateMoveTool ( const lcVector3 & Distance , bool AlternateButtonDrag )
{
2017-11-11 21:46:56 +01:00
lcVector3 PieceDistance = SnapPosition ( Distance ) - SnapPosition ( mMouseToolDistance ) ;
2016-10-05 23:28:52 +02:00
lcVector3 ObjectDistance = Distance - mMouseToolDistance ;
MoveSelectedObjects ( PieceDistance , ObjectDistance , true , AlternateButtonDrag , true , false ) ;
mMouseToolDistance = Distance ;
gMainWindow - > UpdateSelectedObjects ( false ) ;
gMainWindow - > UpdateAllViews ( ) ;
}
void lcModel : : UpdateRotateTool ( const lcVector3 & Angles , bool AlternateButtonDrag )
{
2017-11-11 21:46:56 +01:00
lcVector3 Delta = SnapRotation ( Angles ) - SnapRotation ( mMouseToolDistance ) ;
2016-10-05 23:28:52 +02:00
RotateSelectedPieces ( Delta , true , AlternateButtonDrag , false , false ) ;
mMouseToolDistance = Angles ;
gMainWindow - > UpdateSelectedObjects ( false ) ;
gMainWindow - > UpdateAllViews ( ) ;
}
void lcModel : : UpdateScaleTool ( const float Scale )
{
ScaleSelectedPieces ( Scale , true , false ) ;
gMainWindow - > UpdateSelectedObjects ( false ) ;
gMainWindow - > UpdateAllViews ( ) ;
}
void lcModel : : EraserToolClicked ( lcObject * Object )
{
if ( ! Object )
return ;
switch ( Object - > GetType ( ) )
{
2020-04-19 04:45:21 +02:00
case lcObjectType : : Piece :
2016-10-05 23:28:52 +02:00
mPieces . Remove ( ( lcPiece * ) Object ) ;
RemoveEmptyGroups ( ) ;
break ;
2020-04-19 04:45:21 +02:00
case lcObjectType : : Camera :
2016-10-05 23:28:52 +02:00
{
const lcArray < View * > * Views = gMainWindow - > GetViewsForModel ( this ) ;
for ( int ViewIdx = 0 ; ViewIdx < Views - > GetSize ( ) ; ViewIdx + + )
{
View * View = ( * Views ) [ ViewIdx ] ;
lcCamera * Camera = View - > mCamera ;
if ( Camera = = Object )
View - > SetCamera ( Camera , true ) ;
}
mCameras . Remove ( ( lcCamera * ) Object ) ;
gMainWindow - > UpdateCameraMenu ( ) ;
}
break ;
2020-04-19 04:45:21 +02:00
case lcObjectType : : Light :
2016-10-05 23:28:52 +02:00
mLights . Remove ( ( lcLight * ) Object ) ;
break ;
}
delete Object ;
gMainWindow - > UpdateTimeline ( false , false ) ;
gMainWindow - > UpdateSelectedObjects ( true ) ;
gMainWindow - > UpdateAllViews ( ) ;
SaveCheckpoint ( tr ( " Deleting " ) ) ;
}
void lcModel : : PaintToolClicked ( lcObject * Object )
{
2020-04-19 04:45:21 +02:00
if ( ! Object | | ! Object - > IsPiece ( ) )
2016-10-05 23:28:52 +02:00
return ;
lcPiece * Piece = ( lcPiece * ) Object ;
if ( Piece - > mColorIndex ! = gMainWindow - > mColorIndex )
{
Piece - > SetColorIndex ( gMainWindow - > mColorIndex ) ;
SaveCheckpoint ( tr ( " Painting " ) ) ;
gMainWindow - > UpdateSelectedObjects ( false ) ;
gMainWindow - > UpdateAllViews ( ) ;
gMainWindow - > UpdateTimeline ( false , true ) ;
}
}
2020-02-15 20:14:12 +01:00
void lcModel : : ColorPickerToolClicked ( lcObject * Object )
2020-02-15 19:59:14 +01:00
{
2020-04-19 04:45:21 +02:00
if ( ! Object | | ! Object - > IsPiece ( ) )
2020-02-15 20:14:12 +01:00
return ;
2020-02-15 19:59:14 +01:00
2020-02-15 20:14:12 +01:00
lcPiece * Piece = ( lcPiece * ) Object ;
2020-02-15 19:59:14 +01:00
2020-02-15 20:14:12 +01:00
gMainWindow - > SetColorIndex ( Piece - > mColorIndex ) ;
2020-02-15 19:59:14 +01:00
}
2016-10-05 23:28:52 +02:00
void lcModel : : UpdateZoomTool ( lcCamera * Camera , float Mouse )
{
Camera - > Zoom ( Mouse - mMouseToolDistance . x , mCurrentStep , gMainWindow - > GetAddKeys ( ) ) ;
mMouseToolDistance . x = Mouse ;
gMainWindow - > UpdateAllViews ( ) ;
}
void lcModel : : UpdatePanTool ( lcCamera * Camera , const lcVector3 & Distance )
{
Camera - > Pan ( Distance - mMouseToolDistance , mCurrentStep , gMainWindow - > GetAddKeys ( ) ) ;
mMouseToolDistance = Distance ;
gMainWindow - > UpdateAllViews ( ) ;
}
void lcModel : : UpdateOrbitTool ( lcCamera * Camera , float MouseX , float MouseY )
{
lcVector3 Center ;
GetSelectionCenter ( Center ) ;
Camera - > Orbit ( MouseX - mMouseToolDistance . x , MouseY - mMouseToolDistance . y , Center , mCurrentStep , gMainWindow - > GetAddKeys ( ) ) ;
mMouseToolDistance . x = MouseX ;
mMouseToolDistance . y = MouseY ;
gMainWindow - > UpdateAllViews ( ) ;
}
void lcModel : : UpdateRollTool ( lcCamera * Camera , float Mouse )
{
Camera - > Roll ( Mouse - mMouseToolDistance . x , mCurrentStep , gMainWindow - > GetAddKeys ( ) ) ;
mMouseToolDistance . x = Mouse ;
gMainWindow - > UpdateAllViews ( ) ;
}
void lcModel : : ZoomRegionToolClicked ( lcCamera * Camera , float AspectRatio , const lcVector3 & Position , const lcVector3 & TargetPosition , const lcVector3 * Corners )
{
Camera - > ZoomRegion ( AspectRatio , Position , TargetPosition , Corners , mCurrentStep , gMainWindow - > GetAddKeys ( ) ) ;
gMainWindow - > UpdateSelectedObjects ( false ) ;
gMainWindow - > UpdateAllViews ( ) ;
if ( ! Camera - > IsSimple ( ) )
SaveCheckpoint ( tr ( " Zoom " ) ) ;
}
void lcModel : : LookAt ( lcCamera * Camera )
{
lcVector3 Center ;
if ( ! GetSelectionCenter ( Center ) )
{
lcVector3 Min ( FLT_MAX , FLT_MAX , FLT_MAX ) , Max ( - FLT_MAX , - FLT_MAX , - FLT_MAX ) ;
if ( GetPiecesBoundingBox ( Min , Max ) )
Center = ( Min + Max ) / 2.0f ;
else
Center = lcVector3 ( 0.0f , 0.0f , 0.0f ) ;
}
Camera - > Center ( Center , mCurrentStep , gMainWindow - > GetAddKeys ( ) ) ;
gMainWindow - > UpdateSelectedObjects ( false ) ;
gMainWindow - > UpdateAllViews ( ) ;
if ( ! Camera - > IsSimple ( ) )
SaveCheckpoint ( tr ( " Look At " ) ) ;
}
2018-01-15 20:35:15 +01:00
void lcModel : : MoveCamera ( lcCamera * Camera , const lcVector3 & Direction )
{
Camera - > MoveRelative ( Direction , mCurrentStep , gMainWindow - > GetAddKeys ( ) ) ;
gMainWindow - > UpdateSelectedObjects ( false ) ;
gMainWindow - > UpdateAllViews ( ) ;
if ( ! Camera - > IsSimple ( ) )
SaveCheckpoint ( tr ( " Moving Camera " ) ) ;
}
2016-10-05 23:28:52 +02:00
void lcModel : : ZoomExtents ( lcCamera * Camera , float Aspect )
{
lcVector3 Min ( FLT_MAX , FLT_MAX , FLT_MAX ) , Max ( - FLT_MAX , - FLT_MAX , - FLT_MAX ) ;
if ( ! GetPiecesBoundingBox ( Min , Max ) )
return ;
lcVector3 Center = ( Min + Max ) / 2.0f ;
lcVector3 Points [ 8 ] ;
lcGetBoxCorners ( Min , Max , Points ) ;
Camera - > ZoomExtents ( Aspect , Center , Points , 8 , mCurrentStep , gMainWindow - > GetAddKeys ( ) ) ;
gMainWindow - > UpdateSelectedObjects ( false ) ;
gMainWindow - > UpdateAllViews ( ) ;
if ( ! Camera - > IsSimple ( ) )
SaveCheckpoint ( tr ( " Zoom " ) ) ;
}
void lcModel : : Zoom ( lcCamera * Camera , float Amount )
{
Camera - > Zoom ( Amount , mCurrentStep , gMainWindow - > GetAddKeys ( ) ) ;
gMainWindow - > UpdateSelectedObjects ( false ) ;
gMainWindow - > UpdateAllViews ( ) ;
if ( ! Camera - > IsSimple ( ) )
SaveCheckpoint ( tr ( " Zoom " ) ) ;
}
void lcModel : : ShowPropertiesDialog ( )
{
lcPropertiesDialogOptions Options ;
Options . Properties = mProperties ;
Options . SetDefault = false ;
2020-01-11 21:45:36 +01:00
GetPartsList ( gDefaultColor , true , false , Options . PartsList ) ;
2016-10-05 23:28:52 +02:00
2017-12-11 03:12:31 +01:00
lcQPropertiesDialog Dialog ( gMainWindow , & Options ) ;
if ( Dialog . exec ( ) ! = QDialog : : Accepted )
2016-10-05 23:28:52 +02:00
return ;
if ( Options . SetDefault )
Options . Properties . SaveDefaults ( ) ;
if ( mProperties = = Options . Properties )
return ;
mProperties = Options . Properties ;
UpdateBackgroundTexture ( ) ;
SaveCheckpoint ( tr ( " Changing Properties " ) ) ;
}
void lcModel : : ShowSelectByNameDialog ( )
{
if ( mPieces . IsEmpty ( ) & & mCameras . IsEmpty ( ) & & mLights . IsEmpty ( ) )
{
QMessageBox : : information ( gMainWindow , tr ( " LeoCAD " ) , tr ( " Nothing to select. " ) ) ;
return ;
}
2018-04-17 03:29:42 +02:00
lcQSelectDialog Dialog ( gMainWindow , this ) ;
2016-10-05 23:28:52 +02:00
if ( Dialog . exec ( ) ! = QDialog : : Accepted )
return ;
2017-11-22 07:54:49 +01:00
SetSelectionAndFocus ( Dialog . mObjects , nullptr , 0 , false ) ;
2016-10-05 23:28:52 +02:00
}
2017-02-17 07:57:11 +01:00
void lcModel : : ShowSelectByColorDialog ( )
{
if ( mPieces . IsEmpty ( ) )
{
QMessageBox : : information ( gMainWindow , tr ( " LeoCAD " ) , tr ( " Nothing to select. " ) ) ;
return ;
}
int ColorIndex = gMainWindow - > mColorIndex ;
lcObject * Focus = GetFocusObject ( ) ;
if ( Focus & & Focus - > IsPiece ( ) )
ColorIndex = ( ( lcPiece * ) Focus ) - > mColorIndex ;
lcSelectByColorDialog Dialog ( gMainWindow , ColorIndex ) ;
if ( Dialog . exec ( ) ! = QDialog : : Accepted )
return ;
ColorIndex = Dialog . mColorIndex ;
lcArray < lcObject * > Selection ;
2019-03-09 18:50:34 +01:00
for ( lcPiece * Piece : mPieces )
2017-02-17 07:57:11 +01:00
if ( Piece - > IsVisible ( mCurrentStep ) & & Piece - > mColorIndex = = ColorIndex )
Selection . Add ( Piece ) ;
2017-11-22 07:54:49 +01:00
SetSelectionAndFocus ( Selection , nullptr , 0 , false ) ;
2017-02-17 07:57:11 +01:00
}
2016-10-05 23:28:52 +02:00
void lcModel : : ShowArrayDialog ( )
{
lcVector3 Center ;
if ( ! GetPieceFocusOrSelectionCenter ( Center ) )
{
QMessageBox : : information ( gMainWindow , tr ( " LeoCAD " ) , tr ( " No pieces selected. " ) ) ;
return ;
}
lcQArrayDialog Dialog ( gMainWindow ) ;
if ( Dialog . exec ( ) ! = QDialog : : Accepted )
return ;
if ( Dialog . mCounts [ 0 ] * Dialog . mCounts [ 1 ] * Dialog . mCounts [ 2 ] < 2 )
{
QMessageBox : : information ( gMainWindow , tr ( " LeoCAD " ) , tr ( " Array only has 1 element or less, no pieces added. " ) ) ;
return ;
}
lcArray < lcObject * > NewPieces ;
for ( int Step1 = 0 ; Step1 < Dialog . mCounts [ 0 ] ; Step1 + + )
{
for ( int Step2 = 0 ; Step2 < Dialog . mCounts [ 1 ] ; Step2 + + )
{
for ( int Step3 = ( Step1 = = 0 & & Step2 = = 0 ) ? 1 : 0 ; Step3 < Dialog . mCounts [ 2 ] ; Step3 + + )
{
lcMatrix44 ModelWorld ;
lcVector3 Position ;
lcVector3 RotationAngles = Dialog . mRotations [ 0 ] * Step1 + Dialog . mRotations [ 1 ] * Step2 + Dialog . mRotations [ 2 ] * Step3 ;
lcVector3 Offset = Dialog . mOffsets [ 0 ] * Step1 + Dialog . mOffsets [ 1 ] * Step2 + Dialog . mOffsets [ 2 ] * Step3 ;
2019-03-09 18:50:34 +01:00
for ( lcPiece * Piece : mPieces )
2016-10-05 23:28:52 +02:00
{
if ( ! Piece - > IsSelected ( ) )
continue ;
ModelWorld = Piece - > mModelWorld ;
ModelWorld . r [ 3 ] - = lcVector4 ( Center , 0.0f ) ;
ModelWorld = lcMul ( ModelWorld , lcMatrix44RotationX ( RotationAngles [ 0 ] * LC_DTOR ) ) ;
ModelWorld = lcMul ( ModelWorld , lcMatrix44RotationY ( RotationAngles [ 1 ] * LC_DTOR ) ) ;
ModelWorld = lcMul ( ModelWorld , lcMatrix44RotationZ ( RotationAngles [ 2 ] * LC_DTOR ) ) ;
ModelWorld . r [ 3 ] + = lcVector4 ( Center , 0.0f ) ;
Position = lcVector3 ( ModelWorld . r [ 3 ] . x , ModelWorld . r [ 3 ] . y , ModelWorld . r [ 3 ] . z ) ;
ModelWorld . SetTranslation ( Position + Offset ) ;
2017-07-23 05:54:33 +02:00
lcPiece * NewPiece = new lcPiece ( nullptr ) ;
NewPiece - > SetPieceInfo ( Piece - > mPieceInfo , Piece - > GetID ( ) , true ) ;
2016-10-05 23:28:52 +02:00
NewPiece - > Initialize ( ModelWorld , mCurrentStep ) ;
NewPiece - > SetColorIndex ( Piece - > mColorIndex ) ;
NewPieces . Add ( NewPiece ) ;
}
}
}
}
for ( int PieceIdx = 0 ; PieceIdx < NewPieces . GetSize ( ) ; PieceIdx + + )
{
lcPiece * Piece = ( lcPiece * ) NewPieces [ PieceIdx ] ;
Piece - > UpdatePosition ( mCurrentStep ) ;
AddPiece ( Piece ) ;
}
2017-11-22 07:54:49 +01:00
AddToSelection ( NewPieces , false , true ) ;
2016-10-05 23:28:52 +02:00
gMainWindow - > UpdateTimeline ( false , false ) ;
SaveCheckpoint ( tr ( " Array " ) ) ;
}
void lcModel : : ShowMinifigDialog ( )
{
lcQMinifigDialog Dialog ( gMainWindow ) ;
if ( Dialog . exec ( ) ! = QDialog : : Accepted )
return ;
2016-12-28 22:30:31 +01:00
gMainWindow - > GetActiveView ( ) - > MakeCurrent ( ) ;
2016-10-05 23:28:52 +02:00
2017-04-14 02:26:40 +02:00
lcGroup * Group = AddGroup ( tr ( " Minifig # " ) , nullptr ) ;
2016-10-05 23:28:52 +02:00
lcArray < lcObject * > Pieces ( LC_MFW_NUMITEMS ) ;
lcMinifig & Minifig = Dialog . mMinifigWidget - > mMinifig ;
for ( int PartIdx = 0 ; PartIdx < LC_MFW_NUMITEMS ; PartIdx + + )
{
2017-04-14 02:26:40 +02:00
if ( Minifig . Parts [ PartIdx ] = = nullptr )
2016-10-05 23:28:52 +02:00
continue ;
lcPiece * Piece = new lcPiece ( Minifig . Parts [ PartIdx ] ) ;
Piece - > Initialize ( Minifig . Matrices [ PartIdx ] , mCurrentStep ) ;
Piece - > SetColorIndex ( Minifig . Colors [ PartIdx ] ) ;
Piece - > SetGroup ( Group ) ;
AddPiece ( Piece ) ;
Piece - > UpdatePosition ( mCurrentStep ) ;
Pieces . Add ( Piece ) ;
}
2017-11-22 07:54:49 +01:00
SetSelectionAndFocus ( Pieces , nullptr , 0 , false ) ;
2016-10-05 23:28:52 +02:00
gMainWindow - > UpdateTimeline ( false , false ) ;
SaveCheckpoint ( tr ( " Minifig " ) ) ;
}
void lcModel : : UpdateInterface ( )
{
gMainWindow - > UpdateTimeline ( true , false ) ;
2019-06-24 03:28:14 +02:00
gMainWindow - > UpdateUndoRedo ( mUndoHistory . size ( ) > 1 ? mUndoHistory [ 0 ] - > Description : nullptr , ! mRedoHistory . empty ( ) ? mRedoHistory [ 0 ] - > Description : nullptr ) ;
2017-12-03 04:42:42 +01:00
gMainWindow - > UpdatePaste ( ! gApplication - > mClipboard . isEmpty ( ) ) ;
2016-10-05 23:28:52 +02:00
gMainWindow - > UpdateCategories ( ) ;
gMainWindow - > UpdateTitle ( ) ;
gMainWindow - > SetTool ( gMainWindow - > GetTool ( ) ) ;
gMainWindow - > UpdateSelectedObjects ( true ) ;
gMainWindow - > SetTransformType ( gMainWindow - > GetTransformType ( ) ) ;
gMainWindow - > UpdateLockSnap ( ) ;
gMainWindow - > UpdateSnap ( ) ;
gMainWindow - > UpdateCameraMenu ( ) ;
gMainWindow - > UpdateModels ( ) ;
gMainWindow - > UpdatePerspective ( ) ;
2017-08-25 21:57:14 +02:00
gMainWindow - > UpdateShadingMode ( ) ;
2016-10-05 23:28:52 +02:00
gMainWindow - > UpdateCurrentStep ( ) ;
2017-11-22 02:58:36 +01:00
gMainWindow - > UpdateSelectionMode ( ) ;
2016-10-05 23:28:52 +02:00
}