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

Allow user to click on the level where they want to place a new entity instead of just placing it at the origin #20

Closed
idanarye opened this issue Apr 13, 2023 · 5 comments
Labels
enhancement New feature or request

Comments

@idanarye
Copy link
Owner

Currently, when adding a new entity in the editor, all the YoleckComponents are initialized to their default value. For the position component, this usually means the origin. This can get a bit cumbersome:

  1. You can't put anything at the level origin, because then when you add new entities they'll appear in the same place.
  2. If you edit the level too far away from the origin, you have to scroll to the origin every time you want to add something.

It could be nice if instead of just spawning the thing at the origin, the user would click in the world space where they want to place the new entity.

Note that because there is no position in Yoleck's core (it's part of Vpeol), this will have to be user-customizable. On the plus size this could mean that the same mechanism can be used for other initializations.

@idanarye idanarye added the enhancement New feature or request label Apr 13, 2023
@idanarye
Copy link
Owner Author

The idea - just like we have edit systems and populate systems, we should also have initialize systems for initializing entities.

Initialize systems are similar to edit systems: they use YoleckEdit to edit the new entity and potentially YoleckUi to use egui, and they are stored in a vector that maintains a deterministic order.

Unlike edit systems, only one initialize system is active at any given time. This allows the initialize system to take control over the entire input. The initialize system must return a value - probably an enum, but maybe an Option will work better because it'd allow easily exit with ? instead of the usual let...else (then again, maybe it's better to force a let...else for conformity?). Once the initialize system returns a value that indicates it is done, the next initialize system will be active. Once all the initialize systems finish, the editor/entity goes back to edit mode and once again runs edit systems.

@idanarye
Copy link
Owner Author

Something like this:

fn vpeol_2d_initialize_position(
    mut edit: YoleckEdit<&mut Vpeol2dPosition>,
    mut cameras_query: Query<&VpeolCameraState>,
    buttons: Res<Input<MouseButton>>,
) -> Option<YoleckInitialize> {
    let mut position = edit.get_single_mut().ok()?;

    // I think `cursor_ray` is `None` if the cursor is inside the egui window, but if it isn't I
    // should probably make it so it does. That would mean clicking inside the egui window should
    // not be considered as clicking to set the position.
    let cursor_position = camera_state
        .iter()
        .find_map(|camera_state| camera_state.cursor_ray)?;
    position.0 = cursor_position.origin.truncate();

    if buttons.just_released(MouseButton::Left) {
        Some(YoleckInitialize::Done)
    } else {
        None
    }
}

@idanarye
Copy link
Owner Author

Note that there are still default values - we just immediately start to edit them.

@idanarye
Copy link
Owner Author

Not sure if the next initialize system should start in the exact same frame. I worry that buttons.just_released will also be true in the next initialize system if I do that, but if each initialize system has its own frame it'll cause a delay when some of them are skipped.

Maybe a good heuristic is that if an initialize system returns None on the first frame it runs, the next one can run in the same frame.

@idanarye
Copy link
Owner Author

idanarye commented Jun 6, 2023

Actually, maybe returning an Option is not a good idea? In the example I've naturally written I used None both for "no editable entity with a position" and for "the button was not just released", but one of them would mean "just skip this system" while the other would mean "keep running this system".

I should probably just use an explicit enum with all three directives (keep running this, continue to the next, abort)

Actually, do I need abort? Maybe abort should be done externally (e.g. - always done when the user hits Escape) instead of controlled by these systems?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant