2dog.templates 4.7.2.132

dotnet new install 2dog.templates@4.7.2.132
                    
This package contains a .NET Template Package you can call from the shell/command line.

2dog Templates

This directory contains the dotnet new templates for creating 2dog projects.

Template Overview

The twodog template creates a complete 2dog application. The output directory is the Godot project (and the solution root); the host projects are nested inside it, each carrying a .gdignore so the Godot editor, importer, and exporter skip them:

  • Sample Godot project - project.godot, the Godot.NET.Sdk csproj, and a simple scene at the root
  • Desktop host (<Name>.2dog/) - Minimal working 2dog application (Program.cs with Main)
  • xUnit test project (<Name>.xunit/) - xUnit (v3) tests with 2dog.xunit collection fixtures (opt-in: --xunit true)
  • GdUnit test project (<Name>.gdunit/) - GDScript suites through embedded Godot and MTP (opt-in: --gdunit true)
  • NUnit test project (<Name>.nunit/) - NUnit tests with 2dog.nunit (opt-in: --nunit true)
  • Web host project (<Name>.web/) - Browser (WebAssembly) host that publishes the game as a static site (included by default; --web false to omit)
  • WebXR host (<Name>.webxr/) - Browser host whose page ships the WebXR Layers polyfill for VR (opt-in via --webxr true)
  • MAUI host (<Name>.maui/) - Embedded Godot view for Windows and Android with MAUI overlays (opt-in via --maui true; requires MAUI workloads)
  • Blazor host (<Name>.blazor/) - Blazor Web App: ASP.NET Core server plus a WebAssembly client (Client/) whose page embeds the game through 2dog.blazor's GodotView (opt-in via --blazor true)
  • Avalonia host (<Name>.avalonia/) - Cross-platform GUI embedding the game (opt-in via --avalonia true)
  • Qt Quick host (<Name>.qt/) - QML window on Qt Bridge for C# showing the game through 2dog.qt's GodotView (opt-in via --qt true; building needs CMake, Ninja and a C++ toolchain, and outside win-x64 a Qt 6 install in QtDir)
  • Android host (<Name>.android/) - Experimental APK host (opt-in via --android true; building requires the Android workload, SDK and JDK 17)
  • WinForms host (<Name>.winforms/) - Embeds the game window inside a WinForms form with a Pause button (opt-in via --winforms true; Windows-only at runtime)
  • WinUI 3 host (<Name>.winui/) - Embeds the game window inside a WinUI 3 (Windows App SDK) window (opt-in via --winui true; Windows-only, builds only on Windows)
  • .editorconfig - Standard .NET coding conventions
  • .gitignore - Ignores for .NET and Godot artifacts

Local Development

Installing the Template Locally

# From the repository root
dotnet pack twodog.templates
# Replace <TwoDogVersion> with the version printed by pack:
dotnet new install packages/2dog.templates.<TwoDogVersion>.nupkg

Packing substitutes the source template's version placeholders. Installing the raw templates/twodog directory leaves those placeholders unresolved.

Creating Projects

# Default project (app + Godot project + web host)
dotnet new 2dog -n MyGame

# With an xUnit test project
dotnet new 2dog -n MyGame --xunit true

# GDScript tests, double precision and experimental threaded web
dotnet new 2dog -n MyGame --gdunit true --double-precision true --web-threads true

# Without the web host (all hosts require .NET 10; only browser builds need wasm-tools)
dotnet new 2dog -n MyGame --web false

# With the WebXR browser host (omitted by default)
dotnet new 2dog -n MyGame --webxr true

# With the Blazor Web App host (omitted by default)
dotnet new 2dog -n MyGame --blazor true

# With the Windows-only WinForms host (omitted by default)
dotnet new 2dog -n MyGame --winforms true

# With the Qt Quick host (omitted by default; needs CMake, Ninja and a C++ toolchain)
dotnet new 2dog -n MyGame --qt true

Uninstalling the Template

dotnet new uninstall 2dog.templates

Template Structure

