Toggle menu
Toggle personal menu
Not logged in
Your IP address will be publicly visible if you make any edits.

Action wheel (tutorial): Difference between revisions

From FiguraMC
PenguinEncounter (talk | contribs)
m fix warn
Tag: 2017 source edit
PenguinEncounter (talk | contribs)
m finished the basic example
Tag: 2017 source edit
Line 1: Line 1:
{{Notice/Warning|This page is under construction.}}
{{Notice/Warning|This page is under construction.}}
{{Notice/Warning|content=
<span style="font-size: 1.4rem; font-weight: bolder;">Untested scripts</span><br>
Handle with care.
}}


The Action Wheel is a GUI element added by Figura which allows you to add additional functionality to your avatar.
The Action Wheel is a GUI element added by Figura which allows you to add additional functionality to your avatar.


By default, the action wheel is opened with the <kbd>B</kbd> key. This can be changed in Figura's Settings.
By default, the action wheel is opened by holding down the <kbd>B</kbd> key. This can be changed in Figura's Settings.


The Action Wheel consists of a set of [[Page|Pages]], of which only one can be active at a time.
The Action Wheel consists of a set of [[Page|Pages]], of which only one can be active at a time.
Line 18: Line 13:
* {{type|Action}} for actions.
* {{type|Action}} for actions.


