Skip to content

Commit 55a0690

Browse files
committed
Refactor HelixViewer extend format support
1 parent 0714574 commit 55a0690

File tree

5 files changed

+148
-49
lines changed

5 files changed

+148
-49
lines changed

QuickLook.Plugin/QuickLook.Plugin.HelixViewer/Handler.cs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,10 @@
1515
// You should have received a copy of the GNU General Public License
1616
// along with this program. If not, see <http://www.gnu.org/licenses/>.
1717

18+
using System;
1819
using System.IO;
1920
using System.Linq;
21+
using System.Text;
2022

2123
namespace QuickLook.Plugin.HelixViewer;
2224

@@ -26,6 +28,7 @@ public static bool CanHandle(string path)
2628
{
2729
var ext = Path.GetExtension(path).ToLower();
2830

31+
// Simple solution to doubts
2932
if (ext == ".obj")
3033
{
3134
var firstLines = File.ReadLines(path).Take(10);
@@ -38,9 +41,27 @@ public static bool CanHandle(string path)
3841
}
3942
}
4043
}
44+
#if S_DXF
45+
else if (ext == ".dxf")
46+
{
47+
using var s = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
48+
const int bufferLength = 16 * 1024;
49+
var buffer = new byte[bufferLength];
50+
int size = s.Read(buffer, 0, buffer.Length);
51+
52+
for (int i = 0; i < size - 1; i++)
53+
{
54+
if (buffer[i] == (byte)'3' && buffer[i + 1] == (byte)'D')
55+
{
56+
return true;
57+
}
58+
}
59+
}
60+
#endif
4161
else
4262
{
43-
return true; // Assume other formats are supported
63+
// Assume other formats are supported
64+
return true;
4465
}
4566

4667
return false;
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
// Copyright © 2017-2025 QL-Win Contributors
2+
//
3+
// This file is part of QuickLook program.
4+
//
5+
// This program is free software: you can redistribute it and/or modify
6+
// it under the terms of the GNU General Public License as published by
7+
// the Free Software Foundation, either version 3 of the License, or
8+
// (at your option) any later version.
9+
//
10+
// This program is distributed in the hope that it will be useful,
11+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
// GNU General Public License for more details.
14+
//
15+
// You should have received a copy of the GNU General Public License
16+
// along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
18+
using Assimp;
19+
using HelixToolkit.Wpf;
20+
using System;
21+
using System.IO;
22+
using System.Linq;
23+
using System.Windows.Media;
24+
using System.Windows.Media.Media3D;
25+
26+
namespace QuickLook.Plugin.HelixViewer;
27+
28+
public partial class HelixPanel
29+
{
30+
private void Load()
31+
{
32+
var importerType = Importer.GetImporterType(_path);
33+
34+
try
35+
{
36+
if (importerType == ImporterType.Extended)
37+
{
38+
var context = new AssimpContext();
39+
var scene = context.ImportFile(_path, PostProcessSteps.Triangulate);
40+
41+
foreach (var mesh in scene.Meshes)
42+
{
43+
var geometry = new MeshGeometry3D()
44+
{
45+
Positions = [.. mesh.Vertices.Select(v => new Point3D(v.X, v.Y, v.Z))],
46+
TriangleIndices = [.. mesh.GetIndices()],
47+
};
48+
var model = new GeometryModel3D()
49+
{
50+
Geometry = geometry,
51+
Material = Materials.Gray,
52+
};
53+
54+
modelVisual.Content = model;
55+
}
56+
}
57+
else
58+
{
59+
var modelImporter = new ModelImporter();
60+
var model3DGroup = modelImporter.Load(_path);
61+
var diffuseMaterial = new DiffuseMaterial(new SolidColorBrush(Color.FromRgb(0xA0, 0xA0, 0xA0)));
62+
63+
foreach (GeometryModel3D child in model3DGroup.Children.Cast<GeometryModel3D>())
64+
{
65+
child.Material = diffuseMaterial;
66+
child.BackMaterial = diffuseMaterial;
67+
}
68+
69+
modelVisual.Content = model3DGroup;
70+
}
71+
}
72+
catch (Exception ex)
73+
{
74+
errorInfo.Text = $"[{nameof(ImporterType)}.{importerType}] {ex}";
75+
errorInfo.Visibility = System.Windows.Visibility.Visible;
76+
viewer.Visibility = System.Windows.Visibility.Collapsed;
77+
}
78+
}
79+
}
80+
81+
file static class Importer
82+
{
83+
public static ImporterType GetImporterType(string path)
84+
{
85+
if (string.IsNullOrEmpty(path))
86+
return ImporterType.Unknown;
87+
88+
return Path.GetExtension(path).ToLower() switch
89+
{
90+
".stl" or ".obj" or ".3ds" or ".lwo" or ".ply" => ImporterType.Default,
91+
".fbx" or ".3mf" or ".glb" or ".gltf" or ".dae" or ".dxf" => ImporterType.Extended,
92+
".pmx" => ImporterType.Extended_MMD,
93+
_ => ImporterType.Unknown,
94+
};
95+
}
96+
}
97+
98+
file enum ImporterType
99+
{
100+
Unknown,
101+
Default,
102+
Extended,
103+
Extended_MMD,
104+
}

