Compare commits

..

50 Commits

Author SHA1 Message Date
karlis 3f1421a1bd bug:黑屏 2023-03-14 00:20:31 +08:00
karlis 4c9fe168a9 bug: pixmap溢出 2023-03-13 23:36:31 +08:00
karlis de9d7143b6 添加【可能存在问题的】拖拽和旋转 2023-03-13 21:06:05 +08:00
karlis ed4c3c0064 实现【位置错误的】LayerBounding虚线框 2023-03-13 20:47:35 +08:00
wuyize 0d42af9200 实现彩绘纹理部分替换 2023-03-13 13:48:20 +08:00
ArgonarioD acd25b4964 temp fix: 编译不通过的问题
为PaintingUtil中的transformToPainting函数临时添加了返回值,需要在后续修改
2023-03-11 23:34:13 +08:00
karlis e3217aa134 Merge branch 'main' of http://101.34.228.45:3000/BigC/ArchitectureColoredPainting 2023-03-11 22:58:31 +08:00
karlis 2cb25b8607 添加Layer的组合元素创建 2023-03-11 22:57:23 +08:00
yang.yongquan 631f0f8af7 Merge branch 'main' of http://101.34.228.45:3000/BigC/ArchitectureColoredPainting 2023-03-11 19:52:39 +08:00
yang.yongquan 50acb3b625 转换为Painting类,(z轴、线宽、测试) 2023-03-11 19:52:36 +08:00
karlis c92a3553ce 修改getReferencedBy为动态 2023-03-11 18:33:56 +08:00
wuyize 4bfdb0d9f6 Fix: 模型包围盒计算错误 2023-03-10 23:24:19 +08:00
karlis ca8d68fe93 Merge branch 'main' of http://101.34.228.45:3000/BigC/ArchitectureColoredPainting 2023-03-10 19:44:34 +08:00
karlis 3dd7fd7c0f bug fix 2023-03-10 19:44:18 +08:00
wuyize 6508f54333 MaterialStyle加入深拷贝方法clone 2023-03-10 19:41:06 +08:00
ArgonarioD b981056674 将LayerStyleDialog改为了修改拷贝对象
MaterialStyle的拷贝有问题,导致编译报错
2023-03-10 17:00:52 +08:00
ArgonarioD 293c1f3096 Merge branch 'main' of http://101.34.228.45:3000/BigC/ArchitectureColoredPainting 2023-03-10 16:07:54 +08:00
ArgonarioD 65e03ed3ba 修改了MaterialStyle的属性访问权限 2023-03-10 16:07:21 +08:00
ArgonarioD 94b16ac536 修改了LayerStyle的materialStyles的类型,添加了深拷贝构造函数 2023-03-10 16:07:07 +08:00
ArgonarioD 7c7cd02d71 移动了LayerStyleDialog所在的文件夹 2023-03-10 16:06:33 +08:00
wuyize 520597e288 添加MaterialStyleStroke的拷贝构造 2023-03-10 16:04:29 +08:00
ArgonarioD 15e2522591 让图层功能暂时能用了 2023-03-10 14:08:40 +08:00
ArgonarioD 14a1502a22 Merge branch 'main' of http://101.34.228.45:3000/BigC/ArchitectureColoredPainting 2023-03-10 13:58:11 +08:00
ArgonarioD 846f334d54 完成style的基本构架 2023-03-10 13:57:57 +08:00
karlis fedb147dd3 FIX: Crash U 2023-03-09 23:31:55 +08:00
wuyize d0cbdd65ec 解决ElementRenderer线程无法退出的问题 2023-03-09 22:54:33 +08:00
wuyize f504480050 解决线程无法析构的问题 2023-03-09 21:39:32 +08:00
ArgonarioD 52734adda8 修正了merge 2023-03-09 20:04:01 +08:00
ArgonarioD e7bce3f93e Merge 2023-03-09 19:54:07 +08:00
karlis 25eec60e5c 初步完成Layer新建 2023-03-09 19:04:33 +08:00
ArgonarioD 652fa483ba 完成了LayerStyle的基本构架 2023-03-09 16:35:04 +08:00
karlis 6f8bfa1558 Merge branch 'main' of http://101.34.228.45:3000/BigC/ArchitectureColoredPainting 2023-03-09 16:32:17 +08:00
karlis ef990cd4b4 重置了LayerTree的右键菜单 2023-03-09 16:32:00 +08:00
wuyize c2dd8271e3 ElementRender改为单例 2023-03-09 16:21:55 +08:00
wuyize 6412d9c865 模型添加彩绘配置文件 2023-03-09 15:44:14 +08:00
yang.yongquan 11c9ccc3a9 修改了ElementPool的样式 2023-03-08 19:15:42 +08:00
wuyize 08e54cfc30 ElementRenderer初始化移至构造函数 2023-03-08 16:40:04 +08:00
wuyize f4f1547d21 ElementRenderer改用独立Context 2023-03-08 12:43:19 +08:00
yang.yongquan 7d4a191f02 Merge branch 'main' of http://101.34.228.45:3000/BigC/ArchitectureColoredPainting 2023-03-08 12:40:09 +08:00
yang.yongquan 1118dc819a 修改了ElementPool 2023-03-08 12:40:05 +08:00
karlis 477517d919 优化ui,剔除不必要部分 2023-03-08 12:16:15 +08:00
karlis 368eaa6c89 添加了ElementPoolWidget 2023-03-07 22:36:39 +08:00
karlis edb7e37b91 更改了按钮位置 2023-03-07 21:12:48 +08:00
karlis 06c96144e4 Merge 2023-03-07 20:55:29 +08:00
wuyize 526f33ceba 主导航改用StackedWidget 2023-03-07 20:27:58 +08:00
yang.yongquan 6a4a724f00 更新单元测试 2023-03-07 16:54:19 +08:00
yang.yongquan 53025b93e4 完成了元素池的窗口 2023-03-07 16:53:03 +08:00
yang.yongquan a28e484cb2 Merge branch 'main' of http://101.34.228.45:3000/BigC/ArchitectureColoredPainting 2023-03-07 16:24:50 +08:00
yang.yongquan f578fe6184 完成元素池,待测试 2023-03-07 16:24:38 +08:00
wuyize 56f64f00f0 清理了一些无用代码 2023-03-07 16:22:44 +08:00
76 changed files with 2042 additions and 1557 deletions

View File

@ -104,10 +104,12 @@
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="src\Editor\EditorWidgetComponent\LayerCreateWidget.cpp" />
<ClCompile Include="src\Editor\EditorWidgetComponent\LayerStyleDialog.cpp" />
<ClCompile Include="src\Editor\EditorWidget.cpp" /> <ClCompile Include="src\Editor\EditorWidget.cpp" />
<ClCompile Include="src\CaptionButton.cpp" />
<ClCompile Include="src\Editor\EditorWidgetItem.cpp" /> <ClCompile Include="src\Editor\EditorWidgetItem.cpp" />
<ClCompile Include="src\Editor\ElementManager.cpp" /> <ClCompile Include="src\Editor\ElementManager.cpp" />
<ClCompile Include="src\Editor\ElementPoolWidget.cpp" />
<ClCompile Include="src\Editor\GraphicElement.cpp" /> <ClCompile Include="src\Editor\GraphicElement.cpp" />
<ClCompile Include="src\Editor\LayerManager.cpp" /> <ClCompile Include="src\Editor\LayerManager.cpp" />
<ClCompile Include="src\Editor\LayerStyle.cpp" /> <ClCompile Include="src\Editor\LayerStyle.cpp" />
@ -119,9 +121,10 @@
<ClCompile Include="src\Editor\ThirdPartyLib\qquick\qquicksvgparser.cpp" /> <ClCompile Include="src\Editor\ThirdPartyLib\qquick\qquicksvgparser.cpp" />
<ClCompile Include="src\Editor\ThirdPartyLib\SvgHelper.cpp" /> <ClCompile Include="src\Editor\ThirdPartyLib\SvgHelper.cpp" />
<ClCompile Include="src\Editor\util\PainterPathUtil.cpp" /> <ClCompile Include="src\Editor\util\PainterPathUtil.cpp" />
<ClCompile Include="src\Editor\util\PaintingUtil.cpp" />
<ClCompile Include="src\Editor\util\SvgFileLoader.cpp" /> <ClCompile Include="src\Editor\util\SvgFileLoader.cpp" />
<ClCompile Include="src\FluentMenu.cpp" />
<ClCompile Include="src\gl.c" /> <ClCompile Include="src\gl.c" />
<ClCompile Include="src\IconWidget.cpp" />
<ClCompile Include="src\main.cpp" /> <ClCompile Include="src\main.cpp" />
<ClCompile Include="src\MainWindow.cpp" /> <ClCompile Include="src\MainWindow.cpp" />
<ClCompile Include="src\NavigationBarWidget.cpp" /> <ClCompile Include="src\NavigationBarWidget.cpp" />
@ -149,13 +152,11 @@
<ClCompile Include="src\Renderer\Painting\StraightLine.cpp" /> <ClCompile Include="src\Renderer\Painting\StraightLine.cpp" />
<ClCompile Include="src\Renderer\VirtualTextureManager.cpp" /> <ClCompile Include="src\Renderer\VirtualTextureManager.cpp" />
<ClCompile Include="src\SvgParser.cpp" /> <ClCompile Include="src\SvgParser.cpp" />
<ClCompile Include="src\TitleWidget.cpp" />
<QtUic Include="EditorWidgetItem.ui" />
<QtUic Include="FramelessWindow.ui" />
<QtUic Include="MainWindow.ui" />
<QtUic Include="NavigationBarWidget.ui" />
<QtUic Include="RendererWidget.ui" />
<QtUic Include="EditorWidget.ui" /> <QtUic Include="EditorWidget.ui" />
<QtUic Include="EditorWidgetItem.ui" />
<QtUic Include="MainWindow.ui" />
<QtUic Include="RendererWidget.ui" />
<QtUic Include="src\Editor\EditorWidgetComponent\LayerCreateWidget.ui" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\data.json" /> <None Include="..\data.json" />
@ -190,7 +191,10 @@
<QtMoc Include="src\Editor\RightBar\InfoDisplayWidget.h" /> <QtMoc Include="src\Editor\RightBar\InfoDisplayWidget.h" />
<QtMoc Include="src\MainWindow.h" /> <QtMoc Include="src\MainWindow.h" />
<QtMoc Include="src\Editor\EditorWidget.h" /> <QtMoc Include="src\Editor\EditorWidget.h" />
<QtMoc Include="src\Editor\EditorWidgetComponent\LayerCreateWidget.h" />
<QtMoc Include="src\Editor\EditorWidgetComponent\LayerStyleDialog.h" />
<ClInclude Include="src\Editor\ElementManager.h" /> <ClInclude Include="src\Editor\ElementManager.h" />
<QtMoc Include="src\Editor\ElementPoolWidget.h" />
<ClInclude Include="src\Editor\GraphicElement.h" /> <ClInclude Include="src\Editor\GraphicElement.h" />
<ClInclude Include="src\Editor\LayerManager.h" /> <ClInclude Include="src\Editor\LayerManager.h" />
<ClInclude Include="src\Editor\LayerStyle.h" /> <ClInclude Include="src\Editor\LayerStyle.h" />
@ -201,7 +205,9 @@
<ClInclude Include="src\Editor\ThirdPartyLib\qquick\qtquickglobal_p.h" /> <ClInclude Include="src\Editor\ThirdPartyLib\qquick\qtquickglobal_p.h" />
<ClInclude Include="src\Editor\ThirdPartyLib\SvgHelper.h" /> <ClInclude Include="src\Editor\ThirdPartyLib\SvgHelper.h" />
<ClInclude Include="src\Editor\util\PainterPathUtil.h" /> <ClInclude Include="src\Editor\util\PainterPathUtil.h" />
<ClInclude Include="src\Editor\util\PaintingUtil.h" />
<ClInclude Include="src\Editor\util\SvgFileLoader.h" /> <ClInclude Include="src\Editor\util\SvgFileLoader.h" />
<QtMoc Include="src\FluentMenu.h" />
<ClInclude Include="src\Renderer\IblUtils.h" /> <ClInclude Include="src\Renderer\IblUtils.h" />
<ClInclude Include="src\Renderer\Painting\BaseStyle.h" /> <ClInclude Include="src\Renderer\Painting\BaseStyle.h" />
<ClInclude Include="src\Renderer\Painting\CubicBezierSignedDistance.h" /> <ClInclude Include="src\Renderer\Painting\CubicBezierSignedDistance.h" />
@ -214,9 +220,6 @@
<ClInclude Include="src\Renderer\Preview\ElementRenderer.h" /> <ClInclude Include="src\Renderer\Preview\ElementRenderer.h" />
<ClInclude Include="src\Renderer\VirtualTextureManager.h" /> <ClInclude Include="src\Renderer\VirtualTextureManager.h" />
<ClInclude Include="src\SvgParser.h" /> <ClInclude Include="src\SvgParser.h" />
<QtMoc Include="src\TitleWidget.h" />
<QtMoc Include="src\IconWidget.h" />
<QtMoc Include="src\CaptionButton.h" />
<QtMoc Include="src\NavigationBarWidget.h" /> <QtMoc Include="src\NavigationBarWidget.h" />
<QtMoc Include="src\Renderer\RendererWidget.h" /> <QtMoc Include="src\Renderer\RendererWidget.h" />
<QtMoc Include="src\Editor\EditorWidgetItem.h" /> <QtMoc Include="src\Editor\EditorWidgetItem.h" />

View File

@ -70,15 +70,12 @@
<QtUic Include="MainWindow.ui"> <QtUic Include="MainWindow.ui">
<Filter>Form Files</Filter> <Filter>Form Files</Filter>
</QtUic> </QtUic>
<QtUic Include="NavigationBarWidget.ui">
<Filter>Form Files</Filter>
</QtUic>
<QtUic Include="FramelessWindow.ui">
<Filter>Form Files</Filter>
</QtUic>
<QtUic Include="EditorWidget.ui"> <QtUic Include="EditorWidget.ui">
<Filter>Form Files</Filter> <Filter>Form Files</Filter>
</QtUic> </QtUic>
<QtUic Include="src\Editor\EditorWidgetComponent\LayerCreateWidget.ui">
<Filter>Form Files</Filter>
</QtUic>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="src\Editor\EditorWidgetItem.cpp"> <ClCompile Include="src\Editor\EditorWidgetItem.cpp">
@ -117,15 +114,6 @@
<ClCompile Include="src\NavigationBarWidget.cpp"> <ClCompile Include="src\NavigationBarWidget.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="src\CaptionButton.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\IconWidget.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\TitleWidget.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\Renderer\Painting\BvhTree.cpp"> <ClCompile Include="src\Renderer\Painting\BvhTree.cpp">
<Filter>Source Files\Renderer\Painting</Filter> <Filter>Source Files\Renderer\Painting</Filter>
</ClCompile> </ClCompile>
@ -219,6 +207,21 @@
<ClCompile Include="src\Editor\EditorWidget.cpp"> <ClCompile Include="src\Editor\EditorWidget.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="src\Editor\ElementPoolWidget.cpp">
<Filter>Source Files\Editor</Filter>
</ClCompile>
<ClCompile Include="src\FluentMenu.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\Editor\util\PaintingUtil.cpp">
<Filter>Source Files\Editor\util</Filter>
</ClCompile>
<ClCompile Include="src\Editor\EditorWidgetComponent\LayerCreateWidget.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\Editor\EditorWidgetComponent\LayerStyleDialog.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<QtMoc Include="src\Renderer\RendererGLWidget.h"> <QtMoc Include="src\Renderer\RendererGLWidget.h">
@ -233,15 +236,6 @@
<QtMoc Include="src\NavigationBarWidget.h"> <QtMoc Include="src\NavigationBarWidget.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</QtMoc> </QtMoc>
<QtMoc Include="src\CaptionButton.h">
<Filter>Header Files</Filter>
</QtMoc>
<QtMoc Include="src\IconWidget.h">
<Filter>Header Files</Filter>
</QtMoc>
<QtMoc Include="src\TitleWidget.h">
<Filter>Header Files</Filter>
</QtMoc>
<QtMoc Include="src\MainWindow.h"> <QtMoc Include="src\MainWindow.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</QtMoc> </QtMoc>
@ -257,6 +251,18 @@
<QtMoc Include="src\Editor\EditorWidget.h"> <QtMoc Include="src\Editor\EditorWidget.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</QtMoc> </QtMoc>
<QtMoc Include="src\Editor\ElementPoolWidget.h">
<Filter>Header Files\Editor</Filter>
</QtMoc>
<QtMoc Include="src\FluentMenu.h">
<Filter>Header Files</Filter>
</QtMoc>
<QtMoc Include="src\Editor\EditorWidgetComponent\LayerCreateWidget.h">
<Filter>Header Files</Filter>
</QtMoc>
<QtMoc Include="src\Editor\EditorWidgetComponent\LayerStyleDialog.h">
<Filter>Header Files</Filter>
</QtMoc>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\data.json" /> <None Include="..\data.json" />
@ -390,9 +396,6 @@
<ClInclude Include="src\Editor\GraphicElement.h"> <ClInclude Include="src\Editor\GraphicElement.h">
<Filter>Header Files\Editor</Filter> <Filter>Header Files\Editor</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="src\Editor\LayerStyle.h">
<Filter>Header Files\Editor</Filter>
</ClInclude>
<ClInclude Include="src\Editor\LayerManager.h"> <ClInclude Include="src\Editor\LayerManager.h">
<Filter>Header Files\Editor</Filter> <Filter>Header Files\Editor</Filter>
</ClInclude> </ClInclude>
@ -450,6 +453,12 @@
<ClInclude Include="src\Renderer\VirtualTextureManager.h"> <ClInclude Include="src\Renderer\VirtualTextureManager.h">
<Filter>Header Files\Renderer</Filter> <Filter>Header Files\Renderer</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="src\Editor\util\PaintingUtil.h">
<Filter>Header Files\Editor\util</Filter>
</ClInclude>
<ClInclude Include="src\Editor\LayerStyle.h">
<Filter>Header Files\Editor</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<QtRcc Include="res\MainWindow.qrc"> <QtRcc Include="res\MainWindow.qrc">

View File

@ -7,42 +7,53 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>1139</width> <width>1139</width>
<height>685</height> <height>862</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
<string>Form</string> <string>Form</string>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_2"> <layout class="QVBoxLayout" name="verticalLayout_2">
<property name="topMargin">
<number>0</number>
</property>
<item> <item>
<layout class="QVBoxLayout" name="verticalLayout" stretch="1,1,1,20"> <layout class="QVBoxLayout" name="verticalLayout" stretch="1,20">
<property name="topMargin"> <property name="topMargin">
<number>0</number> <number>0</number>
</property> </property>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item> <item>
<widget class="QWidget" name="widget" native="true"> <widget class="QWidget" name="widget" native="true">
<property name="autoFillBackground">
<bool>false</bool>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_3"> <layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout_2"> <layout class="QHBoxLayout" name="horizontalLayout_2" stretch="1,1,1,1,1,0">
<property name="spacing">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<item> <item>
<widget class="QPushButton" name="createButton"> <widget class="QPushButton" name="createButton">
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>80</width> <width>80</width>
<height>0</height> <height>40</height>
</size> </size>
</property> </property>
<property name="maximumSize"> <property name="maximumSize">
@ -61,7 +72,7 @@
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>80</width> <width>80</width>
<height>0</height> <height>40</height>
</size> </size>
</property> </property>
<property name="maximumSize"> <property name="maximumSize">
@ -80,7 +91,7 @@
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>80</width> <width>80</width>
<height>0</height> <height>40</height>
</size> </size>
</property> </property>
<property name="maximumSize"> <property name="maximumSize">
@ -99,7 +110,7 @@
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>80</width> <width>80</width>
<height>0</height> <height>40</height>
</size> </size>
</property> </property>
<property name="maximumSize"> <property name="maximumSize">
@ -115,10 +126,16 @@
</item> </item>
<item> <item>
<widget class="QPushButton" name="closeButton"> <widget class="QPushButton" name="closeButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>80</width> <width>80</width>
<height>0</height> <height>40</height>
</size> </size>
</property> </property>
<property name="maximumSize"> <property name="maximumSize">
@ -132,28 +149,34 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout> </layout>
</item> </item>
</layout> </layout>
</widget> </widget>
</item> </item>
<item> <item>
<spacer name="horizontalSpacer"> <widget class="QTabWidget" name="tabWidget">
<property name="orientation"> <property name="minimumSize">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size> <size>
<width>40</width> <width>0</width>
<height>20</height> <height>800</height>
</size> </size>
</property> </property>
</spacer>
</item>
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex"> <property name="currentIndex">
<number>1</number> <number>0</number>
</property> </property>
<widget class="QWidget" name="tab"> <widget class="QWidget" name="tab">
<attribute name="title"> <attribute name="title">

View File

@ -6,14 +6,23 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>1124</width> <width>1473</width>
<height>695</height> <height>1103</height>
</rect> </rect>
</property> </property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="windowTitle"> <property name="windowTitle">
<string>RendererWidget</string> <string>RendererWidget</string>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin"> <property name="leftMargin">
<number>0</number> <number>0</number>
</property> </property>
@ -28,53 +37,98 @@
</property> </property>
<item> <item>
<widget class="QWidget" name="MainWindow" native="true"> <widget class="QWidget" name="MainWindow" native="true">
<layout class="QVBoxLayout" name="verticalLayout_2" stretch="1,30"> <layout class="QVBoxLayout" name="verticalLayout_2" stretch="30">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item> <item>
<widget class="QLabel" name="Title"> <layout class="QHBoxLayout" name="horizontalLayout" stretch="0,12,5">
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,18,5">
<item> <item>
<widget class="QWidget" name="LeftBar" native="true"/> <widget class="QWidget" name="LeftBar" native="true"/>
</item> </item>
<item> <item>
<widget class="PreviewWindow" name="Preview"/> <widget class="PreviewWindow" name="Preview">
<property name="minimumSize">
<size>
<width>1080</width>
<height>1080</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>1080</width>
<height>1080</height>
</size>
</property>
</widget>
</item> </item>
<item> <item>
<widget class="QWidget" name="RightBar" native="true"> <widget class="QWidget" name="RightBar" native="true">
<layout class="QVBoxLayout" name="verticalLayout_4" stretch="1,2"> <layout class="QVBoxLayout" name="verticalLayout_4" stretch="3,2">
<property name="spacing">
<number>20</number>
</property>
<property name="leftMargin">
<number>11</number>
</property>
<property name="topMargin">
<number>11</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>11</number>
</property>
<item> <item>
<widget class="QTabWidget" name="DisplayTab"> <widget class="QTabWidget" name="DisplayTab">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="currentIndex"> <property name="currentIndex">
<number>0</number> <number>1</number>
</property> </property>
<widget class="InfoDisplayWidget" name="LayerDisplay"> <widget class="InfoDisplayWidget" name="LayerDisplay">
<attribute name="title"> <attribute name="title">
<string>Layer</string> <string>图层信息</string>
</attribute> </attribute>
</widget> </widget>
<widget class="QWidget" name="ElementDisplay"> <widget class="ElementPoolWidget" name="ElementDisplay">
<attribute name="title"> <attribute name="title">
<string>Element</string> <string>图元池</string>
</attribute> </attribute>
</widget> </widget>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="LayerTreeWidget" name="LayerTree"> <widget class="LayerTreeWidget" name="LayerTree">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="contextMenuPolicy"> <property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum> <enum>Qt::CustomContextMenu</enum>
</property> </property>
<property name="accessibleName">
<string/>
</property>
<column> <column>
<property name="text"> <property name="text">
<string notr="true">1</string> <string>图层树</string>
</property> </property>
</column> </column>
</widget> </widget>
@ -107,6 +161,12 @@
<header location="global">InfoDisplayWidget.h</header> <header location="global">InfoDisplayWidget.h</header>
<container>1</container> <container>1</container>
</customwidget> </customwidget>
<customwidget>
<class>ElementPoolWidget</class>
<extends>QWidget</extends>
<header>ElementPoolWidget.h</header>
<container>1</container>
</customwidget>
</customwidgets> </customwidgets>
<resources/> <resources/>
<connections/> <connections/>

View File

