summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPaweł Redman <pawel.redman@gmail.com>2018-04-01 13:46:47 +0200
committerPaweł Redman <pawel.redman@gmail.com>2018-04-01 13:46:47 +0200
commitbe628dc7f9c32ca84674c8717f07cc15a40f333c (patch)
tree09c54df1ce9e5905a1a3d90434b8c9fea021eb1b /src
parent6c46e70e3576ae9d27c3ad5c8c95c3198c9be501 (diff)
Improve selecting.
Diffstat (limited to 'src')
-rw-r--r--src/common.hpp12
-rw-r--r--src/game/game.cpp65
-rw-r--r--src/game/interface.cpp36
-rw-r--r--src/math.hpp10
-rw-r--r--src/render.cpp9
5 files changed, 114 insertions, 18 deletions
diff --git a/src/common.hpp b/src/common.hpp
index fcda5e5..0f51590 100644
--- a/src/common.hpp
+++ b/src/common.hpp
@@ -248,8 +248,15 @@ namespace game {
die_t(size_t count_, size_t sides_, size_t bonus_);
};
+ enum {
+ SELECT_NEW,
+ SELECT_OR,
+ SELECT_XOR
+ };
+
class state_t {
void group_say(std::string text);
+ void select_unit(unit_t *unit, int type);
public:
world::world_t world;
@@ -274,7 +281,7 @@ namespace game {
void resume(void);
// These are called by the interface.
- void select(rectf_t rect);
+ void select(rectf_t rect, int type);
bool populate_pie_menu(std::vector<interface::pie_item_t> &items);
void command(v2f_t x, int number);
void spawn_soldier(v2f_t x);
@@ -323,6 +330,7 @@ namespace interface {
struct {
bool selecting = false;
+ int type;
rectf_t rect;
} select;
@@ -394,6 +402,8 @@ namespace render {
} text_align_t;
void register_tile(uint8_t type, const char *top, const char *side, float height);
+ bool rendering_order(const world::entity_t *x, const world::entity_t *y);
+ bool visibility_order(const world::entity_t *x, const world::entity_t *y);
class state_t {
sf::RenderWindow *window;
diff --git a/src/game/game.cpp b/src/game/game.cpp
index f21bccd..27db5e5 100644
--- a/src/game/game.cpp
+++ b/src/game/game.cpp
@@ -91,7 +91,6 @@ void state_t::start(void)
soldier->place(&world, v2f_t(1.5, 0.5));
soldier = new unit_soldier_t(this);
soldier->place(&world, v2f_t(2.5, 0.5));
- select(rectf_t(v2f_t(0.5, 0.5), v2f_t(2.5, 0.5)));
resume();
}
@@ -105,12 +104,53 @@ void state_t::group_say(std::string text)
interface->print(text::get(text::SAY_GROUP) + ": " + text);
}
-void state_t::select(rectf_t x)
+void state_t::select_unit(unit_t *unit, int type)
{
- selection_cookie++;
- selected_units.clear();
+ switch (type) {
+ case SELECT_NEW:
+ case SELECT_OR:
+ if (unit->selected == selection_cookie)
+ return;
+ else
+ goto do_select;
+
+ case SELECT_XOR:
+ if (unit->selected == selection_cookie)
+ goto do_deselect;
+ else
+ goto do_select;
+ }
+
+do_select:
+ unit->selected = selection_cookie;
+ selected_units.insert(unit);
+ return;
+
+do_deselect:
+ unit->selected = selection_cookie - 1;
+ selected_units.erase(unit);
+}
+
+void state_t::select(rectf_t rect, int type)
+{
+ size_t before;
+ bool select_one;
+ std::list<world::entity_t*> ents;
+
+ before = selected_units.size();
- for (world::entity_t *ent : world.get_render_entities(x)) {
+ if (type == SELECT_NEW) {
+ selection_cookie++;
+ selected_units.clear();
+ }
+
+ select_one = rect.area() < 0.2f;
+
+ ents = world.get_render_entities(rect);
+ if (select_one)
+ ents.sort(render::visibility_order);
+
+ for (world::entity_t *ent : ents) {
unit_t *unit;
if (ent->type != ET_UNIT)
@@ -121,14 +161,17 @@ void state_t::select(rectf_t x)
if (!unit->controllable)
continue;
- unit->selected = selection_cookie;
- selected_units.insert(unit);
+ select_unit(unit, type);
+ if (select_one)
+ break;
}
- if (selected_units.size() == 1)
- (*selected_units.begin())->say(text::get(text::SAY_READY));
- else if (selected_units.size() > 1)
- group_say(text::get(text::SAY_READY_GROUP));
+ if (selected_units.size() > before) {
+ if (selected_units.size() == 1)
+ (*selected_units.begin())->say(text::get(text::SAY_READY));
+ else if (selected_units.size() > 1)
+ group_say(text::get(text::SAY_READY_GROUP));
+ }
}
enum {
diff --git a/src/game/interface.cpp b/src/game/interface.cpp
index 25d256c..8a02e98 100644
--- a/src/game/interface.cpp
+++ b/src/game/interface.cpp
@@ -114,6 +114,15 @@ void pie_menu_t::update(v2f_t mouse)
}
}
+static int get_selection_type(void)
+{
+ if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::LControl))
+ return game::SELECT_OR;
+ if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::LShift))
+ return game::SELECT_XOR;
+ return game::SELECT_NEW;
+}
+
void state_t::tick(double dt)
{
vec_t<int, 2> window_size;
@@ -205,7 +214,7 @@ void state_t::tick(double dt)
switch (event.mouseButton.button) {
case sf::Mouse::Button::Left:
if (select.selecting)
- game->select(select.rect);
+ game->select(select.rect, select.type);
select.selecting = false;
break;
@@ -279,8 +288,10 @@ void state_t::tick(double dt)
}
}
- if (select.selecting)
+ if (select.selecting) {
+ select.type = get_selection_type();
select.rect[1] = wmouse;
+ }
pie_menu.update(mouse);
}
@@ -327,8 +338,25 @@ void state_t::render_to(render::state_t *render)
std::stringstream ss;
double fps;
- if (select.selecting)
- render->render_hlrect(select.rect, sf::Color(60, 60, 150));
+ if (select.selecting) {
+ sf::Color color;
+
+ switch (select.type) {
+ case SELECT_NEW:
+ color = sf::Color(60, 60, 150);
+ break;
+
+ case SELECT_OR:
+ color = sf::Color(60, 150, 60);
+ break;
+
+ case SELECT_XOR:
+ color = sf::Color(150, 150, 60);
+ break;
+ }
+
+ render->render_hlrect(select.rect, color);
+ }
window->setView(sf::View(sf::FloatRect(0, 0, w, h)));
em = std::max(w, h) * 0.017;
diff --git a/src/math.hpp b/src/math.hpp
index 9b909cf..7cbd829 100644
--- a/src/math.hpp
+++ b/src/math.hpp
@@ -352,6 +352,16 @@ public:
return min;
}
+ T area(void) const
+ {
+ T area = 1;
+
+ for (size_t i = 0; i < N; i++)
+ area *= dim(i);
+
+ return area;
+ }
+
rect_t<T, N> norm(void) const
{
rect_t<T, N> r;
diff --git a/src/render.cpp b/src/render.cpp
index 96153f9..beda97b 100644
--- a/src/render.cpp
+++ b/src/render.cpp
@@ -200,7 +200,7 @@ rectf_t state_t::window_in_world_space(void)
return window_bounds(window);
}
-bool entity_order(const world::entity_t *x, const world::entity_t *y)
+bool rendering_order(const world::entity_t *x, const world::entity_t *y)
{
if (x->render_layer < y->render_layer)
return true;
@@ -210,6 +210,11 @@ bool entity_order(const world::entity_t *x, const world::entity_t *y)
return x->render_bounds[1][1] < y->render_bounds[1][1];
}
+bool visibility_order(const world::entity_t *x, const world::entity_t *y)
+{
+ return !rendering_order(x, y);
+}
+
void state_t::render(game::state_t *game)
{
rectf_t bounds;
@@ -222,7 +227,7 @@ void state_t::render(game::state_t *game)
sectors[1] = world::sector_index_at(bounds[1]);
ents = game->world.get_render_entities(bounds);
- ents.sort(entity_order);
+ ents.sort(rendering_order);
ent = ents.begin();
for (world::coord_t sy = sectors[0][1]; sy <= sectors[1][1]; sy++)