CM3D2 Converter.misc_INFO_MT_curve_add
1# 「3Dビュー」エリア → 追加(Shift+A) → カーブ 2import math 3import random 4import bpy 5import bpy_extras.view3d_utils 6import mathutils 7from . import common 8from . import compat 9from .translations.pgettext_functions import * 10 11 12# メニュー等に項目追加 13def menu_func(self, context): 14 self.layout.separator() 15 self.layout.operator('curve.hair_bunch_add', text="髪の房", icon_value=common.kiss_icon()) 16 17 18@compat.BlRegister() 19class CNV_OT_hair_bunch_add(bpy.types.Operator): 20 bl_idname = 'curve.hair_bunch_add' 21 bl_label = "髪の房を追加" 22 bl_description = "アニメ調の髪の房を追加します" 23 bl_options = {'REGISTER', 'UNDO'} 24 25 radius = bpy.props.FloatProperty(name="房の半径", default=0.1, min=0, max=10, soft_min=0, soft_max=10, step=10, precision=2) 26 random_multi = bpy.props.FloatProperty(name="ランダム要素の強さ", default=0.5, min=0, max=10, soft_min=0, soft_max=10, step=10, precision=2) 27 z_plus = bpy.props.FloatProperty(name="中間のZ軸の高さ", default=0.1, min=0, max=10, soft_min=0, soft_max=10, step=10, precision=2) 28 29 @classmethod 30 def poll(cls, context): 31 return context.mode == 'OBJECT' 32 33 def invoke(self, context, event): 34 35 self.pre_draw = bpy.types.VIEW3D_HT_header.draw 36 37 def header_draw(self, context): 38 row = self.layout.row(align=True) 39 row.label(text="ホイール:太さ変更") 40 row.label(text="ホイールクリック:ランダム強度変更") 41 row.label(text="ZXキー:高さ変更") 42 bpy.types.VIEW3D_HT_header.draw = header_draw 43 44 # if context.active_object: 45 # if context.active_object.mode != 'OBJECT': 46 # self.report(type={'ERROR'}, message="オブジェクトモードで実行してください") 47 # return {'CANCELLED'} 48 49 cursor_loc = compat.get_cursor_loc(context) 50 self.end_location = bpy_extras.view3d_utils.region_2d_to_location_3d(context.region, context.region_data, (event.mouse_region_x, event.mouse_region_y), cursor_loc) 51 52 curve = context.blend_data.curves.new("Hair Bunch", 'CURVE') 53 ob = context.blend_data.objects.new("Hair Bunch", curve) 54 compat.link(context.scene, ob) 55 compat.set_active(context, ob) 56 compat.set_select(ob, True) 57 58 curve.dimensions = '3D' 59 curve.resolution_u = 5 60 61 spline = curve.splines.new('NURBS') 62 63 spline.points.add(3) 64 spline.points[0].radius = 0.0 65 spline.points[-1].radius = 0.0 66 spline.use_endpoint_u = True 67 spline.order_u = 4 68 spline.resolution_u = 5 69 70 self.set_spline(spline, context) 71 72 self.object = ob 73 self.curve = curve 74 self.spline = spline 75 76 bevel_curve = context.blend_data.curves.new("Hair Bunch Bevel", 'CURVE') 77 bevel_ob = context.blend_data.objects.new("Hair Bunch Bevel", bevel_curve) 78 compat.link(context.scene, bevel_ob) 79 compat.set_select(bevel_ob, True) 80 curve.bevel_object = bevel_ob 81 82 bevel_ob.parent = ob 83 bevel_ob.parent_type = 'VERTEX' 84 bevel_ob.parent_vertices = (3, 3, 3) 85 86 bevel_curve.dimensions = '2D' 87 bevel_curve.fill_mode = 'NONE' 88 bevel_curve.resolution_u = 2 89 90 spline = bevel_curve.splines.new('NURBS') 91 spline.points.add(7) 92 spline.use_cyclic_u = True 93 spline.order_u = 4 94 spline.resolution_u = 2 95 96 self.bevel_object = bevel_ob 97 self.bevel_curve = bevel_curve 98 self.bevel_spline = spline 99 100 self.set_bevel_spline(spline) 101 102 context.window_manager.modal_handler_add(self) 103 return {'RUNNING_MODAL'} 104 105 def modal(self, context, event): 106 107 if event.type == 'MOUSEMOVE': 108 cursor_loc = compat.get_cursor_loc(context) 109 self.end_location = bpy_extras.view3d_utils.region_2d_to_location_3d(context.region, context.region_data, (event.mouse_region_x, event.mouse_region_y), cursor_loc) 110 self.execute(context) 111 112 elif event.type == 'WHEELUPMOUSE' and event.value == 'PRESS': 113 self.radius += 0.05 114 self.set_bevel_spline(self.bevel_spline) 115 self.object.update_tag({'OBJECT', 'DATA'}) 116 elif event.type == 'WHEELDOWNMOUSE' and event.value == 'PRESS': 117 self.radius -= 0.05 118 self.set_bevel_spline(self.bevel_spline) 119 self.object.update_tag({'OBJECT', 'DATA'}) 120 121 elif event.type == 'MIDDLEMOUSE' and event.value == 'PRESS': 122 if 0.9 < self.random_multi: 123 self.random_multi = 0.0 124 elif 0.4 < self.random_multi: 125 self.random_multi = 1.0 126 else: 127 self.random_multi = 0.5 128 self.set_bevel_spline(self.bevel_spline) 129 130 elif event.type == 'Z' and event.value == 'PRESS': 131 self.z_plus += 0.1 132 self.execute(context) 133 elif event.type == 'X' and event.value == 'PRESS': 134 self.z_plus -= 0.1 135 self.execute(context) 136 137 elif event.type == 'LEFTMOUSE' and event.value == 'PRESS': 138 bpy.types.VIEW3D_HT_header.draw = self.pre_draw 139 context.area.tag_redraw() 140 return {'FINISHED'} 141 142 elif event.type in {'RIGHTMOUSE', 'ESC'} and event.value == 'PRESS': 143 common.remove_data([self.object, self.bevel_object, self.curve, self.bevel_curve]) 144 bpy.types.VIEW3D_HT_header.draw = self.pre_draw 145 context.area.tag_redraw() 146 return {'CANCELLED'} 147 148 return {'RUNNING_MODAL'} 149 150 def get_random_point(self, co): 151 r = self.radius * self.random_multi 152 co.x = co.x + random.uniform(-r, r) 153 co.y = co.y + random.uniform(-r, r) 154 return co 155 156 def set_bevel_spline(self, spline): 157 r = self.radius 158 vec = mathutils.Vector((0, r, 0)) 159 min_rad = -math.radians(360 / len(spline.points)) 160 for index, point in enumerate(spline.points): 161 eul = mathutils.Euler((0, 0, min_rad * index), 'XYZ') 162 now_vec = vec.copy() 163 now_vec.rotate(eul) 164 now_vec = self.get_random_point(now_vec) 165 point.co = list(now_vec[:]) + [1] 166 167 def set_spline(self, spline, context): 168 cursor_loc = compat.get_cursor_loc(context) 169 diff_co = self.end_location - cursor_loc 170 171 plus_co = diff_co * 0.333333 172 plus_co.z = -plus_co.z + self.z_plus 173 174 point1 = diff_co * 0.333333 175 point1 += plus_co * 1 176 point1 += cursor_loc 177 178 point2 = diff_co * 0.666666 179 point2 += plus_co * 1 180 point2 += cursor_loc 181 182 spline.points[0].co = list(cursor_loc[:]) + [1] 183 spline.points[1].co = list(point1[:]) + [1] 184 spline.points[2].co = list(point2[:]) + [1] 185 spline.points[-1].co = list(self.end_location[:]) + [1] 186 187 def execute(self, context): 188 try: 189 self.set_spline(self.spline, context) 190 except: 191 self.report(type={'ERROR'}, message="オブジェクトモードで実行してください") 192 return {'CANCELLED'} 193 return {'FINISHED'}
@compat.BlRegister()
class
CNV_OT_hair_bunch_add19@compat.BlRegister() 20class CNV_OT_hair_bunch_add(bpy.types.Operator): 21 bl_idname = 'curve.hair_bunch_add' 22 bl_label = "髪の房を追加" 23 bl_description = "アニメ調の髪の房を追加します" 24 bl_options = {'REGISTER', 'UNDO'} 25 26 radius = bpy.props.FloatProperty(name="房の半径", default=0.1, min=0, max=10, soft_min=0, soft_max=10, step=10, precision=2) 27 random_multi = bpy.props.FloatProperty(name="ランダム要素の強さ", default=0.5, min=0, max=10, soft_min=0, soft_max=10, step=10, precision=2) 28 z_plus = bpy.props.FloatProperty(name="中間のZ軸の高さ", default=0.1, min=0, max=10, soft_min=0, soft_max=10, step=10, precision=2) 29 30 @classmethod 31 def poll(cls, context): 32 return context.mode == 'OBJECT' 33 34 def invoke(self, context, event): 35 36 self.pre_draw = bpy.types.VIEW3D_HT_header.draw 37 38 def header_draw(self, context): 39 row = self.layout.row(align=True) 40 row.label(text="ホイール:太さ変更") 41 row.label(text="ホイールクリック:ランダム強度変更") 42 row.label(text="ZXキー:高さ変更") 43 bpy.types.VIEW3D_HT_header.draw = header_draw 44 45 # if context.active_object: 46 # if context.active_object.mode != 'OBJECT': 47 # self.report(type={'ERROR'}, message="オブジェクトモードで実行してください") 48 # return {'CANCELLED'} 49 50 cursor_loc = compat.get_cursor_loc(context) 51 self.end_location = bpy_extras.view3d_utils.region_2d_to_location_3d(context.region, context.region_data, (event.mouse_region_x, event.mouse_region_y), cursor_loc) 52 53 curve = context.blend_data.curves.new("Hair Bunch", 'CURVE') 54 ob = context.blend_data.objects.new("Hair Bunch", curve) 55 compat.link(context.scene, ob) 56 compat.set_active(context, ob) 57 compat.set_select(ob, True) 58 59 curve.dimensions = '3D' 60 curve.resolution_u = 5 61 62 spline = curve.splines.new('NURBS') 63 64 spline.points.add(3) 65 spline.points[0].radius = 0.0 66 spline.points[-1].radius = 0.0 67 spline.use_endpoint_u = True 68 spline.order_u = 4 69 spline.resolution_u = 5 70 71 self.set_spline(spline, context) 72 73 self.object = ob 74 self.curve = curve 75 self.spline = spline 76 77 bevel_curve = context.blend_data.curves.new("Hair Bunch Bevel", 'CURVE') 78 bevel_ob = context.blend_data.objects.new("Hair Bunch Bevel", bevel_curve) 79 compat.link(context.scene, bevel_ob) 80 compat.set_select(bevel_ob, True) 81 curve.bevel_object = bevel_ob 82 83 bevel_ob.parent = ob 84 bevel_ob.parent_type = 'VERTEX' 85 bevel_ob.parent_vertices = (3, 3, 3) 86 87 bevel_curve.dimensions = '2D' 88 bevel_curve.fill_mode = 'NONE' 89 bevel_curve.resolution_u = 2 90 91 spline = bevel_curve.splines.new('NURBS') 92 spline.points.add(7) 93 spline.use_cyclic_u = True 94 spline.order_u = 4 95 spline.resolution_u = 2 96 97 self.bevel_object = bevel_ob 98 self.bevel_curve = bevel_curve 99 self.bevel_spline = spline 100 101 self.set_bevel_spline(spline) 102 103 context.window_manager.modal_handler_add(self) 104 return {'RUNNING_MODAL'} 105 106 def modal(self, context, event): 107 108 if event.type == 'MOUSEMOVE': 109 cursor_loc = compat.get_cursor_loc(context) 110 self.end_location = bpy_extras.view3d_utils.region_2d_to_location_3d(context.region, context.region_data, (event.mouse_region_x, event.mouse_region_y), cursor_loc) 111 self.execute(context) 112 113 elif event.type == 'WHEELUPMOUSE' and event.value == 'PRESS': 114 self.radius += 0.05 115 self.set_bevel_spline(self.bevel_spline) 116 self.object.update_tag({'OBJECT', 'DATA'}) 117 elif event.type == 'WHEELDOWNMOUSE' and event.value == 'PRESS': 118 self.radius -= 0.05 119 self.set_bevel_spline(self.bevel_spline) 120 self.object.update_tag({'OBJECT', 'DATA'}) 121 122 elif event.type == 'MIDDLEMOUSE' and event.value == 'PRESS': 123 if 0.9 < self.random_multi: 124 self.random_multi = 0.0 125 elif 0.4 < self.random_multi: 126 self.random_multi = 1.0 127 else: 128 self.random_multi = 0.5 129 self.set_bevel_spline(self.bevel_spline) 130 131 elif event.type == 'Z' and event.value == 'PRESS': 132 self.z_plus += 0.1 133 self.execute(context) 134 elif event.type == 'X' and event.value == 'PRESS': 135 self.z_plus -= 0.1 136 self.execute(context) 137 138 elif event.type == 'LEFTMOUSE' and event.value == 'PRESS': 139 bpy.types.VIEW3D_HT_header.draw = self.pre_draw 140 context.area.tag_redraw() 141 return {'FINISHED'} 142 143 elif event.type in {'RIGHTMOUSE', 'ESC'} and event.value == 'PRESS': 144 common.remove_data([self.object, self.bevel_object, self.curve, self.bevel_curve]) 145 bpy.types.VIEW3D_HT_header.draw = self.pre_draw 146 context.area.tag_redraw() 147 return {'CANCELLED'} 148 149 return {'RUNNING_MODAL'} 150 151 def get_random_point(self, co): 152 r = self.radius * self.random_multi 153 co.x = co.x + random.uniform(-r, r) 154 co.y = co.y + random.uniform(-r, r) 155 return co 156 157 def set_bevel_spline(self, spline): 158 r = self.radius 159 vec = mathutils.Vector((0, r, 0)) 160 min_rad = -math.radians(360 / len(spline.points)) 161 for index, point in enumerate(spline.points): 162 eul = mathutils.Euler((0, 0, min_rad * index), 'XYZ') 163 now_vec = vec.copy() 164 now_vec.rotate(eul) 165 now_vec = self.get_random_point(now_vec) 166 point.co = list(now_vec[:]) + [1] 167 168 def set_spline(self, spline, context): 169 cursor_loc = compat.get_cursor_loc(context) 170 diff_co = self.end_location - cursor_loc 171 172 plus_co = diff_co * 0.333333 173 plus_co.z = -plus_co.z + self.z_plus 174 175 point1 = diff_co * 0.333333 176 point1 += plus_co * 1 177 point1 += cursor_loc 178 179 point2 = diff_co * 0.666666 180 point2 += plus_co * 1 181 point2 += cursor_loc 182 183 spline.points[0].co = list(cursor_loc[:]) + [1] 184 spline.points[1].co = list(point1[:]) + [1] 185 spline.points[2].co = list(point2[:]) + [1] 186 spline.points[-1].co = list(self.end_location[:]) + [1] 187 188 def execute(self, context): 189 try: 190 self.set_spline(self.spline, context) 191 except: 192 self.report(type={'ERROR'}, message="オブジェクトモードで実行してください") 193 return {'CANCELLED'} 194 return {'FINISHED'}
radius: <_PropertyDeferred, <built-in function FloatProperty>, {'name': '房の半径', 'default': 0.1, 'min': 0, 'max': 10, 'soft_min': 0, 'soft_max': 10, 'step': 10, 'precision': 2, 'attr': 'radius'}> =
<_PropertyDeferred, <built-in function FloatProperty>, {'name': '房の半径', 'default': 0.1, 'min': 0, 'max': 10, 'soft_min': 0, 'soft_max': 10, 'step': 10, 'precision': 2, 'attr': 'radius'}>
random_multi: <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'ランダム要素の強さ', 'default': 0.5, 'min': 0, 'max': 10, 'soft_min': 0, 'soft_max': 10, 'step': 10, 'precision': 2, 'attr': 'random_multi'}> =
<_PropertyDeferred, <built-in function FloatProperty>, {'name': 'ランダム要素の強さ', 'default': 0.5, 'min': 0, 'max': 10, 'soft_min': 0, 'soft_max': 10, 'step': 10, 'precision': 2, 'attr': 'random_multi'}>
z_plus: <_PropertyDeferred, <built-in function FloatProperty>, {'name': '中間のZ軸の高さ', 'default': 0.1, 'min': 0, 'max': 10, 'soft_min': 0, 'soft_max': 10, 'step': 10, 'precision': 2, 'attr': 'z_plus'}> =
<_PropertyDeferred, <built-in function FloatProperty>, {'name': '中間のZ軸の高さ', 'default': 0.1, 'min': 0, 'max': 10, 'soft_min': 0, 'soft_max': 10, 'step': 10, 'precision': 2, 'attr': 'z_plus'}>
def
invoke(self, context, event):
34 def invoke(self, context, event): 35 36 self.pre_draw = bpy.types.VIEW3D_HT_header.draw 37 38 def header_draw(self, context): 39 row = self.layout.row(align=True) 40 row.label(text="ホイール:太さ変更") 41 row.label(text="ホイールクリック:ランダム強度変更") 42 row.label(text="ZXキー:高さ変更") 43 bpy.types.VIEW3D_HT_header.draw = header_draw 44 45 # if context.active_object: 46 # if context.active_object.mode != 'OBJECT': 47 # self.report(type={'ERROR'}, message="オブジェクトモードで実行してください") 48 # return {'CANCELLED'} 49 50 cursor_loc = compat.get_cursor_loc(context) 51 self.end_location = bpy_extras.view3d_utils.region_2d_to_location_3d(context.region, context.region_data, (event.mouse_region_x, event.mouse_region_y), cursor_loc) 52 53 curve = context.blend_data.curves.new("Hair Bunch", 'CURVE') 54 ob = context.blend_data.objects.new("Hair Bunch", curve) 55 compat.link(context.scene, ob) 56 compat.set_active(context, ob) 57 compat.set_select(ob, True) 58 59 curve.dimensions = '3D' 60 curve.resolution_u = 5 61 62 spline = curve.splines.new('NURBS') 63 64 spline.points.add(3) 65 spline.points[0].radius = 0.0 66 spline.points[-1].radius = 0.0 67 spline.use_endpoint_u = True 68 spline.order_u = 4 69 spline.resolution_u = 5 70 71 self.set_spline(spline, context) 72 73 self.object = ob 74 self.curve = curve 75 self.spline = spline 76 77 bevel_curve = context.blend_data.curves.new("Hair Bunch Bevel", 'CURVE') 78 bevel_ob = context.blend_data.objects.new("Hair Bunch Bevel", bevel_curve) 79 compat.link(context.scene, bevel_ob) 80 compat.set_select(bevel_ob, True) 81 curve.bevel_object = bevel_ob 82 83 bevel_ob.parent = ob 84 bevel_ob.parent_type = 'VERTEX' 85 bevel_ob.parent_vertices = (3, 3, 3) 86 87 bevel_curve.dimensions = '2D' 88 bevel_curve.fill_mode = 'NONE' 89 bevel_curve.resolution_u = 2 90 91 spline = bevel_curve.splines.new('NURBS') 92 spline.points.add(7) 93 spline.use_cyclic_u = True 94 spline.order_u = 4 95 spline.resolution_u = 2 96 97 self.bevel_object = bevel_ob 98 self.bevel_curve = bevel_curve 99 self.bevel_spline = spline 100 101 self.set_bevel_spline(spline) 102 103 context.window_manager.modal_handler_add(self) 104 return {'RUNNING_MODAL'}
def
modal(self, context, event):
106 def modal(self, context, event): 107 108 if event.type == 'MOUSEMOVE': 109 cursor_loc = compat.get_cursor_loc(context) 110 self.end_location = bpy_extras.view3d_utils.region_2d_to_location_3d(context.region, context.region_data, (event.mouse_region_x, event.mouse_region_y), cursor_loc) 111 self.execute(context) 112 113 elif event.type == 'WHEELUPMOUSE' and event.value == 'PRESS': 114 self.radius += 0.05 115 self.set_bevel_spline(self.bevel_spline) 116 self.object.update_tag({'OBJECT', 'DATA'}) 117 elif event.type == 'WHEELDOWNMOUSE' and event.value == 'PRESS': 118 self.radius -= 0.05 119 self.set_bevel_spline(self.bevel_spline) 120 self.object.update_tag({'OBJECT', 'DATA'}) 121 122 elif event.type == 'MIDDLEMOUSE' and event.value == 'PRESS': 123 if 0.9 < self.random_multi: 124 self.random_multi = 0.0 125 elif 0.4 < self.random_multi: 126 self.random_multi = 1.0 127 else: 128 self.random_multi = 0.5 129 self.set_bevel_spline(self.bevel_spline) 130 131 elif event.type == 'Z' and event.value == 'PRESS': 132 self.z_plus += 0.1 133 self.execute(context) 134 elif event.type == 'X' and event.value == 'PRESS': 135 self.z_plus -= 0.1 136 self.execute(context) 137 138 elif event.type == 'LEFTMOUSE' and event.value == 'PRESS': 139 bpy.types.VIEW3D_HT_header.draw = self.pre_draw 140 context.area.tag_redraw() 141 return {'FINISHED'} 142 143 elif event.type in {'RIGHTMOUSE', 'ESC'} and event.value == 'PRESS': 144 common.remove_data([self.object, self.bevel_object, self.curve, self.bevel_curve]) 145 bpy.types.VIEW3D_HT_header.draw = self.pre_draw 146 context.area.tag_redraw() 147 return {'CANCELLED'} 148 149 return {'RUNNING_MODAL'}
def
set_bevel_spline(self, spline):
157 def set_bevel_spline(self, spline): 158 r = self.radius 159 vec = mathutils.Vector((0, r, 0)) 160 min_rad = -math.radians(360 / len(spline.points)) 161 for index, point in enumerate(spline.points): 162 eul = mathutils.Euler((0, 0, min_rad * index), 'XYZ') 163 now_vec = vec.copy() 164 now_vec.rotate(eul) 165 now_vec = self.get_random_point(now_vec) 166 point.co = list(now_vec[:]) + [1]
def
set_spline(self, spline, context):
168 def set_spline(self, spline, context): 169 cursor_loc = compat.get_cursor_loc(context) 170 diff_co = self.end_location - cursor_loc 171 172 plus_co = diff_co * 0.333333 173 plus_co.z = -plus_co.z + self.z_plus 174 175 point1 = diff_co * 0.333333 176 point1 += plus_co * 1 177 point1 += cursor_loc 178 179 point2 = diff_co * 0.666666 180 point2 += plus_co * 1 181 point2 += cursor_loc 182 183 spline.points[0].co = list(cursor_loc[:]) + [1] 184 spline.points[1].co = list(point1[:]) + [1] 185 spline.points[2].co = list(point2[:]) + [1] 186 spline.points[-1].co = list(self.end_location[:]) + [1]
Inherited Members
- bpy_types.Operator
- as_keywords
- poll_message_set
- builtins.bpy_struct
- keys
- values
- items
- get
- pop
- as_pointer
- keyframe_insert
- keyframe_delete
- driver_add
- driver_remove
- is_property_set
- property_unset
- is_property_readonly
- is_property_overridable_library
- property_overridable_library_set
- path_resolve
- path_from_id
- type_recast
- bl_rna_get_subclass_py
- bl_rna_get_subclass
- id_properties_ensure
- id_properties_clear
- id_properties_ui
- id_data