diff --git a/.gitmodules b/.gitmodules index cc83a83..8969bad 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,3 @@ [submodule "third_party/msdfgen"] path = third_party/msdfgen - url = https://github.com/Chlumsky/msdfgen.git -[submodule "third_party/LLGL"] - path = third_party/LLGL - url = https://github.com/LukasBanana/LLGL.git + url = https://github.com/Chlumsky/msdfgen.git \ No newline at end of file diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index 3a9e12a..7be86f4 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -5,6 +5,6 @@ set(SRC_FILES "") retrieve_files(${CMAKE_CURRENT_SOURCE_DIR}/src SRC_FILES) add_executable(${PROJECT_NAME} ${SRC_FILES}) target_link_libraries(${PROJECT_NAME} PRIVATE mirage_core) -if (WIN32) +if (MSVC) target_link_options(${PROJECT_NAME} PRIVATE "/SUBSYSTEM:WINDOWS" "/ENTRY:mainCRTStartup") endif() diff --git a/example/src/main.cpp b/example/src/main.cpp index c1708c1..0286b4b 100644 --- a/example/src/main.cpp +++ b/example/src/main.cpp @@ -22,8 +22,8 @@ int main(int argc, char* argv[]) { auto button = std::make_shared(); border->set_content(button) - .h_alignment(horizontal_alignment::center) - .v_alignment(vertical_alignment::center) + .h_alignment(horizontal_alignment::stretch) + .v_alignment(vertical_alignment::bottom) .margin({ 20 }); app.run(); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9f488de..c96bc11 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -27,6 +27,7 @@ add_shader_dependencies(${PROJECT_NAME}) if (WIN32) target_compile_definitions(${PROJECT_NAME} PUBLIC -DSOKOL_D3D11) + target_link_libraries(${PROJECT_NAME} PUBLIC d3d11 dxgi) elseif (UNIX) target_compile_definitions(${PROJECT_NAME} PUBLIC -DSOKOL_GLCORE33) endif () diff --git a/src/core/render_elements.cpp b/src/core/render_elements.cpp index b7fcb87..7a5a6c2 100644 --- a/src/core/render_elements.cpp +++ b/src/core/render_elements.cpp @@ -210,7 +210,7 @@ void render_elements::make_rect( float in_rotation_radians, const Eigen::Vector2f& in_pivot, const Eigen::Vector2f& in_scale) { - const auto& pos = in_geometry.absolute_to_local(in_pos); + const auto& pos = in_geometry.local_to_parent(in_pos); add_rect_to_batch(pos, in_size, in_color, diff --git a/src/core/window/render_window.cpp b/src/core/window/render_window.cpp index cbf12f8..81e728a 100644 --- a/src/core/window/render_window.cpp +++ b/src/core/window/render_window.cpp @@ -3,7 +3,7 @@ #include "widget/mwidget.h" void mirage_window::on_paint() { - if (!child_slot_.get()) + if (!content_widget_) return; elements_.begin_frame(); @@ -12,16 +12,29 @@ void mirage_window::on_paint() { } geometry_t mirage_window::get_window_geometry_in_screen() const { - auto local_to_screen = get_local_to_screen_transform(); + auto local_to_screen = get_local_to_window_transform(); geometry_t root_geometry(get_window_frame_size().cast(), local_to_screen, transform2d()); return root_geometry; } -void mirage_window::on_set_content(const std::shared_ptr& in_widget) { - // layout_tree_.get_root()->add_child(in_widget); +void mirage_window::arrange_children(const geometry_t& in_allotted_geometry, arranged_children& in_arranged_children) { + if (content_widget_) { + auto child_geo = in_allotted_geometry.make_child({0, 0}, get_window_frame_size().cast()); + in_arranged_children.add_widget(arranged_widget(child_geo, content_widget_)); + } +} + +void mirage_window::set_content(const std::shared_ptr& in_widget) { + content_widget_ = in_widget; layout_tree_.invalidate_layout(); } +std::vector> mirage_window::get_children() const { + if (content_widget_) + return { content_widget_ }; + return mwidget::get_children(); +} + void mirage_window::on_resize(int width, int height) { const Eigen::Vector2i size(width, height); state_->swapchain.width = width; @@ -47,3 +60,8 @@ void mirage_window::init_window() { layout_tree_.set_root_geometry(root_geometry); } +uint32_t mirage_window::on_paint(render_elements& in_drawer, geometry_t& in_geometry, uint32_t in_layer) { + if (content_widget_) + return content_widget_->on_paint(in_drawer, in_geometry, in_layer); + return in_layer; +} diff --git a/src/core/window/render_window.h b/src/core/window/render_window.h index 2e7d606..36ed98d 100644 --- a/src/core/window/render_window.h +++ b/src/core/window/render_window.h @@ -24,10 +24,13 @@ struct mirage_window_state { }; struct window_slot : mcompound_widget_slot { - + window_slot() { + h_alignment(horizontal_alignment::stretch); + v_alignment(vertical_alignment::stretch); + } }; -class mirage_window : public mcompound_widget { +class mirage_window : public mwidget { public: bool create_window(int width, int height, const wchar_t* title); @@ -82,15 +85,23 @@ public: [[nodiscard]] geometry_t get_window_geometry_in_screen() const; virtual Eigen::Vector2f compute_desired_size(float in_layout_scale_multiplier) const override { return get_window_frame_size().cast(); } -protected: - virtual void on_set_content(const std::shared_ptr& in_widget) override; + + virtual void arrange_children(const geometry_t& in_allotted_geometry, arranged_children& in_arranged_children) override; + void set_content(const std::shared_ptr& in_widget); + virtual std::vector> get_children() const override; private: void init_window(); - void* window_handle_{}; - bool close_request_ = false; +public: + virtual uint32_t on_paint(render_elements& in_drawer, geometry_t& in_geometry, uint32_t in_layer) override; + +private: + void* window_handle_{}; + bool close_request_ = false; render_elements elements_; // 渲染元素 std::unique_ptr state_; + + std::shared_ptr content_widget_; widget_layout_tree layout_tree_; }; diff --git a/src/core/window/windows/windows_render_context.cpp b/src/core/window/windows/windows_render_context.cpp index 28ad2b0..397e1dd 100644 --- a/src/core/window/windows/windows_render_context.cpp +++ b/src/core/window/windows/windows_render_context.cpp @@ -41,10 +41,7 @@ bool windows_mirage_render_context::init() { // 尝试按优先级创建设备 HRESULT hr = E_FAIL; D3D_DRIVER_TYPE used_driver_type = D3D_DRIVER_TYPE_UNKNOWN; - // 使用 DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2(推荐) - if (SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2)) { - std::cout << "mirage: " << "DPI awareness set to per-monitor aware v2" << std::endl; - } + SetProcessDPIAware(); for (const auto& driver_type: driver_types) { hr = D3D11CreateDevice( diff --git a/src/geometry/arranged_children.h b/src/geometry/arranged_children.h index bcdb8d4..6401234 100644 --- a/src/geometry/arranged_children.h +++ b/src/geometry/arranged_children.h @@ -12,6 +12,7 @@ public: widget_(std::move(in_widget)) { } + [[nodiscard]] auto& get_geometry() { return geometry_; } [[nodiscard]] const auto& get_geometry() const { return geometry_; } [[nodiscard]] const auto& get_widget() const { return widget_; } auto operator==(const arranged_widget& in_other) const { @@ -30,6 +31,14 @@ public: std::ranges::reverse(children_); } + [[nodiscard]] auto accepts(visibility in_visibility) const { + return in_visibility >= visibility_filter_; + } + + void set_filter(visibility in_visibility_filter) { + visibility_filter_ = in_visibility_filter; + } + void add_widget(visibility in_visibility_override, const arranged_widget& in_widget_geometry) { if (accepts(in_visibility_override)) children_.push_back(in_widget_geometry); @@ -43,15 +52,8 @@ public: void add_widget(const arranged_widget& in_widget_geometry); void insert_widget(const arranged_widget& in_widget_geometry, size_t in_index); - [[nodiscard]] auto accepts(visibility in_visibility) const { - return in_visibility >= visibility_filter_; - } - - void set_filter(visibility in_visibility_filter) { - visibility_filter_ = in_visibility_filter; - } - [[nodiscard]] const auto& get_children() const { return children_; } + [[nodiscard]] auto& get_children() { return children_; } private: visibility visibility_filter_; std::vector children_; diff --git a/src/geometry/geometry.h b/src/geometry/geometry.h index 33a0945..1c3db1e 100644 --- a/src/geometry/geometry.h +++ b/src/geometry/geometry.h @@ -189,6 +189,25 @@ public: return geometry_t(size_, new_local_to_parent, parent_to_absolute); } + + /** + * 按照边距偏移变换 + * + * @param in_margin 要缩小的边距 + */ + void shrink(const margin_t& in_margin) { + // 获取左上角偏移 + const Eigen::Vector2f offset = in_margin.left_top(); + + // 创建一个表示偏移的变换(从缩小后的空间到原始空间) + transform2d offset_transform; + offset_transform.set_transform(offset, 0.0f, Eigen::Vector2f(1.0f, 1.0f)); + + // 更新变换 - 先应用原变换,再应用偏移变换 + local_to_parent_ = local_to_parent_.concatenate(offset_transform); + local_to_absolute_ = local_to_absolute_.concatenate(offset_transform); + } + private: Eigen::Vector2f size_; transform2d local_to_parent_; diff --git a/src/geometry/margin.h b/src/geometry/margin.h index 8f10d57..9ce5471 100644 --- a/src/geometry/margin.h +++ b/src/geometry/margin.h @@ -15,6 +15,25 @@ struct margin_t { static auto all(float in_uniform) { return margin_t(in_uniform); } static auto symmetric(float in_horizontal, float in_vertical) { return margin_t(in_horizontal, in_vertical); } + auto left_top() const { + return Eigen::Vector2f(left, top); + } + auto right_bottom() const { + return Eigen::Vector2f(right, bottom); + } + auto horizontal() const { + return left + right; + } + auto vertical() const { + return top + bottom; + } + auto area() const { + return horizontal() * vertical(); + } + auto size() const { + return Eigen::Vector2f(horizontal(), vertical()); + } + auto is_zero() const { return left == 0 && right == 0 && top == 0 && bottom == 0; } diff --git a/src/widget/compound_widget/mborder.cpp b/src/widget/compound_widget/mborder.cpp index 494785d..6709b36 100644 --- a/src/widget/compound_widget/mborder.cpp +++ b/src/widget/compound_widget/mborder.cpp @@ -1,7 +1,11 @@ #include "mborder.h" void mborder::arrange_children(const geometry_t& in_allotted_geometry, arranged_children& in_arranged_children) { - mcompound_widget::arrange_children(in_allotted_geometry, in_arranged_children); - - + mcompound_widget::arrange_children(in_allotted_geometry, in_arranged_children); + auto& children = in_arranged_children.get_children(); + for (auto& child: children) { + auto& child_geo = child.get_geometry(); + const auto& margin = child_slot_.margin(); + child_geo.shrink(margin); + } } diff --git a/src/widget/compound_widget/mborder.h b/src/widget/compound_widget/mborder.h index 2a4c3c1..a3a1f46 100644 --- a/src/widget/compound_widget/mborder.h +++ b/src/widget/compound_widget/mborder.h @@ -3,17 +3,12 @@ #include "geometry/margin.h" struct mborder_slot : mcompound_widget_slot { -public: mborder_slot() { - h_alignment_ = horizontal_alignment::stretch; - v_alignment_ = vertical_alignment::stretch; + h_alignment(horizontal_alignment::stretch); + v_alignment(vertical_alignment::stretch); } - auto& margin(const margin_t& in_margin) { - margin_ = in_margin; - return me(); - } -protected: - margin_t margin_{}; + + SLOT_ATTRIBUTE(margin_t, margin) }; class mborder : public mcompound_widget { diff --git a/src/widget/compound_widget/mcompound_widget.h b/src/widget/compound_widget/mcompound_widget.h index 28cc686..34e911a 100644 --- a/src/widget/compound_widget/mcompound_widget.h +++ b/src/widget/compound_widget/mcompound_widget.h @@ -1,39 +1,16 @@ #pragma once #include "widget/mwidget.h" +#include "widget/slot_util.h" template struct mcompound_widget_slot { -public: auto& me() { return static_cast(*this); } - void set(const std::shared_ptr& in_widget) { - widget_ = in_widget; - } - const auto& get() const { - return widget_; - } - - auto& h_alignment(horizontal_alignment in_alignment) { - h_alignment_ = in_alignment; - return me(); - } - auto h_alignment() const { return h_alignment_; } - auto& v_alignment(vertical_alignment in_alignment) { - v_alignment_ = in_alignment; - return me(); - } - auto v_alignment() const { return v_alignment_; } - - auto& operator[](const std::shared_ptr& in_widget) { - set(in_widget); - return me(); - } -protected: - std::shared_ptr widget_{}; - horizontal_alignment h_alignment_{}; - vertical_alignment v_alignment_{}; + SLOT_ATTRIBUTE(horizontal_alignment, h_alignment) + SLOT_ATTRIBUTE(vertical_alignment, v_alignment) + SLOT_CONTENT() }; template @@ -90,7 +67,7 @@ void mcompound_widget::arrange_children(const geometry_t& in_allotted_ break; case horizontal_alignment::center: child_size.x() = child_desired_size.x(); - child_pos.x() = (local_size.x() - child_desired_size.x()) / 2; + child_pos.x() = local_size.x() / 2 - child_desired_size.x(); break; case horizontal_alignment::right: child_size.x() = local_size.x() - child_desired_size.x(); @@ -109,7 +86,7 @@ void mcompound_widget::arrange_children(const geometry_t& in_allotted_ break; case vertical_alignment::center: child_size.y() = child_desired_size.y(); - child_pos.y() = (local_size.y() - child_desired_size.y()) / 2; + child_pos.y() = local_size.y() / 2 - child_desired_size.y(); break; case vertical_alignment::bottom: child_size.y() = local_size.y() - child_desired_size.y(); @@ -122,9 +99,8 @@ void mcompound_widget::arrange_children(const geometry_t& in_allotted_ default:break; } - geometry_t child_geometry = in_allotted_geometry.make_child(child_pos, child_size); - - in_arranged_children.add_widget(arranged_widget(child_geometry, child_widget)); + const auto child_geo = in_allotted_geometry.make_child(child_pos, child_size); + in_arranged_children.add_widget(arranged_widget(child_geo, child_widget)); } } diff --git a/src/widget/slot_util.h b/src/widget/slot_util.h new file mode 100644 index 0000000..c1e4366 --- /dev/null +++ b/src/widget/slot_util.h @@ -0,0 +1,27 @@ +#pragma once + +#define SLOT_ME() auto& me() { return static_cast(*this) } + +#define SLOT_ATTRIBUTE(type, name) \ + public: \ + auto& name(type in_##name) { \ + name##_ = in_##name; \ + return me(); \ + } \ + const auto& name() const { return name##_; } \ + protected: \ + type name##_{}; + +#define SLOT_CONTENT() \ + public: \ + auto& set(const std::shared_ptr& in_widget) { \ + widget_ = in_widget; \ + return me(); \ + } \ + const auto& get() const { return widget_; } \ + auto& operator[](const std::shared_ptr& in_widget) { \ + set(in_widget); \ + return me(); \ + } \ + protected: \ + std::shared_ptr widget_{}; diff --git a/third_party/msdfgen b/third_party/msdfgen index 84bfb2a..0388956 160000 --- a/third_party/msdfgen +++ b/third_party/msdfgen @@ -1 +1 @@ -Subproject commit 84bfb2a402a3cffa4b44fb75123b37297ff37477 +Subproject commit 03889564a50452fa2e0b0a60973b5057001b391b