-
Notifications
You must be signed in to change notification settings - Fork 10
[DRAFT] Initial work on allowing Model to output to Data #12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Conversation
Removed Windows SDK component from setup step.
Added an example code snippet and updated Cadova version in README.
Updated image width in README example.
Adjusted image width in README example.
Updated the list of dependencies in the README. [no ci]
|
Nice. This makes sense. The main concern is the breaking change. The way the There are a few backwards-compatible options I can think of:
What do you think? |
|
I'd personally argue that a What we could do is keep the existing API and initialiser, but mark it as deprecated. This won't break existing projects, and will nudge users towards using a new initialiser then either So it'd be something like: await Model("MyCoolModel") { … } // WARNING: Deprecated. Use Model(named:) and .writeToDisk() or .generateData() instead.
let url = await Model(named: "MyCoolModel") { … }
.writeToDisk()
let fileContents = await Model(named: "MyCoolModel") { … }
.generateData()This keeps backward compatibility and moves over to giving the client choice of what happens with very minimal impact on the rest of the project. What do you think? |
|
In the vast majority of cases, writing to disk is what people need. It's the current workflow for previewing while developing a model, and it's how you get something to give a slicer to print. I designed this use case to be as lightweight as possible – just a simple call to Model with a name and the geometry in a result builder. Getting the model as data is awesome, but I'm not convinced adding boilerplate to the common case to enable it is the way to go. |
|
Ok, how about this: A new, optional parameter to the initialiser, something like So: await Model("MyCoolModel") { … } // Same behaviour and API as now
let fileContents: Data = await Model("MyCoolModel", automaticallyWritesToDisk: false) { … }
.generateData()
let url: URL = await Model("MyCoolModel", automaticallyWritesToDisk: false) { … }
.writeToDisk()The keeps the existing behaviour as the default, and adds options for those who want more control. What do you think? |
|
This looks like a good solution! 👍 |
|
Alright, I've made some changes. I'm thinking about three use cases: Question: I saw that the
Model("MyCoolModel") { … } // Will write to the current working directoryFor folks wanting more control for whatever reason, I added the method let directoryUrl: URL = …
// NOTE: This will always return `nil` if the file already exists?
let fileUrl: URL? = Model("MyCoolModel", automaticallyWriteToDisk: false) { … }
.writeToDirectory(directoryUrl)
let fileUrl: URL = … // Present a system save dialog etc
let fileName: String = fileUrl.lastPathComponent.deletingPathExtension
try Model(fileName, automaticallyWriteToDisk: false) { … }
.writeToFile(fileUrl)
let file: InMemoryFile? = try Model("MyCoolModel", automaticallyWriteToDisk: false) { … }
.generateData()
let fileName: String = file?.suggestedFileName
let fileContents: Data = file?.contentsBoth Let me know what you think. If you're happy with the code changes, I'll update all the documentation etc. |
|
I also realised I probably should've pointed this PR at |
The reason is tied to Cadova’s reveal workflow. New models are automatically revealed in the file browser only when they don’t already exist, which makes it easy to immediately open them in Cadova Viewer (or another viewer). On subsequent updates, the expectation is that the viewer reloads the existing file and we don't want to interrupt the user by revealing again. When generating via a This is also why I’ve been a bit cautious about reusing Your code looks solid. I’m still wondering whether stretching |
|
I don't really think that Ignoring preexisting API, I think a sensible design would be:
At any rate, I generally really don't think that one extra line to instruct a model to write to disk etc is enough to be considered boilerplate. Since you want to keep the existing API, that's a bit more complex since before this PR, the thing called Here's my proposal for a middle-ground:
enum DirectoryWriteResult {
case newFileWritten(URL)
case existingFileOverwritten(URL)
}
Have a think and let me know your decision. I'm happy to build this out and do all the docs etc once a concrete decision is made, and I'd love to be able to use this in my projects. |
This PR relates to issue #11.
This is early work on allowing
Modelto output to an in-memory representation rather than always to disk.Since
Model's initialiser was very side-effecty (creating an instance ofModelcreated a file on disk), this is a breaking API change. I've added two public functions:generateInMemoryFile(…) -> InMemoryFile?returns the newInMemoryFilestruct, which contains file data and a path extension.writeToFile(…) -> URL?writes to disk as before, and returns the URL to that file.I'd like feedback on this before I go further, since this breaks all existing usages of
Modeland needs a ton of documentation updates (wiki, examples, etc). I also think this change makes theisCollectingModelsflag obsolete, but I'm not super familiar with the project.Another thought I had would be to add free functions that mimic the old API, as this project does with the
Projecttype.Let me know how you feel about the proposed changes, and I'll be happy to adapt and move forward.