Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 19 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@

The [RGX-Framework](https://github.com/DonnieDice/RGX-Framework) reference addon **and** its in-game testing suite, in one install. It exists for two audiences at once:

> This source branch targets the unreleased `v1.3.0` candidate and requires the
> RGX-Framework `v2.7.0` candidate. The latest published pair remains RGX-Hello
> `v1.2.1` with RGX-Framework `v2.6.2`.

- **Addon developers** — `data/core.lua` is the canonical "hello world": the smallest complete RGX addon, written in the declarative `RGXAddon` style you should copy when starting your own.
- **Framework development** — `data/visualtest.lua` is the visual QA harness used to test RGX-Framework's features in-game before releases. As the framework grows, this suite grows with it; the goal is coverage of **every** framework feature.

## Built with rgx-mcp
## Source Contract Conformance

RGX-Framework temporarily maintains an MCP server at `tools/rgx-mcp/` as a source-tree contract-conformance fixture. It is excluded from the published Framework addon; public API/MCP/editor tooling belongs to RGX Studio. RGX-Hello remains wired into the transition fixture in both directions:
RGX-Framework temporarily maintains an MCP transport at `tools/rgx-mcp/` as a private source-tree contract-conformance fixture. It is not part of the framework runtime or its published addon; public API/MCP/editor tooling belongs to the later RGX Studio product. RGX-Hello remains wired into the fixture in both directions:

- `rgx_generate_addon` can reproduce `data/core.lua`'s structure from a short spec — the hand-written file and the generator's output are kept convergent.
- The framework's end-to-end test (`tools/rgx-mcp/test/test-rgx-hello.mjs`) runs the real MCP server against **this repo**: it validates `core.lua`'s opts table against the schema and audits every Lua file here for unsafe patterns. If this repo drifts from the contract, the framework's own test fails.
Expand All @@ -27,6 +31,15 @@ RGXAddon "RGX-Hello" {
volume = 50,
},

every = {
heartbeat = { 1, function(self, timer)
self.heartbeatTicks = (self.heartbeatTicks or 0) + 1
if self.heartbeatTicks >= 3 then
self:CancelTimer(timer)
end
end },
},

options = {
General = {
{ toggle = "enabled", label = "Enable Addon" },
Expand All @@ -36,20 +49,13 @@ RGXAddon "RGX-Hello" {

onInit = function(self)
self:Print("Hello from RGX-Hello!")
self.heartbeatTimer = self:Every(1, function(timer)
self.heartbeatTicks = (self.heartbeatTicks or 0) + 1
if self.heartbeatTicks >= 3 then
self:CancelTimer(timer)
self.heartbeatTimer = nil
end
end, "RGX-Hello:heartbeat")
end,

welcome = "loaded -- /rgxhello for options",
}
```

That single call gives you saved settings with automatic persistence, a tabbed options panel with db-bound controls, a slash command, a minimap button, branded chat output, and framework-scoped startup/timer logic. No event frames, no `C_Timer`, no `SLASH_X` globals, no SavedVariables boilerplate.
That single call gives you saved settings with automatic persistence, a tabbed options panel with db-bound controls, a named repeating timer, a slash command, a minimap button, branded chat output, and framework-scoped startup logic. No event frames, no `C_Timer`, no `SLASH_X` globals, no SavedVariables boilerplate.

## The Testing Suite (`data/visualtest.lua`)

Expand All @@ -73,21 +79,21 @@ Current coverage:
| Auras | `RGXAuras` — `IterateAuras` scan, `WatchUnit` + `OnApplied`/`OnRemoved` live log with unsubscribe |
| Minimap | `RGXMinimap` — `MM:Create` (icon, tooltip, drag, persistent angle), `Toggle`/`IsShown` |
| Design | `RGX:Font` one-call styling, `RGXDesign` `CreateButton`/`CreateSectionHeader`/`CreateDivider`, theme tokens |
| System | reference-addon heartbeat via `addon:Every`, `RGX:After`, `RGX:Every`, `RGX:CancelTimer` |
| System | declarative `every.heartbeat` self-cancellation, `RGX:After`, `RGX:Every`, `RGX:CancelTimer` |

Sound is intentionally untested here — the sound module is a per-addon registry that [BLU](https://github.com/DonnieDice/BLU) exercises in production, which is a more honest test than a synthetic registration. Standing pattern: when a framework module ships or changes, its test tab lands here in the same cycle.

## Installation

1. Install [RGX-Framework](https://github.com/DonnieDice/RGX-Framework) (required dependency, v2.4.1+).
1. Install [RGX-Framework](https://github.com/DonnieDice/RGX-Framework) (required dependency, v2.7.0+).
2. Copy the `RGX-Hello` folder to `World of Warcraft\_retail_\Interface\AddOns\`.
3. `/reload` or restart, and enable both addons.

## Using This As a Template

1. Copy the repo; rename the folder, `RGX-Hello.toc`, and `RGX-Hello.xml` to your addon's name.
2. Edit the TOC header (`Title`, `Notes`, `Author`, `SavedVariables`).
3. Edit the `RGXAddon "..." { }` call in `data/core.lua` — `db` for settings, `options` for the panel, `on` for triggers, and `every` for repeating work.
3. Edit the `RGXAddon "..." { }` call in `data/core.lua` — `db` for settings, `options` for the panel, `every` for repeating work, and `onInit` for event/setup code while declarative `on` remains Tier 4.
4. Delete `data/visualtest.lua` (and its TOC/XML lines) — it tests the framework, not your addon.
5. Replace `media/icon.tga`, or drop the `minimap` key.

Expand Down
4 changes: 2 additions & 2 deletions RGX-Hello.toc
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
## Interface: 120100
## Version: 1.2.1
## Version: 1.3.0
## Title: RGX-Hello
## Notes: The smallest complete RGX-Framework addon -- a reference/template for building on RGX, plus its visual QA harness (/rgxvisual, /rgxcolor).
## Author: DonnieDice
## Category: RGX
## Group: RGX
## RequiredDeps: RGX-Framework
## X-RGX-Framework-MinVersion: 2.6.0
## X-RGX-Framework-MinVersion: 2.7.0
## SavedVariables: RGXHelloDB, RGXVisualTestDB
## IconTexture: Interface\AddOns\RGX-Framework\media\logo.tga

Expand Down
4 changes: 2 additions & 2 deletions RGX-Hello_Cata.toc
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
## Interface: 40402
## Version: 1.2.1
## Version: 1.3.0
## Title: RGX-Hello
## Notes: RGX-Framework reference and compatibility test addon
## Author: DonnieDice
## Category: RGX
## Group: RGX
## RequiredDeps: RGX-Framework
## X-RGX-Framework-MinVersion: 2.6.0
## X-RGX-Framework-MinVersion: 2.7.0
## SavedVariables: RGXHelloDB, RGXVisualTestDB
## IconTexture: Interface\AddOns\RGX-Framework\media\logo.tga

Expand Down
4 changes: 2 additions & 2 deletions RGX-Hello_Mists.toc
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
## Interface: 50504
## Version: 1.2.1
## Version: 1.3.0
## Title: RGX-Hello
## Notes: RGX-Framework reference and compatibility test addon
## Author: DonnieDice
## Category: RGX
## Group: RGX
## RequiredDeps: RGX-Framework
## X-RGX-Framework-MinVersion: 2.6.0
## X-RGX-Framework-MinVersion: 2.7.0
## SavedVariables: RGXHelloDB, RGXVisualTestDB
## IconTexture: Interface\AddOns\RGX-Framework\media\logo.tga

Expand Down
4 changes: 2 additions & 2 deletions RGX-Hello_TBC.toc
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
## Interface: 20506
## Version: 1.2.1
## Version: 1.3.0
## Title: RGX-Hello
## Notes: RGX-Framework reference and compatibility test addon
## Author: DonnieDice
## Category: RGX
## Group: RGX
## RequiredDeps: RGX-Framework
## X-RGX-Framework-MinVersion: 2.6.0
## X-RGX-Framework-MinVersion: 2.7.0
## SavedVariables: RGXHelloDB, RGXVisualTestDB
## IconTexture: Interface\AddOns\RGX-Framework\media\logo.tga

Expand Down
4 changes: 2 additions & 2 deletions RGX-Hello_Vanilla.toc
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
## Interface: 11509
## Version: 1.2.1
## Version: 1.3.0
## Title: RGX-Hello
## Notes: RGX-Framework reference and compatibility test addon
## Author: DonnieDice
## Category: RGX
## Group: RGX
## RequiredDeps: RGX-Framework
## X-RGX-Framework-MinVersion: 2.6.0
## X-RGX-Framework-MinVersion: 2.7.0
## SavedVariables: RGXHelloDB, RGXVisualTestDB
## IconTexture: Interface\AddOns\RGX-Framework\media\logo.tga

Expand Down
4 changes: 2 additions & 2 deletions RGX-Hello_Wrath.toc
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
## Interface: 38002
## Version: 1.2.1
## Version: 1.3.0
## Title: RGX-Hello
## Notes: RGX-Framework reference and compatibility test addon
## Author: DonnieDice
## Category: RGX
## Group: RGX
## RequiredDeps: RGX-Framework
## X-RGX-Framework-MinVersion: 2.6.0
## X-RGX-Framework-MinVersion: 2.7.0
## SavedVariables: RGXHelloDB, RGXVisualTestDB
## IconTexture: Interface\AddOns\RGX-Framework\media\logo.tga

Expand Down
18 changes: 10 additions & 8 deletions data/core.lua
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
-- - a minimap button (minimap)
-- - branded chat output (welcome, self:Print)
-- - startup and repeating timer logic routed through RGX paths -- never a
-- manual event frame or C_Timer (onInit, self:Every)
-- manual event frame or C_Timer (onInit, declarative every)
--=====================================================================================

RGXAddon "RGX-Hello" {
Expand All @@ -27,6 +27,15 @@ RGXAddon "RGX-Hello" {
volume = 50,
},

every = {
heartbeat = { 1, function(self, timer)
self.heartbeatTicks = (self.heartbeatTicks or 0) + 1
if self.heartbeatTicks >= 3 then
self:CancelTimer(timer)
end
end },
},

options = {
General = {
{ toggle = "enabled", label = "Enable Addon" },
Expand All @@ -36,13 +45,6 @@ RGXAddon "RGX-Hello" {

onInit = function(self)
self:Print("Hello from RGX-Hello!")
self.heartbeatTimer = self:Every(1, function(timer)
self.heartbeatTicks = (self.heartbeatTicks or 0) + 1
if self.heartbeatTicks >= 3 then
self:CancelTimer(timer)
self.heartbeatTimer = nil
end
end, "RGX-Hello:heartbeat")
end,

welcome = "loaded -- /rgxhello for options",
Expand Down
13 changes: 7 additions & 6 deletions data/visualtest.lua
Original file line number Diff line number Diff line change
Expand Up @@ -590,27 +590,28 @@ local function BuildSystemTab(frame)
local add = Place(frame)

add(UI:CreateLabel(frame, {
text = "Timers Visual Test (RGX:After / RGX:Every)",
text = "Timers Visual Test (declarative every / RGX:After / RGX:Every)",
size = "large",
color = "accent",
}))

local referenceAddon = R:GetAddon("RGX-Hello")
local heartbeatLabel = UI:CreateLabel(frame, {
text = "Reference addon heartbeat: not checked",
text = "Declarative every.heartbeat: not checked",
size = "small",
color = "normal",
width = 340,
})
local function RefreshHeartbeatStatus()
local ticks = referenceAddon and referenceAddon.heartbeatTicks or 0
heartbeatLabel:SetText("Reference addon heartbeat: " .. ticks .. "/3 ticks"
.. (ticks == 3 and " (self-cancelled: PASS)" or " (wait and check again)"))
local result = ticks == 3 and " (self-cancelled: PASS)"
or (ticks > 3 and " (FAILED: timer did not stop)" or " (wait and check again)")
heartbeatLabel:SetText("Declarative every.heartbeat: " .. ticks .. "/3 ticks" .. result)
end
RefreshHeartbeatStatus()
add(heartbeatLabel)

local heartbeatBtn = UI:CreateButton(frame, "Check reference heartbeat", 200, 26)
local heartbeatBtn = UI:CreateButton(frame, "Check declarative heartbeat", 210, 26)
heartbeatBtn:SetScript("OnClick", RefreshHeartbeatStatus)
add(heartbeatBtn, 12)

Expand Down Expand Up @@ -645,7 +646,7 @@ local function BuildSystemTab(frame)
add(tickLabel, 16)

add(UI:CreateLabel(frame, {
text = "What to test: the reference addon's scoped heartbeat reaches 3 and self-cancels; After fires exactly once ~2s after the click; imperative Every increments the counter each second; Stop must freeze it immediately (CancelTimer). Sound is intentionally not tested here -- BLU exercises the sound registry in production.",
text = "What to test: declarative every.heartbeat reaches exactly 3 and self-cancels. Wait at least 5 more seconds, click Check again, and confirm it remains 3. After fires exactly once ~2s after the click; imperative Every increments each second; Stop freezes it immediately (CancelTimer). Sound is intentionally not tested here -- BLU exercises the sound registry in production.",
size = "small",
color = "muted",
width = 340,
Expand Down
21 changes: 16 additions & 5 deletions docs/CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,22 @@

## Current Development

- The canonical addon uses the shipped `onInit` and `addon:Every` APIs for its
three-tick heartbeat while declarative `on`/`every` remain future forms.
- The System tab displays the heartbeat result for in-game timer verification.
- Updated MCP distribution wording: Node tooling is maintained with the
framework source but excluded from the WoW player archive.
### [v1.3.0](changelogs/1.3.0.md) (Expected)

- Moved the reference heartbeat from imperative `addon:Every` setup into
`every.heartbeat`, exercising Framework v2.7.0's shipped named timer contract.
- Added explicit in-game verification that the timer reaches 3 ticks,
self-cancels, and remains at 3.
- Raised the minimum Framework version to 2.7.0 across all six flavor TOCs.

## Current Release

### [v1.2.1](changelogs/1.2.1.md) - 2026-08-13

- Replaced premature declarative `on`/`every` usage with shipped imperative
APIs until the named timer vertical slice could be rebuilt cleanly.
- Preserved the three-tick heartbeat and corrected Framework/MCP distribution
wording and Retail metadata.

## [v1.2.0](changelogs/1.2.0.md) - 2026-07-04

Expand Down
11 changes: 11 additions & 0 deletions docs/changelogs/1.3.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# RGX-Hello 1.3.0

Status: unreleased source candidate pending RGX-Framework 2.7.0 and the required
in-game heartbeat validation.

- Requires RGX-Framework v2.7.0 or newer.
- Moves the three-tick reference heartbeat into the shipped declarative
`every.heartbeat` timer form.
- Keeps startup output in `onInit`; declarative `on` remains Tier 4.
- Updates the System test tab to verify the heartbeat reaches exactly 3,
self-cancels, and remains at 3 after at least five additional seconds.
Loading