From 6966908022e36df9fb4c5e2233603a6fef18e97d Mon Sep 17 00:00:00 2001 From: Paweł Redman Date: Wed, 28 Mar 2018 14:17:47 +0200 Subject: Pie menu; start redoing shooting mechanics. --- src/game/interface.cpp | 105 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 104 insertions(+), 1 deletion(-) (limited to 'src/game/interface.cpp') diff --git a/src/game/interface.cpp b/src/game/interface.cpp index 262c3ae..d3ef661 100644 --- a/src/game/interface.cpp +++ b/src/game/interface.cpp @@ -51,6 +51,69 @@ void state_t::stop_following(void) print(text::get(text::FOLLOWING_OFF)); } +void pie_menu_t::open(v2f_t wmouse, v2f_t mouse) +{ + size_t layer = 0; + float base_radius = 50.0f; // FIXME + + for (size_t i = 0; i < items.size(); ) { + size_t left, layer_cap, on_layer; + + left = items.size() - i; + layer_cap = (layer + 1) * (layer + 1); + on_layer = std::min(left, layer_cap); + + for (size_t j = 0; j < on_layer; j++) { + pie_item_t *item = &items[i + j]; + float dt = 2 * M_PI / on_layer; + + item->r0 = layer * base_radius; + item->r1 = (layer + 1) * base_radius; + item->t0 = j * dt; + item->t1 = (j + 1) * dt; + } + + i += on_layer; + layer++; + } + + is_open = true; + x_world = wmouse; + x = mouse; +} + +void pie_menu_t::close(game::state_t *game) +{ + if (!is_open) + return; + + if (selected) + game->command(x_world, selected->action); + + is_open = false; + items.clear(); +} + +void pie_menu_t::update(v2f_t mouse) +{ + v2f_t delta; + float r, t; + + delta = mouse - x; + r = delta.len(); + t = atan2(delta[1], delta[0]); + if (t < 0) + t += 2 * M_PI; + + selected = nullptr; + for (pie_item_t &i : items) { + if (r >= i.r0 && r <= i.r1 && t >= i.t0 && t <= i.t1) { + selected = &i; + break; + } + } +} + void state_t::tick(double dt) { vec_t window_size; @@ -59,6 +122,7 @@ void state_t::tick(double dt) v2f_t view_size; v2f_t follow_center(0, 0), view_center, pan_delta; float view_scale; + sf::Vector2i mouse; v2f_t wmouse; // Mouse position in world space; window_size = window->getSize(); @@ -101,6 +165,7 @@ void state_t::tick(double dt) window->setView(sf::View(view_center, view_size)); } + mouse = sf::Mouse::getPosition(*window); wmouse = window->mapPixelToCoords(sf::Mouse::getPosition(*window)); while (window->pollEvent(event)) { @@ -119,7 +184,8 @@ void state_t::tick(double dt) break; case sf::Mouse::Button::Right: - game->command(wmouse); + if (game->populate_pie_menu(pie_menu.items)) + pie_menu.open(wmouse, mouse); break; case sf::Mouse::Button::Middle: @@ -139,6 +205,10 @@ void state_t::tick(double dt) select.selecting = false; break; + case sf::Mouse::Button::Right: + pie_menu.close(game); + break; + case sf::Mouse::Button::Middle: if (camera.panning) camera.center += pan_delta; @@ -207,6 +277,8 @@ void state_t::tick(double dt) if (select.selecting) select.rect[1] = wmouse; + + pie_menu.update(mouse); } void state_t::print(std::string str) @@ -215,6 +287,35 @@ void state_t::print(std::string str) std::cout << str << std::endl; } +void pie_menu_t::render_to(render::state_t *render) +{ + if (!is_open) + return; + + for (pie_item_t &i : items) { + sf::Color color; + v2f_t rad, center; + + if (&i == selected) + color = sf::Color(255, 255, 255, 120); + else + color = sf::Color(255, 255, 255, 40); + + render->render_ring_sect(x, i.r0, i.r1, i.t0, i.t1, color); + + color.a = 255; + + if (i.r0 == 0.0f) { + center = x; + } else { + center = x + (i.r1 + i.r0) / 2 * + v2f_t::rad((i.t1 + i.t0) / 2); + } + + render->render_text(center, 15, i.label, render::text_align_t::ALIGN_CENTER_BOTTOM, color); + } +} + void state_t::render_to(render::state_t *render) { size_t w = window->getSize().x, h = window->getSize().y; @@ -228,6 +329,8 @@ void state_t::render_to(render::state_t *render) window->setView(sf::View(sf::FloatRect(0, 0, w, h))); em = std::max(w, h) * 0.017; + pie_menu.render_to(render); + for (auto i = log.begin(); i != log.end(); ) { if (i->time + 3 < game->now) i = log.erase(i); -- cgit