@ -1,94 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>FramelessWindow</class>
<widget class="QWidget" name="FramelessWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>560</width>
<height>544</height>
</rect>
</property>
<property name="windowTitle">
<string/>
</property>
<property name="autoFillBackground">
<bool>false</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QWidget" name="windowFrame" native="true">
<property name="autoFillBackground">
<bool>false</bool>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>1</number>
</property>
<property name="topMargin">
<number>1</number>
</property>
<property name="rightMargin">
<number>1</number>
</property>
<property name="bottomMargin">
<number>1</number>
</property>
<item>
<widget class="QWidget" name="windowContent" native="true">
<property name="autoFillBackground">
<bool>false</bool>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"> <ui version="4.0">
<class>MainWindowClass</class> <class>MainWindowClass</class>
<widget class="QMainWindow" name="MainWindowClass"> <widget class="QWidget" name="MainWindowClass">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>
@ -10,102 +10,45 @@
<height>722</height> <height>722</height>
</rect> </rect>
</property> </property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<property name="styleSheet"> <property name="styleSheet">
<string notr="true">font: 10pt &quot;Segoe UI, Microsoft YaHei UI&quot;;</string> <string notr="true">font: 10pt &quot;Segoe UI, Microsoft YaHei UI&quot;;</string>
</property> </property>
<widget class="QWidget" name="centralWidget"> <layout class="QVBoxLayout" name="verticalLayout">
<property name="sizePolicy"> <property name="spacing">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred"> <number>0</number>
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout"> <property name="leftMargin">
<property name="spacing"> <number>0</number>
<number>0</number> </property>
</property> <property name="topMargin">
<property name="leftMargin"> <number>0</number>
<number>0</number> </property>
</property> <property name="rightMargin">
<property name="topMargin"> <number>0</number>
<number>0</number> </property>
</property> <property name="bottomMargin">
<property name="rightMargin"> <number>0</number>
<number>0</number> </property>
</property> <item>
<property name="bottomMargin"> <layout class="QGridLayout" name="gridLayout">
<number>0</number> <property name="sizeConstraint">
</property> <enum>QLayout::SetDefaultConstraint</enum>
<item> </property>
<layout class="QVBoxLayout" name="verticalLayout_4" stretch="1"> <property name="topMargin">
<property name="spacing"> <number>0</number>
<number>0</number> </property>
</property> <property name="spacing">
<property name="sizeConstraint"> <number>0</number>
<enum>QLayout::SetDefaultConstraint</enum> </property>
</property> <item row="0" column="0">
<item> <widget class="QStackedWidget" name="stackedWidget">
<widget class="QTabWidget" name="tabWidget"> <widget class="EditorWidget" name="editorWidget"/>
<property name="font"> <widget class="Renderer::RendererWidget" name="rendererWidget"/>
<font> </widget>
<family>Segoe UI, Microsoft YaHei UI</family> </item>
<pointsize>10</pointsize> </layout>
<weight>50</weight> </item>
<italic>false</italic> </layout>
<bold>false</bold>
</font>
</property>
<property name="styleSheet">
<string notr="true">
QTabBar::tab.rendererWidget {
height: 0px;
margin-top:0px;
}
QTabWidget::tab-bar.rendererWidget
{
height: 0px;
top:0px;
}
QTabWidget::pane.rendererWidget {
border: 0px;
background-color: transparent;
}
</string>
</property>
<property name="tabPosition">
<enum>QTabWidget::North</enum>
</property>
<property name="tabShape">
<enum>QTabWidget::Rounded</enum>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<property name="elideMode">
<enum>Qt::ElideNone</enum>
</property>
<property name="tabsClosable">
<bool>false</bool>
</property>
<widget class="EditorWidget" name="editorWidget">
<attribute name="title">
<string>纹理编辑</string>
</attribute>
</widget>
<widget class="Renderer::RendererWidget" name="rendererWidget">
<attribute name="title">
<string>场景渲染</string>
</attribute>
</widget>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</widget> </widget>
<layoutdefault spacing="6" margin="11"/> <layoutdefault spacing="6" margin="11"/>
<customwidgets> <customwidgets>
@ -120,8 +63,6 @@
<header>Editor/EditorWidget.h</header> <header>Editor/EditorWidget.h</header>
</customwidget> </customwidget>
</customwidgets> </customwidgets>
<resources> <resources/>
<include location="MainWindow.qrc"/>
</resources>
<connections/> <connections/>
</ui> </ui>

View File

@ -0,0 +1,2 @@
17876391417123941155.jpg 0.json 0 0 1 1
11474523244911310074.jpg 1.json 0 0 1 1

View File

@ -1,100 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>NavigationBarWidgetClass</class>
<widget class="QWidget" name="NavigationBarWidgetClass">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>612</width>
<height>41</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>40</height>
</size>
</property>
<property name="baseSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="windowTitle">
<string>NavigationBarWidget</string>
</property>
<property name="styleSheet">
<string notr="true">QRadioButton::indicator {
width: 0px;
border: 0px;
background-color: rgba(0, 0, 0, 0);
}</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QPushButton" name="radioButton0">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="baseSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>纹理编辑</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="radioButton1">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>场景渲染</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>

View File

@ -13,7 +13,7 @@
<property name="windowTitle"> <property name="windowTitle">
<string>RendererWidget</string> <string>RendererWidget</string>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,0,1"> <layout class="QVBoxLayout" name="verticalLayout" stretch="0,1">
<property name="spacing"> <property name="spacing">
<number>0</number> <number>0</number>
</property> </property>
@ -31,25 +31,37 @@
</property> </property>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout_3"> <layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="sizeConstraint"> <property name="leftMargin">
<enum>QLayout::SetDefaultConstraint</enum> <number>6</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="bottomMargin">
<number>5</number>
</property> </property>
<item> <item>
<widget class="QPushButton" name="openButton"> <widget class="QtMaterialFlatButton" name="openButton">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed"> <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch> <horstretch>0</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>0</width> <width>50</width>
<height>40</height> <height>30</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>50</width>
<height>30</height>
</size> </size>
</property> </property>
<property name="text"> <property name="text">
<string>打开</string> <string>文件</string>
</property> </property>
<property name="flat"> <property name="flat">
<bool>false</bool> <bool>false</bool>
@ -71,34 +83,6 @@
</item> </item>
</layout> </layout>
</item> </item>
<item>
<widget class="QMenuBar" name="menuBar">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Ignored">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<widget class="QMenu" name="menu">
<property name="minimumSize">
<size>
<width>0</width>
<height>40</height>
</size>
</property>
<property name="title">
<string>打开</string>
</property>
</widget>
<addaction name="menu"/>
</widget>
</item>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,0"> <layout class="QHBoxLayout" name="horizontalLayout" stretch="1,0">
<property name="sizeConstraint"> <property name="sizeConstraint">
@ -180,6 +164,11 @@
<extends>QOpenGLWidget</extends> <extends>QOpenGLWidget</extends>
<header>RendererGLWidget.h</header> <header>RendererGLWidget.h</header>
</customwidget> </customwidget>
<customwidget>
<class>QtMaterialFlatButton</class>
<extends>QPushButton</extends>
<header location="global">qtmaterialflatbutton.h</header>
</customwidget>
</customwidgets> </customwidgets>
<resources/> <resources/>
<connections/> <connections/>

View File

@ -1190,7 +1190,7 @@ void main()
//imageStore(gBaseColor, pixelLocation, vec4(uv,1,1)); //imageStore(gBaseColor, pixelLocation, vec4(uv,1,1));
//imageStore(gMetallicRoughness, pixelLocation, vec4(uv,1,1)); //imageStore(gMetallicRoughness, pixelLocation, vec4(uv,1,1));
//return; //return;
uv = vec2(1)-uv*2; uv = uv*2-vec2(1);
//vec2 uv = imageLoad(gPaintingTexCoord, pixelLocation).rg; //vec2 uv = imageLoad(gPaintingTexCoord, pixelLocation).rg;
vec3 debugBVH = vec3(0); vec3 debugBVH = vec3(0);

View File

@ -1,261 +0,0 @@
/*
The MIT License (MIT)
Copyright © 2018-2022 Antonio Dias
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "CaptionButton.h"
CaptionButton::CaptionButton(QWidget *parent) : QWidget(parent)
{
m_is_active = false;
m_is_under_mouse = false;
m_is_pressed = false;
m_icon_dark = false;
setAttribute(Qt::WA_Hover);
}
CaptionButton::~CaptionButton()
{
}
QPixmap CaptionButton::drawIcon(const QPixmap &icon, bool active, bool force_light)
{
QImage tmp = icon.toImage();
if (!active)
{
for (int i = 0; i < tmp.height(); i++)
{
for (int j = 0; j < tmp.width(); j++)
{
QColor pixel = QColor::fromRgba(tmp.pixel(j, i));
pixel.setRedF(pixel.redF() * 0.5f);
pixel.setGreenF(pixel.greenF() * 0.5f);
pixel.setBlueF(pixel.blueF() * 0.5f);
tmp.setPixel(j, i, pixel.rgba());
}
}
}
if (m_icon_dark && !force_light)
tmp.invertPixels();
return QPixmap::fromImage(tmp);
}
void CaptionButton::init(IconType type)
{
m_type = type;
setColors();
drawIcons();
}
void CaptionButton::drawIcons()
{
switch (m_type)
{
case IconType::Minimize:
{
QPixmap icon = QPixmap(":/images/icon_window_minimize.png");
m_active_icon = drawIcon(icon, true);
m_inactive_icon = drawIcon(icon, false);
break;
}
case IconType::Restore:
{
QPixmap icon = QPixmap(":/images/icon_window_restore.png");
m_active_icon = drawIcon(icon, true);
m_inactive_icon = drawIcon(icon, false);
break;
}
case IconType::Maximize:
{
QPixmap icon = QPixmap(":/images/icon_window_maximize.png");
m_active_icon = drawIcon(icon, true);
m_inactive_icon = drawIcon(icon, false);
break;
}
case IconType::Close:
{
QPixmap icon = QPixmap(":/images/icon_window_close.png");
m_active_icon = drawIcon(icon, true);
m_inactive_icon = drawIcon(icon, false);
m_close_icon_hover = drawIcon(icon, true, true);
break;
}
}
}
void CaptionButton::setColors()
{
if (m_icon_dark)
{
if (m_type == IconType::Close)
{
m_normal = QColor("transparent");
m_hover = QColor("#F00000");
m_pressed = QColor("#F1707A");
}
else
{
m_normal = QColor("transparent");
m_hover = QColor("#E5E5E5");
m_pressed = QColor("#CACACB");
}
}
else
{
if (m_type == IconType::Close)
{
m_normal = QColor("transparent");
m_hover = QColor("#F00000");
m_pressed = QColor("#F1707A");
}
else
{
m_normal = QColor("transparent");
m_hover = QColor("#505050");
m_pressed = QColor("#3F3F3F");
}
}
repaint();
}
void CaptionButton::setIconMode(bool icon_dark)
{
m_icon_dark = icon_dark;
drawIcons();
setColors();
repaint();
}
void CaptionButton::setActive(bool is_active)
{
m_is_active = is_active;
repaint();
}
void CaptionButton::setState(int state)
{
switch (state)
{
case QEvent::HoverEnter:
{
m_is_under_mouse = true;
repaint();
break;
}
case QEvent::HoverLeave:
{
m_is_under_mouse = false;
repaint();
break;
}
case QEvent::MouseButtonPress:
{
m_is_pressed = true;
m_is_under_mouse = true;
repaint();
break;
}
case QEvent::MouseButtonRelease:
{
m_is_pressed = false;
m_is_under_mouse = false;
repaint();
break;
}
default:
break;
}
}
void CaptionButton::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event)
QPixmap current_icon = m_active_icon;
QColor current_color = m_normal;
//Change icon if needed
if (m_is_under_mouse)
{
if (m_type == IconType::Close)
current_icon = m_close_icon_hover;
}
else
{
if (!m_is_active)
current_icon = m_inactive_icon;
}
//Change background color if needed
if (m_is_pressed)
{
if (m_is_under_mouse)
current_color = m_pressed;
}
else
{
if (m_is_under_mouse)
current_color = m_hover;
}
QPainter painter(this);
painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
painter.fillRect(rect(), current_color);
QRect target_rect;
target_rect = current_icon.rect();
target_rect.setSize(QSize(16, 16));
target_rect = QRect(rect().center() - target_rect.center(), target_rect.size());
painter.drawPixmap(target_rect, current_icon);
}

View File

@ -1,81 +0,0 @@
/*
The MIT License (MIT)
Copyright © 2018-2022 Antonio Dias
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef CAPTIONBUTTON_H
#define CAPTIONBUTTON_H
#include <QtCore>
#include <QtGui>
#include <QtWidgets>
class CaptionButton : public QWidget
{
Q_OBJECT
public:
explicit CaptionButton(QWidget *parent = nullptr);
~CaptionButton();
enum class IconType
{
Minimize,
Restore,
Maximize,
Close
};
void init(IconType type);
signals:
void clicked();
public slots:
void setIconMode(bool icon_dark);
void setActive(bool is_active);
void setState(int state);
private:
//Functions
QPixmap drawIcon(const QPixmap &icon, bool active, bool force_light = false);
void setColors();
void drawIcons();
void paintEvent(QPaintEvent *event);
//Variables
QPixmap m_inactive_icon;
QPixmap m_active_icon;
QPixmap m_close_icon_hover;
QColor m_normal;
QColor m_hover;
QColor m_pressed;
IconType m_type;
bool m_is_active;
bool m_is_under_mouse;
bool m_is_pressed;
bool m_icon_dark;
};
#endif // CAPTIONBUTTON_H

View File

@ -0,0 +1,54 @@
#include "LayerCreateWidget.h"
#include <QComboBox>
LayerCreateWidget::LayerCreateWidget(ElementManager* elementManager, QWidget* parent) :
QDialog(parent)
{
ui.setupUi(this);
connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
connect(ui.comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onCurrentIndexChanged(int)));
elementPool = new ElementPoolWidget(ui.elementPool);
elementPool->setElementList(elementManager->elements);
}
LayerCreateWidget::~LayerCreateWidget()
{
}
void LayerCreateWidget::accept()
{
QJsonObject jsonObj;
jsonObj.insert("name", ui.name->text());
if (ui.comboBox->currentIndex() == 0) {
jsonObj.insert("is-folder", false);
jsonObj.insert("element", elementPool->currentIndex);
}
else {
jsonObj.insert("is-folder", true);
jsonObj.insert("children", QJsonArray());
}
QJsonObject transform;
QJsonObject offset;
QJsonObject scale;
scale.insert("x", 1);
scale.insert("y", 1);
offset.insert("x", 0);
offset.insert("y", 0);
transform.insert("offset", offset);
transform.insert("scale", scale);
transform.insert("rotation", 0);
jsonObj.insert("transform", transform);
jsonObj.insert("referenced-by", QJsonValue());
emit LayerInfoReturned(jsonObj);
QDialog::accept();
}
void LayerCreateWidget::onCurrentIndexChanged(int index) {
if (index == 0) {// leaf layer
elementPool->setVisible(true);
}
else {// folder layer
elementPool->setVisible(false);
}
}

View File

@ -0,0 +1,29 @@
#pragma once
#include <QDialog>
#include <QJsonObject>
#include "ElementPoolWidget.h"
#include "ElementManager.h"
#include "ui_LayerCreateWidget.h"
class LayerCreateWidget :
public QDialog
{
Q_OBJECT
private:
Ui::LayerCreateWidget ui;
ElementPoolWidget* elementPool;
public:
LayerCreateWidget(ElementManager* elementManager,QWidget* parent = nullptr);
~LayerCreateWidget();
void accept() override;
public slots:
void onCurrentIndexChanged(int index);
signals:
void LayerInfoReturned(QJsonObject jsonObj);
};

View File

@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>LayerCreateWidget</class>
<widget class="QWidget" name="LayerCreateWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>326</width>
<height>355</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,1,5,1,0">
<item>
<widget class="QComboBox" name="comboBox">
<property name="maximumSize">
<size>
<width>90</width>
<height>16777215</height>
</size>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<property name="maxVisibleItems">
<number>2</number>
</property>
<property name="maxCount">
<number>2</number>
</property>
<property name="insertPolicy">
<enum>QComboBox::NoInsert</enum>
</property>
<property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToContents</enum>
</property>
<item>
<property name="text">
<string>叶子节点</string>
</property>
</item>
<item>
<property name="text">
<string>组合节点</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QWidget" name="widget" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>11</number>
</property>
<property name="rightMargin">
<number>11</number>
</property>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>图层名:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="name"/>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="elementPool" native="true"/>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Close|QDialogButtonBox::Ok</set>
</property>
<property name="centerButtons">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -0,0 +1,88 @@
#include "LayerStyleDialog.h"
#include <QComboBox>
#include <QDialogButtonBox>
#include <QHBoxLayout>
#include <QGridLayout>
#include <QDebug>
#include <unordered_set>
LayerStyleDialog::LayerStyleDialog(
QWidget* parent,
std::shared_ptr<LayerStyle> existedStyle,
std::vector<std::shared_ptr<LayerStyle>>* excludeStyles
) : QDialog(parent)
{
QVBoxLayout* dialogLayout = new QVBoxLayout(this);
dialogLayout->setAlignment(Qt::AlignmentFlag::AlignHCenter);
this->setLayout(dialogLayout);
if (existedStyle)
{
this->modifyingStyle = existedStyle->clonePtr();
this->styleContainer = nullptr;
this->styleWidget = modifyingStyle->getInputWidget();
this->styleWidget->setParent(this);
dialogLayout->addWidget(styleWidget);
// do something
}
else
{
std::unordered_set<QString> excludeStyleNames;
for(auto &style : *excludeStyles)
{
excludeStyleNames.insert(style->getStyleName());
}
QComboBox* typeSelector = new QComboBox(this);
for (auto& pair : LayerStyle::types)
{
if (!excludeStyleNames.contains(pair.first))
{
typeSelector->addItem(pair.first);
if (!this->modifyingStyle)
{
this->modifyingStyle = std::move(pair.second());
}
}
}
if (typeSelector->count() > 0)
{
dialogLayout->addWidget(typeSelector);
this->styleContainer = new QGridLayout(this);
dialogLayout->addLayout(styleContainer);
this->styleWidget = this->modifyingStyle->getInputWidget();
this->styleWidget->setParent(this);
this->styleContainer->addWidget(styleWidget);
connect(typeSelector, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &LayerStyleDialog::onStyleTypeSelectorChanged);
}
}
QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
connect(buttonBox, &QDialogButtonBox::accepted, this, &LayerStyleDialog::accept);
connect(buttonBox, &QDialogButtonBox::rejected, this, &LayerStyleDialog::reject);
dialogLayout->addWidget(buttonBox);
}
void LayerStyleDialog::accept()
{
this->layerStyle = std::move(this->modifyingStyle);
QDialog::accept();
}
void LayerStyleDialog::onStyleTypeSelectorChanged(int index)
{
if (this->styleWidget)
{
this->styleContainer->removeWidget(this->styleWidget);
this->styleWidget->setParent(nullptr);
delete styleWidget;
}
this->modifyingStyle = std::move(LayerStyle::types[index].second());
this->styleWidget = this->modifyingStyle->getInputWidget();
this->styleWidget->setParent(this);
this->styleContainer->addWidget(styleWidget, 0, 0, 1, 1);
}

View File

@ -0,0 +1,23 @@
#pragma once
#include "LayerStyle.h"
#include <QDialog>
#include <QGridLayout>
class LayerStyleDialog : public QDialog
{
Q_OBJECT
private:
QWidget* styleWidget;
QGridLayout* styleContainer;
std::unique_ptr<LayerStyle> modifyingStyle;
public:
LayerStyleDialog(
QWidget* parent = nullptr,
std::shared_ptr<LayerStyle> existedStyle = nullptr,
std::vector<std::shared_ptr<LayerStyle>>* excludeStyles = nullptr);
std::shared_ptr<LayerStyle> layerStyle;
private slots:
void onStyleTypeSelectorChanged(int index);
void accept() override;
};

View File

@ -11,7 +11,13 @@ EditorWidgetItem::EditorWidgetItem(QString filePath,QWidget *parent) : QWidget(p
tabWidget = ui.DisplayTab; tabWidget = ui.DisplayTab;
this->filePath = filePath; this->filePath = filePath;
layerInfoDisplayWidget = dynamic_cast<InfoDisplayWidget *>(tabWidget->widget(0)); layerInfoDisplayWidget = dynamic_cast<InfoDisplayWidget *>(tabWidget->widget(0));
elementInfoDisplayWidget = dynamic_cast<InfoDisplayWidget *>(tabWidget->widget(1)); elementInfoDisplayWidget = dynamic_cast<ElementPoolWidget *>(tabWidget->widget(1));
qDebug() << layerInfoDisplayWidget;
qDebug() << elementInfoDisplayWidget;
connect(previewWindow, &PreviewWindow::layerInfoChanged, layerInfoDisplayWidget, &InfoDisplayWidget::triggerSelfRefresh);
connect(treeWidget, &LayerTreeWidget::displayLayerChange, previewWindow, &PreviewWindow::currentLayerChanged);
connect(treeWidget, &LayerTreeWidget::requireRefreshElementWidget, elementInfoDisplayWidget, &ElementPoolWidget::refresh);
connect(layerInfoDisplayWidget, &InfoDisplayWidget::requireRefreshElementWidget, elementInfoDisplayWidget, &ElementPoolWidget::refresh);
connect(treeWidget, &LayerTreeWidget::displayLayerChange, this, &EditorWidgetItem::onLayerChange); connect(treeWidget, &LayerTreeWidget::displayLayerChange, this, &EditorWidgetItem::onLayerChange);
connect(layerInfoDisplayWidget, &InfoDisplayWidget::requireRefreshPreview, this, connect(layerInfoDisplayWidget, &InfoDisplayWidget::requireRefreshPreview, this,
&EditorWidgetItem::triggerRefreshPreview); &EditorWidgetItem::triggerRefreshPreview);
@ -33,8 +39,12 @@ EditorWidgetItem::EditorWidgetItem(QString filePath,QWidget *parent) : QWidget(p
QJsonObject source = jsonDoc.object(); QJsonObject source = jsonDoc.object();
elementManager = new ElementManager(source,previewWindow->getRenderer()); elementManager = new ElementManager(source,previewWindow->getRenderer());
layerManager = new LayerManager(source, elementManager); layerManager = new LayerManager(source, elementManager);
elementInfoDisplayWidget->setElementManager(elementManager);
treeWidget->elementManager = elementManager;
qDebug() << layerManager->toJson(); qDebug() << layerManager->toJson();
previewWindow->initialize(layerManager,QSize(jsonDoc.object().value("width").toDouble(),jsonDoc.object().value("height").toDouble())); previewWindow->initialize(layerManager,QSize(jsonDoc.object().value("width").toDouble(),jsonDoc.object().value("height").toDouble()));
if (layerManager->getRoot() != nullptr) if (layerManager->getRoot() != nullptr)
{ {
treeWidget->root = layerManager->getRoot(); treeWidget->root = layerManager->getRoot();
@ -49,6 +59,11 @@ EditorWidgetItem::~EditorWidgetItem()
void EditorWidgetItem::paintEvent(QPaintEvent *event) void EditorWidgetItem::paintEvent(QPaintEvent *event)
{ {
QPainter painter(this);
// 设置画刷的颜色为灰色,并填充整个窗口区域
painter.setBrush(Qt::gray);
painter.drawRect(this->rect());
} }
void EditorWidgetItem::onLayerChange(LayerWrapper *layer) void EditorWidgetItem::onLayerChange(LayerWrapper *layer)

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "ElementManager.h" #include "ElementManager.h"
#include "ElementPoolWidget.h"
#include "InfoDisplayWidget.h" #include "InfoDisplayWidget.h"
#include "LayerManager.h" #include "LayerManager.h"
#include "LayerTreeWidget.h" #include "LayerTreeWidget.h"
@ -23,7 +24,8 @@ class EditorWidgetItem : public QWidget
Ui::EditorWidgetItem ui; Ui::EditorWidgetItem ui;
LayerTreeWidget *treeWidget; LayerTreeWidget *treeWidget;
QTabWidget *tabWidget; QTabWidget *tabWidget;
InfoDisplayWidget *layerInfoDisplayWidget, *elementInfoDisplayWidget; InfoDisplayWidget* layerInfoDisplayWidget;
ElementPoolWidget* elementInfoDisplayWidget;
// QT DATA PART // QT DATA PART
LayerWrapper *displayLayer; LayerWrapper *displayLayer;
GraphicElement *displayElement; GraphicElement *displayElement;

View File

@ -10,7 +10,7 @@ ElementManager::ElementManager(QJsonObject source,Renderer::ElementRenderer* ren
elements.push_back(new GroupElement()); elements.push_back(new GroupElement());
else else
elements.push_back(new SimpleElement(elementJson.toObject())); elements.push_back(new SimpleElement(elementJson.toObject()));
(*elements.rbegin())->name = elementJson.toObject().value("name").toString();
(*elements.rbegin())->renderer = renderer; (*elements.rbegin())->renderer = renderer;
} }
for (auto element : elements) for (auto element : elements)
@ -19,10 +19,19 @@ ElementManager::ElementManager(QJsonObject source,Renderer::ElementRenderer* ren
void ElementManager::addElement(GraphicElement *element) void ElementManager::addElement(GraphicElement *element)
{ {
this->elements.push_back(element);
} }
void ElementManager::removeElement(GraphicElement *pElement) void ElementManager::removeElement(GraphicElement *pElement)
{ {
for (auto& element : elements)
{
if (element == pElement)
{
elements.erase(std::find(elements.begin(), elements.end(), element));
break;
}
}
} }
GraphicElement *ElementManager::getElementById(int index) GraphicElement *ElementManager::getElementById(int index)
@ -45,4 +54,49 @@ QJsonObject ElementManager::toJson() const
QJsonObject result; QJsonObject result;
result.insert("elements", elementsJson); result.insert("elements", elementsJson);
return result; return result;
}
int ElementManager::getElementIndex(GraphicElement* pelement)
{
for (int i = 0; i < elements.size(); i++)
if (elements[i] == pelement)
return i;
return -1;
}
int ElementManager::getLayerReferencedBy(const FolderLayerWrapper* layer)
{
for (int i = 0; i < elements.size(); i++)
if (typeid(*elements[i]) == typeid(GroupElement)) {
qDebug() << ((GroupElement*)elements[i])->sourceLayer;
qDebug() << layer;
qDebug() << "------------";
if (((GroupElement*)elements[i])->sourceLayer == layer)
return i;
}
return -1;
}
void ElementManager::removeElement(int index)
{
if (index < elements.size())
elements.erase(elements.begin() + index);
}
void ElementManager::createGroupElement(QString name, FolderLayerWrapper* sourceLayer) {
auto element = new GroupElement();
element->name = name;
element->setSourceLayer(sourceLayer);
addElement(element);
}
void ElementManager::createSimpleElement(QString name, QString filePath) {
QJsonObject json;
QJsonObject data;
data.insert("include", filePath);
json.insert("data", data);
auto element = new SimpleElement(json);
element->name = name;
addElement(element);
} }

View File

@ -8,10 +8,11 @@ using std::vector;
class LayerManager; class LayerManager;
class GraphicElement; class GraphicElement;
class Renderer::ElementRenderer; class Renderer::ElementRenderer;
class FolderLayerWrapper;
class ElementManager class ElementManager
{ {
private: public:
vector<GraphicElement *> elements; vector<GraphicElement *> elements;
public: public:
@ -19,9 +20,14 @@ class ElementManager
~ElementManager(); ~ElementManager();
void addElement(GraphicElement *element); void addElement(GraphicElement *element);
void removeElement(GraphicElement *pElement); void removeElement(GraphicElement *pElement);
void removeElement(int index);
void createGroupElement(QString name, FolderLayerWrapper* sourceLayer);
void createSimpleElement(QString name, QString filePath);
QJsonObject toJson()const; QJsonObject toJson()const;
/** /**
* only used in initialization * only used in initialization
*/ */
GraphicElement *getElementById(int index); GraphicElement *getElementById(int index);
int getElementIndex(GraphicElement* pElement);
int getLayerReferencedBy(const FolderLayerWrapper* layer);
}; };

