Fix material move (fill opacity problem comes from blender 4.3 itself)
parent
4d6dc06e4e
commit
58e6816e39
|
@ -373,10 +373,6 @@ def add_multiple_strokes(stroke_list, layer=None, use_current_frame=True, select
|
|||
|
||||
for s in stroke_list:
|
||||
add_stroke(s, target_frame, layer, obj, select=select)
|
||||
'''
|
||||
for s in stroke_data:
|
||||
add_stroke(s, target_frame)
|
||||
'''
|
||||
|
||||
# print(len(stroke_list), 'strokes pasted')
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ import numpy as np
|
|||
from time import time
|
||||
from .utils import (location_to_region, region_to_location)
|
||||
|
||||
|
||||
## DISABLED (in init, also in menu append, see register below)
|
||||
"""
|
||||
## Do not work on multiple object
|
||||
def batch_flat_reproject(obj, proj_type='VIEW', all_strokes=True, restore_frame=False):
|
||||
|
|
|
@ -93,6 +93,7 @@ class GPTB_OT_move_material_to_layer(Operator) :
|
|||
# t = time.time() # Dbg
|
||||
total = 0
|
||||
oct = 0
|
||||
|
||||
for ob in pool:
|
||||
mat_index = next((i for i, ms in enumerate(ob.material_slots) if ms.material and ms.material == mat), None)
|
||||
if mat_index is None:
|
||||
|
@ -110,26 +111,26 @@ class GPTB_OT_move_material_to_layer(Operator) :
|
|||
### Move Strokes to a new key (or existing key if comming for yet another layer)
|
||||
fct = 0
|
||||
sct = 0
|
||||
for l in gpl:
|
||||
if l == target_layer:
|
||||
for layer in gpl:
|
||||
if layer == target_layer:
|
||||
## ! infinite loop if target layer is included
|
||||
continue
|
||||
for f in l.frames:
|
||||
for fr in layer.frames:
|
||||
## skip if no stroke has active material
|
||||
if not next((s for s in f.drawing.strokes if s.material_index == mat_index), None):
|
||||
if not next((s for s in fr.drawing.strokes if s.material_index == mat_index), None):
|
||||
continue
|
||||
## Get/Create a destination frame and keep a reference to it
|
||||
if not (dest_key := key_dict.get(f.frame_number)):
|
||||
dest_key = target_layer.frames.new(f.frame_number)
|
||||
if not (dest_key := key_dict.get(fr.frame_number)):
|
||||
dest_key = target_layer.frames.new(fr.frame_number)
|
||||
key_dict[dest_key.frame_number] = dest_key
|
||||
|
||||
print(f'{ob.name} : frame {f.frame_number}')
|
||||
print(f'{ob.name} : frame {fr.frame_number}')
|
||||
## Replicate strokes in dest_keys
|
||||
stroke_to_delete = []
|
||||
for s in f.drawing.strokes:
|
||||
for s_idx, s in enumerate(fr.drawing.strokes):
|
||||
if s.material_index == mat_index:
|
||||
utils.copy_stroke_to_frame(s, dest_key)
|
||||
stroke_to_delete.append(s)
|
||||
stroke_to_delete.append(s_idx)
|
||||
|
||||
## Debug
|
||||
# if time.time() - t > 10:
|
||||
|
@ -138,16 +139,15 @@ class GPTB_OT_move_material_to_layer(Operator) :
|
|||
|
||||
sct += len(stroke_to_delete)
|
||||
|
||||
# print('Removing frames') # Dbg
|
||||
## Remove from source frame (f)
|
||||
## Remove from source frame (fr)
|
||||
if not self.copy:
|
||||
for s in reversed(stroke_to_delete):
|
||||
f.drawing.strokes.remove(s)
|
||||
# print('Removing frames') # Dbg
|
||||
if stroke_to_delete:
|
||||
fr.drawing.remove_strokes(indices=stroke_to_delete)
|
||||
|
||||
## ? Remove frame if layer is empty ? -> probably not, will show previous frame
|
||||
## ? Remove frame if layer is empty ? -> probably not, otherwise will show previous frame
|
||||
|
||||
fct += 1
|
||||
l.frames.update()
|
||||
|
||||
|
||||
if fct:
|
||||
|
|
|
@ -4,7 +4,7 @@ bl_info = {
|
|||
"name": "GP toolbox",
|
||||
"description": "Tool set for Grease Pencil in animation production",
|
||||
"author": "Samuel Bernou, Christophe Seux",
|
||||
"version": (4, 0, 1),
|
||||
"version": (4, 0, 2),
|
||||
"blender": (4, 3, 0),
|
||||
"location": "Sidebar (N menu) > Gpencil > Toolbox / Gpencil properties",
|
||||
"warning": "",
|
||||
|
@ -35,7 +35,7 @@ from . import OP_brushes
|
|||
from . import OP_file_checker
|
||||
from . import OP_copy_paste
|
||||
from . import OP_realign
|
||||
from . import OP_flat_reproject
|
||||
# from . import OP_flat_reproject # Disabled
|
||||
from . import OP_depth_move
|
||||
from . import OP_key_duplicate_send
|
||||
from . import OP_layer_manager
|
||||
|
@ -793,7 +793,7 @@ addon_modules = (
|
|||
OP_brushes,
|
||||
OP_cursor_snap_canvas,
|
||||
OP_copy_paste,
|
||||
OP_flat_reproject,
|
||||
# OP_flat_reproject # Disabled,
|
||||
OP_realign,
|
||||
OP_depth_move,
|
||||
OP_key_duplicate_send,
|
||||
|
|
194
utils.py
194
utils.py
|
@ -10,14 +10,80 @@ from math import sqrt
|
|||
from mathutils import Vector
|
||||
from sys import platform
|
||||
|
||||
## constants values
|
||||
|
||||
|
||||
""" def get_gp_parent(layer) :
|
||||
if layer.parent_type == "BONE" and layer.parent_bone :
|
||||
return layer.parent.pose.bones.get(layer.parent_bone)
|
||||
else :
|
||||
return layer.parent
|
||||
"""
|
||||
## Default stroke and points attributes
|
||||
stroke_attr = [
|
||||
'start_cap',
|
||||
'end_cap',
|
||||
'softness',
|
||||
'material_index',
|
||||
'fill_opacity',
|
||||
'fill_color',
|
||||
'cyclic',
|
||||
'aspect_ratio',
|
||||
'time_start',
|
||||
# 'curve_type', # read-only
|
||||
]
|
||||
|
||||
point_attr = [
|
||||
'position',
|
||||
'radius',
|
||||
'rotation',
|
||||
'opacity',
|
||||
'vertex_color',
|
||||
'delta_time',
|
||||
# 'select',
|
||||
]
|
||||
|
||||
### Attribute value, types and shape
|
||||
|
||||
attribute_value_string = {
|
||||
'FLOAT': "value",
|
||||
'INT': "value",
|
||||
'FLOAT_VECTOR': "vector",
|
||||
'FLOAT_COLOR': "color",
|
||||
'BYTE_COLOR': "color",
|
||||
'STRING': "value",
|
||||
'BOOLEAN': "value",
|
||||
'FLOAT2': "value",
|
||||
'INT8': "value",
|
||||
'INT32_2D': "value",
|
||||
'QUATERNION': "value",
|
||||
'FLOAT4X4': "value",
|
||||
}
|
||||
|
||||
attribute_value_dtype = {
|
||||
'FLOAT': np.float32,
|
||||
'INT': np.dtype('int'),
|
||||
'FLOAT_VECTOR': np.float32,
|
||||
'FLOAT_COLOR': np.float32,
|
||||
'BYTE_COLOR': np.int8,
|
||||
'STRING': np.dtype('str'),
|
||||
'BOOLEAN': np.dtype('bool'),
|
||||
'FLOAT2': np.float32,
|
||||
'INT8': np.int8,
|
||||
'INT32_2D': np.dtype('int'),
|
||||
'QUATERNION': np.float32,
|
||||
'FLOAT4X4': np.float32,
|
||||
}
|
||||
|
||||
attribute_value_shape = {
|
||||
'FLOAT': (),
|
||||
'INT': (),
|
||||
'FLOAT_VECTOR': (3,),
|
||||
'FLOAT_COLOR': (4,),
|
||||
'BYTE_COLOR': (4,),
|
||||
'STRING': (),
|
||||
'BOOLEAN': (),
|
||||
'FLOAT2':(2,),
|
||||
'INT8': (),
|
||||
'INT32_2D': (2,),
|
||||
'QUATERNION': (4,),
|
||||
'FLOAT4X4': (4,4),
|
||||
}
|
||||
|
||||
|
||||
def translate_range(OldValue, OldMin, OldMax, NewMax, NewMin):
|
||||
return (((OldValue - OldMin) * (NewMax - NewMin)) / (OldMax - OldMin)) + NewMin
|
||||
|
@ -557,64 +623,30 @@ def copy_stroke_to_frame(s, frame, select=True):
|
|||
return created stroke
|
||||
'''
|
||||
|
||||
ns = frame.drawing.strokes.new()
|
||||
|
||||
## Set strokes attr
|
||||
stroke_attr = [
|
||||
'line_width',
|
||||
'material_index',
|
||||
'draw_cyclic',
|
||||
'use_cyclic',
|
||||
'uv_scale',
|
||||
'uv_rotation',
|
||||
'hardness',
|
||||
'uv_translation',
|
||||
'vertex_color_fill',
|
||||
]
|
||||
frame.drawing.add_strokes([len(s.points)])
|
||||
ns = frame.drawing.strokes[-1]
|
||||
# print(len(s.points), 'new:', len(ns.points))
|
||||
#ns.material_index
|
||||
|
||||
## replicate attributes (simple loop)
|
||||
## TODO : might need to create atribute domain if does not exists in destination
|
||||
for attr in stroke_attr:
|
||||
if not hasattr(s, attr):
|
||||
continue
|
||||
# print(f'transfer stroke {attr}') # Dbg
|
||||
setattr(ns, attr, getattr(s, attr))
|
||||
|
||||
## create points
|
||||
point_count = len(s.points)
|
||||
ns.points.add(len(s.points))
|
||||
for src_p, dest_p in zip(s.points, ns.points):
|
||||
for attr in point_attr:
|
||||
setattr(dest_p, attr, getattr(src_p, attr))
|
||||
## Define selection
|
||||
dest_p.select=select
|
||||
|
||||
## Set points attr
|
||||
# for p, np in zip(s.points, ns.points):
|
||||
flat_list = [0.0] * point_count
|
||||
flat_uv_fill_list = [0.0, 0.0] * point_count
|
||||
flat_vector_list = [0.0, 0.0, 0.0] * point_count
|
||||
flat_color_list = [0.0, 0.0, 0.0, 0.0] * point_count
|
||||
## Direcly iterate over attribute ?
|
||||
# src_start = src_dr.curve_offsets[0].value
|
||||
# src_end = src_start + data_size
|
||||
# dst_start = dst_dr.curve_offsets[0].value
|
||||
# dst_end = dst_start + data_size
|
||||
# for src_idx, dest_idx in zip(range(src_start, src_end),range(dst_start, dst_end)):
|
||||
# setattr(dest_attr.data[dest_idx], val_type, getattr(source_attr.data[src_idx], val_type))
|
||||
|
||||
single_attr = [
|
||||
'pressure',
|
||||
'strength',
|
||||
'uv_factor',
|
||||
'uv_rotation',
|
||||
]
|
||||
|
||||
for attr in single_attr:
|
||||
# print(f'transfer point {attr}') # Dbg
|
||||
s.points.foreach_get(attr, flat_list)
|
||||
ns.points.foreach_set(attr, flat_list)
|
||||
|
||||
# print(f'transfer point co') # Dbg
|
||||
s.points.foreach_get('co', flat_vector_list)
|
||||
ns.points.foreach_set('co', flat_vector_list)
|
||||
|
||||
# print(f'transfer point uv_fill') # Dbg
|
||||
s.points.foreach_get('uv_fill', flat_uv_fill_list)
|
||||
ns.points.foreach_set('uv_fill', flat_uv_fill_list)
|
||||
|
||||
# print(f'transfer point vertex_color') # Dbg
|
||||
s.points.foreach_get('vertex_color', flat_color_list)
|
||||
ns.points.foreach_set('vertex_color', flat_color_list)
|
||||
|
||||
ns.select = select
|
||||
ns.points.update()
|
||||
return ns
|
||||
|
||||
"""## Works, but do not copy all attributes type (probably ok for GP though)
|
||||
|
@ -657,52 +689,6 @@ def bulk_frame_copy_attributes(source_attr, target_attr):
|
|||
# setattr(dest_attr.data[dest_idx], val_type, getattr(source_attr.data[src_idx], val_type))
|
||||
"""
|
||||
|
||||
attribute_value_string = {
|
||||
'FLOAT': "value",
|
||||
'INT': "value",
|
||||
'FLOAT_VECTOR': "vector",
|
||||
'FLOAT_COLOR': "color",
|
||||
'BYTE_COLOR': "color",
|
||||
'STRING': "value",
|
||||
'BOOLEAN': "value",
|
||||
'FLOAT2': "value",
|
||||
'INT8': "value",
|
||||
'INT32_2D': "value",
|
||||
'QUATERNION': "value",
|
||||
'FLOAT4X4': "value",
|
||||
}
|
||||
|
||||
attribute_value_dtype = {
|
||||
'FLOAT': np.float32,
|
||||
'INT': np.dtype('int'),
|
||||
'FLOAT_VECTOR': np.float32,
|
||||
'FLOAT_COLOR': np.float32,
|
||||
'BYTE_COLOR': np.int8,
|
||||
'STRING': np.dtype('str'),
|
||||
'BOOLEAN': np.dtype('bool'),
|
||||
'FLOAT2': np.float32,
|
||||
'INT8': np.int8,
|
||||
'INT32_2D': np.dtype('int'),
|
||||
'QUATERNION': np.float32,
|
||||
'FLOAT4X4': np.float32,
|
||||
}
|
||||
|
||||
attribute_value_shape = {
|
||||
'FLOAT': (),
|
||||
'INT': (),
|
||||
'FLOAT_VECTOR': (3,),
|
||||
'FLOAT_COLOR': (4,),
|
||||
'BYTE_COLOR': (4,),
|
||||
'STRING': (),
|
||||
'BOOLEAN': (),
|
||||
'FLOAT2':(2,),
|
||||
'INT8': (),
|
||||
'INT32_2D': (2,),
|
||||
'QUATERNION': (4,),
|
||||
'FLOAT4X4': (4,4),
|
||||
}
|
||||
|
||||
|
||||
def bulk_copy_attributes(source_attr, target_attr):
|
||||
'''Get and apply data as flat numpy array based on attribute type'''
|
||||
value_string = attribute_value_string[source_attr.data_type]
|
||||
|
|
Loading…
Reference in New Issue