Virtual Elements
You aren't limited to just GuiObject's for reference areas, you can create custom ones as well using virtual elements.
Virtual elements are for positioning floating element relative to a custom reference area, useful for context menus, range selections, following the cursor, and more.
Example
The most basic virtual element is a plain object that has a getBoundingRect method, which mimics a real element’s AbsoluteSize and AbsolutePosition:
- luau
- roblox-ts
local Aether = require(path.to.aether)
local virtualElement: Aether.VirtualElement = {
getBoundingRect = function()
return {
x = 0,
y = 0,
top = 0,
left = 0,
bottom = 20,
right = 20,
width = 20,
height = 20,
}
end
}
Aether.process(virtualElement, reference)
import { process, type VirtualElement } from "@rbxts/aether";
const virtualElement: VirtualElement = {
getBoundingRect: () => {
return {
x: 0,
y: 0,
top: 0,
left: 0,
bottom: 20,
right: 20,
width: 20,
height: 20,
}
}
}
process(virtualElement, reference)
To better understand the properties and how'd they work for a "real" element:
x-AbsolutePosition.Xy-AbsolutePosition.Ytop-AbsolutePosition.Yleft-AbsolutePosition.Xbottom-AbsolutePosition.Y + AbsoluteSize.Yright-AbsolutePosition.X + AbsoluteSize.Xwidth-AbsoluteSize.Xheight-AbsoluteSize.Y
contextElement
This property is useful if your getBoundingRect method is derived from a real element, to ensure clipping and position update detection works as expected.
- luau
- roblox-ts
local Aether = require(path.to.aether)
local contextElement = Instance.new("Frame")
local virtualElement: Aether.VirtualElement = {
getBoundingRect = function()
return {
x = 0,
y = 0,
top = 0,
left = 0,
bottom = 20,
right = 20,
width = 20,
height = 20,
}
end,
contextElement = contextElement,
}
Aether.process(virtualElement, reference)
import { process, type VirtualElement } from "@rbxts/aether";
const contextElement = new Instance("Frame")
const virtualElement: VirtualElement = {
getBoundingRect: () => {
return {
x: 0,
y: 0,
top: 0,
left: 0,
bottom: 20,
right: 20,
width: 20,
height: 20,
}
},
contextElement,
}
process(virtualElement, reference)
getNativeRects
This property is useful when using range selections and the inline() middleware.
- luau
- roblox-ts
local Aether = require(path.to.aether)
local virtualElement: Aether.VirtualElement = {
getBoundingRect = function()
...
end,
getNativeRects = function()
return {
{ x = 0, y = 0, width = 10, height = 10 },
{ x = 10, y = 0, width = 10, height = 10 },
{ x = 20, y = 0, width = 10, height = 10 }
}
end,
}
Aether.process(virtualElement, reference)
import { process, type VirtualElement } from "@rbxts/aether";
const virtualElement: VirtualElement = {
getBoundingRect: () => ...,
getNativeRects: () => {
return [
{ x: 0, y: 0, width: 10, height: 10 },
{ x: 10, y: 0, width: 10, height: 10 },
{ x: 20, y: 0, width: 10, height: 10 }
]
}
}
process(virtualElement, reference)