Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions README.md
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
# Changes on this fork

This framework is an awesome project from Axford, but it appears to have been abandoned, at least it's not been worked on since 2016 or so (it's now Jan 2019). Original was written for Python 2, and assumed Unix (or Mac?) conventions. I've updated it to work with Python 3 (only tested with 3.6.5) and made some changes to make it work on Windows.

**Note**: I have not tested this extensively. I've only used it with Python 3.6.5 on Win10, and don't know if I broke anything for other platforms. I'm also quite new to using it, so there may be use cases that don't currently work (sadly, the tutorial only has part 1) If you find any bugs, please open an issue, I'll try to take a look.

Everythng below is from the original project.

# OpenSCAD for Machine Design framework

## Overview
Expand Down
4 changes: 2 additions & 2 deletions scripts/adda.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -77,7 +77,7 @@ def adda(t, n, d):
o.write("include <"+incFile+">\n")

else:
print(templateFile + " template is missing")
print((templateFile + " template is missing"))

# Sandbox
templateFile = os.path.join(config.paths['template'],"sandbox","sandbox.scad")
Expand All@@ -93,7 +93,7 @@ def adda(t, n, d):
o.write(s)

else:
print(templateFile + " template is missing")
print((templateFile + " template is missing"))


if __name__ == '__main__':
Expand Down
20 changes: 10 additions & 10 deletions scripts/animate.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -57,8 +57,8 @@ def animateAssembly(mname, aname, prefix, framesPerStep):

# locate required machine
for m in jso:
if type(m) is DictType and m['type'] == 'machine' and m['title'] == mname:
print("Found machine: "+m['title'])
if type(m) is dict and m['type'] == 'machine' and m['title'] == mname:
print(("Found machine: "+m['title']))

al = m['assemblies']

Expand All@@ -70,7 +70,7 @@ def animateAssembly(mname, aname, prefix, framesPerStep):
# locate required assembly
for a in al:
if a['title'] == aname:
print("Found assembly: "+a['title'])
print(("Found assembly: "+a['title']))
fn = config.paths['root'] + a['file']
if (os.path.isfile(fn)):

Expand All@@ -94,7 +94,7 @@ def animateAssembly(mname, aname, prefix, framesPerStep):
}
firstView = True
for step in a['steps']:
print("Step: "+str(step['num']))
print(("Step: "+str(step['num'])))

# generate a transition move?
if len(step['views']) > 0:
Expand DownExpand Up@@ -177,7 +177,7 @@ def animateAssembly(mname, aname, prefix, framesPerStep):
views.PolishTransparentBackground = False
views.PolishCrop = False
fn = view_dir + "/" +prefix + format(frameNum, '03') + "_" +view['title']+".png"
print("Rendering: "+fn)
print(("Rendering: "+fn))
views.render_view_using_file(prefix + format(frameNum, '03'), config.paths['tempscad'], view_dir, view, hashchanged, h)
frameNum = frameNum + 1

Expand All@@ -199,7 +199,7 @@ def animateAssembly(mname, aname, prefix, framesPerStep):
alpha = extra / (1.0*framesPerStep)
if (alpha > 1.0):
alpha = 1.0
print("Blending: "+str(alpha) +", "+str(frameNum))
print(("Blending: "+str(alpha) +", "+str(frameNum)))
imgNew = Image.blend(imgPrev,img,alpha)

draw = ImageDraw.Draw(imgNew, "RGBA")
Expand All@@ -219,7 +219,7 @@ def animateAssembly(mname, aname, prefix, framesPerStep):

fn = view_dir + "/" +prefix + format(frameNum, '03') + "_" +view['title']+".png"
frameNum = frameNum + 1
print("Saving: "+fn)
print(("Saving: "+fn))
imgNew.save(fn)

lfn = fn
Expand DownExpand Up@@ -262,12 +262,12 @@ def animateAssembly(mname, aname, prefix, framesPerStep):

# build video
cmd = "ffmpeg -r "+str(framesPerStep)+" -y -i "+view_dir + "/" + prefix+"%03d_"+view['title']+".png -vcodec libx264 -pix_fmt yuv420p "+view_dir + "/" + prefix+".mp4"
print("Encoding video with: "+cmd)
print(("Encoding video with: "+cmd))
os.system(cmd)

# build animated gif
cmd = "convert "+view_dir + "/" + prefix+".mp4 "+view_dir + "/" + prefix+".gif"
print("Creating GIF with: "+cmd)
print(("Creating GIF with: "+cmd))
os.system(cmd)

# clean up temporary images
Expand All@@ -283,7 +283,7 @@ def animateAssembly(mname, aname, prefix, framesPerStep):
print("Exception running osascript")

else:
print(" Error: scad file not found: "+a['file'])
print((" Error: scad file not found: "+a['file']))

return 0

Expand Down
12 changes: 6 additions & 6 deletions scripts/assemblies.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -34,8 +34,8 @@ def assemblies():

# for each machine
for m in jso:
if type(m) is DictType and m['type'] == 'machine':
print(m['title'])
if type(m) is dict and m['type'] == 'machine':
print((m['title']))

al = m['assemblies']

Expand All@@ -46,7 +46,7 @@ def assemblies():

# for each assembly
for a in al:
print(" "+a['title'])
print((" "+a['title']))
fn = config.paths['root'] + a['file']
if (os.path.isfile(fn)):

Expand All@@ -73,18 +73,18 @@ def assemblies():
f.close()

# Views
print(" Step "+str(step['num']))
print((" Step "+str(step['num'])))
for view in step['views']:
render_view_using_file(a['title']+'_step'+str(step['num']), config.paths['tempscad'], view_dir, view, hashchanged, h)

# for each animation
for anim in a['animations']:
print(" Animation: "+anim['title']+", framesPerStep="+str(anim['framesPerStep']))
print((" Animation: "+anim['title']+", framesPerStep="+str(anim['framesPerStep'])))

animateAssembly(m['title'], a['title'], anim['title'], anim['framesPerStep'])

else:
print(" Error: scad file not found: "+a['file'])
print((" Error: scad file not found: "+a['file']))


# Save changes to json
Expand Down
14 changes: 7 additions & 7 deletions scripts/build.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -22,15 +22,15 @@ def build(argv):
try:
opts, args = getopt.getopt(argv,"hcq",[])
except getopt.GetoptError:
print'build.py -h -c -q'
print ''
print('build.py -h -c -q')
print( '')
sys.exit(2)
for opt, arg in opts:
if opt == '-h':
print'Usage: -h -c -q'
print ''
print' -c Skip catalogue'
print ' -q Quick build - skip assemblies, guide and catalogue'
print('Usage: -h -c -q')
print('')
print(' -c Skip catalogue')
print( ' -q Quick build - skip assemblies, guide and catalogue')
sys.exit()
if opt in ("-c"):
doCatalogue = False
Expand DownExpand Up@@ -82,7 +82,7 @@ def build(argv):
print("Build Complete")

if errorlevel > 0:
print("Error: " + str(errorlevel))
print(("Error: " + str(errorlevel)))

return errorlevel

Expand Down
2 changes: 1 addition & 1 deletion scripts/c14n_stl.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -6,7 +6,7 @@
# This has no effect on the model but makes the STL consistent. I.e. it makes a canonical form.
#

from __future__ import print_function


import sys
import math
Expand Down
20 changes: 10 additions & 10 deletions scripts/catalogue.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -36,7 +36,7 @@ def output_vitamin(v):

# per view
for view in t['children']:
if type(view) is DictType and view['type'] == 'view':
if type(view) is dict and view['type'] == 'view':
md += '!['+t['title']+']('+view['png_name']+')\n'

md += '\n'
Expand DownExpand Up@@ -68,7 +68,7 @@ def compile_vitamin(v, dom):
os.makedirs(config.paths['vitaminsimages'])

# Compile
print(" "+v['title'])
print((" "+v['title']))
fn = '../' + v['file']
if (os.path.isfile(fn)):

Expand All@@ -84,8 +84,8 @@ def compile_vitamin(v, dom):
# Views
print(" Views")
for view in v['children']:
if type(view) is DictType and view['type'] == 'view':
print(" "+view['title'])
if type(view) is dict and view['type'] == 'view':
print((" "+view['title']))

render_view(v['title'], v['call'], config.paths['vitaminsimages'], view, hashchanged, h, [fn], False, useVitaminSTL=False)

Expand All@@ -96,14 +96,14 @@ def compile_vitamin(v, dom):


else:
print(" Error: scad file not found: "+v['file'])
print((" Error: scad file not found: "+v['file']))


def parse_vitamin(vitaminscad, use_catalogue_call=False):

vitamincall = vitaminscad[:-5];

print(" Calling: "+ vitamincall + "();")
print((" Calling: "+ vitamincall + "();"))

# Generate a wrapper scad file for the vitamin file
with open(config.paths['tempscad'], "w") as f:
Expand DownExpand Up@@ -157,7 +157,7 @@ def parse_vitamin(vitaminscad, use_catalogue_call=False):
js = json.dumps(jso, sort_keys=False, indent=4, separators=(',', ': '))

except Exception as e:
print(" "+e)
print((" "+e))
# Stop malformed machine json screwing up everything else!
js = ''

Expand DownExpand Up@@ -185,7 +185,7 @@ def catalogue():

for filename in os.listdir(config.paths['vitamins']):
if filename[-5:] == '.scad':
print(" Parsing: "+filename)
print((" Parsing: "+filename))

s = ''

Expand DownExpand Up@@ -225,12 +225,12 @@ def catalogue():
try:
jso = json.loads(js)

print("Parsed "+str(files)+" vitamin files")
print(("Parsed "+str(files)+" vitamin files"))

dom = {'vitamins':[]}

for v in jso:
if type(v) is DictType and v['type'] == 'vitamin':
if type(v) is dict and v['type'] == 'vitamin':
try:
compile_vitamin(v, dom)
except Exception as e:
Expand Down
10 changes: 5 additions & 5 deletions scripts/cut.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -33,8 +33,8 @@ def cut():

# for each machine
for m in jso:
if type(m) is DictType and m['type'] == 'machine':
print(m['title'])
if type(m) is dict and m['type'] == 'machine':
print((m['title']))

al = m['cut']

Expand All@@ -43,7 +43,7 @@ def cut():
os.makedirs(config.paths['cutpartsimages'])

for a in al:
print(" "+a['title'])
print((" "+a['title']))
fn = config.paths['root'] + a['file']
if (os.path.isfile(fn)):

Expand DownExpand Up@@ -81,13 +81,13 @@ def cut():
f.close()

# Views
print(" Step "+str(step['num']))
print((" Step "+str(step['num'])))
for view in step['views']:
render_view_using_file(a['title']+'_step'+str(step['num']), config.paths['tempscad'], config.paths['cutpartsimages'], view, hashchanged, h)


else:
print(" Error: scad file not found: "+a['file'])
print((" Error: scad file not found: "+a['file']))


# Save changes to json
Expand Down
22 changes: 11 additions & 11 deletions scripts/guides.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -215,7 +215,7 @@ def assembly_level(a):


def gen_assembly_guide(m, guide_template):
print(m['title'])
print((m['title']))

md = ''

Expand All@@ -224,7 +224,7 @@ def gen_assembly_guide(m, guide_template):

# machine views
for c in m['children']:
if type(c) is DictType and c['type'] == 'view' and 'filepath' in c:
if type(c) is dict and c['type'] == 'view' and 'filepath' in c:
view = c
md += '!['+view['caption']+']('+ view['filepath'][3:] +')\n\n'

Expand DownExpand Up@@ -273,7 +273,7 @@ def gen_assembly_guide(m, guide_template):


def gen_printing_guide(m, guide_template):
print(m['title'])
print((m['title']))

if len(m['printed']) == 0:
return {};
Expand DownExpand Up@@ -347,29 +347,29 @@ def gen_printing_guide(m, guide_template):


def load_sources():
print"Loading sourcing info..."
print("Loading sourcing info...")

load_source(config.paths['sourcingcsv'])

for filename in os.listdir(config.paths['vitamins']):
if filename[-4:] == '.csv':
print(" Parsing: "+filename)
print((" Parsing: "+filename))
csvfn = os.path.join(src_dir, filename)
load_source(csvfn)

def load_source(csvfn):
if os.path.isfile(csvfn):
with open(csvfn, 'rb') as csvfile:
with open(csvfn, 'r') as csvfile:
rdr = csv.DictReader(csvfile)
for row in rdr:
vn = row['Vitamin']
vn = row.get('Vitamin');
if vn not in sourcing:
sourcing[vn] = []
sourcing[vn].append({"Cost":row['Cost'], "Source":row['Source'], 'Notes':row['Notes']});
sourcing[vn].append({"Cost":row.get('Cost'), "Source":row.get('Source'), 'Notes':row.get('Notes')});


def gen_sourcing_guide(m, guide_template):
print(m['title'])
print((m['title']))

if len(m['vitamins']) == 0:
return {};
Expand DownExpand Up@@ -469,7 +469,7 @@ def gen_index(jso, index_file, index_template):
# build object
indexObj = { 'machines': [], 'project':'' };
for m in jso:
if type(m) is DictType and m['type'] == 'machine':
if type(m) is dict and m['type'] == 'machine':

# tack in a view filename
m['viewFilename'] = views.view_filename(m['title'] + '_view')
Expand DownExpand Up@@ -527,7 +527,7 @@ def guides():

# for each machine
for m in jso:
if type(m) is DictType and m['type'] == 'machine':
if type(m) is dict and m['type'] == 'machine':

if 'guides' not in m:
m['guides'] = []
Expand Down
2 changes: 1 addition & 1 deletion scripts/jsontools.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -11,7 +11,7 @@ def json_merge_missing_keys(j1, j2, overwrite=False, exclude=[]):
def get_child_by_key_values(j1, kvs={}):
if 'children' in j1:
for c in j1['children']:
if type(c) is DictType:
if type(c) is dict:
match = True
for kv in kvs:
if not (kv in c and c[kv] == kvs[kv]):
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions README.md
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
# Changes on this fork

This framework is an awesome project from Axford, but it appears to have been abandoned, at least it's not been worked on since 2016 or so (it's now Jan 2019). Original was written for Python 2, and assumed Unix (or Mac?) conventions. I've updated it to work with Python 3 (only tested with 3.6.5) and made some changes to make it work on Windows.

**Note**: I have not tested this extensively. I've only used it with Python 3.6.5 on Win10, and don't know if I broke anything for other platforms. I'm also quite new to using it, so there may be use cases that don't currently work (sadly, the tutorial only has part 1) If you find any bugs, please open an issue, I'll try to take a look.

Everythng below is from the original project.

# OpenSCAD for Machine Design framework

## Overview
Expand Down
4 changes: 2 additions & 2 deletions scripts/adda.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -77,7 +77,7 @@ def adda(t, n, d):
o.write("include <"+incFile+">\n")

else:
print(templateFile + " template is missing")
print((templateFile + " template is missing"))

# Sandbox
templateFile = os.path.join(config.paths['template'],"sandbox","sandbox.scad")
Expand All@@ -93,7 +93,7 @@ def adda(t, n, d):
o.write(s)

else:
print(templateFile + " template is missing")
print((templateFile + " template is missing"))


if __name__ == '__main__':
Expand Down
20 changes: 10 additions & 10 deletions scripts/animate.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -57,8 +57,8 @@ def animateAssembly(mname, aname, prefix, framesPerStep):

# locate required machine
for m in jso:
if type(m) is DictType and m['type'] == 'machine' and m['title'] == mname:
print("Found machine: "+m['title'])
if type(m) is dict and m['type'] == 'machine' and m['title'] == mname:
print(("Found machine: "+m['title']))

al = m['assemblies']

Expand All@@ -70,7 +70,7 @@ def animateAssembly(mname, aname, prefix, framesPerStep):
# locate required assembly
for a in al:
if a['title'] == aname:
print("Found assembly: "+a['title'])
print(("Found assembly: "+a['title']))
fn = config.paths['root'] + a['file']
if (os.path.isfile(fn)):

Expand All@@ -94,7 +94,7 @@ def animateAssembly(mname, aname, prefix, framesPerStep):
}
firstView = True
for step in a['steps']:
print("Step: "+str(step['num']))
print(("Step: "+str(step['num'])))

# generate a transition move?
if len(step['views']) > 0:
Expand DownExpand Up@@ -177,7 +177,7 @@ def animateAssembly(mname, aname, prefix, framesPerStep):
views.PolishTransparentBackground = False
views.PolishCrop = False
fn = view_dir + "/" +prefix + format(frameNum, '03') + "_" +view['title']+".png"
print("Rendering: "+fn)
print(("Rendering: "+fn))
views.render_view_using_file(prefix + format(frameNum, '03'), config.paths['tempscad'], view_dir, view, hashchanged, h)
frameNum = frameNum + 1

Expand All@@ -199,7 +199,7 @@ def animateAssembly(mname, aname, prefix, framesPerStep):
alpha = extra / (1.0*framesPerStep)
if (alpha > 1.0):
alpha = 1.0
print("Blending: "+str(alpha) +", "+str(frameNum))
print(("Blending: "+str(alpha) +", "+str(frameNum)))
imgNew = Image.blend(imgPrev,img,alpha)

draw = ImageDraw.Draw(imgNew, "RGBA")
Expand All@@ -219,7 +219,7 @@ def animateAssembly(mname, aname, prefix, framesPerStep):

fn = view_dir + "/" +prefix + format(frameNum, '03') + "_" +view['title']+".png"
frameNum = frameNum + 1
print("Saving: "+fn)
print(("Saving: "+fn))
imgNew.save(fn)

lfn = fn
Expand DownExpand Up@@ -262,12 +262,12 @@ def animateAssembly(mname, aname, prefix, framesPerStep):

# build video
cmd = "ffmpeg -r "+str(framesPerStep)+" -y -i "+view_dir + "/" + prefix+"%03d_"+view['title']+".png -vcodec libx264 -pix_fmt yuv420p "+view_dir + "/" + prefix+".mp4"
print("Encoding video with: "+cmd)
print(("Encoding video with: "+cmd))
os.system(cmd)

# build animated gif
cmd = "convert "+view_dir + "/" + prefix+".mp4 "+view_dir + "/" + prefix+".gif"
print("Creating GIF with: "+cmd)
print(("Creating GIF with: "+cmd))
os.system(cmd)

# clean up temporary images
Expand All@@ -283,7 +283,7 @@ def animateAssembly(mname, aname, prefix, framesPerStep):
print("Exception running osascript")

else:
print(" Error: scad file not found: "+a['file'])
print((" Error: scad file not found: "+a['file']))

return 0

Expand Down
12 changes: 6 additions & 6 deletions scripts/assemblies.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -34,8 +34,8 @@ def assemblies():

# for each machine
for m in jso:
if type(m) is DictType and m['type'] == 'machine':
print(m['title'])
if type(m) is dict and m['type'] == 'machine':
print((m['title']))

al = m['assemblies']

Expand All@@ -46,7 +46,7 @@ def assemblies():

# for each assembly
for a in al:
print(" "+a['title'])
print((" "+a['title']))
fn = config.paths['root'] + a['file']
if (os.path.isfile(fn)):

Expand All@@ -73,18 +73,18 @@ def assemblies():
f.close()

# Views
print(" Step "+str(step['num']))
print((" Step "+str(step['num'])))
for view in step['views']:
render_view_using_file(a['title']+'_step'+str(step['num']), config.paths['tempscad'], view_dir, view, hashchanged, h)

# for each animation
for anim in a['animations']:
print(" Animation: "+anim['title']+", framesPerStep="+str(anim['framesPerStep']))
print((" Animation: "+anim['title']+", framesPerStep="+str(anim['framesPerStep'])))

animateAssembly(m['title'], a['title'], anim['title'], anim['framesPerStep'])

else:
print(" Error: scad file not found: "+a['file'])
print((" Error: scad file not found: "+a['file']))


# Save changes to json
Expand Down
14 changes: 7 additions & 7 deletions scripts/build.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -22,15 +22,15 @@ def build(argv):
try:
opts, args = getopt.getopt(argv,"hcq",[])
except getopt.GetoptError:
print'build.py -h -c -q'
print ''
print('build.py -h -c -q')
print( '')
sys.exit(2)
for opt, arg in opts:
if opt == '-h':
print'Usage: -h -c -q'
print ''
print' -c Skip catalogue'
print ' -q Quick build - skip assemblies, guide and catalogue'
print('Usage: -h -c -q')
print('')
print(' -c Skip catalogue')
print( ' -q Quick build - skip assemblies, guide and catalogue')
sys.exit()
if opt in ("-c"):
doCatalogue = False
Expand DownExpand Up@@ -82,7 +82,7 @@ def build(argv):
print("Build Complete")

if errorlevel > 0:
print("Error: " + str(errorlevel))
print(("Error: " + str(errorlevel)))

return errorlevel

Expand Down
2 changes: 1 addition & 1 deletion scripts/c14n_stl.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -6,7 +6,7 @@
# This has no effect on the model but makes the STL consistent. I.e. it makes a canonical form.
#

from __future__ import print_function


import sys
import math
Expand Down
20 changes: 10 additions & 10 deletions scripts/catalogue.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -36,7 +36,7 @@ def output_vitamin(v):

# per view
for view in t['children']:
if type(view) is DictType and view['type'] == 'view':
if type(view) is dict and view['type'] == 'view':
md += '!['+t['title']+']('+view['png_name']+')\n'

md += '\n'
Expand DownExpand Up@@ -68,7 +68,7 @@ def compile_vitamin(v, dom):
os.makedirs(config.paths['vitaminsimages'])

# Compile
print(" "+v['title'])
print((" "+v['title']))
fn = '../' + v['file']
if (os.path.isfile(fn)):

Expand All@@ -84,8 +84,8 @@ def compile_vitamin(v, dom):
# Views
print(" Views")
for view in v['children']:
if type(view) is DictType and view['type'] == 'view':
print(" "+view['title'])
if type(view) is dict and view['type'] == 'view':
print((" "+view['title']))

render_view(v['title'], v['call'], config.paths['vitaminsimages'], view, hashchanged, h, [fn], False, useVitaminSTL=False)

Expand All@@ -96,14 +96,14 @@ def compile_vitamin(v, dom):


else:
print(" Error: scad file not found: "+v['file'])
print((" Error: scad file not found: "+v['file']))


def parse_vitamin(vitaminscad, use_catalogue_call=False):

vitamincall = vitaminscad[:-5];

print(" Calling: "+ vitamincall + "();")
print((" Calling: "+ vitamincall + "();"))

# Generate a wrapper scad file for the vitamin file
with open(config.paths['tempscad'], "w") as f:
Expand DownExpand Up@@ -157,7 +157,7 @@ def parse_vitamin(vitaminscad, use_catalogue_call=False):
js = json.dumps(jso, sort_keys=False, indent=4, separators=(',', ': '))

except Exception as e:
print(" "+e)
print((" "+e))
# Stop malformed machine json screwing up everything else!
js = ''

Expand DownExpand Up@@ -185,7 +185,7 @@ def catalogue():

for filename in os.listdir(config.paths['vitamins']):
if filename[-5:] == '.scad':
print(" Parsing: "+filename)
print((" Parsing: "+filename))

s = ''

Expand DownExpand Up@@ -225,12 +225,12 @@ def catalogue():
try:
jso = json.loads(js)

print("Parsed "+str(files)+" vitamin files")
print(("Parsed "+str(files)+" vitamin files"))

dom = {'vitamins':[]}

for v in jso:
if type(v) is DictType and v['type'] == 'vitamin':
if type(v) is dict and v['type'] == 'vitamin':
try:
compile_vitamin(v, dom)
except Exception as e:
Expand Down
10 changes: 5 additions & 5 deletions scripts/cut.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -33,8 +33,8 @@ def cut():

# for each machine
for m in jso:
if type(m) is DictType and m['type'] == 'machine':
print(m['title'])
if type(m) is dict and m['type'] == 'machine':
print((m['title']))

al = m['cut']

Expand All@@ -43,7 +43,7 @@ def cut():
os.makedirs(config.paths['cutpartsimages'])

for a in al:
print(" "+a['title'])
print((" "+a['title']))
fn = config.paths['root'] + a['file']
if (os.path.isfile(fn)):

Expand DownExpand Up@@ -81,13 +81,13 @@ def cut():
f.close()

# Views
print(" Step "+str(step['num']))
print((" Step "+str(step['num'])))
for view in step['views']:
render_view_using_file(a['title']+'_step'+str(step['num']), config.paths['tempscad'], config.paths['cutpartsimages'], view, hashchanged, h)


else:
print(" Error: scad file not found: "+a['file'])
print((" Error: scad file not found: "+a['file']))


# Save changes to json
Expand Down
22 changes: 11 additions & 11 deletions scripts/guides.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -215,7 +215,7 @@ def assembly_level(a):


def gen_assembly_guide(m, guide_template):
print(m['title'])
print((m['title']))

md = ''

Expand All@@ -224,7 +224,7 @@ def gen_assembly_guide(m, guide_template):

# machine views
for c in m['children']:
if type(c) is DictType and c['type'] == 'view' and 'filepath' in c:
if type(c) is dict and c['type'] == 'view' and 'filepath' in c:
view = c
md += '!['+view['caption']+']('+ view['filepath'][3:] +')\n\n'

Expand DownExpand Up@@ -273,7 +273,7 @@ def gen_assembly_guide(m, guide_template):


def gen_printing_guide(m, guide_template):
print(m['title'])
print((m['title']))

if len(m['printed']) == 0:
return {};
Expand DownExpand Up@@ -347,29 +347,29 @@ def gen_printing_guide(m, guide_template):


def load_sources():
print"Loading sourcing info..."
print("Loading sourcing info...")

load_source(config.paths['sourcingcsv'])

for filename in os.listdir(config.paths['vitamins']):
if filename[-4:] == '.csv':
print(" Parsing: "+filename)
print((" Parsing: "+filename))
csvfn = os.path.join(src_dir, filename)
load_source(csvfn)

def load_source(csvfn):
if os.path.isfile(csvfn):
with open(csvfn, 'rb') as csvfile:
with open(csvfn, 'r') as csvfile:
rdr = csv.DictReader(csvfile)
for row in rdr:
vn = row['Vitamin']
vn = row.get('Vitamin');
if vn not in sourcing:
sourcing[vn] = []
sourcing[vn].append({"Cost":row['Cost'], "Source":row['Source'], 'Notes':row['Notes']});
sourcing[vn].append({"Cost":row.get('Cost'), "Source":row.get('Source'), 'Notes':row.get('Notes')});


def gen_sourcing_guide(m, guide_template):
print(m['title'])
print((m['title']))

if len(m['vitamins']) == 0:
return {};
Expand DownExpand Up@@ -469,7 +469,7 @@ def gen_index(jso, index_file, index_template):
# build object
indexObj = { 'machines': [], 'project':'' };
for m in jso:
if type(m) is DictType and m['type'] == 'machine':
if type(m) is dict and m['type'] == 'machine':

# tack in a view filename
m['viewFilename'] = views.view_filename(m['title'] + '_view')
Expand DownExpand Up@@ -527,7 +527,7 @@ def guides():

# for each machine
for m in jso:
if type(m) is DictType and m['type'] == 'machine':
if type(m) is dict and m['type'] == 'machine':

if 'guides' not in m:
m['guides'] = []
Expand Down
2 changes: 1 addition & 1 deletion scripts/jsontools.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -11,7 +11,7 @@ def json_merge_missing_keys(j1, j2, overwrite=False, exclude=[]):
def get_child_by_key_values(j1, kvs={}):
if 'children' in j1:
for c in j1['children']:
if type(c) is DictType:
if type(c) is dict:
match = True
for kv in kvs:
if not (kv in c and c[kv] == kvs[kv]):
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions README.md
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
# Changes on this fork

This framework is an awesome project from Axford, but it appears to have been abandoned, at least it's not been worked on since 2016 or so (it's now Jan 2019). Original was written for Python 2, and assumed Unix (or Mac?) conventions. I've updated it to work with Python 3 (only tested with 3.6.5) and made some changes to make it work on Windows.

**Note**: I have not tested this extensively. I've only used it with Python 3.6.5 on Win10, and don't know if I broke anything for other platforms. I'm also quite new to using it, so there may be use cases that don't currently work (sadly, the tutorial only has part 1) If you find any bugs, please open an issue, I'll try to take a look.

Everythng below is from the original project.

# OpenSCAD for Machine Design framework

## Overview
Expand Down
4 changes: 2 additions & 2 deletions scripts/adda.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -77,7 +77,7 @@ def adda(t, n, d):
o.write("include <"+incFile+">\n")

else:
print(templateFile + " template is missing")
print((templateFile + " template is missing"))

# Sandbox
templateFile = os.path.join(config.paths['template'],"sandbox","sandbox.scad")
Expand All@@ -93,7 +93,7 @@ def adda(t, n, d):
o.write(s)

else:
print(templateFile + " template is missing")
print((templateFile + " template is missing"))


if __name__ == '__main__':
Expand Down
20 changes: 10 additions & 10 deletions scripts/animate.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -57,8 +57,8 @@ def animateAssembly(mname, aname, prefix, framesPerStep):

# locate required machine
for m in jso:
if type(m) is DictType and m['type'] == 'machine' and m['title'] == mname:
print("Found machine: "+m['title'])
if type(m) is dict and m['type'] == 'machine' and m['title'] == mname:
print(("Found machine: "+m['title']))

al = m['assemblies']

Expand All@@ -70,7 +70,7 @@ def animateAssembly(mname, aname, prefix, framesPerStep):
# locate required assembly
for a in al:
if a['title'] == aname:
print("Found assembly: "+a['title'])
print(("Found assembly: "+a['title']))
fn = config.paths['root'] + a['file']
if (os.path.isfile(fn)):

Expand All@@ -94,7 +94,7 @@ def animateAssembly(mname, aname, prefix, framesPerStep):
}
firstView = True
for step in a['steps']:
print("Step: "+str(step['num']))
print(("Step: "+str(step['num'])))

# generate a transition move?
if len(step['views']) > 0:
Expand DownExpand Up@@ -177,7 +177,7 @@ def animateAssembly(mname, aname, prefix, framesPerStep):
views.PolishTransparentBackground = False
views.PolishCrop = False
fn = view_dir + "/" +prefix + format(frameNum, '03') + "_" +view['title']+".png"
print("Rendering: "+fn)
print(("Rendering: "+fn))
views.render_view_using_file(prefix + format(frameNum, '03'), config.paths['tempscad'], view_dir, view, hashchanged, h)
frameNum = frameNum + 1

Expand All@@ -199,7 +199,7 @@ def animateAssembly(mname, aname, prefix, framesPerStep):
alpha = extra / (1.0*framesPerStep)
if (alpha > 1.0):
alpha = 1.0
print("Blending: "+str(alpha) +", "+str(frameNum))
print(("Blending: "+str(alpha) +", "+str(frameNum)))
imgNew = Image.blend(imgPrev,img,alpha)

draw = ImageDraw.Draw(imgNew, "RGBA")
Expand All@@ -219,7 +219,7 @@ def animateAssembly(mname, aname, prefix, framesPerStep):

fn = view_dir + "/" +prefix + format(frameNum, '03') + "_" +view['title']+".png"
frameNum = frameNum + 1
print("Saving: "+fn)
print(("Saving: "+fn))
imgNew.save(fn)

lfn = fn
Expand DownExpand Up@@ -262,12 +262,12 @@ def animateAssembly(mname, aname, prefix, framesPerStep):

# build video
cmd = "ffmpeg -r "+str(framesPerStep)+" -y -i "+view_dir + "/" + prefix+"%03d_"+view['title']+".png -vcodec libx264 -pix_fmt yuv420p "+view_dir + "/" + prefix+".mp4"
print("Encoding video with: "+cmd)
print(("Encoding video with: "+cmd))
os.system(cmd)

# build animated gif
cmd = "convert "+view_dir + "/" + prefix+".mp4 "+view_dir + "/" + prefix+".gif"
print("Creating GIF with: "+cmd)
print(("Creating GIF with: "+cmd))
os.system(cmd)

# clean up temporary images
Expand All@@ -283,7 +283,7 @@ def animateAssembly(mname, aname, prefix, framesPerStep):
print("Exception running osascript")

else:
print(" Error: scad file not found: "+a['file'])
print((" Error: scad file not found: "+a['file']))

return 0

Expand Down
12 changes: 6 additions & 6 deletions scripts/assemblies.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -34,8 +34,8 @@ def assemblies():

# for each machine
for m in jso:
if type(m) is DictType and m['type'] == 'machine':
print(m['title'])
if type(m) is dict and m['type'] == 'machine':
print((m['title']))

al = m['assemblies']

Expand All@@ -46,7 +46,7 @@ def assemblies():

# for each assembly
for a in al:
print(" "+a['title'])
print((" "+a['title']))
fn = config.paths['root'] + a['file']
if (os.path.isfile(fn)):

Expand All@@ -73,18 +73,18 @@ def assemblies():
f.close()

# Views
print(" Step "+str(step['num']))
print((" Step "+str(step['num'])))
for view in step['views']:
render_view_using_file(a['title']+'_step'+str(step['num']), config.paths['tempscad'], view_dir, view, hashchanged, h)

# for each animation
for anim in a['animations']:
print(" Animation: "+anim['title']+", framesPerStep="+str(anim['framesPerStep']))
print((" Animation: "+anim['title']+", framesPerStep="+str(anim['framesPerStep'])))

animateAssembly(m['title'], a['title'], anim['title'], anim['framesPerStep'])

else:
print(" Error: scad file not found: "+a['file'])
print((" Error: scad file not found: "+a['file']))


# Save changes to json
Expand Down
14 changes: 7 additions & 7 deletions scripts/build.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -22,15 +22,15 @@ def build(argv):
try:
opts, args = getopt.getopt(argv,"hcq",[])
except getopt.GetoptError:
print'build.py -h -c -q'
print ''
print('build.py -h -c -q')
print( '')
sys.exit(2)
for opt, arg in opts:
if opt == '-h':
print'Usage: -h -c -q'
print ''
print' -c Skip catalogue'
print ' -q Quick build - skip assemblies, guide and catalogue'
print('Usage: -h -c -q')
print('')
print(' -c Skip catalogue')
print( ' -q Quick build - skip assemblies, guide and catalogue')
sys.exit()
if opt in ("-c"):
doCatalogue = False
Expand DownExpand Up@@ -82,7 +82,7 @@ def build(argv):
print("Build Complete")

if errorlevel > 0:
print("Error: " + str(errorlevel))
print(("Error: " + str(errorlevel)))

return errorlevel

Expand Down
2 changes: 1 addition & 1 deletion scripts/c14n_stl.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -6,7 +6,7 @@
# This has no effect on the model but makes the STL consistent. I.e. it makes a canonical form.
#

from __future__ import print_function


import sys
import math
Expand Down
20 changes: 10 additions & 10 deletions scripts/catalogue.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -36,7 +36,7 @@ def output_vitamin(v):

# per view
for view in t['children']:
if type(view) is DictType and view['type'] == 'view':
if type(view) is dict and view['type'] == 'view':
md += '!['+t['title']+']('+view['png_name']+')\n'

md += '\n'
Expand DownExpand Up@@ -68,7 +68,7 @@ def compile_vitamin(v, dom):
os.makedirs(config.paths['vitaminsimages'])

# Compile
print(" "+v['title'])
print((" "+v['title']))
fn = '../' + v['file']
if (os.path.isfile(fn)):

Expand All@@ -84,8 +84,8 @@ def compile_vitamin(v, dom):
# Views
print(" Views")
for view in v['children']:
if type(view) is DictType and view['type'] == 'view':
print(" "+view['title'])
if type(view) is dict and view['type'] == 'view':
print((" "+view['title']))

render_view(v['title'], v['call'], config.paths['vitaminsimages'], view, hashchanged, h, [fn], False, useVitaminSTL=False)

Expand All@@ -96,14 +96,14 @@ def compile_vitamin(v, dom):


else:
print(" Error: scad file not found: "+v['file'])
print((" Error: scad file not found: "+v['file']))


def parse_vitamin(vitaminscad, use_catalogue_call=False):

vitamincall = vitaminscad[:-5];

print(" Calling: "+ vitamincall + "();")
print((" Calling: "+ vitamincall + "();"))

# Generate a wrapper scad file for the vitamin file
with open(config.paths['tempscad'], "w") as f:
Expand DownExpand Up@@ -157,7 +157,7 @@ def parse_vitamin(vitaminscad, use_catalogue_call=False):
js = json.dumps(jso, sort_keys=False, indent=4, separators=(',', ': '))

except Exception as e:
print(" "+e)
print((" "+e))
# Stop malformed machine json screwing up everything else!
js = ''

Expand DownExpand Up@@ -185,7 +185,7 @@ def catalogue():

for filename in os.listdir(config.paths['vitamins']):
if filename[-5:] == '.scad':
print(" Parsing: "+filename)
print((" Parsing: "+filename))

s = ''

Expand DownExpand Up@@ -225,12 +225,12 @@ def catalogue():
try:
jso = json.loads(js)

print("Parsed "+str(files)+" vitamin files")
print(("Parsed "+str(files)+" vitamin files"))

dom = {'vitamins':[]}

for v in jso:
if type(v) is DictType and v['type'] == 'vitamin':
if type(v) is dict and v['type'] == 'vitamin':
try:
compile_vitamin(v, dom)
except Exception as e:
Expand Down
10 changes: 5 additions & 5 deletions scripts/cut.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -33,8 +33,8 @@ def cut():

# for each machine
for m in jso:
if type(m) is DictType and m['type'] == 'machine':
print(m['title'])
if type(m) is dict and m['type'] == 'machine':
print((m['title']))

al = m['cut']

Expand All@@ -43,7 +43,7 @@ def cut():
os.makedirs(config.paths['cutpartsimages'])

for a in al:
print(" "+a['title'])
print((" "+a['title']))
fn = config.paths['root'] + a['file']
if (os.path.isfile(fn)):

Expand DownExpand Up@@ -81,13 +81,13 @@ def cut():
f.close()

# Views
print(" Step "+str(step['num']))
print((" Step "+str(step['num'])))
for view in step['views']:
render_view_using_file(a['title']+'_step'+str(step['num']), config.paths['tempscad'], config.paths['cutpartsimages'], view, hashchanged, h)


else:
print(" Error: scad file not found: "+a['file'])
print((" Error: scad file not found: "+a['file']))


# Save changes to json
Expand Down
22 changes: 11 additions & 11 deletions scripts/guides.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -215,7 +215,7 @@ def assembly_level(a):


def gen_assembly_guide(m, guide_template):
print(m['title'])
print((m['title']))

md = ''

Expand All@@ -224,7 +224,7 @@ def gen_assembly_guide(m, guide_template):

# machine views
for c in m['children']:
if type(c) is DictType and c['type'] == 'view' and 'filepath' in c:
if type(c) is dict and c['type'] == 'view' and 'filepath' in c:
view = c
md += '!['+view['caption']+']('+ view['filepath'][3:] +')\n\n'

Expand DownExpand Up@@ -273,7 +273,7 @@ def gen_assembly_guide(m, guide_template):


def gen_printing_guide(m, guide_template):
print(m['title'])
print((m['title']))

if len(m['printed']) == 0:
return {};
Expand DownExpand Up@@ -347,29 +347,29 @@ def gen_printing_guide(m, guide_template):


def load_sources():
print"Loading sourcing info..."
print("Loading sourcing info...")

load_source(config.paths['sourcingcsv'])

for filename in os.listdir(config.paths['vitamins']):
if filename[-4:] == '.csv':
print(" Parsing: "+filename)
print((" Parsing: "+filename))
csvfn = os.path.join(src_dir, filename)
load_source(csvfn)

def load_source(csvfn):
if os.path.isfile(csvfn):
with open(csvfn, 'rb') as csvfile:
with open(csvfn, 'r') as csvfile:
rdr = csv.DictReader(csvfile)
for row in rdr:
vn = row['Vitamin']
vn = row.get('Vitamin');
if vn not in sourcing:
sourcing[vn] = []
sourcing[vn].append({"Cost":row['Cost'], "Source":row['Source'], 'Notes':row['Notes']});
sourcing[vn].append({"Cost":row.get('Cost'), "Source":row.get('Source'), 'Notes':row.get('Notes')});


def gen_sourcing_guide(m, guide_template):
print(m['title'])
print((m['title']))

if len(m['vitamins']) == 0:
return {};
Expand DownExpand Up@@ -469,7 +469,7 @@ def gen_index(jso, index_file, index_template):
# build object
indexObj = { 'machines': [], 'project':'' };
for m in jso:
if type(m) is DictType and m['type'] == 'machine':
if type(m) is dict and m['type'] == 'machine':

# tack in a view filename
m['viewFilename'] = views.view_filename(m['title'] + '_view')
Expand DownExpand Up@@ -527,7 +527,7 @@ def guides():

# for each machine
for m in jso:
if type(m) is DictType and m['type'] == 'machine':
if type(m) is dict and m['type'] == 'machine':

if 'guides' not in m:
m['guides'] = []
Expand Down
2 changes: 1 addition & 1 deletion scripts/jsontools.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -11,7 +11,7 @@ def json_merge_missing_keys(j1, j2, overwrite=False, exclude=[]):
def get_child_by_key_values(j1, kvs={}):
if 'children' in j1:
for c in j1['children']:
if type(c) is DictType:
if type(c) is dict:
match = True
for kv in kvs:
if not (kv in c and c[kv] == kvs[kv]):
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions README.md
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
# Changes on this fork

This framework is an awesome project from Axford, but it appears to have been abandoned, at least it's not been worked on since 2016 or so (it's now Jan 2019). Original was written for Python 2, and assumed Unix (or Mac?) conventions. I've updated it to work with Python 3 (only tested with 3.6.5) and made some changes to make it work on Windows.

**Note**: I have not tested this extensively. I've only used it with Python 3.6.5 on Win10, and don't know if I broke anything for other platforms. I'm also quite new to using it, so there may be use cases that don't currently work (sadly, the tutorial only has part 1) If you find any bugs, please open an issue, I'll try to take a look.

Everythng below is from the original project.

# OpenSCAD for Machine Design framework

## Overview
Expand Down
4 changes: 2 additions & 2 deletions scripts/adda.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -77,7 +77,7 @@ def adda(t, n, d):
o.write("include <"+incFile+">\n")

else:
print(templateFile + " template is missing")
print((templateFile + " template is missing"))

# Sandbox
templateFile = os.path.join(config.paths['template'],"sandbox","sandbox.scad")
Expand All@@ -93,7 +93,7 @@ def adda(t, n, d):
o.write(s)

else:
print(templateFile + " template is missing")
print((templateFile + " template is missing"))


if __name__ == '__main__':
Expand Down
20 changes: 10 additions & 10 deletions scripts/animate.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -57,8 +57,8 @@ def animateAssembly(mname, aname, prefix, framesPerStep):

# locate required machine
for m in jso:
if type(m) is DictType and m['type'] == 'machine' and m['title'] == mname:
print("Found machine: "+m['title'])
if type(m) is dict and m['type'] == 'machine' and m['title'] == mname:
print(("Found machine: "+m['title']))

al = m['assemblies']

Expand All@@ -70,7 +70,7 @@ def animateAssembly(mname, aname, prefix, framesPerStep):
# locate required assembly
for a in al:
if a['title'] == aname:
print("Found assembly: "+a['title'])
print(("Found assembly: "+a['title']))
fn = config.paths['root'] + a['file']
if (os.path.isfile(fn)):

Expand All@@ -94,7 +94,7 @@ def animateAssembly(mname, aname, prefix, framesPerStep):
}
firstView = True
for step in a['steps']:
print("Step: "+str(step['num']))
print(("Step: "+str(step['num'])))

# generate a transition move?
if len(step['views']) > 0:
Expand DownExpand Up@@ -177,7 +177,7 @@ def animateAssembly(mname, aname, prefix, framesPerStep):
views.PolishTransparentBackground = False
views.PolishCrop = False
fn = view_dir + "/" +prefix + format(frameNum, '03') + "_" +view['title']+".png"
print("Rendering: "+fn)
print(("Rendering: "+fn))
views.render_view_using_file(prefix + format(frameNum, '03'), config.paths['tempscad'], view_dir, view, hashchanged, h)
frameNum = frameNum + 1

Expand All@@ -199,7 +199,7 @@ def animateAssembly(mname, aname, prefix, framesPerStep):
alpha = extra / (1.0*framesPerStep)
if (alpha > 1.0):
alpha = 1.0
print("Blending: "+str(alpha) +", "+str(frameNum))
print(("Blending: "+str(alpha) +", "+str(frameNum)))
imgNew = Image.blend(imgPrev,img,alpha)

draw = ImageDraw.Draw(imgNew, "RGBA")
Expand All@@ -219,7 +219,7 @@ def animateAssembly(mname, aname, prefix, framesPerStep):

fn = view_dir + "/" +prefix + format(frameNum, '03') + "_" +view['title']+".png"
frameNum = frameNum + 1
print("Saving: "+fn)
print(("Saving: "+fn))
imgNew.save(fn)

lfn = fn
Expand DownExpand Up@@ -262,12 +262,12 @@ def animateAssembly(mname, aname, prefix, framesPerStep):

# build video
cmd = "ffmpeg -r "+str(framesPerStep)+" -y -i "+view_dir + "/" + prefix+"%03d_"+view['title']+".png -vcodec libx264 -pix_fmt yuv420p "+view_dir + "/" + prefix+".mp4"
print("Encoding video with: "+cmd)
print(("Encoding video with: "+cmd))
os.system(cmd)

# build animated gif
cmd = "convert "+view_dir + "/" + prefix+".mp4 "+view_dir + "/" + prefix+".gif"
print("Creating GIF with: "+cmd)
print(("Creating GIF with: "+cmd))
os.system(cmd)

# clean up temporary images
Expand All@@ -283,7 +283,7 @@ def animateAssembly(mname, aname, prefix, framesPerStep):
print("Exception running osascript")

else:
print(" Error: scad file not found: "+a['file'])
print((" Error: scad file not found: "+a['file']))

return 0

Expand Down
12 changes: 6 additions & 6 deletions scripts/assemblies.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -34,8 +34,8 @@ def assemblies():

# for each machine
for m in jso:
if type(m) is DictType and m['type'] == 'machine':
print(m['title'])
if type(m) is dict and m['type'] == 'machine':
print((m['title']))

al = m['assemblies']

Expand All@@ -46,7 +46,7 @@ def assemblies():

# for each assembly
for a in al:
print(" "+a['title'])
print((" "+a['title']))
fn = config.paths['root'] + a['file']
if (os.path.isfile(fn)):

Expand All@@ -73,18 +73,18 @@ def assemblies():
f.close()

# Views
print(" Step "+str(step['num']))
print((" Step "+str(step['num'])))
for view in step['views']:
render_view_using_file(a['title']+'_step'+str(step['num']), config.paths['tempscad'], view_dir, view, hashchanged, h)

# for each animation
for anim in a['animations']:
print(" Animation: "+anim['title']+", framesPerStep="+str(anim['framesPerStep']))
print((" Animation: "+anim['title']+", framesPerStep="+str(anim['framesPerStep'])))

animateAssembly(m['title'], a['title'], anim['title'], anim['framesPerStep'])

else:
print(" Error: scad file not found: "+a['file'])
print((" Error: scad file not found: "+a['file']))


# Save changes to json
Expand Down
14 changes: 7 additions & 7 deletions scripts/build.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -22,15 +22,15 @@ def build(argv):
try:
opts, args = getopt.getopt(argv,"hcq",[])
except getopt.GetoptError:
print'build.py -h -c -q'
print ''
print('build.py -h -c -q')
print( '')
sys.exit(2)
for opt, arg in opts:
if opt == '-h':
print'Usage: -h -c -q'
print ''
print' -c Skip catalogue'
print ' -q Quick build - skip assemblies, guide and catalogue'
print('Usage: -h -c -q')
print('')
print(' -c Skip catalogue')
print( ' -q Quick build - skip assemblies, guide and catalogue')
sys.exit()
if opt in ("-c"):
doCatalogue = False
Expand DownExpand Up@@ -82,7 +82,7 @@ def build(argv):
print("Build Complete")

if errorlevel > 0:
print("Error: " + str(errorlevel))
print(("Error: " + str(errorlevel)))

return errorlevel

Expand Down
2 changes: 1 addition & 1 deletion scripts/c14n_stl.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -6,7 +6,7 @@
# This has no effect on the model but makes the STL consistent. I.e. it makes a canonical form.
#

from __future__ import print_function


import sys
import math
Expand Down
20 changes: 10 additions & 10 deletions scripts/catalogue.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -36,7 +36,7 @@ def output_vitamin(v):

# per view
for view in t['children']:
if type(view) is DictType and view['type'] == 'view':
if type(view) is dict and view['type'] == 'view':
md += '!['+t['title']+']('+view['png_name']+')\n'

md += '\n'
Expand DownExpand Up@@ -68,7 +68,7 @@ def compile_vitamin(v, dom):
os.makedirs(config.paths['vitaminsimages'])

# Compile
print(" "+v['title'])
print((" "+v['title']))
fn = '../' + v['file']
if (os.path.isfile(fn)):

Expand All@@ -84,8 +84,8 @@ def compile_vitamin(v, dom):
# Views
print(" Views")
for view in v['children']:
if type(view) is DictType and view['type'] == 'view':
print(" "+view['title'])
if type(view) is dict and view['type'] == 'view':
print((" "+view['title']))

render_view(v['title'], v['call'], config.paths['vitaminsimages'], view, hashchanged, h, [fn], False, useVitaminSTL=False)

Expand All@@ -96,14 +96,14 @@ def compile_vitamin(v, dom):


else:
print(" Error: scad file not found: "+v['file'])
print((" Error: scad file not found: "+v['file']))


def parse_vitamin(vitaminscad, use_catalogue_call=False):

vitamincall = vitaminscad[:-5];

print(" Calling: "+ vitamincall + "();")
print((" Calling: "+ vitamincall + "();"))

# Generate a wrapper scad file for the vitamin file
with open(config.paths['tempscad'], "w") as f:
Expand DownExpand Up@@ -157,7 +157,7 @@ def parse_vitamin(vitaminscad, use_catalogue_call=False):
js = json.dumps(jso, sort_keys=False, indent=4, separators=(',', ': '))

except Exception as e:
print(" "+e)
print((" "+e))
# Stop malformed machine json screwing up everything else!
js = ''

Expand DownExpand Up@@ -185,7 +185,7 @@ def catalogue():

for filename in os.listdir(config.paths['vitamins']):
if filename[-5:] == '.scad':
print(" Parsing: "+filename)
print((" Parsing: "+filename))

s = ''

Expand DownExpand Up@@ -225,12 +225,12 @@ def catalogue():
try:
jso = json.loads(js)

print("Parsed "+str(files)+" vitamin files")
print(("Parsed "+str(files)+" vitamin files"))

dom = {'vitamins':[]}

for v in jso:
if type(v) is DictType and v['type'] == 'vitamin':
if type(v) is dict and v['type'] == 'vitamin':
try:
compile_vitamin(v, dom)
except Exception as e:
Expand Down
10 changes: 5 additions & 5 deletions scripts/cut.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -33,8 +33,8 @@ def cut():

# for each machine
for m in jso:
if type(m) is DictType and m['type'] == 'machine':
print(m['title'])
if type(m) is dict and m['type'] == 'machine':
print((m['title']))

al = m['cut']

Expand All@@ -43,7 +43,7 @@ def cut():
os.makedirs(config.paths['cutpartsimages'])

for a in al:
print(" "+a['title'])
print((" "+a['title']))
fn = config.paths['root'] + a['file']
if (os.path.isfile(fn)):

Expand DownExpand Up@@ -81,13 +81,13 @@ def cut():
f.close()

# Views
print(" Step "+str(step['num']))
print((" Step "+str(step['num'])))
for view in step['views']:
render_view_using_file(a['title']+'_step'+str(step['num']), config.paths['tempscad'], config.paths['cutpartsimages'], view, hashchanged, h)


else:
print(" Error: scad file not found: "+a['file'])
print((" Error: scad file not found: "+a['file']))


# Save changes to json
Expand Down
22 changes: 11 additions & 11 deletions scripts/guides.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -215,7 +215,7 @@ def assembly_level(a):


def gen_assembly_guide(m, guide_template):
print(m['title'])
print((m['title']))

md = ''

Expand All@@ -224,7 +224,7 @@ def gen_assembly_guide(m, guide_template):

# machine views
for c in m['children']:
if type(c) is DictType and c['type'] == 'view' and 'filepath' in c:
if type(c) is dict and c['type'] == 'view' and 'filepath' in c:
view = c
md += '!['+view['caption']+']('+ view['filepath'][3:] +')\n\n'

Expand DownExpand Up@@ -273,7 +273,7 @@ def gen_assembly_guide(m, guide_template):


def gen_printing_guide(m, guide_template):
print(m['title'])
print((m['title']))

if len(m['printed']) == 0:
return {};
Expand DownExpand Up@@ -347,29 +347,29 @@ def gen_printing_guide(m, guide_template):


def load_sources():
print"Loading sourcing info..."
print("Loading sourcing info...")

load_source(config.paths['sourcingcsv'])

for filename in os.listdir(config.paths['vitamins']):
if filename[-4:] == '.csv':
print(" Parsing: "+filename)
print((" Parsing: "+filename))
csvfn = os.path.join(src_dir, filename)
load_source(csvfn)

def load_source(csvfn):
if os.path.isfile(csvfn):
with open(csvfn, 'rb') as csvfile:
with open(csvfn, 'r') as csvfile:
rdr = csv.DictReader(csvfile)
for row in rdr:
vn = row['Vitamin']
vn = row.get('Vitamin');
if vn not in sourcing:
sourcing[vn] = []
sourcing[vn].append({"Cost":row['Cost'], "Source":row['Source'], 'Notes':row['Notes']});
sourcing[vn].append({"Cost":row.get('Cost'), "Source":row.get('Source'), 'Notes':row.get('Notes')});


def gen_sourcing_guide(m, guide_template):
print(m['title'])
print((m['title']))

if len(m['vitamins']) == 0:
return {};
Expand DownExpand Up@@ -469,7 +469,7 @@ def gen_index(jso, index_file, index_template):
# build object
indexObj = { 'machines': [], 'project':'' };
for m in jso:
if type(m) is DictType and m['type'] == 'machine':
if type(m) is dict and m['type'] == 'machine':

# tack in a view filename
m['viewFilename'] = views.view_filename(m['title'] + '_view')
Expand DownExpand Up@@ -527,7 +527,7 @@ def guides():

# for each machine
for m in jso:
if type(m) is DictType and m['type'] == 'machine':
if type(m) is dict and m['type'] == 'machine':

if 'guides' not in m:
m['guides'] = []
Expand Down
2 changes: 1 addition & 1 deletion scripts/jsontools.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -11,7 +11,7 @@ def json_merge_missing_keys(j1, j2, overwrite=False, exclude=[]):
def get_child_by_key_values(j1, kvs={}):
if 'children' in j1:
for c in j1['children']:
if type(c) is DictType:
if type(c) is dict:
match = True
for kv in kvs:
if not (kv in c and c[kv] == kvs[kv]):
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions README.md
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
# Changes on this fork

This framework is an awesome project from Axford, but it appears to have been abandoned, at least it's not been worked on since 2016 or so (it's now Jan 2019). Original was written for Python 2, and assumed Unix (or Mac?) conventions. I've updated it to work with Python 3 (only tested with 3.6.5) and made some changes to make it work on Windows.

**Note**: I have not tested this extensively. I've only used it with Python 3.6.5 on Win10, and don't know if I broke anything for other platforms. I'm also quite new to using it, so there may be use cases that don't currently work (sadly, the tutorial only has part 1) If you find any bugs, please open an issue, I'll try to take a look.

Everythng below is from the original project.

# OpenSCAD for Machine Design framework

## Overview
Expand Down
4 changes: 2 additions & 2 deletions scripts/adda.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -77,7 +77,7 @@ def adda(t, n, d):
o.write("include <"+incFile+">\n")

else:
print(templateFile + " template is missing")
print((templateFile + " template is missing"))

# Sandbox
templateFile = os.path.join(config.paths['template'],"sandbox","sandbox.scad")
Expand All@@ -93,7 +93,7 @@ def adda(t, n, d):
o.write(s)

else:
print(templateFile + " template is missing")
print((templateFile + " template is missing"))


if __name__ == '__main__':
Expand Down
20 changes: 10 additions & 10 deletions scripts/animate.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -57,8 +57,8 @@ def animateAssembly(mname, aname, prefix, framesPerStep):

# locate required machine
for m in jso:
if type(m) is DictType and m['type'] == 'machine' and m['title'] == mname:
print("Found machine: "+m['title'])
if type(m) is dict and m['type'] == 'machine' and m['title'] == mname:
print(("Found machine: "+m['title']))

al = m['assemblies']

Expand All@@ -70,7 +70,7 @@ def animateAssembly(mname, aname, prefix, framesPerStep):
# locate required assembly
for a in al:
if a['title'] == aname:
print("Found assembly: "+a['title'])
print(("Found assembly: "+a['title']))
fn = config.paths['root'] + a['file']
if (os.path.isfile(fn)):

Expand All@@ -94,7 +94,7 @@ def animateAssembly(mname, aname, prefix, framesPerStep):
}
firstView = True
for step in a['steps']:
print("Step: "+str(step['num']))
print(("Step: "+str(step['num'])))

# generate a transition move?
if len(step['views']) > 0:
Expand DownExpand Up@@ -177,7 +177,7 @@ def animateAssembly(mname, aname, prefix, framesPerStep):
views.PolishTransparentBackground = False
views.PolishCrop = False
fn = view_dir + "/" +prefix + format(frameNum, '03') + "_" +view['title']+".png"
print("Rendering: "+fn)
print(("Rendering: "+fn))
views.render_view_using_file(prefix + format(frameNum, '03'), config.paths['tempscad'], view_dir, view, hashchanged, h)
frameNum = frameNum + 1

Expand All@@ -199,7 +199,7 @@ def animateAssembly(mname, aname, prefix, framesPerStep):
alpha = extra / (1.0*framesPerStep)
if (alpha > 1.0):
alpha = 1.0
print("Blending: "+str(alpha) +", "+str(frameNum))
print(("Blending: "+str(alpha) +", "+str(frameNum)))
imgNew = Image.blend(imgPrev,img,alpha)

draw = ImageDraw.Draw(imgNew, "RGBA")
Expand All@@ -219,7 +219,7 @@ def animateAssembly(mname, aname, prefix, framesPerStep):

fn = view_dir + "/" +prefix + format(frameNum, '03') + "_" +view['title']+".png"
frameNum = frameNum + 1
print("Saving: "+fn)
print(("Saving: "+fn))
imgNew.save(fn)

lfn = fn
Expand DownExpand Up@@ -262,12 +262,12 @@ def animateAssembly(mname, aname, prefix, framesPerStep):

# build video
cmd = "ffmpeg -r "+str(framesPerStep)+" -y -i "+view_dir + "/" + prefix+"%03d_"+view['title']+".png -vcodec libx264 -pix_fmt yuv420p "+view_dir + "/" + prefix+".mp4"
print("Encoding video with: "+cmd)
print(("Encoding video with: "+cmd))
os.system(cmd)

# build animated gif
cmd = "convert "+view_dir + "/" + prefix+".mp4 "+view_dir + "/" + prefix+".gif"
print("Creating GIF with: "+cmd)
print(("Creating GIF with: "+cmd))
os.system(cmd)

# clean up temporary images
Expand All@@ -283,7 +283,7 @@ def animateAssembly(mname, aname, prefix, framesPerStep):
print("Exception running osascript")

else:
print(" Error: scad file not found: "+a['file'])
print((" Error: scad file not found: "+a['file']))

return 0

Expand Down
12 changes: 6 additions & 6 deletions scripts/assemblies.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -34,8 +34,8 @@ def assemblies():

# for each machine
for m in jso:
if type(m) is DictType and m['type'] == 'machine':
print(m['title'])
if type(m) is dict and m['type'] == 'machine':
print((m['title']))

al = m['assemblies']

Expand All@@ -46,7 +46,7 @@ def assemblies():

# for each assembly
for a in al:
print(" "+a['title'])
print((" "+a['title']))
fn = config.paths['root'] + a['file']
if (os.path.isfile(fn)):

Expand All@@ -73,18 +73,18 @@ def assemblies():
f.close()

# Views
print(" Step "+str(step['num']))
print((" Step "+str(step['num'])))
for view in step['views']:
render_view_using_file(a['title']+'_step'+str(step['num']), config.paths['tempscad'], view_dir, view, hashchanged, h)

# for each animation
for anim in a['animations']:
print(" Animation: "+anim['title']+", framesPerStep="+str(anim['framesPerStep']))
print((" Animation: "+anim['title']+", framesPerStep="+str(anim['framesPerStep'])))

animateAssembly(m['title'], a['title'], anim['title'], anim['framesPerStep'])

else:
print(" Error: scad file not found: "+a['file'])
print((" Error: scad file not found: "+a['file']))


# Save changes to json
Expand Down
14 changes: 7 additions & 7 deletions scripts/build.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -22,15 +22,15 @@ def build(argv):
try:
opts, args = getopt.getopt(argv,"hcq",[])
except getopt.GetoptError:
print'build.py -h -c -q'
print ''
print('build.py -h -c -q')
print( '')
sys.exit(2)
for opt, arg in opts:
if opt == '-h':
print'Usage: -h -c -q'
print ''
print' -c Skip catalogue'
print ' -q Quick build - skip assemblies, guide and catalogue'
print('Usage: -h -c -q')
print('')
print(' -c Skip catalogue')
print( ' -q Quick build - skip assemblies, guide and catalogue')
sys.exit()
if opt in ("-c"):
doCatalogue = False
Expand DownExpand Up@@ -82,7 +82,7 @@ def build(argv):
print("Build Complete")

if errorlevel > 0:
print("Error: " + str(errorlevel))
print(("Error: " + str(errorlevel)))

return errorlevel

Expand Down
2 changes: 1 addition & 1 deletion scripts/c14n_stl.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -6,7 +6,7 @@
# This has no effect on the model but makes the STL consistent. I.e. it makes a canonical form.
#

from __future__ import print_function


import sys
import math
Expand Down
20 changes: 10 additions & 10 deletions scripts/catalogue.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -36,7 +36,7 @@ def output_vitamin(v):

# per view
for view in t['children']:
if type(view) is DictType and view['type'] == 'view':
if type(view) is dict and view['type'] == 'view':
md += '!['+t['title']+']('+view['png_name']+')\n'

md += '\n'
Expand DownExpand Up@@ -68,7 +68,7 @@ def compile_vitamin(v, dom):
os.makedirs(config.paths['vitaminsimages'])

# Compile
print(" "+v['title'])
print((" "+v['title']))
fn = '../' + v['file']
if (os.path.isfile(fn)):

Expand All@@ -84,8 +84,8 @@ def compile_vitamin(v, dom):
# Views
print(" Views")
for view in v['children']:
if type(view) is DictType and view['type'] == 'view':
print(" "+view['title'])
if type(view) is dict and view['type'] == 'view':
print((" "+view['title']))

render_view(v['title'], v['call'], config.paths['vitaminsimages'], view, hashchanged, h, [fn], False, useVitaminSTL=False)

Expand All@@ -96,14 +96,14 @@ def compile_vitamin(v, dom):


else:
print(" Error: scad file not found: "+v['file'])
print((" Error: scad file not found: "+v['file']))


def parse_vitamin(vitaminscad, use_catalogue_call=False):

vitamincall = vitaminscad[:-5];

print(" Calling: "+ vitamincall + "();")
print((" Calling: "+ vitamincall + "();"))

# Generate a wrapper scad file for the vitamin file
with open(config.paths['tempscad'], "w") as f:
Expand DownExpand Up@@ -157,7 +157,7 @@ def parse_vitamin(vitaminscad, use_catalogue_call=False):
js = json.dumps(jso, sort_keys=False, indent=4, separators=(',', ': '))

except Exception as e:
print(" "+e)
print((" "+e))
# Stop malformed machine json screwing up everything else!
js = ''

Expand DownExpand Up@@ -185,7 +185,7 @@ def catalogue():

for filename in os.listdir(config.paths['vitamins']):
if filename[-5:] == '.scad':
print(" Parsing: "+filename)
print((" Parsing: "+filename))

s = ''

Expand DownExpand Up@@ -225,12 +225,12 @@ def catalogue():
try:
jso = json.loads(js)

print("Parsed "+str(files)+" vitamin files")
print(("Parsed "+str(files)+" vitamin files"))

dom = {'vitamins':[]}

for v in jso:
if type(v) is DictType and v['type'] == 'vitamin':
if type(v) is dict and v['type'] == 'vitamin':
try:
compile_vitamin(v, dom)
except Exception as e:
Expand Down
10 changes: 5 additions & 5 deletions scripts/cut.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -33,8 +33,8 @@ def cut():

# for each machine
for m in jso:
if type(m) is DictType and m['type'] == 'machine':
print(m['title'])
if type(m) is dict and m['type'] == 'machine':
print((m['title']))

al = m['cut']

Expand All@@ -43,7 +43,7 @@ def cut():
os.makedirs(config.paths['cutpartsimages'])

for a in al:
print(" "+a['title'])
print((" "+a['title']))
fn = config.paths['root'] + a['file']
if (os.path.isfile(fn)):

Expand DownExpand Up@@ -81,13 +81,13 @@ def cut():
f.close()

# Views
print(" Step "+str(step['num']))
print((" Step "+str(step['num'])))
for view in step['views']:
render_view_using_file(a['title']+'_step'+str(step['num']), config.paths['tempscad'], config.paths['cutpartsimages'], view, hashchanged, h)


else:
print(" Error: scad file not found: "+a['file'])
print((" Error: scad file not found: "+a['file']))


# Save changes to json
Expand Down
22 changes: 11 additions & 11 deletions scripts/guides.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -215,7 +215,7 @@ def assembly_level(a):


def gen_assembly_guide(m, guide_template):
print(m['title'])
print((m['title']))

md = ''

Expand All@@ -224,7 +224,7 @@ def gen_assembly_guide(m, guide_template):

# machine views
for c in m['children']:
if type(c) is DictType and c['type'] == 'view' and 'filepath' in c:
if type(c) is dict and c['type'] == 'view' and 'filepath' in c:
view = c
md += '!['+view['caption']+']('+ view['filepath'][3:] +')\n\n'

Expand DownExpand Up@@ -273,7 +273,7 @@ def gen_assembly_guide(m, guide_template):


def gen_printing_guide(m, guide_template):
print(m['title'])
print((m['title']))

if len(m['printed']) == 0:
return {};
Expand DownExpand Up@@ -347,29 +347,29 @@ def gen_printing_guide(m, guide_template):


def load_sources():
print"Loading sourcing info..."
print("Loading sourcing info...")

load_source(config.paths['sourcingcsv'])

for filename in os.listdir(config.paths['vitamins']):
if filename[-4:] == '.csv':
print(" Parsing: "+filename)
print((" Parsing: "+filename))
csvfn = os.path.join(src_dir, filename)
load_source(csvfn)

def load_source(csvfn):
if os.path.isfile(csvfn):
with open(csvfn, 'rb') as csvfile:
with open(csvfn, 'r') as csvfile:
rdr = csv.DictReader(csvfile)
for row in rdr:
vn = row['Vitamin']
vn = row.get('Vitamin');
if vn not in sourcing:
sourcing[vn] = []
sourcing[vn].append({"Cost":row['Cost'], "Source":row['Source'], 'Notes':row['Notes']});
sourcing[vn].append({"Cost":row.get('Cost'), "Source":row.get('Source'), 'Notes':row.get('Notes')});


def gen_sourcing_guide(m, guide_template):
print(m['title'])
print((m['title']))

if len(m['vitamins']) == 0:
return {};
Expand DownExpand Up@@ -469,7 +469,7 @@ def gen_index(jso, index_file, index_template):
# build object
indexObj = { 'machines': [], 'project':'' };
for m in jso:
if type(m) is DictType and m['type'] == 'machine':
if type(m) is dict and m['type'] == 'machine':

# tack in a view filename
m['viewFilename'] = views.view_filename(m['title'] + '_view')
Expand DownExpand Up@@ -527,7 +527,7 @@ def guides():

# for each machine
for m in jso:
if type(m) is DictType and m['type'] == 'machine':
if type(m) is dict and m['type'] == 'machine':

if 'guides' not in m:
m['guides'] = []
Expand Down
2 changes: 1 addition & 1 deletion scripts/jsontools.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -11,7 +11,7 @@ def json_merge_missing_keys(j1, j2, overwrite=False, exclude=[]):
def get_child_by_key_values(j1, kvs={}):
if 'children' in j1:
for c in j1['children']:
if type(c) is DictType:
if type(c) is dict:
match = True
for kv in kvs:
if not (kv in c and c[kv] == kvs[kv]):
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions README.md
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
# Changes on this fork

This framework is an awesome project from Axford, but it appears to have been abandoned, at least it's not been worked on since 2016 or so (it's now Jan 2019). Original was written for Python 2, and assumed Unix (or Mac?) conventions. I've updated it to work with Python 3 (only tested with 3.6.5) and made some changes to make it work on Windows.

**Note**: I have not tested this extensively. I've only used it with Python 3.6.5 on Win10, and don't know if I broke anything for other platforms. I'm also quite new to using it, so there may be use cases that don't currently work (sadly, the tutorial only has part 1) If you find any bugs, please open an issue, I'll try to take a look.

Everythng below is from the original project.

# OpenSCAD for Machine Design framework

## Overview
Expand Down
4 changes: 2 additions & 2 deletions scripts/adda.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -77,7 +77,7 @@ def adda(t, n, d):
o.write("include <"+incFile+">\n")

else:
print(templateFile + " template is missing")
print((templateFile + " template is missing"))

# Sandbox
templateFile = os.path.join(config.paths['template'],"sandbox","sandbox.scad")
Expand All@@ -93,7 +93,7 @@ def adda(t, n, d):
o.write(s)

else:
print(templateFile + " template is missing")
print((templateFile + " template is missing"))


if __name__ == '__main__':
Expand Down
20 changes: 10 additions & 10 deletions scripts/animate.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -57,8 +57,8 @@ def animateAssembly(mname, aname, prefix, framesPerStep):

# locate required machine
for m in jso:
if type(m) is DictType and m['type'] == 'machine' and m['title'] == mname:
print("Found machine: "+m['title'])
if type(m) is dict and m['type'] == 'machine' and m['title'] == mname:
print(("Found machine: "+m['title']))

al = m['assemblies']

Expand All@@ -70,7 +70,7 @@ def animateAssembly(mname, aname, prefix, framesPerStep):
# locate required assembly
for a in al:
if a['title'] == aname:
print("Found assembly: "+a['title'])
print(("Found assembly: "+a['title']))
fn = config.paths['root'] + a['file']
if (os.path.isfile(fn)):

Expand All@@ -94,7 +94,7 @@ def animateAssembly(mname, aname, prefix, framesPerStep):
}
firstView = True
for step in a['steps']:
print("Step: "+str(step['num']))
print(("Step: "+str(step['num'])))

# generate a transition move?
if len(step['views']) > 0:
Expand DownExpand Up@@ -177,7 +177,7 @@ def animateAssembly(mname, aname, prefix, framesPerStep):
views.PolishTransparentBackground = False
views.PolishCrop = False
fn = view_dir + "/" +prefix + format(frameNum, '03') + "_" +view['title']+".png"
print("Rendering: "+fn)
print(("Rendering: "+fn))
views.render_view_using_file(prefix + format(frameNum, '03'), config.paths['tempscad'], view_dir, view, hashchanged, h)
frameNum = frameNum + 1

Expand All@@ -199,7 +199,7 @@ def animateAssembly(mname, aname, prefix, framesPerStep):
alpha = extra / (1.0*framesPerStep)
if (alpha > 1.0):
alpha = 1.0
print("Blending: "+str(alpha) +", "+str(frameNum))
print(("Blending: "+str(alpha) +", "+str(frameNum)))
imgNew = Image.blend(imgPrev,img,alpha)

draw = ImageDraw.Draw(imgNew, "RGBA")
Expand All@@ -219,7 +219,7 @@ def animateAssembly(mname, aname, prefix, framesPerStep):

fn = view_dir + "/" +prefix + format(frameNum, '03') + "_" +view['title']+".png"
frameNum = frameNum + 1
print("Saving: "+fn)
print(("Saving: "+fn))
imgNew.save(fn)

lfn = fn
Expand DownExpand Up@@ -262,12 +262,12 @@ def animateAssembly(mname, aname, prefix, framesPerStep):

# build video
cmd = "ffmpeg -r "+str(framesPerStep)+" -y -i "+view_dir + "/" + prefix+"%03d_"+view['title']+".png -vcodec libx264 -pix_fmt yuv420p "+view_dir + "/" + prefix+".mp4"
print("Encoding video with: "+cmd)
print(("Encoding video with: "+cmd))
os.system(cmd)

# build animated gif
cmd = "convert "+view_dir + "/" + prefix+".mp4 "+view_dir + "/" + prefix+".gif"
print("Creating GIF with: "+cmd)
print(("Creating GIF with: "+cmd))
os.system(cmd)

# clean up temporary images
Expand All@@ -283,7 +283,7 @@ def animateAssembly(mname, aname, prefix, framesPerStep):
print("Exception running osascript")

else:
print(" Error: scad file not found: "+a['file'])
print((" Error: scad file not found: "+a['file']))

return 0

Expand Down
12 changes: 6 additions & 6 deletions scripts/assemblies.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -34,8 +34,8 @@ def assemblies():

# for each machine
for m in jso:
if type(m) is DictType and m['type'] == 'machine':
print(m['title'])
if type(m) is dict and m['type'] == 'machine':
print((m['title']))

al = m['assemblies']

Expand All@@ -46,7 +46,7 @@ def assemblies():

# for each assembly
for a in al:
print(" "+a['title'])
print((" "+a['title']))
fn = config.paths['root'] + a['file']
if (os.path.isfile(fn)):

Expand All@@ -73,18 +73,18 @@ def assemblies():
f.close()

# Views
print(" Step "+str(step['num']))
print((" Step "+str(step['num'])))
for view in step['views']:
render_view_using_file(a['title']+'_step'+str(step['num']), config.paths['tempscad'], view_dir, view, hashchanged, h)

# for each animation
for anim in a['animations']:
print(" Animation: "+anim['title']+", framesPerStep="+str(anim['framesPerStep']))
print((" Animation: "+anim['title']+", framesPerStep="+str(anim['framesPerStep'])))

animateAssembly(m['title'], a['title'], anim['title'], anim['framesPerStep'])

else:
print(" Error: scad file not found: "+a['file'])
print((" Error: scad file not found: "+a['file']))


# Save changes to json
Expand Down
14 changes: 7 additions & 7 deletions scripts/build.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -22,15 +22,15 @@ def build(argv):
try:
opts, args = getopt.getopt(argv,"hcq",[])
except getopt.GetoptError:
print'build.py -h -c -q'
print ''
print('build.py -h -c -q')
print( '')
sys.exit(2)
for opt, arg in opts:
if opt == '-h':
print'Usage: -h -c -q'
print ''
print' -c Skip catalogue'
print ' -q Quick build - skip assemblies, guide and catalogue'
print('Usage: -h -c -q')
print('')
print(' -c Skip catalogue')
print( ' -q Quick build - skip assemblies, guide and catalogue')
sys.exit()
if opt in ("-c"):
doCatalogue = False
Expand DownExpand Up@@ -82,7 +82,7 @@ def build(argv):
print("Build Complete")

if errorlevel > 0:
print("Error: " + str(errorlevel))
print(("Error: " + str(errorlevel)))

return errorlevel

Expand Down
2 changes: 1 addition & 1 deletion scripts/c14n_stl.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -6,7 +6,7 @@
# This has no effect on the model but makes the STL consistent. I.e. it makes a canonical form.
#

from __future__ import print_function


import sys
import math
Expand Down
20 changes: 10 additions & 10 deletions scripts/catalogue.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -36,7 +36,7 @@ def output_vitamin(v):

# per view
for view in t['children']:
if type(view) is DictType and view['type'] == 'view':
if type(view) is dict and view['type'] == 'view':
md += '!['+t['title']+']('+view['png_name']+')\n'

md += '\n'
Expand DownExpand Up@@ -68,7 +68,7 @@ def compile_vitamin(v, dom):
os.makedirs(config.paths['vitaminsimages'])

# Compile
print(" "+v['title'])
print((" "+v['title']))
fn = '../' + v['file']
if (os.path.isfile(fn)):

Expand All@@ -84,8 +84,8 @@ def compile_vitamin(v, dom):
# Views
print(" Views")
for view in v['children']:
if type(view) is DictType and view['type'] == 'view':
print(" "+view['title'])
if type(view) is dict and view['type'] == 'view':
print((" "+view['title']))

render_view(v['title'], v['call'], config.paths['vitaminsimages'], view, hashchanged, h, [fn], False, useVitaminSTL=False)

Expand All@@ -96,14 +96,14 @@ def compile_vitamin(v, dom):


else:
print(" Error: scad file not found: "+v['file'])
print((" Error: scad file not found: "+v['file']))


def parse_vitamin(vitaminscad, use_catalogue_call=False):

vitamincall = vitaminscad[:-5];

print(" Calling: "+ vitamincall + "();")
print((" Calling: "+ vitamincall + "();"))

# Generate a wrapper scad file for the vitamin file
with open(config.paths['tempscad'], "w") as f:
Expand DownExpand Up@@ -157,7 +157,7 @@ def parse_vitamin(vitaminscad, use_catalogue_call=False):
js = json.dumps(jso, sort_keys=False, indent=4, separators=(',', ': '))

except Exception as e:
print(" "+e)
print((" "+e))
# Stop malformed machine json screwing up everything else!
js = ''

Expand DownExpand Up@@ -185,7 +185,7 @@ def catalogue():

for filename in os.listdir(config.paths['vitamins']):
if filename[-5:] == '.scad':
print(" Parsing: "+filename)
print((" Parsing: "+filename))

s = ''

Expand DownExpand Up@@ -225,12 +225,12 @@ def catalogue():
try:
jso = json.loads(js)

print("Parsed "+str(files)+" vitamin files")
print(("Parsed "+str(files)+" vitamin files"))

dom = {'vitamins':[]}

for v in jso:
if type(v) is DictType and v['type'] == 'vitamin':
if type(v) is dict and v['type'] == 'vitamin':
try:
compile_vitamin(v, dom)
except Exception as e:
Expand Down
10 changes: 5 additions & 5 deletions scripts/cut.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -33,8 +33,8 @@ def cut():

# for each machine
for m in jso:
if type(m) is DictType and m['type'] == 'machine':
print(m['title'])
if type(m) is dict and m['type'] == 'machine':
print((m['title']))

al = m['cut']

Expand All@@ -43,7 +43,7 @@ def cut():
os.makedirs(config.paths['cutpartsimages'])

for a in al:
print(" "+a['title'])
print((" "+a['title']))
fn = config.paths['root'] + a['file']
if (os.path.isfile(fn)):

Expand DownExpand Up@@ -81,13 +81,13 @@ def cut():
f.close()

# Views
print(" Step "+str(step['num']))
print((" Step "+str(step['num'])))
for view in step['views']:
render_view_using_file(a['title']+'_step'+str(step['num']), config.paths['tempscad'], config.paths['cutpartsimages'], view, hashchanged, h)


else:
print(" Error: scad file not found: "+a['file'])
print((" Error: scad file not found: "+a['file']))


# Save changes to json
Expand Down
22 changes: 11 additions & 11 deletions scripts/guides.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -215,7 +215,7 @@ def assembly_level(a):


def gen_assembly_guide(m, guide_template):
print(m['title'])
print((m['title']))

md = ''

Expand All@@ -224,7 +224,7 @@ def gen_assembly_guide(m, guide_template):

# machine views
for c in m['children']:
if type(c) is DictType and c['type'] == 'view' and 'filepath' in c:
if type(c) is dict and c['type'] == 'view' and 'filepath' in c:
view = c
md += '!['+view['caption']+']('+ view['filepath'][3:] +')\n\n'

Expand DownExpand Up@@ -273,7 +273,7 @@ def gen_assembly_guide(m, guide_template):


def gen_printing_guide(m, guide_template):
print(m['title'])
print((m['title']))

if len(m['printed']) == 0:
return {};
Expand DownExpand Up@@ -347,29 +347,29 @@ def gen_printing_guide(m, guide_template):


def load_sources():
print"Loading sourcing info..."
print("Loading sourcing info...")

load_source(config.paths['sourcingcsv'])

for filename in os.listdir(config.paths['vitamins']):
if filename[-4:] == '.csv':
print(" Parsing: "+filename)
print((" Parsing: "+filename))
csvfn = os.path.join(src_dir, filename)
load_source(csvfn)

def load_source(csvfn):
if os.path.isfile(csvfn):
with open(csvfn, 'rb') as csvfile:
with open(csvfn, 'r') as csvfile:
rdr = csv.DictReader(csvfile)
for row in rdr:
vn = row['Vitamin']
vn = row.get('Vitamin');
if vn not in sourcing:
sourcing[vn] = []
sourcing[vn].append({"Cost":row['Cost'], "Source":row['Source'], 'Notes':row['Notes']});
sourcing[vn].append({"Cost":row.get('Cost'), "Source":row.get('Source'), 'Notes':row.get('Notes')});


def gen_sourcing_guide(m, guide_template):
print(m['title'])
print((m['title']))

if len(m['vitamins']) == 0:
return {};
Expand DownExpand Up@@ -469,7 +469,7 @@ def gen_index(jso, index_file, index_template):
# build object
indexObj = { 'machines': [], 'project':'' };
for m in jso:
if type(m) is DictType and m['type'] == 'machine':
if type(m) is dict and m['type'] == 'machine':

# tack in a view filename
m['viewFilename'] = views.view_filename(m['title'] + '_view')
Expand DownExpand Up@@ -527,7 +527,7 @@ def guides():

# for each machine
for m in jso:
if type(m) is DictType and m['type'] == 'machine':
if type(m) is dict and m['type'] == 'machine':

if 'guides' not in m:
m['guides'] = []
Expand Down
2 changes: 1 addition & 1 deletion scripts/jsontools.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -11,7 +11,7 @@ def json_merge_missing_keys(j1, j2, overwrite=False, exclude=[]):
def get_child_by_key_values(j1, kvs={}):
if 'children' in j1:
for c in j1['children']:
if type(c) is DictType:
if type(c) is dict:
match = True
for kv in kvs:
if not (kv in c and c[kv] == kvs[kv]):
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions README.md
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
# Changes on this fork

This framework is an awesome project from Axford, but it appears to have been abandoned, at least it's not been worked on since 2016 or so (it's now Jan 2019). Original was written for Python 2, and assumed Unix (or Mac?) conventions. I've updated it to work with Python 3 (only tested with 3.6.5) and made some changes to make it work on Windows.

**Note**: I have not tested this extensively. I've only used it with Python 3.6.5 on Win10, and don't know if I broke anything for other platforms. I'm also quite new to using it, so there may be use cases that don't currently work (sadly, the tutorial only has part 1) If you find any bugs, please open an issue, I'll try to take a look.

Everythng below is from the original project.

# OpenSCAD for Machine Design framework

## Overview
Expand Down
4 changes: 2 additions & 2 deletions scripts/adda.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -77,7 +77,7 @@ def adda(t, n, d):
o.write("include <"+incFile+">\n")

else:
print(templateFile + " template is missing")
print((templateFile + " template is missing"))

# Sandbox
templateFile = os.path.join(config.paths['template'],"sandbox","sandbox.scad")
Expand All@@ -93,7 +93,7 @@ def adda(t, n, d):
o.write(s)

else:
print(templateFile + " template is missing")
print((templateFile + " template is missing"))


if __name__ == '__main__':
Expand Down
20 changes: 10 additions & 10 deletions scripts/animate.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -57,8 +57,8 @@ def animateAssembly(mname, aname, prefix, framesPerStep):

# locate required machine
for m in jso:
if type(m) is DictType and m['type'] == 'machine' and m['title'] == mname:
print("Found machine: "+m['title'])
if type(m) is dict and m['type'] == 'machine' and m['title'] == mname:
print(("Found machine: "+m['title']))

al = m['assemblies']

Expand All@@ -70,7 +70,7 @@ def animateAssembly(mname, aname, prefix, framesPerStep):
# locate required assembly
for a in al:
if a['title'] == aname:
print("Found assembly: "+a['title'])
print(("Found assembly: "+a['title']))
fn = config.paths['root'] + a['file']
if (os.path.isfile(fn)):

Expand All@@ -94,7 +94,7 @@ def animateAssembly(mname, aname, prefix, framesPerStep):
}
firstView = True
for step in a['steps']:
print("Step: "+str(step['num']))
print(("Step: "+str(step['num'])))

# generate a transition move?
if len(step['views']) > 0:
Expand DownExpand Up@@ -177,7 +177,7 @@ def animateAssembly(mname, aname, prefix, framesPerStep):
views.PolishTransparentBackground = False
views.PolishCrop = False
fn = view_dir + "/" +prefix + format(frameNum, '03') + "_" +view['title']+".png"
print("Rendering: "+fn)
print(("Rendering: "+fn))
views.render_view_using_file(prefix + format(frameNum, '03'), config.paths['tempscad'], view_dir, view, hashchanged, h)
frameNum = frameNum + 1

Expand All@@ -199,7 +199,7 @@ def animateAssembly(mname, aname, prefix, framesPerStep):
alpha = extra / (1.0*framesPerStep)
if (alpha > 1.0):
alpha = 1.0
print("Blending: "+str(alpha) +", "+str(frameNum))
print(("Blending: "+str(alpha) +", "+str(frameNum)))
imgNew = Image.blend(imgPrev,img,alpha)

draw = ImageDraw.Draw(imgNew, "RGBA")
Expand All@@ -219,7 +219,7 @@ def animateAssembly(mname, aname, prefix, framesPerStep):

fn = view_dir + "/" +prefix + format(frameNum, '03') + "_" +view['title']+".png"
frameNum = frameNum + 1
print("Saving: "+fn)
print(("Saving: "+fn))
imgNew.save(fn)

lfn = fn
Expand DownExpand Up@@ -262,12 +262,12 @@ def animateAssembly(mname, aname, prefix, framesPerStep):

# build video
cmd = "ffmpeg -r "+str(framesPerStep)+" -y -i "+view_dir + "/" + prefix+"%03d_"+view['title']+".png -vcodec libx264 -pix_fmt yuv420p "+view_dir + "/" + prefix+".mp4"
print("Encoding video with: "+cmd)
print(("Encoding video with: "+cmd))
os.system(cmd)

# build animated gif
cmd = "convert "+view_dir + "/" + prefix+".mp4 "+view_dir + "/" + prefix+".gif"
print("Creating GIF with: "+cmd)
print(("Creating GIF with: "+cmd))
os.system(cmd)

# clean up temporary images
Expand All@@ -283,7 +283,7 @@ def animateAssembly(mname, aname, prefix, framesPerStep):
print("Exception running osascript")

else:
print(" Error: scad file not found: "+a['file'])
print((" Error: scad file not found: "+a['file']))

return 0

Expand Down
12 changes: 6 additions & 6 deletions scripts/assemblies.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -34,8 +34,8 @@ def assemblies():

# for each machine
for m in jso:
if type(m) is DictType and m['type'] == 'machine':
print(m['title'])
if type(m) is dict and m['type'] == 'machine':
print((m['title']))

al = m['assemblies']

Expand All@@ -46,7 +46,7 @@ def assemblies():

# for each assembly
for a in al:
print(" "+a['title'])
print((" "+a['title']))
fn = config.paths['root'] + a['file']
if (os.path.isfile(fn)):

Expand All@@ -73,18 +73,18 @@ def assemblies():
f.close()

# Views
print(" Step "+str(step['num']))
print((" Step "+str(step['num'])))
for view in step['views']:
render_view_using_file(a['title']+'_step'+str(step['num']), config.paths['tempscad'], view_dir, view, hashchanged, h)

# for each animation
for anim in a['animations']:
print(" Animation: "+anim['title']+", framesPerStep="+str(anim['framesPerStep']))
print((" Animation: "+anim['title']+", framesPerStep="+str(anim['framesPerStep'])))

animateAssembly(m['title'], a['title'], anim['title'], anim['framesPerStep'])

else:
print(" Error: scad file not found: "+a['file'])
print((" Error: scad file not found: "+a['file']))


# Save changes to json
Expand Down
14 changes: 7 additions & 7 deletions scripts/build.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -22,15 +22,15 @@ def build(argv):
try:
opts, args = getopt.getopt(argv,"hcq",[])
except getopt.GetoptError:
print'build.py -h -c -q'
print ''
print('build.py -h -c -q')
print( '')
sys.exit(2)
for opt, arg in opts:
if opt == '-h':
print'Usage: -h -c -q'
print ''
print' -c Skip catalogue'
print ' -q Quick build - skip assemblies, guide and catalogue'
print('Usage: -h -c -q')
print('')
print(' -c Skip catalogue')
print( ' -q Quick build - skip assemblies, guide and catalogue')
sys.exit()
if opt in ("-c"):
doCatalogue = False
Expand DownExpand Up@@ -82,7 +82,7 @@ def build(argv):
print("Build Complete")

if errorlevel > 0:
print("Error: " + str(errorlevel))
print(("Error: " + str(errorlevel)))

return errorlevel

Expand Down
2 changes: 1 addition & 1 deletion scripts/c14n_stl.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -6,7 +6,7 @@
# This has no effect on the model but makes the STL consistent. I.e. it makes a canonical form.
#

from __future__ import print_function


import sys
import math
Expand Down
20 changes: 10 additions & 10 deletions scripts/catalogue.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -36,7 +36,7 @@ def output_vitamin(v):

# per view
for view in t['children']:
if type(view) is DictType and view['type'] == 'view':
if type(view) is dict and view['type'] == 'view':
md += '!['+t['title']+']('+view['png_name']+')\n'

md += '\n'
Expand DownExpand Up@@ -68,7 +68,7 @@ def compile_vitamin(v, dom):
os.makedirs(config.paths['vitaminsimages'])

# Compile
print(" "+v['title'])
print((" "+v['title']))
fn = '../' + v['file']
if (os.path.isfile(fn)):

Expand All@@ -84,8 +84,8 @@ def compile_vitamin(v, dom):
# Views
print(" Views")
for view in v['children']:
if type(view) is DictType and view['type'] == 'view':
print(" "+view['title'])
if type(view) is dict and view['type'] == 'view':
print((" "+view['title']))

render_view(v['title'], v['call'], config.paths['vitaminsimages'], view, hashchanged, h, [fn], False, useVitaminSTL=False)

Expand All@@ -96,14 +96,14 @@ def compile_vitamin(v, dom):


else:
print(" Error: scad file not found: "+v['file'])
print((" Error: scad file not found: "+v['file']))


def parse_vitamin(vitaminscad, use_catalogue_call=False):

vitamincall = vitaminscad[:-5];

print(" Calling: "+ vitamincall + "();")
print((" Calling: "+ vitamincall + "();"))

# Generate a wrapper scad file for the vitamin file
with open(config.paths['tempscad'], "w") as f:
Expand DownExpand Up@@ -157,7 +157,7 @@ def parse_vitamin(vitaminscad, use_catalogue_call=False):
js = json.dumps(jso, sort_keys=False, indent=4, separators=(',', ': '))

except Exception as e:
print(" "+e)
print((" "+e))
# Stop malformed machine json screwing up everything else!
js = ''

Expand DownExpand Up@@ -185,7 +185,7 @@ def catalogue():

for filename in os.listdir(config.paths['vitamins']):
if filename[-5:] == '.scad':
print(" Parsing: "+filename)
print((" Parsing: "+filename))

s = ''

Expand DownExpand Up@@ -225,12 +225,12 @@ def catalogue():
try:
jso = json.loads(js)

print("Parsed "+str(files)+" vitamin files")
print(("Parsed "+str(files)+" vitamin files"))

dom = {'vitamins':[]}

for v in jso:
if type(v) is DictType and v['type'] == 'vitamin':
if type(v) is dict and v['type'] == 'vitamin':
try:
compile_vitamin(v, dom)
except Exception as e:
Expand Down
10 changes: 5 additions & 5 deletions scripts/cut.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -33,8 +33,8 @@ def cut():

# for each machine
for m in jso:
if type(m) is DictType and m['type'] == 'machine':
print(m['title'])
if type(m) is dict and m['type'] == 'machine':
print((m['title']))

al = m['cut']

Expand All@@ -43,7 +43,7 @@ def cut():
os.makedirs(config.paths['cutpartsimages'])

for a in al:
print(" "+a['title'])
print((" "+a['title']))
fn = config.paths['root'] + a['file']
if (os.path.isfile(fn)):

Expand DownExpand Up@@ -81,13 +81,13 @@ def cut():
f.close()

# Views
print(" Step "+str(step['num']))
print((" Step "+str(step['num'])))
for view in step['views']:
render_view_using_file(a['title']+'_step'+str(step['num']), config.paths['tempscad'], config.paths['cutpartsimages'], view, hashchanged, h)


else:
print(" Error: scad file not found: "+a['file'])
print((" Error: scad file not found: "+a['file']))


# Save changes to json
Expand Down
22 changes: 11 additions & 11 deletions scripts/guides.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -215,7 +215,7 @@ def assembly_level(a):


def gen_assembly_guide(m, guide_template):
print(m['title'])
print((m['title']))

md = ''

Expand All@@ -224,7 +224,7 @@ def gen_assembly_guide(m, guide_template):

# machine views
for c in m['children']:
if type(c) is DictType and c['type'] == 'view' and 'filepath' in c:
if type(c) is dict and c['type'] == 'view' and 'filepath' in c:
view = c
md += '!['+view['caption']+']('+ view['filepath'][3:] +')\n\n'

Expand DownExpand Up@@ -273,7 +273,7 @@ def gen_assembly_guide(m, guide_template):


def gen_printing_guide(m, guide_template):
print(m['title'])
print((m['title']))

if len(m['printed']) == 0:
return {};
Expand DownExpand Up@@ -347,29 +347,29 @@ def gen_printing_guide(m, guide_template):


def load_sources():
print"Loading sourcing info..."
print("Loading sourcing info...")

load_source(config.paths['sourcingcsv'])

for filename in os.listdir(config.paths['vitamins']):
if filename[-4:] == '.csv':
print(" Parsing: "+filename)
print((" Parsing: "+filename))
csvfn = os.path.join(src_dir, filename)
load_source(csvfn)

def load_source(csvfn):
if os.path.isfile(csvfn):
with open(csvfn, 'rb') as csvfile:
with open(csvfn, 'r') as csvfile:
rdr = csv.DictReader(csvfile)
for row in rdr:
vn = row['Vitamin']
vn = row.get('Vitamin');
if vn not in sourcing:
sourcing[vn] = []
sourcing[vn].append({"Cost":row['Cost'], "Source":row['Source'], 'Notes':row['Notes']});
sourcing[vn].append({"Cost":row.get('Cost'), "Source":row.get('Source'), 'Notes':row.get('Notes')});


def gen_sourcing_guide(m, guide_template):
print(m['title'])
print((m['title']))

if len(m['vitamins']) == 0:
return {};
Expand DownExpand Up@@ -469,7 +469,7 @@ def gen_index(jso, index_file, index_template):
# build object
indexObj = { 'machines': [], 'project':'' };
for m in jso:
if type(m) is DictType and m['type'] == 'machine':
if type(m) is dict and m['type'] == 'machine':

# tack in a view filename
m['viewFilename'] = views.view_filename(m['title'] + '_view')
Expand DownExpand Up@@ -527,7 +527,7 @@ def guides():

# for each machine
for m in jso:
if type(m) is DictType and m['type'] == 'machine':
if type(m) is dict and m['type'] == 'machine':

if 'guides' not in m:
m['guides'] = []
Expand Down
2 changes: 1 addition & 1 deletion scripts/jsontools.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -11,7 +11,7 @@ def json_merge_missing_keys(j1, j2, overwrite=False, exclude=[]):
def get_child_by_key_values(j1, kvs={}):
if 'children' in j1:
for c in j1['children']:
if type(c) is DictType:
if type(c) is dict:
match = True
for kv in kvs:
if not (kv in c and c[kv] == kvs[kv]):
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions README.md
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
# Changes on this fork

This framework is an awesome project from Axford, but it appears to have been abandoned, at least it's not been worked on since 2016 or so (it's now Jan 2019). Original was written for Python 2, and assumed Unix (or Mac?) conventions. I've updated it to work with Python 3 (only tested with 3.6.5) and made some changes to make it work on Windows.

**Note**: I have not tested this extensively. I've only used it with Python 3.6.5 on Win10, and don't know if I broke anything for other platforms. I'm also quite new to using it, so there may be use cases that don't currently work (sadly, the tutorial only has part 1) If you find any bugs, please open an issue, I'll try to take a look.

Everythng below is from the original project.

# OpenSCAD for Machine Design framework

## Overview
Expand Down
4 changes: 2 additions & 2 deletions scripts/adda.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -77,7 +77,7 @@ def adda(t, n, d):
o.write("include <"+incFile+">\n")

else:
print(templateFile + " template is missing")
print((templateFile + " template is missing"))

# Sandbox
templateFile = os.path.join(config.paths['template'],"sandbox","sandbox.scad")
Expand All@@ -93,7 +93,7 @@ def adda(t, n, d):
o.write(s)

else:
print(templateFile + " template is missing")
print((templateFile + " template is missing"))


if __name__ == '__main__':
Expand Down
20 changes: 10 additions & 10 deletions scripts/animate.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -57,8 +57,8 @@ def animateAssembly(mname, aname, prefix, framesPerStep):

# locate required machine
for m in jso:
if type(m) is DictType and m['type'] == 'machine' and m['title'] == mname:
print("Found machine: "+m['title'])
if type(m) is dict and m['type'] == 'machine' and m['title'] == mname:
print(("Found machine: "+m['title']))

al = m['assemblies']

Expand All@@ -70,7 +70,7 @@ def animateAssembly(mname, aname, prefix, framesPerStep):
# locate required assembly
for a in al:
if a['title'] == aname:
print("Found assembly: "+a['title'])
print(("Found assembly: "+a['title']))
fn = config.paths['root'] + a['file']
if (os.path.isfile(fn)):

Expand All@@ -94,7 +94,7 @@ def animateAssembly(mname, aname, prefix, framesPerStep):
}
firstView = True
for step in a['steps']:
print("Step: "+str(step['num']))
print(("Step: "+str(step['num'])))

# generate a transition move?
if len(step['views']) > 0:
Expand DownExpand Up@@ -177,7 +177,7 @@ def animateAssembly(mname, aname, prefix, framesPerStep):
views.PolishTransparentBackground = False
views.PolishCrop = False
fn = view_dir + "/" +prefix + format(frameNum, '03') + "_" +view['title']+".png"
print("Rendering: "+fn)
print(("Rendering: "+fn))
views.render_view_using_file(prefix + format(frameNum, '03'), config.paths['tempscad'], view_dir, view, hashchanged, h)
frameNum = frameNum + 1

Expand All@@ -199,7 +199,7 @@ def animateAssembly(mname, aname, prefix, framesPerStep):
alpha = extra / (1.0*framesPerStep)
if (alpha > 1.0):
alpha = 1.0
print("Blending: "+str(alpha) +", "+str(frameNum))
print(("Blending: "+str(alpha) +", "+str(frameNum)))
imgNew = Image.blend(imgPrev,img,alpha)

draw = ImageDraw.Draw(imgNew, "RGBA")
Expand All@@ -219,7 +219,7 @@ def animateAssembly(mname, aname, prefix, framesPerStep):

fn = view_dir + "/" +prefix + format(frameNum, '03') + "_" +view['title']+".png"
frameNum = frameNum + 1
print("Saving: "+fn)
print(("Saving: "+fn))
imgNew.save(fn)

lfn = fn
Expand DownExpand Up@@ -262,12 +262,12 @@ def animateAssembly(mname, aname, prefix, framesPerStep):

# build video
cmd = "ffmpeg -r "+str(framesPerStep)+" -y -i "+view_dir + "/" + prefix+"%03d_"+view['title']+".png -vcodec libx264 -pix_fmt yuv420p "+view_dir + "/" + prefix+".mp4"
print("Encoding video with: "+cmd)
print(("Encoding video with: "+cmd))
os.system(cmd)

# build animated gif
cmd = "convert "+view_dir + "/" + prefix+".mp4 "+view_dir + "/" + prefix+".gif"
print("Creating GIF with: "+cmd)
print(("Creating GIF with: "+cmd))
os.system(cmd)

# clean up temporary images
Expand All@@ -283,7 +283,7 @@ def animateAssembly(mname, aname, prefix, framesPerStep):
print("Exception running osascript")

else:
print(" Error: scad file not found: "+a['file'])
print((" Error: scad file not found: "+a['file']))

return 0

Expand Down
12 changes: 6 additions & 6 deletions scripts/assemblies.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -34,8 +34,8 @@ def assemblies():

# for each machine
for m in jso:
if type(m) is DictType and m['type'] == 'machine':
print(m['title'])
if type(m) is dict and m['type'] == 'machine':
print((m['title']))

al = m['assemblies']

Expand All@@ -46,7 +46,7 @@ def assemblies():

# for each assembly
for a in al:
print(" "+a['title'])
print((" "+a['title']))
fn = config.paths['root'] + a['file']
if (os.path.isfile(fn)):

Expand All@@ -73,18 +73,18 @@ def assemblies():
f.close()

# Views
print(" Step "+str(step['num']))
print((" Step "+str(step['num'])))
for view in step['views']:
render_view_using_file(a['title']+'_step'+str(step['num']), config.paths['tempscad'], view_dir, view, hashchanged, h)

# for each animation
for anim in a['animations']:
print(" Animation: "+anim['title']+", framesPerStep="+str(anim['framesPerStep']))
print((" Animation: "+anim['title']+", framesPerStep="+str(anim['framesPerStep'])))

animateAssembly(m['title'], a['title'], anim['title'], anim['framesPerStep'])

else:
print(" Error: scad file not found: "+a['file'])
print((" Error: scad file not found: "+a['file']))


# Save changes to json
Expand Down
14 changes: 7 additions & 7 deletions scripts/build.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -22,15 +22,15 @@ def build(argv):
try:
opts, args = getopt.getopt(argv,"hcq",[])
except getopt.GetoptError:
print'build.py -h -c -q'
print ''
print('build.py -h -c -q')
print( '')
sys.exit(2)
for opt, arg in opts:
if opt == '-h':
print'Usage: -h -c -q'
print ''
print' -c Skip catalogue'
print ' -q Quick build - skip assemblies, guide and catalogue'
print('Usage: -h -c -q')
print('')
print(' -c Skip catalogue')
print( ' -q Quick build - skip assemblies, guide and catalogue')
sys.exit()
if opt in ("-c"):
doCatalogue = False
Expand DownExpand Up@@ -82,7 +82,7 @@ def build(argv):
print("Build Complete")

if errorlevel > 0:
print("Error: " + str(errorlevel))
print(("Error: " + str(errorlevel)))

return errorlevel

Expand Down
2 changes: 1 addition & 1 deletion scripts/c14n_stl.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -6,7 +6,7 @@
# This has no effect on the model but makes the STL consistent. I.e. it makes a canonical form.
#

from __future__ import print_function


import sys
import math
Expand Down
20 changes: 10 additions & 10 deletions scripts/catalogue.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -36,7 +36,7 @@ def output_vitamin(v):

# per view
for view in t['children']:
if type(view) is DictType and view['type'] == 'view':
if type(view) is dict and view['type'] == 'view':
md += '!['+t['title']+']('+view['png_name']+')\n'

md += '\n'
Expand DownExpand Up@@ -68,7 +68,7 @@ def compile_vitamin(v, dom):
os.makedirs(config.paths['vitaminsimages'])

# Compile
print(" "+v['title'])
print((" "+v['title']))
fn = '../' + v['file']
if (os.path.isfile(fn)):

Expand All@@ -84,8 +84,8 @@ def compile_vitamin(v, dom):
# Views
print(" Views")
for view in v['children']:
if type(view) is DictType and view['type'] == 'view':
print(" "+view['title'])
if type(view) is dict and view['type'] == 'view':
print((" "+view['title']))

render_view(v['title'], v['call'], config.paths['vitaminsimages'], view, hashchanged, h, [fn], False, useVitaminSTL=False)

Expand All@@ -96,14 +96,14 @@ def compile_vitamin(v, dom):


else:
print(" Error: scad file not found: "+v['file'])
print((" Error: scad file not found: "+v['file']))


def parse_vitamin(vitaminscad, use_catalogue_call=False):

vitamincall = vitaminscad[:-5];

print(" Calling: "+ vitamincall + "();")
print((" Calling: "+ vitamincall + "();"))

# Generate a wrapper scad file for the vitamin file
with open(config.paths['tempscad'], "w") as f:
Expand DownExpand Up@@ -157,7 +157,7 @@ def parse_vitamin(vitaminscad, use_catalogue_call=False):
js = json.dumps(jso, sort_keys=False, indent=4, separators=(',', ': '))

except Exception as e:
print(" "+e)
print((" "+e))
# Stop malformed machine json screwing up everything else!
js = ''

Expand DownExpand Up@@ -185,7 +185,7 @@ def catalogue():

for filename in os.listdir(config.paths['vitamins']):
if filename[-5:] == '.scad':
print(" Parsing: "+filename)
print((" Parsing: "+filename))

s = ''

Expand DownExpand Up@@ -225,12 +225,12 @@ def catalogue():
try:
jso = json.loads(js)

print("Parsed "+str(files)+" vitamin files")
print(("Parsed "+str(files)+" vitamin files"))

dom = {'vitamins':[]}

for v in jso:
if type(v) is DictType and v['type'] == 'vitamin':
if type(v) is dict and v['type'] == 'vitamin':
try:
compile_vitamin(v, dom)
except Exception as e:
Expand Down
10 changes: 5 additions & 5 deletions scripts/cut.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -33,8 +33,8 @@ def cut():

# for each machine
for m in jso:
if type(m) is DictType and m['type'] == 'machine':
print(m['title'])
if type(m) is dict and m['type'] == 'machine':
print((m['title']))

al = m['cut']

Expand All@@ -43,7 +43,7 @@ def cut():
os.makedirs(config.paths['cutpartsimages'])

for a in al:
print(" "+a['title'])
print((" "+a['title']))
fn = config.paths['root'] + a['file']
if (os.path.isfile(fn)):

Expand DownExpand Up@@ -81,13 +81,13 @@ def cut():
f.close()

# Views
print(" Step "+str(step['num']))
print((" Step "+str(step['num'])))
for view in step['views']:
render_view_using_file(a['title']+'_step'+str(step['num']), config.paths['tempscad'], config.paths['cutpartsimages'], view, hashchanged, h)


else:
print(" Error: scad file not found: "+a['file'])
print((" Error: scad file not found: "+a['file']))


# Save changes to json
Expand Down
22 changes: 11 additions & 11 deletions scripts/guides.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -215,7 +215,7 @@ def assembly_level(a):


def gen_assembly_guide(m, guide_template):
print(m['title'])
print((m['title']))

md = ''

Expand All@@ -224,7 +224,7 @@ def gen_assembly_guide(m, guide_template):

# machine views
for c in m['children']:
if type(c) is DictType and c['type'] == 'view' and 'filepath' in c:
if type(c) is dict and c['type'] == 'view' and 'filepath' in c:
view = c
md += '!['+view['caption']+']('+ view['filepath'][3:] +')\n\n'

Expand DownExpand Up@@ -273,7 +273,7 @@ def gen_assembly_guide(m, guide_template):


def gen_printing_guide(m, guide_template):
print(m['title'])
print((m['title']))

if len(m['printed']) == 0:
return {};
Expand DownExpand Up@@ -347,29 +347,29 @@ def gen_printing_guide(m, guide_template):


def load_sources():
print"Loading sourcing info..."
print("Loading sourcing info...")

load_source(config.paths['sourcingcsv'])

for filename in os.listdir(config.paths['vitamins']):
if filename[-4:] == '.csv':
print(" Parsing: "+filename)
print((" Parsing: "+filename))
csvfn = os.path.join(src_dir, filename)
load_source(csvfn)

def load_source(csvfn):
if os.path.isfile(csvfn):
with open(csvfn, 'rb') as csvfile:
with open(csvfn, 'r') as csvfile:
rdr = csv.DictReader(csvfile)
for row in rdr:
vn = row['Vitamin']
vn = row.get('Vitamin');
if vn not in sourcing:
sourcing[vn] = []
sourcing[vn].append({"Cost":row['Cost'], "Source":row['Source'], 'Notes':row['Notes']});
sourcing[vn].append({"Cost":row.get('Cost'), "Source":row.get('Source'), 'Notes':row.get('Notes')});


def gen_sourcing_guide(m, guide_template):
print(m['title'])
print((m['title']))

if len(m['vitamins']) == 0:
return {};
Expand DownExpand Up@@ -469,7 +469,7 @@ def gen_index(jso, index_file, index_template):
# build object
indexObj = { 'machines': [], 'project':'' };
for m in jso:
if type(m) is DictType and m['type'] == 'machine':
if type(m) is dict and m['type'] == 'machine':

# tack in a view filename
m['viewFilename'] = views.view_filename(m['title'] + '_view')
Expand DownExpand Up@@ -527,7 +527,7 @@ def guides():

# for each machine
for m in jso:
if type(m) is DictType and m['type'] == 'machine':
if type(m) is dict and m['type'] == 'machine':

if 'guides' not in m:
m['guides'] = []
Expand Down
2 changes: 1 addition & 1 deletion scripts/jsontools.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -11,7 +11,7 @@ def json_merge_missing_keys(j1, j2, overwrite=False, exclude=[]):
def get_child_by_key_values(j1, kvs={}):
if 'children' in j1:
for c in j1['children']:
if type(c) is DictType:
if type(c) is dict:
match = True
for kv in kvs:
if not (kv in c and c[kv] == kvs[kv]):
Expand Down
Loading