void printer::draw_text( const drawer out, const vec2i pos, const drafter& d, const ltrbi clipper ) const { const auto& colors = d.cached_str; auto& lines = d.lines; auto& sectors = d.sectors; const bool clip = clipper.good(); if (!lines.empty() && !sectors.empty()) { simple_pair<int, int> visible; if (clip) { visible = d.get_line_visibility(clipper - pos); } else { visible = { 0, static_cast<int>(lines.size()) - 1 }; } if (visible.first == -1) { return; } /* for every visible line */ for (unsigned l = visible.first; l <= static_cast<unsigned>(visible.second); ++l) { /* for every character in line */ for (unsigned i = lines[l].begin; i < lines[l].end; ++i) { /* shortcut */ auto& g = *d.cached[i]; /* if it's not a whitespace */ if (g.in_atlas.exists()) { rgba charcolor = style(colors[i]).color; out.aabb_clipped( g.in_atlas, xywhi({ sectors[i] + g.meta.bear_x, lines[l].top + lines[l].asc - g.meta.bear_y }, g.in_atlas.get_original_size()) + pos, clipper, charcolor ); } } } } }
void gui_system::advance_gui_elements(const logic_step step) { auto& cosmos = step.cosm; for (const auto root : cosmos.get(processing_subjects::WITH_GUI_ELEMENT)) { auto& element = root.get<components::gui_element>(); auto& rect_world = element.rect_world; const auto screen_size = element.get_screen_size(); if (root.has<components::item_slot_transfers>()) { game_gui_rect_tree tree; augs::gui::gui_entropy<game_gui_element_location> entropy; root_of_inventory_gui root_of_gui(screen_size); logic_gui_context context(step, root, tree, root_of_gui); root_of_inventory_gui_in_context root_location; rect_world.build_tree_data_into_context(context, root_location); const auto& entropies = step.entropy.entropy_per_entity; const auto& inputs_for_this_element = entropies.find(root); if (inputs_for_this_element != entropies.end()) { for (const auto& e : (*inputs_for_this_element).second) { //if (!element.is_gui_look_enabled) { // ensure(!e.has_event_for_gui); //} if (e.has_event_for_gui) { bool fetched = false; const auto& change = e.event_for_gui; const auto held_rect = context._dynamic_cast<item_button_in_item>(rect_world.rect_held_by_lmb); if (held_rect != nullptr) { const auto& item_entity = cosmos[held_rect.get_location().item_id]; auto& dragged_charges = element.dragged_charges; if (change.msg == augs::window::event::message::rdown || change.msg == augs::window::event::message::rdoubleclick ) { if (rect_world.held_rect_is_dragged) { step.transient.messages.post(item_slot_transfer_request_data{ item_entity, cosmos[inventory_slot_id()], dragged_charges }); fetched = true; } } if (change.msg == augs::window::event::message::wheel) { const auto& item = item_entity.get<components::item>(); const auto delta = change.scroll.amount; dragged_charges += delta; if (dragged_charges <= 0) { dragged_charges = item.charges + dragged_charges; } if (dragged_charges > item.charges) { dragged_charges = dragged_charges - item.charges; } } } if (!fetched) { rect_world.consume_raw_input_and_generate_gui_events(context, root_location, e.event_for_gui, entropy); } } } } // rect_world.call_idle_mousemotion_updater(context, root_location, entropy); rect_world.advance_elements(context, root_location, entropy, cosmos.get_fixed_delta()); auto& transfers = step.transient.messages.get_queue<item_slot_transfer_request_data>(); for (const auto& t : transfers) { perform_transfer(cosmos[t], step); } rect_world.rebuild_layouts(context, root_location); int max_height = 0; int total_width = 0; for (size_t i = 0; i < element.hotbar_buttons.size(); ++i) { const auto& hb = element.hotbar_buttons[i]; const auto bbox = hb.get_bbox(root); max_height = std::max(max_height, bbox.y); total_width += bbox.x; } const int left_rc_spacing = 2; const int right_rc_spacing = 1; int current_x = screen_size.x / 2 - total_width / 2 - left_rc_spacing; auto set_rc = [&](auto& hb) { const auto bbox = hb.get_bbox(root); hb.rc = xywh(xywhi(current_x, screen_size.y - max_height - 50, bbox.x + left_rc_spacing + right_rc_spacing, max_height)); current_x += bbox.x + left_rc_spacing + right_rc_spacing; }; for (size_t i = 1; i < element.hotbar_buttons.size(); ++i) { set_rc(element.hotbar_buttons[i]); } set_rc(element.hotbar_buttons[0]); transfers.clear(); } } }
void printer::draw_text( const drawer_with_default out, const vec2i pos, const drafter& d, const caret_info& caret, const ltrbi clipper ) const { const auto& colors = d.cached_str; auto& lines = d.lines; auto& sectors = d.sectors; const bool clip = clipper.good(); auto getf = [&](auto& f) -> decltype(auto) { return *f; }; /* here we highlight the line caret is currently on */ if (active && highlight_current_line) { drafter::line highlighted = lines.size() ? lines[d.get_line(caret.pos)] : drafter::line(); out.aabb_clipped( xywhi( 0, highlighted.top, clip ? d.get_bbox().x + clipper.w() : d.get_bbox().x, /* snap to default style's height */ highlighted.empty() ? getf(caret.default_style.font).metrics.get_height() : highlighted.height() ) + pos, clipper, highlight_col ); } auto caret_rect = xywhi(0, 0, 0, 0); if (!lines.empty() && !sectors.empty()) { /* only these lines we want to process */ simple_pair<int, int> visible; if (clip) visible = d.get_line_visibility(clipper - pos); else visible = { 0, static_cast<int>(lines.size() - 1) }; /* if this happens: - check if there is always an empty line - check if we return when clipper is not valid - check if scroll is always aligned */ if (visible.first == -1) { return; } /* we'll need these variables later so we declare them here */ unsigned select_left = 0; unsigned select_right = 0; unsigned caret_line = 0; caret_line = d.get_line(caret.pos); /* let's calculate some values only once */ select_left = caret.get_left_selection(); select_right = caret.get_right_selection(); if (caret.selection_offset) { const unsigned select_left_line = d.get_line(select_left); const unsigned select_right_line = d.get_line(select_right); const unsigned first_visible_selection = std::max(select_left_line, static_cast<unsigned>(visible.first)); const unsigned last_visible_selection = std::min(select_right_line, static_cast<unsigned>(visible.second)); /* manage selections */ for (unsigned i = first_visible_selection; i <= last_visible_selection; ++i) { /* init selection rect on line rectangle; its values won't change if selecting between first and the last line */ ltrbi sel_rect = d.lines[i].get_rect(); /* if it's the first line to process and we can see it, we have to trim its x coordinate */ if (i == first_visible_selection && select_left_line >= first_visible_selection) { sel_rect.l = d.sectors[select_left]; } /* similiarly with the last one note that with only one line selecting, it is still correct to apply these two conditions */ if (i == last_visible_selection && select_right_line <= last_visible_selection) { sel_rect.r = d.sectors[select_right]; } out.aabb_clipped(sel_rect + pos, clipper, active ? selection_bg_col : selection_inactive_bg_col); } } /* for every visible line */ for (unsigned l = visible.first; l <= static_cast<unsigned>(visible.second); ++l) { /* for every character in line */ for (unsigned i = lines[l].begin; i < lines[l].end; ++i) { /* shortcut */ auto& g = *d.cached[i]; /* if it's not a whitespace */ if (g.in_atlas.exists()) { rgba charcolor = style(colors[i]).color; /* if a character is between selection bounds, we change its color to the one specified in selected_text_color if there's no caret, this is never true */ if (i > select_left && i < select_right) { charcolor = selected_text_color; } /* add the resulting character taking bearings into account */ out.aabb_clipped( g.in_atlas, ltrb(xywhi({ sectors[i] + g.meta.bear_x, lines[l].top + lines[l].asc - g.meta.bear_y }, g.in_atlas.get_original_size()) + pos), ltrb(clipper), charcolor ); } } } if (active) { /* if we can retrieve some sane values */ if (!lines[caret_line].empty()) { if (align_caret_height) caret_rect = xywhi(sectors[caret.pos], lines[caret_line].top, caret_width, lines[caret_line].height()); else { const auto pos = std::max(1u, caret.pos); auto& glyph_font = getf(colors[pos - 1].format.font); caret_rect = xywhi( sectors[caret.pos], lines[caret_line].top + lines[caret_line].asc - glyph_font.metrics.ascender, caret_width, glyph_font.metrics.get_height() ); } } /* otherwise set caret's height to default style's height to avoid strange situations */ else { caret_rect = xywhi(0, d.lines[caret_line].top, caret_width, getf(caret.default_style.font).metrics.get_height()); } } } /* there is nothing to draw, but we are still active so we want to draw caret anyway */ else if (active) { caret_rect = xywhi(0, 0, caret_width, getf(caret.default_style.font).metrics.get_height()); } if (blink.caret_visible) { out.aabb_clipped(caret_rect + pos, clipper, caret_col); } }