templates/
└── twodog/                        # Template content = the Godot project root
    ├── .template.config/
    │   └── template.json          # Template configuration
    ├── Company.Product1.slnx      # The single solution, next to project.godot
    ├── Company.Product1.csproj    # Godot project (Godot.NET.Sdk)
    ├── project.godot
    ├── main.tscn
    ├── export_presets.cfg         # Web preset for the wasm host
    ├── global.json                # Wasm-capable SDK pin (--web false to omit)
    ├── Company.Product1.2dog/     # Desktop host
    │   ├── .gdignore
    │   ├── Company.Product1.2dog.csproj
    │   ├── Program.cs
    │   └── app.manifest
    ├── Company.Product1.xunit/    # xUnit test project (opt-in: --xunit true)
    │   ├── .gdignore
    │   ├── Company.Product1.xunit.csproj
    │   ├── BasicTests.cs
    │   └── xunit.runner.json
    ├── Company.Product1.web/      # Browser (wasm) host (default; --web false to omit)
    │   ├── .gdignore
    │   ├── Company.Product1.web.csproj
    │   ├── Program.cs
    │   ├── global.json            # Same SDK pin as the root, for runs started in here
    │   └── wwwroot/index.html
    ├── Company.Product1.webxr/    # WebXR browser host (opt-in; --webxr true to include)
    │   ├── .gdignore
    │   ├── Company.Product1.webxr.csproj
    │   ├── Program.cs
    │   ├── global.json
    │   └── wwwroot/               # index.html + vendored webxr-layers-polyfill.min.js
    ├── Company.Product1.blazor/   # Blazor Web App host (opt-in; --blazor true to include)
    │   ├── .gdignore
    │   ├── Company.Product1.blazor.csproj   # ASP.NET Core server
    │   ├── Program.cs
    │   ├── Components/            # App.razor, Routes.razor, Error page
    │   ├── wwwroot/               # app.css, favicon
    │   ├── global.json
    │   └── Client/                # Blazor WebAssembly client (links Godot, hosts GodotView)
    │       ├── Company.Product1.blazor.Client.csproj
    │       ├── Program.cs
    │       └── Pages/Home.razor
    ├── Company.Product1.qt/       # Qt Quick host (opt-in; --qt true to include)
    │   ├── .gdignore
    │   ├── Company.Product1.qt.csproj
    │   ├── Program.cs
    │   ├── GameControls.cs        # overlay state the QML binds to
    │   ├── Main.qml               # ApplicationWindow with the GodotView and the overlay
    │   └── app.manifest
    ├── Company.Product1.winforms/ # WinForms host (opt-in; --winforms true to include)
    │   ├── .gdignore
    │   ├── Company.Product1.winforms.csproj
    │   ├── Program.cs
    │   ├── MainForm.cs
    │   └── app.manifest
    ├── Company.Product1.winui/    # WinUI 3 host (opt-in; --winui true to include)
    │   ├── .gdignore
    │   ├── Company.Product1.winui.csproj
    │   ├── Program.cs
    │   ├── App.cs
    │   ├── MainWindow.cs
    │   └── app.manifest
    ├── .editorconfig
    └── .gitignore

The host csprojs point <GodotProjectDir> at the parent directory (..) and reference ../Company.Product1.csproj; the Godot csproj excludes the nested host folders via DefaultItemExcludes. The solution gives the web host ActiveCfg-only entries (no .Build.0) so "Build Solution" works without the wasm-tools workload – the web host is built explicitly with dotnet publish.

Template Parameters

Parameter Type Default Description
--xunit bool false Include a test project with xUnit (v3) and 2dog.xunit collection fixtures
--nunit bool false Include an NUnit test project with 2dog.nunit
--web bool true Include a browser (WebAssembly) host project (building it requires a .NET 10+ SDK with the wasm-tools workload)
--webxr bool false Include a browser host preconfigured for WebXR: its page ships the WebXR Layers polyfill (same wasm-tools requirement as --web)
--blazor bool false Include a Blazor Web App host (server + WebAssembly client embedding the game; same wasm-tools requirement as --web)
--skipRestore bool false Skip automatic NuGet restore after creation

