Skip to content
Closed
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
3 changes: 3 additions & 0 deletions Controls/Metadata.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
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">
Expand Down Expand Up @@ -31,6 +32,8 @@
<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"/>
<Label Content="Export Texture Scaling:" Grid.Row="4" Grid.Column="0" VerticalAlignment="Center" HorizontalContentAlignment="Right"/>
<ComboBox ItemsSource="{Binding ExportTextureScalingModes}" SelectedItem="{Binding SelectedExportTextureScaling}" Grid.Row="4" Grid.Column="2" VerticalAlignment="Center" HorizontalAlignment="Stretch" Margin="4,0"/>

</Grid>
</Grid>
Expand Down
19 changes: 16 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,25 @@ 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));

//Scaling of the texture if necessary
if (image is DynamicInputTexture texture)
{
if (texture.ExportImageScaling != 0 && texture.ExportImageScaling != texture.ImageWidthScaling)
{
texture.SetImageScaling(output_location, texture.ExportImageScaling);
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
85 changes: 83 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 @@ -187,18 +188,98 @@ public double ImageHeightScaling
}
}

/// <summary>
/// The image size is set to a multiple of the original size when exporting.
/// 0 = Keep current size.
/// </summary>
public int ExportImageScaling
{
get => _export_image_scaling;
set
{
if (value < 0) throw new ArgumentException("cannot be less than zero", nameof(ExportImageScaling));

_export_image_scaling = (byte)value;
OnPropertyChanged(nameof(ExportImageScaling));
}
}
private byte _export_image_scaling = 0;
#endregion

#region Update

/// <summary>
/// Scales the image in relation to the original size.
/// </summary>
/// <param name="savepath">Save location of the new file</param>
/// <param name="Scaling">Size in relation to the original size</param>
public void SetImageScaling(string savepath, int Scaling)
{
if (Scaling <= 0)
{
throw new ArgumentException("Must be at least 1 or greater", nameof(Scaling));
}

SetImageScaling(savepath, (int)(HashProperties.ImageWidth * Scaling), (int)(HashProperties.ImageHeight * Scaling));
}

/// <summary>
/// Scales the image to an absulute size.
/// </summary>
/// <param name="savepath">Save location of the new file</param>
/// <param name="width">width in pixel</param>
/// <param name="height">height in pixel</param>
public void SetImageScaling(string savepath, int width, int height)
{
using(Bitmap newImage = new Bitmap(width, height))
{
using (Bitmap Image = new Bitmap(TexturePath))
using (Graphics graphics = Graphics.FromImage(newImage))
{
graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
graphics.DrawImage(Image, 0, 0, newImage.Width, newImage.Height);
}
newImage.Save(savepath, System.Drawing.Imaging.ImageFormat.Png);

// sets the new path and updates the regions to the new size.
TexturePath = savepath;
}
}

/// <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
3 changes: 3 additions & 0 deletions ViewModels/Dialogs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,10 @@ public static bool DialogExportToLocation(in DynamicInputPackViewModel pack)
var dialog = new System.Windows.Forms.FolderBrowserDialog();
if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
pack.SetExportTextureScaling();
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
102 changes: 102 additions & 0 deletions ViewModels/DynamicInputPackViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,45 @@ public bool ShouldGetHashFromTextureFilename
}
}

/// <summary>
/// List of possible texture scaling during export.
/// </summary>
public string[] ExportTextureScalingModes
{
get => _export_texture_scaling_modes ??= new string[] { "Deactivated", "Dynamic", "1x (Original Size)", "2x", "3x", "4x", "5x" , "6x", "7x", "8x" };
}
private string[] _export_texture_scaling_modes;

/// <summary>
/// The currently selected export texture scaling.
/// </summary>
public string SelectedExportTextureScaling
{
get => (string)ExportTextureScalingModes.GetValue(_selected_export_texture_scaling);
set
{
for (int i = 0; i < ExportTextureScalingModes.Length; i++)
{
if (value == ExportTextureScalingModes[i])
{
_selected_export_texture_scaling = i;
OnPropertyChanged(nameof(SelectedExportTextureScaling));
return;
}
}
_selected_export_texture_scaling = 0;
OnPropertyChanged(nameof(SelectedExportTextureScaling));
}
}
internal int _selected_export_texture_scaling = 0;

/// <summary>
/// Number of pixels that the smallest region should have at least after exporting, when the Dynamic mode is used.
/// </summary>
private int _targeted_regione_size = 96;

#endregion

#region Commands

#region SelectedTexture
Expand Down Expand Up @@ -331,5 +369,69 @@ public void SetInitialZoom(DynamicInputTexture Texture, double absolutescale = 6

#endregion

#region ExportScale

/// <summary>
/// set the export scale for each texture.
/// </summary>
public void SetExportTextureScaling()
{
foreach (DynamicInputTexture texture in Textures)
{
switch (_selected_export_texture_scaling)
{
case 0:
//(Disabled) Leaves the textures unchanged.
texture.ExportImageScaling = 0;
break;
case 1:
//(Dynamic) Calculates a good display size.
SetExportTextureScaling_Dynamic(texture);
break;
default:
//(x1-8) Use the specified scaling.
texture.ExportImageScaling = _selected_export_texture_scaling - 1;
break;
}
}

}

/// <summary>
/// Calculates a good texture scaling based on region size.
/// </summary>
/// <param name="texture"></param>
private void SetExportTextureScaling_Dynamic(DynamicInputTexture texture)
{
// 0 if there are no regions.
if (texture.Regions.Count <= 0)
{
texture.ExportImageScaling = 0;
return;
}

//calculate a scaling based on the regions.
int smallest_region = texture.ImageWidth;
foreach (InputRegion region in texture.Regions)
{
int regionsize = (int)(region.RegionRect.Height + region.RegionRect.Width) / 2;
if (smallest_region > regionsize)
{
smallest_region = regionsize;
}
}
smallest_region = (int)(smallest_region / ((texture.ImageHeightScaling + texture.ImageWidthScaling) / 2));
int scaling = (int)Math.Round((double)_targeted_regione_size / smallest_region, 0, MidpointRounding.AwayFromZero);

// unlikely however try to avoid too large textures.
int pixelsize = texture.HashProperties.ImageWidth > texture.HashProperties.ImageHeight ? texture.HashProperties.ImageWidth : texture.HashProperties.ImageHeight;
if (pixelsize * scaling > 4096)
{
scaling = (int)Math.Round((double)4096 / pixelsize, MidpointRounding.ToZero);
}

texture.ExportImageScaling = (byte)scaling;
}
#endregion
}
}