mirror of
https://github.com/leozide/leocad
synced 2025-01-14 08:01:45 +01:00
Merge pull request #2 from leozide/master
Merge latest upstream changes
This commit is contained in:
commit
6b3412ec2f
174 changed files with 40005 additions and 27885 deletions
34
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
34
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
|
@ -0,0 +1,34 @@
|
|||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: bug
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Version (please complete the following information):**
|
||||
- OS: [e.g. Windows 10, Ubuntu, macOS]
|
||||
- LeoCAD Version [e.g. 19.07 or continuous]
|
||||
|
||||
**Crash information:**
|
||||
Some versions of LeoCAD will show a message that they saved a minidump file when they crash, if you see this message please attach the file.
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here. If you're seeing a graphical issue, adding a screenshot of the About Dialog may help.
|
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -20,6 +20,7 @@
|
|||
*.dae
|
||||
*.3ds
|
||||
*.obj
|
||||
.vs
|
||||
build
|
||||
debug
|
||||
release
|
||||
|
|
163
.travis.yml
163
.travis.yml
|
@ -1,20 +1,9 @@
|
|||
language: cpp
|
||||
|
||||
matrix:
|
||||
jobs:
|
||||
include:
|
||||
- os: linux
|
||||
dist: trusty
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- sourceline: "ppa:beineri/opt-qt487-trusty"
|
||||
packages:
|
||||
- opt-qt4-qmake opt-qt4-dev-tools opt-libqt4-dev opt-libqt4-dev-bin opt-libqt4-opengl-dev
|
||||
sudo: required
|
||||
compiler: gcc
|
||||
env:
|
||||
- QT_BASE=48
|
||||
- os: linux
|
||||
name: Linux amd64
|
||||
dist: trusty
|
||||
addons:
|
||||
apt:
|
||||
|
@ -22,76 +11,90 @@ matrix:
|
|||
- sourceline: "ppa:beineri/opt-qt-5.10.1-trusty"
|
||||
packages:
|
||||
- qt510base
|
||||
sudo: required
|
||||
compiler: gcc
|
||||
env:
|
||||
- QT_BASE=510
|
||||
script:
|
||||
- source /opt/qt*/bin/qt*-env.sh
|
||||
- qmake PREFIX=/usr -v
|
||||
- qmake PREFIX=/usr
|
||||
- make -j$(nproc)
|
||||
after_success:
|
||||
- make install INSTALL_ROOT=AppDir
|
||||
- wget https://github.com/leozide/leocad/releases/download/v19.07.1/Library-20.03.zip -O library.zip
|
||||
- unzip library.zip
|
||||
- mkdir -p AppDir/usr/share/leocad
|
||||
- mv library.bin AppDir/usr/share/leocad/library.bin
|
||||
- wget -c "https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-x86_64.AppImage"
|
||||
- chmod a+x linuxdeployqt*.AppImage
|
||||
- unset QTDIR; unset QT_PLUGIN_PATH ; unset LD_LIBRARY_PATH
|
||||
- export VERSION=$(git rev-parse --short HEAD)
|
||||
- ./linuxdeployqt*.AppImage ./AppDir/usr/share/applications/*.desktop -bundle-non-qt-libs
|
||||
- ./linuxdeployqt*.AppImage --appimage-extract
|
||||
- export PATH=$(readlink -f ./squashfs-root/usr/bin/):$PATH
|
||||
- ./squashfs-root/usr/bin/appimagetool AppDir/
|
||||
- mv ./LeoCAD-$VERSION-x86_64.AppImage ./LeoCAD-Linux-$VERSION-x86_64.AppImage
|
||||
- 'curl -s -H "Authorization: token $GITHUB_TOKEN" https://api.github.com/repos/leozide/leocad/commits/master -o repo.txt'
|
||||
- 'export REMOTE=$(grep -Po ''(?<=: \")(([a-z0-9])\w+)(?=\")'' -m 1 repo.txt)'
|
||||
- export LOCAL=$(git rev-parse HEAD)
|
||||
- if [[ "$REMOTE" != "$LOCAL" ]]; then echo "Build no longer current. $REMOTE vs $LOCAL - aborting upload."; exit 0; fi;
|
||||
- wget -c https://github.com/probonopd/uploadtool/raw/master/upload.sh
|
||||
- bash upload.sh LeoCAD*.AppImage*
|
||||
|
||||
- os: linux
|
||||
name: Linux arm64
|
||||
arch: arm64
|
||||
dist: focal
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- qt5-default
|
||||
- qtbase5-dev
|
||||
- qttools5-dev-tools
|
||||
- libqt5opengl5-dev
|
||||
- zip
|
||||
compiler: gcc
|
||||
script:
|
||||
- qmake -v
|
||||
- qmake PREFIX=/usr
|
||||
- make -j$(nproc)
|
||||
after_success:
|
||||
- cp build/release/leocad .
|
||||
- export VERSION=$(git rev-parse --short HEAD)
|
||||
- zip LeoCAD-Linux-$VERSION-arm64.zip leocad
|
||||
- 'curl -s -H "Authorization: token $GITHUB_TOKEN" https://api.github.com/repos/leozide/leocad/commits/master -o repo.txt'
|
||||
- 'export REMOTE=$(grep -Po ''(?<=: \")(([a-z0-9])\w+)(?=\")'' -m 1 repo.txt)'
|
||||
- export LOCAL=$(git rev-parse HEAD)
|
||||
- if [[ "$REMOTE" != "$LOCAL" ]]; then echo "Build no longer current. $REMOTE vs $LOCAL - aborting upload."; travis_terminate 0; fi;
|
||||
- wget -c https://github.com/probonopd/uploadtool/raw/master/upload.sh
|
||||
- bash upload.sh LeoCAD*.zip
|
||||
|
||||
- os: osx
|
||||
name: macOS
|
||||
osx_image: xcode11
|
||||
compiler: clang
|
||||
env:
|
||||
- QT_BASE=57
|
||||
|
||||
before_install:
|
||||
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
|
||||
brew update;
|
||||
fi
|
||||
|
||||
install:
|
||||
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
|
||||
brew install qt5 grep;
|
||||
brew link --force qt5;
|
||||
wget https://github.com/leozide/leocad/releases/download/v18.02/Library-Linux-11494.zip -O library.zip;
|
||||
unzip library.zip;
|
||||
fi
|
||||
|
||||
script:
|
||||
- |
|
||||
if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
|
||||
source /opt/qt*/bin/qt*-env.sh
|
||||
qmake PREFIX=/usr -v
|
||||
qmake PREFIX=/usr -r
|
||||
make -j$(nproc); export COMPILE_RESULT=$?
|
||||
if [[ "$QT_BASE" != "510" ]]; then exit $COMPILE_RESULT; fi
|
||||
make install INSTALL_ROOT=AppDir
|
||||
if [[ "$TRAVIS_TAG" != "" ]]; then
|
||||
wget https://github.com/leozide/leocad/releases/download/v18.02/Library-Linux-11494.zip -O library.zip;
|
||||
unzip library.zip;
|
||||
mkdir -p AppDir/usr/share/leocad;
|
||||
mv library.bin AppDir/usr/share/leocad/library.bin;
|
||||
fi
|
||||
wget -c "https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-x86_64.AppImage"
|
||||
chmod a+x linuxdeployqt*.AppImage
|
||||
unset QTDIR; unset QT_PLUGIN_PATH ; unset LD_LIBRARY_PATH
|
||||
export VERSION=$(git rev-parse --short HEAD)
|
||||
./linuxdeployqt*.AppImage ./AppDir/usr/share/applications/*.desktop -bundle-non-qt-libs
|
||||
./linuxdeployqt*.AppImage --appimage-extract
|
||||
export PATH=$(readlink -f ./squashfs-root/usr/bin/):$PATH
|
||||
./squashfs-root/usr/bin/appimagetool AppDir/
|
||||
mv ./LeoCAD-$VERSION-x86_64.AppImage ./LeoCAD-Linux-$VERSION-x86_64.AppImage
|
||||
elif [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
|
||||
qmake PREFIX=/usr -v
|
||||
qmake PREFIX=/usr -r
|
||||
make -j$(sysctl -n hw.ncpu)
|
||||
cd build/release
|
||||
macdeployqt LeoCAD.app -dmg
|
||||
mv LeoCAD.dmg LeoCAD-macOS-$(git rev-parse --short HEAD).dmg
|
||||
fi
|
||||
|
||||
after_success:
|
||||
- |
|
||||
export GREP_PATH=grep;
|
||||
if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then export GREP_PATH=ggrep; fi
|
||||
curl -s -H "Authorization: token $GITHUB_TOKEN" https://api.github.com/repos/leozide/leocad/commits/master -o repo.txt;
|
||||
export REMOTE=$($GREP_PATH -Po '(?<=: \")(([a-z0-9])\w+)(?=\")' -m 1 repo.txt);
|
||||
export LOCAL=$(git rev-parse HEAD);
|
||||
if [[ "$REMOTE" != "$LOCAL" ]]; then echo "Build no longer current. $REMOTE vs $LOCAL - aborting upload."; exit 0; fi;
|
||||
if [[ "$QT_BASE" = "510" && "$TRAVIS_OS_NAME" = "linux" ]]; then
|
||||
wget -c https://github.com/probonopd/uploadtool/raw/master/upload.sh
|
||||
bash upload.sh LeoCAD*.AppImage*
|
||||
elif [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
|
||||
wget -c https://github.com/probonopd/uploadtool/raw/master/upload.sh
|
||||
bash upload.sh LeoCAD*.dmg*
|
||||
fi
|
||||
addons:
|
||||
homebrew:
|
||||
packages:
|
||||
- grep
|
||||
- qt5
|
||||
install:
|
||||
- brew link --force qt5
|
||||
- wget https://github.com/leozide/povray/releases/download/continuous/povray
|
||||
- wget https://github.com/leozide/leocad/releases/download/v19.07.1/Library-20.03.zip -O library.zip
|
||||
- unzip library.zip
|
||||
script:
|
||||
- qmake -v
|
||||
- qmake
|
||||
- make -j$(sysctl -n hw.ncpu)
|
||||
after_success:
|
||||
- cd build/release
|
||||
- macdeployqt LeoCAD.app -dmg
|
||||
- mv LeoCAD.dmg LeoCAD-macOS-$(git rev-parse --short HEAD).dmg
|
||||
- 'curl -s -H "Authorization: token $GITHUB_TOKEN" https://api.github.com/repos/leozide/leocad/commits/master -o repo.txt'
|
||||
- 'export REMOTE=$(ggrep -Po ''(?<=: \")(([a-z0-9])\w+)(?=\")'' -m 1 repo.txt)'
|
||||
- export LOCAL=$(git rev-parse HEAD)
|
||||
- if [[ "$REMOTE" != "$LOCAL" ]]; then echo "Build no longer current. $REMOTE vs $LOCAL - aborting upload."; exit 0; fi;
|
||||
- wget -c https://github.com/probonopd/uploadtool/raw/master/upload.sh
|
||||
- bash upload.sh LeoCAD*.dmg*
|
||||
|
||||
branches:
|
||||
except:
|
||||
|
|
48
appveyor.yml
Normal file
48
appveyor.yml
Normal file
|
@ -0,0 +1,48 @@
|
|||
version: '{branch}.{build}'
|
||||
skip_tags: true
|
||||
image:
|
||||
- Visual Studio 2019
|
||||
configuration: Release
|
||||
platform: x64
|
||||
|
||||
environment:
|
||||
GITHUB_TOKEN:
|
||||
secure: +EZPzYX4wUEc6MYg4kBLx9TogAqeeeWUPgtEW3VtAJATrBtxwpuOQIHrrR4hbc7a
|
||||
|
||||
before_build:
|
||||
- call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat"
|
||||
- set PATH=C:\Qt\5.15\msvc2019_64\bin;%PATH%
|
||||
- git rev-parse --short HEAD > version.txt
|
||||
- set /p VERSION= < version.txt
|
||||
- qmake -v
|
||||
- qmake -tp vc
|
||||
|
||||
build:
|
||||
project: leocad.vcxproj
|
||||
verbosity: minimal
|
||||
|
||||
after_build:
|
||||
- 7z a symbols.zip build/release/leocad.exe build/release/leocad.pdb
|
||||
- mkdir appdir
|
||||
- copy build\release\leocad.exe appdir
|
||||
- copy docs\readme.txt appdir
|
||||
- appveyor DownloadFile https://github.com/leozide/leocad/releases/download/v19.07.1/Library-20.03.zip -FileName library.zip
|
||||
- 7z e library.zip
|
||||
- copy library.bin appdir\\library.bin
|
||||
- appveyor DownloadFile https://github.com/leozide/povray/releases/download/continuous/povconsole32-sse2.exe -FileName appdir\povconsole32-sse2.exe
|
||||
- windeployqt appdir\leocad.exe
|
||||
- copy tools\setup\leocad.nsi .
|
||||
- copy tools\setup\setup.ico .
|
||||
- 'copy "%VCToolsRedistDir%\vcredist_x64.exe" appdir'
|
||||
- '"C:\Program Files (x86)\NSIS\makensis.exe" /V4 /DX64 "/XOutFile LeoCAD-Windows-%VERSION%.exe" leocad.nsi'
|
||||
- set TRAVIS_TAG=%APPVEYOR_REPO_TAG_NAME%
|
||||
- set TRAVIS_REPO_SLUG=%APPVEYOR_REPO_NAME%
|
||||
- set TRAVIS_COMMIT=%APPVEYOR_REPO_COMMIT%
|
||||
- appveyor DownloadFile https://github.com/probonopd/uploadtool/raw/master/upload.sh
|
||||
- if not defined APPVEYOR_PULL_REQUEST_NUMBER (bash upload.sh LeoCAD*.exe)
|
||||
|
||||
artifacts:
|
||||
- path: symbols.zip
|
||||
name: symbols
|
||||
- path: LeoCAD-Windows-$(VERSION).exe
|
||||
name: leocad
|
|
@ -28,9 +28,9 @@ lcCamera::lcCamera(bool Simple)
|
|||
mTargetPosition = lcVector3(0.0f, 0.0f, 0.0f);
|
||||
mUpVector = lcVector3(-0.2357f, -0.2357f, 0.94281f);
|
||||
|
||||
ChangeKey(mPositionKeys, mPosition, 1, true);
|
||||
ChangeKey(mTargetPositionKeys, mTargetPosition, 1, true);
|
||||
ChangeKey(mUpVectorKeys, mUpVector, 1, true);
|
||||
mPositionKeys.ChangeKey(mPosition, 1, true);
|
||||
mTargetPositionKeys.ChangeKey(mTargetPosition, 1, true);
|
||||
mUpVectorKeys.ChangeKey(mUpVector, 1, true);
|
||||
|
||||
UpdatePosition(1);
|
||||
}
|
||||
|
@ -51,9 +51,9 @@ lcCamera::lcCamera(float ex, float ey, float ez, float tx, float ty, float tz)
|
|||
|
||||
Initialize();
|
||||
|
||||
ChangeKey(mPositionKeys, lcVector3(ex, ey, ez), 1, true);
|
||||
ChangeKey(mTargetPositionKeys, lcVector3(tx, ty, tz), 1, true);
|
||||
ChangeKey(mUpVectorKeys, UpVector, 1, true);
|
||||
mPositionKeys.ChangeKey(lcVector3(ex, ey, ez), 1, true);
|
||||
mTargetPositionKeys.ChangeKey(lcVector3(tx, ty, tz), 1, true);
|
||||
mUpVectorKeys.ChangeKey(UpVector, 1, true);
|
||||
|
||||
UpdatePosition(1);
|
||||
}
|
||||
|
@ -62,23 +62,50 @@ lcCamera::~lcCamera()
|
|||
{
|
||||
}
|
||||
|
||||
lcViewpoint lcCamera::GetViewpoint(const QString& ViewpointName)
|
||||
{
|
||||
const QLatin1String ViewpointNames[] =
|
||||
{
|
||||
QLatin1String("front"),
|
||||
QLatin1String("back"),
|
||||
QLatin1String("top"),
|
||||
QLatin1String("bottom"),
|
||||
QLatin1String("left"),
|
||||
QLatin1String("right"),
|
||||
QLatin1String("home")
|
||||
};
|
||||
|
||||
LC_ARRAY_SIZE_CHECK(ViewpointNames, lcViewpoint::Count);
|
||||
|
||||
for (int ViewpointIndex = 0; ViewpointIndex < static_cast<int>(lcViewpoint::Count); ViewpointIndex++)
|
||||
if (ViewpointNames[ViewpointIndex] == ViewpointName)
|
||||
return static_cast<lcViewpoint>(ViewpointIndex);
|
||||
|
||||
return lcViewpoint::Count;
|
||||
}
|
||||
|
||||
void lcCamera::Initialize()
|
||||
{
|
||||
m_fovy = 30.0f;
|
||||
m_zNear = 25.0f;
|
||||
m_zFar = 50000.0f;
|
||||
mState = 0;
|
||||
memset(m_strName, 0, sizeof(m_strName));
|
||||
}
|
||||
|
||||
void lcCamera::SetName(const QString& Name)
|
||||
{
|
||||
mName = Name;
|
||||
}
|
||||
|
||||
void lcCamera::CreateName(const lcArray<lcCamera*>& Cameras)
|
||||
{
|
||||
if (m_strName[0])
|
||||
if (!mName.isEmpty())
|
||||
{
|
||||
bool Found = false;
|
||||
for (int CameraIdx = 0; CameraIdx < Cameras.GetSize(); CameraIdx++)
|
||||
|
||||
for (const lcCamera* Camera : Cameras)
|
||||
{
|
||||
if (!strcmp(Cameras[CameraIdx]->m_strName, m_strName))
|
||||
if (Camera->GetName() == mName)
|
||||
{
|
||||
Found = true;
|
||||
break;
|
||||
|
@ -89,16 +116,24 @@ void lcCamera::CreateName(const lcArray<lcCamera*>& Cameras)
|
|||
return;
|
||||
}
|
||||
|
||||
int i, max = 0;
|
||||
const char* Prefix = "Camera ";
|
||||
int MaxCameraNumber = 0;
|
||||
const QLatin1String Prefix("Camera ");
|
||||
|
||||
for (int CameraIdx = 0; CameraIdx < Cameras.GetSize(); CameraIdx++)
|
||||
if (strncmp(Cameras[CameraIdx]->m_strName, Prefix, strlen(Prefix)) == 0)
|
||||
if (sscanf(Cameras[CameraIdx]->m_strName + strlen(Prefix), " %d", &i) == 1)
|
||||
if (i > max)
|
||||
max = i;
|
||||
for (const lcCamera* Camera : Cameras)
|
||||
{
|
||||
QString CameraName = Camera->GetName();
|
||||
|
||||
sprintf(m_strName, "%s %d", Prefix, max+1);
|
||||
if (CameraName.startsWith(Prefix))
|
||||
{
|
||||
bool Ok = false;
|
||||
int CameraNumber = CameraName.midRef(Prefix.size()).toInt(&Ok);
|
||||
|
||||
if (Ok && CameraNumber > MaxCameraNumber)
|
||||
MaxCameraNumber = CameraNumber;
|
||||
}
|
||||
}
|
||||
|
||||
mName = Prefix + QString::number(MaxCameraNumber + 1);
|
||||
}
|
||||
|
||||
void lcCamera::SaveLDraw(QTextStream& Stream) const
|
||||
|
@ -108,17 +143,17 @@ void lcCamera::SaveLDraw(QTextStream& Stream) const
|
|||
Stream << QLatin1String("0 !LEOCAD CAMERA FOV ") << m_fovy << QLatin1String(" ZNEAR ") << m_zNear << QLatin1String(" ZFAR ") << m_zFar << LineEnding;
|
||||
|
||||
if (mPositionKeys.GetSize() > 1)
|
||||
SaveKeysLDraw(Stream, mPositionKeys, "CAMERA POSITION_KEY ");
|
||||
mPositionKeys.SaveKeysLDraw(Stream, "CAMERA POSITION_KEY ");
|
||||
else
|
||||
Stream << QLatin1String("0 !LEOCAD CAMERA POSITION ") << mPosition[0] << ' ' << mPosition[1] << ' ' << mPosition[2] << LineEnding;
|
||||
|
||||
if (mTargetPositionKeys.GetSize() > 1)
|
||||
SaveKeysLDraw(Stream, mTargetPositionKeys, "CAMERA TARGET_POSITION_KEY ");
|
||||
mTargetPositionKeys.SaveKeysLDraw(Stream, "CAMERA TARGET_POSITION_KEY ");
|
||||
else
|
||||
Stream << QLatin1String("0 !LEOCAD CAMERA TARGET_POSITION ") << mTargetPosition[0] << ' ' << mTargetPosition[1] << ' ' << mTargetPosition[2] << LineEnding;
|
||||
|
||||
if (mUpVectorKeys.GetSize() > 1)
|
||||
SaveKeysLDraw(Stream, mUpVectorKeys, "CAMERA UP_VECTOR_KEY ");
|
||||
mUpVectorKeys.SaveKeysLDraw(Stream, "CAMERA UP_VECTOR_KEY ");
|
||||
else
|
||||
Stream << QLatin1String("0 !LEOCAD CAMERA UP_VECTOR ") << mUpVector[0] << ' ' << mUpVector[1] << ' ' << mUpVector[2] << LineEnding;
|
||||
|
||||
|
@ -130,7 +165,7 @@ void lcCamera::SaveLDraw(QTextStream& Stream) const
|
|||
if (IsOrtho())
|
||||
Stream << QLatin1String("ORTHOGRAPHIC ");
|
||||
|
||||
Stream << QLatin1String("NAME ") << m_strName << LineEnding;
|
||||
Stream << QLatin1String("NAME ") << mName << LineEnding;
|
||||
}
|
||||
|
||||
bool lcCamera::ParseLDrawLine(QTextStream& Stream)
|
||||
|
@ -153,30 +188,27 @@ bool lcCamera::ParseLDrawLine(QTextStream& Stream)
|
|||
else if (Token == QLatin1String("POSITION"))
|
||||
{
|
||||
Stream >> mPosition[0] >> mPosition[1] >> mPosition[2];
|
||||
ChangeKey(mPositionKeys, mPosition, 1, true);
|
||||
mPositionKeys.ChangeKey(mPosition, 1, true);
|
||||
}
|
||||
else if (Token == QLatin1String("TARGET_POSITION"))
|
||||
{
|
||||
Stream >> mTargetPosition[0] >> mTargetPosition[1] >> mTargetPosition[2];
|
||||
ChangeKey(mTargetPositionKeys, mTargetPosition, 1, true);
|
||||
mTargetPositionKeys.ChangeKey(mTargetPosition, 1, true);
|
||||
}
|
||||
else if (Token == QLatin1String("UP_VECTOR"))
|
||||
{
|
||||
Stream >> mUpVector[0] >> mUpVector[1] >> mUpVector[2];
|
||||
ChangeKey(mUpVectorKeys, mUpVector, 1, true);
|
||||
mUpVectorKeys.ChangeKey(mUpVector, 1, true);
|
||||
}
|
||||
else if (Token == QLatin1String("POSITION_KEY"))
|
||||
LoadKeysLDraw(Stream, mPositionKeys);
|
||||
mPositionKeys.LoadKeysLDraw(Stream);
|
||||
else if (Token == QLatin1String("TARGET_POSITION_KEY"))
|
||||
LoadKeysLDraw(Stream, mTargetPositionKeys);
|
||||
mTargetPositionKeys.LoadKeysLDraw(Stream);
|
||||
else if (Token == QLatin1String("UP_VECTOR_KEY"))
|
||||
LoadKeysLDraw(Stream, mUpVectorKeys);
|
||||
mUpVectorKeys.LoadKeysLDraw(Stream);
|
||||
else if (Token == QLatin1String("NAME"))
|
||||
{
|
||||
QString Name = Stream.readAll().trimmed();
|
||||
QByteArray NameUtf = Name.toUtf8(); // todo: replace with qstring
|
||||
strncpy(m_strName, NameUtf.constData(), sizeof(m_strName));
|
||||
m_strName[sizeof(m_strName) - 1] = 0;
|
||||
mName = Stream.readAll().trimmed();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -212,13 +244,6 @@ bool lcCamera::FileLoad(lcFile& file)
|
|||
file.ReadU16(&time, 1);
|
||||
file.ReadFloats(param, 4);
|
||||
file.ReadU8(&type, 1);
|
||||
|
||||
if (type == 0)
|
||||
ChangeKey(mPositionKeys, lcVector3(param[0], param[1], param[2]), time, true);
|
||||
else if (type == 1)
|
||||
ChangeKey(mTargetPositionKeys, lcVector3(param[0], param[1], param[2]), time, true);
|
||||
else if (type == 2)
|
||||
ChangeKey(mUpVectorKeys, lcVector3(param[0], param[1], param[2]), time, true);
|
||||
}
|
||||
|
||||
file.ReadU32(&n, 1);
|
||||
|
@ -232,40 +257,25 @@ bool lcCamera::FileLoad(lcFile& file)
|
|||
|
||||
if (version == 4)
|
||||
{
|
||||
file.ReadBuffer(m_strName, 80);
|
||||
m_strName[80] = 0;
|
||||
char Name[81];
|
||||
file.ReadBuffer(Name, 80);
|
||||
}
|
||||
else
|
||||
{
|
||||
ch = file.ReadU8();
|
||||
if (ch == 0xFF)
|
||||
return false; // don't read CString
|
||||
file.ReadBuffer(m_strName, ch);
|
||||
m_strName[ch] = 0;
|
||||
return false;
|
||||
char Name[81];
|
||||
file.ReadBuffer(Name, ch);
|
||||
}
|
||||
|
||||
if (version < 3)
|
||||
{
|
||||
double d[3];
|
||||
float f[3];
|
||||
|
||||
file.ReadDoubles(d, 3);
|
||||
f[0] = (float)d[0];
|
||||
f[1] = (float)d[1];
|
||||
f[2] = (float)d[2];
|
||||
ChangeKey(mPositionKeys, lcVector3(f[0], f[1], f[2]), 1, true);
|
||||
|
||||
file.ReadDoubles(d, 3);
|
||||
f[0] = (float)d[0];
|
||||
f[1] = (float)d[1];
|
||||
f[2] = (float)d[2];
|
||||
ChangeKey(mTargetPositionKeys, lcVector3(f[0], f[1], f[2]), 1, true);
|
||||
|
||||
file.ReadDoubles(d, 3);
|
||||
f[0] = (float)d[0];
|
||||
f[1] = (float)d[1];
|
||||
f[2] = (float)d[2];
|
||||
ChangeKey(mUpVectorKeys, lcVector3(f[0], f[1], f[2]), 1, true);
|
||||
}
|
||||
|
||||
if (version == 3)
|
||||
|
@ -276,31 +286,12 @@ bool lcCamera::FileLoad(lcFile& file)
|
|||
{
|
||||
quint8 step;
|
||||
double eye[3], target[3], up[3];
|
||||
float f[3];
|
||||
|
||||
file.ReadDoubles(eye, 3);
|
||||
file.ReadDoubles(target, 3);
|
||||
file.ReadDoubles(up, 3);
|
||||
file.ReadU8(&step, 1);
|
||||
|
||||
if (up[0] == 0 && up[1] == 0 && up[2] == 0)
|
||||
up[2] = 1;
|
||||
|
||||
f[0] = (float)eye[0];
|
||||
f[1] = (float)eye[1];
|
||||
f[2] = (float)eye[2];
|
||||
ChangeKey(mPositionKeys, lcVector3(f[0], f[1], f[2]), step, true);
|
||||
|
||||
f[0] = (float)target[0];
|
||||
f[1] = (float)target[1];
|
||||
f[2] = (float)target[2];
|
||||
ChangeKey(mTargetPositionKeys, lcVector3(f[0], f[1], f[2]), step, true);
|
||||
|
||||
f[0] = (float)up[0];
|
||||
f[1] = (float)up[1];
|
||||
f[2] = (float)up[2];
|
||||
ChangeKey(mUpVectorKeys, lcVector3(f[0], f[1], f[2]), step, true);
|
||||
|
||||
file.ReadS32(); // snapshot
|
||||
file.ReadS32(); // cam
|
||||
}
|
||||
|
@ -308,9 +299,9 @@ bool lcCamera::FileLoad(lcFile& file)
|
|||
|
||||
if (version < 4)
|
||||
{
|
||||
m_fovy = (float)file.ReadDouble();
|
||||
m_zFar = (float)file.ReadDouble();
|
||||
m_zNear= (float)file.ReadDouble();
|
||||
file.ReadDouble(); // m_fovy
|
||||
file.ReadDouble(); // m_zFar
|
||||
file.ReadDouble(); // m_zNear
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -328,13 +319,6 @@ bool lcCamera::FileLoad(lcFile& file)
|
|||
file.ReadU16(&time, 1);
|
||||
file.ReadFloats(param, 3);
|
||||
file.ReadU8(&type, 1);
|
||||
|
||||
if (type == 0)
|
||||
ChangeKey(mPositionKeys, lcVector3(param[0], param[1], param[2]), time, true);
|
||||
else if (type == 1)
|
||||
ChangeKey(mTargetPositionKeys, lcVector3(param[0], param[1], param[2]), time, true);
|
||||
else if (type == 2)
|
||||
ChangeKey(mUpVectorKeys, lcVector3(param[0], param[1], param[2]), time, true);
|
||||
}
|
||||
|
||||
n = file.ReadS32();
|
||||
|
@ -346,21 +330,18 @@ bool lcCamera::FileLoad(lcFile& file)
|
|||
}
|
||||
}
|
||||
|
||||
file.ReadFloats(&m_fovy, 1);
|
||||
file.ReadFloats(&m_zFar, 1);
|
||||
file.ReadFloats(&m_zNear, 1);
|
||||
float f;
|
||||
file.ReadFloats(&f, 1); // m_fovy
|
||||
file.ReadFloats(&f, 1); // m_zFar
|
||||
file.ReadFloats(&f, 1); // m_zNear
|
||||
|
||||
if (version < 5)
|
||||
{
|
||||
n = file.ReadS32();
|
||||
if (n != 0)
|
||||
mState |= LC_CAMERA_HIDDEN;
|
||||
}
|
||||
else
|
||||
{
|
||||
ch = file.ReadU8();
|
||||
if (ch & 1)
|
||||
mState |= LC_CAMERA_HIDDEN;
|
||||
file.ReadU8();
|
||||
}
|
||||
}
|
||||
|
@ -373,20 +354,6 @@ bool lcCamera::FileLoad(lcFile& file)
|
|||
file.ReadU32(&show, 1);
|
||||
// if (version > 2)
|
||||
file.ReadS32(&user, 1);
|
||||
if (show == 0)
|
||||
mState |= LC_CAMERA_HIDDEN;
|
||||
}
|
||||
|
||||
if (version < 7)
|
||||
{
|
||||
m_zFar *= 25.0f;
|
||||
m_zNear *= 25.0f;
|
||||
|
||||
for (int KeyIdx = 0; KeyIdx < mPositionKeys.GetSize(); KeyIdx++)
|
||||
mPositionKeys[KeyIdx].Value *= 25.0f;
|
||||
|
||||
for (int KeyIdx = 0; KeyIdx < mTargetPositionKeys.GetSize(); KeyIdx++)
|
||||
mTargetPositionKeys[KeyIdx].Value *= 25.0f;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -418,19 +385,19 @@ void lcCamera::MoveSelected(lcStep Step, bool AddKey, const lcVector3& Distance)
|
|||
if (IsSelected(LC_CAMERA_SECTION_POSITION))
|
||||
{
|
||||
mPosition += Distance;
|
||||
ChangeKey(mPositionKeys, mPosition, Step, AddKey);
|
||||
mPositionKeys.ChangeKey(mPosition, Step, AddKey);
|
||||
}
|
||||
|
||||
if (IsSelected(LC_CAMERA_SECTION_TARGET))
|
||||
{
|
||||
mTargetPosition += Distance;
|
||||
ChangeKey(mTargetPositionKeys, mTargetPosition, Step, AddKey);
|
||||
mTargetPositionKeys.ChangeKey(mTargetPosition, Step, AddKey);
|
||||
}
|
||||
else if (IsSelected(LC_CAMERA_SECTION_UPVECTOR))
|
||||
{
|
||||
mUpVector += Distance;
|
||||
mUpVector.Normalize();
|
||||
ChangeKey(mUpVectorKeys, mUpVector, Step, AddKey);
|
||||
mUpVectorKeys.ChangeKey(mUpVector, Step, AddKey);
|
||||
}
|
||||
|
||||
lcVector3 FrontVector(mTargetPosition - mPosition);
|
||||
|
@ -451,10 +418,10 @@ void lcCamera::MoveRelative(const lcVector3& Distance, lcStep Step, bool AddKey)
|
|||
lcVector3 Relative = lcMul30(Distance, lcMatrix44Transpose(mWorldView)) * 5.0f;
|
||||
|
||||
mPosition += Relative;
|
||||
ChangeKey(mPositionKeys, mPosition, Step, AddKey);
|
||||
mPositionKeys.ChangeKey(mPosition, Step, AddKey);
|
||||
|
||||
mTargetPosition += Relative;
|
||||
ChangeKey(mTargetPositionKeys, mTargetPosition, Step, AddKey);
|
||||
mTargetPositionKeys.ChangeKey(mTargetPosition, Step, AddKey);
|
||||
|
||||
UpdatePosition(Step);
|
||||
}
|
||||
|
@ -463,9 +430,9 @@ void lcCamera::UpdatePosition(lcStep Step)
|
|||
{
|
||||
if (!IsSimple())
|
||||
{
|
||||
mPosition = CalculateKey(mPositionKeys, Step);
|
||||
mTargetPosition = CalculateKey(mTargetPositionKeys, Step);
|
||||
mUpVector = CalculateKey(mUpVectorKeys, Step);
|
||||
mPosition = mPositionKeys.CalculateKey(Step);
|
||||
mTargetPosition = mTargetPositionKeys.CalculateKey(Step);
|
||||
mUpVector = mUpVectorKeys.CalculateKey(Step);
|
||||
}
|
||||
|
||||
lcVector3 FrontVector(mPosition - mTargetPosition);
|
||||
|
@ -647,13 +614,13 @@ void lcCamera::DrawInterface(lcContext* Context, const lcScene& Scene) const
|
|||
void lcCamera::RemoveKeyFrames()
|
||||
{
|
||||
mPositionKeys.RemoveAll();
|
||||
ChangeKey(mPositionKeys, mPosition, 1, true);
|
||||
mPositionKeys.ChangeKey(mPosition, 1, true);
|
||||
|
||||
mTargetPositionKeys.RemoveAll();
|
||||
ChangeKey(mTargetPositionKeys, mTargetPosition, 1, true);
|
||||
mTargetPositionKeys.ChangeKey(mTargetPosition, 1, true);
|
||||
|
||||
mUpVectorKeys.RemoveAll();
|
||||
ChangeKey(mUpVectorKeys, mUpVector, 1, true);
|
||||
mUpVectorKeys.ChangeKey(mUpVector, 1, true);
|
||||
}
|
||||
|
||||
void lcCamera::RayTest(lcObjectRayTest& ObjectRayTest) const
|
||||
|
@ -763,27 +730,27 @@ void lcCamera::BoxTest(lcObjectBoxTest& ObjectBoxTest) const
|
|||
|
||||
void lcCamera::InsertTime(lcStep Start, lcStep Time)
|
||||
{
|
||||
lcObject::InsertTime(mPositionKeys, Start, Time);
|
||||
lcObject::InsertTime(mTargetPositionKeys, Start, Time);
|
||||
lcObject::InsertTime(mUpVectorKeys, Start, Time);
|
||||
mPositionKeys.InsertTime(Start, Time);
|
||||
mTargetPositionKeys.InsertTime(Start, Time);
|
||||
mUpVectorKeys.InsertTime(Start, Time);
|
||||
}
|
||||
|
||||
void lcCamera::RemoveTime(lcStep Start, lcStep Time)
|
||||
{
|
||||
lcObject::RemoveTime(mPositionKeys, Start, Time);
|
||||
lcObject::RemoveTime(mTargetPositionKeys, Start, Time);
|
||||
lcObject::RemoveTime(mUpVectorKeys, Start, Time);
|
||||
mPositionKeys.RemoveTime(Start, Time);
|
||||
mTargetPositionKeys.RemoveTime(Start, Time);
|
||||
mUpVectorKeys.RemoveTime(Start, Time);
|
||||
}
|
||||
|
||||
void lcCamera::ZoomExtents(float AspectRatio, const lcVector3& Center, const lcVector3* Points, int NumPoints, lcStep Step, bool AddKey)
|
||||
void lcCamera::ZoomExtents(float AspectRatio, const lcVector3& Center, const std::vector<lcVector3>& Points, lcStep Step, bool AddKey)
|
||||
{
|
||||
if (IsOrtho())
|
||||
{
|
||||
float MinX = FLT_MAX, MaxX = -FLT_MAX, MinY = FLT_MAX, MaxY = -FLT_MAX;
|
||||
|
||||
for (int PointIdx = 0; PointIdx < NumPoints; PointIdx++)
|
||||
for (lcVector3 Point : Points)
|
||||
{
|
||||
lcVector3 Point = lcMul30(Points[PointIdx], mWorldView);
|
||||
Point = lcMul30(Point, mWorldView);
|
||||
|
||||
MinX = lcMin(MinX, Point.x);
|
||||
MinY = lcMin(MinY, Point.y);
|
||||
|
@ -791,8 +758,9 @@ void lcCamera::ZoomExtents(float AspectRatio, const lcVector3& Center, const lcV
|
|||
MaxY = lcMax(MaxY, Point.y);
|
||||
}
|
||||
|
||||
float Width = MaxX - MinX;
|
||||
float Height = MaxY - MinY;
|
||||
lcVector3 ViewCenter = lcMul30(Center, mWorldView);
|
||||
float Width = qMax(fabsf(MaxX - ViewCenter.x), fabsf(ViewCenter.x - MinX)) * 2;
|
||||
float Height = qMax(fabsf(MaxY - ViewCenter.y), fabsf(ViewCenter.y - MinY)) * 2;
|
||||
|
||||
if (Width > Height * AspectRatio)
|
||||
Height = Width / AspectRatio;
|
||||
|
@ -808,15 +776,15 @@ void lcCamera::ZoomExtents(float AspectRatio, const lcVector3& Center, const lcV
|
|||
lcVector3 Position(mPosition + Center - mTargetPosition);
|
||||
lcMatrix44 ProjectionMatrix = lcMatrix44Perspective(m_fovy, AspectRatio, m_zNear, m_zFar);
|
||||
|
||||
std::tie(mPosition, std::ignore) = lcZoomExtents(Position, mWorldView, ProjectionMatrix, Points, NumPoints);
|
||||
std::tie(mPosition, std::ignore) = lcZoomExtents(Position, mWorldView, ProjectionMatrix, Points.data(), Points.size());
|
||||
mTargetPosition = Center;
|
||||
}
|
||||
|
||||
if (IsSimple())
|
||||
AddKey = false;
|
||||
|
||||
ChangeKey(mPositionKeys, mPosition, Step, AddKey);
|
||||
ChangeKey(mTargetPositionKeys, mTargetPosition, Step, AddKey);
|
||||
mPositionKeys.ChangeKey(mPosition, Step, AddKey);
|
||||
mTargetPositionKeys.ChangeKey(mTargetPosition, Step, AddKey);
|
||||
|
||||
UpdatePosition(Step);
|
||||
}
|
||||
|
@ -861,8 +829,8 @@ void lcCamera::ZoomRegion(float AspectRatio, const lcVector3& Position, const lc
|
|||
if (IsSimple())
|
||||
AddKey = false;
|
||||
|
||||
ChangeKey(mPositionKeys, mPosition, Step, AddKey);
|
||||
ChangeKey(mTargetPositionKeys, mTargetPosition, Step, AddKey);
|
||||
mPositionKeys.ChangeKey(mPosition, Step, AddKey);
|
||||
mTargetPositionKeys.ChangeKey(mTargetPosition, Step, AddKey);
|
||||
|
||||
UpdatePosition(Step);
|
||||
}
|
||||
|
@ -890,8 +858,8 @@ void lcCamera::Zoom(float Distance, lcStep Step, bool AddKey)
|
|||
if (IsSimple())
|
||||
AddKey = false;
|
||||
|
||||
ChangeKey(mPositionKeys, mPosition, Step, AddKey);
|
||||
ChangeKey(mTargetPositionKeys, mTargetPosition, Step, AddKey);
|
||||
mPositionKeys.ChangeKey(mPosition, Step, AddKey);
|
||||
mTargetPositionKeys.ChangeKey(mTargetPosition, Step, AddKey);
|
||||
|
||||
UpdatePosition(Step);
|
||||
}
|
||||
|
@ -904,8 +872,8 @@ void lcCamera::Pan(const lcVector3& Distance, lcStep Step, bool AddKey)
|
|||
if (IsSimple())
|
||||
AddKey = false;
|
||||
|
||||
ChangeKey(mPositionKeys, mPosition, Step, AddKey);
|
||||
ChangeKey(mTargetPositionKeys, mTargetPosition, Step, AddKey);
|
||||
mPositionKeys.ChangeKey(mPosition, Step, AddKey);
|
||||
mTargetPositionKeys.ChangeKey(mTargetPosition, Step, AddKey);
|
||||
|
||||
UpdatePosition(Step);
|
||||
}
|
||||
|
@ -935,9 +903,9 @@ void lcCamera::Orbit(float DistanceX, float DistanceY, const lcVector3& CenterPo
|
|||
if (IsSimple())
|
||||
AddKey = false;
|
||||
|
||||
ChangeKey(mPositionKeys, mPosition, Step, AddKey);
|
||||
ChangeKey(mTargetPositionKeys, mTargetPosition, Step, AddKey);
|
||||
ChangeKey(mUpVectorKeys, mUpVector, Step, AddKey);
|
||||
mPositionKeys.ChangeKey(mPosition, Step, AddKey);
|
||||
mTargetPositionKeys.ChangeKey(mTargetPosition, Step, AddKey);
|
||||
mUpVectorKeys.ChangeKey(mUpVector, Step, AddKey);
|
||||
|
||||
UpdatePosition(Step);
|
||||
}
|
||||
|
@ -952,7 +920,7 @@ void lcCamera::Roll(float Distance, lcStep Step, bool AddKey)
|
|||
if (IsSimple())
|
||||
AddKey = false;
|
||||
|
||||
ChangeKey(mUpVectorKeys, mUpVector, Step, AddKey);
|
||||
mUpVectorKeys.ChangeKey(mUpVector, Step, AddKey);
|
||||
|
||||
UpdatePosition(Step);
|
||||
}
|
||||
|
@ -962,18 +930,19 @@ void lcCamera::Center(const lcVector3& NewCenter, lcStep Step, bool AddKey)
|
|||
const lcMatrix44 Inverse = lcMatrix44AffineInverse(mWorldView);
|
||||
const lcVector3 Direction = -lcVector3(Inverse[2]);
|
||||
|
||||
float Yaw, Pitch, Roll;
|
||||
// float Yaw, Pitch, Roll;
|
||||
float Roll;
|
||||
|
||||
if (fabsf(Direction.z) < 0.9999f)
|
||||
{
|
||||
Yaw = atan2f(Direction.y, Direction.x);
|
||||
Pitch = asinf(Direction.z);
|
||||
// Yaw = atan2f(Direction.y, Direction.x);
|
||||
// Pitch = asinf(Direction.z);
|
||||
Roll = atan2f(Inverse[0][2], Inverse[1][2]);
|
||||
}
|
||||
else
|
||||
{
|
||||
Yaw = 0.0f;
|
||||
Pitch = asinf(Direction.z);
|
||||
// Yaw = 0.0f;
|
||||
// Pitch = asinf(Direction.z);
|
||||
Roll = atan2f(Inverse[0][1], Inverse[1][1]);
|
||||
}
|
||||
|
||||
|
@ -995,8 +964,8 @@ void lcCamera::Center(const lcVector3& NewCenter, lcStep Step, bool AddKey)
|
|||
if (IsSimple())
|
||||
AddKey = false;
|
||||
|
||||
ChangeKey(mTargetPositionKeys, mTargetPosition, Step, AddKey);
|
||||
ChangeKey(mUpVectorKeys, mUpVector, Step, AddKey);
|
||||
mTargetPositionKeys.ChangeKey(mTargetPosition, Step, AddKey);
|
||||
mUpVectorKeys.ChangeKey(mUpVector, Step, AddKey);
|
||||
|
||||
UpdatePosition(Step);
|
||||
}
|
||||
|
@ -1005,13 +974,13 @@ void lcCamera::SetViewpoint(lcViewpoint Viewpoint)
|
|||
{
|
||||
lcVector3 Positions[] =
|
||||
{
|
||||
lcVector3( 0.0f, -1250.0f, 0.0f), // LC_VIEWPOINT_FRONT
|
||||
lcVector3( 0.0f, 1250.0f, 0.0f), // LC_VIEWPOINT_BACK
|
||||
lcVector3( 0.0f, 0.0f, 1250.0f), // LC_VIEWPOINT_TOP
|
||||
lcVector3( 0.0f, 0.0f, -1250.0f), // LC_VIEWPOINT_BOTTOM
|
||||
lcVector3( 1250.0f, 0.0f, 0.0f), // LC_VIEWPOINT_LEFT
|
||||
lcVector3(-1250.0f, 0.0f, 0.0f), // LC_VIEWPOINT_RIGHT
|
||||
lcVector3( 375.0f, -375.0f, 187.5f) // LC_VIEWPOINT_HOME
|
||||
lcVector3( 0.0f, -1250.0f, 0.0f), // lcViewpoint::Front
|
||||
lcVector3( 0.0f, 1250.0f, 0.0f), // lcViewpoint::Back
|
||||
lcVector3( 0.0f, 0.0f, 1250.0f), // lcViewpoint::Top
|
||||
lcVector3( 0.0f, 0.0f, -1250.0f), // lcViewpoint::Bottom
|
||||
lcVector3( 1250.0f, 0.0f, 0.0f), // lcViewpoint::Left
|
||||
lcVector3(-1250.0f, 0.0f, 0.0f), // lcViewpoint::Right
|
||||
lcVector3( 375.0f, -375.0f, 187.5f) // lcViewpoint::Home
|
||||
};
|
||||
|
||||
lcVector3 Ups[] =
|
||||
|
@ -1025,13 +994,13 @@ void lcCamera::SetViewpoint(lcViewpoint Viewpoint)
|
|||
lcVector3(0.2357f, -0.2357f, 0.94281f)
|
||||
};
|
||||
|
||||
mPosition = Positions[Viewpoint];
|
||||
mPosition = Positions[static_cast<int>(Viewpoint)];
|
||||
mTargetPosition = lcVector3(0, 0, 0);
|
||||
mUpVector = Ups[Viewpoint];
|
||||
mUpVector = Ups[static_cast<int>(Viewpoint)];
|
||||
|
||||
ChangeKey(mPositionKeys, mPosition, 1, false);
|
||||
ChangeKey(mTargetPositionKeys, mTargetPosition, 1, false);
|
||||
ChangeKey(mUpVectorKeys, mUpVector, 1, false);
|
||||
mPositionKeys.ChangeKey(mPosition, 1, false);
|
||||
mTargetPositionKeys.ChangeKey(mTargetPosition, 1, false);
|
||||
mUpVectorKeys.ChangeKey(mUpVector, 1, false);
|
||||
|
||||
UpdatePosition(1);
|
||||
}
|
||||
|
@ -1051,9 +1020,28 @@ void lcCamera::SetViewpoint(const lcVector3& Position)
|
|||
UpVector.Normalize();
|
||||
mUpVector = UpVector;
|
||||
|
||||
ChangeKey(mPositionKeys, mPosition, 1, false);
|
||||
ChangeKey(mTargetPositionKeys, mTargetPosition, 1, false);
|
||||
ChangeKey(mUpVectorKeys, mUpVector, 1, false);
|
||||
mPositionKeys.ChangeKey(mPosition, 1, false);
|
||||
mTargetPositionKeys.ChangeKey(mTargetPosition, 1, false);
|
||||
mUpVectorKeys.ChangeKey(mUpVector, 1, false);
|
||||
|
||||
UpdatePosition(1);
|
||||
}
|
||||
|
||||
void lcCamera::SetViewpoint(const lcVector3& Position, const lcVector3& Target, const lcVector3& Up)
|
||||
{
|
||||
mPosition = Position;
|
||||
mTargetPosition = Target;
|
||||
|
||||
lcVector3 Direction = Target - Position;
|
||||
lcVector3 UpVector, SideVector;
|
||||
SideVector = lcCross(Direction, Up);
|
||||
UpVector = lcCross(SideVector, Direction);
|
||||
UpVector.Normalize();
|
||||
mUpVector = UpVector;
|
||||
|
||||
mPositionKeys.ChangeKey(mPosition, 1, false);
|
||||
mTargetPositionKeys.ChangeKey(mTargetPosition, 1, false);
|
||||
mUpVectorKeys.ChangeKey(mUpVector, 1, false);
|
||||
|
||||
UpdatePosition(1);
|
||||
}
|
||||
|
@ -1072,9 +1060,9 @@ void lcCamera::SetAngles(float Latitude, float Longitude, float Distance)
|
|||
mPosition = lcMul(mPosition, LatitudeMatrix) * Distance;
|
||||
mUpVector = lcMul(mUpVector, LatitudeMatrix);
|
||||
|
||||
ChangeKey(mPositionKeys, mPosition, 1, false);
|
||||
ChangeKey(mTargetPositionKeys, mTargetPosition, 1, false);
|
||||
ChangeKey(mUpVectorKeys, mUpVector, 1, false);
|
||||
mPositionKeys.ChangeKey(mPosition, 1, false);
|
||||
mTargetPositionKeys.ChangeKey(mTargetPosition, 1, false);
|
||||
mUpVectorKeys.ChangeKey(mUpVector, 1, false);
|
||||
|
||||
UpdatePosition(1);
|
||||
}
|
||||
|
|
|
@ -17,15 +17,16 @@
|
|||
#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 lcViewpoint
|
||||
enum class lcViewpoint
|
||||
{
|
||||
LC_VIEWPOINT_FRONT,
|
||||
LC_VIEWPOINT_BACK,
|
||||
LC_VIEWPOINT_TOP,
|
||||
LC_VIEWPOINT_BOTTOM,
|
||||
LC_VIEWPOINT_LEFT,
|
||||
LC_VIEWPOINT_RIGHT,
|
||||
LC_VIEWPOINT_HOME
|
||||
Front,
|
||||
Back,
|
||||
Top,
|
||||
Bottom,
|
||||
Left,
|
||||
Right,
|
||||
Home,
|
||||
Count
|
||||
};
|
||||
|
||||
enum lcCameraSection
|
||||
|
@ -43,15 +44,16 @@ public:
|
|||
~lcCamera();
|
||||
|
||||
lcCamera(const lcCamera&) = delete;
|
||||
lcCamera(lcCamera&&) = delete;
|
||||
lcCamera& operator=(const lcCamera&) = delete;
|
||||
lcCamera& operator=(lcCamera&&) = delete;
|
||||
|
||||
const char* GetName() const override
|
||||
static lcViewpoint GetViewpoint(const QString& ViewpointName);
|
||||
|
||||
QString GetName() const override
|
||||
{
|
||||
return m_strName;
|
||||
return mName;
|
||||
}
|
||||
|
||||
void SetName(const QString& Name);
|
||||
void CreateName(const lcArray<lcCamera*>& Cameras);
|
||||
|
||||
bool IsSimple() const
|
||||
|
@ -240,17 +242,17 @@ public:
|
|||
|
||||
void SetPosition(const lcVector3& Position, lcStep Step, bool AddKey)
|
||||
{
|
||||
ChangeKey(mPositionKeys, Position, Step, AddKey);
|
||||
mPositionKeys.ChangeKey(Position, Step, AddKey);
|
||||
}
|
||||
|
||||
void SetTargetPosition(const lcVector3& TargetPosition, lcStep Step, bool AddKey)
|
||||
{
|
||||
ChangeKey(mTargetPositionKeys, TargetPosition, Step, AddKey);
|
||||
mTargetPositionKeys.ChangeKey(TargetPosition, Step, AddKey);
|
||||
}
|
||||
|
||||
void SetUpVector(const lcVector3& UpVector, lcStep Step, bool AddKey)
|
||||
{
|
||||
ChangeKey(mPositionKeys, UpVector, Step, AddKey);
|
||||
mPositionKeys.ChangeKey(UpVector, Step, AddKey);
|
||||
}
|
||||
|
||||
float GetOrthoHeight() const
|
||||
|
@ -272,15 +274,14 @@ public:
|
|||
void InsertTime(lcStep Start, lcStep Time);
|
||||
void RemoveTime(lcStep Start, lcStep Time);
|
||||
|
||||
bool FileLoad(lcFile& file);
|
||||
void Select(bool bSelecting, bool bFocus, bool bMultiple);
|
||||
static bool FileLoad(lcFile& file);
|
||||
|
||||
void CompareBoundingBox(lcVector3& Min, lcVector3& Max);
|
||||
void UpdatePosition(lcStep Step);
|
||||
void CopyPosition(const lcCamera* Camera);
|
||||
void CopySettings(const lcCamera* Camera);
|
||||
|
||||
void ZoomExtents(float AspectRatio, const lcVector3& Center, const lcVector3* Points, int NumPoints, lcStep Step, bool AddKey);
|
||||
void ZoomExtents(float AspectRatio, const lcVector3& Center, const std::vector<lcVector3>& Points, lcStep Step, bool AddKey);
|
||||
void ZoomRegion(float AspectRatio, const lcVector3& Position, const lcVector3& TargetPosition, const lcVector3* Corners, lcStep Step, bool AddKey);
|
||||
void Zoom(float Distance, lcStep Step, bool AddKey);
|
||||
void Pan(const lcVector3& Distance, lcStep Step, bool AddKey);
|
||||
|
@ -291,11 +292,10 @@ public:
|
|||
void MoveRelative(const lcVector3& Distance, lcStep Step, bool AddKey);
|
||||
void SetViewpoint(lcViewpoint Viewpoint);
|
||||
void SetViewpoint(const lcVector3& Position);
|
||||
void SetViewpoint(const lcVector3& Position, const lcVector3& Target, const lcVector3& Up);
|
||||
void GetAngles(float& Latitude, float& Longitude, float& Distance) const;
|
||||
void SetAngles(float Latitude, float Longitude, float Distance);
|
||||
|
||||
char m_strName[81];
|
||||
|
||||
float m_fovy;
|
||||
float m_zNear;
|
||||
float m_zFar;
|
||||
|
@ -306,12 +306,12 @@ public:
|
|||
lcVector3 mUpVector;
|
||||
|
||||
protected:
|
||||
lcArray<lcObjectKey<lcVector3>> mPositionKeys;
|
||||
lcArray<lcObjectKey<lcVector3>> mTargetPositionKeys;
|
||||
lcArray<lcObjectKey<lcVector3>> mUpVectorKeys;
|
||||
lcObjectKeyArray<lcVector3> mPositionKeys;
|
||||
lcObjectKeyArray<lcVector3> mTargetPositionKeys;
|
||||
lcObjectKeyArray<lcVector3> mUpVectorKeys;
|
||||
|
||||
void Initialize();
|
||||
|
||||
QString mName;
|
||||
quint32 mState;
|
||||
};
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,9 +1,11 @@
|
|||
#pragma once
|
||||
|
||||
#include "lc_array.h"
|
||||
#include "lc_math.h"
|
||||
|
||||
class Project;
|
||||
class lcPiecesLibrary;
|
||||
enum class lcViewSphereLocation;
|
||||
|
||||
enum class lcShadingMode
|
||||
{
|
||||
|
@ -13,12 +15,10 @@ enum class lcShadingMode
|
|||
Full
|
||||
};
|
||||
|
||||
enum class lcViewSphereLocation
|
||||
enum class lcColorTheme
|
||||
{
|
||||
TopLeft,
|
||||
TopRight,
|
||||
BottomLeft,
|
||||
BottomRight
|
||||
Dark,
|
||||
System
|
||||
};
|
||||
|
||||
class lcPreferences
|
||||
|
@ -26,22 +26,37 @@ class lcPreferences
|
|||
public:
|
||||
void LoadDefaults();
|
||||
void SaveDefaults();
|
||||
void SetInterfaceColors(lcColorTheme ColorTheme);
|
||||
|
||||
int mMouseSensitivity;
|
||||
lcShadingMode mShadingMode;
|
||||
bool mBackgroundGradient;
|
||||
quint32 mBackgroundSolidColor;
|
||||
quint32 mBackgroundGradientColorTop;
|
||||
quint32 mBackgroundGradientColorBottom;
|
||||
bool mDrawAxes;
|
||||
quint32 mAxesColor;
|
||||
quint32 mTextColor;
|
||||
quint32 mMarqueeBorderColor;
|
||||
quint32 mMarqueeFillColor;
|
||||
quint32 mOverlayColor;
|
||||
quint32 mActiveViewColor;
|
||||
quint32 mInactiveViewColor;
|
||||
bool mDrawEdgeLines;
|
||||
float mLineWidth;
|
||||
bool mAllowLOD;
|
||||
float mMeshLODDistance;
|
||||
bool mFadeSteps;
|
||||
quint32 mFadeStepsColor;
|
||||
bool mHighlightNewParts;
|
||||
quint32 mHighlightNewPartsColor;
|
||||
bool mGridEnabled = true;
|
||||
bool mDrawGridStuds;
|
||||
quint32 mGridStudColor;
|
||||
bool mDrawGridLines;
|
||||
int mGridLineSpacing;
|
||||
quint32 mGridLineColor;
|
||||
bool mDrawGridOrigin;
|
||||
bool mFixedAxes;
|
||||
bool mViewSphereEnabled;
|
||||
lcViewSphereLocation mViewSphereLocation;
|
||||
|
@ -51,6 +66,80 @@ public:
|
|||
quint32 mViewSphereHighlightColor;
|
||||
bool mAutoLoadMostRecent;
|
||||
bool mRestoreTabLayout;
|
||||
lcColorTheme mColorTheme;
|
||||
|
||||
int mPreviewViewSphereEnabled;
|
||||
int mPreviewViewSphereSize;
|
||||
lcViewSphereLocation mPreviewViewSphereLocation;
|
||||
int mDrawPreviewAxis;
|
||||
|
||||
quint32 mStudCylinderColor;
|
||||
quint32 mPartEdgeColor;
|
||||
quint32 mBlackEdgeColor;
|
||||
quint32 mDarkEdgeColor;
|
||||
float mPartEdgeContrast;
|
||||
float mPartColorValueLDIndex;
|
||||
bool mAutomateEdgeColor;
|
||||
};
|
||||
|
||||
struct lcCommandLineOptions
|
||||
{
|
||||
bool ParseOK;
|
||||
bool Exit;
|
||||
bool SaveImage;
|
||||
bool SaveWavefront;
|
||||
bool Save3DS;
|
||||
bool SaveCOLLADA;
|
||||
bool SaveHTML;
|
||||
bool SetCameraAngles;
|
||||
bool SetCameraPosition;
|
||||
bool Orthographic;
|
||||
bool SetFoV;
|
||||
bool SetZPlanes;
|
||||
bool SetFadeStepsColor;
|
||||
bool SetHighlightColor;
|
||||
bool FadeSteps;
|
||||
bool ImageHighlight;
|
||||
bool AutomateEdgeColor;
|
||||
int ImageWidth;
|
||||
int ImageHeight;
|
||||
int AASamples;
|
||||
lcShadingMode ShadingMode;
|
||||
float LineWidth;
|
||||
lcStudStyle StudStyle;
|
||||
lcStep ImageStart;
|
||||
lcStep ImageEnd;
|
||||
lcVector3 CameraPosition[3];
|
||||
lcVector2 CameraLatLon;
|
||||
float FoV;
|
||||
float PartEdgeContrast;
|
||||
float PartColorValueLDIndex;
|
||||
lcVector2 ZPlanes;
|
||||
lcViewpoint Viewpoint;
|
||||
quint32 StudCylinderColor;
|
||||
quint32 PartEdgeColor;
|
||||
quint32 BlackEdgeColor;
|
||||
quint32 DarkEdgeColor;
|
||||
quint32 FadeStepsColor;
|
||||
quint32 HighlightColor;
|
||||
QString ImageName;
|
||||
QString ModelName;
|
||||
QString CameraName;
|
||||
QString ProjectName;
|
||||
QString SaveWavefrontName;
|
||||
QString Save3DSName;
|
||||
QString SaveCOLLADAName;
|
||||
QString SaveHTMLName;
|
||||
QList<QPair<QString, bool>> LibraryPaths;
|
||||
QString StdOut;
|
||||
QString StdErr;
|
||||
};
|
||||
|
||||
enum class lcStartupMode
|
||||
{
|
||||
ShowWindow,
|
||||
Success,
|
||||
Error
|
||||
};
|
||||
|
||||
class lcApplication : public QApplication
|
||||
|
@ -62,23 +151,29 @@ public:
|
|||
~lcApplication();
|
||||
|
||||
void SetProject(Project* Project);
|
||||
bool Initialize(QList<QPair<QString, bool>>& LibraryPaths, bool& ShowWindow);
|
||||
static lcCommandLineOptions ParseCommandLineOptions();
|
||||
lcStartupMode Initialize(const QList<QPair<QString, bool>>& LibraryPaths);
|
||||
void Shutdown();
|
||||
void ShowPreferencesDialog();
|
||||
void SaveTabLayout() const;
|
||||
|
||||
bool LoadPartsLibrary(const QList<QPair<QString, bool>>& LibraryPaths, bool OnlyUsePaths, bool ShowProgress);
|
||||
bool LoadPartsLibrary(const QList<QPair<QString, bool>>& LibraryPaths, bool OnlyUsePaths);
|
||||
|
||||
void SetClipboard(const QByteArray& Clipboard);
|
||||
void ExportClipboard(const QByteArray& Clipboard);
|
||||
|
||||
Project* mProject;
|
||||
lcPiecesLibrary* mLibrary;
|
||||
Project* mProject = nullptr;
|
||||
lcPiecesLibrary* mLibrary = nullptr;
|
||||
lcPreferences mPreferences;
|
||||
QByteArray mClipboard;
|
||||
|
||||
protected:
|
||||
bool InitializeRenderer();
|
||||
void ShutdownRenderer();
|
||||
void UpdateStyle();
|
||||
QString GetTabLayoutKey() const;
|
||||
|
||||
QString mDefaultStyle;
|
||||
};
|
||||
|
||||
extern lcApplication* gApplication;
|
||||
|
@ -97,4 +192,3 @@ inline lcPreferences& lcGetPreferences()
|
|||
{
|
||||
return gApplication->mPreferences;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,47 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "lc_math.h"
|
||||
#include "lc_array.h"
|
||||
#include "lc_application.h"
|
||||
#include "lc_model.h"
|
||||
#include "lc_category.h"
|
||||
#include "lc_shortcuts.h"
|
||||
#include "image.h"
|
||||
|
||||
struct lcPropertiesDialogOptions
|
||||
{
|
||||
lcModelProperties Properties;
|
||||
bool SetDefault;
|
||||
|
||||
lcPartsList PartsList;
|
||||
};
|
||||
|
||||
struct lcPreferencesDialogOptions
|
||||
{
|
||||
lcPreferences Preferences;
|
||||
|
||||
QString LibraryPath;
|
||||
QString ColorConfigPath;
|
||||
QString MinifigSettingsPath;
|
||||
QString POVRayPath;
|
||||
QString LGEOPath;
|
||||
QString DefaultAuthor;
|
||||
QString Language;
|
||||
int CheckForUpdates;
|
||||
|
||||
int AASamples;
|
||||
int StudLogo;
|
||||
|
||||
std::vector<lcLibraryCategory> Categories;
|
||||
bool CategoriesModified;
|
||||
bool CategoriesDefault;
|
||||
|
||||
lcKeyboardShortcuts KeyboardShortcuts;
|
||||
bool KeyboardShortcutsModified;
|
||||
bool KeyboardShortcutsDefault;
|
||||
|
||||
lcMouseShortcuts MouseShortcuts;
|
||||
bool MouseShortcutsModified;
|
||||
bool MouseShortcutsDefault;
|
||||
};
|
||||
|
88
common/lc_collapsiblewidget.cpp
Normal file
88
common/lc_collapsiblewidget.cpp
Normal file
|
@ -0,0 +1,88 @@
|
|||
#include "lc_global.h"
|
||||
#include "lc_collapsiblewidget.h"
|
||||
|
||||
QImage lcCollapsibleWidget::mExpandedIcon;
|
||||
QImage lcCollapsibleWidget::mCollapsedIcon;
|
||||
|
||||
lcCollapsibleWidget::lcCollapsibleWidget(const QString& Title, QWidget* Parent)
|
||||
: QWidget(Parent)
|
||||
{
|
||||
QVBoxLayout* Layout = new QVBoxLayout(this);
|
||||
// Layout->setSpacing(0);
|
||||
Layout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
QHBoxLayout* TitleLayout = new QHBoxLayout();
|
||||
TitleLayout->setContentsMargins(0, 0, 0, 0);
|
||||
Layout->addLayout(TitleLayout);
|
||||
|
||||
mTitleButton = new QToolButton(this);
|
||||
mTitleButton->setText(Title);
|
||||
mTitleButton->setAutoRaise(true);
|
||||
mTitleButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
|
||||
mTitleButton->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Maximum);
|
||||
TitleLayout->addWidget(mTitleButton);
|
||||
|
||||
connect(mTitleButton, SIGNAL(clicked()), this, SLOT(TitleClicked()));
|
||||
|
||||
mChildWidget = new QWidget(this);
|
||||
Layout->addWidget(mChildWidget);
|
||||
|
||||
UpdateIcon();
|
||||
}
|
||||
|
||||
void lcCollapsibleWidget::TitleClicked()
|
||||
{
|
||||
mExpanded = !mExpanded;
|
||||
mChildWidget->setVisible(mExpanded);
|
||||
UpdateIcon();
|
||||
}
|
||||
|
||||
void lcCollapsibleWidget::Collapse()
|
||||
{
|
||||
if (mExpanded)
|
||||
TitleClicked();
|
||||
}
|
||||
|
||||
void lcCollapsibleWidget::SetChildLayout(QLayout* Layout)
|
||||
{
|
||||
Layout->setContentsMargins(12, 0, 0, 0);
|
||||
mChildWidget->setLayout(Layout);
|
||||
}
|
||||
|
||||
void lcCollapsibleWidget::UpdateIcon()
|
||||
{
|
||||
if (mExpanded)
|
||||
{
|
||||
if (mExpandedIcon.isNull())
|
||||
{
|
||||
QImage Image(16, 16, QImage::Format::Format_ARGB32);
|
||||
Image.fill(QColor(0, 0, 0, 0));
|
||||
uint Color = palette().color(QPalette::Text).rgba();
|
||||
|
||||
for (int y = 0; y < 8; y++)
|
||||
for (int x = y; x < 8 - y; x++)
|
||||
Image.setPixel(x + 4, y + 6, Color);
|
||||
|
||||
mExpandedIcon = Image;
|
||||
}
|
||||
|
||||
mTitleButton->setIcon(QPixmap::fromImage(mExpandedIcon));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mCollapsedIcon.isNull())
|
||||
{
|
||||
QImage Image(16, 16, QImage::Format::Format_ARGB32);
|
||||
Image.fill(QColor(0, 0, 0, 0));
|
||||
uint Color = palette().color(QPalette::Text).rgba();
|
||||
|
||||
for (int y = 0; y < 8; y++)
|
||||
for (int x = y; x < 8 - y; x++)
|
||||
Image.setPixel(y + 6, x + 4, Color);
|
||||
|
||||
mCollapsedIcon = Image;
|
||||
}
|
||||
|
||||
mTitleButton->setIcon(QPixmap::fromImage(mCollapsedIcon));
|
||||
}
|
||||
}
|
25
common/lc_collapsiblewidget.h
Normal file
25
common/lc_collapsiblewidget.h
Normal file
|
@ -0,0 +1,25 @@
|
|||
#pragma once
|
||||
|
||||
class lcCollapsibleWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
lcCollapsibleWidget(const QString& RootTitle, QWidget* Parent = nullptr);
|
||||
|
||||
void Collapse();
|
||||
void SetChildLayout(QLayout* Layout);
|
||||
|
||||
protected slots:
|
||||
void TitleClicked();
|
||||
|
||||
protected:
|
||||
void UpdateIcon();
|
||||
|
||||
QToolButton* mTitleButton = nullptr;
|
||||
QWidget* mChildWidget = nullptr;
|
||||
bool mExpanded = true;
|
||||
|
||||
static QImage mExpandedIcon;
|
||||
static QImage mCollapsedIcon;
|
||||
};
|
|
@ -1,11 +1,12 @@
|
|||
#include "lc_global.h"
|
||||
#include "lc_colors.h"
|
||||
#include "lc_file.h"
|
||||
#include "lc_library.h"
|
||||
#include "lc_application.h"
|
||||
#include <float.h>
|
||||
|
||||
std::vector<lcColor> gColorList;
|
||||
lcColorGroup gColorGroups[LC_NUM_COLORGROUPS];
|
||||
int gNumUserColors;
|
||||
int gEdgeColor;
|
||||
int gDefaultColor;
|
||||
|
||||
|
@ -209,46 +210,54 @@ int lcGetBrickLinkColor(int ColorIndex)
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool lcLoadColorFile(lcFile& File)
|
||||
static void lcAdjustStudStyleColors(std::vector<lcColor>& Colors, lcStudStyle StudStyle)
|
||||
{
|
||||
const lcPreferences& Preferences = lcGetPreferences();
|
||||
|
||||
if (!Preferences.mAutomateEdgeColor && !lcIsHighContrast(StudStyle))
|
||||
return;
|
||||
|
||||
const lcVector4 Edge = lcVector4FromColor(Preferences.mPartEdgeColor);
|
||||
const lcVector4 DarkEdge = lcVector4FromColor(Preferences.mDarkEdgeColor);
|
||||
const lcVector4 BlackEdge = lcVector4FromColor(Preferences.mBlackEdgeColor);
|
||||
|
||||
const float ContrastControl = Preferences.mPartEdgeContrast;
|
||||
const float LightDarkControl = Preferences.mAutomateEdgeColor ? Preferences.mPartColorValueLDIndex : LC_SRGB_TO_LINEAR(Preferences.mPartColorValueLDIndex);
|
||||
|
||||
for (lcColor& Color : Colors)
|
||||
{
|
||||
lcVector3 LinearColor = lcSRGBToLinear(lcVector3(Color.Value));
|
||||
const float ValueLuminescence = lcLuminescence(LinearColor);
|
||||
|
||||
if (Preferences.mAutomateEdgeColor)
|
||||
{
|
||||
if (Color.Adjusted)
|
||||
continue;
|
||||
|
||||
const float EdgeLuminescence = lcLuminescence(lcSRGBToLinear(lcVector3(Color.Edge)));
|
||||
|
||||
Color.Edge = lcAlgorithmicEdgeColor(LinearColor, ValueLuminescence, EdgeLuminescence, ContrastControl, LightDarkControl);
|
||||
Color.Adjusted = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Color.Code == 4242)
|
||||
continue;
|
||||
else if (Color.Code == 0)
|
||||
Color.Edge = BlackEdge;
|
||||
else if (ValueLuminescence < LightDarkControl)
|
||||
Color.Edge = DarkEdge;
|
||||
else
|
||||
Color.Edge = Edge;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static std::vector<lcColor> lcParseColorFile(lcFile& File)
|
||||
{
|
||||
char Line[1024], Token[1024];
|
||||
std::vector<lcColor>& Colors = gColorList;
|
||||
lcColor Color, MainColor, EdgeColor;
|
||||
|
||||
Colors.clear();
|
||||
|
||||
for (int GroupIdx = 0; GroupIdx < LC_NUM_COLORGROUPS; GroupIdx++)
|
||||
gColorGroups[GroupIdx].Colors.clear();
|
||||
|
||||
gColorGroups[0].Name = QApplication::tr("Solid Colors", "Colors");
|
||||
gColorGroups[1].Name = QApplication::tr("Translucent Colors", "Colors");
|
||||
gColorGroups[2].Name = QApplication::tr("Special Colors", "Colors");
|
||||
|
||||
MainColor.Code = 16;
|
||||
MainColor.Translucent = false;
|
||||
MainColor.Value[0] = 1.0f;
|
||||
MainColor.Value[1] = 1.0f;
|
||||
MainColor.Value[2] = 0.5f;
|
||||
MainColor.Value[3] = 1.0f;
|
||||
MainColor.Edge[0] = 0.2f;
|
||||
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");
|
||||
|
||||
EdgeColor.Code = 24;
|
||||
EdgeColor.Translucent = false;
|
||||
EdgeColor.Value[0] = 0.5f;
|
||||
EdgeColor.Value[1] = 0.5f;
|
||||
EdgeColor.Value[2] = 0.5f;
|
||||
EdgeColor.Value[3] = 1.0f;
|
||||
EdgeColor.Edge[0] = 0.2f;
|
||||
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");
|
||||
std::vector<lcColor> Colors;
|
||||
lcColor Color;
|
||||
|
||||
while (File.ReadLine(Line, sizeof(Line)))
|
||||
{
|
||||
|
@ -263,11 +272,9 @@ bool lcLoadColorFile(lcFile& File)
|
|||
if (strcmp(Token, "!COLOUR"))
|
||||
continue;
|
||||
|
||||
bool GroupTranslucent = false;
|
||||
bool GroupSpecial = false;
|
||||
|
||||
Color.Code = ~0U;
|
||||
Color.Translucent = false;
|
||||
Color.Group = LC_COLORGROUP_SOLID;
|
||||
Color.Value[0] = FLT_MAX;
|
||||
Color.Value[1] = FLT_MAX;
|
||||
Color.Value[2] = FLT_MAX;
|
||||
|
@ -335,18 +342,18 @@ bool lcLoadColorFile(lcFile& File)
|
|||
Color.Translucent = true;
|
||||
|
||||
if (Value == 128)
|
||||
GroupTranslucent = true;
|
||||
Color.Group = LC_COLORGROUP_TRANSLUCENT;
|
||||
else if (Value != 0)
|
||||
GroupSpecial = true;
|
||||
Color.Group = LC_COLORGROUP_SPECIAL;
|
||||
}
|
||||
else if (!strcmp(Token, "CHROME") || !strcmp(Token, "PEARLESCENT") || !strcmp(Token, "RUBBER") ||
|
||||
!strcmp(Token, "MATTE_METALIC") || !strcmp(Token, "METAL") || !strcmp(Token, "LUMINANCE"))
|
||||
!strcmp(Token, "MATTE_METALIC") || !strcmp(Token, "METAL") || !strcmp(Token, "LUMINANCE"))
|
||||
{
|
||||
GroupSpecial = true;
|
||||
Color.Group = LC_COLORGROUP_SPECIAL;
|
||||
}
|
||||
else if (!strcmp(Token, "MATERIAL"))
|
||||
{
|
||||
GroupSpecial = true;
|
||||
Color.Group = LC_COLORGROUP_SPECIAL;
|
||||
break; // Material is always last so ignore it and the rest of the line.
|
||||
}
|
||||
}
|
||||
|
@ -373,62 +380,165 @@ bool lcLoadColorFile(lcFile& File)
|
|||
}
|
||||
}
|
||||
|
||||
if (Duplicate)
|
||||
continue;
|
||||
|
||||
if (Color.Code == 16)
|
||||
{
|
||||
MainColor = Color;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Color.Code == 24)
|
||||
{
|
||||
EdgeColor = Color;
|
||||
continue;
|
||||
}
|
||||
|
||||
Colors.push_back(Color);
|
||||
|
||||
if (GroupSpecial)
|
||||
gColorGroups[LC_COLORGROUP_SPECIAL].Colors.push_back((int)Colors.size() - 1);
|
||||
else if (GroupTranslucent)
|
||||
gColorGroups[LC_COLORGROUP_TRANSLUCENT].Colors.push_back((int)Colors.size() - 1);
|
||||
else
|
||||
gColorGroups[LC_COLORGROUP_SOLID].Colors.push_back((int)Colors.size() - 1);
|
||||
if (!Duplicate)
|
||||
Colors.push_back(Color);
|
||||
}
|
||||
|
||||
gDefaultColor = (int)Colors.size();
|
||||
Colors.push_back(MainColor);
|
||||
gColorGroups[LC_COLORGROUP_SOLID].Colors.push_back(gDefaultColor);
|
||||
|
||||
gNumUserColors = (int)Colors.size();
|
||||
|
||||
gEdgeColor = (int)Colors.size();
|
||||
Colors.push_back(EdgeColor);
|
||||
|
||||
return Colors.size() > 2;
|
||||
return Colors;
|
||||
}
|
||||
|
||||
void lcLoadDefaultColors()
|
||||
bool lcLoadColorFile(lcFile& File, lcStudStyle StudStyle)
|
||||
{
|
||||
QResource Resource(":/resources/ldconfig.ldr");
|
||||
std::vector<lcColor> Colors = lcParseColorFile(File);
|
||||
const bool Valid = !Colors.empty();
|
||||
|
||||
if (!Resource.isValid())
|
||||
return;
|
||||
if (Valid)
|
||||
lcAdjustStudStyleColors(Colors, StudStyle);
|
||||
|
||||
QByteArray Data;
|
||||
bool FoundMain = false, FoundEdge = false, FoundStud = false, FoundNoColor = false;
|
||||
|
||||
if (Resource.isCompressed())
|
||||
Data = qUncompress(Resource.data(), Resource.size());
|
||||
else
|
||||
Data = QByteArray::fromRawData((const char*)Resource.data(), Resource.size());
|
||||
for (const lcColor& Color : Colors)
|
||||
{
|
||||
switch (Color.Code)
|
||||
{
|
||||
case 16:
|
||||
FoundMain = true;
|
||||
break;
|
||||
|
||||
lcMemFile MemSettings;
|
||||
case 24:
|
||||
FoundEdge = true;
|
||||
break;
|
||||
|
||||
MemSettings.WriteBuffer(Data.constData(), Data.size());
|
||||
MemSettings.Seek(0, SEEK_SET);
|
||||
lcLoadColorFile(MemSettings);
|
||||
case 4242:
|
||||
FoundStud = true;
|
||||
break;
|
||||
|
||||
case LC_COLOR_NOCOLOR:
|
||||
FoundNoColor = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!FoundMain)
|
||||
{
|
||||
lcColor MainColor;
|
||||
|
||||
MainColor.Code = 16;
|
||||
MainColor.Translucent = false;
|
||||
MainColor.Group = LC_COLORGROUP_SOLID;
|
||||
MainColor.Value[0] = 1.0f;
|
||||
MainColor.Value[1] = 1.0f;
|
||||
MainColor.Value[2] = 0.5f;
|
||||
MainColor.Value[3] = 1.0f;
|
||||
MainColor.Edge[0] = 0.2f;
|
||||
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");
|
||||
|
||||
Colors.push_back(MainColor);
|
||||
}
|
||||
|
||||
if (!FoundEdge)
|
||||
{
|
||||
lcColor EdgeColor;
|
||||
|
||||
EdgeColor.Code = 24;
|
||||
EdgeColor.Translucent = false;
|
||||
EdgeColor.Group = LC_NUM_COLORGROUPS;
|
||||
EdgeColor.Value[0] = 0.5f;
|
||||
EdgeColor.Value[1] = 0.5f;
|
||||
EdgeColor.Value[2] = 0.5f;
|
||||
EdgeColor.Value[3] = 1.0f;
|
||||
EdgeColor.Edge[0] = 0.2f;
|
||||
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");
|
||||
|
||||
Colors.push_back(EdgeColor);
|
||||
}
|
||||
|
||||
if (!FoundStud)
|
||||
{
|
||||
const lcPreferences& Preferences = lcGetPreferences();
|
||||
lcColor StudCylinderColor;
|
||||
|
||||
StudCylinderColor.Code = 4242;
|
||||
StudCylinderColor.Translucent = false;
|
||||
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");
|
||||
|
||||
Colors.push_back(StudCylinderColor);
|
||||
}
|
||||
|
||||
if (!FoundNoColor)
|
||||
{
|
||||
lcColor NoColor;
|
||||
|
||||
NoColor.Code = LC_COLOR_NOCOLOR;
|
||||
NoColor.Translucent = false;
|
||||
NoColor.Group = LC_NUM_COLORGROUPS;
|
||||
NoColor.Value[0] = 0.5f;
|
||||
NoColor.Value[1] = 0.5f;
|
||||
NoColor.Value[2] = 0.5f;
|
||||
NoColor.Value[3] = 1.0f;
|
||||
NoColor.Edge[0] = 0.2f;
|
||||
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");
|
||||
|
||||
Colors.push_back(NoColor);
|
||||
}
|
||||
|
||||
for (lcColor& Color : gColorList)
|
||||
Color.Group = LC_NUM_COLORGROUPS;
|
||||
|
||||
for (int GroupIdx = 0; GroupIdx < LC_NUM_COLORGROUPS; GroupIdx++)
|
||||
gColorGroups[GroupIdx].Colors.clear();
|
||||
|
||||
gColorGroups[0].Name = QApplication::tr("Solid", "Colors");
|
||||
gColorGroups[1].Name = QApplication::tr("Translucent", "Colors");
|
||||
gColorGroups[2].Name = QApplication::tr("Special", "Colors");
|
||||
|
||||
for (lcColor& Color : Colors)
|
||||
{
|
||||
int ColorIndex;
|
||||
|
||||
for (ColorIndex = 0; ColorIndex < static_cast<int>(gColorList.size()); ColorIndex++)
|
||||
if (gColorList[ColorIndex].Code == Color.Code)
|
||||
break;
|
||||
|
||||
if (ColorIndex == static_cast<int>(gColorList.size()))
|
||||
gColorList.push_back(Color);
|
||||
else
|
||||
gColorList[ColorIndex] = Color;
|
||||
|
||||
if (Color.Group != LC_NUM_COLORGROUPS)
|
||||
gColorGroups[Color.Group].Colors.push_back(ColorIndex);
|
||||
|
||||
if (Color.Code == 16)
|
||||
gDefaultColor = ColorIndex;
|
||||
else if (Color.Code == 24)
|
||||
gEdgeColor = ColorIndex;
|
||||
}
|
||||
|
||||
return Valid;
|
||||
}
|
||||
|
||||
void lcLoadDefaultColors(lcStudStyle StudStyle)
|
||||
{
|
||||
lcDiskFile ConfigFile(":/resources/ldconfig.ldr");
|
||||
|
||||
if (ConfigFile.Open(QIODevice::ReadOnly))
|
||||
lcLoadColorFile(ConfigFile, StudStyle);
|
||||
}
|
||||
|
||||
int lcGetColorIndex(quint32 ColorCode)
|
||||
|
@ -449,8 +559,8 @@ int lcGetColorIndex(quint32 ColorCode)
|
|||
if (ColorCode & LC_COLOR_DIRECT)
|
||||
{
|
||||
Color.Value[0] = (float)((ColorCode & 0xff0000) >> 16) / 255.0f;
|
||||
Color.Value[1] = (float)((ColorCode & 0x00ff00) >> 8) / 255.0f;
|
||||
Color.Value[2] = (float)((ColorCode & 0x0000ff) >> 0) / 255.0f;
|
||||
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);
|
||||
|
|
|
@ -5,11 +5,14 @@
|
|||
|
||||
#define LC_MAX_COLOR_NAME 64
|
||||
#define LC_COLOR_DIRECT 0x80000000
|
||||
#define LC_COLOR_NOCOLOR 0xffffffff
|
||||
|
||||
struct lcColor
|
||||
{
|
||||
quint32 Code;
|
||||
bool Translucent;
|
||||
int Group;
|
||||
bool Translucent = false;
|
||||
bool Adjusted = false;
|
||||
lcVector4 Value;
|
||||
lcVector4 Edge;
|
||||
char Name[LC_MAX_COLOR_NAME];
|
||||
|
@ -44,25 +47,24 @@ enum lcInterfaceColor
|
|||
extern lcVector4 gInterfaceColors[LC_NUM_INTERFACECOLORS];
|
||||
extern std::vector<lcColor> gColorList;
|
||||
extern lcColorGroup gColorGroups[LC_NUM_COLORGROUPS];
|
||||
extern int gNumUserColors;
|
||||
extern int gEdgeColor;
|
||||
extern int gDefaultColor;
|
||||
|
||||
void lcLoadDefaultColors();
|
||||
bool lcLoadColorFile(lcFile& File);
|
||||
void lcLoadDefaultColors(lcStudStyle StudStyle);
|
||||
bool lcLoadColorFile(lcFile& File, lcStudStyle StudStyle);
|
||||
int lcGetColorIndex(quint32 ColorCode);
|
||||
int lcGetBrickLinkColor(int ColorIndex);
|
||||
|
||||
inline quint32 lcGetColorCodeFromExtendedColor(int Color)
|
||||
{
|
||||
const int ConverstionTable[] = { 4, 12, 2, 10, 1, 9, 14, 15, 8, 0, 6, 13, 13, 334, 36, 44, 34, 42, 33, 41, 46, 47, 7, 382, 6, 13, 11, 383 };
|
||||
return ConverstionTable[Color];
|
||||
const quint32 ConversionTable[] = { 4, 12, 2, 10, 1, 9, 14, 15, 8, 0, 6, 13, 13, 334, 36, 44, 34, 42, 33, 41, 46, 47, 7, 382, 6, 13, 11, 383 };
|
||||
return ConversionTable[Color];
|
||||
}
|
||||
|
||||
inline quint32 lcGetColorCodeFromOriginalColor(int Color)
|
||||
{
|
||||
const int ConverstionTable[] = { 0, 2, 4, 9, 7, 6, 22, 8, 10, 11, 14, 16, 18, 9, 21, 20, 22, 8, 10, 11 };
|
||||
return lcGetColorCodeFromExtendedColor(ConverstionTable[Color]);
|
||||
const quint32 ConversionTable[] = { 0, 2, 4, 9, 7, 6, 22, 8, 10, 11, 14, 16, 18, 9, 21, 20, 22, 8, 10, 11 };
|
||||
return lcGetColorCodeFromExtendedColor(ConversionTable[Color]);
|
||||
}
|
||||
|
||||
inline quint32 lcGetColorCode(int ColorIndex)
|
||||
|
@ -74,4 +76,3 @@ inline bool lcIsColorTranslucent(size_t ColorIndex)
|
|||
{
|
||||
return gColorList[ColorIndex].Translucent;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#include "lc_global.h"
|
||||
#include "lc_commands.h"
|
||||
|
||||
lcCommand gCommands[LC_NUM_COMMANDS] =
|
||||
const lcCommand gCommands[] =
|
||||
{
|
||||
// LC_FILE_NEW
|
||||
{
|
||||
|
@ -115,6 +115,13 @@ lcCommand gCommands[LC_NUM_COMMANDS] =
|
|||
QT_TRANSLATE_NOOP("Status", "Render the current model using POV-Ray"),
|
||||
""
|
||||
},
|
||||
// LC_FILE_INSTRUCTIONS
|
||||
{
|
||||
QT_TRANSLATE_NOOP("Action", "File.Instructions"),
|
||||
QT_TRANSLATE_NOOP("Menu", "&Instructions..."),
|
||||
QT_TRANSLATE_NOOP("Status", "Configure instructions layout"),
|
||||
""
|
||||
},
|
||||
// LC_FILE_PRINT
|
||||
{
|
||||
QT_TRANSLATE_NOOP("Action", "File.Print"),
|
||||
|
@ -129,13 +136,6 @@ lcCommand gCommands[LC_NUM_COMMANDS] =
|
|||
QT_TRANSLATE_NOOP("Status", "Display how the model would look if printed"),
|
||||
""
|
||||
},
|
||||
// LC_FILE_PRINT_BOM
|
||||
{
|
||||
QT_TRANSLATE_NOOP("Action", "File.PrintBOM"),
|
||||
QT_TRANSLATE_NOOP("Menu", "Print &Bill of Materials..."),
|
||||
QT_TRANSLATE_NOOP("Status", "Print a list of parts used"),
|
||||
""
|
||||
},
|
||||
// LC_FILE_RECENT1
|
||||
{
|
||||
QT_TRANSLATE_NOOP("Action", "File.Recent1"),
|
||||
|
@ -203,30 +203,65 @@ lcCommand gCommands[LC_NUM_COMMANDS] =
|
|||
{
|
||||
QT_TRANSLATE_NOOP("Action", "Edit.Paste"),
|
||||
QT_TRANSLATE_NOOP("Menu", "&Paste"),
|
||||
QT_TRANSLATE_NOOP("Status", "Insert Clipboard contents"),
|
||||
QT_TRANSLATE_NOOP("Status", "Insert Clipboard contents in the current step"),
|
||||
"Ctrl+V"
|
||||
},
|
||||
// LC_EDIT_PASTE_STEPS
|
||||
{
|
||||
QT_TRANSLATE_NOOP("Action", "Edit.PasteSteps"),
|
||||
QT_TRANSLATE_NOOP("Menu", "Paste with Steps"),
|
||||
QT_TRANSLATE_NOOP("Status", "Insert Clipboard contents in their original steps"),
|
||||
""
|
||||
},
|
||||
// LC_EDIT_FIND
|
||||
{
|
||||
QT_TRANSLATE_NOOP("Action", "Edit.Find"),
|
||||
QT_TRANSLATE_NOOP("Menu", "&Find..."),
|
||||
QT_TRANSLATE_NOOP("Status", "Find object"),
|
||||
QT_TRANSLATE_NOOP("Menu", "&Find"),
|
||||
QT_TRANSLATE_NOOP("Status", "Find piece"),
|
||||
"Ctrl+F"
|
||||
},
|
||||
// LC_EDIT_FIND_NEXT
|
||||
{
|
||||
QT_TRANSLATE_NOOP("Action", "Edit.FindNext"),
|
||||
QT_TRANSLATE_NOOP("Menu", "Find Ne&xt"),
|
||||
QT_TRANSLATE_NOOP("Status", "Find next object"),
|
||||
QT_TRANSLATE_NOOP("Status", "Find next piece"),
|
||||
"F3"
|
||||
},
|
||||
// LC_EDIT_FIND_PREVIOUS
|
||||
{
|
||||
QT_TRANSLATE_NOOP("Action", "Edit.FindPrevious"),
|
||||
QT_TRANSLATE_NOOP("Menu", "Find Pre&vious"),
|
||||
QT_TRANSLATE_NOOP("Status", "Find object"),
|
||||
QT_TRANSLATE_NOOP("Status", "Find previous piece"),
|
||||
"Shift+F3"
|
||||
},
|
||||
// LC_EDIT_FIND_ALL
|
||||
{
|
||||
QT_TRANSLATE_NOOP("Action", "Edit.FindAll"),
|
||||
QT_TRANSLATE_NOOP("Menu", "Find All"),
|
||||
QT_TRANSLATE_NOOP("Status", "Find all pieces that match the search criteria"),
|
||||
""
|
||||
},
|
||||
// LC_EDIT_REPLACE
|
||||
{
|
||||
QT_TRANSLATE_NOOP("Action", "Edit.Replace"),
|
||||
QT_TRANSLATE_NOOP("Menu", "&Replace"),
|
||||
QT_TRANSLATE_NOOP("Status", "Replace piece"),
|
||||
""
|
||||
},
|
||||
// LC_EDIT_REPLACE_NEXT
|
||||
{
|
||||
QT_TRANSLATE_NOOP("Action", "Edit.ReplaceNext"),
|
||||
QT_TRANSLATE_NOOP("Menu", "Replace Next"),
|
||||
QT_TRANSLATE_NOOP("Status", "Replace next piece"),
|
||||
""
|
||||
},
|
||||
// LC_EDIT_REPLACE_ALL
|
||||
{
|
||||
QT_TRANSLATE_NOOP("Action", "Edit.ReplaceAll"),
|
||||
QT_TRANSLATE_NOOP("Menu", "Replace All"),
|
||||
QT_TRANSLATE_NOOP("Status", "Replace all pieces that match the search criteria"),
|
||||
""
|
||||
},
|
||||
// LC_EDIT_SELECT_ALL
|
||||
{
|
||||
QT_TRANSLATE_NOOP("Action", "Edit.SelectAll"),
|
||||
|
@ -255,13 +290,6 @@ lcCommand gCommands[LC_NUM_COMMANDS] =
|
|||
QT_TRANSLATE_NOOP("Status", "Select objects by name"),
|
||||
""
|
||||
},
|
||||
// LC_EDIT_SELECT_BY_COLOR
|
||||
{
|
||||
QT_TRANSLATE_NOOP("Action", "Edit.SelectByColor"),
|
||||
QT_TRANSLATE_NOOP("Menu", "Select by Col&or..."),
|
||||
QT_TRANSLATE_NOOP("Status", "Select pieces by color"),
|
||||
""
|
||||
},
|
||||
// LC_EDIT_SELECT_SINGLE
|
||||
{
|
||||
QT_TRANSLATE_NOOP("Action", "Edit.SelectSingle"),
|
||||
|
@ -290,18 +318,46 @@ lcCommand gCommands[LC_NUM_COMMANDS] =
|
|||
QT_TRANSLATE_NOOP("Status", "Select all pieces of the same type and color"),
|
||||
""
|
||||
},
|
||||
// LC_EDIT_TRANSFORM_RELATIVE
|
||||
{
|
||||
QT_TRANSLATE_NOOP("Action", "Edit.TransformRelative"),
|
||||
QT_TRANSLATE_NOOP("Menu", "Relative Transforms"),
|
||||
QT_TRANSLATE_NOOP("Status", "Move and rotate objects relative to the one that has focus"),
|
||||
// LC_EDIT_TRANSFORM_RELATIVE
|
||||
{
|
||||
QT_TRANSLATE_NOOP("Action", "Edit.TransformRelative"),
|
||||
QT_TRANSLATE_NOOP("Menu", "Relative Transforms"),
|
||||
QT_TRANSLATE_NOOP("Status", "Move and rotate objects relative to the one that has focus"),
|
||||
""
|
||||
},
|
||||
// LC_EDIT_TRANSFORM_ABSOLUTE
|
||||
{
|
||||
QT_TRANSLATE_NOOP("Action", "Edit.TransformAbsolute"),
|
||||
QT_TRANSLATE_NOOP("Menu", "Absolute Transforms"),
|
||||
QT_TRANSLATE_NOOP("Status", "Move and rotate objects in absolute coordinates"),
|
||||
""
|
||||
},
|
||||
// LC_EDIT_TRANSFORM_TOGGLE_RELATIVE
|
||||
{
|
||||
QT_TRANSLATE_NOOP("Action", "Edit.TransformToggleRelative"),
|
||||
QT_TRANSLATE_NOOP("Menu", "Toggle Relative Transforms"),
|
||||
QT_TRANSLATE_NOOP("Status", "Toggle moving and rotating objects relative to the one that has focus"),
|
||||
""
|
||||
},
|
||||
// LC_EDIT_TRANSFORM_LOCAL
|
||||
// LC_EDIT_TRANSFORM_SEPARATELY
|
||||
{
|
||||
QT_TRANSLATE_NOOP("Action", "Edit.TransformSeparately"),
|
||||
QT_TRANSLATE_NOOP("Menu", "Rotate Separately"),
|
||||
QT_TRANSLATE_NOOP("Status", "Rotate selected pieces separately"),
|
||||
""
|
||||
},
|
||||
// LC_EDIT_TRANSFORM_TOGETHER
|
||||
{
|
||||
QT_TRANSLATE_NOOP("Action", "Edit.TransformTogether"),
|
||||
QT_TRANSLATE_NOOP("Menu", "Rotate Together"),
|
||||
QT_TRANSLATE_NOOP("Status", "Rotate selected pieces together"),
|
||||
""
|
||||
},
|
||||
// LC_EDIT_TRANSFORM_TOGGLE_SEPARATE
|
||||
{
|
||||
QT_TRANSLATE_NOOP("Action", "Edit.TransformLocal"),
|
||||
QT_TRANSLATE_NOOP("Menu", "Local Transforms"),
|
||||
QT_TRANSLATE_NOOP("Status", "Rotate pieces around their individual pivot point"),
|
||||
QT_TRANSLATE_NOOP("Action", "Edit.TransformToggleSeparate"),
|
||||
QT_TRANSLATE_NOOP("Menu", "Toggle Separate Transforms"),
|
||||
QT_TRANSLATE_NOOP("Status", "Toggle rotating selected pieces separately"),
|
||||
""
|
||||
},
|
||||
// LC_EDIT_SNAP_MOVE_TOGGLE
|
||||
|
@ -1011,6 +1067,62 @@ lcCommand gCommands[LC_NUM_COMMANDS] =
|
|||
QT_TRANSLATE_NOOP("Status", "Reset all views"),
|
||||
""
|
||||
},
|
||||
// LC_VIEW_TOOLBAR_STANDARD
|
||||
{
|
||||
QT_TRANSLATE_NOOP("Action", "View.Toolbars.Standard"),
|
||||
QT_TRANSLATE_NOOP("Menu", "Standard"),
|
||||
QT_TRANSLATE_NOOP("Status", "Toggle the Standard Toolbar"),
|
||||
""
|
||||
},
|
||||
// LC_VIEW_TOOLBAR_TOOLS
|
||||
{
|
||||
QT_TRANSLATE_NOOP("Action", "View.Toolbars.Tools"),
|
||||
QT_TRANSLATE_NOOP("Menu", "Tools"),
|
||||
QT_TRANSLATE_NOOP("Status", "Toggle the Tools Toolbar"),
|
||||
""
|
||||
},
|
||||
// LC_VIEW_TOOLBAR_TIME
|
||||
{
|
||||
QT_TRANSLATE_NOOP("Action", "View.Toolbars.Time"),
|
||||
QT_TRANSLATE_NOOP("Menu", "Time"),
|
||||
QT_TRANSLATE_NOOP("Status", "Toggle the Time Toolbar"),
|
||||
""
|
||||
},
|
||||
// LC_VIEW_TOOLBAR_PARTS
|
||||
{
|
||||
QT_TRANSLATE_NOOP("Action", "View.Toolbars.Parts"),
|
||||
QT_TRANSLATE_NOOP("Menu", "Parts"),
|
||||
QT_TRANSLATE_NOOP("Status", "Toggle the Parts Toolbar"),
|
||||
""
|
||||
},
|
||||
// LC_VIEW_TOOLBAR_COLORS
|
||||
{
|
||||
QT_TRANSLATE_NOOP("Action", "View.Toolbars.Colors"),
|
||||
QT_TRANSLATE_NOOP("Menu", "Colors"),
|
||||
QT_TRANSLATE_NOOP("Status", "Toggle the Colors Toolbar"),
|
||||
""
|
||||
},
|
||||
// LC_VIEW_TOOLBAR_PROPERTIES
|
||||
{
|
||||
QT_TRANSLATE_NOOP("Action", "View.Toolbars.Properties"),
|
||||
QT_TRANSLATE_NOOP("Menu", "Properties"),
|
||||
QT_TRANSLATE_NOOP("Status", "Toggle the Properties Toolbar"),
|
||||
""
|
||||
},
|
||||
// LC_VIEW_TOOLBAR_TIMELINE
|
||||
{
|
||||
QT_TRANSLATE_NOOP("Action", "View.Toolbars.Timeline"),
|
||||
QT_TRANSLATE_NOOP("Menu", "Timeline"),
|
||||
QT_TRANSLATE_NOOP("Status", "Toggle the Timeline Toolbar"),
|
||||
""
|
||||
},
|
||||
// LC_VIEW_TOOLBAR_PREVIEW
|
||||
{
|
||||
QT_TRANSLATE_NOOP("Action", "View.Toolbars.Preview"),
|
||||
QT_TRANSLATE_NOOP("Menu", "Preview"),
|
||||
QT_TRANSLATE_NOOP("Status", "Toggle the Preview Toolbar"),
|
||||
""
|
||||
},
|
||||
// LC_VIEW_FULLSCREEN
|
||||
{
|
||||
QT_TRANSLATE_NOOP("Action", "View.FullScreen"),
|
||||
|
@ -1067,6 +1179,20 @@ lcCommand gCommands[LC_NUM_COMMANDS] =
|
|||
QT_TRANSLATE_NOOP("Status", "Toggle the view sphere"),
|
||||
""
|
||||
},
|
||||
// LC_VIEW_TOGGLE_AXIS_ICON
|
||||
{
|
||||
QT_TRANSLATE_NOOP("Action", "View.ToggleAxisIcon"),
|
||||
QT_TRANSLATE_NOOP("Menu", "Axis Icon"),
|
||||
QT_TRANSLATE_NOOP("Status", "Toggle axis icon"),
|
||||
""
|
||||
},
|
||||
// LC_VIEW_TOGGLE_GRID
|
||||
{
|
||||
QT_TRANSLATE_NOOP("Action", "View.ToggleGrid"),
|
||||
QT_TRANSLATE_NOOP("Menu", "Base Grid"),
|
||||
QT_TRANSLATE_NOOP("Status", "Toggle grid"),
|
||||
""
|
||||
},
|
||||
// LC_VIEW_FADE_PREVIOUS_STEPS
|
||||
{
|
||||
QT_TRANSLATE_NOOP("Action", "View.FadePreviousSteps"),
|
||||
|
@ -1095,6 +1221,13 @@ lcCommand gCommands[LC_NUM_COMMANDS] =
|
|||
QT_TRANSLATE_NOOP("Status", "Create a copy of the selected pieces"),
|
||||
"Ctrl+D"
|
||||
},
|
||||
// LC_PIECE_PAINT_SELECTED
|
||||
{
|
||||
QT_TRANSLATE_NOOP("Action", "Piece.PaintSelected"),
|
||||
QT_TRANSLATE_NOOP("Menu", "&Paint Selected"),
|
||||
QT_TRANSLATE_NOOP("Status", "Change the color of the selected pieces"),
|
||||
""
|
||||
},
|
||||
// LC_PIECE_RESET_PIVOT_POINT
|
||||
{
|
||||
QT_TRANSLATE_NOOP("Action", "Piece.ResetPivotPoint"),
|
||||
|
@ -1522,6 +1655,118 @@ lcCommand gCommands[LC_NUM_COMMANDS] =
|
|||
QT_TRANSLATE_NOOP("Status", "Switch to this submodel"),
|
||||
""
|
||||
},
|
||||
// LC_MODEL_25
|
||||
{
|
||||
QT_TRANSLATE_NOOP("Action", "Model.Model25"),
|
||||
QT_TRANSLATE_NOOP("Menu", "Model 25"),
|
||||
QT_TRANSLATE_NOOP("Status", "Switch to this submodel"),
|
||||
""
|
||||
},
|
||||
// LC_MODEL_26
|
||||
{
|
||||
QT_TRANSLATE_NOOP("Action", "Model.Model26"),
|
||||
QT_TRANSLATE_NOOP("Menu", "Model 26"),
|
||||
QT_TRANSLATE_NOOP("Status", "Switch to this submodel"),
|
||||
""
|
||||
},
|
||||
// LC_MODEL_27
|
||||
{
|
||||
QT_TRANSLATE_NOOP("Action", "Model.Model27"),
|
||||
QT_TRANSLATE_NOOP("Menu", "Model 27"),
|
||||
QT_TRANSLATE_NOOP("Status", "Switch to this submodel"),
|
||||
""
|
||||
},
|
||||
// LC_MODEL_28
|
||||
{
|
||||
QT_TRANSLATE_NOOP("Action", "Model.Model28"),
|
||||
QT_TRANSLATE_NOOP("Menu", "Model 28"),
|
||||
QT_TRANSLATE_NOOP("Status", "Switch to this submodel"),
|
||||
""
|
||||
},
|
||||
// LC_MODEL_29
|
||||
{
|
||||
QT_TRANSLATE_NOOP("Action", "Model.Model29"),
|
||||
QT_TRANSLATE_NOOP("Menu", "Model 29"),
|
||||
QT_TRANSLATE_NOOP("Status", "Switch to this submodel"),
|
||||
""
|
||||
},
|
||||
// LC_MODEL_30
|
||||
{
|
||||
QT_TRANSLATE_NOOP("Action", "Model.Model30"),
|
||||
QT_TRANSLATE_NOOP("Menu", "Model 30"),
|
||||
QT_TRANSLATE_NOOP("Status", "Switch to this submodel"),
|
||||
""
|
||||
},
|
||||
// LC_MODEL_31
|
||||
{
|
||||
QT_TRANSLATE_NOOP("Action", "Model.Model31"),
|
||||
QT_TRANSLATE_NOOP("Menu", "Model 31"),
|
||||
QT_TRANSLATE_NOOP("Status", "Switch to this submodel"),
|
||||
""
|
||||
},
|
||||
// LC_MODEL_32
|
||||
{
|
||||
QT_TRANSLATE_NOOP("Action", "Model.Model32"),
|
||||
QT_TRANSLATE_NOOP("Menu", "Model 32"),
|
||||
QT_TRANSLATE_NOOP("Status", "Switch to this submodel"),
|
||||
""
|
||||
},
|
||||
// LC_MODEL_33
|
||||
{
|
||||
QT_TRANSLATE_NOOP("Action", "Model.Model33"),
|
||||
QT_TRANSLATE_NOOP("Menu", "Model 33"),
|
||||
QT_TRANSLATE_NOOP("Status", "Switch to this submodel"),
|
||||
""
|
||||
},
|
||||
// LC_MODEL_34
|
||||
{
|
||||
QT_TRANSLATE_NOOP("Action", "Model.Model34"),
|
||||
QT_TRANSLATE_NOOP("Menu", "Model 34"),
|
||||
QT_TRANSLATE_NOOP("Status", "Switch to this submodel"),
|
||||
""
|
||||
},
|
||||
// LC_MODEL_35
|
||||
{
|
||||
QT_TRANSLATE_NOOP("Action", "Model.Model35"),
|
||||
QT_TRANSLATE_NOOP("Menu", "Model 35"),
|
||||
QT_TRANSLATE_NOOP("Status", "Switch to this submodel"),
|
||||
""
|
||||
},
|
||||
// LC_MODEL_36
|
||||
{
|
||||
QT_TRANSLATE_NOOP("Action", "Model.Model36"),
|
||||
QT_TRANSLATE_NOOP("Menu", "Model 36"),
|
||||
QT_TRANSLATE_NOOP("Status", "Switch to this submodel"),
|
||||
""
|
||||
},
|
||||
// LC_MODEL_37
|
||||
{
|
||||
QT_TRANSLATE_NOOP("Action", "Model.Model37"),
|
||||
QT_TRANSLATE_NOOP("Menu", "Model 37"),
|
||||
QT_TRANSLATE_NOOP("Status", "Switch to this submodel"),
|
||||
""
|
||||
},
|
||||
// LC_MODEL_38
|
||||
{
|
||||
QT_TRANSLATE_NOOP("Action", "Model.Model38"),
|
||||
QT_TRANSLATE_NOOP("Menu", "Model 38"),
|
||||
QT_TRANSLATE_NOOP("Status", "Switch to this submodel"),
|
||||
""
|
||||
},
|
||||
// LC_MODEL_39
|
||||
{
|
||||
QT_TRANSLATE_NOOP("Action", "Model.Model39"),
|
||||
QT_TRANSLATE_NOOP("Menu", "Model 39"),
|
||||
QT_TRANSLATE_NOOP("Status", "Switch to this submodel"),
|
||||
""
|
||||
},
|
||||
// LC_MODEL_40
|
||||
{
|
||||
QT_TRANSLATE_NOOP("Action", "Model.Model40"),
|
||||
QT_TRANSLATE_NOOP("Menu", "Model 40"),
|
||||
QT_TRANSLATE_NOOP("Status", "Switch to this submodel"),
|
||||
""
|
||||
},
|
||||
// LC_HELP_HOMEPAGE
|
||||
{
|
||||
QT_TRANSLATE_NOOP("Action", "Help.HomePage"),
|
||||
|
@ -1587,25 +1832,25 @@ lcCommand gCommands[LC_NUM_COMMANDS] =
|
|||
}
|
||||
};
|
||||
|
||||
static_assert(sizeof(gCommands)/sizeof(gCommands[0]) == LC_NUM_COMMANDS, "Array size mismatch.");
|
||||
LC_ARRAY_SIZE_CHECK(gCommands, LC_NUM_COMMANDS);
|
||||
|
||||
const char* gToolNames[LC_NUM_TOOLS] =
|
||||
const char* gToolNames[] =
|
||||
{
|
||||
QT_TRANSLATE_NOOP("Mouse", "NewPiece"), // LC_TOOL_INSERT
|
||||
QT_TRANSLATE_NOOP("Mouse", "NewPointLight"), // LC_TOOL_LIGHT
|
||||
QT_TRANSLATE_NOOP("Mouse", "NewSpotLight"), // LC_TOOL_SPOTLIGHT
|
||||
QT_TRANSLATE_NOOP("Mouse", "NewCamera"), // LC_TOOL_CAMERA
|
||||
QT_TRANSLATE_NOOP("Mouse", "Select"), // LC_TOOL_SELECT
|
||||
QT_TRANSLATE_NOOP("Mouse", "Move"), // LC_TOOL_MOVE
|
||||
QT_TRANSLATE_NOOP("Mouse", "Rotate"), // LC_TOOL_ROTATE
|
||||
QT_TRANSLATE_NOOP("Mouse", "Delete"), // LC_TOOL_ERASER
|
||||
QT_TRANSLATE_NOOP("Mouse", "Paint"), // LC_TOOL_PAINT
|
||||
QT_TRANSLATE_NOOP("Mouse", "ColorPicker"), // LC_TOOL_COLOR_PICKER
|
||||
QT_TRANSLATE_NOOP("Mouse", "Zoom"), // LC_TOOL_ZOOM
|
||||
QT_TRANSLATE_NOOP("Mouse", "Pan"), // LC_TOOL_PAN
|
||||
QT_TRANSLATE_NOOP("Mouse", "Orbit"), // LC_TOOL_ROTATE_VIEW
|
||||
QT_TRANSLATE_NOOP("Mouse", "Roll"), // LC_TOOL_ROLL
|
||||
QT_TRANSLATE_NOOP("Mouse", "ZoomRegion") // LC_TOOL_ZOOM_REGION
|
||||
QT_TRANSLATE_NOOP("Mouse", "NewPiece"), // lcTool::Insert
|
||||
QT_TRANSLATE_NOOP("Mouse", "NewPointLight"), // lcTool::Light
|
||||
QT_TRANSLATE_NOOP("Mouse", "NewSpotLight"), // lcTool::SpotLight
|
||||
QT_TRANSLATE_NOOP("Mouse", "NewCamera"), // lcTool::Camera
|
||||
QT_TRANSLATE_NOOP("Mouse", "Select"), // lcTool::Select
|
||||
QT_TRANSLATE_NOOP("Mouse", "Move"), // lcTool::Move
|
||||
QT_TRANSLATE_NOOP("Mouse", "Rotate"), // lcTool::Rotate
|
||||
QT_TRANSLATE_NOOP("Mouse", "Delete"), // lcTool::Eraser
|
||||
QT_TRANSLATE_NOOP("Mouse", "Paint"), // lcTool::Paint
|
||||
QT_TRANSLATE_NOOP("Mouse", "ColorPicker"), // lcTool::ColorPicker
|
||||
QT_TRANSLATE_NOOP("Mouse", "Zoom"), // lcTool::Zoom
|
||||
QT_TRANSLATE_NOOP("Mouse", "Pan"), // lcTool::Pan
|
||||
QT_TRANSLATE_NOOP("Mouse", "Orbit"), // lcTool::RotateView
|
||||
QT_TRANSLATE_NOOP("Mouse", "Roll"), // lcTool::Roll
|
||||
QT_TRANSLATE_NOOP("Mouse", "ZoomRegion") // lcTool::ZoomRegion
|
||||
};
|
||||
|
||||
static_assert(LC_ARRAY_COUNT(gToolNames) == LC_NUM_TOOLS, "Array size mismatch.");
|
||||
LC_ARRAY_SIZE_CHECK(gToolNames, lcTool::Count);
|
||||
|
|
|
@ -18,9 +18,9 @@ enum lcCommandId
|
|||
LC_FILE_EXPORT_POVRAY,
|
||||
LC_FILE_EXPORT_WAVEFRONT,
|
||||
LC_FILE_RENDER,
|
||||
LC_FILE_INSTRUCTIONS,
|
||||
LC_FILE_PRINT,
|
||||
LC_FILE_PRINT_PREVIEW,
|
||||
LC_FILE_PRINT_BOM,
|
||||
LC_FILE_RECENT_FIRST,
|
||||
LC_FILE_RECENT1 = LC_FILE_RECENT_FIRST,
|
||||
LC_FILE_RECENT2,
|
||||
|
@ -33,14 +33,18 @@ enum lcCommandId
|
|||
LC_EDIT_CUT,
|
||||
LC_EDIT_COPY,
|
||||
LC_EDIT_PASTE,
|
||||
LC_EDIT_PASTE_STEPS,
|
||||
LC_EDIT_FIND,
|
||||
LC_EDIT_FIND_NEXT,
|
||||
LC_EDIT_FIND_PREVIOUS,
|
||||
LC_EDIT_FIND_ALL,
|
||||
LC_EDIT_REPLACE,
|
||||
LC_EDIT_REPLACE_NEXT,
|
||||
LC_EDIT_REPLACE_ALL,
|
||||
LC_EDIT_SELECT_ALL,
|
||||
LC_EDIT_SELECT_NONE,
|
||||
LC_EDIT_SELECT_INVERT,
|
||||
LC_EDIT_SELECT_BY_NAME,
|
||||
LC_EDIT_SELECT_BY_COLOR,
|
||||
LC_EDIT_SELECTION_MODE_FIRST,
|
||||
LC_EDIT_SELECTION_SINGLE = LC_EDIT_SELECTION_MODE_FIRST,
|
||||
LC_EDIT_SELECTION_PIECE,
|
||||
|
@ -48,7 +52,11 @@ enum lcCommandId
|
|||
LC_EDIT_SELECTION_PIECE_COLOR,
|
||||
LC_EDIT_SELECTION_MODE_LAST = LC_EDIT_SELECTION_PIECE_COLOR,
|
||||
LC_EDIT_TRANSFORM_RELATIVE,
|
||||
LC_EDIT_TRANSFORM_LOCAL,
|
||||
LC_EDIT_TRANSFORM_ABSOLUTE,
|
||||
LC_EDIT_TRANSFORM_TOGGLE_RELATIVE,
|
||||
LC_EDIT_TRANSFORM_SEPARATELY,
|
||||
LC_EDIT_TRANSFORM_TOGETHER,
|
||||
LC_EDIT_TRANSFORM_TOGGLE_SEPARATE,
|
||||
LC_EDIT_SNAP_MOVE_TOGGLE,
|
||||
LC_EDIT_SNAP_MOVE_XY0,
|
||||
LC_EDIT_SNAP_MOVE_XY1,
|
||||
|
@ -154,6 +162,16 @@ enum lcCommandId
|
|||
LC_VIEW_SPLIT_VERTICAL,
|
||||
LC_VIEW_REMOVE_VIEW,
|
||||
LC_VIEW_RESET_VIEWS,
|
||||
LC_VIEW_TOOLBAR_STANDARD,
|
||||
LC_VIEW_TOOLBAR_FIRST = LC_VIEW_TOOLBAR_STANDARD,
|
||||
LC_VIEW_TOOLBAR_TOOLS,
|
||||
LC_VIEW_TOOLBAR_TIME,
|
||||
LC_VIEW_TOOLBAR_PARTS,
|
||||
LC_VIEW_TOOLBAR_COLORS,
|
||||
LC_VIEW_TOOLBAR_PROPERTIES,
|
||||
LC_VIEW_TOOLBAR_TIMELINE,
|
||||
LC_VIEW_TOOLBAR_PREVIEW,
|
||||
LC_VIEW_TOOLBAR_LAST = LC_VIEW_TOOLBAR_PREVIEW,
|
||||
LC_VIEW_FULLSCREEN,
|
||||
LC_VIEW_CLOSE_CURRENT_TAB,
|
||||
LC_VIEW_SHADING_FIRST,
|
||||
|
@ -166,10 +184,13 @@ enum lcCommandId
|
|||
LC_VIEW_PROJECTION_ORTHO,
|
||||
LC_VIEW_PROJECTION_LAST = LC_VIEW_PROJECTION_ORTHO,
|
||||
LC_VIEW_TOGGLE_VIEW_SPHERE,
|
||||
LC_VIEW_TOGGLE_AXIS_ICON,
|
||||
LC_VIEW_TOGGLE_GRID,
|
||||
LC_VIEW_FADE_PREVIOUS_STEPS,
|
||||
LC_PIECE_INSERT,
|
||||
LC_PIECE_DELETE,
|
||||
LC_PIECE_DUPLICATE,
|
||||
LC_PIECE_PAINT_SELECTED,
|
||||
LC_PIECE_RESET_PIVOT_POINT,
|
||||
LC_PIECE_REMOVE_KEY_FRAMES,
|
||||
LC_PIECE_CONTROL_POINT_INSERT,
|
||||
|
@ -232,7 +253,23 @@ enum lcCommandId
|
|||
LC_MODEL_22,
|
||||
LC_MODEL_23,
|
||||
LC_MODEL_24,
|
||||
LC_MODEL_LAST = LC_MODEL_24,
|
||||
LC_MODEL_25,
|
||||
LC_MODEL_26,
|
||||
LC_MODEL_27,
|
||||
LC_MODEL_28,
|
||||
LC_MODEL_29,
|
||||
LC_MODEL_30,
|
||||
LC_MODEL_31,
|
||||
LC_MODEL_32,
|
||||
LC_MODEL_33,
|
||||
LC_MODEL_34,
|
||||
LC_MODEL_35,
|
||||
LC_MODEL_36,
|
||||
LC_MODEL_37,
|
||||
LC_MODEL_38,
|
||||
LC_MODEL_39,
|
||||
LC_MODEL_40,
|
||||
LC_MODEL_LAST = LC_MODEL_40,
|
||||
LC_HELP_HOMEPAGE,
|
||||
LC_HELP_BUG_REPORT,
|
||||
LC_HELP_UPDATES,
|
||||
|
@ -253,27 +290,27 @@ struct lcCommand
|
|||
const char* DefaultShortcut;
|
||||
};
|
||||
|
||||
extern lcCommand gCommands[LC_NUM_COMMANDS];
|
||||
extern const lcCommand gCommands[];
|
||||
|
||||
enum lcTool
|
||||
enum class lcTool
|
||||
{
|
||||
LC_TOOL_INSERT,
|
||||
LC_TOOL_LIGHT,
|
||||
LC_TOOL_SPOTLIGHT,
|
||||
LC_TOOL_CAMERA,
|
||||
LC_TOOL_SELECT,
|
||||
LC_TOOL_MOVE,
|
||||
LC_TOOL_ROTATE,
|
||||
LC_TOOL_ERASER,
|
||||
LC_TOOL_PAINT,
|
||||
LC_TOOL_COLOR_PICKER,
|
||||
LC_TOOL_ZOOM,
|
||||
LC_TOOL_PAN,
|
||||
LC_TOOL_ROTATE_VIEW,
|
||||
LC_TOOL_ROLL,
|
||||
LC_TOOL_ZOOM_REGION,
|
||||
LC_NUM_TOOLS
|
||||
Insert,
|
||||
Light,
|
||||
SpotLight,
|
||||
Camera,
|
||||
Select,
|
||||
Move,
|
||||
Rotate,
|
||||
Eraser,
|
||||
Paint,
|
||||
ColorPicker,
|
||||
Zoom,
|
||||
Pan,
|
||||
RotateView,
|
||||
Roll,
|
||||
ZoomRegion,
|
||||
Count
|
||||
};
|
||||
|
||||
extern const char* gToolNames[LC_NUM_TOOLS];
|
||||
extern const char* gToolNames[];
|
||||
|
||||
|
|
|
@ -6,6 +6,12 @@
|
|||
#include "lc_colors.h"
|
||||
#include "lc_mainwindow.h"
|
||||
#include "lc_library.h"
|
||||
#include "texfont.h"
|
||||
#include "lc_view.h"
|
||||
#include "lc_viewsphere.h"
|
||||
#include "lc_stringcache.h"
|
||||
#include "lc_partselectionwidget.h"
|
||||
#include <QOpenGLFunctions_3_2_Core>
|
||||
|
||||
#ifdef LC_OPENGLES
|
||||
#define glEnableClientState(...)
|
||||
|
@ -18,7 +24,10 @@
|
|||
#define GL_STATIC_DRAW_ARB GL_STATIC_DRAW
|
||||
#endif
|
||||
|
||||
std::unique_ptr<QOpenGLContext> lcContext::mOffscreenContext;
|
||||
std::unique_ptr<QOffscreenSurface> lcContext::mOffscreenSurface;
|
||||
lcProgram lcContext::mPrograms[static_cast<int>(lcMaterialType::Count)];
|
||||
int lcContext::mValidContexts;
|
||||
|
||||
lcContext::lcContext()
|
||||
{
|
||||
|
@ -33,18 +42,17 @@ lcContext::lcContext()
|
|||
mColorEnabled = false;
|
||||
|
||||
mTexture2D = 0;
|
||||
mTexture2DMS = 0;
|
||||
mTextureCubeMap = 0;
|
||||
mPolygonOffset = lcPolygonOffset::None;
|
||||
mDepthWrite = true;
|
||||
mDepthFunction = lcDepthFunction::LessEqual;
|
||||
mCullFace = false;
|
||||
mLineWidth = 1.0f;
|
||||
#ifndef LC_OPENGLES
|
||||
mMatrixMode = GL_MODELVIEW;
|
||||
mTextureEnabled = false;
|
||||
#endif
|
||||
|
||||
mFramebufferObject = 0;
|
||||
|
||||
mColor = lcVector4(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
mWorldMatrix = lcMatrix44Identity();
|
||||
mViewMatrix = lcMatrix44Identity();
|
||||
|
@ -66,6 +74,58 @@ lcContext::lcContext()
|
|||
|
||||
lcContext::~lcContext()
|
||||
{
|
||||
if (mValid)
|
||||
{
|
||||
mValidContexts--;
|
||||
|
||||
if (!mValidContexts)
|
||||
{
|
||||
gStringCache.Reset();
|
||||
gTexFont.Reset();
|
||||
|
||||
lcGetPiecesLibrary()->ReleaseBuffers(this);
|
||||
lcView::DestroyResources(this);
|
||||
DestroyResources();
|
||||
lcViewSphere::DestroyResources(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool lcContext::CreateOffscreenContext()
|
||||
{
|
||||
std::unique_ptr<QOpenGLContext> OffscreenContext(new QOpenGLContext());
|
||||
|
||||
if (!OffscreenContext)
|
||||
return false;
|
||||
|
||||
OffscreenContext->setShareContext(QOpenGLContext::globalShareContext());
|
||||
|
||||
if (!OffscreenContext->create() || !OffscreenContext->isValid())
|
||||
return false;
|
||||
|
||||
std::unique_ptr<QOffscreenSurface> OffscreenSurface(new QOffscreenSurface());
|
||||
|
||||
if (!OffscreenSurface)
|
||||
return false;
|
||||
|
||||
OffscreenSurface->create();
|
||||
|
||||
if (!OffscreenSurface->isValid())
|
||||
return false;
|
||||
|
||||
if (!OffscreenContext->makeCurrent(OffscreenSurface.get()))
|
||||
return false;
|
||||
|
||||
mOffscreenContext = std::move(OffscreenContext);
|
||||
mOffscreenSurface = std::move(OffscreenSurface);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void lcContext::DestroyOffscreenContext()
|
||||
{
|
||||
mOffscreenSurface.reset();
|
||||
mOffscreenContext.reset();
|
||||
}
|
||||
|
||||
void lcContext::CreateShaderPrograms()
|
||||
|
@ -102,7 +162,7 @@ void lcContext::CreateShaderPrograms()
|
|||
" LC_SHADER_PRECISION float Diffuse = min(abs(dot(Normal, LightDirection)) * 0.6 + 0.65, 1.0);\n"
|
||||
};
|
||||
|
||||
const char* const VertexShaders[static_cast<int>(lcMaterialType::Count)] =
|
||||
const char* const VertexShaders[] =
|
||||
{
|
||||
":/resources/shaders/unlit_color_vs.glsl", // UnlitColor
|
||||
":/resources/shaders/unlit_texture_modulate_vs.glsl", // UnlitTextureModulate
|
||||
|
@ -113,7 +173,9 @@ void lcContext::CreateShaderPrograms()
|
|||
":/resources/shaders/fakelit_texture_decal_vs.glsl" // FakeLitTextureDecal
|
||||
};
|
||||
|
||||
const char* const FragmentShaders[static_cast<int>(lcMaterialType::Count)] =
|
||||
LC_ARRAY_SIZE_CHECK(VertexShaders, lcMaterialType::Count);
|
||||
|
||||
const char* const FragmentShaders[] =
|
||||
{
|
||||
":/resources/shaders/unlit_color_ps.glsl", // UnlitColor
|
||||
":/resources/shaders/unlit_texture_modulate_ps.glsl", // UnlitTextureModulate
|
||||
|
@ -124,21 +186,16 @@ void lcContext::CreateShaderPrograms()
|
|||
":/resources/shaders/fakelit_texture_decal_ps.glsl" // FakeLitTextureDecal
|
||||
};
|
||||
|
||||
const auto LoadShader = [ShaderPrefix](const char* FileName, GLuint ShaderType) -> GLuint
|
||||
{
|
||||
QResource Resource(FileName);
|
||||
LC_ARRAY_SIZE_CHECK(FragmentShaders, lcMaterialType::Count);
|
||||
|
||||
if (!Resource.isValid())
|
||||
const auto LoadShader = [this, ShaderPrefix](const char* FileName, GLuint ShaderType) -> GLuint
|
||||
{
|
||||
QFile ShaderFile(FileName);
|
||||
|
||||
if (!ShaderFile.open(QIODevice::ReadOnly))
|
||||
return 0;
|
||||
|
||||
QByteArray Data;
|
||||
|
||||
if (Resource.isCompressed())
|
||||
Data = qUncompress(Resource.data(), Resource.size());
|
||||
else
|
||||
Data = QByteArray::fromRawData((const char*)Resource.data(), Resource.size());
|
||||
|
||||
Data = ShaderPrefix + Data;
|
||||
QByteArray Data = ShaderPrefix + ShaderFile.readAll();
|
||||
const char* Source = Data.constData();
|
||||
|
||||
const GLuint Shader = glCreateShader(ShaderType);
|
||||
|
@ -233,10 +290,60 @@ void lcContext::DestroyResources()
|
|||
}
|
||||
}
|
||||
|
||||
void lcContext::MakeCurrent()
|
||||
{
|
||||
if (mWidget)
|
||||
mWidget->makeCurrent();
|
||||
else
|
||||
mOffscreenContext->makeCurrent(mOffscreenSurface.get());
|
||||
}
|
||||
|
||||
void lcContext::SetGLContext(QOpenGLContext* Context, QOpenGLWidget* Widget)
|
||||
{
|
||||
mContext = Context;
|
||||
mWidget = Widget;
|
||||
|
||||
MakeCurrent();
|
||||
initializeOpenGLFunctions();
|
||||
|
||||
if (!mValidContexts)
|
||||
{
|
||||
lcInitializeGLExtensions(Context);
|
||||
|
||||
// TODO: Find a better place for the grid texture and font
|
||||
gStringCache.Initialize(this);
|
||||
gTexFont.Initialize(this);
|
||||
|
||||
CreateResources();
|
||||
lcView::CreateResources(this);
|
||||
lcViewSphere::CreateResources(this);
|
||||
|
||||
if (!gSupportsShaderObjects && lcGetPreferences().mShadingMode == lcShadingMode::DefaultLights)
|
||||
lcGetPreferences().mShadingMode = lcShadingMode::Flat;
|
||||
|
||||
if (!gSupportsFramebufferObject)
|
||||
gMainWindow->GetPartSelectionWidget()->DisableIconMode();
|
||||
}
|
||||
|
||||
mValid = true;
|
||||
mValidContexts++;
|
||||
}
|
||||
|
||||
void lcContext::SetOffscreenContext()
|
||||
{
|
||||
SetGLContext(mOffscreenContext.get(), nullptr);
|
||||
}
|
||||
|
||||
void lcContext::SetDefaultState()
|
||||
{
|
||||
#ifndef LC_OPENGLES
|
||||
if (QSurfaceFormat::defaultFormat().samples() > 1)
|
||||
glEnable(GL_LINE_SMOOTH);
|
||||
#endif
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
mDepthFunction = lcDepthFunction::LessEqual;
|
||||
|
||||
if (gSupportsBlendFuncSeparate)
|
||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE_MINUS_DST_ALPHA, GL_ONE);
|
||||
|
@ -283,13 +390,6 @@ void lcContext::SetDefaultState()
|
|||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
mTexture2D = 0;
|
||||
#ifndef LC_OPENGLES
|
||||
if (gSupportsTexImage2DMultisample)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
|
||||
mTexture2DMS = 0;
|
||||
}
|
||||
#endif
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
|
||||
mTextureCubeMap = 0;
|
||||
|
||||
|
@ -299,6 +399,9 @@ void lcContext::SetDefaultState()
|
|||
mDepthWrite = true;
|
||||
glDepthMask(GL_TRUE);
|
||||
|
||||
glDisable(GL_CULL_FACE);
|
||||
mCullFace = false;
|
||||
|
||||
glLineWidth(1.0f);
|
||||
mLineWidth = 1.0f;
|
||||
|
||||
|
@ -320,12 +423,22 @@ void lcContext::SetDefaultState()
|
|||
}
|
||||
}
|
||||
|
||||
void lcContext::ClearColorAndDepth(const lcVector4& ClearColor)
|
||||
{
|
||||
glClearColor(ClearColor[0], ClearColor[1], ClearColor[2], ClearColor[3]);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
void lcContext::ClearDepth()
|
||||
{
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
void lcContext::ClearResources()
|
||||
{
|
||||
ClearVertexBuffer();
|
||||
ClearIndexBuffer();
|
||||
BindTexture2D(0);
|
||||
BindTexture2DMS(0);
|
||||
}
|
||||
|
||||
void lcContext::SetMaterial(lcMaterialType MaterialType)
|
||||
|
@ -426,6 +539,38 @@ void lcContext::SetDepthWrite(bool Enable)
|
|||
mDepthWrite = Enable;
|
||||
}
|
||||
|
||||
void lcContext::SetDepthFunction(lcDepthFunction DepthFunction)
|
||||
{
|
||||
if (DepthFunction == mDepthFunction)
|
||||
return;
|
||||
|
||||
switch (DepthFunction)
|
||||
{
|
||||
case lcDepthFunction::Always:
|
||||
glDepthFunc(GL_ALWAYS);
|
||||
break;
|
||||
|
||||
case lcDepthFunction::LessEqual:
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
break;
|
||||
}
|
||||
|
||||
mDepthFunction = DepthFunction;
|
||||
}
|
||||
|
||||
void lcContext::EnableCullFace(bool Enable)
|
||||
{
|
||||
if (Enable == mCullFace)
|
||||
return;
|
||||
|
||||
if (Enable)
|
||||
glEnable(GL_CULL_FACE);
|
||||
else
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
mCullFace = Enable;
|
||||
}
|
||||
|
||||
void lcContext::SetLineWidth(float LineWidth)
|
||||
{
|
||||
if (LineWidth == mLineWidth)
|
||||
|
@ -452,20 +597,6 @@ void lcContext::BindTexture2D(GLuint Texture)
|
|||
mTexture2D = Texture;
|
||||
}
|
||||
|
||||
void lcContext::BindTexture2DMS(GLuint Texture)
|
||||
{
|
||||
if (mTexture2DMS == Texture)
|
||||
return;
|
||||
|
||||
#ifndef LC_OPENGLES
|
||||
if (gSupportsTexImage2DMultisample)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, Texture);
|
||||
mTexture2DMS = Texture;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void lcContext::BindTextureCubeMap(GLuint Texture)
|
||||
{
|
||||
if (mTextureCubeMap == Texture)
|
||||
|
@ -529,210 +660,6 @@ void lcContext::SetInterfaceColor(lcInterfaceColor InterfaceColor)
|
|||
SetColor(gInterfaceColors[InterfaceColor]);
|
||||
}
|
||||
|
||||
void lcContext::ClearFramebuffer()
|
||||
{
|
||||
if (!mFramebufferObject)
|
||||
return;
|
||||
|
||||
if (gSupportsFramebufferObjectARB)
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
#ifndef LC_OPENGLES
|
||||
else if (gSupportsFramebufferObjectEXT)
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||
#endif
|
||||
|
||||
mFramebufferObject = 0;
|
||||
}
|
||||
|
||||
lcFramebuffer lcContext::CreateFramebuffer(int Width, int Height, bool Depth, bool Multisample)
|
||||
{
|
||||
lcFramebuffer Framebuffer(Width, Height);
|
||||
|
||||
if (gSupportsFramebufferObjectARB)
|
||||
{
|
||||
int Samples = (Multisample && gSupportsTexImage2DMultisample && QGLFormat::defaultFormat().sampleBuffers()) ? QGLFormat::defaultFormat().samples() : 1;
|
||||
|
||||
glGenFramebuffers(1, &Framebuffer.mObject);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, Framebuffer.mObject);
|
||||
|
||||
glGenTextures(1, &Framebuffer.mColorTexture);
|
||||
if (Depth)
|
||||
glGenRenderbuffers(1, &Framebuffer.mDepthRenderbuffer);
|
||||
|
||||
if (Samples == 1)
|
||||
{
|
||||
BindTexture2D(Framebuffer.mColorTexture);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Width, Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
||||
BindTexture2D(0);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, Framebuffer.mColorTexture, 0);
|
||||
|
||||
if (Depth)
|
||||
{
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, Framebuffer.mDepthRenderbuffer);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, Width, Height);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, Framebuffer.mDepthRenderbuffer);
|
||||
}
|
||||
}
|
||||
#ifndef LC_OPENGLES
|
||||
else
|
||||
{
|
||||
BindTexture2DMS(Framebuffer.mColorTexture);
|
||||
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, Samples, GL_RGBA, Width, Height, GL_TRUE);
|
||||
BindTexture2DMS(0);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, Framebuffer.mColorTexture, 0);
|
||||
|
||||
if (Depth)
|
||||
{
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, Framebuffer.mDepthRenderbuffer);
|
||||
glRenderbufferStorageMultisample(GL_RENDERBUFFER, Samples, GL_DEPTH_COMPONENT24, Width, Height);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, Framebuffer.mDepthRenderbuffer);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
||||
DestroyFramebuffer(Framebuffer);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mFramebufferObject);
|
||||
}
|
||||
#ifndef LC_OPENGLES
|
||||
else if (gSupportsFramebufferObjectEXT)
|
||||
{
|
||||
glGenFramebuffersEXT(1, &Framebuffer.mObject);
|
||||
glGenTextures(1, &Framebuffer.mColorTexture);
|
||||
|
||||
BindTexture2D(Framebuffer.mColorTexture);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, Width, Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
||||
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, Framebuffer.mObject);
|
||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, Framebuffer.mColorTexture, 0);
|
||||
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, Framebuffer.mObject);
|
||||
|
||||
glGenRenderbuffersEXT(1, &Framebuffer.mDepthRenderbuffer);
|
||||
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, Framebuffer.mDepthRenderbuffer);
|
||||
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, Width, Height);
|
||||
|
||||
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, Framebuffer.mDepthRenderbuffer);
|
||||
|
||||
BindTexture2D(0);
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, Framebuffer.mObject);
|
||||
|
||||
if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT)
|
||||
DestroyFramebuffer(Framebuffer);
|
||||
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFramebufferObject);
|
||||
}
|
||||
#endif
|
||||
|
||||
return Framebuffer;
|
||||
}
|
||||
|
||||
void lcContext::DestroyFramebuffer(lcFramebuffer& Framebuffer)
|
||||
{
|
||||
if (gSupportsFramebufferObjectARB)
|
||||
{
|
||||
glDeleteFramebuffers(1, &Framebuffer.mObject);
|
||||
glDeleteTextures(1, &Framebuffer.mColorTexture);
|
||||
glDeleteRenderbuffers(1, &Framebuffer.mDepthRenderbuffer);
|
||||
}
|
||||
#ifndef LC_OPENGLES
|
||||
else if (gSupportsFramebufferObjectEXT)
|
||||
{
|
||||
glDeleteFramebuffersEXT(1, &Framebuffer.mObject);
|
||||
glDeleteTextures(1, &Framebuffer.mColorTexture);
|
||||
glDeleteRenderbuffersEXT(1, &Framebuffer.mDepthRenderbuffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
Framebuffer.mObject = 0;
|
||||
Framebuffer.mColorTexture = 0;
|
||||
Framebuffer.mDepthRenderbuffer = 0;
|
||||
Framebuffer.mWidth = 0;
|
||||
Framebuffer.mHeight = 0;
|
||||
}
|
||||
|
||||
void lcContext::BindFramebuffer(GLuint FramebufferObject)
|
||||
{
|
||||
if (FramebufferObject == mFramebufferObject)
|
||||
return;
|
||||
|
||||
if (gSupportsFramebufferObjectARB)
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, FramebufferObject);
|
||||
#ifndef LC_OPENGLES
|
||||
else if (gSupportsFramebufferObjectEXT)
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FramebufferObject);
|
||||
#endif
|
||||
|
||||
mFramebufferObject = FramebufferObject;
|
||||
}
|
||||
|
||||
std::pair<lcFramebuffer, lcFramebuffer> lcContext::CreateRenderFramebuffer(int Width, int Height)
|
||||
{
|
||||
if (gSupportsFramebufferObjectARB && QGLFormat::defaultFormat().sampleBuffers() && QGLFormat::defaultFormat().samples() > 1)
|
||||
return std::make_pair(CreateFramebuffer(Width, Height, true, true), CreateFramebuffer(Width, Height, false, false));
|
||||
else
|
||||
return std::make_pair(CreateFramebuffer(Width, Height, true, false), lcFramebuffer());
|
||||
}
|
||||
|
||||
void lcContext::DestroyRenderFramebuffer(std::pair<lcFramebuffer, lcFramebuffer>& RenderFramebuffer)
|
||||
{
|
||||
DestroyFramebuffer(RenderFramebuffer.first);
|
||||
DestroyFramebuffer(RenderFramebuffer.second);
|
||||
}
|
||||
|
||||
QImage lcContext::GetRenderFramebufferImage(const std::pair<lcFramebuffer, lcFramebuffer>& RenderFramebuffer)
|
||||
{
|
||||
QImage Image(RenderFramebuffer.first.mWidth, RenderFramebuffer.first.mHeight, QImage::Format_ARGB32);
|
||||
|
||||
GetRenderFramebufferImage(RenderFramebuffer, Image.bits());
|
||||
|
||||
return Image;
|
||||
}
|
||||
|
||||
void lcContext::GetRenderFramebufferImage(const std::pair<lcFramebuffer, lcFramebuffer>& RenderFramebuffer, quint8* Buffer)
|
||||
{
|
||||
const int Width = RenderFramebuffer.first.mWidth;
|
||||
const int Height = RenderFramebuffer.first.mHeight;
|
||||
const GLuint SavedFramebuffer = mFramebufferObject;
|
||||
|
||||
if (RenderFramebuffer.second.IsValid())
|
||||
{
|
||||
#ifndef LC_OPENGLES
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, RenderFramebuffer.second.mObject);
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, RenderFramebuffer.first.mObject);
|
||||
glBlitFramebuffer(0, 0, Width, Height, 0, 0, Width, Height, GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
||||
BindFramebuffer(RenderFramebuffer.second);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
BindFramebuffer(RenderFramebuffer.first);
|
||||
|
||||
glFinish();
|
||||
glReadPixels(0, 0, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, Buffer);
|
||||
BindFramebuffer(SavedFramebuffer);
|
||||
|
||||
for (int y = 0; y < (Height + 1) / 2; y++)
|
||||
{
|
||||
quint8* Top = Buffer + ((Height - y - 1) * Width * 4);
|
||||
quint8* Bottom = Buffer + y * Width * 4;
|
||||
|
||||
for (int x = 0; x < Width; x++)
|
||||
{
|
||||
QRgb TopColor = qRgba(Top[0], Top[1], Top[2], Top[3]);
|
||||
QRgb BottomColor = qRgba(Bottom[0], Bottom[1], Bottom[2], Bottom[3]);
|
||||
|
||||
*(QRgb*)Top = BottomColor;
|
||||
*(QRgb*)Bottom = TopColor;
|
||||
|
||||
Top += 4;
|
||||
Bottom += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lcVertexBuffer lcContext::CreateVertexBuffer(int Size, const void* Data)
|
||||
{
|
||||
lcVertexBuffer VertexBuffer;
|
||||
|
@ -966,7 +893,7 @@ void lcContext::SetVertexFormatPosition(int PositionSize)
|
|||
|
||||
void lcContext::SetVertexFormat(int BufferOffset, int PositionSize, int NormalSize, int TexCoordSize, int ColorSize, bool EnableNormals)
|
||||
{
|
||||
const int VertexSize = (PositionSize + TexCoordSize + ColorSize) * sizeof(float) + NormalSize * sizeof(quint32);
|
||||
const int VertexSize = (PositionSize + TexCoordSize) * sizeof(float) + NormalSize * sizeof(quint32) + ColorSize;
|
||||
char* VertexBufferPointer = mVertexBufferPointer + BufferOffset;
|
||||
|
||||
if (gSupportsShaderObjects)
|
||||
|
@ -1017,7 +944,7 @@ void lcContext::SetVertexFormat(int BufferOffset, int PositionSize, int NormalSi
|
|||
|
||||
if (ColorSize)
|
||||
{
|
||||
glVertexAttribPointer(LC_ATTRIB_COLOR, ColorSize, GL_FLOAT, false, VertexSize, VertexBufferPointer + Offset);
|
||||
glVertexAttribPointer(LC_ATTRIB_COLOR, ColorSize, GL_UNSIGNED_BYTE, true, VertexSize, VertexBufferPointer + Offset);
|
||||
|
||||
if (!mColorEnabled)
|
||||
{
|
||||
|
@ -1229,10 +1156,7 @@ void lcContext::FlushState()
|
|||
|
||||
if (mHighlightParamsDirty && Program.HighlightParamsLocation != -1)
|
||||
{
|
||||
lcMatrix44 InverseViewMatrix = lcMatrix44AffineInverse(mViewMatrix);
|
||||
mHighlightParams[4] = InverseViewMatrix[2];
|
||||
|
||||
glUniform4fv(Program.HighlightParamsLocation, 5, mHighlightParams[0]);
|
||||
glUniform4fv(Program.HighlightParamsLocation, 4, mHighlightParams[0]);
|
||||
mHighlightParamsDirty = false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -76,30 +76,6 @@ struct lcProgram
|
|||
GLint HighlightParamsLocation;
|
||||
};
|
||||
|
||||
class lcFramebuffer
|
||||
{
|
||||
public:
|
||||
lcFramebuffer()
|
||||
{
|
||||
}
|
||||
|
||||
lcFramebuffer(int Width, int Height)
|
||||
: mWidth(Width), mHeight(Height)
|
||||
{
|
||||
}
|
||||
|
||||
bool IsValid() const
|
||||
{
|
||||
return mObject != 0;
|
||||
}
|
||||
|
||||
GLuint mObject = 0;
|
||||
GLuint mColorTexture = 0;
|
||||
GLuint mDepthRenderbuffer = 0;
|
||||
int mWidth = 0;
|
||||
int mHeight = 0;
|
||||
};
|
||||
|
||||
enum class lcPolygonOffset
|
||||
{
|
||||
None,
|
||||
|
@ -107,23 +83,38 @@ enum class lcPolygonOffset
|
|||
Translucent
|
||||
};
|
||||
|
||||
class lcContext
|
||||
enum class lcDepthFunction
|
||||
{
|
||||
LessEqual,
|
||||
Always
|
||||
};
|
||||
|
||||
class lcContext : protected QOpenGLFunctions
|
||||
{
|
||||
public:
|
||||
lcContext();
|
||||
~lcContext();
|
||||
|
||||
lcContext(const lcContext&) = delete;
|
||||
lcContext(lcContext&&) = delete;
|
||||
lcContext& operator=(const lcContext&) = delete;
|
||||
lcContext& operator=(lcContext&&) = delete;
|
||||
|
||||
static void CreateResources();
|
||||
static void DestroyResources();
|
||||
static bool CreateOffscreenContext();
|
||||
static void DestroyOffscreenContext();
|
||||
|
||||
void CreateResources();
|
||||
void DestroyResources();
|
||||
|
||||
void SetDefaultState();
|
||||
void ClearResources();
|
||||
|
||||
void MakeCurrent();
|
||||
|
||||
void SetGLContext(QOpenGLContext* GLContext, QOpenGLWidget* Widget);
|
||||
void SetOffscreenContext();
|
||||
|
||||
void ClearColorAndDepth(const lcVector4& ClearColor);
|
||||
void ClearDepth();
|
||||
|
||||
void SetWorldMatrix(const lcMatrix44& WorldMatrix)
|
||||
{
|
||||
mWorldMatrix = WorldMatrix;
|
||||
|
@ -153,10 +144,11 @@ public:
|
|||
void SetViewport(int x, int y, int Width, int Height);
|
||||
void SetPolygonOffset(lcPolygonOffset PolygonOffset);
|
||||
void SetDepthWrite(bool Enable);
|
||||
void SetDepthFunction(lcDepthFunction DepthFunction);
|
||||
void EnableCullFace(bool Enable);
|
||||
void SetLineWidth(float LineWidth);
|
||||
void SetSmoothShading(bool Smooth);
|
||||
void BindTexture2D(GLuint Texture);
|
||||
void BindTexture2DMS(GLuint Texture);
|
||||
void BindTextureCubeMap(GLuint Texture);
|
||||
void UnbindTexture2D(GLuint Texture);
|
||||
void UnbindTextureCubeMap(GLuint Texture);
|
||||
|
@ -184,20 +176,6 @@ public:
|
|||
void SetEdgeColorIndexTinted(int ColorIndex, const lcVector4& Tint);
|
||||
void SetInterfaceColor(lcInterfaceColor InterfaceColor);
|
||||
|
||||
void ClearFramebuffer();
|
||||
lcFramebuffer CreateFramebuffer(int Width, int Height, bool Depth, bool Multisample);
|
||||
void DestroyFramebuffer(lcFramebuffer& Framebuffer);
|
||||
void BindFramebuffer(GLuint FramebufferObject);
|
||||
void BindFramebuffer(const lcFramebuffer& Framebuffer)
|
||||
{
|
||||
BindFramebuffer(Framebuffer.mObject);
|
||||
}
|
||||
|
||||
std::pair<lcFramebuffer, lcFramebuffer> CreateRenderFramebuffer(int Width, int Height);
|
||||
void DestroyRenderFramebuffer(std::pair<lcFramebuffer, lcFramebuffer>& RenderFramebuffer);
|
||||
QImage GetRenderFramebufferImage(const std::pair<lcFramebuffer, lcFramebuffer>& RenderFramebuffer);
|
||||
void GetRenderFramebufferImage(const std::pair<lcFramebuffer, lcFramebuffer>& RenderFramebuffer, quint8* Buffer);
|
||||
|
||||
lcVertexBuffer CreateVertexBuffer(int Size, const void* Data);
|
||||
void DestroyVertexBuffer(lcVertexBuffer& VertexBuffer);
|
||||
lcIndexBuffer CreateIndexBuffer(int Size, const void* Data);
|
||||
|
@ -219,9 +197,13 @@ public:
|
|||
void BindMesh(const lcMesh* Mesh);
|
||||
|
||||
protected:
|
||||
static void CreateShaderPrograms();
|
||||
void CreateShaderPrograms();
|
||||
void FlushState();
|
||||
|
||||
QOpenGLWidget* mWidget = nullptr;
|
||||
QOpenGLContext* mContext = nullptr;
|
||||
bool mValid = false;
|
||||
|
||||
GLuint mVertexBufferObject;
|
||||
GLuint mIndexBufferObject;
|
||||
char* mVertexBufferPointer;
|
||||
|
@ -234,10 +216,11 @@ protected:
|
|||
bool mColorEnabled;
|
||||
|
||||
GLuint mTexture2D;
|
||||
GLuint mTexture2DMS;
|
||||
GLuint mTextureCubeMap;
|
||||
lcPolygonOffset mPolygonOffset;
|
||||
bool mDepthWrite;
|
||||
lcDepthFunction mDepthFunction;
|
||||
bool mCullFace;
|
||||
float mLineWidth;
|
||||
int mMatrixMode;
|
||||
bool mTextureEnabled;
|
||||
|
@ -247,7 +230,7 @@ protected:
|
|||
lcMatrix44 mViewMatrix;
|
||||
lcMatrix44 mProjectionMatrix;
|
||||
lcMatrix44 mViewProjectionMatrix;
|
||||
lcVector4 mHighlightParams[5];
|
||||
lcVector4 mHighlightParams[4];
|
||||
bool mColorDirty;
|
||||
bool mWorldMatrixDirty;
|
||||
bool mViewMatrixDirty;
|
||||
|
@ -255,9 +238,11 @@ protected:
|
|||
bool mViewProjectionMatrixDirty;
|
||||
bool mHighlightParamsDirty;
|
||||
|
||||
GLuint mFramebufferObject;
|
||||
static std::unique_ptr<QOpenGLContext> mOffscreenContext;
|
||||
static std::unique_ptr<QOffscreenSurface> mOffscreenSurface;
|
||||
|
||||
static lcProgram mPrograms[static_cast<int>(lcMaterialType::Count)];
|
||||
static int mValidContexts;
|
||||
|
||||
Q_DECLARE_TR_FUNCTIONS(lcContext);
|
||||
};
|
||||
|
|
270
common/lc_edgecolordialog.cpp
Normal file
270
common/lc_edgecolordialog.cpp
Normal file
|
@ -0,0 +1,270 @@
|
|||
#include "lc_edgecolordialog.h"
|
||||
#include "lc_application.h"
|
||||
|
||||
lcAutomateEdgeColorDialog::lcAutomateEdgeColorDialog(QWidget* Parent, bool ShowHighContrastDialog)
|
||||
:QDialog(Parent)
|
||||
{
|
||||
const lcPreferences& Preferences = lcGetPreferences();
|
||||
mStudCylinderColor = Preferences.mStudCylinderColor;
|
||||
mPartEdgeColor = Preferences.mPartEdgeColor;
|
||||
mBlackEdgeColor = Preferences.mBlackEdgeColor;
|
||||
mDarkEdgeColor = Preferences.mDarkEdgeColor;
|
||||
mPartEdgeContrast = Preferences.mPartEdgeContrast;
|
||||
mPartColorValueLDIndex = Preferences.mPartColorValueLDIndex;
|
||||
|
||||
setWindowTitle(tr("Color Preferences"));
|
||||
QVBoxLayout* MainLayout = new QVBoxLayout(this);
|
||||
|
||||
QGroupBox* EdgeSettingsBox = new QGroupBox(tr("Edge Colors"), this);
|
||||
MainLayout->addWidget(EdgeSettingsBox);
|
||||
QGridLayout* EdgeSettingsLayout = new QGridLayout(EdgeSettingsBox);
|
||||
EdgeSettingsBox->setLayout(EdgeSettingsLayout);
|
||||
|
||||
int LDIndexRow = 0;
|
||||
PartEdgeContrast = nullptr;
|
||||
PartEdgeContrastSlider = nullptr;
|
||||
if (!ShowHighContrastDialog)
|
||||
{
|
||||
LDIndexRow = 1;
|
||||
QLabel* PartEdgeContrastLabel = new QLabel(tr("Contrast:"), this);
|
||||
PartEdgeContrast = new QLabel(this);
|
||||
PartEdgeContrastSlider = new QSlider(Qt::Horizontal, this);
|
||||
PartEdgeContrastSlider->setRange(0, 100);
|
||||
PartEdgeContrastSlider->setValue(mPartEdgeContrast * 100);
|
||||
PartEdgeContrastSlider->setToolTip(tr("Set the amount of contrast - 0.50 is midway."));
|
||||
connect(PartEdgeContrastSlider, SIGNAL(valueChanged(int)), this, SLOT(SliderValueChanged(int)));
|
||||
emit PartEdgeContrastSlider->valueChanged(PartEdgeContrastSlider->value());
|
||||
|
||||
ResetPartEdgeContrastButton = new QToolButton(this);
|
||||
ResetPartEdgeContrastButton->setText(tr("Reset"));
|
||||
connect(ResetPartEdgeContrastButton, SIGNAL(clicked()), this, SLOT(ResetSliderButtonClicked()));
|
||||
|
||||
EdgeSettingsLayout->addWidget(PartEdgeContrastLabel,0,0);
|
||||
EdgeSettingsLayout->addWidget(PartEdgeContrastSlider,0,1);
|
||||
EdgeSettingsLayout->addWidget(PartEdgeContrast,0,2);
|
||||
EdgeSettingsLayout->addWidget(ResetPartEdgeContrastButton,0,3);
|
||||
}
|
||||
|
||||
QLabel* PartColorValueLDIndexLabel = new QLabel(tr(ShowHighContrastDialog ? "Light/Dark Value:" : "Saturation:"), this);
|
||||
PartColorValueLDIndex = new QLabel(this);
|
||||
PartColorValueLDIndexSlider = new QSlider(Qt::Horizontal, this);
|
||||
PartColorValueLDIndexSlider->setRange(0, 100);
|
||||
PartColorValueLDIndexSlider->setValue(mPartColorValueLDIndex * 100);
|
||||
PartColorValueLDIndexSlider->setToolTip(tr(ShowHighContrastDialog ?
|
||||
"Set to classify where color values are light or dark - e.g. Dark Bluish Gray (72) is light at 0.39." :
|
||||
"Set to specify amount of edge color tint or shade from the saturation adjusted part color"));
|
||||
connect(PartColorValueLDIndexSlider, SIGNAL(valueChanged(int)), this, SLOT(SliderValueChanged(int)));
|
||||
emit PartColorValueLDIndexSlider->valueChanged(PartColorValueLDIndexSlider->value());
|
||||
|
||||
ResetPartColorValueLDIndexButton = new QToolButton(this);
|
||||
ResetPartColorValueLDIndexButton->setText(tr("Reset"));
|
||||
connect(ResetPartColorValueLDIndexButton, SIGNAL(clicked()), this, SLOT(ResetSliderButtonClicked()));
|
||||
|
||||
EdgeSettingsLayout->addWidget(PartColorValueLDIndexLabel,LDIndexRow,0);
|
||||
EdgeSettingsLayout->addWidget(PartColorValueLDIndexSlider,LDIndexRow,1);
|
||||
EdgeSettingsLayout->addWidget(PartColorValueLDIndex,LDIndexRow,2);
|
||||
EdgeSettingsLayout->addWidget(ResetPartColorValueLDIndexButton,LDIndexRow,3);
|
||||
|
||||
QGroupBox* HighContrastColorBox = new QGroupBox(tr("High Contrast"), this);
|
||||
HighContrastColorBox->setVisible(ShowHighContrastDialog);
|
||||
MainLayout->addWidget(HighContrastColorBox);
|
||||
QGridLayout* HighContrastColorLayout = new QGridLayout(HighContrastColorBox);
|
||||
HighContrastColorBox->setLayout(HighContrastColorLayout);
|
||||
|
||||
auto SetButtonPixmap = [](quint32 Color, QToolButton* Button)
|
||||
{
|
||||
QPixmap Pixmap(12, 12);
|
||||
QColor ButtonColor(QColor(LC_RGBA_RED(Color), LC_RGBA_GREEN(Color), LC_RGBA_BLUE(Color)));
|
||||
Pixmap.fill(ButtonColor);
|
||||
Button->setIcon(Pixmap);
|
||||
Button->setToolTip(ButtonColor.name().toUpper());
|
||||
};
|
||||
|
||||
QLabel* StudCylinderColorLabel = new QLabel(tr("Stud Cylinder Color:"), this);
|
||||
StudCylinderColorButton = new QToolButton(this);
|
||||
SetButtonPixmap(mStudCylinderColor, StudCylinderColorButton);
|
||||
connect(StudCylinderColorButton, SIGNAL(clicked()), this, SLOT(ColorButtonClicked()));
|
||||
|
||||
ResetStudCylinderColorButton = new QToolButton(this);
|
||||
ResetStudCylinderColorButton->setText(tr("Reset"));;
|
||||
connect(ResetStudCylinderColorButton, SIGNAL(clicked()), this, SLOT(ResetColorButtonClicked()));
|
||||
|
||||
HighContrastColorLayout->addWidget(StudCylinderColorLabel,0,0);
|
||||
HighContrastColorLayout->addWidget(StudCylinderColorButton,0,1);
|
||||
HighContrastColorLayout->addWidget(ResetStudCylinderColorButton,0,2);
|
||||
|
||||
QLabel* PartEdgeColorLabel = new QLabel(tr("Parts Edge Color:"), this);
|
||||
PartEdgeColorButton = new QToolButton(this);
|
||||
SetButtonPixmap(mPartEdgeColor, PartEdgeColorButton);
|
||||
connect(PartEdgeColorButton, SIGNAL(clicked()), this, SLOT(ColorButtonClicked()));
|
||||
|
||||
ResetPartEdgeColorButton = new QToolButton(this);
|
||||
ResetPartEdgeColorButton->setText(tr("Reset"));
|
||||
connect(ResetPartEdgeColorButton, SIGNAL(clicked()), this, SLOT(ResetColorButtonClicked()));
|
||||
|
||||
HighContrastColorLayout->addWidget(PartEdgeColorLabel,1,0);
|
||||
HighContrastColorLayout->addWidget(PartEdgeColorButton,1,1);
|
||||
HighContrastColorLayout->addWidget(ResetPartEdgeColorButton,1,2);
|
||||
|
||||
QLabel* BlackEdgeColorLabel = new QLabel(tr("Black Parts Edge Color:"), this);
|
||||
BlackEdgeColorButton = new QToolButton(this);
|
||||
SetButtonPixmap(mBlackEdgeColor, BlackEdgeColorButton);
|
||||
connect(BlackEdgeColorButton, SIGNAL(clicked()), this, SLOT(ColorButtonClicked()));
|
||||
|
||||
ResetBlackEdgeColorButton = new QToolButton(this);
|
||||
ResetBlackEdgeColorButton->setText(tr("Reset"));
|
||||
connect(ResetBlackEdgeColorButton, SIGNAL(clicked()), this, SLOT(ResetColorButtonClicked()));
|
||||
|
||||
HighContrastColorLayout->addWidget(BlackEdgeColorLabel,2,0);
|
||||
HighContrastColorLayout->addWidget(BlackEdgeColorButton,2,1);
|
||||
HighContrastColorLayout->addWidget(ResetBlackEdgeColorButton,2,2);
|
||||
|
||||
QLabel* DarkEdgeColorLabel = new QLabel(tr("Dark Parts Edge Color:"), this);
|
||||
DarkEdgeColorButton = new QToolButton(this);
|
||||
SetButtonPixmap(mDarkEdgeColor, DarkEdgeColorButton);
|
||||
connect(DarkEdgeColorButton, SIGNAL(clicked()), this, SLOT(ColorButtonClicked()));
|
||||
|
||||
ResetDarkEdgeColorButton = new QToolButton(this);
|
||||
ResetDarkEdgeColorButton->setText(tr("Reset"));
|
||||
connect(ResetDarkEdgeColorButton, SIGNAL(clicked()), this, SLOT(ResetColorButtonClicked()));
|
||||
|
||||
HighContrastColorLayout->addWidget(DarkEdgeColorLabel,3,0);
|
||||
HighContrastColorLayout->addWidget(DarkEdgeColorButton,3,1);
|
||||
HighContrastColorLayout->addWidget(ResetDarkEdgeColorButton,3,2);
|
||||
|
||||
QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, this);
|
||||
MainLayout->addWidget(buttonBox);
|
||||
QObject::connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
|
||||
QObject::connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
|
||||
|
||||
setMinimumSize(220,100);
|
||||
}
|
||||
|
||||
void lcAutomateEdgeColorDialog::SliderValueChanged(int Value)
|
||||
{
|
||||
if (sender() == PartEdgeContrastSlider)
|
||||
{
|
||||
mPartEdgeContrast = Value * 0.01f;
|
||||
PartEdgeContrast->setText(QString::number(mPartEdgeContrast, 'f', 2));
|
||||
}
|
||||
else if (sender() == PartColorValueLDIndexSlider)
|
||||
{
|
||||
mPartColorValueLDIndex = Value * 0.01f;
|
||||
PartColorValueLDIndex->setText(QString::number(mPartColorValueLDIndex, 'f', 2));
|
||||
}
|
||||
}
|
||||
|
||||
void lcAutomateEdgeColorDialog::ColorButtonClicked()
|
||||
{
|
||||
QObject* Button = sender();
|
||||
QString Title;
|
||||
quint32* Color = nullptr;
|
||||
QColorDialog::ColorDialogOptions DialogOptions;
|
||||
|
||||
if (Button == StudCylinderColorButton)
|
||||
{
|
||||
Title = tr("Select Stud Cylinder Color");
|
||||
Color = &mStudCylinderColor;
|
||||
}
|
||||
else if (Button == PartEdgeColorButton)
|
||||
{
|
||||
Title = tr("Select Part Edge Color");
|
||||
Color = &mPartEdgeColor;
|
||||
}
|
||||
else if (Button == BlackEdgeColorButton)
|
||||
{
|
||||
if (lcGetPreferences().mAutomateEdgeColor)
|
||||
{
|
||||
QMessageBox msgBox;
|
||||
msgBox.setText("Automate edge color appears to be enabled.<br>Black parts edge color will not be accessible.<br>Do you want to continue ?");
|
||||
if (msgBox.exec() != QMessageBox::Accepted)
|
||||
return;
|
||||
}
|
||||
Title = tr("Select Black Edge Color");
|
||||
Color = &mBlackEdgeColor;
|
||||
}
|
||||
else if (Button == DarkEdgeColorButton)
|
||||
{
|
||||
if (lcGetPreferences().mAutomateEdgeColor)
|
||||
{
|
||||
QMessageBox msgBox;
|
||||
msgBox.setText("Automate edge color appears to be enabled.<br>Dark parts edge color will not be accessible.<br>Do you want to continue ?");
|
||||
if (msgBox.exec() != QMessageBox::Accepted)
|
||||
return;
|
||||
}
|
||||
Title = tr("Select Dark Edge Color");
|
||||
Color = &mDarkEdgeColor;
|
||||
}
|
||||
else
|
||||
return;
|
||||
|
||||
QColor OldColor = QColor(LC_RGBA_RED(*Color), LC_RGBA_GREEN(*Color), LC_RGBA_BLUE(*Color), LC_RGBA_ALPHA(*Color));
|
||||
QColor NewColor = QColorDialog::getColor(OldColor, this, Title, DialogOptions);
|
||||
|
||||
if (NewColor == OldColor || !NewColor.isValid())
|
||||
return;
|
||||
|
||||
*Color = LC_RGBA(NewColor.red(), NewColor.green(), NewColor.blue(), NewColor.alpha());
|
||||
|
||||
QPixmap Pix(12, 12);
|
||||
NewColor.setAlpha(255);
|
||||
Pix.fill(NewColor);
|
||||
((QToolButton*)Button)->setIcon(Pix);
|
||||
((QToolButton*)Button)->setToolTip(NewColor.name().toUpper());
|
||||
}
|
||||
|
||||
void lcAutomateEdgeColorDialog::ResetSliderButtonClicked()
|
||||
{
|
||||
if (sender() == ResetPartEdgeContrastButton)
|
||||
{
|
||||
PartEdgeContrastSlider->setValue(0.5f * 100);
|
||||
}
|
||||
else if (sender() == ResetPartColorValueLDIndexButton)
|
||||
{
|
||||
PartColorValueLDIndexSlider->setValue(0.5f * 100);
|
||||
}
|
||||
}
|
||||
|
||||
void lcAutomateEdgeColorDialog::ResetColorButtonClicked()
|
||||
{
|
||||
quint32* Color = nullptr;
|
||||
QPixmap Pix(12, 12);
|
||||
QColor ResetColor;
|
||||
|
||||
if (sender() == ResetStudCylinderColorButton)
|
||||
{
|
||||
Color = &mStudCylinderColor;
|
||||
*Color = LC_RGBA(27, 42, 52, 255);
|
||||
ResetColor = QColor(LC_RGBA_RED(*Color), LC_RGBA_GREEN(*Color), LC_RGBA_BLUE(*Color), LC_RGBA_ALPHA(*Color));
|
||||
Pix.fill(ResetColor);
|
||||
StudCylinderColorButton->setIcon(Pix);
|
||||
StudCylinderColorButton->setToolTip(ResetColor.name().toUpper());
|
||||
}
|
||||
else if (sender() == ResetPartEdgeColorButton)
|
||||
{
|
||||
Color = &mPartEdgeColor;
|
||||
*Color = LC_RGBA(0, 0, 0, 255);
|
||||
ResetColor = QColor(LC_RGBA_RED(*Color), LC_RGBA_GREEN(*Color), LC_RGBA_BLUE(*Color), LC_RGBA_ALPHA(*Color));
|
||||
Pix.fill(ResetColor);
|
||||
PartEdgeColorButton->setIcon(Pix);
|
||||
PartEdgeColorButton->setToolTip(ResetColor.name().toUpper());
|
||||
}
|
||||
else if (sender() == ResetBlackEdgeColorButton)
|
||||
{
|
||||
Color = &mBlackEdgeColor;
|
||||
*Color = LC_RGBA(255, 255, 255, 255);
|
||||
ResetColor = QColor(LC_RGBA_RED(*Color), LC_RGBA_GREEN(*Color), LC_RGBA_BLUE(*Color), LC_RGBA_ALPHA(*Color));
|
||||
Pix.fill(ResetColor);
|
||||
BlackEdgeColorButton->setIcon(Pix);
|
||||
BlackEdgeColorButton->setToolTip(ResetColor.name().toUpper());
|
||||
}
|
||||
else if (sender() == ResetDarkEdgeColorButton)
|
||||
{
|
||||
Color = &mDarkEdgeColor;
|
||||
*Color = LC_RGBA(27, 42, 52, 255);
|
||||
ResetColor = QColor(LC_RGBA_RED(*Color), LC_RGBA_GREEN(*Color), LC_RGBA_BLUE(*Color), LC_RGBA_ALPHA(*Color));
|
||||
Pix.fill(ResetColor);
|
||||
DarkEdgeColorButton->setIcon(Pix);
|
||||
DarkEdgeColorButton->setToolTip(ResetColor.name().toUpper());
|
||||
}
|
||||
}
|
43
common/lc_edgecolordialog.h
Normal file
43
common/lc_edgecolordialog.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
#pragma once
|
||||
|
||||
#include <QtWidgets>
|
||||
|
||||
class lcAutomateEdgeColorDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
lcAutomateEdgeColorDialog(QWidget *Parent, bool ShowHighContrastDialog);
|
||||
quint32 mStudCylinderColor;
|
||||
quint32 mPartEdgeColor;
|
||||
quint32 mDarkEdgeColor;
|
||||
quint32 mBlackEdgeColor;
|
||||
float mPartEdgeContrast;
|
||||
float mPartColorValueLDIndex;
|
||||
|
||||
protected slots:
|
||||
void SliderValueChanged(int);
|
||||
void ResetSliderButtonClicked();
|
||||
void ColorButtonClicked();
|
||||
void ResetColorButtonClicked();
|
||||
|
||||
protected:
|
||||
QSlider* PartColorValueLDIndexSlider;
|
||||
QSlider* PartEdgeContrastSlider;
|
||||
|
||||
QLabel* PartEdgeContrast;
|
||||
QLabel* PartColorValueLDIndex;
|
||||
|
||||
QToolButton* ResetPartEdgeContrastButton;
|
||||
QToolButton* ResetPartColorValueLDIndexButton;
|
||||
|
||||
QToolButton* StudCylinderColorButton;
|
||||
QToolButton* PartEdgeColorButton;
|
||||
QToolButton* BlackEdgeColorButton;
|
||||
QToolButton* DarkEdgeColorButton;
|
||||
|
||||
QToolButton* ResetStudCylinderColorButton;
|
||||
QToolButton* ResetPartEdgeColorButton;
|
||||
QToolButton* ResetBlackEdgeColorButton;
|
||||
QToolButton* ResetDarkEdgeColorButton;
|
||||
};
|
||||
|
164
common/lc_findreplacewidget.cpp
Normal file
164
common/lc_findreplacewidget.cpp
Normal file
|
@ -0,0 +1,164 @@
|
|||
#include "lc_global.h"
|
||||
#include "lc_findreplacewidget.h"
|
||||
#include "lc_qcolorpicker.h"
|
||||
#include "lc_library.h"
|
||||
#include "lc_mainwindow.h"
|
||||
#include "pieceinf.h"
|
||||
#include "piece.h"
|
||||
#include "lc_model.h"
|
||||
#include "lc_view.h"
|
||||
|
||||
lcFindReplaceWidget::lcFindReplaceWidget(QWidget* Parent, lcModel* Model, bool Replace)
|
||||
: QWidget(Parent)
|
||||
{
|
||||
setAutoFillBackground(true);
|
||||
QPalette Palette = palette();
|
||||
Palette.setColor(QPalette::Window, QApplication::palette().color(QPalette::Button));
|
||||
setPalette(Palette);
|
||||
|
||||
QGridLayout* Layout = new QGridLayout(this);
|
||||
Layout->setContentsMargins(5, 5, 5, 5);
|
||||
|
||||
Layout->addWidget(new QLabel(tr("Find:")), 0, 0);
|
||||
|
||||
lcQColorPicker* FindColorPicker = new lcQColorPicker(this, true);
|
||||
Layout->addWidget(FindColorPicker, 0, 1);
|
||||
|
||||
mFindPartComboBox = new QComboBox(this);
|
||||
mFindPartComboBox->setEditable(true);
|
||||
mFindPartComboBox->setInsertPolicy(QComboBox::NoInsert);
|
||||
Layout->addWidget(mFindPartComboBox, 0, 2);
|
||||
|
||||
QToolButton* FindNextButton = new QToolButton(this);
|
||||
FindNextButton->setAutoRaise(true);
|
||||
FindNextButton->setDefaultAction(gMainWindow->mActions[LC_EDIT_FIND_NEXT]);
|
||||
Layout->addWidget(FindNextButton, 0, 3);
|
||||
|
||||
QToolButton* FindAllButton = new QToolButton(this);
|
||||
FindAllButton ->setAutoRaise(true);
|
||||
FindAllButton ->setDefaultAction(gMainWindow->mActions[LC_EDIT_FIND_ALL]);
|
||||
Layout->addWidget(FindAllButton, 0, 4);
|
||||
|
||||
connect(FindColorPicker, &lcQColorPicker::colorChanged, this, &lcFindReplaceWidget::FindColorIndexChanged);
|
||||
connect(mFindPartComboBox->lineEdit(), &QLineEdit::returnPressed, gMainWindow->mActions[LC_EDIT_FIND_NEXT], &QAction::trigger);
|
||||
connect(mFindPartComboBox->lineEdit(), &QLineEdit::textEdited, this, &lcFindReplaceWidget::FindTextEdited);
|
||||
connect(mFindPartComboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), this, &lcFindReplaceWidget::FindActivated);
|
||||
|
||||
lcQColorPicker* ReplaceColorPicker = nullptr;
|
||||
|
||||
if (Replace)
|
||||
{
|
||||
Layout->addWidget(new QLabel(tr("Replace:")), 1, 0);
|
||||
|
||||
ReplaceColorPicker = new lcQColorPicker(this, true);
|
||||
Layout->addWidget(ReplaceColorPicker, 1, 1);
|
||||
|
||||
mReplacePartComboBox = new QComboBox(this);
|
||||
Layout->addWidget(mReplacePartComboBox, 1, 2);
|
||||
|
||||
QToolButton* ReplaceNextButton = new QToolButton(this);
|
||||
ReplaceNextButton->setAutoRaise(true);
|
||||
ReplaceNextButton->setDefaultAction(gMainWindow->mActions[LC_EDIT_REPLACE_NEXT]);
|
||||
Layout->addWidget(ReplaceNextButton, 1, 3);
|
||||
|
||||
QToolButton* ReplaceAllButton = new QToolButton(this);
|
||||
ReplaceAllButton->setAutoRaise(true);
|
||||
ReplaceAllButton->setDefaultAction(gMainWindow->mActions[LC_EDIT_REPLACE_ALL]);
|
||||
Layout->addWidget(ReplaceAllButton, 1, 4);
|
||||
|
||||
connect(ReplaceColorPicker, &lcQColorPicker::colorChanged, this, &lcFindReplaceWidget::ReplaceColorIndexChanged);
|
||||
connect(mReplacePartComboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), this, &lcFindReplaceWidget::ReplaceActivated);
|
||||
|
||||
mReplacePartComboBox->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon);
|
||||
mReplacePartComboBox->setMinimumContentsLength(1);
|
||||
|
||||
lcPiecesLibrary* Library = lcGetPiecesLibrary();
|
||||
std::vector<PieceInfo*> SortedPieces;
|
||||
SortedPieces.reserve(Library->mPieces.size());
|
||||
|
||||
for (const auto& PartIt : Library->mPieces)
|
||||
SortedPieces.push_back(PartIt.second);
|
||||
|
||||
auto PieceCompare = [](PieceInfo* Info1, PieceInfo* Info2)
|
||||
{
|
||||
return strcmp(Info1->m_strDescription, Info2->m_strDescription) < 0;
|
||||
};
|
||||
|
||||
std::sort(SortedPieces.begin(), SortedPieces.end(), PieceCompare);
|
||||
|
||||
mReplacePartComboBox->addItem(QString(), QVariant::fromValue((void*)nullptr));
|
||||
for (PieceInfo* Info : SortedPieces)
|
||||
mReplacePartComboBox->addItem(QString::fromLatin1(Info->m_strDescription), QVariant::fromValue((void*)Info));
|
||||
|
||||
ReplaceColorPicker->setCurrentColor(lcGetColorIndex(LC_COLOR_NOCOLOR));
|
||||
mReplacePartComboBox->setCurrentIndex(0);
|
||||
}
|
||||
|
||||
lcPartsList PartsList;
|
||||
Model->GetPartsList(gDefaultColor, false, true, PartsList);
|
||||
|
||||
for (const auto& PartIt : PartsList)
|
||||
mFindPartComboBox->addItem(QString::fromLatin1(PartIt.first->m_strDescription), QVariant::fromValue((void*)PartIt.first));
|
||||
mFindPartComboBox->model()->sort(0);
|
||||
|
||||
lcPiece* Focus = dynamic_cast<lcPiece*>(Model->GetFocusObject());
|
||||
|
||||
if (Focus)
|
||||
{
|
||||
lcFindReplaceParams& Params = lcView::GetFindReplaceParams();
|
||||
|
||||
Params.FindInfo = Focus->mPieceInfo;
|
||||
Params.FindColorIndex = Focus->GetColorIndex();
|
||||
|
||||
FindColorPicker->setCurrentColor(Params.FindColorIndex);
|
||||
mFindPartComboBox->setCurrentIndex(mFindPartComboBox->findData(QVariant::fromValue((void*)Params.FindInfo)));
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
FindColorPicker->setCurrentColor(lcGetColorIndex(LC_COLOR_NOCOLOR));
|
||||
mFindPartComboBox->setEditText(QString());
|
||||
}
|
||||
|
||||
mFindPartComboBox->setFocus();
|
||||
adjustSize();
|
||||
move(1, 1);
|
||||
show();
|
||||
}
|
||||
|
||||
void lcFindReplaceWidget::FindColorIndexChanged(int ColorIndex)
|
||||
{
|
||||
lcFindReplaceParams& Params = lcView::GetFindReplaceParams();
|
||||
|
||||
Params.FindColorIndex = ColorIndex;
|
||||
}
|
||||
|
||||
void lcFindReplaceWidget::FindTextEdited(const QString& Text)
|
||||
{
|
||||
lcFindReplaceParams& Params = lcView::GetFindReplaceParams();
|
||||
|
||||
Params.FindString = Text;
|
||||
Params.FindInfo = nullptr;
|
||||
}
|
||||
|
||||
void lcFindReplaceWidget::FindActivated(int Index)
|
||||
{
|
||||
lcFindReplaceParams& Params = lcView::GetFindReplaceParams();
|
||||
|
||||
Params.FindString.clear();
|
||||
Params.FindInfo = (PieceInfo*)mFindPartComboBox->itemData(Index).value<void*>();
|
||||
}
|
||||
|
||||
void lcFindReplaceWidget::ReplaceColorIndexChanged(int ColorIndex)
|
||||
{
|
||||
lcFindReplaceParams& Params = lcView::GetFindReplaceParams();
|
||||
|
||||
Params.ReplaceColorIndex = ColorIndex;
|
||||
}
|
||||
|
||||
void lcFindReplaceWidget::ReplaceActivated(int Index)
|
||||
{
|
||||
lcFindReplaceParams& Params = lcView::GetFindReplaceParams();
|
||||
|
||||
Params.ReplacePieceInfo = (PieceInfo*)mReplacePartComboBox->itemData(Index).value<void*>();
|
||||
}
|
20
common/lc_findreplacewidget.h
Normal file
20
common/lc_findreplacewidget.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
#pragma once
|
||||
|
||||
class lcFindReplaceWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
lcFindReplaceWidget(QWidget* Parent, lcModel* Model, bool Replace);
|
||||
|
||||
protected slots:
|
||||
void FindColorIndexChanged(int ColorIndex);
|
||||
void FindTextEdited(const QString& Text);
|
||||
void FindActivated(int Index);
|
||||
void ReplaceColorIndexChanged(int ColorIndex);
|
||||
void ReplaceActivated(int Index);
|
||||
|
||||
protected:
|
||||
QComboBox* mFindPartComboBox = nullptr;
|
||||
QComboBox* mReplacePartComboBox = nullptr;
|
||||
};
|
11847
common/lc_glext.h
11847
common/lc_glext.h
File diff suppressed because it is too large
Load diff
|
@ -1,157 +1,14 @@
|
|||
#include "lc_global.h"
|
||||
#include "lc_glextensions.h"
|
||||
#include <QOpenGLFunctions_3_2_Core>
|
||||
|
||||
bool gSupportsShaderObjects;
|
||||
bool gSupportsVertexBufferObject;
|
||||
bool gSupportsFramebufferObjectARB;
|
||||
bool gSupportsFramebufferObjectEXT;
|
||||
bool gSupportsTexImage2DMultisample;
|
||||
bool gSupportsFramebufferObject;
|
||||
bool gSupportsBlendFuncSeparate;
|
||||
bool gSupportsAnisotropic;
|
||||
GLfloat gMaxAnisotropy;
|
||||
|
||||
#ifdef LC_LOAD_GLEXTENSIONS
|
||||
|
||||
PFNGLBINDBUFFERARBPROC lcBindBufferARB;
|
||||
PFNGLDELETEBUFFERSARBPROC lcDeleteBuffersARB;
|
||||
PFNGLGENBUFFERSARBPROC lcGenBuffersARB;
|
||||
PFNGLISBUFFERARBPROC lcIsBufferARB;
|
||||
PFNGLBUFFERDATAARBPROC lcBufferDataARB;
|
||||
PFNGLBUFFERSUBDATAARBPROC lcBufferSubDataARB;
|
||||
PFNGLGETBUFFERSUBDATAARBPROC lcGetBufferSubDataARB;
|
||||
PFNGLMAPBUFFERARBPROC lcMapBufferARB;
|
||||
PFNGLUNMAPBUFFERARBPROC lcUnmapBufferARB;
|
||||
PFNGLGETBUFFERPARAMETERIVARBPROC lcGetBufferParameterivARB;
|
||||
PFNGLGETBUFFERPOINTERVARBPROC lcGetBufferPointervARB;
|
||||
|
||||
PFNGLISRENDERBUFFERPROC lcIsRenderbuffer;
|
||||
PFNGLBINDRENDERBUFFERPROC lcBindRenderbuffer;
|
||||
PFNGLDELETERENDERBUFFERSPROC lcDeleteRenderbuffers;
|
||||
PFNGLGENRENDERBUFFERSPROC lcGenRenderbuffers;
|
||||
PFNGLRENDERBUFFERSTORAGEPROC lcRenderbufferStorage;
|
||||
PFNGLGETRENDERBUFFERPARAMETERIVPROC lcGetRenderbufferParameteriv;
|
||||
PFNGLISFRAMEBUFFERPROC lcIsFramebuffer;
|
||||
PFNGLBINDFRAMEBUFFERPROC lcBindFramebuffer;
|
||||
PFNGLDELETEFRAMEBUFFERSPROC lcDeleteFramebuffers;
|
||||
PFNGLGENFRAMEBUFFERSPROC lcGenFramebuffers;
|
||||
PFNGLCHECKFRAMEBUFFERSTATUSPROC lcCheckFramebufferStatus;
|
||||
PFNGLFRAMEBUFFERTEXTURE1DPROC lcFramebufferTexture1D;
|
||||
PFNGLFRAMEBUFFERTEXTURE2DPROC lcFramebufferTexture2D;
|
||||
PFNGLFRAMEBUFFERTEXTURE3DPROC lcFramebufferTexture3D;
|
||||
PFNGLFRAMEBUFFERRENDERBUFFERPROC lcFramebufferRenderbuffer;
|
||||
PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC lcGetFramebufferAttachmentParameteriv;
|
||||
PFNGLGENERATEMIPMAPPROC lcGenerateMipmap;
|
||||
PFNGLBLITFRAMEBUFFERPROC lcBlitFramebuffer;
|
||||
PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC lcRenderbufferStorageMultisample;
|
||||
PFNGLFRAMEBUFFERTEXTURELAYERPROC lcFramebufferTextureLayer;
|
||||
|
||||
PFNGLISRENDERBUFFEREXTPROC lcIsRenderbufferEXT;
|
||||
PFNGLBINDRENDERBUFFEREXTPROC lcBindRenderbufferEXT;
|
||||
PFNGLDELETERENDERBUFFERSEXTPROC lcDeleteRenderbuffersEXT;
|
||||
PFNGLGENRENDERBUFFERSEXTPROC lcGenRenderbuffersEXT;
|
||||
PFNGLRENDERBUFFERSTORAGEEXTPROC lcRenderbufferStorageEXT;
|
||||
PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC lcGetRenderbufferParameterivEXT;
|
||||
PFNGLISFRAMEBUFFEREXTPROC lcIsFramebufferEXT;
|
||||
PFNGLBINDFRAMEBUFFEREXTPROC lcBindFramebufferEXT;
|
||||
PFNGLDELETEFRAMEBUFFERSEXTPROC lcDeleteFramebuffersEXT;
|
||||
PFNGLGENFRAMEBUFFERSEXTPROC lcGenFramebuffersEXT;
|
||||
PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC lcCheckFramebufferStatusEXT;
|
||||
PFNGLFRAMEBUFFERTEXTURE1DEXTPROC lcFramebufferTexture1DEXT;
|
||||
PFNGLFRAMEBUFFERTEXTURE2DEXTPROC lcFramebufferTexture2DEXT;
|
||||
PFNGLFRAMEBUFFERTEXTURE3DEXTPROC lcFramebufferTexture3DEXT;
|
||||
PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC lcFramebufferRenderbufferEXT;
|
||||
PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC lcGetFramebufferAttachmentParameterivEXT;
|
||||
PFNGLGENERATEMIPMAPEXTPROC lcGenerateMipmapEXT;
|
||||
|
||||
PFNGLATTACHSHADERPROC lcAttachShader;
|
||||
PFNGLBINDATTRIBLOCATIONPROC lcBindAttribLocation;
|
||||
PFNGLCOMPILESHADERPROC lcCompileShader;
|
||||
PFNGLCREATEPROGRAMPROC lcCreateProgram;
|
||||
PFNGLCREATESHADERPROC lcCreateShader;
|
||||
PFNGLDELETEPROGRAMPROC lcDeleteProgram;
|
||||
PFNGLDELETESHADERPROC lcDeleteShader;
|
||||
PFNGLDETACHSHADERPROC lcDetachShader;
|
||||
PFNGLDISABLEVERTEXATTRIBARRAYPROC lcDisableVertexAttribArray;
|
||||
PFNGLENABLEVERTEXATTRIBARRAYPROC lcEnableVertexAttribArray;
|
||||
PFNGLGETACTIVEATTRIBPROC lcGetActiveAttrib;
|
||||
PFNGLGETACTIVEUNIFORMPROC lcGetActiveUniform;
|
||||
PFNGLGETATTACHEDSHADERSPROC lcGetAttachedShaders;
|
||||
PFNGLGETATTRIBLOCATIONPROC lcGetAttribLocation;
|
||||
PFNGLGETPROGRAMIVPROC lcGetProgramiv;
|
||||
PFNGLGETPROGRAMINFOLOGPROC lcGetProgramInfoLog;
|
||||
PFNGLGETSHADERIVPROC lcGetShaderiv;
|
||||
PFNGLGETSHADERINFOLOGPROC lcGetShaderInfoLog;
|
||||
PFNGLGETSHADERSOURCEPROC lcGetShaderSource;
|
||||
PFNGLGETUNIFORMLOCATIONPROC lcGetUniformLocation;
|
||||
PFNGLGETUNIFORMFVPROC lcGetUniformfv;
|
||||
PFNGLGETUNIFORMIVPROC lcGetUniformiv;
|
||||
PFNGLGETVERTEXATTRIBDVPROC lcGetVertexAttribdv;
|
||||
PFNGLGETVERTEXATTRIBFVPROC lcGetVertexAttribfv;
|
||||
PFNGLGETVERTEXATTRIBIVPROC lcGetVertexAttribiv;
|
||||
PFNGLGETVERTEXATTRIBPOINTERVPROC lcGetVertexAttribPointerv;
|
||||
PFNGLISPROGRAMPROC lcIsProgram;
|
||||
PFNGLISSHADERPROC lcIsShader;
|
||||
PFNGLLINKPROGRAMPROC lcLinkProgram;
|
||||
PFNGLSHADERSOURCEPROC lcShaderSource;
|
||||
PFNGLUSEPROGRAMPROC lcUseProgram;
|
||||
PFNGLUNIFORM1FPROC lcUniform1f;
|
||||
PFNGLUNIFORM2FPROC lcUniform2f;
|
||||
PFNGLUNIFORM3FPROC lcUniform3f;
|
||||
PFNGLUNIFORM4FPROC lcUniform4f;
|
||||
PFNGLUNIFORM1IPROC lcUniform1i;
|
||||
PFNGLUNIFORM2IPROC lcUniform2i;
|
||||
PFNGLUNIFORM3IPROC lcUniform3i;
|
||||
PFNGLUNIFORM4IPROC lcUniform4i;
|
||||
PFNGLUNIFORM1FVPROC lcUniform1fv;
|
||||
PFNGLUNIFORM2FVPROC lcUniform2fv;
|
||||
PFNGLUNIFORM3FVPROC lcUniform3fv;
|
||||
PFNGLUNIFORM4FVPROC lcUniform4fv;
|
||||
PFNGLUNIFORM1IVPROC lcUniform1iv;
|
||||
PFNGLUNIFORM2IVPROC lcUniform2iv;
|
||||
PFNGLUNIFORM3IVPROC lcUniform3iv;
|
||||
PFNGLUNIFORM4IVPROC lcUniform4iv;
|
||||
PFNGLUNIFORMMATRIX2FVPROC lcUniformMatrix2fv;
|
||||
PFNGLUNIFORMMATRIX3FVPROC lcUniformMatrix3fv;
|
||||
PFNGLUNIFORMMATRIX4FVPROC lcUniformMatrix4fv;
|
||||
PFNGLVALIDATEPROGRAMPROC lcValidateProgram;
|
||||
PFNGLVERTEXATTRIBPOINTERPROC lcVertexAttribPointer;
|
||||
|
||||
PFNGLTEXIMAGE2DMULTISAMPLEPROC lcTexImage2DMultisample;
|
||||
|
||||
PFNGLBLENDFUNCSEPARATEPROC lcBlendFuncSeparate;
|
||||
|
||||
#endif
|
||||
|
||||
static bool lcIsGLExtensionSupported(const GLubyte* Extensions, const char* Name)
|
||||
{
|
||||
const GLubyte* Start;
|
||||
GLubyte* Where;
|
||||
GLubyte* Terminator;
|
||||
|
||||
Where = (GLubyte*)strchr(Name, ' ');
|
||||
if (Where || *Name == '\0')
|
||||
return false;
|
||||
|
||||
if (!Extensions)
|
||||
return false;
|
||||
|
||||
for (Start = Extensions; ;)
|
||||
{
|
||||
Where = (GLubyte*)strstr((const char*)Start, Name);
|
||||
if (!Where)
|
||||
break;
|
||||
|
||||
Terminator = Where + strlen(Name);
|
||||
if (Where == Start || *(Where - 1) == ' ')
|
||||
if (*Terminator == ' ' || *Terminator == '\0')
|
||||
return true;
|
||||
|
||||
Start = Terminator;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#if !defined(QT_NO_DEBUG) && defined(GL_ARB_debug_output)
|
||||
|
||||
static void APIENTRY lcGLDebugCallback(GLenum Source, GLenum Type, GLuint Id, GLenum Severity, GLsizei Length, const GLchar* Message, GLvoid* UserParam)
|
||||
|
@ -168,17 +25,12 @@ static void APIENTRY lcGLDebugCallback(GLenum Source, GLenum Type, GLuint Id, GL
|
|||
|
||||
#endif
|
||||
|
||||
void lcInitializeGLExtensions(const QGLContext* Context)
|
||||
void lcInitializeGLExtensions(const QOpenGLContext* Context)
|
||||
{
|
||||
const GLubyte* Extensions = glGetString(GL_EXTENSIONS);
|
||||
const GLubyte* Version = glGetString(GL_VERSION);
|
||||
int VersionMajor = 0, VersionMinor = 0;
|
||||
|
||||
if (Version)
|
||||
sscanf((const char*)Version, "%d.%d", &VersionMajor, &VersionMinor);
|
||||
const QOpenGLFunctions* Functions = Context->functions();
|
||||
|
||||
#if !defined(QT_NO_DEBUG) && defined(GL_ARB_debug_output)
|
||||
if (lcIsGLExtensionSupported(Extensions, "GL_KHR_debug"))
|
||||
if (Context->hasExtension("GL_KHR_debug"))
|
||||
{
|
||||
PFNGLDEBUGMESSAGECALLBACKARBPROC DebugMessageCallback = (PFNGLDEBUGMESSAGECALLBACKARBPROC)Context->getProcAddress("glDebugMessageCallback");
|
||||
|
||||
|
@ -186,7 +38,7 @@ void lcInitializeGLExtensions(const QGLContext* Context)
|
|||
#define GL_DEBUG_OUTPUT 0x92E0
|
||||
#endif
|
||||
|
||||
if (DebugMessageCallback)
|
||||
if (DebugMessageCallback)
|
||||
{
|
||||
DebugMessageCallback((GLDEBUGPROCARB)&lcGLDebugCallback, nullptr);
|
||||
glEnable(GL_DEBUG_OUTPUT);
|
||||
|
@ -195,181 +47,15 @@ void lcInitializeGLExtensions(const QGLContext* Context)
|
|||
}
|
||||
#endif
|
||||
|
||||
if (lcIsGLExtensionSupported(Extensions, "GL_EXT_texture_filter_anisotropic"))
|
||||
if (Context->hasExtension("GL_EXT_texture_filter_anisotropic"))
|
||||
{
|
||||
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gMaxAnisotropy);
|
||||
|
||||
gSupportsAnisotropic = true;
|
||||
}
|
||||
|
||||
// todo: check gl version and use core functions instead
|
||||
if (lcIsGLExtensionSupported(Extensions, "GL_ARB_vertex_buffer_object"))
|
||||
{
|
||||
#ifdef LC_LOAD_GLEXTENSIONS
|
||||
lcBindBufferARB = (PFNGLBINDBUFFERARBPROC)Context->getProcAddress("glBindBufferARB");
|
||||
lcDeleteBuffersARB = (PFNGLDELETEBUFFERSARBPROC)Context->getProcAddress("glDeleteBuffersARB");
|
||||
lcGenBuffersARB = (PFNGLGENBUFFERSARBPROC)Context->getProcAddress("glGenBuffersARB");
|
||||
lcIsBufferARB = (PFNGLISBUFFERARBPROC)Context->getProcAddress("glIsBufferARB");
|
||||
lcBufferDataARB = (PFNGLBUFFERDATAARBPROC)Context->getProcAddress("glBufferDataARB");
|
||||
lcBufferSubDataARB = (PFNGLBUFFERSUBDATAARBPROC)Context->getProcAddress("glBufferSubDataARB");
|
||||
lcGetBufferSubDataARB = (PFNGLGETBUFFERSUBDATAARBPROC)Context->getProcAddress("glGetBufferSubDataARB");
|
||||
lcMapBufferARB = (PFNGLMAPBUFFERARBPROC)Context->getProcAddress("glMapBufferARB");
|
||||
lcUnmapBufferARB = (PFNGLUNMAPBUFFERARBPROC)Context->getProcAddress("glUnmapBufferARB");
|
||||
lcGetBufferParameterivARB = (PFNGLGETBUFFERPARAMETERIVARBPROC)Context->getProcAddress("glGetBufferParameterivARB");
|
||||
lcGetBufferPointervARB = (PFNGLGETBUFFERPOINTERVARBPROC)Context->getProcAddress("glGetBufferPointervARB");
|
||||
#endif
|
||||
gSupportsVertexBufferObject = true;
|
||||
}
|
||||
|
||||
// todo: check gl version
|
||||
if (lcIsGLExtensionSupported(Extensions, "GL_ARB_framebuffer_object"))
|
||||
{
|
||||
#ifdef LC_LOAD_GLEXTENSIONS
|
||||
lcIsRenderbuffer = (PFNGLISRENDERBUFFERPROC)Context->getProcAddress("glIsRenderbuffer");
|
||||
lcBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC)Context->getProcAddress("glBindRenderbuffer");
|
||||
lcDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC)Context->getProcAddress("glDeleteRenderbuffers");
|
||||
lcGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC)Context->getProcAddress("glGenRenderbuffers");
|
||||
lcRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC)Context->getProcAddress("glRenderbufferStorage");
|
||||
lcGetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVPROC)Context->getProcAddress("glGetRenderbufferParameteriv");
|
||||
lcIsFramebuffer = (PFNGLISFRAMEBUFFERPROC)Context->getProcAddress("glIsFramebuffer");
|
||||
lcBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC)Context->getProcAddress("glBindFramebuffer");
|
||||
lcDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC)Context->getProcAddress("glDeleteFramebuffers");
|
||||
lcGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC)Context->getProcAddress("glGenFramebuffers");
|
||||
lcCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC)Context->getProcAddress("glCheckFramebufferStatus");
|
||||
lcFramebufferTexture1D = (PFNGLFRAMEBUFFERTEXTURE1DPROC)Context->getProcAddress("glFramebufferTexture1D");
|
||||
lcFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC)Context->getProcAddress("glFramebufferTexture2D");
|
||||
lcFramebufferTexture3D = (PFNGLFRAMEBUFFERTEXTURE3DPROC)Context->getProcAddress("glFramebufferTexture3D");
|
||||
lcFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC)Context->getProcAddress("glFramebufferRenderbuffer");
|
||||
lcGetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC)Context->getProcAddress("glGetFramebufferAttachmentParameteriv");
|
||||
lcGenerateMipmap = (PFNGLGENERATEMIPMAPPROC)Context->getProcAddress("glGenerateMipmap");
|
||||
lcBlitFramebuffer = (PFNGLBLITFRAMEBUFFERPROC)Context->getProcAddress("glBlitFramebuffer");
|
||||
lcRenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC)Context->getProcAddress("glRenderbufferStorageMultisample");
|
||||
lcFramebufferTextureLayer = (PFNGLFRAMEBUFFERTEXTURELAYERARBPROC)Context->getProcAddress("glFramebufferTextureLayer");
|
||||
#endif
|
||||
gSupportsFramebufferObjectARB = true;
|
||||
}
|
||||
|
||||
if (lcIsGLExtensionSupported(Extensions, "GL_EXT_framebuffer_object"))
|
||||
{
|
||||
#ifdef LC_LOAD_GLEXTENSIONS
|
||||
lcIsRenderbufferEXT = (PFNGLISRENDERBUFFEREXTPROC)Context->getProcAddress("glIsRenderbufferEXT");
|
||||
lcBindRenderbufferEXT = (PFNGLBINDRENDERBUFFEREXTPROC)Context->getProcAddress("glBindRenderbufferEXT");
|
||||
lcDeleteRenderbuffersEXT = (PFNGLDELETERENDERBUFFERSEXTPROC)Context->getProcAddress("glDeleteRenderbuffersEXT");
|
||||
lcGenRenderbuffersEXT = (PFNGLGENRENDERBUFFERSEXTPROC)Context->getProcAddress("glGenRenderbuffersEXT");
|
||||
lcRenderbufferStorageEXT = (PFNGLRENDERBUFFERSTORAGEEXTPROC)Context->getProcAddress("glRenderbufferStorageEXT");
|
||||
lcGetRenderbufferParameterivEXT = (PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC)Context->getProcAddress("glGetRenderbufferParameterivEXT");
|
||||
lcIsFramebufferEXT = (PFNGLISFRAMEBUFFEREXTPROC)Context->getProcAddress("glIsFramebufferEXT");
|
||||
lcBindFramebufferEXT = (PFNGLBINDFRAMEBUFFEREXTPROC)Context->getProcAddress("glBindFramebufferEXT");
|
||||
lcDeleteFramebuffersEXT = (PFNGLDELETEFRAMEBUFFERSEXTPROC)Context->getProcAddress("glDeleteFramebuffersEXT");
|
||||
lcGenFramebuffersEXT = (PFNGLGENFRAMEBUFFERSEXTPROC)Context->getProcAddress("glGenFramebuffersEXT");
|
||||
lcCheckFramebufferStatusEXT = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)Context->getProcAddress("glCheckFramebufferStatusEXT");
|
||||
lcFramebufferTexture1DEXT = (PFNGLFRAMEBUFFERTEXTURE1DEXTPROC)Context->getProcAddress("glFramebufferTexture1DEXT");
|
||||
lcFramebufferTexture2DEXT = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)Context->getProcAddress("glFramebufferTexture2DEXT");
|
||||
lcFramebufferTexture3DEXT = (PFNGLFRAMEBUFFERTEXTURE3DEXTPROC)Context->getProcAddress("glFramebufferTexture3DEXT");
|
||||
lcFramebufferRenderbufferEXT = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)Context->getProcAddress("glFramebufferRenderbufferEXT");
|
||||
lcGetFramebufferAttachmentParameterivEXT = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC)Context->getProcAddress("glGetFramebufferAttachmentParameterivEXT");
|
||||
lcGenerateMipmapEXT = (PFNGLGENERATEMIPMAPEXTPROC)Context->getProcAddress("glGenerateMipmapEXT");
|
||||
#endif
|
||||
gSupportsFramebufferObjectEXT = true;
|
||||
}
|
||||
|
||||
if (lcIsGLExtensionSupported(Extensions, "GL_EXT_blend_func_separate"))
|
||||
{
|
||||
#ifdef LC_LOAD_GLEXTENSIONS
|
||||
lcBlendFuncSeparate = (PFNGLBLENDFUNCSEPARATEPROC)Context->getProcAddress("glBlendFuncSeparateEXT");
|
||||
#endif
|
||||
|
||||
gSupportsBlendFuncSeparate = true;
|
||||
}
|
||||
|
||||
const GLubyte* GLSLVersion = glGetString(GL_SHADING_LANGUAGE_VERSION);
|
||||
int GLSLMajor = 0, GLSLMinor = 0;
|
||||
|
||||
if (GLSLVersion)
|
||||
sscanf((const char*)GLSLVersion, "%d.%d", &GLSLMajor, &GLSLMinor);
|
||||
|
||||
if (VersionMajor >= 2 && (GLSLMajor > 1 || (GLSLMajor == 1 && GLSLMinor >= 10)))
|
||||
{
|
||||
#ifdef LC_LOAD_GLEXTENSIONS
|
||||
lcAttachShader = (PFNGLATTACHSHADERPROC)Context->getProcAddress("glAttachShader");
|
||||
lcBindAttribLocation = (PFNGLBINDATTRIBLOCATIONPROC)Context->getProcAddress("glBindAttribLocation");
|
||||
lcCompileShader = (PFNGLCOMPILESHADERPROC)Context->getProcAddress("glCompileShader");
|
||||
lcCreateProgram = (PFNGLCREATEPROGRAMPROC)Context->getProcAddress("glCreateProgram");
|
||||
lcCreateShader = (PFNGLCREATESHADERPROC)Context->getProcAddress("glCreateShader");
|
||||
lcDeleteProgram = (PFNGLDELETEPROGRAMPROC)Context->getProcAddress("glDeleteProgram");
|
||||
lcDeleteShader = (PFNGLDELETESHADERPROC)Context->getProcAddress("glDeleteShader");
|
||||
lcDetachShader = (PFNGLDETACHSHADERPROC)Context->getProcAddress("glDetachShader");
|
||||
lcDisableVertexAttribArray = (PFNGLDISABLEVERTEXATTRIBARRAYPROC)Context->getProcAddress("glDisableVertexAttribArray");
|
||||
lcEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC)Context->getProcAddress("glEnableVertexAttribArray");
|
||||
lcGetActiveAttrib = (PFNGLGETACTIVEATTRIBPROC)Context->getProcAddress("glGetActiveAttrib");
|
||||
lcGetActiveUniform = (PFNGLGETACTIVEUNIFORMPROC)Context->getProcAddress("glGetActiveUniform");
|
||||
lcGetAttachedShaders = (PFNGLGETATTACHEDSHADERSPROC)Context->getProcAddress("glGetAttachedShaders");
|
||||
lcGetAttribLocation = (PFNGLGETATTRIBLOCATIONPROC)Context->getProcAddress("glGetAttribLocation");
|
||||
lcGetProgramiv = (PFNGLGETPROGRAMIVPROC)Context->getProcAddress("glGetProgramiv");
|
||||
lcGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC)Context->getProcAddress("glGetProgramInfoLog");
|
||||
lcGetShaderiv = (PFNGLGETSHADERIVPROC)Context->getProcAddress("glGetShaderiv");
|
||||
lcGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC)Context->getProcAddress("glGetShaderInfoLog");
|
||||
lcGetShaderSource = (PFNGLGETSHADERSOURCEPROC)Context->getProcAddress("glGetShaderSource");
|
||||
lcGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC)Context->getProcAddress("glGetUniformLocation");
|
||||
lcGetUniformfv = (PFNGLGETUNIFORMFVPROC)Context->getProcAddress("glGetUniformfv");
|
||||
lcGetUniformiv = (PFNGLGETUNIFORMIVPROC)Context->getProcAddress("glGetUniformiv");
|
||||
lcGetVertexAttribdv = (PFNGLGETVERTEXATTRIBDVPROC)Context->getProcAddress("glGetVertexAttribdv");
|
||||
lcGetVertexAttribfv = (PFNGLGETVERTEXATTRIBFVPROC)Context->getProcAddress("glGetVertexAttribfv");
|
||||
lcGetVertexAttribiv = (PFNGLGETVERTEXATTRIBIVPROC)Context->getProcAddress("glGetVertexAttribiv");
|
||||
lcGetVertexAttribPointerv = (PFNGLGETVERTEXATTRIBPOINTERVPROC)Context->getProcAddress("glGetVertexAttribPointerv");
|
||||
lcIsProgram = (PFNGLISPROGRAMPROC)Context->getProcAddress("glIsProgram");
|
||||
lcIsShader = (PFNGLISSHADERPROC)Context->getProcAddress("glIsShader");
|
||||
lcLinkProgram = (PFNGLLINKPROGRAMPROC)Context->getProcAddress("glLinkProgram");
|
||||
lcShaderSource = (PFNGLSHADERSOURCEPROC)Context->getProcAddress("glShaderSource");
|
||||
lcUseProgram = (PFNGLUSEPROGRAMPROC)Context->getProcAddress("glUseProgram");
|
||||
lcUniform1f = (PFNGLUNIFORM1FPROC)Context->getProcAddress("glUniform1f");
|
||||
lcUniform2f = (PFNGLUNIFORM2FPROC)Context->getProcAddress("glUniform2f");
|
||||
lcUniform3f = (PFNGLUNIFORM3FPROC)Context->getProcAddress("glUniform3f");
|
||||
lcUniform4f = (PFNGLUNIFORM4FPROC)Context->getProcAddress("glUniform4f");
|
||||
lcUniform1i = (PFNGLUNIFORM1IPROC)Context->getProcAddress("glUniform1i");
|
||||
lcUniform2i = (PFNGLUNIFORM2IPROC)Context->getProcAddress("glUniform2i");
|
||||
lcUniform3i = (PFNGLUNIFORM3IPROC)Context->getProcAddress("glUniform3i");
|
||||
lcUniform4i = (PFNGLUNIFORM4IPROC)Context->getProcAddress("glUniform4i");
|
||||
lcUniform1fv = (PFNGLUNIFORM1FVPROC)Context->getProcAddress("glUniform1fv");
|
||||
lcUniform2fv = (PFNGLUNIFORM2FVPROC)Context->getProcAddress("glUniform2fv");
|
||||
lcUniform3fv = (PFNGLUNIFORM3FVPROC)Context->getProcAddress("glUniform3fv");
|
||||
lcUniform4fv = (PFNGLUNIFORM4FVPROC)Context->getProcAddress("glUniform4fv");
|
||||
lcUniform1iv = (PFNGLUNIFORM1IVPROC)Context->getProcAddress("glUniform1iv");
|
||||
lcUniform2iv = (PFNGLUNIFORM2IVPROC)Context->getProcAddress("glUniform2iv");
|
||||
lcUniform3iv = (PFNGLUNIFORM3IVPROC)Context->getProcAddress("glUniform3iv");
|
||||
lcUniform4iv = (PFNGLUNIFORM4IVPROC)Context->getProcAddress("glUniform4iv");
|
||||
lcUniformMatrix2fv = (PFNGLUNIFORMMATRIX2FVPROC)Context->getProcAddress("glUniformMatrix2fv");
|
||||
lcUniformMatrix3fv = (PFNGLUNIFORMMATRIX3FVPROC)Context->getProcAddress("glUniformMatrix3fv");
|
||||
lcUniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC)Context->getProcAddress("glUniformMatrix4fv");
|
||||
lcValidateProgram = (PFNGLVALIDATEPROGRAMPROC)Context->getProcAddress("glValidateProgram");
|
||||
lcVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC)Context->getProcAddress("glVertexAttribPointer");
|
||||
#endif
|
||||
gSupportsShaderObjects = true;
|
||||
}
|
||||
|
||||
#ifndef LC_OPENGLES
|
||||
if (VersionMajor > 3 || (VersionMajor == 3 && VersionMinor >= 2))
|
||||
{
|
||||
#ifdef LC_LOAD_GLEXTENSIONS
|
||||
lcTexImage2DMultisample = (PFNGLTEXIMAGE2DMULTISAMPLEPROC)Context->getProcAddress("glTexImage2DMultisample");
|
||||
#endif
|
||||
|
||||
gSupportsTexImage2DMultisample = true;
|
||||
}
|
||||
|
||||
if (VersionMajor >= 4)
|
||||
{
|
||||
#ifdef LC_LOAD_GLEXTENSIONS
|
||||
lcBlendFuncSeparate = (PFNGLBLENDFUNCSEPARATEPROC)Context->getProcAddress("glBlendFuncSeparate");
|
||||
#endif
|
||||
|
||||
gSupportsBlendFuncSeparate = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef LC_OPENGLES
|
||||
gSupportsVertexBufferObject = true;
|
||||
gSupportsFramebufferObjectARB = true;
|
||||
gSupportsShaderObjects = true;
|
||||
#endif
|
||||
gSupportsVertexBufferObject = Functions->hasOpenGLFeature(QOpenGLFunctions::Buffers);
|
||||
gSupportsFramebufferObject = Functions->hasOpenGLFeature(QOpenGLFunctions::Framebuffers);
|
||||
gSupportsBlendFuncSeparate = Functions->hasOpenGLFeature(QOpenGLFunctions::BlendFuncSeparate);
|
||||
gSupportsShaderObjects = Functions->hasOpenGLFeature(QOpenGLFunctions::Shaders);
|
||||
}
|
||||
|
|
|
@ -1,236 +1,10 @@
|
|||
#pragma once
|
||||
|
||||
void lcInitializeGLExtensions(const QGLContext* Context);
|
||||
void lcInitializeGLExtensions(const QOpenGLContext* Context);
|
||||
|
||||
extern bool gSupportsShaderObjects;
|
||||
extern bool gSupportsVertexBufferObject;
|
||||
extern bool gSupportsFramebufferObjectARB;
|
||||
extern bool gSupportsFramebufferObjectEXT;
|
||||
extern bool gSupportsTexImage2DMultisample;
|
||||
extern bool gSupportsFramebufferObject;
|
||||
extern bool gSupportsBlendFuncSeparate;
|
||||
extern bool gSupportsAnisotropic;
|
||||
extern GLfloat gMaxAnisotropy;
|
||||
|
||||
#if !defined(Q_OS_MAC) && !defined(QT_OPENGL_ES)
|
||||
#define LC_LOAD_GLEXTENSIONS
|
||||
#endif
|
||||
|
||||
#ifdef LC_LOAD_GLEXTENSIONS
|
||||
|
||||
extern PFNGLBINDBUFFERARBPROC lcBindBufferARB;
|
||||
extern PFNGLDELETEBUFFERSARBPROC lcDeleteBuffersARB;
|
||||
extern PFNGLGENBUFFERSARBPROC lcGenBuffersARB;
|
||||
extern PFNGLISBUFFERARBPROC lcIsBufferARB;
|
||||
extern PFNGLBUFFERDATAARBPROC lcBufferDataARB;
|
||||
extern PFNGLBUFFERSUBDATAARBPROC lcBufferSubDataARB;
|
||||
extern PFNGLGETBUFFERSUBDATAARBPROC lcGetBufferSubDataARB;
|
||||
extern PFNGLMAPBUFFERARBPROC lcMapBufferARB;
|
||||
extern PFNGLUNMAPBUFFERARBPROC lcUnmapBufferARB;
|
||||
extern PFNGLGETBUFFERPARAMETERIVARBPROC lcGetBufferParameterivARB;
|
||||
extern PFNGLGETBUFFERPOINTERVARBPROC lcGetBufferPointervARB;
|
||||
|
||||
extern PFNGLISRENDERBUFFERPROC lcIsRenderbuffer;
|
||||
extern PFNGLBINDRENDERBUFFERPROC lcBindRenderbuffer;
|
||||
extern PFNGLDELETERENDERBUFFERSPROC lcDeleteRenderbuffers;
|
||||
extern PFNGLGENRENDERBUFFERSPROC lcGenRenderbuffers;
|
||||
extern PFNGLRENDERBUFFERSTORAGEPROC lcRenderbufferStorage;
|
||||
extern PFNGLGETRENDERBUFFERPARAMETERIVPROC lcGetRenderbufferParameteriv;
|
||||
extern PFNGLISFRAMEBUFFERPROC lcIsFramebuffer;
|
||||
extern PFNGLBINDFRAMEBUFFERPROC lcBindFramebuffer;
|
||||
extern PFNGLDELETEFRAMEBUFFERSPROC lcDeleteFramebuffers;
|
||||
extern PFNGLGENFRAMEBUFFERSPROC lcGenFramebuffers;
|
||||
extern PFNGLCHECKFRAMEBUFFERSTATUSPROC lcCheckFramebufferStatus;
|
||||
extern PFNGLFRAMEBUFFERTEXTURE1DPROC lcFramebufferTexture1D;
|
||||
extern PFNGLFRAMEBUFFERTEXTURE2DPROC lcFramebufferTexture2D;
|
||||
extern PFNGLFRAMEBUFFERTEXTURE3DPROC lcFramebufferTexture3D;
|
||||
extern PFNGLFRAMEBUFFERRENDERBUFFERPROC lcFramebufferRenderbuffer;
|
||||
extern PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC lcGetFramebufferAttachmentParameteriv;
|
||||
extern PFNGLGENERATEMIPMAPPROC lcGenerateMipmap;
|
||||
extern PFNGLBLITFRAMEBUFFERPROC lcBlitFramebuffer;
|
||||
extern PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC lcRenderbufferStorageMultisample;
|
||||
extern PFNGLFRAMEBUFFERTEXTURELAYERPROC lcFramebufferTextureLayer;
|
||||
|
||||
extern PFNGLISRENDERBUFFEREXTPROC lcIsRenderbufferEXT;
|
||||
extern PFNGLBINDRENDERBUFFEREXTPROC lcBindRenderbufferEXT;
|
||||
extern PFNGLDELETERENDERBUFFERSEXTPROC lcDeleteRenderbuffersEXT;
|
||||
extern PFNGLGENRENDERBUFFERSEXTPROC lcGenRenderbuffersEXT;
|
||||
extern PFNGLRENDERBUFFERSTORAGEEXTPROC lcRenderbufferStorageEXT;
|
||||
extern PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC lcGetRenderbufferParameterivEXT;
|
||||
extern PFNGLISFRAMEBUFFEREXTPROC lcIsFramebufferEXT;
|
||||
extern PFNGLBINDFRAMEBUFFEREXTPROC lcBindFramebufferEXT;
|
||||
extern PFNGLDELETEFRAMEBUFFERSEXTPROC lcDeleteFramebuffersEXT;
|
||||
extern PFNGLGENFRAMEBUFFERSEXTPROC lcGenFramebuffersEXT;
|
||||
extern PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC lcCheckFramebufferStatusEXT;
|
||||
extern PFNGLFRAMEBUFFERTEXTURE1DEXTPROC lcFramebufferTexture1DEXT;
|
||||
extern PFNGLFRAMEBUFFERTEXTURE2DEXTPROC lcFramebufferTexture2DEXT;
|
||||
extern PFNGLFRAMEBUFFERTEXTURE3DEXTPROC lcFramebufferTexture3DEXT;
|
||||
extern PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC lcFramebufferRenderbufferEXT;
|
||||
extern PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC lcGetFramebufferAttachmentParameterivEXT;
|
||||
extern PFNGLGENERATEMIPMAPEXTPROC lcGenerateMipmapEXT;
|
||||
|
||||
extern PFNGLATTACHSHADERPROC lcAttachShader;
|
||||
extern PFNGLBINDATTRIBLOCATIONPROC lcBindAttribLocation;
|
||||
extern PFNGLCOMPILESHADERPROC lcCompileShader;
|
||||
extern PFNGLCREATEPROGRAMPROC lcCreateProgram;
|
||||
extern PFNGLCREATESHADERPROC lcCreateShader;
|
||||
extern PFNGLDELETEPROGRAMPROC lcDeleteProgram;
|
||||
extern PFNGLDELETESHADERPROC lcDeleteShader;
|
||||
extern PFNGLDETACHSHADERPROC lcDetachShader;
|
||||
extern PFNGLDISABLEVERTEXATTRIBARRAYPROC lcDisableVertexAttribArray;
|
||||
extern PFNGLENABLEVERTEXATTRIBARRAYPROC lcEnableVertexAttribArray;
|
||||
extern PFNGLGETACTIVEATTRIBPROC lcGetActiveAttrib;
|
||||
extern PFNGLGETACTIVEUNIFORMPROC lcGetActiveUniform;
|
||||
extern PFNGLGETATTACHEDSHADERSPROC lcGetAttachedShaders;
|
||||
extern PFNGLGETATTRIBLOCATIONPROC lcGetAttribLocation;
|
||||
extern PFNGLGETPROGRAMIVPROC lcGetProgramiv;
|
||||
extern PFNGLGETPROGRAMINFOLOGPROC lcGetProgramInfoLog;
|
||||
extern PFNGLGETSHADERIVPROC lcGetShaderiv;
|
||||
extern PFNGLGETSHADERINFOLOGPROC lcGetShaderInfoLog;
|
||||
extern PFNGLGETSHADERSOURCEPROC lcGetShaderSource;
|
||||
extern PFNGLGETUNIFORMLOCATIONPROC lcGetUniformLocation;
|
||||
extern PFNGLGETUNIFORMFVPROC lcGetUniformfv;
|
||||
extern PFNGLGETUNIFORMIVPROC lcGetUniformiv;
|
||||
extern PFNGLGETVERTEXATTRIBDVPROC lcGetVertexAttribdv;
|
||||
extern PFNGLGETVERTEXATTRIBFVPROC lcGetVertexAttribfv;
|
||||
extern PFNGLGETVERTEXATTRIBIVPROC lcGetVertexAttribiv;
|
||||
extern PFNGLGETVERTEXATTRIBPOINTERVPROC lcGetVertexAttribPointerv;
|
||||
extern PFNGLISPROGRAMPROC lcIsProgram;
|
||||
extern PFNGLISSHADERPROC lcIsShader;
|
||||
extern PFNGLLINKPROGRAMPROC lcLinkProgram;
|
||||
extern PFNGLSHADERSOURCEPROC lcShaderSource;
|
||||
extern PFNGLUSEPROGRAMPROC lcUseProgram;
|
||||
extern PFNGLUNIFORM1FPROC lcUniform1f;
|
||||
extern PFNGLUNIFORM2FPROC lcUniform2f;
|
||||
extern PFNGLUNIFORM3FPROC lcUniform3f;
|
||||
extern PFNGLUNIFORM4FPROC lcUniform4f;
|
||||
extern PFNGLUNIFORM1IPROC lcUniform1i;
|
||||
extern PFNGLUNIFORM2IPROC lcUniform2i;
|
||||
extern PFNGLUNIFORM3IPROC lcUniform3i;
|
||||
extern PFNGLUNIFORM4IPROC lcUniform4i;
|
||||
extern PFNGLUNIFORM1FVPROC lcUniform1fv;
|
||||
extern PFNGLUNIFORM2FVPROC lcUniform2fv;
|
||||
extern PFNGLUNIFORM3FVPROC lcUniform3fv;
|
||||
extern PFNGLUNIFORM4FVPROC lcUniform4fv;
|
||||
extern PFNGLUNIFORM1IVPROC lcUniform1iv;
|
||||
extern PFNGLUNIFORM2IVPROC lcUniform2iv;
|
||||
extern PFNGLUNIFORM3IVPROC lcUniform3iv;
|
||||
extern PFNGLUNIFORM4IVPROC lcUniform4iv;
|
||||
extern PFNGLUNIFORMMATRIX2FVPROC lcUniformMatrix2fv;
|
||||
extern PFNGLUNIFORMMATRIX3FVPROC lcUniformMatrix3fv;
|
||||
extern PFNGLUNIFORMMATRIX4FVPROC lcUniformMatrix4fv;
|
||||
extern PFNGLVALIDATEPROGRAMPROC lcValidateProgram;
|
||||
extern PFNGLVERTEXATTRIBPOINTERPROC lcVertexAttribPointer;
|
||||
|
||||
extern PFNGLTEXIMAGE2DMULTISAMPLEPROC lcTexImage2DMultisample;
|
||||
|
||||
extern PFNGLBLENDFUNCSEPARATEPROC lcBlendFuncSeparate;
|
||||
|
||||
#define glBindBuffer lcBindBufferARB
|
||||
#define glDeleteBuffers lcDeleteBuffersARB
|
||||
#define glGenBuffers lcGenBuffersARB
|
||||
#define glIsBuffer lcIsBufferARB
|
||||
#define glBufferData lcBufferDataARB
|
||||
#define glBufferSubData lcBufferSubDataARB
|
||||
#define glGetBufferSubData lcGetBufferSubDataARB
|
||||
#define glMapBuffer lcMapBufferARB
|
||||
#define glUnmapBuffer lcUnmapBufferARB
|
||||
#define glGetBufferParameteriv lcGetBufferParameterivARB
|
||||
#define glGetBufferPointerv lcGetBufferPointervARB
|
||||
|
||||
#define glIsRenderbuffer lcIsRenderbuffer
|
||||
#define glBindRenderbuffer lcBindRenderbuffer
|
||||
#define glDeleteRenderbuffers lcDeleteRenderbuffers
|
||||
#define glGenRenderbuffers lcGenRenderbuffers
|
||||
#define glRenderbufferStorage lcRenderbufferStorage
|
||||
#define glGetRenderbufferParameteriv lcGetRenderbufferParameteriv
|
||||
#define glIsFramebuffer lcIsFramebuffer
|
||||
#define glBindFramebuffer lcBindFramebuffer
|
||||
#define glDeleteFramebuffers lcDeleteFramebuffers
|
||||
#define glGenFramebuffers lcGenFramebuffers
|
||||
#define glCheckFramebufferStatus lcCheckFramebufferStatus
|
||||
#define glFramebufferTexture1D lcFramebufferTexture1D
|
||||
#define glFramebufferTexture2D lcFramebufferTexture2D
|
||||
#define glFramebufferTexture3D lcFramebufferTexture3D
|
||||
#define glFramebufferRenderbuffer lcFramebufferRenderbuffer
|
||||
#define glGetFramebufferAttachmentParameteriv lcGetFramebufferAttachmentParameteriv
|
||||
#define glGenerateMipmap lcGenerateMipmap
|
||||
#define glBlitFramebuffer lcBlitFramebuffer
|
||||
#define glRenderbufferStorageMultisample lcRenderbufferStorageMultisample
|
||||
#define glFramebufferTextureLayer lcFramebufferTextureLayer
|
||||
|
||||
#define glIsRenderbufferEXT lcIsRenderbufferEXT
|
||||
#define glBindRenderbufferEXT lcBindRenderbufferEXT
|
||||
#define glDeleteRenderbuffersEXT lcDeleteRenderbuffersEXT
|
||||
#define glGenRenderbuffersEXT lcGenRenderbuffersEXT
|
||||
#define glRenderbufferStorageEXT lcRenderbufferStorageEXT
|
||||
#define glGetRenderbufferParameterivEXT lcGetRenderbufferParameterivEXT
|
||||
#define glIsFramebufferEXT lcIsFramebufferEXT
|
||||
#define glBindFramebufferEXT lcBindFramebufferEXT
|
||||
#define glDeleteFramebuffersEXT lcDeleteFramebuffersEXT
|
||||
#define glGenFramebuffersEXT lcGenFramebuffersEXT
|
||||
#define glCheckFramebufferStatusEXT lcCheckFramebufferStatusEXT
|
||||
#define glFramebufferTexture1DEXT lcFramebufferTexture1DEXT
|
||||
#define glFramebufferTexture2DEXT lcFramebufferTexture2DEXT
|
||||
#define glFramebufferTexture3DEXT lcFramebufferTexture3DEXT
|
||||
#define glFramebufferRenderbufferEXT lcFramebufferRenderbufferEXT
|
||||
#define glGetFramebufferAttachmentParameterivEXT lcGetFramebufferAttachmentParameterivEXT
|
||||
#define glGenerateMipmapEXT lcGenerateMipmapEXT
|
||||
|
||||
#define glAttachShader lcAttachShader
|
||||
#define glBindAttribLocation lcBindAttribLocation
|
||||
#define glCompileShader lcCompileShader
|
||||
#define glCreateProgram lcCreateProgram
|
||||
#define glCreateShader lcCreateShader
|
||||
#define glDeleteProgram lcDeleteProgram
|
||||
#define glDeleteShader lcDeleteShader
|
||||
#define glDetachShader lcDetachShader
|
||||
#define glDisableVertexAttribArray lcDisableVertexAttribArray
|
||||
#define glEnableVertexAttribArray lcEnableVertexAttribArray
|
||||
#define glGetActiveAttrib lcGetActiveAttrib
|
||||
#define glGetActiveUniform lcGetActiveUniform
|
||||
#define glGetAttachedShaders lcGetAttachedShaders
|
||||
#define glGetAttribLocation lcGetAttribLocation
|
||||
#define glGetProgramiv lcGetProgramiv
|
||||
#define glGetProgramInfoLog lcGetProgramInfoLog
|
||||
#define glGetShaderiv lcGetShaderiv
|
||||
#define glGetShaderInfoLog lcGetShaderInfoLog
|
||||
#define glGetShaderSource lcGetShaderSource
|
||||
#define glGetUniformLocation lcGetUniformLocation
|
||||
#define glGetUniformfv lcGetUniformfv
|
||||
#define glGetUniformiv lcGetUniformiv
|
||||
#define glGetVertexAttribdv lcGetVertexAttribdv
|
||||
#define glGetVertexAttribfv lcGetVertexAttribfv
|
||||
#define glGetVertexAttribiv lcGetVertexAttribiv
|
||||
#define glGetVertexAttribPointerv lcGetVertexAttribPointerv
|
||||
#define glIsProgram lcIsProgram
|
||||
#define glIsShader lcIsShader
|
||||
#define glLinkProgram lcLinkProgram
|
||||
#define glShaderSource lcShaderSource
|
||||
#define glUseProgram lcUseProgram
|
||||
#define glUniform1f lcUniform1f
|
||||
#define glUniform2f lcUniform2f
|
||||
#define glUniform3f lcUniform3f
|
||||
#define glUniform4f lcUniform4f
|
||||
#define glUniform1i lcUniform1i
|
||||
#define glUniform2i lcUniform2i
|
||||
#define glUniform3i lcUniform3i
|
||||
#define glUniform4i lcUniform4i
|
||||
#define glUniform1fv lcUniform1fv
|
||||
#define glUniform2fv lcUniform2fv
|
||||
#define glUniform3fv lcUniform3fv
|
||||
#define glUniform4fv lcUniform4fv
|
||||
#define glUniform1iv lcUniform1iv
|
||||
#define glUniform2iv lcUniform2iv
|
||||
#define glUniform3iv lcUniform3iv
|
||||
#define glUniform4iv lcUniform4iv
|
||||
#define glUniformMatrix2fv lcUniformMatrix2fv
|
||||
#define glUniformMatrix3fv lcUniformMatrix3fv
|
||||
#define glUniformMatrix4fv lcUniformMatrix4fv
|
||||
#define glValidateProgram lcValidateProgram
|
||||
#define glVertexAttribPointer lcVertexAttribPointer
|
||||
|
||||
#define glTexImage2DMultisample lcTexImage2DMultisample
|
||||
|
||||
#define glBlendFuncSeparate lcBlendFuncSeparate
|
||||
|
||||
#endif
|
||||
|
|
|
@ -9,11 +9,19 @@
|
|||
#include <QGLWidget>
|
||||
#include <QtGui>
|
||||
#include <QPrinter>
|
||||
#include <QtConcurrent>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include <set>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
#if _MSC_VER
|
||||
#pragma warning(default : 4062) // enumerator 'identifier' in switch of enum 'enumeration' is not handled
|
||||
#pragma warning(default : 4388) // 'token' : signed/unsigned mismatch
|
||||
#pragma warning(default : 4389) // 'equality-operator' : signed/unsigned mismatch
|
||||
#endif
|
||||
|
||||
#ifndef Q_FALLTHROUGH
|
||||
#define Q_FALLTHROUGH();
|
||||
|
@ -25,13 +33,9 @@
|
|||
#endif
|
||||
|
||||
#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)
|
||||
#undef GL_LINES_ADJACENCY_EXT
|
||||
#undef GL_LINE_STRIP_ADJACENCY_EXT
|
||||
#undef GL_TRIANGLES_ADJACENCY_EXT
|
||||
#undef GL_TRIANGLE_STRIP_ADJACENCY_EXT
|
||||
#include "lc_glext.h"
|
||||
#else
|
||||
#define LC_OPENGLES 1
|
||||
#endif
|
||||
|
@ -40,18 +44,20 @@
|
|||
#define LC_MAXPATH 1024
|
||||
#define LC_MAXNAME 1000
|
||||
|
||||
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);
|
||||
char* strlwr(char* string);
|
||||
#endif
|
||||
|
||||
// Version number.
|
||||
#define LC_VERSION_MAJOR 19
|
||||
#define LC_VERSION_MINOR 07
|
||||
#define LC_VERSION_PATCH 1
|
||||
#define LC_VERSION_TEXT "19.07.1"
|
||||
#define LC_VERSION_MAJOR 21
|
||||
#define LC_VERSION_MINOR 01
|
||||
#define LC_VERSION_PATCH 0
|
||||
#define LC_VERSION_TEXT "21.01"
|
||||
|
||||
// Forward declarations.
|
||||
class Project;
|
||||
|
@ -64,6 +70,14 @@ class lcGroup;
|
|||
class PieceInfo;
|
||||
typedef std::map<const PieceInfo*, std::map<int, int>> lcPartsList;
|
||||
struct lcModelPartsEntry;
|
||||
struct lcMinifig;
|
||||
enum class lcViewpoint;
|
||||
enum class lcShadingMode;
|
||||
enum class lcStudStyle;
|
||||
class lcInstructions;
|
||||
struct lcInstructionsPageSetup;
|
||||
struct lcObjectRayTest;
|
||||
struct lcObjectBoxTest;
|
||||
|
||||
class lcVector2;
|
||||
class lcVector3;
|
||||
|
@ -71,12 +85,19 @@ class lcVector4;
|
|||
class lcMatrix33;
|
||||
class lcMatrix44;
|
||||
|
||||
class lcFindReplaceWidget;
|
||||
struct lcFindReplaceParams;
|
||||
class lcCollapsibleWidget;
|
||||
class lcViewWidget;
|
||||
class lcView;
|
||||
class lcContext;
|
||||
class lcMesh;
|
||||
struct lcMeshSection;
|
||||
struct lcRenderMesh;
|
||||
struct lcObjectSection;
|
||||
class lcTexture;
|
||||
class lcScene;
|
||||
class lcViewSphere;
|
||||
enum class lcRenderMeshState : int;
|
||||
|
||||
class lcFile;
|
||||
|
|
|
@ -1,96 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "lc_context.h"
|
||||
|
||||
enum class lcCursor
|
||||
{
|
||||
Default,
|
||||
Brick,
|
||||
Light,
|
||||
Spotlight,
|
||||
Camera,
|
||||
Select,
|
||||
SelectAdd,
|
||||
SelectRemove,
|
||||
Move,
|
||||
Rotate,
|
||||
RotateX,
|
||||
RotateY,
|
||||
Delete,
|
||||
Paint,
|
||||
ColorPicker,
|
||||
Zoom,
|
||||
ZoomRegion,
|
||||
Pan,
|
||||
Roll,
|
||||
RotateView,
|
||||
Count
|
||||
};
|
||||
|
||||
struct lcInputState
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
Qt::KeyboardModifiers Modifiers;
|
||||
};
|
||||
|
||||
class lcGLWidget
|
||||
{
|
||||
public:
|
||||
lcGLWidget()
|
||||
{
|
||||
mCursor = lcCursor::Default;
|
||||
mWidget = nullptr;
|
||||
mInputState.x = 0;
|
||||
mInputState.y = 0;
|
||||
mInputState.Modifiers = Qt::NoModifier;
|
||||
mWidth = 1;
|
||||
mHeight = 1;
|
||||
mContext = new lcContext();
|
||||
mDeleteContext = true;
|
||||
}
|
||||
|
||||
virtual ~lcGLWidget()
|
||||
{
|
||||
if (mDeleteContext)
|
||||
delete mContext;
|
||||
}
|
||||
|
||||
void SetContext(lcContext* Context)
|
||||
{
|
||||
if (mDeleteContext)
|
||||
delete mContext;
|
||||
|
||||
mContext = Context;
|
||||
mDeleteContext = false;
|
||||
}
|
||||
|
||||
void MakeCurrent();
|
||||
void Redraw();
|
||||
void SetCursor(lcCursor Cursor);
|
||||
|
||||
virtual void OnDraw() { }
|
||||
virtual void OnInitialUpdate() { }
|
||||
virtual void OnUpdateCursor() { }
|
||||
virtual void OnLeftButtonDown() { }
|
||||
virtual void OnLeftButtonUp() { }
|
||||
virtual void OnLeftButtonDoubleClick() { }
|
||||
virtual void OnMiddleButtonDown() { }
|
||||
virtual void OnMiddleButtonUp() { }
|
||||
virtual void OnRightButtonDown() { }
|
||||
virtual void OnRightButtonUp() { }
|
||||
virtual void OnBackButtonDown() { }
|
||||
virtual void OnBackButtonUp() { }
|
||||
virtual void OnForwardButtonDown() { }
|
||||
virtual void OnForwardButtonUp() { }
|
||||
virtual void OnMouseMove() { }
|
||||
virtual void OnMouseWheel(float Direction) { Q_UNUSED(Direction); }
|
||||
|
||||
lcInputState mInputState;
|
||||
int mWidth;
|
||||
int mHeight;
|
||||
lcCursor mCursor;
|
||||
void* mWidget;
|
||||
lcContext* mContext;
|
||||
bool mDeleteContext;
|
||||
};
|
253
common/lc_instructions.cpp
Normal file
253
common/lc_instructions.cpp
Normal file
|
@ -0,0 +1,253 @@
|
|||
#include "lc_global.h"
|
||||
#include "lc_instructions.h"
|
||||
#include "project.h"
|
||||
#include "lc_model.h"
|
||||
#include "piece.h"
|
||||
#include "pieceinf.h"
|
||||
|
||||
const float lcInstructions::mDisplayDPI = 72.0f;
|
||||
|
||||
lcInstructions::lcInstructions(Project* Project)
|
||||
: mProject(Project)
|
||||
{
|
||||
mPageSetup.Width = 8.5f * mDisplayDPI;
|
||||
mPageSetup.Height = 11.0f * mDisplayDPI;
|
||||
mPageSetup.MarginLeft = 0.5 * mDisplayDPI;
|
||||
mPageSetup.MarginRight = 0.5 * mDisplayDPI;
|
||||
mPageSetup.MarginTop = 0.5 * mDisplayDPI;
|
||||
mPageSetup.MarginBottom = 0.5 * mDisplayDPI;
|
||||
|
||||
mPageSettings.Rows = 1;
|
||||
mPageSettings.Columns = 1;
|
||||
mPageSettings.Direction = lcInstructionsDirection::Horizontal;
|
||||
|
||||
mStepProperties[static_cast<int>(lcInstructionsPropertyType::ShowStepNumber)].Value = true;
|
||||
mStepProperties[static_cast<int>(lcInstructionsPropertyType::ShowStepPLI)].Value = true;
|
||||
mStepProperties[static_cast<int>(lcInstructionsPropertyType::StepNumberFont)].Value = QFont("Arial", 72).toString();
|
||||
mStepProperties[static_cast<int>(lcInstructionsPropertyType::StepNumberColor)].Value = LC_RGBA(0, 0, 0, 255);
|
||||
mStepProperties[static_cast<int>(lcInstructionsPropertyType::StepBackgroundColor)].Value = LC_RGBA(255, 255, 255, 0);
|
||||
mStepProperties[static_cast<int>(lcInstructionsPropertyType::PLIBackgroundColor)].Value = LC_RGBA(255, 255, 255, 255);
|
||||
mStepProperties[static_cast<int>(lcInstructionsPropertyType::PLIFont)].Value = QFont("Arial", 16, QFont::Bold).toString();
|
||||
mStepProperties[static_cast<int>(lcInstructionsPropertyType::PLITextColor)].Value = LC_RGBA(0, 0, 0, 255);
|
||||
mStepProperties[static_cast<int>(lcInstructionsPropertyType::PLIBorderColor)].Value = LC_RGBA(0, 0, 0, 255);
|
||||
// mStepProperties[static_cast<int>(lcInstructionsPropertyType::PLIBorderWidth)].Value = 2.0f;
|
||||
// mStepProperties[static_cast<int>(lcInstructionsPropertyType::PLIBorderRound)].Value = true;
|
||||
|
||||
static_assert(static_cast<int>(lcInstructionsPropertyType::Count) == 9, "Missing default property");
|
||||
|
||||
CreatePages();
|
||||
}
|
||||
|
||||
QString lcInstructions::GetPropertyLabel(lcInstructionsPropertyType Type)
|
||||
{
|
||||
switch (Type)
|
||||
{
|
||||
case lcInstructionsPropertyType::ShowStepNumber:
|
||||
return tr("Show Step Number");
|
||||
case lcInstructionsPropertyType::ShowStepPLI:
|
||||
return tr("Show Parts List");
|
||||
case lcInstructionsPropertyType::StepNumberFont:
|
||||
return tr("Font:");
|
||||
case lcInstructionsPropertyType::StepNumberColor:
|
||||
return tr("Text Color:");
|
||||
case lcInstructionsPropertyType::StepBackgroundColor:
|
||||
return tr("Background Color:");
|
||||
case lcInstructionsPropertyType::PLIBackgroundColor:
|
||||
return tr("Background Color:");
|
||||
case lcInstructionsPropertyType::PLIFont:
|
||||
return tr("Font:");
|
||||
case lcInstructionsPropertyType::PLITextColor:
|
||||
return tr("Text Color:");
|
||||
case lcInstructionsPropertyType::PLIBorderColor:
|
||||
return tr("Border Color:");
|
||||
case lcInstructionsPropertyType::Count:
|
||||
break;
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
void lcInstructions::SetDefaultPageSettings(const lcInstructionsPageSettings& PageSettings)
|
||||
{
|
||||
mPageSettings = PageSettings;
|
||||
|
||||
CreatePages();
|
||||
}
|
||||
|
||||
bool lcInstructions::GetBoolProperty(lcInstructionsPropertyType Type, lcModel* Model, lcStep Step) const
|
||||
{
|
||||
QVariant Value = GetProperty(Type, Model, Step);
|
||||
return Value.toBool();
|
||||
}
|
||||
|
||||
QColor lcInstructions::GetColorProperty(lcInstructionsPropertyType Type, lcModel* Model, lcStep Step) const
|
||||
{
|
||||
QVariant Value = GetProperty(Type, Model, Step);
|
||||
return lcRGBAFromQColor(Value.toUInt());
|
||||
}
|
||||
|
||||
QFont lcInstructions::GetFontProperty(lcInstructionsPropertyType Type, lcModel* Model, lcStep Step) const
|
||||
{
|
||||
QVariant Value = GetProperty(Type, Model, Step);
|
||||
QFont Font;
|
||||
Font.fromString(Value.toString());
|
||||
return Font;
|
||||
}
|
||||
|
||||
QVariant lcInstructions::GetProperty(lcInstructionsPropertyType Type, lcModel* Model, lcStep Step) const
|
||||
{
|
||||
QVariant Value = mStepProperties[static_cast<int>(Type)].Value;
|
||||
|
||||
std::map<lcModel*, lcInstructionsModel>::const_iterator ModelIt = mModels.find(Model);
|
||||
|
||||
if (ModelIt == mModels.end())
|
||||
return Value;
|
||||
|
||||
const lcInstructionsModel& InstructionModel = ModelIt->second;
|
||||
|
||||
for (lcStep StepIndex = 0; StepIndex <= Step; StepIndex++)
|
||||
{
|
||||
const lcInstructionsProperties& Properties = InstructionModel.StepProperties[StepIndex];
|
||||
const lcInstructionsProperty& Property = Properties[static_cast<int>(Type)];
|
||||
|
||||
if (Property.Mode == lcInstructionsPropertyMode::NotSet || (Property.Mode == lcInstructionsPropertyMode::StepOnly && StepIndex != Step))
|
||||
continue;
|
||||
|
||||
Value = Property.Value;
|
||||
}
|
||||
|
||||
return Value;
|
||||
}
|
||||
|
||||
void lcInstructions::SetDefaultBool(lcInstructionsPropertyType Type, bool Enabled)
|
||||
{
|
||||
SetDefaultProperty(Type, Enabled);
|
||||
}
|
||||
|
||||
void lcInstructions::SetDefaultColor(lcInstructionsPropertyType Type, const QColor& Color)
|
||||
{
|
||||
SetDefaultProperty(Type, lcRGBAFromQColor(Color));
|
||||
}
|
||||
|
||||
void lcInstructions::SetDefaultFont(lcInstructionsPropertyType Type, const QFont& Font)
|
||||
{
|
||||
SetDefaultProperty(Type, Font.toString());
|
||||
}
|
||||
|
||||
void lcInstructions::SetDefaultProperty(lcInstructionsPropertyType Type, const QVariant& Value)
|
||||
{
|
||||
lcInstructionsProperty& Property = mStepProperties[static_cast<int>(Type)];
|
||||
|
||||
if (Property.Value == Value)
|
||||
return;
|
||||
|
||||
Property.Value = Value;
|
||||
|
||||
emit StepSettingsChanged(nullptr, 0);
|
||||
}
|
||||
|
||||
void lcInstructions::CreatePages()
|
||||
{
|
||||
mPages.clear();
|
||||
|
||||
if (mProject)
|
||||
{
|
||||
std::vector<const lcModel*> AddedModels;
|
||||
|
||||
lcModel* Model = mProject->GetMainModel();
|
||||
|
||||
if (Model)
|
||||
AddDefaultPages(Model, AddedModels);
|
||||
}
|
||||
}
|
||||
|
||||
void lcInstructions::AddDefaultPages(lcModel* Model, std::vector<const lcModel*>& AddedModels)
|
||||
{
|
||||
if (std::find(AddedModels.begin(), AddedModels.end(), Model) != AddedModels.end())
|
||||
return;
|
||||
|
||||
AddedModels.push_back(Model);
|
||||
|
||||
const lcStep LastStep = Model->GetLastStep();
|
||||
lcInstructionsPage Page;
|
||||
int Row = 0, Column = 0;
|
||||
|
||||
lcInstructionsModel InstructionModel;
|
||||
InstructionModel.StepProperties.resize(LastStep + 1);
|
||||
mModels.emplace(Model, std::move(InstructionModel));
|
||||
|
||||
for (lcStep Step = 1; Step <= LastStep; Step++)
|
||||
{
|
||||
std::set<lcModel*> StepSubModels;
|
||||
|
||||
for (lcPiece* Piece : Model->GetPieces())
|
||||
{
|
||||
if (!Piece->IsHidden() && Piece->GetStepShow() == Step && Piece->mPieceInfo->IsModel())
|
||||
{
|
||||
lcModel* SubModel = Piece->mPieceInfo->GetModel();
|
||||
|
||||
if (std::find(AddedModels.begin(), AddedModels.end(), SubModel) != AddedModels.end())
|
||||
StepSubModels.insert(SubModel);
|
||||
}
|
||||
}
|
||||
|
||||
if (!StepSubModels.empty())
|
||||
{
|
||||
if (!Page.Steps.empty())
|
||||
{
|
||||
mPages.emplace_back(std::move(Page));
|
||||
Row = 0;
|
||||
Column = 0;
|
||||
}
|
||||
|
||||
for (lcModel* SubModel : StepSubModels)
|
||||
AddDefaultPages(SubModel, AddedModels);
|
||||
}
|
||||
|
||||
lcInstructionsStep InstructionsStep;
|
||||
|
||||
InstructionsStep.Model = Model;
|
||||
InstructionsStep.Step = Step;
|
||||
|
||||
const double Width = 1.0 / (double)mPageSettings.Columns;
|
||||
const double Height = 1.0 / (double)mPageSettings.Rows;
|
||||
InstructionsStep.Rect = QRectF(Column * Width, Row * Height, Width, Height);
|
||||
|
||||
Page.Steps.push_back(std::move(InstructionsStep));
|
||||
|
||||
if (mPageSettings.Direction == lcInstructionsDirection::Horizontal)
|
||||
{
|
||||
Column++;
|
||||
|
||||
if (Column == mPageSettings.Columns)
|
||||
{
|
||||
Row++;
|
||||
Column = 0;
|
||||
}
|
||||
|
||||
if (Row == mPageSettings.Rows)
|
||||
{
|
||||
mPages.emplace_back(std::move(Page));
|
||||
Row = 0;
|
||||
Column = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Row++;
|
||||
|
||||
if (Row == mPageSettings.Rows)
|
||||
{
|
||||
Row = 0;
|
||||
Column++;
|
||||
}
|
||||
|
||||
if (Column == mPageSettings.Columns)
|
||||
{
|
||||
mPages.emplace_back(std::move(Page));
|
||||
Row = 0;
|
||||
Column = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
122
common/lc_instructions.h
Normal file
122
common/lc_instructions.h
Normal file
|
@ -0,0 +1,122 @@
|
|||
#pragma once
|
||||
|
||||
#include "lc_math.h"
|
||||
|
||||
struct lcInstructionsPageSetup
|
||||
{
|
||||
float Width;
|
||||
float Height;
|
||||
float MarginLeft;
|
||||
float MarginRight;
|
||||
float MarginTop;
|
||||
float MarginBottom;
|
||||
};
|
||||
|
||||
enum class lcInstructionsDirection
|
||||
{
|
||||
Horizontal,
|
||||
Vertical
|
||||
};
|
||||
|
||||
struct lcInstructionsPageSettings
|
||||
{
|
||||
int Rows;
|
||||
int Columns;
|
||||
lcInstructionsDirection Direction;
|
||||
};
|
||||
|
||||
enum class lcInstructionsPropertyMode
|
||||
{
|
||||
NotSet,
|
||||
Default,
|
||||
Model,
|
||||
StepForward,
|
||||
StepOnly
|
||||
};
|
||||
|
||||
enum class lcInstructionsPropertyType
|
||||
{
|
||||
ShowStepNumber,
|
||||
ShowStepPLI,
|
||||
StepNumberFont,
|
||||
StepNumberColor,
|
||||
StepBackgroundColor,
|
||||
PLIBackgroundColor,
|
||||
PLIFont,
|
||||
PLITextColor,
|
||||
PLIBorderColor,
|
||||
// PLIBorderWidth,
|
||||
// PLIBorderRound,
|
||||
// pli: spacing and margins, text alignment
|
||||
Count
|
||||
};
|
||||
|
||||
struct lcInstructionsProperty
|
||||
{
|
||||
lcInstructionsPropertyMode Mode = lcInstructionsPropertyMode::NotSet;
|
||||
QVariant Value;
|
||||
};
|
||||
|
||||
using lcInstructionsProperties = std::array<lcInstructionsProperty, static_cast<int>(lcInstructionsPropertyType::Count)>;
|
||||
|
||||
struct lcInstructionsStep
|
||||
{
|
||||
QRectF Rect;
|
||||
lcModel* Model;
|
||||
lcStep Step;
|
||||
|
||||
lcInstructionsProperties Properties;
|
||||
};
|
||||
|
||||
struct lcInstructionsPage
|
||||
{
|
||||
// lcInstructionsPageSettings Settings;
|
||||
std::vector<lcInstructionsStep> Steps;
|
||||
};
|
||||
|
||||
struct lcInstructionsModel
|
||||
{
|
||||
std::vector<lcInstructionsProperties> StepProperties;
|
||||
};
|
||||
|
||||
class lcInstructions : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
lcInstructions(Project* Project = nullptr);
|
||||
|
||||
static QString GetPropertyLabel(lcInstructionsPropertyType Type);
|
||||
|
||||
void SetDefaultPageSettings(const lcInstructionsPageSettings& PageSettings);
|
||||
|
||||
bool GetBoolProperty(lcInstructionsPropertyType Type, lcModel* Model, lcStep Step) const;
|
||||
QColor GetColorProperty(lcInstructionsPropertyType Type, lcModel* Model, lcStep Step) const;
|
||||
QFont GetFontProperty(lcInstructionsPropertyType Type, lcModel* Model, lcStep Step) const;
|
||||
|
||||
void SetDefaultBool(lcInstructionsPropertyType Type, bool Enabled);
|
||||
void SetDefaultColor(lcInstructionsPropertyType Type, const QColor& Color);
|
||||
void SetDefaultFont(lcInstructionsPropertyType Type, const QFont& Font);
|
||||
|
||||
//protected:
|
||||
std::vector<lcInstructionsPage> mPages;
|
||||
lcInstructionsPageSettings mPageSettings;
|
||||
lcInstructionsPageSetup mPageSetup;
|
||||
lcInstructionsProperties mStepProperties;
|
||||
|
||||
std::map<lcModel*, lcInstructionsModel> mModels;
|
||||
|
||||
signals:
|
||||
void StepSettingsChanged(lcModel* Model, lcStep Step);
|
||||
|
||||
protected:
|
||||
void CreatePages();
|
||||
void AddDefaultPages(lcModel* Model, std::vector<const lcModel*>& AddedModels);
|
||||
|
||||
QVariant GetProperty(lcInstructionsPropertyType Type, lcModel* Model, lcStep Step) const;
|
||||
void SetDefaultProperty(lcInstructionsPropertyType Type, const QVariant& Value);
|
||||
|
||||
Project* mProject = nullptr;
|
||||
|
||||
static const float mDisplayDPI;
|
||||
};
|
632
common/lc_instructionsdialog.cpp
Normal file
632
common/lc_instructionsdialog.cpp
Normal file
|
@ -0,0 +1,632 @@
|
|||
#include "lc_global.h"
|
||||
#include "lc_instructionsdialog.h"
|
||||
#include "lc_pagesetupdialog.h"
|
||||
#include "project.h"
|
||||
#include "lc_model.h"
|
||||
#include "lc_view.h"
|
||||
#include "lc_collapsiblewidget.h"
|
||||
|
||||
lcInstructionsStepImageItem::lcInstructionsStepImageItem(QGraphicsItem* Parent, lcInstructions* Instructions, lcModel* Model, lcStep Step)
|
||||
: QGraphicsPixmapItem(Parent), mInstructions(Instructions), mModel(Model), mStep(Step)
|
||||
{
|
||||
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsFocusable);
|
||||
}
|
||||
|
||||
void lcInstructionsStepImageItem::Update()
|
||||
{
|
||||
lcView View(lcViewType::View, mModel);
|
||||
|
||||
View.SetOffscreenContext();
|
||||
View.MakeCurrent();
|
||||
View.SetBackgroundColorOverride(lcRGBAFromQColor(mInstructions->GetColorProperty(lcInstructionsPropertyType::StepBackgroundColor, mModel, mStep)));
|
||||
View.SetSize(mWidth, mHeight);
|
||||
|
||||
std::vector<QImage> Images = View.GetStepImages(mStep, mStep);
|
||||
|
||||
if (!Images.empty())
|
||||
setPixmap(QPixmap::fromImage(Images.front()));
|
||||
}
|
||||
|
||||
lcInstructionsStepNumberItem::lcInstructionsStepNumberItem(QGraphicsItem* Parent, lcInstructions* Instructions, lcModel* Model, lcStep Step)
|
||||
: QGraphicsSimpleTextItem(Parent), mInstructions(Instructions), mModel(Model), mStep(Step)
|
||||
{
|
||||
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsFocusable);
|
||||
}
|
||||
|
||||
void lcInstructionsStepNumberItem::Update()
|
||||
{
|
||||
bool Visible = mInstructions->GetBoolProperty(lcInstructionsPropertyType::ShowStepNumber, mModel, mStep);
|
||||
setVisible(Visible);
|
||||
|
||||
QFont StepNumberFont = mInstructions->GetFontProperty(lcInstructionsPropertyType::StepNumberFont, mModel, mStep);
|
||||
|
||||
setFont(StepNumberFont);
|
||||
setBrush(QBrush(mInstructions->GetColorProperty(lcInstructionsPropertyType::StepNumberColor, mModel, mStep)));
|
||||
setText(QString::number(mStep));
|
||||
}
|
||||
|
||||
lcInstructionsPartsListItem::lcInstructionsPartsListItem(QGraphicsItem* Parent, lcInstructions* Instructions, lcModel* Model, lcStep Step)
|
||||
: QGraphicsPixmapItem(Parent), mInstructions(Instructions), mModel(Model), mStep(Step)
|
||||
{
|
||||
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsFocusable);
|
||||
}
|
||||
|
||||
void lcInstructionsPartsListItem::Update()
|
||||
{
|
||||
bool Visible = mInstructions->GetBoolProperty(lcInstructionsPropertyType::ShowStepPLI, mModel, mStep);
|
||||
setVisible(Visible);
|
||||
|
||||
if (!Visible)
|
||||
return;
|
||||
|
||||
QColor BackgroundColor = mInstructions->GetColorProperty(lcInstructionsPropertyType::PLIBackgroundColor, mModel, mStep);
|
||||
QFont Font = mInstructions->GetFontProperty(lcInstructionsPropertyType::PLIFont, mModel, mStep);
|
||||
QColor TextColor = mInstructions->GetColorProperty(lcInstructionsPropertyType::PLITextColor, mModel, mStep);
|
||||
|
||||
QImage PartsImage = mModel->GetPartsListImage(300, mStep, lcRGBAFromQColor(BackgroundColor), Font, TextColor);
|
||||
setPixmap(QPixmap::fromImage(PartsImage));
|
||||
}
|
||||
|
||||
lcInstructionsPageWidget::lcInstructionsPageWidget(QWidget* Parent, lcInstructions* Instructions, lcInstructionsPropertiesWidget* PropertiesWidget)
|
||||
: QGraphicsView(Parent), mInstructions(Instructions), mPropertiesWidget(PropertiesWidget)
|
||||
{
|
||||
QGraphicsScene* Scene = new QGraphicsScene();
|
||||
setScene(Scene);
|
||||
|
||||
connect(mInstructions, &lcInstructions::StepSettingsChanged, this, &lcInstructionsPageWidget::StepSettingsChanged);
|
||||
connect(Scene, &QGraphicsScene::selectionChanged, this, &lcInstructionsPageWidget::SelectionChanged);
|
||||
}
|
||||
|
||||
void lcInstructionsPageWidget::StepSettingsChanged(lcModel* Model, lcStep Step)
|
||||
{
|
||||
QGraphicsScene* Scene = scene();
|
||||
|
||||
QList<QGraphicsItem*> Items = Scene->items();
|
||||
|
||||
for (QGraphicsItem* Item : Items)
|
||||
{
|
||||
lcInstructionsStepImageItem* ImageItem = dynamic_cast<lcInstructionsStepImageItem*>(Item);
|
||||
|
||||
if (ImageItem)
|
||||
{
|
||||
if (!Model || (ImageItem->GetModel() == Model && ImageItem->GetStep() == Step))
|
||||
ImageItem->Update();
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
lcInstructionsStepNumberItem* NumberItem = dynamic_cast<lcInstructionsStepNumberItem*>(Item);
|
||||
|
||||
if (NumberItem)
|
||||
{
|
||||
if (!Model || (NumberItem->GetModel() == Model && NumberItem->GetStep() == Step))
|
||||
NumberItem->Update();
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
lcInstructionsPartsListItem* PartsItem = dynamic_cast<lcInstructionsPartsListItem*>(Item);
|
||||
|
||||
if (PartsItem)
|
||||
{
|
||||
if (!Model || (PartsItem->GetModel() == Model && PartsItem->GetStep() == Step))
|
||||
PartsItem->Update();
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void lcInstructionsPageWidget::SelectionChanged()
|
||||
{
|
||||
QGraphicsScene* Scene = qobject_cast<QGraphicsScene*>(sender());
|
||||
QGraphicsItem* Focus = nullptr;
|
||||
|
||||
if (Scene)
|
||||
{
|
||||
QList<QGraphicsItem*> SelectedItems = Scene->selectedItems();
|
||||
|
||||
if (!SelectedItems.isEmpty())
|
||||
Focus = SelectedItems.first();
|
||||
}
|
||||
|
||||
mPropertiesWidget->SelectionChanged(Focus);
|
||||
}
|
||||
|
||||
void lcInstructionsPageWidget::SetCurrentPage(const lcInstructionsPage* Page)
|
||||
{
|
||||
QGraphicsScene* Scene = scene();
|
||||
|
||||
Scene->clear();
|
||||
|
||||
if (!Page)
|
||||
return;
|
||||
|
||||
const lcInstructionsPageSetup& PageSetup = mInstructions->mPageSetup;
|
||||
// Scene->setSceneRect(0, 0, mInstructions->mPageSetup.Width, mInstructions->mPageSetup.Height);
|
||||
|
||||
QGraphicsRectItem* PageItem = Scene->addRect(QRectF(0.0f, 0.0f, PageSetup.Width, PageSetup.Height), QPen(Qt::black), QBrush(Qt::white));
|
||||
PageItem->setFlag(QGraphicsItem::ItemClipsChildrenToShape, true);
|
||||
|
||||
QRectF MarginsRect(PageSetup.MarginLeft, PageSetup.MarginTop, PageSetup.Width - PageSetup.MarginLeft - PageSetup.MarginRight, PageSetup.Height - PageSetup.MarginTop - PageSetup.MarginBottom);
|
||||
|
||||
for (const lcInstructionsStep& Step : Page->Steps)
|
||||
{
|
||||
lcInstructionsStepImageItem* StepImageItem = new lcInstructionsStepImageItem(PageItem, mInstructions, Step.Model, Step.Step);
|
||||
StepImageItem->setPos(MarginsRect.left() + MarginsRect.width() * Step.Rect.x(), MarginsRect.top() + MarginsRect.height() * Step.Rect.y());
|
||||
StepImageItem->SetImageSize(MarginsRect.width() * Step.Rect.width(), MarginsRect.height() * Step.Rect.height());
|
||||
StepImageItem->Update();
|
||||
|
||||
lcInstructionsStepNumberItem* StepNumberItem = new lcInstructionsStepNumberItem(StepImageItem, mInstructions, Step.Model, Step.Step);
|
||||
StepNumberItem->Update();
|
||||
|
||||
lcInstructionsPartsListItem* PartsImageItem = new lcInstructionsPartsListItem(StepImageItem, mInstructions, Step.Model, Step.Step);
|
||||
PartsImageItem->setPos(StepNumberItem->boundingRect().topRight());
|
||||
PartsImageItem->Update();
|
||||
}
|
||||
}
|
||||
|
||||
lcInstructionsPageListWidget::lcInstructionsPageListWidget(QWidget* Parent, lcInstructions* Instructions)
|
||||
: QDockWidget(Parent), mInstructions(Instructions)
|
||||
{
|
||||
QWidget* CentralWidget = new QWidget(this);
|
||||
setWidget(CentralWidget);
|
||||
setWindowTitle(tr("Pages"));
|
||||
|
||||
QVBoxLayout* Layout = new QVBoxLayout(CentralWidget);
|
||||
Layout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
QHBoxLayout* ButtonsLayout = new QHBoxLayout();
|
||||
ButtonsLayout->setContentsMargins(0, 0, 0, 0);
|
||||
Layout->addLayout(ButtonsLayout);
|
||||
|
||||
QToolButton* PageSetupButton = new QToolButton();
|
||||
PageSetupButton->setText("Page Setup");
|
||||
ButtonsLayout->addWidget(PageSetupButton);
|
||||
|
||||
connect(PageSetupButton, SIGNAL(clicked()), this, SLOT(ShowPageSetupDialog()));
|
||||
|
||||
ButtonsLayout->addStretch(1);
|
||||
|
||||
/*
|
||||
lcCollapsibleWidget* SetupWidget = new lcCollapsibleWidget(tr("Page Setup"), CentralWidget);
|
||||
Layout->addWidget(SetupWidget);
|
||||
|
||||
// QVBoxLayout* SetupLayout = new QVBoxLayout();
|
||||
// SetupWidget->SetChildLayout(SetupLayout);
|
||||
|
||||
QGridLayout* SetupLayout = new QGridLayout();
|
||||
SetupWidget->SetChildLayout(SetupLayout);
|
||||
|
||||
// lcCollapsibleWidget* SizeWidget = new lcCollapsibleWidget(tr("Size"));
|
||||
QGroupBox* SizeWidget = new QGroupBox(tr("Size"));
|
||||
|
||||
SetupLayout->addWidget(SizeWidget);
|
||||
|
||||
QGridLayout* SizeLayout = new QGridLayout();
|
||||
// SizeWidget->SetChildLayout(SizeLayout);
|
||||
SizeWidget->setLayout(SizeLayout);
|
||||
|
||||
mWidthEdit = new lcSmallLineEdit();
|
||||
SizeLayout->addWidget(new QLabel(tr("Width:")), 1, 0);
|
||||
SizeLayout->addWidget(mWidthEdit, 1, 1);
|
||||
|
||||
mHeightEdit = new lcSmallLineEdit();
|
||||
SizeLayout->addWidget(new QLabel(tr("Height:")), 1, 2);
|
||||
SizeLayout->addWidget(mHeightEdit, 1, 3);
|
||||
|
||||
mUnitsComboBox = new QComboBox();
|
||||
mUnitsComboBox->addItems(QStringList() << tr("Pixels") << tr("Centimeters") << tr("Inches"));
|
||||
SizeLayout->addWidget(new QLabel(tr("Units:")), 4, 0);
|
||||
SizeLayout->addWidget(mUnitsComboBox, 4, 1, 1, -1);
|
||||
|
||||
mSizeComboBox = new QComboBox();
|
||||
SizeLayout->addWidget(new QLabel(tr("Preset:")), 5, 0);
|
||||
SizeLayout->addWidget(mSizeComboBox, 5, 1, 1, -1);
|
||||
|
||||
|
||||
// lcCollapsibleWidget* OrientationWidget = new lcCollapsibleWidget(tr("Orientation"));
|
||||
// SetupLayout->addWidget(OrientationWidget);
|
||||
//
|
||||
// QVBoxLayout* OrientationLayout = new QVBoxLayout();
|
||||
// OrientationWidget->SetChildLayout(OrientationLayout);
|
||||
//
|
||||
// mPortraitButton = new QRadioButton(tr("Portrait"));
|
||||
// OrientationLayout->addWidget(mPortraitButton);
|
||||
// mLandscapeButton = new QRadioButton(tr("Landscape"));
|
||||
// OrientationLayout->addWidget(mLandscapeButton);
|
||||
|
||||
QGroupBox* MarginsWidget = new QGroupBox(tr("Margins"));
|
||||
// lcCollapsibleWidget* MarginsWidget = new lcCollapsibleWidget(tr("Margins"));
|
||||
SetupLayout->addWidget(MarginsWidget);
|
||||
|
||||
QGridLayout* MarginsLayout = new QGridLayout();
|
||||
// MarginsWidget->SetChildLayout(MarginsLayout);
|
||||
MarginsWidget->setLayout(MarginsLayout);
|
||||
|
||||
mLeftMarginEdit = new lcSmallLineEdit();
|
||||
MarginsLayout->addWidget(new QLabel(tr("Left:")), 2, 0);
|
||||
MarginsLayout->addWidget(mLeftMarginEdit, 2, 1);
|
||||
|
||||
mRightMarginEdit = new lcSmallLineEdit();
|
||||
MarginsLayout->addWidget(new QLabel(tr("Right:")), 2, 2);
|
||||
MarginsLayout->addWidget(mRightMarginEdit, 2, 3);
|
||||
|
||||
mTopMarginEdit = new lcSmallLineEdit();
|
||||
MarginsLayout->addWidget(new QLabel(tr("Top:")), 3, 0);
|
||||
MarginsLayout->addWidget(mTopMarginEdit, 3, 1);
|
||||
|
||||
mBottomMarginEdit = new lcSmallLineEdit();
|
||||
MarginsLayout->addWidget(new QLabel(tr("Bottom:")), 3, 2);
|
||||
MarginsLayout->addWidget(mBottomMarginEdit, 3, 3);
|
||||
|
||||
// lcCollapsibleWidget* UnitsWidget = new lcCollapsibleWidget(tr("Units"));
|
||||
// SetupLayout->addWidget(UnitsWidget);
|
||||
//
|
||||
// QVBoxLayout* UnitsLayout = new QVBoxLayout();
|
||||
// UnitsWidget->SetChildLayout(UnitsLayout);
|
||||
|
||||
// SetupWidget->Collapse();
|
||||
*/
|
||||
mThumbnailsWidget = new QListWidget(CentralWidget);
|
||||
Layout->addWidget(mThumbnailsWidget);
|
||||
}
|
||||
|
||||
void lcInstructionsPageListWidget::ShowPageSetupDialog()
|
||||
{
|
||||
lcPageSetupDialog Dialog(this, &mInstructions->mPageSetup);
|
||||
|
||||
if (Dialog.exec() != QDialog::Accepted)
|
||||
return;
|
||||
}
|
||||
|
||||
lcInstructionsPropertiesWidget::lcInstructionsPropertiesWidget(QWidget* Parent, lcInstructions* Instructions)
|
||||
: QDockWidget(Parent), mInstructions(Instructions)
|
||||
{
|
||||
QWidget* CentralWidget = new QWidget(this);
|
||||
setWidget(CentralWidget);
|
||||
setWindowTitle(tr("Properties"));
|
||||
|
||||
QGridLayout* Layout = new QGridLayout(CentralWidget);
|
||||
Layout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
QComboBox* ScopeComboBox = new QComboBox(CentralWidget);
|
||||
ScopeComboBox->addItems(QStringList() << tr("Default") << tr("Current Model") << tr("Current Step Only") << tr("Current Step Forward"));
|
||||
|
||||
Layout->addWidget(new QLabel(tr("Scope:")), 0, 0);
|
||||
Layout->addWidget(ScopeComboBox, 0, 1);
|
||||
|
||||
QComboBox* PresetComboBox = new QComboBox(CentralWidget);
|
||||
|
||||
Layout->addWidget(new QLabel(tr("Preset:")), 1, 0);
|
||||
Layout->addWidget(PresetComboBox, 1, 1);
|
||||
|
||||
Layout->setRowStretch(3, 1);
|
||||
}
|
||||
|
||||
void lcInstructionsPropertiesWidget::AddBoolProperty(lcInstructionsPropertyType Type)
|
||||
{
|
||||
const QString Label = mInstructions->GetPropertyLabel(Type);
|
||||
const int Row = mPropertiesLayout->rowCount();
|
||||
|
||||
QCheckBox* CheckBox = new QCheckBox(Label);
|
||||
mPropertiesLayout->addWidget(CheckBox, Row, 0, 1, -1);
|
||||
|
||||
bool Enabled = mInstructions->GetBoolProperty(Type, mModel, mStep);
|
||||
CheckBox->setChecked(Enabled);
|
||||
|
||||
connect(CheckBox, &QToolButton::toggled, [this, Type](bool Checked)
|
||||
{
|
||||
mInstructions->SetDefaultBool(Type, Checked);
|
||||
} );
|
||||
}
|
||||
|
||||
void lcInstructionsPropertiesWidget::AddColorProperty(lcInstructionsPropertyType Type)
|
||||
{
|
||||
const QString Label = mInstructions->GetPropertyLabel(Type);
|
||||
const int Row = mPropertiesLayout->rowCount();
|
||||
|
||||
mPropertiesLayout->addWidget(new QLabel(Label), Row, 0);
|
||||
|
||||
QToolButton* ColorButton = new QToolButton();
|
||||
mPropertiesLayout->addWidget(ColorButton, Row, 1);
|
||||
|
||||
auto UpdateButton = [this, Type, ColorButton]()
|
||||
{
|
||||
QPixmap Pixmap(12, 12);
|
||||
QColor Color = mInstructions->GetColorProperty(Type, mModel, mStep);
|
||||
Pixmap.fill(Color);
|
||||
ColorButton->setIcon(Pixmap);
|
||||
};
|
||||
|
||||
UpdateButton();
|
||||
|
||||
connect(ColorButton, &QToolButton::clicked, [this, Type, UpdateButton]()
|
||||
{
|
||||
QString Title;
|
||||
|
||||
switch (Type)
|
||||
{
|
||||
case lcInstructionsPropertyType::StepNumberColor:
|
||||
Title = tr("Select Step Number Color");
|
||||
break;
|
||||
|
||||
case lcInstructionsPropertyType::StepBackgroundColor:
|
||||
Title = tr("Select Step Background Color");
|
||||
break;
|
||||
|
||||
case lcInstructionsPropertyType::PLIBackgroundColor:
|
||||
Title = tr("Select Parts List Background Color");
|
||||
break;
|
||||
|
||||
case lcInstructionsPropertyType::PLIBorderColor:
|
||||
Title = tr("Select Parts List Border Color");
|
||||
break;
|
||||
|
||||
case lcInstructionsPropertyType::PLITextColor:
|
||||
Title = tr("Select Parts List Text Color");
|
||||
break;
|
||||
|
||||
case lcInstructionsPropertyType::ShowStepNumber:
|
||||
case lcInstructionsPropertyType::ShowStepPLI:
|
||||
case lcInstructionsPropertyType::StepNumberFont:
|
||||
case lcInstructionsPropertyType::PLIFont:
|
||||
// case lcInstructionsPropertyType::StepPLIBorderWidth:
|
||||
// case lcInstructionsPropertyType::StepPLIBorderRound:
|
||||
case lcInstructionsPropertyType::Count:
|
||||
break;
|
||||
}
|
||||
|
||||
QColor Color = mInstructions->GetColorProperty(Type, mModel, mStep);
|
||||
Color = QColorDialog::getColor(Color, this, Title);
|
||||
|
||||
if (Color.isValid())
|
||||
{
|
||||
mInstructions->SetDefaultColor(Type, Color);
|
||||
UpdateButton();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void lcInstructionsPropertiesWidget::AddFontProperty(lcInstructionsPropertyType Type)
|
||||
{
|
||||
const QString Label = mInstructions->GetPropertyLabel(Type);
|
||||
const int Row = mPropertiesLayout->rowCount();
|
||||
|
||||
mPropertiesLayout->addWidget(new QLabel(Label), Row, 0);
|
||||
|
||||
QToolButton* FontButton = new QToolButton();
|
||||
mPropertiesLayout->addWidget(FontButton, Row, 1);
|
||||
|
||||
auto UpdateButton = [this, Type, FontButton]()
|
||||
{
|
||||
QFont Font = mInstructions->GetFontProperty(Type, mModel, mStep);
|
||||
QString FontName = QString("%1 %2").arg(Font.family(), QString::number(Font.pointSize()));
|
||||
FontButton->setText(FontName);
|
||||
};
|
||||
|
||||
UpdateButton();
|
||||
|
||||
connect(FontButton, &QToolButton::clicked, [this, Type, UpdateButton]()
|
||||
{
|
||||
QString Title;
|
||||
|
||||
switch (Type)
|
||||
{
|
||||
case lcInstructionsPropertyType::StepNumberFont:
|
||||
Title = tr("Select Step Number Font");
|
||||
break;
|
||||
|
||||
case lcInstructionsPropertyType::PLIFont:
|
||||
Title = tr("Select Parts List Font");
|
||||
break;
|
||||
|
||||
case lcInstructionsPropertyType::ShowStepNumber:
|
||||
case lcInstructionsPropertyType::ShowStepPLI:
|
||||
case lcInstructionsPropertyType::StepNumberColor:
|
||||
case lcInstructionsPropertyType::StepBackgroundColor:
|
||||
case lcInstructionsPropertyType::PLIBackgroundColor:
|
||||
case lcInstructionsPropertyType::PLITextColor:
|
||||
case lcInstructionsPropertyType::PLIBorderColor:
|
||||
case lcInstructionsPropertyType::Count:
|
||||
break;
|
||||
}
|
||||
|
||||
bool Ok = false;
|
||||
|
||||
QFont Font = mInstructions->GetFontProperty(Type, mModel, mStep);
|
||||
Font = QFontDialog::getFont(&Ok, Font, this, tr("Select Step Number Font"));
|
||||
|
||||
if (Ok)
|
||||
{
|
||||
UpdateButton();
|
||||
mInstructions->SetDefaultFont(Type, Font);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void lcInstructionsPropertiesWidget::SelectionChanged(QGraphicsItem* FocusItem)
|
||||
{
|
||||
if (mFocusItem == FocusItem)
|
||||
return;
|
||||
|
||||
delete mWidget;
|
||||
mWidget = nullptr;
|
||||
mFocusItem = FocusItem;
|
||||
mModel = nullptr;
|
||||
mStep = 1;
|
||||
|
||||
if (!FocusItem)
|
||||
return;
|
||||
|
||||
auto CreatePropertyWidget = [this](const QString& Title)
|
||||
{
|
||||
mWidget = new lcCollapsibleWidget(Title); // todo: disable collapse
|
||||
|
||||
QGridLayout* WidgetLayout = qobject_cast<QGridLayout*>(widget()->layout());
|
||||
WidgetLayout->addWidget(mWidget, 2, 0, 1, -1);
|
||||
|
||||
mPropertiesLayout = new QGridLayout();
|
||||
mWidget->SetChildLayout(mPropertiesLayout);
|
||||
};
|
||||
|
||||
lcInstructionsStepImageItem* ImageItem = dynamic_cast<lcInstructionsStepImageItem*>(FocusItem);
|
||||
|
||||
if (ImageItem)
|
||||
{
|
||||
CreatePropertyWidget(tr("Step Properties"));
|
||||
|
||||
mModel = ImageItem->GetModel();
|
||||
mStep = ImageItem->GetStep();
|
||||
|
||||
AddBoolProperty(lcInstructionsPropertyType::ShowStepNumber);
|
||||
AddBoolProperty(lcInstructionsPropertyType::ShowStepPLI);
|
||||
AddColorProperty(lcInstructionsPropertyType::StepBackgroundColor);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
lcInstructionsStepNumberItem* NumberItem = dynamic_cast<lcInstructionsStepNumberItem*>(FocusItem);
|
||||
|
||||
if (NumberItem)
|
||||
{
|
||||
CreatePropertyWidget(tr("Step Number Properties"));
|
||||
|
||||
mModel = NumberItem->GetModel();
|
||||
mStep = NumberItem->GetStep();
|
||||
|
||||
AddFontProperty(lcInstructionsPropertyType::StepNumberFont);
|
||||
AddColorProperty(lcInstructionsPropertyType::StepNumberColor);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
lcInstructionsPartsListItem* PartsItem = dynamic_cast<lcInstructionsPartsListItem*>(FocusItem);
|
||||
|
||||
if (PartsItem)
|
||||
{
|
||||
CreatePropertyWidget(tr("Parts List Properties"));
|
||||
|
||||
mModel = PartsItem->GetModel();
|
||||
mStep = PartsItem->GetStep();
|
||||
|
||||
AddColorProperty(lcInstructionsPropertyType::PLIBackgroundColor);
|
||||
AddFontProperty(lcInstructionsPropertyType::PLIFont);
|
||||
AddColorProperty(lcInstructionsPropertyType::PLITextColor);
|
||||
AddColorProperty(lcInstructionsPropertyType::PLIBorderColor);
|
||||
// PLIBorderWidth,
|
||||
// PLIBorderRound,
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
lcInstructionsDialog::lcInstructionsDialog(QWidget* Parent, Project* Project)
|
||||
: QMainWindow(Parent), mProject(Project)
|
||||
{
|
||||
setWindowTitle(tr("Instructions"));
|
||||
|
||||
mInstructions = mProject->GetInstructions();
|
||||
|
||||
mPropertiesWidget = new lcInstructionsPropertiesWidget(this, mInstructions);
|
||||
mPropertiesWidget->setObjectName("InstructionsProperties");
|
||||
addDockWidget(Qt::RightDockWidgetArea, mPropertiesWidget);
|
||||
|
||||
mPageWidget = new lcInstructionsPageWidget(this, mInstructions, mPropertiesWidget);
|
||||
setCentralWidget(mPageWidget);
|
||||
|
||||
mPageListWidget = new lcInstructionsPageListWidget(this, mInstructions);
|
||||
mPageListWidget->setObjectName("InstructionsPageList");
|
||||
addDockWidget(Qt::LeftDockWidgetArea, mPageListWidget);
|
||||
|
||||
mPageSettingsToolBar = addToolBar(tr("Page Settings"));
|
||||
mPageSettingsToolBar->setObjectName("PageSettings");
|
||||
mPageSettingsToolBar->setFloatable(false);
|
||||
mPageSettingsToolBar->setMovable(false);
|
||||
|
||||
mVerticalPageAction = mPageSettingsToolBar->addAction("Vertical");
|
||||
mVerticalPageAction->setCheckable(true);
|
||||
mHorizontalPageAction = mPageSettingsToolBar->addAction("Horizontal");
|
||||
mHorizontalPageAction->setCheckable(true);
|
||||
|
||||
mRowsSpinBox = new QSpinBox(mPageSettingsToolBar);
|
||||
mPageSettingsToolBar->addWidget(mRowsSpinBox);
|
||||
|
||||
mColumnsSpinBox = new QSpinBox(mPageSettingsToolBar);
|
||||
mPageSettingsToolBar->addWidget(mColumnsSpinBox);
|
||||
|
||||
QActionGroup* PageDirectionGroup = new QActionGroup(mPageSettingsToolBar);
|
||||
PageDirectionGroup->addAction(mVerticalPageAction);
|
||||
PageDirectionGroup->addAction(mHorizontalPageAction);
|
||||
|
||||
for (size_t PageNumber = 0; PageNumber < mInstructions->mPages.size(); PageNumber++)
|
||||
mPageListWidget->mThumbnailsWidget->addItem(QString("Page %1").arg(PageNumber + 1));
|
||||
|
||||
connect(mPageListWidget->mThumbnailsWidget, SIGNAL(currentRowChanged(int)), this, SLOT(CurrentThumbnailChanged(int)));
|
||||
mPageListWidget->mThumbnailsWidget->setCurrentRow(0);
|
||||
|
||||
connect(mVerticalPageAction, SIGNAL(toggled(bool)), this, SLOT(UpdatePageSettings()));
|
||||
connect(mHorizontalPageAction, SIGNAL(toggled(bool)), this, SLOT(UpdatePageSettings()));
|
||||
connect(mRowsSpinBox, SIGNAL(valueChanged(int)), this, SLOT(UpdatePageSettings()));
|
||||
connect(mColumnsSpinBox, SIGNAL(valueChanged(int)), this, SLOT(UpdatePageSettings()));
|
||||
}
|
||||
|
||||
void lcInstructionsDialog::UpdatePageSettings()
|
||||
{
|
||||
lcInstructionsPageSettings PageSettings;
|
||||
|
||||
PageSettings.Rows = mRowsSpinBox->value();
|
||||
PageSettings.Columns = mColumnsSpinBox->value();
|
||||
|
||||
if (mHorizontalPageAction->isChecked())
|
||||
PageSettings.Direction = lcInstructionsDirection::Horizontal;
|
||||
else
|
||||
PageSettings.Direction = lcInstructionsDirection::Vertical;
|
||||
|
||||
mInstructions->SetDefaultPageSettings(PageSettings);
|
||||
// lcInstructionsPage* Page = &mInstructions.mPages[mThumbnailsWidget->currentIndex().row()];
|
||||
|
||||
mPageListWidget->mThumbnailsWidget->clear();
|
||||
for (size_t PageNumber = 0; PageNumber < mInstructions->mPages.size(); PageNumber++)
|
||||
mPageListWidget->mThumbnailsWidget->addItem(QString("Page %1").arg(PageNumber + 1));
|
||||
|
||||
// mThumbnailsWidget->setCurrentRow(0);
|
||||
|
||||
// mPageWidget->SetCurrentPage(Page);
|
||||
}
|
||||
|
||||
void lcInstructionsDialog::CurrentThumbnailChanged(int Index)
|
||||
{
|
||||
if (Index < 0 || Index >= static_cast<int>(mInstructions->mPages.size()))
|
||||
{
|
||||
mPageWidget->SetCurrentPage(nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
const lcInstructionsPage* Page = &mInstructions->mPages[Index];
|
||||
// const lcInstructionsPageSettings& PageSettings = Page->Settings;
|
||||
const lcInstructionsPageSettings& PageSettings = mInstructions->mPageSettings;
|
||||
|
||||
mPageWidget->SetCurrentPage(Page);
|
||||
|
||||
if (PageSettings.Direction == lcInstructionsDirection::Horizontal)
|
||||
{
|
||||
mHorizontalPageAction->blockSignals(true);
|
||||
mHorizontalPageAction->setChecked(true);
|
||||
mHorizontalPageAction->blockSignals(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
mVerticalPageAction->blockSignals(true);
|
||||
mVerticalPageAction->setChecked(true);
|
||||
mVerticalPageAction->blockSignals(false);
|
||||
}
|
||||
|
||||
mRowsSpinBox->blockSignals(true);
|
||||
mRowsSpinBox->setValue(PageSettings.Rows);
|
||||
mRowsSpinBox->blockSignals(false);
|
||||
|
||||
mColumnsSpinBox->blockSignals(true);
|
||||
mColumnsSpinBox->setValue(PageSettings.Columns);
|
||||
mColumnsSpinBox->blockSignals(false);
|
||||
}
|
182
common/lc_instructionsdialog.h
Normal file
182
common/lc_instructionsdialog.h
Normal file
|
@ -0,0 +1,182 @@
|
|||
#pragma once
|
||||
|
||||
#include "lc_instructions.h"
|
||||
|
||||
class lcInstructionsPropertiesWidget;
|
||||
|
||||
class lcInstructionsStepImageItem : public QGraphicsPixmapItem
|
||||
{
|
||||
public:
|
||||
lcInstructionsStepImageItem(QGraphicsItem* Parent, lcInstructions* Instructions, lcModel* Model, lcStep Step);
|
||||
|
||||
lcModel* GetModel() const
|
||||
{
|
||||
return mModel;
|
||||
}
|
||||
|
||||
lcStep GetStep() const
|
||||
{
|
||||
return mStep;
|
||||
}
|
||||
|
||||
void SetImageSize(int Width, int Height)
|
||||
{
|
||||
mWidth = Width;
|
||||
mHeight = Height;
|
||||
}
|
||||
|
||||
void Update();
|
||||
|
||||
protected:
|
||||
lcInstructions* mInstructions = nullptr;
|
||||
lcModel* mModel = nullptr;
|
||||
lcStep mStep = 1;
|
||||
int mWidth = 1;
|
||||
int mHeight = 1;
|
||||
};
|
||||
|
||||
class lcInstructionsStepNumberItem : public QGraphicsSimpleTextItem
|
||||
{
|
||||
public:
|
||||
lcInstructionsStepNumberItem(QGraphicsItem* Parent, lcInstructions* Instructions, lcModel* Model, lcStep Step);
|
||||
|
||||
lcModel* GetModel() const
|
||||
{
|
||||
return mModel;
|
||||
}
|
||||
|
||||
lcStep GetStep() const
|
||||
{
|
||||
return mStep;
|
||||
}
|
||||
|
||||
void Update();
|
||||
|
||||
protected:
|
||||
lcInstructions* mInstructions = nullptr;
|
||||
lcModel* mModel = nullptr;
|
||||
lcStep mStep = 1;
|
||||
};
|
||||
|
||||
class lcInstructionsPartsListItem : public QGraphicsPixmapItem
|
||||
{
|
||||
public:
|
||||
lcInstructionsPartsListItem(QGraphicsItem* Parent, lcInstructions* Instructions, lcModel* Model, lcStep Step);
|
||||
|
||||
lcModel* GetModel() const
|
||||
{
|
||||
return mModel;
|
||||
}
|
||||
|
||||
lcStep GetStep() const
|
||||
{
|
||||
return mStep;
|
||||
}
|
||||
|
||||
void Update();
|
||||
|
||||
protected:
|
||||
lcInstructions* mInstructions = nullptr;
|
||||
lcModel* mModel = nullptr;
|
||||
lcStep mStep = 1;
|
||||
};
|
||||
|
||||
class lcInstructionsPageWidget : public QGraphicsView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
lcInstructionsPageWidget(QWidget* Parent, lcInstructions* Instructions, lcInstructionsPropertiesWidget* PropertiesWidget);
|
||||
|
||||
void SetCurrentPage(const lcInstructionsPage* Page);
|
||||
|
||||
protected slots:
|
||||
void StepSettingsChanged(lcModel* Model, lcStep Step);
|
||||
void SelectionChanged();
|
||||
|
||||
protected:
|
||||
lcInstructions* mInstructions;
|
||||
lcInstructionsPropertiesWidget* mPropertiesWidget;
|
||||
};
|
||||
|
||||
class lcInstructionsPageListWidget : public QDockWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
lcInstructionsPageListWidget(QWidget* Parent, lcInstructions* Instructions);
|
||||
|
||||
protected slots:
|
||||
void ShowPageSetupDialog();
|
||||
|
||||
public:
|
||||
//protected:
|
||||
// QComboBox* mSizeComboBox = nullptr;
|
||||
// QLineEdit* mWidthEdit = nullptr;
|
||||
// QLineEdit* mHeightEdit = nullptr;
|
||||
//
|
||||
// QRadioButton* mPortraitButton = nullptr;
|
||||
// QRadioButton* mLandscapeButton = nullptr;
|
||||
//
|
||||
// QLineEdit* mLeftMarginEdit = nullptr;
|
||||
// QLineEdit* mRightMarginEdit = nullptr;
|
||||
// QLineEdit* mTopMarginEdit = nullptr;
|
||||
// QLineEdit* mBottomMarginEdit = nullptr;
|
||||
//
|
||||
// QComboBox* mUnitsComboBox = nullptr;
|
||||
|
||||
QListWidget* mThumbnailsWidget = nullptr;
|
||||
|
||||
protected:
|
||||
lcInstructions* mInstructions;
|
||||
};
|
||||
|
||||
class lcInstructionsPropertiesWidget : public QDockWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
lcInstructionsPropertiesWidget(QWidget* Parent, lcInstructions* Instructions);
|
||||
|
||||
void SelectionChanged(QGraphicsItem* FocusItem);
|
||||
|
||||
protected:
|
||||
void AddBoolProperty(lcInstructionsPropertyType Type);
|
||||
void AddColorProperty(lcInstructionsPropertyType Type);
|
||||
void AddFontProperty(lcInstructionsPropertyType Type);
|
||||
|
||||
lcCollapsibleWidget* mWidget = nullptr;
|
||||
QGridLayout* mPropertiesLayout = nullptr;
|
||||
lcInstructions* mInstructions = nullptr;
|
||||
QGraphicsItem* mFocusItem = nullptr;
|
||||
lcModel* mModel = nullptr;
|
||||
lcStep mStep = 1;
|
||||
};
|
||||
|
||||
class lcInstructionsDialog : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
lcInstructionsDialog(QWidget* Parent, Project* Project);
|
||||
|
||||
protected slots:
|
||||
void UpdatePageSettings();
|
||||
void CurrentThumbnailChanged(int Index);
|
||||
|
||||
protected:
|
||||
Project* mProject = nullptr;
|
||||
|
||||
int mCurrentPageNumber;
|
||||
lcInstructions* mInstructions;
|
||||
|
||||
lcInstructionsPageWidget* mPageWidget = nullptr;
|
||||
lcInstructionsPageListWidget* mPageListWidget = nullptr;
|
||||
lcInstructionsPropertiesWidget* mPropertiesWidget = nullptr;
|
||||
|
||||
QToolBar* mPageSettingsToolBar = nullptr;
|
||||
QAction* mVerticalPageAction = nullptr;
|
||||
QAction* mHorizontalPageAction = nullptr;
|
||||
QSpinBox* mRowsSpinBox = nullptr;
|
||||
QSpinBox* mColumnsSpinBox = nullptr;
|
||||
};
|
|
@ -16,9 +16,7 @@
|
|||
#include <ctype.h>
|
||||
#include <locale.h>
|
||||
#include <zlib.h>
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
|
||||
#include <QtConcurrent>
|
||||
#endif
|
||||
|
||||
#if MAX_MEM_LEVEL >= 8
|
||||
# define DEF_MEM_LEVEL 8
|
||||
|
@ -33,23 +31,17 @@
|
|||
lcPiecesLibrary::lcPiecesLibrary()
|
||||
: mLoadMutex(QMutex::Recursive)
|
||||
{
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
|
||||
QStringList cachePathList = QStandardPaths::standardLocations(QStandardPaths::CacheLocation);
|
||||
mCachePath = cachePathList.first();
|
||||
#else
|
||||
mCachePath = QDesktopServices::storageLocation(QDesktopServices::CacheLocation);
|
||||
#endif
|
||||
|
||||
QDir Dir;
|
||||
Dir.mkpath(mCachePath);
|
||||
|
||||
mNumOfficialPieces = 0;
|
||||
mZipFiles[LC_ZIPFILE_OFFICIAL] = nullptr;
|
||||
mZipFiles[LC_ZIPFILE_UNOFFICIAL] = nullptr;
|
||||
mBuffersDirty = false;
|
||||
mHasUnofficial = false;
|
||||
mCancelLoading = false;
|
||||
mStudLogo = lcGetProfileInt(LC_PROFILE_STUD_LOGO);
|
||||
mStudStyle = static_cast<lcStudStyle>(lcGetProfileInt(LC_PROFILE_STUD_STYLE));
|
||||
}
|
||||
|
||||
lcPiecesLibrary::~lcPiecesLibrary()
|
||||
|
@ -68,19 +60,16 @@ void lcPiecesLibrary::Unload()
|
|||
delete PieceIt.second;
|
||||
mPieces.clear();
|
||||
|
||||
for (const auto& PrimitiveIt : mPrimitives)
|
||||
delete PrimitiveIt.second;
|
||||
mPrimitives.clear();
|
||||
mSources.clear();
|
||||
|
||||
for (lcTexture* Texture : mTextures)
|
||||
delete Texture;
|
||||
mTextures.clear();
|
||||
|
||||
mNumOfficialPieces = 0;
|
||||
delete mZipFiles[LC_ZIPFILE_OFFICIAL];
|
||||
mZipFiles[LC_ZIPFILE_OFFICIAL] = nullptr;
|
||||
delete mZipFiles[LC_ZIPFILE_UNOFFICIAL];
|
||||
mZipFiles[LC_ZIPFILE_UNOFFICIAL] = nullptr;
|
||||
|
||||
for (std::unique_ptr<lcZipFile>& ZipFile : mZipFiles)
|
||||
ZipFile.reset();
|
||||
}
|
||||
|
||||
void lcPiecesLibrary::RemoveTemporaryPieces()
|
||||
|
@ -249,29 +238,14 @@ bool lcPiecesLibrary::Load(const QString& LibraryPath, bool ShowProgress)
|
|||
{
|
||||
Unload();
|
||||
|
||||
auto LoadCustomColors = []()
|
||||
if (OpenArchive(LibraryPath, lcZipFileType::Official))
|
||||
{
|
||||
QString CustomColorsPath = lcGetProfileString(LC_PROFILE_COLOR_CONFIG);
|
||||
|
||||
if (CustomColorsPath.isEmpty())
|
||||
return false;
|
||||
|
||||
lcDiskFile ColorFile(CustomColorsPath);
|
||||
return ColorFile.Open(QIODevice::ReadOnly) && lcLoadColorFile(ColorFile);
|
||||
};
|
||||
|
||||
if (OpenArchive(LibraryPath, LC_ZIPFILE_OFFICIAL))
|
||||
{
|
||||
lcMemFile ColorFile;
|
||||
|
||||
if (!LoadCustomColors())
|
||||
if (!mZipFiles[LC_ZIPFILE_OFFICIAL]->ExtractFile("ldraw/ldconfig.ldr", ColorFile) || !lcLoadColorFile(ColorFile))
|
||||
lcLoadDefaultColors();
|
||||
LoadColors();
|
||||
|
||||
mLibraryDir = QFileInfo(LibraryPath).absoluteDir();
|
||||
QString UnofficialFileName = mLibraryDir.absoluteFilePath(QLatin1String("ldrawunf.zip"));
|
||||
|
||||
if (!OpenArchive(UnofficialFileName, LC_ZIPFILE_UNOFFICIAL))
|
||||
if (!OpenArchive(UnofficialFileName, lcZipFileType::Unofficial))
|
||||
UnofficialFileName.clear();
|
||||
|
||||
ReadArchiveDescriptions(LibraryPath, UnofficialFileName);
|
||||
|
@ -281,59 +255,125 @@ bool lcPiecesLibrary::Load(const QString& LibraryPath, bool ShowProgress)
|
|||
mLibraryDir.setPath(LibraryPath);
|
||||
|
||||
if (OpenDirectory(mLibraryDir, ShowProgress))
|
||||
{
|
||||
if (!LoadCustomColors())
|
||||
{
|
||||
lcDiskFile ColorFile(mLibraryDir.absoluteFilePath(QLatin1String("ldconfig.ldr")));
|
||||
|
||||
if (!ColorFile.Open(QIODevice::ReadOnly) || !lcLoadColorFile(ColorFile))
|
||||
{
|
||||
ColorFile.SetFileName(mLibraryDir.absoluteFilePath(QLatin1String("LDConfig.ldr")));
|
||||
|
||||
if (!ColorFile.Open(QIODevice::ReadOnly) || !lcLoadColorFile(ColorFile))
|
||||
lcLoadDefaultColors();
|
||||
}
|
||||
}
|
||||
}
|
||||
LoadColors();
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
UpdateStudStyleSource();
|
||||
lcLoadDefaultCategories();
|
||||
lcSynthInit();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool lcPiecesLibrary::OpenArchive(const QString& FileName, lcZipFileType ZipFileType)
|
||||
void lcPiecesLibrary::LoadColors()
|
||||
{
|
||||
lcDiskFile* File = new lcDiskFile(FileName);
|
||||
QString CustomColorsPath = lcGetProfileString(LC_PROFILE_COLOR_CONFIG);
|
||||
|
||||
if (!File->Open(QIODevice::ReadOnly) || !OpenArchive(File, FileName, ZipFileType))
|
||||
if (!CustomColorsPath.isEmpty())
|
||||
{
|
||||
delete File;
|
||||
return false;
|
||||
lcDiskFile ColorFile(CustomColorsPath);
|
||||
|
||||
if (ColorFile.Open(QIODevice::ReadOnly) && lcLoadColorFile(ColorFile, mStudStyle))
|
||||
{
|
||||
emit ColorsLoaded();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
if (mZipFiles[static_cast<int>(lcZipFileType::Official)])
|
||||
{
|
||||
lcMemFile ColorFile;
|
||||
|
||||
if (!mZipFiles[static_cast<int>(lcZipFileType::Official)]->ExtractFile("ldraw/ldconfig.ldr", ColorFile) || !lcLoadColorFile(ColorFile, mStudStyle))
|
||||
lcLoadDefaultColors(mStudStyle);
|
||||
}
|
||||
else
|
||||
{
|
||||
lcDiskFile ColorFile(mLibraryDir.absoluteFilePath(QLatin1String("ldconfig.ldr")));
|
||||
|
||||
if (!ColorFile.Open(QIODevice::ReadOnly) || !lcLoadColorFile(ColorFile, mStudStyle))
|
||||
{
|
||||
ColorFile.SetFileName(mLibraryDir.absoluteFilePath(QLatin1String("LDConfig.ldr")));
|
||||
|
||||
if (!ColorFile.Open(QIODevice::ReadOnly) || !lcLoadColorFile(ColorFile, mStudStyle))
|
||||
lcLoadDefaultColors(mStudStyle);
|
||||
}
|
||||
}
|
||||
|
||||
emit ColorsLoaded();
|
||||
}
|
||||
|
||||
bool lcPiecesLibrary::OpenArchive(lcFile* File, const QString& FileName, lcZipFileType ZipFileType)
|
||||
bool lcPiecesLibrary::IsStudPrimitive(const char* FileName)
|
||||
{
|
||||
lcZipFile* ZipFile = new lcZipFile();
|
||||
return memcmp(FileName, "STU", 3) == 0;
|
||||
}
|
||||
|
||||
if (!ZipFile->OpenRead(File))
|
||||
bool lcPiecesLibrary::IsStudStylePrimitive(const char* FileName)
|
||||
{
|
||||
constexpr std::array<const char*, 15> StudStylePrimitives =
|
||||
{
|
||||
delete ZipFile;
|
||||
"2-4STUD4.DAT", "STUD.DAT", "STUD2.DAT", "STUD2A.DAT", "STUD3.DAT", "STUD4.DAT", "STUD4A.DAT", "STUD4H.DAT",
|
||||
"8/STUD.DAT", "8/STUD2.DAT", "8/STUD2A.DAT", "8/STUD3.DAT", "8/STUD4.DAT", "8/STUD4A.DAT", "8/STUD4H.DAT"
|
||||
};
|
||||
|
||||
for (const char* StudStylePrimitive : StudStylePrimitives)
|
||||
if (!strcmp(StudStylePrimitive, FileName))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void lcPiecesLibrary::UpdateStudStyleSource()
|
||||
{
|
||||
if (!mSources.empty() && mSources.front()->Type == lcLibrarySourceType::StudStyle)
|
||||
mSources.erase(mSources.begin());
|
||||
|
||||
mZipFiles[static_cast<int>(lcZipFileType::StudStyle)].reset();
|
||||
|
||||
if (mStudStyle == lcStudStyle::Plain)
|
||||
return;
|
||||
|
||||
const QLatin1String FileNames[] =
|
||||
{
|
||||
QLatin1String(), // Plain
|
||||
QLatin1String(":/resources/studlogo1.zip"), // ThinLinesLogo
|
||||
QLatin1String(":/resources/studlogo2.zip"), // OutlineLogo
|
||||
QLatin1String(":/resources/studlogo3.zip"), // SharpTopLogo
|
||||
QLatin1String(":/resources/studlogo4.zip"), // RoundedTopLogo
|
||||
QLatin1String(":/resources/studlogo5.zip"), // FlattenedLogo
|
||||
QLatin1String(":/resources/studslegostyle1.zip"), // HighContrast
|
||||
QLatin1String(":/resources/studslegostyle2.zip") // HighContrastLogo
|
||||
};
|
||||
|
||||
LC_ARRAY_SIZE_CHECK(FileNames, lcStudStyle::Count);
|
||||
|
||||
std::unique_ptr<lcDiskFile> StudStyleFile(new lcDiskFile(FileNames[static_cast<int>(mStudStyle)]));
|
||||
|
||||
if (StudStyleFile->Open(QIODevice::ReadOnly))
|
||||
OpenArchive(std::move(StudStyleFile), lcZipFileType::StudStyle);
|
||||
}
|
||||
|
||||
bool lcPiecesLibrary::OpenArchive(const QString& FileName, lcZipFileType ZipFileType)
|
||||
{
|
||||
std::unique_ptr<lcDiskFile> File(new lcDiskFile(FileName));
|
||||
|
||||
if (!File->Open(QIODevice::ReadOnly))
|
||||
return false;
|
||||
}
|
||||
|
||||
mZipFiles[ZipFileType] = ZipFile;
|
||||
return OpenArchive(std::move(File), ZipFileType);
|
||||
}
|
||||
|
||||
if (ZipFileType == LC_ZIPFILE_OFFICIAL)
|
||||
mLibraryFileName = FileName;
|
||||
else
|
||||
mUnofficialFileName = FileName;
|
||||
bool lcPiecesLibrary::OpenArchive(std::unique_ptr<lcFile> File, lcZipFileType ZipFileType)
|
||||
{
|
||||
std::unique_ptr<lcZipFile> ZipFile(new lcZipFile());
|
||||
|
||||
if (!ZipFile->OpenRead(std::move(File)))
|
||||
return false;
|
||||
|
||||
std::unique_ptr<lcLibrarySource> Source(new lcLibrarySource);
|
||||
Source->Type = ZipFileType != lcZipFileType::StudStyle ? lcLibrarySourceType::Library : lcLibrarySourceType::StudStyle;
|
||||
|
||||
for (int FileIdx = 0; FileIdx < ZipFile->mFiles.GetSize(); FileIdx++)
|
||||
{
|
||||
|
@ -366,14 +406,14 @@ bool lcPiecesLibrary::OpenArchive(lcFile* File, const QString& FileName, lcZipFi
|
|||
{
|
||||
if (!memcmp(Dst, ".PNG", 4))
|
||||
{
|
||||
if ((ZipFileType == LC_ZIPFILE_OFFICIAL && !memcmp(Name, "LDRAW/PARTS/TEXTURES/", 21)) ||
|
||||
(ZipFileType == LC_ZIPFILE_UNOFFICIAL && !memcmp(Name, "PARTS/TEXTURES/", 15)))
|
||||
if ((ZipFileType == lcZipFileType::Official && !memcmp(Name, "LDRAW/PARTS/TEXTURES/", 21)) ||
|
||||
(ZipFileType == lcZipFileType::Unofficial && !memcmp(Name, "PARTS/TEXTURES/", 15)))
|
||||
{
|
||||
lcTexture* Texture = new lcTexture();
|
||||
mTextures.push_back(Texture);
|
||||
|
||||
*Dst = 0;
|
||||
strncpy(Texture->mName, Name + (ZipFileType == LC_ZIPFILE_OFFICIAL ? 21 : 15), sizeof(Texture->mName));
|
||||
strncpy(Texture->mName, Name + (ZipFileType == lcZipFileType::Official ? 21 : 15), sizeof(Texture->mName)-1);
|
||||
Texture->mName[sizeof(Texture->mName) - 1] = 0;
|
||||
}
|
||||
}
|
||||
|
@ -381,7 +421,7 @@ bool lcPiecesLibrary::OpenArchive(lcFile* File, const QString& FileName, lcZipFi
|
|||
continue;
|
||||
}
|
||||
|
||||
if (ZipFileType == LC_ZIPFILE_OFFICIAL)
|
||||
if (ZipFileType == lcZipFileType::Official)
|
||||
{
|
||||
if (memcmp(Name, "LDRAW/", 6))
|
||||
continue;
|
||||
|
@ -401,7 +441,7 @@ bool lcPiecesLibrary::OpenArchive(lcFile* File, const QString& FileName, lcZipFi
|
|||
{
|
||||
Info = new PieceInfo();
|
||||
|
||||
strncpy(Info->mFileName, FileInfo.file_name + (Name - NameBuffer), sizeof(Info->mFileName));
|
||||
strncpy(Info->mFileName, FileInfo.file_name + (Name - NameBuffer), sizeof(Info->mFileName)-1);
|
||||
Info->mFileName[sizeof(Info->mFileName) - 1] = 0;
|
||||
|
||||
mPieces[Name] = Info;
|
||||
|
@ -410,28 +450,19 @@ bool lcPiecesLibrary::OpenArchive(lcFile* File, const QString& FileName, lcZipFi
|
|||
Info->SetZipFile(ZipFileType, FileIdx);
|
||||
}
|
||||
else
|
||||
{
|
||||
lcLibraryPrimitive* Primitive = FindPrimitive(Name);
|
||||
|
||||
if (!Primitive)
|
||||
mPrimitives[Name] = new lcLibraryPrimitive(QString(), FileInfo.file_name + (Name - NameBuffer), ZipFileType, FileIdx, false, true);
|
||||
else
|
||||
Primitive->SetZipFile(ZipFileType, FileIdx);
|
||||
}
|
||||
Source->Primitives[Name] = new lcLibraryPrimitive(QString(), FileInfo.file_name + (Name - NameBuffer), ZipFileType, FileIdx, false, false, true);
|
||||
}
|
||||
else if (!memcmp(Name, "P/", 2))
|
||||
{
|
||||
Name += 2;
|
||||
|
||||
lcLibraryPrimitive* Primitive = FindPrimitive(Name);
|
||||
|
||||
if (!Primitive)
|
||||
mPrimitives[Name] = new lcLibraryPrimitive(QString(), FileInfo.file_name + (Name - NameBuffer), ZipFileType, FileIdx, (memcmp(Name, "STU", 3) == 0), false);
|
||||
else
|
||||
Primitive->SetZipFile(ZipFileType, FileIdx);
|
||||
Source->Primitives[Name] = new lcLibraryPrimitive(QString(), FileInfo.file_name + (Name - NameBuffer), ZipFileType, FileIdx, IsStudPrimitive(Name), IsStudStylePrimitive(Name), false);
|
||||
}
|
||||
}
|
||||
|
||||
mZipFiles[static_cast<int>(ZipFileType)] = std::move(ZipFile);
|
||||
mSources.insert(mSources.begin(), std::move(Source));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -441,19 +472,12 @@ void lcPiecesLibrary::ReadArchiveDescriptions(const QString& OfficialFileName, c
|
|||
QFileInfo UnofficialInfo(UnofficialFileName);
|
||||
|
||||
mArchiveCheckSum[0] = OfficialInfo.size();
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(4, 7, 0))
|
||||
mArchiveCheckSum[1] = OfficialInfo.lastModified().toMSecsSinceEpoch();
|
||||
#else
|
||||
mArchiveCheckSum[1] = OfficialInfo.lastModified().toTime_t();
|
||||
#endif
|
||||
|
||||
if (!UnofficialFileName.isEmpty())
|
||||
{
|
||||
mArchiveCheckSum[2] = UnofficialInfo.size();
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(4, 7, 0))
|
||||
mArchiveCheckSum[3] = UnofficialInfo.lastModified().toMSecsSinceEpoch();
|
||||
#else
|
||||
mArchiveCheckSum[3] = UnofficialInfo.lastModified().toTime_t();
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -471,7 +495,7 @@ void lcPiecesLibrary::ReadArchiveDescriptions(const QString& OfficialFileName, c
|
|||
{
|
||||
PieceInfo* Info = PieceIt.second;
|
||||
|
||||
mZipFiles[Info->mZipFileType]->ExtractFile(Info->mZipFileIndex, PieceFile, 256);
|
||||
mZipFiles[static_cast<int>(Info->mZipFileType)]->ExtractFile(Info->mZipFileIndex, PieceFile, 256);
|
||||
PieceFile.Seek(0, SEEK_END);
|
||||
PieceFile.WriteU8(0);
|
||||
|
||||
|
@ -517,6 +541,9 @@ bool lcPiecesLibrary::OpenDirectory(const QDir& LibraryDir, bool ShowProgress)
|
|||
|
||||
for (unsigned int BaseFolderIdx = 0; BaseFolderIdx < LC_ARRAY_COUNT(BaseFolders); BaseFolderIdx++)
|
||||
{
|
||||
std::unique_ptr<lcLibrarySource> Source(new lcLibrarySource);
|
||||
Source->Type = lcLibrarySourceType::Library;
|
||||
|
||||
const char* PrimitiveDirectories[] = { "p/", "parts/s/" };
|
||||
bool SubFileDirectories[] = { false, false, true };
|
||||
QDir BaseDir(LibraryDir.absoluteFilePath(QLatin1String(BaseFolders[BaseFolderIdx])));
|
||||
|
@ -562,9 +589,11 @@ bool lcPiecesLibrary::OpenDirectory(const QDir& LibraryDir, bool ShowProgress)
|
|||
mHasUnofficial = true;
|
||||
|
||||
const bool SubFile = SubFileDirectories[DirectoryIdx];
|
||||
mPrimitives[Name] = new lcLibraryPrimitive(std::move(FileName), strchr(FileString, '/') + 1, LC_NUM_ZIPFILES, 0, !SubFile && (memcmp(Name, "STU", 3) == 0), SubFile);
|
||||
Source->Primitives[Name] = new lcLibraryPrimitive(std::move(FileName), strchr(FileString, '/') + 1, lcZipFileType::Count, 0, !SubFile && IsStudPrimitive(Name), IsStudStylePrimitive(Name), SubFile);
|
||||
}
|
||||
}
|
||||
|
||||
mSources.push_back(std::move(Source));
|
||||
}
|
||||
|
||||
for (unsigned int BaseFolderIdx = 0; BaseFolderIdx < LC_ARRAY_COUNT(BaseFolders); BaseFolderIdx++)
|
||||
|
@ -707,11 +736,7 @@ void lcPiecesLibrary::ReadDirectoryDescriptions(const QFileInfoList (&FileLists)
|
|||
const char* Description = FileName + strlen(FileName) + 1;
|
||||
const uint64_t CachedFileTime = *(uint64_t*)(Description + strlen(Description) + 1 + 4 + 1);
|
||||
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(4, 7, 0))
|
||||
quint64 FileTime = FileLists[Info->mFolderType][Info->mFolderIndex].lastModified().toMSecsSinceEpoch();
|
||||
#else
|
||||
quint64 FileTime = FileLists[Info->mFolderType][Info->mFolderIndex].lastModified().toTime_t();
|
||||
#endif
|
||||
|
||||
if (FileTime == CachedFileTime)
|
||||
{
|
||||
|
@ -761,19 +786,11 @@ void lcPiecesLibrary::ReadDirectoryDescriptions(const QFileInfoList (&FileLists)
|
|||
|
||||
while (!LoadFuture.isFinished())
|
||||
{
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 3, 0) || QT_VERSION < QT_VERSION_CHECK(5, 0, 0) )
|
||||
ProgressDialog->setValue(FilesLoaded);
|
||||
#else
|
||||
ProgressDialog->setValue(FilesLoaded.load());
|
||||
#endif
|
||||
QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
|
||||
}
|
||||
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 3, 0) || QT_VERSION < QT_VERSION_CHECK(5, 0, 0) )
|
||||
ProgressDialog->setValue(FilesLoaded);
|
||||
#else
|
||||
ProgressDialog->setValue(FilesLoaded.load());
|
||||
#endif
|
||||
QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
|
||||
|
||||
ProgressDialog->deleteLater();
|
||||
|
@ -808,11 +825,7 @@ void lcPiecesLibrary::ReadDirectoryDescriptions(const QFileInfoList (&FileLists)
|
|||
|
||||
NewIndexFile.WriteU8(Info->mFolderType);
|
||||
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(4, 7, 0))
|
||||
quint64 FileTime = FileLists[Info->mFolderType][Info->mFolderIndex].lastModified().toMSecsSinceEpoch();
|
||||
#else
|
||||
quint64 FileTime = FileLists[Info->mFolderType][Info->mFolderIndex].lastModified().toTime_t();
|
||||
#endif
|
||||
|
||||
NewIndexFile.WriteU64(FileTime);
|
||||
}
|
||||
|
@ -1097,7 +1110,7 @@ bool lcPiecesLibrary::LoadCachePiece(PieceInfo* Info)
|
|||
if (MeshData.ReadBuffer((char*)&Flags, sizeof(Flags)) == 0)
|
||||
return false;
|
||||
|
||||
if (Flags != mStudLogo)
|
||||
if (Flags != static_cast<qint32>(mStudStyle))
|
||||
return false;
|
||||
|
||||
lcMesh* Mesh = new lcMesh;
|
||||
|
@ -1117,7 +1130,7 @@ bool lcPiecesLibrary::SaveCachePiece(PieceInfo* Info)
|
|||
{
|
||||
lcMemFile MeshData;
|
||||
|
||||
const qint32 Flags = mStudLogo;
|
||||
const qint32 Flags = static_cast<qint32>(mStudStyle);
|
||||
if (MeshData.WriteBuffer((char*)&Flags, sizeof(Flags)) == 0)
|
||||
return false;
|
||||
|
||||
|
@ -1226,17 +1239,17 @@ bool lcPiecesLibrary::LoadPieceData(PieceInfo* Info)
|
|||
bool Loaded = false;
|
||||
bool SaveCache = false;
|
||||
|
||||
if (Info->mZipFileType != LC_NUM_ZIPFILES && mZipFiles[Info->mZipFileType])
|
||||
if (Info->mZipFileType != lcZipFileType::Count && mZipFiles[static_cast<int>(Info->mZipFileType)])
|
||||
{
|
||||
if (LoadCachePiece(Info))
|
||||
return true;
|
||||
|
||||
lcMemFile PieceFile;
|
||||
|
||||
if (mZipFiles[Info->mZipFileType]->ExtractFile(Info->mZipFileIndex, PieceFile))
|
||||
if (mZipFiles[static_cast<int>(Info->mZipFileType)]->ExtractFile(Info->mZipFileIndex, PieceFile))
|
||||
Loaded = MeshLoader.LoadMesh(PieceFile, LC_MESHDATA_SHARED);
|
||||
|
||||
SaveCache = Loaded && (Info->mZipFileType == LC_ZIPFILE_OFFICIAL);
|
||||
SaveCache = Loaded && (Info->mZipFileType == lcZipFileType::Official);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1260,25 +1273,34 @@ bool lcPiecesLibrary::LoadPieceData(PieceInfo* Info)
|
|||
}
|
||||
}
|
||||
|
||||
if (!Loaded || mCancelLoading)
|
||||
if (mCancelLoading)
|
||||
return false;
|
||||
|
||||
if (Info)
|
||||
Info->SetMesh(MeshData.CreateMesh());
|
||||
if (Info)
|
||||
{
|
||||
if (Loaded)
|
||||
Info->SetMesh(MeshData.CreateMesh());
|
||||
else
|
||||
{
|
||||
lcMesh* Mesh = new lcMesh;
|
||||
Mesh->CreateBox();
|
||||
Info->SetMesh(Mesh);
|
||||
}
|
||||
}
|
||||
|
||||
if (SaveCache)
|
||||
SaveCachePiece(Info);
|
||||
|
||||
return true;
|
||||
return Loaded;
|
||||
}
|
||||
|
||||
void lcPiecesLibrary::GetPrimitiveFile(lcLibraryPrimitive* Primitive, std::function<void(lcFile& File)> Callback)
|
||||
{
|
||||
if (mZipFiles[LC_ZIPFILE_OFFICIAL])
|
||||
if (mZipFiles[static_cast<int>(lcZipFileType::Official)])
|
||||
{
|
||||
lcMemFile IncludeFile;
|
||||
|
||||
if (mZipFiles[Primitive->mZipFileType]->ExtractFile(Primitive->mZipFileIndex, IncludeFile))
|
||||
if (mZipFiles[static_cast<int>(Primitive->mZipFileType)]->ExtractFile(Primitive->mZipFileIndex, IncludeFile))
|
||||
Callback(IncludeFile);
|
||||
}
|
||||
else
|
||||
|
@ -1298,11 +1320,11 @@ void lcPiecesLibrary::GetPieceFile(const char* PieceName, std::function<void(lcF
|
|||
{
|
||||
PieceInfo* Info = PieceIt->second;
|
||||
|
||||
if (mZipFiles[LC_ZIPFILE_OFFICIAL] && Info->mZipFileType != LC_NUM_ZIPFILES)
|
||||
if (mZipFiles[static_cast<int>(lcZipFileType::Official)] && Info->mZipFileType != lcZipFileType::Count)
|
||||
{
|
||||
lcMemFile IncludeFile;
|
||||
|
||||
if (mZipFiles[Info->mZipFileType]->ExtractFile(Info->mZipFileIndex, IncludeFile))
|
||||
if (mZipFiles[static_cast<int>(Info->mZipFileType)]->ExtractFile(Info->mZipFileIndex, IncludeFile))
|
||||
Callback(IncludeFile);
|
||||
}
|
||||
else
|
||||
|
@ -1333,31 +1355,31 @@ void lcPiecesLibrary::GetPieceFile(const char* PieceName, std::function<void(lcF
|
|||
{
|
||||
bool Found = false;
|
||||
|
||||
if (mZipFiles[LC_ZIPFILE_OFFICIAL])
|
||||
if (mZipFiles[static_cast<int>(lcZipFileType::Official)])
|
||||
{
|
||||
lcMemFile IncludeFile;
|
||||
|
||||
auto LoadIncludeFile = [&IncludeFile, PieceName, this](const char* Folder, int ZipFileIndex)
|
||||
auto LoadIncludeFile = [&IncludeFile, PieceName, this](const char* Folder, lcZipFileType ZipFileType)
|
||||
{
|
||||
char IncludeFileName[LC_MAXPATH];
|
||||
sprintf(IncludeFileName, Folder, PieceName);
|
||||
return mZipFiles[ZipFileIndex]->ExtractFile(IncludeFileName, IncludeFile);
|
||||
return mZipFiles[static_cast<int>(ZipFileType)]->ExtractFile(IncludeFileName, IncludeFile);
|
||||
};
|
||||
|
||||
if (mHasUnofficial)
|
||||
{
|
||||
Found = LoadIncludeFile("parts/%s", LC_ZIPFILE_UNOFFICIAL);
|
||||
Found = LoadIncludeFile("parts/%s", lcZipFileType::Unofficial);
|
||||
|
||||
if (!Found)
|
||||
Found = LoadIncludeFile("p/%s", LC_ZIPFILE_UNOFFICIAL);
|
||||
Found = LoadIncludeFile("p/%s", lcZipFileType::Unofficial);
|
||||
}
|
||||
|
||||
if (!Found)
|
||||
{
|
||||
Found = LoadIncludeFile("ldraw/parts/%s", LC_ZIPFILE_OFFICIAL);
|
||||
Found = LoadIncludeFile("ldraw/parts/%s", lcZipFileType::Official);
|
||||
|
||||
if (!Found)
|
||||
Found = LoadIncludeFile("ldraw/p/%s", LC_ZIPFILE_OFFICIAL);
|
||||
Found = LoadIncludeFile("ldraw/p/%s", lcZipFileType::Official);
|
||||
}
|
||||
|
||||
if (Found)
|
||||
|
@ -1367,18 +1389,16 @@ void lcPiecesLibrary::GetPieceFile(const char* PieceName, std::function<void(lcF
|
|||
{
|
||||
lcDiskFile IncludeFile;
|
||||
|
||||
auto LoadIncludeFile = [&IncludeFile, PieceName, this](const char* Folder)
|
||||
auto LoadIncludeFile = [&IncludeFile, PieceName, this](const QLatin1String& Folder)
|
||||
{
|
||||
char IncludeFileName[LC_MAXPATH];
|
||||
sprintf(IncludeFileName, Folder, PieceName);
|
||||
IncludeFile.SetFileName(mLibraryDir.absoluteFilePath(QLatin1String(IncludeFileName)));
|
||||
const QString IncludeFileName = Folder + PieceName;
|
||||
IncludeFile.SetFileName(mLibraryDir.absoluteFilePath(IncludeFileName));
|
||||
if (IncludeFile.Open(QIODevice::ReadOnly))
|
||||
return true;
|
||||
|
||||
#if defined(Q_OS_MACOS) || defined(Q_OS_LINUX)
|
||||
// todo: instead of using strlwr, search the parts/primitive lists and get the file name from there
|
||||
strlwr(IncludeFileName);
|
||||
IncludeFile.SetFileName(mLibraryDir.absoluteFilePath(QLatin1String(IncludeFileName)));
|
||||
// todo: search the parts/primitive lists and get the file name from there instead of using toLower
|
||||
IncludeFile.SetFileName(mLibraryDir.absoluteFilePath(IncludeFileName.toLower()));
|
||||
return IncludeFile.Open(QIODevice::ReadOnly);
|
||||
#else
|
||||
return false;
|
||||
|
@ -1387,18 +1407,18 @@ void lcPiecesLibrary::GetPieceFile(const char* PieceName, std::function<void(lcF
|
|||
|
||||
if (mHasUnofficial)
|
||||
{
|
||||
Found = LoadIncludeFile("unofficial/parts/%s");
|
||||
Found = LoadIncludeFile(QLatin1String("unofficial/parts/"));
|
||||
|
||||
if (!Found)
|
||||
Found = LoadIncludeFile("unofficial/p/%s");
|
||||
Found = LoadIncludeFile(QLatin1String("unofficial/p/"));
|
||||
}
|
||||
|
||||
if (!Found)
|
||||
{
|
||||
Found = LoadIncludeFile("parts/%s");
|
||||
Found = LoadIncludeFile(QLatin1String("parts/"));
|
||||
|
||||
if (!Found)
|
||||
Found = LoadIncludeFile("p/%s");
|
||||
Found = LoadIncludeFile(QLatin1String("p/"));
|
||||
}
|
||||
|
||||
if (Found)
|
||||
|
@ -1426,7 +1446,7 @@ void lcPiecesLibrary::UpdateBuffers(lcContext* Context)
|
|||
for (const auto& PieceIt : mPieces)
|
||||
{
|
||||
const PieceInfo* const Info = PieceIt.second;
|
||||
lcMesh* Mesh = Info->IsPlaceholder() ? gPlaceholderMesh : Info->GetMesh();
|
||||
lcMesh* Mesh = Info->GetMesh();
|
||||
|
||||
if (!Mesh)
|
||||
continue;
|
||||
|
@ -1488,17 +1508,17 @@ bool lcPiecesLibrary::LoadTexture(lcTexture* Texture)
|
|||
{
|
||||
char FileName[2*LC_MAXPATH];
|
||||
|
||||
if (mZipFiles[LC_ZIPFILE_OFFICIAL])
|
||||
if (mZipFiles[static_cast<int>(lcZipFileType::Official)])
|
||||
{
|
||||
lcMemFile TextureFile;
|
||||
|
||||
sprintf(FileName, "parts/textures/%s.png", Texture->mName);
|
||||
|
||||
if (!mZipFiles[LC_ZIPFILE_UNOFFICIAL] || !mZipFiles[LC_ZIPFILE_UNOFFICIAL]->ExtractFile(FileName, TextureFile))
|
||||
if (!mZipFiles[static_cast<int>(lcZipFileType::Unofficial)] || !mZipFiles[static_cast<int>(lcZipFileType::Unofficial)]->ExtractFile(FileName, TextureFile))
|
||||
{
|
||||
sprintf(FileName, "ldraw/parts/textures/%s.png", Texture->mName);
|
||||
|
||||
if (!mZipFiles[LC_ZIPFILE_OFFICIAL]->ExtractFile(FileName, TextureFile))
|
||||
if (!mZipFiles[static_cast<int>(lcZipFileType::Official)]->ExtractFile(FileName, TextureFile))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1537,17 +1557,32 @@ void lcPiecesLibrary::UploadTextures(lcContext* Context)
|
|||
mTextureUploads.clear();
|
||||
}
|
||||
|
||||
void lcPiecesLibrary::SetStudLogo(int StudLogo, bool Reload)
|
||||
bool lcPiecesLibrary::SupportsStudStyle() const
|
||||
{
|
||||
mStudLogo = StudLogo;
|
||||
return true;
|
||||
}
|
||||
|
||||
void lcPiecesLibrary::SetStudStyle(lcStudStyle StudStyle, bool Reload)
|
||||
{
|
||||
if (mStudStyle == StudStyle)
|
||||
return;
|
||||
|
||||
mStudStyle = StudStyle;
|
||||
|
||||
LoadColors();
|
||||
UpdateStudStyleSource();
|
||||
|
||||
mLoadMutex.lock();
|
||||
|
||||
for (const auto& PrimitiveIt : mPrimitives)
|
||||
for (const std::unique_ptr<lcLibrarySource>& Source : mSources)
|
||||
{
|
||||
lcLibraryPrimitive* Primitive = PrimitiveIt.second;
|
||||
if (Primitive->mMeshData.mHasLogoStud)
|
||||
Primitive->Unload();
|
||||
for (const auto& PrimitiveIt : Source->Primitives)
|
||||
{
|
||||
lcLibraryPrimitive* Primitive = PrimitiveIt.second;
|
||||
|
||||
if (Primitive->mStudStyle || Primitive->mMeshData.mHasStyleStud)
|
||||
Primitive->Unload();
|
||||
}
|
||||
}
|
||||
|
||||
mLoadMutex.unlock();
|
||||
|
@ -1560,7 +1595,7 @@ void lcPiecesLibrary::SetStudLogo(int StudLogo, bool Reload)
|
|||
{
|
||||
PieceInfo* Info = PieceIt.second;
|
||||
|
||||
if (Info->mState == LC_PIECEINFO_LOADED && Info->GetMesh() && Info->GetMesh()->mFlags & lcMeshFlag::HasLogoStud)
|
||||
if (Info->mState == LC_PIECEINFO_LOADED && Info->GetMesh() && Info->GetMesh()->mFlags & lcMeshFlag::HasStyleStud)
|
||||
{
|
||||
Info->Unload();
|
||||
mLoadQueue.append(Info);
|
||||
|
@ -1574,84 +1609,68 @@ void lcPiecesLibrary::SetStudLogo(int StudLogo, bool Reload)
|
|||
}
|
||||
}
|
||||
|
||||
bool lcPiecesLibrary::GetStudLogoFile(lcMemFile& PrimFile, int StudLogo, bool OpenStud)
|
||||
bool lcPiecesLibrary::IsPrimitive(const char* Name) const
|
||||
{
|
||||
// validate logo choice and unofficial lib available
|
||||
if (!StudLogo || (!mZipFiles[LC_ZIPFILE_UNOFFICIAL] && !mHasUnofficial))
|
||||
return false;
|
||||
for (const std::unique_ptr<lcLibrarySource>& Source : mSources)
|
||||
if (Source->Primitives.find(Name) != Source->Primitives.end())
|
||||
return true;
|
||||
|
||||
// construct logo reference line
|
||||
QString Logo = QString("%1").arg(StudLogo);
|
||||
QString LogoRefLine = QString("1 16 0 0 0 1 0 0 0 1 0 0 0 1 ");
|
||||
LogoRefLine += (OpenStud ? QString("stud2-logo%1.dat").arg(StudLogo > 1 ? Logo : ""):
|
||||
QString("stud-logo%1.dat").arg(StudLogo > 1 ? Logo : ""));
|
||||
return false;
|
||||
}
|
||||
|
||||
// construct primitive file
|
||||
QByteArray FileData;
|
||||
QTextStream out(&FileData);
|
||||
out << (OpenStud ? "0 Stud Open" : "0 Stud") << endl;
|
||||
out << (OpenStud ? "0 Name: stud2.dat" : "0 Name: stud.dat") << endl;
|
||||
out << "0 Author: James Jessiman" << endl;
|
||||
out << "0 !LDRAW_ORG Primitive" << endl;
|
||||
out << "0 BFC CERTIFY CCW" << endl;
|
||||
out << LogoRefLine << endl;
|
||||
lcLibraryPrimitive* lcPiecesLibrary::FindPrimitive(const char* Name) const
|
||||
{
|
||||
for (const std::unique_ptr<lcLibrarySource>& Source : mSources)
|
||||
{
|
||||
const auto PrimitiveIt = Source->Primitives.find(Name);
|
||||
|
||||
PrimFile.WriteBuffer(FileData.constData(), size_t(FileData.size()));
|
||||
PrimFile.Seek(0, SEEK_SET);
|
||||
return true;
|
||||
if (PrimitiveIt != Source->Primitives.end())
|
||||
return PrimitiveIt->second;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool lcPiecesLibrary::LoadPrimitive(lcLibraryPrimitive* Primitive)
|
||||
{
|
||||
mLoadMutex.lock();
|
||||
|
||||
if (Primitive->mState == lcPrimitiveState::NOT_LOADED)
|
||||
Primitive->mState = lcPrimitiveState::LOADING;
|
||||
if (Primitive->mState == lcPrimitiveState::NotLoaded)
|
||||
Primitive->mState = lcPrimitiveState::Loading;
|
||||
else
|
||||
{
|
||||
mLoadMutex.unlock();
|
||||
|
||||
while (Primitive->mState == lcPrimitiveState::LOADING)
|
||||
while (Primitive->mState == lcPrimitiveState::Loading)
|
||||
lcSleeper::msleep(5);
|
||||
|
||||
return Primitive->mState == lcPrimitiveState::LOADED;
|
||||
return Primitive->mState == lcPrimitiveState::Loaded;
|
||||
}
|
||||
|
||||
mLoadMutex.unlock();
|
||||
|
||||
lcMeshLoader MeshLoader(Primitive->mMeshData, true, nullptr, false);
|
||||
|
||||
bool SetStudLogo = false;
|
||||
|
||||
if (mZipFiles[LC_ZIPFILE_OFFICIAL])
|
||||
if (mZipFiles[static_cast<int>(lcZipFileType::Official)])
|
||||
{
|
||||
lcLibraryPrimitive* LowPrimitive = nullptr;
|
||||
|
||||
lcMemFile PrimFile;
|
||||
|
||||
if (Primitive->mStud)
|
||||
if (Primitive->mStud && !Primitive->mStudStyle)
|
||||
{
|
||||
const bool OpenStud = !strcmp(Primitive->mName,"stud2.dat");
|
||||
if (OpenStud || !strcmp(Primitive->mName,"stud.dat"))
|
||||
{
|
||||
Primitive->mMeshData.mHasLogoStud = true;
|
||||
|
||||
if (mStudLogo)
|
||||
SetStudLogo = GetStudLogoFile(PrimFile, mStudLogo, OpenStud);
|
||||
}
|
||||
|
||||
if (!SetStudLogo && 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.
|
||||
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);
|
||||
|
||||
LowPrimitive = FindPrimitive(Name);
|
||||
LowPrimitive = FindPrimitive(Name); // todo: low primitives don't work with studlogo, because the low stud gets added as shared
|
||||
}
|
||||
}
|
||||
|
||||
if (!SetStudLogo && !mZipFiles[Primitive->mZipFileType]->ExtractFile(Primitive->mZipFileIndex, PrimFile))
|
||||
if (!mZipFiles[static_cast<int>(Primitive->mZipFileType)]->ExtractFile(Primitive->mZipFileIndex, PrimFile))
|
||||
return false;
|
||||
|
||||
if (!LowPrimitive)
|
||||
|
@ -1664,7 +1683,7 @@ bool lcPiecesLibrary::LoadPrimitive(lcLibraryPrimitive* Primitive)
|
|||
if (!MeshLoader.LoadMesh(PrimFile, LC_MESHDATA_HIGH))
|
||||
return false;
|
||||
|
||||
if (!mZipFiles[LowPrimitive->mZipFileType]->ExtractFile(LowPrimitive->mZipFileIndex, PrimFile))
|
||||
if (!mZipFiles[static_cast<int>(LowPrimitive->mZipFileType)]->ExtractFile(LowPrimitive->mZipFileIndex, PrimFile))
|
||||
return false;
|
||||
|
||||
if (!MeshLoader.LoadMesh(PrimFile, LC_MESHDATA_LOW))
|
||||
|
@ -1673,34 +1692,27 @@ bool lcPiecesLibrary::LoadPrimitive(lcLibraryPrimitive* Primitive)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (Primitive->mStud)
|
||||
{
|
||||
const bool OpenStud = !strcmp(Primitive->mName,"stud2.dat");
|
||||
if (OpenStud || !strcmp(Primitive->mName,"stud.dat"))
|
||||
{
|
||||
Primitive->mMeshData.mHasLogoStud = true;
|
||||
|
||||
if (mStudLogo)
|
||||
{
|
||||
lcMemFile PrimFile;
|
||||
|
||||
if (GetStudLogoFile(PrimFile, mStudLogo, OpenStud))
|
||||
SetStudLogo = MeshLoader.LoadMesh(PrimFile, LC_MESHDATA_SHARED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!SetStudLogo)
|
||||
if (Primitive->mZipFileType == lcZipFileType::Count)
|
||||
{
|
||||
lcDiskFile PrimFile(Primitive->mFileName);
|
||||
|
||||
if (!PrimFile.Open(QIODevice::ReadOnly) || !MeshLoader.LoadMesh(PrimFile, LC_MESHDATA_SHARED)) // todo: LOD like the zip files
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
lcMemFile PrimFile;
|
||||
|
||||
if (!mZipFiles[static_cast<int>(Primitive->mZipFileType)]->ExtractFile(Primitive->mZipFileIndex, PrimFile))
|
||||
return false;
|
||||
|
||||
if (!MeshLoader.LoadMesh(PrimFile, LC_MESHDATA_SHARED))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
mLoadMutex.lock();
|
||||
Primitive->mState = lcPrimitiveState::LOADED;
|
||||
Primitive->mState = lcPrimitiveState::Loaded;
|
||||
mLoadMutex.unlock();
|
||||
|
||||
return true;
|
||||
|
@ -1860,27 +1872,18 @@ std::string lcPiecesLibrary::GetPartId(const PieceInfo* Info) const
|
|||
|
||||
bool lcPiecesLibrary::LoadBuiltinPieces()
|
||||
{
|
||||
QResource Resource(":/resources/library.zip");
|
||||
std::unique_ptr<lcDiskFile> File(new lcDiskFile(":/resources/library.zip"));
|
||||
|
||||
if (!Resource.isValid())
|
||||
if (!File->Open(QIODevice::ReadOnly) || !OpenArchive(std::move(File), lcZipFileType::Official))
|
||||
return false;
|
||||
|
||||
lcMemFile* File = new lcMemFile();
|
||||
File->WriteBuffer(Resource.data(), Resource.size());
|
||||
|
||||
if (!OpenArchive(File, "builtin", LC_ZIPFILE_OFFICIAL))
|
||||
{
|
||||
delete File;
|
||||
return false;
|
||||
}
|
||||
|
||||
lcMemFile PieceFile;
|
||||
|
||||
for (const auto& PieceIt : mPieces)
|
||||
{
|
||||
PieceInfo* Info = PieceIt.second;
|
||||
|
||||
mZipFiles[Info->mZipFileType]->ExtractFile(Info->mZipFileIndex, PieceFile, 256);
|
||||
mZipFiles[static_cast<int>(Info->mZipFileType)]->ExtractFile(Info->mZipFileIndex, PieceFile, 256);
|
||||
PieceFile.Seek(0, SEEK_END);
|
||||
PieceFile.WriteU8(0);
|
||||
|
||||
|
@ -1900,7 +1903,7 @@ bool lcPiecesLibrary::LoadBuiltinPieces()
|
|||
}
|
||||
}
|
||||
|
||||
lcLoadDefaultColors();
|
||||
lcLoadDefaultColors(lcStudStyle::Plain);
|
||||
lcLoadDefaultCategories(true);
|
||||
lcSynthInit();
|
||||
|
||||
|
|
|
@ -10,11 +10,30 @@ class PieceInfo;
|
|||
class lcZipFile;
|
||||
class lcLibraryMeshData;
|
||||
|
||||
enum lcZipFileType
|
||||
enum class lcStudStyle
|
||||
{
|
||||
LC_ZIPFILE_OFFICIAL,
|
||||
LC_ZIPFILE_UNOFFICIAL,
|
||||
LC_NUM_ZIPFILES
|
||||
Plain,
|
||||
ThinLinesLogo,
|
||||
OutlineLogo,
|
||||
SharpTopLogo,
|
||||
RoundedTopLogo,
|
||||
FlattenedLogo,
|
||||
HighContrast,
|
||||
HighContrastLogo,
|
||||
Count
|
||||
};
|
||||
|
||||
inline bool lcIsHighContrast(lcStudStyle StudStyle)
|
||||
{
|
||||
return StudStyle == lcStudStyle::HighContrast || StudStyle == lcStudStyle::HighContrastLogo;
|
||||
}
|
||||
|
||||
enum class lcZipFileType
|
||||
{
|
||||
Official,
|
||||
Unofficial,
|
||||
StudStyle,
|
||||
Count
|
||||
};
|
||||
|
||||
enum lcLibraryFolderType
|
||||
|
@ -26,24 +45,25 @@ enum lcLibraryFolderType
|
|||
|
||||
enum class lcPrimitiveState
|
||||
{
|
||||
NOT_LOADED,
|
||||
LOADING,
|
||||
LOADED
|
||||
NotLoaded,
|
||||
Loading,
|
||||
Loaded
|
||||
};
|
||||
|
||||
class lcLibraryPrimitive
|
||||
{
|
||||
public:
|
||||
explicit lcLibraryPrimitive(QString&& FileName, const char* Name, lcZipFileType ZipFileType, quint32 ZipFileIndex, bool Stud, bool SubFile)
|
||||
explicit lcLibraryPrimitive(QString&& FileName, const char* Name, lcZipFileType ZipFileType, quint32 ZipFileIndex, bool Stud, bool StudStyle, bool SubFile)
|
||||
: mFileName(std::move(FileName))
|
||||
{
|
||||
strncpy(mName, Name, sizeof(mName));
|
||||
strncpy(mName, Name, sizeof(mName)-1);
|
||||
mName[sizeof(mName) - 1] = 0;
|
||||
|
||||
mZipFileType = ZipFileType;
|
||||
mZipFileIndex = ZipFileIndex;
|
||||
mState = lcPrimitiveState::NOT_LOADED;
|
||||
mState = lcPrimitiveState::NotLoaded;
|
||||
mStud = Stud;
|
||||
mStudStyle = StudStyle;
|
||||
mSubFile = SubFile;
|
||||
}
|
||||
|
||||
|
@ -55,7 +75,7 @@ public:
|
|||
|
||||
void Unload()
|
||||
{
|
||||
mState = lcPrimitiveState::NOT_LOADED;
|
||||
mState = lcPrimitiveState::NotLoaded;
|
||||
mMeshData.RemoveAll();
|
||||
}
|
||||
|
||||
|
@ -65,10 +85,29 @@ public:
|
|||
quint32 mZipFileIndex;
|
||||
lcPrimitiveState mState;
|
||||
bool mStud;
|
||||
bool mStudStyle;
|
||||
bool mSubFile;
|
||||
lcLibraryMeshData mMeshData;
|
||||
};
|
||||
|
||||
enum class lcLibrarySourceType
|
||||
{
|
||||
Library,
|
||||
StudStyle
|
||||
};
|
||||
|
||||
struct lcLibrarySource
|
||||
{
|
||||
~lcLibrarySource()
|
||||
{
|
||||
for (const auto& PrimitiveIt : Primitives)
|
||||
delete PrimitiveIt.second;
|
||||
}
|
||||
|
||||
lcLibrarySourceType Type;
|
||||
std::map<std::string, lcLibraryPrimitive*> Primitives;
|
||||
};
|
||||
|
||||
class lcPiecesLibrary : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@ -83,6 +122,7 @@ public:
|
|||
lcPiecesLibrary& operator=(lcPiecesLibrary&&) = delete;
|
||||
|
||||
bool Load(const QString& LibraryPath, bool ShowProgress);
|
||||
void LoadColors();
|
||||
void Unload();
|
||||
void RemoveTemporaryPieces();
|
||||
void RemovePiece(PieceInfo* Info);
|
||||
|
@ -114,29 +154,21 @@ public:
|
|||
void GetPrimitiveFile(lcLibraryPrimitive* Primitive, std::function<void(lcFile& File)> Callback);
|
||||
void GetPieceFile(const char* FileName, std::function<void(lcFile& File)> Callback);
|
||||
|
||||
bool IsPrimitive(const char* Name) const
|
||||
{
|
||||
return mPrimitives.find(Name) != mPrimitives.end();
|
||||
}
|
||||
|
||||
lcLibraryPrimitive* FindPrimitive(const char* Name) const
|
||||
{
|
||||
const auto PrimitiveIt = mPrimitives.find(Name);
|
||||
return PrimitiveIt != mPrimitives.end() ? PrimitiveIt->second : nullptr;
|
||||
}
|
||||
|
||||
bool IsPrimitive(const char* Name) const;
|
||||
lcLibraryPrimitive* FindPrimitive(const char* Name) const;
|
||||
bool LoadPrimitive(lcLibraryPrimitive* Primitive);
|
||||
|
||||
void SetStudLogo(int StudLogo, bool Reload);
|
||||
bool SupportsStudStyle() const;
|
||||
void SetStudStyle(lcStudStyle StudStyle, bool Reload);
|
||||
|
||||
int GetStudLogo() const
|
||||
lcStudStyle GetStudStyle() const
|
||||
{
|
||||
return mStudLogo;
|
||||
return mStudStyle;
|
||||
}
|
||||
|
||||
void SetOfficialPieces()
|
||||
{
|
||||
if (mZipFiles[LC_ZIPFILE_OFFICIAL])
|
||||
if (mZipFiles[static_cast<int>(lcZipFileType::Official)])
|
||||
mNumOfficialPieces = (int)mPieces.size();
|
||||
}
|
||||
|
||||
|
@ -150,7 +182,6 @@ public:
|
|||
void UnloadUnusedParts();
|
||||
|
||||
std::map<std::string, PieceInfo*> mPieces;
|
||||
std::map<std::string, lcLibraryPrimitive*> mPrimitives;
|
||||
int mNumOfficialPieces;
|
||||
|
||||
std::vector<lcTexture*> mTextures;
|
||||
|
@ -163,10 +194,11 @@ public:
|
|||
|
||||
signals:
|
||||
void PartLoaded(PieceInfo* Info);
|
||||
void ColorsLoaded();
|
||||
|
||||
protected:
|
||||
bool OpenArchive(const QString& FileName, lcZipFileType ZipFileType);
|
||||
bool OpenArchive(lcFile* File, const QString& FileName, lcZipFileType ZipFileType);
|
||||
bool OpenArchive(std::unique_ptr<lcFile> File, lcZipFileType ZipFileType);
|
||||
bool OpenDirectory(const QDir& LibraryDir, bool ShowProgress);
|
||||
void ReadArchiveDescriptions(const QString& OfficialFileName, const QString& UnofficialFileName);
|
||||
void ReadDirectoryDescriptions(const QFileInfoList (&FileLists)[LC_NUM_FOLDERTYPES], bool ShowProgress);
|
||||
|
@ -180,7 +212,11 @@ protected:
|
|||
bool ReadDirectoryCacheFile(const QString& FileName, lcMemFile& CacheFile);
|
||||
bool WriteDirectoryCacheFile(const QString& FileName, lcMemFile& CacheFile);
|
||||
|
||||
bool GetStudLogoFile(lcMemFile& PrimFile, int StudLogo, bool OpenStud);
|
||||
static bool IsStudPrimitive(const char* FileName);
|
||||
static bool IsStudStylePrimitive(const char* FileName);
|
||||
void UpdateStudStyleSource();
|
||||
|
||||
std::vector<std::unique_ptr<lcLibrarySource>> mSources;
|
||||
|
||||
QMutex mLoadMutex;
|
||||
QList<QFuture<void>> mLoadFutures;
|
||||
|
@ -189,14 +225,11 @@ protected:
|
|||
QMutex mTextureMutex;
|
||||
std::vector<lcTexture*> mTextureUploads;
|
||||
|
||||
int mStudLogo;
|
||||
lcStudStyle mStudStyle;
|
||||
|
||||
QString mCachePath;
|
||||
qint64 mArchiveCheckSum[4];
|
||||
QString mLibraryFileName;
|
||||
QString mUnofficialFileName;
|
||||
lcZipFile* mZipFiles[LC_NUM_ZIPFILES];
|
||||
std::unique_ptr<lcZipFile> mZipFiles[static_cast<int>(lcZipFileType::Count)];
|
||||
bool mHasUnofficial;
|
||||
bool mCancelLoading;
|
||||
};
|
||||
|
||||
|
|
|
@ -16,15 +16,10 @@ static bool lcLoadLDrawXML(std::map<int, int>& MaterialTable, std::map<int, std:
|
|||
Data = File.readAll();
|
||||
else
|
||||
{
|
||||
QResource Resource(":/resources/ldraw.xml");
|
||||
QFile DefaultFile(":/resources/ldraw.xml");
|
||||
|
||||
if (Resource.isValid())
|
||||
{
|
||||
if (Resource.isCompressed())
|
||||
Data = qUncompress(Resource.data(), Resource.size());
|
||||
else
|
||||
Data = QByteArray::fromRawData((const char*)Resource.data(), Resource.size());
|
||||
}
|
||||
if (DefaultFile.open(QIODevice::ReadOnly))
|
||||
Data = DefaultFile.readAll();
|
||||
}
|
||||
|
||||
if (Data.isEmpty())
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,14 +1,14 @@
|
|||
#pragma once
|
||||
|
||||
#include "lc_basewindow.h"
|
||||
#include "lc_application.h"
|
||||
#include "lc_shortcuts.h"
|
||||
#include "lc_array.h"
|
||||
#include "lc_commands.h"
|
||||
#include "lc_model.h"
|
||||
|
||||
class View;
|
||||
class lcPartSelectionWidget;
|
||||
class lcPreviewDockWidget;
|
||||
class PiecePreview;
|
||||
class lcQGLWidget;
|
||||
class lcQPartsTree;
|
||||
class lcQColorList;
|
||||
class lcQPropertiesTree;
|
||||
|
@ -20,17 +20,6 @@ class QPrinter;
|
|||
|
||||
#define LC_MAX_RECENT_FILES 4
|
||||
|
||||
struct lcSearchOptions
|
||||
{
|
||||
bool SearchValid;
|
||||
bool MatchInfo;
|
||||
bool MatchColor;
|
||||
bool MatchName;
|
||||
PieceInfo* Info;
|
||||
int ColorIndex;
|
||||
char Name[256];
|
||||
};
|
||||
|
||||
class lcTabBar : public QTabBar
|
||||
{
|
||||
public:
|
||||
|
@ -46,19 +35,6 @@ protected:
|
|||
int mMousePressTab;
|
||||
};
|
||||
|
||||
class lcTabWidget : public QTabWidget
|
||||
{
|
||||
public:
|
||||
lcTabWidget();
|
||||
|
||||
#if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
|
||||
QTabBar* tabBar()
|
||||
{
|
||||
return QTabWidget::tabBar();
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
class lcModelTabWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@ -83,22 +59,22 @@ public:
|
|||
return Widget;
|
||||
}
|
||||
|
||||
View* GetActiveView() const
|
||||
lcView* GetActiveView() const
|
||||
{
|
||||
return mActiveView;
|
||||
}
|
||||
|
||||
void SetActiveView(View* ActiveView)
|
||||
void SetActiveView(lcView* ActiveView)
|
||||
{
|
||||
mActiveView = ActiveView;
|
||||
}
|
||||
|
||||
void AddView(View* View)
|
||||
void AddView(lcView* View)
|
||||
{
|
||||
mViews.Add(View);
|
||||
}
|
||||
|
||||
void RemoveView(View* View)
|
||||
void RemoveView(lcView* View)
|
||||
{
|
||||
if (View == mActiveView)
|
||||
mActiveView = nullptr;
|
||||
|
@ -116,15 +92,15 @@ public:
|
|||
mModel = Model;
|
||||
}
|
||||
|
||||
const lcArray<View*>* GetViews() const
|
||||
const lcArray<lcView*>* GetViews() const
|
||||
{
|
||||
return &mViews;
|
||||
}
|
||||
|
||||
protected:
|
||||
lcModel* mModel;
|
||||
View* mActiveView;
|
||||
lcArray<View*> mViews;
|
||||
lcView* mActiveView;
|
||||
lcArray<lcView*> mViews;
|
||||
};
|
||||
|
||||
class lcMainWindow : public QMainWindow
|
||||
|
@ -192,7 +168,7 @@ public:
|
|||
return mRelativeTransform;
|
||||
}
|
||||
|
||||
bool GetLocalTransform() const
|
||||
bool GetSeparateTransform() const
|
||||
{
|
||||
return mLocalTransform;
|
||||
}
|
||||
|
@ -207,7 +183,7 @@ public:
|
|||
return mCurrentPieceInfo;
|
||||
}
|
||||
|
||||
View* GetActiveView() const
|
||||
lcView* GetActiveView() const
|
||||
{
|
||||
const lcModelTabWidget* const CurrentTab = mModelTabWidget ? (lcModelTabWidget*)mModelTabWidget->currentWidget() : nullptr;
|
||||
return CurrentTab ? CurrentTab->GetActiveView() : nullptr;
|
||||
|
@ -221,13 +197,13 @@ public:
|
|||
return CurrentTab ? CurrentTab->GetModel() : nullptr;
|
||||
}
|
||||
|
||||
const lcArray<View*>* GetViewsForModel(const lcModel* Model) const
|
||||
const lcArray<lcView*>* GetViewsForModel(const lcModel* Model) const
|
||||
{
|
||||
const lcModelTabWidget* const TabWidget = GetTabWidgetForModel(Model);
|
||||
return TabWidget ? TabWidget->GetViews() : nullptr;
|
||||
}
|
||||
|
||||
lcModelTabWidget* GetTabForView(View* View) const
|
||||
lcModelTabWidget* GetTabForView(lcView* View) const
|
||||
{
|
||||
for (int TabIdx = 0; TabIdx < mModelTabWidget->count(); TabIdx++)
|
||||
{
|
||||
|
@ -246,6 +222,11 @@ public:
|
|||
return mPartSelectionWidget;
|
||||
}
|
||||
|
||||
lcPreviewDockWidget* GetPreviewWidget() const
|
||||
{
|
||||
return mPreviewWidget;
|
||||
}
|
||||
|
||||
QMenu* GetToolsMenu() const
|
||||
{
|
||||
return mToolsMenu;
|
||||
|
@ -277,10 +258,8 @@ public:
|
|||
void CloseCurrentModelTab();
|
||||
void SetCurrentModelTab(lcModel* Model);
|
||||
void ResetCameras();
|
||||
void AddView(View* View);
|
||||
void RemoveView(View* View);
|
||||
void SetActiveView(View* ActiveView);
|
||||
void UpdateAllViews();
|
||||
void AddView(lcView* View);
|
||||
void RemoveView(lcView* View);
|
||||
|
||||
void SetTool(lcTool Tool);
|
||||
void SetTransformType(lcTransformType TransformType);
|
||||
|
@ -291,11 +270,13 @@ public:
|
|||
void SetMoveZSnapIndex(int Index);
|
||||
void SetAngleSnapIndex(int Index);
|
||||
void SetRelativeTransform(bool RelativeTransform);
|
||||
void SetLocalTransform(bool SelectionTransform);
|
||||
void SetSeparateTransform(bool SelectionTransform);
|
||||
void SetCurrentPieceInfo(PieceInfo* Info);
|
||||
void SetShadingMode(lcShadingMode ShadingMode);
|
||||
void SetSelectionMode(lcSelectionMode SelectionMode);
|
||||
void ToggleViewSphere();
|
||||
void ToggleAxisIcon();
|
||||
void ToggleGrid();
|
||||
void ToggleFadePreviousSteps();
|
||||
|
||||
void NewProject();
|
||||
|
@ -330,7 +311,6 @@ public:
|
|||
void UpdateSnap();
|
||||
void UpdateColor();
|
||||
void UpdateUndoRedo(const QString& UndoText, const QString& RedoText);
|
||||
void UpdateCurrentCamera(int CameraIndex);
|
||||
void UpdatePerspective();
|
||||
void UpdateCameraMenu();
|
||||
void UpdateShadingMode();
|
||||
|
@ -346,13 +326,17 @@ public:
|
|||
|
||||
QString mRecentFiles[LC_MAX_RECENT_FILES];
|
||||
int mColorIndex;
|
||||
lcSearchOptions mSearchOptions;
|
||||
QAction* mActions[LC_NUM_COMMANDS];
|
||||
|
||||
public slots:
|
||||
void ProjectFileChanged(const QString& Path);
|
||||
void PreviewPiece(const QString& PartId, int ColorCode, bool ShowPreview);
|
||||
void TogglePreviewWidget(bool Visible);
|
||||
|
||||
protected slots:
|
||||
void ViewFocusReceived();
|
||||
void ViewCameraChanged();
|
||||
void UpdateDockWidgetActions();
|
||||
void UpdateGamepads();
|
||||
void ModelTabContextMenuRequested(const QPoint& Point);
|
||||
void ModelTabCloseOtherTabs();
|
||||
|
@ -361,7 +345,9 @@ protected slots:
|
|||
void ClipboardChanged();
|
||||
void ActionTriggered();
|
||||
void ColorChanged(int ColorIndex);
|
||||
void ColorButtonClicked();
|
||||
void Print(QPrinter* Printer);
|
||||
void EnableWindowFlags(bool);
|
||||
|
||||
protected:
|
||||
void closeEvent(QCloseEvent *event) override;
|
||||
|
@ -373,13 +359,17 @@ protected:
|
|||
void CreateMenus();
|
||||
void CreateToolBars();
|
||||
void CreateStatusBar();
|
||||
lcView* CreateView(lcModel* Model);
|
||||
void SetActiveView(lcView* ActiveView);
|
||||
void ToggleDockWidget(QWidget* DockWidget);
|
||||
void SplitView(Qt::Orientation Orientation);
|
||||
void ShowSearchDialog();
|
||||
void ShowUpdatesDialog();
|
||||
void ShowAboutDialog();
|
||||
void ShowHTMLDialog();
|
||||
void ShowRenderDialog();
|
||||
void ShowInstructionsDialog();
|
||||
void ShowPrintDialog();
|
||||
void CreatePreviewWidget();
|
||||
|
||||
bool OpenProjectFile(const QString& FileName);
|
||||
|
||||
|
@ -415,10 +405,11 @@ protected:
|
|||
|
||||
QAction* mActionFileRecentSeparator;
|
||||
|
||||
lcTabWidget* mModelTabWidget;
|
||||
QTabWidget* mModelTabWidget;
|
||||
QToolBar* mStandardToolBar;
|
||||
QToolBar* mToolsToolBar;
|
||||
QToolBar* mTimeToolBar;
|
||||
QDockWidget* mPreviewToolBar;
|
||||
QDockWidget* mPartsToolBar;
|
||||
QDockWidget* mColorsToolBar;
|
||||
QDockWidget* mPropertiesToolBar;
|
||||
|
@ -426,17 +417,20 @@ protected:
|
|||
|
||||
lcPartSelectionWidget* mPartSelectionWidget;
|
||||
lcQColorList* mColorList;
|
||||
QToolButton* mColorButton;
|
||||
lcQPropertiesTree* mPropertiesWidget;
|
||||
lcTimelineWidget* mTimelineWidget;
|
||||
QLineEdit* mTransformXEdit;
|
||||
QLineEdit* mTransformYEdit;
|
||||
QLineEdit* mTransformZEdit;
|
||||
lcPreviewDockWidget* mPreviewWidget;
|
||||
|
||||
lcElidedLabel* mStatusBarLabel;
|
||||
QLabel* mStatusPositionLabel;
|
||||
QLabel* mStatusSnapLabel;
|
||||
QLabel* mStatusTimeLabel;
|
||||
|
||||
QMenu* mTransformMenu;
|
||||
QMenu* mToolsMenu;
|
||||
QMenu* mViewpointMenu;
|
||||
QMenu* mCameraMenu;
|
||||
|
|
209
common/lc_math.h
209
common/lc_math.h
|
@ -7,14 +7,26 @@
|
|||
#define LC_RTOD (static_cast<float>(180 / M_PI))
|
||||
#define LC_PI (static_cast<float>(M_PI))
|
||||
#define LC_2PI (static_cast<float>(2 * M_PI))
|
||||
#define LC_RGB_EPSILON (static_cast<float>(0.5f / 255.0f))
|
||||
|
||||
#define LC_RGB(r,g,b) LC_RGBA(r,g,b,255)
|
||||
#define LC_RGBA(r,g,b,a) ((quint32)(((quint8) (r) | ((quint16) (g) << 8)) | (((quint32) (quint8) (b)) << 16) | (((quint32) (quint8) (a)) << 24)))
|
||||
#define LC_RGBA(r,g,b,a) ((quint32)(((quint8) (r) | ((quint16) (g) << 8)) | (((quint32) (quint8) (b)) << 16) | (((quint32) (quint8) (a)) << 24)))
|
||||
#define LC_RGBA_RED(rgba) ((quint8)(((rgba) >> 0) & 0xff))
|
||||
#define LC_RGBA_GREEN(rgba) ((quint8)(((rgba) >> 8) & 0xff))
|
||||
#define LC_RGBA_BLUE(rgba) ((quint8)(((rgba) >> 16) & 0xff))
|
||||
#define LC_RGBA_ALPHA(rgba) ((quint8)(((rgba) >> 24) & 0xff))
|
||||
#define LC_FLOATRGB(f) LC_RGB(f[0]*255, f[1]*255, f[2]*255)
|
||||
#define LC_SRGB_TO_LINEAR(v) (powf(v, 2.2f))
|
||||
#define LC_LINEAR_TO_SRGB(v) (powf(v, 1.0f / 2.2f))
|
||||
|
||||
inline quint32 lcRGBAFromQColor(const QColor& Color)
|
||||
{
|
||||
return LC_RGBA(Color.red(), Color.green(), Color.blue(), Color.alpha());
|
||||
}
|
||||
|
||||
inline QColor lcQColorFromRGBA(quint32 RGBA)
|
||||
{
|
||||
return QColor::fromRgb(LC_RGBA_RED(RGBA), LC_RGBA_GREEN(RGBA), LC_RGBA_BLUE(RGBA), LC_RGBA_ALPHA(RGBA));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T lcMin(const T& a, const T& b)
|
||||
|
@ -55,12 +67,12 @@ public:
|
|||
{
|
||||
return (const float*)this;
|
||||
}
|
||||
|
||||
|
||||
operator float*()
|
||||
{
|
||||
return (float*)this;
|
||||
}
|
||||
|
||||
|
||||
const float& operator[](int i) const
|
||||
{
|
||||
return ((float*)this)[i];
|
||||
|
@ -97,12 +109,12 @@ public:
|
|||
{
|
||||
return (const float*)this;
|
||||
}
|
||||
|
||||
|
||||
operator float*()
|
||||
{
|
||||
return (float*)this;
|
||||
}
|
||||
|
||||
|
||||
const float& operator[](int i) const
|
||||
{
|
||||
return ((float*)this)[i];
|
||||
|
@ -146,12 +158,12 @@ public:
|
|||
{
|
||||
return (const float*)this;
|
||||
}
|
||||
|
||||
|
||||
operator float*()
|
||||
{
|
||||
return (float*)this;
|
||||
}
|
||||
|
||||
|
||||
const float& operator[](int i) const
|
||||
{
|
||||
return ((float*)this)[i];
|
||||
|
@ -190,12 +202,12 @@ public:
|
|||
{
|
||||
return (const float*)this;
|
||||
}
|
||||
|
||||
|
||||
operator float*()
|
||||
{
|
||||
return (float*)this;
|
||||
}
|
||||
|
||||
|
||||
const lcVector3& operator[](int i) const
|
||||
{
|
||||
return r[i];
|
||||
|
@ -248,12 +260,12 @@ public:
|
|||
{
|
||||
return (const float*)this;
|
||||
}
|
||||
|
||||
|
||||
operator float*()
|
||||
{
|
||||
return (float*)this;
|
||||
}
|
||||
|
||||
|
||||
const lcVector4& operator[](int i) const
|
||||
{
|
||||
return r[i];
|
||||
|
@ -355,6 +367,15 @@ inline lcVector3& operator/=(lcVector3& a, const lcVector3& b)
|
|||
return a;
|
||||
}
|
||||
|
||||
inline lcVector3& operator+=(lcVector3& a, float b)
|
||||
{
|
||||
a.x += b;
|
||||
a.y += b;
|
||||
a.z += b;
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
inline lcVector3& operator*=(lcVector3& a, float b)
|
||||
{
|
||||
a.x *= b;
|
||||
|
@ -637,7 +658,30 @@ inline lcVector4 lcVector4FromColor(quint32 Color)
|
|||
|
||||
inline quint32 lcColorFromVector3(const lcVector3& Color)
|
||||
{
|
||||
return LC_RGB(Color[0] * 255, Color[1] * 255, Color[2] * 255);
|
||||
return LC_RGB(roundf(Color[0] * 255), roundf(Color[1] * 255), roundf(Color[2] * 255));
|
||||
}
|
||||
|
||||
inline float lcLuminescence(const lcVector3& Color)
|
||||
{
|
||||
return 0.2126f * Color[0] + 0.7152f * Color[1] + 0.0722f * Color[2];
|
||||
}
|
||||
|
||||
inline lcVector3 lcSRGBToLinear(const lcVector3& Color)
|
||||
{
|
||||
const float r = LC_SRGB_TO_LINEAR(Color[0]);
|
||||
const float g = LC_SRGB_TO_LINEAR(Color[1]);
|
||||
const float b = LC_SRGB_TO_LINEAR(Color[2]);
|
||||
|
||||
return lcVector3(r, g, b);
|
||||
}
|
||||
|
||||
inline lcVector3 lcLinearToSRGB(const lcVector3& Color)
|
||||
{
|
||||
const float r = LC_LINEAR_TO_SRGB(Color[0]);
|
||||
const float g = LC_LINEAR_TO_SRGB(Color[1]);
|
||||
const float b = LC_LINEAR_TO_SRGB(Color[2]);
|
||||
|
||||
return lcVector3(r, g, b);
|
||||
}
|
||||
|
||||
inline lcVector3 lcMul(const lcVector3& a, const lcMatrix33& b)
|
||||
|
@ -1212,7 +1256,7 @@ inline lcVector3 lcMatrix44ToEulerAngles(const lcMatrix44& RotMat)
|
|||
CosRoll = RotMat.r[2][2] / CosPitch;
|
||||
SinYaw = RotMat.r[0][1] / CosPitch;
|
||||
CosYaw = RotMat.r[0][0] / CosPitch;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SinRoll = -RotMat.r[2][1];
|
||||
|
@ -1362,9 +1406,9 @@ inline lcMatrix44 lcMatrix44Inverse(const lcMatrix44& m)
|
|||
const lcVector4 Row1(r0[5], r1[5], r2[5], r3[5]);
|
||||
const lcVector4 Row2(r0[6], r1[6], r2[6], r3[6]);
|
||||
const lcVector4 Row3(r0[7], r1[7], r2[7], r3[7]);
|
||||
|
||||
|
||||
lcMatrix44 out(Row0, Row1, Row2, Row3);
|
||||
|
||||
|
||||
return out;
|
||||
|
||||
#undef MAT
|
||||
|
@ -1562,7 +1606,7 @@ inline void lcGetFrustumPlanes(const lcMatrix44& WorldView, const lcMatrix44& Pr
|
|||
}
|
||||
}
|
||||
|
||||
inline std::tuple<lcVector3, float> lcZoomExtents(const lcVector3& Position, const lcMatrix44& WorldView, const lcMatrix44& Projection, const lcVector3* Points, int NumPoints)
|
||||
inline std::tuple<lcVector3, float> lcZoomExtents(const lcVector3& Position, const lcMatrix44& WorldView, const lcMatrix44& Projection, const lcVector3* Points, size_t NumPoints)
|
||||
{
|
||||
if (!NumPoints)
|
||||
return std::make_tuple(Position, 2500.0f);
|
||||
|
@ -1580,7 +1624,7 @@ inline std::tuple<lcVector3, float> lcZoomExtents(const lcVector3& Position, con
|
|||
const float ep = lcDot(Position, Plane);
|
||||
const float fp = lcDot(Front, Plane);
|
||||
|
||||
for (int PointIdx = 0; PointIdx < NumPoints; PointIdx++)
|
||||
for (size_t PointIdx = 0; PointIdx < NumPoints; PointIdx++)
|
||||
{
|
||||
const float u = (ep - lcDot(Points[PointIdx], Plane)) / fp;
|
||||
|
||||
|
@ -1593,7 +1637,7 @@ inline std::tuple<lcVector3, float> lcZoomExtents(const lcVector3& Position, con
|
|||
|
||||
float FarDistance = 2500.0f;
|
||||
|
||||
for (int PointIdx = 0; PointIdx < NumPoints; PointIdx++)
|
||||
for (size_t PointIdx = 0; PointIdx < NumPoints; PointIdx++)
|
||||
{
|
||||
const float Distance = lcDot(Points[PointIdx], Front);
|
||||
|
||||
|
@ -1987,7 +2031,7 @@ inline bool lcBoundingBoxIntersectsVolume(const lcVector3& Min, const lcVector3&
|
|||
if (OutcodesOR == 0)
|
||||
return true;
|
||||
|
||||
int Indices[36] =
|
||||
int Indices[36] =
|
||||
{
|
||||
0, 1, 2,
|
||||
0, 2, 3,
|
||||
|
@ -2043,3 +2087,128 @@ bool SphereIntersectsVolume(const Vector3& Center, float Radius, const Vector4*
|
|||
return true;
|
||||
}*/
|
||||
|
||||
inline lcVector3 lcRGBToHSL(const lcVector3& rgb)
|
||||
{
|
||||
int Mi;
|
||||
float M, m, C, h, S, L; // h is H/60
|
||||
|
||||
Mi = (rgb[0] >= rgb[1]) ? 0 : 1;
|
||||
Mi = (rgb[Mi] >= rgb[2]) ? Mi : 2;
|
||||
M = rgb[Mi];
|
||||
|
||||
m = (rgb[0] < rgb[1]) ? rgb[0] : rgb[1];
|
||||
m = (m < rgb[2]) ? m : rgb[2];
|
||||
|
||||
C = M - m;
|
||||
L = (M + m) / 2.0f;
|
||||
|
||||
if (C < LC_RGB_EPSILON) // C == 0.0
|
||||
h = 0.0f;
|
||||
else if (Mi == 0) // M == R
|
||||
h = 0.0f + (rgb[1] - rgb[2]) / C;
|
||||
else if (Mi == 1) // M == G
|
||||
h = 2.0f + (rgb[2] - rgb[0]) / C;
|
||||
else // M = B
|
||||
h = 4.0f + (rgb[0] - rgb[1]) / C;
|
||||
|
||||
h = (h < 0.0) ? h + 6.0f : h;
|
||||
h = (h >= 6.0) ? h - 6.0f : h;
|
||||
|
||||
S = ((L < (LC_RGB_EPSILON / 2.0f)) || (L > (1.0f -(LC_RGB_EPSILON / 2.0f))))
|
||||
? 0.0f : (2.0f * (M - L)) / (1.0f - fabs((2.0f * L) - 1.0f)) ;
|
||||
|
||||
return lcVector3(h, S, L);
|
||||
}
|
||||
|
||||
inline lcVector3 lcHSLToRGB(const lcVector3& hSL)
|
||||
{
|
||||
lcVector3 rgb;
|
||||
float h, S, L, C, X, m;
|
||||
|
||||
h = hSL[0];
|
||||
S = hSL[1];
|
||||
L = hSL[2];
|
||||
|
||||
C = (1.0f - fabs(2.0f * L - 1.0f)) * S;
|
||||
X = C * (1.0f - fabs(fmodf(h, 2.0f) - 1.0f));
|
||||
|
||||
if (h < 1.0f)
|
||||
rgb = lcVector3(C, X, 0.0f);
|
||||
else if (h < 2.0f)
|
||||
rgb = lcVector3(X, C, 0.0f);
|
||||
else if (h < 3.0f)
|
||||
rgb = lcVector3(0.0f, C, X);
|
||||
else if (h < 4.0f)
|
||||
rgb = lcVector3(0.0f, X, C);
|
||||
else if (h < 5.0f)
|
||||
rgb = lcVector3(X, 0.0f, C);
|
||||
else
|
||||
rgb = lcVector3(C, 0.0f, X);
|
||||
|
||||
m = L - C / 2.0f;
|
||||
rgb += m;
|
||||
|
||||
return rgb;
|
||||
}
|
||||
|
||||
inline lcVector4 lcAlgorithmicEdgeColor(const lcVector3& Value, const float ValueLum, const float EdgeLum, const float Contrast, const float Saturation)
|
||||
{
|
||||
float y1, yt;
|
||||
lcVector3 hSL, rgb1, rgbf;
|
||||
|
||||
// Determine luma target
|
||||
if (EdgeLum < ValueLum)
|
||||
{
|
||||
// Light base color
|
||||
yt = ValueLum - Contrast * ValueLum;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Dark base color
|
||||
yt = ValueLum + Contrast * (1.0f - ValueLum);
|
||||
}
|
||||
|
||||
// Get base color in hSL
|
||||
hSL = lcRGBToHSL(Value);
|
||||
|
||||
// Adjust saturation
|
||||
// sat = 4.0f * sat - 2.0f;
|
||||
// if (sat < 0.0f)
|
||||
// {
|
||||
// sat = -sat;
|
||||
// hSL[0] = (hSL[0] < 3.0f) ? hSL[0] + 3.0f : hSL[0] - 3.0f;
|
||||
// }
|
||||
// sat = (sat > 2.0f) ? 2.0f : sat;
|
||||
// if (sat > 1.0f)
|
||||
// {
|
||||
// // Supersaturate
|
||||
// sat -= 1.0f;
|
||||
// hSL[1] += sat * (1.0f - hSL[1]);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// Desaturate
|
||||
hSL[1] *= Saturation;
|
||||
// }
|
||||
|
||||
// Adjusted color to RGB
|
||||
rgb1 = lcHSLToRGB(lcVector3(hSL[0], hSL[1], 0.5f));
|
||||
|
||||
// Fix adjusted color luma to target value
|
||||
y1 = lcLuminescence(rgb1);
|
||||
|
||||
if (yt < y1)
|
||||
{
|
||||
// Make darker via scaling
|
||||
rgbf = (yt/y1) * rgb1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Make lighter via scaling anti-color
|
||||
rgbf = lcVector3(1.0f, 1.0f, 1.0f) - rgb1;
|
||||
rgbf *= (1.0f - yt) / (1.0f - y1);
|
||||
rgbf = lcVector3(1.0f, 1.0f, 1.0f) - rgbf;
|
||||
}
|
||||
|
||||
return lcVector4(lcLinearToSRGB(rgbf), 1.0f);
|
||||
}
|
||||
|
|
|
@ -29,7 +29,6 @@ lcMesh::lcMesh()
|
|||
mIndexDataSize = 0;
|
||||
mVertexCacheOffset = -1;
|
||||
mIndexCacheOffset = -1;
|
||||
mFlags = 0;
|
||||
}
|
||||
|
||||
lcMesh::~lcMesh()
|
||||
|
@ -493,10 +492,10 @@ bool lcMesh::FileSave(lcMemFile& File)
|
|||
|
||||
int lcMesh::GetLodIndex(float Distance) const
|
||||
{
|
||||
if (lcGetPiecesLibrary()->GetStudLogo())
|
||||
if (lcGetPiecesLibrary()->GetStudStyle() != lcStudStyle::Plain) // todo: support low lod studs
|
||||
return LC_MESH_LOD_HIGH;
|
||||
|
||||
if (mLods[LC_MESH_LOD_LOW].NumSections && (Distance - mRadius) > 250.0f)
|
||||
if (mLods[LC_MESH_LOD_LOW].NumSections && (Distance > mRadius))
|
||||
return LC_MESH_LOD_LOW;
|
||||
else
|
||||
return LC_MESH_LOD_HIGH;
|
||||
|
|
|
@ -48,18 +48,14 @@ enum
|
|||
LC_NUM_MESH_LODS
|
||||
};
|
||||
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
|
||||
enum class lcMeshFlag
|
||||
#else
|
||||
enum lcMeshFlag
|
||||
#endif
|
||||
{
|
||||
HasDefault = 0x01, // Mesh has triangles using the default color
|
||||
HasSolid = 0x02, // Mesh has triangles using a solid color
|
||||
HasTranslucent = 0x04, // Mesh has triangles using a translucent color
|
||||
HasLines = 0x08, // Mesh has lines
|
||||
HasTexture = 0x10, // Mesh has sections using textures
|
||||
HasLogoStud = 0x20 // Mesh has a stud that can have a logo applied
|
||||
HasStyleStud = 0x20 // Mesh has a stud that can have a logo applied
|
||||
};
|
||||
|
||||
Q_DECLARE_FLAGS(lcMeshFlags, lcMeshFlag)
|
||||
|
@ -117,5 +113,4 @@ public:
|
|||
int mIndexType;
|
||||
};
|
||||
|
||||
extern lcMesh* gPlaceholderMesh;
|
||||
|
||||
|
|
|
@ -1187,8 +1187,8 @@ lcMesh* lcLibraryMeshData::CreateMesh()
|
|||
}
|
||||
}
|
||||
|
||||
if (mHasLogoStud)
|
||||
Mesh->mFlags |= lcMeshFlag::HasLogoStud;
|
||||
if (mHasStyleStud)
|
||||
Mesh->mFlags |= lcMeshFlag::HasStyleStud;
|
||||
|
||||
lcVector3 MeshMin(FLT_MAX, FLT_MAX, FLT_MAX), MeshMax(-FLT_MAX, -FLT_MAX, -FLT_MAX);
|
||||
bool UpdatedBoundingBox = false;
|
||||
|
@ -1610,7 +1610,7 @@ bool lcMeshLoader::ReadMeshData(lcFile& File, const lcMatrix44& CurrentTransform
|
|||
|
||||
if (Primitive)
|
||||
{
|
||||
if (Primitive->mState != lcPrimitiveState::LOADED && !Library->LoadPrimitive(Primitive))
|
||||
if (Primitive->mState != lcPrimitiveState::Loaded && !Library->LoadPrimitive(Primitive))
|
||||
break;
|
||||
|
||||
if (Primitive->mStud)
|
||||
|
@ -1625,7 +1625,7 @@ bool lcMeshLoader::ReadMeshData(lcFile& File, const lcMatrix44& CurrentTransform
|
|||
else
|
||||
Library->GetPrimitiveFile(Primitive, FileCallback);
|
||||
|
||||
mMeshData.mHasLogoStud |= Primitive->mMeshData.mHasLogoStud;
|
||||
mMeshData.mHasStyleStud |= Primitive->mStudStyle | Primitive->mMeshData.mHasStyleStud;
|
||||
}
|
||||
else
|
||||
Library->GetPieceFile(FileName, FileCallback);
|
||||
|
|
|
@ -93,7 +93,7 @@ public:
|
|||
lcLibraryMeshData()
|
||||
{
|
||||
mHasTextures = false;
|
||||
mHasLogoStud = false;
|
||||
mHasStyleStud = false;
|
||||
|
||||
for (int MeshDataIdx = 0; MeshDataIdx < LC_NUM_MESHDATA_TYPES; MeshDataIdx++)
|
||||
mVertices[MeshDataIdx].SetGrow(1024);
|
||||
|
@ -148,7 +148,7 @@ public:
|
|||
lcArray<lcLibraryMeshSection*> mSections[LC_NUM_MESHDATA_TYPES];
|
||||
lcArray<lcLibraryMeshVertex> mVertices[LC_NUM_MESHDATA_TYPES];
|
||||
bool mHasTextures;
|
||||
bool mHasLogoStud;
|
||||
bool mHasStyleStud;
|
||||
};
|
||||
|
||||
class lcMeshLoader
|
||||
|
|
280
common/lc_minifigdialog.cpp
Normal file
280
common/lc_minifigdialog.cpp
Normal file
|
@ -0,0 +1,280 @@
|
|||
#include "lc_global.h"
|
||||
#include "lc_minifigdialog.h"
|
||||
#include "ui_lc_minifigdialog.h"
|
||||
#include "lc_viewwidget.h"
|
||||
#include "lc_qcolorpicker.h"
|
||||
#include "minifig.h"
|
||||
#include "lc_application.h"
|
||||
#include "pieceinf.h"
|
||||
#include "lc_library.h"
|
||||
#include "lc_view.h"
|
||||
#include "camera.h"
|
||||
|
||||
lcMinifigDialog::lcMinifigDialog(QWidget* Parent)
|
||||
: QDialog(Parent), ui(new Ui::lcMinifigDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
mComboBoxes =
|
||||
{
|
||||
ui->hatsType, ui->hats2Type, ui->headType, ui->neckType, ui->bodyType, ui->body2Type, ui->body3Type, ui->rarmType, ui->larmType,
|
||||
ui->rhandType, ui->lhandType, ui->rhandaType, ui->lhandaType, ui->rlegType, ui->llegType, ui->rlegaType, ui->llegaType
|
||||
};
|
||||
|
||||
mColorPickers =
|
||||
{
|
||||
ui->hatsColor, ui->hats2Color, ui->headColor, ui->neckColor, ui->bodyColor, ui->body2Color, ui->body3Color, ui->rarmColor, ui->larmColor,
|
||||
ui->rhandColor, ui->lhandColor, ui->rhandaColor, ui->lhandaColor, ui->rlegColor, ui->llegColor, ui->rlegaColor, ui->llegaColor
|
||||
};
|
||||
|
||||
mSpinBoxes =
|
||||
{
|
||||
ui->hatsAngle, ui->hats2Angle, ui->headAngle, nullptr, nullptr, nullptr, nullptr, ui->rarmAngle, ui->larmAngle,
|
||||
ui->rhandAngle, ui->lhandAngle, ui->rhandaAngle, ui->lhandaAngle, ui->rlegAngle, ui->llegAngle, ui->rlegaAngle, ui->llegaAngle
|
||||
};
|
||||
|
||||
for (QComboBox* ComboBox : mComboBoxes)
|
||||
connect(ComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(TypeChanged(int)));
|
||||
|
||||
for (lcQColorPicker* ColorPicker : mColorPickers)
|
||||
connect(ColorPicker, SIGNAL(colorChanged(int)), this, SLOT(ColorChanged(int)));
|
||||
|
||||
for (QDoubleSpinBox* SpinBox : mSpinBoxes)
|
||||
if (SpinBox)
|
||||
connect(SpinBox, SIGNAL(valueChanged(double)), this, SLOT(AngleChanged(double)));
|
||||
|
||||
QGridLayout* PreviewLayout = new QGridLayout(ui->minifigFrame);
|
||||
PreviewLayout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
mMinifigWizard = new MinifigWizard();
|
||||
mView = new lcView(lcViewType::Minifig, mMinifigWizard->GetModel());
|
||||
|
||||
lcViewWidget* ViewWidget = new lcViewWidget(nullptr, mView);
|
||||
ViewWidget->setMinimumWidth(100);
|
||||
PreviewLayout->addWidget(ViewWidget);
|
||||
|
||||
mView->MakeCurrent();
|
||||
mMinifigWizard->LoadDefault();
|
||||
|
||||
for (int ItemIndex = 0; ItemIndex < LC_MFW_NUMITEMS; ItemIndex++)
|
||||
{
|
||||
const std::vector<lcMinifigPieceInfo>& PartList = mMinifigWizard->mSettings[ItemIndex];
|
||||
QStringList ItemStrings;
|
||||
QVector<int> Separators;
|
||||
|
||||
for (const lcMinifigPieceInfo& MinifigPieceInfo : PartList)
|
||||
{
|
||||
const char* Description = MinifigPieceInfo.Description;
|
||||
|
||||
if (Description[0] != '-' || Description[1] != '-')
|
||||
ItemStrings.append(Description);
|
||||
else
|
||||
Separators.append(ItemStrings.size());
|
||||
}
|
||||
|
||||
QComboBox* ItemCombo = mComboBoxes[ItemIndex];
|
||||
|
||||
ItemCombo->blockSignals(true);
|
||||
ItemCombo->addItems(ItemStrings);
|
||||
for (int SeparatorIndex = Separators.size() - 1; SeparatorIndex >= 0; SeparatorIndex--)
|
||||
ItemCombo->insertSeparator(Separators[SeparatorIndex]);
|
||||
ItemCombo->setCurrentIndex(mMinifigWizard->GetSelectionIndex(ItemIndex));
|
||||
ItemCombo->blockSignals(false);
|
||||
|
||||
lcQColorPicker* ColorPicker = mColorPickers[ItemIndex];
|
||||
|
||||
ColorPicker->blockSignals(true);
|
||||
ColorPicker->setCurrentColor(mMinifigWizard->mMinifig.Colors[ItemIndex]);
|
||||
ColorPicker->blockSignals(false);
|
||||
}
|
||||
|
||||
UpdateTemplateCombo();
|
||||
|
||||
mMinifigWizard->Calculate();
|
||||
mView->GetCamera()->SetViewpoint(lcVector3(0.0f, -270.0f, 90.0f));
|
||||
mView->ZoomExtents();
|
||||
}
|
||||
|
||||
lcMinifigDialog::~lcMinifigDialog()
|
||||
{
|
||||
delete mMinifigWizard;
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void lcMinifigDialog::UpdateTemplateCombo()
|
||||
{
|
||||
ui->TemplateComboBox->clear();
|
||||
|
||||
const auto& Templates = mMinifigWizard->GetTemplates();
|
||||
for (const auto& Template : Templates)
|
||||
ui->TemplateComboBox->addItem(Template.first);
|
||||
}
|
||||
|
||||
void lcMinifigDialog::on_TemplateComboBox_currentIndexChanged(const QString& TemplateName)
|
||||
{
|
||||
const auto& Templates = mMinifigWizard->GetTemplates();
|
||||
const auto& Position = Templates.find(TemplateName);
|
||||
if (Position == Templates.end())
|
||||
return;
|
||||
|
||||
const lcMinifigTemplate& Template = Position->second;
|
||||
|
||||
for (int PartIdx = 0; PartIdx < LC_MFW_NUMITEMS; PartIdx++)
|
||||
{
|
||||
if (!Template.Parts[PartIdx].isEmpty())
|
||||
{
|
||||
PieceInfo* Info = lcGetPiecesLibrary()->FindPiece(Template.Parts[PartIdx].toLatin1(), nullptr, false, false);
|
||||
|
||||
if (Info)
|
||||
{
|
||||
for (const lcMinifigPieceInfo& MinifigPieceInfo : mMinifigWizard->mSettings[PartIdx])
|
||||
{
|
||||
if (Info == MinifigPieceInfo.Info)
|
||||
{
|
||||
mComboBoxes[PartIdx]->setCurrentText(MinifigPieceInfo.Description);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mComboBoxes[PartIdx]->setCurrentText("None");
|
||||
}
|
||||
|
||||
mColorPickers[PartIdx]->setCurrentColorCode(Template.Colors[PartIdx]);
|
||||
|
||||
QDoubleSpinBox* AngleSpinBox = mSpinBoxes[PartIdx];
|
||||
if (AngleSpinBox)
|
||||
AngleSpinBox->setValue(Template.Angles[PartIdx]);
|
||||
}
|
||||
|
||||
mMinifigWizard->Calculate();
|
||||
}
|
||||
|
||||
void lcMinifigDialog::on_TemplateSaveButton_clicked()
|
||||
{
|
||||
QString CurrentName = ui->TemplateComboBox->currentText();
|
||||
bool Ok;
|
||||
QString TemplateName = QInputDialog::getText(this, tr("Save Template"), tr("Template Name:"), QLineEdit::Normal, CurrentName, &Ok);
|
||||
|
||||
if (!Ok)
|
||||
return;
|
||||
|
||||
if (TemplateName.isEmpty())
|
||||
{
|
||||
QMessageBox::information(this, tr("Save Template"), tr("Template name cannot be empty."));
|
||||
return;
|
||||
}
|
||||
|
||||
if (TemplateName == CurrentName)
|
||||
{
|
||||
QString Question = tr("Are you sure you want to overwrite the template '%1'?").arg(TemplateName);
|
||||
if (QMessageBox::question(this, tr("Overwrite Template"), Question, QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes)
|
||||
return;
|
||||
}
|
||||
|
||||
lcMinifigTemplate Template;
|
||||
|
||||
for (int PartIdx = 0; PartIdx < LC_MFW_NUMITEMS; PartIdx++)
|
||||
{
|
||||
Template.Parts[PartIdx] = mMinifigWizard->mSettings[PartIdx][mComboBoxes[PartIdx]->currentIndex()].Info->mFileName;
|
||||
Template.Colors[PartIdx] = mColorPickers[PartIdx]->currentColorCode();
|
||||
QDoubleSpinBox* AngleSpinBox = mSpinBoxes[PartIdx];
|
||||
Template.Angles[PartIdx] = AngleSpinBox ? AngleSpinBox->value() : 0.0f;
|
||||
}
|
||||
|
||||
mMinifigWizard->SaveTemplate(TemplateName, Template);
|
||||
|
||||
ui->TemplateComboBox->blockSignals(true);
|
||||
UpdateTemplateCombo();
|
||||
ui->TemplateComboBox->setCurrentText(TemplateName);
|
||||
ui->TemplateComboBox->blockSignals(false);
|
||||
}
|
||||
|
||||
void lcMinifigDialog::on_TemplateDeleteButton_clicked()
|
||||
{
|
||||
QString Template = ui->TemplateComboBox->currentText();
|
||||
QString Question = tr("Are you sure you want to delete the template '%1'?").arg(Template);
|
||||
|
||||
if (QMessageBox::question(this, tr("Delete Template"), Question, QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes)
|
||||
return;
|
||||
|
||||
mMinifigWizard->DeleteTemplate(Template);
|
||||
|
||||
UpdateTemplateCombo();
|
||||
}
|
||||
|
||||
void lcMinifigDialog::on_TemplateImportButton_clicked()
|
||||
{
|
||||
QString FileName = QFileDialog::getOpenFileName(this, tr("Import Templates"), "", tr("Minifig Template Files (*.minifig);;All Files (*.*)"));
|
||||
|
||||
if (FileName.isEmpty())
|
||||
return;
|
||||
|
||||
QFile File(FileName);
|
||||
|
||||
if (!File.open(QIODevice::ReadOnly))
|
||||
{
|
||||
QMessageBox::warning(this, tr("Error"), tr("Error reading file '%1':\n%2").arg(FileName, File.errorString()));
|
||||
return;
|
||||
}
|
||||
|
||||
QByteArray FileData = File.readAll();
|
||||
mMinifigWizard->AddTemplatesJson(FileData);
|
||||
|
||||
UpdateTemplateCombo();
|
||||
}
|
||||
|
||||
void lcMinifigDialog::on_TemplateExportButton_clicked()
|
||||
{
|
||||
QString FileName = QFileDialog::getSaveFileName(this, tr("Export Templates"), "", tr("Minifig Template Files (*.minifig);;All Files (*.*)"));
|
||||
|
||||
if (FileName.isEmpty())
|
||||
return;
|
||||
|
||||
QFile File(FileName);
|
||||
|
||||
if (!File.open(QIODevice::WriteOnly))
|
||||
{
|
||||
QMessageBox::warning(this, tr("Error"), tr("Error writing to file '%1':\n%2").arg(FileName, File.errorString()));
|
||||
return;
|
||||
}
|
||||
|
||||
QByteArray Templates = mMinifigWizard->GetTemplatesJson();
|
||||
File.write(Templates);
|
||||
}
|
||||
|
||||
void lcMinifigDialog::TypeChanged(int Index)
|
||||
{
|
||||
std::array<QComboBox*, LC_MFW_NUMITEMS>::iterator Search = std::find(mComboBoxes.begin(), mComboBoxes.end(), sender());
|
||||
|
||||
if (Search == mComboBoxes.end())
|
||||
return;
|
||||
|
||||
mView->MakeCurrent();
|
||||
mMinifigWizard->SetSelectionIndex(std::distance(mComboBoxes.begin(), Search), Index);
|
||||
mView->Redraw();
|
||||
}
|
||||
|
||||
void lcMinifigDialog::ColorChanged(int Index)
|
||||
{
|
||||
std::array<lcQColorPicker*, LC_MFW_NUMITEMS>::iterator Search = std::find(mColorPickers.begin(), mColorPickers.end(), sender());
|
||||
|
||||
if (Search == mColorPickers.end())
|
||||
return;
|
||||
|
||||
mMinifigWizard->SetColor(std::distance(mColorPickers.begin(), Search), Index);
|
||||
mView->Redraw();
|
||||
}
|
||||
|
||||
void lcMinifigDialog::AngleChanged(double Value)
|
||||
{
|
||||
std::array<QDoubleSpinBox*, LC_MFW_NUMITEMS>::iterator Search = std::find(mSpinBoxes.begin(), mSpinBoxes.end(), sender());
|
||||
|
||||
if (Search == mSpinBoxes.end())
|
||||
return;
|
||||
|
||||
mMinifigWizard->SetAngle(std::distance(mSpinBoxes.begin(), Search), Value);
|
||||
mView->Redraw();
|
||||
}
|
40
common/lc_minifigdialog.h
Normal file
40
common/lc_minifigdialog.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
#pragma once
|
||||
|
||||
#include "minifig.h"
|
||||
class lcQColorPicker;
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class lcMinifigDialog;
|
||||
}
|
||||
|
||||
class lcMinifigDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit lcMinifigDialog(QWidget* Parent);
|
||||
~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 TypeChanged(int Index);
|
||||
void ColorChanged(int Index);
|
||||
void AngleChanged(double Value);
|
||||
|
||||
protected:
|
||||
void UpdateTemplateCombo();
|
||||
|
||||
Ui::lcMinifigDialog* ui;
|
||||
|
||||
lcView* mView;
|
||||
std::array<QComboBox*, LC_MFW_NUMITEMS> mComboBoxes;
|
||||
std::array<lcQColorPicker*, LC_MFW_NUMITEMS> mColorPickers;
|
||||
std::array<QDoubleSpinBox*, LC_MFW_NUMITEMS> mSpinBoxes;
|
||||
};
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>lcQMinifigDialog</class>
|
||||
<widget class="QDialog" name="lcQMinifigDialog">
|
||||
<class>lcMinifigDialog</class>
|
||||
<widget class="QDialog" name="lcMinifigDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
|
@ -26,7 +26,7 @@
|
|||
</sizepolicy>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QComboBox::AdjustToMinimumContentsLength</enum>
|
||||
<enum>QComboBox::AdjustToContents</enum>
|
||||
</property>
|
||||
<property name="minimumContentsLength">
|
||||
<number>24</number>
|
||||
|
@ -68,7 +68,7 @@
|
|||
</sizepolicy>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::Panel</enum>
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Plain</enum>
|
||||
|
@ -110,7 +110,7 @@
|
|||
</sizepolicy>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QComboBox::AdjustToMinimumContentsLength</enum>
|
||||
<enum>QComboBox::AdjustToContents</enum>
|
||||
</property>
|
||||
<property name="minimumContentsLength">
|
||||
<number>24</number>
|
||||
|
@ -126,7 +126,7 @@
|
|||
</sizepolicy>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QComboBox::AdjustToMinimumContentsLength</enum>
|
||||
<enum>QComboBox::AdjustToContents</enum>
|
||||
</property>
|
||||
<property name="minimumContentsLength">
|
||||
<number>24</number>
|
||||
|
@ -168,7 +168,7 @@
|
|||
</sizepolicy>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QComboBox::AdjustToMinimumContentsLength</enum>
|
||||
<enum>QComboBox::AdjustToContents</enum>
|
||||
</property>
|
||||
<property name="minimumContentsLength">
|
||||
<number>24</number>
|
||||
|
@ -198,7 +198,7 @@
|
|||
</sizepolicy>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QComboBox::AdjustToMinimumContentsLength</enum>
|
||||
<enum>QComboBox::AdjustToContents</enum>
|
||||
</property>
|
||||
<property name="minimumContentsLength">
|
||||
<number>24</number>
|
||||
|
@ -214,7 +214,7 @@
|
|||
</sizepolicy>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QComboBox::AdjustToMinimumContentsLength</enum>
|
||||
<enum>QComboBox::AdjustToContents</enum>
|
||||
</property>
|
||||
<property name="minimumContentsLength">
|
||||
<number>24</number>
|
||||
|
@ -282,7 +282,7 @@
|
|||
</sizepolicy>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QComboBox::AdjustToMinimumContentsLength</enum>
|
||||
<enum>QComboBox::AdjustToContents</enum>
|
||||
</property>
|
||||
<property name="minimumContentsLength">
|
||||
<number>24</number>
|
||||
|
@ -298,7 +298,7 @@
|
|||
</sizepolicy>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QComboBox::AdjustToMinimumContentsLength</enum>
|
||||
<enum>QComboBox::AdjustToContents</enum>
|
||||
</property>
|
||||
<property name="minimumContentsLength">
|
||||
<number>24</number>
|
||||
|
@ -366,7 +366,7 @@
|
|||
</sizepolicy>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QComboBox::AdjustToMinimumContentsLength</enum>
|
||||
<enum>QComboBox::AdjustToContents</enum>
|
||||
</property>
|
||||
<property name="minimumContentsLength">
|
||||
<number>24</number>
|
||||
|
@ -382,7 +382,7 @@
|
|||
</sizepolicy>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QComboBox::AdjustToMinimumContentsLength</enum>
|
||||
<enum>QComboBox::AdjustToContents</enum>
|
||||
</property>
|
||||
<property name="minimumContentsLength">
|
||||
<number>24</number>
|
||||
|
@ -450,7 +450,7 @@
|
|||
</sizepolicy>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QComboBox::AdjustToMinimumContentsLength</enum>
|
||||
<enum>QComboBox::AdjustToContents</enum>
|
||||
</property>
|
||||
<property name="minimumContentsLength">
|
||||
<number>24</number>
|
||||
|
@ -466,7 +466,7 @@
|
|||
</sizepolicy>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QComboBox::AdjustToMinimumContentsLength</enum>
|
||||
<enum>QComboBox::AdjustToContents</enum>
|
||||
</property>
|
||||
<property name="minimumContentsLength">
|
||||
<number>24</number>
|
||||
|
@ -496,7 +496,7 @@
|
|||
</sizepolicy>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QComboBox::AdjustToMinimumContentsLength</enum>
|
||||
<enum>QComboBox::AdjustToContents</enum>
|
||||
</property>
|
||||
<property name="minimumContentsLength">
|
||||
<number>24</number>
|
||||
|
@ -512,7 +512,7 @@
|
|||
</sizepolicy>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QComboBox::AdjustToMinimumContentsLength</enum>
|
||||
<enum>QComboBox::AdjustToContents</enum>
|
||||
</property>
|
||||
<property name="minimumContentsLength">
|
||||
<number>24</number>
|
||||
|
@ -580,7 +580,7 @@
|
|||
</sizepolicy>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QComboBox::AdjustToMinimumContentsLength</enum>
|
||||
<enum>QComboBox::AdjustToContents</enum>
|
||||
</property>
|
||||
<property name="minimumContentsLength">
|
||||
<number>24</number>
|
||||
|
@ -596,7 +596,7 @@
|
|||
</sizepolicy>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QComboBox::AdjustToMinimumContentsLength</enum>
|
||||
<enum>QComboBox::AdjustToContents</enum>
|
||||
</property>
|
||||
<property name="minimumContentsLength">
|
||||
<number>24</number>
|
||||
|
@ -664,7 +664,7 @@
|
|||
</sizepolicy>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QComboBox::AdjustToMinimumContentsLength</enum>
|
||||
<enum>QComboBox::AdjustToContents</enum>
|
||||
</property>
|
||||
<property name="minimumContentsLength">
|
||||
<number>24</number>
|
||||
|
@ -803,7 +803,7 @@
|
|||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>lcQMinifigDialog</receiver>
|
||||
<receiver>lcMinifigDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
|
@ -819,7 +819,7 @@
|
|||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>lcQMinifigDialog</receiver>
|
||||
<receiver>lcMinifigDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
File diff suppressed because it is too large
Load diff
|
@ -1,8 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include "lc_math.h"
|
||||
#include "object.h"
|
||||
#include "lc_commands.h"
|
||||
#include "lc_array.h"
|
||||
|
||||
#define LC_SEL_NO_PIECES 0x0001 // No pieces in model
|
||||
#define LC_SEL_PIECE 0x0002 // At last 1 piece selected
|
||||
|
@ -18,8 +18,6 @@
|
|||
#define LC_SEL_CAN_ADD_CONTROL_POINT 0x0800 // Can add control points to focused piece
|
||||
#define LC_SEL_CAN_REMOVE_CONTROL_POINT 0x1000 // Can remove control points from focused piece
|
||||
|
||||
class lcGLWidget;
|
||||
|
||||
enum class lcSelectionMode
|
||||
{
|
||||
Single,
|
||||
|
@ -38,30 +36,18 @@ enum class lcTransformType
|
|||
Count
|
||||
};
|
||||
|
||||
enum lcBackgroundType
|
||||
{
|
||||
LC_BACKGROUND_SOLID,
|
||||
LC_BACKGROUND_GRADIENT,
|
||||
LC_BACKGROUND_IMAGE
|
||||
};
|
||||
|
||||
class lcModelProperties
|
||||
{
|
||||
public:
|
||||
void LoadDefaults();
|
||||
void SaveDefaults();
|
||||
|
||||
bool operator==(const lcModelProperties& Properties)
|
||||
bool operator==(const lcModelProperties& Properties) const
|
||||
{
|
||||
if (mFileName != Properties.mFileName || mModelName != Properties.mModelName || mAuthor != Properties.mAuthor ||
|
||||
mDescription != Properties.mDescription || mComments != Properties.mComments)
|
||||
return false;
|
||||
|
||||
if (mBackgroundType != Properties.mBackgroundType || mBackgroundSolidColor != Properties.mBackgroundSolidColor ||
|
||||
mBackgroundGradientColor1 != Properties.mBackgroundGradientColor1 || mBackgroundGradientColor2 != Properties.mBackgroundGradientColor2 ||
|
||||
mBackgroundImage != Properties.mBackgroundImage || mBackgroundImageTile != Properties.mBackgroundImageTile)
|
||||
return false;
|
||||
|
||||
if (mAmbientColor != Properties.mAmbientColor)
|
||||
return false;
|
||||
|
||||
|
@ -78,13 +64,6 @@ public:
|
|||
QString mAuthor;
|
||||
QString mComments;
|
||||
|
||||
lcBackgroundType mBackgroundType;
|
||||
lcVector3 mBackgroundSolidColor;
|
||||
lcVector3 mBackgroundGradientColor1;
|
||||
lcVector3 mBackgroundGradientColor2;
|
||||
QString mBackgroundImage;
|
||||
bool mBackgroundImageTile;
|
||||
|
||||
lcVector3 mAmbientColor;
|
||||
};
|
||||
|
||||
|
@ -97,24 +76,33 @@ struct lcModelHistoryEntry
|
|||
class lcModel
|
||||
{
|
||||
public:
|
||||
lcModel(const QString& FileName);
|
||||
lcModel(const QString& FileName, Project* Project, bool Preview);
|
||||
~lcModel();
|
||||
|
||||
lcModel(const lcModel&) = delete;
|
||||
lcModel(lcModel&&) = delete;
|
||||
lcModel& operator=(const lcModel&) = delete;
|
||||
lcModel& operator=(lcModel&&) = delete;
|
||||
|
||||
Project* GetProject() const
|
||||
{
|
||||
return mProject;
|
||||
}
|
||||
|
||||
bool IsModified() const
|
||||
{
|
||||
return mSavedHistory != mUndoHistory[0];
|
||||
}
|
||||
|
||||
bool IsActive() const
|
||||
{
|
||||
return mActive;
|
||||
}
|
||||
|
||||
bool GetPieceWorldMatrix(lcPiece* Piece, lcMatrix44& ParentWorldMatrix) const;
|
||||
bool IncludesModel(const lcModel* Model) const;
|
||||
void CreatePieceInfo(Project* Project);
|
||||
void UpdatePieceInfo(std::vector<lcModel*>& UpdatedModels);
|
||||
void UpdateMesh();
|
||||
void UpdateAllViews() const;
|
||||
|
||||
PieceInfo* GetPieceInfo() const
|
||||
{
|
||||
|
@ -228,27 +216,31 @@ public:
|
|||
if (mUndoHistory.empty())
|
||||
SaveCheckpoint(QString());
|
||||
|
||||
mSavedHistory = mUndoHistory[0];
|
||||
if (!mIsPreview)
|
||||
mSavedHistory = mUndoHistory[0];
|
||||
}
|
||||
|
||||
void SetMinifig(const lcMinifig& Minifig);
|
||||
void SetPreviewPieceInfo(PieceInfo* Info, int ColorIndex);
|
||||
|
||||
void Cut();
|
||||
void Copy();
|
||||
void Paste();
|
||||
void Paste(bool PasteToCurrentStep);
|
||||
void DuplicateSelectedPieces();
|
||||
void PaintSelectedPieces();
|
||||
|
||||
void GetScene(lcScene& Scene, lcCamera* ViewCamera, bool AllowHighlight, bool AllowFade) const;
|
||||
void AddSubModelRenderMeshes(lcScene& Scene, const lcMatrix44& WorldMatrix, int DefaultColorIndex, lcRenderMeshState RenderMeshState, bool ParentActive) const;
|
||||
void DrawBackground(lcGLWidget* Widget);
|
||||
void GetScene(lcScene* Scene, lcCamera* ViewCamera, bool AllowHighlight, bool AllowFade) const;
|
||||
void AddSubModelRenderMeshes(lcScene* Scene, const lcMatrix44& WorldMatrix, int DefaultColorIndex, lcRenderMeshState RenderMeshState, bool ParentActive) const;
|
||||
QImage GetStepImage(bool Zoom, int Width, int Height, lcStep Step);
|
||||
QImage GetPartsListImage(int MaxWidth, lcStep Step) const;
|
||||
QImage GetPartsListImage(int MaxWidth, lcStep Step, quint32 BackgroundColor, QFont Font, QColor TextColor) const;
|
||||
void SaveStepImages(const QString& BaseName, bool AddStepSuffix, bool Zoom, int Width, int Height, lcStep Start, lcStep End);
|
||||
std::vector<std::pair<lcModel*, lcStep>> GetPageLayouts(std::vector<const lcModel*>& AddedModels);
|
||||
|
||||
void RayTest(lcObjectRayTest& ObjectRayTest) const;
|
||||
void BoxTest(lcObjectBoxTest& ObjectBoxTest) const;
|
||||
bool SubModelMinIntersectDist(const lcVector3& WorldStart, const lcVector3& WorldEnd, float& MinDistance) const;
|
||||
bool SubModelBoxTest(const lcVector4 Planes[6]) const;
|
||||
void SubModelCompareBoundingBox(const lcMatrix44& WorldMatrix, lcVector3& Min, lcVector3& Max) const;
|
||||
void SubModelAddBoundingBoxPoints(const lcMatrix44& WorldMatrix, std::vector<lcVector3>& Points) const;
|
||||
|
||||
bool HasPieces() const
|
||||
{
|
||||
|
@ -266,6 +258,7 @@ public:
|
|||
lcObject* GetFocusObject() const;
|
||||
bool GetSelectionCenter(lcVector3& Center) const;
|
||||
bool GetPiecesBoundingBox(lcVector3& Min, lcVector3& Max) const;
|
||||
std::vector<lcVector3> GetPiecesBoundingBoxPoints() const;
|
||||
void GetPartsList(int DefaultColorIndex, bool ScanSubModels, bool AddSubModels, lcPartsList& PartsList) const;
|
||||
void GetPartsListForStep(lcStep Step, int DefaultColorIndex, lcPartsList& PartsList) const;
|
||||
void GetModelParts(const lcMatrix44& WorldMatrix, int DefaultColorIndex, std::vector<lcModelPartsEntry>& ModelParts) const;
|
||||
|
@ -288,7 +281,7 @@ public:
|
|||
void UnhideSelectedPieces();
|
||||
void UnhideAllPieces();
|
||||
|
||||
void FindPiece(bool FindFirst, bool SearchForward);
|
||||
void FindReplacePiece(bool SearchForward, bool FindAll);
|
||||
|
||||
void UndoAction();
|
||||
void RedoAction();
|
||||
|
@ -344,11 +337,10 @@ public:
|
|||
void SetCameraFOV(lcCamera* Camera, float FOV);
|
||||
void SetCameraZNear(lcCamera* Camera, float ZNear);
|
||||
void SetCameraZFar(lcCamera* Camera, float ZFar);
|
||||
void SetCameraName(lcCamera* Camera, const char* Name);
|
||||
void SetCameraName(lcCamera* Camera, const QString& Name);
|
||||
|
||||
void ShowPropertiesDialog();
|
||||
void ShowSelectByNameDialog();
|
||||
void ShowSelectByColorDialog();
|
||||
void ShowArrayDialog();
|
||||
void ShowMinifigDialog();
|
||||
void UpdateInterface();
|
||||
|
@ -363,20 +355,19 @@ protected:
|
|||
void RemoveEmptyGroups();
|
||||
bool RemoveSelectedObjects();
|
||||
|
||||
void UpdateBackgroundTexture();
|
||||
|
||||
void SelectGroup(lcGroup* TopGroup, bool Select);
|
||||
|
||||
void AddPiece(lcPiece* Piece);
|
||||
void InsertPiece(lcPiece* Piece, int Index);
|
||||
|
||||
lcModelProperties mProperties;
|
||||
Project* const mProject;
|
||||
PieceInfo* mPieceInfo;
|
||||
|
||||
bool mIsPreview;
|
||||
bool mActive;
|
||||
lcStep mCurrentStep;
|
||||
lcVector3 mMouseToolDistance;
|
||||
lcTexture* mBackgroundTexture;
|
||||
|
||||
lcArray<lcPiece*> mPieces;
|
||||
lcArray<lcCamera*> mCameras;
|
||||
|
@ -390,4 +381,3 @@ protected:
|
|||
|
||||
Q_DECLARE_TR_FUNCTIONS(lcModel);
|
||||
};
|
||||
|
||||
|
|
34
common/lc_pagesetupdialog.cpp
Normal file
34
common/lc_pagesetupdialog.cpp
Normal file
|
@ -0,0 +1,34 @@
|
|||
#include "lc_global.h"
|
||||
#include "lc_pagesetupdialog.h"
|
||||
#include "ui_lc_pagesetupdialog.h"
|
||||
#include "lc_instructions.h"
|
||||
|
||||
lcPageSetupDialog::lcPageSetupDialog(QWidget* Parent, lcInstructionsPageSetup* PageSetup)
|
||||
: QDialog(Parent), ui(new Ui::lcPageSetupDialog), mPageSetup(PageSetup)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
ui->WidthEdit->setText(QString::number(PageSetup->Width));
|
||||
ui->HeightEdit->setText(QString::number(PageSetup->Height));
|
||||
ui->LeftEdit->setText(QString::number(PageSetup->MarginLeft));
|
||||
ui->RightEdit->setText(QString::number(PageSetup->MarginRight));
|
||||
ui->TopEdit->setText(QString::number(PageSetup->MarginTop));
|
||||
ui->BottomEdit->setText(QString::number(PageSetup->MarginBottom));
|
||||
}
|
||||
|
||||
lcPageSetupDialog::~lcPageSetupDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void lcPageSetupDialog::accept()
|
||||
{
|
||||
mPageSetup->Width = ui->WidthEdit->text().toFloat();
|
||||
mPageSetup->Height = ui->HeightEdit->text().toFloat();
|
||||
mPageSetup->MarginLeft = ui->LeftEdit->text().toFloat();
|
||||
mPageSetup->MarginRight = ui->RightEdit->text().toFloat();
|
||||
mPageSetup->MarginTop = ui->TopEdit->text().toFloat();
|
||||
mPageSetup->MarginBottom = ui->BottomEdit->text().toFloat();
|
||||
|
||||
QDialog::accept();
|
||||
}
|
22
common/lc_pagesetupdialog.h
Normal file
22
common/lc_pagesetupdialog.h
Normal file
|
@ -0,0 +1,22 @@
|
|||
#pragma once
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class lcPageSetupDialog;
|
||||
}
|
||||
|
||||
class lcPageSetupDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
lcPageSetupDialog(QWidget* Parent, lcInstructionsPageSetup* PageSetup);
|
||||
~lcPageSetupDialog();
|
||||
|
||||
public slots:
|
||||
void accept() override;
|
||||
|
||||
private:
|
||||
Ui::lcPageSetupDialog *ui;
|
||||
lcInstructionsPageSetup* mPageSetup;
|
||||
};
|
190
common/lc_pagesetupdialog.ui
Normal file
190
common/lc_pagesetupdialog.ui
Normal file
|
@ -0,0 +1,190 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>lcPageSetupDialog</class>
|
||||
<widget class="QDialog" name="lcPageSetupDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Page Setup</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Size</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="3">
|
||||
<widget class="QLineEdit" name="HeightEdit"/>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="WidthEdit"/>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Width:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>WidthEdit</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Height:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>HeightEdit</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Preset:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1" colspan="3">
|
||||
<widget class="QComboBox" name="comboBox"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>Units:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" colspan="3">
|
||||
<widget class="QComboBox" name="comboBox_2"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Margins</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Left:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>LeftEdit</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="LeftEdit"/>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Right:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>RightEdit</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QLineEdit" name="RightEdit"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Top:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>TopEdit</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="TopEdit"/>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Bottom:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>BottomEdit</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="3">
|
||||
<widget class="QLineEdit" name="BottomEdit"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>WidthEdit</tabstop>
|
||||
<tabstop>HeightEdit</tabstop>
|
||||
<tabstop>comboBox_2</tabstop>
|
||||
<tabstop>comboBox</tabstop>
|
||||
<tabstop>LeftEdit</tabstop>
|
||||
<tabstop>RightEdit</tabstop>
|
||||
<tabstop>TopEdit</tabstop>
|
||||
<tabstop>BottomEdit</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>lcPageSetupDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>227</x>
|
||||
<y>282</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>lcPageSetupDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>295</x>
|
||||
<y>288</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
|
@ -9,10 +9,6 @@ lcPartPaletteDialog::lcPartPaletteDialog(QWidget* Parent, std::vector<lcPartPale
|
|||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
#if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
|
||||
ui->ImportButton->hide();
|
||||
#endif
|
||||
|
||||
for (const lcPartPalette& Palette : PartPalettes)
|
||||
{
|
||||
QListWidgetItem* Item = new QListWidgetItem(Palette.Name);
|
||||
|
@ -128,7 +124,6 @@ void lcPartPaletteDialog::on_ImportButton_clicked()
|
|||
Palette->Name = Dialog.GetSetDescription();
|
||||
mImportedPalettes.push_back(Palette);
|
||||
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
|
||||
QByteArray Inventory = Dialog.GetSetInventory();
|
||||
QJsonDocument Document = QJsonDocument::fromJson(Inventory);
|
||||
QJsonObject Root = Document.object();
|
||||
|
@ -144,7 +139,6 @@ void lcPartPaletteDialog::on_ImportButton_clicked()
|
|||
|
||||
Palette->Parts.push_back(PartID.toUpper().toStdString() + ".DAT");
|
||||
}
|
||||
#endif
|
||||
|
||||
QListWidgetItem* Item = new QListWidgetItem(Palette->Name);
|
||||
Item->setData(Qt::UserRole, QVariant::fromValue<uintptr_t>(reinterpret_cast<uintptr_t>(Palette)));
|
||||
|
|
|
@ -8,10 +8,13 @@
|
|||
#include "lc_model.h"
|
||||
#include "project.h"
|
||||
#include "pieceinf.h"
|
||||
#include "view.h"
|
||||
#include "camera.h"
|
||||
#include "lc_scene.h"
|
||||
#include "lc_view.h"
|
||||
#include "lc_glextensions.h"
|
||||
#include "lc_category.h"
|
||||
|
||||
Q_DECLARE_METATYPE(QList<int>)
|
||||
Q_DECLARE_METATYPE(QList<int>)
|
||||
|
||||
void lcPartSelectionItemDelegate::paint(QPainter* Painter, const QStyleOptionViewItem& Option, const QModelIndex& Index) const
|
||||
{
|
||||
|
@ -63,6 +66,9 @@ lcPartSelectionListModel::lcPartSelectionListModel(QObject* Parent)
|
|||
lcPartSelectionListModel::~lcPartSelectionListModel()
|
||||
{
|
||||
ClearRequests();
|
||||
|
||||
mView.reset();
|
||||
mModel.reset();
|
||||
}
|
||||
|
||||
void lcPartSelectionListModel::ClearRequests()
|
||||
|
@ -383,67 +389,56 @@ void lcPartSelectionListModel::PartLoaded(PieceInfo* Info)
|
|||
|
||||
void lcPartSelectionListModel::DrawPreview(int InfoIndex)
|
||||
{
|
||||
View* ActiveView = gMainWindow->GetActiveView();
|
||||
if (!ActiveView)
|
||||
return;
|
||||
const int Width = mIconSize * 2;
|
||||
const int Height = mIconSize * 2;
|
||||
|
||||
ActiveView->MakeCurrent();
|
||||
lcContext* Context = ActiveView->mContext;
|
||||
int Width = mIconSize * 2;
|
||||
int Height = mIconSize * 2;
|
||||
if (mView && (mView->GetWidth() != Width || mView->GetHeight() != Height))
|
||||
mView.reset();
|
||||
|
||||
if (mRenderFramebuffer.first.mWidth != Width || mRenderFramebuffer.first.mHeight != Height)
|
||||
if (!mView)
|
||||
{
|
||||
Context->DestroyRenderFramebuffer(mRenderFramebuffer);
|
||||
mRenderFramebuffer = Context->CreateRenderFramebuffer(Width, Height);
|
||||
if (!mModel)
|
||||
mModel = std::unique_ptr<lcModel>(new lcModel(QString(), nullptr, true));
|
||||
mView = std::unique_ptr<lcView>(new lcView(lcViewType::PartsList, mModel.get()));
|
||||
|
||||
mView->SetOffscreenContext();
|
||||
mView->MakeCurrent();
|
||||
mView->SetSize(Width, Height);
|
||||
|
||||
if (!mView->BeginRenderToImage(Width, Height))
|
||||
{
|
||||
mView.reset();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!mRenderFramebuffer.first.IsValid())
|
||||
return;
|
||||
mView->MakeCurrent();
|
||||
mView->BindRenderFramebuffer();
|
||||
|
||||
float Aspect = (float)Width / (float)Height;
|
||||
Context->SetViewport(0, 0, Width, Height);
|
||||
const uint BackgroundColor = mListView->palette().color(QPalette::Base).rgba();
|
||||
mView->SetBackgroundColorOverride(LC_RGBA(qRed(BackgroundColor), qGreen(BackgroundColor), qBlue(BackgroundColor), 0));
|
||||
|
||||
Context->SetDefaultState();
|
||||
Context->BindFramebuffer(mRenderFramebuffer.first);
|
||||
|
||||
lcPiecesLibrary* Library = lcGetPiecesLibrary();
|
||||
PieceInfo* Info = mParts[InfoIndex].first;
|
||||
mModel->SetPreviewPieceInfo(Info, mColorIndex);
|
||||
|
||||
glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
lcMatrix44 ProjectionMatrix, ViewMatrix;
|
||||
const lcVector3 Center = (Info->GetBoundingBox().Min + Info->GetBoundingBox().Max) / 2.0f;
|
||||
const lcVector3 Position = Center + lcVector3(100.0f, -100.0f, 75.0f);
|
||||
|
||||
Info->ZoomExtents(20.0f, Aspect, ProjectionMatrix, ViewMatrix);
|
||||
mView->GetCamera()->SetViewpoint(Position, Center, lcVector3(0, 0, 1));
|
||||
mView->GetCamera()->m_fovy = 20.0f;
|
||||
mView->ZoomExtents();
|
||||
|
||||
Context->SetProjectionMatrix(ProjectionMatrix);
|
||||
mView->OnDraw();
|
||||
|
||||
lcScene Scene;
|
||||
Scene.SetAllowWireframe(false);
|
||||
Scene.SetAllowLOD(false);
|
||||
Scene.Begin(ViewMatrix);
|
||||
mView->UnbindRenderFramebuffer();
|
||||
|
||||
Info->AddRenderMeshes(Scene, lcMatrix44Identity(), mColorIndex, lcRenderMeshState::Default, false);
|
||||
QImage Image = mView->GetRenderFramebufferImage().convertToFormat(QImage::Format_ARGB32);
|
||||
|
||||
Scene.End();
|
||||
mParts[InfoIndex].second = QPixmap::fromImage(Image).scaled(mIconSize, mIconSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
|
||||
|
||||
Scene.Draw(Context);
|
||||
lcGetPiecesLibrary()->ReleasePieceInfo(Info);
|
||||
|
||||
mParts[InfoIndex].second = QPixmap::fromImage(Context->GetRenderFramebufferImage(mRenderFramebuffer)).scaled(mIconSize, mIconSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
|
||||
|
||||
Library->ReleasePieceInfo(Info);
|
||||
|
||||
Context->ClearFramebuffer();
|
||||
Context->ClearResources();
|
||||
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 2, 0))
|
||||
QVector<int> Roles;
|
||||
Roles.append(Qt::DecorationRole);
|
||||
emit dataChanged(index(InfoIndex, 0), index(InfoIndex, 0), Roles);
|
||||
#else
|
||||
emit dataChanged(index(InfoIndex, 0), index(InfoIndex, 0));
|
||||
#endif
|
||||
emit dataChanged(index(InfoIndex, 0), index(InfoIndex, 0), QVector<int>() << Qt::DecorationRole);
|
||||
}
|
||||
|
||||
void lcPartSelectionListModel::SetShowDecoratedParts(bool Show)
|
||||
|
@ -514,9 +509,7 @@ lcPartSelectionListView::lcPartSelectionListView(QWidget* Parent, lcPartSelectio
|
|||
lcPartSelectionItemDelegate* ItemDelegate = new lcPartSelectionItemDelegate(this, mListModel);
|
||||
setItemDelegate(ItemDelegate);
|
||||
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
|
||||
connect(this, SIGNAL(customContextMenuRequested(QPoint)), SLOT(CustomContextMenuRequested(QPoint)));
|
||||
#endif
|
||||
|
||||
SetIconSize(lcGetProfileInt(LC_PROFILE_PARTS_LIST_ICONS));
|
||||
}
|
||||
|
@ -572,9 +565,9 @@ void lcPartSelectionListView::SetCategory(lcPartCategoryType Type, int Index)
|
|||
case lcPartCategoryType::Category:
|
||||
mListModel->SetCategory(Index);
|
||||
break;
|
||||
case lcPartCategoryType::Count:
|
||||
break;
|
||||
}
|
||||
case lcPartCategoryType::Count:
|
||||
break;
|
||||
}
|
||||
|
||||
setCurrentIndex(mListModel->index(0, 0));
|
||||
}
|
||||
|
@ -680,6 +673,26 @@ void lcPartSelectionListView::startDrag(Qt::DropActions SupportedActions)
|
|||
Drag->exec(Qt::CopyAction);
|
||||
}
|
||||
|
||||
void lcPartSelectionListView::mouseDoubleClickEvent(QMouseEvent* MouseEvent)
|
||||
{
|
||||
if (MouseEvent->button() == Qt::LeftButton )
|
||||
PreviewSelection(currentIndex().row());
|
||||
|
||||
QListView::mouseDoubleClickEvent(MouseEvent);
|
||||
}
|
||||
|
||||
void lcPartSelectionListView::PreviewSelection(int InfoIndex)
|
||||
{
|
||||
PieceInfo* Info = mListModel->GetPieceInfo(InfoIndex);
|
||||
|
||||
if (!Info)
|
||||
return;
|
||||
|
||||
quint32 ColorCode = lcGetColorCode(mListModel->GetColorIndex());
|
||||
|
||||
gMainWindow->PreviewPiece(Info->mFileName, ColorCode, true);
|
||||
}
|
||||
|
||||
lcPartSelectionWidget::lcPartSelectionWidget(QWidget* Parent)
|
||||
: QWidget(Parent), mFilterAction(nullptr)
|
||||
{
|
||||
|
@ -704,10 +717,8 @@ lcPartSelectionWidget::lcPartSelectionWidget(QWidget* Parent)
|
|||
|
||||
mFilterWidget = new QLineEdit(PartsGroupWidget);
|
||||
mFilterWidget->setPlaceholderText(tr("Search Parts"));
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 2, 0))
|
||||
mFilterAction = mFilterWidget->addAction(QIcon(":/resources/parts_search.png"), QLineEdit::TrailingPosition);
|
||||
connect(mFilterAction, SIGNAL(triggered()), this, SLOT(FilterTriggered()));
|
||||
#endif
|
||||
SearchLayout->addWidget(mFilterWidget);
|
||||
|
||||
QToolButton* OptionsButton = new QToolButton();
|
||||
|
@ -866,7 +877,7 @@ void lcPartSelectionWidget::OptionsMenuAboutToShow()
|
|||
|
||||
lcPartSelectionListModel* ListModel = mPartsWidget->GetListModel();
|
||||
|
||||
if (gSupportsFramebufferObjectARB || gSupportsFramebufferObjectEXT)
|
||||
if (gSupportsFramebufferObject)
|
||||
{
|
||||
QActionGroup* IconGroup = new QActionGroup(Menu);
|
||||
|
||||
|
@ -957,7 +968,6 @@ void lcPartSelectionWidget::SetDefaultPart()
|
|||
|
||||
void lcPartSelectionWidget::LoadPartPalettes()
|
||||
{
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
|
||||
QByteArray Buffer = lcGetProfileBuffer(LC_PROFILE_PART_PALETTES);
|
||||
QJsonDocument Document = QJsonDocument::fromJson(Buffer);
|
||||
|
||||
|
@ -988,12 +998,10 @@ void lcPartSelectionWidget::LoadPartPalettes()
|
|||
|
||||
mPartPalettes.emplace_back(std::move(Palette));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void lcPartSelectionWidget::SavePartPalettes()
|
||||
{
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
|
||||
QJsonObject RootObject;
|
||||
|
||||
RootObject["Version"] = 1;
|
||||
|
@ -1013,7 +1021,6 @@ void lcPartSelectionWidget::SavePartPalettes()
|
|||
|
||||
QByteArray Buffer = QJsonDocument(RootObject).toJson();
|
||||
lcSetProfileBuffer(LC_PROFILE_PART_PALETTES, Buffer);
|
||||
#endif
|
||||
}
|
||||
|
||||
void lcPartSelectionWidget::AddToPalette()
|
||||
|
|
|
@ -88,6 +88,11 @@ public:
|
|||
return mShowPartNames;
|
||||
}
|
||||
|
||||
int GetColorIndex() const
|
||||
{
|
||||
return mColorIndex;
|
||||
}
|
||||
|
||||
bool IsColorLocked() const
|
||||
{
|
||||
return mColorLocked;
|
||||
|
@ -131,7 +136,8 @@ protected:
|
|||
bool mShowDecoratedParts;
|
||||
bool mShowPartAliases;
|
||||
QByteArray mFilter;
|
||||
std::pair<lcFramebuffer, lcFramebuffer> mRenderFramebuffer;
|
||||
std::unique_ptr<lcView> mView;
|
||||
std::unique_ptr<lcModel> mModel;
|
||||
};
|
||||
|
||||
class lcPartSelectionListView : public QListView
|
||||
|
@ -182,6 +188,8 @@ public slots:
|
|||
|
||||
protected:
|
||||
void SetIconSize(int Size);
|
||||
void PreviewSelection(int InfoIndex);
|
||||
void mouseDoubleClickEvent(QMouseEvent* MouseEvent) override;
|
||||
|
||||
lcPartSelectionListModel* mListModel;
|
||||
lcPartSelectionWidget* mPartSelectionWidget;
|
||||
|
|
175
common/lc_previewwidget.cpp
Normal file
175
common/lc_previewwidget.cpp
Normal file
|
@ -0,0 +1,175 @@
|
|||
#include "lc_global.h"
|
||||
#include "lc_previewwidget.h"
|
||||
#include "pieceinf.h"
|
||||
#include "piece.h"
|
||||
#include "project.h"
|
||||
#include "lc_model.h"
|
||||
#include "lc_library.h"
|
||||
#include "lc_viewwidget.h"
|
||||
#include "lc_view.h"
|
||||
|
||||
lcPreviewDockWidget::lcPreviewDockWidget(QMainWindow* Parent)
|
||||
: QMainWindow(Parent)
|
||||
{
|
||||
mPreview = new lcPreview();
|
||||
mViewWidget = new lcViewWidget(nullptr, mPreview);
|
||||
setCentralWidget(mViewWidget);
|
||||
setMinimumSize(200, 200);
|
||||
|
||||
mLockAction = new QAction(QIcon(":/resources/action_preview_unlocked.png"),tr("Lock Preview"), this);
|
||||
mLockAction->setCheckable(true);
|
||||
mLockAction->setChecked(false);
|
||||
mLockAction->setShortcut(tr("Ctrl+L"));
|
||||
connect(mLockAction, SIGNAL(triggered()), this, SLOT(SetPreviewLock()));
|
||||
SetPreviewLock();
|
||||
|
||||
mLabel = new QLabel();
|
||||
|
||||
mToolBar = addToolBar(tr("Toolbar"));
|
||||
mToolBar->setObjectName("Toolbar");
|
||||
mToolBar->setStatusTip(tr("Preview Toolbar"));
|
||||
mToolBar->setMovable(false);
|
||||
mToolBar->addAction(mLockAction);
|
||||
mToolBar->addSeparator();
|
||||
mToolBar->addWidget(mLabel);
|
||||
if (mToolBar->isHidden())
|
||||
mToolBar->show();
|
||||
}
|
||||
|
||||
bool lcPreviewDockWidget::SetCurrentPiece(const QString& PartType, int ColorCode)
|
||||
{
|
||||
if (mLockAction->isChecked())
|
||||
return true;
|
||||
|
||||
mLabel->setText(tr("Loading..."));
|
||||
if (mPreview->SetCurrentPiece(PartType, ColorCode))
|
||||
{
|
||||
mLabel->setText(mPreview->GetDescription());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void lcPreviewDockWidget::UpdatePreview()
|
||||
{
|
||||
mPreview->UpdatePreview();
|
||||
}
|
||||
|
||||
void lcPreviewDockWidget::ClearPreview()
|
||||
{
|
||||
if (mPreview->GetModel()->GetPieces().GetSize())
|
||||
mPreview->ClearPreview();
|
||||
|
||||
mLabel->setText(QString());
|
||||
}
|
||||
|
||||
void lcPreviewDockWidget::SetPreviewLock()
|
||||
{
|
||||
bool Locked = mLockAction->isChecked();
|
||||
|
||||
if (Locked && mPreview->GetModel()->GetPieces().IsEmpty())
|
||||
{
|
||||
mLockAction->setChecked(false);
|
||||
return;
|
||||
}
|
||||
|
||||
QIcon LockIcon(Locked ? ":/resources/action_preview_locked.png" : ":/resources/action_preview_unlocked.png");
|
||||
QString State(Locked ? tr("Unlock") : tr("Lock"));
|
||||
QString StatusTip(tr("%1 the preview display to %2 updates").arg(State).arg(Locked ? "enable" : "disable"));
|
||||
|
||||
mLockAction->setToolTip(tr("%1 Preview").arg(State));
|
||||
mLockAction->setIcon(LockIcon);
|
||||
mLockAction->setStatusTip(StatusTip);
|
||||
}
|
||||
|
||||
lcPreview::lcPreview()
|
||||
: lcView(lcViewType::Preview, nullptr), mLoader(new Project(true))
|
||||
{
|
||||
mLoader->SetActiveModel(0);
|
||||
mModel = mLoader->GetActiveModel();
|
||||
}
|
||||
|
||||
bool lcPreview::SetCurrentPiece(const QString& PartType, int ColorCode)
|
||||
{
|
||||
lcPiecesLibrary* Library = lcGetPiecesLibrary();
|
||||
PieceInfo* Info = Library->FindPiece(PartType.toLatin1().constData(), nullptr, false, false);
|
||||
|
||||
if (Info)
|
||||
{
|
||||
for (lcPiece* ModelPiece : mModel->GetPieces())
|
||||
{
|
||||
if (Info == ModelPiece->mPieceInfo)
|
||||
{
|
||||
int ModelColorCode = ModelPiece->GetColorCode();
|
||||
if (ModelColorCode == ColorCode)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
mIsModel = Info->IsModel();
|
||||
mDescription = Info->m_strDescription;
|
||||
|
||||
mModel->SelectAllPieces();
|
||||
mModel->DeleteSelectedObjects();
|
||||
|
||||
Library->LoadPieceInfo(Info, false, true);
|
||||
Library->WaitForLoadQueue();
|
||||
|
||||
mModel->SetPreviewPieceInfo(Info, lcGetColorIndex(ColorCode));
|
||||
|
||||
Library->ReleasePieceInfo(Info);
|
||||
}
|
||||
else
|
||||
{
|
||||
QString ModelPath = QString("%1/%2").arg(QDir::currentPath()).arg(PartType);
|
||||
|
||||
if (!mLoader->Load(ModelPath))
|
||||
{
|
||||
QMessageBox::warning(nullptr, QMessageBox::tr("Error"), QMessageBox::tr("Failed to load '%1'.").arg(ModelPath));
|
||||
return false;
|
||||
}
|
||||
|
||||
mLoader->SetActiveModel(0);
|
||||
lcGetPiecesLibrary()->RemoveTemporaryPieces();
|
||||
mModel = mLoader->GetActiveModel();
|
||||
if (!mModel->GetProperties().mDescription.isEmpty())
|
||||
mDescription = mModel->GetProperties().mDescription;
|
||||
else
|
||||
mDescription = PartType;
|
||||
mIsModel = true;
|
||||
}
|
||||
|
||||
ZoomExtents();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void lcPreview::ClearPreview()
|
||||
{
|
||||
mLoader = std::unique_ptr<Project>(new Project(true/*IsPreview*/));
|
||||
mLoader->SetActiveModel(0);
|
||||
mModel = mLoader->GetActiveModel();
|
||||
lcGetPiecesLibrary()->UnloadUnusedParts();
|
||||
Redraw();
|
||||
}
|
||||
|
||||
void lcPreview::UpdatePreview()
|
||||
{
|
||||
QString PartType;
|
||||
int ColorCode = -1;
|
||||
|
||||
for (lcPiece* ModelPiece : mModel->GetPieces())
|
||||
{
|
||||
if (ModelPiece->mPieceInfo)
|
||||
{
|
||||
PartType = ModelPiece->mPieceInfo->mFileName;
|
||||
ColorCode = ModelPiece->GetColorCode();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ClearPreview();
|
||||
|
||||
if (!PartType.isEmpty() && ColorCode > -1)
|
||||
SetCurrentPiece(PartType, ColorCode);
|
||||
}
|
53
common/lc_previewwidget.h
Normal file
53
common/lc_previewwidget.h
Normal file
|
@ -0,0 +1,53 @@
|
|||
#pragma once
|
||||
|
||||
#include "lc_view.h"
|
||||
|
||||
class lcPreview;
|
||||
|
||||
class lcPreviewDockWidget : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit lcPreviewDockWidget(QMainWindow* Parent = nullptr);
|
||||
|
||||
bool SetCurrentPiece(const QString& PartType, int ColorCode);
|
||||
void ClearPreview();
|
||||
void UpdatePreview();
|
||||
|
||||
protected slots:
|
||||
void SetPreviewLock();
|
||||
|
||||
protected:
|
||||
QAction* mLockAction;
|
||||
QToolBar* mToolBar;
|
||||
QLabel* mLabel;
|
||||
lcPreview* mPreview;
|
||||
lcViewWidget* mViewWidget;
|
||||
};
|
||||
|
||||
class lcPreview : public lcView
|
||||
{
|
||||
public:
|
||||
lcPreview();
|
||||
|
||||
QString GetDescription() const
|
||||
{
|
||||
return mDescription;
|
||||
}
|
||||
|
||||
bool IsModel() const
|
||||
{
|
||||
return mIsModel;
|
||||
}
|
||||
|
||||
void ClearPreview();
|
||||
void UpdatePreview();
|
||||
bool SetCurrentPiece(const QString& PartType, int ColorCode);
|
||||
|
||||
protected:
|
||||
std::unique_ptr<Project> mLoader;
|
||||
|
||||
QString mDescription;
|
||||
bool mIsModel = false;
|
||||
};
|
|
@ -4,6 +4,7 @@
|
|||
#include "image.h"
|
||||
#include "lc_model.h"
|
||||
#include "project.h"
|
||||
#include "lc_viewsphere.h"
|
||||
|
||||
lcProfileEntry::lcProfileEntry(const char* Section, const char* Key, int DefaultValue)
|
||||
{
|
||||
|
@ -58,27 +59,41 @@ static lcProfileEntry gProfileEntries[LC_NUM_PROFILE_KEYS] =
|
|||
lcProfileEntry("Settings", "FixedAxes", false), // LC_PROFILE_FIXED_AXES
|
||||
lcProfileEntry("Settings", "LineWidth", 1.0f), // LC_PROFILE_LINE_WIDTH
|
||||
lcProfileEntry("Settings", "AllowLOD", true), // LC_PROFILE_ALLOW_LOD
|
||||
lcProfileEntry("Settings", "LODDistance", 750.0f), // LC_PROFILE_LOD_DISTANCE
|
||||
lcProfileEntry("Settings", "FadeSteps", false), // LC_PROFILE_FADE_STEPS
|
||||
lcProfileEntry("Settings", "FadeStepsColor", LC_RGBA(128, 128, 128, 128)), // LC_PROFILE_FADE_STEPS_COLOR
|
||||
lcProfileEntry("Settings", "HighlightNewParts", 0), // LC_PROFILE_HIGHLIGHT_NEW_PARTS
|
||||
lcProfileEntry("Settings", "HighlightNewPartsColor", LC_RGBA(255, 242, 0, 192)), // LC_PROFILE_HIGHLIGHT_NEW_PARTS_COLOR
|
||||
lcProfileEntry("Settings", "ShadingMode", static_cast<int>(lcShadingMode::DefaultLights)), // LC_PROFILE_SHADING_MODE
|
||||
lcProfileEntry("Settings", "BackgroundGradient", false), // LC_PROFILE_BACKGROUND_GRADIENT
|
||||
lcProfileEntry("Settings", "BackgroundColor", LC_RGB(49, 52, 55)), // LC_PROFILE_BACKGROUND_COLOR
|
||||
lcProfileEntry("Settings", "GradientColorTop", LC_RGB(54, 72, 95)), // LC_PROFILE_GRADIENT_COLOR_TOP
|
||||
lcProfileEntry("Settings", "GradientColorBottom", LC_RGB(49, 52, 55)), // LC_PROFILE_GRADIENT_COLOR_BOTTOM
|
||||
lcProfileEntry("Settings", "DrawAxes", 0), // LC_PROFILE_DRAW_AXES
|
||||
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", "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
|
||||
lcProfileEntry("Settings", "ActiveViewColor", LC_RGBA(41, 128, 185, 255)), // LC_PROFILE_ACTIVE_VIEW_COLOR
|
||||
lcProfileEntry("Settings", "InactiveViewColor", LC_RGBA(69, 69, 69, 255)), // LC_PROFILE_INACTIVE_VIEW_COLOR
|
||||
lcProfileEntry("Settings", "DrawEdgeLines", 1), // LC_PROFILE_DRAW_EDGE_LINES
|
||||
lcProfileEntry("Settings", "GridStuds", 1), // LC_PROFILE_GRID_STUDS
|
||||
lcProfileEntry("Settings", "GridStudColor", LC_RGBA(64, 64, 64, 192)), // LC_PROFILE_GRID_STUD_COLOR
|
||||
lcProfileEntry("Settings", "GridStudColor", LC_RGBA(24, 24, 24, 192)), // LC_PROFILE_GRID_STUD_COLOR
|
||||
lcProfileEntry("Settings", "GridLines", 1), // LC_PROFILE_GRID_LINES
|
||||
lcProfileEntry("Settings", "GridLineSpacing", 5), // LC_PROFILE_GRID_LINE_SPACING
|
||||
lcProfileEntry("Settings", "GridLineColor", LC_RGBA(0, 0, 0, 255)), // LC_PROFILE_GRID_LINE_COLOR
|
||||
lcProfileEntry("Settings", "GridLineColor", LC_RGBA(24, 24, 24, 255)), // LC_PROFILE_GRID_LINE_COLOR
|
||||
lcProfileEntry("Settings", "GridOrigin", 0), // LC_PROFILE_GRID_ORIGIN
|
||||
lcProfileEntry("Settings", "AASamples", 1), // LC_PROFILE_ANTIALIASING_SAMPLES
|
||||
lcProfileEntry("Settings", "ViewSphereEnabled", 1), // LC_PROFILE_VIEW_SPHERE_ENABLED
|
||||
lcProfileEntry("Settings", "ViewSphereLocation", (int)lcViewSphereLocation::TopRight), // LC_PROFILE_VIEW_SPHERE_LOCATION
|
||||
lcProfileEntry("Settings", "ViewSphereSize", 100), // LC_PROFILE_VIEW_SPHERE_SIZE
|
||||
lcProfileEntry("Settings", "ViewSphereColor", LC_RGBA(255, 255, 255, 255)), // LC_PROFILE_VIEW_SPHERE_COLOR
|
||||
lcProfileEntry("Settings", "ViewSphereTextColor", LC_RGBA(0, 0, 0, 255)), // LC_PROFILE_VIEW_SPHERE_TEXT_COLOR
|
||||
lcProfileEntry("Settings", "ViewSphereHighlightColor", LC_RGBA(255, 0, 0, 255)), // LC_PROFILE_VIEW_SPHERE_HIGHLIGHT_COLOR
|
||||
lcProfileEntry("Settings", "ViewSphereColor", LC_RGBA(35, 38, 41, 255)), // LC_PROFILE_VIEW_SPHERE_COLOR
|
||||
lcProfileEntry("Settings", "ViewSphereTextColor", LC_RGBA(224, 224, 224, 255)), // LC_PROFILE_VIEW_SPHERE_TEXT_COLOR
|
||||
lcProfileEntry("Settings", "ViewSphereHighlightColor", LC_RGBA(41, 128, 185, 255)), // LC_PROFILE_VIEW_SPHERE_HIGHLIGHT_COLOR
|
||||
|
||||
lcProfileEntry("Settings", "Language", ""), // LC_PROFILE_LANGUAGE
|
||||
lcProfileEntry("Settings", "ColorTheme", static_cast<int>(lcColorTheme::Dark)), // LC_PROFILE_COLOR_THEME
|
||||
lcProfileEntry("Settings", "CheckUpdates", 1), // LC_PROFILE_CHECK_UPDATES
|
||||
lcProfileEntry("Settings", "ProjectsPath", ""), // LC_PROFILE_PROJECTS_PATH
|
||||
lcProfileEntry("Settings", "PartsLibrary", ""), // LC_PROFILE_PARTS_LIBRARY
|
||||
|
@ -105,18 +120,10 @@ static lcProfileEntry gProfileEntries[LC_NUM_PROFILE_KEYS] =
|
|||
lcProfileEntry("Settings", "PartsListDecorated", 1), // LC_PROFILE_PARTS_LIST_DECORATED
|
||||
lcProfileEntry("Settings", "PartsListAliases", 1), // LC_PROFILE_PARTS_LIST_ALIASES
|
||||
lcProfileEntry("Settings", "PartsListListMode", 0), // LC_PROFILE_PARTS_LIST_LISTMODE
|
||||
lcProfileEntry("Settings", "StudLogo", 0), // LC_PROFILE_STUD_LOGO
|
||||
lcProfileEntry("Settings", "StudStyle", 0), // LC_PROFILE_STUD_STYLE
|
||||
|
||||
lcProfileEntry("Defaults", "Author", ""), // LC_PROFILE_DEFAULT_AUTHOR_NAME
|
||||
lcProfileEntry("Defaults", "FloorColor", LC_RGB(0, 191, 0)), // LC_PROFILE_DEFAULT_FLOOR_COLOR
|
||||
lcProfileEntry("Defaults", "FloorTexture", ""), // LC_PROFILE_DEFAULT_FLOOR_TEXTURE
|
||||
lcProfileEntry("Defaults", "AmbientColor", LC_RGB(75, 75, 75)), // LC_PROFILE_DEFAULT_AMBIENT_COLOR
|
||||
lcProfileEntry("Defaults", "BackgroundType", LC_BACKGROUND_SOLID), // LC_PROFILE_DEFAULT_BACKGROUND_TYPE
|
||||
lcProfileEntry("Defaults", "BackgroundColor", LC_RGB(255, 255, 255)), // LC_PROFILE_DEFAULT_BACKGROUND_COLOR
|
||||
lcProfileEntry("Defaults", "GradientColor1", LC_RGB(0, 0, 191)), // LC_PROFILE_DEFAULT_GRADIENT_COLOR1
|
||||
lcProfileEntry("Defaults", "GradientColor2", LC_RGB(255, 255, 255)), // LC_PROFILE_DEFAULT_GRADIENT_COLOR2
|
||||
lcProfileEntry("Defaults", "BackgroundTexture", ""), // LC_PROFILE_DEFAULT_BACKGROUND_TEXTURE
|
||||
lcProfileEntry("Defaults", "BackgroundTile", 0), // LC_PROFILE_DEFAULT_BACKGROUND_TILE
|
||||
|
||||
lcProfileEntry("HTML", "Options", LC_HTML_SINGLEPAGE), // LC_PROFILE_HTML_OPTIONS
|
||||
lcProfileEntry("HTML", "ImageOptions", LC_IMAGE_TRANSPARENT), // LC_PROFILE_HTML_IMAGE_OPTIONS
|
||||
|
@ -126,7 +133,20 @@ static lcProfileEntry gProfileEntries[LC_NUM_PROFILE_KEYS] =
|
|||
lcProfileEntry("POVRay", "Path", "/usr/bin/povray"), // LC_PROFILE_POVRAY_PATH
|
||||
lcProfileEntry("POVRay", "LGEOPath", ""), // LC_PROFILE_POVRAY_LGEO_PATH
|
||||
lcProfileEntry("POVRay", "Width", 1280), // LC_PROFILE_POVRAY_WIDTH
|
||||
lcProfileEntry("POVRay", "Height", 720) // LC_PROFILE_POVRAY_HEIGHT
|
||||
lcProfileEntry("POVRay", "Height", 720), // LC_PROFILE_POVRAY_HEIGHT
|
||||
|
||||
lcProfileEntry("Settgins", "PreviewViewSphereEnabled", 0), // LC_PROFILE_PREVIEW_VIEW_SPHERE_ENABLED
|
||||
lcProfileEntry("Settings", "PreviewViewSphereSize", 75), // LC_PROFILE_PREVIEW_VIEW_SPHERE_SIZE
|
||||
lcProfileEntry("Settings", "PreviewViewSphereLocation", (int)lcViewSphereLocation::TopRight), // LC_PROFILE_PREVIEW_VIEW_SPHERE_LOCATION
|
||||
lcProfileEntry("Settings", "DrawPreviewAxis", 0), // LC_PROFILE_PREVIEW_DRAW_AXES
|
||||
|
||||
lcProfileEntry("Settings", "StudCylinderColor", LC_RGBA(27, 42, 52, 255)), // LC_PROFILE_STUD_CYLINDER_COLOR
|
||||
lcProfileEntry("Settings", "PartEdgeColor", LC_RGBA(0, 0, 0, 255)), // LC_PROFILE_PART_EDGE_COLOR
|
||||
lcProfileEntry("Settings", "BlackEdgeColor", LC_RGBA(255, 255, 255, 255)), // LC_PROFILE_BLACK_EDGE_COLOR
|
||||
lcProfileEntry("Settings", "DarkEdgeColor", LC_RGBA(27, 42, 52, 255)), // LC_PROFILE_DARK_EDGE_COLOR
|
||||
lcProfileEntry("Settings", "PartEdgeContrast", 0.5f), // LC_PROFILE_PART_EDGE_CONTRAST
|
||||
lcProfileEntry("Settings", "mPartColorValueLDIndex", 0.5f), // LC_PROFILE_PART_COLOR_VALUE_LD_INDEX
|
||||
lcProfileEntry("Settings", "AutomateEdgeColor", 0) // LC_PROFILE_AUTOMATE_EDGE_COLOR
|
||||
};
|
||||
|
||||
void lcRemoveProfileKey(LC_PROFILE_KEY Key)
|
||||
|
|
|
@ -6,18 +6,31 @@ enum LC_PROFILE_KEY
|
|||
LC_PROFILE_FIXED_AXES,
|
||||
LC_PROFILE_LINE_WIDTH,
|
||||
LC_PROFILE_ALLOW_LOD,
|
||||
LC_PROFILE_LOD_DISTANCE,
|
||||
LC_PROFILE_FADE_STEPS,
|
||||
LC_PROFILE_FADE_STEPS_COLOR,
|
||||
LC_PROFILE_HIGHLIGHT_NEW_PARTS,
|
||||
LC_PROFILE_HIGHLIGHT_NEW_PARTS_COLOR,
|
||||
LC_PROFILE_SHADING_MODE,
|
||||
LC_PROFILE_BACKGROUND_GRADIENT,
|
||||
LC_PROFILE_BACKGROUND_COLOR,
|
||||
LC_PROFILE_GRADIENT_COLOR_TOP,
|
||||
LC_PROFILE_GRADIENT_COLOR_BOTTOM,
|
||||
LC_PROFILE_DRAW_AXES,
|
||||
LC_PROFILE_AXES_COLOR,
|
||||
LC_PROFILE_TEXT_COLOR,
|
||||
LC_PROFILE_MARQUEE_BORDER_COLOR,
|
||||
LC_PROFILE_MARQUEE_FILL_COLOR,
|
||||
LC_PROFILE_OVERLAY_COLOR,
|
||||
LC_PROFILE_ACTIVE_VIEW_COLOR,
|
||||
LC_PROFILE_INACTIVE_VIEW_COLOR,
|
||||
LC_PROFILE_DRAW_EDGE_LINES,
|
||||
LC_PROFILE_GRID_STUDS,
|
||||
LC_PROFILE_GRID_STUD_COLOR,
|
||||
LC_PROFILE_GRID_LINES,
|
||||
LC_PROFILE_GRID_LINE_SPACING,
|
||||
LC_PROFILE_GRID_LINE_COLOR,
|
||||
LC_PROFILE_GRID_ORIGIN,
|
||||
LC_PROFILE_ANTIALIASING_SAMPLES,
|
||||
LC_PROFILE_VIEW_SPHERE_ENABLED,
|
||||
LC_PROFILE_VIEW_SPHERE_LOCATION,
|
||||
|
@ -27,6 +40,7 @@ enum LC_PROFILE_KEY
|
|||
LC_PROFILE_VIEW_SPHERE_HIGHLIGHT_COLOR,
|
||||
|
||||
LC_PROFILE_LANGUAGE,
|
||||
LC_PROFILE_COLOR_THEME,
|
||||
LC_PROFILE_CHECK_UPDATES,
|
||||
LC_PROFILE_PROJECTS_PATH,
|
||||
LC_PROFILE_PARTS_LIBRARY,
|
||||
|
@ -53,19 +67,11 @@ enum LC_PROFILE_KEY
|
|||
LC_PROFILE_PARTS_LIST_DECORATED,
|
||||
LC_PROFILE_PARTS_LIST_ALIASES,
|
||||
LC_PROFILE_PARTS_LIST_LISTMODE,
|
||||
LC_PROFILE_STUD_LOGO,
|
||||
LC_PROFILE_STUD_STYLE,
|
||||
|
||||
// Defaults for new projects.
|
||||
LC_PROFILE_DEFAULT_AUTHOR_NAME,
|
||||
LC_PROFILE_DEFAULT_FLOOR_COLOR,
|
||||
LC_PROFILE_DEFAULT_FLOOR_TEXTURE,
|
||||
LC_PROFILE_DEFAULT_AMBIENT_COLOR,
|
||||
LC_PROFILE_DEFAULT_BACKGROUND_TYPE,
|
||||
LC_PROFILE_DEFAULT_BACKGROUND_COLOR,
|
||||
LC_PROFILE_DEFAULT_GRADIENT_COLOR1,
|
||||
LC_PROFILE_DEFAULT_GRADIENT_COLOR2,
|
||||
LC_PROFILE_DEFAULT_BACKGROUND_TEXTURE,
|
||||
LC_PROFILE_DEFAULT_BACKGROUND_TILE,
|
||||
|
||||
// Exporters.
|
||||
LC_PROFILE_HTML_OPTIONS,
|
||||
|
@ -77,6 +83,19 @@ enum LC_PROFILE_KEY
|
|||
LC_PROFILE_POVRAY_WIDTH,
|
||||
LC_PROFILE_POVRAY_HEIGHT,
|
||||
|
||||
LC_PROFILE_PREVIEW_VIEW_SPHERE_ENABLED,
|
||||
LC_PROFILE_PREVIEW_VIEW_SPHERE_SIZE,
|
||||
LC_PROFILE_PREVIEW_VIEW_SPHERE_LOCATION,
|
||||
LC_PROFILE_PREVIEW_DRAW_AXES,
|
||||
|
||||
LC_PROFILE_STUD_CYLINDER_COLOR,
|
||||
LC_PROFILE_PART_EDGE_COLOR,
|
||||
LC_PROFILE_BLACK_EDGE_COLOR,
|
||||
LC_PROFILE_DARK_EDGE_COLOR,
|
||||
LC_PROFILE_PART_EDGE_CONTRAST,
|
||||
LC_PROFILE_PART_COLOR_VALUE_LD_INDEX,
|
||||
LC_PROFILE_AUTOMATE_EDGE_COLOR,
|
||||
|
||||
LC_NUM_PROFILE_KEYS
|
||||
};
|
||||
|
||||
|
@ -129,4 +148,3 @@ void lcSetProfileFloat(LC_PROFILE_KEY Key, float Value);
|
|||
void lcSetProfileString(LC_PROFILE_KEY Key, const QString& Value);
|
||||
void lcSetProfileStringList(LC_PROFILE_KEY Key, const QStringList& Value);
|
||||
void lcSetProfileBuffer(LC_PROFILE_KEY Key, const QByteArray& Buffer);
|
||||
|
||||
|
|
|
@ -12,8 +12,9 @@ lcScene::lcScene()
|
|||
{
|
||||
mActiveSubmodelInstance = nullptr;
|
||||
mDrawInterface = false;
|
||||
mAllowWireframe = true;
|
||||
mShadingMode = lcShadingMode::DefaultLights;
|
||||
mAllowLOD = true;
|
||||
mMeshLODDistance = 250.0f;
|
||||
mHasFadedParts = false;
|
||||
mPreTranslucentCallback = nullptr;
|
||||
}
|
||||
|
@ -69,7 +70,7 @@ void lcScene::AddMesh(lcMesh* Mesh, const lcMatrix44& WorldMatrix, int ColorInde
|
|||
RenderMesh.Mesh = Mesh;
|
||||
RenderMesh.ColorIndex = ColorIndex;
|
||||
RenderMesh.State = State;
|
||||
const float Distance = fabsf(lcMul31(WorldMatrix[3], mViewMatrix).z);
|
||||
const float Distance = fabsf(lcMul31(WorldMatrix[3], mViewMatrix).z) - mMeshLODDistance;
|
||||
RenderMesh.LodIndex = mAllowLOD ? RenderMesh.Mesh->GetLodIndex(Distance) : LC_MESH_LOD_HIGH;
|
||||
|
||||
const bool ForceTranslucent = (mTranslucentFade && State == lcRenderMeshState::Faded);
|
||||
|
@ -206,10 +207,20 @@ void lcScene::DrawOpaqueMeshes(lcContext* Context, bool DrawLit, int PrimitiveTy
|
|||
switch (RenderMesh.State)
|
||||
{
|
||||
case lcRenderMeshState::Default:
|
||||
if (ColorIndex == gEdgeColor)
|
||||
Context->SetEdgeColorIndex(RenderMesh.ColorIndex);
|
||||
if (mShadingMode != lcShadingMode::Wireframe)
|
||||
{
|
||||
if (ColorIndex != gEdgeColor)
|
||||
Context->SetColorIndex(ColorIndex);
|
||||
else
|
||||
Context->SetEdgeColorIndex(RenderMesh.ColorIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ColorIndex == gEdgeColor)
|
||||
ColorIndex = RenderMesh.ColorIndex;
|
||||
|
||||
Context->SetColorIndex(ColorIndex);
|
||||
}
|
||||
break;
|
||||
|
||||
case lcRenderMeshState::Selected:
|
||||
|
@ -422,11 +433,11 @@ void lcScene::Draw(lcContext* Context) const
|
|||
constexpr bool DrawConditional = false;
|
||||
const lcPreferences& Preferences = lcGetPreferences();
|
||||
|
||||
lcShadingMode ShadingMode = Preferences.mShadingMode;
|
||||
if (ShadingMode == lcShadingMode::Wireframe && !mAllowWireframe)
|
||||
ShadingMode = lcShadingMode::Flat;
|
||||
// lcShadingMode ShadingMode = Preferences.mShadingMode;
|
||||
// if (ShadingMode == lcShadingMode::Wireframe && !mAllowWireframe)
|
||||
// ShadingMode = lcShadingMode::Flat;
|
||||
|
||||
if (ShadingMode == lcShadingMode::Wireframe)
|
||||
if (mShadingMode == lcShadingMode::Wireframe)
|
||||
{
|
||||
int PrimitiveTypes = LC_MESH_LINES;
|
||||
|
||||
|
@ -438,7 +449,7 @@ void lcScene::Draw(lcContext* Context) const
|
|||
if (mPreTranslucentCallback)
|
||||
mPreTranslucentCallback();
|
||||
}
|
||||
else if (ShadingMode == lcShadingMode::Flat)
|
||||
else if (mShadingMode == lcShadingMode::Flat)
|
||||
{
|
||||
const bool DrawLines = Preferences.mDrawEdgeLines && Preferences.mLineWidth != 0.0f;
|
||||
|
||||
|
|
|
@ -59,9 +59,9 @@ public:
|
|||
return mDrawInterface;
|
||||
}
|
||||
|
||||
void SetAllowWireframe(bool AllowWireframe)
|
||||
void SetShadingMode(lcShadingMode ShadingMode)
|
||||
{
|
||||
mAllowWireframe = AllowWireframe;
|
||||
mShadingMode = ShadingMode;
|
||||
}
|
||||
|
||||
void SetAllowLOD(bool AllowLOD)
|
||||
|
@ -69,6 +69,11 @@ public:
|
|||
mAllowLOD = AllowLOD;
|
||||
}
|
||||
|
||||
void SetLODDistance(float Distance)
|
||||
{
|
||||
mMeshLODDistance = Distance;
|
||||
}
|
||||
|
||||
void SetPreTranslucentCallback(std::function<void()> Callback)
|
||||
{
|
||||
mPreTranslucentCallback = Callback;
|
||||
|
@ -99,9 +104,10 @@ protected:
|
|||
lcMatrix44 mViewMatrix;
|
||||
lcMatrix44 mActiveSubmodelTransform;
|
||||
lcPiece* mActiveSubmodelInstance;
|
||||
lcShadingMode mShadingMode;
|
||||
bool mDrawInterface;
|
||||
bool mAllowWireframe;
|
||||
bool mAllowLOD;
|
||||
float mMeshLODDistance;
|
||||
|
||||
lcVector4 mFadeColor;
|
||||
lcVector4 mHighlightColor;
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
#include "lc_global.h"
|
||||
#include "lc_selectbycolordialog.h"
|
||||
#include "lc_qcolorpicker.h"
|
||||
|
||||
lcSelectByColorDialog::lcSelectByColorDialog(QWidget* Parent, int ColorIndex)
|
||||
: QDialog(Parent), mColorIndex(ColorIndex)
|
||||
{
|
||||
setWindowTitle(tr("Select By Color"));
|
||||
|
||||
QVBoxLayout* MainLayout = new QVBoxLayout(this);
|
||||
|
||||
QHBoxLayout* ColorLayout = new QHBoxLayout();
|
||||
ColorLayout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
QLabel* ColorLabel = new QLabel(tr("Color:"), this);
|
||||
ColorLayout->addWidget(ColorLabel);
|
||||
|
||||
mColorPicker = new lcQColorPicker(this);
|
||||
mColorPicker->setCurrentColor(mColorIndex);
|
||||
ColorLayout->addWidget(mColorPicker);
|
||||
|
||||
MainLayout->addLayout(ColorLayout);
|
||||
|
||||
QDialogButtonBox* ButtonBox = new QDialogButtonBox(this);
|
||||
ButtonBox->setOrientation(Qt::Horizontal);
|
||||
ButtonBox->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok);
|
||||
|
||||
MainLayout->addWidget(ButtonBox);
|
||||
|
||||
QObject::connect(ButtonBox, SIGNAL(accepted()), this, SLOT(accept()));
|
||||
QObject::connect(ButtonBox, SIGNAL(rejected()), this, SLOT(reject()));
|
||||
}
|
||||
|
||||
lcSelectByColorDialog::~lcSelectByColorDialog()
|
||||
{
|
||||
}
|
||||
|
||||
void lcSelectByColorDialog::accept()
|
||||
{
|
||||
mColorIndex = mColorPicker->currentColor();
|
||||
|
||||
QDialog::accept();
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "lc_array.h"
|
||||
class lcQColorPicker;
|
||||
|
||||
class lcSelectByColorDialog : public QDialog
|
||||
{
|
||||
public:
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
lcSelectByColorDialog(QWidget* Parent, int ColorIndex);
|
||||
~lcSelectByColorDialog();
|
||||
|
||||
int mColorIndex;
|
||||
|
||||
public slots:
|
||||
void accept() override;
|
||||
|
||||
protected:
|
||||
lcQColorPicker* mColorPicker;
|
||||
};
|
||||
|
|
@ -132,30 +132,49 @@ void lcMouseShortcuts::Reset()
|
|||
{
|
||||
memset(mShortcuts, 0, sizeof(mShortcuts));
|
||||
|
||||
mShortcuts[LC_TOOL_ROTATE_VIEW].Modifiers1 = Qt::AltModifier;
|
||||
mShortcuts[LC_TOOL_ROTATE_VIEW].Button1 = Qt::LeftButton;
|
||||
mShortcuts[LC_TOOL_ROTATE_VIEW].Modifiers2 = Qt::NoModifier;
|
||||
mShortcuts[LC_TOOL_ROTATE_VIEW].Button2 = Qt::RightButton;
|
||||
lcToolShortcut& RotateViewShortcut = mShortcuts[static_cast<int>(lcTool::RotateView)];
|
||||
RotateViewShortcut.Modifiers1 = Qt::AltModifier;
|
||||
RotateViewShortcut.Button1 = Qt::LeftButton;
|
||||
RotateViewShortcut.Modifiers2 = Qt::NoModifier;
|
||||
RotateViewShortcut.Button2 = Qt::RightButton;
|
||||
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(4, 7, 0))
|
||||
mShortcuts[LC_TOOL_PAN].Modifiers1 = Qt::AltModifier;
|
||||
mShortcuts[LC_TOOL_PAN].Button1 = Qt::MiddleButton;
|
||||
mShortcuts[LC_TOOL_PAN].Modifiers2 = Qt::ShiftModifier;
|
||||
mShortcuts[LC_TOOL_PAN].Button2 = Qt::RightButton;
|
||||
#else
|
||||
mShortcuts[LC_TOOL_PAN].Modifiers1 = Qt::ShiftModifier;
|
||||
mShortcuts[LC_TOOL_PAN].Button1 = Qt::RightButton;
|
||||
#endif
|
||||
lcToolShortcut& PanShortcut = mShortcuts[static_cast<int>(lcTool::Pan)];
|
||||
PanShortcut.Modifiers1 = Qt::AltModifier;
|
||||
PanShortcut.Button1 = Qt::MiddleButton;
|
||||
PanShortcut.Modifiers2 = Qt::ShiftModifier;
|
||||
PanShortcut.Button2 = Qt::RightButton;
|
||||
|
||||
mShortcuts[LC_TOOL_ZOOM].Modifiers1 = Qt::AltModifier;
|
||||
mShortcuts[LC_TOOL_ZOOM].Button1 = Qt::RightButton;
|
||||
lcToolShortcut& ZoomShortcut = mShortcuts[static_cast<int>(lcTool::Zoom)];
|
||||
ZoomShortcut.Modifiers1 = Qt::AltModifier;
|
||||
ZoomShortcut.Button1 = Qt::RightButton;
|
||||
}
|
||||
|
||||
bool lcMouseShortcuts::Save(const QString& FileName)
|
||||
{
|
||||
QStringList Shortcuts;
|
||||
|
||||
if (!Save(Shortcuts))
|
||||
return false;
|
||||
|
||||
QFile File(FileName);
|
||||
|
||||
if (!File.open(QIODevice::WriteOnly))
|
||||
return false;
|
||||
|
||||
QTextStream Stream(&File);
|
||||
|
||||
for (const QString& Shortcut : Shortcuts)
|
||||
Stream << Shortcut << QLatin1String("\n");
|
||||
|
||||
Stream.flush();
|
||||
|
||||
return true;
|
||||
}
|
||||
bool lcMouseShortcuts::Save(QStringList& Shortcuts)
|
||||
{
|
||||
Shortcuts.clear();
|
||||
|
||||
for (int ToolIdx = 0; ToolIdx < LC_NUM_TOOLS; ToolIdx++)
|
||||
for (int ToolIdx = 0; ToolIdx < static_cast<int>(lcTool::Count); ToolIdx++)
|
||||
{
|
||||
int ButtonIndex1 = 0;
|
||||
for (int Button1 = mShortcuts[ToolIdx].Button1; Button1; Button1 >>= 1)
|
||||
|
@ -179,6 +198,22 @@ bool lcMouseShortcuts::Save(QStringList& Shortcuts)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool lcMouseShortcuts::Load(const QString& FileName)
|
||||
{
|
||||
QFile File(FileName);
|
||||
|
||||
if (!File.open(QIODevice::ReadOnly))
|
||||
return false;
|
||||
|
||||
QTextStream Stream(&File);
|
||||
QStringList Lines;
|
||||
|
||||
while (!Stream.atEnd())
|
||||
Lines += Stream.readLine();
|
||||
|
||||
return Load(Lines);
|
||||
}
|
||||
|
||||
bool lcMouseShortcuts::Load(const QStringList& FullShortcuts)
|
||||
{
|
||||
memset(mShortcuts, 0, sizeof(mShortcuts));
|
||||
|
@ -193,11 +228,11 @@ bool lcMouseShortcuts::Load(const QStringList& FullShortcuts)
|
|||
QString Key = FullShortcut.left(Equals);
|
||||
|
||||
int ToolIdx;
|
||||
for (ToolIdx = 0; ToolIdx < LC_NUM_TOOLS; ToolIdx++)
|
||||
for (ToolIdx = 0; ToolIdx < static_cast<int>(lcTool::Count); ToolIdx++)
|
||||
if (Key == gToolNames[ToolIdx])
|
||||
break;
|
||||
|
||||
if (ToolIdx == LC_NUM_TOOLS)
|
||||
if (ToolIdx == static_cast<int>(lcTool::Count))
|
||||
continue;
|
||||
|
||||
QStringList Shortcuts = FullShortcut.mid(Equals + 1).split(',');
|
||||
|
@ -233,9 +268,9 @@ bool lcMouseShortcuts::Load(const QStringList& FullShortcuts)
|
|||
|
||||
lcTool lcMouseShortcuts::GetTool(Qt::MouseButton Button, Qt::KeyboardModifiers Modifiers) const
|
||||
{
|
||||
for (int ToolIdx = 0; ToolIdx < LC_NUM_TOOLS; ToolIdx++)
|
||||
for (int ToolIdx = 0; ToolIdx < static_cast<int>(lcTool::Count); ToolIdx++)
|
||||
if ((mShortcuts[ToolIdx].Button1 == Button && mShortcuts[ToolIdx].Modifiers1 == Modifiers) || (mShortcuts[ToolIdx].Button2 == Button && mShortcuts[ToolIdx].Modifiers2 == Modifiers))
|
||||
return (lcTool)ToolIdx;
|
||||
|
||||
return LC_NUM_TOOLS;
|
||||
return lcTool::Count;
|
||||
}
|
||||
|
|
|
@ -24,18 +24,22 @@ class lcMouseShortcuts
|
|||
{
|
||||
public:
|
||||
void Reset();
|
||||
bool Save(const QString& FileName);
|
||||
bool Save(QStringList& Shortcuts);
|
||||
bool Load(const QString& FileName);
|
||||
bool Load(const QStringList& Shortcuts);
|
||||
|
||||
lcTool GetTool(Qt::MouseButton Button, Qt::KeyboardModifiers Modifiers) const;
|
||||
|
||||
struct
|
||||
struct lcToolShortcut
|
||||
{
|
||||
Qt::KeyboardModifiers Modifiers1;
|
||||
Qt::MouseButton Button1;
|
||||
Qt::KeyboardModifiers Modifiers2;
|
||||
Qt::MouseButton Button2;
|
||||
}
|
||||
mShortcuts[LC_NUM_TOOLS];
|
||||
};
|
||||
|
||||
lcToolShortcut mShortcuts[static_cast<int>(lcTool::Count)];
|
||||
};
|
||||
|
||||
extern lcMouseShortcuts gMouseShortcuts;
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
lcStringCache gStringCache;
|
||||
|
||||
lcStringCache::lcStringCache()
|
||||
: mTexture(nullptr), mRefCount(0)
|
||||
: mTexture(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -15,27 +15,17 @@ lcStringCache::~lcStringCache()
|
|||
delete mTexture;
|
||||
}
|
||||
|
||||
void lcStringCache::AddRef(lcContext* Context)
|
||||
void lcStringCache::Initialize(lcContext* Context)
|
||||
{
|
||||
Q_UNUSED(Context);
|
||||
|
||||
mRefCount++;
|
||||
|
||||
if (mRefCount == 1)
|
||||
mTexture = new lcTexture();
|
||||
mTexture = new lcTexture();
|
||||
}
|
||||
|
||||
void lcStringCache::Release(lcContext* Context)
|
||||
void lcStringCache::Reset()
|
||||
{
|
||||
mRefCount--;
|
||||
|
||||
if (mRefCount == 0)
|
||||
{
|
||||
Context->UnbindTexture2D(mTexture->mTexture); // todo: unbind from all contexts
|
||||
|
||||
delete mTexture;
|
||||
mTexture = nullptr;
|
||||
}
|
||||
delete mTexture;
|
||||
mTexture = nullptr;
|
||||
}
|
||||
|
||||
void lcStringCache::CacheStrings(const QStringList& Strings)
|
||||
|
|
|
@ -11,8 +11,8 @@ public:
|
|||
lcStringCache();
|
||||
~lcStringCache();
|
||||
|
||||
void AddRef(lcContext* Context);
|
||||
void Release(lcContext* Context);
|
||||
void Initialize(lcContext* Context);
|
||||
void Reset();
|
||||
|
||||
void CacheStrings(const QStringList& Strings);
|
||||
void GetStringDimensions(int* cx, int* cy, const QString& String) const;
|
||||
|
@ -20,7 +20,6 @@ public:
|
|||
|
||||
protected:
|
||||
lcTexture* mTexture;
|
||||
int mRefCount;
|
||||
|
||||
std::map<QString, lcStringCacheEntry> mStrings;
|
||||
};
|
||||
|
|
|
@ -111,12 +111,17 @@ protected:
|
|||
class lcSynthInfoActuator : public lcSynthInfoStraight
|
||||
{
|
||||
public:
|
||||
explicit lcSynthInfoActuator(float Length);
|
||||
explicit lcSynthInfoActuator(const char* BodyPart, const char* PistonPart, const char* AxlePart, float Length, float AxleOffset);
|
||||
|
||||
void GetDefaultControlPoints(lcArray<lcPieceControlPoint>& ControlPoints) const override;
|
||||
|
||||
protected:
|
||||
void AddParts(lcMemFile& File, lcLibraryMeshData& MeshData, const lcArray<lcMatrix44>& Sections) const override;
|
||||
|
||||
const char* mBodyPart;
|
||||
const char* mPistonPart;
|
||||
const char* mAxlePart;
|
||||
float mAxleOffset;
|
||||
};
|
||||
|
||||
class lcSynthInfoUniversalJoint : public lcSynthInfo
|
||||
|
@ -319,12 +324,22 @@ void lcSynthInit()
|
|||
static const struct
|
||||
{
|
||||
char PartID[16];
|
||||
char BodyPart[16];
|
||||
char PistonPart[16];
|
||||
char AxlePart[16];
|
||||
float Length;
|
||||
float AxleOffset;
|
||||
}
|
||||
Actuators[] =
|
||||
{
|
||||
{ "61927C01.dat", 270.00f }, // Technic Power Functions Linear Actuator (Extended)
|
||||
{ "61927.dat", 170.00f } // Technic Power Functions Linear Actuator (Contracted)
|
||||
{ "61927-F1.dat", "62271c01.dat", "62274c01.dat", "47157.dat", 170.00f, 0.0f }, // Technic Linear Actuator 8 x 2 x 2 (Contracted)
|
||||
{ "61927-F2.dat", "62271c01.dat", "62274c01.dat", "47157.dat", 270.00f, 0.0f }, // Technic Linear Actuator 8 x 2 x 2 (Extended)
|
||||
{ "61927C01.dat", "62271c01.dat", "62274c01.dat", "47157.dat", 270.00f, 0.0f }, // Moved to 61927-f2 (was Technic Power Functions Linear Actuator (Extended))
|
||||
{ "61927.dat", "62271c01.dat", "62274c01.dat", "47157.dat", 170.00f, 0.0f }, // Moved to 61927-f1 (was Technic Power Functions Linear Actuator (Contracted))
|
||||
{ "92693C01-F1.dat", "92693c01.dat", "92696.dat", "92695.dat", 120.00f, 30.0f }, // Technic Linear Actuator 4 x 1 x 1 (Contracted)
|
||||
{ "92693C01-F2.dat", "92693c01.dat", "92696.dat", "92695.dat", 180.00f, 30.0f }, // Technic Linear Actuator 4 x 1 x 1 (Extended)
|
||||
{ "92693C02.dat", "92693c01.dat", "92696.dat", "92695.dat", 120.00f, 30.0f }, // Moved to 92693c01-f1 (was Technic Linear Actuator Small (Contracted))
|
||||
{ "92693C03.dat", "92693c01.dat", "92696.dat", "92695.dat", 180.00f, 30.0f }, // Moved to 92693c01-f2 (was Technic Linear Actuator Small (Extended))
|
||||
};
|
||||
|
||||
for (const auto& ActuatorInfo: Actuators)
|
||||
|
@ -332,7 +347,8 @@ void lcSynthInit()
|
|||
PieceInfo* Info = Library->FindPiece(ActuatorInfo.PartID, nullptr, false, false);
|
||||
|
||||
if (Info)
|
||||
Info->SetSynthInfo(new lcSynthInfoActuator(ActuatorInfo.Length));
|
||||
Info->SetSynthInfo(new lcSynthInfoActuator(ActuatorInfo.BodyPart, ActuatorInfo.PistonPart,
|
||||
ActuatorInfo.AxlePart, ActuatorInfo.Length, ActuatorInfo.AxleOffset));
|
||||
}
|
||||
|
||||
static const struct
|
||||
|
@ -345,9 +361,10 @@ void lcSynthInit()
|
|||
}
|
||||
UniversalJoints[] =
|
||||
{
|
||||
{ "61903.dat", 60.00f, 0.0f, "62520.dat", "62519.dat" }, // Technic Universal Joint 3L
|
||||
{ "3712C01.dat", 60.00f, 30.0f, "3712.dat", "3326.dat" }, // Technic Universal Joint
|
||||
{ "575C01.dat", 60.00f, 30.0f, "575.dat", "3326a.dat" } // Technic Universal Joint Type 1
|
||||
{ "61903.dat", 60.00f, 0.0f, "62520.dat", "62519.dat" }, // Technic Universal Joint 3L (Complete)
|
||||
{ "3712C01.dat", 60.00f, 30.0f, "3712.dat", "3326.dat" }, // Technic Universal Joint 4L with Bush Ends with Centre Type 2 (Complete)
|
||||
{ "3712C03.dat", 60.00f, 30.0f, "3712.dat", "3326a.dat" }, // Technic Universal Joint 4L with Bush Ends with Centre Type 1 (Complete)
|
||||
{ "575C01.dat", 60.00f, 30.0f, "575.dat", "3326a.dat" } // Technic Universal Joint Type 1 (Complete)
|
||||
};
|
||||
|
||||
for (const auto& JointInfo: UniversalJoints)
|
||||
|
@ -432,8 +449,8 @@ lcSynthInfoShockAbsorber::lcSynthInfoShockAbsorber(const char* SpringPart)
|
|||
{
|
||||
}
|
||||
|
||||
lcSynthInfoActuator::lcSynthInfoActuator(float Length)
|
||||
: lcSynthInfoStraight(Length)
|
||||
lcSynthInfoActuator::lcSynthInfoActuator(const char* BodyPart, const char* PistonPart, const char* AxlePart, float Length, float AxleOffset)
|
||||
: lcSynthInfoStraight(Length), mBodyPart(BodyPart), mPistonPart(PistonPart), mAxlePart(AxlePart), mAxleOffset(AxleOffset)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -1327,13 +1344,15 @@ void lcSynthInfoActuator::AddParts(lcMemFile& File, lcLibraryMeshData&, const lc
|
|||
lcVector3 Offset;
|
||||
|
||||
Offset = Sections[0].GetTranslation();
|
||||
sprintf(Line, "1 25 %f %f %f 0 1 0 -1 0 0 0 0 1 47157.dat\n", Offset[0], Offset[1], Offset[2]);
|
||||
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);
|
||||
File.WriteBuffer(Line, strlen(Line));
|
||||
sprintf(Line, "1 16 %f %f %f 1 0 0 0 1 0 0 0 1 62271c01.dat\n", Offset[0], Offset[1], Offset[2]);
|
||||
|
||||
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);
|
||||
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 62274c01.dat\n", Offset[0], Offset[1], Offset[2]);
|
||||
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);
|
||||
File.WriteBuffer(Line, strlen(Line));
|
||||
}
|
||||
|
||||
|
|
|
@ -41,11 +41,7 @@ public:
|
|||
{
|
||||
mRefCount.ref();
|
||||
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 3, 0) || QT_VERSION < QT_VERSION_CHECK(5, 0, 0) )
|
||||
if (mRefCount == 1)
|
||||
#else
|
||||
if (mRefCount.load() == 1)
|
||||
#endif
|
||||
Load();
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
#include "piece.h"
|
||||
#include "pieceinf.h"
|
||||
#include "lc_mainwindow.h"
|
||||
#include "lc_viewwidget.h"
|
||||
#include "lc_previewwidget.h"
|
||||
|
||||
lcTimelineWidget::lcTimelineWidget(QWidget* Parent)
|
||||
: QTreeWidget(Parent)
|
||||
|
@ -188,7 +190,7 @@ void lcTimelineWidget::Update(bool Clear, bool UpdateItems)
|
|||
{
|
||||
PieceItem->setText(0, Piece->mPieceInfo->m_strDescription);
|
||||
|
||||
int ColorIndex = Piece->mColorIndex;
|
||||
int ColorIndex = Piece->GetColorIndex();
|
||||
if (!mIcons.contains(ColorIndex))
|
||||
{
|
||||
int Size = rowHeight(indexFromItem(PieceItem));
|
||||
|
@ -209,7 +211,7 @@ void lcTimelineWidget::Update(bool Clear, bool UpdateItems)
|
|||
QColor Color = palette().text().color();
|
||||
if (Piece->IsHidden())
|
||||
Color.setAlpha(128);
|
||||
PieceItem->setTextColor(0, Color);
|
||||
PieceItem->setForeground(0, Color);
|
||||
}
|
||||
|
||||
PieceItem->setSelected(Piece->IsSelected());
|
||||
|
@ -263,11 +265,11 @@ void lcTimelineWidget::UpdateCurrentStepItem()
|
|||
QFont Font = CurrentStepItem->font(0);
|
||||
Font.setBold(true);
|
||||
CurrentStepItem->setFont(0, Font);
|
||||
setCurrentItem(CurrentStepItem);
|
||||
}
|
||||
|
||||
mCurrentStepItem = CurrentStepItem;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void lcTimelineWidget::UpdateSelection()
|
||||
|
@ -507,6 +509,35 @@ void lcTimelineWidget::mousePressEvent(QMouseEvent* Event)
|
|||
QTreeWidget::mousePressEvent(Event);
|
||||
}
|
||||
|
||||
void lcTimelineWidget::mouseDoubleClickEvent(QMouseEvent* MouseEvent)
|
||||
{
|
||||
if (MouseEvent->button() == Qt::LeftButton)
|
||||
{
|
||||
QTreeWidgetItem* CurrentItem = currentItem();
|
||||
PreviewSelection(CurrentItem);
|
||||
}
|
||||
|
||||
QTreeWidget::mouseDoubleClickEvent(MouseEvent);
|
||||
}
|
||||
|
||||
void lcTimelineWidget::PreviewSelection(QTreeWidgetItem* CurrentItem)
|
||||
{
|
||||
if (!CurrentItem)
|
||||
return;
|
||||
|
||||
lcPiece* Piece = (lcPiece*)CurrentItem->data(0, Qt::UserRole).value<uintptr_t>();
|
||||
|
||||
if (!Piece)
|
||||
return;
|
||||
|
||||
PieceInfo* Info = Piece->mPieceInfo;
|
||||
|
||||
if (!Info)
|
||||
return;
|
||||
|
||||
gMainWindow->PreviewPiece(Info->mFileName, Piece->GetColorCode(), false);
|
||||
}
|
||||
|
||||
void lcTimelineWidget::UpdateModel()
|
||||
{
|
||||
QList<QPair<lcPiece*, lcStep>> PieceSteps;
|
||||
|
|
|
@ -21,10 +21,12 @@ public slots:
|
|||
void CurrentItemChanged(QTreeWidgetItem* Current, QTreeWidgetItem* Previous);
|
||||
void ItemSelectionChanged();
|
||||
void CustomMenuRequested(QPoint Pos);
|
||||
void PreviewSelection(QTreeWidgetItem* Current);
|
||||
|
||||
protected:
|
||||
void dropEvent(QDropEvent* DropEvent) override;
|
||||
void mousePressEvent(QMouseEvent* MouseEvent) override;
|
||||
void mouseDoubleClickEvent(QMouseEvent* MouseEvent) override;
|
||||
void UpdateModel();
|
||||
void UpdateCurrentStepItem();
|
||||
|
||||
|
@ -33,4 +35,3 @@ protected:
|
|||
QTreeWidgetItem* mCurrentStepItem;
|
||||
bool mIgnoreUpdates;
|
||||
};
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
351
common/lc_view.h
Normal file
351
common/lc_view.h
Normal file
|
@ -0,0 +1,351 @@
|
|||
#pragma once
|
||||
|
||||
#include "lc_context.h"
|
||||
#include "lc_math.h"
|
||||
#include "lc_commands.h"
|
||||
|
||||
enum class lcDragState
|
||||
{
|
||||
None,
|
||||
Piece,
|
||||
Color
|
||||
};
|
||||
|
||||
enum class lcCursor
|
||||
{
|
||||
First,
|
||||
Hidden = First,
|
||||
Default,
|
||||
Brick,
|
||||
Light,
|
||||
Spotlight,
|
||||
Camera,
|
||||
Select,
|
||||
SelectAdd,
|
||||
SelectRemove,
|
||||
Move,
|
||||
Rotate,
|
||||
RotateX,
|
||||
RotateY,
|
||||
Delete,
|
||||
Paint,
|
||||
ColorPicker,
|
||||
Zoom,
|
||||
ZoomRegion,
|
||||
Pan,
|
||||
Roll,
|
||||
RotateView,
|
||||
Count
|
||||
};
|
||||
|
||||
enum class lcTrackButton
|
||||
{
|
||||
None,
|
||||
Left,
|
||||
Middle,
|
||||
Right
|
||||
};
|
||||
|
||||
enum class lcTrackTool
|
||||
{
|
||||
None,
|
||||
Insert,
|
||||
PointLight,
|
||||
SpotLight,
|
||||
Camera,
|
||||
Select,
|
||||
MoveX,
|
||||
MoveY,
|
||||
MoveZ,
|
||||
MoveXY,
|
||||
MoveXZ,
|
||||
MoveYZ,
|
||||
MoveXYZ,
|
||||
RotateX,
|
||||
RotateY,
|
||||
RotateZ,
|
||||
RotateXY,
|
||||
RotateXYZ,
|
||||
ScalePlus,
|
||||
ScaleMinus,
|
||||
Eraser,
|
||||
Paint,
|
||||
ColorPicker,
|
||||
Zoom,
|
||||
Pan,
|
||||
OrbitX,
|
||||
OrbitY,
|
||||
OrbitXY,
|
||||
Roll,
|
||||
ZoomRegion,
|
||||
Count
|
||||
};
|
||||
|
||||
enum class lcViewType
|
||||
{
|
||||
View,
|
||||
Preview,
|
||||
Minifig,
|
||||
PartsList,
|
||||
Count
|
||||
};
|
||||
|
||||
struct lcFindReplaceParams
|
||||
{
|
||||
PieceInfo* FindInfo = nullptr;
|
||||
QString FindString;
|
||||
int FindColorIndex = 0;
|
||||
PieceInfo* ReplacePieceInfo = nullptr;
|
||||
int ReplaceColorIndex = 0;
|
||||
};
|
||||
|
||||
class lcView : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
lcView(lcViewType ViewType, lcModel* Model);
|
||||
~lcView();
|
||||
|
||||
lcView(const lcView&) = delete;
|
||||
lcView& operator=(const lcView&) = delete;
|
||||
|
||||
static lcFindReplaceParams& GetFindReplaceParams()
|
||||
{
|
||||
return mFindReplaceParams;
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
mModel = nullptr;
|
||||
mActiveSubmodelInstance = nullptr;
|
||||
}
|
||||
|
||||
lcModel* GetModel() const
|
||||
{
|
||||
return mModel;
|
||||
}
|
||||
|
||||
lcViewType GetViewType() const
|
||||
{
|
||||
return mViewType;
|
||||
}
|
||||
|
||||
lcCamera* GetCamera() const
|
||||
{
|
||||
return mCamera;
|
||||
}
|
||||
|
||||
bool IsLastFocused() const
|
||||
{
|
||||
return mLastFocusedView == this;
|
||||
}
|
||||
|
||||
bool IsTracking() const
|
||||
{
|
||||
return mTrackButton != lcTrackButton::None;
|
||||
}
|
||||
|
||||
int GetWidth() const
|
||||
{
|
||||
return mWidth;
|
||||
}
|
||||
|
||||
int GetHeight() const
|
||||
{
|
||||
return mHeight;
|
||||
}
|
||||
|
||||
void SetSize(int Width, int Height)
|
||||
{
|
||||
mWidth = Width;
|
||||
mHeight = Height;
|
||||
}
|
||||
|
||||
lcViewWidget* GetWidget() const
|
||||
{
|
||||
return mWidget;
|
||||
}
|
||||
|
||||
void SetWidget(lcViewWidget* Widget)
|
||||
{
|
||||
mWidget = Widget;
|
||||
}
|
||||
|
||||
int GetMouseX() const
|
||||
{
|
||||
return mMouseX;
|
||||
}
|
||||
|
||||
int GetMouseY() const
|
||||
{
|
||||
return mMouseY;
|
||||
}
|
||||
|
||||
void SetBackgroundColorOverride(quint32 BackgroundColor)
|
||||
{
|
||||
mOverrideBackgroundColor = true;
|
||||
mBackgroundColor = BackgroundColor;
|
||||
}
|
||||
|
||||
static void UpdateProjectViews(const Project* Project);
|
||||
static void UpdateAllViews();
|
||||
|
||||
static void CreateResources(lcContext* Context);
|
||||
static void DestroyResources(lcContext* Context);
|
||||
|
||||
void MakeCurrent();
|
||||
void Redraw();
|
||||
|
||||
void SetOffscreenContext();
|
||||
|
||||
void SetFocus(bool Focus);
|
||||
void SetMousePosition(int MouseX, int MouseY);
|
||||
void SetMouseModifiers(Qt::KeyboardModifiers MouseModifiers);
|
||||
|
||||
lcModel* GetActiveModel() const;
|
||||
void SetTopSubmodelActive();
|
||||
void SetSelectedSubmodelActive();
|
||||
|
||||
void OnDraw();
|
||||
void OnLeftButtonDown();
|
||||
void OnLeftButtonUp();
|
||||
void OnLeftButtonDoubleClick();
|
||||
void OnMiddleButtonDown();
|
||||
void OnMiddleButtonUp();
|
||||
void OnRightButtonDown();
|
||||
void OnRightButtonUp();
|
||||
void OnBackButtonDown();
|
||||
void OnBackButtonUp();
|
||||
void OnForwardButtonDown();
|
||||
void OnForwardButtonUp();
|
||||
void OnMouseMove();
|
||||
void OnMouseWheel(float Direction);
|
||||
void BeginDrag(lcDragState DragState);
|
||||
void EndDrag(bool Accept);
|
||||
|
||||
void UpdateCursor();
|
||||
void StartOrbitTracking();
|
||||
void CancelTrackingOrClearSelection();
|
||||
|
||||
void SetViewpoint(lcViewpoint Viewpoint);
|
||||
void SetViewpoint(const lcVector3& Position);
|
||||
void SetViewpoint(const lcVector3& Position, const lcVector3& Target, const lcVector3& Up);
|
||||
void SetCameraAngles(float Latitude, float Longitude);
|
||||
void SetDefaultCamera();
|
||||
void SetCamera(lcCamera* Camera, bool ForceCopy);
|
||||
void SetCamera(const QString& CameraName);
|
||||
void SetCameraIndex(int Index);
|
||||
|
||||
void SetProjection(bool Ortho);
|
||||
void LookAt();
|
||||
void MoveCamera(const lcVector3& Direction);
|
||||
void Zoom(float Amount);
|
||||
void ZoomExtents();
|
||||
|
||||
void RemoveCamera();
|
||||
void ShowContextMenu() const;
|
||||
bool CloseFindReplaceDialog();
|
||||
void ShowFindReplaceWidget(bool Replace);
|
||||
|
||||
lcVector3 GetMoveDirection(const lcVector3& Direction) const;
|
||||
lcMatrix44 GetPieceInsertPosition(bool IgnoreSelected, PieceInfo* Info) const;
|
||||
lcVector3 GetCameraLightInsertPosition() const;
|
||||
void GetRayUnderPointer(lcVector3& Start, lcVector3& End) const;
|
||||
lcObjectSection FindObjectUnderPointer(bool PiecesOnly, bool IgnoreSelected) const;
|
||||
lcArray<lcObject*> FindObjectsInBox(float x1, float y1, float x2, float y2) const;
|
||||
|
||||
bool BeginRenderToImage(int Width, int Height);
|
||||
void EndRenderToImage();
|
||||
QImage GetRenderImage() const;
|
||||
void BindRenderFramebuffer();
|
||||
void UnbindRenderFramebuffer();
|
||||
QImage GetRenderFramebufferImage() const;
|
||||
std::vector<QImage> GetStepImages(lcStep Start, lcStep End);
|
||||
void SaveStepImages(const QString& BaseName, bool AddStepSuffix, lcStep Start, lcStep End, std::function<void(const QString&)> ProgressCallback);
|
||||
|
||||
lcContext* mContext = nullptr;
|
||||
|
||||
signals:
|
||||
void FocusReceived();
|
||||
void CameraChanged();
|
||||
|
||||
protected:
|
||||
static void CreateSelectMoveOverlayMesh(lcContext* Context);
|
||||
|
||||
void DrawBackground() const;
|
||||
void DrawViewport() const;
|
||||
void DrawAxes() const;
|
||||
|
||||
void DrawSelectMoveOverlay();
|
||||
void DrawRotateOverlay();
|
||||
void DrawSelectZoomRegionOverlay();
|
||||
void DrawRotateViewOverlay();
|
||||
void DrawGrid();
|
||||
|
||||
lcVector3 ProjectPoint(const lcVector3& Point) const;
|
||||
lcVector3 UnprojectPoint(const lcVector3& Point) const;
|
||||
void UnprojectPoints(lcVector3* Points, int NumPoints) const;
|
||||
lcMatrix44 GetProjectionMatrix() const;
|
||||
lcMatrix44 GetTileProjectionMatrix(int CurrentRow, int CurrentColumn, int CurrentTileWidth, int CurrentTileHeight) const;
|
||||
|
||||
lcCursor GetCursor() const;
|
||||
void SetCursor(lcCursor Cursor);
|
||||
lcTool GetCurrentTool() const;
|
||||
void UpdateTrackTool();
|
||||
bool IsTrackToolAllowed(lcTrackTool TrackTool, quint32 AllowedTransforms) const;
|
||||
lcTrackTool GetOverrideTrackTool(Qt::MouseButton Button) const;
|
||||
float GetOverlayScale() const;
|
||||
void StartTracking(lcTrackButton TrackButton);
|
||||
void StopTracking(bool Accept);
|
||||
void OnButtonDown(lcTrackButton TrackButton);
|
||||
|
||||
lcViewWidget* mWidget = nullptr;
|
||||
int mWidth = 1;
|
||||
int mHeight = 1;
|
||||
bool mDeleteContext = true;
|
||||
lcViewType mViewType;
|
||||
|
||||
int mMouseX = 0;
|
||||
int mMouseY = 0;
|
||||
int mMouseDownX = 0;
|
||||
int mMouseDownY = 0;
|
||||
Qt::KeyboardModifiers mMouseModifiers = Qt::NoModifier;
|
||||
|
||||
bool mTrackUpdated = false;
|
||||
bool mToolClicked = false;
|
||||
lcTrackTool mTrackTool = lcTrackTool::None;
|
||||
lcTrackButton mTrackButton = lcTrackButton::None;
|
||||
lcCursor mCursor = lcCursor::Default;
|
||||
|
||||
lcDragState mDragState;
|
||||
bool mTrackToolFromOverlay;
|
||||
lcVector3 mMouseDownPosition;
|
||||
PieceInfo* mMouseDownPiece;
|
||||
|
||||
QImage mRenderImage;
|
||||
std::unique_ptr<QOpenGLFramebufferObject> mRenderFramebuffer;
|
||||
bool mOverrideBackgroundColor = false;
|
||||
quint32 mBackgroundColor = 0;
|
||||
|
||||
std::unique_ptr<lcScene> mScene;
|
||||
std::unique_ptr<lcViewSphere> mViewSphere;
|
||||
|
||||
lcModel* mModel = nullptr;
|
||||
lcPiece* mActiveSubmodelInstance = nullptr;
|
||||
lcMatrix44 mActiveSubmodelTransform;
|
||||
|
||||
lcCamera* mCamera = nullptr;
|
||||
|
||||
lcVertexBuffer mGridBuffer;
|
||||
int mGridSettings[7];
|
||||
|
||||
static lcFindReplaceWidget* mFindWidget;
|
||||
static lcFindReplaceParams mFindReplaceParams;
|
||||
|
||||
static lcView* mLastFocusedView;
|
||||
static std::vector<lcView*> mViews;
|
||||
|
||||
static lcVertexBuffer mRotateMoveVertexBuffer;
|
||||
static lcIndexBuffer mRotateMoveIndexBuffer;
|
||||
};
|
|
@ -1,6 +1,7 @@
|
|||
#include "lc_global.h"
|
||||
#include "lc_viewsphere.h"
|
||||
#include "view.h"
|
||||
#include "lc_view.h"
|
||||
#include "camera.h"
|
||||
#include "lc_context.h"
|
||||
#include "lc_stringcache.h"
|
||||
#include "lc_application.h"
|
||||
|
@ -14,15 +15,40 @@ const float lcViewSphere::mRadius = 1.0f;
|
|||
const float lcViewSphere::mHighlightRadius = 0.35f;
|
||||
const int lcViewSphere::mSubdivisions = 7;
|
||||
|
||||
lcViewSphere::lcViewSphere(View* View)
|
||||
lcViewSphere::lcViewSphere(lcView* View)
|
||||
: mView(View)
|
||||
{
|
||||
mMouseDown = false;
|
||||
UpdateSettings();
|
||||
}
|
||||
|
||||
void lcViewSphere::UpdateSettings()
|
||||
{
|
||||
const lcPreferences& Preferences = lcGetPreferences();
|
||||
|
||||
switch (mView->GetViewType())
|
||||
{
|
||||
case lcViewType::View:
|
||||
mSize = Preferences.mViewSphereSize;
|
||||
mEnabled = Preferences.mViewSphereEnabled;
|
||||
mLocation = Preferences.mViewSphereLocation;
|
||||
break;
|
||||
|
||||
case lcViewType::Preview:
|
||||
mSize = Preferences.mPreviewViewSphereSize;
|
||||
mEnabled = Preferences.mPreviewViewSphereEnabled;
|
||||
mLocation = Preferences.mPreviewViewSphereLocation;
|
||||
break;
|
||||
|
||||
case lcViewType::Minifig:
|
||||
case lcViewType::PartsList:
|
||||
case lcViewType::Count:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
lcMatrix44 lcViewSphere::GetViewMatrix() const
|
||||
{
|
||||
lcMatrix44 ViewMatrix = mView->mCamera->mWorldView;
|
||||
lcMatrix44 ViewMatrix = mView->GetCamera()->mWorldView;
|
||||
ViewMatrix.SetTranslation(lcVector3(0, 0, 0));
|
||||
return ViewMatrix;
|
||||
}
|
||||
|
@ -151,23 +177,21 @@ void lcViewSphere::DestroyResources(lcContext* Context)
|
|||
|
||||
void lcViewSphere::Draw()
|
||||
{
|
||||
const lcPreferences& Preferences = lcGetPreferences();
|
||||
int ViewportSize = Preferences.mViewSphereSize;
|
||||
UpdateSettings();
|
||||
|
||||
if (ViewportSize == 0 || !Preferences.mViewSphereEnabled)
|
||||
if (!mSize || !mEnabled)
|
||||
return;
|
||||
|
||||
lcContext* Context = mView->mContext;
|
||||
int Width = mView->mWidth;
|
||||
int Height = mView->mHeight;
|
||||
lcViewSphereLocation Location = Preferences.mViewSphereLocation;
|
||||
|
||||
int Left = (Location == lcViewSphereLocation::BottomLeft || Location == lcViewSphereLocation::TopLeft) ? 0 : Width - ViewportSize;
|
||||
int Bottom = (Location == lcViewSphereLocation::BottomLeft || Location == lcViewSphereLocation::BottomRight) ? 0 : Height - ViewportSize;
|
||||
const int Width = mView->GetWidth();
|
||||
const int Height = mView->GetHeight();
|
||||
const int ViewportSize = mSize;
|
||||
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);
|
||||
|
||||
glDepthFunc(GL_ALWAYS);
|
||||
glEnable(GL_CULL_FACE);
|
||||
Context->SetDepthFunction(lcDepthFunction::Always);
|
||||
Context->EnableCullFace(true);
|
||||
|
||||
Context->SetVertexBuffer(mVertexBuffer);
|
||||
Context->SetVertexFormatPosition(3);
|
||||
|
@ -205,6 +229,7 @@ void lcViewSphere::Draw()
|
|||
HighlightPosition = lcVector4(lcNormalize(lcVector3(HighlightPosition)), mHighlightRadius);
|
||||
}
|
||||
|
||||
const lcPreferences& Preferences = lcGetPreferences();
|
||||
const lcVector4 TextColor = lcVector4FromColor(Preferences.mViewSphereTextColor);
|
||||
const lcVector4 BackgroundColor = lcVector4FromColor(Preferences.mViewSphereColor);
|
||||
const lcVector4 HighlightColor = lcVector4FromColor(Preferences.mViewSphereHighlightColor);
|
||||
|
@ -212,16 +237,15 @@ void lcViewSphere::Draw()
|
|||
Context->SetHighlightParams(HighlightPosition, TextColor, BackgroundColor, HighlightColor);
|
||||
Context->DrawIndexedPrimitives(GL_TRIANGLES, mSubdivisions * mSubdivisions * 6 * 6, GL_UNSIGNED_SHORT, 0);
|
||||
|
||||
glDisable(GL_CULL_FACE);
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
Context->EnableCullFace(false);
|
||||
Context->SetDepthFunction(lcDepthFunction::LessEqual);
|
||||
|
||||
Context->SetViewport(0, 0, Width, Height);
|
||||
}
|
||||
|
||||
bool lcViewSphere::OnLeftButtonDown()
|
||||
{
|
||||
const lcPreferences& Preferences = lcGetPreferences();
|
||||
if (Preferences.mViewSphereSize == 0 || !Preferences.mViewSphereEnabled)
|
||||
if (!mSize || !mEnabled)
|
||||
return false;
|
||||
|
||||
mIntersectionFlags = GetIntersectionFlags(mIntersection);
|
||||
|
@ -229,8 +253,8 @@ bool lcViewSphere::OnLeftButtonDown()
|
|||
if (!mIntersectionFlags.any())
|
||||
return false;
|
||||
|
||||
mMouseDownX = mView->mInputState.x;
|
||||
mMouseDownY = mView->mInputState.y;
|
||||
mMouseDownX = mView->GetMouseX();
|
||||
mMouseDownY = mView->GetMouseY();
|
||||
mMouseDown = true;
|
||||
|
||||
return true;
|
||||
|
@ -238,8 +262,7 @@ bool lcViewSphere::OnLeftButtonDown()
|
|||
|
||||
bool lcViewSphere::OnLeftButtonUp()
|
||||
{
|
||||
const lcPreferences& Preferences = lcGetPreferences();
|
||||
if (Preferences.mViewSphereSize == 0 || !Preferences.mViewSphereEnabled)
|
||||
if (!mSize || !mEnabled)
|
||||
return false;
|
||||
|
||||
if (!mMouseDown)
|
||||
|
@ -267,8 +290,7 @@ bool lcViewSphere::OnLeftButtonUp()
|
|||
|
||||
bool lcViewSphere::OnMouseMove()
|
||||
{
|
||||
const lcPreferences& Preferences = lcGetPreferences();
|
||||
if (Preferences.mViewSphereSize == 0 || !Preferences.mViewSphereEnabled)
|
||||
if (!mSize || !mEnabled)
|
||||
return false;
|
||||
|
||||
if (IsDragging())
|
||||
|
@ -294,21 +316,20 @@ bool lcViewSphere::OnMouseMove()
|
|||
|
||||
bool lcViewSphere::IsDragging() const
|
||||
{
|
||||
return mMouseDown && (qAbs(mMouseDownX - mView->mInputState.x) > 3 || qAbs(mMouseDownY - mView->mInputState.y) > 3);
|
||||
int InputStateX = mView->GetMouseX();
|
||||
int InputStateY = mView->GetMouseY();
|
||||
return mMouseDown && (qAbs(mMouseDownX - InputStateX) > 3 || qAbs(mMouseDownY - InputStateY) > 3);
|
||||
}
|
||||
|
||||
std::bitset<6> lcViewSphere::GetIntersectionFlags(lcVector3& Intersection) const
|
||||
{
|
||||
const lcPreferences& Preferences = lcGetPreferences();
|
||||
lcViewSphereLocation Location = Preferences.mViewSphereLocation;
|
||||
|
||||
int Width = mView->mWidth;
|
||||
int Height = mView->mHeight;
|
||||
int ViewportSize = Preferences.mViewSphereSize;
|
||||
int Left = (Location == lcViewSphereLocation::BottomLeft || Location == lcViewSphereLocation::TopLeft) ? 0 : Width - ViewportSize;
|
||||
int Bottom = (Location == lcViewSphereLocation::BottomLeft || Location == lcViewSphereLocation::BottomRight) ? 0 : Height - ViewportSize;
|
||||
int x = mView->mInputState.x - Left;
|
||||
int y = mView->mInputState.y - Bottom;
|
||||
const int Width = mView->GetWidth();
|
||||
const int Height = mView->GetHeight();
|
||||
const int ViewportSize = mSize;
|
||||
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;
|
||||
const int y = mView->GetMouseY() - Bottom;
|
||||
std::bitset<6> IntersectionFlags;
|
||||
|
||||
if (x < 0 || x > Width || y < 0 || y > Height)
|
||||
|
|
|
@ -4,12 +4,18 @@
|
|||
#include "lc_context.h"
|
||||
#include <bitset>
|
||||
|
||||
class View;
|
||||
enum class lcViewSphereLocation
|
||||
{
|
||||
TopLeft,
|
||||
TopRight,
|
||||
BottomLeft,
|
||||
BottomRight
|
||||
};
|
||||
|
||||
class lcViewSphere
|
||||
{
|
||||
public:
|
||||
lcViewSphere(View* View);
|
||||
lcViewSphere(lcView* View);
|
||||
|
||||
void Draw();
|
||||
bool OnMouseMove();
|
||||
|
@ -21,16 +27,23 @@ public:
|
|||
static void DestroyResources(lcContext* Context);
|
||||
|
||||
protected:
|
||||
void UpdateSettings();
|
||||
lcMatrix44 GetViewMatrix() const;
|
||||
lcMatrix44 GetProjectionMatrix() const;
|
||||
std::bitset<6> GetIntersectionFlags(lcVector3& Intersection) const;
|
||||
|
||||
View* mView;
|
||||
lcView* const mView = nullptr;
|
||||
|
||||
int mSize = 1;
|
||||
bool mEnabled = false;
|
||||
lcViewSphereLocation mLocation = lcViewSphereLocation::TopRight;
|
||||
|
||||
int mMouseDownX = 0;
|
||||
int mMouseDownY = 0;
|
||||
bool mMouseDown = false;
|
||||
|
||||
lcVector3 mIntersection;
|
||||
std::bitset<6> mIntersectionFlags;
|
||||
int mMouseDownX;
|
||||
int mMouseDownY;
|
||||
bool mMouseDown;
|
||||
|
||||
static lcTexture* mTexture;
|
||||
static lcVertexBuffer mVertexBuffer;
|
||||
|
|
312
common/lc_viewwidget.cpp
Normal file
312
common/lc_viewwidget.cpp
Normal file
|
@ -0,0 +1,312 @@
|
|||
#include "lc_global.h"
|
||||
#include "lc_viewwidget.h"
|
||||
#include "lc_glextensions.h"
|
||||
#include "project.h"
|
||||
#include "lc_library.h"
|
||||
#include "lc_application.h"
|
||||
#include "lc_mainwindow.h"
|
||||
#include "lc_context.h"
|
||||
#include "lc_view.h"
|
||||
#include "lc_texture.h"
|
||||
#include "lc_mesh.h"
|
||||
#include "lc_profile.h"
|
||||
#include "lc_previewwidget.h"
|
||||
|
||||
static QList<lcViewWidget*> gWidgetList;
|
||||
|
||||
lcViewWidget::lcViewWidget(QWidget* Parent, lcView* View)
|
||||
: QOpenGLWidget(Parent)
|
||||
{
|
||||
mWheelAccumulator = 0;
|
||||
mView = View;
|
||||
mView->SetWidget(this);
|
||||
|
||||
gWidgetList.append(this);
|
||||
|
||||
setMouseTracking(true);
|
||||
|
||||
if (View->GetViewType() == lcViewType::View)
|
||||
{
|
||||
setFocusPolicy(Qt::StrongFocus);
|
||||
setAcceptDrops(true);
|
||||
}
|
||||
}
|
||||
|
||||
lcViewWidget::~lcViewWidget()
|
||||
{
|
||||
gWidgetList.removeOne(this);
|
||||
|
||||
delete mView;
|
||||
}
|
||||
|
||||
QSize lcViewWidget::sizeHint() const
|
||||
{
|
||||
return mPreferredSize.isEmpty() ? QOpenGLWidget::sizeHint() : mPreferredSize;
|
||||
}
|
||||
|
||||
void lcViewWidget::SetView(lcView* View)
|
||||
{
|
||||
if (View)
|
||||
{
|
||||
if (context())
|
||||
{
|
||||
makeCurrent();
|
||||
View->mContext->SetGLContext(context(), this);
|
||||
}
|
||||
|
||||
View->SetWidget(this);
|
||||
const float Scale = GetDeviceScale();
|
||||
View->SetSize(width() * Scale, height() * Scale);
|
||||
|
||||
if (hasFocus())
|
||||
View->SetFocus(true);
|
||||
}
|
||||
|
||||
delete mView;
|
||||
mView = View;
|
||||
}
|
||||
|
||||
void lcViewWidget::initializeGL()
|
||||
{
|
||||
mView->mContext->SetGLContext(context(), this);
|
||||
}
|
||||
|
||||
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
|
||||
mView->SetSize(Width * Scale, Height * Scale);
|
||||
}
|
||||
|
||||
void lcViewWidget::paintGL()
|
||||
{
|
||||
mView->OnDraw();
|
||||
}
|
||||
|
||||
void lcViewWidget::focusInEvent(QFocusEvent* FocusEvent)
|
||||
{
|
||||
if (mView)
|
||||
mView->SetFocus(true);
|
||||
|
||||
QOpenGLWidget::focusInEvent(FocusEvent);
|
||||
}
|
||||
|
||||
void lcViewWidget::focusOutEvent(QFocusEvent* FocusEvent)
|
||||
{
|
||||
if (mView)
|
||||
mView->SetFocus(false);
|
||||
|
||||
QOpenGLWidget::focusOutEvent(FocusEvent);
|
||||
}
|
||||
|
||||
void lcViewWidget::keyPressEvent(QKeyEvent* KeyEvent)
|
||||
{
|
||||
if (KeyEvent->key() == Qt::Key_Control || KeyEvent->key() == Qt::Key_Shift)
|
||||
{
|
||||
mView->SetMouseModifiers(KeyEvent->modifiers());
|
||||
mView->UpdateCursor();
|
||||
}
|
||||
|
||||
QOpenGLWidget::keyPressEvent(KeyEvent);
|
||||
}
|
||||
|
||||
void lcViewWidget::keyReleaseEvent(QKeyEvent* KeyEvent)
|
||||
{
|
||||
if (KeyEvent->key() == Qt::Key_Control || KeyEvent->key() == Qt::Key_Shift)
|
||||
{
|
||||
mView->SetMouseModifiers(KeyEvent->modifiers());
|
||||
mView->UpdateCursor();
|
||||
}
|
||||
|
||||
QOpenGLWidget::keyReleaseEvent(KeyEvent);
|
||||
}
|
||||
|
||||
void lcViewWidget::mousePressEvent(QMouseEvent* MouseEvent)
|
||||
{
|
||||
float DeviceScale = GetDeviceScale();
|
||||
|
||||
mView->SetMousePosition(MouseEvent->x() * DeviceScale, mView->GetHeight() - MouseEvent->y() * DeviceScale - 1);
|
||||
mView->SetMouseModifiers(MouseEvent->modifiers());
|
||||
|
||||
switch (MouseEvent->button())
|
||||
{
|
||||
case Qt::LeftButton:
|
||||
mView->OnLeftButtonDown();
|
||||
break;
|
||||
|
||||
case Qt::MiddleButton:
|
||||
mView->OnMiddleButtonDown();
|
||||
break;
|
||||
|
||||
case Qt::RightButton:
|
||||
mView->OnRightButtonDown();
|
||||
break;
|
||||
|
||||
case Qt::BackButton:
|
||||
mView->OnBackButtonDown();
|
||||
break;
|
||||
|
||||
case Qt::ForwardButton:
|
||||
mView->OnForwardButtonDown();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void lcViewWidget::mouseReleaseEvent(QMouseEvent* MouseEvent)
|
||||
{
|
||||
float DeviceScale = GetDeviceScale();
|
||||
|
||||
mView->SetMousePosition(MouseEvent->x() * DeviceScale, mView->GetHeight() - MouseEvent->y() * DeviceScale - 1);
|
||||
mView->SetMouseModifiers(MouseEvent->modifiers());
|
||||
|
||||
switch (MouseEvent->button())
|
||||
{
|
||||
case Qt::LeftButton:
|
||||
mView->OnLeftButtonUp();
|
||||
break;
|
||||
|
||||
case Qt::MiddleButton:
|
||||
mView->OnMiddleButtonUp();
|
||||
break;
|
||||
|
||||
case Qt::RightButton:
|
||||
mView->OnRightButtonUp();
|
||||
break;
|
||||
|
||||
case Qt::BackButton:
|
||||
mView->OnBackButtonUp();
|
||||
break;
|
||||
|
||||
case Qt::ForwardButton:
|
||||
mView->OnForwardButtonUp();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void lcViewWidget::mouseDoubleClickEvent(QMouseEvent* MouseEvent)
|
||||
{
|
||||
float DeviceScale = GetDeviceScale();
|
||||
|
||||
mView->SetMousePosition(MouseEvent->x() * DeviceScale, mView->GetHeight() - MouseEvent->y() * DeviceScale - 1);
|
||||
mView->SetMouseModifiers(MouseEvent->modifiers());
|
||||
|
||||
switch (MouseEvent->button())
|
||||
{
|
||||
case Qt::LeftButton:
|
||||
mView->OnLeftButtonDoubleClick();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void lcViewWidget::mouseMoveEvent(QMouseEvent* MouseEvent)
|
||||
{
|
||||
float DeviceScale = GetDeviceScale();
|
||||
|
||||
mView->SetMousePosition(MouseEvent->x() * DeviceScale, mView->GetHeight() - MouseEvent->y() * DeviceScale - 1);
|
||||
mView->SetMouseModifiers(MouseEvent->modifiers());
|
||||
|
||||
mView->OnMouseMove();
|
||||
}
|
||||
|
||||
void lcViewWidget::wheelEvent(QWheelEvent* WheelEvent)
|
||||
{
|
||||
if (WheelEvent->angleDelta().y() == 0)
|
||||
{
|
||||
WheelEvent->ignore();
|
||||
return;
|
||||
}
|
||||
|
||||
float DeviceScale = GetDeviceScale();
|
||||
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
|
||||
mView->SetMousePosition(WheelEvent->position().x() * DeviceScale, mView->GetHeight() - WheelEvent->position().y() * DeviceScale - 1);
|
||||
#else
|
||||
mView->SetMousePosition(WheelEvent->x() * DeviceScale, mView->GetHeight() - WheelEvent->y() * DeviceScale - 1);
|
||||
#endif
|
||||
mView->SetMouseModifiers(WheelEvent->modifiers());
|
||||
|
||||
mWheelAccumulator += WheelEvent->angleDelta().y() / 8;
|
||||
int numSteps = mWheelAccumulator / 15;
|
||||
|
||||
if (numSteps)
|
||||
{
|
||||
mView->OnMouseWheel(numSteps);
|
||||
mWheelAccumulator -= numSteps * 15;
|
||||
}
|
||||
|
||||
WheelEvent->accept();
|
||||
}
|
||||
|
||||
void lcViewWidget::dragEnterEvent(QDragEnterEvent* DragEnterEvent)
|
||||
{
|
||||
const QMimeData* MimeData = DragEnterEvent->mimeData();
|
||||
|
||||
if (MimeData->hasFormat("application/vnd.leocad-part"))
|
||||
{
|
||||
DragEnterEvent->acceptProposedAction();
|
||||
mView->BeginDrag(lcDragState::Piece);
|
||||
return;
|
||||
}
|
||||
else if (MimeData->hasFormat("application/vnd.leocad-color"))
|
||||
{
|
||||
DragEnterEvent->acceptProposedAction();
|
||||
mView->BeginDrag(lcDragState::Color);
|
||||
return;
|
||||
}
|
||||
|
||||
DragEnterEvent->ignore();
|
||||
}
|
||||
|
||||
void lcViewWidget::dragLeaveEvent(QDragLeaveEvent* DragLeaveEvent)
|
||||
{
|
||||
mView->EndDrag(false);
|
||||
DragLeaveEvent->accept();
|
||||
}
|
||||
|
||||
void lcViewWidget::dragMoveEvent(QDragMoveEvent* DragMoveEvent)
|
||||
{
|
||||
const QMimeData* MimeData = DragMoveEvent->mimeData();
|
||||
|
||||
if (MimeData->hasFormat("application/vnd.leocad-part") || MimeData->hasFormat("application/vnd.leocad-color"))
|
||||
{
|
||||
float DeviceScale = GetDeviceScale();
|
||||
|
||||
mView->SetMousePosition(DragMoveEvent->pos().x() * DeviceScale, mView->GetHeight() - DragMoveEvent->pos().y() * DeviceScale - 1);
|
||||
mView->SetMouseModifiers(DragMoveEvent->keyboardModifiers());
|
||||
|
||||
mView->OnMouseMove();
|
||||
|
||||
DragMoveEvent->accept();
|
||||
return;
|
||||
}
|
||||
|
||||
QOpenGLWidget::dragMoveEvent(DragMoveEvent);
|
||||
}
|
||||
|
||||
void lcViewWidget::dropEvent(QDropEvent* DropEvent)
|
||||
{
|
||||
const QMimeData* MimeData = DropEvent->mimeData();
|
||||
|
||||
if (MimeData->hasFormat("application/vnd.leocad-part") || MimeData->hasFormat("application/vnd.leocad-color"))
|
||||
{
|
||||
mView->EndDrag(true);
|
||||
setFocus(Qt::MouseFocusReason);
|
||||
|
||||
DropEvent->accept();
|
||||
return;
|
||||
}
|
||||
|
||||
QOpenGLWidget::dropEvent(DropEvent);
|
||||
}
|
|
@ -1,35 +1,37 @@
|
|||
#pragma once
|
||||
|
||||
#include <QGLWidget>
|
||||
class lcGLWidget;
|
||||
|
||||
class lcQGLWidget : public QGLWidget
|
||||
class lcViewWidget : public QOpenGLWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
lcQGLWidget(QWidget* Parent, lcGLWidget* Owner, bool IsView);
|
||||
~lcQGLWidget();
|
||||
lcViewWidget(QWidget* Parent, lcView* View);
|
||||
~lcViewWidget();
|
||||
|
||||
lcView* GetView() const
|
||||
{
|
||||
return mView;
|
||||
}
|
||||
|
||||
void SetView(lcView* View);
|
||||
|
||||
QSize sizeHint() const override;
|
||||
|
||||
lcGLWidget *widget;
|
||||
QSize preferredSize;
|
||||
bool mIsView;
|
||||
|
||||
float deviceScale()
|
||||
protected:
|
||||
float GetDeviceScale() const
|
||||
{
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
|
||||
return windowHandle()->devicePixelRatio();
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
|
||||
return devicePixelRatioF();
|
||||
#else
|
||||
return 1.0f;
|
||||
return devicePixelRatio();
|
||||
#endif
|
||||
}
|
||||
|
||||
QTimer mUpdateTimer;
|
||||
|
||||
protected:
|
||||
void initializeGL() override;
|
||||
void resizeGL(int Width, int Height) override;
|
||||
void paintGL() override;
|
||||
void focusInEvent(QFocusEvent* FocusEvent) override;
|
||||
void focusOutEvent(QFocusEvent* FocusEvent) override;
|
||||
void keyPressEvent(QKeyEvent* KeyEvent) override;
|
||||
void keyReleaseEvent(QKeyEvent* KeyEvent) override;
|
||||
void mousePressEvent(QMouseEvent* MouseEvent) override;
|
||||
|
@ -42,6 +44,7 @@ protected:
|
|||
void dragMoveEvent(QDragMoveEvent* DragMoveEvent) override;
|
||||
void dropEvent(QDropEvent* DropEvent) override;
|
||||
|
||||
lcView* mView;
|
||||
QSize mPreferredSize;
|
||||
int mWheelAccumulator;
|
||||
};
|
||||
|
|
@ -14,32 +14,25 @@
|
|||
lcZipFile::lcZipFile()
|
||||
{
|
||||
mModified = false;
|
||||
mFile = nullptr;
|
||||
}
|
||||
|
||||
lcZipFile::~lcZipFile()
|
||||
{
|
||||
delete mFile;
|
||||
}
|
||||
|
||||
bool lcZipFile::OpenRead(const QString& FileName)
|
||||
{
|
||||
lcDiskFile* File = new lcDiskFile(FileName);
|
||||
mFile = File;
|
||||
std::unique_ptr<lcDiskFile> File(new lcDiskFile(FileName));
|
||||
|
||||
if (!File->Open(QIODevice::ReadOnly) || !Open())
|
||||
{
|
||||
delete File;
|
||||
mFile = nullptr;
|
||||
if (!File->Open(QIODevice::ReadOnly))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return OpenRead(std::move(File));
|
||||
}
|
||||
|
||||
bool lcZipFile::OpenRead(lcFile* File)
|
||||
bool lcZipFile::OpenRead(std::unique_ptr<lcFile> File)
|
||||
{
|
||||
mFile = File;
|
||||
mFile = std::move(File);
|
||||
|
||||
if (!Open())
|
||||
{
|
||||
|
@ -52,8 +45,12 @@ bool lcZipFile::OpenRead(lcFile* File)
|
|||
|
||||
bool lcZipFile::OpenWrite(const QString& FileName)
|
||||
{
|
||||
lcDiskFile* File = new lcDiskFile(FileName);
|
||||
mFile = File;
|
||||
std::unique_ptr<lcDiskFile> File(new lcDiskFile(FileName));
|
||||
|
||||
if (!File->Open(QIODevice::WriteOnly))
|
||||
return false;
|
||||
|
||||
mFile = std::move(File);
|
||||
|
||||
mNumEntries = 0;
|
||||
mCentralDirSize = 0;
|
||||
|
@ -61,13 +58,6 @@ bool lcZipFile::OpenWrite(const QString& FileName)
|
|||
mBytesBeforeZipFile = 0;
|
||||
mCentralPos = 0;
|
||||
|
||||
if (!File->Open(QIODevice::WriteOnly))
|
||||
{
|
||||
delete File;
|
||||
mFile = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ public:
|
|||
lcZipFile& operator=(lcZipFile&&) = delete;
|
||||
|
||||
bool OpenRead(const QString& FileName);
|
||||
bool OpenRead(lcFile* File);
|
||||
bool OpenRead(std::unique_ptr<lcFile> File);
|
||||
bool OpenWrite(const QString& FileName);
|
||||
|
||||
bool ExtractFile(int FileIndex, lcMemFile& File, quint32 MaxLength = 0xffffffff);
|
||||
|
@ -74,7 +74,7 @@ protected:
|
|||
bool CheckFileCoherencyHeader(int FileIndex, quint32* SizeVar, quint64* OffsetLocalExtraField, quint32* SizeLocalExtraField);
|
||||
|
||||
QMutex mMutex;
|
||||
lcFile* mFile;
|
||||
std::unique_ptr<lcFile> mFile;
|
||||
|
||||
bool mModified;
|
||||
bool mZip64;
|
||||
|
|
108
common/light.cpp
108
common/light.cpp
|
@ -32,16 +32,15 @@ lcLight::lcLight(float px, float py, float pz, float tx, float ty, float tz)
|
|||
void lcLight::Initialize(const lcVector3& Position, const lcVector3& TargetPosition)
|
||||
{
|
||||
mState = 0;
|
||||
memset(m_strName, 0, sizeof(m_strName));
|
||||
|
||||
ChangeKey(mPositionKeys, Position, 1, true);
|
||||
ChangeKey(mTargetPositionKeys, TargetPosition, 1, true);
|
||||
ChangeKey(mAmbientColorKeys, lcVector4(0.0f, 0.0f, 0.0f, 1.0f), 1, true);
|
||||
ChangeKey(mDiffuseColorKeys, lcVector4(0.8f, 0.8f, 0.8f, 1.0f), 1, true);
|
||||
ChangeKey(mSpecularColorKeys, lcVector4(1.0f, 1.0f, 1.0f, 1.0f), 1, true);
|
||||
ChangeKey(mAttenuationKeys, lcVector3(1.0f, 0.0f, 0.0f), 1, true);
|
||||
ChangeKey(mSpotCutoffKeys, 30.0f, 1, true);
|
||||
ChangeKey(mSpotExponentKeys, 0.0f, 1, true);
|
||||
mPositionKeys.ChangeKey(Position, 1, true);
|
||||
mTargetPositionKeys.ChangeKey(TargetPosition, 1, true);
|
||||
mAmbientColorKeys.ChangeKey(lcVector4(0.0f, 0.0f, 0.0f, 1.0f), 1, true);
|
||||
mDiffuseColorKeys.ChangeKey(lcVector4(0.8f, 0.8f, 0.8f, 1.0f), 1, true);
|
||||
mSpecularColorKeys.ChangeKey(lcVector4(1.0f, 1.0f, 1.0f, 1.0f), 1, true);
|
||||
mAttenuationKeys.ChangeKey(lcVector3(1.0f, 0.0f, 0.0f), 1, true);
|
||||
mSpotCutoffKeys.ChangeKey(30.0f, 1, true);
|
||||
mSpotExponentKeys.ChangeKey(0.0f, 1, true);
|
||||
}
|
||||
|
||||
lcLight::~lcLight()
|
||||
|
@ -55,13 +54,13 @@ void lcLight::SaveLDraw(QTextStream& Stream) const
|
|||
|
||||
void lcLight::CreateName(const lcArray<lcLight*>& Lights)
|
||||
{
|
||||
if (m_strName[0])
|
||||
if (!mName.isEmpty())
|
||||
{
|
||||
bool Found = false;
|
||||
|
||||
for (lcLight* Light : Lights)
|
||||
{
|
||||
if (!strcmp(Light->m_strName, m_strName))
|
||||
if (Light->GetName() == mName)
|
||||
{
|
||||
Found = true;
|
||||
break;
|
||||
|
@ -72,21 +71,24 @@ void lcLight::CreateName(const lcArray<lcLight*>& Lights)
|
|||
return;
|
||||
}
|
||||
|
||||
int i, max = 0;
|
||||
int MaxLightNumber = 0;
|
||||
const QLatin1String Prefix("Light ");
|
||||
|
||||
for (lcLight* Light : Lights)
|
||||
{
|
||||
if (strncmp(Light->m_strName, "Light ", 6) == 0)
|
||||
QString LightName = Light->GetName();
|
||||
|
||||
if (LightName.startsWith(Prefix))
|
||||
{
|
||||
if (sscanf(Light->m_strName + 6, " #%d", &i) == 1)
|
||||
{
|
||||
if (i > max)
|
||||
max = i;
|
||||
}
|
||||
bool Ok = false;
|
||||
int LightNumber = LightName.midRef(Prefix.size()).toInt(&Ok);
|
||||
|
||||
if (Ok && LightNumber > MaxLightNumber)
|
||||
MaxLightNumber = LightNumber;
|
||||
}
|
||||
}
|
||||
|
||||
sprintf(m_strName, "Light #%.2d", max+1);
|
||||
mName = Prefix + QString::number(MaxLightNumber + 1);
|
||||
}
|
||||
|
||||
void lcLight::CompareBoundingBox(lcVector3& Min, lcVector3& Max)
|
||||
|
@ -207,50 +209,50 @@ void lcLight::MoveSelected(lcStep Step, bool AddKey, const lcVector3& Distance)
|
|||
if (IsSelected(LC_LIGHT_SECTION_POSITION))
|
||||
{
|
||||
mPosition += Distance;
|
||||
ChangeKey(mPositionKeys, mPosition, Step, AddKey);
|
||||
mPositionKeys.ChangeKey(mPosition, Step, AddKey);
|
||||
}
|
||||
|
||||
if (IsSelected(LC_LIGHT_SECTION_TARGET))
|
||||
{
|
||||
mTargetPosition += Distance;
|
||||
ChangeKey(mTargetPositionKeys, mTargetPosition, Step, AddKey);
|
||||
mTargetPositionKeys.ChangeKey(mTargetPosition, Step, AddKey);
|
||||
}
|
||||
}
|
||||
|
||||
void lcLight::InsertTime(lcStep Start, lcStep Time)
|
||||
{
|
||||
lcObject::InsertTime(mPositionKeys, Start, Time);
|
||||
lcObject::InsertTime(mTargetPositionKeys, Start, Time);
|
||||
lcObject::InsertTime(mAmbientColorKeys, Start, Time);
|
||||
lcObject::InsertTime(mDiffuseColorKeys, Start, Time);
|
||||
lcObject::InsertTime(mSpecularColorKeys, Start, Time);
|
||||
lcObject::InsertTime(mAttenuationKeys, Start, Time);
|
||||
lcObject::InsertTime(mSpotCutoffKeys, Start, Time);
|
||||
lcObject::InsertTime(mSpotExponentKeys, Start, Time);
|
||||
mPositionKeys.InsertTime(Start, Time);
|
||||
mTargetPositionKeys.InsertTime(Start, Time);
|
||||
mAmbientColorKeys.InsertTime(Start, Time);
|
||||
mDiffuseColorKeys.InsertTime(Start, Time);
|
||||
mSpecularColorKeys.InsertTime(Start, Time);
|
||||
mAttenuationKeys.InsertTime(Start, Time);
|
||||
mSpotCutoffKeys.InsertTime(Start, Time);
|
||||
mSpotExponentKeys.InsertTime(Start, Time);
|
||||
}
|
||||
|
||||
void lcLight::RemoveTime(lcStep Start, lcStep Time)
|
||||
{
|
||||
lcObject::RemoveTime(mPositionKeys, Start, Time);
|
||||
lcObject::RemoveTime(mTargetPositionKeys, Start, Time);
|
||||
lcObject::RemoveTime(mAmbientColorKeys, Start, Time);
|
||||
lcObject::RemoveTime(mDiffuseColorKeys, Start, Time);
|
||||
lcObject::RemoveTime(mSpecularColorKeys, Start, Time);
|
||||
lcObject::RemoveTime(mAttenuationKeys, Start, Time);
|
||||
lcObject::RemoveTime(mSpotCutoffKeys, Start, Time);
|
||||
lcObject::RemoveTime(mSpotExponentKeys, Start, Time);
|
||||
mPositionKeys.RemoveTime(Start, Time);
|
||||
mTargetPositionKeys.RemoveTime(Start, Time);
|
||||
mAmbientColorKeys.RemoveTime(Start, Time);
|
||||
mDiffuseColorKeys.RemoveTime(Start, Time);
|
||||
mSpecularColorKeys.RemoveTime(Start, Time);
|
||||
mAttenuationKeys.RemoveTime(Start, Time);
|
||||
mSpotCutoffKeys.RemoveTime(Start, Time);
|
||||
mSpotExponentKeys.RemoveTime(Start, Time);
|
||||
}
|
||||
|
||||
void lcLight::UpdatePosition(lcStep Step)
|
||||
{
|
||||
mPosition = CalculateKey(mPositionKeys, Step);
|
||||
mTargetPosition = CalculateKey(mTargetPositionKeys, Step);
|
||||
mAmbientColor = CalculateKey(mAmbientColorKeys, Step);
|
||||
mDiffuseColor = CalculateKey(mDiffuseColorKeys, Step);
|
||||
mSpecularColor = CalculateKey(mSpecularColorKeys, Step);
|
||||
mAttenuation = CalculateKey(mAttenuationKeys, Step);
|
||||
mSpotCutoff = CalculateKey(mSpotCutoffKeys, Step);
|
||||
mSpotExponent = CalculateKey(mSpotExponentKeys, Step);
|
||||
mPosition = mPositionKeys.CalculateKey(Step);
|
||||
mTargetPosition = mTargetPositionKeys.CalculateKey(Step);
|
||||
mAmbientColor = mAmbientColorKeys.CalculateKey(Step);
|
||||
mDiffuseColor = mDiffuseColorKeys.CalculateKey(Step);
|
||||
mSpecularColor = mSpecularColorKeys.CalculateKey(Step);
|
||||
mAttenuation = mAttenuationKeys.CalculateKey(Step);
|
||||
mSpotCutoff = mSpotCutoffKeys.CalculateKey(Step);
|
||||
mSpotExponent = mSpotExponentKeys.CalculateKey(Step);
|
||||
|
||||
if (IsPointLight())
|
||||
{
|
||||
|
@ -527,28 +529,28 @@ void lcLight::DrawPointLight(lcContext* Context) const
|
|||
void lcLight::RemoveKeyFrames()
|
||||
{
|
||||
mPositionKeys.RemoveAll();
|
||||
ChangeKey(mPositionKeys, mPosition, 1, true);
|
||||
mPositionKeys.ChangeKey(mPosition, 1, true);
|
||||
|
||||
mTargetPositionKeys.RemoveAll();
|
||||
ChangeKey(mTargetPositionKeys, mTargetPosition, 1, true);
|
||||
mTargetPositionKeys.ChangeKey(mTargetPosition, 1, true);
|
||||
|
||||
mAmbientColorKeys.RemoveAll();
|
||||
ChangeKey(mAmbientColorKeys, mAmbientColor, 1, true);
|
||||
mAmbientColorKeys.ChangeKey(mAmbientColor, 1, true);
|
||||
|
||||
mDiffuseColorKeys.RemoveAll();
|
||||
ChangeKey(mDiffuseColorKeys, mDiffuseColor, 1, true);
|
||||
mDiffuseColorKeys.ChangeKey(mDiffuseColor, 1, true);
|
||||
|
||||
mSpecularColorKeys.RemoveAll();
|
||||
ChangeKey(mSpecularColorKeys, mSpecularColor, 1, true);
|
||||
mSpecularColorKeys.ChangeKey(mSpecularColor, 1, true);
|
||||
|
||||
mAttenuationKeys.RemoveAll();
|
||||
ChangeKey(mAttenuationKeys, mAttenuation, 1, true);
|
||||
mAttenuationKeys.ChangeKey(mAttenuation, 1, true);
|
||||
|
||||
mSpotCutoffKeys.RemoveAll();
|
||||
ChangeKey(mSpotCutoffKeys, mSpotCutoff, 1, true);
|
||||
mSpotCutoffKeys.ChangeKey(mSpotCutoff, 1, true);
|
||||
|
||||
mSpotExponentKeys.RemoveAll();
|
||||
ChangeKey(mSpotExponentKeys, mSpotExponent, 1, true);
|
||||
mSpotExponentKeys.ChangeKey(mSpotExponent, 1, true);
|
||||
}
|
||||
|
||||
bool lcLight::Setup(int LightIndex)
|
||||
|
|
|
@ -191,8 +191,10 @@ public:
|
|||
bool IsVisible() const
|
||||
{ return (mState & LC_LIGHT_HIDDEN) == 0; }
|
||||
|
||||
const char* GetName() const override
|
||||
{ return m_strName; }
|
||||
QString GetName() const override
|
||||
{
|
||||
return mName;
|
||||
}
|
||||
|
||||
void CompareBoundingBox(lcVector3& Min, lcVector3& Max);
|
||||
void UpdatePosition(lcStep Step);
|
||||
|
@ -212,21 +214,20 @@ public:
|
|||
float mSpotExponent;
|
||||
|
||||
protected:
|
||||
lcArray<lcObjectKey<lcVector3>> mPositionKeys;
|
||||
lcArray<lcObjectKey<lcVector3>> mTargetPositionKeys;
|
||||
lcArray<lcObjectKey<lcVector4>> mAmbientColorKeys;
|
||||
lcArray<lcObjectKey<lcVector4>> mDiffuseColorKeys;
|
||||
lcArray<lcObjectKey<lcVector4>> mSpecularColorKeys;
|
||||
lcArray<lcObjectKey<lcVector3>> mAttenuationKeys;
|
||||
lcArray<lcObjectKey<float>> mSpotCutoffKeys;
|
||||
lcArray<lcObjectKey<float>> mSpotExponentKeys;
|
||||
lcObjectKeyArray<lcVector3> mPositionKeys;
|
||||
lcObjectKeyArray<lcVector3> mTargetPositionKeys;
|
||||
lcObjectKeyArray<lcVector4> mAmbientColorKeys;
|
||||
lcObjectKeyArray<lcVector4> mDiffuseColorKeys;
|
||||
lcObjectKeyArray<lcVector4> mSpecularColorKeys;
|
||||
lcObjectKeyArray<lcVector3> mAttenuationKeys;
|
||||
lcObjectKeyArray<float> mSpotCutoffKeys;
|
||||
lcObjectKeyArray<float> mSpotExponentKeys;
|
||||
|
||||
void Initialize(const lcVector3& Position, const lcVector3& TargetPosition);
|
||||
|
||||
void DrawPointLight(lcContext* Context) const;
|
||||
void DrawSpotLight(lcContext* Context) const;
|
||||
|
||||
QString mName;
|
||||
quint32 mState;
|
||||
char m_strName[81];
|
||||
};
|
||||
|
||||
|
|
|
@ -1,16 +1,10 @@
|
|||
#include "lc_global.h"
|
||||
#include "lc_colors.h"
|
||||
#include "lc_math.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "minifig.h"
|
||||
#include "lc_colors.h"
|
||||
#include "pieceinf.h"
|
||||
#include "project.h"
|
||||
#include "lc_model.h"
|
||||
#include "lc_library.h"
|
||||
#include "lc_application.h"
|
||||
#include "lc_context.h"
|
||||
#include "lc_scene.h"
|
||||
#include "lc_file.h"
|
||||
#include "lc_profile.h"
|
||||
|
||||
|
@ -36,15 +30,10 @@ const char* MinifigWizard::mSectionNames[LC_MFW_NUMITEMS] =
|
|||
};
|
||||
|
||||
MinifigWizard::MinifigWizard()
|
||||
: mModel(new lcModel(QString(), nullptr, false))
|
||||
{
|
||||
LoadSettings();
|
||||
LoadTemplates();
|
||||
|
||||
mRotateX = 75.0f;
|
||||
mRotateZ = 180.0f;
|
||||
mDistance = 10.0f;
|
||||
mAutoZoom = true;
|
||||
mTracking = LC_TRACK_NONE;
|
||||
}
|
||||
|
||||
MinifigWizard::~MinifigWizard()
|
||||
|
@ -53,7 +42,7 @@ MinifigWizard::~MinifigWizard()
|
|||
|
||||
for (int i = 0; i < LC_MFW_NUMITEMS; i++)
|
||||
if (mMinifig.Parts[i])
|
||||
Library->ReleasePieceInfo(mMinifig.Parts[i]);
|
||||
Library->ReleasePieceInfo(mMinifig.Parts[i]); // todo: don't call ReleasePieceInfo here because it may release textures and they need a GL context current
|
||||
|
||||
SaveTemplates();
|
||||
}
|
||||
|
@ -73,29 +62,15 @@ void MinifigWizard::LoadSettings()
|
|||
}
|
||||
}
|
||||
|
||||
QResource Resource(":/resources/minifig.ini");
|
||||
lcDiskFile MinifigFile(":/resources/minifig.ini");
|
||||
|
||||
if (Resource.isValid())
|
||||
{
|
||||
QByteArray Data;
|
||||
|
||||
if (Resource.isCompressed())
|
||||
Data = qUncompress(Resource.data(), Resource.size());
|
||||
else
|
||||
Data = QByteArray::fromRawData((const char*)Resource.data(), Resource.size());
|
||||
|
||||
lcMemFile MemSettings;
|
||||
MemSettings.WriteBuffer(Data.constData(), Data.size());
|
||||
ParseSettings(MemSettings);
|
||||
}
|
||||
if (MinifigFile.Open(QIODevice::ReadOnly))
|
||||
ParseSettings(MinifigFile);
|
||||
}
|
||||
|
||||
void MinifigWizard::OnInitialUpdate()
|
||||
void MinifigWizard::LoadDefault()
|
||||
{
|
||||
MakeCurrent();
|
||||
mContext->SetDefaultState();
|
||||
|
||||
static_assert(LC_ARRAY_COUNT(MinifigWizard::mSectionNames) == LC_MFW_NUMITEMS, "Array size mismatch.");
|
||||
LC_ARRAY_SIZE_CHECK(MinifigWizard::mSectionNames, LC_MFW_NUMITEMS);
|
||||
|
||||
const int ColorCodes[LC_MFW_NUMITEMS] = { 4, 7, 14, 7, 1, 0, 7, 4, 4, 14, 14, 7, 7, 0, 0, 7, 7 };
|
||||
const char* const Pieces[LC_MFW_NUMITEMS] = { "3624.dat", "", "3626bp01.dat", "", "973.dat", "3815.dat", "", "3819.dat", "3818.dat", "3820.dat", "3820.dat", "", "", "3817.dat", "3816.dat", "", "" };
|
||||
|
@ -229,7 +204,6 @@ void MinifigWizard::DeleteTemplate(const QString& TemplateName)
|
|||
|
||||
void MinifigWizard::AddTemplatesJson(const QByteArray& TemplateData)
|
||||
{
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
|
||||
QJsonDocument Document = QJsonDocument::fromJson(TemplateData);
|
||||
QJsonObject RootObject = Document.object();
|
||||
|
||||
|
@ -260,17 +234,10 @@ void MinifigWizard::AddTemplatesJson(const QByteArray& TemplateData)
|
|||
|
||||
mTemplates.emplace(ElementIt.key(), std::move(Template));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
QByteArray MinifigWizard::GetTemplatesJson() const
|
||||
{
|
||||
QByteArray TemplateData;
|
||||
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
|
||||
QJsonObject RootObject;
|
||||
|
||||
RootObject["Version"] = 1;
|
||||
QJsonObject TemplatesObject;
|
||||
|
||||
for (const auto& TemplateEntry : mTemplates)
|
||||
|
@ -292,11 +259,11 @@ QByteArray MinifigWizard::GetTemplatesJson() const
|
|||
TemplatesObject[TemplateEntry.first] = TemplateObject;
|
||||
}
|
||||
|
||||
QJsonObject RootObject;
|
||||
RootObject["Templates"] = TemplatesObject;
|
||||
TemplateData = QJsonDocument(RootObject).toJson();
|
||||
#endif
|
||||
RootObject["Version"] = 1;
|
||||
|
||||
return TemplateData;
|
||||
return QJsonDocument(RootObject).toJson();
|
||||
}
|
||||
|
||||
void MinifigWizard::LoadTemplates()
|
||||
|
@ -312,162 +279,9 @@ void MinifigWizard::LoadTemplates()
|
|||
|
||||
void MinifigWizard::SaveTemplates()
|
||||
{
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
|
||||
QSettings Settings;
|
||||
Settings.beginGroup("Minifig");
|
||||
Settings.setValue("Templates", GetTemplatesJson());
|
||||
#endif
|
||||
}
|
||||
|
||||
void MinifigWizard::OnDraw()
|
||||
{
|
||||
mContext->SetDefaultState();
|
||||
|
||||
const float Aspect = (float)mWidth/(float)mHeight;
|
||||
mContext->SetViewport(0, 0, mWidth, mHeight);
|
||||
|
||||
lcGetActiveModel()->DrawBackground(this);
|
||||
|
||||
lcVector3 Min(FLT_MAX, FLT_MAX, FLT_MAX), Max(-FLT_MAX, -FLT_MAX, -FLT_MAX);
|
||||
|
||||
for (int InfoIdx = 0; InfoIdx < LC_MFW_NUMITEMS; InfoIdx++)
|
||||
{
|
||||
const PieceInfo* const Info = mMinifig.Parts[InfoIdx];
|
||||
|
||||
if (!Info)
|
||||
continue;
|
||||
|
||||
lcVector3 Points[8];
|
||||
lcGetBoxCorners(Info->GetBoundingBox(), Points);
|
||||
|
||||
for (int PointIdx = 0; PointIdx < 8; PointIdx++)
|
||||
{
|
||||
const lcVector3 Point = lcMul31(Points[PointIdx], mMinifig.Matrices[InfoIdx]);
|
||||
|
||||
Min = lcMin(Point, Min);
|
||||
Max = lcMax(Point, Max);
|
||||
}
|
||||
}
|
||||
|
||||
const lcVector3 Center = (Min + Max) / 2.0f;
|
||||
|
||||
lcVector3 Eye(0.0f, 0.0f, 1.0f);
|
||||
|
||||
Eye = lcMul30(Eye, lcMatrix44RotationX(-mRotateX * LC_DTOR));
|
||||
Eye = lcMul30(Eye, lcMatrix44RotationZ(-mRotateZ * LC_DTOR));
|
||||
|
||||
const lcMatrix44 Projection = lcMatrix44Perspective(30.0f, Aspect, 1.0f, 2500.0f);
|
||||
mContext->SetProjectionMatrix(Projection);
|
||||
|
||||
lcMatrix44 ViewMatrix;
|
||||
|
||||
if (mAutoZoom)
|
||||
{
|
||||
lcVector3 Points[8];
|
||||
lcGetBoxCorners(Min, Max, Points);
|
||||
|
||||
Eye += Center;
|
||||
|
||||
const lcMatrix44 ModelView = lcMatrix44LookAt(Eye, Center, lcVector3(0, 0, 1));
|
||||
std::tie(Eye, std::ignore) = lcZoomExtents(Eye, ModelView, Projection, Points, 8);
|
||||
|
||||
ViewMatrix = lcMatrix44LookAt(Eye, Center, lcVector3(0, 0, 1));
|
||||
|
||||
const lcVector3 d = Eye - Center;
|
||||
mDistance = d.Length();
|
||||
}
|
||||
else
|
||||
{
|
||||
ViewMatrix = lcMatrix44LookAt(Eye * mDistance, Center, lcVector3(0, 0, 1));
|
||||
}
|
||||
|
||||
Calculate();
|
||||
|
||||
lcScene Scene;
|
||||
Scene.Begin(ViewMatrix);
|
||||
Scene.SetAllowLOD(false);
|
||||
|
||||
for (int PieceIdx = 0; PieceIdx < LC_MFW_NUMITEMS; PieceIdx++)
|
||||
if (mMinifig.Parts[PieceIdx])
|
||||
mMinifig.Parts[PieceIdx]->AddRenderMeshes(Scene, mMinifig.Matrices[PieceIdx], mMinifig.Colors[PieceIdx], lcRenderMeshState::Default, true);
|
||||
|
||||
Scene.End();
|
||||
|
||||
Scene.Draw(mContext);
|
||||
|
||||
mContext->ClearResources();
|
||||
}
|
||||
|
||||
void MinifigWizard::OnLeftButtonDown()
|
||||
{
|
||||
if (mTracking == LC_TRACK_NONE)
|
||||
{
|
||||
mDownX = mInputState.x;
|
||||
mDownY = mInputState.y;
|
||||
mTracking = LC_TRACK_LEFT;
|
||||
}
|
||||
}
|
||||
|
||||
void MinifigWizard::OnLeftButtonUp()
|
||||
{
|
||||
if (mTracking == LC_TRACK_LEFT)
|
||||
mTracking = LC_TRACK_NONE;
|
||||
}
|
||||
|
||||
void MinifigWizard::OnLeftButtonDoubleClick()
|
||||
{
|
||||
mAutoZoom = true;
|
||||
Redraw();
|
||||
}
|
||||
|
||||
void MinifigWizard::OnRightButtonDown()
|
||||
{
|
||||
if (mTracking == LC_TRACK_NONE)
|
||||
{
|
||||
mDownX = mInputState.x;
|
||||
mDownY = mInputState.y;
|
||||
mTracking = LC_TRACK_RIGHT;
|
||||
}
|
||||
}
|
||||
|
||||
void MinifigWizard::OnRightButtonUp()
|
||||
{
|
||||
if (mTracking == LC_TRACK_RIGHT)
|
||||
mTracking = LC_TRACK_NONE;
|
||||
}
|
||||
|
||||
void MinifigWizard::OnMouseMove()
|
||||
{
|
||||
if (mTracking == LC_TRACK_LEFT)
|
||||
{
|
||||
// Rotate.
|
||||
mRotateZ += mInputState.x - mDownX;
|
||||
mRotateX += mInputState.y - mDownY;
|
||||
|
||||
if (mRotateX > 179.5f)
|
||||
mRotateX = 179.5f;
|
||||
else if (mRotateX < 0.5f)
|
||||
mRotateX = 0.5f;
|
||||
|
||||
mDownX = mInputState.x;
|
||||
mDownY = mInputState.y;
|
||||
|
||||
Redraw();
|
||||
}
|
||||
else if (mTracking == LC_TRACK_RIGHT)
|
||||
{
|
||||
// Zoom.
|
||||
mDistance += (float)(mDownY - mInputState.y) * 0.2f;
|
||||
mAutoZoom = false;
|
||||
|
||||
if (mDistance < 0.5f)
|
||||
mDistance = 0.5f;
|
||||
|
||||
mDownX = mInputState.x;
|
||||
mDownY = mInputState.y;
|
||||
|
||||
Redraw();
|
||||
}
|
||||
}
|
||||
|
||||
void MinifigWizard::Calculate()
|
||||
|
@ -544,7 +358,7 @@ void MinifigWizard::Calculate()
|
|||
if (Parts[LC_MFW_RHANDA])
|
||||
{
|
||||
Mat = lcMatrix44RotationZ(LC_DTOR * Angles[LC_MFW_RHANDA]);
|
||||
Mat.SetTranslation(lcVector3(0, -10.0f, 0));
|
||||
Mat.SetTranslation(lcVector3(0, -9.25f, 0));
|
||||
Mat = lcMul(mSettings[LC_MFW_RHANDA][GetSelectionIndex(LC_MFW_RHANDA)].Offset, Mat);
|
||||
Mat = lcMul(Mat, lcMatrix44RotationX(LC_DTOR * 15.0f));
|
||||
Matrices[LC_MFW_RHANDA] = lcMul(Mat, Matrices[LC_MFW_RHAND]);
|
||||
|
@ -578,7 +392,7 @@ void MinifigWizard::Calculate()
|
|||
if (Parts[LC_MFW_LHANDA])
|
||||
{
|
||||
Mat = lcMatrix44RotationZ(LC_DTOR * Angles[LC_MFW_LHANDA]);
|
||||
Mat.SetTranslation(lcVector3(0, -10.0f, 0));
|
||||
Mat.SetTranslation(lcVector3(0, -9.25f, 0));
|
||||
Mat = lcMul(mSettings[LC_MFW_LHANDA][GetSelectionIndex(LC_MFW_LHANDA)].Offset, Mat);
|
||||
Mat = lcMul(Mat, lcMatrix44RotationX(LC_DTOR * 15.0f));
|
||||
Matrices[LC_MFW_LHANDA] = lcMul(Mat, Matrices[LC_MFW_LHAND]);
|
||||
|
@ -637,6 +451,8 @@ void MinifigWizard::Calculate()
|
|||
Mat.SetTranslation(lcMul31(Center, Mat2));
|
||||
Matrices[LC_MFW_LLEGA] = lcMul(Mat, Matrices[LC_MFW_LLEG]);
|
||||
}
|
||||
|
||||
mModel->SetMinifig(mMinifig);
|
||||
}
|
||||
|
||||
int MinifigWizard::GetSelectionIndex(int Type) const
|
||||
|
@ -653,7 +469,6 @@ int MinifigWizard::GetSelectionIndex(int Type) const
|
|||
void MinifigWizard::SetSelectionIndex(int Type, int Index)
|
||||
{
|
||||
lcPiecesLibrary* Library = lcGetPiecesLibrary();
|
||||
MakeCurrent();
|
||||
|
||||
if (mMinifig.Parts[Type])
|
||||
Library->ReleasePieceInfo(mMinifig.Parts[Type]);
|
||||
|
@ -669,9 +484,13 @@ void MinifigWizard::SetSelectionIndex(int Type, int Index)
|
|||
void MinifigWizard::SetColor(int Type, int Color)
|
||||
{
|
||||
mMinifig.Colors[Type] = Color;
|
||||
|
||||
Calculate();
|
||||
}
|
||||
|
||||
void MinifigWizard::SetAngle(int Type, float Angle)
|
||||
{
|
||||
mMinifig.Angles[Type] = Angle;
|
||||
|
||||
Calculate();
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#include "lc_glwidget.h"
|
||||
#include "lc_math.h"
|
||||
|
||||
enum LC_MFW_TYPES
|
||||
|
@ -47,16 +46,19 @@ struct lcMinifigTemplate
|
|||
float Angles[LC_MFW_NUMITEMS];
|
||||
};
|
||||
|
||||
class MinifigWizard : public lcGLWidget
|
||||
class MinifigWizard
|
||||
{
|
||||
public:
|
||||
MinifigWizard();
|
||||
~MinifigWizard();
|
||||
|
||||
MinifigWizard(const MinifigWizard&) = delete;
|
||||
MinifigWizard(MinifigWizard&&) = delete;
|
||||
MinifigWizard& operator=(const MinifigWizard&) = delete;
|
||||
MinifigWizard& operator=(MinifigWizard&&) = delete;
|
||||
|
||||
lcModel* GetModel() const
|
||||
{
|
||||
return mModel.get();
|
||||
}
|
||||
|
||||
const std::map<QString, lcMinifigTemplate>& GetTemplates() const
|
||||
{
|
||||
|
@ -68,14 +70,7 @@ public:
|
|||
void AddTemplatesJson(const QByteArray& TemplateData);
|
||||
QByteArray GetTemplatesJson() const;
|
||||
|
||||
void OnDraw() override;
|
||||
void OnLeftButtonDown() override;
|
||||
void OnLeftButtonUp() override;
|
||||
void OnLeftButtonDoubleClick() override;
|
||||
void OnRightButtonDown() override;
|
||||
void OnRightButtonUp() override;
|
||||
void OnMouseMove() override;
|
||||
void OnInitialUpdate() override;
|
||||
void LoadDefault();
|
||||
|
||||
void Calculate();
|
||||
int GetSelectionIndex(int Type) const;
|
||||
|
@ -83,26 +78,18 @@ public:
|
|||
void SetColor(int Type, int Color);
|
||||
void SetAngle(int Type, float Angle);
|
||||
|
||||
void ParseSettings(lcFile& Settings);
|
||||
|
||||
std::vector<lcMinifigPieceInfo> mSettings[LC_MFW_NUMITEMS];
|
||||
|
||||
lcMinifig mMinifig;
|
||||
|
||||
int mTracking;
|
||||
int mDownX;
|
||||
int mDownY;
|
||||
|
||||
float mDistance;
|
||||
float mRotateX;
|
||||
float mRotateZ;
|
||||
bool mAutoZoom;
|
||||
|
||||
protected:
|
||||
void LoadSettings();
|
||||
void ParseSettings(lcFile& Settings);
|
||||
|
||||
void LoadTemplates();
|
||||
void SaveTemplates();
|
||||
|
||||
std::unique_ptr<lcModel> mModel;
|
||||
std::map<QString, lcMinifigTemplate> mTemplates;
|
||||
static const char* mSectionNames[LC_MFW_NUMITEMS];
|
||||
};
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#include "lc_global.h"
|
||||
#include "object.h"
|
||||
#include "lc_file.h"
|
||||
|
||||
lcObject::lcObject(lcObjectType ObjectType)
|
||||
: mObjectType(ObjectType)
|
||||
|
@ -10,3 +9,162 @@ lcObject::lcObject(lcObjectType ObjectType)
|
|||
lcObject::~lcObject()
|
||||
{
|
||||
}
|
||||
|
||||
template void lcObjectKeyArray<float>::SaveKeysLDraw(QTextStream& Stream, const char* KeyName) const;
|
||||
template void lcObjectKeyArray<float>::LoadKeysLDraw(QTextStream& Stream);
|
||||
template const float& lcObjectKeyArray<float>::CalculateKey(lcStep Step) const;
|
||||
template void lcObjectKeyArray<float>::ChangeKey(const float& Value, lcStep Step, bool AddKey);
|
||||
template void lcObjectKeyArray<float>::InsertTime(lcStep Start, lcStep Time);
|
||||
template void lcObjectKeyArray<float>::RemoveTime(lcStep Start, lcStep Time);
|
||||
|
||||
template void lcObjectKeyArray<lcVector3>::SaveKeysLDraw(QTextStream& Stream, const char* KeyName) const;
|
||||
template void lcObjectKeyArray<lcVector3>::LoadKeysLDraw(QTextStream& Stream);
|
||||
template const lcVector3& lcObjectKeyArray<lcVector3>::CalculateKey(lcStep Step) const;
|
||||
template void lcObjectKeyArray<lcVector3>::ChangeKey(const lcVector3& Value, lcStep Step, bool AddKey);
|
||||
template void lcObjectKeyArray<lcVector3>::InsertTime(lcStep Start, lcStep Time);
|
||||
template void lcObjectKeyArray<lcVector3>::RemoveTime(lcStep Start, lcStep Time);
|
||||
|
||||
template void lcObjectKeyArray<lcVector4>::SaveKeysLDraw(QTextStream& Stream, const char* KeyName) const;
|
||||
template void lcObjectKeyArray<lcVector4>::LoadKeysLDraw(QTextStream& Stream);
|
||||
template const lcVector4& lcObjectKeyArray<lcVector4>::CalculateKey(lcStep Step) const;
|
||||
template void lcObjectKeyArray<lcVector4>::ChangeKey(const lcVector4& Value, lcStep Step, bool AddKey);
|
||||
template void lcObjectKeyArray<lcVector4>::InsertTime(lcStep Start, lcStep Time);
|
||||
template void lcObjectKeyArray<lcVector4>::RemoveTime(lcStep Start, lcStep Time);
|
||||
|
||||
template void lcObjectKeyArray<lcMatrix33>::SaveKeysLDraw(QTextStream& Stream, const char* KeyName) const;
|
||||
template void lcObjectKeyArray<lcMatrix33>::LoadKeysLDraw(QTextStream& Stream);
|
||||
template const lcMatrix33& lcObjectKeyArray<lcMatrix33>::CalculateKey(lcStep Step) const;
|
||||
template void lcObjectKeyArray<lcMatrix33>::ChangeKey(const lcMatrix33& Value, lcStep Step, bool AddKey);
|
||||
template void lcObjectKeyArray<lcMatrix33>::InsertTime(lcStep Start, lcStep Time);
|
||||
template void lcObjectKeyArray<lcMatrix33>::RemoveTime(lcStep Start, lcStep Time);
|
||||
|
||||
template<typename T>
|
||||
void lcObjectKeyArray<T>::SaveKeysLDraw(QTextStream& Stream, const char* KeyName) const
|
||||
{
|
||||
const int Count = sizeof(T) / sizeof(float);
|
||||
|
||||
for (const lcObjectKey<T>& Key : mKeys)
|
||||
{
|
||||
Stream << QLatin1String("0 !LEOCAD ") << KeyName << Key.Step << ' ';
|
||||
|
||||
for (int ValueIdx = 0; ValueIdx < Count; ValueIdx++)
|
||||
Stream << ((float*)&Key.Value)[ValueIdx] << ' ';
|
||||
|
||||
Stream << QLatin1String("\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void lcObjectKeyArray<T>::LoadKeysLDraw(QTextStream& Stream)
|
||||
{
|
||||
QString Token;
|
||||
Stream >> Token;
|
||||
|
||||
int Step = Token.toInt();
|
||||
T Value;
|
||||
|
||||
const int Count = sizeof(T) / sizeof(float);
|
||||
|
||||
for (int ValueIdx = 0; ValueIdx < Count; ValueIdx++)
|
||||
Stream >> ((float*)&Value)[ValueIdx];
|
||||
|
||||
ChangeKey(Value, Step, true);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const T& lcObjectKeyArray<T>::CalculateKey(lcStep Step) const
|
||||
{
|
||||
const lcObjectKey<T>* PreviousKey = &mKeys[0];
|
||||
|
||||
for (const lcObjectKey<T>& Key : mKeys)
|
||||
{
|
||||
if (Key.Step > Step)
|
||||
break;
|
||||
|
||||
PreviousKey = &Key;
|
||||
}
|
||||
|
||||
return PreviousKey->Value;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void lcObjectKeyArray<T>::ChangeKey(const T& Value, lcStep Step, bool AddKey)
|
||||
{
|
||||
for (typename std::vector<lcObjectKey<T>>::iterator KeyIt = mKeys.begin(); KeyIt != mKeys.end(); KeyIt++)
|
||||
{
|
||||
if (KeyIt->Step < Step)
|
||||
continue;
|
||||
|
||||
if (KeyIt->Step == Step)
|
||||
KeyIt->Value = Value;
|
||||
else if (AddKey)
|
||||
mKeys.insert(KeyIt, lcObjectKey<T>{ Step, Value });
|
||||
else if (KeyIt == mKeys.begin())
|
||||
KeyIt->Value = Value;
|
||||
else
|
||||
{
|
||||
KeyIt = KeyIt - 1;
|
||||
KeyIt->Value = Value;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (AddKey || mKeys.empty())
|
||||
mKeys.emplace_back(lcObjectKey<T>{ Step, Value });
|
||||
else
|
||||
mKeys.back().Value = Value;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void lcObjectKeyArray<T>::InsertTime(lcStep Start, lcStep Time)
|
||||
{
|
||||
bool EndKey = false;
|
||||
|
||||
for (typename std::vector<lcObjectKey<T>>::iterator KeyIt = mKeys.begin(); KeyIt != mKeys.end();)
|
||||
{
|
||||
if ((KeyIt->Step < Start) || (KeyIt->Step == 1))
|
||||
{
|
||||
KeyIt++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (EndKey)
|
||||
{
|
||||
KeyIt = mKeys.erase(KeyIt);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (KeyIt->Step >= LC_STEP_MAX - Time)
|
||||
{
|
||||
KeyIt->Step = LC_STEP_MAX;
|
||||
EndKey = true;
|
||||
}
|
||||
else
|
||||
KeyIt->Step += Time;
|
||||
|
||||
KeyIt++;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void lcObjectKeyArray<T>::RemoveTime(lcStep Start, lcStep Time)
|
||||
{
|
||||
for (typename std::vector<lcObjectKey<T>>::iterator KeyIt = mKeys.begin(); KeyIt != mKeys.end();)
|
||||
{
|
||||
if ((KeyIt->Step < Start) || (KeyIt->Step == 1))
|
||||
{
|
||||
KeyIt++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (KeyIt->Step < Start + Time)
|
||||
{
|
||||
KeyIt = mKeys.erase(KeyIt);
|
||||
continue;
|
||||
}
|
||||
|
||||
KeyIt->Step -= Time;
|
||||
KeyIt++;
|
||||
}
|
||||
}
|
||||
|
|
178
common/object.h
178
common/object.h
|
@ -3,9 +3,6 @@
|
|||
#include "lc_math.h"
|
||||
#include "lc_array.h"
|
||||
|
||||
typedef quint32 lcStep;
|
||||
#define LC_STEP_MAX 0xffffffff
|
||||
|
||||
enum class lcObjectType
|
||||
{
|
||||
Piece,
|
||||
|
@ -20,6 +17,36 @@ struct lcObjectKey
|
|||
T Value;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class lcObjectKeyArray
|
||||
{
|
||||
public:
|
||||
int GetSize() const
|
||||
{
|
||||
return static_cast<int>(mKeys.size());
|
||||
}
|
||||
|
||||
bool IsEmpty() const
|
||||
{
|
||||
return mKeys.empty();
|
||||
}
|
||||
|
||||
void RemoveAll()
|
||||
{
|
||||
mKeys.clear();
|
||||
}
|
||||
|
||||
void SaveKeysLDraw(QTextStream& Stream, const char* KeyName) const;
|
||||
void LoadKeysLDraw(QTextStream& Stream);
|
||||
const T& CalculateKey(lcStep Step) const;
|
||||
void ChangeKey(const T& Value, lcStep Step, bool AddKey);
|
||||
void InsertTime(lcStep Start, lcStep Time);
|
||||
void RemoveTime(lcStep Start, lcStep Time);
|
||||
|
||||
protected:
|
||||
std::vector<lcObjectKey<T>> mKeys;
|
||||
};
|
||||
|
||||
struct lcObjectSection
|
||||
{
|
||||
lcObject* Object;
|
||||
|
@ -61,9 +88,7 @@ public:
|
|||
virtual ~lcObject();
|
||||
|
||||
lcObject(const lcObject&) = delete;
|
||||
lcObject(lcObject&&) = delete;
|
||||
lcObject& operator=(const lcObject&) = delete;
|
||||
lcObject& operator=(lcObject&&) = delete;
|
||||
|
||||
public:
|
||||
bool IsPiece() const
|
||||
|
@ -101,148 +126,7 @@ public:
|
|||
virtual void BoxTest(lcObjectBoxTest& ObjectBoxTest) const = 0;
|
||||
virtual void DrawInterface(lcContext* Context, const lcScene& Scene) const = 0;
|
||||
virtual void RemoveKeyFrames() = 0;
|
||||
virtual const char* GetName() const = 0;
|
||||
|
||||
protected:
|
||||
template<typename T>
|
||||
void SaveKeysLDraw(QTextStream& Stream, const lcArray<lcObjectKey<T>>& Keys, const char* KeyName) const
|
||||
{
|
||||
const int Count = sizeof(T) / sizeof(float);
|
||||
for (int KeyIdx = 0; KeyIdx < Keys.GetSize(); KeyIdx++)
|
||||
{
|
||||
const lcObjectKey<T>& Key = Keys[KeyIdx];
|
||||
Stream << QLatin1String("0 !LEOCAD ") << KeyName << Key.Step << ' ';
|
||||
for (int ValueIdx = 0; ValueIdx < Count; ValueIdx++)
|
||||
Stream << ((float*)&Key.Value)[ValueIdx] << ' ';
|
||||
Stream << QLatin1String("\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void LoadKeysLDraw(QTextStream& Stream, lcArray<lcObjectKey<T>>& Keys)
|
||||
{
|
||||
QString Token;
|
||||
Stream >> Token;
|
||||
|
||||
int Step = Token.toInt();
|
||||
T Value;
|
||||
|
||||
const int Count = sizeof(T) / sizeof(float);
|
||||
for (int ValueIdx = 0; ValueIdx < Count; ValueIdx++)
|
||||
Stream >> ((float*)&Value)[ValueIdx];
|
||||
|
||||
ChangeKey(Keys, Value, Step, true);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const T& CalculateKey(const lcArray<lcObjectKey<T>>& Keys, lcStep Step)
|
||||
{
|
||||
const lcObjectKey<T>* PreviousKey = &Keys[0];
|
||||
|
||||
for (int KeyIdx = 0; KeyIdx < Keys.GetSize(); KeyIdx++)
|
||||
{
|
||||
if (Keys[KeyIdx].Step > Step)
|
||||
break;
|
||||
|
||||
PreviousKey = &Keys[KeyIdx];
|
||||
}
|
||||
|
||||
return PreviousKey->Value;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void ChangeKey(lcArray<lcObjectKey<T>>& Keys, const T& Value, lcStep Step, bool AddKey)
|
||||
{
|
||||
for (int KeyIdx = 0; KeyIdx < Keys.GetSize(); KeyIdx++)
|
||||
{
|
||||
lcObjectKey<T>* Key = &Keys[KeyIdx];
|
||||
|
||||
if (Key->Step == Step)
|
||||
{
|
||||
Key->Value = Value;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (Key->Step > Step)
|
||||
{
|
||||
if (AddKey)
|
||||
{
|
||||
Key = &Keys.InsertAt(KeyIdx);
|
||||
Key->Step = Step;
|
||||
}
|
||||
else if (KeyIdx)
|
||||
Key = &Keys[KeyIdx - 1];
|
||||
|
||||
Key->Value = Value;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (AddKey || Keys.GetSize() == 0)
|
||||
{
|
||||
lcObjectKey<T>* Key = &Keys.Add();
|
||||
|
||||
Key->Step = Step;
|
||||
Key->Value = Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
lcObjectKey<T>* Key = &Keys[Keys.GetSize() - 1];
|
||||
Key->Value = Value;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void InsertTime(lcArray<lcObjectKey<T>>& Keys, lcStep Start, lcStep Time)
|
||||
{
|
||||
bool EndKey = false;
|
||||
|
||||
for (int KeyIdx = 0; KeyIdx < Keys.GetSize(); KeyIdx++)
|
||||
{
|
||||
lcObjectKey<T>& Key = Keys[KeyIdx];
|
||||
|
||||
if ((Key.Step < Start) || (Key.Step == 1))
|
||||
continue;
|
||||
|
||||
if (EndKey)
|
||||
{
|
||||
Keys.RemoveIndex(KeyIdx);
|
||||
KeyIdx--;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Key.Step >= LC_STEP_MAX - Time)
|
||||
{
|
||||
Key.Step = LC_STEP_MAX;
|
||||
EndKey = true;
|
||||
}
|
||||
else
|
||||
Key.Step += Time;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void RemoveTime(lcArray<lcObjectKey<T>>& Keys, lcStep Start, lcStep Time)
|
||||
{
|
||||
for (int KeyIdx = 0; KeyIdx < Keys.GetSize(); KeyIdx++)
|
||||
{
|
||||
lcObjectKey<T>& Key = Keys[KeyIdx];
|
||||
|
||||
if ((Key.Step < Start) || (Key.Step == 1))
|
||||
continue;
|
||||
|
||||
if (Key.Step < Start + Time)
|
||||
{
|
||||
Keys.RemoveIndex(KeyIdx);
|
||||
KeyIdx--;
|
||||
continue;
|
||||
}
|
||||
|
||||
Key.Step -= Time;
|
||||
}
|
||||
}
|
||||
virtual QString GetName() const = 0;
|
||||
|
||||
private:
|
||||
lcObjectType mObjectType;
|
||||
|
|
337
common/piece.cpp
337
common/piece.cpp
|
@ -123,10 +123,10 @@ void lcPiece::SaveLDraw(QTextStream& Stream) const
|
|||
}
|
||||
|
||||
if (mPositionKeys.GetSize() > 1)
|
||||
SaveKeysLDraw(Stream, mPositionKeys, "PIECE POSITION_KEY ");
|
||||
mPositionKeys.SaveKeysLDraw(Stream, "PIECE POSITION_KEY ");
|
||||
|
||||
if (mRotationKeys.GetSize() > 1)
|
||||
SaveKeysLDraw(Stream, mRotationKeys, "PIECE ROTATION_KEY ");
|
||||
mRotationKeys.SaveKeysLDraw(Stream, "PIECE ROTATION_KEY ");
|
||||
|
||||
Stream << "1 " << mColorCode << ' ';
|
||||
|
||||
|
@ -163,9 +163,9 @@ bool lcPiece::ParseLDrawLine(QTextStream& Stream)
|
|||
mState |= LC_PIECE_PIVOT_POINT_VALID;
|
||||
}
|
||||
else if (Token == QLatin1String("POSITION_KEY"))
|
||||
LoadKeysLDraw(Stream, mPositionKeys);
|
||||
mPositionKeys.LoadKeysLDraw(Stream);
|
||||
else if (Token == QLatin1String("ROTATION_KEY"))
|
||||
LoadKeysLDraw(Stream, mRotationKeys);
|
||||
mRotationKeys.LoadKeysLDraw(Stream);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -180,6 +180,8 @@ bool lcPiece::FileLoad(lcFile& file)
|
|||
if (version > 12) // LeoCAD 0.80
|
||||
return false;
|
||||
|
||||
const float PositionScale = (version < 12) ? 25.0f : 1.0f;
|
||||
|
||||
if (version > 8)
|
||||
{
|
||||
if (file.ReadU8() != 1)
|
||||
|
@ -198,9 +200,9 @@ bool lcPiece::FileLoad(lcFile& file)
|
|||
file.ReadU8(&type, 1);
|
||||
|
||||
if (type == 0)
|
||||
ChangeKey(mPositionKeys, lcVector3(param[0], param[1], param[2]), time, true);
|
||||
mPositionKeys.ChangeKey(lcVector3(param[0], param[1], param[2]) * PositionScale, time, true);
|
||||
else if (type == 1)
|
||||
ChangeKey(mRotationKeys, lcMatrix33FromAxisAngle(lcVector3(param[0], param[1], param[2]), param[3] * LC_DTOR), time, true);
|
||||
mRotationKeys.ChangeKey(lcMatrix33FromAxisAngle(lcVector3(param[0], param[1], param[2]), param[3] * LC_DTOR), time, true);
|
||||
}
|
||||
|
||||
file.ReadU32(&n, 1);
|
||||
|
@ -212,50 +214,71 @@ bool lcPiece::FileLoad(lcFile& file)
|
|||
}
|
||||
}
|
||||
|
||||
if (version < 9)
|
||||
{
|
||||
quint16 time;
|
||||
quint8 type;
|
||||
if (version < 9)
|
||||
{
|
||||
quint16 time;
|
||||
quint8 type;
|
||||
|
||||
if (version > 5)
|
||||
{
|
||||
quint32 keys;
|
||||
float param[4];
|
||||
if (version > 5)
|
||||
{
|
||||
quint32 keys;
|
||||
float param[4];
|
||||
|
||||
file.ReadU32(&keys, 1);
|
||||
while (keys--)
|
||||
{
|
||||
file.ReadFloats(param, 4);
|
||||
file.ReadU16(&time, 1);
|
||||
file.ReadU8(&type, 1);
|
||||
|
||||
if (type == 0)
|
||||
ChangeKey(mPositionKeys, lcVector3(param[0], param[1], param[2]), time, true);
|
||||
else if (type == 1)
|
||||
ChangeKey(mRotationKeys, lcMatrix33FromAxisAngle(lcVector3(param[0], param[1], param[2]), param[3] * LC_DTOR), time, true);
|
||||
}
|
||||
|
||||
file.ReadU32(&keys, 1);
|
||||
while (keys--)
|
||||
{
|
||||
file.ReadFloats(param, 4);
|
||||
file.ReadU16(&time, 1);
|
||||
file.ReadU8(&type, 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (version > 2)
|
||||
{
|
||||
file.ReadU8(&ch, 1);
|
||||
|
||||
while (ch--)
|
||||
{
|
||||
lcMatrix44 ModelWorld;
|
||||
|
||||
if (version > 3)
|
||||
file.ReadU32(&keys, 1);
|
||||
while (keys--)
|
||||
{
|
||||
file.ReadFloats(ModelWorld, 16);
|
||||
file.ReadFloats(param, 4);
|
||||
file.ReadU16(&time, 1);
|
||||
file.ReadU8(&type, 1);
|
||||
|
||||
if (type == 0)
|
||||
mPositionKeys.ChangeKey(lcVector3(param[0], param[1], param[2]) * PositionScale, time, true);
|
||||
else if (type == 1)
|
||||
mRotationKeys.ChangeKey(lcMatrix33FromAxisAngle(lcVector3(param[0], param[1], param[2]), param[3] * LC_DTOR), time, true);
|
||||
}
|
||||
|
||||
file.ReadU32(&keys, 1);
|
||||
while (keys--)
|
||||
{
|
||||
file.ReadFloats(param, 4);
|
||||
file.ReadU16(&time, 1);
|
||||
file.ReadU8(&type, 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (version > 2)
|
||||
{
|
||||
file.ReadU8(&ch, 1);
|
||||
|
||||
while (ch--)
|
||||
{
|
||||
lcMatrix44 ModelWorld;
|
||||
|
||||
if (version > 3)
|
||||
{
|
||||
file.ReadFloats(ModelWorld, 16);
|
||||
}
|
||||
else
|
||||
{
|
||||
lcVector3 Translation;
|
||||
float Rotation[3];
|
||||
file.ReadFloats(Translation, 3);
|
||||
file.ReadFloats(Rotation, 3);
|
||||
ModelWorld = lcMatrix44Translation(Translation);
|
||||
ModelWorld = lcMul(lcMatrix44RotationZ(Rotation[2] * LC_DTOR), lcMul(lcMatrix44RotationY(Rotation[1] * LC_DTOR), lcMul(lcMatrix44RotationX(Rotation[0] * LC_DTOR), ModelWorld)));
|
||||
}
|
||||
|
||||
quint8 b;
|
||||
file.ReadU8(&b, 1);
|
||||
time = b;
|
||||
|
||||
mPositionKeys.ChangeKey(ModelWorld.GetTranslation() * PositionScale, 1, true);
|
||||
mRotationKeys.ChangeKey(lcMatrix33(ModelWorld), time, true);
|
||||
|
||||
qint32 bl;
|
||||
file.ReadS32(&bl, 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -263,46 +286,25 @@ bool lcPiece::FileLoad(lcFile& file)
|
|||
float Rotation[3];
|
||||
file.ReadFloats(Translation, 3);
|
||||
file.ReadFloats(Rotation, 3);
|
||||
ModelWorld = lcMatrix44Translation(Translation);
|
||||
lcMatrix44 ModelWorld = lcMatrix44Translation(Translation);
|
||||
ModelWorld = lcMul(lcMatrix44RotationZ(Rotation[2] * LC_DTOR), lcMul(lcMatrix44RotationY(Rotation[1] * LC_DTOR), lcMul(lcMatrix44RotationX(Rotation[0] * LC_DTOR), ModelWorld)));
|
||||
|
||||
mPositionKeys.ChangeKey(lcVector3(ModelWorld.r[3][0], ModelWorld.r[3][1], ModelWorld.r[3][2]) * PositionScale, 1, true);
|
||||
mRotationKeys.ChangeKey(lcMatrix33(ModelWorld), 1, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
quint8 b;
|
||||
file.ReadU8(&b, 1);
|
||||
time = b;
|
||||
|
||||
ChangeKey(mPositionKeys, ModelWorld.GetTranslation(), 1, true);
|
||||
ChangeKey(mRotationKeys, lcMatrix33(ModelWorld), time, true);
|
||||
|
||||
qint32 bl;
|
||||
file.ReadS32(&bl, 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lcVector3 Translation;
|
||||
float Rotation[3];
|
||||
file.ReadFloats(Translation, 3);
|
||||
file.ReadFloats(Rotation, 3);
|
||||
lcMatrix44 ModelWorld = lcMatrix44Translation(Translation);
|
||||
ModelWorld = lcMul(lcMatrix44RotationZ(Rotation[2] * LC_DTOR), lcMul(lcMatrix44RotationY(Rotation[1] * LC_DTOR), lcMul(lcMatrix44RotationX(Rotation[0] * LC_DTOR), ModelWorld)));
|
||||
|
||||
ChangeKey(mPositionKeys, lcVector3(ModelWorld.r[3][0], ModelWorld.r[3][1], ModelWorld.r[3][2]), 1, true);
|
||||
ChangeKey(mRotationKeys, lcMatrix33(ModelWorld), 1, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Common to all versions.
|
||||
// Common to all versions.
|
||||
char name[LC_PIECE_NAME_LEN];
|
||||
if (version < 10)
|
||||
{
|
||||
memset(name, 0, LC_PIECE_NAME_LEN);
|
||||
file.ReadBuffer(name, 9);
|
||||
}
|
||||
else
|
||||
file.ReadBuffer(name, LC_PIECE_NAME_LEN);
|
||||
strcat(name, ".dat");
|
||||
if (version < 10)
|
||||
{
|
||||
memset(name, 0, LC_PIECE_NAME_LEN);
|
||||
file.ReadBuffer(name, 9);
|
||||
}
|
||||
else
|
||||
file.ReadBuffer(name, LC_PIECE_NAME_LEN);
|
||||
strcat(name, ".dat");
|
||||
|
||||
PieceInfo* pInfo = lcGetPiecesLibrary()->FindPiece(name, nullptr, true, false);
|
||||
SetPieceInfo(pInfo, QString(), true);
|
||||
|
@ -323,63 +325,57 @@ bool lcPiece::FileLoad(lcFile& file)
|
|||
file.ReadU32(&mColorCode, 1);
|
||||
mColorIndex = lcGetColorIndex(mColorCode);
|
||||
|
||||
quint8 Step;
|
||||
file.ReadU8(&Step, 1);
|
||||
mStepShow = Step;
|
||||
if (version > 1)
|
||||
{
|
||||
file.ReadU8(&Step, 1);
|
||||
mStepHide = Step == 255 ? LC_STEP_MAX : Step;
|
||||
}
|
||||
else
|
||||
mStepHide = LC_STEP_MAX;
|
||||
|
||||
if (version > 5)
|
||||
{
|
||||
file.ReadU16(); // m_nFrameShow
|
||||
file.ReadU16(); // m_nFrameHide
|
||||
|
||||
if (version > 7)
|
||||
{
|
||||
quint8 Hidden;
|
||||
file.ReadU8(&Hidden, 1);
|
||||
if (Hidden & 1)
|
||||
mState |= LC_PIECE_HIDDEN;
|
||||
file.ReadU8(&ch, 1);
|
||||
file.Seek(ch, SEEK_CUR);
|
||||
}
|
||||
else
|
||||
{
|
||||
qint32 hide;
|
||||
file.ReadS32(&hide, 1);
|
||||
if (hide != 0)
|
||||
mState |= LC_PIECE_HIDDEN;
|
||||
file.Seek(81, SEEK_CUR);
|
||||
}
|
||||
|
||||
// 7 (0.64)
|
||||
qint32 i = -1;
|
||||
if (version > 6)
|
||||
file.ReadS32(&i, 1);
|
||||
mGroup = (lcGroup*)(quintptr)i;
|
||||
}
|
||||
else
|
||||
{
|
||||
file.ReadU8(&ch, 1);
|
||||
if (ch == 0)
|
||||
mGroup = (lcGroup*)-1;
|
||||
else
|
||||
mGroup = (lcGroup*)(quintptr)ch;
|
||||
|
||||
file.ReadU8(&ch, 1);
|
||||
if (ch & 0x01)
|
||||
mState |= LC_PIECE_HIDDEN;
|
||||
}
|
||||
|
||||
if (version < 12)
|
||||
quint8 Step;
|
||||
file.ReadU8(&Step, 1);
|
||||
mStepShow = Step;
|
||||
if (version > 1)
|
||||
{
|
||||
for (int KeyIdx = 0; KeyIdx < mPositionKeys.GetSize(); KeyIdx++)
|
||||
mPositionKeys[KeyIdx].Value *= 25.0f;
|
||||
file.ReadU8(&Step, 1);
|
||||
mStepHide = Step == 255 ? LC_STEP_MAX : Step;
|
||||
}
|
||||
else
|
||||
mStepHide = LC_STEP_MAX;
|
||||
|
||||
if (version > 5)
|
||||
{
|
||||
file.ReadU16(); // m_nFrameShow
|
||||
file.ReadU16(); // m_nFrameHide
|
||||
|
||||
if (version > 7)
|
||||
{
|
||||
quint8 Hidden;
|
||||
file.ReadU8(&Hidden, 1);
|
||||
if (Hidden & 1)
|
||||
mState |= LC_PIECE_HIDDEN;
|
||||
file.ReadU8(&ch, 1);
|
||||
file.Seek(ch, SEEK_CUR);
|
||||
}
|
||||
else
|
||||
{
|
||||
qint32 hide;
|
||||
file.ReadS32(&hide, 1);
|
||||
if (hide != 0)
|
||||
mState |= LC_PIECE_HIDDEN;
|
||||
file.Seek(81, SEEK_CUR);
|
||||
}
|
||||
|
||||
// 7 (0.64)
|
||||
qint32 i = -1;
|
||||
if (version > 6)
|
||||
file.ReadS32(&i, 1);
|
||||
mGroup = (lcGroup*)(quintptr)i;
|
||||
}
|
||||
else
|
||||
{
|
||||
file.ReadU8(&ch, 1);
|
||||
if (ch == 0)
|
||||
mGroup = (lcGroup*)-1;
|
||||
else
|
||||
mGroup = (lcGroup*)(quintptr)ch;
|
||||
|
||||
file.ReadU8(&ch, 1);
|
||||
if (ch & 0x01)
|
||||
mState |= LC_PIECE_HIDDEN;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -390,9 +386,9 @@ void lcPiece::Initialize(const lcMatrix44& WorldMatrix, lcStep Step)
|
|||
mStepShow = Step;
|
||||
|
||||
if (mPositionKeys.IsEmpty())
|
||||
ChangeKey(mPositionKeys, WorldMatrix.GetTranslation(), 1, true);
|
||||
mPositionKeys.ChangeKey(WorldMatrix.GetTranslation(), 1, true);
|
||||
if (mRotationKeys.IsEmpty())
|
||||
ChangeKey(mRotationKeys, lcMatrix33(WorldMatrix), 1, true);
|
||||
mRotationKeys.ChangeKey(lcMatrix33(WorldMatrix), 1, true);
|
||||
|
||||
UpdatePosition(Step);
|
||||
}
|
||||
|
@ -426,8 +422,8 @@ void lcPiece::InsertTime(lcStep Start, lcStep Time)
|
|||
}
|
||||
}
|
||||
|
||||
lcObject::InsertTime(mPositionKeys, Start, Time);
|
||||
lcObject::InsertTime(mRotationKeys, Start, Time);
|
||||
mPositionKeys.InsertTime(Start, Time);
|
||||
mRotationKeys.InsertTime(Start, Time);
|
||||
}
|
||||
|
||||
void lcPiece::RemoveTime(lcStep Start, lcStep Time)
|
||||
|
@ -459,8 +455,8 @@ void lcPiece::RemoveTime(lcStep Start, lcStep Time)
|
|||
}
|
||||
}
|
||||
|
||||
lcObject::RemoveTime(mPositionKeys, Start, Time);
|
||||
lcObject::RemoveTime(mRotationKeys, Start, Time);
|
||||
mPositionKeys.RemoveTime(Start, Time);
|
||||
mRotationKeys.RemoveTime(Start, Time);
|
||||
}
|
||||
|
||||
void lcPiece::RayTest(lcObjectRayTest& ObjectRayTest) const
|
||||
|
@ -617,7 +613,7 @@ void lcPiece::DrawInterface(lcContext* Context, const lcScene& Scene) const
|
|||
};
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glEnable(GL_CULL_FACE);
|
||||
Context->EnableCullFace(true);
|
||||
|
||||
for (int ControlPointIdx = 0; ControlPointIdx < mControlPoints.GetSize(); ControlPointIdx++)
|
||||
{
|
||||
|
@ -635,7 +631,7 @@ void lcPiece::DrawInterface(lcContext* Context, const lcScene& Scene) const
|
|||
Context->DrawIndexedPrimitives(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, 0);
|
||||
}
|
||||
|
||||
glDisable(GL_CULL_FACE);
|
||||
Context->EnableCullFace(false);
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
}
|
||||
|
@ -643,13 +639,13 @@ void lcPiece::DrawInterface(lcContext* Context, const lcScene& Scene) const
|
|||
void lcPiece::RemoveKeyFrames()
|
||||
{
|
||||
mPositionKeys.RemoveAll();
|
||||
ChangeKey(mPositionKeys, mModelWorld.GetTranslation(), 1, true);
|
||||
mPositionKeys.ChangeKey(mModelWorld.GetTranslation(), 1, true);
|
||||
|
||||
mRotationKeys.RemoveAll();
|
||||
ChangeKey(mRotationKeys, lcMatrix33(mModelWorld), 1, true);
|
||||
mRotationKeys.ChangeKey(lcMatrix33(mModelWorld), 1, true);
|
||||
}
|
||||
|
||||
void lcPiece::AddMainModelRenderMeshes(lcScene& Scene, bool Highlight, bool Fade) const
|
||||
void lcPiece::AddMainModelRenderMeshes(lcScene* Scene, bool Highlight, bool Fade) const
|
||||
{
|
||||
lcRenderMeshState RenderMeshState = lcRenderMeshState::Default;
|
||||
bool ParentActive = false;
|
||||
|
@ -660,9 +656,9 @@ void lcPiece::AddMainModelRenderMeshes(lcScene& Scene, bool Highlight, bool Fade
|
|||
if (Fade)
|
||||
RenderMeshState = lcRenderMeshState::Faded;
|
||||
|
||||
if (Scene.GetDrawInterface())
|
||||
if (Scene->GetDrawInterface())
|
||||
{
|
||||
lcPiece* ActiveSubmodelInstance = Scene.GetActiveSubmodelInstance();
|
||||
lcPiece* ActiveSubmodelInstance = Scene->GetActiveSubmodelInstance();
|
||||
|
||||
if (!ActiveSubmodelInstance)
|
||||
RenderMeshState = IsFocused() ? lcRenderMeshState::Focused : (IsSelected() ? lcRenderMeshState::Selected : RenderMeshState);
|
||||
|
@ -675,20 +671,20 @@ void lcPiece::AddMainModelRenderMeshes(lcScene& Scene, bool Highlight, bool Fade
|
|||
if (!mMesh)
|
||||
mPieceInfo->AddRenderMeshes(Scene, mModelWorld, mColorIndex, RenderMeshState, ParentActive);
|
||||
else
|
||||
Scene.AddMesh(mMesh, mModelWorld, mColorIndex, RenderMeshState);
|
||||
Scene->AddMesh(mMesh, mModelWorld, mColorIndex, RenderMeshState);
|
||||
|
||||
if (RenderMeshState == lcRenderMeshState::Focused || RenderMeshState == lcRenderMeshState::Selected)
|
||||
Scene.AddInterfaceObject(this);
|
||||
Scene->AddInterfaceObject(this);
|
||||
}
|
||||
|
||||
void lcPiece::AddSubModelRenderMeshes(lcScene& Scene, const lcMatrix44& WorldMatrix, int DefaultColorIndex, lcRenderMeshState RenderMeshState, bool ParentActive) const
|
||||
void lcPiece::AddSubModelRenderMeshes(lcScene* Scene, const lcMatrix44& WorldMatrix, int DefaultColorIndex, lcRenderMeshState RenderMeshState, bool ParentActive) const
|
||||
{
|
||||
int ColorIndex = mColorIndex;
|
||||
|
||||
if (ColorIndex == gDefaultColor)
|
||||
ColorIndex = DefaultColorIndex;
|
||||
|
||||
lcPiece* ActiveSubmodelInstance = Scene.GetActiveSubmodelInstance();
|
||||
lcPiece* ActiveSubmodelInstance = Scene->GetActiveSubmodelInstance();
|
||||
|
||||
if (ActiveSubmodelInstance == this)
|
||||
RenderMeshState = lcRenderMeshState::Default;
|
||||
|
@ -698,17 +694,32 @@ void lcPiece::AddSubModelRenderMeshes(lcScene& Scene, const lcMatrix44& WorldMat
|
|||
if (!mMesh)
|
||||
mPieceInfo->AddRenderMeshes(Scene, lcMul(mModelWorld, WorldMatrix), ColorIndex, RenderMeshState, ActiveSubmodelInstance == this);
|
||||
else
|
||||
Scene.AddMesh(mMesh, lcMul(mModelWorld, WorldMatrix), ColorIndex, RenderMeshState);
|
||||
Scene->AddMesh(mMesh, lcMul(mModelWorld, WorldMatrix), ColorIndex, RenderMeshState);
|
||||
|
||||
if (ParentActive && (RenderMeshState == lcRenderMeshState::Focused || RenderMeshState == lcRenderMeshState::Selected))
|
||||
Scene.AddInterfaceObject(this);
|
||||
Scene->AddInterfaceObject(this);
|
||||
}
|
||||
|
||||
void lcPiece::SubmodelCompareBoundingBox(const lcMatrix44& WorldMatrix, lcVector3& Min, lcVector3& Max) const
|
||||
void lcPiece::SubModelCompareBoundingBox(const lcMatrix44& WorldMatrix, lcVector3& Min, lcVector3& Max) const
|
||||
{
|
||||
mPieceInfo->CompareBoundingBox(lcMul(mModelWorld, WorldMatrix), Min, Max);
|
||||
}
|
||||
|
||||
void lcPiece::SubModelAddBoundingBoxPoints(const lcMatrix44& WorldMatrix, std::vector<lcVector3>& Points) const
|
||||
{
|
||||
if (!mMesh)
|
||||
mPieceInfo->AddSubModelBoundingBoxPoints(lcMul(mModelWorld, WorldMatrix), Points);
|
||||
else
|
||||
{
|
||||
lcVector3 BoxPoints[8];
|
||||
|
||||
lcGetBoxCorners(mMesh->mBoundingBox, BoxPoints);
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
Points.emplace_back(lcMul31(BoxPoints[i], mModelWorld));
|
||||
}
|
||||
}
|
||||
|
||||
void lcPiece::MoveSelected(lcStep Step, bool AddKey, const lcVector3& Distance)
|
||||
{
|
||||
quint32 Section = GetFocusSection();
|
||||
|
@ -896,9 +907,9 @@ void lcPiece::VerifyControlPoints(lcArray<lcPieceControlPoint>& ControlPoints) c
|
|||
}
|
||||
}
|
||||
|
||||
const char* lcPiece::GetName() const
|
||||
QString lcPiece::GetName() const
|
||||
{
|
||||
return mPieceInfo->m_strDescription;
|
||||
return QString::fromLatin1(mPieceInfo->m_strDescription);
|
||||
}
|
||||
|
||||
bool lcPiece::IsVisible(lcStep Step) const
|
||||
|
@ -965,8 +976,8 @@ lcGroup* lcPiece::GetTopGroup()
|
|||
|
||||
void lcPiece::UpdatePosition(lcStep Step)
|
||||
{
|
||||
lcVector3 Position = CalculateKey(mPositionKeys, Step);
|
||||
lcMatrix33 Rotation = CalculateKey(mRotationKeys, Step);
|
||||
lcVector3 Position = mPositionKeys.CalculateKey(Step);
|
||||
lcMatrix33 Rotation = mRotationKeys.CalculateKey(Step);
|
||||
|
||||
mModelWorld = lcMatrix44(Rotation, Position);
|
||||
}
|
||||
|
|
|
@ -409,9 +409,10 @@ public:
|
|||
void DrawInterface(lcContext* Context, const lcScene& Scene) const override;
|
||||
void RemoveKeyFrames() override;
|
||||
|
||||
void AddMainModelRenderMeshes(lcScene& Scene, bool Highlight, bool Fade) const;
|
||||
void AddSubModelRenderMeshes(lcScene& Scene, const lcMatrix44& WorldMatrix, int DefaultColorIndex, lcRenderMeshState RenderMeshState, bool ParentActive) const;
|
||||
void SubmodelCompareBoundingBox(const lcMatrix44& WorldMatrix, lcVector3& Min, lcVector3& Max) const;
|
||||
void AddMainModelRenderMeshes(lcScene* Scene, bool Highlight, bool Fade) const;
|
||||
void AddSubModelRenderMeshes(lcScene* Scene, const lcMatrix44& WorldMatrix, int DefaultColorIndex, lcRenderMeshState RenderMeshState, bool ParentActive) const;
|
||||
void SubModelCompareBoundingBox(const lcMatrix44& WorldMatrix, lcVector3& Min, lcVector3& Max) const;
|
||||
void SubModelAddBoundingBoxPoints(const lcMatrix44& WorldMatrix, std::vector<lcVector3>& Points) const;
|
||||
|
||||
void InsertTime(lcStep Start, lcStep Time);
|
||||
void RemoveTime(lcStep Start, lcStep Time);
|
||||
|
@ -453,7 +454,7 @@ public:
|
|||
|
||||
void UpdateID();
|
||||
|
||||
const char* GetName() const override;
|
||||
QString GetName() const override;
|
||||
bool IsVisible(lcStep Step) const;
|
||||
bool IsVisibleInSubModel() const;
|
||||
void GetModelParts(const lcMatrix44& WorldMatrix, int DefaultColorIndex, std::vector<lcModelPartsEntry>& ModelParts) const;
|
||||
|
@ -524,12 +525,22 @@ public:
|
|||
mStepHide = mStepShow + 1;
|
||||
}
|
||||
|
||||
quint32 GetColorCode() const
|
||||
{
|
||||
return mColorCode;
|
||||
}
|
||||
|
||||
void SetColorCode(quint32 ColorCode)
|
||||
{
|
||||
mColorCode = ColorCode;
|
||||
mColorIndex = lcGetColorIndex(ColorCode);
|
||||
}
|
||||
|
||||
int GetColorIndex() const
|
||||
{
|
||||
return mColorIndex;
|
||||
}
|
||||
|
||||
void SetColorIndex(int ColorIndex)
|
||||
{
|
||||
mColorIndex = ColorIndex;
|
||||
|
@ -538,12 +549,12 @@ public:
|
|||
|
||||
void SetPosition(const lcVector3& Position, lcStep Step, bool AddKey)
|
||||
{
|
||||
ChangeKey(mPositionKeys, Position, Step, AddKey);
|
||||
mPositionKeys.ChangeKey(Position, Step, AddKey);
|
||||
}
|
||||
|
||||
void SetRotation(const lcMatrix33& Rotation, lcStep Step, bool AddKey)
|
||||
{
|
||||
ChangeKey(mRotationKeys, Rotation, Step, AddKey);
|
||||
mRotationKeys.ChangeKey(Rotation, Step, AddKey);
|
||||
}
|
||||
|
||||
lcVector3 GetRotationCenter() const
|
||||
|
@ -605,9 +616,6 @@ public:
|
|||
public:
|
||||
PieceInfo* mPieceInfo;
|
||||
|
||||
int mColorIndex;
|
||||
quint32 mColorCode;
|
||||
|
||||
lcMatrix44 mModelWorld;
|
||||
lcMatrix44 mPivotMatrix;
|
||||
|
||||
|
@ -624,14 +632,17 @@ protected:
|
|||
return IsSelected();
|
||||
}
|
||||
|
||||
lcArray<lcObjectKey<lcVector3>> mPositionKeys;
|
||||
lcArray<lcObjectKey<lcMatrix33>> mRotationKeys;
|
||||
lcObjectKeyArray<lcVector3> mPositionKeys;
|
||||
lcObjectKeyArray<lcMatrix33> mRotationKeys;
|
||||
|
||||
int mFileLine;
|
||||
QString mID;
|
||||
|
||||
lcGroup* mGroup;
|
||||
|
||||
int mColorIndex;
|
||||
quint32 mColorCode;
|
||||
|
||||
lcStep mStepShow;
|
||||
lcStep mStepHide;
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
PieceInfo::PieceInfo()
|
||||
{
|
||||
mZipFileType = LC_NUM_ZIPFILES;
|
||||
mZipFileType = lcZipFileType::Count;
|
||||
mZipFileIndex = -1;
|
||||
mState = LC_PIECEINFO_UNLOADED;
|
||||
mRefCount = 0;
|
||||
|
@ -44,9 +44,9 @@ void PieceInfo::SetMesh(lcMesh* Mesh)
|
|||
|
||||
void PieceInfo::SetPlaceholder()
|
||||
{
|
||||
mBoundingBox.Min = lcVector3(-10.0f, -10.0f, -24.0f);
|
||||
mBoundingBox.Max = lcVector3(10.0f, 10.0f, 4.0f);
|
||||
ReleaseMesh();
|
||||
lcMesh* Mesh = new lcMesh;
|
||||
Mesh->CreateBox();
|
||||
SetMesh(Mesh);
|
||||
|
||||
mType = lcPieceInfoType::Placeholder;
|
||||
mModel = nullptr;
|
||||
|
@ -59,11 +59,13 @@ void PieceInfo::SetModel(lcModel* Model, bool UpdateMesh, Project* CurrentProjec
|
|||
{
|
||||
mType = lcPieceInfoType::Model;
|
||||
mModel = Model;
|
||||
delete mMesh;
|
||||
mMesh = nullptr;
|
||||
}
|
||||
|
||||
strncpy(mFileName, Model->GetProperties().mFileName.toLatin1().data(), sizeof(mFileName));
|
||||
strncpy(mFileName, Model->GetProperties().mFileName.toLatin1().data(), sizeof(mFileName) - 1);
|
||||
mFileName[sizeof(mFileName)-1] = 0;
|
||||
strncpy(m_strDescription, Model->GetProperties().mFileName.toLatin1().data(), sizeof(m_strDescription));
|
||||
strncpy(m_strDescription, Model->GetProperties().mFileName.toLatin1().data(), sizeof(m_strDescription) - 1);
|
||||
m_strDescription[sizeof(m_strDescription)-1] = 0;
|
||||
|
||||
const QStringList& MeshLines = Model->GetFileLines();
|
||||
|
@ -100,9 +102,9 @@ void PieceInfo::CreateProject(Project* Project, const char* PieceName)
|
|||
mState = LC_PIECEINFO_LOADED;
|
||||
}
|
||||
|
||||
strncpy(mFileName, PieceName, sizeof(mFileName));
|
||||
strncpy(mFileName, PieceName, sizeof(mFileName) - 1);
|
||||
mFileName[sizeof(mFileName) - 1] = 0;
|
||||
strncpy(m_strDescription, Project->GetFileName().toLatin1().data(), sizeof(m_strDescription));
|
||||
strncpy(m_strDescription, Project->GetFileName().toLatin1().data(), sizeof(m_strDescription) - 1);
|
||||
m_strDescription[sizeof(m_strDescription) - 1] = 0;
|
||||
}
|
||||
|
||||
|
@ -147,8 +149,6 @@ void PieceInfo::Load()
|
|||
{
|
||||
if (lcGetPiecesLibrary()->LoadPieceData(this))
|
||||
mType = lcPieceInfoType::Part;
|
||||
else
|
||||
mBoundingBox = gPlaceholderMesh->mBoundingBox;
|
||||
}
|
||||
else
|
||||
lcGetPiecesLibrary()->LoadPieceData(this);
|
||||
|
@ -266,9 +266,6 @@ bool PieceInfo::BoxTest(const lcMatrix44& WorldMatrix, const lcVector4 WorldPlan
|
|||
if (OutcodesOR == 0)
|
||||
return true;
|
||||
|
||||
if (IsPlaceholder())
|
||||
return gPlaceholderMesh->IntersectsPlanes(LocalPlanes);
|
||||
|
||||
if (mMesh && mMesh->IntersectsPlanes(LocalPlanes))
|
||||
return true;
|
||||
|
||||
|
@ -305,10 +302,10 @@ void PieceInfo::AddRenderMesh(lcScene& Scene)
|
|||
Scene.AddMesh(mMesh, lcMatrix44Identity(), gDefaultColor, lcRenderMeshState::Default);
|
||||
}
|
||||
|
||||
void PieceInfo::AddRenderMeshes(lcScene& Scene, const lcMatrix44& WorldMatrix, int ColorIndex, lcRenderMeshState RenderMeshState, bool ParentActive) const
|
||||
void PieceInfo::AddRenderMeshes(lcScene* Scene, const lcMatrix44& WorldMatrix, int ColorIndex, lcRenderMeshState RenderMeshState, bool ParentActive) const
|
||||
{
|
||||
if (mMesh || IsPlaceholder())
|
||||
Scene.AddMesh(IsPlaceholder() ? gPlaceholderMesh : mMesh, WorldMatrix, ColorIndex, RenderMeshState);
|
||||
Scene->AddMesh(mMesh, WorldMatrix, ColorIndex, RenderMeshState);
|
||||
|
||||
if (IsModel())
|
||||
mModel->AddSubModelRenderMeshes(Scene, WorldMatrix, ColorIndex, RenderMeshState, ParentActive);
|
||||
|
@ -327,7 +324,7 @@ void PieceInfo::GetPartsList(int DefaultColorIndex, bool ScanSubModels, bool Add
|
|||
if (ScanSubModels)
|
||||
mModel->GetPartsList(DefaultColorIndex, ScanSubModels, AddSubModels, PartsList);
|
||||
|
||||
if (AddSubModels && DefaultColorIndex < gNumUserColors)
|
||||
if (AddSubModels)
|
||||
PartsList[this][DefaultColorIndex]++;
|
||||
}
|
||||
else if (IsProject())
|
||||
|
@ -336,7 +333,7 @@ void PieceInfo::GetPartsList(int DefaultColorIndex, bool ScanSubModels, bool Add
|
|||
if (Model)
|
||||
Model->GetPartsList(DefaultColorIndex, ScanSubModels, AddSubModels, PartsList);
|
||||
}
|
||||
else if (DefaultColorIndex < gNumUserColors)
|
||||
else
|
||||
PartsList[this][DefaultColorIndex]++;
|
||||
}
|
||||
|
||||
|
@ -383,6 +380,26 @@ void PieceInfo::CompareBoundingBox(const lcMatrix44& WorldMatrix, lcVector3& Min
|
|||
}
|
||||
}
|
||||
|
||||
void PieceInfo::AddSubModelBoundingBoxPoints(const lcMatrix44& WorldMatrix, std::vector<lcVector3>& Points) const
|
||||
{
|
||||
if (!IsModel())
|
||||
{
|
||||
lcVector3 BoxPoints[8];
|
||||
|
||||
if (!mMesh)
|
||||
lcGetBoxCorners(GetBoundingBox(), BoxPoints);
|
||||
else
|
||||
lcGetBoxCorners(mMesh->mBoundingBox, BoxPoints);
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
Points.emplace_back(lcMul31(BoxPoints[i], WorldMatrix));
|
||||
}
|
||||
else
|
||||
{
|
||||
mModel->SubModelAddBoundingBoxPoints(WorldMatrix, Points);
|
||||
}
|
||||
}
|
||||
|
||||
void PieceInfo::UpdateBoundingBox(std::vector<lcModel*>& UpdatedModels)
|
||||
{
|
||||
if (IsModel())
|
||||
|
|
|
@ -30,6 +30,7 @@ struct lcModelPartsEntry
|
|||
};
|
||||
|
||||
class lcSynthInfo;
|
||||
enum class lcZipFileType;
|
||||
|
||||
class PieceInfo
|
||||
{
|
||||
|
@ -117,7 +118,7 @@ public:
|
|||
return mType != lcPieceInfoType::Part;
|
||||
}
|
||||
|
||||
void SetZipFile(int ZipFileType, int ZipFileIndex)
|
||||
void SetZipFile(lcZipFileType ZipFileType, int ZipFileIndex)
|
||||
{
|
||||
mZipFileType = ZipFileType;
|
||||
mZipFileIndex = ZipFileIndex;
|
||||
|
@ -130,6 +131,11 @@ public:
|
|||
|
||||
const char* Name = mFileName;
|
||||
|
||||
// Heuristic: Names matching '^[Uu]?[0-9]*[A-Za-z][^.][^.]' are patterned.
|
||||
|
||||
if (*Name == 'U' || *Name == 'u')
|
||||
Name++;
|
||||
|
||||
while (*Name)
|
||||
{
|
||||
if (*Name < '0' || *Name > '9')
|
||||
|
@ -138,7 +144,10 @@ public:
|
|||
Name++;
|
||||
}
|
||||
|
||||
if (*Name == 'P' || *Name == 'p')
|
||||
if (!*Name || !((*Name >= 'A' && *Name <= 'Z') || (*Name >= 'a' && *Name <= 'z')))
|
||||
return false;
|
||||
|
||||
if (Name[1] && Name[1] != '.' && Name[2] && Name[2] != '.')
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
@ -151,7 +160,7 @@ public:
|
|||
|
||||
void ZoomExtents(float FoV, float AspectRatio, lcMatrix44& ProjectionMatrix, lcMatrix44& ViewMatrix) const;
|
||||
void AddRenderMesh(lcScene& Scene);
|
||||
void AddRenderMeshes(lcScene& Scene, const lcMatrix44& WorldMatrix, int ColorIndex, lcRenderMeshState RenderMeshState, bool ParentActive) const;
|
||||
void AddRenderMeshes(lcScene* Scene, const lcMatrix44& WorldMatrix, int ColorIndex, lcRenderMeshState RenderMeshState, bool ParentActive) const;
|
||||
|
||||
void CreatePlaceholder(const char* Name);
|
||||
|
||||
|
@ -165,6 +174,7 @@ public:
|
|||
void GetPartsList(int DefaultColorIndex, bool ScanSubModels, bool AddSubModels, lcPartsList& PartsList) const;
|
||||
void GetModelParts(const lcMatrix44& WorldMatrix, int DefaultColorIndex, std::vector<lcModelPartsEntry>& ModelParts) const;
|
||||
void CompareBoundingBox(const lcMatrix44& WorldMatrix, lcVector3& Min, lcVector3& Max) const;
|
||||
void AddSubModelBoundingBoxPoints(const lcMatrix44& WorldMatrix, std::vector<lcVector3>& Points) const;
|
||||
void UpdateBoundingBox(std::vector<lcModel*>& UpdatedModels);
|
||||
|
||||
void Load();
|
||||
|
@ -173,7 +183,7 @@ public:
|
|||
public:
|
||||
char mFileName[LC_PIECE_NAME_LEN];
|
||||
char m_strDescription[128];
|
||||
int mZipFileType;
|
||||
lcZipFileType mZipFileType;
|
||||
int mZipFileIndex;
|
||||
lcPieceInfoState mState;
|
||||
int mFolderType;
|
||||
|
|
|
@ -5,9 +5,10 @@
|
|||
#include "pieceinf.h"
|
||||
#include "camera.h"
|
||||
#include "project.h"
|
||||
#include "lc_instructions.h"
|
||||
#include "image.h"
|
||||
#include "lc_mainwindow.h"
|
||||
#include "view.h"
|
||||
#include "lc_view.h"
|
||||
#include "lc_library.h"
|
||||
#include "lc_application.h"
|
||||
#include "lc_profile.h"
|
||||
|
@ -60,15 +61,17 @@ void lcHTMLExportOptions::SaveDefaults()
|
|||
lcSetProfileInt(LC_PROFILE_HTML_IMAGE_HEIGHT, StepImagesHeight);
|
||||
}
|
||||
|
||||
Project::Project()
|
||||
Project::Project(bool IsPreview)
|
||||
: mIsPreview(IsPreview)
|
||||
{
|
||||
mModified = false;
|
||||
mActiveModel = new lcModel(tr("New Model.ldr"));
|
||||
mActiveModel = new lcModel(tr(mIsPreview ? "Preview.ldr" : "New Model.ldr"), this, mIsPreview);
|
||||
mActiveModel->CreatePieceInfo(this);
|
||||
mActiveModel->SetSaved();
|
||||
mModels.Add(mActiveModel);
|
||||
|
||||
QObject::connect(&mFileWatcher, SIGNAL(fileChanged(const QString&)), gMainWindow, SLOT(ProjectFileChanged(const QString&)));
|
||||
if (!mIsPreview && gMainWindow)
|
||||
QObject::connect(&mFileWatcher, SIGNAL(fileChanged(const QString&)), gMainWindow, SLOT(ProjectFileChanged(const QString&)));
|
||||
}
|
||||
|
||||
Project::~Project()
|
||||
|
@ -121,12 +124,8 @@ QString Project::GetImageFileName(bool AllowCurrentFolder) const
|
|||
FileName = QLatin1String("image");
|
||||
else
|
||||
{
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
|
||||
QStringList cachePathList = QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation);
|
||||
FileName = cachePathList.first();
|
||||
#else
|
||||
FileName = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation);
|
||||
#endif
|
||||
QStringList CachePathList = QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation);
|
||||
FileName = CachePathList.first();
|
||||
FileName = QDir(FileName).absoluteFilePath(QLatin1String("image"));
|
||||
}
|
||||
}
|
||||
|
@ -149,8 +148,12 @@ void Project::SetActiveModel(int ModelIndex)
|
|||
mModels[ModelIdx]->UpdatePieceInfo(UpdatedModels);
|
||||
|
||||
mActiveModel = mModels[ModelIndex];
|
||||
gMainWindow->SetCurrentModelTab(mActiveModel);
|
||||
mActiveModel->UpdateInterface();
|
||||
|
||||
if (!mIsPreview && gMainWindow)
|
||||
{
|
||||
gMainWindow->SetCurrentModelTab(mActiveModel);
|
||||
mActiveModel->UpdateInterface();
|
||||
}
|
||||
}
|
||||
|
||||
void Project::SetActiveModel(const QString& FileName)
|
||||
|
@ -245,7 +248,7 @@ lcModel* Project::CreateNewModel(bool ShowModel)
|
|||
return nullptr;
|
||||
|
||||
mModified = true;
|
||||
lcModel* Model = new lcModel(Name);
|
||||
lcModel* Model = new lcModel(Name, this, false);
|
||||
Model->CreatePieceInfo(this);
|
||||
Model->SetSaved();
|
||||
mModels.Add(Model);
|
||||
|
@ -263,39 +266,53 @@ lcModel* Project::CreateNewModel(bool ShowModel)
|
|||
|
||||
void Project::ShowModelListDialog()
|
||||
{
|
||||
QList<QPair<QString, lcModel*>> Models;
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(4, 7, 0))
|
||||
Models.reserve(mModels.GetSize());
|
||||
#endif
|
||||
lcQModelListDialog Dialog(gMainWindow, mModels);
|
||||
|
||||
for (int ModelIdx = 0; ModelIdx < mModels.GetSize(); ModelIdx++)
|
||||
{
|
||||
lcModel* Model = mModels[ModelIdx];
|
||||
Models.append(QPair<QString, lcModel*>(Model->GetProperties().mFileName, Model));
|
||||
}
|
||||
|
||||
lcQModelListDialog Dialog(gMainWindow, Models);
|
||||
|
||||
if (Dialog.exec() != QDialog::Accepted || Models.isEmpty())
|
||||
if (Dialog.exec() != QDialog::Accepted)
|
||||
return;
|
||||
|
||||
lcArray<lcModel*> NewModels;
|
||||
std::vector<lcModelListDialogEntry> Results = Dialog.GetResults();
|
||||
|
||||
for (QList<QPair<QString, lcModel*>>::iterator it = Models.begin(); it != Models.end(); it++)
|
||||
for (const lcModelListDialogEntry& Entry : Results)
|
||||
{
|
||||
lcModel* Model = it->second;
|
||||
lcModel* Model = Entry.ExistingModel;
|
||||
|
||||
if (!Model)
|
||||
{
|
||||
Model = new lcModel(it->first);
|
||||
const lcModel* Source = Entry.DuplicateSource;
|
||||
|
||||
if (!Source)
|
||||
{
|
||||
Model = new lcModel(Entry.Name, this, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
Model = new lcModel(Source->GetProperties().mFileName, this, false);
|
||||
|
||||
QByteArray File;
|
||||
|
||||
QTextStream SaveStream(&File);
|
||||
Source->SaveLDraw(SaveStream, false);
|
||||
SaveStream.flush();
|
||||
|
||||
QBuffer Buffer(&File);
|
||||
Buffer.open(QIODevice::ReadOnly);
|
||||
|
||||
Model->LoadLDraw(Buffer, this);
|
||||
Model->SetFileName(Entry.Name);
|
||||
Model->CreatePieceInfo(this);
|
||||
}
|
||||
|
||||
Model->CreatePieceInfo(this);
|
||||
Model->SetSaved();
|
||||
|
||||
mModified = true;
|
||||
}
|
||||
else if (Model->GetProperties().mFileName != it->first)
|
||||
else if (Model->GetProperties().mFileName != Entry.Name)
|
||||
{
|
||||
Model->SetFileName(it->first);
|
||||
lcGetPiecesLibrary()->RenamePiece(Model->GetPieceInfo(), it->first.toLatin1().constData());
|
||||
Model->SetFileName(Entry.Name);
|
||||
lcGetPiecesLibrary()->RenamePiece(Model->GetPieceInfo(), Entry.Name.toLatin1().constData());
|
||||
|
||||
for (lcModel* CheckModel : mModels)
|
||||
CheckModel->RenamePiece(Model->GetPieceInfo());
|
||||
|
@ -332,10 +349,10 @@ void Project::SetFileName(const QString& FileName)
|
|||
if (mFileName == FileName)
|
||||
return;
|
||||
|
||||
if (!mFileName.isEmpty())
|
||||
if (!mIsPreview && !mFileName.isEmpty())
|
||||
mFileWatcher.removePath(mFileName);
|
||||
|
||||
if (!FileName.isEmpty())
|
||||
if (!mIsPreview && !FileName.isEmpty())
|
||||
mFileWatcher.addPath(FileName);
|
||||
|
||||
mFileName = FileName;
|
||||
|
@ -343,11 +360,15 @@ void Project::SetFileName(const QString& FileName)
|
|||
|
||||
bool Project::Load(const QString& FileName)
|
||||
{
|
||||
QWidget *parent = nullptr;
|
||||
if (!mIsPreview)
|
||||
parent = gMainWindow;
|
||||
|
||||
QFile File(FileName);
|
||||
|
||||
if (!File.open(QIODevice::ReadOnly))
|
||||
{
|
||||
QMessageBox::warning(gMainWindow, tr("Error"), tr("Error reading file '%1':\n%2").arg(FileName, File.errorString()));
|
||||
QMessageBox::warning(parent, tr("Error"), tr("Error reading file '%1':\n%2").arg(FileName, File.errorString()));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -374,14 +395,24 @@ bool Project::Load(const QString& FileName)
|
|||
|
||||
while (!Buffer.atEnd())
|
||||
{
|
||||
lcModel* Model = new lcModel(QString());
|
||||
lcModel* Model = new lcModel(QString(), this, mIsPreview);
|
||||
int Pos = Model->SplitMPD(Buffer);
|
||||
|
||||
if (Models.empty() || !Model->GetFileName().isEmpty())
|
||||
{
|
||||
mModels.Add(Model);
|
||||
Models.emplace_back(std::make_pair(Pos, Model));
|
||||
Model->CreatePieceInfo(this);
|
||||
auto ModelCompare = [Model](const std::pair<int, lcModel*>& ModelIt)
|
||||
{
|
||||
return ModelIt.second->GetFileName().compare(Model->GetFileName(), Qt::CaseInsensitive) == 0;
|
||||
};
|
||||
|
||||
if (std::find_if(Models.begin(), Models.end(), ModelCompare) == Models.end())
|
||||
{
|
||||
mModels.Add(Model);
|
||||
Models.emplace_back(std::make_pair(Pos, Model));
|
||||
Model->CreatePieceInfo(this);
|
||||
}
|
||||
else
|
||||
delete Model;
|
||||
}
|
||||
else
|
||||
delete Model;
|
||||
|
@ -401,7 +432,7 @@ bool Project::Load(const QString& FileName)
|
|||
MemFile.WriteBuffer(FileData.constData(), FileData.size());
|
||||
MemFile.Seek(0, SEEK_SET);
|
||||
|
||||
lcModel* Model = new lcModel(QString());
|
||||
lcModel* Model = new lcModel(QString(), this, mIsPreview);
|
||||
|
||||
if (Model->LoadBinary(&MemFile))
|
||||
{
|
||||
|
@ -415,7 +446,7 @@ bool Project::Load(const QString& FileName)
|
|||
|
||||
if (mModels.IsEmpty())
|
||||
{
|
||||
QMessageBox::warning(gMainWindow, tr("Error"), tr("Error loading file '%1':\nFile format is not recognized.").arg(FileName));
|
||||
QMessageBox::warning(parent, tr("Error"), tr("Error loading file '%1':\nFile format is not recognized.").arg(FileName));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -534,7 +565,7 @@ bool Project::ImportLDD(const QString& FileName)
|
|||
|
||||
mModels.DeleteAll();
|
||||
QString ModelName = QFileInfo(FileName).completeBaseName();
|
||||
lcModel* Model = new lcModel(ModelName);
|
||||
lcModel* Model = new lcModel(ModelName, this, false);
|
||||
|
||||
if (Model->LoadLDD(QString::fromUtf8((const char*)XMLFile.mBuffer)))
|
||||
{
|
||||
|
@ -567,7 +598,7 @@ bool Project::ImportInventory(const QByteArray& Inventory, const QString& Name,
|
|||
return false;
|
||||
|
||||
mModels.DeleteAll();
|
||||
lcModel* Model = new lcModel(Name);
|
||||
lcModel* Model = new lcModel(Name, this, false);
|
||||
|
||||
if (Model->LoadInventory(Inventory))
|
||||
{
|
||||
|
@ -655,27 +686,27 @@ QString Project::GetExportFileName(const QString& FileName, const QString& Defau
|
|||
return QFileDialog::getSaveFileName(gMainWindow, DialogTitle, SaveFileName, DialogFilter);
|
||||
}
|
||||
|
||||
void Project::Export3DStudio(const QString& FileName)
|
||||
bool Project::Export3DStudio(const QString& FileName)
|
||||
{
|
||||
std::vector<lcModelPartsEntry> ModelParts = GetModelParts();
|
||||
|
||||
if (ModelParts.empty())
|
||||
{
|
||||
QMessageBox::information(gMainWindow, tr("LeoCAD"), tr("Nothing to export."));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
QString SaveFileName = GetExportFileName(FileName, "3ds", tr("Export 3D Studio"), tr("3DS Files (*.3ds);;All Files (*.*)"));
|
||||
|
||||
if (SaveFileName.isEmpty())
|
||||
return;
|
||||
return false;
|
||||
|
||||
lcDiskFile File(SaveFileName);
|
||||
|
||||
if (!File.Open(QIODevice::WriteOnly))
|
||||
{
|
||||
QMessageBox::warning(gMainWindow, tr("LeoCAD"), tr("Could not open file '%1' for writing.").arg(SaveFileName));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
long M3DStart = File.GetPosition();
|
||||
|
@ -882,17 +913,15 @@ void Project::Export3DStudio(const QString& FileName)
|
|||
File.WriteU16(0x0010); // CHK_COLOR_F
|
||||
File.WriteU32(18);
|
||||
|
||||
File.WriteFloats(Properties.mBackgroundSolidColor, 3);
|
||||
const lcPreferences& Preferences = lcGetPreferences();
|
||||
lcVector3 BackgroundSolidColor = lcVector3FromColor(Preferences.mBackgroundSolidColor);
|
||||
|
||||
File.WriteFloats(BackgroundSolidColor, 3);
|
||||
|
||||
File.WriteU16(0x0013); // CHK_LIN_COLOR_F
|
||||
File.WriteU32(18);
|
||||
|
||||
File.WriteFloats(Properties.mBackgroundSolidColor, 3);
|
||||
|
||||
File.WriteU16(0x1100); // CHK_BIT_MAP
|
||||
QByteArray BackgroundImage = Properties.mBackgroundImage.toLatin1();
|
||||
File.WriteU32(6 + 1 + (quint32)strlen(BackgroundImage.constData()));
|
||||
File.WriteBuffer(BackgroundImage.constData(), strlen(BackgroundImage.constData()) + 1);
|
||||
File.WriteFloats(BackgroundSolidColor, 3);
|
||||
|
||||
File.WriteU16(0x1300); // CHK_V_GRADIENT
|
||||
File.WriteU32(118);
|
||||
|
@ -902,43 +931,41 @@ void Project::Export3DStudio(const QString& FileName)
|
|||
File.WriteU16(0x0010); // CHK_COLOR_F
|
||||
File.WriteU32(18);
|
||||
|
||||
File.WriteFloats(Properties.mBackgroundGradientColor1, 3);
|
||||
const lcVector3 BackgroundGradientColor1 = lcVector3FromColor(Preferences.mBackgroundGradientColorTop);
|
||||
const lcVector3 BackgroundGradientColor2 = lcVector3FromColor(Preferences.mBackgroundGradientColorBottom);
|
||||
|
||||
File.WriteFloats(BackgroundGradientColor1, 3);
|
||||
|
||||
File.WriteU16(0x0013); // CHK_LIN_COLOR_F
|
||||
File.WriteU32(18);
|
||||
|
||||
File.WriteFloats(Properties.mBackgroundGradientColor1, 3);
|
||||
File.WriteFloats(BackgroundGradientColor1, 3);
|
||||
|
||||
File.WriteU16(0x0010); // CHK_COLOR_F
|
||||
File.WriteU32(18);
|
||||
|
||||
File.WriteFloats((Properties.mBackgroundGradientColor1 + Properties.mBackgroundGradientColor2) / 2.0f, 3);
|
||||
File.WriteFloats((BackgroundGradientColor1 + BackgroundGradientColor2) / 2.0f, 3);
|
||||
|
||||
File.WriteU16(0x0013); // CHK_LIN_COLOR_F
|
||||
File.WriteU32(18);
|
||||
|
||||
File.WriteFloats((Properties.mBackgroundGradientColor1 + Properties.mBackgroundGradientColor2) / 2.0f, 3);
|
||||
File.WriteFloats((BackgroundGradientColor1 + BackgroundGradientColor2) / 2.0f, 3);
|
||||
|
||||
File.WriteU16(0x0010); // CHK_COLOR_F
|
||||
File.WriteU32(18);
|
||||
|
||||
File.WriteFloats(Properties.mBackgroundGradientColor2, 3);
|
||||
File.WriteFloats(BackgroundGradientColor2, 3);
|
||||
|
||||
File.WriteU16(0x0013); // CHK_LIN_COLOR_F
|
||||
File.WriteU32(18);
|
||||
|
||||
File.WriteFloats(Properties.mBackgroundGradientColor2, 3);
|
||||
File.WriteFloats(BackgroundGradientColor2, 3);
|
||||
|
||||
if (Properties.mBackgroundType == LC_BACKGROUND_GRADIENT)
|
||||
if (Preferences.mBackgroundGradient)
|
||||
{
|
||||
File.WriteU16(0x1301); // LIB3DS_USE_V_GRADIENT
|
||||
File.WriteU32(6);
|
||||
}
|
||||
else if (Properties.mBackgroundType == LC_BACKGROUND_IMAGE)
|
||||
{
|
||||
File.WriteU16(0x1101); // LIB3DS_USE_BIT_MAP
|
||||
File.WriteU32(6);
|
||||
}
|
||||
else
|
||||
{
|
||||
File.WriteU16(0x1201); // LIB3DS_USE_SOLID_BGND
|
||||
|
@ -1096,6 +1123,8 @@ void Project::Export3DStudio(const QString& FileName)
|
|||
File.Seek(M3DStart + 2, SEEK_SET);
|
||||
File.WriteU32(M3DEnd - M3DStart);
|
||||
File.Seek(M3DEnd, SEEK_SET);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Project::ExportBrickLink()
|
||||
|
@ -1162,27 +1191,27 @@ void Project::ExportBrickLink()
|
|||
BrickLinkFile.WriteLine("</INVENTORY>\n");
|
||||
}
|
||||
|
||||
void Project::ExportCOLLADA(const QString& FileName)
|
||||
bool Project::ExportCOLLADA(const QString& FileName)
|
||||
{
|
||||
std::vector<lcModelPartsEntry> ModelParts = GetModelParts();
|
||||
|
||||
if (ModelParts.empty())
|
||||
{
|
||||
QMessageBox::information(gMainWindow, tr("LeoCAD"), tr("Nothing to export."));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
QString SaveFileName = GetExportFileName(FileName, "dae", tr("Export COLLADA"), tr("COLLADA Files (*.dae);;All Files (*.*)"));
|
||||
|
||||
if (SaveFileName.isEmpty())
|
||||
return;
|
||||
return false;
|
||||
|
||||
QFile File(SaveFileName);
|
||||
|
||||
if (!File.open(QIODevice::WriteOnly))
|
||||
{
|
||||
QMessageBox::warning(gMainWindow, tr("LeoCAD"), tr("Could not open file '%1' for writing.").arg(SaveFileName));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
QTextStream Stream(&File);
|
||||
|
@ -1270,7 +1299,7 @@ void Project::ExportCOLLADA(const QString& FileName)
|
|||
QString ID = GetMeshID(ModelPart);
|
||||
|
||||
if (!Mesh)
|
||||
Mesh = gPlaceholderMesh;
|
||||
continue;
|
||||
|
||||
Stream << QString("\t<geometry id=\"%1\">\r\n").arg(ID);
|
||||
Stream << "\t\t<mesh>\r\n";
|
||||
|
@ -1379,6 +1408,11 @@ void Project::ExportCOLLADA(const QString& FileName)
|
|||
|
||||
for (const lcModelPartsEntry& ModelPart : ModelParts)
|
||||
{
|
||||
lcMesh* Mesh = !ModelPart.Mesh ? ModelPart.Info->GetMesh() : ModelPart.Mesh;
|
||||
|
||||
if (!Mesh)
|
||||
continue;
|
||||
|
||||
QString ID = GetMeshID(ModelPart);
|
||||
|
||||
Stream << "\t\t<node>\r\n";
|
||||
|
@ -1395,11 +1429,6 @@ void Project::ExportCOLLADA(const QString& FileName)
|
|||
Stream << "\t\t\t\t<bind_material>\r\n";
|
||||
Stream << "\t\t\t\t\t<technique_common>\r\n";
|
||||
|
||||
lcMesh* Mesh = !ModelPart.Mesh ? ModelPart.Info->GetMesh() : ModelPart.Mesh;
|
||||
|
||||
if (!Mesh)
|
||||
Mesh = gPlaceholderMesh;
|
||||
|
||||
for (int SectionIdx = 0; SectionIdx < Mesh->mLods[LC_MESH_LOD_HIGH].NumSections; SectionIdx++)
|
||||
{
|
||||
lcMeshSection* Section = &Mesh->mLods[LC_MESH_LOD_HIGH].Sections[SectionIdx];
|
||||
|
@ -1430,6 +1459,8 @@ void Project::ExportCOLLADA(const QString& FileName)
|
|||
Stream << "</scene>\r\n";
|
||||
|
||||
Stream << "</COLLADA>\r\n";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Project::ExportCSV()
|
||||
|
@ -1473,14 +1504,12 @@ void Project::ExportCSV()
|
|||
}
|
||||
}
|
||||
|
||||
std::vector<std::pair<lcModel*, lcStep>> Project::GetPageLayouts() const
|
||||
lcInstructions* Project::GetInstructions()
|
||||
{
|
||||
std::vector<const lcModel*> AddedModels;
|
||||
mInstructions.reset();
|
||||
mInstructions = std::unique_ptr<lcInstructions>(new lcInstructions(this));
|
||||
|
||||
if (mActiveModel)
|
||||
return mActiveModel->GetPageLayouts(AddedModels);
|
||||
|
||||
return std::vector<std::pair<lcModel*, lcStep>>();
|
||||
return mInstructions.get();
|
||||
}
|
||||
|
||||
void Project::ExportHTML(const lcHTMLExportOptions& Options)
|
||||
|
@ -1504,7 +1533,7 @@ void Project::ExportHTML(const lcHTMLExportOptions& Options)
|
|||
|
||||
auto AddPartsListImage = [&Dir](QTextStream& Stream, lcModel* Model, lcStep Step, const QString& BaseName)
|
||||
{
|
||||
QImage Image = Model->GetPartsListImage(1024, Step);
|
||||
QImage Image = Model->GetPartsListImage(1024, Step, LC_RGBA(255, 255, 255, 0), QFont("Arial", 16, QFont::Bold), Qt::black);
|
||||
|
||||
if (!Image.isNull())
|
||||
{
|
||||
|
@ -1731,7 +1760,7 @@ bool Project::ExportPOVRay(const QString& FileName)
|
|||
char Line[1024];
|
||||
|
||||
lcPiecesLibrary* Library = lcGetPiecesLibrary();
|
||||
std::map<const PieceInfo*, std::pair<char[LC_PIECE_NAME_LEN], int>> PieceTable;
|
||||
std::map<const PieceInfo*, std::pair<char[LC_PIECE_NAME_LEN + 1], int>> PieceTable;
|
||||
size_t NumColors = gColorList.size();
|
||||
std::vector<std::array<char, LC_MAX_COLOR_NAME>> ColorTable(NumColors);
|
||||
|
||||
|
@ -1767,12 +1796,12 @@ bool Project::ExportPOVRay(const QString& FileName)
|
|||
|
||||
while (TableFile.ReadLine(Line, sizeof(Line)))
|
||||
{
|
||||
char Src[1024], Dst[1024], Flags[1024];
|
||||
char Src[129], Dst[129], Flags[11];
|
||||
|
||||
if (*Line == ';')
|
||||
continue;
|
||||
|
||||
if (sscanf(Line,"%s%s%s", Src, Dst, Flags) != 3)
|
||||
if (sscanf(Line,"%128s%128s%10s", Src, Dst, Flags) != 3)
|
||||
continue;
|
||||
|
||||
strcat(Src, ".dat");
|
||||
|
@ -1783,21 +1812,21 @@ bool Project::ExportPOVRay(const QString& FileName)
|
|||
|
||||
if (strchr(Flags, 'L'))
|
||||
{
|
||||
std::pair<char[LC_PIECE_NAME_LEN], int>& Entry = PieceTable[Info];
|
||||
std::pair<char[LC_PIECE_NAME_LEN + 1], int>& Entry = PieceTable[Info];
|
||||
Entry.second |= LGEO_PIECE_LGEO;
|
||||
sprintf(Entry.first, "lg_%s", Dst);
|
||||
}
|
||||
|
||||
if (strchr(Flags, 'A'))
|
||||
{
|
||||
std::pair<char[LC_PIECE_NAME_LEN], int>& Entry = PieceTable[Info];
|
||||
std::pair<char[LC_PIECE_NAME_LEN + 1], int>& Entry = PieceTable[Info];
|
||||
Entry.second |= LGEO_PIECE_AR;
|
||||
sprintf(Entry.first, "ar_%s", Dst);
|
||||
}
|
||||
|
||||
if (strchr(Flags, 'S'))
|
||||
{
|
||||
std::pair<char[LC_PIECE_NAME_LEN], int>& Entry = PieceTable[Info];
|
||||
std::pair<char[LC_PIECE_NAME_LEN + 1], int>& Entry = PieceTable[Info];
|
||||
Entry.second |= LGEO_PIECE_SLOPE;
|
||||
Entry.first[0] = 0;
|
||||
}
|
||||
|
@ -1853,7 +1882,7 @@ bool Project::ExportPOVRay(const QString& FileName)
|
|||
if (!AddedMeshes.insert(Mesh).second)
|
||||
continue;
|
||||
|
||||
const std::pair<char[LC_PIECE_NAME_LEN], int>& Entry = Search->second;
|
||||
const std::pair<char[LC_PIECE_NAME_LEN + 1], int>& Entry = Search->second;
|
||||
if (Entry.first[0])
|
||||
{
|
||||
sprintf(Line, "#include \"%s.inc\"\n", Entry.first);
|
||||
|
@ -1892,7 +1921,7 @@ bool Project::ExportPOVRay(const QString& FileName)
|
|||
for (size_t ColorIdx = 0; ColorIdx < NumColors; ColorIdx++)
|
||||
ColorTablePointer[ColorIdx] = ColorTable[ColorIdx].data();
|
||||
|
||||
auto GetMeshName = [](const lcModelPartsEntry& ModelPart, char* Name)
|
||||
auto GetMeshName = [](const lcModelPartsEntry& ModelPart, char (&Name)[LC_PIECE_NAME_LEN])
|
||||
{
|
||||
strcpy(Name, ModelPart.Info->mFileName);
|
||||
|
||||
|
@ -1904,7 +1933,8 @@ bool Project::ExportPOVRay(const QString& FileName)
|
|||
{
|
||||
char Suffix[32];
|
||||
sprintf(Suffix, "_%p", ModelPart.Mesh);
|
||||
strcat(Name, Suffix);
|
||||
strncat(Name, Suffix, sizeof(Name) - 1);
|
||||
Name[sizeof(Name) - 1] = 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1923,8 +1953,10 @@ bool Project::ExportPOVRay(const QString& FileName)
|
|||
|
||||
if (!ModelPart.Mesh)
|
||||
{
|
||||
std::pair<char[LC_PIECE_NAME_LEN], int>& Entry = PieceTable[ModelPart.Info];
|
||||
sprintf(Entry.first, "lc_%s", Name);
|
||||
std::pair<char[LC_PIECE_NAME_LEN + 1], int>& Entry = PieceTable[ModelPart.Info];
|
||||
strcpy(Entry.first, "lc_");
|
||||
strncat(Entry.first, Name, sizeof(Entry.first) - 1);
|
||||
Entry.first[sizeof(Entry.first) - 1] = 0;
|
||||
}
|
||||
|
||||
Mesh->ExportPOVRay(POVFile, Name, &ColorTablePointer[0]);
|
||||
|
@ -1933,16 +1965,16 @@ bool Project::ExportPOVRay(const QString& FileName)
|
|||
POVFile.WriteLine(Line);
|
||||
}
|
||||
|
||||
lcCamera* Camera = gMainWindow->GetActiveView()->mCamera;
|
||||
const lcCamera* Camera = gMainWindow->GetActiveView()->GetCamera();
|
||||
const lcVector3& Position = Camera->mPosition;
|
||||
const lcVector3& Target = Camera->mTargetPosition;
|
||||
const lcVector3& Up = Camera->mUpVector;
|
||||
const lcModelProperties& Properties = mModels[0]->GetProperties();
|
||||
|
||||
sprintf(Line, "camera {\n perspective\n right x * image_width / image_height\n sky<%1g,%1g,%1g>\n location <%1g, %1g, %1g>\n look_at <%1g, %1g, %1g>\n angle %.0f * image_width / image_height\n}\n\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, "background { color rgb <%1g, %1g, %1g> }\n\n", Properties.mBackgroundSolidColor[0], Properties.mBackgroundSolidColor[1], Properties.mBackgroundSolidColor[2]);
|
||||
lcVector3 BackgroundColor = lcVector3FromColor(lcGetPreferences().mBackgroundSolidColor);
|
||||
sprintf(Line, "background { color rgb <%1g, %1g, %1g> }\n\n", BackgroundColor[0], BackgroundColor[1], BackgroundColor[2]);
|
||||
POVFile.WriteLine(Line);
|
||||
|
||||
lcVector3 Min(FLT_MAX, FLT_MAX, FLT_MAX);
|
||||
|
@ -1984,7 +2016,7 @@ bool Project::ExportPOVRay(const QString& FileName)
|
|||
|
||||
if (!ModelPart.Mesh)
|
||||
{
|
||||
std::pair<char[LC_PIECE_NAME_LEN], int>& Entry = PieceTable[ModelPart.Info];
|
||||
std::pair<char[LC_PIECE_NAME_LEN + 1], int>& Entry = PieceTable[ModelPart.Info];
|
||||
|
||||
if (Entry.second & LGEO_PIECE_SLOPE)
|
||||
{
|
||||
|
@ -2019,20 +2051,20 @@ bool Project::ExportPOVRay(const QString& FileName)
|
|||
return true;
|
||||
}
|
||||
|
||||
void Project::ExportWavefront(const QString& FileName)
|
||||
bool Project::ExportWavefront(const QString& FileName)
|
||||
{
|
||||
std::vector<lcModelPartsEntry> ModelParts = GetModelParts();
|
||||
|
||||
if (ModelParts.empty())
|
||||
{
|
||||
QMessageBox::information(gMainWindow, tr("LeoCAD"), tr("Nothing to export."));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
QString SaveFileName = GetExportFileName(FileName, QLatin1String("obj"), tr("Export Wavefront"), tr("Wavefront Files (*.obj);;All Files (*.*)"));
|
||||
|
||||
if (SaveFileName.isEmpty())
|
||||
return;
|
||||
return false;
|
||||
|
||||
lcDiskFile OBJFile(SaveFileName);
|
||||
char Line[1024];
|
||||
|
@ -2040,7 +2072,7 @@ void Project::ExportWavefront(const QString& FileName)
|
|||
if (!OBJFile.Open(QIODevice::WriteOnly))
|
||||
{
|
||||
QMessageBox::warning(gMainWindow, tr("LeoCAD"), tr("Could not open file '%1' for writing.").arg(SaveFileName));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
quint32 vert = 1;
|
||||
|
@ -2057,7 +2089,7 @@ void Project::ExportWavefront(const QString& FileName)
|
|||
if (!MaterialFile.Open(QIODevice::WriteOnly))
|
||||
{
|
||||
QMessageBox::warning(gMainWindow, tr("LeoCAD"), tr("Could not open file '%1' for writing.").arg(MaterialFileName));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
MaterialFile.WriteLine("# Colors used by LeoCAD\n\n");
|
||||
|
@ -2124,6 +2156,8 @@ void Project::ExportWavefront(const QString& FileName)
|
|||
vert += Mesh->mNumVertices;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Project::SaveImage()
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#include "object.h"
|
||||
#include "lc_array.h"
|
||||
#include "lc_application.h"
|
||||
|
||||
|
@ -29,23 +28,14 @@ public:
|
|||
bool PartsListEnd;
|
||||
};
|
||||
|
||||
enum LC_MOUSE_TRACK
|
||||
{
|
||||
LC_TRACK_NONE,
|
||||
LC_TRACK_LEFT,
|
||||
LC_TRACK_RIGHT
|
||||
};
|
||||
|
||||
class Project
|
||||
{
|
||||
public:
|
||||
Project();
|
||||
Project(bool IsPreview = false);
|
||||
~Project();
|
||||
|
||||
Project(const Project&) = delete;
|
||||
Project(Project&&) = delete;
|
||||
Project& operator=(const Project&) = delete;
|
||||
Project& operator=(Project&&) = delete;
|
||||
|
||||
const lcArray<lcModel*>& GetModels() const
|
||||
{
|
||||
|
@ -80,7 +70,7 @@ public:
|
|||
|
||||
QString GetImageFileName(bool AllowCurrentFolder) const;
|
||||
|
||||
std::vector<std::pair<lcModel*, lcStep>> GetPageLayouts() const;
|
||||
lcInstructions* GetInstructions();
|
||||
|
||||
void SetActiveModel(int ModelIndex);
|
||||
void SetActiveModel(const QString& FileName);
|
||||
|
@ -98,13 +88,13 @@ public:
|
|||
|
||||
void SaveImage();
|
||||
bool ExportModel(const QString& FileName, lcModel* Model) const;
|
||||
void Export3DStudio(const QString& FileName);
|
||||
bool Export3DStudio(const QString& FileName);
|
||||
void ExportBrickLink();
|
||||
void ExportCOLLADA(const QString& FileName);
|
||||
bool ExportCOLLADA(const QString& FileName);
|
||||
void ExportCSV();
|
||||
void ExportHTML(const lcHTMLExportOptions& Options);
|
||||
bool ExportPOVRay(const QString& FileName);
|
||||
void ExportWavefront(const QString& FileName);
|
||||
bool ExportWavefront(const QString& FileName);
|
||||
|
||||
void UpdatePieceInfo(PieceInfo* Info) const;
|
||||
|
||||
|
@ -113,12 +103,14 @@ protected:
|
|||
std::vector<lcModelPartsEntry> GetModelParts();
|
||||
void SetFileName(const QString& FileName);
|
||||
|
||||
bool mIsPreview;
|
||||
bool mModified;
|
||||
QString mFileName;
|
||||
QFileSystemWatcher mFileWatcher;
|
||||
|
||||
lcArray<lcModel*> mModels;
|
||||
lcModel* mActiveModel;
|
||||
std::unique_ptr<lcInstructions> mInstructions;
|
||||
|
||||
Q_DECLARE_TR_FUNCTIONS(Project);
|
||||
};
|
||||
|
|
|
@ -93,16 +93,13 @@ TexFont gTexFont;
|
|||
|
||||
TexFont::TexFont()
|
||||
{
|
||||
mRefCount = 0;
|
||||
mTexture = 0;
|
||||
memset(&mGlyphs, 0, sizeof(mGlyphs));
|
||||
}
|
||||
|
||||
bool TexFont::Load(lcContext* Context)
|
||||
bool TexFont::Initialize(lcContext* Context)
|
||||
{
|
||||
mRefCount++;
|
||||
|
||||
if (mRefCount != 1)
|
||||
if (mTexture)
|
||||
return true;
|
||||
|
||||
mFontHeight = 16;
|
||||
|
@ -151,14 +148,9 @@ bool TexFont::Load(lcContext* Context)
|
|||
return true;
|
||||
}
|
||||
|
||||
void TexFont::Release()
|
||||
void TexFont::Reset()
|
||||
{
|
||||
mRefCount--;
|
||||
if (mRefCount == 0)
|
||||
{
|
||||
glDeleteTextures(1, &mTexture);
|
||||
mTexture = 0;
|
||||
}
|
||||
mTexture = 0;
|
||||
}
|
||||
|
||||
void TexFont::GetStringDimensions(int* cx, int* cy, const char* Text) const
|
||||
|
|
|
@ -15,8 +15,8 @@ public:
|
|||
return mTexture;
|
||||
}
|
||||
|
||||
bool Load(lcContext* Context);
|
||||
void Release();
|
||||
bool Initialize(lcContext* Context);
|
||||
void Reset();
|
||||
|
||||
void PrintText(lcContext* Context, float Left, float Top, float Z, const char* Text) const;
|
||||
void GetTriangles(const lcMatrix44& Transform, const char* Text, float* Buffer) const;
|
||||
|
@ -34,7 +34,6 @@ protected:
|
|||
int mTextureWidth;
|
||||
int mTextureHeight;
|
||||
int mFontHeight;
|
||||
int mRefCount;
|
||||
};
|
||||
|
||||
extern TexFont gTexFont;
|
||||
|
|
211
common/view.h
211
common/view.h
|
@ -1,211 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "lc_glwidget.h"
|
||||
#include "camera.h"
|
||||
#include "lc_scene.h"
|
||||
#include "lc_viewsphere.h"
|
||||
#include "lc_commands.h"
|
||||
|
||||
enum class lcTrackButton
|
||||
{
|
||||
None,
|
||||
Left,
|
||||
Middle,
|
||||
Right
|
||||
};
|
||||
|
||||
enum lcTrackTool
|
||||
{
|
||||
LC_TRACKTOOL_NONE,
|
||||
LC_TRACKTOOL_INSERT,
|
||||
LC_TRACKTOOL_POINTLIGHT,
|
||||
LC_TRACKTOOL_SPOTLIGHT,
|
||||
LC_TRACKTOOL_CAMERA,
|
||||
LC_TRACKTOOL_SELECT,
|
||||
LC_TRACKTOOL_MOVE_X,
|
||||
LC_TRACKTOOL_MOVE_Y,
|
||||
LC_TRACKTOOL_MOVE_Z,
|
||||
LC_TRACKTOOL_MOVE_XY,
|
||||
LC_TRACKTOOL_MOVE_XZ,
|
||||
LC_TRACKTOOL_MOVE_YZ,
|
||||
LC_TRACKTOOL_MOVE_XYZ,
|
||||
LC_TRACKTOOL_ROTATE_X,
|
||||
LC_TRACKTOOL_ROTATE_Y,
|
||||
LC_TRACKTOOL_ROTATE_Z,
|
||||
LC_TRACKTOOL_ROTATE_XY,
|
||||
LC_TRACKTOOL_ROTATE_XYZ,
|
||||
LC_TRACKTOOL_SCALE_PLUS,
|
||||
LC_TRACKTOOL_SCALE_MINUS,
|
||||
LC_TRACKTOOL_ERASER,
|
||||
LC_TRACKTOOL_PAINT,
|
||||
LC_TRACKTOOL_COLOR_PICKER,
|
||||
LC_TRACKTOOL_ZOOM,
|
||||
LC_TRACKTOOL_PAN,
|
||||
LC_TRACKTOOL_ORBIT_X,
|
||||
LC_TRACKTOOL_ORBIT_Y,
|
||||
LC_TRACKTOOL_ORBIT_XY,
|
||||
LC_TRACKTOOL_ROLL,
|
||||
LC_TRACKTOOL_ZOOM_REGION,
|
||||
LC_TRACKTOOL_COUNT
|
||||
};
|
||||
|
||||
enum class lcDragState
|
||||
{
|
||||
None,
|
||||
Piece,
|
||||
Color
|
||||
};
|
||||
|
||||
class View : public lcGLWidget
|
||||
{
|
||||
public:
|
||||
View(lcModel* Model);
|
||||
~View();
|
||||
|
||||
View(const View&) = delete;
|
||||
View(View&&) = delete;
|
||||
View& operator=(const View&) = delete;
|
||||
View& operator=(View&&) = delete;
|
||||
|
||||
void Clear()
|
||||
{
|
||||
mModel = nullptr;
|
||||
mActiveSubmodelInstance = nullptr;
|
||||
}
|
||||
|
||||
lcModel* GetModel() const
|
||||
{
|
||||
return mModel;
|
||||
}
|
||||
|
||||
lcModel* GetActiveModel() const;
|
||||
void SetTopSubmodelActive();
|
||||
void SetSelectedSubmodelActive();
|
||||
|
||||
static void CreateResources(lcContext* Context);
|
||||
static void DestroyResources(lcContext* Context);
|
||||
|
||||
void OnDraw() override;
|
||||
void OnInitialUpdate() override;
|
||||
void OnUpdateCursor() override;
|
||||
void OnLeftButtonDown() override;
|
||||
void OnLeftButtonUp() override;
|
||||
void OnLeftButtonDoubleClick() override;
|
||||
void OnMiddleButtonDown() override;
|
||||
void OnMiddleButtonUp() override;
|
||||
void OnRightButtonDown() override;
|
||||
void OnRightButtonUp() override;
|
||||
void OnBackButtonUp() override;
|
||||
void OnForwardButtonUp() override;
|
||||
void OnMouseMove() override;
|
||||
void OnMouseWheel(float Direction) override;
|
||||
|
||||
bool IsTracking() const
|
||||
{
|
||||
return mTrackButton != lcTrackButton::None;
|
||||
}
|
||||
|
||||
void StartOrbitTracking();
|
||||
void CancelTrackingOrClearSelection();
|
||||
void BeginDrag(lcDragState DragState);
|
||||
void EndDrag(bool Accept);
|
||||
|
||||
void SetProjection(bool Ortho);
|
||||
void LookAt();
|
||||
void ZoomExtents();
|
||||
void MoveCamera(const lcVector3& Direction);
|
||||
void Zoom(float Amount);
|
||||
|
||||
void RemoveCamera();
|
||||
void SetCamera(lcCamera* Camera, bool ForceCopy);
|
||||
void SetCamera(const char* CameraName);
|
||||
void SetCameraIndex(int Index);
|
||||
void SetViewpoint(lcViewpoint Viewpoint);
|
||||
void SetViewpoint(const lcVector3& Position);
|
||||
void SetCameraAngles(float Latitude, float Longitude);
|
||||
void SetDefaultCamera();
|
||||
lcMatrix44 GetProjectionMatrix() const;
|
||||
lcCursor GetCursor() const;
|
||||
void ShowContextMenu() const;
|
||||
|
||||
lcVector3 GetMoveDirection(const lcVector3& Direction) const;
|
||||
lcMatrix44 GetPieceInsertPosition(bool IgnoreSelected, PieceInfo* Info) const;
|
||||
lcVector3 GetCameraLightInsertPosition() const;
|
||||
void GetRayUnderPointer(lcVector3& Start, lcVector3& End) const;
|
||||
lcObjectSection FindObjectUnderPointer(bool PiecesOnly, bool IgnoreSelected) const;
|
||||
lcArray<lcObject*> FindObjectsInBox(float x1, float y1, float x2, float y2) const;
|
||||
|
||||
lcCamera* mCamera;
|
||||
|
||||
lcVector3 ProjectPoint(const lcVector3& Point) const
|
||||
{
|
||||
int Viewport[4] = { 0, 0, mWidth, mHeight };
|
||||
return lcProjectPoint(Point, mCamera->mWorldView, GetProjectionMatrix(), Viewport);
|
||||
}
|
||||
|
||||
lcVector3 UnprojectPoint(const lcVector3& Point) const
|
||||
{
|
||||
int Viewport[4] = { 0, 0, mWidth, mHeight };
|
||||
return lcUnprojectPoint(Point, mCamera->mWorldView, GetProjectionMatrix(), Viewport);
|
||||
}
|
||||
|
||||
void UnprojectPoints(lcVector3* Points, int NumPoints) const
|
||||
{
|
||||
int Viewport[4] = { 0, 0, mWidth, mHeight };
|
||||
lcUnprojectPoints(Points, NumPoints, mCamera->mWorldView, GetProjectionMatrix(), Viewport);
|
||||
}
|
||||
|
||||
bool BeginRenderToImage(int Width, int Height);
|
||||
void EndRenderToImage();
|
||||
|
||||
QImage GetRenderImage() const
|
||||
{
|
||||
return mRenderImage;
|
||||
}
|
||||
|
||||
protected:
|
||||
static void CreateSelectMoveOverlayMesh(lcContext* Context);
|
||||
|
||||
void DrawSelectMoveOverlay();
|
||||
void DrawRotateOverlay();
|
||||
void DrawSelectZoomRegionOverlay();
|
||||
void DrawRotateViewOverlay();
|
||||
void DrawGrid();
|
||||
void DrawAxes();
|
||||
void DrawViewport();
|
||||
|
||||
void UpdateTrackTool();
|
||||
bool IsTrackToolAllowed(lcTrackTool TrackTool, quint32 AllowedTransforms) const;
|
||||
lcTool GetCurrentTool() const;
|
||||
lcTrackTool GetOverrideTrackTool(Qt::MouseButton Button) const;
|
||||
float GetOverlayScale() const;
|
||||
void StartTracking(lcTrackButton TrackButton);
|
||||
void StopTracking(bool Accept);
|
||||
void OnButtonDown(lcTrackButton TrackButton);
|
||||
lcMatrix44 GetTileProjectionMatrix(int CurrentRow, int CurrentColumn, int CurrentTileWidth, int CurrentTileHeight) const;
|
||||
|
||||
lcModel* mModel;
|
||||
lcPiece* mActiveSubmodelInstance;
|
||||
lcMatrix44 mActiveSubmodelTransform;
|
||||
|
||||
lcScene mScene;
|
||||
lcDragState mDragState;
|
||||
lcTrackButton mTrackButton;
|
||||
lcTrackTool mTrackTool;
|
||||
bool mTrackToolFromOverlay;
|
||||
bool mTrackUpdated;
|
||||
int mMouseDownX;
|
||||
int mMouseDownY;
|
||||
lcVector3 mMouseDownPosition;
|
||||
PieceInfo* mMouseDownPiece;
|
||||
QImage mRenderImage;
|
||||
std::pair<lcFramebuffer, lcFramebuffer> mRenderFramebuffer;
|
||||
lcViewSphere mViewSphere;
|
||||
|
||||
lcVertexBuffer mGridBuffer;
|
||||
int mGridSettings[7];
|
||||
|
||||
static lcVertexBuffer mRotateMoveVertexBuffer;
|
||||
static lcIndexBuffer mRotateMoveIndexBuffer;
|
||||
};
|
||||
|
|
@ -18,25 +18,40 @@ rendering.
|
|||
|
||||
- LeoCAD for Windows:
|
||||
|
||||
Download LeoCAD-Windows-19.07.exe to your computer, double click on the
|
||||
icon to launch the installer and follow the intructions.
|
||||
Download the latest LeoCAD-Windows.exe to your computer, double click on
|
||||
the icon to launch the installer and follow the instructions.
|
||||
|
||||
- LeoCAD for Linux:
|
||||
|
||||
Download LeoCAD-Linux-19.07-x86_64.AppImage, make the file executable
|
||||
There are multiple ways to install LeoCAD on Linux.
|
||||
|
||||
* AppImage:
|
||||
|
||||
Download the latest LeoCAD-Linux.AppImage, make the file executable
|
||||
(chmod +x) and run it.
|
||||
|
||||
* Flatpak:
|
||||
|
||||
You can also install LeoCAD releases as a Flatpak from Flathub:
|
||||
https://flathub.org/apps/details/org.leocad.LeoCAD
|
||||
|
||||
Note: there might be a delay for new releases to appear there. If
|
||||
you have it already installed, it will be updated.
|
||||
|
||||
* From source:
|
||||
|
||||
If you prefer to compile LeoCAD yourself, go to the GitHub releases page
|
||||
at https://github.com/leozide/leocad/releases/latest and download the
|
||||
at https://github.com/leozide/leocad/releases/latest and download the
|
||||
source archive from there. If you do not already have a Parts Library
|
||||
installed, you will need to download one and follow the installation
|
||||
instructions. More information on how to compile your own executable is
|
||||
available in the Documentation section of https://www.leocad.org
|
||||
|
||||
- LeoCAD for Mac OSX:
|
||||
- LeoCAD for macOS:
|
||||
|
||||
Download LeoCAD-macOS-19.07.dmg to your computer, double click on the
|
||||
icon to open the archive and copy LeoCAD.app to your Applications folder.
|
||||
Download the latest LeoCAD-macOS.dmg to your computer, double click on
|
||||
the icon to open the archive, copy LeoCAD.app to your Applications folder
|
||||
and then launch it from there.
|
||||
|
||||
New users should read the online tutorial located at
|
||||
https://www.leocad.org/docs/tutorial1.html to learn how to use LeoCAD.
|
||||
|
@ -51,6 +66,9 @@ Online Resources
|
|||
- GitHub page:
|
||||
https://github.com/leozide/leocad
|
||||
|
||||
- Unstable builds:
|
||||
https://github.com/leozide/leocad/releases/tag/continuous
|
||||
|
||||
|
||||
Legal Disclaimer
|
||||
----------------
|
||||
|
|
187
docs/leocad.1
187
docs/leocad.1
|
@ -1,10 +1,10 @@
|
|||
.TH LEOCAD 1 "20 July 2000"
|
||||
.TH LEOCAD 1 "26 January 2021"
|
||||
.\" NAME should be all caps, SECTION should be 1-8, maybe w/ subsection
|
||||
.\" other parms are allowed: see man(7), man(1)
|
||||
.\" other params are allowed: see man(7), man(1)
|
||||
.SH NAME
|
||||
LeoCAD \- CAD program for LEGO models.
|
||||
.SH SYNOPSIS
|
||||
\fIleocad \fR[\fI infile \fR[ \-i \fR[\fI outfile.ext \fR]\fI \fR[\fI\-w x\fR]\fI \fR[\fI\-h y\fR] ] \fR] [\fI\-l path\fR]
|
||||
\fIleocad \fR[\fIOPTIONS\fR] [\fIINFILE\fR]
|
||||
.SH "DESCRIPTION"
|
||||
\fILeoCAD \fR is a CAD program for creating virtual LEGO models. It
|
||||
has an easy to use interface and includes thousands of different
|
||||
|
@ -12,20 +12,23 @@ parts in its library.
|
|||
|
||||
.SH OPTIONS
|
||||
Below is a summary of all of the options that \fILeoCAD\fR
|
||||
accepts. Most options have two equivalent names, one of
|
||||
accepts. Many options have two equivalent names, one of
|
||||
which is a single letter preceded by -, and the other of
|
||||
which is a long name preceded by --. Brackets ([ and ])
|
||||
indicate that an option takes an optional argument.
|
||||
indicate that an option takes an optional parameter.
|
||||
|
||||
.TP
|
||||
.B infile
|
||||
Loads the project file \fIinfile\fR
|
||||
|
||||
.TP
|
||||
.BI "\-i [" outfile.ext ]
|
||||
.ns
|
||||
\fB\-l \fIpath\fR, \fB\-\-libpath \fIpath
|
||||
.br
|
||||
Set the parts library location.
|
||||
|
||||
.TP
|
||||
.BI "\-\-image [" outfile.ext ]
|
||||
\fB\-i \fR[\fIoutfile.ext\fR], \fB\-\-image \fR[\fIoutfile.ext\fR]
|
||||
.br
|
||||
Saves a picture to \fIoutfile.ext \fR in the image format specified
|
||||
by \fIext\fR and exits. If outfile is not given then the program will
|
||||
use a name based on \fIinfile\fR. The file format is selected by \fIext\fR
|
||||
|
@ -33,83 +36,169 @@ and can be gif, bmp, png or jpg (if \fIext\fR is not present then the
|
|||
default preferences format will be used).
|
||||
|
||||
.TP
|
||||
.BI "\-w "width
|
||||
.ns
|
||||
.TP
|
||||
.BI "\-\-width "width
|
||||
\fB\-w \fIwidth\fR, \fB\-\-width \fIwidth
|
||||
.br
|
||||
Sets the width of the picture to \fIwidth\fR.
|
||||
|
||||
.TP
|
||||
.BI "\-h "height
|
||||
.ns
|
||||
.TP
|
||||
.BI "\-\-height "height
|
||||
\fB\-h \fIheight\fR, \fB\-\-height \fIheight
|
||||
.br
|
||||
Sets the height of the picture to \fIheight\fR.
|
||||
|
||||
.TP
|
||||
.BI "\-f "time
|
||||
.ns
|
||||
.TP
|
||||
.BI "\-\-from "time
|
||||
Start saving pictures at the step \fItime\fR.
|
||||
\fB\-f \fItime\fR, \fB\-\-from \fItime
|
||||
.br
|
||||
Start saving pictures at the step \fItime\fR. Steps start at 1.
|
||||
|
||||
.TP
|
||||
.BI "\-t "time
|
||||
.ns
|
||||
.TP
|
||||
.BI "\-\-to "time
|
||||
\fB\-t \fItime\fR, \fB\-\-to \fItime
|
||||
.br
|
||||
Save pictures until the step \fItime\fR.
|
||||
|
||||
.TP
|
||||
.BI "\-m "model
|
||||
.ns
|
||||
.TP
|
||||
.BI "\-\-model "model
|
||||
Sets the active submodel to \fImodel\fR.
|
||||
\fB\-s \fIsubmodel\fR, \fB\-\-submodel \fIsubmodel
|
||||
.br
|
||||
Sets the active submodel to \fIsubmodel\fR.
|
||||
|
||||
.TP
|
||||
.BI "\-c "camera
|
||||
.ns
|
||||
.TP
|
||||
.BI "\-\-camera "camera
|
||||
\fB\-c \fIcamera\fR, \fB\-\-camera \fIcamera
|
||||
.br
|
||||
Sets the active camera to \fIcamera\fR.
|
||||
|
||||
.TP
|
||||
.BI "\-\-viewpoint "front\ back\ left\ right\ top\ bottom\ home
|
||||
Sets the viewpoint to one of the predefined angles.
|
||||
\fB\-ss \fIid\fR,\ \fB\-\-stud\-style\ \fIid
|
||||
.br
|
||||
Set the stud style. Valid values 0=Plain, 1=Thin Lines Logo, 2=Outline Logo, 3=Sharp Top Logo, 4=Rounded Top Logo, 5=Flattened Logo, 6=High Contrast, 7=High Contrast with Logo.
|
||||
|
||||
.TP
|
||||
\fB\-\-viewpoint \fRfront\ |\ back\ |\ left\ |\ right\ |\ top\ |\ bottom\ |\ home
|
||||
.br
|
||||
Sets the viewpoint to one of the predefined view angles.
|
||||
|
||||
.TP
|
||||
.BI "\-\-camera\-angles " latitude " " longitude
|
||||
Set the camera angles in degrees around the model.
|
||||
|
||||
.TP
|
||||
.BI "\-\-camera\-position " x " " y " " z " " tx " " ty " " tz " " ux " " uy " " uz
|
||||
Set the camera position, target and up vector using the \fILeoCAD\fR coordinate system.
|
||||
|
||||
.TP
|
||||
.BI "\-\-camera\-position-ldraw " x " " y " " z " " tx " " ty " " tz " " ux " " uy " " uz
|
||||
Set the camera position, target and up vector using the \fILDraw\fR coordinate system.
|
||||
|
||||
.TP
|
||||
.B \-\-orthographic
|
||||
Use an orthographic projection.
|
||||
|
||||
.TP
|
||||
.BI "\-\-fov " degrees
|
||||
Set the vertical field of view used to render images.
|
||||
|
||||
.TP
|
||||
.BI "\-\-zplanes " near " " far
|
||||
Set the near and far clipping planes used to render images (1 <= \fInear\fR < \fIfar\fR).
|
||||
|
||||
.TP
|
||||
.B \-\-fade\-steps
|
||||
Render parts from prior steps faded.
|
||||
|
||||
.TP
|
||||
.B \-\-no\-fade\-steps
|
||||
Do not render parts from prior steps faded.
|
||||
|
||||
.TP
|
||||
.BI "\-\-fade\-steps\-color " color
|
||||
Color to use for rendering faded parts. (#AARRGGBB where AA, RR, GG, and BB are hexadecimal values for alpha, red, green, and blue respectively.)
|
||||
|
||||
.TP
|
||||
.B \-\-highlight
|
||||
Adds a border around the pieces in the step they appear when saving pictures.
|
||||
Highlight parts in the steps they appear.
|
||||
|
||||
.TP
|
||||
.BI "\-l "path
|
||||
.ns
|
||||
.TP
|
||||
.BI "\-\-libpath "path
|
||||
Use alternate parts library found in \fIpath \fR. The Linux version
|
||||
of \fILeoCAD \fRuses /usr/share/leocad/ as the default.
|
||||
.B \-\-no\-highlight
|
||||
Do not highlight parts in the steps they appear.
|
||||
|
||||
.TP
|
||||
.BI "\-obj [" outfile.obj ]
|
||||
.BI "\-\-highlight\-color " color
|
||||
Color to use to highlight parts, (#AARRGGBB where AA, RR, GG, and BB are hexadecimal values for alpha, red, green, and blue respectively.)
|
||||
|
||||
.TP
|
||||
\fB\-\-shading \fRwireframe\ |\ flat\ |\ default\ |\ full
|
||||
.br
|
||||
Select shading mode for rendering.
|
||||
|
||||
.TP
|
||||
.BI "\-\-line-width " width
|
||||
Set the with of the edge lines.
|
||||
|
||||
.TP
|
||||
.BI "\-\-aa\-samples " count
|
||||
AntiAliasing sample size (1, 2, 4, or 8).
|
||||
|
||||
.TP
|
||||
\fB\-scc \fI#AARRGGBB\fR,\ \fB\-\-stud\-cylinder\-color\ \fI#AARRGGBB
|
||||
.br
|
||||
High contrast stud cylinder color.
|
||||
|
||||
.TP
|
||||
\fB\-ec \fI#AARRGGBB\fR,\ \fB\-\-edge\-color\ \fI#AARRGGBB
|
||||
.br
|
||||
High contrast edge color.
|
||||
|
||||
.TP
|
||||
\fB\-bec \fI#AARRGGBB\fR,\ \fB\-\-black\-edge\-color\ \fI#AARRGGBB
|
||||
.br
|
||||
High contrast edge color for black parts.
|
||||
|
||||
.TP
|
||||
\fB\-dec \fI#AARRGGBB\fR,\ \fB\-\-dark\-edge\-color\ \fI#AARRGGBB
|
||||
.br
|
||||
High contrast edge color for dark color parts.
|
||||
|
||||
.TP
|
||||
\fB\-aec,\ \fB\-\-automate\-edge\-color
|
||||
.br
|
||||
Enable automatically adjusted edge colors.\
|
||||
|
||||
.TP
|
||||
\fB\-cc \fIfloat\fR,\ \fB\-\-color\-contrast\ \ffloat
|
||||
.br
|
||||
Set the near and far clipping planes used to render images (1 <= \fInear\fR < \fIfar\fR).
|
||||
|
||||
.TP
|
||||
\fB\-ldv \fIfloat\fR,\ \fB\-\-light\-dark\-value\ \ffloat
|
||||
.br
|
||||
Set the value to indicate a light or dark color.
|
||||
|
||||
.TP
|
||||
\fB\-obj \fR[\fIoutfile.obj\fR]
|
||||
.br
|
||||
Exports the model to wavefront format.
|
||||
|
||||
.TP
|
||||
.BI "\-3ds [" outfile.3ds ]
|
||||
\fB\-3ds \fR[\fIoutfile.3ds\fR]
|
||||
.br
|
||||
Exports the model to 3DS format.
|
||||
|
||||
.TP
|
||||
.BI "\-dae [" outfile.dae ]
|
||||
\fB\-dae \fR[\fIoutfile.dae\fR]
|
||||
.br
|
||||
Exports the model to COLLADA DAE format.
|
||||
|
||||
.TP
|
||||
.BI "\-html [" path ]
|
||||
\fB\-html \fR[\fIpath\fR]
|
||||
.br
|
||||
Creates an HTML page for the model.
|
||||
|
||||
.TP
|
||||
.BR \-v ",\ " \-\-version
|
||||
Output version information and exit.
|
||||
|
||||
.TP
|
||||
.BR \-? ",\ " \-\-help
|
||||
Display a brief usage synopsis and exit.
|
||||
|
||||
.SH ENVIRONMENT
|
||||
``LEOCAD_LIB'' may be set to the path of the parts library.
|
||||
|
||||
|
@ -132,6 +221,6 @@ If you find any bugs please report them at https://github.com/leozide/leocad/iss
|
|||
\fILeoCAD \fRis written by Leonardo Zide <leozide@gmail.com>.
|
||||
You can visit the LeoCAD homepage at https://www.leocad.org/
|
||||
|
||||
This manual page was written by Patrick Mahoney <pat7@gmx.net>,
|
||||
This manual page was originally written by Patrick Mahoney <pat7@gmx.net>,
|
||||
for the Debian GNU/Linux system (but may be used by others).
|
||||
|
||||
It has since been edited by others.
|
||||
|
|
368
leocad.pro
368
leocad.pro
|
@ -1,16 +1,18 @@
|
|||
QT += core gui opengl network xml
|
||||
QT += core gui opengl network xml concurrent
|
||||
QT *= printsupport
|
||||
TEMPLATE = app
|
||||
|
||||
greaterThan(QT_MAJOR_VERSION, 4) {
|
||||
QT *= printsupport
|
||||
QT += concurrent
|
||||
lessThan(QT_MAJOR_VERSION, 5) {
|
||||
error("LeoCAD requires Qt5.4 or later.")
|
||||
}
|
||||
|
||||
equals(QT_MAJOR_VERSION, 5) {
|
||||
qtHaveModule(gamepad) {
|
||||
QT += gamepad
|
||||
DEFINES += LC_ENABLE_GAMEPAD
|
||||
}
|
||||
equals(QT_MAJOR_VERSION, 5):lessThan(QT_MINOR_VERSION, 4) {
|
||||
error("LeoCAD requires Qt5.4 or later.")
|
||||
}
|
||||
|
||||
qtHaveModule(gamepad) {
|
||||
QT += gamepad
|
||||
DEFINES += LC_ENABLE_GAMEPAD
|
||||
}
|
||||
|
||||
INCLUDEPATH += qt common
|
||||
|
@ -18,7 +20,7 @@ CONFIG += precompile_header incremental c++11 force_debug_info
|
|||
|
||||
win32 {
|
||||
RC_ICONS = resources/leocad.ico
|
||||
VERSION = 19.7.1.0
|
||||
VERSION = 21.1.0.0
|
||||
QMAKE_TARGET_COMPANY = LeoCAD Software
|
||||
QMAKE_TARGET_DESCRIPTION = LeoCAD
|
||||
QMAKE_TARGET_COPYRIGHT = "Copyright (C) LeoCAD.org"
|
||||
|
@ -29,17 +31,13 @@ win32 {
|
|||
LIBS += -lwininet
|
||||
}
|
||||
win32-msvc* {
|
||||
QMAKE_CXXFLAGS_WARN_ON += -wd4100
|
||||
QMAKE_CXXFLAGS *= /MP /W4
|
||||
QMAKE_CXXFLAGS_WARN_ON += /W4 -wd4100
|
||||
QMAKE_CXXFLAGS *= /MP
|
||||
PRECOMPILED_HEADER = common/lc_global.h
|
||||
DEFINES += _CRT_SECURE_NO_WARNINGS _CRT_SECURE_NO_DEPRECATE=1 _CRT_NONSTDC_NO_WARNINGS=1
|
||||
greaterThan(QT_MAJOR_VERSION, 4) {
|
||||
INCLUDEPATH += $$[QT_INSTALL_HEADERS]/QtZlib
|
||||
} else {
|
||||
INCLUDEPATH += $$[QT_INSTALL_PREFIX]/src/3rdparty/zlib
|
||||
}
|
||||
QMAKE_LFLAGS += /INCREMENTAL
|
||||
PRECOMPILED_SOURCE = common/lc_global.cpp
|
||||
DEFINES += _CRT_SECURE_NO_WARNINGS _CRT_SECURE_NO_DEPRECATE=1 _CRT_NONSTDC_NO_WARNINGS=1
|
||||
INCLUDEPATH += $$[QT_INSTALL_HEADERS]/QtZlib
|
||||
QMAKE_LFLAGS += /INCREMENTAL
|
||||
LIBS += -ladvapi32 -lshell32 -lopengl32 -luser32
|
||||
} else {
|
||||
PRECOMPILED_HEADER = common/lc_global.h
|
||||
|
@ -47,17 +45,6 @@ win32-msvc* {
|
|||
QMAKE_CXXFLAGS_WARN_ON += -Wno-unused-parameter
|
||||
}
|
||||
|
||||
lessThan(QT_MAJOR_VERSION, 5) {
|
||||
unix {
|
||||
GCC_VERSION = $$system(g++ -dumpversion)
|
||||
greaterThan(GCC_VERSION, 4.6) {
|
||||
QMAKE_CXXFLAGS += -std=c++11
|
||||
} else {
|
||||
QMAKE_CXXFLAGS += -std=c++0x
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
isEmpty(QMAKE_LRELEASE) {
|
||||
win32:QMAKE_LRELEASE = $$[QT_INSTALL_BINS]\\lrelease.exe
|
||||
else:QMAKE_LRELEASE = $$[QT_INSTALL_BINS]/lrelease
|
||||
|
@ -116,11 +103,10 @@ unix:!macx {
|
|||
isEmpty(INSTALL_PREFIX):INSTALL_PREFIX = /usr
|
||||
isEmpty(BIN_DIR):BIN_DIR = $$INSTALL_PREFIX/bin
|
||||
isEmpty(DOCS_DIR):DOCS_DIR = $$INSTALL_PREFIX/share/doc/leocad
|
||||
isEmpty(ICON_DIR):ICON_DIR = $$INSTALL_PREFIX/share/pixmaps
|
||||
isEmpty(ICON_DIR):ICON_DIR = $$INSTALL_PREFIX/share/icons
|
||||
isEmpty(MAN_DIR):MAN_DIR = $$INSTALL_PREFIX/share/man/man1
|
||||
isEmpty(DESKTOP_DIR):DESKTOP_DIR = $$INSTALL_PREFIX/share/applications
|
||||
isEmpty(MIME_DIR):MIME_DIR = $$INSTALL_PREFIX/share/mime/packages
|
||||
isEmpty(MIME_ICON_DIR):MIME_ICON_DIR = $$INSTALL_PREFIX/share/icons/hicolor/scalable/mimetypes
|
||||
isEmpty(APPDATA_DIR):APPDATA_DIR = $$INSTALL_PREFIX/share/metainfo
|
||||
|
||||
target.path = $$BIN_DIR
|
||||
|
@ -130,16 +116,22 @@ unix:!macx {
|
|||
man.files = docs/leocad.1
|
||||
desktop.path = $$DESKTOP_DIR
|
||||
desktop.files = qt/leocad.desktop
|
||||
icon.path = $$ICON_DIR
|
||||
icon.files = resources/leocad.png
|
||||
icons.path = $$ICON_DIR/hicolor
|
||||
icons.files += tools/icon/128x128
|
||||
icons.files += tools/icon/16x16
|
||||
icons.files += tools/icon/24x24
|
||||
icons.files += tools/icon/256x256
|
||||
icons.files += tools/icon/32x32
|
||||
icons.files += tools/icon/48x48
|
||||
icons.files += tools/icon/512x512
|
||||
icons.files += tools/icon/64x64
|
||||
icons.files += tools/icon/scalable
|
||||
mime.path = $$MIME_DIR
|
||||
mime.files = qt/leocad.xml
|
||||
mime_icon.path = $$MIME_ICON_DIR
|
||||
mime_icon.files = resources/application-vnd.leocad.svg
|
||||
appdata.path = $$APPDATA_DIR
|
||||
appdata.files = tools/setup/leocad.appdata.xml
|
||||
|
||||
INSTALLS += target docs man desktop icon mime mime_icon appdata
|
||||
|
||||
INSTALLS += target docs man desktop icons mime appdata
|
||||
|
||||
!isEmpty(DISABLE_UPDATE_CHECK) {
|
||||
DEFINES += LC_DISABLE_UPDATE_CHECK=$$DISABLE_UPDATE_CHECK
|
||||
|
@ -158,159 +150,167 @@ macx {
|
|||
document_icon.path = Contents/Resources
|
||||
library.files += $$_PRO_FILE_PWD_/library.bin
|
||||
library.path = Contents/Resources
|
||||
povray.files += $$_PRO_FILE_PWD_/tools/povray/povray
|
||||
povray.files += $$_PRO_FILE_PWD_/povray
|
||||
povray.path = Contents/MacOS
|
||||
|
||||
QMAKE_BUNDLE_DATA += document_icon library povray
|
||||
DEFINES += LC_DISABLE_UPDATE_CHECK=1
|
||||
}
|
||||
|
||||
SOURCES += common/view.cpp \
|
||||
common/texfont.cpp \
|
||||
common/project.cpp \
|
||||
common/pieceinf.cpp \
|
||||
common/piece.cpp \
|
||||
common/object.cpp \
|
||||
common/minifig.cpp \
|
||||
common/light.cpp \
|
||||
common/lc_application.cpp \
|
||||
common/lc_category.cpp \
|
||||
common/lc_colors.cpp \
|
||||
common/lc_commands.cpp \
|
||||
common/lc_context.cpp \
|
||||
common/lc_file.cpp \
|
||||
common/lc_glextensions.cpp \
|
||||
common/lc_http.cpp \
|
||||
common/lc_library.cpp \
|
||||
common/lc_lxf.cpp \
|
||||
common/lc_mainwindow.cpp \
|
||||
common/lc_mesh.cpp \
|
||||
common/lc_meshloader.cpp \
|
||||
common/lc_model.cpp \
|
||||
common/lc_profile.cpp \
|
||||
common/lc_scene.cpp \
|
||||
common/lc_selectbycolordialog.cpp \
|
||||
common/lc_shortcuts.cpp \
|
||||
common/lc_stringcache.cpp \
|
||||
common/lc_synth.cpp \
|
||||
common/lc_texture.cpp \
|
||||
common/lc_viewsphere.cpp \
|
||||
common/lc_zipfile.cpp \
|
||||
common/image.cpp \
|
||||
common/group.cpp \
|
||||
common/camera.cpp \
|
||||
qt/system.cpp \
|
||||
qt/qtmain.cpp \
|
||||
qt/lc_qarraydialog.cpp \
|
||||
qt/lc_qgroupdialog.cpp \
|
||||
qt/lc_qaboutdialog.cpp \
|
||||
qt/lc_qeditgroupsdialog.cpp \
|
||||
qt/lc_qselectdialog.cpp \
|
||||
qt/lc_qpropertiesdialog.cpp \
|
||||
qt/lc_qhtmldialog.cpp \
|
||||
qt/lc_qminifigdialog.cpp \
|
||||
qt/lc_qpreferencesdialog.cpp \
|
||||
qt/lc_qcategorydialog.cpp \
|
||||
qt/lc_qimagedialog.cpp \
|
||||
qt/lc_qupdatedialog.cpp \
|
||||
qt/lc_qutils.cpp \
|
||||
qt/lc_qpropertiestree.cpp \
|
||||
qt/lc_qcolorpicker.cpp \
|
||||
qt/lc_qglwidget.cpp \
|
||||
qt/lc_qcolorlist.cpp \
|
||||
qt/lc_qfinddialog.cpp \
|
||||
qt/lc_qmodellistdialog.cpp \
|
||||
common/lc_partselectionwidget.cpp \
|
||||
common/lc_timelinewidget.cpp \
|
||||
qt/lc_renderdialog.cpp \
|
||||
qt/lc_setsdatabasedialog.cpp \
|
||||
common/lc_partpalettedialog.cpp
|
||||
SOURCES += \
|
||||
common/texfont.cpp \
|
||||
common/project.cpp \
|
||||
common/pieceinf.cpp \
|
||||
common/piece.cpp \
|
||||
common/object.cpp \
|
||||
common/minifig.cpp \
|
||||
common/light.cpp \
|
||||
common/lc_application.cpp \
|
||||
common/lc_category.cpp \
|
||||
common/lc_collapsiblewidget.cpp \
|
||||
common/lc_colors.cpp \
|
||||
common/lc_commands.cpp \
|
||||
common/lc_context.cpp \
|
||||
common/lc_edgecolordialog.cpp \
|
||||
common/lc_file.cpp \
|
||||
common/lc_findreplacewidget.cpp \
|
||||
common/lc_glextensions.cpp \
|
||||
common/lc_http.cpp \
|
||||
common/lc_instructions.cpp \
|
||||
common/lc_instructionsdialog.cpp \
|
||||
common/lc_library.cpp \
|
||||
common/lc_lxf.cpp \
|
||||
common/lc_mainwindow.cpp \
|
||||
common/lc_mesh.cpp \
|
||||
common/lc_meshloader.cpp \
|
||||
common/lc_minifigdialog.cpp \
|
||||
common/lc_model.cpp \
|
||||
common/lc_pagesetupdialog.cpp \
|
||||
common/lc_partselectionwidget.cpp \
|
||||
common/lc_previewwidget.cpp \
|
||||
common/lc_profile.cpp \
|
||||
common/lc_scene.cpp \
|
||||
common/lc_shortcuts.cpp \
|
||||
common/lc_stringcache.cpp \
|
||||
common/lc_synth.cpp \
|
||||
common/lc_texture.cpp \
|
||||
common/lc_timelinewidget.cpp \
|
||||
common/lc_view.cpp \
|
||||
common/lc_viewsphere.cpp \
|
||||
common/lc_viewwidget.cpp \
|
||||
common/lc_zipfile.cpp \
|
||||
common/image.cpp \
|
||||
common/group.cpp \
|
||||
common/camera.cpp \
|
||||
qt/system.cpp \
|
||||
qt/qtmain.cpp \
|
||||
qt/lc_qarraydialog.cpp \
|
||||
qt/lc_qgroupdialog.cpp \
|
||||
qt/lc_qaboutdialog.cpp \
|
||||
qt/lc_qeditgroupsdialog.cpp \
|
||||
qt/lc_qselectdialog.cpp \
|
||||
qt/lc_qpropertiesdialog.cpp \
|
||||
qt/lc_qhtmldialog.cpp \
|
||||
qt/lc_qpreferencesdialog.cpp \
|
||||
qt/lc_qcategorydialog.cpp \
|
||||
qt/lc_qimagedialog.cpp \
|
||||
qt/lc_qupdatedialog.cpp \
|
||||
qt/lc_qutils.cpp \
|
||||
qt/lc_qpropertiestree.cpp \
|
||||
qt/lc_qcolorpicker.cpp \
|
||||
qt/lc_qcolorlist.cpp \
|
||||
qt/lc_qmodellistdialog.cpp \
|
||||
qt/lc_renderdialog.cpp \
|
||||
qt/lc_setsdatabasedialog.cpp \
|
||||
common/lc_partpalettedialog.cpp
|
||||
HEADERS += \
|
||||
common/view.h \
|
||||
common/texfont.h \
|
||||
common/project.h \
|
||||
common/pieceinf.h \
|
||||
common/piece.h \
|
||||
common/object.h \
|
||||
common/minifig.h \
|
||||
common/light.h \
|
||||
common/lc_application.h \
|
||||
common/lc_array.h \
|
||||
common/lc_basewindow.h \
|
||||
common/lc_category.h \
|
||||
common/lc_colors.h \
|
||||
common/lc_commands.h \
|
||||
common/lc_context.h \
|
||||
common/lc_file.h \
|
||||
common/lc_glext.h \
|
||||
common/lc_glextensions.h \
|
||||
common/lc_global.h \
|
||||
common/lc_glwidget.h \
|
||||
common/lc_http.h \
|
||||
common/lc_library.h \
|
||||
common/lc_lxf.h \
|
||||
common/lc_mainwindow.h \
|
||||
common/lc_math.h \
|
||||
common/lc_mesh.h \
|
||||
common/lc_meshloader.h \
|
||||
common/lc_model.h \
|
||||
common/lc_profile.h \
|
||||
common/lc_scene.h \
|
||||
common/lc_selectbycolordialog.h \
|
||||
common/lc_shortcuts.h \
|
||||
common/lc_stringcache.h \
|
||||
common/lc_synth.h \
|
||||
common/lc_texture.h \
|
||||
common/lc_viewsphere.h \
|
||||
common/lc_zipfile.h \
|
||||
common/image.h \
|
||||
common/group.h \
|
||||
common/camera.h \
|
||||
qt/lc_qarraydialog.h \
|
||||
qt/lc_qgroupdialog.h \
|
||||
qt/lc_qaboutdialog.h \
|
||||
qt/lc_qeditgroupsdialog.h \
|
||||
qt/lc_qselectdialog.h \
|
||||
qt/lc_qpropertiesdialog.h \
|
||||
qt/lc_qhtmldialog.h \
|
||||
qt/lc_qminifigdialog.h \
|
||||
qt/lc_qpreferencesdialog.h \
|
||||
qt/lc_qcategorydialog.h \
|
||||
qt/lc_qimagedialog.h \
|
||||
qt/lc_qupdatedialog.h \
|
||||
qt/lc_qutils.h \
|
||||
qt/lc_qpropertiestree.h \
|
||||
qt/lc_qcolorpicker.h \
|
||||
qt/lc_qglwidget.h \
|
||||
qt/lc_qcolorlist.h \
|
||||
qt/lc_qfinddialog.h \
|
||||
qt/lc_qmodellistdialog.h \
|
||||
common/lc_partselectionwidget.h \
|
||||
common/lc_timelinewidget.h \
|
||||
qt/lc_renderdialog.h \
|
||||
qt/lc_setsdatabasedialog.h \
|
||||
common/lc_partpalettedialog.h
|
||||
FORMS += \
|
||||
qt/lc_qarraydialog.ui \
|
||||
qt/lc_qgroupdialog.ui \
|
||||
qt/lc_qaboutdialog.ui \
|
||||
qt/lc_qeditgroupsdialog.ui \
|
||||
qt/lc_qselectdialog.ui \
|
||||
qt/lc_qpropertiesdialog.ui \
|
||||
qt/lc_qhtmldialog.ui \
|
||||
qt/lc_qminifigdialog.ui \
|
||||
qt/lc_qpreferencesdialog.ui \
|
||||
qt/lc_qcategorydialog.ui \
|
||||
qt/lc_qimagedialog.ui \
|
||||
qt/lc_qupdatedialog.ui \
|
||||
qt/lc_qfinddialog.ui \
|
||||
qt/lc_qmodellistdialog.ui \
|
||||
qt/lc_renderdialog.ui \
|
||||
qt/lc_setsdatabasedialog.ui \
|
||||
common/lc_partpalettedialog.ui
|
||||
OTHER_FILES +=
|
||||
RESOURCES += leocad.qrc
|
||||
common/texfont.h \
|
||||
common/project.h \
|
||||
common/pieceinf.h \
|
||||
common/piece.h \
|
||||
common/object.h \
|
||||
common/minifig.h \
|
||||
common/light.h \
|
||||
common/lc_application.h \
|
||||
common/lc_array.h \
|
||||
common/lc_category.h \
|
||||
common/lc_collapsiblewidget.h \
|
||||
common/lc_colors.h \
|
||||
common/lc_commands.h \
|
||||
common/lc_context.h \
|
||||
common/lc_edgecolordialog.h \
|
||||
common/lc_file.h \
|
||||
common/lc_findreplacewidget.h \
|
||||
common/lc_glextensions.h \
|
||||
common/lc_global.h \
|
||||
common/lc_http.h \
|
||||
common/lc_instructions.h \
|
||||
common/lc_instructionsdialog.h \
|
||||
common/lc_library.h \
|
||||
common/lc_lxf.h \
|
||||
common/lc_mainwindow.h \
|
||||
common/lc_math.h \
|
||||
common/lc_mesh.h \
|
||||
common/lc_meshloader.h \
|
||||
common/lc_minifigdialog.h \
|
||||
common/lc_model.h \
|
||||
common/lc_pagesetupdialog.h \
|
||||
common/lc_previewwidget.h \
|
||||
common/lc_profile.h \
|
||||
common/lc_scene.h \
|
||||
common/lc_shortcuts.h \
|
||||
common/lc_stringcache.h \
|
||||
common/lc_synth.h \
|
||||
common/lc_texture.h \
|
||||
common/lc_view.h \
|
||||
common/lc_viewsphere.h \
|
||||
common/lc_viewwidget.h \
|
||||
common/lc_zipfile.h \
|
||||
common/lc_partselectionwidget.h \
|
||||
common/lc_timelinewidget.h \
|
||||
common/image.h \
|
||||
common/group.h \
|
||||
common/camera.h \
|
||||
qt/lc_qarraydialog.h \
|
||||
qt/lc_qgroupdialog.h \
|
||||
qt/lc_qaboutdialog.h \
|
||||
qt/lc_qeditgroupsdialog.h \
|
||||
qt/lc_qselectdialog.h \
|
||||
qt/lc_qpropertiesdialog.h \
|
||||
qt/lc_qhtmldialog.h \
|
||||
qt/lc_qpreferencesdialog.h \
|
||||
qt/lc_qcategorydialog.h \
|
||||
qt/lc_qimagedialog.h \
|
||||
qt/lc_qupdatedialog.h \
|
||||
qt/lc_qutils.h \
|
||||
qt/lc_qpropertiestree.h \
|
||||
qt/lc_qcolorpicker.h \
|
||||
qt/lc_qcolorlist.h \
|
||||
qt/lc_qmodellistdialog.h \
|
||||
qt/lc_renderdialog.h \
|
||||
qt/lc_setsdatabasedialog.h \
|
||||
common/lc_partpalettedialog.h
|
||||
FORMS += \
|
||||
qt/lc_qarraydialog.ui \
|
||||
qt/lc_qgroupdialog.ui \
|
||||
qt/lc_qaboutdialog.ui \
|
||||
qt/lc_qeditgroupsdialog.ui \
|
||||
qt/lc_qselectdialog.ui \
|
||||
qt/lc_qpropertiesdialog.ui \
|
||||
qt/lc_qhtmldialog.ui \
|
||||
qt/lc_qpreferencesdialog.ui \
|
||||
qt/lc_qcategorydialog.ui \
|
||||
qt/lc_qimagedialog.ui \
|
||||
qt/lc_qupdatedialog.ui \
|
||||
qt/lc_qmodellistdialog.ui \
|
||||
qt/lc_renderdialog.ui \
|
||||
qt/lc_setsdatabasedialog.ui \
|
||||
common/lc_minifigdialog.ui \
|
||||
common/lc_pagesetupdialog.ui \
|
||||
common/lc_partpalettedialog.ui
|
||||
OTHER_FILES +=
|
||||
RESOURCES += leocad.qrc resources/stylesheet/stylesheet.qrc
|
||||
|
||||
!win32 {
|
||||
TRANSLATIONS = resources/leocad_pt.ts resources/leocad_fr.ts resources/leocad_de.ts resources/leocad_uk.ts resources/leocad_cs.ts resources/leocad_es.ts
|
||||
TRANSLATIONS = resources/leocad_pt.ts resources/leocad_fr.ts resources/leocad_de.ts resources/leocad_uk.ts resources/leocad_cs.ts resources/leocad_es.ts
|
||||
}
|
||||
|
|
16
leocad.qrc
16
leocad.qrc
|
@ -30,6 +30,8 @@
|
|||
<file>resources/action_next.png</file>
|
||||
<file>resources/action_paint.png</file>
|
||||
<file>resources/action_pan.png</file>
|
||||
<file>resources/action_preview_locked.png</file>
|
||||
<file>resources/action_preview_unlocked.png</file>
|
||||
<file>resources/action_previous.png</file>
|
||||
<file>resources/action_roll.png</file>
|
||||
<file>resources/action_rotate.png</file>
|
||||
|
@ -61,6 +63,11 @@
|
|||
<file>resources/edit_copy.png</file>
|
||||
<file>resources/edit_cut.png</file>
|
||||
<file>resources/edit_find.png</file>
|
||||
<file>resources/edit_find_next.png</file>
|
||||
<file>resources/edit_find_previous.png</file>
|
||||
<file>resources/edit_find_all.png</file>
|
||||
<file>resources/edit_replace_next.png</file>
|
||||
<file>resources/edit_replace_all.png</file>
|
||||
<file>resources/edit_paste.png</file>
|
||||
<file>resources/edit_redo.png</file>
|
||||
<file>resources/edit_snap_angle.png</file>
|
||||
|
@ -76,7 +83,7 @@
|
|||
<file>resources/time_next.png</file>
|
||||
<file>resources/time_previous.png</file>
|
||||
<file>resources/time_stop.png</file>
|
||||
<file>resources/leocad.png</file>
|
||||
<file alias="resources/leocad.png">tools/icon/64x64/apps/leocad.png</file>
|
||||
<file>resources/help_homepage.png</file>
|
||||
<file>resources/view_zoomextents.png</file>
|
||||
<file>resources/view_split_horizontal.png</file>
|
||||
|
@ -94,6 +101,13 @@
|
|||
<file>resources/parts_cancel.png</file>
|
||||
<file>resources/archive.png</file>
|
||||
<file>resources/library.zip</file>
|
||||
<file>resources/studlogo1.zip</file>
|
||||
<file>resources/studlogo2.zip</file>
|
||||
<file>resources/studlogo3.zip</file>
|
||||
<file>resources/studlogo4.zip</file>
|
||||
<file>resources/studlogo5.zip</file>
|
||||
<file>resources/studslegostyle1.zip</file>
|
||||
<file>resources/studslegostyle2.zip</file>
|
||||
<file>resources/ldconfig.ldr</file>
|
||||
<file>resources/minifig.ini</file>
|
||||
<file>resources/ldraw.xml</file>
|
||||
|
|
|
@ -63,7 +63,7 @@
|
|||
<key>CFBundleSignature</key>
|
||||
<string>LCAD</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>19.07.1</string>
|
||||
<string>21.01.0</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>LeoCAD</string>
|
||||
<key>CFBundleName</key>
|
||||
|
|
|
@ -2,8 +2,9 @@
|
|||
#include "lc_qaboutdialog.h"
|
||||
#include "ui_lc_qaboutdialog.h"
|
||||
#include "lc_mainwindow.h"
|
||||
#include "view.h"
|
||||
#include "lc_view.h"
|
||||
#include "lc_glextensions.h"
|
||||
#include "lc_viewwidget.h"
|
||||
|
||||
lcQAboutDialog::lcQAboutDialog(QWidget *parent) :
|
||||
QDialog(parent),
|
||||
|
@ -17,25 +18,26 @@ lcQAboutDialog::lcQAboutDialog(QWidget *parent) :
|
|||
ui->version->setText(tr("LeoCAD Version %1").arg(QString::fromLatin1(LC_VERSION_TEXT)));
|
||||
#endif
|
||||
|
||||
QGLWidget* Widget = (QGLWidget*)gMainWindow->GetActiveView()->mWidget;
|
||||
QGLFormat Format = Widget->context()->format();
|
||||
lcViewWidget* Widget = gMainWindow->GetActiveView()->GetWidget();
|
||||
QSurfaceFormat Format = Widget->context()->format();
|
||||
|
||||
int ColorDepth = Format.redBufferSize() + Format.greenBufferSize() + Format.blueBufferSize() + Format.alphaBufferSize();
|
||||
|
||||
QString QtVersionFormat = tr("Qt Version %1 (compiled with %2)\n\n");
|
||||
QString QtVersion = QtVersionFormat.arg(qVersion(), QT_VERSION_STR);
|
||||
QString VersionFormat = tr("OpenGL Version %1 (GLSL %2)\n%3 - %4\n\n");
|
||||
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)));
|
||||
QString BuffersFormat = tr("Color Buffer: %1 bits %2 %3\nDepth Buffer: %4 bits\nStencil Buffer: %5 bits\n\n");
|
||||
QString Buffers = BuffersFormat.arg(QString::number(ColorDepth), Format.rgba() ? "RGBA" : tr("indexed"), Format.doubleBuffer() ? tr("double buffered") : QString(), QString::number(Format.depthBufferSize()), QString::number(Format.stencilBufferSize()));
|
||||
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 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()));
|
||||
|
||||
QString ExtensionsFormat = tr("GL_ARB_vertex_buffer_object extension: %1\nGL_ARB_framebuffer_object extension: %2\nGL_EXT_framebuffer_object extension: %3\nGL_EXT_blend_func_separate: %4\nGL_EXT_texture_filter_anisotropic extension: %5\n");
|
||||
QString VertexBufferObject = gSupportsVertexBufferObject ? tr("Supported") : tr("Not supported");
|
||||
QString FramebufferObjectARB = gSupportsFramebufferObjectARB ? tr("Supported") : tr("Not supported");
|
||||
QString FramebufferObjectEXT = gSupportsFramebufferObjectEXT ? tr("Supported") : tr("Not supported");
|
||||
QString BlendFuncSeparateEXT = gSupportsBlendFuncSeparate ? tr("Supported") : tr("Not supported");
|
||||
QString Anisotropic = gSupportsAnisotropic ? tr("Supported (max %1)").arg(gMaxAnisotropy) : tr("Not supported");
|
||||
QString Extensions = ExtensionsFormat.arg(VertexBufferObject, FramebufferObjectARB, FramebufferObjectEXT, BlendFuncSeparateEXT, Anisotropic);
|
||||
const QString ExtensionsFormat = tr("Buffers: %1\nShaders: %2\nFramebuffers: %3\nBlendFuncSeparate: %4\nAnisotropic: %5\n");
|
||||
const QString VertexBuffers = gSupportsVertexBufferObject ? tr("Supported") : tr("Not supported");
|
||||
const QString Shaders = gSupportsShaderObjects ? tr("Supported") : tr("Not supported");
|
||||
const QString Framebuffers = gSupportsFramebufferObject ? tr("Supported") : tr("Not supported");
|
||||
const QString BlendFuncSeparate = gSupportsBlendFuncSeparate ? tr("Supported") : tr("Not supported");
|
||||
const QString Anisotropic = gSupportsAnisotropic ? tr("Supported (max %1)").arg(gMaxAnisotropy) : tr("Not supported");
|
||||
|
||||
const QString Extensions = ExtensionsFormat.arg(VertexBuffers, Shaders, Framebuffers, BlendFuncSeparate, Anisotropic);
|
||||
|
||||
ui->info->setText(QtVersion + Version + Buffers + Extensions);
|
||||
}
|
||||
|
|
|
@ -1,54 +1,204 @@
|
|||
#include <QtGui>
|
||||
#include "lc_global.h"
|
||||
#include "lc_qcolorlist.h"
|
||||
#include "lc_application.h"
|
||||
#include "lc_library.h"
|
||||
#include "lc_colors.h"
|
||||
|
||||
lcQColorList::lcQColorList(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
void lcDrawNoColorRect(QPainter& Painter, const QRect& Rect)
|
||||
{
|
||||
mCellRects = new QRect[gNumUserColors];
|
||||
mCellColors = new int[gNumUserColors];
|
||||
mNumCells = 0;
|
||||
Painter.setBrush(Qt::black);
|
||||
Painter.drawRect(Rect);
|
||||
|
||||
mCurCell = 0;
|
||||
const int SquareSize = 3;
|
||||
int Column = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
int x = Rect.left() + 1 + Column * SquareSize;
|
||||
|
||||
if (x >= Rect.right())
|
||||
break;
|
||||
|
||||
int Row = Column & 1;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
int y = Rect.top() + 1 + Row * SquareSize;
|
||||
|
||||
if (y >= Rect.bottom())
|
||||
break;
|
||||
|
||||
QRect GridRect(x, y, SquareSize, SquareSize);
|
||||
|
||||
if (GridRect.right() > Rect.right())
|
||||
GridRect.setRight(Rect.right());
|
||||
|
||||
if (GridRect.bottom() > Rect.bottom())
|
||||
GridRect.setBottom(Rect.bottom());
|
||||
|
||||
Painter.fillRect(GridRect, Qt::white);
|
||||
|
||||
Row += 2;
|
||||
}
|
||||
|
||||
Column++;
|
||||
}
|
||||
}
|
||||
|
||||
lcQColorList::lcQColorList(QWidget* Parent, bool AllowNoColor)
|
||||
: QWidget(Parent), mAllowNoColor(AllowNoColor)
|
||||
{
|
||||
setFocusPolicy(Qt::StrongFocus);
|
||||
|
||||
UpdateCells();
|
||||
|
||||
connect(lcGetPiecesLibrary(), &lcPiecesLibrary::ColorsLoaded, this, &lcQColorList::ColorsLoaded);
|
||||
}
|
||||
|
||||
void lcQColorList::UpdateCells()
|
||||
{
|
||||
mCells.clear();
|
||||
mGroups.clear();
|
||||
|
||||
for (int GroupIdx = 0; GroupIdx < LC_NUM_COLORGROUPS; GroupIdx++)
|
||||
{
|
||||
lcColorGroup* Group = &gColorGroups[GroupIdx];
|
||||
lcColorListGroup ListGroup;
|
||||
|
||||
for (int ColorIndex : Group->Colors)
|
||||
{
|
||||
mCells.emplace_back(lcColorListCell{ QRect(), ColorIndex });
|
||||
ListGroup.Name = Group->Name;
|
||||
ListGroup.Cells.emplace_back(mCells.size());
|
||||
}
|
||||
|
||||
mGroups.emplace_back(std::move(ListGroup));
|
||||
}
|
||||
|
||||
if (mAllowNoColor)
|
||||
{
|
||||
mCells.emplace_back(lcColorListCell{ QRect(), lcGetColorIndex(LC_COLOR_NOCOLOR) });
|
||||
mGroups[LC_COLORGROUP_SPECIAL].Cells.emplace_back(mCells.size());
|
||||
}
|
||||
|
||||
mColumns = 14;
|
||||
mRows = 0;
|
||||
|
||||
for (int GroupIdx = 0; GroupIdx < LC_NUM_COLORGROUPS; GroupIdx++)
|
||||
{
|
||||
lcColorGroup* Group = &gColorGroups[GroupIdx];
|
||||
|
||||
for (int Color: Group->Colors)
|
||||
mCellColors[mNumCells++] = Color;
|
||||
|
||||
mRows += ((int)Group->Colors.size() + mColumns - 1) / mColumns;
|
||||
}
|
||||
|
||||
mWidth = 0;
|
||||
mHeight = 0;
|
||||
for (const lcColorListGroup& Group : mGroups)
|
||||
mRows += ((int)Group.Cells.size() + mColumns - 1) / mColumns;
|
||||
|
||||
QFontMetrics Metrics(font());
|
||||
int TextHeight = 0;
|
||||
|
||||
for (int GroupIdx = 0; GroupIdx < LC_NUM_COLORGROUPS; GroupIdx++)
|
||||
for (lcColorListGroup& Group : mGroups)
|
||||
{
|
||||
lcColorGroup* Group = &gColorGroups[GroupIdx];
|
||||
Group.Rect = Metrics.boundingRect(rect(), Qt::TextSingleLine | Qt::AlignCenter, Group.Name);
|
||||
|
||||
mGroupRects[GroupIdx] = Metrics.boundingRect(rect(), Qt::TextSingleLine | Qt::AlignCenter, Group->Name);
|
||||
|
||||
TextHeight += mGroupRects[GroupIdx].height();
|
||||
TextHeight += Group.Rect.height();
|
||||
}
|
||||
|
||||
mPreferredHeight = TextHeight + 10 * mRows;
|
||||
|
||||
setFocusPolicy(Qt::StrongFocus);
|
||||
setMinimumHeight(TextHeight + 5 * mRows);
|
||||
}
|
||||
|
||||
lcQColorList::~lcQColorList()
|
||||
void lcQColorList::UpdateRects()
|
||||
{
|
||||
delete[] mCellRects;
|
||||
delete[] mCellColors;
|
||||
QFontMetrics Metrics(font());
|
||||
int TextHeight = 0;
|
||||
|
||||
for (lcColorListGroup& Group : mGroups)
|
||||
{
|
||||
Group.Rect = Metrics.boundingRect(rect(), Qt::TextSingleLine | Qt::AlignCenter, Group.Name);
|
||||
|
||||
TextHeight += Group.Rect.height();
|
||||
}
|
||||
|
||||
mPreferredHeight = TextHeight + 10 * mRows;
|
||||
|
||||
float CellWidth = (float)(width() + 1) / (float)mColumns;
|
||||
float CellHeight = (float)(height() - TextHeight) / (float)mRows;
|
||||
|
||||
while (CellWidth / CellHeight > 1.5f)
|
||||
{
|
||||
mColumns++;
|
||||
mRows = 0;
|
||||
|
||||
for (const lcColorListGroup& Group : mGroups)
|
||||
mRows += ((int)Group.Cells.size() + mColumns - 1) / mColumns;
|
||||
|
||||
CellWidth = (float)(width() + 1) / (float)mColumns;
|
||||
CellHeight = (float)(height() - TextHeight) / (float)mRows;
|
||||
|
||||
if (mRows <= LC_NUM_COLORGROUPS)
|
||||
break;
|
||||
}
|
||||
|
||||
while (CellHeight / CellWidth > 1.5f)
|
||||
{
|
||||
mColumns--;
|
||||
mRows = 0;
|
||||
|
||||
for (const lcColorListGroup& Group : mGroups)
|
||||
mRows += ((int)Group.Cells.size() + mColumns - 1) / mColumns;
|
||||
|
||||
CellWidth = (float)(width() + 1) / (float)mColumns;
|
||||
CellHeight = (float)(height() - TextHeight) / (float)mRows;
|
||||
|
||||
if (mColumns <= 5)
|
||||
break;
|
||||
}
|
||||
|
||||
int CurCell = 0;
|
||||
float GroupY = 0.0f;
|
||||
int TotalRows = 1;
|
||||
|
||||
for (lcColorListGroup& Group : mGroups)
|
||||
{
|
||||
int CurColumn = 0;
|
||||
int NumRows = 0;
|
||||
|
||||
Group.Rect = QRect(0, (int)GroupY, width(), Group.Rect.height());
|
||||
GroupY += Group.Rect.height();
|
||||
|
||||
for (size_t ColorIdx = 0; ColorIdx < Group.Cells.size(); ColorIdx++)
|
||||
{
|
||||
const int Left = CellWidth * CurColumn - 1;
|
||||
const int Right = (CurColumn + 1) * CellWidth - 1;
|
||||
const int Top = GroupY + CellHeight * NumRows;
|
||||
const int Bottom = (TotalRows != mRows) ? GroupY + CellHeight * (NumRows + 1) : height() - 1;
|
||||
|
||||
mCells[CurCell].Rect = QRect(Left, Top, Right - Left, Bottom - Top);
|
||||
|
||||
CurColumn++;
|
||||
if (CurColumn == mColumns)
|
||||
{
|
||||
CurColumn = 0;
|
||||
NumRows++;
|
||||
TotalRows++;
|
||||
}
|
||||
|
||||
CurCell++;
|
||||
}
|
||||
|
||||
if (CurColumn != 0)
|
||||
{
|
||||
NumRows++;
|
||||
TotalRows++;
|
||||
}
|
||||
|
||||
GroupY += NumRows * CellHeight;
|
||||
}
|
||||
}
|
||||
|
||||
void lcQColorList::ColorsLoaded()
|
||||
{
|
||||
UpdateCells();
|
||||
UpdateRects();
|
||||
|
||||
setCurrentColor(lcGetColorIndex(mColorCode));
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
QSize lcQColorList::sizeHint() const
|
||||
|
@ -56,15 +206,15 @@ QSize lcQColorList::sizeHint() const
|
|||
return QSize(200, mPreferredHeight);
|
||||
}
|
||||
|
||||
void lcQColorList::setCurrentColor(int colorIndex)
|
||||
void lcQColorList::setCurrentColor(int ColorIndex)
|
||||
{
|
||||
for (int CellIdx = 0; CellIdx < mNumCells; CellIdx++)
|
||||
for (size_t CellIndex = 0; CellIndex < mCells.size(); CellIndex++)
|
||||
{
|
||||
if (mCellColors[CellIdx] != colorIndex)
|
||||
continue;
|
||||
|
||||
SelectCell(CellIdx);
|
||||
break;
|
||||
if (mCells[CellIndex].ColorIndex == ColorIndex)
|
||||
{
|
||||
SelectCell(CellIndex);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -74,19 +224,22 @@ bool lcQColorList::event(QEvent *event)
|
|||
{
|
||||
QHelpEvent *helpEvent = static_cast<QHelpEvent *>(event);
|
||||
|
||||
for (int CellIdx = 0; CellIdx < mNumCells; CellIdx++)
|
||||
for (size_t CellIndex = 0; CellIndex < mCells.size(); CellIndex++)
|
||||
{
|
||||
if (!mCellRects[CellIdx].contains(helpEvent->pos()))
|
||||
if (!mCells[CellIndex].Rect.contains(helpEvent->pos()))
|
||||
continue;
|
||||
|
||||
lcColor* color = &gColorList[mCellColors[CellIdx]];
|
||||
lcColor* color = &gColorList[mCells[CellIndex].ColorIndex];
|
||||
QColor rgb(color->Value[0] * 255, color->Value[1] * 255, color->Value[2] * 255);
|
||||
|
||||
QImage image(16, 16, QImage::Format_RGB888);
|
||||
image.fill(rgb);
|
||||
QPainter painter(&image);
|
||||
painter.setPen(Qt::darkGray);
|
||||
painter.drawRect(0, 0, image.width() - 1, image.height() - 1);
|
||||
if (color->Code != LC_COLOR_NOCOLOR)
|
||||
painter.drawRect(0, 0, image.width() - 1, image.height() - 1);
|
||||
else
|
||||
lcDrawNoColorRect(painter, QRect(0, 0, image.width() - 1, image.height() - 1));
|
||||
painter.end();
|
||||
|
||||
QByteArray ba;
|
||||
|
@ -95,9 +248,18 @@ bool lcQColorList::event(QEvent *event)
|
|||
image.save(&buffer, "PNG");
|
||||
buffer.close();
|
||||
|
||||
int colorIndex = mCellColors[CellIdx];
|
||||
const char* format = "<table><tr><td style=\"vertical-align:middle\"><img src=\"data:image/png;base64,%1\"/></td><td>%2 (%3)</td></tr></table>";
|
||||
QString text = QString(format).arg(QString(buffer.data().toBase64()), gColorList[colorIndex].Name, QString::number(gColorList[colorIndex].Code));
|
||||
int colorIndex = mCells[CellIndex].ColorIndex;
|
||||
QString text;
|
||||
if (color->Code != LC_COLOR_NOCOLOR)
|
||||
{
|
||||
const char* format = "<table><tr><td style=\"vertical-align:middle\"><img src=\"data:image/png;base64,%1\"/></td><td>%2 (%3)</td></tr></table>";
|
||||
text = QString(format).arg(QString(buffer.data().toBase64()), gColorList[colorIndex].Name, QString::number(gColorList[colorIndex].Code));
|
||||
}
|
||||
else
|
||||
{
|
||||
const char* format = "<table><tr><td style=\"vertical-align:middle\"><img src=\"data:image/png;base64,%1\"/></td><td>%2</td></tr></table>";
|
||||
text = QString(format).arg(QString(buffer.data().toBase64()), gColorList[colorIndex].Name);
|
||||
}
|
||||
|
||||
QToolTip::showText(helpEvent->globalPos(), text);
|
||||
return true;
|
||||
|
@ -132,13 +294,13 @@ bool lcQColorList::event(QEvent *event)
|
|||
|
||||
void lcQColorList::mousePressEvent(QMouseEvent* MouseEvent)
|
||||
{
|
||||
for (int CellIdx = 0; CellIdx < mNumCells; CellIdx++)
|
||||
for (size_t CellIndex = 0; CellIndex < mCells.size(); CellIndex++)
|
||||
{
|
||||
if (!mCellRects[CellIdx].contains(MouseEvent->pos()))
|
||||
if (!mCells[CellIndex].Rect.contains(MouseEvent->pos()))
|
||||
continue;
|
||||
|
||||
SelectCell(CellIdx);
|
||||
emit colorSelected(mCellColors[CellIdx]);
|
||||
SelectCell(CellIndex);
|
||||
emit colorSelected(mCells[CellIndex].ColorIndex);
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -155,7 +317,7 @@ void lcQColorList::mouseMoveEvent(QMouseEvent* MouseEvent)
|
|||
return;
|
||||
|
||||
QMimeData* MimeData = new QMimeData;
|
||||
MimeData->setData("application/vnd.leocad-color", QString::number(mCellColors[mCurCell]).toLatin1());
|
||||
MimeData->setData("application/vnd.leocad-color", QString::number(mCells[mCurrentCell].ColorIndex).toLatin1());
|
||||
|
||||
QDrag* Drag = new QDrag(this);
|
||||
Drag->setMimeData(MimeData);
|
||||
|
@ -165,232 +327,142 @@ void lcQColorList::mouseMoveEvent(QMouseEvent* MouseEvent)
|
|||
|
||||
void lcQColorList::keyPressEvent(QKeyEvent *event)
|
||||
{
|
||||
int NewCell = mCurCell;
|
||||
size_t NewCell = mCurrentCell;
|
||||
|
||||
if (event->key() == Qt::Key_Left)
|
||||
{
|
||||
if (mCurCell > 0)
|
||||
NewCell = mCurCell - 1;
|
||||
if (mCurrentCell > 0)
|
||||
NewCell = mCurrentCell - 1;
|
||||
}
|
||||
else if (event->key() == Qt::Key_Right)
|
||||
{
|
||||
if (mCurCell < mNumCells - 1)
|
||||
NewCell = mCurCell + 1;
|
||||
if (mCurrentCell < mCells.size() - 1)
|
||||
NewCell = mCurrentCell + 1;
|
||||
}
|
||||
else if (event->key() == Qt::Key_Up || event->key() == Qt::Key_Down)
|
||||
{
|
||||
if (mCurCell < 0 || mCurCell >= mNumCells)
|
||||
mCurCell = 0;
|
||||
if (mCurrentCell >= mCells.size())
|
||||
mCurrentCell = 0;
|
||||
|
||||
int CurGroup = 0;
|
||||
int NumCells = 0;
|
||||
size_t CurGroup = 0;
|
||||
size_t NumCells = 0;
|
||||
|
||||
for (CurGroup = 0; CurGroup < LC_NUM_COLORGROUPS; CurGroup++)
|
||||
for (CurGroup = 0; CurGroup < mGroups.size(); CurGroup++)
|
||||
{
|
||||
int NumColors = (int)gColorGroups[CurGroup].Colors.size();
|
||||
int NumColors = (int)mGroups[CurGroup].Cells.size();
|
||||
|
||||
if (mCurCell < NumCells + NumColors)
|
||||
if (mCurrentCell < NumCells + NumColors)
|
||||
break;
|
||||
|
||||
NumCells += NumColors;
|
||||
}
|
||||
|
||||
int Row = (mCurCell - NumCells) / mColumns;
|
||||
int Column = (mCurCell - NumCells) % mColumns;
|
||||
size_t Row = (mCurrentCell - NumCells) / mColumns;
|
||||
size_t Column = (mCurrentCell - NumCells) % mColumns;
|
||||
|
||||
if (event->key() == Qt::Key_Up)
|
||||
{
|
||||
if (Row > 0)
|
||||
NewCell = mCurCell - mColumns;
|
||||
NewCell = mCurrentCell - mColumns;
|
||||
else if (CurGroup > 0)
|
||||
{
|
||||
size_t NumColors = gColorGroups[CurGroup - 1].Colors.size();
|
||||
int NumColumns = NumColors % mColumns;
|
||||
size_t NumColors = mGroups[CurGroup - 1].Cells.size();
|
||||
size_t NumColumns = NumColors % mColumns;
|
||||
|
||||
if (NumColumns <= Column + 1)
|
||||
NewCell = mCurCell - NumColumns - mColumns;
|
||||
if (NumColumns < Column + 1)
|
||||
NewCell = mCurrentCell - NumColumns - mColumns;
|
||||
else
|
||||
NewCell = mCurCell - NumColumns;
|
||||
NewCell = mCurrentCell - NumColumns;
|
||||
}
|
||||
}
|
||||
else if (event->key() == Qt::Key_Down)
|
||||
{
|
||||
int NumColors = (int)gColorGroups[CurGroup].Colors.size();
|
||||
int NumColors = (int)mGroups[CurGroup].Cells.size();
|
||||
|
||||
if (mCurCell + mColumns < NumCells + NumColors)
|
||||
NewCell = mCurCell + mColumns;
|
||||
if (mCurrentCell + mColumns < NumCells + NumColors)
|
||||
NewCell = mCurrentCell + mColumns;
|
||||
else
|
||||
{
|
||||
int NumColumns = NumColors % mColumns;
|
||||
size_t NumColumns = NumColors % mColumns;
|
||||
|
||||
if (NumColumns > Column)
|
||||
{
|
||||
if (mCurCell + NumColumns < mNumCells)
|
||||
NewCell = mCurCell + NumColumns;
|
||||
if (mCurrentCell + NumColumns < mCells.size())
|
||||
NewCell = mCurrentCell + NumColumns;
|
||||
}
|
||||
else
|
||||
NewCell = mCurCell + mColumns + NumColumns;
|
||||
NewCell = mCurrentCell + mColumns + NumColumns;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter)
|
||||
{
|
||||
emit colorSelected(mCellColors[mCurCell]);
|
||||
emit colorSelected(mCells[mCurrentCell].ColorIndex);
|
||||
}
|
||||
|
||||
if (NewCell != mCurCell)
|
||||
if (NewCell != mCurrentCell)
|
||||
SelectCell(NewCell);
|
||||
else
|
||||
QWidget::keyPressEvent(event);
|
||||
}
|
||||
|
||||
void lcQColorList::resizeEvent(QResizeEvent *event)
|
||||
void lcQColorList::resizeEvent(QResizeEvent* Event)
|
||||
{
|
||||
if (mWidth == width() && mHeight == height())
|
||||
return;
|
||||
|
||||
QFontMetrics Metrics(font());
|
||||
int TextHeight = 0;
|
||||
|
||||
for (int GroupIdx = 0; GroupIdx < LC_NUM_COLORGROUPS; GroupIdx++)
|
||||
{
|
||||
lcColorGroup* Group = &gColorGroups[GroupIdx];
|
||||
|
||||
mGroupRects[GroupIdx] = Metrics.boundingRect(rect(), Qt::TextSingleLine | Qt::AlignCenter, Group->Name);
|
||||
|
||||
TextHeight += mGroupRects[GroupIdx].height();
|
||||
}
|
||||
|
||||
mPreferredHeight = TextHeight + 10 * mRows;
|
||||
|
||||
float CellWidth = (float)(width() + 1) / (float)mColumns;
|
||||
float CellHeight = (float)(height() - TextHeight) / (float)mRows;
|
||||
|
||||
while (CellWidth / CellHeight > 1.5f)
|
||||
{
|
||||
mColumns++;
|
||||
mRows = 0;
|
||||
|
||||
for (int GroupIdx = 0; GroupIdx < LC_NUM_COLORGROUPS; GroupIdx++)
|
||||
{
|
||||
lcColorGroup* Group = &gColorGroups[GroupIdx];
|
||||
mRows += ((int)Group->Colors.size() + mColumns - 1) / mColumns;
|
||||
}
|
||||
|
||||
CellWidth = (float)(width() + 1) / (float)mColumns;
|
||||
CellHeight = (float)(height() - TextHeight) / (float)mRows;
|
||||
|
||||
if (mRows <= LC_NUM_COLORGROUPS)
|
||||
break;
|
||||
}
|
||||
|
||||
while (CellHeight / CellWidth > 1.5f)
|
||||
{
|
||||
mColumns--;
|
||||
mRows = 0;
|
||||
|
||||
for (int GroupIdx = 0; GroupIdx < LC_NUM_COLORGROUPS; GroupIdx++)
|
||||
{
|
||||
lcColorGroup* Group = &gColorGroups[GroupIdx];
|
||||
mRows += ((int)Group->Colors.size() + mColumns - 1) / mColumns;
|
||||
}
|
||||
|
||||
CellWidth = (float)(width() + 1) / (float)mColumns;
|
||||
CellHeight = (float)(height() - TextHeight) / (float)mRows;
|
||||
|
||||
if (mColumns <= 5)
|
||||
break;
|
||||
}
|
||||
|
||||
int CurCell = 0;
|
||||
float GroupY = 0.0f;
|
||||
int TotalRows = 1;
|
||||
|
||||
for (int GroupIdx = 0; GroupIdx < LC_NUM_COLORGROUPS; GroupIdx++)
|
||||
{
|
||||
lcColorGroup* Group = &gColorGroups[GroupIdx];
|
||||
int CurColumn = 0;
|
||||
int NumRows = 0;
|
||||
|
||||
mGroupRects[GroupIdx] = QRect(0, (int)GroupY, width(), mGroupRects[GroupIdx].height());
|
||||
GroupY += mGroupRects[GroupIdx].height();
|
||||
|
||||
for (size_t ColorIdx = 0; ColorIdx < Group->Colors.size(); ColorIdx++)
|
||||
{
|
||||
const int Left = CellWidth * CurColumn - 1;
|
||||
const int Right = (CurColumn + 1) * CellWidth - 1;
|
||||
const int Top = GroupY + CellHeight * NumRows;
|
||||
const int Bottom = (TotalRows != mRows) ? GroupY + CellHeight * (NumRows + 1) : height();
|
||||
|
||||
mCellRects[CurCell] = QRect(Left, Top, Right - Left, Bottom - Top);
|
||||
|
||||
CurColumn++;
|
||||
if (CurColumn == mColumns)
|
||||
{
|
||||
CurColumn = 0;
|
||||
NumRows++;
|
||||
TotalRows++;
|
||||
}
|
||||
|
||||
CurCell++;
|
||||
}
|
||||
|
||||
if (CurColumn != 0)
|
||||
{
|
||||
NumRows++;
|
||||
TotalRows++;
|
||||
}
|
||||
|
||||
GroupY += NumRows * CellHeight;
|
||||
}
|
||||
UpdateRects();
|
||||
|
||||
mWidth = width();
|
||||
mHeight = height();
|
||||
|
||||
QWidget::resizeEvent(event);
|
||||
QWidget::resizeEvent(Event);
|
||||
}
|
||||
|
||||
void lcQColorList::paintEvent(QPaintEvent *event)
|
||||
void lcQColorList::paintEvent(QPaintEvent* Event)
|
||||
{
|
||||
Q_UNUSED(event);
|
||||
Q_UNUSED(Event);
|
||||
|
||||
QPainter painter(this);
|
||||
QPainter Painter(this);
|
||||
|
||||
painter.fillRect(rect(), palette().brush(QPalette::Base));
|
||||
Painter.fillRect(rect(), palette().brush(QPalette::Window));
|
||||
|
||||
painter.setFont(font());
|
||||
painter.setPen(palette().color(QPalette::Text));
|
||||
Painter.setFont(font());
|
||||
Painter.setPen(palette().color(QPalette::Text));
|
||||
|
||||
for (int GroupIdx = 0; GroupIdx < LC_NUM_COLORGROUPS; GroupIdx++)
|
||||
for (const lcColorListGroup& Group : mGroups)
|
||||
Painter.drawText(Group.Rect, Qt::TextSingleLine | Qt::AlignLeft, Group.Name);
|
||||
|
||||
Painter.setPen(palette().color(QPalette::Shadow));
|
||||
|
||||
for (size_t CellIndex = 0; CellIndex < mCells.size(); CellIndex++)
|
||||
{
|
||||
lcColorGroup* Group = &gColorGroups[GroupIdx];
|
||||
const lcColor* Color = &gColorList[mCells[CellIndex].ColorIndex];
|
||||
|
||||
painter.drawText(mGroupRects[GroupIdx], Qt::TextSingleLine | Qt::AlignCenter, Group->Name);
|
||||
const QRect& Rect = mCells[CellIndex].Rect;
|
||||
|
||||
if (Color->Code != LC_COLOR_NOCOLOR)
|
||||
{
|
||||
QColor CellColor(Color->Value[0] * 255, Color->Value[1] * 255, Color->Value[2] * 255);
|
||||
|
||||
Painter.setBrush(CellColor);
|
||||
Painter.drawRect(Rect);
|
||||
}
|
||||
else
|
||||
lcDrawNoColorRect(Painter, Rect);
|
||||
}
|
||||
|
||||
painter.setPen(palette().color(QPalette::Shadow));
|
||||
|
||||
for (int CellIdx = 0; CellIdx < mNumCells; CellIdx++)
|
||||
if (mCurrentCell < mCells.size())
|
||||
{
|
||||
lcColor* Color = &gColorList[mCellColors[CellIdx]];
|
||||
QColor CellColor(Color->Value[0] * 255, Color->Value[1] * 255, Color->Value[2] * 255);
|
||||
|
||||
painter.setBrush(CellColor);
|
||||
painter.drawRect(mCellRects[CellIdx]);
|
||||
}
|
||||
|
||||
if (mCurCell < mNumCells)
|
||||
{
|
||||
lcColor* Color = &gColorList[mCellColors[mCurCell]];
|
||||
const lcColor* Color = &gColorList[mCells[mCurrentCell].ColorIndex];
|
||||
QColor EdgeColor(255 - Color->Value[0] * 255, 255 - Color->Value[1] * 255, 255 - Color->Value[2] * 255);
|
||||
QColor CellColor(Color->Value[0] * 255, Color->Value[1] * 255, Color->Value[2] * 255);
|
||||
|
||||
painter.setPen(EdgeColor);
|
||||
painter.setBrush(CellColor);
|
||||
Painter.setPen(EdgeColor);
|
||||
Painter.setBrush(Qt::NoBrush);
|
||||
|
||||
QRect CellRect = mCellRects[mCurCell];
|
||||
QRect CellRect = mCells[mCurrentCell].Rect;
|
||||
CellRect.adjust(1, 1, -1, -1);
|
||||
painter.drawRect(CellRect);
|
||||
Painter.drawRect(CellRect);
|
||||
|
||||
/*
|
||||
if (GetFocus() == this)
|
||||
|
@ -402,36 +474,17 @@ void lcQColorList::paintEvent(QPaintEvent *event)
|
|||
}
|
||||
}
|
||||
|
||||
void lcQColorList::SelectCell(int CellIdx)
|
||||
void lcQColorList::SelectCell(size_t CellIndex)
|
||||
{
|
||||
if (CellIdx < 0 || CellIdx >= mNumCells)
|
||||
if (CellIndex >= mCells.size())
|
||||
return;
|
||||
|
||||
if (CellIdx == mCurCell)
|
||||
if (CellIndex == mCurrentCell)
|
||||
return;
|
||||
|
||||
update(mCellRects[mCurCell]);
|
||||
update(mCellRects[CellIdx]);
|
||||
mCurCell = CellIdx;
|
||||
mCurrentCell = CellIndex;
|
||||
mColorCode = lcGetColorCode(mCells[CellIndex].ColorIndex);
|
||||
|
||||
emit colorChanged(mCellColors[mCurCell]);
|
||||
emit colorChanged(mCells[mCurrentCell].ColorIndex);
|
||||
update();
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
*/
|
||||
void ColorPickerButton::focusInEvent(QFocusEvent *e)
|
||||
{
|
||||
setFrameShadow(Raised);
|
||||
update();
|
||||
QFrame::focusOutEvent(e);
|
||||
}
|
||||
|
||||
void ColorPickerButton::focusOutEvent(QFocusEvent *e)
|
||||
{
|
||||
setFrameShadow(Raised);
|
||||
update();
|
||||
QFrame::focusOutEvent(e);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,15 +1,27 @@
|
|||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
#include "lc_colors.h"
|
||||
struct lcColorListCell
|
||||
{
|
||||
QRect Rect;
|
||||
int ColorIndex;
|
||||
};
|
||||
|
||||
struct lcColorListGroup
|
||||
{
|
||||
QRect Rect;
|
||||
QString Name;
|
||||
std::vector<size_t> Cells;
|
||||
};
|
||||
|
||||
void lcDrawNoColorRect(QPainter& Painter, const QRect& Rect);
|
||||
|
||||
class lcQColorList : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
lcQColorList(QWidget *parent = 0);
|
||||
~lcQColorList();
|
||||
lcQColorList(QWidget* Parent = nullptr, bool AllowNoColor = false);
|
||||
~lcQColorList() = default;
|
||||
|
||||
QSize sizeHint() const override;
|
||||
|
||||
|
@ -19,7 +31,14 @@ signals:
|
|||
void colorChanged(int colorIndex);
|
||||
void colorSelected(int colorIndex);
|
||||
|
||||
protected slots:
|
||||
void ColorsLoaded();
|
||||
|
||||
protected:
|
||||
void UpdateCells();
|
||||
void UpdateRects();
|
||||
void SelectCell(size_t CellIndex);
|
||||
|
||||
bool event(QEvent* Event) override;
|
||||
void paintEvent(QPaintEvent* PaintEvent) override;
|
||||
void resizeEvent(QResizeEvent* ResizeEvent) override;
|
||||
|
@ -27,20 +46,19 @@ protected:
|
|||
void mouseMoveEvent(QMouseEvent* MouseEvent) override;
|
||||
void keyPressEvent(QKeyEvent* KeyEvent) override;
|
||||
|
||||
void SelectCell(int CellIdx);
|
||||
std::vector<lcColorListCell> mCells;
|
||||
std::vector<lcColorListGroup> mGroups;
|
||||
|
||||
QRect mGroupRects[LC_NUM_COLORGROUPS];
|
||||
QRect* mCellRects;
|
||||
int* mCellColors;
|
||||
int mNumCells;
|
||||
size_t mCurrentCell = 0;
|
||||
quint32 mColorCode = 0;
|
||||
|
||||
int mColumns;
|
||||
int mRows;
|
||||
int mWidth;
|
||||
int mHeight;
|
||||
int mPreferredHeight;
|
||||
int mColumns = 0;
|
||||
int mRows = 0;
|
||||
int mWidth = 0;
|
||||
int mHeight = 0;
|
||||
int mPreferredHeight = 0;
|
||||
bool mAllowNoColor;
|
||||
|
||||
int mCurCell;
|
||||
QPoint mDragStartPosition;
|
||||
};
|
||||
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
#include "lc_qcolorlist.h"
|
||||
#include "lc_colors.h"
|
||||
|
||||
lcQColorPickerPopup::lcQColorPickerPopup(QWidget *parent, int colorIndex)
|
||||
: QFrame(parent, Qt::Popup)
|
||||
lcQColorPickerPopup::lcQColorPickerPopup(QWidget* Parent, int ColorIndex, bool AllowNoColor)
|
||||
: QFrame(Parent, Qt::Popup)
|
||||
{
|
||||
setFrameStyle(QFrame::StyledPanel);
|
||||
setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
|
||||
|
@ -16,13 +16,13 @@ lcQColorPickerPopup::lcQColorPickerPopup(QWidget *parent, int colorIndex)
|
|||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
setLayout(layout);
|
||||
|
||||
colorList = new lcQColorList(this);
|
||||
colorList = new lcQColorList(this, AllowNoColor);
|
||||
connect(colorList, SIGNAL(colorChanged(int)), this, SLOT(colorChanged(int)));
|
||||
connect(colorList, SIGNAL(colorSelected(int)), this, SLOT(colorSelected(int)));
|
||||
layout->addWidget(colorList);
|
||||
|
||||
colorList->blockSignals(true);
|
||||
colorList->setCurrentColor(colorIndex);
|
||||
colorList->setCurrentColor(ColorIndex);
|
||||
colorList->blockSignals(false);
|
||||
|
||||
eventLoop = nullptr;
|
||||
|
@ -75,17 +75,15 @@ void lcQColorPickerPopup::showEvent(QShowEvent *)
|
|||
colorList->setFocus();
|
||||
}
|
||||
|
||||
lcQColorPicker::lcQColorPicker(QWidget *parent)
|
||||
: QPushButton(parent)
|
||||
lcQColorPicker::lcQColorPicker(QWidget* Parent, bool AllowNoColor)
|
||||
: QPushButton(Parent), mAllowNoColor(AllowNoColor)
|
||||
{
|
||||
setFocusPolicy(Qt::StrongFocus);
|
||||
setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
|
||||
setAutoDefault(false);
|
||||
setCheckable(true);
|
||||
|
||||
initialColorIndex = 0;
|
||||
currentColorIndex = 0;
|
||||
updateIcon();
|
||||
UpdateIcon();
|
||||
|
||||
connect(this, SIGNAL(toggled(bool)), SLOT(buttonPressed(bool)));
|
||||
}
|
||||
|
@ -106,12 +104,12 @@ void lcQColorPicker::setCurrentColorCode(int colorCode)
|
|||
|
||||
int lcQColorPicker::currentColor() const
|
||||
{
|
||||
return currentColorIndex;
|
||||
return mCurrentColorIndex;
|
||||
}
|
||||
|
||||
int lcQColorPicker::currentColorCode() const
|
||||
{
|
||||
return gColorList[currentColorIndex].Code;
|
||||
return gColorList[mCurrentColorIndex].Code;
|
||||
}
|
||||
|
||||
void lcQColorPicker::buttonPressed(bool toggled)
|
||||
|
@ -119,7 +117,7 @@ void lcQColorPicker::buttonPressed(bool toggled)
|
|||
if (!toggled)
|
||||
return;
|
||||
|
||||
lcQColorPickerPopup *popup = new lcQColorPickerPopup(this, currentColorIndex);
|
||||
lcQColorPickerPopup *popup = new lcQColorPickerPopup(this, mCurrentColorIndex, mAllowNoColor);
|
||||
connect(popup, SIGNAL(changed(int)), SLOT(changed(int)));
|
||||
connect(popup, SIGNAL(selected(int)), SLOT(selected(int)));
|
||||
connect(popup, SIGNAL(hid()), SLOT(popupClosed()));
|
||||
|
@ -146,26 +144,34 @@ void lcQColorPicker::buttonPressed(bool toggled)
|
|||
popup->show();
|
||||
}
|
||||
|
||||
void lcQColorPicker::updateIcon()
|
||||
void lcQColorPicker::UpdateIcon()
|
||||
{
|
||||
int iconSize = style()->pixelMetric(QStyle::PM_SmallIconSize);
|
||||
QPixmap pix(iconSize, iconSize);
|
||||
const int IconSize = 14;//style()->pixelMetric(QStyle::PM_SmallIconSize);
|
||||
QPixmap Pixmap(IconSize, IconSize);
|
||||
|
||||
QPainter p(&pix);
|
||||
QPainter Painter(&Pixmap);
|
||||
|
||||
lcColor* color = &gColorList[currentColorIndex];
|
||||
p.setPen(Qt::darkGray);
|
||||
p.setBrush(QColor::fromRgbF(color->Value[0], color->Value[1], color->Value[2]));
|
||||
p.drawRect(0, 0, pix.width() - 1, pix.height() - 1);
|
||||
p.end();
|
||||
Painter.setPen(Qt::darkGray);
|
||||
|
||||
setIcon(QIcon(pix));
|
||||
const lcColor* Color = &gColorList[mCurrentColorIndex];
|
||||
|
||||
if (Color->Code != LC_COLOR_NOCOLOR)
|
||||
{
|
||||
Painter.setBrush(QColor::fromRgbF(Color->Value[0], Color->Value[1], Color->Value[2]));
|
||||
Painter.drawRect(0, 0, Pixmap.width() - 1, Pixmap.height() - 1);
|
||||
}
|
||||
else
|
||||
lcDrawNoColorRect(Painter, QRect(0, 0, Pixmap.width() - 1, Pixmap.height() - 1));
|
||||
|
||||
Painter.end();
|
||||
|
||||
setIcon(QIcon(Pixmap));
|
||||
}
|
||||
|
||||
void lcQColorPicker::popupClosed()
|
||||
{
|
||||
if (initialColorIndex != currentColorIndex)
|
||||
changed(initialColorIndex);
|
||||
if (mInitialColorIndex != mCurrentColorIndex)
|
||||
changed(mInitialColorIndex);
|
||||
|
||||
setChecked(false);
|
||||
setFocus();
|
||||
|
@ -173,19 +179,19 @@ void lcQColorPicker::popupClosed()
|
|||
|
||||
void lcQColorPicker::changed(int colorIndex)
|
||||
{
|
||||
if (colorIndex == currentColorIndex)
|
||||
if (colorIndex == mCurrentColorIndex)
|
||||
return;
|
||||
|
||||
currentColorIndex = colorIndex;
|
||||
updateIcon();
|
||||
mCurrentColorIndex = colorIndex;
|
||||
UpdateIcon();
|
||||
|
||||
repaint();
|
||||
|
||||
emit colorChanged(currentColorIndex);
|
||||
emit colorChanged(mCurrentColorIndex);
|
||||
}
|
||||
|
||||
void lcQColorPicker::selected(int colorIndex)
|
||||
{
|
||||
initialColorIndex = colorIndex;
|
||||
mInitialColorIndex = colorIndex;
|
||||
changed(colorIndex);
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue