Merge pull request #4 from joemarshall/autoupdate

Autoupdate
pull/254/head
Joe Marshall 2024-01-12 16:06:15 +00:00 zatwierdzone przez GitHub
commit b63abfe007
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
87 zmienionych plików z 248 dodań i 2317 usunięć

Wyświetl plik

@ -1,694 +0,0 @@
bl_info = {
"name": "G - Pack",
"author": "Velem Novak",
"version": (0, 2, 0),
"blender": (2, 77, 0),
"location": "Object > G-Pack",
"description": "UV packing game",
"warning": "",
"wiki_url": "http://www.blendercam.blogspot.com",
"category": "Object"
}
import bpy
import math, random, os
import mathutils
from mathutils import *
import bmesh
PRECISION=0.0000000001
def activate(ob):
bpy.ops.object.select_all(action='DESELECT')
ob.select=True
bpy.context.scene.objects.active=ob
def createMeshFromData(name, verts, faces):
# Create mesh and object
me = bpy.data.meshes.new(name+'Mesh')
ob = bpy.data.objects.new(name, me)
#ob.show_name = True
# Link object to scene and make active
scn = bpy.context.scene
scn.objects.link(ob)
scn.objects.active = ob
ob.select = True
# Create mesh from given verts, faces.
me.from_pydata(verts, [], faces)
# Update mesh with new data
me.update()
return ob
def getIslands(me):
bm = bmesh.from_edit_mesh(me)
for f in bm.faces:
f.select=False
all=False
done={}
islands=[]
while not len(done)>=len(bm.faces):
island=[]
for i,p in enumerate(bm.faces):
if done.get(i) == None:
p.select=True
done[i]=True
island.append(p.index)
break
nf = [p]
while len(nf)>0:
selected_faces = nf
nf = []
for f in selected_faces:
for edge in f.edges:
if edge.seam==False:
linkede = edge.link_faces
for face in linkede:
if not face.select and done.get(face.index)==None:
done[face.index]=True
nf.append(face)
face.select=True
island.append(face.index)
islands.append(island)
return islands
#print(islands)
def GameDropOb(ob,margin,enablerotation):
activate(ob)
#ob.rotation_euler.x=math.pi/2
#bpy.ops.object.transform_apply(location=False, rotation=True, scale=False)
#ob.location.z = ob.location.y
#ob.location.x=0
ob.select=True
ob.game.physics_type='RIGID_BODY'
ob.game.use_collision_bounds=True
ob.game.collision_bounds_type = 'TRIANGLE_MESH'
ob.game.collision_margin = margin
ob.game.velocity_max = 1
ob.game.damping = 0.5
ob.game.rotation_damping = 0.9
ob.game.lock_location_y = True
ob.game.lock_rotation_x = True
if not enablerotation:
ob.game.lock_rotation_y = True#conditional#
ob.game.lock_rotation_z = True
bpy.ops.object.game_property_new(name="island")
def UVobs(obs,set):
uvobs=[]
zoffset=0
for ob in obs:
activate(ob)
bpy.ops.object.editmode_toggle()
if set.startConditions=='NEW':
bpy.ops.uv.pack_islands(margin=0.01)
#print('a')
islands = getIslands(ob.data)
#print('b')
bpy.ops.object.editmode_toggle()
print(len(islands))
for iidx,island in enumerate(islands):
out_verts=[]
out_faces=[]
print(iidx,len(islands))
vertidx=0
vertindices= {}
loops=[]
for fi in island:
face = ob.data.polygons[fi]
oface=[]
for vert, loop in zip(face.vertices, face.loop_indices):
uv = ob.data.uv_layers.active.data[loop].uv.copy()
# if vertindices.get(vert) == None:
#
# vertindices[vert]=vertidx
# nvertindex = vertidx
# out_verts.append((uv.x,0,uv.y))
# vertidx+=1
#
#
# nvertindex = vertindices[vert]
#
# #print(vert,nvertindex, vertindices)
# #print()
# oface.append(nvertindex)
loops.append(loop)
out_verts.append((uv.x,0,uv.y))
oface.append(vertidx)
vertidx+=1
#print(oface)
out_faces.append(oface)
#print(out_verts,out_faces)
uvob = createMeshFromData(ob.name + 'UVObj', out_verts, out_faces)
activate(uvob)
bpy.ops.mesh.uv_texture_add()
#print(uvob.name)
#print(bpy.context.active_object.name)
activate(uvob)
vertidx = 0
for fi in island:
face = ob.data.polygons[fi]
oface=[]
for vert, loop in zip(face.vertices, face.loop_indices):
uvob.data.uv_layers.active.data[vertidx].uv = (loops[vertidx],0)#ob.data.uv_layers.active.data[loop].uv
#print('loop',loops[vertidx])
vertidx+=1
print(uvob.name)
bpy.ops.object.editmode_toggle()
bpy.ops.mesh.remove_doubles(threshold = 0.0000001)
#print('d')
bpy.ops.object.editmode_toggle()
bpy.ops.object.modifier_add(type='SOLIDIFY')
bpy.context.object.modifiers["Solidify"].thickness = min(0.3, min(uvob.dimensions.x,uvob.dimensions.y)) #0.1
bpy.ops.object.modifier_apply(apply_as='DATA', modifier="Solidify")
#print('e')
uvob['source']=ob.name
uvob['island']=iidx
uvob['islandindices']=island
if set.startConditions=='NEW':
uvob.location.z+=zoffset#we shift the uv to not collide when packing more objects
uvobs.append(uvob)
bpy.ops.object.origin_set(type='ORIGIN_CENTER_OF_MASS')
zoffset+=uvob.dimensions.z+0.005
#fal
print('c')
for ob in uvobs:
ob.select=True
s=bpy.context.scene
s.objects.active=uvobs[0]
bpy.ops.object.material_slot_add()
mat=bpy.data.materials.new('GPackMaterial')
uvobs[0].material_slots[0].material=mat
mat.use_object_color = True
for ob in uvobs:
ob.color = (0.5+random.random(),0.5+random.random(),0.5+random.random(),1)
mat.diffuse_color = (1,1,1)
bpy.ops.object.make_links_data(type='MATERIAL')
return uvobs
def doGameUV(context):
#getIslands(bpy.context.active_object)
obs=bpy.context.selected_objects
activeOb=bpy.context.object
origscene=bpy.context.scene
import_scene('GPack')
set=bpy.context.scene.gpacker_settings
uvobs = UVobs(obs,set)
for ob in uvobs:
GameDropOb(ob,set.initialmargin, set.enablerotation)
bpy.ops.object.select_all(action='DESELECT')
for ob in uvobs:
ob.select=True
bpy.ops.group.create()
bpy.ops.object.make_links_scene(scene='GPack')
bpy.ops.object.delete(use_global=False)
bpy.context.window.screen.scene = bpy.data.scenes['GPack']
bpy.ops.view3d.viewnumpad(type='CAMERA')
bpy.context.space_data.viewport_shade = 'MATERIAL'
#bpy.ops.view3d.zoom_camera_1_to_1()
#bpy.context.scene.update()
for ob in bpy.data.scenes['GPack'].objects:
if ob.game.properties.get('startconditions')!=None:
ob.game.properties['startconditions'].value = set.startConditions
ob.game.properties['doobjects'].value = False
ob.game.properties['xsize'].value = set.xsize
ob.game.properties['ysize'].value = set.ysize
#PLAY THE GAME!
bpy.ops.view3d.game_start()
if set.apply==True:
print('after game')
#reassign UV's
bpy.context.scene.update()
#get size object
for ob in bpy.context.scene.objects:
if ob.name[:5]=='ssize':
scale=ob.location.z+1
for uvob in uvobs:
uvobmat=uvob.matrix_world
ob=bpy.data.objects[uvob['source']]
assigns=[]
for uvfi,fi in enumerate(uvob['islandindices']):
face = ob.data.polygons[fi]
uvface = uvob.data.polygons[uvfi]
for vert1, loop1 in zip(uvface.vertices, uvface.loop_indices):
co=uvobmat*uvob.data.vertices[vert1].co/scale
idxuv = int(uvob.data.uv_layers.active.data[loop1].uv.x)
print(idxuv)
uv=ob.data.uv_layers.active.data[idxuv].uv
uv.x = co.x
uv.y = co.z
#print(fdict)
assigns=[]
print(len(assigns))
bpy.context.window.screen.scene = origscene
bpy.data.scenes.remove(bpy.data.scenes['GPack'], do_unlink = True)
bpy.data.texts.remove(bpy.data.texts['root'])
activate(activeOb)
for ob in obs:
ob.select=True
#packing of curves
def getBoundsWorldspace(ob):
#progress('getting bounds of object(s)')
maxx=maxy=maxz=-10000000
minx=miny=minz=10000000
bb=ob.bound_box
mw=ob.matrix_world
for coord in bb:
#this can work badly with some imported curves, don't know why...
#worldCoord = mw * Vector((coord[0]/ob.scale.x, coord[1]/ob.scale.y, coord[2]/ob.scale.z))
worldCoord = mw * Vector((coord[0], coord[1], coord[2]))
minx=min(minx,worldCoord.x)
miny=min(miny,worldCoord.y)
minz=min(minz,worldCoord.z)
maxx=max(maxx,worldCoord.x)
maxy=max(maxy,worldCoord.y)
maxz=max(maxz,worldCoord.z)
#progress(time.time()-t)
return minx,miny,minz,maxx,maxy,maxz
def getBoundsSpline(s):
#progress('getting bounds of object(s)')
maxx=maxy=maxz=-10000000
minx=miny=minz=10000000
for p in s.points:
#this can work badly with some imported curves, don't know why...
#worldCoord = mw * Vector((coord[0]/ob.scale.x, coord[1]/ob.scale.y, coord[2]/ob.scale.z))
minx=min(minx,p.co.x)
miny=min(miny,p.co.y)
minz=min(minz,p.co.z)
maxx=max(maxx,p.co.x)
maxy=max(maxy,p.co.y)
maxz=max(maxz,p.co.z)
for p in s.bezier_points:
minx=min(minx,p.co.x)
miny=min(miny,p.co.y)
minz=min(minz,p.co.z)
maxx=max(maxx,p.co.x)
maxy=max(maxy,p.co.y)
maxz=max(maxz,p.co.z)
#progress(time.time()-t)
return minx,miny,minz,maxx,maxy,maxz
def getInstances(obs):
instanceindices=[]
data=[]
dataindices=[]
counti=0
#dataindex=0
for ob in obs:
if not ob.data in data:# or 1:
data.append(ob.data)
instanceindices.append(counti)
dataindices.append(counti)
#dataindex+=1
else:
i = data.index(ob.data)
#print(i);
instanceindices.append(instanceindices[dataindices[i]])
counti+=1
print('number of original shapes',str(len(data)))
print(instanceindices)
return instanceindices
def prepareCurves(obs, set):
packobs=[]
zoffset=0
instanceindices=getInstances(obs)
instanceindex=0
e=mathutils.Euler((math.pi/2,0,0))
for ob in obs:
if ob.type=='CURVE':
oldloc=ob.location.copy()
if instanceindices[instanceindex]==instanceindex:
activate(ob)
bpy.ops.object.duplicate()
packob=bpy.context.active_object
#bpy.ops.object.rotation_clear()
simplify=True
thickness=0.1
if simplify:
c=packob.data
if len(c.splines)>0:
maxbounds=-10000
maxc=0
for i in range(0,len(c.splines)):
minx,miny,minz,maxx,maxy,maxz=getBoundsSpline(c.splines[i])
if maxx-minx+maxy-miny>maxbounds:
maxc=i
maxbounds= maxx-minx+maxy-miny
for i in range(len(c.splines)-1,-1,-1):
if i!=maxc:
c.splines.remove(c.splines[i])
doconvert=False
for s in c.splines:
if s.type!='POLY':
doconvert=True
if doconvert:
c.dimensions = '3D'
bpy.ops.object.convert(target='MESH')
bpy.ops.object.convert(target='CURVE')
bpy.ops.curve.simplify(error = 0.001)
#delete packob here?
bpy.context.scene.objects.unlink(packob)
packob=bpy.context.active_object
activate(packob)
for s in packob.data.splines:
s.use_cyclic_u=True
if min(maxx-minx,maxy-miny)<0.1:
thickness=min(maxx-minx,maxy-miny)
packob.data.dimensions = '2D'
bpy.context.active_object.rotation_euler.rotate(e)
#packob.rotation_euler=(math.pi/2,0,0)
#bpy.ops.object.origin_set(type='ORIGIN_CENTER_OF_MASS')
newloc=packob.location.copy()
#print(newloc-oldloc)
bpy.ops.object.convert(target='MESH')
activate(packob)
bpy.ops.object.transform_apply(location=False, rotation=False, scale=True)
#print(packob.name)
#print(bpy.context.active_object)
bpy.ops.object.modifier_add(type='SOLIDIFY')
bpy.context.object.modifiers["Solidify"].thickness = thickness
bpy.ops.object.modifier_apply(apply_as='DATA', modifier="Solidify")
#bpy.ops.object.transform_apply(location=False, rotation=True, scale=True)
else:
print(instanceindex)
source_packob=packobs[instanceindices[instanceindex]][0]
activate(source_packob)
bpy.ops.object.duplicate(linked=True)
packob=bpy.context.active_object
packob.rotation_euler=(math.pi/2,-ob.rotation_euler.z,0)
#packob.rotation_euler.rotate()
#packob.rotation_euler.rotate(e)
packob['source']=ob.name
if set.startConditions=='TWEAK' or set.startConditions=='FIXED':
packob.location=(oldloc.x,0,oldloc.y)
if set.startConditions=='NEW':
packob.location=(0,0,0)
bpy.ops.object.location_clear()
packob.rotation_euler=(math.pi/2,0,0)
minx,maxx,miny,maxy,minz,maxz=getBoundsWorldspace(packob)
packob.location.x=-minx
packob.location.z= -miny+zoffset
zoffset+= maxy-miny
#bpy.ops.object.editmode_toggle()
#bpy.ops.mesh.separate(type='LOOSE')
#bpy.ops.object.editmode_toggle()
packobs.append((packob,ob, newloc-oldloc))
instanceindex+=1
return packobs
def doGameObs(context):
#getIslands(bpy.context.active_object)
obs=bpy.context.selected_objects
origscene=bpy.context.scene
import_scene('GPack')
set=bpy.context.scene.gpacker_settings
packobs=prepareCurves(obs,set)
gobs=[]
for data in packobs:
ob=data[0]
GameDropOb(ob,set.initialmargin, set.enablerotation)
for data in packobs:
data[0].select=True
bpy.ops.group.create()
print('done')
bpy.ops.object.make_links_scene(scene='GPack')
bpy.ops.object.delete(use_global=False)
bpy.context.window.screen.scene = bpy.data.scenes['GPack']
bpy.ops.view3d.viewnumpad(type='CAMERA')
bpy.context.space_data.viewport_shade = 'MATERIAL'
#pass data to game:
for ob in bpy.data.scenes['GPack'].objects:
if ob.game.properties.get('startconditions')!=None:
ob.game.properties['startconditions'].value = set.startConditions
ob.game.properties['doobjects'].value = True
ob.game.properties['xsize'].value = set.xsize
ob.game.properties['ysize'].value = set.ysize
bpy.ops.view3d.game_start()
for s in bpy.data.scenes:
s.gpacker_settings.doobjects=False
print('repack')
if set.apply:
for data in packobs:
print(data[0].location,data[1].location)
data[1].location.x=data[0].location.x
data[1].location.y=data[0].location.z
data[1].rotation_euler.z=-data[0].rotation_euler.y
#bpy.context.scene.objects.unlink(data[0])
for s in bpy.data.scenes:
s.gpacker_settings.apply=False
bpy.context.window.screen.scene = origscene
bpy.data.scenes.remove(bpy.data.scenes['GPack'])
for ob in obs:
ob.select=True
#####################################################################
# Import Functions
def import_scene(obname):
opath = "//data.blend\\Scene\\" + obname
s = os.sep
for p in bpy.utils.script_paths():
fname= p + '%saddons%sGPack%spack_scene.blend' % (s,s,s)
dpath = p + \
'%saddons%sGPack%spack_scene.blend\\Scene\\' % (s, s, s)
if os.path.isfile(fname):
break
# DEBUG
#print('import_object: ' + opath)
print(dpath,opath)
result = bpy.ops.wm.append(
filepath=opath,
filename=obname,
directory=dpath,
filemode=1,
link=False,
autoselect=True,
active_layer=True,
instance_groups=True
)
print(result)
import bpy
class GPackUVOperator(bpy.types.Operator):
"""Tooltip"""
bl_idname = "object.gpack_uv"
bl_label = "Gravity Pack UVs"
@classmethod
def poll(cls, context):
return len(context.selected_objects)>0
def execute(self, context):
doGameUV(context)
return {'FINISHED'}
class GPackCurvesOperator(bpy.types.Operator):
"""Tooltip"""
bl_idname = "object.gpack"
bl_label = "Gravity Pack Curves"
@classmethod
def poll(cls, context):
return len(context.selected_objects)>0
def execute(self, context):
doGameObs(context)
return {'FINISHED'}
class GPackSettings(bpy.types.PropertyGroup):
#lpgroup = bpy.props.StringProperty(name="low poly group", default="")
#hpgroup = bpy.props.StringProperty(name="high poly group", default="")
apply = bpy.props.BoolProperty(name="apply",description="", default=False)
doobjects = bpy.props.BoolProperty(name="doobjects",description="", default=False)
startConditions = bpy.props.EnumProperty(name='start state', items=(('NEW','Drop All','all parts are dropped into the layout'),('FIXED','Fixed','All objects are still in beginning, just tweak the extra additions'),('TWEAK','Tweak','start from current state, position objects before to drop properly')),
description='start conditions',
default='TWEAK')
xsize = bpy.props.FloatProperty(name="X-sheet-size",description="", default=1)
ysize = bpy.props.FloatProperty(name="Y-size",description="", default=1)
initialmargin = bpy.props.FloatProperty(name="initial margin",description="", default=0.003)
enablerotation = bpy.props.BoolProperty(name="rotation",description="", default=True)
class GPackCurvesPanel(bpy.types.Panel):
"""Creates a Panel in the Object properties window"""
bl_space_type = 'VIEW_3D'
bl_region_type = 'TOOLS'
bl_label = "Gravity Packer"
bl_idname = "WORLD_PT_GPACKER"
bl_context = "objectmode"
bl_options = {'DEFAULT_CLOSED'}
bl_category = "Tools"
def draw(self, context):
layout = self.layout
obj = bpy.context.active_object
#s=bpy.context.scene
s=bpy.context.scene.gpacker_settings
row = layout.row()
layout.operator("object.gpack")
layout.operator("object.gpack_uv")
#layout.prop_search(s, "lpgroup", bpy.data, "groups")
#layout.prop_search(s, "hpgroup", bpy.data, "groups")
layout.prop(s,'startConditions')
layout.prop(s,'xsize')
layout.prop(s,'ysize')
layout.prop(s,'initialmargin')
layout.prop(s,'enablerotation')
#layout.prop(s,'pass_combined')
# separate UV's????
# class GPackUVPanel(bpy.types.Panel):
# '''Creates a Panel in the Object properties window"""
# bl_label = "Gravity Packer"
# bl_idname = "WORLD_PT_GPACKER"
# bl_space_type = 'PROPERTIES'
# bl_region_type = 'WINDOW'
# bl_context = "object"
#
#
# def draw(self, context):
# layout = self.layout
#
# obj = bpy.context.active_object
# #s=bpy.context.scene
# s=bpy.context.scene.gpacker_settings
# row = layout.row()
# layout.operator("object.gpack_uv")
# #layout.prop_search(s, "lpgroup", bpy.data, "groups")
# #layout.prop_search(s, "hpgroup", bpy.data, "groups")
#
# layout.prop(s,'startConditions')
# layout.prop(s,'xsize')
# layout.prop(s,'ysize')
# layout.prop(s,'initialmargin')
#
#
# #layout.prop(s,'pass_combined')
def register():
s = bpy.types.Scene
bpy.utils.register_class(GPackUVOperator)
bpy.utils.register_class(GPackCurvesOperator)
bpy.utils.register_class(GPackSettings)
bpy.utils.register_class(GPackCurvesPanel)
s.gpacker_settings = bpy.props.PointerProperty(type= GPackSettings)
def unregister():
bpy.utils.unregister_class(GPackUVOperator)
bpy.utils.unregister_class(GPackCurvesOperator)
bpy.utils.unregister_class(GPackSettings)
bpy.utils.unregister_class(GPackCurvesPanel)
if __name__ == "__main__":
register()

Plik binarny nie jest wyświetlany.

Plik binarny nie jest wyświetlany.

Plik binarny nie jest wyświetlany.

Wyświetl plik

@ -28,11 +28,14 @@ import math
import numpy
import os
import pickle
import shutil
import subprocess
import sys
import threading
import time
from pathlib import Path
try:
import shapely
except ImportError:
@ -47,7 +50,7 @@ from bpy.props import *
from bpy.types import Menu, Operator, UIList, AddonPreferences
from bpy_extras.object_utils import object_data_add
from cam import ui, ops, curvecamtools, curvecamequation, curvecamcreate, utils, simple, \
polygon_utils_cam # , post_processors
polygon_utils_cam, autoupdate, basrelief # , post_processors
from mathutils import *
from shapely import geometry as sgeometry
@ -119,6 +122,7 @@ def updateOperation(self, context):
print(e)
class CamAddonPreferences(AddonPreferences):
# this must match the addon name, use '__package__'
# when defining this in a submodule of a python package.
@ -129,6 +133,36 @@ class CamAddonPreferences(AddonPreferences):
default=False,
)
update_source: bpy.props.StringProperty(
name="Source of updates for the addon",
description="This can be either a github repo link in which case it will download the latest release on there, "
"or an api link like https://api.github.com/repos/<author>/blendercam/commits to get from a github repository",
default="https://github.com/pppalain/blendercam",
)
last_update_check: IntProperty(
name="Last update time",
default=0
)
last_commit_hash: StringProperty(
name="Hash of last commit from updater",
default=""
)
just_updated: BoolProperty(
name="Set to true on update or initial install",
default=True
)
new_version_available: StringProperty(
name="Set to new version name if one is found",
default=""
)
default_interface_level: bpy.props.EnumProperty(
name="Interface level in new file",
description="Choose visible options",
@ -148,9 +182,23 @@ class CamAddonPreferences(AddonPreferences):
def draw(self, context):
layout = self.layout
layout.label(text="Use experimental features when you want to help development of Blender CAM:")
layout.prop(self, "experimental")
layout.prop(self, "update_source")
layout.label(text="Choose a preset update source")
UPDATE_SOURCES=[("https://github.com/vilemduha/blendercam", "Stable", "Stable releases (github.com/vilemduja/blendercam)"),
("https://github.com/pppalain/blendercam", "Unstable", "Unstable releases (github.com/pppalain/blendercam)"),
# comments for searching in github actions release script to automatically set this repo
# if required
## REPO ON NEXT LINE
("https://api.github.com/repos/pppalain/blendercam/commits","Direct from git (may not work)","Get from git commits directly"),
## REPO ON PREV LINE
("","None","Don't do auto update"),
]
grid=layout.grid_flow(align=True)
for (url,short,long) in UPDATE_SOURCES:
op=grid.operator("render.cam_set_update_source",text=short)
op.new_source=url
class machineSettings(bpy.types.PropertyGroup):
"""stores all data for machines"""
@ -1170,6 +1218,20 @@ def check_operations_on_load(context):
# load last used machine preset
bpy.ops.script.execute_preset(filepath=machine_preset,menu_idname="CAM_MACHINE_MT_presets")
_IS_LOADING_DEFAULTS=False
# check for updated version of the plugin
bpy.ops.render.cam_check_updates()
# copy presets if not there yet
if bpy.context.preferences.addons['cam'].preferences.just_updated:
preset_source_path = Path(__file__).parent / 'presets'
preset_target_path = Path(bpy.utils.script_path_user()) / 'presets'
def copy_if_not_exists(src,dst):
if Path(dst).exists()==False:
shutil.copy2(src,dst)
shutil.copytree(preset_source_path,preset_target_path,copy_function=copy_if_not_exists,dirs_exist_ok=True)
bpy.context.preferences.addons['cam'].preferences.just_updated=False
bpy.ops.wm.save_userpref()
@ -1380,6 +1442,9 @@ def compatible_panels():
classes = [
autoupdate.UpdateSourceOperator,
autoupdate.Updater,
autoupdate.UpdateChecker,
ui.CAM_UL_operations,
ui.CAM_UL_chains,
opReference,
@ -1482,7 +1547,6 @@ classes = [
def register():
for p in classes:
bpy.utils.register_class(p)
@ -1510,6 +1574,8 @@ def register():
bpy.types.Scene.interface = bpy.props.PointerProperty(type=CAM_INTERFACE_Properties)
basrelief.register()
def unregister():
for p in classes:
@ -1526,3 +1592,4 @@ def unregister():
del s.cam_text
del s.cam_pack
del s.cam_slice
basrelief.unregister()

Wyświetl plik

@ -0,0 +1,164 @@
from datetime import date
from cam.version import __version__ as current_version
from urllib.request import urlopen
import json
import pathlib
import zipfile
import bpy
import re
import io
import os
import sys
import calendar
class UpdateChecker(bpy.types.Operator):
"""check for updates"""
bl_idname = "render.cam_check_updates"
bl_label = "Check for updates in blendercam plugin"
bl_options = {'REGISTER', 'UNDO'}
def execute(self, context):
last_update_check = bpy.context.preferences.addons['cam'].preferences.last_update_check
today=date.today().toordinal()
update_source = bpy.context.preferences.addons['cam'].preferences.update_source
match = re.match(r"https://github.com/([^/]+/[^/]+)",update_source)
if match:
update_source = f"https://api.github.com/repos/{match.group(1)}/releases"
print(f"update check: {update_source}")
if update_source=="None" or len(update_source)==0:
return {'FINISHED'}
bpy.context.preferences.addons['cam'].preferences.new_version_available = ""
bpy.ops.wm.save_userpref()
# get list of releases from github release
if update_source.endswith("/releases"):
with urlopen(update_source,timeout=2.0) as response:
body = response.read().decode("UTF-8")
# find the tag name
release_list=json.loads(body)
if len(release_list) > 0:
release = release_list[0]
tag = release["tag_name"]
print(f"Found release: {tag}")
match = re.match(r".*(\d+)\.(\s*\d+)\.(\s*\d+)",tag)
if match:
version_num = tuple(map(int,match.groups()))
print(f"Found version: {version_num}")
bpy.context.preferences.addons['cam'].preferences.last_update_check = today
if version_num > current_version:
bpy.context.preferences.addons['cam'].preferences.new_version_available = ".".join(
[str(x) for x in version_num])
bpy.ops.wm.save_userpref()
elif update_source.endswith("/commits"):
with urlopen(update_source+"?per_page=1",timeout=2) as response:
body = response.read().decode("UTF-8")
# find the tag name
commit_list=json.loads(body)
commit_sha=commit_list[0]['sha']
commit_date=commit_list[0]['commit']['author']['date']
if bpy.context.preferences.addons['cam'].preferences.last_commit_hash != commit_sha:
bpy.context.preferences.addons['cam'].preferences.new_version_available=commit_date
bpy.ops.wm.save_userpref()
return {'FINISHED'}
class Updater(bpy.types.Operator):
"""update to newer version if possible """
bl_idname = "render.cam_update_now"
bl_label = "Update"
bl_options = {'REGISTER', 'UNDO'}
def execute(self, context):
print("update check")
last_update_check = bpy.context.preferences.addons['cam'].preferences.last_update_check
today=date.today().toordinal()
update_source = bpy.context.preferences.addons['cam'].preferences.update_source
if update_source=="None" or len(update_source)==0:
return {'FINISHED'}
match = re.match(r"https://github.com/([^/]+/[^/]+)",update_source)
if match:
update_source = f"https://api.github.com/repos/{match.group(1)}/releases"
# get list of releases from github release
if update_source.endswith("/releases"):
with urlopen(update_source,timeout=2) as response:
body = response.read().decode("UTF-8")
# find the tag name
release_list=json.loads(body)
if len(release_list) > 0:
release = release_list[0]
tag = release["tag_name"]
print(f"Found release: {tag}")
match = re.match(r".*(\d+)\.(\s*\d+)\.(\s*\d+)",tag)
if match:
version_num = tuple(map(int,match.groups()))
print(f"Found version: {version_num}")
bpy.context.preferences.addons['cam'].preferences.last_update_check = today
bpy.ops.wm.save_userpref()
if version_num > current_version:
print("Version is newer, downloading source")
zip_url = release["zipball_url"]
self.install_zip_from_url(zip_url)
return {'FINISHED'}
elif update_source.endswith("/commits"):
with urlopen(update_source+"?per_page=1",timeout=2) as response:
body = response.read().decode("UTF-8")
# find the tag name
commit_list=json.loads(body)
commit_sha=commit_list[0]['sha']
if bpy.context.preferences.addons['cam'].preferences.last_commit_hash != commit_sha:
# get zipball from this commit
zip_url = update_source.replace("/commits",f"/zipball/{commit_sha}")
self.install_zip_from_url(zip_url)
bpy.context.preferences.addons['cam'].preferences.last_commit_hash = commit_sha
bpy.ops.wm.save_userpref()
return {'FINISHED'}
def install_zip_from_url(self,zip_url):
with urlopen(zip_url) as zip_response:
zip_body=zip_response.read()
buffer= io.BytesIO(zip_body)
zf=zipfile.ZipFile(buffer,mode='r')
files=zf.infolist()
cam_addon_path = pathlib.Path(__file__).parent
for fileinfo in files:
filename=fileinfo.filename
if fileinfo.is_dir() == False:
path_pos=filename.replace("\\","/").find("/scripts/addons/cam/")
if path_pos!=-1:
relative_path=filename[path_pos+len("/scripts/addons/cam/"):]
out_path = cam_addon_path / relative_path
print(out_path)
# check folder exists
out_path.parent.mkdir(parents=True,exist_ok=True)
with zf.open(filename,"r") as in_file, open(out_path,"wb") as out_file:
time_struct=(*fileinfo.date_time,0,0,0)
mtime=calendar.timegm(time_struct)
out_file.write(in_file.read())
os.utime(out_path,times=(mtime,mtime))
# TODO: check for newer times
# TODO: what about if a file is deleted...
# updated everything, now mark as updated and reload scripts
bpy.context.preferences.addons['cam'].preferences.just_updated=True
bpy.context.preferences.addons['cam'].preferences.new_version_available = ""
bpy.ops.wm.save_userpref()
# unload ourself from python module system
delete_list=[]
for m in sys.modules.keys():
if m.startswith("cam.") or m=='cam':
delete_list.append(m)
for d in delete_list:
del sys.modules[d]
bpy.ops.script.reload()
class UpdateSourceOperator(bpy.types.Operator):
bl_idname = "render.cam_set_update_source"
bl_label = "Set blendercam update source"
new_source: bpy.props.StringProperty(default='')
def execute(self,context):
bpy.context.preferences.addons['cam'].preferences.update_source=self.new_source
bpy.ops.wm.save_userpref()
return {'FINISHED'}

Wyświetl plik

@ -6,18 +6,6 @@ from math import *
from bpy.props import *
bl_info = {
"name": "Bas relief",
"author": "Vilem Novak",
"version": (0, 1, 0),
"blender": (2, 80, 0),
"location": "Properties > render",
"description": "Converts zbuffer image to bas relief.",
"warning": "there is no warranty. needs Numpy library installed in blender python directory.",
"wiki_url": "blendercam.blogspot.com",
"tracker_url": "",
"category": "Scene"}
##////////////////////////////////////////////////////////////////////
#// Full Multigrid Algorithm for solving partial differential equations
#//////////////////////////////////////////////////////////////////////
@ -1164,5 +1152,3 @@ def unregister():
s=bpy.types.Scene
del s.basreliefsettings
if __name__ == "__main__":
register()

Wyświetl plik

@ -4,6 +4,7 @@ from cam.simple import strInUnits
from cam.ui_panels.buttons_panel import CAMButtonsPanel
import cam.utils
import cam.constants
from cam.version import __version__ as cam_version
# Info panel
# This panel gives general information about the current operation
@ -33,13 +34,23 @@ class CAM_INFO_Panel(CAMButtonsPanel, bpy.types.Panel):
panel_interface_level = 0
prop_level = {
'draw_blendercam_version': 0,
'draw_opencamlib_version': 1,
'draw_op_warnings': 0,
'draw_op_time': 0,
'draw_op_chipload': 0,
'draw_op_money_cost': 1
'draw_op_money_cost': 1,
}
# Draw blendercam version (and whether there are updates available)
def draw_blendercam_version(self):
if not self.has_correct_level(): return
self.layout.label(text=f'Blendercam version: {".".join([str(x) for x in cam_version])}')
if len(bpy.context.preferences.addons['cam'].preferences.new_version_available)>0:
self.layout.label(text=f"New version available:")
self.layout.label(text=f" {bpy.context.preferences.addons['cam'].preferences.new_version_available}")
self.layout.operator("render.cam_update_now")
# Display the OpenCamLib version
def draw_opencamlib_version(self):
if not self.has_correct_level(): return
@ -102,6 +113,7 @@ class CAM_INFO_Panel(CAMButtonsPanel, bpy.types.Panel):
# Display the Info Panel
def draw(self, context):
self.context = context
self.draw_blendercam_version()
self.draw_opencamlib_version()
self.draw_op_warnings()
self.draw_op_time()

Wyświetl plik

@ -1 +1 @@
__version__=(0,9,7)
__version__=(0,9,6)

Wyświetl plik

@ -1,525 +0,0 @@
# blender CAM __init__.py (c) 2012 Vilem Novak
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ***** END GPL LICENCE BLOCK *****
bl_info = {
"name": "Send to 3d printer",
"author": "Vilem Novak",
"version": (0, 1, 0),
"blender": (2, 7, 0),
"location": "Render > Engine > 3d printer",
"description": "Send 3d model to printer. Needs Cura to be installed on your system.",
"warning": "",
"wiki_url": "blendercam.blogspot.com",
"tracker_url": "",
"category": "Scene"}
import bpy
from bpy.props import *
import subprocess, os
import threading
import bgl, blf
PRECISION=7
class PrintSettings(bpy.types.PropertyGroup):
"""stores all data for machines"""
#name = bpy.props.StringProperty(name="Machine Name", default="Machine")
slicer = EnumProperty(name='System',
items=(('CURA','Cura','the default slicer'),('INTERNAL','Internal (not existing)','experimental code')),
description='System to use',
default='CURA')
printers=[]
for p in bpy.utils.script_paths():
try:
directory=p+'\\addons\\print_3d\\machine_profiles\\'
list=os.listdir(directory)
for profile in list:
if profile[-4:]=='.ini':
profile=profile
printers.append((profile[:-4],profile[:-4],profile+' config file'))
except:
pass;
printer = EnumProperty(name='printer',
items=printers,
description='Printer')
#default='PEACHY')
presets=[]
for p in bpy.utils.script_paths():
try:
directory=p+'\\addons\\print_3d\\ini\\'
list=os.listdir(directory)
for preset in list:
if preset[-4:]=='.ini':
#preset=preset[:-4]
presets.append((directory+preset,preset[:-4],preset+' config file'))
except:
pass;
preset = EnumProperty(name='preset',
items=presets,
description='Preset')
#default='PEACHY')
filepath_engine = StringProperty(
name="Cura binary location",
description="Path to engine executable",
subtype='FILE_PATH',
)
dirpath_engine = StringProperty(
name="Cura directory",
description="Path to cura top directory",
subtype='DIR_PATH',
)
interface = EnumProperty(name='interface',
items=(('STANDARD','Standard user',"Everybody, if you really don't want to mess with how things work"),('DEVELOPER','Developer','If you want to improve how things work and understand what you are doing')),
description='Interface type',
default='DEVELOPER')
mm = 0.001
# layerThickness=bpy.props.FloatProperty(name="layerThickness", description="layerThickness", default=0.1 * mm, min=0.00001, max=320000,precision=PRECISION)
# initialLayerThickness=bpy.props.FloatProperty(name="initialLayerThickness", description="initialLayerThickness", default=0.15 * mm, min=0.00001, max=320000,precision=PRECISION)
# filamentDiameter=bpy.props.FloatProperty(name="filamentDiameter", description="filamentDiameter", default=0.4 * mm, min=0.00001, max=320000,precision=PRECISION)
# filamentFlow=bpy.props.FloatProperty(name="filamentFlow", description="filamentFlow", default=0.4 * mm, min=0.00001, max=320000,precision=PRECISION)
# extrusionWidth=bpy.props.FloatProperty(name="extrusionWidth", description="extrusionWidth", default=0.4 * mm, min=0.00001, max=320000,precision=PRECISION)
# insetCount=bpy.props.IntProperty(name="insetCount", description="insetCount", default=1, min=0, max=1000)
# downSkinCount=bpy.props.FloatProperty(name="downSkinCount", description="downSkinCount", default=1, min=0.00001, max=320000,precision=PRECISION)
# upSkinCount=bpy.props.FloatProperty(name="upSkinCount", description="upSkinCount", default=1, min=0.00001, max=320000,precision=PRECISION)
# infillOverlap=bpy.props.FloatProperty(name="infillOverlap", description="infillOverlap", default=0.4 * mm, min=0.00001, max=320000,precision=PRECISION)
# initialSpeedupLayers=bpy.props.FloatProperty(name="initialSpeedupLayers", description="initialSpeedupLayers", default=0.4 * mm, min=0.00001, max=320000,precision=PRECISION)
# initialLayerSpeed=bpy.props.FloatProperty(name="initialLayerSpeed", description="initialLayerSpeed", default=0.4 * mm, min=0.00001, max=320000,precision=PRECISION)
# printSpeed=bpy.props.FloatProperty(name="printSpeed", description="printSpeed", default=0.4 * mm, min=0.00001, max=320000,precision=PRECISION)
# infillSpeed=bpy.props.FloatProperty(name="infillSpeed", description="infillSpeed", default=0.4 * mm, min=0.00001, max=320000,precision=PRECISION)
# moveSpeed=bpy.props.FloatProperty(name="moveSpeed", description="moveSpeed", default=0.4 * mm, min=0.00001, max=320000,precision=PRECISION)
# fanSpeedMin=bpy.props.FloatProperty(name="fanSpeedMin", description="fanSpeedMin", default=0.4 * mm, min=0.00001, max=320000,precision=PRECISION)
# fanSpeedMax=bpy.props.FloatProperty(name="fanSpeedMax", description="fanSpeedMax", default=0.4 * mm, min=0.00001, max=320000,precision=PRECISION)
# supportAngle=bpy.props.FloatProperty(name="supportAngle", description="supportAngle", default=0.4 , min=0.00000, max=3.141926,precision=PRECISION,subtype="ANGLE",)
# supportEverywhere=bpy.props.BoolProperty(name="supportEverywhere", description="supportEverywhere", default=0)
# supportLineDistance=bpy.props.FloatProperty(name="supportLineDistance", description="supportLineDistance", default=0.4 * mm, min=0.00001, max=320000,precision=PRECISION)
# supportXYDistance=bpy.props.FloatProperty(name="supportXYDistance", description="supportXYDistance", default=0.4 * mm, min=0.00001, max=320000,precision=PRECISION)
# supportZDistance=bpy.props.FloatProperty(name="supportZDistance", description="supportZDistance", default=0.4 * mm, min=0.00001, max=320000,precision=PRECISION)
# supportExtruder=bpy.props.FloatProperty(name="supportExtruder", description="supportExtruder", default=0.4 * mm, min=0.00001, max=320000,precision=PRECISION)
# retractionAmount=bpy.props.FloatProperty(name="retractionAmount", description="retractionAmount", default=0.4 * mm, min=0.00001, max=320000,precision=PRECISION)
# retractionSpeed=bpy.props.FloatProperty(name="retractionSpeed", description="retractionSpeed", default=0.4 * mm, min=0.00001, max=320000,precision=PRECISION)
# retractionMinimalDistance=bpy.props.FloatProperty(name="retractionMinimalDistance", description="retractionMinimalDistance", default=0.4 * mm, min=0.00001, max=320000,precision=PRECISION)
# retractionAmountExtruderSwitch=bpy.props.FloatProperty(name="retractionAmountExtruderSwitch", description="retractionAmountExtruderSwitch", default=0.4 * mm, min=0.00001, max=320000,precision=PRECISION)
# minimalExtrusionBeforeRetraction=bpy.props.FloatProperty(name="minimalExtrusionBeforeRetraction", description="minimalExtrusionBeforeRetraction", default=0.4 * mm, min=0.00001, max=320000,precision=PRECISION)
# enableCombing=bpy.props.BoolProperty(name="enableCombing", description="enableCombing", default=0)
# multiVolumeOverlap=bpy.props.FloatProperty(name="multiVolumeOverlap", description="multiVolumeOverlap", default=0.4 * mm, min=0.00001, max=320000,precision=PRECISION)
# objectSink=bpy.props.FloatProperty(name="objectSink", description="objectSink", default=0.4 * mm, min=0.00001, max=320000,precision=PRECISION)
# minimalLayerTime=bpy.props.FloatProperty(name="minimalLayerTime", description="minimalLayerTime", default=0.4 * mm, min=0.00001, max=320000,precision=PRECISION)
# minimalFeedrate=bpy.props.FloatProperty(name="minimalFeedrate", description="minimalFeedrate", default=0.4 * mm, min=0.00001, max=320000,precision=PRECISION)
# coolHeadLift=bpy.props.BoolProperty(name="coolHeadLift", description="coolHeadLift", default=0)
#
# startCode= bpy.props.StringProperty(name='LimitstartCodecurve', description='startCode')
# endCode= bpy.props.StringProperty(name='endCode', description='endCode')
#
# fixHorrible=bpy.props.BoolProperty(name="fixHorrible", description="fixHorrible", default=0)
#
# propnames = ["layerThickness","initialLayerThickness","filamentDiameter","filamentFlow","extrusionWidth","insetCount","downSkinCount","upSkinCount","infillOverlap","initialSpeedupLayers","initialLayerSpeed","printSpeed","infillSpeed","printSpeed","moveSpeed","fanSpeedMin","fanSpeedMax","supportAngle","supportEverywhere","supportLineDistance","supportXYDistance","supportZDistance","supportExtruder","retractionAmount","retractionSpeed","retractionMinimalDistance","retractionAmountExtruderSwitch","minimalExtrusionBeforeRetraction","enableCombing","multiVolumeOverlap","objectSink","minimalLayerTime","minimalFeedrate","coolHeadLift","startCode","endCode","fixHorrible"]
class threadComPrint3d:#object passed to threads to read background process stdout info
def __init__(self,ob,proc):
self.obname=ob.name
self.outtext=''
self.proc=proc
self.lasttext=''
self.progress=0
def threadread_print3d( tcom):
"""reads stdout of background process, done this way to have it non-blocking"""
#print(tcom.proc)
#if tcom.proc!=None:
inline = tcom.proc.stdout.readline()
inline=str(inline)
s=inline.find('Preparing: ')
if s>-1:
perc=inline[ s+11 :s+14]
tcom.outtext=''.join(c for c in perc if c.isdigit())
tcom.progress = min(100,int(tcom.outtext))
else:
#print(inline)
s=inline.find('GCode')
#print(s)
if s>-1:
tcom.outtext='finished'#inline[s:]
# def header_info_print3d(self, context):
# """writes background operations data to header"""
# s=bpy.context.scene
# self.layout.label(s.print3d_text)
@bpy.app.handlers.persistent
def timer_update_print3d(context):
"""monitoring of background processes"""
text=''
s=bpy.context.scene
if hasattr(bpy.ops.object.print3d.__class__,'print3d_processes'):
processes=bpy.ops.object.print3d.__class__.print3d_processes
for p in processes:
#proc=p[1].proc
readthread=p[0]
tcom=p[1]
if not readthread.is_alive():
readthread.join()
#readthread.
tcom.lasttext=tcom.outtext
if tcom.outtext!='':
#print(tcom.obname,tcom.outtext)
tcom.outtext=''
if 'finished'in tcom.lasttext:#'GCode file saved'
processes.remove(p)
else:
readthread=threading.Thread(target=threadread_print3d, args = ([tcom]), daemon=True)
readthread.start()
p[0]=readthread
if tcom.lasttext!=tcom.outtext:
tcom.lasttext=tcom.outtext
for area in bpy.context.screen.areas:
#print(area.type)
if area.type == 'VIEW_3D':
area.tag_redraw()
def draw_callback_px_box(self, context):
wm = context.window_manager
sc = context.scene
pos_x, pos_y = 0,0 #getDisplayLocation(context)
# get text-width/height to resize the box
# Got the size right, now draw box using proper colors
box_color_r, box_color_g, box_color_b, box_color_alpha = .2,.6,.2,.1#sc.screencast_keys_box_color
if hasattr(bpy.ops.object.print3d.__class__,'print3d_processes'):
processes=bpy.ops.object.print3d.__class__.print3d_processes
i=0
for p in processes:
#proc=p[1].proc
readthread=p[0]
tcom=p[1]
progress=tcom.progress*.01
box_width = context.region.width * progress
offset_y = 80
bar_height = 30
x0 = 0# max(0, pos_x - padding_x)
y0 = context.region.height-offset_y-bar_height*i# max(0, pos_y - padding_y)
x1 = box_width
y1 = bar_height+y0
positions = [[x0, y0], [x0, y1], [x1, y1], [x1, y0]]
settings = [[bgl.GL_QUADS, min(0.0, box_color_alpha)], [bgl.GL_LINE_LOOP, min(0.0, box_color_alpha)]]
#print('boxie')
for mode, box_alpha in settings:
bgl.glEnable(bgl.GL_BLEND)
bgl.glBegin(mode)
bgl.glColor4f(box_color_r, box_color_g, box_color_b, box_color_alpha)
for v1, v2 in positions:
bgl.glVertex2f(v1, v2)
bgl.glEnd()
#TEXT HERE
#calculate overall time
timer_color_r, timer_color_g, timer_color_b, timer_color_alpha = .9,.9,.9,.5
pos_x = 20
pos_y = context.region.height-offset_y-bar_height*i+int(bar_height*.3)
#draw time
blf.size(0, int(bar_height*.45) , 72)
blf.position(0, pos_x, pos_y, 0)
bgl.glColor4f(timer_color_r, timer_color_g, timer_color_b, timer_color_alpha)
blf.draw(0, "Slicing %s : %s %%" % (tcom.obname,tcom.outtext))
i+=1
def draw_callback_px(self, context):
draw_callback_px_box(self, context)
def addLine(text,line):
text+=line+'\n'
def tweakCuraPreferences(enginepath,printer):
filepath=enginepath+'\\Cura\preferences.ini'
for p in bpy.utils.script_paths():
directory=p+'\\addons\\print_3d\\machine_profiles\\'
flist=os.listdir(directory)
n=printer+'.ini'
if n in flist:
presetfilepath=directory+n
f=open(filepath,'r')
text=f.read()
f.close()
machineblocks=[]
machinesnum=0
found=0
while found>-1:
found=text.find('[machine_',found+1)
if found>-1:
machineblocks.append(found)
machinesnum+=1
#print(machinesnum)
idx=text.find(printer)
printerindex=0
if idx==-1:
#print('Selected printer not in Cura settings, adding it')
#print(presetfilepath)
printerindex=machinesnum
pf=open(presetfilepath,'r')
printerpreset = pf.read()
#print(printerpreset)
pf.close()
text+=('\n\n[machine_%i]\n' % (machinesnum))
text+=printerpreset
#print(text)
else:
for i,m in enumerate(machineblocks):
if m<idx<m+40:
printerindex=i
break;
#set active machine to the printerindex
lines=text.split('\n')
#print(lines)
for i,l in enumerate(lines):
prop=l.split(' = ')
tweakprops={'active_machine':printerindex}
if tweakprops.get(prop[0])!=None:
lines[i]='%s = %s' %( prop[0],str(tweakprops[prop[0]]))
text=''
for l in lines:
addLine(text,l)
f=open(filepath,'w')
f.write(text)
f.close()
return printerindex
class Print3d(bpy.types.Operator):
"""send object to 3d printer"""
bl_idname = "object.print3d"
bl_label = "Print object in 3d"
bl_options = {'REGISTER', 'UNDO'}
#processes=[]
@classmethod
def poll(cls, context):
return context.active_object is not None
@staticmethod
def handle_add(self, context):
if not(hasattr(PrintSettings,'handle')) or PrintSettings.handle == None:
PrintSettings.handle = bpy.types.SpaceView3D.draw_handler_add(draw_callback_px, (self, context), 'WINDOW', 'POST_PIXEL')
#bpy.app.handlers.scene_update_pre.append(timer_update_print3d)
#ScreencastKeysStatus._handle = bpy.types.SpaceView3D.draw_handler_add(draw_callback_px, (self, context), 'WINDOW', 'POST_PIXEL')
#ScreencastKeysStatus._timer = context.window_manager.event_timer_add(0.075, context.window)
@staticmethod
def handle_remove(context):
if ScreencastKeysStatus._handle is not None:
#context.window_manager.event_timer_remove(ScreencastKeysStatus._timer)
bpy.types.SpaceView3D.draw_handler_remove(PrintSettings._handle, 'WINDOW')
PrintSettings._handle = None
#PrintSettings._timer = None
def execute(self, context):
Print3d.handle_add(self,context)
s=bpy.context.scene
settings=s.print3d_settings
ob=bpy.context.active_object
"""
#this was first try - using the slicer directly.
if settings.slicer=='CURA':
fpath=bpy.data.filepath+'_'+ob.name+'.stl'
gcodepath=bpy.data.filepath+'_'+ob.name+'.gcode'
enginepath=settings.filepath_engine
#Export stl, with a scale correcting blenders and Cura size interpretation in stl:
bpy.ops.export_mesh.stl(check_existing=False, filepath=fpath, filter_glob="*.stl", ascii=False, use_mesh_modifiers=True, axis_forward='Y', axis_up='Z', global_scale=1000)
#this is Cura help line:
#CuraEngine [-h] [-v] [-m 3x3matrix] [-s <settingkey>=<value>] -o <output.gcode> <model.stl>
#we build the command line here:
commands=[enginepath]
#add the properties, here add whatever you want exported from cura props, so far it doesn't work. Going with .ini files will be probably better in future:
unit=1000000#conversion between blender mm unit(0.001 of basic unit) and slicer unit (0.001 mm)
for name in settings.propnames:
#print(s)
commands.append('-s')
commands.append(name+'='+str(eval('settings.'+name)))
#commands.extend([key,str(propsdict[key])])
commands.extend(['-o', gcodepath,fpath])
print(commands)
#run cura in background:
proc = subprocess.Popen(commands,bufsize=1, stdout=subprocess.PIPE,stdin=subprocess.PIPE)
s=''
for command in commands:
s+=(command)+' '
print(s)
print('gcode file exported:')
print(gcodepath)
"""
#second try - use cura command line options, with .ini files.
if settings.slicer=='CURA':
opath=bpy.data.filepath[:-6]
fpath=opath+'_'+ob.name+'.stl'
gcodepath=opath+'_'+ob.name+'.gcode'
enginepath=settings.dirpath_engine
inipath=settings.preset
tweakCuraPreferences(enginepath,settings.printer)
#return {'FINISHED'}
#Export stl, with a scale correcting blenders and Cura size interpretation in stl:
bpy.ops.export_mesh.stl(check_existing=False, filepath=fpath, filter_glob="*.stl", ascii=False, use_mesh_modifiers=True, axis_forward='Y', axis_up='Z', global_scale=1000)
#this is Cura help line:
#CuraEngine [-h] [-v] [-m 3x3matrix] [-s <settingkey>=<value>] -o <output.gcode> <model.stl>
#we build the command line here:
#commands=[enginepath+'python\python.exe,']#,'-m', 'Cura.cura', '%*']
os.chdir(settings.dirpath_engine)
#print('\n\n\n')
#print(os.listdir())
commands=['python\\python.exe','-m', 'Cura.cura','-i',inipath, '-s', fpath]
#commands=[enginepath+'cura.bat', '-s', fpath]
#commands.extend()#'-o', gcodepath,
#print(commands)
#print('\n\n\n')
s=''
for command in commands:
s+=(command)+' '
#print(s)
#run cura in background:
#proc = subprocess.call(commands,bufsize=1, stdout=subprocess.PIPE,stdin=subprocess.PIPE)
#print(proc)
proc= subprocess.Popen(commands,bufsize=1, stdout=subprocess.PIPE,stdin=subprocess.PIPE)#,env={"PATH": enginepath})
#print(proc)
tcom=threadComPrint3d(ob,proc)
readthread=threading.Thread(target=threadread_print3d, args = ([tcom]), daemon=True)
readthread.start()
#self.__class__.print3d_processes=[]
if not hasattr(bpy.ops.object.print3d.__class__,'print3d_processes'):
bpy.ops.object.print3d.__class__.print3d_processes=[]
bpy.ops.object.print3d.__class__.print3d_processes.append([readthread,tcom])
#print('gcode file exported:')
#print(gcodepath)
return {'FINISHED'}
class PRINT3D_SETTINGS_Panel(bpy.types.Panel):
"""CAM feedrate panel"""
bl_label = "3d print settings"
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "render"
COMPAT_ENGINES = {'PRINT3D'}
@classmethod
def poll(cls, context):
rd = context.scene.render
return rd.engine in cls.COMPAT_ENGINES
def draw(self, context):
layout = self.layout
scene=bpy.context.scene
settings=scene.print3d_settings
#layout.prop(settings,'slicer')
layout.prop(settings,'printer')
layout.prop(settings,'preset')
#layout.prop(settings,'filepath_engine')
layout.prop(settings,'dirpath_engine')
layout.operator("object.print3d")
layout.separator()
#reporting code in the property window got moved to view_3d
#texts = scene.print3d_text.split('\n')
#for t in texts:
# layout.label(text=t)
#layout.prop(settings,'interface')
#if settings.interface=='DEVELOPER':
#for prop in settings.propnames:
# layout.prop(settings,prop)
#else:
#layout.label('here will be settings for casual users after we tune them.')
#layout.label('also, Cura binary should be found automagically,')
#layout.label('so you really set up which printer you have.')
class PRINT3D_ENGINE(bpy.types.RenderEngine):
bl_idname = 'PRINT3D'
bl_label = "Print 3d"
def register():
s=bpy.types.Scene
s.print3d_text= bpy.props.StringProperty()
bpy.utils.register_module(__name__)
bpy.types.Scene.print3d_settings=PointerProperty(type=PrintSettings)
# bpy.app.handlers.scene_update_pre.append(timer_update_print3d)
#bpy.types.INFO_HT_header.append(header_info_print3d)
def unregister():
bpy.utils.unregister_module(__name__)
del bpy.types.Scene.print3d_settings
# bpy.app.handlers.scene_update_pre.remove(timer_update_print3d)
#bpy.types.INFO_HT_header.remove(header_info_print3d)
#if __name__ == "__main__":
# register()

Wyświetl plik

@ -1,148 +0,0 @@
[profile]
layer_height = 0.1
wall_thickness = 0.2
retraction_enable = True
solid_layer_thickness = 0.6
fill_density = 20
nozzle_size = 0.1
print_speed = 50
print_temperature = 220
print_temperature2 = 0
print_temperature3 = 0
print_temperature4 = 0
print_bed_temperature = 70
support = None
platform_adhesion = None
support_dual_extrusion = Both
wipe_tower = False
wipe_tower_volume = 15
ooze_shield = False
filament_diameter = 2.85
filament_diameter2 = 0
filament_diameter3 = 0
filament_diameter4 = 0
filament_flow = 100.0
retraction_speed = 40.0
retraction_amount = 4.5
retraction_dual_amount = 16.5
retraction_min_travel = 1.5
retraction_combing = True
retraction_minimal_extrusion = 0.02
bottom_thickness = 0.3
object_sink = 0.0
overlap_dual = 0.15
travel_speed = 150.0
bottom_layer_speed = 20
infill_speed = 0.0
cool_min_layer_time = 5
fan_enabled = True
skirt_line_count = 1
skirt_gap = 3.0
skirt_minimal_length = 150.0
fan_full_height = 0.5
fan_speed = 100
fan_speed_max = 100
cool_min_feedrate = 10
cool_head_lift = False
solid_top = True
solid_bottom = True
fill_overlap = 15
support_fill_rate = 15
support_xy_distance = 0.7
support_z_distance = 0.15
spiralize = False
brim_line_count = 20
raft_margin = 5
raft_line_spacing = 1.0
raft_base_thickness = 0.3
raft_base_linewidth = 0.7
raft_interface_thickness = 0.2
raft_interface_linewidth = 0.2
fix_horrible_union_all_type_a = True
fix_horrible_union_all_type_b = False
fix_horrible_use_open_bits = False
fix_horrible_extensive_stitching = False
object_center_x = -1
object_center_y = -1
[alterations]
start.gcode = ;Sliced at: {day} {date} {time}
;Basic settings: Layer height: {layer_height} Walls: {wall_thickness} Fill: {fill_density}
;Print time: {print_time}
;Filament used: {filament_amount}m {filament_weight}g
;Filament cost: {filament_cost}
;M190 S{print_bed_temperature} ;Uncomment to add your own bed temperature line
;M109 S{print_temperature} ;Uncomment to add your own temperature line
G21 ;metric values
G90 ;absolute positioning
M107 ;start with the fan off
G28 X0 Y0 ;move X/Y to min endstops
G28 Z0 ;move Z to min endstops
G1 Z15.0 F{travel_speed} ;move the platform down 15mm
G92 E0 ;zero the extruded length
G1 F200 E3 ;extrude 3mm of feed stock
G92 E0 ;zero the extruded length again
G1 F{travel_speed}
;Put printing message on LCD screen
M117 Printing...
end.gcode = ;End GCode
M104 S0 ;extruder heater off
M140 S0 ;heated bed heater off (if you have it)
G91 ;relative positioning
G1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure
G1 Z+0.5 E-5 X-20 Y-20 F{travel_speed} ;move Z up a bit and retract filament even more
G28 X0 Y0 ;move X/Y to min endstops, so the head is out of the way
M84 ;steppers off
G90 ;absolute positioning
start2.gcode = ;Sliced at: {day} {date} {time}
;Basic settings: Layer height: {layer_height} Walls: {wall_thickness} Fill: {fill_density}
;Print time: {print_time}
;Filament used: {filament_amount}m {filament_weight}g
;Filament cost: {filament_cost}
;M190 S{print_bed_temperature} ;Uncomment to add your own bed temperature line
;M104 S{print_temperature} ;Uncomment to add your own temperature line
;M109 T1 S{print_temperature2} ;Uncomment to add your own temperature line
;M109 T0 S{print_temperature} ;Uncomment to add your own temperature line
G21 ;metric values
G90 ;absolute positioning
M107 ;start with the fan off
G28 X0 Y0 ;move X/Y to min endstops
G28 Z0 ;move Z to min endstops
G1 Z15.0 F{travel_speed} ;move the platform down 15mm
T1 ;Switch to the 2nd extruder
G92 E0 ;zero the extruded length
G1 F200 E10 ;extrude 10mm of feed stock
G92 E0 ;zero the extruded length again
G1 F200 E-{retraction_dual_amount}
T0 ;Switch to the first extruder
G92 E0 ;zero the extruded length
G1 F200 E10 ;extrude 10mm of feed stock
G92 E0 ;zero the extruded length again
G1 F{travel_speed}
;Put printing message on LCD screen
M117 Printing...
end2.gcode = ;End GCode
M104 T0 S0 ;extruder heater off
M104 T1 S0 ;extruder heater off
M140 S0 ;heated bed heater off (if you have it)
G91 ;relative positioning
G1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure
G1 Z+0.5 E-5 X-20 Y-20 F{travel_speed} ;move Z up a bit and retract filament even more
G28 X0 Y0 ;move X/Y to min endstops, so the head is out of the way
M84 ;steppers off
G90 ;absolute positioning
support_start.gcode =
support_end.gcode =
cool_start.gcode =
cool_end.gcode =
replace.csv =
switchextruder.gcode = ;Switch between the current extruder and the next extruder, when printing with multiple extruders.
G92 E0
G1 E-36 F5000
G92 E0
T{extruder}
G1 X{new_x} Y{new_y} Z{new_z} F{travel_speed}
G1 E36 F5000
G92 E0

Wyświetl plik

@ -1,149 +0,0 @@
[profile]
layer_height = 0.1
wall_thickness = 0.2
retraction_enable = True
solid_layer_thickness = 0.6
fill_density = 20
nozzle_size = 0.1
print_speed = 50
print_temperature = 220
print_temperature2 = 0
print_temperature3 = 0
print_temperature4 = 0
print_bed_temperature = 70
support = None
platform_adhesion = None
support_dual_extrusion = Both
wipe_tower = False
wipe_tower_volume = 15
ooze_shield = False
filament_diameter = 2.85
filament_diameter2 = 0
filament_diameter3 = 0
filament_diameter4 = 0
filament_flow = 100.0
retraction_speed = 40.0
retraction_amount = 4.5
retraction_dual_amount = 16.5
retraction_min_travel = 1.5
retraction_combing = True
retraction_minimal_extrusion = 0.02
bottom_thickness = 0.3
object_sink = 0.0
overlap_dual = 0.15
travel_speed = 150.0
bottom_layer_speed = 20
infill_speed = 0.0
cool_min_layer_time = 5
fan_enabled = True
skirt_line_count = 1
skirt_gap = 3.0
skirt_minimal_length = 150.0
fan_full_height = 0.5
fan_speed = 100
fan_speed_max = 100
cool_min_feedrate = 10
cool_head_lift = False
solid_top = True
solid_bottom = True
fill_overlap = 15
support_fill_rate = 15
support_xy_distance = 0.7
support_z_distance = 0.15
spiralize = False
brim_line_count = 20
raft_margin = 5
raft_line_spacing = 1.0
raft_base_thickness = 0.3
raft_base_linewidth = 0.7
raft_interface_thickness = 0.2
raft_interface_linewidth = 0.2
fix_horrible_union_all_type_a = True
fix_horrible_union_all_type_b = False
fix_horrible_use_open_bits = False
fix_horrible_extensive_stitching = False
plugin_config = (lp1
.
object_center_x = -1
object_center_y = -1
[alterations]
start.gcode = ;Sliced at: {day} {date} {time}
;Basic settings: Layer height: {layer_height} Walls: {wall_thickness} Fill: {fill_density}
;Print time: {print_time}
;Filament used: {filament_amount}m {filament_weight}g
;Filament cost: {filament_cost}
;M190 S{print_bed_temperature} ;Uncomment to add your own bed temperature line
;M109 S{print_temperature} ;Uncomment to add your own temperature line
G21 ;metric values
G90 ;absolute positioning
M107 ;start with the fan off
G28 X0 Y0 ;move X/Y to min endstops
G28 Z0 ;move Z to min endstops
G1 Z15.0 F{travel_speed} ;move the platform down 15mm
G92 E0 ;zero the extruded length
G1 F200 E3 ;extrude 3mm of feed stock
G92 E0 ;zero the extruded length again
G1 F{travel_speed}
;Put printing message on LCD screen
M117 Printing...
end.gcode = ;End GCode
M104 S0 ;extruder heater off
M140 S0 ;heated bed heater off (if you have it)
G91 ;relative positioning
G1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure
G1 Z+0.5 E-5 X-20 Y-20 F{travel_speed} ;move Z up a bit and retract filament even more
G28 X0 Y0 ;move X/Y to min endstops, so the head is out of the way
M84 ;steppers off
G90 ;absolute positioning
start2.gcode = ;Sliced at: {day} {date} {time}
;Basic settings: Layer height: {layer_height} Walls: {wall_thickness} Fill: {fill_density}
;Print time: {print_time}
;Filament used: {filament_amount}m {filament_weight}g
;Filament cost: {filament_cost}
;M190 S{print_bed_temperature} ;Uncomment to add your own bed temperature line
;M104 S{print_temperature} ;Uncomment to add your own temperature line
;M109 T1 S{print_temperature2} ;Uncomment to add your own temperature line
;M109 T0 S{print_temperature} ;Uncomment to add your own temperature line
G21 ;metric values
G90 ;absolute positioning
M107 ;start with the fan off
G28 X0 Y0 ;move X/Y to min endstops
G28 Z0 ;move Z to min endstops
G1 Z15.0 F{travel_speed} ;move the platform down 15mm
T1 ;Switch to the 2nd extruder
G92 E0 ;zero the extruded length
G1 F200 E10 ;extrude 10mm of feed stock
G92 E0 ;zero the extruded length again
G1 F200 E-{retraction_dual_amount}
T0 ;Switch to the first extruder
G92 E0 ;zero the extruded length
G1 F200 E10 ;extrude 10mm of feed stock
G92 E0 ;zero the extruded length again
G1 F{travel_speed}
;Put printing message on LCD screen
M117 Printing...
end2.gcode = ;End GCode
M104 T0 S0 ;extruder heater off
M104 T1 S0 ;extruder heater off
M140 S0 ;heated bed heater off (if you have it)
G91 ;relative positioning
G1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure
G1 Z+0.5 E-5 X-20 Y-20 F{travel_speed} ;move Z up a bit and retract filament even more
G28 X0 Y0 ;move X/Y to min endstops, so the head is out of the way
M84 ;steppers off
G90 ;absolute positioning
support_start.gcode =
support_end.gcode =
cool_start.gcode =
cool_end.gcode =
replace.csv =
switchextruder.gcode = ;Switch between the current extruder and the next extruder, when printing with multiple extruders.
G92 E0
G1 E-36 F5000
G92 E0
T{extruder}
G1 X{new_x} Y{new_y} Z{new_z} F{travel_speed}
G1 E36 F5000
G92 E0

Wyświetl plik

@ -1,149 +0,0 @@
[profile]
layer_height = 0.8
wall_thickness = 0.2
retraction_enable = True
solid_layer_thickness = 0.6
fill_density = 20
nozzle_size = 0.1
print_speed = 50
print_temperature = 220
print_temperature2 = 0
print_temperature3 = 0
print_temperature4 = 0
print_bed_temperature = 70
support = None
platform_adhesion = None
support_dual_extrusion = Both
wipe_tower = False
wipe_tower_volume = 15
ooze_shield = False
filament_diameter = 2.85
filament_diameter2 = 0
filament_diameter3 = 0
filament_diameter4 = 0
filament_flow = 100.0
retraction_speed = 40.0
retraction_amount = 4.5
retraction_dual_amount = 16.5
retraction_min_travel = 1.5
retraction_combing = True
retraction_minimal_extrusion = 0.02
bottom_thickness = 0.3
object_sink = 0.0
overlap_dual = 0.15
travel_speed = 150.0
bottom_layer_speed = 20
infill_speed = 0.0
cool_min_layer_time = 5
fan_enabled = True
skirt_line_count = 1
skirt_gap = 3.0
skirt_minimal_length = 150.0
fan_full_height = 0.5
fan_speed = 100
fan_speed_max = 100
cool_min_feedrate = 10
cool_head_lift = False
solid_top = True
solid_bottom = True
fill_overlap = 15
support_fill_rate = 15
support_xy_distance = 0.7
support_z_distance = 0.15
spiralize = False
brim_line_count = 20
raft_margin = 5
raft_line_spacing = 1.0
raft_base_thickness = 0.3
raft_base_linewidth = 0.7
raft_interface_thickness = 0.2
raft_interface_linewidth = 0.2
fix_horrible_union_all_type_a = True
fix_horrible_union_all_type_b = False
fix_horrible_use_open_bits = False
fix_horrible_extensive_stitching = False
plugin_config = (lp1
.
object_center_x = -1
object_center_y = -1
[alterations]
start.gcode = ;Sliced at: {day} {date} {time}
;Basic settings: Layer height: {layer_height} Walls: {wall_thickness} Fill: {fill_density}
;Print time: {print_time}
;Filament used: {filament_amount}m {filament_weight}g
;Filament cost: {filament_cost}
;M190 S{print_bed_temperature} ;Uncomment to add your own bed temperature line
;M109 S{print_temperature} ;Uncomment to add your own temperature line
G21 ;metric values
G90 ;absolute positioning
M107 ;start with the fan off
G28 X0 Y0 ;move X/Y to min endstops
G28 Z0 ;move Z to min endstops
G1 Z15.0 F{travel_speed} ;move the platform down 15mm
G92 E0 ;zero the extruded length
G1 F200 E3 ;extrude 3mm of feed stock
G92 E0 ;zero the extruded length again
G1 F{travel_speed}
;Put printing message on LCD screen
M117 Printing...
end.gcode = ;End GCode
M104 S0 ;extruder heater off
M140 S0 ;heated bed heater off (if you have it)
G91 ;relative positioning
G1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure
G1 Z+0.5 E-5 X-20 Y-20 F{travel_speed} ;move Z up a bit and retract filament even more
G28 X0 Y0 ;move X/Y to min endstops, so the head is out of the way
M84 ;steppers off
G90 ;absolute positioning
start2.gcode = ;Sliced at: {day} {date} {time}
;Basic settings: Layer height: {layer_height} Walls: {wall_thickness} Fill: {fill_density}
;Print time: {print_time}
;Filament used: {filament_amount}m {filament_weight}g
;Filament cost: {filament_cost}
;M190 S{print_bed_temperature} ;Uncomment to add your own bed temperature line
;M104 S{print_temperature} ;Uncomment to add your own temperature line
;M109 T1 S{print_temperature2} ;Uncomment to add your own temperature line
;M109 T0 S{print_temperature} ;Uncomment to add your own temperature line
G21 ;metric values
G90 ;absolute positioning
M107 ;start with the fan off
G28 X0 Y0 ;move X/Y to min endstops
G28 Z0 ;move Z to min endstops
G1 Z15.0 F{travel_speed} ;move the platform down 15mm
T1 ;Switch to the 2nd extruder
G92 E0 ;zero the extruded length
G1 F200 E10 ;extrude 10mm of feed stock
G92 E0 ;zero the extruded length again
G1 F200 E-{retraction_dual_amount}
T0 ;Switch to the first extruder
G92 E0 ;zero the extruded length
G1 F200 E10 ;extrude 10mm of feed stock
G92 E0 ;zero the extruded length again
G1 F{travel_speed}
;Put printing message on LCD screen
M117 Printing...
end2.gcode = ;End GCode
M104 T0 S0 ;extruder heater off
M104 T1 S0 ;extruder heater off
M140 S0 ;heated bed heater off (if you have it)
G91 ;relative positioning
G1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure
G1 Z+0.5 E-5 X-20 Y-20 F{travel_speed} ;move Z up a bit and retract filament even more
G28 X0 Y0 ;move X/Y to min endstops, so the head is out of the way
M84 ;steppers off
G90 ;absolute positioning
support_start.gcode =
support_end.gcode =
cool_start.gcode =
cool_end.gcode =
replace.csv =
switchextruder.gcode = ;Switch between the current extruder and the next extruder, when printing with multiple extruders.
G92 E0
G1 E-36 F5000
G92 E0
T{extruder}
G1 X{new_x} Y{new_y} Z{new_z} F{travel_speed}
G1 E36 F5000
G92 E0

Wyświetl plik

@ -1,58 +0,0 @@
[machine]
machine_name = MakerBot Replicator
machine_type = MakerBot
machine_width = 225
machine_depth = 145
machine_height = 150
machine_center_is_zero = False
has_heated_bed = True
gcode_flavor = MakerBot
extruder_amount = 1
[profile]
filament_diameter = 1.75
nozzle_size = 0.4
layer_height = 0.15
fill_density = 10
print_speed = 50
print_temperature = 220
travel_speed = 150
[alterations]
start.gcode = ; -- START GCODE --
M136 (enable build)
M73 P0
G162 X Y F2000(home XY axes maximum)
G161 Z F900(home Z axis minimum)
G92 X0 Y0 Z-5 A0 B0 (set Z to -5)
G1 Z0.0 F{travel_speed}(move Z to '0')
G161 Z F100(home Z axis minimum)
M132 X Y Z A B (Recall stored home offsets for XYZAB axis)
G92 X152 Y72 Z0 A0 B0
G1 X-141 Y-74 Z40 F{travel_speed} (move to waiting position)
G130 X20 Y20 A20 B20 (Lower stepper Vrefs while heating)
M135 T0
M104 S220 T0
M133 T0
G130 X127 Y127 A127 B127 (Set Stepper motor Vref to defaults)
; Sliced {filename} at: {day} {date} {time}
; Basic settings: Layer height: {layer_height} Walls: {wall_thickness} Fill: {fill_density}
; Print time: {print_time}
; Filament used: {filament_amount}m {filament_weight}g
; Filament cost: {filament_cost}
M73 P0;
; -- end of START GCODE --
end.gcode = ; -- END GCODE --
M127 T0; fan off
M127 T0 (Fan Off)
M18 A B(Turn off A and B Steppers)
G1 Z155 F900
G162 X Y F2000
M18 X Y Z(Turn off steppers after a build)
M104 S0 T0
M70 P5 (We <3 Making Things!)
M72 P1 ( Play Ta-Da song )
M73 P100
M137 (build end notification)
; -- end of END GCODE --

Wyświetl plik

@ -1,19 +0,0 @@
[machine]
machine_name = Mendel
machine_type = RepRap
machine_width = 200
machine_depth = 200
machine_height = 140
machine_center_is_zero = False
has_heated_bed = True
gcode_flavor = RepRap (Marlin/Sprinter)
extruder_amount = 1
[profile]
filament_diameter = 2.85
nozzle_size = 0.5
layer_height = 0.2
print_speed = 50
print_temperature = 240
travel_speed = 150

Wyświetl plik

@ -1,19 +0,0 @@
[machine]
machine_name = Peachy
machine_type = RepRap
machine_width = 80
machine_depth = 80
machine_height = 150
machine_center_is_zero = False
has_heated_bed = True
gcode_flavor = RepRap (Marlin/Sprinter)
extruder_amount = 1
[profile]
filament_diameter = 2.85
nozzle_size = 0.5
layer_height = 0.2
fill_density = 10
print_speed = 30
print_temperature = 240
travel_speed = 150

Wyświetl plik

@ -1,19 +0,0 @@
[machine]
machine_name = PrintrBot
machine_type = RepRap
machine_width = 150
machine_depth = 150
machine_height = 150
machine_center_is_zero = False
has_heated_bed = True
gcode_flavor = RepRap (Marlin/Sprinter)
extruder_amount = 1
[profile]
filament_diameter = 2.85
nozzle_size = 0.5
layer_height = 0.2
fill_density = 10
print_speed = 30
print_temperature = 240
travel_speed = 150

Wyświetl plik

@ -1,19 +0,0 @@
[machine]
machine_name = PrintrBot LC+
machine_type = RepRap
machine_width = 200
machine_depth = 200
machine_height = 200
machine_center_is_zero = False
has_heated_bed = True
gcode_flavor = RepRap (Marlin/Sprinter)
extruder_amount = 1
[profile]
filament_diameter = 2.85
nozzle_size = 0.5
layer_height = 0.2
fill_density = 10
print_speed = 30
print_temperature = 240
travel_speed = 150

Wyświetl plik

@ -1,18 +0,0 @@
[machine]
machine_name = Prusa Mendel i3
machine_type = RepRap
machine_width = 198
machine_depth = 185
machine_height = 200
machine_center_is_zero = False
has_heated_bed = True
gcode_flavor = RepRap (Marlin/Sprinter)
extruder_amount = 1
[profile]
filament_diameter = 2.85
nozzle_size = 0.5
layer_height = 0.2
print_speed = 50
print_temperature = 240
travel_speed = 150

Wyświetl plik

@ -1,316 +0,0 @@
import bpy
import mathutils
from mathutils import Vector
from bpy_extras import view3d_utils
bl_info = {
"name": "Scan tools",
"author": "Vilem Novak",
"version": (1, 0),
"blender": (2, 69, 0),
"location": "View3D > Scan tools",
"description": "Various tools for postprocessing scan results",
"warning": "",
"wiki_url": "",
"tracker_url": "",
"category": "Object"}
def floor(self,context, event, ray_max=100000.0):
"""Run this function on left mouse, execute the ray cast"""
# get the context arguments
scene = context.scene
region = context.region
rv3d = context.region_data
coord = event.mouse_region_x, event.mouse_region_y
# get the ray from the viewport and mouse
view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord)
ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord)
ray_target = ray_origin + (view_vector * ray_max)
def obj_ray_cast(obj, matrix):
"""Wrapper for ray casting that moves the ray into object space"""
# get the ray relative to the object
matrix_inv = matrix.inverted()
ray_origin_obj = matrix_inv * ray_origin
ray_target_obj = matrix_inv * ray_target
vec = ray_target_obj - ray_origin_obj
# cast the ray
result, hit, normal, face_index = obj.ray_cast(ray_origin_obj, vec, vec.length)
if face_index != -1:
return hit, normal, face_index
else:
return None, None, None
# cast rays and find the closest object
best_length_squared = ray_max * ray_max
best_obj = None
obj=bpy.context.active_object
matrix = obj.matrix_world.copy()
if obj.type == 'MESH':
hit, normal, face_index = obj_ray_cast(obj, matrix)
print(hit)
if hit is not None:
hit_world = matrix * hit
scene.cursor_location = hit_world
self.hits.append(hit)
print(len(self.hits))
#if len(self.hits)==1:
#
n=mathutils.Vector((0,0,0))
if len(self.hits)>=3:
for a in range(0,len(self.hits)-2):
v1=matrix * self.hits[a]
v2=matrix * self.hits[a+1]
v3=matrix * self.hits[a+2]
ntri=mathutils.geometry.normal(v1,v2,v3)
n+=ntri
up=mathutils.Vector((0,0,1))
r=n.rotation_difference(up)#.to_euler()
print(n,r)
print(obj.rotation_quaternion)
print(matrix)
#print(r)
v=matrix * ((self.hits[0]+self.hits[1]+self.hits[2])/3)
obj.location-=v
m=obj.rotation_mode
bpy.ops.object.transform_apply(location=True, rotation=False, scale=True)
obj.rotation_mode='QUATERNION'
obj.rotation_quaternion.rotate(r)
obj.rotation_mode=m
#obj.rotation_euler=obj.rotation_euler
#obj.update()
matrix = obj.matrix_world.copy()
print(matrix)
bpy.ops.object.transform_apply(location=False, rotation=True, scale=False)
return True
return False
class ObjectFloor(bpy.types.Operator):
"""define floor on scan mesh"""
bl_idname = "object.align_floor"
bl_label = "Floor"
bl_options = {'REGISTER', 'UNDO'}
@classmethod
def poll(cls, context):
return context.active_object is not None
def modal(self, context, event):
#self.report({'OPERATOR'}, "Select 3 or more points on the floor, Esc exits")
if event.type in {'MIDDLEMOUSE', 'WHEELUPMOUSE', 'WHEELDOWNMOUSE'}:
# allow navigation
return {'PASS_THROUGH'}
elif event.type == 'LEFTMOUSE' and event.value=='PRESS':
#print(dir(event))
#print(event.value)
finish = floor(self,context, event)
if finish:
return{'FINISHED'}
return {'RUNNING_MODAL'}
elif event.type in {'RIGHTMOUSE', 'ESC'}:
#self.hits=[]
return {'CANCELLED'}
return {'RUNNING_MODAL'}
def invoke(self, context, event):
if context.space_data.type == 'VIEW_3D':
self.hits=[]
context.window_manager.modal_handler_add(self)
return {'RUNNING_MODAL'}
else:
self.report({'WARNING'}, "Active space must be a View3d")
return {'CANCELLED'}
def removeFloor(context,threshold):
ob=bpy.context.active_object
m=ob.data
matrix = ob.matrix_world.copy()
sel=0
bpy.ops.object.editmode_toggle()
bpy.ops.mesh.select_all(action='DESELECT')
bpy.ops.object.editmode_toggle()
for vert in m.vertices:
v=matrix*vert.co
if v.z<threshold:
vert.select=True
sel+=1
else:
vert.select=False
print(len(m.vertices),sel)
m.update()
bpy.ops.object.editmode_toggle()
for a in range(0,5):
bpy.ops.mesh.select_more()
for a in range(0,8):# this is larger, so legs etc won't be cut
bpy.ops.mesh.select_less()
bpy.ops.mesh.delete(type='VERT')
bpy.ops.object.editmode_toggle()
class RemoveFloor(bpy.types.Operator):
"""Remove floor (distance from XY plane in world coordinates) on aligned mesh"""
bl_idname = "object.remove_floor"
bl_label = "Remove Floor"
bl_options = {'REGISTER', 'UNDO'}
threshold = bpy.props.FloatProperty(
name="threshold",
description="Distance in world units from axis plane",
min=0.00001, max=100.0,
default=.01)
@classmethod
def poll(cls, context):
return context.active_object is not None
def execute(self, context):
removeFloor(context,self.threshold)
return {'FINISHED'}
def makeLOD(context):
ob=bpy.context.active_object
bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY')
parent=None
if ob.parent!=None:
parent=ob.parent
bpy.ops.object.duplicate()
bpy.ops.object.modifier_add(type='DECIMATE')
bpy.context.object.modifiers["Decimate"].ratio = 0.05
bpy.ops.object.modifier_apply(apply_as='DATA', modifier="Decimate")
lod=bpy.context.active_object
ob.select=True
bpy.ops.object.parent_set(type='OBJECT', keep_transform=True)
ob.hide=True
par=bpy.context.active_object
par.hide_render=True
if parent!=None:
par.parent
class MakeLOD(bpy.types.Operator):
"""Add low poly mesh for view and hide high poly mesh"""
bl_idname = "object.make_lod"
bl_label = "make LOD"
bl_options = {'REGISTER', 'UNDO'}
@classmethod
def poll(cls, context):
return context.active_object is not None
def execute(self, context):
makeLOD(context)
return {'FINISHED'}
class ReconstructmeTransform(bpy.types.Operator):
"""Transform import from reconstructme to blender axes/scale"""
bl_idname = "object.reconstructme_trans"
bl_label = "Reconstructme transform"
bl_options = {'REGISTER', 'UNDO'}
@classmethod
def poll(cls, context):
return context.active_object is not None
def execute(self, context):
reconstructmTransform(context)
return {'FINISHED'}
def reconstructmTransform(context):
ob=bpy.context.active_object
ob.scale=(0.001,0.001,0.001)
ob.rotation_euler.x=90
bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY')
ob.location=(0,0,0)
bpy.ops.object.transform_apply(location=True, rotation=True, scale=True)
class RemoveSmallParts(bpy.types.Operator):
"""Transform import from reconstructme to blender axes/scale"""
bl_idname = "object.remove_small_parts"
bl_label = "Remove small parts"
bl_options = {'REGISTER', 'UNDO'}
@classmethod
def poll(cls, context):
return context.active_object is not None
def execute(self, context):
removeSmallParts(context)
return {'FINISHED'}
def removeSmallParts(context):
actob=bpy.context.active_object
bpy.ops.object.editmode_toggle()
bpy.ops.mesh.separate(type='LOOSE')
bpy.ops.object.editmode_toggle()
obs=bpy.context.selected_objects
rem=[]
nrem=[]
for ob in obs:
if len(ob.data.vertices)<300:
print(ob.name)
rem.append(ob)
else:
nrem.append(ob)
bpy.ops.object.select_all(action='DESELECT')
for ob in rem:
ob.select=True
bpy.ops.object.delete(use_global=False)
for ob in nrem:
ob.select=True
bpy.context.scene.objects.active=nrem[0]
bpy.ops.object.join()
#panel containing all tools
class VIEW3D_PT_tools_scantools(bpy.types.Panel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'TOOLS'
bl_context = "objectmode"
bl_label = "Scan Tools"
bl_options = {'DEFAULT_CLOSED'}
def draw(self, context):
layout = self.layout
#col = layout.column(align=True)
#lt = context.window_manager.looptools
layout.operator("object.reconstructme_trans")
layout.operator("object.align_floor")
layout.operator("object.remove_floor")
layout.operator("object.remove_small_parts")
layout.operator("object.make_lod")
def register():
bpy.utils.register_class(ObjectFloor)
bpy.utils.register_class(RemoveFloor)
bpy.utils.register_class(ReconstructmeTransform)
bpy.utils.register_class(RemoveSmallParts)
bpy.utils.register_class(MakeLOD)
bpy.utils.register_class(VIEW3D_PT_tools_scantools)
def unregister():
bpy.utils.unregister_class(ObjectFloor)
bpy.utils.unregister_class(RemoveFloor)
bpy.utils.unregister_class(ReconstructmeTransform)
bpy.utils.unregister_class(RemoveSmallParts)
bpy.utils.unregister_class(MakeLOD)
bpy.utils.unregister_class(VIEW3D_PT_tools_scantools)
if __name__ == "__main__":
register()

Wyświetl plik

@ -1,165 +0,0 @@
bl_info = {
"name": "Select Similar extended",
"author": "Vilem Novak",
"version": (1, 0),
"blender": (2, 69, 0),
"location": "View3D > Select > Grouped",
"description": "Adds a new Mesh Object",
"warning": "",
"wiki_url": "",
"category": "Add Mesh"}
import bpy
from bpy.props import *
prec=0.001;
def precc3(v1,v2,prec):
return v1[0]-prec<v2[0]<v1[0]+prec and v1[1]-prec<v2[1]<v1[1]+prec and v1[2]-prec<v2[2]<v1[2]+prec
condition = 'VERTEX_COLOR';
def compare(o,o1, rules):
return 0;
def compareColor(col1,col2,threshold):
r=col2[0]-threshold<col1[0]<col2[0]+threshold
g=col2[1]-threshold<col1[1]<col2[1]+threshold
b=col2[2]-threshold<col1[2]<col2[2]+threshold
return r and g and b
def selectSimilarObject(condition,threshold):
ao=bpy.context.active_object
if condition =='MATERIAL_COLOR':
if len(ao.material_slots)>0:
m=ao.material_slots[0].material.diffuse_color
for o in bpy.context.scene.objects:
#print (o.material_slots)
if len(o.material_slots)>0 and o.material_slots[0].material!=None:
#print (precc3(m,o.material_slots[0].material.diffuse_color,prec))
if precc3(m,o.material_slots[0].material.diffuse_color,prec):
o.select=1;
if condition =='DIMENSIONS':
d = ao.dimensions
for o in bpy.context.scene.objects:
if o.dimensions.x-prec<d.x<o.dimensions.x+prec and o.dimensions.y-prec<d.y<o.dimensions.y+prec and o.dimensions.z-prec<d.z<o.dimensions.z+prec:
o.select=1
if condition == 'VERTEX_COUNT':
# select similar num of verts
n=len(ao.data.vertices);
for o in bpy.context.scene.objects:
if o.type == 'MESH':
if len(o.data.vertices)==n:# and o.material_slots[0].material == mat:
o.select=1
def selectSimilarMesh(condition,threshold):
bpy.ops.object.editmode_toggle()
print(condition,threshold)
if condition == 'VERTEX_COLOR':
ao=bpy.context.active_object
m=ao.data
if len(m.vertex_colors)>0:
for li in range(0,len(m.loops)):
l=m.loops[li]
v=m.vertices[l.vertex_index]
if v.select:
color = m.vertex_colors['Col'].data[li].color
print(color)
for li in range(0,len(m.loops)):
l=m.loops[li]
v=m.vertices[l.vertex_index]
color1 = m.vertex_colors['Col'].data[li].color
if compareColor(color, color1, threshold):
v.select=True
bpy.ops.object.editmode_toggle()
class SelectSimilarObject(bpy.types.Operator):
"""Select similar objects"""
bl_idname = "object.select_similar_addon"
bl_label = "Select similar objects"
bl_options = {'REGISTER', 'UNDO'}
condition = EnumProperty(
name="type",
description="type",
items=(('DIMENSIONS','DIMENSIONS','DIMENSIONS'),
('MATERIAL_COLOR','MATERIAL_COLOR','MATERIAL_COLOR'),
('VERTEX_COLOR','VERTEX_COLOR','VERTEX_COLOR'),
('VERTEX_COUNT','VERTEX_COUNT','VERTEX_COUNT')
),
default='DIMENSIONS'
)
threshold = FloatProperty(
name="Threshold",
description="Threshold",
min=0.000001, max=100.0,
default=0.1,
)
conditions=[]
def execute(self, context):
selectSimilarObject(self.condition,self.threshold)
return {'FINISHED'}
class SelectSimilarMesh(bpy.types.Operator):
"""Select similar elements"""
bl_idname = "mesh.select_similar_addon"
bl_label = "Select similar elements"
bl_options = {'REGISTER', 'UNDO'}
condition = EnumProperty(
name="type",
description="type",
items=(
('VERTEX_COLOR','VERTEX_COLOR','VERTEX_COLOR'),
('VERTEX_COUNT','VERTEX_COUNT','VERTEX_COUNT')
),
default='VERTEX_COLOR'
)
threshold = FloatProperty(
name="Threshold",
description="Threshold",
min=0.000001, max=100.0,
default=0.1,
)
conditions=[]
#view_align = BoolProperty(
# name="Align to View",
# default=False,
# )
# generic transform props
def execute(self, context):
selectSimilarMesh(self.condition,self.threshold)
return {'FINISHED'}
def register():
bpy.utils.register_class(SelectSimilarObject)
bpy.utils.register_class(SelectSimilarMesh)
#bpy.types.INFO_MT_mesh_add.append(menu_func)
def unregister():
bpy.utils.unregister_class(SelectSimilarObject)
bpy.utils.unregister_class(SelectSimilarMesh)
#bpy.types.INFO_MT_mesh_add.remove(menu_func)
if __name__ == "__main__":
register()
# test call
#bpy.ops.mesh.primitive_box_add()