├── .editorconfig ├── .gitattributes ├── .gitignore ├── LICENSE.txt ├── NodeLib.File ├── Define │ ├── FileNode.cs │ ├── Func_GetFileMD5.cs │ └── Rename │ │ └── Func_Upper.cs ├── NodeLib.File.csproj └── NodeLibManager.cs ├── README.md ├── XLib.Animate ├── Animation.cs ├── AnimationDelay.cs ├── AnimationEngine.cs ├── AnimationGroup.cs ├── AnimationHelper.cs ├── AnimationQueue.cs ├── IAnimation.cs ├── IMotion.cs └── XLib.Animate.csproj ├── XLib.Base ├── AppFrame │ ├── ManagerDelegate.cs │ ├── ServiceBase.cs │ └── ServiceDelegate.cs ├── ArchiveFrame │ ├── ArchiveFile.cs │ └── ArchiveVersion.cs ├── DataWindow.cs ├── Drive │ └── IFrameDriver.cs ├── EM.cs ├── Ex │ ├── ClassExtension.cs │ ├── DoubleExtension.cs │ ├── IntExtension.cs │ ├── ListExtension.cs │ └── StringExtension.cs ├── FileFilter.cs ├── HighPrecisionTimer.cs ├── ID │ ├── IDBox.cs │ └── IDGrid.cs ├── IDropable.cs ├── IManager.cs ├── ITreeItem.cs ├── NaturalComparator.cs ├── OSTool.cs ├── TreeNodePath.cs ├── UIComponent │ ├── TComponent.cs │ └── TComponentBox.cs ├── VirtualDisk │ ├── File.cs │ ├── FileType.cs │ ├── FileTypeManager.cs │ ├── Folder.cs │ └── Harddisk.cs └── XLib.Base.csproj ├── XLib.Drawing ├── Bitmap.cs ├── Pixel.cs └── XLib.Drawing.csproj ├── XLib.Math ├── Easing │ ├── EF.cs │ ├── EasingMode.cs │ ├── EasingType.cs │ └── IEasingFunction.cs ├── Range.cs └── XLib.Math.csproj ├── XLib.Node ├── EnumDefine.cs ├── INodeLib.cs ├── IProgressGetter.cs ├── NodeBase.cs ├── NodeColor.cs ├── NodeColorSet.cs ├── NodePoint.cs ├── NodeProperty.cs ├── NodeType.cs ├── PinBase.cs ├── PinGroupBase.cs └── XLib.Node.csproj ├── XLib.Sample ├── App.xaml ├── App.xaml.cs ├── AssemblyInfo.cs ├── Layer │ ├── LoadingLayer.cs │ └── TargetPointLayer.cs ├── MainWindow.xaml ├── MainWindow.xaml.cs └── XLib.Sample.csproj ├── XLib.WPF ├── Behavior │ ├── BehaviorArgs.cs │ ├── BehaviorHandler.cs │ ├── BehaviorNode.cs │ ├── BehaviorTree.cs │ └── Behaviors.cs ├── Drawing │ ├── DrawingBoard.cs │ ├── SingleBoard.cs │ └── VisualElement.cs ├── Ex │ ├── StringExtension.cs │ └── StructExtension.cs ├── ToolBase.cs ├── UI │ └── MoveableControl.cs ├── WindowDefine │ ├── XDialog.cs │ ├── XMainWindow.cs │ └── XWindow.cs └── XLib.WPF.csproj ├── XLib.WPFControl ├── BaseStyleSet.xaml ├── ProgressBar.xaml ├── ProgressBar.xaml.cs ├── Tool │ └── SelectTool.cs ├── ToolBar.xaml ├── ToolBar.xaml.cs ├── ToolSplitBar.xaml ├── ToolSplitBar.xaml.cs ├── TreeItem.cs ├── TreeItemView.xaml ├── TreeItemView.xaml.cs ├── TreeView.xaml ├── TreeView.xaml.cs └── XLib.WPFControl.csproj ├── XLib.WPFStyle ├── ButtonStyle.xaml ├── ConvertSet.cs ├── ConverterSet.xaml ├── Image │ ├── Close.png │ ├── Close2.png │ ├── Expand.png │ ├── Furl.png │ ├── Max.png │ ├── Min.png │ ├── Normal.png │ └── XNode.png ├── ScrollBarStyle.xaml ├── TextBoxStyle.xaml ├── ToolTipStyle.xaml ├── WindowStyle.xaml └── XLib.WPFStyle.csproj ├── XNode-MainWindow.png ├── XNode.sln └── XNode ├── App.xaml ├── App.xaml.cs ├── AppTool ├── AppDelegate.cs ├── ClassExtension.cs ├── ProjectDelegate.cs └── SystemDelegate.cs ├── Assets ├── Cursor │ ├── CanNotMove.cur │ ├── Cross.cur │ ├── Disable.cur │ ├── DragObject.cur │ ├── Draw.cur │ ├── Insert.cur │ ├── Move.cur │ ├── MoveBottom.cur │ ├── MoveSelected.cur │ ├── MoveTop.cur │ ├── MoveX.cur │ ├── MoveY.cur │ ├── OnOff.cur │ ├── ResizeDownUp.cur │ ├── ResizeUpDown.cur │ └── Select.cur ├── Font │ └── simsun.ttc ├── Icon15 │ ├── Add.png │ ├── Browse.png │ ├── Clear.png │ ├── ControlBoard.png │ ├── Copy.png │ ├── Delete.png │ ├── EmptyFolder.png │ ├── File.png │ ├── Folder.png │ ├── Lib.png │ ├── Node.png │ ├── NodePreset.png │ ├── Remove.png │ └── Rename.png └── Icon16 │ ├── AlignCenter.png │ ├── AlignLeft.png │ ├── AlignRight.png │ ├── ClearConsole.png │ ├── CloseFile.png │ ├── Console.png │ ├── ExpandAll.png │ ├── FurlAll.png │ ├── NewFile.png │ ├── Node │ ├── CPU.png │ ├── Calculator.png │ ├── Chip.png │ ├── Delay.png │ ├── Fan.png │ ├── Flow.png │ ├── FrameDriver.png │ ├── Function.png │ ├── Key.png │ ├── Loop.png │ ├── Message.png │ ├── Midi.png │ ├── Net.png │ ├── Node.png │ ├── Pause.png │ ├── Spectrum.png │ ├── Timer.png │ ├── Variate.png │ └── Volume.png │ ├── OpenFile.png │ ├── Redo.png │ ├── Rename.png │ ├── Revert.png │ ├── Save.png │ ├── SaveAll.png │ ├── SaveAs.png │ └── Undo.png ├── CoreEditer.xaml ├── CoreEditer.xaml.cs ├── MainWindow.xaml ├── MainWindow.xaml.cs ├── SubSystem ├── ArchiveSystem │ ├── ArchiveManager.cs │ ├── Define │ │ └── Data_1_0 │ │ │ ├── ConnectLineData.cs │ │ │ ├── Data_1_0.cs │ │ │ ├── NodeBaseData.cs │ │ │ └── NodeData.cs │ ├── Extracter.cs │ └── Loader │ │ └── Loader_1_0.cs ├── CacheSystem │ ├── CacheData.cs │ └── CacheManager.cs ├── ControlSystem │ └── ControlEngine.cs ├── EventSystem │ ├── EM.cs │ └── EventType.cs ├── NodeEditSystem │ ├── Control │ │ ├── ActionPinGroupView.xaml │ │ ├── ActionPinGroupView.xaml.cs │ │ ├── ControlPinGroupView.xaml │ │ ├── ControlPinGroupView.xaml.cs │ │ ├── DataPinGroupView.xaml │ │ ├── DataPinGroupView.xaml.cs │ │ ├── ExecutePinGroupView.xaml │ │ ├── ExecutePinGroupView.xaml.cs │ │ ├── HoverToolBar.xaml │ │ ├── HoverToolBar.xaml.cs │ │ ├── Image │ │ │ ├── BreakPin.png │ │ │ ├── Delete.png │ │ │ ├── Light_Black.png │ │ │ ├── Light_Green.png │ │ │ ├── Light_Red.png │ │ │ ├── Start.png │ │ │ └── Stop.png │ │ ├── NodeMap.xaml │ │ ├── NodeMap.xaml.cs │ │ ├── NodePropertyPanel.xaml │ │ ├── NodePropertyPanel.xaml.cs │ │ ├── NodeView.xaml │ │ ├── NodeView.xaml.cs │ │ ├── PinGroupViewBase.cs │ │ └── PropertyBar │ │ │ ├── CustomListItem.xaml │ │ │ ├── CustomListItem.xaml.cs │ │ │ ├── ListEditer.xaml │ │ │ ├── ListEditer.xaml.cs │ │ │ ├── ListSelecter.xaml │ │ │ ├── ListSelecter.xaml.cs │ │ │ ├── PropertyBarBase.cs │ │ │ ├── TextInput.xaml │ │ │ └── TextInput.xaml.cs │ ├── Define │ │ ├── ConnectLine.cs │ │ ├── EnumDefine.cs │ │ ├── PinColorSet.cs │ │ ├── PinConnectInfo.cs │ │ ├── PinPath.cs │ │ └── TargetBox.cs │ └── Panel │ │ ├── Component │ │ ├── CardComponent.cs │ │ ├── DrawingComponent.cs │ │ ├── EditerComponent.cs │ │ ├── InteractionComponent.cs │ │ └── NodeComponent.cs │ │ ├── EditPanel.xaml │ │ ├── EditPanel.xaml.cs │ │ ├── Layer │ │ ├── ConnectLineBackLayer.cs │ │ ├── ConnectLineLayer.cs │ │ ├── GridLayer.cs │ │ ├── HoverBoxLayer.cs │ │ ├── SelectBoxLayer.cs │ │ ├── SelectedBoxLayer.cs │ │ ├── TempConnectLineLayer.cs │ │ └── VisualConnectLine.cs │ │ └── SelectTool.cs ├── NodeLibSystem │ ├── Define │ │ ├── Data │ │ │ ├── Data_Double.cs │ │ │ ├── Data_Int.cs │ │ │ └── Data_String.cs │ │ ├── Drivers │ │ │ ├── FrameDriver.cs │ │ │ └── TimerDriver.cs │ │ ├── Events │ │ │ └── Event_Keyboard.cs │ │ ├── Flows │ │ │ ├── Flow_If.cs │ │ │ ├── Flow_LoopByCount.cs │ │ │ ├── Flow_Switch.cs │ │ │ └── Flow_While.cs │ │ └── Functions │ │ │ ├── Func_Compare.cs │ │ │ ├── Func_CreateThread.cs │ │ │ ├── Func_Delay.cs │ │ │ ├── Func_Log.cs │ │ │ ├── Func_NumberToRatio.cs │ │ │ ├── Func_RatioToInt.cs │ │ │ ├── Func_SendNetMessage.cs │ │ │ └── Func_Sleep.cs │ ├── NodeLibManager.cs │ ├── NodeLibPanel.xaml │ └── NodeLibPanel.xaml.cs ├── OptionSystem │ └── OptionManager.cs ├── ProjectSystem │ ├── FileTool.cs │ ├── NodeProject.cs │ └── ProjectManager.cs ├── ResourceSystem │ ├── CursorManager.cs │ ├── ImageResManager.cs │ ├── PinIconManager.cs │ ├── PinIconTool.cs │ └── ResourceManager.cs ├── TimerSystem │ ├── AppTimer.cs │ ├── ITimerHandler.cs │ └── TimeEngine.cs └── WindowSystem │ ├── AskDialog.xaml │ ├── AskDialog.xaml.cs │ ├── Image │ ├── Break.png │ ├── Error.png │ ├── Info.png │ └── Warning.png │ ├── TipDialog.xaml │ ├── TipDialog.xaml.cs │ └── WM.cs └── XNode.csproj /.editorconfig: -------------------------------------------------------------------------------- 1 | [*.cs] 2 | 3 | # IDE0090: 使用 "new(...)" 4 | dotnet_diagnostic.IDE0090.severity = none 5 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) [year] [fullname] 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, 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, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /NodeLib.File/Define/FileNode.cs: -------------------------------------------------------------------------------- 1 | using XLib.Node; 2 | 3 | namespace NodeLib.File.Define 4 | { 5 | public abstract class FileNode : NodeBase 6 | { 7 | public FileNode() => NodeLibName = "File"; 8 | 9 | public override Dictionary GetParaDict() => new Dictionary(); 10 | } 11 | } -------------------------------------------------------------------------------- /NodeLib.File/Define/Func_GetFileMD5.cs: -------------------------------------------------------------------------------- 1 | using System.Security.Cryptography; 2 | using System.Text; 3 | using XLib.Node; 4 | 5 | namespace NodeLib.File.Define 6 | { 7 | public class Func_GetFileMD5 : FileNode 8 | { 9 | public override void Init() 10 | { 11 | SetViewProperty(NodeColorSet.Function, "Function", "计算文件摘要"); 12 | 13 | PinGroupList.Add(new ExecutePinGroup(this, "计算指定文件的MD5")); 14 | PinGroupList.Add(new DataPinGroup(this, "string", "文件路径", "") 15 | { 16 | BoxWidth = 300, 17 | Readable = false, 18 | Writeable = false 19 | }); 20 | PinGroupList.Add(new DataPinGroup(this, "string", "摘要", "") 21 | { 22 | BoxWidth = 220, 23 | Writeable = false 24 | }); 25 | 26 | InitPinGroup(); 27 | } 28 | 29 | protected override void ExecuteNode() 30 | { 31 | // 获取文件路径 32 | string filePath = GetData(1); 33 | if (filePath == "") return; 34 | 35 | try 36 | { 37 | // 打开文件 38 | using FileStream fileStream = System.IO.File.OpenRead(filePath); 39 | // 计算摘要 40 | using MD5 md5 = MD5.Create(); 41 | byte[] hashBytes = md5.ComputeHash(fileStream); 42 | // 将字节数组转换为十六进制字符串 43 | StringBuilder builder = new StringBuilder(); 44 | foreach (byte item in hashBytes) builder.Append(item.ToString("x2")); 45 | // 设置结果 46 | SetData(2, builder.ToString()); 47 | 48 | GetPinGroup().Execute(); 49 | } 50 | catch (Exception ex) { InvokeExecuteError(ex); } 51 | } 52 | 53 | public override string GetTypeString() => nameof(Func_GetFileMD5); 54 | 55 | public override Dictionary GetParaDict() 56 | { 57 | Dictionary result = new Dictionary 58 | { 59 | { "FilePath", GetData(1) }, 60 | }; 61 | return result; 62 | } 63 | 64 | public override void LoadParaDict(string version, Dictionary paraDict) 65 | { 66 | SetData(1, paraDict["FilePath"]); 67 | } 68 | 69 | protected override NodeBase CloneNode() => new Func_GetFileMD5(); 70 | } 71 | } -------------------------------------------------------------------------------- /NodeLib.File/Define/Rename/Func_Upper.cs: -------------------------------------------------------------------------------- 1 | using XLib.Node; 2 | 3 | namespace NodeLib.File.Define.Rename 4 | { 5 | /// 6 | /// 全大写 7 | /// 8 | public class Func_Upper : FileNode 9 | { 10 | public override void Init() 11 | { 12 | SetViewProperty(NodeColorSet.Function, "Function", "全大写"); 13 | 14 | PinGroupList.Add(new ExecutePinGroup(this, "将文件名改为全大写,忽略扩展名")); 15 | PinGroupList.Add(new DataPinGroup(this, "string", "文件路径", "") 16 | { 17 | BoxWidth = 300, 18 | Readable = false, 19 | Writeable = true 20 | }); 21 | 22 | InitPinGroup(); 23 | } 24 | 25 | protected override void ExecuteNode() 26 | { 27 | // 更新并获取文件路径 28 | UpdateData(1); 29 | string filePath = GetData(1); 30 | if (filePath == "") return; 31 | 32 | try 33 | { 34 | // 获取文件名 35 | string fileName = Path.GetFileNameWithoutExtension(filePath); 36 | // 获取扩展名 37 | string extension = Path.GetExtension(filePath); 38 | // 修改文件名 39 | string newFileName = fileName.ToUpper() + extension; 40 | // 获取文件夹路径 41 | string folderPath = Path.GetDirectoryName(filePath); 42 | // 获取新文件路径 43 | string newFilePath = Path.Combine(folderPath, newFileName); 44 | // 修改文件名 45 | System.IO.File.Move(filePath, newFilePath); 46 | 47 | GetPinGroup().Execute(); 48 | } 49 | catch (Exception ex) { InvokeExecuteError(ex); } 50 | } 51 | 52 | public override string GetTypeString() => nameof(Func_Upper); 53 | 54 | public override Dictionary GetParaDict() 55 | { 56 | Dictionary result = new Dictionary 57 | { 58 | { "FilePath", GetData(1) }, 59 | }; 60 | return result; 61 | } 62 | 63 | public override void LoadParaDict(string version, Dictionary paraDict) 64 | { 65 | SetData(1, paraDict["FilePath"]); 66 | } 67 | 68 | protected override NodeBase CloneNode() => new Func_Upper(); 69 | } 70 | } -------------------------------------------------------------------------------- /NodeLib.File/NodeLib.File.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /NodeLib.File/NodeLibManager.cs: -------------------------------------------------------------------------------- 1 | using NodeLib.File.Define; 2 | using NodeLib.File.Define.Rename; 3 | using XLib.Base.Ex; 4 | using XLib.Base.VirtualDisk; 5 | using XLib.Node; 6 | 7 | namespace NodeLib.File 8 | { 9 | public class NodeLibManager : INodeLib 10 | { 11 | #region 单例 12 | 13 | private NodeLibManager() { } 14 | public static NodeLibManager Instance { get; } = new NodeLibManager(); 15 | 16 | #endregion 17 | 18 | #region INodeLib 属性 19 | 20 | public string Name { get; set; } = "File"; 21 | 22 | public string Title { get; set; } = "文件处理"; 23 | 24 | public Harddisk LibHarddisk { get; set; } = new Harddisk(); 25 | 26 | #endregion 27 | 28 | #region INodeLib 方法 29 | 30 | public void Init() 31 | { 32 | Folder 重命名 = LibHarddisk.CreateFolder("重命名".PackToList()); 33 | 34 | LibHarddisk.CreateFile(重命名, "全大写", "nt", new NodeType()); 35 | 36 | LibHarddisk.CreateFile(LibHarddisk.Root, "计算文件摘要", "nt", new NodeType()); 37 | } 38 | 39 | public void Clear() { } 40 | 41 | public NodeBase? CreateNode(string typeString) 42 | { 43 | return typeString switch 44 | { 45 | nameof(Func_Upper) => new Func_Upper(), 46 | 47 | nameof(Func_GetFileMD5) => new Func_GetFileMD5(), 48 | 49 | _ => null, 50 | }; 51 | } 52 | 53 | #endregion 54 | } 55 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![](https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/master/XNode-MainWindow.png) 2 | 有问题欢迎加QQ群:895857206 3 | -------------------------------------------------------------------------------- /XLib.Animate/AnimationDelay.cs: -------------------------------------------------------------------------------- 1 | namespace XLib.Animate 2 | { 3 | /// 4 | /// 动画延迟 5 | /// 6 | public class AnimationDelay : IAnimation 7 | { 8 | public double Duration { get; set; } = 0; 9 | 10 | public event Action Finished; 11 | 12 | public void Drive(double time) 13 | { 14 | if (time >= Duration) Finished?.Invoke(this); 15 | } 16 | 17 | public double GetTotalLength() => Duration; 18 | 19 | public void Stop() => Finished?.Invoke(this); 20 | } 21 | } -------------------------------------------------------------------------------- /XLib.Animate/AnimationGroup.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | 3 | namespace XLib.Animate 4 | { 5 | /// 6 | /// 动画组:用于同时驱动一组动画 7 | /// 8 | public class AnimationGroup : IAnimation 9 | { 10 | #region 属性、事件 11 | 12 | public List AnimationList { get; set; } = new List(); 13 | 14 | /// 动画已完成 15 | public event Action Finished; 16 | 17 | #endregion 18 | 19 | #region IDriveable 方法 20 | 21 | public double GetTotalLength() 22 | { 23 | double total = 0; 24 | foreach (var animation in AnimationList) 25 | { 26 | double length = animation.GetTotalLength(); 27 | if (length > total) total = length; 28 | } 29 | return total; 30 | } 31 | 32 | public void Drive(double time) 33 | { 34 | foreach (var animation in AnimationList) animation.Drive(time); 35 | } 36 | 37 | public void Stop() 38 | { 39 | foreach (var animation in AnimationList) animation.Stop(); 40 | } 41 | 42 | #endregion 43 | 44 | #region 公开方法 45 | 46 | /// 47 | /// 添加动画 48 | /// 49 | public void Add(IAnimation animation) 50 | { 51 | // 监听动画完成 52 | animation.Finished += Animation_Finished; 53 | // 添加到动画组 54 | AnimationList.Add(animation); 55 | } 56 | 57 | #endregion 58 | 59 | #region 私有方法 60 | 61 | private void Animation_Finished(IAnimation driveable) 62 | { 63 | _finishedCount++; 64 | // 全部完成时,调用动画组完成 65 | if (_finishedCount == AnimationList.Count) Finished?.Invoke(this); 66 | } 67 | 68 | #endregion 69 | 70 | private int _finishedCount = 0; 71 | } 72 | } -------------------------------------------------------------------------------- /XLib.Animate/IAnimation.cs: -------------------------------------------------------------------------------- 1 | namespace XLib.Animate 2 | { 3 | /// 4 | /// 表示一个动画对象 5 | /// 6 | public interface IAnimation 7 | { 8 | /// 动画已完成 9 | public event Action Finished; 10 | 11 | /// 12 | /// 获取总时长 13 | /// 14 | public double GetTotalLength(); 15 | 16 | /// 17 | /// 驱动至指定毫秒 18 | /// 19 | public void Drive(double time); 20 | 21 | /// 22 | /// 停止 23 | /// 24 | public void Stop(); 25 | } 26 | } -------------------------------------------------------------------------------- /XLib.Animate/IMotion.cs: -------------------------------------------------------------------------------- 1 | namespace XLib.Animate 2 | { 3 | /// 4 | /// 表示可运动的对象 5 | /// 6 | public interface IMotion 7 | { 8 | /// 9 | /// 获取运动属性值 10 | /// 11 | public double GetMotionProperty(string propertyName); 12 | 13 | /// 14 | /// 设置运动属性值 15 | /// 16 | public void SetMotionProperty(string propertyName, double value); 17 | } 18 | } -------------------------------------------------------------------------------- /XLib.Animate/XLib.Animate.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /XLib.Base/AppFrame/ManagerDelegate.cs: -------------------------------------------------------------------------------- 1 | namespace XLib.Base.AppFrame 2 | { 3 | /// 4 | /// 管理器代理 5 | /// 6 | public class ManagerDelegate 7 | { 8 | public List ManagerList { get; private set; } = new List(); 9 | 10 | public virtual void Init() 11 | { 12 | foreach (var manager in ManagerList) manager.Init(); 13 | InitFinish(); 14 | } 15 | 16 | public virtual void Clear() 17 | { 18 | foreach (var manager in ManagerList) manager.Clear(); 19 | } 20 | 21 | protected virtual void InitFinish() { } 22 | } 23 | } -------------------------------------------------------------------------------- /XLib.Base/AppFrame/ServiceBase.cs: -------------------------------------------------------------------------------- 1 | namespace XLib.Base.AppFrame 2 | { 3 | /// 4 | /// 服务基类 5 | /// 6 | public abstract class ServiceBase 7 | { 8 | public abstract void Start(); 9 | 10 | public abstract void Stop(); 11 | 12 | public void Restart() 13 | { 14 | Stop(); 15 | Start(); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /XLib.Base/AppFrame/ServiceDelegate.cs: -------------------------------------------------------------------------------- 1 | namespace XLib.Base.AppFrame 2 | { 3 | /// 4 | /// 服务代理 5 | /// 6 | public class ServiceDelegate 7 | { 8 | public List ServiceList { get; private set; } = new List(); 9 | 10 | public void Start() 11 | { 12 | foreach (var service in ServiceList) service.Start(); 13 | } 14 | 15 | public void Stop() 16 | { 17 | foreach (var service in ServiceList) service.Stop(); 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /XLib.Base/ArchiveFrame/ArchiveFile.cs: -------------------------------------------------------------------------------- 1 | namespace XLib.Base.ArchiveFrame 2 | { 3 | /// 4 | /// 存档文件 5 | /// 6 | public class ArchiveFile 7 | { 8 | /// 存档版本 9 | public string Version { get; set; } = "1.0"; 10 | 11 | /// 存档数据 12 | public object? Data { get; set; } = null; 13 | } 14 | } -------------------------------------------------------------------------------- /XLib.Base/ArchiveFrame/ArchiveVersion.cs: -------------------------------------------------------------------------------- 1 | namespace XLib.Base.ArchiveFrame 2 | { 3 | /// 4 | /// 存档版本 5 | /// 6 | public class ArchiveVersion 7 | { 8 | public ArchiveVersion(string version) 9 | { 10 | string[] versionInfo = version.Split('.'); 11 | Main = int.Parse(versionInfo[0]); 12 | Sub = int.Parse(versionInfo[1]); 13 | } 14 | 15 | public int Main { get; set; } = 1; 16 | 17 | public int Sub { get; set; } = 0; 18 | 19 | public string VersionString => $"{Main}.{Sub}"; 20 | 21 | public int CompareTo(ArchiveVersion version) 22 | { 23 | if (version.Main != Main) return version.Main.CompareTo(Main); 24 | if (version.Sub != Sub) return version.Sub.CompareTo(Sub); 25 | return 0; 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /XLib.Base/DataWindow.cs: -------------------------------------------------------------------------------- 1 | namespace XLib.Base 2 | { 3 | /// 4 | /// 数据窗口 5 | /// 6 | public class DataWindow 7 | { 8 | /// 数据 9 | public List Data { get; set; } = new List(); 10 | 11 | /// 窗口高度 12 | public int WindowHeight { get => _windowHeight; set => _windowHeight = value; } 13 | 14 | /// 数据量 15 | public int DataCount => Data.Count; 16 | 17 | public int Top { get => _top; set => _top = value; } 18 | 19 | /// 20 | /// 重置 21 | /// 22 | public void Reset() 23 | { 24 | Data.Clear(); 25 | _startIndex = 0; 26 | _top = 0; 27 | } 28 | 29 | /// 30 | /// 获取可见数据 31 | /// 32 | public List GetVisibleData() 33 | { 34 | // 数据源全部可见 35 | if (Data.Count <= _windowHeight) return Data; 36 | 37 | List result = new List(); 38 | 39 | // 尾端索引 = 起始索引 + 窗口大小 40 | int endIndex = _startIndex + _windowHeight; 41 | // 尾端空白数 42 | int endSpace = endIndex - Data.Count; 43 | // 前移起始索引 44 | if (endSpace > 0) 45 | { 46 | _startIndex -= endSpace; 47 | if (_startIndex < 0) _startIndex = 0; 48 | } 49 | // 插入可见数据 50 | for (int counter = 0; counter < WindowHeight; counter++) 51 | { 52 | result.Add(Data[_startIndex + counter]); 53 | } 54 | 55 | return result; 56 | } 57 | 58 | /// 59 | /// 获取可视数据 60 | /// 61 | /// 是否有剩余空间 62 | public List GetVisibleDataNew(bool residue = false) 63 | { 64 | if (Data.Count <= WindowHeight) return new List(Data); 65 | 66 | List result = new List(); 67 | int endIndex = _top + _windowHeight; 68 | if (residue) endIndex++; 69 | for (int index = _top; index < endIndex; index++) 70 | { 71 | if (index > Data.Count - 1) break; 72 | result.Add(Data[index]); 73 | } 74 | return result; 75 | } 76 | 77 | #region 属性字段 78 | 79 | private int _windowHeight = 10; 80 | private int _startIndex; 81 | private int _top = 0; 82 | 83 | #endregion 84 | } 85 | } -------------------------------------------------------------------------------- /XLib.Base/Drive/IFrameDriver.cs: -------------------------------------------------------------------------------- 1 | namespace XLib.Base.Drive 2 | { 3 | /// 4 | /// 帧驱动器 5 | /// 6 | public interface IFrameDriver 7 | { 8 | public void Update(); 9 | } 10 | } -------------------------------------------------------------------------------- /XLib.Base/Ex/ClassExtension.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | 3 | namespace XLib.Base.Ex 4 | { 5 | public static class ClassExtension 6 | { 7 | public static double DoubleMs(this Stopwatch stopwatch) => stopwatch.ElapsedTicks / (double)Stopwatch.Frequency * 1000; 8 | } 9 | } -------------------------------------------------------------------------------- /XLib.Base/Ex/DoubleExtension.cs: -------------------------------------------------------------------------------- 1 | namespace XLib.Base.Ex 2 | { 3 | public static class DoubleExtension 4 | { 5 | /// 6 | /// 将双精度浮点数限制在指定范围内 7 | /// 8 | public static double Limit(this double value, double min, double max) 9 | { 10 | if (value < min) return min; 11 | if (value > max) return max; 12 | return value; 13 | } 14 | 15 | public static double Round(this double doubleValue) => Math.Round(doubleValue); 16 | 17 | /// 18 | /// 将双精度浮点型四舍五入至整型 19 | /// 20 | public static int RoundInt(this double value) => (int)Math.Round(value); 21 | 22 | public static byte RoundByte(this double doubleValue) 23 | { 24 | // 限定范围 25 | doubleValue = doubleValue.Limit(0, 256); 26 | // 0 - 256 >> 0 - 255 27 | doubleValue = doubleValue / 256 * 255; 28 | return (byte)Math.Round(doubleValue); 29 | } 30 | 31 | /// 32 | /// 四舍五入至指定精度 33 | /// 34 | public static double RoundWithDigits(this double value, int digits = 1) => Math.Round(value, digits); 35 | } 36 | } -------------------------------------------------------------------------------- /XLib.Base/Ex/IntExtension.cs: -------------------------------------------------------------------------------- 1 | namespace XLib.Base.Ex 2 | { 3 | public static class IntExtension 4 | { 5 | /// 6 | /// 将整数限制在指定范围内 7 | /// 8 | public static int Limit(this int value, int min, int max) 9 | { 10 | if (value < min) return min; 11 | if (value > max) return max; 12 | return value; 13 | } 14 | 15 | /// 16 | /// 将毫秒转为时间字符串 17 | /// 18 | public static string ToTimeString(this int ms) => TimeSpan.FromMilliseconds(ms).ToString(StringEx.TimeFormat3); 19 | 20 | public static string ToShortTimeString(this int ms) => TimeSpan.FromSeconds(ms).ToString(StringEx.ShortTime); 21 | } 22 | } -------------------------------------------------------------------------------- /XLib.Base/FileFilter.cs: -------------------------------------------------------------------------------- 1 | using XLib.Base.Ex; 2 | 3 | namespace XLib.Base 4 | { 5 | /// 6 | /// 类型信息 7 | /// 8 | public class TypeInfo 9 | { 10 | public TypeInfo(string name, string extension) 11 | { 12 | Name = name; 13 | Extension = extension; 14 | } 15 | 16 | /// 类型名 17 | public string Name { get; set; } = "文件"; 18 | 19 | /// 扩展名 20 | public string Extension { get; set; } = "*"; 21 | 22 | public override string ToString() => $"{Name}(*.{Extension})|*.{Extension}"; 23 | } 24 | 25 | /// 26 | /// 文件过滤器 27 | /// 28 | public class FileFilter 29 | { 30 | public List TypeList { get; set; } = new List(); 31 | 32 | public override string ToString() => TypeList.ToListString("|"); 33 | } 34 | } -------------------------------------------------------------------------------- /XLib.Base/ID/IDGrid.cs: -------------------------------------------------------------------------------- 1 | namespace XLib.Base.ID 2 | { 3 | /// 4 | /// 编号格子 5 | /// 6 | public class IDGrid 7 | { 8 | public int ID { get; set; } = -1; 9 | 10 | public bool Used { get; set; } = false; 11 | 12 | public override string ToString() => $"{ID:00}{(Used ? " Used" : "")}"; 13 | } 14 | } -------------------------------------------------------------------------------- /XLib.Base/IDropable.cs: -------------------------------------------------------------------------------- 1 | namespace XLib.Base 2 | { 3 | public interface IDropable 4 | { 5 | /// 6 | /// 拖动 7 | /// 8 | public void OnDrag(List fileList); 9 | 10 | /// 11 | /// 放下 12 | /// 13 | public void OnDrop(List fileList); 14 | 15 | /// 16 | /// 能否放下 17 | /// 18 | public bool CanDrop(List fileList); 19 | } 20 | } -------------------------------------------------------------------------------- /XLib.Base/IManager.cs: -------------------------------------------------------------------------------- 1 | namespace XLib.Base 2 | { 3 | /// 4 | /// 管理器接口 5 | /// 6 | public interface IManager 7 | { 8 | /// 初始化 9 | void Init(); 10 | 11 | /// 重置 12 | void Reset(); 13 | 14 | /// 清理 15 | void Clear(); 16 | } 17 | } -------------------------------------------------------------------------------- /XLib.Base/ITreeItem.cs: -------------------------------------------------------------------------------- 1 | namespace XLib.Base 2 | { 3 | public interface ITreeItem 4 | { 5 | #region 属性 6 | 7 | /// 是否为文件夹 8 | public bool IsFolder { get; } 9 | 10 | #endregion 11 | 12 | #region 方法 13 | 14 | /// 15 | /// 重命名 16 | /// 17 | public void Rename(string newName); 18 | 19 | /// 20 | /// 能否移动至 21 | /// 22 | public bool CanMoveTo(ITreeItem target, out string reason); 23 | 24 | /// 25 | /// 通知移动至 26 | /// 27 | public void NotifyMoveTo(ITreeItem target); 28 | 29 | #endregion 30 | } 31 | } -------------------------------------------------------------------------------- /XLib.Base/NaturalComparator.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | 3 | namespace XLib.Base 4 | { 5 | /// 6 | /// 自然比较器 7 | /// 8 | public class NaturalComparator 9 | { 10 | /// 11 | /// 操作系统自带的文件名排序函数 12 | /// 13 | [DllImport("shlwapi.dll", CharSet = CharSet.Unicode, ExactSpelling = true)] 14 | private static extern int StrCmpLogicalW(string? x, string? y); 15 | 16 | public static int Compare(string? x, string? y) => StrCmpLogicalW(x, y); 17 | } 18 | } -------------------------------------------------------------------------------- /XLib.Base/TreeNodePath.cs: -------------------------------------------------------------------------------- 1 | using XLib.Base.Ex; 2 | 3 | namespace XLib.Base 4 | { 5 | /// 6 | /// 表示树中某个节点的路径 7 | /// 8 | public class TreeNodePath 9 | { 10 | public TreeNodePath() { } 11 | 12 | public TreeNodePath(string path, string split = "/") 13 | { 14 | _split = split; 15 | if (path != "") 16 | { 17 | // 移除前后空格 18 | path = path.Trim(); 19 | // 移除前后路径分割符 20 | if (path.StartsWith(_split)) path = path[1..]; 21 | if (path.EndsWith(_split)) path = path[..^1]; 22 | // 分割路径 23 | if (path.Contains(_split)) NodeList = path.Split(_split).ToList(); 24 | else NodeList = new List { path }; 25 | } 26 | } 27 | 28 | /// 路径分割符 29 | public string PathSplit { get => _split; set => _split = value; } 30 | 31 | /// 节点列表 32 | public List NodeList { get; set; } = new List(); 33 | 34 | public TreeNodePath Append(string node) 35 | { 36 | NodeList.Add(node); 37 | return this; 38 | } 39 | 40 | /// 41 | /// 移除第一个节点 42 | /// 43 | public void RemoveFirst() => NodeList.RemoveAt(0); 44 | 45 | /// 46 | /// 移除最后一个节点 47 | /// 48 | public void RemoveLast() => NodeList.RemoveLast(); 49 | 50 | public override string ToString() => NodeList.ToListString(_split); 51 | 52 | private string _split = "/"; 53 | } 54 | } -------------------------------------------------------------------------------- /XLib.Base/VirtualDisk/FileType.cs: -------------------------------------------------------------------------------- 1 | namespace XLib.Base.VirtualDisk 2 | { 3 | public class FileType 4 | { 5 | /// 扩展名 6 | public string Extension { get; set; } = ""; 7 | 8 | /// 图标名 9 | public string IconName { get; set; } = ""; 10 | 11 | /// 类型名 12 | public string TypeName { get; set; } = ""; 13 | } 14 | } -------------------------------------------------------------------------------- /XLib.Base/VirtualDisk/FileTypeManager.cs: -------------------------------------------------------------------------------- 1 | namespace XLib.Base.VirtualDisk 2 | { 3 | /// 4 | /// 文件类型管理器 5 | /// 6 | public class FileTypeManager 7 | { 8 | #region 单例 9 | 10 | private FileTypeManager() { } 11 | public static FileTypeManager Instance { get; } = new FileTypeManager(); 12 | 13 | #endregion 14 | 15 | #region 公开方法 16 | 17 | /// 18 | /// 注册文件类型 19 | /// 20 | public void RegisterFileType(string extension, string icon, string typeName) 21 | { 22 | if (extension == "") 23 | throw new Exception("扩展名不能为空"); 24 | if (_fileTypeDict.ContainsKey(extension)) 25 | throw new Exception("已注册扩展名:" + extension); 26 | 27 | _fileTypeDict.Add(extension, new FileType() 28 | { 29 | Extension = extension, 30 | IconName = icon, 31 | TypeName = typeName 32 | }); 33 | } 34 | 35 | /// 36 | /// 获取文件类型 37 | /// 38 | public FileType GetFileType(string extension) 39 | { 40 | if (extension == "") 41 | throw new Exception("扩展名不能为空"); 42 | if (!_fileTypeDict.ContainsKey(extension)) 43 | throw new Exception("未注册扩展名:" + extension); 44 | 45 | return _fileTypeDict[extension]; 46 | } 47 | 48 | #endregion 49 | 50 | #region 字段 51 | 52 | /// 文件类型表 53 | private readonly Dictionary _fileTypeDict = new Dictionary(); 54 | 55 | #endregion 56 | } 57 | } -------------------------------------------------------------------------------- /XLib.Base/XLib.Base.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /XLib.Drawing/XLib.Drawing.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /XLib.Math/Easing/EasingMode.cs: -------------------------------------------------------------------------------- 1 | namespace XLib.Math.Easing 2 | { 3 | /// 4 | /// 缓动模式 5 | /// 6 | public enum EasingMode 7 | { 8 | /// 缓入缓出 9 | EaseInOut, 10 | /// 缓入 11 | EaseIn, 12 | /// 缓出 13 | EaseOut, 14 | } 15 | } -------------------------------------------------------------------------------- /XLib.Math/Easing/EasingType.cs: -------------------------------------------------------------------------------- 1 | namespace XLib.Math.Easing 2 | { 3 | /// 4 | /// 缓动类型 5 | /// 6 | public enum EasingType 7 | { 8 | /// 线性 9 | LinearEase, 10 | /// 二次方 11 | QuadraticEase, 12 | /// 三次方 13 | CubicEase, 14 | /// 四次方 15 | QuarticEase, 16 | /// 五次方 17 | QuinticEase, 18 | /// 正弦 19 | SineEase, 20 | /// 振荡 21 | ElasticEase, 22 | /// 弹跳 23 | BounceEase, 24 | /// 后退 25 | BackEase, 26 | /// 圆形 27 | CircleEase, 28 | } 29 | } -------------------------------------------------------------------------------- /XLib.Math/Range.cs: -------------------------------------------------------------------------------- 1 | namespace XLib.Math 2 | { 3 | public struct Range 4 | { 5 | public Range(double left, double right) 6 | { 7 | Left = left; 8 | Right = right; 9 | } 10 | 11 | public double Left { get; set; } 12 | 13 | public double Right { get; set; } 14 | } 15 | } -------------------------------------------------------------------------------- /XLib.Math/XLib.Math.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /XLib.Node/EnumDefine.cs: -------------------------------------------------------------------------------- 1 | namespace XLib.Node; 2 | 3 | /// 4 | /// 节点状态 5 | /// 6 | public enum NodeState 7 | { 8 | /// 禁用 9 | Disable, 10 | /// 启用 11 | Enable, 12 | } 13 | 14 | /// 15 | /// 引脚组类型 16 | /// 17 | public enum PinGroupType 18 | { 19 | /// 执行引脚组 20 | Execute, 21 | /// 数据引脚组 22 | Data, 23 | /// 动作引脚组 24 | Action, 25 | /// 控件引脚组 26 | Control, 27 | } 28 | 29 | /// 30 | /// 引脚流向 31 | /// 32 | public enum PinFlow 33 | { 34 | /// 输入 35 | Input, 36 | /// 输出 37 | Output, 38 | } -------------------------------------------------------------------------------- /XLib.Node/INodeLib.cs: -------------------------------------------------------------------------------- 1 | using XLib.Base.VirtualDisk; 2 | 3 | namespace XLib.Node; 4 | 5 | /// 6 | /// 节点库接口 7 | /// 8 | public interface INodeLib 9 | { 10 | /// 库名称:用于标识库 11 | public string Name { get; set; } 12 | 13 | /// 库标题:用于显示 14 | public string Title { get; set; } 15 | 16 | /// 库磁盘 17 | public Harddisk LibHarddisk { get; set; } 18 | 19 | /// 20 | /// 初始化库 21 | /// 22 | public void Init(); 23 | 24 | /// 25 | /// 清理库 26 | /// 27 | public void Clear(); 28 | 29 | /// 30 | /// 创建节点 31 | /// 32 | public NodeBase? CreateNode(string typeString); 33 | } -------------------------------------------------------------------------------- /XLib.Node/IProgressGetter.cs: -------------------------------------------------------------------------------- 1 | namespace XLib.Node 2 | { 3 | /// 4 | /// 进度获取器 5 | /// 6 | public interface IProgressGetter 7 | { 8 | /// 9 | /// 获取进度 10 | /// 11 | public double GetProgress(); 12 | } 13 | } -------------------------------------------------------------------------------- /XLib.Node/NodeColor.cs: -------------------------------------------------------------------------------- 1 | namespace XLib.Node; 2 | 3 | /// 4 | /// 节点颜色 5 | /// 6 | public class NodeColor 7 | { 8 | public NodeColor() { } 9 | 10 | public NodeColor(byte r, byte g, byte b, byte a = 255) 11 | { 12 | this.r = r; 13 | this.g = g; 14 | this.b = b; 15 | this.a = a; 16 | } 17 | 18 | public NodeColor(string hexCode) 19 | { 20 | r = Convert.ToByte(hexCode.Substring(0, 2), 16); 21 | g = Convert.ToByte(hexCode.Substring(2, 2), 16); 22 | b = Convert.ToByte(hexCode.Substring(4, 2), 16); 23 | } 24 | 25 | #pragma warning disable IDE1006 26 | 27 | public byte a { get; set; } = 255; 28 | 29 | public byte r { get; set; } = 255; 30 | 31 | public byte g { get; set; } = 255; 32 | 33 | public byte b { get; set; } = 255; 34 | 35 | #pragma warning restore IDE1006 36 | 37 | public string HexCode => $"{a:X2}{r:X2}{g:X2}{b:X2}"; 38 | } -------------------------------------------------------------------------------- /XLib.Node/NodeColorSet.cs: -------------------------------------------------------------------------------- 1 | namespace XLib.Node 2 | { 3 | /// 4 | /// 节点颜色集 5 | /// 6 | public class NodeColorSet 7 | { 8 | /// 传感器 9 | public static NodeColor Sensor => new NodeColor("DC6464"); 10 | 11 | /// 驱动器 12 | public static NodeColor Driver => new NodeColor("FF8400"); 13 | 14 | /// 事件 15 | public static NodeColor Event => new NodeColor("F4E89D"); 16 | 17 | /// 函数 18 | public static NodeColor Function => new NodeColor("55AAFE"); 19 | 20 | /// 流控制 21 | public static NodeColor Flow => new NodeColor("B3D465"); 22 | 23 | /// 数据 24 | public static NodeColor Data => new NodeColor("AAAAAA"); 25 | 26 | /// 显示器 27 | public static NodeColor Display => new NodeColor("FFFFFF"); 28 | } 29 | } -------------------------------------------------------------------------------- /XLib.Node/NodePoint.cs: -------------------------------------------------------------------------------- 1 | namespace XLib.Node; 2 | 3 | /// 4 | /// 节点坐标 5 | /// 6 | public class NodePoint 7 | { 8 | public NodePoint() { } 9 | 10 | public NodePoint(int x, int y) 11 | { 12 | X = x; 13 | Y = y; 14 | } 15 | 16 | public NodePoint(string point) 17 | { 18 | X = int.Parse(point.Split(',')[0]); 19 | Y = int.Parse(point.Split(',')[1]); 20 | } 21 | 22 | public int X { get; set; } = 0; 23 | 24 | public int Y { get; set; } = 0; 25 | 26 | public override string ToString() => $"{X},{Y}"; 27 | } -------------------------------------------------------------------------------- /XLib.Node/NodeProperty.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json; 2 | 3 | namespace XLib.Node; 4 | 5 | /// 6 | /// 节点属性 7 | /// 8 | public class NodeProperty 9 | { 10 | public NodeProperty() { } 11 | 12 | public NodeProperty(string type, string name, string value) 13 | { 14 | Type = type; 15 | Name = name; 16 | Value = value; 17 | } 18 | 19 | /// 类型 20 | public string Type { get; set; } = ""; 21 | 22 | /// 名称 23 | public string Name { get; set; } = ""; 24 | 25 | /// 26 | public string Value 27 | { 28 | get => _value; 29 | set 30 | { 31 | if (_value == value) return; 32 | _value = value; 33 | ValueChanged?.Invoke(_value); 34 | } 35 | } 36 | 37 | public event Action ValueChanged; 38 | 39 | private string _value = ""; 40 | } 41 | 42 | /// 43 | /// 列表属性 44 | /// 45 | public class ListProperty : NodeProperty 46 | { 47 | public ListProperty() => Type = "List"; 48 | 49 | /// 获取值列表 50 | public Func>? GetValueList { get; set; } = null; 51 | 52 | public int Index 53 | { 54 | get => _index; 55 | set 56 | { 57 | _index = value; 58 | IndexChanged?.Invoke(_index); 59 | } 60 | } 61 | 62 | public Action? IndexChanged { get; set; } = null; 63 | 64 | private int _index = -1; 65 | } 66 | 67 | /// 68 | /// 自定义列表。表示可手动添加、删除的列表 69 | /// 70 | public class CustomListProperty : NodeProperty 71 | { 72 | public CustomListProperty() => Type = "CustomList"; 73 | 74 | public CustomListProperty(string itemList) 75 | { 76 | Type = "CustomList"; 77 | ItemList = JsonSerializer.Deserialize>(itemList); 78 | } 79 | 80 | public List ItemList { get; set; } = new List(); 81 | 82 | public Action? ItemAdded { get; set; } = null; 83 | 84 | public Action? ItemRemoved { get; set; } = null; 85 | 86 | public Action? ItemChanged { get; set; } = null; 87 | 88 | public override string ToString() => JsonSerializer.Serialize(ItemList); 89 | } -------------------------------------------------------------------------------- /XLib.Node/NodeType.cs: -------------------------------------------------------------------------------- 1 | namespace XLib.Node; 2 | 3 | /// 4 | /// 节点类型 5 | /// 6 | public abstract class NodeType 7 | { 8 | /// 9 | /// 实例化默认类型的节点 10 | /// 11 | public abstract NodeBase NewInstance(); 12 | 13 | /// 14 | /// 实例化指定类型的节点 15 | /// 16 | public abstract T NewInstance() where T : NodeBase; 17 | } 18 | 19 | public class NodeType : NodeType where SourceType : NodeBase, new() 20 | { 21 | public override string ToString() => typeof(SourceType).Name; 22 | 23 | public override NodeBase NewInstance() 24 | { 25 | SourceType result = new SourceType(); 26 | result.Init(); 27 | return result; 28 | } 29 | 30 | public override ResultType NewInstance() 31 | { 32 | SourceType instance = new SourceType(); 33 | if (instance is ResultType result) 34 | { 35 | result.Init(); 36 | return result; 37 | } 38 | throw new Exception($"无法将“{typeof(SourceType).Name}”转换为“{typeof(ResultType).Name}”"); 39 | } 40 | } -------------------------------------------------------------------------------- /XLib.Node/PinBase.cs: -------------------------------------------------------------------------------- 1 | namespace XLib.Node; 2 | 3 | /// 4 | /// 引脚基类 5 | /// 6 | public abstract class PinBase 7 | { 8 | public PinBase(PinGroupBase group) => OwnerGroup = group; 9 | 10 | /// 流向 11 | public PinFlow Flow { get; set; } = PinFlow.Input; 12 | 13 | /// 所属引脚组 14 | public PinGroupBase OwnerGroup { get; set; } 15 | 16 | /// 源引脚列表 17 | public List SourceList { get; set; } = new List(); 18 | 19 | /// 目标引脚列表 20 | public List TargetList { get; set; } = new List(); 21 | 22 | /// 23 | /// 添加源引脚 24 | /// 25 | public virtual void AddSource(PinBase source) 26 | { 27 | if (SourceList.Contains(source)) return; 28 | SourceList.Add(source); 29 | } 30 | 31 | /// 32 | /// 添加目标引脚 33 | /// 34 | public void AddTarget(PinBase target) 35 | { 36 | if (TargetList.Contains(target)) return; 37 | TargetList.Add(target); 38 | } 39 | } 40 | 41 | /// 42 | /// 执行引脚 43 | /// 44 | public class ExecutePin : PinBase 45 | { 46 | public ExecutePin(PinGroupBase group) : base(group) { } 47 | 48 | public void Execute() 49 | { 50 | // 输入引脚,执行所属节点 51 | if (Flow == PinFlow.Input) 52 | { 53 | OwnerGroup.OwnerNode.Execute(); 54 | return; 55 | } 56 | // 输出引脚,执行目标引脚列表 57 | foreach (var item in TargetList) 58 | if (item is ExecutePin executePin) executePin.Execute(); 59 | } 60 | } 61 | 62 | /// 63 | /// 数据引脚 64 | /// 65 | public class DataPin : PinBase 66 | { 67 | public DataPin(PinGroupBase group) : base(group) { } 68 | 69 | public override void AddSource(PinBase source) 70 | { 71 | // 如果已有连接,则先与源断开 72 | if (SourceList.Count > 0) 73 | { 74 | SourceList[0].TargetList.Remove(this); 75 | SourceList.Clear(); 76 | } 77 | // 添加新的连接 78 | SourceList.Add(source); 79 | } 80 | } -------------------------------------------------------------------------------- /XLib.Node/XLib.Node.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /XLib.Sample/App.xaml: -------------------------------------------------------------------------------- 1 |  6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /XLib.Sample/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using XLib.Animate; 3 | 4 | namespace XLib.Sample 5 | { 6 | /// 7 | /// 此应用程序用于演示 XLib 的功能 8 | /// 9 | public partial class App : Application 10 | { 11 | public App() 12 | { 13 | Startup += App_Startup; 14 | } 15 | 16 | private void App_Startup(object sender, StartupEventArgs e) 17 | { 18 | AnimationEngine.Instance.Start(); 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /XLib.Sample/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | 3 | [assembly: ThemeInfo( 4 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located 5 | //(used if a resource is not found in the page, 6 | // or application resource dictionaries) 7 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located 8 | //(used if a resource is not found in the page, 9 | // app, or any theme specific resource dictionaries) 10 | )] 11 | -------------------------------------------------------------------------------- /XLib.Sample/Layer/TargetPointLayer.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using System.Windows.Media; 3 | using System.Windows.Threading; 4 | using XLib.Animate; 5 | using XLib.Math.Easing; 6 | using XLib.WPF.Drawing; 7 | 8 | namespace XLib.Sample.Layer 9 | { 10 | /// 11 | /// 目标点图层。测试动画用 12 | /// 13 | public class TargetPointLayer : SingleBoard, IMotion 14 | { 15 | public Point TargetPoint { get; set; } = new Point(); 16 | 17 | public override void Init() 18 | { 19 | _pen.Freeze(); 20 | } 21 | 22 | protected override void OnUpdate() 23 | { 24 | Opacity = _opacity; 25 | _dc.DrawEllipse(null, _pen, TargetPoint, _size / 2, _size / 2); 26 | } 27 | 28 | public double GetMotionProperty(string propertyName) => 0; 29 | 30 | public void SetMotionProperty(string propertyName, double value) 31 | { 32 | switch (propertyName) 33 | { 34 | case "Size": 35 | _size = value; 36 | Console.WriteLine(_size); 37 | break; 38 | case "Alpha": 39 | _opacity = value; 40 | break; 41 | } 42 | Dispatcher.Invoke(Update); 43 | } 44 | 45 | public void SetTargetPoint(Point point) 46 | { 47 | TargetPoint = point; 48 | // 创建动画组 49 | AnimationGroup group = new AnimationGroup(); 50 | group.Add(this.CreateAnimation("Size", 0, 400, 2800, EasingType.QuinticEase, EasingMode.EaseOut, loop: true)); 51 | group.Add(this.CreateAnimation("Alpha", 1, 0, 2800, loop: true)); 52 | // 添加动画组 53 | AnimationEngine.Instance.AddAnimation(group); 54 | } 55 | 56 | private double _size = 0; 57 | private double _opacity = 1; 58 | 59 | private readonly Pen _pen = new Pen(Brushes.Black, 1); 60 | } 61 | } -------------------------------------------------------------------------------- /XLib.Sample/MainWindow.xaml: -------------------------------------------------------------------------------- 1 |  9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /XLib.Sample/MainWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using System.Windows.Input; 3 | using XLib.Sample.Layer; 4 | 5 | namespace XLib.Sample 6 | { 7 | public partial class MainWindow : Window 8 | { 9 | public MainWindow() 10 | { 11 | InitializeComponent(); 12 | } 13 | 14 | private void MainGrid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) 15 | { 16 | LoadingLayer loadingLayer = new LoadingLayer { Margin = new Thickness(50) }; 17 | loadingLayer.Init(); 18 | MainGrid.Children.Add(loadingLayer); 19 | loadingLayer.Start(); 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /XLib.Sample/XLib.Sample.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | WinExe 5 | net6.0-windows 6 | enable 7 | enable 8 | true 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /XLib.WPF/Behavior/BehaviorArgs.cs: -------------------------------------------------------------------------------- 1 | namespace XLib.WPF.Behavior 2 | { 3 | /// 4 | /// 行为参数 5 | /// 6 | public class BehaviorArgs { } 7 | } -------------------------------------------------------------------------------- /XLib.WPF/Behavior/BehaviorNode.cs: -------------------------------------------------------------------------------- 1 | namespace XLib.WPF.Behavior 2 | { 3 | /// 4 | /// 行为节点 5 | /// 6 | public class BehaviorNode 7 | { 8 | public BehaviorNode(string name, Action? action) 9 | { 10 | Name = name; 11 | Action = action; 12 | } 13 | 14 | /// 名称 15 | public string Name { get; set; } 16 | 17 | /// 动作 18 | public Action? Action { get; set; } 19 | 20 | /// 键盘按下 21 | public Action? KeyDown { get; set; } 22 | 23 | /// 键盘松开 24 | public Action? KeyUp { get; set; } 25 | 26 | /// 鼠标滚轮 27 | public Action? MouseWheel { get; set; } 28 | 29 | /// 子节点列表 30 | public List SubNodeList { get; set; } = new List(); 31 | 32 | /// 启用 33 | public bool Enabled { get; set; } = true; 34 | 35 | /// 36 | /// 查找子节点 37 | /// 38 | public BehaviorNode? FindSubNode(string name) => SubNodeList.Find(node => node.Name == name); 39 | } 40 | } -------------------------------------------------------------------------------- /XLib.WPF/Behavior/Behaviors.cs: -------------------------------------------------------------------------------- 1 | namespace XLib.WPF.Behavior 2 | { 3 | /// 4 | /// 通用行为 5 | /// 6 | public class Behaviors 7 | { 8 | /// 左键按下 9 | public static readonly string LeftDown = "左键按下"; 10 | 11 | /// 左键松开 12 | public static readonly string LeftUp = "左键松开"; 13 | 14 | /// 左键长按 15 | public static readonly string LongPress = "长按"; 16 | 17 | /// 左键双击 18 | public static readonly string DoubleClick = "左键双击"; 19 | 20 | /// 中键按下 21 | public static readonly string MiddleDown = "中键按下"; 22 | 23 | /// 中键松开 24 | public static readonly string MiddleUp = "中键松开"; 25 | 26 | /// 右键按下 27 | public static readonly string RightDown = "右键按下"; 28 | 29 | /// 右键松开 30 | public static readonly string RightUp = "右键松开"; 31 | 32 | /// 移动 33 | public static readonly string Move = "移动"; 34 | 35 | /// 滚轮 36 | public static readonly string Wheel = "滚轮"; 37 | 38 | /// 鼠标进入 39 | public static readonly string Enter = "鼠标进入"; 40 | 41 | /// 鼠标离开 42 | public static readonly string Leave = "鼠标离开"; 43 | 44 | /// 键盘按下 45 | public static readonly string KeyDown = "键盘按下"; 46 | 47 | /// 键盘松开 48 | public static readonly string KeyUp = "键盘松开"; 49 | 50 | /// 命中空白处 51 | public static readonly string HitedSpace = "命中空白处"; 52 | } 53 | } -------------------------------------------------------------------------------- /XLib.WPF/Drawing/SingleBoard.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | using System.Windows; 3 | using System.Windows.Media; 4 | 5 | namespace XLib.WPF.Drawing 6 | { 7 | /// 8 | /// 简单画板。仅包含一个可视对象 9 | /// 10 | public abstract class SingleBoard : FrameworkElement 11 | { 12 | public SingleBoard() 13 | { 14 | AddVisualChild(_visual); 15 | AddLogicalChild(_visual); 16 | } 17 | 18 | public Point Point { get; set; } = new Point(); 19 | 20 | protected override int VisualChildrenCount => 1; 21 | 22 | protected override Visual GetVisualChild(int index) => _visual; 23 | 24 | public virtual void Init() { } 25 | 26 | public void Update() 27 | { 28 | _dc = _visual.RenderOpen(); 29 | if (IsEnabled) OnUpdate(); 30 | _dc.Close(); 31 | } 32 | 33 | public void Clear() => _visual.RenderOpen().Close(); 34 | 35 | protected abstract void OnUpdate(); 36 | 37 | /// 38 | /// 绘制顶点 39 | /// 40 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 41 | protected void DrawVertex(DrawingContext dc, Point point, double size, Brush brush, Pen pen) 42 | { 43 | double x = point.X - size / 2; 44 | double y = point.Y - size / 2; 45 | dc.DrawRectangle(brush, pen, new Rect(x, y, size, size)); 46 | } 47 | 48 | private readonly DrawingVisual _visual = new DrawingVisual(); 49 | protected DrawingContext? _dc; 50 | } 51 | } -------------------------------------------------------------------------------- /XLib.WPF/Drawing/VisualElement.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Media; 2 | 3 | namespace XLib.WPF.Drawing 4 | { 5 | /// 6 | /// 可视元素 7 | /// 8 | public abstract class VisualElement : DrawingVisual 9 | { 10 | public void Update() 11 | { 12 | using DrawingContext context = RenderOpen(); 13 | OnUpdate(context); 14 | } 15 | 16 | public void Clear() => RenderOpen().Close(); 17 | 18 | protected abstract void OnUpdate(DrawingContext context); 19 | } 20 | } -------------------------------------------------------------------------------- /XLib.WPF/Ex/StringExtension.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Media; 2 | 3 | namespace XLib.WPF.Ex 4 | { 5 | public static class StringExtension 6 | { 7 | /// 8 | /// 颜色代码转颜色。格式:FFFFFF 9 | /// 10 | public static Color ToColor(this string hexCode) 11 | { 12 | try 13 | { 14 | byte r = Convert.ToByte(hexCode.Substring(0, 2), 16); 15 | byte g = Convert.ToByte(hexCode.Substring(2, 2), 16); 16 | byte b = Convert.ToByte(hexCode.Substring(4, 2), 16); 17 | return Color.FromRgb(r, g, b); 18 | } 19 | catch (Exception) { return Colors.Black; } 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /XLib.WPF/Ex/StructExtension.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Media; 2 | 3 | namespace XLib.WPF.Ex 4 | { 5 | public static class StructExtension 6 | { 7 | /// 8 | /// Drawing.Color -> Media.Color 9 | /// 10 | public static Color ToMediaColor(this System.Drawing.Color color) 11 | { 12 | return Color.FromArgb(color.A, color.R, color.G, color.B); 13 | } 14 | 15 | /// 16 | /// Media.Color -> Drawing.Color 17 | /// 18 | public static System.Drawing.Color ToDrawingColor(this Color color) 19 | { 20 | return System.Drawing.Color.FromArgb(color.A, color.R, color.G, color.B); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /XLib.WPF/UI/MoveableControl.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using System.Windows.Controls; 3 | 4 | namespace XLib.WPF.UI 5 | { 6 | /// 7 | /// 表示可移动的用户控件 8 | /// 9 | public class MoveableControl : UserControl 10 | { 11 | #region 属性 12 | 13 | /// 当前坐标 14 | public Point Point 15 | { 16 | get => new(_real.X + _offset.X, _real.Y + _offset.Y); 17 | set 18 | { 19 | _real = value; 20 | _offset = new Point(); 21 | } 22 | } 23 | 24 | #endregion 25 | 26 | #region 公开方法 27 | 28 | /// 29 | /// 设置偏移 30 | /// 31 | public void SetOffset(Point offset) 32 | { 33 | _offset = offset; 34 | } 35 | 36 | /// 37 | /// 应用偏移 38 | /// 39 | public void ApplyOffset() 40 | { 41 | _real.X += _offset.X; 42 | _real.Y += _offset.Y; 43 | _offset = new Point(); 44 | OnOffsetChanged(); 45 | } 46 | 47 | #endregion 48 | 49 | protected virtual void OnOffsetChanged() { } 50 | 51 | #region 字段 52 | 53 | /// 真实坐标 54 | private Point _real = new Point(); 55 | /// 偏移坐标 56 | private Point _offset = new Point(); 57 | 58 | #endregion 59 | } 60 | } -------------------------------------------------------------------------------- /XLib.WPF/WindowDefine/XDialog.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Controls; 2 | using System.Windows.Input; 3 | using System.Windows.Media; 4 | 5 | namespace XLib.WPF.WindowDefine 6 | { 7 | public class XDialog : XWindow 8 | { 9 | protected override void AddWindowControl() 10 | { 11 | // 关闭按钮 12 | if (GetTemplateChild("CloseButton") is Button close) 13 | close.Click += (_, _) => OnCloseClick(); 14 | // 查找背景网格 15 | if (FindName("BackGrid") is Grid grid) 16 | { 17 | // 设置背景色,确保能被鼠标命中 18 | grid.Background ??= Brushes.Transparent; 19 | grid.MouseLeftButtonDown += BackGrid_MouseDown; 20 | } 21 | } 22 | 23 | /// 24 | /// 关闭.单击 25 | /// 26 | protected virtual void OnCloseClick() => Close(); 27 | 28 | private void BackGrid_MouseDown(object sender, MouseButtonEventArgs e) 29 | { 30 | if (e.LeftButton == MouseButtonState.Pressed) DragMove(); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /XLib.WPF/WindowDefine/XWindow.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using System.Windows.Controls; 3 | using System.Windows.Media.Imaging; 4 | 5 | namespace XLib.WPF.WindowDefine 6 | { 7 | public abstract class XWindow : Window 8 | { 9 | #region 属性 10 | 11 | /// 自定义图标 12 | public string CustomIcon { get; set; } = ""; 13 | 14 | #endregion 15 | 16 | #region 构造方法 17 | 18 | public XWindow() 19 | 20 | { 21 | Loaded += XWindow_Loaded; 22 | } 23 | 24 | #endregion 25 | 26 | #region 内部方法 27 | 28 | /// 29 | /// 添加窗口控制 30 | /// 31 | protected abstract void AddWindowControl(); 32 | 33 | /// 34 | /// 窗口已加载 35 | /// 36 | protected virtual void XWindowLoaded() { } 37 | 38 | #endregion 39 | 40 | #region 窗口事件 41 | 42 | private void XWindow_Loaded(object sender, RoutedEventArgs e) 43 | { 44 | // 添加窗口控制 45 | AddWindowControl(); 46 | // 设置左上角图标 47 | if (CustomIcon != "") 48 | { 49 | if (GetTemplateChild("WindowIcon") is Image icon) 50 | { 51 | var uri = new Uri($"pack://application:,,,/Assets/{CustomIcon}.png"); 52 | var bitmap = new BitmapImage(uri); 53 | icon.Source = bitmap; 54 | } 55 | } 56 | // 调用已加载 57 | XWindowLoaded(); 58 | } 59 | 60 | #endregion 61 | } 62 | } -------------------------------------------------------------------------------- /XLib.WPF/XLib.WPF.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0-windows 5 | enable 6 | true 7 | enable 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /XLib.WPFControl/BaseStyleSet.xaml: -------------------------------------------------------------------------------- 1 |  3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /XLib.WPFControl/ProgressBar.xaml: -------------------------------------------------------------------------------- 1 |  9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /XLib.WPFControl/ProgressBar.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using System.Windows.Controls; 3 | using XLib.Base.Ex; 4 | 5 | namespace XLib.WPFControl 6 | { 7 | public partial class ProgressBar : UserControl 8 | { 9 | /// 进度 10 | public double Progress 11 | { 12 | get => _progress; 13 | set 14 | { 15 | _progress = value.Limit(0, 1); 16 | if (double.IsNaN(_progress)) _progress = 0; 17 | UpdateProgress(); 18 | } 19 | } 20 | 21 | public ProgressBar() 22 | { 23 | InitializeComponent(); 24 | SizeChanged += ProgressBar_SizeChanged; 25 | } 26 | 27 | private void ProgressBar_SizeChanged(object sender, SizeChangedEventArgs e) 28 | { 29 | if (e.WidthChanged) UpdateProgress(); 30 | } 31 | 32 | /// 33 | /// 更新进度 34 | /// 35 | private void UpdateProgress() 36 | { 37 | Progress_Inner.Width = MainGrid.ActualWidth; 38 | Progress_Box.Width = (int)(MainGrid.ActualWidth * _progress); 39 | } 40 | 41 | private double _progress = 0; 42 | } 43 | } -------------------------------------------------------------------------------- /XLib.WPFControl/Tool/SelectTool.cs: -------------------------------------------------------------------------------- 1 | using XLib.WPF; 2 | using XLib.WPF.Behavior; 3 | 4 | namespace XLib.WPFControl.Tool 5 | { 6 | public class SelectTool : ToolBase 7 | { 8 | public SelectTool(TreeView host) : base(host) { } 9 | 10 | public override void Init() 11 | { 12 | // 开始拖动 -> 松开 13 | NewTree("开始拖动", (_) => 14 | { 15 | _host.BeginDragItem(); 16 | _host.Capture(); 17 | }); 18 | NewNode(Behaviors.LeftUp, (_) => 19 | { 20 | ResetTree(); 21 | _host.ReleaseCapture(); 22 | }); 23 | // 开始拖动 -> 移动 -> 松开 24 | BackToRoot(); 25 | NewNode(Behaviors.Move, (_) => 26 | { 27 | switch (_host.GetMouseSide()) 28 | { 29 | case MouseSide.InSide: 30 | _host.DragItem(); 31 | break; 32 | case MouseSide.OutSide: 33 | _host.DragItemTo(); 34 | break; 35 | } 36 | }); 37 | NewNode(Behaviors.LeftUp, (_) => 38 | { 39 | ResetTree(); 40 | _host.ReleaseCapture(); 41 | _host.EndDragItem(); 42 | }); 43 | Finish(); 44 | } 45 | 46 | public override void OnLeftButtonDown() 47 | { 48 | if (_host.HasSelected()) 49 | { 50 | // 只允许拖动文件 51 | if (_host.DragFileOnly) 52 | { 53 | // 判断选中项是否包含文件夹 54 | if (!FolderSelected()) Invoke("开始拖动", null); 55 | } 56 | else Invoke("开始拖动", null); 57 | } 58 | } 59 | 60 | private bool FolderSelected() 61 | { 62 | foreach (var item in _host.SelectedItemList) 63 | if (item.IsFolder) return true; 64 | return false; 65 | } 66 | } 67 | } -------------------------------------------------------------------------------- /XLib.WPFControl/ToolBar.xaml: -------------------------------------------------------------------------------- 1 |  9 | 10 | -------------------------------------------------------------------------------- /XLib.WPFControl/ToolSplitBar.xaml: -------------------------------------------------------------------------------- 1 |  9 | 10 | -------------------------------------------------------------------------------- /XLib.WPFControl/ToolSplitBar.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using System.Windows.Controls; 3 | 4 | namespace XLib.WPFControl 5 | { 6 | public partial class ToolSplitBar : UserControl 7 | { 8 | public Thickness CustomMargin { get; set; } = new Thickness(5); 9 | 10 | public ToolSplitBar() => InitializeComponent(); 11 | 12 | private void UserControl_Loaded(object sender, RoutedEventArgs e) => MainGrid.Margin = CustomMargin; 13 | } 14 | } -------------------------------------------------------------------------------- /XLib.WPFControl/TreeItemView.xaml: -------------------------------------------------------------------------------- 1 |  9 | 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 | -------------------------------------------------------------------------------- /XLib.WPFControl/TreeView.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 | 39 | 40 | -------------------------------------------------------------------------------- /XLib.WPFControl/XLib.WPFControl.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0-windows 5 | enable 6 | true 7 | enable 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /XLib.WPFStyle/ConvertSet.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using System.Windows; 3 | using System.Windows.Data; 4 | 5 | namespace XLib.WPFStyle 6 | { 7 | public class TagToTrackMargin : IValueConverter 8 | { 9 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 10 | { 11 | string tagString = (string)value; 12 | if (tagString == null) return new Thickness(); 13 | 14 | Thickness thickness = (Thickness)new ThicknessConverter().ConvertFromString(tagString); 15 | return thickness; 16 | } 17 | 18 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => null; 19 | } 20 | } -------------------------------------------------------------------------------- /XLib.WPFStyle/ConverterSet.xaml: -------------------------------------------------------------------------------- 1 |  4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /XLib.WPFStyle/Image/Close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XLib.WPFStyle/Image/Close.png -------------------------------------------------------------------------------- /XLib.WPFStyle/Image/Close2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XLib.WPFStyle/Image/Close2.png -------------------------------------------------------------------------------- /XLib.WPFStyle/Image/Expand.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XLib.WPFStyle/Image/Expand.png -------------------------------------------------------------------------------- /XLib.WPFStyle/Image/Furl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XLib.WPFStyle/Image/Furl.png -------------------------------------------------------------------------------- /XLib.WPFStyle/Image/Max.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XLib.WPFStyle/Image/Max.png -------------------------------------------------------------------------------- /XLib.WPFStyle/Image/Min.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XLib.WPFStyle/Image/Min.png -------------------------------------------------------------------------------- /XLib.WPFStyle/Image/Normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XLib.WPFStyle/Image/Normal.png -------------------------------------------------------------------------------- /XLib.WPFStyle/Image/XNode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XLib.WPFStyle/Image/XNode.png -------------------------------------------------------------------------------- /XLib.WPFStyle/ToolTipStyle.xaml: -------------------------------------------------------------------------------- 1 |  3 | 4 | 23 | 24 | -------------------------------------------------------------------------------- /XLib.WPFStyle/XLib.WPFStyle.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0-windows 5 | enable 6 | true 7 | enable 8 | 9 | 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 | -------------------------------------------------------------------------------- /XNode-MainWindow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode-MainWindow.png -------------------------------------------------------------------------------- /XNode/App.xaml: -------------------------------------------------------------------------------- 1 |  6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /XNode/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using XNode.AppTool; 3 | using XNode.SubSystem.WindowSystem; 4 | 5 | namespace XNode 6 | { 7 | public partial class App : Application 8 | { 9 | #region 构造方法 10 | 11 | public App() 12 | { 13 | Startup += App_Startup; 14 | } 15 | 16 | #endregion 17 | 18 | #region 应用程序事件 19 | 20 | private void App_Startup(object sender, StartupEventArgs e) 21 | { 22 | // 启动异常 23 | bool startException = false; 24 | try 25 | { 26 | Init(); 27 | } 28 | catch (Exception ex) 29 | { 30 | startException = true; 31 | WM.ShowAppError("软件启动异常:" + ex.Message); 32 | } 33 | finally 34 | { 35 | if (startException) Shutdown(); 36 | } 37 | } 38 | 39 | #endregion 40 | 41 | #region 私有方法 42 | 43 | /// 44 | /// 初始化应用程序 45 | /// 46 | private void Init() 47 | { 48 | // 初始化应用程序代理 49 | AppDelegate.Init(); 50 | 51 | // 初始化系统数据 52 | SystemDataDelegate.Instance.Init(); 53 | // 启动系统服务 54 | SystemServiceDelegate.Instance.Start(); 55 | // 初始化系统工具 56 | SystemToolDelegate.Instance.Init(); 57 | } 58 | 59 | #endregion 60 | } 61 | } -------------------------------------------------------------------------------- /XNode/AppTool/AppDelegate.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | 3 | namespace XNode.AppTool 4 | { 5 | /// 6 | /// 应用程序代理 7 | /// 8 | public class AppDelegate 9 | { 10 | public static App Main { get; set; } 11 | 12 | public static string AppTitle => "XNode 1.0.3 Alpha"; 13 | 14 | public static void Init() 15 | { 16 | if (Application.Current is App app) Main = app; 17 | } 18 | 19 | public static void Invoke(Action action) 20 | { 21 | Main.Dispatcher.Invoke(action); 22 | } 23 | 24 | public static void BeginInvoke(Action action) 25 | { 26 | Main.Dispatcher.BeginInvoke(action); 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /XNode/AppTool/ClassExtension.cs: -------------------------------------------------------------------------------- 1 | using XLib.Node; 2 | using XNode.SubSystem.NodeEditSystem.Define; 3 | 4 | namespace XNode.AppTool 5 | { 6 | public static class ClassExtension 7 | { 8 | /// 9 | /// 获取引脚路径 10 | /// 11 | public static PinPath GetPinPath(this PinBase pin) 12 | { 13 | return new PinPath 14 | { 15 | NodeVersion = pin.OwnerGroup.OwnerNode.Version, 16 | NodeID = pin.OwnerGroup.OwnerNode.ID, 17 | GroupIndex = pin.OwnerGroup.Index, 18 | PinIndex = pin.OwnerGroup.GetPinIndex(pin) 19 | }; 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /XNode/AppTool/ProjectDelegate.cs: -------------------------------------------------------------------------------- 1 | namespace XNode.AppTool 2 | { 3 | class ProjectDelegate 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /XNode/AppTool/SystemDelegate.cs: -------------------------------------------------------------------------------- 1 | using XLib.Animate; 2 | using XLib.Base.AppFrame; 3 | using XNode.SubSystem.CacheSystem; 4 | using XNode.SubSystem.ControlSystem; 5 | using XNode.SubSystem.EventSystem; 6 | using XNode.SubSystem.NodeLibSystem; 7 | using XNode.SubSystem.OptionSystem; 8 | using XNode.SubSystem.ResourceSystem; 9 | using XNode.SubSystem.TimerSystem; 10 | 11 | namespace XNode.AppTool 12 | { 13 | /// 14 | /// 系统数据代理 15 | /// 16 | public class SystemDataDelegate : ManagerDelegate 17 | { 18 | private SystemDataDelegate() 19 | { 20 | // 选项、缓存 21 | ManagerList.Add(OptionManager.Instance); 22 | ManagerList.Add(CacheManager.Instance); 23 | // 资源、节点库 24 | ManagerList.Add(ResourceManager.Instance); 25 | ManagerList.Add(NodeLibManager.Instance); 26 | } 27 | public static SystemDataDelegate Instance { get; } = new SystemDataDelegate(); 28 | } 29 | 30 | /// 31 | /// 系统服务代理 32 | /// 33 | public class SystemServiceDelegate : ServiceDelegate 34 | { 35 | private SystemServiceDelegate() 36 | { 37 | // 时间引擎 38 | ServiceList.Add(TimeEngine.Instance); 39 | // 应用定时器 40 | ServiceList.Add(AppTimer.Instance); 41 | // 控制引擎 42 | ServiceList.Add(ControlEngine.Instance); 43 | // 动画引擎 44 | ServiceList.Add(AnimationEngine.Instance); 45 | } 46 | public static SystemServiceDelegate Instance { get; } = new SystemServiceDelegate(); 47 | } 48 | 49 | /// 50 | /// 系统工具代理 51 | /// 52 | public class SystemToolDelegate : ManagerDelegate 53 | { 54 | private SystemToolDelegate() 55 | { 56 | // 事件管理器 57 | ManagerList.Add(EM.Instance); 58 | } 59 | public static SystemToolDelegate Instance { get; } = new SystemToolDelegate(); 60 | } 61 | } -------------------------------------------------------------------------------- /XNode/Assets/Cursor/CanNotMove.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Cursor/CanNotMove.cur -------------------------------------------------------------------------------- /XNode/Assets/Cursor/Cross.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Cursor/Cross.cur -------------------------------------------------------------------------------- /XNode/Assets/Cursor/Disable.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Cursor/Disable.cur -------------------------------------------------------------------------------- /XNode/Assets/Cursor/DragObject.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Cursor/DragObject.cur -------------------------------------------------------------------------------- /XNode/Assets/Cursor/Draw.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Cursor/Draw.cur -------------------------------------------------------------------------------- /XNode/Assets/Cursor/Insert.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Cursor/Insert.cur -------------------------------------------------------------------------------- /XNode/Assets/Cursor/Move.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Cursor/Move.cur -------------------------------------------------------------------------------- /XNode/Assets/Cursor/MoveBottom.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Cursor/MoveBottom.cur -------------------------------------------------------------------------------- /XNode/Assets/Cursor/MoveSelected.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Cursor/MoveSelected.cur -------------------------------------------------------------------------------- /XNode/Assets/Cursor/MoveTop.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Cursor/MoveTop.cur -------------------------------------------------------------------------------- /XNode/Assets/Cursor/MoveX.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Cursor/MoveX.cur -------------------------------------------------------------------------------- /XNode/Assets/Cursor/MoveY.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Cursor/MoveY.cur -------------------------------------------------------------------------------- /XNode/Assets/Cursor/OnOff.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Cursor/OnOff.cur -------------------------------------------------------------------------------- /XNode/Assets/Cursor/ResizeDownUp.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Cursor/ResizeDownUp.cur -------------------------------------------------------------------------------- /XNode/Assets/Cursor/ResizeUpDown.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Cursor/ResizeUpDown.cur -------------------------------------------------------------------------------- /XNode/Assets/Cursor/Select.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Cursor/Select.cur -------------------------------------------------------------------------------- /XNode/Assets/Font/simsun.ttc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Font/simsun.ttc -------------------------------------------------------------------------------- /XNode/Assets/Icon15/Add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Icon15/Add.png -------------------------------------------------------------------------------- /XNode/Assets/Icon15/Browse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Icon15/Browse.png -------------------------------------------------------------------------------- /XNode/Assets/Icon15/Clear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Icon15/Clear.png -------------------------------------------------------------------------------- /XNode/Assets/Icon15/ControlBoard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Icon15/ControlBoard.png -------------------------------------------------------------------------------- /XNode/Assets/Icon15/Copy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Icon15/Copy.png -------------------------------------------------------------------------------- /XNode/Assets/Icon15/Delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Icon15/Delete.png -------------------------------------------------------------------------------- /XNode/Assets/Icon15/EmptyFolder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Icon15/EmptyFolder.png -------------------------------------------------------------------------------- /XNode/Assets/Icon15/File.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Icon15/File.png -------------------------------------------------------------------------------- /XNode/Assets/Icon15/Folder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Icon15/Folder.png -------------------------------------------------------------------------------- /XNode/Assets/Icon15/Lib.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Icon15/Lib.png -------------------------------------------------------------------------------- /XNode/Assets/Icon15/Node.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Icon15/Node.png -------------------------------------------------------------------------------- /XNode/Assets/Icon15/NodePreset.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Icon15/NodePreset.png -------------------------------------------------------------------------------- /XNode/Assets/Icon15/Remove.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Icon15/Remove.png -------------------------------------------------------------------------------- /XNode/Assets/Icon15/Rename.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Icon15/Rename.png -------------------------------------------------------------------------------- /XNode/Assets/Icon16/AlignCenter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Icon16/AlignCenter.png -------------------------------------------------------------------------------- /XNode/Assets/Icon16/AlignLeft.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Icon16/AlignLeft.png -------------------------------------------------------------------------------- /XNode/Assets/Icon16/AlignRight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Icon16/AlignRight.png -------------------------------------------------------------------------------- /XNode/Assets/Icon16/ClearConsole.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Icon16/ClearConsole.png -------------------------------------------------------------------------------- /XNode/Assets/Icon16/CloseFile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Icon16/CloseFile.png -------------------------------------------------------------------------------- /XNode/Assets/Icon16/Console.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Icon16/Console.png -------------------------------------------------------------------------------- /XNode/Assets/Icon16/ExpandAll.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Icon16/ExpandAll.png -------------------------------------------------------------------------------- /XNode/Assets/Icon16/FurlAll.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Icon16/FurlAll.png -------------------------------------------------------------------------------- /XNode/Assets/Icon16/NewFile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Icon16/NewFile.png -------------------------------------------------------------------------------- /XNode/Assets/Icon16/Node/CPU.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Icon16/Node/CPU.png -------------------------------------------------------------------------------- /XNode/Assets/Icon16/Node/Calculator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Icon16/Node/Calculator.png -------------------------------------------------------------------------------- /XNode/Assets/Icon16/Node/Chip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Icon16/Node/Chip.png -------------------------------------------------------------------------------- /XNode/Assets/Icon16/Node/Delay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Icon16/Node/Delay.png -------------------------------------------------------------------------------- /XNode/Assets/Icon16/Node/Fan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Icon16/Node/Fan.png -------------------------------------------------------------------------------- /XNode/Assets/Icon16/Node/Flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Icon16/Node/Flow.png -------------------------------------------------------------------------------- /XNode/Assets/Icon16/Node/FrameDriver.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Icon16/Node/FrameDriver.png -------------------------------------------------------------------------------- /XNode/Assets/Icon16/Node/Function.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Icon16/Node/Function.png -------------------------------------------------------------------------------- /XNode/Assets/Icon16/Node/Key.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Icon16/Node/Key.png -------------------------------------------------------------------------------- /XNode/Assets/Icon16/Node/Loop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Icon16/Node/Loop.png -------------------------------------------------------------------------------- /XNode/Assets/Icon16/Node/Message.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Icon16/Node/Message.png -------------------------------------------------------------------------------- /XNode/Assets/Icon16/Node/Midi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Icon16/Node/Midi.png -------------------------------------------------------------------------------- /XNode/Assets/Icon16/Node/Net.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Icon16/Node/Net.png -------------------------------------------------------------------------------- /XNode/Assets/Icon16/Node/Node.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Icon16/Node/Node.png -------------------------------------------------------------------------------- /XNode/Assets/Icon16/Node/Pause.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Icon16/Node/Pause.png -------------------------------------------------------------------------------- /XNode/Assets/Icon16/Node/Spectrum.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Icon16/Node/Spectrum.png -------------------------------------------------------------------------------- /XNode/Assets/Icon16/Node/Timer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Icon16/Node/Timer.png -------------------------------------------------------------------------------- /XNode/Assets/Icon16/Node/Variate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Icon16/Node/Variate.png -------------------------------------------------------------------------------- /XNode/Assets/Icon16/Node/Volume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Icon16/Node/Volume.png -------------------------------------------------------------------------------- /XNode/Assets/Icon16/OpenFile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Icon16/OpenFile.png -------------------------------------------------------------------------------- /XNode/Assets/Icon16/Redo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Icon16/Redo.png -------------------------------------------------------------------------------- /XNode/Assets/Icon16/Rename.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Icon16/Rename.png -------------------------------------------------------------------------------- /XNode/Assets/Icon16/Revert.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Icon16/Revert.png -------------------------------------------------------------------------------- /XNode/Assets/Icon16/Save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Icon16/Save.png -------------------------------------------------------------------------------- /XNode/Assets/Icon16/SaveAll.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Icon16/SaveAll.png -------------------------------------------------------------------------------- /XNode/Assets/Icon16/SaveAs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Icon16/SaveAs.png -------------------------------------------------------------------------------- /XNode/Assets/Icon16/Undo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/Assets/Icon16/Undo.png -------------------------------------------------------------------------------- /XNode/CoreEditer.xaml: -------------------------------------------------------------------------------- 1 |  12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /XNode/CoreEditer.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using System.Windows.Controls; 3 | using XLib.Node; 4 | using XNode.SubSystem.NodeEditSystem.Define; 5 | using XNode.SubSystem.ProjectSystem; 6 | 7 | namespace XNode 8 | { 9 | public partial class CoreEditer : UserControl 10 | { 11 | #region 属性 12 | 13 | /// 节点列表 14 | public List NodeList => Panel_NodeEditer.NodeList; 15 | 16 | #endregion 17 | 18 | #region 构造方法 19 | 20 | public CoreEditer() 21 | { 22 | InitializeComponent(); 23 | Loaded += CoreEditer_Loaded; 24 | } 25 | 26 | #endregion 27 | 28 | #region 公开方法 29 | 30 | /// 31 | /// 重置编辑器 32 | /// 33 | public void ResetEditer() => Panel_NodeEditer.Reset(); 34 | 35 | /// 36 | /// 加载节点 37 | /// 38 | public void LoadNode(NodeBase node) => Panel_NodeEditer.LoadNode(node); 39 | 40 | /// 41 | /// 查找引脚 42 | /// 43 | public PinBase? FindPin(PinPath path) => Panel_NodeEditer.FindPin(path); 44 | 45 | #endregion 46 | 47 | #region 控件事件 48 | 49 | private void CoreEditer_Loaded(object sender, RoutedEventArgs e) 50 | { 51 | Init(); 52 | ProjectManager.Instance.NewProject(); 53 | ProjectManager.Instance.Saved = true; 54 | } 55 | 56 | #endregion 57 | 58 | #region 私有方法 59 | 60 | /// 61 | /// 初始化核心编辑器 62 | /// 63 | private void Init() 64 | { 65 | // 初始化编辑器面板 66 | Panel_NodeEditer.Init(); 67 | // 初始化节点库面板 68 | Panel_NodeLib.Init(); 69 | } 70 | 71 | #endregion 72 | } 73 | } -------------------------------------------------------------------------------- /XNode/MainWindow.xaml: -------------------------------------------------------------------------------- 1 |  13 | 14 | -------------------------------------------------------------------------------- /XNode/SubSystem/ArchiveSystem/Define/Data_1_0/ConnectLineData.cs: -------------------------------------------------------------------------------- 1 | namespace XNode.SubSystem.ArchiveSystem.Define.Data_1_0 2 | { 3 | /// 4 | /// 连接线数据 5 | /// 6 | public class ConnectLineData 7 | { 8 | public string Start { get; set; } = ""; 9 | 10 | public string End { get; set; } = ""; 11 | 12 | public override string ToString() => $"{Start}-{End}"; 13 | } 14 | } -------------------------------------------------------------------------------- /XNode/SubSystem/ArchiveSystem/Define/Data_1_0/Data_1_0.cs: -------------------------------------------------------------------------------- 1 | namespace XNode.SubSystem.ArchiveSystem.Define.Data_1_0 2 | { 3 | /// 4 | /// 存档数据 5 | /// 6 | public class Data_1_0 7 | { 8 | /// 节点列表 9 | public List NodeList { get; set; } = new List(); 10 | 11 | /// 连接线列表 12 | public List ConnectLineList { get; set; } = new List(); 13 | } 14 | } -------------------------------------------------------------------------------- /XNode/SubSystem/ArchiveSystem/Define/Data_1_0/NodeBaseData.cs: -------------------------------------------------------------------------------- 1 | namespace XNode.SubSystem.ArchiveSystem.Define.Data_1_0 2 | { 3 | public class NodeBaseData 4 | { 5 | public NodeBaseData() { } 6 | 7 | public NodeBaseData(string data) 8 | { 9 | string[] array = data.Split('/'); 10 | NodeLibName = array[0]; 11 | TypeString = array[1]; 12 | Version = array[2]; 13 | ID = int.Parse(array[3]); 14 | Point = array[4]; 15 | } 16 | 17 | /// 节点库名称 18 | public string NodeLibName { get; set; } = "Inner"; 19 | 20 | /// 类型字符串 21 | public string TypeString { get; set; } = ""; 22 | 23 | /// 节点版本 24 | public string Version { get; set; } = "1.0"; 25 | 26 | /// 编号 27 | public int ID { get; set; } = -1; 28 | 29 | /// 坐标 30 | public string Point { get; set; } = "0,0"; 31 | 32 | public override string ToString() => $"{NodeLibName}/{TypeString}/{Version}/{ID}/{Point}"; 33 | } 34 | } -------------------------------------------------------------------------------- /XNode/SubSystem/ArchiveSystem/Define/Data_1_0/NodeData.cs: -------------------------------------------------------------------------------- 1 | namespace XNode.SubSystem.ArchiveSystem.Define.Data_1_0 2 | { 3 | /// 4 | /// 节点数据 5 | /// 6 | public class NodeData 7 | { 8 | /// 基本数据 9 | public string BaseData { get; set; } = ""; 10 | 11 | /// 参数表 12 | public Dictionary ParaDict { get; set; } = new Dictionary(); 13 | 14 | /// 属性表 15 | public Dictionary PropertyDict { get; set; } = new Dictionary(); 16 | } 17 | } -------------------------------------------------------------------------------- /XNode/SubSystem/CacheSystem/CacheData.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | 3 | namespace XNode.SubSystem.CacheSystem 4 | { 5 | public class MainWindowCache 6 | { 7 | public WindowState State { get; set; } = WindowState.Normal; 8 | public int Width { get; set; } = 1280; 9 | public int Height { get; set; } = 720; 10 | } 11 | 12 | /// 13 | /// 节点库缓存 14 | /// 15 | public class NodeLibCache 16 | { 17 | public List ExpandedFolderList { get; set; } = new List(); 18 | 19 | /// 20 | /// 判断指定的文件夹是否处于展开状态 21 | /// 22 | public bool IsExpanded(string folderPath) => ExpandedFolderList.Contains(folderPath); 23 | 24 | /// 25 | /// 折叠指定文件夹 26 | /// 27 | public void Fold(string folderPath) 28 | { 29 | if (ExpandedFolderList.Contains(folderPath)) ExpandedFolderList.Remove(folderPath); 30 | CacheManager.Instance.UpdateCache(); 31 | } 32 | 33 | /// 34 | /// 展开指定文件夹 35 | /// 36 | public void Expand(string folderPath) 37 | { 38 | if (!ExpandedFolderList.Contains(folderPath)) ExpandedFolderList.Add(folderPath); 39 | CacheManager.Instance.UpdateCache(); 40 | } 41 | } 42 | 43 | public class CacheData 44 | { 45 | public MainWindowCache MainWindow { get; set; } = new MainWindowCache(); 46 | 47 | public NodeLibCache NodeLib { get; set; } = new NodeLibCache(); 48 | } 49 | } -------------------------------------------------------------------------------- /XNode/SubSystem/CacheSystem/CacheManager.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System.IO; 3 | using XLib.Base; 4 | using XNode.SubSystem.OptionSystem; 5 | 6 | namespace XNode.SubSystem.CacheSystem 7 | { 8 | /// 9 | /// 缓存管理器 10 | /// 11 | public class CacheManager : IManager 12 | { 13 | #region 单例 14 | 15 | private CacheManager() { } 16 | public static CacheManager Instance { get; } = new CacheManager(); 17 | 18 | #endregion 19 | 20 | #region 属性 21 | 22 | public string Name { get; set; } = "缓存管理器"; 23 | 24 | /// 缓存数据 25 | public CacheData Cache { get; set; } = new CacheData(); 26 | 27 | #endregion 28 | 29 | #region “IManager”方法 30 | 31 | public void Init() 32 | { 33 | // 不存在缓存,则新建缓存 34 | if (!File.Exists($"{OptionManager.Instance.CachePath}\\{_cacheFileName}")) SaveCacheFile(); 35 | // 加载缓存文件 36 | LoadCacheFile(); 37 | } 38 | 39 | public void Reset() { } 40 | 41 | public void Clear() { } 42 | 43 | #endregion 44 | 45 | #region 公开方法 46 | 47 | /// 48 | /// 更新缓存 49 | /// 50 | public void UpdateCache() => SaveCacheFile(); 51 | 52 | #endregion 53 | 54 | #region 私有方法 55 | 56 | /// 57 | /// 保存缓存文件 58 | /// 59 | private void SaveCacheFile() 60 | { 61 | string filePath = $"{OptionManager.Instance.CachePath}\\{_cacheFileName}"; 62 | File.WriteAllText(filePath, JsonConvert.SerializeObject(Cache, Formatting.Indented)); 63 | } 64 | 65 | /// 66 | /// 加载缓存文件 67 | /// 68 | private void LoadCacheFile() 69 | { 70 | string jsonData = File.ReadAllText($"{OptionManager.Instance.CachePath}\\{_cacheFileName}"); 71 | CacheData? cache = JsonConvert.DeserializeObject(jsonData); 72 | if (cache != null) Cache = cache; 73 | } 74 | 75 | #endregion 76 | 77 | #region 字段 78 | 79 | /// 缓存文件名 80 | private readonly string _cacheFileName = "Cache.json"; 81 | 82 | #endregion 83 | } 84 | } -------------------------------------------------------------------------------- /XNode/SubSystem/ControlSystem/ControlEngine.cs: -------------------------------------------------------------------------------- 1 | using XLib.Base.AppFrame; 2 | using XLib.Base.Drive; 3 | using XNode.SubSystem.TimerSystem; 4 | 5 | namespace XNode.SubSystem.ControlSystem 6 | { 7 | public class ControlEngine : ServiceBase, ITimerHandler 8 | { 9 | #region 单例 10 | 11 | private ControlEngine() { } 12 | public static ControlEngine Instance { get; } = new ControlEngine(); 13 | 14 | #endregion 15 | 16 | #region 生命周期 17 | 18 | public override void Start() => TimeEngine.Instance.AddTimerHandler(this); 19 | 20 | public override void Stop() => TimeEngine.Instance.RemoveHandler(this); 21 | 22 | #endregion 23 | 24 | #region 接口实现 25 | 26 | public void Tick() 27 | { 28 | foreach (var frameDriver in _frameDriverList) frameDriver.Update(); 29 | } 30 | 31 | #endregion 32 | 33 | #region 公开方法 34 | 35 | /// 36 | /// 连接驱动器 37 | /// 38 | public void Connect(IFrameDriver frameDriver) 39 | { 40 | if (_frameDriverList.Contains(frameDriver)) return; 41 | _frameDriverList = new List(_frameDriverList) { frameDriver }; 42 | } 43 | 44 | /// 45 | /// 断开驱动器 46 | /// 47 | public void Disconnect(IFrameDriver frameDriver) 48 | { 49 | List newList = new List(_frameDriverList); 50 | newList.Remove(frameDriver); 51 | _frameDriverList = newList; 52 | } 53 | 54 | #endregion 55 | 56 | #region 字段 57 | 58 | /// 帧驱动器列表 59 | private List _frameDriverList = new List(); 60 | 61 | #endregion 62 | } 63 | } -------------------------------------------------------------------------------- /XNode/SubSystem/EventSystem/EM.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using XLib.Base; 3 | 4 | namespace XNode.SubSystem.EventSystem 5 | { 6 | public class EM : EM 7 | { 8 | #region 单例 9 | 10 | private EM() { } 11 | public static EM Instance { get; } = new EM(); 12 | 13 | #endregion 14 | 15 | #region 引发事件 16 | 17 | public void Invoke(EventType eventType) 18 | { 19 | InnerInvoke(eventType); 20 | } 21 | 22 | public void Invoke(EventType eventType, T1 value1) 23 | { 24 | InnerInvoke(eventType, value1); 25 | } 26 | 27 | public void Invoke(EventType eventType, T1 value1, T2 value2) 28 | { 29 | InnerInvoke(eventType, value1, value2); 30 | } 31 | 32 | public void Invoke(EventType eventType, T1 value1, T2 value2, T3 value3) 33 | { 34 | InnerInvoke(eventType, value1, value2, value3); 35 | } 36 | 37 | #endregion 38 | 39 | #region 引发事件 40 | 41 | public void BeginInvoke(EventType eventType) 42 | { 43 | Application.Current.Dispatcher.BeginInvoke(() => InnerInvoke(eventType)); 44 | } 45 | 46 | public void BeginInvoke(EventType eventType, T1 value1) 47 | { 48 | Application.Current.Dispatcher.BeginInvoke(() => InnerInvoke(eventType, value1)); 49 | } 50 | 51 | public void BeginInvoke(EventType eventType, T1 value1, T2 value2) 52 | { 53 | Application.Current.Dispatcher.BeginInvoke(() => InnerInvoke(eventType, value1, value2)); 54 | } 55 | 56 | public void BeginInvoke(EventType eventType, T1 value1, T2 value2, T3 value3) 57 | { 58 | Application.Current.Dispatcher.BeginInvoke(() => InnerInvoke(eventType, value1, value2, value3)); 59 | } 60 | 61 | #endregion 62 | } 63 | } -------------------------------------------------------------------------------- /XNode/SubSystem/EventSystem/EventType.cs: -------------------------------------------------------------------------------- 1 | namespace XNode.SubSystem.EventSystem 2 | { 3 | public enum EventType 4 | { 5 | /// 按键按下 6 | KeyDown, 7 | /// 按键松开 8 | KeyUp, 9 | 10 | /// 项目已变更 11 | Project_Changed, 12 | 13 | /// 项目已加载 14 | Project_Loaded, 15 | } 16 | } -------------------------------------------------------------------------------- /XNode/SubSystem/NodeEditSystem/Control/ActionPinGroupView.xaml: -------------------------------------------------------------------------------- 1 |  9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /XNode/SubSystem/NodeEditSystem/Control/ActionPinGroupView.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using System.Windows.Controls; 3 | using System.Windows.Input; 4 | using XLib.Node; 5 | using XNode.SubSystem.ResourceSystem; 6 | 7 | namespace XNode.SubSystem.NodeEditSystem.Control 8 | { 9 | public partial class ActionPinGroupView : PinGroupViewBase 10 | { 11 | public ActionPinGroupView() => InitializeComponent(); 12 | 13 | public ActionPinGroup? Instance { get; set; } = null; 14 | 15 | public override void Init() 16 | { 17 | if (Instance == null) return; 18 | Title_Pin.Text = Instance.ActionName; 19 | Instance.ActionNameChanged = (name) => Title_Pin.Text = name; 20 | Icon_Pin.Source = PinIconManager.Instance.ExecutePin_Null; 21 | 22 | PinArea.MouseEnter += PinArea_MouseEnter; 23 | PinArea.MouseLeave += PinArea_MouseLeave; 24 | } 25 | 26 | public override Grid GetPinArea() 27 | { 28 | if (HoveredPin != null) return PinArea; 29 | throw new Exception("无命中引脚"); 30 | } 31 | 32 | private void PinArea_MouseEnter(object sender, MouseEventArgs e) 33 | { 34 | HoveredPin = Instance.OutputPin; 35 | } 36 | 37 | private void PinArea_MouseLeave(object sender, MouseEventArgs e) 38 | { 39 | HoveredPin = null; 40 | } 41 | 42 | public override Point GetPinOffset(NodeView card, int pinIndex) => PinArea.TranslatePoint(new Point(14, 8), card); 43 | 44 | public override void UpdatePinIcon() 45 | { 46 | if (Instance.OutputPin.TargetList.Count == 0) Icon_Pin.Source = PinIconManager.Instance.ExecutePin_Null; 47 | else Icon_Pin.Source = PinIconManager.Instance.ExecutePin; 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /XNode/SubSystem/NodeEditSystem/Control/ControlPinGroupView.xaml: -------------------------------------------------------------------------------- 1 |  9 | 10 | 11 | -------------------------------------------------------------------------------- /XNode/SubSystem/NodeEditSystem/Control/ControlPinGroupView.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using XLib.Node; 3 | 4 | namespace XNode.SubSystem.NodeEditSystem.Control 5 | { 6 | /// 7 | /// 控件引脚组视图 8 | /// 9 | public partial class ControlPinGroupView : PinGroupViewBase 10 | { 11 | public ControlPinGroupView() => InitializeComponent(); 12 | 13 | public ControlPinGroup? Instance { get; set; } = null; 14 | 15 | public override void Init() 16 | { 17 | if (Instance == null) return; 18 | ControlBox.Children.Add((UIElement)Instance.ControlInstance); 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /XNode/SubSystem/NodeEditSystem/Control/DataPinGroupView.xaml: -------------------------------------------------------------------------------- 1 |  9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /XNode/SubSystem/NodeEditSystem/Control/ExecutePinGroupView.xaml: -------------------------------------------------------------------------------- 1 |  9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /XNode/SubSystem/NodeEditSystem/Control/ExecutePinGroupView.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using System.Windows.Controls; 3 | using System.Windows.Input; 4 | using XLib.Node; 5 | using XNode.SubSystem.ResourceSystem; 6 | 7 | namespace XNode.SubSystem.NodeEditSystem.Control 8 | { 9 | public partial class ExecutePinGroupView : PinGroupViewBase 10 | { 11 | public ExecutePinGroupView() => InitializeComponent(); 12 | 13 | public ExecutePinGroup? Instance { get; set; } = null; 14 | 15 | public override void Init() 16 | { 17 | if (Instance == null) return; 18 | Icon_LeftPin.Source = PinIconManager.Instance.ExecutePin_Null; 19 | Block_ExecuteDesc.Text = Instance.ExecuteDesc; 20 | Icon_RightPin.Source = PinIconManager.Instance.ExecutePin_Null; 21 | 22 | LeftPinArea.MouseEnter += LeftPinArea_MouseEnter; 23 | RightPinArea.MouseEnter += RightPinArea_MouseEnter; 24 | LeftPinArea.MouseLeave += PinArea_MouseLeave; 25 | RightPinArea.MouseLeave += PinArea_MouseLeave; 26 | } 27 | 28 | public override Grid GetPinArea() 29 | { 30 | if (HoveredPin == Instance.InputPin) return LeftPinArea; 31 | if (HoveredPin == Instance.OutputPin) return RightPinArea; 32 | throw new Exception("无命中引脚"); 33 | } 34 | 35 | private void LeftPinArea_MouseEnter(object sender, MouseEventArgs e) 36 | { 37 | HoveredPin = Instance.InputPin; 38 | } 39 | 40 | private void RightPinArea_MouseEnter(object sender, MouseEventArgs e) 41 | { 42 | HoveredPin = Instance.OutputPin; 43 | } 44 | 45 | private void PinArea_MouseLeave(object sender, MouseEventArgs e) 46 | { 47 | HoveredPin = null; 48 | } 49 | 50 | public override Point GetPinOffset(NodeView card, int pinIndex) 51 | { 52 | if (pinIndex == 0) return LeftPinArea.TranslatePoint(new Point(3, 8), card); 53 | return RightPinArea.TranslatePoint(new Point(14, 8), card); 54 | } 55 | 56 | public override void UpdatePinIcon() 57 | { 58 | if (Instance.InputPin.SourceList.Count == 0) Icon_LeftPin.Source = PinIconManager.Instance.ExecutePin_Null; 59 | else Icon_LeftPin.Source = PinIconManager.Instance.ExecutePin; 60 | if (Instance.OutputPin.TargetList.Count == 0) Icon_RightPin.Source = PinIconManager.Instance.ExecutePin_Null; 61 | else Icon_RightPin.Source = PinIconManager.Instance.ExecutePin; 62 | } 63 | } 64 | } -------------------------------------------------------------------------------- /XNode/SubSystem/NodeEditSystem/Control/HoverToolBar.xaml: -------------------------------------------------------------------------------- 1 |  8 | 9 | 10 | 15 | 20 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /XNode/SubSystem/NodeEditSystem/Control/HoverToolBar.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using System.Windows.Controls; 3 | 4 | namespace XNode.SubSystem.NodeEditSystem.Control 5 | { 6 | public partial class HoverToolBar : UserControl 7 | { 8 | public HoverToolBar() => InitializeComponent(); 9 | 10 | public event Action ToolClick; 11 | 12 | public void Init() 13 | { 14 | foreach (var item in Stack_ToolBar.Children) 15 | if (item is Button button) button.Click += Tool_Click; 16 | } 17 | 18 | private void Tool_Click(object sender, RoutedEventArgs e) => ToolClick?.Invoke(((Button)sender).Name); 19 | } 20 | } -------------------------------------------------------------------------------- /XNode/SubSystem/NodeEditSystem/Control/Image/BreakPin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/SubSystem/NodeEditSystem/Control/Image/BreakPin.png -------------------------------------------------------------------------------- /XNode/SubSystem/NodeEditSystem/Control/Image/Delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/SubSystem/NodeEditSystem/Control/Image/Delete.png -------------------------------------------------------------------------------- /XNode/SubSystem/NodeEditSystem/Control/Image/Light_Black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/SubSystem/NodeEditSystem/Control/Image/Light_Black.png -------------------------------------------------------------------------------- /XNode/SubSystem/NodeEditSystem/Control/Image/Light_Green.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/SubSystem/NodeEditSystem/Control/Image/Light_Green.png -------------------------------------------------------------------------------- /XNode/SubSystem/NodeEditSystem/Control/Image/Light_Red.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/SubSystem/NodeEditSystem/Control/Image/Light_Red.png -------------------------------------------------------------------------------- /XNode/SubSystem/NodeEditSystem/Control/Image/Start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/SubSystem/NodeEditSystem/Control/Image/Start.png -------------------------------------------------------------------------------- /XNode/SubSystem/NodeEditSystem/Control/Image/Stop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WPFDevelopersOrg/XNode/2a50feb6739722bf77c9017427cf0ff55493c623/XNode/SubSystem/NodeEditSystem/Control/Image/Stop.png -------------------------------------------------------------------------------- /XNode/SubSystem/NodeEditSystem/Control/NodeMap.xaml: -------------------------------------------------------------------------------- 1 |  9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /XNode/SubSystem/NodeEditSystem/Control/NodeMap.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | 16 | namespace XNode.SubSystem.NodeEditSystem.Control 17 | { 18 | /// 19 | /// NodeMap.xaml 的交互逻辑 20 | /// 21 | public partial class NodeMap : UserControl 22 | { 23 | public NodeMap() 24 | { 25 | InitializeComponent(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /XNode/SubSystem/NodeEditSystem/Control/NodePropertyPanel.xaml: -------------------------------------------------------------------------------- 1 |  9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 32 | 33 | -------------------------------------------------------------------------------- /XNode/SubSystem/NodeEditSystem/Control/PinGroupViewBase.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using System.Windows.Controls; 3 | using System.Windows.Input; 4 | using XLib.Node; 5 | 6 | namespace XNode.SubSystem.NodeEditSystem.Control 7 | { 8 | /// 9 | /// 引脚组视图基类 10 | /// 11 | public class PinGroupViewBase : UserControl 12 | { 13 | /// 悬停引脚 14 | public PinBase? HoveredPin { get; set; } = null; 15 | 16 | /// 17 | /// 初始化 18 | /// 19 | public virtual void Init() { } 20 | 21 | /// 22 | /// 获取引脚区域控件 23 | /// 24 | public virtual Grid GetPinArea() => throw new NotImplementedException(); 25 | 26 | /// 27 | /// 获取悬停引脚相对于鼠标的偏移量 28 | /// 29 | public Point GetHoveredPinOffset() 30 | { 31 | Grid pinArea = GetPinArea(); 32 | Point offset = Mouse.GetPosition(pinArea); 33 | if (HoveredPin.Flow == PinFlow.Input) 34 | { 35 | offset.X = 3 - offset.X; 36 | offset.Y = 8 - offset.Y; 37 | } 38 | else 39 | { 40 | offset.X = 14 - offset.X; 41 | offset.Y = 8 - offset.Y; 42 | } 43 | return offset; 44 | } 45 | 46 | /// 47 | /// 获取相对于节点的坐标 48 | /// 49 | public virtual Point GetPinOffset(NodeView card, int pinIndex) => new Point(); 50 | 51 | /// 52 | /// 更新引脚图标 53 | /// 54 | public virtual void UpdatePinIcon() { } 55 | } 56 | } -------------------------------------------------------------------------------- /XNode/SubSystem/NodeEditSystem/Control/PropertyBar/CustomListItem.xaml: -------------------------------------------------------------------------------- 1 |  9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /XNode/SubSystem/NodeEditSystem/Control/PropertyBar/CustomListItem.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using System.Windows.Controls; 3 | 4 | namespace XNode.SubSystem.NodeEditSystem.Control.PropertyBar 5 | { 6 | public partial class CustomListItem : UserControl 7 | { 8 | public CustomListItem() 9 | { 10 | InitializeComponent(); 11 | } 12 | 13 | public string ItemValue 14 | { 15 | get => Input_Value.Text; 16 | set => Input_Value.Text = value; 17 | } 18 | 19 | public Action? Remove_Click { get; set; } = null; 20 | 21 | public Action? Value_Changed { get; set; } = null; 22 | 23 | private void Input_Value_TextChanged(object sender, TextChangedEventArgs e) => Value_Changed?.Invoke(this); 24 | 25 | private void Tool_Remove_Click(object sender, RoutedEventArgs e) => Remove_Click?.Invoke(this); 26 | } 27 | } -------------------------------------------------------------------------------- /XNode/SubSystem/NodeEditSystem/Control/PropertyBar/ListEditer.xaml: -------------------------------------------------------------------------------- 1 |  9 | 10 | 11 | 12 | 13 | 14 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /XNode/SubSystem/NodeEditSystem/Control/PropertyBar/ListSelecter.xaml: -------------------------------------------------------------------------------- 1 |  9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /XNode/SubSystem/NodeEditSystem/Control/PropertyBar/ListSelecter.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Controls; 2 | using System.Windows.Input; 3 | 4 | namespace XNode.SubSystem.NodeEditSystem.Control.PropertyBar 5 | { 6 | public partial class ListSelecter : PropertyBarBase 7 | { 8 | public ListSelecter() => InitializeComponent(); 9 | 10 | public Action? SelectionChanged { get; set; } = null; 11 | 12 | public void LoadProperty(List list, string value) 13 | { 14 | Block_Title.Text = Title; 15 | foreach (var item in list) 16 | { 17 | ComboBoxItem boxItem = new ComboBoxItem 18 | { 19 | Content = item, 20 | ToolTip = item, 21 | }; 22 | Box_ItemList.Items.Add(boxItem); 23 | } 24 | Box_ItemList.SelectedIndex = list.IndexOf(value); 25 | } 26 | 27 | private void MainGrid_MouseEnter(object sender, MouseEventArgs e) 28 | { 29 | Block_Title.Foreground = _hovered; 30 | } 31 | 32 | private void MainGrid_MouseLeave(object sender, MouseEventArgs e) 33 | { 34 | Block_Title.Foreground = _default; 35 | } 36 | 37 | private void Box_ItemList_SelectionChanged(object sender, SelectionChangedEventArgs e) 38 | { 39 | SelectionChanged?.Invoke(Box_ItemList.SelectedIndex - 1); 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /XNode/SubSystem/NodeEditSystem/Control/PropertyBar/PropertyBarBase.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Controls; 2 | using System.Windows.Media; 3 | 4 | namespace XNode.SubSystem.NodeEditSystem.Control.PropertyBar 5 | { 6 | public class PropertyBarBase : UserControl 7 | { 8 | public string Title { get; set; } = ""; 9 | 10 | public virtual void LoadProperty(string value) { } 11 | 12 | protected SolidColorBrush _default = new SolidColorBrush(Color.FromRgb(140, 140, 140)); 13 | protected SolidColorBrush _hovered = new SolidColorBrush(Color.FromRgb(255, 255, 255)); 14 | } 15 | } -------------------------------------------------------------------------------- /XNode/SubSystem/NodeEditSystem/Control/PropertyBar/TextInput.xaml: -------------------------------------------------------------------------------- 1 |  9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /XNode/SubSystem/NodeEditSystem/Control/PropertyBar/TextInput.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Controls; 2 | using System.Windows.Input; 3 | 4 | namespace XNode.SubSystem.NodeEditSystem.Control.PropertyBar 5 | { 6 | public partial class TextInput : PropertyBarBase 7 | { 8 | public TextInput() 9 | { 10 | InitializeComponent(); 11 | // Input_Value.TextChanged += OnTextChanged; 12 | Input_Value.KeyDown += Input_Value_KeyDown; 13 | } 14 | 15 | public string Text { get; set; } = ""; 16 | 17 | public event Action TextChanged; 18 | 19 | /// 20 | /// 加载属性 21 | /// 22 | public override void LoadProperty(string text) 23 | { 24 | Block_Title.Text = Title; 25 | Input_Value.Text = text; 26 | } 27 | 28 | private void MainGrid_MouseEnter(object sender, MouseEventArgs e) 29 | { 30 | Block_Title.Foreground = _hovered; 31 | } 32 | 33 | private void MainGrid_MouseLeave(object sender, MouseEventArgs e) 34 | { 35 | Block_Title.Foreground = _default; 36 | } 37 | 38 | private void OnTextChanged(object sender, TextChangedEventArgs e) 39 | { 40 | TextChanged?.Invoke(Input_Value.Text); 41 | Text = Input_Value.Text; 42 | } 43 | 44 | private void Input_Value_KeyDown(object sender, KeyEventArgs e) 45 | { 46 | if (e.Key == Key.Enter) 47 | { 48 | e.Handled = true; 49 | TextChanged?.Invoke(Input_Value.Text); 50 | Text = Input_Value.Text; 51 | } 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /XNode/SubSystem/NodeEditSystem/Define/ConnectLine.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | 3 | namespace XNode.SubSystem.NodeEditSystem.Define 4 | { 5 | /// 6 | /// 连接线 7 | /// 8 | public class ConnectLine 9 | { 10 | public Point Start { get; set; } 11 | 12 | public Point End { get; set; } 13 | } 14 | } -------------------------------------------------------------------------------- /XNode/SubSystem/NodeEditSystem/Define/EnumDefine.cs: -------------------------------------------------------------------------------- 1 | namespace XNode.SubSystem.NodeEditSystem.Define 2 | { 3 | /// 4 | /// 鼠标命中区域 5 | /// 6 | public enum MouseHitedArea 7 | { 8 | /// 空白处 9 | Space, 10 | /// 节点 11 | Node, 12 | /// 引脚 13 | Pin, 14 | /// 连接线 15 | ConnectLine, 16 | } 17 | 18 | /// 19 | /// 选择方式 20 | /// 21 | public enum SelectType 22 | { 23 | /// 框选 24 | Box, 25 | /// 交叉 26 | Cross 27 | } 28 | } -------------------------------------------------------------------------------- /XNode/SubSystem/NodeEditSystem/Define/PinColorSet.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Media; 2 | using XLib.WPF.Ex; 3 | 4 | namespace XNode.SubSystem.NodeEditSystem.Define 5 | { 6 | /// 7 | /// 引脚颜色集 8 | /// 9 | public class PinColorSet 10 | { 11 | public static Color Execute => "C47EFF".ToColor(); 12 | 13 | public static Color Bool => "A7C4B5".ToColor(); 14 | 15 | public static Color Int => "B3D465".ToColor(); 16 | 17 | public static Color Double => "E06C9F".ToColor(); 18 | 19 | public static Color String => "F3B562".ToColor(); 20 | 21 | public static Color ByteArray => "6CB891".ToColor(); 22 | } 23 | } -------------------------------------------------------------------------------- /XNode/SubSystem/NodeEditSystem/Define/PinConnectInfo.cs: -------------------------------------------------------------------------------- 1 | using XLib.Node; 2 | 3 | namespace XNode.SubSystem.NodeEditSystem.Define 4 | { 5 | /// 6 | /// 引脚连接信息 7 | /// 8 | public class PinConnectInfo 9 | { 10 | public string Title { get; set; } = ""; 11 | 12 | public PinFlow Flow { get; set; } = PinFlow.Input; 13 | 14 | public List PathList { get; set; } = new List(); 15 | } 16 | } -------------------------------------------------------------------------------- /XNode/SubSystem/NodeEditSystem/Define/PinPath.cs: -------------------------------------------------------------------------------- 1 | namespace XNode.SubSystem.NodeEditSystem.Define 2 | { 3 | /// 4 | /// 引脚路径:节点编号.引脚组索引.引脚索引 5 | /// 6 | public class PinPath 7 | { 8 | /// 9 | /// 解析引脚路径 10 | /// 11 | public static PinPath ParsePinPath(string path) 12 | { 13 | string[] nodeArray = path.Split(','); 14 | return new PinPath 15 | { 16 | NodeVersion = nodeArray[0], 17 | NodeID = int.Parse(nodeArray[1]), 18 | GroupIndex = int.Parse(nodeArray[2]), 19 | PinIndex = int.Parse(nodeArray[3]) 20 | }; 21 | } 22 | 23 | public string NodeVersion { get; set; } = "1.0"; 24 | 25 | public int NodeID { get; set; } = -1; 26 | 27 | public int GroupIndex { get; set; } = -1; 28 | 29 | public int PinIndex { get; set; } = -1; 30 | 31 | public override string ToString() => $"{NodeVersion},{NodeID},{GroupIndex},{PinIndex}"; 32 | } 33 | } -------------------------------------------------------------------------------- /XNode/SubSystem/NodeEditSystem/Define/TargetBox.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | 3 | namespace XNode.SubSystem.NodeEditSystem.Define 4 | { 5 | /// 6 | /// 目标框 7 | /// 8 | public class TargetBox 9 | { 10 | public Point ScreenPoint { get; set; } 11 | 12 | public double Height { get; set; } 13 | 14 | public double Width { get; set; } 15 | 16 | /// 外框偏移。正数向外,负数向内 17 | public double BoxOffset { get; set; } = 0; 18 | 19 | /// 20 | /// 获取绘制目标框的坐标列表。共绘制八条线,每条线两个坐标 21 | /// 22 | public List GetPointList(int lineLength) 23 | { 24 | List result = new List(); 25 | 26 | double left = ScreenPoint.X - BoxOffset; 27 | double right = ScreenPoint.X + Width + BoxOffset; 28 | double top = ScreenPoint.Y - BoxOffset; 29 | double bottom = ScreenPoint.Y + Height + BoxOffset; 30 | 31 | double hx1 = left + lineLength; 32 | double hx2 = right - lineLength; 33 | double hy1 = top + 0.5; 34 | double hy2 = bottom - 0.5; 35 | 36 | result.Add(new Point(left, hy1)); 37 | result.Add(new Point(hx1, hy1)); 38 | result.Add(new Point(hx2, hy1)); 39 | result.Add(new Point(right, hy1)); 40 | 41 | result.Add(new Point(left, hy2)); 42 | result.Add(new Point(hx1, hy2)); 43 | result.Add(new Point(hx2, hy2)); 44 | result.Add(new Point(right, hy2)); 45 | 46 | double vx1 = left + 0.5; 47 | double vx2 = right - 0.5; 48 | double vy1 = top + lineLength; 49 | double vy2 = bottom - lineLength; 50 | 51 | result.Add(new Point(vx1, top)); 52 | result.Add(new Point(vx1, vy1)); 53 | result.Add(new Point(vx1, vy2)); 54 | result.Add(new Point(vx1, bottom)); 55 | 56 | result.Add(new Point(vx2, top)); 57 | result.Add(new Point(vx2, vy1)); 58 | result.Add(new Point(vx2, vy2)); 59 | result.Add(new Point(vx2, bottom)); 60 | 61 | return result; 62 | } 63 | } 64 | } -------------------------------------------------------------------------------- /XNode/SubSystem/NodeEditSystem/Panel/Component/EditerComponent.cs: -------------------------------------------------------------------------------- 1 | using XLib.Base.UIComponent; 2 | 3 | namespace XNode.SubSystem.NodeEditSystem.Panel.Component 4 | { 5 | public class EditerComponent : Component 6 | { 7 | #region 生命周期 8 | 9 | 10 | 11 | #endregion 12 | 13 | #region 公开方法 14 | 15 | 16 | 17 | #endregion 18 | } 19 | } -------------------------------------------------------------------------------- /XNode/SubSystem/NodeEditSystem/Panel/EditPanel.xaml: -------------------------------------------------------------------------------- 1 |  11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /XNode/SubSystem/NodeEditSystem/Panel/Layer/ConnectLineBackLayer.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using System.Windows.Media; 3 | using XLib.WPF.Drawing; 4 | 5 | namespace XNode.SubSystem.NodeEditSystem.Panel.Layer 6 | { 7 | /// 8 | /// 连接线背景图层 9 | /// 10 | public class ConnectLineBackLayer : SingleBoard 11 | { 12 | public Point Start { get; set; } 13 | 14 | public Point End { get; set; } 15 | 16 | public override void Init() => _pen.Freeze(); 17 | 18 | protected override void OnUpdate() 19 | { 20 | // 计算连接线区域 21 | _left = Start.X; 22 | _right = End.X; 23 | _top = Start.Y + 0.5; 24 | _bottom = End.Y + 0.5; 25 | 26 | // 计算贝塞尔曲线的控制线长度 27 | double controlLineLength = (_right - _left) / 2; 28 | if (controlLineLength < _minLength) controlLineLength = _minLength; 29 | 30 | // 创建形状 31 | PathGeometry geometry = new PathGeometry(); 32 | PathFigure figure = new PathFigure(); 33 | geometry.Figures.Add(figure); 34 | 35 | // 计算贝塞尔曲线的控制点与终点 36 | Point p1 = new Point(_left + controlLineLength, _top); 37 | Point p2 = new Point(_right - controlLineLength, _bottom); 38 | Point endPoint = new Point(_right, _bottom); 39 | 40 | // 设置起点并添加贝塞尔曲线 41 | figure.StartPoint = new Point(_left, _top); 42 | figure.Segments.Add(new BezierSegment(p1, p2, endPoint, true)); 43 | 44 | _dc.DrawGeometry(null, _pen, geometry); 45 | } 46 | 47 | private double _left = 0; 48 | private double _right = 0; 49 | private double _top = 0; 50 | private double _bottom = 0; 51 | 52 | /// 控制线最短长度 53 | private readonly int _minLength = 40; 54 | 55 | private readonly Pen _pen = new Pen(new SolidColorBrush(Color.FromArgb(64, 255, 255, 255)), 5); 56 | } 57 | } -------------------------------------------------------------------------------- /XNode/SubSystem/NodeEditSystem/Panel/Layer/ConnectLineLayer.cs: -------------------------------------------------------------------------------- 1 | using XLib.Node; 2 | using XLib.WPF.Drawing; 3 | 4 | namespace XNode.SubSystem.NodeEditSystem.Panel.Layer 5 | { 6 | /// 7 | /// 连接线图层 8 | /// 9 | public class ConnectLineLayer : DrawingBoard 10 | { 11 | public List ConnectLineList => _connectLineList; 12 | 13 | public void AddConnectLine(VisualConnectLine connectLine) 14 | { 15 | _connectLineList.Add(connectLine); 16 | // 添加可视元素 17 | AddVisualElement(connectLine); 18 | // 绘制可视元素 19 | connectLine.Update(); 20 | } 21 | 22 | public void RemoveConnectLine(PinBase start, PinBase end) 23 | { 24 | int lineIndex = -1; 25 | int index = 0; 26 | // 查找连接线 27 | foreach (var line in _connectLineList) 28 | { 29 | if (line.StartPin == start && line.EndPin == end) 30 | { 31 | lineIndex = index; 32 | break; 33 | } 34 | index++; 35 | } 36 | // 移除连接线 37 | if (lineIndex != -1) 38 | { 39 | RemoveVisualElement(_connectLineList[lineIndex]); 40 | _connectLineList.RemoveAt(lineIndex); 41 | } 42 | } 43 | 44 | public void ClearConnectLine() 45 | { 46 | _connectLineList.Clear(); 47 | ClearVisualElement(); 48 | } 49 | 50 | private readonly List _connectLineList = new List(); 51 | } 52 | } -------------------------------------------------------------------------------- /XNode/SubSystem/NodeEditSystem/Panel/Layer/HoverBoxLayer.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using System.Windows.Media; 3 | using XLib.Animate; 4 | using XLib.WPF.Drawing; 5 | using XNode.SubSystem.NodeEditSystem.Define; 6 | 7 | namespace XNode.SubSystem.NodeEditSystem.Panel.Layer 8 | { 9 | /// 10 | /// 悬停框图层 11 | /// 12 | public class HoverBoxLayer : SingleBoard, IMotion 13 | { 14 | /// 悬停框 15 | public TargetBox? Box { get; set; } = null; 16 | 17 | protected override void OnUpdate() 18 | { 19 | if (Box == null) return; 20 | 21 | List pointList = Box.GetPointList(15); 22 | for (int index = 0; index < pointList.Count / 2; index++) 23 | _dc.DrawLine(_pen, pointList[index * 2], pointList[index * 2 + 1]); 24 | } 25 | 26 | public double GetMotionProperty(string propertyName) => 0; 27 | 28 | public void SetMotionProperty(string propertyName, double value) 29 | { 30 | if (Box == null) return; 31 | switch (propertyName) 32 | { 33 | case "BoxMargin": 34 | Box.BoxOffset = value; 35 | break; 36 | } 37 | Dispatcher.Invoke(Update); 38 | } 39 | 40 | private readonly Pen _pen = new Pen(Brushes.White, 1); 41 | } 42 | } -------------------------------------------------------------------------------- /XNode/SubSystem/NodeEditSystem/Panel/Layer/SelectBoxLayer.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using System.Windows.Media; 3 | using XLib.WPF.Drawing; 4 | 5 | namespace XNode.SubSystem.NodeEditSystem.Panel.Layer 6 | { 7 | /// 8 | /// 选框图层 9 | /// 10 | public class SelectBoxLayer : SingleBoard 11 | { 12 | public Point Start { get; set; } = new Point(); 13 | 14 | public Point End { get; set; } = new Point(); 15 | 16 | public override void Init() 17 | { 18 | _border.Freeze(); 19 | _blue.Freeze(); 20 | _orange.Freeze(); 21 | } 22 | 23 | protected override void OnUpdate() 24 | { 25 | var start = new Point(Start.X + 0.5, Start.Y + 0.5); 26 | var end = new Point(End.X + 0.5, End.Y + 0.5); 27 | if (End.X >= Start.X) 28 | _dc.DrawRectangle(_blue, _border, new Rect(start, end)); 29 | else 30 | _dc.DrawRectangle(_orange, _border, new Rect(start, end)); 31 | } 32 | 33 | private readonly Pen _border = new Pen(new SolidColorBrush(Color.FromRgb(255, 255, 255)), 1); 34 | private readonly Brush _blue = new SolidColorBrush(Color.FromArgb(32, 0, 128, 235)); 35 | private readonly Brush _orange = new SolidColorBrush(Color.FromArgb(32, 255, 120, 0)); 36 | } 37 | } -------------------------------------------------------------------------------- /XNode/SubSystem/NodeEditSystem/Panel/Layer/SelectedBoxLayer.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using System.Windows.Media; 3 | using XLib.WPF.Drawing; 4 | using XNode.SubSystem.NodeEditSystem.Define; 5 | 6 | namespace XNode.SubSystem.NodeEditSystem.Panel.Layer 7 | { 8 | /// 9 | /// 选中框图层 10 | /// 11 | public class SelectedBoxLayer : SingleBoard 12 | { 13 | public List BoxList { get; set; } = new List(); 14 | 15 | protected override void OnUpdate() 16 | { 17 | foreach (var box in BoxList) 18 | { 19 | List pointList = box.GetPointList(15); 20 | for (int index = 0; index < pointList.Count / 2; index++) 21 | _dc.DrawLine(_pen, pointList[index * 2], pointList[index * 2 + 1]); 22 | } 23 | } 24 | 25 | private readonly Pen _pen = new Pen(new SolidColorBrush(Color.FromRgb(237, 100, 21)), 1); 26 | } 27 | } -------------------------------------------------------------------------------- /XNode/SubSystem/NodeEditSystem/Panel/Layer/TempConnectLineLayer.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using System.Windows.Media; 3 | using XLib.WPF.Drawing; 4 | using XNode.SubSystem.NodeEditSystem.Define; 5 | 6 | namespace XNode.SubSystem.NodeEditSystem.Panel.Layer 7 | { 8 | /// 9 | /// 临时连接线图层 10 | /// 11 | public class TempConnectLineLayer : SingleBoard 12 | { 13 | public ConnectLine? Line { get; set; } = null; 14 | 15 | protected override void OnUpdate() 16 | { 17 | if (Line == null) return; 18 | 19 | // 计算连接线区域 20 | _left = Line.Start.X; 21 | _right = Line.End.X; 22 | _top = Line.Start.Y + 0.5; 23 | _bottom = Line.End.Y + 0.5; 24 | // 计算贝塞尔曲线的控制线长度 25 | double controlLineLength = (_right - _left) / 2; 26 | if (controlLineLength < _minLength) controlLineLength = _minLength; 27 | 28 | // 创建形状 29 | PathGeometry geometry = new PathGeometry(); 30 | PathFigure figure = new PathFigure(); 31 | geometry.Figures.Add(figure); 32 | 33 | // 计算贝塞尔曲线的控制点与终点 34 | Point p1 = new Point(_left + controlLineLength, _top); 35 | Point p2 = new Point(_right - controlLineLength, _bottom); 36 | Point endPoint = new Point(_right, _bottom); 37 | 38 | // 设置起点并添加贝塞尔曲线 39 | figure.StartPoint = new Point(_left, _top); 40 | figure.Segments.Add(new BezierSegment(p1, p2, endPoint, true)); 41 | 42 | // 绘制形状 43 | _dc.DrawGeometry(null, _pen, geometry); 44 | } 45 | 46 | #region 字段 47 | 48 | private double _left = 0; 49 | private double _right = 0; 50 | private double _top = 0; 51 | private double _bottom = 0; 52 | 53 | /// 控制线最短长度 54 | private readonly int _minLength = 40; 55 | 56 | private readonly Pen _pen = new Pen(new SolidColorBrush(Color.FromArgb(255, 255, 255, 255)), 1); 57 | 58 | #endregion 59 | } 60 | } -------------------------------------------------------------------------------- /XNode/SubSystem/NodeEditSystem/Panel/Layer/VisualConnectLine.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using System.Windows.Media; 3 | using XLib.Node; 4 | using XLib.WPF.Drawing; 5 | 6 | namespace XNode.SubSystem.NodeEditSystem.Panel.Layer 7 | { 8 | public class VisualConnectLine : VisualElement 9 | { 10 | public VisualConnectLine() => _penExecute.Freeze(); 11 | 12 | public PinBase StartPin { get; set; } 13 | 14 | public PinBase EndPin { get; set; } 15 | 16 | public Point Start { get; set; } 17 | 18 | public Point End { get; set; } 19 | 20 | public Color Color { get; set; } = Colors.White; 21 | 22 | public bool IsData { get; set; } = false; 23 | 24 | protected override void OnUpdate(DrawingContext context) 25 | { 26 | // 计算连接线区域 27 | _left = Start.X; 28 | _right = End.X; 29 | _top = Start.Y + 0.5; 30 | _bottom = End.Y + 0.5; 31 | 32 | // 计算贝塞尔曲线的控制线长度 33 | double controlLineLength = (_right - _left) / 2; 34 | if (controlLineLength < _minLength) controlLineLength = _minLength; 35 | 36 | // 创建形状 37 | PathGeometry geometry = new PathGeometry(); 38 | PathFigure figure = new PathFigure(); 39 | geometry.Figures.Add(figure); 40 | 41 | // 计算贝塞尔曲线的控制点与终点 42 | Point p1 = new Point(_left + controlLineLength, _top); 43 | Point p2 = new Point(_right - controlLineLength, _bottom); 44 | Point endPoint = new Point(_right, _bottom); 45 | 46 | // 设置起点并添加贝塞尔曲线 47 | figure.StartPoint = new Point(_left, _top); 48 | figure.Segments.Add(new BezierSegment(p1, p2, endPoint, true)); 49 | 50 | Pen pen = new Pen(new SolidColorBrush(Color), 1); 51 | // 绘制形状 52 | if (!IsData) context.DrawGeometry(null, _penExecute, geometry); 53 | else context.DrawGeometry(null, new Pen(new SolidColorBrush(Color), 1), geometry); 54 | } 55 | 56 | public override string ToString() => $"{Start}-{End}"; 57 | 58 | private double _left = 0; 59 | private double _right = 0; 60 | private double _top = 0; 61 | private double _bottom = 0; 62 | 63 | /// 控制线最短长度 64 | private readonly int _minLength = 40; 65 | 66 | /// 执行引脚线 67 | private readonly Pen _penExecute = new Pen(new SolidColorBrush(Color.FromArgb(255, 196, 126, 255)), 1); 68 | } 69 | } -------------------------------------------------------------------------------- /XNode/SubSystem/NodeLibSystem/Define/Data/Data_Double.cs: -------------------------------------------------------------------------------- 1 | using XLib.Node; 2 | 3 | namespace XNode.SubSystem.NodeLibSystem.Define.Data 4 | { 5 | public class Data_Double : NodeBase 6 | { 7 | public override void Init() 8 | { 9 | SetViewProperty(NodeColorSet.Data, "Variate", "小数"); 10 | 11 | PinGroupList.Add(new DataPinGroup(this, "double", "数据", "0.0") 12 | { 13 | Readable = true, 14 | Writeable = false 15 | }); 16 | 17 | InitPinGroup(); 18 | } 19 | 20 | public override string GetTypeString() => nameof(Data_Double); 21 | 22 | public override Dictionary GetParaDict() 23 | { 24 | Dictionary result = new Dictionary 25 | { 26 | { "Data", GetData(0) }, 27 | }; 28 | return result; 29 | } 30 | 31 | public override void LoadParaDict(string version, Dictionary paraDict) 32 | { 33 | SetData(0, paraDict["Data"]); 34 | } 35 | 36 | protected override NodeBase CloneNode() => new Data_Double(); 37 | } 38 | } -------------------------------------------------------------------------------- /XNode/SubSystem/NodeLibSystem/Define/Data/Data_Int.cs: -------------------------------------------------------------------------------- 1 | using XLib.Node; 2 | 3 | namespace XNode.SubSystem.NodeLibSystem.Define.Data 4 | { 5 | public class Data_Int : NodeBase 6 | { 7 | public override void Init() 8 | { 9 | SetViewProperty(NodeColorSet.Data, "Variate", "整数"); 10 | 11 | PinGroupList.Add(new DataPinGroup(this, "int", "数据", "0") 12 | { 13 | Readable = true, 14 | Writeable = false 15 | }); 16 | 17 | InitPinGroup(); 18 | } 19 | 20 | public override string GetTypeString() => nameof(Data_Int); 21 | 22 | public override Dictionary GetParaDict() 23 | { 24 | Dictionary result = new Dictionary 25 | { 26 | { "Data", GetData(0) }, 27 | }; 28 | return result; 29 | } 30 | 31 | public override void LoadParaDict(string version, Dictionary paraDict) 32 | { 33 | SetData(0, paraDict["Data"]); 34 | } 35 | 36 | protected override NodeBase CloneNode() => new Data_Int(); 37 | } 38 | } -------------------------------------------------------------------------------- /XNode/SubSystem/NodeLibSystem/Define/Data/Data_String.cs: -------------------------------------------------------------------------------- 1 | using XLib.Node; 2 | 3 | namespace XNode.SubSystem.NodeLibSystem.Define.Data 4 | { 5 | public class Data_String : NodeBase 6 | { 7 | public override void Init() 8 | { 9 | SetViewProperty(NodeColorSet.Data, "Variate", "字符串"); 10 | 11 | PinGroupList.Add(new DataPinGroup(this, "string", "数据", "") 12 | { 13 | BoxWidth = 240, 14 | Readable = true, 15 | Writeable = false 16 | }); 17 | 18 | InitPinGroup(); 19 | } 20 | 21 | public override string GetTypeString() => nameof(Data_String); 22 | 23 | public override Dictionary GetParaDict() 24 | { 25 | Dictionary result = new Dictionary 26 | { 27 | { "Data", GetData(0) }, 28 | }; 29 | return result; 30 | } 31 | 32 | public override void LoadParaDict(string version, Dictionary paraDict) 33 | { 34 | SetData(0, paraDict["Data"]); 35 | } 36 | 37 | protected override NodeBase CloneNode() => new Data_String(); 38 | } 39 | } -------------------------------------------------------------------------------- /XNode/SubSystem/NodeLibSystem/Define/Events/Event_Keyboard.cs: -------------------------------------------------------------------------------- 1 | using XLib.Node; 2 | using XNode.SubSystem.EventSystem; 3 | 4 | namespace XNode.SubSystem.NodeLibSystem.Define.Events 5 | { 6 | /// 7 | /// 键盘事件 8 | /// 9 | public class Event_Keyboard : NodeBase 10 | { 11 | public override void Init() 12 | { 13 | SetViewProperty(NodeColorSet.Event, "Key", "按键"); 14 | 15 | PinGroupList.Add(new DataPinGroup(this, "string", "当前按键", "") { BoxWidth = 120, Writeable = false }); 16 | PinGroupList.Add(new DataPinGroup(this, "string", "监听按键", "Space") { BoxWidth = 120, Readable = false, Writeable = false }); 17 | PinGroupList.Add(new ActionPinGroup(this, "按下")); 18 | PinGroupList.Add(new ActionPinGroup(this, "松开")); 19 | 20 | InitPinGroup(); 21 | } 22 | 23 | public override void Enable() 24 | { 25 | EM.Instance.Add(EventType.KeyDown, OnKeyDown); 26 | EM.Instance.Add(EventType.KeyUp, OnKeyUp); 27 | } 28 | 29 | public override void Disable() 30 | { 31 | EM.Instance.Remove(EventType.KeyDown, OnKeyDown); 32 | EM.Instance.Remove(EventType.KeyUp, OnKeyUp); 33 | } 34 | 35 | public override void Clear() 36 | { 37 | EM.Instance.Remove(EventType.KeyDown, OnKeyDown); 38 | EM.Instance.Remove(EventType.KeyUp, OnKeyUp); 39 | } 40 | 41 | public override string GetTypeString() => nameof(Event_Keyboard); 42 | 43 | public override Dictionary GetParaDict() => 44 | new Dictionary { { "ListenKey", GetData(1) } }; 45 | 46 | public override void LoadParaDict(string version, Dictionary paraDict) 47 | { 48 | try 49 | { 50 | SetData(1, paraDict["ListenKey"]); 51 | } 52 | catch (Exception) { } 53 | } 54 | 55 | protected override NodeBase CloneNode() => new Event_Keyboard(); 56 | 57 | private void OnKeyDown(string key) 58 | { 59 | SetData(0, key); 60 | if (key == GetData(1)) 61 | GetPinGroup(2).Invoke(); 62 | } 63 | 64 | private void OnKeyUp(string key) 65 | { 66 | SetData(0, key); 67 | if (key == GetData(1)) 68 | GetPinGroup(3).Invoke(); 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /XNode/SubSystem/NodeLibSystem/Define/Flows/Flow_If.cs: -------------------------------------------------------------------------------- 1 | using XLib.Node; 2 | 3 | namespace XNode.SubSystem.NodeLibSystem.Define.Flows 4 | { 5 | public class Flow_If : NodeBase 6 | { 7 | public override void Init() 8 | { 9 | SetViewProperty(NodeColorSet.Flow, "Flow", "判断"); 10 | 11 | PinGroupList.Add(new ExecutePinGroup(this, "根据逻辑值执行不同的逻辑")); 12 | PinGroupList.Add(new DataPinGroup(this, "bool", "逻辑值", "True") { Readable = false }); 13 | PinGroupList.Add(new ActionPinGroup(this, "逻辑真")); 14 | PinGroupList.Add(new ActionPinGroup(this, "逻辑假")); 15 | 16 | InitPinGroup(); 17 | } 18 | 19 | protected override void ExecuteNode() 20 | { 21 | // 获取逻辑值引脚组 22 | DataPinGroup logicValueGroup = (DataPinGroup)PinGroupList[1]; 23 | // 执行连接至逻辑值的节点 24 | if (logicValueGroup.InputPin != null && logicValueGroup.InputPin.SourceList.Count > 0) 25 | // 输入引脚.第一个源引脚.所属引脚组.所属节点.执行 26 | logicValueGroup.InputPin.SourceList[0].OwnerGroup.OwnerNode.Execute(); 27 | // 更新逻辑值 28 | UpdateData(1); 29 | // 解析值 30 | bool logicResult = bool.Parse(GetData(1)); 31 | 32 | if (logicResult == true) GetPinGroup(2).Invoke(); 33 | else GetPinGroup(3).Invoke(); 34 | 35 | GetPinGroup().Execute(); 36 | } 37 | 38 | public override string GetTypeString() => nameof(Flow_If); 39 | 40 | public override Dictionary GetParaDict() => 41 | new Dictionary { { "LogicValue", GetData(1) } }; 42 | 43 | public override void LoadParaDict(string version, Dictionary paraDict) 44 | { 45 | try 46 | { 47 | SetData(1, paraDict["LogicValue"]); 48 | } 49 | catch (Exception) { } 50 | } 51 | 52 | protected override NodeBase CloneNode() => new Flow_If(); 53 | } 54 | } -------------------------------------------------------------------------------- /XNode/SubSystem/NodeLibSystem/Define/Flows/Flow_LoopByCount.cs: -------------------------------------------------------------------------------- 1 | using XLib.Node; 2 | 3 | namespace XNode.SubSystem.NodeLibSystem.Define.Flows 4 | { 5 | public class Flow_LoopByCount : NodeBase 6 | { 7 | public override void Init() 8 | { 9 | SetViewProperty(NodeColorSet.Flow, "Loop", "计数循环"); 10 | 11 | PinGroupList.Add(new ExecutePinGroup(this, "循环执行多少次循环体")); 12 | PinGroupList.Add(new DataPinGroup(this, "int", "次数", "10") { Readable = false }); 13 | PinGroupList.Add(new ActionPinGroup(this, "循环体")); 14 | 15 | InitPinGroup(); 16 | } 17 | 18 | protected override void ExecuteNode() 19 | { 20 | int count = int.Parse(GetData(1)); 21 | for (int counter = 0; counter < count; counter++) 22 | GetPinGroup(2).Invoke(); 23 | GetPinGroup().Execute(); 24 | } 25 | 26 | public override string GetTypeString() => nameof(Flow_LoopByCount); 27 | 28 | public override Dictionary GetParaDict() => 29 | new Dictionary { { "Times", GetData(1) } }; 30 | 31 | protected override NodeBase CloneNode() => new Flow_LoopByCount(); 32 | } 33 | } -------------------------------------------------------------------------------- /XNode/SubSystem/NodeLibSystem/Define/Flows/Flow_While.cs: -------------------------------------------------------------------------------- 1 | using XLib.Node; 2 | 3 | namespace XNode.SubSystem.NodeLibSystem.Define.Flows 4 | { 5 | public class Flow_While : NodeBase 6 | { 7 | public override void Init() 8 | { 9 | SetViewProperty(NodeColorSet.Flow, "Loop", "条件循环"); 10 | 11 | PinGroupList.Add(new ExecutePinGroup(this, "逻辑值为真,则无限循环执行")); 12 | PinGroupList.Add(new DataPinGroup(this, "bool", "逻辑值", "True") { Readable = false }); 13 | PinGroupList.Add(new ActionPinGroup(this, "循环体")); 14 | 15 | InitPinGroup(); 16 | } 17 | 18 | protected override void ExecuteNode() 19 | { 20 | // 获取逻辑值引脚组 21 | DataPinGroup logicValueGroup = (DataPinGroup)PinGroupList[1]; 22 | // 获取循环体引脚组 23 | ActionPinGroup loopBodyGroup = GetPinGroup(2); 24 | 25 | SynchronizationContext? context = SynchronizationContext.Current; 26 | if (context == null) 27 | { 28 | context = new SynchronizationContext(); 29 | SynchronizationContext.SetSynchronizationContext(context); 30 | } 31 | Task.Run(() => ExecuteWhileSync(logicValueGroup, loopBodyGroup, context)); 32 | } 33 | 34 | public override string GetTypeString() => nameof(Flow_While); 35 | 36 | public override Dictionary GetParaDict() => 37 | new Dictionary { { "LogicValue", GetData(1) } }; 38 | 39 | protected override NodeBase CloneNode() => new Flow_While(); 40 | 41 | private void ExecuteWhileSync(DataPinGroup logicValueGroup, ActionPinGroup loopBodyGroup, SynchronizationContext context) 42 | { 43 | try 44 | { 45 | while (true) 46 | { 47 | // 执行连接至逻辑值的节点 48 | if (logicValueGroup.InputPin != null && logicValueGroup.InputPin.SourceList.Count > 0) 49 | // 输入引脚.第一个源引脚.所属引脚组.所属节点.执行 50 | logicValueGroup.InputPin.SourceList[0].OwnerGroup.OwnerNode.Execute(); 51 | // 更新逻辑值 52 | UpdateData(1); 53 | // 如果值为假,则退出循环 54 | if (!bool.Parse(GetData(1))) break; 55 | // 执行循环体 56 | loopBodyGroup.Invoke(); 57 | } 58 | context.Post(_ => GetPinGroup().Execute(), null); 59 | } 60 | catch (Exception ex) 61 | { 62 | context.Post(_ => 63 | { 64 | RunError = true; 65 | Stop(); 66 | InvokeExecuteError(ex); 67 | }, null); 68 | } 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /XNode/SubSystem/NodeLibSystem/Define/Functions/Func_CreateThread.cs: -------------------------------------------------------------------------------- 1 | using XLib.Node; 2 | 3 | namespace XNode.SubSystem.NodeLibSystem.Define.Functions 4 | { 5 | public class Func_CreateThread : NodeBase 6 | { 7 | public override void Init() 8 | { 9 | SetViewProperty(NodeColorSet.Function, "Function", "多线程执行"); 10 | 11 | PinGroupList.Add(new ExecutePinGroup(this, "创建新线程,并在新线程中执行后续节点")); 12 | 13 | InitPinGroup(); 14 | } 15 | 16 | protected override void ExecuteNode() 17 | { 18 | Task.Run(() => GetPinGroup().Execute()); 19 | } 20 | 21 | public override string GetTypeString() => nameof(Func_CreateThread); 22 | 23 | public override Dictionary GetParaDict() => new Dictionary(); 24 | 25 | protected override NodeBase CloneNode() => new Func_CreateThread(); 26 | } 27 | } -------------------------------------------------------------------------------- /XNode/SubSystem/NodeLibSystem/Define/Functions/Func_Delay.cs: -------------------------------------------------------------------------------- 1 | using XLib.Node; 2 | 3 | namespace XNode.SubSystem.NodeLibSystem.Define.Functions 4 | { 5 | public class Func_Delay : NodeBase 6 | { 7 | #region 生命周期 8 | 9 | public override void Init() 10 | { 11 | SetViewProperty(NodeColorSet.Function, "Delay", "延迟执行"); 12 | 13 | PinGroupList.Add(new ExecutePinGroup(this, "延迟指定毫秒后执行")); 14 | PinGroupList.Add(new DataPinGroup(this, "int", "时长", "5000") { Readable = false, Writeable = false }); 15 | 16 | InitPinGroup(); 17 | } 18 | 19 | #endregion 20 | 21 | #region NodeBase 方法 22 | 23 | protected override async void ExecuteNode() 24 | { 25 | await Task.Delay(int.Parse(GetData(1))); 26 | GetPinGroup().Execute(); 27 | } 28 | 29 | public override string GetTypeString() => nameof(Func_Delay); 30 | 31 | public override Dictionary GetParaDict() 32 | { 33 | return new Dictionary 34 | { 35 | { "Time", GetData(1) } 36 | }; 37 | } 38 | 39 | public override void LoadParaDict(string version, Dictionary paraDict) 40 | { 41 | try 42 | { 43 | SetData(1, paraDict["Time"]); 44 | } 45 | catch (Exception) { } 46 | } 47 | 48 | protected override NodeBase CloneNode() => new Func_Delay(); 49 | 50 | #endregion 51 | } 52 | } -------------------------------------------------------------------------------- /XNode/SubSystem/NodeLibSystem/Define/Functions/Func_Log.cs: -------------------------------------------------------------------------------- 1 | using XLib.Node; 2 | 3 | namespace XNode.SubSystem.NodeLibSystem.Define.Functions 4 | { 5 | public class Func_Log : NodeBase 6 | { 7 | public override void Init() 8 | { 9 | SetViewProperty(NodeColorSet.Function, "Function", "日志"); 10 | 11 | PinGroupList.Add(new ExecutePinGroup(this, "发送消息至控制台")); 12 | PinGroupList.Add(new DataPinGroup(this, "string", "消息", "Message") { BoxWidth = 180, Readable = false }); 13 | 14 | InitPinGroup(); 15 | } 16 | 17 | protected override void ExecuteNode() 18 | { 19 | ((DataPinGroup)PinGroupList[1]).UpdateValue(); 20 | 21 | Console.WriteLine(((DataPinGroup)PinGroupList[1]).Value); 22 | 23 | ((ExecutePinGroup)PinGroupList[0]).Execute(); 24 | } 25 | 26 | public override string GetTypeString() => nameof(Func_Log); 27 | 28 | public override Dictionary GetParaDict() => 29 | new Dictionary { { "Msg", GetData(1) } }; 30 | 31 | public override void LoadParaDict(string version, Dictionary paraDict) 32 | { 33 | try 34 | { 35 | SetData(1, paraDict["Msg"]); 36 | } 37 | catch (Exception) { } 38 | } 39 | 40 | protected override NodeBase CloneNode() => new Func_Log(); 41 | } 42 | } -------------------------------------------------------------------------------- /XNode/SubSystem/NodeLibSystem/Define/Functions/Func_RatioToInt.cs: -------------------------------------------------------------------------------- 1 | using XLib.Node; 2 | 3 | namespace XNode.SubSystem.NodeLibSystem.Define.Functions 4 | { 5 | /// 6 | /// 比例转整数 7 | /// 8 | public class Func_RatioToInt : NodeBase 9 | { 10 | public override void Init() 11 | { 12 | SetViewProperty(NodeColorSet.Function, "Function", "比例转整数"); 13 | 14 | PinGroupList.Add(new ExecutePinGroup(this, "将比例值转换为指定范围内的整数")); 15 | PinGroupList.Add(new DataPinGroup(this, "int", "最小值", "0") { Readable = false, Writeable = false }); 16 | PinGroupList.Add(new DataPinGroup(this, "int", "最大值", "100") { Readable = false, Writeable = false }); 17 | PinGroupList.Add(new DataPinGroup(this, "double", "比例", "0") { Readable = false }); 18 | PinGroupList.Add(new DataPinGroup(this, "int", "转换结果", "0") { Readable = true, Writeable = false }); 19 | 20 | InitPinGroup(); 21 | } 22 | 23 | protected override void ExecuteNode() 24 | { 25 | // 更新比例 26 | ((DataPinGroup)PinGroupList[3]).UpdateValue(); 27 | // 解析参数 28 | int min = int.Parse(((DataPinGroup)PinGroupList[1]).Value); 29 | int max = int.Parse(((DataPinGroup)PinGroupList[2]).Value); 30 | double ratio = double.Parse(((DataPinGroup)PinGroupList[3]).Value); 31 | // 计算结果 32 | int result = (int)(Math.Round((max - min) * ratio) + min); 33 | // 设置结果 34 | ((DataPinGroup)PinGroupList[4]).Value = result.ToString(); 35 | 36 | ((ExecutePinGroup)PinGroupList[0]).Execute(); 37 | } 38 | 39 | public override string GetTypeString() => nameof(Func_RatioToInt); 40 | 41 | public override Dictionary GetParaDict() 42 | { 43 | Dictionary result = new Dictionary 44 | { 45 | { "Min", GetData(1) }, 46 | { "Max", GetData(2) }, 47 | { "Current", GetData(3) }, 48 | { "Result", GetData(4) } 49 | }; 50 | return result; 51 | } 52 | 53 | public override void LoadParaDict(string version, Dictionary paraDict) 54 | { 55 | try 56 | { 57 | SetData(1, paraDict["Min"]); 58 | SetData(2, paraDict["Max"]); 59 | SetData(3, paraDict["Current"]); 60 | SetData(4, paraDict["Result"]); 61 | } 62 | catch (Exception) { } 63 | } 64 | 65 | protected override NodeBase CloneNode() => new Func_RatioToInt(); 66 | } 67 | } -------------------------------------------------------------------------------- /XNode/SubSystem/NodeLibSystem/Define/Functions/Func_Sleep.cs: -------------------------------------------------------------------------------- 1 | using XLib.Node; 2 | 3 | namespace XNode.SubSystem.NodeLibSystem.Define.Functions 4 | { 5 | public class Func_Sleep : NodeBase 6 | { 7 | public override void Init() 8 | { 9 | SetViewProperty(NodeColorSet.Function, "Pause", "暂停执行"); 10 | 11 | PinGroupList.Add(new ExecutePinGroup(this, "暂停指定毫秒后执行")); 12 | PinGroupList.Add(new DataPinGroup(this, "int", "时长", "5000") { Readable = false, Writeable = false }); 13 | 14 | InitPinGroup(); 15 | } 16 | 17 | protected override void ExecuteNode() 18 | { 19 | Thread.Sleep(int.Parse(GetData(1))); 20 | GetPinGroup().Execute(); 21 | } 22 | 23 | public override string GetTypeString() => nameof(Func_Sleep); 24 | 25 | public override Dictionary GetParaDict() 26 | { 27 | return new Dictionary 28 | { 29 | { "Time", GetData(1) } 30 | }; 31 | } 32 | 33 | public override void LoadParaDict(string version, Dictionary paraDict) 34 | { 35 | try 36 | { 37 | SetData(1, paraDict["Time"]); 38 | } 39 | catch (Exception) { } 40 | } 41 | 42 | protected override NodeBase CloneNode() => new Func_Sleep(); 43 | } 44 | } -------------------------------------------------------------------------------- /XNode/SubSystem/NodeLibSystem/NodeLibPanel.xaml: -------------------------------------------------------------------------------- 1 |  10 | 11 | 12 | 17 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /XNode/SubSystem/OptionSystem/OptionManager.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using XLib.Base; 3 | 4 | namespace XNode.SubSystem.OptionSystem 5 | { 6 | /// 7 | /// 选项管理器 8 | /// 9 | public class OptionManager : IManager 10 | { 11 | #region 单例 12 | 13 | private OptionManager() { } 14 | public static OptionManager Instance { get; } = new OptionManager(); 15 | 16 | #endregion 17 | 18 | #region 属性 19 | 20 | /// 缓存路径 21 | public string CachePath => _root + "Cache\\"; 22 | 23 | /// 项目路径 24 | public string ProjectPath => _root + "Project\\"; 25 | 26 | /// 节点库路径 27 | public string NodeLibPath => _root + "NodeLib\\"; 28 | 29 | #endregion 30 | 31 | #region “IManager”方法 32 | 33 | public void Init() 34 | { 35 | if (!Directory.Exists(CachePath)) Directory.CreateDirectory(CachePath); 36 | if (!Directory.Exists(ProjectPath)) Directory.CreateDirectory(ProjectPath); 37 | if (!Directory.Exists(NodeLibPath)) Directory.CreateDirectory(NodeLibPath); 38 | } 39 | 40 | public void Reset() { } 41 | 42 | public void Clear() { } 43 | 44 | #endregion 45 | 46 | #region 字段 47 | 48 | /// 根路径 49 | private readonly string _root = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\XNode\\"; 50 | 51 | #endregion 52 | } 53 | } -------------------------------------------------------------------------------- /XNode/SubSystem/ProjectSystem/FileTool.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Win32; 2 | using XLib.Base; 3 | using XNode.SubSystem.OptionSystem; 4 | 5 | namespace XNode.SubSystem.ProjectSystem 6 | { 7 | /// 8 | /// 文件工具 9 | /// 10 | public class FileTool 11 | { 12 | private FileTool() 13 | { 14 | _projectFilter.TypeList.Add(new TypeInfo("节点项目", "xnode")); 15 | _projectFilter.TypeList.Add(new TypeInfo("节点项目", "json")); 16 | } 17 | public static FileTool Instance { get; } = new FileTool(); 18 | 19 | /// 20 | /// 打开读取项目对话框 21 | /// 22 | public string OpenReadProjectDialog() 23 | { 24 | OpenFileDialog dialog = new OpenFileDialog 25 | { 26 | InitialDirectory = OptionManager.Instance.ProjectPath, 27 | Filter = _projectFilter.ToString(), 28 | }; 29 | return dialog.ShowDialog() == true ? dialog.FileName : ""; 30 | } 31 | 32 | /// 33 | /// 打开保存项目对话框 34 | /// 35 | public string OpenSaveProjectDialog(string fileName) 36 | { 37 | SaveFileDialog dialog = new SaveFileDialog 38 | { 39 | InitialDirectory = OptionManager.Instance.ProjectPath, 40 | FileName = $"{fileName}.xnode", 41 | Filter = _projectFilter.ToString(), 42 | }; 43 | return dialog.ShowDialog() == true ? dialog.FileName : ""; 44 | } 45 | 46 | private readonly FileFilter _projectFilter = new FileFilter(); 47 | } 48 | } -------------------------------------------------------------------------------- /XNode/SubSystem/ProjectSystem/NodeProject.cs: -------------------------------------------------------------------------------- 1 | namespace XNode.SubSystem.ProjectSystem 2 | { 3 | /// 4 | /// 节点项目 5 | /// 6 | public class NodeProject 7 | { 8 | /// 项目路径。仅文件夹 9 | public string ProjectPath { get; set; } = ""; 10 | 11 | /// 项目名称。不包含扩展名 12 | public string ProjectName { get; set; } = ""; 13 | 14 | public string ProjectFileName 15 | { 16 | get 17 | { 18 | if (_projectFileName == "") return ProjectName; 19 | return _projectFileName; 20 | } 21 | set => _projectFileName = value; 22 | } 23 | 24 | /// 文件扩展名 25 | public static string FileExtension { get; private set; } = ".xnode"; 26 | 27 | /// 项目文件路径 28 | public string ProjectFilePath => $"{ProjectPath}\\{ProjectFileName}{FileExtension}"; 29 | 30 | public NodeProject Clone() 31 | { 32 | return new NodeProject 33 | { 34 | ProjectPath = ProjectPath, 35 | ProjectName = ProjectName, 36 | }; 37 | } 38 | 39 | private string _projectFileName = ""; 40 | } 41 | } -------------------------------------------------------------------------------- /XNode/SubSystem/ResourceSystem/ResourceManager.cs: -------------------------------------------------------------------------------- 1 | using XLib.Base; 2 | 3 | namespace XNode.SubSystem.ResourceSystem 4 | { 5 | public class ResourceManager : IManager 6 | { 7 | #region 单例 8 | 9 | private ResourceManager() { } 10 | public static ResourceManager Instance { get; } = new ResourceManager(); 11 | 12 | #endregion 13 | 14 | #region 属性 15 | 16 | public string Name { get; set; } = "资源管理器"; 17 | 18 | #endregion 19 | 20 | #region 接口实现 21 | 22 | public void Init() 23 | { 24 | // 光标管理器 25 | CursorManager.Instance.Init(); 26 | // 引脚图标管理器 27 | PinIconManager.Instance.Init(); 28 | } 29 | 30 | public void Reset() { } 31 | 32 | public void Clear() { } 33 | 34 | #endregion 35 | } 36 | } -------------------------------------------------------------------------------- /XNode/SubSystem/TimerSystem/AppTimer.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using System.Windows.Threading; 3 | using XLib.Base.AppFrame; 4 | 5 | namespace XNode.SubSystem.TimerSystem 6 | { 7 | /// 8 | /// 应用程序定时器 9 | /// 10 | public class AppTimer : ServiceBase 11 | { 12 | #region 单例 13 | 14 | private AppTimer() 15 | { 16 | _timer.Interval = TimeSpan.FromMilliseconds(1000.0 / 30.0); 17 | _timer.Tick += Timer_Tick; 18 | } 19 | public static AppTimer Instance { get; } = new AppTimer(); 20 | 21 | #endregion 22 | 23 | #region 生命周期 24 | 25 | public override void Start() 26 | { 27 | if (_handlerList.Count > 0) _timer.Start(); 28 | } 29 | 30 | public override void Stop() 31 | { 32 | _timer.Stop(); 33 | } 34 | 35 | #endregion 36 | 37 | #region 公开方法 38 | 39 | /// 40 | /// 添加定时器处理器 41 | /// 42 | public void AddTimerHandler(ITimerHandler handler) 43 | { 44 | List newList = new List(_handlerList); 45 | if (!newList.Contains(handler)) newList.Add(handler); 46 | _handlerList = newList; 47 | _timer.Start(); 48 | } 49 | 50 | /// 51 | /// 移除定时器处理器 52 | /// 53 | public void RemoveTimerHandler(ITimerHandler handler) 54 | { 55 | List newList = new List(_handlerList); 56 | newList.Remove(handler); 57 | _handlerList = newList; 58 | if (_handlerList.Count == 0) _timer.Stop(); 59 | } 60 | 61 | #endregion 62 | 63 | #region 私有方法 64 | 65 | /// 66 | /// 定时器.走动 67 | /// 68 | private void Timer_Tick(object? sender, EventArgs e) 69 | { 70 | foreach (var handler in _handlerList) handler.Tick(); 71 | } 72 | 73 | #endregion 74 | 75 | #region 字段 76 | 77 | /// 定时器 78 | private readonly DispatcherTimer _timer = new DispatcherTimer(DispatcherPriority.Background); 79 | /// 定时器处理器列表 80 | private List _handlerList = new List(); 81 | 82 | #endregion 83 | } 84 | } -------------------------------------------------------------------------------- /XNode/SubSystem/TimerSystem/ITimerHandler.cs: -------------------------------------------------------------------------------- 1 | namespace XNode.SubSystem.TimerSystem 2 | { 3 | public interface ITimerHandler 4 | { 5 | void Tick(); 6 | } 7 | 8 | /// 9 | /// 通用定时器处理器 10 | /// 11 | public class TimerHandler : ITimerHandler 12 | { 13 | public Action? OnTick { get; set; } = null; 14 | 15 | public void Tick() => OnTick?.Invoke(); 16 | } 17 | } -------------------------------------------------------------------------------- /XNode/SubSystem/TimerSystem/TimeEngine.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using XLib.Base; 3 | using XLib.Base.AppFrame; 4 | using XLib.Base.Ex; 5 | 6 | namespace XNode.SubSystem.TimerSystem 7 | { 8 | /// 9 | /// 时间引擎 10 | /// 其中定时器以每秒一千次模拟实时触发 11 | /// 12 | public class TimeEngine : ServiceBase 13 | { 14 | #region 单例 15 | 16 | private TimeEngine() => _timer.Tick += Timer_Tick; 17 | public static TimeEngine Instance { get; } = new TimeEngine(); 18 | 19 | #endregion 20 | 21 | #region 属性 22 | 23 | /// 当前时间。单位:毫秒 24 | public static double Time => Instance._stopwatch.DoubleMs(); 25 | 26 | /// 秒表实例 27 | public static Stopwatch Watch => Instance._stopwatch; 28 | 29 | #endregion 30 | 31 | #region 生命周期 32 | 33 | public override void Start() 34 | { 35 | _timer.Start(); 36 | _stopwatch.Start(); 37 | } 38 | 39 | public override void Stop() 40 | { 41 | _timer.Stop(); 42 | _stopwatch.Stop(); 43 | } 44 | 45 | #endregion 46 | 47 | #region 公开方法 48 | 49 | public void AddTimerHandler(ITimerHandler handler) 50 | { 51 | if (_handlerList.Contains(handler)) return; 52 | _handlerList = new List(_handlerList) { handler }; 53 | } 54 | 55 | public void RemoveHandler(ITimerHandler handler) 56 | { 57 | List newList = new List(_handlerList); 58 | newList.Remove(handler); 59 | _handlerList = newList; 60 | } 61 | 62 | #endregion 63 | 64 | #region 私有方法 65 | 66 | private void Timer_Tick() 67 | { 68 | try 69 | { 70 | foreach (var item in _handlerList) item.Tick(); 71 | } 72 | catch (Exception) { } 73 | } 74 | 75 | #endregion 76 | 77 | #region 字段 78 | 79 | /// 秒表:用作应用程序的精确时间参考 80 | private readonly Stopwatch _stopwatch = new Stopwatch(); 81 | /// 定时器:定时驱动引擎 82 | private readonly HighPrecisionTimer _timer = new HighPrecisionTimer(); 83 | 84 | /// 定时处理器列表 85 | private List _handlerList = new List(); 86 | 87 | #endregion 88 | } 89 | } -------------------------------------------------------------------------------- /XNode/SubSystem/WindowSystem/AskDialog.xaml: -------------------------------------------------------------------------------- 1 |  11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 30 | 31 | 32 |