PGPSCN Format Example

This example demonstrates how to use the PGPSCN (PopcorningGuineaPig Scene) format to create declarative UI scenes. The PGPSCN format allows you to define UI layouts, styling, and interactions in JSON files, providing a clean separation between presentation and logic while maintaining full backward compatibility with traditional C# scenes.
Overview
The PGPSCN example shows a main menu implementation using the declarative PGPSCN format instead of traditional C# UI creation. This example is located in examples/main-menu-pgpscn/ and demonstrates:
- Declarative UI Definition: UI elements defined in JSON format
- Localization Support: Multi-language support with fallbacks
- Asset Management: Centralized asset registry system
- Command Integration: Actions defined declaratively
- Scene Transitions: Navigation between scenes
- Settings Integration: Language selection and settings persistence
Key Features
1. PGPSCN File Structure
The main menu is defined in MainMenuScene.pgpscn:
{
"version": "1.0",
"sceneType": "2d",
"metadata": {
"name": "MainMenuScene",
"description": "Main menu with 2D UI elements matching original example",
"backgroundColor": "#000000"
},
"assets": {
"textures": {
"button_texture": "assets/kenney/panel-002.png"
},
"fonts": {
"unicode_font": "assets/Roboto-Regular.ttf",
"chinese_font": "assets/NotoSansSC-VariableFont_wght.ttf",
"japanese_font": "assets/NotoSansJP-VariableFont_wght.ttf",
"korean_font": "assets/NotoSansKR-VariableFont_wght.ttf"
}
},
"UIElements": [...]
}
2. Responsive Positioning
Elements use percentage-based positioning for responsive design:
{
"id": "settings_button",
"type": "Button",
"properties": {
"position": {
"type": "percentage",
"x": 2,
"y": 93
},
"size": {
"type": "percentage",
"width": 12.5,
"height": 6.7
}
}
}
3. Localization Integration
Text elements automatically resolve localization keys:
{
"bindings": [
{
"property": "text",
"source": {
"type": "localization",
"key": "settings_button"
},
"fallback": "Settings"
}
]
}
4. Declarative Actions
Button actions are defined without code:
{
"actions": [
{
"trigger": "onClick",
"command": {
"type": "scene_transition",
"target": "SettingsScene"
}
}
]
}
C# Integration
The C# scene class works alongside the PGPSCN file:
public class MainMenuScene : Scene
{
private MainMenuScene _mainMenu;
private Settings _settings;
private ISettingsService _settingsService;
public MyGame() : base()
{
// Load settings
LoadSettings();
// Load localization (optional)
string localizationPath = Path.Combine(Directory.GetCurrentDirectory(), "assets", "localization.csv");
if (File.Exists(localizationPath))
{
Localization.LoadLocalization(localizationPath);
}
// Create scenes - PGPSCN handles UI creation automatically
_mainMenu = new MainMenuScene();
// Initialize window and apply settings
this.Init(width, height);
_settingsService.ApplySettings(_settings, this);
this.SceneManager.QueueScene(_mainMenu, 0f);
}
}
Multi-Language Support
The example includes comprehensive Unicode font support:
- Roboto-Regular.ttf - Western languages
- NotoSansSC-VariableFont_wght.ttf - Simplified Chinese
- NotoSansJP-VariableFont_wght.ttf - Japanese
- NotoSansKR-VariableFont_wght.ttf - Korean
The language dropdown allows runtime language switching:
{
"id": "language_dropdown",
"type": "Dropdown",
"properties": {
"options": ["en", "zh", "ko", "ja"]
},
"actions": [
{
"trigger": "onSelectionChanged",
"command": {
"type": "scene_method",
"method": "OnLanguageChanged",
"parameters": ["{value}"]
}
}
]
}
Running the Example
Prerequisites
- .NET 10.0 or later
- PopcorningGuineaPig.Engine reference
Build and Run
cd examples/main-menu-pgpscn/MainMenu
dotnet build
dotnet run
Project Structure
MainMenu/
├── MainMenu.Pgpscn.csproj # Project file with PGPSCN support
├── MyGame.cs # Game initialization
├── Program.cs # Entry point
├── settings.json # Game settings
├── assets/ # Assets (fonts, textures, localization)
└── scenes/
├── MainMenuScene.cs # C# scene class
├── MainMenuScene.pgpscn # PGPSCN UI definition
├── SettingsScene.cs # Settings scene class
└── SettingsScene.pgpscn # Settings UI definition
What You'll Learn
- PGPSCN Format Basics: How to structure scenes declaratively
- Asset Management: Centralized asset registry and referencing
- Responsive Design: Percentage-based positioning and sizing
- Localization: Multi-language support with automatic font selection
- Command System: Declarative actions and scene transitions
- Property Binding: Dynamic UI updates from game state
- Settings Integration: Persistent settings with UI controls
Comparison with Traditional C# Approach
Traditional C# Approach
// Manual UI creation in C#
var settingsButton = new Button("Settings", new Vector2(30, 600), new Vector2(120, 50), Color.Blue);
settingsButton.SetOnClick(() => SceneManager.LoadScene("SettingsScene"));
PGPSCN Approach
// Declarative UI in JSON
{
"id": "settings_button",
"type": "Button",
"properties": {
"text": "@settings_button",
"position": {"type": "percentage", "x": 2, "y": 93}
},
"actions": [
{
"trigger": "onClick",
"command": {"type": "scene_transition", "target": "SettingsScene"}
}
]
}
Benefits of PGPSCN Format
- Rapid Iteration: Modify UI without recompilation
- Designer Friendly: JSON format accessible to non-programmers
- Responsive by Default: Built-in responsive positioning
- Localization Ready: Automatic localization key resolution
- Asset Management: Centralized asset registry
- Version Control Friendly: Text-based format for easy diffing
- Backward Compatible: Works alongside existing C# scenes
Related Documentation
- PGPSCN Format - Complete format specification
- UI Components - Available UI elements
- Localization - Localization system
- Settings Management - Settings service
- Asset Registry - Asset management
Next Steps
After exploring this example, consider:
- Modifying the UI layout by editing the PGPSCN file
- Adding new UI elements or changing styling
- Implementing custom commands or property bindings
- Creating your own PGPSCN-based scenes
- Exploring hybrid 3D + UI scenes
The PGPSCN format provides a powerful foundation for scalable UI development while maintaining the flexibility and performance of the underlying C# engine.