diff --git a/QuickLook.Plugin/QuickLook.Plugin.HelixViewer/Handler.cs b/QuickLook.Plugin/QuickLook.Plugin.HelixViewer/Handler.cs index c4724e4..f837abd 100644 --- a/QuickLook.Plugin/QuickLook.Plugin.HelixViewer/Handler.cs +++ b/QuickLook.Plugin/QuickLook.Plugin.HelixViewer/Handler.cs @@ -15,8 +15,10 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +using System; using System.IO; using System.Linq; +using System.Text; namespace QuickLook.Plugin.HelixViewer; @@ -26,6 +28,7 @@ internal static class Handler { var ext = Path.GetExtension(path).ToLower(); + // Simple solution to doubts if (ext == ".obj") { var firstLines = File.ReadLines(path).Take(10); @@ -38,9 +41,27 @@ internal static class Handler } } } +#if S_DXF + else if (ext == ".dxf") + { + using var s = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); + const int bufferLength = 16 * 1024; + var buffer = new byte[bufferLength]; + int size = s.Read(buffer, 0, buffer.Length); + + for (int i = 0; i < size - 1; i++) + { + if (buffer[i] == (byte)'3' && buffer[i + 1] == (byte)'D') + { + return true; + } + } + } +#endif else { - return true; // Assume other formats are supported + // Assume other formats are supported + return true; } return false; diff --git a/QuickLook.Plugin/QuickLook.Plugin.HelixViewer/HelixPanel.Import.cs b/QuickLook.Plugin/QuickLook.Plugin.HelixViewer/HelixPanel.Import.cs new file mode 100644 index 0000000..7fa8b84 --- /dev/null +++ b/QuickLook.Plugin/QuickLook.Plugin.HelixViewer/HelixPanel.Import.cs @@ -0,0 +1,104 @@ +// Copyright © 2017-2025 QL-Win Contributors +// +// This file is part of QuickLook program. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +using Assimp; +using HelixToolkit.Wpf; +using System; +using System.IO; +using System.Linq; +using System.Windows.Media; +using System.Windows.Media.Media3D; + +namespace QuickLook.Plugin.HelixViewer; + +public partial class HelixPanel +{ + private void Load() + { + var importerType = Importer.GetImporterType(_path); + + try + { + if (importerType == ImporterType.Extended) + { + var context = new AssimpContext(); + var scene = context.ImportFile(_path, PostProcessSteps.Triangulate); + + foreach (var mesh in scene.Meshes) + { + var geometry = new MeshGeometry3D() + { + Positions = [.. mesh.Vertices.Select(v => new Point3D(v.X, v.Y, v.Z))], + TriangleIndices = [.. mesh.GetIndices()], + }; + var model = new GeometryModel3D() + { + Geometry = geometry, + Material = Materials.Gray, + }; + + modelVisual.Content = model; + } + } + else + { + var modelImporter = new ModelImporter(); + var model3DGroup = modelImporter.Load(_path); + var diffuseMaterial = new DiffuseMaterial(new SolidColorBrush(Color.FromRgb(0xA0, 0xA0, 0xA0))); + + foreach (GeometryModel3D child in model3DGroup.Children.Cast()) + { + child.Material = diffuseMaterial; + child.BackMaterial = diffuseMaterial; + } + + modelVisual.Content = model3DGroup; + } + } + catch (Exception ex) + { + errorInfo.Text = $"[{nameof(ImporterType)}.{importerType}] {ex}"; + errorInfo.Visibility = System.Windows.Visibility.Visible; + viewer.Visibility = System.Windows.Visibility.Collapsed; + } + } +} + +file static class Importer +{ + public static ImporterType GetImporterType(string path) + { + if (string.IsNullOrEmpty(path)) + return ImporterType.Unknown; + + return Path.GetExtension(path).ToLower() switch + { + ".stl" or ".obj" or ".3ds" or ".lwo" or ".ply" => ImporterType.Default, + ".fbx" or ".3mf" or ".glb" or ".gltf" or ".dae" or ".dxf" => ImporterType.Extended, + ".pmx" => ImporterType.Extended_MMD, + _ => ImporterType.Unknown, + }; + } +} + +file enum ImporterType +{ + Unknown, + Default, + Extended, + Extended_MMD, +} diff --git a/QuickLook.Plugin/QuickLook.Plugin.HelixViewer/HelixPanel.xaml b/QuickLook.Plugin/QuickLook.Plugin.HelixViewer/HelixPanel.xaml index aa2b44c..adcdc77 100644 --- a/QuickLook.Plugin/QuickLook.Plugin.HelixViewer/HelixPanel.xaml +++ b/QuickLook.Plugin/QuickLook.Plugin.HelixViewer/HelixPanel.xaml @@ -9,6 +9,12 @@ d:DesignWidth="800" mc:Ignorable="d"> + . -using Assimp; -using HelixToolkit.Wpf; -using System; -using System.Linq; using System.Windows.Controls; -using System.Windows.Media; -using System.Windows.Media.Media3D; namespace QuickLook.Plugin.HelixViewer; @@ -39,43 +33,4 @@ public partial class HelixPanel : UserControl { InitializeComponent(); } - - private void Load() - { - if (_path.EndsWith(".fbx", StringComparison.OrdinalIgnoreCase)) - { - var context = new AssimpContext(); - var scene = context.ImportFile(_path, PostProcessSteps.Triangulate); - - foreach (var mesh in scene.Meshes) - { - var geometry = new MeshGeometry3D() - { - Positions = [.. mesh.Vertices.Select(v => new Point3D(v.X, v.Y, v.Z))], - TriangleIndices = [.. mesh.GetIndices()], - }; - var model = new GeometryModel3D() - { - Geometry = geometry, - Material = Materials.Gray, - }; - - modelVisual.Content = model; - } - } - else - { - var modelImporter = new ModelImporter(); - var model3DGroup = modelImporter.Load(_path); - var diffuseMaterial = new DiffuseMaterial(new SolidColorBrush(Color.FromRgb(0xA0, 0xA0, 0xA0))); - - foreach (GeometryModel3D child in model3DGroup.Children.Cast()) - { - child.Material = diffuseMaterial; - child.BackMaterial = diffuseMaterial; - } - - modelVisual.Content = model3DGroup; - } - } } diff --git a/QuickLook.Plugin/QuickLook.Plugin.HelixViewer/Plugin.cs b/QuickLook.Plugin/QuickLook.Plugin.HelixViewer/Plugin.cs index 029a937..16fc1bf 100644 --- a/QuickLook.Plugin/QuickLook.Plugin.HelixViewer/Plugin.cs +++ b/QuickLook.Plugin/QuickLook.Plugin.HelixViewer/Plugin.cs @@ -19,21 +19,34 @@ using QuickLook.Common.Plugin; using System; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Windows; namespace QuickLook.Plugin.HelixViewer; public class Plugin : IViewer { + /// + /// + /// private static readonly HashSet WellKnownExtensions = new( [ + // Default ".stl", ".obj", ".3ds", ".lwo", ".ply", - ".fbx", + + // Extended + ".fbx", ".3mf", ".blend", ".glb", ".gltf", ".dae", +#if S_DXF + ".dxf", +#endif + + // Extended_MMD + ".pmx", ]); private HelixPanel _hp; - public int Priority => 0; + public int Priority => -5; public void Init() { @@ -42,7 +55,7 @@ public class Plugin : IViewer public bool CanHandle(string path) { return !Directory.Exists(path) - && WellKnownExtensions.Contains(Path.GetExtension(path.ToLower())) + && WellKnownExtensions.Any(ext => path.EndsWith(ext, StringComparison.OrdinalIgnoreCase)) && Handler.CanHandle(path); }