Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The find references feature improvements, and more. #1293

Merged
64 changes: 38 additions & 26 deletions UndertaleModTool/Editors/UndertaleEmbeddedTextureEditor.xaml
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
<local:DataUserControl x:Class="UndertaleModTool.UndertaleEmbeddedTextureEditor"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:UndertaleModTool"
xmlns:undertale="clr-namespace:UndertaleModLib.Models;assembly=UndertaleModLib"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800" d:DataContext="{d:DesignInstance undertale:UndertaleEmbeddedTexture}">
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:UndertaleModTool"
xmlns:undertale="clr-namespace:UndertaleModLib.Models;assembly=UndertaleModLib"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800" d:DataContext="{d:DesignInstance undertale:UndertaleEmbeddedTexture}"
DataContextChanged="DataUserControl_DataContextChanged" Loaded="DataUserControl_Loaded" Unloaded="DataUserControl_Unloaded">
<UserControl.Resources>
<local:BooleanToVisibilityConverter x:Key="BoolFalseToVisConverter" local:trueValue="Collapsed" local:falseValue="Visible"/>
<local:TextureLoadedWrapper x:Key="TextureLoadedWrapper"/>
Expand Down Expand Up @@ -66,26 +67,37 @@
</Grid.RowDefinitions>

<TextBlock Grid.Row="0" Grid.ColumnSpan="3" Margin="3" HorizontalAlignment="Center" Foreground="DarkGray" FontStyle="Italic" TextWrapping="Wrap" TextAlignment="Center">
Hint: You can open a texture page item by clicking on its region below.<LineBreak/>
The middle (wheel) mouse button will open it in a new tab.
Hint: This image is mouse interactable (3 mouse buttons and mouse wheel).
</TextBlock>
<Viewbox Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="3" Stretch="Uniform" StretchDirection="DownOnly"
SnapsToDevicePixels="True" RenderOptions.BitmapScalingMode="NearestNeighbor">
<Border>
<Border.Background>
<DrawingBrush Stretch="None" TileMode="Tile" Viewport="0,0,20,20" ViewportUnits="Absolute">
<DrawingBrush.Drawing>
<DrawingGroup>
<GeometryDrawing Geometry="M0,0 L20,0 20,20, 0,20Z" Brush="White"/>
<GeometryDrawing Geometry="M0,10 L20,10 20,20, 10,20 10,0 0,0Z" Brush="LightGray"/>
</DrawingGroup>
</DrawingBrush.Drawing>
</DrawingBrush>
</Border.Background>
<ScrollViewer Name="TextureScroll" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="3" MaxHeight="450"
HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Visible" ScrollChanged="TextureScroll_ScrollChanged">
<ScrollViewer.Background>
<DynamicResource ResourceKey="{x:Static SystemColors.MenuBrushKey}"/>
</ScrollViewer.Background>
<Viewbox Name="TextureViewbox" Stretch="Uniform" StretchDirection="DownOnly"
SnapsToDevicePixels="True" RenderOptions.BitmapScalingMode="NearestNeighbor" MouseWheel="TextureViewbox_MouseWheel">
<Border>
<Border.Background>
<DrawingBrush Stretch="None" TileMode="Tile" Viewport="0,0,20,20" ViewportUnits="Absolute">
<DrawingBrush.Drawing>
<DrawingGroup>
<GeometryDrawing Geometry="M0,0 L20,0 20,20, 0,20Z" Brush="White"/>
<GeometryDrawing Geometry="M0,10 L20,10 20,20, 10,20 10,0 0,0Z" Brush="LightGray"/>
</DrawingGroup>
</DrawingBrush.Drawing>
</DrawingBrush>
</Border.Background>

<Image Source="{Binding TextureData.TextureBlob, Mode=OneWay}" MouseDown="Image_MouseDown" Cursor="Hand"/>
</Border>
</Viewbox>
<Grid Cursor="Hand" MouseDown="Grid_MouseDown" MouseMove="Grid_MouseMove" MouseLeave="Grid_MouseLeave">
<Image Source="{Binding TextureData.TextureBlob, Mode=OneWay}"/>
<Canvas>
<Border Name="PageItemBorder" Background="LightBlue" BorderThickness="2" BorderBrush="Blue" Opacity="0.65"
Width="0" Height="0"/>
</Canvas>
</Grid>
</Border>
</Viewbox>
</ScrollViewer>

