### Configure and Interact with Owlbear Rodeo Scene Grid Source: https://context7.com/zjhsteven/owlbear-doc/llms.txt This snippet demonstrates how to configure and interact with the scene's grid system. It covers getting grid properties like DPI, scale, type, and measurement, as well as setting grid appearance (color, opacity, line type). It also shows how to set the grid type and scale, snap positions to the grid with optional sensitivity and corner/center snapping, and calculate distances between points. Finally, it includes examples of reacting to grid changes using useEffect and setting up different grid configurations (square, hex, isometric). ```javascript import OBR from "@owlbear-rodeo/sdk"; // Get grid properties const dpi = await OBR.scene.grid.getDpi(); // e.g., 150 const scale = await OBR.scene.grid.getScale(); // e.g., "5ft" const gridType = await OBR.scene.grid.getType(); // "SQUARE", "HEX_VERTICAL", etc. const measurementType = await OBR.scene.grid.getMeasurement(); // "CHEBYSHEV", etc. console.log(`Grid: ${gridType} at ${scale} (${dpi} DPI)`); // Configure grid appearance await OBR.scene.grid.setColor("DARK"); await OBR.scene.grid.setOpacity(0.3); await OBR.scene.grid.setLineType("DASHED"); // Set grid type and scale await OBR.scene.grid.setType("HEX_VERTICAL"); await OBR.scene.grid.setScale("10ft"); await OBR.scene.grid.setMeasurement("EUCLIDEAN"); // Snap position to grid const mousePos = { x: 523, y: 478 }; const snappedPos = await OBR.scene.grid.snapPosition(mousePos); console.log(`Snapped ${mousePos.x},${mousePos.y} to ${snappedPos.x},${snappedPos.y}`); // Snap with custom sensitivity (0-1, higher = more sensitive) const cornerSnap = await OBR.scene.grid.snapPosition( mousePos, 0.5, // sensitivity true, // useCorners false // useCenter ); // Calculate distance between points const start = { x: 0, y: 0 }; const end = { x: 500, y: 500 }; const distance = await OBR.scene.grid.getDistance(start, end); console.log(`Distance: ${distance} ${scale}`); // React to grid changes // Assuming useEffect and setGridScale/setGridType are defined elsewhere in the component context // useEffect(() => { // return OBR.scene.grid.onChange((grid) => { // console.log(`Grid changed: ${grid.type} at ${grid.scale}`); // setGridScale(grid.scale); // setGridType(grid.type); // }); // }, []); // Complete grid configuration tool async function setupSquareGrid() { await OBR.scene.grid.setType("SQUARE"); await OBR.scene.grid.setScale("5ft"); await OBR.scene.grid.setMeasurement("CHEBYSHEV"); // D&D 5e style await OBR.scene.grid.setColor("DARK"); await OBR.scene.grid.setOpacity(0.2); } async function setupHexGrid() { await OBR.scene.grid.setType("HEX_HORIZONTAL"); await OBR.scene.grid.setScale("5ft"); await OBR.scene.grid.setMeasurement("EUCLIDEAN"); } async function setupIsometricGrid() { await OBR.scene.grid.setType("ISOMETRIC"); await OBR.scene.grid.setScale("5ft"); await OBR.scene.grid.setMeasurement("MANHATTAN"); } // Measurement tool with grid snapping (Example Component) // Assuming useState is imported from React // function MeasurementTool() { // const [start, setStart] = useState(null); // const [end, setEnd] = useState(null); // const [distance, setDistance] = useState(0); // const handleClick = async (e) => { // const pos = { x: e.clientX, y: e.clientY }; // const snapped = await OBR.scene.grid.snapPosition(pos); // if (!start) { // setStart(snapped); // } else { // setEnd(snapped); // const dist = await OBR.scene.grid.getDistance(start, snapped); // setDistance(dist); // } // }; // return ( //
// {distance > 0 &&
Distance: {distance}
} //
// ); // } ``` -------------------------------- ### Dynamic Lighting with OBR.scene.items Source: https://context7.com/zjhsteven/owlbear-doc/llms.txt Examples of creating and adding various types of lights and walls to the scene to create dynamic lighting effects. ```APIDOC ## Dynamic Lighting with OBR.scene.items ### Description Implement dynamic lighting by creating and adding light sources and blocking elements (walls) to the scene. Supports various light types and configurations. ### Methods - `OBR.scene.items.addItems(items: Item[])`: Adds one or more items (lights, images) to the scene. - `OBR.scene.items.getItems(filter?: (item: Item) => boolean)`: Retrieves items from the scene, optionally filtered. ### Light Configuration Examples #### 1. Torch Light (360° with falloff) ```javascript const torch = buildLight() .position({ x: 500, y: 500 }) .attenuationRadius(300) // Light reach .sourceRadius(20) // Soft shadow size (0 = hard shadows) .falloff(0.5) // Edge softness (0 = hard, 1 = soft) .innerAngle(360) // Full circle .name("Torch") .build(); await OBR.scene.items.addItems([torch]); ``` #### 2. Directional Light (Spotlight/Cone) ```javascript const spotlight = buildLight() .position({ x: 1000, y: 500 }) .attenuationRadius(500) .sourceRadius(30) .falloff(0.7) .innerAngle(60) // Cone angle in degrees .outerAngle(90) // Outer cone for falloff .rotation(45) // Direction in degrees .name("Spotlight") .build(); await OBR.scene.items.addItems([spotlight]); ``` #### 3. Vision Light for Token ```javascript const visionLight = buildLight() .position({ x: 500, y: 500 }) .attenuationRadius(400) .sourceRadius(0) // Hard shadows for performance .innerAngle(360) .attachedTo("token-id-123") // Attach to token .name("Player Vision") .build(); await OBR.scene.items.addItems([visionLight]); ``` #### 4. Walls to Block Light ```javascript const wall = buildImage() .url("/wall-texture.png") .position({ x: 700, y: 500 }) .width(400) .height(50) .layer("MOUNT") .locked(true) .disableHit(true) // Not selectable .name("Wall") .build(); await OBR.scene.items.addItems([wall]); ``` #### 5. Multi-level Dungeon with Elevation ```javascript const lowerLight = buildLight() .position({ x: 500, y: 500 }) .attenuationRadius(300) .zIndex(0) // Lower level .build(); const upperLight = buildLight() .position({ x: 500, y: 500 }) .attenuationRadius(300) .zIndex(1) // Upper level .build(); const lowerWall = buildImage() .url("/wall.png") .position({ x: 700, y: 500 }) .layer("MOUNT") .zIndex(0) // Blocks lower lights only .build(); ``` #### 6. Secondary Lighting (Conditional) ```javascript const conditionalLight = buildLight() .position({ x: 800, y: 500 }) .attenuationRadius(200) .sourceRadius(0) .visionOnly(true) // Only active when another light hits it .name("Reflective Surface") .build(); ``` #### 7. Performance Optimization (Hard Shadows) ```javascript const performantLight = buildLight() .position({ x: 300, y: 300 }) .attenuationRadius(250) .sourceRadius(0) // Hard shadows = better performance .innerAngle(360) .build(); ``` #### 8. Complete Dungeon Lighting Setup Function ```javascript async function setupDungeonLighting() { const lights = []; // Player vision lights const tokens = await OBR.scene.items.getItems( item => item.layer === "CHARACTER" && isImage(item) ); for (const token of tokens) { const visionLight = buildLight() .position(token.position) .attenuationRadius(400) .sourceRadius(0) .attachedTo(token.id) .name(`Vision: ${token.name}`) .build(); lights.push(visionLight); } // Ambient torches const torchPositions = [ { x: 200, y: 200 }, { x: 800, y: 200 }, { x: 200, y: 800 }, { x: 800, y: 800 } ]; for (const pos of torchPositions) { const torch = buildLight() .position(pos) .attenuationRadius(250) .sourceRadius(15) .falloff(0.6) .innerAngle(360) .name("Torch") .build(); lights.push(torch); } await OBR.scene.items.addItems(lights); } ``` ``` -------------------------------- ### OBR Core API - SDK Initialization Source: https://context7.com/zjhsteven/owlbear-doc/llms.txt Provides core functionality for initializing extensions and checking SDK availability. It includes examples for checking SDK readiness and accessing player information. ```APIDOC ## OBR Core API - SDK Initialization ### Description This section covers the initialization of the Owlbear Rodeo SDK and checking for its availability. It demonstrates how to listen for the SDK's ready state and access basic player and scene information. ### Method Initialization and event listening ### Endpoint N/A (Client-side SDK) ### Parameters N/A ### Request Example ```javascript import OBR from "@owlbear-rodeo/sdk"; // Check if embedded in Owlbear Rodeo if (OBR.isAvailable) { // Initialize extension when SDK is ready OBR.onReady(() => { console.log("SDK is ready"); // Get current player info OBR.player.getName().then(name => { console.log(`Player name: ${name}`); }); // Check if scene is loaded OBR.scene.isReady().then(ready => { if (ready) { console.log("Scene is ready for manipulation"); } }); }); } // React integration pattern import { useEffect, useState } from "react"; function MyExtension() { const [isReady, setIsReady] = useState(false); useEffect(() => { return OBR.onReady(() => { setIsReady(true); }); }, []); if (!isReady) return
Loading...
; return
Extension ready!
; } ``` ### Response N/A (Client-side SDK behavior) ``` -------------------------------- ### KeyFilter Examples for Conditional Logic Source: https://github.com/zjhsteven/owlbear-doc/blob/master/docs/markdown/reference/filters.md Provides examples of KeyFilter configurations used to define conditional logic for filters. These filters check key-value pairs on objects, allowing for various comparison operators and logical coordinators (AND/OR) for complex filtering scenarios. ```javascript // The visible property must be `true` const a = [{ key: "visible", value: true }]; // The visible property must be `true` and the type must not equal `DRAWING` const b = [ { key: "visible", value: true }, { key: "type", value: "DRAWING", operator: "!=" }, ]; // The visible property must be `true` or the type must not equal `DRAWING` const c = [ { key: "visible", value: true, coordinator: "||" }, { key: "type", value: "DRAWING", operator: "!=" }, ]; ``` -------------------------------- ### Build Image Upload with File Source: https://github.com/zjhsteven/owlbear-doc/blob/master/docs/markdown/reference/image-upload.md Initializes an ImageUploadBuilder with a specified file. This is the starting point for configuring an image upload. It takes a File or Blob object as input. ```javascript buildImageUpload(file); ``` -------------------------------- ### Example Metadata Structure Source: https://github.com/zjhsteven/owlbear-doc/blob/master/docs/markdown/reference/metadata.md This JSON snippet illustrates the recommended structure for metadata, using a reverse domain name notation prefix ('com.tutorial.initiative-tracker/metadata') to prevent key collisions with other extensions. It shows how to store custom data, such as 'initiative' for an initiative tracker. ```json { "com.tutorial.initiative-tracker/metadata": { initiative: number } } ``` -------------------------------- ### Manage Tool Configuration Metadata with OWLBear SDK Source: https://context7.com/zjhsteven/owlbear-doc/llms.txt This snippet demonstrates how to store configuration metadata for specific tools within the OWLBear SDK. It provides an example of setting custom properties like stroke and fill colors for a drawing tool. ```javascript await OBR.tool.setMetadata("com.example.drawing/circle", { "com.example.drawing/strokeColor": "#FF0000", "com.example.drawing/fillColor": "#FFCCCC", "com.example.drawing/strokeWidth": 3 }); ``` -------------------------------- ### Manage Scene Metadata with OWLBear SDK Source: https://context7.com/zjhsteven/owlbear-doc/llms.txt This code example shows how to set and manage metadata for the entire scene using the OWLBear SDK. It covers storing scene-specific attributes such as difficulty, environment type, and level. ```javascript await OBR.scene.setMetadata({ "com.example.scene/difficulty": "hard", "com.example.scene/environment": "dungeon", "com.example.scene/level": 5 }); ``` -------------------------------- ### Grid API Source: https://github.com/zjhsteven/owlbear-doc/blob/master/docs/markdown/apis/grid.md This section covers the API endpoints for interacting with the scene's grid. You can get and set various properties like DPI, scale, color, opacity, type, line type, measurement, and line width. ```APIDOC ## `OBR.scene.grid.getDpi` ### Description Get the dots per inch (DPI) of the grid. Determines the resolution of one grid cell. For square grids this represents both the width and height of the grid cell. For vertically oriented hex grids this is the width of the grid cell. For horizontally oriented hex grids this is the height of the grid cell. For isometric and dimetric grids this is the post-transform height of the grid cell. ### Method GET ### Endpoint /scene/grid/dpi ### Parameters None ### Request Example ```javascript OBR.scene.grid.getDpi() ``` ### Response #### Success Response (200) - **dpi** (number) - The dots per inch of the grid. #### Response Example ```json { "dpi": 100 } ``` ``` ```APIDOC ## `OBR.scene.grid.getScale` ### Description Get the current scale of the grid. ### Method GET ### Endpoint /scene/grid/scale ### Parameters None ### Request Example ```javascript OBR.scene.grid.getScale() ``` ### Response #### Success Response (200) - **scale** (GridScale) - The current scale of the grid. See [GridScale](#gridscale) for possible values. #### Response Example ```json { "scale": "5ft" } ``` ``` ```APIDOC ## `OBR.scene.grid.setScale` ### Description Set the scale of the grid as a raw string. ### Method POST ### Endpoint /scene/grid/scale ### Parameters #### Request Body - **scale** (string) - Required - The new raw scale of the grid. ### Request Example ```json { "scale": "5ft" } ``` ### Response #### Success Response (204) No content is returned on successful update. #### Response Example (No content) ``` ```APIDOC ## `OBR.scene.grid.getColor` ### Description Get the current color of the grid. ### Method GET ### Endpoint /scene/grid/color ### Parameters None ### Request Example ```javascript OBR.scene.grid.getColor() ``` ### Response #### Success Response (200) - **color** (GridColor) - The current color of the grid. See [GridColor](#gridcolor) for possible values. #### Response Example ```json { "color": "DARK" } ``` ``` ```APIDOC ## `OBR.scene.grid.setColor` ### Description Set the color of the grid. ### Method POST ### Endpoint /scene/grid/color ### Parameters #### Request Body - **color** (GridColor) - Required - The new color of the grid. See [GridColor](#gridcolor) for possible values. ### Request Example ```json { "color": "DARK" } ``` ### Response #### Success Response (204) No content is returned on successful update. #### Response Example (No content) ``` ```APIDOC ## `OBR.scene.grid.getOpacity` ### Description Get the current opacity of the grid between 0 and 1. ### Method GET ### Endpoint /scene/grid/opacity ### Parameters None ### Request Example ```javascript OBR.scene.grid.getOpacity() ``` ### Response #### Success Response (200) - **opacity** (number) - The current opacity of the grid. #### Response Example ```json { "opacity": 0.5 } ``` ``` ```APIDOC ## `OBR.scene.grid.setOpacity` ### Description Set the opacity of the grid. ### Method POST ### Endpoint /scene/grid/opacity ### Parameters #### Request Body - **opacity** (number) - Required - The new opacity of the grid between 0 and 1. ### Request Example ```json { "opacity": 0.5 } ``` ### Response #### Success Response (204) No content is returned on successful update. #### Response Example (No content) ``` ```APIDOC ## `OBR.scene.grid.getType` ### Description Get the current grid type. ### Method GET ### Endpoint /scene/grid/type ### Parameters None ### Request Example ```javascript OBR.scene.grid.getType() ``` ### Response #### Success Response (200) - **type** (GridType) - The current grid type. See [GridType](#gridtype) for possible values. #### Response Example ```json { "type": "HEX_VERTICAL" } ``` ``` ```APIDOC ## `OBR.scene.grid.setType` ### Description Set the type of the grid. ### Method POST ### Endpoint /scene/grid/type ### Parameters #### Request Body - **type** (GridType) - Required - The new type of the grid. See [GridType](#gridtype) for possible values. ### Request Example ```json { "type": "HEX_VERTICAL" } ``` ### Response #### Success Response (204) No content is returned on successful update. #### Response Example (No content) ``` ```APIDOC ## `OBR.scene.grid.getLineType` ### Description Get the current grid line type. ### Method GET ### Endpoint /scene/grid/lineType ### Parameters None ### Request Example ```javascript OBR.scene.grid.getLineType() ``` ### Response #### Success Response (200) - **lineType** (GridLineType) - The current grid line type. See [GridLineType](#gridlinetype) for possible values. #### Response Example ```json { "lineType": "DASHED" } ``` ``` ```APIDOC ## `OBR.scene.grid.setLineType` ### Description Set the type of the grid line. ### Method POST ### Endpoint /scene/grid/lineType ### Parameters #### Request Body - **lineType** (GridLineType) - Required - The new type of the grid line. See [GridLineType](#gridlinetype) for possible values. ### Request Example ```json { "lineType": "DASHED" } ``` ### Response #### Success Response (204) No content is returned on successful update. #### Response Example (No content) ``` ```APIDOC ## `OBR.scene.grid.getMeasurement` ### Description Get the current grid measurement type. ### Method GET ### Endpoint /scene/grid/measurement ### Parameters None ### Request Example ```javascript OBR.scene.grid.getMeasurement() ``` ### Response #### Success Response (200) - **measurement** (GridMeasurement) - The current grid measurement type. See [GridMeasurement](#gridmeasurement) for possible values. #### Response Example ```json { "measurement": "EUCLIDEAN" } ``` ``` ```APIDOC ## `OBR.scene.grid.setMeasurement` ### Description Set the measurement type of the grid. ### Method POST ### Endpoint /scene/grid/measurement ### Parameters #### Request Body - **measurement** (GridMeasurement) - Required - The new measurement type of the grid. See [GridMeasurement](#gridmeasurement) for possible values. ### Request Example ```json { "measurement": "EUCLIDEAN" } ``` ### Response #### Success Response (204) No content is returned on successful update. #### Response Example (No content) ``` ```APIDOC ## `OBR.scene.grid.getLineWidth` ### Description Get the current line width of the grid in pixels. ### Method GET ### Endpoint /scene/grid/lineWidth ### Parameters None ### Request Example ```javascript OBR.scene.grid.getLineWidth() ``` ### Response #### Success Response (200) - **lineWidth** (number) - The current line width of the grid in pixels. #### Response Example ```json { "lineWidth": 1 } ``` ``` -------------------------------- ### Room State and Metadata Management Source: https://context7.com/zjhsteven/owlbear-doc/llms.txt This section covers how to interact with room-level data, including getting the current room ID, checking and reacting to player permissions, and managing room-wide metadata. ```APIDOC ## Room State and Metadata Management This API provides functionalities to manage room-level data and permissions shared across all players. ### Get Room ID Retrieves the unique identifier for the current room. - **Method**: GET - **Endpoint**: `OBR.room.id` - **Description**: Returns the ID of the current room. ### Get Player Permissions Retrieves the current permissions for the player within the room. - **Method**: GET - **Endpoint**: `OBR.room.getPermissions()` - **Description**: Fetches the player's permissions in the room. - **Returns**: A Promise that resolves to an object containing permission details. ### Subscribe to Permission Changes Allows you to register a listener that will be called whenever player permissions change. - **Method**: SUBSCRIBE - **Endpoint**: `OBR.room.onPermissionsChange(callback)` - **Description**: Attaches a callback function to be executed when permissions are updated. - **Parameters**: - `callback` (function) - The function to execute with the new permissions data. - **Returns**: A function to unsubscribe from the event. ### Set Room Metadata Stores or updates room-wide metadata. The metadata is stored as a key-value object and has a maximum size limit of 16KB per namespace. - **Method**: POST - **Endpoint**: `OBR.room.setMetadata(metadata)` - **Description**: Sets or updates metadata for the room. Can accept an object of key-value pairs or a function to update existing values. - **Parameters**: - `metadata` (object | function) - An object where keys are namespaces and values are the data to store, or a function that receives the previous value and returns the new value. - Example object: `{ "com.example.combat/state": { ... } }` - Example function: `(prev) => { ... return updated; }` ### Get Room Metadata Retrieves all room-wide metadata. - **Method**: GET - **Endpoint**: `OBR.room.getMetadata()` - **Description**: Fetches all metadata associated with the room. - **Returns**: A Promise that resolves to an object containing all room metadata. ### Subscribe to Metadata Changes Allows you to register a listener that will be called whenever room metadata changes. - **Method**: SUBSCRIBE - **Endpoint**: `OBR.room.onMetadataChange(callback)` - **Description**: Attaches a callback function to be executed when metadata is updated. - **Parameters**: - `callback` (function) - The function to execute with the new metadata object. - **Returns**: A function to unsubscribe from the event. ### Request Example: Setting Combat State Metadata ```json { "com.example.combat/state": { "active": true, "round": 3, "currentTurn": "player-id-123", "initiative": [ { "id": "player-id-123", "name": "Fighter", "initiative": 18 }, { "id": "player-id-456", "name": "Wizard", "initiative": 15 }, { "id": "npc-id-789", "name": "Goblin", "initiative": 12 } ] }, "com.example.session/info": { "sessionNumber": 5, "campaignName": "Lost Mines of Phandelver", "startTime": 1678886400000 } } ``` ### Response Example: Getting Room Metadata ```json { "com.example.combat/state": { "active": true, "round": 3, "currentTurn": "player-id-123", "initiative": [ { "id": "player-id-123", "name": "Fighter", "initiative": 18 }, { "id": "player-id-456", "name": "Wizard", "initiative": 15 }, { "id": "npc-id-789", "name": "Goblin", "initiative": 12 } ] }, "com.example.session/info": { "sessionNumber": 5, "campaignName": "Lost Mines of Phandelver", "startTime": 1678886400000 } } ``` ``` -------------------------------- ### Scene Fog API Source: https://github.com/zjhsteven/owlbear-doc/blob/master/docs/markdown/apis/fog.md Provides methods to interact with the base fog settings for a scene, including getting and setting its color, stroke width, and fill state. It also allows for subscribing to changes in fog settings. ```APIDOC ## GET /api/scene/fog/color ### Description Gets the current color of the scene's fog. ### Method GET ### Endpoint /api/scene/fog/color ### Parameters None ### Request Example None ### Response #### Success Response (200) - **color** (string) - The current color of the fog. #### Response Example ```json { "color": "#FFFFFF" } ``` ``` ```APIDOC ## PUT /api/scene/fog/color ### Description Sets the color of the scene's fog. ### Method PUT ### Endpoint /api/scene/fog/color ### Parameters #### Request Body - **color** (string) - Required - The new color for the fog. ### Request Example ```json { "color": "#FF0000" } ``` ### Response #### Success Response (200) - **message** (string) - Confirmation message. #### Response Example ```json { "message": "Fog color updated successfully." } ``` ``` ```APIDOC ## GET /api/scene/fog/strokeWidth ### Description Gets the current stroke width of the scene's fog. ### Method GET ### Endpoint /api/scene/fog/strokeWidth ### Parameters None ### Request Example None ### Response #### Success Response (200) - **strokeWidth** (number) - The current stroke width of the fog. #### Response Example ```json { "strokeWidth": 5 } ``` ``` ```APIDOC ## PUT /api/scene/fog/strokeWidth ### Description Sets the stroke width of the scene's fog. ### Method PUT ### Endpoint /api/scene/fog/strokeWidth ### Parameters #### Request Body - **width** (number) - Required - The new stroke width for the fog. ### Request Example ```json { "width": 10 } ``` ### Response #### Success Response (200) - **message** (string) - Confirmation message. #### Response Example ```json { "message": "Fog stroke width updated successfully." } ``` ``` ```APIDOC ## GET /api/scene/fog/filled ### Description Gets the current filled state of the scene's fog. ### Method GET ### Endpoint /api/scene/fog/filled ### Parameters None ### Request Example None ### Response #### Success Response (200) - **filled** (boolean) - True if the fog is filling the scene, false otherwise. #### Response Example ```json { "filled": true } ``` ``` ```APIDOC ## PUT /api/scene/fog/filled ### Description Sets the filled state of the scene's fog. ### Method PUT ### Endpoint /api/scene/fog/filled ### Parameters #### Request Body - **filled** (boolean) - Required - The new filled state for the fog (true/false). ### Request Example ```json { "filled": false } ``` ### Response #### Success Response (200) - **message** (string) - Confirmation message. #### Response Example ```json { "message": "Fog filled state updated successfully." } ``` ``` ```APIDOC ## POST /api/scene/fog/onChange ### Description Subscribes to changes in the scene's fog settings. A callback function is executed whenever fog properties are updated. ### Method POST ### Endpoint /api/scene/fog/onChange ### Parameters #### Request Body - **callback** (function) - Required - A function that accepts a `Fog` object as an argument and returns void. This function will be called when fog changes. ### Request Example ```javascript OBR.scene.fog.onChange((fog) => { console.log('Fog has changed:', fog); }); ``` ### Response #### Success Response (200) - **unsubscribe** (function) - A function that, when called, will unsubscribe the callback from fog change events. #### Response Example ```javascript const unsubscribe = OBR.scene.fog.onChange(...); // To unsubscribe later: unsubscribe(); ``` ``` -------------------------------- ### React to Theme Changes with useEffect Source: https://github.com/zjhsteven/owlbear-doc/blob/master/docs/markdown/apis/theme.md An example demonstrating how to use the `onChange` theme event with React's `useEffect` hook. The `useEffect` hook manages the subscription and unsubscription to theme changes automatically. ```javascript /** * Use an `onChange` event with a React `useEffect`. * `onChange` returns an unsubscribe event to make this easy. */ useEffect( () => OBR.theme.onChange((theme) => { // React to theme changes }), [] ); ``` -------------------------------- ### Send and Receive Messages with OBR.broadcast (JavaScript) Source: https://context7.com/zjhsteven/owlbear-doc/llms.txt Demonstrates sending ephemeral messages to players using different destinations (REMOTE, LOCAL, ALL) and receiving messages via an event listener. Messages are limited to 16KB. It requires the '@owlbear-rodeo/sdk' and 'react' for the example. ```javascript import OBR from "@owlbear-rodeo/sdk"; import { useEffect, useState } from "react"; // Define message channel (use your extension namespace) const CHANNEL = "com.example.combat/events"; // Send message to other players (REMOTE is default) await OBR.broadcast.sendMessage(CHANNEL, { type: "ROLL_DICE", playerId: await OBR.player.getId(), playerName: await OBR.player.getName(), roll: { dice: "1d20", result: 18, modifier: 3, total: 21 }, timestamp: Date.now() }); // Send to specific destinations await OBR.broadcast.sendMessage( CHANNEL, { type: "PING", position: { x: 500, y: 500 } }, { destination: "REMOTE" } // Only other players ); await OBR.broadcast.sendMessage( CHANNEL, { type: "LOCAL_UPDATE", data: "test" }, { destination: "LOCAL" } // Only current player (for multi-window sync) ); await OBR.broadcast.sendMessage( CHANNEL, { type: "GLOBAL_EVENT", message: "Session starting" }, { destination: "ALL" } // All players including sender ); // Receive messages useEffect(() => { return OBR.broadcast.onMessage(CHANNEL, (event) => { const { data, connectionId } = event; console.log(`Message from ${connectionId}:`, data); switch (data.type) { case "ROLL_DICE": // showDiceRoll(data.playerName, data.roll); break; case "PING": // showPing(data.position); break; case "DAMAGE": // applyDamage(data.targetId, data.amount); break; case "TURN_END": // advanceInitiative(); break; } }); }, []); // Complete dice roller example function DiceRoller() { const [rolls, setRolls] = useState([]); useEffect(() => { return OBR.broadcast.onMessage("com.example.dice/rolls", (event) => { setRolls(prev => [...prev, event.data]); }); }, []); const rollDice = async (dice) => { const result = Math.floor(Math.random() * 20) + 1; const playerName = await OBR.player.getName(); await OBR.broadcast.sendMessage("com.example.dice/rolls", { player: playerName, dice, result, timestamp: Date.now() }); }; return (
); } // Note: Messages limited to 16KB ``` -------------------------------- ### Manage Room State and Permissions with OBR.room SDK Source: https://context7.com/zjhsteven/owlbear-doc/llms.txt This snippet demonstrates how to get the current room ID, check player permissions, and subscribe to permission changes using the OBR.room module. It showcases asynchronous operations and event handling for real-time updates. ```javascript import OBR from "@owlbear-rodeo/sdk"; // Get room ID const roomId = OBR.room.id; console.log(`Current room: ${roomId}`); // Check player permissions const permissions = await OBR.room.getPermissions(); console.log("Room permissions:", permissions); // React to permission changes useEffect(() => { return OBR.room.onPermissionsChange((permissions) => { console.log("Permissions updated:", permissions); }); }, []); ``` -------------------------------- ### Find World Position of Line Start Source: https://github.com/zjhsteven/owlbear-doc/blob/master/docs/markdown/reference/math-m.md This example shows how to calculate the world position of a line's start point. It involves creating transformation matrices from the line and its start position, multiplying them, and then decomposing the resulting matrix to extract the world position. ```javascript const line = buildLine().build(); const lineTransform = MathM.fromItem(line); const startTransform = MathM.fromPosition(line.startPosition); const worldTransform = MathM.multiply(lineTransform, startTransform); const worldPosition = MathM.decompose(worldTransform).position; ``` -------------------------------- ### Delete Items and Attachments using Context Menu Source: https://github.com/zjhsteven/owlbear-doc/blob/master/docs/markdown/apis/items.md An example demonstrating how to delete selected items and their attachments when a context menu item is clicked. It uses `getItemAttachments` to get all related items and then `deleteItems` to remove them from the scene. This requires access to the context menu and scene items API. ```javascript OBR.contextMenu.create({ id: "rodeo.owlbear.example", icons: [ { icon: "icon.svg", label: "Example", }, ], async onClick(context) { const ids = context.items.map((item) => item.id); const allItems = await OBR.scene.items.getItemAttachments(ids); const allIds = allItems.map((item) => item.id); OBR.scene.items.deleteItems(allIds); }, }); ``` -------------------------------- ### Complete Dungeon Lighting Setup Function - JavaScript Source: https://context7.com/zjhsteven/owlbear-doc/llms.txt Provides a complete function to set up dungeon lighting dynamically. It creates player vision lights attached to tokens and adds ambient torch lights. Dependencies include OBR SDK and helper functions like isImage. Inputs are existing scene tokens. Outputs are a scene populated with lights. ```javascript // Complete dungeon lighting setup async function setupDungeonLighting() { const lights = []; // Player vision lights const tokens = await OBR.scene.items.getItems( item => item.layer === "CHARACTER" && isImage(item) ); for (const token of tokens) { const visionLight = buildLight() .position(token.position) .attenuationRadius(400) .sourceRadius(0) .attachedTo(token.id) .name(`Vision: ${token.name}`) .build(); lights.push(visionLight); } // Ambient torches const torchPositions = [ { x: 200, y: 200 }, { x: 800, y: 200 }, { x: 200, y: 800 }, { x: 800, y: 800 } ]; for (const pos of torchPositions) { const torch = buildLight() .position(pos) .attenuationRadius(250) .sourceRadius(15) .falloff(0.6) .innerAngle(360) .name("Torch") .build(); lights.push(torch); } await OBR.scene.items.addItems(lights); } ``` -------------------------------- ### Get and Set Grid Color - OBR.scene.grid Source: https://github.com/zjhsteven/owlbear-doc/blob/master/docs/markdown/apis/grid.md Enables getting the current grid color and setting a new color. The color can be set using predefined string values. ```javascript async getColor() ``` ```javascript async setColor(color) ``` ```javascript OBR.scene.grid.setColor("DARK"); ``` -------------------------------- ### Initialize Owlbear Rodeo SDK and Check Availability (JavaScript) Source: https://context7.com/zjhsteven/owlbear-doc/llms.txt Initializes the Owlbear Rodeo SDK and checks for its availability within the Owlbear Rodeo environment. It demonstrates how to react to the SDK being ready and retrieve basic player and scene information. Requires the @owlbear-rodeo/sdk package. ```javascript import OBR from "@owlbear-rodeo/sdk"; // Check if embedded in Owlbear Rodeo if (OBR.isAvailable) { // Initialize extension when SDK is ready OBR.onReady(() => { console.log("SDK is ready"); // Get current player info OBR.player.getName().then(name => { console.log(`Player name: ${name}`); }); // Check if scene is loaded OBR.scene.isReady().then(ready => { if (ready) { console.log("Scene is ready for manipulation"); } }); }); } // React integration pattern import { useEffect, useState } from "react"; function MyExtension() { const [isReady, setIsReady] = useState(false); useEffect(() => { return OBR.onReady(() => { setIsReady(true); }); }, []); if (!isReady) return
Loading...
; return
Extension ready!
; } ``` -------------------------------- ### Create Dynamic Lights (Torch, Spotlight, Vision) and Walls - JavaScript Source: https://context7.com/zjhsteven/owlbear-doc/llms.txt Demonstrates creating and adding various dynamic lighting elements and walls to the scene using the OBR SDK. This includes a 360° torch light, a directional spotlight, a token-attached vision light, and a wall image to block light. Dependencies include OBR SDK's buildLight and buildImage. Inputs are light properties (position, radius, angle) and image properties (URL, position, dimensions). Outputs are the added items to the scene. ```javascript // Create torch light (360° with falloff) const torch = buildLight() .position({ x: 500, y: 500 }) .attenuationRadius(300) // Light reach .sourceRadius(20) // Soft shadow size (0 = hard shadows) .falloff(0.5) // Edge softness (0 = hard, 1 = soft) .innerAngle(360) // Full circle .name("Torch") .build(); await OBR.scene.items.addItems([torch]); // Create directional light (spotlight/cone) const spotlight = buildLight() .position({ x: 1000, y: 500 }) .attenuationRadius(500) .sourceRadius(30) .falloff(0.7) .innerAngle(60) // Cone angle in degrees .outerAngle(90) // Outer cone for falloff .rotation(45) // Direction in degrees .name("Spotlight") .build(); await OBR.scene.items.addItems([spotlight]); // Create vision light for token const visionLight = buildLight() .position({ x: 500, y: 500 }) .attenuationRadius(400) .sourceRadius(0) // Hard shadows for performance .innerAngle(360) .attachedTo("token-id-123") // Attach to token .name("Player Vision") .build(); await OBR.scene.items.addItems([visionLight]); // Create walls to block light const wall = buildImage() .url("/wall-texture.png") .position({ x: 700, y: 500 }) .width(400) .height(50) .layer("MOUNT") .locked(true) .disableHit(true) // Not selectable .name("Wall") .build(); await OBR.scene.items.addItems([wall]); ``` -------------------------------- ### Get and Set Grid Line Type - OBR.scene.grid Source: https://github.com/zjhsteven/owlbear-doc/blob/master/docs/markdown/apis/grid.md Enables getting the current grid line type and setting a new line type. Available line types include DASHED and others defined by GridLineType. ```javascript async getLineType() ``` ```javascript async setLineType(lineType) ``` ```javascript OBR.scene.grid.setLineType("DASHED"); ```