mirror of
https://github.com/noctalia-dev/noctalia-shell.git
synced 2026-05-11 17:08:27 +08:00
fix(screen-corners): sharper without dedicated shader for more control: no more faint lines on the outside
This commit is contained in:
@@ -390,6 +390,7 @@ _noctalia_sources = files(
|
||||
'src/render/programs/image_program.cpp',
|
||||
'src/render/programs/linear_gradient_program.cpp',
|
||||
'src/render/programs/rect_program.cpp',
|
||||
'src/render/programs/screen_corner_program.cpp',
|
||||
'src/render/programs/spinner_program.cpp',
|
||||
'src/render/programs/audio_spectrum_program.cpp',
|
||||
'src/render/programs/effect_program.cpp',
|
||||
@@ -552,6 +553,7 @@ _noctalia_sources = files(
|
||||
'src/ui/controls/radio_button.cpp',
|
||||
'src/ui/controls/scroll_view.cpp',
|
||||
'src/ui/controls/search_picker.cpp',
|
||||
'src/ui/controls/screen_corner.cpp',
|
||||
'src/ui/controls/segmented.cpp',
|
||||
'src/ui/controls/select.cpp',
|
||||
'src/ui/controls/separator.cpp',
|
||||
|
||||
@@ -340,6 +340,13 @@ void GlesRenderBackend::drawSpinner(float surfaceWidth, float surfaceHeight, flo
|
||||
m_spinnerProgram.draw(surfaceWidth, surfaceHeight, width, height, style, transform);
|
||||
}
|
||||
|
||||
void GlesRenderBackend::drawScreenCorner(float surfaceWidth, float surfaceHeight, float pixelScaleX, float pixelScaleY,
|
||||
float width, float height, const ScreenCornerStyle& style,
|
||||
const Mat3& transform) {
|
||||
m_screenCornerProgram.ensureInitialized();
|
||||
m_screenCornerProgram.draw(surfaceWidth, surfaceHeight, pixelScaleX, pixelScaleY, width, height, style, transform);
|
||||
}
|
||||
|
||||
void GlesRenderBackend::drawAudioSpectrum(float surfaceWidth, float surfaceHeight, float pixelScaleX, float pixelScaleY,
|
||||
float width, float height, const AudioSpectrumStyle& style,
|
||||
std::span<const float> values, const Mat3& transform) {
|
||||
@@ -429,6 +436,7 @@ void GlesRenderBackend::cleanup() {
|
||||
m_imageProgram.destroy();
|
||||
m_glyphProgram.destroy();
|
||||
m_spinnerProgram.destroy();
|
||||
m_screenCornerProgram.destroy();
|
||||
m_audioSpectrumProgram.destroy();
|
||||
m_effectProgram.destroy();
|
||||
m_graphProgram.destroy();
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "render/programs/graph_program.h"
|
||||
#include "render/programs/image_program.h"
|
||||
#include "render/programs/rect_program.h"
|
||||
#include "render/programs/screen_corner_program.h"
|
||||
#include "render/programs/spinner_program.h"
|
||||
#include "render/programs/wallpaper_program.h"
|
||||
|
||||
@@ -48,6 +49,8 @@ public:
|
||||
void drawGlyph(const RenderGlyphDraw& draw) override;
|
||||
void drawSpinner(float surfaceWidth, float surfaceHeight, float width, float height, const SpinnerStyle& style,
|
||||
const Mat3& transform) override;
|
||||
void drawScreenCorner(float surfaceWidth, float surfaceHeight, float pixelScaleX, float pixelScaleY, float width,
|
||||
float height, const ScreenCornerStyle& style, const Mat3& transform) override;
|
||||
void drawAudioSpectrum(float surfaceWidth, float surfaceHeight, float pixelScaleX, float pixelScaleY, float width,
|
||||
float height, const AudioSpectrumStyle& style, std::span<const float> values,
|
||||
const Mat3& transform) override;
|
||||
@@ -82,6 +85,7 @@ private:
|
||||
ImageProgram m_imageProgram;
|
||||
GlyphProgram m_glyphProgram;
|
||||
SpinnerProgram m_spinnerProgram;
|
||||
ScreenCornerProgram m_screenCornerProgram;
|
||||
AudioSpectrumProgram m_audioSpectrumProgram;
|
||||
EffectProgram m_effectProgram;
|
||||
GraphProgram m_graphProgram;
|
||||
|
||||
@@ -18,6 +18,7 @@ struct AudioSpectrumStyle;
|
||||
struct EffectStyle;
|
||||
struct GraphStyle;
|
||||
struct RoundedRectStyle;
|
||||
struct ScreenCornerStyle;
|
||||
struct SpinnerStyle;
|
||||
struct TransitionParams;
|
||||
|
||||
@@ -122,6 +123,8 @@ public:
|
||||
virtual void drawGlyph(const RenderGlyphDraw& draw) = 0;
|
||||
virtual void drawSpinner(float surfaceWidth, float surfaceHeight, float width, float height,
|
||||
const SpinnerStyle& style, const Mat3& transform) = 0;
|
||||
virtual void drawScreenCorner(float surfaceWidth, float surfaceHeight, float pixelScaleX, float pixelScaleY,
|
||||
float width, float height, const ScreenCornerStyle& style, const Mat3& transform) = 0;
|
||||
virtual void drawAudioSpectrum(float surfaceWidth, float surfaceHeight, float pixelScaleX, float pixelScaleY,
|
||||
float width, float height, const AudioSpectrumStyle& style,
|
||||
std::span<const float> values, const Mat3& transform) = 0;
|
||||
|
||||
@@ -117,6 +117,25 @@ struct SpinnerStyle {
|
||||
float thickness = 2.0f;
|
||||
};
|
||||
|
||||
enum class ScreenCornerPosition : std::uint8_t {
|
||||
TopLeft,
|
||||
TopRight,
|
||||
BottomRight,
|
||||
BottomLeft,
|
||||
};
|
||||
|
||||
struct ScreenCornerStyle {
|
||||
Color color = rgba(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
ScreenCornerPosition position = ScreenCornerPosition::TopLeft;
|
||||
float exponent = 4.0f;
|
||||
float softness = 1.0f;
|
||||
};
|
||||
|
||||
constexpr bool operator==(const ScreenCornerStyle& lhs, const ScreenCornerStyle& rhs) noexcept {
|
||||
return lhs.color == rhs.color && lhs.position == rhs.position && lhs.exponent == rhs.exponent &&
|
||||
lhs.softness == rhs.softness;
|
||||
}
|
||||
|
||||
enum class AudioSpectrumOrientation : std::uint8_t {
|
||||
Horizontal,
|
||||
Vertical,
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
#include "render/programs/screen_corner_program.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr char kVertexShaderSource[] = R"(
|
||||
precision highp float;
|
||||
|
||||
attribute vec2 a_position;
|
||||
uniform vec2 u_surface_size;
|
||||
uniform vec2 u_size;
|
||||
uniform mat3 u_transform;
|
||||
varying vec2 v_local;
|
||||
|
||||
vec2 to_ndc(vec2 pixel_pos) {
|
||||
vec2 normalized = pixel_pos / u_surface_size;
|
||||
return vec2(normalized.x * 2.0 - 1.0, 1.0 - normalized.y * 2.0);
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 local = a_position * u_size;
|
||||
vec3 pixel = u_transform * vec3(local, 1.0);
|
||||
v_local = local;
|
||||
gl_Position = vec4(to_ndc(pixel.xy), 0.0, 1.0);
|
||||
}
|
||||
)";
|
||||
|
||||
constexpr char kFragmentShaderSource[] = R"(
|
||||
precision highp float;
|
||||
|
||||
uniform vec2 u_size;
|
||||
uniform vec2 u_pixel_scale;
|
||||
uniform vec4 u_color;
|
||||
uniform int u_corner;
|
||||
uniform float u_exponent;
|
||||
uniform float u_softness;
|
||||
varying vec2 v_local;
|
||||
|
||||
vec2 corner_center() {
|
||||
if (u_corner == 1) {
|
||||
return vec2(0.0, u_size.y);
|
||||
}
|
||||
if (u_corner == 2) {
|
||||
return vec2(0.0, 0.0);
|
||||
}
|
||||
if (u_corner == 3) {
|
||||
return vec2(u_size.x, 0.0);
|
||||
}
|
||||
return u_size;
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 radius = max(u_size, vec2(1.0));
|
||||
vec2 normalized = abs(v_local - corner_center()) / radius;
|
||||
float shape = pow(normalized.x, u_exponent) + pow(normalized.y, u_exponent) - 1.0;
|
||||
float pixel_scale = max(min(u_pixel_scale.x, u_pixel_scale.y), 1.0);
|
||||
float aa = max(u_softness / (min(radius.x, radius.y) * pixel_scale), 0.0001);
|
||||
float coverage = smoothstep(-aa, aa, shape);
|
||||
float alpha = u_color.a * coverage;
|
||||
if (alpha <= 0.0) {
|
||||
discard;
|
||||
}
|
||||
gl_FragColor = vec4(u_color.rgb * alpha, alpha);
|
||||
}
|
||||
)";
|
||||
|
||||
} // namespace
|
||||
|
||||
void ScreenCornerProgram::ensureInitialized() {
|
||||
if (m_program.isValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_program.create(kVertexShaderSource, kFragmentShaderSource);
|
||||
m_positionLocation = glGetAttribLocation(m_program.id(), "a_position");
|
||||
m_surfaceSizeLocation = glGetUniformLocation(m_program.id(), "u_surface_size");
|
||||
m_sizeLocation = glGetUniformLocation(m_program.id(), "u_size");
|
||||
m_pixelScaleLocation = glGetUniformLocation(m_program.id(), "u_pixel_scale");
|
||||
m_colorLocation = glGetUniformLocation(m_program.id(), "u_color");
|
||||
m_cornerLocation = glGetUniformLocation(m_program.id(), "u_corner");
|
||||
m_exponentLocation = glGetUniformLocation(m_program.id(), "u_exponent");
|
||||
m_softnessLocation = glGetUniformLocation(m_program.id(), "u_softness");
|
||||
m_transformLocation = glGetUniformLocation(m_program.id(), "u_transform");
|
||||
|
||||
if (m_positionLocation < 0 || m_surfaceSizeLocation < 0 || m_sizeLocation < 0 || m_pixelScaleLocation < 0 ||
|
||||
m_colorLocation < 0 || m_cornerLocation < 0 || m_exponentLocation < 0 || m_softnessLocation < 0 ||
|
||||
m_transformLocation < 0) {
|
||||
throw std::runtime_error("failed to query screen-corner shader locations");
|
||||
}
|
||||
}
|
||||
|
||||
void ScreenCornerProgram::destroy() {
|
||||
m_program.destroy();
|
||||
m_positionLocation = -1;
|
||||
m_surfaceSizeLocation = -1;
|
||||
m_sizeLocation = -1;
|
||||
m_pixelScaleLocation = -1;
|
||||
m_colorLocation = -1;
|
||||
m_cornerLocation = -1;
|
||||
m_exponentLocation = -1;
|
||||
m_softnessLocation = -1;
|
||||
m_transformLocation = -1;
|
||||
}
|
||||
|
||||
void ScreenCornerProgram::draw(float surfaceWidth, float surfaceHeight, float pixelScaleX, float pixelScaleY,
|
||||
float width, float height, const ScreenCornerStyle& style, const Mat3& transform) const {
|
||||
if (!m_program.isValid() || width <= 0.0f || height <= 0.0f || style.color.a <= 0.0f) {
|
||||
return;
|
||||
}
|
||||
|
||||
const std::array<GLfloat, 12> vertices = {
|
||||
0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
|
||||
};
|
||||
|
||||
glUseProgram(m_program.id());
|
||||
glUniform2f(m_surfaceSizeLocation, surfaceWidth, surfaceHeight);
|
||||
glUniform2f(m_sizeLocation, width, height);
|
||||
glUniform2f(m_pixelScaleLocation, std::max(1.0f, pixelScaleX), std::max(1.0f, pixelScaleY));
|
||||
glUniform4f(m_colorLocation, style.color.r, style.color.g, style.color.b, style.color.a);
|
||||
glUniform1i(m_cornerLocation, static_cast<GLint>(style.position));
|
||||
glUniform1f(m_exponentLocation, std::max(1.0f, style.exponent));
|
||||
glUniform1f(m_softnessLocation, std::max(0.0f, style.softness));
|
||||
glUniformMatrix3fv(m_transformLocation, 1, GL_FALSE, transform.m.data());
|
||||
glVertexAttribPointer(m_positionLocation, 2, GL_FLOAT, GL_FALSE, 0, vertices.data());
|
||||
glEnableVertexAttribArray(m_positionLocation);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
glDisableVertexAttribArray(m_positionLocation);
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#include "render/core/mat3.h"
|
||||
#include "render/core/render_styles.h"
|
||||
#include "render/core/shader_program.h"
|
||||
|
||||
#include <GLES2/gl2.h>
|
||||
|
||||
class ScreenCornerProgram {
|
||||
public:
|
||||
ScreenCornerProgram() = default;
|
||||
~ScreenCornerProgram() = default;
|
||||
|
||||
ScreenCornerProgram(const ScreenCornerProgram&) = delete;
|
||||
ScreenCornerProgram& operator=(const ScreenCornerProgram&) = delete;
|
||||
|
||||
void ensureInitialized();
|
||||
void destroy();
|
||||
|
||||
void draw(float surfaceWidth, float surfaceHeight, float pixelScaleX, float pixelScaleY, float width, float height,
|
||||
const ScreenCornerStyle& style, const Mat3& transform = Mat3::identity()) const;
|
||||
|
||||
private:
|
||||
ShaderProgram m_program;
|
||||
GLint m_positionLocation = -1;
|
||||
GLint m_surfaceSizeLocation = -1;
|
||||
GLint m_sizeLocation = -1;
|
||||
GLint m_pixelScaleLocation = -1;
|
||||
GLint m_colorLocation = -1;
|
||||
GLint m_cornerLocation = -1;
|
||||
GLint m_exponentLocation = -1;
|
||||
GLint m_softnessLocation = -1;
|
||||
GLint m_transformLocation = -1;
|
||||
};
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "render/scene/image_node.h"
|
||||
#include "render/scene/node.h"
|
||||
#include "render/scene/rect_node.h"
|
||||
#include "render/scene/screen_corner_node.h"
|
||||
#include "render/scene/spinner_node.h"
|
||||
#include "render/scene/text_node.h"
|
||||
#include "render/scene/wallpaper_node.h"
|
||||
@@ -320,6 +321,15 @@ void RenderContext::renderNode(const Node* node, const Mat3& parentTransform, fl
|
||||
m_backend->drawSpinner(sw, sh, node->width(), node->height(), style, worldTransform);
|
||||
break;
|
||||
}
|
||||
case NodeType::ScreenCorner: {
|
||||
const auto* corner = static_cast<const ScreenCornerNode*>(node);
|
||||
auto style = corner->style();
|
||||
style.color.a *= effectiveOpacity;
|
||||
const float pixelScaleX = sw > 0.0f ? bw / sw : 1.0f;
|
||||
const float pixelScaleY = sh > 0.0f ? bh / sh : 1.0f;
|
||||
m_backend->drawScreenCorner(sw, sh, pixelScaleX, pixelScaleY, node->width(), node->height(), style, worldTransform);
|
||||
break;
|
||||
}
|
||||
case NodeType::AudioSpectrum: {
|
||||
const auto* spectrum = static_cast<const AudioSpectrumNode*>(node);
|
||||
auto style = spectrum->style();
|
||||
|
||||
@@ -17,6 +17,7 @@ enum class NodeType : std::uint8_t {
|
||||
Image,
|
||||
Glyph,
|
||||
Spinner,
|
||||
ScreenCorner,
|
||||
AudioSpectrum,
|
||||
Effect,
|
||||
Graph,
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
#pragma once
|
||||
|
||||
#include "render/core/render_styles.h"
|
||||
#include "render/scene/node.h"
|
||||
|
||||
class ScreenCornerNode : public Node {
|
||||
public:
|
||||
ScreenCornerNode() : Node(NodeType::ScreenCorner) {}
|
||||
|
||||
[[nodiscard]] const ScreenCornerStyle& style() const noexcept { return m_style; }
|
||||
|
||||
void setStyle(const ScreenCornerStyle& style) {
|
||||
if (m_style == style) {
|
||||
return;
|
||||
}
|
||||
m_style = style;
|
||||
markPaintDirty();
|
||||
}
|
||||
|
||||
void setColor(const Color& color) {
|
||||
if (m_style.color == color) {
|
||||
return;
|
||||
}
|
||||
m_style.color = color;
|
||||
markPaintDirty();
|
||||
}
|
||||
|
||||
void setCorner(ScreenCornerPosition position) {
|
||||
if (m_style.position == position) {
|
||||
return;
|
||||
}
|
||||
m_style.position = position;
|
||||
markPaintDirty();
|
||||
}
|
||||
|
||||
void setExponent(float exponent) {
|
||||
if (m_style.exponent == exponent) {
|
||||
return;
|
||||
}
|
||||
m_style.exponent = exponent;
|
||||
markPaintDirty();
|
||||
}
|
||||
|
||||
void setSoftness(float softness) {
|
||||
if (m_style.softness == softness) {
|
||||
return;
|
||||
}
|
||||
m_style.softness = softness;
|
||||
markPaintDirty();
|
||||
}
|
||||
|
||||
private:
|
||||
ScreenCornerStyle m_style;
|
||||
};
|
||||
@@ -3,7 +3,7 @@
|
||||
#include "config/config_service.h"
|
||||
#include "core/ui_phase.h"
|
||||
#include "render/render_context.h"
|
||||
#include "ui/controls/box.h"
|
||||
#include "ui/controls/screen_corner.h"
|
||||
#include "wayland/wayland_connection.h"
|
||||
|
||||
#include <algorithm>
|
||||
@@ -17,18 +17,18 @@ namespace {
|
||||
LayerShellAnchor::Bottom | LayerShellAnchor::Left,
|
||||
};
|
||||
|
||||
Radii cornerRadii(int cornerIndex, float size) {
|
||||
ScreenCornerPosition cornerPosition(int cornerIndex) {
|
||||
switch (cornerIndex) {
|
||||
case 0:
|
||||
return Radii{size, 0.0f, 0.0f, 0.0f};
|
||||
return ScreenCornerPosition::TopLeft;
|
||||
case 1:
|
||||
return Radii{0.0f, size, 0.0f, 0.0f};
|
||||
return ScreenCornerPosition::TopRight;
|
||||
case 2:
|
||||
return Radii{0.0f, 0.0f, size, 0.0f};
|
||||
return ScreenCornerPosition::BottomRight;
|
||||
case 3:
|
||||
return Radii{0.0f, 0.0f, 0.0f, size};
|
||||
return ScreenCornerPosition::BottomLeft;
|
||||
default:
|
||||
return Radii{};
|
||||
return ScreenCornerPosition::TopLeft;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,14 +105,16 @@ void ScreenCorners::ensureSurfaces() {
|
||||
|
||||
auto* cornerPtr = &corner;
|
||||
const int cornerIndex = i;
|
||||
const float cornerSize = static_cast<float>(size);
|
||||
|
||||
corner.surface->setConfigureCallback(
|
||||
[cornerPtr](std::uint32_t, std::uint32_t) { cornerPtr->surface->requestLayout(); });
|
||||
corner.surface->setPrepareFrameCallback([this, cornerPtr, cornerSize, cornerIndex](bool, bool) {
|
||||
if (cornerPtr->sceneRoot == nullptr) {
|
||||
corner.surface->setPrepareFrameCallback([this, cornerPtr, size, cornerIndex](bool, bool) {
|
||||
auto& target = cornerPtr->surface->renderTarget();
|
||||
const auto width = target.logicalWidth() == 0 ? size : target.logicalWidth();
|
||||
const auto height = target.logicalHeight() == 0 ? size : target.logicalHeight();
|
||||
if (cornerPtr->sceneRoot == nullptr || cornerPtr->builtWidth != width || cornerPtr->builtHeight != height) {
|
||||
UiPhaseScope layoutPhase(UiPhase::Layout);
|
||||
buildCornerScene(*cornerPtr, cornerSize, cornerIndex);
|
||||
buildCornerScene(*cornerPtr, width, height, cornerIndex);
|
||||
}
|
||||
});
|
||||
corner.surface->setRenderContext(m_renderContext);
|
||||
@@ -132,17 +134,19 @@ void ScreenCorners::ensureSurfaces() {
|
||||
|
||||
void ScreenCorners::destroySurfaces() { m_instances.clear(); }
|
||||
|
||||
void ScreenCorners::buildCornerScene(Corner& corner, float size, int cornerIndex) {
|
||||
auto root = std::make_unique<Box>();
|
||||
root->setSize(size, size);
|
||||
root->setStyle(RoundedRectStyle{
|
||||
.fill = Color{0.0f, 0.0f, 0.0f, 1.0f},
|
||||
.fillMode = FillMode::Solid,
|
||||
.radius = cornerRadii(cornerIndex, size),
|
||||
.softness = 0.5f,
|
||||
.invertFill = true,
|
||||
});
|
||||
void ScreenCorners::buildCornerScene(Corner& corner, std::uint32_t width, std::uint32_t height, int cornerIndex) {
|
||||
const float logicalWidth = static_cast<float>(std::max<std::uint32_t>(1, width));
|
||||
const float logicalHeight = static_cast<float>(std::max<std::uint32_t>(1, height));
|
||||
|
||||
auto root = std::make_unique<ScreenCorner>();
|
||||
root->setSize(logicalWidth, logicalHeight);
|
||||
root->setColor(Color{0.0f, 0.0f, 0.0f, 1.0f});
|
||||
root->setCorner(cornerPosition(cornerIndex));
|
||||
root->setExponent(4.0f);
|
||||
root->setSoftness(1.5f);
|
||||
|
||||
corner.sceneRoot = std::move(root);
|
||||
corner.builtWidth = width;
|
||||
corner.builtHeight = height;
|
||||
corner.surface->setSceneRoot(corner.sceneRoot.get());
|
||||
}
|
||||
|
||||
@@ -27,6 +27,8 @@ private:
|
||||
struct Corner {
|
||||
std::unique_ptr<LayerSurface> surface;
|
||||
std::unique_ptr<Node> sceneRoot;
|
||||
std::uint32_t builtWidth = 0;
|
||||
std::uint32_t builtHeight = 0;
|
||||
};
|
||||
|
||||
struct OutputInstance {
|
||||
@@ -36,7 +38,7 @@ private:
|
||||
|
||||
void ensureSurfaces();
|
||||
void destroySurfaces();
|
||||
void buildCornerScene(Corner& corner, float size, int cornerIndex);
|
||||
void buildCornerScene(Corner& corner, std::uint32_t width, std::uint32_t height, int cornerIndex);
|
||||
|
||||
WaylandConnection* m_wayland = nullptr;
|
||||
ConfigService* m_config = nullptr;
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
#include "ui/controls/screen_corner.h"
|
||||
|
||||
#include "render/scene/screen_corner_node.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
ScreenCorner::ScreenCorner() {
|
||||
auto corner = std::make_unique<ScreenCornerNode>();
|
||||
m_corner = static_cast<ScreenCornerNode*>(addChild(std::move(corner)));
|
||||
}
|
||||
|
||||
void ScreenCorner::setColor(const Color& color) { m_corner->setColor(color); }
|
||||
|
||||
void ScreenCorner::setCorner(ScreenCornerPosition position) { m_corner->setCorner(position); }
|
||||
|
||||
void ScreenCorner::setExponent(float exponent) { m_corner->setExponent(exponent); }
|
||||
|
||||
void ScreenCorner::setSoftness(float softness) { m_corner->setSoftness(softness); }
|
||||
|
||||
void ScreenCorner::setSize(float width, float height) {
|
||||
Node::setSize(width, height);
|
||||
m_corner->setFrameSize(width, height);
|
||||
}
|
||||
|
||||
void ScreenCorner::setFrameSize(float width, float height) {
|
||||
Node::setFrameSize(width, height);
|
||||
m_corner->setFrameSize(width, height);
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include "render/core/color.h"
|
||||
#include "render/core/render_styles.h"
|
||||
#include "render/scene/node.h"
|
||||
|
||||
class ScreenCornerNode;
|
||||
|
||||
class ScreenCorner : public Node {
|
||||
public:
|
||||
ScreenCorner();
|
||||
|
||||
void setColor(const Color& color);
|
||||
void setCorner(ScreenCornerPosition position);
|
||||
void setExponent(float exponent);
|
||||
void setSoftness(float softness);
|
||||
|
||||
void setSize(float width, float height) override;
|
||||
void setFrameSize(float width, float height);
|
||||
|
||||
private:
|
||||
ScreenCornerNode* m_corner = nullptr;
|
||||
};
|
||||
Reference in New Issue
Block a user