kopia lustrzana https://github.com/vilemduha/blendercam
commit
b63abfe007
|
@ -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.
|
@ -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()
|
||||
|
|
|
@ -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'}
|
|
@ -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()
|
|
@ -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()
|
||||
|
|
|
@ -1 +1 @@
|
|||
__version__=(0,9,7)
|
||||
__version__=(0,9,6)
|
|
@ -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()
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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 --
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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()
|
|
@ -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()
|
Ładowanie…
Reference in New Issue