diff --git a/source/application.cpp b/source/application.cpp index cd773a4..a4544e4 100644 --- a/source/application.cpp +++ b/source/application.cpp @@ -240,6 +240,28 @@ namespace gmtk float state = 0.f; }; + geom::point position(ecs::container & world, item const & i) + { + if (i.target) + { + auto end = world.get(i.target).get().location; + return geom::lerp(i.start.center(), end.center(), i.state); + } + else + return i.start.center(); + } + + float scale(ecs::container & world, item const & i) + { + if (i.target) + { + auto end = world.get(i.target).get().location; + return 3.f * std::pow(3.f, -geom::lerp(i.start.level, end.level, i.state)); + } + else + return 3.f * std::pow(3.f, -i.start.level); + } + bool within_grid(location const & l) { int max = std::pow(3, l.level + 1); @@ -453,17 +475,19 @@ namespace gmtk } } - void draw_item(resource_type type, geom::point const & pos, float scale, gfx::painter & painter) + void draw_item(resource_type type, geom::point const & pos, float scale, gfx::painter & painter, bool selected = false) { auto color = color_of(type); + gfx::color_rgba bcolor = selected ? gfx::red : gfx::black; + switch (type) { case resource_type::coal: case resource_type::stone: case resource_type::iron_ore: case resource_type::copper_ore: - painter.circle(pos, 0.075f * scale, {0, 0, 0, 255}); + painter.circle(pos, 0.075f * scale, bcolor); painter.circle(pos, 0.05f * scale, color); break; case resource_type::stone_brick: @@ -471,7 +495,7 @@ namespace gmtk case resource_type::copper_plate: { auto box = geom::expand(geom::box::singleton(pos), 0.075f * scale); - painter.rect(box, {0, 0, 0, 255}); + painter.rect(box, bcolor); box = geom::shrink(box, 0.025f * scale); painter.rect(box, color); } @@ -484,8 +508,9 @@ namespace gmtk bool first = true; for (float radius : {0.075f * scale, 0.05f * scale}) { + auto c = first ? bcolor : color; for (int i = 0; i < 6; ++i) - painter.triangle(pos, pos + geom::direction(geom::rad(i * 60.f)) * radius, pos + geom::direction(geom::rad((i + 1) * 60.f)) * radius, first ? gfx::black : color); + painter.triangle(pos, pos + geom::direction(geom::rad(i * 60.f)) * radius, pos + geom::direction(geom::rad((i + 1) * 60.f)) * radius, c); first = false; } } @@ -494,7 +519,7 @@ namespace gmtk case resource_type::green_science_pack: { auto box = geom::expand(geom::box::singleton(pos), 0.075f * scale); - painter.triangle(box.corner(0, 0), box.corner(1, 0), box.corner(0.5f, 1), {0, 0, 0, 255}); + painter.triangle(box.corner(0, 0), box.corner(1, 0), box.corner(0.5f, 1), bcolor); box = geom::shrink(box, 0.025f * scale); painter.triangle(box.corner(0, 0), box.corner(1, 0), box.corner(0.5f, 1), color); } @@ -610,22 +635,7 @@ namespace gmtk map.world.apply([&](item const & i) { - geom::point pos; - float scale; - if (i.target) - { - auto end = map.world.get(i.target).get().location; - pos = geom::lerp(i.start.center(), end.center(), i.state); - scale = std::pow(3.f, -geom::lerp(i.start.level, end.level, i.state)); - } - else - { - pos = i.start.center(); - scale = std::pow(3.f, -i.start.level); - } - scale *= 3.f; - - draw_item(i.type, pos, scale, painter); + draw_item(i.type, position(map.world, i), scale(map.world, i), painter); }); } @@ -685,6 +695,17 @@ namespace gmtk transitioned = true; } } + + if (selected_item_) + { + auto const & i = map_.world.get(*selected_item_).get(); + if (i.target) + map_.world.detach(i.target); + else + map_.world.detach(map_.world.index().get(i.start)); + map_.world.destroy(*selected_item_); + selected_item_ = std::nullopt; + } } if (event.down && event.button == app::mouse_button::right) @@ -1046,6 +1067,7 @@ namespace gmtk view_box_[0] = geom::expand(view_box_[0], (view_box_[1].length() * aspect_ratio - view_box_[0].length()) / 2.f); selected_ = std::nullopt; + selected_item_ = std::nullopt; if (!view_transition_) { @@ -1054,41 +1076,50 @@ namespace gmtk 1.f - mouse_[1] * 1.f / screen_size_[1] ); - float s = std::pow(3.f, 1 + view_stack_.back().level); - - m[0] *= s; - m[1] *= s; - - auto l = view_stack_.back(); - - location p{1 + l.level, {std::floor(m[0]), std::floor(m[1])}}; - - geom::interval xrange{3 * l.coords[0], 3 * l.coords[0] + 2}; - geom::interval yrange{3 * l.coords[1], 3 * l.coords[1] + 2}; - auto xwrange = geom::expand(xrange, 1); - auto ywrange = geom::expand(yrange, 1); - - if (geom::contains(xrange, p.coords[0]) && geom::contains(yrange, p.coords[1])) - selected_ = p; - else if (view_stack_.size() > 1 && within_grid(p) && ((geom::contains(xwrange, p.coords[0]) && geom::contains(yrange, p.coords[1])) || (geom::contains(xrange, p.coords[0]) && geom::contains(ywrange, p.coords[1])))) + map_.world.apply([&](ecs::handle entity, item const & i) { - selected_ = p; - while (selected_->level > 0) - { - if (auto entity = map_.world.index().find(p.up())) - if (map_.world.get(*entity).contains()) - break; + auto box = geom::expand(geom::box::singleton(position(map_.world, i)), scale(map_.world, i) / 9.f); + if (geom::contains(box, m)) + selected_item_ = entity; + }); - selected_ = std::nullopt; - break; + { + float s = std::pow(3.f, 1 + view_stack_.back().level); - // TODO: - selected_ = selected_->up(); - } - } - else if (!within_grid(p)) - if (auto entity = map_.world.index().find(p)) + m[0] *= s; + m[1] *= s; + + auto l = view_stack_.back(); + + location p{1 + l.level, {std::floor(m[0]), std::floor(m[1])}}; + + geom::interval xrange{3 * l.coords[0], 3 * l.coords[0] + 2}; + geom::interval yrange{3 * l.coords[1], 3 * l.coords[1] + 2}; + auto xwrange = geom::expand(xrange, 1); + auto ywrange = geom::expand(yrange, 1); + + if (geom::contains(xrange, p.coords[0]) && geom::contains(yrange, p.coords[1])) selected_ = p; + else if (view_stack_.size() > 1 && within_grid(p) && ((geom::contains(xwrange, p.coords[0]) && geom::contains(yrange, p.coords[1])) || (geom::contains(xrange, p.coords[0]) && geom::contains(ywrange, p.coords[1])))) + { + selected_ = p; + while (selected_->level > 0) + { + if (auto entity = map_.world.index().find(p.up())) + if (map_.world.get(*entity).contains()) + break; + + selected_ = std::nullopt; + break; + + // TODO: + selected_ = selected_->up(); + } + } + else if (!within_grid(p)) + if (auto entity = map_.world.index().find(p)) + selected_ = p; + } } } @@ -1108,7 +1139,7 @@ namespace gmtk draw(map_, view_level, painter_); if (selected_) - draw_selection(*selected_, painter_, {255, 0, 255, 255}); + draw_selection(*selected_, painter_, {255, 0, 0, 255}); if (belt_start_) draw_selection(*belt_start_, painter_, {255, 255, 0, 255}); @@ -1140,6 +1171,12 @@ namespace gmtk painter_.triangle(p10 - d, p11 - n, p11 - d, c1, c0, c1); } + if (selected_item_) + { + auto const & i = map_.world.get(*selected_item_).get(); + draw_item(i.type, position(map_.world, i), scale(map_.world, i), painter_, true); + } + if (selected_) if (auto entity = map_.world.index().find(*selected_)) if (auto t = map_.world.get(*entity).get_if()) @@ -1202,21 +1239,7 @@ namespace gmtk std::optional selected_; std::optional belt_start_; - - geom::point screen_to_grid(geom::point const & p) - { - auto result = view_box_.corner( - p[0] / screen_size_[0], - 1.f - p[1] / screen_size_[1] - ); - - float s = std::pow(3.f, 1 + view_stack_.back().level); - - result[0] *= s; - result[1] *= s; - - return result; - } + std::optional selected_item_; }; }