Skip to content
Open
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
100 changes: 75 additions & 25 deletions Controls/Metadata.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,34 +4,84 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:DolphinDynamicInputTextureCreator.Controls"
xmlns:converters="clr-namespace:DolphinDynamicInputTextureCreator.ValueConverters"
mc:Ignorable="d"
Height="220" Width="320">
<Grid Background="White">
Height="200" Width="320">
<UserControl.Resources>
<ResourceDictionary>

</ResourceDictionary>
</UserControl.Resources>
<Grid Grid.Row="0" Background="White">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="25"/>
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Content="Output json name:" Grid.Row="0" Grid.Column="0" VerticalAlignment="Center" HorizontalContentAlignment="Right"/>
<TextBox Text="{Binding GeneratedJsonName, Mode=TwoWay}" Grid.Row="0" Grid.Column="2" VerticalAlignment="Center" HorizontalAlignment="Stretch" Margin="4,0"/>
<Label Content="Generated folder name:" Grid.Row="1" Grid.Column="0" VerticalAlignment="Center" HorizontalContentAlignment="Right"/>
<TextBox Text="{Binding GeneratedFolderName, Mode=TwoWay}" Grid.Row="1" Grid.Column="2" VerticalAlignment="Center" HorizontalAlignment="Stretch" Margin="4,0"/>
<Label Content="Preserve aspect ratio:" Grid.Row="2" Grid.Column="0" VerticalAlignment="Center" HorizontalContentAlignment="Right"/>
<CheckBox IsChecked="{Binding PreserveAspectRatio, Mode=TwoWay}" Grid.Row="2" Grid.Column="2" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="4,0"/>
<Label Content="Game ID:" Grid.Row="3" Grid.Column="0" VerticalAlignment="Center" HorizontalContentAlignment="Right"/>
<TextBox Text="{Binding GameID, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Grid.Row="3" Grid.Column="2" VerticalAlignment="Center" HorizontalAlignment="Stretch" Margin="4,0"/>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Content="Output json name:" Grid.Row="0" Grid.Column="0" VerticalAlignment="Center" HorizontalContentAlignment="Right"/>
<TextBox Text="{Binding GeneratedJsonName, Mode=TwoWay}" Grid.Row="0" Grid.Column="2" VerticalAlignment="Center" HorizontalAlignment="Stretch" Margin="4,6"/>
<Label Content="Generated folder name:" Grid.Row="1" Grid.Column="0" VerticalAlignment="Center" HorizontalContentAlignment="Right"/>
<TextBox Text="{Binding GeneratedFolderName, Mode=TwoWay}" Grid.Row="1" Grid.Column="2" VerticalAlignment="Center" HorizontalAlignment="Stretch" Margin="4,6"/>
<Label Content="Preserve aspect ratio:" Grid.Row="2" Grid.Column="0" VerticalAlignment="Center" HorizontalContentAlignment="Right"/>
<CheckBox IsChecked="{Binding PreserveAspectRatio, Mode=TwoWay}" Grid.Row="2" Grid.Column="2" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="4,6"/>
<Label Content="Game ID:" Grid.Row="3" Grid.Column="0" VerticalAlignment="Center" HorizontalContentAlignment="Right"/>
<TextBox Text="{Binding GameID, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Grid.Row="3" Grid.Column="2" VerticalAlignment="Center" HorizontalAlignment="Stretch" Margin="4,6"/>

<GroupBox Header="Export Texture Scaling" Grid.Row="4" Grid.ColumnSpan="2" BorderThickness="1" BorderBrush="Gray">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal">
<Label Content="Mode:" VerticalAlignment="Center"/>
<ComboBox ItemsSource="{Binding ExportTextureScaling.ScalingModesHelper}" SelectedItem="{Binding ExportTextureScaling.SelectedScalingModeHelper}" MinWidth="125" VerticalAlignment="Center" HorizontalAlignment="Stretch" Margin="2,6"/>
</StackPanel>

<DockPanel Grid.Column="1">

<DockPanel.Style>
<Style TargetType="{x:Type DockPanel}">
<Setter Property="IsEnabled" Value="False"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ExportTextureScaling.SelectedScalingModeHelper}" Value="NearestNeighbor">
<Setter Property="IsEnabled" Value="True"/>
</DataTrigger>
<DataTrigger Binding="{Binding ExportTextureScaling.SelectedScalingModeHelper}" Value="Bicubic">
<Setter Property="IsEnabled" Value="True"/>
</DataTrigger>
<DataTrigger Binding="{Binding ExportTextureScaling.SelectedScalingModeHelper}" Value="Bilinear">
<Setter Property="IsEnabled" Value="True"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DockPanel.Style>

