En este post voy a documentar el proceso de como modificar la ui de intersect, el plan es comenzar por la pantalla principal y las ventanas de login, registro, configuraciones, y créditos.
¿Cómo funciona la UI de Intersect?
El motor usa un framework llamado Gwen con una arquitectura de 3 capas:
├─────────────────────────────────────────────────────────┤
CAPA 1: Imágenes (recursos/gui/*.png)
REEMPLAZO DIRECTO – NO requiere recompilación

En esta carpeta de \resources\gui podemos editar los botones principales del login y muchas cosas de la interfaz con tan solo con remplazar las imágenes que se encuentran ahi, en mi caso solo agregare background.png y logo.png.
├─────────────────────────────────────────────────────────┤
CAPA 2: JSON LAYOUTS (recursos/gui/layouts/menu/)
EDICIÓN SIMPLE – NO requiere recompilación

Cada control en el JSON tiene estas propiedades:
{
// POSICIÓN Y TAMAÑO
"Bounds": "x,y,width,height", // Coordenadas y dimensiones
"Dock": "None|Fill|Top|Bottom|Left|Right", // Sistema de dock
"Margin": "l,t,r,b", // Margen externo
"Padding": "l,t,r,b", // Relleno interno
// ALINEACIÓN
"Alignments": "CenterH|CenterV|Center|Top|Bottom|Left|Right",
"AlignmentEdgeDistances": "0,0,0,0",
"AlignmentTransform": "0,0",
// COLORES (formato ARGB: 0-255,0-255,0-255,0-255)
"RenderColor": "255,255,255,255", // Color de mezcla
"TextColor": "255,255,255,255", // Color de texto
"HoveredTextColor": "255,200,100,255",
"ClickedTextColor": "255,150,50,255",
"DisabledTextColor": "128,128,128,255",
// VISIBILIDAD
"Hidden": false,
"Disabled": false,
"DrawBackground": true,
"DrawShadow": true,
// FUENTES
"FontName": "sourcesansproblack", // Nombre de fuente
"FontSize": 12, // Tamaño en puntos
"TextScale": 1.0, // Escala adicional
"TextAlign": "Center|CenterV|Left|Right|Top|Bottom",
// TEXTURAS DE BOTONES
"NormalImage": "mainmenu_buttonLogin.png",
"HoveredImage": "mainmenu_buttonLogin_hovered.png",
"ClickedImage": "mainmenu_buttonLogin_clicked.png",
"DisabledImage": "mainmenu_buttonLogin_disabled.png",
// SONIDOS
"_stateSoundNames": {
"Hover": "octave-tap-resonant.wav",
"MouseDown": "octave-tap-warm.wav",
"MouseUp": "octave-tap-warm.wav"
},
// TAMAÑOS MÍNIMOS/MÁXIMOS
"MinimumSize": "160,24",
"MaximumSize": "0,0",
// CONTROL DE INTERACCIÓN
"MouseInputEnabled": true,
"AutoSizeToContents": false,
// CONTROLES HIJO
"Children": {
"_usernameLabel": { ... },
"_usernameInput": { ... }
}
}
Un Ejemplo para poder cambiar el color de la ventana principal del login,
en MaimMenuWindows_online.json se modifica el primer RenderColor.


en resources/config.json podemos personalizar el menú con algunas opciones:
{
// FUENTES
"GameFont": "sourcesansproblack", // Fuente principal
"EntityNameFont": "sourcesansproblack", // Nombres de entidades
"ChatBubbleFont": "sourcesansproblack", // Burbujas de chat
"UIFont": "sourcesanspro,10", // Fuente UI general
// FONDO DEL MENÚ
"MenuBackground": ["background.png"], // Array de imágenes (puede haber varias para slideshow)
"MenuBackgroundDisplayMode": "Default", // Modo de display
"MenuBackgroundFrameInterval": 50, // Ms entre frames de slideshow (50ms = 20fps)
// MÚSICA
"MenuMusic": "RPG-Theme_v001_Looping.ogg",
"MusicFadeTimer": 1500, // Ms para fade out de música
// SKIN DE UI
"UiSkin": "IntersectSkin", // Skin a usar (avanzado)
// EFECTOS
"TypewriterEnabled": true, // Efecto de máquina de escribir en texto
"FadeDurationMs": 3000.0, // Duración de fade en ms
// MISC
"EnableContextMenus": true, // Menús contextuales
"EnableZebraStripedRows": true // Filas alternadas en listas
}
Modos de Display del Fondo
| Modo | Descripción |
|---|---|
Default | Centrado, puede dejar barras negras |
Centered | Centrado exactamente |
Stretched | Estirado a pantalla completa (deforma) |
FitHeight | Ajusta a altura, mantiene proporción |
FitWidth | Ajusta a ancho, mantiene proporción |
FitMaximum | Escala hacia arriba hasta llenar pantalla |
FitMinimum | Escala hacia abajo hasta llenar pantalla |
├─────────────────────────────────────────────────────────┤
CAPA 3: CÓDIGO C# (código fuente/*.cs)
REQUIERE RECOMPILACIÓN

Flujo de carga de una ventana
1. MainMenu.cs crea la ventana
↓
2. Constructor de LoginWindow.cs
- Crea todos los controles (TextBox, Button, Label)
- Configura propiedades base (tamaño, fuentes, colores)
- Asigna event handlers (Clicked, SubmitPressed, etc.)
↓
3. EnsureInitialized() se llama automáticamente
↓
4. LoadJsonUi() carga el JSON
- Busca: resources/gui/layouts/menu/LoginWindow.json
- Aplica propiedades del JSON sobre las del código
- Procesa alineaciones
↓
5. OnJsonReloaded() - hook para post-procesamiento
Ejemplo: Crear una ventana completamente nueva
// 1. Crear clase que herede de Window
public class CustomWindow : Window, IMainMenuWindow
{
public CustomWindow(Canvas parent, MainMenu mainMenu) : base(
parent,
title: "Mi Ventana Personalizada",
modal: false,
name: nameof(CustomWindow)
)
{
// Configuración inicial
Alignment = [Alignments.CenterH];
MinimumSize = new Point(400, 300);
// Crear controles...
}
protected override void EnsureInitialized()
{
LoadJsonUi(GameContentManager.UI.Menu,
Graphics.Renderer?.GetResolutionString());
}
}
// 2. Registrar en MainMenu.cs
private CustomWindow? _customWindow;
public CustomWindow CustomWindow => _customWindow ??= new CustomWindow(_menuCanvas, this);
// 3. Agregar navegación
internal void SwitchToWindow<TMainMenuWindow>() where TMainMenuWindow : IMainMenuWindow
{
// ...código existente...
if (typeof(TMainMenuWindow) == typeof(CustomWindow))
{
CustomWindow.Show();
}
}
├─────────────────────────────────────────────────────────┤
Cambiar nombre del ejecutable
Hacer 3 modificaciones para no generar errores:
1.-En /Intersect.Client/Intersect.Client.csproj
<AssemblyName>Mini RPG</AssemblyName>
2.-En /Intersect.Client.Core/Intersect.Client.Core.csproj
<_Parameter1>Mini RPG</_Parameter1>
3.-En /Intersect-Engine/Framework/Intersect.Framework.Core.csproj
<_Parameter1>Mini RPG</_Parameter1>

Cambiar el icono de intersect
-Para cambiar el icono se puede realizar presionando Ctrl + mayus + F y buscar en todas las ubicaciones que tengan el nombre del logo de Intersect (intersect-logo-qu) que se encuentra en la carpeta Assets.
1.-en Intersect-Engine/Intersect.Client/Intersect.Client.csproj
<EmbeddedResource Include=»$(IntersectRepoPath)\assets\sharingan.bmp»>
2.-en Intersect-Engine/Intersect.props/
<PackageIcon>$(IntersectRepoPath)\assets\sharingan.png
<ApplicationIcon>$(IntersectRepoPath)\assets\sharingan.ico
<None Include=»$(IntersectRepoPath)\assets\sharingan.png» Pack=»true» PackagePath=»\» />
<EmbeddedResource Include=»$(IntersectRepoPath)\assets\sharingan.ico» Pack=»true» PackagePath=»\» />
3.-En Intersect-Engine\Intersect.Client.Framework\Intersect.Client.Framework.nuspec\
assets\sharingan.png
<icon>assets\sharingan.png</icon>
<file src=»..\assets\sharingan.png» target=»assets» />
4.-En \Intersect-Engine\Intersect.Editor\Core\Program.cs
private const string IconManifestResourceName = «Intersect.Editor.sharingan.ico»;
5.-En \Intersect-Engine\Intersect.Server.Framework\Intersect.Server.Framework.nuspec
assets\sharingan.png
<icon>assets\sharingan.png</icon>
<file src=»..\assets\sharingan.png» target=»assets» />
6.-En \Intersect-Engine\Intersect.SinglePlayer\Intersect.SinglePlayer.csproj
<EmbeddedResource Include=»$(IntersectRepoPath)\assets\sharingan.bmp»>
7.-En Intersect-Engine\Intersect.Client.Framework\Intersect.Client.Framework.nuspec\
<icon>assets\sharingan.png
<file src=»..\assets\sharingan.png» target=»assets» />
8.-En \Intersect-Engine\Intersect.Editor\Core\Program.cs
private const string IconManifestResourceName = «Intersect.Editor.sharingan.ico»;
9.-En \Intersect-Engine\Intersect.Server.Framework\Intersect.Server.Framework.nuspec
<icon>assets\sharingan.png
<file src=»..\assets\sharingan.png» target=»assets» />
10.-En \Intersect-Engine\Intersect.SinglePlayer\Intersect.SinglePlayer.csproj
<EmbeddedResource Include=»$(IntersectRepoPath)\assets\sharingan.bmp»>
Nombre en la ventana del juego
1.-\Intersect-Engine\Framework\Intersect.Framework.Core\Config\Options.cs
public const string DefaultGameName = «Intersect»;
2.-\Intersect-Engine\Intersect.Client.Core\Localization\Strings.cs
public static LocalizedString GameName = @»Intersect»;
Nota:
si el archivo config.json y client_strings.json ya existe en la carpeta de salida /Resources/, no se sobreescribe automáticamente, se deberá eliminar manualmente client_strings.json y ejecutar:
dotnet clean
dotnet build -p:Configuration=Debug -p:PackageVersion=0.8.0-beta -p:Version=0.8.0
Este fue el resultado de la modificación:






Deja una respuesta