Skip to content

Commit 24b212d

Browse files
Merge pull request #378 from pro3d-space/features/updateSbmOnLocateSurfaces
Issue #244 On locate surfaces, update SurfaceModel in sequenced bookmarks
2 parents bcb19b2 + 78e6335 commit 24b212d

File tree

9 files changed

+170
-46
lines changed

9 files changed

+170
-46
lines changed

.config/dotnet-tools.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
]
2222
},
2323
"fantomas": {
24-
"version": "6.1.1",
24+
"version": "6.2.3",
2525
"commands": [
2626
"fantomas"
2727
]

src/PRo3D.Core/PRo3D.Core.fsproj

+1
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
<Compile Include="Drawing\PackedRendering.fs" />
6161
<Compile Include="Drawing\Drawing-App.fs" />
6262
<Compile Include="SequencedBookmarks\SequencedBookmarks-Model.fs" />
63+
<Compile Include="SequencedBookmarks\SequencedBookmark.fs" />
6364
<Compile Include="SequencedBookmarks\BookmarkUtils.fs" />
6465
<Compile Include="SequencedBookmarks\BookmarkAnimations.fs" />
6566
<Compile Include="SequencedBookmarks\SequencedBookmarksApp.fs" />

src/PRo3D.Core/SequencedBookmarks/BookmarkUtils.fs

+40-3
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ open Aether
2020
open Aether.Operators
2121

2222
module BookmarkUtils =
23+
/// Returns a path to a folder with the same name as the scene file,
24+
/// which lies inside the same folder as the scene file.
25+
/// This path is used to store sequenced bookmarks as individual files
26+
/// when saving the scene.
2327
let basePathFromScenePath (scenePath : string) =
2428
Path.combine [Path.GetDirectoryName scenePath;
2529
Path.GetFileNameWithoutExtension scenePath]
@@ -171,8 +175,12 @@ module BookmarkUtils =
171175
let updatePath (basePath : string) (bm : SequencedBookmark) =
172176
match bm with
173177
| SequencedBookmark.LoadedBookmark loaded ->
174-
Log.line "Updating sequenced bookmark base path from %s to %s"
175-
(string loaded.basePath) basePath
178+
match loaded.basePath with
179+
| Some oldBasePath ->
180+
if not (oldBasePath = basePath) then
181+
Log.line "[BookmarkUtils] Updating sequenced bookmark base path from %s to %s"
182+
(string oldBasePath) basePath
183+
| None -> ()
176184
SequencedBookmark.LoadedBookmark {loaded with basePath = Some basePath}
177185
| SequencedBookmarks.NotYetLoaded notLoaded ->
178186
let newPath = Path.combine [basePath;Path.GetFileName notLoaded.path]
@@ -189,13 +197,42 @@ module BookmarkUtils =
189197
HashMap.map (fun g bm -> updatePath basePath bm) m.bookmarks
190198
{m with bookmarks = bookmarks}
191199

200+
/// Checks the given folder sceneBasePath for
201+
/// sequenced bookmark files, and deletes all files that do
202+
/// not have a corresponding bookmark in bookmarks.
203+
/// Should be used when saving a scene to clean up saved bookmarks
204+
/// that were deleted in the viewer.
205+
let cleanUpOldBookmarks (sceneBasePath : string)
206+
(bookmarks : SequencedBookmarks) =
207+
let files = Directory.GetFiles sceneBasePath
208+
for filePath in files do
209+
let bmGuid =
210+
SequencedBookmark.guidFromFilename filePath
211+
let guidExists =
212+
bmGuid
213+
|> Option.map (fun guid ->
214+
HashMap.containsKey guid bookmarks.bookmarks)
215+
match guidExists with
216+
| Some true ->
217+
()
218+
| _ ->
219+
Log.line "[BookmarkUtils] Cleaning up old bookmarks %s"
220+
filePath
221+
try
222+
File.Delete filePath
223+
with e ->
224+
Log.line "[BookmarkUtils] Could not clean up old bookmark %s" filePath
225+
192226
/// updates the paths of all bookmarks and
193227
/// saves bookmarks to file system
194228
let saveSequencedBookmarks (basePath:string)
195-
(bookmarks : SequencedBookmarks) =
229+
(bookmarks : SequencedBookmarks) =
230+
let bookmarks = loadAll bookmarks
196231
let bookmarks = updatePaths basePath bookmarks
197232
if not (Directory.Exists basePath) then
198233
Directory.CreateDirectory basePath |> ignore
234+
else // if the folder exists, clean up and delete all old bookmarks
235+
cleanUpOldBookmarks basePath bookmarks
199236

200237
for guid, bm in bookmarks.bookmarks do
201238
match bm with
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
namespace PRo3D.Core
2+
3+
open Aardvark.Base
4+
open Aardvark.UI
5+
open System
6+
open System.IO
7+
open PRo3D.Core.SequencedBookmarks
8+
9+
open Aether
10+
open Aether.Operators
11+
12+
module SequencedBookmark =
13+
let filenameIsSequencedBookmark (filename : string) =
14+
let nameNoPath = Path.GetFileName filename
15+
let startsWithPrefix =
16+
String.startsWith
17+
SequencedBookmarkDefaults.filenamePrefix
18+
nameNoPath
19+
let ending =
20+
SequencedBookmarkDefaults.filenamePostfix
21+
+ SequencedBookmarkDefaults.filenameExtension
22+
let containsPostfix =
23+
String.contains ending nameNoPath
24+
startsWithPrefix && containsPostfix
25+
26+
/// Extracts the guid from the filename of a sequenced bookmark.
27+
let guidFromFilename (filename : string) =
28+
let isProperName = filenameIsSequencedBookmark filename
29+
if isProperName then
30+
let nameNoPathNoExt = Path.GetFileNameWithoutExtension filename
31+
let guidString =
32+
nameNoPathNoExt
33+
|> String.replace SequencedBookmarkDefaults.filenamePrefix ""
34+
|> String.replace SequencedBookmarkDefaults.filenamePostfix ""
35+
let (success, guid) = System.Guid.TryParse guidString
36+
if success
37+
then Some guid
38+
else None
39+
else None
40+
41+
let update (m : SequencedBookmarkModel) (msg : SequencedBookmarkAction) =
42+
match msg with
43+
| SetName name ->
44+
{m with bookmark = {m.bookmark with name = name}}
45+
| SetDelay msg ->
46+
{m with delay = Numeric.update m.delay msg}
47+
| SetDuration msg ->
48+
{m with duration = Numeric.update m.duration msg}

src/PRo3D.Core/SequencedBookmarks/SequencedBookmarks-Model.fs

+25-17
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ open Chiron
1313
open System.Text.Json
1414
open Aether
1515
open Aether.Operators
16+
open System.Text.RegularExpressions
1617

1718
/// used to set whether all recorded frames should be used
1819
/// for batch rendering, or half
@@ -194,6 +195,11 @@ type SceneState =
194195
(fun (self : SceneState) -> self.stateConfig),
195196
(fun (value) (self : SceneState) -> { self with stateConfig = value })
196197
)
198+
static member surfaces_ =
199+
(
200+
(fun (self : SceneState) -> self.stateSurfaces),
201+
(fun (value) (self : SceneState) -> { self with stateSurfaces = value })
202+
)
197203
static member frustum_ =
198204
SceneState.stateConfig_
199205
>-> SceneStateViewConfig.frustumModel_
@@ -381,6 +387,8 @@ type SequencedBookmarkModel = {
381387
SequencedBookmarkModel._sceneState >?> SceneState.focalLength_
382388
static member _stateConfig =
383389
SequencedBookmarkModel._sceneState >?> SceneState.stateConfig_
390+
static member _surfaces =
391+
SequencedBookmarkModel._sceneState >?> SceneState.surfaces_
384392
static member _bookmark =
385393
(
386394
(fun (self : SequencedBookmarkModel) -> self.bookmark),
@@ -394,24 +402,12 @@ type SequencedBookmarkModel = {
394402
this.bookmark.cameraView
395403
member this.name =
396404
this.bookmark.name
397-
member this.path =
398-
match this.basePath with
399-
| Some basePath ->
400-
Path.combine
401-
[
402-
basePath
403-
this.filename
404-
]
405-
| None ->
406-
//Log.warn "[SequencedBookmarks] Bookmark has no basePath." //debugging
407-
this.filename
408-
409-
member this.filename =
410-
sprintf "%s_%s.pro3d.sbm" "SBookmark" (this.key |> string)
411-
412-
413405

414406
module SequencedBookmarkDefaults =
407+
let filenamePrefix = "SBookmark_"
408+
let filenamePostfix = ".pro3d"
409+
let filenameExtension = ".sbm"
410+
415411
let initSmoothing value =
416412
{
417413
value = value
@@ -494,6 +490,18 @@ module SequencedBookmarkModel =
494490
}
495491

496492
type SequencedBookmarkModel with
493+
member this.filename =
494+
sprintf "%s%s%s%s"
495+
SequencedBookmarkDefaults.filenamePrefix
496+
(this.key |> string)
497+
SequencedBookmarkDefaults.filenamePostfix
498+
SequencedBookmarkDefaults.filenameExtension
499+
member this.path =
500+
match this.basePath with
501+
| Some basePath ->
502+
Path.combine [basePath;this.filename]
503+
| None ->
504+
this.filename
497505
static member FromJson( _ : SequencedBookmarkModel) =
498506
json {
499507
let! v = Json.read "version"
@@ -596,7 +604,7 @@ module SequencedBookmark =
596604
|> Json.deserialize
597605
Some loadedBookmark
598606
with e ->
599-
Log.error "Error Loading Bookmark %s" m.path
607+
Log.error "[SequencedBookmarks] Error Loading Bookmark %s" m.path
600608
Log.error "%s" e.Message
601609
None
602610
| SequencedBookmark.LoadedBookmark m ->

src/PRo3D.Core/SequencedBookmarks/SequencedBookmarksApp.fs

+24-13
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,6 @@ open PRo3D.Core.BookmarkAnimations
2020
open Aether
2121
open Aether.Operators
2222

23-
module SequencedBookmark =
24-
25-
let update (m : SequencedBookmarkModel) (msg : SequencedBookmarkAction) =
26-
match msg with
27-
| SetName name ->
28-
{m with bookmark = {m.bookmark with name = name}}
29-
| SetDelay msg ->
30-
{m with delay = Numeric.update m.delay msg}
31-
| SetDuration msg ->
32-
{m with duration = Numeric.update m.duration msg}
33-
3423
module AnimationSettings =
3524
let update (m : AnimationSettings) (msg : AnimationSettingsAction) =
3625
match msg with
@@ -55,14 +44,36 @@ module AnimationSettings =
5544
let smoothingFactor = Numeric.update m.smoothingFactor msg
5645
{m with smoothingFactor = smoothingFactor}
5746

58-
59-
6047
module SequencedBookmarksApp =
6148
let mutable (snapshotProcess : option<System.Diagnostics.Process>) = None
6249

6350
let outputPath (m : SequencedBookmarks) =
6451
Path.combine [m.outputPath;"batchRendering.json"]
6552

53+
let applytoAllBookmarks (f : (SequencedBookmarkModel -> SequencedBookmarkModel))
54+
(m : SequencedBookmarks) =
55+
let bookmarks =
56+
m.bookmarks
57+
|> HashMap.map (fun id bm ->
58+
match bm with
59+
| SequencedBookmark.LoadedBookmark loadedBm ->
60+
let bm = f loadedBm
61+
SequencedBookmark.LoadedBookmark bm
62+
| SequencedBookmark.NotYetLoaded notLoadedBm ->
63+
match SequencedBookmark.tryLoad bm with
64+
| Some bm ->
65+
let bm = f bm
66+
SequencedBookmark.LoadedBookmark bm
67+
| None ->
68+
bm)
69+
{m with bookmarks = bookmarks}
70+
71+
let withSurfaceModel (surfaceModel : SurfaceModel)
72+
(m : SequencedBookmarks) =
73+
let f bm =
74+
Optic.set SequencedBookmarkModel._surfaces surfaceModel.surfaces bm
75+
applytoAllBookmarks f m
76+
6677
let update
6778
(m : SequencedBookmarks)
6879
(act : SequencedBookmarksAction)

src/PRo3D.Core/Surface/SurfaceApp.fs

+10-3
Original file line numberDiff line numberDiff line change
@@ -769,9 +769,16 @@ module SurfaceApp =
769769
| false -> None
770770
)
771771
|> List.choose( fun np -> np)
772-
match newPath.IsEmpty with
773-
| true -> s
774-
| false -> { s with importPath = newPath.Head }
772+
match newPath with
773+
| [] ->
774+
Log.line "[SurfaceApp] No correct path found in %s" (selectedPaths |> String.concat ";")
775+
s
776+
| pathsHead::pathsTail ->
777+
let names = Files.getOPCNames pathsHead
778+
{ s with importPath = pathsHead
779+
opcPaths = names |> Files.expandNamesToPaths pathsHead
780+
781+
}
775782
)
776783

777784
let flat' =

src/PRo3D.Viewer/Scene.fs

+1-3
Original file line numberDiff line numberDiff line change
@@ -85,11 +85,9 @@ module SceneLoader =
8585
let sequencedBookmarks =
8686
let basePath = PRo3D.Core.BookmarkUtils.basePathFromScenePath p
8787
BookmarkUtils.updatePaths basePath m.sequencedBookmarks
88-
{ m with surfacesModel = { m.surfacesModel with surfaces = sm }
88+
{ m with surfacesModel = { m.surfacesModel with surfaces = sm }
8989
sequencedBookmarks = sequencedBookmarks
9090
}
91-
92-
9391
| None -> m
9492

9593
let private readLine (filePath:string) =

src/PRo3D.Viewer/Viewer/Viewer.fs

+20-6
Original file line numberDiff line numberDiff line change
@@ -556,16 +556,30 @@ module ViewerApp =
556556

557557
let model = { m with scene = { m.scene with surfacesModel = s}; animations = animation}
558558

559-
let surfaceModel =
559+
let model =
560560
match msg with
561561
| SurfaceAppAction.ChangeImportDirectories _
562562
| SurfaceAppAction.ChangeOBJImportDirectories _ ->
563-
model.scene.surfacesModel
564-
|> SceneLoader.prepareSurfaceModel runtime signature model.scene.scenePath
563+
let surfacesModel =
564+
model.scene.surfacesModel
565+
|> SceneLoader.prepareSurfaceModel
566+
runtime signature model.scene.scenePath
567+
let model =
568+
Optic.set _surfacesModel surfacesModel model
569+
let sequencedBookmarks =
570+
match m.scene.sequencedBookmarks.bookmarks.IsEmpty with
571+
| true ->
572+
m.scene.sequencedBookmarks
573+
| false ->
574+
SequencedBookmarksApp.withSurfaceModel
575+
surfacesModel model.scene.sequencedBookmarks
576+
let model =
577+
Optic.set _sequencedBookmarks sequencedBookmarks model
578+
model
565579
| _ ->
566-
model.scene.surfacesModel
567-
568-
{ model with scene = { model.scene with surfacesModel = surfaceModel} }
580+
model
581+
model
582+
569583
| AnnotationMessage msg,_,_ ->
570584
match m.drawing.annotations.singleSelectLeaf with
571585
| Some selected ->

0 commit comments

Comments
 (0)