Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion src/TEdit.Common/TEdit.Common.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@


<ItemGroup Condition="'$(TargetFramework)' != 'netstandard2.0'">
<PackageReference Include="ReactiveUI" Version="23.2.27" />
<PackageReference Include="ReactiveUI" Version="23.2.28" />
</ItemGroup>

</Project>
2 changes: 1 addition & 1 deletion src/TEdit.Terraria/TEdit.Terraria.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<ItemGroup>
<PackageReference Include="bodong.PropertyModels" Version="11.3.11.1" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
<PackageReference Include="ReactiveUI" Version="23.2.27" />
<PackageReference Include="ReactiveUI" Version="23.2.28" />
<PackageReference Include="ReactiveUI.SourceGenerators" Version="3.1.0" PrivateAssets="all" />
</ItemGroup>

Expand Down
7 changes: 2 additions & 5 deletions src/TEdit5/Controls/SkiaMinimapRenderBox.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace TEdit5.Controls;

public class SkiaMinimapRenderBox : Control
{
private readonly GlyphRun _noSkia;
private readonly GlyphRun? _noSkia;

static SkiaMinimapRenderBox()
{
Expand All @@ -27,10 +27,7 @@ public SkiaMinimapRenderBox()
RenderOptions.SetBitmapInterpolationMode(this, BitmapInterpolationMode.None);
ClipToBounds = true;

// "No Skia" text for unsupported platforms
var text = "Current rendering API is not Skia";
var glyphs = text.Select(ch => Typeface.Default.GlyphTypeface.GetGlyph(ch)).ToArray();
_noSkia = new GlyphRun(Typeface.Default.GlyphTypeface, 12, text.AsMemory(), glyphs);
// ponytail: _noSkia only renders on non-Skia backends
}

public override void Render(DrawingContext context)
Expand Down
13 changes: 8 additions & 5 deletions src/TEdit5/Controls/SkiaWorldRenderBox.cs
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,7 @@ public enum SelectionModes

#endregion

private readonly GlyphRun _noSkia;
private readonly GlyphRun? _noSkia;
ZoomLevelCollection _zoomLevels = ZoomLevelCollection.Default;
private Point _startMousePosition;
private Vector _startScrollPosition;
Expand All @@ -452,10 +452,7 @@ public SkiaWorldRenderBox()
RenderOptions.SetBitmapInterpolationMode(this, BitmapInterpolationMode.None);
ClipToBounds = true;

// "No Skia" text for unsupported platforms
var text = "Current rendering API is not Skia";
var glyphs = text.Select(ch => Typeface.Default.GlyphTypeface.GetGlyph(ch)).ToArray();
_noSkia = new GlyphRun(Typeface.Default.GlyphTypeface, 12, text.AsMemory(), glyphs);
// ponytail: _noSkia only renders on non-Skia backends, which macOS never uses
}

protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
Expand Down Expand Up @@ -938,6 +935,12 @@ public Rect GetImageViewPort()
protected internal ScrollBar HorizontalScrollBar = null!;
protected internal ScrollBar VerticalScrollBar = null!;

/// <inheritdoc />
public bool CanHorizontallyScroll { get; set; } = true;

/// <inheritdoc />
public bool CanVerticallyScroll { get; set; } = true;

