lighttroupe/luz

View on GitHub
engine/engine.rb

Summary

Maintainability
A
0 mins
Test Coverage
multi_require 'engine/engine_methods_for_user_object', 'director', 'actor', 'curve', 'theme', 'variable', 'event', 'user_object', 'user_object_setting', 'project', 'image', 'actor_shape', 'actor_canvas'

optional_require 'message_bus'

class Engine
    PLUGIN_DIRECTORY_PATH = File.join(Dir.pwd, 'engine', 'plugins')

    attr_accessor :director, :theme, :simulation_speed, :frame_number
    attr_reader :project, :background_color

    #
    # Callbacks
    #
    callback :frame_end
    callback :reload
    callback :user_object_exception

    include Drawing
    include MethodsForUserObject        # engine gets 'em, too.

    require 'engine/engine_project'
    include EngineProject

    require 'engine/engine_time'
    include EngineTime

    require 'engine/engine_beats'
    include EngineBeats

    require 'engine/engine_message_bus'
    include EngineMessageBus

    require 'engine/engine_buttons'
    include EngineButtons

    require 'engine/engine_sliders'
    include EngineSliders

    require 'engine/engine_images'
    include EngineImages

    require 'engine/engine_exceptions'
    include EngineExceptions

    require 'engine/engine_rendering'
    include EngineRendering

    require 'engine/engine_environment'
    include EngineEnvironment

    require 'engine/engine_plugins'
    include EnginePlugins

    require 'engine/engine_file_monitoring'
    include EngineFileMonitoring

    if optional_require 'engine/engine_dmx'
        include EngineDMX
    end

    #
    # Init (happens after $engine variable is set, ie after initialize returns)
    #
    def post_initialize(options = {})
        @frame_number = 0

        init_time
        init_beats

        init_message_bus
        add_message_bus(options[:listen_ip] || MESSAGE_BUS_IP, options[:listen_port] || MESSAGE_BUS_PORT)

        $env = Hash.new
        init_environment

        init_buttons
        init_sliders

        init_project

        set_opengl_defaults
        set_opengl_projection
        set_opengl_view

        # set up the environment
        @frame_number -= 1            # HACK: without counting it
        tick(@last_frame_time)
    end

    def do_frame(time)
        record_frame_time {
            tick(time)
            render(enable_frame_saving=true)
            frame_end_notify
        }
    end

    def reload
        change_count = reload_modified_source_files        # Kernel add-on method
        change_count += load_plugins        # Pick up any new plugins
        reinitialize_user_objects
        reload_notify
        return change_count
    end

    def view_source(object)
        return unless object
        path = object.source_file_path
        command_line(GuiDefault::OPEN_RUBY_FILE_COMMAND, path)
    end

    def command_line(command, arguments='')
        begin
            open("|#{command} #{arguments}")
            return true
        rescue Errno::ENOENT
            $gui.negative_message "Command '#{command}' not found."
        end
        false
    end

private

    def tick(frame_time)
        slider_tick                                # TODO: does this really need to come first?

        @frame_number += 1                # ; printf("Frame: %05d ==================================\n", @frame_number)

        project_pretick                        # NOTE: at this point $env is from previous frame
        update_time(frame_time)
        read_from_message_bus
        update_environment
        resolve_events
        project_tick
        update_beats(frame_time)

        $gui.gui_tick if $gui        # TODO: remove 'if' ($gui is not present at startup)

        @last_frame_time = frame_time
    end

    def resolve_events
        @project.events.each(&:do_value)            # unlike sliders, events would lose "presses" if not updated every frame
    end
end