Git Product home page Git Product logo

Comments (4)

MichaelBelousov avatar MichaelBelousov commented on August 12, 2024 2

I'm just personally a big fan of strong typing in typescript, and it offers better intellisense/tooling, such as having a type error if you pass arguments that don't correspond to the connected signal. I can look into it and offer a PR and better proof of concept

i.e.

this.get_tree().connect("network_peer_connected", (id: string, otherArg: number) => {}, "other");

that will be a type error because the id argument should be a number, and a string was passed to the otherArg when a number is required.

from ecmascript.

MichaelBelousov avatar MichaelBelousov commented on August 12, 2024

another place that stronger inference would generate useful tooling: although I would need to research if it's even possible.

function rpc_id<T extends {} = {}, MethodKey extends key of T, Method = T[]>(id: number, method: MethodKey, ...args: Parameters<Method>): any;

from ecmascript.

Geequlim avatar Geequlim commented on August 12, 2024

In godot signal just a string constant.
That seems a lot of work to do but gains no difference in JavaScript.

from ecmascript.

jkb0o avatar jkb0o commented on August 12, 2024

This is an interesting and useful suggestion. I was able to implement such a thing for C# using godot4-like signal declaration. For now, I am on the way to implementing this for our project (and it goes much much simpler). There is a code snippet of how this can work in typescript:

// This part should be defined somewhere in the ECMAScript
// The implementation of `emit` and `connect` is omitted to keep things simple
// In real Life each signal instance should keep owenr_id and name (which is set by
// ECMAscript when object instantiating) and bypass connection to singleton proxy Object
// ProxyObject well receive all Godot signals and additional argument bypassed
// by Signal instance - `callback_id` and then calls exact function.

// Godot signal are generated as properties which create instances of Signal
// on demand.
type VarArgs = readonly unknown[];
type Action<T extends VarArgs> = (...args: T) => void; 
class Signal<T extends VarArgs> implements PromiseLike<T> {
    object_id: Number = 0
    name: String = ""

    // showcase
    callbacks:Action<T>[] = []

    public emit(...args: T) {
        // something from real world:
        // godot.instance_from_id(this.instance_id).emit(this.name, ...args)
        

        // just for showcase
        for (const cb of this.callbacks) {
            cb(...args)
        }
    }

    public connect(cb: Action<T>) {
        // real world:
        // let obj = godot.instance_from_id(this.instance_id)
        // let callback_id = Proxy.get_instance().register_callback(cb)
        // obj.connect(this.name, Proxy.get_instance(), "handle_signal", [callback_id])

        // just for showcase
        this.callbacks.push(cb);
    }

    // this is required for awaiting directly for signals
    public then<TResult1 = T>(onfulfilled?: ((value: T) => (PromiseLike<TResult1> | TResult1)) | undefined | null): PromiseLike<TResult1> {
        return new Promise<TResult1>( (resolve, reject) => {
            this.connect((...args: T) => {
                if (typeof onfulfilled === 'function') {
                    resolve(onfulfilled(args))
                } else {
                    // exception?
                    reject("Don't know how to complete without onfulfilled");
                }
            })
        })
    }
}

// the rest part is the usage example
class Obj  /* extends godot.Object */ {

    // @godot.typedsignal - for registering signal nad providing name and owner_id (or maybe generating property)
    pressed: Signal<[]> = new Signal();
    input: Signal<[name: String]> = new Signal();
    selected: Signal<[name: String, age: Number]> = new Signal();

    public async ready() {
        console.log("in ready")
        this.input.connect(this.handle_input) // <= everything typed as excpected
        this.pressed.connect(() => console.log("pressed"))
        this.input.connect((name) => console.log("input", name))
        this.selected.connect((name, age) => console.log("selected", name, age))
        
        // faking signals for showcase
        setTimeout(() => this.pressed.emit(), 100)
        setTimeout(() => this.input.emit("jhj"), 200);
        setTimeout(() => this.selected.emit("vasia", 21), 300);

        console.log("before handle")
        await this.handle()
        console.log("after handle")
    }

    public handle_input(name: String) {
        console.log("Handling input with handle_input method", name)
    }

    public async handle(a: String = "" ) {
        console.log("in handle")
        await this.pressed
        console.log("after pressed")
        let [key] = await this.input; // key is str
        console.log("after input", key)
        let [name, age] = await this.selected; // name is str, age is num
        console.log("after selected", name, age)
    }
}

let n = new Obj()
n.ready()

/* Output:
[LOG]: "in ready" 
[LOG]: "before handle" 
[LOG]: "in handle" 
[LOG]: "pressed" 
[LOG]: "after pressed" 
[LOG]: "Handling input with handle_input method",  "jhj" 
[LOG]: "input",  "jhj" 
[LOG]: "after input",  "jhj" 
[LOG]: "selected",  "vasia",  21 
[LOG]: "after selected",  "vasia",  21 
[LOG]: "after handle" 
*/

This approach has some memory overhead but adding a lot of impact and stability. It is also fully compatible
with Godot API, e.g. I am able to emit a signal from the engine using old good emit_signal and so on.

There is Playground Link

from ecmascript.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.