Upgrading to 3.0.0

Turian 3.0.0 groups the breaking changes since 2.0 into one release, so a 2.x project upgrades once. Each section below says what changed, who is affected and what to do. Most game projects only need models, and only if they use .obj files. The rest affects Studio plugins, custom themes and code that draws with Guinevere directly. Scene, prefab and data asset files keep their ids and need no conversion.

Change Who is affected Effort
The renderer is a brick projects that removed default bricks, code that used renderer types directly usually nothing
The project asset every project, automatically nothing; keep a backup
Models: glTF inside, OBJ as a brick projects with .obj models, exported games, mesh tooling one brick and a rebuild
Themes are .pss sheets custom Studio themes, plugins that read theme colors rewrite the theme as a sheet
Gaya settings and panel headers Studio plugins with settings pages or tab-strip widgets move metadata into attributes
Guinevere 6 drawing and styling code that draws with Guinevere or Excalibur directly split color and fluent calls

The renderer is a brick

What changed: the Vulkan renderer, the window, window input and the GPU asset caches moved out of the engine core into the built-in brick org.mass4.turian.vulkan. The brick is client-only: a server build profile leaves it out, together with every brick that depends on it (such as the UI brick), and the game then runs the headless player.

Who is affected:

  • Most projects are not. The renderer is a default dependency: every project gets it without declaring it, and new projects list it in Bricks/manifest.json too.
  • Projects that edit their manifest by hand and want to stay windowless must opt out explicitly, by mapping the id to null. Removing or disabling the brick in the Bricks panel does this for you.
  • Scripts and plugins that referenced renderer classes directly. Scene components now reach the GPU only through the IRenderDevice service.

What to do:

  1. Open the project in Studio 3.0 once and check that the Bricks panel lists org.mass4.turian.vulkan.

  2. Replace direct references to renderer types with an injected IRenderDevice. The brick's types keep the Turian.Engine.Core namespace, so using lines do not change.

  3. To leave the renderer out on purpose, declare:

    {
      "dependencies": {
        "org.mass4.turian.vulkan": null
      }
    }
    

The project asset

What changed: Assets/Project.dataasset now registers the project's settings assets and build profiles and records the engine version that last saved the project. Only registered settings count.

Who is affected: every 2.x project, automatically. When Studio or turian-cli opens an older project, it converts it: a leftover project.data is moved into settings assets and renamed to project.data.bak, and a project without a project asset gets one, registering the settings it already has.

What to do:

  1. Commit or back up the project before opening it with 3.0. The conversion is one-way: a 2.x Studio does not read the project asset.
  2. Open the project, then commit Assets/Project.dataasset and any new files under Assets/Settings.
  3. If Studio reports duplicate or unreadable settings, keep one asset per kind registered. A second settings asset of the same kind stays unregistered and can be used by a build profile as an override.

Models: glTF inside, OBJ as a brick

What changed: imported models are now cached and shipped as glTF 2.0 / GLB geometry instead of Turian's former .ammesh format. Wavefront OBJ import moved into the optional, editor-only brick org.mass4.turian.obj. glTF, GLB and FBX import stay in the engine.

Who is affected: projects with .obj models, exported games and OAP packages built with 2.x, and editor code that read or wrote mesh caches.

What to do:

  1. Back up the original model sources and their .meta files. Keep their ids and import settings.

  2. If the project has .obj models, install the OBJ brick from the Bricks panel or with:

    turian-cli brick add <project> org.mass4.turian.obj builtin:org.mass4.turian.obj
    

    Without it, Studio reports each .obj as unsupported and tells you how to install the brick or convert the file.

  3. Reopen the project. The new importer versions recreate the old caches as GLB from the original sources; scenes keep pointing at the same model ids.

  4. Rebuild every exported game and OAP package. The new runtime cannot load a package that contains only .ammesh geometry, so recover the original sources before upgrading if you only have a built package.

  5. In editor code, replace MeshBlob, MeshBlobWriter, MeshBlobBaker and Turian.Editor.Obj.ObjModelBuilder with GltfModelReader to read geometry and AssimpModelConverter.ConvertToGlb to convert sources, then rebuild your plugins.

To leave OBJ behind entirely, export each model to glTF/GLB or FBX, move its .meta file next to the new source so the asset keeps its id, check that scenes still reference it, and only then delete the .obj.

GLB and glTF sources are imported unchanged, with their materials and images packaged as before. Sparse accessors and external buffers are supported; compressed geometry (Draco, meshopt) is not. .max and .blend files still need an export to an interchange format. The OBJ importer keeps its 2.x behavior: faces need normals and texture coordinates, and material libraries and object hierarchies are not imported.

Themes are .pss sheets

What changed: Studio's appearance is now four independent choices: a look (the shape of every control), a color theme, an icon set and fonts. Color themes are .pss style sheets, compiled into ThemeTokens and reloaded live while you edit them. The default look is Material 3. The C# StudioTheme record was deprecated in 3.0.0 and has since been removed.

Who is affected: anyone with a custom Studio theme, and plugins that read theme colors or call IThemeService.

