https://posfie.com/@timekagura?sort=0&page=1

# 2026-02-22 02:30:00 Session Template
# Blender 5.0+ Exclusive | International English | V30 - Circle Solidify
UNIQUE_SCRIPT_ID = "YZ_RAYS_STABLE_TEMPLATE_2026_02_22_V30"
SCRIPT_VERSION = 30
bl_info = {
"name": "YZ Plane 12 Rays Generator (V30)",
"author": "zionadchat Gemini",
"version": (1, 30),
"blender": (5, 0, 0),
"location": "View3D > Sidebar > YZ_Rays",
"description": "Added Face Solidify (Thickness) to the circular wave front.",
"category": "Object",
}
import bpy
import bmesh
import math
import webbrowser
from mathutils import Vector, Matrix
from datetime import datetime
# ==============================================================================
# DYNAMIC DEFAULTS (Saved State)
# ==============================================================================
# <BEGIN_DICT>
CURRENT_DEFAULTS = {
"show_circle": True,
"show_train_rays": True,
"show_cone_rays": True,
"ray_color": (0.8000, 0.8000, 0.1000),
"cone_color": (0.8000, 0.2000, 0.1000),
"circle_color": (0.1000, 0.5000, 0.8000),
"speed_v": 0.5000,
"time_t": 10.0000,
"circle_depth": 0.1000,
"circle_solid": 0.0500,
"ray_thickness": 0.0500,
"cone_thickness": 0.0350,
}
# <END_DICT>
TAB_NAME = "YZ_Rays"
COLLECTION_NAME = "YZ_Rays_Output"
TAG_C, TAG_T, TAG_O = "tag_yz_c", "tag_yz_t", "tag_yz_o"
ADDON_LINKS = (
{"label": "Theory Background", "url": "<https://www.notion.so/>"},
{"label": "Blender Guide", "url": "<https://www.notion.so/>"},
)
# ------------------------------------------------------------------------
# Material Helper
# ------------------------------------------------------------------------
def get_mat(name, color_rgb, alpha=1.0):
mat_name = f"Mat_{name}_V30"
mat = bpy.data.materials.get(mat_name) or bpy.data.materials.new(name=mat_name)
mat.use_nodes = True
if hasattr(mat, "blend_method"): mat.blend_method = 'BLEND'
if hasattr(mat, "eevee"): mat.eevee.shadow_method = 'NONE'
nodes = mat.node_tree.nodes
bsdf = nodes.get("Principled BSDF") or nodes.new('ShaderNodeBsdfPrincipled')
bsdf.inputs["Base Color"].default_value = (*color_rgb, 1.0)
bsdf.inputs["Alpha"].default_value = alpha
bsdf.inputs["Emission Color"].default_value = (*color_rgb, 1.0)
bsdf.inputs["Emission Strength"].default_value = 1.0
return mat
# ------------------------------------------------------------------------
# Geometry Engine
# ------------------------------------------------------------------------
def create_arrow_bm(bm, start, end, thick):
vec = end - start
length = vec.length
if length < 0.001: return
s_len, h_len = length * 0.9, length * 0.1
s = bmesh.ops.create_cone(bm, cap_ends=True, segments=12, radius1=thick, radius2=thick, depth=s_len)
bmesh.ops.translate(bm, verts=s['verts'], vec=Vector((0, 0, s_len/2)))
h = bmesh.ops.create_cone(bm, cap_ends=True, segments=12, radius1=thick*2, radius2=0, depth=h_len)
bmesh.ops.translate(bm, verts=h['verts'], vec=Vector((0, 0, s_len + h_len/2)))
rot = Vector((0, 0, 1)).rotation_difference(vec.normalized())
bmesh.ops.rotate(bm, verts=list(s['verts']) + list(h['verts']), cent=(0,0,0), matrix=rot.to_matrix().to_4x4())
bmesh.ops.translate(bm, verts=list(s['verts']) + list(h['verts']), vec=start)
def draw_rays_core(context):
p = context.scene.yz_rays_props
col = bpy.data.collections.get(COLLECTION_NAME) or bpy.data.collections.new(COLLECTION_NAME)
if col.name not in context.scene.collection.children: context.scene.collection.children.link(col)
def sync_obj(name, tag):
obj = next((o for o in col.objects if o.get(tag)), None)
if obj: obj.data.clear_geometry(); return obj, obj.data
mesh = bpy.data.meshes.new(name)
obj = bpy.data.objects.new(name, mesh); obj[tag] = True; col.objects.link(obj)
return obj, mesh
c, t, v = 1.0, p.time_t, p.speed_v
R_circle = c * t
R_rays = math.sqrt(max(0, (c*t)**2 - (v*t)**2))
emission_origin = Vector((-v * t, 0, 0))
# 1. Circle with Solidify (Tube effect)
o_c, m_c = sync_obj("YZ_Circle", TAG_C)
o_c.hide_viewport = not p.show_circle
bm = bmesh.new()
res_c = bmesh.ops.create_cone(bm, cap_ends=False, segments=96, radius1=R_circle, radius2=R_circle, depth=p.circle_depth)
# Apply Face Solidify
circle_faces = [f for f in res_c.get('geom', res_c.get('faces', [])) if isinstance(f, bmesh.types.BMFace)]
if not circle_faces: circle_faces = bm.faces[:]
if p.circle_solid > 0:
bmesh.ops.solidify(bm, geom=circle_faces, thickness=p.circle_solid)
bmesh.ops.rotate(bm, verts=bm.verts, cent=(0,0,0), matrix=Matrix.Rotation(math.radians(90), 4, 'Y'))
bm.to_mesh(m_c); bm.free()
o_c.data.materials.clear(); o_c.data.materials.append(get_mat("Circle", p.circle_color, 0.5))
# 2. Train Rays
o_t, m_t = sync_obj("YZ_Train_Rays", TAG_T)
o_t.hide_viewport = not p.show_train_rays
bm = bmesh.new()
if R_rays > 0.001:
for i in range(12):
ang = math.radians(i * 30); tip = Vector((0, R_rays * math.cos(ang), R_rays * math.sin(ang)))
create_arrow_bm(bm, Vector((0,0,0)), tip, p.ray_thickness)
bm.to_mesh(m_t); bm.free()
o_t.data.materials.clear(); o_t.data.materials.append(get_mat("Train", p.ray_color, 1.0))
# 3. Cone Rays
o_o, m_o = sync_obj("YZ_Cone_Rays", TAG_O)
o_o.hide_viewport = not p.show_cone_rays
bm = bmesh.new()
if R_rays > 0.001:
for i in range(12):
ang = math.radians(i * 30); tip = Vector((0, R_rays * math.cos(ang), R_rays * math.sin(ang)))
create_arrow_bm(bm, emission_origin, tip, p.cone_thickness)
bm.to_mesh(m_o); bm.free()
o_o.data.materials.clear(); o_o.data.materials.append(get_mat("Cone", p.cone_color, 0.6))
# ------------------------------------------------------------------------
# UI & Logic
# ------------------------------------------------------------------------
_update_timer = None
def update_view(self, context):
global _update_timer
if _update_timer:
try: bpy.app.timers.unregister(_update_timer)
except: pass
_update_timer = bpy.app.timers.register(lambda: draw_rays_core(bpy.context), first_interval=0.05)
class PG_YZRaysProps(bpy.types.PropertyGroup):
show_circle: bpy.props.BoolProperty(name="Show Circle", default=True, update=update_view)
show_train_rays: bpy.props.BoolProperty(name="Show Train Rays", default=True, update=update_view)
show_cone_rays: bpy.props.BoolProperty(name="Show Cone Rays", default=True, update=update_view)
ray_color: bpy.props.FloatVectorProperty(name="Train Color", subtype='COLOR', size=3, default=CURRENT_DEFAULTS["ray_color"], update=update_view)
cone_color: bpy.props.FloatVectorProperty(name="Cone Color", subtype='COLOR', size=3, default=CURRENT_DEFAULTS["cone_color"], update=update_view)
circle_color: bpy.props.FloatVectorProperty(name="Circle Color", subtype='COLOR', size=3, default=CURRENT_DEFAULTS["circle_color"], update=update_view)
speed_v: bpy.props.FloatProperty(name="Velocity (v/c)", default=0.5, min=0.0, max=0.99, update=update_view)
time_t: bpy.props.FloatProperty(name="Time (t)", default=10.0, min=0.1, update=update_view)
circle_depth: bpy.props.FloatProperty(name="Axial Width (Depth)", default=0.1, min=0.0, max=10.0, update=update_view)
circle_solid: bpy.props.FloatProperty(name="Face Solidify (Thickness)", default=0.05, min=0.0, max=2.0, update=update_view)
ray_thickness: bpy.props.FloatProperty(name="Train Ray Thick", default=0.05, min=0.01, max=1.0, update=update_view)
cone_thickness: bpy.props.FloatProperty(name="Cone Ray Thick", default=0.035, min=0.01, max=1.0, update=update_view)
class OBJECT_OT_DrawYZRays(bpy.types.Operator):
bl_idname = "object.draw_yz_rays"; bl_label = "EXECUTE DRAW"
def execute(self, context): draw_rays_core(context); return {'FINISHED'}
class WM_OT_CopyYZScript(bpy.types.Operator):
bl_idname = "wm.copy_yz_script"; bl_label = "Copy Full Script"
def execute(self, context):
p = context.scene.yz_rays_props; M_START, M_END = "# <BEGIN_DICT>", "# <END_DICT>"
target_text = next((t for t in bpy.data.texts if UNIQUE_SCRIPT_ID in t.as_string()), None)
if not target_text: return {'CANCELLED'}
d_str = "CURRENT_DEFAULTS = {\n"
for k in CURRENT_DEFAULTS.keys():
val = getattr(p, k)
if hasattr(val, "__len__"): d_str += f' "{k}": ({", ".join([f"{v:.4f}" for v in val])}),\n'
elif isinstance(val, bool): d_str += f' "{k}": {val},\n'
else: d_str += f' "{k}": {val:.4f},\n'
d_str += "}\n"
code = target_text.as_string()
try:
res = code.split(M_START)[0] + M_START + "\n" + d_str + M_END + code.split(M_END)[1]
context.window_manager.clipboard = f"# {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} Session Template\n" + '\n'.join(res.split('\n')[1:])
self.report({'INFO'}, "Copied.")
except: pass
return {'FINISHED'}
class WM_OT_OpenRaysUrl(bpy.types.Operator):
bl_idname = "wm.open_rays_url"; bl_label = "Open URL"; url: bpy.props.StringProperty()
def execute(self, context): webbrowser.open(self.url); return {'FINISHED'}
class WM_OT_RemoveYZAddon(bpy.types.Operator):
bl_idname = "wm.remove_yz_addon"; bl_label = "Remove Addon"
def execute(self, context): unregister(); return {'FINISHED'}
class VIEW3D_PT_YZRays(bpy.types.Panel):
bl_label = "YZ Plane Rays (V30)"; bl_space_type = 'VIEW_3D'; bl_region_type = 'UI'; bl_category = TAB_NAME
def draw(self, context):
layout = self.layout; p = context.scene.yz_rays_props
layout.operator("object.draw_yz_rays", icon='PLAY')
layout.operator("wm.copy_yz_script", icon='COPY_ID')
box = layout.box(); box.prop(p, "show_circle"); box.prop(p, "circle_color", text=""); box.prop(p, "circle_depth"); box.prop(p, "circle_solid")
box = layout.box(); box.prop(p, "show_train_rays"); box.prop(p, "ray_color", text=""); box.prop(p, "ray_thickness")
box = layout.box(); box.prop(p, "show_cone_rays"); box.prop(p, "cone_color", text=""); box.prop(p, "cone_thickness")
phys = layout.box(); phys.prop(p, "speed_v"); phys.prop(p, "time_t")
class VIEW3D_PT_YZLinks(bpy.types.Panel):
bl_label = "Theory Links"; bl_space_type = 'VIEW_3D'; bl_region_type = 'UI'; bl_category = TAB_NAME; bl_options = {'DEFAULT_CLOSED'}
def draw(self, context):
for l in ADDON_LINKS: op = self.layout.operator("wm.open_rays_url", text=l["label"], icon='WORLD'); op.url = l["url"]
class VIEW3D_PT_YZSystem(bpy.types.Panel):
bl_label = "System"; bl_space_type = 'VIEW_3D'; bl_region_type = 'UI'; bl_category = TAB_NAME; bl_options = {'DEFAULT_CLOSED'}
def draw(self, context): self.layout.operator("wm.remove_yz_addon", icon='CANCEL')
classes = (PG_YZRaysProps, OBJECT_OT_DrawYZRays, WM_OT_CopyYZScript, WM_OT_OpenRaysUrl, WM_OT_RemoveYZAddon, VIEW3D_PT_YZRays, VIEW3D_PT_YZLinks, VIEW3D_PT_YZSystem)
def register():
for c in classes: bpy.utils.register_class(c)
bpy.types.Scene.yz_rays_props = bpy.props.PointerProperty(type=PG_YZRaysProps)
def unregister():
for c in reversed(classes): bpy.utils.unregister_class(c)
if hasattr(bpy.types.Scene, "yz_rays_props"): del bpy.types.Scene.yz_rays_props
if __name__ == "__main__":
register()

