Files
project_misth/src/app/scene.cc
T

92 lines
2.1 KiB
C++

#include "app/scene.h"
namespace app {
Scene::~Scene() {
for (const uint64_t &id : element_ids)
element_pool.release(id);
}
void Scene::add_element(uint64_t element_id) {
auto it = std::lower_bound(
element_ids.begin(),
element_ids.end(),
element_id,
[](auto &a, auto &b) {
auto e_a = element_pool[a];
auto e_b = element_pool[b];
return e_a->z < e_b->z || (e_a->z == e_b->z && a < b);
}
);
element_pool.use(element_id);
element_ids.insert(it, element_id);
}
void Scene::delete_element(uint64_t element_id) {
auto it = std::find(element_ids.begin(), element_ids.end(), element_id);
if (it != element_ids.end()) {
element_pool.release(element_id);
element_ids.erase(it);
}
}
void Scene::update_scene(mrb_value dt_val) {
if (mrb_nil_p(update.proc))
return;
update.call(1, &dt_val);
}
void Scene::click(Vec2<float> position) {
std::vector<uint64_t> clicked_elements = elements_at(position);
for (const uint64_t &id : clicked_elements)
element_pool[id]->click();
}
void Scene::render(uint64_t abs_time) {
for (const uint64_t &e : element_ids)
element_pool[e]->render(abs_time);
}
std::vector<uint64_t> Scene::elements_at(Vec2<float> position) {
std::vector<uint64_t> result;
for (auto it = element_ids.rbegin(); it != element_ids.rend(); ++it) {
Element *e = element_pool[*it];
Vec2<float> size = e->size();
Rect rect = Rect::from(size);
if (rect.contains(world_to_local(position, e))) {
if (e->click_mode == ClickMode::PASS) {
result.push_back(*it);
} else if (e->click_mode == ClickMode::BLOCK) {
result.push_back(*it);
break;
} else {
continue;
}
}
}
return result;
}
Vec2<float> Scene::world_to_local(Vec2<float> p, Element *e) {
Vec2<float> size = e->size();
Vec2<float> pivot = e->pivot * size * e->scale;
p = p - e->position;
float rad = -e->rotation * (M_PI / 180.0f);
float c = cos(rad);
float s = sin(rad);
p = p - pivot;
p = {
p.x * c - p.y * s,
p.x * s + p.y * c
};
p = p + pivot;
p = p / e->scale;
return p;
}
} // namespace app