== Example ==
== Basic Example ==
The first step to using the Action Wheel is to create a page to hold the Actions, via <code>[[ActionWheelAPI#newPage|newPage]]</code>.
The first step to using the Action Wheel is to create a page to hold the Actions, via <code>[[ActionWheelAPI#newPage|newPage]]</code>.


Line 34: Line 29:
The message about not having an active page should be gone now, but the page is still empty. Let's add some actions.
The message about not having an active page should be gone now, but the page is still empty. Let's add some actions.


=== Adding actions ===
=== Adding Actions ===


Create a new action by calling <code>[[Page#newAction|newAction]]</code> on a Page, like so:
Create a new action by calling <code>[[Page#newAction|newAction]]</code> on a Page, like so:
Line 43: Line 38:


local action = mainPage:newAction()
local action = mainPage:newAction()
</syntaxhighlight>
Because we haven't set up the visuals, the action is essentially invisible, but you should still be able to hover it with your mouse and have it be highlighted. Let's add some visuals!
{{note|1=
Most methods applying to Actions return the the Action being worked upon. This also applies to quite a few other kinds of object in Figura. In the documentation, this is noted by the presence of the word 'self' in the ''Return Type'' column. Methods that return 'self' are handy because they allow for 'chaining', as demonstrated below.
}}
* <code>[[Action#setTitle|title]]</code>: Set the text displayed when hovering over the action
* <code>[[Action#setItem|item]]</code>: Use an item as the icon to be displayed
* <code>[[Action#setHoverColor|hoverColor]]</code>: Set the background color of the action when it is hovered over, as red/green/blue
<syntaxhighlight lang="lua" line="1" highlight="5-7">
local mainPage = action_wheel:newPage()
action_wheel:setPage(mainPage)
local action = mainPage:newAction()
    :title("My Action") -- displayed when hovering the action
    :item("minecraft:stick") -- action icon
    :hoverColor(1, 0, 1) -- magenta
</syntaxhighlight>
=== Making Actions work ===
Now that you can see the action, it's time to add some functionality to it. It is possible to define behavior for when an action is [[Action#field_leftClick|left-clicked]] and [[Action#field_rightClick|right-clicked]] separately. For this tutorial, we will define a left-click action.
<syntaxhighlight lang="lua" line="1" highlight="8-11">
local mainPage = action_wheel:newPage()
action_wheel:setPage(mainPage)
local action = mainPage:newAction()
    :title("My Action") -- displayed when hovering the action
    :item("minecraft:stick") -- action icon
    :hoverColor(1, 0, 1) -- magenta
    -- this method sets the leftClick field of the Action
    :onLeftClick(function()
        print("Hello, world!")
    end)
</syntaxhighlight>
If you click the Action in your Action Wheel (don't forget to save), it should write "Hello, world!" in your chat.
However, there is a problem with the current code &mdash; its effects won't be seen by other players when playing multiplayer.
=== Making Actions work in multiplayer ===
{{hatnote|For more information, see [[Pings (Tutorial)]].|extraclasses=no-border}}
Due to the nature of Figura, all code is run client-side. Because the Action Wheel is entirely added and controlled by Figura, the Minecraft Server will '''never synchronize it with other clients'''. To fix this problem, we need to utilize Pings to synchronize the actions you take with the Action Wheel.
The first step to this process is to move the code that would normally be executed when you click the Action into a ping function. Next, replace the 'anonymous function' (<code>function()...end</code> block) with the ping function.
{{Notice/Warning|content=
All actions '''must have unique names'''. If you're adding multiple actions, you need to '''use a different name for each action function.''' Otherwise, every Action will run the same function (this is probably not what you want!)
}}
{{note|1=
Choose a function name that describes what the function does. It will help you (and people giving support) understand your code when reading it in the future.
}}
<syntaxhighlight lang="lua" line="1" highlight="4-8,14-15">
local mainPage = action_wheel:newPage()
action_wheel:setPage(mainPage)
-- Create a ping function that does the same thing that the Action did before
-- The function needs to be defined above the code that defines the Action.
function pings.printHelloWorld()
    print("Hello, world!")
end
local action = mainPage:newAction()
    :title("My Action") -- displayed when hovering the action
    :item("minecraft:stick") -- action icon
    :hoverColor(1, 0, 1) -- magenta
    -- Pass the ping function directly to onLeftClick - note that there is no () after 'printHelloWorld'
    :onLeftClick(pings.printHelloWorld)
</syntaxhighlight>
This code correctly synchronizes your actions across clients!
If you need to pass arguments to the function (i.e. sending data only the host knows), you need to do a bit more work.
For this example, we are sending a random number to the function and we want to use Pings so that each client sees the same number (rather than selecting a different random number on each client.)
We need to wrap the call to the ping inside another function:
<syntaxhighlight lang="lua" line="1" highlight="12-14">
local mainPage = action_wheel:newPage()
action_wheel:setPage(mainPage)
function pings.printANumber(a)
    print("the number is ", a)
end
local action = mainPage:newAction()
    :title("My Action") -- displayed when hovering the action
    :item("minecraft:stick") -- action icon
    :hoverColor(1, 0, 1) -- magenta
    :onLeftClick(function()
        pings.printANumber(math.random())
    end)
</syntaxhighlight>
Watch out for this common mistake:
<syntaxhighlight lang="lua">
-- THIS CODE DOES NOT WORK, DON'T DO THIS
-- ... more action stuff ...
    :onLeftClick(pings.printANumber(math.random()))
</syntaxhighlight>
While this may appear to make sense, it actually '''calls the ping function''' and then sets the result as the left-click action. Because ping functions don't return values (effectively, they always return {{type|nil}}) this code removes the left-click action.
=== Full example ===
<syntaxhighlight lang="lua" line="1">
local mainPage = action_wheel:newPage()
action_wheel:setPage(mainPage)
function pings.actionClicked() -- don't forget to change the name if you're re-using this
    print("Hello, world!")
    -- one of the most common things to do is play an animation (like an emote wheel)
    -- you'll need to fill out the path to your Blockbench model and name of the animation to use this
    -- animations["<MODEL PATH HERE>"]["<ANIMATION NAME HERE>"]:play()
end
local action = mainPage:newAction()
    :title("Action name")
    :item("minecraft:stick")
    :hoverColor(1, 0, 1)
    :onLeftClick(pings.actionClicked)
</syntaxhighlight>
</syntaxhighlight>

Revision as of 03:53, 1 December 2024

This page is under construction.

The Action Wheel is a GUI element added by Figura which allows you to add additional functionality to your avatar.

By default, the action wheel is opened by holding down the B key. This can be changed in Figura's Settings.

The Action Wheel consists of a set of Pages, of which only one can be active at a time. Each page can have an unlimited number of Actions. Only 8 Actions can be rendered at a time, however — if more than 8 Actions are active on a page, the scroll wheel can be used to navigate between the sets of Actions (8 at a time.)

For full documentation, see:

  • ActionWheelAPI for the global action_wheel,
  • Page for pages, and
  • Action for actions.

Basic Example

The first step to using the Action Wheel is to create a page to hold the Actions, via newPage.

local mainPage = action_wheel:newPage()

This creates a new page, but doesn't do anything else. If you save the script and try to open the Action Wheel (B), you will see a message stating that there is no active page. Using setPage with the newly created page will change the current active page:

local mainPage = action_wheel:newPage()
action_wheel:setPage(mainPage)

The message about not having an active page should be gone now, but the page is still empty. Let's add some actions.

Adding Actions

Create a new action by calling newAction on a Page, like so:

local mainPage = action_wheel:newPage()
action_wheel:setPage(mainPage)

local action = mainPage:newAction()

Because we haven't set up the visuals, the action is essentially invisible, but you should still be able to hover it with your mouse and have it be highlighted. Let's add some visuals!

ⓘ Note

Most methods applying to Actions return the the Action being worked upon. This also applies to quite a few other kinds of object in Figura. In the documentation, this is noted by the presence of the word 'self' in the Return Type column. Methods that return 'self' are handy because they allow for 'chaining', as demonstrated below.

  • title: Set the text displayed when hovering over the action
  • item: Use an item as the icon to be displayed
  • hoverColor: Set the background color of the action when it is hovered over, as red/green/blue
local mainPage = action_wheel:newPage()
action_wheel:setPage(mainPage)

local action = mainPage:newAction()
    :title("My Action") -- displayed when hovering the action
    :item("minecraft:stick") -- action icon
    :hoverColor(1, 0, 1) -- magenta

Making Actions work

Now that you can see the action, it's time to add some functionality to it. It is possible to define behavior for when an action is left-clicked and right-clicked separately. For this tutorial, we will define a left-click action.

local mainPage = action_wheel:newPage()
action_wheel:setPage(mainPage)

local action = mainPage:newAction()
    :title("My Action") -- displayed when hovering the action
    :item("minecraft:stick") -- action icon
    :hoverColor(1, 0, 1) -- magenta
    -- this method sets the leftClick field of the Action
    :onLeftClick(function()
        print("Hello, world!")
    end)

If you click the Action in your Action Wheel (don't forget to save), it should write "Hello, world!" in your chat. However, there is a problem with the current code — its effects won't be seen by other players when playing multiplayer.

Making Actions work in multiplayer

For more information, see Pings (Tutorial).

Due to the nature of Figura, all code is run client-side. Because the Action Wheel is entirely added and controlled by Figura, the Minecraft Server will never synchronize it with other clients. To fix this problem, we need to utilize Pings to synchronize the actions you take with the Action Wheel.

The first step to this process is to move the code that would normally be executed when you click the Action into a ping function. Next, replace the 'anonymous function' (function()...end block) with the ping function.

All actions must have unique names. If you're adding multiple actions, you need to use a different name for each action function. Otherwise, every Action will run the same function (this is probably not what you want!)

ⓘ Note

Choose a function name that describes what the function does. It will help you (and people giving support) understand your code when reading it in the future.

local mainPage = action_wheel:newPage()
action_wheel:setPage(mainPage)

-- Create a ping function that does the same thing that the Action did before
-- The function needs to be defined above the code that defines the Action.
function pings.printHelloWorld()
    print("Hello, world!")
end

local action = mainPage:newAction()
    :title("My Action") -- displayed when hovering the action
    :item("minecraft:stick") -- action icon
    :hoverColor(1, 0, 1) -- magenta
    -- Pass the ping function directly to onLeftClick - note that there is no () after 'printHelloWorld'
    :onLeftClick(pings.printHelloWorld)

This code correctly synchronizes your actions across clients!

If you need to pass arguments to the function (i.e. sending data only the host knows), you need to do a bit more work. For this example, we are sending a random number to the function and we want to use Pings so that each client sees the same number (rather than selecting a different random number on each client.)

We need to wrap the call to the ping inside another function:

local mainPage = action_wheel:newPage()
action_wheel:setPage(mainPage)

function pings.printANumber(a)
    print("the number is ", a)
end

local action = mainPage:newAction()
    :title("My Action") -- displayed when hovering the action
    :item("minecraft:stick") -- action icon
    :hoverColor(1, 0, 1) -- magenta
    :onLeftClick(function()
        pings.printANumber(math.random())
    end)

Watch out for this common mistake:

-- THIS CODE DOES NOT WORK, DON'T DO THIS
-- ... more action stuff ...
    :onLeftClick(pings.printANumber(math.random()))

While this may appear to make sense, it actually calls the ping function and then sets the result as the left-click action. Because ping functions don't return values (effectively, they always return nil) this code removes the left-click action.

Full example

local mainPage = action_wheel:newPage()
action_wheel:setPage(mainPage)

function pings.actionClicked() -- don't forget to change the name if you're re-using this
    print("Hello, world!")
    -- one of the most common things to do is play an animation (like an emote wheel)
    -- you'll need to fill out the path to your Blockbench model and name of the animation to use this
    -- animations["<MODEL PATH HERE>"]["<ANIMATION NAME HERE>"]:play()
end

local action = mainPage:newAction()
    :title("Action name")
    :item("minecraft:stick")
    :hoverColor(1, 0, 1)
    :onLeftClick(pings.actionClicked)