#ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #include #define SANDBOX_THEME "ephysics_sandbox" #define WIDTH (1280) #define HEIGHT (720) #define DEPTH (100) #define INITIAL_MASS (15) static const char *materials[] = { "Custom", "Concrete", "Iron", "Plastic", "Polystyrene", "Rubber", "Wood" }; typedef struct _World_Data World_Data; typedef struct _Body_Data Body_Data; struct _World_Data { EPhysics_Body *top, *bottom, *left, *right; Evas_Object *win, *tb, *nf; EPhysics_World *world; Body_Data *bd1, *bd2; }; struct _Body_Data { World_Data *wd; EPhysics_Body *body; struct { struct { Evas_Object *x, *y, *relx, *rely; }impulse; struct { Evas_Object *x, *y, *relx, *rely, *torque; }force; struct { Evas_Object *x, *y, *angular; }velocity; Evas_Object *hardness; }controls; }; /*** Sandbox Callbacks ***/ static void _body_del(void *data __UNUSED__, EPhysics_Body *body __UNUSED__, void *event_info) { if (event_info) evas_object_del(event_info); } static void _world_gravity_x_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__) { EPhysics_World *world = data; double gravity_y, gravity_z; ephysics_world_gravity_get(world, NULL, &gravity_y, &gravity_z); ephysics_world_gravity_set(world, elm_slider_value_get(obj), gravity_y, gravity_z); } static void _world_gravity_y_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__) { EPhysics_World *world = data; double gravity_x, gravity_z; ephysics_world_gravity_get(world, &gravity_x, NULL, &gravity_z); ephysics_world_gravity_set(world, gravity_x, elm_slider_value_get(obj), gravity_z); } static void _world_rate_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__) { EPhysics_World *world = data; ephysics_world_rate_set(world, elm_slider_value_get(obj)); } static void _world_max_sleeping_time_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__) { EPhysics_World *world = data; ephysics_world_max_sleeping_time_set(world, elm_slider_value_get(obj)); } static void _world_friction_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__) { World_Data *wd = data; ephysics_body_friction_set(wd->top, elm_slider_value_get(obj)); ephysics_body_friction_set(wd->bottom, elm_slider_value_get(obj)); ephysics_body_friction_set(wd->left, elm_slider_value_get(obj)); ephysics_body_friction_set(wd->right, elm_slider_value_get(obj)); } static void _world_restitution_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__) { World_Data *wd = data; ephysics_body_restitution_set(wd->top, elm_slider_value_get(obj)); ephysics_body_restitution_set(wd->bottom, elm_slider_value_get(obj)); ephysics_body_restitution_set(wd->left, elm_slider_value_get(obj)); ephysics_body_restitution_set(wd->right, elm_slider_value_get(obj)); } static void _type_set_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__) { double mass, friction, restitution, lin_damping, ang_damping; double lin_sleeping, ang_sleeping; EPhysics_Body_Material material; EPhysics_Quaternion rotation; Evas_Object *body_image; EPhysics_World *world; Body_Data *bd = data; EPhysics_Body *body = bd->body; mass = ephysics_body_mass_get(body); ephysics_body_rotation_get(body, &rotation); friction = ephysics_body_friction_get(body); restitution = ephysics_body_restitution_get(body); ephysics_body_damping_get(body, &lin_damping, &ang_damping); ephysics_body_sleeping_threshold_get(body, &lin_sleeping, &ang_sleeping); material = ephysics_body_material_get(body); world = ephysics_body_world_get(body); body_image = ephysics_body_evas_object_unset(body); ephysics_body_del(body); if (elm_radio_value_get(obj)) { body = ephysics_body_soft_circle_add(world); ephysics_body_soft_body_hardness_set( body, elm_slider_value_get(bd->controls.hardness)); elm_object_disabled_set(bd->controls.hardness, EINA_FALSE); } else { body = ephysics_body_cylinder_add(world); elm_object_disabled_set(bd->controls.hardness, EINA_TRUE); } ephysics_body_evas_object_set(body, body_image, EINA_TRUE); ephysics_body_mass_set(body, mass); ephysics_body_rotation_set(body, &rotation); ephysics_body_friction_set(body, friction); ephysics_body_restitution_set(body, restitution); ephysics_body_damping_set(body, lin_damping, ang_damping); ephysics_body_sleeping_threshold_set(body, lin_sleeping, ang_sleeping); ephysics_body_material_set(body, material); ephysics_body_force_apply(body, elm_slider_value_get(bd->controls.force.x), elm_slider_value_get(bd->controls.force.y), 0, elm_slider_value_get(bd->controls.force.relx), elm_slider_value_get(bd->controls.force.rely), 0); ephysics_body_torque_apply(body, 0, 0, elm_slider_value_get(bd->controls.force.torque)); bd->body = body; } static void _material_set_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__) { Body_Data *bd = evas_object_data_get(obj, "bd"); Evas_Object *win = bd->wd->win; EPhysics_Body *body = bd->body; EPhysics_Body_Material material = (EPhysics_Body_Material) data; Evas_Object *body_image; int x, y, w, h; elm_object_text_set(obj, materials[material]); ephysics_body_material_set(body, material); elm_slider_value_set(evas_object_data_get(obj, "mass"), ephysics_body_mass_get(body)); elm_slider_value_set(evas_object_data_get(obj, "density"), ephysics_body_density_get(body)); elm_slider_value_set(evas_object_data_get(obj, "friction"), ephysics_body_friction_get(body)); elm_slider_value_set(evas_object_data_get(obj, "restitution"), ephysics_body_restitution_get(body)); body_image = ephysics_body_evas_object_unset(body); evas_object_geometry_get(body_image, &x, &y, &w, &h); evas_object_del(body_image); body_image = elm_image_add(win); elm_image_file_set( body_image, PACKAGE_DATA_DIR "/" SANDBOX_THEME ".edj", materials[material]); evas_object_resize(body_image, w, h); evas_object_move(body_image, x, y); evas_object_show(body_image); ephysics_body_evas_object_set(body, body_image, EINA_FALSE); } static void _mass_set_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__) { Body_Data *bd = data; double mass = elm_slider_value_get(obj); ephysics_body_mass_set(bd->body, mass); elm_slider_value_set(evas_object_data_get(obj, "density"), mass / ephysics_body_volume_get(bd->body)); } static void _density_set_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__) { Body_Data *bd = data; ephysics_body_density_set(bd->body, elm_slider_value_get(obj)); elm_slider_value_set(evas_object_data_get(obj, "mass"), ephysics_body_mass_get(bd->body)); } static void _rotation_set_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__) { EPhysics_Quaternion quat; Body_Data *bd = data; ephysics_quaternion_euler_set(&quat, 0, 0, elm_slider_value_get(obj)); ephysics_body_rotation_set(bd->body, &quat); } static void _friction_set_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__) { Body_Data *bd = data; ephysics_body_friction_set(bd->body, elm_slider_value_get(obj)); } static void _restitution_set_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__) { Body_Data *bd = data; ephysics_body_restitution_set(bd->body, elm_slider_value_get(obj)); } static void _linear_damping_set_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__) { Body_Data *bd = data; double ang_damping; ephysics_body_damping_get(bd->body, NULL, &ang_damping); ephysics_body_damping_set(bd->body, elm_slider_value_get(obj), ang_damping); } static void _angular_damping_set_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__) { Body_Data *bd = data; double lin_damping; ephysics_body_damping_get(bd->body, &lin_damping, NULL); ephysics_body_damping_set(bd->body, lin_damping, elm_slider_value_get(obj)); } static void _lin_sleeping_threshold_set_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__) { Body_Data *bd = data; double ang_sleeping; ephysics_body_sleeping_threshold_get(bd->body, NULL, &ang_sleeping); ephysics_body_sleeping_threshold_set(bd->body, elm_slider_value_get(obj), ang_sleeping); } static void _ang_sleeping_threshold_set_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__) { Body_Data *bd = data; double lin_sleeping; ephysics_body_sleeping_threshold_get(bd->body, &lin_sleeping, NULL); ephysics_body_sleeping_threshold_set(bd->body, lin_sleeping, elm_slider_value_get(obj)); } static void _torque_set_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__) { Body_Data *bd = data; ephysics_body_torque_apply(bd->body, 0, 0, elm_slider_value_get(obj)); } static void _impulse_x_x_set_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__) { Evas_Coord rel_x, rel_y; Body_Data *bd = data; double y; y = elm_slider_value_get(evas_object_data_get(obj, "y")); rel_x = elm_slider_value_get(evas_object_data_get(obj, "relx")); rel_y = elm_slider_value_get(evas_object_data_get(obj, "rely")); ephysics_body_impulse_apply(bd->body, elm_slider_value_get(obj), y, 0, rel_x, rel_y, 0); } static void _impulse_x_rel_set_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__) { Body_Data *bd = data; Evas_Object *aux; Evas_Coord rel_y; double x, y; aux = evas_object_data_get(obj, "x"); x = elm_slider_value_get(aux); y = elm_slider_value_get(evas_object_data_get(aux, "y")); rel_y = elm_slider_value_get(evas_object_data_get(aux, "rely")); ephysics_body_impulse_apply(bd->body, x, y, 0, elm_slider_value_get(obj), rel_y, 0); } static void _impulse_y_y_set_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__) { Body_Data *bd = data; Evas_Object *aux; Evas_Coord rel_x, rel_y; double x; aux = evas_object_data_get(obj, "x"); x = elm_slider_value_get(aux); rel_x = elm_slider_value_get(evas_object_data_get(aux, "relx")); rel_y = elm_slider_value_get(evas_object_data_get(aux, "rely")); ephysics_body_impulse_apply(bd->body, x, elm_slider_value_get(obj), 0, rel_x, rel_y, 0); } static void _impulse_y_rel_set_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__) { Body_Data *bd = data; Evas_Object *aux; Evas_Coord rel_x; double x, y; aux = evas_object_data_get(obj, "x"); x = elm_slider_value_get(aux); y = elm_slider_value_get(evas_object_data_get(aux, "y")); rel_x = elm_slider_value_get(evas_object_data_get(aux, "relx")); ephysics_body_impulse_apply(bd->body, x, y, 0, rel_x, 0, elm_slider_value_get(obj)); } static void _force_x_x_set_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__) { Evas_Coord rel_x, rel_y; Body_Data *bd = data; double y; y = elm_slider_value_get(evas_object_data_get(obj, "y")); rel_x = elm_slider_value_get(evas_object_data_get(obj, "relx")); rel_y = elm_slider_value_get(evas_object_data_get(obj, "rely")); ephysics_body_force_apply(bd->body, elm_slider_value_get(obj), y, 0, rel_x, rel_y, 0); } static void _force_x_rel_set_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__) { Body_Data *bd = data; Evas_Object *aux; Evas_Coord rel_y; double x, y; aux = evas_object_data_get(obj, "x"); x = elm_slider_value_get(aux); y = elm_slider_value_get(evas_object_data_get(aux, "y")); rel_y = elm_slider_value_get(evas_object_data_get(aux, "rely")); ephysics_body_force_apply(bd->body, x, y, 0, elm_slider_value_get(obj), rel_y, 0); } static void _force_y_y_set_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__) { Evas_Coord rel_x, rel_y; Body_Data *bd = data; Evas_Object *aux; double x; aux = evas_object_data_get(obj, "x"); x = elm_slider_value_get(aux); rel_x = elm_slider_value_get(evas_object_data_get(aux, "relx")); rel_y = elm_slider_value_get(evas_object_data_get(aux, "rely")); ephysics_body_force_apply(bd->body, x, elm_slider_value_get(obj), 0, rel_x, rel_y, 0); } static void _force_y_rel_set_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__) { Body_Data *bd = data; Evas_Object *aux; Evas_Coord rel_x; double x, y; aux = evas_object_data_get(obj, "x"); x = elm_slider_value_get(aux); y = elm_slider_value_get(evas_object_data_get(aux, "y")); rel_x = elm_slider_value_get(evas_object_data_get(aux, "relx")); ephysics_body_force_apply(bd->body, x, y, 0, rel_x, elm_slider_value_get(obj), 0); } static void _linear_velocity_x_set_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__) { Body_Data *bd = data; double ylinear; ylinear = elm_slider_value_get(evas_object_data_get(obj, "y")); ephysics_body_linear_velocity_set(bd->body, elm_slider_value_get(obj), ylinear, 0); } static void _linear_velocity_y_set_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__) { Body_Data *bd = data; double xlinear; xlinear = elm_slider_value_get(evas_object_data_get(obj, "x")); ephysics_body_linear_velocity_set(bd->body, xlinear, elm_slider_value_get(obj), 0); } static void _angular_velocity_set_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__) { Body_Data *bd = data; ephysics_body_angular_velocity_set(bd->body, 0, 0, elm_slider_value_get(obj)); } static void _hardness_set_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__) { Body_Data *bd = data; ephysics_body_soft_body_hardness_set(bd->body, elm_slider_value_get(obj)); } static void _simulate_body(Body_Data *bd, Evas_Coord x, Evas_Coord y) { ephysics_body_stop(bd->body); ephysics_body_geometry_set(bd->body, x, y, -15, 70, 70, 30); ephysics_body_linear_velocity_set(bd->body, elm_slider_value_get( bd->controls.velocity.x), elm_slider_value_get( bd->controls.velocity.y), 0); ephysics_body_angular_velocity_set(bd->body, 0, 0, elm_slider_value_get( bd->controls.velocity.angular)); ephysics_body_impulse_apply(bd->body, elm_slider_value_get(bd->controls.impulse.x), elm_slider_value_get(bd->controls.impulse.y), 0, elm_slider_value_get(bd->controls.impulse.relx), elm_slider_value_get(bd->controls.impulse.rely), 0); } static void _simulate(World_Data *wd) { _simulate_body(wd->bd1, (int) WIDTH / 5, (int) HEIGHT / 5); _simulate_body(wd->bd2, (int) WIDTH / 2, (int) HEIGHT / 5); } static void _simulate_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) { _simulate(data); } static void _promote(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) { elm_naviframe_item_promote(data); } /*** Sandbox Widgets ***/ static void _label_add(Evas_Object *bxparent, const char *subcategory, float align) { Evas_Object *label; label = elm_label_add(bxparent); elm_object_text_set(label, subcategory); evas_object_size_hint_weight_set(label, 0.0, 0.0); evas_object_size_hint_align_set(label, align, 0.5); elm_box_pack_end(bxparent, label); evas_object_show(label); } static Evas_Object * _material_selector_add(Body_Data *bd, Evas_Object *bxparent) { Evas_Object *box, *hv; box = elm_box_add(bxparent); elm_box_horizontal_set(box, EINA_TRUE); elm_box_homogeneous_set(box, EINA_TRUE); elm_box_padding_set(box, 25, 0); evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, 0.0); evas_object_size_hint_align_set(box, EVAS_HINT_FILL, 0.0); evas_object_show(box); elm_box_pack_end(bxparent, box); _label_add(box, "Body Material", 1); hv = elm_hoversel_add(box); elm_hoversel_hover_parent_set(hv, bd->wd->nf); elm_object_text_set(hv, materials[EPHYSICS_BODY_MATERIAL_CUSTOM]); elm_hoversel_item_add(hv, materials[EPHYSICS_BODY_MATERIAL_CUSTOM], NULL, ELM_ICON_NONE, _material_set_cb, (void *) EPHYSICS_BODY_MATERIAL_CUSTOM); elm_hoversel_item_add(hv, materials[EPHYSICS_BODY_MATERIAL_CONCRETE], NULL, ELM_ICON_NONE, _material_set_cb, (void *) EPHYSICS_BODY_MATERIAL_CONCRETE); elm_hoversel_item_add(hv, materials[EPHYSICS_BODY_MATERIAL_IRON], NULL, ELM_ICON_NONE, _material_set_cb, (void *) EPHYSICS_BODY_MATERIAL_IRON); elm_hoversel_item_add(hv, materials[EPHYSICS_BODY_MATERIAL_PLASTIC], NULL, ELM_ICON_NONE, _material_set_cb, (void *) EPHYSICS_BODY_MATERIAL_PLASTIC); elm_hoversel_item_add(hv, materials[EPHYSICS_BODY_MATERIAL_POLYSTYRENE], NULL, ELM_ICON_NONE, _material_set_cb, (void *) EPHYSICS_BODY_MATERIAL_POLYSTYRENE); elm_hoversel_item_add(hv, materials[EPHYSICS_BODY_MATERIAL_RUBBER], NULL, ELM_ICON_NONE, _material_set_cb, (void *) EPHYSICS_BODY_MATERIAL_RUBBER); elm_hoversel_item_add(hv, materials[EPHYSICS_BODY_MATERIAL_WOOD], NULL, ELM_ICON_NONE, _material_set_cb, (void *) EPHYSICS_BODY_MATERIAL_WOOD); evas_object_size_hint_align_set(hv, 0.5, 0.5); elm_box_pack_end(box, hv); evas_object_show(hv); evas_object_data_set(hv, "bd", bd); return hv; } static void _type_radio_add(Body_Data *bd, Evas_Object *bxparent) { Evas_Object *dbx, *rbx, *rd, *rdg; dbx = elm_box_add(bxparent); elm_box_horizontal_set(dbx, EINA_TRUE); evas_object_size_hint_weight_set(dbx, EVAS_HINT_EXPAND, 0.0); evas_object_size_hint_align_set(dbx, EVAS_HINT_FILL, 0.0); elm_box_homogeneous_set(dbx, EINA_TRUE); elm_box_align_set(dbx, 1, 0.5); elm_box_pack_end(bxparent, dbx); evas_object_show(dbx); _label_add(dbx, "Body Type", 1); rbx = elm_box_add(bxparent); elm_box_horizontal_set(rbx, EINA_TRUE); evas_object_size_hint_weight_set(rbx, EVAS_HINT_EXPAND, 0.0); evas_object_size_hint_align_set(rbx, EVAS_HINT_FILL, 0.0); elm_box_padding_set(rbx, 25, 0); elm_box_align_set(rbx, 0.5, 0.5); elm_box_pack_end(dbx, rbx); evas_object_show(rbx); rd = elm_radio_add(bxparent); elm_radio_state_value_set(rd, 0); elm_object_text_set(rd, "Solid"); evas_object_size_hint_align_set(rd, 1, 0.5); evas_object_size_hint_weight_set(rd, 0, EVAS_HINT_EXPAND); elm_box_pack_end(rbx, rd); evas_object_show(rd); rdg = rd; evas_object_smart_callback_add(rd, "changed", _type_set_cb, bd); rd = elm_radio_add(bxparent); elm_radio_state_value_set(rd, 1); elm_radio_group_add(rd, rdg); elm_object_text_set(rd, "Soft"); evas_object_size_hint_align_set(rd, 1, 0.5); evas_object_size_hint_weight_set(rd, 0, EVAS_HINT_EXPAND); elm_box_pack_end(rbx, rd); evas_object_show(rd); evas_object_smart_callback_add(rd, "changed", _type_set_cb, bd); } static Evas_Object * _slider_add(Evas_Object *bxparent, const char *subcategory, const char *itemlb, float min, float max, float initial) { Evas_Object *sl, *dbx; dbx = elm_box_add(bxparent); elm_box_horizontal_set(dbx, EINA_TRUE); evas_object_size_hint_weight_set(dbx, EVAS_HINT_EXPAND, 0.0); evas_object_size_hint_align_set(dbx, EVAS_HINT_FILL, 0.0); elm_box_homogeneous_set(dbx, EINA_TRUE); elm_box_align_set(dbx, 0, 0.5); elm_box_pack_end(bxparent, dbx); evas_object_show(dbx); _label_add(dbx, subcategory, 1); sl = elm_slider_add(bxparent); elm_slider_unit_format_set(sl, itemlb); elm_slider_min_max_set(sl, min, max); elm_slider_value_set(sl, initial); elm_slider_span_size_set(sl, 100); evas_object_size_hint_weight_set(sl, EVAS_HINT_EXPAND, 0.0); evas_object_size_hint_align_set(sl, 0, 0.5); elm_box_pack_end(dbx, sl); evas_object_show(sl); return sl; } static Evas_Object * _category_add(Evas_Object *bxparent, const char *label, Eina_Bool collapse) { Evas_Object *cfr, *cbx; cfr = elm_frame_add(bxparent); elm_frame_autocollapse_set(cfr, collapse); elm_frame_collapse_set(cfr, collapse); elm_object_text_set(cfr, label); evas_object_size_hint_weight_set(cfr, EVAS_HINT_EXPAND, 0.0); evas_object_size_hint_fill_set(cfr, EVAS_HINT_FILL, 0.0); elm_box_pack_end(bxparent, cfr); evas_object_show(cfr); cbx = elm_box_add(bxparent); elm_box_horizontal_set(cbx, EINA_FALSE); evas_object_size_hint_weight_set(cbx, EVAS_HINT_EXPAND, 0.0); evas_object_size_hint_align_set(cbx, EVAS_HINT_FILL, 0.0); elm_object_content_set(cfr, cbx); evas_object_show(cbx); return cbx; } /*** Sandbox Pages ***/ static void _menu_page_add(Evas_Object *win, Evas_Object **scroller_box, Evas_Object **content_box) { Evas_Object *scbx, *bx, *sc; scbx = elm_box_add(win); evas_object_size_hint_weight_set(scbx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(scbx, EVAS_HINT_FILL, EVAS_HINT_FILL); evas_object_show(scbx); sc = elm_scroller_add(win); elm_scroller_bounce_set(sc, EINA_FALSE, EINA_TRUE); elm_scroller_policy_set(sc, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO); evas_object_size_hint_weight_set(sc, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_fill_set(sc, EVAS_HINT_FILL, EVAS_HINT_FILL); elm_box_pack_end(scbx, sc); evas_object_show(sc); bx = elm_box_add(win); evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, 0); evas_object_size_hint_align_set(bx, EVAS_HINT_FILL, 0); evas_object_show(bx); elm_object_content_set(sc, bx); *scroller_box = scbx; *content_box = bx; } static void _menu_body_page_add(World_Data *wd, Body_Data *bd, const char *pg_label) { Evas_Object *bx, *bxbody, *scbxbody, *widget, *aux_widget, *material_widget; Elm_Object_Item *it; _menu_page_add(wd->win, &scbxbody, &bxbody); bx = _category_add(bxbody, "", EINA_FALSE); _type_radio_add(bd, bx); material_widget = _material_selector_add(bd, bx); bx = _category_add(bxbody, "Properties", EINA_TRUE); aux_widget = _slider_add(bx, "Mass (kg)", "%1.3f", 0, 99999, INITIAL_MASS); evas_object_data_set(material_widget, "mass", aux_widget); widget = _slider_add(bx, "Density (kg/m³)", "%1.3f", 0, 9999, 0); evas_object_data_set(aux_widget, "density", widget); evas_object_data_set(material_widget, "density", widget); evas_object_smart_callback_add(aux_widget, "delay,changed", _mass_set_cb, bd); evas_object_data_set(widget, "mass", aux_widget); evas_object_smart_callback_add(widget, "delay,changed", _density_set_cb, bd); widget = _slider_add(bx, "Rotation (rad)", "%1.3f", -3.1415, 3.1415, 0); evas_object_smart_callback_add(widget, "delay,changed", _rotation_set_cb, bd); widget = _slider_add(bx, "Friction", "%1.3f", 0, 1, 0.5); evas_object_data_set(material_widget, "friction", widget); evas_object_smart_callback_add(widget, "delay,changed", _friction_set_cb, bd); widget = _slider_add(bx, "Restitution", "%1.3f", 0, 1, 0); evas_object_data_set(material_widget, "restitution", widget); evas_object_smart_callback_add(widget, "delay,changed", _restitution_set_cb, bd); _label_add(bx, "Damping", 0.5); widget = _slider_add(bx, "Linear", "%1.3f", 0, 1, 0); evas_object_smart_callback_add(widget, "delay,changed", _linear_damping_set_cb, bd); widget = _slider_add(bx, "Angular", "%1.3f", 0, 1, 0); evas_object_smart_callback_add(widget, "delay,changed", _angular_damping_set_cb, bd); _label_add(bx, "Sleeping Threshold", 0.5); widget = _slider_add(bx, "Linear (p/s)", "%1.2f", 0, 250, 24); evas_object_smart_callback_add(widget, "delay,changed", _lin_sleeping_threshold_set_cb, bd); widget = _slider_add(bx, "Angular (º/s)", "%1.2f", 0, 360, 57.29); evas_object_smart_callback_add(widget, "delay,changed", _ang_sleeping_threshold_set_cb, bd); bx = _category_add(bxbody, "Actions", EINA_TRUE); _label_add(bx, "Impulse X", 0.5); aux_widget = _slider_add(bx, "X (kg * p/s)", "%1.3f", -9999, 9999, 0); bd->controls.impulse.x = aux_widget; widget = _slider_add(bx, "Rel Position X", "%1.2f", -360, 360, 0); bd->controls.impulse.relx = widget; evas_object_data_set(aux_widget, "relx", widget); _label_add(bx, "Impulse Y", 0.5); widget = _slider_add(bx, "Y (kg * p/s)", "%1.3f", -9999, 9999, 0); bd->controls.impulse.y = widget; evas_object_data_set(aux_widget, "y", widget); widget = _slider_add(bx, "Rel Position Y", "%1.2f", -360, 360, 0); bd->controls.impulse.rely = widget; evas_object_data_set(aux_widget, "rely", widget); evas_object_smart_callback_add(aux_widget, "delay,changed", _impulse_x_x_set_cb, bd); evas_object_data_set(widget, "x", aux_widget); evas_object_smart_callback_add(widget, "delay,changed", _impulse_x_rel_set_cb, bd); widget = evas_object_data_get(aux_widget, "y"); evas_object_data_set(widget, "x", aux_widget); evas_object_smart_callback_add(widget, "delay,changed", _impulse_y_y_set_cb, bd); widget = evas_object_data_get(aux_widget, "relx"); evas_object_data_set(widget, "x", aux_widget); evas_object_smart_callback_add(widget, "delay,changed", _impulse_y_rel_set_cb, bd); _label_add(bx, "Force X", 0.5); aux_widget = _slider_add(bx, "X (kg * p/s/s)", "%1.3f", -1999, 1999, 0); bd->controls.force.x = aux_widget; widget = _slider_add(bx, "Rel Position X", "%1.2f", -360, 360, 0); bd->controls.force.relx = widget; evas_object_data_set(aux_widget, "relx", widget); _label_add(bx, "Force Y", 0.5); widget = _slider_add(bx, "Y (kg * p/s/s)", "%1.3f", -1999, 1999, 0); bd->controls.force.y = widget; evas_object_data_set(aux_widget, "y", widget); widget = _slider_add(bx, "Rel Position Y", "%1.2f", -360, 360, 0); bd->controls.force.rely = widget; evas_object_data_set(aux_widget, "rely", widget); evas_object_smart_callback_add(aux_widget, "delay,changed", _force_x_x_set_cb, bd); evas_object_data_set(widget, "x", aux_widget); evas_object_smart_callback_add(widget, "delay,changed", _force_x_rel_set_cb, bd); widget = evas_object_data_get(aux_widget, "y"); evas_object_data_set(widget, "x", aux_widget); evas_object_smart_callback_add(widget, "delay,changed", _force_y_y_set_cb, bd); widget = evas_object_data_get(aux_widget, "relx"); evas_object_data_set(widget, "x", aux_widget); evas_object_smart_callback_add(widget, "delay,changed", _force_y_rel_set_cb, bd); widget = _slider_add(bx, "Torque", "%1.3f", -100, 100, 0); bd->controls.force.torque = widget; evas_object_smart_callback_add(widget, "delay,changed", _torque_set_cb, bd); _label_add(bx, "Linear Velocity", 0.5); aux_widget = _slider_add(bx, "X (p/s)", "%1.2f", -1499, 1499, 0); bd->controls.velocity.x = aux_widget; widget = _slider_add(bx, "Y (p/s)", "%1.2f", -1499, 1499, 0); bd->controls.velocity.y = widget; evas_object_data_set(aux_widget, "y", widget); evas_object_smart_callback_add(aux_widget, "delay,changed", _linear_velocity_x_set_cb, bd); evas_object_data_set(widget, "x", aux_widget); evas_object_smart_callback_add(widget, "delay,changed", _linear_velocity_y_set_cb, bd); widget = _slider_add(bx, "Angular Velocity (º/s)", "%1.2f", -360, 360, 0); bd->controls.velocity.angular = widget; evas_object_smart_callback_add(widget, "delay,changed", _angular_velocity_set_cb, bd); bx = _category_add(bxbody, "Soft Body", EINA_TRUE); widget = _slider_add(bx, "Hardness (%)", "%1.2f%", 0, 100, 100); bd->controls.hardness = widget; elm_object_disabled_set(widget, EINA_TRUE); evas_object_smart_callback_add(widget, "delay,changed", _hardness_set_cb, bd); it = elm_naviframe_item_insert_before(wd->nf, evas_object_data_get(wd->nf, "world"), NULL, NULL, NULL, scbxbody, NULL); elm_naviframe_item_title_visible_set(it, EINA_FALSE); elm_toolbar_item_append(wd->tb, NULL, pg_label, _promote, it); } static void _menu_world_page_add(World_Data *wd) { Evas_Object *bx, *scbx, *bxparent, *widget; Elm_Object_Item *it; _menu_page_add(wd->win, &scbx, &bxparent); bx = _category_add(bxparent, "World", EINA_FALSE); _label_add(bx, "Gravity (px/s²)", 0.5); widget = _slider_add(bx, "X:", "%1.2f", -1000, 1000, 0); evas_object_smart_callback_add(widget, "delay,changed", _world_gravity_x_cb, wd->world); widget = _slider_add(bx, "Y:", "%1.2f", -1000, 1000, 294); evas_object_smart_callback_add(widget, "delay,changed", _world_gravity_y_cb, wd->world); widget = _slider_add(bx, "Rate (px/m)", "%1.0f", 1, 100, 30); evas_object_smart_callback_add(widget, "delay,changed", _world_rate_cb, wd->world); widget = _slider_add(bx, "Max Sleeping Time (s)", "%1.0f", 0, 50, 2); evas_object_smart_callback_add(widget, "delay,changed", _world_max_sleeping_time_cb, wd->world); bx = _category_add(bxparent, "Boundaries", EINA_FALSE); widget = _slider_add(bx, "Friction", "%1.3f", 0, 1, 0.5); evas_object_smart_callback_add(widget, "delay,changed", _world_friction_cb, wd); widget = _slider_add(bx, "Restitution", "%1.3f", 0, 1, 0); evas_object_smart_callback_add(widget, "delay,changed", _world_restitution_cb, wd); it = elm_naviframe_item_push(wd->nf, NULL, NULL, NULL, scbx, NULL); evas_object_data_set(wd->nf, "world", it); elm_naviframe_item_title_visible_set(it, EINA_FALSE); elm_toolbar_item_append(wd->tb, NULL, "World", _promote, it); } static void _menu_create(World_Data *wd) { Evas_Object *mainbx, *dbx, *btn, *bg, *layout; bg = elm_bg_add(wd->win); elm_win_resize_object_add(wd->win, bg); evas_object_size_hint_min_set(bg, WIDTH, HEIGHT); evas_object_size_hint_max_set(bg, WIDTH, HEIGHT); layout = elm_layout_add(wd->win); elm_layout_file_set(layout, PACKAGE_DATA_DIR "/" SANDBOX_THEME ".edj", "sandbox"); evas_object_resize(layout, WIDTH, HEIGHT); evas_object_show(layout); mainbx = elm_box_add(wd->win); evas_object_size_hint_fill_set(mainbx, EVAS_HINT_FILL, EVAS_HINT_FILL); elm_object_part_content_set(layout, "swallow", mainbx); evas_object_show(mainbx); dbx = elm_box_add(mainbx); elm_box_horizontal_set(dbx, EINA_TRUE); evas_object_size_hint_weight_set(dbx, EVAS_HINT_EXPAND, 0.0); evas_object_size_hint_align_set(dbx, EVAS_HINT_FILL, 0.0); elm_box_align_set(dbx, 0, 0.5); elm_box_pack_end(mainbx, dbx); evas_object_show(dbx); wd->tb = elm_toolbar_add(wd->win); evas_object_size_hint_weight_set(wd->tb, EVAS_HINT_EXPAND, 0); evas_object_size_hint_fill_set(wd->tb, EVAS_HINT_FILL, EVAS_HINT_FILL); elm_toolbar_select_mode_set(wd->tb, ELM_OBJECT_SELECT_MODE_ALWAYS); elm_box_pack_end(dbx, wd->tb); evas_object_show(wd->tb); btn = elm_button_add(wd->win); elm_object_text_set(btn, "Restart"); evas_object_size_hint_min_set(btn, 100, 30); evas_object_size_hint_align_set(btn, 1, 0.5); elm_box_pack_end(dbx, btn); evas_object_show(btn); evas_object_smart_callback_add(btn, "clicked", _simulate_cb, wd); wd->nf = elm_naviframe_add(wd->win); evas_object_size_hint_weight_set(wd->nf, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_fill_set(wd->nf, EVAS_HINT_FILL, EVAS_HINT_FILL); elm_box_pack_end(mainbx, wd->nf); evas_object_show(wd->nf); } static EPhysics_Body * _body_add(Evas_Object *win, EPhysics_World *world, int x, int y) { Evas_Object *body_image; EPhysics_Body *body; body_image = elm_image_add(win); elm_image_file_set( body_image, PACKAGE_DATA_DIR "/" SANDBOX_THEME ".edj", "Custom"); evas_object_resize(body_image, 70, 70); evas_object_move(body_image, x, y); evas_object_show(body_image); body = ephysics_body_cylinder_add(world); ephysics_body_evas_object_set(body, body_image, EINA_TRUE); ephysics_body_mass_set(body, INITIAL_MASS); ephysics_body_event_callback_add(body, EPHYSICS_CALLBACK_BODY_DEL, _body_del, NULL); return body; } EAPI int elm_main() { EPhysics_World *world; Body_Data bd1, bd2; Evas_Object *win; World_Data wd; if (!ephysics_init()) { fprintf(stderr, "Failed to init ephysics\n"); elm_shutdown(); return -1; } elm_theme_extension_add(NULL, PACKAGE_DATA_DIR "/" SANDBOX_THEME ".edj"); elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED); win = elm_win_add(NULL, "Sandbox", ELM_WIN_BASIC); elm_win_title_set(win, "EPhysics Sandbox"); elm_win_autodel_set(win, EINA_TRUE); evas_object_show(win); world = ephysics_world_new(); ephysics_world_simulation_set(world, 1/100.f, 10); ephysics_world_render_geometry_set(world, 80, 80, -50, (int) WIDTH * 0.7 - 160, HEIGHT - 160, DEPTH); wd.top = ephysics_body_top_boundary_add(world); wd.bottom = ephysics_body_bottom_boundary_add(world); wd.left = ephysics_body_left_boundary_add(world); wd.right = ephysics_body_right_boundary_add(world); wd.world = world; wd.win = win; wd.bd1 = &bd1; wd.bd2 = &bd2; bd1.wd = &wd; bd2.wd = &wd; _menu_create(&wd); _menu_world_page_add(&wd); _menu_body_page_add(&wd, &bd1, "Body 1"); _menu_body_page_add(&wd, &bd2, "Body 2"); bd1.body = _body_add(win, world, WIDTH / 5, HEIGHT / 5); bd2.body = _body_add(win, world, WIDTH / 2, HEIGHT / 5); _simulate(&wd); elm_run(); ephysics_shutdown(); elm_shutdown(); return 0; } ELM_MAIN()