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

View File

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

View File

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

View File

@ -6,14 +6,23 @@
<rect>
<x>0</x>
<y>0</y>
<width>1124</width>
<height>695</height>
<width>1473</width>
<height>1103</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="windowTitle">
<string>RendererWidget</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
@ -28,53 +37,98 @@
</property>
<item>
<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>
<widget class="QLabel" name="Title">
<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">
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,12,5">
<item>
<widget class="QWidget" name="LeftBar" native="true"/>
</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>
<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>
<widget class="QTabWidget" name="DisplayTab">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="currentIndex">
<number>0</number>
<number>1</number>
</property>
<widget class="InfoDisplayWidget" name="LayerDisplay">
<attribute name="title">
<string>Layer</string>
<string>图层信息</string>
</attribute>
</widget>
<widget class="QWidget" name="ElementDisplay">
<widget class="ElementPoolWidget" name="ElementDisplay">
<attribute name="title">
<string>Element</string>
<string>图元池</string>
</attribute>
</widget>
</widget>
</item>
<item>
<widget class="LayerTreeWidget" name="LayerTree">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum>
</property>
<property name="accessibleName">
<string/>
</property>
<column>
<property name="text">
<string notr="true">1</string>
<string>图层树</string>
</property>
</column>
</widget>
@ -107,6 +161,12 @@
<header location="global">InfoDisplayWidget.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>ElementPoolWidget</class>
<extends>QWidget</extends>
<header>ElementPoolWidget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<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"?>
<ui version="4.0">
<class>MainWindowClass</class>
<widget class="QMainWindow" name="MainWindowClass">
<widget class="QWidget" name="MainWindowClass">
<property name="geometry">
<rect>
<x>0</x>
@ -10,102 +10,45 @@
<height>722</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<property name="styleSheet">
<string notr="true">font: 10pt &quot;Segoe UI, Microsoft YaHei UI&quot;;</string>
</property>
<widget class="QWidget" name="centralWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<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>
<layout class="QVBoxLayout" name="verticalLayout_4" stretch="1">
<property name="spacing">
<number>0</number>
</property>
<property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum>
</property>
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="font">
<font>
<family>Segoe UI, Microsoft YaHei UI</family>
<pointsize>10</pointsize>
<weight>50</weight>
<italic>false</italic>
<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>
<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="QGridLayout" name="gridLayout">
<property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="spacing">
<number>0</number>
</property>
<item row="0" column="0">
<widget class="QStackedWidget" name="stackedWidget">
<widget class="EditorWidget" name="editorWidget"/>
<widget class="Renderer::RendererWidget" name="rendererWidget"/>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>
@ -120,8 +63,6 @@
<header>Editor/EditorWidget.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="MainWindow.qrc"/>
</resources>
<resources/>
<connections/>
</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">
<string>RendererWidget</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,0,1">
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,1">
<property name="spacing">
<number>0</number>
</property>
@ -31,25 +31,37 @@
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum>
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="bottomMargin">
<number>5</number>
</property>
<item>
<widget class="QPushButton" name="openButton">
<widget class="QtMaterialFlatButton" name="openButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>40</height>
<width>50</width>
<height>30</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>50</width>
<height>30</height>
</size>
</property>
<property name="text">
<string>打开</string>
<string>文件</string>
</property>
<property name="flat">
<bool>false</bool>
@ -71,34 +83,6 @@
</item>
</layout>
</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>
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,0">
<property name="sizeConstraint">
@ -180,6 +164,11 @@
<extends>QOpenGLWidget</extends>
<header>RendererGLWidget.h</header>
</customwidget>
<customwidget>
<class>QtMaterialFlatButton</class>
<extends>QPushButton</extends>
<header location="global">qtmaterialflatbutton.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>

View File

