1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-13 05:48:35 +00:00

Merge branch 'development'

This commit is contained in:
Robert 2022-09-30 20:47:29 +02:00
commit a21d26706d
43 changed files with 440 additions and 23399 deletions

35
.github/workflows/docfx.yml vendored Normal file
View File

@ -0,0 +1,35 @@
name: Master - DocFX
on:
workflow_dispatch:
push:
branches:
- master
jobs:
docfx:
name: Build DocFX Documentation
runs-on: windows-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup .NET
uses: actions/setup-dotnet@v2
with:
dotnet-version: '6.0.x'
- name: Setup DocFX
run: choco install docfx -y
- name: Build Core
run: dotnet build src/Artemis.Core/Artemis.Core.csproj
- name: Build UI.Shared
run: dotnet build src/Artemis.UI.Shared/Artemis.UI.Shared.csproj
- name: Build DocFX
run: docfx.exe docfx/docfx_project/docfx.json
- name: Upload to FTP
uses: SamKirkland/FTP-Deploy-Action@4.3.2
with:
server: artemis-rgb.com
username: ${{ secrets.FTP_USER }}
password: ${{ secrets.FTP_PASSWORD }}
local-dir: docfx/docfx_project/_site/
server-dir: /httpdocs/docs/

45
.github/workflows/nuget.yml vendored Normal file
View File

