Sidebar (Nパネル)", "description": "初期半径10。6種の円のサイズ・太さ、ペン線の太さ調整機能を追加", "category": "Object", } import bpy import math import mathutils import webbrowser # ========================================================================= # 【基本設定】 # ========================================================================= TAB_NAME = "アルファ地球儀" PREFIX_NAME = "alpha_globe" # --- リンク設定 --- ADDON_LINKS = [ { "label": "地球儀 緯度経度 xyz", "url": "https://note.com/zionadmillion/n/na0b25ce45488", "icon": "URL" }, { "label": "最新 posfie", "url": "https://posfie.com/@timekagura/t/zionad2022?sort=0", "icon": "URL" } ] # --- カラー設定 --- INIT_C0_COLOR = (0.60, 0.64, 0.71) # 中心点 INIT_LON_COLOR = (0.89, 0.47, 0.35) # ロンドン点 INIT_EQ_COLOR = (0.36, "> Sidebar (Nパネル)", "description": "初期半径10。6種の円のサイズ・太さ、ペン線の太さ調整機能を追加", "category": "Object", } import bpy import math import mathutils import webbrowser # ========================================================================= # 【基本設定】 # ========================================================================= TAB_NAME = "アルファ地球儀" PREFIX_NAME = "alpha_globe" # --- リンク設定 --- ADDON_LINKS = [ { "label": "地球儀 緯度経度 xyz", "url": "https://note.com/zionadmillion/n/na0b25ce45488", "icon": "URL" }, { "label": "最新 posfie", "url": "https://posfie.com/@timekagura/t/zionad2022?sort=0", "icon": "URL" } ] # --- カラー設定 --- INIT_C0_COLOR = (0.60, 0.64, 0.71) # 中心点 INIT_LON_COLOR = (0.89, 0.47, 0.35) # ロンドン点 INIT_EQ_COLOR = (0.36, "> Sidebar (Nパネル)", "description": "初期半径10。6種の円のサイズ・太さ、ペン線の太さ調整機能を追加", "category": "Object", } import bpy import math import mathutils import webbrowser # ========================================================================= # 【基本設定】 # ========================================================================= TAB_NAME = "アルファ地球儀" PREFIX_NAME = "alpha_globe" # --- リンク設定 --- ADDON_LINKS = [ { "label": "地球儀 緯度経度 xyz", "url": "https://note.com/zionadmillion/n/na0b25ce45488", "icon": "URL" }, { "label": "最新 posfie", "url": "https://posfie.com/@timekagura/t/zionad2022?sort=0", "icon": "URL" } ] # --- カラー設定 --- INIT_C0_COLOR = (0.60, 0.64, 0.71) # 中心点 INIT_LON_COLOR = (0.89, 0.47, 0.35) # ロンドン点 INIT_EQ_COLOR = (0.36, ">
bl_info = {
"name": "Alpha Globe Generator Pro (Blender 5 Optimized)",
"author": "Your Name",
"version": (1, 2),
"blender": (4, 0, 0), # Blender 4.0/5.x対応
"location": "View3D > Sidebar (Nパネル)",
"description": "初期半径10。6種の円のサイズ・太さ、ペン線の太さ調整機能を追加",
"category": "Object",
}
import bpy
import math
import mathutils
import webbrowser
# =========================================================================
# 【基本設定】
# =========================================================================
TAB_NAME = "アルファ地球儀"
PREFIX_NAME = "alpha_globe"
# --- リンク設定 ---
ADDON_LINKS = [
{
"label": "地球儀 緯度経度 xyz",
"url": "<https://note.com/zionadmillion/n/na0b25ce45488>",
"icon": "URL"
},
{
"label": "最新 posfie",
"url": "<https://posfie.com/@timekagura/t/zionad2022?sort=0>",
"icon": "URL"
}
]
# --- カラー設定 ---
INIT_C0_COLOR = (0.60, 0.64, 0.71) # 中心点
INIT_LON_COLOR = (0.89, 0.47, 0.35) # ロンドン点
INIT_EQ_COLOR = (0.36, 0.79, 0.65) # 赤道点
INIT_TRI_COLOR = (0.53, 0.53, 0.50) # ペン線(三角形)
# 6種の円の初期色
INIT_LONG_X_C = (1.0, 0.0, 0.0)
INIT_LONG_Y_C = (0.0, 1.0, 0.0)
INIT_LONG_Z_C = (0.0, 0.7, 1.0)
INIT_LAT_X_C = (1.0, 0.0, 1.0)
INIT_LAT_Y_C = (0.9, 0.5, 1.0)
INIT_LAT_Z_C = (0.9, 0.8, 1.0)
# =========================================================================
# 【プロパティ定義】
# =========================================================================
class AlphaGlobeProperties(bpy.types.PropertyGroup):
# トランスフォーム
loc_x: bpy.props.FloatProperty(name="位置 X", default=0.0)
loc_y: bpy.props.FloatProperty(name="位置 Y", default=0.0)
loc_z: bpy.props.FloatProperty(name="位置 Z", default=0.0)
rot_x: bpy.props.FloatProperty(name="X軸", default=0.0, subtype='ANGLE')
rot_y: bpy.props.FloatProperty(name="Y軸", default=0.0, subtype='ANGLE')
rot_z: bpy.props.FloatProperty(name="Z軸", default=0.0, subtype='ANGLE')
# サイズとアニメーション (初期半径10ベース)
radius: bpy.props.FloatProperty(name="基準半径 (R)", default=10.0, min=0.1)
frames_per_rev: bpy.props.IntProperty(name="1周のフレーム数", default=240, min=1)
point_size: bpy.props.FloatProperty(name="点のサイズ", default=0.35, min=0.01)
# 【太さの設定群】
main_line_thick: bpy.props.FloatProperty(name="メインの赤道・ロンドン緯線の太さ", default=0.08, min=0.001)
pen_line_thick: bpy.props.FloatProperty(name="ペン線の太さ (三角形)", default=0.08, min=0.001) # 追加要件: ペン線の太さ
# -------------------------------------------------------------
# 【6種類の円 (経度XYZ / 緯度XYZ) の 設定: サイズ(数)と太さ】
# -------------------------------------------------------------
long_x_use: bpy.props.BoolProperty(default=True)
long_x_num: bpy.props.IntProperty(default=18, min=1)
long_x_thick: bpy.props.FloatProperty(default=0.05, min=0.001)
long_x_color: bpy.props.FloatVectorProperty(subtype='COLOR', default=INIT_LONG_X_C, min=0.0, max=1.0)
long_y_use: bpy.props.BoolProperty(default=True)
long_y_num: bpy.props.IntProperty(default=18, min=1)
long_y_thick: bpy.props.FloatProperty(default=0.05, min=0.001)
long_y_color: bpy.props.FloatVectorProperty(subtype='COLOR', default=INIT_LONG_Y_C, min=0.0, max=1.0)
long_z_use: bpy.props.BoolProperty(default=True)
long_z_num: bpy.props.IntProperty(default=18, min=1)
long_z_thick: bpy.props.FloatProperty(default=0.05, min=0.001)
long_z_color: bpy.props.FloatVectorProperty(subtype='COLOR', default=INIT_LONG_Z_C, min=0.0, max=1.0)
lat_x_use: bpy.props.BoolProperty(default=True)
lat_x_num: bpy.props.IntProperty(default=17, min=1)
lat_x_thick: bpy.props.FloatProperty(default=0.05, min=0.001)
lat_x_color: bpy.props.FloatVectorProperty(subtype='COLOR', default=INIT_LAT_X_C, min=0.0, max=1.0)
lat_y_use: bpy.props.BoolProperty(default=True)
lat_y_num: bpy.props.IntProperty(default=17, min=1)
lat_y_thick: bpy.props.FloatProperty(default=0.05, min=0.001)
lat_y_color: bpy.props.FloatVectorProperty(subtype='COLOR', default=INIT_LAT_Y_C, min=0.0, max=1.0)
lat_z_use: bpy.props.BoolProperty(default=True)
lat_z_num: bpy.props.IntProperty(default=17, min=1)
lat_z_thick: bpy.props.FloatProperty(default=0.05, min=0.001)
lat_z_color: bpy.props.FloatVectorProperty(subtype='COLOR', default=INIT_LAT_Z_C, min=0.0, max=1.0)
# アニメーション用基本カラー
c0_color: bpy.props.FloatVectorProperty(name="C0色", subtype='COLOR', default=INIT_C0_COLOR, min=0.0, max=1.0)
eq_color: bpy.props.FloatVectorProperty(name="赤道色", subtype='COLOR', default=INIT_EQ_COLOR, min=0.0, max=1.0)
lon_color: bpy.props.FloatVectorProperty(name="ロンドン色", subtype='COLOR', default=INIT_LON_COLOR, min=0.0, max=1.0)
tri_color: bpy.props.FloatVectorProperty(name="線分色", subtype='COLOR', default=INIT_TRI_COLOR, min=0.0, max=1.0)
# =========================================================================
# 【オペレーター:生成処理】
# =========================================================================
class ALPHA_OT_create_globe(bpy.types.Operator):
bl_idname = f"mesh.{PREFIX_NAME.lower()}_create"
bl_label = "アルファ地球儀を生成"
bl_options = {'REGISTER', 'UNDO'}
def execute(self, context):
props = getattr(context.scene, f"{PREFIX_NAME.lower()}_props")
# コレクション作成
set_count = 1
while bpy.data.collections.get(f"アルファ地球儀_{set_count}"):
set_count += 1
coll = bpy.data.collections.new(f"アルファ地球儀_{set_count}")
context.scene.collection.children.link(coll)
def move_to_coll(obj):
for c in obj.users_collection: c.objects.unlink(obj)
coll.objects.link(obj)
def create_mat(name, color):
mat = bpy.data.materials.new(name=name)
mat.use_nodes = True
bsdf = mat.node_tree.nodes.get("Principled BSDF")
if bsdf: bsdf.inputs["Base Color"].default_value = (color[0], color[1], color[2], 1.0)
return mat
# マテリアル
mat_c0 = create_mat(f"{PREFIX_NAME}_C0_{set_count}", props.c0_color)
mat_eq = create_mat(f"{PREFIX_NAME}_EQ_{set_count}", props.eq_color)
mat_lon = create_mat(f"{PREFIX_NAME}_LON_{set_count}", props.lon_color)
mat_tri = create_mat(f"{PREFIX_NAME}_TRI_{set_count}", props.tri_color)
mat_long_x = create_mat(f"{PREFIX_NAME}_LONG_X_{set_count}", props.long_x_color)
mat_long_y = create_mat(f"{PREFIX_NAME}_LONG_Y_{set_count}", props.long_y_color)
mat_long_z = create_mat(f"{PREFIX_NAME}_LONG_Z_{set_count}", props.long_z_color)
mat_lat_x = create_mat(f"{PREFIX_NAME}_LAT_X_{set_count}", props.lat_x_color)
mat_lat_y = create_mat(f"{PREFIX_NAME}_LAT_Y_{set_count}", props.lat_y_color)
mat_lat_z = create_mat(f"{PREFIX_NAME}_LAT_Z_{set_count}", props.lat_z_color)
R = props.radius
t = props.main_line_thick
p = props.point_size
pen_t = props.pen_line_thick
# Base Empty
bpy.ops.object.empty_add(type='ARROWS', radius=R*1.2, location=(0,0,0))
base_empty = context.active_object
base_empty.name = f"AlphaGlobe_Base_{set_count}"
base_empty["globe_prefix"] = PREFIX_NAME
base_empty["alpha_part"] = "BASE"
move_to_coll(base_empty)
# ----------------------------------------------------------------
# ★ 6種類の円の生成関数
def generate_torus_ring(part_type, count, thick, mat):
if part_type.startswith('LONG'):
for i in range(count):
angle = i * (math.pi / count)
if part_type == 'LONG_X': rot = (angle, 0.0, 0.0)
elif part_type == 'LONG_Y': rot = (0.0, angle, 0.0)
else: rot = (math.pi / 2.0, 0.0, angle)
bpy.ops.mesh.primitive_torus_add(major_radius=R, minor_radius=thick, major_segments=64, minor_segments=8, location=(0,0,0), rotation=rot)
tr = context.active_object
tr.name = f"{part_type}_{i+1}_{set_count}"
tr.data.materials.append(mat)
tr.parent = base_empty
tr["globe_prefix"] = PREFIX_NAME
tr["alpha_part"] = part_type
move_to_coll(tr)
elif part_type.startswith('LAT'):
step = math.pi / (count + 1)
for i in range(1, count + 1):
theta = -math.pi / 2.0 + i * step
r_val = max(0.001, R * math.cos(theta))
z_val = R * math.sin(theta)
if part_type == 'LAT_X': loc, rot = (z_val, 0, 0), (0, math.pi / 2.0, 0)
elif part_type == 'LAT_Y': loc, rot = (0, z_val, 0), (math.pi / 2.0, 0, 0)
else: loc, rot = (0, 0, z_val), (0, 0, 0)
bpy.ops.mesh.primitive_torus_add(major_radius=r_val, minor_radius=thick, major_segments=64, minor_segments=8, location=loc, rotation=rot)
tr = context.active_object
tr.name = f"{part_type}_{i}_{set_count}"
tr.data.materials.append(mat)
tr.parent = base_empty
tr["globe_prefix"] = PREFIX_NAME
tr["alpha_part"] = part_type
move_to_coll(tr)
# 6種類の円を一括処理
config = [
('LONG_X', props.long_x_use, props.long_x_num, props.long_x_thick, mat_long_x),
('LONG_Y', props.long_y_use, props.long_y_num, props.long_y_thick, mat_long_y),
('LONG_Z', props.long_z_use, props.long_z_num, props.long_z_thick, mat_long_z),
('LAT_X', props.lat_x_use, props.lat_x_num, props.lat_x_thick, mat_lat_x),
('LAT_Y', props.lat_y_use, props.lat_y_num, props.lat_y_thick, mat_lat_y),
('LAT_Z', props.lat_z_use, props.lat_z_num, props.lat_z_thick, mat_lat_z)
]
for part, use, num, thick, mat in config:
if use: generate_torus_ring(part, num, thick, mat)
# ----------------------------------------------------------------
# C0 中心点
bpy.ops.mesh.primitive_uv_sphere_add(radius=p * 1.5, segments=32, ring_count=16, location=(0,0,0))
c0 = context.active_object
c0.name = f"C0_Center_{set_count}"
c0.data.materials.append(mat_c0)
c0.parent = base_empty
c0["globe_prefix"], c0["alpha_part"] = PREFIX_NAME, "C0"
move_to_coll(c0)
# メイン緯線(赤道・ロンドン)
lat_lon_rad, lon_eq_rad = math.radians(51.5), math.radians(-78.5)
r_lon, z_lon = R * math.cos(lat_lon_rad), R * math.sin(lat_lon_rad)
bpy.ops.mesh.primitive_torus_add(major_radius=R, minor_radius=t, major_segments=64, minor_segments=16, location=(0,0,0))
eq_line = context.active_object
eq_line.name, eq_line["globe_prefix"], eq_line["alpha_part"] = f"Equator_Line_{set_count}", PREFIX_NAME, "EQ"
eq_line.data.materials.append(mat_eq)
eq_line.parent = base_empty
move_to_coll(eq_line)
bpy.ops.mesh.primitive_torus_add(major_radius=r_lon, minor_radius=t, major_segments=64, minor_segments=16, location=(0,0,z_lon))
lon_line = context.active_object
lon_line.name, lon_line["globe_prefix"], lon_line["alpha_part"] = f"London_Line_{set_count}", PREFIX_NAME, "LON"
lon_line.data.materials.append(mat_lon)
lon_line.parent = base_empty
move_to_coll(lon_line)
# アニメーションローター
bpy.ops.object.empty_add(type='PLAIN_AXES', radius=R*1.5, location=(0,0,0))
rotor = context.active_object
rotor.name, rotor.parent, rotor["globe_prefix"], rotor["alpha_part"] = f"Rotor_Anim_{set_count}", base_empty, PREFIX_NAME, "ROTOR"
move_to_coll(rotor)
driver = rotor.driver_add('rotation_euler', 2).driver
driver.type, driver.expression = 'SCRIPTED', f"(frame / {props.frames_per_rev}) * {2 * math.pi}"
# 動く点 (赤道・ロンドン)
x_eq, y_eq = R * math.cos(lon_eq_rad), R * math.sin(lon_eq_rad)
bpy.ops.mesh.primitive_uv_sphere_add(radius=p, segments=32, ring_count=16, location=(x_eq, y_eq, 0))
eq_pt = context.active_object
eq_pt.name, eq_pt.parent, eq_pt["globe_prefix"], eq_pt["alpha_part"] = f"Equator_Point_{set_count}", rotor, PREFIX_NAME, "EQ"
eq_pt.data.materials.append(mat_eq)
move_to_coll(eq_pt)
bpy.ops.mesh.primitive_uv_sphere_add(radius=p, segments=32, ring_count=16, location=(r_lon, 0, z_lon))
lon_pt = context.active_object
lon_pt.name, lon_pt.parent, lon_pt["globe_prefix"], lon_pt["alpha_part"] = f"London_Point_{set_count}", rotor, PREFIX_NAME, "LON"
lon_pt.data.materials.append(mat_lon)
move_to_coll(lon_pt)
# ★ ペン線 (三角形の辺) -> pen_line_thick を適用
mesh = bpy.data.meshes.new(f"TriangleMesh_{set_count}")
mesh.from_pydata([(0, 0, 0), (r_lon, 0, z_lon), (x_eq, y_eq, 0)], [(0,1), (0,2), (1,2)], [])
tri_obj = bpy.data.objects.new(f"Triangle_Edges_{set_count}", mesh)
tri_obj.data.materials.append(mat_tri)
tri_obj.parent, tri_obj["globe_prefix"], tri_obj["alpha_part"] = rotor, PREFIX_NAME, "TRIANGLE"
coll.objects.link(tri_obj)
mod = tri_obj.modifiers.new(name="Wireframe", type='WIREFRAME')
mod.thickness = pen_t # ペン線の太さをここで適用
# トランスフォーム適用
rot_mat = mathutils.Euler((props.rot_x, props.rot_y, props.rot_z), 'XYZ').to_matrix().to_4x4()
loc_mat = mathutils.Matrix.Translation((props.loc_x, props.loc_y, props.loc_z))
base_empty.matrix_world = loc_mat @ rot_mat @ base_empty.matrix_world
context.view_layer.objects.active = base_empty
base_empty.select_set(True)
return {'FINISHED'}
# =========================================================================
# 【各種オペレーターとUIパネル】
# =========================================================================
class ALPHA_OT_toggle_visibility(bpy.types.Operator):
bl_idname = f"object.{PREFIX_NAME.lower()}_toggle_vis"
bl_label = "表示切替"
part_type: bpy.props.StringProperty()
def execute(self, context):
objs = [o for o in context.scene.objects if o.get("globe_prefix") == PREFIX_NAME and o.get("alpha_part") == self.part_type]
if not objs: return {'CANCELLED'}
state = not objs[0].hide_viewport
for o in objs: o.hide_viewport = state
return {'FINISHED'}
class ALPHA_PT_main_panel(bpy.types.Panel):
bl_idname = f"{PREFIX_NAME.upper()}_PT_main_panel"
bl_label = "アルファ地球儀 (生成・基本)"
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
bl_category = TAB_NAME
def draw(self, context):
layout = self.layout
props = getattr(context.scene, f"{PREFIX_NAME.lower()}_props")
box_gen = layout.box()
box_gen.scale_y = 1.3
box_gen.operator(f"mesh.{PREFIX_NAME.lower()}_create", text="地球儀とアニメーションを生成", icon='PLAY')
box_b = layout.box()
box_b.label(text="基本設定", icon='PREFERENCES')
col = box_b.column(align=True)
col.prop(props, "radius")
col.prop(props, "frames_per_rev")
col.prop(props, "point_size")
box_t = layout.box()
box_t.label(text="太さの調整", icon='IPO_CONSTANT')
col_t = box_t.column(align=True)
col_t.prop(props, "main_line_thick", text="赤道・ロンドン緯線の太さ")
col_t.prop(props, "pen_line_thick", text="ペン線の太さ (点線相当)")
box_p = layout.box()
box_p.label(text="アニメーションパーツ表示", icon='ANIM')
for title, icon, p_col, p_type in [("C0 (中心点)", 'DOT', "c0_color", 'C0'),
("赤道 (緯線・点)", 'MESH_TORUS', "eq_color", 'EQ'),
("ロンドン (緯線・点)", 'MESH_TORUS', "lon_color", 'LON'),
("ペン線 (三角形)", 'MESH_DATA', "tri_color", 'TRIANGLE')]:
r = box_p.row(align=True)
r.prop(props, p_col, text="")
r.operator(f"object.{PREFIX_NAME.lower()}_toggle_vis", text=title, icon=icon).part_type = p_type
class ALPHA_PT_circles_panel(bpy.types.Panel):
bl_idname = f"{PREFIX_NAME.upper()}_PT_circles_panel"
bl_label = "6種類の円の設定 (数と太さ)"
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
bl_category = TAB_NAME
def draw(self, context):
props = getattr(context.scene, f"{PREFIX_NAME.lower()}_props")
def draw_ring(parent, title, prefix):
c = parent.column(align=True)
c.label(text=title)
r = c.row(align=True)
r.prop(props, f"{prefix}_use", text="")
r.prop(props, f"{prefix}_color", text="")
c.prop(props, f"{prefix}_num", text="数(Size)")
c.prop(props, f"{prefix}_thick", text="太さ")
c.operator(f"object.{PREFIX_NAME.lower()}_toggle_vis", text="表示切替").part_type = prefix.upper()
b1 = self.layout.box()
b1.label(text="経度 (縦の円)", icon='MESH_TORUS')
r1 = b1.row(align=True)
draw_ring(r1, "経度 X", "long_x")
draw_ring(r1, "経度 Y", "long_y")
draw_ring(r1, "経度 Z", "long_z")
b2 = self.layout.box()
b2.label(text="緯度 (横の円)", icon='MESH_TORUS')
r2 = b2.row(align=True)
draw_ring(r2, "緯度 X", "lat_x")
draw_ring(r2, "緯度 Y", "lat_y")
draw_ring(r2, "緯度 Z", "lat_z")
class ALPHA_PT_transform_panel(bpy.types.Panel):
bl_idname = f"{PREFIX_NAME.upper()}_PT_transform_panel"
bl_label = "全体の位置・回転"
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
bl_category = TAB_NAME
bl_options = {'DEFAULT_CLOSED'}
def draw(self, context):
props = getattr(context.scene, f"{PREFIX_NAME.lower()}_props")
c1, c2 = self.layout.column(align=True), self.layout.column(align=True)
c1.label(text="位置:"); c1.prop(props, "loc_x"); c1.prop(props, "loc_y"); c1.prop(props, "loc_z")
c2.label(text="回転:"); c2.prop(props, "rot_x"); c2.prop(props, "rot_y"); c2.prop(props, "rot_z")
class ALPHA_OT_open_url(bpy.types.Operator):
bl_idname = f"wm.{PREFIX_NAME.lower()}_open_url"
bl_label = "URL"
url: bpy.props.StringProperty()
def execute(self, context):
webbrowser.open(self.url)
return {'FINISHED'}
class ALPHA_OT_remove_addon(bpy.types.Operator):
bl_idname = f"wm.{PREFIX_NAME.lower()}_remove_addon"
bl_label = "アドオン削除"
def execute(self, context):
unregister()
return {'FINISHED'}
class ALPHA_PT_footer_panel(bpy.types.Panel):
bl_idname = f"{PREFIX_NAME.upper()}_PT_footer_panel"
bl_label = "リンク / 管理"
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
bl_category = TAB_NAME
bl_order = 100
bl_options = {'DEFAULT_CLOSED'}
def draw(self, context):
layout = self.layout
for link in ADDON_LINKS:
layout.operator(f"wm.{PREFIX_NAME.lower()}_open_url", text=link["label"], icon='URL').url = link["url"]
layout.separator()
layout.operator(f"wm.{PREFIX_NAME.lower()}_remove_addon", text="アドオンを無効化して閉じる", icon='CANCEL')
classes = [
AlphaGlobeProperties, ALPHA_OT_create_globe, ALPHA_OT_toggle_visibility,
ALPHA_OT_open_url, ALPHA_OT_remove_addon,
ALPHA_PT_main_panel, ALPHA_PT_circles_panel, ALPHA_PT_transform_panel, ALPHA_PT_footer_panel
]
def register():
for c in classes: bpy.utils.register_class(c)
setattr(bpy.types.Scene, f"{PREFIX_NAME.lower()}_props", bpy.props.PointerProperty(type=AlphaGlobeProperties))
def unregister():
if hasattr(bpy.types.Scene, f"{PREFIX_NAME.lower()}_props"): delattr(bpy.types.Scene, f"{PREFIX_NAME.lower()}_props")
for c in reversed(classes):
try: bpy.utils.unregister_class(c)
except: pass
if __name__ == "__main__":
try: unregister()
except: pass
register()