diff --git a/AGENTS.md b/AGENTS.md
new file mode 100644
index 000000000..8cb870037
--- /dev/null
+++ b/AGENTS.md
@@ -0,0 +1,126 @@
+# AGENTS.md
+
+## Repo Purpose
+
+Flax Engine is a modern 3D game engine written in C++ and C#.
+This repository contains the engine, editor, tooling, shaders, tests, assets, and platform-specific sources, excluding NDA-protected platform support.
+
+## High-Level Structure
+
+- `Source/Engine/`: engine runtime code and managed/runtime integration.
+- `Source/Editor/`: editor code in both C++ and C#.
+- `Source/Tools/`: build system and developer tooling, including `Flax.Build`.
+- `Source/Platforms/`: platform-specific code, dependencies, and binaries.
+- `Source/ThirdParty/`: vendored third-party code. Avoid changes here unless the task explicitly requires it.
+- `Source/Engine/Tests/`: native and managed engine tests.
+- `Source/Tools/Flax.Build.Tests/`: .NET tests for the build tool.
+- `Content/`: engine/editor assets.
+- `Development/Scripts/`: helper scripts for project generation and builds.
+
+## Working Assumptions
+
+- Generated solutions and project files are not committed. On a clean clone, generate them first.
+- Git LFS is required. The Windows build scripts explicitly check for LFS-populated files.
+- On Windows, the main entry points are `GenerateProjectFiles.bat` and `Development\Scripts\Windows\CallBuildTool.bat`.
+- Prefer edits in `Source/Engine`, `Source/Editor`, `Source/Tools`, or docs. Do not modify `Binaries/`, `Cache/`, or generated project files unless the task explicitly targets generated output.
+
+## Windows Setup And Build
+
+Use these commands from the repo root.
+
+Generate project files:
+
+```powershell
+.\GenerateProjectFiles.bat -vs2022 -log -verbose -printSDKs -dotnet=8
+```
+
+Alternative default generation:
+
+```powershell
+.\GenerateProjectFiles.bat
+```
+
+Build the editor target:
+
+```powershell
+.\Development\Scripts\Windows\CallBuildTool.bat -build -log -dotnet=8 -arch=x64 -platform=Windows -configuration=Development -buildtargets=FlaxEditor
+```
+
+Run the editor:
+
+```powershell
+.\Binaries\Editor\Win64\Development\FlaxEditor.exe
+```
+
+Visual Studio workflow after generation:
+
+- Open `Flax.sln`.
+- Use solution configuration `Editor.Development` and platform `Win64`.
+- Set `Flax` or `FlaxEngine` as the startup project.
+
+## Tests And Validation
+
+The checked-in CI workflow in `.github/workflows/tests.yml` is the most reliable source for current validation commands.
+
+Build native tests:
+
+```powershell
+.\Development\Scripts\Windows\CallBuildTool.bat -build -log -dotnet=8 -arch=x64 -platform=Windows -configuration=Development -buildtargets=FlaxTestsTarget
+```
+
+Run native tests:
+
+```powershell
+.\Binaries\Editor\Win64\Development\FlaxTests.exe -headless
+```
+
+Build Flax.Build tests:
+
+```powershell
+dotnet msbuild Source\Tools\Flax.Build.Tests\Flax.Build.Tests.csproj /m /t:Restore,Build /p:Configuration=Debug /p:Platform=AnyCPU /nologo
+```
+
+Run Flax.Build tests:
+
+```powershell
+dotnet test -f net8.0 Binaries\Tests\Flax.Build.Tests.dll
+```
+
+Run managed engine tests after copying runtime dependencies:
+
+```powershell
+xcopy /y Binaries\Editor\Win64\Development\FlaxEngine.CSharp.dll Binaries\Tests
+xcopy /y Binaries\Editor\Win64\Development\FlaxEngine.CSharp.runtimeconfig.json Binaries\Tests
+xcopy /y Binaries\Editor\Win64\Development\Newtonsoft.Json.dll Binaries\Tests
+dotnet test -f net8.0 Binaries\Tests\FlaxEngine.CSharp.dll
+```
+
+If a change is localized, prefer the narrowest possible target build and only run the relevant tests for that area.
+
+## Style And Conventions
+
+- The root `Source/.editorconfig` sets CRLF line endings, UTF-8, final newline, and spaces for indentation.
+- Use 4 spaces for C++, C#, shaders, and Python. Use 2 spaces for XAML and MSBuild files.
+- Keep the existing copyright header in source files.
+- Public APIs in both C++ headers and C# commonly use XML-style documentation comments such as `/// `.
+- Preserve local file style instead of mass-normalizing. The C# codebase mixes block namespaces and file-scoped namespaces.
+- Follow existing naming patterns: PascalCase for types and public members; private C# fields often use `_camelCase`.
+- In C++ headers, prefer forward declarations where practical and keep includes minimal.
+
+## Build System Notes
+
+- `FlaxEditor` is the main standalone editor target.
+- `FlaxGame` is the standalone game target.
+- `FlaxTestsTarget` builds the native test executable.
+- `Flax.Build` supports project generation switches such as `-vs2022`, `-vs2026`, `-vscode`, and `-rider`.
+- `GenerateProjectFiles.bat` also builds C# bindings for `FlaxEditor` on Windows.
+
+## Agent Guidance
+
+- Treat `.github/workflows/tests.yml` as the source of truth for CI-backed validation.
+- Do not assume generated artifacts already exist in the repo.
+- Avoid broad style-only rewrites.
+- Avoid touching `Source/ThirdParty/` unless explicitly requested.
+- If a change affects developer workflow or build/test steps, update the relevant root docs as part of the task.
+- No dedicated repo-wide formatter or linter command is checked in. Prefer build and test validation over inventing formatting steps.
+- PVS-Studio is mentioned in `README.md`, but it is not wired here as a standard local validation command.
diff --git a/Source/Editor/Content/GUI/ContentView.cs b/Source/Editor/Content/GUI/ContentView.cs
index 4928722b6..5382bd731 100644
--- a/Source/Editor/Content/GUI/ContentView.cs
+++ b/Source/Editor/Content/GUI/ContentView.cs
@@ -384,7 +384,7 @@ namespace FlaxEditor.Content.GUI
/// Selects the specified item.
///
/// The item.
- /// If set to true item will be added to the current selection. Otherwise selection will be cleared before.
+ /// If set to true item will be added to the current selection. Otherwise, selection will be cleared before.
public void Select(ContentItem item, bool additive = false)
{
if (item == null)
diff --git a/Source/Editor/Content/Import/ImportFilesDialog.cs b/Source/Editor/Content/Import/ImportFilesDialog.cs
index c9b1b8c4f..f245f49ee 100644
--- a/Source/Editor/Content/Import/ImportFilesDialog.cs
+++ b/Source/Editor/Content/Import/ImportFilesDialog.cs
@@ -21,6 +21,7 @@ namespace FlaxEditor.Content.Import
{
private TreeNode _rootNode;
private CustomEditorPresenter _settingsEditor;
+ private Tree _tree;
///
/// Gets the entries count.
@@ -106,11 +107,11 @@ namespace FlaxEditor.Content.Import
_settingsEditor.Panel.Parent = splitPanel.Panel2;
// Setup tree
- var tree = new Tree(true)
+ _tree = new Tree(true)
{
Parent = splitPanel.Panel1
};
- tree.RightClick += OnTreeRightClick;
+ _tree.RightClick += OnTreeRightClick;
_rootNode = new TreeNode(false);
for (int i = 0; i < entries.Count; i++)
{
@@ -124,12 +125,12 @@ namespace FlaxEditor.Content.Import
}
_rootNode.Expand();
_rootNode.ChildrenIndent = 0;
- _rootNode.Parent = tree;
- tree.Margin = new Margin(0.0f, 0.0f, -14.0f, 2.0f); // Hide root node
- tree.SelectedChanged += OnSelectedChanged;
+ _rootNode.Parent = _tree;
+ _tree.Margin = new Margin(0.0f, 0.0f, -16.0f, 2.0f); // Hide root node
+ _tree.SelectedChanged += OnSelectedChanged;
// Select the first item
- tree.Select(_rootNode.Children[0] as TreeNode);
+ _tree.Select(_rootNode.Children[0] as TreeNode);
_dialogSize = new Float2(TotalWidth, EditorHeight + splitPanel.Offsets.Height);
}
@@ -257,5 +258,12 @@ namespace FlaxEditor.Content.Import
settings.MinimumSize = new Float2(300, 400);
settings.HasSizingFrame = true;
}
+
+ ///
+ public override void Focus()
+ {
+ base.Focus();
+ _tree.SelectedNode?.Focus();
+ }
}
}
diff --git a/Source/Editor/Cooker/GameCooker.cpp b/Source/Editor/Cooker/GameCooker.cpp
index 98cf609a7..969e71b71 100644
--- a/Source/Editor/Cooker/GameCooker.cpp
+++ b/Source/Editor/Cooker/GameCooker.cpp
@@ -239,7 +239,7 @@ String CookingData::GetGameBinariesPath() const
archDir = TEXT("ARM64");
break;
default:
- CRASH;
+ CRASH;
return String::Empty;
}
diff --git a/Source/Editor/Cooker/Steps/ValidateStep.cpp b/Source/Editor/Cooker/Steps/ValidateStep.cpp
index cf7cab4dc..b18994f9b 100644
--- a/Source/Editor/Cooker/Steps/ValidateStep.cpp
+++ b/Source/Editor/Cooker/Steps/ValidateStep.cpp
@@ -69,8 +69,6 @@ bool ValidateStep::Perform(CookingData& data)
return true;
}
- // TODO: validate version
-
AssetInfo info;
if (!Content::GetAssetInfo(gameSettings->FirstScene, info))
{
@@ -79,9 +77,5 @@ bool ValidateStep::Perform(CookingData& data)
}
}
- // TODO: validate more game config
-
- // TODO: validate all input scenes?
-
return false;
}
diff --git a/Source/Editor/Editor.cpp b/Source/Editor/Editor.cpp
index 3806317b3..18bf43a3a 100644
--- a/Source/Editor/Editor.cpp
+++ b/Source/Editor/Editor.cpp
@@ -654,7 +654,7 @@ Window* Editor::CreateMainWindow()
PROFILE_MEM(Editor);
Window* window = Managed->GetMainWindow();
-#if PLATFORM_LINUX || (PLATFORM_MAC && PLATFORM_SDL)
+#if PLATFORM_LINUX || PLATFORM_MAC
// Set window icon
const String iconPath = Globals::BinariesFolder / TEXT("Logo.png");
if (FileSystem::FileExists(iconPath))
diff --git a/Source/Editor/GUI/ContextMenu/ContextMenuBase.cs b/Source/Editor/GUI/ContextMenu/ContextMenuBase.cs
index 3eace0363..3947430f9 100644
--- a/Source/Editor/GUI/ContextMenu/ContextMenuBase.cs
+++ b/Source/Editor/GUI/ContextMenu/ContextMenuBase.cs
@@ -1,8 +1,8 @@
-#if PLATFORM_WINDOWS || PLATFORM_SDL
+#if PLATFORM_WINDOWS || PLATFORM_SDL || PLATFORM_MAC
#define USE_IS_FOREGROUND
#else
#endif
-#if PLATFORM_SDL
+#if PLATFORM_SDL || PLATFORM_MAC
#define USE_SDL_WORKAROUNDS
#endif
// Copyright (c) Wojciech Figat. All rights reserved.
diff --git a/Source/Editor/GUI/Timeline/Tracks/ScriptTrack.cs b/Source/Editor/GUI/Timeline/Tracks/ScriptTrack.cs
index ee0bf5c1f..ae2e4e0c1 100644
--- a/Source/Editor/GUI/Timeline/Tracks/ScriptTrack.cs
+++ b/Source/Editor/GUI/Timeline/Tracks/ScriptTrack.cs
@@ -52,8 +52,67 @@ namespace FlaxEditor.GUI.Timeline.Tracks
///
public Script Script
{
- get => FlaxEngine.Object.TryFind