View File

@ -0,0 +1,81 @@
#include "ElementPoolWidget.h"
ElementPoolWidget::ElementPoolWidget(QWidget* parent)
: QWidget(parent)
{
elementManager = nullptr;
iconWidth = 120, iconHeight = 90;
pictureList = new QListWidget();
pictureList->setIconSize(QSize(iconWidth, iconHeight));
pictureList->setWindowFlags(Qt::FramelessWindowHint);
pictureList->setResizeMode(QListWidget::Adjust);
pictureList->setViewMode(QListWidget::IconMode);
pictureList->setMovement(QListWidget::Static);
pictureList->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
pictureList->setWrapping(true);
pictureList->setSpacing(5);
pictureList->setStyleSheet("QListWidget::Item:hover{background-color: #f5f5f5;border-radius:5px; }"
"QListWidget::item:selected{background-color:rgba(234,234,234,1);color:rgb(61,61,61);border:1px solid #778899;border-radius:2px; }"
"QScrollBar:vertical{width:6px}"
"QListWidget{outline:none;border:0px}");
pictureList->setFocusPolicy(Qt::NoFocus);
QLayout* layout = new QHBoxLayout();
layout->addWidget(pictureList);
setLayout(layout);
//pictureList->setFixedSize(600, 800);
connect(pictureList, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(pictureItemClicked(QListWidgetItem*)));
}
void ElementPoolWidget::setElementList(std::vector<GraphicElement*> elements) {
pictureList->clear();
this->elements = elements;
for (int index = 0; index < elements.size(); index++) {
//
//QString strPath = QString("C:\\Users\\86177\\Pictures\\Screenshots\\test.png");
//QPixmap itemPixmap(strPath);
//QPixmap itemPixmap(QSize(200, 200));
//itemPixmap.fill(Qt::red);
QPixmap itemPixmap = elements[index]->getPaintObject().getDetail();
qDebug() << this->parentWidget()->size();
//auto p = new QWidget();
//auto lb = new QLabel(p);
//lb->setPixmap(itemPixmap);
//lb->setFixedSize(1920, 1080);
//p->setFixedSize(1920, 1080);
//lb->show();
//p->show();
QListWidgetItem* pItem = new QListWidgetItem(
itemPixmap.scaled(QSize(iconWidth - 25, iconHeight - 25)),
elements[index]->name);
pItem->setSizeHint(QSize(iconWidth, iconHeight));
pictureList->insertItem(index, pItem);
}
if(elements.size() > 0)
pictureList->setCurrentRow(0),
currentIndex = 0;
}
ElementPoolWidget::~ElementPoolWidget() {
}
int ElementPoolWidget::pictureItemClicked(QListWidgetItem* item) {
//qDebug() << pictureList->currentRow();
currentIndex = pictureList->currentRow();
emit elementSelected(this->elements[pictureList->currentRow()]);
return pictureList->currentRow();
}
void ElementPoolWidget::setElementManager(ElementManager* element)
{
this->elementManager = element;
this->setElementList(this->elementManager->elements);
}
void ElementPoolWidget::refresh() {
this->setElementList(this->elementManager->elements);
// update();
}

View File

@ -0,0 +1,32 @@
#pragma once
#include <QWidget>
#include <vector>
#include <GraphicElement.h>
#include <QListWidget>
#include <ElementManager.h>
#include <QLayout>
class ElementPoolWidget : public QWidget
{
Q_OBJECT
private:
std::vector<GraphicElement*> elements;
QListWidget* pictureList;
int iconWidth, iconHeight;
ElementManager* elementManager;
public:
int currentIndex = -1;
ElementPoolWidget(QWidget* parent = nullptr);
void setElementList(std::vector<GraphicElement*> elementList);
void setElementManager(ElementManager* element);
~ElementPoolWidget();
signals:
void elementSelected(GraphicElement* element);
public slots:
int pictureItemClicked(QListWidgetItem* item);
void refresh();
};

View File

@ -43,10 +43,11 @@ PixelPath GroupElement::getPaintObject() const
} }
//TODO: apply styles and send back //TODO: apply styles and send back
PixelPath SimpleElement::getPaintObject(std::vector<Renderer::ElementStyleStrokeDemo> styles) const { PixelPath SimpleElement::getPaintObject(std::vector<std::shared_ptr<LayerStyle>>* styles) const {
PixelPath result; PixelPath result;
Renderer::ElementStyleStrokeDemo demo(2); Renderer::ElementStyleStrokeDemo demo(2);
auto [img, mov] = renderer->drawElement(painterPath, demo, 1.0, false); auto [img, mov] = renderer->drawElement(painterPath, demo, 1.0);
//qDebug() << mov;
//qDebug() << img << " ------"; //qDebug() << img << " ------";
result.addImage(img, mov); result.addImage(img, mov);
//result.addPath(painterPath); //result.addPath(painterPath);
@ -59,7 +60,7 @@ PixelPath SimpleElement::getPaintObject(std::vector<Renderer::ElementStyleStroke
return result; return result;
} }
PixelPath GroupElement::getPaintObject(std::vector<Renderer::ElementStyleStrokeDemo> styles) const { PixelPath GroupElement::getPaintObject(std::vector<std::shared_ptr<LayerStyle>>* styles) const {
return getPaintObject(); return getPaintObject();
} }

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "LayerWrapper.h" #include "LayerWrapper.h"
#include "LayerStyle.h"
#include <QJsonArray> #include <QJsonArray>
#include <QJsonObject> #include <QJsonObject>
#include <QPainterPath> #include <QPainterPath>
@ -26,7 +27,7 @@ public:
// TODO: ¸ÄΪBitmapPath // TODO: ¸ÄΪBitmapPath
virtual QJsonObject toJson() const; virtual QJsonObject toJson() const;
virtual PixelPath getPaintObject() const = 0; virtual PixelPath getPaintObject() const = 0;
virtual PixelPath getPaintObject(std::vector<Renderer::ElementStyleStrokeDemo>) const = 0; virtual PixelPath getPaintObject(std::vector<std::shared_ptr<LayerStyle>>*) const = 0;
}; };
class SimpleElement : public GraphicElement class SimpleElement : public GraphicElement
@ -39,9 +40,10 @@ private:
public: public:
SimpleElement(QJsonObject jsonSource); SimpleElement(QJsonObject jsonSource);
SimpleElement(QString filePath);
~SimpleElement() = default; ~SimpleElement() = default;
PixelPath getPaintObject() const override; PixelPath getPaintObject() const override;
PixelPath getPaintObject(std::vector<Renderer::ElementStyleStrokeDemo>) const override; PixelPath getPaintObject(std::vector<std::shared_ptr<LayerStyle>>*) const override;
}; };
class GroupElement : public GraphicElement class GroupElement : public GraphicElement
@ -54,7 +56,7 @@ public:
GroupElement(FolderLayerWrapper* mSourceLayer); GroupElement(FolderLayerWrapper* mSourceLayer);
~GroupElement() = default; ~GroupElement() = default;
PixelPath getPaintObject() const override; PixelPath getPaintObject() const override;
PixelPath getPaintObject(std::vector<Renderer::ElementStyleStrokeDemo>) const override; PixelPath getPaintObject(std::vector<std::shared_ptr<LayerStyle>>*) const override;
void setSourceLayer(FolderLayerWrapper* sourceLayer); void setSourceLayer(FolderLayerWrapper* sourceLayer);
}; };

View File

@ -11,10 +11,10 @@ LayerWrapper *LayerManager::getRoot() const
{ {
return root; return root;
} }
void LayerManager::paint(QPainter *painter, QSize size) const void LayerManager::paint(QPainter *painter, QSize size,LayerWrapper* selecetedLayer) const
{ {
auto p = root->getCache().resizedPixel(size); root->getCache();
painter->drawPixmap(0, 0, p); root->paint(painter);
} }
bool LayerManager::singleSelectedCheck() const bool LayerManager::singleSelectedCheck() const
{ {

View File

@ -32,7 +32,7 @@ class LayerManager
LayerManager() = default; LayerManager() = default;
LayerManager(QJsonObject source, ElementManager* elementManager); LayerManager(QJsonObject source, ElementManager* elementManager);
QJsonObject toJson() const; QJsonObject toJson() const;
void paint(QPainter *painter, QSize size) const; void paint(QPainter *painter, QSize size, LayerWrapper* selecetedLayer=nullptr) const;
bool rename(QString newName) const; bool rename(QString newName) const;
bool combine() const; bool combine() const;
// bool seperate() const; // bool seperate() const;

View File

@ -1,6 +1,103 @@
#include "LayerStyle.h" #include "LayerStyle.h"
#include <QHBoxLayout>
#include <QDialogButtonBox>
#include <QPushButton>
#include <QLabel>
#include <QLineEdit>
std::vector<Renderer::BaseStyle> StrokeElementStyle::toBaseStyles() const const std::vector<std::pair<QString, std::function<std::unique_ptr<LayerStyle>()>>> LayerStyle::types = {
{
QStringLiteral("Ãè±ß"),
[]() { return std::make_unique<StrokeElementLayerStyle>(); }
},
{
QStringLiteral("Ìî³ä"),
[]() { return std::make_unique<FillElementLayerStyle>(); }
}
};
std::vector<Renderer::BaseStyle> StrokeElementLayerStyle::toBaseStyles() const
{ {
return std::vector<Renderer::BaseStyle>(); return std::vector<Renderer::BaseStyle>();
} }
QString StrokeElementLayerStyle::getStyleName() const
{
return QStringLiteral("Ãè±ß");
}
QWidget* StrokeElementLayerStyle::getInputWidget() const
{
// TODO
QLabel* le = new QLabel;
le->setText(QStringLiteral("Ãè±ß"));
return le;
}
QWidget* StrokeElementLayerStyle::getListDisplayWidget() const
{
QWidget* w = new QWidget;
QLabel* name = new QLabel(w);
name->setText(QStringLiteral("Ãè±ß"));
QHBoxLayout* layout = new QHBoxLayout(w);
layout->setMargin(0);
layout->addWidget(name);
return w;
}
StrokeElementLayerStyle::StrokeElementLayerStyle(const StrokeElementLayerStyle& other)
{
materialStyles = std::vector<std::shared_ptr<Renderer::MaterialStyleStroke>>(other.materialStyles.size());
for (size_t i = 0; i < other.materialStyles.size(); i++)
{
materialStyles[i] = std::make_shared<Renderer::MaterialStyleStroke>(*other.materialStyles[i]);
}
}
std::unique_ptr<LayerStyle> StrokeElementLayerStyle::clonePtr() const
{
return std::make_unique<StrokeElementLayerStyle>(StrokeElementLayerStyle(*this));
}
std::vector<Renderer::BaseStyle> FillElementLayerStyle::toBaseStyles() const
{
return std::vector<Renderer::BaseStyle>();
}
QString FillElementLayerStyle::getStyleName() const
{
return QStringLiteral("Ìî³ä");
}
QWidget* FillElementLayerStyle::getInputWidget() const
{
// TODO
QLineEdit* name = new QLineEdit;
name->setText(QStringLiteral("Ìî³ä"));
return name;
}
QWidget* FillElementLayerStyle::getListDisplayWidget() const
{
QWidget* w = new QWidget;
QLabel* name = new QLabel(w);
name->setText(QStringLiteral("Ìî³ä"));
QHBoxLayout* layout = new QHBoxLayout(w);
layout->setMargin(0);
layout->addWidget(name);
return w;
}
FillElementLayerStyle::FillElementLayerStyle(const FillElementLayerStyle& other)
{
materialStyles = std::vector<std::shared_ptr<Renderer::MaterialStyleFill>>(other.materialStyles.size());
for (size_t i = 0; i < other.materialStyles.size(); i++)
{
materialStyles[i] = std::make_shared<Renderer::MaterialStyleFill>(*other.materialStyles[i]);
}
}
std::unique_ptr<LayerStyle> FillElementLayerStyle::clonePtr() const
{
return std::make_unique<FillElementLayerStyle>(FillElementLayerStyle(*this));
}

View File

@ -1,24 +1,56 @@
#pragma once #pragma once
#include <map>
#include <functional>
#include <utility>
#include <QWidget>
#include <QObject>
#include <QListWidget>
#include "../Renderer/Painting/ElementStyle.h" #include "../Renderer/Painting/ElementStyle.h"
#include "../Renderer/Painting/MaterialStyleStroke.h" #include "../Renderer/Painting/MaterialStyleStroke.h"
#include "../Renderer/Painting/MaterialStyleFill.h"
/**
* StylegetInputWidget()
* StylegetInputWidget()
*
* LayerStyleElementStylestyle
*
*/
class LayerStyle class LayerStyle
{ {
public: public:
virtual void apply() = 0; const static std::vector<std::pair<QString, std::function<std::unique_ptr<LayerStyle>()>>> types;
virtual QString getStyleName() const = 0;
virtual QWidget* getInputWidget() const = 0;
virtual QWidget* getListDisplayWidget() const = 0;
virtual ~LayerStyle() {};
virtual std::unique_ptr<LayerStyle> clonePtr() const = 0;
}; };
struct EditorStrokeMaterialStyle class StrokeElementLayerStyle : public Renderer::ElementStyle, public LayerStyle
{
float applyWidth;
Renderer::StrokeType strokeType;
Renderer::StrokeEndType endType;
std::shared_ptr<Renderer::MaterialStroke> materialStroke;
};
class StrokeElementStyle : Renderer::ElementStyle
{ {
public: public:
virtual std::vector<Renderer::BaseStyle> toBaseStyles() const override; std::vector<Renderer::BaseStyle> toBaseStyles() const override;
std::vector<EditorStrokeMaterialStyle> materialStyles; QString getStyleName() const override;
QWidget* getInputWidget() const override;
QWidget* getListDisplayWidget() const override;
StrokeElementLayerStyle() = default;
StrokeElementLayerStyle(const StrokeElementLayerStyle& other);
~StrokeElementLayerStyle() = default;
std::vector<std::shared_ptr<Renderer::MaterialStyleStroke>> materialStyles;
std::unique_ptr<LayerStyle> clonePtr() const override;
};
class FillElementLayerStyle : public Renderer::ElementStyle, public LayerStyle
{
public:
std::vector<Renderer::BaseStyle> toBaseStyles() const override;
QString getStyleName() const override;
QWidget* getInputWidget() const override;
QWidget* getListDisplayWidget() const override;
FillElementLayerStyle() = default;
FillElementLayerStyle(const FillElementLayerStyle& other);
~FillElementLayerStyle() = default;
std::vector<std::shared_ptr<Renderer::MaterialStyleFill>> materialStyles;
std::unique_ptr<LayerStyle> clonePtr() const override;
}; };

View File

@ -23,16 +23,22 @@ FolderLayerWrapper*LayerWrapper::getParent() const
return this == nullptr ? nullptr : this->parent; return this == nullptr ? nullptr : this->parent;
} }
PixelPath LayerWrapper::getCache() PixelPath LayerWrapper::getCache(LayerWrapper* selectedLayer)
{ {
this->refresh(); this->refresh(selectedLayer);
if (selectedLayer == this)
{
this->cache.highLight();
}
return cache; return cache;
} }
// TODO: undone // TODO: undone
LayerWrapper::LayerWrapper(QJsonObject json, FolderLayerWrapper*parent) LayerWrapper::LayerWrapper(QJsonObject json, FolderLayerWrapper*parent, ElementManager* elementManager)
{ {
this->parent = parent; this->parent = parent;
this->elementManager = elementManager;
this->qTreeWidgetItem = new QTreeWidgetItem();
auto transformJson = json.value("transform").toObject(); auto transformJson = json.value("transform").toObject();
property.name = json.value("name").toString(); property.name = json.value("name").toString();
property.offset = {transformJson.value("offset").toObject().value("x").toDouble(), property.offset = {transformJson.value("offset").toObject().value("x").toDouble(),
@ -43,7 +49,7 @@ LayerWrapper::LayerWrapper(QJsonObject json, FolderLayerWrapper*parent)
} }
FolderLayerWrapper::FolderLayerWrapper(QJsonObject json, ElementManager *elementManager, FolderLayerWrapper*parent) FolderLayerWrapper::FolderLayerWrapper(QJsonObject json, ElementManager *elementManager, FolderLayerWrapper*parent)
: LayerWrapper(json, parent) : LayerWrapper(json, parent, elementManager)
{ {
qDebug() << json.value("name").toString() << " " << this; qDebug() << json.value("name").toString() << " " << this;
QJsonArray childrenJson = json.value("children").toArray(); QJsonArray childrenJson = json.value("children").toArray();
@ -73,6 +79,7 @@ LeafLayerWrapper::LeafLayerWrapper(QJsonObject json, ElementManager *elementMana
int elementIndex = json.value("element").toInt(); int elementIndex = json.value("element").toInt();
wrappedElement = elementManager->getElementById(elementIndex); wrappedElement = elementManager->getElementById(elementIndex);
} }
void LayerWrapper::SimpleProperty::apply(PixelPath&cache) const void LayerWrapper::SimpleProperty::apply(PixelPath&cache) const
{ {
QTransform trans; QTransform trans;
@ -81,32 +88,48 @@ void LayerWrapper::SimpleProperty::apply(PixelPath&cache) const
//qDebug() << name << " " << cache.boundingRect().center(); //qDebug() << name << " " << cache.boundingRect().center();
//qDebug() << name << " " << cache.boundingRect(); //qDebug() << name << " " << cache.boundingRect();
trans.translate(centerX, centerY); trans.translate(centerX, centerY);
trans.scale(scale.x(), scale.y());
trans.rotate(rotation);
trans.translate(-centerX, -centerY);
trans.translate(offset.x(), offset.y()); trans.translate(offset.x(), offset.y());
trans.rotate(rotation);
trans.scale(scale.x(), scale.y());
trans.translate(-centerX, -centerY);
cache = cache.trans(trans); cache = cache.trans(trans);
} }
void LayerWrapper::refresh()
QTransform LayerWrapper::getTransform()
{
QTransform trans;
double centerX = cache.getBoundingRect().center().x();
double centerY = cache.getBoundingRect().center().y();
//qDebug() << name << " " << cache.boundingRect().center();
//qDebug() << name << " " << cache.boundingRect();
trans.translate(centerX, centerY);
trans.translate(property.offset.x(), property.offset.y());
trans.rotate(property.rotation);
trans.scale(property.scale.x(), property.scale.y());
trans.translate(-centerX, -centerY);
return trans;
}
void LayerWrapper::refresh(LayerWrapper* layer)
{ {
property.apply(cache); property.apply(cache);
} }
void FolderLayerWrapper::refresh() void FolderLayerWrapper::refresh(LayerWrapper* layer)
{ {
cache.clear(); cache.clear();
for (auto& child : children) { for (auto& child : children) {
cache.addPath(child.get()->getCache()); cache.addPath(child.get()->getCache(layer));
} }
LayerWrapper::refresh(); LayerWrapper::refresh();
} }
void LeafLayerWrapper::refresh() void LeafLayerWrapper::refresh(LayerWrapper* layer)
{ {
cache.clear(); cache.clear();
if (wrappedElement != nullptr) if (wrappedElement != nullptr)
{ {
cache.addPath(wrappedElement->getPaintObject(this->styles)); cache.addPath(wrappedElement->getPaintObject(&(this->styles)));
} }
LayerWrapper::refresh(); LayerWrapper::refresh();
} }
@ -119,22 +142,22 @@ void LayerWrapper::setParent(FolderLayerWrapper* newParent)
void FolderLayerWrapper::removeAllChild() void FolderLayerWrapper::removeAllChild()
{ {
children.clear(); children.clear();
qTreeWidgetItem.takeChildren(); qTreeWidgetItem->takeChildren();
} }
void LayerWrapper::del() { void LayerWrapper::del() {
qDebug() << "LayerWrapper::del()"; qDebug() << "LayerWrapper::del()";
if (parent != nullptr){ if (parent != nullptr){
qTreeWidgetItem.takeChildren(); qTreeWidgetItem->takeChildren();
parent->qTreeWidgetItem.removeChild(&qTreeWidgetItem); parent->qTreeWidgetItem->removeChild(qTreeWidgetItem);
} }
} }
void LayerWrapper::delSelf() { void LayerWrapper::delSelf() {
qDebug() << "LayerWrapper::delSelf()"; qDebug() << "LayerWrapper::delSelf()";
if (parent != nullptr) { if (parent != nullptr) {
qTreeWidgetItem.takeChildren(); qTreeWidgetItem->takeChildren();
parent->qTreeWidgetItem.removeChild(&qTreeWidgetItem); parent->qTreeWidgetItem->removeChild(qTreeWidgetItem);
} }
} }
@ -154,7 +177,7 @@ void FolderLayerWrapper::delSelf() {
qDebug() << this; qDebug() << this;
for (auto& child : this->children) { for (auto& child : this->children) {
this->parent->addChild(child); this->parent->addChild(child);
this->parent->qTreeWidgetItem.addChild(&child.get()->qTreeWidgetItem); this->parent->qTreeWidgetItem->addChild(child.get()->qTreeWidgetItem);
child->setParent(this->parent); child->setParent(this->parent);
} }
while (!this->children.empty()) { while (!this->children.empty()) {
@ -166,18 +189,18 @@ void FolderLayerWrapper::delSelf() {
QTreeWidgetItem* LayerWrapper::getQTreeItem() QTreeWidgetItem* LayerWrapper::getQTreeItem()
{ {
this->qTreeWidgetItem.setText(0, this->property.name); this->qTreeWidgetItem->setText(0, this->property.name);
this->qTreeWidgetItem.setData(0, Qt::UserRole, QVariant::fromValue(this)); this->qTreeWidgetItem->setData(0, Qt::UserRole, QVariant::fromValue(this));
return &this->qTreeWidgetItem; return this->qTreeWidgetItem;
} }
QTreeWidgetItem* FolderLayerWrapper::getQTreeItem() QTreeWidgetItem* FolderLayerWrapper::getQTreeItem()
{ {
while (this->qTreeWidgetItem.childCount() > 0) { while (this->qTreeWidgetItem->childCount() > 0) {
this->qTreeWidgetItem.removeChild(this->qTreeWidgetItem.child(0)); this->qTreeWidgetItem->removeChild(this->qTreeWidgetItem->child(0));
} }
for (auto& child : this->children) { for (auto& child : this->children) {
this->qTreeWidgetItem.addChild(child->getQTreeItem()); this->qTreeWidgetItem->addChild(child->getQTreeItem());
} }
return LayerWrapper::getQTreeItem(); return LayerWrapper::getQTreeItem();
} }
@ -204,8 +227,8 @@ QJsonObject FolderLayerWrapper::toJson() const
childrenJson.push_back(child->toJson()); childrenJson.push_back(child->toJson());
json.insert("children", childrenJson); json.insert("children", childrenJson);
json.insert("is-folder", true); json.insert("is-folder", true);
if(this->referencedBy != -1) if(this->getReferencedBy() != -1)
json.insert("referenced-by", this->referencedBy); json.insert("referenced-by", this->getReferencedBy());
else else
json.insert("referenced-by", QJsonValue()); json.insert("referenced-by", QJsonValue());
return json; return json;
@ -217,4 +240,41 @@ QJsonObject LeafLayerWrapper::toJson() const
json.insert("element", wrappedElement->index); json.insert("element", wrappedElement->index);
json.insert("is-folder", false); json.insert("is-folder", false);
return json; return json;
}
int FolderLayerWrapper::getReferencedBy()const
{
if (this->elementManager != nullptr)
return this->elementManager->getLayerReferencedBy(this);
else
return -1;
}
void LayerWrapper::paint(QPainter* painter)
{
}
void FolderLayerWrapper::paint(QPainter* painter)
{
for (auto& child : children)
child->paint(painter);
}
void LeafLayerWrapper::paint(QPainter* painter)
{
if (wrappedElement != nullptr)
{
//painter->save();
QTransform trans;
LayerWrapper* layer = this;
while (layer != nullptr) {
trans *= layer->getTransform();
layer = layer->getParent();
}
auto p = wrappedElement->getPaintObject(&this->styles);
p.trans(trans);
painter->drawPixmap(0, 0, p.getPixmap());
//painter->restore();
}
} }

View File

@ -28,12 +28,13 @@ class LayerWrapper
protected: protected:
FolderLayerWrapper* parent; FolderLayerWrapper* parent;
QPointF referencePoint; QPointF referencePoint;
ElementManager* elementManager;
// vector<LayerStyle> styles; // vector<LayerStyle> styles;
// TODO: 将cache移到子类对Leaf用ComposedPainterPath对Folder用FolderBitmapPath // TODO: 将cache移到子类对Leaf用ComposedPainterPath对Folder用FolderBitmapPath
PixelPath cache; PixelPath cache;
public: public:
QTreeWidgetItem qTreeWidgetItem; QTreeWidgetItem* qTreeWidgetItem;
struct SimpleProperty struct SimpleProperty
{ {
QString name = ""; QString name = "";
@ -46,13 +47,15 @@ class LayerWrapper
void apply(PixelPath&cache) const; void apply(PixelPath&cache) const;
} property; } property;
virtual void setParent(FolderLayerWrapper*newParent); virtual void setParent(FolderLayerWrapper*newParent);
virtual void refresh(); virtual void refresh(LayerWrapper* layer = nullptr);
virtual QTreeWidgetItem* getQTreeItem(); virtual QTreeWidgetItem* getQTreeItem();
// TODO: 将QPainterPath改为BitmapPath/QImage或者直接将其删除绘制时直接使用BitmapPath的paint方法 // TODO: 将QPainterPath改为BitmapPath/QImage或者直接将其删除绘制时直接使用BitmapPath的paint方法
virtual PixelPath getCache(); virtual PixelPath getCache(LayerWrapper* selectedLayer=nullptr);
QTransform getTransform();
FolderLayerWrapper*getParent() const; // invoke by manager, then invoke parent's applyStyles FolderLayerWrapper*getParent() const; // invoke by manager, then invoke parent's applyStyles
LayerWrapper(QJsonObject json, FolderLayerWrapper*parent); LayerWrapper(QJsonObject json, FolderLayerWrapper*parent, ElementManager* elementManager=nullptr);
LayerWrapper() = default; LayerWrapper() = default;
virtual void paint(QPainter* painter);
// TODO : export Function // TODO : export Function
// virtual LayerWrapper *addChild() = 0; // Leaf Child Only // virtual LayerWrapper *addChild() = 0; // Leaf Child Only
// virtual LayerWrapper *addParent() = 0; // Folder Parent Only // virtual LayerWrapper *addParent() = 0; // Folder Parent Only
@ -74,7 +77,7 @@ class FolderLayerWrapper : public LayerWrapper
public: public:
~FolderLayerWrapper() = default; ~FolderLayerWrapper() = default;
void refresh() override; void refresh(LayerWrapper* layer=nullptr) override;
FolderLayerWrapper() = default; FolderLayerWrapper() = default;
FolderLayerWrapper(QJsonObject json, ElementManager *elementManager, FolderLayerWrapper*parent); FolderLayerWrapper(QJsonObject json, ElementManager *elementManager, FolderLayerWrapper*parent);
void addChild(shared_ptr<LayerWrapper> child); void addChild(shared_ptr<LayerWrapper> child);
@ -84,20 +87,24 @@ class FolderLayerWrapper : public LayerWrapper
void delSelf() override; void delSelf() override;
QTreeWidgetItem* getQTreeItem() override; QTreeWidgetItem* getQTreeItem() override;
QJsonObject toJson() const override; QJsonObject toJson() const override;
int getReferencedBy()const;
void paint(QPainter* painter) override;
}; };
class LeafLayerWrapper : public LayerWrapper class LeafLayerWrapper : public LayerWrapper
{ {
public: public:
GraphicElement *wrappedElement; GraphicElement *wrappedElement;
const vector<Renderer::ElementStyleStrokeDemo> styles; //const vector<Renderer::ElementStyleStrokeDemo> styles;
vector<std::shared_ptr<LayerStyle>> styles;
public: public:
~LeafLayerWrapper() = default; ~LeafLayerWrapper() = default;
void refresh() override; void refresh(LayerWrapper* layer = nullptr) override;
LeafLayerWrapper() = default; LeafLayerWrapper() = default;
LeafLayerWrapper(QJsonObject json, ElementManager *elementManager, FolderLayerWrapper*parent); LeafLayerWrapper(QJsonObject json, ElementManager *elementManager, FolderLayerWrapper*parent);
QJsonObject toJson() const override; QJsonObject toJson() const override;
void paint(QPainter* painter) override;
}; };
Q_DECLARE_METATYPE(LayerWrapper *) Q_DECLARE_METATYPE(LayerWrapper *)

View File

@ -32,10 +32,15 @@ QPixmap PixelPath::getPixmap() const
return pixmap; return pixmap;
} }
QPainterPath PixelPath::getPainterPath() const {
return painterPath;
}
void PixelPath::addPath(const PixelPath& path) void PixelPath::addPath(const PixelPath& path)
{ {
QPainter painter(&pixmap); QPainter painter(&pixmap);
painter.drawPixmap(0, 0, path.getPixmap()); painter.drawPixmap(0, 0, path.getPixmap());
this->painterPath.addPath(path.getPainterPath());
boundingRect = boundingRect.united(path.getBoundingRect()); boundingRect = boundingRect.united(path.getBoundingRect());
} }
@ -46,6 +51,7 @@ void PixelPath::addPath(const QPainterPath& path)
painter.setRenderHint(QPainter::HighQualityAntialiasing); painter.setRenderHint(QPainter::HighQualityAntialiasing);
painter.setPen(QPen(Qt::black,1)); painter.setPen(QPen(Qt::black,1));
painter.drawPath(path); painter.drawPath(path);
this->painterPath.addPath(path);
boundingRect = boundingRect.united(path.boundingRect()); boundingRect = boundingRect.united(path.boundingRect());
} }
@ -83,5 +89,32 @@ QPixmap PixelPath::resizedPixel(QSize size)const
painter.setRenderHint(QPainter::SmoothPixmapTransform); painter.setRenderHint(QPainter::SmoothPixmapTransform);
painter.setRenderHint(QPainter::HighQualityAntialiasing); painter.setRenderHint(QPainter::HighQualityAntialiasing);
painter.drawPixmap(0, 0, pixmap.scaled(size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); painter.drawPixmap(0, 0, pixmap.scaled(size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
return result; return result;
}
QPixmap PixelPath::getDetail()const
{
QPixmap result;
auto rect = boundingRect.toRect();
rect.setHeight(rect.height() + 20);
rect.setWidth(rect.width() + 20);
qDebug() << rect;
result = pixmap.copy(rect);
return result;
}
void PixelPath::highLight()
{
// 创建一个QPainter对象关联到QPixmap对象
QPainter painter(&pixmap);
// 设置画笔的颜色、宽度和样式
painter.setPen(QPen(Qt::black, 1, Qt::DashLine));
// 绘制一个矩形,指定左上角和右下角的坐标
painter.drawRect(boundingRect);
// 结束绘制
painter.end();
} }

View File

@ -10,17 +10,21 @@ class PixelPath
private: private:
QRectF boundingRect; QRectF boundingRect;
QPixmap pixmap; QPixmap pixmap;
QPainterPath painterPath;
int w,h; int w,h;
public: public:
PixelPath(int w=1920, int h= 1080); PixelPath(int w=1080, int h= 1080);
PixelPath(QPainterPath painterPath,int w = 1920, int h = 1080); PixelPath(QPainterPath painterPath,int w = 1080, int h = 1080);
~PixelPath() = default; ~PixelPath() = default;
QRectF getBoundingRect() const; QRectF getBoundingRect() const;
QPixmap getPixmap() const; QPixmap getPixmap() const;
QPainterPath getPainterPath() const;
void addPath(const PixelPath& path); void addPath(const PixelPath& path);
void addPath(const QPainterPath& path); void addPath(const QPainterPath& path);
void addImage(const QImage& image,const QPointF& pos); void addImage(const QImage& image,const QPointF& pos);
void clear(); void clear();
PixelPath trans(QTransform& mat)const; PixelPath trans(QTransform& mat)const;
QPixmap resizedPixel(QSize size)const; QPixmap resizedPixel(QSize size)const;
QPixmap getDetail()const;
void highLight();
}; };

View File

@ -2,7 +2,8 @@
PreviewWindow::PreviewWindow(QWidget *parent) : QOpenGLWidget(parent) PreviewWindow::PreviewWindow(QWidget *parent) : QOpenGLWidget(parent)
{ {
this->renderer = new Renderer::ElementRenderer(this); this->setFixedSize(QSize(1080, 1080));
this->renderer = Renderer::ElementRenderer::instance();
QSurfaceFormat surfaceFormat; QSurfaceFormat surfaceFormat;
surfaceFormat.setSamples(16); surfaceFormat.setSamples(16);
setFormat(surfaceFormat); setFormat(surfaceFormat);
@ -10,6 +11,7 @@ PreviewWindow::PreviewWindow(QWidget *parent) : QOpenGLWidget(parent)
painter->setRenderHint(QPainter::SmoothPixmapTransform); painter->setRenderHint(QPainter::SmoothPixmapTransform);
painter->setRenderHint(QPainter::HighQualityAntialiasing); painter->setRenderHint(QPainter::HighQualityAntialiasing);
layerManager = nullptr; layerManager = nullptr;
currentLayer = nullptr;
} }
void PreviewWindow::initialize(LayerManager *layerManager,QSize windowSize) void PreviewWindow::initialize(LayerManager *layerManager,QSize windowSize)
@ -36,7 +38,6 @@ void PreviewWindow::show()
void PreviewWindow::initializeGL() void PreviewWindow::initializeGL()
{ {
this->renderer->initialize();
initializeOpenGLFunctions(); initializeOpenGLFunctions();
} }
@ -47,7 +48,7 @@ void PreviewWindow::paintGL()
painter->begin(this); painter->begin(this);
painter->setRenderHint(QPainter::Antialiasing); painter->setRenderHint(QPainter::Antialiasing);
painter->setRenderHint(QPainter::HighQualityAntialiasing); painter->setRenderHint(QPainter::HighQualityAntialiasing);
layerManager->paint(painter,this->size()); layerManager->paint(painter,this->size(),currentLayer);
painter->end(); painter->end();
} }
@ -57,4 +58,50 @@ void PreviewWindow::resizeGL(int w, int h)
Renderer::ElementRenderer* const PreviewWindow::getRenderer()const { Renderer::ElementRenderer* const PreviewWindow::getRenderer()const {
return this->renderer; return this->renderer;
}
void PreviewWindow::currentLayerChanged(LayerWrapper* layer)
{
this->currentLayer = layer;
}
void PreviewWindow::refresh()
{
this->repaint();
}
void PreviewWindow::mousePressEvent(QMouseEvent* event)
{
// 当鼠标按下时,记录当前的位置
m_lastPos = event->pos();
}
void PreviewWindow::mouseMoveEvent(QMouseEvent* event)
{
// 当鼠标移动时,计算移动的距离,并根据需要更新图形的状态
int dx = event->x() - m_lastPos.x();
int dy = event->y() - m_lastPos.y();
if (currentLayer != nullptr) {
if (event->buttons() & Qt::LeftButton) {
// 如果按下的是左键,那么平移图形
currentLayer->property.offset.setX(currentLayer->property.offset.x() + dx);
currentLayer->property.offset.setY(currentLayer->property.offset.y() + dy);
qDebug() << dx << "----" << dy;
emit layerInfoChanged();
}
else if (event->buttons() & Qt::RightButton) {
// 如果按下的是右键,那么旋转图形
qreal angle = -sqrt(dx * dx + dy * dy) / 1.0;
currentLayer->property.rotation += angle;
emit layerInfoChanged();
}
}
// 更新上一次的位置
m_lastPos = event->pos();
this->repaint();
}
void PreviewWindow::mouseReleaseEvent(QMouseEvent* event)
{
// 当鼠标释放时,不做任何操作
} }

View File

@ -7,6 +7,7 @@
#include <QJsonObject> #include <QJsonObject>
#include <QJsonValue> #include <QJsonValue>
#include <QOpenGLFunctions> #include <QOpenGLFunctions>
#include <QMouseEvent>
#include <QOpenGLWidget> #include <QOpenGLWidget>
#include "../Renderer/Preview/ElementRenderer.h" #include "../Renderer/Preview/ElementRenderer.h"
@ -19,7 +20,13 @@ class PreviewWindow : public QOpenGLWidget, protected QOpenGLFunctions
LayerManager *layerManager; LayerManager *layerManager;
Renderer::ElementRenderer* renderer; Renderer::ElementRenderer* renderer;
QSize logicalSize; QSize logicalSize;
QRectF viewportRect;
LayerWrapper* currentLayer;
QPointF m_lastPos;
void mousePressEvent(QMouseEvent* event) override;
void mouseMoveEvent(QMouseEvent* event) override;
void mouseReleaseEvent(QMouseEvent* event) override;
public: public:
PreviewWindow(QWidget *parent = nullptr); PreviewWindow(QWidget *parent = nullptr);
void initialize(LayerManager *layerManager, QSize windowSize = QSize(1920, 1080)); void initialize(LayerManager *layerManager, QSize windowSize = QSize(1920, 1080));
@ -28,4 +35,11 @@ class PreviewWindow : public QOpenGLWidget, protected QOpenGLFunctions
void paintGL() override; void paintGL() override;
void resizeGL(int w, int h) override; void resizeGL(int w, int h) override;
Renderer::ElementRenderer* const getRenderer()const; Renderer::ElementRenderer* const getRenderer()const;
public slots:
void currentLayerChanged(LayerWrapper*);
void refresh();
signals:
void layerInfoChanged();
}; };

View File

