bc.Gem 0.0.15

dotnet add package bc.Gem --version 0.0.15
                    
NuGet\Install-Package bc.Gem -Version 0.0.15
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="bc.Gem" Version="0.0.15" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="bc.Gem" Version="0.0.15" />
                    
Directory.Packages.props
<PackageReference Include="bc.Gem" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add bc.Gem --version 0.0.15
                    
#r "nuget: bc.Gem, 0.0.15"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package bc.Gem@0.0.15
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=bc.Gem&version=0.0.15
                    
Install as a Cake Addin
#tool nuget:?package=bc.Gem&version=0.0.15
                    
Install as a Cake Tool

bc.Gem

bc.Gem is a lightweight, MonoGame-friendly framework that provides scene management, an action/gesture input runtime, and supporting utilities for game loops and state history.

Features

  • Scene lifecycle management (activate/show/hide/deactivate) with focus and render layers.
  • Action-surface input system with typed gestures and phases.
  • Device discovery and state history tracking (keyboard, mouse, gamepad).
  • Scene transitions and state persistence helpers.

Requirements

bc.Gem targets Microsoft.Xna.Framework types. Add the MonoGame package that matches your target platform.

dotnet add package MonoGame.Framework.DesktopGL

Install

dotnet add package bc.Gem

Getting Started

This is a minimal path to a running scene manager with the input runtime.

1) Create a SceneInputContext

namespace MyGame;

public readonly record struct SceneInputContext(string Identity);

2) Create InputRuntime and SceneManager

using bc.Gem.Framework.Input;
using bc.Gem.Framework.Scenes;
using Microsoft.Xna.Framework;

public sealed class MyGame : Game
{
    private readonly InputRuntime<string, SceneInputContext> _inputRuntime;
    private readonly SceneManager _sceneManager;

    public MyGame(IGameContext gameContext)
    {
        _inputRuntime = new InputRuntime<string, SceneInputContext>(id => new SceneInputContext(id));

        var registry = new SceneRegistry();
        var factoryRegistry = new SceneFactoryRegistry();
        var stateStore = new SceneStateStore();
        var activeScenes = new ActiveSceneSet(registry);
        var focusChain = new FocusChain();
        var renderSorter = new RenderSorter();
        var router = new DemoSceneRouter();

        _sceneManager = new SceneManager(
            gameContext,
            router,
            registry,
            factoryRegistry,
            stateStore,
            activeScenes,
            focusChain,
            renderSorter);
    }

    protected override void Update(GameTime gameTime)
    {
        _inputRuntime.Update(gameTime);
        _sceneManager.Update(gameTime);
        base.Update(gameTime);
    }

    protected override void Draw(GameTime gameTime)
    {
        _sceneManager.Draw(gameTime);
        base.Draw(gameTime);
    }
}

3) Define a Scene With Action-Surface Input

using bc.Gem.Framework;
using bc.Gem.Framework.Input;
using bc.Gem.Framework.Input.Actions;
using bc.Gem.Framework.Input.Contexts;
using bc.Gem.Framework.Input.Core;
using bc.Gem.Framework.Input.Devices.Core;
using bc.Gem.Framework.Input.Gestures;
using bc.Gem.Framework.Input.Handlers;
using bc.Gem.Framework.Scenes;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;

public sealed class TitleScene : IScene
{
    private const string StartActionId = "Start";

    private readonly InputRuntime<string, SceneInputContext> _runtime;
    private readonly ActionSurface _surface;
    private readonly ActionGestureMapper _mapper;
    private readonly ActionHandlerRegistry<SceneInputContext> _handlers;
    private readonly InputContextDefinition<SceneInputContext> _context;

