indexing description: "[ Objects representing clickable areas or items on the world panorama cylinder. If they represent clickable areas then they are static and invisible. If they represent clickable items then they have a representing image and they are animatable. This class is part of the XAE Extended Adventure Engine Project. ]" author: "Ralph Wiedemeier, ralphw@student.ethz.ch" date: "$Date$" revision: "$Revision$" class GUI_CLICKABLE_3D inherit GUI_CLICKABLE redefine make_from_position_and_size, make_from_rect end GUI_DRAWABLE undefine out end GUI_SHARED export {NONE} all undefine out end EM_SHARED_BITMAP_FACTORY export {NONE} all undefine out end create make_animated, make_from_position_and_image, make_from_rect, make_from_position_and_size feature -- Initialization make_animated (a_path: STRING; an_x, an_y: INTEGER; an_animation: ANIMATION) is -- create new visible and animated item require valid_animation: an_animation /= Void do animation := an_animation make_from_position_and_image (a_path, an_x, an_y) end make_from_position_and_image (a_path: STRING; an_x: INTEGER; an_y: INTEGER) is -- create new visible item require valid_path: a_path /= Void do create textures.make set_x (an_x) set_y (an_y) set_visible set_enabled image_path := a_path pre_load_all_images current_display_list := display_lists.item (0) end make_from_rect (a_rect: EM_RECT) is -- create new invisible clickable area do make_from_position_and_size (a_rect.x, a_rect.y, a_rect.width, a_rect.height) end make_from_position_and_size (an_x: INTEGER; an_y: INTEGER; a_width: INTEGER; a_height: INTEGER) is -- Create new invisible clickable from specified position and size do create textures.make set_x (an_x) set_y (an_y) set_width (a_width) set_height (a_height) image_path := Void pre_load_all_images set_invisible set_enabled end feature -- Status set_animation (an_animation: ANIMATION) is -- Attach animation script to current item require valid_animation: an_animation /= Void do animation := an_animation pre_load_all_images end feature -- Operations draw (a_surface: EM_VIDEO_SURFACE) is -- Draws representation of current item if visible local angle: DOUBLE xx, yy: INTEGER do xx := x + width // 2 yy := y + height // 2 if is_visible then angle := 180 - (xx * 360 / 4096) emgl_push_matrix emgl_translated (0, 256 - yy, 0) emgl_rotated (angle, 0, 1, 0) current_display_list.call_list emgl_pop_matrix end end update (time: INTEGER) is -- Update position of item according to the -- given time and the animation script do if animation /= Void then animation.set_interpolation_request (time) set_x (animation.x) set_y (animation.y) current_display_list := display_lists.item (animation.image_number) end end dispose_texture_memory is -- Free memory of used textures do from textures.start until textures.after loop textures.item.dispose textures.forth end end feature {NONE} -- Implementation generate_gl_script (texture: EM3D_TEXTURE_2D[ EMGL_FORMAT_RGBA ]): EMGL_DISPLAY_LIST is -- Creates OpenGL script using specified texture -- and return script id. local xw, yh: DOUBLE stage_radius: INTEGER display_list: EMGL_DISPLAY_LIST do stage_radius := gui_constants.stage_radius xw := width * 0.5 yh := height * 0.5 create display_list display_list.new_list_compile if texture /= void then texture.bind else emgl_disable (em_gl_texture_2d) end emgl_enable( em_gl_blend ) emgl_blend_func ( em_gl_src_alpha, em_gl_one_minus_src_alpha) emgl_disable( em_gl_depth_test ) -- Draw the item emgl_begin (em_gl_quads) emgl_color4f (1, 0, 0, 0.3) if texture /= void then emgl_tex_coord2f( 1, 0 ) end emgl_vertex3d ( xw, yh, -stage_radius) if texture /= void then emgl_tex_coord2f( 0, 0 ) end emgl_vertex3d (-xw, yh, -stage_radius) if texture /= void then emgl_tex_coord2f( 0, 1 ) end emgl_vertex3d (-xw, -yh, -stage_radius) if texture /= void then emgl_tex_coord2f( 1, 1 ) end emgl_vertex3d ( xw, -yh, -stage_radius) emgl_end if texture /= void then texture.unbind end display_list.end_list Result := display_list end make_texture_from_image (a_path: STRING): EMGL_DISPLAY_LIST is -- Load image, create texture and script macro -- and return id of created macro local texture: EM3D_TEXTURE_2D[ EMGL_FORMAT_RGBA ] do bitmap_factory.create_bitmap_from_image (a_path) check bitmap_created: bitmap_factory.last_bitmap /= Void end if bitmap_factory.last_bitmap = Void then gui.application.throw_unrecoverable_exception ("File not found error: " + a_path) -- Result := -1 Result := void else set_width (bitmap_factory.last_bitmap.width) set_height (bitmap_factory.last_bitmap.height) create texture.make_mipmap_from_surface ( bitmap_factory.last_bitmap ) textures.extend (texture) Result := generate_gl_script (texture) end end pre_load_all_images is -- Cache all images used by animation of current item local display_list: EMGL_DISPLAY_LIST i, n: INTEGER do if image_path /= Void then if animation = Void then create display_lists.make (0, 0) display_list := make_texture_from_image (image_path) display_lists.put (display_list, 0) else n := animation.total_number_of_images_used create display_lists.make (0, n-1) from i := 0 until i = n loop display_list := make_texture_from_image (full_image_path (image_path, i)) display_lists.put (display_list, i) i := i + 1 end end else create display_lists.make (0, 0) display_list := generate_gl_script (void) display_lists.put (display_list, 0) end end full_image_path (a_path: STRING; a_number: INTEGER): STRING is -- Returns fully qualified image path made of 'a_path', followed -- by 'a_number' and the extension specified in 'a_path' local body, extension: STRING do if a_number < 1 then Result := a_path else create body.make_from_string (a_path) body.remove_tail (4) create extension.make_from_string (a_path) extension.remove_head (a_path.count - 4) Result := body + a_number.out + extension end end textures: LINKED_LIST [ DISPOSABLE ] image_path: STRING -- Base path and filename for images display_lists: ARRAY [EMGL_DISPLAY_LIST] -- Array containing script id's for all images -- used by current item current_display_list: EMGL_DISPLAY_LIST -- Number of current script animation: ANIMATION -- Animation object attached to 'current' end -- class GUI_CLICKABLE_3D