</Grid>
<StackPanel Orientation="Horizontal" Grid.Column="1" Margin="5,0">
<Label Content="Factor:" Grid.Row="0" Grid.Column="0" VerticalAlignment="Center" />
<ComboBox ItemsSource="{Binding ExportTextureScaling.ScalingFactorHelper}" SelectedItem="{Binding ExportTextureScaling.SelectedScalingFactor}" MinWidth="50" VerticalAlignment="Center" HorizontalAlignment="Stretch" Margin="4,0">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock VerticalAlignment="Center" Text="{Binding}" />
<TextBlock VerticalAlignment="Center" Text="x" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</StackPanel>
</DockPanel>
</Grid>
</GroupBox>
</Grid>
</UserControl>
23 changes: 20 additions & 3 deletions DolphinDynamicInputTexture/Data/DynamicInputPack.cs
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,8 @@ public string GameID
/// <param name="location">export directory</param>
public void ExportToLocation(string location)
{
WriteJson(Path.Combine(location, GeneratedJsonName + ".json"));
WriteImages(location);
WriteJson(Path.Combine(location, GeneratedJsonName + ".json"));
WriteGameID(location);
}

Expand Down Expand Up @@ -153,6 +153,7 @@ private void WriteImages(string location)
{
//exports the images for the output_textures
WriteImage(location, texture);

foreach (HostDevice device in texture.HostDevices)
{
foreach (HostKey key in device.HostKeys)
Expand All @@ -164,7 +165,7 @@ private void WriteImages(string location)
}
}

private void WriteImage(string location, Interfaces.IImage image)
private void WriteImage(string location, IImage image)
{
// Unlikely that we get here but skip textures that don't exist
if (!File.Exists(image.TexturePath))
Expand All @@ -174,13 +175,29 @@ private void WriteImage(string location, Interfaces.IImage image)
image.RelativeTexturePath = CheckRelativeTexturePath(image);
string output_location = Path.Combine(location, image.RelativeTexturePath);

//create the directory when it does not exist.
Directory.CreateDirectory(Path.GetDirectoryName(output_location));

//Use External Scaling if necessary.
if (image is DynamicInputTexture texture)
{
if (DynamicInputTextureEvents.DynamicInputTextureExportProcessor != null)
{
DynamicInputTextureEvents.DynamicInputTextureExportProcessor.Invoke(output_location, texture);
if (File.Exists(output_location))
{
texture.TexturePath = output_location;
return;
}
}
}

// Prevents the file from trying to overwrite itself.
if (Path.GetFullPath(output_location) == Path.GetFullPath(image.TexturePath))
return;

//write the image
const bool overwrite = true;
Directory.CreateDirectory(Path.GetDirectoryName(output_location));
File.Copy(image.TexturePath, output_location, overwrite);
}

Expand Down
31 changes: 29 additions & 2 deletions DolphinDynamicInputTexture/Data/DynamicInputTexture.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using DolphinDynamicInputTexture.Interfaces;
using Newtonsoft.Json;
using System;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Drawing;
Expand Down Expand Up @@ -191,14 +192,40 @@ public double ImageHeightScaling

#region Update

/// <summary>
/// reads the image size and adjusts the regions if necessary.
/// </summary>
private void UpdateImageWidthHeight()
{
if (File.Exists(_texture_path))
{
using (var bmp = new Bitmap(_texture_path))
{
ImageHeight = bmp.Height;
ImageWidth = bmp.Width;
if (ImageHeight > 0 && ImageWidth > 0)
{
double width_scale = (double)bmp.Width / ImageWidth;
double height_scale = (double)bmp.Height / ImageHeight;

//When scaling up, the scale must be set directly.
if (width_scale >= 1) ImageWidth = bmp.Width;
if (height_scale >= 1) ImageHeight = bmp.Height;

foreach (InputRegion region in Regions)
{
region.RegionRect.X *= width_scale;
region.RegionRect.Width *= width_scale;
region.RegionRect.Y *= height_scale;
region.RegionRect.Height *= height_scale;
}

ImageWidth = bmp.Width;
ImageHeight = bmp.Height;
}
else
{
ImageHeight = bmp.Height;
ImageWidth = bmp.Width;
}
}
}
}
Expand Down
13 changes: 13 additions & 0 deletions DolphinDynamicInputTexture/Data/DynamicInputTextureEvents.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,18 @@ public static class DynamicInputTextureEvents

public delegate bool ImageNotExistAction(Interfaces.IImage image, string details);

