Skip to content

9-Slice Image Support (for games) #430

@softmarshmallow

Description

@softmarshmallow

Feature Request: 9-Slice Image Support

Overview

Add 9-slice (9-patch) image support to Grida Canvas to enable efficient UI element rendering, particularly for game development and responsive UI design.

Background

9-slice is a technique that divides an image into 9 regions (3x3 grid) where:

  • Corners: Scale proportionally (maintain aspect ratio)
  • Edges: Scale in one direction only
  • Center: Scales in both directions

This is essential for creating scalable UI elements like buttons, panels, and decorative borders that maintain visual integrity at any size.

Current State

Currently, Grida Canvas supports:

  • Single image fitting modes (ImagePaintFit::Fit, ImagePaintFit::Transform, ImagePaintFit::Tile)
  • Basic image transformations and effects
  • Resource references via ResourceRef

Missing: 9-slice specific functionality for UI/game development workflows.

Use Cases

Primary Use Cases

  1. Game UI Development

    • Scalable buttons, panels, and HUD elements
    • Responsive UI that works across different screen resolutions
    • Efficient memory usage (single texture for multiple sizes)
  2. Web/App UI Design

    • Scalable decorative borders and frames
    • Responsive design elements
    • Consistent visual appearance across devices
  3. Design System Components

    • Reusable UI components
    • Consistent scaling behavior
    • Reduced asset management overhead

Proposed Implementation

1. Core Data Structures

/// 9-slice image paint configuration
#[derive(Debug, Clone)]
pub struct NineSlicePaint {
    pub active: bool,
    pub image: ResourceRef,
    pub quarter_turns: u8,
    pub alignment: Alignment,
    pub opacity: f32,
    pub blend_mode: BlendMode,
    pub filters: ImageFilters,

    /// 9-slice specific configuration
    pub nine_slice: NineSliceConfig,
}

/// 9-slice configuration defining the slice boundaries
#[derive(Debug, Clone)]
pub struct NineSliceConfig {
    /// Left edge position (0.0 to 1.0, relative to image width)
    pub left: f32,
    /// Right edge position (0.0 to 1.0, relative to image width)
    pub right: f32,
    /// Top edge position (0.0 to 1.0, relative to image height)
    pub top: f32,
    /// Bottom edge position (0.0 to 1.0, relative to image height)
    pub bottom: f32,
    /// Whether to fill the center region (true) or leave it transparent (false)
    pub fill_center: bool,
}

/// 9-slice region enumeration
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum NineSliceRegion {
    TopLeft,
    TopCenter,
    TopRight,
    MiddleLeft,
    MiddleCenter,
    MiddleRight,
    BottomLeft,
    BottomCenter,
    BottomRight,
}

2. Enhanced ImagePaintFit

#[derive(Debug, Clone)]
pub enum ImagePaintFit {
    /// Standard fitting modes
    Fit(BoxFit),
    /// Custom transform
    Transform(AffineTransform),
    /// Pattern tiling
    Tile(ImageTile),
    /// 9-slice rendering
    NineSlice(NineSliceConfig),
}

3. Editor UX Design

Visual Slice Editor

  • Interactive slice handles: Draggable guides on the image preview
  • Live preview: Real-time scaling demonstration
  • Slice visualization: Color-coded regions (corners, edges, center)
  • Constraint indicators: Show minimum/maximum slice sizes

Property Panel

9-Slice Configuration
├── Slice Boundaries
│   ├── Left: [0.25] (25%)
│   ├── Right: [0.75] (75%)
│   ├── Top: [0.25] (25%)
│   └── Bottom: [0.75] (75%)
├── Center Fill: [✓] Fill center region
└── Preview
    ├── Test Scale: [2x] [4x] [8x]
    └── Show Grid: [✓]

Keyboard Shortcuts

  • Ctrl+9: Toggle 9-slice mode
  • Tab: Cycle through slice handles
  • Shift+Click: Precise numeric input for slice values

4. Game Engine Compatibility

Export Metadata

