mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Modules - Added support for SVG icons in sidebar
Modules - Removed separate DisplayIconPath property Data model debugger - Generics now display their types nicely Data model debugger - Type keywords are used where applicable Data model debugger - Nullables display properly
This commit is contained in:
parent
7b7b75be78
commit
09cd0b4dae
@ -69,19 +69,16 @@ namespace Artemis.Core.Modules
|
||||
/// <summary>
|
||||
/// The modules display name that's shown in the menu
|
||||
/// </summary>
|
||||
public string DisplayName { get; protected set; }
|
||||
public string? DisplayName { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// The modules display icon that's shown in the menu see <see href="https://materialdesignicons.com" /> for available
|
||||
/// icons
|
||||
/// The modules display icon that's shown in the UI accepts:
|
||||
/// <para>
|
||||
/// Either set to the name of a Material Icon see (<see href="https://materialdesignicons.com" /> for available
|
||||
/// icons) or set to a path relative to the plugin folder pointing to a .svg file
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public string DisplayIcon { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A path to an image to use as the modules display icon that's shown in the menu.
|
||||
/// <para>If set, takes precedence over <see cref="DisplayIcon" /></para>
|
||||
/// </summary>
|
||||
public string DisplayIconPath { get; set; }
|
||||
public string? DisplayIcon { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether this module is activated. A module can only be active while its <see cref="ActivationRequirements" />
|
||||
@ -97,7 +94,8 @@ namespace Artemis.Core.Modules
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether this module should update while <see cref="IsActivatedOverride" /> is <see langword="true" />. When
|
||||
/// set to <see langword="false" /> <see cref="Update" /> and any timed updates will not get called during an activation override.
|
||||
/// set to <see langword="false" /> <see cref="Update" /> and any timed updates will not get called during an
|
||||
/// activation override.
|
||||
/// <para>Defaults to <see langword="false" /></para>
|
||||
/// </summary>
|
||||
public bool UpdateDuringActivationOverride { get; protected set; }
|
||||
@ -129,21 +127,21 @@ namespace Artemis.Core.Modules
|
||||
/// </summary>
|
||||
public int Priority { get; internal set; }
|
||||
|
||||
internal DataModel InternalDataModel { get; set; }
|
||||
|
||||
internal bool InternalExpandsMainDataModel { get; set; }
|
||||
internal ModuleSettingsEntity Entity { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A list of custom module tabs that show in the UI
|
||||
/// </summary>
|
||||
public IEnumerable<ModuleTab> ModuleTabs { get; protected set; }
|
||||
public IEnumerable<ModuleTab>? ModuleTabs { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether updating this module is currently allowed
|
||||
/// </summary>
|
||||
public bool IsUpdateAllowed => IsActivated && (UpdateDuringActivationOverride || !IsActivatedOverride);
|
||||
|
||||
internal DataModel? InternalDataModel { get; set; }
|
||||
|
||||
internal bool InternalExpandsMainDataModel { get; set; }
|
||||
internal ModuleSettingsEntity? Entity { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Called each frame when the module should update
|
||||
/// </summary>
|
||||
|
||||
@ -176,5 +176,10 @@ namespace Artemis.Core
|
||||
{
|
||||
return File.Exists(Path.Combine(Directory.FullName, "artemis.lock"));
|
||||
}
|
||||
|
||||
public string? ResolveRelativePath(string path)
|
||||
{
|
||||
return path == null ? null : Path.Combine(Directory.FullName, path);
|
||||
}
|
||||
}
|
||||
}
|
||||
29
src/Artemis.UI.Shared/Converters/TypeToStringConverter.cs
Normal file
29
src/Artemis.UI.Shared/Converters/TypeToStringConverter.cs
Normal file
@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
using Artemis.Core;
|
||||
|
||||
namespace Artemis.UI.Shared
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts <see cref="T:System.Type" /> into <see cref="T:System.String" />.
|
||||
/// </summary>
|
||||
public class TypeToStringConverter : IValueConverter
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
bool humanizeProvided = bool.TryParse(parameter?.ToString(), out bool humanize);
|
||||
if (value is Type type)
|
||||
return type.GetDisplayName(humanizeProvided && humanize);
|
||||
|
||||
return value?.ToString();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -12,6 +12,7 @@ namespace Artemis.UI.Shared
|
||||
private string _countDisplay;
|
||||
private IEnumerable _list;
|
||||
private int _listCount;
|
||||
private Type _displayValueType;
|
||||
|
||||
internal DataModelListViewModel(DataModel dataModel, DataModelVisualizationViewModel parent, DataModelPath dataModelPath) : base(dataModel, parent, dataModelPath)
|
||||
{
|
||||
@ -30,6 +31,12 @@ namespace Artemis.UI.Shared
|
||||
set => SetAndNotify(ref _listCount, value);
|
||||
}
|
||||
|
||||
public Type DisplayValueType
|
||||
{
|
||||
get => _displayValueType;
|
||||
set => SetAndNotify(ref _displayValueType, value);
|
||||
}
|
||||
|
||||
public string CountDisplay
|
||||
{
|
||||
get => _countDisplay;
|
||||
@ -68,6 +75,7 @@ namespace Artemis.UI.Shared
|
||||
return;
|
||||
|
||||
List = GetCurrentValue() as IEnumerable;
|
||||
DisplayValueType = List?.GetType();
|
||||
if (List == null)
|
||||
return;
|
||||
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using Artemis.Core;
|
||||
using System;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core.DataModelExpansions;
|
||||
using Artemis.UI.Shared.Services;
|
||||
|
||||
@ -6,12 +7,21 @@ namespace Artemis.UI.Shared
|
||||
{
|
||||
public class DataModelPropertiesViewModel : DataModelVisualizationViewModel
|
||||
{
|
||||
private Type _displayValueType;
|
||||
|
||||
internal DataModelPropertiesViewModel(DataModel dataModel, DataModelVisualizationViewModel parent, DataModelPath dataModelPath) : base(dataModel, parent, dataModelPath)
|
||||
{
|
||||
}
|
||||
|
||||
public Type DisplayValueType
|
||||
{
|
||||
get => _displayValueType;
|
||||
set => SetAndNotify(ref _displayValueType, value);
|
||||
}
|
||||
|
||||
public override void Update(IDataModelUIService dataModelUIService)
|
||||
{
|
||||
DisplayValueType = DataModelPath?.GetPropertyType();
|
||||
// Always populate properties
|
||||
PopulateProperties(dataModelUIService);
|
||||
|
||||
@ -28,15 +38,15 @@ namespace Artemis.UI.Shared
|
||||
return Parent.IsRootViewModel ? DataModel : base.GetCurrentValue();
|
||||
}
|
||||
|
||||
internal override int GetChildDepth()
|
||||
{
|
||||
return PropertyDescription != null && !PropertyDescription.ResetsDepth ? Depth + 1 : 1;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return DisplayPath ?? Path;
|
||||
}
|
||||
|
||||
internal override int GetChildDepth()
|
||||
{
|
||||
return PropertyDescription != null && !PropertyDescription.ResetsDepth ? Depth + 1 : 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -81,7 +81,9 @@ namespace Artemis.UI.Shared
|
||||
}
|
||||
}
|
||||
|
||||
public virtual string DisplayPath => string.Join(" › ", DataModelPath.Segments.Select(s => s.GetPropertyDescription()?.Name ?? s.Identifier));
|
||||
public virtual string DisplayPath => DataModelPath != null
|
||||
? string.Join(" › ", DataModelPath.Segments.Select(s => s.GetPropertyDescription()?.Name ?? s.Identifier))
|
||||
: null;
|
||||
|
||||
/// <summary>
|
||||
/// Updates the datamodel and if in an parent, any children
|
||||
@ -133,7 +135,7 @@ namespace Artemis.UI.Shared
|
||||
}
|
||||
|
||||
if (looseMatch)
|
||||
IsMatchingFilteredTypes = filteredTypes.Any(t => t.IsCastableFrom(type) ||
|
||||
IsMatchingFilteredTypes = filteredTypes.Any(t => t.IsCastableFrom(type) ||
|
||||
t == typeof(Enum) && type.IsEnum ||
|
||||
t == typeof(IEnumerable<>) && type.IsGenericEnumerable());
|
||||
else
|
||||
@ -267,7 +269,7 @@ namespace Artemis.UI.Shared
|
||||
// For other value types create a child view model
|
||||
if (propertyType.IsClass || propertyType.IsStruct())
|
||||
return new DataModelPropertiesViewModel(DataModel, this, dataModelPath) {Depth = depth};
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@ -5,6 +5,11 @@
|
||||
private bool _showNull;
|
||||
private bool _showToString;
|
||||
|
||||
public DefaultDataModelDisplayViewModel()
|
||||
{
|
||||
ShowNull = true;
|
||||
}
|
||||
|
||||
public bool ShowToString
|
||||
{
|
||||
get => _showToString;
|
||||
|
||||
46
src/Artemis.UI.Shared/Utilities/PluginUtilities.cs
Normal file
46
src/Artemis.UI.Shared/Utilities/PluginUtilities.cs
Normal file
@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using Artemis.Core;
|
||||
using Artemis.UI.Shared.Controls;
|
||||
using MaterialDesignThemes.Wpf;
|
||||
|
||||
namespace Artemis.UI.Shared
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides utilities for UI-related plugin tasks
|
||||
/// </summary>
|
||||
public static class PluginUtilities
|
||||
{
|
||||
/// <summary>
|
||||
/// Transforms the provided icon so that it is usable by the <see cref="ArtemisIcon" /> control
|
||||
/// </summary>
|
||||
/// <param name="pluginInfo">The info of the plugin the icon belongs to</param>
|
||||
/// <param name="icon">
|
||||
/// The icon, may be a string representation of a <see cref="PackIconKind" /> or a relative path
|
||||
/// pointing to a .svg file
|
||||
/// </param>
|
||||
/// <returns></returns>
|
||||
public static object GetPluginIcon(PluginInfo pluginInfo, string icon)
|
||||
{
|
||||
if (icon == null)
|
||||
return PackIconKind.QuestionMarkCircle;
|
||||
|
||||
// Icon is provided as a path
|
||||
if (icon.EndsWith(".svg"))
|
||||
{
|
||||
string iconPath = pluginInfo.ResolveRelativePath(icon);
|
||||
if (!File.Exists(iconPath))
|
||||
return PackIconKind.QuestionMarkCircle;
|
||||
return iconPath;
|
||||
}
|
||||
|
||||
// Icon is provided as string to avoid having to reference MaterialDesignThemes
|
||||
bool parsedIcon = Enum.TryParse(icon, true, out PackIconKind iconEnum);
|
||||
if (parsedIcon == false)
|
||||
iconEnum = PackIconKind.QuestionMarkCircle;
|
||||
return iconEnum;
|
||||
|
||||
return icon;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -24,9 +24,11 @@
|
||||
<ResourceDictionary Source="pack://application:,,,/MaterialDesignExtensions;component/Themes/MaterialDesignLightTheme.xaml" />
|
||||
|
||||
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Scrollbar.xaml" />
|
||||
|
||||
|
||||
<!-- Shared UI -->
|
||||
<ResourceDictionary Source="pack://application:,,,/Artemis.UI.Shared;component/Resources/ArtemisShared.xaml" />
|
||||
|
||||
<ResourceDictionary Source="ResourceDictionaries/SideNavigation.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
|
||||
<!-- Some general convertes etc. -->
|
||||
|
||||
49
src/Artemis.UI/ResourceDictionaries/SideNavigation.xaml
Normal file
49
src/Artemis.UI/ResourceDictionaries/SideNavigation.xaml
Normal file
@ -0,0 +1,49 @@
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:model="clr-namespace:MaterialDesignExtensions.Model;assembly=MaterialDesignExtensions"
|
||||
xmlns:shared="clr-namespace:Artemis.UI.Shared.Controls;assembly=Artemis.UI.Shared"
|
||||
xmlns:controls="clr-namespace:MaterialDesignExtensions.Controls;assembly=MaterialDesignExtensions">
|
||||
|
||||
<DataTemplate DataType="{x:Type model:FirstLevelNavigationItem}">
|
||||
<Grid Height="48">
|
||||
<Border Style="{StaticResource navigationItemBackgroundBorderStyle}" />
|
||||
<Border HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Padding="16,0,0,0">
|
||||
<Grid Height="24" VerticalAlignment="Center">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="24" />
|
||||
<ColumnDefinition Width="100*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<shared:ArtemisIcon Icon="{Binding Path=Icon}" Height="24" Width="24">
|
||||
<shared:ArtemisIcon.Style>
|
||||
<Style TargetType="{x:Type shared:ArtemisIcon}">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Path=IsSelected}" Value="False">
|
||||
<Setter Property="Foreground" Value="{Binding Path=IconForeground, RelativeSource={RelativeSource AncestorType={x:Type controls:SideNavigation}}}" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding Path=IsSelected}" Value="True">
|
||||
<Setter Property="Foreground" Value="{Binding Path=SelectionForeground, RelativeSource={RelativeSource AncestorType={x:Type controls:SideNavigation}}}" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</shared:ArtemisIcon.Style>
|
||||
</shared:ArtemisIcon>
|
||||
<TextBlock Grid.Column="1" FontSize="14" FontWeight="Bold" Text="{Binding Path=Label}" TextTrimming="CharacterEllipsis"
|
||||
Margin="32,0,0,0" HorizontalAlignment="Stretch" VerticalAlignment="Center">
|
||||
<TextBlock.Style>
|
||||
<Style TargetType="{x:Type TextBlock}">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Path=IsSelected}" Value="False">
|
||||
<Setter Property="Foreground" Value="{Binding Path=LabelForeground, RelativeSource={RelativeSource AncestorType={x:Type controls:SideNavigation}}}" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding Path=IsSelected}" Value="True">
|
||||
<Setter Property="Foreground" Value="{Binding Path=SelectionForeground, RelativeSource={RelativeSource AncestorType={x:Type controls:SideNavigation}}}" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</TextBlock.Style>
|
||||
</TextBlock>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ResourceDictionary>
|
||||
@ -10,6 +10,9 @@
|
||||
xmlns:dataModel="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800" d:DataContext="{d:DesignInstance local:DataModelDebugViewModel}">
|
||||
<UserControl.Resources>
|
||||
<dataModel:TypeToStringConverter x:Key="TypeToStringConverter"/>
|
||||
</UserControl.Resources>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
@ -60,7 +63,17 @@
|
||||
<Setter Property="IsExpanded" Value="{Binding IsVisualizationExpanded, Mode=TwoWay}" />
|
||||
</Style>
|
||||
<HierarchicalDataTemplate DataType="{x:Type dataModel:DataModelPropertiesViewModel}" ItemsSource="{Binding Children}">
|
||||
<TextBlock Text="{Binding PropertyDescription.Name}" ToolTip="{Binding PropertyDescription.Description}" />
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0" Margin="0 0 5 0" FontWeight="Bold">
|
||||
<Run>[</Run><Run Text="{Binding DisplayValueType, Converter={StaticResource TypeToStringConverter}, Mode=OneWay}" /><Run>]</Run>
|
||||
</TextBlock>
|
||||
<TextBlock Grid.Column="1" Text="{Binding PropertyDescription.Name}" ToolTip="{Binding PropertyDescription.Description}" />
|
||||
</Grid>
|
||||
|
||||
</HierarchicalDataTemplate>
|
||||
<HierarchicalDataTemplate DataType="{x:Type dataModel:DataModelListViewModel}" ItemsSource="{Binding ListChildren}">
|
||||
<Grid>
|
||||
@ -69,7 +82,9 @@
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0" Margin="0 0 5 0" FontWeight="Bold" Text="[List]"/>
|
||||
<TextBlock Grid.Column="0" Margin="0 0 5 0" FontWeight="Bold">
|
||||
<Run>[</Run><Run Text="{Binding DisplayValueType, Converter={StaticResource TypeToStringConverter}, Mode=OneWay}" /><Run>]</Run>
|
||||
</TextBlock>
|
||||
<TextBlock Grid.Column="1" Text="{Binding PropertyDescription.Name}" ToolTip="{Binding PropertyDescription.Description}" />
|
||||
<TextBlock Grid.Column="2"
|
||||
Text="{Binding CountDisplay, Mode=OneWay}"
|
||||
@ -87,7 +102,7 @@
|
||||
|
||||
<!-- Value description -->
|
||||
<TextBlock Grid.Column="0" Margin="0 0 5 0" FontWeight="Bold">
|
||||
<Run>[</Run><Run Text="{Binding DisplayValueType.Name, Mode=OneWay}" /><Run>]</Run>
|
||||
<Run>[</Run><Run Text="{Binding DisplayValueType, Converter={StaticResource TypeToStringConverter}, Mode=OneWay}" /><Run>]</Run>
|
||||
</TextBlock>
|
||||
<TextBlock Grid.Column="1" Text="{Binding PropertyDescription.Name}" ToolTip="{Binding PropertyDescription.Description}" />
|
||||
|
||||
@ -105,7 +120,7 @@
|
||||
|
||||
<!-- Value description -->
|
||||
<TextBlock Grid.Column="0" Margin="0 0 5 0" FontWeight="Bold">
|
||||
<Run>[</Run><Run Text="{Binding ListType.Name, Mode=OneWay}" /><Run>]</Run>
|
||||
<Run>[</Run><Run Text="{Binding ListType, Converter={StaticResource TypeToStringConverter}, Mode=OneWay}" /><Run>]</Run>
|
||||
</TextBlock>
|
||||
<TextBlock Grid.Column="1" ToolTip="{Binding PropertyDescription.Description}">
|
||||
<Run>List item [</Run><Run Text="{Binding Index, Mode=OneWay}" /><Run>]</Run>
|
||||
|
||||
@ -15,6 +15,7 @@ using Artemis.UI.Screens.News;
|
||||
using Artemis.UI.Screens.Settings;
|
||||
using Artemis.UI.Screens.SurfaceEditor;
|
||||
using Artemis.UI.Screens.Workshop;
|
||||
using Artemis.UI.Shared;
|
||||
using MaterialDesignExtensions.Controls;
|
||||
using MaterialDesignExtensions.Model;
|
||||
using MaterialDesignThemes.Wpf;
|
||||
@ -143,19 +144,11 @@ namespace Artemis.UI.Screens.Sidebar
|
||||
if (SidebarModules.Any(io => io.Value == module))
|
||||
return;
|
||||
|
||||
object icon;
|
||||
if (module.DisplayIconPath != null && File.Exists(Path.Combine(module.PluginInfo.Directory.FullName, module.DisplayIconPath)))
|
||||
icon = new BitmapImage(new Uri(Path.Combine(module.PluginInfo.Directory.FullName, module.DisplayIconPath)));
|
||||
else
|
||||
FirstLevelNavigationItem sidebarItem = new FirstLevelNavigationItem
|
||||
{
|
||||
// Icon is provided as string to avoid having to reference MaterialDesignThemes
|
||||
bool parsedIcon = Enum.TryParse<PackIconKind>(module.DisplayIcon, true, out PackIconKind iconEnum);
|
||||
if (parsedIcon == false)
|
||||
iconEnum = PackIconKind.QuestionMarkCircle;
|
||||
icon = iconEnum;
|
||||
}
|
||||
|
||||
FirstLevelNavigationItem sidebarItem = new FirstLevelNavigationItem {Icon = icon, Label = module.DisplayName};
|
||||
Icon = PluginUtilities.GetPluginIcon(module.PluginInfo, module.DisplayIcon),
|
||||
Label = module.DisplayName
|
||||
};
|
||||
SidebarItems.Add(sidebarItem);
|
||||
SidebarModules.Add(sidebarItem, module);
|
||||
}
|
||||
|
||||
@ -32,6 +32,11 @@
|
||||
<Private>false</Private>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Update="Images\bow.svg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="PostBuild" AfterTargets="PostBuildEvent" Condition="'$(BuildingInsideVisualStudio)' == 'true'">
|
||||
<Exec Command="echo Copying plugin to Artemis.UI output directory
XCOPY "$(TargetDir.TrimEnd('\'))" "$(SolutionDir)\Artemis.UI\$(OutDir)Plugins\$(ProjectName)" /s /q /i /y" />
|
||||
|
||||
@ -16,7 +16,7 @@ namespace Artemis.Plugins.Modules.General
|
||||
public override void EnablePlugin()
|
||||
{
|
||||
DisplayName = "General";
|
||||
DisplayIcon = "AllInclusive";
|
||||
DisplayIcon = "Images/bow.svg";
|
||||
ExpandsDataModel = true;
|
||||
|
||||
ModuleTabs = new List<ModuleTab> {new ModuleTab<GeneralViewModel>("General")};
|
||||
|
||||
44
src/Plugins/Artemis.Plugins.Modules.General/Images/bow.svg
Normal file
44
src/Plugins/Artemis.Plugins.Modules.General/Images/bow.svg
Normal file
@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||
width="242.000000pt" height="341.000000pt" viewBox="0 0 242.000000 341.000000"
|
||||
preserveAspectRatio="xMidYMid meet">
|
||||
<metadata>
|
||||
Created by potrace 1.15, written by Peter Selinger 2001-2017
|
||||
</metadata>
|
||||
<g transform="translate(0.000000,341.000000) scale(0.100000,-0.100000)"
|
||||
fill="#ffffff" stroke="none">
|
||||
<path d="M46 3388 l-48 -22 5 -47 c15 -121 99 -212 249 -268 l75 -28 1 36 c1
|
||||
20 4 71 8 114 3 46 2 77 -3 77 -16 0 -33 49 -33 94 0 40 -3 45 -31 55 -54 19
|
||||
-168 13 -223 -11z"/>
|
||||
<path d="M378 3281 c-24 -19 -25 -26 -31 -173 -3 -84 -24 -409 -47 -723 -22
|
||||
-313 -44 -628 -48 -700 -5 -71 -10 -111 -11 -88 l-1 42 -85 -37 c-46 -20 -85
|
||||
-42 -85 -47 0 -6 38 -19 85 -29 l85 -19 0 -43 c0 -57 14 -92 44 -105 l25 -12
|
||||
-40 -79 c-22 -44 -39 -81 -37 -83 5 -5 472 215 484 228 6 7 21 51 34 98 l22
|
||||
86 615 288 c337 158 615 286 617 284 2 -2 -9 -49 -25 -103 -16 -55 -27 -102
|
||||
-24 -104 7 -8 144 108 235 198 92 91 230 263 230 286 0 27 -334 14 -562 -22
|
||||
-60 -10 -108 -20 -108 -24 0 -4 45 -27 100 -52 l100 -45 -172 -81 c-684 -321
|
||||
-1017 -476 -1042 -485 -24 -8 -44 -5 -110 18 l-82 28 -98 -46 c-55 -26 -101
|
||||
-45 -103 -43 -5 5 87 1349 93 1355 2 2 4 -12 4 -31 0 -29 4 -37 23 -41 12 -4
|
||||
132 -18 267 -32 333 -35 482 -69 585 -133 62 -38 86 -63 111 -117 33 -69 31
|
||||
-135 -6 -247 l-30 -89 77 -110 c42 -61 80 -112 84 -115 4 -2 55 18 113 45
|
||||
l105 50 -49 73 -48 74 41 84 c41 81 42 86 42 184 0 96 -2 104 -34 163 -34 64
|
||||
-118 154 -184 199 -21 14 -81 46 -135 72 l-97 47 -325 6 c-179 4 -358 12 -397
|
||||
18 -40 7 -78 9 -84 6 -6 -4 -20 -21 -31 -39 -24 -37 -22 -30 16 57 l29 68 -28
|
||||
29 c-34 35 -71 39 -107 11z"/>
|
||||
<path d="M1730 2035 c-52 -25 -99 -46 -103 -48 -5 -1 8 -66 28 -144 l37 -141
|
||||
45 -12 c115 -28 217 -106 244 -186 47 -138 -16 -306 -236 -635 -74 -110 -147
|
||||
-221 -162 -246 -26 -45 -26 -46 -7 -60 34 -27 98 -53 129 -52 27 0 37 11 103
|
||||
112 40 62 105 151 145 198 39 48 110 131 155 185 100 119 116 148 149 273 32
|
||||
125 34 267 6 357 -47 145 -150 232 -314 266 -34 7 -63 17 -65 23 -2 5 -13 43
|
||||
-24 83 -12 39 -25 72 -28 72 -4 0 -50 -20 -102 -45z"/>
|
||||
<path d="M450 1273 l-35 -15 25 -17 c13 -9 123 -86 245 -172 121 -85 360 -254
|
||||
530 -374 171 -120 352 -251 403 -292 79 -62 98 -72 120 -67 61 15 79 42 64 99
|
||||
-8 27 -17 33 -113 65 -103 35 -109 39 -641 413 -296 207 -543 377 -550 376 -7
|
||||
0 -29 -8 -48 -16z"/>
|
||||
<path d="M1486 380 c-29 -90 -34 -190 -12 -253 17 -46 65 -117 85 -125 20 -8
|
||||
117 45 147 81 14 16 36 51 49 77 l24 48 -44 45 c-25 24 -45 53 -45 64 0 13
|
||||
-26 38 -77 75 -43 30 -83 58 -89 61 -7 4 -21 -22 -38 -73z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.6 KiB |
Loading…
x
Reference in New Issue
Block a user