diff --git a/src/examples/evas/Makefile.am b/src/examples/evas/Makefile.am index 0218472979..6a47303011 100644 --- a/src/examples/evas/Makefile.am +++ b/src/examples/evas/Makefile.am @@ -359,6 +359,7 @@ resources/images/four_NM_height.tga \ resources/images/rocks_NM_height.tga \ resources/images/grid.png \ resources/images/grid_n.png \ +resources/images/billboard.png \ resources/models/mesh_for_mmap.eet \ resources/models/mesh_for_mmap.md2 \ resources/models/mesh_for_mmap.obj \ diff --git a/src/examples/evas/evas-3d-shadows.c b/src/examples/evas/evas-3d-shadows.c index c1eb0875d5..701a474067 100644 --- a/src/examples/evas/evas-3d-shadows.c +++ b/src/examples/evas/evas-3d-shadows.c @@ -1,9 +1,11 @@ /** - * This example illustrating use of shadows in the scene and callbacks(clicked, collision). + * This example illustrating use of shadows, callbacks(clicked, collision), + * and technic of the billboard. * Model and cube are clickable. Model detects collision with sphere. * Cube detects collision with sphere, model and cone. * @see evas_3d_scene_shadows_enable_set(Eina_Bool _shadows_enabled) * @see evas_3d_object_callback_register + * @see evas_3d_billboard_set/get * * @verbatim * gcc -o evas-3d-shadows evas-3d-shadows.c evas-3d-primitives.c `pkg-config --libs --cflags efl evas ecore ecore-evas eo eina` -lm @@ -37,7 +39,8 @@ #define SPECULAR_LIGHT 1.0, 1.0, 1.0 static const char *model_path = PACKAGE_EXAMPLES_DIR EVAS_MODEL_FOLDER "/sonic.md2"; - +static const char *image_path = PACKAGE_EXAMPLES_DIR EVAS_IMAGE_FOLDER "/sonic.png"; +static const char *b_image_path = PACKAGE_EXAMPLES_DIR EVAS_IMAGE_FOLDER "/billboard.png"; static const vec2 tex_scale = {1, 1}; static const vec2 fence_tex_scale = {80, 6}; @@ -89,6 +92,7 @@ typedef struct _Body_3D Eo *material; Eo *mesh; Eo *node; + Eo *texture; } Body_3D; typedef struct _Scene_Data @@ -99,6 +103,7 @@ typedef struct _Scene_Data Eo *camera; Eo *light_node; Eo *light; + Eo *mediator; Body_3D sphere; Body_3D cube; @@ -107,6 +112,9 @@ typedef struct _Scene_Data Body_3D model; Body_3D cone; Body_3D fence; + Body_3D billboard; + + Eina_Bool init; } Scene_Data; static void @@ -114,23 +122,37 @@ _show_help() { fprintf(stdout, "Press 'w'/'s' key to move up/down object\n"); fprintf(stdout, "Press 'a'/'d' key to move left/right object\n"); - fprintf(stdout, "Press 'q'/'e' key to to move near/far object\n"); + fprintf(stdout, "Press 'q'/'e' key to move near/far object\n"); fprintf(stdout, "Cude and model can be moved.\n"); fprintf(stdout, "Cube detects intersection with model, sphere, cone\n"); fprintf(stdout, "Model detects intersection with sphere\n"); + fprintf(stdout, "Press '1'/'2' key to change kind of node - billboard/normal model\n"); + fprintf(stdout, "Press Up/Down key to change position of camera\n"); + fprintf(stdout, "Press 'i' key to return initial view of scene\n"); } static Eina_Bool _animate_scene(void *data) { - static int frame = 0; - Body_3D *body = (Body_3D *)data; - - eo_do(body->node, evas_3d_node_mesh_frame_set(body->mesh, frame)); - - /*frame += 32;*/ - - if (frame > 256 * 20) frame = 0; + static float angle = 0; + Evas_Real x, y, z; + Scene_Data *scene = (Scene_Data *)data; + if (scene->init) + { + eo_do(scene->mediator, + evas_3d_node_position_get(EVAS_3D_SPACE_PARENT, &x, &y, &z)); + eo_do(scene->mediator, + evas_3d_node_position_set(sin(angle) * 20 , y , cos(angle) * 20), + evas_3d_node_look_at_set(EVAS_3D_SPACE_PARENT, 0.0, 3.0, 0.0, + EVAS_3D_SPACE_PARENT, 0.0, 5.0, 0.0)); + angle += 0.005; + if (angle > 360) angle = 0.0; + } + else + eo_do(scene->mediator, + evas_3d_node_position_set(0.0, 6.0, 12.0), + evas_3d_node_look_at_set(EVAS_3D_SPACE_PARENT, 0.0, 3.0, 0.0, + EVAS_3D_SPACE_PARENT, 0.0, 5.0, 0.0)); return EINA_TRUE; } @@ -241,6 +263,9 @@ _fence_setup(Body_3D *fence) evas_3d_material_enable_set(EVAS_3D_MATERIAL_SPECULAR, EINA_TRUE), evas_3d_material_enable_set(EVAS_3D_MATERIAL_NORMAL, EINA_TRUE), evas_3d_material_texture_set(EVAS_3D_MATERIAL_NORMAL, texture1), + evas_3d_material_color_set(EVAS_3D_MATERIAL_AMBIENT, 1.0, 1.0, 1.0, 1.0), + evas_3d_material_color_set(EVAS_3D_MATERIAL_DIFFUSE, 1.0, 1.0, 1.0, 1.0), + evas_3d_material_color_set(EVAS_3D_MATERIAL_SPECULAR, 1.0, 1.0, 1.0, 1.0), evas_3d_material_shininess_set(100.0)); fence->mesh = eo_add(EVAS_3D_MESH_CLASS, evas); evas_3d_add_cylinder_frame(fence->mesh, 0, 50, fence_tex_scale); @@ -292,9 +317,9 @@ _box_setup(Body_3D *box) static void _model_setup(Body_3D *model) { - Eo *texture = eo_add(EVAS_3D_TEXTURE_CLASS, evas); - eo_do(texture, - evas_3d_texture_file_set(PACKAGE_EXAMPLES_DIR EVAS_IMAGE_FOLDER "/sonic.png", NULL), + model->texture = eo_add(EVAS_3D_TEXTURE_CLASS, evas); + eo_do(model->texture, + evas_3d_texture_file_set(image_path, NULL), evas_3d_texture_filter_set(EVAS_3D_TEXTURE_FILTER_NEAREST, EVAS_3D_TEXTURE_FILTER_NEAREST), evas_3d_texture_wrap_set(EVAS_3D_WRAP_MODE_REPEAT, @@ -302,8 +327,8 @@ _model_setup(Body_3D *model) model->material = eo_add(EVAS_3D_MATERIAL_CLASS, evas); eo_do(model->material, - evas_3d_material_texture_set(EVAS_3D_MATERIAL_DIFFUSE, texture), - evas_3d_material_texture_set(EVAS_3D_MATERIAL_AMBIENT, texture), + evas_3d_material_texture_set(EVAS_3D_MATERIAL_DIFFUSE, model->texture), + evas_3d_material_texture_set(EVAS_3D_MATERIAL_AMBIENT, model->texture), evas_3d_material_enable_set(EVAS_3D_MATERIAL_AMBIENT, EINA_TRUE), evas_3d_material_enable_set(EVAS_3D_MATERIAL_DIFFUSE, EINA_TRUE), evas_3d_material_enable_set(EVAS_3D_MATERIAL_SPECULAR, EINA_TRUE), @@ -311,7 +336,6 @@ _model_setup(Body_3D *model) model->mesh = eo_add(EVAS_3D_MESH_CLASS, evas); - eo_do(model->mesh, efl_file_set(model_path, NULL), evas_3d_mesh_frame_material_set(0, model->material), @@ -325,25 +349,70 @@ _model_setup(Body_3D *model) evas_3d_node_orientation_angle_axis_set(120.0, -0.577, -0.577, -0.577)); } +static void +_billboard_setup(Scene_Data *data) +{ + data->billboard.texture = eo_add(EVAS_3D_TEXTURE_CLASS, evas); + eo_do(data->billboard.texture, + evas_3d_texture_file_set(b_image_path, NULL), + evas_3d_texture_filter_set(EVAS_3D_TEXTURE_FILTER_NEAREST, + EVAS_3D_TEXTURE_FILTER_NEAREST), + evas_3d_texture_wrap_set(EVAS_3D_WRAP_MODE_REPEAT, + EVAS_3D_WRAP_MODE_REPEAT)); + + data->billboard.mesh = eo_add(EVAS_3D_MESH_CLASS, evas); + evas_3d_add_square_frame(data->billboard.mesh, 0); + + _body_material_set(&(data->billboard), 1.0, 1.0, 1.0); + + eo_do(data->billboard.material, + evas_3d_material_texture_set(EVAS_3D_MATERIAL_DIFFUSE, data->billboard.texture)); + + eo_do(data->billboard.mesh, + evas_3d_mesh_frame_material_set(0, data->billboard.material), + evas_3d_mesh_alpha_func_set(EVAS_3D_COMPARISON_GREATER, 0), + evas_3d_mesh_alpha_test_enable_set(EINA_TRUE), + evas_3d_mesh_shade_mode_set(EVAS_3D_SHADE_MODE_DIFFUSE), + evas_3d_mesh_blending_enable_set(EINA_TRUE), + evas_3d_mesh_blending_func_set(EVAS_3D_BLEND_SRC_ALPHA, + EVAS_3D_BLEND_ONE_MINUS_SRC_ALPHA)); + + data->billboard.node = eo_add(EVAS_3D_NODE_CLASS, evas, + evas_3d_node_constructor(EVAS_3D_NODE_TYPE_MESH)); + eo_do(data->billboard.node, + evas_3d_node_mesh_add(data->billboard.mesh), + evas_3d_node_position_set(0.0, 2.0, 0.0), + evas_3d_node_scale_set(2.2, 4.6, 4.0)); + + eo_do(data->billboard.node, + evas_3d_node_billboard_target_set(data->mediator)); +} + static void _camera_setup(Scene_Data *data) { data->camera = eo_add(EVAS_3D_CAMERA_CLASS, evas); + data->mediator = eo_add(EVAS_3D_NODE_CLASS, evas, + evas_3d_node_constructor(EVAS_3D_NODE_TYPE_NODE)); eo_do(data->camera, - evas_3d_camera_projection_perspective_set(50.0, 1.0, 2.0, 50.0)); + evas_3d_camera_projection_perspective_set(50.0, 1.0, 2.0, 100.0)); data->camera_node = eo_add(EVAS_3D_NODE_CLASS, evas, evas_3d_node_constructor(EVAS_3D_NODE_TYPE_CAMERA)); eo_do(data->camera_node, - evas_3d_node_camera_set(data->camera), + evas_3d_node_camera_set(data->camera)); + + + eo_do(data->mediator, evas_3d_node_position_set(0.0, 6.0, 12.0), evas_3d_node_look_at_set(EVAS_3D_SPACE_PARENT, 0.0, 3.0, 0.0, EVAS_3D_SPACE_PARENT, 0.0, 5.0, 0.0)); - eo_do(data->root_node, evas_3d_node_member_add(data->camera_node)); + eo_do(data->mediator, evas_3d_node_member_add(data->camera_node)); + eo_do(data->root_node, evas_3d_node_member_add(data->mediator)); } static void @@ -362,7 +431,7 @@ _light_setup(Scene_Data *data) evas_3d_node_constructor(EVAS_3D_NODE_TYPE_LIGHT)); eo_do(data->light_node, evas_3d_node_light_set(data->light), - evas_3d_node_position_set(50.0, 50.0, 20.0), + evas_3d_node_position_set(50.0, 50.0, 70.0), evas_3d_node_look_at_set(EVAS_3D_SPACE_PARENT, 15.0, 0.0, -5.0, EVAS_3D_SPACE_PARENT, 0.0, 0.0, 1.0)); eo_do(data->root_node, evas_3d_node_member_add(data->light_node)); @@ -371,6 +440,8 @@ _light_setup(Scene_Data *data) static void _scene_setup(Scene_Data *data) { + data->init = EINA_FALSE; + data->scene = eo_add(EVAS_3D_SCENE_CLASS, evas); eo_do(data->scene, @@ -392,8 +463,9 @@ _scene_setup(Scene_Data *data) _model_setup(&data->model); _cone_setup(&data->cone); _fence_setup(&data->fence); + _billboard_setup(data); - eo_do(data->root_node, + eo_do(data->root_node, evas_3d_node_member_add(data->sphere.node), evas_3d_node_member_add(data->cube.node), evas_3d_node_member_add(data->cylinder.node), @@ -412,6 +484,7 @@ static void _on_key_down(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *eo EINA_UNUSED, void *event_info) { Evas_Event_Key_Down *ev = event_info; + Scene_Data *scene = (Scene_Data *)data; if (!strcmp("w", ev->key)) { Evas_Real x, y, z; @@ -448,6 +521,34 @@ _on_key_down(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *eo EINA_U eo_do(choosed_node, evas_3d_node_position_get(EVAS_3D_SPACE_PARENT, &x, &y, &z)); eo_do(choosed_node, evas_3d_node_position_set(x, y, z + STEP)); } + else if(!strcmp("1", ev->key)) + { + eo_do(scene->root_node, evas_3d_node_member_del(scene->model.node)); + eo_do(scene->root_node, evas_3d_node_member_add(scene->billboard.node)); + } + else if(!strcmp("2", ev->key)) + { + eo_do(scene->root_node, evas_3d_node_member_add(scene->model.node)); + eo_do(scene->root_node, evas_3d_node_member_del(scene->billboard.node)); + } + else if(!strcmp("Up", ev->key)) + { + Evas_Real x, y, z; + eo_do(scene->camera_node, evas_3d_node_position_get(EVAS_3D_SPACE_PARENT, &x, &y, &z)); + eo_do(scene->camera_node, evas_3d_node_position_set(x, y, z + STEP)); + } + else if(!strcmp("Down", ev->key)) + { + Evas_Real x, y, z; + eo_do(scene->camera_node, evas_3d_node_position_get(EVAS_3D_SPACE_PARENT, &x, &y, &z)); + eo_do(scene->camera_node, evas_3d_node_position_set(x, y, z - STEP)); + } + else if (!strcmp("i", ev->key)) + { + scene->init = !scene->init; + eo_do(scene->model.node, evas_3d_node_position_set(0.0, 0.0, 0.0)); + eo_do(scene->billboard.node, evas_3d_node_position_set(0.0, 2.0, 0.0)); + } else { _show_help(); @@ -551,12 +652,15 @@ main(void) eo_do(data.model.node, eo_event_callback_add(EVAS_3D_OBJECT_EVENT_CLICKED, _cb_clicked, NULL)); eo_do(data.model.node, eo_event_callback_add(EVAS_3D_OBJECT_EVENT_COLLISION, _cb_collision, nodes1)); + eo_do(data.billboard.node, eo_event_callback_add(EVAS_3D_OBJECT_EVENT_CLICKED, _cb_clicked, NULL)); + eo_do(data.billboard.node, eo_event_callback_add(EVAS_3D_OBJECT_EVENT_COLLISION, _cb_collision, nodes1)); + evas_object_event_callback_add(image, EVAS_CALLBACK_MOUSE_DOWN, _on_mouse_down, &data); evas_object_event_callback_add(image, EVAS_CALLBACK_KEY_DOWN, _on_key_down, &data); /* Add animator. */ ecore_animator_frametime_set(0.008); - anim = ecore_animator_add(_animate_scene, &data.model); + anim = ecore_animator_add(_animate_scene, &data); /* Enter main loop. */ ecore_main_loop_begin(); diff --git a/src/examples/evas/resources/images/billboard.png b/src/examples/evas/resources/images/billboard.png new file mode 100644 index 0000000000..0a6915de04 Binary files /dev/null and b/src/examples/evas/resources/images/billboard.png differ diff --git a/src/lib/evas/Evas_Eo.h b/src/lib/evas/Evas_Eo.h index 1e1c639bb0..1e1fb5945b 100644 --- a/src/lib/evas/Evas_Eo.h +++ b/src/lib/evas/Evas_Eo.h @@ -516,6 +516,7 @@ typedef enum _Evas_3D_State EVAS_3D_STATE_NODE_PARENT_ORIENTATION, EVAS_3D_STATE_NODE_PARENT_SCALE, EVAS_3D_STATE_NODE_MEMBER, + EVAS_3D_STATE_NODE_PARENT_BILLBOARD, } Evas_3D_State; /** diff --git a/src/lib/evas/canvas/evas_3d_node.c b/src/lib/evas/canvas/evas_3d_node.c index 1f69cdcd66..746665e3df 100644 --- a/src/lib/evas/canvas/evas_3d_node.c +++ b/src/lib/evas/canvas/evas_3d_node.c @@ -7,6 +7,9 @@ Evas_3D_Mesh_Frame *evas_3d_mesh_frame_find(Evas_3D_Mesh_Data *pd, int frame); +static void +_look_at_set(Evas_3D_Node_Data *pd, Evas_Vec3 *target, Evas_Vec3 *up); + static Eina_Stringshare * _generate_unic_color_key(Evas_Color *color, Evas_Color *bg_color, Evas_3D_Node *node, Evas_3D_Mesh *mesh, Eina_Bool init) @@ -156,9 +159,13 @@ _evas_3d_node_evas_3d_object_change_notify(Eo *obj, Evas_3D_Node_Data *pd, Evas_ { eo_do(n, evas_3d_object_change(EVAS_3D_STATE_NODE_PARENT_SCALE, obj)); } - if (orientation) + if (orientation && !(pd->billboard_target)) EINA_LIST_FOREACH(pd->members, l, n) { + /*Skip change orientation if node is billboard*/ + Evas_3D_Node_Data *pdm = eo_data_scope_get(n, EVAS_3D_NODE_CLASS); + if (pdm->billboard_target) + continue; eo_do(n, evas_3d_object_change(EVAS_3D_STATE_NODE_PARENT_ORIENTATION, obj)); } if (position) @@ -285,6 +292,46 @@ _node_transform_update(Evas_3D_Node *node, void *data EINA_UNUSED) return EINA_TRUE; } +static Eina_Bool +_node_billboard_update(Evas_3D_Node *node, void *data EINA_UNUSED) +{ + Evas_Vec3 target; + Evas_Vec3 up; + Evas_3D_Node_Data *pd_node = eo_data_scope_get(node, MY_CLASS); + if (pd_node->billboard_target) + { + Evas_3D_Node_Data *pd_target = eo_data_scope_get(pd_node->billboard_target, + MY_CLASS); + evas_vec3_set(&target, pd_target->position.x, pd_target->position.y, + pd_target->position.z); + evas_vec3_set(&up, 0, 1, 0); + + _look_at_set(pd_node, &target, &up); + + if (pd_node->type == EVAS_3D_NODE_TYPE_MESH) + { + evas_mat4_build(&pd_node->data.mesh.matrix_local_to_world, + &pd_node->position, &pd_node->orientation, + &pd_node->scale); + } + else if (pd_node->type == EVAS_3D_NODE_TYPE_LIGHT) + { + evas_mat4_build(&pd_node->data.light.matrix_local_to_world, + &pd_node->position, &pd_node->orientation, + &pd_node->scale); + } + else if (pd_node->type == EVAS_3D_NODE_TYPE_CAMERA) + { + evas_mat4_inverse_build(&pd_node->data.light.matrix_local_to_world, + &pd_node->position, &pd_node->orientation, + &pd_node->scale); + } + else + ERR("Not supported type of node: line %d in file %s", __LINE__ , __FILE__); + } + return EINA_TRUE; +} + static Eina_Bool _node_item_update(Evas_3D_Node *node, void *data EINA_UNUSED) { @@ -589,7 +636,9 @@ _evas_3d_node_evas_3d_object_update_notify(Eo *obj, Evas_3D_Node_Data *pd EINA_U /* Update transform. */ evas_3d_node_tree_traverse(obj, EVAS_3D_TREE_TRAVERSE_LEVEL_ORDER, EINA_FALSE, _node_transform_update, NULL); - + /*Update billboard*/ + evas_3d_node_tree_traverse(obj, EVAS_3D_TREE_TRAVERSE_ANY_ORDER, EINA_FALSE, + _node_billboard_update, NULL); /* Update AABB. */ evas_3d_node_tree_traverse(obj, EVAS_3D_TREE_TRAVERSE_POST_ORDER, EINA_FALSE, _node_aabb_update, NULL); @@ -1035,6 +1084,7 @@ _evas_3d_node_constructor(Eo *obj, Evas_3D_Node_Data *pd, Evas_3D_Node_Type type pd->orientation_inherit = EINA_TRUE; pd->scale_inherit = EINA_TRUE; pd->data.mesh.node_meshes = 0; + pd->billboard_target = NULL; evas_box3_set(&pd->aabb, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); @@ -1310,62 +1360,15 @@ _evas_3d_node_scale_inherit_get(Eo *obj EINA_UNUSED, Evas_3D_Node_Data *pd) return pd->scale_inherit; } -EOLIAN static void -_evas_3d_node_look_at_set(Eo *obj, Evas_3D_Node_Data *pd, - Evas_3D_Space target_space, Evas_Real tx, Evas_Real ty, Evas_Real tz, - Evas_3D_Space up_space, Evas_Real ux, Evas_Real uy, Evas_Real uz) +static void +_look_at_set(Evas_3D_Node_Data *pd, Evas_Vec3 *target, Evas_Vec3 *up) { - Evas_Vec3 target; - Evas_Vec3 up; Evas_Vec3 x, y, z; - /* Target position in parent space. */ - if (target_space == EVAS_3D_SPACE_LOCAL) - { - ERR("TODO:"); - return; - } - else if (target_space == EVAS_3D_SPACE_PARENT) - { - evas_vec3_set(&target, tx, ty, tz); - } - else if (target_space == EVAS_3D_SPACE_WORLD) - { - ERR("TODO:"); - return; - } - else - { - ERR("Invalid coordinate space."); - return; - } - - if (up_space == EVAS_3D_SPACE_LOCAL) - { - evas_vec3_set(&up, ux, uy, uz); - //ERR("TODO:"); - //return; - } - else if (up_space == EVAS_3D_SPACE_PARENT) - { - evas_vec3_set(&up, ux, uy, uz); - } - else if (up_space == EVAS_3D_SPACE_WORLD) - { - ERR("TODO:"); - return; - } - else - { - ERR("Invalid coordinate space."); - return; - } - - /* From now on, everything takes place in parent space. */ - evas_vec3_subtract(&z, &pd->position, &target); + evas_vec3_subtract(&z, &pd->position, target); evas_vec3_normalize(&z, &z); - evas_vec3_cross_product(&x, &up, &z); + evas_vec3_cross_product(&x, up, &z); evas_vec3_normalize(&x, &x); evas_vec3_cross_product(&y, &z, &x); @@ -1416,6 +1419,60 @@ _evas_3d_node_look_at_set(Eo *obj, Evas_3D_Node_Data *pd, pd->orientation.x = (z.x + x.z) * s; pd->orientation.y = (y.z + z.y) * s; } +} + +EOLIAN static void +_evas_3d_node_look_at_set(Eo *obj, Evas_3D_Node_Data *pd, + Evas_3D_Space target_space, Evas_Real tx, Evas_Real ty, Evas_Real tz, + Evas_3D_Space up_space, Evas_Real ux, Evas_Real uy, Evas_Real uz) +{ + Evas_Vec3 target; + Evas_Vec3 up; + + /* Target position in parent space. */ + if (target_space == EVAS_3D_SPACE_LOCAL) + { + ERR("TODO:"); + return; + } + else if (target_space == EVAS_3D_SPACE_PARENT) + { + evas_vec3_set(&target, tx, ty, tz); + } + else if (target_space == EVAS_3D_SPACE_WORLD) + { + ERR("TODO:"); + return; + + } + else + { + ERR("Invalid coordinate space."); + return; + } + + if (up_space == EVAS_3D_SPACE_LOCAL) + { + evas_vec3_set(&up, ux, uy, uz); + //ERR("TODO:"); + //return; + } + else if (up_space == EVAS_3D_SPACE_PARENT) + { + evas_vec3_set(&up, ux, uy, uz); + } + else if (up_space == EVAS_3D_SPACE_WORLD) + { + ERR("TODO:"); + return; + } + else + { + ERR("Invalid coordinate space."); + return; + } + + _look_at_set(pd, &target, &up); eo_do(obj, evas_3d_object_change(EVAS_3D_STATE_NODE_TRANSFORM_ORIENTATION, NULL)); } @@ -1624,4 +1681,20 @@ _evas_3d_node_bounding_sphere_get(Eo *obj EINA_UNUSED, Evas_3D_Node_Data *pd, Ev if (r) *r = pd->bsphere.radius; } +EOLIAN static void +_evas_3d_node_billboard_target_set(Eo *obj EINA_UNUSED, Evas_3D_Node_Data *pd, + Eo *target) +{ + if (pd->billboard_target != target) + { + pd->billboard_target = target; + eo_do(obj, evas_3d_object_change(EVAS_3D_STATE_NODE_PARENT_BILLBOARD, NULL)); + } +} + +EOLIAN static Evas_3D_Node * +_evas_3d_node_billboard_target_get(Eo *obj EINA_UNUSED, Evas_3D_Node_Data *pd) +{ + return pd->billboard_target; +} #include "canvas/evas_3d_node.eo.c" diff --git a/src/lib/evas/canvas/evas_3d_node.eo b/src/lib/evas/canvas/evas_3d_node.eo index b602fd29bc..4ecb26141e 100644 --- a/src/lib/evas/canvas/evas_3d_node.eo +++ b/src/lib/evas/canvas/evas_3d_node.eo @@ -576,6 +576,35 @@ class Evas_3D_Node (Evas_3D_Object, Evas.Common_Interface) int frame; /*@ The animation frame number.*/ } } + + billboard_target { + set { + /* + Set behavior of node like billboard object. + + @param node The given node. + @param billboard Pointer to target node for given node. + + @ingroup Evas_3D_Node + */ + } + get { + /* + Get the target node for billboard object. + + @param node The given node. + @return The pointer to target node for billboard object, + or @c NULL if there're none. + + @see evas_3d_node_billboard_set() + + @ingroup Evas_3D_Node + */ + } + values { + Eo *target; /*@ Target node.*/ + } + } } implements { Eo.Base.destructor; diff --git a/src/lib/evas/include/evas_private.h b/src/lib/evas/include/evas_private.h index c44a240e5e..03df174926 100644 --- a/src/lib/evas/include/evas_private.h +++ b/src/lib/evas/include/evas_private.h @@ -209,6 +209,7 @@ struct _Evas_3D_Node { Eina_List *members; Evas_3D_Node *parent; + Evas_3D_Node *billboard_target; Evas_Vec3 position; Evas_Vec4 orientation;