Skip to content

Instantly share code, notes, and snippets.

@zeffii
Forked from anonymous/node_BMesh_Instancer.py
Created June 9, 2014 22:49
Show Gist options
  • Save zeffii/db9001094fe91b676b34 to your computer and use it in GitHub Desktop.
Save zeffii/db9001094fe91b676b34 to your computer and use it in GitHub Desktop.
import bpy
import bmesh
import mathutils
from mathutils import Vector, Matrix
from bpy.props import BoolProperty, FloatVectorProperty, StringProperty
from node_s import *
from util import *
import random
def get_random_init():
greek_alphabet = [
'Alpha', 'Beta', 'Gamma', 'Delta',
'Epsilon', 'Zeta', 'Eta', 'Theta',
'Iota', 'Kappa', 'Lamda', 'Mu',
'Nu', 'Xi', 'Omicron', 'Pi',
'Rho', 'Sigma', 'Tau', 'Upsilon',
'Phi', 'Chi', 'Psi', 'Omega']
return random.choice(greek_alphabet)
def make_or_update_instance(node, context, obj_name, matrix):
scene = context.scene
meshes = bpy.data.meshes
objects = bpy.data.objects
clone_mesh_name = n.object_to_clone
if obj_name in objects:
sv_object = objects[obj_name]
else:
instance_mesh = meshes[clone_mesh_name]
sv_object = objects.new(obj_name, instance_mesh)
scene.objects.link(sv_object)
scene.update()
# apply matrices
if matrix:
sv_object.matrix_local = list(zip(*matrix))
class SvInstancerOp(bpy.types.Operator):
bl_idname = "node.instancer_config"
bl_label = "Sverchok instancer op"
bl_options = {'REGISTER', 'UNDO'}
obj_name = StringProperty(default="")
def execute(self, context):
n = context.node
n.object_to_clone = bpy.data.objects[obj_name].data.name
return {'FINISHED'}
class SvInstancerNode(Node, SverchCustomTreeNode):
bl_idname = 'InstancerNode'
bl_label = 'Instancer Node'
bl_icon = 'OUTLINER_OB_EMPTY'
activate = BoolProperty(
name='Show', description='Activate node?',
default=True,
update=updateNode)
basemesh_name = StringProperty(default='Alpha', update=updateNode)
grouping = BoolProperty(default=False)
object_to_clone = StringProperty(default='', update=updateNode)
def init(self, context):
self.inputs.new('MatrixSocket', 'matrix', 'matrix')
def draw_buttons(self, context, layout):
row = layout.row(align=True)
row.prop(self, "activate", text="Update")
row = layout.row(align=True)
row.label('name of object')
row = layout.row(align=True)
row.prop(self, "object_to_clone")
row.operator(self, "node.instancer_config", text="use")
row = layout.row()
row.prop(self, "grouping", text="to Group")
layout.label("Base mesh name(s)", icon='OUTLINER_OB_MESH')
col = layout.column(align=True)
row = col.row(align=True)
row.prop(self, "basemesh_name", text="")
def abort_processing(self):
try:
l = bpy.data.node_groups[self.id_data.name]
except Exception as e:
print(self.name, "cannot run during startup, press update.")
return True
def get_corrected_data(self, socket_name, socket_type):
inputs = self.inputs
socket = inputs[socket_name].links[0].from_socket
if isinstance(socket, socket_type):
socket_in = SvGetSocketAnyType(self, inputs[socket_name])
return dataCorrect(socket_in)
else:
return []
def update(self):
if self.abort_processing() and not self.activate:
return
s_name, s_type = ['matrices', MatrixSocket]
if s_name in inputs and inputs[s_name].links:
matrices = self.get_corrected_data(s_name, s_type)
if not matrices:
return
# we have matrices, we can process, go go go!
for obj_index, matrix in enumerate(matrices):
obj_name = self.basemesh_name + "_" + str(obj_index)
make_or_update_instance(self, context, obj_name, matrix)
# obj_index is now the last index fond in matrices
self.remove_non_updated_objects(obj_index, self.basemesh_name)
if self.grouping:
self.to_group()
def to_group(self):
objs = bpy.data.objects
if not self.basemesh_name in bpy.data.groups:
newgroup = bpy.data.groups.new(self.basemesh_name)
else:
newgroup = bpy.data.groups[self.basemesh_name]
for obj in objs:
if self.basemesh_name in obj.name:
if obj.name not in newgroup.objects:
newgroup.objects.link(obj)
def remove_non_updated_objects(self, obj_index, _name):
meshes = bpy.data.meshes
objects = bpy.data.objects
objects_to_reselect = []
for i in (i for i in objects if i.select):
objects_to_reselect.append(i.name)
i.select = False
objs = [obj for obj in objects if obj.type == 'MESH']
objs = [obj for obj in objs if obj.name.startswith(_name)]
objs = [obj.name for obj in objs if int(obj.name.split("_")[-1]) > obj_index]
# select and finally remove all excess objects
for object_name in objs:
objects[object_name].select = True
bpy.ops.object.delete()
# reselect
for name in objects_to_reselect:
bpy.data.objects[name].select = True
# fingers crossed.
def update_socket(self, context):
self.update()
def register():
bpy.utils.register_class(SvInstancerNode)
bpy.utils.register_class(SvInstancerOp)
def unregister():
bpy.utils.unregister_class(SvInstancerNode)
bpy.utils.unregister_class(SvInstancerOp)
if __name__ == '__main__':
register()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment