Skip to content
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

Feature Request: Some way to inline literal OpenSCAD code #178

Open
etjones opened this issue May 30, 2021 · 2 comments
Open

Feature Request: Some way to inline literal OpenSCAD code #178

etjones opened this issue May 30, 2021 · 2 comments

Comments

@etjones
Copy link
Contributor

etjones commented May 30, 2021

With the impending arrival (fingers crossed) of Customizer support for #61, some features of SolidPython won't play nicely with customizer values. For example:

from solid import cube, scad_render_to_file
from solid.utils import right
from solid.customizer import CustomizerSliderFloat
object_count = CustomizerSlider('objects', 2, 1, 10, step=1)
side = 2
objs = [right(2*i*side)(cube(side)) for i in range(object_count)] # we want this to use a reactive slider value but it can't :-/
all_objs = union()(objs)
scad_render_to_file(all_objs, 'customizer_fail.scad')

This will create an OpenSCAD file with a slider, objects from 1 to 10. But, because the list comprehension (objs = [right(...]) happens only in Python code, the SCAD file will only use the initial value of the slider no matter how a user changes the slider in OpenSCAD.

If we want a row of cubes that reacts to the OpenSCAD slider, we need to run the object connection loop in OpenSCAD itself. One way to do this would be a dedicated scad_loop() function we could add. But we might also add a scad_inline() function that would just paste an OpenSCAD string directly into the output .scad file without translating at all. That should make us able to use Customizer values anywhere, however we like.

Proposed fix:

from solid import cube, scad_render_to_file, scad_inline
from solid.utils import right
from solid.customizer import CustomizerSliderFloat
object_count = CustomizerSlider('objects', 2, 1, 10, step=1)
side = 2
objs = scad_inline('''
for (i = [1:objects]){
    translate([2*i*side,0,0]){
        cube(side);
    }
}
''')

all_objs = union()(objs)
scad_render_to_file(all_objs, 'customizer_fail.scad')

I'm not sure how I should build this yet, but I don't think it should take too much work

@jeff-dh
Copy link
Contributor

jeff-dh commented May 31, 2021

class ConstantOpenSCADObject(OpenSCADObject):
    def __init__(self, code):
        super().__init__("not reander able", {})
        self.code = code

    def _render(self, render_holes=42):
        return self.code
 
def scad_inline(code):
    return ConstantOpenSCADObject(code)

You should be able to just plug this into your code in "user space" and use it.

This is not 100% clean, because OpenSCADObject contains a lot of stuff not needed for ConstantOpenSCADObject but since there's no other base class...... You might also leave the inheritance away and just plug a duck typing class with _render into it. (set_modifier or similar will not work with tihs, but I think it also makes not a lot sense to make it work)

Another solution could be to use py2openscad. When ever you render a child, don't call _render, but call py2openscad. If it's a OpenSCADObject it calls _render anyway but if it's just a string it return's it......... this should also work.

But I don't think you'll gain a lot with this..... I'm not really into these customizer stuff but mixing OpenSCAD and SolidPython code -- I think -- will never work properly.

Isn't this the same as if you would create a .scad file that contains:

side = customizer_stuff(....)
objects = customizer_stuff(..)

module customized_boxes()
for (i = [1:objects]){
    translate([2*i*side,0,0]){
        cube(side);
    }
}

import it with SolidPython and call customized_boxes ?

@jeff-dh
Copy link
Contributor

jeff-dh commented Feb 19, 2022

Update:

The scad_inline posted above has a minor issue.

Here's a working (but therefor hacky version):

from solid import *

class ConstantOpenSCADObject(IncludedOpenSCADObject):
    def __init__(self, code):
        self._get_include_path = lambda x : ''
        super().__init__("not reander able", {}, "blablub")
        self.include_string = ''
        self.code = " " + code + " "

    def _render(self, render_holes=42):
        return self.code
 
def scad_inline(code):
    return ConstantOpenSCADObject(code)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants