-
Notifications
You must be signed in to change notification settings - Fork 178
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
new release has customiser UI #61
Comments
Excellent! I haven't looked into this yet, but I've been wanting some better interactivity for a long time. I'll see what I can figure out there, and if you've got any code suggestions, I'd love to hear them. Cheers! |
For future reference: docs for customizer syntax here: |
Looks like this shouldn't be too hard to do. My initial thought is something like: from solid import *
cube_width = ScadSlider(default=5, min=1, max=20, description="Cube Width Label")
c = cube(size=[cube_width, 5, 5,])
print(scad_render(c))
# yields:
'''
// Cube Width Label
cube_width = 5; // [1:20]
cube(size=[cube_width, 5, 5]);
''' The following classes should cover what's in the current docs: ScadComboBox( list_or_dict)
ScadSlider()
ScadCheckbox()
ScadSpinbox()
ScadTextBox()
ScadVector() Not quite sure how to handle code that involves actions on these adjustable parameters, like:
Subclassing |
How about - create a new special_named variable if there was any complex usage of a variable - then use that new name instead. e.g. in above example - new variable There is a python program that does this called rope which can do code refactoring automagically. Check out a related github project I started here for micropython (unfinished and languishing I admit)
|
Some things just aren't possible - if n_sides is a customizer value, then there's no way to (say) let python loop up to n_sides without rerunning python every time the customizer is tweaked. Since SolidPython doesn't generate loops (it doesn't normally need to) this makes customizer variables fundamentally less useful in SolidPython. Nevertheless, basic support could be had by allowing OpenSCAD expressions to be formed: say a CustomizerExpression class so that doing 2 * x generates the OpenSCAD expression "2 * (whatever is in x)". Fundamentally interactivity is going to require rerunning python code, so it's in the domain of making python code interactive. I know IPython notebooks provide some features to allow web controls in cells to set variables for python. With suitable hackery these could be connected up to generate OpenSCAD scripts, and the autoreload could handle updating the rendered object, |
I don't see any particular problem with running the python over and over and over again. Because SP is just doing some fancy string manipulation, it's rare for even big complex models to take more than a half- second or so to run. Not to say that it wouldn't be nice if we could avoid doing that, but changes like that would require a significant architectural change that's not entirely clear to me. I think your IPython notebook example is a great way to go, @aarchiba; it would be cross-platform and wouldn't require much in the way of widget programming, which is appealing. Probably not going to get to that in the next couple months, but I think it would be a great addition to the project and I hope to have some time to spend on it in the autumn if nobody's beaten me to it |
I would suggest the following: #test.py
from solid import *
outer_radius = 5
inner_radius = 2
thickness = 3
def customized_washer():
washer = cylinder(outer_radius, thickness) - cylinder(inner_radius, thickness + 1).down(0.5)
return washer #some customizer interface (-> python shell for now ;)
>>> import test
>>> test.outer_radius=20
>>> test.inner_radius=16
>>> test.thickness = 4
>>> test.customized_washer()
difference() {
cylinder(h = 4, r = 20);
translate(v = [0, 0, -0.5000000000]) {
cylinder(h = 5, r = 16);
}
}
>>> test.customized_washer().save_as_scad() #updates OpenSCAD preview
'/home/xxx/xxx/SolidPython/solid/examples/customize/expsolid_out.scad'
>>> test.outer_radius=8
>>> test.inner_radius=4
>>> test.thickness = 2
>>> test.customized_washer()
difference() {
cylinder(h = 2, r = 8);
translate(v = [0, 0, -0.5000000000]) {
cylinder(h = 3, r = 4);
}
}
>>> test.customized_washer().save_as_scad() #updates OpenSCAD preview
'/home/xxx/xxx/SolidPython/solid/examples/customize/expsolid_out.scad'
>>> (This was tested with This is the command line version of a customizer. If you want a GUI, you could implement a solid-customizer-gui that might use outer_radius = 5 #slider[1, 20,1]
#or
outer_radius = customizerGUI.getSliderValue("outer_radius", min=1, max=20, step=1) or similar, I think this should be possible to implement. As far as I understand the whole system I don't think it's possible to interact between OpenSCAD and (Solid)Python on a code-level (sharing variables). Therefor I see OpenSCAD only as a "backend" for SolidPython which could actually be replaced (by ImplicitCAD or any csg library). As such I think if SolidPython wants to provide features like a customizer or animated scenes it would have to implement them on it's own and keep using OpenSCAD as backend for processing the resulting csg tree (actually that's how SolidPython uses OpenSCAD and I guess(!) -- any way of trying to overcome this barrier will become a hassle and will not be scalable properly. You will for example have a lot of restrictions. With this solution you can do anything, you can pass the customized variables into any python functions and do whatever you. This solution is perfectly scalable to really large projects. You could have a config.py which configures a whole printer design (that's how Joseph Prusa did it for the I3, c.f. https://github.com/josefprusa/Prusa3/blob/master/box_frame/configuration.scad.dist). #config.py
outer_radius = 5
inner_radius = 2
thickness = 3 #test.py
from solid import *
import config
def customized_washer():
washer = cylinder(config.outer_radius, config.thickness) - cylinder(config.inner_radius, config.thickness + 1).down(0.5)
return washer #some customizer interface (-> python shell for now ;)
>>> import config
>>> import test
>>> config.outer_radius = 10
>>> config.inner_radius = 8
>>> config.thickness = 3
>>> test.customized_washer()
difference() {
cylinder(h = 3, r = 10);
translate(v = [0, 0, -0.5000000000]) {
cylinder(h = 4, r = 8);
}
} PS: You might get the GUI more or less for free if you use xml configuration files, because I assume there are xml editors out there that can do what you would need and you just have to add a "execute solidpython script" button ;) |
I think what I want really is a native OpenSCAD implementation of the Customizer syntax, so that generated OpenSCAD code can be changed dynamically in the OpenSCAD viewer, and so that projects created with SolidPython could be customized on Thingiverse. I have a working prototype for OpenSCAD's sliders and dropdown boxes, and I should have checkbox & spinbox variants shortly. Because the OpenSCAD customizer syntax is so minimal, that part was simple. I had to make a custom subclass of |
What do you think about this: from solid import *
# ======================================
# = this could be done in some library =
# ======================================
class CustomizerInterface:
def __init__(self):
self.header = ""
def register(self, name, value, options=''):
self.header += f'{name} = {value}; //{options}\n'
def get(self, name):
return scad_inline(name)
# ======================================
customizer = CustomizerInterface()
#register all the custom variables you want to use
customizer.register("objects", "4", "[2, 4, 6]")
customizer.register("side", "4")
customizer.register("cube_pos", "[5, 5, 5]")
customizer.register("cube_size", "5")
customizer.register("text", '"customize me!"' ,' ["customize me!", "Thank you!"]')
#use scad_inline to use them
scene = scad_inline("""
for (i = [1:objects]){
translate([2*i*side,0,0]){
cube(side);
}
}
""")
#use the customizer.get function to use them as parameters
scene += translate(customizer.get("cube_pos")) (
cube(customizer.get("cube_size")))
scene += translate([0, -20, 0]) (
text(customizer.get("text")))
scad_render_to_file(scene, file_header = customizer.header) 😃 Works great with expsolid and I think it will also work for the master. You need the |
py_factor = 2
cube_size = customizer.get(f"sin(cube_size) * {py_factor}")
scene += translate(customizer.get("cube_pos")) (
cube(cube_size)) |
cube_size = customizer.get(f"cube_size - cube_pos[0] * {py_factor}") |
The customiser-style ui is now integrated into openSCAD.
So there is apane with variables that the user can fool with interactively.
IWBNI SolidPython could support this.
What this would mean (I think):
Maybe thereis a way to tag a parameter (using @ decorator maybe?) as a group name, or interactive variable...
The text was updated successfully, but these errors were encountered: