Separate general GUI managing code and global configuration from toolbar UI code

This commit is contained in:
Yousef Khadadeh 2026-03-31 13:17:58 +03:00
parent 2abe7271a8
commit ea35397326
53 changed files with 859 additions and 788 deletions

View file

@ -50,6 +50,8 @@ set(sources "src/main.cpp"
"src/VersionConstants.cpp"
"src/ScaleUpCanvas.cpp"
"src/WorldUndoManager.cpp"
"src/GUIHolder.cpp"
"src/GlobalConfig.cpp"
"src/Bookmarks/BookmarkListItem.cpp"
"src/Bookmarks/BookmarkManager.cpp"
"src/ResourceDisplay/ResourceDisplay.cpp"

View file

@ -64,7 +64,7 @@ void ImageCanvasComponent::draw_download_progress_bar(SkCanvas* canvas, const Dr
p.setStroke(true);
p.setStrokeWidth(10.0f);
p.setStrokeCap(SkPaint::kRound_Cap);
p.setColor4f(drawData.main->toolbar.io->theme->fillColor1);
p.setColor4f(drawData.main->g.gui.io.theme->fillColor1);
p.setAntiAlias(drawData.skiaAA);
Vector2f center = (d.p1 + d.p2) * 0.5f;

View file

@ -38,13 +38,13 @@ CanvasTheme::CanvasTheme(World& w):
{}
void CanvasTheme::server_init_no_file() {
backColor = world.netObjMan.make_obj_direct<BackColor>(world.main.defaultCanvasBackgroundColor);
backColor = world.netObjMan.make_obj_direct<BackColor>(world.main.conf.defaultCanvasBackgroundColor);
set_tool_front_color(world.drawProg);
}
SkColor4f CanvasTheme::get_back_color() const {
if(!backColor)
return SkColor4f{world.main.defaultCanvasBackgroundColor.x(), world.main.defaultCanvasBackgroundColor.y(), world.main.defaultCanvasBackgroundColor.z(), 1.0f};
return SkColor4f{world.main.conf.defaultCanvasBackgroundColor.x(), world.main.conf.defaultCanvasBackgroundColor.y(), world.main.conf.defaultCanvasBackgroundColor.z(), 1.0f};
else
return SkColor4f{backColor->c.x(), backColor->c.y(), backColor->c.z(), 1.0f};
}
@ -91,7 +91,7 @@ void CanvasTheme::save_file(cereal::PortableBinaryOutputArchive& a) const {
}
void CanvasTheme::load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version) {
backColor = world.netObjMan.make_obj_direct<BackColor>(world.main.defaultCanvasBackgroundColor);
backColor = world.netObjMan.make_obj_direct<BackColor>(world.main.conf.defaultCanvasBackgroundColor);
set_tool_front_color(world.drawProg);
if(version < VersionNumber(0, 1, 0))

View file

@ -199,7 +199,7 @@ void ClientData::draw_cursor(SkCanvas* canvas, const DrawData& drawData) const {
p.setColor4f({cursorColor.x(), cursorColor.y(), cursorColor.z(), 0.7f});
canvas->drawCircle(0.0f, 0.0f, 5.0f, p);
SkFont f = drawData.main->toolbar.io->get_font(18.0f);
SkFont f = drawData.main->g.gui.io.get_font(18.0f);
SkFontMetrics metrics;
f.getMetrics(&metrics);
@ -209,7 +209,7 @@ void ClientData::draw_cursor(SkCanvas* canvas, const DrawData& drawData) const {
SkPaint p2(SkColor4f{cursorColor.x(), cursorColor.y(), cursorColor.z(), 0.5f});
canvas->drawSimpleText(displayName.c_str(), displayName.length(), SkTextEncoding::kUTF8, 6.0f, -metrics.fDescent, f, p2);
SkPaint p3(color_mul_alpha(drawData.main->toolbar.io->theme->backColor1, 0.5f));
SkPaint p3(color_mul_alpha(drawData.main->g.gui.io.theme->backColor1, 0.5f));
canvas->drawRoundRect(SkRect::MakeXYWH(6.0f, -bounds.y(), bounds.x(), bounds.y()), 3.0f, 3.0f, p3);
canvas->restore();

View file

@ -49,7 +49,7 @@ void DrawCamera::smooth_move_to(World& w, const CoordSpaceHelper& newCoords, Vec
smoothMove.endUniformZoom = std::max(smoothMove.end.inverseScale.multiply_double((a1 < a2) ? a1 : a2), WorldScalar(1));
smoothMove.occurring = true;
smoothMove.moveTime = (instantJump || w.main.toolbar.jumpTransitionTime <= 0.01f) ? w.main.toolbar.jumpTransitionTime : 0.0f;
smoothMove.moveTime = (instantJump || w.main.conf.jumpTransitionTime <= 0.01f) ? w.main.conf.jumpTransitionTime : 0.0f;
}
void DrawCamera::scale_up(World& w, const WorldScalar& scaleUpAmount) {
@ -64,8 +64,8 @@ void DrawCamera::scale_up(World& w, const WorldScalar& scaleUpAmount) {
void DrawCamera::update_main(World& w) {
if(smoothMove.occurring) {
BezierEasing zoomAnim{w.main.toolbar.jumpTransitionEasing};
float smoothTime = smooth_two_way_time(smoothMove.moveTime, w.main.deltaTime, true, w.main.toolbar.jumpTransitionTime);
BezierEasing zoomAnim{w.main.conf.jumpTransitionEasing};
float smoothTime = smooth_two_way_time(smoothMove.moveTime, w.main.deltaTime, true, w.main.conf.jumpTransitionTime);
float lerpTime;
float rotationLerpTime = zoomAnim(smoothTime);
lerpTime = zoomAnim(smoothTime);
@ -142,7 +142,7 @@ void DrawCamera::input_key_callback(const InputManager::KeyCallbackArgs& key) {
void DrawCamera::input_mouse_button_on_canvas_callback(World& w, const InputManager::MouseButtonCallbackArgs& button) {
if(!smoothMove.occurring && !isTouchTransforming) {
bool newIsAccurateZooming = (w.drawProg.controls.middleClickHeld && w.main.input.pen.isDown && w.main.toolbar.tabletOptions.zoomWhilePenDownAndButtonHeld) || // Hold middle click (pen button assigned to middle click) while pen is down
bool newIsAccurateZooming = (w.drawProg.controls.middleClickHeld && w.main.input.pen.isDown && w.main.conf.tabletOptions.zoomWhilePenDownAndButtonHeld) || // Hold middle click (pen button assigned to middle click) while pen is down
(w.drawProg.controls.middleClickHeld && w.main.input.key(InputManager::KEY_GENERIC_LCTRL).held) || // Hold middle click/pen button while holding control
(w.drawProg.controls.leftClickHeld && w.drawProg.drawTool->get_type() == DrawingProgramToolType::ZOOM); // Hold left click while on zoom tool
if(newIsAccurateZooming && !isAccurateZooming) {
@ -159,7 +159,7 @@ void DrawCamera::input_mouse_button_on_canvas_callback(World& w, const InputMana
void DrawCamera::input_mouse_motion_callback(World& w, const InputManager::MouseMotionCallbackArgs& motion) {
if(!smoothMove.occurring && !isTouchTransforming) {
if(isAccurateZooming && startZoomVal != WorldScalar(0)) {
WorldScalar zoomFactor(std::pow(1.0 + w.main.toolbar.dragZoomSpeed, w.main.toolbar.flipZoomToolDirection ? motion.move.y() : -motion.move.y()));
WorldScalar zoomFactor(std::pow(1.0 + w.main.conf.dragZoomSpeed, w.main.conf.flipZoomToolDirection ? motion.move.y() : -motion.move.y()));
if(zoomFactor < WorldScalar(0.000001))
zoomFactor = WorldScalar(0.000001);
@ -180,7 +180,7 @@ void DrawCamera::input_mouse_motion_callback(World& w, const InputManager::Mouse
void DrawCamera::input_mouse_wheel_callback(World& w, const InputManager::MouseWheelCallbackArgs& wheel) {
if(!smoothMove.occurring && !isTouchTransforming && wheel.tickAmount.y()) {
WorldVec mouseWorldPos = c.from_space(wheel.mousePos);
WorldScalar zoomFactor(1.0 + w.main.toolbar.scrollZoomSpeed);
WorldScalar zoomFactor(1.0 + w.main.conf.scrollZoomSpeed);
if(zoomFactor < WorldScalar(0.000001))
zoomFactor = WorldScalar(0.000001);

View file

@ -328,23 +328,25 @@ void DrawingProgram::toolbar_gui() {
using namespace GUIStuff;
using namespace ElementHelpers;
Toolbar& t = world.main.toolbar;
t.gui.new_id("Drawing Program Toolbar GUI", [&] {
t.gui.element<LayoutElement>("Drawing Program Toolbar GUI", [&] {
GUIManager& gui = world.main.g.gui;
auto& io = gui.io;
gui.new_id("Drawing Program Toolbar GUI", [&] {
gui.element<LayoutElement>("Drawing Program Toolbar GUI", [&] {
CLAY_AUTO_ID({
.layout = {
.sizing = {.width = CLAY_SIZING_FIT(0), .height = CLAY_SIZING_FIT(0)},
.padding = CLAY_PADDING_ALL(static_cast<uint16_t>(t.io->theme->padding1 / 2)),
.childGap = static_cast<uint16_t>(t.io->theme->childGap1 / 2),
.padding = CLAY_PADDING_ALL(static_cast<uint16_t>(io.theme->padding1 / 2)),
.childGap = static_cast<uint16_t>(io.theme->childGap1 / 2),
.childAlignment = { .x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_TOP},
.layoutDirection = CLAY_TOP_TO_BOTTOM
},
.backgroundColor = convert_vec4<Clay_Color>(t.io->theme->backColor1),
.cornerRadius = CLAY_CORNER_RADIUS(t.io->theme->windowCorners1)
.backgroundColor = convert_vec4<Clay_Color>(io.theme->backColor1),
.cornerRadius = CLAY_CORNER_RADIUS(io.theme->windowCorners1)
}) {
auto tool_button = [&](const char* id, const std::string& svgPath, DrawingProgramToolType toolType) {
svg_icon_button(t.gui, id, svgPath, {
svg_icon_button(gui, id, svgPath, {
.drawType = SelectableButton::DrawType::TRANSPARENT_ALL,
.isSelected = drawTool->get_type() == toolType,
.onClick = [&, toolType] {
@ -367,7 +369,7 @@ void DrawingProgram::toolbar_gui() {
tool_button("Pan Canvas Toolbar Button", "data/icons/hand.svg", DrawingProgramToolType::PAN);
std::shared_ptr<double> oldRotationAngle = std::make_shared<double>(world.drawData.cam.c.rotation);
t.gui.element<RotateWheel>("Canvas Rotate Wheel", &world.drawData.cam.c.rotation, [&, oldRotationAngle] {
gui.element<RotateWheel>("Canvas Rotate Wheel", &world.drawData.cam.c.rotation, [&, oldRotationAngle] {
world.drawData.cam.c.rotate_about(world.drawData.cam.c.from_space(world.main.window.size.cast<float>() * 0.5f), world.drawData.cam.c.rotation - *oldRotationAngle);
*oldRotationAngle = world.drawData.cam.c.rotation;
});
@ -377,7 +379,9 @@ void DrawingProgram::toolbar_gui() {
}
void DrawingProgram::popup_menu_action_button(const char* id, const char* text, const std::function<void()>& onClick) {
GUIStuff::ElementHelpers::text_button(world.main.toolbar.gui, id, text, {
GUIStuff::GUIManager& gui = world.main.g.gui;
GUIStuff::ElementHelpers::text_button(gui, id, text, {
.drawType = GUIStuff::SelectableButton::DrawType::TRANSPARENT_ALL,
.wide = true,
.onClick = onClick
@ -390,8 +394,11 @@ void DrawingProgram::selection_action_menu(Vector2f popupPos) {
using namespace ElementHelpers;
Toolbar& t = world.main.toolbar;
t.gui.element<PositionAdjustingPopupMenu>("Selection popup menu", popupPos, [&, popupPos] {
text_label_light(t.gui, "Selection menu");
GUIStuff::GUIManager& gui = world.main.g.gui;
auto& io = gui.io;
gui.element<PositionAdjustingPopupMenu>("Selection popup menu", popupPos, [&, popupPos] {
text_label_light(gui, "Selection menu");
popup_menu_action_button("Paste", "Paste", [&] {
selection.deselect_all();
selection.paste_clipboard(popupPos * t.final_gui_scale());
@ -423,7 +430,10 @@ void DrawingProgram::selection_action_menu(Vector2f popupPos) {
void DrawingProgram::right_click_popup_gui(Vector2f popupPos) {
Toolbar& t = world.main.toolbar;
t.gui.new_id("Drawing Program right click GUI", [&] {
GUIStuff::GUIManager& gui = world.main.g.gui;
auto& io = gui.io;
gui.new_id("Drawing Program right click GUI", [&] {
drawTool->right_click_popup_gui(popupPos);
});
}
@ -432,18 +442,21 @@ void DrawingProgram::tool_options_gui() {
using namespace GUIStuff;
Toolbar& t = world.main.toolbar;
GUIStuff::GUIManager& gui = world.main.g.gui;
auto& io = gui.io;
float minGUIWidth = drawTool->get_type() == DrawingProgramToolType::SCREENSHOT ? 300 : 200;
t.gui.element<LayoutElement>("Drawing program tool options gui", [&] {
gui.element<LayoutElement>("Drawing program tool options gui", [&] {
CLAY_AUTO_ID({
.layout = {
.sizing = {.width = CLAY_SIZING_FIT(minGUIWidth), .height = CLAY_SIZING_FIT(0)},
.padding = CLAY_PADDING_ALL(t.io->theme->padding1),
.childGap = t.io->theme->childGap1,
.padding = CLAY_PADDING_ALL(io.theme->padding1),
.childGap = io.theme->childGap1,
.childAlignment = { .x = CLAY_ALIGN_X_LEFT, .y = CLAY_ALIGN_Y_TOP},
.layoutDirection = CLAY_TOP_TO_BOTTOM
},
.backgroundColor = convert_vec4<Clay_Color>(t.io->theme->backColor1),
.cornerRadius = CLAY_CORNER_RADIUS(t.io->theme->windowCorners1)
.backgroundColor = convert_vec4<Clay_Color>(io.theme->backColor1),
.cornerRadius = CLAY_CORNER_RADIUS(io.theme->windowCorners1)
}) {
drawTool->gui_toolbox();
}
@ -514,7 +527,7 @@ void DrawingProgram::switch_to_tool_ptr(std::unique_ptr<DrawingProgramToolBase>
drawTool->switch_tool(newTool->get_type());
drawTool = std::move(newTool);
world.main.toolbar.rightClickPopupLocation = std::nullopt;
world.main.toolbar.gui.set_to_layout();
world.main.g.gui.set_to_layout();
}
void DrawingProgram::switch_to_tool(DrawingProgramToolType newToolType, bool force) {

View file

@ -35,21 +35,22 @@ void DrawingProgramSelection::selection_gui() {
using namespace GUIStuff;
using namespace ElementHelpers;
auto& t = drawP.world.main.toolbar;
t.gui.new_id("general selection gui", [&] {
text_label(t.gui, "Select from:");
radio_button_selector(t.gui, "layer selector", &drawP.controls.layerSelector, {
auto& gui = drawP.world.main.g.gui;
gui.new_id("general selection gui", [&] {
text_label(gui, "Select from:");
radio_button_selector(gui, "layer selector", &drawP.controls.layerSelector, {
{"Layer being edited", DrawingProgramLayerManager::LayerSelector::LAYER_BEING_EDITED},
{"All visible layers", DrawingProgramLayerManager::LayerSelector::ALL_VISIBLE_LAYERS}
});
if(is_something_selected()) {
left_to_right_line_layout(t.gui, [&]() {
//if(t.gui.color_button_big("Stroke Color Button", &strokeColorChangeData.newColor, &strokeColorChangeData.newColor == t.colorRight)) {
left_to_right_line_layout(gui, [&]() {
//if(gui.color_button_big("Stroke Color Button", &strokeColorChangeData.newColor, &strokeColorChangeData.newColor == t.colorRight)) {
// if(strokeColorChangeData.newColor.w() == 0.0f)
// strokeColorChangeData.newColor.w() = 1.0f;
// t.color_selector_right(&strokeColorChangeData.newColor == t.colorRight ? nullptr : &strokeColorChangeData.newColor);
//}
text_label(t.gui, "Stroke Color");
text_label(gui, "Stroke Color");
});
update_selection_stroke_color();
}

View file

@ -81,7 +81,7 @@ void ToolConfiguration::print_relative_width_fail_message(RelativeWidthFailCode
}
void ToolConfiguration::relative_width_gui(DrawingProgram& drawP, const char* label) {
auto& gui = drawP.world.main.toolbar.gui;
auto& gui = drawP.world.main.g.gui;
auto& lockedCameraScale = drawP.controls.lockedCameraScale;
GUIStuff::ElementHelpers::slider_scalar_field(gui, "relstrokewidth", label, &get_stroke_size_relative_width_ref(drawP.drawTool->get_type()), 3.0f, 40.0f);
GUIStuff::ElementHelpers::text_button(gui, "lock brush size", lockedCameraScale.has_value() ? "Unlock Size" : "Lock Size to Zoom", {

View file

@ -41,7 +41,7 @@ void BrushTool::input_mouse_button_on_canvas_callback(const InputManager::MouseB
if(drawP.world.main.input.pen.isDown) {
penWidth = drawP.world.main.input.pen.pressure;
if(penWidth != 0.0f) {
float brushMinSize = drawP.world.main.toolbar.tabletOptions.brushMinimumSize;
float brushMinSize = drawP.world.main.conf.tabletOptions.brushMinimumSize;
penWidth = brushMinSize + penWidth * (1.0f - brushMinSize);
}
}
@ -124,7 +124,7 @@ void BrushTool::input_pen_axis_callback(const InputManager::PenAxisCallbackArgs&
if(axis.axis == SDL_PEN_AXIS_PRESSURE) {
penWidth = axis.value;
if(penWidth != 0.0f) {
float brushMinSize = drawP.world.main.toolbar.tabletOptions.brushMinimumSize;
float brushMinSize = drawP.world.main.conf.tabletOptions.brushMinimumSize;
penWidth = brushMinSize + penWidth * (1.0f - brushMinSize);
}
}
@ -172,9 +172,11 @@ void BrushTool::gui_toolbox() {
using namespace ElementHelpers;
Toolbar& t = drawP.world.main.toolbar;
t.gui.new_id("brush tool", [&] {
text_label_centered(t.gui, "Brush");
checkbox_boolean_field(t.gui, "hasroundcaps", "Round Caps", &drawP.world.main.toolConfig.brush.hasRoundCaps);
auto& gui = drawP.world.main.g.gui;
gui.new_id("brush tool", [&] {
text_label_centered(gui, "Brush");
checkbox_boolean_field(gui, "hasroundcaps", "Round Caps", &drawP.world.main.toolConfig.brush.hasRoundCaps);
drawP.world.main.toolConfig.relative_width_gui(drawP, "Size");
});
}

View file

@ -30,11 +30,13 @@ void EditTool::gui_toolbox() {
using namespace ElementHelpers;
Toolbar& t = drawP.world.main.toolbar;
auto& gui = drawP.world.main.g.gui;
if(objInfoBeingEdited)
compEditTool->edit_gui(objInfoBeingEdited);
else {
t.gui.new_id("edit tool", [&] {
text_label_centered(t.gui, "Edit");
gui.new_id("edit tool", [&] {
text_label_centered(gui, "Edit");
});
}
}

View file

@ -16,12 +16,13 @@ void BrushEditTool::edit_gui(CanvasComponentContainer::ObjInfo* comp) {
using namespace ElementHelpers;
Toolbar& t = drawP.world.main.toolbar;
t.gui.new_id("edit tool brush", [&] {
text_label_centered(t.gui, "Edit Brush Stroke");
left_to_right_line_layout(t.gui, [&]() {
//if(t.gui.color_button_big("Outline Color", &a.d.color, &a.d.color == t.colorRight))
auto& gui = drawP.world.main.g.gui;
gui.new_id("edit tool brush", [&] {
text_label_centered(gui, "Edit Brush Stroke");
left_to_right_line_layout(gui, [&]() {
//if(gui.color_button_big("Outline Color", &a.d.color, &a.d.color == t.colorRight))
// t.color_selector_right(&a.d.color == t.colorRight ? nullptr : &a.d.color);
text_label(t.gui, "Outline Color");
text_label(gui, "Outline Color");
});
});
}

View file

@ -21,28 +21,29 @@ void EllipseDrawEditTool::edit_gui(CanvasComponentContainer::ObjInfo* comp) {
using namespace ElementHelpers;
auto& a = static_cast<EllipseCanvasComponent&>(comp->obj->get_comp());
auto& gui = drawP.world.main.g.gui;
Toolbar& t = drawP.world.main.toolbar;
t.gui.new_id("edit tool ellipse", [&] {
text_label_centered(t.gui, "Edit Ellipse");
radio_button_selector(t.gui, "Fill selector", &a.d.fillStrokeMode, {
gui.new_id("edit tool ellipse", [&] {
text_label_centered(gui, "Edit Ellipse");
radio_button_selector(gui, "Fill selector", &a.d.fillStrokeMode, {
{"Fill only", 0},
{"Outline only", 1},
{"Fill and outline", 2}
});
if(a.d.fillStrokeMode == 0 || a.d.fillStrokeMode == 2) {
left_to_right_line_layout(t.gui, [&] {
//if(t.gui.color_button_big("Fill Color", &a.d.fillColor, &a.d.fillColor == t.colorRight))
left_to_right_line_layout(gui, [&] {
//if(gui.color_button_big("Fill Color", &a.d.fillColor, &a.d.fillColor == t.colorRight))
// t.color_selector_right(&a.d.fillColor == t.colorRight ? nullptr : &a.d.fillColor);
text_label(t.gui, "Fill Color");
text_label(gui, "Fill Color");
});
}
if(a.d.fillStrokeMode == 1 || a.d.fillStrokeMode == 2) {
slider_scalar_field(t.gui, "relstrokewidth", "Outline Size", &a.d.strokeWidth, 3.0f, 40.0f);
left_to_right_line_layout(t.gui, [&] {
//if(t.gui.color_button_big("Outline Color", &a.d.strokeColor, &a.d.strokeColor == t.colorRight))
slider_scalar_field(gui, "relstrokewidth", "Outline Size", &a.d.strokeWidth, 3.0f, 40.0f);
left_to_right_line_layout(gui, [&] {
//if(gui.color_button_big("Outline Color", &a.d.strokeColor, &a.d.strokeColor == t.colorRight))
// t.color_selector_right(&a.d.strokeColor == t.colorRight ? nullptr : &a.d.strokeColor);
text_label(t.gui, "Outline Color");
text_label(gui, "Outline Color");
});
}
});

View file

@ -51,13 +51,14 @@ void ImageEditTool::edit_gui(CanvasComponentContainer::ObjInfo* comp) {
ImageCanvasComponent& a = static_cast<ImageCanvasComponent&>(comp->obj->get_comp());
Toolbar& t = drawP.world.main.toolbar;
t.gui.new_id("edit tool image", [&] {
text_label_centered(t.gui, "File Properties");
auto& gui = drawP.world.main.g.gui;
gui.new_id("edit tool image", [&] {
text_label_centered(gui, "File Properties");
auto resourceData = drawP.world.netObjMan.get_obj_temporary_ref_from_id<ResourceData>(a.d.imageID);
if(resourceData) {
text_label(t.gui, "Name: " + resourceData->name);
text_button(t.gui, "file download", "Download file", {
text_label(gui, "Name: " + resourceData->name);
text_button(gui, "file download", "Download file", {
.wide = true,
.onClick = [&] {
#ifdef __EMSCRIPTEN__
@ -74,6 +75,6 @@ void ImageEditTool::edit_gui(CanvasComponentContainer::ObjInfo* comp) {
});
}
else
text_label_centered(t.gui, "Loading resource...");
text_label_centered(gui, "Loading resource...");
});
}

View file

@ -19,27 +19,28 @@ void RectDrawEditTool::edit_gui(CanvasComponentContainer::ObjInfo* comp) {
auto& a = static_cast<RectangleCanvasComponent&>(comp->obj->get_comp());
Toolbar& t = drawP.world.main.toolbar;
t.gui.new_id("edit tool rectangle", [&] {
text_label_centered(t.gui, "Edit Rectangle");
slider_scalar_field(t.gui, "relradiuswidth", "Corner Radius", &a.d.cornerRadius, 0.0f, 40.0f);
radio_button_selector(t.gui, "Fill selector", &a.d.fillStrokeMode, {
auto& gui = drawP.world.main.g.gui;
gui.new_id("edit tool rectangle", [&] {
text_label_centered(gui, "Edit Rectangle");
slider_scalar_field(gui, "relradiuswidth", "Corner Radius", &a.d.cornerRadius, 0.0f, 40.0f);
radio_button_selector(gui, "Fill selector", &a.d.fillStrokeMode, {
{"Fill only", 0},
{"Outline only", 1},
{"Fill and outline", 2}
});
if(a.d.fillStrokeMode == 0 || a.d.fillStrokeMode == 2) {
left_to_right_line_layout(t.gui, [&] {
//if(t.gui.color_button_big("Fill Color", &a.d.fillColor, &a.d.fillColor == t.colorRight))
left_to_right_line_layout(gui, [&] {
//if(gui.color_button_big("Fill Color", &a.d.fillColor, &a.d.fillColor == t.colorRight))
// t.color_selector_right(&a.d.fillColor == t.colorRight ? nullptr : &a.d.fillColor);
text_label(t.gui, "Fill Color");
text_label(gui, "Fill Color");
});
}
if(a.d.fillStrokeMode == 1 || a.d.fillStrokeMode == 2) {
slider_scalar_field(t.gui, "relstrokewidth", "Outline Size", &a.d.strokeWidth, 3.0f, 40.0f);
left_to_right_line_layout(t.gui, [&] {
//if(t.gui.color_button_big("Outline Color", &a.d.strokeColor, &a.d.strokeColor == t.colorRight))
slider_scalar_field(gui, "relstrokewidth", "Outline Size", &a.d.strokeWidth, 3.0f, 40.0f);
left_to_right_line_layout(gui, [&] {
//if(gui.color_button_big("Outline Color", &a.d.strokeColor, &a.d.strokeColor == t.colorRight))
// t.color_selector_right(&a.d.strokeColor == t.colorRight ? nullptr : &a.d.strokeColor);
text_label(t.gui, "Outline Color");
text_label(gui, "Outline Color");
});
}
});

View file

@ -30,43 +30,44 @@ void TextBoxEditTool::edit_gui(CanvasComponentContainer::ObjInfo* comp) {
auto& a = static_cast<TextBoxCanvasComponent&>(comp->obj->get_comp());
Toolbar& t = drawP.world.main.toolbar;
auto& gui = drawP.world.main.g.gui;
auto& currentMods = *currentModsPtr;
t.gui.new_id("edit tool text", [&] {
text_label_centered(t.gui, "Edit Text");
gui.new_id("edit tool text", [&] {
text_label_centered(gui, "Edit Text");
left_to_right_line_layout(t.gui, [&] {
text_label(t.gui, "Font");
//if(t.gui.font_picker("font picker", &newFontName)) {
left_to_right_line_layout(gui, [&] {
text_label(gui, "Font");
//if(gui.font_picker("font picker", &newFontName)) {
// currentMods[TextStyleModifier::ModifierType::FONT_FAMILIES] = std::make_shared<FontFamiliesTextStyleModifier>(std::vector<SkString>{SkString{newFontName.c_str(), newFontName.size()}});
// add_undo_if_selecting_area(a, [&]() {a.textBox->set_text_style_modifier_between(a.cursor->selectionBeginPos, a.cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::FONT_FAMILIES]);});
//}
});
//left_to_right_line_centered_layout(t.gui, [&] {
//left_to_right_line_centered_layout(gui, [&] {
// if(svg_icon_button("Bold button", "data/icons/RemixIcon/bold.svg", newIsBold)) {
// newIsBold = !newIsBold;
// currentMods[TextStyleModifier::ModifierType::WEIGHT] = std::make_shared<WeightTextStyleModifier>(newIsBold ? SkFontStyle::Weight::kBold_Weight : SkFontStyle::Weight::kNormal_Weight);
// add_undo_if_selecting_area(a, [&]() {a.textBox->set_text_style_modifier_between(a.cursor->selectionBeginPos, a.cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::WEIGHT]);});
// }
// if(t.gui.svg_icon_button("Italic button", "data/icons/RemixIcon/italic.svg", newIsItalic)) {
// if(gui.svg_icon_button("Italic button", "data/icons/RemixIcon/italic.svg", newIsItalic)) {
// newIsItalic = !newIsItalic;
// currentMods[TextStyleModifier::ModifierType::SLANT] = std::make_shared<SlantTextStyleModifier>(newIsItalic ? SkFontStyle::Slant::kItalic_Slant : SkFontStyle::Slant::kUpright_Slant);
// add_undo_if_selecting_area(a, [&]() {a.textBox->set_text_style_modifier_between(a.cursor->selectionBeginPos, a.cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::SLANT]);});
// }
// bool decorationEdited = false;
// if(t.gui.svg_icon_button("Underline button", "data/icons/RemixIcon/underline.svg", newIsUnderlined)) {
// if(gui.svg_icon_button("Underline button", "data/icons/RemixIcon/underline.svg", newIsUnderlined)) {
// newIsUnderlined = !newIsUnderlined;
// decorationEdited = true;
// }
// if(t.gui.svg_icon_button("Strikethrough button", "data/icons/RemixIcon/strikethrough.svg", newIsLinethrough)) {
// if(gui.svg_icon_button("Strikethrough button", "data/icons/RemixIcon/strikethrough.svg", newIsLinethrough)) {
// newIsLinethrough = !newIsLinethrough;
// decorationEdited = true;
// }
// if(t.gui.svg_icon_button("Overline button", "data/icons/RemixIcon/overline.svg", newIsOverline)) {
// if(gui.svg_icon_button("Overline button", "data/icons/RemixIcon/overline.svg", newIsOverline)) {
// newIsOverline = !newIsOverline;
// decorationEdited = true;
// }
@ -76,22 +77,22 @@ void TextBoxEditTool::edit_gui(CanvasComponentContainer::ObjInfo* comp) {
// }
//});
//t.gui.left_to_right_line_centered_layout([&]() {
// if(t.gui.svg_icon_button("Align left button", "data/icons/RemixIcon/align-left.svg", currentPStyle.textAlignment == skia::textlayout::TextAlign::kLeft))
//gui.left_to_right_line_centered_layout([&]() {
// if(gui.svg_icon_button("Align left button", "data/icons/RemixIcon/align-left.svg", currentPStyle.textAlignment == skia::textlayout::TextAlign::kLeft))
// add_undo([&](){a.textBox->set_text_alignment_between(a.cursor->selectionBeginPos.fParagraphIndex, a.cursor->selectionEndPos.fParagraphIndex, skia::textlayout::TextAlign::kLeft);});
// if(t.gui.svg_icon_button("Align center button", "data/icons/RemixIcon/align-center.svg", currentPStyle.textAlignment == skia::textlayout::TextAlign::kCenter))
// if(gui.svg_icon_button("Align center button", "data/icons/RemixIcon/align-center.svg", currentPStyle.textAlignment == skia::textlayout::TextAlign::kCenter))
// add_undo([&](){a.textBox->set_text_alignment_between(a.cursor->selectionBeginPos.fParagraphIndex, a.cursor->selectionEndPos.fParagraphIndex, skia::textlayout::TextAlign::kCenter);});
// if(t.gui.svg_icon_button("Align right button", "data/icons/RemixIcon/align-right.svg", currentPStyle.textAlignment == skia::textlayout::TextAlign::kRight))
// if(gui.svg_icon_button("Align right button", "data/icons/RemixIcon/align-right.svg", currentPStyle.textAlignment == skia::textlayout::TextAlign::kRight))
// add_undo([&](){a.textBox->set_text_alignment_between(a.cursor->selectionBeginPos.fParagraphIndex, a.cursor->selectionEndPos.fParagraphIndex, skia::textlayout::TextAlign::kRight);});
// if(t.gui.svg_icon_button("Align justify button", "data/icons/RemixIcon/align-justify.svg", currentPStyle.textAlignment == skia::textlayout::TextAlign::kJustify))
// if(gui.svg_icon_button("Align justify button", "data/icons/RemixIcon/align-justify.svg", currentPStyle.textAlignment == skia::textlayout::TextAlign::kJustify))
// add_undo([&](){a.textBox->set_text_alignment_between(a.cursor->selectionBeginPos.fParagraphIndex, a.cursor->selectionEndPos.fParagraphIndex, skia::textlayout::TextAlign::kJustify);});
// if(t.gui.svg_icon_button("Text direction left", "data/icons/RemixIcon/text-direction-l.svg", currentPStyle.textDirection == skia::textlayout::TextDirection::kLtr))
// if(gui.svg_icon_button("Text direction left", "data/icons/RemixIcon/text-direction-l.svg", currentPStyle.textDirection == skia::textlayout::TextDirection::kLtr))
// add_undo([&](){a.textBox->set_text_direction_between(a.cursor->selectionBeginPos.fParagraphIndex, a.cursor->selectionEndPos.fParagraphIndex, skia::textlayout::TextDirection::kLtr);});
// if(t.gui.svg_icon_button("Text direction right", "data/icons/RemixIcon/text-direction-r.svg", currentPStyle.textDirection == skia::textlayout::TextDirection::kRtl))
// if(gui.svg_icon_button("Text direction right", "data/icons/RemixIcon/text-direction-r.svg", currentPStyle.textDirection == skia::textlayout::TextDirection::kRtl))
// add_undo([&](){a.textBox->set_text_direction_between(a.cursor->selectionBeginPos.fParagraphIndex, a.cursor->selectionEndPos.fParagraphIndex, skia::textlayout::TextDirection::kRtl);});
//});
//if(t.gui.slider_scalar_field<uint32_t>("Font Size Slider", "Font Size", &newFontSize, 3, 100)) {
//if(gui.slider_scalar_field<uint32_t>("Font Size Slider", "Font Size", &newFontSize, 3, 100)) {
// hold_undo_data("Font Size", a);
// currentMods[TextStyleModifier::ModifierType::SIZE] = std::make_shared<SizeTextStyleModifier>(newFontSize);
// a.textBox->set_text_style_modifier_between(a.cursor->selectionBeginPos, a.cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::SIZE]);
@ -100,10 +101,10 @@ void TextBoxEditTool::edit_gui(CanvasComponentContainer::ObjInfo* comp) {
// release_undo_data("Font Size");
//// Text color
//t.gui.left_to_right_line_layout([&]() {
// if(t.gui.color_button_big("Text Color", &newTextColor, &newTextColor == t.colorRight))
//gui.left_to_right_line_layout([&]() {
// if(gui.color_button_big("Text Color", &newTextColor, &newTextColor == t.colorRight))
// t.color_selector_right(&newTextColor == t.colorRight ? nullptr : &newTextColor);
// t.gui.text_label("Text Color");
// gui.text_label("Text Color");
//});
//if(&newTextColor == t.colorRight)
@ -119,8 +120,8 @@ void TextBoxEditTool::edit_gui(CanvasComponentContainer::ObjInfo* comp) {
//// Highlight color
//t.gui.left_to_right_line_layout([&]() {
// if(t.gui.color_button_big("Highlight Color", &newHighlightColor, &newHighlightColor == t.colorRight)) {
//gui.left_to_right_line_layout([&]() {
// if(gui.color_button_big("Highlight Color", &newHighlightColor, &newHighlightColor == t.colorRight)) {
// if(newHighlightColor.w() == 0.0f) { // Make highlight appear when the button is pressed
// newHighlightColor.w() = 1.0f;
// currentMods[TextStyleModifier::ModifierType::HIGHLIGHT_COLOR] = std::make_shared<HighlightColorTextStyleModifier>(newHighlightColor);
@ -129,13 +130,13 @@ void TextBoxEditTool::edit_gui(CanvasComponentContainer::ObjInfo* comp) {
// t.color_selector_right(&newHighlightColor == t.colorRight ? nullptr : &newHighlightColor);
// }
// if(newHighlightColor.w() != 0.0f) {
// if(t.gui.svg_icon_button("Remove Highlight Color", "data/icons/close.svg")) {
// if(gui.svg_icon_button("Remove Highlight Color", "data/icons/close.svg")) {
// newHighlightColor = {0.0f, 0.0f, 0.0f, 0.0f};
// currentMods[TextStyleModifier::ModifierType::HIGHLIGHT_COLOR] = std::make_shared<HighlightColorTextStyleModifier>(newHighlightColor);
// add_undo_if_selecting_area(a, [&]() {a.textBox->set_text_style_modifier_between(a.cursor->selectionBeginPos, a.cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::HIGHLIGHT_COLOR]);});
// }
// }
// t.gui.text_label("Highlight Color");
// gui.text_label("Highlight Color");
//});
//if(&newHighlightColor == t.colorRight)
@ -200,10 +201,11 @@ void TextBoxEditTool::right_click_popup_gui(CanvasComponentContainer::ObjInfo* c
using namespace ElementHelpers;
Toolbar& t = drawP.world.main.toolbar;
auto& gui = drawP.world.main.g.gui;
auto& a = static_cast<TextBoxCanvasComponent&>(comp->obj->get_comp());
t.gui.element<PositionAdjustingPopupMenu>("Text popup menu", popupPos, [&, popupPos] {
text_label_light(t.gui, "Text menu");
gui.element<PositionAdjustingPopupMenu>("Text popup menu", popupPos, [&, popupPos] {
text_label_light(gui, "Text menu");
InputManager& input = drawP.world.main.input;
drawP.popup_menu_action_button("Paste", "Paste", [&] {
input.call_text_paste(true);

View file

@ -25,11 +25,12 @@ void EllipseDrawTool::gui_toolbox() {
using namespace ElementHelpers;
Toolbar& t = drawP.world.main.toolbar;
auto& gui = drawP.world.main.g.gui;
auto& toolConfig = drawP.world.main.toolConfig;
auto& fillStrokeMode = toolConfig.ellipseDraw.fillStrokeMode;
t.gui.new_id("ellipse draw tool", [&] {
text_label_centered(t.gui, "Draw Ellipse");
radio_button_selector(t.gui, "fill type", &fillStrokeMode, {
gui.new_id("ellipse draw tool", [&] {
text_label_centered(gui, "Draw Ellipse");
radio_button_selector(gui, "fill type", &fillStrokeMode, {
{"Fill only", 0},
{"Outline only", 1},
{"Fill and Outline", 2}

View file

@ -21,11 +21,12 @@ void EraserTool::gui_toolbox() {
using namespace ElementHelpers;
Toolbar& t = drawP.world.main.toolbar;
t.gui.new_id("eraser tool", [&] {
text_label_centered(t.gui, "Eraser");
auto& gui = drawP.world.main.g.gui;
gui.new_id("eraser tool", [&] {
text_label_centered(gui, "Eraser");
drawP.world.main.toolConfig.relative_width_gui(drawP, "Size");
text_label(t.gui, "Erase from:");
radio_button_selector(t.gui, "layer selector", &drawP.controls.layerSelector, {
text_label(gui, "Erase from:");
radio_button_selector(gui, "layer selector", &drawP.controls.layerSelector, {
{"Layer being edited", DrawingProgramLayerManager::LayerSelector::LAYER_BEING_EDITED},
{"All visible layers", DrawingProgramLayerManager::LayerSelector::ALL_VISIBLE_LAYERS}
});

View file

@ -31,11 +31,12 @@ void EyeDropperTool::gui_toolbox() {
using namespace ElementHelpers;
Toolbar& t = drawP.world.main.toolbar;
auto& gui = drawP.world.main.g.gui;
auto& selectingStrokeColor = drawP.world.main.toolConfig.eyeDropper.selectingStrokeColor;
t.gui.new_id("Color select tool", [&] {
text_label_centered(t.gui, "Color Select");
gui.new_id("Color select tool", [&] {
text_label_centered(gui, "Color Select");
radio_button_selector<bool>(t.gui, "Stroke type", &selectingStrokeColor, {
radio_button_selector<bool>(gui, "Stroke type", &selectingStrokeColor, {
{"Stroke Color", true},
{"Fill Color", false}
});

View file

@ -118,14 +118,16 @@ void GridModifyTool::gui_toolbox() {
using namespace ElementHelpers;
Toolbar& t = drawP.world.main.toolbar;
t.gui.new_id("Grid modify tool", [&] {
text_label_centered(t.gui, "Edit Grid");
auto& gui = drawP.world.main.g.gui;
gui.new_id("Grid modify tool", [&] {
text_label_centered(gui, "Edit Grid");
NetworkingObjects::NetObjTemporaryPtr<WorldGrid> gLock = grid.lock();
if(gLock) {
WorldGrid& g = *gLock;
input_text_field(t.gui, "grid name", "Name", &g.name);
checkbox_boolean_field(t.gui, "Visible", "Visible", &g.visible);
checkbox_boolean_field(t.gui, "Display in Front", "Display in front of canvas", &g.displayInFront);
input_text_field(gui, "grid name", "Name", &g.name);
checkbox_boolean_field(gui, "Visible", "Visible", &g.visible);
checkbox_boolean_field(gui, "Display in Front", "Display in front of canvas", &g.displayInFront);
size_t typeSelected = static_cast<size_t>(g.gridType);
std::vector<std::string> listOfGridTypes = {
"Circle Points",
@ -133,25 +135,25 @@ void GridModifyTool::gui_toolbox() {
"Square Lines",
"Horizontal Lines"
};
left_to_right_line_layout(t.gui, [&]() {
text_label(t.gui, "Type");
t.gui.element<DropDown<size_t>>("filepicker select type", &typeSelected, listOfGridTypes);
left_to_right_line_layout(gui, [&]() {
text_label(gui, "Type");
gui.element<DropDown<size_t>>("filepicker select type", &typeSelected, listOfGridTypes);
});
g.gridType = static_cast<WorldGrid::GridType>(typeSelected);
uint32_t sDiv = g.subdivisions;
input_scalar_field<uint32_t>(t.gui, "Subdivisions", "Subdivisions", &sDiv, 1, 10);
input_scalar_field<uint32_t>(gui, "Subdivisions", "Subdivisions", &sDiv, 1, 10);
g.set_subdivisions(sDiv);
bool divOut = g.removeDivisionsOutwards;
checkbox_boolean_field(t.gui, "Subdivide outwards", "Subdivide when zooming out", &divOut);
checkbox_boolean_field(gui, "Subdivide outwards", "Subdivide when zooming out", &divOut);
g.set_remove_divisions_outwards(divOut);
left_to_right_line_layout(t.gui, [&]() {
//if(t.gui.color_button_big("Grid Color", &g.color, &g.color == t.colorRight))
left_to_right_line_layout(gui, [&]() {
//if(gui.color_button_big("Grid Color", &g.color, &g.color == t.colorRight))
// t.color_selector_right(&g.color == t.colorRight ? nullptr : &g.color);
text_label(t.gui, "Grid Color");
text_label(gui, "Grid Color");
});
bool bounded = g.bounds.has_value();
bool prevBoundedValue = bounded;
checkbox_boolean_field(t.gui, "Bounded", "Bounded", &bounded);
checkbox_boolean_field(gui, "Bounded", "Bounded", &bounded);
if(bounded && !prevBoundedValue) {
SCollision::AABB<WorldScalar> newBounds;
newBounds.min = g.offset - drawP.world.drawData.cam.c.dir_from_space(drawP.world.main.window.size.cast<float>() * 0.3f);
@ -160,7 +162,7 @@ void GridModifyTool::gui_toolbox() {
}
else if(!bounded && prevBoundedValue)
g.bounds = std::nullopt;
checkbox_boolean_field(t.gui, "Show Coordinates", "Show Coordinates (visible\nwhen canvas isn't rotated)", &g.showCoordinates);
checkbox_boolean_field(gui, "Show Coordinates", "Show Coordinates (visible\nwhen canvas isn't rotated)", &g.showCoordinates);
}
});
}

View file

@ -42,8 +42,9 @@ DrawingProgramToolType LassoSelectTool::get_type() {
void LassoSelectTool::gui_toolbox() {
auto& t = drawP.world.main.toolbar;
t.gui.new_id("lasso select tool", [&] {
GUIStuff::ElementHelpers::text_label_centered(t.gui, "Lasso Select");
auto& gui = drawP.world.main.g.gui;
gui.new_id("lasso select tool", [&] {
GUIStuff::ElementHelpers::text_label_centered(gui, "Lasso Select");
drawP.selection.selection_gui();
});
}

View file

@ -23,11 +23,12 @@ void LineDrawTool::gui_toolbox() {
using namespace GUIStuff;
using namespace ElementHelpers;
Toolbar& t = drawP.world.main.toolbar;
auto& gui = drawP.world.main.g.gui;
auto& toolConfig = drawP.world.main.toolConfig;
t.gui.new_id("rect draw tool", [&] {
text_label_centered(t.gui, "Draw Line");
gui.new_id("rect draw tool", [&] {
text_label_centered(gui, "Draw Line");
toolConfig.relative_width_gui(drawP, "Size");
checkbox_boolean_field(t.gui, "hasroundcaps", "Round Caps", &toolConfig.lineDraw.hasRoundCaps);
checkbox_boolean_field(gui, "hasroundcaps", "Round Caps", &toolConfig.lineDraw.hasRoundCaps);
});
}

View file

@ -18,8 +18,9 @@ DrawingProgramToolType PanCanvasTool::get_type() {
void PanCanvasTool::gui_toolbox() {
Toolbar& t = drawP.world.main.toolbar;
t.gui.new_id("Pan canvas tool", [&] {
GUIStuff::ElementHelpers::text_label_centered(t.gui, "Pan tool");
auto& gui = drawP.world.main.g.gui;
gui.new_id("Pan canvas tool", [&] {
GUIStuff::ElementHelpers::text_label_centered(gui, "Pan tool");
});
}

View file

@ -23,13 +23,14 @@ void RectDrawTool::gui_toolbox() {
using namespace ElementHelpers;
Toolbar& t = drawP.world.main.toolbar;
auto& gui = drawP.world.main.g.gui;
auto& toolConfig = drawP.world.main.toolConfig;
auto& fillStrokeMode = toolConfig.rectDraw.fillStrokeMode;
auto& relativeRadiusWidth = toolConfig.rectDraw.relativeRadiusWidth;
t.gui.new_id("rect draw tool", [&] {
text_label_centered(t.gui, "Draw Rectangle");
slider_scalar_field(t.gui, "relradiuswidth", "Corner Radius", &relativeRadiusWidth, 0.0f, 40.0f);
radio_button_selector(t.gui, "fill type", &fillStrokeMode, {
gui.new_id("rect draw tool", [&] {
text_label_centered(gui, "Draw Rectangle");
slider_scalar_field(gui, "relradiuswidth", "Corner Radius", &relativeRadiusWidth, 0.0f, 40.0f);
radio_button_selector(gui, "fill type", &fillStrokeMode, {
{"Fill only", 0},
{"Outline only", 1},
{"Fill and Outline", 2}

View file

@ -20,8 +20,9 @@ DrawingProgramToolType RectSelectTool::get_type() {
void RectSelectTool::gui_toolbox() {
auto& t = drawP.world.main.toolbar;
t.gui.new_id("rectangle select tool", [&] {
GUIStuff::ElementHelpers::text_label_centered(t.gui, "Rectangle Select");
auto& gui = drawP.world.main.g.gui;
gui.new_id("rectangle select tool", [&] {
GUIStuff::ElementHelpers::text_label_centered(gui, "Rectangle Select");
drawP.selection.selection_gui();
});
}

View file

@ -57,25 +57,26 @@ void ScreenshotTool::gui_toolbox() {
using namespace ElementHelpers;
Toolbar& t = drawP.world.main.toolbar;
auto& gui = drawP.world.main.g.gui;
auto& screenshotConfig = drawP.world.main.toolConfig.screenshot;
t.gui.new_id("screenshot tool", [&] {
text_label_centered(t.gui, "Screenshot");
gui.new_id("screenshot tool", [&] {
text_label_centered(gui, "Screenshot");
auto oldImgSize = controls.imageSize;
if(controls.selectionMode == ScreenshotControls::SelectionMode::NO_SELECTION)
text_label(t.gui, "Select an area on the canvas...");
text_label(gui, "Select an area on the canvas...");
if(controls.selectionMode != ScreenshotControls::SelectionMode::NO_SELECTION && screenshotConfig.selectedType != SCREENSHOT_SVG)
input_scalars_field(t.gui, "Image Size", "Image Size", &controls.imageSize, 2, 0, 999999999);
input_scalars_field(gui, "Image Size", "Image Size", &controls.imageSize, 2, 0, 999999999);
if(controls.selectionMode == ScreenshotControls::SelectionMode::SELECTION_EXISTS) {
left_to_right_line_layout(t.gui, [&]() {
text_label(t.gui, "Image Type");
t.gui.element<DropDown<size_t>>("image type select", (size_t*)(&screenshotConfig.selectedType), controls.typeSelections);
left_to_right_line_layout(gui, [&]() {
text_label(gui, "Image Type");
gui.element<DropDown<size_t>>("image type select", (size_t*)(&screenshotConfig.selectedType), controls.typeSelections);
});
if(screenshotConfig.selectedType != SCREENSHOT_SVG)
checkbox_boolean_field(t.gui, "Display Grid", "Display Grid", &controls.displayGrid);
checkbox_boolean_field(gui, "Display Grid", "Display Grid", &controls.displayGrid);
else
text_label(t.gui, "Note: Screenshot will ignore blend\nmodes and layer alpha");
text_label(gui, "Note: Screenshot will ignore blend\nmodes and layer alpha");
if(screenshotConfig.selectedType != 0)
checkbox_boolean_field(t.gui, "Transparent Background", "Transparent Background", &controls.transparentBackground);
checkbox_boolean_field(gui, "Transparent Background", "Transparent Background", &controls.transparentBackground);
if(controls.imageSize.x() != oldImgSize.x()) {
screenshotConfig.setDimensionSize = controls.imageSize.x();
screenshotConfig.setDimensionIsX = true;
@ -86,7 +87,7 @@ void ScreenshotTool::gui_toolbox() {
screenshotConfig.setDimensionIsX = false;
controls.imageSize.x() = controls.imageSize.y() * (controls.rectX2 - controls.rectX1) / (controls.rectY2 - controls.rectY1);
}
text_button(t.gui, "Take Screenshot", "Take Screenshot", {
text_button(gui, "Take Screenshot", "Take Screenshot", {
.wide = true,
.onClick = [&] {
controls.selectionMode = ScreenshotControls::SelectionMode::NO_SELECTION;

View file

@ -23,8 +23,9 @@ DrawingProgramToolType TextBoxTool::get_type() {
void TextBoxTool::gui_toolbox() {
Toolbar& t = drawP.world.main.toolbar;
t.gui.new_id("textbox tool", [&] {
GUIStuff::ElementHelpers::text_label_centered(t.gui, "Zoom tool");
auto& gui = drawP.world.main.g.gui;
gui.new_id("textbox tool", [&] {
GUIStuff::ElementHelpers::text_label_centered(gui, "Zoom tool");
});
}

View file

@ -18,8 +18,9 @@ DrawingProgramToolType ZoomCanvasTool::get_type() {
void ZoomCanvasTool::gui_toolbox() {
Toolbar& t = drawP.world.main.toolbar;
t.gui.new_id("Zoom canvas tool", [&] {
GUIStuff::ElementHelpers::text_label_centered(t.gui, "Zoom tool");
auto& gui = drawP.world.main.g.gui;
gui.new_id("Zoom canvas tool", [&] {
GUIStuff::ElementHelpers::text_label_centered(gui, "Zoom tool");
});
}

106
src/GUIHolder.cpp Normal file
View file

@ -0,0 +1,106 @@
#include "GUIHolder.hpp"
#include <filesystem>
#include <fstream>
#include <include/core/SkStream.h>
GUIHolder::GUIHolder() {
// NOTE: On windows, when the native file picker is open, any call to MakeFromFile fails
// So, it's better to load the icons at the beginning of the program so that the icon loading doesn't fail later
load_icons_at("data/icons");
#ifdef __ANDROID__
load_icons_at("data/icons/RemixIcon"); // SDL_GlobDirectory doesn't work recursively on Android
#endif
load_default_theme();
}
void GUIHolder::load_icons_at(const std::filesystem::path& pathToLoad) {
int globCount;
char** filesInPath = SDL_GlobDirectory(pathToLoad.c_str(), nullptr, 0, &globCount);
if(filesInPath) {
for(int i = 0; i < globCount; i++) {
std::filesystem::path filePath = pathToLoad / std::filesystem::path(filesInPath[i]);
SDL_PathInfo fileInfo;
if(SDL_GetPathInfo(filePath.c_str(), &fileInfo) && fileInfo.type == SDL_PATHTYPE_FILE) {
std::string iconRelativePath = filePath.relative_path().string();
std::replace(iconRelativePath.begin(), iconRelativePath.end(), '\\', '/');
std::string iconData = read_file_to_string(iconRelativePath);
auto stream = SkMemoryStream(iconData.c_str(), iconData.size(), false);
auto svgDom = SkSVGDOM::Builder().make(stream);
if(!svgDom)
throw std::runtime_error("[Toolbar::Toolbar] Could not parse SVG " + iconRelativePath);
else {
if(svgDom->containerSize().width() == 0 || svgDom->containerSize().height() == 0)
svgDom->setContainerSize({1000, 1000});
gui.io.svgData[iconRelativePath] = svgDom;
}
}
}
SDL_free(filesInPath);
}
}
void GUIHolder::load_default_theme() {
gui.io.theme = GUIStuff::get_default_dark_mode();
}
void GUIHolder::save_theme(const std::filesystem::path& configPath, const std::string& themeName) {
std::filesystem::create_directory(configPath / "themes");
std::ofstream f(configPath / "themes" / (themeName + ".json"));
if(f.is_open()) {
using json = nlohmann::json;
json j;
j = *gui.io.theme;
f << j;
f.close();
}
}
bool GUIHolder::load_theme(const std::filesystem::path& configPath, const std::string& themeName) {
std::filesystem::path themeDir = configPath / "themes";
bool successfullyLoaded = false;
if(std::filesystem::exists(themeDir) && std::filesystem::is_directory(themeDir)) {
std::ifstream f(themeDir / (themeName + ".json"));
if(f.is_open()) {
using json = nlohmann::json;
try {
json j;
f >> j;
auto theme(std::make_shared<GUIStuff::Theme>());
j.get_to(*theme);
gui.io.theme = theme;
successfullyLoaded = true;
} catch(...) {}
f.close();
}
}
if(!successfullyLoaded)
load_default_theme();
return successfullyLoaded;
}
void GUIHolder::update() {
}
void GUIHolder::draw(SkCanvas* canvas) {
}
void GUIHolder::input_key_callback(const InputManager::KeyCallbackArgs& key) {
}
void GUIHolder::input_mouse_button_callback(const InputManager::MouseButtonCallbackArgs& button) {
}
void GUIHolder::input_mouse_motion_callback(const InputManager::MouseMotionCallbackArgs& motion) {
}
void GUIHolder::input_mouse_wheel_callback(const InputManager::MouseWheelCallbackArgs& wheel) {
}
void GUIHolder::input_finger_touch_callback(const InputManager::FingerTouchCallbackArgs& touch) {
}
void GUIHolder::input_finger_motion_callback(const InputManager::FingerMotionCallbackArgs& motion) {
}

24
src/GUIHolder.hpp Normal file
View file

@ -0,0 +1,24 @@
#pragma once
#include "GUIStuff/GUIManager.hpp"
class GUIHolder {
public:
GUIHolder();
GUIStuff::GUIManager gui;
void load_icons_at(const std::filesystem::path& pathToLoad);
void load_default_theme();
void save_theme(const std::filesystem::path& configPath, const std::string& themeName);
bool load_theme(const std::filesystem::path& configPath, const std::string& themeName);
void update();
void draw(SkCanvas* canvas);
void input_key_callback(const InputManager::KeyCallbackArgs& key);
void input_mouse_button_callback(const InputManager::MouseButtonCallbackArgs& button);
void input_mouse_motion_callback(const InputManager::MouseMotionCallbackArgs& motion);
void input_mouse_wheel_callback(const InputManager::MouseWheelCallbackArgs& wheel);
void input_finger_touch_callback(const InputManager::FingerTouchCallbackArgs& touch);
void input_finger_motion_callback(const InputManager::FingerMotionCallbackArgs& motion);
};

View file

@ -8,14 +8,14 @@ void top_to_bottom_window_popup_layout(GUIManager& gui, const char* id, Clay_Siz
CLAY_AUTO_ID({
.layout = {
.sizing = {.width = x, .height = y },
.padding = CLAY_PADDING_ALL(gui.io->theme->padding1),
.childGap = gui.io->theme->childGap1,
.padding = CLAY_PADDING_ALL(gui.io.theme->padding1),
.childGap = gui.io.theme->childGap1,
.layoutDirection = CLAY_TOP_TO_BOTTOM
},
.backgroundColor = convert_vec4<Clay_Color>(gui.io->theme->backColor1),
.backgroundColor = convert_vec4<Clay_Color>(gui.io.theme->backColor1),
.cornerRadius = CLAY_CORNER_RADIUS(10),
.floating = { .attachTo = CLAY_ATTACH_TO_PARENT },
.border = {.color = convert_vec4<Clay_Color>(gui.io->theme->fillColor2), .width = CLAY_BORDER_OUTSIDE(1)}
.border = {.color = convert_vec4<Clay_Color>(gui.io.theme->fillColor2), .width = CLAY_BORDER_OUTSIDE(1)}
}) {
innerContent();
}
@ -25,7 +25,7 @@ void top_to_bottom_window_popup_layout(GUIManager& gui, const char* id, Clay_Siz
void left_to_right_layout(GUIManager& gui, Clay_SizingAxis x, Clay_SizingAxis y, const std::function<void()>& innerContent) {
CLAY_AUTO_ID({.layout = {
.sizing = {.width = x, .height = y },
.childGap = gui.io->theme->childGap1,
.childGap = gui.io.theme->childGap1,
.childAlignment = {.x = CLAY_ALIGN_X_LEFT, .y = CLAY_ALIGN_Y_CENTER},
.layoutDirection = CLAY_LEFT_TO_RIGHT,
}
@ -41,7 +41,7 @@ void left_to_right_line_layout(GUIManager& gui, const std::function<void()>& inn
void left_to_right_line_centered_layout(GUIManager& gui, const std::function<void()>& innerContent) {
CLAY_AUTO_ID({.layout = {
.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIT(0) },
.childGap = gui.io->theme->childGap1,
.childGap = gui.io.theme->childGap1,
.childAlignment = {.x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_CENTER},
.layoutDirection = CLAY_LEFT_TO_RIGHT,
}

View file

@ -3,19 +3,19 @@
namespace GUIStuff { namespace ElementHelpers {
void text_label_size(GUIManager& gui, std::string_view val, float modifier) {
CLAY_TEXT(gui.strArena.std_str_to_clay_str(val), CLAY_TEXT_CONFIG({.textColor = convert_vec4<Clay_Color>(gui.io->theme->frontColor1), .fontSize = static_cast<uint16_t>(gui.io->fontSize * modifier)}));
CLAY_TEXT(gui.strArena.std_str_to_clay_str(val), CLAY_TEXT_CONFIG({.textColor = convert_vec4<Clay_Color>(gui.io.theme->frontColor1), .fontSize = static_cast<uint16_t>(gui.io.fontSize * modifier)}));
}
void text_label_color(GUIManager& gui, std::string_view val, const SkColor4f& color) {
CLAY_TEXT(gui.strArena.std_str_to_clay_str(val), CLAY_TEXT_CONFIG({.textColor = convert_vec4<Clay_Color>(color), .fontSize = gui.io->fontSize }));
CLAY_TEXT(gui.strArena.std_str_to_clay_str(val), CLAY_TEXT_CONFIG({.textColor = convert_vec4<Clay_Color>(color), .fontSize = gui.io.fontSize }));
}
void text_label_light(GUIManager& gui, std::string_view val) {
CLAY_TEXT(gui.strArena.std_str_to_clay_str(val), CLAY_TEXT_CONFIG({.textColor = convert_vec4<Clay_Color>(gui.io->theme->frontColor2), .fontSize = gui.io->fontSize }));
CLAY_TEXT(gui.strArena.std_str_to_clay_str(val), CLAY_TEXT_CONFIG({.textColor = convert_vec4<Clay_Color>(gui.io.theme->frontColor2), .fontSize = gui.io.fontSize }));
}
void text_label(GUIManager& gui, std::string_view val) {
CLAY_TEXT(gui.strArena.std_str_to_clay_str(val), CLAY_TEXT_CONFIG({.textColor = convert_vec4<Clay_Color>(gui.io->theme->frontColor1), .fontSize = gui.io->fontSize }));
CLAY_TEXT(gui.strArena.std_str_to_clay_str(val), CLAY_TEXT_CONFIG({.textColor = convert_vec4<Clay_Color>(gui.io.theme->frontColor1), .fontSize = gui.io.fontSize }));
}
void text_label_centered(GUIManager& gui, std::string_view val) {
@ -25,7 +25,7 @@ void text_label_centered(GUIManager& gui, std::string_view val) {
.childAlignment = {.x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_CENTER},
}
}) {
CLAY_TEXT(gui.strArena.std_str_to_clay_str(val), CLAY_TEXT_CONFIG({.textColor = convert_vec4<Clay_Color>(gui.io->theme->frontColor1), .fontSize = gui.io->fontSize, .textAlignment = CLAY_TEXT_ALIGN_CENTER}));
CLAY_TEXT(gui.strArena.std_str_to_clay_str(val), CLAY_TEXT_CONFIG({.textColor = convert_vec4<Clay_Color>(gui.io.theme->frontColor1), .fontSize = gui.io.fontSize, .textAlignment = CLAY_TEXT_ALIGN_CENTER}));
}
}
@ -36,7 +36,7 @@ void text_label_light_centered(GUIManager& gui, std::string_view val) {
.childAlignment = {.x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_CENTER},
}
}) {
CLAY_TEXT(gui.strArena.std_str_to_clay_str(val), CLAY_TEXT_CONFIG({.textColor = convert_vec4<Clay_Color>(gui.io->theme->frontColor2), .fontSize = gui.io->fontSize, .textAlignment = CLAY_TEXT_ALIGN_CENTER}));
CLAY_TEXT(gui.strArena.std_str_to_clay_str(val), CLAY_TEXT_CONFIG({.textColor = convert_vec4<Clay_Color>(gui.io.theme->frontColor2), .fontSize = gui.io.fontSize, .textAlignment = CLAY_TEXT_ALIGN_CENTER}));
}
}

View file

@ -32,7 +32,7 @@ template <typename T> class DropDown : public Element {
.layout = {
.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0) },
.padding = {.left = 4, .right = 4},
.childGap = gui.io->theme->childGap1,
.childGap = gui.io.theme->childGap1,
.childAlignment = {.x = CLAY_ALIGN_X_LEFT, .y = CLAY_ALIGN_Y_CENTER},
.layoutDirection = CLAY_LEFT_TO_RIGHT,
}
@ -55,13 +55,13 @@ template <typename T> class DropDown : public Element {
Clay_ElementData dropdownElemData = Clay_GetElementData(localID);
float calculatedDropdownMaxHeight = 0.0f;
if(dropdownElemData.found)
calculatedDropdownMaxHeight = std::max(gui.io->windowSize.y() - dropdownElemData.boundingBox.y - 2.0f, 0.0f);
calculatedDropdownMaxHeight = std::max(gui.io.windowSize.y() - dropdownElemData.boundingBox.y - 2.0f, 0.0f);
CLAY(localID, {
.layout = {
.sizing = {.width = CLAY_SIZING_FIXED(opts.width), .height = CLAY_SIZING_FIT(0, calculatedDropdownMaxHeight)},
.childGap = 0
},
.backgroundColor = convert_vec4<Clay_Color>(gui.io->theme->backColor1),
.backgroundColor = convert_vec4<Clay_Color>(gui.io.theme->backColor1),
.cornerRadius = CLAY_CORNER_RADIUS(4),
.floating = {
.offset = {
@ -74,7 +74,7 @@ template <typename T> class DropDown : public Element {
.attachTo = CLAY_ATTACH_TO_PARENT
},
.border = {
.color = convert_vec4<Clay_Color>(gui.io->theme->fillColor2),
.color = convert_vec4<Clay_Color>(gui.io.theme->fillColor2),
.width = CLAY_BORDER_OUTSIDE(1)
}
}) {
@ -96,11 +96,11 @@ template <typename T> class DropDown : public Element {
}) {
SkColor4f entryColor;
if(selectedEntry)
entryColor = gui.io->theme->backColor2;
entryColor = gui.io.theme->backColor2;
else if(hoveringOver.has_value() && hoveringOver.value() == i)
entryColor = gui.io->theme->backColor2;
entryColor = gui.io.theme->backColor2;
else
entryColor = gui.io->theme->backColor1;
entryColor = gui.io.theme->backColor1;
CLAY_AUTO_ID({
.layout = {
.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0)},

View file

@ -68,7 +68,7 @@ struct Theme {
std::shared_ptr<Theme> get_default_dark_mode();
struct UpdateInputData {
InputManager* input;
InputManager* input = nullptr;
std::function<void()> layoutRun;
SkFont get_font(float fSize) const;
@ -84,7 +84,6 @@ struct UpdateInputData {
std::shared_ptr<FontData> fonts;
sk_sp<SkTypeface> textTypeface;
DefaultStringArena* strArena;
std::shared_ptr<Theme> theme;
std::unordered_map<std::string, sk_sp<SkSVGDOM>> svgData;
};

View file

@ -8,9 +8,9 @@ PositionAdjustingPopupMenu::PositionAdjustingPopupMenu(GUIManager& gui): Element
void PositionAdjustingPopupMenu::layout(Vector2f popupPos, const std::function<void()>& innerContent) {
if(layoutElement && layoutElement->get_bb().has_value()) {
auto& bb = layoutElement->get_bb().value();
if((popupPos.y() + bb.height()) > gui.io->windowSize.y())
if((popupPos.y() + bb.height()) > gui.io.windowSize.y())
popupPos.y() -= bb.height();
if((popupPos.x() + bb.width()) > gui.io->windowSize.x())
if((popupPos.x() + bb.width()) > gui.io.windowSize.x())
popupPos.x() -= bb.width();
}
@ -18,13 +18,13 @@ void PositionAdjustingPopupMenu::layout(Vector2f popupPos, const std::function<v
CLAY_AUTO_ID({
.layout = {
.sizing = {.width = CLAY_SIZING_FIT(100), .height = CLAY_SIZING_FIT(0)},
.padding = CLAY_PADDING_ALL(gui.io->theme->padding1),
.padding = CLAY_PADDING_ALL(gui.io.theme->padding1),
.childGap = 1,
.childAlignment = { .x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_TOP},
.layoutDirection = CLAY_TOP_TO_BOTTOM
},
.backgroundColor = convert_vec4<Clay_Color>(gui.io->theme->backColor1),
.cornerRadius = CLAY_CORNER_RADIUS(gui.io->theme->windowCorners1),
.backgroundColor = convert_vec4<Clay_Color>(gui.io.theme->backColor1),
.cornerRadius = CLAY_CORNER_RADIUS(gui.io.theme->windowCorners1),
.floating = {
.offset = {popupPos.x(), popupPos.y()},
.zIndex = gui.zIndex,

View file

@ -11,7 +11,7 @@ SVGIcon::SVGIcon(GUIManager& gui):
Element(gui) {}
void SVGIcon::layout(const std::string& newSvgPath, bool newIsHighlighted) {
auto& io = *gui.io;
auto& io = gui.io;
auto findSVGData = io.svgData.find(newSvgPath);
if(findSVGData == io.svgData.end())
throw std::runtime_error("[SVGIcon::update] Could not load icon " + newSvgPath);

View file

@ -46,15 +46,15 @@ void ScrollArea::layout(const Options& options) {
// .childAlignment = {.x = CLAY_ALIGN_X_LEFT, .y = CLAY_ALIGN_Y_TOP},
// .layoutDirection = CLAY_TOP_TO_BOTTOM
// },
// .backgroundColor = convert_vec4<Clay_Color>(io->theme->backColor2)
// .backgroundColor = convert_vec4<Clay_Color>(io.theme->backColor2)
// }) {
// SkColor4f scrollerColor;
// if(sD.isMoving)
// scrollerColor = io->theme->fillColor1;
// scrollerColor = io.theme->fillColor1;
// else if(Clay_Hovered())
// scrollerColor = io->theme->fillColor1;
// scrollerColor = io.theme->fillColor1;
// else
// scrollerColor = io->theme->fillColor2;
// scrollerColor = io.theme->fillColor2;
// bool isHoveringOverScroller = false;
// CLAY_AUTO_ID({
@ -71,19 +71,19 @@ void ScrollArea::layout(const Options& options) {
// isHoveringOverScroller = true;
// }
// CLAY_AUTO_ID({ .layout = {.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0)}}}) {}
// if(Clay_Hovered() && io->mouse.leftClick) {
// if(Clay_Hovered() && io.mouse.leftClick) {
// isMoving = true;
// if(isHoveringOverScroller)
// scrollerStartPos = scrollAreaBB.y + areaAboveScrollerSize + scrollerSize * 0.5f;
// else
// scrollerStartPos = std::clamp(io->mouse.pos.y(), scrollAreaBB.y + scrollerSize * 0.5f, scrollAreaBB.y + scrollAreaBB.height - scrollerSize * 0.5f);
// mouseStartPos = io->mouse.pos.y();
// scrollerStartPos = std::clamp(io.mouse.pos.y(), scrollAreaBB.y + scrollerSize * 0.5f, scrollAreaBB.y + scrollAreaBB.height - scrollerSize * 0.5f);
// mouseStartPos = io.mouse.pos.y();
// }
// if(!io->mouse.leftHeld)
// if(!io.mouse.leftHeld)
// isMoving = false;
// if(isMoving) {
// float newScrollPosFrac;
// newScrollPosFrac = std::clamp((scrollerStartPos - (mouseStartPos - io->mouse.pos.y()) - scrollAreaBB.y - scrollerSize * 0.5f) / (scrollAreaBB.height - scrollerSize), 0.0f, 1.0f);
// newScrollPosFrac = std::clamp((scrollerStartPos - (mouseStartPos - io.mouse.pos.y()) - scrollAreaBB.y - scrollerSize * 0.5f) / (scrollAreaBB.height - scrollerSize), 0.0f, 1.0f);
// currentScrollPos = newScrollPosFrac * (-scrollPosMax);
// }
// currentScrollPos = std::clamp(currentScrollPos, -scrollPosMax, 0.0f);

View file

@ -8,7 +8,7 @@ SelectableButton::SelectableButton(GUIManager& gui):
Element(gui) {}
void SelectableButton::layout(const Data& d) {
auto& io = *gui.io;
auto& io = gui.io;
SkColor4f borderColor;
SkColor4f backgroundColorHighlight;

View file

@ -6,7 +6,7 @@ namespace GUIStuff {
template <typename T> TextBox<T>::TextBox(GUIManager& gui): Element(gui) {}
template <typename T> void TextBox<T>::layout(const TextBoxData<T>& userInfo) {
auto& io = *gui.io;
auto& io = gui.io;
this->userInfo = userInfo;
init_textbox(io);
CLAY_AUTO_ID({
@ -59,26 +59,26 @@ template <typename T> void TextBox<T>::clay_draw(SkCanvas* canvas, UpdateInputDa
}
template <typename T> bool TextBox<T>::input_mouse_button_callback(const InputManager::MouseButtonCallbackArgs& button, bool mouseHovering) {
auto& io = *gui.io;
auto& io = gui.io;
if(button.button == InputManager::MouseButton::LEFT && boundingBox.has_value()) {
if(button.down) {
if(mouseHovering) {
*rect = {(boundingBox.value().min + io.windowPos) * io.guiScaleMultiplier, (boundingBox.value().max + io.windowPos) * io.guiScaleMultiplier};
gui.io->input->set_rich_text_box_input_front(textbox, cur, false, rect, userInfo.textInputProps, nullptr);
textbox->process_mouse_left_button(*cur, button.pos - boundingBox.value().min, button.clicks, true, gui.io->input->key(InputManager::KEY_TEXT_SHIFT).held);
gui.io.input->set_rich_text_box_input_front(textbox, cur, false, rect, userInfo.textInputProps, nullptr);
textbox->process_mouse_left_button(*cur, button.pos - boundingBox.value().min, button.clicks, true, gui.io.input->key(InputManager::KEY_TEXT_SHIFT).held);
isSelected = true;
}
else {
gui.io->input->remove_rich_text_box_input(textbox);
gui.io.input->remove_rich_text_box_input(textbox);
if(update_data())
gui.set_post_callback_func(userInfo.onEdit);
init_textbox(*gui.io);
init_textbox(gui.io);
isSelected = false;
}
}
else {
textbox->process_mouse_left_button(*cur, button.pos - boundingBox.value().min, 0, false, gui.io->input->key(InputManager::KEY_TEXT_SHIFT).held);
textbox->process_mouse_left_button(*cur, button.pos - boundingBox.value().min, 0, false, gui.io.input->key(InputManager::KEY_TEXT_SHIFT).held);
}
}
return Element::input_mouse_button_callback(button, mouseHovering);
@ -86,7 +86,7 @@ template <typename T> bool TextBox<T>::input_mouse_button_callback(const InputMa
template <typename T> bool TextBox<T>::input_mouse_motion_callback(const InputManager::MouseMotionCallbackArgs& motion, bool mouseHovering) {
if(boundingBox.has_value())
textbox->process_mouse_left_button(*cur, motion.pos - boundingBox.value().min, 0, gui.io->input->mouse.leftDown, gui.io->input->key(InputManager::KEY_TEXT_SHIFT).held);
textbox->process_mouse_left_button(*cur, motion.pos - boundingBox.value().min, 0, gui.io.input->mouse.leftDown, gui.io.input->key(InputManager::KEY_TEXT_SHIFT).held);
return Element::input_mouse_motion_callback(motion, mouseHovering);
}
@ -130,7 +130,7 @@ template <typename T> bool TextBox<T>::update_data() {
}
template <typename T> TextBox<T>::~TextBox() {
gui.io->input->remove_rich_text_box_input(textbox);
gui.io.input->remove_rich_text_box_input(textbox);
}
}

View file

@ -45,10 +45,10 @@ Clay_Dimensions GUIManager::clay_skia_measure_text(Clay_StringSlice str, Clay_Te
pStyle.setTextAlign(skia::textlayout::TextAlign::kLeft);
skia::textlayout::TextStyle tStyle;
tStyle.setFontSize(config->fontSize);
tStyle.setFontFamilies(window->io->fonts->get_default_font_families());
tStyle.setFontFamilies(window->io.fonts->get_default_font_families());
pStyle.setTextStyle(tStyle);
skia::textlayout::ParagraphBuilderImpl a(pStyle, window->io->fonts->collection, SkUnicodes::ICU::Make());
skia::textlayout::ParagraphBuilderImpl a(pStyle, window->io.fonts->collection, SkUnicodes::ICU::Make());
a.addText(str.chars, str.length);
std::unique_ptr<skia::textlayout::Paragraph> p = a.Build();
p->layout(std::numeric_limits<float>::max());
@ -58,7 +58,7 @@ Clay_Dimensions GUIManager::clay_skia_measure_text(Clay_StringSlice str, Clay_Te
void GUIManager::draw(SkCanvas* canvas, bool skiaAA) {
canvas->save();
canvas->translate(io->windowPos.x(), io->windowPos.y());
canvas->translate(io.windowPos.x(), io.windowPos.y());
for(size_t i = 0; i < static_cast<size_t>(renderCommands.length); i++) {
Clay_RenderCommand* command = Clay_RenderCommandArray_Get(&renderCommands, i);
@ -94,11 +94,11 @@ void GUIManager::draw(SkCanvas* canvas, bool skiaAA) {
pStyle.setTextAlign(skia::textlayout::TextAlign::kLeft);
skia::textlayout::TextStyle tStyle;
tStyle.setFontSize(config->fontSize);
tStyle.setFontFamilies(io->fonts->get_default_font_families());
tStyle.setFontFamilies(io.fonts->get_default_font_families());
tStyle.setColor(convert_vec4<SkColor4f>(config->textColor).toSkColor());
pStyle.setTextStyle(tStyle);
skia::textlayout::ParagraphBuilderImpl a(pStyle, io->fonts->collection, SkUnicodes::ICU::Make());
skia::textlayout::ParagraphBuilderImpl a(pStyle, io.fonts->collection, SkUnicodes::ICU::Make());
a.addText(config->stringContents.chars, config->stringContents.length);
std::unique_ptr<skia::textlayout::Paragraph> p = a.Build();
p->layout(std::numeric_limits<float>::max());
@ -211,7 +211,7 @@ void GUIManager::draw(SkCanvas* canvas, bool skiaAA) {
}
case CLAY_RENDER_COMMAND_TYPE_CUSTOM: {
Element* customElement = static_cast<Element*>(command->renderData.custom.customData);
customElement->clay_draw(canvas, *io, command, skiaAA);
customElement->clay_draw(canvas, io, command, skiaAA);
break;
}
default:
@ -223,11 +223,11 @@ void GUIManager::draw(SkCanvas* canvas, bool skiaAA) {
}
void GUIManager::update_window(const Vector2f& windowPos, const Vector2f& windowSize, float guiScaleMultiplier) {
if(io->windowPos != windowPos || io->windowSize != windowSize || io->guiScaleMultiplier != guiScaleMultiplier)
if(io.windowPos != windowPos || io.windowSize != windowSize || io.guiScaleMultiplier != guiScaleMultiplier)
set_to_layout();
io->windowPos = windowPos;
io->windowSize = windowSize;
io->guiScaleMultiplier = guiScaleMultiplier;
io.windowPos = windowPos;
io.windowSize = windowSize;
io.guiScaleMultiplier = guiScaleMultiplier;
}
void GUIManager::set_to_layout() {
@ -251,8 +251,7 @@ void GUIManager::layout_begin() {
for(auto& [id, e] : elements)
e.isUsedThisFrame = false;
io->strArena = &strArena;
Clay_SetLayoutDimensions(Clay_Dimensions(io->windowSize.x(), io->windowSize.y()));
Clay_SetLayoutDimensions(Clay_Dimensions(io.windowSize.x(), io.windowSize.y()));
Clay_SetCurrentContext(clayInstance);
strArena.reset();
@ -284,7 +283,7 @@ void GUIManager::update_element_bounding_boxes() {
void GUIManager::single_layout_run() {
layout_begin();
io->layoutRun();
io.layoutRun();
layout_end();
}

View file

@ -23,7 +23,7 @@ class GUIManager {
void update_window(const Vector2f& windowPos, const Vector2f& windowSize, float guiScaleMultiplier);
std::shared_ptr<UpdateInputData> io;
UpdateInputData io;
GUIManagerIDStack idStack;
std::unordered_map<GUIManagerIDStack, ElementContainer> elements;

130
src/GlobalConfig.cpp Normal file
View file

@ -0,0 +1,130 @@
#include "GlobalConfig.hpp"
#include <Helpers/Random.hpp>
#include "ResourceDisplay/ImageResourceDisplay.hpp"
#include "DrawingProgram/DrawingProgramCache.hpp"
GlobalConfig::GlobalConfig() {
displayName = Random::get().alphanumeric_str(10);
}
nlohmann::json GlobalConfig::get_config_json(const InputManager& input) const {
using json = nlohmann::json;
json toRet;
json jKeybinds;
for(unsigned i = 0; i < InputManager::KEY_ASSIGNABLE_COUNT; i++) {
auto f = std::find_if(input.keyAssignments.begin(), input.keyAssignments.end(), [&](auto& p) {
return p.second == i;
});
if(f != input.keyAssignments.end())
jKeybinds[json(static_cast<InputManager::KeyCodeEnum>(i))] = input.key_assignment_to_str(f->first);
}
toRet["keybinds"] = jKeybinds;
toRet["guiScale"] = guiScale;
toRet["jumpTransitionTime"] = jumpTransitionTime;
toRet["disableGraphicsDriverWorkarounds"] = disableGraphicsDriverWorkarounds;
toRet["dragZoomSpeed"] = dragZoomSpeed;
toRet["scrollZoomSpeed"] = scrollZoomSpeed;
toRet["vsync"] = vsyncValue;
#ifndef __EMSCRIPTEN__
toRet["applyDisplayScale"] = applyDisplayScale;
#endif
toRet["displayName"] = displayName;
toRet["antialiasing"] = antialiasing;
toRet["useNativeFilePicker"] = useNativeFilePicker;
toRet["themeInUse"] = themeCurrentlyLoaded;
toRet["defaultCanvasBackgroundColor"] = defaultCanvasBackgroundColor;
toRet["flipZoomToolDirection"] = flipZoomToolDirection;
#ifndef __EMSCRIPTEN__
toRet["checkForUpdates"] = checkForUpdates;
#endif
json tablet;
tablet["pressureAffectsBrushWidth"] = tabletOptions.pressureAffectsBrushWidth;
tablet["smoothingSamplingTime"] = tabletOptions.smoothingSamplingTime;
tablet["middleClickButton"] = tabletOptions.middleClickButton;
tablet["rightClickButton"] = tabletOptions.rightClickButton;
tablet["ignoreMouseMovementWhenPenInProximity"] = tabletOptions.ignoreMouseMovementWhenPenInProximity;
tablet["brushMinimumSize"] = tabletOptions.brushMinimumSize;
tablet["zoomWhilePenDownAndButtonHeld"] = tabletOptions.zoomWhilePenDownAndButtonHeld;
toRet["tablet"] = tablet;
json debugJson;
debugJson["showPerformance"] = showPerformance;
debugJson["fpsLimit"] = fpsLimit;
debugJson["jumpTransitionEasing"] = jumpTransitionEasing;
debugJson["imageLoadMaxThreads"] = ImageResourceDisplay::IMAGE_LOAD_THREAD_COUNT_MAX;
debugJson["cacheNodeResolution"] = DrawingProgramCache::CACHE_NODE_RESOLUTION;
debugJson["maxCacheNodes"] = DrawingProgramCache::MAXIMUM_DRAW_CACHE_SURFACES;
debugJson["maxComponentsInNode"] = DrawingProgramCache::MAXIMUM_COMPONENTS_IN_SINGLE_NODE;
debugJson["componentCountToForceCacheRebuild"] = DrawingProgramCache::MINIMUM_COMPONENTS_TO_START_REBUILD;
debugJson["maximumFrameTimeToForceCacheRebuild"] = DrawingProgramCache::MILLISECOND_FRAME_TIME_TO_FORCE_CACHE_REFRESH;
debugJson["millisecondMinimumTimeToCheckForCacheRebuild"] = DrawingProgramCache::MILLISECOND_MINIMUM_TIME_TO_CHECK_FORCE_REFRESH;
toRet["debug"] = debugJson;
return toRet;
}
void GlobalConfig::set_config_json(InputManager& input, const nlohmann::json& j, VersionNumber version) {
using json = nlohmann::json;
input.keyAssignments.clear();
try {
const json& jKeybinds = j.at("keybinds");
for(unsigned i = 0; i < InputManager::KEY_ASSIGNABLE_COUNT; i++) {
try {
Vector2ui32 a = input.key_assignment_from_str(jKeybinds.at(json(static_cast<InputManager::KeyCodeEnum>(i))));
if(a != Vector2ui32{0, 0})
input.keyAssignments.emplace(a, i);
else
throw;
}
catch(...) {
auto f = std::find_if(input.defaultKeyAssignments.begin(), input.defaultKeyAssignments.end(), [&](auto& p) {
return p.second == i;
});
input.keyAssignments.emplace(f->first, i);
}
}
}
catch(...) {
input.keyAssignments = input.defaultKeyAssignments;
}
try{j.at("displayName").get_to(displayName);} catch(...) {}
try{j.at("dragZoomSpeed").get_to(dragZoomSpeed);} catch(...) {}
try{j.at("scrollZoomSpeed").get_to(scrollZoomSpeed);} catch(...) {}
try{j.at("vsync").get_to(vsyncValue);} catch(...) {}
#ifndef __EMSCRIPTEN__
try{j.at("applyDisplayScale").get_to(applyDisplayScale);} catch(...) {}
#endif
try{j.at("guiScale").get_to(guiScale);} catch(...) {}
try{j.at("jumpTransitionTime").get_to(jumpTransitionTime);} catch(...) {}
try{j.at("disableGraphicsDriverWorkarounds").get_to(disableGraphicsDriverWorkarounds);} catch(...) {}
try{j.at("useNativeFilePicker").get_to(useNativeFilePicker);} catch(...) {}
try{j.at("themeInUse").get_to(themeCurrentlyLoaded);} catch(...) {}
if(version >= VersionNumber(0, 3, 0))
try{j.at("defaultCanvasBackgroundColor").get_to(defaultCanvasBackgroundColor);} catch(...) {}
try{j.at("flipZoomToolDirection").get_to(flipZoomToolDirection);} catch(...) {}
#ifndef __EMSCRIPTEN__
try{j.at("checkForUpdates").get_to(checkForUpdates);} catch(...) {}
#endif
try{j.at("antialiasing").get_to(antialiasing);} catch(...) {}
try{j.at("tablet").at("pressureAffectsBrushWidth").get_to(tabletOptions.pressureAffectsBrushWidth);} catch(...) {}
try{j.at("tablet").at("smoothingSamplingTime").get_to(tabletOptions.smoothingSamplingTime);} catch(...) {}
try{j.at("tablet").at("middleClickButton").get_to(tabletOptions.middleClickButton);} catch(...) {}
try{j.at("tablet").at("rightClickButton").get_to(tabletOptions.rightClickButton);} catch(...) {}
try{j.at("tablet").at("ignoreMouseMovementWhenPenInProximity").get_to(tabletOptions.ignoreMouseMovementWhenPenInProximity);} catch(...) {}
try{j.at("tablet").at("brushMinimumSize").get_to(tabletOptions.brushMinimumSize);} catch(...) {}
try{j.at("tablet").at("zoomWhilePenDownAndButtonHeld").get_to(tabletOptions.zoomWhilePenDownAndButtonHeld);} catch(...) {}
try{j.at("debug").at("showPerformance").get_to(showPerformance);} catch(...) {}
try{j.at("debug").at("fpsLimit").get_to(fpsLimit);} catch(...) {}
try{j.at("debug").at("jumpTransitionEasing").get_to(jumpTransitionEasing);} 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(...) {}
try{j.at("debug").at("maxComponentsInNode").get_to(DrawingProgramCache::MAXIMUM_COMPONENTS_IN_SINGLE_NODE);} catch(...) {}
try{j.at("debug").at("componentCountToForceCacheRebuild").get_to(DrawingProgramCache::MINIMUM_COMPONENTS_TO_START_REBUILD);} catch(...) {}
try{j.at("debug").at("maximumFrameTimeToForceCacheRebuild").get_to(DrawingProgramCache::MILLISECOND_FRAME_TIME_TO_FORCE_CACHE_REFRESH);} catch(...) {}
try{j.at("debug").at("millisecondMinimumTimeToCheckForCacheRebuild").get_to(DrawingProgramCache::MILLISECOND_MINIMUM_TIME_TO_CHECK_FORCE_REFRESH);} catch(...) {}
}

63
src/GlobalConfig.hpp Normal file
View file

@ -0,0 +1,63 @@
#pragma once
#include <nlohmann/json.hpp>
#include <Helpers/VersionNumber.hpp>
#include "InputManager.hpp"
#define DEFAULT_CANVAS_BACKGROUND_COLOR Vector3f{0.07f, 0.07f, 0.07f}
class GlobalConfig {
public:
GlobalConfig();
float guiScale = 1.0f;
double dragZoomSpeed = 0.02;
double scrollZoomSpeed = 0.4;
float jumpTransitionTime = 0.5f;
Vector4f jumpTransitionEasing{0.75, 0.25, 0.25, 0.75};
bool viewWebVersionWelcome = false;
struct TabletOptions {
bool pressureAffectsBrushWidth = true;
float smoothingSamplingTime = 0.04f;
uint8_t middleClickButton = 1;
uint8_t rightClickButton = 2;
bool ignoreMouseMovementWhenPenInProximity = false;
float brushMinimumSize = 0.0f;
bool zoomWhilePenDownAndButtonHeld = true;
} tabletOptions;
Vector3f defaultCanvasBackgroundColor = DEFAULT_CANVAS_BACKGROUND_COLOR;
float fpsLimit = 10000.0f;
nlohmann::json get_config_json(const InputManager& input) const;
void set_config_json(InputManager& input, const nlohmann::json& j, VersionNumber version);
bool showPerformance = false;
bool checkForUpdates = false;
bool useNativeFilePicker = true;
std::string themeCurrentlyLoaded = "Default";
enum class AntiAliasing {
NONE,
SKIA,
DYNAMIC_MSAA
} antialiasing = AntiAliasing::DYNAMIC_MSAA;
std::string displayName;
bool flipZoomToolDirection = false;
bool disableGraphicsDriverWorkarounds = false;
int vsyncValue = 1;
#ifndef __EMSCRIPTEN__
bool applyDisplayScale = true;
#endif
};
NLOHMANN_JSON_SERIALIZE_ENUM(GlobalConfig::AntiAliasing, {
{GlobalConfig::AntiAliasing::NONE, "None"},
{GlobalConfig::AntiAliasing::SKIA, "Skia"},
{GlobalConfig::AntiAliasing::DYNAMIC_MSAA, "Dynamic MSAA"},
})

View file

@ -326,7 +326,7 @@ void InputManager::set_clipboard_plain_and_richtext_pair(const std::pair<std::st
lastCopiedRichText = plainAndRichtextPair.second;
}
std::string InputManager::key_assignment_to_str(const Vector2ui32& k) {
std::string InputManager::key_assignment_to_str(const Vector2ui32& k) const {
std::string toRet;
if(k.x() & SDL_KMOD_CTRL)
toRet += "CTRL+";
@ -340,7 +340,7 @@ std::string InputManager::key_assignment_to_str(const Vector2ui32& k) {
return toRet;
}
Vector2ui32 InputManager::key_assignment_from_str(const std::string& s) {
Vector2ui32 InputManager::key_assignment_from_str(const std::string& s) const {
Vector2ui32 toRet = {0, 0};
if(s.find("CTRL+") != std::string::npos)
toRet.x() |= SDL_KMOD_CTRL;
@ -489,7 +489,7 @@ void InputManager::backend_pen_button_down_update(const SDL_PenButtonEvent& e) {
pen.buttons[e.button].held = true;
pen.isEraser = e.pen_state & SDL_PEN_INPUT_ERASER_TIP;
if(e.button == main.toolbar.tabletOptions.middleClickButton) {
if(e.button == main.conf.tabletOptions.middleClickButton) {
main.input_mouse_button_callback({
.deviceType = MouseDeviceType::PEN,
.button = MouseButton::MIDDLE,
@ -498,7 +498,7 @@ void InputManager::backend_pen_button_down_update(const SDL_PenButtonEvent& e) {
.pos = mouseNewPos
});
}
else if(e.button == main.toolbar.tabletOptions.rightClickButton) {
else if(e.button == main.conf.tabletOptions.rightClickButton) {
main.input_mouse_button_callback({
.deviceType = MouseDeviceType::PEN,
.button = MouseButton::RIGHT,
@ -525,7 +525,7 @@ void InputManager::backend_pen_button_up_update(const SDL_PenButtonEvent& e) {
pen.buttons[e.button].held = false;
pen.isEraser = e.pen_state & SDL_PEN_INPUT_ERASER_TIP;
if(e.button == main.toolbar.tabletOptions.middleClickButton) {
if(e.button == main.conf.tabletOptions.middleClickButton) {
main.input_mouse_button_callback({
.deviceType = MouseDeviceType::PEN,
.button = MouseButton::MIDDLE,
@ -534,7 +534,7 @@ void InputManager::backend_pen_button_up_update(const SDL_PenButtonEvent& e) {
.pos = mouseNewPos
});
}
else if(e.button == main.toolbar.tabletOptions.rightClickButton) {
else if(e.button == main.conf.tabletOptions.rightClickButton) {
main.input_mouse_button_callback({
.deviceType = MouseDeviceType::PEN,
.button = MouseButton::RIGHT,

View file

@ -302,8 +302,8 @@ struct InputManager {
std::optional<RichText::TextData> lastCopiedRichText;
std::string key_assignment_to_str(const Vector2ui32& k);
Vector2ui32 key_assignment_from_str(const std::string& s);
std::string key_assignment_to_str(const Vector2ui32& k) const;
Vector2ui32 key_assignment_from_str(const std::string& s) const;
const KeyData& key(KeyCode kCode);

View file

@ -40,8 +40,6 @@ MainProgram::MainProgram():
fonts(std::make_shared<FontData>()),
toolbar(*this)
{
displayName = Random::get().alphanumeric_str(10);
Logger::get().add_log("WORLDFATAL", [&](const std::string& text) {
*logFile << "[WORLDFATAL] " << text << std::endl;
std::cout << "[WORLDFATAL] " << text << std::endl;
@ -65,7 +63,7 @@ MainProgram::MainProgram():
}
void MainProgram::update() {
while(std::chrono::duration_cast<std::chrono::duration<float>>(std::chrono::steady_clock::now() - lastFrameTime).count() < 1.0 / fpsLimit);
while(std::chrono::duration_cast<std::chrono::duration<float>>(std::chrono::steady_clock::now() - lastFrameTime).count() < 1.0 / conf.fpsLimit);
lastFrameTime = std::chrono::steady_clock::now();
input.update();
@ -120,7 +118,7 @@ bool MainProgram::app_close_requested() {
void MainProgram::update_display_names() {
for(auto& w : worlds) {
if(!w->netObjMan.is_connected())
w->ownClientData->set_display_name(displayName);
w->ownClientData->set_display_name(conf.displayName);
}
}
@ -160,7 +158,7 @@ void MainProgram::save_config() {
json j;
j["version"] = VersionConstants::CURRENT_VERSION_STRING;
j["settings"] = toolbar.get_config_json();
j["settings"] = conf.get_config_json(input);
j["window"]["pos"] = window.writtenPos;
j["window"]["size"] = window.writtenSize;
j["window"]["maximized"] = window.maximized;
@ -206,7 +204,7 @@ void MainProgram::load_config() {
catch(...) {}
try {
toolbar.set_config_json(j["settings"], version);
conf.set_config_json(input, j["settings"], version);
}
catch(...) {}
#ifndef __EMSCRIPTEN__
@ -238,11 +236,13 @@ void MainProgram::load_config() {
toolbar.viewWebVersionWelcome = true;
#endif
toolbar.load_palettes();
toolbar.load_theme();
g.load_theme(configPath, conf.themeCurrentlyLoaded);
toolbar.load_licenses();
NetLibrary::copy_default_p2p_config_to_path(configPath / "p2p.json");
update_display_names();
set_vsync_value(conf.vsyncValue);
refresh_draw_surfaces();
}
@ -255,14 +255,14 @@ void MainProgram::set_vsync_value(int vsyncValue) {
}
SDL_GL_SetSwapInterval(1);
}
window.vsyncValue = vsyncValue;
conf.vsyncValue = vsyncValue;
}
void MainProgram::update_scale_and_density() {
#ifdef __EMSCRIPTEN__
window.scale = 1.0f;
#else
window.scale = window.applyDisplayScale ? SDL_GetWindowDisplayScale(window.sdlWindow) : 1.0f;
window.scale = conf.applyDisplayScale ? SDL_GetWindowDisplayScale(window.sdlWindow) : 1.0f;
#endif
window.density = SDL_GetWindowPixelDensity(window.sdlWindow);
}
@ -274,7 +274,7 @@ float MainProgram::get_scale_and_density_factor_gui() {
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.defaultMSAASurfaceProps = SkSurfaceProps(conf.antialiasing == GlobalConfig::AntiAliasing::DYNAMIC_MSAA ? SkSurfaceProps::kDynamicMSAA_Flag : SkSurfaceProps::kDefault_Flag, kUnknown_SkPixelGeometry);
window.intermediateSurface = create_native_surface(window.size, true);
window.intermediateCanvas = window.intermediateSurface->getCanvas();
@ -288,10 +288,8 @@ void MainProgram::refresh_draw_surfaces() {
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());
DrawData drawDataCopy = drawData;
drawDataCopy.skiaAA = antialiasing == AntiAliasing::SKIA;
drawDataCopy.skiaAA = conf.antialiasing == GlobalConfig::AntiAliasing::SKIA;
worldToDraw->draw(canvas, drawDataCopy);
if(!drawData.takingScreenshot)
toolbar.draw(canvas, drawDataCopy.skiaAA);
}
sk_sp<SkSurface> MainProgram::create_native_surface(Vector2i resolution, bool isMSAA) {
@ -348,25 +346,21 @@ void MainProgram::input_key_callback(const InputManager::KeyCallbackArgs& key) {
drawGui = !drawGui;
}
}
toolbar.input_key_callback(key);
if(world)
world->input_key_callback(key);
}
void MainProgram::input_mouse_button_callback(const InputManager::MouseButtonCallbackArgs& button) {
toolbar.input_mouse_button_callback(button);
if(world)
world->input_mouse_button_callback(button);
}
void MainProgram::input_mouse_motion_callback(const InputManager::MouseMotionCallbackArgs& motion) {
toolbar.input_mouse_motion_callback(motion);
if(world)
world->input_mouse_motion_callback(motion);
}
void MainProgram::input_mouse_wheel_callback(const InputManager::MouseWheelCallbackArgs& wheel) {
toolbar.input_mouse_wheel_callback(wheel);
if(world)
world->input_mouse_wheel_callback(wheel);
}
@ -402,11 +396,9 @@ void MainProgram::input_multi_finger_motion_callback(const InputManager::MultiFi
}
void MainProgram::input_finger_touch_callback(const InputManager::FingerTouchCallbackArgs& touch) {
toolbar.input_finger_touch_callback(touch);
}
void MainProgram::input_finger_motion_callback(const InputManager::FingerMotionCallbackArgs& motion) {
toolbar.input_finger_motion_callback(motion);
}
bool MainProgram::network_being_used() {

View file

@ -12,6 +12,8 @@
#include "Toolbar.hpp"
#include "World.hpp"
#include "DrawingProgram/ToolConfiguration.hpp"
#include "GUIHolder.hpp"
#include "GlobalConfig.hpp"
#ifdef USE_SKIA_BACKEND_GRAPHITE
#include "include/gpu/graphite/Recorder.h"
@ -28,7 +30,6 @@ class MainProgram {
InputManager input;
std::chrono::steady_clock::time_point lastFrameTime = std::chrono::steady_clock::now();
float fpsLimit = 10000.0f;
Vector3f userColor;
@ -42,15 +43,9 @@ class MainProgram {
bool fullscreen = false;
SkColorType defaultColorType;
SkAlphaType defaultAlphaType;
int vsyncValue = 1;
float density = 1.0f;
float scale = 1.0f;
#ifndef __EMSCRIPTEN__
bool applyDisplayScale = true;
#endif
bool disableGraphicsDriverWorkarounds = false;
int defaultMSAASampleCount = 0;
SkSurfaceProps defaultMSAASurfaceProps;
@ -92,12 +87,6 @@ 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();
@ -124,12 +113,11 @@ class MainProgram {
bool drawGui = true;
Vector3f defaultCanvasBackgroundColor = DEFAULT_CANVAS_BACKGROUND_COLOR;
size_t worldIndex = 0;
std::vector<std::shared_ptr<World>> worlds;
std::string displayName;
GUIHolder g;
GlobalConfig conf;
void input_drop_file_callback(const InputManager::DropCallbackArgs& drop);
void input_drop_text_callback(const InputManager::DropCallbackArgs& drop);
@ -159,9 +147,3 @@ 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

@ -23,10 +23,10 @@ bool FileResourceDisplay::load(ResourceManager& rMan, const std::string& fileNam
}
void FileResourceDisplay::draw(SkCanvas* canvas, const DrawData& drawData, const SkRect& imRect) {
std::shared_ptr<GUIStuff::UpdateInputData>& io = drawData.main->toolbar.io;
auto findSVGData = io->svgData.find(FILE_ICON_PATH);
GUIStuff::UpdateInputData& io = drawData.main->g.gui.io;
auto findSVGData = io.svgData.find(FILE_ICON_PATH);
sk_sp<SkSVGDOM> svgDom;
if(findSVGData == io->svgData.end())
if(findSVGData == io.svgData.end())
throw std::runtime_error("[FileResourceDisplay::draw] Could not load icon " + FILE_ICON_PATH);
else
svgDom = findSVGData->second;

File diff suppressed because it is too large Load diff

View file

@ -40,15 +40,8 @@ class Toolbar {
std::string chatMessageInput;
Toolbar(MainProgram& initMain);
void input_key_callback(const InputManager::KeyCallbackArgs& key);
void input_mouse_button_callback(const InputManager::MouseButtonCallbackArgs& button);
void input_mouse_motion_callback(const InputManager::MouseMotionCallbackArgs& motion);
void input_mouse_wheel_callback(const InputManager::MouseWheelCallbackArgs& wheel);
void input_finger_touch_callback(const InputManager::FingerTouchCallbackArgs& touch);
void input_finger_motion_callback(const InputManager::FingerMotionCallbackArgs& motion);
void update();
void layout_run();
void draw(SkCanvas* canvas, bool skiaAA);
void color_selector_left(Vector4f* color);
void color_selector_right(Vector4f* color);
void paint_popup(Vector2f popupPos);
@ -58,34 +51,11 @@ class Toolbar {
void save_func();
void save_as_func();
std::filesystem::path& file_selector_path();
std::shared_ptr<GUIStuff::UpdateInputData> io;
GUIStuff::GUIManager gui;
nlohmann::json get_config_json();
void set_config_json(const nlohmann::json& j, VersionNumber version);
void save_palettes();
void load_palettes();
void save_theme();
bool load_theme();
void load_licenses();
double dragZoomSpeed = 0.02;
double scrollZoomSpeed = 0.4;
float jumpTransitionTime = 0.5f;
Vector4f jumpTransitionEasing{0.75, 0.25, 0.25, 0.75};
bool viewWebVersionWelcome = false;
struct TabletOptions {
bool pressureAffectsBrushWidth = true;
float smoothingSamplingTime = 0.04f;
uint8_t middleClickButton = 1;
uint8_t rightClickButton = 2;
bool ignoreMouseMovementWhenPenInProximity = false;
float brushMinimumSize = 0.0f;
bool zoomWhilePenDownAndButtonHeld = true;
} tabletOptions;
Vector4f* colorLeft = nullptr;
Vector4f* colorRight = nullptr;
bool isUpdatingColorLeft = false;
@ -93,7 +63,6 @@ class Toolbar {
std::optional<Vector2f> rightClickPopupLocation;
bool flipZoomToolDirection = false;
float final_gui_scale();
@ -146,7 +115,6 @@ class Toolbar {
void update_notification_gui();
void update_notification_check();
struct UpdateCheckerData {
bool checkForUpdates = true;
bool showGui = false;
bool updateCheckDone = false;
std::string newVersionStr;
@ -177,7 +145,6 @@ class Toolbar {
struct ThemeData {
std::vector<std::string> themeDirList;
std::optional<size_t> selectedThemeIndex;
std::string themeCurrentlyLoaded = "Default";
bool openedSaveAsMenu = false;
} themeData;
@ -190,7 +157,6 @@ class Toolbar {
bool optionsMenuOpen = false;
bool playerMenuOpen = false;
float guiScale = 1.0f;
float finalCalculatedGuiScale = 1.0f;
enum {
@ -225,7 +191,6 @@ class Toolbar {
uint32_t selectedGrid = std::numeric_limits<uint32_t>::max();
} gridMenu;
bool useNativeFilePicker = true;
struct FilePicker {
bool isOpen = false;
std::string filePickerWindowName;
@ -249,8 +214,6 @@ class Toolbar {
std::optional<unsigned> keybindWaiting;
std::filesystem::path testing;
std::unique_ptr<skia::textlayout::Paragraph> build_paragraph_from_chat_message(const ChatMessage& message, float alpha);
void load_icons_at(const std::filesystem::path& pathToLoad);

View file

@ -80,7 +80,7 @@ void World::init_client_data_list() {
clients = netObjMan.make_obj<NetworkingObjects::NetObjUnorderedSet<ClientData>>();
ownClientData = clients->emplace_direct(clients, ClientData::InitStruct{
.cursorColor = get_random_cursor_color(),
.displayName = main.displayName
.displayName = main.conf.displayName
});
init_client_data_list_callbacks();
}
@ -161,7 +161,7 @@ void World::init_client(const std::string& serverFullID) {
netClient->add_recv_callback(CLIENT_KEEP_ALIVE, [&](cereal::PortableBinaryInputArchive& message) {
});
netClient->send_items_to_server(RELIABLE_COMMAND_CHANNEL, SERVER_INITIAL_DATA, main.displayName);
netClient->send_items_to_server(RELIABLE_COMMAND_CHANNEL, SERVER_INITIAL_DATA, main.conf.displayName);
}
void World::focus_update() {

View file

@ -19,8 +19,6 @@ class MainProgram;
//#define ENABLE_ORDERED_LIST_TEST
#define DEFAULT_CANVAS_BACKGROUND_COLOR Vector3f{0.07f, 0.07f, 0.07f}
class World {
public:
static constexpr std::string FILE_EXTENSION = "infpnt";

View file

@ -353,12 +353,12 @@ void WorldGrid::draw_coordinates(SkCanvas* canvas, const DrawData& drawData, Vec
const WorldVec& worldWindowTopLeftClipPos = coordinatesAxisOnBounds ? bounds.value().min : drawData.cam.c.pos;
SCollision::AABB<float> boundsCamSpace;
float coordFontSize = drawData.main->toolbar.final_gui_scale() * drawData.main->toolbar.io->fontSize;
float coordFontSize = drawData.main->toolbar.final_gui_scale() * drawData.main->g.gui.io.fontSize;
if(coordinatesAxisOnBounds)
boundsCamSpace = SCollision::AABB<float>(drawData.cam.c.to_space(bounds.value().min), drawData.cam.c.to_space(bounds.value().max));
else {
float toolbarXLength = drawData.main->drawGui ? drawData.main->toolbar.final_gui_scale() * (50.0f + drawData.main->toolbar.io->theme->padding1 * 3.0f) : 0.0f;
float toolbarXLength = drawData.main->drawGui ? drawData.main->toolbar.final_gui_scale() * (50.0f + drawData.main->g.gui.io.theme->padding1 * 3.0f) : 0.0f;
boundsCamSpace = SCollision::AABB<float>({toolbarXLength + axisOffset.x(), 0.0f}, {drawData.cam.viewingArea.x(), drawData.cam.viewingArea.y() - axisOffset.y()});
if(boundsCamSpace.width() < 100.0f || boundsCamSpace.height() < 100.0f)
return;
@ -371,7 +371,7 @@ void WorldGrid::draw_coordinates(SkCanvas* canvas, const DrawData& drawData, Vec
return;
}
SkFont f = drawData.main->toolbar.io->get_font(coordFontSize);
SkFont f = drawData.main->g.gui.io.get_font(coordFontSize);
SkFontMetrics metrics;
f.getMetrics(&metrics);
float fontHeight = (-metrics.fAscent + metrics.fDescent);
@ -493,9 +493,9 @@ void WorldGrid::draw_coordinates(SkCanvas* canvas, const DrawData& drawData, Vec
canvas->clipRect(SkRect::MakeLTRB(boundsCamSpace.min.x(), boundsCamSpace.min.y(), boundsCamSpace.max.x(), boundsCamSpace.max.y()));
}
canvas->drawRect(SkRect::MakeXYWH(boundsCamSpace.min.x(), boundsCamSpace.min.y(), yAxisMaxXLength, boundsCamSpace.max.y() - boundsCamSpace.min.y()), SkPaint{color_mul_alpha(drawData.main->toolbar.io->theme->backColor1, 0.9f)});
canvas->drawRect(SkRect::MakeXYWH(boundsCamSpace.min.x(), boundsCamSpace.min.y(), yAxisMaxXLength, boundsCamSpace.max.y() - boundsCamSpace.min.y()), SkPaint{color_mul_alpha(drawData.main->g.gui.io.theme->backColor1, 0.9f)});
if(!xAxisLabels.empty())
canvas->drawRect(SkRect::MakeLTRB(boundsCamSpace.min.x() + yAxisMaxXLength, xAxisYPosRect, boundsCamSpace.max.x(), boundsCamSpace.max.y()), SkPaint{color_mul_alpha(drawData.main->toolbar.io->theme->backColor1, 0.9f)});
canvas->drawRect(SkRect::MakeLTRB(boundsCamSpace.min.x() + yAxisMaxXLength, xAxisYPosRect, boundsCamSpace.max.x(), boundsCamSpace.max.y()), SkPaint{color_mul_alpha(drawData.main->g.gui.io.theme->backColor1, 0.9f)});
for(auto& l : xAxisLabels) {
canvas->drawSimpleText(l.mainText.c_str(), l.mainText.length(), SkTextEncoding::kUTF8, l.mainPos, xAxisYPosLabels, f, labelColor);

View file

@ -499,7 +499,7 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char **argv) {
GrContextOptions opts;
opts.fSuppressPrints = true;
opts.fDisableDriverCorrectnessWorkarounds = mS.m->window.disableGraphicsDriverWorkarounds; // Driver workarounds causing glitches on intel drivers on windows, but are required in the Emscripten version. Good idea to have a toggle for it
opts.fDisableDriverCorrectnessWorkarounds = mS.m->conf.disableGraphicsDriverWorkarounds; // Driver workarounds causing glitches on intel drivers on windows, but are required in the Emscripten version. Good idea to have a toggle for it
mS.ctx = GrDirectContexts::MakeGL(iface, opts);
if(!mS.ctx)