    public TitleScene(InputRuntime<string, SceneInputContext> runtime)
    {
        _runtime = runtime;
        _surface = new ActionSurface(new Dictionary<string, Type> { [StartActionId] = typeof(bool) });
        _handlers = new ActionHandlerRegistry<SceneInputContext>(_surface.Actions);
        _handlers.Register<bool>(StartActionId, GesturePhase.Performed, (_, _) => Start());
        _mapper = new ActionGestureMapper(_surface);
        _context = new InputContextDefinition<SceneInputContext>("Title", _surface, _handlers, _mapper);
    }

    public string Id => "Title";
    public ScenePolicy Policy { get; } = new() { Participation = Participation.Input | Participation.Draw };
    public SceneVisibility Visibility { get; set; } = SceneVisibility.Hidden;

    public void OnShow()
    {
        if (_runtime.DeviceManager.TryGetStateHistory<KeyboardState>(
                new DevicePath { Kind = DeviceKind.Keyboard, Index = 0 },
                out var keyboard))
        {
            _mapper.Map(StartActionId, GesturePhase.Performed, keyboard.KeyPress(Keys.Enter));
        }

        _runtime.Router.SetActiveContexts(Id, [_context]);
    }

    public void OnHide() => _runtime.Router.Remove(Id);
    public void HandleInput(GameTime gameTime) => _runtime.Router.Update(gameTime, Id);

    public void LoadContent() { }
    public void UnloadContent() { }
    public void Update(GameTime gameTime) { }
    public void Draw(GameTime gameTime) { }
    public void OnEnter(IGameContext gameContext) { }
    public void OnExit() { }

    private void Start() { }
}

Input System Basics

  • Define actions on an ActionSurface (action id → value type).
  • Register behavior with ActionHandlerRegistry (action id + phase → handler).
  • Map gestures to actions with ActionGestureMapper.
  • Wrap those in an InputContextDefinition and activate via InputRuntime.Router.
  • Call Router.Update(gameTime, identity) in HandleInput.

Gesture Mapping Tips

Use the gesture helpers for common devices:

  • KeyboardGestures.KeyPress, KeyPressAndHold, KeyDoubleTap
  • MouseGestures.ButtonPress, ButtonRelease, Position
  • GamePadGestures.ButtonPress, LeftThumbstick, DPad

Scene Transitions

Use SceneTransition to express changes:

_router.Enqueue(new SceneTransition(
    SceneTransitionKind.Composite,
    activate: ["Gameplay"],
    hide: ["Title"],
    focusOrder: ["Gameplay"]));
  • activate / deactivate load and unload scenes.
  • show / hide toggle visibility while keeping the scene active.
  • focusOrder controls input focus order.

Rebinding Controls

ActionGestureMapper only adds mappings; it does not replace them. For rebinding, create a new mapper and new context definition, then set it active again.

_mapper = new ActionGestureMapper(_surface);
// map new gestures
_context = new InputContextDefinition<SceneInputContext>("Gameplay", _surface, _handlers, _mapper);
_runtime.Router.SetActiveContexts(Id, [_context]);

Docs

  • doc/Scene Management Quickstart.md
  • doc/Screen Lifecycle.md
  • doc/Input System Overview.md
  • doc/Getting Started - Input System.md
  • doc/Input Contexts.md
  • doc/Input Gesture Lifecycle.md

Key Namespaces

  • bc.Gem.Framework (scenes, state, game helpers)
  • bc.Gem.Framework.Scenes (scene manager, policies, transitions)
  • bc.Gem.Framework.Input (input runtime, actions, gestures, devices)
Product Compatible and additional computed target framework versions.
.NET net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.0.15 768 1/25/2026
0.0.13 133 1/22/2026
0.0.12 242 1/10/2026
0.0.11 225 1/4/2026
0.0.10 115 1/4/2026
0.0.9 127 1/4/2026
0.0.8 121 1/1/2026
0.0.7 116 1/1/2026
0.0.6 136 12/30/2025
0.0.5 116 12/30/2025
0.0.4 195 12/22/2025
0.0.3 194 12/21/2025
0.0.2 169 12/21/2025
0.0.1 158 3/1/2025