Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Input signletone returns incorrent instance pointer #767

Closed
snatvb opened this issue Jun 15, 2024 · 9 comments
Closed

Input signletone returns incorrent instance pointer #767

snatvb opened this issue Jun 15, 2024 · 9 comments
Labels
question Not a problem with the library, but a question regarding usage. status: upstream Depending on upstream fix (typically Godot)

Comments

@snatvb
Copy link

snatvb commented Jun 15, 2024

Hello 👋
I've found defferent behaviour when you use Input and InputMap with tool annotation and without.
So if you will use such:

#[derive(GodotClass)]
#[class(init, base=Node)]
struct InputTest2 {
    base: Base<Node>,
}

#[godot_api]
impl INode for InputTest2 {
    fn ready(&mut self) {
        godot_print!("======== START Rust Test[2] ========");
        let mut input_map = InputMap::singleton();
        let actions = input_map.get_actions();
        for index in 0..actions.len() {
            let action = actions.at(index);
            godot_print!("Action: {:?}", action);
        }
        godot_print!("======== END Rust Test[2] ========");
    }

    fn physics_process(&mut self, _delta: f64) {
        let input = Input::singleton();
        let direction = input.get_vector(
            "move_left".into(),
            "move_right".into(),
            "move_down".into(),
            "move_up".into(),
        );

        godot_print!("Direction: {:?}", direction);
    }
}

It works fine. But if you add tool:

#[derive(GodotClass)]
#[class(init, tool, base=Node)]
struct InputTest {
    base: Base<Node>,
}

#[godot_api]
impl INode for InputTest {
    fn ready(&mut self) {
        godot_print!("======== START Rust Test ========");
        let mut input_map = InputMap::singleton();
        let actions = input_map.get_actions();
        for index in 0..actions.len() {
            let action = actions.at(index);
            godot_print!("Action: {:?}", action);
        }
        godot_print!("======== END Rust Test ========");
    }

    fn physics_process(&mut self, _delta: f64) {
        let input = Input::singleton();
        let direction = input.get_vector(
            "move_left".into(),
            "move_right".into(),
            "move_down".into(),
            "move_up".into(),
        );

        godot_print!("Direction: {:?}", direction);
    }
}

then you get incorrect action list and physics_process spam with error, that these actions are not defined:

  The InputMap action "move_down" doesn't exist. Did you mean "ui_down"?
  The InputMap action "move_right" doesn't exist. Did you mean "ui_right"?
  The InputMap action "move_left" doesn't exist. Did you mean "ui_left"?
  The InputMap action "move_right" doesn't exist. Did you mean "ui_right"?
  The InputMap action "move_left" doesn't exist. Did you mean "ui_left"?
  The InputMap action "move_up" doesn't exist. Did you mean "ui_up"?
  The InputMap action "move_down" doesn't exist. Did you mean "ui_down"?
  The InputMap action "move_up" doesn't exist. Did you mean "ui_up"?
  The InputMap action "move_down" doesn't exist. Did you mean "ui_down"?
  The InputMap action "move_right" doesn't exist. Did you mean "ui_right"?
  The InputMap action "move_left" doesn't exist. Did you mean "ui_left"?
  The InputMap action "move_right" doesn't exist. Did you mean "ui_right"?
  The InputMap action "move_left" doesn't exist. Did you mean "ui_left"?
  The InputMap action "move_up" doesn't exist. Did you mean "ui_up"?
  The InputMap action "move_down" doesn't exist. Did you mean "ui_down"?

Of course it's not true. Seems it's UB.

I've attach reprocase. There is two scenes: main - that works correctly, and corrupted that contains this issue.
godot_reprocase.zip

@Bromeon
Copy link
Member

Bromeon commented Jun 16, 2024

I don't think Godot supports this directly.

From InputMap.action_get_events() docs:

Note: When used in the editor (e.g. a tool script or EditorPlugin), this method will return events for the editor action. If you want to access your project's input binds from the editor, read the input/* settings from ProjectSettings.

@snatvb
Copy link
Author

snatvb commented Jun 16, 2024

@Bromeon so, then it gives two different inputs for tool and non-tool, right? I just use this annotation to show warnings on node. As I get it's not correct way. Then maybe you know how to do it better?

@Bromeon
Copy link
Member

Bromeon commented Jun 16, 2024

I don't know about it, but I don't think this behavior is specific to Rust. I would recommend asking on the Godot forum or the Contributors chat.

There's probably not much we can do on godot-rust side, as such I'll close this. Feel free to continue the discussion and share findings though! 🙂

@Bromeon Bromeon closed this as not planned Won't fix, can't repro, duplicate, stale Jun 16, 2024
@Bromeon Bromeon added status: upstream Depending on upstream fix (typically Godot) question Not a problem with the library, but a question regarding usage. labels Jun 16, 2024
@snatvb
Copy link
Author

snatvb commented Jun 16, 2024

@tool
extends Node

func _ready():
    var actions = InputMap.get_actions()
  
    print("====== gd start ======")

    for action in actions:
        print("Action: ", action)
    
    print("====== gd end ======")

it shows actions correctly, not like Rust version

@snatvb
Copy link
Author

snatvb commented Jun 16, 2024

So, my research has been leaded me to next one:
We have two Input and InputMap signletones - one in editor, one in play mode.
physics_process also executes in editor for extenstions. You need to check, that your code invokes not in editor. For this you need to use Engine::singleton().is_editor_hint().

For example:

    fn physics_process(&mut self, delta: f64) {
        if Engine::singleton().is_editor_hint() {
            return;
        }
        let input = Input::singleton();
        let direction = input.get_vector(
            "move_left".into(),
            "move_right".into(),
            "move_down".into(),
            "move_up".into(),
        );
        if direction.is_zero() {
            return;
        }
        godot_print!("Direction: {:?}", direction.normalized());
    }

With this checker, you can control where is your code will be executed.

@Bromeon
Copy link
Member

Bromeon commented Jun 16, 2024

GDExtension editor plugins work differently from GDScript ones.

Additionally, in godot-rust we have changed the way how #[class(tool)] works for Godot 4.3. Can you see if you experience a difference between Godot 4.2 and 4.3-dev?

@snatvb
Copy link
Author

snatvb commented Jun 16, 2024

I haven't check 4.3 yet, my project on 4.2

@0x53A
Copy link
Contributor

0x53A commented Nov 3, 2024

I hit the same issue and found a solution:

InputMap.load_from_project_settings()

full credit to https://www.reddit.com/r/godot/comments/194l8dc/comment/khgv4hw/

@Bromeon
Copy link
Member

Bromeon commented Nov 3, 2024

Related: #132 (comment) 🙂

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Not a problem with the library, but a question regarding usage. status: upstream Depending on upstream fix (typically Godot)
Projects
None yet
Development

No branches or pull requests

3 participants