diff --git a/CHANGELOG.md b/CHANGELOG.md index b73b47a..2af1db6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +2.0.2 + +- added: possibility to select which point attribute is copied by GP layer copy to clipboard + 2.0.1 - added: enable/disable camera animation separately in `animation manager` diff --git a/OP_copy_paste.py b/OP_copy_paste.py index cc167b8..48d86e2 100644 --- a/OP_copy_paste.py +++ b/OP_copy_paste.py @@ -61,7 +61,8 @@ def getMatrix (layer) : default_pt_uv_fill = Vector((0.5, 0.5)) -def dump_gp_point(p, l, obj): +def dump_gp_point(p, l, obj, + pressure=True, strength=True, vertex_color=True, uv_fill=True, uv_factor=True, uv_rotation=True): '''add properties of a given points to a dic and return it''' pdic = {} #point_attr_list = ('co', 'pressure', 'select', 'strength') #select#'rna_type' @@ -72,26 +73,30 @@ def dump_gp_point(p, l, obj): pdic['co'] = convertAttr(obj.matrix_world @ mat @ getattr(p,'co')) else: pdic['co'] = convertAttr(obj.matrix_world @ getattr(p,'co')) - pdic['pressure'] = convertAttr(getattr(p,'pressure')) - # pdic['select'] = convertAttr(getattr(p,'select'))# need selection ? - pdic['strength'] = convertAttr(getattr(p,'strength')) + + # pdic['select'] = convertAttr(getattr(p,'select')) # need selection ? + if pressure and p.pressure != 1.0: + pdic['pressure'] = convertAttr(getattr(p,'pressure')) + if strength and p.strength != 1.0: + pdic['strength'] = convertAttr(getattr(p,'strength')) ## get vertex color (long...) - if p.vertex_color[:] != (0.0, 0.0, 0.0, 0.0): + if vertex_color and p.vertex_color[:] != (0.0, 0.0, 0.0, 0.0): pdic['vertex_color'] = convertAttr(p.vertex_color) ## UV attr (maybe uv fill is always (0.5,0.5) ? also exists at stroke level...) - if p.uv_fill != default_pt_uv_fill: + if uv_fill and p.uv_fill != default_pt_uv_fill: pdic['uv_fill'] = convertAttr(p.uv_fill) - if p.uv_factor != 0.0: + if uv_factor and p.uv_factor != 0.0: pdic['uv_factor'] = convertAttr(p.uv_factor) - if p.uv_rotation != 0.0: + if uv_rotation and p.uv_rotation != 0.0: pdic['uv_rotation'] = convertAttr(p.uv_rotation) return pdic -def dump_gp_stroke_range(s, sid, l, obj): +def dump_gp_stroke_range(s, sid, l, obj, + pressure=True, strength=True, vertex_color=True, uv_fill=True, uv_factor=True, uv_rotation=True): '''Get a grease pencil stroke and return a dic with attribute (points attribute being a dic of dics to store points and their attributes) ''' @@ -105,10 +110,10 @@ def dump_gp_stroke_range(s, sid, l, obj): if s.material_index != 0: sdic['material_index'] = s.material_index - if getattr(s, 'draw_cyclic', None):# pre-2.92 + if getattr(s, 'draw_cyclic', None): # pre-2.92 sdic['draw_cyclic'] = s.draw_cyclic - if getattr(s, 'use_cyclic', None):# from 2.92 + if getattr(s, 'use_cyclic', None): # from 2.92 sdic['use_cyclic'] = s.use_cyclic if s.uv_scale != 1.0: @@ -127,18 +132,20 @@ def dump_gp_stroke_range(s, sid, l, obj): sdic['vertex_color_fill'] = convertAttr(s.vertex_color_fill) points = [] - if sid is None:#no ids, just full points... + if sid is None: # no ids, just full points... for p in s.points: - points.append(dump_gp_point(p,l,obj)) + points.append(dump_gp_point(p,l,obj, + pressure=pressure, strength=strength, vertex_color=vertex_color, uv_fill=uv_fill, uv_factor=uv_factor, uv_rotation=uv_rotation)) else: for pid in sid: - points.append(dump_gp_point(s.points[pid],l,obj)) + points.append(dump_gp_point(s.points[pid],l,obj, + pressure=pressure, strength=strength, vertex_color=vertex_color, uv_fill=uv_fill, uv_factor=uv_factor, uv_rotation=uv_rotation)) sdic['points'] = points return sdic -def copycut_strokes(layers=None, copy=True, keep_empty=True):# (mayber allow filter) +def copycut_strokes(layers=None, copy=True, keep_empty=True): ''' copy all visibles selected strokes on active frame layers can be None, a single layer object or list of layer object as filter @@ -276,7 +283,8 @@ def copy_all_strokes(layers=None): return stroke_list """ -def copy_all_strokes_in_frame(frame=None, layers=None, obj=None): +def copy_all_strokes_in_frame(frame=None, layers=None, obj=None, + pressure=True, strength=True, vertex_color=True, uv_fill=True, uv_factor=True, uv_rotation=True): ''' copy all stroke, not affected by selection on active frame layers can be None, a single layer object or list of layer object as filter @@ -292,7 +300,7 @@ def copy_all_strokes_in_frame(frame=None, layers=None, obj=None): if not layers: # by default all visible layers - layers = [l for l in gpl if not l.hide and not l.lock]# include locked ? + layers = [l for l in gpl if not l.hide and not l.lock] # include locked ? if not isinstance(layers, list): # if a single layer object is send put in a list layers = [layers] @@ -309,7 +317,8 @@ def copy_all_strokes_in_frame(frame=None, layers=None, obj=None): ## full stroke version # if s.select: # send index of all points to get the whole stroke with "range" - stroke_list.append( dump_gp_stroke_range(s, [i for i in range(len(s.points))], l, obj) ) + stroke_list.append( dump_gp_stroke_range(s, [i for i in range(len(s.points))], l, obj, + pressure=pressure,strength=strength,vertex_color=vertex_color,uv_fill=uv_fill,uv_factor=uv_factor,uv_rotation=uv_rotation)) # print(len(stroke_list), 'strokes copied in', time()-t0, 'seconds') return stroke_list @@ -338,7 +347,7 @@ def add_stroke(s, frame, layer, obj, select=False): for k, v in pt.items(): if k == 'co': setattr(ns.points[i], k, v) - ns.points[i].co = ob_mat_inv @ mat @ ns.points[i].co# invert of object * invert of layer * coordinate + ns.points[i].co = ob_mat_inv @ mat @ ns.points[i].co # invert of object * invert of layer * coordinate else: setattr(ns.points[i], k, v) if select: @@ -408,7 +417,7 @@ def add_multiple_strokes(stroke_list, layer=None, use_current_frame=True, select class GPCLIP_OT_copy_strokes(bpy.types.Operator): bl_idname = "gp.copy_strokes" bl_label = "GP Copy strokes" - bl_description = "Copy strokes to str in paperclip" + bl_description = "Copy strokes to text in paperclip" bl_options = {"REGISTER"} #copy = bpy.props.BoolProperty(default=True) @@ -425,7 +434,7 @@ class GPCLIP_OT_copy_strokes(bpy.types.Operator): #ct = check_pressure() strokelist = copycut_strokes(copy=True, keep_empty=True) if not strokelist: - self.report({'ERROR'},'rien a copier') + self.report({'ERROR'}, 'Nothing to copy') return {"CANCELLED"} bpy.context.window_manager.clipboard = json.dumps(strokelist)#copy=self.copy #if ct: @@ -438,7 +447,7 @@ class GPCLIP_OT_copy_strokes(bpy.types.Operator): class GPCLIP_OT_cut_strokes(bpy.types.Operator): bl_idname = "gp.cut_strokes" bl_label = "GP Cut strokes" - bl_description = "Cut strokes to str in paperclip" + bl_description = "Cut strokes to text in paperclip" bl_options = {"REGISTER"} @classmethod @@ -451,7 +460,7 @@ class GPCLIP_OT_cut_strokes(bpy.types.Operator): # return {"CANCELLED"} t0 = time() - strokelist = copycut_strokes(copy=False, keep_empty=True)#ct = check_pressure() + strokelist = copycut_strokes(copy=False, keep_empty=True) # ct = check_pressure() if not strokelist: self.report({'ERROR'},'Nothing to cut') return {"CANCELLED"} @@ -503,6 +512,37 @@ class GPCLIP_OT_copy_multi_strokes(bpy.types.Operator): def poll(cls, context): return context.object and context.object.type == 'GPENCIL' + pressure : bpy.props.BoolProperty(name='pressure', default=True, + description='Dump point pressure attribute (already skipped if at default value)') + strength : bpy.props.BoolProperty(name='strength', default=True, + description='Dump point strength attribute (already skipped if at default value)') + vertex_color : bpy.props.BoolProperty(name='vertex color', default=True, + description='Dump point vertex_color attribute (already skipped if at default value)') + uv_fill : bpy.props.BoolProperty(name='uv fill', default=True, + description='Dump point uv_fill attribute (already skipped if at default value)') + uv_factor : bpy.props.BoolProperty(name='uv factor', default=True, + description='Dump point uv_factor attribute (already skipped if at default value)') + uv_rotation : bpy.props.BoolProperty(name='uv rotation', default=True, + description='Dump point uv_rotation attribute (already skipped if at default value)') + + def invoke(self, context, event): + # self.file_dump = event.ctrl + return context.window_manager.invoke_props_dialog(self) # , width=400 + # return self.execute(context) + + def draw(self, context): + layout=self.layout + layout.use_property_split = True + col = layout.column() + col.label(text='Keep following point attributes:') + col.prop(self, 'pressure') + col.prop(self, 'strength') + col.prop(self, 'vertex_color') + col.prop(self, 'uv_fill') + col.prop(self, 'uv_factor') + col.prop(self, 'uv_rotation') + return + def execute(self, context): bake_moves = True skip_empty_frame = False @@ -528,15 +568,18 @@ class GPCLIP_OT_copy_multi_strokes(bpy.types.Operator): for f in l.frames: if skip_empty_frame and not len(f.strokes): continue - context.scene.frame_set(f.frame_number)#use matrix of this frame - strokelist = copy_all_strokes_in_frame(frame=f, layers=l, obj=obj) + context.scene.frame_set(f.frame_number) # use matrix of this frame + strokelist = copy_all_strokes_in_frame(frame=f, layers=l, obj=obj, + pressure=self.pressure, strength=self.strength, vertex_color=self.vertex_color, + uv_fill=self.uv_fill, uv_factor=self.uv_factor, uv_rotation=self.uv_rotation) frame_dic[f.frame_number] = strokelist layerdic[l.info] = frame_dic - else:# bake position: copy frame where object as moved even if frame is unchanged + else: # bake position: copy frame where object as moved even if frame is unchanged for l in layerpool: + print('dump layer:', l.info) if not l.frames: continue# skip empty layers @@ -548,7 +591,7 @@ class GPCLIP_OT_copy_multi_strokes(bpy.types.Operator): curmat = prevmat = obj.matrix_world.copy() for i in range(context.scene.frame_start, context.scene.frame_end): - context.scene.frame_set(i)#use matrix of this frame + context.scene.frame_set(i) # use matrix of this frame curmat = obj.matrix_world.copy() # if object has moved or current time is on a draw key @@ -563,7 +606,10 @@ class GPCLIP_OT_copy_multi_strokes(bpy.types.Operator): if skip_empty_frame and not len(f.strokes): continue - strokelist = copy_all_strokes_in_frame(frame=f, layers=l, obj=obj) + strokelist = copy_all_strokes_in_frame(frame=f, layers=l, obj=obj, + pressure=self.pressure, strength=self.strength, vertex_color=self.vertex_color, + uv_fill=self.uv_fill, uv_factor=self.uv_factor, uv_rotation=self.uv_rotation) + frame_dic[i] = strokelist prevmat = curmat diff --git a/__init__.py b/__init__.py index e7de68b..4f29337 100755 --- a/__init__.py +++ b/__init__.py @@ -4,7 +4,7 @@ bl_info = { "name": "GP toolbox", "description": "Tool set for Grease Pencil in animation production", "author": "Samuel Bernou, Christophe Seux", -"version": (2, 0, 1), +"version": (2, 0, 2), "blender": (2, 91, 0), "location": "Sidebar (N menu) > Gpencil > Toolbox / Gpencil properties", "warning": "",