Is there a good way to either mimic the Save and SaveAs methods or at least influence the existing methods to inject path and filename?
I have tried using the Rhino.UI.SaveFileDialog which I can fully control the path and filename, and I have also subscribed to the Rhino.Commands.Command.BeginCommand event. Each of these pose issues I can’t seem to find my way around.
With creating a substitute dialog I then need to actually save the file itself to disk. This only seems to more-or-less operate as an export where the active document remains open and unnamed. It also relies on users remembering to use this new command in lieu of the Save and SaveAs commands.
With subscribing to the event I can run lines of code before or after the original Save or SaveAs but I see no way to provide the path and filename it uses.
Yes, I am trying to fill-in-the-blanks of the save dialog before it is shown. Both filename and save location path would need to be changed.
Per your suggestions I looked at BeginSave event but cannot yet figure out how to use the BinaryArchiveWriter. I also just looked at the WriteDocument method but at first glance the filename property is read-only there too.
So you want to, by default, whenever Save is called within Rhino, default the FileDialog to a path that you’ll determine? None of my solutions will achieve this.
I feel compelled to ask, as I want to help solve this, and avoid XY problems, why do you want to do this?
We have many Rhino users throughout many offices and would like to enforce file naming and folder structure standards. This will enable any of these users to better navigate each others projects.
I’ve had a poke around, and I can’t find anything that would do this, macros nor code-wise.
You could of course prompt users in a new, unsaved file to save it somewhere with a custom prompt that validates the name. But I don’t feel like this is a particularly good solution.
Yes, I have already written my own Save/SaveAs commands which do most of what I want. However, when I get the result of the dialog and apply them to a WriteFile/WriteDocument/Doc.Save/Doc.SaveAs it treats it more like an export leaving the original document unnamed, unsaved and active. I feel this will be very confusing to the end users who will most likely continue working in the open document which they will eventually save again and wonder what is going on.
Do you know of any way to save the active document in-place where the user can then continue working?
This is why I experimented with subscribing to the Save & SaveAs events since they already do what I want. I just merely want to front load the filename and path.
Protected Overrides Function RunCommand(ByVal doc As RhinoDoc, ByVal mode As RunMode) As Result
Dim thisSelectEnEDialog As New SelectExhibitorAndEvent
Dim thisSelectEnEDialogResult As Boolean = thisSelectEnEDialog.ShowDialog()
If thisSelectEnEDialogResult Then
' Create Directory Structure
Dim ExhibitorDir As IO.DirectoryInfo = Utilities.Directories.CreateDesignExhibitorDirs(thisSelectEnEDialog.ExhibitorName)
Dim EventDir As IO.DirectoryInfo = Utilities.Directories.CreateDesignShowDirs(ExhibitorDir, CInt(Today.ToString("yyyy")), thisSelectEnEDialog.EventName)
Dim thisActiveDoc As RhinoDoc = Rhino.RhinoDoc.ActiveDoc
Dim thisSaveDialog As New Rhino.UI.SaveFileDialog With {
.Title = "Smart Save",
.DefaultExt = "3dm",
.Filter = ".3dm",
.InitialDirectory = EventDir.FullName & "\3D Design",
.FileName = thisSelectEnEDialog.EventName & "_" & "V1"
}
If thisSaveDialog.ShowSaveDialog() Then
Dim SaveScript As String = "_-SaveAs """ & thisSaveDialog.FileName.Substring(0, thisSaveDialog.FileName.Length - 4) & """"
Rhino.RhinoApp.RunScript(SaveScript, True)
RhinoApp.WriteLine("New file saved.")
End If
End If
Return Result.Success
End Function
The SaveScript variable returns the following:
"_-SaveAs ""\\det-fs3\Design\Client\Exhibitor\1_Shows and Events\2022-2023\Show Name 2023\3D Design\Show Name 2023_V1"""
However, it does not save the file. No feedback or errors either.
If I open Rhino manually and run _-SaveAs and paste the below excerpt of that string it works fine.
"\\det-fs3\Design\Client\Exhibitor\1_Shows and Events\2022-2023\Show Name 2023\3D Design\Show Name 2023_V1"
Also, if I hardcode the path it works. It just doesn’t seem to like a concatenated string.
I then tried testing for finding that extension and rooted path with the System.IO.Path tests you suggested. - No difference.
I also replaced the manual double quotes with Char(34) - no difference.
Lastly, I mapped the network drive to replace UNC path - no difference.
If I programmatically run a script with a path it simply ignores it and fails. If I paste _-SaveAs and then separately paste the single-quoted path into Rhino’s command line the file saves as expected.
Will you please attempt this last test from your end and see if you get the same result?
"_-SaveAs ""C:\Test\File Name.3dm"""
Sorry to be a pest, but I have run out of ideas on my end.
it must be something related to string manipulation/escaping in vb or the rhino save file dialog; try this in your python editor just to prove that scripting SaveAs works fine in your environment
import Rhino
import System
sfd = System.Windows.Forms.SaveFileDialog()
if sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK:
# split the path and put it back together just to prove it works fine
dir = System.IO.Path.GetDirectoryName(sfd.FileName)
file = System.IO.Path.GetFileName(sfd.FileName)
path = System.IO.Path.Combine(dir, file)
Rhino.RhinoApp.RunScript('-_SaveAs "' + path + '"', True)
The python script you provided runs fine and the file saves as expected.
I noticed a slight difference in your example so I tried switching from two double quotes to two single quotes - no difference.
I even tried switching over to the Windows form in lieu of the Rhino one - no difference.
Protected Overrides Function RunCommand(ByVal doc As RhinoDoc, ByVal mode As RunMode) As Result
Dim thisSelectEnEDialog As New SelectExhibitorAndEvent
Dim thisSelectEnEDialogResult As Boolean = thisSelectEnEDialog.ShowDialog()
If thisSelectEnEDialogResult Then
' Create Directory Structure
Dim ExhibitorDir As IO.DirectoryInfo = Utilities.Directories.CreateDesignExhibitorDirs(thisSelectEnEDialog.ExhibitorName)
Dim EventDir As IO.DirectoryInfo = Utilities.Directories.CreateDesignShowDirs(ExhibitorDir, CInt(Today.ToString("yyyy")), thisSelectEnEDialog.EventName)
Dim thisActiveDoc As RhinoDoc = Rhino.RhinoDoc.ActiveDoc
Dim thisDate As String = Today.ToString("yyyyMMdd")
Dim thisSaveFileDialog As New System.Windows.Forms.SaveFileDialog With {
.Title = "Smart Save",
.DefaultExt = "3dm",
.Filter = "Rhino files (*.3dm)|*.3dm|All files (*.*)|*.*",
.InitialDirectory = EventDir.FullName & "\3D Design",
.FileName = thisDate & "_" & thisSelectEnEDialog.EventName & "_" & "V1"
}
If thisSaveFileDialog.ShowDialog() = Windows.Forms.DialogResult.OK Then
Dim thisDir As String = System.IO.Path.GetDirectoryName(thisSaveFileDialog.FileName)
Dim thisFileName As String = System.IO.Path.GetFileName(thisSaveFileDialog.FileName)
Dim thisPath As String = System.IO.Path.Combine(thisDir, thisFileName)
Dim SaveScript As String = "_-SaveAs """ & thisPath & """"
Rhino.RhinoApp.RunScript(SaveScript, True)
End If
End If
Return Result.Success
End Function
While doing so I noticed that your script uses -_SaveAs (dash, then underscore) rather than _-SaveAs (underscore, then dash). Tried it - no difference.
I then created a new command and narrowed it down to just the scripting portion.
Protected Overrides Function RunCommand(ByVal doc As RhinoDoc, ByVal mode As RunMode) As Result
Dim SaveScriptHC As String = "_-SaveAs ""C:\Test\File Name.3dm"""
Rhino.RhinoApp.RunScript(SaveScriptHC, True)
' TODO: complete command.
Return Result.Success
End Function
it’s been a very long time since touched vb so I can’t comment much on that, but I would just focus on using the last command example you gave to get the command to work, and then go from there
I use the _ to make sure I am calling SaveAs by its english command name, so the dash goes before it; on an english system I guess it will work either way, with the underscore just being pointless (a rhino dev could comment in more detail on this)
beyond that, I would just say to remove variables by confirming you are writing to a path where you have permission (try writing a text file there directly, from code, but not by asking rhino to do it), and remove extra directories & spaces from the filename
I don’t find reason to raise suspicion of of any vb-specific limitation, since this all compiles to IL and gets executed by the framework