@ -1190,7 +1190,7 @@ void main()
//imageStore(gBaseColor, pixelLocation, vec4(uv,1,1));
//imageStore(gMetallicRoughness, pixelLocation, vec4(uv,1,1));
//return;
uv = vec2(1)-uv*2;
uv = uv*2-vec2(1);
//vec2 uv = imageLoad(gPaintingTexCoord, pixelLocation).rg;
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;
this->filePath = filePath;
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(layerInfoDisplayWidget, &InfoDisplayWidget::requireRefreshPreview, this,
&EditorWidgetItem::triggerRefreshPreview);
@ -33,8 +39,12 @@ EditorWidgetItem::EditorWidgetItem(QString filePath,QWidget *parent) : QWidget(p
QJsonObject source = jsonDoc.object();
elementManager = new ElementManager(source,previewWindow->getRenderer());
layerManager = new LayerManager(source, elementManager);
elementInfoDisplayWidget->setElementManager(elementManager);
treeWidget->elementManager = elementManager;
qDebug() << layerManager->toJson();
previewWindow->initialize(layerManager,QSize(jsonDoc.object().value("width").toDouble(),jsonDoc.object().value("height").toDouble()));
if (layerManager->getRoot() != nullptr)
{
treeWidget->root = layerManager->getRoot();
@ -49,6 +59,11 @@ EditorWidgetItem::~EditorWidgetItem()
void EditorWidgetItem::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
// 设置画刷的颜色为灰色,并填充整个窗口区域
painter.setBrush(Qt::gray);
painter.drawRect(this->rect());
}
void EditorWidgetItem::onLayerChange(LayerWrapper *layer)

View File

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

View File

@ -10,7 +10,7 @@ ElementManager::ElementManager(QJsonObject source,Renderer::ElementRenderer* ren
elements.push_back(new GroupElement());
else
elements.push_back(new SimpleElement(elementJson.toObject()));
(*elements.rbegin())->name = elementJson.toObject().value("name").toString();
(*elements.rbegin())->renderer = renderer;
}
for (auto element : elements)
@ -19,10 +19,19 @@ ElementManager::ElementManager(QJsonObject source,Renderer::ElementRenderer* ren
void ElementManager::addElement(GraphicElement *element)
{
this->elements.push_back(element);
}
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)
@ -45,4 +54,49 @@ QJsonObject ElementManager::toJson() const
QJsonObject result;
result.insert("elements", elementsJson);
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 GraphicElement;
class Renderer::ElementRenderer;
class FolderLayerWrapper;
class ElementManager
{
private:
public:
vector<GraphicElement *> elements;
public:
@ -19,9 +20,14 @@ class ElementManager
~ElementManager();
void addElement(GraphicElement *element);
void removeElement(GraphicElement *pElement);
void removeElement(int index);
void createGroupElement(QString name, FolderLayerWrapper* sourceLayer);
void createSimpleElement(QString name, QString filePath);
QJsonObject toJson()const;
/**
* only used in initialization
*/
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
PixelPath SimpleElement::getPaintObject(std::vector<Renderer::ElementStyleStrokeDemo> styles) const {
PixelPath SimpleElement::getPaintObject(std::vector<std::shared_ptr<LayerStyle>>* styles) const {
PixelPath result;
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 << " ------";
result.addImage(img, mov);
//result.addPath(painterPath);
@ -59,7 +60,7 @@ PixelPath SimpleElement::getPaintObject(std::vector<Renderer::ElementStyleStroke
return result;
}
PixelPath GroupElement::getPaintObject(std::vector<Renderer::ElementStyleStrokeDemo> styles) const {
PixelPath GroupElement::getPaintObject(std::vector<std::shared_ptr<LayerStyle>>* styles) const {
return getPaintObject();
}

View File

@ -1,6 +1,7 @@
#pragma once
#include "LayerWrapper.h"
#include "LayerStyle.h"
#include <QJsonArray>
#include <QJsonObject>
#include <QPainterPath>
@ -26,7 +27,7 @@ public:
// TODO: ¸ÄΪBitmapPath
virtual QJsonObject toJson() const;
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
@ -39,9 +40,10 @@ private:
public:
SimpleElement(QJsonObject jsonSource);
SimpleElement(QString filePath);
~SimpleElement() = default;
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
@ -54,7 +56,7 @@ public:
GroupElement(FolderLayerWrapper* mSourceLayer);
~GroupElement() = default;
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);
};

View File

@ -11,10 +11,10 @@ LayerWrapper *LayerManager::getRoot() const
{
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);
painter->drawPixmap(0, 0, p);
root->getCache();
root->paint(painter);
}
bool LayerManager::singleSelectedCheck() const
{

View File

@ -32,7 +32,7 @@ class LayerManager
LayerManager() = default;
LayerManager(QJsonObject source, ElementManager* elementManager);
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 combine() const;
// bool seperate() const;

View File

@ -1,6 +1,103 @@
#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>();
}
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
#include <map>
#include <functional>
#include <utility>
#include <QWidget>
#include <QObject>
#include <QListWidget>
#include "../Renderer/Painting/ElementStyle.h"
#include "../Renderer/Painting/MaterialStyleStroke.h"
#include "../Renderer/Painting/MaterialStyleFill.h"
/**
* StylegetInputWidget()
* StylegetInputWidget()
*
* LayerStyleElementStylestyle
*
*/
class LayerStyle
{
public:
virtual void apply() = 0;
public:
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
{
float applyWidth;
Renderer::StrokeType strokeType;
Renderer::StrokeEndType endType;
std::shared_ptr<Renderer::MaterialStroke> materialStroke;
};
class StrokeElementStyle : Renderer::ElementStyle
class StrokeElementLayerStyle : public Renderer::ElementStyle, public LayerStyle
{
public:
virtual std::vector<Renderer::BaseStyle> toBaseStyles() const override;
std::vector<EditorStrokeMaterialStyle> materialStyles;
std::vector<Renderer::BaseStyle> toBaseStyles() const override;
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;
}
PixelPath LayerWrapper::getCache()
PixelPath LayerWrapper::getCache(LayerWrapper* selectedLayer)
{
this->refresh();
this->refresh(selectedLayer);
if (selectedLayer == this)
{
this->cache.highLight();
}
return cache;
}
// TODO: undone
LayerWrapper::LayerWrapper(QJsonObject json, FolderLayerWrapper*parent)
LayerWrapper::LayerWrapper(QJsonObject json, FolderLayerWrapper*parent, ElementManager* elementManager)
{
this->parent = parent;
this->elementManager = elementManager;
this->qTreeWidgetItem = new QTreeWidgetItem();
auto transformJson = json.value("transform").toObject();
property.name = json.value("name").toString();
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)
: LayerWrapper(json, parent)
: LayerWrapper(json, parent, elementManager)
{
qDebug() << json.value("name").toString() << " " << this;
QJsonArray childrenJson = json.value("children").toArray();
@ -73,6 +79,7 @@ LeafLayerWrapper::LeafLayerWrapper(QJsonObject json, ElementManager *elementMana
int elementIndex = json.value("element").toInt();
wrappedElement = elementManager->getElementById(elementIndex);
}
void LayerWrapper::SimpleProperty::apply(PixelPath&cache) const
{
QTransform trans;
@ -81,32 +88,48 @@ void LayerWrapper::SimpleProperty::apply(PixelPath&cache) const
//qDebug() << name << " " << cache.boundingRect().center();
//qDebug() << name << " " << cache.boundingRect();
trans.translate(centerX, centerY);
trans.scale(scale.x(), scale.y());
trans.rotate(rotation);
trans.translate(-centerX, -centerY);
trans.translate(offset.x(), offset.y());
trans.rotate(rotation);
trans.scale(scale.x(), scale.y());
trans.translate(-centerX, -centerY);
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);
}
void FolderLayerWrapper::refresh()
void FolderLayerWrapper::refresh(LayerWrapper* layer)
{
cache.clear();
for (auto& child : children) {
cache.addPath(child.get()->getCache());
cache.addPath(child.get()->getCache(layer));
}
LayerWrapper::refresh();
}
void LeafLayerWrapper::refresh()
void LeafLayerWrapper::refresh(LayerWrapper* layer)
{
cache.clear();
if (wrappedElement != nullptr)
{
cache.addPath(wrappedElement->getPaintObject(this->styles));
cache.addPath(wrappedElement->getPaintObject(&(this->styles)));
}
LayerWrapper::refresh();
}
@ -119,22 +142,22 @@ void LayerWrapper::setParent(FolderLayerWrapper* newParent)
void FolderLayerWrapper::removeAllChild()
{
children.clear();
qTreeWidgetItem.takeChildren();
qTreeWidgetItem->takeChildren();
}
void LayerWrapper::del() {
qDebug() << "LayerWrapper::del()";
if (parent != nullptr){
qTreeWidgetItem.takeChildren();
parent->qTreeWidgetItem.removeChild(&qTreeWidgetItem);
qTreeWidgetItem->takeChildren();
parent->qTreeWidgetItem->removeChild(qTreeWidgetItem);
}
}
void LayerWrapper::delSelf() {
qDebug() << "LayerWrapper::delSelf()";
if (parent != nullptr) {
qTreeWidgetItem.takeChildren();
parent->qTreeWidgetItem.removeChild(&qTreeWidgetItem);
qTreeWidgetItem->takeChildren();
parent->qTreeWidgetItem->removeChild(qTreeWidgetItem);
}
}
@ -154,7 +177,7 @@ void FolderLayerWrapper::delSelf() {
qDebug() << this;
for (auto& child : this->children) {
this->parent->addChild(child);
this->parent->qTreeWidgetItem.addChild(&child.get()->qTreeWidgetItem);
this->parent->qTreeWidgetItem->addChild(child.get()->qTreeWidgetItem);
child->setParent(this->parent);
}
while (!this->children.empty()) {
@ -166,18 +189,18 @@ void FolderLayerWrapper::delSelf() {
QTreeWidgetItem* LayerWrapper::getQTreeItem()
{
this->qTreeWidgetItem.setText(0, this->property.name);
this->qTreeWidgetItem.setData(0, Qt::UserRole, QVariant::fromValue(this));
return &this->qTreeWidgetItem;
this->qTreeWidgetItem->setText(0, this->property.name);
this->qTreeWidgetItem->setData(0, Qt::UserRole, QVariant::fromValue(this));
return this->qTreeWidgetItem;
}
QTreeWidgetItem* FolderLayerWrapper::getQTreeItem()
{
while (this->qTreeWidgetItem.childCount() > 0) {
this->qTreeWidgetItem.removeChild(this->qTreeWidgetItem.child(0));
while (this->qTreeWidgetItem->childCount() > 0) {
this->qTreeWidgetItem->removeChild(this->qTreeWidgetItem->child(0));
}
for (auto& child : this->children) {
this->qTreeWidgetItem.addChild(child->getQTreeItem());
this->qTreeWidgetItem->addChild(child->getQTreeItem());
}
return LayerWrapper::getQTreeItem();
}
@ -204,8 +227,8 @@ QJsonObject FolderLayerWrapper::toJson() const
childrenJson.push_back(child->toJson());
json.insert("children", childrenJson);
json.insert("is-folder", true);
if(this->referencedBy != -1)
json.insert("referenced-by", this->referencedBy);
if(this->getReferencedBy() != -1)
json.insert("referenced-by", this->getReferencedBy());
else
json.insert("referenced-by", QJsonValue());
return json;
@ -217,4 +240,41 @@ QJsonObject LeafLayerWrapper::toJson() const
json.insert("element", wrappedElement->index);
json.insert("is-folder", false);
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:
FolderLayerWrapper* parent;
QPointF referencePoint;
ElementManager* elementManager;
// vector<LayerStyle> styles;
// TODO: 将cache移到子类对Leaf用ComposedPainterPath对Folder用FolderBitmapPath
PixelPath cache;
public:
QTreeWidgetItem qTreeWidgetItem;
QTreeWidgetItem* qTreeWidgetItem;
struct SimpleProperty
{
QString name = "";
@ -46,13 +47,15 @@ class LayerWrapper
void apply(PixelPath&cache) const;
} property;
virtual void setParent(FolderLayerWrapper*newParent);
virtual void refresh();
virtual void refresh(LayerWrapper* layer = nullptr);
virtual QTreeWidgetItem* getQTreeItem();
// 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
LayerWrapper(QJsonObject json, FolderLayerWrapper*parent);
LayerWrapper(QJsonObject json, FolderLayerWrapper*parent, ElementManager* elementManager=nullptr);
LayerWrapper() = default;
virtual void paint(QPainter* painter);
// TODO : export Function
// virtual LayerWrapper *addChild() = 0; // Leaf Child Only
// virtual LayerWrapper *addParent() = 0; // Folder Parent Only
@ -74,7 +77,7 @@ class FolderLayerWrapper : public LayerWrapper
public:
~FolderLayerWrapper() = default;
void refresh() override;
void refresh(LayerWrapper* layer=nullptr) override;
FolderLayerWrapper() = default;
FolderLayerWrapper(QJsonObject json, ElementManager *elementManager, FolderLayerWrapper*parent);
void addChild(shared_ptr<LayerWrapper> child);
@ -84,20 +87,24 @@ class FolderLayerWrapper : public LayerWrapper
void delSelf() override;
QTreeWidgetItem* getQTreeItem() override;
QJsonObject toJson() const override;
int getReferencedBy()const;
void paint(QPainter* painter) override;
};
class LeafLayerWrapper : public LayerWrapper
{
public:
GraphicElement *wrappedElement;
const vector<Renderer::ElementStyleStrokeDemo> styles;
//const vector<Renderer::ElementStyleStrokeDemo> styles;
vector<std::shared_ptr<LayerStyle>> styles;
public:
~LeafLayerWrapper() = default;
void refresh() override;
void refresh(LayerWrapper* layer = nullptr) override;
LeafLayerWrapper() = default;
LeafLayerWrapper(QJsonObject json, ElementManager *elementManager, FolderLayerWrapper*parent);
QJsonObject toJson() const override;
void paint(QPainter* painter) override;
};
Q_DECLARE_METATYPE(LayerWrapper *)

View File

@ -32,10 +32,15 @@ QPixmap PixelPath::getPixmap() const
return pixmap;
}
QPainterPath PixelPath::getPainterPath() const {
return painterPath;
}
void PixelPath::addPath(const PixelPath& path)
{
QPainter painter(&pixmap);
painter.drawPixmap(0, 0, path.getPixmap());
this->painterPath.addPath(path.getPainterPath());
boundingRect = boundingRect.united(path.getBoundingRect());
}
@ -46,6 +51,7 @@ void PixelPath::addPath(const QPainterPath& path)
painter.setRenderHint(QPainter::HighQualityAntialiasing);
painter.setPen(QPen(Qt::black,1));
painter.drawPath(path);
this->painterPath.addPath(path);
boundingRect = boundingRect.united(path.boundingRect());
}
@ -83,5 +89,32 @@ QPixmap PixelPath::resizedPixel(QSize size)const
painter.setRenderHint(QPainter::SmoothPixmapTransform);
painter.setRenderHint(QPainter::HighQualityAntialiasing);
painter.drawPixmap(0, 0, pixmap.scaled(size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
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:
QRectF boundingRect;
QPixmap pixmap;
QPainterPath painterPath;
int w,h;
public:
PixelPath(int w=1920, int h= 1080);
PixelPath(QPainterPath painterPath,int w = 1920, int h = 1080);
PixelPath(int w=1080, int h= 1080);
PixelPath(QPainterPath painterPath,int w = 1080, int h = 1080);
~PixelPath() = default;
QRectF getBoundingRect() const;
QPixmap getPixmap() const;
QPainterPath getPainterPath() const;
void addPath(const PixelPath& path);
void addPath(const QPainterPath& path);
void addImage(const QImage& image,const QPointF& pos);
void clear();
PixelPath trans(QTransform& mat)const;
QPixmap resizedPixel(QSize size)const;
QPixmap getDetail()const;
void highLight();
};

View File

@ -2,7 +2,8 @@
PreviewWindow::PreviewWindow(QWidget *parent) : QOpenGLWidget(parent)
{
this->renderer = new Renderer::ElementRenderer(this);
this->setFixedSize(QSize(1080, 1080));
this->renderer = Renderer::ElementRenderer::instance();
QSurfaceFormat surfaceFormat;
surfaceFormat.setSamples(16);
setFormat(surfaceFormat);
@ -10,6 +11,7 @@ PreviewWindow::PreviewWindow(QWidget *parent) : QOpenGLWidget(parent)
painter->setRenderHint(QPainter::SmoothPixmapTransform);
painter->setRenderHint(QPainter::HighQualityAntialiasing);
layerManager = nullptr;
currentLayer = nullptr;
}
void PreviewWindow::initialize(LayerManager *layerManager,QSize windowSize)
@ -36,7 +38,6 @@ void PreviewWindow::show()
void PreviewWindow::initializeGL()
{
this->renderer->initialize();
initializeOpenGLFunctions();
}
@ -47,7 +48,7 @@ void PreviewWindow::paintGL()
painter->begin(this);
painter->setRenderHint(QPainter::Antialiasing);
painter->setRenderHint(QPainter::HighQualityAntialiasing);
layerManager->paint(painter,this->size());
layerManager->paint(painter,this->size(),currentLayer);
painter->end();
}
@ -57,4 +58,50 @@ void PreviewWindow::resizeGL(int w, int h)
Renderer::ElementRenderer* const PreviewWindow::getRenderer()const {
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 <QJsonValue>
#include <QOpenGLFunctions>
#include <QMouseEvent>
#include <QOpenGLWidget>
#include "../Renderer/Preview/ElementRenderer.h"
@ -19,7 +20,13 @@ class PreviewWindow : public QOpenGLWidget, protected QOpenGLFunctions
LayerManager *layerManager;
Renderer::ElementRenderer* renderer;
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:
PreviewWindow(QWidget *parent = nullptr);
void initialize(LayerManager *layerManager, QSize windowSize = QSize(1920, 1080));
@ -28,4 +35,11 @@ class PreviewWindow : public QOpenGLWidget, protected QOpenGLFunctions
void paintGL() override;
void resizeGL(int w, int h) override;
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 "./EditorWidgetComponent/LayerStyleDialog.h"
#include <QLineEdit>
#include <QTextBlock>
#include <QListWidget>
#include <QPushButton>
#include <QDialog>
#include <QComboBox>
#include <QDialogButtonBox>
#include <qtmaterialraisedbutton.h>
#include <qtmaterialflatbutton.h>
void InfoDisplayWidget::setLayer(LayerWrapper *layer)
{
this->displayLayer = layer;
generateLayerForm();
}
void InfoDisplayWidget::setElement(GraphicElement *element)
{
this->displayElement = element;
generateElementForm();
}
void InfoDisplayWidget::generateLayerForm()
{
QLayoutItem *item;
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;
@ -47,26 +46,31 @@ void InfoDisplayWidget::generateLayerForm()
rotation->setValidator(new QIntValidator(-10000, 10000, this));
connect(rotation, &QLineEdit::textChanged, [=](QString content) {
this->displayLayer->property.rotation = content.toDouble();
emit requireRefreshElementWidget();
emit requireRefreshPreview();
});
offsetX->setValidator(new QIntValidator(-10000, 10000, this));
connect(offsetX, &QLineEdit::textChanged, [=](QString content) {
this->displayLayer->property.offset = {content.toDouble(), this->displayLayer->property.offset.y()};
emit requireRefreshElementWidget();
emit requireRefreshPreview();
});
offsetY->setValidator(new QIntValidator(-10000, 10000, this));
connect(offsetY, &QLineEdit::textChanged, [=](QString content) {
this->displayLayer->property.offset = {this->displayLayer->property.offset.x(), content.toDouble()};
emit requireRefreshElementWidget();
emit requireRefreshPreview();
});
scaleX->setValidator(new QDoubleValidator(0.001, 1000, 4, this));
connect(scaleX, &QLineEdit::textChanged, [=](QString content) {
this->displayLayer->property.scale = {content.toDouble(), this->displayLayer->property.scale.y()};
emit requireRefreshElementWidget();
emit requireRefreshPreview();
});
scaleY->setValidator(new QDoubleValidator(0.001, 1000, 4, this));
connect(scaleY, &QLineEdit::textChanged, [=](QString content) {
this->displayLayer->property.scale = {this->displayLayer->property.scale.x(), content.toDouble()};
emit requireRefreshElementWidget();
emit requireRefreshPreview();
});
@ -78,78 +82,165 @@ void InfoDisplayWidget::generateLayerForm()
layout->addRow("scale-Y:", scaleY);
layout->setRowWrapPolicy(QFormLayout::DontWrapRows);
bool styleEnabled = true;
if (styleEnabled) {
LeafLayerWrapper* leafP = dynamic_cast<LeafLayerWrapper*>(this->displayLayer);
if (leafP) {
QListWidget* styleList = new QListWidget(this);
QListWidgetItem* item = new QListWidgetItem("样式列表");
item->setFlags(Qt::NoItemFlags);
styleList->addItem(item);
static vector<QString> styleNames = { "样例1", "样例2", "样例3" };
auto createStyleItem = [this, styleList](int index) {
QListWidgetItem* header = new QListWidgetItem;
QWidget* headerWidget = new QWidget(styleList);
QHBoxLayout* headerLayout = new QHBoxLayout;
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;
QWidget* w = new QWidget;
item->setSizeHint(QSize(50, 40));
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);
QLabel* name = new QLabel(w);
name->setText(styleNames[index]);
detailButton->setText("...");
QPushButton* removeButton = new QPushButton(w);
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();
// 在此处修改新样式信息至内存
removeButton->setText("×");
removeButton->setFixedSize(QSize(20, 20));
connect(detailButton, &QPushButton::clicked, this,
[this, styleIterator]()
{
LayerStyleDialog* dialog = new LayerStyleDialog(nullptr, *styleIterator);
dialog->exec();
if (dialog->layerStyle)
{
(*styleIterator) = dialog->layerStyle;
emit requireRefreshPreview();
emit requireSelfRefresh();
emit requireRefreshElementWidget();
}
dialog->deleteLater();
});
connect(removeButton, &QPushButton::clicked, this,
[this, styleIterator, styles]()
{
styles->erase(styleIterator);
emit requireRefreshPreview();
emit requireSelfRefresh();
}
emit requireRefreshElementWidget();
});
connect(deleteButton, &QPushButton::clicked, [styleList,item,this]() {
styleList->removeItemWidget(item);
delete item;
// 删除layer对应样式
emit requireRefreshPreview();
emit requireSelfRefresh();
});
layout->addWidget(name);
QWidget* styleDisplayWidget = (*styleIterator)->getListDisplayWidget();
styleDisplayWidget->setParent(w);
styleDisplayWidget->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
layout->addWidget(styleDisplayWidget);
layout->addWidget(detailButton);
layout->addWidget(deleteButton);
layout->addWidget(removeButton);
w->setLayout(layout);
styleList->addItem(item);
styleList->setItemWidget(item, w);
};
for (int i = 0; i < styleNames.size(); i++)
createStyleItem(i);
}
layout->addRow(styleList);
}
}
this->setLayout(layout);
}
void InfoDisplayWidget::generateElementForm()
{
}
void InfoDisplayWidget::triggerSelfRefresh()
{
if (this->displayLayer != nullptr)
this->generateLayerForm();
if (this->displayElement != nullptr)
this->generateElementForm();
}

View File

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

View File

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

View File

@ -1,5 +1,6 @@
#pragma once
#include "LayerWrapper.h"
#include "ElementManager.h"
#include <QPoint>
#include <QTreeWidget>
class LayerTreeWidget : public QTreeWidget
@ -10,6 +11,7 @@ class LayerTreeWidget : public QTreeWidget
LayerWrapper *copiedItem;
public:
ElementManager* elementManager;
LayerWrapper* root;
LayerTreeWidget(QWidget *parent = nullptr);
void onRenameEvent();
@ -18,7 +20,8 @@ class LayerTreeWidget : public QTreeWidget
// void mouseDoubleClickEvent(QMouseEvent *event) override;
// void onItemDoubleClicked(QTreeWidgetItem *item, int column = 0);
signals:
signals:
void displayLayerChange(LayerWrapper *);
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) {
QTransform trans;
QStringList ops = transformStyle.split(')');
reverse(ops.begin(), ops.end());
vector<double> numbers;
for (auto op : ops) {
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 "qslider.h"
#include <QPushButton>
#include <QScreen>
#include "NavigationBarWidget.h"
#include <FramelessHelper/Core/utils.h>
#include <FramelessHelper/Widgets/standardtitlebar.h>
@ -11,111 +12,13 @@
FRAMELESSHELPER_USE_NAMESPACE
inline void fontTheme()
{
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)
CentralWidget::CentralWidget(QWidget* parent) : QWidget(parent)
{
ui.setupUi(this);
NavigationBarWidget* navigationBarWidget = new NavigationBarWidget();
QHBoxLayout* tabBarLayout = new QHBoxLayout(ui.tabWidget);
tabBarLayout->setSpacing(0);
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);
NavigationBarWidget* navigationBarWidget = new NavigationBarWidget(this);
ui.gridLayout->addWidget(navigationBarWidget, 0, 0, 1, 1, Qt::AlignTop | Qt::AlignHCenter);
QObject::connect(navigationBarWidget->tabs, &QtMaterialTabs::currentChanged, ui.stackedWidget, &QStackedWidget::setCurrentIndex);
QObject::connect(ui.stackedWidget, &QStackedWidget::currentChanged, ui.rendererWidget, &Renderer::RendererWidget::currentTabChanged);
}
CentralWidget::~CentralWidget()
@ -133,38 +36,29 @@ MainWindow::MainWindow(QWidget* parent, const Qt::WindowFlags flags)
m_titleBar->maximizeButton()->setFixedHeight(kTitleBarHeight);
m_titleBar->closeButton()->setFixedHeight(kTitleBarHeight);
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_window = new FramelessWindow(this);
m_central_widget = new CentralWidget(this);
m_window->ui->windowContent->layout()->addWidget(m_central_widget);
setMenuWidget(m_titleBar);
setCentralWidget(m_window);
setCentralWidget(m_central_widget);
FramelessWidgetsHelper* helper = FramelessWidgetsHelper::get(this);
helper->setTitleBarWidget(m_titleBar);
#ifndef Q_OS_MACOS
helper->setSystemButton(m_titleBar->minimizeButton(), Global::SystemButtonType::Minimize);
helper->setSystemButton(m_titleBar->maximizeButton(), Global::SystemButtonType::Maximize);
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"));
setWindowTitle("ArchitectureColoredPainting");
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)
event->ignore();*/
qDebug() << "closeEvent";
}

