TaoZhang-Branch
ArgonarioD 2023-03-09 19:54:07 +08:00
commit e7bce3f93e
1308 changed files with 30854 additions and 1443 deletions

View File

@ -14,6 +14,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UnitTest", "UnitTest\UnitTe
{3FE96A33-2BB7-4686-A710-3EB8E3BBD709} = {3FE96A33-2BB7-4686-A710-3EB8E3BBD709}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "components", "qt-material-widgets\components\components.vcxproj", "{8F360763-A045-3808-87A9-3FAE38E69819}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "examples", "qt-material-widgets\examples\examples.vcxproj", "{2CF18346-77C1-3A0A-B9ED-8B38C828491B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
@ -54,6 +58,22 @@ Global
{C81742B7-2428-4329-BEA8-01E4B985810A}.Release|x64.Build.0 = Release|x64
{C81742B7-2428-4329-BEA8-01E4B985810A}.Release|x86.ActiveCfg = Release|x64
{C81742B7-2428-4329-BEA8-01E4B985810A}.Release|x86.Build.0 = Release|x64
{8F360763-A045-3808-87A9-3FAE38E69819}.Debug|x64.ActiveCfg = Debug|x64
{8F360763-A045-3808-87A9-3FAE38E69819}.Debug|x64.Build.0 = Debug|x64
{8F360763-A045-3808-87A9-3FAE38E69819}.Debug|x86.ActiveCfg = Debug|x64
{8F360763-A045-3808-87A9-3FAE38E69819}.Debug|x86.Build.0 = Debug|x64
{8F360763-A045-3808-87A9-3FAE38E69819}.Release|x64.ActiveCfg = Release|x64
{8F360763-A045-3808-87A9-3FAE38E69819}.Release|x64.Build.0 = Release|x64
{8F360763-A045-3808-87A9-3FAE38E69819}.Release|x86.ActiveCfg = Release|x64
{8F360763-A045-3808-87A9-3FAE38E69819}.Release|x86.Build.0 = Release|x64
{2CF18346-77C1-3A0A-B9ED-8B38C828491B}.Debug|x64.ActiveCfg = Debug|x64
{2CF18346-77C1-3A0A-B9ED-8B38C828491B}.Debug|x64.Build.0 = Debug|x64
{2CF18346-77C1-3A0A-B9ED-8B38C828491B}.Debug|x86.ActiveCfg = Debug|x64
{2CF18346-77C1-3A0A-B9ED-8B38C828491B}.Debug|x86.Build.0 = Debug|x64
{2CF18346-77C1-3A0A-B9ED-8B38C828491B}.Release|x64.ActiveCfg = Release|x64
{2CF18346-77C1-3A0A-B9ED-8B38C828491B}.Release|x64.Build.0 = Release|x64
{2CF18346-77C1-3A0A-B9ED-8B38C828491B}.Release|x86.ActiveCfg = Release|x64
{2CF18346-77C1-3A0A-B9ED-8B38C828491B}.Release|x86.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -68,7 +68,7 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<LanguageStandard>stdcpp20</LanguageStandard>
<AdditionalIncludeDirectories>$(ProjectDir)include;$(SolutionDir)ArchitectureColoredPainting\src\Editor\RightBar;$(SolutionDir)ArchitectureColoredPainting\src\Editor\;$(SolutionDir)FramelessHelper\include;$(SolutionDir)FramelessHelper\qmake\inc\core;$(SolutionDir)FramelessHelper\include\FramelessHelper\Core;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(ProjectDir)include;$(SolutionDir)ArchitectureColoredPainting\src\Editor\RightBar;$(SolutionDir)ArchitectureColoredPainting\src\Editor\;$(SolutionDir)FramelessHelper\include;$(SolutionDir)FramelessHelper\qmake\inc\core;$(SolutionDir)FramelessHelper\include\FramelessHelper\Core;$(SolutionDir)qt-material-widgets\components;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>FRAMELESSHELPER_WIDGETS_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<WarningLevel>Level1</WarningLevel>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
@ -104,10 +104,13 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="src\Editor\EditorWidgetComponent\LayerCreateWidget.cpp" />
<ClCompile Include="src\Editor\LayerStyleDialog.cpp" />
<ClCompile Include="src\CaptionButton.cpp" />
<ClCompile Include="src\Editor\EditorWidget.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 +122,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,12 +153,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="EditorWidget.ui" />
<QtUic Include="FramelessWindow.ui" />
<QtUic Include="EditorWidgetItem.ui" />
<QtUic Include="MainWindow.ui" />
<QtUic Include="NavigationBarWidget.ui" />
<QtUic Include="RendererWidget.ui" />
<QtUic Include="src\Editor\EditorWidgetComponent\LayerCreateWidget.ui" />
</ItemGroup>
<ItemGroup>
<None Include="..\data.json" />
@ -188,8 +191,11 @@
<QtMoc Include="src\Editor\RightBar\LayerTreeWidget.h" />
<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\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" />
@ -200,7 +206,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" />
@ -213,12 +221,9 @@
<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\EditorWidget.h" />
<QtMoc Include="src\Editor\EditorWidgetItem.h" />
<ClInclude Include="src\Renderer\Painting\BvhTree.h" />
<ClInclude Include="src\Renderer\Camera.h" />
<ClInclude Include="src\Renderer\Painting\CubicBezier.h" />
@ -239,6 +244,9 @@
<ProjectReference Include="..\FramelessHelper\qmake\FramelessHelperWidgets\FramelessHelperWidgets.vcxproj">
<Project>{e7a71e05-4aa5-31db-a17d-542fc7bd83a3}</Project>
</ProjectReference>
<ProjectReference Include="..\qt-material-widgets\components\components.vcxproj">
<Project>{8f360763-a045-3808-87a9-3fae38e69819}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Condition="Exists('$(QtMsBuild)\qt.targets')">

View File

@ -70,15 +70,15 @@
<QtUic Include="MainWindow.ui">
<Filter>Form Files</Filter>
</QtUic>
<QtUic Include="NavigationBarWidget.ui">
<QtUic Include="EditorWidget.ui">
<Filter>Form Files</Filter>
</QtUic>
<QtUic Include="FramelessWindow.ui">
<QtUic Include="src\Editor\EditorWidgetComponent\LayerCreateWidget.ui">
<Filter>Form Files</Filter>
</QtUic>
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\Editor\EditorWidget.cpp">
<ClCompile Include="src\Editor\EditorWidgetItem.cpp">
<Filter>Source Files\Editor</Filter>
</ClCompile>
<ClCompile Include="src\Renderer\Camera.cpp">
@ -114,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>
@ -213,6 +204,21 @@
<ClCompile Include="src\Editor\PixelPath.cpp">
<Filter>Source Files\Editor</Filter>
</ClCompile>
<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\LayerStyleDialog.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@ -221,7 +227,7 @@
<QtMoc Include="src\Renderer\RendererGLWidget.h">
<Filter>Header Files\Renderer</Filter>
</QtMoc>
<QtMoc Include="src\Editor\EditorWidget.h">
<QtMoc Include="src\Editor\EditorWidgetItem.h">
<Filter>Header Files\Editor</Filter>
</QtMoc>
<QtMoc Include="src\Renderer\RendererWidget.h">
@ -230,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>
@ -251,6 +248,18 @@
<QtMoc Include="src\Editor\RightBar\InfoDisplayWidget.h">
<Filter>Header Files</Filter>
</QtMoc>
<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\LayerStyleDialog.h">
<Filter>Header Files</Filter>
</QtMoc>
@ -334,7 +343,7 @@
</None>
</ItemGroup>
<ItemGroup>
<QtUic Include="EditorWidget.ui">
<QtUic Include="EditorWidgetItem.ui">
<Filter>Form Files</Filter>
</QtUic>
<QtUic Include="RendererWidget.ui">
@ -444,6 +453,9 @@
<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>

View File

@ -1,108 +1,199 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>EditorWidgetClass</class>
<widget class="QWidget" name="EditorWidgetClass">
<class>EditorWidget</class>
<widget class="QWidget" name="EditorWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1124</width>
<height>695</height>
<width>1139</width>
<height>862</height>
</rect>
</property>
<property name="windowTitle">
<string>RendererWidget</string>
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<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="MainWindow" native="true">
<layout class="QVBoxLayout" name="verticalLayout_2" stretch="1,30">
<item>
<widget class="QLabel" name="Title">
<property name="text">
<string>纹理编辑</string>
<layout class="QVBoxLayout" name="verticalLayout" stretch="1,20">
<property name="topMargin">
<number>0</number>
</property>
<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="alignment">
<set>Qt::AlignCenter</set>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,18,5">
<item>
<widget class="QWidget" name="LeftBar" native="true"/>
</item>
<item>
<widget class="PreviewWindow" name="Preview"/>
</item>
<item>
<widget class="QWidget" name="RightBar" native="true">
<layout class="QVBoxLayout" name="verticalLayout_4" stretch="1,2">
<item>
<widget class="QTabWidget" name="DisplayTab">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="InfoDisplayWidget" name="LayerDisplay">
<attribute name="title">
<string>Layer</string>
</attribute>
</widget>
<widget class="QWidget" name="ElementDisplay">
<attribute name="title">
<string>Element</string>
</attribute>
</widget>
</widget>
</item>
<item>
<widget class="LayerTreeWidget" name="LayerTree">
<property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum>
</property>
</widget>
</item>
</layout>
</widget>
<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>40</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>80</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>新建</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="openButton">
<property name="minimumSize">
<size>
<width>80</width>
<height>40</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>80</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>打开</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="saveButton">
<property name="minimumSize">
<size>
<width>80</width>
<height>40</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>80</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>保存</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="saveAsButton">
<property name="minimumSize">
<size>
<width>80</width>
<height>40</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>80</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>另存为</string>
</property>
</widget>
</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>40</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>80</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>关闭</string>
</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>
</item>
</layout>
</widget>
</widget>
</item>
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="minimumSize">
<size>
<width>0</width>
<height>800</height>
</size>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="tab">
<attribute name="title">
<string>Tab 1</string>
</attribute>
</widget>
<widget class="QWidget" name="tab_2">
<attribute name="title">
<string>Tab 2</string>
</attribute>
</widget>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>
<customwidget>
<class>PreviewWindow</class>
<extends>QOpenGLWidget</extends>
<header>PreviewWindow.h</header>
</customwidget>
<customwidget>
<class>LayerTreeWidget</class>
<extends>QTreeWidget</extends>
<header location="global">LayerTreeWidget.h</header>
</customwidget>
<customwidget>
<class>InfoDisplayWidget</class>
<extends>QWidget</extends>
<header location="global">InfoDisplayWidget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View File

@ -0,0 +1,160 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>EditorWidgetItem</class>
<widget class="QWidget" name="EditorWidgetItem">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1124</width>
<height>1010</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>
<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="MainWindow" native="true">
<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>
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,12,5">
<item>
<widget class="QWidget" name="LeftBar" native="true"/>
</item>
<item>
<widget class="PreviewWindow" name="Preview"/>
</item>
<item>
<widget class="QWidget" name="RightBar" native="true">
<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>1</number>
</property>
<widget class="InfoDisplayWidget" name="LayerDisplay">
<attribute name="title">
<string>图层信息</string>
</attribute>
</widget>
<widget class="ElementPoolWidget" name="ElementDisplay">
<attribute name="title">
<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>图层树</string>
</property>
</column>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>
<customwidget>
<class>PreviewWindow</class>
<extends>QOpenGLWidget</extends>
<header>PreviewWindow.h</header>
</customwidget>
<customwidget>
<class>LayerTreeWidget</class>
<extends>QTreeWidget</extends>
<header location="global">LayerTreeWidget.h</header>
</customwidget>
<customwidget>
<class>InfoDisplayWidget</class>
<extends>QWidget</extends>
<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/>
</ui>

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

@ -40,65 +40,20 @@
<number>0</number>
</property>
<item>
<layout class="QVBoxLayout" name="verticalLayout_4" stretch="1">
<property name="spacing">
<number>0</number>
</property>
<layout class="QGridLayout" name="gridLayout">
<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 {
height: 0px;
margin-top:0px;
}
QTabWidget::tab-bar
{
height: 0px;
top:0px;
}
QTabWidget::pane {
border: 0px;
background-color: rgba(0, 0, 0, 0);
}
</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>
<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>
@ -119,8 +74,6 @@ QTabWidget::pane {
<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

@ -22,8 +22,9 @@ layout(std430, binding = 2) buffer elementOffsetBuffer
* @[1] styleOffset
* @[2] pointsOffset
* @[3] linesOffset
*/
uint elementOffset[][4];
uint elementOffset[][5];
};
layout(std430, binding = 3) buffer elementIndexBuffer
{
@ -961,7 +962,7 @@ void drawLine(in float d, in uint styleIndex, out vec4 elementColor, out vec2 me
}
}
bool drawElement(uint elementIndex, vec2 localUV, out vec3 color, out vec2 metallicRoughness, inout vec3 debugBVH = vec3(0))
bool drawElement(uint elementIndex, vec2 localUV, vec2 scale, out vec3 color, out vec2 metallicRoughness, inout vec3 debugBVH = vec3(0))
{
bool hitElement = false;
vec4 elementColor = vec4(-1);
@ -1053,6 +1054,13 @@ bool drawElement(uint elementIndex, vec2 localUV, out vec3 color, out vec2 metal
else //Ïß
{
float strokeWidth = elementData[styleIndex];
float widthHeightRatio = uintBitsToFloat(currentOffset[4]);
vec2 size = normalize(vec2(widthHeightRatio, 1)) + vec2(2 * strokeWidth);
vec2 ratio = widthHeightRatio < 1 ? vec2(widthHeightRatio, 1) : vec2(1, 1 / widthHeightRatio);
localUV *= ratio;
uint contourIndex = linesOffset + leftChild - 0x80000000;
float minDistance = 1e38;
uint lineCount = elementIndexs[contourIndex];
@ -1077,6 +1085,11 @@ bool drawElement(uint elementIndex, vec2 localUV, out vec3 color, out vec2 metal
elementData[pxIndex[2]], elementData[pyIndex[2]],
elementData[pxIndex[3]], elementData[pyIndex[3]]);
p[0] *= ratio;
p[1] *= ratio;
p[2] *= ratio;
p[3] *= ratio;
if(p[0]==p[1]&&p[2]==p[3])
{
p[1] = (p[0]+p[3])/2;
@ -1203,7 +1216,8 @@ void main()
mat2 rotation = {{cos(angle), -sin(angle)}, {sin(angle), cos(angle)}};
vec2 localUV = uv - (bound.xy + bound.zw) / 2;
localUV = rotation * localUV;
localUV /= (bound.zw - bound.xy) / 2;
vec2 scale = (bound.zw - bound.xy) / 2;
localUV /= scale;
if (all(lessThan(vec2(-1), localUV)) && all(lessThan(localUV, vec2(1))) && zIndex>color.w)
{
//if (any(greaterThan(bound.xy+vec2(0.005), uv)) || any(greaterThan(uv, bound.zw-vec2(0.005))))
@ -1217,7 +1231,7 @@ void main()
if(flip.y) localUV.y = -localUV.y;
vec3 elementColor;
vec2 elementMetallicRoughness;
if(drawElement(leftChild - 0x80000000, localUV, elementColor, elementMetallicRoughness, debugBVH))
if(drawElement(leftChild - 0x80000000, localUV, scale, elementColor, elementMetallicRoughness, debugBVH))
{
color = vec4(elementColor, zIndex);
metallicRoughness = elementMetallicRoughness;

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

@ -1,62 +1,48 @@
#include "EditorWidget.h"
#include "EditorWidgetItem.h"
#include <QMouseEvent>
#include <QInputDialog>
#include <QMenu>
#include <QFileDialog>
EditorWidget::EditorWidget(QWidget *parent) : QWidget(parent)
EditorWidget::EditorWidget(QWidget* parent) : QWidget(parent)
{
QImage x;
displayLayer = nullptr;
displayElement = nullptr;
ui.setupUi(this);
previewWindow = ui.Preview;
treeWidget = ui.LayerTree;
tabWidget = ui.DisplayTab;
layerInfoDisplayWidget = dynamic_cast<InfoDisplayWidget *>(tabWidget->widget(0));
elementInfoDisplayWidget = dynamic_cast<InfoDisplayWidget *>(tabWidget->widget(1));
connect(treeWidget, &LayerTreeWidget::displayLayerChange, this, &EditorWidget::onLayerChange);
connect(layerInfoDisplayWidget, &InfoDisplayWidget::requireRefreshPreview, this,
&EditorWidget::triggerRefreshPreview);
connect(treeWidget, &LayerTreeWidget::requireRefreshPreview, this,
&EditorWidget::triggerRefreshPreview);
connect(layerInfoDisplayWidget, &InfoDisplayWidget::requireSelfRefresh, layerInfoDisplayWidget, &InfoDisplayWidget::triggerSelfRefresh);
// &EditorWidget::triggerRefreshPreview);
// test
QFile settingFile;
settingFile.setFileName("../data.json");
settingFile.open(QFile::ReadOnly);
QByteArray setting = settingFile.readAll().trimmed();
QJsonParseError jError;
QJsonDocument jsonDoc(QJsonDocument::fromJson(setting, &jError));
qDebug() << jsonDoc.object().value("height").toDouble();
qDebug() << jError.errorString();
// end test
QJsonObject source = jsonDoc.object();
elementManager = new ElementManager(source,previewWindow->getRenderer());
layerManager = new LayerManager(source, elementManager);
previewWindow->initialize(layerManager,QSize(jsonDoc.object().value("width").toDouble(),jsonDoc.object().value("height").toDouble()));
if (layerManager->getRoot() != nullptr)
{
treeWidget->root = layerManager->getRoot();
treeWidget->refresh();
treeWidget->addTopLevelItem(treeWidget->root->getQTreeItem());
}
ui.setupUi(this);
this->createButton = ui.createButton;
this->closeButton = ui.closeButton;
this->saveButton = ui.saveButton;
this->saveAsButton = ui.saveAsButton;
this->openButton = ui.openButton;
this->tabWidget = ui.tabWidget;
while (this->tabWidget->count() > 0)
{
this->tabWidget->removeTab(0);
}
connect(this->createButton, &QPushButton::clicked, this, [this]() {
static int count = 0;
this->tabWidget->addTab(new EditorWidgetItem("../data.json",this), "untitled" + QString::number(count++));
});
connect(this->openButton, &QPushButton::clicked, this, [this]() {
QString fileName = QFileDialog::getOpenFileName(this->saveAsButton, QString::fromLocal8Bit("´ò¿ª"), "", QString::fromLocal8Bit("JSONÎļþ(*.json)"));
this->tabWidget->addTab(new EditorWidgetItem(fileName, this), fileName);
});
connect(this->closeButton, &QPushButton::clicked, this, [this]() {
this->tabWidget->removeTab(this->tabWidget->currentIndex());
});
connect(this->saveButton, &QPushButton::clicked, this, [this]() {
EditorWidgetItem* item = dynamic_cast<EditorWidgetItem*>(this->tabWidget->currentWidget());
if (item != nullptr)
{
//item->save();
}
});
connect(this->saveAsButton, &QPushButton::clicked, this, [this]() {
EditorWidgetItem* item = dynamic_cast<EditorWidgetItem*>(this->tabWidget->currentWidget());
if (item != nullptr)
{
QString fileName = QFileDialog::getSaveFileName(this->saveAsButton, QString::fromLocal8Bit("Áí´æΪ"), "", QString::fromLocal8Bit("JSONÎļþ(*.json)"));
item->saveAs(fileName);
}
});
}
EditorWidget::~EditorWidget()
{
}
void EditorWidget::paintEvent(QPaintEvent *event)
{
}
void EditorWidget::onLayerChange(LayerWrapper *layer)
{
displayLayer = layer;
// TODO : notify InfoDisplayWidget and update
dynamic_cast<InfoDisplayWidget *>(tabWidget->widget(0))->setLayer(layer);
this->update();
}
void EditorWidget::triggerRefreshPreview()
{
previewWindow->update();
}

View File

@ -1,39 +1,23 @@
#pragma once
#include "ElementManager.h"
#include "InfoDisplayWidget.h"
#include "LayerManager.h"
#include "LayerTreeWidget.h"
#include "PreviewWindow.h"
#include <qwidget.h>
#include "ui_EditorWidget.h"
#include <QPainter>
#include <QTreeWidget>
#include <QWidget>
class EditorWidget : public QWidget
class EditorWidget :
public QWidget
{
Q_OBJECT
private:
// DATA PART
PreviewWindow *previewWindow;
ElementManager *elementManager;
LayerManager *layerManager;
// QT GUI PART
Ui::EditorWidgetClass ui;
LayerTreeWidget *treeWidget;
QTabWidget *tabWidget;
InfoDisplayWidget *layerInfoDisplayWidget, *elementInfoDisplayWidget;
// QT DATA PART
LayerWrapper *displayLayer;
GraphicElement *displayElement;
public:
EditorWidget(QWidget *parent = nullptr);
~EditorWidget();
void paintEvent(QPaintEvent *event) override;
private slots:
void onLayerChange(LayerWrapper *layer);
void triggerRefreshPreview();
private:
Ui::EditorWidget ui;
QTabWidget* tabWidget;
QPushButton* createButton;
QPushButton* closeButton;
QPushButton* saveButton;
QPushButton* saveAsButton;
QPushButton* openButton;
public:
EditorWidget(QWidget* parent = nullptr);
~EditorWidget()=default;
};

View File

@ -0,0 +1,44 @@
#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());
}
jsonObj.insert("tranform", "{\"offset\":{\"x\":0,\"y\":0},\"scale\":{\"x\":1,\"y\":1},\"rotation\":0}");
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,98 @@
#include "EditorWidgetItem.h"
EditorWidgetItem::EditorWidgetItem(QString filePath,QWidget *parent) : QWidget(parent)
{
QImage x;
displayLayer = nullptr;
displayElement = nullptr;
ui.setupUi(this);
previewWindow = ui.Preview;
treeWidget = ui.LayerTree;
tabWidget = ui.DisplayTab;
this->filePath = filePath;
layerInfoDisplayWidget = dynamic_cast<InfoDisplayWidget *>(tabWidget->widget(0));
elementInfoDisplayWidget = dynamic_cast<ElementPoolWidget *>(tabWidget->widget(1));
qDebug() << layerInfoDisplayWidget;
qDebug() << elementInfoDisplayWidget;
connect(treeWidget, &LayerTreeWidget::displayLayerChange, this, &EditorWidgetItem::onLayerChange);
connect(layerInfoDisplayWidget, &InfoDisplayWidget::requireRefreshPreview, this,
&EditorWidgetItem::triggerRefreshPreview);
connect(treeWidget, &LayerTreeWidget::requireRefreshPreview, this,
&EditorWidgetItem::triggerRefreshPreview);
connect(layerInfoDisplayWidget, &InfoDisplayWidget::requireSelfRefresh, layerInfoDisplayWidget, &InfoDisplayWidget::triggerSelfRefresh);
// &EditorWidget::triggerRefreshPreview);
// test
QFile settingFile;
//settingFile.setFileName("../data.json");
settingFile.setFileName(filePath);
settingFile.open(QFile::ReadOnly);
QByteArray setting = settingFile.readAll().trimmed();
QJsonParseError jError;
QJsonDocument jsonDoc(QJsonDocument::fromJson(setting, &jError));
qDebug() << jsonDoc.object().value("height").toDouble();
qDebug() << jError.errorString();
// end test
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();
treeWidget->refresh();
treeWidget->addTopLevelItem(treeWidget->root->getQTreeItem());
}
}
EditorWidgetItem::~EditorWidgetItem()
{
}
void EditorWidgetItem::paintEvent(QPaintEvent *event)
{
}
void EditorWidgetItem::onLayerChange(LayerWrapper *layer)
{
displayLayer = layer;
// TODO : notify InfoDisplayWidget and update
dynamic_cast<InfoDisplayWidget *>(tabWidget->widget(0))->setLayer(layer);
this->update();
}
void EditorWidgetItem::triggerRefreshPreview()
{
previewWindow->update();
}
void EditorWidgetItem::save() const
{
saveImpl(this->filePath);
}
void EditorWidgetItem::saveAs(QString filePath) const
{
saveImpl(filePath);
}
void EditorWidgetItem::saveImpl(QString filePath) const
{
QJsonObject source1 = layerManager->toJson();
QJsonObject source2 = elementManager->toJson();
QJsonObject json;
json.insert("width", 1080);
json.insert("height", 1080);
json.insert("root-layer", source1.value("root-layer"));
json.insert("elements", source2.value("elements"));
QJsonDocument doc(json);
QFile file(filePath);
file.open(QIODevice::WriteOnly);
file.write(doc.toJson());
file.close();
}

View File

@ -0,0 +1,45 @@
#pragma once
#include "ElementManager.h"
#include "ElementPoolWidget.h"
#include "InfoDisplayWidget.h"
#include "LayerManager.h"
#include "LayerTreeWidget.h"
#include "PreviewWindow.h"
#include "ui_EditorWidgetItem.h"
#include <QPainter>
#include <QTreeWidget>
#include <QWidget>
class EditorWidgetItem : public QWidget
{
Q_OBJECT
private:
// DATA PART
PreviewWindow *previewWindow;
ElementManager *elementManager;
LayerManager *layerManager;
// QT GUI PART
Ui::EditorWidgetItem ui;
LayerTreeWidget *treeWidget;
QTabWidget *tabWidget;
InfoDisplayWidget* layerInfoDisplayWidget;
ElementPoolWidget* elementInfoDisplayWidget;
// QT DATA PART
LayerWrapper *displayLayer;
GraphicElement *displayElement;
QString filePath;
void saveImpl(QString filePath)const;
public:
EditorWidgetItem(QString filePath, QWidget *parent = nullptr);
~EditorWidgetItem();
void paintEvent(QPaintEvent *event) override;
void save() const;
void saveAs(QString filePath)const;
private slots:
void onLayerChange(LayerWrapper *layer);
void triggerRefreshPreview();
};

View File

@ -3,6 +3,7 @@ ElementManager::ElementManager(QJsonObject source,Renderer::ElementRenderer* ren
{
auto elementsJson = source.value("elements").toArray();
qDebug() << elementsJson.size();
int index = 0;
for (auto elementJson : elementsJson)
{
if (elementJson.toObject().value("type").toString() == "group")
@ -12,6 +13,8 @@ ElementManager::ElementManager(QJsonObject source,Renderer::ElementRenderer* ren
(*elements.rbegin())->renderer = renderer;
}
for (auto element : elements)
element->index = index++;
}
void ElementManager::addElement(GraphicElement *element)
@ -33,3 +36,13 @@ GraphicElement *ElementManager::getElementById(int index)
ElementManager::~ElementManager()
{
}
QJsonObject ElementManager::toJson() const
{
QJsonArray elementsJson;
for (auto element : elements)
elementsJson.push_back(element->toJson());
QJsonObject result;
result.insert("elements", elementsJson);
return result;
}

View File

@ -11,7 +11,7 @@ class Renderer::ElementRenderer;
class ElementManager
{
private:
public:
vector<GraphicElement *> elements;
public:
@ -19,6 +19,7 @@ class ElementManager
~ElementManager();
void addElement(GraphicElement *element);
void removeElement(GraphicElement *pElement);
QJsonObject toJson()const;
/**
* only used in initialization
*/

View File

@ -0,0 +1,81 @@
#include "ElementPoolWidget.h"
ElementPoolWidget::ElementPoolWidget(QWidget* parent)
: QWidget(parent)
{
elementManager = nullptr;
iconWidth = 100, iconHeight = 75;
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 - 15, iconHeight - 15)),
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

@ -46,7 +46,7 @@ PixelPath GroupElement::getPaintObject() 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() << img << " ------";
result.addImage(img, mov);
//result.addPath(painterPath);
@ -76,3 +76,10 @@ PixelPath GroupElement::getPaintObject(std::vector<std::shared_ptr<LayerStyle>>*
// rawPath.addPath(path);
// }
//}
//TODO : Ìí¼Óϸ½Ú
QJsonObject GraphicElement::toJson() const
{
QJsonObject result;
result.insert("name", name);
return result;
}

View File

@ -23,7 +23,9 @@ class GraphicElement
public:
Renderer::ElementRenderer *renderer;
QString name = "";
int index;
// TODO: ¸ÄΪBitmapPath
virtual QJsonObject toJson() const;
virtual PixelPath getPaintObject() const = 0;
virtual PixelPath getPaintObject(std::vector<std::shared_ptr<LayerStyle>>*) const = 0;
};

View File

@ -62,11 +62,20 @@ bool LayerManager::changeParent(FolderLayerWrapper *newParent) const
selectedLayers[0]->setParent(newParent);
return true;
}
void LayerManager::addLayer(LayerWrapper *layer)
{
layerSet.insert(layer);
}
void LayerManager::removeLayer(LayerWrapper *layer)
{
layerSet.erase(layer);
}
QJsonObject LayerManager::toJson() const
{
QJsonObject result;
result.insert("root-layer", root->toJson());
return result;
}

View File

@ -31,6 +31,7 @@ class LayerManager
LayerWrapper *getRoot() const;
LayerManager() = default;
LayerManager(QJsonObject source, ElementManager* elementManager);
QJsonObject toJson() const;
void paint(QPainter *painter, QSize size) const;
bool rename(QString newName) const;
bool combine() const;

View File

@ -53,6 +53,7 @@ FolderLayerWrapper::FolderLayerWrapper(QJsonObject json, ElementManager *element
auto p = reinterpret_cast<GroupElement *>(elementManager->getElementById(referencedJson.toInt()));
if (p != nullptr)
p->setSourceLayer(this);
this->referencedBy = referencedJson.toInt();
}
for (auto childJson : childrenJson)
{
@ -95,7 +96,6 @@ void FolderLayerWrapper::refresh()
{
cache.clear();
for (auto& child : children) {
qDebug() << child.get();
cache.addPath(child.get()->getCache());
}
LayerWrapper::refresh();
@ -181,3 +181,40 @@ QTreeWidgetItem* FolderLayerWrapper::getQTreeItem()
}
return LayerWrapper::getQTreeItem();
}
//TODO: add effects
QJsonObject LayerWrapper::toJson() const
{
QJsonObject json;
json.insert("name", property.name);
QJsonObject transformJson;
transformJson.insert("offset", QJsonObject({ {"x", property.offset.x()}, {"y", property.offset.y()} }));
transformJson.insert("scale", QJsonObject({ {"x", property.scale.x()}, {"y", property.scale.y()} }));
transformJson.insert("rotation", property.rotation);
json.insert("transform", transformJson);
return json;
}
QJsonObject FolderLayerWrapper::toJson() const
{
QJsonObject json = LayerWrapper::toJson();
QJsonArray childrenJson;
for (auto& child : children)
childrenJson.push_back(child->toJson());
json.insert("children", childrenJson);
json.insert("is-folder", true);
if(this->referencedBy != -1)
json.insert("referenced-by", this->referencedBy);
else
json.insert("referenced-by", QJsonValue());
return json;
}
QJsonObject LeafLayerWrapper::toJson() const
{
QJsonObject json = LayerWrapper::toJson();
json.insert("element", wrappedElement->index);
json.insert("is-folder", false);
return json;
}

View File

@ -60,13 +60,16 @@ class LayerWrapper
// virtual void deleteAll() const = 0;
virtual void del();
virtual void delSelf();
virtual QJsonObject toJson() const;
~LayerWrapper() = default;
};
class FolderLayerWrapper : public LayerWrapper
{
public:
vector<shared_ptr<LayerWrapper>> children;
int referencedBy = -1;
public:
@ -80,6 +83,7 @@ class FolderLayerWrapper : public LayerWrapper
void del() override;
void delSelf() override;
QTreeWidgetItem* getQTreeItem() override;
QJsonObject toJson() const override;
};
class LeafLayerWrapper : public LayerWrapper
@ -94,6 +98,7 @@ class LeafLayerWrapper : public LayerWrapper
void refresh() override;
LeafLayerWrapper() = default;
LeafLayerWrapper(QJsonObject json, ElementManager *elementManager, FolderLayerWrapper*parent);
QJsonObject toJson() const override;
};
Q_DECLARE_METATYPE(LayerWrapper *)

View File

@ -84,4 +84,15 @@ QPixmap PixelPath::resizedPixel(QSize size)const
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;
}

View File

@ -23,4 +23,5 @@ public:
void clear();
PixelPath trans(QTransform& mat)const;
QPixmap resizedPixel(QSize size)const;
QPixmap getDetail()const;
};

View File

@ -2,7 +2,7 @@
PreviewWindow::PreviewWindow(QWidget *parent) : QOpenGLWidget(parent)
{
this->renderer = new Renderer::ElementRenderer(this);
this->renderer = Renderer::ElementRenderer::instance();
QSurfaceFormat surfaceFormat;
surfaceFormat.setSamples(16);
setFormat(surfaceFormat);
@ -36,7 +36,6 @@ void PreviewWindow::show()
void PreviewWindow::initializeGL()
{
this->renderer->initialize();
initializeOpenGLFunctions();
}

View File

@ -13,17 +13,13 @@ 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;
@ -211,15 +207,8 @@ void InfoDisplayWidget::generateLayerForm()
this->setLayout(layout);
}
void InfoDisplayWidget::generateElementForm()
{
}
void InfoDisplayWidget::triggerSelfRefresh()
{
if (this->displayLayer != nullptr)
this->generateLayerForm();
else
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();

View File

@ -1,6 +1,8 @@
#include "LayerTreeWidget.h"
#include <QInputDialog>
#include <QMenu>
#include "./EditorWidgetComponent/LayerCreateWidget.h"
LayerTreeWidget::LayerTreeWidget(QWidget *parent)
{
emit displayLayerChange(nullptr);
@ -35,27 +37,47 @@ void LayerTreeWidget::popMenu(const QPoint &pos)
QMenu menu;
QTreeWidgetItem *item = itemAt(pos);
this->selectedItem = item;
// TODO
menu.addAction(QString::fromLocal8Bit("创建子节点"), this, &LayerTreeWidget::onRenameEvent);
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]() {
auto layer = this->selectedItem->data(0, Qt::UserRole).value<LayerWrapper*>();
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();
});
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();
});
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 (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);
}
}
}
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();