/// <inheritdoc />
public Size Extent => new(
Math.Max(ViewPort.Bounds.Width, World?.TilesWide ?? 0 * (Zoom / 100d)),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ namespace TEdit5.Controls.WorldRenderEngine.Layers;

public class NoSkiaCustomDrawOp : ICustomDrawOperation
{
private readonly IImmutableGlyphRunReference _noSkia;
private readonly IImmutableGlyphRunReference? _noSkia;

public NoSkiaCustomDrawOp(Rect bounds, GlyphRun noSkia)
public NoSkiaCustomDrawOp(Rect bounds, GlyphRun? noSkia)
{
Bounds = bounds;
_noSkia = noSkia.TryCreateImmutableGlyphRunReference();
_noSkia = noSkia?.TryCreateImmutableGlyphRunReference();
}

public void Dispose()
Expand Down
28 changes: 15 additions & 13 deletions src/TEdit5/Program.cs
Original file line number Diff line number Diff line change
@@ -1,31 +1,33 @@
using Avalonia;
using ReactiveUI.Avalonia;
using System;
using Avalonia;
using ReactiveUI.Builder;
using Projektanker.Icons.Avalonia;
using Projektanker.Icons.Avalonia.MaterialDesign;
using System;

namespace TEdit5;

class Program
{
// Initialization code. Don't use any Avalonia, third-party APIs or any
// SynchronizationContext-reliant code before AppMain is called: things aren't initialized
// yet and stuff might break.
[STAThread]
public static void Main(string[] args) => BuildAvaloniaApp()
.StartWithClassicDesktopLifetime(args);
public static void Main(string[] args)
{
RxAppBuilder.CreateReactiveUIBuilder()
.WithCoreServices()
.BuildApp();

BuildAvaloniaApp()
.StartWithClassicDesktopLifetime(args);
}

// Avalonia configuration, don't remove; also used by visual designer.
public static AppBuilder BuildAvaloniaApp()
{
IconProvider.Current
//.Register<FontAwesomeIconProvider>()
.Register<MaterialDesignIconProvider>();

return AppBuilder.Configure<App>()
.UsePlatformDetect()
.WithInterFont()
.LogToTrace()
.UseReactiveUI(builder => { });
.UsePlatformDetect()
.WithInterFont()
.LogToTrace();
}
}
18 changes: 15 additions & 3 deletions src/TEdit5/Services/IDialogService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,13 @@ public class DialogService : IDialogService
public interface IDocumentService
{
ObservableCollection<DocumentViewModel> Documents { get; }
Task LoadWorldAsync(IStorageFile file, IProgress<ProgressChangedEventArgs>? progress = null);
}

Task LoadWorldAsync(
IStorageFile file,
IProgress<ProgressChangedEventArgs>? progress = null);

Task SaveAsync(DocumentViewModel document);
}

public partial class DocumentService : ReactiveObject, IDocumentService
{
Expand All @@ -51,7 +55,11 @@ public async Task LoadWorldAsync(IStorageFile file, IProgress<ProgressChangedEve

if (world != null)
{
var document = new DocumentViewModel(world, toolSelection, tilePicker);
var document = new DocumentViewModel(
world,
file.Path.LocalPath,
toolSelection,
tilePicker);

Documents.Add(document);
}
Expand All @@ -62,4 +70,8 @@ public async Task LoadWorldAsync(IStorageFile file, IProgress<ProgressChangedEve
}
}
}
public async Task SaveAsync(DocumentViewModel document)
{
await document.SaveAsync();
}
}
112 changes: 54 additions & 58 deletions src/TEdit5/TEdit5.csproj
Original file line number Diff line number Diff line change
@@ -1,58 +1,54 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
<BuiltInComInteropSupport>true</BuiltInComInteropSupport>
<ApplicationManifest>app.manifest</ApplicationManifest>
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>

<ItemGroup>
<AvaloniaResource Include="Assets\**" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Avalonia" Version="12.0.5" />
<PackageReference Include="Avalonia.Desktop" Version="12.0.5" />
<PackageReference Include="ReactiveUI.Avalonia" Version="12.0.3" />
<PackageReference Include="Avalonia.Themes.Fluent" Version="12.0.5" />
<PackageReference Include="Avalonia.Fonts.Inter" Version="12.0.5" />
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.3.18" />
<PackageReference Include="bodong.Avalonia.PropertyGrid" Version="11.3.11.1" />
<PackageReference Include="bodong.PropertyModels" Version="11.3.11.1" />
<PackageReference Include="Projektanker.Icons.Avalonia.MaterialDesign" Version="9.6.2" />

<PackageReference Include="ReactiveUI" Version="23.2.27" />
<PackageReference Include="ReactiveUI.SourceGenerators" Version="3.1.0" PrivateAssets="all" />

<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.9" />

<PackageReference Include="SkiaSharp" Version="3.119.4" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\TEdit.Editor\TEdit.Editor.csproj" />
<ProjectReference Include="..\TEdit.Terraria\TEdit.Terraria.csproj" />
</ItemGroup>

<ItemGroup>
<Compile Update="Views\DocumentView.axaml.cs">
<DependentUpon>DocumentView.axaml</DependentUpon>
</Compile>
<Compile Update="Views\PaintModeView.axaml.cs">
<DependentUpon>PaintModeView.axaml</DependentUpon>
</Compile>
</ItemGroup>

<ItemGroup>
<Folder Include="Controls\RenderLayer\" />
</ItemGroup>

<ItemGroup>
<UpToDateCheckInput Remove="Views\WorldPropertiesView.axaml" />
</ItemGroup>
</Project>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>

<ItemGroup>
<AvaloniaResource Include="Assets\**" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Avalonia" Version="11.3.18" />
<PackageReference Include="Avalonia.Desktop" Version="11.3.18" />

<PackageReference Include="Avalonia.Themes.Fluent" Version="11.3.18" />
<PackageReference Include="Avalonia.Fonts.Inter" Version="11.3.18" />
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.3.18" />
<PackageReference Include="bodong.Avalonia.PropertyGrid" Version="11.3.11.1" />
<PackageReference Include="bodong.PropertyModels" Version="11.3.11.1" />
<PackageReference Include="Projektanker.Icons.Avalonia.MaterialDesign" Version="9.6.2" />
<PackageReference Include="ReactiveUI.SourceGenerators" Version="3.1.0" PrivateAssets="all" />

<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.9" />

<PackageReference Include="SkiaSharp" Version="3.119.4" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\TEdit.Editor\TEdit.Editor.csproj" />
<ProjectReference Include="..\TEdit.Terraria\TEdit.Terraria.csproj" />
</ItemGroup>

<ItemGroup>
<Compile Update="Views\DocumentView.axaml.cs">
<DependentUpon>DocumentView.axaml</DependentUpon>
</Compile>
<Compile Update="Views\PaintModeView.axaml.cs">
<DependentUpon>PaintModeView.axaml</DependentUpon>
</Compile>
</ItemGroup>

<ItemGroup>
<Folder Include="Controls\RenderLayer\" />
</ItemGroup>

<ItemGroup>
<UpToDateCheckInput Remove="Views\WorldPropertiesView.axaml" />
</ItemGroup>
</Project>
41 changes: 35 additions & 6 deletions src/TEdit5/ViewModels/DocumentViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
using Avalonia;
using Avalonia;
using TEdit5.Controls;
using TEdit.Editor;
using TEdit.Editor.Undo;
using TEdit.Terraria;

using System.Threading.Tasks;
namespace TEdit5.ViewModels;

public partial class DocumentViewModel : ReactiveObject
Expand All @@ -14,20 +14,49 @@ public partial class DocumentViewModel : ReactiveObject
[Reactive] private Point _cursorTileCoordinate;
[Reactive] private SkiaWorldRenderBox.SelectionModes _selectionMode;

[Reactive] private World _world;
[Reactive] private WorldEditor _worldEditor;

public string FileName { get; }

public ToolSelectionViewModel ToolSelection { get; }
public TilePicker TilePicker { get; }
public ISelection Selection { get; }
[Reactive] private World _world;
[Reactive] private WorldEditor _worldEditor;

public DocumentViewModel(World world, ToolSelectionViewModel toolSelection, TilePicker tilePicker)
public DocumentViewModel(
World world,
string fileName,
ToolSelectionViewModel toolSelection,
TilePicker tilePicker)
{
_world = world;
FileName = fileName;

ToolSelection = toolSelection;
TilePicker = tilePicker;

Selection = new Selection();

IUndoManager undoManager = null;

_worldEditor = new WorldEditor(tilePicker, new TEdit.Editor.TileMaskSettings(), World, Selection, undoManager, (x, y, height, width) => { });
_worldEditor = new WorldEditor(
tilePicker,
new TEdit.Editor.TileMaskSettings(),
World,
Selection,
undoManager,
(x, y, height, width) => { });
}

public Task SaveAsync()
{
// Run synchronously on the UI thread. Saving mutates World state that is
// bound to the UI (the PropertyGrid over World, plus the Chests/Signs/
// TileEntities ObservableCollections that Validate() prunes, and
// FileRevision). World.SaveAsync does this work on a background thread,
// so those change notifications reach Avalonia bindings off-thread and
// throw "Call from invalid thread". World.Save is the synchronous variant.
World.Save(World, FileName);
return Task.CompletedTask;
}
}
18 changes: 13 additions & 5 deletions src/TEdit5/ViewModels/ToolSelectionViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
using System.Collections.Generic;
using Avalonia.Threading;
using ReactiveUI;
using System.Collections.Generic;
using System.Linq;
using System.Reactive;
using System.Reactive.Concurrency;
using TEdit5.Editor;

namespace TEdit5.ViewModels;
Expand All @@ -17,17 +20,22 @@ public partial class ToolSelectionViewModel : ReactiveObject
public ToolSelectionViewModel(IEnumerable<IMouseTool> tools)
{
_tools = tools.ToList();
SetToolCommand = ReactiveCommand.Create<IMouseTool>(SetTool);

SetToolCommand = ReactiveCommand.Create<IMouseTool>(
tool => SetTool(tool),
outputScheduler: CurrentThreadScheduler.Instance
);

SetTool(Tools.FirstOrDefault(t => t.Name == "Arrow"));
}

private void SetTool(IMouseTool? tool)
{
// deactivate previous tool
if (ActiveTool != null) { ActiveTool.IsActive = false; }
if (ActiveTool != null)
{
ActiveTool.IsActive = false;
}

// activate new tool
if (tool != null)
{
tool.IsActive = true;
Expand Down
Loading