Appearance
System & Local Storage
Vulpis provides a suite of native C++ bindings designed to handle the complexities of cross-platform file systems, encrypted data persistence, and OS-level integration like the clipboard.
These APIs are essential for building production-ready desktop applications, allowing your Lua code to interact securely and reliably with the host operating system.
Secure Storage
Standard file I/O (like Lua's io.open) is sufficient for saving basic app settings. However, it is a major security vulnerability to store sensitive information—such as OAuth tokens, API keys, or user passwords—in plain text.
The Vulpis Secure Storage API solves this by utilizing platform-native encryption. This ensures that the data can only be decrypted and read by your application while running under the current user's operating system account.
Platform Implementation
- Windows: Utilizes the Data Protection API (DPAPI) via
CryptProtectDatato encrypt strings using the logged-in user's credentials. - Linux/macOS: Writes files using strictly enforced POSIX permissions (
0600), ensuring that only the owner of the process can read or write the data.
Methods
| Function | Arguments | Description |
|---|---|---|
vulpis.saveSecure | (filename, data) | Encrypts and saves a string to the Vulpis cache directory. Returns a boolean indicating success. |
vulpis.loadSecure | (filename) | Decrypts and returns the stored string. Returns nil if the file is missing or decryption fails. |
vulpis.deleteSecure | (filename) | Permanently removes the encrypted file. Returns a boolean indicating success. |
Example: A Secure Authentication Panel
This example demonstrates how to build a login panel that securely saves a session token, allowing the user to remain logged in between app restarts.
lua
local el = require("utils.core.elements")
function App()
-- Attempt to load the secure token on startup. If it fails, default to "None"
local saved_token = useState("auth_token", vulpis.loadSecure("session.dat") or "None")
return el.VBox({
style = { gap = 10, padding = 20, BGColor = "#222222", borderRadius = 8 },
children = {
el.Text("Current Token: " .. saved_token),
el.HBox({
style = { gap = 10 },
children = {
el.Button({
text = "Login (Save Token)",
onClick = function()
-- Simulate getting a token from a web request
local newToken = "usr_9988776655"
-- Encrypt and save to disk
if vulpis.saveSecure("session.dat", newToken) then
setState("auth_token", newToken)
print("Token secured.")
else
print("Critical error: Failed to encrypt token.")
end
end
}),
el.Button({
text = "Logout (Delete Token)",
style = { BGColor = "#EF4444" },
onClick = function()
-- Remove the encrypted file from the disk
if vulpis.deleteSecure("session.dat") then
setState("auth_token", "None")
print("User logged out.")
end
end
})
}
})
}
})
endPath Utilities
Handling file paths manually is notoriously difficult due to the differences between Windows (\) and Unix-like (/) file systems. The Path Utilities module provides a consistent, OS-agnostic way to locate assets and internal directories.
Core Directories Explained
- Project Root: The absolute path to the directory containing your Vulpis application. The engine intelligently strips out temporary build folders (like
/buildor/debug) to find your true project source. - Assets Directory: Automatically resolves to
/assets/. - Cache Directory: The OS-specific location for persistent application data.
- Windows:
%LOCALAPPDATA%/Vulpis/Cache. - macOS:
~/Library/Caches/Vulpis. - Linux: Respects
$XDG_CACHE_HOMEor defaults to~/.cache/Vulpis.
- Windows:
Functions
| Function | Description |
|---|---|
vulpis.getProjectRoot() | Returns the absolute path to the application root folder. |
vulpis.getAssetPath(rel) | Appends a relative string (e.g., "data/level.json") to the absolute asset path. |
vulpis.getCacheDir() | Returns the OS-specific directory for persistent cache files. |
Example: Reliable File Parsing
While Vulpis automatically resolves paths for internal UI components like el.Image (meaning you can just pass "images/icon.png" directly to src), you must use vulpis.getAssetPath when using standard Lua file I/O.
This guarantees that io.open will not crash if the application is launched from a different working directory (e.g., via a desktop shortcut).
lua
function LoadLevelData()
-- Get the bulletproof absolute path regardless of OS
local abs_path = vulpis.getAssetPath("data/level_1.json")
local file = io.open(abs_path, "r")
if file then
local content = file:read("*all")
file:close()
-- Parse your JSON string here
print("Level Loaded Successfully!")
return content
else
print("Error: Could not locate " .. abs_path)
return nil
end
endClipboard Access
Vulpis bridges the gap between your UI and the host operating system's clipboard, allowing users to copy and paste data seamlessly between Vulpis and other desktop applications.
(Note: The core TextInput utility already implements these bindings automatically for standard system shortcuts like Ctrl+C / Ctrl+V.)
Functions
| Function | Description |
|---|---|
vulpis.setClipboardText(text) | Places the provided string into the system clipboard. |
vulpis.getClipboardText() | Returns the current string stored in the system clipboard. |
Example: Copy and Paste Tools
lua
local el = require("utils.core.elements")
function App()
local pasted_text = useState("pasted_content", "Nothing pasted yet.")
return el.VBox({
style = { gap = 15, padding = 20 },
children = {
el.Button({
text = "Copy Invite Link",
onClick = function()
vulpis.setClipboardText("https://myapp.com/invite/vulpis123")
print("Copied to clipboard!")
end
}),
el.Button({
text = "Paste from OS",
onClick = function()
local txt = vulpis.getClipboardText()
if txt and txt ~= "" then
setState("pasted_content", txt)
end
end
}),
el.Text("Clipboard contains: " .. pasted_text)
}
})
endCache Management
To maintain high rendering performance, Vulpis aggressively caches baked textures (.vtex) and downloaded web images on both the physical disk and in GPU memory.
The clearCache function is provided as a utility to reset these systems if you need to force-reload assets or free up disk space for the user.
vulpis.clearCache()
When called, this function performs two actions simultaneously:
- Disk: Safely deletes and recreates the entire Vulpis cache directory for the current OS.
- Memory: Wipes the OpenGL texture registry and deletes texture IDs to prevent stale pointers and memory leaks.
Returns true if the wipe was successful, false otherwise.
Performance Impact
Calling clearCache() will cause a noticeable, temporary performance drop. The engine will need to re-bake local textures (like fonts and images) and re-download any active web images during the next render frame. Do not call this function during normal gameplay or continuous loops.
Example: A "Clear Storage" Settings Button
lua
local el = require("utils.core.elements")
function App()
local status = useState("cache_status", "Tracking...")
return el.VBox({
style = { gap = 10, padding = 20, BGColor = "#333333" },
children = {
el.Text("System Maintenance"),
el.Text(status),
el.Button({
text = "Clear All Cached Data",
style = { BGColor = "#EF4444" },
onClick = function()
if vulpis.clearCache() then
setState("cache_status", "Cache successfully cleared!")
else
setState("cache_status", "Error: Failed to clear cache.")
end
end
})
}
})
end