<commit_before>package luxe;

import Luxe.Ev;
import luxe.Core;
import luxe.Vector;
import snow.api.Timer;

#if deflect
    import luxe.physics.deflect.PhysicsDeflect;
#end //deflect

#if nape
    import luxe.physics.nape.PhysicsNape;
#end //nape


class Physics {


    #if deflect
        public var deflect : PhysicsDeflect;
    #end //deflect

    #if nape
        public var nape : PhysicsNape;
    #end //nape

    public var core : Core;
    public var engines : Array<PhysicsEngine>;

        //how often to update
    public var step_rate (default,set) : Float = 1/60;
        //how much is a single step. This is set from step_rate initially, but can be changed manually
    public var step_delta : Float = 1/60;

//Physics fixed updates
    @:noCompletion public var timer : Timer;

    public function new( _core:Core ) {

        core = _core;

    } //new

    public function init() {

        engines = [];

        #if deflect
            deflect = add_engine(PhysicsDeflect);
        #end //deflect

        #if nape
            nape = add_engine(PhysicsNape);
        #end //nape

    } //init

    public function reset() {

            //stop any existing loop
        if(timer != null) {
            timer.stop();
            timer = null;
        }

        if(step_rate != 0) {

                //Start the physics update loop
            timer = Luxe.timer.schedule( step_rate, fixed_update, true );

        } //only if there is a step rate

    } //reset

    static var tag_physics : String = 'physics';

        //called by the timer at a fixed rate
    function fixed_update() {

            #if !luxe_noprofile Luxe.debug.start(tag_physics); #end

        update();

            #if !luxe_noprofile Luxe.debug.end(tag_physics); #end

    } //fixed_update

        /** Add a physics engine type to be run by this class. */
    public function add_engine<T1,T2>( type:Class<T1>, ?_data:T2 ) : T1 {

        var _engine_instance = Type.createInstance( type, [ _data ] );
        var _physics_engine : PhysicsEngine = cast _engine_instance;

            //start with init
        _physics_engine.init();

            //push the engine into the list to be updated
        engines.push( _physics_engine );

            //return typed instance
        return _engine_instance;

    } //add_engine

        /** Only call this manually if step_rate is 0! */
    public function update() {
        for(engine in engines) {
            engine.update();
        }
    }

    public function process() {
        for(engine in engines) {
            engine.process();
        }
    } //process

    public function render() {
        for(engine in engines) {
            engine.render();
        }
    } //render

    public function destroy() {

        if(timer != null) {
            timer.stop();
        }

        timer = null;

        for(engine in engines) {
            engine.destroy();
        }

    } //destroy

        //on changing the fixed rate, update the physics timer
    function set_step_rate( _rate:Float ) {

            //update the step size
        step_rate = _rate;
        step_delta = step_rate;

            //reset the timer so it runs at the new rate
        reset();

        return step_rate;

    } //set_step_rate


} //Physics



    //base class for simple physics world
    //updates and access
class PhysicsEngine {

    public var name : String = 'engine';
<commit_msg>Physics; add events; pre/post world step/fixed update events for modifying physics properties in lockstep with the physics world, and reading them back immediately after each step (via @bfod)<commit_after>package luxe;

import Luxe.Ev;
import luxe.Core;
import luxe.Vector;
import snow.api.Timer;

#if deflect
    import luxe.physics.deflect.PhysicsDeflect;
#end //deflect

#if nape
    import luxe.physics.nape.PhysicsNape;
#end //nape


class Physics {


    #if deflect
        public var deflect : PhysicsDeflect;
    #end //deflect

    #if nape
        public var nape : PhysicsNape;
    #end //nape

    public var core : Core;
    public var engines : Array<PhysicsEngine>;

        //how often to update
    public var step_rate (default,set) : Float = 1/60;
        //how much is a single step. This is set from step_rate initially, but can be changed manually
    public var step_delta : Float = 1/60;

//Physics fixed updates
    @:noCompletion public var timer : Timer;

    var emitter : luxe.Emitter<PhysicsEvent>;

    public function new( _core:Core ) {

        core = _core;
        emitter = new Emitter();

    } //new

    public function init() {

        engines = [];

        #if deflect
            deflect = add_engine(PhysicsDeflect);
        #end //deflect

        #if nape
            nape = add_engine(PhysicsNape);
        #end //nape

    } //init

    public function reset() {

            //stop any existing loop
        if(timer != null) {
            timer.stop();
            timer = null;
        }

        if(step_rate != 0) {

                //Start the physics update loop
            timer = Luxe.timer.schedule( step_rate, fixed_update, true );

        } //only if there is a step rate

    } //reset

    static var tag_physics : String = 'physics';

        //called by the timer at a fixed rate
    function fixed_update() {

            #if !luxe_noprofile Luxe.debug.start(tag_physics); #end

            //calculated because the values will change
        emit(ph_fixed_update, step_delta * Luxe.timescale);

        update();

        emit(ph_fixed_update_post, step_delta * Luxe.timescale);

            #if !luxe_noprofile Luxe.debug.end(tag_physics); #end

    } //fixed_update

        /** Add a physics engine type to be run by this class. */
    public function add_engine<T1,T2>( type:Class<T1>, ?_data:T2 ) : T1 {

        var _engine_instance = Type.createInstance( type, [ _data ] );
        var _physics_engine : PhysicsEngine = cast _engine_instance;

            //start with init
        _physics_engine.init();

            //push the engine into the list to be updated
        engines.push( _physics_engine );

            //return typed instance
        return _engine_instance;

    } //add_engine

        /** Only call this manually if step_rate is 0! */
    public function update() {
        for(engine in engines) {
            engine.update();
        }
    }

    public function process() {
        for(engine in engines) {
            engine.process();
        }
    } //process

    public function render() {
        for(engine in engines) {
            engine.render();
        }
    } //render

    public function destroy() {

        if(timer != null) {
            timer.stop();
        }

        timer = null;

        for(engine in engines) {
            engine.destroy();
        }

    } //destroy

//Events

    public inline function on(_event:PhysicsEvent, _handler:Float->Void) : Void {
        emitter.on(_event, _handler);
    }
    
    public inline function off(_event:PhysicsEvent, _handler:Float->Void) : Bool {
        return emitter.off(_event, _handler);
    }
    
    public inline function emit(_event:PhysicsEvent, _float:Float) : Void {
        emitter.emit(_event, _float);
    }

//Internal

        //on changing the fixed rate, update the physics timer
    function set_step_rate( _rate:Float ) {

            //update the step size
        step_rate = _rate;
        step_delta = step_rate;

            //reset the timer so it runs at the new rate
        reset();

        return step_rate;

    } //set_step_rate


} //Physics


/** :todo:WIP: This api is work in progress, and might change a bit */
@:enum abstract PhysicsEvent(Int) from Int to Int {

        /** An unknown physics engine event */
    var ph_unknown           = 0;
        /** Emitted at the start of the fixed update, before the world is updated */
    var ph_fixed_update      = 1;
        /** Emitted at the end of the fixed update, after the world is updated */
    var ph_fixed_update_post = 2;

} //PhysicsEvent

    //base class for simple physics world
    //updates and access
class PhysicsEngine {

    public var name : String = 'engine';

{'fraction_non_alphanumeric': 0.09543619234063379, 'fraction_numerical': 0.0035482686895876667, 'mean_word_length': 1.9234620886981402, 'pattern_counts': {'":': 0, '<': 10, '<?xml version=': 0, '>': 12, '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': '5647700', 'n_tokens_mistral': 2459, 'n_tokens_neox': 2301, 'n_words': 756}