@ -1,27 +1,26 @@
#include "InfoDisplayWidget.h" #include "InfoDisplayWidget.h"
#include "./EditorWidgetComponent/LayerStyleDialog.h"
#include <QLineEdit> #include <QLineEdit>
#include <QTextBlock> #include <QTextBlock>
#include <QListWidget> #include <QListWidget>
#include <QPushButton>
#include <QDialog> #include <QDialog>
#include <QComboBox>
#include <QDialogButtonBox> #include <QDialogButtonBox>
#include <qtmaterialraisedbutton.h>
#include <qtmaterialflatbutton.h>
void InfoDisplayWidget::setLayer(LayerWrapper *layer) void InfoDisplayWidget::setLayer(LayerWrapper *layer)
{ {
this->displayLayer = layer; this->displayLayer = layer;
generateLayerForm(); generateLayerForm();
} }
void InfoDisplayWidget::setElement(GraphicElement *element)
{
this->displayElement = element;
generateElementForm();
}
void InfoDisplayWidget::generateLayerForm() void InfoDisplayWidget::generateLayerForm()
{ {
QLayoutItem *item; QLayoutItem *item;
if (this->layout() != nullptr) if (this->layout() != nullptr)
{ {
while ((item = this->layout()->takeAt(0)) != nullptr) while (this->layout()->count() > 0 && (item = this->layout()->takeAt(0)) != nullptr)
{ {
delete item->widget(); delete item->widget();
delete item; delete item;
@ -47,26 +46,31 @@ void InfoDisplayWidget::generateLayerForm()
rotation->setValidator(new QIntValidator(-10000, 10000, this)); rotation->setValidator(new QIntValidator(-10000, 10000, this));
connect(rotation, &QLineEdit::textChanged, [=](QString content) { connect(rotation, &QLineEdit::textChanged, [=](QString content) {
this->displayLayer->property.rotation = content.toDouble(); this->displayLayer->property.rotation = content.toDouble();
emit requireRefreshElementWidget();
emit requireRefreshPreview(); emit requireRefreshPreview();
}); });
offsetX->setValidator(new QIntValidator(-10000, 10000, this)); offsetX->setValidator(new QIntValidator(-10000, 10000, this));
connect(offsetX, &QLineEdit::textChanged, [=](QString content) { connect(offsetX, &QLineEdit::textChanged, [=](QString content) {
this->displayLayer->property.offset = {content.toDouble(), this->displayLayer->property.offset.y()}; this->displayLayer->property.offset = {content.toDouble(), this->displayLayer->property.offset.y()};
emit requireRefreshElementWidget();
emit requireRefreshPreview(); emit requireRefreshPreview();
}); });
offsetY->setValidator(new QIntValidator(-10000, 10000, this)); offsetY->setValidator(new QIntValidator(-10000, 10000, this));
connect(offsetY, &QLineEdit::textChanged, [=](QString content) { connect(offsetY, &QLineEdit::textChanged, [=](QString content) {
this->displayLayer->property.offset = {this->displayLayer->property.offset.x(), content.toDouble()}; this->displayLayer->property.offset = {this->displayLayer->property.offset.x(), content.toDouble()};
emit requireRefreshElementWidget();
emit requireRefreshPreview(); emit requireRefreshPreview();
}); });
scaleX->setValidator(new QDoubleValidator(0.001, 1000, 4, this)); scaleX->setValidator(new QDoubleValidator(0.001, 1000, 4, this));
connect(scaleX, &QLineEdit::textChanged, [=](QString content) { connect(scaleX, &QLineEdit::textChanged, [=](QString content) {
this->displayLayer->property.scale = {content.toDouble(), this->displayLayer->property.scale.y()}; this->displayLayer->property.scale = {content.toDouble(), this->displayLayer->property.scale.y()};
emit requireRefreshElementWidget();
emit requireRefreshPreview(); emit requireRefreshPreview();
}); });
scaleY->setValidator(new QDoubleValidator(0.001, 1000, 4, this)); scaleY->setValidator(new QDoubleValidator(0.001, 1000, 4, this));
connect(scaleY, &QLineEdit::textChanged, [=](QString content) { connect(scaleY, &QLineEdit::textChanged, [=](QString content) {
this->displayLayer->property.scale = {this->displayLayer->property.scale.x(), content.toDouble()}; this->displayLayer->property.scale = {this->displayLayer->property.scale.x(), content.toDouble()};
emit requireRefreshElementWidget();
emit requireRefreshPreview(); emit requireRefreshPreview();
}); });
@ -78,78 +82,165 @@ void InfoDisplayWidget::generateLayerForm()
layout->addRow("scale-Y:", scaleY); layout->addRow("scale-Y:", scaleY);
layout->setRowWrapPolicy(QFormLayout::DontWrapRows); layout->setRowWrapPolicy(QFormLayout::DontWrapRows);
bool styleEnabled = true; LeafLayerWrapper* leafP = dynamic_cast<LeafLayerWrapper*>(this->displayLayer);
if (styleEnabled) { if (leafP) {
QListWidget* styleList = new QListWidget(this); QListWidget* styleList = new QListWidget(this);
QListWidgetItem* item = new QListWidgetItem("样式列表");
item->setFlags(Qt::NoItemFlags); QListWidgetItem* header = new QListWidgetItem;
styleList->addItem(item); QWidget* headerWidget = new QWidget(styleList);
static vector<QString> styleNames = { "样例1", "样例2", "样例3" }; QHBoxLayout* headerLayout = new QHBoxLayout;
auto createStyleItem = [this, styleList](int index) {
QLabel* headerLabel = new QLabel(headerWidget);
headerLabel->setText("样式列表");
headerLabel->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
//QtMaterialRaisedButton* addStyleButton = new QtMaterialRaisedButton("+", headerWidget);
QPushButton* addStyleButton = new QPushButton("+", headerWidget);
addStyleButton->setFixedSize(QSize(20, 20));
if (leafP->styles.size() >= LayerStyle::types.size())
{
addStyleButton->setDisabled(true);
}
else
{
connect(addStyleButton, &QPushButton::clicked, [&, leafP]() {
LayerStyleDialog* dialog = new LayerStyleDialog(nullptr, nullptr, &(leafP->styles));
dialog->exec();
if (dialog->layerStyle)
{
leafP->styles.push_back(dialog->layerStyle);
emit requireRefreshPreview();
emit requireSelfRefresh();
emit requireRefreshElementWidget();
}
dialog->deleteLater();
});
}
headerLayout->addWidget(headerLabel);
headerLayout->addWidget(addStyleButton);
headerLayout->setContentsMargins(5, 0, 5, 0);
headerWidget->setLayout(headerLayout);
header->setFlags(Qt::NoItemFlags);
styleList->addItem(header);
styleList->setItemWidget(header, headerWidget);
//static vector<QString> styleNames = { "样例1", "样例2", "样例3" };
// auto createStyleItem = [this, styleList](int index) {
// QListWidgetItem* item = new QListWidgetItem;
// QWidget* w = new QWidget;
// item->setSizeHint(QSize(50, 40));
// QHBoxLayout* layout = new QHBoxLayout;
// QPushButton* deleteButton = new QPushButton(w);
// QPushButton* detailButton = new QPushButton(w);
// QLabel* name = new QLabel(w);
// name->setText(styleNames[index]);
// detailButton->setText("...");
// detailButton->setFixedSize(QSize(20, 20));
// deleteButton->setText("×");
// deleteButton->setFixedSize(QSize(20, 20));
// connect(detailButton, &QPushButton::clicked, [styleList, item, this, index]() {
// QDialog dlg(this);
// dlg.setWindowTitle("样式详情");
// dlg.resize(400, 200);
// QGridLayout *contentLayout = new QGridLayout(&dlg);
// QLineEdit* name = new QLineEdit(styleNames[index], &dlg);
// auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Save | QDialogButtonBox::Cancel);
// contentLayout->addWidget(buttonBox);
// connect(buttonBox, &QDialogButtonBox::accepted, &dlg, &QDialog::accept);
// connect(buttonBox, &QDialogButtonBox::rejected, &dlg, &QDialog::reject);
// bool updateStyle = dlg.exec();
// if (updateStyle) {
// styleNames[index] = name->text();
// qDebug() << name->text();
// // 在此处修改新样式信息至内存
// emit requireRefreshPreview();
// emit requireSelfRefresh();
// }
// });
// connect(deleteButton, &QPushButton::clicked, [styleList,item,this]() {
// styleList->removeItemWidget(item);
// delete item;
// // 删除layer对应样式
// emit requireRefreshPreview();
// emit requireSelfRefresh();
// });
// layout->addWidget(name);
// layout->addWidget(detailButton);
// layout->addWidget(deleteButton);
// w->setLayout(layout);
// styleList->addItem(item);
// styleList->setItemWidget(item, w);
// };
// for (int i = 0; i < styleNames.size(); i++)
// createStyleItem(i);
/*if (leafP->styles.empty())
{
leafP->styles.push_back(std::shared_ptr<LayerStyle>(new StrokeElementLayerStyle()));
}*/
std::vector<std::shared_ptr<LayerStyle>>* styles = &(leafP->styles);
for (auto styleIterator = styles->begin(); styleIterator != styles->end(); styleIterator++)
{
QListWidgetItem* item = new QListWidgetItem; QListWidgetItem* item = new QListWidgetItem;
QWidget* w = new QWidget; QWidget* w = new QWidget;
item->setSizeHint(QSize(50, 40)); item->setSizeHint(QSize(50, 40));
QHBoxLayout* layout = new QHBoxLayout; QHBoxLayout* layout = new QHBoxLayout;
QPushButton* deleteButton = new QPushButton(w); layout->setAlignment(Qt::AlignmentFlag::AlignRight);
//QtMaterialFlatButton* detailButton = new QtMaterialFlatButton(w);
//QtMaterialFlatButton* removeButton = new QtMaterialFlatButton(w);
QPushButton* detailButton = new QPushButton(w); QPushButton* detailButton = new QPushButton(w);
QLabel* name = new QLabel(w); QPushButton* removeButton = new QPushButton(w);
name->setText(styleNames[index]); detailButton->setText("...");
detailButton->setText("...");
detailButton->setFixedSize(QSize(20, 20)); detailButton->setFixedSize(QSize(20, 20));
deleteButton->setText("×"); removeButton->setText("×");
deleteButton->setFixedSize(QSize(20, 20)); removeButton->setFixedSize(QSize(20, 20));
connect(detailButton, &QPushButton::clicked, [styleList, item, this, index]() {
QDialog dlg(this); connect(detailButton, &QPushButton::clicked, this,
dlg.setWindowTitle("样式详情"); [this, styleIterator]()
dlg.resize(400, 200); {
QGridLayout *contentLayout = new QGridLayout(&dlg); LayerStyleDialog* dialog = new LayerStyleDialog(nullptr, *styleIterator);
QLineEdit* name = new QLineEdit(styleNames[index], &dlg); dialog->exec();
auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Save | QDialogButtonBox::Cancel);
contentLayout->addWidget(buttonBox); if (dialog->layerStyle)
connect(buttonBox, &QDialogButtonBox::accepted, &dlg, &QDialog::accept); {
connect(buttonBox, &QDialogButtonBox::rejected, &dlg, &QDialog::reject); (*styleIterator) = dialog->layerStyle;
bool updateStyle = dlg.exec(); emit requireRefreshPreview();
if (updateStyle) { emit requireSelfRefresh();
styleNames[index] = name->text(); emit requireRefreshElementWidget();
qDebug() << name->text(); }
// 在此处修改新样式信息至内存 dialog->deleteLater();
});
connect(removeButton, &QPushButton::clicked, this,
[this, styleIterator, styles]()
{
styles->erase(styleIterator);
emit requireRefreshPreview(); emit requireRefreshPreview();
emit requireSelfRefresh(); emit requireSelfRefresh();
} emit requireRefreshElementWidget();
}); });
connect(deleteButton, &QPushButton::clicked, [styleList,item,this]() {
styleList->removeItemWidget(item); QWidget* styleDisplayWidget = (*styleIterator)->getListDisplayWidget();
delete item; styleDisplayWidget->setParent(w);
// 删除layer对应样式 styleDisplayWidget->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
emit requireRefreshPreview();
emit requireSelfRefresh(); layout->addWidget(styleDisplayWidget);
});
layout->addWidget(name);
layout->addWidget(detailButton); layout->addWidget(detailButton);
layout->addWidget(deleteButton); layout->addWidget(removeButton);
w->setLayout(layout); w->setLayout(layout);
styleList->addItem(item); styleList->addItem(item);
styleList->setItemWidget(item, w); styleList->setItemWidget(item, w);
}; }
for (int i = 0; i < styleNames.size(); i++)
createStyleItem(i);
layout->addRow(styleList); layout->addRow(styleList);
} }
} }
this->setLayout(layout); this->setLayout(layout);
} }
void InfoDisplayWidget::generateElementForm()
{
}
void InfoDisplayWidget::triggerSelfRefresh() void InfoDisplayWidget::triggerSelfRefresh()
{ {
if (this->displayLayer != nullptr) if (this->displayLayer != nullptr)
this->generateLayerForm(); this->generateLayerForm();
if (this->displayElement != nullptr)
this->generateElementForm();
} }

View File

@ -4,19 +4,18 @@
#include <QFormLayout> #include <QFormLayout>
#include <QLabel> #include <QLabel>
#include <QWidget> #include <QWidget>
#include "ElementPoolWidget.h"
class InfoDisplayWidget : public QWidget class InfoDisplayWidget : public QWidget
{ {
Q_OBJECT Q_OBJECT
private: private:
LayerWrapper *displayLayer; LayerWrapper *displayLayer;
GraphicElement *displayElement;
public: public:
void setLayer(LayerWrapper *layer); void setLayer(LayerWrapper *layer);
void setElement(GraphicElement *element);
void generateLayerForm(); void generateLayerForm();
void generateElementForm();
public slots: public slots:
void triggerSelfRefresh(); void triggerSelfRefresh();
@ -24,6 +23,6 @@ class InfoDisplayWidget : public QWidget
signals: signals:
void requireRefreshPreview(); void requireRefreshPreview();
void requireSelfRefresh(); void requireSelfRefresh();
void requireRefreshElementWidget();
}; };

View File

@ -1,6 +1,8 @@
#include "LayerTreeWidget.h" #include "LayerTreeWidget.h"
#include <QInputDialog> #include <QInputDialog>
#include <QMenu> #include <QMenu>
#include "./EditorWidgetComponent/LayerCreateWidget.h"
LayerTreeWidget::LayerTreeWidget(QWidget *parent) LayerTreeWidget::LayerTreeWidget(QWidget *parent)
{ {
emit displayLayerChange(nullptr); emit displayLayerChange(nullptr);
@ -11,10 +13,14 @@ LayerTreeWidget::LayerTreeWidget(QWidget *parent)
connect(this, &QTreeWidget::customContextMenuRequested, this, &LayerTreeWidget::popMenu); connect(this, &QTreeWidget::customContextMenuRequested, this, &LayerTreeWidget::popMenu);
connect(this, &QTreeWidget::currentItemChanged, [=](QTreeWidgetItem *currentItem) { connect(this, &QTreeWidget::currentItemChanged, [=](QTreeWidgetItem *currentItem) {
this->selectedItem = currentItem; this->selectedItem = currentItem;
if(this->selectedItem !=nullptr) if (this->selectedItem != nullptr) {
emit displayLayerChange(this->selectedItem->data(0, Qt::UserRole).value<LayerWrapper *>()); auto layer = this->selectedItem->data(0, Qt::UserRole).value<LayerWrapper*>();
else emit displayLayerChange(layer);
emit displayLayerChange(nullptr); }
else {
emit displayLayerChange(nullptr);
}
emit requireRefreshPreview();
}); });
// connect(this, &QTreeWidget::itemDoubleClicked, this, &LayerTreeWidget::onItemDoubleClicked); // connect(this, &QTreeWidget::itemDoubleClicked, this, &LayerTreeWidget::onItemDoubleClicked);
} }
@ -35,32 +41,64 @@ void LayerTreeWidget::popMenu(const QPoint &pos)
QMenu menu; QMenu menu;
QTreeWidgetItem *item = itemAt(pos); QTreeWidgetItem *item = itemAt(pos);
this->selectedItem = item; this->selectedItem = item;
// TODO if (item != nullptr) {
menu.addAction(QString::fromLocal8Bit("创建子节点"), this, &LayerTreeWidget::onRenameEvent); auto layer = this->selectedItem->data(0, Qt::UserRole).value<LayerWrapper*>();
//if (item != root->getQTreeItem()) if (layer != nullptr) {
//{ if (typeid(*layer) == typeid(FolderLayerWrapper)) {
menu.addAction(QString::fromLocal8Bit("重命名"), this, &LayerTreeWidget::onRenameEvent); menu.addAction(QString::fromLocal8Bit("创建子节点"), this, [this, layer]() {
// menu.addAction("Copy", this, &LayerTreeWidget::onRenameEvent); auto dialog = new LayerCreateWidget(elementManager, this);
if (item != nullptr && item->childCount() > 0) connect(dialog, &LayerCreateWidget::LayerInfoReturned, this, [this, layer](QJsonObject jsonObj) {
menu.addAction(QString::fromLocal8Bit("删除(保留子节点)"), this, [this]() { auto folderLayer = dynamic_cast<FolderLayerWrapper*>(layer);
if (this->selectedItem == nullptr) LayerWrapper* newLayer;
return; if(jsonObj.value("is-folder").toBool())
auto layer = this->selectedItem->data(0, Qt::UserRole).value<LayerWrapper*>(); newLayer = new FolderLayerWrapper(jsonObj, this->elementManager, folderLayer);
layer->delSelf(); else
layer->getParent()->removeChild(layer); newLayer = new LeafLayerWrapper(jsonObj, this->elementManager, folderLayer);
this->refresh();
emit requireRefreshPreview(); folderLayer->addChild(std::shared_ptr<LayerWrapper>(newLayer));
}); folderLayer->qTreeWidgetItem->addChild(newLayer->getQTreeItem());
menu.addAction(QString::fromLocal8Bit("删除"), this, [this]() { qDebug() << jsonObj<<"----------------------";
if (this->selectedItem == nullptr) this->refresh();
return; emit requireRefreshPreview();
auto layer = this->selectedItem->data(0, Qt::UserRole).value<LayerWrapper*>(); emit requireRefreshElementWidget();
layer->del(); });
layer->getParent()->removeChild(layer); dialog->exec();
this->refresh(); });
emit requireRefreshPreview(); menu.addAction(QString::fromLocal8Bit("删除(保留子节点)"), this, [this]() {
}); auto layer = this->selectedItem->data(0, Qt::UserRole).value<LayerWrapper*>();
//} layer->delSelf();
layer->getParent()->removeChild(layer);
this->refresh();
emit requireRefreshPreview();
});
}
if (layer != root) {
menu.addAction(QString::fromLocal8Bit("删除"), this, [this]() {
auto layer = this->selectedItem->data(0, Qt::UserRole).value<LayerWrapper*>();
layer->del();
layer->getParent()->removeChild(layer);
this->refresh();
emit requireRefreshPreview();
});
menu.addAction(QString::fromLocal8Bit("重命名"), this, &LayerTreeWidget::onRenameEvent);
}
if (typeid(*layer) == typeid(FolderLayerWrapper) && ((FolderLayerWrapper*)layer)->getReferencedBy() == -1) {
menu.addAction(QString::fromLocal8Bit("创建组合元素"), this, [this]() {
auto layer = dynamic_cast<FolderLayerWrapper*>(this->selectedItem->data(0, Qt::UserRole).value<LayerWrapper*>());
if (layer != nullptr) {
bool ok;
QString name = QInputDialog::getText(this, QString::fromLocal8Bit("创建组合元素"),
QString::fromLocal8Bit("组合元素名称:"), QLineEdit::Normal,
"", &ok);
if (ok && !name.isEmpty()) {
elementManager->createGroupElement(name, layer);
emit requireRefreshElementWidget();
}
}
});
}
}
}
menu.exec(mapToGlobal(pos)); menu.exec(mapToGlobal(pos));
} }

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include "LayerWrapper.h" #include "LayerWrapper.h"
#include "ElementManager.h"
#include <QPoint> #include <QPoint>
#include <QTreeWidget> #include <QTreeWidget>
class LayerTreeWidget : public QTreeWidget class LayerTreeWidget : public QTreeWidget
@ -10,6 +11,7 @@ class LayerTreeWidget : public QTreeWidget
LayerWrapper *copiedItem; LayerWrapper *copiedItem;
public: public:
ElementManager* elementManager;
LayerWrapper* root; LayerWrapper* root;
LayerTreeWidget(QWidget *parent = nullptr); LayerTreeWidget(QWidget *parent = nullptr);
void onRenameEvent(); void onRenameEvent();
@ -18,7 +20,8 @@ class LayerTreeWidget : public QTreeWidget
// void mouseDoubleClickEvent(QMouseEvent *event) override; // void mouseDoubleClickEvent(QMouseEvent *event) override;
// void onItemDoubleClicked(QTreeWidgetItem *item, int column = 0); // void onItemDoubleClicked(QTreeWidgetItem *item, int column = 0);
signals: signals:
void displayLayerChange(LayerWrapper *); void displayLayerChange(LayerWrapper *);
void requireRefreshPreview(); void requireRefreshPreview();
void requireRefreshElementWidget();
}; };

View File

@ -0,0 +1,128 @@
#include "PaintingUtil.h"
#include <QFile>
#include <QJsondocument>
#include "PainterPathUtil.h"
using Renderer::Painting;
using Renderer::Element;
using Renderer::ElementTransform;
using glm::bvec2;
using std::max;
QJsonObject PaintingUtil::readJsonFile(QString jsonFilePath) {
QFile jsonFile(jsonFilePath);
jsonFile.open(QFile::ReadOnly);
QByteArray fileContent = jsonFile.readAll().trimmed();
jsonFile.close();
QJsonParseError jError;
QJsonDocument jsonDoc(QJsonDocument::fromJson(fileContent, &jError));
return jsonDoc.object();
}
Painting PaintingUtil::transfromToPainting(QString jsonFilePath) {
Painting painting;
QTransform transform;
glm::bvec2 flip(0, 0);
QJsonObject jsonObj = readJsonFile(jsonFilePath);
ElementManager *elementManager = new ElementManager(jsonObj, Renderer::ElementRenderer::instance());
LayerManager* layerManager = new LayerManager(jsonObj, elementManager);
traverseLayTree(layerManager->getRoot(), transform, flip, painting);
// FIXME: 为了编译通过添加的返回
return painting;
}
void PaintingUtil::traverseLayTree(LayerWrapper* nowLayer, QTransform transform, bvec2 flip, Painting& painting) {
LeafLayerWrapper* leafLayer = dynamic_cast<LeafLayerWrapper*>(nowLayer);
PixelPath pixelPath = nowLayer->getCache();
double centerX = pixelPath.getBoundingRect().center().x();
double centerY = pixelPath.getBoundingRect().center().y();
flip ^= bvec2(nowLayer->property.flipHorizontally, nowLayer->property.flipVertically);
QRectF transBound = transform.map(pixelPath.getPainterPath()).boundingRect();
transform.translate(nowLayer->property.offset.x(), nowLayer->property.offset.y())
.translate(-centerX, -centerY)
.rotate(nowLayer->property.rotation)
.scale(nowLayer->property.scale.x(), nowLayer->property.scale.y())
.translate(centerX, centerY);
if (leafLayer != nullptr) {
Element element;
ElementTransform elementTrans;
QRectF bound = pixelPath.getBoundingRect();
element.ratio = bound.width() / bound.height();
// transform to initial painterPath
QTransform trans;
trans.translate(-centerX, -centerY)
.scale(1 / nowLayer->property.scale.x(), 1 / nowLayer->property.scale.y())
.rotate(-nowLayer->property.rotation)
.translate(centerX, centerY)
.translate(-nowLayer->property.offset.x(), -nowLayer->property.offset.y());
QPainterPath painterPath = trans.map(pixelPath.getPainterPath());
// transfrom to -1 1
bound = painterPath.boundingRect();
trans.reset();
trans.translate(1, 1);
trans.scale(2 / bound.width(), 2 / bound.height());
trans.translate(bound.x(), bound.y());
painterPath = trans.map(painterPath);
element.contour.reset(new vector<vector<Renderer::Point> >(PainterPathUtil::transformToLines(painterPath)));
QSize screenSize = pixelPath.getPixmap().size();
elementTrans.center = glm::vec2(
(2 * (transBound.x() + transBound.width()) - screenSize.width()) / screenSize.width(),
(2 * (transBound.y() + transBound.height()) - screenSize.height()) / screenSize.height()
);
decomposeTransform(transform, elementTrans.rotation, elementTrans.scale);
elementTrans.flip = glm::bvec2(
nowLayer->property.flipHorizontally,
nowLayer->property.flipVertically
);
return;
}
FolderLayerWrapper* folderLayer = dynamic_cast<FolderLayerWrapper*>(nowLayer);
for (auto sonLayer : folderLayer->children) {
traverseLayTree(sonLayer.get(), transform, flip, painting);
}
return;
}
void PaintingUtil::decomposeTransform(QTransform trans, float& angle, glm::vec2& scale) {
trans.translate(-trans.dx(), -trans.dy());
int count = 0;
double norm = 0, n = 0;
QTransform R = trans, Rit, Rnext;
do {
++count;
Rit = R.inverted();
Rnext.setMatrix(
(R.m11() + Rit.m11()) / 2,
(R.m12() + Rit.m12()) / 2,
(R.m13() + Rit.m13()) / 2,
(R.m21() + Rit.m21()) / 2,
(R.m22() + Rit.m22()) / 2,
(R.m23() + Rit.m23()) / 2,
(R.m31() + Rit.m31()) / 2,
(R.m32() + Rit.m32()) / 2,
(R.m33() + Rit.m33()) / 2
);
norm = 0;
norm = max(norm,
fabs(R.m11() - Rnext.m11())
+ fabs(R.m12() - Rnext.m12())
+ fabs(R.m13() - Rnext.m13()));
norm = max(norm,
fabs(R.m21() - Rnext.m21())
+ fabs(R.m22() - Rnext.m22())
+ fabs(R.m23() - Rnext.m23()));
norm = max(norm,
fabs(R.m31() - Rnext.m31())
+ fabs(R.m32() - Rnext.m32())
+ fabs(R.m33() - Rnext.m33()));
R = Rnext;
} while (count < 100 && norm > 0.0001);
angle = acos(R.m11());
R = R.inverted() * trans;
scale = glm::vec2(R.m11(), R.m22());
return;
}

View File

@ -0,0 +1,15 @@
#pragma once
#include "../../Renderer/Painting/Painting.h"
#include <QJsonObject>
#include <ElementManager.h>
class PaintingUtil
{
private:
static QJsonObject readJsonFile(QString jsonFilePath);
static void traverseLayTree(LayerWrapper* nowLayer, QTransform transform, glm::bvec2 flip, Renderer::Painting& painting);
static void decomposeTransform(QTransform trans, float& angle, glm::vec2& scale);
public:
static Renderer::Painting transfromToPainting(QString jsonFilePath);
};

View File