QuickLook.Plugin/QuickLook.Plugin.HelixViewer/HelixPanel.xaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@
99
d:DesignWidth="800"
1010
mc:Ignorable="d">
1111
<Grid>
12+
<TextBlock x:Name="errorInfo"
13+
HorizontalAlignment="Left"
14+
VerticalAlignment="Center"
15+
FontSize="12"
16+
TextWrapping="Wrap"
17+
Visibility="Collapsed" />
1218
<helix:HelixViewport3D x:Name="viewer"
1319
CameraRotationMode="Turnball"
1420
CoordinateSystemHorizontalPosition="Left"

QuickLook.Plugin/QuickLook.Plugin.HelixViewer/HelixPanel.xaml.cs

Lines changed: 0 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,7 @@
1515
// You should have received a copy of the GNU General Public License
1616
// along with this program. If not, see <http://www.gnu.org/licenses/>.
1717

18-
using Assimp;
19-
using HelixToolkit.Wpf;
20-
using System;
21-
using System.Linq;
2218
using System.Windows.Controls;
23-
using System.Windows.Media;
24-
using System.Windows.Media.Media3D;
2519

2620
namespace QuickLook.Plugin.HelixViewer;
2721

@@ -39,43 +33,4 @@ public HelixPanel()
3933
{
4034
InitializeComponent();
4135
}
42-
43-
private void Load()
44-
{
45-
if (_path.EndsWith(".fbx", StringComparison.OrdinalIgnoreCase))
46-
{
47-
var context = new AssimpContext();
48-
var scene = context.ImportFile(_path, PostProcessSteps.Triangulate);
49-
50-
foreach (var mesh in scene.Meshes)
51-
{
52-
var geometry = new MeshGeometry3D()
53-
{
54-
Positions = [.. mesh.Vertices.Select(v => new Point3D(v.X, v.Y, v.Z))],
55-
TriangleIndices = [.. mesh.GetIndices()],
56-
};
57-
var model = new GeometryModel3D()
58-
{
59-
Geometry = geometry,
60-
Material = Materials.Gray,
61-
};
62-
63-
modelVisual.Content = model;
64-
}
65-
}
66-
else
67-
{
68-
var modelImporter = new ModelImporter();
69-
var model3DGroup = modelImporter.Load(_path);
70-
var diffuseMaterial = new DiffuseMaterial(new SolidColorBrush(Color.FromRgb(0xA0, 0xA0, 0xA0)));
71-
72-
foreach (GeometryModel3D child in model3DGroup.Children.Cast<GeometryModel3D>())
73-
{
74-
child.Material = diffuseMaterial;
75-
child.BackMaterial = diffuseMaterial;
76-
}
77-
78-
modelVisual.Content = model3DGroup;
79-
}
80-
}
8136
}

QuickLook.Plugin/QuickLook.Plugin.HelixViewer/Plugin.cs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,21 +19,34 @@
1919
using System;
2020
using System.Collections.Generic;
2121
using System.IO;
22+
using System.Linq;
2223
using System.Windows;
2324

2425
namespace QuickLook.Plugin.HelixViewer;
2526

2627
public class Plugin : IViewer
2728
{
29+
/// <summary>
30+
/// <seealso cref="ImporterType"/>
31+
/// </summary>
2832
private static readonly HashSet<string> WellKnownExtensions = new(
2933
[
34+
// Default
3035
".stl", ".obj", ".3ds", ".lwo", ".ply",
31-
".fbx",
36+
37+
// Extended
38+
".fbx", ".3mf", ".blend", ".glb", ".gltf", ".dae",
39+
#if S_DXF
40+
".dxf",
41+
#endif
42+
43+
// Extended_MMD
44+
".pmx",
3245
]);
3346

3447
private HelixPanel _hp;
3548

36-
public int Priority => 0;
49+
public int Priority => -5;
3750

3851
public void Init()
3952
{
@@ -42,7 +55,7 @@ public void Init()
4255
public bool CanHandle(string path)
4356
{
4457
return !Directory.Exists(path)
45-
&& WellKnownExtensions.Contains(Path.GetExtension(path.ToLower()))
58+
&& WellKnownExtensions.Any(ext => path.EndsWith(ext, StringComparison.OrdinalIgnoreCase))
4659
&& Handler.CanHandle(path);
4760
}
4861

0 commit comments

Comments
 (0)