frame::frame(variant node) : id_(node["id"].as_string()), image_(node["image"].as_string()), variant_id_(id_), enter_event_id_(get_object_event_id("enter_" + id_ + "_anim")), end_event_id_(get_object_event_id("end_" + id_ + "_anim")), leave_event_id_(get_object_event_id("leave_" + id_ + "_anim")), process_event_id_(get_object_event_id("process_" + id_)), texture_(node.has_key("fbo") ? node["fbo"].convert_to<texture_object>()->texture() : graphics::texture::get(image_, node["image_formula"].as_string_default())), solid_(solid_info::create(node)), collide_rect_(node.has_key("collide") ? rect(node["collide"]) : rect(node["collide_x"].as_int(), node["collide_y"].as_int(), node["collide_w"].as_int(), node["collide_h"].as_int())), hit_rect_(node.has_key("hit") ? rect(node["hit"]) : rect(node["hit_x"].as_int(), node["hit_y"].as_int(), node["hit_w"].as_int(), node["hit_h"].as_int())), platform_rect_(node.has_key("platform") ? rect(node["platform"]) : rect(node["platform_x"].as_int(), node["platform_y"].as_int(), node["platform_w"].as_int(), 1)), img_rect_(node.has_key("rect") ? rect(node["rect"]) : rect(node["x"].as_int(), node["y"].as_int(), node["w"].as_int(), node["h"].as_int())), feet_x_(node["feet_x"].as_int()), feet_y_(node["feet_y"].as_int()), accel_x_(node["accel_x"].as_int(INT_MIN)), accel_y_(node["accel_y"].as_int(INT_MIN)), velocity_x_(node["velocity_x"].as_int(INT_MIN)), velocity_y_(node["velocity_y"].as_int(INT_MIN)), nframes_(node["frames"].as_int(1)), nframes_per_row_(node["frames_per_row"].as_int(-1)), frame_time_(node["duration"].as_int(-1)), reverse_frame_(node["reverse"].as_bool()), play_backwards_(node["play_backwards"].as_bool()), scale_(node["scale"].as_int(2)), pad_(node["pad"].as_int()), rotate_(node["rotate"].as_int()), blur_(node["blur"].as_int()), rotate_on_slope_(node["rotate_on_slope"].as_bool()), damage_(node["damage"].as_int()), sounds_(util::split(node["sound"].as_string_default())), no_remove_alpha_borders_(node["no_remove_alpha_borders"].as_bool(false)), collision_areas_inside_frame_(true), current_palette_(-1) { std::vector<std::string> hit_frames = util::split(node["hit_frames"].as_string_default()); foreach(const std::string& f, hit_frames) { hit_frames_.push_back(boost::lexical_cast<int>(f)); }
frame::frame(wml::const_node_ptr node) : id_(node->attr("id")), image_(node->attr("image")), variant_id_(id_), enter_event_id_(get_object_event_id("enter_" + id_ + "_anim")), end_event_id_(get_object_event_id("end_" + id_ + "_anim")), leave_event_id_(get_object_event_id("leave_" + id_ + "_anim")), process_event_id_(get_object_event_id("process_" + id_)), texture_(graphics::texture::get(image_, node->attr("image_formula"))), solid_(solid_info::create(node)), collide_rect_(node->has_attr("collide") ? rect(node->attr("collide")) : rect(wml::get_int(node, "collide_x"), wml::get_int(node, "collide_y"), wml::get_int(node, "collide_w"), wml::get_int(node, "collide_h"))), hit_rect_(node->has_attr("hit") ? rect(node->attr("hit")) : rect(wml::get_int(node, "hit_x"), wml::get_int(node, "hit_y"), wml::get_int(node, "hit_w"), wml::get_int(node, "hit_h"))), platform_rect_(node->has_attr("platform") ? rect(node->attr("platform")) : rect(wml::get_int(node, "platform_x"), wml::get_int(node, "platform_y"), wml::get_int(node, "platform_w"), 1)), img_rect_(node->has_attr("rect") ? rect(node->attr("rect")) : rect(wml::get_int(node, "x"), wml::get_int(node, "y"), wml::get_int(node, "w"), wml::get_int(node, "h"))), feet_x_(wml::get_int(node, "feet_x")), feet_y_(wml::get_int(node, "feet_y")), accel_x_(wml::get_int(node, "accel_x", INT_MIN)), accel_y_(wml::get_int(node, "accel_y", INT_MIN)), velocity_x_(wml::get_int(node, "velocity_x", INT_MIN)), velocity_y_(wml::get_int(node, "velocity_y", INT_MIN)), nframes_(wml::get_int(node, "frames", 1)), nframes_per_row_(wml::get_int(node, "frames_per_row", -1)), frame_time_(wml::get_int(node, "duration", -1)), reverse_frame_(wml::get_bool(node, "reverse")), play_backwards_(wml::get_bool(node, "play_backwards")), scale_(wml::get_int(node, "scale", 2)), pad_(wml::get_int(node, "pad")), rotate_(wml::get_int(node, "rotate")), blur_(wml::get_int(node, "blur")), rotate_on_slope_(wml::get_bool(node, "rotate_on_slope")), damage_(wml::get_int(node, "damage")), sounds_(util::split(node->attr("sound"))), no_remove_alpha_borders_(wml::get_bool(node, "no_remove_alpha_borders", false)), current_palette_(-1) { std::vector<std::string> hit_frames = util::split((*node)["hit_frames"]); foreach(const std::string& f, hit_frames) { hit_frames_.push_back(boost::lexical_cast<int>(f)); }
void level_runner::video_resize_event(const SDL_Event &event) { const SDL_ResizeEvent* resize = reinterpret_cast<const SDL_ResizeEvent*>(&event); int width = resize->w; int height = resize->h; static const int WindowResizeEventID = get_object_event_id("window_resize"); game_logic::map_formula_callable_ptr callable(new game_logic::map_formula_callable); callable->add("width", variant(width)); callable->add("height", variant(height)); lvl_->player()->get_entity().handle_event(WindowResizeEventID, callable.get()); }
bool level_runner::handle_mouse_events(const SDL_Event &event) { static const int MouseDownEventID = get_object_event_id("mouse_down"); static const int MouseUpEventID = get_object_event_id("mouse_up"); static const int MouseMoveEventID = get_object_event_id("mouse_move"); static const int MouseDownEventAllID = get_object_event_id("mouse_down*"); static const int MouseUpEventAllID = get_object_event_id("mouse_up*"); static const int MouseMoveEventAllID = get_object_event_id("mouse_move*"); static const int MouseEnterID = get_object_event_id("mouse_enter"); static const int MouseLeaveID = get_object_event_id("mouse_leave"); static const int MouseClickID = get_object_event_id("click"); //static const int MouseDblClickID = get_object_event_id("dblclick"); static const int MouseDragID = get_object_event_id("drag"); static const int MouseDragStartID = get_object_event_id("drag_start"); static const int MouseDragEndID = get_object_event_id("drag_end"); if(paused) { // skip mouse event handling when paused. // XXX: when we become unpaused we need to reset the state of drag operations // and partial clicks. return false; } switch(event.type) { #if defined(__ANDROID__) case SDL_JOYBUTTONDOWN: case SDL_JOYBUTTONUP: case SDL_JOYBALLMOTION: int x, mx = event.type == SDL_JOYBALLMOTION ? event.jball.xrel : event.jbutton.x; int y, my = event.type == SDL_JOYBALLMOTION ? event.jball.yrel : event.jbutton.y; int i = event.type == SDL_JOYBALLMOTION ? event.jball.ball : event.jbutton.button; int event_button_button = event.jbutton.button; int event_type = event.type == SDL_JOYBALLMOTION ? SDL_MOUSEMOTION : event.type == SDL_JOYBUTTONDOWN ? SDL_MOUSEBUTTONDOWN : SDL_MOUSEBUTTONUP; #else case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: case SDL_MOUSEMOTION: int x, mx = event.type == SDL_MOUSEMOTION ? event.motion.x : event.button.x; int y, my = event.type == SDL_MOUSEMOTION ? event.motion.y : event.button.y; int i = event.type == SDL_MOUSEMOTION ? event.motion.which : event.button.which; int event_type = event.type; int event_button_button = event.button.button; #endif const int basic_evt = event_type == SDL_MOUSEBUTTONDOWN ? MouseDownEventID : event_type == SDL_MOUSEMOTION ? MouseMoveEventID : MouseUpEventID; const int catch_all_event = event_type == SDL_MOUSEBUTTONDOWN ? MouseDownEventAllID : event_type == SDL_MOUSEMOTION ? MouseMoveEventAllID : MouseUpEventAllID; Uint8 button_state = SDL_GetMouseState(0,0); if(!lvl_->gui_event(event)) { x = (mx*graphics::screen_width())/preferences::virtual_screen_width() + last_draw_position().x/100; y = (my*graphics::screen_height())/preferences::virtual_screen_height() + last_draw_position().y/100; game_logic::map_formula_callable_ptr callable(new game_logic::map_formula_callable); callable->add("mouse_x", variant(x)); callable->add("mouse_y", variant(y)); callable->add("mouse_index", variant(i)); if(event_type != SDL_MOUSEMOTION) { callable->add("mouse_button", variant(event_button_button)); } else { callable->add("mouse_button", variant(button_state)); } std::vector<variant> items; // Grab characters around point, z-order sort them, so that when // we process them we go from highest to lowest, allowing a higher // object to swallow an event before the lower ones get it. std::vector<entity_ptr> cs = lvl_->get_characters_at_point(x, y, last_draw_position().x/100, last_draw_position().y/100); std::sort(cs.begin(), cs.end(), zorder_compare); std::vector<entity_ptr>::iterator it; bool handled = false; bool click_handled = false; std::set<entity_ptr> mouse_in; for(it = cs.begin(); it != cs.end(); ++it) { rect clip_area; // n.b. clip_area is in level coordinates, not relative to the object. if((*it)->get_clip_area(&clip_area)) { point p(x,y); if((*it)->use_absolute_screen_coordinates()) { p = point(mx,my); } if(point_in_rect(p, clip_area) == false) { continue; } } if(event_type == SDL_MOUSEBUTTONDOWN) { (*it)->set_mouse_buttons((*it)->get_mouse_buttons() | SDL_BUTTON(event_button_button)); } else if(event_type == SDL_MOUSEMOTION) { // handling for mouse_enter if((*it)->is_mouse_over_entity() == false) { (*it)->handle_event(MouseEnterID, callable.get()); (*it)->set_mouse_over_entity(); } mouse_in.insert(*it); } handled |= (*it)->handle_event(basic_evt, callable.get()); // XXX: fix this for dragging(with multiple mice) if(event_type == SDL_MOUSEBUTTONUP && !click_handled && (*it)->is_being_dragged() == false) { (*it)->handle_event(MouseClickID, callable.get()); if((*it)->mouse_event_swallowed()) { click_handled = true; } } items.push_back(variant((*it).get())); } // Handling for "catch all" mouse events. callable->add("handled", variant(handled)); variant obj_ary(&items); callable->add("objects_under_mouse", obj_ary); std::vector<entity_ptr> level_chars(level::current().get_chars()); foreach(entity_ptr object, level_chars) { if(object) { object->handle_event(catch_all_event, callable.get()); // drag handling if(event_type == SDL_MOUSEBUTTONUP) { object->set_mouse_buttons(object->get_mouse_buttons() & ~SDL_BUTTON(event_button_button)); if(object->get_mouse_buttons() == 0 && object->is_being_dragged()) { object->handle_event(MouseDragEndID, callable.get()); object->set_being_dragged(false); } } else if(event_type == SDL_MOUSEMOTION) { // drag check. if(object->is_being_dragged()) { if(object->get_mouse_buttons() & button_state) { object->handle_event(MouseDragID, callable.get()); } else { object->handle_event(MouseDragEndID, callable.get()); object->set_being_dragged(false); } } else if(object->get_mouse_buttons() & button_state) { // start drag. object->handle_event(MouseDragStartID, callable.get()); object->set_being_dragged(); } } } } if(event_type == SDL_MOUSEMOTION) { // handling for mouse_leave level_chars = level::current().get_chars(); foreach(const entity_ptr& e, level_chars) { if(e) { // n.b. clip_area is in level coordinates, not relative to the object. rect clip_area; bool has_clip_area = e->get_clip_area(&clip_area); point p(x,y); if(e->use_absolute_screen_coordinates()) { p = point(mx,my); } if(mouse_in.find(e) == mouse_in.end() && ((has_clip_area == false && e->is_mouse_over_entity()) || (e->is_mouse_over_entity() && has_clip_area && point_in_rect(p, clip_area) == false))) { e->handle_event(MouseLeaveID, callable.get()); e->set_mouse_over_entity(false); } } } } }