@ -0,0 +1,45 @@
name: Publish Nuget packages
on:
workflow_dispatch:
push:
branches:
- master
jobs:
version:
runs-on: ubuntu-latest
outputs:
version-suffix: ${{ steps.get-version.outputs.version-suffix }}
steps:
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Get Version String
id: get-version
shell: pwsh
run: |
$MidnightUtc = [DateTime]::UtcNow.Date
$BranchName = "${{ github.ref_name }}".replace('/','-').replace('.','-')
$NumberOfCommitsToday = (git log --after=$($MidnightUtc.ToString("o")) --oneline | Measure-Object -Line).Lines
$VersionSuffix = "$BranchName.$($MidnightUtc.ToString("yyyyMMdd")).$NumberOfCommitsToday"
Write-Output "::set-output name=version-suffix::$VersionSuffix"
nuget:
name: Publish Nuget Packages
needs: version
runs-on: ubuntu-latest
steps:
- name: Setup .NET
uses: actions/setup-dotnet@v2
with:
dotnet-version: '6.0.x'
- name: Checkout
uses: actions/checkout@v3
- name: Pack Artemis.Core
run: dotnet pack -c Release -p:VersionSuffix=${{ needs.version.outputs.version-suffix }} -p:BuildingNuget=True src/Artemis.Core/Artemis.Core.csproj
- name: Pack Artemis.UI.Shared
run: dotnet pack -c Release -p:VersionSuffix=${{ needs.version.outputs.version-suffix }} src/Artemis.UI.Shared/Artemis.UI.Shared.csproj
- name: Push Nugets
run: dotnet nuget push **/*.nupkg --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate

1
.gitignore vendored
View File

@ -198,3 +198,4 @@ src/Artemis\.Storage/Storage\.db
docfx/docfx_project/_site/
src/.idea/
packages.lock.json

View File

@ -8,35 +8,27 @@
<Copyright>Copyright © Robert Beekman - 2020</Copyright>
<OutputPath>bin\</OutputPath>
<Platforms>x64</Platforms>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<PlatformTarget>x64</PlatformTarget>
<DocumentationFile>bin\Artemis.Core.xml</DocumentationFile>
<NoWarn></NoWarn>
<WarningLevel>5</WarningLevel>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PackageId>ArtemisRGB.Core</PackageId>
<!-- API Version -->
<VersionPrefix>1.0.0.0</VersionPrefix>
</PropertyGroup>
<PropertyGroup>
<NrtRevisionFormat>1.0-{chash:6}</NrtRevisionFormat>
<NrtResolveSimpleAttributes>true</NrtResolveSimpleAttributes>
<NrtResolveInformationalAttribute>true</NrtResolveInformationalAttribute>
<NrtResolveCopyright>true</NrtResolveCopyright>
<NrtTagMatch>v[0-9]*</NrtTagMatch>
<NrtRemoveTagV>true</NrtRemoveTagV>
<NrtRequiredVcs>git</NrtRequiredVcs>
<NrtShowRevision>true</NrtShowRevision>
<Nullable>enable</Nullable>
<AnalysisLevel>latest</AnalysisLevel>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<DocumentationFile>bin\Artemis.Core.xml</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Artemis.Storage\Artemis.Storage.csproj">
<Private>false</Private>
</ProjectReference>
<ProjectReference Include="..\Artemis.Storage\Artemis.Storage.csproj"/>
<ProjectReference Condition="'$(BuildingNuget)' == 'True'" Update="..\Artemis.Storage\Artemis.Storage.csproj" PrivateAssets="All"/>
<!--
Include Artemis.Storage directly in the NuGet package instead of expecting it as an external dependency
https://github.com/NuGet/Home/issues/3891#issuecomment-309792369
https://github.com/NuGet/Home/pull/11708
-->
<_PackageFiles Include="$(OutputPath)\Artemis.Storage.dll">
<BuildAction>None</BuildAction>
<PackagePath>lib\$(TargetFramework)</PackagePath>
</_PackageFiles>
</ItemGroup>
<ItemGroup>
<PackageReference Include="EmbedIO" Version="3.4.3" />
<PackageReference Include="HidSharp" Version="2.1.0" />
@ -59,20 +51,10 @@
<PackageReference Include="System.IO.FileSystem.AccessControl" Version="5.0.0" />
<PackageReference Include="System.Numerics.Vectors" Version="4.5.0" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
<PackageReference Include="Unclassified.NetRevisionTask" Version="0.4.3">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<None Update="Resources\intro-profile.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<None Update="DefaultLayouts\**">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Resources/intro-profile.json" CopyToOutputDirectory="PreserveNewest" />
<None Include="DefaultLayouts/**" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
</Project>

View File

@ -93,6 +93,7 @@
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=stores_005Cregistrations/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=utilities/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=visualscripting/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=visualscripting_005Cextensions/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=visualscripting_005Cinterfaces/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=visualscripting_005Cnodes/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=visualscripting_005Cpins/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

View File

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
@ -61,7 +61,7 @@ public static class Constants
/// <summary>
/// The current API version for plugins
/// </summary>
public static readonly Version PluginApi = new(1, 0);
public static readonly Version PluginApi = CoreAssembly.GetName().Version!;
/// <summary>
/// The plugin info used by core components of Artemis

View File

@ -0,0 +1,26 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using System;
namespace Artemis.Core.JsonConverters
{
/// <summary>
/// Version converter that is forgiving of missing parts of the version string,
/// setting them to zero instead of -1.
/// </summary>
internal class ForgivingVersionConverter : VersionConverter
{
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
object obj = base.ReadJson(reader, objectType, existingValue, serializer);
if (obj is not Version v)
return obj;
int major = v.Major == -1 ? 0 : v.Major;
int minor = v.Minor == -1 ? 0 : v.Minor;
int build = v.Build == -1 ? 0 : v.Build;
int revision = v.Revision == -1 ? 0 : v.Revision;
return new Version(major, minor, build, revision);
}
}
}

View File

@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using Artemis.Core.JsonConverters;
using Newtonsoft.Json;
namespace Artemis.Core;
@ -158,6 +159,7 @@ public class PluginInfo : CorePropertyChanged, IPrerequisitesSubject
/// Gets the API version the plugin was built for
/// </summary>
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
[JsonConverter(typeof(ForgivingVersionConverter))]
public Version? Api
{
get => _api;

View File

@ -0,0 +1,88 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace Artemis.Core;
/// <summary>
/// Provides extension methods for nodes.
/// </summary>
public static class NodeExtension
{
#region Methods
/// <summary>
/// Estimates a height of a node in the editor.
/// </summary>
/// <param name="node">The node whose height to estimate.</param>
/// <returns>The estimated height in pixels.</returns>
public static double EstimateHeight(this INode node)
{
const double PIN_HEIGHT = 26;
const double TITLE_HEIGHT = 46;
int inputPinCount = node.Pins.Count(x => x.Direction == PinDirection.Input)
+ node.PinCollections.Where(x => x.Direction == PinDirection.Input).Sum(x => x.Count() + 1);
int outputPinCount = node.Pins.Count(x => x.Direction == PinDirection.Output)
+ node.PinCollections.Where(x => x.Direction == PinDirection.Output).Sum(x => x.Count() + 1);
return TITLE_HEIGHT + Math.Max(inputPinCount, outputPinCount) * PIN_HEIGHT;
}
/// <summary>
/// Estimates a width a node in the editor.
/// </summary>
/// <param name="node">The node whose width to estimate.</param>
/// <returns>The estimated width in pixels.</returns>
public static double EstimateWidth(this INode node)
{
// DarthAffe 13.09.2022: For now just assume they are all the same size
return 120;
}
/// <summary>
/// Determines whether the node is part of a loop when the provided pending connecting would be connected.
/// </summary>
/// <param name="node">The node to check</param>
/// <param name="pendingConnection">The node to which a connection is pending</param>
/// <returns><see langword="true" /> if there would be a loop; otherwise <see langword="false" />.</returns>
public static bool IsInLoop(this INode node, INode pendingConnection)
{
HashSet<INode> checkedNodes = new();
bool CheckNode(INode checkNode, INode? pending)
{
if (checkedNodes.Contains(checkNode)) return false;
checkedNodes.Add(checkNode);
List<INode> connectedNodes = checkNode.Pins
.Where(x => x.Direction == PinDirection.Input)
.SelectMany(x => x.ConnectedTo)
.Select(x => x.Node)
.Concat(checkNode.PinCollections
.Where(x => x.Direction == PinDirection.Input)
.SelectMany(x => x)
.SelectMany(x => x.ConnectedTo)
.Select(x => x.Node))
.Distinct()
.ToList();
if (pending != null)
connectedNodes.Add(pending);
foreach (INode connectedNode in connectedNodes)
{
if (connectedNode == node)
return true;
else if (CheckNode(connectedNode, null))
return true;
}
return false;
}
return CheckNode(node, pendingConnection);
}
#endregion
}

View File

@ -0,0 +1,97 @@
using System.Collections.Generic;
using System.Linq;
namespace Artemis.Core;
/// <summary>
/// Provides extension methods for node scripts.
/// </summary>
public static class NodeScriptExtension
{
#region Methods
/// <summary>
/// Organize a node script, attempting to lay out nodes in a logical manner.
/// </summary>
/// <param name="nodeScript">The node script to organize.</param>
public static void Organize(this NodeScript nodeScript)
{
const double SPACING_HORIZONTAL = 160;
const double SPACING_VERTICAL = 20;
Dictionary<INode, int> levels = nodeScript.Nodes.ToDictionary(node => node, _ => -1);
List<INode> currentLevelNodes = nodeScript.Nodes.Where(x => x.IsExitNode).ToList();
foreach (INode currentLevelNode in currentLevelNodes)
levels[currentLevelNode] = 0; // DarthAffe 13.09.2022: Init-exit nodes as zero
int currentLevel = 1;
while (currentLevelNodes.Count > 0 && currentLevel < 1000)
{
List<INode> nextLevelNodes = currentLevelNodes.SelectMany(node => node.Pins
.Where(x => x.Direction == PinDirection.Input)
.SelectMany(x => x.ConnectedTo)
.Select(x => x.Node)
.Concat(node.PinCollections
.Where(x => x.Direction == PinDirection.Input)
.SelectMany(x => x)
.SelectMany(x => x.ConnectedTo)
.Select(x => x.Node)))
.Distinct()
.ToList();
foreach (INode nextLevelNode in nextLevelNodes)
{
if (currentLevel > levels[nextLevelNode])
levels[nextLevelNode] = currentLevel;
}
currentLevelNodes = nextLevelNodes;
currentLevel++;
}
void LayoutLevel(IList<INode> nodes, double posX, double posY)
{
foreach (INode node in nodes)
{
node.X = posX;
node.Y = posY;
posY += SPACING_VERTICAL + node.EstimateHeight();
}
}
List<INode>? unusedNodes = null;
double unusedPosY = 0;
double level0Width = 0;
double positionX = 0;
foreach (IGrouping<int, INode> levelGroup in levels.GroupBy(x => x.Value, x => x.Key).OrderBy(x => x.Key))
{
List<INode> nodes = levelGroup.ToList();
double levelHeight = nodes.Sum(x => x.EstimateHeight()) + (nodes.Count - 1) * SPACING_VERTICAL;
double levelWidth = nodes.Max(x => x.EstimateWidth());
double positionY = -(levelHeight / 2.0);
if (levelGroup.Key == -1)
{
unusedNodes = nodes;
unusedPosY = positionY;
}
else
{
if (levelGroup.Key == 0)
level0Width = levelWidth;
LayoutLevel(nodes, positionX, positionY);
positionX -= SPACING_HORIZONTAL + levelWidth;
}
}
if (unusedNodes != null)
LayoutLevel(unusedNodes, level0Width + SPACING_HORIZONTAL / 2.0, unusedPosY);
}
#endregion
}

File diff suppressed because it is too large Load Diff

View File

@ -4,9 +4,6 @@
<PreserveCompilationContext>false</PreserveCompilationContext>
<Platforms>x64</Platforms>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<PlatformTarget>x64</PlatformTarget>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="LiteDB" Version="5.0.12" />

View File

@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Artemis.Storage.Entities.Profile;
using Artemis.Storage.Entities.Profile.Nodes;
@ -63,13 +64,13 @@ public class M0021GradientNodes : IStorageMigration
public void Apply(LiteRepository repository)
{
// Find all color gradient data bindings, there's no really good way to do this so infer it from the value
ILiteCollection<ProfileEntity> collection = repository.Database.GetCollection<ProfileEntity>();
foreach (ProfileEntity profileEntity in collection.FindAll())
List<ProfileEntity> profiles = repository.Query<ProfileEntity>().ToList();
foreach (ProfileEntity profileEntity in profiles)
{
foreach (LayerEntity layer in profileEntity.Layers)
MigrateDataBinding(layer.LayerBrush.PropertyGroup);
collection.Update(profileEntity);
repository.Update(profileEntity);
}
}

View File

@ -1,19 +0,0 @@
{
"version": 1,
"dependencies": {
"net6.0": {
"LiteDB": {
"type": "Direct",
"requested": "[5.0.12, )",
"resolved": "5.0.12",
"contentHash": "HaOjSIGS9BRm7dw42qcHd5NGYl5wdjsFB31pImt3QQNLKUNEmRAr7ADos5VsujwBc9c4otJgb+G6NA4MlzKyAw=="
},
"Serilog": {
"type": "Direct",
"requested": "[2.11.0, )",
"resolved": "2.11.0",
"contentHash": "ysv+hBzTul6Dp+Hvm10FlhJO3yMQcFKSAleus+LpiIzvNstpeV4Z7gGuIZ1OPNfIMulSHOjmLuGAEDKzpnV8ZQ=="
}
}
}
}

View File

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net6.0</TargetFramework>
@ -6,7 +6,8 @@
<PlatformTarget>x64</PlatformTarget>
<Platforms>x64</Platforms>
<OutputPath>bin</OutputPath>
<AssemblyTitle>Artemis 2</AssemblyTitle>
<AssemblyTitle>Artemis</AssemblyTitle>
<RuntimeIdentifier>linux-x64</RuntimeIdentifier>
<AppendTargetFrameworkToOutputPath>False</AppendTargetFrameworkToOutputPath>
</PropertyGroup>
<ItemGroup>

File diff suppressed because it is too large Load Diff

View File

@ -6,7 +6,7 @@
<PlatformTarget>x64</PlatformTarget>
<Platforms>x64</Platforms>
<OutputPath>bin</OutputPath>
<AssemblyTitle>Artemis 2</AssemblyTitle>
<AssemblyTitle>Artemis</AssemblyTitle>
<AppendTargetFrameworkToOutputPath>False</AppendTargetFrameworkToOutputPath>
</PropertyGroup>
<ItemGroup>

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +0,0 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=plugins/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=services_005Cwindowservice/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

View File

@ -1,564 +0,0 @@
<?xml version="1.0"?>
<doc>
<assembly>
<name>Artemis.UI.Shared</name>
</assembly>
<members>
<member name="F:Artemis.UI.Avalonia.Shared.Controls.ArtemisIcon.IconProperty">
<summary>
Gets or sets the currently displayed icon as either a
<see cref="T:Material.Icons.MaterialIconKind"/>
or an
<see cref="T:System.Uri"/>
pointing
to an SVG
</summary>
</member>
<member name="P:Artemis.UI.Avalonia.Shared.Controls.ArtemisIcon.Icon">
<summary>
Gets or sets the currently displayed icon as either a
<see cref="T:Material.Icons.MaterialIconKind"/>
or an
<see cref="T:System.Uri"/>
pointing
to an SVG
</summary>
</member>
<member name="T:Artemis.UI.Avalonia.Shared.Controls.DeviceVisualizer">
<summary>
Visualizes an
<see cref="T:Artemis.Core.ArtemisDevice"/>
with optional per-LED colors
</summary>
</member>
<member name="M:Artemis.UI.Avalonia.Shared.Controls.DeviceVisualizer.#ctor">
<inheritdoc/>
</member>
<member name="M:Artemis.UI.Avalonia.Shared.Controls.DeviceVisualizer.Render(Avalonia.Media.DrawingContext)">
<inheritdoc/>
</member>
<member name="E:Artemis.UI.Avalonia.Shared.Controls.DeviceVisualizer.LedClicked">
<summary>
Occurs when a LED of the device has been clicked
</summary>
</member>
<member name="M:Artemis.UI.Avalonia.Shared.Controls.DeviceVisualizer.OnLedClicked(Artemis.UI.Avalonia.Shared.Events.LedClickedEventArgs)">
<summary>
Invokes the
<see cref="E:Artemis.UI.Avalonia.Shared.Controls.DeviceVisualizer.LedClicked"/>
event
</summary>
<param name="e"></param>
</member>
<member name="F:Artemis.UI.Avalonia.Shared.Controls.DeviceVisualizer.DeviceProperty">
<summary>
Gets or sets the
<see cref="T:Artemis.Core.ArtemisDevice"/>
to display
</summary>
</member>
<member name="P:Artemis.UI.Avalonia.Shared.Controls.DeviceVisualizer.Device">
<summary>
Gets or sets the
<see cref="T:Artemis.Core.ArtemisDevice"/>
to display
</summary>
</member>
<member name="F:Artemis.UI.Avalonia.Shared.Controls.DeviceVisualizer.ShowColorsProperty">
<summary>
Gets or sets boolean indicating whether or not to show per-LED colors
</summary>
</member>
<member name="P:Artemis.UI.Avalonia.Shared.Controls.DeviceVisualizer.ShowColors">
<summary>
Gets or sets a boolean indicating whether or not to show per-LED colors
</summary>
</member>
<member name="F:Artemis.UI.Avalonia.Shared.Controls.DeviceVisualizer.HighlightedLedsProperty">
<summary>
Gets or sets a list of LEDs to highlight
</summary>
</member>
<member name="P:Artemis.UI.Avalonia.Shared.Controls.DeviceVisualizer.HighlightedLeds">
<summary>
Gets or sets a list of LEDs to highlight
</summary>
</member>
<member name="M:Artemis.UI.Avalonia.Shared.Controls.DeviceVisualizer.OnAttachedToLogicalTree(Avalonia.LogicalTree.LogicalTreeAttachmentEventArgs)">
<inheritdoc/>
</member>
<member name="M:Artemis.UI.Avalonia.Shared.Controls.DeviceVisualizer.OnDetachedFromLogicalTree(Avalonia.LogicalTree.LogicalTreeAttachmentEventArgs)">
<inheritdoc/>
</member>
<member name="M:Artemis.UI.Avalonia.Shared.Controls.DeviceVisualizer.MeasureOverride(Avalonia.Size)">
<inheritdoc/>
</member>
<member name="F:Artemis.UI.Avalonia.Shared.Controls.EnumComboBox.ValueProperty">
<summary>
Gets or sets the currently selected value
</summary>
</member>
<member name="P:Artemis.UI.Avalonia.Shared.Controls.EnumComboBox.Value">
<summary>
Gets or sets the currently selected value
</summary>
</member>
<member name="M:Artemis.UI.Avalonia.Shared.Controls.EnumComboBox.OnAttachedToLogicalTree(Avalonia.LogicalTree.LogicalTreeAttachmentEventArgs)">
<inheritdoc/>
</member>
<member name="M:Artemis.UI.Avalonia.Shared.Controls.EnumComboBox.OnDetachedFromLogicalTree(Avalonia.LogicalTree.LogicalTreeAttachmentEventArgs)">
<inheritdoc/>
</member>
<member name="F:Artemis.UI.Avalonia.Shared.Controls.ProfileConfigurationIcon.ConfigurationIconProperty">
<summary>
Gets or sets the
<see cref="T:Artemis.Core.ProfileConfigurationIcon"/>
to display
</summary>
</member>
<member name="P:Artemis.UI.Avalonia.Shared.Controls.ProfileConfigurationIcon.ConfigurationIcon">
<summary>
Gets or sets the
<see cref="T:Artemis.Core.ProfileConfigurationIcon"/>
to display
</summary>
</member>
<member name="T:Artemis.UI.Avalonia.Shared.Controls.SelectionRectangle">
<summary>
Visualizes an
<see cref="T:Artemis.Core.ArtemisDevice"/>
with optional per-LED colors
</summary>
</member>
<member name="F:Artemis.UI.Avalonia.Shared.Controls.SelectionRectangle.BackgroundProperty">
<summary>
Defines the
<see cref="P:Artemis.UI.Avalonia.Shared.Controls.SelectionRectangle.Background"/>
property.
</summary>
</member>
<member name="F:Artemis.UI.Avalonia.Shared.Controls.SelectionRectangle.BorderBrushProperty">
<summary>
Defines the
<see cref="P:Artemis.UI.Avalonia.Shared.Controls.SelectionRectangle.BorderBrush"/>
property.
</summary>
</member>
<member name="F:Artemis.UI.Avalonia.Shared.Controls.SelectionRectangle.BorderThicknessProperty">
<summary>
Defines the
<see cref="P:Artemis.UI.Avalonia.Shared.Controls.SelectionRectangle.BorderBrush"/>
property.
</summary>
</member>
<member name="F:Artemis.UI.Avalonia.Shared.Controls.SelectionRectangle.InputElementProperty">
<summary>
Defines the
<see cref="M:Artemis.UI.Avalonia.Shared.Controls.SelectionRectangle.get_InputElement"/>
property.
</summary>
</member>
<member name="M:Artemis.UI.Avalonia.Shared.Controls.SelectionRectangle.#ctor">
<inheritdoc/>
</member>
<member name="P:Artemis.UI.Avalonia.Shared.Controls.SelectionRectangle.Background">
<summary>
Gets or sets a brush used to paint the control's background.
</summary>
</member>
<member name="P:Artemis.UI.Avalonia.Shared.Controls.SelectionRectangle.BorderBrush">
<summary>
Gets or sets a brush used to paint the control's border
</summary>
</member>
<member name="P:Artemis.UI.Avalonia.Shared.Controls.SelectionRectangle.BorderThickness">
<summary>
Gets or sets the width of the control's border
</summary>
</member>
<member name="M:Artemis.UI.Avalonia.Shared.Controls.SelectionRectangle.OnAttachedToVisualTree(Avalonia.VisualTreeAttachmentEventArgs)">
<inheritdoc/>
</member>
<member name="M:Artemis.UI.Avalonia.Shared.Controls.SelectionRectangle.OnDetachedFromVisualTree(Avalonia.VisualTreeAttachmentEventArgs)">
<inheritdoc/>
</member>
<member name="T:Artemis.UI.Avalonia.Shared.Converters.ColorToSKColorConverter">
<summary>
Converts
<see cref="T:Avalonia.Media.Color"/>
into<see cref="T:SkiaSharp.SKColor"/>.
</summary>
</member>
<member name="M:Artemis.UI.Avalonia.Shared.Converters.ColorToSKColorConverter.Convert(System.Object,System.Type,System.Object,System.Globalization.CultureInfo)">
<inheritdoc/>
</member>
<member name="M:Artemis.UI.Avalonia.Shared.Converters.ColorToSKColorConverter.ConvertBack(System.Object,System.Type,System.Object,System.Globalization.CultureInfo)">
<inheritdoc/>
</member>
<member name="T:Artemis.UI.Avalonia.Shared.Converters.SKColorToColorConverter">
<summary>
Converts
<see cref="T:SkiaSharp.SKColor"/>
into<see cref="T:Avalonia.Media.Color"/>.
</summary>
</member>
<member name="M:Artemis.UI.Avalonia.Shared.Converters.SKColorToColorConverter.Convert(System.Object,System.Type,System.Object,System.Globalization.CultureInfo)">
<inheritdoc/>
</member>
<member name="M:Artemis.UI.Avalonia.Shared.Converters.SKColorToColorConverter.ConvertBack(System.Object,System.Type,System.Object,System.Globalization.CultureInfo)">
<inheritdoc/>
</member>
<member name="T:Artemis.UI.Avalonia.Shared.Events.DataModelInputDynamicEventArgs">
<summary>
Provides data about selection events raised by
<see cref="!:DataModelDynamicViewModel"/>
</summary>
</member>
<member name="P:Artemis.UI.Avalonia.Shared.Events.DataModelInputDynamicEventArgs.DataModelPath">
<summary>
Gets the data model path that was selected
</summary>
</member>
<member name="T:Artemis.UI.Avalonia.Shared.Events.DataModelInputStaticEventArgs">
<summary>
Provides data about submit events raised by
<see cref="!:DataModelStaticViewModel"/>
</summary>
</member>
<member name="P:Artemis.UI.Avalonia.Shared.Events.DataModelInputStaticEventArgs.Value">
<summary>
The value that was submitted
</summary>
</member>
<member name="T:Artemis.UI.Avalonia.Shared.Events.LedClickedEventArgs">
<summary>
Provides data on LED click events raised by the device visualizer
</summary>
</member>
<member name="P:Artemis.UI.Avalonia.Shared.Events.LedClickedEventArgs.Device">
<summary>
The device that was clicked
</summary>
</member>
<member name="P:Artemis.UI.Avalonia.Shared.Events.LedClickedEventArgs.Led">
<summary>
The LED that was clicked
</summary>
</member>
<member name="T:Artemis.UI.Avalonia.Shared.Events.ProfileConfigurationEventArgs">
<summary>
Provides data on profile related events raised by the profile editor
</summary>
</member>
<member name="P:Artemis.UI.Avalonia.Shared.Events.ProfileConfigurationEventArgs.ProfileConfiguration">
<summary>
Gets the profile the event was raised for
</summary>
</member>
<member name="P:Artemis.UI.Avalonia.Shared.Events.ProfileConfigurationEventArgs.PreviousProfileConfiguration">
<summary>
If applicable, the previous active profile before the event was raised
</summary>
</member>
<member name="T:Artemis.UI.Avalonia.Shared.Events.RenderProfileElementEventArgs">
<summary>
Provides data on profile element related events raised by the profile editor
</summary>
</member>
<member name="P:Artemis.UI.Avalonia.Shared.Events.RenderProfileElementEventArgs.RenderProfileElement">
<summary>
Gets the profile element the event was raised for
</summary>
</member>
<member name="P:Artemis.UI.Avalonia.Shared.Events.RenderProfileElementEventArgs.PreviousRenderProfileElement">
<summary>
If applicable, the previous active profile element before the event was raised
</summary>
</member>
<member name="T:Artemis.UI.Avalonia.Shared.Exceptions.ArtemisSharedUIException">
<summary>
Represents errors that occur within the Artemis Shared UI library
</summary>
</member>
<member name="T:Artemis.UI.Avalonia.Shared.Ninject.SharedUIModule">
<summary>
The main
<see cref="T:Ninject.Modules.NinjectModule"/>
of the Artemis Shared UI toolkit that binds all services
</summary>
</member>
<member name="M:Artemis.UI.Avalonia.Shared.Ninject.SharedUIModule.Load">
<inheritdoc/>
</member>
<member name="T:Artemis.UI.Avalonia.Shared.PluginConfigurationDialog`1">
<inheritdoc/>
</member>
<member name="P:Artemis.UI.Avalonia.Shared.PluginConfigurationDialog`1.Type">
<inheritdoc/>
</member>
<member name="T:Artemis.UI.Avalonia.Shared.PluginConfigurationDialog">
<summary>
Describes a configuration dialog for a specific plugin
</summary>
</member>
<member name="P:Artemis.UI.Avalonia.Shared.PluginConfigurationDialog.Type">
<inheritdoc/>
</member>
<member name="T:Artemis.UI.Avalonia.Shared.PluginConfigurationViewModel">
<summary>
Represents a view model for a plugin configuration window
</summary>
</member>
<member name="M:Artemis.UI.Avalonia.Shared.PluginConfigurationViewModel.#ctor(Artemis.Core.Plugin)">
<summary>
Creates a new instance of the
<see cref="T:Artemis.UI.Avalonia.Shared.PluginConfigurationViewModel"/>
class
</summary>
<param name="plugin"></param>
</member>
<member name="P:Artemis.UI.Avalonia.Shared.PluginConfigurationViewModel.Plugin">
<summary>
Gets the plugin this configuration view model is associated with
</summary>
</member>
<member name="M:Artemis.UI.Avalonia.Shared.PluginConfigurationViewModel.Close">
<summary>
Closes the window hosting the view model
</summary>
</member>
<member name="E:Artemis.UI.Avalonia.Shared.PluginConfigurationViewModel.CloseRequested">
<summary>
Occurs when the the window hosting the view model should close
</summary>
</member>
<member name="T:Artemis.UI.Avalonia.Shared.Services.Builders.FileDialogFilterBuilder">
<summary>
Represents a builder that can create a<see cref="T:Avalonia.Controls.FileDialogFilter"/>.
</summary>
</member>
<member name="M:Artemis.UI.Avalonia.Shared.Services.Builders.FileDialogFilterBuilder.WithName(System.String)">
<summary>
Sets the name of the filter
</summary>
</member>
<member name="M:Artemis.UI.Avalonia.Shared.Services.Builders.FileDialogFilterBuilder.WithExtension(System.String)">
<summary>
Adds the provided extension to the filter
</summary>
</member>
<member name="M:Artemis.UI.Avalonia.Shared.Services.Builders.NotificationBuilder.HavingButton(System.Action{Artemis.UI.Avalonia.Shared.Services.Builders.NotificationButtonBuilder})">
<summary>
Add a filter to the dialog
</summary>
</member>
<member name="T:Artemis.UI.Avalonia.Shared.Services.Builders.OpenFileDialogBuilder">
<summary>
Represents a builder that can create a<see cref="T:Avalonia.Controls.OpenFileDialog"/>.
</summary>
</member>
<member name="M:Artemis.UI.Avalonia.Shared.Services.Builders.OpenFileDialogBuilder.WithAllowMultiple">
<summary>
Indicate that the user can select multiple files.
</summary>
</member>
<member name="M:Artemis.UI.Avalonia.Shared.Services.Builders.OpenFileDialogBuilder.WithTitle(System.String)">
<summary>
Set the title of the dialog
</summary>
</member>
<member name="M:Artemis.UI.Avalonia.Shared.Services.Builders.OpenFileDialogBuilder.WithDirectory(System.String)">
<summary>
Set the initial directory of the dialog
</summary>
</member>
<member name="M:Artemis.UI.Avalonia.Shared.Services.Builders.OpenFileDialogBuilder.WithInitialFileName(System.String)">
<summary>
Set the initial file name of the dialog
</summary>
</member>
<member name="M:Artemis.UI.Avalonia.Shared.Services.Builders.OpenFileDialogBuilder.HavingFilter(System.Action{Artemis.UI.Avalonia.Shared.Services.Builders.FileDialogFilterBuilder})">
<summary>
Add a filter to the dialog
</summary>
</member>
<member name="M:Artemis.UI.Avalonia.Shared.Services.Builders.OpenFileDialogBuilder.ShowAsync">
<summary>
Shows the file dialog
</summary>
<returns>
A task that on completion returns an array containing the full path to the selected
files, or null if the dialog was canceled.
</returns>
</member>
<member name="T:Artemis.UI.Avalonia.Shared.Services.Builders.SaveFileDialogBuilder">
<summary>
Represents a builder that can create a<see cref="T:Avalonia.Controls.SaveFileDialog"/>.
</summary>
</member>
<member name="M:Artemis.UI.Avalonia.Shared.Services.Builders.SaveFileDialogBuilder.WithTitle(System.String)">
<summary>
Set the title of the dialog
</summary>
</member>
<member name="M:Artemis.UI.Avalonia.Shared.Services.Builders.SaveFileDialogBuilder.WithDirectory(System.String)">
<summary>
Set the initial directory of the dialog
</summary>
</member>
<member name="M:Artemis.UI.Avalonia.Shared.Services.Builders.SaveFileDialogBuilder.WithInitialFileName(System.String)">
<summary>
Set the initial file name of the dialog
</summary>
</member>
<member name="M:Artemis.UI.Avalonia.Shared.Services.Builders.SaveFileDialogBuilder.WithDefaultExtension(System.String)">
<summary>
Set the default extension of the dialog
</summary>
</member>
<member name="M:Artemis.UI.Avalonia.Shared.Services.Builders.SaveFileDialogBuilder.HavingFilter(System.Action{Artemis.UI.Avalonia.Shared.Services.Builders.FileDialogFilterBuilder})">
<summary>
Add a filter to the dialog
</summary>
</member>
<member name="M:Artemis.UI.Avalonia.Shared.Services.Builders.SaveFileDialogBuilder.ShowAsync">
<summary>
Shows the save file dialog.
</summary>
<returns>
A task that on completion contains the full path of the save location, or null if the
dialog was canceled.
</returns>
</member>
<member name="T:Artemis.UI.Avalonia.Shared.Services.Interfaces.IArtemisSharedUIService">
<summary>
Represents a service provided by the Artemis Shared UI library
</summary>
</member>
<member name="M:Artemis.UI.Avalonia.Shared.Services.Interfaces.IWindowService.ShowWindow``1(System.ValueTuple{System.String,System.Object}[])">
<summary>
Creates a view model instance of type
<typeparamref name="TViewModel"/>
and shows its corresponding View as a window
</summary>
<typeparam name="TViewModel">The type of view model to create</typeparam>
<returns>The created view model</returns>
</member>
<member name="M:Artemis.UI.Avalonia.Shared.Services.Interfaces.IWindowService.ShowWindow(System.Object)">
<summary>
Given a ViewModel, show its corresponding View as a window
</summary>
<param name="viewModel">ViewModel to show the View for</param>
</member>
<member name="M:Artemis.UI.Avalonia.Shared.Services.Interfaces.IWindowService.ShowExceptionDialog(System.String,System.Exception)">
<summary>
Shows a dialog displaying the given exception
</summary>
<param name="title">The title of the dialog</param>
<param name="exception">The exception to display</param>
</member>
<member name="M:Artemis.UI.Avalonia.Shared.Services.Interfaces.IWindowService.ShowDialogAsync``1(Artemis.UI.Avalonia.Shared.DialogViewModelBase{``0})">
<summary>
Given an existing ViewModel, show its corresponding View as a Dialog
</summary>
<typeparam name="TResult">The return type</typeparam>
<param name="viewModel">ViewModel to show the View for</param>
<returns>A task containing the return value of type
<typeparamref name="TResult"/>
</returns>
</member>
<member name="M:Artemis.UI.Avalonia.Shared.Services.Interfaces.IWindowService.ShowDialogAsync``2(System.ValueTuple{System.String,System.Object}[])">
<summary>
Creates a view model instance of type
<typeparamref name="TViewModel"/>
and shows its corresponding View as a Dialog
</summary>
<typeparam name="TViewModel">The view model type</typeparam>
<typeparam name="TResult">The return type</typeparam>
<returns>A task containing the return value of type
<typeparamref name="TResult"/>
</returns>
</member>
<member name="M:Artemis.UI.Avalonia.Shared.Services.Interfaces.IWindowService.ShowConfirmContentDialog(System.String,System.String,System.String,System.String)">
<summary>
Shows a content dialog asking the user to confirm an action
</summary>
<param name="title">The title of the dialog</param>
<param name="message">The message of the dialog</param>
<param name="confirm">The text of the confirm button</param>
<param name="cancel">The text of the cancel button, if
<see langword="null"/>
the cancel button will not be shown
</param>
<returns>A task containing the result of the dialog,
<see langword="true"/>
if confirmed; otherwise
<see langword="false"/>
</returns>
</member>
<member name="M:Artemis.UI.Avalonia.Shared.Services.Interfaces.IWindowService.CreateOpenFileDialog">
<summary>
Creates an open file dialog, use the fluent API to configure it
</summary>
<returns>The builder that can be used to configure the dialog</returns>
</member>
<member name="M:Artemis.UI.Avalonia.Shared.Services.Interfaces.IWindowService.CreateSaveFileDialog">
<summary>
Creates a save file dialog, use the fluent API to configure it
</summary>
<returns>The builder that can be used to configure the dialog</returns>
</member>
<member name="T:Artemis.UI.Avalonia.Shared.ViewModelBase">
<summary>
Represents the base class for Artemis view models
</summary>
</member>
<member name="P:Artemis.UI.Avalonia.Shared.ViewModelBase.DisplayName">
<summary>
Gets or sets the display name of the view model
</summary>
</member>
<member name="T:Artemis.UI.Avalonia.Shared.ActivatableViewModelBase">
<summary>
Represents the base class for Artemis view models that are interested in the activated event
</summary>
</member>
<member name="M:Artemis.UI.Avalonia.Shared.ActivatableViewModelBase.#ctor">
<inheritdoc/>
</member>
<member name="M:Artemis.UI.Avalonia.Shared.ActivatableViewModelBase.Dispose(System.Boolean)">
<summary>
Releases the unmanaged resources used by the object and optionally releases the managed resources.
</summary>
<param name="disposing">
<see langword="true"/>
to release both managed and unmanaged resources;
<see langword="false"/>
to release only unmanaged resources.
</param>
</member>
<member name="P:Artemis.UI.Avalonia.Shared.ActivatableViewModelBase.Activator">
<inheritdoc/>
</member>
<member name="M:Artemis.UI.Avalonia.Shared.ActivatableViewModelBase.Dispose">
<inheritdoc/>
</member>
<member name="T:Artemis.UI.Avalonia.Shared.DialogViewModelBase`1">
<summary>
Represents the base class for Artemis view models used to drive dialogs
</summary>
</member>
<member name="M:Artemis.UI.Avalonia.Shared.DialogViewModelBase`1.Close(`0)">
<summary>
Closes the dialog with the given
<paramref name="result"/>
</summary>
<param name="result">The result of the dialog</param>
</member>
<member name="M:Artemis.UI.Avalonia.Shared.DialogViewModelBase`1.Cancel">
<summary>
Closes the dialog without a result
</summary>
</member>
</members>
</doc>

View File

@ -1,19 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Library</OutputType>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<ApplicationIcon />
<StartupObject />
<OutputPath>bin\</OutputPath>
<PlatformTarget>x64</PlatformTarget>
<Platforms>x64</Platforms>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PackageId>ArtemisRGB.UI.Shared</PackageId>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<DocumentationFile>bin\Artemis.UI.Avalonia.Shared.xml</DocumentationFile>
</PropertyGroup>
<ItemGroup>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Avalonia" Version="0.10.18" />
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
@ -31,12 +26,4 @@
<ItemGroup>
<ProjectReference Include="..\Artemis.Core\Artemis.Core.csproj" />
</ItemGroup>
<ItemGroup>
<Compile Update="Controls\HotkeyBox.axaml.cs">
<DependentUpon>HotkeyBox.axaml</DependentUpon>
</Compile>
<Compile Update="Services\Window\ExceptionDialogView.axaml.cs">
<DependentUpon>%(Filename)</DependentUpon>
</Compile>
</ItemGroup>
</Project>

View File

@ -0,0 +1,43 @@
using System.Collections.Generic;
using System.Linq;
using Artemis.Core;
namespace Artemis.UI.Shared.Services.NodeEditor.Commands;
/// <summary>
/// Represents a node editor command that can be used to organize a script
/// </summary>
public class OrganizeScript : INodeEditorCommand
{
private readonly NodeScript _script;
private readonly List<(INode node, double x, double y)> _originalPositions;
/// <summary>
/// Creates a new instance of the <see cref="OrganizeScript"/> class.
/// </summary>
/// <param name="script">The script to organize.</param>
public OrganizeScript(NodeScript script)
{
_script = script;
_originalPositions = script.Nodes.Select(n => (n, n.X, n.Y)).ToList();
}
/// <inheritdoc />
public string DisplayName => "Organize script";
/// <inheritdoc />
public void Execute()
{
_script.Organize();
}
/// <inheritdoc />
public void Undo()
{
foreach ((INode? node, double x, double y) in _originalPositions)
{
node.X = x;
node.Y = y;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -3,11 +3,10 @@
<OutputType>WinExe</OutputType>
<TargetFramework>net6.0-windows10.0.17763.0</TargetFramework>
<Nullable>enable</Nullable>
<PlatformTarget>x64</PlatformTarget>
<Platforms>x64</Platforms>
<OutputPath>bin</OutputPath>
<AppendTargetFrameworkToOutputPath>False</AppendTargetFrameworkToOutputPath>
<AssemblyTitle>Artemis 2</AssemblyTitle>
<AssemblyTitle>Artemis</AssemblyTitle>
<ApplicationIcon>..\Artemis.UI\Assets\Images\Logo\application.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
@ -27,7 +26,7 @@
<None Remove="Assets\Cursors\aero_rotate_tl.cur" />
<None Remove="Assets\Cursors\aero_rotate_tr.cur" />
<None Include="..\Artemis.UI\Assets\Images\Logo\application.ico">
<Link>application.ico</Link>
<Link>application.ico</Link>
</None>
</ItemGroup>
<ItemGroup>
@ -39,6 +38,7 @@
<PackageReference Include="Avalonia.Win32" Version="0.10.18" />
<PackageReference Include="Microsoft.Toolkit.Uwp.Notifications" Version="7.1.2" />
<PackageReference Include="Microsoft.Win32" Version="2.0.1" />
<PackageReference Include="Microsoft.Windows.Compatibility" Version="6.0.0" />
<PackageReference Include="RawInput.Sharp" Version="0.0.4" />
<PackageReference Include="ReactiveUI" Version="17.1.50" />
<PackageReference Include="SkiaSharp.Vulkan.SharpVk" Version="2.88.1-preview.108" />

File diff suppressed because it is too large Load Diff

View File

@ -1,2 +0,0 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=events/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

View File

@ -3,18 +3,16 @@
<OutputType>Library</OutputType>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<OutputPath>bin\</OutputPath>
<PlatformTarget>x64</PlatformTarget>
<OutputPath>bin/</OutputPath>
<Platforms>x64</Platforms>
</PropertyGroup>
<ItemGroup>
<AvaloniaResource Include="Assets\**" />
</ItemGroup>
<ItemGroup>
<None Remove="Artemis.UI.Avalonia.csproj.DotSettings" />
<None Remove="Artemis.UI.csproj.DotSettings" />
<None Remove="Assets\Images\Logo\application.ico" />
<ProjectReference Include="..\Artemis.Core\Artemis.Core.csproj" />
<ProjectReference Include="..\Artemis.UI.Shared\Artemis.UI.Shared.csproj" />
<ProjectReference Include="..\Artemis.VisualScripting\Artemis.VisualScripting.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Avalonia" Version="0.10.18" />
<PackageReference Include="Avalonia.Controls.PanAndZoom" Version="10.14.0" />
@ -36,56 +34,8 @@
<PackageReference Include="SkiaSharp" Version="2.88.1-preview.108" />
<PackageReference Include="Splat.Ninject" Version="14.4.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Artemis.Core\Artemis.Core.csproj" />
<ProjectReference Include="..\Artemis.UI.Shared\Artemis.UI.Shared.csproj" />
<ProjectReference Include="..\Artemis.VisualScripting\Artemis.VisualScripting.csproj" />
</ItemGroup>
<ItemGroup>
<Content Include="Assets\Images\Logo\bow-white.ico" />
<Content Include="Assets\Images\Logo\bow.ico" />
</ItemGroup>
<ItemGroup>
<Resource Include="Assets\Images\Logo\bow-black.ico" />
<Resource Include="Assets\Images\Logo\bow-white.ico" />
</ItemGroup>
<ItemGroup>
<Compile Update="DefaultTypes\PropertyInput\StringPropertyInputView.axaml.cs">
<DependentUpon>StringPropertyInputView.xaml</DependentUpon>
</Compile>
<Compile Update="Screens\ProfileEditor\Panels\Properties\PropertiesView.axaml.cs">
<DependentUpon>PropertiesView.axaml</DependentUpon>
</Compile>
<Compile Update="Screens\ProfileEditor\Panels\VisualEditor\Visualizers\LayerShapeVisualizerView.axaml.cs">
<DependentUpon>LayerShapeVisualizerView.axaml</DependentUpon>
</Compile>
<Compile Update="Screens\VisualScripting\DragCableView.axaml.cs">
<DependentUpon>DragCableView.axaml</DependentUpon>
</Compile>
<Compile Update="Screens\VisualScripting\NodeScriptWindowView.axaml.cs">
<DependentUpon>NodeScriptWindowView.axaml</DependentUpon>
</Compile>
<Compile Update="Screens\ProfileEditor\Panels\Properties\Tree\ContentDialogs\LayerEffectRenameView.axaml.cs">
<DependentUpon>LayerEffectRenameView.axaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Update="Screens\ProfileEditor\Panels\Properties\Tree\ContentDialogs\SidebarCategoryEditView.axaml.cs">
<DependentUpon>SidebarCategoryEditView.axaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Update="Screens\Scripting\Dialogs\ScriptConfigurationEditView.axaml.cs">
<DependentUpon>ScriptConfigurationEditView.axaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
</ItemGroup>
<ItemGroup>
<AvaloniaXaml Update="DefaultTypes\PropertyInput\StringPropertyInputView.axaml">
<Generator>MSBuild:Compile</Generator>
</AvaloniaXaml>
</ItemGroup>
<ItemGroup>
<Reference Include="SkiaSharp">
<HintPath>..\..\..\..\Users\Robert\.nuget\packages\skiasharp\2.88.1-preview.1\lib\netstandard2.0\SkiaSharp.dll</HintPath>
</Reference>
<AvaloniaResource Include="Assets\**" />
</ItemGroup>
</Project>

View File

@ -216,7 +216,7 @@
</Button>
</Grid>
<Panel Grid.Row="1">
<Panel Grid.Row="1" IsVisible="{CompiledBinding !IsCollapsed}">
<ListBox Name="SidebarListBox"
Classes="sidebar-listbox"
Items="{CompiledBinding ProfileConfigurations}"

View File

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Reactive;
using System.Reactive.Linq;
@ -197,8 +198,14 @@ public class NodeScriptViewModel : ActivatableViewModelBase
DragViewModel = new DragCableViewModel(sourcePinViewModel);
DragViewModel.DragPoint = position;
if (targetPinVmModel == null)
return true;
if (!targetPinVmModel.IsCompatibleWith(sourcePinViewModel))
return false;
return targetPinVmModel == null || targetPinVmModel.IsCompatibleWith(sourcePinViewModel);
return sourcePinViewModel.Pin.Direction == PinDirection.Output
? !targetPinVmModel.Pin.Node.IsInLoop(sourcePinViewModel.Pin.Node)
: !sourcePinViewModel.Pin.Node.IsInLoop(targetPinVmModel.Pin.Node);
}
public void FinishPinDrag(PinViewModel sourcePinViewModel, PinViewModel? targetPinVmModel, Point position)
@ -211,7 +218,10 @@ public class NodeScriptViewModel : ActivatableViewModelBase
// If dropped on top of a compatible pin, connect to it
if (targetPinVmModel != null && targetPinVmModel.IsCompatibleWith(sourcePinViewModel))
{
_nodeEditorService.ExecuteCommand(NodeScript, new ConnectPins(sourcePinViewModel.Pin, targetPinVmModel.Pin));
if (sourcePinViewModel.Pin.Direction == PinDirection.Output && !targetPinVmModel.Pin.Node.IsInLoop(sourcePinViewModel.Pin.Node))
_nodeEditorService.ExecuteCommand(NodeScript, new ConnectPins(sourcePinViewModel.Pin, targetPinVmModel.Pin));
else if (sourcePinViewModel.Pin.Direction == PinDirection.Input && !sourcePinViewModel.Pin.Node.IsInLoop(targetPinVmModel.Pin.Node))
_nodeEditorService.ExecuteCommand(NodeScript, new ConnectPins(sourcePinViewModel.Pin, targetPinVmModel.Pin));
}
// If not dropped on a pin allow the user to create a new node
else if (targetPinVmModel == null)

View File

@ -16,6 +16,7 @@
<Window.KeyBindings>
<KeyBinding Command="{CompiledBinding History.Undo}" Gesture="Ctrl+Z" />
<KeyBinding Command="{CompiledBinding History.Redo}" Gesture="Ctrl+Y" />
<KeyBinding Command="{CompiledBinding AutoArrange}" Gesture="Ctrl+F" />
</Window.KeyBindings>
<Grid Margin="15" ColumnDefinitions="*,*" RowDefinitions="Auto,Auto,*">
<Menu Grid.Row="0" Grid.ColumnSpan="2" VerticalAlignment="Top" Margin="-10 -10 -10 0">
@ -43,6 +44,11 @@
</DataTemplate>
</MenuItem.DataTemplates>
</MenuItem>
<MenuItem Header="Auto-arrange" Command="{CompiledBinding AutoArrange}" InputGesture="Ctrl+F">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="Sort" />
</MenuItem.Icon>
</MenuItem>
<Separator />
<MenuItem Header="Export Script" Command="{CompiledBinding Export}">
<MenuItem.Icon>

View File

@ -26,6 +26,7 @@ public class NodeScriptWindowViewModel : NodeScriptWindowViewModelBase
private readonly IProfileService _profileService;
private readonly ISettingsService _settingsService;
private readonly IWindowService _windowService;
private bool _pauseUpdate;
public NodeScriptWindowViewModel(NodeScript nodeScript,
INodeService nodeService,
@ -56,6 +57,7 @@ public class NodeScriptWindowViewModel : NodeScriptWindowViewModelBase
Categories = categories;
CreateNode = ReactiveCommand.Create<NodeData>(ExecuteCreateNode);
AutoArrange = ReactiveCommand.CreateFromTask(ExecuteAutoArrange);
Export = ReactiveCommand.CreateFromTask(ExecuteExport);
Import = ReactiveCommand.CreateFromTask(ExecuteImport);
@ -83,6 +85,7 @@ public class NodeScriptWindowViewModel : NodeScriptWindowViewModelBase
public ReactiveCommand<string, Unit> OpenUri { get; set; }
public ReadOnlyObservableCollection<IGrouping<NodeData, string>> Categories { get; }
public ReactiveCommand<NodeData, Unit> CreateNode { get; }
public ReactiveCommand<Unit, Unit> AutoArrange { get; }
public ReactiveCommand<Unit, Unit> Export { get; }
public ReactiveCommand<Unit, Unit> Import { get; }
@ -108,6 +111,27 @@ public class NodeScriptWindowViewModel : NodeScriptWindowViewModelBase
_nodeEditorService.ExecuteCommand(NodeScript, new AddNode(NodeScript, node));
}
private async Task ExecuteAutoArrange()
{
try
{
if (!NodeScript.ExitNodeConnected)
{
await _windowService.ShowConfirmContentDialog("Cannot auto-arrange", "The exit node must be connected in order to perform auto-arrange.", "Close", null);
return;
}
_pauseUpdate = true;
_nodeEditorService.ExecuteCommand(NodeScript, new OrganizeScript(NodeScript));
await Task.Delay(200);
NodeScriptViewModel.RequestAutoFit();
}
finally
{
_pauseUpdate = false;
}
}
private async Task ExecuteExport()
{
// Might not cover everything but then the dialog will complain and that's good enough
@ -131,17 +155,26 @@ public class NodeScriptWindowViewModel : NodeScriptWindowViewModelBase
if (result == null)
return;
string json = await File.ReadAllTextAsync(result[0]);
_nodeService.ImportScript(json, NodeScript);
History.Clear();
try
{
_pauseUpdate = true;
string json = await File.ReadAllTextAsync(result[0]);
_nodeService.ImportScript(json, NodeScript);
History.Clear();
await Task.Delay(200);
NodeScriptViewModel.RequestAutoFit();
await Task.Delay(200);
NodeScriptViewModel.RequestAutoFit();
}
finally
{
_pauseUpdate = false;
}
}
private void Update(object? sender, EventArgs e)
{
NodeScript.Run();
if (!_pauseUpdate)
NodeScript.Run();
}
private void Save(object? sender, EventArgs e)

File diff suppressed because it is too large Load Diff

View File

@ -23,23 +23,4 @@
<ProjectReference Include="..\Artemis.UI.Shared\Artemis.UI.Shared.csproj" />
</ItemGroup>
<ItemGroup>
<Compile Update="Nodes\Easing\Screens\EasingTypeNodeEasingView.axaml.cs">
<DependentUpon>EasingTypeNodeEasingView.axaml</DependentUpon>
</Compile>
<Compile Update="Nodes\Static\Screens\StaticStringValueNodeCustomView.axaml.cs">
<DependentUpon>StaticStringValueNodeCustomView.axaml</DependentUpon>
</Compile>
<Compile Update="Nodes\DataModel\Screens\DataModelNodeCustomView.axaml.cs">
<DependentUpon>DataModelNodeCustomView.axaml</DependentUpon>
</Compile>
<Compile Update="Nodes\DataModel\Screens\DataModelEventNodeCustomView.axaml.cs">
<DependentUpon>DataModelEventNodeCustomView.axaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Update="Nodes\Color\Screens\ColorGradientNodeCustomView.axaml.cs">
<DependentUpon>ColorGradientNodeCustomView.axaml</DependentUpon>
</Compile>
</ItemGroup>
</Project>

File diff suppressed because it is too large Load Diff

View File

@ -1,99 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.32014.148
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Artemis.Storage", "Artemis.Storage\Artemis.Storage.csproj", "{E489E5E3-1A65-4AF5-A1EA-F9805FD19A65}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Artemis.Core", "Artemis.Core\Artemis.Core.csproj", "{9B811F9B-86B9-4771-87AF-72BAE7078A36}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Artemis.UI", "Avalonia\Artemis.UI\Artemis.UI.csproj", "{035CBB38-7B9E-4375-A39C-E9A5B01F23A5}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Artemis.UI.Shared", "Avalonia\Artemis.UI.Shared\Artemis.UI.Shared.csproj", "{05A5AB0F-A303-4404-9623-4DB1C9AA1DA0}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Avalonia", "Avalonia", "{960CAAC5-AA73-49F5-BF2F-DF2C789DF042}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Artemis.UI.Windows", "Avalonia\Artemis.UI.Windows\Artemis.UI.Windows.csproj", "{DE45A288-9320-461F-BE2A-26DFE3817216}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Artemis.UI.Linux", "Avalonia\Artemis.UI.Linux\Artemis.UI.Linux.csproj", "{9012C8E2-3BEC-42F5-8270-7352A5922B04}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Artemis.UI.MacOS", "Avalonia\Artemis.UI.MacOS\Artemis.UI.MacOS.csproj", "{2F5F16DC-FACF-4559-9882-37C2949814C7}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Artemis.VisualScripting", "Avalonia\Artemis.VisualScripting\Artemis.VisualScripting.csproj", "{412B921A-26F5-4AE6-8B32-0C19BE54F421}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{E489E5E3-1A65-4AF5-A1EA-F9805FD19A65}.Debug|Any CPU.ActiveCfg = Debug|x64
{E489E5E3-1A65-4AF5-A1EA-F9805FD19A65}.Debug|x64.ActiveCfg = Debug|x64
{E489E5E3-1A65-4AF5-A1EA-F9805FD19A65}.Debug|x64.Build.0 = Debug|x64
{E489E5E3-1A65-4AF5-A1EA-F9805FD19A65}.Release|Any CPU.ActiveCfg = Release|x64
{E489E5E3-1A65-4AF5-A1EA-F9805FD19A65}.Release|x64.ActiveCfg = Release|x64
{E489E5E3-1A65-4AF5-A1EA-F9805FD19A65}.Release|x64.Build.0 = Release|x64
{9B811F9B-86B9-4771-87AF-72BAE7078A36}.Debug|Any CPU.ActiveCfg = Debug|x64
{9B811F9B-86B9-4771-87AF-72BAE7078A36}.Debug|x64.ActiveCfg = Debug|x64
{9B811F9B-86B9-4771-87AF-72BAE7078A36}.Debug|x64.Build.0 = Debug|x64
{9B811F9B-86B9-4771-87AF-72BAE7078A36}.Release|Any CPU.ActiveCfg = Release|x64
{9B811F9B-86B9-4771-87AF-72BAE7078A36}.Release|x64.ActiveCfg = Release|x64
{9B811F9B-86B9-4771-87AF-72BAE7078A36}.Release|x64.Build.0 = Release|x64
{035CBB38-7B9E-4375-A39C-E9A5B01F23A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{035CBB38-7B9E-4375-A39C-E9A5B01F23A5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{035CBB38-7B9E-4375-A39C-E9A5B01F23A5}.Debug|x64.ActiveCfg = Debug|Any CPU
{035CBB38-7B9E-4375-A39C-E9A5B01F23A5}.Debug|x64.Build.0 = Debug|Any CPU
{035CBB38-7B9E-4375-A39C-E9A5B01F23A5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{035CBB38-7B9E-4375-A39C-E9A5B01F23A5}.Release|Any CPU.Build.0 = Release|Any CPU
{035CBB38-7B9E-4375-A39C-E9A5B01F23A5}.Release|x64.ActiveCfg = Release|Any CPU
{035CBB38-7B9E-4375-A39C-E9A5B01F23A5}.Release|x64.Build.0 = Release|Any CPU
{05A5AB0F-A303-4404-9623-4DB1C9AA1DA0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{05A5AB0F-A303-4404-9623-4DB1C9AA1DA0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{05A5AB0F-A303-4404-9623-4DB1C9AA1DA0}.Debug|x64.ActiveCfg = Debug|Any CPU
{05A5AB0F-A303-4404-9623-4DB1C9AA1DA0}.Debug|x64.Build.0 = Debug|Any CPU
{05A5AB0F-A303-4404-9623-4DB1C9AA1DA0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{05A5AB0F-A303-4404-9623-4DB1C9AA1DA0}.Release|Any CPU.Build.0 = Release|Any CPU
{05A5AB0F-A303-4404-9623-4DB1C9AA1DA0}.Release|x64.ActiveCfg = Release|Any CPU
{05A5AB0F-A303-4404-9623-4DB1C9AA1DA0}.Release|x64.Build.0 = Release|Any CPU
{DE45A288-9320-461F-BE2A-26DFE3817216}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DE45A288-9320-461F-BE2A-26DFE3817216}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DE45A288-9320-461F-BE2A-26DFE3817216}.Debug|x64.ActiveCfg = Debug|Any CPU
{DE45A288-9320-461F-BE2A-26DFE3817216}.Debug|x64.Build.0 = Debug|Any CPU
{DE45A288-9320-461F-BE2A-26DFE3817216}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DE45A288-9320-461F-BE2A-26DFE3817216}.Release|Any CPU.Build.0 = Release|Any CPU
{DE45A288-9320-461F-BE2A-26DFE3817216}.Release|x64.ActiveCfg = Release|Any CPU
{DE45A288-9320-461F-BE2A-26DFE3817216}.Release|x64.Build.0 = Release|Any CPU
{9012C8E2-3BEC-42F5-8270-7352A5922B04}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9012C8E2-3BEC-42F5-8270-7352A5922B04}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9012C8E2-3BEC-42F5-8270-7352A5922B04}.Debug|x64.ActiveCfg = Debug|Any CPU
{9012C8E2-3BEC-42F5-8270-7352A5922B04}.Debug|x64.Build.0 = Debug|Any CPU
{9012C8E2-3BEC-42F5-8270-7352A5922B04}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9012C8E2-3BEC-42F5-8270-7352A5922B04}.Release|Any CPU.Build.0 = Release|Any CPU
{9012C8E2-3BEC-42F5-8270-7352A5922B04}.Release|x64.ActiveCfg = Release|Any CPU
{9012C8E2-3BEC-42F5-8270-7352A5922B04}.Release|x64.Build.0 = Release|Any CPU
{2F5F16DC-FACF-4559-9882-37C2949814C7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2F5F16DC-FACF-4559-9882-37C2949814C7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2F5F16DC-FACF-4559-9882-37C2949814C7}.Debug|x64.ActiveCfg = Debug|Any CPU
{2F5F16DC-FACF-4559-9882-37C2949814C7}.Debug|x64.Build.0 = Debug|Any CPU
{2F5F16DC-FACF-4559-9882-37C2949814C7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2F5F16DC-FACF-4559-9882-37C2949814C7}.Release|Any CPU.Build.0 = Release|Any CPU
{2F5F16DC-FACF-4559-9882-37C2949814C7}.Release|x64.ActiveCfg = Release|Any CPU
{2F5F16DC-FACF-4559-9882-37C2949814C7}.Release|x64.Build.0 = Release|Any CPU
{412B921A-26F5-4AE6-8B32-0C19BE54F421}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{412B921A-26F5-4AE6-8B32-0C19BE54F421}.Debug|Any CPU.Build.0 = Debug|Any CPU
{412B921A-26F5-4AE6-8B32-0C19BE54F421}.Debug|x64.ActiveCfg = Debug|Any CPU
{412B921A-26F5-4AE6-8B32-0C19BE54F421}.Debug|x64.Build.0 = Debug|Any CPU
{412B921A-26F5-4AE6-8B32-0C19BE54F421}.Release|Any CPU.ActiveCfg = Release|Any CPU
{412B921A-26F5-4AE6-8B32-0C19BE54F421}.Release|Any CPU.Build.0 = Release|Any CPU
{412B921A-26F5-4AE6-8B32-0C19BE54F421}.Release|x64.ActiveCfg = Release|Any CPU
{412B921A-26F5-4AE6-8B32-0C19BE54F421}.Release|x64.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C203080A-4473-4CC2-844B-F552EA43D66A}
EndGlobalSection
EndGlobal

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +0,0 @@
<Project>
<PropertyGroup>
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
<DisableImplicitNuGetFallbackFolder>true</DisableImplicitNuGetFallbackFolder>
</PropertyGroup>
</Project>

View File

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="NuGet.org" value="https://api.nuget.org/v3/index.json" />
<add key="RGB.NET" value="http://nuget.arge.be/v3/index.json" />
</packageSources>
<activePackageSource>
<add key="All" value="(Aggregate source)" />
</activePackageSource>
</configuration>