Compare commits
17 Commits
73719905db
...
adb28a67e8
Author | SHA1 | Date |
---|---|---|
ArgonarioD | adb28a67e8 | |
ArgonarioD | 47ada04c3a | |
ArgonarioD | 1378997f64 | |
ArgonarioD | 1650404bb9 | |
karlis | 69422ba96a | |
karlis | 3d8420f617 | |
yang.yongquan | e48954175d | |
yang.yongquan | 3c2eada43f | |
karlis | 6494c2b9af | |
wuyize | fd1baf42f6 | |
karlis | aeead9d22e | |
ArgonarioD | f42868cf3f | |
ArgonarioD | d40796abb0 | |
karlis | 84bddf4447 | |
wuyize | 31f2c1be8f | |
ArgonarioD | c15e8c3a5b | |
karlis | 24f8daf1fd |
|
@ -104,6 +104,7 @@
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClCompile Include="src\Editor\EditorWidgetComponent\FillStyleWidget.cpp" />
|
||||||
<ClCompile Include="src\Editor\RightBar\EditorSettingWidget.cpp" />
|
<ClCompile Include="src\Editor\RightBar\EditorSettingWidget.cpp" />
|
||||||
<ClCompile Include="src\Editor\EditorWidgetComponent\ColorPicker.cpp" />
|
<ClCompile Include="src\Editor\EditorWidgetComponent\ColorPicker.cpp" />
|
||||||
<ClCompile Include="src\Editor\EditorWidgetComponent\LayerCreateWidget.cpp" />
|
<ClCompile Include="src\Editor\EditorWidgetComponent\LayerCreateWidget.cpp" />
|
||||||
|
@ -200,6 +201,7 @@
|
||||||
<QtMoc Include="src\Editor\EditorWidgetComponent\LayerStyleDialog.h" />
|
<QtMoc Include="src\Editor\EditorWidgetComponent\LayerStyleDialog.h" />
|
||||||
<QtMoc Include="src\Editor\EditorWidgetComponent\ColorPicker.h" />
|
<QtMoc Include="src\Editor\EditorWidgetComponent\ColorPicker.h" />
|
||||||
<QtMoc Include="src\Editor\RightBar\EditorSettingWidget.h" />
|
<QtMoc Include="src\Editor\RightBar\EditorSettingWidget.h" />
|
||||||
|
<QtMoc Include="src\Editor\EditorWidgetComponent\FillStyleWidget.h" />
|
||||||
<ClInclude Include="src\Editor\util\EncodeUtil.hpp" />
|
<ClInclude Include="src\Editor\util\EncodeUtil.hpp" />
|
||||||
<ClInclude Include="src\Editor\util\JsonUtil.hpp" />
|
<ClInclude Include="src\Editor\util\JsonUtil.hpp" />
|
||||||
<ClInclude Include="src\Editor\ElementManager.h" />
|
<ClInclude Include="src\Editor\ElementManager.h" />
|
||||||
|
|
|
@ -240,6 +240,9 @@
|
||||||
<ClCompile Include="src\Editor\RightBar\EditorSettingWidget.cpp">
|
<ClCompile Include="src\Editor\RightBar\EditorSettingWidget.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Editor\EditorWidgetComponent\FillStyleWidget.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<QtMoc Include="src\Renderer\RendererGLWidget.h">
|
<QtMoc Include="src\Renderer\RendererGLWidget.h">
|
||||||
|
@ -290,6 +293,9 @@
|
||||||
<QtMoc Include="src\Editor\RightBar\EditorSettingWidget.h">
|
<QtMoc Include="src\Editor\RightBar\EditorSettingWidget.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</QtMoc>
|
</QtMoc>
|
||||||
|
<QtMoc Include="src\Editor\EditorWidgetComponent\FillStyleWidget.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</QtMoc>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="..\data.json" />
|
<None Include="..\data.json" />
|
||||||
|
|
|
@ -182,7 +182,12 @@
|
||||||
</property>
|
</property>
|
||||||
<column>
|
<column>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>图层树</string>
|
<string>图层名</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>关联图元</string>
|
||||||
</property>
|
</property>
|
||||||
</column>
|
</column>
|
||||||
</widget>
|
</widget>
|
||||||
|
|
|
@ -84,10 +84,26 @@
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,0">
|
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,1,0">
|
||||||
<property name="sizeConstraint">
|
<property name="sizeConstraint">
|
||||||
<enum>QLayout::SetDefaultConstraint</enum>
|
<enum>QLayout::SetDefaultConstraint</enum>
|
||||||
</property>
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QListWidget" name="textureListWidget">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Expanding">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="Renderer::RendererGLWidget" name="openGLWidget">
|
<widget class="Renderer::RendererGLWidget" name="openGLWidget">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
|
|
|
@ -20,22 +20,25 @@ layout(std430, binding = 1) buffer bvhBoundBuffer
|
||||||
{
|
{
|
||||||
vec4 bvhBound[];
|
vec4 bvhBound[];
|
||||||
};
|
};
|
||||||
layout(std430, binding = 2) buffer elementOffsetBuffer
|
layout(std430, binding = 2) buffer elementTranformBuffer
|
||||||
|
{
|
||||||
|
mat3x2 elementTranform[];
|
||||||
|
};
|
||||||
|
layout(std430, binding = 3) buffer elementOffsetBuffer
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @[0] elementBvhRoot
|
* @[0] elementBvhRoot
|
||||||
* @[1] styleOffset
|
* @[1] styleOffset
|
||||||
* @[2] pointsOffset
|
* @[2] pointsOffset
|
||||||
* @[3] linesOffset
|
* @[3] linesOffset
|
||||||
|
|
||||||
*/
|
*/
|
||||||
uint elementOffset[][5];
|
uint elementOffset[][4];
|
||||||
};
|
};
|
||||||
layout(std430, binding = 3) buffer elementIndexBuffer
|
layout(std430, binding = 4) buffer elementIndexBuffer
|
||||||
{
|
{
|
||||||
uint elementIndexs[]; // ÏߺÍÃæ
|
uint elementIndexs[]; // ÏߺÍÃæ
|
||||||
};
|
};
|
||||||
layout(std430, binding = 4) buffer elementDataBuffer
|
layout(std430, binding = 5) buffer elementDataBuffer
|
||||||
{
|
{
|
||||||
float elementData[]; // µãºÍStyle
|
float elementData[]; // µãºÍStyle
|
||||||
};
|
};
|
||||||
|
@ -1115,15 +1118,11 @@ bool fillElement(vec2 localUV, uint contourIndex, uint linesOffset, uint pointsO
|
||||||
}
|
}
|
||||||
|
|
||||||
bool strokeElement(vec2 localUV, uint contourIndex, uint linesOffset, uint pointsOffset, uint styleIndex,
|
bool strokeElement(vec2 localUV, uint contourIndex, uint linesOffset, uint pointsOffset, uint styleIndex,
|
||||||
float widthHeightRatio, inout vec4 elementColor, inout vec2 metallicRoughness)
|
inout vec4 elementColor, inout vec2 metallicRoughness)
|
||||||
{
|
{
|
||||||
bool hitElement = false;
|
bool hitElement = false;
|
||||||
float strokeWidth = elementData[styleIndex];
|
float strokeWidth = elementData[styleIndex];
|
||||||
|
|
||||||
vec2 size = normalize(vec2(widthHeightRatio, 1)) + vec2(2 * strokeWidth);
|
|
||||||
vec2 ratio = widthHeightRatio < 1 ? vec2(widthHeightRatio, 1) : vec2(1, 1 / widthHeightRatio);
|
|
||||||
localUV *= ratio;
|
|
||||||
|
|
||||||
float minDistance = 1e38;
|
float minDistance = 1e38;
|
||||||
uint lineCount = elementIndexs[contourIndex];
|
uint lineCount = elementIndexs[contourIndex];
|
||||||
vec4 styleHead = unpackUnorm4x8(floatBitsToUint(elementData[styleIndex + 1]));
|
vec4 styleHead = unpackUnorm4x8(floatBitsToUint(elementData[styleIndex + 1]));
|
||||||
|
@ -1149,17 +1148,13 @@ bool strokeElement(vec2 localUV, uint contourIndex, uint linesOffset, uint point
|
||||||
mat4x2 p =
|
mat4x2 p =
|
||||||
mat4x2(elementData[pxIndex[0]], elementData[pyIndex[0]], elementData[pxIndex[1]], elementData[pyIndex[1]],
|
mat4x2(elementData[pxIndex[0]], elementData[pyIndex[0]], elementData[pxIndex[1]], elementData[pyIndex[1]],
|
||||||
elementData[pxIndex[2]], elementData[pyIndex[2]], elementData[pxIndex[3]], elementData[pyIndex[3]]);
|
elementData[pxIndex[2]], elementData[pyIndex[2]], elementData[pxIndex[3]], elementData[pyIndex[3]]);
|
||||||
p[0] *= ratio;
|
|
||||||
p[1] *= ratio;
|
|
||||||
p[2] *= ratio;
|
|
||||||
p[3] *= ratio;
|
|
||||||
|
|
||||||
vec2 tangentBeginNext = vec2(0);
|
vec2 tangentBeginNext = vec2(0);
|
||||||
if (contourIterator + 1 < contourIndex + 1 + lineCount)
|
if (contourIterator + 1 < contourIndex + 1 + lineCount)
|
||||||
{
|
{
|
||||||
uint lineIndex = elementIndexs[contourIterator + 1];
|
uint lineIndex = elementIndexs[contourIterator + 1];
|
||||||
uint pLocation = linesOffset + 3 * lineIndex;
|
uint pLocation = linesOffset + 3 * lineIndex;
|
||||||
//vec2 percent = unpackUnorm2x16(elementIndexs[pLocation + 2]);
|
// vec2 percent = unpackUnorm2x16(elementIndexs[pLocation + 2]);
|
||||||
uvec4 pxIndex = uvec4(pointsOffset) +
|
uvec4 pxIndex = uvec4(pointsOffset) +
|
||||||
2 * uvec4(elementIndexs[pLocation] >> 16, elementIndexs[pLocation] & 0xFFFF,
|
2 * uvec4(elementIndexs[pLocation] >> 16, elementIndexs[pLocation] & 0xFFFF,
|
||||||
elementIndexs[pLocation + 1] >> 16, elementIndexs[pLocation + 1] & 0xFFFF);
|
elementIndexs[pLocation + 1] >> 16, elementIndexs[pLocation + 1] & 0xFFFF);
|
||||||
|
@ -1168,10 +1163,6 @@ bool strokeElement(vec2 localUV, uint contourIndex, uint linesOffset, uint point
|
||||||
mat4x2 pNext = mat4x2(elementData[pxIndex[0]], elementData[pyIndex[0]], elementData[pxIndex[1]],
|
mat4x2 pNext = mat4x2(elementData[pxIndex[0]], elementData[pyIndex[0]], elementData[pxIndex[1]],
|
||||||
elementData[pyIndex[1]], elementData[pxIndex[2]], elementData[pyIndex[2]],
|
elementData[pyIndex[1]], elementData[pxIndex[2]], elementData[pyIndex[2]],
|
||||||
elementData[pxIndex[3]], elementData[pyIndex[3]]);
|
elementData[pxIndex[3]], elementData[pyIndex[3]]);
|
||||||
pNext[0] *= ratio;
|
|
||||||
pNext[1] *= ratio;
|
|
||||||
pNext[2] *= ratio;
|
|
||||||
pNext[3] *= ratio;
|
|
||||||
|
|
||||||
if (pNext[0] == pNext[1] && pNext[2] == pNext[3])
|
if (pNext[0] == pNext[1] && pNext[2] == pNext[3])
|
||||||
{
|
{
|
||||||
|
@ -1179,8 +1170,8 @@ bool strokeElement(vec2 localUV, uint contourIndex, uint linesOffset, uint point
|
||||||
pNext[2] = pNext[1];
|
pNext[2] = pNext[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
//if(pNext[0]!=p[3])
|
// if(pNext[0]!=p[3])
|
||||||
// break;
|
// break;
|
||||||
if (pNext[0] != pNext[1])
|
if (pNext[0] != pNext[1])
|
||||||
tangentBeginNext = normalize(pNext[0] - pNext[1]);
|
tangentBeginNext = normalize(pNext[0] - pNext[1]);
|
||||||
else
|
else
|
||||||
|
@ -1221,11 +1212,11 @@ bool strokeElement(vec2 localUV, uint contourIndex, uint linesOffset, uint point
|
||||||
|
|
||||||
bool hit = d < minDistance;
|
bool hit = d < minDistance;
|
||||||
if (onBegin)
|
if (onBegin)
|
||||||
hit =
|
hit = hit && shouldFillBeginCap(localUV, contourIterator == contourIndex + 1, endType, p[0],
|
||||||
hit && shouldFillBeginCap(localUV, contourIterator == contourIndex + 1, endType, p[0], tangentBegin, p3Last - p2Last);
|
tangentBegin, p3Last - p2Last);
|
||||||
if (onEnd)
|
if (onEnd)
|
||||||
hit = hit &&
|
hit = hit && shouldFillEndCap(localUV, tangentBeginNext == vec2(0), endType, p[3], tangentEnd,
|
||||||
shouldFillEndCap(localUV, tangentBeginNext==vec2(0), endType, p[3], tangentEnd, tangentBeginNext);
|
tangentBeginNext);
|
||||||
if (hit)
|
if (hit)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -1272,7 +1263,7 @@ bool strokeElement(vec2 localUV, uint contourIndex, uint linesOffset, uint point
|
||||||
return hitElement;
|
return hitElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool drawElement(uint elementIndex, vec2 localUV, vec2 scale, out vec3 color, out vec2 metallicRoughness,
|
bool drawElement(uint elementIndex, vec2 localUV, out vec3 color, out vec2 metallicRoughness,
|
||||||
inout vec3 debugBVH = vec3(0))
|
inout vec3 debugBVH = vec3(0))
|
||||||
{
|
{
|
||||||
bool hitElement = false;
|
bool hitElement = false;
|
||||||
|
@ -1284,7 +1275,7 @@ bool drawElement(uint elementIndex, vec2 localUV, vec2 scale, out vec3 color, ou
|
||||||
uint styleIndex = currentOffset[1];
|
uint styleIndex = currentOffset[1];
|
||||||
uint pointsOffset = currentOffset[2];
|
uint pointsOffset = currentOffset[2];
|
||||||
uint linesOffset = currentOffset[3];
|
uint linesOffset = currentOffset[3];
|
||||||
float widthHeightRatio = uintBitsToFloat(currentOffset[4]);
|
// float widthHeightRatio = uintBitsToFloat(currentOffset[4]);
|
||||||
|
|
||||||
elementStack.top = 0;
|
elementStack.top = 0;
|
||||||
uint elementBvhIndex = 0;
|
uint elementBvhIndex = 0;
|
||||||
|
@ -1317,7 +1308,7 @@ bool drawElement(uint elementIndex, vec2 localUV, vec2 scale, out vec3 color, ou
|
||||||
else // Ïß
|
else // Ïß
|
||||||
{
|
{
|
||||||
hitElement = strokeElement(localUV, contourIndex, linesOffset, pointsOffset, styleIndex,
|
hitElement = strokeElement(localUV, contourIndex, linesOffset, pointsOffset, styleIndex,
|
||||||
widthHeightRatio, elementColor, metallicRoughness);
|
elementColor, metallicRoughness);
|
||||||
}
|
}
|
||||||
|
|
||||||
elementBvhIndex = elementBvhLength;
|
elementBvhIndex = elementBvhLength;
|
||||||
|
@ -1357,7 +1348,7 @@ void main()
|
||||||
|
|
||||||
vec3 debugBVH = vec3(0);
|
vec3 debugBVH = vec3(0);
|
||||||
// bool debugHit = false;
|
// bool debugHit = false;
|
||||||
//vec4 color = vec4(0.76, 0.33, 0.15, -1);
|
// vec4 color = vec4(0.76, 0.33, 0.15, -1);
|
||||||
vec4 color = vec4(backgroundColor, -1);
|
vec4 color = vec4(backgroundColor, -1);
|
||||||
vec2 metallicRoughness = vec2(0, 0.8);
|
vec2 metallicRoughness = vec2(0, 0.8);
|
||||||
stack.top = 0;
|
stack.top = 0;
|
||||||
|
@ -1371,49 +1362,39 @@ void main()
|
||||||
visitTime++;
|
visitTime++;
|
||||||
vec4 bound = bvhBound[index];
|
vec4 bound = bvhBound[index];
|
||||||
uint leftChild = bvhChildren[index].x;
|
uint leftChild = bvhChildren[index].x;
|
||||||
if (leftChild >= bvhLength)
|
|
||||||
{
|
|
||||||
uint zIndex = bvhChildren[index].y >> 18;
|
|
||||||
bvec2 flip = bvec2(bvhChildren[index].y & (1 << 16), bvhChildren[index].y & (1 << 17));
|
|
||||||
float angle = (float(bvhChildren[index].y & ((1 << 16) - 1)) / 65535.0) * 2 * PI;
|
|
||||||
mat2 rotation = {{cos(angle), -sin(angle)}, {sin(angle), cos(angle)}};
|
|
||||||
vec2 localUV = uv - (bound.xy + bound.zw) / 2;
|
|
||||||
localUV = rotation * localUV;
|
|
||||||
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))))
|
|
||||||
if (any(greaterThan(vec2(-1) + vec2(0.005), localUV)) ||
|
|
||||||
any(greaterThan(localUV, vec2(1) - vec2(0.005))))
|
|
||||||
debugBVH.g += 0.3;
|
|
||||||
// uint elementIndex = leftChild - bvhLength;
|
|
||||||
// debugBVH.bg += 0.5 * (localUV + vec2(1));
|
|
||||||
|
|
||||||
// debugBVH = vec3(0);
|
if (all(lessThan(bound.xy, uv)) && all(lessThan(uv, bound.zw)))
|
||||||
if (flip.x)
|
{
|
||||||
localUV.x = -localUV.x;
|
if (any(greaterThan(bound.xy + vec2(0.005), uv)) || any(greaterThan(uv, bound.zw - vec2(0.005))))
|
||||||
if (flip.y)
|
debugBVH.g += 0.3;
|
||||||
localUV.y = -localUV.y;
|
|
||||||
|
if (leftChild >= bvhLength)
|
||||||
|
{
|
||||||
|
uint transformIndex = leftChild - 0x80000000;
|
||||||
|
uint zIndex = bvhChildren[index].y >> 18;
|
||||||
|
uint elementIndex = bvhChildren[index].y - zIndex;
|
||||||
|
mat3x2 transform = elementTranform[transformIndex];
|
||||||
|
vec2 localUV =
|
||||||
|
(mat3(vec3(transform[0], 0), vec3(transform[1], 0), vec3(transform[2], 1)) * vec3(uv, 1)).xy;
|
||||||
|
|
||||||
vec3 elementColor;
|
vec3 elementColor;
|
||||||
vec2 elementMetallicRoughness;
|
vec2 elementMetallicRoughness;
|
||||||
if (drawElement(leftChild - 0x80000000, localUV, scale, elementColor, elementMetallicRoughness,
|
if (drawElement(elementIndex, localUV, elementColor, elementMetallicRoughness,
|
||||||
debugBVH))
|
debugBVH))
|
||||||
{
|
{
|
||||||
color = vec4(elementColor, zIndex);
|
color = vec4(elementColor, zIndex);
|
||||||
metallicRoughness = elementMetallicRoughness;
|
metallicRoughness = elementMetallicRoughness;
|
||||||
}
|
}
|
||||||
}
|
//if(elementIndex == 1 && transformIndex==1)
|
||||||
|
// color = vec4(1,1,0,1);
|
||||||
|
|
||||||
index = bvhLength;
|
index = bvhLength;
|
||||||
}
|
}
|
||||||
else if (all(lessThan(bound.xy, uv)) && all(lessThan(uv, bound.zw)))
|
else
|
||||||
{
|
{
|
||||||
if (any(greaterThan(bound.xy + vec2(0.005), uv)) || any(greaterThan(uv, bound.zw - vec2(0.005))))
|
stack.push(index);
|
||||||
debugBVH.g += 0.3;
|
index = leftChild;
|
||||||
// debugBVH.r += 0.02;
|
}
|
||||||
stack.push(index);
|
|
||||||
index = leftChild;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
index = bvhLength;
|
index = bvhLength;
|
||||||
|
@ -1428,7 +1409,7 @@ void main()
|
||||||
|
|
||||||
imageStore(gBaseColor, pixelLocation, vec4(color.rgb, 1));
|
imageStore(gBaseColor, pixelLocation, vec4(color.rgb, 1));
|
||||||
imageStore(gMetallicRoughness, pixelLocation, vec4(metallicRoughness, 0, 1));
|
imageStore(gMetallicRoughness, pixelLocation, vec4(metallicRoughness, 0, 1));
|
||||||
return;
|
//return;
|
||||||
if (/*color.a!=-1&&*/ debugBVH == vec3(0))
|
if (/*color.a!=-1&&*/ debugBVH == vec3(0))
|
||||||
{
|
{
|
||||||
// imageStore(gBaseColor, pixelLocation, vec4(vec3(1, 1, 0),1));
|
// imageStore(gBaseColor, pixelLocation, vec4(vec3(1, 1, 0),1));
|
||||||
|
|
|
@ -6,7 +6,7 @@ class ColorPicker : public QPushButton
|
||||||
private:
|
private:
|
||||||
QColor color;
|
QColor color;
|
||||||
public:
|
public:
|
||||||
ColorPicker(const QColor& color, QWidget* parent = nullptr);
|
ColorPicker(const QColor& color = QColor::fromRgb(0, 0, 0), QWidget* parent = nullptr);
|
||||||
QColor getColor() const;
|
QColor getColor() const;
|
||||||
public slots:
|
public slots:
|
||||||
void onClicked();
|
void onClicked();
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
#include "FillStyleWidget.h"
|
||||||
|
#include "ColorPicker.h"
|
||||||
|
#include <QGridLayout>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <qtmaterialtextfield.h>
|
||||||
|
|
||||||
|
FillStyleWidget::FillStyleWidget(std::shared_ptr<Renderer::MaterialStyleFill> fill, QWidget* parent)
|
||||||
|
: QWidget(parent), fill(fill)
|
||||||
|
{
|
||||||
|
auto* layout = new QGridLayout(this);
|
||||||
|
this->setLayout(layout);
|
||||||
|
|
||||||
|
// ÑÕÉ«
|
||||||
|
auto* material = &plainFill(fill)->material;
|
||||||
|
auto* colorLabel = new QLabel(QStringLiteral("ÑÕÉ«"), this);
|
||||||
|
layout->addWidget(colorLabel, 0, 0);
|
||||||
|
auto* colorPicker = new ColorPicker(material->color);
|
||||||
|
connect(colorPicker, &ColorPicker::colorChanged,
|
||||||
|
[material](QColor color)
|
||||||
|
{
|
||||||
|
material->color = color;
|
||||||
|
});
|
||||||
|
layout->addWidget(colorPicker, 0, 1);
|
||||||
|
|
||||||
|
// ½ðÊô¶È
|
||||||
|
auto* metallicLabel = new QLabel(QStringLiteral("½ðÊô¶È"), this);
|
||||||
|
layout->addWidget(metallicLabel, 1, 0);
|
||||||
|
auto* metallicInput = new QtMaterialTextField(this);
|
||||||
|
metallicInput->setText(QString::number(material->metallicF(), 'g', 3));
|
||||||
|
connect(metallicInput, &QtMaterialTextField::textChanged,
|
||||||
|
[material](const QString& text)
|
||||||
|
{
|
||||||
|
material->setMetallicF(text.toFloat());
|
||||||
|
});
|
||||||
|
layout->addWidget(metallicInput, 1, 1);
|
||||||
|
|
||||||
|
// ´Ö²Ú¶È
|
||||||
|
auto* roughnessLabel = new QLabel(QStringLiteral("´Ö²Ú¶È"), this);
|
||||||
|
layout->addWidget(roughnessLabel, 2, 0);
|
||||||
|
auto* roughnessInput = new QtMaterialTextField(this);
|
||||||
|
roughnessInput->setText(QString::number(material->roughnessF(), 'g', 3));
|
||||||
|
connect(roughnessInput, &QtMaterialTextField::textChanged,
|
||||||
|
[material](const QString& text)
|
||||||
|
{
|
||||||
|
material->setRoughnessF(text.toFloat());
|
||||||
|
});
|
||||||
|
layout->addWidget(roughnessInput, 2, 1);
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
#pragma once
|
||||||
|
#include "../Renderer/Painting/MaterialStyleFill.h"
|
||||||
|
#include "LayerStyle.h"
|
||||||
|
#include <QWidget>
|
||||||
|
class FillStyleWidget : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
FillStyleWidget(std::shared_ptr<Renderer::MaterialStyleFill> fill, QWidget* parent = nullptr);
|
||||||
|
std::shared_ptr<Renderer::MaterialStyleFill> fill;
|
||||||
|
};
|
||||||
|
|
|
@ -1,15 +1,46 @@
|
||||||
#include "LayerCreateWidget.h"
|
#include "LayerCreateWidget.h"
|
||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
|
|
||||||
LayerCreateWidget::LayerCreateWidget(ElementManager* elementManager, QWidget* parent) :
|
LayerCreateWidget::LayerCreateWidget(ElementManager* elementManager, FolderLayerWrapper* folderLayer, QWidget* parent) :
|
||||||
QDialog(parent)
|
QDialog(parent)
|
||||||
{
|
{
|
||||||
|
this->elementManager = elementManager;
|
||||||
ui.setupUi(this);
|
ui.setupUi(this);
|
||||||
connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
|
connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
|
||||||
connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
|
connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
|
||||||
connect(ui.comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onCurrentIndexChanged(int)));
|
connect(ui.comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onCurrentIndexChanged(int)));
|
||||||
elementPool = new ElementPoolWidget(ui.elementPool);
|
elementPool = new ElementPoolWidget(ui.elementPool);
|
||||||
elementPool->setElementList(elementManager->elements);
|
elements = elementManager->elements;
|
||||||
|
elementsCheck(folderLayer);
|
||||||
|
elementPool->setElementList(elements);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LayerCreateWidget::elementsCheck(FolderLayerWrapper* parent)
|
||||||
|
{
|
||||||
|
std::set<LayerWrapper*> upSet, downSet;
|
||||||
|
parent->collectUpReachable(upSet);
|
||||||
|
for (auto it = elements.begin(); it != elements.end();)
|
||||||
|
{
|
||||||
|
bool valid = true;
|
||||||
|
auto ele = dynamic_cast<GroupElement*>(*it);
|
||||||
|
if (ele != nullptr)
|
||||||
|
{
|
||||||
|
downSet.clear();
|
||||||
|
ele->collectReachable(downSet);
|
||||||
|
for (auto& layer : downSet)
|
||||||
|
{
|
||||||
|
if (upSet.find(layer) != upSet.end())
|
||||||
|
{
|
||||||
|
valid = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (valid)
|
||||||
|
++it;
|
||||||
|
else
|
||||||
|
it = elements.erase(it);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LayerCreateWidget::~LayerCreateWidget()
|
LayerCreateWidget::~LayerCreateWidget()
|
||||||
|
@ -21,8 +52,20 @@ void LayerCreateWidget::accept()
|
||||||
QJsonObject jsonObj;
|
QJsonObject jsonObj;
|
||||||
jsonObj.insert("name", ui.name->text());
|
jsonObj.insert("name", ui.name->text());
|
||||||
if (ui.comboBox->currentIndex() == 0) {
|
if (ui.comboBox->currentIndex() == 0) {
|
||||||
|
auto currentEle = elements[elementPool->currentIndex];
|
||||||
|
int index = -1;
|
||||||
|
for (int i = 0; i < elementManager->elements.size(); i++)
|
||||||
|
{
|
||||||
|
if (elementManager->elements[i] == currentEle)
|
||||||
|
{
|
||||||
|
index = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (index == -1)
|
||||||
|
return;
|
||||||
jsonObj.insert("is-folder", false);
|
jsonObj.insert("is-folder", false);
|
||||||
jsonObj.insert("element", elementPool->currentIndex);
|
jsonObj.insert("element", index);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
jsonObj.insert("is-folder", true);
|
jsonObj.insert("is-folder", true);
|
||||||
|
|
|
@ -11,12 +11,15 @@ class LayerCreateWidget :
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
ElementManager* elementManager;
|
||||||
|
std::vector<GraphicElement*> elements;
|
||||||
Ui::LayerCreateWidget ui;
|
Ui::LayerCreateWidget ui;
|
||||||
ElementPoolWidget* elementPool;
|
ElementPoolWidget* elementPool;
|
||||||
|
void elementsCheck(FolderLayerWrapper*);
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
LayerCreateWidget(ElementManager* elementManager,QWidget* parent = nullptr);
|
LayerCreateWidget(ElementManager* elementManager, FolderLayerWrapper* folderLayer, QWidget* parent = nullptr);
|
||||||
~LayerCreateWidget();
|
~LayerCreateWidget();
|
||||||
void accept() override;
|
void accept() override;
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ constexpr int COLUMN_ROUGHNESS = 3;
|
||||||
constexpr int COLUMN_OPERATIONS = 4;
|
constexpr int COLUMN_OPERATIONS = 4;
|
||||||
|
|
||||||
StrokeStyleWidget::StrokeStyleWidget(
|
StrokeStyleWidget::StrokeStyleWidget(
|
||||||
std::shared_ptr<Renderer::MaterialStyleStroke> stroke,
|
std::shared_ptr<MaterialStyleStroke> stroke,
|
||||||
QWidget* parent
|
QWidget* parent
|
||||||
) : QWidget(parent), stroke(stroke)
|
) : QWidget(parent), stroke(stroke)
|
||||||
{
|
{
|
||||||
|
|
|
@ -32,6 +32,7 @@ EditorWidgetItem::EditorWidgetItem(QString filePath,QWidget *parent) : QWidget(p
|
||||||
connect(treeWidget, &LayerTreeWidget::requireRefreshPreview, this,
|
connect(treeWidget, &LayerTreeWidget::requireRefreshPreview, this,
|
||||||
&EditorWidgetItem::triggerRefreshPreview);
|
&EditorWidgetItem::triggerRefreshPreview);
|
||||||
connect(layerInfoDisplayWidget, &InfoDisplayWidget::requireSelfRefresh, layerInfoDisplayWidget, &InfoDisplayWidget::triggerSelfRefresh);
|
connect(layerInfoDisplayWidget, &InfoDisplayWidget::requireSelfRefresh, layerInfoDisplayWidget, &InfoDisplayWidget::triggerSelfRefresh);
|
||||||
|
connect(elementInfoDisplayWidget, &ElementPoolWidget::refreshLayerTree, treeWidget, &LayerTreeWidget::refresh);
|
||||||
// &EditorWidget::triggerRefreshPreview);
|
// &EditorWidget::triggerRefreshPreview);
|
||||||
// test
|
// test
|
||||||
QFile settingFile;
|
QFile settingFile;
|
||||||
|
|
|
@ -67,6 +67,7 @@ void ElementPoolWidget::setElementManager(ElementManager* element)
|
||||||
|
|
||||||
void ElementPoolWidget::refresh() {
|
void ElementPoolWidget::refresh() {
|
||||||
this->setElementList(this->elementManager->elements);
|
this->setElementList(this->elementManager->elements);
|
||||||
|
emit refreshLayerTree();
|
||||||
// update();
|
// update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ public:
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void elementSelected(GraphicElement* element);
|
void elementSelected(GraphicElement* element);
|
||||||
|
void refreshLayerTree();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
int pictureItemClicked(QListWidgetItem* item);
|
int pictureItemClicked(QListWidgetItem* item);
|
||||||
|
|
|
@ -149,3 +149,11 @@ QPixmap GroupElement::getPreview(QSize size)
|
||||||
result = result.copy(rect);
|
result = result.copy(rect);
|
||||||
return result.scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
return result.scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GroupElement::collectReachable(std::set<LayerWrapper*>& set) const
|
||||||
|
{
|
||||||
|
if (sourceLayer != nullptr)
|
||||||
|
{
|
||||||
|
sourceLayer->collectDownReachable(set);
|
||||||
|
}
|
||||||
|
}
|
|
@ -66,6 +66,7 @@ public:
|
||||||
void setSourceLayer(FolderLayerWrapper* sourceLayer);
|
void setSourceLayer(FolderLayerWrapper* sourceLayer);
|
||||||
void paint(QPainter* painter, QTransform transform, const LayerStyleContainer& styles) override;
|
void paint(QPainter* painter, QTransform transform, const LayerStyleContainer& styles) override;
|
||||||
QPixmap getPreview(QSize size) override;
|
QPixmap getPreview(QSize size) override;
|
||||||
|
void collectReachable(std::set<LayerWrapper*>& set) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
//******************************** BitmapPath ********************************//
|
//******************************** BitmapPath ********************************//
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
#include "LayerStyle.h"
|
#include "LayerStyle.h"
|
||||||
#include "./EditorWidgetComponent/StrokeStyleWidget.h"
|
#include "./EditorWidgetComponent/StrokeStyleWidget.h"
|
||||||
|
#include "./EditorWidgetComponent/FillStyleWidget.h"
|
||||||
#include "./util/EncodeUtil.hpp"
|
#include "./util/EncodeUtil.hpp"
|
||||||
#include <qtmaterialcheckbox.h>
|
#include <qtmaterialcheckbox.h>
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
#include <QDialogButtonBox>
|
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QLineEdit>
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#define _USE_JOIN_VIEW_INPUT_RANGE
|
#define _USE_JOIN_VIEW_INPUT_RANGE
|
||||||
|
@ -20,21 +19,19 @@ std::vector<Renderer::BaseStyle> StrokeElementLayerStyle::toBaseStyles() const
|
||||||
{
|
{
|
||||||
if (!radialStroke(strokePair.first)->materialMap.empty())
|
if (!radialStroke(strokePair.first)->materialMap.empty())
|
||||||
{
|
{
|
||||||
baseStyles.push_back(Renderer::BaseStyle(std::make_shared<Renderer::TransformStyle>(),
|
baseStyles.push_back({ std::make_shared<Renderer::TransformStyle>(), strokePair.first });
|
||||||
strokePair.first));
|
|
||||||
}
|
}
|
||||||
if (!radialStroke(strokePair.second)->materialMap.empty())
|
if (!radialStroke(strokePair.second)->materialMap.empty())
|
||||||
{
|
{
|
||||||
baseStyles.push_back(Renderer::BaseStyle(std::make_shared<Renderer::TransformStyle>(),
|
baseStyles.push_back({ std::make_shared<Renderer::TransformStyle>(), strokePair.second });
|
||||||
strokePair.second));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!radialStroke(strokePair.first)->materialMap.empty())
|
else if (!radialStroke(strokePair.first)->materialMap.empty())
|
||||||
{
|
{
|
||||||
const auto material = std::shared_ptr(std::move(strokePair.first->clone()));
|
const auto material = std::shared_ptr(std::move(strokePair.first->clone()));
|
||||||
std::dynamic_pointer_cast<MaterialStyleStroke>(material)->strokeType = Renderer::StrokeType::kBothSides;
|
std::static_pointer_cast<MaterialStyleStroke>(material)->strokeType = Renderer::StrokeType::kBothSides;
|
||||||
|
|
||||||
baseStyles.push_back(Renderer::BaseStyle(std::make_shared<Renderer::TransformStyle>(), material));
|
baseStyles.push_back({ std::make_shared<Renderer::TransformStyle>(), material });
|
||||||
}
|
}
|
||||||
return baseStyles;
|
return baseStyles;
|
||||||
}
|
}
|
||||||
|
@ -197,11 +194,49 @@ bool LayerStyleContainer::dropStyle(const QString& styleName)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline size_t LayerStyleContainer::getHash() const
|
float LayerStyleContainer::boundingBoxAffectValue() const {
|
||||||
|
float maxLineWidth = 0;
|
||||||
|
const auto strokeStyle = styles.at(StrokeElementLayerStyle::displayName());
|
||||||
|
if (strokeStyle != nullptr)
|
||||||
|
{
|
||||||
|
if (const auto strokeElementLayerStyle =
|
||||||
|
std::dynamic_pointer_cast<StrokeElementLayerStyle>(strokeStyle);
|
||||||
|
strokeElementLayerStyle != nullptr)
|
||||||
|
{
|
||||||
|
const auto& leftStyleStroke = strokeElementLayerStyle->strokePair.first;
|
||||||
|
const auto& rightStyleStroke = strokeElementLayerStyle->strokePair.second;
|
||||||
|
if (leftStyleStroke != nullptr)
|
||||||
|
{
|
||||||
|
maxLineWidth = std::max(maxLineWidth, leftStyleStroke->halfWidth);
|
||||||
|
}
|
||||||
|
if (rightStyleStroke != nullptr)
|
||||||
|
{
|
||||||
|
maxLineWidth = std::max(maxLineWidth, rightStyleStroke->halfWidth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return maxLineWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t LayerStyleContainer::getHash() const
|
||||||
{
|
{
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<StrokeElementLayerStyle> StrokeElementLayerStyle::fromJson(const QJsonObject& json)
|
||||||
|
{
|
||||||
|
auto ptr = std::make_unique<StrokeElementLayerStyle>(
|
||||||
|
std::static_pointer_cast<MaterialStyleStroke>(
|
||||||
|
std::shared_ptr(std::move(MaterialStyle::decoded(EncodeUtil::fromBase64<GLfloat>(json["left"].toString()))))
|
||||||
|
),
|
||||||
|
std::static_pointer_cast<MaterialStyleStroke>(
|
||||||
|
std::shared_ptr(std::move(MaterialStyle::decoded(EncodeUtil::fromBase64<GLfloat>(json["right"].toString()))))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
ptr->enableEachSideIndependent = json["enableEachSideIndependent"].toBool();
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
StrokeElementLayerStyle::StrokeElementLayerStyle()
|
StrokeElementLayerStyle::StrokeElementLayerStyle()
|
||||||
{
|
{
|
||||||
const auto materialMap = std::map<float, Renderer::Material>();
|
const auto materialMap = std::map<float, Renderer::Material>();
|
||||||
|
@ -219,7 +254,7 @@ StrokeElementLayerStyle::StrokeElementLayerStyle()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
StrokeElementLayerStyle::StrokeElementLayerStyle(PMaterialStyleStroke left, PMaterialStyleStroke right)
|
StrokeElementLayerStyle::StrokeElementLayerStyle(const PMaterialStyleStroke& left, const PMaterialStyleStroke& right)
|
||||||
{
|
{
|
||||||
this->strokePair.first = left;
|
this->strokePair.first = left;
|
||||||
this->strokePair.second = right ? right : std::static_pointer_cast<MaterialStyleStroke>(
|
this->strokePair.second = right ? right : std::static_pointer_cast<MaterialStyleStroke>(
|
||||||
|
@ -240,8 +275,7 @@ StrokeElementLayerStyle::StrokeElementLayerStyle(const StrokeElementLayerStyle&
|
||||||
|
|
||||||
QJsonObject StrokeElementLayerStyle::toJson() const
|
QJsonObject StrokeElementLayerStyle::toJson() const
|
||||||
{
|
{
|
||||||
QJsonObject json;
|
auto json = LayerStyle::toJson();
|
||||||
json["type"] = typeName();
|
|
||||||
json["enableEachSideIndependent"] = enableEachSideIndependent;
|
json["enableEachSideIndependent"] = enableEachSideIndependent;
|
||||||
json["left"] = EncodeUtil::toBase64<GLfloat>(strokePair.first->encoded());
|
json["left"] = EncodeUtil::toBase64<GLfloat>(strokePair.first->encoded());
|
||||||
json["right"] = EncodeUtil::toBase64<GLfloat>(strokePair.second->encoded());
|
json["right"] = EncodeUtil::toBase64<GLfloat>(strokePair.second->encoded());
|
||||||
|
@ -253,18 +287,24 @@ std::unique_ptr<LayerStyle> StrokeElementLayerStyle::clone() const
|
||||||
return std::make_unique<StrokeElementLayerStyle>(StrokeElementLayerStyle(*this));
|
return std::make_unique<StrokeElementLayerStyle>(StrokeElementLayerStyle(*this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<FillElementLayerStyle> FillElementLayerStyle::fromJson(const QJsonObject& json)
|
||||||
|
{
|
||||||
|
auto ptr = std::make_unique<FillElementLayerStyle>(
|
||||||
|
std::static_pointer_cast<MaterialStyleFill>(
|
||||||
|
std::shared_ptr(std::move(MaterialStyle::decoded(EncodeUtil::fromBase64<GLfloat>(json["material"].toString()))))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<Renderer::BaseStyle> FillElementLayerStyle::toBaseStyles() const
|
std::vector<Renderer::BaseStyle> FillElementLayerStyle::toBaseStyles() const
|
||||||
{
|
{
|
||||||
// TODO: implement
|
return { {std::make_shared<Renderer::TransformStyle>(), fillMaterialStyle} };
|
||||||
return std::vector<Renderer::BaseStyle>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QWidget* FillElementLayerStyle::getInputWidget()
|
QWidget* FillElementLayerStyle::getInputWidget()
|
||||||
{
|
{
|
||||||
// TODO
|
return new FillStyleWidget(fillMaterialStyle);
|
||||||
auto* name = new QLineEdit;
|
|
||||||
name->setText(QStringLiteral("Ìî³ä"));
|
|
||||||
return name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QWidget* FillElementLayerStyle::getListDisplayWidget() const
|
QWidget* FillElementLayerStyle::getListDisplayWidget() const
|
||||||
|
@ -278,18 +318,29 @@ QWidget* FillElementLayerStyle::getListDisplayWidget() const
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FillElementLayerStyle::FillElementLayerStyle(const PMaterialStyleFill& fillMaterialStyle)
|
||||||
|
: fillMaterialStyle(fillMaterialStyle)
|
||||||
|
{
|
||||||
|
if (!fillMaterialStyle)
|
||||||
|
{
|
||||||
|
this->fillMaterialStyle = std::make_shared<MaterialStyleFill>(
|
||||||
|
std::make_shared<Renderer::FillPlain>(Renderer::Material(QColor::fromRgb(0, 0, 0)))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
FillElementLayerStyle::FillElementLayerStyle(const FillElementLayerStyle& other)
|
FillElementLayerStyle::FillElementLayerStyle(const FillElementLayerStyle& other)
|
||||||
{
|
{
|
||||||
materialStyles = std::vector<std::shared_ptr<Renderer::MaterialStyleFill>>(other.materialStyles.size());
|
this->fillMaterialStyle = std::static_pointer_cast<MaterialStyleFill>(
|
||||||
for (size_t i = 0; i < other.materialStyles.size(); i++)
|
std::shared_ptr(std::move(other.fillMaterialStyle->clone()))
|
||||||
{
|
);
|
||||||
materialStyles[i] = std::make_shared<Renderer::MaterialStyleFill>(*other.materialStyles[i]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject FillElementLayerStyle::toJson() const
|
QJsonObject FillElementLayerStyle::toJson() const
|
||||||
{
|
{
|
||||||
return QJsonObject();
|
auto json = LayerStyle::toJson();
|
||||||
|
json["material"] = EncodeUtil::toBase64<GLfloat>(fillMaterialStyle->encoded());
|
||||||
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<LayerStyle> FillElementLayerStyle::clone() const
|
std::unique_ptr<LayerStyle> FillElementLayerStyle::clone() const
|
||||||
|
@ -302,23 +353,18 @@ std::unique_ptr<LayerStyle> LayerStyle::fromJson(const QJsonObject& json)
|
||||||
QString type = json["type"].toString();
|
QString type = json["type"].toString();
|
||||||
if (type == StrokeElementLayerStyle::typeName())
|
if (type == StrokeElementLayerStyle::typeName())
|
||||||
{
|
{
|
||||||
auto ptr = std::make_unique<StrokeElementLayerStyle>(
|
return StrokeElementLayerStyle::fromJson(json);
|
||||||
std::static_pointer_cast<MaterialStyleStroke>(
|
|
||||||
std::shared_ptr(std::move(MaterialStyle::decoded(EncodeUtil::fromBase64<GLfloat>(json["left"].toString()))))
|
|
||||||
),
|
|
||||||
std::static_pointer_cast<MaterialStyleStroke>(
|
|
||||||
std::shared_ptr(std::move(MaterialStyle::decoded(EncodeUtil::fromBase64<GLfloat>(json["right"].toString()))))
|
|
||||||
)
|
|
||||||
);
|
|
||||||
ptr->enableEachSideIndependent = json["enableEachSideIndependent"].toBool();
|
|
||||||
return ptr;
|
|
||||||
}
|
}
|
||||||
else if (type == FillElementLayerStyle::typeName())
|
if (type == FillElementLayerStyle::typeName())
|
||||||
{
|
{
|
||||||
return std::make_unique<FillElementLayerStyle>();
|
return FillElementLayerStyle::fromJson(json);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonObject LayerStyle::toJson() const
|
||||||
|
{
|
||||||
|
QJsonObject json;
|
||||||
|
json["type"] = this->getTypeName();
|
||||||
|
return json;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,26 +12,35 @@
|
||||||
|
|
||||||
using Renderer::MaterialStyle;
|
using Renderer::MaterialStyle;
|
||||||
using Renderer::MaterialStyleStroke;
|
using Renderer::MaterialStyleStroke;
|
||||||
|
using Renderer::MaterialStyleFill;
|
||||||
|
|
||||||
#define STYLE_NAME(display_name, type_name) \
|
#define STYLE_NAME(display_name, type_name) \
|
||||||
static QString displayName() { return QStringLiteral(display_name); } \
|
static QString displayName() { return QStringLiteral(display_name); } \
|
||||||
QString getDisplayName() const override { return QStringLiteral(display_name); } \
|
QString getDisplayName() const override { return QStringLiteral(display_name); } \
|
||||||
static QString typeName() { return type_name; }
|
static QString typeName() { return type_name; } \
|
||||||
|
QString getTypeName() const override { return type_name; }
|
||||||
#define radialStroke(stroke) std::static_pointer_cast<Renderer::StrokeRadialGradient>(stroke->materialStroke)
|
#define radialStroke(stroke) std::static_pointer_cast<Renderer::StrokeRadialGradient>(stroke->materialStroke)
|
||||||
|
#define plainFill(fill) std::static_pointer_cast<Renderer::FillPlain>(fill->materialFill)
|
||||||
|
|
||||||
class LayerStyle : public Renderer::ElementStyle
|
class LayerStyle : public Renderer::ElementStyle
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static std::unique_ptr<LayerStyle> fromJson(const QJsonObject& json);
|
static std::unique_ptr<LayerStyle> fromJson(const QJsonObject& json);
|
||||||
|
virtual ~LayerStyle() = default;
|
||||||
|
|
||||||
virtual QString getDisplayName() const = 0;
|
virtual QString getDisplayName() const = 0;
|
||||||
|
virtual QString getTypeName() const = 0;
|
||||||
|
|
||||||
virtual QWidget* getInputWidget() = 0;
|
virtual QWidget* getInputWidget() = 0;
|
||||||
virtual QWidget* getListDisplayWidget() const = 0;
|
virtual QWidget* getListDisplayWidget() const = 0;
|
||||||
virtual ~LayerStyle() = default;
|
|
||||||
virtual QJsonObject toJson() const = 0;
|
virtual QJsonObject toJson() const;
|
||||||
virtual std::unique_ptr<LayerStyle> clone() const = 0;
|
virtual std::unique_ptr<LayerStyle> clone() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LayerStyle的容器,在每次数据变更时需要手动调用computeNewHash()方法,否则哈希值不会更新
|
||||||
|
*/
|
||||||
class LayerStyleContainer : public Renderer::ElementStyle
|
class LayerStyleContainer : public Renderer::ElementStyle
|
||||||
{
|
{
|
||||||
using DisplayNameWithSupplier = std::map<QString, std::function<std::unique_ptr<LayerStyle>()>>;
|
using DisplayNameWithSupplier = std::map<QString, std::function<std::unique_ptr<LayerStyle>()>>;
|
||||||
|
@ -56,6 +65,7 @@ public:
|
||||||
std::unique_ptr<LayerStyle> makeUnusedStyle(const QString& styleName) const;
|
std::unique_ptr<LayerStyle> makeUnusedStyle(const QString& styleName) const;
|
||||||
bool useStyle(const std::shared_ptr<LayerStyle>& style);
|
bool useStyle(const std::shared_ptr<LayerStyle>& style);
|
||||||
bool dropStyle(const QString& styleName);
|
bool dropStyle(const QString& styleName);
|
||||||
|
float boundingBoxAffectValue() const;
|
||||||
size_t getHash() const;
|
size_t getHash() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -69,10 +79,11 @@ class StrokeElementLayerStyle : public LayerStyle
|
||||||
using PMaterialStyleStroke = std::shared_ptr<MaterialStyleStroke>;
|
using PMaterialStyleStroke = std::shared_ptr<MaterialStyleStroke>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
STYLE_NAME("Ãè±ß","stroke")
|
STYLE_NAME("描边", "stroke")
|
||||||
|
static std::unique_ptr<StrokeElementLayerStyle> fromJson(const QJsonObject& json);
|
||||||
|
|
||||||
StrokeElementLayerStyle();
|
StrokeElementLayerStyle();
|
||||||
StrokeElementLayerStyle(PMaterialStyleStroke left, PMaterialStyleStroke right = nullptr);
|
StrokeElementLayerStyle(const PMaterialStyleStroke& left, const PMaterialStyleStroke& right = nullptr);
|
||||||
StrokeElementLayerStyle(const StrokeElementLayerStyle& other);
|
StrokeElementLayerStyle(const StrokeElementLayerStyle& other);
|
||||||
~StrokeElementLayerStyle() override = default;
|
~StrokeElementLayerStyle() override = default;
|
||||||
|
|
||||||
|
@ -88,16 +99,21 @@ public:
|
||||||
|
|
||||||
class FillElementLayerStyle : public LayerStyle
|
class FillElementLayerStyle : public LayerStyle
|
||||||
{
|
{
|
||||||
|
using PMaterialStyleFill = std::shared_ptr<MaterialStyleFill>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
STYLE_NAME("Ìî³ä","fill")
|
STYLE_NAME("填充", "fill")
|
||||||
|
static std::unique_ptr<FillElementLayerStyle> fromJson(const QJsonObject& json);
|
||||||
|
|
||||||
|
FillElementLayerStyle(const PMaterialStyleFill& fillMaterialStyle = nullptr);
|
||||||
|
FillElementLayerStyle(const FillElementLayerStyle& other);
|
||||||
|
~FillElementLayerStyle() override = default;
|
||||||
|
|
||||||
std::vector<Renderer::BaseStyle> toBaseStyles() const override;
|
std::vector<Renderer::BaseStyle> toBaseStyles() const override;
|
||||||
QWidget* getInputWidget() override;
|
QWidget* getInputWidget() override;
|
||||||
QWidget* getListDisplayWidget() const override;
|
QWidget* getListDisplayWidget() const override;
|
||||||
FillElementLayerStyle() = default;
|
|
||||||
FillElementLayerStyle(const FillElementLayerStyle& other);
|
|
||||||
~FillElementLayerStyle() override = default;
|
|
||||||
std::vector<std::shared_ptr<Renderer::MaterialStyleFill>> materialStyles;
|
|
||||||
QJsonObject toJson() const override;
|
QJsonObject toJson() const override;
|
||||||
std::unique_ptr<LayerStyle> clone() const override;
|
std::unique_ptr<LayerStyle> clone() const override;
|
||||||
|
|
||||||
|
PMaterialStyleFill fillMaterialStyle;
|
||||||
};
|
};
|
|
@ -192,19 +192,39 @@ void FolderLayerWrapper::delSelf() {
|
||||||
|
|
||||||
QTreeWidgetItem* LayerWrapper::getQTreeItem()
|
QTreeWidgetItem* LayerWrapper::getQTreeItem()
|
||||||
{
|
{
|
||||||
this->qTreeWidgetItem->setText(0, this->property.name);
|
|
||||||
this->qTreeWidgetItem->setData(0, Qt::UserRole, QVariant::fromValue(this));
|
this->qTreeWidgetItem->setData(0, Qt::UserRole, QVariant::fromValue(this));
|
||||||
return this->qTreeWidgetItem;
|
return this->qTreeWidgetItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QTreeWidgetItem* LeafLayerWrapper::getQTreeItem()
|
||||||
|
{
|
||||||
|
if (this->qTreeWidgetItem == nullptr)
|
||||||
|
this->qTreeWidgetItem = new QTreeWidgetItem();
|
||||||
|
if (typeid(*wrappedElement) == typeid(GroupElement))
|
||||||
|
{
|
||||||
|
this->qTreeWidgetItem->setText(0, "@ "+this->property.name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->qTreeWidgetItem->setText(0, this->property.name);
|
||||||
|
}
|
||||||
|
this->qTreeWidgetItem->setText(1,">> "+this->wrappedElement->name);
|
||||||
|
this->qTreeWidgetItem->setTextColor(1, Qt::blue);
|
||||||
|
return LayerWrapper::getQTreeItem();
|
||||||
|
}
|
||||||
|
|
||||||
QTreeWidgetItem* FolderLayerWrapper::getQTreeItem()
|
QTreeWidgetItem* FolderLayerWrapper::getQTreeItem()
|
||||||
{
|
{
|
||||||
while (this->qTreeWidgetItem->childCount() > 0) {
|
for (auto& child : this->children) {
|
||||||
this->qTreeWidgetItem->removeChild(this->qTreeWidgetItem->child(0));
|
|
||||||
}
|
|
||||||
for (auto& child : this->children) {
|
|
||||||
this->qTreeWidgetItem->addChild(child->getQTreeItem());
|
this->qTreeWidgetItem->addChild(child->getQTreeItem());
|
||||||
}
|
}
|
||||||
|
this->qTreeWidgetItem->setText(0, this->property.name);
|
||||||
|
auto ele = this->elementManager->getElementById(this->getReferencedBy());
|
||||||
|
if (ele != nullptr)
|
||||||
|
{
|
||||||
|
this->qTreeWidgetItem->setText(1, "<< " + ele->name);
|
||||||
|
this->qTreeWidgetItem->setTextColor(1, Qt::darkGreen);
|
||||||
|
}
|
||||||
return LayerWrapper::getQTreeItem();
|
return LayerWrapper::getQTreeItem();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -286,3 +306,68 @@ void LeafLayerWrapper::paint(QPainter* painter, QTransform transform, bool ignor
|
||||||
wrappedElement->paint(painter, transform, styles);
|
wrappedElement->paint(painter, transform, styles);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LayerWrapper::collectUpReachable(std::set<LayerWrapper*>& reachable)
|
||||||
|
{
|
||||||
|
auto cPos = this;
|
||||||
|
while (cPos != nullptr)
|
||||||
|
{
|
||||||
|
reachable.insert(cPos);
|
||||||
|
cPos = cPos->parent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LayerWrapper::collectDownReachable(std::set<LayerWrapper*>& reachable)
|
||||||
|
{
|
||||||
|
reachable.insert(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LeafLayerWrapper::collectDownReachable(std::set<LayerWrapper*>& reachable)
|
||||||
|
{
|
||||||
|
LayerWrapper::collectDownReachable(reachable);
|
||||||
|
auto ele = dynamic_cast<GroupElement*>(wrappedElement);
|
||||||
|
if (ele != nullptr)
|
||||||
|
{
|
||||||
|
ele->collectReachable(reachable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FolderLayerWrapper::collectDownReachable(std::set<LayerWrapper*>& reachable)
|
||||||
|
{
|
||||||
|
LayerWrapper::collectDownReachable(reachable);
|
||||||
|
for (auto& child : children)
|
||||||
|
child->collectDownReachable(reachable);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LayerWrapper::refreshTreeItem()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void LeafLayerWrapper::refreshTreeItem()
|
||||||
|
{
|
||||||
|
if (typeid(*wrappedElement) == typeid(GroupElement))
|
||||||
|
{
|
||||||
|
this->qTreeWidgetItem->setText(0, "@ " + this->property.name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->qTreeWidgetItem->setText(0, this->property.name);
|
||||||
|
}
|
||||||
|
this->qTreeWidgetItem->setText(1, ">> " + this->wrappedElement->name);
|
||||||
|
this->qTreeWidgetItem->setTextColor(1, Qt::blue);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FolderLayerWrapper::refreshTreeItem()
|
||||||
|
{
|
||||||
|
for (auto& child : this->children) {
|
||||||
|
child->refreshTreeItem();
|
||||||
|
}
|
||||||
|
this->qTreeWidgetItem->setText(0, this->property.name);
|
||||||
|
auto ele = this->elementManager->getElementById(this->getReferencedBy());
|
||||||
|
if (ele != nullptr)
|
||||||
|
{
|
||||||
|
this->qTreeWidgetItem->setText(1, "<< " + ele->name);
|
||||||
|
this->qTreeWidgetItem->setTextColor(1, Qt::darkGreen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -68,7 +68,9 @@ class LayerWrapper
|
||||||
virtual void delSelf();
|
virtual void delSelf();
|
||||||
virtual QJsonObject toJson() const;
|
virtual QJsonObject toJson() const;
|
||||||
~LayerWrapper() = default;
|
~LayerWrapper() = default;
|
||||||
|
virtual void collectUpReachable(std::set<LayerWrapper*>& reachable);
|
||||||
|
virtual void collectDownReachable(std::set<LayerWrapper*>& reachable);
|
||||||
|
virtual void refreshTreeItem();
|
||||||
};
|
};
|
||||||
|
|
||||||
class FolderLayerWrapper : public LayerWrapper
|
class FolderLayerWrapper : public LayerWrapper
|
||||||
|
@ -92,6 +94,8 @@ class FolderLayerWrapper : public LayerWrapper
|
||||||
QJsonObject toJson() const override;
|
QJsonObject toJson() const override;
|
||||||
int getReferencedBy()const;
|
int getReferencedBy()const;
|
||||||
void paint(QPainter* painter, QTransform transform = QTransform(), bool ignoreSelected = false) override;
|
void paint(QPainter* painter, QTransform transform = QTransform(), bool ignoreSelected = false) override;
|
||||||
|
void collectDownReachable(std::set<LayerWrapper*>& reachable) override;
|
||||||
|
void refreshTreeItem() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class LeafLayerWrapper : public LayerWrapper
|
class LeafLayerWrapper : public LayerWrapper
|
||||||
|
@ -107,6 +111,9 @@ class LeafLayerWrapper : public LayerWrapper
|
||||||
LeafLayerWrapper(QJsonObject json, ElementManager *elementManager, FolderLayerWrapper*parent);
|
LeafLayerWrapper(QJsonObject json, ElementManager *elementManager, FolderLayerWrapper*parent);
|
||||||
QJsonObject toJson() const override;
|
QJsonObject toJson() const override;
|
||||||
void paint(QPainter* painter, QTransform transform = QTransform(), bool ignoreSelected = false) override;
|
void paint(QPainter* painter, QTransform transform = QTransform(), bool ignoreSelected = false) override;
|
||||||
|
void collectDownReachable(std::set<LayerWrapper*>& reachable) override;
|
||||||
|
QTreeWidgetItem* getQTreeItem() override;
|
||||||
|
void refreshTreeItem() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(LayerWrapper *)
|
Q_DECLARE_METATYPE(LayerWrapper *)
|
||||||
|
|
|
@ -60,13 +60,13 @@ void InfoDisplayWidget::generateLayerForm()
|
||||||
emit requireRefreshElementWidget();
|
emit requireRefreshElementWidget();
|
||||||
emit requireRefreshPreview();
|
emit requireRefreshPreview();
|
||||||
});
|
});
|
||||||
scaleX->setValidator(new QDoubleValidator(0.001, 1000, 4, this));
|
scaleX->setValidator(new QDoubleValidator(-1000, 1000, 4, this));
|
||||||
connect(scaleX, &QLineEdit::textChanged, [=](QString content) {
|
connect(scaleX, &QLineEdit::textChanged, [=](QString content) {
|
||||||
this->displayLayer->property.scale = {content.toDouble(), this->displayLayer->property.scale.y()};
|
this->displayLayer->property.scale = {content.toDouble(), this->displayLayer->property.scale.y()};
|
||||||
emit requireRefreshElementWidget();
|
emit requireRefreshElementWidget();
|
||||||
emit requireRefreshPreview();
|
emit requireRefreshPreview();
|
||||||
});
|
});
|
||||||
scaleY->setValidator(new QDoubleValidator(0.001, 1000, 4, this));
|
scaleY->setValidator(new QDoubleValidator(-1000, 1000, 4, this));
|
||||||
connect(scaleY, &QLineEdit::textChanged, [=](QString content) {
|
connect(scaleY, &QLineEdit::textChanged, [=](QString content) {
|
||||||
this->displayLayer->property.scale = {this->displayLayer->property.scale.x(), content.toDouble()};
|
this->displayLayer->property.scale = {this->displayLayer->property.scale.x(), content.toDouble()};
|
||||||
emit requireRefreshElementWidget();
|
emit requireRefreshElementWidget();
|
||||||
|
@ -102,7 +102,7 @@ void InfoDisplayWidget::generateLayerForm()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
connect(addStyleButton, &QPushButton::clicked, [&, leafP] {
|
connect(addStyleButton, &QPushButton::clicked, [&, leafP] {
|
||||||
auto* dialog = new LayerStyleDialog(leafP->styles);
|
auto* dialog = new LayerStyleDialog(leafP->styles, nullptr, this);
|
||||||
dialog->exec();
|
dialog->exec();
|
||||||
if (dialog->layerStyle)
|
if (dialog->layerStyle)
|
||||||
{
|
{
|
||||||
|
@ -113,7 +113,6 @@ void InfoDisplayWidget::generateLayerForm()
|
||||||
emit requireSelfRefresh();
|
emit requireSelfRefresh();
|
||||||
emit requireRefreshElementWidget();
|
emit requireRefreshElementWidget();
|
||||||
}
|
}
|
||||||
dialog->deleteLater();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,60 +124,7 @@ void InfoDisplayWidget::generateLayerForm()
|
||||||
header->setFlags(Qt::NoItemFlags);
|
header->setFlags(Qt::NoItemFlags);
|
||||||
styleList->addItem(header);
|
styleList->addItem(header);
|
||||||
styleList->setItemWidget(header, headerWidget);
|
styleList->setItemWidget(header, headerWidget);
|
||||||
//static vector<QString> styleNames = { "样例1", "样例2", "样例3" };
|
|
||||||
// auto createStyleItem = [this, styleList](int index) {
|
|
||||||
// QListWidgetItem* item = new QListWidgetItem;
|
|
||||||
// QWidget* w = new QWidget;
|
|
||||||
// item->setSizeHint(QSize(50, 40));
|
|
||||||
// QHBoxLayout* layout = new QHBoxLayout;
|
|
||||||
// QPushButton* deleteButton = new QPushButton(w);
|
|
||||||
// QPushButton* detailButton = new QPushButton(w);
|
|
||||||
// QLabel* name = new QLabel(w);
|
|
||||||
// name->setText(styleNames[index]);
|
|
||||||
// detailButton->setText("...");
|
|
||||||
// detailButton->setFixedSize(QSize(20, 20));
|
|
||||||
// deleteButton->setText("×");
|
|
||||||
// deleteButton->setFixedSize(QSize(20, 20));
|
|
||||||
// connect(detailButton, &QPushButton::clicked, [styleList, item, this, index]() {
|
|
||||||
// QDialog dlg(this);
|
|
||||||
// dlg.setWindowTitle("样式详情");
|
|
||||||
// dlg.resize(400, 200);
|
|
||||||
// QGridLayout *contentLayout = new QGridLayout(&dlg);
|
|
||||||
// QLineEdit* name = new QLineEdit(styleNames[index], &dlg);
|
|
||||||
// auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Save | QDialogButtonBox::Cancel);
|
|
||||||
// contentLayout->addWidget(buttonBox);
|
|
||||||
// connect(buttonBox, &QDialogButtonBox::accepted, &dlg, &QDialog::accept);
|
|
||||||
// connect(buttonBox, &QDialogButtonBox::rejected, &dlg, &QDialog::reject);
|
|
||||||
// bool updateStyle = dlg.exec();
|
|
||||||
// if (updateStyle) {
|
|
||||||
// styleNames[index] = name->text();
|
|
||||||
// qDebug() << name->text();
|
|
||||||
// // 在此处修改新样式信息至内存
|
|
||||||
// emit requireRefreshPreview();
|
|
||||||
// emit requireSelfRefresh();
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// connect(deleteButton, &QPushButton::clicked, [styleList,item,this]() {
|
|
||||||
// styleList->removeItemWidget(item);
|
|
||||||
// delete item;
|
|
||||||
// // 删除layer对应样式
|
|
||||||
// emit requireRefreshPreview();
|
|
||||||
// emit requireSelfRefresh();
|
|
||||||
// });
|
|
||||||
// layout->addWidget(name);
|
|
||||||
// layout->addWidget(detailButton);
|
|
||||||
// layout->addWidget(deleteButton);
|
|
||||||
// w->setLayout(layout);
|
|
||||||
// styleList->addItem(item);
|
|
||||||
// styleList->setItemWidget(item, w);
|
|
||||||
// };
|
|
||||||
// for (int i = 0; i < styleNames.size(); i++)
|
|
||||||
// createStyleItem(i);
|
|
||||||
|
|
||||||
/*if (leafP->styles.empty())
|
|
||||||
{
|
|
||||||
leafP->styles.push_back(std::shared_ptr<LayerStyle>(new StrokeElementLayerStyle()));
|
|
||||||
}*/
|
|
||||||
auto* styles = &leafP->styles;
|
auto* styles = &leafP->styles;
|
||||||
for (auto styleIterator = styles->begin(); styleIterator != styles->end(); ++styleIterator)
|
for (auto styleIterator = styles->begin(); styleIterator != styles->end(); ++styleIterator)
|
||||||
{
|
{
|
||||||
|
@ -200,7 +146,7 @@ void InfoDisplayWidget::generateLayerForm()
|
||||||
[this, styles, styleIterator]
|
[this, styles, styleIterator]
|
||||||
{
|
{
|
||||||
auto* dialog =
|
auto* dialog =
|
||||||
new LayerStyleDialog(*styles, styleIterator->second);
|
new LayerStyleDialog(*styles, styleIterator->second, this);
|
||||||
dialog->exec();
|
dialog->exec();
|
||||||
|
|
||||||
if (dialog->layerStyle)
|
if (dialog->layerStyle)
|
||||||
|
@ -212,7 +158,6 @@ void InfoDisplayWidget::generateLayerForm()
|
||||||
emit requireSelfRefresh();
|
emit requireSelfRefresh();
|
||||||
emit requireRefreshElementWidget();
|
emit requireRefreshElementWidget();
|
||||||
}
|
}
|
||||||
dialog->deleteLater();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(removeButton, &QPushButton::clicked, this,
|
connect(removeButton, &QPushButton::clicked, this,
|
||||||
|
|
|
@ -9,7 +9,7 @@ LayerTreeWidget::LayerTreeWidget(QWidget *parent)
|
||||||
this->selectedItem = nullptr;
|
this->selectedItem = nullptr;
|
||||||
this->copiedItem = nullptr;
|
this->copiedItem = nullptr;
|
||||||
this->setContextMenuPolicy(Qt::CustomContextMenu);
|
this->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
this->setHeaderLabel("Layer Content");
|
this->setColumnWidth(0, 240);
|
||||||
connect(this, &QTreeWidget::customContextMenuRequested, this, &LayerTreeWidget::popMenu);
|
connect(this, &QTreeWidget::customContextMenuRequested, this, &LayerTreeWidget::popMenu);
|
||||||
connect(this, &QTreeWidget::currentItemChanged, [=](QTreeWidgetItem *currentItem) {
|
connect(this, &QTreeWidget::currentItemChanged, [=](QTreeWidgetItem *currentItem) {
|
||||||
if (this->selectedItem != nullptr) {
|
if (this->selectedItem != nullptr) {
|
||||||
|
@ -50,7 +50,7 @@ void LayerTreeWidget::popMenu(const QPoint &pos)
|
||||||
if (layer != nullptr) {
|
if (layer != nullptr) {
|
||||||
if (typeid(*layer) == typeid(FolderLayerWrapper)) {
|
if (typeid(*layer) == typeid(FolderLayerWrapper)) {
|
||||||
menu.addAction(QString::fromLocal8Bit("创建子节点"), this, [this, layer]() {
|
menu.addAction(QString::fromLocal8Bit("创建子节点"), this, [this, layer]() {
|
||||||
auto dialog = new LayerCreateWidget(elementManager, this);
|
auto dialog = new LayerCreateWidget(elementManager, dynamic_cast<FolderLayerWrapper*>(layer), this);
|
||||||
connect(dialog, &LayerCreateWidget::LayerInfoReturned, this, [this, layer](QJsonObject jsonObj) {
|
connect(dialog, &LayerCreateWidget::LayerInfoReturned, this, [this, layer](QJsonObject jsonObj) {
|
||||||
auto folderLayer = dynamic_cast<FolderLayerWrapper*>(layer);
|
auto folderLayer = dynamic_cast<FolderLayerWrapper*>(layer);
|
||||||
LayerWrapper* newLayer;
|
LayerWrapper* newLayer;
|
||||||
|
@ -76,15 +76,18 @@ void LayerTreeWidget::popMenu(const QPoint &pos)
|
||||||
layer->getParent()->removeChild(layer);
|
layer->getParent()->removeChild(layer);
|
||||||
this->refresh();
|
this->refresh();
|
||||||
emit requireRefreshPreview();
|
emit requireRefreshPreview();
|
||||||
|
emit requireRefreshElementWidget();
|
||||||
});
|
});
|
||||||
menu.addAction(QString::fromLocal8Bit("重命名"), this, &LayerTreeWidget::onRenameEvent);
|
menu.addAction(QString::fromLocal8Bit("重命名"), this, &LayerTreeWidget::onRenameEvent);
|
||||||
menu.addAction(QString::fromLocal8Bit("ɾ³ý£¨±£Áô×ӽڵ㣩"), this, [this]() {
|
if(typeid(*layer) == typeid(FolderLayerWrapper))
|
||||||
auto layer = this->selectedItem->data(0, Qt::UserRole).value<LayerWrapper*>();
|
menu.addAction(QString::fromLocal8Bit("ɾ³ý£¨±£Áô×ӽڵ㣩"), this, [this]() {
|
||||||
layer->delSelf();
|
auto layer = this->selectedItem->data(0, Qt::UserRole).value<LayerWrapper*>();
|
||||||
layer->getParent()->removeChild(layer);
|
layer->delSelf();
|
||||||
this->refresh();
|
layer->getParent()->removeChild(layer);
|
||||||
emit requireRefreshPreview();
|
this->refresh();
|
||||||
});
|
emit requireRefreshPreview();
|
||||||
|
emit requireRefreshElementWidget();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if (typeid(*layer) == typeid(FolderLayerWrapper) && ((FolderLayerWrapper*)layer)->getReferencedBy() == -1) {
|
if (typeid(*layer) == typeid(FolderLayerWrapper) && ((FolderLayerWrapper*)layer)->getReferencedBy() == -1) {
|
||||||
menu.addAction(QString::fromLocal8Bit("创建组合元素"), this, [this]() {
|
menu.addAction(QString::fromLocal8Bit("创建组合元素"), this, [this]() {
|
||||||
|
@ -123,9 +126,5 @@ void LayerTreeWidget::onRenameEvent()
|
||||||
}
|
}
|
||||||
|
|
||||||
void LayerTreeWidget::refresh() {
|
void LayerTreeWidget::refresh() {
|
||||||
// if(this->root!=nullptr)
|
this->root->refreshTreeItem();
|
||||||
//{
|
|
||||||
// this->clear();
|
|
||||||
// this->addTopLevelItem(this->root->getQTreeItem());
|
|
||||||
//}
|
|
||||||
}
|
}
|
|
@ -99,7 +99,10 @@ FolderLayerWrapper* PaintingUtil::handleLayerWrapper(LayerWrapper* nowLayer, QTr
|
||||||
qDebug() << painterPath;
|
qDebug() << painterPath;
|
||||||
bound = painterPath.boundingRect();
|
bound = painterPath.boundingRect();
|
||||||
qDebug() << bound;
|
qDebug() << bound;
|
||||||
elementTrans.center = glm::vec2(
|
|
||||||
|
// TODO 改用矩阵
|
||||||
|
|
||||||
|
/* elementTrans.center = glm::vec2(
|
||||||
(2 * bound.center().x() - screenSize.width()) / screenSize.width(),
|
(2 * bound.center().x() - screenSize.width()) / screenSize.width(),
|
||||||
(2 * bound.center().y() - screenSize.height()) / screenSize.height()
|
(2 * bound.center().y() - screenSize.height()) / screenSize.height()
|
||||||
);
|
);
|
||||||
|
@ -114,7 +117,7 @@ FolderLayerWrapper* PaintingUtil::handleLayerWrapper(LayerWrapper* nowLayer, QTr
|
||||||
nowLayer->property.flipVertically
|
nowLayer->property.flipVertically
|
||||||
);
|
);
|
||||||
qDebug() << elementTrans.scale.x << elementTrans.scale.y;
|
qDebug() << elementTrans.scale.x << elementTrans.scale.y;
|
||||||
painting.addElement(element, elementTrans);
|
painting.addElement(element, elementTrans);*/
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ namespace Renderer
|
||||||
glm::vec3 Position;
|
glm::vec3 Position;
|
||||||
glm::vec3 Normal;
|
glm::vec3 Normal;
|
||||||
glm::vec2 TexCoords;
|
glm::vec2 TexCoords;
|
||||||
Vertex(const aiVector3D& position, const aiVector3D& Normal, const aiVector3D& TexCoords);
|
Vertex(const aiVector3D& position, const aiVector3D& normal, const aiVector3D& texCoords);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Texture
|
struct Texture
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include <ThirdPartyLib/qquick/qquicksvgparser_p.h>
|
#include <ThirdPartyLib/qquick/qquicksvgparser_p.h>
|
||||||
#include <util/PaintingUtil.h>
|
#include <util/PaintingUtil.h>
|
||||||
#include "Painting/MaterialStyleStroke.h"
|
#include "Painting/MaterialStyleStroke.h"
|
||||||
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
|
||||||
using namespace Renderer;
|
using namespace Renderer;
|
||||||
using std::vector;
|
using std::vector;
|
||||||
|
@ -32,14 +33,12 @@ Model::Model(QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram,
|
||||||
}
|
}
|
||||||
|
|
||||||
void Model::draw() {
|
void Model::draw() {
|
||||||
//shaderProgram->bind();
|
|
||||||
for (auto& mesh : meshes) {
|
for (auto& mesh : meshes) {
|
||||||
mesh->draw();
|
mesh->draw();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Model::drawShadow() {
|
void Model::drawShadow() {
|
||||||
//shaderProgram->bind();
|
|
||||||
for (auto& mesh : meshes) {
|
for (auto& mesh : meshes) {
|
||||||
mesh->drawShadow();
|
mesh->drawShadow();
|
||||||
}
|
}
|
||||||
|
@ -55,7 +54,7 @@ void Renderer::Model::loadModel(QString path)
|
||||||
const aiScene* scene = importer.ReadFile(modelFile.absoluteFilePath().toUtf8(), aiProcess_Triangulate);
|
const aiScene* scene = importer.ReadFile(modelFile.absoluteFilePath().toUtf8(), aiProcess_Triangulate);
|
||||||
if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode)
|
if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode)
|
||||||
{
|
{
|
||||||
qCritical() << "ERROR::ASSIMP::" << importer.GetErrorString() << endl;
|
qCritical() << "ERROR::ASSIMP::" << importer.GetErrorString();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
qDebug() << modelFile.absoluteFilePath() << "Loaded Successfully";
|
qDebug() << modelFile.absoluteFilePath() << "Loaded Successfully";
|
||||||
|
@ -63,9 +62,11 @@ void Renderer::Model::loadModel(QString path)
|
||||||
qDebug() << "NumMaterials: " << scene->mNumMaterials;
|
qDebug() << "NumMaterials: " << scene->mNumMaterials;
|
||||||
qDebug() << "NumTextures: " << scene->mNumTextures;
|
qDebug() << "NumTextures: " << scene->mNumTextures;
|
||||||
|
|
||||||
|
unloadModel();
|
||||||
|
|
||||||
|
|
||||||
if (QFile paintingConfigFile(directory.filePath(name + ".txt")); paintingConfigFile.open(QFile::ReadOnly | QIODevice::Text))
|
if (QFile paintingConfigFile(directory.filePath(name + ".txt")); paintingConfigFile.open(QFile::ReadOnly | QIODevice::Text))
|
||||||
{
|
{
|
||||||
paintingMap.clear();
|
|
||||||
QTextStream stream(&paintingConfigFile);
|
QTextStream stream(&paintingConfigFile);
|
||||||
while (!stream.atEnd())
|
while (!stream.atEnd())
|
||||||
{
|
{
|
||||||
|
@ -82,23 +83,36 @@ void Renderer::Model::loadModel(QString path)
|
||||||
qWarning() << "Painting Config Not Found!";
|
qWarning() << "Painting Config Not Found!";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
aiMatrix4x4 transform;
|
||||||
|
aiMatrix4x4::Scaling(aiVector3D(1 / 0.008), transform);
|
||||||
|
processNode(scene->mRootNode, scene, transform * scene->mRootNode->mTransformation);
|
||||||
|
AABB.clear();
|
||||||
|
AABB.emplace_back(minX, minY, minZ);
|
||||||
|
AABB.emplace_back(minX, minY, maxZ);
|
||||||
|
AABB.emplace_back(minX, maxY, minZ);
|
||||||
|
AABB.emplace_back(minX, maxY, maxZ);
|
||||||
|
AABB.emplace_back(maxX, minY, minZ);
|
||||||
|
AABB.emplace_back(maxX, minY, maxZ);
|
||||||
|
AABB.emplace_back(maxX, maxY, minZ);
|
||||||
|
AABB.emplace_back(maxX, maxY, maxZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::Model::unloadModel()
|
||||||
|
{
|
||||||
|
paintingMap.clear();
|
||||||
|
for (auto& i : paintingLoaded)
|
||||||
|
vtManager->deleteVirtualTexture(i.second);
|
||||||
|
paintingLoaded.clear();
|
||||||
|
texturesLoaded.clear();
|
||||||
|
meshes.clear();
|
||||||
|
|
||||||
minX = std::numeric_limits<float>::max();
|
minX = std::numeric_limits<float>::max();
|
||||||
maxX = std::numeric_limits<float>::min();
|
maxX = std::numeric_limits<float>::min();
|
||||||
minY = std::numeric_limits<float>::max();
|
minY = std::numeric_limits<float>::max();
|
||||||
maxY = std::numeric_limits<float>::min();
|
maxY = std::numeric_limits<float>::min();
|
||||||
minZ = std::numeric_limits<float>::max();
|
minZ = std::numeric_limits<float>::max();
|
||||||
maxZ = std::numeric_limits<float>::min();
|
maxZ = std::numeric_limits<float>::min();
|
||||||
aiMatrix4x4 transform;
|
|
||||||
aiMatrix4x4::Scaling(aiVector3D(1 / 0.008), transform);
|
|
||||||
processNode(scene->mRootNode, scene, transform * scene->mRootNode->mTransformation);
|
|
||||||
AABB.push_back(QVector3D(minX, minY, minZ));
|
|
||||||
AABB.push_back(QVector3D(minX, minY, maxZ));
|
|
||||||
AABB.push_back(QVector3D(minX, maxY, minZ));
|
|
||||||
AABB.push_back(QVector3D(minX, maxY, maxZ));
|
|
||||||
AABB.push_back(QVector3D(maxX, minY, minZ));
|
|
||||||
AABB.push_back(QVector3D(maxX, minY, maxZ));
|
|
||||||
AABB.push_back(QVector3D(maxX, maxY, minZ));
|
|
||||||
AABB.push_back(QVector3D(maxX, maxY, maxZ));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Model::processNode(aiNode* node, const aiScene* scene, aiMatrix4x4 mat4)
|
void Model::processNode(aiNode* node, const aiScene* scene, aiMatrix4x4 mat4)
|
||||||
|
@ -267,13 +281,13 @@ GLuint Renderer::Model::loadPainting(std::string path)
|
||||||
|
|
||||||
if (path == "0.json")
|
if (path == "0.json")
|
||||||
{
|
{
|
||||||
painting.addElement(*element[0], ElementTransform{ glm::vec2(-0.45,-0.45), glm::vec2(0.5,0.5) / 2.f, 0, glm::bvec2(false), 0 });
|
//painting.addElement(*element[0], ElementTransform{ glm::vec2(-0.45,-0.45), glm::vec2(0.5,0.5) / 2.f, 0, glm::bvec2(false), 0 });
|
||||||
painting.addElement(*element[1], ElementTransform{ glm::vec2(-0.45, 0.45), glm::vec2(0.5,0.5) / 2.f, 0, glm::bvec2(false), 0 });
|
//painting.addElement(*element[1], ElementTransform{ glm::vec2(-0.45, 0.45), glm::vec2(0.5,0.5) / 2.f, 0, glm::bvec2(false), 0 });
|
||||||
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.addElement(*element[2], ElementTransform{ glm::vec2(0.50,-0.45), glm::vec2(0.6,0.7) / 2.f, 0, glm::bvec2(false), 0 });
|
||||||
}
|
}
|
||||||
else if (path == "1.json")
|
else if (path == "1.json")
|
||||||
{
|
{
|
||||||
painting.backgroundColor = QColor(196, 81, 35);
|
//painting.backgroundColor = QColor(196, 81, 35);
|
||||||
float widths[] = { 0.22, 0.22 * 0.25 / 0.15, 0.22 * 0.25 / 0.15 };
|
float widths[] = { 0.22, 0.22 * 0.25 / 0.15, 0.22 * 0.25 / 0.15 };
|
||||||
QPainterPath painterPaths[6];
|
QPainterPath painterPaths[6];
|
||||||
for (int i = 0; i < 6; i++)
|
for (int i = 0; i < 6; i++)
|
||||||
|
@ -309,14 +323,39 @@ GLuint Renderer::Model::loadPainting(std::string path)
|
||||||
std::make_shared<StyleStrokeRadialGradient>(widths[1], StrokeType::kRightSide),
|
std::make_shared<StyleStrokeRadialGradient>(widths[1], StrokeType::kRightSide),
|
||||||
std::make_shared<StyleStrokeRadialGradient>(widths[2], StrokeType::kLeftSide),
|
std::make_shared<StyleStrokeRadialGradient>(widths[2], StrokeType::kLeftSide),
|
||||||
};
|
};
|
||||||
vector<std::shared_ptr<Element>> element = {
|
std::map<float, Material> materialMap = {
|
||||||
std::make_shared<Element>(Element{ contours[0].first, style[0], contours[0].second}),
|
{0.09, Material{QColor(255,255,255),0,0.8}},
|
||||||
std::make_shared<Element>(Element{ contours[1].first, style[1], contours[1].second}),
|
{0.63, Material{QColor(165,176,207),0,0.8}},
|
||||||
std::make_shared<Element>(Element{ contours[2].first, style[2], contours[2].second}),
|
{1.00, Material{QColor(58,64,151),0,0.8}}
|
||||||
};
|
};
|
||||||
painting.addElement(*element[0], ElementTransform{ glm::vec2(-0.45,0.45), glm::vec2(0.25), 0, glm::bvec2(false), 0 });
|
vector<std::shared_ptr<BaseElement>> element = {
|
||||||
painting.addElement(*element[1], ElementTransform{ glm::vec2(-0.535,0.33), glm::vec2(0.15), 0, glm::bvec2(false), 0 });
|
std::make_shared<BaseElement>(contours[0].first, std::make_shared<MaterialStyleStroke>(
|
||||||
painting.addElement(*element[2], ElementTransform{ glm::vec2(-0.535,0.23), glm::vec2(0.15), 0, glm::bvec2(false), 0 });
|
widths[0], StrokeType::kLeftSide, StrokeEndType::kFlat, std::make_shared<StrokeRadialGradient>(materialMap, false))),
|
||||||
|
std::make_shared<BaseElement>(contours[1].first, std::make_shared<MaterialStyleStroke>(
|
||||||
|
widths[1], StrokeType::kRightSide, StrokeEndType::kFlat, std::make_shared<StrokeRadialGradient>(materialMap, false))),
|
||||||
|
std::make_shared<BaseElement>(contours[2].first, std::make_shared<MaterialStyleStroke>(
|
||||||
|
widths[2], StrokeType::kLeftSide, StrokeEndType::kFlat, std::make_shared<StrokeRadialGradient>(materialMap, false))),
|
||||||
|
};
|
||||||
|
|
||||||
|
QTransform trans = QTransform::fromScale(0.3, 0.3).inverted();
|
||||||
|
glm::mat3x2 mat(trans.m11(), trans.m12(), trans.m21(), trans.m22(), trans.m31(), trans.m32());
|
||||||
|
|
||||||
|
trans = QTransform::fromTranslate(0.5, 0).scale(0.3, 0.3).inverted();
|
||||||
|
glm::mat3x2 mat2(trans.m11(), trans.m12(), trans.m21(), trans.m22(), trans.m31(), trans.m32());
|
||||||
|
//mat = glm::mat3x2(11, 22, 33, 44, 55, 66);
|
||||||
|
//mat2 = glm::mat3x2(1, 2, 3, 4, 5, 6);
|
||||||
|
|
||||||
|
qDebug() << std::format("\n{} {} {}\n {} {} {}\n{} {} {}",
|
||||||
|
trans.m11(), trans.m21(), trans.m31(),
|
||||||
|
trans.m12(), trans.m22(), trans.m32(),
|
||||||
|
trans.m13(), trans.m23(), trans.m33()).c_str();
|
||||||
|
|
||||||
|
//painting.addElement(*element[0], ElementTransform{ glm::vec4(-1,-1,1,1), mat, 0});
|
||||||
|
painting.addElement(*element[1], ElementTransform{ glm::vec4(-1,-1,0,1), mat, 0 });
|
||||||
|
painting.addElement(*element[2], ElementTransform{ glm::vec4(0,-1,1,1), mat2, 0 });
|
||||||
|
//painting.addElement(*element[0], ElementTransform{ glm::vec2(-0.45,0.45), glm::vec2(0.25), 0, glm::bvec2(false), 0 });
|
||||||
|
//painting.addElement(*element[1], ElementTransform{ glm::vec2(-0.535,0.33), glm::vec2(0.15), 0, glm::bvec2(false), 0 });
|
||||||
|
//painting.addElement(*element[2], ElementTransform{ glm::vec2(-0.535,0.23), glm::vec2(0.15), 0, glm::bvec2(false), 0 });
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -324,7 +363,7 @@ GLuint Renderer::Model::loadPainting(std::string path)
|
||||||
{
|
{
|
||||||
float x = (float)rand() / RAND_MAX * 2 - 1;
|
float x = (float)rand() / RAND_MAX * 2 - 1;
|
||||||
float y = (float)rand() / RAND_MAX * 2 - 1;
|
float y = (float)rand() / RAND_MAX * 2 - 1;
|
||||||
painting.addElement(*element[i % 3], ElementTransform{ glm::vec2(x,y), glm::vec2(0.025), (float)rand() / RAND_MAX * 360, glm::bvec2(false), 0 });
|
//painting.addElement(*element[i % 3], ElementTransform{ glm::vec2(x,y), glm::vec2(0.025), (float)rand() / RAND_MAX * 360, glm::bvec2(false), 0 });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ namespace Renderer
|
||||||
void draw();
|
void draw();
|
||||||
void drawShadow();
|
void drawShadow();
|
||||||
void loadModel(QString path);
|
void loadModel(QString path);
|
||||||
|
void unloadModel();
|
||||||
Model(QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* paintingProgram, QOpenGLShaderProgram* shadowProgram, VirtualTextureManager* vtManager);
|
Model(QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* paintingProgram, QOpenGLShaderProgram* shadowProgram, VirtualTextureManager* vtManager);
|
||||||
private:
|
private:
|
||||||
QOpenGLContext* context = nullptr;
|
QOpenGLContext* context = nullptr;
|
||||||
|
@ -25,8 +26,8 @@ namespace Renderer
|
||||||
VirtualTextureManager* vtManager = nullptr;
|
VirtualTextureManager* vtManager = nullptr;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param key BaseColor路径
|
* @brief key BaseColor路径 \n
|
||||||
* @param value json路径, 纹理坐标
|
* value json路径, 纹理坐标
|
||||||
*/
|
*/
|
||||||
std::unordered_map<std::string, std::tuple<std::string, glm::vec2, glm::vec2>> paintingMap;
|
std::unordered_map<std::string, std::tuple<std::string, glm::vec2, glm::vec2>> paintingMap;
|
||||||
std::unordered_map<std::string, GLuint> paintingLoaded;
|
std::unordered_map<std::string, GLuint> paintingLoaded;
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
#include "Element.h"
|
#include "Element.h"
|
||||||
|
|
||||||
void Renderer::ElementTransform::applyTransformStyle(const TransformStyle& t)
|
//void Renderer::ElementTransform::applyTransformStyle(const TransformStyle& t)
|
||||||
{
|
//{
|
||||||
center += t.translation;
|
// /*center += t.translation;
|
||||||
scale *= t.scale;
|
// scale *= t.scale;
|
||||||
rotation += t.rotation;
|
// rotation += t.rotation;
|
||||||
flip ^= t.flip;
|
// flip ^= t.flip;*/
|
||||||
}
|
//}
|
||||||
|
//
|
||||||
Renderer::ElementTransform Renderer::ElementTransform::appliedTransformStyle(const TransformStyle& t) const
|
//Renderer::ElementTransform Renderer::ElementTransform::appliedTransformStyle(const TransformStyle& t) const
|
||||||
{
|
//{
|
||||||
ElementTransform result = *this;
|
// ElementTransform result = *this;
|
||||||
result.applyTransformStyle(t);
|
// result.applyTransformStyle(t);
|
||||||
return result;
|
// return result;
|
||||||
}
|
//}
|
||||||
|
|
|
@ -18,14 +18,15 @@ namespace Renderer
|
||||||
|
|
||||||
struct ElementTransform
|
struct ElementTransform
|
||||||
{
|
{
|
||||||
glm::vec2 center;
|
//glm::vec2 center;
|
||||||
//glm::vec2 size;
|
//glm::vec2 scale; /// 相对于画布
|
||||||
glm::vec2 scale; /// 相对于画布
|
//float rotation; /// 角度制
|
||||||
float rotation; /// 角度制
|
//glm::bvec2 flip;
|
||||||
glm::bvec2 flip;
|
glm::vec4 bound; /// 包围盒,不影响变换
|
||||||
|
glm::mat3x2 transform; /// 逆变换
|
||||||
GLuint zIndex;
|
GLuint zIndex;
|
||||||
|
|
||||||
void applyTransformStyle(const TransformStyle& t);
|
//void applyTransformStyle(const TransformStyle& t);
|
||||||
ElementTransform appliedTransformStyle(const TransformStyle& t) const;
|
//ElementTransform appliedTransformStyle(const TransformStyle& t) const;
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -53,87 +53,40 @@ void Renderer::Painting::addElement(ElementWithTransform elementWithTransform)
|
||||||
elementPool.insert({ element, 0 });
|
elementPool.insert({ element, 0 });
|
||||||
}
|
}
|
||||||
elements.push_back(elementWithTransform);
|
elements.push_back(elementWithTransform);
|
||||||
|
elementTransformPool.emplace(elementWithTransform.transform.transform, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::Painting::addElement(const Element& element, const ElementTransform& transform)
|
void Renderer::Painting::addElement(const BaseElement& element, const ElementTransform& transform)
|
||||||
{
|
{
|
||||||
auto contour = element.contour;
|
addElement({ element , transform });
|
||||||
auto it = elementStyleMap.find(element.style);
|
|
||||||
if (it == elementStyleMap.end())
|
|
||||||
{
|
|
||||||
std::vector<BaseStyle> baseStyles;
|
|
||||||
for (auto& style : element.style->toBaseStyles())
|
|
||||||
{
|
|
||||||
auto [iter, _] = styleSet.insert(style.material);
|
|
||||||
baseStyles.push_back(BaseStyle{ style.transform, *iter });
|
|
||||||
}
|
|
||||||
it = elementStyleMap.insert({ element.style, baseStyles }).first;
|
|
||||||
}
|
|
||||||
for (int i = 0; i < it->second.size(); i++)
|
|
||||||
{
|
|
||||||
auto& style = it->second[i];
|
|
||||||
ElementTransform trans = transform;
|
|
||||||
trans.applyTransformStyle(*style.transform);
|
|
||||||
trans.zIndex = trans.zIndex * 10 + i;
|
|
||||||
|
|
||||||
addElement(ElementWithTransform{ BaseElement{element.contour, style.material, element.ratio}, trans });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Renderer::BaseTransform::BaseTransform(ElementTransform t)
|
BvhTreeData Painting::encodeElementLeaf(const ElementWithTransform& e)
|
||||||
: bound(glm::vec4(t.center - t.scale, t.center + t.scale))
|
|
||||||
, rotation(t.rotation)
|
|
||||||
, flip(t.flip)
|
|
||||||
, zIndex(t.zIndex)
|
|
||||||
{
|
{
|
||||||
}
|
QVector4D bound(e.transform.bound.x, e.transform.bound.y, e.transform.bound.z, e.transform.bound.w);
|
||||||
|
GLuint rightSon = elementPool[e.element] + (e.transform.zIndex << 18);
|
||||||
void Renderer::Painting::addElement(std::shared_ptr<Element> element, QVector4D bound, float rotation, int zIndex)
|
return { bound, elementTransformPool[e.transform.transform], rightSon };
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
BvhTreeData Painting::encodeElementLeaf(ElementWithTransform e)
|
|
||||||
{
|
|
||||||
glm::vec4 bound;
|
|
||||||
switch (e.element.style->type())
|
|
||||||
{
|
|
||||||
case MaterialStyleType::kStroke:
|
|
||||||
{
|
|
||||||
auto w = std::static_pointer_cast<MaterialStyleStroke>(e.element.style)->getHalfWidth();
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
case MaterialStyleType::kFill:
|
|
||||||
{
|
|
||||||
bound = glm::vec4(e.transform.center - e.transform.scale, e.transform.center + e.transform.scale);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Painting::generateBuffers(QOpenGLFunctions_4_5_Core* glFunc)
|
void Painting::generateBuffers(QOpenGLFunctions_4_5_Core* glFunc)
|
||||||
{
|
{
|
||||||
qDebug() << "Element Count: " << elementPool.size();
|
qDebug() << "Element Count: " << elementPool.size();
|
||||||
qDebug() << "Coutour Count: " << contourPool.size();
|
qDebug() << "Contour Count: " << contourPool.size();
|
||||||
qDebug() << " Style Count: " << stylePool.size();
|
qDebug() << " Style Count: " << stylePool.size();
|
||||||
|
|
||||||
bvhChildren.clear();
|
bvhChildren.clear();
|
||||||
bvhBounds.clear();
|
bvhBounds.clear();
|
||||||
|
elementTransform.clear();
|
||||||
elementOffsets.clear();
|
elementOffsets.clear();
|
||||||
elementIndex.clear();
|
elementIndex.clear();
|
||||||
elementData.clear();
|
elementData.clear();
|
||||||
|
|
||||||
for (int index = 0; auto & i : elementPool)
|
for (int index = 0; auto & i : elementPool)
|
||||||
{
|
|
||||||
i.second = index++;
|
i.second = index++;
|
||||||
}
|
for (int index = 0; auto & i : elementTransformPool)
|
||||||
|
i.second = index++;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
std::vector<BvhTreeData> rootBvhTreeData;
|
std::vector<BvhTreeData> rootBvhTreeData;
|
||||||
for (auto& i : elements)
|
for (auto& i : elements)
|
||||||
|
@ -162,30 +115,35 @@ void Painting::generateBuffers(QOpenGLFunctions_4_5_Core* glFunc)
|
||||||
elementData.insert(elementData.end(), encodedStyle.begin(), encodedStyle.end());
|
elementData.insert(elementData.end(), encodedStyle.begin(), encodedStyle.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (auto & i : elementTransformPool)
|
||||||
|
elementTransform.emplace_back(i.first);
|
||||||
|
|
||||||
for (auto& i : elementPool)
|
for (auto& i : elementPool)
|
||||||
{
|
{
|
||||||
//qDebug() <<"element:" << i.second;
|
//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;
|
//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()}];
|
auto& contourBuffer = contourPool[{i.first.contour, i.first.style->type()}];
|
||||||
elementOffsets.push_back({ contourBuffer.bvhOffset, stylePool[i.first.style], contourBuffer.pointsOffset, contourBuffer.linesOffset, glm::floatBitsToUint(i.first.ratio) });
|
elementOffsets.push_back({ contourBuffer.bvhOffset, stylePool[i.first.style], contourBuffer.pointsOffset, contourBuffer.linesOffset });
|
||||||
//std::cout << std::format("{} {} {} {}\n", contourBuffer->bvhOffset, stylePool[i.first->style], contourBuffer->pointsOffset, contourBuffer->linesOffset);
|
//std::cout << std::format("{} {} {} {}\n", contourBuffer->bvhOffset, stylePool[i.first->style], contourBuffer->pointsOffset, contourBuffer->linesOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
glFunc->glCreateBuffers(6, buffers.data());
|
glFunc->glCreateBuffers(7, buffers.data());
|
||||||
GLuint& bvhSSBO = buffers[0];
|
GLuint& bvhSSBO = buffers[0];
|
||||||
GLuint& bvhBoundSSBO = buffers[1];
|
GLuint& bvhBoundSSBO = buffers[1];
|
||||||
GLuint& elementOffsetSSBO = buffers[2];
|
GLuint& elementTransformSSBO = buffers[2];
|
||||||
GLuint& elementIndexSSBO = buffers[3];
|
GLuint& elementOffsetSSBO = buffers[3];
|
||||||
GLuint& elementDataSSBO = buffers[4];
|
GLuint& elementIndexSSBO = buffers[4];
|
||||||
GLuint& backgroundColorUBO = buffers[5];
|
GLuint& elementDataSSBO = buffers[5];
|
||||||
|
GLuint& backgroundColorUBO = buffers[6];
|
||||||
|
|
||||||
glFunc->glNamedBufferData(buffers[0], bvhChildren.size() * sizeof(bvhChildren[0]), bvhChildren.data(), GL_STATIC_READ);
|
glFunc->glNamedBufferData(buffers[0], bvhChildren.size() * sizeof(bvhChildren[0]), bvhChildren.data(), GL_STATIC_READ);
|
||||||
glFunc->glNamedBufferData(buffers[1], bvhBounds.size() * sizeof(bvhBounds[0]), bvhBounds.data(), GL_STATIC_READ);
|
glFunc->glNamedBufferData(buffers[1], bvhBounds.size() * sizeof(bvhBounds[0]), bvhBounds.data(), GL_STATIC_READ);
|
||||||
glFunc->glNamedBufferData(buffers[2], elementOffsets.size() * sizeof(elementOffsets[0]), elementOffsets.data(), GL_STATIC_READ);
|
glFunc->glNamedBufferData(buffers[2], elementTransform.size() * sizeof(elementTransform[0]), elementTransform.data(), GL_STATIC_READ);
|
||||||
glFunc->glNamedBufferData(buffers[3], elementIndex.size() * sizeof(elementIndex[0]), elementIndex.data(), GL_STATIC_READ);
|
glFunc->glNamedBufferData(buffers[3], elementOffsets.size() * sizeof(elementOffsets[0]), elementOffsets.data(), GL_STATIC_READ);
|
||||||
glFunc->glNamedBufferData(buffers[4], elementData.size() * sizeof(elementData[0]), elementData.data(), GL_STATIC_READ);
|
glFunc->glNamedBufferData(buffers[4], elementIndex.size() * sizeof(elementIndex[0]), elementIndex.data(), GL_STATIC_READ);
|
||||||
|
glFunc->glNamedBufferData(buffers[5], elementData.size() * sizeof(elementData[0]), elementData.data(), GL_STATIC_READ);
|
||||||
glm::vec3 color(backgroundColor.redF(), backgroundColor.greenF(), backgroundColor.blueF());
|
glm::vec3 color(backgroundColor.redF(), backgroundColor.greenF(), backgroundColor.blueF());
|
||||||
glFunc->glNamedBufferData(buffers[5], sizeof(glm::vec3), &color, GL_STATIC_READ);
|
glFunc->glNamedBufferData(buffers[6], sizeof(glm::vec3), &color, GL_STATIC_READ);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLuint Renderer::Painting::getElementCount()
|
GLuint Renderer::Painting::getElementCount()
|
||||||
|
@ -223,3 +181,17 @@ bool Renderer::Painting::CompareMaterialStyle::operator()(const std::shared_ptr<
|
||||||
else
|
else
|
||||||
return left < right;
|
return left < right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::size_t Renderer::Painting::HashMat3x2::operator()(const glm::mat3x2& mat) const
|
||||||
|
{
|
||||||
|
std::size_t result = 0;
|
||||||
|
constexpr long long P = 998244353;
|
||||||
|
long long base = 1;
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
for (int j = 0; j < 2; j++)
|
||||||
|
{
|
||||||
|
result += base * mat[i][j];
|
||||||
|
base *= P;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
|
@ -15,24 +15,13 @@ namespace Renderer
|
||||||
{
|
{
|
||||||
std::shared_ptr<Contour> contour;
|
std::shared_ptr<Contour> contour;
|
||||||
std::shared_ptr<MaterialStyle> style;
|
std::shared_ptr<MaterialStyle> style;
|
||||||
float ratio; /// ¿í¸ß±È
|
|
||||||
bool operator<(const BaseElement& e) const;
|
bool operator<(const BaseElement& e) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BaseTransform
|
|
||||||
{
|
|
||||||
glm::vec4 bound;
|
|
||||||
float rotation;
|
|
||||||
glm::bvec2 flip;
|
|
||||||
GLuint zIndex;
|
|
||||||
BaseTransform(ElementTransform t);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ElementWithTransform
|
struct ElementWithTransform
|
||||||
{
|
{
|
||||||
BaseElement element;
|
BaseElement element;
|
||||||
ElementTransform transform;
|
ElementTransform transform;
|
||||||
//BaseTransform transform;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ContourBuffer
|
struct ContourBuffer
|
||||||
|
@ -52,7 +41,6 @@ namespace Renderer
|
||||||
GLuint styleOffset;
|
GLuint styleOffset;
|
||||||
GLuint pointsOffset;
|
GLuint pointsOffset;
|
||||||
GLuint linesOffset;
|
GLuint linesOffset;
|
||||||
GLuint ratio;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Painting
|
class Painting
|
||||||
|
@ -60,16 +48,16 @@ namespace Renderer
|
||||||
public:
|
public:
|
||||||
std::vector<GLuint> bvhChildren;
|
std::vector<GLuint> bvhChildren;
|
||||||
std::vector<QVector4D> bvhBounds;
|
std::vector<QVector4D> bvhBounds;
|
||||||
|
std::vector<glm::mat3x2> elementTransform;
|
||||||
std::vector<ElementOffset> elementOffsets;
|
std::vector<ElementOffset> elementOffsets;
|
||||||
std::vector<GLuint> elementIndex;
|
std::vector<GLuint> elementIndex;
|
||||||
std::vector<GLfloat> elementData;
|
std::vector<GLfloat> elementData;
|
||||||
int paintingId = 0;
|
int paintingId = 0;
|
||||||
std::array<GLuint, 6> buffers;
|
std::array<GLuint, 7> buffers;
|
||||||
QColor backgroundColor;
|
QColor backgroundColor;
|
||||||
|
|
||||||
Painting(QColor backgroundColor = Qt::white);
|
Painting(QColor backgroundColor = Qt::white);
|
||||||
void addElement(const Element& element, const ElementTransform& transform);
|
void addElement(const BaseElement& element, const ElementTransform& transform);
|
||||||
void addElement(std::shared_ptr<Element> element, QVector4D bound, float rotation, int zIndex);
|
|
||||||
void generateBuffers(QOpenGLFunctions_4_5_Core* glFunc);
|
void generateBuffers(QOpenGLFunctions_4_5_Core* glFunc);
|
||||||
GLuint getElementCount();
|
GLuint getElementCount();
|
||||||
private:
|
private:
|
||||||
|
@ -77,14 +65,15 @@ namespace Renderer
|
||||||
std::unordered_map<std::tuple<std::shared_ptr<Contour>, MaterialStyleType>, ContourBuffer, ContourHash> contourPool;
|
std::unordered_map<std::tuple<std::shared_ptr<Contour>, MaterialStyleType>, ContourBuffer, ContourHash> contourPool;
|
||||||
struct CompareMaterialStyle { bool operator()(const std::shared_ptr<MaterialStyle>&, const std::shared_ptr<MaterialStyle>&) const; };
|
struct CompareMaterialStyle { bool operator()(const std::shared_ptr<MaterialStyle>&, const std::shared_ptr<MaterialStyle>&) const; };
|
||||||
std::set<std::shared_ptr<MaterialStyle>, CompareMaterialStyle> styleSet;
|
std::set<std::shared_ptr<MaterialStyle>, CompareMaterialStyle> styleSet;
|
||||||
std::unordered_map<std::shared_ptr<ElementStyle>, std::vector<BaseStyle>> elementStyleMap;
|
|
||||||
std::unordered_map<std::shared_ptr<MaterialStyle>, GLuint> stylePool;
|
std::unordered_map<std::shared_ptr<MaterialStyle>, GLuint> stylePool;
|
||||||
|
struct HashMat3x2 { std::size_t operator()(const glm::mat3x2&) const; };
|
||||||
|
std::unordered_map<glm::mat3x2, GLuint, HashMat3x2> elementTransformPool;
|
||||||
std::map<BaseElement, GLuint> elementPool;
|
std::map<BaseElement, GLuint> elementPool;
|
||||||
std::vector<ElementWithTransform> elements;
|
std::vector<ElementWithTransform> elements;
|
||||||
|
|
||||||
void addElement(ElementWithTransform element);
|
void addElement(ElementWithTransform element);
|
||||||
void insertContourBuffer(ContourBuffer& buffer);
|
void insertContourBuffer(ContourBuffer& buffer);
|
||||||
BvhTreeData encodeElementLeaf(ElementWithTransform e);
|
BvhTreeData encodeElementLeaf(const ElementWithTransform& e);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -88,13 +88,23 @@ QRectF calcBoundingRect(const QPainterPath& path, const std::vector<BaseStyle>&
|
||||||
{
|
{
|
||||||
QRectF bound = path.boundingRect();
|
QRectF bound = path.boundingRect();
|
||||||
|
|
||||||
ElementTransform originTransform{ glm::vec2(bound.center().x(), bound.center().y()), glm::vec2(bound.width(), bound.height()), 0, glm::bvec2(false), 0 };
|
//ElementTransform originTransform{ glm::vec2(bound.center().x(), bound.center().y()), glm::vec2(bound.width(), bound.height()), 0, glm::bvec2(false), 0 };
|
||||||
|
|
||||||
glm::vec2 leftTop(std::numeric_limits<float>::max()), rightBottom(std::numeric_limits<float>::min());
|
glm::vec2 leftTop(std::numeric_limits<float>::max()), rightBottom(std::numeric_limits<float>::min());
|
||||||
|
|
||||||
for (auto& baseStyle : styles)
|
for (auto& baseStyle : styles)
|
||||||
{
|
{
|
||||||
BaseTransform transform(originTransform.appliedTransformStyle(*baseStyle.transform));
|
struct BaseTransform
|
||||||
|
{
|
||||||
|
glm::vec4 bound;
|
||||||
|
float rotation = 0;
|
||||||
|
glm::bvec2 flip = glm::bvec2(false);
|
||||||
|
GLuint zIndex = 0;
|
||||||
|
};
|
||||||
|
//BaseTransform transform(originTransform.appliedTransformStyle(*baseStyle.transform));
|
||||||
|
glm::vec2 center(bound.center().x(), bound.center().y());
|
||||||
|
glm::vec2 scale(bound.width(), bound.height());
|
||||||
|
BaseTransform transform{ glm::vec4(center - scale, center + scale) };
|
||||||
if (baseStyle.material->type() == MaterialStyleType::kStroke)
|
if (baseStyle.material->type() == MaterialStyleType::kStroke)
|
||||||
{
|
{
|
||||||
float halfWidth = std::static_pointer_cast<MaterialStyleStroke>(baseStyle.material)->getHalfWidth();
|
float halfWidth = std::static_pointer_cast<MaterialStyleStroke>(baseStyle.material)->getHalfWidth();
|
||||||
|
|
|
@ -13,6 +13,7 @@ namespace Renderer
|
||||||
~RendererWidget();
|
~RendererWidget();
|
||||||
public slots:
|
public slots:
|
||||||
void currentTabChanged(int index);
|
void currentTabChanged(int index);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::RendererWidgetClass ui;
|
Ui::RendererWidgetClass ui;
|
||||||
};
|
};
|
||||||
|
|
|
@ -124,9 +124,9 @@ std::uint16_t Renderer::VirtualTextureManager::createVirtualTexture(Painting pai
|
||||||
glMain->TextureParameteri(metallicRoughness, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
glMain->TextureParameteri(metallicRoughness, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
glMain->TextureStorage2D(metallicRoughness, levels, GL_RG8, GLsizei(textureSize), GLsizei(textureSize));
|
glMain->TextureStorage2D(metallicRoughness, levels, GL_RG8, GLsizei(textureSize), GLsizei(textureSize));
|
||||||
|
|
||||||
for (int i = 0; i < 5; i++)
|
for (int i = 0; i < 6; i++)
|
||||||
glMain->BindBufferBase(GL_SHADER_STORAGE_BUFFER, i, painting.buffers[i]);
|
glMain->BindBufferBase(GL_SHADER_STORAGE_BUFFER, i, painting.buffers[i]);
|
||||||
glMain->BindBufferBase(GL_UNIFORM_BUFFER, 1, painting.buffers[5]);
|
glMain->BindBufferBase(GL_UNIFORM_BUFFER, 1, painting.buffers[6]);
|
||||||
|
|
||||||
for (auto level = levels - 1; level < levels; ++level)
|
for (auto level = levels - 1; level < levels; ++level)
|
||||||
{
|
{
|
||||||
|
@ -152,8 +152,28 @@ std::uint16_t Renderer::VirtualTextureManager::createVirtualTexture(Painting pai
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
paintings.emplace_back(baseColor, metallicRoughness, painting.buffers);
|
if (const auto it = std::find_if(paintings.begin(), paintings.end(), [](const PaintingHandle& i) { return i.baseColor == 0; });
|
||||||
return paintings.size();
|
it != paintings.end())
|
||||||
|
{
|
||||||
|
*it = { baseColor, metallicRoughness, painting.buffers };
|
||||||
|
return it - paintings.begin() + 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
paintings.emplace_back(baseColor, metallicRoughness, painting.buffers);
|
||||||
|
return paintings.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::VirtualTextureManager::deleteVirtualTexture(std::uint16_t id)
|
||||||
|
{
|
||||||
|
auto& painting = getPaintingHandle(id);
|
||||||
|
glMain->DeleteTextures(2, (GLuint*)&painting);
|
||||||
|
glMain->DeleteBuffers(7, painting.buffers.data());
|
||||||
|
painting.baseColor = 0;
|
||||||
|
painting.metallicRoughness = 0;
|
||||||
|
painting.buffers.fill(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Renderer::PaintingHandle& Renderer::VirtualTextureManager::getPaintingHandle(std::uint16_t id)
|
Renderer::PaintingHandle& Renderer::VirtualTextureManager::getPaintingHandle(std::uint16_t id)
|
||||||
|
@ -189,9 +209,9 @@ void Renderer::VirtualTextureManager::pageCommitmentById(const glm::u16vec2& pag
|
||||||
if (commit)
|
if (commit)
|
||||||
{
|
{
|
||||||
program.bind();
|
program.bind();
|
||||||
for (int i = 0; i < 5; i++)
|
for (int i = 0; i < 6; i++)
|
||||||
gl->BindBufferBase(GL_SHADER_STORAGE_BUFFER, i, painting.buffers[i]);
|
gl->BindBufferBase(GL_SHADER_STORAGE_BUFFER, i, painting.buffers[i]);
|
||||||
glMain->BindBufferBase(GL_UNIFORM_BUFFER, 1, painting.buffers[5]);
|
glMain->BindBufferBase(GL_UNIFORM_BUFFER, 1, painting.buffers[6]);
|
||||||
gl->Uniform2i(gl->GetUniformLocation(program.programId(), "pixelOffset"), static_cast<GLsizei>(pageSize) * page.x, static_cast<GLsizei>(pageSize) * page.y);
|
gl->Uniform2i(gl->GetUniformLocation(program.programId(), "pixelOffset"), static_cast<GLsizei>(pageSize) * page.x, static_cast<GLsizei>(pageSize) * page.y);
|
||||||
gl->BindImageTexture(0, painting.baseColor, level, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8);
|
gl->BindImageTexture(0, painting.baseColor, level, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8);
|
||||||
gl->BindImageTexture(1, painting.metallicRoughness, level, GL_FALSE, 0, GL_READ_WRITE, GL_RG8);
|
gl->BindImageTexture(1, painting.metallicRoughness, level, GL_FALSE, 0, GL_READ_WRITE, GL_RG8);
|
||||||
|
|
|
@ -15,7 +15,7 @@ namespace Renderer
|
||||||
{
|
{
|
||||||
GLuint baseColor;
|
GLuint baseColor;
|
||||||
GLuint metallicRoughness;
|
GLuint metallicRoughness;
|
||||||
std::array<GLuint, 6> buffers;
|
std::array<GLuint, 7> buffers;
|
||||||
};
|
};
|
||||||
|
|
||||||
class VirtualTextureManager
|
class VirtualTextureManager
|
||||||
|
@ -24,11 +24,12 @@ namespace Renderer
|
||||||
VirtualTextureManager(GladGLContext* glMain);
|
VirtualTextureManager(GladGLContext* glMain);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief
|
* @brief 创建彩绘虚拟纹理
|
||||||
* @param painting
|
* @param painting 彩绘
|
||||||
* @return ÐéÄâÎÆÀíid
|
* @return ÐéÄâÎÆÀíid
|
||||||
*/
|
*/
|
||||||
std::uint16_t createVirtualTexture(Painting painting);
|
std::uint16_t createVirtualTexture(Painting painting);
|
||||||
|
void deleteVirtualTexture(std::uint16_t id);
|
||||||
PaintingHandle& getPaintingHandle(std::uint16_t id);
|
PaintingHandle& getPaintingHandle(std::uint16_t id);
|
||||||
void tryUpdatePages(const std::vector<glm::u16vec2>& pageIds);
|
void tryUpdatePages(const std::vector<glm::u16vec2>& pageIds);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue