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.jsontoo. - 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
IRenderDeviceservice.
What to do:
Open the project in Studio 3.0 once and check that the Bricks panel lists
org.mass4.turian.vulkan.Replace direct references to renderer types with an injected
IRenderDevice. The brick's types keep theTurian.Engine.Corenamespace, sousinglines do not change.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:
- 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.
- Open the project, then commit
Assets/Project.dataassetand any new files underAssets/Settings. - 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:
Back up the original model sources and their
.metafiles. Keep their ids and import settings.If the project has
.objmodels, install the OBJ brick from the Bricks panel or with:turian-cli brick add <project> org.mass4.turian.obj builtin:org.mass4.turian.objWithout it, Studio reports each
.objas unsupported and tells you how to install the brick or convert the file.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.
Rebuild every exported game and OAP package. The new runtime cannot load a package that contains only
.ammeshgeometry, so recover the original sources before upgrading if you only have a built package.In editor code, replace
MeshBlob,MeshBlobWriter,MeshBlobBakerandTurian.Editor.Obj.ObjModelBuilderwithGltfModelReaderto read geometry andAssimpModelConverter.ConvertToGlbto 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:
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.Put the sheet in
~/.gaya/themes, or package it as a brick withturian-cli brick new <id> --kind theme. Check it first withturian-cli theme verify <path>, which reports unknown or mistyped tokens and low text contrast.To adjust a few tokens over whatever theme is active, use
~/.gaya/theme.user.pssinstead of a whole theme.In plugin code, update the
IThemeServicecalls:2.x 3.0 ThemesColorThemes(andLooks,IconThemes)Current(aStudioTheme)Current(compiledThemeTokens)CommittedNameCommittedColorThemeApply(name),Preview(name)ApplyColorTheme(id),PreviewColorTheme(id)Register(StudioTheme)Register(ThemeSource)with a.psssheetStudioThemeExtensions.ToDockTheme,ToControlPaletteremoved: 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:
Replace
MASS4.Attributes.EditorSettingAttributewithGaya.EditorSettingAttributefromMASS4.Gaya.Attributes. Write[Gaya.EditorSetting(...)]when both namespaces are imported; regenerated Turian projects provide an alias for[EditorSetting].Move the page's path, id, description, order, scope and visibility from the
SettingsPageDescriptorinto 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 = truestores values with the project, andHidden = truekeeps a page out of the Settings list.Move
TabStripChromeDescriptorcontributions into the panel'sRenderHeader(Gui, PanelHeaderContext)method.IPluginContext.TabStripChromeis gone; application-wide chrome stays onIPluginContext.Chrome.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:
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, ornull, for a direct one.Default look. Excalibur controls default to Material 3. To keep the previous look in your own
Gui, callExcaliburStyles.SetBaseSheet(gui, ExcaliburStyles.Classic).Style sheets. Excalibur is styled by
.psssheets from theMASS4.Guinevere.Stylingpackage instead of.uss. Colors are tokens: replaceControlPalettewith a token sheet passed toExcaliburStyles.SetTheme, and read colors withExcaliburStyles.TokenColor(gui, "text"). Shadows follow CSSbox-shadowsemantics, so check offsets and spread on custom shadows.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.
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(…) |