<local:ButtonDark Grid.Row="2" Grid.Column="0" Margin="0,2" Content="Import" Click="Import_Click"/>
<local:ButtonDark Grid.Row="2" Grid.Column="3" Margin="0,2" Content="Export" Click="Export_Click"/>
Expand Down
205 changes: 193 additions & 12 deletions UndertaleModTool/Editors/UndertaleEmbeddedTextureEditor.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
using UndertaleModLib.Util;
using System.Globalization;
using UndertaleModLib;
using UndertaleModTool.Windows;
using System.Windows.Threading;

namespace UndertaleModTool
{
Expand All @@ -28,10 +30,115 @@ namespace UndertaleModTool
public partial class UndertaleEmbeddedTextureEditor : DataUserControl
{
private static readonly MainWindow mainWindow = Application.Current.MainWindow as MainWindow;
private readonly ContextMenuDark pageContextMenu = new();
private bool isMenuOpen;
private UndertaleTexturePageItem[] items;
private UndertaleTexturePageItem hoveredItem;

public static (Transform Transform, double Left, double Top) OverriddenPreviewState { get; set; }

public UndertaleEmbeddedTextureEditor()
{
InitializeComponent();

var newTabItem = new MenuItem()
{
Header = "Open in new tab"
};
newTabItem.Click += OpenInNewTabItem_Click;
var referencesItem = new MenuItem()
{
Header = "Find all references to this page item"
};
referencesItem.Click += FindAllItemReferencesItem_Click;
pageContextMenu.Items.Add(newTabItem);
pageContextMenu.Items.Add(referencesItem);

pageContextMenu.Closed += PageContextMenu_Closed;
}

private void OpenInNewTabItem_Click(object sender, RoutedEventArgs e)
{
mainWindow.ChangeSelection((sender as FrameworkElement)?.DataContext, true);
}
private void FindAllItemReferencesItem_Click(object sender, RoutedEventArgs e)
{
if ((sender as FrameworkElement)?.DataContext is not UndertaleTexturePageItem item)
return;

FindReferencesTypesDialog dialog = null;
try
{
dialog = new(item, mainWindow.Data);
dialog.ShowDialog();
}
catch (Exception ex)
{
mainWindow.ShowError("An error occured in the object references related window.\n" +
$"Please report this on GitHub.\n\n{ex}");
}
finally
{
dialog?.Close();
}
}
private void PageContextMenu_Closed(object sender, RoutedEventArgs e)
{
isMenuOpen = false;
Grid_MouseLeave(null, null);
}

private void ScaleTextureToFit()
{
var scrollPres = MainWindow.FindVisualChild<ScrollContentPresenter>(TextureScroll);
if (scrollPres is null)
return;

double initScale = 1;
if (DataContext is UndertaleEmbeddedTexture texturePage)
{
int textureWidth = texturePage.TextureData?.Width ?? 1;
if (textureWidth < scrollPres.ActualWidth)
initScale = scrollPres.ActualWidth / textureWidth;
}

Transform t;
double top, left;
if (OverriddenPreviewState == default)
{
t = new MatrixTransform(initScale, 0, 0, initScale, 0, 0);
top = 0;
left = 0;
}
else
{
t = OverriddenPreviewState.Transform;
top = OverriddenPreviewState.Top;
left = OverriddenPreviewState.Left;
}

TextureViewbox.LayoutTransform = t;
TextureViewbox.UpdateLayout();
TextureScroll.ScrollToVerticalOffset(top);
TextureScroll.ScrollToHorizontalOffset(left);
}
private void DataUserControl_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if (DataContext is UndertaleEmbeddedTexture texturePage)
items = mainWindow.Data.TexturePageItems.Where(x => x.TexturePage == texturePage).ToArray();

if (!IsLoaded)
return;
// "UpdateLayout()" doesn't work here
_ = Dispatcher.InvokeAsync(ScaleTextureToFit, DispatcherPriority.ContextIdle);
}
private void DataUserControl_Loaded(object sender, RoutedEventArgs e)
{
ScaleTextureToFit();
}
private void DataUserControl_Unloaded(object sender, RoutedEventArgs e)
{
OverriddenPreviewState = default;
}

private void Import_Click(object sender, RoutedEventArgs e)
Expand Down Expand Up @@ -100,23 +207,97 @@ private void Export_Click(object sender, RoutedEventArgs e)
}
}

private void Image_MouseDown(object sender, MouseButtonEventArgs e)
private void Grid_MouseDown(object sender, MouseButtonEventArgs e)
{
if (hoveredItem is null)
return;

if (e.ChangedButton == MouseButton.Right)
{
isMenuOpen = true;
pageContextMenu.DataContext = hoveredItem;
pageContextMenu.IsOpen = true;
return;
}

mainWindow.ChangeSelection(hoveredItem, e.ChangedButton == MouseButton.Middle);
}

private void Grid_MouseMove(object sender, MouseEventArgs e)
{
var prevItem = hoveredItem;
hoveredItem = null;

var pos = e.GetPosition(sender as IInputElement);
var tex = this.DataContext as UndertaleEmbeddedTexture;
var tpag = mainWindow.Data.TexturePageItems.Where((x) =>
{
if (x.TexturePage != tex)
return false;
return pos.X > x.SourceX && pos.X < x.SourceX + x.SourceWidth && pos.Y > x.SourceY && pos.Y < x.SourceY + x.SourceHeight;
}).FirstOrDefault();
if (tpag != null)
mainWindow.ChangeSelection(tpag, e.ChangedButton == MouseButton.Middle);
else
mainWindow.ShowWarning("Cannot find a texture page item at this position.");
foreach (var item in items)
{
if (pos.X > item.SourceX && pos.X < item.SourceX + item.SourceWidth
&& pos.Y > item.SourceY && pos.Y < item.SourceY + item.SourceHeight)
{
hoveredItem = item;
break;
}
}

if (hoveredItem is null)
{
PageItemBorder.Width = PageItemBorder.Height = 0;
return;
}

if (prevItem == hoveredItem)
return;

PageItemBorder.Width = hoveredItem.SourceWidth;
PageItemBorder.Height = hoveredItem.SourceHeight;
Canvas.SetLeft(PageItemBorder, hoveredItem.SourceX);
Canvas.SetTop(PageItemBorder, hoveredItem.SourceY);
}
private void Grid_MouseLeave(object sender, MouseEventArgs e)
{
if (isMenuOpen)
return;

PageItemBorder.Width = PageItemBorder.Height = 0;
hoveredItem = null;
}

private void TextureScroll_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
if (e.ExtentHeightChange != 0 || e.ExtentWidthChange != 0)
{
double xMousePositionOnScrollViewer = Mouse.GetPosition(TextureScroll).X;
double yMousePositionOnScrollViewer = Mouse.GetPosition(TextureScroll).Y;
double offsetX = e.HorizontalOffset + xMousePositionOnScrollViewer;
double offsetY = e.VerticalOffset + yMousePositionOnScrollViewer;

double oldExtentWidth = e.ExtentWidth - e.ExtentWidthChange;
double oldExtentHeight = e.ExtentHeight - e.ExtentHeightChange;

double relx = offsetX / oldExtentWidth;
double rely = offsetY / oldExtentHeight;

offsetX = Math.Max(relx * e.ExtentWidth - xMousePositionOnScrollViewer, 0);
offsetY = Math.Max(rely * e.ExtentHeight - yMousePositionOnScrollViewer, 0);

TextureScroll.ScrollToHorizontalOffset(offsetX);
TextureScroll.ScrollToVerticalOffset(offsetY);
}
}

private void TextureViewbox_MouseWheel(object sender, MouseWheelEventArgs e)
{
e.Handled = true;
var mousePos = e.GetPosition(TextureViewbox);
var transform = TextureViewbox.LayoutTransform as MatrixTransform;
var matrix = transform.Matrix;
var scale = e.Delta >= 0 ? 1.1 : (1.0 / 1.1); // choose appropriate scaling factor

if ((matrix.M11 > 0.2 || (matrix.M11 <= 0.2 && scale > 1)) && (matrix.M11 < 3 || (matrix.M11 >= 3 && scale < 1)))
{
matrix.ScaleAtPrepend(scale, scale, mousePos.X, mousePos.Y);
}
TextureViewbox.LayoutTransform = new MatrixTransform(matrix);
}
}

Expand Down
19 changes: 12 additions & 7 deletions UndertaleModTool/Editors/UndertaleRoomEditor.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -146,12 +146,18 @@ private void UndertaleRoomEditor_DataContextChanged(object sender, DependencyPro
RoomRootItem.IsSelected = true;

ScrollViewer viewer = MainWindow.FindVisualChild<ScrollViewer>(RoomObjectsTree);
viewer.ScrollToVerticalOffset(0);
viewer.ScrollToHorizontalOffset(0);
if (viewer is not null)
{
viewer.ScrollToTop();
viewer.ScrollToLeftEnd();
}

RoomGraphics.ClearValue(LayoutTransformProperty);
RoomGraphicsScroll.ScrollToVerticalOffset(0);
RoomGraphicsScroll.ScrollToHorizontalOffset(0);
_ = Dispatcher.InvokeAsync(() =>
{
RoomGraphicsScroll.ScrollToTop();
RoomGraphicsScroll.ScrollToLeftEnd();
}, DispatcherPriority.ContextIdle);
}

UndertaleCachedImageLoader.Reset();
Expand Down Expand Up @@ -711,17 +717,16 @@ private void RectangleTile_MouseMove(object sender, MouseEventArgs e)
private void Canvas_MouseWheel(object sender, MouseWheelEventArgs e)
{
e.Handled = true;
var element = sender as ItemsControl;
var mousePos = e.GetPosition(RoomGraphics);
var transform = element.LayoutTransform as MatrixTransform;
var transform = RoomGraphics.LayoutTransform as MatrixTransform;
var matrix = transform.Matrix;
var scale = e.Delta >= 0 ? 1.1 : (1.0 / 1.1); // choose appropriate scaling factor

if ((matrix.M11 > 0.2 || (matrix.M11 <= 0.2 && scale > 1)) && (matrix.M11 < 3 || (matrix.M11 >= 3 && scale < 1)))
{
matrix.ScaleAtPrepend(scale, scale, mousePos.X, mousePos.Y);
}
element.LayoutTransform = new MatrixTransform(matrix);
RoomGraphics.LayoutTransform = new MatrixTransform(matrix);
}

private void ScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
Expand Down
10 changes: 7 additions & 3 deletions UndertaleModTool/Editors/UndertaleTexturePageItemEditor.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>

<TextBlock Grid.Row="0" Grid.Column="0" Margin="3">Source position/size</TextBlock>
Expand Down Expand Up @@ -63,7 +64,10 @@
<TextBlock Grid.Row="3" Grid.Column="0" Margin="3">Texture</TextBlock>
<local:UndertaleObjectReference Grid.Row="3" Grid.Column="1" Margin="3" ObjectReference="{Binding TexturePage}" ObjectType="{x:Type undertale:UndertaleEmbeddedTexture}"/>

<Viewbox Grid.Row="4" Grid.Column="0" Grid.ColumnSpan="2" Stretch="Uniform" StretchDirection="DownOnly" Margin="0,0,0,20">
<local:ButtonDark Grid.Row="4" Grid.ColumnSpan="3" Width="230" Margin="3"
Click="FindReferencesButton_Click">Find all references to this page item</local:ButtonDark>

<Viewbox Grid.Row="5" Grid.Column="0" Grid.ColumnSpan="2" Stretch="Uniform" StretchDirection="DownOnly" Margin="3">
<Border>
<Border.Background>
<DrawingBrush Stretch="None" TileMode="Tile" Viewport="0,0,20,20" ViewportUnits="Absolute">
Expand All @@ -80,7 +84,7 @@
</Border>
</Viewbox>

<Grid Grid.Row="5" Grid.Column="0" Grid.ColumnSpan="2" Margin="3">
<Grid Grid.Row="6" Grid.Column="0" Grid.ColumnSpan="2" Margin="3,3,3,25">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
Expand All @@ -91,7 +95,7 @@
<local:ButtonDark Grid.Column="3" Content="Export" Click="Export_Click"/>
</Grid>

<Viewbox Grid.Row="6" Grid.Column="0" Grid.ColumnSpan="2" Stretch="Uniform" StretchDirection="DownOnly"
<Viewbox Grid.Row="7" Grid.Column="0" Grid.ColumnSpan="2" Stretch="Uniform" StretchDirection="DownOnly"
SnapsToDevicePixels="True" RenderOptions.BitmapScalingMode="NearestNeighbor">
<Grid>
<Grid.ColumnDefinitions>
Expand Down
Loading