Merge pull request #1013 from leozide/undo

New Undo System
This commit is contained in:
Leonardo Zide
2026-03-12 21:31:17 -07:00
committed by GitHub
87 changed files with 3332 additions and 2340 deletions
+132 -73
View File
@@ -1,8 +1,6 @@
#include "lc_global.h"
#include "lc_math.h"
#include "lc_colors.h"
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <float.h>
#include "lc_file.h"
@@ -15,28 +13,29 @@
#define LC_CAMERA_SAVE_VERSION 7 // LeoCAD 0.80
lcCamera::lcCamera(bool Simple)
: lcObject(lcObjectType::Camera)
lcCamera::lcCamera()
: lcObject(lcObjectType::Camera)
{
Initialize();
}
if (Simple)
mState |= LC_CAMERA_SIMPLE;
else
lcCamera::lcCamera(bool Simple)
: lcObject(lcObjectType::Camera), mSimple(Simple)
{
if (!Simple)
{
mPosition.SetValue(lcVector3(-250.0f, -250.0f, 75.0f));
mTargetPosition.SetValue(lcVector3(0.0f, 0.0f, 0.0f));
mUpVector.SetValue(lcVector3(-0.2357f, -0.2357f, 0.94281f));
UpdatePosition(1);
lcCamera::UpdatePosition(1);
}
}
lcCamera::lcCamera(float ex, float ey, float ez, float tx, float ty, float tz)
: lcObject(lcObjectType::Camera)
lcCamera::lcCamera(bool Simple, const lcVector3& Position, const lcVector3& TargetPosition)
: lcObject(lcObjectType::Camera), mSimple(Simple)
{
// Fix the up vector
lcVector3 UpVector(0, 0, 1), FrontVector(ex - tx, ey - ty, ez - tz), SideVector;
lcVector3 UpVector(0, 0, 1), FrontVector(Position - TargetPosition), SideVector;
FrontVector.Normalize();
if (FrontVector == UpVector)
SideVector = lcVector3(1, 0, 0);
@@ -45,44 +44,42 @@ lcCamera::lcCamera(float ex, float ey, float ez, float tx, float ty, float tz)
UpVector = lcCross(SideVector, FrontVector);
UpVector.Normalize();
Initialize();
mPosition.SetValue(lcVector3(ex, ey, ez));
mTargetPosition.SetValue(lcVector3(tx, ty, tz));
mPosition.SetValue(Position);
mTargetPosition.SetValue(TargetPosition);
mUpVector.SetValue(UpVector);
UpdatePosition(1);
lcCamera::UpdatePosition(1);
}
lcCamera::~lcCamera()
{
}
QString lcCamera::GetCameraTypeString(lcCameraType CameraType)
QString lcCamera::GetCameraProjectionString(lcCameraProjection CameraProjection)
{
switch (CameraType)
switch (CameraProjection)
{
case lcCameraType::Perspective:
return QT_TRANSLATE_NOOP("Camera Type", "Perspective");
case lcCameraProjection::Perspective:
return QT_TRANSLATE_NOOP("Camera Projection", "Perspective");
case lcCameraType::Orthographic:
return QT_TRANSLATE_NOOP("Camera Type", "Orthographic");
case lcCameraProjection::Orthographic:
return QT_TRANSLATE_NOOP("Camera Projection", "Orthographic");
case lcCameraType::Count:
case lcCameraProjection::Count:
break;
}
return QString();
}
QStringList lcCamera::GetCameraTypeStrings()
QStringList lcCamera::GetCameraProjectionStrings()
{
QStringList CameraType;
QStringList CameraProjections;
for (int CameraTypeIndex = 0; CameraTypeIndex < static_cast<int>(lcCameraType::Count); CameraTypeIndex++)
CameraType.push_back(GetCameraTypeString(static_cast<lcCameraType>(CameraTypeIndex)));
for (int CameraProjectionIndex = 0; CameraProjectionIndex < static_cast<int>(lcCameraProjection::Count); CameraProjectionIndex++)
CameraProjections.push_back(GetCameraProjectionString(static_cast<lcCameraProjection>(CameraProjectionIndex)));
return CameraType;
return CameraProjections;
}
lcViewpoint lcCamera::GetViewpoint(const QString& ViewpointName)
@@ -107,14 +104,6 @@ lcViewpoint lcCamera::GetViewpoint(const QString& ViewpointName)
return lcViewpoint::Count;
}
void lcCamera::Initialize()
{
m_fovy = 30.0f;
m_zNear = 25.0f;
m_zFar = 50000.0f;
mState = 0;
}
bool lcCamera::SetName(const QString& Name)
{
if (mName == Name)
@@ -164,15 +153,45 @@ void lcCamera::CreateName(const std::vector<std::unique_ptr<lcCamera>>& Cameras)
mName = Prefix + QString::number(MaxCameraNumber + 1);
}
bool lcCamera::SetCameraType(lcCameraType CameraType)
bool lcCamera::SetProjection(lcCameraProjection CameraProjection)
{
if (static_cast<int>(CameraType) < 0 || CameraType >= lcCameraType::Count)
if (static_cast<int>(CameraProjection) < 0 || CameraProjection >= lcCameraProjection::Count)
return false;
if (GetCameraType() == CameraType)
if (GetProjection() == CameraProjection)
return false;
SetOrtho(CameraType == lcCameraType::Orthographic);
mProjection = CameraProjection;
return true;
}
bool lcCamera::SetFOV(float Fovy)
{
if (m_fovy == Fovy)
return false;
m_fovy = Fovy;
return true;
}
bool lcCamera::SetNearPlane(float NearPlane)
{
if (m_zNear == NearPlane)
return false;
m_zNear = NearPlane;
return true;
}
bool lcCamera::SetFarPlane(float FarPlane)
{
if (m_zFar == FarPlane)
return false;
m_zFar = FarPlane;
return true;
}
@@ -192,7 +211,7 @@ void lcCamera::SaveLDraw(QTextStream& Stream) const
if (IsHidden())
Stream << QLatin1String("HIDDEN");
if (IsOrtho())
if (mProjection == lcCameraProjection::Orthographic)
Stream << QLatin1String("ORTHOGRAPHIC ");
Stream << QLatin1String("NAME ") << mName << LineEnding;
@@ -208,7 +227,7 @@ bool lcCamera::ParseLDrawLine(QTextStream& Stream)
if (Token == QLatin1String("HIDDEN"))
SetHidden(true);
else if (Token == QLatin1String("ORTHOGRAPHIC"))
SetOrtho(true);
SetProjection(lcCameraProjection::Orthographic);
else if (Token == QLatin1String("FOV"))
Stream >> m_fovy;
else if (Token == QLatin1String("ZNEAR"))
@@ -352,11 +371,11 @@ bool lcCamera::FileLoad(lcFile& file)
if (version < 5)
{
n = file.ReadS32();
file.ReadS32();
}
else
{
ch = file.ReadU8();
file.ReadU8();
file.ReadU8();
}
}
@@ -408,7 +427,7 @@ void lcCamera::MoveSelected(lcStep Step, bool AddKey, const lcVector3& Distance)
{
mTargetPosition.ChangeKey(mTargetPosition + Distance, Step, AddKey);
}
if (FocusSection == LC_CAMERA_SECTION_UPVECTOR)
{
mUpVector.ChangeKey(lcNormalize(mUpVector + Distance), Step, AddKey);
@@ -453,7 +472,7 @@ void lcCamera::Rotate(lcStep Step, bool AddKey, const lcMatrix33& RotationMatrix
SetTargetPosition(Center + Distance, Step, AddKey);
lcVector3 UpVector = mUpVector;
UpVector = lcMul(UpVector, WorldToLocalMatrix);
UpVector = lcMul(UpVector, NewLocalToWorldMatrix);
@@ -483,16 +502,16 @@ void lcCamera::CopyPosition(const lcCamera* Camera)
mPosition = Camera->mPosition;
mTargetPosition = Camera->mTargetPosition;
mUpVector = Camera->mUpVector;
mState |= (Camera->mState & LC_CAMERA_ORTHO);
mProjection = Camera->mProjection;
}
void lcCamera::CopySettings(const lcCamera* camera)
void lcCamera::CopySettings(const lcCamera* Camera)
{
m_fovy = camera->m_fovy;
m_zNear = camera->m_zNear;
m_zFar = camera->m_zFar;
m_fovy = Camera->m_fovy;
m_zNear = Camera->m_zNear;
m_zFar = Camera->m_zFar;
mState |= (camera->mState & LC_CAMERA_ORTHO);
mProjection = Camera->mProjection;
}
void lcCamera::DrawInterface(lcContext* Context, const lcScene& Scene) const
@@ -546,7 +565,7 @@ void lcCamera::DrawInterface(lcContext* Context, const lcScene& Scene) const
*CurVert++ = 0.0f; *CurVert++ = 0.0f; *CurVert++ = -Length;
*CurVert++ = 0.0f; *CurVert++ = 25.0f; *CurVert++ = 0.0f;
const GLushort Indices[40 + 24 + 24 + 4 + 16] =
const GLushort Indices[40 + 24 + 24 + 4 + 16] =
{
0, 1, 1, 2, 2, 3, 3, 0,
4, 5, 5, 6, 6, 7, 7, 4,
@@ -583,7 +602,7 @@ void lcCamera::DrawInterface(lcContext* Context, const lcScene& Scene) const
}
else
{
if (IsSelected(LC_CAMERA_SECTION_POSITION))
if (IsSelected())
{
Context->SetLineWidth(2.0f * LineWidth);
if (IsFocused(LC_CAMERA_SECTION_POSITION))
@@ -599,7 +618,7 @@ void lcCamera::DrawInterface(lcContext* Context, const lcScene& Scene) const
Context->DrawIndexedPrimitives(GL_LINES, 40, GL_UNSIGNED_SHORT, 0);
if (IsSelected(LC_CAMERA_SECTION_TARGET))
if (IsSelected())
{
Context->SetLineWidth(2.0f * LineWidth);
if (IsFocused(LC_CAMERA_SECTION_TARGET))
@@ -615,7 +634,7 @@ void lcCamera::DrawInterface(lcContext* Context, const lcScene& Scene) const
Context->DrawIndexedPrimitives(GL_LINES, 24, GL_UNSIGNED_SHORT, 40 * 2);
if (IsSelected(LC_CAMERA_SECTION_UPVECTOR))
if (IsSelected())
{
Context->SetLineWidth(2.0f * LineWidth);
if (IsFocused(LC_CAMERA_SECTION_UPVECTOR))
@@ -659,8 +678,8 @@ QVariant lcCamera::GetPropertyValue(lcObjectPropertyId PropertyId) const
case lcObjectPropertyId::CameraName:
return GetName();
case lcObjectPropertyId::CameraType:
return static_cast<int>(GetCameraType());
case lcObjectPropertyId::CameraProjection:
return static_cast<int>(GetProjection());
case lcObjectPropertyId::CameraFOV:
case lcObjectPropertyId::CameraNear:
@@ -721,12 +740,18 @@ bool lcCamera::SetPropertyValue(lcObjectPropertyId PropertyId, lcStep Step, bool
case lcObjectPropertyId::CameraName:
return SetName(Value.toString());
case lcObjectPropertyId::CameraType:
return SetCameraType(static_cast<lcCameraType>(Value.toInt()));
case lcObjectPropertyId::CameraProjection:
return SetProjection(static_cast<lcCameraProjection>(Value.toInt()));
case lcObjectPropertyId::CameraFOV:
return SetFOV(Value.toFloat());
case lcObjectPropertyId::CameraNear:
return SetNearPlane(Value.toFloat());
case lcObjectPropertyId::CameraFar:
return SetFarPlane(Value.toFloat());
case lcObjectPropertyId::CameraPositionX:
case lcObjectPropertyId::CameraPositionY:
case lcObjectPropertyId::CameraPositionZ:
@@ -776,7 +801,7 @@ bool lcCamera::HasKeyFrame(lcObjectPropertyId PropertyId, lcStep Time) const
case lcObjectPropertyId::PieceStepShow:
case lcObjectPropertyId::PieceStepHide:
case lcObjectPropertyId::CameraName:
case lcObjectPropertyId::CameraType:
case lcObjectPropertyId::CameraProjection:
case lcObjectPropertyId::CameraFOV:
case lcObjectPropertyId::CameraNear:
case lcObjectPropertyId::CameraFar:
@@ -837,7 +862,7 @@ bool lcCamera::SetKeyFrame(lcObjectPropertyId PropertyId, lcStep Time, bool KeyF
case lcObjectPropertyId::PieceStepShow:
case lcObjectPropertyId::PieceStepHide:
case lcObjectPropertyId::CameraName:
case lcObjectPropertyId::CameraType:
case lcObjectPropertyId::CameraProjection:
case lcObjectPropertyId::CameraFOV:
case lcObjectPropertyId::CameraNear:
case lcObjectPropertyId::CameraFar:
@@ -896,6 +921,40 @@ void lcCamera::RemoveKeyFrames()
mUpVector.RemoveAllKeys();
}
lcCameraHistoryState lcCamera::GetHistoryState([[maybe_unused]] const lcModel* Model) const
{
lcCameraHistoryState State;
State.Id = mId;
State.Hidden = mHidden;
State.Simple = mSimple;
State.Fovy = m_fovy;
State.NearPlane = m_zNear;
State.FarPlane = m_zFar;
State.Projection = mProjection;
State.Position = mPosition;
State.TargetPosition = mTargetPosition;
State.UpVector = mUpVector;
State.Name = mName;
return State;
}
void lcCamera::SetHistoryState(const lcCameraHistoryState& State, [[maybe_unused]] const lcModel* Model)
{
mId = State.Id;
mHidden = State.Hidden;
mSimple = State.Simple;
m_fovy = State.Fovy;
m_zNear = State.NearPlane;
m_zFar = State.FarPlane;
mProjection = State.Projection;
mPosition = State.Position;
mTargetPosition = State.TargetPosition;
mUpVector = State.UpVector;
mName = State.Name;
}
void lcCamera::RayTest(lcObjectRayTest& ObjectRayTest) const
{
lcVector3 Min = lcVector3(-LC_CAMERA_POSITION_EDGE, -LC_CAMERA_POSITION_EDGE, -LC_CAMERA_POSITION_EDGE);
@@ -1024,7 +1083,7 @@ void lcCamera::ZoomExtents(float AspectRatio, const lcVector3& Center, const std
{
lcVector3 Position, TargetPosition;
if (IsOrtho())
if (GetProjection() == lcCameraProjection::Orthographic)
{
float MinX = FLT_MAX, MaxX = -FLT_MAX, MinY = FLT_MAX, MaxY = -FLT_MAX;
@@ -1037,28 +1096,28 @@ void lcCamera::ZoomExtents(float AspectRatio, const lcVector3& Center, const std
MaxX = lcMax(MaxX, Point.x);
MaxY = lcMax(MaxY, Point.y);
}
float Width = fabsf(MaxX - MinX);
float Height = fabsf(MaxY - MinY);
const lcVector3 ViewCenter = lcMul30(Center, mWorldView);
float OffsetX = (fabsf(MaxX - ViewCenter.x) - fabsf(ViewCenter.x - MinX)) / 2.0f;
float OffsetY = (fabsf(MaxY - ViewCenter.y) - fabsf(ViewCenter.y - MinY)) / 2.0f;
lcVector3 ViewOffset(OffsetX, OffsetY, 0.0f);
lcMatrix44 ViewWorldMatrix = lcMatrix44AffineInverse(mWorldView);
ViewWorldMatrix.SetTranslation(lcVector3(0, 0, 0));
lcVector3 WorldOffset = lcMul30(ViewOffset, ViewWorldMatrix);
if (Width > Height * AspectRatio)
Height = Width / AspectRatio;
const float f = Height / (m_fovy * (LC_PI / 180.0f));
const lcVector3 FrontVector(mTargetPosition - mPosition);
TargetPosition = Center + WorldOffset;
Position = TargetPosition - lcNormalize(FrontVector) * f;
}
@@ -1084,7 +1143,7 @@ void lcCamera::ZoomRegion(float AspectRatio, const lcVector3& Position, const lc
{
lcVector3 NewPosition;
if (IsOrtho())
if (GetProjection() == lcCameraProjection::Orthographic)
{
float MinX = FLT_MAX, MaxX = -FLT_MAX, MinY = FLT_MAX, MaxY = -FLT_MAX;
@@ -1133,7 +1192,7 @@ void lcCamera::Zoom(float Distance, lcStep Step, bool AddKey)
FrontVector *= -5.0f * Distance;
// Don't zoom ortho in if it would cross the ortho focal plane.
if (IsOrtho())
if (GetProjection() == lcCameraProjection::Orthographic)
{
if ((Distance > 0) && (lcDot(mPosition + FrontVector - mTargetPosition, mPosition - mTargetPosition) <= 0))
return;
@@ -1144,7 +1203,7 @@ void lcCamera::Zoom(float Distance, lcStep Step, bool AddKey)
mPosition.ChangeKey(mPosition + FrontVector, Step, AddKey);
if (!IsOrtho())
if (GetProjection() != lcCameraProjection::Orthographic)
mTargetPosition.ChangeKey(mTargetPosition + FrontVector, Step, AddKey);
UpdatePosition(Step);
+48 -172
View File
@@ -3,19 +3,6 @@
#include "object.h"
#include "lc_math.h"
#define LC_CAMERA_HIDDEN 0x0001
#define LC_CAMERA_SIMPLE 0x0002
#define LC_CAMERA_ORTHO 0x0004
#define LC_CAMERA_POSITION_SELECTED 0x0010
#define LC_CAMERA_POSITION_FOCUSED 0x0020
#define LC_CAMERA_TARGET_SELECTED 0x0040
#define LC_CAMERA_TARGET_FOCUSED 0x0080
#define LC_CAMERA_UPVECTOR_SELECTED 0x0100
#define LC_CAMERA_UPVECTOR_FOCUSED 0x0200
#define LC_CAMERA_SELECTION_MASK (LC_CAMERA_POSITION_SELECTED | LC_CAMERA_TARGET_SELECTED | LC_CAMERA_UPVECTOR_SELECTED)
#define LC_CAMERA_FOCUS_MASK (LC_CAMERA_POSITION_FOCUSED | LC_CAMERA_TARGET_FOCUSED | LC_CAMERA_UPVECTOR_FOCUSED)
enum class lcViewpoint
{
Front,
@@ -28,7 +15,7 @@ enum class lcViewpoint
Count
};
enum class lcCameraType
enum class lcCameraProjection
{
Perspective,
Orthographic,
@@ -37,26 +24,49 @@ enum class lcCameraType
enum lcCameraSection : quint32
{
LC_CAMERA_SECTION_INVALID = ~0U,
LC_CAMERA_SECTION_INVALID = LC_OBJECT_SECTION_INVALID,
LC_CAMERA_SECTION_POSITION = 0,
LC_CAMERA_SECTION_TARGET,
LC_CAMERA_SECTION_UPVECTOR
};
struct lcCameraHistoryState
{
lcObjectId Id;
bool Hidden;
bool Simple;
float Fovy;
float NearPlane;
float FarPlane;
lcCameraProjection Projection;
lcObjectProperty<lcVector3> Position;
lcObjectProperty<lcVector3> TargetPosition;
lcObjectProperty<lcVector3> UpVector;
QString Name;
bool operator==(const lcCameraHistoryState& Other) const
{
return Id == Other.Id && Hidden == Other.Hidden && Simple == Other.Simple && Fovy == Other.Fovy &&
NearPlane == Other.NearPlane && FarPlane == Other.FarPlane && Projection == Other.Projection &&
Position == Other.Position && TargetPosition == Other.TargetPosition && UpVector == Other.UpVector && Name == Other.Name;
}
};
class lcCamera : public lcObject
{
public:
lcCamera();
lcCamera(bool Simple);
lcCamera(float ex, float ey, float ez, float tx, float ty, float tz);
~lcCamera();
lcCamera(bool Simple, const lcVector3& Position, const lcVector3& TargetPosition);
virtual ~lcCamera();
lcCamera(const lcCamera&) = delete;
lcCamera(lcCamera&&) = delete;
lcCamera& operator=(const lcCamera&) = delete;
lcCamera& operator=(lcCamera&&) = delete;
static QString GetCameraTypeString(lcCameraType CameraType);
static QStringList GetCameraTypeStrings();
static QString GetCameraProjectionString(lcCameraProjection CameraProjection);
static QStringList GetCameraProjectionStrings();
static lcViewpoint GetViewpoint(const QString& ViewpointName);
QString GetName() const override
@@ -69,152 +79,18 @@ public:
bool IsSimple() const
{
return (mState & LC_CAMERA_SIMPLE) != 0;
return mSimple;
}
lcCameraType GetCameraType() const
lcCameraProjection GetProjection() const
{
return ((mState & LC_CAMERA_ORTHO) == 0) ? lcCameraType::Perspective : lcCameraType::Orthographic;
return mProjection;
}
bool SetCameraType(lcCameraType CameraType);
bool IsOrtho() const
{
return (mState & LC_CAMERA_ORTHO) != 0;
}
void SetOrtho(bool Ortho)
{
if (Ortho)
mState |= LC_CAMERA_ORTHO;
else
mState &= ~LC_CAMERA_ORTHO;
}
bool IsSelected() const override
{
return (mState & LC_CAMERA_SELECTION_MASK) != 0;
}
bool IsSelected(quint32 Section) const override
{
switch (Section)
{
case LC_CAMERA_SECTION_POSITION:
return (mState & LC_CAMERA_POSITION_SELECTED) != 0;
break;
case LC_CAMERA_SECTION_TARGET:
return (mState & LC_CAMERA_TARGET_SELECTED) != 0;
break;
case LC_CAMERA_SECTION_UPVECTOR:
return (mState & LC_CAMERA_UPVECTOR_SELECTED) != 0;
break;
}
return false;
}
void SetSelected(bool Selected) override
{
if (Selected)
mState |= LC_CAMERA_SELECTION_MASK;
else
mState &= ~(LC_CAMERA_SELECTION_MASK | LC_CAMERA_FOCUS_MASK);
}
void SetSelected(quint32 Section, bool Selected) override
{
switch (Section)
{
case LC_CAMERA_SECTION_POSITION:
if (Selected)
mState |= LC_CAMERA_POSITION_SELECTED;
else
mState &= ~(LC_CAMERA_POSITION_SELECTED | LC_CAMERA_POSITION_FOCUSED);
break;
case LC_CAMERA_SECTION_TARGET:
if (Selected)
mState |= LC_CAMERA_TARGET_SELECTED;
else
mState &= ~(LC_CAMERA_TARGET_SELECTED | LC_CAMERA_TARGET_FOCUSED);
break;
case LC_CAMERA_SECTION_UPVECTOR:
if (Selected)
mState |= LC_CAMERA_UPVECTOR_SELECTED;
else
mState &= ~(LC_CAMERA_UPVECTOR_SELECTED | LC_CAMERA_UPVECTOR_FOCUSED);
break;
}
}
bool IsFocused() const override
{
return (mState & LC_CAMERA_FOCUS_MASK) != 0;
}
bool IsFocused(quint32 Section) const override
{
switch (Section)
{
case LC_CAMERA_SECTION_POSITION:
return (mState & LC_CAMERA_POSITION_FOCUSED) != 0;
break;
case LC_CAMERA_SECTION_TARGET:
return (mState & LC_CAMERA_TARGET_FOCUSED) != 0;
break;
case LC_CAMERA_SECTION_UPVECTOR:
return (mState & LC_CAMERA_UPVECTOR_FOCUSED) != 0;
break;
}
return false;
}
void SetFocused(quint32 Section, bool Focus) override
{
switch (Section)
{
case LC_CAMERA_SECTION_POSITION:
if (Focus)
mState |= LC_CAMERA_SELECTION_MASK | LC_CAMERA_POSITION_FOCUSED;
else
mState &= ~LC_CAMERA_POSITION_FOCUSED;
break;
case LC_CAMERA_SECTION_TARGET:
if (Focus)
mState |= LC_CAMERA_SELECTION_MASK | LC_CAMERA_TARGET_FOCUSED;
else
mState &= ~LC_CAMERA_TARGET_FOCUSED;
break;
case LC_CAMERA_SECTION_UPVECTOR:
if (Focus)
mState |= LC_CAMERA_SELECTION_MASK | LC_CAMERA_UPVECTOR_FOCUSED;
else
mState &= ~LC_CAMERA_UPVECTOR_FOCUSED;
break;
}
}
quint32 GetFocusSection() const override
{
if (mState & LC_CAMERA_POSITION_FOCUSED)
return LC_CAMERA_SECTION_POSITION;
if (mState & LC_CAMERA_TARGET_FOCUSED)
return LC_CAMERA_SECTION_TARGET;
if (mState & LC_CAMERA_UPVECTOR_FOCUSED)
return LC_CAMERA_SECTION_UPVECTOR;
return LC_CAMERA_SECTION_INVALID;
}
bool SetProjection(lcCameraProjection CameraProjection);
bool SetFOV(float Fovy);
bool SetNearPlane(float NearPlane);
bool SetFarPlane(float FarPlane);
quint32 GetAllowedTransforms() const override
{
@@ -267,19 +143,18 @@ public:
public:
bool IsVisible() const
{ return (mState & LC_CAMERA_HIDDEN) == 0; }
{
return !mHidden;
}
bool IsHidden() const
{
return (mState & LC_CAMERA_HIDDEN) != 0;
return mHidden;
}
void SetHidden(bool Hidden)
{
if (Hidden)
mState |= LC_CAMERA_HIDDEN;
else
mState &= ~LC_CAMERA_HIDDEN;
mHidden = Hidden;
}
void SetPosition(const lcVector3& Position, lcStep Step, bool AddKey)
@@ -316,6 +191,8 @@ public:
bool HasKeyFrame(lcObjectPropertyId PropertyId, lcStep Time) const override;
bool SetKeyFrame(lcObjectPropertyId PropertyId, lcStep Time, bool KeyFrame) override;
void RemoveKeyFrames() override;
lcCameraHistoryState GetHistoryState(const lcModel* Model) const;
void SetHistoryState(const lcCameraHistoryState& State, const lcModel* Model);
void InsertTime(lcStep Start, lcStep Time);
void RemoveTime(lcStep Start, lcStep Time);
@@ -343,9 +220,9 @@ public:
void GetAngles(float& Latitude, float& Longitude, float& Distance) const;
void SetAngles(float Latitude, float Longitude, float Distance);
float m_fovy;
float m_zNear;
float m_zFar;
float m_fovy = 30.0f;
float m_zNear = 25.0f;
float m_zFar = 50000;
lcMatrix44 mWorldView;
lcObjectProperty<lcVector3> mPosition = lcObjectProperty<lcVector3>(lcVector3(0.0f, 0.0f, 0.0f));
@@ -353,8 +230,7 @@ public:
lcObjectProperty<lcVector3> mUpVector = lcObjectProperty<lcVector3>(lcVector3(0.0f, 0.0f, 0.0f));
protected:
void Initialize();
QString mName;
quint32 mState;
bool mSimple = true;
lcCameraProjection mProjection = lcCameraProjection::Perspective;
};
+40 -2
View File
@@ -1,11 +1,15 @@
#include "lc_global.h"
#include <stdlib.h>
#include "group.h"
#include "lc_model.h"
#include "lc_file.h"
lcGroupId lcGroup::mNextId;
lcGroup::lcGroup()
: mId(mNextId)
{
mGroup = nullptr;
mNextId = static_cast<lcGroupId>(static_cast<uint32_t>(mNextId) + 1);
}
void lcGroup::FileLoad(lcFile* File)
@@ -41,7 +45,7 @@ void lcGroup::CreateName(const std::vector<std::unique_ptr<lcGroup>>& Groups)
int Max = 0;
QString Prefix = QApplication::tr("Group #");
const int Length = Prefix.length();
const qsizetype Length = Prefix.length();
for (const std::unique_ptr<lcGroup>& Group : Groups)
{
@@ -58,3 +62,37 @@ void lcGroup::CreateName(const std::vector<std::unique_ptr<lcGroup>>& Groups)
mName = Prefix + QString::number(Max + 1);
}
lcGroupHistoryState lcGroup::GetHistoryState(const lcModel* Model) const
{
lcGroupHistoryState State;
State.Id = mId;
State.ParentIndex = ~0U;
State.Name = mName;
if (mGroup)
{
const std::vector<std::unique_ptr<lcGroup>>& Groups = Model->GetGroups();
for (size_t GroupIndex = 0; GroupIndex < Groups.size(); GroupIndex++)
{
if (Groups[GroupIndex].get() == mGroup)
{
State.ParentIndex = static_cast<uint32_t>(GroupIndex);
break;
}
}
}
return State;
}
void lcGroup::SetHistoryState(const lcGroupHistoryState& State, const lcModel* Model)
{
const std::vector<std::unique_ptr<lcGroup>>& Groups = Model->GetGroups();
mId = State.Id;
mName = State.Name;
mGroup = (State.ParentIndex < Groups.size()) ? Groups[State.ParentIndex].get() : nullptr;
}
+29 -3
View File
@@ -2,6 +2,20 @@
#define LC_MAX_GROUP_NAME 64
enum class lcGroupId : uint32_t;
struct lcGroupHistoryState
{
lcGroupId Id;
uint32_t ParentIndex;
QString Name;
bool operator==(const lcGroupHistoryState& Other) const
{
return Id == Other.Id && ParentIndex == Other.ParentIndex && Name == Other.Name;
}
};
class lcGroup
{
public:
@@ -12,10 +26,22 @@ public:
return mGroup ? mGroup->GetTopGroup() : this;
}
lcGroupId GetId() const
{
return mId;
}
void FileLoad(lcFile* File);
void CreateName(const std::vector<std::unique_ptr<lcGroup>>& Groups);
lcGroup* mGroup;
QString mName;
};
lcGroupHistoryState GetHistoryState(const lcModel* Model) const;
void SetHistoryState(const lcGroupHistoryState& State, const lcModel* Model);
lcGroup* mGroup = nullptr;
QString mName;
protected:
lcGroupId mId = static_cast<lcGroupId>(0);
static lcGroupId mNextId;
};
+9 -2
View File
@@ -18,14 +18,21 @@ lcAboutDialog::lcAboutDialog(QWidget* Parent)
#endif
lcViewWidget* Widget = gMainWindow->GetActiveView()->GetWidget();
QSurfaceFormat Format = Widget->context()->format();
QOpenGLContext* Context = Widget->context();
QOpenGLFunctions* Functions = Context->functions();
QSurfaceFormat Format = Context->format();
int ColorDepth = Format.redBufferSize() + Format.greenBufferSize() + Format.blueBufferSize() + Format.alphaBufferSize();
const QString QtVersionFormat = tr("Qt Version %1 (compiled with %2)\n\n");
const QString QtVersion = QtVersionFormat.arg(qVersion(), QT_VERSION_STR);
const QString VersionFormat = tr("OpenGL Version %1 (GLSL %2)\n%3 - %4\n\n");
const QString Version = VersionFormat.arg(QString((const char*)glGetString(GL_VERSION)), QString((const char*)glGetString(GL_SHADING_LANGUAGE_VERSION)), QString((const char*)glGetString(GL_RENDERER)), QString((const char*)glGetString(GL_VENDOR)));
const QString GLVersion(reinterpret_cast<const char*>(Functions->glGetString(GL_VERSION)));
const QString ShaderVersion(reinterpret_cast<const char*>(Functions->glGetString(GL_SHADING_LANGUAGE_VERSION)));
const QString Renderer(reinterpret_cast<const char*>(Functions->glGetString(GL_RENDERER)));
const QString Vendor(reinterpret_cast<const char*>(Functions->glGetString(GL_VENDOR)));
const QString Version = VersionFormat.arg(GLVersion, ShaderVersion, Renderer, Vendor);
const QString BuffersFormat = tr("Color Buffer: %1 bits\nDepth Buffer: %2 bits\nStencil Buffer: %3 bits\n\n");
const QString Buffers = BuffersFormat.arg(QString::number(ColorDepth), QString::number(Format.depthBufferSize()), QString::number(Format.stencilBufferSize()));
+2 -1
View File
@@ -11,6 +11,7 @@
#include "lc_view.h"
#include "camera.h"
#include "lc_previewwidget.h"
#include "lc_colors.h"
#ifdef Q_OS_WIN
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
@@ -1058,7 +1059,7 @@ lcStartupMode lcApplication::Initialize(const QList<QPair<QString, bool>>& Libra
ActiveView->SetCamera(Options.CameraName);
else
{
ActiveView->SetProjection(Options.Orthographic);
ActiveView->SetCameraProjection(Options.Orthographic ? lcCameraProjection::Orthographic : lcCameraProjection::Perspective);
if (Options.SetFoV)
ActiveView->GetCamera()->m_fovy = Options.FoV;
+60 -62
View File
@@ -53,10 +53,10 @@ const QLatin1String LineEnding("\r\n");
#define LC_BLENDER_ADDON_URL LC_BLENDER_ADDON_STR "releases/latest/download/" LC_BLENDER_ADDON_FILE
#define LC_BLENDER_ADDON_SHA_HASH_URL LC_BLENDER_ADDON_URL ".sha256"
#define LC_THEME_DARK_PALETTE_MIDLIGHT "#3E3E3E" // 62, 62, 62, 255
#define LC_THEME_DEFAULT_PALETTE_LIGHT "#AEADAC" // 174, 173, 172, 255
#define LC_THEME_DARK_PALETTE_MIDLIGHT QColor( 62, 62, 62, 255)
#define LC_THEME_DEFAULT_PALETTE_LIGHT QColor(174, 173, 172, 255)
#define LC_THEME_DARK_DECORATE_QUOTED_TEXT "#81D4FA" // 129, 212, 250, 255
#define LC_DISABLED_TEXT "#808080" // 128, 128, 128, 255
#define LC_DISABLED_TEXT QColor(128, 128, 128, 255)
#define LC_RENDER_IMAGE_MAX_SIZE 32768 // pixels
@@ -415,10 +415,10 @@ lcBlenderPreferences::lcBlenderPreferences(int Width, int Height, double Scale,
QPalette ReadOnlyPalette = QApplication::palette();
const lcPreferences& Preferences = lcGetPreferences();
if (Preferences.mColorTheme == lcColorTheme::Dark)
ReadOnlyPalette.setColor(QPalette::Base,QColor(LC_THEME_DARK_PALETTE_MIDLIGHT));
ReadOnlyPalette.setColor(QPalette::Base, LC_THEME_DARK_PALETTE_MIDLIGHT);
else
ReadOnlyPalette.setColor(QPalette::Base,QColor(LC_THEME_DEFAULT_PALETTE_LIGHT));
ReadOnlyPalette.setColor(QPalette::Text,QColor(LC_DISABLED_TEXT));
ReadOnlyPalette.setColor(QPalette::Base, LC_THEME_DEFAULT_PALETTE_LIGHT);
ReadOnlyPalette.setColor(QPalette::Text, LC_DISABLED_TEXT);
QGroupBox* BlenderExeBox = new QGroupBox(tr("Blender Executable"),mContent);
mForm->addRow(BlenderExeBox);
@@ -549,7 +549,7 @@ lcBlenderPreferences::lcBlenderPreferences(int Width, int Height, double Scale,
else
mBlenderVersionEdit->setText(mBlenderVersion);
if (QFileInfo(QString("%1/Blender/%2").arg(mDataDir).arg(LC_BLENDER_ADDON_FILE)).isReadable())
if (QFileInfo(QString("%1/Blender/%2").arg(mDataDir, LC_BLENDER_ADDON_FILE)).isReadable())
{
mModulesBox->setEnabled(false);
mImportActBox->setChecked(true);
@@ -947,7 +947,7 @@ void lcBlenderPreferences::ConfigureBlenderAddon(bool TestBlender, bool AddonUpd
const QString BlenderConfigDir = QString("%1/setup/addon_setup/config").arg(BlenderDir);
const QString BlenderAddonDir = QDir::toNativeSeparators(QString("%1/addons").arg(BlenderDir));
const QString BlenderExeCompare = QDir::toNativeSeparators(lcGetProfileString(LC_PROFILE_BLENDER_PATH)).toLower();
const QString BlenderInstallFile = QDir::toNativeSeparators(QString("%1/%2").arg(BlenderDir).arg(LC_BLENDER_ADDON_INSTALL_FILE));
const QString BlenderInstallFile = QDir::toNativeSeparators(QString("%1/%2").arg(BlenderDir, LC_BLENDER_ADDON_INSTALL_FILE));
const QString BlenderTestString = QLatin1String("###TEST_BLENDER###");
QByteArray AddonPathsAndModuleNames;
QString Message, ShellProgram;
@@ -1018,7 +1018,7 @@ void lcBlenderPreferences::ConfigureBlenderAddon(bool TestBlender, bool AddonUpd
if (!mProcess->waitForStarted())
{
Message = tr("Cannot start Blender %1 mProcess.\n%2").arg(ProcessAction).arg(QString(mProcess->readAllStandardError()));
Message = tr("Cannot start Blender %1 mProcess.\n%2").arg(ProcessAction, QString(mProcess->readAllStandardError()));
delete mProcess;
mProcess = nullptr;
return PR_WAIT;
@@ -1027,7 +1027,7 @@ void lcBlenderPreferences::ConfigureBlenderAddon(bool TestBlender, bool AddonUpd
{
if (mProcess->exitStatus() != QProcess::NormalExit || mProcess->exitCode() != 0)
{
Message = tr("Failed to execute Blender %1.\n%2").arg(ProcessAction).arg(QString(mProcess->readAllStandardError()));
Message = tr("Failed to execute Blender %1.\n%2").arg(ProcessAction, QString(mProcess->readAllStandardError()));
return PR_FAIL;
}
}
@@ -1066,7 +1066,7 @@ void lcBlenderPreferences::ConfigureBlenderAddon(bool TestBlender, bool AddonUpd
// set default LDraw import module if not configured
if (!mImportActBox->isChecked() && !mImportMMActBox->isChecked())
mImportActBox->setChecked(true);
Message = tr("Blender %1 mProcess completed. Version: %2 validated.").arg(ProcessAction).arg(mBlenderVersion);
Message = tr("Blender %1 mProcess completed. Version: %2 validated.").arg(ProcessAction, mBlenderVersion);
}
}
}
@@ -1107,9 +1107,9 @@ void lcBlenderPreferences::ConfigureBlenderAddon(bool TestBlender, bool AddonUpd
#else
ScriptName = QLatin1String("blender_test.sh");
#endif
ScriptCommand = QString("\"%1\" %2").arg(BlenderExe).arg(Arguments.join(" "));
ScriptCommand = QString("\"%1\" %2").arg(BlenderExe, Arguments.join(" "));
ScriptFile.setFileName(QString("%1/%2").arg(QDir::tempPath()).arg(ScriptName));
ScriptFile.setFileName(QString("%1/%2").arg(QDir::tempPath(), ScriptName));
if (ScriptFile.open(QIODevice::WriteOnly | QIODevice::Text))
{
QTextStream Stream(&ScriptFile);
@@ -1213,7 +1213,7 @@ void lcBlenderPreferences::ConfigureBlenderAddon(bool TestBlender, bool AddonUpd
return;
}
if (!QFileInfo(BlenderInstallFile).exists())
if (!QFileInfo::exists(BlenderInstallFile))
{
ShowMessage(this, tr("Could not find addon install file: %1").arg(BlenderInstallFile));
StatusUpdate(true, true, tr("Not found."));
@@ -1242,7 +1242,7 @@ void lcBlenderPreferences::ConfigureBlenderAddon(bool TestBlender, bool AddonUpd
Arguments << QString("--disable_ldraw_render");
Arguments << QString("--leocad");
Message = tr("Blender Addon Install Arguments: %1 %2").arg(BlenderExe).arg(Arguments.join(" "));
Message = tr("Blender Addon Install Arguments: %1 %2").arg(BlenderExe, Arguments.join(" "));
if (!TestBlender)
mBlenderVersionFound = false;
@@ -1250,10 +1250,10 @@ void lcBlenderPreferences::ConfigureBlenderAddon(bool TestBlender, bool AddonUpd
if (QDir(BlenderAddonDir).entryInfoList(QDir::Dirs|QDir::NoSymLinks).count() > 0)
{
QJsonArray JsonArray;
QStringList AddonDirs = QDir(BlenderAddonDir).entryList(QDir::NoDotAndDotDot | QDir::Dirs, QDir::SortByMask);
const QStringList AddonDirs = QDir(BlenderAddonDir).entryList(QDir::NoDotAndDotDot | QDir::Dirs, QDir::SortByMask);
for (const QString& Addon : AddonDirs)
{
QDir Dir(QString("%1/%2").arg(BlenderAddonDir).arg(Addon));
QDir Dir(QString("%1/%2").arg(BlenderAddonDir, Addon));
Dir.setFilter(QDir::Files | QDir::NoDotAndDotDot | QDir::NoSymLinks);
QFileInfoList List = Dir.entryInfoList();
for (int LblIdx = 0; LblIdx < List.size(); LblIdx++)
@@ -1263,7 +1263,7 @@ void lcBlenderPreferences::ConfigureBlenderAddon(bool TestBlender, bool AddonUpd
QFile File(QFileInfo(List.at(LblIdx)).absoluteFilePath());
if (!File.open(QFile::ReadOnly | QFile::Text))
{
ShowMessage(this, tr("Cannot read addon file %1<br>%2").arg(List.at(LblIdx).fileName()).arg(File.errorString()));
ShowMessage(this, tr("Cannot read addon file %1<br>%2").arg(List.at(LblIdx).fileName(), File.errorString()));
break;
}
else
@@ -1350,14 +1350,14 @@ bool lcBlenderPreferences::ExtractBlenderAddon(const QString& BlenderDir)
if (AddonAction == ADDON_EXTRACT)
{
gAddonPreferences->StatusUpdate(true, false, tr("Extracting..."));
const QString BlenderAddonFile = QDir::toNativeSeparators(QString("%1/%2").arg(BlenderDir).arg(LC_BLENDER_ADDON_FILE));
const QString BlenderAddonFile = QDir::toNativeSeparators(QString("%1/%2").arg(BlenderDir, LC_BLENDER_ADDON_FILE));
QString Result;
Extracted = gAddonPreferences->ExtractAddon(BlenderAddonFile, Result);
if (!Extracted)
{
QString Message = tr("Failed to extract %1 to %2").arg(LC_BLENDER_ADDON_FILE).arg(BlenderDir);
QString Message = tr("Failed to extract %1 to %2").arg(LC_BLENDER_ADDON_FILE, BlenderDir);
if (Result.size())
Message.append(" "+Result);
@@ -1373,8 +1373,8 @@ bool lcBlenderPreferences::ExtractBlenderAddon(const QString& BlenderDir)
int lcBlenderPreferences::GetBlenderAddon(const QString& BlenderDir)
{
const QString BlenderAddonDir = QDir::toNativeSeparators(QString("%1/addons").arg(BlenderDir));
const QString BlenderAddonFile = QDir::toNativeSeparators(QString("%1/%2").arg(BlenderDir).arg(LC_BLENDER_ADDON_FILE));
const QString AddonVersionFile = QDir::toNativeSeparators(QString("%1/%2/__version__.py").arg(BlenderAddonDir).arg(LC_BLENDER_ADDON_RENDER_FOLDER));
const QString BlenderAddonFile = QDir::toNativeSeparators(QString("%1/%2").arg(BlenderDir, LC_BLENDER_ADDON_FILE));
const QString AddonVersionFile = QDir::toNativeSeparators(QString("%1/%2/__version__.py").arg(BlenderAddonDir, LC_BLENDER_ADDON_RENDER_FOLDER));
bool ExtractedAddon = QFileInfo(AddonVersionFile).isReadable();
bool BlenderAddonValidated = ExtractedAddon || QFileInfo(BlenderAddonFile).isReadable();
AddonEnc AddonAction = ADDON_DOWNLOAD;
@@ -1418,7 +1418,7 @@ int lcBlenderPreferences::GetBlenderAddon(const QString& BlenderDir)
if (!gAddonPreferences->mData.isEmpty())
{
QJsonDocument Json = QJsonDocument::fromJson(gAddonPreferences->mData);
OnlineVersion = Json.object()["tag_name"].toString();
OnlineVersion = Json.object().value("tag_name").toString();
gAddonPreferences->mData.clear();
}
else
@@ -1460,7 +1460,7 @@ int lcBlenderPreferences::GetBlenderAddon(const QString& BlenderDir)
QFile File(AddonVersionFile);
if (!File.open(QIODevice::ReadOnly))
{
ShowMessage(this, tr("Cannot read addon version file: [%1]<br>%2.").arg(AddonVersionFile).arg(File.errorString()));
ShowMessage(this, tr("Cannot read addon version file: [%1]<br>%2.").arg(AddonVersionFile, File.errorString()));
return false; // Download new archive
}
Ba = File.readAll();
@@ -1505,7 +1505,7 @@ int lcBlenderPreferences::GetBlenderAddon(const QString& BlenderDir)
if (LocalVersion.isEmpty())
LocalVersion = gAddonPreferences->mAddonVersion;
const QString& Title = tr ("%1 Blender LDraw Addon").arg(LC_PRODUCTNAME_STR);
const QString& Header = tr ("Detected %1 Blender LDraw addon %2. A newer version %3 exists.").arg(LC_PRODUCTNAME_STR).arg(LocalVersion).arg(OnlineVersion);
const QString& Header = tr ("Detected %1 Blender LDraw addon %2. A newer version %3 exists.").arg(LC_PRODUCTNAME_STR, LocalVersion, OnlineVersion);
const QString& Body = tr ("Do you want to download version %1 ?").arg(OnlineVersion);
int Exec = ShowMessage(this, Header, Title, Body, QString(), MBB_YES, QMessageBox::NoIcon);
if (Exec == QMessageBox::Cancel)
@@ -1526,7 +1526,7 @@ int lcBlenderPreferences::GetBlenderAddon(const QString& BlenderDir)
auto RemoveOldBlenderAddon = [&] (const QString& OldBlenderAddonFile)
{
if (QFileInfo(BlenderAddonDir).exists())
if (QFileInfo::exists(BlenderAddonDir))
{
bool Result = true;
QDir Dir(BlenderAddonDir);
@@ -1538,7 +1538,7 @@ int lcBlenderPreferences::GetBlenderAddon(const QString& BlenderDir)
Result &= QFile::remove(FileInfo.absoluteFilePath());
}
if (QFileInfo(OldBlenderAddonFile).exists())
if (QFileInfo::exists(OldBlenderAddonFile))
Result &= QFile::remove(OldBlenderAddonFile);
Result &= Dir.rmdir(BlenderAddonDir);
@@ -1556,7 +1556,7 @@ int lcBlenderPreferences::GetBlenderAddon(const QString& BlenderDir)
if (!gAddonPreferences->mData.isEmpty())
{
const QString OldBlenderAddonFile = QString("%1.hold").arg(BlenderAddonFile);
if (QFileInfo(BlenderAddonFile).exists())
if (QFileInfo::exists(BlenderAddonFile))
{
if (!QFile::rename(BlenderAddonFile, OldBlenderAddonFile))
ShowMessage(this, tr("Failed to rename existing Blender addon archive %1.").arg(BlenderAddonFile));
@@ -1578,8 +1578,8 @@ int lcBlenderPreferences::GetBlenderAddon(const QString& BlenderDir)
qint64 DataSize = File.size();
const qint64 BufferSize = Q_INT64_C(1000);
char Buf[BufferSize];
int BytesRead;
int ReadSize = qMin(DataSize, BufferSize);
qint64 BytesRead;
qint64 ReadSize = qMin(DataSize, BufferSize);
while (ReadSize > 0 && (BytesRead = File.read(Buf, ReadSize)) > 0)
{
DataSize -= BytesRead;
@@ -1615,17 +1615,17 @@ int lcBlenderPreferences::GetBlenderAddon(const QString& BlenderDir)
ShowMessage(this, tr("Failed to receive SHA hash for Blender addon %1.sha256").arg(LC_BLENDER_ADDON_FILE));
}
else
ShowMessage(this, tr("Failed to read Blender addon archive:<br>%1:<br>%2").arg(BlenderAddonFile).arg(File.errorString()));
ShowMessage(this, tr("Failed to read Blender addon archive:<br>%1:<br>%2").arg(BlenderAddonFile, File.errorString()));
}
else
ShowMessage(this, tr("Failed to write Blender addon archive:<br>%1:<br>%2").arg(BlenderAddonFile).arg(File.errorString()));
ShowMessage(this, tr("Failed to write Blender addon archive:<br>%1:<br>%2").arg(BlenderAddonFile, File.errorString()));
if (!BlenderAddonValidated)
{
if (QFileInfo(BlenderAddonFile).exists())
if (QFileInfo::exists(BlenderAddonFile))
if (!QFile::remove(BlenderAddonFile))
ShowMessage(this, tr("Failed to remove invalid Blender addon archive:<br>%1").arg(BlenderAddonFile));
if (QFileInfo(OldBlenderAddonFile).exists())
if (QFileInfo::exists(OldBlenderAddonFile))
if (!QFile::rename(OldBlenderAddonFile, BlenderAddonFile))
ShowMessage(this, tr("Failed to restore Blender addon archive:<br>%1 from %2").arg(ArchiveFileName, OldArchiveFileName));
AddonAction = ADDON_FAIL;
@@ -1640,7 +1640,7 @@ int lcBlenderPreferences::GetBlenderAddon(const QString& BlenderDir)
if (!BlenderAddonValidated)
gAddonPreferences->StatusUpdate(true, true, tr("Download failed."));
if (!QDir(BlenderAddonDir).exists() && QFileInfo(BlenderAddonFile).exists())
if (!QDir(BlenderAddonDir).exists() && QFileInfo::exists(BlenderAddonFile))
AddonAction = ADDON_EXTRACT;
return AddonAction;
@@ -1867,7 +1867,7 @@ void lcBlenderPreferences::ReadStdOut(const QString& StdOutput, QString& Errors)
QRegularExpression RxError("^(?:\\w)*ERROR: ", QRegularExpression::CaseInsensitiveOption);
QRegularExpression RxWarning("^(?:\\w)*WARNING: ", QRegularExpression::CaseInsensitiveOption);
QRegularExpression RxAddonVersion("^ADDON VERSION: ", QRegularExpression::CaseInsensitiveOption);
QStringList StdOutLines = StdOutput.split(QRegularExpression("\n|\r\n|\r"));
const QStringList StdOutLines = StdOutput.split(QRegularExpression("\n|\r\n|\r"));
#else
QRegExp RxInfo("^INFO: ");
QRegExp RxData("^DATA: ");
@@ -1883,7 +1883,7 @@ void lcBlenderPreferences::ReadStdOut(const QString& StdOutput, QString& Errors)
const QString SaveAddonVersion = mAddonVersion;
const QString SaveVersion = mBlenderVersion;
int EditListItems = mPathLineEditList.size();
qsizetype EditListItems = mPathLineEditList.size();
for (const QString& StdOutLine : StdOutLines)
{
if (StdOutLine.isEmpty())
@@ -2024,7 +2024,7 @@ QString lcBlenderPreferences::ReadStdErr(bool& Error) const
QFile File(QString("%1/stderr-blender-addon-install").arg(BlenderDir));
if (!File.open(QFile::ReadOnly | QFile::Text))
{
const QString Message = tr("Failed to open log file: %1:\n%2").arg(File.fileName()).arg(File.errorString());
const QString Message = tr("Failed to open log file: %1:\n%2").arg(File.fileName(), File.errorString());
return Message;
}
QTextStream In(&File);
@@ -2045,13 +2045,13 @@ void lcBlenderPreferences::WriteStdOut()
if (File.open(QFile::WriteOnly | QIODevice::Truncate | QFile::Text))
{
QTextStream Out(&File);
for (const QString& Line : mStdOutList)
for (const QString& Line : std::as_const(mStdOutList))
Out << Line << LineEnding;
File.close();
mAddonStdOutButton->setEnabled(true);
}
else
ShowMessage(this, tr("Error writing to %1 file '%2':\n%3").arg("stdout").arg(File.fileName(), File.errorString()));
ShowMessage(this, tr("Error writing to %1 file '%2':\n%3").arg("stdout", File.fileName(), File.errorString()));
}
bool lcBlenderPreferences::PromptCancel()
@@ -2515,7 +2515,7 @@ void lcBlenderPreferences::LoadSettings()
lcSetProfileString(LC_PROFILE_BLENDER_IMPORT_MODULE, QString());
}
if (!QDir(QString("%1/Blender/addons/%2").arg(gAddonPreferences->mDataDir).arg(LC_BLENDER_ADDON_RENDER_FOLDER)).isReadable())
if (!QDir(QString("%1/Blender/addons/%2").arg(gAddonPreferences->mDataDir, LC_BLENDER_ADDON_RENDER_FOLDER)).isReadable())
lcSetProfileString(LC_PROFILE_BLENDER_IMPORT_MODULE, QString());
bool UseArchiveLibrary = false;
@@ -2538,11 +2538,11 @@ void lcBlenderPreferences::LoadSettings()
if (!NumPaths())
{
const QString DefaultBlendFile = QString("%1/Blender/config/%2").arg(gAddonPreferences->mDataDir).arg(LC_BLENDER_ADDON_BLEND_FILE);
const QString DefaultBlendFile = QString("%1/Blender/config/%2").arg(gAddonPreferences->mDataDir, LC_BLENDER_ADDON_BLEND_FILE);
QStringList const AddonPaths = QStringList()
/* 0 PATH_BLENDER */ << lcGetProfileString(LC_PROFILE_BLENDER_PATH)
/* 1 PATH_BLENDFILE */ << (QFileInfo(DefaultBlendFile).exists() ? DefaultBlendFile : QString())
/* 1 PATH_BLENDFILE */ << (QFileInfo::exists(DefaultBlendFile) ? DefaultBlendFile : QString())
/* 2 PATH_ENVIRONMENT */ << QString()
/* 3 PATH_LDCONFIG */ << lcGetProfileString(LC_PROFILE_COLOR_CONFIG)
/* 4 PATH_LDRAW */ << LDrawPartsLibrary(lcGetProfileString(LC_PROFILE_PARTS_LIBRARY))
@@ -2607,7 +2607,7 @@ void lcBlenderPreferences::LoadSettings()
continue;
const QString& Key = QString("%1/%2").arg(LC_BLENDER_ADDON, mBlenderPaths[LblIdx].key);
const QString& Value = Settings.value(Key, QString()).toString();
if (QFileInfo(Value).exists())
if (QFileInfo::exists(Value))
mBlenderPaths[LblIdx].value = QDir::toNativeSeparators(Value);
}
@@ -2617,7 +2617,7 @@ void lcBlenderPreferences::LoadSettings()
continue;
const QString& Key = QString("%1/%2").arg(LC_BLENDER_ADDON_MM, mBlenderPaths[LblIdx].key_mm);
const QString& Value = Settings.value(Key, QString()).toString();
if (QFileInfo(Value).exists())
if (QFileInfo::exists(Value))
mBlenderPaths[LblIdx].value = QDir::toNativeSeparators(Value);
}
@@ -2635,7 +2635,7 @@ void lcBlenderPreferences::LoadSettings()
if (LblIdx == LBL_IMAGE_WIDTH || LblIdx == LBL_IMAGE_HEIGHT || LblIdx == LBL_RENDER_PERCENTAGE)
{
const QString& Label = mDefaultSettings[LblIdx].label;
mBlenderSettings[LblIdx].label = QString("%1 - Setting (%2)").arg(Label).arg(Value);
mBlenderSettings[LblIdx].label = QString("%1 - Setting (%2)").arg(Label, Value);
}
}
@@ -2653,7 +2653,7 @@ void lcBlenderPreferences::LoadSettings()
if (LblIdx == LBL_RENDER_PERCENTAGE_MM || LblIdx == LBL_RESOLUTION_WIDTH || LblIdx == LBL_RESOLUTION_HEIGHT)
{
const QString& Label = mDefaultSettingsMM[LblIdx].label;
mBlenderSettingsMM[LblIdx].label = QString("%1 - Setting (%2)").arg(Label).arg(Value);
mBlenderSettingsMM[LblIdx].label = QString("%1 - Setting (%2)").arg(Label, Value);
}
}
}
@@ -2678,8 +2678,7 @@ void lcBlenderPreferences::LoadSettings()
{
ShowMessage(nullptr, tr("Blender config file was not found. "
"Install log check failed:<br>%1:<br>%2")
.arg(File.fileName())
.arg(File.errorString()));
.arg(File.fileName(), File.errorString()));
}
}
}
@@ -2720,24 +2719,24 @@ void lcBlenderPreferences::SaveSettings()
lcSetProfileString(LC_PROFILE_BLENDER_VERSION, Value);
const QString BlenderConfigDir = QString("%1/Blender/addons/%2/config").arg(gAddonPreferences->mDataDir).arg(LC_BLENDER_ADDON_RENDER_FOLDER);
const QString BlenderConfigDir = QString("%1/Blender/addons/%2/config").arg(gAddonPreferences->mDataDir, LC_BLENDER_ADDON_RENDER_FOLDER);
Value = lcGetProfileString(LC_PROFILE_BLENDER_LDRAW_CONFIG_PATH);
if (!Value.contains(LC_BLENDER_ADDON_RENDER_FOLDER))
{
Value = QString("%1/%2").arg(BlenderConfigDir).arg(LC_BLENDER_ADDON_CONFIG_FILE);
Value = QString("%1/%2").arg(BlenderConfigDir, LC_BLENDER_ADDON_CONFIG_FILE);
lcSetProfileString(LC_PROFILE_BLENDER_LDRAW_CONFIG_PATH, QDir::toNativeSeparators(Value));
}
QString searchDirectoriesKey = QLatin1String("additionalSearchPaths");
QString parameterFileKey = QLatin1String("ParameterFile");
QString ParameterFile = QString("%1/%2").arg(BlenderConfigDir).arg(LC_BLENDER_ADDON_PARAMS_FILE);
QString ParameterFile = QString("%1/%2").arg(BlenderConfigDir, LC_BLENDER_ADDON_PARAMS_FILE);
QSettings Settings(Value, QSettings::IniFormat);
auto concludeSettingsGroup = [&]()
{
if (!QFileInfo(ParameterFile).exists())
if (!QFileInfo::exists(ParameterFile))
ExportParameterFile();
Value = QDir::toNativeSeparators(QFileInfo(lcGetProfileString(LC_PROFILE_PROJECTS_PATH)).absolutePath());
Settings.setValue(searchDirectoriesKey, QVariant(Value));
@@ -3127,7 +3126,7 @@ void lcBlenderPreferences::SetModelSize(bool Update)
{
const QString& Title = tr ("LDraw Render Settings Conflict");
const QString& Header = "<b>" + tr ("Crop image configuration settings conflict were resolved.") + "</b>";
const QString& Body = QString("%1%2%3").arg(Conflict[0] ? tr("Keep aspect ratio set to false.<br>") : "").arg(Conflict[1] ? tr("Add environment (backdrop and base plane) set to false.<br>") : "").arg(Conflict[2] ? tr("Transparent background set to true.<br>") : "");
const QString& Body = QString("%1%2%3").arg(Conflict[0] ? tr("Keep aspect ratio set to false.<br>") : "", Conflict[1] ? tr("Add environment (backdrop and base plane) set to false.<br>") : "", Conflict[2] ? tr("Transparent background set to true.<br>") : "");
ShowMessage(this, Header, Title, Body, QString(), MBB_OK, QMessageBox::Information);
}
}
@@ -3457,8 +3456,8 @@ void lcBlenderPreferences::LoadDefaultParameters(QByteArray& Buffer, int Which)
bool lcBlenderPreferences::ExportParameterFile()
{
const QString BlenderConfigDir = QString("%1/Blender/addons/%2/config").arg(gAddonPreferences->mDataDir).arg(LC_BLENDER_ADDON_RENDER_FOLDER);
const QString ParameterFile = QString("%1/%2").arg(BlenderConfigDir).arg(LC_BLENDER_ADDON_PARAMS_FILE);
const QString BlenderConfigDir = QString("%1/Blender/addons/%2/config").arg(gAddonPreferences->mDataDir, LC_BLENDER_ADDON_RENDER_FOLDER);
const QString ParameterFile = QString("%1/%2").arg(BlenderConfigDir, LC_BLENDER_ADDON_PARAMS_FILE);
QDir ConfigDir(BlenderConfigDir);
if(!ConfigDir.exists())
ConfigDir.mkpath(".");
@@ -3550,8 +3549,7 @@ bool lcBlenderPreferences::ExportParameterFile()
else
{
Message = tr("Failed to open Blender parameter file: %1:<br>%2")
.arg(File.fileName())
.arg(File.errorString());
.arg(File.fileName(), File.errorString());
ShowMessage(nullptr, Message);
return false;
}
@@ -3627,16 +3625,16 @@ int lcBlenderPreferences::ShowMessage(QWidget* Parent, const QString& Header, c
QWidget* TextWidget = BoxLayoutItem->widget();
if (TextWidget)
{
int FixedWidth = Body.length() * FontWidth;
qsizetype FixedWidth = Body.length() * FontWidth;
if (FixedWidth == MinimumWidth)
{
int Index = (MinimumWidth / FontWidth) - 1;
if (!Body.mid(Index,1).isEmpty())
if (!Body.mid(Index, 1).isEmpty())
FixedWidth = Body.indexOf(" ", Index);
}
else if (FixedWidth < MinimumWidth)
FixedWidth = MinimumWidth;
TextWidget->setFixedWidth(FixedWidth);
TextWidget->setFixedWidth(static_cast<int>(FixedWidth));
}
}
+6 -4
View File
@@ -2,7 +2,9 @@
#include "lc_file.h"
#include "lc_library.h"
#include "lc_mainwindow.h"
#include "lc_string.h"
#include "pieceinf.h"
#include "lc_colors.h"
static QJsonDocument lcLoadBrickLinkMapping()
{
@@ -84,7 +86,7 @@ void lcExportBrickLink(const QString& SaveFileName, const lcPartsList& PartsList
for (const auto& ColorIt : PartIt.second)
{
char FileName[LC_PIECE_NAME_LEN];
strcpy(FileName, Info->mFileName);
lcstrcpy(FileName, Info->mFileName);
char* Ext = strchr(FileName, '.');
if (Ext)
*Ext = 0;
@@ -109,15 +111,15 @@ void lcExportBrickLink(const QString& SaveFileName, const lcPartsList& PartsList
{
BrickLinkFile.WriteLine(" <ITEM>\n");
BrickLinkFile.WriteLine(" <ITEMTYPE>P</ITEMTYPE>\n");
sprintf(Line, " <ITEMID>%s</ITEMID>\n", Item.second.mId.c_str());
snprintf(Line, sizeof(Line), " <ITEMID>%s</ITEMID>\n", Item.second.mId.c_str());
BrickLinkFile.WriteLine(Line);
sprintf(Line, " <MINQTY>%d</MINQTY>\n", Item.second.mCount);
snprintf(Line, sizeof(Line), " <MINQTY>%d</MINQTY>\n", Item.second.mCount);
BrickLinkFile.WriteLine(Line);
if (Item.second.mColor)
{
sprintf(Line, " <COLOR>%d</COLOR>\n", Item.second.mColor);
snprintf(Line, sizeof(Line), " <COLOR>%d</COLOR>\n", Item.second.mColor);
BrickLinkFile.WriteLine(Line);
}
+3 -3
View File
@@ -1,6 +1,6 @@
#include "lc_global.h"
#include "lc_category.h"
#include "lc_file.h"
#include "lc_string.h"
#include "lc_profile.h"
std::vector<lcLibraryCategory> gCategories;
@@ -106,7 +106,7 @@ bool lcLoadCategories(const QByteArray& Buffer, std::vector<lcLibraryCategory>&
for (QString Line = Stream.readLine(); !Line.isNull(); Line = Stream.readLine())
{
int Equals = Line.indexOf('=');
qsizetype Equals = Line.indexOf('=');
if (Equals == -1)
continue;
@@ -261,7 +261,7 @@ bool lcMatchCategory(const char* PieceName, const char* Expression)
if (!Word[0])
return false;
const char* Result = strcasestr(PieceName, Word);
const char* Result = lcstrcasestr(PieceName, Word);
if (!Result)
return false;
+1 -1
View File
@@ -9,7 +9,7 @@ class lcCategoryDialog;
class lcCategoryDialog : public QDialog
{
Q_OBJECT
public:
explicit lcCategoryDialog(QWidget* Parent, lcLibraryCategory* Category);
virtual ~lcCategoryDialog();
+16 -15
View File
@@ -3,6 +3,7 @@
#include "lc_file.h"
#include "lc_library.h"
#include "lc_application.h"
#include "lc_string.h"
#include <float.h>
std::vector<lcColor> gColorList;
@@ -79,7 +80,7 @@ static std::vector<lcColor> lcParseColorFile(lcFile& File)
continue;
GetToken(Ptr, Token);
strupr(Token);
lcstrupr(Token);
if (strcmp(Token, "!COLOUR"))
continue;
@@ -107,7 +108,7 @@ static std::vector<lcColor> lcParseColorFile(lcFile& File)
for (GetToken(Ptr, Token); Token[0]; GetToken(Ptr, Token))
{
strupr(Token);
lcstrupr(Token);
if (!strcmp(Token, "CODE"))
{
@@ -258,8 +259,8 @@ bool lcLoadColorFile(lcFile& File, lcStudStyle StudStyle)
MainColor.Edge[1] = 0.2f;
MainColor.Edge[2] = 0.2f;
MainColor.Edge[3] = 1.0f;
strcpy(MainColor.Name, "Main Color");
strcpy(MainColor.SafeName, "Main_Color");
lcstrcpy(MainColor.Name, "Main Color");
lcstrcpy(MainColor.SafeName, "Main_Color");
Colors.push_back(MainColor);
}
@@ -281,8 +282,8 @@ bool lcLoadColorFile(lcFile& File, lcStudStyle StudStyle)
EdgeColor.Edge[1] = 0.2f;
EdgeColor.Edge[2] = 0.2f;
EdgeColor.Edge[3] = 1.0f;
strcpy(EdgeColor.Name, "Edge Color");
strcpy(EdgeColor.SafeName, "Edge_Color");
lcstrcpy(EdgeColor.Name, "Edge Color");
lcstrcpy(EdgeColor.SafeName, "Edge_Color");
Colors.push_back(EdgeColor);
}
@@ -299,8 +300,8 @@ bool lcLoadColorFile(lcFile& File, lcStudStyle StudStyle)
StudCylinderColor.Group = LC_NUM_COLORGROUPS;
StudCylinderColor.Value = lcVector4FromColor(Preferences.mStudCylinderColor);
StudCylinderColor.Edge = lcVector4FromColor(Preferences.mPartEdgeColor);
strcpy(StudCylinderColor.Name, "Stud Cylinder Color");
strcpy(StudCylinderColor.SafeName, "Stud_Cylinder_Color");
lcstrcpy(StudCylinderColor.Name, "Stud Cylinder Color");
lcstrcpy(StudCylinderColor.SafeName, "Stud_Cylinder_Color");
Colors.push_back(StudCylinderColor);
}
@@ -322,8 +323,8 @@ bool lcLoadColorFile(lcFile& File, lcStudStyle StudStyle)
NoColor.Edge[1] = 0.2f;
NoColor.Edge[2] = 0.2f;
NoColor.Edge[3] = 1.0f;
strcpy(NoColor.Name, "No Color");
strcpy(NoColor.SafeName, "No_Color");
lcstrcpy(NoColor.Name, "No Color");
lcstrcpy(NoColor.SafeName, "No_Color");
Colors.push_back(NoColor);
}
@@ -394,8 +395,8 @@ int lcGetColorIndex(quint32 ColorCode)
Color.Value[1] = (float)((ColorCode & 0x00ff00) >> 8) / 255.0f;
Color.Value[2] = (float)((ColorCode & 0x0000ff) >> 0) / 255.0f;
Color.Value[3] = 1.0f;
sprintf(Color.Name, "Color %06X", ColorCode & 0xffffff);
sprintf(Color.SafeName, "Color_%06X", ColorCode & 0xffffff);
snprintf(Color.Name, sizeof(Color.Name), "Color %06X", ColorCode & 0xffffff);
snprintf(Color.SafeName, sizeof(Color.SafeName), "Color_%06X", ColorCode & 0xffffff);
}
else
{
@@ -403,8 +404,8 @@ int lcGetColorIndex(quint32 ColorCode)
Color.Value[1] = 0.5f;
Color.Value[2] = 0.5f;
Color.Value[3] = 1.0f;
sprintf(Color.Name, "Color %03d", ColorCode);
sprintf(Color.SafeName, "Color_%03d", ColorCode);
snprintf(Color.Name, sizeof(Color.Name), "Color %03d", ColorCode);
snprintf(Color.SafeName, sizeof(Color.SafeName), "Color_%03d", ColorCode);
}
gColorList.push_back(Color);
@@ -421,7 +422,7 @@ QString lcGetColorToolTip(int ColorIndex)
QPainter Painter(&Image);
Painter.setPen(Qt::darkGray);
if (Color->Code != LC_COLOR_NOCOLOR)
Painter.drawRect(0, 0, Image.width() - 1, Image.height() - 1);
else
-217
View File
@@ -52,10 +52,6 @@ lcContext::lcContext()
mColorBlend = false;
mCullFace = false;
mLineWidth = 1.0f;
#if LC_FIXED_FUNCTION
mMatrixMode = GL_MODELVIEW;
mTextureEnabled = false;
#endif
mColor = lcVector4(0.0f, 0.0f, 0.0f, 0.0f);
mWorldMatrix = lcMatrix44Identity();
@@ -417,24 +413,6 @@ void lcContext::SetDefaultState()
DisableVertexAttrib(lcProgramAttrib::Color);
SetVertexAttribPointer(lcProgramAttrib::Color, 4, GL_FLOAT, false, 0, nullptr);
}
else
{
#if LC_FIXED_FUNCTION
glEnableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, nullptr);
glNormalPointer(GL_BYTE, 0, nullptr);
glTexCoordPointer(2, GL_FLOAT, 0, nullptr);
glColorPointer(4, GL_FLOAT, 0, nullptr);
mNormalEnabled = false;
mTexCoordEnabled = false;
mColorEnabled = false;
#endif
}
mVertexBufferObject = 0;
mIndexBufferObject = 0;
@@ -467,17 +445,6 @@ void lcContext::SetDefaultState()
glUseProgram(0);
mMaterialType = lcMaterialType::Count;
}
else
{
#if LC_FIXED_FUNCTION
glMatrixMode(GL_MODELVIEW);
mMatrixMode = GL_MODELVIEW;
glShadeModel(GL_FLAT);
glDisable(GL_TEXTURE_2D);
mTextureEnabled = false;
#endif
}
}
void lcContext::ClearColorAndDepth(const lcVector4& ClearColor)
@@ -513,49 +480,6 @@ void lcContext::SetMaterial(lcMaterialType MaterialType)
mViewMatrixDirty = true;
mHighlightParamsDirty = true;
}
else
{
#if LC_FIXED_FUNCTION
switch (MaterialType)
{
case lcMaterialType::UnlitTextureModulate:
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
if (!mTextureEnabled)
{
glEnable(GL_TEXTURE_2D);
mTextureEnabled = true;
}
break;
case lcMaterialType::FakeLitTextureDecal:
case lcMaterialType::UnlitTextureDecal:
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
if (!mTextureEnabled)
{
glEnable(GL_TEXTURE_2D);
mTextureEnabled = true;
}
break;
case lcMaterialType::UnlitColor:
case lcMaterialType::UnlitColorConditional:
case lcMaterialType::UnlitVertexColor:
case lcMaterialType::FakeLitColor:
if (mTextureEnabled)
{
glDisable(GL_TEXTURE_2D);
mTextureEnabled = false;
}
break;
case lcMaterialType::UnlitViewSphere:
case lcMaterialType::Count:
break;
}
#endif
}
}
void lcContext::SetViewport(int x, int y, int Width, int Height)
@@ -981,24 +905,6 @@ void lcContext::ClearVertexBuffer()
DisableVertexAttrib(lcProgramAttrib::Color);
SetVertexAttribPointer(lcProgramAttrib::Color, 4, GL_FLOAT, false, 0, nullptr);
}
else
{
#if LC_FIXED_FUNCTION
if (mNormalEnabled)
glDisableClientState(GL_NORMAL_ARRAY);
if (mTexCoordEnabled)
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
if (mColorEnabled)
glDisableClientState(GL_COLOR_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, nullptr);
glNormalPointer(GL_BYTE, 0, nullptr);
glTexCoordPointer(2, GL_FLOAT, 0, nullptr);
glColorPointer(4, GL_FLOAT, 0, nullptr);
#endif
}
}
void lcContext::SetVertexBuffer(lcVertexBuffer VertexBuffer)
@@ -1088,34 +994,6 @@ void lcContext::SetVertexFormatPosition(int PositionSize)
DisableVertexAttrib(lcProgramAttrib::TexCoord);
DisableVertexAttrib(lcProgramAttrib::Color);
}
else
{
#if LC_FIXED_FUNCTION
if (mVertexBufferOffset != mVertexBufferPointer)
{
glVertexPointer(PositionSize, GL_FLOAT, VertexSize, VertexBufferPointer);
mVertexBufferOffset = VertexBufferPointer;
}
if (mNormalEnabled)
{
glDisableClientState(GL_NORMAL_ARRAY);
mNormalEnabled = false;
}
if (mTexCoordEnabled)
{
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
mTexCoordEnabled = false;
}
if (mColorEnabled)
{
glDisableClientState(GL_COLOR_ARRAY);
mColorEnabled = false;
}
#endif
}
}
void lcContext::SetVertexFormatConditional(int BufferOffset)
@@ -1178,70 +1056,6 @@ void lcContext::SetVertexFormat(int BufferOffset, int PositionSize, int NormalSi
else
DisableVertexAttrib(lcProgramAttrib::Color);
}
else
{
#if LC_FIXED_FUNCTION
if (mVertexBufferOffset != VertexBufferPointer)
{
glVertexPointer(PositionSize, GL_FLOAT, VertexSize, VertexBufferPointer);
mVertexBufferOffset = VertexBufferPointer;
}
int Offset = PositionSize * sizeof(float);
if (NormalSize && EnableNormals)
{
glNormalPointer(GL_BYTE, VertexSize, VertexBufferPointer + Offset);
if (!mNormalEnabled)
{
glEnableClientState(GL_NORMAL_ARRAY);
mNormalEnabled = true;
}
}
else if (mNormalEnabled)
{
glDisableClientState(GL_NORMAL_ARRAY);
mNormalEnabled = false;
}
Offset += NormalSize * sizeof(quint32);
if (TexCoordSize)
{
glTexCoordPointer(TexCoordSize, GL_FLOAT, VertexSize, VertexBufferPointer + Offset);
if (!mTexCoordEnabled)
{
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
mTexCoordEnabled = true;
}
Offset += 2 * sizeof(float);
}
else if (mTexCoordEnabled)
{
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
mTexCoordEnabled = false;
}
if (ColorSize)
{
glColorPointer(ColorSize, GL_FLOAT, VertexSize, VertexBufferPointer + Offset);
if (!mColorEnabled)
{
glEnableClientState(GL_COLOR_ARRAY);
mColorEnabled = true;
}
}
else if (mColorEnabled)
{
glDisableClientState(GL_COLOR_ARRAY);
mColorEnabled = false;
}
#endif
}
}
void lcContext::ClearIndexBuffer()
@@ -1380,37 +1194,6 @@ void lcContext::FlushState()
mHighlightParamsDirty = false;
}
}
else
{
#if LC_FIXED_FUNCTION
glColor4fv(mColor.GetFloats());
if (mWorldMatrixDirty || mViewMatrixDirty)
{
if (mMatrixMode != GL_MODELVIEW)
{
glMatrixMode(GL_MODELVIEW);
mMatrixMode = GL_MODELVIEW;
}
glLoadMatrixf(lcMul(mWorldMatrix, mViewMatrix).GetFloats());
mWorldMatrixDirty = false;
mViewMatrixDirty = false;
}
if (mProjectionMatrixDirty)
{
if (mMatrixMode != GL_PROJECTION)
{
glMatrixMode(GL_PROJECTION);
mMatrixMode = GL_PROJECTION;
}
glLoadMatrixf(mProjectionMatrix.GetFloats());
mProjectionMatrixDirty = false;
}
#endif
}
}
void lcContext::DrawPrimitives(GLenum Mode, GLint First, GLsizei Count)
+1 -2
View File
@@ -1,7 +1,6 @@
#pragma once
#include "lc_math.h"
#include "lc_colors.h"
#include "lc_mesh.h"
class lcVertexBuffer
@@ -105,7 +104,7 @@ struct lcVertexAttribState
GLuint VertexBufferObject = 0;
};
class lcContext : protected QOpenGLFunctions
class lcContext : public QOpenGLFunctions
{
public:
lcContext();
+17
View File
@@ -216,6 +216,23 @@ bool lcDoubleSpinBox::event(QEvent* Event)
return true;
}
}
else if (Event->type() == QEvent::ShortcutOverride)
{
QKeyEvent* KeyEvent = static_cast<QKeyEvent*>(Event);
switch (KeyEvent->key())
{
case Qt::Key_Up:
case Qt::Key_Down:
case Qt::Key_PageUp:
case Qt::Key_PageDown:
Event->accept();
return true;
default:
break;
}
}
return QDoubleSpinBox::event(Event);
}
+1 -1
View File
@@ -16,7 +16,7 @@ lcMemFile::lcMemFile()
lcMemFile::~lcMemFile()
{
Close();
lcMemFile::Close();
}
void lcMemFile::Seek(qint64 Offset, int From)
+4 -4
View File
@@ -283,7 +283,7 @@ public:
void WriteQString(const QString& String)
{
QByteArray Data = String.toUtf8();
WriteU32(Data.size());
WriteU32(static_cast<quint32>(Data.size()));
WriteBuffer(Data, Data.size());
}
@@ -459,7 +459,7 @@ class lcMemFile : public lcFile
{
public:
lcMemFile();
~lcMemFile();
virtual ~lcMemFile();
lcMemFile(const lcMemFile&) = delete;
lcMemFile(lcMemFile&&) = delete;
@@ -498,9 +498,9 @@ public:
{
}
~lcDiskFile()
virtual ~lcDiskFile()
{
Close();
lcDiskFile::Close();
}
lcDiskFile(const lcDiskFile&) = delete;
+27 -26
View File
@@ -1,5 +1,6 @@
#include "lc_global.h"
#include "lc_filter.h"
#include "lc_string.h"
lcFilter::lcFilter(const std::string_view FilterString)
{
@@ -80,7 +81,7 @@ bool lcFilter::Match(const char* String) const
for (const FilterPart& FilterPart : mFilterParts)
{
bool Match = FilterPart.Wildcard ? FastWildCompare(String, FilterPart.String.c_str()) : strcasestr(String, FilterPart.String.c_str()) != nullptr;
bool Match = FilterPart.Wildcard ? FastWildCompare(String, FilterPart.String.c_str()) : lcstrcasestr(String, FilterPart.String.c_str()) != nullptr;
switch (FilterPart.Op)
{
@@ -106,41 +107,41 @@ bool lcFilter::Match(const char* String) const
}
// Copyright 2018 IBM Corporation
//
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//
// http://www.apache.org/licenses/LICENSE-2.0
//
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Compares two text strings. Accepts '?' as a single-character wildcard.
// For each '*' wildcard, seeks out a matching sequence of any characters
// beyond it. Otherwise compares the strings a character at a time.
// Compares two text strings. Accepts '?' as a single-character wildcard.
// For each '*' wildcard, seeks out a matching sequence of any characters
// beyond it. Otherwise compares the strings a character at a time.
//
bool lcFilter::FastWildCompare(const char* Tame, const char* Wild)
{
const char* WildSequence; // Points to prospective wild string match after '*'
const char* TameSequence; // Points to prospective tame string match
auto NotEquals=[](char a, char b)
{
// Lowercase the characters to be compared.
if (a >= 'A' && a <= 'Z')
a += ('a' - 'A');
if (b >= 'A' && b <= 'Z')
b += ('a' - 'A');
return a != b;
};
// Find a first wildcard, if one exists, and the beginning of any
// Find a first wildcard, if one exists, and the beginning of any
// prospectively matching sequence after it.
do
{
@@ -156,7 +157,7 @@ bool lcFilter::FastWildCompare(const char* Tame, const char* Wild)
return true; // "ab" matches "ab*".
}
}
return false; // "abcd" doesn't match "abc".
}
else
@@ -171,12 +172,12 @@ bool lcFilter::FastWildCompare(const char* Tame, const char* Wild)
{
continue;
}
if (!*Wild)
{
return true; // "abc*" matches "abcd".
}
// Search for the next prospective match.
if (*Wild != '?')
{
@@ -188,7 +189,7 @@ bool lcFilter::FastWildCompare(const char* Tame, const char* Wild)
}
}
}
// Keep fallback positions for retry in case of incomplete match.
WildSequence = Wild;
TameSequence = Tame;
@@ -198,11 +199,11 @@ bool lcFilter::FastWildCompare(const char* Tame, const char* Wild)
{
return false; // "abc" doesn't match "abd".
}
++Wild; // Everything's a match, so far.
++Tame;
} while (true);
// Find any further wildcards and any further matching sequences.
do
{
@@ -213,17 +214,17 @@ bool lcFilter::FastWildCompare(const char* Tame, const char* Wild)
{
continue;
}
if (!*Wild)
{
return true; // "ab*c*" matches "abcd".
}
if (!*Tame)
{
return false; // "*bcd*" doesn't match "abc".
}
// Search for the next prospective match.
if (*Wild != '?')
{
@@ -235,7 +236,7 @@ bool lcFilter::FastWildCompare(const char* Tame, const char* Wild)
}
}
}
// Keep the new fallback positions.
WildSequence = Wild;
TameSequence = Tame;
@@ -247,16 +248,16 @@ bool lcFilter::FastWildCompare(const char* Tame, const char* Wild)
{
return false; // "*bcd" doesn't match "abc".
}
// A fine time for questions.
while (*WildSequence == '?')
{
++WildSequence;
++TameSequence;
}
Wild = WildSequence;
// Fall back, but never so far again.
while (NotEquals(*Wild, *(++TameSequence)))
{
@@ -265,10 +266,10 @@ bool lcFilter::FastWildCompare(const char* Tame, const char* Wild)
return false; // "*a*b" doesn't match "ac".
}
}
Tame = TameSequence;
}
// Another check for the end, at the end.
if (!*Tame)
{
@@ -281,7 +282,7 @@ bool lcFilter::FastWildCompare(const char* Tame, const char* Wild)
return false; // "*bc" doesn't match "abcd".
}
}
++Wild; // Everything's still a match.
++Tame;
} while (true);
+29 -14
View File
@@ -2,6 +2,7 @@
#include "lc_findreplacewidget.h"
#include "lc_colorpicker.h"
#include "lc_mainwindow.h"
#include "lc_partselectionpopup.h"
#include "pieceinf.h"
#include "piece.h"
#include "lc_model.h"
@@ -37,8 +38,8 @@ lcFindReplaceWidget::lcFindReplaceWidget(QWidget* Parent, lcModel* Model, bool R
Layout->addWidget(FindNextButton, 0, 3);
QToolButton* FindAllButton = new QToolButton(this);
FindAllButton ->setAutoRaise(true);
FindAllButton ->setDefaultAction(gMainWindow->mActions[LC_EDIT_FIND_ALL]);
FindAllButton->setAutoRaise(true);
FindAllButton->setDefaultAction(gMainWindow->mActions[LC_EDIT_FIND_ALL]);
Layout->addWidget(FindAllButton, 0, 4);
connect(FindColorPicker, &lcColorPicker::ColorChanged, this, &lcFindReplaceWidget::FindColorIndexChanged);
@@ -56,9 +57,21 @@ lcFindReplaceWidget::lcFindReplaceWidget(QWidget* Parent, lcModel* Model, bool R
ReplaceColorPicker->setToolTip(tr("Replacement Color"));
Layout->addWidget(ReplaceColorPicker, 1, 1);
mReplacePartComboBox = new QComboBox(this);
mReplacePartComboBox->setToolTip(tr("Replacement Part"));
Layout->addWidget(mReplacePartComboBox, 1, 2);
QPixmap Pixmap(1, 1);
Pixmap.fill(QColor::fromRgba64(0, 0, 0, 0));
mReplacePartButton = new lcElidableToolButton(this);
mReplacePartButton->setToolTip(tr("Replacement Part"));
QSizePolicy PieceButtonSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
PieceButtonSizePolicy.setHorizontalStretch(2);
PieceButtonSizePolicy.setVerticalStretch(0);
mReplacePartButton->setSizePolicy(PieceButtonSizePolicy);
mReplacePartButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
mReplacePartButton->setIcon(Pixmap);
Layout->addWidget(mReplacePartButton, 1, 2);
QToolButton* ReplaceNextButton = new QToolButton(this);
ReplaceNextButton->setAutoRaise(true);
@@ -71,15 +84,10 @@ lcFindReplaceWidget::lcFindReplaceWidget(QWidget* Parent, lcModel* Model, bool R
Layout->addWidget(ReplaceAllButton, 1, 4);
connect(ReplaceColorPicker, &lcColorPicker::ColorChanged, this, &lcFindReplaceWidget::ReplaceColorIndexChanged);
connect(mReplacePartComboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), this, &lcFindReplaceWidget::ReplaceActivated);
mReplacePartComboBox->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon);
mReplacePartComboBox->setMinimumContentsLength(1);
mReplacePartComboBox->setModel(new lcPieceIdStringModel(gMainWindow->GetActiveModel(), mReplacePartComboBox));
connect(mReplacePartButton, &lcElidableToolButton::clicked, this, &lcFindReplaceWidget::ReplaceButtonClicked);
ReplaceColorPicker->SetCurrentColor(lcGetColorIndex(LC_COLOR_NOCOLOR));
mReplacePartComboBox->setCurrentIndex(0);
mReplacePartButton->setText(tr("None"));
}
QToolButton* CloseButton = new QToolButton(this);
@@ -152,9 +160,16 @@ void lcFindReplaceWidget::ReplaceColorIndexChanged(int ColorIndex)
Params.ReplaceColorIndex = ColorIndex;
}
void lcFindReplaceWidget::ReplaceActivated(int Index)
void lcFindReplaceWidget::ReplaceButtonClicked()
{
lcFindReplaceParams& Params = lcView::GetFindReplaceParams();
Params.ReplacePieceInfo = (PieceInfo*)mReplacePartComboBox->itemData(Index).value<void*>();
std::optional<PieceInfo*> Result = lcShowPartSelectionPopup(Params.ReplacePieceInfo, std::vector<std::pair<PieceInfo*, std::string>>(),
gDefaultColor, mReplacePartButton, mReplacePartButton->mapToGlobal(mReplacePartButton->rect().bottomLeft()));
if (!Result.has_value())
return;
Params.ReplacePieceInfo = Result.value();
mReplacePartButton->setText(Result.value()->m_strDescription);
}
+4 -2
View File
@@ -1,5 +1,7 @@
#pragma once
class lcElidableToolButton;
class lcFindReplaceWidget : public QWidget
{
Q_OBJECT
@@ -12,9 +14,9 @@ protected slots:
void FindTextEdited(const QString& Text);
void FindActivated(int Index);
void ReplaceColorIndexChanged(int ColorIndex);
void ReplaceActivated(int Index);
void ReplaceButtonClicked();
protected:
QComboBox* mFindPartComboBox = nullptr;
QComboBox* mReplacePartComboBox = nullptr;
lcElidableToolButton* mReplacePartButton = nullptr;
};
+2 -2
View File
@@ -31,7 +31,7 @@ static void APIENTRY lcGLDebugCallback(GLenum Source, GLenum Type, GLuint Id, GL
void lcInitializeGLExtensions(const QOpenGLContext* Context)
{
const QOpenGLFunctions* Functions = Context->functions();
QOpenGLFunctions* Functions = Context->functions();
#if !defined(QT_NO_DEBUG) && defined(GL_ARB_debug_output)
if (Context->hasExtension("GL_KHR_debug"))
@@ -53,7 +53,7 @@ void lcInitializeGLExtensions(const QOpenGLContext* Context)
if (Context->hasExtension("GL_EXT_texture_filter_anisotropic"))
{
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gMaxAnisotropy);
Functions->glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gMaxAnisotropy);
gSupportsAnisotropic = true;
}
+3 -14
View File
@@ -3,6 +3,7 @@
#ifdef __cplusplus
#define QT_NO_DEPRECATED_WARNINGS
#include <QtGlobal>
#include <QtWidgets>
#include <QtConcurrent>
@@ -48,15 +49,8 @@ class QPrinter;
#define LC_ARRAY_COUNT(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))
#define LC_ARRAY_SIZE_CHECK(a,s) static_assert(LC_ARRAY_COUNT(a) == static_cast<int>(s), QT_STRINGIFY(a) " size mismatch.")
#if !defined(EGL_VERSION_1_0) && !defined(GL_ES_VERSION_2_0) && !defined(GL_ES_VERSION_3_0) && !defined(QT_OPENGL_ES)
#ifdef Q_OS_MACOS
#define LC_FIXED_FUNCTION 0
#else
#define LC_FIXED_FUNCTION 1
#endif
#else
#if defined(EGL_VERSION_1_0) || defined(GL_ES_VERSION_2_0) || defined(GL_ES_VERSION_3_0) || defined(QT_OPENGL_ES)
#define LC_OPENGLES 1
#define LC_FIXED_FUNCTION 0
#endif
// Old defines and declarations.
@@ -66,12 +60,6 @@ class QPrinter;
typedef quint32 lcStep;
#define LC_STEP_MAX 0xffffffff
#ifdef Q_OS_WIN
char* strcasestr(const char *s, const char *find);
#else
char* strupr(char* string);
#endif
// Version number.
#define LC_VERSION_MAJOR 25
#define LC_VERSION_MINOR 9
@@ -88,6 +76,7 @@ class lcLight;
enum class lcLightType;
enum class lcLightAreaShape;
class lcGroup;
class lcModelAction;
class PieceInfo;
typedef std::map<const PieceInfo*, std::map<int, int>> lcPartsList;
struct lcModelPartsEntry;
+11 -2
View File
@@ -3,8 +3,8 @@
#include "ui_lc_groupdialog.h"
#include "group.h"
lcGroupDialog::lcGroupDialog(QWidget* Parent, const QString& Name)
: QDialog(Parent), ui(new Ui::lcGroupDialog)
lcGroupDialog::lcGroupDialog(QWidget* Parent, const QString& Name, const std::vector<std::unique_ptr<lcGroup>>& Groups)
: QDialog(Parent), mGroups(Groups), ui(new Ui::lcGroupDialog)
{
ui->setupUi(this);
@@ -26,6 +26,15 @@ void lcGroupDialog::accept()
return;
}
for (const std::unique_ptr<lcGroup>& Group : mGroups)
{
if (Group->mName == Name)
{
QMessageBox::information(this, "LeoCAD", tr("A group with this name already exists."));
return;
}
}
mName = Name;
QDialog::accept();
+2 -1
View File
@@ -11,7 +11,7 @@ class lcGroupDialog : public QDialog
Q_OBJECT
public:
explicit lcGroupDialog(QWidget* Parent, const QString& Name);
explicit lcGroupDialog(QWidget* Parent, const QString& Name, const std::vector<std::unique_ptr<lcGroup>>& Groups);
~lcGroupDialog();
QString mName;
@@ -20,5 +20,6 @@ public slots:
void accept() override;
private:
const std::vector<std::unique_ptr<lcGroup>>& mGroups;
Ui::lcGroupDialog *ui;
};
+7 -3
View File
@@ -81,7 +81,7 @@ void lcInstructionsPageWidget::StepSettingsChanged(lcModel* Model, lcStep Step)
{
QGraphicsScene* Scene = scene();
QList<QGraphicsItem*> Items = Scene->items();
const QList<QGraphicsItem*> Items = Scene->items();
for (QGraphicsItem* Item : Items)
{
@@ -291,7 +291,7 @@ lcInstructionsPropertiesWidget::lcInstructionsPropertiesWidget(QWidget* Parent,
QWidget* CentralWidget = new QWidget(this);
setWidget(CentralWidget);
setWindowTitle(tr("Properties"));
QGridLayout* Layout = new QGridLayout(CentralWidget);
Layout->setContentsMargins(0, 0, 0, 0);
@@ -343,7 +343,7 @@ void lcInstructionsPropertiesWidget::AddColorProperty(lcInstructionsPropertyType
Pixmap.fill(Color);
ColorButton->setIcon(Pixmap);
};
UpdateButton();
connect(ColorButton, &QToolButton::clicked, [this, Type, UpdateButton]()
@@ -649,7 +649,11 @@ void lcInstructionsDialog::Print(QPrinter* Printer)
for (int PageCopy = 0; PageCopy < PageCopies; PageCopy++)
{
if (Printer->printerState() == QPrinter::Aborted || Printer->printerState() == QPrinter::Error)
{
delete Scene;
return;
}
if (!FirstPage)
Printer->newPage();
+2 -2
View File
@@ -40,7 +40,7 @@ void lcLadderWidget::Show()
if (Position.y() + HalfHeight > Desktop.bottom())
Position.setY(Desktop.bottom() - HalfHeight);
move(Position);
mLastMousePositionX = mapFromGlobal(QCursor::pos()).x();
@@ -97,7 +97,7 @@ void lcLadderWidget::UpdateMousePosition()
{
int CellHeight = height() / static_cast<int>(mSteps.size());
int CurrentStep = MousePosition.y() / CellHeight;
if (CurrentStep != mCurrentStep)
{
mCurrentStep = CurrentStep;
+20 -21
View File
@@ -16,8 +16,7 @@
#include "project.h"
#include "lc_profile.h"
#include "lc_meshloader.h"
#include <ctype.h>
#include <locale.h>
#include "lc_string.h"
#include <zlib.h>
#include <QtConcurrent>
@@ -129,8 +128,8 @@ void lcPiecesLibrary::RenamePiece(PieceInfo* Info, const char* NewName)
Info->m_strDescription[sizeof(Info->m_strDescription) - 1] = 0;
char PieceName[LC_PIECE_NAME_LEN];
strcpy(PieceName, Info->mFileName);
strupr(PieceName);
lcstrcpy(PieceName, Info->mFileName);
lcstrupr(PieceName);
mPieces[PieceName] = Info;
}
@@ -237,7 +236,7 @@ lcTexture* lcPiecesLibrary::FindTexture(const char* TextureName, Project* Curren
if (TextureFile.isFile())
{
lcTexture* Texture = lcLoadTexture(TextureFile.absoluteFilePath(), LC_TEXTURE_WRAPU | LC_TEXTURE_WRAPV);
lcTexture* Texture = lcLoadTexture(TextureFile.absoluteFilePath(), LC_TEXTURE_MIPMAPS);
if (Texture)
{
@@ -426,7 +425,7 @@ bool lcPiecesLibrary::OpenArchive(std::unique_ptr<lcFile> File, lcZipFileType Zi
if ((ZipFileType == lcZipFileType::Official && !memcmp(Name, "LDRAW/PARTS/TEXTURES/", 21)) ||
(ZipFileType == lcZipFileType::Unofficial && !memcmp(Name, "PARTS/TEXTURES/", 15)))
{
lcTexture* Texture = new lcTexture();
lcTexture* Texture = new lcTexture(LC_TEXTURE_MIPMAPS);
mTextures.push_back(Texture);
*Dst = 0;
@@ -653,7 +652,7 @@ bool lcPiecesLibrary::OpenDirectory(const QDir& LibraryDir, bool ShowProgress)
continue;
*Dst = 0;
lcTexture* Texture = new lcTexture();
lcTexture* Texture = new lcTexture(LC_TEXTURE_MIPMAPS);
mTextures.push_back(Texture);
strncpy(Texture->mName, Name, sizeof(Texture->mName));
@@ -761,7 +760,7 @@ void lcPiecesLibrary::ReadDirectoryDescriptions(const QFileInfoList (&FileLists)
if (FileTime == CachedFileTime)
{
strcpy(Info->m_strDescription, Description);
lcstrcpy(Info->m_strDescription, Description);
return;
}
}
@@ -769,7 +768,7 @@ void lcPiecesLibrary::ReadDirectoryDescriptions(const QFileInfoList (&FileLists)
if (!PieceFile.Open(QIODevice::ReadOnly) || !PieceFile.ReadLine(Line, sizeof(Line)))
{
strcpy(Info->m_strDescription, "Unknown");
lcstrcpy(Info->m_strDescription, "Unknown");
return;
}
@@ -1283,14 +1282,14 @@ bool lcPiecesLibrary::LoadPieceData(PieceInfo* Info)
char FileName[LC_MAXPATH];
lcDiskFile PieceFile;
sprintf(FileName, "parts/%s", Info->mFileName);
snprintf(FileName, sizeof(FileName), "parts/%s", Info->mFileName);
PieceFile.SetFileName(mLibraryDir.absoluteFilePath(QLatin1String(FileName)));
if (PieceFile.Open(QIODevice::ReadOnly))
Loaded = MeshLoader.LoadMesh(PieceFile, LC_MESHDATA_SHARED);
if (mHasUnofficial && !Loaded)
{
sprintf(FileName, "unofficial/parts/%s", Info->mFileName);
snprintf(FileName, sizeof(FileName), "unofficial/parts/%s", Info->mFileName);
PieceFile.SetFileName(mLibraryDir.absoluteFilePath(QLatin1String(FileName)));
if (PieceFile.Open(QIODevice::ReadOnly))
Loaded = MeshLoader.LoadMesh(PieceFile, LC_MESHDATA_SHARED);
@@ -1357,13 +1356,13 @@ void lcPiecesLibrary::GetPieceFile(const char* PieceName, std::function<void(lcF
char FileName[LC_MAXPATH];
bool Found = false;
sprintf(FileName, "parts/%s", Info->mFileName);
snprintf(FileName, sizeof(FileName), "parts/%s", Info->mFileName);
IncludeFile.SetFileName(mLibraryDir.absoluteFilePath(QLatin1String(FileName)));
Found = IncludeFile.Open(QIODevice::ReadOnly);
if (mHasUnofficial && !Found)
{
sprintf(FileName, "unofficial/parts/%s", Info->mFileName);
snprintf(FileName, sizeof(FileName), "unofficial/parts/%s", Info->mFileName);
IncludeFile.SetFileName(mLibraryDir.absoluteFilePath(QLatin1String(FileName)));
Found = IncludeFile.Open(QIODevice::ReadOnly);
}
@@ -1383,7 +1382,7 @@ void lcPiecesLibrary::GetPieceFile(const char* PieceName, std::function<void(lcF
auto LoadIncludeFile = [&IncludeFile, PieceName, this](const char* Folder, lcZipFileType ZipFileType)
{
char IncludeFileName[LC_MAXPATH];
sprintf(IncludeFileName, Folder, PieceName);
snprintf(IncludeFileName, sizeof(IncludeFileName), Folder, PieceName);
return mZipFiles[static_cast<int>(ZipFileType)]->ExtractFile(IncludeFileName, IncludeFile);
};
@@ -1532,11 +1531,11 @@ bool lcPiecesLibrary::LoadTexture(lcTexture* Texture)
{
lcMemFile TextureFile;
sprintf(FileName, "ldraw/parts/textures/%s.png", Texture->mName);
snprintf(FileName, sizeof(FileName), "ldraw/parts/textures/%s.png", Texture->mName);
if (!mZipFiles[static_cast<int>(lcZipFileType::Official)]->ExtractFile(FileName, TextureFile))
{
sprintf(FileName, "parts/textures/%s.png", Texture->mName);
snprintf(FileName, sizeof(FileName), "parts/textures/%s.png", Texture->mName);
if (!mZipFiles[static_cast<int>(lcZipFileType::Unofficial)] || !mZipFiles[static_cast<int>(lcZipFileType::Unofficial)]->ExtractFile(FileName, TextureFile))
return false;
@@ -1668,9 +1667,9 @@ bool lcPiecesLibrary::LoadPrimitive(lcLibraryPrimitive* Primitive)
if (strncmp(Primitive->mName, "8/", 2)) // todo: this is currently the only place that uses mName so use mFileName instead. this should also be done for the loose file libraries.
{
char Name[LC_PIECE_NAME_LEN];
strcpy(Name, "8/");
strcat(Name, Primitive->mName);
strupr(Name);
lcstrcpy(Name, "8/");
lcstrcat(Name, Primitive->mName);
lcstrupr(Name);
LowPrimitive = FindPrimitive(Name); // todo: low primitives don't work with studlogo, because the low stud gets added as shared
}
@@ -1769,9 +1768,9 @@ void lcPiecesLibrary::GetCategoryEntries(const char* CategoryKeywords, bool Grou
// Find the parent of this patterned piece.
char ParentName[LC_PIECE_NAME_LEN];
strcpy(ParentName, Info->mFileName);
lcstrcpy(ParentName, Info->mFileName);
*strchr(ParentName, 'P') = '\0';
strcat(ParentName, ".dat");
lcstrcat(ParentName, ".dat");
Parent = FindPiece(ParentName, nullptr, false, false);
+3 -3
View File
@@ -135,7 +135,7 @@ bool lcImportLXFMLFile(const QString& FileData, std::vector<lcPiece*>& Pieces, s
WorldMatrix[2][0] = BoneElements[6].toFloat();
WorldMatrix[2][1] = BoneElements[7].toFloat();
WorldMatrix[2][2] = BoneElements[8].toFloat();
WorldMatrix[3][3] = 0.0f;
WorldMatrix[2][3] = 0.0f;
WorldMatrix[3][0] = BoneElements[9].toFloat();
WorldMatrix[3][1] = BoneElements[10].toFloat();
WorldMatrix[3][2] = BoneElements[11].toFloat();
@@ -179,13 +179,13 @@ bool lcImportLXFMLFile(const QString& FileData, std::vector<lcPiece*>& Pieces, s
lcVector4(-WorldMatrix[2][0], WorldMatrix[2][1], WorldMatrix[2][2], 0.0f), lcVector4(WorldMatrix[3][0] * 25.0f, -WorldMatrix[3][1] * 25.0f, -WorldMatrix[3][2] * 25.0f, 1.0f));
lcPiece* Piece = new lcPiece(nullptr);
Piece->SetPieceInfo(Info, QString(), false);
Piece->SetPieceInfo(Info, QString(), false, true);
Piece->Initialize(lcMatrix44LDrawToLeoCAD(WorldMatrix), 1);
Piece->SetColorCode(ColorCode);
Pieces.push_back(Piece);
NumBrickPieces++;
}
if (NumBrickPieces > 1)
{
std::vector<lcPiece*> Group;
+19 -18
View File
@@ -24,6 +24,7 @@
#include "lc_library.h"
#include "lc_colors.h"
#include "lc_previewwidget.h"
#include "lc_modelaction.h"
#if LC_ENABLE_GAMEPAD
#include <QtGamepad/QGamepad>
@@ -2232,7 +2233,7 @@ void lcMainWindow::ProjectionMenuAboutToShow()
if (ActiveView)
{
if (ActiveView->GetCamera()->IsOrtho())
if (ActiveView->GetCamera()->GetProjection() == lcCameraProjection::Orthographic)
mActions[LC_VIEW_PROJECTION_ORTHO]->setChecked(true);
else
mActions[LC_VIEW_PROJECTION_PERSPECTIVE]->setChecked(true);
@@ -2784,12 +2785,12 @@ void lcMainWindow::HandleCommand(lcCommandId CommandId)
case LC_EDIT_SELECT_NONE:
if (ActiveModel)
ActiveModel->ClearSelection(true);
ActiveModel->ClearSelection();
break;
case LC_EDIT_SELECT_INVERT:
if (ActiveModel)
ActiveModel->InvertSelection();
ActiveModel->InvertPieceSelection();
break;
case LC_EDIT_SELECT_BY_NAME:
@@ -2885,12 +2886,12 @@ void lcMainWindow::HandleCommand(lcCommandId CommandId)
case LC_VIEW_PROJECTION_PERSPECTIVE:
if (ActiveView)
ActiveView->SetProjection(false);
ActiveView->SetCameraProjection(lcCameraProjection::Perspective);
break;
case LC_VIEW_PROJECTION_ORTHO:
if (ActiveView)
ActiveView->SetProjection(true);
ActiveView->SetCameraProjection(lcCameraProjection::Orthographic);
break;
case LC_VIEW_TOGGLE_VIEW_SPHERE:
@@ -2936,7 +2937,7 @@ void lcMainWindow::HandleCommand(lcCommandId CommandId)
case LC_PIECE_REMOVE_KEY_FRAMES:
if (ActiveModel)
ActiveModel->RemoveSelectedPiecesKeyFrames();
ActiveModel->RemoveSelectedObjectsKeyFrames();
break;
case LC_PIECE_CONTROL_POINT_INSERT:
@@ -2966,62 +2967,62 @@ void lcMainWindow::HandleCommand(lcCommandId CommandId)
case LC_PIECE_MOVE_PLUSX:
if (ActiveModel)
ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(lcMax(GetMoveXYSnap(), 0.1f), 0.0f, 0.0f)), true, false, true, true, true);
ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(lcMax(GetMoveXYSnap(), 0.1f), 0.0f, 0.0f)), true, false, true, true, lcModelActionEditMerge::KeyboardMove);
break;
case LC_PIECE_MOVE_MINUSX:
if (ActiveModel)
ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(-lcMax(GetMoveXYSnap(), 0.1f), 0.0f, 0.0f)), true, false, true, true, true);
ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(-lcMax(GetMoveXYSnap(), 0.1f), 0.0f, 0.0f)), true, false, true, true, lcModelActionEditMerge::KeyboardMove);
break;
case LC_PIECE_MOVE_PLUSY:
if (ActiveModel)
ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, lcMax(GetMoveXYSnap(), 0.1f), 0.0f)), true, false, true, true, true);
ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, lcMax(GetMoveXYSnap(), 0.1f), 0.0f)), true, false, true, true, lcModelActionEditMerge::KeyboardMove);
break;
case LC_PIECE_MOVE_MINUSY:
if (ActiveModel)
ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, -lcMax(GetMoveXYSnap(), 0.1f), 0.0f)), true, false, true, true, true);
ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, -lcMax(GetMoveXYSnap(), 0.1f), 0.0f)), true, false, true, true, lcModelActionEditMerge::KeyboardMove);
break;
case LC_PIECE_MOVE_PLUSZ:
if (ActiveModel)
ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, 0.0f, lcMax(GetMoveZSnap(), 0.1f))), true, false, true, true, true);
ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, 0.0f, lcMax(GetMoveZSnap(), 0.1f))), true, false, true, true, lcModelActionEditMerge::KeyboardMove);
break;
case LC_PIECE_MOVE_MINUSZ:
if (ActiveModel)
ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, 0.0f, -lcMax(GetMoveZSnap(), 0.1f))), true, false, true, true, true);
ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, 0.0f, -lcMax(GetMoveZSnap(), 0.1f))), true, false, true, true, lcModelActionEditMerge::KeyboardMove);
break;
case LC_PIECE_ROTATE_PLUSX:
if (ActiveModel)
ActiveModel->RotateSelectedObjects(ActiveView->GetMoveDirection(lcVector3(lcMax(GetAngleSnap(), 1.0f), 0.0f, 0.0f)), true, false, true, true);
ActiveModel->RotateSelectedObjects(ActiveView->GetMoveDirection(lcVector3(lcMax(GetAngleSnap(), 1.0f), 0.0f, 0.0f)), true, false, true, lcModelActionEditMerge::KeyboardRotate);
break;
case LC_PIECE_ROTATE_MINUSX:
if (ActiveModel)
ActiveModel->RotateSelectedObjects(ActiveView->GetMoveDirection(-lcVector3(lcMax(GetAngleSnap(), 1.0f), 0.0f, 0.0f)), true, false, true, true);
ActiveModel->RotateSelectedObjects(ActiveView->GetMoveDirection(lcVector3(-lcMax(GetAngleSnap(), 1.0f), 0.0f, 0.0f)), true, false, true, lcModelActionEditMerge::KeyboardRotate);
break;
case LC_PIECE_ROTATE_PLUSY:
if (ActiveModel)
ActiveModel->RotateSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, lcMax(GetAngleSnap(), 1.0f), 0.0f)), true, false, true, true);
ActiveModel->RotateSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, lcMax(GetAngleSnap(), 1.0f), 0.0f)), true, false, true, lcModelActionEditMerge::KeyboardRotate);
break;
case LC_PIECE_ROTATE_MINUSY:
if (ActiveModel)
ActiveModel->RotateSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, -lcMax(GetAngleSnap(), 1.0f), 0.0f)), true, false, true, true);
ActiveModel->RotateSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, -lcMax(GetAngleSnap(), 1.0f), 0.0f)), true, false, true, lcModelActionEditMerge::KeyboardRotate);
break;
case LC_PIECE_ROTATE_PLUSZ:
if (ActiveModel)
ActiveModel->RotateSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, 0.0f, lcMax(GetAngleSnap(), 1.0f))), true, false, true, true);
ActiveModel->RotateSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, 0.0f, lcMax(GetAngleSnap(), 1.0f))), true, false, true, lcModelActionEditMerge::KeyboardRotate);
break;
case LC_PIECE_ROTATE_MINUSZ:
if (ActiveModel)
ActiveModel->RotateSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, 0.0f, -lcMax(GetAngleSnap(), 1.0f))), true, false, true, true);
ActiveModel->RotateSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, 0.0f, -lcMax(GetAngleSnap(), 1.0f))), true, false, true, lcModelActionEditMerge::KeyboardRotate);
break;
case LC_PIECE_MINIFIG_WIZARD:
+30 -1
View File
@@ -464,6 +464,11 @@ inline bool operator==(const lcMatrix33& a, const lcMatrix33& b)
return a.r[0] == b.r[0] && a.r[1] == b.r[1] && a.r[2] == b.r[2];
}
inline bool operator==(const lcMatrix44& a, const lcMatrix44& b)
{
return a.r[0] == b.r[0] && a.r[1] == b.r[1] && a.r[2] == b.r[2] && a.r[3] == b.r[3];
}
#ifndef QT_NO_DEBUG
inline QDebug operator<<(QDebug Debug, const lcVector2& v)
@@ -521,12 +526,36 @@ inline QDataStream& operator<<(QDataStream& Stream, const lcVector4& v)
return Stream;
}
inline QDataStream& operator >> (QDataStream& Stream, lcVector4& v)
inline QDataStream& operator>>(QDataStream& Stream, lcVector4& v)
{
Stream >> v.x >> v.y >> v.z >> v.w;
return Stream;
}
inline QDataStream& operator<<(QDataStream& Stream, const lcMatrix33& m)
{
Stream << m[0] << m[1] << m[2];
return Stream;
}
inline QDataStream& operator>>(QDataStream& Stream, lcMatrix33& m)
{
Stream >> m[0] >> m[1] >> m[2];
return Stream;
}
inline QDataStream& operator<<(QDataStream& Stream, const lcMatrix44& m)
{
Stream << m[0] << m[1] << m[2] << m[3];
return Stream;
}
inline QDataStream& operator>>(QDataStream& Stream, lcMatrix44& m)
{
Stream >> m[0] >> m[1] >> m[2] >> m[3];
return Stream;
}
inline void lcVector3::Normalize()
{
const float InvLength = 1.0f / Length();
+14 -12
View File
@@ -284,9 +284,9 @@ void lcMesh::ExportPOVRay(lcFile& File, const char* MeshName, const char** Color
}
if (NumSections > 1)
sprintf(Line, "#declare lc_%s = union {\n", MeshName);
snprintf(Line, sizeof(Line), "#declare lc_%s = union {\n", MeshName);
else
sprintf(Line, "#declare lc_%s = mesh {\n", MeshName);
snprintf(Line, sizeof(Line), "#declare lc_%s = mesh {\n", MeshName);
File.WriteLine(Line);
for (int SectionIdx = 0; SectionIdx < mLods[LC_MESH_LOD_HIGH].NumSections; SectionIdx++)
@@ -297,7 +297,7 @@ void lcMesh::ExportPOVRay(lcFile& File, const char* MeshName, const char** Color
{
const lcVertex* Verts = GetVertexData();
const IndexType* Indices = (IndexType*)mIndexData + Section->IndexOffset / sizeof(IndexType);
if (NumSections > 1)
File.WriteLine(" mesh {\n");
@@ -310,8 +310,8 @@ void lcMesh::ExportPOVRay(lcFile& File, const char* MeshName, const char** Color
const lcVector3 n2 = lcUnpackNormal(Verts[Indices[Idx + 1]].Normal);
const lcVector3 n3 = lcUnpackNormal(Verts[Indices[Idx + 2]].Normal);
sprintf(Line, " smooth_triangle { <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g> }\n",
-v1.y, -v1.x, v1.z, -n1.y, -n1.x, n1.z, -v2.y, -v2.x, v2.z, -n2.y, -n2.x, n2.z, -v3.y, -v3.x, v3.z, -n3.y, -n3.x, n3.z);
snprintf(Line, sizeof(Line), " smooth_triangle { <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g> }\n",
-v1.y, -v1.x, v1.z, -n1.y, -n1.x, n1.z, -v2.y, -v2.x, v2.z, -n2.y, -n2.x, n2.z, -v3.y, -v3.x, v3.z, -n3.y, -n3.x, n3.z);
File.WriteLine(Line);
}
}
@@ -332,8 +332,8 @@ void lcMesh::ExportPOVRay(lcFile& File, const char* MeshName, const char** Color
const lcVector3 n2 = lcUnpackNormal(Verts[Indices[Idx + 1]].Normal);
const lcVector3 n3 = lcUnpackNormal(Verts[Indices[Idx + 2]].Normal);
sprintf(Line, " smooth_triangle { <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g> }\n",
-v1.y, -v1.x, v1.z, -n1.y, -n1.x, n1.z, -v2.y, -v2.x, v2.z, -n2.y, -n2.x, n2.z, -v3.y, -v3.x, v3.z, -n3.y, -n3.x, n3.z);
snprintf(Line, sizeof(Line), " smooth_triangle { <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g> }\n",
-v1.y, -v1.x, v1.z, -n1.y, -n1.x, n1.z, -v2.y, -v2.x, v2.z, -n2.y, -n2.x, n2.z, -v3.y, -v3.x, v3.z, -n3.y, -n3.x, n3.z);
File.WriteLine(Line);
}
}
@@ -342,7 +342,7 @@ void lcMesh::ExportPOVRay(lcFile& File, const char* MeshName, const char** Color
if (Section->ColorIndex != gDefaultColor)
{
sprintf(Line, " material { texture { %s normal { bumps 0.1 scale 2 } } }", ColorTable[Section->ColorIndex]);
snprintf(Line, sizeof(Line), " material { texture { %s normal { bumps 0.1 scale 2 } } }", ColorTable[Section->ColorIndex]);
File.WriteLine(Line);
}
@@ -376,9 +376,9 @@ void lcMesh::ExportWavefrontIndices(lcFile& File, int DefaultColorIndex, int Ver
IndexType* Indices = (IndexType*)mIndexData + Section->IndexOffset / sizeof(IndexType);
if (Section->ColorIndex == gDefaultColor)
sprintf(Line, "usemtl %s\n", gColorList[DefaultColorIndex].SafeName);
snprintf(Line, sizeof(Line), "usemtl %s\n", gColorList[DefaultColorIndex].SafeName);
else
sprintf(Line, "usemtl %s\n", gColorList[Section->ColorIndex].SafeName);
snprintf(Line, sizeof(Line), "usemtl %s\n", gColorList[Section->ColorIndex].SafeName);
File.WriteLine(Line);
for (int Idx = 0; Idx < Section->NumIndices; Idx += 3)
@@ -388,8 +388,10 @@ void lcMesh::ExportWavefrontIndices(lcFile& File, int DefaultColorIndex, int Ver
const long int idx3 = Indices[Idx + 2] + VertexOffset;
if (idx1 != idx2 && idx1 != idx3 && idx2 != idx3)
sprintf(Line, "f %ld//%ld %ld//%ld %ld//%ld\n", idx1, idx1, idx2, idx2, idx3, idx3);
File.WriteLine(Line);
{
snprintf(Line, sizeof(Line), "f %ld//%ld %ld//%ld %ld//%ld\n", idx1, idx1, idx2, idx2, idx3, idx3);
File.WriteLine(Line);
}
}
}
+18 -7
View File
@@ -5,6 +5,7 @@
#include "lc_library.h"
#include "lc_application.h"
#include "lc_texture.h"
#include "lc_string.h"
static void lcCheckTexCoordsWrap(const lcVector4& Plane2, const lcVector3 (&Positions)[3], lcVector2 (&TexCoords)[3])
{
@@ -350,7 +351,7 @@ void lcMeshLoaderTypeData::AddMeshData(const lcMeshLoaderTypeData& Data, const l
for (const lcMeshLoaderConditionalVertex& DataVertex : Data.mConditionalVertices)
{
lcVector3 Position[4];
Position[0] = lcMul31(DataVertex.Position[0], Transform);
Position[1] = lcMul31(DataVertex.Position[1], Transform);
Position[2] = lcMul31(DataVertex.Position[2], Transform);
@@ -368,7 +369,12 @@ void lcMeshLoaderTypeData::AddMeshData(const lcMeshLoaderTypeData& Data, const l
if (SrcSection->mMaterial->Type != lcMeshLoaderMaterialType::Solid)
{
lcMeshLoaderTextureMap DstTextureMap = *TextureMap;
lcMeshLoaderTextureParams DstTextureMap;
if (TextureMap)
DstTextureMap = *TextureMap;
else
DstTextureMap = *SrcSection->mMaterial;
for (lcVector3& Point : DstTextureMap.Points)
Point = lcMul31(Point, Transform);
@@ -451,7 +457,12 @@ void lcMeshLoaderTypeData::AddMeshDataNoDuplicateCheck(const lcMeshLoaderTypeDat
if (SrcSection->mMaterial->Type != lcMeshLoaderMaterialType::Solid)
{
lcMeshLoaderTextureMap DstTextureMap = *TextureMap;
lcMeshLoaderTextureParams DstTextureMap;
if (TextureMap)
DstTextureMap = *TextureMap;
else
DstTextureMap = *SrcSection->mMaterial;
for (lcVector3& Point : DstTextureMap.Points)
Point = lcMul31(Point, Transform);
@@ -552,7 +563,7 @@ lcMeshLoaderMaterial* lcLibraryMeshData::GetMaterial(quint32 ColorCode)
return Material;
}
lcMeshLoaderMaterial* lcLibraryMeshData::GetTexturedMaterial(quint32 ColorCode, const lcMeshLoaderTextureMap& TextureMap)
lcMeshLoaderMaterial* lcLibraryMeshData::GetTexturedMaterial(quint32 ColorCode, const lcMeshLoaderTextureParams& TextureMap)
{
for (const std::unique_ptr<lcMeshLoaderMaterial>& Material : mMaterials)
{
@@ -589,7 +600,7 @@ lcMeshLoaderMaterial* lcLibraryMeshData::GetTexturedMaterial(quint32 ColorCode,
Material->Points[2] = TextureMap.Points[2];
Material->Angles[0] = TextureMap.Angles[0];
Material->Angles[1] = TextureMap.Angles[1];
strcpy(Material->Name, TextureMap.Name);
lcstrcpy(Material->Name, TextureMap.Name);
return Material;
}
@@ -831,7 +842,7 @@ lcMesh* lcLibraryMeshData::CreateMesh()
FinalSection.PrimitiveType = Section->mPrimitiveType;
FinalSection.Color = Section->mMaterial->Color;
strcpy(FinalSection.Name, Section->mMaterial->Name);
lcstrcpy(FinalSection.Name, Section->mMaterial->Name);
};
for (const std::unique_ptr<lcMeshLoaderSection>& Section : mData[LC_MESHDATA_SHARED].mSections)
@@ -1370,7 +1381,7 @@ bool lcMeshLoader::ReadMeshData(lcFile& File, const lcMatrix44& CurrentTransform
sscanf(Line, "%d %i %f %f %f %f %f %f %f %f %f %f %f %f %s", &LineType, &Dummy, &fm[0], &fm[1], &fm[2], &fm[3], &fm[4], &fm[5], &fm[6], &fm[7], &fm[8], &fm[9], &fm[10], &fm[11], OriginalFileName);
char FileName[LC_MAXPATH];
strcpy(FileName, OriginalFileName);
lcstrcpy(FileName, OriginalFileName);
char* Ch;
for (Ch = FileName; *Ch; Ch++)
+9 -21
View File
@@ -41,13 +41,17 @@ enum class lcMeshLoaderMaterialType
Spherical
};
struct lcMeshLoaderMaterial
struct lcMeshLoaderTextureParams
{
lcMeshLoaderMaterialType Type = lcMeshLoaderMaterialType::Solid;
quint32 Color = 16;
lcVector3 Points[3] = {};
float Angles[2] = {};
char Name[256] = {};
char Name[LC_MAXPATH] = {};
};
struct lcMeshLoaderMaterial : public lcMeshLoaderTextureParams
{
quint32 Color = 16;
};
class lcMeshLoaderSection
@@ -71,24 +75,8 @@ struct lcMeshLoaderFinalSection
char Name[256];
};
struct lcMeshLoaderTextureMap
struct lcMeshLoaderTextureMap : public lcMeshLoaderTextureParams
{
union lcTextureMapParams
{
lcTextureMapParams()
{
}
struct lcTextureMapSphericalParams
{
} Spherical;
} Params;
lcMeshLoaderMaterialType Type;
lcVector3 Points[3];
float Angles[2];
char Name[LC_MAXPATH];
bool Fallback = false;
bool Next = false;
};
@@ -182,7 +170,7 @@ public:
void AddMeshDataNoDuplicateCheck(const lcLibraryMeshData& Data, const lcMatrix44& Transform, quint32 CurrentColorCode, bool InvertWinding, bool InvertNormals, lcMeshLoaderTextureMap* TextureMap, lcMeshDataType OverrideDestIndex);
lcMeshLoaderMaterial* GetMaterial(quint32 ColorCode);
lcMeshLoaderMaterial* GetTexturedMaterial(quint32 ColorCode, const lcMeshLoaderTextureMap& TextureMap);
lcMeshLoaderMaterial* GetTexturedMaterial(quint32 ColorCode, const lcMeshLoaderTextureParams& TextureMap);
std::array<lcMeshLoaderTypeData, LC_NUM_MESHDATA_TYPES> mData;
bool mHasTextures;
+22 -11
View File
@@ -4,7 +4,6 @@
#include "lc_viewwidget.h"
#include "lc_colorpicker.h"
#include "minifig.h"
#include "lc_application.h"
#include "pieceinf.h"
#include "lc_library.h"
#include "lc_view.h"
@@ -135,6 +134,14 @@ lcMinifigDialog::lcMinifigDialog(QWidget* Parent)
mMinifigWizard->Calculate();
mView->GetCamera()->SetViewpoint(lcVector3(0.0f, -270.0f, 90.0f));
mView->ZoomExtents();
ui->buttonBox->button(QDialogButtonBox::StandardButton::Ok)->setFocus();
connect(ui->TemplateComboBox, &QComboBox::currentTextChanged, this, &lcMinifigDialog::TemplateComboBoxCurrentTextChanged);
connect(ui->TemplateSaveButton, &QPushButton::clicked, this, &lcMinifigDialog::TemplateSaveButtonClicked);
connect(ui->TemplateDeleteButton, &QPushButton::clicked, this, &lcMinifigDialog::TemplateDeleteButtonClicked);
connect(ui->TemplateImportButton, &QPushButton::clicked, this, &lcMinifigDialog::TemplateImportButtonClicked);
connect(ui->TemplateExportButton, &QPushButton::clicked, this, &lcMinifigDialog::TemplateExportButtonClicked);
}
lcMinifigDialog::~lcMinifigDialog()
@@ -175,7 +182,7 @@ void lcMinifigDialog::UpdateTemplateCombo()
ui->TemplateComboBox->setCurrentText(CurrentName);
}
void lcMinifigDialog::on_TemplateComboBox_currentIndexChanged(const QString& TemplateName)
void lcMinifigDialog::TemplateComboBoxCurrentTextChanged(const QString& TemplateName)
{
const auto& Templates = mMinifigWizard->GetTemplates();
const auto& Position = Templates.find(TemplateName);
@@ -189,7 +196,7 @@ void lcMinifigDialog::on_TemplateComboBox_currentIndexChanged(const QString& Tem
UpdateTemplateCombo();
const lcMinifigTemplate& Template = Position->second;
mView->MakeCurrent();
mMinifigWizard->LoadTemplate(TemplateName);
@@ -234,7 +241,7 @@ void lcMinifigDialog::on_TemplateComboBox_currentIndexChanged(const QString& Tem
mView->Redraw();
}
void lcMinifigDialog::on_TemplateSaveButton_clicked()
void lcMinifigDialog::TemplateSaveButtonClicked()
{
QString CurrentName = mCurrentTemplateName;
bool Ok;
@@ -280,7 +287,7 @@ void lcMinifigDialog::on_TemplateSaveButton_clicked()
UpdateTemplateCombo();
}
void lcMinifigDialog::on_TemplateDeleteButton_clicked()
void lcMinifigDialog::TemplateDeleteButtonClicked()
{
if (mCurrentTemplateName.isEmpty() || mCurrentTemplateName == MinifigWizard::GetDefaultTemplateName())
return;
@@ -299,7 +306,7 @@ void lcMinifigDialog::on_TemplateDeleteButton_clicked()
UpdateTemplateCombo();
}
void lcMinifigDialog::on_TemplateImportButton_clicked()
void lcMinifigDialog::TemplateImportButtonClicked()
{
QString FileName = QFileDialog::getOpenFileName(this, tr("Import Templates"), "", tr("Minifig Template Files (*.minifig);;All Files (*.*)"));
@@ -320,7 +327,7 @@ void lcMinifigDialog::on_TemplateImportButton_clicked()
UpdateTemplateCombo();
}
void lcMinifigDialog::on_TemplateExportButton_clicked()
void lcMinifigDialog::TemplateExportButtonClicked()
{
QString FileName = QFileDialog::getSaveFileName(this, tr("Export Templates"), "", tr("Minifig Template Files (*.minifig);;All Files (*.*)"));
@@ -359,7 +366,7 @@ void lcMinifigDialog::PieceButtonClicked()
if (Search == mPieceButtons.end())
return;
int ItemIndex = std::distance(mPieceButtons.begin(), Search);
int ItemIndex = static_cast<int>(std::distance(mPieceButtons.begin(), Search));
PieceInfo* CurrentInfo = mMinifigWizard->mMinifig.Parts[ItemIndex];
QPoint Position = PieceButton->mapToGlobal(PieceButton->rect().bottomLeft());
@@ -380,7 +387,7 @@ void lcMinifigDialog::PieceButtonClicked()
return;
PieceInfo* NewPiece = Result.value();
SetCurrentTemplateModified();
UpdateTemplateCombo();
@@ -411,7 +418,9 @@ void lcMinifigDialog::ColorChanged(int Index)
SetCurrentTemplateModified();
UpdateTemplateCombo();
mMinifigWizard->SetColorIndex(std::distance(mColorPickers.begin(), Search), Index);
int ItemIndex = static_cast<int>(std::distance(mColorPickers.begin(), Search));
mMinifigWizard->SetColorIndex(ItemIndex, Index);
mView->Redraw();
}
@@ -425,6 +434,8 @@ void lcMinifigDialog::AngleChanged(double Value)
SetCurrentTemplateModified();
UpdateTemplateCombo();
mMinifigWizard->SetAngle(std::distance(mSpinBoxes.begin(), Search), Value);
int ItemIndex = static_cast<int>(std::distance(mSpinBoxes.begin(), Search));
mMinifigWizard->SetAngle(ItemIndex, Value);
mView->Redraw();
}
+6 -6
View File
@@ -16,16 +16,16 @@ class lcMinifigDialog : public QDialog
public:
explicit lcMinifigDialog(QWidget* Parent);
~lcMinifigDialog();
virtual ~lcMinifigDialog();
MinifigWizard* mMinifigWizard;
protected slots:
void on_TemplateComboBox_currentIndexChanged(const QString& TemplateName);
void on_TemplateSaveButton_clicked();
void on_TemplateDeleteButton_clicked();
void on_TemplateImportButton_clicked();
void on_TemplateExportButton_clicked();
void TemplateComboBoxCurrentTextChanged(const QString& TemplateName);
void TemplateSaveButtonClicked();
void TemplateDeleteButtonClicked();
void TemplateImportButtonClicked();
void TemplateExportButtonClicked();
void PieceButtonClicked();
void ColorChanged(int Index);
void AngleChanged(double Value);
+1203 -814
View File
File diff suppressed because it is too large Load Diff
+71 -51
View File
@@ -4,6 +4,13 @@
#include "lc_commands.h"
enum class lcObjectPropertyId;
enum class lcCameraProjection;
struct lcModelHistoryState;
class lcModelAction;
class lcModelActionSelection;
class lcModelActionObjectEdit;
class lcModelActionProperties;
enum class lcModelActionEditMerge;
#define LC_SEL_NO_PIECES 0x0001 // No pieces in model
#define LC_SEL_PIECE 0x0002 // At least 1 piece selected
@@ -65,6 +72,11 @@ public:
return true;
}
bool operator!=(const lcModelProperties& Properties) const
{
return !(*this == Properties);
}
void SaveLDraw(QTextStream& Stream) const;
bool ParseLDrawHeader(QString Line, bool FirstLine);
void ParseLDrawLine(QTextStream& Stream);
@@ -99,7 +111,7 @@ public:
struct lcModelHistoryEntry
{
QByteArray File;
std::vector<std::unique_ptr<lcModelAction>> ModelActions;
QString Description;
};
@@ -119,16 +131,14 @@ public:
return mProject;
}
bool IsModified() const
{
return mSavedHistory != mUndoHistory[0];
}
bool IsActive() const
{
return mActive;
}
bool IsModified() const;
void SetSaved();
bool GetPieceWorldMatrix(lcPiece* Piece, lcMatrix44& ParentWorldMatrix) const;
bool IncludesModel(const lcModel* Model) const;
void CreatePieceInfo(Project* Project);
@@ -216,11 +226,16 @@ public:
void InsertStep(lcStep Step);
void RemoveStep(lcStep Step);
template<typename StateType, typename ObjectType>
void LoadObjectHistoryState(const std::vector<StateType>& ObjectStates, std::vector<std::unique_ptr<ObjectType>>& Objects);
void LoadHistoryState(const lcModelHistoryState& HistoryState);
void SetModelProperties(const lcModelProperties& ModelProperties);
lcPiece* AddPiece(PieceInfo* Info, quint32 Section);
void DeleteAllCameras();
void AddPiece(std::unique_ptr<lcPiece> Piece, size_t PieceIndex);
void DeleteSelectedObjects();
void ResetSelectedPiecesPivotPoint();
void RemoveSelectedPiecesKeyFrames();
void RemoveSelectedObjectsKeyFrames();
void InsertControlPoint();
void RemoveFocusedControlPoint();
void FocusNextTrainTrack();
@@ -249,16 +264,7 @@ public:
bool LoadLDD(const QString& FileData);
bool LoadInventory(const QByteArray& Inventory);
int SplitMPD(QIODevice& Device);
void Merge(lcModel* Other);
void SetSaved()
{
if (mUndoHistory.empty())
SaveCheckpoint(QString());
if (!mIsPreview)
mSavedHistory = mUndoHistory[0];
}
void Merge(std::unique_ptr<lcModel> Other);
void SetMinifig(const lcMinifig& Minifig);
void SetPreviewPieceInfo(PieceInfo* Info, int ColorIndex);
@@ -307,18 +313,14 @@ public:
void GetPartsListForStep(lcStep Step, int DefaultColorIndex, lcPartsList& PartsList, bool Cumulative) const;
void GetModelParts(const lcMatrix44& WorldMatrix, int DefaultColorIndex, std::vector<lcModelPartsEntry>& ModelParts) const;
void GetSelectionInformation(int* Flags, std::vector<lcObject*>& Selection, lcObject** Focus) const;
std::vector<lcObject*> GetSelectionModePieces(const lcPiece* SelectedPiece) const;
void FocusOrDeselectObject(const lcObjectSection& ObjectSection);
void ClearSelection(bool UpdateInterface);
void ClearSelectionAndSetFocus(lcObject* Object, quint32 Section, bool EnableSelectionMode);
void ClearSelectionAndSetFocus(const lcObjectSection& ObjectSection, bool EnableSelectionMode);
void SetSelectionAndFocus(const std::vector<lcObject*>& Selection, lcObject* Focus, quint32 Section, bool EnableSelectionMode);
void AddToSelection(const std::vector<lcObject*>& Objects, bool EnableSelectionMode, bool UpdateInterface);
void RemoveFromSelection(const std::vector<lcObject*>& Objects);
void RemoveFromSelection(const lcObjectSection& ObjectSection);
void ClearSelection();
void SetSelectionAndFocus(const std::vector<lcObject*>& Selection, lcObject* Focus, quint32 Section, lcSelectionMode SelectionMode);
void FocusOrDeselectObject(lcObject* Object, uint32_t Section, lcSelectionMode SelectionMode);
void SelectAllPieces();
void InvertSelection();
void InvertPieceSelection();
void AddToSelection(const std::vector<lcObject*>& Objects);
void RemoveFromSelection(const std::vector<lcObject*>& Objects);
void HideSelectedPieces();
void HideUnselectedPieces();
@@ -339,12 +341,11 @@ public:
return mMouseToolDistance;
}
void BeginMouseTool();
void EndMouseTool(lcTool Tool, bool Accept);
void BeginMouseTool(lcTool Tool, lcView* View);
void EndMouseTool(lcTool Tool, lcView* View, bool Accept);
void InsertPieceToolClicked(const std::vector<lcInsertPieceInfo>& PieceInfoTransforms);
void InsertCameraToolClicked(const lcVector3& Position);
void InsertLightToolClicked(const lcVector3& Position, lcLightType LightType);
void BeginCameraTool(const lcVector3& Position, const lcVector3& Target);
void UpdateCameraTool(const lcVector3& Position);
void UpdateMoveTool(const lcVector3& Distance, bool AllowRelative, bool AlternateButtonDrag);
void UpdateFreeMoveTool(lcPiece* MousePiece, const lcMatrix44& StartTransform, const lcMatrix44& NewTransform, bool IsConnection, bool AlternateButtonDrag);
void UpdateRotateTool(const lcVector3& Angles, bool AlternateButtonDrag);
@@ -356,33 +357,30 @@ public:
void UpdatePanTool(lcCamera* Camera, const lcVector3& Distance);
void UpdateOrbitTool(lcCamera* Camera, float MouseX, float MouseY);
void UpdateRollTool(lcCamera* Camera, float Mouse);
void ZoomRegionToolClicked(lcCamera* Camera, float AspectRatio, const lcVector3& Position, const lcVector3& TargetPosition, const lcVector3* Corners);
void ZoomRegionToolClicked(lcView* View, float AspectRatio, const lcVector3& Position, const lcVector3& TargetPosition, const lcVector3* Corners);
void LookAt(lcCamera* Camera);
void MoveCamera(lcCamera* Camera, const lcVector3& Direction);
void ZoomExtents(lcCamera* Camera, float Aspect, const lcMatrix44& WorldMatrix);
void Zoom(lcCamera* Camera, float Amount);
void MoveSelectedObjects(const lcVector3& Distance, bool AllowRelative, bool AlternateButtonDrag, bool Update, bool Checkpoint, bool FirstMove)
void MoveSelectedObjects(const lcVector3& Distance, bool AllowRelative, bool AlternateButtonDrag, bool Checkpoint, bool FirstMove, lcModelActionEditMerge ModelActionEditMerge)
{
MoveSelectedObjects(Distance, Distance, AllowRelative, AlternateButtonDrag, Update, Checkpoint, FirstMove);
MoveSelectedObjects(Distance, Distance, AllowRelative, AlternateButtonDrag, Checkpoint, FirstMove, ModelActionEditMerge);
}
void MoveSelectedObjects(const lcVector3& PieceDistance, const lcVector3& ObjectDistance, bool AllowRelative, bool AlternateButtonDrag, bool Update, bool Checkpoint, bool FirstMove);
void RotateSelectedObjects(const lcVector3& Angles, bool Relative, bool RotatePivotPoint, bool Update, bool Checkpoint);
void ScaleSelectedPieces(const float Scale, bool Update, bool Checkpoint);
void MoveSelectedObjects(const lcVector3& PieceDistance, const lcVector3& ObjectDistance, bool AllowRelative, bool AlternateButtonDrag, bool Checkpoint, bool FirstMove, lcModelActionEditMerge ModelActionEditMerge);
void RotateSelectedObjects(const lcVector3& Angles, bool Relative, bool RotatePivotPoint, bool Checkpoint, lcModelActionEditMerge ModelActionEditMerge);
void ScaleSelectedPieces(const float Scale);
void TransformSelectedObjects(lcTransformType TransformType, const lcVector3& Transform);
void SetObjectsKeyFrame(const std::vector<lcObject*>& Objects, lcObjectPropertyId PropertyId, bool KeyFrame);
void SetSelectedPiecesColorIndex(int ColorIndex);
void SetSelectedPiecesStepShow(lcStep Step);
void SetSelectedPiecesStepHide(lcStep Step);
void SetObjectsProperty(const std::vector<lcObject*>& Objects, lcObjectPropertyId PropertyId, QVariant Value, bool AddUndo);
void SetObjectsProperty(const std::vector<lcObject*>& Objects, lcObjectPropertyId PropertyId, QVariant Value);
void EndPropertyEdit(lcObjectPropertyId PropertyId, bool Accept);
void SetCameraOrthographic(lcCamera* Camera, bool Ortho);
void SetCameraFOV(lcCamera* Camera, float FOV, bool Checkpoint);
void SetCameraZNear(lcCamera* Camera, float ZNear, bool Checkpoint);
void SetCameraZFar(lcCamera* Camera, float ZFar, bool Checkpoint);
void SetCameraProjection(lcCamera* Camera, lcCameraProjection CameraProjection);
void ShowPropertiesDialog();
void ShowSelectByNameDialog();
@@ -392,18 +390,39 @@ public:
protected:
void DeleteModel();
void DeleteHistory();
void SaveCheckpoint(const QString& Description);
void LoadCheckPoint(lcModelHistoryEntry* CheckPoint);
void RecordSelectionAction(std::function<void()> Callback);
void RecordClearSelectionAction();
void RecordSetFocusAction(lcObject* FocusObject, uint32_t FocusSection, lcSelectionMode SelectionMode);
void RecordSetSelectionAndFocusAction(const std::vector<lcObject*>& Objects, lcObject* FocusObject, uint32_t FocusSection, lcSelectionMode SelectionMode);
void RecordSelectAllPiecesAction();
void RecordInvertPieceSelectionAction();
void RecordAddToSelectionAction(const std::vector<lcObject*>& Objects);
void RecordRemoveFromSelectionAction(const std::vector<lcObject*>& Objects);
void BeginObjectEditAction(lcModelActionEditMerge ModelActionEditMerge);
void EndObjectEditAction();
void RecordModelPropertiesAction(const lcModelProperties& ModelProperties);
void RunActionSequence(const std::vector<std::unique_ptr<lcModelAction>>& ActionSequence, bool Apply);
void BeginActionSequence();
void EndActionSequence(const QString& Description);
void DiscardActionSequence();
void RevertActionSequence();
void RemoveFirstUndoIfUnchanged();
const lcModelHistoryEntry* GetFirstUndoChange() const;
QString GetGroupName(const QString& Prefix);
void RemoveEmptyGroups();
bool RemoveSelectedObjects();
void RemoveCameraFromViews(lcCamera* Camera);
std::vector<lcObject*> GetSelectionModePieces(lcSelectionMode SelectionMode, const lcPiece* SelectedPiece) const;
void DeselectAllObjects();
void SetFocusedObject(lcObject* FocusObject, uint32_t FocusSection, lcSelectionMode SelectionMode);
void SetObjectsSelected(const std::vector<lcObject*>& Objects, bool Selected);
void SelectGroup(lcGroup* TopGroup, bool Select);
void AddPiece(lcPiece* Piece);
void InsertPiece(lcPiece* Piece, size_t Index);
size_t AddPiece(lcPiece* Piece);
lcPOVRayOptions mPOVRayOptions;
lcModelProperties mProperties;
@@ -422,9 +441,10 @@ protected:
std::vector<std::unique_ptr<lcGroup>> mGroups;
QStringList mFileLines;
lcModelHistoryEntry* mSavedHistory;
std::vector<lcModelHistoryEntry*> mUndoHistory;
std::vector<lcModelHistoryEntry*> mRedoHistory;
std::vector<std::unique_ptr<lcModelAction>> mActionSequence;
const lcModelHistoryEntry* mSavedHistory = nullptr;
std::vector<std::unique_ptr<lcModelHistoryEntry>> mUndoHistory;
std::vector<std::unique_ptr<lcModelHistoryEntry>> mRedoHistory;
Q_DECLARE_TR_FUNCTIONS(lcModel);
};
+260
View File
@@ -0,0 +1,260 @@
#include "lc_global.h"
#include "lc_modelaction.h"
#include "lc_model.h"
#include "piece.h"
#include "camera.h"
#include "light.h"
#include "group.h"
void lcModelActionSelection::SaveStartState(const lcModel* Model)
{
SaveState(mStartState, Model);
}
void lcModelActionSelection::SaveEndState(const lcModel* Model)
{
SaveState(mEndState, Model);
}
void lcModelActionSelection::LoadStartState(lcModel* Model) const
{
LoadState(mStartState, Model);
}
void lcModelActionSelection::LoadEndState(lcModel* Model) const
{
LoadState(mEndState, Model);
}
bool lcModelActionSelection::StateChanged() const
{
return mStartState != mEndState;
}
void lcModelActionSelection::SaveState(lcModelActionSelectionState& State, const lcModel* Model)
{
State = lcModelActionSelectionState();
const std::vector<std::unique_ptr<lcPiece>>& Pieces = Model->GetPieces();
State.PieceSelection.resize(Pieces.size(), false);
for (size_t PieceIndex = 0; PieceIndex < Pieces.size(); PieceIndex++)
{
lcPiece* Piece = Pieces[PieceIndex].get();
if (!Piece->IsSelected())
continue;
State.PieceSelection[PieceIndex] = true;
if (Piece->IsFocused())
{
State.FocusIndex = PieceIndex;
State.FocusSection = Piece->GetFocusSection();
State.FocusObjectType = lcObjectType::Piece;
}
}
const std::vector<std::unique_ptr<lcCamera>>& Cameras = Model->GetCameras();
State.CameraSelection.resize(Cameras.size(), false);
for (size_t CameraIndex = 0; CameraIndex < Cameras.size(); CameraIndex++)
{
lcCamera* Camera = Cameras[CameraIndex].get();
if (!Camera->IsSelected())
continue;
State.CameraSelection[CameraIndex] = true;
if (Camera->IsFocused())
{
State.FocusIndex = CameraIndex;
State.FocusSection = Camera->GetFocusSection();
State.FocusObjectType = lcObjectType::Camera;
}
}
const std::vector<std::unique_ptr<lcLight>>& Lights = Model->GetLights();
State.LightSelection.resize(Lights.size(), false);
for (size_t LightIndex = 0; LightIndex < Lights.size(); LightIndex++)
{
lcLight* Light = Lights[LightIndex].get();
if (!Light->IsSelected())
continue;
State.LightSelection[LightIndex] = true;
if (Light->IsFocused())
{
State.FocusIndex = LightIndex;
State.FocusSection = Light->GetFocusSection();
State.FocusObjectType = lcObjectType::Light;
}
}
}
void lcModelActionSelection::LoadState(const lcModelActionSelectionState& State, lcModel* Model)
{
const std::vector<std::unique_ptr<lcPiece>>& Pieces = Model->GetPieces();
const std::vector<std::unique_ptr<lcCamera>>& Cameras = Model->GetCameras();
const std::vector<std::unique_ptr<lcLight>>& Lights = Model->GetLights();
if (Pieces.size() != State.PieceSelection.size() || Cameras.size() != State.CameraSelection.size() || Lights.size() != State.LightSelection.size())
return;
for (size_t PieceIndex = 0; PieceIndex < Pieces.size(); PieceIndex++)
{
lcPiece* Piece = Pieces[PieceIndex].get();
Piece->SetSelected(State.PieceSelection[PieceIndex]);
if (State.FocusObjectType == lcObjectType::Piece && State.FocusIndex == PieceIndex)
Piece->SetFocused(State.FocusSection, true);
else
Piece->SetFocused(State.FocusSection, false);
}
for (size_t CameraIndex = 0; CameraIndex < Cameras.size(); CameraIndex++)
{
lcCamera* Camera = Cameras[CameraIndex].get();
Camera->SetSelected(State.CameraSelection[CameraIndex]);
if (State.FocusObjectType == lcObjectType::Camera && State.FocusIndex == CameraIndex)
Camera->SetFocused(State.FocusSection, true);
else
Camera->SetFocused(State.FocusSection, false);
}
for (size_t LightIndex = 0; LightIndex < Lights.size(); LightIndex++)
{
lcLight* Light = Lights[LightIndex].get();
Light->SetSelected(State.LightSelection[LightIndex]);
if (State.FocusObjectType == lcObjectType::Light && State.FocusIndex == LightIndex)
Light->SetFocused(State.FocusSection, true);
else
Light->SetFocused(State.FocusSection, false);
}
}
bool operator!=(const lcModelHistoryState& a, const lcModelHistoryState& b)
{
return a.Groups != b.Groups || a.Pieces != b.Pieces || a.Cameras != b.Cameras || a.Lights != b.Lights;
}
lcModelActionObjectEdit::lcModelActionObjectEdit(lcModelActionEditMerge ModelActionEditMerge)
: mMerge(ModelActionEditMerge)
{
}
lcModelActionObjectEdit::~lcModelActionObjectEdit()
{
}
void lcModelActionObjectEdit::SaveState(lcModelHistoryState& State, const lcModel* Model)
{
const std::vector<std::unique_ptr<lcGroup>>& Groups = Model->GetGroups();
for (const std::unique_ptr<lcGroup>& Group : Groups)
State.Groups.emplace_back(Group->GetHistoryState(Model));
const std::vector<std::unique_ptr<lcPiece>>& Pieces = Model->GetPieces();
for (const std::unique_ptr<lcPiece>& Piece : Pieces)
State.Pieces.emplace_back(Piece->GetHistoryState(Model));
const std::vector<std::unique_ptr<lcCamera>>& Cameras = Model->GetCameras();
for (const std::unique_ptr<lcCamera>& Camera : Cameras)
State.Cameras.emplace_back(Camera->GetHistoryState(Model));
const std::vector<std::unique_ptr<lcLight>>& Lights = Model->GetLights();
for (const std::unique_ptr<lcLight>& Light : Lights)
State.Lights.emplace_back(Light->GetHistoryState(Model));
}
void lcModelActionObjectEdit::LoadState(const lcModelHistoryState& State, lcModel* Model)
{
Model->LoadHistoryState(State);
}
void lcModelActionObjectEdit::SaveStartState(const lcModel* Model)
{
SaveState(mStartState, Model);
}
void lcModelActionObjectEdit::SaveEndState(const lcModel* Model)
{
SaveState(mEndState, Model);
}
void lcModelActionObjectEdit::LoadStartState(lcModel* Model) const
{
LoadState(mStartState, Model);
}
void lcModelActionObjectEdit::LoadEndState(lcModel* Model) const
{
LoadState(mEndState, Model);
}
bool lcModelActionObjectEdit::StateChanged() const
{
return mStartState != mEndState;
}
bool lcModelActionObjectEdit::CanMergeWith(const lcModelAction* Other) const
{
const lcModelActionObjectEdit* OtherModelActionEdit = dynamic_cast<const lcModelActionObjectEdit*>(Other);
return OtherModelActionEdit && mMerge != lcModelActionEditMerge::None && mMerge == OtherModelActionEdit->mMerge;
}
void lcModelActionObjectEdit::MergeWith(lcModelAction* Other)
{
lcModelActionObjectEdit* OtherModelActionEdit = dynamic_cast<lcModelActionObjectEdit*>(Other);
if (OtherModelActionEdit)
mEndState = std::move(OtherModelActionEdit->mEndState);
}
void lcModelActionProperties::SaveStartState(const lcModel* Model)
{
SaveState(mStartState, Model);
}
void lcModelActionProperties::SaveEndState(const lcModel* Model)
{
SaveState(mEndState, Model);
}
void lcModelActionProperties::LoadStartState(lcModel* Model) const
{
LoadState(mStartState, Model);
}
void lcModelActionProperties::LoadEndState(lcModel* Model) const
{
LoadState(mEndState, Model);
}
bool lcModelActionProperties::StateChanged() const
{
return mStartState != mEndState;
}
void lcModelActionProperties::SaveState(lcModelProperties& State, const lcModel* Model)
{
State = Model->GetProperties();
}
void lcModelActionProperties::LoadState(const lcModelProperties& State, lcModel* Model)
{
Model->SetModelProperties(State);
}
+138
View File
@@ -0,0 +1,138 @@
#pragma once
#include "lc_model.h"
enum class lcObjectType;
enum class lcSelectionMode;
class lcModelAction
{
public:
lcModelAction() = default;
virtual ~lcModelAction() = default;
virtual void SaveStartState(const lcModel* Model) = 0;
virtual void SaveEndState(const lcModel* Model) = 0;
virtual void LoadStartState(lcModel* Model) const = 0;
virtual void LoadEndState(lcModel* Model) const = 0;
virtual bool StateChanged() const = 0;
virtual bool CanMergeWith(const lcModelAction* Other) const
{
Q_UNUSED(Other);
return false;
}
virtual void MergeWith(lcModelAction* Other)
{
Q_UNUSED(Other);
}
};
struct lcModelActionSelectionState
{
std::vector<bool> PieceSelection;
std::vector<bool> CameraSelection;
std::vector<bool> LightSelection;
size_t FocusIndex = SIZE_MAX;
uint32_t FocusSection = ~0U;
lcObjectType FocusObjectType = static_cast<lcObjectType>(~0);
bool operator!=(const lcModelActionSelectionState& Other) const
{
return PieceSelection != Other.PieceSelection || CameraSelection != Other.CameraSelection || LightSelection != Other.LightSelection ||
FocusIndex != Other.FocusIndex || FocusSection != Other.FocusSection || FocusObjectType != Other.FocusObjectType;
}
};
class lcModelActionSelection : public lcModelAction
{
public:
lcModelActionSelection() = default;
virtual ~lcModelActionSelection() = default;
void SaveStartState(const lcModel* Model) override;
void SaveEndState(const lcModel* Model) override;
void LoadStartState(lcModel* Model) const override;
void LoadEndState(lcModel* Model) const override;
bool StateChanged() const override;
protected:
static void SaveState(lcModelActionSelectionState& State, const lcModel* Model);
static void LoadState(const lcModelActionSelectionState& State, lcModel* Model);
lcModelActionSelectionState mStartState;
lcModelActionSelectionState mEndState;
};
struct lcGroupHistoryState;
struct lcPieceHistoryState;
struct lcCameraHistoryState;
struct lcLightHistoryState;
struct lcModelHistoryState
{
std::vector<lcGroupHistoryState> Groups;
std::vector<lcPieceHistoryState> Pieces;
std::vector<lcCameraHistoryState> Cameras;
std::vector<lcLightHistoryState> Lights;
};
bool operator!=(const lcModelHistoryState& a, const lcModelHistoryState& b);
enum class lcModelActionEditMerge
{
None,
KeyboardMove,
KeyboardRotate,
KeyboardZoom,
KeyboardMoveCamera,
PropertiesMove,
PropertiesRotate,
PropertiesEdit = 0x40000000
};
class lcModelActionObjectEdit: public lcModelAction
{
public:
lcModelActionObjectEdit(lcModelActionEditMerge ModelActionEditMerge);
virtual ~lcModelActionObjectEdit();
void SaveStartState(const lcModel* Model) override;
void SaveEndState(const lcModel* Model) override;
void LoadStartState(lcModel* Model) const override;
void LoadEndState(lcModel* Model) const override;
bool StateChanged() const override;
bool CanMergeWith(const lcModelAction* Other) const override;
void MergeWith(lcModelAction* Other) override;
protected:
static void SaveState(lcModelHistoryState& State, const lcModel* Model);
static void LoadState(const lcModelHistoryState& State, lcModel* Model);
lcModelHistoryState mStartState;
lcModelHistoryState mEndState;
lcModelActionEditMerge mMerge;
};
class lcModelActionProperties : public lcModelAction
{
public:
lcModelActionProperties() = default;
virtual ~lcModelActionProperties() = default;
void SaveStartState(const lcModel* Model) override;
void SaveEndState(const lcModel* Model) override;
void LoadStartState(lcModel* Model) const override;
void LoadEndState(lcModel* Model) const override;
bool StateChanged() const override;
protected:
static void SaveState(lcModelProperties& State, const lcModel* Model);
static void LoadState(const lcModelProperties& State, lcModel* Model);
lcModelProperties mStartState;
lcModelProperties mEndState;
};
+4 -4
View File
@@ -135,7 +135,7 @@ void lcModelListDialog::on_DeleteModel_clicked()
return;
}
QList<QListWidgetItem*> SelectedItems = ui->ModelList->selectedItems();
const QList<QListWidgetItem*> SelectedItems = ui->ModelList->selectedItems();
if (SelectedItems.isEmpty())
{
@@ -165,7 +165,7 @@ void lcModelListDialog::on_DeleteModel_clicked()
void lcModelListDialog::on_RenameModel_clicked()
{
QList<QListWidgetItem*> SelectedItems = ui->ModelList->selectedItems();
const QList<QListWidgetItem*> SelectedItems = ui->ModelList->selectedItems();
if (SelectedItems.isEmpty())
{
@@ -189,7 +189,7 @@ void lcModelListDialog::on_RenameModel_clicked()
void lcModelListDialog::on_ExportModel_clicked()
{
QList<QListWidgetItem*> SelectedItems = ui->ModelList->selectedItems();
const QList<QListWidgetItem*> SelectedItems = ui->ModelList->selectedItems();
if (SelectedItems.isEmpty())
{
@@ -248,7 +248,7 @@ void lcModelListDialog::on_ExportModel_clicked()
void lcModelListDialog::on_DuplicateModel_clicked()
{
QList<QListWidgetItem*> SelectedItems = ui->ModelList->selectedItems();
const QList<QListWidgetItem*> SelectedItems = ui->ModelList->selectedItems();
if (SelectedItems.isEmpty())
{
+3 -1
View File
@@ -7,7 +7,7 @@ enum class lcObjectPropertyId
PieceStepShow,
PieceStepHide,
CameraName,
CameraType,
CameraProjection,
CameraFOV,
CameraNear,
CameraFar,
@@ -67,6 +67,8 @@ template<typename T>
class lcObjectProperty
{
public:
lcObjectProperty() = default;
explicit lcObjectProperty(const T& DefaultValue)
: mValue(DefaultValue)
{
+1 -1
View File
@@ -127,7 +127,7 @@ void lcPartPaletteDialog::on_ImportButton_clicked()
QByteArray Inventory = Dialog.GetSetInventory();
QJsonDocument Document = QJsonDocument::fromJson(Inventory);
QJsonObject Root = Document.object();
QJsonArray Parts = Root["results"].toArray();
const QJsonArray Parts = Root["results"].toArray();
for (const QJsonValue& Part : Parts)
{
+37 -10
View File
@@ -12,6 +12,7 @@
#include "lc_category.h"
#include "lc_traintrack.h"
#include "lc_filter.h"
#include "lc_colors.h"
Q_DECLARE_METATYPE(QList<int>)
@@ -245,10 +246,10 @@ void lcPartSelectionListModel::SetCustomParts(const std::vector<std::pair<PieceI
ReleaseThumbnails();
mParts.clear();
for (auto [Info, Description] : Parts)
for (const auto& [Info, Description] : Parts)
{
lcPartSelectionListModelEntry& Entry = mParts.emplace_back();
Entry.Info = Info;
Entry.Description = Description;
@@ -298,7 +299,7 @@ void lcPartSelectionListModel::SetFilter(const QString& FilterString)
Visible = (mPartDescriptionFilter && Description.contains(FilterRx)) || (mFileNameFilter && QString(Info->mFileName).contains(FilterRx));
}
mListView->setRowHidden((int)PartIdx, !Visible);
}
}
@@ -398,7 +399,7 @@ void lcPartSelectionListModel::RequestThumbnail(int PartIndex)
int ColorIndex = mParts[PartIndex].ColorIndex == -1 ? mColorIndex : mParts[PartIndex].ColorIndex;
auto [ThumbnailId, Thumbnail] = lcGetPiecesLibrary()->GetThumbnailManager()->RequestThumbnail(Info, ColorIndex, mIconSize);
auto [ThumbnailId, Thumbnail] = lcGetPiecesLibrary()->GetThumbnailManager()->RequestThumbnail(Info, ColorIndex, mIconSize, mDeviceScale);
mParts[PartIndex].ThumbnailId = ThumbnailId;
@@ -485,12 +486,13 @@ void lcPartSelectionListModel::SetPartDescriptionFilter(bool Option)
SetFilter(mFilterString);
}
void lcPartSelectionListModel::SetIconSize(int Size)
void lcPartSelectionListModel::SetIconSize(int Size, float DeviceScale)
{
if (Size == mIconSize)
if (Size == mIconSize && DeviceScale == mDeviceScale)
return;
mIconSize = Size;
mDeviceScale = DeviceScale;
beginResetModel();
@@ -660,7 +662,7 @@ void lcPartSelectionListView::SetCurrentPart(PieceInfo* Info)
{
setCurrentIndex(Index);
scrollTo(Index, QAbstractItemView::EnsureVisible);
}
}
}
void lcPartSelectionListView::SetNoIcons()
@@ -769,7 +771,14 @@ void lcPartSelectionListView::SetIconSize(int Size)
{
setIconSize(QSize(Size, Size));
lcSetProfileInt(LC_PROFILE_PARTS_LIST_ICONS, Size);
mListModel->SetIconSize(Size);
#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
float DeviceScale = devicePixelRatioF();
#else
float DeviceScale = devicePixelRatio();
#endif
mListModel->SetIconSize(Size, DeviceScale);
UpdateViewMode();
int Width = Size + 2 * frameWidth() + 6;
@@ -977,7 +986,25 @@ void lcPartSelectionWidget::SetCurrentPart(PieceInfo* Info)
void lcPartSelectionWidget::SetCategory(lcPartCategoryType Type, int Index)
{
mPartsWidget->SetCategory(Type, Index);
for (int Row = 0; Row < mCategoriesWidget->topLevelItemCount(); Row++)
{
QTreeWidgetItem* Item = mCategoriesWidget->topLevelItem(Row);
lcPartCategoryType ItemType = static_cast<lcPartCategoryType>(Item->data(0, static_cast<int>(lcPartCategoryRole::Type)).toInt());
if (ItemType != Type)
continue;
if (Type == lcPartCategoryType::Palette || Type == lcPartCategoryType::Category)
{
int ItemIndex = Item->data(0, static_cast<int>(lcPartCategoryRole::Index)).toInt();
if (ItemIndex != Index)
continue;
}
mCategoriesWidget->setCurrentItem(Item);
break;
}
}
void lcPartSelectionWidget::SetCustomParts(const std::vector<std::pair<PieceInfo*, std::string>>& Parts, int ColorIndex)
@@ -1269,7 +1296,7 @@ void lcPartSelectionWidget::LoadPartPalettes()
lcPartPalette Palette;
Palette.Name = ElementIt.key();
QJsonArray Parts = ElementIt.value().toArray();
const QJsonArray Parts = ElementIt.value().toArray();
for (const QJsonValue& Part : Parts)
Palette.Parts.emplace_back(Part.toString().toStdString());
+2 -1
View File
@@ -159,7 +159,7 @@ public:
void SetCaseSensitiveFilter(bool Option);
void SetFileNameFilter(bool Option);
void SetPartDescriptionFilter(bool Option);
void SetIconSize(int Size);
void SetIconSize(int Size, float DeviceScale);
void SetShowPartNames(bool Show);
protected slots:
@@ -172,6 +172,7 @@ protected:
std::vector<lcPartSelectionListModelEntry> mParts;
lcPartFilterType mPartFilterType;
int mIconSize;
float mDeviceScale = 1.0f;
bool mColorLocked;
int mColorIndex;
bool mShowPartNames;
+1 -1
View File
@@ -122,7 +122,7 @@ bool lcPreview::SetCurrentPiece(const QString& PartType, int ColorCode)
}
else
{
QString ModelPath = QString("%1/%2").arg(QDir::currentPath()).arg(PartType);
QString ModelPath = QString("%1/%2").arg(QDir::currentPath(), PartType);
if (!mLoader->Load(ModelPath, false))
return false;
+2 -2
View File
@@ -72,8 +72,8 @@ static lcProfileEntry gProfileEntries[LC_NUM_PROFILE_KEYS] =
lcProfileEntry("Settings", "GradientColorBottom", LC_RGB(49, 52, 55)), // LC_PROFILE_GRADIENT_COLOR_BOTTOM
lcProfileEntry("Settings", "DrawAxes", 0), // LC_PROFILE_DRAW_AXES
lcProfileEntry("Settings", "DrawAxesLocation", static_cast<int>(lcAxisIconLocation::BottomLeft)), // LC_PROFILE_DRAW_AXES_LOCATION
lcProfileEntry("Settings", "AxesColor", LC_RGBA(0, 0, 0, 255)), // LC_PROFILE_AXES_COLOR
lcProfileEntry("Settings", "TextColor", LC_RGBA(0, 0, 0, 255)), // LC_PROFILE_TEXT_COLOR
lcProfileEntry("Settings", "AxesColor", LC_RGBA(160, 160, 160, 255)), // LC_PROFILE_AXES_COLOR
lcProfileEntry("Settings", "TextColor", LC_RGBA(160, 160, 160, 255)), // LC_PROFILE_TEXT_COLOR
lcProfileEntry("Settings", "MarqueeBorderColor", LC_RGBA(64, 64, 255, 255)), // LC_PROFILE_MARQUEE_BORDER_COLOR
lcProfileEntry("Settings", "MarqueeFillColor", LC_RGBA(64, 64, 255, 64)), // LC_PROFILE_MARQUEE_FILL_COLOR
lcProfileEntry("Settings", "OverlayColor", LC_RGBA(0, 0, 0, 255)), // LC_PROFILE_OVERLAY_COLOR
+38 -47
View File
@@ -12,6 +12,7 @@
#include "lc_colorpicker.h"
#include "lc_qutils.h"
#include "lc_partselectionpopup.h"
#include "lc_modelaction.h"
lcPropertiesWidget::lcPropertiesWidget(QWidget* Parent)
: QWidget(Parent)
@@ -203,7 +204,7 @@ void lcPropertiesWidget::BoolChanged()
return;
const bool Value = Widget->isChecked();
Model->SetObjectsProperty(mFocusObject ? std::vector<lcObject*>{ mFocusObject } : mSelection, PropertyId, Value, true);
Model->SetObjectsProperty(mFocusObject ? std::vector<lcObject*>{ mFocusObject } : mSelection, PropertyId, Value);
}
void lcPropertiesWidget::UpdateBool(lcObjectPropertyId PropertyId)
@@ -280,16 +281,15 @@ void lcPropertiesWidget::FloatEditingCanceled()
Model->EndPropertyEdit(PropertyId, false);
}
void lcPropertiesWidget::FloatChanged(const QString& TextValue)
void lcPropertiesWidget::FloatChanged(double Value)
{
lcDoubleSpinBox* Widget = qobject_cast<lcDoubleSpinBox*>(sender());
lcObjectPropertyId PropertyId = GetEditorWidgetPropertyId(Widget);
float Value = lcParseValueLocalized(TextValue);
ChangeFloatValue(PropertyId, Value, true);
ChangeFloatValue(PropertyId, Value);
}
void lcPropertiesWidget::ChangeFloatValue(lcObjectPropertyId PropertyId, float Value, bool Dragging)
void lcPropertiesWidget::ChangeFloatValue(lcObjectPropertyId PropertyId, float Value)
{
if (PropertyId == lcObjectPropertyId::Count)
return;
@@ -321,13 +321,15 @@ void lcPropertiesWidget::ChangeFloatValue(lcObjectPropertyId PropertyId, float V
lcVector3 Distance = Position - Center;
Model->MoveSelectedObjects(Distance, false, false, true, !Dragging, true);
Model->MoveSelectedObjects(Distance, false, false, true, true, lcModelActionEditMerge::PropertiesMove);
}
else if (PropertyId == lcObjectPropertyId::ObjectRotationX || PropertyId == lcObjectPropertyId::ObjectRotationY || PropertyId == lcObjectPropertyId::ObjectRotationZ)
{
lcVector3 InitialRotation(0.0f, 0.0f, 0.0f);
if (Piece)
if (mLastRotation)
InitialRotation = mLastRotation.value();
else if (Piece)
InitialRotation = lcMatrix44ToEulerAngles(Piece->mModelWorld) * LC_RTOD;
else if (Light)
InitialRotation = lcMatrix44ToEulerAngles(Light->GetWorldMatrix()) * LC_RTOD;
@@ -341,14 +343,11 @@ void lcPropertiesWidget::ChangeFloatValue(lcObjectPropertyId PropertyId, float V
else if (PropertyId == lcObjectPropertyId::ObjectRotationZ)
Rotation[2] = Value;
Model->RotateSelectedObjects(Rotation - InitialRotation, true, false, true, !Dragging);
}
else if (Piece || Light)
{
Model->SetObjectsProperty(mFocusObject ? std::vector<lcObject*>{ mFocusObject } : mSelection, PropertyId, Value, !Dragging);
}
Model->RotateSelectedObjects(Rotation - InitialRotation, true, false, true, lcModelActionEditMerge::PropertiesRotate);
if (PropertyId == lcObjectPropertyId::CameraPositionX || PropertyId == lcObjectPropertyId::CameraPositionY || PropertyId == lcObjectPropertyId::CameraPositionZ)
mLastRotation = Rotation;
}
else if (PropertyId == lcObjectPropertyId::CameraPositionX || PropertyId == lcObjectPropertyId::CameraPositionY || PropertyId == lcObjectPropertyId::CameraPositionZ)
{
quint32 FocusSection = LC_CAMERA_SECTION_INVALID;
lcVector3 Start;
@@ -377,7 +376,7 @@ void lcPropertiesWidget::ChangeFloatValue(lcObjectPropertyId PropertyId, float V
lcVector3 Distance = End - Start;
Model->MoveSelectedObjects(Distance, false, false, true, !Dragging, true);
Model->MoveSelectedObjects(Distance, false, false, true, true, lcModelActionEditMerge::PropertiesMove);
if (Camera)
{
@@ -414,7 +413,7 @@ void lcPropertiesWidget::ChangeFloatValue(lcObjectPropertyId PropertyId, float V
lcVector3 Distance = End - Start;
Model->MoveSelectedObjects(Distance, false, false, true, !Dragging, true);
Model->MoveSelectedObjects(Distance, false, false, true, true, lcModelActionEditMerge::PropertiesMove);
if (Camera)
{
@@ -451,7 +450,7 @@ void lcPropertiesWidget::ChangeFloatValue(lcObjectPropertyId PropertyId, float V
lcVector3 Distance = End - Start;
Model->MoveSelectedObjects(Distance, false, false, true, !Dragging, true);
Model->MoveSelectedObjects(Distance, false, false, true, true, lcModelActionEditMerge::PropertiesMove);
if (Camera)
{
@@ -459,20 +458,9 @@ void lcPropertiesWidget::ChangeFloatValue(lcObjectPropertyId PropertyId, float V
Camera->SetFocused(FocusSection, true);
}
}
else if (Camera)
else
{
if (PropertyId == lcObjectPropertyId::CameraFOV)
{
Model->SetCameraFOV(Camera, Value, !Dragging);
}
else if (PropertyId == lcObjectPropertyId::CameraNear)
{
Model->SetCameraZNear(Camera, Value, !Dragging);
}
else if (PropertyId == lcObjectPropertyId::CameraFar)
{
Model->SetCameraZFar(Camera, Value, !Dragging);
}
Model->SetObjectsProperty(mFocusObject ? std::vector<lcObject*>{ mFocusObject } : mSelection, PropertyId, Value);
}
mDisableUpdates = false;
@@ -481,7 +469,7 @@ void lcPropertiesWidget::ChangeFloatValue(lcObjectPropertyId PropertyId, float V
void lcPropertiesWidget::UpdateFloat(lcObjectPropertyId PropertyId, float Value)
{
lcDoubleSpinBox* Widget = qobject_cast<lcDoubleSpinBox*>(mPropertyWidgets[static_cast<int>(PropertyId)].Editor);
if (Widget)
{
QSignalBlocker Blocker(Widget);
@@ -493,7 +481,7 @@ void lcPropertiesWidget::UpdateFloat(lcObjectPropertyId PropertyId, float Value)
case lcObjectPropertyId::PieceStepShow:
case lcObjectPropertyId::PieceStepHide:
case lcObjectPropertyId::CameraName:
case lcObjectPropertyId::CameraType:
case lcObjectPropertyId::CameraProjection:
break;
case lcObjectPropertyId::CameraFOV:
@@ -580,9 +568,9 @@ void lcPropertiesWidget::AddFloatProperty(lcObjectPropertyId PropertyId, const Q
connect(Widget, &lcDoubleSpinBox::EditingFinished, this, &lcPropertiesWidget::FloatEditingFinished);
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
connect(Widget, QOverload<const QString&>::of(&lcDoubleSpinBox::valueChanged), this, &lcPropertiesWidget::FloatChanged);
connect(Widget, QOverload<double>::of(&lcDoubleSpinBox::valueChanged), this, &lcPropertiesWidget::FloatChanged);
#else
connect(Widget, &lcDoubleSpinBox::textChanged, this, &lcPropertiesWidget::FloatChanged);
connect(Widget, &lcDoubleSpinBox::valueChanged, this, &lcPropertiesWidget::FloatChanged);
#endif
mLayout->addWidget(Widget, mLayoutRow, 2);
@@ -612,7 +600,7 @@ void lcPropertiesWidget::IntegerChanged()
return;
const int Value = LineEdit->text().toInt();
Model->SetObjectsProperty(mFocusObject ? std::vector<lcObject*>{ mFocusObject } : mSelection, PropertyId, Value, true);
Model->SetObjectsProperty(mFocusObject ? std::vector<lcObject*>{ mFocusObject } : mSelection, PropertyId, Value);
}
void lcPropertiesWidget::UpdateInteger(lcObjectPropertyId PropertyId)
@@ -745,7 +733,7 @@ void lcPropertiesWidget::StringChanged()
return;
QString Value = LineEdit->text();
Model->SetObjectsProperty(mFocusObject ? std::vector<lcObject*>{ mFocusObject } : mSelection, PropertyId, Value, true);
Model->SetObjectsProperty(mFocusObject ? std::vector<lcObject*>{ mFocusObject } : mSelection, PropertyId, Value);
}
void lcPropertiesWidget::UpdateString(lcObjectPropertyId PropertyId)
@@ -809,7 +797,7 @@ void lcPropertiesWidget::StringListChanged(int Value)
if (!Model)
return;
Model->SetObjectsProperty(mFocusObject ? std::vector<lcObject*>{ mFocusObject } : mSelection, PropertyId, Value, true);
Model->SetObjectsProperty(mFocusObject ? std::vector<lcObject*>{ mFocusObject } : mSelection, PropertyId, Value);
}
void lcPropertiesWidget::UpdateStringList(lcObjectPropertyId PropertyId)
@@ -911,7 +899,7 @@ void lcPropertiesWidget::ColorChanged(QColor Color)
return;
const lcVector3 FloatColor = lcVector3FromQColor(Color);
Model->SetObjectsProperty(mFocusObject ? std::vector<lcObject*>{ mFocusObject } : mSelection, PropertyId, QVariant::fromValue<lcVector3>(FloatColor), true);
Model->SetObjectsProperty(mFocusObject ? std::vector<lcObject*>{ mFocusObject } : mSelection, PropertyId, QVariant::fromValue<lcVector3>(FloatColor));
}
void lcPropertiesWidget::UpdateColor(lcObjectPropertyId PropertyId)
@@ -977,7 +965,7 @@ void lcPropertiesWidget::PieceColorChanged(int ColorIndex)
if (!Model)
return;
Model->SetObjectsProperty(mFocusObject ? std::vector<lcObject*>{ mFocusObject } : mSelection, PropertyId, ColorIndex, true);
Model->SetObjectsProperty(mFocusObject ? std::vector<lcObject*>{ mFocusObject } : mSelection, PropertyId, ColorIndex);
}
void lcPropertiesWidget::PieceColorButtonClicked()
@@ -1095,7 +1083,7 @@ void lcPropertiesWidget::PieceIdButtonClicked()
PieceInfo* Info = Partial ? nullptr : static_cast<PieceInfo*>(Value.value<void*>());
std::tie(Value, Partial) = GetUpdateValue(lcObjectPropertyId::PieceColor);
int ColorIndex = Partial ? gDefaultColor : Value.toInt();
std::optional<PieceInfo*> Result = lcShowPartSelectionPopup(Info, std::vector<std::pair<PieceInfo*, std::string>>(), ColorIndex, PieceIdButton, PieceIdButton->mapToGlobal(PieceIdButton->rect().bottomLeft()));
@@ -1108,7 +1096,7 @@ void lcPropertiesWidget::PieceIdButtonClicked()
if (!Model || !Info)
return;
Model->SetObjectsProperty(mFocusObject ? std::vector<lcObject*>{ mFocusObject } : mSelection, PropertyId, QVariant::fromValue<void*>(Info), true);
Model->SetObjectsProperty(mFocusObject ? std::vector<lcObject*>{ mFocusObject } : mSelection, PropertyId, QVariant::fromValue<void*>(Info));
}
}
@@ -1159,13 +1147,13 @@ void lcPropertiesWidget::CreateWidgets()
AddCategory(CategoryIndex::Camera, tr("Camera"));
AddStringProperty(lcObjectPropertyId::CameraName, tr("Name"), tr("Camera name"), false);
AddStringListProperty(lcObjectPropertyId::CameraType, tr("Type"), tr("Camera type"), false, lcCamera::GetCameraTypeStrings());
AddStringListProperty(lcObjectPropertyId::CameraProjection, tr("Projection"), tr("Camera projection"), false, lcCamera::GetCameraProjectionStrings());
AddSpacing();
AddFloatProperty(lcObjectPropertyId::CameraFOV, tr("FOV"), tr("Field of view in degrees"), false, 0.1f, 179.9f);
AddFloatProperty(lcObjectPropertyId::CameraNear, tr("Near"), tr("Near clipping distance"), false, 0.001f, FLT_MAX);
AddFloatProperty(lcObjectPropertyId::CameraFar, tr("Far"), tr("Far clipping distance"), false, 0.001f, FLT_MAX);
AddFloatProperty(lcObjectPropertyId::CameraNear, tr("Near"), tr("Near clipping distance"), false, 0.1f, FLT_MAX);
AddFloatProperty(lcObjectPropertyId::CameraFar, tr("Far"), tr("Far clipping distance"), false, 0.1f, FLT_MAX);
AddSpacing();
@@ -1324,8 +1312,10 @@ void lcPropertiesWidget::SetPiece(const std::vector<lcObject*>& Selection, lcObj
lcMatrix33 RelativeRotation;
lcModel* Model = gMainWindow->GetActiveModel();
if (Model)
Model->GetMoveRotateTransform(Position, RelativeRotation);
if (!Model)
return;
Model->GetMoveRotateTransform(Position, RelativeRotation);
UpdateFloat(lcObjectPropertyId::ObjectPositionX, Position[0]);
UpdateFloat(lcObjectPropertyId::ObjectPositionY, Position[1]);
@@ -1412,7 +1402,7 @@ void lcPropertiesWidget::SetCamera(const std::vector<lcObject*>& Selection, lcOb
}
UpdateString(lcObjectPropertyId::CameraName);
UpdateStringList(lcObjectPropertyId::CameraType);
UpdateStringList(lcObjectPropertyId::CameraProjection);
UpdateFloat(lcObjectPropertyId::CameraFOV, FoV);
UpdateFloat(lcObjectPropertyId::CameraNear, ZNear);
@@ -1573,6 +1563,7 @@ void lcPropertiesWidget::Update(const std::vector<lcObject*>& Selection, lcObjec
if (mDisableUpdates)
return;
mLastRotation.reset();
mFocusObject = nullptr;
mSelection.clear();
+4 -2
View File
@@ -1,6 +1,7 @@
#pragma once
#include "lc_objectproperty.h"
#include "lc_math.h"
class lcCollapsibleWidgetButton;
class lcKeyFrameWidget;
@@ -20,7 +21,7 @@ protected slots:
void BoolChanged();
void FloatEditingFinished();
void FloatEditingCanceled();
void FloatChanged(const QString& TextValue);
void FloatChanged(double Value);
void IntegerChanged();
void StepNumberChanged();
void StringChanged();
@@ -114,7 +115,7 @@ protected:
void UpdatePieceColor(lcObjectPropertyId PropertyId);
void UpdatePieceId(lcObjectPropertyId PropertyId);
void ChangeFloatValue(lcObjectPropertyId PropertyId, float Value, bool Dragging);
void ChangeFloatValue(lcObjectPropertyId PropertyId, float Value);
void SetEmpty();
void SetPiece(const std::vector<lcObject*>& Selection, lcObject* Focus);
@@ -131,6 +132,7 @@ protected:
std::vector<lcObject*> mSelection;
lcObject* mFocusObject = nullptr;
bool mDisableUpdates = false;
std::optional<lcVector3> mLastRotation;
std::array<PropertyWidgets, static_cast<int>(lcObjectPropertyId::Count)> mPropertyWidgets = {};
std::array<CategoryWidgets, static_cast<int>(CategoryIndex::Count)> mCategoryWidgets = {};
+1
View File
@@ -6,6 +6,7 @@
#include "lc_library.h"
#include "lc_application.h"
#include "object.h"
#include "lc_colors.h"
lcScene::lcScene()
{
+4 -4
View File
@@ -107,7 +107,7 @@ bool lcKeyboardShortcuts::Load(QTextStream& Stream)
for (QString Line = Stream.readLine(); !Line.isNull(); Line = Stream.readLine())
{
int Equals = Line.indexOf('=');
qsizetype Equals = Line.indexOf('=');
if (Equals == -1)
continue;
@@ -174,7 +174,7 @@ bool lcMouseShortcuts::Save(const QString& FileName)
QTextStream Stream(&File);
for (const QString& Shortcut : Shortcuts)
for (const QString& Shortcut : std::as_const(Shortcuts))
Stream << Shortcut << QLatin1String("\n");
Stream.flush();
@@ -231,7 +231,7 @@ bool lcMouseShortcuts::Load(const QStringList& FullShortcuts)
for (const QString& FullShortcut : FullShortcuts)
{
int Equals = FullShortcut.indexOf('=');
qsizetype Equals = FullShortcut.indexOf('=');
if (Equals == -1)
continue;
@@ -246,7 +246,7 @@ bool lcMouseShortcuts::Load(const QStringList& FullShortcuts)
if (ToolIdx == static_cast<int>(lcTool::Count))
continue;
QStringList Shortcuts = FullShortcut.mid(Equals + 1).split(',');
const QStringList Shortcuts = FullShortcut.mid(Equals + 1).split(',');
bool AddedShortcut = false;
for (const QString& Shortcut : Shortcuts)
+82
View File
@@ -0,0 +1,82 @@
#include "lc_global.h"
#include "lc_string.h"
char* lcstrcasestr(const char* s, const char* find)
{
char c, sc;
if ((c = *find++) != 0)
{
c = tolower((unsigned char)c);
const int len = (int)strlen(find);
do
{
do
{
if ((sc = *s++) == 0)
return (nullptr);
} while ((char)tolower((unsigned char)sc) != c);
} while (qstrnicmp(s, find, len) != 0);
s--;
}
return ((char *)s);
}
char* lcstrupr(char* string)
{
for (char* c = string; *c; c++)
*c = toupper(*c);
return string;
}
size_t lcstrcpy(char* dest, const char* source, size_t size)
{
if (size == 0)
return 0;
for (size_t i = 0; i < size; i++)
{
dest[i] = source[i];
if (source[i] == '\0')
{
return i;
}
}
dest[--size] = '\0';
return size;
}
size_t lcstrcat(char* dest, const char* source, size_t size)
{
char* d = dest;
const char* s = source;
size_t n = size;
size_t dlen;
while (n-- != 0 && *d != '\0')
d++;
dlen = d - dest;
n = size - dlen;
if (n == 0)
return(dlen + strlen(s));
while (*s != '\0')
{
if (n != 1)
{
*d++ = *s;
n--;
}
s++;
}
*d = '\0';
return (dlen + (s - source));
}
+18
View File
@@ -0,0 +1,18 @@
#pragma once
char* lcstrcasestr(const char* s, const char* find);
char* lcstrupr(char* string);
size_t lcstrcpy(char* dest, const char* source, size_t size);
size_t lcstrcat(char* dest, const char* source, size_t size);
template<size_t size>
size_t lcstrcpy(char (&dest)[size], const char* source)
{
return lcstrcpy(dest, source, size);
}
template<size_t size>
size_t lcstrcat(char (&dest)[size], const char* source)
{
return lcstrcat(dest, source, size);
}
+1 -1
View File
@@ -195,6 +195,6 @@ void lcStringCache::DrawStrings(lcContext* Context, const lcMatrix44* Transforms
Context->BindTexture2D(mTexture);
Context->SetColor(0.0f, 0.0f, 0.0f, 1.0f);
Context->DrawPrimitives(GL_TRIANGLES, 0, Strings.size() * 6);
Context->DrawPrimitives(GL_TRIANGLES, 0, static_cast<int>(Strings.size()) * 6);
}
+44 -50
View File
@@ -458,6 +458,7 @@ lcSynthInfoCurved::lcSynthInfoCurved(float Length, float DefaultScale, int NumSe
mCurve = true;
mStart.Transform = lcMatrix44(lcMatrix33(lcVector3(0.0f, 0.0f, 1.0f), lcVector3(1.0f, 0.0f, 0.0f), lcVector3(0.0f, 1.0f, 0.0f)), lcVector3(0.0f, 0.0f, 0.0f));
mMiddle.Length = 0.0f;
mEnd.Transform = lcMatrix44(lcMatrix33(lcVector3(0.0f, 0.0f, 1.0f), lcVector3(1.0f, 0.0f, 0.0f), lcVector3(0.0f, 1.0f, 0.0f)), lcVector3(0.0f, 0.0f, 0.0f));
}
@@ -957,8 +958,8 @@ void lcSynthInfoFlexibleHose::AddParts(lcMemFile& File, lcLibraryMeshData&, cons
lcMatrix33 Transform(lcMul(lcMul(EdgeTransforms[PartIdx], lcMatrix33Scale(lcVector3(1.0f, -1.0f, 1.0f))), lcMatrix33(Sections[SectionIndex])));
lcVector3 Offset = lcMul31(lcVector3(0.0f, -5.0f, 0.0f), Sections[SectionIndex]);
sprintf(Line, "1 16 %f %f %f %f %f %f %f %f %f %f %f %f %s\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0],
Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2], EdgeParts[PartIdx]);
snprintf(Line, sizeof(Line), "1 16 %f %f %f %f %f %f %f %f %f %f %f %f %s\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0],
Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2], EdgeParts[PartIdx]);
File.WriteBuffer(Line, strlen(Line));
}
@@ -977,8 +978,8 @@ void lcSynthInfoFlexibleHose::AddParts(lcMemFile& File, lcLibraryMeshData&, cons
const char* Part = SectionIndex != Sections.size() / 2 ? "754.dat" : "756.dat";
sprintf(Line, "1 16 %f %f %f %f %f %f %f %f %f %f %f %f %s\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0],
Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2], Part);
snprintf(Line, sizeof(Line), "1 16 %f %f %f %f %f %f %f %f %f %f %f %f %s\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0],
Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2], Part);
File.WriteBuffer(Line, strlen(Line));
}
@@ -989,8 +990,8 @@ void lcSynthInfoFlexibleHose::AddParts(lcMemFile& File, lcLibraryMeshData&, cons
lcMatrix33 Transform(lcMul(EdgeTransforms[PartIdx], lcMatrix33(Sections[SectionIndex])));
lcVector3 Offset = lcMul31(lcVector3(0.0f, 5.0f - 2.56f, 0.0f), Sections[SectionIndex]);
sprintf(Line, "1 16 %f %f %f %f %f %f %f %f %f %f %f %f %s\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0],
Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2], EdgeParts[PartIdx]);
snprintf(Line, sizeof(Line), "1 16 %f %f %f %f %f %f %f %f %f %f %f %f %s\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0],
Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2], EdgeParts[PartIdx]);
File.WriteBuffer(Line, strlen(Line));
}
@@ -1082,8 +1083,8 @@ void lcSynthInfoFlexSystemHose::AddParts(lcMemFile& File, lcLibraryMeshData& Mes
lcMatrix33 Transform(lcMul(lcMatrix33Scale(lcVector3(-1.0f, 1.0f, 1.0f)), lcMatrix33(Sections[SectionIndex])));
lcVector3 Offset = lcMul31(lcVector3(0.0f, -1.0f, 0.0f), Sections[SectionIndex]);
sprintf(Line, "1 16 %f %f %f %f %f %f %f %f %f %f %f %f u9053.dat\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0],
Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2]);
snprintf(Line, sizeof(Line), "1 16 %f %f %f %f %f %f %f %f %f %f %f %f u9053.dat\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0],
Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2]);
File.WriteBuffer(Line, strlen(Line));
}
@@ -1093,8 +1094,8 @@ void lcSynthInfoFlexSystemHose::AddParts(lcMemFile& File, lcLibraryMeshData& Mes
lcMatrix33 Transform(lcMul(lcMatrix33Scale(lcVector3(1.0f, -1.0f, 1.0f)), lcMatrix33(Sections[SectionIndex])));
lcVector3 Offset = lcMul31(lcVector3(0.0f, 1.0f, 0.0f), Sections[SectionIndex]);
sprintf(Line, "1 16 %f %f %f %f %f %f %f %f %f %f %f %f u9053.dat\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0],
Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2]);
snprintf(Line, sizeof(Line), "1 16 %f %f %f %f %f %f %f %f %f %f %f %f u9053.dat\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0],
Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2]);
File.WriteBuffer(Line, strlen(Line));
}
@@ -1116,9 +1117,8 @@ void lcSynthInfoPneumaticTube::AddParts(lcMemFile& File, lcLibraryMeshData& Mesh
lcMatrix33 Transform(lcMul(lcMul(EdgeTransform, lcMatrix33Scale(lcVector3(1.0f, 1.0f, 1.0f))), lcMatrix33(Sections[SectionIndex])));
lcVector3 Offset = lcMul31(lcVector3(0.0f, 0.0f, 0.0f), Sections[SectionIndex]);
sprintf(Line, "1 16 %f %f %f %f %f %f %f %f %f %f %f %f %s\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0],
Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2],
mEndPart);
snprintf(Line, sizeof(Line), "1 16 %f %f %f %f %f %f %f %f %f %f %f %f %s\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0],
Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2], mEndPart);
File.WriteBuffer(Line, strlen(Line));
}
@@ -1129,9 +1129,8 @@ void lcSynthInfoPneumaticTube::AddParts(lcMemFile& File, lcLibraryMeshData& Mesh
lcMatrix33 Transform(lcMul(lcMul(EdgeTransform, lcMatrix33Scale(lcVector3(1.0f, -1.0f, 1.0f))), lcMatrix33(Sections[SectionIndex])));
lcVector3 Offset = lcMul31(lcVector3(0.0f, 0.0f, 0.0f), Sections[SectionIndex]);
sprintf(Line, "1 16 %f %f %f %f %f %f %f %f %f %f %f %f %s\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0],
Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2],
mEndPart);
snprintf(Line, sizeof(Line), "1 16 %f %f %f %f %f %f %f %f %f %f %f %f %s\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0],
Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2], mEndPart);
File.WriteBuffer(Line, strlen(Line));
}
@@ -1152,8 +1151,8 @@ void lcSynthInfoRibbedHose::AddParts(lcMemFile& File, lcLibraryMeshData&, const
lcMatrix33 Transform(lcMul(lcMatrix33Scale(lcVector3(1.0f, -1.0f, 1.0f)), lcMatrix33(Sections[SectionIndex])));
lcVector3 Offset = Sections[SectionIndex].GetTranslation();
sprintf(Line, "1 16 %f %f %f %f %f %f %f %f %f %f %f %f 79.dat\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0],
Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2]);
snprintf(Line, sizeof(Line), "1 16 %f %f %f %f %f %f %f %f %f %f %f %f 79.dat\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0],
Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2]);
File.WriteBuffer(Line, strlen(Line));
}
@@ -1162,8 +1161,8 @@ void lcSynthInfoRibbedHose::AddParts(lcMemFile& File, lcLibraryMeshData&, const
{
const lcMatrix44& Transform = Sections[SectionIndex];
sprintf(Line, "1 16 %f %f %f %f %f %f %f %f %f %f %f %f 80.dat\n", Transform[3][0], Transform[3][1], Transform[3][2], Transform[0][0], Transform[1][0], Transform[2][0],
Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2]);
snprintf(Line, sizeof(Line), "1 16 %f %f %f %f %f %f %f %f %f %f %f %f 80.dat\n", Transform[3][0], Transform[3][1], Transform[3][2], Transform[0][0], Transform[1][0], Transform[2][0],
Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2]);
File.WriteBuffer(Line, strlen(Line));
}
@@ -1173,8 +1172,8 @@ void lcSynthInfoRibbedHose::AddParts(lcMemFile& File, lcLibraryMeshData&, const
lcMatrix33 Transform(Sections[SectionIndex]);
lcVector3 Offset = lcMul31(lcVector3(0.0f, -6.25f, 0.0f), Sections[SectionIndex]);
sprintf(Line, "1 16 %f %f %f %f %f %f %f %f %f %f %f %f 79.dat\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0],
Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2]);
snprintf(Line, sizeof(Line), "1 16 %f %f %f %f %f %f %f %f %f %f %f %f 79.dat\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0],
Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2]);
File.WriteBuffer(Line, strlen(Line));
}
@@ -1188,7 +1187,7 @@ void lcSynthInfoFlexibleAxle::AddParts(lcMemFile& File, lcLibraryMeshData& MeshD
char Line[256];
const int NumEdgeParts = 6;
lcMatrix33 EdgeTransforms[6] =
lcMatrix33 EdgeTransforms[6] =
{
lcMatrix33(lcVector3(-1.0f, 0.0f, 0.0f), lcVector3(0.0f, -5.0f, 0.0f), lcVector3(0.0f, 0.0f, 1.0f)),
lcMatrix33(lcVector3( 0.0f, 1.0f, 0.0f), lcVector3(1.0f, 0.0f, 0.0f), lcVector3(0.0f, 0.0f, -1.0f)),
@@ -1209,8 +1208,8 @@ void lcSynthInfoFlexibleAxle::AddParts(lcMemFile& File, lcLibraryMeshData& MeshD
lcMatrix33 Transform(lcMul(lcMul(EdgeTransforms[PartIdx], lcMatrix33Scale(lcVector3(1.0f, -1.0f, 1.0f))), lcMatrix33(Sections[SectionIndex])));
lcVector3 Offset = lcMul31(lcVector3(0.0f, -4.0f * (5 - PartIdx), 0.0f), Sections[SectionIndex]);
sprintf(Line, "1 16 %f %f %f %f %f %f %f %f %f %f %f %f %s\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0],
Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2], EdgeParts[PartIdx]);
snprintf(Line, sizeof(Line), "1 16 %f %f %f %f %f %f %f %f %f %f %f %f %s\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0],
Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2], EdgeParts[PartIdx]);
File.WriteBuffer(Line, strlen(Line));
}
@@ -1221,8 +1220,8 @@ void lcSynthInfoFlexibleAxle::AddParts(lcMemFile& File, lcLibraryMeshData& MeshD
lcMatrix33 Transform(lcMul(EdgeTransforms[PartIdx], lcMatrix33(Sections[SectionIndex])));
lcVector3 Offset = lcMul31(lcVector3(0.0f, 4.0f * (5 - PartIdx), 0.0f), Sections[SectionIndex]);
sprintf(Line, "1 16 %f %f %f %f %f %f %f %f %f %f %f %f %s\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0],
Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2], EdgeParts[PartIdx]);
snprintf(Line, sizeof(Line), "1 16 %f %f %f %f %f %f %f %f %f %f %f %f %s\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0],
Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2], EdgeParts[PartIdx]);
File.WriteBuffer(Line, strlen(Line));
}
@@ -1283,7 +1282,7 @@ void lcSynthInfoFlexibleAxle::AddParts(lcMemFile& File, lcLibraryMeshData& MeshD
for (size_t SectionIndex = 1; SectionIndex < Sections.size() - 1; SectionIndex++)
{
const int Indices[] = { 1, 3, 5, 8, 10, 12, 15, 17, 19, 22, 24, 26 };
for (int VertexIdx = 0; VertexIdx < 12; VertexIdx++)
{
*IndexBuffer++ = BaseLinesVertex + Indices[VertexIdx];
@@ -1332,8 +1331,8 @@ void lcSynthInfoBraidedString::AddParts(lcMemFile& File, lcLibraryMeshData& Mesh
lcMatrix33 Transform(Sections[SectionIndex]);
lcVector3 Offset = lcMul31(lcVector3(-8.0f, 0.0f, 0.0f), Sections[SectionIndex]);
sprintf(Line, "1 16 %f %f %f %f %f %f %f %f %f %f %f %f 572A.dat\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0],
Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2]);
snprintf(Line, sizeof(Line), "1 16 %f %f %f %f %f %f %f %f %f %f %f %f 572A.dat\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0],
Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2]);
File.WriteBuffer(Line, strlen(Line));
}
@@ -1439,8 +1438,8 @@ void lcSynthInfoBraidedString::AddParts(lcMemFile& File, lcLibraryMeshData& Mesh
lcMatrix33 Transform(Sections[SectionIndex]);
lcVector3 Offset = lcMul31(lcVector3(8.0f, 0.0f, 0.0f), Sections[SectionIndex]);
sprintf(Line, "1 16 %f %f %f %f %f %f %f %f %f %f %f %f 572A.dat\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0],
Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2]);
snprintf(Line, sizeof(Line), "1 16 %f %f %f %f %f %f %f %f %f %f %f %f 572A.dat\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0],
Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2]);
File.WriteBuffer(Line, strlen(Line));
}
@@ -1452,18 +1451,18 @@ void lcSynthInfoShockAbsorber::AddParts(lcMemFile& File, lcLibraryMeshData&, con
lcVector3 Offset;
Offset = Sections[0].GetTranslation();
sprintf(Line, "1 0 %f %f %f 1 0 0 0 1 0 0 0 1 4254.dat\n", Offset[0], Offset[1], Offset[2]);
snprintf(Line, sizeof(Line), "1 0 %f %f %f 1 0 0 0 1 0 0 0 1 4254.dat\n", Offset[0], Offset[1], Offset[2]);
File.WriteBuffer(Line, strlen(Line));
Offset = Sections[1].GetTranslation();
sprintf(Line, "1 16 %f %f %f 1 0 0 0 1 0 0 0 1 4255.dat\n", Offset[0], Offset[1], Offset[2]);
snprintf(Line, sizeof(Line), "1 16 %f %f %f 1 0 0 0 1 0 0 0 1 4255.dat\n", Offset[0], Offset[1], Offset[2]);
File.WriteBuffer(Line, strlen(Line));
float Distance = Sections[0].GetTranslation().y - Sections[1].GetTranslation().y;
float Scale = (Distance - 66.0f) / 44.0f;
Offset = Sections[0].GetTranslation();
sprintf(Line, "1 494 %f %f %f 1 0 0 0 %f 0 0 0 1 %s\n", Offset[0], Offset[1] - 10 - 44.0f * Scale, Offset[2], Scale, mSpringPart);
snprintf(Line, sizeof(Line), "1 494 %f %f %f 1 0 0 0 %f 0 0 0 1 %s\n", Offset[0], Offset[1] - 10 - 44.0f * Scale, Offset[2], Scale, mSpringPart);
File.WriteBuffer(Line, strlen(Line));
}
@@ -1473,15 +1472,15 @@ void lcSynthInfoActuator::AddParts(lcMemFile& File, lcLibraryMeshData&, const st
lcVector3 Offset;
Offset = Sections[0].GetTranslation();
sprintf(Line, "1 16 %f %f %f 1 0 0 0 1 0 0 0 1 %s\n", Offset[0], Offset[1], Offset[2], mBodyPart);
snprintf(Line, sizeof(Line), "1 16 %f %f %f 1 0 0 0 1 0 0 0 1 %s\n", Offset[0], Offset[1], Offset[2], mBodyPart);
File.WriteBuffer(Line, strlen(Line));
Offset = lcMul(Sections[0], lcMatrix44Translation(lcVector3(0.0f, 0.0f, mAxleOffset))).GetTranslation();
sprintf(Line, "1 25 %f %f %f 0 1 0 -1 0 0 0 0 1 %s\n", Offset[0], Offset[1], Offset[2], mAxlePart);
snprintf(Line, sizeof(Line), "1 25 %f %f %f 0 1 0 -1 0 0 0 0 1 %s\n", Offset[0], Offset[1], Offset[2], mAxlePart);
File.WriteBuffer(Line, strlen(Line));
Offset = Sections[1].GetTranslation();
sprintf(Line, "1 72 %f %f %f 1 0 0 0 1 0 0 0 1 %s\n", Offset[0], Offset[1], Offset[2], mPistonPart);
snprintf(Line, sizeof(Line), "1 72 %f %f %f 1 0 0 0 1 0 0 0 1 %s\n", Offset[0], Offset[1], Offset[2], mPistonPart);
File.WriteBuffer(Line, strlen(Line));
}
@@ -1494,27 +1493,22 @@ void lcSynthInfoUniversalJoint::AddParts(lcMemFile& File, lcLibraryMeshData&, co
lcMatrix44 Rotation = lcMatrix44RotationZ(Angle);
lcMatrix44 Transform = lcMatrix44LeoCADToLDraw(Rotation);
sprintf(Line, "1 16 0 0 0 %f %f %f %f %f %f %f %f %f %s\n", Transform[0][0], Transform[1][0], Transform[2][0],
Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2], mCenterPart);
snprintf(Line, sizeof(Line), "1 16 0 0 0 %f %f %f %f %f %f %f %f %f %s\n", Transform[0][0], Transform[1][0], Transform[2][0],
Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2], mCenterPart);
File.WriteBuffer(Line, strlen(Line));
Angle = atan2f(Offset.y, hypotf(Offset.x, Offset.z));
Rotation = lcMul(Rotation, lcMatrix44RotationX(Angle));
Transform = lcMul(
lcMatrix44Translation(lcVector3(0.0f, 0.0f, mEndOffset)),
lcMatrix44LeoCADToLDraw(Rotation)
);
Transform = lcMul(lcMatrix44Translation(lcVector3(0.0f, 0.0f, mEndOffset)), lcMatrix44LeoCADToLDraw(Rotation));
sprintf(Line, "1 16 %f %f %f %f %f %f %f %f %f %f %f %f %s\n", Transform[3][0], Transform[3][1], Transform[3][2],
Transform[0][0], Transform[1][0], Transform[2][0],
Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2], mEndPart);
snprintf(Line, sizeof(Line), "1 16 %f %f %f %f %f %f %f %f %f %f %f %f %s\n", Transform[3][0], Transform[3][1], Transform[3][2],
Transform[0][0], Transform[1][0], Transform[2][0], Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2], mEndPart);
File.WriteBuffer(Line, strlen(Line));
Rotation = lcMatrix44FromEulerAngles(lcVector3(0.0f, LC_PI/2, LC_PI));
Transform = lcMatrix44LeoCADToLDraw(lcMul(lcMatrix44Translation(lcVector3(0.0f, mEndOffset, 0.0f)), Rotation));
sprintf(Line, "1 16 %f %f %f %f %f %f %f %f %f %f %f %f %s\n", Transform[3][0], Transform[3][1], Transform[3][2],
Transform[0][0], Transform[1][0], Transform[2][0],
Transform[0][1], Transform[1][1], -Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2], mEndPart);
snprintf(Line, sizeof(Line), "1 16 %f %f %f %f %f %f %f %f %f %f %f %f %s\n", Transform[3][0], Transform[3][1], Transform[3][2],
Transform[0][0], Transform[1][0], Transform[2][0], Transform[0][1], Transform[1][1], -Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2], mEndPart);
File.WriteBuffer(Line, strlen(Line));
}
+12 -5
View File
@@ -4,6 +4,7 @@
#include "lc_library.h"
#include "image.h"
#include "lc_glextensions.h"
#include "lc_string.h"
lcTexture* gGridTexture;
@@ -18,7 +19,7 @@ lcTexture* lcLoadTexture(const QString& FileName, int Flags)
}
else
{
strcpy(Texture->mName, QFileInfo(FileName).baseName().toLatin1());
lcstrcpy(Texture->mName, QFileInfo(FileName).baseName().toLatin1());
Texture->SetTemporary(true);
}
@@ -31,11 +32,9 @@ void lcReleaseTexture(lcTexture* Texture)
delete Texture;
}
lcTexture::lcTexture()
lcTexture::lcTexture(int Flags)
: mFlags(Flags)
{
mTexture = 0;
mRefCount = 0;
mTemporary = false;
}
lcTexture::~lcTexture()
@@ -176,8 +175,12 @@ bool lcTexture::Load(const QString& FileName, int Flags)
if (!Image.FileLoad(FileName))
return false;
mLoading = true;
SetImage(std::move(Image), Flags);
mLoading = false;
return true;
}
@@ -188,8 +191,12 @@ bool lcTexture::Load(lcMemFile& File, int Flags)
if (!Image.FileLoad(File))
return false;
mLoading = true;
SetImage(std::move(Image), Flags);
mLoading = false;
return true;
}
+7 -6
View File
@@ -20,7 +20,7 @@
class lcTexture
{
public:
lcTexture();
lcTexture(int Flags = 0);
~lcTexture();
lcTexture(const lcTexture&) = delete;
@@ -67,7 +67,7 @@ public:
bool NeedsUpload() const
{
return mTexture == 0 && !mImages.empty();
return !mLoading && mTexture == 0 && !mImages.empty();
}
int GetFlags() const
@@ -89,16 +89,17 @@ public:
int mHeight;
char mName[LC_TEXTURE_NAME_LEN];
QString mFileName;
GLuint mTexture;
GLuint mTexture = 0;
protected:
bool Load();
bool LoadImages();
bool mTemporary;
QAtomicInt mRefCount;
bool mTemporary = false;
QAtomicInt mRefCount = 0;
std::vector<Image> mImages;
int mFlags;
int mFlags = 0;
bool mLoading = false;
};
lcTexture* lcLoadTexture(const QString& FileName, int Flags);
+11 -6
View File
@@ -19,10 +19,10 @@ lcThumbnailManager::~lcThumbnailManager()
mLibrary->ReleasePieceInfo(Thumbnail.Info);
}
std::pair<lcPartThumbnailId, QPixmap> lcThumbnailManager::RequestThumbnail(PieceInfo* Info, int ColorIndex, int Size)
std::pair<lcPartThumbnailId, QPixmap> lcThumbnailManager::RequestThumbnail(PieceInfo* Info, int ColorIndex, int Size, float DeviceScale)
{
for (auto &[ThumbnailId, Thumbnail] : mThumbnails)
if (Thumbnail.Info == Info && Thumbnail.ColorIndex == ColorIndex && Thumbnail.Size == Size)
if (Thumbnail.Info == Info && Thumbnail.ColorIndex == ColorIndex && Thumbnail.Size == Size && Thumbnail.DeviceScale == DeviceScale)
return { ThumbnailId, Thumbnail.Pixmap };
lcPartThumbnailId ThumbnailId = static_cast<lcPartThumbnailId>(mNextThumbnailId++);
@@ -31,6 +31,7 @@ std::pair<lcPartThumbnailId, QPixmap> lcThumbnailManager::RequestThumbnail(Piece
Thumbnail.Info = Info;
Thumbnail.ColorIndex = ColorIndex;
Thumbnail.Size = Size;
Thumbnail.DeviceScale = DeviceScale;
Thumbnail.ReferenceCount = 1;
mLibrary->LoadPieceInfo(Info, false, false);
@@ -70,8 +71,8 @@ void lcThumbnailManager::PartLoaded(PieceInfo* Info)
void lcThumbnailManager::DrawThumbnail(lcPartThumbnailId ThumbnailId, lcPartThumbnail& Thumbnail)
{
const int Width = Thumbnail.Size * 2;
const int Height = Thumbnail.Size * 2;
const int Width = Thumbnail.Size * 2 * Thumbnail.DeviceScale;
const int Height = Thumbnail.Size * 2 * Thumbnail.DeviceScale;
if (mView && (mView->GetWidth() != Width || mView->GetHeight() != Height))
mView.reset();
@@ -120,7 +121,7 @@ void lcThumbnailManager::DrawThumbnail(lcPartThumbnailId ThumbnailId, lcPartThum
IconName = ":/resources/part_flexible.png";
else if (Info->GetTrainTrackInfo())
IconName = ":/resources/part_traintrack.png";
if (IconName)
{
QPainter Painter(&Image);
@@ -146,7 +147,11 @@ void lcThumbnailManager::DrawThumbnail(lcPartThumbnailId ThumbnailId, lcPartThum
Painter.end();
}
Thumbnail.Pixmap = QPixmap::fromImage(Image).scaled(Thumbnail.Size, Thumbnail.Size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
Image.setDevicePixelRatio(Thumbnail.DeviceScale);
float ScaledSize = Thumbnail.Size * Thumbnail.DeviceScale;
Thumbnail.Pixmap = QPixmap::fromImage(Image).scaled(ScaledSize, ScaledSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
mLibrary->ReleasePieceInfo(Info);
+2 -1
View File
@@ -8,6 +8,7 @@ struct lcPartThumbnail
PieceInfo* Info;
int ColorIndex;
int Size;
float DeviceScale;
int ReferenceCount;
};
@@ -24,7 +25,7 @@ public:
lcThumbnailManager(lcPiecesLibrary* Library);
~lcThumbnailManager();
std::pair<lcPartThumbnailId, QPixmap> RequestThumbnail(PieceInfo* Info, int ColorIndex, int Size);
std::pair<lcPartThumbnailId, QPixmap> RequestThumbnail(PieceInfo* Info, int ColorIndex, int Size, float DeviceScale);
void ReleaseThumbnail(lcPartThumbnailId ThumbnailId);
signals:
+10 -9
View File
@@ -4,8 +4,6 @@
#include "piece.h"
#include "pieceinf.h"
#include "lc_mainwindow.h"
#include "lc_viewwidget.h"
#include "lc_previewwidget.h"
lcTimelineWidget::lcTimelineWidget(QWidget* Parent)
: QTreeWidget(Parent)
@@ -249,7 +247,7 @@ void lcTimelineWidget::Update(bool Clear, bool UpdateItems)
StepItem = topLevelItem(Step - 1);
PieceItemIndex = 0;
}
UpdateCurrentStepItem();
blockSignals(Blocked);
@@ -383,7 +381,7 @@ void lcTimelineWidget::MoveSelection()
return;
Step++;
QList<QTreeWidgetItem*> SelectedItems = selectedItems();
const QList<QTreeWidgetItem*> SelectedItems = selectedItems();
for (QTreeWidgetItem* PieceItem : SelectedItems)
{
@@ -421,7 +419,7 @@ void lcTimelineWidget::MoveSelectionBefore()
Step++;
QList<QTreeWidgetItem*> SelectedItems = selectedItems();
const QList<QTreeWidgetItem*> SelectedItems = selectedItems();
gMainWindow->GetActiveModel()->InsertStep(Step);
@@ -463,7 +461,7 @@ void lcTimelineWidget::MoveSelectionAfter()
Step += 2;
QList<QTreeWidgetItem*> SelectedItems = selectedItems();
const QList<QTreeWidgetItem*> SelectedItems = selectedItems();
gMainWindow->GetActiveModel()->InsertStep(Step);
@@ -526,7 +524,7 @@ void lcTimelineWidget::ItemSelectionChanged()
{
std::vector<lcObject*> Selection;
lcStep LastStep = 1;
QList<QTreeWidgetItem*> SelectedItems = selectedItems();
const QList<QTreeWidgetItem*> SelectedItems = selectedItems();
for (QTreeWidgetItem* PieceItem : SelectedItems)
{
@@ -554,9 +552,12 @@ void lcTimelineWidget::ItemSelectionChanged()
UpdateCurrentStepItem();
}
Model->SetSelectionAndFocus(Selection, CurrentPiece, LC_PIECE_SECTION_POSITION, false);
Model->SetSelectionAndFocus(Selection, CurrentPiece, LC_PIECE_SECTION_POSITION, lcSelectionMode::Single);
mIgnoreUpdates = false;
blockSignals(Blocked);
UpdateSelection();
}
void lcTimelineWidget::dropEvent(QDropEvent* Event)
@@ -589,7 +590,7 @@ void lcTimelineWidget::dropEvent(QDropEvent* Event)
std::sort(SelectedItems.begin(), SelectedItems.end(), SortItems);
for (QTreeWidgetItem* SelectedItem : SelectedItems)
for (QTreeWidgetItem* SelectedItem : std::as_const(SelectedItems))
SelectedItem->setSelected(true);
QTreeWidget::dropEvent(Event);
+125 -107
View File
@@ -9,7 +9,6 @@
#include "lc_texture.h"
#include "piece.h"
#include "pieceinf.h"
#include "lc_synth.h"
#include "lc_traintrack.h"
#include "lc_scene.h"
#include "lc_context.h"
@@ -75,8 +74,7 @@ lcView::~lcView()
if (mLastFocusedView == this)
mLastFocusedView = nullptr;
if (mDeleteContext)
delete mContext;
delete mContext;
}
std::vector<lcView*> lcView::GetModelViews(const lcModel* Model)
@@ -251,7 +249,7 @@ lcMatrix44 lcView::GetProjectionMatrix() const
{
float AspectRatio = (float)mWidth / (float)mHeight;
if (mCamera->IsOrtho())
if (mCamera->GetProjection() == lcCameraProjection::Orthographic)
{
float OrthoHeight = mCamera->GetOrthoHeight() / 2.0f;
float OrthoWidth = OrthoHeight * AspectRatio;
@@ -270,7 +268,7 @@ lcMatrix44 lcView::GetTileProjectionMatrix(int CurrentRow, int CurrentColumn, in
double ImageLeft, ImageRight, ImageBottom, ImageTop, Near, Far;
double AspectRatio = (double)ImageWidth / (double)ImageHeight;
if (mCamera->IsOrtho())
if (mCamera->GetProjection() == lcCameraProjection::Orthographic)
{
float OrthoHeight = mCamera->GetOrthoHeight() / 2.0f;
float OrthoWidth = OrthoHeight * AspectRatio;
@@ -303,7 +301,7 @@ lcMatrix44 lcView::GetTileProjectionMatrix(int CurrentRow, int CurrentColumn, in
double Bottom = ImageBottom + (ImageTop - ImageBottom) * (CurrentRow * mHeight) / ImageHeight;
double Top = Bottom + (ImageTop - ImageBottom) * CurrentTileHeight / ImageHeight;
if (mCamera->IsOrtho())
if (mCamera->GetProjection() == lcCameraProjection::Orthographic)
return lcMatrix44Ortho(Left, Right, Bottom, Top, Near, Far);
else
return lcMatrix44Frustum(Left, Right, Bottom, Top, Near, Far);
@@ -807,9 +805,10 @@ void lcView::SaveStepImages(const QString& BaseName, bool AddStepSuffix, lcStep
bool lcView::BeginRenderToImage(int Width, int Height)
{
lcContext* Context = lcContext::GetGlobalOffscreenContext();
GLint MaxTexture;
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &MaxTexture);
Context->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &MaxTexture);
MaxTexture = qMin(MaxTexture, 2048);
const int Samples = QSurfaceFormat::defaultFormat().samples();
@@ -1151,9 +1150,13 @@ void lcView::DrawBackground(int CurrentTileRow, int TotalTileRows, int CurrentTi
void lcView::DrawViewport() const
{
float Scale = GetUIScale();
float Width = mWidth / Scale;
float Height = mHeight / Scale;
mContext->SetWorldMatrix(lcMatrix44Identity());
mContext->SetViewMatrix(lcMatrix44Translation(lcVector3(0.375, 0.375, 0.0)));
mContext->SetProjectionMatrix(lcMatrix44Ortho(0.0f, mWidth, 0.0f, mHeight, -1.0f, 1.0f));
mContext->SetProjectionMatrix(lcMatrix44Ortho(0.0f, Width, 0.0f, Height, -1.0f, 1.0f));
mContext->SetLineWidth(1.0f);
mContext->SetDepthWrite(false);
@@ -1166,7 +1169,7 @@ void lcView::DrawViewport() const
else
mContext->SetColor(lcVector4FromColor(lcGetPreferences().mInactiveViewColor));
float Verts[8] = { 0.0f, 0.0f, mWidth - 1.0f, 0.0f, mWidth - 1.0f, mHeight - 1.0f, 0.0f, mHeight - 1.0f };
float Verts[8] = { 0.0f, 0.0f, Width - 1.0f, 0.0f, Width - 1.0f, Height - 1.0f, 0.0f, Height - 1.0f };
mContext->SetVertexBufferPointer(Verts);
mContext->SetVertexFormatPosition(2);
@@ -1182,7 +1185,7 @@ void lcView::DrawViewport() const
mContext->EnableColorBlend(true);
gTexFont.PrintText(mContext, 3.0f, (float)mHeight - 1.0f - 6.0f, 0.0f, CameraName.toLatin1().constData());
gTexFont.PrintText(mContext, 3.0f, (float)Height - 1.0f - 6.0f, 0.0f, CameraName.toLatin1().constData());
mContext->EnableColorBlend(false);
}
@@ -1244,26 +1247,28 @@ void lcView::DrawAxes() const
};
lcMatrix44 TranslationMatrix;
float Scale = GetUIScale();
switch (Preferences.mAxisIconLocation)
{
default:
case lcAxisIconLocation::BottomLeft:
TranslationMatrix = lcMatrix44Translation(lcVector3(32, 32, 0.0f));
TranslationMatrix = lcMatrix44Translation(lcVector3(32, 32, 0.0f) / Scale);
break;
case lcAxisIconLocation::BottomRight:
TranslationMatrix = lcMatrix44Translation(lcVector3(mWidth - 36, 32, 0.0f));
TranslationMatrix = lcMatrix44Translation(lcVector3(mWidth - 36, 32, 0.0f) / Scale);
break;
case lcAxisIconLocation::TopLeft:
TranslationMatrix = lcMatrix44Translation(lcVector3(32, mHeight - 36, 0.0f));
TranslationMatrix = lcMatrix44Translation(lcVector3(32, mHeight - 36, 0.0f) / Scale);
break;
case lcAxisIconLocation::TopRight:
TranslationMatrix = lcMatrix44Translation(lcVector3(mWidth - 36, mHeight - 36, 0.0f));
TranslationMatrix = lcMatrix44Translation(lcVector3(mWidth - 36, mHeight - 36, 0.0f) / Scale);
break;
}
lcMatrix44 WorldViewMatrix = mCamera->mWorldView;
WorldViewMatrix.SetTranslation(lcVector3(0, 0, 0));
@@ -1271,7 +1276,7 @@ void lcView::DrawAxes() const
mContext->SetMaterial(lcMaterialType::UnlitVertexColor);
mContext->SetWorldMatrix(lcMatrix44Identity());
mContext->SetViewMatrix(lcMul(WorldViewMatrix, TranslationMatrix));
mContext->SetProjectionMatrix(lcMatrix44Ortho(0, mWidth, 0, mHeight, -50, 50));
mContext->SetProjectionMatrix(lcMatrix44Ortho(0, mWidth / Scale, 0, mHeight / Scale, -50, 50));
mContext->SetVertexBufferPointer(Verts);
mContext->SetVertexFormat(0, 3, 0, 0, 4, false);
@@ -1519,69 +1524,76 @@ void lcView::DrawGrid()
if (Preferences.mDrawGridLines)
VertexBufferSize += 2 * (MaxX - MinX + MaxY - MinY + 2) * 3 * sizeof(float);
float* Verts = (float*)malloc(VertexBufferSize);
if (!Verts)
return;
float* CurVert = Verts;
float* Verts = nullptr;
if (Preferences.mDrawGridStuds)
if (VertexBufferSize)
{
float Left = MinX * 20.0f * Spacing;
float Right = MaxX * 20.0f * Spacing;
float Top = MinY * 20.0f * Spacing;
float Bottom = MaxY * 20.0f * Spacing;
float Z = 0;
float U = (MaxX - MinX) * Spacing;
float V = (MaxY - MinY) * Spacing;
Verts = static_cast<float*>(malloc(VertexBufferSize));
*CurVert++ = Left;
*CurVert++ = Top;
*CurVert++ = Z;
*CurVert++ = 0.0f;
*CurVert++ = V;
if (!Verts)
return;
*CurVert++ = Right;
*CurVert++ = Top;
*CurVert++ = Z;
*CurVert++ = U;
*CurVert++ = V;
float* CurVert = Verts;
*CurVert++ = Left;
*CurVert++ = Bottom;
*CurVert++ = Z;
*CurVert++ = 0.0f;
*CurVert++ = 0.0f;
if (Preferences.mDrawGridStuds)
{
float Left = MinX * 20.0f * Spacing;
float Right = MaxX * 20.0f * Spacing;
float Top = MinY * 20.0f * Spacing;
float Bottom = MaxY * 20.0f * Spacing;
float Z = 0;
float U = (MaxX - MinX) * Spacing;
float V = (MaxY - MinY) * Spacing;
*CurVert++ = Right;
*CurVert++ = Bottom;
*CurVert++ = Z;
*CurVert++ = U;
*CurVert++ = 0.0f;
}
*CurVert++ = Left;
*CurVert++ = Top;
*CurVert++ = Z;
*CurVert++ = 0.0f;
*CurVert++ = V;
if (Preferences.mDrawGridLines)
{
float LineSpacing = Spacing * 20.0f;
*CurVert++ = Right;
*CurVert++ = Top;
*CurVert++ = Z;
*CurVert++ = U;
*CurVert++ = V;
for (int Step = MinX; Step < MaxX + 1; Step++)
{
*CurVert++ = Step * LineSpacing;
*CurVert++ = MinY * LineSpacing;
*CurVert++ = 0.0f;
*CurVert++ = Step * LineSpacing;
*CurVert++ = MaxY * LineSpacing;
*CurVert++ = 0.0f;
}
*CurVert++ = Left;
*CurVert++ = Bottom;
*CurVert++ = Z;
*CurVert++ = 0.0f;
*CurVert++ = 0.0f;
for (int Step = MinY; Step < MaxY + 1; Step++)
{
*CurVert++ = MinX * LineSpacing;
*CurVert++ = Step * LineSpacing;
*CurVert++ = 0.0f;
*CurVert++ = MaxX * LineSpacing;
*CurVert++ = Step * LineSpacing;
*CurVert++ = 0.0f;
}
*CurVert++ = Right;
*CurVert++ = Bottom;
*CurVert++ = Z;
*CurVert++ = U;
*CurVert++ = 0.0f;
}
if (Preferences.mDrawGridLines)
{
float LineSpacing = Spacing * 20.0f;
for (int Step = MinX; Step < MaxX + 1; Step++)
{
*CurVert++ = Step * LineSpacing;
*CurVert++ = MinY * LineSpacing;
*CurVert++ = 0.0f;
*CurVert++ = Step * LineSpacing;
*CurVert++ = MaxY * LineSpacing;
*CurVert++ = 0.0f;
}
for (int Step = MinY; Step < MaxY + 1; Step++)
{
*CurVert++ = MinX * LineSpacing;
*CurVert++ = Step * LineSpacing;
*CurVert++ = 0.0f;
*CurVert++ = MaxX * LineSpacing;
*CurVert++ = Step * LineSpacing;
*CurVert++ = 0.0f;
}
}
}
mGridSettings[0] = MinX;
@@ -1692,6 +1704,11 @@ lcTrackTool lcView::GetOverrideTrackTool(Qt::MouseButton Button) const
return TrackToolFromTool[static_cast<int>(OverrideTool)];
}
float lcView::GetUIScale() const
{
return mWidget ? mWidget->GetDeviceScale() : 1.0f;
}
float lcView::GetOverlayScale() const
{
lcVector3 OverlayCenter;
@@ -1709,7 +1726,8 @@ float lcView::GetOverlayScale() const
lcVector3 Point = UnprojectPoint(ScreenPos);
lcVector3 Dist(Point - WorldMatrix.GetTranslation());
return Dist.Length() * 5.0f;
return Dist.Length() * 5.0f * GetUIScale();
}
void lcView::BeginDrag(lcDragState DragState)
@@ -1868,18 +1886,19 @@ void lcView::SetCameraIndex(size_t CameraIndex)
Redraw();
}
void lcView::SetProjection(bool Ortho)
void lcView::SetCameraProjection(lcCameraProjection CameraProjection)
{
if (mCamera->IsSimple())
{
mCamera->SetOrtho(Ortho);
mCamera->SetProjection(CameraProjection);
Redraw();
}
else
{
lcModel* ActiveModel = GetActiveModel();
if (ActiveModel)
ActiveModel->SetCameraOrthographic(mCamera, Ortho);
ActiveModel->SetCameraProjection(mCamera, CameraProjection);
}
}
@@ -2276,7 +2295,7 @@ void lcView::StartPanGesture()
lcModel* ActiveModel = GetActiveModel();
StartPan(mWidth / 2, mHeight / 2);
ActiveModel->BeginMouseTool();
ActiveModel->BeginMouseTool(lcTool::Pan, this);
}
void lcView::UpdatePanGesture(int dx, int dy)
@@ -2336,7 +2355,7 @@ void lcView::EndPanGesture(bool Accept)
{
lcModel* ActiveModel = GetActiveModel();
ActiveModel->EndMouseTool(lcTool::Pan, Accept);
ActiveModel->EndMouseTool(lcTool::Pan, this, Accept);
}
void lcView::StartTracking(lcTrackButton TrackButton)
@@ -2355,22 +2374,13 @@ void lcView::StartTracking(lcTrackButton TrackButton)
case lcTool::SpotLight:
case lcTool::DirectionalLight:
case lcTool::AreaLight:
break;
case lcTool::Camera:
{
lcVector3 Position = GetCameraLightInsertPosition();
lcVector3 Target = Position + lcVector3(0.1f, 0.1f, 0.1f);
ActiveModel->BeginCameraTool(Position, Target);
}
break;
case lcTool::Select:
break;
case lcTool::Move:
case lcTool::Rotate:
ActiveModel->BeginMouseTool();
ActiveModel->BeginMouseTool(Tool, this);
break;
case lcTool::Eraser:
@@ -2380,13 +2390,13 @@ void lcView::StartTracking(lcTrackButton TrackButton)
case lcTool::Pan:
StartPan(mMouseX, mMouseY);
ActiveModel->BeginMouseTool();
ActiveModel->BeginMouseTool(Tool, this);
break;
case lcTool::Zoom:
case lcTool::RotateView:
case lcTool::Roll:
ActiveModel->BeginMouseTool();
ActiveModel->BeginMouseTool(Tool, this);
break;
case lcTool::ZoomRegion:
@@ -2411,13 +2421,10 @@ void lcView::StopTracking(bool Accept)
{
case lcTool::Insert:
case lcTool::PointLight:
break;
case lcTool::SpotLight:
case lcTool::DirectionalLight:
case lcTool::AreaLight:
case lcTool::Camera:
ActiveModel->EndMouseTool(Tool, Accept);
break;
case lcTool::Select:
@@ -2426,17 +2433,17 @@ void lcView::StopTracking(bool Accept)
std::vector<lcObject*> Objects = FindObjectsInBox(mMouseDownX, mMouseDownY, mMouseX, mMouseY);
if (mMouseModifiers & Qt::ControlModifier)
ActiveModel->AddToSelection(Objects, true, true);
ActiveModel->AddToSelection(Objects);
else if (mMouseModifiers & Qt::ShiftModifier)
ActiveModel->RemoveFromSelection(Objects);
else
ActiveModel->SetSelectionAndFocus(Objects, nullptr, 0, true);
ActiveModel->SetSelectionAndFocus(Objects, nullptr, 0, gMainWindow->GetSelectionMode());
}
break;
case lcTool::Move:
case lcTool::Rotate:
ActiveModel->EndMouseTool(Tool, Accept);
ActiveModel->EndMouseTool(Tool, this, Accept);
break;
case lcTool::Eraser:
@@ -2448,7 +2455,7 @@ void lcView::StopTracking(bool Accept)
case lcTool::Pan:
case lcTool::RotateView:
case lcTool::Roll:
ActiveModel->EndMouseTool(Tool, Accept);
ActiveModel->EndMouseTool(Tool, this, Accept);
break;
case lcTool::ZoomRegion:
@@ -2477,7 +2484,7 @@ void lcView::StopTracking(bool Accept)
if (lcLineSegmentPlaneIntersection(&Target, Points[0], Points[1], Plane) && lcLineSegmentPlaneIntersection(&Corners[0], Points[2], Points[3], Plane) && lcLineSegmentPlaneIntersection(&Corners[1], Points[3], Points[4], Plane))
{
float AspectRatio = (float)mWidth / (float)mHeight;
ActiveModel->ZoomRegionToolClicked(mCamera, AspectRatio, Points[0], Target, Corners);
ActiveModel->ZoomRegionToolClicked(this, AspectRatio, Points[0], Target, Corners);
}
}
break;
@@ -2499,7 +2506,7 @@ void lcView::CancelTrackingOrClearSelection()
{
lcModel* ActiveModel = GetActiveModel();
if (ActiveModel)
ActiveModel->ClearSelection(true);
ActiveModel->ClearSelection();
}
}
@@ -2562,7 +2569,15 @@ void lcView::OnButtonDown(lcTrackButton TrackButton)
break;
case lcTrackTool::Camera:
StartTracking(TrackButton);
{
ActiveModel->InsertCameraToolClicked(GetCameraLightInsertPosition());
if ((mMouseModifiers & Qt::ControlModifier) == 0)
gMainWindow->SetTool(lcTool::Select);
mToolClicked = true;
UpdateTrackTool();
}
break;
case lcTrackTool::Select:
@@ -2570,11 +2585,14 @@ void lcView::OnButtonDown(lcTrackButton TrackButton)
lcObjectSection ObjectSection = FindObjectUnderPointer(false, false);
if (mMouseModifiers & Qt::ControlModifier)
ActiveModel->FocusOrDeselectObject(ObjectSection);
ActiveModel->FocusOrDeselectObject(ObjectSection.Object, ObjectSection.Section, gMainWindow->GetSelectionMode());
else if (mMouseModifiers & Qt::ShiftModifier)
ActiveModel->RemoveFromSelection(ObjectSection);
{
if (ObjectSection.Object)
ActiveModel->RemoveFromSelection({ ObjectSection.Object });
}
else
ActiveModel->ClearSelectionAndSetFocus(ObjectSection, true);
ActiveModel->SetSelectionAndFocus(std::vector<lcObject*>(), ObjectSection.Object, ObjectSection.Section, gMainWindow->GetSelectionMode());
StartTracking(TrackButton);
}
@@ -2640,7 +2658,7 @@ void lcView::OnButtonDown(lcTrackButton TrackButton)
ObjectSection.Object = Focus;
ObjectSection.Section = mTrackToolSection;
ActiveModel->ClearSelectionAndSetFocus(ObjectSection, true);
ActiveModel->SetSelectionAndFocus(std::vector<lcObject*>(), ObjectSection.Object, ObjectSection.Section, gMainWindow->GetSelectionMode());
}
break;
@@ -2734,11 +2752,14 @@ void lcView::OnLeftButtonDoubleClick()
lcObjectSection ObjectSection = FindObjectUnderPointer(false, false);
if (mMouseModifiers & Qt::ControlModifier)
ActiveModel->FocusOrDeselectObject(ObjectSection);
ActiveModel->FocusOrDeselectObject(ObjectSection.Object, ObjectSection.Section, gMainWindow->GetSelectionMode());
else if (mMouseModifiers & Qt::ShiftModifier)
ActiveModel->RemoveFromSelection(ObjectSection);
{
if (ObjectSection.Object)
ActiveModel->RemoveFromSelection({ ObjectSection.Object });
}
else
ActiveModel->ClearSelectionAndSetFocus(ObjectSection, true);
ActiveModel->SetSelectionAndFocus(std::vector<lcObject*>(), ObjectSection.Object, ObjectSection.Section, gMainWindow->GetSelectionMode());
}
void lcView::OnMiddleButtonDown()
@@ -2854,10 +2875,7 @@ void lcView::OnMouseMove()
case lcTrackTool::SpotLight:
case lcTrackTool::DirectionalLight:
case lcTrackTool::AreaLight:
break;
case lcTrackTool::Camera:
ActiveModel->UpdateCameraTool(GetCameraLightInsertPosition());
break;
case lcTrackTool::Select:
+3 -2
View File
@@ -5,6 +5,7 @@
#include "lc_commands.h"
struct lcInsertPieceInfo;
enum class lcCameraProjection;
enum class lcDragState
{
@@ -252,7 +253,7 @@ public:
void SetCamera(const QString& CameraName);
void SetCameraIndex(size_t CameraIndex);
void SetProjection(bool Ortho);
void SetCameraProjection(lcCameraProjection CameraProjection);
void LookAt();
void MoveCamera(const lcVector3& Direction);
void Zoom(float Amount);
@@ -263,6 +264,7 @@ public:
bool CloseFindReplaceDialog();
void ShowFindReplaceWidget(bool Replace);
float GetUIScale() const;
float GetOverlayScale() const;
lcVector3 GetMoveDirection(const lcVector3& Direction) const;
void UpdatePiecePreview();
@@ -319,7 +321,6 @@ protected:
lcViewWidget* mWidget = nullptr;
int mWidth = 1;
int mHeight = 1;
bool mDeleteContext = true;
lcViewType mViewType;
int mMouseX = 0;
+2 -3
View File
@@ -515,7 +515,7 @@ void lcViewManipulator::DrawTrainTrack(lcPiece* Piece, lcContext* Context, lcTra
else if (TrackTool == lcTrackTool::RotateTrainTrackLeft)
{
Context->DrawIndexedPrimitives(GL_TRIANGLES, 96, GL_UNSIGNED_SHORT, (108 + 360 + 12) * 2);
if (CanAdd)
Context->DrawIndexedPrimitives(GL_TRIANGLES, 72, GL_UNSIGNED_SHORT, (108 + 360 + 12 + 192) * 2);
@@ -890,7 +890,7 @@ void lcViewManipulator::DrawRotate(lcTrackButton TrackButton, lcTrackTool TrackT
Context->EnableColorBlend(true);
char buf[32];
sprintf(buf, "[%.2f]", fabsf(Angle));
snprintf(buf, sizeof(buf), "[%.2f]", fabsf(Angle));
int cx, cy;
gTexFont.GetStringDimensions(&cx, &cy, buf);
@@ -1165,7 +1165,6 @@ std::pair<lcTrackTool, quint32> lcViewManipulator::UpdateSelectMove(lcTrackButto
{
NewTrackTool = TrainTrackTool;
NewTrackSection = TrainTrackSection;
ClosestIntersectionDistance = TrainDistance;
}
}
+5 -3
View File
@@ -183,9 +183,10 @@ void lcViewSphere::Draw()
return;
lcContext* Context = mView->mContext;
const float UIScale = mView->GetUIScale();
const int Width = mView->GetWidth();
const int Height = mView->GetHeight();
const int ViewportSize = mSize;
const int ViewportSize = mSize * UIScale;
const int Left = (mLocation == lcViewSphereLocation::BottomLeft || mLocation == lcViewSphereLocation::TopLeft) ? 0 : Width - ViewportSize;
const int Bottom = (mLocation == lcViewSphereLocation::BottomLeft || mLocation == lcViewSphereLocation::BottomRight) ? 0 : Height - ViewportSize;
Context->SetViewport(Left, Bottom, ViewportSize, ViewportSize);
@@ -240,7 +241,7 @@ void lcViewSphere::Draw()
Context->EnableCullFace(false);
Context->SetDepthFunction(lcDepthFunction::LessEqual);
Context->SetViewport(0, 0, Width, Height);
Context->SetViewport(0, 0, mView->GetWidth(), mView->GetHeight());
}
bool lcViewSphere::OnLeftButtonDown()
@@ -323,9 +324,10 @@ bool lcViewSphere::IsDragging() const
std::bitset<6> lcViewSphere::GetIntersectionFlags(lcVector3& Intersection) const
{
const float UIScale = mView->GetUIScale();
const int Width = mView->GetWidth();
const int Height = mView->GetHeight();
const int ViewportSize = mSize;
const int ViewportSize = mSize * UIScale;
const int Left = (mLocation == lcViewSphereLocation::BottomLeft || mLocation == lcViewSphereLocation::TopLeft) ? 0 : Width - ViewportSize;
const int Bottom = (mLocation == lcViewSphereLocation::BottomLeft || mLocation == lcViewSphereLocation::BottomRight) ? 0 : Height - ViewportSize;
const int x = mView->GetMouseX() - Left;
+3 -6
View File
@@ -63,7 +63,7 @@ void lcViewWidget::SetView(lcView* View)
void lcViewWidget::UpdateMousePosition()
{
QPoint MousePosition = mapFromGlobal( QCursor::pos() );
QPoint MousePosition = mapFromGlobal(QCursor::pos());
float DeviceScale = GetDeviceScale();
mView->SetMousePosition(MousePosition.x() * DeviceScale, mView->GetHeight() - MousePosition.y() * DeviceScale - 1);
@@ -77,11 +77,8 @@ void lcViewWidget::initializeGL()
void lcViewWidget::resizeGL(int Width, int Height)
{
#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
const float Scale = devicePixelRatioF();
#else
const int Scale = devicePixelRatio();
#endif
const float Scale = GetDeviceScale();
mView->SetSize(Width * Scale, Height * Scale);
}
+1 -1
View File
@@ -15,7 +15,6 @@ public:
QSize sizeHint() const override;
protected:
float GetDeviceScale() const
{
#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
@@ -25,6 +24,7 @@ protected:
#endif
}
protected:
void initializeGL() override;
void resizeGL(int Width, int Height) override;
void paintGL() override;
+70 -10
View File
@@ -1,6 +1,5 @@
#include "lc_global.h"
#include "lc_math.h"
#include "lc_colors.h"
#include <string.h>
#include <stdio.h>
#include <math.h>
@@ -20,6 +19,11 @@
static const std::array<QLatin1String, static_cast<int>(lcLightType::Count)> gLightTypes = { QLatin1String("POINT"), QLatin1String("SPOT"), QLatin1String("DIRECTIONAL"), QLatin1String("AREA") };
static const std::array<QLatin1String, static_cast<int>(lcLightAreaShape::Count)> gLightAreaShapes = { QLatin1String("RECTANGLE"), QLatin1String("SQUARE"), QLatin1String("DISK"), QLatin1String("ELLIPSE") };
lcLight::lcLight()
: lcObject(lcObjectType::Light)
{
}
lcLight::lcLight(const lcVector3& Position, lcLightType LightType)
: lcObject(lcObjectType::Light), mLightType(LightType)
{
@@ -28,7 +32,7 @@ lcLight::lcLight(const lcVector3& Position, lcLightType LightType)
mPosition.SetValue(Position);
UpdatePosition(1);
lcLight::UpdatePosition(1);
}
QString lcLight::GetLightTypeString(lcLightType LightType)
@@ -492,7 +496,7 @@ void lcLight::MoveSelected(lcStep Step, bool AddKey, const lcVector3& Distance,
WorldMatrix.Orthonormalize();
SetRotation(WorldMatrix, Step, AddKey);
mWorldMatrix = lcMatrix44(WorldMatrix, mWorldMatrix.GetTranslation());
}
}
@@ -883,7 +887,7 @@ void lcLight::SetupLightMatrix(lcContext* Context) const
const lcPreferences& Preferences = lcGetPreferences();
const float LineWidth = Preferences.mLineWidth;
if (IsSelected(LC_LIGHT_SECTION_POSITION))
if (IsSelected())
{
const lcVector4 SelectedColor = lcVector4FromColor(Preferences.mObjectSelectedColor);
const lcVector4 FocusedColor = lcVector4FromColor(Preferences.mObjectFocusedColor);
@@ -1044,7 +1048,7 @@ void lcLight::DrawTarget(lcContext* Context) const
const lcPreferences& Preferences = lcGetPreferences();
const float LineWidth = Preferences.mLineWidth;
if (IsSelected(LC_LIGHT_SECTION_TARGET))
if (IsSelected())
{
const lcVector4 SelectedColor = lcVector4FromColor(Preferences.mObjectSelectedColor);
const lcVector4 FocusedColor = lcVector4FromColor(Preferences.mObjectFocusedColor);
@@ -1132,7 +1136,7 @@ QVariant lcLight::GetPropertyValue(lcObjectPropertyId PropertyId) const
case lcObjectPropertyId::PieceStepShow:
case lcObjectPropertyId::PieceStepHide:
case lcObjectPropertyId::CameraName:
case lcObjectPropertyId::CameraType:
case lcObjectPropertyId::CameraProjection:
case lcObjectPropertyId::CameraFOV:
case lcObjectPropertyId::CameraNear:
case lcObjectPropertyId::CameraFar:
@@ -1223,7 +1227,7 @@ bool lcLight::SetPropertyValue(lcObjectPropertyId PropertyId, lcStep Step, bool
case lcObjectPropertyId::PieceStepShow:
case lcObjectPropertyId::PieceStepHide:
case lcObjectPropertyId::CameraName:
case lcObjectPropertyId::CameraType:
case lcObjectPropertyId::CameraProjection:
case lcObjectPropertyId::CameraFOV:
case lcObjectPropertyId::CameraNear:
case lcObjectPropertyId::CameraFar:
@@ -1246,7 +1250,7 @@ bool lcLight::SetPropertyValue(lcObjectPropertyId PropertyId, lcStep Step, bool
case lcObjectPropertyId::LightColor:
return SetColor(Value.value<lcVector3>(), Step, AddKey);
case lcObjectPropertyId::LightBlenderPower:
return SetBlenderPower(Value.toFloat(), Step, AddKey);
@@ -1314,7 +1318,7 @@ bool lcLight::HasKeyFrame(lcObjectPropertyId PropertyId, lcStep Time) const
case lcObjectPropertyId::PieceStepShow:
case lcObjectPropertyId::PieceStepHide:
case lcObjectPropertyId::CameraName:
case lcObjectPropertyId::CameraType:
case lcObjectPropertyId::CameraProjection:
case lcObjectPropertyId::CameraFOV:
case lcObjectPropertyId::CameraNear:
case lcObjectPropertyId::CameraFar:
@@ -1405,7 +1409,7 @@ bool lcLight::SetKeyFrame(lcObjectPropertyId PropertyId, lcStep Time, bool KeyFr
case lcObjectPropertyId::PieceStepShow:
case lcObjectPropertyId::PieceStepHide:
case lcObjectPropertyId::CameraName:
case lcObjectPropertyId::CameraType:
case lcObjectPropertyId::CameraProjection:
case lcObjectPropertyId::CameraFOV:
case lcObjectPropertyId::CameraNear:
case lcObjectPropertyId::CameraFar:
@@ -1506,3 +1510,59 @@ void lcLight::RemoveKeyFrames()
mPOVRayFadeDistance.RemoveAllKeys();
mPOVRayFadePower.RemoveAllKeys();
}
lcLightHistoryState lcLight::GetHistoryState([[maybe_unused]] const lcModel* Model) const
{
lcLightHistoryState State;
State.Id = mId;
State.Hidden = mHidden;
State.Name = mName;
State.LightType = mLightType;
State.CastShadow = mCastShadow;
State.Position = mPosition;
State.Rotation = mRotation;
State.Color = mColor;
State.BlenderPower = mBlenderPower;
State.BlenderRadius = mBlenderRadius;
State.BlenderAngle = mBlenderAngle;
State.POVRayPower = mPOVRayPower;
State.POVRayFadeDistance = mPOVRayFadeDistance;
State.POVRayFadePower = mPOVRayFadePower;
State.SpotConeAngle = mSpotConeAngle;
State.SpotPenumbraAngle = mSpotPenumbraAngle;
State.POVRaySpotTightness = mPOVRaySpotTightness;
State.AreaShape = mAreaShape;
State.AreaSizeX = mAreaSizeX;
State.AreaSizeY = mAreaSizeY;
State.POVRayAreaGridX = mPOVRayAreaGridX;
State.POVRayAreaGridY = mPOVRayAreaGridY;
return State;
}
void lcLight::SetHistoryState(const lcLightHistoryState& State, [[maybe_unused]] const lcModel* Model)
{
mId = State.Id;
mHidden = State.Hidden;
mName = State.Name;
mLightType = State.LightType;
mCastShadow = State.CastShadow;
mPosition = State.Position;
mRotation = State.Rotation;
mColor = State.Color;
mBlenderPower = State.BlenderPower;
mBlenderRadius = State.BlenderRadius;
mBlenderAngle = State.BlenderAngle;
mPOVRayPower = State.POVRayPower;
mPOVRayFadeDistance = State.POVRayFadeDistance;
mPOVRayFadePower = State.POVRayFadePower;
mSpotConeAngle = State.SpotConeAngle;
mSpotPenumbraAngle = State.SpotPenumbraAngle;
mPOVRaySpotTightness = State.POVRaySpotTightness;
mAreaShape = State.AreaShape;
mAreaSizeX = State.AreaSizeX;
mAreaSizeY = State.AreaSizeY;
mPOVRayAreaGridX = State.POVRayAreaGridX;
mPOVRayAreaGridY = State.POVRayAreaGridY;
}
+42 -64
View File
@@ -3,12 +3,9 @@
#include "object.h"
#include "lc_math.h"
#define LC_LIGHT_HIDDEN 0x0001
#define LC_LIGHT_DISABLED 0x0002
enum lcLightSection : quint32
{
LC_LIGHT_SECTION_INVALID = ~0U,
LC_LIGHT_SECTION_INVALID = LC_OBJECT_SECTION_INVALID,
LC_LIGHT_SECTION_POSITION = 0,
LC_LIGHT_SECTION_TARGET
};
@@ -31,9 +28,47 @@ enum class lcLightAreaShape
Count
};
struct lcLightHistoryState
{
lcObjectId Id;
bool Hidden;
QString Name;
lcLightType LightType;
bool CastShadow;
lcObjectProperty<lcVector3> Position;
lcObjectProperty<lcMatrix33> Rotation;
lcObjectProperty<lcVector3> Color;
lcObjectProperty<float> BlenderPower;
lcObjectProperty<float> BlenderRadius;
lcObjectProperty<float> BlenderAngle;
lcObjectProperty<float> POVRayPower;
lcObjectProperty<float> POVRayFadeDistance;
lcObjectProperty<float> POVRayFadePower;
lcObjectProperty<float> SpotConeAngle;
lcObjectProperty<float> SpotPenumbraAngle;
lcObjectProperty<float> POVRaySpotTightness;
lcLightAreaShape AreaShape;
lcObjectProperty<float> AreaSizeX;
lcObjectProperty<float> AreaSizeY;
lcObjectProperty<int> POVRayAreaGridX;
lcObjectProperty<int> POVRayAreaGridY;
bool operator==(const lcLightHistoryState& Other) const
{
return Id == Other.Id && Hidden == Other.Hidden && Name == Other.Name && LightType == Other.LightType &&
CastShadow == Other.CastShadow && Position == Other.Position && Rotation == Other.Rotation && Color == Other.Color &&
BlenderPower == Other.BlenderPower && BlenderRadius == Other.BlenderRadius && BlenderAngle == Other.BlenderAngle &&
POVRayPower == Other.POVRayPower && POVRayFadeDistance == Other.POVRayFadeDistance && POVRayFadePower == Other.POVRayFadePower &&
SpotConeAngle == Other.SpotConeAngle && SpotPenumbraAngle == Other.SpotPenumbraAngle &&
POVRaySpotTightness == Other.POVRaySpotTightness && AreaShape == Other.AreaShape && AreaSizeX == Other.AreaSizeX &&
AreaSizeY == Other.AreaSizeY && POVRayAreaGridX == Other.POVRayAreaGridX && POVRayAreaGridY == Other.POVRayAreaGridY;
}
};
class lcLight : public lcObject
{
public:
lcLight();
lcLight(const lcVector3& Position, lcLightType LightType);
virtual ~lcLight() = default;
@@ -74,62 +109,6 @@ public:
bool SetLightType(lcLightType LightType);
bool IsSelected() const override
{
return mSelected;
}
bool IsSelected(quint32 Section) const override
{
Q_UNUSED(Section);
return mSelected;
}
void SetSelected(bool Selected) override
{
mSelected = Selected;
if (!Selected)
mFocusedSection = LC_LIGHT_SECTION_INVALID;
}
void SetSelected(quint32 Section, bool Selected) override
{
Q_UNUSED(Section);
mSelected = Selected;
if (!Selected)
mFocusedSection = LC_LIGHT_SECTION_INVALID;
}
bool IsFocused() const override
{
return mFocusedSection != LC_LIGHT_SECTION_INVALID;
}
bool IsFocused(quint32 Section) const override
{
return mFocusedSection == Section;
}
void SetFocused(quint32 Section, bool Focused) override
{
if (Focused)
{
mFocusedSection = Section;
mSelected = true;
}
else
mFocusedSection = LC_LIGHT_SECTION_INVALID;
}
quint32 GetFocusSection() const override
{
return mFocusedSection;
}
quint32 GetAllowedTransforms() const override
{
if (IsPointLight())
@@ -218,13 +197,15 @@ public:
bool HasKeyFrame(lcObjectPropertyId PropertyId, lcStep Time) const override;
bool SetKeyFrame(lcObjectPropertyId PropertyId, lcStep Time, bool KeyFrame) override;
void RemoveKeyFrames() override;
lcLightHistoryState GetHistoryState(const lcModel* Model) const;
void SetHistoryState(const lcLightHistoryState& State, const lcModel* Model);
void InsertTime(lcStep Start, lcStep Time);
void RemoveTime(lcStep Start, lcStep Time);
bool IsVisible() const
{
return (mState & LC_LIGHT_HIDDEN) == 0;
return !mHidden;
}
bool SetColor(const lcVector3& Color, lcStep Step, bool AddKey);
@@ -385,9 +366,6 @@ protected:
lcObjectProperty<int> mPOVRayAreaGridX = lcObjectProperty<int>(2);
lcObjectProperty<int> mPOVRayAreaGridY = lcObjectProperty<int>(2);
quint32 mState = 0;
bool mSelected = false;
quint32 mFocusedSection = LC_LIGHT_SECTION_INVALID;
lcVector3 mTargetMovePosition = lcVector3(0.0f, 0.0f, 0.0f);
lcMatrix44 mWorldMatrix;
+1 -1
View File
@@ -154,7 +154,7 @@ void MinifigWizard::ParseSettings(lcFile& Settings)
int Flags;
if (sscanf(NameEnd, "%d %g %g %g %g %g %g %g %g %g %g %g %g",
&Flags, &Mat[0], &Mat[1], &Mat[2], &Mat[3], &Mat[4], &Mat[5], &Mat[6],
&Flags, &Mat[0], &Mat[1], &Mat[2], &Mat[3], &Mat[4], &Mat[5], &Mat[6],
&Mat[7], &Mat[8], &Mat[9], &Mat[10], &Mat[11]) != 13)
continue;
+32 -23
View File
@@ -1,9 +1,12 @@
#include "lc_global.h"
#include "object.h"
lcObjectId lcObject::mNextId;
lcObject::lcObject(lcObjectType ObjectType)
: mObjectType(ObjectType)
: mObjectType(ObjectType), mId(mNextId)
{
mNextId = static_cast<lcObjectId>(static_cast<uint32_t>(mNextId) + 1);
}
lcObject::~lcObject()
@@ -15,24 +18,30 @@ QString lcObject::GetCheckpointString(lcObjectPropertyId PropertyId)
switch (PropertyId)
{
case lcObjectPropertyId::PieceId:
return QT_TRANSLATE_NOOP("Checkpoint", "Changing Piece Id");
return QT_TRANSLATE_NOOP("Checkpoint", "Change Piece");
case lcObjectPropertyId::PieceColor:
return QT_TRANSLATE_NOOP("Checkpoint", "Changing Piece Color");
return QT_TRANSLATE_NOOP("Checkpoint", "Change Piece Color");
case lcObjectPropertyId::PieceStepShow:
case lcObjectPropertyId::PieceStepHide:
break;
case lcObjectPropertyId::CameraName:
return QT_TRANSLATE_NOOP("Checkpoint", "Renaming Camera");
return QT_TRANSLATE_NOOP("Checkpoint", "Rename Camera");
case lcObjectPropertyId::CameraType:
return QT_TRANSLATE_NOOP("Checkpoint", "Changing Camera Type");
case lcObjectPropertyId::CameraProjection:
return QT_TRANSLATE_NOOP("Checkpoint", "Change Camera Projection");
case lcObjectPropertyId::CameraFOV:
return QT_TRANSLATE_NOOP("Checkpoint", "Change Camera FOV");
case lcObjectPropertyId::CameraNear:
return QT_TRANSLATE_NOOP("Checkpoint", "Change Camera Near Plane");
case lcObjectPropertyId::CameraFar:
return QT_TRANSLATE_NOOP("Checkpoint", "Change Camera Far Plane");
case lcObjectPropertyId::CameraPositionX:
case lcObjectPropertyId::CameraPositionY:
case lcObjectPropertyId::CameraPositionZ:
@@ -45,56 +54,56 @@ QString lcObject::GetCheckpointString(lcObjectPropertyId PropertyId)
break;
case lcObjectPropertyId::LightName:
return QT_TRANSLATE_NOOP("Checkpoint", "Renaming Light");
return QT_TRANSLATE_NOOP("Checkpoint", "Rename Light");
case lcObjectPropertyId::LightType:
return QT_TRANSLATE_NOOP("Checkpoint", "Changing Light Type");
return QT_TRANSLATE_NOOP("Checkpoint", "Change Light Type");
case lcObjectPropertyId::LightColor:
return QT_TRANSLATE_NOOP("Checkpoint", "Changing Light Color");
return QT_TRANSLATE_NOOP("Checkpoint", "Change Light Color");
case lcObjectPropertyId::LightBlenderPower:
return QT_TRANSLATE_NOOP("Checkpoint", "Changing Light Blender Power");
return QT_TRANSLATE_NOOP("Checkpoint", "Change Light Blender Power");
case lcObjectPropertyId::LightPOVRayPower:
return QT_TRANSLATE_NOOP("Checkpoint", "Changing Light POV-Ray Power");
return QT_TRANSLATE_NOOP("Checkpoint", "Change Light POV-Ray Power");
case lcObjectPropertyId::LightCastShadow:
return QT_TRANSLATE_NOOP("Checkpoint", "Changing Light Shadow");
return QT_TRANSLATE_NOOP("Checkpoint", "Change Light Shadow");
case lcObjectPropertyId::LightPOVRayFadeDistance:
return QT_TRANSLATE_NOOP("Checkpoint", "Changing Light POV-Ray Fade Distance");
return QT_TRANSLATE_NOOP("Checkpoint", "Change Light POV-Ray Fade Distance");
case lcObjectPropertyId::LightPOVRayFadePower:
return QT_TRANSLATE_NOOP("Checkpoint", "Changing Light POV-Ray Fade Power");
return QT_TRANSLATE_NOOP("Checkpoint", "Change Light POV-Ray Fade Power");
case lcObjectPropertyId::LightBlenderRadius:
return QT_TRANSLATE_NOOP("Checkpoint", "Changing Light Blender Radius");
return QT_TRANSLATE_NOOP("Checkpoint", "Change Light Blender Radius");
case lcObjectPropertyId::LightBlenderAngle:
return QT_TRANSLATE_NOOP("Checkpoint", "Changing Light Blender Angle");
return QT_TRANSLATE_NOOP("Checkpoint", "Change Light Blender Angle");
case lcObjectPropertyId::LightAreaSizeX:
return QT_TRANSLATE_NOOP("Checkpoint", "Changing Area Light X Size");
return QT_TRANSLATE_NOOP("Checkpoint", "Change Area Light X Size");
case lcObjectPropertyId::LightAreaSizeY:
return QT_TRANSLATE_NOOP("Checkpoint", "Changing Area Light Y Size");
return QT_TRANSLATE_NOOP("Checkpoint", "Change Area Light Y Size");
case lcObjectPropertyId::LightSpotConeAngle:
return QT_TRANSLATE_NOOP("Checkpoint", "Changing Spot Light Cone Angle");
return QT_TRANSLATE_NOOP("Checkpoint", "Change Spot Light Cone Angle");
case lcObjectPropertyId::LightSpotPenumbraAngle:
return QT_TRANSLATE_NOOP("Checkpoint", "Changing Spot Light Penumbra Angle");
return QT_TRANSLATE_NOOP("Checkpoint", "Change Spot Light Penumbra Angle");
case lcObjectPropertyId::LightPOVRaySpotTightness:
return QT_TRANSLATE_NOOP("Checkpoint", "Changing Spot Light POV-Ray Tightness");
return QT_TRANSLATE_NOOP("Checkpoint", "Change Spot Light POV-Ray Tightness");
case lcObjectPropertyId::LightAreaShape:
return QT_TRANSLATE_NOOP("Checkpoint", "Changing Area Light Shape");
return QT_TRANSLATE_NOOP("Checkpoint", "Change Area Light Shape");
case lcObjectPropertyId::LightPOVRayAreaGridX:
case lcObjectPropertyId::LightPOVRayAreaGridY:
return QT_TRANSLATE_NOOP("Checkpoint", "Changing Area Light POV-Ray Grid");
return QT_TRANSLATE_NOOP("Checkpoint", "Change Area Light POV-Ray Grid");
case lcObjectPropertyId::ObjectPositionX:
case lcObjectPropertyId::ObjectPositionY:
+55 -8
View File
@@ -10,6 +10,8 @@ enum class lcObjectType
Light
};
enum class lcObjectId : uint32_t;
struct lcObjectSection
{
lcObject* Object = nullptr;
@@ -55,6 +57,8 @@ struct lcObjectBoxTest
#define LC_OBJECT_TRANSFORM_SCALE_Z 0x400
#define LC_OBJECT_TRANSFORM_SCALE_XYZ (LC_OBJECT_TRANSFORM_SCALE_X | LC_OBJECT_TRANSFORM_SCALE_Y | LC_OBJECT_TRANSFORM_SCALE_Z)
#define LC_OBJECT_SECTION_INVALID 0xffffffff
class lcObject
{
public:
@@ -87,14 +91,49 @@ public:
return mObjectType;
}
virtual bool IsSelected() const = 0;
virtual bool IsSelected(quint32 Section) const = 0;
virtual void SetSelected(bool Selected) = 0;
virtual void SetSelected(quint32 Section, bool Selected) = 0;
virtual bool IsFocused() const = 0;
virtual bool IsFocused(quint32 Section) const = 0;
virtual void SetFocused(quint32 Section, bool Focused) = 0;
virtual quint32 GetFocusSection() const = 0;
lcObjectId GetId() const
{
return mId;
}
bool IsSelected() const
{
return mSelected;
}
void SetSelected(bool Selected)
{
mSelected = Selected;
if (!Selected)
mFocusedSection = LC_OBJECT_SECTION_INVALID;
}
bool IsFocused() const
{
return mFocusedSection != LC_OBJECT_SECTION_INVALID;
}
bool IsFocused(quint32 Section) const
{
return mFocusedSection == Section;
}
void SetFocused(quint32 Section, bool Focused)
{
if (Focused)
{
mFocusedSection = Section;
mSelected = true;
}
else
mFocusedSection = LC_OBJECT_SECTION_INVALID;
}
quint32 GetFocusSection() const
{
return mFocusedSection;
}
virtual void UpdatePosition(lcStep Step) = 0;
virtual quint32 GetAllowedTransforms() const = 0;
@@ -112,4 +151,12 @@ public:
private:
lcObjectType mObjectType;
protected:
bool mHidden = false;
bool mSelected = false;
quint32 mFocusedSection = LC_OBJECT_SECTION_INVALID;
lcObjectId mId = static_cast<lcObjectId>(0);
static lcObjectId mNextId;
};
+94 -22
View File
@@ -15,25 +15,29 @@
#include "lc_qutils.h"
#include "lc_synth.h"
#include "lc_traintrack.h"
#include "lc_string.h"
#include "lc_model.h"
constexpr float LC_PIECE_CONTROL_POINT_SIZE = 10.0f;
lcPiece::lcPiece()
: lcObject(lcObjectType::Piece)
{
}
lcPiece::lcPiece(PieceInfo* Info)
: lcObject(lcObjectType::Piece)
{
SetPieceInfo(Info, QString(), true);
SetPieceInfo(Info, QString(), true, true);
mColorIndex = gDefaultColor;
mColorCode = 16;
mStepShow = 1;
mStepHide = LC_STEP_MAX;
mGroup = nullptr;
mPivotMatrix = lcMatrix44Identity();
}
lcPiece::lcPiece(const lcPiece& Other)
: lcObject(lcObjectType::Piece)
{
SetPieceInfo(Other.mPieceInfo, Other.mID, true);
SetPieceInfo(Other.mPieceInfo, Other.mID, true, true);
mHidden = Other.mHidden;
mSelected = Other.mSelected;
mColorIndex = Other.mColorIndex;
@@ -63,7 +67,7 @@ lcPiece::~lcPiece()
delete mMesh;
}
void lcPiece::SetPieceInfo(PieceInfo* Info, const QString& ID, bool Wait)
void lcPiece::SetPieceInfo(PieceInfo* Info, const QString& ID, bool Wait, bool UpdateSynthInfo)
{
lcPiecesLibrary* Library = lcGetPiecesLibrary();
@@ -78,16 +82,20 @@ void lcPiece::SetPieceInfo(PieceInfo* Info, const QString& ID, bool Wait)
else
mID.clear();
mControlPoints.clear();
delete mMesh;
mMesh = nullptr;
const lcSynthInfo* SynthInfo = mPieceInfo ? mPieceInfo->GetSynthInfo() : nullptr;
if (SynthInfo)
if (UpdateSynthInfo)
{
SynthInfo->GetDefaultControlPoints(mControlPoints);
UpdateMesh();
mControlPoints.clear();
delete mMesh;
mMesh = nullptr;
const lcSynthInfo* SynthInfo = mPieceInfo ? mPieceInfo->GetSynthInfo() : nullptr;
if (SynthInfo)
{
SynthInfo->GetDefaultControlPoints(mControlPoints);
UpdateMesh();
}
}
}
@@ -98,7 +106,7 @@ bool lcPiece::SetPieceId(PieceInfo* Info)
lcPiecesLibrary* Library = lcGetPiecesLibrary();
Library->ReleasePieceInfo(mPieceInfo);
SetPieceInfo(Info, QString(), true);
SetPieceInfo(Info, QString(), true, true);
return true;
}
@@ -310,10 +318,10 @@ bool lcPiece::FileLoad(lcFile& file)
}
else
file.ReadBuffer(name, LC_PIECE_NAME_LEN);
strcat(name, ".dat");
lcstrcat(name, ".dat");
PieceInfo* pInfo = lcGetPiecesLibrary()->FindPiece(name, nullptr, true, false);
SetPieceInfo(pInfo, QString(), true);
SetPieceInfo(pInfo, QString(), true, true);
// 11 (0.77)
if (version < 11)
@@ -679,7 +687,7 @@ QVariant lcPiece::GetPropertyValue(lcObjectPropertyId PropertyId) const
case lcObjectPropertyId::PieceStepShow:
case lcObjectPropertyId::PieceStepHide:
case lcObjectPropertyId::CameraName:
case lcObjectPropertyId::CameraType:
case lcObjectPropertyId::CameraProjection:
case lcObjectPropertyId::CameraFOV:
case lcObjectPropertyId::CameraNear:
case lcObjectPropertyId::CameraFar:
@@ -739,7 +747,7 @@ bool lcPiece::SetPropertyValue(lcObjectPropertyId PropertyId, lcStep Step, bool
case lcObjectPropertyId::PieceStepShow:
case lcObjectPropertyId::PieceStepHide:
case lcObjectPropertyId::CameraName:
case lcObjectPropertyId::CameraType:
case lcObjectPropertyId::CameraProjection:
case lcObjectPropertyId::CameraFOV:
case lcObjectPropertyId::CameraNear:
case lcObjectPropertyId::CameraFar:
@@ -792,7 +800,7 @@ bool lcPiece::HasKeyFrame(lcObjectPropertyId PropertyId, lcStep Time) const
case lcObjectPropertyId::PieceStepShow:
case lcObjectPropertyId::PieceStepHide:
case lcObjectPropertyId::CameraName:
case lcObjectPropertyId::CameraType:
case lcObjectPropertyId::CameraProjection:
case lcObjectPropertyId::CameraFOV:
case lcObjectPropertyId::CameraNear:
case lcObjectPropertyId::CameraFar:
@@ -851,7 +859,7 @@ bool lcPiece::SetKeyFrame(lcObjectPropertyId PropertyId, lcStep Time, bool KeyFr
case lcObjectPropertyId::PieceStepShow:
case lcObjectPropertyId::PieceStepHide:
case lcObjectPropertyId::CameraName:
case lcObjectPropertyId::CameraType:
case lcObjectPropertyId::CameraProjection:
case lcObjectPropertyId::CameraFOV:
case lcObjectPropertyId::CameraNear:
case lcObjectPropertyId::CameraFar:
@@ -907,6 +915,70 @@ void lcPiece::RemoveKeyFrames()
mRotation.RemoveAllKeys();
}
lcPieceHistoryState lcPiece::GetHistoryState(const lcModel* Model) const
{
lcPieceHistoryState State;
State.Id = mId;
State.Hidden = mHidden;
State.FileLine = mFileLine;
State.PieceId = mID;
State.GroupIndex = ~0U;
State.ColorIndex = mColorIndex;
State.ColorCode = mColorCode;
State.StepShow = mStepShow;
State.StepHide = mStepHide;
State.PivotMatrix = mPivotMatrix;
State.PivotPointValid = mPivotPointValid;
State.ControlPoints = mControlPoints;
State.Position = mPosition;
State.Rotation = mRotation;
const std::vector<std::unique_ptr<lcGroup>>& Groups = Model->GetGroups();
if (mGroup)
{
for (size_t GroupIndex = 0; GroupIndex < Groups.size(); GroupIndex++)
{
if (mGroup == Groups[GroupIndex].get())
{
State.GroupIndex = static_cast<uint32_t>(GroupIndex);
break;
}
}
}
return State;
}
void lcPiece::SetHistoryState(const lcPieceHistoryState& State, const lcModel* Model)
{
const std::vector<std::unique_ptr<lcGroup>>& Groups = Model->GetGroups();
mId = State.Id;
mHidden = State.Hidden;
mFileLine = State.FileLine;
mID = State.PieceId;
mGroup = (State.GroupIndex < Groups.size()) ? Groups[State.GroupIndex].get() : nullptr;
mColorIndex = State.ColorIndex;
mColorCode = State.ColorCode;
mStepShow = State.StepShow;
mStepHide = State.StepHide;
mPivotMatrix = State.PivotMatrix;
mPivotPointValid = State.PivotPointValid;
mControlPoints = State.ControlPoints;
mPosition = State.Position;
mRotation = State.Rotation;
PieceInfo* Info = lcGetPiecesLibrary()->FindPiece(mID.toLatin1(), nullptr, true, false);
SetPieceInfo(Info, mID, true, false);
UpdateMesh();
// std::vector<bool> mTrainTrackConnections;
}
void lcPiece::AddMainModelRenderMeshes(lcScene* Scene, bool Highlight, bool Fade) const
{
lcRenderMeshState RenderMeshState = lcRenderMeshState::Default;
+44 -68
View File
@@ -10,7 +10,7 @@ class PieceInfo;
enum lcPieceSection : quint32
{
LC_PIECE_SECTION_INVALID = ~0U,
LC_PIECE_SECTION_INVALID = LC_OBJECT_SECTION_INVALID,
LC_PIECE_SECTION_POSITION = 0,
LC_PIECE_SECTION_CONTROL_POINT_FIRST,
LC_PIECE_SECTION_CONTROL_POINT_LAST = LC_PIECE_SECTION_CONTROL_POINT_FIRST + LC_MAX_CONTROL_POINTS - 1,
@@ -21,75 +21,52 @@ struct lcPieceControlPoint
{
lcMatrix44 Transform;
float Scale;
bool operator==(const lcPieceControlPoint& Other) const
{
return Transform == Other.Transform && Scale == Other.Scale;
}
};
struct lcPieceHistoryState
{
lcObjectId Id;
bool Hidden;
int FileLine;
QString PieceId;
uint32_t GroupIndex;
int ColorIndex;
quint32 ColorCode;
lcStep StepShow;
lcStep StepHide;
lcMatrix44 PivotMatrix;
bool PivotPointValid;
std::vector<lcPieceControlPoint> ControlPoints;
lcObjectProperty<lcVector3> Position;
lcObjectProperty<lcMatrix33> Rotation;
bool operator==(const lcPieceHistoryState& Other) const
{
return Id == Other.Id && Hidden == Other.Hidden && FileLine == Other.FileLine && PieceId == Other.PieceId &&
GroupIndex == Other.GroupIndex && ColorIndex == Other.ColorIndex && ColorCode == Other.ColorCode &&
StepShow == Other.StepShow && StepHide == Other.StepHide && PivotMatrix == Other.PivotMatrix &&
PivotPointValid == Other.PivotPointValid && ControlPoints == Other.ControlPoints &&
Position == Other.Position && Rotation == Other.Rotation;
}
};
class lcPiece : public lcObject
{
public:
lcPiece();
lcPiece(PieceInfo* Info);
lcPiece(const lcPiece& Other);
~lcPiece();
virtual ~lcPiece();
lcPiece(lcPiece&&) = delete;
lcPiece& operator=(const lcPiece&) = delete;
lcPiece& operator=(lcPiece&&) = delete;
bool IsSelected() const override
{
return mSelected;
}
bool IsSelected(quint32 Section) const override
{
Q_UNUSED(Section);
return mSelected;
}
void SetSelected(bool Selected) override
{
mSelected = Selected;
if (!Selected)
mFocusedSection = LC_PIECE_SECTION_INVALID;
}
void SetSelected(quint32 Section, bool Selected) override
{
Q_UNUSED(Section);
mSelected = Selected;
if (!Selected)
mFocusedSection = LC_PIECE_SECTION_INVALID;
}
bool IsFocused() const override
{
return mFocusedSection != LC_PIECE_SECTION_INVALID;
}
bool IsFocused(quint32 Section) const override
{
return mFocusedSection == Section;
}
void SetFocused(quint32 Section, bool Focused) override
{
if (Focused)
{
mFocusedSection = Section;
mSelected = true;
}
else
mFocusedSection = LC_PIECE_SECTION_INVALID;
}
quint32 GetFocusSection() const override
{
return mFocusedSection;
}
quint32 GetAllowedTransforms() const override;
lcVector3 GetSectionPosition(quint32 Section) const override;
@@ -114,6 +91,8 @@ public:
bool HasKeyFrame(lcObjectPropertyId PropertyId, lcStep Time) const override;
bool SetKeyFrame(lcObjectPropertyId PropertyId, lcStep Time, bool KeyFrame) override;
void RemoveKeyFrames() override;
lcPieceHistoryState GetHistoryState(const lcModel* Model) const;
void SetHistoryState(const lcPieceHistoryState& State, const lcModel* Model);
void AddMainModelRenderMeshes(lcScene* Scene, bool Highlight, bool Fade) const;
void AddSubModelRenderMeshes(lcScene* Scene, const lcMatrix44& WorldMatrix, int DefaultColorIndex, lcRenderMeshState RenderMeshState, bool ParentActive) const;
@@ -180,7 +159,7 @@ public:
void Initialize(const lcMatrix44& WorldMatrix, lcStep Step);
const lcBoundingBox& GetBoundingBox() const;
void CompareBoundingBox(lcVector3& Min, lcVector3& Max) const;
void SetPieceInfo(PieceInfo* Info, const QString& ID, bool Wait);
void SetPieceInfo(PieceInfo* Info, const QString& ID, bool Wait, bool UpdateSynthInfo);
bool SetPieceId(PieceInfo* Info);
bool FileLoad(lcFile& file);
@@ -204,7 +183,7 @@ public:
mGroup = Group;
}
lcGroup* GetGroup()
lcGroup* GetGroup() const
{
return mGroup;
}
@@ -292,10 +271,10 @@ public:
}
public:
PieceInfo* mPieceInfo;
PieceInfo* mPieceInfo = nullptr;
lcMatrix44 mModelWorld;
lcMatrix44 mPivotMatrix;
lcMatrix44 mPivotMatrix = lcMatrix44Identity();
protected:
void UpdateMesh();
@@ -318,18 +297,15 @@ protected:
int mFileLine = -1;
QString mID;
lcGroup* mGroup;
lcGroup* mGroup = nullptr;
int mColorIndex;
quint32 mColorCode;
lcStep mStepShow;
lcStep mStepHide;
lcStep mStepShow = 1;
lcStep mStepHide = LC_STEP_MAX;
bool mPivotPointValid = false;
bool mHidden = false;
bool mSelected = false;
quint32 mFocusedSection = LC_PIECE_SECTION_INVALID;
std::vector<lcPieceControlPoint> mControlPoints;
std::vector<bool> mTrainTrackConnections;
lcMesh* mMesh = nullptr;
+65 -59
View File
@@ -1,7 +1,6 @@
#include "lc_global.h"
#include "lc_math.h"
#include "lc_mesh.h"
#include <locale.h>
#include "pieceinf.h"
#include "camera.h"
#include "project.h"
@@ -18,6 +17,8 @@
#include "lc_qimagedialog.h"
#include "lc_modellistdialog.h"
#include "lc_bricklink.h"
#include "lc_string.h"
#include "lc_colors.h"
lcHTMLExportOptions::lcHTMLExportOptions(const Project* Project)
{
@@ -267,10 +268,12 @@ lcModel* Project::CreateNewModel(bool ShowModel)
SetActiveModel(mModels.back().get(), true);
lcView* ActiveView = gMainWindow ? gMainWindow->GetActiveView() : nullptr;
if (ActiveView)
ActiveView->GetCamera()->SetViewpoint(lcViewpoint::Home);
gMainWindow->UpdateTitle();
if (gMainWindow)
gMainWindow->UpdateTitle();
}
else
SetActiveModel(mActiveModel, true);
@@ -839,7 +842,7 @@ bool Project::Export3DStudio(const QString& FileName)
{
lcColor* Color = &gColorList[ColorIdx];
sprintf(MaterialName, "Material%03d", (int)ColorIdx);
snprintf(MaterialName, sizeof(MaterialName), "Material%03d", (int)ColorIdx);
long MaterialStart = File.GetPosition();
File.WriteU16(0xAFFF); // CHK_MAT_ENTRY
@@ -1092,7 +1095,7 @@ bool Project::Export3DStudio(const QString& FileName)
File.WriteU32(0);
char Name[32];
sprintf(Name, "Piece%.3d", NumPieces);
snprintf(Name, sizeof(Name), "Piece%.3d", NumPieces);
NumPieces++;
File.WriteBuffer(Name, strlen(Name) + 1);
@@ -1180,7 +1183,7 @@ bool Project::Export3DStudio(const QString& FileName)
File.WriteU16(0x4130); // CHK_MSH_MAT_GROUP
File.WriteU32(6 + MaterialNameLength + 1 + 2 + 2 * Section->NumIndices / 3);
sprintf(MaterialName, "Material%03d", MaterialIndex);
snprintf(MaterialName, sizeof(MaterialName), "Material%03d", MaterialIndex);
File.WriteBuffer(MaterialName, MaterialNameLength + 1);
File.WriteU16(Section->NumIndices / 3);
@@ -1565,7 +1568,7 @@ bool Project::ExportCSV(const QString& FileName)
std::string Description = Info->m_strDescription;
Description.erase(std::remove(Description.begin(), Description.end(), ','), Description.end());
sprintf(Line, "\"%s\",\"%s\",%d,%s,%d\n", Description.c_str(), gColorList[ColorIt.first].Name, ColorIt.second, Info->mFileName, gColorList[ColorIt.first].Code);
snprintf(Line, sizeof(Line), "\"%s\",\"%s\",%d,%s,%d\n", Description.c_str(), gColorList[ColorIt.first].Name, ColorIt.second, Info->mFileName, gColorList[ColorIt.first].Code);
CSVFile.WriteLine(Line);
}
}
@@ -1840,7 +1843,7 @@ std::pair<bool, QString> Project::ExportPOVRay(const QString& FileName)
char Line[2048];
sprintf(Line, "// Generated By: LeoCAD %s\n// LDraw File: %s\n// Date: %s\n\n",
snprintf(Line, sizeof(Line), "// Generated By: LeoCAD %s\n// LDraw File: %s\n// Date: %s\n\n",
LC_VERSION_TEXT,
mModels[0]->GetProperties().mFileName.toLatin1().constData(),
QDateTime::currentDateTime().toString(Qt::ISODate).toLatin1().constData());
@@ -1895,22 +1898,23 @@ std::pair<bool, QString> Project::ExportPOVRay(const QString& FileName)
lcVector3 FloorColor = POVRayOptions.FloorColor;
float FloorAmbient = POVRayOptions.FloorAmbient;
float FloorDiffuse = POVRayOptions.FloorDiffuse;
char FloorLocation[32];
char FloorAxis[16];
const char* FloorLocation;
const char* FloorAxis;
if (POVRayOptions.FloorAxis == 0)
{
sprintf(FloorAxis, "x");
sprintf(FloorLocation, "MaxX");
FloorAxis = "x";
FloorLocation = "MaxX";
}
else if (POVRayOptions.FloorAxis == 1)
{
sprintf(FloorAxis, "y");
sprintf(FloorLocation, "MaxY");
FloorAxis = "y";
FloorLocation = "MaxY";
}
else
{
sprintf(FloorAxis, "z");
sprintf(FloorLocation, "MaxZ");
FloorAxis = "z";
FloorLocation = "MaxZ";
}
for (const std::unique_ptr<lcLight>& Light : Lights)
@@ -1929,11 +1933,11 @@ std::pair<bool, QString> Project::ExportPOVRay(const QString& FileName)
if (!POVRayOptions.HeaderIncludeFile.isEmpty())
{
sprintf(Line, "#include \"%s\"\n\n", POVRayOptions.HeaderIncludeFile.toLatin1().constData());
snprintf(Line, sizeof(Line), "#include \"%s\"\n\n", POVRayOptions.HeaderIncludeFile.toLatin1().constData());
POVFile.WriteLine(Line);
}
sprintf(Line,
snprintf(Line, sizeof(Line),
"#ifndef (MinX) #declare MinX = %g; #end\n"
"#ifndef (MinY) #declare MinY = %g; #end\n"
"#ifndef (MinZ) #declare MinZ = %g; #end\n"
@@ -1947,19 +1951,19 @@ std::pair<bool, QString> Project::ExportPOVRay(const QString& FileName)
"#ifndef (Radius) #declare Radius = %g; #end\n",
Min[0], Min[1], Min[2], Max[0], -Max[1], Max[2], Center[0], Center[1], Center[2], Radius);
POVFile.WriteLine(Line);
sprintf(Line,
snprintf(Line, sizeof(Line),
"#ifndef (CameraSky) #declare CameraSky = <%g,%g,%g>; #end\n"
"#ifndef (CameraLocation) #declare CameraLocation = <%g, %g, %g>; #end\n"
"#ifndef (CameraTarget) #declare CameraTarget = <%g, %g, %g>; #end\n"
"#ifndef (CameraAngle) #declare CameraAngle = %g; #end\n",
Up[1], Up[0], Up[2], Position[1] / 25.0f, Position[0] / 25.0f, Position[2] / 25.0f, Target[1] / 25.0f, Target[0] / 25.0f, Target[2] / 25.0f, Camera->m_fovy);
POVFile.WriteLine(Line);
sprintf(Line,
snprintf(Line, sizeof(Line),
"#ifndef (BackgroundColor) #declare BackgroundColor = <%1g, %1g, %1g>; #end\n"
"#ifndef (Background) #declare Background = %s; #end\n",
BackgroundColor[0], BackgroundColor[1], BackgroundColor[2], (POVRayOptions.ExcludeBackground ? "false" : "true"));
POVFile.WriteLine(Line);
sprintf(Line,
snprintf(Line, sizeof(Line),
"#ifndef (FloorAxis) #declare FloorAxis = %s; #end\n"
"#ifndef (FloorLocation) #declare FloorLocation = %s; #end\n"
"#ifndef (FloorColor) #declare FloorColor = <%1g, %1g, %1g>; #end\n"
@@ -1968,7 +1972,7 @@ std::pair<bool, QString> Project::ExportPOVRay(const QString& FileName)
"#ifndef (Floor) #declare Floor = %s; #end\n",
FloorAxis, FloorLocation, FloorColor[0], FloorColor[1], FloorColor[2], FloorAmbient, FloorDiffuse, (POVRayOptions.ExcludeFloor ? "false" : "true"));
POVFile.WriteLine(Line);
sprintf(Line,
snprintf(Line, sizeof(Line),
"#ifndef (Ambient) #declare Ambient = 0.4; #end\n"
"#ifndef (Diffuse) #declare Diffuse = 0.4; #end\n"
"#ifndef (Reflection) #declare Reflection = 0.08; #end\n"
@@ -1987,7 +1991,7 @@ std::pair<bool, QString> Project::ExportPOVRay(const QString& FileName)
"#ifndef (OpaqueNormal) #declare OpaqueNormal = normal { bumps 0.001 scale 0.5 }; #end\n"
"#ifndef (TransNormal) #declare TransNormal = normal { bumps 0.001 scale 0.5 }; #end\n");
POVFile.WriteLine(Line);
sprintf(Line,
snprintf(Line, sizeof(Line),
"#ifndef (Quality) #declare Quality = 3; #end\n"
"#ifndef (Studs) #declare Studs = 1; #end\n"
"#ifndef (LgeoLibrary) #declare LgeoLibrary = %s; #end\n"
@@ -1996,7 +2000,7 @@ std::pair<bool, QString> Project::ExportPOVRay(const QString& FileName)
(POVRayOptions.UseLGEO ? "true" : "false"), (POVRayOptions.NoReflection ? 0 : 1), (POVRayOptions.NoShadow ? 0 : 1));
POVFile.WriteLine(Line);
sprintf(Line,
snprintf(Line, sizeof(Line),
"#ifndef (SkipWriteLightMacro)\n"
"#macro WriteLight(Type, Shadowless, Location, Target, Color, Power, FadeDistance, FadePower, SpotRadius, SpotFalloff, SpotTightness, AreaCircle, AreaWidth, AreaHeight, AreaRows, AreaColumns)\n"
" #local PointLight = %i;\n"
@@ -2048,7 +2052,7 @@ std::pair<bool, QString> Project::ExportPOVRay(const QString& FileName)
{
if (!ColorMacros.contains("TranslucentColor"))
{
sprintf(Line,
snprintf(Line, sizeof(Line),
"#ifndef (SkipTranslucentColorMacro)\n"
"#macro TranslucentColor(r, g, b, f)\n"
" material {\n"
@@ -2070,7 +2074,7 @@ std::pair<bool, QString> Project::ExportPOVRay(const QString& FileName)
{
if (!ColorMacros.contains("ChromeColor"))
{
sprintf(Line,
snprintf(Line, sizeof(Line),
"#ifndef (SkipChromeColorMacro)\n"
"#macro ChromeColor(r, g, b)\n"
"#if (LgeoLibrary) material { #end\n"
@@ -2090,7 +2094,7 @@ std::pair<bool, QString> Project::ExportPOVRay(const QString& FileName)
{
if (!ColorMacros.contains("RubberColor"))
{
sprintf(Line,
snprintf(Line, sizeof(Line),
"#ifndef (SkipRubberColorMacro)\n"
"#macro RubberColor(r, g, b)\n"
"#if (LgeoLibrary) material { #end\n"
@@ -2110,7 +2114,7 @@ std::pair<bool, QString> Project::ExportPOVRay(const QString& FileName)
{
if (!ColorMacros.contains("OpaqueColor"))
{
sprintf(Line,
snprintf(Line, sizeof(Line),
"#ifndef (SkipOpaqueColorMacro)\n"
"#macro OpaqueColor(r, g, b)\n"
"#if (LgeoLibrary) material { #end\n"
@@ -2129,10 +2133,10 @@ std::pair<bool, QString> Project::ExportPOVRay(const QString& FileName)
}
}
sprintf(Line, "#if (Background)\n background {\n color rgb BackgroundColor\n }\n#end\n\n");
snprintf(Line, sizeof(Line), "#if (Background)\n background {\n color rgb BackgroundColor\n }\n#end\n\n");
POVFile.WriteLine(Line);
sprintf(Line, "#ifndef (Skip%s)\n camera {\n perspective\n right x * image_width / image_height\n sky CameraSky\n location CameraLocation\n look_at CameraTarget\n angle CameraAngle * image_width / image_height\n }\n#end\n\n",
snprintf(Line, sizeof(Line), "#ifndef (Skip%s)\n camera {\n perspective\n right x * image_width / image_height\n sky CameraSky\n location CameraLocation\n look_at CameraTarget\n angle CameraAngle * image_width / image_height\n }\n#end\n\n",
(CameraName.isEmpty() ? "Camera" : CameraName.toLatin1().constData()));
POVFile.WriteLine(Line);
@@ -2155,7 +2159,8 @@ std::pair<bool, QString> Project::ExportPOVRay(const QString& FileName)
for (int Idx = 0; Idx < 4; Idx++)
{
Power = Idx < 2 ? 0.75f : 0.5f;
sprintf(Line,"#ifndef (SkipLight%i)\nWriteLight(%i, %i, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, %g, %g, %g, %g, %g, %g, %i, <%g, %g, %g>, <%g, %g, %g>, %i, %i)\n#end\n\n",
snprintf(Line, sizeof(Line),
"#ifndef (SkipLight%i)\nWriteLight(%i, %i, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, %g, %g, %g, %g, %g, %g, %i, <%g, %g, %g>, <%g, %g, %g>, %i, %i)\n#end\n\n",
Idx,
static_cast<int>(LightType),
Shadowless,
@@ -2190,7 +2195,8 @@ std::pair<bool, QString> Project::ExportPOVRay(const QString& FileName)
AreaY = lcVector3(Light->GetWorldMatrix()[1]) * Light->GetAreaSizeY();
AreaGrid = lcVector2i(Light->GetAreaPOVRayGridX(), Light->GetAreaPOVRayGridY());
sprintf(Line,"#ifndef (Skip%s)\n WriteLight(%i, %i, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, %g, %g, %g, %g, %g, %g, %i, <%g, %g, %g>, <%g, %g, %g>, %i, %i)\n#end\n\n",
snprintf(Line, sizeof(Line),
"#ifndef (Skip%s)\n WriteLight(%i, %i, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, %g, %g, %g, %g, %g, %g, %i, <%g, %g, %g>, <%g, %g, %g>, %i, %i)\n#end\n\n",
LightName.toLatin1().constData(),
static_cast<int>(LightType),
Shadowless,
@@ -2233,7 +2239,7 @@ std::pair<bool, QString> Project::ExportPOVRay(const QString& FileName)
if (sscanf(Line,"%128s%128s%10s", Src, Dst, Flags) != 3)
continue;
strcat(Src, ".dat");
lcstrcat(Src, ".dat");
PieceInfo* Info = Library->FindPiece(Src, nullptr, false, false);
if (!Info)
@@ -2245,14 +2251,14 @@ std::pair<bool, QString> Project::ExportPOVRay(const QString& FileName)
{
std::pair<char[LC_PIECE_NAME_LEN + 1], int>& Entry = PieceTable[Info];
Entry.second |= LGEO_PIECE_LGEO;
sprintf(Entry.first, "lg_%s", Dst);
snprintf(Entry.first, sizeof(Entry.first), "lg_%s", Dst);
}
if (strchr(Flags, 'A') && !LgeoPartFound)
{
std::pair<char[LC_PIECE_NAME_LEN + 1], int>& Entry = PieceTable[Info];
Entry.second |= LGEO_PIECE_AR;
sprintf(Entry.first, "ar_%s", Dst);
snprintf(Entry.first, sizeof(Entry.first), "ar_%s", Dst);
}
if (strchr(Flags, 'S'))
@@ -2296,14 +2302,14 @@ std::pair<bool, QString> Project::ExportPOVRay(const QString& FileName)
if (LgeoColorTable[ColorIndex].empty())
{
sprintf(ColorTable[ColorIndex].data(), "lc_%s", Color->SafeName);
snprintf(ColorTable[ColorIndex].data(), ColorTable[ColorIndex].size(), "lc_%s", Color->SafeName);
if (lcIsColorTranslucent(ColorIndex))
{
if (!UseLGEO && !MaterialColors.contains(ColorTable[ColorIndex].data()))
MaterialColors.append(ColorTable[ColorIndex].data());
sprintf(Line, "#ifndef (lc_%s)\n#declare lc_%s = TranslucentColor(%g, %g, %g, TransFilter)\n#end\n\n",
snprintf(Line, sizeof(Line), "#ifndef (lc_%s)\n#declare lc_%s = TranslucentColor(%g, %g, %g, TransFilter)\n#end\n\n",
Color->SafeName, Color->SafeName, Color->Value[0], Color->Value[1], Color->Value[2]);
}
else
@@ -2317,14 +2323,14 @@ std::pair<bool, QString> Project::ExportPOVRay(const QString& FileName)
else
MacroName = "Opaque";
sprintf(Line, "#ifndef (lc_%s)\n#declare lc_%s = %sColor(%g, %g, %g)\n#end\n\n", Color->SafeName, Color->SafeName, MacroName, Color->Value[0], Color->Value[1], Color->Value[2]);
snprintf(Line, sizeof(Line), "#ifndef (lc_%s)\n#declare lc_%s = %sColor(%g, %g, %g)\n#end\n\n", Color->SafeName, Color->SafeName, MacroName, Color->Value[0], Color->Value[1], Color->Value[2]);
}
}
else
{
sprintf(ColorTable[ColorIndex].data(), "LDXColor%i", Color->Code);
snprintf(ColorTable[ColorIndex].data(), ColorTable[ColorIndex].size(), "LDXColor%i", Color->Code);
sprintf(Line,"#ifndef (LDXColor%i) // %s\n#declare LDXColor%i = material { texture { %s } }\n#end\n\n",
snprintf(Line, sizeof(Line), "#ifndef (LDXColor%i) // %s\n#declare LDXColor%i = material { texture { %s } }\n#end\n\n",
Color->Code, Color->Name, Color->Code, LgeoColorTable[ColorIndex].c_str());
}
@@ -2361,7 +2367,7 @@ std::pair<bool, QString> Project::ExportPOVRay(const QString& FileName)
const std::pair<char[LC_PIECE_NAME_LEN + 1], int>& Entry = Search->second;
if (Entry.first[0])
{
sprintf(Line, "#include \"%s.inc\" // %s\n", Entry.first, ModelPart.Info->m_strDescription);
snprintf(Line, sizeof(Line), "#include \"%s.inc\" // %s\n", Entry.first, ModelPart.Info->m_strDescription);
POVFile.WriteLine(Line);
}
}
@@ -2386,7 +2392,7 @@ std::pair<bool, QString> Project::ExportPOVRay(const QString& FileName)
if (ModelPart.Mesh)
{
char Suffix[32];
sprintf(Suffix, "_%p", ModelPart.Mesh);
snprintf(Suffix, sizeof(Suffix), "_%p", ModelPart.Mesh);
strncat(Name, Suffix, sizeof(Name) - strlen(Name) - 1);
Name[sizeof(Name) - 1] = 0;
}
@@ -2408,18 +2414,18 @@ std::pair<bool, QString> Project::ExportPOVRay(const QString& FileName)
if (!ModelPart.Mesh)
{
std::pair<char[LC_PIECE_NAME_LEN + 1], int>& Entry = PieceTable[ModelPart.Info];
strcpy(Entry.first, "lc_");
lcstrcpy(Entry.first, "lc_");
strncat(Entry.first, Name, sizeof(Entry.first) - 1);
Entry.first[sizeof(Entry.first) - 1] = 0;
}
Mesh->ExportPOVRay(POVFile, Name, &ColorTablePointer[0]);
sprintf(Line, "#declare lc_%s_clear = lc_%s\n\n", Name, Name);
snprintf(Line, sizeof(Line), "#declare lc_%s_clear = lc_%s\n\n", Name, Name);
POVFile.WriteLine(Line);
}
sprintf(Line, "#declare %s = union {\n", TopModelName.toLatin1().constData());
snprintf(Line, sizeof(Line), "#declare %s = union {\n", TopModelName.toLatin1().constData());
POVFile.WriteLine(Line);
for (const lcModelPartsEntry& ModelPart : ModelParts)
@@ -2429,16 +2435,16 @@ std::pair<bool, QString> Project::ExportPOVRay(const QString& FileName)
const float* f = ModelPart.WorldMatrix.GetFloats();
char Modifier[32];
if (UseLGEO || MaterialColors.contains(ColorTable[ColorIdx].data()))
sprintf(Modifier, "material");
snprintf(Modifier, sizeof(Modifier), "material");
else
sprintf(Modifier, "texture");
snprintf(Modifier, sizeof(Modifier), "texture");
if (!ModelPart.Mesh)
{
std::pair<char[LC_PIECE_NAME_LEN + 1], int>& Entry = PieceTable[ModelPart.Info];
if (Entry.second & LGEO_PIECE_SLOPE)
{
sprintf(Line,
snprintf(Line, sizeof(Line),
" merge {\n object {\n %s%s\n %s { %s }\n }\n"
" object {\n %s_slope\n texture {\n %s normal { bumps 0.3 scale 0.02 }\n }\n }\n"
" matrix <%g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g>\n }\n",
@@ -2450,7 +2456,7 @@ std::pair<bool, QString> Project::ExportPOVRay(const QString& FileName)
if (!ModelPart.Info || !ModelPart.Info->GetMesh())
continue;
sprintf(Line, " object {\n %s%s\n %s { %s }\n matrix <%g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g>\n }\n",
snprintf(Line, sizeof(Line), " object {\n %s%s\n %s { %s }\n matrix <%g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g>\n }\n",
Entry.first, Suffix, Modifier, ColorTable[ColorIdx].data(), -f[5], -f[4], -f[6], -f[1], -f[0], -f[2], f[9], f[8], f[10], f[13] / 25.0f, f[12] / 25.0f, f[14] / 25.0f);
}
@@ -2460,26 +2466,26 @@ std::pair<bool, QString> Project::ExportPOVRay(const QString& FileName)
char Name[LC_PIECE_NAME_LEN];
GetMeshName(ModelPart, Name);
sprintf(Line, " object {\n lc_%s%s\n %s { %s }\n matrix <%g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g>\n }\n",
snprintf(Line, sizeof(Line), " object {\n lc_%s%s\n %s { %s }\n matrix <%g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g>\n }\n",
Name, Suffix, Modifier, ColorTable[ColorIdx].data(), -f[5], -f[4], -f[6], -f[1], -f[0], -f[2], f[9], f[8], f[10], f[13] / 25.0f, f[12] / 25.0f, f[14] / 25.0f);
}
POVFile.WriteLine(Line);
}
sprintf(Line, "\n #if (ModelReflection = 0)\n no_reflection\n #end\n #if (ModelShadow = 0)\n no_shadow\n #end\n}\n\n");
snprintf(Line, sizeof(Line), "\n #if (ModelReflection = 0)\n no_reflection\n #end\n #if (ModelShadow = 0)\n no_shadow\n #end\n}\n\n");
POVFile.WriteLine(Line);
sprintf(Line, "object {\n %s\n %s { %s }\n}\n\n",
snprintf(Line, sizeof(Line), "object {\n %s\n %s { %s }\n}\n\n",
TopModelName.toLatin1().constData(), (UseLGEO ? "material" : "texture"), ColorTable[lcGetColorIndex(TopModelColorCode)].data());
POVFile.WriteLine(Line);
sprintf(Line, "#if (Floor)\n object {\n plane { FloorAxis, FloorLocation hollow }\n texture {\n pigment { color srgb FloorColor }\n finish { emission 0 ambient FloorAmbient diffuse FloorDiffuse }\n }\n }\n#end\n");
snprintf(Line, sizeof(Line), "#if (Floor)\n object {\n plane { FloorAxis, FloorLocation hollow }\n texture {\n pigment { color srgb FloorColor }\n finish { emission 0 ambient FloorAmbient diffuse FloorDiffuse }\n }\n }\n#end\n");
POVFile.WriteLine(Line);
if (!POVRayOptions.FooterIncludeFile.isEmpty())
{
sprintf(Line, "\n#include \"%s\"\n", POVRayOptions.FooterIncludeFile.toLatin1().constData());
snprintf(Line, sizeof(Line), "\n#include \"%s\"\n", POVRayOptions.FooterIncludeFile.toLatin1().constData());
POVFile.WriteLine(Line);
}
@@ -2517,7 +2523,7 @@ bool Project::ExportWavefront(const QString& FileName)
QFileInfo SaveInfo(SaveFileName);
QString MaterialFileName = QDir(SaveInfo.absolutePath()).absoluteFilePath(SaveInfo.completeBaseName() + QLatin1String(".mtl"));
sprintf(Line, "#\n\nmtllib %s\n\n", QFileInfo(MaterialFileName).fileName().toLatin1().constData());
snprintf(Line, sizeof(Line), "#\n\nmtllib %s\n\n", QFileInfo(MaterialFileName).fileName().toLatin1().constData());
OBJFile.WriteLine(Line);
lcDiskFile MaterialFile(MaterialFileName);
@@ -2531,9 +2537,9 @@ bool Project::ExportWavefront(const QString& FileName)
for (const lcColor& Color : gColorList)
{
if (Color.Translucent)
sprintf(Line, "newmtl %s\nKd %.2f %.2f %.2f\nD %.2f\n\n", Color.SafeName, Color.Value[0], Color.Value[1], Color.Value[2], Color.Value[3]);
snprintf(Line, sizeof(Line), "newmtl %s\nKd %.2f %.2f %.2f\nD %.2f\n\n", Color.SafeName, Color.Value[0], Color.Value[1], Color.Value[2], Color.Value[3]);
else
sprintf(Line, "newmtl %s\nKd %.2f %.2f %.2f\n\n", Color.SafeName, Color.Value[0], Color.Value[1], Color.Value[2]);
snprintf(Line, sizeof(Line), "newmtl %s\nKd %.2f %.2f %.2f\n\n", Color.SafeName, Color.Value[0], Color.Value[1], Color.Value[2]);
MaterialFile.WriteLine(Line);
}
@@ -2550,7 +2556,7 @@ bool Project::ExportWavefront(const QString& FileName)
for (int VertexIdx = 0; VertexIdx < Mesh->mNumVertices; VertexIdx++)
{
lcVector3 Vertex = lcMul31(Verts[VertexIdx].Position, ModelWorld);
sprintf(Line, "v %.2f %.2f %.2f\n", Vertex[0], Vertex[1], Vertex[2]);
snprintf(Line, sizeof(Line), "v %.2f %.2f %.2f\n", Vertex[0], Vertex[1], Vertex[2]);
OBJFile.WriteLine(Line);
}
@@ -2570,7 +2576,7 @@ bool Project::ExportWavefront(const QString& FileName)
for (int VertexIdx = 0; VertexIdx < Mesh->mNumVertices; VertexIdx++)
{
lcVector3 Normal = lcMul30(lcUnpackNormal(Verts[VertexIdx].Normal), ModelWorld);
sprintf(Line, "vn %.2f %.2f %.2f\n", Normal[0], Normal[1], Normal[2]);
snprintf(Line, sizeof(Line), "vn %.2f %.2f %.2f\n", Normal[0], Normal[1], Normal[2]);
OBJFile.WriteLine(Line);
}
@@ -2580,7 +2586,7 @@ bool Project::ExportWavefront(const QString& FileName)
int NumPieces = 0;
for (const lcModelPartsEntry& ModelPart : ModelParts)
{
sprintf(Line, "g Piece%.3d\n", NumPieces++);
snprintf(Line, sizeof(Line), "g Piece%.3d\n", NumPieces++);
OBJFile.WriteLine(Line);
lcMesh* Mesh = !ModelPart.Mesh ? ModelPart.Info->GetMesh() : ModelPart.Mesh;
+9 -7
View File
@@ -175,6 +175,8 @@ void TexFont::PrintText(lcContext* Context, float Left, float Top, float Z, cons
while (*Text)
{
int ch = *Text;
float Right = Left + mGlyphs[ch].width;
float Bottom = Top - mFontHeight;
*CurVert++ = Left;
*CurVert++ = Top;
@@ -183,24 +185,24 @@ void TexFont::PrintText(lcContext* Context, float Left, float Top, float Z, cons
*CurVert++ = mGlyphs[ch].top;
*CurVert++ = Left;
*CurVert++ = Top - mFontHeight;
*CurVert++ = Bottom;
*CurVert++ = Z;
*CurVert++ = mGlyphs[ch].left;
*CurVert++ = mGlyphs[ch].bottom;
*CurVert++ = Left + mGlyphs[ch].width;
*CurVert++ = Top - mFontHeight;
*CurVert++ = Right;
*CurVert++ = Bottom;
*CurVert++ = Z;
*CurVert++ = mGlyphs[ch].right;
*CurVert++ = mGlyphs[ch].bottom;
*CurVert++ = Left + mGlyphs[ch].width;
*CurVert++ = Top - mFontHeight;
*CurVert++ = Right;
*CurVert++ = Bottom;
*CurVert++ = Z;
*CurVert++ = mGlyphs[ch].right;
*CurVert++ = mGlyphs[ch].bottom;
*CurVert++ = Left + mGlyphs[ch].width;
*CurVert++ = Right;
*CurVert++ = Top;
*CurVert++ = Z;
*CurVert++ = mGlyphs[ch].right;
@@ -212,7 +214,7 @@ void TexFont::PrintText(lcContext* Context, float Left, float Top, float Z, cons
*CurVert++ = mGlyphs[ch].left;
*CurVert++ = mGlyphs[ch].top;
Left += mGlyphs[ch].width;
Left = Right;
Text++;
}
+4 -1
View File
@@ -207,6 +207,7 @@ SOURCES += \
common/lc_meshloader.cpp \
common/lc_minifigdialog.cpp \
common/lc_model.cpp \
common/lc_modelaction.cpp \
common/lc_modellistdialog.cpp \
common/lc_objectproperty.cpp \
common/lc_pagesetupdialog.cpp \
@@ -218,6 +219,7 @@ SOURCES += \
common/lc_propertieswidget.cpp \
common/lc_scene.cpp \
common/lc_shortcuts.cpp \
common/lc_string.cpp \
common/lc_stringcache.cpp \
common/lc_synth.cpp \
common/lc_texture.cpp \
@@ -229,7 +231,6 @@ SOURCES += \
common/lc_viewsphere.cpp \
common/lc_viewwidget.cpp \
common/lc_zipfile.cpp \
qt/system.cpp \
qt/qtmain.cpp \
qt/lc_qeditgroupsdialog.cpp \
qt/lc_qselectdialog.cpp \
@@ -286,6 +287,7 @@ HEADERS += \
common/lc_meshloader.h \
common/lc_minifigdialog.h \
common/lc_model.h \
common/lc_modelaction.h \
common/lc_modellistdialog.h \
common/lc_objectproperty.h \
common/lc_pagesetupdialog.h \
@@ -296,6 +298,7 @@ HEADERS += \
common/lc_propertieswidget.h \
common/lc_scene.h \
common/lc_shortcuts.h \
common/lc_string.h \
common/lc_stringcache.h \
common/lc_synth.h \
common/lc_texture.h \
+149 -100
View File
@@ -1,28 +1,52 @@
#include "lc_global.h"
#include "lc_qeditgroupsdialog.h"
#include "ui_lc_qeditgroupsdialog.h"
#include "lc_application.h"
#include "lc_model.h"
#include "piece.h"
#include "group.h"
lcQEditGroupsDialog::lcQEditGroupsDialog(QWidget* Parent, const QMap<lcPiece*, lcGroup*>& PieceParents, const QMap<lcGroup*, lcGroup*>& GroupParents, lcModel* Model)
: QDialog(Parent), mPieceParents(PieceParents), mGroupParents(GroupParents)
constexpr uintptr_t LC_GROUPDIALOG_NEW_GROUP = ~0U;
class lcEditGroupsDialogDelegate : public QItemDelegate
{
public:
lcEditGroupsDialogDelegate(QObject* Parent)
: QItemDelegate(Parent)
{
}
void setModelData(QWidget* Editor, QAbstractItemModel* Model, const QModelIndex& Index) const
{
QLineEdit* LineEdit = qobject_cast<QLineEdit *>(Editor);
if (!LineEdit->isModified())
return;
QString Text = LineEdit->text().trimmed();
lcQEditGroupsDialog* Dialog = qobject_cast<lcQEditGroupsDialog*>(parent());
if (Dialog && !Dialog->CanRenameGroup(Text))
return;
QItemDelegate::setModelData(Editor, Model, Index);
}
};
lcQEditGroupsDialog::lcQEditGroupsDialog(QWidget* Parent, const lcModel* Model)
: QDialog(Parent), mModel(Model)
{
mLastItemClicked = nullptr;
mModel = Model;
ui = new Ui::lcQEditGroupsDialog;
ui->setupUi(this);
connect(ui->treeWidget, &QTreeWidget::itemClicked, this, &lcQEditGroupsDialog::onItemClicked);
connect(ui->treeWidget, &QTreeWidget::itemDoubleClicked, this, &lcQEditGroupsDialog::onItemDoubleClicked);
QPushButton* NewGroup = ui->buttonBox->addButton(tr("&New Group"), QDialogButtonBox::ActionRole);
QPushButton *newGroup = ui->buttonBox->addButton(tr("New Group"), QDialogButtonBox::ActionRole);
connect(NewGroup, &QPushButton::clicked, this, &lcQEditGroupsDialog::NewGroupClicked);
connect(newGroup, &QPushButton::clicked, this, &lcQEditGroupsDialog::on_newGroup_clicked);
PopulateTree();
AddChildren(ui->treeWidget->invisibleRootItem(), nullptr);
ui->treeWidget->setItemDelegate(new lcEditGroupsDialogDelegate(this));
ui->treeWidget->expandAll();
}
@@ -31,22 +55,31 @@ lcQEditGroupsDialog::~lcQEditGroupsDialog()
delete ui;
}
void lcQEditGroupsDialog::accept()
bool lcQEditGroupsDialog::CanRenameGroup(const QString& Text) const
{
UpdateParents(ui->treeWidget->invisibleRootItem(), nullptr);
if (Text.isEmpty())
return false;
QDialog::accept();
std::function<bool(QTreeWidgetItem*)> ScanGroups = [&ScanGroups, &Text](QTreeWidgetItem* ParentItem)
{
for (int ChildIndex = 0; ChildIndex < ParentItem->childCount(); ChildIndex++)
{
QTreeWidgetItem* ChildItem = ParentItem->child(ChildIndex);
if (ChildItem->data(0, GroupRole).value<uintptr_t>())
{
if (ChildItem->text(0) == Text || !ScanGroups(ChildItem))
return false;
}
}
return true;
};
return ScanGroups(ui->treeWidget->invisibleRootItem());
}
void lcQEditGroupsDialog::reject()
{
for (int GroupIdx = 0; GroupIdx < mNewGroups.size(); GroupIdx++)
mModel->RemoveGroup(mNewGroups[GroupIdx]);
QDialog::reject();
}
void lcQEditGroupsDialog::on_newGroup_clicked()
void lcQEditGroupsDialog::NewGroupClicked()
{
QTreeWidgetItem* CurrentItem = ui->treeWidget->currentItem();
@@ -56,114 +89,130 @@ void lcQEditGroupsDialog::on_newGroup_clicked()
if (!CurrentItem)
CurrentItem = ui->treeWidget->invisibleRootItem();
lcGroup* ParentGroup = (lcGroup*)CurrentItem->data(0, GroupRole).value<uintptr_t>();
QString Prefix = tr("Group #");
int MaxIndex = 0;
lcGroup* NewGroup = mModel->AddGroup(tr("Group #"), ParentGroup);
mGroupParents[NewGroup] = ParentGroup;
mNewGroups.append(NewGroup);
std::function<void(QTreeWidgetItem*)> ScanGroups = [&ScanGroups, &Prefix, &MaxIndex](QTreeWidgetItem* ParentItem)
{
for (int ChildIndex = 0; ChildIndex < ParentItem->childCount(); ChildIndex++)
{
QTreeWidgetItem* ChildItem = ParentItem->child(ChildIndex);
QTreeWidgetItem* GroupItem = new QTreeWidgetItem(CurrentItem, QStringList(NewGroup->mName));
if (ChildItem->data(0, GroupRole).value<uintptr_t>())
{
QString Name = ChildItem->text(0);
if (Name.startsWith(Prefix))
{
bool Ok = false;
int GroupNumber = Name.mid(Prefix.length()).toInt(&Ok);
if (Ok && GroupNumber > MaxIndex)
MaxIndex = GroupNumber;
}
ScanGroups(ChildItem);
}
}
};
ScanGroups(ui->treeWidget->invisibleRootItem());
QString Name = Prefix + QString::number(MaxIndex + 1);
QTreeWidgetItem* GroupItem = new QTreeWidgetItem(CurrentItem, QStringList(Name));
GroupItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsEditable);
GroupItem->setData(0, GroupRole, QVariant::fromValue<uintptr_t>((uintptr_t)NewGroup));
GroupItem->setData(0, GroupRole, QVariant::fromValue<uintptr_t>(LC_GROUPDIALOG_NEW_GROUP));
GroupItem->setExpanded(true);
}
void lcQEditGroupsDialog::onItemClicked(QTreeWidgetItem *item, int column)
lcQEditGroupsDialog::GroupInfo lcQEditGroupsDialog::GetGroupInfo(QTreeWidgetItem* ParentItem) const
{
Q_UNUSED(column);
lcQEditGroupsDialog::GroupInfo GroupInfo;
if (item->flags() & Qt::ItemIsEditable)
GroupInfo.Name = ParentItem->text(0);
uintptr_t GroupPointer = ParentItem->data(0, GroupRole).value<uintptr_t>();
GroupInfo.Group = (GroupPointer == LC_GROUPDIALOG_NEW_GROUP) ? nullptr : reinterpret_cast<lcGroup*>(GroupPointer);
for (int ChildIndex = 0; ChildIndex < ParentItem->childCount(); ChildIndex++)
{
mClickTimer.stop();
QTreeWidgetItem* ChildItem = ParentItem->child(ChildIndex);
if (mLastItemClicked != item)
{
mLastItemClicked = item;
mEditableDoubleClicked = false;
}
if (ChildItem->data(0, GroupRole).value<uintptr_t>())
GroupInfo.ChildGroups.emplace_back(GetGroupInfo(ChildItem));
else
{
mClickTimer.start(QApplication::doubleClickInterval() + 50, this);
lcPiece* Piece = reinterpret_cast<lcPiece*>(ChildItem->data(0, PieceRole).value<uintptr_t>());
if (Piece)
GroupInfo.ChildPieces.push_back(Piece);
}
}
return GroupInfo;
}
void lcQEditGroupsDialog::onItemDoubleClicked(QTreeWidgetItem *item, int column)
lcQEditGroupsDialog::GroupInfo lcQEditGroupsDialog::GetGroups() const
{
Q_UNUSED(column);
if (item->flags() & Qt::ItemIsEditable)
{
mEditableDoubleClicked = true;
}
return GetGroupInfo(ui->treeWidget->invisibleRootItem());
}
void lcQEditGroupsDialog::timerEvent(QTimerEvent *event)
void lcQEditGroupsDialog::PopulateTree()
{
Q_UNUSED(event);
const std::vector<std::unique_ptr<lcGroup>>& Groups = mModel->GetGroups();
std::unordered_map<lcGroup*, QTreeWidgetItem*> AddedGroups;
std::vector<lcGroup*> GroupsToAdd;
mClickTimer.stop();
if (!mEditableDoubleClicked)
AddedGroups[nullptr] = ui->treeWidget->invisibleRootItem();
auto CreateGroupItem = [&AddedGroups](lcGroup* Group)
{
ui->treeWidget->editItem(mLastItemClicked);
}
QTreeWidgetItem* ParentItem = AddedGroups.find(Group->mGroup)->second;
mEditableDoubleClicked = false;
}
void lcQEditGroupsDialog::UpdateParents(QTreeWidgetItem* ParentItem, lcGroup* ParentGroup)
{
for (int ChildIdx = 0; ChildIdx < ParentItem->childCount(); ChildIdx++)
{
QTreeWidgetItem* ChildItem = ParentItem->child(ChildIdx);
lcPiece* Piece = (lcPiece*)ChildItem->data(0, PieceRole).value<uintptr_t>();
if (Piece)
{
mPieceParents[Piece] = ParentGroup;
}
else
{
lcGroup* Group = (lcGroup*)ChildItem->data(0, GroupRole).value<uintptr_t>();
// todo: validate unique group name
if (Group)
Group->mName = ChildItem->text(0);
mGroupParents[Group] = ParentGroup;
UpdateParents(ChildItem, Group);
}
}
}
void lcQEditGroupsDialog::AddChildren(QTreeWidgetItem* ParentItem, lcGroup* ParentGroup)
{
for (QMap<lcGroup*, lcGroup*>::const_iterator it = mGroupParents.constBegin(); it != mGroupParents.constEnd(); it++)
{
lcGroup* Group = it.key();
lcGroup* Parent = it.value();
if (Parent != ParentGroup)
continue;
if (!ParentItem)
return false;
QTreeWidgetItem* GroupItem = new QTreeWidgetItem(ParentItem, QStringList(Group->mName));
GroupItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsEditable);
GroupItem->setData(0, GroupRole, QVariant::fromValue<uintptr_t>((uintptr_t)Group));
AddChildren(GroupItem, Group);
AddedGroups[Group] = GroupItem;
return true;
};
for (const std::unique_ptr<lcGroup>& Group : Groups)
if (!CreateGroupItem(Group.get()))
GroupsToAdd.push_back(Group.get());
while (!GroupsToAdd.empty())
{
size_t GroupCount = GroupsToAdd.size();
for (auto GroupIt = GroupsToAdd.begin(); GroupIt != GroupsToAdd.end();)
{
if (CreateGroupItem(*GroupIt))
GroupIt = GroupsToAdd.erase(GroupIt);
else
++GroupIt;
}
if (GroupCount == GroupsToAdd.size())
break;
}
for (QMap<lcPiece*, lcGroup*>::const_iterator it = mPieceParents.constBegin(); it != mPieceParents.constEnd(); it++)
const std::vector<std::unique_ptr<lcPiece>>& Pieces = mModel->GetPieces();
for (const std::unique_ptr<lcPiece>& Piece : Pieces)
{
lcPiece* Piece = it.key();
lcGroup* Parent = it.value();
QTreeWidgetItem* ParentItem = AddedGroups.find(Piece->GetGroup())->second;
if (Parent != ParentGroup)
continue;
QTreeWidgetItem* PieceItem = new QTreeWidgetItem(ParentItem, QStringList(Piece->GetName()));
PieceItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled);
PieceItem->setData(0, PieceRole, QVariant::fromValue<uintptr_t>((uintptr_t)Piece));
if (ParentItem)
{
QTreeWidgetItem* PieceItem = new QTreeWidgetItem(ParentItem, QStringList(Piece->GetName()));
PieceItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled);
PieceItem->setData(0, PieceRole, QVariant::fromValue<uintptr_t>((uintptr_t)Piece.get()));
}
}
}
+23 -29
View File
@@ -1,7 +1,5 @@
#pragma once
#include <QDialog>
namespace Ui {
class lcQEditGroupsDialog;
}
@@ -9,39 +7,35 @@ class lcQEditGroupsDialog;
class lcQEditGroupsDialog : public QDialog
{
Q_OBJECT
public:
lcQEditGroupsDialog(QWidget* Parent, const QMap<lcPiece*, lcGroup*>& PieceParents, const QMap<lcGroup*, lcGroup*>& GroupParents, lcModel* Model);
~lcQEditGroupsDialog();
QMap<lcPiece*, lcGroup*> mPieceParents;
QMap<lcGroup*, lcGroup*> mGroupParents;
QList<lcGroup*> mNewGroups;
//QList<lcGroup*> mDeletedGroups; // todo: support deleting groups in the edit groups dialog
public:
lcQEditGroupsDialog(QWidget* Parent, const lcModel* Model);
virtual ~lcQEditGroupsDialog();
struct GroupInfo
{
QString Name;
lcGroup* Group;
std::vector<GroupInfo> ChildGroups;
std::vector<lcPiece*> ChildPieces;
};
GroupInfo GetGroups() const;
bool CanRenameGroup(const QString& Text) const;
protected slots:
void NewGroupClicked();
protected:
enum
{
PieceRole = Qt::UserRole,
GroupRole
};
public slots:
void accept() override;
void reject() override;
void on_newGroup_clicked();
void onItemClicked(QTreeWidgetItem* Item, int Column);
void onItemDoubleClicked(QTreeWidgetItem* Item, int Column);
GroupInfo GetGroupInfo(QTreeWidgetItem* ParentItem) const;
void PopulateTree();
private:
Ui::lcQEditGroupsDialog *ui;
void UpdateParents(QTreeWidgetItem* ParentItem, lcGroup* ParentGroup);
void AddChildren(QTreeWidgetItem* ParentItem, lcGroup* ParentGroup);
void timerEvent(QTimerEvent* Event) override;
lcModel* mModel;
QTreeWidgetItem* mLastItemClicked;
bool mEditableDoubleClicked;
QBasicTimer mClickTimer;
Ui::lcQEditGroupsDialog* ui = nullptr;
const lcModel* mModel = nullptr;
};
+4 -4
View File
@@ -17,13 +17,13 @@
<item>
<widget class="QTreeWidget" name="treeWidget">
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
<set>QAbstractItemView::EditTrigger::DoubleClicked|QAbstractItemView::EditTrigger::EditKeyPressed|QAbstractItemView::EditTrigger::SelectedClicked</set>
</property>
<property name="dragEnabled">
<bool>true</bool>
</property>
<property name="dragDropMode">
<enum>QAbstractItemView::InternalMove</enum>
<enum>QAbstractItemView::DragDropMode::InternalMove</enum>
</property>
<property name="uniformRowHeights">
<bool>true</bool>
@@ -41,10 +41,10 @@
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
<set>QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok</set>
</property>
</widget>
</item>
+1 -1
View File
@@ -9,7 +9,7 @@ class lcQImageDialog;
class lcQImageDialog : public QDialog
{
Q_OBJECT
public:
lcQImageDialog(QWidget* Parent);
~lcQImageDialog();
+13 -5
View File
@@ -10,6 +10,9 @@
#include "pieceinf.h"
#include "lc_edgecolordialog.h"
#include "lc_blenderpreferences.h"
#include "lc_mainwindow.h"
#include "lc_viewwidget.h"
#include "lc_view.h"
static const char* gLanguageLocales[] =
{
@@ -99,16 +102,20 @@ lcQPreferencesDialog::lcQPreferencesDialog(QWidget* Parent, lcPreferencesDialogO
ui->ConditionalLinesCheckBox->setEnabled(false);
}
lcViewWidget* Widget = gMainWindow->GetActiveView()->GetWidget();
QOpenGLContext* Context = Widget->context();
QOpenGLFunctions* Functions = Context->functions();
#ifndef LC_OPENGLES
if (QSurfaceFormat::defaultFormat().samples() > 1)
{
glGetFloatv(GL_SMOOTH_LINE_WIDTH_RANGE, mLineWidthRange);
glGetFloatv(GL_SMOOTH_LINE_WIDTH_GRANULARITY, &mLineWidthGranularity);
Functions->glGetFloatv(GL_SMOOTH_LINE_WIDTH_RANGE, mLineWidthRange);
Functions->glGetFloatv(GL_SMOOTH_LINE_WIDTH_GRANULARITY, &mLineWidthGranularity);
}
else
#endif
{
glGetFloatv(GL_ALIASED_LINE_WIDTH_RANGE, mLineWidthRange);
Functions->glGetFloatv(GL_ALIASED_LINE_WIDTH_RANGE, mLineWidthRange);
mLineWidthGranularity = 1.0f;
}
@@ -903,8 +910,9 @@ void lcQPreferencesDialog::updateCommandList()
const QString identifier = tr(gCommands[actionIdx].ID);
int pos = identifier.indexOf(QLatin1Char('.'));
int subPos = identifier.indexOf(QLatin1Char('.'), pos + 1);
qsizetype pos = identifier.indexOf(QLatin1Char('.'));
qsizetype subPos = identifier.indexOf(QLatin1Char('.'), pos + 1);
if (subPos == -1)
subPos = pos;
-1
View File
@@ -1,7 +1,6 @@
#include "lc_global.h"
#include "lc_qselectdialog.h"
#include "ui_lc_qselectdialog.h"
#include "lc_application.h"
#include "lc_model.h"
#include "piece.h"
#include "camera.h"
+1 -1
View File
@@ -9,7 +9,7 @@ class lcQSelectDialog;
class lcQSelectDialog : public QDialog
{
Q_OBJECT
public:
lcQSelectDialog(QWidget* Parent, lcModel* Model);
~lcQSelectDialog();
+1 -1
View File
@@ -14,7 +14,7 @@ void lcDoInitialUpdateCheck();
class lcQUpdateDialog : public QDialog
{
Q_OBJECT
public:
explicit lcQUpdateDialog(QWidget* Parent, bool InitialUpdate);
~lcQUpdateDialog();
+11 -12
View File
@@ -4,8 +4,7 @@
#include "lc_library.h"
#include "lc_model.h"
#include "pieceinf.h"
#include "lc_partselectionwidget.h"
#include "lc_mainwindow.h"
#include "lc_string.h"
#ifdef Q_OS_WIN
#include <windows.h>
@@ -15,7 +14,7 @@
QString lcFormatValue(float Value, int Precision)
{
QString String = QString::number(Value, 'f', Precision);
const int Dot = String.indexOf('.');
const qsizetype Dot = String.indexOf('.');
if (Dot != -1)
{
@@ -153,14 +152,14 @@ void lcQTreeWidgetColumnStretcher::SectionResized(int LogicalIndex, int OldSize,
{
Q_UNUSED(OldSize)
if (LogicalIndex == mColumnToStretch)
{
QHeaderView* HeaderView = qobject_cast<QHeaderView*>(parent());
if (HeaderView->isVisible())
mInteractiveResize = true;
mStretchWidth = NewSize;
if (LogicalIndex == mColumnToStretch)
{
QHeaderView* HeaderView = qobject_cast<QHeaderView*>(parent());
if (HeaderView->isVisible())
mInteractiveResize = true;
mStretchWidth = NewSize;
}
}
@@ -238,7 +237,7 @@ std::vector<bool> lcPieceIdStringModel::GetFilteredRows(const QString& FilterTex
{
const PieceInfo* Info = mSortedPieces[PieceInfoIndex];
FilteredRows[PieceInfoIndex] = (strcasestr(Info->m_strDescription, Text.c_str()) || strcasestr(Info->mFileName, Text.c_str()));
FilteredRows[PieceInfoIndex] = (lcstrcasestr(Info->m_strDescription, Text.c_str()) || lcstrcasestr(Info->mFileName, Text.c_str()));
}
return FilteredRows;
+17 -17
View File
@@ -82,7 +82,7 @@ lcRenderDialog::lcRenderDialog(QWidget* Parent, lcRenderDialogMode RenderDialogM
bool BlenderConfigured = !lcGetProfileString(LC_PROFILE_BLENDER_IMPORT_MODULE).isEmpty();
QStringList const& DataPathList = QStandardPaths::standardLocations(QStandardPaths::AppLocalDataLocation);
if (!QDir(QString("%1/Blender/addons/%2").arg(DataPathList.first()).arg(LC_BLENDER_ADDON_RENDER_FOLDER)).isReadable())
if (!QDir(QString("%1/Blender/addons/%2").arg(DataPathList.first(), LC_BLENDER_ADDON_RENDER_FOLDER)).isReadable())
{
BlenderConfigured = false;
lcSetProfileString(LC_PROFILE_BLENDER_IMPORT_MODULE, QString());
@@ -175,7 +175,7 @@ bool lcRenderDialog::PromptCancel()
{
if (!mProcess)
return true;
if (QMessageBox::question(this, tr("Cancel Render"), tr("Are you sure you want to cancel the current render?"), QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes)
return false;
@@ -305,28 +305,28 @@ void lcRenderDialog::RenderPOVRay()
const QString POVRayDir = QFileInfo(POVRayPath).absolutePath();
const QString IncludePath = QDir::cleanPath(POVRayDir + "/include");
if (QFileInfo(IncludePath).exists())
if (QFileInfo::exists(IncludePath))
Arguments.append(QString("+L\"%1\"").arg(IncludePath));
const QString IniPath = QDir::cleanPath(POVRayDir + "/ini");
if (QFileInfo(IniPath).exists())
if (QFileInfo::exists(IniPath))
Arguments.append(QString("+L\"%1\"").arg(IniPath));
if (lcGetActiveProject()->GetModels()[0]->GetPOVRayOptions().UseLGEO)
{
const QString LGEOPath = lcGetProfileString(LC_PROFILE_POVRAY_LGEO_PATH);
if (QFileInfo(LGEOPath).exists())
if (QFileInfo::exists(LGEOPath))
{
const QString LgPath = QDir::cleanPath(LGEOPath + "/lg");
if (QFileInfo(LgPath).exists())
if (QFileInfo::exists(LgPath))
Arguments.append(QString("+L\"%1\"").arg(LgPath));
const QString ArPath = QDir::cleanPath(LGEOPath + "/ar");
if (QFileInfo(ArPath).exists())
if (QFileInfo::exists(ArPath))
Arguments.append(QString("+L\"%1\"").arg(ArPath));
const QString StlPath = QDir::cleanPath(LGEOPath + "/stl");
if (QFileInfo(StlPath).exists())
if (QFileInfo::exists(StlPath))
Arguments.append(QString("+L\"%1\"").arg(StlPath));
}
}
@@ -376,7 +376,7 @@ void lcRenderDialog::RenderBlender()
const QStringList DataPathList = QStandardPaths::standardLocations(QStandardPaths::AppLocalDataLocation);
mDataPath = DataPathList.first();
const QString DefaultBlendFile = QString("%1/blender/config/%2").arg(mDataPath).arg(LC_BLENDER_ADDON_BLEND_FILE);
const QString DefaultBlendFile = QString("%1/blender/config/%2").arg(mDataPath, LC_BLENDER_ADDON_BLEND_FILE);
lcModel* Model = lcGetActiveProject()->GetActiveModel();
const QString ModelFileName = QFileInfo(QDir(lcGetProfileString(LC_PROFILE_PROJECTS_PATH)), QString("%1_Step_%2.ldr").arg(QFileInfo(Model->GetProperties().mFileName).baseName()).arg(Model->GetCurrentStep())).absoluteFilePath();
@@ -400,8 +400,8 @@ void lcRenderDialog::RenderBlender()
"image_file=r'%5'")
.arg(mWidth).arg(mHeight)
.arg(mScale * 100)
.arg(QDir::toNativeSeparators(ModelFileName).replace("\\","\\\\"))
.arg(QDir::toNativeSeparators(ui->OutputEdit->text()).replace("\\","\\\\"));
.arg(QDir::toNativeSeparators(ModelFileName).replace("\\","\\\\"),
QDir::toNativeSeparators(ui->OutputEdit->text()).replace("\\","\\\\"));
if (BlenderImportModule == QLatin1String("MM"))
PythonExpression.append(", use_ldraw_import_mm=True");
if (SearchCustomDir)
@@ -421,7 +421,7 @@ void lcRenderDialog::RenderBlender()
PythonExpression.append(", cli_render=True)\"");
if (QFileInfo(DefaultBlendFile).exists())
if (QFileInfo::exists(DefaultBlendFile))
Arguments << QDir::toNativeSeparators(DefaultBlendFile);
Arguments << QString("--python-expr");
Arguments << PythonExpression;
@@ -433,14 +433,14 @@ void lcRenderDialog::RenderBlender()
#else
ScriptName = QLatin1String("render_ldraw_model.sh");
#endif
ScriptCommand = QString("\"%1\" %2").arg(lcGetProfileString(LC_PROFILE_BLENDER_PATH)).arg(Arguments.join(" "));
ScriptCommand = QString("\"%1\" %2").arg(lcGetProfileString(LC_PROFILE_BLENDER_PATH), Arguments.join(" "));
if (mDialogMode == lcRenderDialogMode::OpenInBlender)
ScriptCommand.append(QString(" > %1").arg(QDir::toNativeSeparators(GetStdOutFileName())));
const QLatin1String LineEnding("\r\n");
QFile ScriptFile(QString("%1/%2").arg(QDir::tempPath()).arg(ScriptName));
QFile ScriptFile(QString("%1/%2").arg(QDir::tempPath(), ScriptName));
if (ScriptFile.open(QIODevice::WriteOnly | QIODevice::Text))
{
QTextStream Stream(&ScriptFile);
@@ -608,7 +608,7 @@ QString lcRenderDialog::ReadStdErr(bool& HasError) const
if (!File.open(QFile::ReadOnly | QFile::Text))
{
const QString message = tr("Failed to open log file: %1:\n%2").arg(File.fileName()).arg(File.errorString());
const QString message = tr("Failed to open log file: %1:\n%2").arg(File.fileName(), File.errorString());
return message;
}
@@ -646,7 +646,7 @@ void lcRenderDialog::WriteStdOut()
{
QTextStream Out(&File);
for (const QString& Line : mStdOutList)
for (const QString& Line : std::as_const(mStdOutList))
Out << Line;
File.close();
@@ -774,7 +774,7 @@ void lcRenderDialog::ShowResult()
}
else if (mDialogMode == lcRenderDialogMode::RenderBlender)
{
Success = QFileInfo(FileName).exists();
Success = QFileInfo::exists(FileName);
if (Success)
{
setMinimumSize(100, 100);
+2 -2
View File
@@ -166,7 +166,7 @@ void lcSetsDatabaseDialog::DownloadFinished(lcHttpReply* Reply)
if (Version == 1)
{
QJsonArray Keys = Root["Keys"].toArray();
const QJsonArray Keys = Root["Keys"].toArray();
for (const QJsonValue& Key : Keys)
mKeys.append(Key.toString());
@@ -190,8 +190,8 @@ void lcSetsDatabaseDialog::DownloadFinished(lcHttpReply* Reply)
{
QJsonDocument Document = QJsonDocument::fromJson(Reply->readAll());
QJsonObject Root = Document.object();
const QJsonArray Sets = Root["results"].toArray();
QJsonArray Sets = Root["results"].toArray();
for (const QJsonValue& Set : Sets)
{
QJsonObject SetObject = Set.toObject();
+2 -2
View File
@@ -27,7 +27,7 @@
static TCHAR gMinidumpPath[_MAX_PATH];
static LONG WINAPI lcSehHandler(PEXCEPTION_POINTERS exceptionPointers)
{
{
if (IsDebuggerPresent())
return EXCEPTION_CONTINUE_SEARCH;
@@ -203,7 +203,7 @@ int main(int argc, char *argv[])
#ifdef LC_LDRAW_LIBRARY_PATH
LibraryPaths += qMakePair(QString::fromLatin1(LC_LDRAW_LIBRARY_PATH), false);
#endif
setlocale(LC_NUMERIC, "C");
lcStartupMode StartupMode = Application.Initialize(LibraryPaths);
-36
View File
@@ -1,36 +0,0 @@
#include "lc_global.h"
#ifdef Q_OS_WIN
char* strcasestr(const char* s, const char* find)
{
char c, sc;
if ((c = *find++) != 0)
{
c = tolower((unsigned char)c);
const int len = (int)strlen(find);
do
{
do
{
if ((sc = *s++) == 0)
return (nullptr);
} while ((char)tolower((unsigned char)sc) != c);
} while (qstrnicmp(s, find, len) != 0);
s--;
}
return ((char *)s);
}
#else
char* strupr(char* string)
{
for (char* c = string; *c; c++)
*c = toupper(*c);
return string;
}
#endif