View File

@ -0,0 +1,2 @@
#include "PaintingUtil.h"

View File

@ -0,0 +1,8 @@
#pragma once
#include "../../Renderer/Painting/Painting.h"
class PaintingUtil
{
public:
//static Renderer::Painting transfromToPainting();
};

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)
{
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->buttonGroup, &QButtonGroup::idClicked,
ui.tabWidget, &QTabWidget::setCurrentIndex);
QObject::connect(ui.tabWidget, &QTabWidget::currentChanged,
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);
}
@ -134,38 +37,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);
m_central_widget = new CentralWidget();
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());
}
@ -180,5 +74,3 @@ void MainWindow::closeEvent(QCloseEvent* event)
if (result != QMessageBox::Yes)
event->ignore();*/
}

View File

@ -2,7 +2,6 @@
#include <QtWidgets/QMainWindow>
#include "ui_MainWindow.h"
#include "ui_FramelessWindow.h"
#include <FramelessHelper/Widgets/framelessmainwindow.h>
@ -10,19 +9,6 @@ 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
{
Q_OBJECT
@ -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,14 +1,25 @@
#include "NavigationBarWidget.h"
#include <qtmaterialraisedbutton.h>
#include <QVBoxLayout>
#include <QDebug>
NavigationBarWidget::NavigationBarWidget(QWidget *parent)
: QWidget(parent)
, tabs(new QtMaterialTabs)
{
ui.setupUi(this);
buttonGroup = new QButtonGroup(this);
buttonGroup->addButton(ui.radioButton0, 0);
buttonGroup->addButton(ui.radioButton1, 1);
ui.radioButton0->setChecked(true);
;}
tabs->addTab(QStringLiteral("ÎÆÀí±à¼­"));
tabs->addTab(QStringLiteral("³¡¾°äÖȾ"));
tabs->setHaloVisible(false);
tabs->setBackgroundColor(Qt::transparent);
tabs->setTextColor(Qt::black);
tabs->setInkColor(QColor(0, 90, 158));
tabs->setFixedHeight(38);
QVBoxLayout* layout = new QVBoxLayout;
layout->setContentsMargins(0, 0, 0, 0);
layout->addWidget(tabs);
layout->setAlignment(tabs, Qt::AlignHCenter);
setLayout(layout);
}
NavigationBarWidget::~NavigationBarWidget()
{}