/// <summary>
/// Allows editing the terxtures during exporting.
/// </summary>
/// <param name="savepath">Path where the new texture should be saved</param>
/// <param name="dynamicinputtexture">texture that should be scaled</param>
/// <returns></returns>
public delegate bool ExternalScalingProcesses(string savepath, DynamicInputTexture dynamicinputtexture);

/// <summary>
/// Allows editing the DynamicInputTextures during exporting.
/// </summary>
public static ExternalScalingProcesses DynamicInputTextureExportProcessor { get; set; }

}
}
2 changes: 2 additions & 0 deletions ViewModels/Dialogs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ public static bool DialogExportToLocation(in DynamicInputPackViewModel pack)
if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
pack.ExportToLocation(dialog.SelectedPath);
// Updating the user interface in case the image file has changed.
pack.Textures.Select(pack.Textures.Selected);
return true;
}
return false;
Expand Down
21 changes: 21 additions & 0 deletions ViewModels/DynamicInputPackViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,28 @@ public InputRegion SelectedRegion
}
private InputRegion _selected_region;

/// <summary>
/// Options used to rescale textures during export.
/// </summary>
public ExportTextureScalingViewModel ExportTextureScaling
{
get
{
if (_export_texture_scaling == null)
{
_export_texture_scaling = new ExportTextureScalingViewModel();
if (Textures.ValidSelection)
{
ExportTextureScaling.SelectedScalingFactor = (int)Textures.Selected.ImageWidthScaling;
}
}
return _export_texture_scaling;
}
}
public ExportTextureScalingViewModel _export_texture_scaling;

#endregion

#region Commands

#region SelectedTexture
Expand Down
120 changes: 120 additions & 0 deletions ViewModels/ExportTextureScalingViewModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
using DolphinDynamicInputTexture.Data;
using System;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace DolphinDynamicInputTextureCreator.ViewModels
{
public class ExportTextureScalingViewModel : Other.PropertyChangedBase
{
/// <summary>
/// Possible texture scaling modes.
/// </summary>
internal enum Modes
{
None, NearestNeighbor, Bicubic, Bilinear
}

/// <summary>
/// The currently selected export texture scaling mode.
/// </summary>
internal Modes SelectedScalingMode
{
get => _selected_scaling_mode;
set
{
_selected_scaling_mode = value;
SetExportTextureScaling();
OnPropertyChanged(nameof(SelectedScalingMode));
}
}
private Modes _selected_scaling_mode = Modes.None;

/// <summary>
/// Scaling factor that the exported image should have.
/// </summary>
public int SelectedScalingFactor { get; set; } = 4;

#region UI Helper

public string[] ScalingModesHelper
{
get => Enum.GetNames(typeof(Modes));
}

public string SelectedScalingModeHelper
{
get => SelectedScalingMode.ToString();
set
{
SelectedScalingMode = Enum.Parse<Modes>(value);
OnPropertyChanged(nameof(SelectedScalingModeHelper));
}
}

public int[] ScalingFactorHelper => new int[] { 1, 2, 3, 4, 5, 6, 8, 10 };

#endregion UI Helper

/// <summary>
/// set the export scale for each texture.
/// </summary>
private void SetExportTextureScaling()
{
switch (SelectedScalingMode)
{
case Modes.None:
DynamicInputTextureEvents.DynamicInputTextureExportProcessor = null;
break;

case Modes.NearestNeighbor:
case Modes.Bicubic:
case Modes.Bilinear:
DynamicInputTextureEvents.DynamicInputTextureExportProcessor = DefaultScalingProcessor;
break;

default:
break;
}
}

public bool DefaultScalingProcessor(string savepath, DynamicInputTexture dynamicinputtexture)
{
int Scaling = SelectedScalingFactor;

//Should we use scaling?
if (Scaling == dynamicinputtexture.ImageWidthScaling) return false;

//The actual scaling.
using (Bitmap newImage = new Bitmap(dynamicinputtexture.HashProperties.ImageWidth * Scaling, dynamicinputtexture.HashProperties.ImageHeight * Scaling))
{
using (Bitmap Image = new Bitmap(dynamicinputtexture.TexturePath))
using (Graphics graphics = Graphics.FromImage(newImage))
{
switch (SelectedScalingMode)
{
case Modes.NearestNeighbor:
graphics.InterpolationMode = InterpolationMode.NearestNeighbor;
break;

case Modes.Bicubic:
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
break;

case Modes.Bilinear:
graphics.InterpolationMode = InterpolationMode.HighQualityBilinear;
break;

default:
break;
}

graphics.DrawImage(Image, 0, 0, newImage.Width, newImage.Height);
}
newImage.Save(savepath, System.Drawing.Imaging.ImageFormat.Png);
}

return true;
}
}
}