Support deleting items

This commit is contained in:
Nikita Lisitsa 2024-08-19 01:07:19 +03:00
parent 259beba780
commit 11f220d8ea

View file

@ -240,6 +240,28 @@ namespace gmtk
float state = 0.f;
};
geom::point<float, 2> position(ecs::container & world, item const & i)
{
if (i.target)
{
auto end = world.get(i.target).get<path_vertex const>().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<path_vertex const>().location;
return 3.f * std::pow(3.f, -geom::lerp<float>(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<float, 2> const & pos, float scale, gfx::painter & painter)
void draw_item(resource_type type, geom::point<float, 2> 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<float, 2>::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<float, 2>::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>([&](item const & i)
{
geom::point<float, 2> pos;
float scale;
if (i.target)
{
auto end = map.world.get(i.target).get<path_vertex const>().location;
pos = geom::lerp(i.start.center(), end.center(), i.state);
scale = std::pow(3.f, -geom::lerp<float>(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<item const>();
if (i.target)
map_.world.detach<occupied>(i.target);
else
map_.world.detach<occupied>(map_.world.index<path_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<item const>([&](ecs::handle entity, item const & i)
{
selected_ = p;
while (selected_->level > 0)
{
if (auto entity = map_.world.index<index>().find(p.up()))
if (map_.world.get(*entity).contains<zoomer>())
break;
auto box = geom::expand(geom::box<float, 2>::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<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<index>().find(p.up()))
if (map_.world.get(*entity).contains<zoomer>())
break;
selected_ = std::nullopt;
break;
// TODO:
selected_ = selected_->up();
}
}
else if (!within_grid(p))
if (auto entity = map_.world.index<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<item const>();
draw_item(i.type, position(map_.world, i), scale(map_.world, i), painter_, true);
}
if (selected_)
if (auto entity = map_.world.index<index>().find(*selected_))
if (auto t = map_.world.get(*entity).get_if<transformer>())
@ -1202,21 +1239,7 @@ namespace gmtk
std::optional<location> selected_;
std::optional<location> belt_start_;
geom::point<float, 2> screen_to_grid(geom::point<float, 2> 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<ecs::handle> selected_item_;
};
}