# 2026-02-22 00:04:59 Session Template
# Blender 5.0+ Exclusive | International English | Bug Fix V19
UNIQUE_SCRIPT_ID = "YZ_RAYS_STABLE_TEMPLATE_2026_02_22_V19"
SCRIPT_VERSION = 19
bl_info = {
"name": "YZ Plane 12 Rays Generator (V19)",
"author": "zionadchat Gemini",
"version": (1, 19),
"blender": (5, 0, 0),
"location": "View3D > Sidebar > YZ_Rays",
"description": "Robust relativity visualization with corrected script copy engine.",
"category": "Object",
}
import bpy
import bmesh
import math
import webbrowser
from mathutils import Vector, Matrix
from datetime import datetime
# ==============================================================================
# DYNAMIC DEFAULTS (Saved State)
# ==============================================================================
# <BEGIN_DICT>
CURRENT_DEFAULTS = {
"show_rays": True,
"ray_color": (0.0615, 0.8000, 0.1287),
"ray_alpha": 1.0000,
"circle_color": (0.1000, 0.5000, 0.8000),
"circle_alpha": 1.0000,
"speed_v": 0.8500,
"time_t": 10.0000,
"ray_thickness": 0.1900,
"circle_depth": 3.7200,
"circle_solid": 0.0500,
}
# <END_DICT>
# ==============================================================================
# SYSTEM DEFAULTS (Factory Reset)
# ==============================================================================
SYSTEM_DEFAULTS = {
"speed_v": 0.1,
"time_t": 10.0,
"ray_thickness": 0.05,
"circle_depth": 0.1,
"circle_solid": 0.05,
}
TAB_NAME = "YZ_Rays"
COLLECTION_NAME = "YZ_Rays_Output"
OBJECT_TAG = "yz_rays_tag"
ADDON_LINKS = (
{"label": "Theory Background", "url": "<https://www.notion.so/>"},
{"label": "Blender Guide", "url": "<https://www.notion.so/>"},
)
# ------------------------------------------------------------------------
# Material Setup
# ------------------------------------------------------------------------
def get_transparent_material(part_id, color_rgb, alpha):
mat_name = f"Mat_{part_id}_V19"
mat = bpy.data.materials.get(mat_name) or bpy.data.materials.new(name=mat_name)
mat.use_nodes = True
if hasattr(mat, "blend_method"): mat.blend_method = 'BLEND'
if hasattr(mat, "eevee"): mat.eevee.shadow_method = 'NONE'
nodes = mat.node_tree.nodes
nodes.clear()
node_output = nodes.new(type='ShaderNodeOutputMaterial')
node_principled = nodes.new(type='ShaderNodeBsdfPrincipled')
rgba = (*color_rgb, 1.0)
node_principled.inputs["Base Color"].default_value = rgba
node_principled.inputs["Alpha"].default_value = alpha
node_principled.inputs["Emission Color"].default_value = rgba
node_principled.inputs["Emission Strength"].default_value = 1.0
mat.node_tree.links.new(node_principled.outputs["BSDF"], node_output.inputs["Surface"])
return mat
# ------------------------------------------------------------------------
# Core Drawing
# ------------------------------------------------------------------------
def draw_rays_core(context):
if not context or not context.scene: return
p = context.scene.yz_rays_props
col = bpy.data.collections.get(COLLECTION_NAME) or bpy.data.collections.new(COLLECTION_NAME)
if col.name not in context.scene.collection.children:
context.scene.collection.children.link(col)
for obj in [o for o in col.objects if o.get(OBJECT_TAG)]:
mesh_data = obj.data
bpy.data.objects.remove(obj, do_unlink=True)
if mesh_data and mesh_data.users == 0:
bpy.data.meshes.remove(mesh_data)
if not p.show_rays: return
mesh = bpy.data.meshes.new("YZ_Rays_Mesh")
obj = bpy.data.objects.new("YZ_Rays_Obj", mesh)
obj[OBJECT_TAG] = True
col.objects.link(obj)
obj.data.materials.append(get_transparent_material("Rays", p.ray_color, p.ray_alpha))
obj.data.materials.append(get_transparent_material("Circle", p.circle_color, p.circle_alpha))
bm = bmesh.new()
c = 1.0
# Circle
R_circle = c * p.time_t
if R_circle > 0.001:
res_c = bmesh.ops.create_cone(bm, cap_ends=False, segments=96, radius1=R_circle, radius2=R_circle, depth=p.circle_depth)
circle_faces = [f for f in res_c.get('geom', res_c.get('faces', [])) if isinstance(f, bmesh.types.BMFace)]
if not circle_faces: circle_faces = bm.faces[:]
if p.circle_solid > 0:
bmesh.ops.solidify(bm, geom=circle_faces, thickness=p.circle_solid)
for face in bm.faces: face.material_index = 1
bmesh.ops.rotate(bm, verts=bm.verts, cent=(0,0,0), matrix=Matrix.Rotation(math.radians(90), 4, 'Y'))
# Rays
c_dist, v_dist = c * p.time_t, p.speed_v * p.time_t
R_rays = math.sqrt(c_dist**2 - v_dist**2) if c_dist >= v_dist else 0.0
if R_rays > 0.001:
for i in range(12):
angle_rad = math.radians(i * 30)
shaft_len, head_len = R_rays * 0.9, R_rays * 0.1
res_s = bmesh.ops.create_cone(bm, cap_ends=True, segments=12, radius1=p.ray_thickness, radius2=p.ray_thickness, depth=shaft_len)
for f in res_s.get('geom', res_s.get('faces', [])):
if isinstance(f, bmesh.types.BMFace): f.material_index = 0
bmesh.ops.translate(bm, verts=res_s['verts'], vec=Vector((0, 0, shaft_len/2)))
res_h = bmesh.ops.create_cone(bm, cap_ends=True, segments=12, radius1=p.ray_thickness * 2, radius2=0, depth=head_len)
for f in res_h.get('geom', res_h.get('faces', [])):
if isinstance(f, bmesh.types.BMFace): f.material_index = 0
bmesh.ops.translate(bm, verts=res_h['verts'], vec=Vector((0, 0, shaft_len + head_len/2)))
bmesh.ops.rotate(bm, verts=list(res_s['verts']) + list(res_h['verts']), cent=(0,0,0), matrix=Matrix.Rotation(angle_rad, 4, 'X'))
bm.to_mesh(mesh)
bm.free()
# ------------------------------------------------------------------------
# Update Logic
# ------------------------------------------------------------------------
_update_timer = None
def delayed_update_func():
global _update_timer
_update_timer = None
if bpy.context and bpy.context.scene: draw_rays_core(bpy.context)
return None
def update_view(self, context):
global _update_timer
if _update_timer:
try: bpy.app.timers.unregister(_update_timer)
except: pass
_update_timer = bpy.app.timers.register(delayed_update_func, first_interval=0.05)
# ------------------------------------------------------------------------
# Properties
# ------------------------------------------------------------------------
class PG_YZRaysProps(bpy.types.PropertyGroup):
show_rays: bpy.props.BoolProperty(name="Show Elements", default=CURRENT_DEFAULTS["show_rays"], update=update_view)
ray_color: bpy.props.FloatVectorProperty(name="Ray Color", subtype='COLOR', size=3, default=CURRENT_DEFAULTS["ray_color"], update=update_view)
ray_alpha: bpy.props.FloatProperty(name="Ray Alpha", min=0.0, max=1.0, default=CURRENT_DEFAULTS["ray_alpha"], update=update_view)
circle_color: bpy.props.FloatVectorProperty(name="Circle Color", subtype='COLOR', size=3, default=CURRENT_DEFAULTS["circle_color"], update=update_view)
circle_alpha: bpy.props.FloatProperty(name="Circle Alpha", min=0.0, max=1.0, default=CURRENT_DEFAULTS["circle_alpha"], update=update_view)
speed_v: bpy.props.FloatProperty(name="Velocity (v/c)", default=CURRENT_DEFAULTS["speed_v"], min=0.0, max=1.0, update=update_view)
time_t: bpy.props.FloatProperty(name="Time (t)", default=CURRENT_DEFAULTS["time_t"], min=0.01, update=update_view)
ray_thickness: bpy.props.FloatProperty(name="Ray Thickness", default=CURRENT_DEFAULTS["ray_thickness"], min=0.01, max=1.0, update=update_view)
circle_depth: bpy.props.FloatProperty(name="Circle Width", default=CURRENT_DEFAULTS["circle_depth"], min=0.0, max=10.0, update=update_view)
circle_solid: bpy.props.FloatProperty(name="Face Thickness", default=CURRENT_DEFAULTS["circle_solid"], min=0.0, max=1.0, update=update_view)
# ------------------------------------------------------------------------
# Operators (Fixed Copy Engine)
# ------------------------------------------------------------------------
class WM_OT_CopyYZScript(bpy.types.Operator):
bl_idname = "wm.copy_yz_script"; bl_label = "Copy Full Script"; bl_options = {'REGISTER'}
def execute(self, context):
p = context.scene.yz_rays_props
M_START, M_END = "# <BEG" + "IN_DICT>", "# <EN" + "D_DICT>"
target_text = next((t for t in bpy.data.texts if UNIQUE_SCRIPT_ID in t.as_string()), None)
if not target_text:
self.report({'ERROR'}, "Script ID not found in Text Editor.")
return {'CANCELLED'}
d_str = "CURRENT_DEFAULTS = {\n"
for k in CURRENT_DEFAULTS.keys():
val = getattr(p, k)
if hasattr(val, "__len__"): # Vectors/Tuples
v_str = ", ".join([f"{v:.4f}" for v in val])
d_str += f' "{k}": ({v_str}),\n'
elif isinstance(val, float):
d_str += f' "{k}": {val:.4f},\n'
else: # Bools/Ints
d_str += f' "{k}": {val},\n'
d_str += "}\n"
code = target_text.as_string()
try:
pre_part = code.split(M_START)[0]
post_part = code.split(M_END)[1]
new_code = pre_part + M_START + "\n" + d_str + M_END + post_part
timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
context.window_manager.clipboard = f"# {timestamp} Session Template\n" + '\n'.join(new_code.split('\n')[1:])
self.report({'INFO'}, "Copied with latest values.")
except Exception as e:
self.report({'ERROR'}, f"Failed to parse dict tags: {e}")
return {'FINISHED'}
class WM_OT_ResetYZDefaults(bpy.types.Operator):
bl_idname = "wm.reset_yz_defaults"; bl_label = "Reset Physics"; bl_description = "Reset values to system defaults"
def execute(self, context):
p = context.scene.yz_rays_props
for k, v in SYSTEM_DEFAULTS.items(): setattr(p, k, v)
self.report({'INFO'}, "Physics parameters reset.")
return {'FINISHED'}
class WM_OT_OpenRaysUrl(bpy.types.Operator):
bl_idname = "wm.open_rays_url"; bl_label = "Open URL"; url: bpy.props.StringProperty()
def execute(self, context): webbrowser.open(self.url); return {'FINISHED'}
class WM_OT_RemoveYZAddon(bpy.types.Operator):
bl_idname = "wm.remove_yz_addon"; bl_label = "Remove Addon"
def execute(self, context): unregister(); return {'FINISHED'}
# ------------------------------------------------------------------------
# UI Panels
# ------------------------------------------------------------------------
class VIEW3D_PT_YZRays(bpy.types.Panel):
bl_label = "YZ Plane Rays (V19)"; bl_space_type = 'VIEW_3D'; bl_region_type = 'UI'; bl_category = TAB_NAME
def draw(self, context):
layout = self.layout; p = context.scene.yz_rays_props
layout.operator("wm.copy_yz_script", text="Copy Code with Values", icon='COPY_ID')
layout.separator()
layout.prop(p, "show_rays", icon='HIDE_OFF')
box = layout.box(); box.label(text="Arrows"); box.prop(p, "ray_color", text=""); box.prop(p, "ray_alpha", slider=True); box.prop(p, "ray_thickness")
box = layout.box(); box.label(text="Circle"); box.prop(p, "circle_color", text=""); box.prop(p, "circle_alpha", slider=True); box.prop(p, "circle_depth"); box.prop(p, "circle_solid")
phys = layout.box(); phys.label(text="Physics"); phys.prop(p, "speed_v"); phys.prop(p, "time_t"); phys.operator("wm.reset_yz_defaults", icon='LOOP_BACK')
class VIEW3D_PT_YZLinks(bpy.types.Panel):
bl_label = "Theory Links"; bl_space_type = 'VIEW_3D'; bl_region_type = 'UI'; bl_category = TAB_NAME; bl_options = {'DEFAULT_CLOSED'}
def draw(self, context):
for l in ADDON_LINKS: op = self.layout.operator("wm.open_rays_url", text=l["label"], icon='WORLD'); op.url = l["url"]
class VIEW3D_PT_YZSystem(bpy.types.Panel):
bl_label = "System"; bl_space_type = 'VIEW_3D'; bl_region_type = 'UI'; bl_category = TAB_NAME; bl_options = {'DEFAULT_CLOSED'}
def draw(self, context): self.layout.operator("wm.remove_yz_addon", icon='CANCEL')
# ------------------------------------------------------------------------
# Registration
# ------------------------------------------------------------------------
classes = (PG_YZRaysProps, WM_OT_CopyYZScript, WM_OT_ResetYZDefaults, WM_OT_OpenRaysUrl, WM_OT_RemoveYZAddon, VIEW3D_PT_YZRays, VIEW3D_PT_YZLinks, VIEW3D_PT_YZSystem)
def register():
for c in classes: bpy.utils.register_class(c)
bpy.types.Scene.yz_rays_props = bpy.props.PointerProperty(type=PG_YZRaysProps)
def unregister():
for c in reversed(classes): bpy.utils.unregister_class(c)
if hasattr(bpy.types.Scene, "yz_rays_props"): del bpy.types.Scene.yz_rays_props
if __name__ == "__main__":
try: unregister()
except: pass
register()