Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
e91473b
Merge remote-tracking branch 'origin/feature/working-dario' into feat…
ynks Oct 7, 2026
dc49526
game frame limiter
dariormt Oct 9, 2026
e8837d9
Git lock support
ynks Oct 10, 2026
670a1d5
Merge branch 'main' into dev
ynks Oct 10, 2026
2e10bb8
Merge branch 'dev' into feature/git-locks
ynks Oct 10, 2026
3208aee
compute queue
dariormt Oct 10, 2026
4c2bf7f
Merge remote-tracking branch 'origin/dev' into feature/working-dario
dariormt Oct 10, 2026
d1b05e8
Fixed Includes
dariormt Oct 10, 2026
df2d85c
tidi
dariormt Oct 10, 2026
4452246
tidi
dariormt Oct 10, 2026
33182d9
fuck off, just pass already
dariormt Oct 10, 2026
3fe028f
Merge branch 'main' into dev
ynks Oct 10, 2026
c956979
Sliding friction
ynks Oct 10, 2026
c0c4e31
Drag
ynks Oct 11, 2026
596e517
C++ and Lua support
ynks Oct 11, 2026
5952160
optimized voxel volume
dariormt Oct 11, 2026
072b569
Git locks (#337)
ynks Oct 11, 2026
908c02d
Optimized sweep?
ynks Oct 11, 2026
d375b15
Rolling and sliding friction
ynks Oct 11, 2026
68f3c8e
raycast, raymulticast and linecast
ynks Oct 12, 2026
fa0d8f0
Merge remote-tracking branch 'origin/dev' into feature/working-dario
dariormt Oct 12, 2026
0e69a15
Layers
ynks Oct 12, 2026
afc9296
clang-tidy
ynks Oct 12, 2026
ac8c61a
Merge remote-tracking branch 'origin/dev' into feature/destruction
ynks Oct 12, 2026
0edbb4e
fix ci
ynks Oct 13, 2026
a5a3d13
disable tracy on release
ynks Oct 13, 2026
f468f05
Friction and drag (#340)
ynks Oct 13, 2026
d6700a2
Tons of fixes, async compute docs and also compute meshed voxels?
dariormt Oct 13, 2026
b0b31c4
rmlui was the input bug
dariormt Oct 13, 2026
bb7d34e
Material hardness tiers
ynks Oct 13, 2026
5a531a6
Energy density fracture
ynks Oct 13, 2026
71687d4
Lua damage bindings
ynks Oct 13, 2026
c25d86c
Fracture debug overlay
ynks Oct 13, 2026
4064eac
Palette editor rework
ynks Oct 13, 2026
5b1913b
Partial carving
ynks Oct 13, 2026
a87013e
Merge remote-tracking branch 'origin/dev' into hotfix/bugfixes
dariormt Oct 13, 2026
76af6e5
clanking git ssh password
dariormt Oct 13, 2026
dc8c129
I DID THE THING DANTE TOLD ME NOT TO DO AND EVERYTHING IS 10000% BETTER
ynks Oct 13, 2026
a682547
async compute queue system (#338)
dariormt Oct 13, 2026
d353046
Merge branch 'hotfix/bugfixes' into feature/working-dario
dariormt Oct 13, 2026
233ba7b
Merge branch 'feature/destruction' into feature/working-dario
dariormt Oct 13, 2026
71b91ab
mesh shaders semi working
dariormt Oct 14, 2026
9c94944
bugfix
ynks Oct 14, 2026
3f62e8b
clang-tidy ahh errors
ynks Oct 14, 2026
bd01239
retarded ahh format
ynks Oct 14, 2026
f016274
Destruction (#344)
ynks Oct 14, 2026
c427835
You want compromise, how´s this?
dariormt Oct 14, 2026
65e39ac
Merge remote-tracking branch 'origin/dev' into feature/working-dario
dariormt Oct 14, 2026
a47032c
i dont wanna do this nomor
dariormt Oct 15, 2026
675b640
Merge remote-tracking branch 'origin/main' into dev
ynks Oct 15, 2026
40fd98b
reverted uid fix
dariormt Oct 16, 2026
09f968a
optimization stuf
dariormt Oct 16, 2026
b267607
Merge branch 'dev' into feature/working-dario
dariormt Oct 16, 2026
7b5026d
mai bat
dariormt Oct 16, 2026
09cefe4
tidi
dariormt Oct 16, 2026
b3e9a2e
Merge branch 'main' into dev
ynks Oct 16, 2026
20aa079
Meshlets and stuff (#350)
dariormt Oct 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions docs/examples/async_compute/debris.slang
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Mirrors DebrisSimulation::Params
struct Params
{
float dt;
uint count;
};

[[vk::push_constant]]
Params gParams;

// xyz position w radius
[[vk::binding(0, 0)]]
StructuredBuffer<float4> gPrevious;

[[vk::binding(1, 0)]]
RWStructuredBuffer<float4> gCurrent;

// xyz velocity w unused
[[vk::binding(2, 0)]]
RWStructuredBuffer<float4> gVelocities;

static const float3 kGravity = float3(0.0, -9.81, 0.0);

[shader("compute")]
[numthreads(64, 1, 1)]
void integrateMain(uint3 id : SV_DispatchThreadID)
{
const uint i = id.x;
if (i >= gParams.count)
{
return;
}

float4 particle = gPrevious[i];
float3 velocity = gVelocities[i].xyz + kGravity * gParams.dt;
particle.xyz += velocity * gParams.dt;

// Ground plane bounce so the example stays on screen
if (particle.y < particle.w)
{
particle.y = particle.w;
velocity.y = -velocity.y * 0.4;
velocity.xz *= 0.8;
}

gCurrent[i] = particle;
gVelocities[i] = float4(velocity, 0.0);
}
42 changes: 42 additions & 0 deletions docs/examples/async_compute/debris_simulation.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/// @file debris_simulation.cpp
/// @author dario
/// @date 10/10/2026

#include "debris_simulation.hpp"

#include <algorithm>

namespace example {

namespace {
constexpr vk::DeviceSize k_particle_bytes = sizeof(glm::vec4) * DebrisSimulation::k_max_particles;
constexpr uint32_t k_workgroup_size = 64;
}

DebrisSimulation::DebrisSimulation()
: AsyncComputeTask({.shader_uri = "core://shaders/debris.slang", .entries = {"integrateMain"}, .debug_name = "Debris"}) {
// The renderer draws positions and gameplay reads them back. Velocities never leave the task
m_positions = addRingBuffer(k_particle_bytes, true);
m_velocities = addPersistentBuffer(k_particle_bytes);

// Mirrors the bindings in debris.slang
bind(0, m_positions, Copy::previous);
bind(1, m_positions, Copy::current);
bind(2, m_velocities);
}

void DebrisSimulation::spawn(std::span<const glm::vec4> positions, std::span<const glm::vec4> velocities) {
m_count = static_cast<uint32_t>(std::min({positions.size(), velocities.size(), size_t {k_max_particles}}));
upload(m_positions, positions.first(m_count));
upload(m_velocities, velocities.first(m_count));
}

void DebrisSimulation::step(float dt) {
if (m_count == 0) {
return;
}
const Params params {.dt = dt, .count = m_count};
AsyncComputeTask::step([&](StepContext& ctx) { ctx.dispatch((m_count + k_workgroup_size - 1) / k_workgroup_size, params); });
}

}
49 changes: 49 additions & 0 deletions docs/examples/async_compute/debris_simulation.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/// @file debris_simulation.hpp
/// @author dario
/// @date 10/10/2026

#pragma once

#include <glm/glm.hpp>
#include <span>
#include <toast/renderer/async_compute_task.hpp>

namespace example {

/// Debris particles integrated on the async compute queue
class DebrisSimulation : public renderer::AsyncComputeTask {
public:
static constexpr uint32_t k_max_particles = 65536;

DebrisSimulation();

/// Physics thread before the first step
void spawn(std::span<const glm::vec4> positions, std::span<const glm::vec4> velocities);

/// Physics thread. Returns right away
void step(float dt);

/// Physics thread. Newest finished positions and false until one exists
auto readPositions(std::span<glm::vec4> out) -> bool {
return read(m_positions, out);
}

/// For the render pass. xyz position w radius
[[nodiscard]]
auto positionsId() const -> BufferId {
return m_positions;
}

private:
/// Mirrors debris.slang Params
struct Params {
float dt;
uint32_t count;
};

BufferId m_positions = 0;
BufferId m_velocities = 0;
uint32_t m_count = 0;
};

}
1 change: 1 addition & 0 deletions editor/App.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
<ResourceInclude Source="avares://editor/Resources/AssetBox.axaml" />
<ResourceInclude Source="avares://editor/Resources/ArrayBox.axaml" />
<ResourceInclude Source="avares://editor/Resources/EnumBox.axaml" />
<ResourceInclude Source="avares://editor/Resources/TagBox.axaml" />
</ResourceDictionary.MergedDictionaries>
<conv:PathToBitmapConverter x:Key="PathToBitmapConverter" />
<conv:SeverityToColorConverter x:Key="SeverityToColorConverter" />
Expand Down
95 changes: 75 additions & 20 deletions editor/Assets/AssetBrowserView.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@
<Setter Property="BorderBrush"
Value="{StaticResource Bg5}" />
</Style>
<Style Selector="Border.card-border.locked-other">
<Setter Property="BorderBrush"
Value="{StaticResource Orange}" />
</Style>
<Style Selector="Border.card-border.selected">
<Setter Property="BorderBrush"
Value="{StaticResource Red}" />
Expand Down Expand Up @@ -579,11 +583,17 @@
Height="{Binding Owner.PreviewHeight, FallbackValue=110}"
Background="{x:Static vm:CheckerBrush.Instance}"
CornerRadius="4">
<LucideIcon Kind="Folder"
Size="{Binding Owner.PreviewIconSize, FallbackValue=52}"
VerticalAlignment="Center"
HorizontalAlignment="Center"
StrokeWidth="2.5" />
<Panel>
<LucideIcon Kind="Folder"
Size="{Binding Owner.PreviewIconSize, FallbackValue=52}"
VerticalAlignment="Center"
HorizontalAlignment="Center"
StrokeWidth="2.5" />
<elements:GitChip Status="{Binding GitStatus}"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Margin="0,0,6,6" />
</Panel>
</Border>
<StackPanel Grid.Row="1"
Margin="8,5,8,4"
Expand All @@ -604,6 +614,7 @@
<Border Classes="card-border"
ContextRequested="OnFileContextRequested"
Classes.selected="{ReflectionBinding IsSelected}"
Classes.locked-other="{ReflectionBinding IsLockedByOthers}"
Width="{Binding Owner.CardWidth, FallbackValue=130}"
Height="{Binding Owner.CardHeight, FallbackValue=170}"
CornerRadius="8"
Expand Down Expand Up @@ -718,6 +729,33 @@
</StackPanel>
</MenuItem.Header>
</MenuItem>
<Separator IsVisible="{Binding IsLockable}" />
<MenuItem Command="{Binding Owner.LockCommand}"
CommandParameter="{Binding}"
IsVisible="{Binding CanLock}">
<MenuItem.Header>
<StackPanel Orientation="Horizontal"
Spacing="8">
<LucideIcon Kind="Lock"
StrokeWidth="2.5"
Size="16" />
<TextBlock Text="Lock" />
</StackPanel>
</MenuItem.Header>
</MenuItem>
<MenuItem Command="{Binding Owner.UnlockCommand}"
CommandParameter="{Binding}"
IsVisible="{Binding CanUnlock}">
<MenuItem.Header>
<StackPanel Orientation="Horizontal"
Spacing="8">
<LucideIcon Kind="LockOpen"
StrokeWidth="2.5"
Size="16" />
<TextBlock Text="Unlock" />
</StackPanel>
</MenuItem.Header>
</MenuItem>
<Separator />
<MenuItem Command="{Binding Owner.DeleteCommand}"
CommandParameter="{Binding}"
Expand All @@ -743,30 +781,47 @@
ClipToBounds="True"
CornerRadius="4">
<Panel>
<Image Source="{Binding Thumbnail}"
<Image Source="{Binding DisplayThumbnail}"
IsVisible="{Binding HasThumbnail}"
Stretch="UniformToFill"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" />
<LucideIcon Kind="{Binding Icon}"
<LucideIcon Kind="{Binding DisplayIcon}"
Size="{Binding Owner.PreviewIconSize, FallbackValue=52}"
VerticalAlignment="Center"
HorizontalAlignment="Center"
StrokeWidth="2.5"
Foreground="{Binding TypeColor}"
Foreground="{Binding DisplayIconBrush}"
IsVisible="{Binding !HasThumbnail}" />
<Border VerticalAlignment="Bottom"
HorizontalAlignment="Left"
IsVisible="{Binding Owner.ShowTypeBadge, FallbackValue=True}"
Background="{Binding TypeColor}"
CornerRadius="4"
Padding="6,2"
Margin="6,0,0,6">
<TextBlock Text="{Binding TypeLabel}"
FontSize="10"
FontWeight="Bold"
Foreground="{StaticResource Bg1}" />
</Border>
<LucideIcon Kind="Lock"
Size="{Binding Owner.PreviewIconSize, FallbackValue=52}"
VerticalAlignment="Center"
HorizontalAlignment="Center"
StrokeWidth="3"
Foreground="{StaticResource Orange}"
IsVisible="{Binding ShowLockOverlay}" />
<StackPanel Orientation="Horizontal"
Spacing="4"
VerticalAlignment="Bottom"
HorizontalAlignment="Left"
Margin="6,0,0,6">
<elements:GitChip Kind="LockMine"
IsVisible="{Binding IsLockedByMe}" />
<Border VerticalAlignment="Bottom"
IsVisible="{Binding Owner.ShowTypeBadge, FallbackValue=True}"
Background="{Binding TypeColor}"
CornerRadius="4"
Padding="6,2">
<TextBlock Text="{Binding TypeLabel}"
FontSize="10"
FontWeight="Bold"
Foreground="{StaticResource Bg1}" />
</Border>
</StackPanel>
<elements:GitChip Status="{Binding GitStatus}"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Margin="0,0,6,6" />
</Panel>
</Border>
<!-- Name section -->
Expand Down
53 changes: 52 additions & 1 deletion editor/Assets/AssetBrowserViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
using editor.Assets.Types;
using editor.Components.Modals;
using editor.Engine;
using editor.Git;
using editor.Workspace;
using Lucide.Avalonia;

Expand Down Expand Up @@ -70,6 +71,7 @@ public class AssetBrowserViewModel : Tool, INotifyPropertyChanged, IDisposable {
private readonly HashSet<object> m_selectedItems = [];

private readonly AssetTypeFilter m_unknownFilter;
private readonly GitService? m_git;
private ClipMode m_clipMode;
private List<string> m_clipPaths = []; // real paths
private string? m_preSearchFolderPath;
Expand Down Expand Up @@ -129,13 +131,21 @@ public AssetBrowserViewModel() {
NewAssetCommand = Track(new AsyncRelayCommand<object>(o => CreateNewAsset(o as BaseAsset),
o => o is BaseAsset && CanWriteToSelectedFolder));
ReimportCommand = Track(new AsyncRelayCommand<object>(ReimportAsync, CanReimport));
LockCommand = Track(new AsyncRelayCommand<object>(LockAsync, p => GetFileTargets(p).Any(f => f.CanLock)));
UnlockCommand = Track(new AsyncRelayCommand<object>(UnlockAsync, p => GetFileTargets(p).Any(f => f.CanUnlock)));
SyncTagFilters();
CaptureFolderSettings();
LoadFolders();

// auto-reload whenever the asset database changes
AssetDatabase.ReloadedDatabase += OnDatabaseReloaded;
AssetBrowserSettings.Changed += OnSettingsChanged;

m_git = GitService.Current;
if (m_git is not null) {
m_git.StatusChanged += OnGitChanged;
m_git.LocksChanged += OnGitChanged;
}
}

public static AssetBrowserViewModel? Current { get; private set; }
Expand Down Expand Up @@ -293,6 +303,8 @@ public IReadOnlyList<BreadcrumbItem> BreadcrumbItems {
public ICommand NewNodeGenericCommand { get; }
public ICommand NewAssetCommand { get; }
public ICommand ReimportCommand { get; }
public ICommand LockCommand { get; }
public ICommand UnlockCommand { get; }

public ICommand ManageTagsCommand { get; } = new RelayCommand(() =>
MainWindowViewModel.Current?.OpenProjectSettingsAt(SettingsTab.Editor,
Expand All @@ -303,6 +315,10 @@ public void Dispose() {
ThumbnailService.Updated -= OnThumbnailUpdated;
AssetDatabase.ReloadedDatabase -= OnDatabaseReloaded;
AssetBrowserSettings.Changed -= OnSettingsChanged;
if (m_git is not null) {
m_git.StatusChanged -= OnGitChanged;
m_git.LocksChanged -= OnGitChanged;
}
foreach (var filter in Filters) filter.PropertyChanged -= OnFilterChanged;
foreach (var filter in TagFilters) {
filter.PropertyChanged -= OnTagFilterChanged;
Expand Down Expand Up @@ -968,7 +984,42 @@ private static bool IsEditablePath(string path) {
}

private static bool IsEditable(AssetFile file) {
return IsEditablePath(file.Filepath);
return IsEditablePath(file.Filepath) && !file.IsLockedByOthers;
}

private void OnGitChanged() {
foreach (var root in Folders) NotifyGitChanged(root);
NotifyActionStateChanged();
}

private static void NotifyGitChanged(AssetFolder folder) {
folder.NotifyGitChanged();
foreach (var file in folder.Files) file.NotifyGitChanged();
foreach (var sub in folder.SubFolders) NotifyGitChanged(sub);
}

private List<AssetFile> GetFileTargets(object? param) {
return GetTargets(param).OfType<AssetFile>().ToList();
}

private async Task LockAsync(object? param) {
if (m_git is null) return;
foreach (var file in GetFileTargets(param).Where(f => f.CanLock)) {
var result = await m_git.LockAsync(file.AssetPath);
if (result.Ok) continue;
await App.Modals.ShowError("Cannot lock " + file.Name, result.Message);
break;
}
}

private async Task UnlockAsync(object? param) {
if (m_git is null) return;
foreach (var file in GetFileTargets(param).Where(f => f.CanUnlock)) {
var result = await m_git.UnlockAsync(file.AssetPath, false);
if (result.Ok) continue;
await App.Modals.ShowError("Cannot unlock " + file.Name, result.Message);
break;
}
}

private static bool IsEditable(AssetFolder folder) {
Expand Down
Loading
Loading