View File

@ -2,7 +2,7 @@
#include <QWidget>
#include <QButtonGroup>
#include "ui_NavigationBarWidget.h"
#include <qtmaterialtabs.h>
class NavigationBarWidget : public QWidget
{
@ -11,8 +11,5 @@ class NavigationBarWidget : public QWidget
public:
NavigationBarWidget(QWidget *parent = nullptr);
~NavigationBarWidget();
QButtonGroup* buttonGroup;
private:
Ui::NavigationBarWidgetClass ui;
QtMaterialTabs* tabs;
};

View File

@ -12,6 +12,7 @@
#include "Painting/Painting.h"
#include "../SvgParser.h"
#include "../Editor/util/PainterPathUtil.h"
#include "../Editor/util/SvgFileLoader.h"
#include <ThirdPartyLib/qquick/qquicksvgparser_p.h>
using namespace Renderer;
@ -44,19 +45,41 @@ 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();
@ -98,8 +121,9 @@ std::unique_ptr<Drawable> Model::processMesh(aiMesh* mesh, const aiScene* scene,
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))
if (auto iter = paintingMap.find(std::string(str.C_Str())); paintingProgram != nullptr && iter != paintingMap.end())
{
auto& [paintingPath, leftBottom, rightTop] = iter->second;
qDebug() << str.C_Str() << "Replaced";
// ³õʼ»¯Íø¸ñ
auto m_mesh = std::make_unique<PaintingMesh>(glFunc, paintingProgram, shadowProgram, modelQ);
@ -128,7 +152,7 @@ std::unique_ptr<Drawable> Model::processMesh(aiMesh* mesh, const aiScene* scene,
}
}
m_mesh->paintingId = loadPainting(std::string(str.C_Str()));
m_mesh->paintingId = loadPainting(paintingPath);
auto& handle = vtManager->getPaintingHandle(m_mesh->paintingId);
m_mesh->textureBasecolor = handle.baseColor;
m_mesh->textureMetallicRoughness = handle.metallicRoughness;
@ -223,8 +247,10 @@ GLuint Renderer::Model::loadPainting(std::string path)
QPainterPath painterPaths[3];
QQuickSvgParser::parsePathDataFast("M100,100C-.5,100,0,100.5,0,0L40,.07C40,59.5,39.5,60,100,60Z",
painterPaths[0]);
QQuickSvgParser::parsePathDataFast("M308.49,212.25l23,28.38-82,78.31c-14.28,13.64-26.34-20.6-53.44,9.32l-30.24-13.4,63.56-51.59L190.71,215.6l-32.92,26.72L149.5,232.1l32.92-26.72L173.2,194l-32.91,26.72-7.38-9.08L165.83,185l-38.69-47.66L94.22,164,85,152.65l32.91-26.72-9.21-11.35L75.79,141.3l-5.53-6.81,32.92-26.72L94,96.42,61.05,123.14l-12-14.76L37.72,117.6l12,14.75L30.41,148,0,110.55,136.2,0l30.4,37.46L147.31,53.12l-12-14.76L124,47.58l12,14.75L103.05,89.05l9.21,11.35,32.92-26.72,5.52,6.81-32.91,26.72L127,118.56l32.92-26.72,9.21,11.35-32.91,26.72,38.69,47.67,32.91-26.72,7.37,9.08-32.91,26.72L191.49,198l32.92-26.72,8.29,10.22-32.92,26.71,38.7,47.68L302,204.3l6.45,7.95Z",
painterPaths[1]);
if (!SvgFileLoader().loadSvgFile("../svg/2.svg", painterPaths[1]))
qCritical() << "load error";
/*QQuickSvgParser::parsePathDataFast("M292.82,107.78s0,0,0,0,0,3.59,0,7.62c0,3.85,0,5.78.06,6.43a19.94,19.94,0,0,0,2.87,7.58,15.85,15.85,0,0,0,6.61,6.23A14.75,14.75,0,0,0,310,137a11.69,11.69,0,0,0,7.59-2.92,11,11,0,0,0,3.2-6.84c.15-1.27.58-4.84-1.79-7.64a8.54,8.54,0,0,0-3.56-2.44c-1.32-.52-3.32-1.31-5.06-.33a5.41,5.41,0,0,0-2.14,3,3.48,3.48,0,0,0-.16,2.71c.78,1.86,3.36,2.14,3.47,2.15",
painterPaths[1]);*/
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]);
@ -237,7 +263,7 @@ GLuint Renderer::Model::loadPainting(std::string path)
vector<std::shared_ptr<ElementStyle>> style = {
std::make_shared<ElementStyleFillDemo>(),
std::make_shared<ElementStyleStrokeDemo>(0.02),
std::make_shared<ElementStyleStrokeRadialGradientDemo>(0.02)
std::make_shared<ElementStyleStrokeRadialGradientDemo>(0.2)
};
vector<std::shared_ptr<Element>> element = {
@ -247,10 +273,10 @@ 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.5,-0.45), glm::vec2(0.6,0.7) / 2.f, 45, glm::bvec2(true, 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[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 });
}
else
@ -263,7 +289,6 @@ GLuint Renderer::Model::loadPainting(std::string path)
}
}
painting.generateBuffers(glFunc);
auto index = vtManager->createVirtualTexture(painting);

