lighttroupe/luz

View on GitHub
gui/gui_object.rb

Summary

Maintainability
B
4 hrs
Test Coverage
#
# GuiObject is base class for all Gui objects
#
class GuiObject
    include MethodsForUserObject

    include GuiPointerBehavior
    include ValueAnimation
    include ValueAnimationStates
    include Drawing

    BACKGROUND_COLOR = [0.0,0.0,0.0,0.0]
    BACKGROUND_COLOR_HOVERING = [1.0,1.0,1.0,0.25]
    BACKGROUND_COLOR_SELECTED = [0.6,0.5,1.0,0.35]
    BACKGROUND_COLOR_SELECTED_AND_HOVERING = [0.8,0.7,1.0,0.45]

    easy_accessor :parent, :offset_x, :offset_y, :float, :scale_x, :scale_y, :roll, :opacity, :color, :keyboard_focus_image, :background_image, :background_scale_x, :background_scale_y
    boolean_accessor :hidden
    boolean_accessor :draggable

    def set(hash)
        hash.each { |key, value|
            self.send(key.to_s + '=', value)
        }
        self
    end

    def set_scale(scale)
        @scale_x, @scale_y = scale, scale
        self
    end
    alias :scale= :set_scale

    def show!
        self.hidden = false
    end

    def visible?
        !hidden?
    end

    def selected?
        @parent && @parent.respond_to?(:child_is_selected?) && @parent.child_is_selected?(self)
    end

    #
    # Keyboard focus
    #
    def cancel_keyboard_focus!
        $gui.cancel_keyboard_focus_for(self)
    end

    def grab_keyboard_focus!(&proc)
        $gui.grab_keyboard_focus(self, &proc)
        self
    end

    def keyboard_focus?
        $gui.has_keyboard_focus?(self)
    end

    def on_key_press(value)
        @parent.on_key_press(value) if @parent        # pass it up the heirarchy
    end

    #
    #
    #
    def gui_tick
        # override
    end

    easy_accessor :skip_hit_test
    def hit_test_render!
        return if skip_hit_test
        with_positioning {
            render_hit_test_unit_square
        }
    end

    def render_hit_test_unit_square
        with_unique_hit_test_color_for_object(self) {
            unit_square
        }
    end

    def gui_render
        with_positioning {
            gui_render_background
            gui_render_placeholder unless background_image
        }
    end

    def with_keyboard_focus_image
        if keyboard_focus_image
            keyboard_focus_image.using { yield }
        else
            @default_keyboard_focus_image ||= $engine.load_image('images/keyboard-focus-overlay.png')
            @default_keyboard_focus_image.using { yield }
        end
    end

    def gui_render_keyboard_focus
        with_keyboard_focus_image {
            with_color($gui.view_color) {
                unit_square
            }
        }
    end

    def gui_render_placeholder
        with_color(color) {
            unit_square
        }
    end

    def gui_render_background
        if background_image
            with_scale(background_scale_x || 1.0, background_scale_y || 1.0) {
                background_image.using {
                    unit_square
                }
            }
        else
            with_color(background_color) {
                unit_square
            }
        end
    end

    boolean_accessor :exiting
    def exit!
        return if exiting?
        exiting!
        after_exit_animation {
            remove_from_parent!
        }
    end

    def after_exit_animation
        set_opacity(opacity || 1.0).animate({:scale_x => 0.0, :scale_y => 0.0, :opacity => 0.0}, duration=0.2) {
            yield
        }
    end

    def background_color
        if selected?
            if pointer_hovering?
                BACKGROUND_COLOR_SELECTED_AND_HOVERING
            else
                BACKGROUND_COLOR_SELECTED
            end
        elsif pointer_hovering?
            BACKGROUND_COLOR_HOVERING
        else
            BACKGROUND_COLOR
        end
    end

    def click(pointer)
        @parent.click(pointer) if @parent                        # pass it up the heirarchy
    end
    def scroll_up!(pointer)
        @parent.scroll_up!(pointer) if @parent            # pass it up the heirarchy
    end
    def scroll_down!(pointer)
        @parent.scroll_down!(pointer) if @parent        # pass it up the heirarchy
    end

    def begin_drag(pointer)
    end

    def update_drag(pointer)
    end

    def end_drag(pointer)
    end

    def with_gui_object_properties
        with_positioning {
            gui_render_background
            yield
            gui_render_keyboard_focus if keyboard_focus?
            gui_render_keyboard_focus if selected?        # TODO: custom drawing
        }
    end

    def with_positioning
        return if hidden?
        with_translation(@offset_x, @offset_y) {
            with_roll(@roll || 0.0) {
                # Record the scaling we do, so it's possible to undo it when proper aspect ratio is needed (ie text)
                with_env(:gui_scale_x, ($env[:gui_scale_x] || 1.0) * (@scale_x || 1.0)) {
                    with_env(:gui_scale_y, ($env[:gui_scale_y] || 1.0) * (@scale_y || 1.0)) {
                        with_scale(@scale_x || 1.0, @scale_y || 1.0) {
                            with_color(color) {
                                with_multiplied_alpha(@opacity || 1.0) {
                                    yield
                                }
                            }
                        }
                    }
                }
            }
        }
    end

    def remove_from_parent!
        @parent.remove(self) if @parent
    end

    def add_to_root(object)
        return @parent.add_to_root(object) if @parent
        self << object
    end
end