Symbol Replacements

The template uses Company.Product1 as the source name, which gets replaced with your project name:

  • Company.Product1 → Your project name in namespace positions (namespace, using, RootNamespace) and in file names. dotnet new gives file contents its safe_namespace form (GWJ-97 → GWJ_97) and file names the name verbatim; the 2dog tool does the same.
  • TPLRAWNAME → Your project name verbatim: paths and folder names inside files (DefaultItemExcludes, the solution), project.godot, TrimmerRootAssembly, window titles and the Engine label. Anything that must match a file or assembly name uses this token, never Company.Product1.

Packaging

The template content in twodog/ is the single source of truth and ships two ways:

  • Bundled in 2dog.templates (packed from twodog.templates/twodog.templates.csproj) as dotnet new template content under content/twodog/, so dotnet new install 2dog.templates registers the template.
  • Embedded as resources into the 2dog tool assembly, which scaffolds the same content via 2dog new and 2dog add. The tool substitutes the rename tokens itself, including the host folder token (Company.Product1.2dog and friends), so hosts can live in freely named folders.

When packing, the version placeholders in template.json are substituted automatically.

Installing from NuGet

dotnet new install 2dog.templates

If you previously installed the template from 2dog, run dotnet new uninstall 2dog before installing 2dog.templates. This leaves the 2dog tool installed.

Known Limitations

Test Project Requires 2dog.xunit Package

The optional xUnit test project references 2dog.xunit, which needs to be packaged and published separately.

To make it resolve:

  1. Package 2dog.xunit as a NuGet package (it depends on 2dog.engine, which carries the fixtures)
  2. Publish it to NuGet or a local feed
  3. Ensure it's available when creating projects

Alternatively, for local development:

  • Omit --xunit and --nunit when creating the project
  • Manually add a test project with project references to local 2dog projects

Web Host Requires .NET 10+ and wasm-tools

The web host project (included by default) targets net10.0 with RuntimeIdentifier=browser-wasm. Building/publishing it requires a .NET 10+ SDK with the wasm-tools workload (dotnet workload install wasm-tools). The rest of the solution builds fine without it; create with --web false to omit the project entirely. The opt-in WebXR (--webxr true) and Blazor (--blazor true) hosts have the same requirements.

Template Configuration

The template is defined in .template.config/template.json:

{
  "identity": "outfox.2dog.Template",
  "name": "2dog Application",
  "shortName": "2dog",
  "sourceName": "Company.Product1",
  "symbols": {
    "tests": {
      "type": "parameter",
      "datatype": "bool",
      "description": "Include a test project",
      "defaultValue": "true"
    },
    "web": {
      "type": "parameter",
      "datatype": "bool",
      "description": "Include a browser (WebAssembly) host project",
      "defaultValue": "true"
    },
    "webxr": {
      "type": "parameter",
      "datatype": "bool",
      "description": "Include a browser host preconfigured for WebXR",
      "defaultValue": "false"
    }
  }
}

(Abridged - see the file for the full symbol list, including winforms, winui, avalonia, blazor, and the version placeholders.)

Testing Changes

After modifying the template:

  1. Pack and reinstall: run dotnet pack twodog.templates, then install the resulting packages/2dog.templates.<TwoDogVersion>.nupkg with dotnet new install --force.

  2. Test project creation:

    mkdir test_project
    cd test_project
    dotnet new 2dog -n TestApp -o TestApp
    cd TestApp
    dotnet build
    dotnet run --project TestApp.2dog
    

The template already generates a solution with Debug/Release/Editor configurations. Browser, Android and WinUI hosts are excluded from ordinary solution builds and are built explicitly when needed.

Future Enhancements

Potential improvements for the template:

  • Add --empty option for projects without sample Godot content
  • Add --minimal option for absolute bare minimum
  • Optional CI/CD workflow files (GitHub Actions, etc.)
  • Optional Docker support

This package has no dependencies.

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
4.7.2.132 0 10/21/2026
4.7.2.127 36 10/20/2026
Loading failed