Added None and Skia antialiasing options in debug menu

This commit is contained in:
Yousef Khadadeh 2026-03-20 20:53:59 +03:00
parent 30fdec05c1
commit d973bde4be
50 changed files with 177 additions and 93 deletions

View file

@ -53,6 +53,7 @@ std::optional<Vector4f> BrushStrokeCanvasComponent::get_stroke_color() const {
void BrushStrokeCanvasComponent::draw(SkCanvas* canvas, const DrawData& drawData, const std::shared_ptr<void>& predrawData) const {
SkPaint paint;
paint.setColor4f(SkColor4f{d.color.x(), d.color.y(), d.color.z(), d.color.w()});
paint.setAntiAlias(drawData.skiaAA);
unsigned mipmapLevel = compContainer ? compContainer->get_mipmap_level(drawData) : 0;

View file

@ -35,6 +35,7 @@ std::optional<Vector4f> EllipseCanvasComponent::get_stroke_color() const {
void EllipseCanvasComponent::draw(SkCanvas* canvas, const DrawData& drawData, const std::shared_ptr<void>& predrawData) const {
SkPaint p;
p.setAntiAlias(drawData.skiaAA);
if(d.fillStrokeMode == 0 || d.fillStrokeMode == 2) {
p.setStyle(SkPaint::kFill_Style);
p.setColor4f(convert_vec4<SkColor4f>(d.fillColor));

View file

@ -65,6 +65,7 @@ void ImageCanvasComponent::draw_download_progress_bar(SkCanvas* canvas, const Dr
p.setStrokeWidth(10.0f);
p.setStrokeCap(SkPaint::kRound_Cap);
p.setColor4f(drawData.main->toolbar.io->theme->fillColor1);
p.setAntiAlias(drawData.skiaAA);
Vector2f center = (d.p1 + d.p2) * 0.5f;
const float DOWNLOAD_ARC_RADIUS = 50.0f;
@ -94,10 +95,12 @@ void ImageCanvasComponent::draw(SkCanvas* canvas, const DrawData& drawData, cons
canvas->saveLayerAlphaf(nullptr, 1.0f);
SkPaint rectPaint;
rectPaint.setColor4f(SkColor4f{0.0f, 0.0f, 0.0f, 0.5f});
rectPaint.setAntiAlias(drawData.skiaAA);
canvas->drawRect(rect_from_points(d.p1, d.p2), rectPaint);
SkPaint openingRectPaint;
openingRectPaint.setColor4f(SkColor4f{0.0f, 0.0f, 0.0f, 0.0f});
openingRectPaint.setBlendMode(SkBlendMode::kSrc);
openingRectPaint.setAntiAlias(drawData.skiaAA);
canvas->drawRect(get_cropped_rectangle(d.p1, d.p2, d.cropP1, d.cropP2), openingRectPaint);
canvas->restore();
canvas->restore();
@ -106,13 +109,16 @@ void ImageCanvasComponent::draw(SkCanvas* canvas, const DrawData& drawData, cons
bool isCropped = d.cropP1 != Vector2f{0.0f, 0.0f} || d.cropP2 != Vector2f{1.0f, 1.0f};
if(isCropped) {
canvas->save();
canvas->clipRect(get_cropped_rectangle(d.p1, d.p2, d.cropP1, d.cropP2));
canvas->clipRect(get_cropped_rectangle(d.p1, d.p2, d.cropP1, d.cropP2), drawData.skiaAA);
}
if(display)
display->draw(canvas, drawData, rect_from_points(d.p1, d.p2));
else
canvas->drawRect(rect_from_points(d.p1, d.p2), SkPaint({0.5f, 0.5f, 0.5f, 0.5f}));
else {
SkPaint p(SkColor4f{0.5f, 0.5f, 0.5f, 0.5f});
p.setAntiAlias(drawData.skiaAA);
canvas->drawRect(rect_from_points(d.p1, d.p2), p);
}
if(isCropped)
canvas->restore();

View file

@ -42,15 +42,15 @@ std::unique_ptr<CanvasComponent> RectangleCanvasComponent::get_data_copy() const
}
void RectangleCanvasComponent::draw(SkCanvas* canvas, const DrawData& drawData, const std::shared_ptr<void>& predrawData) const {
SkPaint p;
p.setAntiAlias(drawData.skiaAA);
if(d.fillStrokeMode == 0 || d.fillStrokeMode == 2) {
SkPaint p;
p.setStyle(SkPaint::kFill_Style);
p.setStrokeCap(SkPaint::kRound_Cap);
p.setColor4f(convert_vec4<SkColor4f>(d.fillColor));
canvas->drawPath(rectPath, p);
}
if(d.fillStrokeMode == 1 || d.fillStrokeMode == 2) {
SkPaint p;
p.setStyle(SkPaint::kStroke_Style);
p.setStrokeCap(SkPaint::kRound_Cap);
p.setColor4f(convert_vec4<SkColor4f>(d.strokeColor));

View file

@ -83,6 +83,7 @@ void TextBoxCanvasComponent::draw(SkCanvas* canvas, const DrawData& drawData, co
SkRect clipR = SkRect::MakeLTRB(d.p1.x(), d.p1.y(), d.p2.x(), d.p2.y());
if(d.editing) {
SkPaint p;
p.setAntiAlias(drawData.skiaAA);
p.setStyle(SkPaint::kStroke_Style);
p.setStrokeWidth(0.0f);
p.setColor4f({0.5f, 0.5f, 0.5f, 1.0f});

View file

@ -17,6 +17,7 @@ struct DrawData {
bool clampDrawBetween = true;
bool drawGrids = true;
bool transparentBackground = false;
bool skiaAA = false;
WorldScalar clampDrawMinimum;
WorldScalar mipMapLevelOne;
WorldScalar mipMapLevelTwo;

View file

@ -512,7 +512,7 @@ bool DrawingProgram::prevent_undo_or_redo() {
return drawTool->prevent_undo_or_redo();
}
SkPaint DrawingProgram::select_tool_line_paint() {
SkPaint DrawingProgram::select_tool_line_paint(const DrawData& drawData) {
SkScalar intervals[] = {10, 5};
float timeSinceEpoch = std::chrono::duration_cast<std::chrono::duration<float>>(std::chrono::steady_clock::now().time_since_epoch()).count();
sk_sp<SkPathEffect> lassoLineDashEffect = SkDashPathEffect::Make({intervals, 2}, -std::fmod(timeSinceEpoch * 50, 15));
@ -523,6 +523,7 @@ SkPaint DrawingProgram::select_tool_line_paint() {
selectLinePaint.setColor4f(world.canvasTheme.get_tool_front_color());
selectLinePaint.setPathEffect(lassoLineDashEffect);
selectLinePaint.setBlender(CanvasTheme::get_visible_blend_mode());
selectLinePaint.setAntiAlias(drawData.skiaAA);
return selectLinePaint;
}
@ -648,6 +649,7 @@ void DrawingProgram::draw_drag_circle(SkCanvas* canvas, const Vector2f& sPos, co
SkPaint paintOutline(SkColor4f{0.95f, 0.95f, 0.95f, 1.0f});
paintOutline.setStroke(true);
paintOutline.setStrokeWidth(constantThickness);
paintOutline.setAntiAlias(drawData.skiaAA);
canvas->drawCircle(sPos.x(), sPos.y(), constantRadius, paintOutline);
}

View file

@ -85,7 +85,7 @@ class DrawingProgram {
float drag_point_radius();
void draw_drag_circle(SkCanvas* canvas, const Vector2f& pos, const SkColor4f& c, const DrawData& drawData, float radiusMultiplier = 1.0f);
SkPaint select_tool_line_paint();
SkPaint select_tool_line_paint(const DrawData& drawData);
bool is_actual_selection_tool(DrawingProgramToolType typeToCheck);
bool is_selection_allowing_tool(DrawingProgramToolType typeToCheck);

View file

@ -327,7 +327,6 @@ void DrawingProgramCache::refresh_draw_cache(const std::shared_ptr<DrawingProgra
void DrawingProgramCache::allocate_window_cache_area() {
const Vector2i& windowSize = drawP.world.main.window.size;
windowCache.surface = drawP.world.main.create_native_surface(windowSize, true);
windowCache.size = windowSize;
}
void DrawingProgramCache::update_window_cache_invalid_bounds(const DrawData& drawData) {
@ -366,7 +365,7 @@ void DrawingProgramCache::window_cache_complete_refresh(const DrawData& drawData
}
void DrawingProgramCache::update_and_draw_cached_canvas(SkCanvas* canvas, const DrawData& drawData) {
if(windowCache.surface == nullptr || drawData.main->window.size != windowCache.size) {
if(windowCache.surface == nullptr) {
allocate_window_cache_area();
refresh_all_draw_cache(drawData);
window_cache_complete_refresh(drawData);

View file

@ -55,7 +55,6 @@ class DrawingProgramCache {
sk_sp<SkSurface> surface;
DrawingProgramCache* attachedDrawingProgramCache = nullptr;
std::optional<SCollision::AABB<WorldScalar>> invalidBounds;
Vector2i size = {0, 0};
CoordSpaceHelper coords;
};
static WindowCache windowCache;

View file

@ -195,6 +195,7 @@ void BrushTool::draw(SkCanvas* canvas, const DrawData& drawData) {
width += 1.0f;
Vector2f pos = drawData.main->input.mouse.pos;
SkPaint linePaint;
linePaint.setAntiAlias(drawData.skiaAA);
linePaint.setColor4f({1.0f, 1.0f, 1.0f, 1.0f});
linePaint.setStyle(SkPaint::kStroke_Style);
linePaint.setStrokeCap(SkPaint::kRound_Cap);

View file

@ -120,6 +120,7 @@ void EraserTool::draw(SkCanvas* canvas, const DrawData& drawData) {
if(relativeWidthResult.first.has_value()) {
float width = relativeWidthResult.first.value() * 0.5f;
SkPaint linePaint;
linePaint.setAntiAlias(drawData.skiaAA);
linePaint.setColor4f({1.0f, 1.0f, 1.0f, 0.5f});
linePaint.setStyle(SkPaint::kStroke_Style);
linePaint.setStrokeCap(SkPaint::kRound_Cap);

View file

@ -44,7 +44,7 @@ void EyeDropperTool::input_mouse_button_on_canvas_callback(const InputManager::M
auto& selectingStrokeColor = drawP.world.main.toolConfig.eyeDropper.selectingStrokeColor;
if(button.button == InputManager::MouseButton::LEFT && button.down && !drawP.selection.is_being_transformed()) {
auto& surface = drawP.world.main.window.surface;
auto& surface = drawP.world.main.window.intermediateSurface;
int xPos = std::clamp<int>(button.pos.x(), 0, drawP.world.main.window.size.x() - 1);
int yPos = std::clamp<int>(button.pos.y(), 0, drawP.world.main.window.size.y() - 1);

View file

@ -184,6 +184,7 @@ void GridModifyTool::draw(SkCanvas* canvas, const DrawData& drawData) {
rectBoundsPaint.setColor4f(drawP.world.canvasTheme.get_tool_front_color());
rectBoundsPaint.setStroke(true);
rectBoundsPaint.setStrokeWidth(0.0f);
rectBoundsPaint.setAntiAlias(drawData.skiaAA);
canvas->drawRect(SkRect::MakeLTRB(bMin.x(), bMin.y(), bMax.x(), bMax.y()), rectBoundsPaint);
if(selectionMode == 0 || selectionMode == 4)
drawP.draw_drag_circle(canvas, bMax, {0.9f, 0.5f, 0.1f, 1.0f}, drawData);

View file

@ -136,7 +136,7 @@ void LassoSelectTool::draw(SkCanvas* canvas, const DrawData& drawData) {
for(Vector2f& p : controls.lassoPoints | std::views::drop(1))
lassoPath.lineTo(convert_vec2<SkPoint>(p));
canvas->drawPath(lassoPath.detach(), drawP.select_tool_line_paint());
canvas->drawPath(lassoPath.detach(), drawP.select_tool_line_paint(drawData));
canvas->restore();
}

View file

@ -97,7 +97,7 @@ void RectSelectTool::draw(SkCanvas* canvas, const DrawData& drawData) {
controls.coords.transform_sk_canvas(canvas, drawData);
SkRect r = SkRect::MakeLTRB(newT[0].x(), newT[0].y(), newT[2].x(), newT[2].y());
canvas->drawRect(r, drawP.select_tool_line_paint());
canvas->drawRect(r, drawP.select_tool_line_paint(drawData));
canvas->restore();
}

View file

@ -21,7 +21,7 @@ void CheckBox::update(UpdateInputData& io, bool newIsTicked, const std::function
}
}
void CheckBox::clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command) {
void CheckBox::clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) {
auto bb = get_bb(command);
canvas->save();
@ -30,6 +30,7 @@ void CheckBox::clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderComma
canvas->translate(0.5f, 0.5f);
SkPaint p;
p.setAntiAlias(skiaAA);
if(isTicked) {
SkRect checkBox = SkRect::MakeLTRB(-0.5f, -0.5f, 0.5f, 0.5f);
p.setColor4f(convert_vec4<SkColor4f>(io.theme->fillColor1));
@ -47,6 +48,7 @@ void CheckBox::clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderComma
if(isTicked) {
SkPaint checkP;
checkP.setAntiAlias(skiaAA);
checkP.setColor4f(io.theme->backColor1);
checkP.setStyle(SkPaint::kFill_Style);
checkP.setStrokeWidth(0.12);

View file

@ -6,7 +6,7 @@ namespace GUIStuff {
class CheckBox : public Element {
public:
void update(UpdateInputData& io, bool newIsTicked, const std::function<void()>& elemUpdate);
virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command) override;
virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) override;
SelectionHelper selection;
private:
static constexpr float CHECKBOX_ANIMATION_TIME = 0.3;

View file

@ -77,20 +77,21 @@ template <typename T> class ColorPicker : public Element {
return isChanged;
}
virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command) {
virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) {
bb = get_bb(command);
canvas->save();
canvas->translate(bb.min.x(), bb.min.y());
float svSelectionAreaSize = get_sv_selection_area_size();
canvas->scale(svSelectionAreaSize, svSelectionAreaSize);
canvas->clipRect(SkRect::MakeXYWH(0.0f, 0.0f, 1.0f, 1.0f));
canvas->clipRect(SkRect::MakeXYWH(0.0f, 0.0f, 1.0f, 1.0f), skiaAA);
SkPaint svSelectionAreaPaint;
svSelectionAreaPaint.setShader(get_sv_selection_shader(savedHsv.x() / 360.0f));
canvas->drawPaint(svSelectionAreaPaint);
SkPaint selectionLinePaint({1.0f, 1.0f, 1.0f, 1.0f});
selectionLinePaint.setAntiAlias(skiaAA);
selectionLinePaint.setStrokeWidth(2.0f / svSelectionAreaSize);
canvas->drawLine(0.0f, 1.0f - savedHsv.z(), 1.0f, 1.0f - savedHsv.z(), selectionLinePaint);
canvas->drawLine(savedHsv.y(), 0.0f, savedHsv.y(), 1.0f, selectionLinePaint);
@ -104,7 +105,7 @@ template <typename T> class ColorPicker : public Element {
canvas->save();
canvas->translate(hueBarPos.x(), hueBarPos.y());
canvas->scale(hueBarDim.x(), hueBarDim.y());
canvas->clipRect(SkRect::MakeXYWH(0.0f, 0.0f, 1.0f, 1.0f));
canvas->clipRect(SkRect::MakeXYWH(0.0f, 0.0f, 1.0f, 1.0f), skiaAA);
SkPaint hueBarPaint;
hueBarPaint.setShader(get_hue_shader());
@ -117,7 +118,7 @@ template <typename T> class ColorPicker : public Element {
Vector2f alphaBarDim = get_alpha_bar_dim();
canvas->save();
canvas->translate(alphaBarPos.x(), alphaBarPos.y());
canvas->clipRect(SkRect::MakeXYWH(0.0f, 0.0f, alphaBarDim.x(), alphaBarDim.y()));
canvas->clipRect(SkRect::MakeXYWH(0.0f, 0.0f, alphaBarDim.x(), alphaBarDim.y()), skiaAA);
SkPaint alphaBarPaint;
if(selectAlpha)

View file

@ -139,7 +139,7 @@ class SelectionHelper {
class Element {
public:
virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command) = 0;
virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) = 0;
virtual ~Element() = default;
protected:

View file

@ -183,5 +183,5 @@ bool GUIStuff::FontPicker::update(UpdateInputData& io, std::string* fontName, GU
return fontChangedFromSelection | fontChangedFromTextbox;
}
void GUIStuff::FontPicker::clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command) {
void GUIStuff::FontPicker::clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) {
}

View file

@ -7,7 +7,7 @@ namespace GUIStuff {
class FontPicker : public Element {
public:
bool update(UpdateInputData& io, std::string* fontName, GUIManager* gui);
virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command) override;
virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) override;
SelectionHelper selection;
private:
std::vector<std::string> sortedFontList;

View file

@ -74,7 +74,7 @@ void MovableTabList::update(UpdateInputData& io, const std::vector<std::pair<std
}
}
void MovableTabList::clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command) {
void MovableTabList::clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) {
}
}

View file

@ -8,7 +8,7 @@ namespace GUIStuff {
class MovableTabList : public Element {
public:
void update(UpdateInputData& io, const std::vector<std::pair<std::string, std::string>>& tabNames, size_t& selectedTab, std::optional<size_t>& closedTab, const std::function<void()>& elemUpdate);
virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command) override;
virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) override;
SelectionHelper selection;
private:
std::vector<std::pair<std::string, std::string>> oldTabNames;

View file

@ -35,7 +35,7 @@ template <typename T> class NumberSlider : public Element {
return isUpdating;
}
virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command) override {
virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) override {
bb = get_bb(command);
canvas->save();
@ -59,10 +59,12 @@ template <typename T> class NumberSlider : public Element {
SkRect barEmpty = SkRect::MakeXYWH(holderPos, yChange, bb.width() - holderPos, holderRadius);
SkPaint barFullP;
barFullP.setAntiAlias(skiaAA);
barFullP.setColor(convert_vec4<SkColor4f>(io.theme->fillColor1));
canvas->drawRoundRect(barFull, 5.0f, 5.0f, barFullP);
SkPaint barEmptyP;
barEmptyP.setAntiAlias(skiaAA);
barEmptyP.setColor(convert_vec4<SkColor4f>(io.theme->backColor2));
canvas->drawRoundRect(barEmpty, 5.0f, 5.0f, barEmptyP);
@ -70,12 +72,14 @@ template <typename T> class NumberSlider : public Element {
SkRect holderRect = SkRect::MakeLTRB(-holderRadius, -holderHeight, holderRadius, holderHeight);
SkPaint holderBorderP;
holderBorderP.setAntiAlias(skiaAA);
holderBorderP.setStyle(SkPaint::kStroke_Style);
holderBorderP.setStrokeWidth(3.0f);
holderBorderP.setColor(convert_vec4<SkColor4f>(io.theme->fillColor1));
canvas->drawRoundRect(holderRect, holderRadius, holderRadius, holderBorderP);
SkPaint holderP;
holderP.setAntiAlias(skiaAA);
holderP.setColor(convert_vec4<SkColor4f>(io.theme->backColor2));
canvas->drawRoundRect(holderRect, holderRadius, holderRadius, holderP);

View file

@ -64,27 +64,29 @@ void PaintCircleMenu::update(GUIManager& gui, const Data& data, const std::funct
d = data;
}
void PaintCircleMenu::clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command) {
void PaintCircleMenu::clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) {
bb = get_bb(command);
canvas->save();
canvas->translate(bb.center().x(), bb.center().y());
draw_rotate_bar(canvas, io);
draw_palette_bar(canvas, io);
draw_rotate_bar(canvas, io, skiaAA);
draw_palette_bar(canvas, io, skiaAA);
SkPaint p;
p.setAntiAlias(skiaAA);
p.setColor4f(color_mul_alpha(io.theme->backColor1, 0.5f));
canvas->drawCircle(0.0f, 0.0f, PALETTE_START, p);
canvas->restore();
}
void PaintCircleMenu::draw_rotate_bar(SkCanvas* canvas, UpdateInputData& io) {
void PaintCircleMenu::draw_rotate_bar(SkCanvas* canvas, UpdateInputData& io, bool skiaAA) {
if(!d.newRotationAngle)
return;
double rotationAngle = d.currentRotationAngle;
float rotateBarMiddleRadius = (CIRCLE_END + ROTATE_START) / 2.0f;
SkPaint rotateBarFill(io.theme->backColor2);
rotateBarFill.setAntiAlias(skiaAA);
rotateBarFill.setStroke(true);
rotateBarFill.setStrokeWidth(CIRCLE_END - ROTATE_START);
canvas->drawCircle(0.0f, 0.0f, rotateBarMiddleRadius, rotateBarFill);
@ -93,12 +95,14 @@ void PaintCircleMenu::draw_rotate_bar(SkCanvas* canvas, UpdateInputData& io) {
for(double snapPos = 0.0; snapPos < std::numbers::pi * 2.0; snapPos += ROTATE_BAR_SNAP_DISTRIBUTION) {
Vector2f lineDir{std::cos(snapPos), -std::sin(snapPos)};
SkPaint p(snapPos == 0.0 ? io.theme->fillColor1 : io.theme->frontColor2);
p.setAntiAlias(skiaAA);
p.setStrokeWidth(2.0f);
canvas->drawLine(lineDir.x() * ROTATE_START, lineDir.y() * ROTATE_START, lineDir.x() * CIRCLE_END, lineDir.y() * CIRCLE_END, p);
}
}
SkPaint rotateBarHolderFill;
rotateBarHolderFill.setAntiAlias(skiaAA);
if(rotateBarSelect.held)
rotateBarHolderFill.setColor4f(io.theme->fillColor1);
else if(rotateBarSelect.hovered)
@ -109,18 +113,20 @@ void PaintCircleMenu::draw_rotate_bar(SkCanvas* canvas, UpdateInputData& io) {
Vector2f rotateBarHolderPos{std::cos(rotationAngle) * rotateBarMiddleRadius, -std::sin(rotationAngle) * rotateBarMiddleRadius};
canvas->drawCircle(rotateBarHolderPos.x(), rotateBarHolderPos.y(), rotateBarHolderRadius, rotateBarHolderFill);
SkPaint rotateBarHolderOutline(io.theme->frontColor1);
rotateBarHolderOutline.setAntiAlias(skiaAA);
rotateBarHolderOutline.setStroke(true);
rotateBarHolderOutline.setStrokeWidth(2.0f);
canvas->drawCircle(rotateBarHolderPos.x(), rotateBarHolderPos.y(), rotateBarHolderRadius, rotateBarHolderOutline);
SkPaint rotateBarOutline(io.theme->frontColor2);
rotateBarOutline.setAntiAlias(skiaAA);
rotateBarOutline.setStroke(true);
rotateBarOutline.setStrokeWidth(2.0f);
canvas->drawCircle(0.0f, 0.0f, ROTATE_START, rotateBarOutline);
canvas->drawCircle(0.0f, 0.0f, CIRCLE_END, rotateBarOutline);
}
void PaintCircleMenu::draw_palette_bar(SkCanvas* canvas, UpdateInputData& io) {
void PaintCircleMenu::draw_palette_bar(SkCanvas* canvas, UpdateInputData& io, bool skiaAA) {
if(d.palette.empty() || !d.selectedColor)
return;
@ -133,18 +139,21 @@ void PaintCircleMenu::draw_palette_bar(SkCanvas* canvas, UpdateInputData& io) {
double angleEnd = (i + 1) * colorDistribution;
SkPaint colorP(SkColor4f{d.palette[i].x(), d.palette[i].y(), d.palette[i].z(), 1.0f});
colorP.setAntiAlias(skiaAA);
colorP.setStroke(true);
colorP.setStrokeWidth(ROTATE_START - PALETTE_START);
canvas->drawArc(colorOval, angleStart * 180.0 / std::numbers::pi, (angleEnd - angleStart) * 180.0 / std::numbers::pi, false, colorP);
Vector2f lineDir1{std::cos(angleStart), std::sin(angleStart)};
SkPaint lineP(io.theme->frontColor2);
lineP.setAntiAlias(skiaAA);
lineP.setStrokeWidth(2.0f);
lineP.setStroke(true);
canvas->drawLine(lineDir1.x() * PALETTE_START, lineDir1.y() * PALETTE_START, lineDir1.x() * ROTATE_START, lineDir1.y() * ROTATE_START, lineP);
}
SkPaint barOutline(io.theme->frontColor2);
barOutline.setAntiAlias(skiaAA);
barOutline.setStroke(true);
barOutline.setStrokeWidth(2.0f);
canvas->drawCircle(0.0f, 0.0f, PALETTE_START, barOutline);
@ -159,6 +168,7 @@ void PaintCircleMenu::draw_palette_bar(SkCanvas* canvas, UpdateInputData& io) {
Vector2f lineDir1{std::cos(angleStart), std::sin(angleStart)};
Vector2f lineDir2{std::cos(angleEnd), std::sin(angleEnd)};
SkPaint lineP(io.theme->fillColor1);
lineP.setAntiAlias(skiaAA);
lineP.setStrokeWidth(5.0f);
lineP.setStroke(true);
lineP.setStrokeJoin(SkPaint::kRound_Join);
@ -178,6 +188,7 @@ void PaintCircleMenu::draw_palette_bar(SkCanvas* canvas, UpdateInputData& io) {
Vector2f lineDir1{std::cos(angleStart), std::sin(angleStart)};
Vector2f lineDir2{std::cos(angleEnd), std::sin(angleEnd)};
SkPaint lineP(io.theme->fillColor1);
lineP.setAntiAlias(skiaAA);
lineP.setStrokeWidth(5.0f);
lineP.setStroke(true);
lineP.setStrokeJoin(SkPaint::kRound_Join);

View file

@ -14,10 +14,10 @@ class PaintCircleMenu : public Element {
std::vector<Vector3f> palette;
};
void update(GUIManager& gui, const Data& data, const std::function<void()>& elemUpdate);
virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command) override;
virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) override;
private:
void draw_rotate_bar(SkCanvas* canvas, UpdateInputData& io);
void draw_palette_bar(SkCanvas* canvas, UpdateInputData& io);
void draw_rotate_bar(SkCanvas* canvas, UpdateInputData& io, bool skiaAA);
void draw_palette_bar(SkCanvas* canvas, UpdateInputData& io, bool skiaAA);
Data d;
SCollision::AABB<float> bb;
SelectionHelper rotateBarSelect;

View file

@ -19,7 +19,7 @@ void RadioButton::update(UpdateInputData& io, bool newIsTicked, const std::funct
}
}
void RadioButton::clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command) {
void RadioButton::clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) {
auto bb = get_bb(command);
canvas->save();
@ -29,11 +29,13 @@ void RadioButton::clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCo
if(isTicked) {
SkPaint p;
p.setAntiAlias(skiaAA);
p.setColor4f(convert_vec4<SkColor4f>(io.theme->fillColor1));
p.setStyle(SkPaint::kFill_Style);
canvas->drawCircle(0.0f, 0.0f, 0.5f, p);
SkPaint innerCircleP;
innerCircleP.setAntiAlias(skiaAA);
innerCircleP.setColor4f(convert_vec4<SkColor4f>(io.theme->backColor2));
innerCircleP.setStyle(SkPaint::kFill_Style);
@ -45,6 +47,7 @@ void RadioButton::clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCo
}
else {
SkPaint p;
p.setAntiAlias(skiaAA);
p.setColor4f(convert_vec4<SkColor4f>(selection.hovered ? io.theme->fillColor1 : io.theme->backColor2));
p.setStyle(SkPaint::kStroke_Style);
p.setStrokeWidth(0.15f);

View file

@ -6,7 +6,7 @@ namespace GUIStuff {
class RadioButton : public Element {
public:
void update(UpdateInputData& io, bool newIsTicked, const std::function<void()>& elemUpdate);
virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command) override;
virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) override;
SelectionHelper selection;
private:
static constexpr float RADIOBUTTON_ANIMATION_TIME = 0.3;

View file

@ -51,17 +51,17 @@ float RotateWheel::wheel_end() {
return bb.width() * 0.5f;
}
void RotateWheel::clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command) {
void RotateWheel::clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) {
bb = get_bb(command);
canvas->save();
canvas->translate(bb.center().x(), bb.center().y());
draw_rotate_wheel(canvas, io);
draw_rotate_wheel(canvas, io, skiaAA);
canvas->restore();
}
void RotateWheel::draw_rotate_wheel(SkCanvas* canvas, UpdateInputData& io) {
void RotateWheel::draw_rotate_wheel(SkCanvas* canvas, UpdateInputData& io, bool skiaAA) {
float wheelStart = wheel_start();
float wheelEnd = wheel_end();
@ -75,12 +75,14 @@ void RotateWheel::draw_rotate_wheel(SkCanvas* canvas, UpdateInputData& io) {
for(double snapPos = 0.0; snapPos < std::numbers::pi * 2.0; snapPos += ROTATE_BAR_SNAP_DISTRIBUTION) {
Vector2f lineDir{std::cos(snapPos), -std::sin(snapPos)};
SkPaint p(snapPos == 0.0 ? io.theme->fillColor1 : io.theme->frontColor2);
p.setAntiAlias(skiaAA);
p.setStrokeWidth(1.0f);
canvas->drawLine(lineDir.x() * wheelStart, lineDir.y() * wheelStart, lineDir.x() * wheelEnd, lineDir.y() * wheelEnd, p);
}
}
SkPaint rotateBarHolderFill;
rotateBarHolderFill.setAntiAlias(skiaAA);
if(selection.held)
rotateBarHolderFill.setColor4f(io.theme->fillColor1);
else if(selection.hovered)
@ -91,11 +93,13 @@ void RotateWheel::draw_rotate_wheel(SkCanvas* canvas, UpdateInputData& io) {
Vector2f rotateBarHolderPos{std::cos(rotateAngle) * rotateBarMiddleRadius, -std::sin(rotateAngle) * rotateBarMiddleRadius};
canvas->drawCircle(rotateBarHolderPos.x(), rotateBarHolderPos.y(), rotateBarHolderRadius, rotateBarHolderFill);
SkPaint rotateBarHolderOutline(io.theme->frontColor1);
rotateBarHolderOutline.setAntiAlias(skiaAA);
rotateBarHolderOutline.setStroke(true);
rotateBarHolderOutline.setStrokeWidth(2.0f);
canvas->drawCircle(rotateBarHolderPos.x(), rotateBarHolderPos.y(), rotateBarHolderRadius, rotateBarHolderOutline);
SkPaint rotateBarOutline(io.theme->frontColor2);
rotateBarOutline.setAntiAlias(skiaAA);
rotateBarOutline.setStroke(true);
rotateBarOutline.setStrokeWidth(1.0f);
canvas->drawCircle(0.0f, 0.0f, wheelStart, rotateBarOutline);

View file

@ -6,12 +6,12 @@ namespace GUIStuff {
class RotateWheel : public Element {
public:
void update(UpdateInputData& io, double* newRotationAnglePtr, const std::function<void()>& elemUpdate);
virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command) override;
virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) override;
SelectionHelper selection;
private:
float wheel_start();
float wheel_end();
void draw_rotate_wheel(SkCanvas* canvas, UpdateInputData& io);
void draw_rotate_wheel(SkCanvas* canvas, UpdateInputData& io, bool skiaAA);
double rotateAngle = 0.0f;
SCollision::AABB<float> bb;

View file

@ -26,7 +26,7 @@ void SVGIcon::update(UpdateInputData& io, const std::string& newSvgPath, bool ne
}
}
void SVGIcon::clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command) {
void SVGIcon::clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) {
if(!svgDom)
return;

View file

@ -6,7 +6,7 @@ namespace GUIStuff {
class SVGIcon : public Element {
public:
void update(UpdateInputData& io, const std::string& newSvgPath, bool newIsHighlighted, const std::function<void()>& elemUpdate);
virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command) override;
virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) override;
private:
bool highlighted;
sk_sp<SkSVGDOM> svgDom;

View file

@ -55,7 +55,7 @@ void SelectableButton::update(UpdateInputData& io, DrawType drawType, const std:
}
}
void SelectableButton::clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command) {
void SelectableButton::clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) {
}
}

View file

@ -13,7 +13,7 @@ class SelectableButton : public Element {
};
void update(UpdateInputData& io, DrawType drawType, const std::function<void(SelectionHelper&, bool)>& elemUpdate, bool isSelected);
virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command) override;
virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) override;
SelectionHelper selection;
};

View file

@ -61,7 +61,7 @@ template <typename T> class TextBox : public Element {
return isUpdating;
}
virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command) override {
virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) override {
if(!data || !textbox || !cur)
return;

View file

@ -18,7 +18,7 @@ void TextParagraph::update(UpdateInputData& io, std::unique_ptr<skia::textlayout
}
}
void TextParagraph::clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command) {
void TextParagraph::clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) {
bb = get_bb(command);
if(data)

View file

@ -7,7 +7,7 @@ namespace GUIStuff {
class TextParagraph : public Element {
public:
void update(UpdateInputData& io, std::unique_ptr<skia::textlayout::Paragraph> paragraph, float width, const std::function<void()>& elemUpdate);
virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command) override;
virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) override;
private:
SCollision::AABB<float> bb = SCollision::AABB<float>({0.0f, 0.0f}, {0.0f, 0.0f});
std::unique_ptr<skia::textlayout::Paragraph> data;

View file

@ -275,7 +275,7 @@ void TreeListing::select_and_unselect_parents(const std::vector<NetworkingObject
selectionData.objsSelected.emplace(newSelectedObj);
}
void TreeListing::clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command) {
void TreeListing::clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) {
}
}

View file

@ -41,7 +41,7 @@ class TreeListing : public Element {
};
void update(UpdateInputData& io, GUIManager& gui, NetworkingObjects::NetObjID rootObjID, const DisplayData& displayData, SelectionData& selectionData);
virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command) override;
virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) override;
private:
bool dragHoldSelected = false;

View file

@ -82,7 +82,7 @@ void GUIManager::end() {
});
}
void GUIManager::draw(SkCanvas* canvas) {
void GUIManager::draw(SkCanvas* canvas, bool skiaAA) {
canvas->save();
canvas->translate(windowPos.x(), windowPos.y());
@ -106,6 +106,7 @@ void GUIManager::draw(SkCanvas* canvas) {
);
SkPaint paint;
paint.setAntiAlias(skiaAA);
paint.setStyle(SkPaint::kFill_Style);
paint.setColor4f(convert_vec4<SkColor4f>(config->backgroundColor));
canvas->drawRRect(rrect, paint);
@ -137,6 +138,7 @@ void GUIManager::draw(SkCanvas* canvas) {
SkPaint p;
p.setColor4f(convert_vec4<SkColor4f>(config->color));
p.setStyle(SkPaint::kStroke_Style);
p.setAntiAlias(skiaAA);
float halfLineWidth = 0.0f;
// Top Left corner
@ -235,7 +237,7 @@ void GUIManager::draw(SkCanvas* canvas) {
}
case CLAY_RENDER_COMMAND_TYPE_CUSTOM: {
Element* customElement = (Element*)command->renderData.custom.customData;
customElement->clay_draw(canvas, *io, command);
customElement->clay_draw(canvas, *io, command, skiaAA);
break;
}
default:

View file

@ -36,7 +36,7 @@ class GUIManager {
GUIManager();
void begin();
void end();
void draw(SkCanvas* canvas);
void draw(SkCanvas* canvas, bool skiaAA);
Vector2f windowPos = Vector2f{0.0f, 0.0f};
Vector2f windowSize = Vector2f{0.0f, 0.0f};

View file

@ -242,6 +242,8 @@ void MainProgram::load_config() {
toolbar.load_licenses();
NetLibrary::copy_default_p2p_config_to_path(configPath / "p2p.json");
refresh_draw_surfaces();
}
void MainProgram::set_vsync_value(int vsyncValue) {
@ -269,30 +271,49 @@ float MainProgram::get_scale_and_density_factor_gui() {
return window.scale * window.density;
}
void MainProgram::refresh_draw_surfaces() {
if(window.canCreateSurfaces) {
window.defaultMSAASampleCount = 0;
window.defaultMSAASurfaceProps = SkSurfaceProps(antialiasing == AntiAliasing::DYNAMIC_MSAA ? SkSurfaceProps::kDynamicMSAA_Flag : SkSurfaceProps::kDefault_Flag, kUnknown_SkPixelGeometry);
window.intermediateSurface = create_native_surface(window.size, true);
window.intermediateCanvas = window.intermediateSurface->getCanvas();
if(!window.intermediateCanvas)
throw std::runtime_error("[refresh_draw_surfaces] Could not create intermediate canvas");
DrawingProgramCache::delete_all_draw_cache();
}
}
void MainProgram::draw(SkCanvas* canvas, std::shared_ptr<World> worldToDraw, const DrawData& drawData) {
canvas->clear(drawData.transparentBackground ? SkColor4f{0.0f, 0.0f, 0.0f, 0.0f} : worldToDraw->canvasTheme.get_back_color());
worldToDraw->draw(canvas, drawData);
DrawData drawDataCopy = drawData;
drawDataCopy.skiaAA = antialiasing == AntiAliasing::SKIA;
worldToDraw->draw(canvas, drawDataCopy);
if(!drawData.takingScreenshot)
toolbar.draw(canvas);
toolbar.draw(canvas, drawDataCopy.skiaAA);
}
sk_sp<SkSurface> MainProgram::create_native_surface(Vector2i resolution, bool isMSAA) {
#ifdef USE_BACKEND_OPENGLES_3_0
SkImageInfo imgInfo = SkImageInfo::Make(resolution.x(), resolution.y(), kRGBA_8888_SkColorType, kPremul_SkAlphaType);
#else
SkImageInfo imgInfo = SkImageInfo::MakeN32Premul(resolution.x(), resolution.y());
#endif
SkSurfaceProps defaultProps;
#ifdef USE_SKIA_BACKEND_GRAPHITE
auto surfaceToRet = SkSurfaces::RenderTarget(window.recorder(), imgInfo, skgpu::Mipmapped::kNo, isMSAA ? &window.defaultMSAASurfaceProps : &defaultProps);
#elif USE_SKIA_BACKEND_GANESH
auto surfaceToRet = SkSurfaces::RenderTarget(window.ctx.get(), skgpu::Budgeted::kNo, imgInfo, isMSAA ? window.defaultMSAASampleCount : 0, isMSAA ? &window.defaultMSAASurfaceProps : &defaultProps);
#endif
if(window.canCreateSurfaces) {
#ifdef USE_BACKEND_OPENGLES_3_0
SkImageInfo imgInfo = SkImageInfo::Make(resolution.x(), resolution.y(), kRGBA_8888_SkColorType, kPremul_SkAlphaType);
#else
SkImageInfo imgInfo = SkImageInfo::MakeN32Premul(resolution.x(), resolution.y());
#endif
SkSurfaceProps defaultProps;
#ifdef USE_SKIA_BACKEND_GRAPHITE
auto surfaceToRet = SkSurfaces::RenderTarget(window.recorder(), imgInfo, skgpu::Mipmapped::kNo, isMSAA ? &window.defaultMSAASurfaceProps : &defaultProps);
#elif USE_SKIA_BACKEND_GANESH
auto surfaceToRet = SkSurfaces::RenderTarget(window.ctx.get(), skgpu::Budgeted::kNo, imgInfo, isMSAA ? window.defaultMSAASampleCount : 0, isMSAA ? &window.defaultMSAASurfaceProps : &defaultProps);
#endif
if(!surfaceToRet)
throw std::runtime_error("[MainProgram::create_native_surface] Could not make native surface");
if(!surfaceToRet)
throw std::runtime_error("[MainProgram::create_native_surface] Could not make native surface");
return surfaceToRet;
return surfaceToRet;
}
return nullptr;
}
void MainProgram::input_drop_file_callback(const InputManager::DropCallbackArgs& drop) {

View file

@ -60,9 +60,12 @@ class MainProgram {
#elif USE_SKIA_BACKEND_GANESH
sk_sp<GrDirectContext> ctx;
#endif
sk_sp<SkSurface> surface;
sk_sp<SkSurface> intermediateSurface;
SkCanvas* intermediateCanvas;
SDL_Window* sdlWindow;
bool canCreateSurfaces = false;
} window;
struct Clipboard {
@ -89,6 +92,12 @@ class MainProgram {
sk_sp<SkSurface> create_native_surface(Vector2i resolution, bool isMSAA);
bool setToQuit = false;
enum class AntiAliasing {
NONE,
SKIA,
DYNAMIC_MSAA
} antialiasing = AntiAliasing::DYNAMIC_MSAA;
void early_destroy();
@ -107,6 +116,8 @@ class MainProgram {
float get_scale_and_density_factor_gui();
bool app_close_requested();
void refresh_draw_surfaces();
std::filesystem::path homePath;
std::filesystem::path configPath;
std::filesystem::path documentsPath;
@ -148,3 +159,9 @@ class MainProgram {
void gui();
void draw_grid(SkCanvas* canvas);
};
NLOHMANN_JSON_SERIALIZE_ENUM(MainProgram::AntiAliasing, {
{MainProgram::AntiAliasing::NONE, "None"},
{MainProgram::AntiAliasing::SKIA, "Skia"},
{MainProgram::AntiAliasing::DYNAMIC_MSAA, "Dynamic MSAA"},
})

View file

@ -197,8 +197,11 @@ void ImageResourceDisplay::load_thread_func(unsigned mipmapLevel) {
}
void ImageResourceDisplay::draw(SkCanvas* canvas, const DrawData& drawData, const SkRect& imRect) {
if(!smallestMipmapLevelLoaded)
canvas->drawRect(imRect, SkPaint({0.5f, 0.5f, 0.5f, 0.5f}));
if(!smallestMipmapLevelLoaded) {
SkPaint p({0.5f, 0.5f, 0.5f, 0.5f});
p.setAntiAlias(drawData.skiaAA);
canvas->drawRect(imRect, p);
}
else {
SkRect imRectPixelSize = canvas->getLocalToDeviceAs3x3().mapRect(imRect);
unsigned mipmapLevel = get_exact_mipmap_level_for_dimensions({imRectPixelSize.width(), imRectPixelSize.height()});

View file

@ -1249,6 +1249,7 @@ void TextBox::paint(SkCanvas* canvas, const PaintOpts& paintOpts) {
if(paintOpts.cursor.has_value()) {
auto& cur = paintOpts.cursor.value();
SkPaint selectionP{SkColor4f{paintOpts.cursorColor.x(), paintOpts.cursorColor.y(), paintOpts.cursorColor.z(), 1.0f}};
selectionP.setAntiAlias(paintOpts.skiaAA);
if(cur.selectionBeginPos != cur.selectionEndPos) {
canvas->saveLayerAlphaf(nullptr, 0.5f);
rects_between_text_positions_func(cur.selectionBeginPos, cur.selectionEndPos, [&](const SkRect& rect) {
@ -1257,6 +1258,7 @@ void TextBox::paint(SkCanvas* canvas, const PaintOpts& paintOpts) {
canvas->restore();
}
SkPaint cursorP{SkColor4f{paintOpts.cursorColor.x(), paintOpts.cursorColor.y(), paintOpts.cursorColor.z(), 1.0f}};
cursorP.setAntiAlias(paintOpts.skiaAA);
canvas->drawRect(get_cursor_rect(cur.pos), cursorP);
}
}

View file

@ -98,6 +98,7 @@ class TextBox {
struct PaintOpts {
Vector3f cursorColor = {1, 0, 0};
std::optional<Cursor> cursor;
bool skiaAA = false;
};
TextPosition move(Movement movement, TextPosition pos, std::optional<float>* previousX = nullptr, bool flipDependingOnTextDirection = false);

View file

@ -306,6 +306,7 @@ nlohmann::json Toolbar::get_config_json() {
debugJson["showPerformance"] = showPerformance;
debugJson["fpsLimit"] = main.fpsLimit;
debugJson["jumpTransitionEasing"] = jumpTransitionEasing;
debugJson["antialiasing"] = main.antialiasing;
debugJson["imageLoadMaxThreads"] = ImageResourceDisplay::IMAGE_LOAD_THREAD_COUNT_MAX;
debugJson["cacheNodeResolution"] = DrawingProgramCache::CACHE_NODE_RESOLUTION;
debugJson["maxCacheNodes"] = DrawingProgramCache::MAXIMUM_DRAW_CACHE_SURFACES;
@ -378,6 +379,7 @@ void Toolbar::set_config_json(const nlohmann::json& j, VersionNumber version) {
try{j.at("debug").at("showPerformance").get_to(showPerformance);} catch(...) {}
try{j.at("debug").at("fpsLimit").get_to(main.fpsLimit);} catch(...) {}
try{j.at("debug").at("jumpTransitionEasing").get_to(jumpTransitionEasing);} catch(...) {}
try{j.at("debug").at("antialiasing").get_to(main.antialiasing);} catch(...) {}
try{j.at("debug").at("imageLoadMaxThreads").get_to(ImageResourceDisplay::IMAGE_LOAD_THREAD_COUNT_MAX);} catch(...) {}
try{j.at("debug").at("cacheNodeResolution").get_to(DrawingProgramCache::CACHE_NODE_RESOLUTION);} catch(...) {}
try{j.at("debug").at("maxCacheNodes").get_to(DrawingProgramCache::MAXIMUM_DRAW_CACHE_SURFACES);} catch(...) {}
@ -1907,6 +1909,13 @@ void Toolbar::options_menu() {
gui.input_scalar_field("fps cap slider", "FPS cap", &main.fpsLimit, 3.0f, 10000.0f);
#endif
gui.input_scalar_field<int>("image load max threads", "Maximum image loading threads", &ImageResourceDisplay::IMAGE_LOAD_THREAD_COUNT_MAX, 1, 10000);
gui.text_label("Antialiasing:");
MainProgram::AntiAliasing aa = main.antialiasing;
if(gui.radio_button_field("AntiAliasing None", "None", aa == MainProgram::AntiAliasing::NONE)) { main.antialiasing = MainProgram::AntiAliasing::NONE; }
if(gui.radio_button_field("AntiAliasing Skia", "Skia", aa == MainProgram::AntiAliasing::SKIA)) { main.antialiasing = MainProgram::AntiAliasing::SKIA; }
if(gui.radio_button_field("AntiAliasing Dynamic MSAA", "Dynamic MSAA", aa == MainProgram::AntiAliasing::DYNAMIC_MSAA)) { main.antialiasing = MainProgram::AntiAliasing::DYNAMIC_MSAA; }
if(main.antialiasing != aa)
main.refresh_draw_surfaces();
gui.text_label_light("Cache related settings");
gui.input_scalar_field<size_t>("cache node resolution", "Cache node resolution", &DrawingProgramCache::CACHE_NODE_RESOLUTION, 256, 8192);
gui.input_scalar_field<size_t>("max cache nodes", "Maximum cached nodes", &DrawingProgramCache::MAXIMUM_DRAW_CACHE_SURFACES, 2, 10000);
@ -2456,9 +2465,9 @@ void Toolbar::end_gui() {
end_io();
}
void Toolbar::draw(SkCanvas* canvas) {
void Toolbar::draw(SkCanvas* canvas, bool skiaAA) {
canvas->save();
canvas->scale(final_gui_scale(), final_gui_scale());
gui.draw(canvas);
gui.draw(canvas, skiaAA);
canvas->restore();
}

View file

@ -47,7 +47,7 @@ class Toolbar {
void input_finger_touch_callback(const InputManager::FingerTouchCallbackArgs& touch);
void input_finger_motion_callback(const InputManager::FingerMotionCallbackArgs& motion);
void update();
void draw(SkCanvas* canvas);
void draw(SkCanvas* canvas, bool skiaAA);
void color_selector_left(Vector4f* color);
void color_selector_right(Vector4f* color);
void paint_popup(Vector2f popupPos);

View file

@ -136,8 +136,6 @@ struct MainStruct {
SkCanvas* canvas;
sk_sp<SkSurface> surface;
sk_sp<SkSurface> intermediateSurface;
SkCanvas* intermediateCanvas;
SDL_Surface* iconSurface = nullptr;
std::string iconData;
@ -312,13 +310,7 @@ void sdl_terminate(MainStruct& mS) {
void resize_window(MainStruct& mS) {
// Having intermediate surface allows for changing options more easily
mS.intermediateSurface = mS.m->create_native_surface(mS.m->window.size, true);
mS.intermediateCanvas = mS.intermediateSurface->getCanvas();
if(!mS.intermediateCanvas)
throw std::runtime_error("[resize_window] Could not create intermediate canvas");
mS.m->window.surface = mS.intermediateSurface;
mS.m->refresh_draw_surfaces();
#ifdef USE_BACKEND_VULKAN
mS.vulkanWindowContext->resize(mS.m->window.size.x(), mS.m->window.size.y());
@ -446,8 +438,6 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char **argv) {
mS.hiddenCursor = SDL_CreateCursor((Uint8 *)cursorData, (Uint8 *)cursorData, 8, 8, 4, 4);
mS.m = std::make_unique<MainProgram>();
mS.m->window.defaultMSAASampleCount = 0;
mS.m->window.defaultMSAASurfaceProps = SkSurfaceProps(SkSurfaceProps::kDynamicMSAA_Flag, kUnknown_SkPixelGeometry);
mS.m->logFile = &mS.logFile;
mS.m->configPath = mS.configPath;
mS.m->homePath = mS.homePath;
@ -552,6 +542,7 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char **argv) {
SDL_SetWindowFullscreen(mS.window, true);
#endif
mS.m->window.canCreateSurfaces = true;
resize_window(mS);
if(listOfFilesToOpenFromCommand.empty()) {
@ -599,15 +590,15 @@ void attempt_redraw_and_swap_buffers(MainStruct& mS) {
#endif
mS.lastRenderTimePoint = std::chrono::steady_clock::now();
mS.intermediateCanvas->save();
mS.m->draw(mS.intermediateCanvas, mS.m->world, mS.m->world->drawData);
mS.intermediateCanvas->restore();
mS.m->window.intermediateCanvas->save();
mS.m->draw(mS.m->window.intermediateCanvas, mS.m->world, mS.m->world->drawData);
mS.m->window.intermediateCanvas->restore();
#ifdef USE_BACKEND_VULKAN
mS.vulkanWindowContext->getBackbufferSurface()->getCanvas()->drawImage(mS.intermediateSurface->makeTemporaryImage(), 0, 0);
mS.ctx->flushAndSubmit();
#elif USE_BACKEND_OPENGL
mS.canvas->drawImage(mS.intermediateSurface->makeTemporaryImage(), 0, 0);
mS.canvas->drawImage(mS.m->window.intermediateSurface->makeTemporaryImage(), 0, 0);
mS.ctx->flushAndSubmit();
#endif
}
@ -616,16 +607,16 @@ void attempt_redraw_and_swap_buffers(MainStruct& mS) {
void regular_draw(MainStruct& mS) {
mS.lastRenderTimePoint = std::chrono::steady_clock::now();
mS.intermediateCanvas->save();
mS.m->draw(mS.intermediateCanvas, mS.m->world, mS.m->world->drawData);
mS.intermediateCanvas->restore();
mS.m->window.intermediateCanvas->save();
mS.m->draw(mS.m->window.intermediateCanvas, mS.m->world, mS.m->world->drawData);
mS.m->window.intermediateCanvas->restore();
#ifdef USE_BACKEND_VULKAN
mS.vulkanWindowContext->getBackbufferSurface()->getCanvas()->drawImage(mS.intermediateSurface->makeTemporaryImage(), 0, 0);
mS.ctx->flushAndSubmit();
mS.vulkanWindowContext->swapBuffers();
#elif USE_BACKEND_OPENGL
mS.canvas->drawImage(mS.intermediateSurface->makeTemporaryImage(), 0, 0);
mS.canvas->drawImage(mS.m->window.intermediateSurface->makeTemporaryImage(), 0, 0);
mS.ctx->flushAndSubmit();
SDL_GL_SwapWindow(mS.window);
#endif