<commit_before>{evaluate_all_animations} = require './animation'
# Logic assumes a frame won't be longer than this
# Below that point, things go slow motion
MAX_FRAME_DURATION = 167  # 6 fps
MAX_TASK_DURATION = MAX_FRAME_DURATION * 0.5

# setImmediate emulation
set_immediate_pending = []

class MainLoop

    constructor: (context)->
        # All in milliseconds
        @frame_duration = 16
        # Time from beginning of a tick to the next (including idle time)
        (@last_frame_durations = new Float32Array(30)).fill?(16)
        # Time it takes for running (logic) JS code
        (@logic_durations = new Float32Array(30)).fill?(16)
        # Time it takes for physics evaluations
        (@physics_durations = new Float32Array(30)).fill?(16)
        # Time it takes for evaluating animations and constraints
        (@animation_durations = new Float32Array(30)).fill?(16)
        # Time it takes for submitting GL commands
        (@render_durations = new Float32Array(30)).fill?(16)
        @_fdi = 0
        @timeout_time = context.MYOU_PARAMS.timeout
        @tasks_per_tick = context.MYOU_PARAMS.tasks_per_tick || 1
        @reset_timeout()
        @last_time = 0
        @enabled = false
        @stopped = true
        @context = context
        @_bound_tick = @tick.bind @
        @_bound_run = @run.bind @
        @_frame_callbacks = []
        @frame_number = 0
        @update_fps = null # assign a function to be called every 30 frames

    run: ->
        @stopped = false
        @enabled = true
        if not @req_tick
            @req_tick = requestAnimationFrame @_bound_tick
        @last_time = performance.now()


    stop: ->
        if @req_tick?
            cancelAnimationFrame @req_tick
            @req_tick = null
        @enabled = false
        @stopped = true

    sleep: (time)->
        if @sleep_timeout_id?
            clearTimeout(@sleep_timeout_id)
            @sleep_timeout_id = null
        if @enabled
            @stop()
        @sleep_timeout_id = setTimeout(@_bound_run, time)

    add_frame_callback: (callback)->
        # Uncomment next line to debug trackebacks involving frame callbacks
        # return callback()
        @_frame_callbacks.push callback

    timeout: (time)->
        if @stopped
            return
        if @timeout_id?
            clearTimeout(@timeout_id)
            @timeout_id = null
        @enabled = true
        @timeout_id = setTimeout((=>@enabled = false), time)

    reset_timeout: =>
        if @timeout_time
            @timeout(@timeout_time)

    tick_once: ->
        if @req_tick?
            cancelAnimationFrame @req_tick
            @tick()
        else
            @tick()
            cancelAnimationFrame @req_tick
            @req_tick = null

    tick: ->
        HMD = @context.vr_screen?.HMD
        if HMD?
            @req_tick = HMD.requestAnimationFrame @_bound_tick
        else
            @req_tick = requestAnimationFrame @_bound_tick
        if set_immediate_pending.length != 0
            for f in set_immediate_pending.splice 0
                f()
        time = performance.now()
        @frame_duration = frame_duration = time - @last_time
        @last_time = time

        task_time = time
        max_task_time = MAX_TASK_DURATION + time
        while (task_time < max_task_time) and (@_frame_callbacks.length != 0)
            @_frame_callbacks.shift()()
            task_time = performance.now()

        if not @enabled
            return
        @last_frame_durations[@_fdi] = frame_duration

        # Limit low speed of logic and physics
        frame_duration = Math.min(frame_duration, MAX_FRAME_DURATION)

        @context.input_manager.update_axes()

        for scene_name in @context.loaded_scenes<commit_msg>Main loop: Add support for generator frame callbacks.<commit_after>{evaluate_all_animations} = require './animation'
# Logic assumes a frame won't be longer than this
# Below that point, things go slow motion
MAX_FRAME_DURATION = 167  # 6 fps
MAX_TASK_DURATION = MAX_FRAME_DURATION * 0.5

# setImmediate emulation
set_immediate_pending = []

class MainLoop

    constructor: (context)->
        # All in milliseconds
        @frame_duration = 16
        # Time from beginning of a tick to the next (including idle time)
        (@last_frame_durations = new Float32Array(30)).fill?(16)
        # Time it takes for running (logic) JS code
        (@logic_durations = new Float32Array(30)).fill?(16)
        # Time it takes for physics evaluations
        (@physics_durations = new Float32Array(30)).fill?(16)
        # Time it takes for evaluating animations and constraints
        (@animation_durations = new Float32Array(30)).fill?(16)
        # Time it takes for submitting GL commands
        (@render_durations = new Float32Array(30)).fill?(16)
        @_fdi = 0
        @timeout_time = context.MYOU_PARAMS.timeout
        @tasks_per_tick = context.MYOU_PARAMS.tasks_per_tick || 1
        @reset_timeout()
        @last_time = 0
        @enabled = false
        @stopped = true
        @context = context
        @_bound_tick = @tick.bind @
        @_bound_run = @run.bind @
        @_frame_callbacks = []
        @frame_number = 0
        @update_fps = null # assign a function to be called every 30 frames

    run: ->
        @stopped = false
        @enabled = true
        if not @req_tick
            @req_tick = requestAnimationFrame @_bound_tick
        @last_time = performance.now()


    stop: ->
        if @req_tick?
            cancelAnimationFrame @req_tick
            @req_tick = null
        @enabled = false
        @stopped = true

    sleep: (time)->
        if @sleep_timeout_id?
            clearTimeout(@sleep_timeout_id)
            @sleep_timeout_id = null
        if @enabled
            @stop()
        @sleep_timeout_id = setTimeout(@_bound_run, time)

    add_frame_callback: (callback)->
        # Uncomment next line to debug trackebacks involving frame callbacks
        # return callback()
        if callback.next?
            # it's a generator instance
            callback = callback.next.bind callback
        @_frame_callbacks.push callback

    timeout: (time)->
        if @stopped
            return
        if @timeout_id?
            clearTimeout(@timeout_id)
            @timeout_id = null
        @enabled = true
        @timeout_id = setTimeout((=>@enabled = false), time)

    reset_timeout: =>
        if @timeout_time
            @timeout(@timeout_time)

    tick_once: ->
        if @req_tick?
            cancelAnimationFrame @req_tick
            @tick()
        else
            @tick()
            cancelAnimationFrame @req_tick
            @req_tick = null

    tick: ->
        HMD = @context.vr_screen?.HMD
        if HMD?
            @req_tick = HMD.requestAnimationFrame @_bound_tick
        else
            @req_tick = requestAnimationFrame @_bound_tick
        if set_immediate_pending.length != 0
            for f in set_immediate_pending.splice 0
                f()
        time = performance.now()
        @frame_duration = frame_duration = time - @last_time
        @last_time = time

        task_time = time
        max_task_time = MAX_TASK_DURATION + time
        while (task_time < max_task_time) and (@_frame_callbacks.length != 0)
            f = @_frame_callbacks.shift()
            ret = f()
            if ret?.done? and ret.done == false
                @_frame_callbacks.push f
            task_time = performance.now()

        if not @enabled
            return
        @last_frame_durations[@_fdi] = frame_duration

        # Limit low speed of logic and physics
        frame_duration = Math.min(frame_duration, MAX_FRAME_DURATION)

        @context.input_manager.update_axes()

        for scene_name in @context.loaded_scenes
{'fraction_non_alphanumeric': 0.08384853168469861, 'fraction_numerical': 0.012107161257083977, 'mean_word_length': 2.0899323517707917, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4002412', 'n_tokens_mistral': 2302, 'n_tokens_neox': 2189, 'n_words': 577}