View File

@ -17,20 +17,20 @@ 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;
/* 模型数据 */
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

@ -35,6 +35,6 @@ std::vector<BaseStyle> Renderer::ElementStyleStrokeRadialGradientDemo::toBaseSty
{1.00, Material{QColor(255,255,0)}},
};
return { BaseStyle(std::make_shared<TransformStyle>(),
std::make_shared<MaterialStyleStroke>(width, StrokeType::kLeftSide, StrokeEndType::kRound,
std::make_shared<MaterialStyleStroke>(width, StrokeType::kBothSides, StrokeEndType::kRound,
std::make_shared<StrokeRadialGradient>(materialMap, false))) };
}

View File

@ -101,7 +101,7 @@ BvhTreeData Painting::encodeElementLeaf(ElementWithTransform e)
case MaterialStyleType::kStroke:
{
auto w = std::static_pointer_cast<MaterialStyleStroke>(e.element.style)->getHalfWidth();
glm::vec2 size = glm::normalize(glm::vec2(e.element.ratio, 1)) + glm::vec2(2 * w);
glm::vec2 size = e.element.ratio < 1 ? glm::vec2(e.element.ratio, 1) : glm::vec2(1, 1 / e.element.ratio);
glm::vec2 scale = size * e.transform.scale;
bound = glm::vec4(e.transform.center - scale, e.transform.center + scale);
break;
@ -112,7 +112,7 @@ BvhTreeData Painting::encodeElementLeaf(ElementWithTransform e)
break;
}
}
bound = glm::vec4(e.transform.center - e.transform.scale, e.transform.center + e.transform.scale);
//bound = glm::vec4(e.transform.center - e.transform.scale, e.transform.center + e.transform.scale);
GLuint rightSon = (GLuint)(glm::mod(e.transform.rotation, 360.f) / 360.f * (1 << 16))
+ (e.transform.flip.x << 16) + (e.transform.flip.y << 17) + (e.transform.zIndex << 18);
return BvhTreeData(QVector4D(bound.x, bound.y, bound.z, bound.w), elementPool[e.element], rightSon);
@ -167,7 +167,7 @@ void Painting::generateBuffers(QOpenGLFunctions_4_5_Core* glFunc)
//qDebug() <<"element:" << i.second;
//std::shared_ptr<ContourBuffer> contourBuffer = i.first.style->type() == MaterialStyleType::kStroke ? contourPool[i.first.contour].second : contourPool[i.first.contour].first;
auto& contourBuffer = contourPool[{i.first.contour, i.first.style->type()}];
elementOffsets.push_back({ contourBuffer.bvhOffset, stylePool[i.first.style], contourBuffer.pointsOffset, contourBuffer.linesOffset });
elementOffsets.push_back({ contourBuffer.bvhOffset, stylePool[i.first.style], contourBuffer.pointsOffset, contourBuffer.linesOffset, glm::floatBitsToUint(i.first.ratio) });
//std::cout << std::format("{} {} {} {}\n", contourBuffer->bvhOffset, stylePool[i.first->style], contourBuffer->pointsOffset, contourBuffer->linesOffset);
}

View File

@ -52,6 +52,7 @@ namespace Renderer
GLuint styleOffset;
GLuint pointsOffset;
GLuint linesOffset;
GLuint ratio;
};
class Painting

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,88 @@ 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([&] {
QOpenGLContext context;
context.create();
context.makeCurrent(&surface);
auto pathBuffer = generatePathBuffer(path);
auto styleBuffer = generateStyleBuffer(baseStyles);
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();
if (releaseContext) glWidget->makeCurrent();
initialized = true;
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);
while (true)
{
std::unique_lock<std::mutex> lock(drawMutex);
draw.wait(lock, [&] {return 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));
auto fbo = QOpenGLFramebufferObject(size, QOpenGLFramebufferObject::NoAttachment, GL_TEXTURE_2D);
fbo.bind();
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
fbo.release();
auto pathBuffer = generatePathBuffer(*path);
auto styleBuffer = generateStyleBuffer(baseStyles);
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();
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);
auto image = fbo.toImage(false);
glDeleteBuffers(2, ssbo);
if (releaseContext) glWidget->doneCurrent();
return { image, leftTop };
auto fbo = QOpenGLFramebufferObject(size, QOpenGLFramebufferObject::NoAttachment, GL_TEXTURE_2D);
fbo.bind();
glClearColor(0, 0, 0, 0);
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);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 10, ssbo[0]);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 11, ssbo[1]);
glBindImageTexture(0, fbo.texture(), 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8);
glDispatchCompute(ceil(size.width() / 8.), ceil(size.height() / 8.), 1);
shader->release();
auto image = fbo.toImage(false);
glDeleteBuffers(2, ssbo);
result = { image, leftTop };
drawFinished = true;
}
draw.notify_all();
}
});
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
{
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

@ -1,29 +1,50 @@
#include "RendererWidget.h"
#include "RendererGLWidget.h"
using namespace Renderer;
RendererWidget::RendererWidget(QWidget *parent)
#include "../FluentMenu.h"
Renderer::RendererWidget::RendererWidget(QWidget* parent)
: QWidget(parent)
{
ui.setupUi(this);
QObject::connect(ui.horizontalSlider, &QSlider::valueChanged,
ui.openGLWidget, &RendererGLWidget::setMainLightPitch);
QObject::connect(ui.horizontalSlider_2, &QSlider::valueChanged,
ui.openGLWidget, &RendererGLWidget::setMainLightYaw);
QObject::connect(ui.exposureSlider, &QSlider::valueChanged, [&](int value) {
ui.openGLWidget->setExposure(value/100.f);
FluentMenu* menu = new FluentMenu(this);
auto openAction = new QAction(QStringLiteral("´ò¿ª"), menu);
auto saveAction = new QAction(QStringLiteral("±£´æ"), menu);
menu->addAction(openAction);
menu->addAction(saveAction);
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, &Renderer::RendererGLWidget::setMainLightPitch);
QObject::connect(ui.horizontalSlider_2, &QSlider::valueChanged,
ui.openGLWidget, &Renderer::RendererGLWidget::setMainLightYaw);
QObject::connect(ui.exposureSlider, &QSlider::valueChanged, [&](int value) {
ui.openGLWidget->setExposure(value / 100.f);
});
QObject::connect(openAction, &QAction::triggered, ui.openGLWidget, &Renderer::RendererGLWidget::setModel);
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 +54,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

@ -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

@ -51,8 +51,8 @@ int main(int argc, char* argv[])
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);
//FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow);
//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>

111
data - 副本.json Normal file
View File

@ -0,0 +1,111 @@
{
"height": 1080,
"width": 1080,
"elements": [
{
"name": "ababa",
"type": "svg-file",
"data": {
"include": "./svg/2.svg"
}
},
{
"name": "ababa-group",
"type": "group",
"data": {
"reference-layer": "0.0"
}
}
],
"root-layer": {
"name": "root",
"transform": {
"offset": {
"x": 0,
"y": 0
},
"scale": {
"x": 1.0,
"y": 1.0
},
"rotation": 0.0
},
"effects": [],
"is-folder": true,
"referenced-by": null,
"children": [
{
"name": "GroupFolderExample",
"transform": {
"offset": {
"x": 50,
"y": 50
},
"scale": {
"x": 1.0,
"y": 1.0
},
"rotation": 0.0
},
"effects": [],
"is-folder": true,
"referenced-by": 1,
"children": [
{
"name": "Leaf1",
"transform": {
"offset": {
"x": 0,
"y": 0
},
"scale": {
"x": 1.0,
"y": 1.0
},
"rotation": 0.0
},
"effects": [],
"is-folder": false,
"element": 0
},
{
"name": "Leaf2",
"transform": {
"offset": {
"x": 150,
"y": 0
},
"scale": {
"x": 1.5,
"y": 1.5
},
"rotation": 0.0
},
"effects": [],
"is-folder": false,
"element": 0
}
]
},
{
"name": "ReferencingGroupLayer",
"transform": {
"offset": {
"x": 100,
"y": 0
},
"scale": {
"x": 1,
"y": 1
},
"rotation": 45
},
"effects": [],
"is-folder": false,
"element": 1
}
]
}
}

96
data.back.json Normal file
View File

@ -0,0 +1,96 @@
{
"elements": [
{
"name": ""
},
{
"name": ""
}
],
"height": 1080,
"root-layer": {
"children": [
{
"children": [
{
"element": 0,
"is-folder": false,
"name": "Leaf1",
"transform": {
"offset": {
"x": 0,
"y": 0
},
"rotation": 0,
"scale": {
"x": 1,
"y": 1
}
}
},
{
"element": 0,
"is-folder": false,
"name": "Leaf2",
"transform": {
"offset": {
"x": 150,
"y": 0
},
"rotation": 0,
"scale": {
"x": 1.5,
"y": 1.5
}
}
}
],
"is-folder": true,
"name": "GroupFolderExample",
"referenced-by": 1,
"transform": {
"offset": {
"x": 50,
"y": 50
},
"rotation": 0,
"scale": {
"x": 1,
"y": 1
}
}
},
{
"element": 1,
"is-folder": false,
"name": "ReferencingGroupLayer",
"transform": {
"offset": {
"x": 100,
"y": 0
},
"rotation": 45,
"scale": {
"x": 1,
"y": 1
}
}
}
],
"is-folder": true,
"name": "root",
"referenced-by": null,
"transform": {
"offset": {
"x": 0,
"y": 0
},
"rotation": 0,
"scale": {
"x": 1,
"y": 1
}
}
},
"width": 1080
}

View File

@ -34,6 +34,7 @@
"is-folder": true,
"referenced-by": null,
"children": [
{
"name": "GroupFolderExample",
"transform": {
@ -87,6 +88,7 @@
}
]
},
{
"name": "ReferencingGroupLayer",
"transform": {

View File

@ -0,0 +1 @@
ref: refs/heads/master

View File

@ -0,0 +1,16 @@
[core]
repositoryformatversion = 0
filemode = false
bare = false
logallrefupdates = true
symlinks = false
ignorecase = true
[remote "origin"]
url = git@github.com:laserpants/qt-material-widgets.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
[gui]
wmstate = normal
geometry = 1425x773+407+375 321 352

View File

@ -0,0 +1 @@
Unnamed repository; edit this file 'description' to name the repository.

View File

@ -0,0 +1,15 @@
#!/bin/sh
#
# An example hook script to check the commit log message taken by
# applypatch from an e-mail message.
#
# The hook should exit with non-zero status after issuing an
# appropriate message if it wants to stop the commit. The hook is
# allowed to edit the commit message file.
#
# To enable this hook, rename this file to "applypatch-msg".
. git-sh-setup
commitmsg="$(git rev-parse --git-path hooks/commit-msg)"
test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"}
:

View File

@ -0,0 +1,24 @@
#!/bin/sh
#
# An example hook script to check the commit log message.
# Called by "git commit" with one argument, the name of the file
# that has the commit message. The hook should exit with non-zero
# status after issuing an appropriate message if it wants to stop the
# commit. The hook is allowed to edit the commit message file.
#
# To enable this hook, rename this file to "commit-msg".
# Uncomment the below to add a Signed-off-by line to the message.
# Doing this in a hook is a bad idea in general, but the prepare-commit-msg
# hook is more suited to it.
#
# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
# This example catches duplicate Signed-off-by lines.
test "" = "$(grep '^Signed-off-by: ' "$1" |
sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || {
echo >&2 Duplicate Signed-off-by lines.
exit 1
}

View File

@ -0,0 +1,173 @@
#!/usr/bin/perl
use strict;
use warnings;
use IPC::Open2;
# An example hook script to integrate Watchman
# (https://facebook.github.io/watchman/) with git to speed up detecting
# new and modified files.
#
# The hook is passed a version (currently 2) and last update token
# formatted as a string and outputs to stdout a new update token and
# all files that have been modified since the update token. Paths must
# be relative to the root of the working tree and separated by a single NUL.
#
# To enable this hook, rename this file to "query-watchman" and set
# 'git config core.fsmonitor .git/hooks/query-watchman'
#
my ($version, $last_update_token) = @ARGV;
# Uncomment for debugging
# print STDERR "$0 $version $last_update_token\n";
# Check the hook interface version
if ($version ne 2) {
die "Unsupported query-fsmonitor hook version '$version'.\n" .
"Falling back to scanning...\n";
}
my $git_work_tree = get_working_dir();
my $retry = 1;
my $json_pkg;
eval {
require JSON::XS;
$json_pkg = "JSON::XS";
1;
} or do {
require JSON::PP;
$json_pkg = "JSON::PP";
};
launch_watchman();
sub launch_watchman {
my $o = watchman_query();
if (is_work_tree_watched($o)) {
output_result($o->{clock}, @{$o->{files}});
}
}
sub output_result {
my ($clockid, @files) = @_;
# Uncomment for debugging watchman output
# open (my $fh, ">", ".git/watchman-output.out");
# binmode $fh, ":utf8";
# print $fh "$clockid\n@files\n";
# close $fh;
binmode STDOUT, ":utf8";
print $clockid;
print "\0";
local $, = "\0";
print @files;
}
sub watchman_clock {
my $response = qx/watchman clock "$git_work_tree"/;
die "Failed to get clock id on '$git_work_tree'.\n" .
"Falling back to scanning...\n" if $? != 0;
return $json_pkg->new->utf8->decode($response);
}
sub watchman_query {
my $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'watchman -j --no-pretty')
or die "open2() failed: $!\n" .
"Falling back to scanning...\n";
# In the query expression below we're asking for names of files that
# changed since $last_update_token but not from the .git folder.
#
# To accomplish this, we're using the "since" generator to use the
# recency index to select candidate nodes and "fields" to limit the
# output to file names only. Then we're using the "expression" term to
# further constrain the results.
if (substr($last_update_token, 0, 1) eq "c") {
$last_update_token = "\"$last_update_token\"";
}
my $query = <<" END";
["query", "$git_work_tree", {
"since": $last_update_token,
"fields": ["name"],
"expression": ["not", ["dirname", ".git"]]
}]
END
# Uncomment for debugging the watchman query
# open (my $fh, ">", ".git/watchman-query.json");
# print $fh $query;
# close $fh;
print CHLD_IN $query;
close CHLD_IN;
my $response = do {local $/; <CHLD_OUT>};
# Uncomment for debugging the watch response
# open ($fh, ">", ".git/watchman-response.json");
# print $fh $response;
# close $fh;
die "Watchman: command returned no output.\n" .
"Falling back to scanning...\n" if $response eq "";
die "Watchman: command returned invalid output: $response\n" .
"Falling back to scanning...\n" unless $response =~ /^\{/;
return $json_pkg->new->utf8->decode($response);
}
sub is_work_tree_watched {
my ($output) = @_;
my $error = $output->{error};
if ($retry > 0 and $error and $error =~ m/unable to resolve root .* directory (.*) is not watched/) {
$retry--;
my $response = qx/watchman watch "$git_work_tree"/;
die "Failed to make watchman watch '$git_work_tree'.\n" .
"Falling back to scanning...\n" if $? != 0;
$output = $json_pkg->new->utf8->decode($response);
$error = $output->{error};
die "Watchman: $error.\n" .
"Falling back to scanning...\n" if $error;
# Uncomment for debugging watchman output
# open (my $fh, ">", ".git/watchman-output.out");
# close $fh;
# Watchman will always return all files on the first query so
# return the fast "everything is dirty" flag to git and do the
# Watchman query just to get it over with now so we won't pay
# the cost in git to look up each individual file.
my $o = watchman_clock();
$error = $output->{error};
die "Watchman: $error.\n" .
"Falling back to scanning...\n" if $error;
output_result($o->{clock}, ("/"));
$last_update_token = $o->{clock};
eval { launch_watchman() };
return 0;
}
die "Watchman: $error.\n" .
"Falling back to scanning...\n" if $error;
return 1;
}
sub get_working_dir {
my $working_dir;
if ($^O =~ 'msys' || $^O =~ 'cygwin') {
$working_dir = Win32::GetCwd();
$working_dir =~ tr/\\/\//;
} else {
require Cwd;
$working_dir = Cwd::cwd();
}
return $working_dir;
}

View File

@ -0,0 +1,8 @@
#!/bin/sh
#
# An example hook script to prepare a packed repository for use over
# dumb transports.
#
# To enable this hook, rename this file to "post-update".
exec git update-server-info

View File

@ -0,0 +1,14 @@
#!/bin/sh
#
# An example hook script to verify what is about to be committed
# by applypatch from an e-mail message.
#
# The hook should exit with non-zero status after issuing an
# appropriate message if it wants to stop the commit.
#
# To enable this hook, rename this file to "pre-applypatch".
. git-sh-setup
precommit="$(git rev-parse --git-path hooks/pre-commit)"
test -x "$precommit" && exec "$precommit" ${1+"$@"}
:

View File

@ -0,0 +1,49 @@
#!/bin/sh
#
# An example hook script to verify what is about to be committed.
# Called by "git commit" with no arguments. The hook should
# exit with non-zero status after issuing an appropriate message if
# it wants to stop the commit.
#
# To enable this hook, rename this file to "pre-commit".
if git rev-parse --verify HEAD >/dev/null 2>&1
then
against=HEAD
else
# Initial commit: diff against an empty tree object
against=$(git hash-object -t tree /dev/null)
fi
# If you want to allow non-ASCII filenames set this variable to true.
allownonascii=$(git config --type=bool hooks.allownonascii)
# Redirect output to stderr.
exec 1>&2
# Cross platform projects tend to avoid non-ASCII filenames; prevent
# them from being added to the repository. We exploit the fact that the
# printable range starts at the space character and ends with tilde.
if [ "$allownonascii" != "true" ] &&
# Note that the use of brackets around a tr range is ok here, (it's
# even required, for portability to Solaris 10's /usr/bin/tr), since
# the square bracket bytes happen to fall in the designated range.
test $(git diff --cached --name-only --diff-filter=A -z $against |
LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0
then
cat <<\EOF
Error: Attempt to add a non-ASCII file name.
This can cause problems if you want to work with people on other platforms.
To be portable it is advisable to rename the file.
If you know what you are doing you can disable this check using:
git config hooks.allownonascii true
EOF
exit 1
fi
# If there are whitespace errors, print the offending file names and fail.
exec git diff-index --check --cached $against --

View File

@ -0,0 +1,13 @@
#!/bin/sh
#
# An example hook script to verify what is about to be committed.
# Called by "git merge" with no arguments. The hook should
# exit with non-zero status after issuing an appropriate message to
# stderr if it wants to stop the merge commit.
#
# To enable this hook, rename this file to "pre-merge-commit".
. git-sh-setup
test -x "$GIT_DIR/hooks/pre-commit" &&
exec "$GIT_DIR/hooks/pre-commit"
:

View File

@ -0,0 +1,53 @@
#!/bin/sh
# An example hook script to verify what is about to be pushed. Called by "git
# push" after it has checked the remote status, but before anything has been
# pushed. If this script exits with a non-zero status nothing will be pushed.
#
# This hook is called with the following parameters:
#
# $1 -- Name of the remote to which the push is being done
# $2 -- URL to which the push is being done
#
# If pushing without using a named remote those arguments will be equal.
#
# Information about the commits which are being pushed is supplied as lines to
# the standard input in the form:
#
# <local ref> <local sha1> <remote ref> <remote sha1>
#
# This sample shows how to prevent push of commits where the log message starts
# with "WIP" (work in progress).
remote="$1"
url="$2"
z40=0000000000000000000000000000000000000000
while read local_ref local_sha remote_ref remote_sha
do
if [ "$local_sha" = $z40 ]
then
# Handle delete
:
else
if [ "$remote_sha" = $z40 ]
then
# New branch, examine all commits
range="$local_sha"
else
# Update to existing branch, examine new commits
range="$remote_sha..$local_sha"
fi
# Check for WIP commit
commit=`git rev-list -n 1 --grep '^WIP' "$range"`
if [ -n "$commit" ]
then
echo >&2 "Found WIP commit in $local_ref, not pushing"
exit 1
fi
fi
done
exit 0

View File

@ -0,0 +1,169 @@
#!/bin/sh
#
# Copyright (c) 2006, 2008 Junio C Hamano
#
# The "pre-rebase" hook is run just before "git rebase" starts doing
# its job, and can prevent the command from running by exiting with
# non-zero status.
#
# The hook is called with the following parameters:
#
# $1 -- the upstream the series was forked from.
# $2 -- the branch being rebased (or empty when rebasing the current branch).
#
# This sample shows how to prevent topic branches that are already
# merged to 'next' branch from getting rebased, because allowing it
# would result in rebasing already published history.
publish=next
basebranch="$1"
if test "$#" = 2
then
topic="refs/heads/$2"
else
topic=`git symbolic-ref HEAD` ||
exit 0 ;# we do not interrupt rebasing detached HEAD
fi
case "$topic" in
refs/heads/??/*)
;;
*)
exit 0 ;# we do not interrupt others.
;;
esac
# Now we are dealing with a topic branch being rebased
# on top of master. Is it OK to rebase it?
# Does the topic really exist?
git show-ref -q "$topic" || {
echo >&2 "No such branch $topic"
exit 1
}
# Is topic fully merged to master?
not_in_master=`git rev-list --pretty=oneline ^master "$topic"`
if test -z "$not_in_master"
then
echo >&2 "$topic is fully merged to master; better remove it."
exit 1 ;# we could allow it, but there is no point.
fi
# Is topic ever merged to next? If so you should not be rebasing it.
only_next_1=`git rev-list ^master "^$topic" ${publish} | sort`
only_next_2=`git rev-list ^master ${publish} | sort`
if test "$only_next_1" = "$only_next_2"
then
not_in_topic=`git rev-list "^$topic" master`
if test -z "$not_in_topic"
then
echo >&2 "$topic is already up to date with master"
exit 1 ;# we could allow it, but there is no point.
else
exit 0
fi
else
not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"`
/usr/bin/perl -e '
my $topic = $ARGV[0];
my $msg = "* $topic has commits already merged to public branch:\n";
my (%not_in_next) = map {
/^([0-9a-f]+) /;
($1 => 1);
} split(/\n/, $ARGV[1]);
for my $elem (map {
/^([0-9a-f]+) (.*)$/;
[$1 => $2];
} split(/\n/, $ARGV[2])) {
if (!exists $not_in_next{$elem->[0]}) {
if ($msg) {
print STDERR $msg;
undef $msg;
}
print STDERR " $elem->[1]\n";
}
}
' "$topic" "$not_in_next" "$not_in_master"
exit 1
fi
<<\DOC_END
This sample hook safeguards topic branches that have been
published from being rewound.
The workflow assumed here is:
* Once a topic branch forks from "master", "master" is never
merged into it again (either directly or indirectly).
* Once a topic branch is fully cooked and merged into "master",
it is deleted. If you need to build on top of it to correct
earlier mistakes, a new topic branch is created by forking at
the tip of the "master". This is not strictly necessary, but
it makes it easier to keep your history simple.
* Whenever you need to test or publish your changes to topic
branches, merge them into "next" branch.
The script, being an example, hardcodes the publish branch name
to be "next", but it is trivial to make it configurable via
$GIT_DIR/config mechanism.
With this workflow, you would want to know:
(1) ... if a topic branch has ever been merged to "next". Young
topic branches can have stupid mistakes you would rather
clean up before publishing, and things that have not been
merged into other branches can be easily rebased without
affecting other people. But once it is published, you would
not want to rewind it.
(2) ... if a topic branch has been fully merged to "master".
Then you can delete it. More importantly, you should not
build on top of it -- other people may already want to
change things related to the topic as patches against your
"master", so if you need further changes, it is better to
fork the topic (perhaps with the same name) afresh from the
tip of "master".
Let's look at this example:
o---o---o---o---o---o---o---o---o---o "next"
/ / / /
/ a---a---b A / /
/ / / /
/ / c---c---c---c B /
/ / / \ /
/ / / b---b C \ /
/ / / / \ /
---o---o---o---o---o---o---o---o---o---o---o "master"
A, B and C are topic branches.
* A has one fix since it was merged up to "next".
* B has finished. It has been fully merged up to "master" and "next",
and is ready to be deleted.
* C has not merged to "next" at all.
We would want to allow C to be rebased, refuse A, and encourage
B to be deleted.
To compute (1):
git rev-list ^master ^topic next
git rev-list ^master next
if these match, topic has not merged in next at all.
To compute (2):
git rev-list master..topic
if this is empty, it is fully merged to "master".
DOC_END

View File

@ -0,0 +1,24 @@
#!/bin/sh
#
# An example hook script to make use of push options.
# The example simply echoes all push options that start with 'echoback='
# and rejects all pushes when the "reject" push option is used.
#
# To enable this hook, rename this file to "pre-receive".
if test -n "$GIT_PUSH_OPTION_COUNT"
then
i=0
while test "$i" -lt "$GIT_PUSH_OPTION_COUNT"
do
eval "value=\$GIT_PUSH_OPTION_$i"
case "$value" in
echoback=*)
echo "echo from the pre-receive-hook: ${value#*=}" >&2
;;
reject)
exit 1
esac
i=$((i + 1))
done
fi

View File

@ -0,0 +1,42 @@
#!/bin/sh
#
# An example hook script to prepare the commit log message.
# Called by "git commit" with the name of the file that has the
# commit message, followed by the description of the commit
# message's source. The hook's purpose is to edit the commit
# message file. If the hook fails with a non-zero status,
# the commit is aborted.
#
# To enable this hook, rename this file to "prepare-commit-msg".
# This hook includes three examples. The first one removes the
# "# Please enter the commit message..." help message.
#
# The second includes the output of "git diff --name-status -r"
# into the message, just before the "git status" output. It is
# commented because it doesn't cope with --amend or with squashed
# commits.
#
# The third example adds a Signed-off-by line to the message, that can
# still be edited. This is rarely a good idea.
COMMIT_MSG_FILE=$1
COMMIT_SOURCE=$2
SHA1=$3
/usr/bin/perl -i.bak -ne 'print unless(m/^. Please enter the commit message/..m/^#$/)' "$COMMIT_MSG_FILE"
# case "$COMMIT_SOURCE,$SHA1" in
# ,|template,)
# /usr/bin/perl -i.bak -pe '
# print "\n" . `git diff --cached --name-status -r`
# if /^#/ && $first++ == 0' "$COMMIT_MSG_FILE" ;;
# *) ;;
# esac
# SOB=$(git var GIT_COMMITTER_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
# git interpret-trailers --in-place --trailer "$SOB" "$COMMIT_MSG_FILE"
# if test -z "$COMMIT_SOURCE"
# then
# /usr/bin/perl -i.bak -pe 'print "\n" if !$first_line++' "$COMMIT_MSG_FILE"
# fi

View File

@ -0,0 +1,128 @@
#!/bin/sh
#
# An example hook script to block unannotated tags from entering.
# Called by "git receive-pack" with arguments: refname sha1-old sha1-new
#
# To enable this hook, rename this file to "update".
#
# Config
# ------
# hooks.allowunannotated
# This boolean sets whether unannotated tags will be allowed into the
# repository. By default they won't be.
# hooks.allowdeletetag
# This boolean sets whether deleting tags will be allowed in the
# repository. By default they won't be.
# hooks.allowmodifytag
# This boolean sets whether a tag may be modified after creation. By default
# it won't be.
# hooks.allowdeletebranch
# This boolean sets whether deleting branches will be allowed in the
# repository. By default they won't be.
# hooks.denycreatebranch
# This boolean sets whether remotely creating branches will be denied
# in the repository. By default this is allowed.
#
# --- Command line
refname="$1"
oldrev="$2"
newrev="$3"
# --- Safety check
if [ -z "$GIT_DIR" ]; then
echo "Don't run this script from the command line." >&2
echo " (if you want, you could supply GIT_DIR then run" >&2
echo " $0 <ref> <oldrev> <newrev>)" >&2
exit 1
fi
if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
echo "usage: $0 <ref> <oldrev> <newrev>" >&2
exit 1
fi
# --- Config
allowunannotated=$(git config --type=bool hooks.allowunannotated)
allowdeletebranch=$(git config --type=bool hooks.allowdeletebranch)
denycreatebranch=$(git config --type=bool hooks.denycreatebranch)
allowdeletetag=$(git config --type=bool hooks.allowdeletetag)
allowmodifytag=$(git config --type=bool hooks.allowmodifytag)
# check for no description
projectdesc=$(sed -e '1q' "$GIT_DIR/description")
case "$projectdesc" in
"Unnamed repository"* | "")
echo "*** Project description file hasn't been set" >&2
exit 1
;;
esac
# --- Check types
# if $newrev is 0000...0000, it's a commit to delete a ref.
zero="0000000000000000000000000000000000000000"
if [ "$newrev" = "$zero" ]; then
newrev_type=delete
else
newrev_type=$(git cat-file -t $newrev)
fi
case "$refname","$newrev_type" in
refs/tags/*,commit)
# un-annotated tag
short_refname=${refname##refs/tags/}
if [ "$allowunannotated" != "true" ]; then
echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2
echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2
exit 1
fi
;;
refs/tags/*,delete)
# delete tag
if [ "$allowdeletetag" != "true" ]; then
echo "*** Deleting a tag is not allowed in this repository" >&2
exit 1
fi
;;
refs/tags/*,tag)
# annotated tag
if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1
then
echo "*** Tag '$refname' already exists." >&2
echo "*** Modifying a tag is not allowed in this repository." >&2
exit 1
fi
;;
refs/heads/*,commit)
# branch
if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then
echo "*** Creating a branch is not allowed in this repository" >&2
exit 1
fi
;;
refs/heads/*,delete)
# delete branch
if [ "$allowdeletebranch" != "true" ]; then
echo "*** Deleting a branch is not allowed in this repository" >&2
exit 1
fi
;;
refs/remotes/*,commit)
# tracking branch
;;
refs/remotes/*,delete)
# delete tracking branch
if [ "$allowdeletebranch" != "true" ]; then
echo "*** Deleting a tracking branch is not allowed in this repository" >&2
exit 1
fi
;;
*)
# Anything else (is there anything else?)
echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2
exit 1
;;
esac
# --- Finished
exit 0

Binary file not shown.

View File

@ -0,0 +1,6 @@
# git ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
# *.[oa]
# *~

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<PendingCommit>
<CommitComment />
<WorkItems />
<PinnedBranches />
<PublishPrompt Enabled="True" />
<RepositorySorts />
</PendingCommit>

View File

@ -0,0 +1,3 @@
# pack-refs with: peeled fully-peeled sorted
80e9a5a4b8021f37baf2c189458f200a6a7ffd67 refs/remotes/origin/debug
3a0e2265972e5203e240489bc975623c85127813 refs/remotes/origin/master

View File

@ -0,0 +1 @@
3a0e2265972e5203e240489bc975623c85127813

View File

@ -0,0 +1 @@
ref: refs/remotes/origin/master

1
qt-material-widgets/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
*.pro.user

View File

@ -0,0 +1,2 @@
top_srcdir=$$PWD
top_builddir=$$shadowed($$PWD)

View File

@ -0,0 +1,23 @@
QMAKE_CXX.QT_COMPILER_STDCXX = 199711L
QMAKE_CXX.QMAKE_MSC_VER = 1935
QMAKE_CXX.QMAKE_MSC_FULL_VER = 193532215
QMAKE_CXX.COMPILER_MACROS = \
QT_COMPILER_STDCXX \
QMAKE_MSC_VER \
QMAKE_MSC_FULL_VER
QMAKE_CXX.INCDIRS = \
"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\VC\\Tools\\MSVC\\14.35.32215\\include" \
"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\VC\\Tools\\MSVC\\14.35.32215\\ATLMFC\\include" \
"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\VC\\Auxiliary\\VS\\include" \
"C:\\Program Files (x86)\\Windows Kits\\10\\include\\10.0.22000.0\\ucrt" \
"C:\\Program Files (x86)\\Windows Kits\\10\\\\include\\10.0.22000.0\\\\um" \
"C:\\Program Files (x86)\\Windows Kits\\10\\\\include\\10.0.22000.0\\\\shared" \
"C:\\Program Files (x86)\\Windows Kits\\10\\\\include\\10.0.22000.0\\\\winrt" \
"C:\\Program Files (x86)\\Windows Kits\\10\\\\include\\10.0.22000.0\\\\cppwinrt" \
"C:\\Program Files (x86)\\Windows Kits\\NETFXSDK\\4.8\\include\\um"
QMAKE_CXX.LIBDIRS = \
"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\VC\\Tools\\MSVC\\14.35.32215\\ATLMFC\\lib\\x64" \
"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\VC\\Tools\\MSVC\\14.35.32215\\lib\\x64" \
"C:\\Program Files (x86)\\Windows Kits\\NETFXSDK\\4.8\\lib\\um\\x64" \
"C:\\Program Files (x86)\\Windows Kits\\10\\lib\\10.0.22000.0\\ucrt\\x64" \
"C:\\Program Files (x86)\\Windows Kits\\10\\\\lib\\10.0.22000.0\\\\um\\x64"

View File

@ -0,0 +1,30 @@
Copyright Johannes Hilden (c) 2017
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of Author name here nor the names of other
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,317 @@
# Qt Material Design Desktop Widgets [![Language](https://img.shields.io/badge/language-c++-brightgreen.svg)]() [![Join the chat at https://gitter.im/qt-material-widgets/Lobby](https://badges.gitter.im/qt-material-widgets/Lobby.svg)](https://gitter.im/qt-material-widgets/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
YouTube video preview [available here](http://www.youtube.com/watch?v=21UMeNVBPU4).
<table>
<tbody>
<tr>
<td colspan="2" align="center"></td>
</tr>
<tr>
<td>
App Bar
</td>
<td>
<code>QtMaterialAppBar</code>
</td>
</tr>
<tr>
<td colspan="2" align="center">
<img src="gifs/appbar.gif" />
</td>
</tr>
<tr>
<td>
Auto Complete
</td>
<td>
<code>QtMaterialAutoComplete</code>
</td>
</tr>
<tr>
<td colspan="2" align="center">
<img src="gifs/autocomplete.gif" />
</td>
</tr>
<tr>
<td>
Avatar
</td>
<td>
<code>QtMaterialAvatar</code>
</td>
</tr>
<tr>
<td colspan="2" align="center">
<img src="gifs/avatar.gif" />
</td>
</tr>
<tr>
<td>
Badge
</td>
<td>
<code>QtMaterialBadge</code>
</td>
</tr>
<tr>
<td colspan="2" align="center">
<img src="gifs/badge.gif" />
</td>
</tr>
<tr>
<td>
Check Box
</td>
<td>
<code>QtMaterialCheckBox</code>
</td>
</tr>
<tr>
<td colspan="2" align="center">
<img src="gifs/checkbox.gif" />
</td>
</tr>
<tr>
<td>
Circular Progress
</td>
<td>
<code>QtMaterialCircularProgress</code>
</td>
</tr>
<tr>
<td colspan="2" align="center">
<img src="gifs/circularprogress.gif" />
</td>
</tr>
<tr>
<td>
Dialog
</td>
<td>
<code>QtMaterialDialog</code>
</td>
</tr>
<tr>
<td colspan="2" align="center">
<img src="gifs/dialog.gif" />
</td>
</tr>
<tr>
<td>
Drawer
</td>
<td>
<code>QtMaterialDrawer</code>
</td>
</tr>
<tr>
<td colspan="2">
<img src="gifs/drawer.gif" />
</td>
</tr>
<tr>
<td>
FAB
</td>
<td>
<code>QtMaterialFloatingActionButton</code>
</td>
</tr>
<tr>
<td colspan="2" align="center">
<img src="gifs/fab.gif" />
</td>
</tr>
<tr>
<td>
Flat Button
</td>
<td>
<code>QtMaterialFlatButton</code>
</td>
</tr>
<tr>
<td colspan="2" align="center">
<img src="gifs/flatbutton.gif" />
</td>
</tr>
<tr>
<td>
Icon Button
</td>
<td>
<code>QtMaterialIconButton</code>
</td>
</tr>
<tr>
<td colspan="2" align="center">
<img src="gifs/iconbutton.gif" />
</td>
</tr>
<tr>
<td>
Progress
</td>
<td>
<code>QtMaterialProgress</code>
</td>
</tr>
<tr>
<td colspan="2" align="center">
<img src="gifs/progress.gif" />
</td>
</tr>
<tr>
<td>
Radio Button
</td>
<td>
<code>QtMaterialRadioButton</code>
</td>
</tr>
<tr>
<td colspan="2" align="center">
<img src="gifs/radiobutton.gif" />
</td>
</tr>
<tr>
<td>
Raised Button
</td>
<td>
<code>QtMaterialRaisedButton</code>
</td>
</tr>
<tr>
<td colspan="2" align="center">
<img src="gifs/raisedbutton.gif" />
</td>
</tr>
<tr>
<td>
Scroll Bar
</td>
<td>
<code>QtMaterialScrollBar</code>
</td>
</tr>
<tr>
<td colspan="2" align="center">
<img src="gifs/scrollbar.gif" />
</td>
</tr>
<tr>
<td>
Slider
</td>
<td>
<code>QtMaterialSlider</code>
</td>
</tr>
<tr>
<td colspan="2" align="center">
<img src="gifs/slider.gif" />
</td>
</tr>
<tr>
<td>
Snackbar
</td>
<td>
<code>QtMaterialSnackBar</code>
</td>
</tr>
<tr>
<td colspan="2" align="center">
<img src="gifs/snackbar.gif" />
</td>
</tr>
<tr>
<td>
Tabs
</td>
<td>
<code>QtMaterialTabs</code>
</td>
</tr>
<tr>
<td colspan="2" align="center">
<img src="gifs/tabs.gif" />
</td>
</tr>
<tr>
<td>
Text Field
</td>
<td>
<code>QtMaterialTextField</code>
</td>
</tr>
<tr>
<td colspan="2" align="center">
<img src="gifs/textfield.gif" />
</td>
</tr>
<tr>
<td>
Toggle
</td>
<td>
<code>QtMaterialToggle</code>
</td>
</tr>
<tr>
<td colspan="2" align="center">
<img src="gifs/toggle.gif" />
</td>
</tr>
</tbody>
</table>
#### Implemented components
- [x] App Bar
- [x] Auto Complete
- [x] Avatar
- [x] Badge
- [x] Check Box
- [x] Circular Progress
- [x] Dialog
- [x] Drawer
- [x] Floating Action Button
- [x] Flat Button
- [x] Icon Button
- [x] Progress
- [x] Radio Button
- [x] Raised Button
- [x] Scroll Bar
- [x] Slider
- [x] Snackbar
- [x] Tabs
- [x] Text Field
- [x] Toggle
#### Work in progress
- [ ] Divider
- [ ] List
- [ ] List Item
- [ ] Menu
- [ ] Paper
- [ ] Snackbar Layout
- [ ] Table
#### Not implemented
- [ ] Card
- [ ] Chips
- [ ] Discrete Slider
- [ ] Grid List
- [ ] Icon Menu
- [ ] Search Field
- [ ] Select Field
- [ ] Stepper
- [ ] Subheaders
- [ ] Toolbar

View File

@ -0,0 +1,130 @@
TEMPLATE = lib
CONFIG += staticlib
SOURCES = \
qtmaterialavatar.cpp \
lib/qtmaterialstyle.cpp \
lib/qtmaterialtheme.cpp \
qtmaterialbadge.cpp \
lib/qtmaterialoverlaywidget.cpp \
qtmaterialcheckbox.cpp \
lib/qtmaterialcheckable_internal.cpp \
lib/qtmaterialcheckable.cpp \
lib/qtmaterialripple.cpp \
lib/qtmaterialrippleoverlay.cpp \
qtmaterialfab.cpp \
qtmaterialraisedbutton.cpp \
qtmaterialflatbutton_internal.cpp \
qtmaterialflatbutton.cpp \
lib/qtmaterialstatetransition.cpp \
qtmaterialiconbutton.cpp \
qtmaterialprogress_internal.cpp \
qtmaterialprogress.cpp \
qtmaterialcircularprogress_internal.cpp \
qtmaterialcircularprogress.cpp \
qtmaterialslider_internal.cpp \
qtmaterialslider.cpp \
qtmaterialsnackbar_internal.cpp \
qtmaterialsnackbar.cpp \
qtmaterialradiobutton.cpp \
qtmaterialtoggle_internal.cpp \
qtmaterialtoggle.cpp \
qtmaterialtextfield_internal.cpp \
qtmaterialtextfield.cpp \
qtmaterialtabs_internal.cpp \
qtmaterialtabs.cpp \
qtmaterialscrollbar_internal.cpp \
qtmaterialscrollbar.cpp \
qtmaterialdialog_internal.cpp \
qtmaterialdialog.cpp \
qtmaterialdrawer_internal.cpp \
qtmaterialdrawer.cpp \
qtmaterialappbar.cpp \
qtmaterialautocomplete.cpp \
qtmaterialpaper.cpp \
qtmaterialtable.cpp \
layouts/qtmaterialsnackbarlayout.cpp \
qtmaterialautocomplete_internal.cpp \
qtmaterialmenu.cpp \
qtmaterialmenu_internal.cpp \
qtmateriallist.cpp \
qtmateriallistitem.cpp
HEADERS = \
qtmaterialavatar_p.h \
qtmaterialavatar.h \
lib/qtmaterialstyle_p.h \
lib/qtmaterialstyle.h \
lib/qtmaterialtheme_p.h \
lib/qtmaterialtheme.h \
qtmaterialbadge_p.h \
qtmaterialbadge.h \
lib/qtmaterialoverlaywidget.h \
qtmaterialcheckbox_p.h \
qtmaterialcheckbox.h \
lib/qtmaterialcheckable_internal.h \
lib/qtmaterialcheckable_p.h \
lib/qtmaterialripple.h \
lib/qtmaterialrippleoverlay.h \
lib/qtmaterialcheckable.h \
qtmaterialfab_p.h \
qtmaterialfab.h \
qtmaterialraisedbutton_p.h \
qtmaterialraisedbutton.h \
qtmaterialflatbutton_internal.h \
qtmaterialflatbutton_p.h \
qtmaterialflatbutton.h \
lib/qtmaterialstatetransition.h \
lib/qtmaterialstatetransitionevent.h \
qtmaterialiconbutton_p.h \
qtmaterialiconbutton.h \
qtmaterialprogress_internal.h \
qtmaterialprogress_p.h \
qtmaterialprogress.h \
qtmaterialcircularprogress_internal.h \
qtmaterialcircularprogress_p.h \
qtmaterialcircularprogress.h \
qtmaterialslider_internal.h \
qtmaterialslider_p.h \
qtmaterialslider.h \
qtmaterialsnackbar_internal.h \
qtmaterialsnackbar_p.h \
qtmaterialsnackbar.h \
qtmaterialradiobutton_p.h \
qtmaterialradiobutton.h \
qtmaterialtoggle_internal.h \
qtmaterialtoggle_p.h \
qtmaterialtoggle.h \
qtmaterialtextfield_internal.h \
qtmaterialtextfield_p.h \
qtmaterialtextfield.h \
qtmaterialtabs_internal.h \
qtmaterialtabs_p.h \
qtmaterialtabs.h \
qtmaterialscrollbar_internal.h \
qtmaterialscrollbar_p.h \
qtmaterialscrollbar.h \
qtmaterialdialog_internal.h \
qtmaterialdialog_p.h \
qtmaterialdialog.h \
qtmaterialdrawer_internal.h \
qtmaterialdrawer_p.h \
qtmaterialdrawer.h \
qtmaterialappbar.h \
qtmaterialappbar_p.h \
qtmaterialautocomplete.h \
qtmaterialautocomplete_p.h \
qtmaterialpaper.h \
qtmaterialpaper_p.h \
qtmaterialtable.h \
qtmaterialtable_p.h \
layouts/qtmaterialsnackbarlayout.h \
layouts/qtmaterialsnackbarlayout_p.h \
qtmaterialautocomplete_internal.h \
qtmaterialmenu.h \
qtmaterialmenu_p.h \
qtmaterialmenu_internal.h \
qtmateriallist.h \
qtmateriallist_p.h \
qtmateriallistitem.h \
qtmateriallistitem_p.h
RESOURCES += \
resources.qrc

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More