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_add(bpy_types.Operator):
 19@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'}
bl_idname = 'curve.hair_bunch_add'
bl_label = '髪の房を追加'
bl_description = 'アニメ調の髪の房を追加します'
bl_options = {'REGISTER', 'UNDO'}
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'}>
@classmethod
def poll(cls, context):
30    @classmethod
31    def poll(cls, context):
32        return context.mode == 'OBJECT'
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 get_random_point(self, co):
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
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]
def execute(self, context):
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'}
bl_rna = <bpy_struct, Struct("CURVE_OT_hair_bunch_add")>
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_hidden
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