├── vimage
├── Resources
│ └── icon.ico
├── vimage.csproj
├── Program.cs
├── Utils
│ ├── WindowsFileSorting.cs
│ └── ImageViewerUtils.cs
├── Display
│ ├── AnimatedImage.cs
│ ├── DisplayObject.cs
│ ├── DWM.cs
│ └── Graphics.cs
├── ImageManipulation
│ ├── Quantizer.cs
│ └── OctreeQuantizer.cs
└── ContextMenu.cs
├── vimage_settings
├── Resources
│ └── icon.ico
├── Xceed.Wpf.Toolkit.dll
├── Properties
│ ├── Settings.settings
│ ├── Settings.Designer.cs
│ ├── Resources.Designer.cs
│ └── Resources.resx
├── Source
│ ├── General.xaml.cs
│ ├── CommandsList.xaml.cs
│ ├── App.xaml
│ ├── About.xaml.cs
│ ├── App.xaml.cs
│ ├── ControlBindings.xaml
│ ├── Misc.cs
│ ├── ContextMenuEditorCanvas.cs
│ ├── MainWindow.xaml.cs
│ ├── ControlItem.xaml
│ ├── About.xaml
│ ├── CustomActionItem.xaml
│ ├── ControlBindings.xaml.cs
│ ├── MainWindow.xaml
│ ├── CustomActions.xaml.cs
│ ├── CustomActionItem.xaml.cs
│ ├── CustomActions.xaml
│ ├── ContextMenuItem.xaml
│ ├── ContextMenu.xaml
│ ├── CommandsList.xaml
│ ├── ControlItem.xaml.cs
│ ├── ContextMenu.xaml.cs
│ ├── General.xaml
│ └── ContextMenuItem.xaml.cs
└── vimage_settings.csproj
├── .vscode
└── launch.json
├── vimage.Common
├── vimage.Common.csproj
└── Actions.cs
├── LICENSE
├── Makefile
├── README.md
├── .gitignore
└── vimage.sln
/vimage/Resources/icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Torrunt/vimage/HEAD/vimage/Resources/icon.ico
--------------------------------------------------------------------------------
/vimage_settings/Resources/icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Torrunt/vimage/HEAD/vimage_settings/Resources/icon.ico
--------------------------------------------------------------------------------
/vimage_settings/Xceed.Wpf.Toolkit.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Torrunt/vimage/HEAD/vimage_settings/Xceed.Wpf.Toolkit.dll
--------------------------------------------------------------------------------
/vimage_settings/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | "configurations": [
3 | {
4 | "name": "C#: vimage",
5 | "type": "dotnet",
6 | "request": "launch",
7 | "projectPath": "${workspaceFolder}\\vimage\\vimage.csproj",
8 | "launchConfigurationId": "TargetFramework=;vimage"
9 | }
10 | ]
11 | }
--------------------------------------------------------------------------------
/vimage_settings/Source/General.xaml.cs:
--------------------------------------------------------------------------------
1 | using System.Windows.Controls;
2 |
3 | namespace vimage_settings
4 | {
5 | ///
6 | /// Interaction logic for General.xaml
7 | ///
8 | public partial class General : UserControl
9 | {
10 | public General()
11 | {
12 | InitializeComponent();
13 | DataContext = App.vimageConfig;
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/vimage.Common/vimage.Common.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net9.0-windows
5 | win-x64;win-x86
6 | enable
7 | enable
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/vimage_settings/Source/CommandsList.xaml.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 |
3 | namespace vimage_settings
4 | {
5 | ///
6 | /// Interaction logic for CommandsList.xaml
7 | ///
8 | public partial class CommandsList : Window
9 | {
10 | public CommandsList()
11 | {
12 | InitializeComponent();
13 | SourceInitialized += (s, e) => { MaxHeight = ActualHeight; };
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/vimage_settings/Source/App.xaml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/vimage_settings/Source/About.xaml.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics;
2 | using System.Windows.Controls;
3 | using System.Windows.Navigation;
4 |
5 | namespace vimage_settings
6 | {
7 | ///
8 | /// Interaction logic for About.xaml
9 | ///
10 | public partial class About : UserControl
11 | {
12 | public About()
13 | {
14 | InitializeComponent();
15 | }
16 |
17 | private void Hyperlink_RequestNavigate(object sender, RequestNavigateEventArgs e)
18 | {
19 | _ = Process.Start(
20 | new ProcessStartInfo { FileName = e.Uri.AbsoluteUri, UseShellExecute = true }
21 | );
22 | e.Handled = true;
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/vimage_settings/Source/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Windows;
3 | using vimage.Common;
4 |
5 | namespace vimage_settings
6 | {
7 | public partial class App : Application
8 | {
9 | public static Config vimageConfig = new();
10 |
11 | protected override void OnStartup(StartupEventArgs e)
12 | {
13 | base.OnStartup(e);
14 |
15 | try
16 | {
17 | vimageConfig.Load(
18 | System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "config.txt")
19 | );
20 | }
21 | catch (UnauthorizedAccessException)
22 | {
23 | MessageBox.Show(
24 | "vimage does not have write permissions for the folder it's located in.\nPlease place it somewhere else (or set it to run as admin).",
25 | "vimage - Error"
26 | );
27 | }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/vimage_settings/Source/ControlBindings.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/vimage_settings/Source/Misc.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Globalization;
3 | using System.Windows.Data;
4 |
5 | namespace vimage_settings
6 | {
7 | public class EnumConverter : IValueConverter
8 | {
9 | public object? Convert(object value, Type targetType, object parameter, CultureInfo culture)
10 | {
11 | if (value == null)
12 | return null;
13 |
14 | // convert int to enum
15 | if (targetType.IsEnum)
16 | return Enum.ToObject(targetType, value);
17 |
18 | // convert enum to int
19 | return value.GetType().IsEnum
20 | ? System.Convert.ChangeType(value, Enum.GetUnderlyingType(value.GetType()))
21 | : null;
22 | }
23 |
24 | public object? ConvertBack(
25 | object value,
26 | Type targetType,
27 | object parameter,
28 | CultureInfo culture
29 | )
30 | {
31 | // perform the same conversion in both directions
32 | return Convert(value, targetType, parameter, culture);
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2013 Corey Womack
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software is furnished to do so,
10 | subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | -include .env
2 |
3 | ## publish: creates a 64bit release build
4 | .PHONY: publish
5 | publish:
6 | @sed -i.bak "s|public const string SENTRY_DSN = \".*\";|public const string SENTRY_DSN = \"$(SENTRY_DSN)\";|" vimage/Program.cs
7 | dotnet publish vimage -c Release -r win-x64 --self-contained false /p:PublishSingleFile=true
8 | dotnet publish vimage_settings -c Release -r win-x64 --self-contained false /p:PublishSingleFile=true
9 | @sed -i "s|public const string SENTRY_DSN = \".*\";|public const string SENTRY_DSN = \"\";|" vimage/Program.cs
10 | @rm -f vimage/Program.cs.bak
11 |
12 | ## publish-x86: creates a 32bit release build
13 | .PHONY: publish-x86
14 | publish-x86:
15 | @sed -i.bak "s|public const string SENTRY_DSN = \".*\";|public const string SENTRY_DSN = \"$(SENTRY_DSN)\";|" vimage/Program.cs
16 | dotnet publish vimage -c Release -r win-x86 --self-contained false /p:PublishSingleFile=true
17 | dotnet publish vimage_settings -c Release -r win-x86 --self-contained false /p:PublishSingleFile=true
18 | @sed -i "s|public const string SENTRY_DSN = \".*\";|public const string SENTRY_DSN = \"\";|" vimage/Program.cs
19 | @rm -f vimage/Program.cs.bak
20 |
--------------------------------------------------------------------------------
/vimage_settings/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace vimage_settings.Properties {
12 |
13 |
14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.3.0.0")]
16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
17 |
18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
19 |
20 | public static Settings Default {
21 | get {
22 | return defaultInstance;
23 | }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/vimage_settings/Source/ContextMenuEditorCanvas.cs:
--------------------------------------------------------------------------------
1 | using System.Windows.Controls;
2 | using System.Windows.Input;
3 | using System.Windows.Shapes;
4 |
5 | namespace vimage_settings
6 | {
7 | public class ContextMenuEditorCanvas : Canvas
8 | {
9 | public ContextMenuItem? MovingItem;
10 | public ContextMenuItem GhostItem = new();
11 | public Rectangle SelectionRect = new() { Height = 4, Fill = System.Windows.Media.Brushes.Black, Opacity = 0.5f };
12 | public int InsertAtIndex = -1;
13 |
14 | public ContextMenuEditorCanvas() : base()
15 | {
16 | }
17 |
18 | protected override void OnMouseUp(MouseButtonEventArgs e)
19 | {
20 | base.OnMouseUp(e);
21 |
22 | if (MovingItem != null)
23 | MovingItem.Dragging = false;
24 | }
25 |
26 | public void SetupGhost(ContextMenuItem item)
27 | {
28 | if (GhostItem.Parent != null)
29 | return;
30 |
31 | GhostItem.UpdateCustomActions();
32 | GhostItem.ItemName.Text = item.ItemName.Text;
33 | GhostItem.ItemFunction.Text = item.ItemFunction.Text;
34 | GhostItem.Indent = item.Indent;
35 | GhostItem.IsEnabled = false;
36 | }
37 |
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/vimage_settings/Source/MainWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using System.Windows;
4 | using System.Windows.Navigation;
5 |
6 | namespace vimage_settings
7 | {
8 | ///
9 | /// Interaction logic for MainWindow.xaml
10 | ///
11 | public partial class MainWindow : Window
12 | {
13 | public MainWindow()
14 | {
15 | InitializeComponent();
16 | DataContext = App.vimageConfig;
17 | }
18 |
19 | private void Hyperlink_RequestNavigate(object sender, RequestNavigateEventArgs e)
20 | {
21 | _ = Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri));
22 | e.Handled = true;
23 | }
24 |
25 | private void Save_Click(object sender, RoutedEventArgs e)
26 | {
27 | ContextMenuEditor.Save();
28 |
29 | try
30 | {
31 | App.vimageConfig?.Save(
32 | System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "config.txt")
33 | );
34 | }
35 | catch (UnauthorizedAccessException)
36 | {
37 | MessageBox.Show(
38 | "vimage does not have write permissions for the folder it's located in.\nPlease place it somewhere else (or set it to run as admin).",
39 | "vimage - Error"
40 | );
41 | }
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/vimage_settings/Source/ControlItem.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## vimage
2 | [torrunt.net/vimage](http://torrunt.net/vimage)
3 |
4 | A simplistic image viewer for Windows, inspired by [vjpeg](http://stereopsis.com/vjpeg/).
5 |
6 | 
7 | 
8 |
9 | ### Created by
10 | Corey Zeke Womack (Torrunt) - [me@torrunt.net](mailto:me@torrunt.net) - [torrunt.net](http://torrunt.net)
11 |
12 | ### Features
13 | - No ugly interface, just the image
14 | - Move it around, resize it, rotate it, flip it and step through images in a folder
15 | - Supports over 100 major file formats (image loading done via [ImageMagick](https://imagemagick.org/script/formats.php#supported))
16 | - Supports animated gifs, pngs and webps (pauseable and the frames can be stepped through)
17 | - Supports transparency
18 | - Toggleable Always on Top Mode
19 | - View Cropping
20 | - Settings, Keyboard/Mouse Bindings and Context Menu are completely configurable
21 |
22 | ### Basic Controls
23 | - Left-Click to Drag
24 | - Right-Click for Context Menu
25 | - Scroll Wheel to Zoom (hold SHIFT to zoom faster)
26 | - Middle-Click to toggle between actual image size and monitor height
27 | - Left/Right Arrows (or Page Up/Down) to navigate between images in a folder
28 | - Up/Down Arrows to Rotate
29 | - F to Flip Horizontally
30 | - S to Toggle Smoothing
31 | - L to Toggle Always On Top mode
32 | - X (hold) + Move Mouse to crop the view of the image
33 | - T (hold) + Scroll Wheel to adjust transparency of the image
34 | - R to Reset Image
35 | - Space to pause Animated Images
36 | - > to step through Animated Image frames
37 |
--------------------------------------------------------------------------------
/vimage_settings/Source/About.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | A simplistic image viewer for Windows.
17 |
18 | torrunt.net/vimage
19 |
20 | github.com/Torrunt/vimage
21 |
22 | Created by Corey Zeke Womack (Torrunt) - me@torrunt.net
23 |
24 | Image Loading via Magick.NET - github.com/dlemstra/Magick.NET
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/vimage_settings/Source/CustomActionItem.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/vimage_settings/vimage_settings.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net9.0-windows
4 | win-x64;win-x86
5 | WinExe
6 | enable
7 | true
8 | true
9 | true
10 | Resources/icon.ico
11 |
12 |
13 |
14 | true
15 | true
16 |
17 |
18 |
19 | TRACE;SETTINGSAPP
20 | true
21 |
22 |
23 |
24 |
25 |
26 | .\Xceed.Wpf.Toolkit.dll
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/vimage_settings/Source/ControlBindings.xaml.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Windows;
3 | using System.Windows.Controls;
4 | using vimage.Common;
5 |
6 | namespace vimage_settings
7 | {
8 | ///
9 | /// Interaction logic for ControlBindings.xaml
10 | ///
11 | public partial class ControlBindings : UserControl
12 | {
13 | public List CustomActionBindings = [];
14 |
15 | public ControlBindings()
16 | {
17 | InitializeComponent();
18 |
19 | if (App.vimageConfig == null)
20 | return;
21 | for (int i = 0; i < App.vimageConfig.Controls.Count; i++)
22 | {
23 | var item = new ControlItem(App.vimageConfig.ControlNames[i], App.vimageConfig.Controls[i]);
24 | _ = ControlsPanel.Children.Add(item);
25 | }
26 | CustomActionBindings = [];
27 | for (int i = 0; i < App.vimageConfig.CustomActionBindings.Count; i++)
28 | {
29 | AddCustomActionBinding(i);
30 | }
31 | }
32 | public void AddCustomActionBinding(int index)
33 | {
34 | if (App.vimageConfig.CustomActionBindings[index] is CustomActionBinding cab)
35 | {
36 | var item = new ControlItem(cab.name, cab.bindings);
37 | _ = ControlsPanel.Children.Add(item);
38 | CustomActionBindings.Add(item);
39 | }
40 | }
41 | public void RemoveCustomActionBinding(int index)
42 | {
43 | ControlsPanel.Children.Remove(CustomActionBindings[index]);
44 | CustomActionBindings.RemoveAt(index);
45 | }
46 |
47 | private void Default_Click(object sender, RoutedEventArgs e)
48 | {
49 | // Reset Controls to Default
50 | App.vimageConfig.SetDefaultControls();
51 |
52 | foreach (ControlItem item in ControlsPanel.Children)
53 | item.UpdateBindings();
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/vimage/vimage.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net9.0-windows
4 | win-x64;win-x86
5 | WinExe
6 | enable
7 | true
8 | true
9 | true
10 | true
11 | Resources/icon.ico
12 | en-US
13 |
14 |
15 |
16 | TRACE;RELEASE
17 | true
18 | false
19 |
20 |
21 |
22 | DEBUG;TRACE
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 | Component
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/vimage_settings/Source/MainWindow.xaml:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
15 | torrunt.net/vimage
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/vimage_settings/Source/CustomActions.xaml.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Windows;
3 | using System.Windows.Controls;
4 | using vimage.Common;
5 |
6 | namespace vimage_settings
7 | {
8 | ///
9 | /// Interaction logic for CustomActions.xaml
10 | ///
11 | public partial class CustomActions : UserControl
12 | {
13 | public CustomActions()
14 | {
15 | InitializeComponent();
16 | DataContext = App.vimageConfig;
17 |
18 | if (App.vimageConfig == null)
19 | return;
20 | LoadItems();
21 | }
22 |
23 | private void LoadItems()
24 | {
25 | if (App.vimageConfig is null) return;
26 | for (int i = 0; i < App.vimageConfig.CustomActions.Count; i++)
27 | {
28 | var item = new CustomActionItem(i, CustomActionItems);
29 | _ = CustomActionItems.Children.Add(item);
30 | }
31 | }
32 |
33 | public void UpdateItemIndices()
34 | {
35 | for (int i = 0; i < CustomActionItems.Children.Count; i++)
36 | {
37 | if (CustomActionItems.Children[i] is CustomActionItem customActionItem)
38 | customActionItem.Index = i;
39 | }
40 | }
41 |
42 | private void Add_Click(object sender, RoutedEventArgs e)
43 | {
44 | int index = CustomActionItems.Children.Count;
45 |
46 | if (App.vimageConfig != null)
47 | {
48 | App.vimageConfig.CustomActions.Add(new CustomAction { name = "ACTION", func = "" });
49 | App.vimageConfig.CustomActionBindings.Add(
50 | new CustomActionBinding { name = "ACTION", bindings = [] }
51 | );
52 | }
53 |
54 | var item = new CustomActionItem(index, CustomActionItems);
55 | _ = CustomActionItems.Children.Add(item);
56 |
57 | if (Application.Current.MainWindow is MainWindow mainWindow)
58 | {
59 | // update controls tab
60 | mainWindow.ControlBindings.AddCustomActionBinding(
61 | index
62 | );
63 | // update context menu function list
64 | mainWindow.ContextMenuEditor.UpdateCustomActions();
65 | }
66 | }
67 |
68 | private void CommandList_Click(object sender, RoutedEventArgs e)
69 | {
70 | new CommandsList().Show();
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | #################
2 | ## Visual Studio
3 | #################
4 |
5 | ## Ignore Visual Studio temporary files, build results, and
6 | ## files generated by popular Visual Studio add-ons.
7 |
8 | packages/
9 |
10 | # User-specific files
11 | *.suo
12 | *.user
13 | *.sln.docstates
14 | .vs
15 |
16 | # Build results
17 |
18 | [Dd]ebug/
19 | [Rr]elease/
20 | build/
21 | [Bb]in/
22 | [Oo]bj/
23 |
24 | # MSTest test Results
25 | [Tt]est[Rr]esult*/
26 | [Bb]uild[Ll]og.*
27 |
28 | *_i.c
29 | *_p.c
30 | *.ilk
31 | *.meta
32 | *.obj
33 | *.pch
34 | *.pdb
35 | *.pgc
36 | *.pgd
37 | *.rsp
38 | *.sbr
39 | *.tlb
40 | *.tli
41 | *.tlh
42 | *.tmp
43 | *.tmp_proj
44 | *.log
45 | *.vspscc
46 | *.vssscc
47 | .builds
48 | *.pidb
49 | *.log
50 | *.scc
51 |
52 | # Visual C++ cache files
53 | ipch/
54 | *.aps
55 | *.ncb
56 | *.opensdf
57 | *.sdf
58 | *.cachefile
59 |
60 | # Visual Studio profiler
61 | *.psess
62 | *.vsp
63 | *.vspx
64 |
65 | # Guidance Automation Toolkit
66 | *.gpState
67 |
68 | # ReSharper is a .NET coding add-in
69 | _ReSharper*/
70 | *.[Rr]e[Ss]harper
71 |
72 | # TeamCity is a build add-in
73 | _TeamCity*
74 |
75 | # DotCover is a Code Coverage Tool
76 | *.dotCover
77 |
78 | # NCrunch
79 | *.ncrunch*
80 | .*crunch*.local.xml
81 |
82 | # Installshield output folder
83 | [Ee]xpress/
84 |
85 | # DocProject is a documentation generator add-in
86 | DocProject/buildhelp/
87 | DocProject/Help/*.HxT
88 | DocProject/Help/*.HxC
89 | DocProject/Help/*.hhc
90 | DocProject/Help/*.hhk
91 | DocProject/Help/*.hhp
92 | DocProject/Help/Html2
93 | DocProject/Help/html
94 |
95 | # Click-Once directory
96 | publish/
97 |
98 | # Publish Web Output
99 | *.Publish.xml
100 | *.pubxml
101 |
102 | # Windows Azure Build Output
103 | csx
104 | *.build.csdef
105 |
106 | # Windows Store app package directory
107 | AppPackages/
108 |
109 | # Others
110 | sql/
111 | *.Cache
112 | ClientBin/
113 | [Ss]tyle[Cc]op.*
114 | ~$*
115 | *~
116 | *.dbmdl
117 | *.[Pp]ublish.xml
118 | *.pfx
119 | *.publishsettings
120 |
121 | # RIA/Silverlight projects
122 | Generated_Code/
123 |
124 | # Backup & report files from converting an old project file to a newer
125 | # Visual Studio version. Backup files are not needed, because we have git ;-)
126 | _UpgradeReport_Files/
127 | Backup*/
128 | UpgradeLog*.XML
129 | UpgradeLog*.htm
130 |
131 | # SQL Server files
132 | App_Data/*.mdf
133 | App_Data/*.ldf
134 |
135 | #############
136 | ## Windows detritus
137 | #############
138 |
139 | # Windows image file caches
140 | Thumbs.db
141 | ehthumbs.db
142 |
143 | # Folder config file
144 | Desktop.ini
145 |
146 | # Recycle Bin used on file shares
147 | $RECYCLE.BIN/
148 |
149 | # Mac crap
150 | .DS_Store
151 |
152 | .env
153 |
--------------------------------------------------------------------------------
/vimage/Program.cs:
--------------------------------------------------------------------------------
1 | // vimage - http://torrunt.net/vimage
2 | // Corey Zeke Womack (Torrunt) - me@torrunt.net
3 |
4 | using System;
5 |
6 | namespace vimage
7 | {
8 | internal class Program
9 | {
10 | public const string SENTRY_DSN = "";
11 |
12 | private static void Main(string[] args)
13 | {
14 | string file = "";
15 | if (args.Length > 0)
16 | {
17 | file = args[0];
18 | if (!System.IO.File.Exists(file))
19 | return;
20 | }
21 |
22 | // Extension supported?
23 | ImageMagick.MagickImageInfo? imageInfo = null;
24 | if (file != "")
25 | {
26 | try
27 | {
28 | imageInfo = new ImageMagick.MagickImageInfo(
29 | file,
30 | Utils.ImageViewerUtils.GetDefaultMagickReadSettings()
31 | );
32 | }
33 | catch (ImageMagick.MagickMissingDelegateErrorException)
34 | {
35 | System.Windows.Forms.MessageBox.Show(
36 | "vimage does not support this file format.",
37 | "vimage - Unknown File Format"
38 | );
39 | return;
40 | }
41 | catch (ImageMagick.MagickCorruptImageErrorException)
42 | {
43 | System.Windows.Forms.MessageBox.Show(
44 | "The file appears to be corrupted and cannot be opened.",
45 | "vimage - Corrupted File"
46 | );
47 | return;
48 | }
49 | if (!Utils.ImageViewerUtils.IsSupportedFileType(imageInfo.Format))
50 | {
51 | System.Windows.Forms.MessageBox.Show(
52 | "vimage does not support this file format.",
53 | "vimage - Unknown File Format"
54 | );
55 | return;
56 | }
57 | }
58 |
59 | // Setup Sentry
60 | Sentry.SentrySdk.Init(options =>
61 | {
62 | options.Dsn = SENTRY_DSN;
63 | options.IsGlobalModeEnabled = true;
64 | options.AutoSessionTracking = true;
65 | });
66 | if (imageInfo != null)
67 | {
68 | Sentry.SentrySdk.ConfigureScope(scope =>
69 | {
70 | scope.Contexts["File"] = new
71 | {
72 | Path = file,
73 | Format = Enum.GetName(imageInfo.Format),
74 | imageInfo.Width,
75 | imageInfo.Height,
76 | imageInfo.Orientation,
77 | };
78 | });
79 | }
80 |
81 | _ = new ImageViewer(file, args);
82 | }
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/vimage_settings/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace vimage_settings.Properties {
12 | using System;
13 |
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal Resources() {
33 | }
34 |
35 | ///
36 | /// Returns the cached ResourceManager instance used by this class.
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | internal static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("vimage_settings.Properties.Resources", typeof(Resources).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// Overrides the current thread's CurrentUICulture property for all
51 | /// resource lookups using this strongly typed resource class.
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | internal static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/vimage_settings/Source/CustomActionItem.xaml.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 | using System.Windows.Controls;
3 | using vimage.Common;
4 |
5 | namespace vimage_settings
6 | {
7 | ///
8 | /// Interaction logic for CustomActionItem.xaml
9 | ///
10 | public partial class CustomActionItem : UserControl
11 | {
12 | private readonly StackPanel ParentPanel;
13 | public int Index;
14 |
15 | public CustomActionItem(int index, StackPanel parentPanel)
16 | {
17 | InitializeComponent();
18 |
19 | Index = index;
20 | ParentPanel = parentPanel;
21 |
22 | ItemName.Text = App.vimageConfig?.CustomActions[Index].name;
23 | ItemAction.Text = App.vimageConfig?.CustomActions[Index].func;
24 |
25 | ItemName.TextChanged += ItemName_TextChanged;
26 | ItemAction.TextChanged += ItemAction_TextChanged;
27 | }
28 |
29 | private void Delete_Click(object sender, RoutedEventArgs e)
30 | {
31 | if (App.vimageConfig is not null)
32 | {
33 | App.vimageConfig.CustomActions.RemoveAt(Index);
34 | App.vimageConfig.CustomActionBindings.RemoveAt(Index);
35 | }
36 |
37 | ParentPanel?.Children.Remove(this);
38 |
39 | if (Application.Current.MainWindow is MainWindow mainWindow)
40 | {
41 | // update controls tab
42 | mainWindow.ControlBindings.RemoveCustomActionBinding(Index);
43 |
44 | // update item indices
45 | mainWindow.CustomActions.UpdateItemIndices();
46 | // update context menu function list
47 | mainWindow.ContextMenuEditor.UpdateCustomActions();
48 | }
49 | }
50 |
51 | private void ItemName_TextChanged(object sender, TextChangedEventArgs e)
52 | {
53 | if (App.vimageConfig == null)
54 | return;
55 | App.vimageConfig.CustomActions[Index] = new CustomAction { name = ItemName.Text, func = ItemAction.Text };
56 |
57 | // update control binding
58 | var bindings = App.vimageConfig.CustomActionBindings[Index].bindings;
59 | App.vimageConfig.CustomActionBindings[Index] = new CustomActionBinding { name = ItemName.Text, bindings = bindings };
60 |
61 | if (Application.Current.MainWindow is MainWindow mainWindow)
62 | {
63 | // update controls tab
64 | mainWindow.ControlBindings.CustomActionBindings[Index].ControlName.Content = ItemName.Text;
65 | // update context menu function list
66 | mainWindow.ContextMenuEditor.UpdateCustomActions();
67 | }
68 | }
69 | private void ItemAction_TextChanged(object sender, TextChangedEventArgs e)
70 | {
71 | if (App.vimageConfig == null)
72 | return;
73 | App.vimageConfig.CustomActions[Index] = new CustomAction { name = ItemName.Text, func = ItemAction.Text };
74 | }
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/vimage_settings/Source/CustomActions.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
35 |
50 |
51 | %f = current file (with quotes)
52 | %d = current directory (without quotes)
53 |
54 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/vimage/Utils/WindowsFileSorting.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Runtime.InteropServices;
5 |
6 | namespace vimage.Utils
7 | {
8 | internal partial class WindowsFileSorting
9 | {
10 | [LibraryImport("shlwapi.dll", StringMarshalling = StringMarshalling.Utf16)]
11 | public static partial int StrCmpLogicalW(string psz1, string psz2);
12 |
13 | [System.Security.SuppressUnmanagedCodeSecurity]
14 | internal static partial class SafeNativeMethods
15 | {
16 | [LibraryImport("shlwapi.dll", StringMarshalling = StringMarshalling.Utf16)]
17 | public static partial int StrCmpLogicalW(string psz1, string psz2);
18 | }
19 |
20 | public sealed class NaturalStringComparer : IComparer
21 | {
22 | public int Compare(string? a, string? b)
23 | {
24 | return SafeNativeMethods.StrCmpLogicalW(a ?? "", b ?? "");
25 | }
26 | }
27 |
28 | public sealed class NaturalFileInfoNameComparer : IComparer
29 | {
30 | public int Compare(FileInfo? a, FileInfo? b)
31 | {
32 | return SafeNativeMethods.StrCmpLogicalW(a?.Name ?? "", b?.Name ?? "");
33 | }
34 | }
35 |
36 | public static string? GetWindowsSortOrder(string fileName)
37 | {
38 | var directory = Path.GetDirectoryName(fileName);
39 | if (directory is null)
40 | return null;
41 | var parentFolder = Path.GetFileName(directory);
42 | if (parentFolder is null)
43 | return null;
44 |
45 | var shellWindowsType = Type.GetTypeFromProgID("Shell.Application");
46 | if (shellWindowsType is null)
47 | return null;
48 | dynamic? shell = Activator.CreateInstance(shellWindowsType);
49 | if (shell is null)
50 | return null;
51 | foreach (var window in shell.Windows())
52 | {
53 | dynamic? view = window.Document;
54 | if (view is null)
55 | continue;
56 |
57 | var folderPath = view.Folder?.Self?.Path;
58 | if (string.IsNullOrEmpty(folderPath))
59 | continue;
60 | if (!string.Equals(folderPath, directory, StringComparison.OrdinalIgnoreCase))
61 | continue;
62 |
63 | string sortColumns = view.SortColumns;
64 |
65 | // can be sorted by multiple columns (eg: date then name) - just return first one
66 | int firstSemi = sortColumns.IndexOf(';');
67 | string firstProp = sortColumns[5..firstSemi]; // strip off "prop:" prefix
68 |
69 | return firstProp;
70 | }
71 | return null;
72 | }
73 |
74 | private static bool HasProperty(dynamic obj, string name)
75 | {
76 | try
77 | {
78 | var val = obj.GetType()
79 | .InvokeMember(
80 | name,
81 | System.Reflection.BindingFlags.GetProperty,
82 | null,
83 | obj,
84 | null
85 | );
86 | return true;
87 | }
88 | catch
89 | {
90 | return false;
91 | }
92 | }
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/vimage_settings/Source/ContextMenuItem.xaml:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
41 |
42 |
43 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/vimage_settings/Source/ContextMenu.xaml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/vimage.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.5.2.0
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "vimage", "vimage\vimage.csproj", "{92394A27-D9C5-1F3C-9D83-93543FA5CDB2}"
7 | EndProject
8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "vimage_settings", "vimage_settings\vimage_settings.csproj", "{80DD9197-20D6-164E-9F06-82E5645C1AFF}"
9 | EndProject
10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "vimage.Common", "vimage.Common\vimage.Common.csproj", "{27028A02-7BA1-4CE4-A12F-9D5CBD333F58}"
11 | EndProject
12 | Global
13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
14 | Debug|Any CPU = Debug|Any CPU
15 | Debug|x64 = Debug|x64
16 | Debug|x86 = Debug|x86
17 | Release|Any CPU = Release|Any CPU
18 | Release|x64 = Release|x64
19 | Release|x86 = Release|x86
20 | EndGlobalSection
21 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
22 | {92394A27-D9C5-1F3C-9D83-93543FA5CDB2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
23 | {92394A27-D9C5-1F3C-9D83-93543FA5CDB2}.Debug|Any CPU.Build.0 = Debug|Any CPU
24 | {92394A27-D9C5-1F3C-9D83-93543FA5CDB2}.Debug|x64.ActiveCfg = Debug|Any CPU
25 | {92394A27-D9C5-1F3C-9D83-93543FA5CDB2}.Debug|x64.Build.0 = Debug|Any CPU
26 | {92394A27-D9C5-1F3C-9D83-93543FA5CDB2}.Debug|x86.ActiveCfg = Debug|Any CPU
27 | {92394A27-D9C5-1F3C-9D83-93543FA5CDB2}.Debug|x86.Build.0 = Debug|Any CPU
28 | {92394A27-D9C5-1F3C-9D83-93543FA5CDB2}.Release|Any CPU.ActiveCfg = Release|Any CPU
29 | {92394A27-D9C5-1F3C-9D83-93543FA5CDB2}.Release|Any CPU.Build.0 = Release|Any CPU
30 | {92394A27-D9C5-1F3C-9D83-93543FA5CDB2}.Release|x64.ActiveCfg = Release|Any CPU
31 | {92394A27-D9C5-1F3C-9D83-93543FA5CDB2}.Release|x64.Build.0 = Release|Any CPU
32 | {92394A27-D9C5-1F3C-9D83-93543FA5CDB2}.Release|x86.ActiveCfg = Release|Any CPU
33 | {92394A27-D9C5-1F3C-9D83-93543FA5CDB2}.Release|x86.Build.0 = Release|Any CPU
34 | {80DD9197-20D6-164E-9F06-82E5645C1AFF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
35 | {80DD9197-20D6-164E-9F06-82E5645C1AFF}.Debug|Any CPU.Build.0 = Debug|Any CPU
36 | {80DD9197-20D6-164E-9F06-82E5645C1AFF}.Debug|x64.ActiveCfg = Debug|Any CPU
37 | {80DD9197-20D6-164E-9F06-82E5645C1AFF}.Debug|x64.Build.0 = Debug|Any CPU
38 | {80DD9197-20D6-164E-9F06-82E5645C1AFF}.Debug|x86.ActiveCfg = Debug|Any CPU
39 | {80DD9197-20D6-164E-9F06-82E5645C1AFF}.Debug|x86.Build.0 = Debug|Any CPU
40 | {80DD9197-20D6-164E-9F06-82E5645C1AFF}.Release|Any CPU.ActiveCfg = Release|Any CPU
41 | {80DD9197-20D6-164E-9F06-82E5645C1AFF}.Release|Any CPU.Build.0 = Release|Any CPU
42 | {80DD9197-20D6-164E-9F06-82E5645C1AFF}.Release|x64.ActiveCfg = Release|Any CPU
43 | {80DD9197-20D6-164E-9F06-82E5645C1AFF}.Release|x64.Build.0 = Release|Any CPU
44 | {80DD9197-20D6-164E-9F06-82E5645C1AFF}.Release|x86.ActiveCfg = Release|Any CPU
45 | {80DD9197-20D6-164E-9F06-82E5645C1AFF}.Release|x86.Build.0 = Release|Any CPU
46 | {27028A02-7BA1-4CE4-A12F-9D5CBD333F58}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
47 | {27028A02-7BA1-4CE4-A12F-9D5CBD333F58}.Debug|Any CPU.Build.0 = Debug|Any CPU
48 | {27028A02-7BA1-4CE4-A12F-9D5CBD333F58}.Debug|x64.ActiveCfg = Debug|Any CPU
49 | {27028A02-7BA1-4CE4-A12F-9D5CBD333F58}.Debug|x64.Build.0 = Debug|Any CPU
50 | {27028A02-7BA1-4CE4-A12F-9D5CBD333F58}.Debug|x86.ActiveCfg = Debug|Any CPU
51 | {27028A02-7BA1-4CE4-A12F-9D5CBD333F58}.Debug|x86.Build.0 = Debug|Any CPU
52 | {27028A02-7BA1-4CE4-A12F-9D5CBD333F58}.Release|Any CPU.ActiveCfg = Release|Any CPU
53 | {27028A02-7BA1-4CE4-A12F-9D5CBD333F58}.Release|Any CPU.Build.0 = Release|Any CPU
54 | {27028A02-7BA1-4CE4-A12F-9D5CBD333F58}.Release|x64.ActiveCfg = Release|Any CPU
55 | {27028A02-7BA1-4CE4-A12F-9D5CBD333F58}.Release|x64.Build.0 = Release|Any CPU
56 | {27028A02-7BA1-4CE4-A12F-9D5CBD333F58}.Release|x86.ActiveCfg = Release|Any CPU
57 | {27028A02-7BA1-4CE4-A12F-9D5CBD333F58}.Release|x86.Build.0 = Release|Any CPU
58 | EndGlobalSection
59 | GlobalSection(SolutionProperties) = preSolution
60 | HideSolutionNode = FALSE
61 | EndGlobalSection
62 | GlobalSection(ExtensibilityGlobals) = postSolution
63 | SolutionGuid = {4ED5620A-F2AF-409A-BBD2-C04B98A544CB}
64 | EndGlobalSection
65 | EndGlobal
66 |
--------------------------------------------------------------------------------
/vimage/Display/AnimatedImage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using SFML.Graphics;
3 |
4 | namespace vimage.Display
5 | {
6 | internal class AnimatedImageData
7 | {
8 | public Texture[] Frames = [];
9 | public int[] FrameDelays = [];
10 | public int FrameCount = 0;
11 | public bool FullyLoaded = false;
12 | public bool CancelLoading = false;
13 |
14 | private bool _Smooth = true;
15 | public bool Smooth
16 | {
17 | get { return _Smooth; }
18 | set
19 | {
20 | _Smooth = value;
21 | if (FullyLoaded)
22 | {
23 | foreach (var texture in Frames)
24 | texture.Smooth = _Smooth;
25 | }
26 | }
27 | }
28 |
29 | private bool _Mipmap = true;
30 | public bool Mipmap
31 | {
32 | get { return _Mipmap; }
33 | set
34 | {
35 | _Mipmap = value;
36 | if (FullyLoaded && _Mipmap)
37 | {
38 | foreach (var texture in Frames)
39 | texture.GenerateMipmap();
40 | }
41 | }
42 | }
43 |
44 | public AnimatedImageData() { }
45 | }
46 |
47 | internal class AnimatedImage : DisplayObject
48 | {
49 | public AnimatedImageData Data;
50 | public Sprite Sprite;
51 | public new Texture Texture
52 | {
53 | get { return Sprite.Texture; }
54 | private set { }
55 | }
56 |
57 | public int CurrentFrame;
58 | public int TotalFrames
59 | {
60 | get { return Data.Frames.Length; }
61 | private set { }
62 | }
63 |
64 | public bool Playing = true;
65 | private bool _Looping = true;
66 | public bool Looping
67 | {
68 | get { return _Looping; }
69 | set
70 | {
71 | _Looping = value;
72 | Finished = false;
73 | }
74 | }
75 | public bool Finished = false;
76 |
77 | /// Keeps track of when to change frame. Resets on frame change.
78 | public float CurrentTime;
79 | private float CurrentFrameDelay;
80 |
81 | /// Default Frame Delay for animated images that don't define it.
82 | public static readonly int DEFAULT_FRAME_DELAY = 100;
83 |
84 | public AnimatedImage(AnimatedImageData data)
85 | {
86 | Data = data;
87 |
88 | Sprite = new Sprite(data.Frames[0]);
89 | AddChild(Sprite);
90 |
91 | CurrentTime = 0;
92 | CurrentFrameDelay = data.FrameDelays[0];
93 | }
94 |
95 | public bool Update(float dt)
96 | {
97 | if (!Playing)
98 | return false;
99 |
100 | CurrentTime += dt;
101 |
102 | while (CurrentTime > CurrentFrameDelay)
103 | {
104 | if (Looping || CurrentFrame < TotalFrames - 1)
105 | {
106 | if (CurrentFrame == TotalFrames - 1)
107 | _ = SetFrame(0);
108 | else
109 | NextFrame();
110 | }
111 | else
112 | Finished = true;
113 |
114 | if (CurrentFrameDelay == 0)
115 | CurrentTime = 0;
116 | else
117 | CurrentTime -= CurrentFrameDelay;
118 |
119 | return true;
120 | }
121 |
122 | return false;
123 | }
124 |
125 | public bool SetFrame(int number)
126 | {
127 | if (number >= TotalFrames)
128 | return false;
129 |
130 | if (!Data.FullyLoaded && Data.Frames[number] == null)
131 | return false; // Hang if next frame hasn't loaded yet
132 |
133 | CurrentFrame = number;
134 | Finished = CurrentFrame == TotalFrames - 1;
135 |
136 | Sprite.Texture = Data.Frames[CurrentFrame];
137 | CurrentFrameDelay = Data.FrameDelays[CurrentFrame];
138 |
139 | return true;
140 | }
141 |
142 | public void NextFrame()
143 | {
144 | _ = SetFrame(Math.Min(CurrentFrame + 1, TotalFrames));
145 | }
146 |
147 | public void PrevFrame()
148 | {
149 | _ = SetFrame(Math.Max(CurrentFrame - 1, 0));
150 | }
151 |
152 | public void Stop()
153 | {
154 | Playing = false;
155 | }
156 |
157 | public void Play()
158 | {
159 | Playing = true;
160 | }
161 |
162 | public void GotoAndPlay(int number)
163 | {
164 | _ = SetFrame(number);
165 | Play();
166 | }
167 |
168 | public void GotoAndStop(int number)
169 | {
170 | _ = SetFrame(number);
171 | Stop();
172 | }
173 | }
174 | }
175 |
--------------------------------------------------------------------------------
/vimage_settings/Source/CommandsList.xaml:
--------------------------------------------------------------------------------
1 |
13 |
14 |
15 |
16 | For custom actions and command line arguments.
17 |
18 |
19 |
20 |
21 |
22 |
23 | -x 0
24 | -y 0
25 | -zoom 0.0
26 | -rotation 0
27 | -sizeX 0
28 | -sizeY 0
29 | -centerX 0.0
30 | -centerY 0.0
31 | -colour #FFFFFFFF
32 | -alpha 0
33 |
34 | -frame 0
35 | -next
36 | -prev
37 | -random
38 | -reset
39 | -clearMemory
40 | -rerenderSVG
41 |
42 | -fitToMonitorHeight
43 | -fitToMonitorWidth
44 | -fitToMonitorAuto
45 |
46 |
47 | -toggleSync
48 |
49 |
50 |
51 | -flip
52 | -smoothing
53 | -background
54 | -lock
55 | -alwaysOnTop
56 | -clickThrough
57 | -titleBar
58 | -taskbarIcon
59 | -animation
60 | -defaultTransparency
61 |
62 |
63 | position of the window
64 |
65 | zoom level (1 = full size)
66 | rotation of the image (0, 90, 180, 270)
67 | size of the window
68 |
69 | position of the view center (use with sizeX/sizeY to crop view)
70 |
71 | image tint (white = no tint)
72 | the transparency of the image (0-255)
73 |
74 | set the current frame of the animated gif
75 | go to the next image
76 | go to the previous image
77 | go to a random image in the folder
78 | reset all transformations (position, zoom, colour, rotation, etc)
79 | remove all current images/animations from vimage's memory
80 | Re-render image (if vector graphic) at the current zoom
81 |
82 | Resizes image to the height of the current monitor
83 | Resizes image to the width of the current monitor
84 | Resizes image to the width or height of the current monitor
85 | based on it's orientation
86 |
87 | all following toggle commands will sync to the same value
88 |
89 | put 0/1 after a toggle command to set directly:
90 |
91 | flips image left/right
92 | toggles smoothing
93 | toggles backgroud
94 | toggles image lock
95 | toggles Always On Top mode
96 | toggles Click-Through-Able mode
97 | toggles window Title Bar
98 | hides/shows window in the task bar
99 | pauses/plays animation
100 | toggles default image transparency
101 |
102 |
103 |
104 |
105 |
106 |
--------------------------------------------------------------------------------
/vimage.Common/Actions.cs:
--------------------------------------------------------------------------------
1 | using System.Text.RegularExpressions;
2 |
3 | namespace vimage.Common
4 | {
5 | public enum Action
6 | {
7 | None,
8 |
9 | Drag,
10 | Close,
11 | OpenContextMenu,
12 | PrevImage,
13 | NextImage,
14 |
15 | RotateClockwise,
16 | RotateAntiClockwise,
17 | Flip,
18 | FitToMonitorHeight,
19 | FitToMonitorWidth,
20 | FitToMonitorAuto,
21 | FitToMonitorAlt,
22 | ZoomIn,
23 | ZoomOut,
24 | ZoomFaster,
25 | ZoomAlt,
26 | DragLimitToMonitorBounds,
27 |
28 | ToggleSmoothing,
29 | ToggleBackground,
30 | ToggleLock,
31 | ToggleAlwaysOnTop,
32 | ToggleClickThroughAble,
33 | ToggleTitleBar,
34 |
35 | PauseAnimation,
36 | PrevFrame,
37 | NextFrame,
38 |
39 | OpenSettings,
40 | ResetImage,
41 | OpenAtLocation,
42 | Delete,
43 | Copy,
44 | CopyAsImage,
45 | OpenDuplicateImage,
46 | OpenFullDuplicateImage,
47 | RandomImage,
48 |
49 | MoveLeft,
50 | MoveRight,
51 | MoveUp,
52 | MoveDown,
53 |
54 | TransparencyToggle,
55 | TransparencyInc,
56 | TransparencyDec,
57 | Crop,
58 | UndoCrop,
59 | ExitAll,
60 | RerenderSVG,
61 |
62 | VisitWebsite,
63 |
64 | SortName,
65 | SortDate,
66 | SortDateModified,
67 | SortDateCreated,
68 | SortSize,
69 | SortAscending,
70 | SortDescending,
71 |
72 | Custom,
73 | }
74 |
75 | public static partial class Actions
76 | {
77 | public static List Names =
78 | [
79 | "",
80 | "DRAG",
81 | "CLOSE",
82 | "OPEN CONTEXT MENU",
83 | "PREV IMAGE",
84 | "NEXT IMAGE",
85 | "ROTATE CLOCKWISE",
86 | "ROTATE ANTICLOCKWISE",
87 | "FLIP",
88 | "FIT TO HEIGHT",
89 | "FIT TO WIDTH",
90 | "FIT TO AUTO",
91 | "FIT TO ALT",
92 | "ZOOM IN",
93 | "ZOOM OUT",
94 | "ZOOM FASTER",
95 | "ZOOM ALT",
96 | "DRAG LIMIT TO MONITOR BOUNDS",
97 | "TOGGLE SMOOTHING",
98 | "TOGGLE BACKGROUND",
99 | "TOGGLE LOCK",
100 | "ALWAYS ON TOP",
101 | "CLICK-THROUGH_ABLE",
102 | "TOGGLE TITLE BAR",
103 | "TOGGLE ANIMATION",
104 | "PREV FRAME",
105 | "NEXT FRAME",
106 | "OPEN SETTINGS",
107 | "RESET IMAGE",
108 | "OPEN FILE LOCATION",
109 | "DELETE",
110 | "COPY",
111 | "COPY AS IMAGE",
112 | "OPEN DUPLICATE",
113 | "OPEN DUPLICATE FULL",
114 | "RANDOM IMAGE",
115 | "MOVE LEFT",
116 | "MOVE RIGHT",
117 | "MOVE UP",
118 | "MOVE DOWN",
119 | "TOGGLE IMAGE TRANSPARENCY",
120 | "TRANSPARENCY INC",
121 | "TRANSPARENCY DEC",
122 | "CROP",
123 | "UNDO CROP",
124 | "EXIT ALL INSTANCES",
125 | "RERENDER SVG",
126 | "VISIT WEBSITE",
127 | "SORT NAME",
128 | "SORT DATE",
129 | "SORT DATE MODIFIED",
130 | "SORT DATE CREATED",
131 | "SORT SIZE",
132 | "SORT ASCENDING",
133 | "SORT DESCENDING",
134 | ];
135 |
136 | public static string ToNameString(this Action action)
137 | {
138 | return Names[(int)action];
139 | }
140 |
141 | public static Action StringToAction(string action)
142 | {
143 | return (Action)Names.IndexOf(action);
144 | }
145 |
146 | /// List of actions that can be used in the Context Menu.
147 | public static readonly Action[] MenuActions =
148 | [
149 | Action.Close,
150 | Action.NextImage,
151 | Action.PrevImage,
152 | Action.RotateClockwise,
153 | Action.RotateAntiClockwise,
154 | Action.Flip,
155 | Action.FitToMonitorHeight,
156 | Action.FitToMonitorWidth,
157 | Action.FitToMonitorAuto,
158 | Action.ResetImage,
159 | Action.ToggleSmoothing,
160 | Action.ToggleBackground,
161 | Action.TransparencyToggle,
162 | Action.ToggleLock,
163 | Action.ToggleAlwaysOnTop,
164 | Action.ToggleClickThroughAble,
165 | Action.ToggleTitleBar,
166 | Action.OpenAtLocation,
167 | Action.Delete,
168 | Action.Copy,
169 | Action.CopyAsImage,
170 | Action.OpenDuplicateImage,
171 | Action.OpenFullDuplicateImage,
172 | Action.RandomImage,
173 | Action.UndoCrop,
174 | Action.ExitAll,
175 | Action.PauseAnimation,
176 | Action.NextFrame,
177 | Action.PrevFrame,
178 | Action.OpenSettings,
179 | Action.VisitWebsite,
180 | Action.SortName,
181 | Action.SortDate,
182 | Action.SortDateModified,
183 | Action.SortDateCreated,
184 | Action.SortSize,
185 | Action.SortAscending,
186 | Action.SortDescending,
187 | ];
188 |
189 | ///
190 | /// Split exe and arguments by the first space (regex to exclude the spaces within the quotes of the exe's path)
191 | ///
192 | [GeneratedRegex("(?<=^[^\"]*(?:\"[^\"]*\"[^\"]*)*) (?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)")]
193 | public static partial Regex CustomActionSplitRegex();
194 | }
195 | }
196 |
--------------------------------------------------------------------------------
/vimage_settings/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | text/microsoft-resx
107 |
108 |
109 | 2.0
110 |
111 |
112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
113 |
114 |
115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
--------------------------------------------------------------------------------
/vimage_settings/Source/ControlItem.xaml.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Windows;
3 | using System.Windows.Controls;
4 | using System.Windows.Input;
5 | using vimage.Common;
6 |
7 | namespace vimage_settings
8 | {
9 | ///
10 | /// Interaction logic for ControlItem.xaml
11 | ///
12 | public partial class ControlItem : UserControl
13 | {
14 | public List Controls = [];
15 | private bool CanRecordMouseButton = false;
16 | private readonly List KeysHeld = [];
17 |
18 | public ControlItem()
19 | {
20 | InitializeComponent();
21 | }
22 |
23 | public ControlItem(string name, List controls)
24 | {
25 | InitializeComponent();
26 |
27 | ControlName.Content = name;
28 | Controls = controls;
29 | UpdateBindings();
30 | }
31 |
32 | private void Clear_Click(object sender, RoutedEventArgs e)
33 | {
34 | Controls.Clear();
35 | ControlSetting.Text = "";
36 | }
37 |
38 | public void UpdateBindings()
39 | {
40 | ControlSetting.Text = Config.ControlsToString(Controls);
41 | }
42 |
43 | private void OnKeyDown(object sender, KeyEventArgs e)
44 | {
45 | e.Handled = true;
46 |
47 | int key = ConvertWindowsKey(e.Key == Key.System ? e.SystemKey : e.Key);
48 | if (KeysHeld.Count == 0 || KeysHeld[^1] != key)
49 | {
50 | KeysHeld.Add(key);
51 | if (KeysHeld.Count > 2)
52 | KeysHeld.RemoveAt(0);
53 | }
54 | }
55 |
56 | private void OnKeyUp(object sender, KeyEventArgs e)
57 | {
58 | e.Handled = true;
59 |
60 | int key = ConvertWindowsKey(e.Key == Key.System ? e.SystemKey : e.Key);
61 | _ = KeysHeld.Remove(key);
62 |
63 | RecordControl(key);
64 | }
65 |
66 | private void ControlSetting_MouseUp(object sender, MouseButtonEventArgs e)
67 | {
68 | if (!ControlSetting.IsFocused)
69 | return;
70 | if (!CanRecordMouseButton)
71 | {
72 | CanRecordMouseButton = true;
73 | return;
74 | }
75 | e.Handled = true;
76 |
77 | // Record Mouse Button Press
78 | int button = e.ChangedButton switch
79 | {
80 | MouseButton.Left => 0,
81 | MouseButton.Right => 1,
82 | MouseButton.Middle => 2,
83 | MouseButton.XButton1 => 3,
84 | MouseButton.XButton2 => 4,
85 | _ => -1,
86 | };
87 | RecordControl(button + Config.MouseCodeOffset);
88 | ControlSetting.ReleaseMouseCapture();
89 | }
90 |
91 | private void ControlSetting_MouseWheel(object sender, MouseWheelEventArgs e)
92 | {
93 | if (!ControlSetting.IsFocused)
94 | return;
95 | e.Handled = true;
96 |
97 | // Record Mouse Wheel Direction
98 | int bind = -1;
99 | if (e.Delta > 0)
100 | bind = Config.MOUSE_SCROLL_UP;
101 | else if (e.Delta < 0)
102 | bind = Config.MOUSE_SCROLL_DOWN;
103 |
104 | RecordControl(bind);
105 | }
106 |
107 | private static int ConvertWindowsKey(Key keyCode)
108 | {
109 | var key = keyCode.ToString().ToUpper();
110 | if (key is null)
111 | return -1;
112 |
113 | // Record Key Press
114 | if (
115 | key.Equals("SCROLL")
116 | || key.Equals("NUMLOCK")
117 | || key.Equals("CAPITAL")
118 | || key.Equals("LWIN")
119 | || key.Equals("RWIN")
120 | )
121 | return -1;
122 |
123 | // fix up some weird names KeyEventArgs gives
124 | key = key switch
125 | {
126 | "OEMOPENBRACKETS" => "[",
127 | "OEM3" => "`",
128 | "OEM6" => "]",
129 | "OEM5" => "\\",
130 | "OEM1" => ";",
131 | "OEM7" => "'",
132 | "OEMMINUS" => "MINUS",
133 | "OEMPLUS" => "PLUS",
134 | _ => key,
135 | };
136 |
137 | // fix number keys (remove D from D#)
138 | if (key.Length == 2 && key[0] == 'D')
139 | key = key[1..];
140 |
141 | return (int)Config.StringToKey(key);
142 | }
143 |
144 | private void RecordControl(int bind, bool canBeKeyCombo = true)
145 | {
146 | if (bind == -1)
147 | return;
148 | int i = Controls.IndexOf(bind);
149 | if (!(i == -1 || (i > 1 && Controls[i - 2] == -2)))
150 | return;
151 |
152 | if (canBeKeyCombo)
153 | {
154 | if (KeysHeld.Count > 0 && KeysHeld[^1] != bind)
155 | {
156 | // Key Combo? (eg: CTRL+C)
157 | int c = KeysHeld[^1];
158 |
159 | if (i != -1 && Controls.IndexOf(c) != -1)
160 | return;
161 | Controls.Add(-2);
162 | Controls.Add(c);
163 | }
164 | else if (i != -1)
165 | return;
166 | }
167 | Controls.Add(bind);
168 | UpdateBindings();
169 | }
170 |
171 | private void ControlSetting_GotFocus(object sender, RoutedEventArgs e)
172 | {
173 | Window window = Window.GetWindow(this);
174 | if (window == null)
175 | return;
176 | window.PreviewKeyDown += OnKeyDown;
177 | window.PreviewKeyUp += OnKeyUp;
178 | ControlSetting.PreviewMouseUp += ControlSetting_MouseUp;
179 | ControlSetting.PreviewMouseWheel += ControlSetting_MouseWheel;
180 | CanRecordMouseButton = false;
181 | }
182 |
183 | private void ControlSetting_LostFocus(object sender, RoutedEventArgs e)
184 | {
185 | Window window = Window.GetWindow(this);
186 | if (window == null)
187 | return;
188 | window.PreviewKeyDown -= OnKeyDown;
189 | window.PreviewKeyUp -= OnKeyUp;
190 | ControlSetting.PreviewMouseUp -= ControlSetting_MouseUp;
191 | ControlSetting.PreviewMouseWheel -= ControlSetting_MouseWheel;
192 | }
193 | }
194 | }
195 |
--------------------------------------------------------------------------------
/vimage/Display/DisplayObject.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using SFML.Graphics;
3 | using SFML.System;
4 |
5 | namespace vimage.Display
6 | {
7 | internal class DisplayObject : Transformable, Drawable
8 | {
9 | private readonly List Children = [];
10 | private int DrawListIndex = 0;
11 | public DisplayObject? Parent = null;
12 |
13 | public bool Visible = true;
14 |
15 | public TextureInfo Texture;
16 |
17 | public DisplayObject()
18 | {
19 | Texture = new TextureInfo(this);
20 | }
21 |
22 | public int NumChildren
23 | {
24 | get { return Children.Count; }
25 | }
26 |
27 | public void AddChild(Transformable child)
28 | {
29 | Children.Add(child);
30 | if (child is DisplayObject displayObject)
31 | {
32 | displayObject.Parent = this;
33 | displayObject.OnAdded();
34 | }
35 | }
36 |
37 | public void AddChildAt(Transformable child, int index)
38 | {
39 | Children.Insert(index, child);
40 | if (child is DisplayObject displayObject)
41 | {
42 | displayObject.Parent = this;
43 | displayObject.OnAdded();
44 | }
45 | }
46 |
47 | public void RemoveChild(Transformable child)
48 | {
49 | for (int i = 0; i < Children.Count; i++)
50 | {
51 | if (!Children[i].Equals(child))
52 | continue;
53 |
54 | if (child is DisplayObject displayObject)
55 | {
56 | displayObject.OnRemoved();
57 | displayObject.Parent = null;
58 | }
59 |
60 | Children.RemoveAt(i);
61 | if (i <= DrawListIndex)
62 | DrawListIndex--;
63 | break;
64 | }
65 | }
66 |
67 | public void RemoveChildAt(int index)
68 | {
69 | RemoveChild(GetChildAt(index));
70 | }
71 |
72 | public void Clear()
73 | {
74 | while (NumChildren > 0)
75 | RemoveChildAt(0);
76 |
77 | Children.Clear();
78 | DrawListIndex = 0;
79 | }
80 |
81 | public Transformable GetChildAt(int i)
82 | {
83 | return Children[i];
84 | }
85 |
86 | public virtual void OnAdded() { }
87 |
88 | public virtual void OnRemoved() { }
89 |
90 | public void Draw(RenderTarget Target, RenderStates states)
91 | {
92 | states.Transform *= Transform;
93 | for (DrawListIndex = 0; DrawListIndex < Children.Count; DrawListIndex++)
94 | {
95 | if (Children[DrawListIndex] is DisplayObject displayObject)
96 | {
97 | if (displayObject.Visible)
98 | displayObject.Draw(Target, states);
99 | }
100 | else if (Children[DrawListIndex] is Drawable drawable)
101 | drawable.Draw(Target, states);
102 | }
103 | }
104 |
105 | public float X
106 | {
107 | get { return Position.X; }
108 | set { Position = new Vector2f(value, Position.Y); }
109 | }
110 | public float Y
111 | {
112 | get { return Position.Y; }
113 | set { Position = new Vector2f(Position.X, value); }
114 | }
115 |
116 | public void SetPosition(float x, float y)
117 | {
118 | Position = new Vector2f(x, y);
119 | }
120 |
121 | public void SetPosition(Vector2f pos)
122 | {
123 | Position = pos;
124 | }
125 |
126 | public void Move(float offsetX, float offsetY)
127 | {
128 | Position = new Vector2f(X + offsetX, Y + offsetY);
129 | }
130 |
131 | public void Move(Vector2f offset)
132 | {
133 | Position = new Vector2f(X + offset.X, Y + offset.Y);
134 | }
135 |
136 | public float ScaleX
137 | {
138 | get { return Scale.X; }
139 | set { Scale = new Vector2f(value, Scale.Y); }
140 | }
141 | public float ScaleY
142 | {
143 | get { return Scale.Y; }
144 | set { Scale = new Vector2f(Scale.X, value); }
145 | }
146 |
147 | public void SetScale(float scaleX, float scaleY)
148 | {
149 | Scale = new Vector2f(scaleX, scaleY);
150 | }
151 |
152 | public void SetScale(float scale)
153 | {
154 | Scale = new Vector2f(scale, scale);
155 | }
156 |
157 | public void SetScale(Vector2f scale)
158 | {
159 | Scale = scale;
160 | }
161 |
162 | public void Rotate(float amount)
163 | {
164 | if (Rotation + amount > 180)
165 | Rotation = Rotation + amount - 360;
166 | else if (Rotation + amount < -180)
167 | Rotation = Rotation + amount + 360;
168 | else
169 | Rotation += amount;
170 | }
171 |
172 | public Color _Color = Color.White;
173 | public Color Color
174 | {
175 | get { return _Color; }
176 | set
177 | {
178 | _Color = value;
179 | for (int i = 0; i < Children.Count; i++)
180 | {
181 | if (Children[i] is Sprite spite)
182 | spite.Color = _Color;
183 | else if (Children[i] is DisplayObject displayObject)
184 | displayObject.Color = _Color;
185 | }
186 | }
187 | }
188 | }
189 |
190 | internal class TextureInfo(DisplayObject obj)
191 | {
192 | private readonly DisplayObject Obj = obj;
193 | public Vector2u Size = new();
194 |
195 | private bool _Smooth = true;
196 | public bool Smooth
197 | {
198 | get { return _Smooth; }
199 | set
200 | {
201 | _Smooth = value;
202 | for (int i = 0; i < Obj.NumChildren; i++)
203 | {
204 | var child = Obj.GetChildAt(i);
205 | if (child is Sprite sprite)
206 | sprite.Texture.Smooth = _Smooth;
207 | else if (child is DisplayObject displayObject)
208 | displayObject.Texture.Smooth = _Smooth;
209 | }
210 | }
211 | }
212 |
213 | private bool _Mipmap = true;
214 | public bool Mipmap
215 | {
216 | get { return _Mipmap; }
217 | set
218 | {
219 | _Mipmap = value;
220 | if (!_Mipmap)
221 | return;
222 |
223 | for (int i = 0; i < Obj.NumChildren; i++)
224 | {
225 | var child = Obj.GetChildAt(i);
226 | if (child is Sprite sprite)
227 | sprite.Texture.GenerateMipmap();
228 | else if (child is DisplayObject displayObject)
229 | displayObject.Texture.Mipmap = true;
230 | }
231 | }
232 | }
233 | }
234 | }
235 |
--------------------------------------------------------------------------------
/vimage_settings/Source/ContextMenu.xaml.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Windows;
3 | using System.Windows.Controls;
4 |
5 | namespace vimage_settings
6 | {
7 | ///
8 | /// Interaction logic for ContextMenu.xaml
9 | ///
10 | public partial class ContextMenu : UserControl
11 | {
12 | public List Items = [];
13 | public ContextMenuItem? CurrentItemSelection = null;
14 |
15 | public ContextMenu()
16 | {
17 | InitializeComponent();
18 | DataContext = App.vimageConfig;
19 |
20 | if (App.vimageConfig == null)
21 | return;
22 | LoadItems(
23 | App.vimageConfig.ContextMenu,
24 | ContextMenuItems_General,
25 | ContextMenuItems_GeneralCanvas,
26 | ContextMenuItems_GeneralScroll
27 | );
28 | LoadItems(
29 | App.vimageConfig.ContextMenu_Animation,
30 | ContextMenuItems_Animation,
31 | ContextMenuItems_AnimationCanvas,
32 | ContextMenuItems_AnimationScroll
33 | );
34 | }
35 |
36 | public void Save()
37 | {
38 | App.vimageConfig.ContextMenu.Clear();
39 | App.vimageConfig.ContextMenu_Animation.Clear();
40 |
41 | SaveContextMenu(App.vimageConfig.ContextMenu, ContextMenuItems_General);
42 | SaveContextMenu(App.vimageConfig.ContextMenu_Animation, ContextMenuItems_Animation);
43 | }
44 |
45 | private static void SaveContextMenu(List