{
  "type": "nine_slice",
  "image": "button.png",
  "slices": {
    "left": 0.25,
    "right": 0.75,
    "top": 0.25,
    "bottom": 0.75
  },
  "fill_center": true,
  "engines": {
    "unity": {
      "sprite_border": [8, 8, 8, 8],
      "sprite_mode": "Sliced"
    },
    "unreal": {
      "texture_group": "UI",
      "mip_gen_settings": "NoMipMaps"
    },
    "godot": {
      "texture_flags": "Repeat",
      "region": [0, 0, 32, 32]
    }
  }
}

Supported Export Formats

  • Unity: .meta files with Sprite Border settings
  • Unreal Engine: Texture import settings
  • Godot: .tres resource files
  • Generic: JSON metadata for custom engines

Technical Implementation

Rendering Pipeline

  1. Slice Calculation: Compute 9 regions based on slice boundaries
  2. UV Mapping: Generate texture coordinates for each region
  3. Geometry Generation: Create mesh vertices for each slice
  4. Shader Application: Apply appropriate scaling to each region

Performance Considerations

  • Mesh Caching: Cache generated geometry for repeated use
  • Texture Atlasing: Support for texture atlases with 9-slice metadata
  • LOD Support: Different slice configurations for different detail levels

Validation Rules

  • Slice boundaries must be within [0.0, 1.0] range
  • Left boundary < Right boundary
  • Top boundary < Bottom boundary
  • Minimum slice size constraints (e.g., 1px minimum)

Editor Integration

Canvas Integration

  • Slice visualization: Overlay guides on image preview
  • Real-time scaling: Interactive resize handles with 9-slice preview
  • Constraint snapping: Snap to pixel boundaries and common ratios

Property Inspector

  • Numeric inputs: Precise slice boundary specification
  • Visual sliders: Intuitive boundary adjustment
  • Preset library: Common 9-slice configurations (buttons, panels, etc.)

Export Options

  • Engine-specific presets: Pre-configured export settings
  • Batch export: Export multiple 9-slice assets with consistent settings
  • Validation: Check for common 9-slice configuration issues

Success Metrics

Developer Experience

  • Setup time: < 2 minutes to configure a 9-slice image
  • Export time: < 30 seconds to generate engine-compatible assets
  • Error rate: < 5% of exports require manual correction

Performance

  • Rendering: No performance penalty compared to regular image rendering
  • Memory: Efficient texture usage with proper UV mapping
  • Export: Fast generation of engine-specific metadata

Compatibility

  • Engine support: Unity, Unreal, Godot, and generic JSON export
  • Format support: PNG, WebP, and other common texture formats
  • Version control: Clean diffs for 9-slice metadata changes

Implementation Phases

Phase 1: Core Implementation

  • Add NineSliceConfig and NineSlicePaint structures
  • Implement basic 9-slice rendering in the canvas engine
  • Add slice boundary validation and constraints

Phase 2: Editor Integration

  • Create visual slice editor interface
  • Add property panel controls
  • Implement real-time preview functionality

Phase 3: Export System

  • Implement engine-specific export formats
  • Add metadata generation for game engines
  • Create batch export functionality

Phase 4: Advanced Features

  • Add preset library for common configurations
  • Implement texture atlas support
  • Add performance optimizations and caching

Related Work

Existing Solutions

  • Unity: Built-in 9-slice sprite support
  • Unreal Engine: Slate UI system with 9-slice borders
  • Figma: Limited 9-slice support in plugins
  • Adobe XD: No native 9-slice support

Standards and References

Conclusion

9-slice image support would significantly enhance Grida Canvas's utility for game development and UI design workflows. The proposed implementation focuses on:

  1. Developer-friendly UX: Intuitive visual editing with real-time preview
  2. Game engine compatibility: Seamless export to popular game engines
  3. Performance: Efficient rendering without overhead
  4. Extensibility: Foundation for advanced features like texture atlasing

This feature would position Grida Canvas as a comprehensive tool for both design and development workflows, particularly in the game development space.

Metadata

Metadata

Labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions