Created
August 2, 2015 22:23
-
-
Save anonymous/b51291c5a63183a53a79 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
bl_info = { | |
"name": "Viewport to SVG", | |
"author": "Zeffi, modified by eppo", | |
"version": (0, 1, 3), | |
"blender": (2, 75, 0), | |
"location": "View3D > Properties", | |
"description": "Generate an SVG file from selected objects", | |
"warning": "Objects should have LocRotScale applied -> Ctrl-A menu", | |
"tracker_url": "http://blenderartists.org/forum/showthread.php?375100-Export-%28a-lot-of%29-curves-to-svg", | |
"category": "Render"} | |
# Cycles Diffuse Color is used for svg outlines. | |
import bpy | |
from bpy_extras.view3d_utils import location_3d_to_region_2d as loc3d2d | |
def flatten(l, ltypes=(list, tuple)): | |
ltype = type(l) | |
l = list(l) | |
i = 0 | |
while i < len(l): | |
while isinstance(l[i], ltypes): | |
if not l[i]: | |
l.pop(i) | |
i -= 1 | |
break | |
else: | |
l[i:i + 1] = l[i] | |
i += 1 | |
return ltype(l) | |
def write_svg(context, region): | |
wm = bpy.context.window_manager | |
width, height = region.width, region.height | |
rv3d = context.space_data.region_3d | |
#bpy.context.area.type = 'VIEW_3D' | |
C= bpy.context | |
styles = [] | |
styles.append('0x000000') #black by default | |
svg_body= [] | |
for idx, ob in enumerate(C.selected_objects): | |
ob_svg= [] | |
if ob.type == 'MESH': | |
C.scene.objects.active = ob | |
vertlist = ob.data.vertices | |
edge_list = [] | |
for edge in ob.data.edges: | |
idx1, idx2 = edge.vertices[:] | |
co1, co2 = vertlist[idx1].co, vertlist[idx2].co | |
co2d_1 = loc3d2d(region, rv3d, co1) | |
co2d_2 = loc3d2d(region, rv3d, co2) | |
edge_list.append((co2d_1, co2d_2)) | |
ob_uses_style = 0 | |
ob_svg.append('\n<g id="%s">' % ob.name) | |
# TODO Gamma correction, again? | |
if len(ob.material_slots)>0 and hasattr(ob.material_slots[0].material,'diffuse_color'): | |
hex_col = '0x%02x%02x%02x' % (ob.material_slots[0].material.diffuse_color * 255.0)[:] | |
if str(hex_col) not in styles: | |
styles.append(str(hex_col)) | |
ob_uses_style = len(styles)-1 | |
else: | |
for i, colr in enumerate(styles): | |
if str(hex_col) == colr: | |
ob_uses_style = i | |
break | |
nones=0 #count None type errors | |
for idx, edge in enumerate(edge_list): | |
path_name="path"+str(idx) | |
co1, co2 = edge | |
if type(co1)==type(None) or type(co2)==type(None): | |
nones += 1 | |
continue | |
ob_svg.append("""\ | |
<path class="fil0 str%s" d="M %s,%s %s,%s" id="%s"/>""" % (str(ob_uses_style),co1.x, height-co1.y, co2.x, height-co2.y, path_name)) | |
ob_svg.append('</g>') | |
svg_body.append(ob_svg) | |
svg_body.append('</svg>') | |
print(nones, '"None type" errors.') | |
# End SVG body | |
# Prepare style block | |
svg_styles=[] | |
svg_styles.append('''\ | |
<defs> | |
<style type="text/css"> | |
<![CDATA[''') | |
en= list(enumerate(styles)) | |
for i, v in enumerate(en): | |
svg_styles.append('''\ | |
.str%s {stroke:#%s;stroke-width:2}''' % (str(i), v[1][2:])) | |
svg_styles.append('''\ | |
.fil0 {fill:none} | |
]]> | |
</style></defs> | |
''') | |
# Drop some header info in | |
svg_header = '''\ | |
<svg width="%spx" height="%spx" id="svg2" version="1.1">\n''' % (width, height) | |
file_to_write = open(wm.path_fn, 'w') | |
file_to_write.write(svg_header) | |
file_to_write.write('\n'.join(svg_styles)) | |
file_to_write.write(str('\n'.join(flatten(svg_body)))) | |
file_to_write.close() | |
print ('Saved as ',wm.path_fn) | |
#That's All Folks. | |
def draw_data(self, context): | |
region = context.region | |
write_svg(context, region) | |
return | |
class RenderButton(bpy.types.Operator): | |
"""Will write svg file""" | |
bl_idname = "svg.render" | |
bl_label = "Render to svg" | |
def execute(self, context): | |
draw_data(self, context) | |
return{'FINISHED'} | |
class SVGPanel(bpy.types.Panel): | |
"""Creates a Panel in the Object properties window""" | |
bl_label = "Render SVG" | |
bl_idname = "OBJECT_PT_render" | |
bl_space_type = "VIEW_3D" | |
bl_region_type = "UI" | |
bl_context = "object" | |
def draw(self, context): | |
wm = bpy.context.window_manager | |
layout = self.layout | |
obj = context.object | |
row = layout.row() | |
sel=[] | |
for ob in bpy.context.selected_objects: | |
sel.append(ob.name) | |
if len(sel)>3: | |
sel=[] | |
sel.append("A whole lot of Objects") | |
row.label(text="Current Selection: " + str(sel)) | |
# Path selector | |
column = layout.column() | |
column.prop(wm, 'path_fn') | |
# display button | |
self.layout.operator("svg.render", text='Render') | |
classes = [SVGPanel, RenderButton] | |
bpy.types.WindowManager.path_fn=bpy.props.StringProperty(name='', subtype='FILE_PATH', | |
default='\\tmp\\exported.svg', description='Save SVG file - use absolute path - checkbox on T-shelf') | |
def register(): | |
for i in classes: | |
bpy.utils.register_class(i) | |
def unregister(): | |
for i in classes: | |
bpy.utils.unregister_class(i) | |
if __name__ == "__main__": | |
register() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment