cancel
Showing results for 
Search instead for 
Did you mean: 

Customizable spatial CUI panel script

Vicentekk
Member

I’m presenting CUI_Spatial, a minimalist and customizable spatial UI panel script for Horizon Worlds. This component allows you to display information, images. perfect for enhancing the user experience in your worlds.

The script is documented in both English and Spanish to make integration easier for creators of all levels. You just need to attach it to a CUI gizmo in your world and configure its properties to fit your needs. It's ideal for displaying messages, instructions, logos, or any relevant content in a clean and visual way.

I hope this resource is helpful for the community and contributes to improving the quality of experiences in Horizon Worlds!
(Apologies if I didn’t format the script properly in the forum I’m still not exactly sure how to do it for TS.)

/*
  CUI_Spatial - Minimal custom UI panel in spatial mode
  Author: Vicentekk

  Description / Descripción:
  This component provides a customizable 3D information panel for Horizon Worlds in spatial mode. 
  You must attach this script to a CUI gizmo that is present in your world for it to function.
  Este componente proporciona un panel de información 3D personalizable para Horizon Worlds en modo espacial.
  Debes adjuntar este script a un gizmo CUI que esté presente en tu mundo para que funcione.
  Example usage / Ejemplo de uso:
    */


import * as hz from 'horizon/core';
import { UIComponent, View, Text, Image, ImageSource } from 'horizon/ui';

// This script defines a minimal and robust UI panel for Horizon Worlds
// Este script define un panel UI mínimo y robusto para Horizon Worlds
class CUI_Spatial extends UIComponent<typeof CUI_Spatial> {
  static propsDefinition = {
    // Text and content / Texto y contenido
    panelTitle: { type: hz.PropTypes.String, default: 'Info Panel', displayName: 'Panel Title / Título del Panel' },
    descriptionText: { type: hz.PropTypes.String, default: 'Description Text', displayName: 'Description / Descripción' },
    showTitle: { type: hz.PropTypes.Boolean, default: true, displayName: 'Show Title / Mostrar Título' },
    showDescription: { type: hz.PropTypes.Boolean, default: true, displayName: 'Show Description / Mostrar Descripción' },
    // Colors and styles / Colores y estilos
    backgroundColor: { type: hz.PropTypes.String, default: '#222C', displayName: 'Background Color / Color de Fondo' },
    borderRadius: { type: hz.PropTypes.Number, default: 12, displayName: 'Border Radius / Radio de Bordes' },
    borderColor: { type: hz.PropTypes.String, default: '#FFFFFF', displayName: 'Border Color / Color de Borde' },
    borderWidth: { type: hz.PropTypes.Number, default: 2, displayName: 'Border Width / Grosor de Borde' },
    titleColor: { type: hz.PropTypes.String, default: '#FFFFFF', displayName: 'Title Color / Color del Título' },
    descriptionColor: { type: hz.PropTypes.String, default: '#CCCCCC', displayName: 'Description Color / Color de la Descripción' },
    // Typography / Tipografía
    titleFontSize: { type: hz.PropTypes.Number, default: 28, displayName: 'Title Font Size / Tamaño de Fuente del Título' },
    descriptionFontSize: { type: hz.PropTypes.Number, default: 18, displayName: 'Description Font Size / Tamaño de Fuente de la Descripción' },
    // Dimensions / Dimensiones
    width: { type: hz.PropTypes.Number, default: 400, displayName: 'Panel Width / Ancho del Panel' },
    height: { type: hz.PropTypes.Number, default: 200, displayName: 'Panel Height / Alto del Panel' },
    padding: { type: hz.PropTypes.Number, default: 20, displayName: 'Inner Padding / Padding Interno' },
    // Background image and logo / Imagen de fondo y logo
    backgroundImage: { type: hz.PropTypes.Asset, default: null, displayName: 'Background Image / Imagen de Fondo' },
    showLogo: { type: hz.PropTypes.Boolean, default: false, displayName: 'Show Logo / Mostrar Logo' },
    logoImage: { type: hz.PropTypes.Asset, default: null, displayName: 'Logo' },
    logoSize: { type: hz.PropTypes.Number, default: 64, displayName: 'Logo Size / Tamaño del Logo' },
  };

  // This method builds the UI tree to be displayed in the panel
  // Este método construye el árbol de UI que se mostrará en el panel
  initializeUI() {
    const panelStyle = {
      flexDirection: 'column' as const,
      alignItems: 'center' as const,
      justifyContent: 'center' as const,
      padding: this.props.padding,
      backgroundColor: this.props.backgroundColor,
      borderRadius: this.props.borderRadius,
      width: this.props.width,
      height: this.props.height,
      borderColor: this.props.borderColor,
      borderWidth: this.props.borderWidth,
    };

    
    const children = [];

    // Background image (if exists) / Imagen de fondo (si existe)
    if (this.props.backgroundImage) {
      children.push(
        Image({
          source: ImageSource.fromTextureAsset(this.props.backgroundImage),
          style: {
            position: 'absolute',
            width: this.props.width,
            height: this.props.height,
            left: 0,
            top: 0,
            borderRadius: this.props.borderRadius,
            zIndex: 0,
          },
        })
      );
    }

    // Logo (if enabled) / Logo (si está habilitado)
    if (this.props.showLogo && this.props.logoImage) {
      children.push(
        Image({
          source: ImageSource.fromTextureAsset(this.props.logoImage),
          style: { width: this.props.logoSize, height: this.props.logoSize, marginBottom: 12, zIndex: 1 },
        })
      );
    }
    // Title (if enabled) / Título (si está habilitado)
    if (this.props.showTitle) {
      children.push(
        Text({
          text: this.props.panelTitle,
          style: { fontSize: this.props.titleFontSize, color: this.props.titleColor, textAlign: 'center', marginBottom: 8 },
        })
      );
    }
    // Description (if enabled) / Descripción (si está habilitada)
    if (this.props.showDescription) {
      children.push(
        Text({
          text: this.props.descriptionText,
          style: { fontSize: this.props.descriptionFontSize, color: this.props.descriptionColor, textAlign: 'center', marginBottom: 12 },
        })
      );
    }
    return View({
      style: panelStyle,
      children,
    });
  }
}

hz.Component.register(CUI_Spatial);


 

Vicentekk
1 REPLY 1

GoodGameGomez
Community Manager
Community Manager