Skip to content

Basic Usage

This guide walks you through creating your first Prisma UI interface, from setting up the C++ plugin code to building an interactive web UI that communicates with Skyrim.

Creating a Prisma UI interface involves three main steps:

  1. Initialize the API in your SKSE plugin
  2. Create a PrismaView that loads your HTML file
  3. Set up bidirectional communication between C++ and JavaScript

First, set up the basic structure in your SKSE plugin to initialize Prisma UI:

#include "PrismaUI_API.h"
// Declare the global PrismaUI API variable
PRISMA_UI_API::IVPrismaUI1* PrismaUI = nullptr;

Now let’s create a PrismaView and set up the communication:

void InitializeUI() {
// Create a view with DOM ready callback
PrismaView view = PrismaUI->CreateView("MyPlugin/index.html", [](PrismaView view) -> void {
logger::info("View DOM is ready {}", view);
// Initialize the UI with game data
PrismaUI->Invoke(view, "updatePlayerStatus('Ready for adventure!')");
// Send initial game state
PrismaUI->Invoke(view, "setPlayerLevel(25)");
PrismaUI->Invoke(view, "setPlayerHealth(100)");
});
// Register JavaScript event listeners
PrismaUI->RegisterJSListener(view, "onPlayerAction", [](const char* data) -> void {
logger::info("Player action received: {}", data);
std::string action = data;
if (action == "heal") {
// Implement healing logic
logger::info("Healing player...");
} else if (action == "save_game") {
// Implement save game logic
logger::info("Saving game...");
}
});
PrismaUI->RegisterJSListener(view, "requestPlayerData", [](const char* data) -> void {
// Send updated player data back to UI
PrismaUI->Invoke(view, "updatePlayerData({health: 85, magicka: 120, stamina: 95})");
});
}

Create your HTML file at Skyrim/Data/PrismaUI/views/MyPlugin/index.html:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Skyrim UI</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div class="ui-container">
<header class="ui-header">
<h1>Player Interface</h1>
<div id="status" class="status">Initializing...</div>
</header>
<main class="ui-main">
<section class="player-stats">
<h2>Player Stats</h2>
<div class="stat-item">
<label>Level:</label>
<span id="player-level">--</span>
</div>
<div class="stat-item">
<label>Health:</label>
<span id="player-health">--</span>
</div>
<div class="stat-item">
<label>Magicka:</label>
<span id="player-magicka">--</span>
</div>
<div class="stat-item">
<label>Stamina:</label>
<span id="player-stamina">--</span>
</div>
</section>
<section class="actions">
<h2>Actions</h2>
<button onclick="performAction('heal')" class="action-btn heal-btn">
Heal Player
</button>
<button onclick="performAction('save_game')" class="action-btn save-btn">
Save Game
</button>
<button onclick="refreshData()" class="action-btn refresh-btn">
Refresh Data
</button>
</section>
<section class="communication-test">
<h2>Communication Test</h2>
<input type="text" id="test-input" placeholder="Enter test data...">
<button onclick="sendTestData()" class="action-btn">Send to SKSE</button>
<div id="response-area" class="response-area"></div>
</section>
</main>
</div>
<script src="script.js"></script>
</body>
</html>

Your project should be organized like this:

Skyrim/Data/PrismaUI/views/MyPlugin/
├── index.html # Main HTML file
├── styles.css # CSS styling
└── script.js # JavaScript logic

For complex data structures, use JSON for reliable serialization:

#include <nlohmann/json.hpp>
using JSON = nlohmann::json;
void SendComplexData() {
JSON playerData = {
{"name", "Dragonborn"},
{"level", 25},
{"stats", {
{"health", 100},
{"magicka", 150},
{"stamina", 120}
}},
{"skills", {
{"oneHanded", 75},
{"destruction", 60},
{"restoration", 45}
}}
};
std::string script = "updateComplexData('" + playerData.dump() + "')";
PrismaUI->Invoke(view, script.c_str());
}

Use callbacks to get return values from JavaScript functions:

// C++ - Request data with callback
PrismaUI->Invoke(view, "getCurrentSettings()", [](const char* data) -> void {
logger::info("Current settings: {}", data);
// Parse and use the returned data
try {
JSON settings = JSON::parse(data);
bool vsync = settings["vsync"];
// Apply settings...
} catch (const std::exception& e) {
logger::error("Failed to parse settings: {}", e.what());
}
});
// JavaScript - Return data
window.getCurrentSettings = () => {
return JSON.stringify({
vsync: true,
quality: "high",
difficulty: "expert"
});
};

Error Handling

Always validate data received from JavaScript and handle parsing errors gracefully in your C++ code.

Performance

Batch UI updates when possible instead of calling Invoke multiple times in rapid succession.

DOM Ready

Use the onDomReadyCallback to ensure your JavaScript functions are available before calling them.

Single View

Create only one PrismaView per plugin. Manage multiple interfaces through your web application.

Now that you have a basic understanding of Prisma UI, explore these resources: