openscad / openscad

OpenSCAD - The Programmers Solid 3D CAD Modeller
https://www.openscad.org
Other
7.1k stars 1.22k forks source link

Can't overwrite Customizer values with -D #4419

Open ModischFabrications opened 2 years ago

ModischFabrications commented 2 years ago

I want to use OpenSCAD to export batches of svg's/stl's with only minor changes, based on a few premade templates.

My intuitive attempt was to create a few base formats like "wild-x" or "hex-M" from the GUI to get a baseline and overwrite/replace values via command line.

openscad -p pendant_v4.json -P hex-M -D p_char='"F"' -o tmp/hex-m.svg pendant_v4.scad

I would have expected to have p_char be "F" in my export, but it seems like the additional "-D" define is silently dropped.

ModischFabrications commented 2 years ago

Changing the order of commands (thankfully) doesn't change the order of operations. https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Using_OpenSCAD_in_a_command_line_environment offers no explanation either.

Tested on v2021.01

rcolyer commented 2 years ago

The -D command operates by appending to the end of the scad file text right after input, while the customizer inputs are designed to override the scad file settings. So yes, this is not going to work, as the designed order is the other way around.

The behavior of -D as a text append predates that customizer input capability, which is in turn emulating the way it works in the gui, so I wouldn't exactly call this a master plan for how these features interact. But the way it currently operates is at least consistent with the history (-D) and the other behaviors (the customizer values).

I will give one argument that I think is pretty strong for why -D cannot be specially parsed as overrides after the customizer. This is (and has been for a long time) a valid invocation of OpenSCAD by command line:

openscad -D "cube(5);" -o foo.png /dev/null

I'll note that this, too, was probably not exactly a master plan. But it has been possible for so long that surely someone is out there doing it.

t-paul commented 2 years ago

Yes, this would mean restricting -D to the originally intended "set variable" behavior. It would be nice to get to that, but I'm not sure the change is worth the potential breakage in command line use.

jordanbrown0 commented 2 years ago

Wouldn't it work to effectively put the JSON values after the file, then the -D values after that?

ModischFabrications commented 2 years ago

I see the historical reason and I totally get the need for compatibility, but it's not obvious from an outside perspective. Is there a recommended way to realize my workflow of "template + small changes"? I don't want to create multiple scad-files just to keep a subset of settings, but I don't see another solution this obvious. If this is something that won't be changed it should imho get some kind of feedback and/or documentation, similar to the "invalid string"-ones.

rcolyer commented 2 years ago

Is there a recommended way to realize my workflow of "template + small changes"? I don't want to create multiple scad-files just to keep a subset of settings, but I don't see another solution this obvious.

Well I would say either all json or all -D. Here's an example of in-place converting the json to all -D format, after which you can override it with an additional -D entry. (Caveat, I tested this on one randomly selected file with a bunch of parameters, and cannot guarantee it is correct for all customizer types. But if not, it is hopefully at least a close model of a general solution.)

openscad -o tmp/hex-m.svg -D"$(cat pendant_v4.json | python3 -c "import json,sys;print(''.join(f'{k}={v};' for k,v in json.load(sys.stdin)['parameterSets']['design default values'].items()))")" -D 'p_char="F";' pendant_v4.scad

Note that for your particular purpose, you probably want to swap out 'design default values' with 'hex-M' and so on, which you should be able to do with a shell variable if this is convenient.

If this is something that won't be changed it should imho get some kind of feedback and/or documentation, similar to the "invalid string"-ones.

Yeah, probably someone should find a place to document it. Although I'm not certain yet where is the best place to reach people with this information.

Wouldn't it work to effectively put the JSON values after the file, then the -D values after that?

Current openscad.cc lines 390 ("text +=") through 415 (close of that "CommentParser::collectParameters" section). It's not obvious to me how you'd wedge it in the middle there. The parse must go first, then, the customizer update, another parse, and then some sort of back-fill of variable entries from the second parse while merging any non-variable content into the original parse? Perhaps someone can sort it out, but it doesn't look like a simple reordering.

PRouzeau commented 1 year ago

See #2037

PRouzeau commented 1 year ago

Edit: both following options don't work, but there is a solution anyway, see my last post. There is two way to have a batch parameter supersede the customizer parameter

1/ Make you variable a ‘special’ variable prefixed with $ (tested, this is a real command)

Work :

openscad -o DXF/Parts_MyZNC_19_Beams.dxf  -p Znc.json -P "MyZNC"  -D '$part=19' Znc.scad 

Don’t work :

openscad -o DXF/Parts_MyZNC_19_Beams.dxf  -p Znc.json -P "MyZNC"  -D 'part=19' Znc.scad

2/ Using specific variable for the batch which supersedes the recorded variables – not tested

So, by example for a part selector, the value recorded in the GUI is ‘gpart’, which will be supersed by another variable only defined in the batch command ‘bpart’

gpart = 18;  //Recorded in customizer, so cannot be superseded in batch
part =!is_undef(bpart)&&bpart?bpart:gpart;  // bpart will supersede gpart if it exists

The is_undef() test avoid the warnings as the allocation is decided as soon as the variable is detected non existing. the '&&bpart' may not be needed, it only prevent reallocation if the batch variable is empty but you may want to have empty variables.

The batch command will so be and the 19th part will replace the 18th....

openscad -o DXF/Parts_MyZNC_19_Beams.dxf  -p Znc.json -P "MyZNC"  -D 'bpart=19' Znc.scad

ModischFabrications commented 1 year ago

Thanks for the hint, will try out when I continue the project. Am I still able to omit the variables and only use the ones defined in the customizer with the other syntax, being an optional overwrite? Is that a feature of a newer version (that I need to update to) or is it a feature that was already working in the old/current version?

PRouzeau commented 1 year ago

Yes, if you don't declare variables in the batch command, they will default on customizer value. First (using special variables) is working on 2021.01 version, not tested on nightly/dev version but I am confident it may work. For the second, it will work if the is_undef() function exist. This function is used to stop warnings since they were implemented, most probably this function won't disappear.

PRouzeau commented 1 year ago

Ooops, none of the proposed option works :( It was probably working the first time for me because I didn’t save the dataset after changing the variable name, so the new name being not yet recorded in the dataset, everything was working fine...

I was needing it to work, so after some trials, what finally work is in fact more simple than that. I discovered than you can surcharge an allocation not only done with a literal but with another variable. Tested in 2021.01

So if you create a variable recorded in customizer, then allocate it to another variable, this second variable not recorded in dataset can be superseded by batch command (here 'cust_part' is recorded by customizer but 'part' is not recorded):

cust_part = 1; // [0:ensemble, 1:part1, 2:part2, 3:part3]
part = cust_part;

if (part==0) {...}
else if (part==1) {...}
…
else if (part==3) {...}

The batch command could then be like (here « MyZNC » is the dataset name):

openscad -o Mypart_03.stl  -p Znc.json -P "MyZNC"  -D part=3 Znc.scad

Also, remember that variable in the [Hidden] tab are not recorded by customizer, this may help.