#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 position) { std::vector 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 Scene::elements_at(Vec2 position) { std::vector result; for (auto it = element_ids.rbegin(); it != element_ids.rend(); ++it) { Element *e = element_pool[*it]; Vec2 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 Scene::world_to_local(Vec2 p, Element *e) { Vec2 size = e->size(); Vec2 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