Skip to content
Merged
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Wago updater
.wago

# Compiled Lua sources
luac.out

Expand Down
23 changes: 23 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1 +1,24 @@
2026-Feb-25 r1.0.11
New: Sound Browser module
- Browse SoundKit IDs by category (auto-read from SOUNDKIT global, grouped by prefix)
- FileID range explorer with async playability scanning
- Live capture tab hooks PlaySound, PlaySoundFile, and PlayMusic calls
- Play/stop controls with single-active-sound management and auto-reset polling
- Favorites and recent lists persisted to SavedVariables
- Context menu: Copy ID, Copy PlaySound/PlaySoundFile/PlayMusic code, Insert to editor
- Search across all sources (kits, file IDs, live captures, favorites)
Improved: API Browser detail view
- Security labels (callable vs protected) instead of raw internal values
- Default values shown on arguments and fields
- Mixin type annotations on arguments (e.g. ItemLocationMixin)
- InnerType shown for table returns (e.g. table<number>)
- MayReturnNothing flag with explanation
- Event LiteralName shown as copyable RegisterEvent string
- Synchronous event timing indicator
- Enumeration range info (count, min, max)
- Per-field documentation on structures and enum values
- Namespace environment and documentation
- Insert Call now uses documented default values for argument placeholders
Fixed: API Browser Documentation field crash when value was a table instead of string

2026-Feb-3 r1.0.0 Initial stable public release
11 changes: 9 additions & 2 deletions DevForge/DevForge.toc
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
## Interface: 120000, 120001
## Title: DevForge
## Notes: In-game dev toolkit: inspector, editor, console, events, errors, APIs, textures, performance
## Notes: In-game dev toolkit: inspector, editor, console, events, errors, APIs, textures, sounds, performance
## Author: hatdragon
## Contributors:
## Version: r1.0.10
## Version: r1.0.11

## SavedVariables: DevForgeDB
## IconTexture: Interface\Icons\INV_Gizmo_02
Expand Down Expand Up @@ -133,3 +133,10 @@ Modules\TextureBrowser\TextureIconData.lua
Modules\TextureBrowser\TextureRuntime.lua
Modules\TextureBrowser\TextureIndex.lua
Modules\TextureBrowser\TextureBrowser.lua

# Sound Browser Module
Modules\SoundBrowser\SoundKitData.lua
Modules\SoundBrowser\SoundFileData.lua
Modules\SoundBrowser\SoundRuntime.lua
Modules\SoundBrowser\SoundIndex.lua
Modules\SoundBrowser\SoundBrowser.lua
37 changes: 26 additions & 11 deletions DevForge/Modules/APIBrowser/APIBrowser.lua
Original file line number Diff line number Diff line change
Expand Up @@ -81,20 +81,35 @@ DF.ModuleSystem:Register("APIBrowser", function(sidebarParent, editorParent)

-- Build arguments with safe placeholder values
local args = {}
if doc.Arguments then
for _, arg in ipairs(doc.Arguments) do
local argType = arg.Type or "any"
if argType == "string" or argType == "cstring" then
args[#args + 1] = '"' .. (arg.Name or "str") .. '"'
elseif argType == "number" or argType == "luaIndex" or argType == "uiMapID" then
args[#args + 1] = "0"
elseif argType == "bool" then
args[#args + 1] = "true"
local function ArgPlaceholder(arg)
local argType = arg.Type or "any"
local argName = arg.Name
-- Use the documented default value when available
if arg.Default ~= nil then
local def = tostring(arg.Default)
if argType == "bool" then
return def
elseif argType == "string" or argType == "cstring" then
return '"' .. def .. '"'
else
-- Use nil with a type hint comment so the code is runnable
args[#args + 1] = "nil --[[" .. (arg.Name or "arg") .. ": " .. argType .. "]]"
return def .. " --[[" .. argName .. "]]"
end
end
if argType == "string" or argType == "cstring" then
return '"' .. (argName or "str") .. '"'
elseif argType == "number" or argType == "luaIndex" or argType == "uiMapID" then
return "0"
elseif argType == "bool" then
return "true"
else
return "nil --[[" .. (argName or "arg") .. ": " .. argType .. "]]"
end
end

if doc.Arguments then
for _, arg in ipairs(doc.Arguments) do
args[#args + 1] = ArgPlaceholder(arg)
end
end

-- Build return values
Expand Down
191 changes: 153 additions & 38 deletions DevForge/Modules/APIBrowser/APIBrowserDetail.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,61 @@ DF.APIBrowserDetail = {}

local Detail = DF.APIBrowserDetail

-- Helper: safely get a Documentation field as a string
local function DocString(doc)
if not doc then return nil end
if type(doc) == "table" then return table.concat(doc, " ") end
return tostring(doc)
end

-- Helper: format a single field/argument/return line with all available metadata
local function FormatField(field)
local typeStr = field.Type or "any"
local parts = {}

-- Name : Type
parts[#parts + 1] = " " .. DF.Colors.text .. field.Name .. "|r"
.. " : " .. DF.Colors.tableRef .. typeStr .. "|r"

-- InnerType for table types (e.g. table<number>)
if field.InnerType then
parts[#parts + 1] = DF.Colors.dim .. "<" .. DF.Colors.tableRef .. field.InnerType .. "|r" .. DF.Colors.dim .. ">|r"
end

-- Mixin — the Lua mixin class this argument expects
if field.Mixin then
parts[#parts + 1] = DF.Colors.dim .. " mixin:" .. DF.Colors.func .. field.Mixin .. "|r"
end

-- Nilable
if field.Nilable then
parts[#parts + 1] = DF.Colors.dim .. " [nilable]|r"
end

-- Default value
if field.Default ~= nil then
parts[#parts + 1] = DF.Colors.dim .. " default:" .. DF.Colors.number .. tostring(field.Default) .. "|r"
end

-- EnumValue (for enum fields)
if field.EnumValue ~= nil then
parts[#parts + 1] = " = " .. DF.Colors.number .. tostring(field.EnumValue) .. "|r"
end

-- StrideIndex — position within repeating argument groups
if field.StrideIndex then
parts[#parts + 1] = DF.Colors.dim .. " stride:" .. tostring(field.StrideIndex) .. "|r"
end

-- Documentation
local doc = DocString(field.Documentation)
if doc then
parts[#parts + 1] = " - " .. DF.Colors.comment .. doc .. "|r"
end

return table.concat(parts)
end

function Detail:Create(parent)
local pane = DF.Widgets:CreateScrollPane(parent, true)

Expand Down Expand Up @@ -56,16 +111,36 @@ function Detail:Create(parent)
end

function detail:FormatFunction(lines, system, doc)
-- Function signature
-- Function header
lines[#lines + 1] = DF.Colors.func .. (system or "") .. "." .. (doc.Name or "?") .. "|r"

-- Security and flags
if doc.SecretArguments then
local secLabel, secColor
if doc.SecretArguments == "AllowedWhenUntainted" then
secLabel = "Callable from addon code (untainted execution only)"
secColor = DF.Colors.dim
elseif doc.SecretArguments == "NotAllowed" then
secLabel = "Protected — cannot be called from addon code"
secColor = DF.Colors.error
else
secLabel = doc.SecretArguments
secColor = DF.Colors.dim
end
lines[#lines + 1] = DF.Colors.text .. "Security: |r" .. secColor .. secLabel .. "|r"
end
if doc.MayReturnNothing then
lines[#lines + 1] = DF.Colors.text .. "Returns: |r" .. DF.Colors.dim .. "may return nothing (check for nil)|r"
end
lines[#lines + 1] = ""

-- Build signature string
local params = {}
if doc.Arguments then
for _, arg in ipairs(doc.Arguments) do
local nilable = arg.Nilable and " [optional]" or ""
params[#params + 1] = arg.Name .. nilable
local p = arg.Name
if arg.Nilable then p = p .. " [optional]" end
params[#params + 1] = p
end
end

Expand All @@ -81,28 +156,26 @@ function Detail:Create(parent)
sig = table.concat(returns, ", ") .. " = "
end
sig = sig .. (system or "") .. "." .. (doc.Name or "?") .. "(" .. table.concat(params, ", ") .. ")"

if doc.MayReturnNothing then
sig = sig .. DF.Colors.dim .. " -- may return nothing|r"
end

lines[#lines + 1] = DF.Colors.text .. sig .. "|r"
lines[#lines + 1] = ""

-- Documentation
if doc.Documentation then
lines[#lines + 1] = DF.Colors.comment .. "-- " .. doc.Documentation .. "|r"
local docText = DocString(doc.Documentation)
if docText then
lines[#lines + 1] = DF.Colors.comment .. "-- " .. docText .. "|r"
lines[#lines + 1] = ""
end

-- Parameters
if doc.Arguments and #doc.Arguments > 0 then
lines[#lines + 1] = DF.Colors.keyword .. "Parameters:|r"
for _, arg in ipairs(doc.Arguments) do
local typeStr = arg.Type or "any"
local nilable = arg.Nilable and (DF.Colors.dim .. " [nilable]|r") or ""
local argLine = " " .. DF.Colors.text .. arg.Name .. "|r"
.. " : " .. DF.Colors.tableRef .. typeStr .. "|r"
.. nilable
if arg.Documentation then
argLine = argLine .. " - " .. DF.Colors.comment .. arg.Documentation .. "|r"
end
lines[#lines + 1] = argLine
lines[#lines + 1] = FormatField(arg)
end
lines[#lines + 1] = ""
end
Expand All @@ -111,15 +184,7 @@ function Detail:Create(parent)
if doc.Returns and #doc.Returns > 0 then
lines[#lines + 1] = DF.Colors.keyword .. "Returns:|r"
for _, ret in ipairs(doc.Returns) do
local typeStr = ret.Type or "any"
local nilable = ret.Nilable and (DF.Colors.dim .. " [nilable]|r") or ""
local retLine = " " .. DF.Colors.text .. ret.Name .. "|r"
.. " : " .. DF.Colors.tableRef .. typeStr .. "|r"
.. nilable
if ret.Documentation then
retLine = retLine .. " - " .. DF.Colors.comment .. ret.Documentation .. "|r"
end
lines[#lines + 1] = retLine
lines[#lines + 1] = FormatField(ret)
end
end
end
Expand All @@ -129,50 +194,88 @@ function Detail:Create(parent)
lines[#lines + 1] = DF.Colors.dim .. "Event in " .. (system or "?") .. "|r"
lines[#lines + 1] = ""

if doc.Documentation then
lines[#lines + 1] = DF.Colors.comment .. "-- " .. doc.Documentation .. "|r"
-- LiteralName — the actual event string for RegisterEvent
if doc.LiteralName then
lines[#lines + 1] = DF.Colors.text .. "RegisterEvent:|r "
.. DF.Colors.string .. "\"" .. doc.LiteralName .. "\"|r"
lines[#lines + 1] = ""
end

-- Synchronous flag
if doc.SynchronousEvent then
lines[#lines + 1] = DF.Colors.text .. "Timing: |r" .. DF.Colors.dim .. "Fires synchronously (before frame rendering)|r"
lines[#lines + 1] = ""
end

-- Documentation
local docText = DocString(doc.Documentation)
if docText then
lines[#lines + 1] = DF.Colors.comment .. "-- " .. docText .. "|r"
lines[#lines + 1] = ""
end

-- Payload
if doc.Payload and #doc.Payload > 0 then
lines[#lines + 1] = DF.Colors.keyword .. "Payload:|r"
for _, arg in ipairs(doc.Payload) do
local typeStr = arg.Type or "any"
local nilable = arg.Nilable and (DF.Colors.dim .. " [nilable]|r") or ""
lines[#lines + 1] = " " .. DF.Colors.text .. arg.Name .. "|r"
.. " : " .. DF.Colors.tableRef .. typeStr .. "|r"
.. nilable
lines[#lines + 1] = FormatField(arg)
end
end
end

function detail:FormatTable(lines, system, doc)
local typeLabel = doc.Type or "Table"
lines[#lines + 1] = DF.Colors.tableRef .. (doc.Name or "?") .. "|r"
lines[#lines + 1] = DF.Colors.dim .. "Table/Enum in " .. (system or "?") .. "|r"
lines[#lines + 1] = DF.Colors.dim .. typeLabel .. " in " .. (system or "?") .. "|r"
lines[#lines + 1] = ""

-- Documentation
local docText = DocString(doc.Documentation)
if docText then
lines[#lines + 1] = DF.Colors.comment .. "-- " .. docText .. "|r"
lines[#lines + 1] = ""
end

-- Enumeration range info
if doc.Type == "Enumeration" then
local rangeParts = {}
if doc.NumValues then
rangeParts[#rangeParts + 1] = DF.Colors.number .. doc.NumValues .. "|r" .. DF.Colors.text .. " values|r"
end
if doc.MinValue then
rangeParts[#rangeParts + 1] = DF.Colors.text .. "min " .. DF.Colors.number .. doc.MinValue .. "|r"
end
if doc.MaxValue then
rangeParts[#rangeParts + 1] = DF.Colors.text .. "max " .. DF.Colors.number .. doc.MaxValue .. "|r"
end
if #rangeParts > 0 then
lines[#lines + 1] = table.concat(rangeParts, DF.Colors.dim .. " | |r")
lines[#lines + 1] = ""
end
end

if doc.Type == "Enumeration" and doc.Fields then
lines[#lines + 1] = DF.Colors.keyword .. "Values:|r"
for _, field in ipairs(doc.Fields) do
local valStr = ""
if field.EnumValue then
if field.EnumValue ~= nil then
valStr = " = " .. DF.Colors.number .. tostring(field.EnumValue) .. "|r"
end
local docStr = DocString(field.Documentation)
if docStr then
valStr = valStr .. " - " .. DF.Colors.comment .. docStr .. "|r"
end
lines[#lines + 1] = " " .. DF.Colors.text .. field.Name .. "|r" .. valStr
end
elseif doc.Type == "Structure" and doc.Fields then
lines[#lines + 1] = DF.Colors.keyword .. "Fields:|r"
for _, field in ipairs(doc.Fields) do
local typeStr = field.Type or "any"
local nilable = field.Nilable and (DF.Colors.dim .. " [nilable]|r") or ""
lines[#lines + 1] = " " .. DF.Colors.text .. field.Name .. "|r"
.. " : " .. DF.Colors.tableRef .. typeStr .. "|r"
.. nilable
lines[#lines + 1] = FormatField(field)
end
elseif doc.Fields then
lines[#lines + 1] = DF.Colors.keyword .. "Fields:|r"
for _, field in ipairs(doc.Fields) do
lines[#lines + 1] = " " .. DF.Colors.text .. (field.Name or "?") .. "|r"
lines[#lines + 1] = FormatField(field)
end
end
end
Expand All @@ -184,13 +287,25 @@ function Detail:Create(parent)

local sys = DF.APIBrowserData:GetSystem(system)
if sys then
-- Environment
if sys.Environment then
lines[#lines + 1] = DF.Colors.text .. "Environment: " .. DF.Colors.dim .. sys.Environment .. "|r"
end

local funcCount = sys.Functions and #sys.Functions or 0
local eventCount = sys.Events and #sys.Events or 0
local tableCount = sys.Tables and #sys.Tables or 0

lines[#lines + 1] = DF.Colors.text .. "Functions: " .. DF.Colors.number .. funcCount .. "|r"
lines[#lines + 1] = DF.Colors.text .. "Events: " .. DF.Colors.number .. eventCount .. "|r"
lines[#lines + 1] = DF.Colors.text .. "Tables: " .. DF.Colors.number .. tableCount .. "|r"

-- Documentation
local docText = DocString(sys.Documentation)
if docText then
lines[#lines + 1] = ""
lines[#lines + 1] = DF.Colors.comment .. "-- " .. docText .. "|r"
end
end

lines[#lines + 1] = ""
Expand Down
Loading