-
-
Notifications
You must be signed in to change notification settings - Fork 260
Description
Edit bromeon for context:
This is about the GDScript feature @export_tool_button.
Needs #1265, probably.
The proposal is as follows:
Right now, registering tool buttons is rather cumbersome, and they are useful enough to maybe deserve either their own #[godot_api] helper or an easier way to register them through #[export]. The discussed way to register them as of right now (I believe) is: (https://discord.com/channels/723850269347283004/1386974297238667355/1386975313392570478)
#[var(
usage_flags = [EDITOR],
hint = TOOL_BUTTON,
hint_string = "Click me!"
)]
#[init(val = Callable::from_local_fn("tool button", |_| { godot_print!("hello world!"); Ok(Variant::nil())}))]
editor_button_fn: Callable,This the proposal for a helper in #[godot_api] would be one of the following:
#[tool_button(text = "", icon = "")]#[tool_button("", icon = "")]#[tool_button("", icon(""))]
I believe the first one to be the most sound though. If no text is specified, defaults to the function identifier, so if it is name_func it would result in Name Func. The icon defaults to Callable.
Another necessity for this API's soundness is the registration order. Since this is an export only API, it is highly important the order is consistent. Allowing to register it in secondary impl blocks, most probably means the order is indeterministic, so we should probably add the following:
#[tool_button(text = "", icon = "", index = 1)]
All tool buttons by default register at the top of the exported properties (or that's the idea), and in case no index is assigned, 0 is assumed. If registered in the same impl block, a subindex is assigned for order of writing, and then all tool buttons are sorted in place with index first and subindex second (maybe not necessary if using an sorting algorithm that maintains insertion order of two equally important items). If there are two tool buttons with index and subindex equal, their order is not determined.
Besides that, there is one other nifty thing we can do, which is to allow the registration of a PhantomVar<Callable>. In that such case, there is no confusion with the actual ordering, so that solves all the above problems, and allows for custom placement. I would suggest for this API to be #[export(tool_button)] (the function with the same name as the field) or #[export(tool_button = ident)] (the function the identifier points to) or #[export(tool_button = expr)] (where expr evaluates to impl Fn() or impl Fn(&Self) or impl Fn(&mut Self)). This would generate a getter that turns the function into a non-thread-safe local function Callable, maybe we can make it thread-safe and add #[tool_button(thread_safe)] for functions?
For the original way to register tool buttons, we could simply check if the property is either Callable or PhantomVar<Callable>, and if it's Callable just let the person assign it in init.
Another option is to just get rid of tool_button and make it as #[export(tool_button(text = "", icon = "", function = ident/expr))], and differentiate between PhantomVar<Callable> and Callable, having function only accessible for PhantomVar.