View File

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

View File

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

View File

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

View File

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

View File

@ -45,26 +45,50 @@ void Model::drawShadow() {
void Renderer::Model::loadModel(QString path)
{
directory = path;
QFileInfo modelFile(path);
name = modelFile.baseName();
directory = modelFile.dir();
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)
{
qDebug() << "ERROR::ASSIMP::" << importer.GetErrorString() << endl;
qCritical() << "ERROR::ASSIMP::" << importer.GetErrorString() << endl;
return;
}
qDebug() << directory.absolutePath() << "Loaded Successfully";
qDebug() << modelFile.absoluteFilePath() << "Loaded Successfully";
qDebug() << "NumMeshes: " << scene->mNumMeshes;
qDebug() << "NumMaterials: " << scene->mNumMaterials;
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();
maxX = std::numeric_limits<float>::min();
minY = std::numeric_limits<float>::max();
maxY = std::numeric_limits<float>::min();
minZ = std::numeric_limits<float>::max();
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, maxZ));
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)
{
aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex];
QMatrix4x4 modelQ((float*)&model);
aiString str;
material->GetTexture(aiTextureType_BASE_COLOR, 0, &str);
if (paintingProgram != nullptr && (std::strcmp(str.C_Str(), "17876391417123941155.jpg") == 0 || std::strcmp(str.C_Str(), "11474523244911310074.jpg") == 0))
std::vector<Vertex> vertices;
for (unsigned int i = 0; i < mesh->mNumVertices; i++)
{
qDebug() << str.C_Str() << "Replaced";
// 初始化网格
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])
{
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);
}
auto pos = mesh->mVertices[i];
vertices.push_back(Vertex(pos, mesh->mNormals[i], mesh->mTextureCoords[0][i]));
auto worldPos = model * pos;
minX = std::min(minX, worldPos.x);
maxX = std::max(maxX, worldPos.x);
minY = std::min(minY, worldPos.y);
maxY = std::max(maxY, worldPos.y);
minZ = std::min(minZ, worldPos.z);
maxZ = std::max(maxZ, worldPos.z);
}
}
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];
// 将所有面的索引数据添加到索引数组中
for (unsigned int j = 0; j < face.mNumIndices; j++) {
m_mesh->indices.push_back(face.mIndices[j]);
}
//qDebug() << v.TexCoords.x << v.TexCoords.y;
v.TexCoords = (v.TexCoords - leftBottom) / (rightTop - leftBottom);
qDebug() << v.TexCoords.x << v.TexCoords.y;
}
m_mesh->paintingId = loadPainting(std::string(str.C_Str()));
auto& handle = vtManager->getPaintingHandle(m_mesh->paintingId);
m_mesh->textureBasecolor = handle.baseColor;
m_mesh->textureMetallicRoughness = handle.metallicRoughness;
m_mesh->setupMesh();
return m_mesh;
mesh->vertices = vertices;
mesh->indices = indices;
mesh->paintingId = loadPainting(paintingPath);
auto& handle = vtManager->getPaintingHandle(mesh->paintingId);
mesh->textureBasecolor = handle.baseColor;
mesh->textureMetallicRoughness = handle.metallicRoughness;
mesh->setupMesh();
return mesh;
}
else
{
// 初始化网格
auto m_mesh = std::make_unique<Mesh>(glFunc, shaderProgram, shadowProgram, modelQ);
// 遍历网格的每个顶点
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);
}
}
auto mesh = std::make_unique<Mesh>(glFunc, shaderProgram, shadowProgram, modelQ);
mesh->vertices = vertices;
mesh->indices = indices;
// 将所有面的索引数据添加到索引数组中
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)))
if (!(mesh->textureBasecolor = loadMaterialTextures(material, aiTextureType_BASE_COLOR)))
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!";
if (!(m_mesh->textureNormal = loadMaterialTextures(material, aiTextureType_NORMALS)))
if (!(mesh->textureNormal = loadMaterialTextures(material, aiTextureType_NORMALS)))
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();
return m_mesh;
mesh->setupMesh();
return mesh;
}
else
return nullptr;
@ -203,7 +218,7 @@ GLuint Model::loadMaterialTextures(aiMaterial* mat, aiTextureType type)
texture.setWrapMode(QOpenGLTexture::DirectionS, QOpenGLTexture::Repeat);
texture.setWrapMode(QOpenGLTexture::DirectionT, QOpenGLTexture::Repeat);
texture.setMinMagFilters(QOpenGLTexture::LinearMipMapLinear, QOpenGLTexture::Linear);
texture.setData(data);
texture.setData(data.mirrored());
return texture.textureId();
}
@ -250,7 +265,7 @@ GLuint Renderer::Model::loadPainting(std::string path)
};
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[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);
auto index = vtManager->createVirtualTexture(painting);

View File

@ -17,20 +17,24 @@ namespace Renderer
void loadModel(QString path);
Model(QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* paintingProgram, QOpenGLShaderProgram* shadowProgram, VirtualTextureManager* vtManager);
private:
QOpenGLContext* context;
QOpenGLContext* context = nullptr;
QOpenGLFunctions_4_5_Core* glFunc = nullptr;
QOpenGLShaderProgram* shaderProgram = nullptr;
QOpenGLShaderProgram* paintingProgram = nullptr;
QOpenGLShaderProgram* shadowProgram = 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, QOpenGLTexture> texturesLoaded;
std::vector<std::unique_ptr<Drawable>> meshes;
/// 模型所在路径
QDir directory;
QDir directory; /// 模型所在路径
QString name; /// 模型文件名
float minX, maxX, minY, maxY, minZ, maxZ;

View File

@ -23,6 +23,7 @@ namespace Renderer
public:
virtual MaterialStyleType type() const = 0;
virtual std::vector<GLfloat> encoded() const = 0;
virtual std::unique_ptr<MaterialStyle> clone() 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())))};
}
std::unique_ptr<MaterialFill> Renderer::FillPlain::clone() const
{
return std::make_unique<FillPlain>(*this);
}
bool Renderer::FillPlain::operator==(const MaterialFill& m) const
{
return type() == m.type()
@ -42,6 +47,11 @@ std::vector<GLfloat> Renderer::MaterialStyleFill::encoded() const
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
{
return type() == m.type() && *materialFill == *static_cast<const MaterialStyleFill&>(m).materialFill;

View File

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

View File

@ -18,6 +18,11 @@ MaterialStrokeType Renderer::StrokePlain::type() const
return MaterialStrokeType::kPlain;
}
std::unique_ptr<MaterialStroke> Renderer::StrokePlain::clone() const
{
return std::make_unique<StrokePlain>(*this);
}
std::vector<GLfloat> Renderer::StrokePlain::encoded() const
{
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;
}
std::unique_ptr<MaterialStroke> Renderer::StrokeRadialGradient::clone() const
{
return std::make_unique<StrokeRadialGradient>(*this);
}
bool Renderer::StrokeRadialGradient::operator==(const MaterialStroke& m) const
{
return type() == m.type()
@ -87,6 +97,11 @@ std::vector<GLfloat> Renderer::MaterialStyleStroke::encoded() const
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
{
return type() == m.type() && *materialStroke == *static_cast<const MaterialStyleStroke&>(m).materialStroke;

View File

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

View File

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

View File

@ -12,22 +12,6 @@
#include "../Painting/MaterialStyleStroke.h"
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> 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));
}
std::pair<QImage, QPointF> Renderer::ElementRenderer::drawElement(const QPainterPath& path, const ElementStyle& style, float pixelRatio, bool releaseContext)
Renderer::ElementRenderer::ElementRenderer()
{
auto baseStyles = style.toBaseStyles();
QRectF bound = calcBoundingRect(path, baseStyles);
QPointF leftTop = bound.topLeft();
QSize size(ceil(bound.width() * pixelRatio), ceil(bound.height() * pixelRatio));
surface.create();
thread = std::jthread([&](std::stop_token stop) {
std::stop_callback cb(stop, [&] {
draw.notify_all();
});
auto pathBuffer = generatePathBuffer(path);
auto styleBuffer = generateStyleBuffer(baseStyles);
QOpenGLContext context;
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];
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);
initialized = true;
auto fbo = QOpenGLFramebufferObject(size, QOpenGLFramebufferObject::NoAttachment, GL_TEXTURE_2D);
fbo.bind();
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
fbo.release();
while (!stop.stop_requested())
{
std::unique_lock<std::mutex> lock(drawMutex);
draw.wait(lock, [&] {return needDraw || stop.stop_requested(); });
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();
shader->setUniformValue("pathSize", (GLint)pathBuffer.size());
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 pathBuffer = generatePathBuffer(*path);
auto styleBuffer = generateStyleBuffer(baseStyles);
auto image = fbo.toImage(false);
glDeleteBuffers(2, ssbo);
if (releaseContext) glWidget->doneCurrent();
return { image, leftTop };
GLuint ssbo[2];
gl->glCreateBuffers(2, ssbo);
gl->glNamedBufferData(ssbo[0], pathBuffer.size() * sizeof(glm::vec2), pathBuffer.data(), GL_STATIC_READ);
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 <QOPenGLShaderProgram>
#include "../Painting/ElementStyle.h"
#include <QOffscreenSurface>
namespace Renderer
{
class ElementRenderer : protected QOpenGLFunctions_4_5_Core
class ElementRenderer
{
public:
ElementRenderer(QOpenGLWidget* glWidget);
/**
* @brief initializeGL
*/
void initialize();
static ElementRenderer* instance();
/**
* @brief QImage
* @param path
* @param style
* @param pixelRatio path
* @param releaseContext initializeGL, resizeGLpaintGLfalse
* @return QImage
* @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:
QOpenGLWidget* glWidget;
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;
}
void RendererGLWidget::setModel()
void RendererGLWidget::setModel(QString path)
{
makeCurrent();
model->loadModel("Models/Sponza/Sponza.gltf");
//model = new Model("E:\\3D Objects\\gallery_gltf\\gallery_gltf.gltf", context(), modelProgramPtr, paintingProgramPtr, shadowProgramPtr, paintingHelper);
//model->loadModel("Models/Sponza/Sponza.gltf");
//model->loadModel("E:\\3D Objects\\Gate\\gltf\\Gate.gltf");
model->loadModel(path);
light.model = model;
qDebug() << model->AABB;
//paintingHelper->allocateBuffers();
//paintingCompProgramPtr->bind();
//paintingHelper->bindPaintingBuffers();
//paintingCompProgramPtr->release();
doneCurrent();
}

View File

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

View File

@ -1,29 +1,62 @@
#include "RendererWidget.h"
#include "RendererGLWidget.h"
using namespace Renderer;
RendererWidget::RendererWidget(QWidget *parent)
#include "../FluentMenu.h"
#include <QFileDialog>
Renderer::RendererWidget::RendererWidget(QWidget* parent)
: QWidget(parent)
{
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,
ui.openGLWidget, &RendererGLWidget::setMainLightPitch);
ui.openGLWidget, &Renderer::RendererGLWidget::setMainLightPitch);
QObject::connect(ui.horizontalSlider_2, &QSlider::valueChanged,
ui.openGLWidget, &RendererGLWidget::setMainLightYaw);
ui.openGLWidget, &Renderer::RendererGLWidget::setMainLightYaw);
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_2->setValue(80);
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)
{
@ -33,4 +66,5 @@ void RendererWidget::currentTabChanged(int index)
{
ui.openGLWidget->stopTimer();
}
}
}

View File

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

View File

@ -18,7 +18,7 @@ Renderer::VirtualTextureManager::VirtualTextureManager(GladGLContext* glMain)
surface.create();
mainContext->doneCurrent();
thread = std::jthread([&] {
thread = std::jthread([&](std::stop_token stop) {
QOpenGLContext context;
context.setFormat(mainContext->format());
context.setShareContext(mainContext);
@ -67,7 +67,7 @@ Renderer::VirtualTextureManager::VirtualTextureManager(GladGLContext* glMain)
GLuint pageLoadTimeQuery;
gl->GenQueries(1, &pageLoadTimeQuery);
while (true)
while (!stop.stop_requested())
{
if (needUpdate)
{
@ -85,6 +85,7 @@ Renderer::VirtualTextureManager::VirtualTextureManager(GladGLContext* glMain)
//qDebug() << 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();
FramelessConfig::instance()->set(Global::Option::ForceNonNativeBackgroundBlur);
//FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow);
FramelessConfig::instance()->set(Global::Option::CenterWindowBeforeShow);
//FramelessConfig::instance()->set(Global::Option::CenterWindowBeforeShow);
MainWindow w;
w.show();
return a.exec();

View File

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

View File

@ -14,15 +14,14 @@ namespace UnitTest
{
Q_OBJECT
private:
Renderer::ElementRenderer renderer;
Renderer::ElementRenderer& renderer;
Renderer::ElementStyle& style;
public:
TestGLWidget(Renderer::ElementStyle& style, QWidget* parent = nullptr)
: QOpenGLWidget(parent), renderer(this), style(style) {};
: QOpenGLWidget(parent), renderer(*Renderer::ElementRenderer::instance()), style(style) {};
void initializeGL() override
{
initializeOpenGLFunctions();
renderer.initialize();
};
void paintGL() override
{
@ -35,7 +34,7 @@ namespace UnitTest
transform.scale(10, 10);
path = transform.map(path);
float pixelRatio = devicePixelRatioF();
auto [img, pos] = renderer.drawElement(path, style, pixelRatio, false);
auto [img, pos] = renderer.drawElement(path, style, pixelRatio);
QPainter painter(this);
painter.setRenderHint(QPainter::SmoothPixmapTransform);
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 "MainWindow.h"
//#include "MainWindow.h"
#include <QGuiApplication>
#include <QtWidgets/QApplication>
#include <FramelessHelper/Core/private/framelessconfig_p.h>
#include <util/SvgFileLoader.h>
#include "Renderer/Painting/CubicBezier.h"
#include <Renderer/Painting/StraightLine.h>
#include <ElementPoolWidget.h>
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
@ -43,24 +44,24 @@ namespace UnitTest
TEST_CLASS(UnitTest)
{
public:
TEST_METHOD(TestMethod1)
{
FRAMELESSHELPER_USE_NAMESPACE
FramelessHelper::Core::initialize();
//QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
char arg[] = "";
char* argv[] = { arg };
int argc = 1;
QApplication a(argc, argv);
FramelessHelper::Core::setApplicationOSThemeAware();
FramelessConfig::instance()->set(Global::Option::ForceNonNativeBackgroundBlur);
FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow);
FramelessConfig::instance()->set(Global::Option::CenterWindowBeforeShow);
MainWindow w;
w.show();
a.exec();
}
//TEST_METHOD(TestMethod1)
//{
// FRAMELESSHELPER_USE_NAMESPACE
// FramelessHelper::Core::initialize();
// //QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
// QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
// char arg[] = "";
// char* argv[] = { arg };
// int argc = 1;
// QApplication a(argc, argv);
// FramelessHelper::Core::setApplicationOSThemeAware();
// FramelessConfig::instance()->set(Global::Option::ForceNonNativeBackgroundBlur);
// FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow);
// FramelessConfig::instance()->set(Global::Option::CenterWindowBeforeShow);
// MainWindow w;
// w.show();
// a.exec();
//}
};
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'">
<ClCompile>
<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>
</ClCompile>
<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>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@ -111,6 +111,12 @@
<DynamicSource Condition="'$(Configuration)|$(Platform)'=='Release|x64'">input</DynamicSource>
<QtMocFileName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(Filename).moc</QtMocFileName>
</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" />
</ItemGroup>
<ItemGroup>
@ -125,6 +131,9 @@
<ItemGroup>
<QtMoc Include="ElementRendererTest.h" />
</ItemGroup>
<ItemGroup>
<QtMoc Include="PaintingTest.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Condition="Exists('$(QtMsBuild)\qt.targets')">
<Import Project="$(QtMsBuild)\qt.targets" />

View File

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