@ -86,7 +86,6 @@ QPolygonF SvgFileLoader::handleAttrPoints(QString points) {
void SvgFileLoader::handleAttrTransform(QString transformStyle, QPainterPath& painterPath) { void SvgFileLoader::handleAttrTransform(QString transformStyle, QPainterPath& painterPath) {
QTransform trans; QTransform trans;
QStringList ops = transformStyle.split(')'); QStringList ops = transformStyle.split(')');
reverse(ops.begin(), ops.end());
vector<double> numbers; vector<double> numbers;
for (auto op : ops) { for (auto op : ops) {
op = op.simplified(); op = op.simplified();

View File

@ -0,0 +1,24 @@
#include "FluentMenu.h"
#include <QPainter>
#include <glm/glm.hpp>
::FluentMenu::FluentMenu(QWidget* parent) : QMenu(parent)
{
setWindowFlags(windowFlags() | Qt::FramelessWindowHint | Qt::NoDropShadowWindowHint);
setAttribute(Qt::WA_TranslucentBackground);
setStyleSheet(QString::fromStdString(std::format("QMenu {{margin:{}px;border-radius:{}px;padding:4px;border: 1px solid #c1c1c1;}}"
"QMenu::item {{height:30px;width:100px;padding-left:20px;border-radius:{}px;}}"
"QMenu::item:selected {{background-color:#dedede;}}", shadowRadius, borderRadius, itemBorderRadius)));
}
void ::FluentMenu::paintEvent(QPaintEvent* event)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing, true);
for (qreal i = 0; i < shadowRadius; i += 1 / devicePixelRatioF())
{
painter.setPen(QColor(0, 0, 0, glm::mix(0.22 * 255, 0., glm::pow(i / shadowRadius, 0.2))));
painter.drawRoundedRect(QRectF(shadowRadius - i, shadowRadius - i, width() - (shadowRadius - i) * 2, height() - (shadowRadius - i) * 2), borderRadius + i, borderRadius + i);
}
QMenu::paintEvent(event);
}

View File

@ -0,0 +1,14 @@
#pragma once
#include <QMenu>
class FluentMenu : public QMenu
{
Q_OBJECT
public:
explicit FluentMenu(QWidget* parent = nullptr);
void paintEvent(QPaintEvent* event) override;
int shadowRadius = 16;
int borderRadius = 6;
int itemBorderRadius = 4;
};

View File

@ -1,75 +0,0 @@
/*
The MIT License (MIT)
Copyright © 2018-2022 Antonio Dias
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "iconwidget.h"
#define ICONWIDTH 16
#define ICONHEIGHT 16
IconWidget::IconWidget(QWidget *parent) : QWidget(parent)
{
m_active = true;
}
void IconWidget::setPixmap(const QPixmap &pixmap)
{
m_pixmap = pixmap;
QImage tmp = m_pixmap.toImage();
for (int i = 0; i < m_pixmap.width(); i++)
{
for (int j = 0; j < m_pixmap.height(); j++)
{
int gray = qGray(tmp.pixel(i, j));
int alpha = qAlpha(tmp.pixel(i, j));
tmp.setPixel(i, j, qRgba(gray, gray, gray, alpha));
}
}
m_grayed_pixmap = QPixmap::fromImage(tmp);
repaint();
}
void IconWidget::setActive(bool active)
{
m_active = active;
repaint();
}
void IconWidget::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event)
QPainter painter(this);
painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
painter.drawPixmap((width() - ICONWIDTH)/ 2,
(height() - ICONHEIGHT) / 2,
ICONWIDTH, ICONHEIGHT,
m_active ? m_pixmap : m_grayed_pixmap);
}

View File

@ -1,52 +0,0 @@
/*
The MIT License (MIT)
Copyright © 2018-2022 Antonio Dias
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef ICONWIDGET_H
#define ICONWIDGET_H
#include <QtCore>
#include <QtGui>
#include <QtWidgets>
class IconWidget : public QWidget
{
Q_OBJECT
public:
explicit IconWidget(QWidget *parent = nullptr);
public slots:
void setPixmap(const QPixmap &pixmap);
void setActive(bool active);
private:
//Functions
void paintEvent(QPaintEvent *event);
//Variables
QPixmap m_pixmap;
QPixmap m_grayed_pixmap;
bool m_active;
};
#endif // ICONWIDGET_H

View File

@ -2,6 +2,7 @@
#include "Renderer/RendererGLWidget.h" #include "Renderer/RendererGLWidget.h"
#include "qslider.h" #include "qslider.h"
#include <QPushButton> #include <QPushButton>
#include <QScreen>
#include "NavigationBarWidget.h" #include "NavigationBarWidget.h"
#include <FramelessHelper/Core/utils.h> #include <FramelessHelper/Core/utils.h>
#include <FramelessHelper/Widgets/standardtitlebar.h> #include <FramelessHelper/Widgets/standardtitlebar.h>
@ -11,111 +12,13 @@
FRAMELESSHELPER_USE_NAMESPACE FRAMELESSHELPER_USE_NAMESPACE
inline void fontTheme() CentralWidget::CentralWidget(QWidget* parent) : QWidget(parent)
{
QFont defaultFont = qApp->font();
defaultFont.setPointSize(defaultFont.pointSize() + 2);
qApp->setFont(defaultFont);
}
inline void setThemeStyleSheet(bool dark)
{
QFile file(dark ? ":/darkstyle.qss" : ":/lightstyle.qss");
if (!file.open(QFile::ReadOnly))
return;
const QString style_sheet = QLatin1String(file.readAll());
file.close();
qApp->setStyleSheet(style_sheet);
}
inline void darkTheme()
{
QPalette darkPalette = qApp->palette();
darkPalette.setColor(QPalette::Window, QColor(53, 53, 53));
darkPalette.setColor(QPalette::WindowText, QColor(255, 255, 255));
darkPalette.setColor(QPalette::Disabled, QPalette::WindowText, QColor(127, 127, 127));
darkPalette.setColor(QPalette::Base, QColor(42, 42, 42));
darkPalette.setColor(QPalette::AlternateBase, QColor(66, 66, 66));
darkPalette.setColor(QPalette::ToolTipBase, QColor(255, 255, 255));
darkPalette.setColor(QPalette::ToolTipText, QColor(255, 255, 255));
darkPalette.setColor(QPalette::Text, QColor(255, 255, 255));
darkPalette.setColor(QPalette::Disabled, QPalette::Text, QColor(127, 127, 127));
darkPalette.setColor(QPalette::Dark, QColor(35, 35, 35));
darkPalette.setColor(QPalette::Shadow, QColor(20, 20, 20));
darkPalette.setColor(QPalette::Button, QColor(53, 53, 53));
darkPalette.setColor(QPalette::ButtonText, QColor(255, 255, 255));
darkPalette.setColor(QPalette::Disabled, QPalette::ButtonText, QColor(127, 127, 127));
darkPalette.setColor(QPalette::BrightText, QColor(255, 0, 0));
darkPalette.setColor(QPalette::Link, QColor(42, 130, 218));
darkPalette.setColor(QPalette::Highlight, QColor(42, 130, 218));
darkPalette.setColor(QPalette::Disabled, QPalette::Highlight, QColor(80, 80, 80));
darkPalette.setColor(QPalette::HighlightedText, QColor(255, 255, 255));
darkPalette.setColor(QPalette::Disabled, QPalette::HighlightedText, QColor(127, 127, 127));
qApp->setPalette(darkPalette);
setThemeStyleSheet(true /*dark*/);
}
inline void lightTheme()
{
QPalette lightPalette = qApp->palette();
lightPalette.setColor(QPalette::Window, QColor(240, 240, 240));
lightPalette.setColor(QPalette::WindowText, QColor(0, 0, 0));
lightPalette.setColor(QPalette::Disabled, QPalette::WindowText, QColor(120, 120, 120));
lightPalette.setColor(QPalette::Base, QColor(255, 255, 255));
lightPalette.setColor(QPalette::AlternateBase, QColor(233, 231, 227));
lightPalette.setColor(QPalette::ToolTipBase, QColor(255, 255, 220));
lightPalette.setColor(QPalette::ToolTipText, QColor(0, 0, 0));
lightPalette.setColor(QPalette::Text, QColor(0, 0, 0));
lightPalette.setColor(QPalette::Disabled, QPalette::Text, QColor(120, 120, 120));
lightPalette.setColor(QPalette::Dark, QColor(160, 160, 160));
lightPalette.setColor(QPalette::Shadow, QColor(105, 105, 105));
lightPalette.setColor(QPalette::Button, QColor(240, 240, 240));
lightPalette.setColor(QPalette::ButtonText, QColor(0, 0, 0));
lightPalette.setColor(QPalette::Disabled, QPalette::ButtonText, QColor(120, 120, 120));
lightPalette.setColor(QPalette::BrightText, QColor(0, 0, 255));
lightPalette.setColor(QPalette::Link, QColor(51, 153, 255));
lightPalette.setColor(QPalette::Highlight, QColor(0, 0, 255));
lightPalette.setColor(QPalette::Disabled, QPalette::Highlight, QColor(51, 153, 255));
lightPalette.setColor(QPalette::HighlightedText, QColor(255, 255, 255));
lightPalette.setColor(QPalette::Disabled, QPalette::HighlightedText, QColor(255, 255, 255));
qApp->setPalette(lightPalette);
setThemeStyleSheet(false /*dark*/);
}
FramelessWindow::FramelessWindow(QWidget* parent) : QWidget(parent), ui(new Ui::FramelessWindow)
{
ui->setupUi(this);
}
FramelessWindow::~FramelessWindow()
{
delete ui;
}
CentralWidget::CentralWidget(QWidget* parent) : QMainWindow(parent)
{ {
ui.setupUi(this); ui.setupUi(this);
NavigationBarWidget* navigationBarWidget = new NavigationBarWidget(); NavigationBarWidget* navigationBarWidget = new NavigationBarWidget(this);
ui.gridLayout->addWidget(navigationBarWidget, 0, 0, 1, 1, Qt::AlignTop | Qt::AlignHCenter);
QHBoxLayout* tabBarLayout = new QHBoxLayout(ui.tabWidget); QObject::connect(navigationBarWidget->tabs, &QtMaterialTabs::currentChanged, ui.stackedWidget, &QStackedWidget::setCurrentIndex);
tabBarLayout->setSpacing(0); QObject::connect(ui.stackedWidget, &QStackedWidget::currentChanged, ui.rendererWidget, &Renderer::RendererWidget::currentTabChanged);
tabBarLayout->setMargin(0);
tabBarLayout->addWidget(navigationBarWidget, 0, Qt::AlignTop | Qt::AlignHCenter);
QObject::connect(navigationBarWidget->tabs, &QtMaterialTabs::currentChanged, ui.tabWidget, &QTabWidget::setCurrentIndex);
QObject::connect(ui.tabWidget, &QTabWidget::currentChanged,
ui.rendererWidget, &Renderer::RendererWidget::currentTabChanged);
} }
CentralWidget::~CentralWidget() CentralWidget::~CentralWidget()
@ -133,38 +36,29 @@ MainWindow::MainWindow(QWidget* parent, const Qt::WindowFlags flags)
m_titleBar->maximizeButton()->setFixedHeight(kTitleBarHeight); m_titleBar->maximizeButton()->setFixedHeight(kTitleBarHeight);
m_titleBar->closeButton()->setFixedHeight(kTitleBarHeight); m_titleBar->closeButton()->setFixedHeight(kTitleBarHeight);
m_titleBar->setTitleFont(QFont(QString("Segoe UI, Microsoft YaHei UI"), 10)); m_titleBar->setTitleFont(QFont(QString("Segoe UI, Microsoft YaHei UI"), 10));
m_titleBar->chromePalette()->setTitleBarActiveBackgroundColor(QColor(0,0,0,0)); m_titleBar->chromePalette()->setTitleBarActiveBackgroundColor(QColor(0, 0, 0, 0));
m_titleBar->chromePalette()->setTitleBarInactiveBackgroundColor(QColor(0, 0, 0, 0)); m_titleBar->chromePalette()->setTitleBarInactiveBackgroundColor(QColor(0, 0, 0, 0));
m_window = new FramelessWindow(this);
m_central_widget = new CentralWidget(this); m_central_widget = new CentralWidget(this);
m_window->ui->windowContent->layout()->addWidget(m_central_widget);
setMenuWidget(m_titleBar); setMenuWidget(m_titleBar);
setCentralWidget(m_window); setCentralWidget(m_central_widget);
FramelessWidgetsHelper* helper = FramelessWidgetsHelper::get(this); FramelessWidgetsHelper* helper = FramelessWidgetsHelper::get(this);
helper->setTitleBarWidget(m_titleBar); helper->setTitleBarWidget(m_titleBar);
#ifndef Q_OS_MACOS
helper->setSystemButton(m_titleBar->minimizeButton(), Global::SystemButtonType::Minimize); helper->setSystemButton(m_titleBar->minimizeButton(), Global::SystemButtonType::Minimize);
helper->setSystemButton(m_titleBar->maximizeButton(), Global::SystemButtonType::Maximize); helper->setSystemButton(m_titleBar->maximizeButton(), Global::SystemButtonType::Maximize);
helper->setSystemButton(m_titleBar->closeButton(), Global::SystemButtonType::Close); helper->setSystemButton(m_titleBar->closeButton(), Global::SystemButtonType::Close);
#endif // Q_OS_MACOS
connect(helper, &FramelessWidgetsHelper::ready, this, [this, helper]() {
helper->moveWindowToDesktopCenter();
});
//connect(helper, &FramelessWidgetsHelper::ready, this, [this, helper]() {
// helper->moveWindowToDesktopCenter();
// });
setWindowIcon(QIcon(":/images/icon.png")); setWindowIcon(QIcon(":/images/icon.png"));
setWindowTitle("ArchitectureColoredPainting"); setWindowTitle("ArchitectureColoredPainting");
resize(m_central_widget->size()); resize(m_central_widget->size());
//setCentralWidget(m_window); move(QGuiApplication::primaryScreen()->availableGeometry().center() - rect().center());
//move(QGuiApplication::primaryScreen()->availableGeometry().center() - rect().center());
} }
@ -178,6 +72,5 @@ void MainWindow::closeEvent(QCloseEvent* event)
if (result != QMessageBox::Yes) if (result != QMessageBox::Yes)
event->ignore();*/ event->ignore();*/
qDebug() << "closeEvent";
} }

View File

@ -2,7 +2,6 @@
#include <QtWidgets/QMainWindow> #include <QtWidgets/QMainWindow>
#include "ui_MainWindow.h" #include "ui_MainWindow.h"
#include "ui_FramelessWindow.h"
#include <FramelessHelper/Widgets/framelessmainwindow.h> #include <FramelessHelper/Widgets/framelessmainwindow.h>
@ -10,20 +9,7 @@ FRAMELESSHELPER_BEGIN_NAMESPACE
class StandardTitleBar; class StandardTitleBar;
FRAMELESSHELPER_END_NAMESPACE FRAMELESSHELPER_END_NAMESPACE
class CentralWidget : public QWidget
class FramelessWindow : public QWidget
{
Q_OBJECT
public:
explicit FramelessWindow(QWidget* parent = nullptr);
~FramelessWindow();
Ui::FramelessWindow* ui;
};
class CentralWidget : public QMainWindow
{ {
Q_OBJECT Q_OBJECT
public: public:
@ -46,10 +32,7 @@ public:
private: private:
FRAMELESSHELPER_PREPEND_NAMESPACE(StandardTitleBar)* m_titleBar = nullptr; FRAMELESSHELPER_PREPEND_NAMESPACE(StandardTitleBar)* m_titleBar = nullptr;
Ui::MainWindowClass ui; Ui::MainWindowClass ui;
CentralWidget* m_central_widget = nullptr;
void closeEvent(QCloseEvent * event);
void closeEvent(QCloseEvent* event);
FramelessWindow* m_window;
CentralWidget* m_central_widget;
}; };

View File

@ -1,5 +1,6 @@
#include "NavigationBarWidget.h" #include "NavigationBarWidget.h"
#include <qtmaterialraisedbutton.h> #include <qtmaterialraisedbutton.h>
#include <QVBoxLayout>
#include <QDebug> #include <QDebug>
NavigationBarWidget::NavigationBarWidget(QWidget *parent) NavigationBarWidget::NavigationBarWidget(QWidget *parent)

View File

@ -3,7 +3,6 @@
#include <QWidget> #include <QWidget>
#include <QButtonGroup> #include <QButtonGroup>
#include <qtmaterialtabs.h> #include <qtmaterialtabs.h>
#include "ui_NavigationBarWidget.h"
class NavigationBarWidget : public QWidget class NavigationBarWidget : public QWidget
{ {

View File

@ -1,24 +1,23 @@
#pragma once #pragma once
#include <QOpenGLFunctions_4_5_Core> #include <QOpenGLFunctions_4_5_Core>
#include <QString> #include <QString>
#include <QVector> #include <vector>
#include <QVector2D>
#include <QVector3D>
#include <QOpenGLShaderProgram> #include <QOpenGLShaderProgram>
#include <QOpenGLBuffer> #include <QOpenGLBuffer>
#include <QOpenGLVertexArrayObject> #include <QOpenGLVertexArrayObject>
#include <QOpenGLTexture> #include <QOpenGLTexture>
#include <QOpenGLWidget> #include <QOpenGLWidget>
#include <assimp/vector3.h> #include <assimp/vector3.h>
#include <glm/glm.hpp>
#include "Drawable.h" #include "Drawable.h"
namespace Renderer namespace Renderer
{ {
struct Vertex struct Vertex
{ {
QVector3D Position; glm::vec3 Position;
QVector3D Normal; glm::vec3 Normal;
QVector2D TexCoords; glm::vec2 TexCoords;
Vertex(const aiVector3D& position, const aiVector3D& Normal, const aiVector3D& TexCoords); Vertex(const aiVector3D& position, const aiVector3D& Normal, const aiVector3D& TexCoords);
}; };
@ -38,8 +37,8 @@ namespace Renderer
class Mesh : public Drawable class Mesh : public Drawable
{ {
public: public:
QVector<Vertex> vertices; std::vector<Vertex> vertices;
QVector<unsigned int> indices; std::vector<unsigned int> indices;
//QVector<Texture*> textures; //QVector<Texture*> textures;
GLuint textureBasecolor = 0; GLuint textureBasecolor = 0;
GLuint textureMetallicRoughness = 0; GLuint textureMetallicRoughness = 0;

View File

@ -45,26 +45,50 @@ void Model::drawShadow() {
void Renderer::Model::loadModel(QString path) void Renderer::Model::loadModel(QString path)
{ {
directory = path; QFileInfo modelFile(path);
name = modelFile.baseName();
directory = modelFile.dir();
Assimp::Importer importer; Assimp::Importer importer;
const aiScene* scene = importer.ReadFile(directory.absolutePath().toUtf8(), aiProcess_Triangulate | aiProcess_FlipUVs); const aiScene* scene = importer.ReadFile(modelFile.absoluteFilePath().toUtf8(), aiProcess_Triangulate /*| aiProcess_FlipUVs*/);
if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode)
{ {
qDebug() << "ERROR::ASSIMP::" << importer.GetErrorString() << endl; qCritical() << "ERROR::ASSIMP::" << importer.GetErrorString() << endl;
return; return;
} }
qDebug() << directory.absolutePath() << "Loaded Successfully"; qDebug() << modelFile.absoluteFilePath() << "Loaded Successfully";
qDebug() << "NumMeshes: " << scene->mNumMeshes; qDebug() << "NumMeshes: " << scene->mNumMeshes;
qDebug() << "NumMaterials: " << scene->mNumMaterials; qDebug() << "NumMaterials: " << scene->mNumMaterials;
qDebug() << "NumTextures: " << scene->mNumTextures; qDebug() << "NumTextures: " << scene->mNumTextures;
directory.cdUp();
if (QFile paintingConfigFile(directory.filePath(name + ".txt")); paintingConfigFile.open(QFile::ReadOnly | QIODevice::Text))
{
paintingMap.clear();
QTextStream stream(&paintingConfigFile);
while (!stream.atEnd())
{
QString source, target;
glm::vec2 leftBottom, rightTop;
stream >> source >> target >> leftBottom.x >> leftBottom.y >> rightTop.x >> rightTop.y;
qDebug() << source << target << leftBottom.x << leftBottom.y << rightTop.x << rightTop.y;
paintingMap.emplace(source.toStdString(), std::forward_as_tuple(target.toStdString(), leftBottom, rightTop));
}
paintingConfigFile.close();
}
else
{
qWarning() << "Painting Config Not Found!";
}
minX = std::numeric_limits<float>::max(); minX = std::numeric_limits<float>::max();
maxX = std::numeric_limits<float>::min(); maxX = std::numeric_limits<float>::min();
minY = std::numeric_limits<float>::max(); minY = std::numeric_limits<float>::max();
maxY = std::numeric_limits<float>::min(); maxY = std::numeric_limits<float>::min();
minZ = std::numeric_limits<float>::max(); minZ = std::numeric_limits<float>::max();
maxZ = std::numeric_limits<float>::min(); maxZ = std::numeric_limits<float>::min();
processNode(scene->mRootNode, scene); aiMatrix4x4 transform;
aiMatrix4x4::Scaling(aiVector3D(1 / 0.008), transform);
processNode(scene->mRootNode, scene, transform * scene->mRootNode->mTransformation);
AABB.push_back(QVector3D(minX, minY, minZ)); AABB.push_back(QVector3D(minX, minY, minZ));
AABB.push_back(QVector3D(minX, minY, maxZ)); AABB.push_back(QVector3D(minX, minY, maxZ));
AABB.push_back(QVector3D(minX, maxY, minZ)); AABB.push_back(QVector3D(minX, maxY, minZ));
@ -93,86 +117,77 @@ void Model::processNode(aiNode* node, const aiScene* scene, aiMatrix4x4 mat4)
std::unique_ptr<Drawable> Model::processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 model) std::unique_ptr<Drawable> Model::processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 model)
{ {
aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex];
QMatrix4x4 modelQ((float*)&model); QMatrix4x4 modelQ((float*)&model);
aiString str; std::vector<Vertex> vertices;
material->GetTexture(aiTextureType_BASE_COLOR, 0, &str); for (unsigned int i = 0; i < mesh->mNumVertices; i++)
if (paintingProgram != nullptr && (std::strcmp(str.C_Str(), "17876391417123941155.jpg") == 0 || std::strcmp(str.C_Str(), "11474523244911310074.jpg") == 0))
{ {
qDebug() << str.C_Str() << "Replaced"; if (mesh->mNormals && mesh->mTextureCoords[0])
// 初始化网格
auto m_mesh = std::make_unique<PaintingMesh>(glFunc, paintingProgram, shadowProgram, modelQ);
// 遍历网格的每个顶点
for (unsigned int i = 0; i < mesh->mNumVertices; i++)
{ {
if (mesh->mNormals && mesh->mTextureCoords[0]) auto pos = mesh->mVertices[i];
{ vertices.push_back(Vertex(pos, mesh->mNormals[i], mesh->mTextureCoords[0][i]));
Vertex vertex(mesh->mVertices[i], mesh->mNormals[i], mesh->mTextureCoords[0][i]); auto worldPos = model * pos;
minX = std::min(minX, vertex.Position.x()); minX = std::min(minX, worldPos.x);
maxX = std::max(maxX, vertex.Position.x()); maxX = std::max(maxX, worldPos.x);
minY = std::min(minY, vertex.Position.y()); minY = std::min(minY, worldPos.y);
maxY = std::max(maxY, vertex.Position.y()); maxY = std::max(maxY, worldPos.y);
minZ = std::min(minZ, vertex.Position.z()); minZ = std::min(minZ, worldPos.z);
maxZ = std::max(maxZ, vertex.Position.z()); maxZ = std::max(maxZ, worldPos.z);
m_mesh->vertices.push_back(vertex);
}
} }
}
for (unsigned int i = 0; i < mesh->mNumFaces; i++) std::vector<unsigned int> indices;
for (auto face = mesh->mFaces; face < mesh->mFaces + mesh->mNumFaces; face++)
indices.insert(indices.end(), face->mIndices, face->mIndices + face->mNumIndices);
aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex];
if (auto iter = paintingMap.find([&] {
aiString str;
material->GetTexture(aiTextureType_BASE_COLOR, 0, &str);
return std::string(str.C_Str());
}()); paintingProgram != nullptr && iter != paintingMap.end())
{
qDebug() << iter->first.c_str() << "Replaced";
auto mesh = std::make_unique<PaintingMesh>(glFunc, paintingProgram, shadowProgram, modelQ);
auto& [paintingPath, leftBottom, rightTop] = iter->second;
for (auto& v : vertices)
{ {
aiFace face = mesh->mFaces[i]; //qDebug() << v.TexCoords.x << v.TexCoords.y;
// 将所有面的索引数据添加到索引数组中 v.TexCoords = (v.TexCoords - leftBottom) / (rightTop - leftBottom);
for (unsigned int j = 0; j < face.mNumIndices; j++) { qDebug() << v.TexCoords.x << v.TexCoords.y;
m_mesh->indices.push_back(face.mIndices[j]);
}
} }
m_mesh->paintingId = loadPainting(std::string(str.C_Str())); mesh->vertices = vertices;
auto& handle = vtManager->getPaintingHandle(m_mesh->paintingId); mesh->indices = indices;
m_mesh->textureBasecolor = handle.baseColor;
m_mesh->textureMetallicRoughness = handle.metallicRoughness; mesh->paintingId = loadPainting(paintingPath);
m_mesh->setupMesh(); auto& handle = vtManager->getPaintingHandle(mesh->paintingId);
return m_mesh; mesh->textureBasecolor = handle.baseColor;
mesh->textureMetallicRoughness = handle.metallicRoughness;
mesh->setupMesh();
return mesh;
} }
else else
{ {
// 初始化网格 auto mesh = std::make_unique<Mesh>(glFunc, shaderProgram, shadowProgram, modelQ);
auto m_mesh = std::make_unique<Mesh>(glFunc, shaderProgram, shadowProgram, modelQ); mesh->vertices = vertices;
// 遍历网格的每个顶点 mesh->indices = indices;
for (unsigned int i = 0; i < mesh->mNumVertices; i++)
{
if (mesh->mNormals && mesh->mTextureCoords[0])
{
Vertex vertex(mesh->mVertices[i], mesh->mNormals[i], mesh->mTextureCoords[0][i]);
minX = std::min(minX, vertex.Position.x());
maxX = std::max(maxX, vertex.Position.x());
minY = std::min(minY, vertex.Position.y());
maxY = std::max(maxY, vertex.Position.y());
minZ = std::min(minZ, vertex.Position.z());
maxZ = std::max(maxZ, vertex.Position.z());
m_mesh->vertices.push_back(vertex);
}
}
// 将所有面的索引数据添加到索引数组中 if (!(mesh->textureBasecolor = loadMaterialTextures(material, aiTextureType_BASE_COLOR)))
for (auto face = mesh->mFaces; face < mesh->mFaces + mesh->mNumFaces; face++)
for (auto indice = face->mIndices; indice < face->mIndices + face->mNumIndices; indice++)
m_mesh->indices.push_back(*indice);
// 处理材质
if (!(m_mesh->textureBasecolor = loadMaterialTextures(material, aiTextureType_BASE_COLOR)))
qWarning() << "Basecolor Texture Loading Failed!"; qWarning() << "Basecolor Texture Loading Failed!";
if (!(m_mesh->textureMetallicRoughness = loadMaterialTextures(material, aiTextureType_METALNESS))) if (!(mesh->textureMetallicRoughness = loadMaterialTextures(material, aiTextureType_METALNESS)))
qWarning() << "MetallicRoughness Texture Loading Failed!"; qWarning() << "MetallicRoughness Texture Loading Failed!";
if (!(m_mesh->textureNormal = loadMaterialTextures(material, aiTextureType_NORMALS))) if (!(mesh->textureNormal = loadMaterialTextures(material, aiTextureType_NORMALS)))
qWarning() << "Normal Texture Loading Failed!"; qWarning() << "Normal Texture Loading Failed!";
if (m_mesh->textureBasecolor && m_mesh->textureMetallicRoughness && m_mesh->textureNormal) if (mesh->textureBasecolor && mesh->textureMetallicRoughness && mesh->textureNormal)
{ {
m_mesh->setupMesh(); mesh->setupMesh();
return m_mesh; return mesh;
} }
else else
return nullptr; return nullptr;
@ -203,7 +218,7 @@ GLuint Model::loadMaterialTextures(aiMaterial* mat, aiTextureType type)
texture.setWrapMode(QOpenGLTexture::DirectionS, QOpenGLTexture::Repeat); texture.setWrapMode(QOpenGLTexture::DirectionS, QOpenGLTexture::Repeat);
texture.setWrapMode(QOpenGLTexture::DirectionT, QOpenGLTexture::Repeat); texture.setWrapMode(QOpenGLTexture::DirectionT, QOpenGLTexture::Repeat);
texture.setMinMagFilters(QOpenGLTexture::LinearMipMapLinear, QOpenGLTexture::Linear); texture.setMinMagFilters(QOpenGLTexture::LinearMipMapLinear, QOpenGLTexture::Linear);
texture.setData(data); texture.setData(data.mirrored());
return texture.textureId(); return texture.textureId();
} }
@ -250,7 +265,7 @@ GLuint Renderer::Model::loadPainting(std::string path)
}; };
Painting painting; Painting painting;
if (path == "17876391417123941155.jpg") if (path == "0.json")
{ {
painting.addElement(*element[0], ElementTransform{ glm::vec2(-0.45,-0.45), glm::vec2(0.5,0.5) / 2.f, 0, glm::bvec2(false), 0 }); painting.addElement(*element[0], ElementTransform{ glm::vec2(-0.45,-0.45), glm::vec2(0.5,0.5) / 2.f, 0, glm::bvec2(false), 0 });
painting.addElement(*element[1], ElementTransform{ glm::vec2(-0.45, 0.45), glm::vec2(0.5,0.5) / 2.f, 0, glm::bvec2(false), 0 }); painting.addElement(*element[1], ElementTransform{ glm::vec2(-0.45, 0.45), glm::vec2(0.5,0.5) / 2.f, 0, glm::bvec2(false), 0 });
@ -266,7 +281,6 @@ GLuint Renderer::Model::loadPainting(std::string path)
} }
} }
painting.generateBuffers(glFunc); painting.generateBuffers(glFunc);
auto index = vtManager->createVirtualTexture(painting); auto index = vtManager->createVirtualTexture(painting);

View File

@ -17,20 +17,24 @@ namespace Renderer
void loadModel(QString path); void loadModel(QString path);
Model(QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* paintingProgram, QOpenGLShaderProgram* shadowProgram, VirtualTextureManager* vtManager); Model(QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* paintingProgram, QOpenGLShaderProgram* shadowProgram, VirtualTextureManager* vtManager);
private: private:
QOpenGLContext* context; QOpenGLContext* context = nullptr;
QOpenGLFunctions_4_5_Core* glFunc = nullptr; QOpenGLFunctions_4_5_Core* glFunc = nullptr;
QOpenGLShaderProgram* shaderProgram = nullptr; QOpenGLShaderProgram* shaderProgram = nullptr;
QOpenGLShaderProgram* paintingProgram = nullptr; QOpenGLShaderProgram* paintingProgram = nullptr;
QOpenGLShaderProgram* shadowProgram = nullptr; QOpenGLShaderProgram* shadowProgram = nullptr;
VirtualTextureManager* vtManager = nullptr; VirtualTextureManager* vtManager = nullptr;
/* 模型数据 */ /**
* @param key BaseColor
* @param value json,
*/
std::unordered_map<std::string, std::tuple<std::string, glm::vec2, glm::vec2>> paintingMap;
std::unordered_map<std::string, GLuint> paintingLoaded; std::unordered_map<std::string, GLuint> paintingLoaded;
std::unordered_map<std::string, QOpenGLTexture> texturesLoaded; std::unordered_map<std::string, QOpenGLTexture> texturesLoaded;
std::vector<std::unique_ptr<Drawable>> meshes; std::vector<std::unique_ptr<Drawable>> meshes;
/// 模型所在路径 QDir directory; /// 模型所在路径
QDir directory; QString name; /// 模型文件名
float minX, maxX, minY, maxY, minZ, maxZ; float minX, maxX, minY, maxY, minZ, maxZ;

View File

@ -23,6 +23,7 @@ namespace Renderer
public: public:
virtual MaterialStyleType type() const = 0; virtual MaterialStyleType type() const = 0;
virtual std::vector<GLfloat> encoded() const = 0; virtual std::vector<GLfloat> encoded() const = 0;
virtual std::unique_ptr<MaterialStyle> clone() const = 0;
virtual bool operator==(const MaterialStyle&) const = 0; virtual bool operator==(const MaterialStyle&) const = 0;
}; };

View File

@ -18,6 +18,11 @@ std::vector<GLfloat> Renderer::FillPlain::encoded() const
glm::uintBitsToFloat(glm::packUnorm4x8(glm::vec4(color.redF(), color.greenF(), color.blueF(), color.alphaF())))}; glm::uintBitsToFloat(glm::packUnorm4x8(glm::vec4(color.redF(), color.greenF(), color.blueF(), color.alphaF())))};
} }
std::unique_ptr<MaterialFill> Renderer::FillPlain::clone() const
{
return std::make_unique<FillPlain>(*this);
}
bool Renderer::FillPlain::operator==(const MaterialFill& m) const bool Renderer::FillPlain::operator==(const MaterialFill& m) const
{ {
return type() == m.type() return type() == m.type()
@ -42,6 +47,11 @@ std::vector<GLfloat> Renderer::MaterialStyleFill::encoded() const
return materialFill->encoded(); return materialFill->encoded();
} }
std::unique_ptr<MaterialStyle> Renderer::MaterialStyleFill::clone() const
{
return std::make_unique<MaterialStyleFill>(materialFill->clone());
}
bool Renderer::MaterialStyleFill::operator==(const MaterialStyle& m) const bool Renderer::MaterialStyleFill::operator==(const MaterialStyle& m) const
{ {
return type() == m.type() && *materialFill == *static_cast<const MaterialStyleFill&>(m).materialFill; return type() == m.type() && *materialFill == *static_cast<const MaterialStyleFill&>(m).materialFill;

View File

@ -10,6 +10,7 @@ namespace Renderer
public: public:
virtual MaterialFillType type() const = 0; virtual MaterialFillType type() const = 0;
virtual std::vector<GLfloat> encoded() const = 0; virtual std::vector<GLfloat> encoded() const = 0;
virtual std::unique_ptr<MaterialFill> clone() const = 0;
virtual bool operator==(const MaterialFill&) const = 0; virtual bool operator==(const MaterialFill&) const = 0;
}; };
@ -19,6 +20,7 @@ namespace Renderer
FillPlain(QColor color, float metallic, float roughness); FillPlain(QColor color, float metallic, float roughness);
virtual MaterialFillType type() const override; virtual MaterialFillType type() const override;
virtual std::vector<GLfloat> encoded() const override; virtual std::vector<GLfloat> encoded() const override;
virtual std::unique_ptr<MaterialFill> clone() const override;
virtual bool operator==(const MaterialFill&) const override; virtual bool operator==(const MaterialFill&) const override;
QColor color; QColor color;
@ -26,16 +28,17 @@ namespace Renderer
float roughness; float roughness;
}; };
class MaterialStyleFill : public MaterialStyle class MaterialStyleFill : public MaterialStyle
{ {
public: public:
MaterialStyleFill(std::shared_ptr<MaterialFill> materialFill); MaterialStyleFill(std::shared_ptr<MaterialFill> materialFill);
virtual MaterialStyleType type() const override; virtual MaterialStyleType type() const override;
virtual std::vector<GLfloat> encoded() const override; virtual std::vector<GLfloat> encoded() const override;
virtual std::unique_ptr<MaterialStyle> clone() const override;
virtual bool operator==(const MaterialStyle&) const override; virtual bool operator==(const MaterialStyle&) const override;
protected: //protected:
std::shared_ptr<MaterialFill> materialFill; std::shared_ptr<MaterialFill> materialFill;
}; };
} }

View File

@ -18,6 +18,11 @@ MaterialStrokeType Renderer::StrokePlain::type() const
return MaterialStrokeType::kPlain; return MaterialStrokeType::kPlain;
} }
std::unique_ptr<MaterialStroke> Renderer::StrokePlain::clone() const
{
return std::make_unique<StrokePlain>(*this);
}
std::vector<GLfloat> Renderer::StrokePlain::encoded() const std::vector<GLfloat> Renderer::StrokePlain::encoded() const
{ {
return { glm::uintBitsToFloat(glm::packUnorm4x8(glm::vec4(material.toVec().second, 0.f, 0.f))), return { glm::uintBitsToFloat(glm::packUnorm4x8(glm::vec4(material.toVec().second, 0.f, 0.f))),
@ -58,6 +63,11 @@ std::vector<GLfloat> Renderer::StrokeRadialGradient::encoded() const
return result; return result;
} }
std::unique_ptr<MaterialStroke> Renderer::StrokeRadialGradient::clone() const
{
return std::make_unique<StrokeRadialGradient>(*this);
}
bool Renderer::StrokeRadialGradient::operator==(const MaterialStroke& m) const bool Renderer::StrokeRadialGradient::operator==(const MaterialStroke& m) const
{ {
return type() == m.type() return type() == m.type()
@ -87,6 +97,11 @@ std::vector<GLfloat> Renderer::MaterialStyleStroke::encoded() const
return v; return v;
} }
std::unique_ptr<MaterialStyle> Renderer::MaterialStyleStroke::clone() const
{
return std::make_unique<MaterialStyleStroke>(halfWidth*2, strokeType, endType, materialStroke->clone());
}
bool Renderer::MaterialStyleStroke::operator==(const MaterialStyle& m) const bool Renderer::MaterialStyleStroke::operator==(const MaterialStyle& m) const
{ {
return type() == m.type() && *materialStroke == *static_cast<const MaterialStyleStroke&>(m).materialStroke; return type() == m.type() && *materialStroke == *static_cast<const MaterialStyleStroke&>(m).materialStroke;

View File

@ -11,6 +11,7 @@ namespace Renderer
public: public:
virtual MaterialStrokeType type() const = 0; virtual MaterialStrokeType type() const = 0;
virtual std::vector<GLfloat> encoded() const = 0; virtual std::vector<GLfloat> encoded() const = 0;
virtual std::unique_ptr<MaterialStroke> clone() const = 0;
virtual bool operator==(const MaterialStroke&) const = 0; virtual bool operator==(const MaterialStroke&) const = 0;
}; };
@ -20,7 +21,9 @@ namespace Renderer
StrokePlain(QColor color, float metallic, float roughness); StrokePlain(QColor color, float metallic, float roughness);
StrokePlain(const Material& material); StrokePlain(const Material& material);
virtual MaterialStrokeType type() const override; virtual MaterialStrokeType type() const override;
virtual std::unique_ptr<MaterialStroke> clone() const override;
virtual std::vector<GLfloat> encoded() const override; virtual std::vector<GLfloat> encoded() const override;
virtual bool operator==(const MaterialStroke&) const override; virtual bool operator==(const MaterialStroke&) const override;
Material material; Material material;
@ -32,6 +35,7 @@ namespace Renderer
StrokeRadialGradient(const std::map<float, Material>& materialMap, bool gradual); StrokeRadialGradient(const std::map<float, Material>& materialMap, bool gradual);
virtual MaterialStrokeType type() const override; virtual MaterialStrokeType type() const override;
virtual std::vector<GLfloat> encoded() const override; virtual std::vector<GLfloat> encoded() const override;
virtual std::unique_ptr<MaterialStroke> clone() const override;
virtual bool operator==(const MaterialStroke&) const override; virtual bool operator==(const MaterialStroke&) const override;
std::map<float, Material> materialMap; std::map<float, Material> materialMap;
@ -47,9 +51,10 @@ namespace Renderer
MaterialStyleStroke(float width, StrokeType strokeType, StrokeEndType endType, std::shared_ptr<MaterialStroke> materialStroke); MaterialStyleStroke(float width, StrokeType strokeType, StrokeEndType endType, std::shared_ptr<MaterialStroke> materialStroke);
virtual MaterialStyleType type() const override; virtual MaterialStyleType type() const override;
virtual std::vector<GLfloat> encoded() const override; virtual std::vector<GLfloat> encoded() const override;
virtual std::unique_ptr<MaterialStyle> clone() const override;
virtual bool operator==(const MaterialStyle&) const override; virtual bool operator==(const MaterialStyle&) const override;
float getHalfWidth() const; float getHalfWidth() const;
protected: //protected:
float halfWidth; float halfWidth;
StrokeType strokeType; StrokeType strokeType;
StrokeEndType endType; StrokeEndType endType;

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
#include <QOpenGLFunctions_4_5_Core> #include <QOpenGLFunctions_4_5_Core>
#include <QString> #include <QString>
#include <QVector> #include <vector>
#include <QVector2D> #include <QVector2D>
#include <QVector3D> #include <QVector3D>
#include <QOpenGLShaderProgram> #include <QOpenGLShaderProgram>
@ -18,8 +18,8 @@ namespace Renderer
class PaintingMesh : public Drawable class PaintingMesh : public Drawable
{ {
public: public:
QVector<Vertex> vertices; std::vector<Vertex> vertices;
QVector<GLuint> indices; std::vector<GLuint> indices;
GLuint textureBasecolor; GLuint textureBasecolor;
GLuint textureMetallicRoughness; GLuint textureMetallicRoughness;
QMatrix4x4 model; QMatrix4x4 model;

View File

@ -12,22 +12,6 @@
#include "../Painting/MaterialStyleStroke.h" #include "../Painting/MaterialStyleStroke.h"
using namespace Renderer; using namespace Renderer;
Renderer::ElementRenderer::ElementRenderer(QOpenGLWidget* glWidget)
: glWidget(glWidget)
{
}
void Renderer::ElementRenderer::initialize()
{
initializeOpenGLFunctions();
shader = std::make_unique<QOpenGLShaderProgram>();
if (!shader->addShaderFromSourceFile(QOpenGLShader::Compute, ":/Shaders/element.comp"))
qDebug() << "ERROR: " << shader->log();
if (!shader->link())
qDebug() << "ERROR: " << shader->log();
}
std::vector<glm::vec2> generatePathBuffer(const QPainterPath& path) std::vector<glm::vec2> generatePathBuffer(const QPainterPath& path)
{ {
std::vector<glm::vec2> pathBuffer; std::vector<glm::vec2> pathBuffer;
@ -130,42 +114,94 @@ QRectF calcBoundingRect(const QPainterPath& path, const std::vector<BaseStyle>&
return QRectF(QPointF(leftTop.x, leftTop.y), QPointF(rightBottom.x, rightBottom.y)); return QRectF(QPointF(leftTop.x, leftTop.y), QPointF(rightBottom.x, rightBottom.y));
} }
std::pair<QImage, QPointF> Renderer::ElementRenderer::drawElement(const QPainterPath& path, const ElementStyle& style, float pixelRatio, bool releaseContext) Renderer::ElementRenderer::ElementRenderer()
{ {
auto baseStyles = style.toBaseStyles(); surface.create();
QRectF bound = calcBoundingRect(path, baseStyles); thread = std::jthread([&](std::stop_token stop) {
QPointF leftTop = bound.topLeft(); std::stop_callback cb(stop, [&] {
QSize size(ceil(bound.width() * pixelRatio), ceil(bound.height() * pixelRatio)); draw.notify_all();
});
auto pathBuffer = generatePathBuffer(path); QOpenGLContext context;
auto styleBuffer = generateStyleBuffer(baseStyles); context.create();
context.makeCurrent(&surface);
if (releaseContext) glWidget->makeCurrent(); auto gl = context.versionFunctions<QOpenGLFunctions_4_5_Core>();
shader = std::make_unique<QOpenGLShaderProgram>();
if (!shader->addShaderFromSourceFile(QOpenGLShader::Compute, ":/Shaders/element.comp"))
qDebug() << "ERROR: " << shader->log();
if (!shader->link())
qDebug() << "ERROR: " << shader->log();
GLuint ssbo[2]; initialized = true;
glCreateBuffers(2, ssbo);
glNamedBufferData(ssbo[0], pathBuffer.size() * sizeof(glm::vec2), pathBuffer.data(), GL_STATIC_READ);
glNamedBufferData(ssbo[1], styleBuffer.size() * sizeof(GLfloat), styleBuffer.data(), GL_STATIC_READ);
auto fbo = QOpenGLFramebufferObject(size, QOpenGLFramebufferObject::NoAttachment, GL_TEXTURE_2D); while (!stop.stop_requested())
fbo.bind(); {
glClearColor(0, 0, 0, 0); std::unique_lock<std::mutex> lock(drawMutex);
glClear(GL_COLOR_BUFFER_BIT); draw.wait(lock, [&] {return needDraw || stop.stop_requested(); });
fbo.release(); if (needDraw)
{
needDraw = false;
auto baseStyles = style->toBaseStyles();
QRectF bound = calcBoundingRect(*path, baseStyles);
QPointF leftTop = bound.topLeft();
QSize size(ceil(bound.width() * pixelRatio), ceil(bound.height() * pixelRatio));
shader->bind(); auto pathBuffer = generatePathBuffer(*path);
shader->setUniformValue("pathSize", (GLint)pathBuffer.size()); auto styleBuffer = generateStyleBuffer(baseStyles);
shader->setUniformValue("styleSize", (GLint)styleBuffer.size());
shader->setUniformValue("leftTop", leftTop);
shader->setUniformValue("pixelRatio", pixelRatio);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 10, ssbo[0]);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 11, ssbo[1]);
glBindImageTexture(0, fbo.texture(), 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8);
glDispatchCompute(ceil(size.width() / 8.), ceil(size.height() / 8.), 1);
shader->release();
auto image = fbo.toImage(false); GLuint ssbo[2];
glDeleteBuffers(2, ssbo); gl->glCreateBuffers(2, ssbo);
if (releaseContext) glWidget->doneCurrent(); gl->glNamedBufferData(ssbo[0], pathBuffer.size() * sizeof(glm::vec2), pathBuffer.data(), GL_STATIC_READ);
return { image, leftTop }; gl->glNamedBufferData(ssbo[1], styleBuffer.size() * sizeof(GLfloat), styleBuffer.data(), GL_STATIC_READ);
auto fbo = QOpenGLFramebufferObject(size, QOpenGLFramebufferObject::NoAttachment, GL_TEXTURE_2D);
fbo.bind();
gl->glClearColor(0, 0, 0, 0);
gl->glClear(GL_COLOR_BUFFER_BIT);
fbo.release();
shader->bind();
shader->setUniformValue("pathSize", (GLint)pathBuffer.size());
shader->setUniformValue("styleSize", (GLint)styleBuffer.size());
shader->setUniformValue("leftTop", leftTop);
shader->setUniformValue("pixelRatio", pixelRatio);
gl->glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 10, ssbo[0]);
gl->glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 11, ssbo[1]);
gl->glBindImageTexture(0, fbo.texture(), 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8);
gl->glDispatchCompute(ceil(size.width() / 8.), ceil(size.height() / 8.), 1);
shader->release();
auto image = fbo.toImage(false);
gl->glDeleteBuffers(2, ssbo);
result = { image, leftTop };
drawFinished = true;
}
draw.notify_all();
}
context.doneCurrent();
});
while (!initialized)
std::this_thread::yield();
} }
ElementRenderer* Renderer::ElementRenderer::instance()
{
static ElementRenderer renderer;
return &renderer;
}
std::pair<QImage, QPointF> Renderer::ElementRenderer::drawElement(const QPainterPath& path, const ElementStyle& style, float pixelRatio)
{
std::unique_lock<std::mutex> lock(drawMutex);
draw.wait(lock, [&] {return drawFinished; });
drawFinished = false;
this->path = &path;
this->style = &style;
this->pixelRatio = pixelRatio;
needDraw = true;
draw.notify_all();
draw.wait(lock, [&] {return drawFinished; });
return result;
}

View File

@ -3,32 +3,40 @@
#include <QOpenGLFunctions_4_5_Core> #include <QOpenGLFunctions_4_5_Core>
#include <QOPenGLShaderProgram> #include <QOPenGLShaderProgram>
#include "../Painting/ElementStyle.h" #include "../Painting/ElementStyle.h"
#include <QOffscreenSurface>
namespace Renderer namespace Renderer
{ {
class ElementRenderer : protected QOpenGLFunctions_4_5_Core class ElementRenderer
{ {
public: public:
ElementRenderer(QOpenGLWidget* glWidget); static ElementRenderer* instance();
/**
* @brief initializeGL
*/
void initialize();
/** /**
* @brief QImage * @brief QImage
* @param path * @param path
* @param style * @param style
* @param pixelRatio path * @param pixelRatio path
* @param releaseContext initializeGL, resizeGLpaintGLfalse
* @return QImage * @return QImage
* @return QPointF QPainterPath * @return QPointF QPainterPath
*/ */
std::pair<QImage, QPointF> drawElement(const QPainterPath& path, const ElementStyle& style, float pixelRatio, bool releaseContext = true); std::pair<QImage, QPointF> drawElement(const QPainterPath& path, const ElementStyle& style, float pixelRatio);
protected: protected:
QOpenGLWidget* glWidget;
std::unique_ptr<QOpenGLShaderProgram> shader; std::unique_ptr<QOpenGLShaderProgram> shader;
std::jthread thread;
QOffscreenSurface surface;
QOpenGLContext context;
std::atomic<bool> initialized = false;
bool drawFinished = true;
bool needDraw = false;
std::condition_variable draw;
std::mutex drawMutex;
const QPainterPath* path;
const ElementStyle* style;
float pixelRatio;
std::pair<QImage, QPointF> result;
ElementRenderer();
}; };
} }

View File

@ -73,17 +73,14 @@ void RendererGLWidget::stopTimer()
timerId = -1; timerId = -1;
} }
void RendererGLWidget::setModel() void RendererGLWidget::setModel(QString path)
{ {
makeCurrent(); makeCurrent();
model->loadModel("Models/Sponza/Sponza.gltf"); //model->loadModel("Models/Sponza/Sponza.gltf");
//model = new Model("E:\\3D Objects\\gallery_gltf\\gallery_gltf.gltf", context(), modelProgramPtr, paintingProgramPtr, shadowProgramPtr, paintingHelper); //model->loadModel("E:\\3D Objects\\Gate\\gltf\\Gate.gltf");
model->loadModel(path);
light.model = model; light.model = model;
qDebug() << model->AABB; qDebug() << model->AABB;
//paintingHelper->allocateBuffers();
//paintingCompProgramPtr->bind();
//paintingHelper->bindPaintingBuffers();
//paintingCompProgramPtr->release();
doneCurrent(); doneCurrent();
} }

View File

@ -26,7 +26,7 @@ namespace Renderer
void startTimer(); void startTimer();
void stopTimer(); void stopTimer();
public slots: public slots:
void setModel(); void setModel(QString path);
void setMainLightPitch(float pitch); void setMainLightPitch(float pitch);
void setMainLightYaw(float yaw); void setMainLightYaw(float yaw);
void setExposure(float exposure); void setExposure(float exposure);

View File

@ -1,29 +1,62 @@
#include "RendererWidget.h" #include "RendererWidget.h"
#include "RendererGLWidget.h" #include "RendererGLWidget.h"
using namespace Renderer; #include "../FluentMenu.h"
RendererWidget::RendererWidget(QWidget *parent) #include <QFileDialog>
Renderer::RendererWidget::RendererWidget(QWidget* parent)
: QWidget(parent) : QWidget(parent)
{ {
ui.setupUi(this); ui.setupUi(this);
FluentMenu* menu = new FluentMenu(this);
auto openAction = new QAction(QStringLiteral("´ò¿ª"), menu);
auto saveAction = new QAction(QStringLiteral("±£´æ"), menu);
auto testAction = new QAction(QStringLiteral("²âÊÔ"), menu);
menu->addAction(openAction);
menu->addAction(saveAction);
menu->addAction(testAction);
ui.openButton->setHaloVisible(false);
ui.openButton->setOverlayStyle(::Material::TintedOverlay);
ui.openButton->setCheckable(true);
QObject::connect(menu, &QMenu::aboutToShow, [&]() {
ui.openButton->setChecked(true);
});
QObject::connect(menu, &QMenu::aboutToHide, [&]() {
ui.openButton->setChecked(false);
});
QObject::connect(ui.openButton, &QPushButton::clicked, [&, menu]() {
menu->exec(ui.openButton->mapToGlobal(QPoint(-menu->shadowRadius, ui.openButton->height() - menu->shadowRadius)));
});
QObject::connect(ui.horizontalSlider, &QSlider::valueChanged, QObject::connect(ui.horizontalSlider, &QSlider::valueChanged,
ui.openGLWidget, &RendererGLWidget::setMainLightPitch); ui.openGLWidget, &Renderer::RendererGLWidget::setMainLightPitch);
QObject::connect(ui.horizontalSlider_2, &QSlider::valueChanged, QObject::connect(ui.horizontalSlider_2, &QSlider::valueChanged,
ui.openGLWidget, &RendererGLWidget::setMainLightYaw); ui.openGLWidget, &Renderer::RendererGLWidget::setMainLightYaw);
QObject::connect(ui.exposureSlider, &QSlider::valueChanged, [&](int value) { QObject::connect(ui.exposureSlider, &QSlider::valueChanged, [&](int value) {
ui.openGLWidget->setExposure(value/100.f); ui.openGLWidget->setExposure(value / 100.f);
});
QObject::connect(openAction, &QAction::triggered, [&] {
QString fileName = QFileDialog::getOpenFileName(this, QStringLiteral("´ò¿ªÄ£ÐÍ"), QString(), QStringLiteral("glTF 2.0 (*.gltf)"));
qDebug() << fileName;
if (fileName != QString())
ui.openGLWidget->setModel(fileName);
});
QObject::connect(testAction, &QAction::triggered, [&] {
ui.openGLWidget->setModel("Models/Sponza/Sponza.gltf");
}); });
ui.horizontalSlider->setValue(105); ui.horizontalSlider->setValue(105);
ui.horizontalSlider_2->setValue(80); ui.horizontalSlider_2->setValue(80);
ui.exposureSlider->setValue(60); ui.exposureSlider->setValue(60);
QObject::connect(ui.openButton, &QPushButton::clicked,
ui.openGLWidget, &RendererGLWidget::setModel);
} }
RendererWidget::~RendererWidget() Renderer::RendererWidget::~RendererWidget()
{} {}
void RendererWidget::currentTabChanged(int index) void Renderer::RendererWidget::currentTabChanged(int index)
{ {
if (index == 1) if (index == 1)
{ {
@ -33,4 +66,5 @@ void RendererWidget::currentTabChanged(int index)
{ {
ui.openGLWidget->stopTimer(); ui.openGLWidget->stopTimer();
} }
} }

View File

@ -1,15 +1,14 @@
#pragma once #pragma once
#include <QWidget> #include <QWidget>
#include <QMenu>
#include "ui_RendererWidget.h" #include "ui_RendererWidget.h"
namespace Renderer namespace Renderer
{ {
class RendererWidget : public QWidget class RendererWidget : public QWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
RendererWidget(QWidget* parent = nullptr); RendererWidget(QWidget* parent = nullptr);
~RendererWidget(); ~RendererWidget();
public slots: public slots:

View File

@ -18,7 +18,7 @@ Renderer::VirtualTextureManager::VirtualTextureManager(GladGLContext* glMain)
surface.create(); surface.create();
mainContext->doneCurrent(); mainContext->doneCurrent();
thread = std::jthread([&] { thread = std::jthread([&](std::stop_token stop) {
QOpenGLContext context; QOpenGLContext context;
context.setFormat(mainContext->format()); context.setFormat(mainContext->format());
context.setShareContext(mainContext); context.setShareContext(mainContext);
@ -67,7 +67,7 @@ Renderer::VirtualTextureManager::VirtualTextureManager(GladGLContext* glMain)
GLuint pageLoadTimeQuery; GLuint pageLoadTimeQuery;
gl->GenQueries(1, &pageLoadTimeQuery); gl->GenQueries(1, &pageLoadTimeQuery);
while (true) while (!stop.stop_requested())
{ {
if (needUpdate) if (needUpdate)
{ {
@ -85,6 +85,7 @@ Renderer::VirtualTextureManager::VirtualTextureManager(GladGLContext* glMain)
//qDebug() << duration; //qDebug() << duration;
pageLoadDuration += duration; pageLoadDuration += duration;
} }
std::this_thread::yield();
} }
}); });

View File

@ -1,80 +0,0 @@
/*
The MIT License (MIT)
Copyright © 2018-2022 Antonio Dias
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "titlewidget.h"
TitleWidget::TitleWidget(QWidget *parent) : QWidget(parent)
{
m_active = false;
}
void TitleWidget::setText(const QString &text)
{
m_title = text;
repaint();
}
void TitleWidget::setActive(bool active)
{
m_active = active;
repaint();
}
void TitleWidget::setTitleColor(const QColor &active_color, const QColor &inactive_color)
{
m_active_color = active_color;
m_inactive_color = inactive_color;
repaint();
}
void TitleWidget::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event)
QPainter painter(this);
painter.setRenderHints(QPainter::Antialiasing);
QFont font;
font.setPointSize(10);
#ifdef Q_OS_WIN
font.setFamily("Segoe UI, Microsoft YaHei UI");
#else
font.setFamily(qApp->font().family());
#endif
painter.setFont(font);
QPen pen;
pen.setColor(m_active ? m_active_color : m_inactive_color);
painter.setPen(pen);
QFontMetrics metrics(painter.font());
QSize title_size = metrics.size(0, m_title);
QString title = metrics.elidedText(m_title, Qt::ElideRight, width());
painter.drawText(0, (height() - title_size.height()) / 2, title_size.width(), title_size.height(), 0, title);
}

View File

@ -1,54 +0,0 @@
/*
The MIT License (MIT)
Copyright © 2018-2022 Antonio Dias
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef TITLEWIDGET_H
#define TITLEWIDGET_H
#include <QtCore>
#include <QtGui>
#include <QtWidgets>
class TitleWidget : public QWidget
{
Q_OBJECT
public:
explicit TitleWidget(QWidget *parent = nullptr);
public slots:
void setText(const QString &text);
void setActive(bool active);
void setTitleColor(const QColor &active_color, const QColor &inactive_color);
private:
//Functions
void paintEvent(QPaintEvent *event);
//Variables
QString m_title;
bool m_active;
QColor m_active_color;
QColor m_inactive_color;
};
#endif // TITLEWIDGET_H

View File

@ -52,7 +52,7 @@ int main(int argc, char* argv[])
//FramelessHelper::Core::setApplicationOSThemeAware(); //FramelessHelper::Core::setApplicationOSThemeAware();
FramelessConfig::instance()->set(Global::Option::ForceNonNativeBackgroundBlur); FramelessConfig::instance()->set(Global::Option::ForceNonNativeBackgroundBlur);
//FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow); //FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow);
FramelessConfig::instance()->set(Global::Option::CenterWindowBeforeShow); //FramelessConfig::instance()->set(Global::Option::CenterWindowBeforeShow);
MainWindow w; MainWindow w;
w.show(); w.show();
return a.exec(); return a.exec();

View File

@ -12,14 +12,20 @@ namespace UnitTest
{ {
TEST_CLASS(ElementRendererStokeTypeTest) TEST_CLASS(ElementRendererStokeTypeTest)
{ {
private:
char* argv[1];
int argc;
public: public:
TEST_METHOD(TestBothSidesRound) ElementRendererStokeTypeTest() :argv{ (char*)"" }, argc(1) {}
TEST_METHOD_INITIALIZE(initialize)
{ {
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough); QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
char* argv[] = { (char*)"" }; }
int argc = 1; TEST_METHOD(TestBothSidesRound)
{
QApplication a(argc, argv); QApplication a(argc, argv);
class StyleStrokeRadialGradient : public Renderer::ElementStyle class StyleStrokeRadialGradient : public Renderer::ElementStyle
{ {
@ -41,11 +47,6 @@ namespace UnitTest
} }
TEST_METHOD(TestBothSidesFlat) TEST_METHOD(TestBothSidesFlat)
{ {
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
char* argv[] = { (char*)"" };
int argc = 1;
QApplication a(argc, argv); QApplication a(argc, argv);
class StyleStrokeRadialGradient : public Renderer::ElementStyle class StyleStrokeRadialGradient : public Renderer::ElementStyle
{ {
@ -67,11 +68,6 @@ namespace UnitTest
} }
TEST_METHOD(TestLeftSideRound) TEST_METHOD(TestLeftSideRound)
{ {
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
char* argv[] = { (char*)"" };
int argc = 1;
QApplication a(argc, argv); QApplication a(argc, argv);
class StyleStrokeRadialGradient : public Renderer::ElementStyle class StyleStrokeRadialGradient : public Renderer::ElementStyle
{ {
@ -93,11 +89,6 @@ namespace UnitTest
} }
TEST_METHOD(TestLeftSideFlat) TEST_METHOD(TestLeftSideFlat)
{ {
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
char* argv[] = { (char*)"" };
int argc = 1;
QApplication a(argc, argv); QApplication a(argc, argv);
class StyleStrokeRadialGradient : public Renderer::ElementStyle class StyleStrokeRadialGradient : public Renderer::ElementStyle
{ {
@ -121,14 +112,13 @@ namespace UnitTest
TEST_CLASS(ElementRendererStokeMaterialTest) TEST_CLASS(ElementRendererStokeMaterialTest)
{ {
private:
char* argv[1];
int argc;
public: public:
ElementRendererStokeMaterialTest() :argv{ (char*)"" }, argc(1) {}
TEST_METHOD(TestStrokePlain) TEST_METHOD(TestStrokePlain)
{ {
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
char* argv[] = { (char*)"" };
int argc = 1;
QApplication a(argc, argv); QApplication a(argc, argv);
class StyleStrokePlain : public Renderer::ElementStyle class StyleStrokePlain : public Renderer::ElementStyle
{ {
@ -145,11 +135,6 @@ namespace UnitTest
} }
TEST_METHOD(TestStrokeRadialGradient1) TEST_METHOD(TestStrokeRadialGradient1)
{ {
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
char* argv[] = { (char*)"" };
int argc = 1;
QApplication a(argc, argv); QApplication a(argc, argv);
class StyleStrokeRadialGradient : public Renderer::ElementStyle class StyleStrokeRadialGradient : public Renderer::ElementStyle
{ {
@ -171,11 +156,6 @@ namespace UnitTest
} }
TEST_METHOD(TestStrokeRadialGradient2) TEST_METHOD(TestStrokeRadialGradient2)
{ {
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
char* argv[] = { (char*)"" };
int argc = 1;
QApplication a(argc, argv); QApplication a(argc, argv);
class StyleStrokeRadialGradient : public Renderer::ElementStyle class StyleStrokeRadialGradient : public Renderer::ElementStyle
{ {

View File

@ -14,15 +14,14 @@ namespace UnitTest
{ {
Q_OBJECT Q_OBJECT
private: private:
Renderer::ElementRenderer renderer; Renderer::ElementRenderer& renderer;
Renderer::ElementStyle& style; Renderer::ElementStyle& style;
public: public:
TestGLWidget(Renderer::ElementStyle& style, QWidget* parent = nullptr) TestGLWidget(Renderer::ElementStyle& style, QWidget* parent = nullptr)
: QOpenGLWidget(parent), renderer(this), style(style) {}; : QOpenGLWidget(parent), renderer(*Renderer::ElementRenderer::instance()), style(style) {};
void initializeGL() override void initializeGL() override
{ {
initializeOpenGLFunctions(); initializeOpenGLFunctions();
renderer.initialize();
}; };
void paintGL() override void paintGL() override
{ {
@ -35,7 +34,7 @@ namespace UnitTest
transform.scale(10, 10); transform.scale(10, 10);
path = transform.map(path); path = transform.map(path);
float pixelRatio = devicePixelRatioF(); float pixelRatio = devicePixelRatioF();
auto [img, pos] = renderer.drawElement(path, style, pixelRatio, false); auto [img, pos] = renderer.drawElement(path, style, pixelRatio);
QPainter painter(this); QPainter painter(this);
painter.setRenderHint(QPainter::SmoothPixmapTransform); painter.setRenderHint(QPainter::SmoothPixmapTransform);
painter.setRenderHint(QPainter::HighQualityAntialiasing); painter.setRenderHint(QPainter::HighQualityAntialiasing);

53
UnitTest/PaintingTest.cpp Normal file
View File

@ -0,0 +1,53 @@
#include "CppUnitTest.h"
#include "PaintingTest.h"
#include <QApplication>
#include "Renderer/Painting/Painting.h"
#include "Renderer/Painting/MaterialStyleStroke.h"
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
using namespace Renderer;
namespace UnitTest
{
TEST_CLASS(PaintingTest)
{
private:
char* argv[1];
int argc;
public:
PaintingTest() :argv{ (char*)"" }, argc(1) {}
TEST_METHOD_INITIALIZE(initialize)
{
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
}
TEST_METHOD(TestBothSidesRound)
{
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
QApplication a(argc, argv);
class StyleStrokeRadialGradient : public Renderer::ElementStyle
{
virtual std::vector<Renderer::BaseStyle> toBaseStyles() const override
{
std::map<float, Material> materialMap = {
{0.20, Material{QColor(255,255,255)}},
{0.60, Material{QColor(165,176,207)}},
{1.00, Material{QColor(58,64,151)}}
};
return { BaseStyle(std::make_shared<TransformStyle>(),
std::make_shared<MaterialStyleStroke>(60, StrokeType::kBothSides, StrokeEndType::kRound,
std::make_shared<StrokeRadialGradient>(materialMap, false))) };
}
} style;
TestPaintingGLWidget w(style);
w.show();
a.exec();
}
};
}

66
UnitTest/PaintingTest.h Normal file
View File

@ -0,0 +1,66 @@
#pragma once
#include <QOpenGLWidget>
#include <QOpenGLFunctions_4_5_Core>
#include "Renderer/Painting/ElementStyle.h"
#include <ThirdPartyLib/qquick/qquicksvgparser_p.h>
#include <util/SvgFileLoader.h>
#include <util/PainterPathUtil.h>
namespace UnitTest
{
class TestPaintingGLWidget : public QOpenGLWidget, protected QOpenGLFunctions_4_5_Core
{
Q_OBJECT
private:
Renderer::ElementStyle& style;
public:
TestPaintingGLWidget(Renderer::ElementStyle& style, QWidget* parent = nullptr)
: QOpenGLWidget(parent), style(style) {};
void initializeGL() override
{
initializeOpenGLFunctions();
/*std::vector<std::pair<std::shared_ptr<Contour>, float>> contours;
QPainterPath painterPaths[3];
QQuickSvgParser::parsePathDataFast("M100,100C-.5,100,0,100.5,0,0L40,.07C40,59.5,39.5,60,100,60Z",
painterPaths[0]);
if (!SvgFileLoader().loadSvgFile("../svg/2.svg", painterPaths[1]))
qCritical() << "load error";
QQuickSvgParser::parsePathDataFast("M377,459.61a11.26,11.26,0,0,1,11.27-11.27H696.12a11.27,11.27,0,0,0,11-8.62A359.84,359.84,0,0,0,708,280.56a11.26,11.26,0,0,0-11-8.73H388.27A11.26,11.26,0,0,1,377,260.57h0a11.26,11.26,0,0,1,11.27-11.26H683.71A11.32,11.32,0,0,0,694.28,234C649.8,113.69,542.57,23.85,412.3,4.12a11.22,11.22,0,0,0-12.76,11.17v158.9a11.26,11.26,0,0,0,11.26,11.27H583.12a11.32,11.32,0,0,0,9.26-17.75c-31.67-46.59-78.51-75.2-109.11-90.07a11.25,11.25,0,0,0-16.13,10.17V115.2a11.24,11.24,0,0,0,6.22,10.07l7.51,3.76a11.28,11.28,0,0,1,5,15.12h0a11.27,11.27,0,0,1-15.11,5l-20-10a11.27,11.27,0,0,1-6.22-10.07V54a11.27,11.27,0,0,1,14.62-10.75c5.11,1.59,125.66,40.35,172.24,149A11.27,11.27,0,0,1,621.11,208H388.27A11.26,11.26,0,0,1,377,196.73V11.36A11.32,11.32,0,0,0,365.89.08C363.34,0,360.79,0,358.22,0s-5.11,0-7.66.08a11.32,11.32,0,0,0-11.11,11.28V196.74A11.26,11.26,0,0,1,328.18,208H95.35A11.27,11.27,0,0,1,85,192.3c46.57-108.67,167.12-147.42,172.23-149A11.26,11.26,0,0,1,271.86,54v75.11a11.25,11.25,0,0,1-6.23,10.07l-20,10a11.27,11.27,0,0,1-15.11-5h0a11.26,11.26,0,0,1,5-15.11l7.52-3.76a11.27,11.27,0,0,0,6.22-10.07V87.82a11.25,11.25,0,0,0-16.14-10.16c-30.6,14.87-77.45,43.48-109.1,90.07a11.3,11.3,0,0,0,9.25,17.74H305.66a11.26,11.26,0,0,0,11.27-11.26V15.31A11.22,11.22,0,0,0,304.17,4.14C173.88,23.86,66.66,113.71,22.17,234a11.32,11.32,0,0,0,10.56,15.29H328.18a11.26,11.26,0,0,1,11.27,11.26v0a11.26,11.26,0,0,1-11.27,11.26H19.52a11.26,11.26,0,0,0-11,8.72,359.84,359.84,0,0,0,.83,159.16,11.26,11.26,0,0,0,11,8.61H328.18a11.26,11.26,0,0,1,11.27,11.27h0a11.26,11.26,0,0,1-11.27,11.26h-294a11.32,11.32,0,0,0-10.53,15.4C69,604.65,175.3,692.78,304.16,712.3a11.21,11.21,0,0,0,12.76-11.16V542.22A11.26,11.26,0,0,0,305.66,531h-166c-9.53,0-14.89,11.22-8.69,18.47,34.09,39.77,74.45,65.66,101.77,80.18a11.25,11.25,0,0,0,16.53-10V591a11.26,11.26,0,0,1,11.26-11.26h0A11.26,11.26,0,0,1,271.85,591v63.85A11.27,11.27,0,0,1,256.8,665.5c-4.45-1.59-109.58-40-171-139.9a11.27,11.27,0,0,1,9.59-17.17H328.18a11.26,11.26,0,0,1,11.27,11.26V705.08a11.32,11.32,0,0,0,11.11,11.28q3.82.07,7.66.08c2.57,0,5.12,0,7.67-.08A11.32,11.32,0,0,0,377,705.08V519.69a11.25,11.25,0,0,1,11.27-11.26H621.1a11.26,11.26,0,0,1,9.59,17.16c-61.46,99.87-166.59,138.3-171,139.9a11.27,11.27,0,0,1-15-10.61V591a11.26,11.26,0,0,1,11.26-11.26h0A11.26,11.26,0,0,1,467.14,591v28.6a11.25,11.25,0,0,0,16.53,10c27.33-14.53,67.68-40.42,101.77-80.19,6.2-7.23.85-18.46-8.69-18.46h-166a11.26,11.26,0,0,0-11.26,11.26V701.12a11.21,11.21,0,0,0,12.76,11.17c128.86-19.51,235.14-107.66,280.48-226a11.33,11.33,0,0,0-10.53-15.41h-294A11.25,11.25,0,0,1,377,459.61ZM35.27,399.53V316.9a11.26,11.26,0,0,1,11.27-11.26H669.92a11.25,11.25,0,0,1,11.26,11.26v82.63a11.25,11.25,0,0,1-11.26,11.26H46.54a11.27,11.27,0,0,1-11.27-11.26Z",
painterPaths[2]);
for (auto& i : painterPaths)
{
auto [contour, ratio] = PainterPathUtil::toNormalizedLines(i);
contours.emplace_back(std::make_shared<Contour>(contour), ratio);
}
std::vector<std::shared_ptr<ElementStyle>> style = {
std::make_shared<ElementStyleFillDemo>(),
std::make_shared<ElementStyleStrokeDemo>(0.02),
std::make_shared<ElementStyleStrokeRadialGradientDemo>(0.2)
};
std::vector<std::shared_ptr<Element>> element = {
std::make_shared<Element>(Element{ contours[0].first, style[0], contours[0].second}),
std::make_shared<Element>(Element{ contours[1].first, style[2], contours[1].second}),
std::make_shared<Element>(Element{ contours[2].first, style[0], contours[2].second}),
};
Painting painting;
painting.addElement(*element[0], ElementTransform{ glm::vec2(-0.45,-0.45), glm::vec2(0.5,0.5) / 2.f, 0, glm::bvec2(false), 0 });
painting.addElement(*element[1], ElementTransform{ glm::vec2(-0.45, 0.45), glm::vec2(0.5,0.5) / 2.f, 0, glm::bvec2(false), 0 });
painting.addElement(*element[2], ElementTransform{ glm::vec2(0.50,-0.45), glm::vec2(0.6,0.7) / 2.f, 0, glm::bvec2(false), 0 });
painting.generateBuffers(this);*/
//auto index = vtManager->createVirtualTexture(painting);
};
void paintGL() override
{
glClearColor(219 / 255., 78 / 255., 32 / 255., 1.0);
glClear(GL_COLOR_BUFFER_BIT);
};
void resizeGL(int w, int h) override {};
};
}

View File

@ -1,11 +1,12 @@
#include "CppUnitTest.h" #include "CppUnitTest.h"
#include "MainWindow.h" //#include "MainWindow.h"
#include <QGuiApplication> #include <QGuiApplication>
#include <QtWidgets/QApplication> #include <QtWidgets/QApplication>
#include <FramelessHelper/Core/private/framelessconfig_p.h> #include <FramelessHelper/Core/private/framelessconfig_p.h>
#include <util/SvgFileLoader.h> #include <util/SvgFileLoader.h>
#include "Renderer/Painting/CubicBezier.h" #include "Renderer/Painting/CubicBezier.h"
#include <Renderer/Painting/StraightLine.h> #include <Renderer/Painting/StraightLine.h>
#include <ElementPoolWidget.h>
using namespace Microsoft::VisualStudio::CppUnitTestFramework; using namespace Microsoft::VisualStudio::CppUnitTestFramework;
@ -43,24 +44,24 @@ namespace UnitTest
TEST_CLASS(UnitTest) TEST_CLASS(UnitTest)
{ {
public: public:
TEST_METHOD(TestMethod1) //TEST_METHOD(TestMethod1)
{ //{
FRAMELESSHELPER_USE_NAMESPACE // FRAMELESSHELPER_USE_NAMESPACE
FramelessHelper::Core::initialize(); // FramelessHelper::Core::initialize();
//QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); // //QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough); // QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
char arg[] = ""; // char arg[] = "";
char* argv[] = { arg }; // char* argv[] = { arg };
int argc = 1; // int argc = 1;
QApplication a(argc, argv); // QApplication a(argc, argv);
FramelessHelper::Core::setApplicationOSThemeAware(); // FramelessHelper::Core::setApplicationOSThemeAware();
FramelessConfig::instance()->set(Global::Option::ForceNonNativeBackgroundBlur); // FramelessConfig::instance()->set(Global::Option::ForceNonNativeBackgroundBlur);
FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow); // FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow);
FramelessConfig::instance()->set(Global::Option::CenterWindowBeforeShow); // FramelessConfig::instance()->set(Global::Option::CenterWindowBeforeShow);
MainWindow w; // MainWindow w;
w.show(); // w.show();
a.exec(); // a.exec();
} //}
}; };
TEST_CLASS(SvgLoaderTest) TEST_CLASS(SvgLoaderTest)
@ -94,5 +95,28 @@ namespace UnitTest
} }
}; };
TEST_CLASS(ElementPoolTest)
{
private:
char* argv[1];
int argc;
public:
ElementPoolTest() :argv{ (char*)"" }, argc(1) {}
TEST_METHOD_INITIALIZE(initialize)
{
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
}
TEST_METHOD(ElementPool) {
QApplication a(argc, argv);
qInstallMessageHandler(messageHandler);
ElementPoolWidget wi;
//wi.setElementList({"1", "2", "3"});
wi.setFixedSize(QSize(600, 800));
wi.show();
a.exec();
}
};
} }

View File

@ -65,11 +65,11 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile> <ClCompile>
<LanguageStandard>stdcpp20</LanguageStandard> <LanguageStandard>stdcpp20</LanguageStandard>
<AdditionalIncludeDirectories>$(VCInstallDir)UnitTest\include;$(SolutionDIr)ArchitectureColoredPainting;$(SolutionDIr)ArchitectureColoredPainting\include;$(SolutionDIr)ArchitectureColoredPainting\src;$(SolutionDir)ArchitectureColoredPainting\src\Editor\RightBar;$(SolutionDir)ArchitectureColoredPainting\src\Editor\;$(SolutionDIr)ArchitectureColoredPainting\x64\Debug\uic;$(SolutionDir)FramelessHelper\include;$(SolutionDir)FramelessHelper\qmake\inc\core;$(SolutionDir)FramelessHelper\include\FramelessHelper\Core;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>$(VCInstallDir)UnitTest\include;$(SolutionDIr)ArchitectureColoredPainting;$(SolutionDIr)ArchitectureColoredPainting\include;$(SolutionDIr)ArchitectureColoredPainting\src;$(SolutionDir)ArchitectureColoredPainting\src\Editor\RightBar;$(SolutionDir)ArchitectureColoredPainting\src\Editor\;$(SolutionDIr)ArchitectureColoredPainting\x64\Debug\uic;$(SolutionDir)FramelessHelper\include;$(SolutionDir)FramelessHelper\qmake\inc\core;$(SolutionDir)FramelessHelper\include\FramelessHelper\Core;$(SolutionDir)qt-material-widgets\components;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>FRAMELESSHELPER_WIDGETS_STATIC;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>FRAMELESSHELPER_WIDGETS_STATIC;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalDependencies>$(SolutionDIr)ArchitectureColoredPainting\x64\Debug\*.obj;$(SolutionDIr)FramelessHelper\qmake\FramelessHelperCore\debug\FramelessHelperCore.lib;$(SolutionDIr)FramelessHelper\qmake\FramelessHelperWidgets\debug\FramelessHelperWidgets.lib;opengl32.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>$(SolutionDIr)ArchitectureColoredPainting\x64\Debug\*.obj;$(SolutionDIr)FramelessHelper\qmake\FramelessHelperCore\debug\FramelessHelperCore.lib;$(SolutionDIr)FramelessHelper\qmake\FramelessHelperWidgets\debug\FramelessHelperWidgets.lib;$(SolutionDIr)qt-material-widgets\components\debug\components.lib;opengl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@ -111,6 +111,12 @@
<DynamicSource Condition="'$(Configuration)|$(Platform)'=='Release|x64'">input</DynamicSource> <DynamicSource Condition="'$(Configuration)|$(Platform)'=='Release|x64'">input</DynamicSource>
<QtMocFileName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(Filename).moc</QtMocFileName> <QtMocFileName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(Filename).moc</QtMocFileName>
</ClCompile> </ClCompile>
<ClCompile Include="PaintingTest.cpp">
<DynamicSource Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">input</DynamicSource>
<QtMocFileName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(Filename).moc</QtMocFileName>
<DynamicSource Condition="'$(Configuration)|$(Platform)'=='Release|x64'">input</DynamicSource>
<QtMocFileName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(Filename).moc</QtMocFileName>
</ClCompile>
<ClCompile Include="UnitTest.cpp" /> <ClCompile Include="UnitTest.cpp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@ -125,6 +131,9 @@
<ItemGroup> <ItemGroup>
<QtMoc Include="ElementRendererTest.h" /> <QtMoc Include="ElementRendererTest.h" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<QtMoc Include="PaintingTest.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Condition="Exists('$(QtMsBuild)\qt.targets')"> <ImportGroup Condition="Exists('$(QtMsBuild)\qt.targets')">
<Import Project="$(QtMsBuild)\qt.targets" /> <Import Project="$(QtMsBuild)\qt.targets" />

View File

@ -37,10 +37,16 @@
<QtMoc Include="ElementRendererTest.h"> <QtMoc Include="ElementRendererTest.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</QtMoc> </QtMoc>
<QtMoc Include="PaintingTest.h">
<Filter>Header Files</Filter>
</QtMoc>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="ElementRendererTest.cpp"> <ClCompile Include="ElementRendererTest.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="PaintingTest.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
</Project> </Project>