What to do:

  1. Rewrite a custom theme as a sheet of $token = value; declarations that imports the base sheet:

    @const theme-id = "user.me.midnight";
    @const theme-name = "Midnight";
    @const theme-kind = dark;
    @import "gaya.base";
    
    $surface-window = #10131a;
    $surface-panel = #161a23;
    $ink = #d8dde8;
    $accent = #6c9cff;
    

    Copy the full list of tokens from a built-in theme, such as gaya.dark.pss, and change the ones you need.

  2. Put the sheet in ~/.gaya/themes, or package it as a brick with turian-cli brick new <id> --kind theme. Check it first with turian-cli theme verify <path>, which reports unknown or mistyped tokens and low text contrast.

  3. To adjust a few tokens over whatever theme is active, use ~/.gaya/theme.user.pss instead of a whole theme.

  4. In plugin code, update the IThemeService calls:

    2.x 3.0
    Themes ColorThemes (and Looks, IconThemes)
    Current (a StudioTheme) Current (compiled ThemeTokens)
    CommittedName CommittedColorTheme
    Apply(name), Preview(name) ApplyColorTheme(id), PreviewColorTheme(id)
    Register(StudioTheme) Register(ThemeSource) with a .pss sheet
    StudioThemeExtensions.ToDockTheme, ToControlPalette removed: docking and controls read the theme tokens themselves

The saved theme choice carries over: a name written by 2.x is still accepted where an id is expected. The Themes page covers looks, icon sets and fonts.

Gaya settings and panel headers

What changed: a settings page is now configured entirely by attributes on its class. Separately, the widgets a panel shows in its dock group's tab strip are drawn by the panel itself.

Who is affected: Studio plugins and editor scripts that add settings pages or tab-strip widgets.

What to do:

  1. Replace MASS4.Attributes.EditorSettingAttribute with Gaya.EditorSettingAttribute from MASS4.Gaya.Attributes. Write [Gaya.EditorSetting(...)] when both namespaces are imported; regenerated Turian projects provide an alias for [EditorSetting].

  2. Move the page's path, id, description, order, scope and visibility from the SettingsPageDescriptor into the class attribute, and register the instance itself:

    [Gaya.EditorSetting("General/Performance", Id = "example.performance")]
    public sealed class PerformanceSettings
    {
        [Gaya.EditorSetting("Cap FPS")]
        public int CapFps { get; set; } = 60;
    }
    
    // 2.x: settings.Register(new SettingsPageDescriptor(...));
    ctx.Settings.Register(new PerformanceSettings());
    

    Keep each page's existing id, or users lose their saved preferences. Workspace = true stores values with the project, and Hidden = true keeps a page out of the Settings list.

  3. Move TabStripChromeDescriptor contributions into the panel's RenderHeader(Gui, PanelHeaderContext) method. IPluginContext.TabStripChrome is gone; application-wide chrome stays on IPluginContext.Chrome.

  4. Rebuild plugins and scripts against the 3.0 assemblies.

Guinevere 6 drawing and styling

What changed: Studio 3.0 runs on Guinevere 6, whose one breaking release changed how drawing calls return and how controls are styled.

Who is affected: plugins, editor panels and games that draw with Guinevere or use Excalibur controls directly. In-game UI built with .ui documents and .uss sheets is not affected.

What to do:

  1. Drawing. A drawing call with an explicit color now draws directly and returns nothing. For chained effects, call the overload without a color and style the returned shape:

    gui.DrawRect(rect, Color.Blue);                    // direct
    gui.DrawRect(rect, 6).SolidColor(Color.Blue)       // fluent
        .InnerShadow(0x00000099, 4);
    

    gui.DrawBackgroundRect() now returns a white fluent background; pass a color, or null, for a direct one.

  2. Default look. Excalibur controls default to Material 3. To keep the previous look in your own Gui, call ExcaliburStyles.SetBaseSheet(gui, ExcaliburStyles.Classic).

  3. Style sheets. Excalibur is styled by .pss sheets from the MASS4.Guinevere.Styling package instead of .uss. Colors are tokens: replace ControlPalette with a token sheet passed to ExcaliburStyles.SetTheme, and read colors with ExcaliburStyles.TokenColor(gui, "text"). Shadows follow CSS box-shadow semantics, so check offsets and spread on custom shadows.

  4. Identity and data. Node ids are automatic and numeric; explicit ids remain usable as style sheet selectors. GUI data has scopes, and animations are keyed and sampled once per frame. Two animation calls on the same source line are now separate animations, so give an animation a name when sharing it between call sites is intentional.

  5. Rebuild against the 3.0 assemblies.

Coming from 2.x, in short

2.x 3.0.0
renderer in the engine core org.mass4.turian.vulkan, a default, client-only brick
settings found by searching Assets/ settings registered in Assets/Project.dataasset
.ammesh caches GLB caches
.obj import built in org.mass4.turian.obj brick
StudioTheme in C# .pss theme sheet in ~/.gaya/themes or a brick
SettingsPageDescriptor [Gaya.EditorSetting] on the class
TabStripChromeDescriptor IPanel.RenderHeader
gui.DrawRect(rect, color).InnerShadow(…) gui.DrawRect(rect).SolidColor(color).InnerShadow(…)

← All docs Edit this page