2025-01-04 20:13:20 +08:00
|
|
|
import bpy, mathutils, math
|
2024-01-06 23:51:11 +08:00
|
|
|
import typing
|
2025-01-04 20:13:20 +08:00
|
|
|
from . import UTIL_rail_creator
|
2024-01-06 23:51:11 +08:00
|
|
|
|
|
|
|
## Const Value Hint:
|
|
|
|
# Default Rail Radius: 0.35 (in measure)
|
|
|
|
# Default Rail Span: 3.75 (in convention)
|
|
|
|
# Default Monorail Sink Depth in Rail & Monorail Transition: 0.6259 (calculated by ImbalancedDream)
|
|
|
|
# Equation: Sink = sqrt( ((RailRadius + BallRadius) ^ 2) - ((RailSpan / 2) ^ 2) ) - BallRadius - RailRadius
|
|
|
|
# BallRadius is the radius of player ball. It always is 2.
|
|
|
|
# Ref: https://tieba.baidu.com/p/6557180791
|
2024-01-08 15:08:20 +08:00
|
|
|
#
|
|
|
|
# For Normal Side Rail (paper ball + wood ball can pass it):
|
|
|
|
# Rail Span: 3.864
|
|
|
|
# Angle (between rail panel and XY panel): 79.563 degree
|
|
|
|
# For Special Side Rail (stone ball can pass it):
|
|
|
|
# Rail Span: 3.864
|
|
|
|
# Angle (between rail panel and XY panel): 57 degree
|
|
|
|
# These infos are gotten from BallanceBug.
|
|
|
|
#
|
|
|
|
# For Side Spiral Rail, the distance between each layer is 3.6
|
|
|
|
# Measured in Level 9 and Level 13.
|
|
|
|
# For Spiral Rail, the distance between each layer is 5
|
|
|
|
# Measured in Level 10.
|
|
|
|
|
|
|
|
c_DefaultRailRadius: float = 0.35
|
|
|
|
c_DefaultRailSpan: float = 3.75
|
|
|
|
c_SideRailSpan: float = 3.864
|
|
|
|
c_NormalSideRailAngle: float = 79.563
|
|
|
|
c_StoneSideRailAngle: float = 57
|
|
|
|
c_SpiralRailScrew: float = 5
|
|
|
|
c_SideSpiralRailScrew: float = 3.6
|
2024-01-06 23:51:11 +08:00
|
|
|
|
2024-01-07 17:33:21 +08:00
|
|
|
#region Operator Helpers
|
|
|
|
|
2024-05-13 13:39:42 +08:00
|
|
|
class SharedExtraTransform():
|
|
|
|
"""
|
|
|
|
This class is served for all rail creation which allow user
|
|
|
|
provide extra transform after moving created rail to cursor.
|
|
|
|
For "what you look is what you gotten" experience, this extra transform is essential.
|
|
|
|
"""
|
|
|
|
|
|
|
|
extra_translation: bpy.props.FloatVectorProperty(
|
|
|
|
name = "Extra Translation",
|
|
|
|
description = "The extra translation applied to object after moving to cursor.",
|
|
|
|
size = 3,
|
|
|
|
subtype = 'TRANSLATION',
|
|
|
|
step = 50, # same step as the float entry of BBP_PG_bme_adder_cfgs
|
2025-01-11 21:36:11 +08:00
|
|
|
default = (0.0, 0.0, 0.0),
|
|
|
|
translation_context = 'BBP/OP_ADDS_rail.SharedExtraTransform/property'
|
2024-05-13 13:39:42 +08:00
|
|
|
) # type: ignore
|
|
|
|
extra_rotation: bpy.props.FloatVectorProperty(
|
|
|
|
name = "Extra Rotation",
|
|
|
|
description = "The extra rotation applied to object after moving to cursor.",
|
|
|
|
size = 3,
|
|
|
|
subtype = 'EULER',
|
|
|
|
step = 100, # We choosen 100, mean 1. Sync with property window.
|
2025-01-11 21:36:11 +08:00
|
|
|
default = (0.0, 0.0, 0.0),
|
|
|
|
translation_context = 'BBP/OP_ADDS_rail.SharedExtraTransform/property'
|
2024-05-13 13:39:42 +08:00
|
|
|
) # type: ignore
|
|
|
|
|
|
|
|
def draw_extra_transform_input(self, layout: bpy.types.UILayout) -> None:
|
|
|
|
# show extra transform props
|
|
|
|
# forcely order that each one are placed horizontally
|
2025-01-04 20:13:20 +08:00
|
|
|
layout.label(text = "Extra Transform")
|
2024-05-13 13:39:42 +08:00
|
|
|
# translation
|
|
|
|
layout.label(text = 'Translation')
|
|
|
|
row = layout.row()
|
|
|
|
row.prop(self, 'extra_translation', text = '')
|
|
|
|
# rotation
|
|
|
|
layout.label(text = 'Rotation')
|
|
|
|
row = layout.row()
|
|
|
|
row.prop(self, 'extra_rotation', text = '')
|
|
|
|
|
|
|
|
def general_get_extra_transform(self) -> mathutils.Matrix:
|
|
|
|
return mathutils.Matrix.LocRotScale(
|
|
|
|
mathutils.Vector(self.extra_translation),
|
|
|
|
mathutils.Euler(self.extra_rotation, 'XYZ'),
|
|
|
|
mathutils.Vector((1.0, 1.0, 1.0)) # no scale
|
|
|
|
)
|
|
|
|
|
2024-01-07 17:33:21 +08:00
|
|
|
class SharedRailSectionInputProperty():
|
|
|
|
"""
|
|
|
|
This class is served for user to pick the transition type of rail.
|
|
|
|
And order rail radius and span accoridng to user picked rail type.
|
|
|
|
"""
|
|
|
|
|
|
|
|
rail_type: bpy.props.EnumProperty(
|
|
|
|
name = "Type",
|
|
|
|
description = "Rail type",
|
|
|
|
items = [
|
|
|
|
('MONORAIL', "Monorail", ""),
|
|
|
|
('RAIL', "Rail", ""),
|
|
|
|
],
|
|
|
|
default = 'RAIL',
|
2025-01-11 21:36:11 +08:00
|
|
|
translation_context = 'BBP/OP_ADDS_rail.SharedRailSectionInputProperty/property'
|
2024-01-07 17:33:21 +08:00
|
|
|
) # type: ignore
|
2024-01-06 23:51:11 +08:00
|
|
|
|
2024-01-08 15:08:20 +08:00
|
|
|
def draw_rail_section_input(self, layout: bpy.types.UILayout) -> None:
|
|
|
|
row = layout.row()
|
|
|
|
row.prop(self, 'rail_type', expand = True)
|
2024-01-07 17:33:21 +08:00
|
|
|
|
|
|
|
def general_get_is_monorail(self) -> bool:
|
|
|
|
return self.rail_type == 'MONORAIL'
|
|
|
|
|
|
|
|
class SharedRailCapInputProperty():
|
|
|
|
"""
|
|
|
|
This class provide properties for cap switch.
|
|
|
|
Support head cap and tail cap. Both straight and screw rail can use this.
|
|
|
|
"""
|
|
|
|
|
|
|
|
rail_start_cap: bpy.props.BoolProperty(
|
|
|
|
name = 'Start Cap',
|
|
|
|
description = 'Whether this rail should have cap at start terminal.',
|
2025-01-11 21:36:11 +08:00
|
|
|
default = False,
|
|
|
|
translation_context = 'BBP/OP_ADDS_rail.SharedRailCapInputProperty/property'
|
2024-01-07 17:33:21 +08:00
|
|
|
) # type: ignore
|
|
|
|
|
|
|
|
rail_end_cap: bpy.props.BoolProperty(
|
|
|
|
name = 'End Cap',
|
|
|
|
description = 'Whether this rail should have cap at end terminal.',
|
2025-01-11 21:36:11 +08:00
|
|
|
default = False,
|
|
|
|
translation_context = 'BBP/OP_ADDS_rail.SharedRailCapInputProperty/property'
|
2024-01-06 23:51:11 +08:00
|
|
|
) # type: ignore
|
|
|
|
|
2024-01-07 17:33:21 +08:00
|
|
|
def draw_rail_cap_input(self, layout: bpy.types.UILayout) -> None:
|
2025-01-04 20:13:20 +08:00
|
|
|
layout.label(text = "Cap Options")
|
2024-01-07 17:33:21 +08:00
|
|
|
row = layout.row()
|
|
|
|
row.prop(self, "rail_start_cap", toggle = 1)
|
|
|
|
row.prop(self, "rail_end_cap", toggle = 1)
|
|
|
|
|
|
|
|
def general_get_rail_start_cap(self) -> bool:
|
|
|
|
return self.rail_start_cap
|
|
|
|
def general_get_rail_end_cap(self) -> bool:
|
|
|
|
return self.rail_end_cap
|
|
|
|
|
|
|
|
class SharedStraightRailInputProperty():
|
|
|
|
"""
|
|
|
|
The properties for straight rail.
|
|
|
|
"""
|
|
|
|
|
2024-01-06 23:51:11 +08:00
|
|
|
rail_length: bpy.props.FloatProperty(
|
2024-01-07 17:33:21 +08:00
|
|
|
name = "Length",
|
2024-01-06 23:51:11 +08:00
|
|
|
description = "The length of this rail.",
|
|
|
|
default = 5.0,
|
|
|
|
min = 0,
|
|
|
|
step = 50, # same unit as BME Struct
|
2025-01-11 21:36:11 +08:00
|
|
|
unit = 'LENGTH',
|
|
|
|
translation_context = 'BBP/OP_ADDS_rail.SharedStraightRailInputProperty/property'
|
2024-01-06 23:51:11 +08:00
|
|
|
) # type: ignore
|
|
|
|
|
2024-01-07 17:33:21 +08:00
|
|
|
def draw_straight_rail_input(self, layout: bpy.types.UILayout) -> None:
|
2024-01-06 23:51:11 +08:00
|
|
|
layout.prop(self, "rail_length")
|
|
|
|
|
|
|
|
def general_get_rail_length(self) -> float:
|
|
|
|
return self.rail_length
|
|
|
|
|
2024-01-07 17:33:21 +08:00
|
|
|
class SharedScrewRailInputProperty():
|
|
|
|
"""
|
|
|
|
The properties for straight rail.
|
|
|
|
"""
|
2024-01-06 23:51:11 +08:00
|
|
|
|
2024-01-07 17:33:21 +08:00
|
|
|
rail_screw_steps: bpy.props.IntProperty(
|
|
|
|
name = "Steps",
|
2024-01-08 15:08:20 +08:00
|
|
|
description = "The segment count per iteration. More segment, more smooth but lower performance.",
|
2024-05-25 20:32:30 +08:00
|
|
|
default = 28,
|
2024-01-07 17:33:21 +08:00
|
|
|
min = 1,
|
2025-01-11 21:36:11 +08:00
|
|
|
translation_context = 'BBP/OP_ADDS_rail.SharedScrewRailInputProperty/property'
|
2024-01-07 17:33:21 +08:00
|
|
|
) # type: ignore
|
|
|
|
|
|
|
|
rail_screw_radius: bpy.props.FloatProperty(
|
|
|
|
name = "Radius",
|
2025-01-04 12:28:59 +08:00
|
|
|
description = "The screw radius.",
|
2024-01-08 15:08:20 +08:00
|
|
|
default = 5,
|
2025-01-04 12:28:59 +08:00
|
|
|
min = 0,
|
2025-01-11 21:36:11 +08:00
|
|
|
unit = 'LENGTH',
|
|
|
|
translation_context = 'BBP/OP_ADDS_rail.SharedScrewRailInputProperty/property'
|
2024-01-07 17:33:21 +08:00
|
|
|
) # type: ignore
|
|
|
|
|
2025-01-04 20:13:20 +08:00
|
|
|
rail_screw_flip_x: bpy.props.BoolProperty(
|
|
|
|
name = 'Flip X',
|
|
|
|
description = 'Whether flip this rail with X axis',
|
2025-01-11 21:36:11 +08:00
|
|
|
default = False,
|
|
|
|
translation_context = 'BBP/OP_ADDS_rail.SharedScrewRailInputProperty/property'
|
2025-01-04 20:13:20 +08:00
|
|
|
) # type: ignore
|
|
|
|
|
|
|
|
rail_screw_flip_y: bpy.props.BoolProperty(
|
|
|
|
name = 'Flip Y',
|
|
|
|
description = 'Whether flip this rail with Y axis',
|
2025-01-11 21:36:11 +08:00
|
|
|
default = False,
|
|
|
|
translation_context = 'BBP/OP_ADDS_rail.SharedScrewRailInputProperty/property'
|
2025-01-04 20:13:20 +08:00
|
|
|
) # type: ignore
|
|
|
|
|
|
|
|
rail_screw_flip_z: bpy.props.BoolProperty(
|
|
|
|
name = 'Flip Z',
|
|
|
|
description = 'Whether flip this rail with Z axis',
|
2025-01-11 21:36:11 +08:00
|
|
|
default = False,
|
|
|
|
translation_context = 'BBP/OP_ADDS_rail.SharedScrewRailInputProperty/property'
|
2025-01-04 20:13:20 +08:00
|
|
|
) # type: ignore
|
|
|
|
|
2024-01-08 15:08:20 +08:00
|
|
|
def draw_screw_rail_input(self, layout: bpy.types.UILayout) -> None:
|
|
|
|
layout.prop(self, "rail_screw_radius")
|
|
|
|
layout.prop(self, "rail_screw_steps")
|
|
|
|
|
2024-01-07 17:33:21 +08:00
|
|
|
def general_get_rail_screw_radius(self) -> float:
|
|
|
|
return self.rail_screw_radius
|
|
|
|
def general_get_rail_screw_steps(self) -> int:
|
|
|
|
return self.rail_screw_steps
|
|
|
|
|
2025-01-04 20:13:20 +08:00
|
|
|
def draw_screw_rail_flip_input(self, layout: bpy.types.UILayout) -> None:
|
|
|
|
# flip options should placed horizontally
|
|
|
|
layout.label(text = "Flip Options")
|
|
|
|
row = layout.row()
|
|
|
|
row.prop(self, "rail_screw_flip_x", toggle = 1)
|
|
|
|
row.prop(self, "rail_screw_flip_y", toggle = 1)
|
|
|
|
row.prop(self, "rail_screw_flip_z", toggle = 1)
|
|
|
|
|
|
|
|
def general_get_rail_screw_flip_x(self) -> bool:
|
|
|
|
return self.rail_screw_flip_x
|
|
|
|
def general_get_rail_screw_flip_y(self) -> bool:
|
|
|
|
return self.rail_screw_flip_y
|
|
|
|
def general_get_rail_screw_flip_z(self) -> bool:
|
|
|
|
return self.rail_screw_flip_z
|
|
|
|
|
2024-01-07 17:33:21 +08:00
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region Operators
|
|
|
|
|
|
|
|
class BBP_OT_add_rail_section(SharedRailSectionInputProperty, bpy.types.Operator):
|
2024-01-06 23:51:11 +08:00
|
|
|
"""Add Rail Section"""
|
|
|
|
bl_idname = "bbp.add_rail_section"
|
|
|
|
bl_label = "Rail Section"
|
|
|
|
bl_options = {'REGISTER', 'UNDO'}
|
2025-01-11 21:36:11 +08:00
|
|
|
bl_translation_context = 'BBP_OT_add_rail_section'
|
2024-01-06 23:51:11 +08:00
|
|
|
|
|
|
|
def execute(self, context):
|
2025-01-04 20:13:20 +08:00
|
|
|
UTIL_rail_creator.rail_creator_wrapper(
|
|
|
|
lambda bm: UTIL_rail_creator.create_rail_section(
|
2024-01-08 15:08:20 +08:00
|
|
|
bm, self.general_get_is_monorail(),
|
|
|
|
c_DefaultRailRadius, c_DefaultRailSpan
|
2024-05-13 13:39:42 +08:00
|
|
|
),
|
|
|
|
mathutils.Matrix.Identity(4)
|
2024-01-07 17:33:21 +08:00
|
|
|
)
|
2024-01-06 23:51:11 +08:00
|
|
|
return {'FINISHED'}
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
layout = self.layout
|
2024-01-08 15:08:20 +08:00
|
|
|
self.draw_rail_section_input(layout)
|
2024-01-06 23:51:11 +08:00
|
|
|
|
2024-01-08 15:08:20 +08:00
|
|
|
class BBP_OT_add_transition_section(bpy.types.Operator):
|
2024-01-06 23:51:11 +08:00
|
|
|
"""Add Transition Section"""
|
|
|
|
bl_idname = "bbp.add_transition_section"
|
|
|
|
bl_label = "Transition Section"
|
|
|
|
bl_options = {'REGISTER', 'UNDO'}
|
2025-01-11 21:36:11 +08:00
|
|
|
bl_translation_context = 'BBP_OT_add_transition_section'
|
2024-01-06 23:51:11 +08:00
|
|
|
|
|
|
|
def execute(self, context):
|
2025-01-04 20:13:20 +08:00
|
|
|
UTIL_rail_creator.rail_creator_wrapper(
|
|
|
|
lambda bm: UTIL_rail_creator.create_transition_section(bm, c_DefaultRailRadius, c_DefaultRailSpan),
|
2024-05-13 13:39:42 +08:00
|
|
|
mathutils.Matrix.Identity(4)
|
2024-01-07 17:33:21 +08:00
|
|
|
)
|
2024-01-06 23:51:11 +08:00
|
|
|
return {'FINISHED'}
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
layout = self.layout
|
2024-01-08 15:08:20 +08:00
|
|
|
layout.label(text = 'No Options Available')
|
2024-01-06 23:51:11 +08:00
|
|
|
|
2024-05-13 13:39:42 +08:00
|
|
|
class BBP_OT_add_straight_rail(SharedExtraTransform, SharedRailSectionInputProperty, SharedRailCapInputProperty, SharedStraightRailInputProperty, bpy.types.Operator):
|
2024-01-07 17:33:21 +08:00
|
|
|
"""Add Straight Rail"""
|
|
|
|
bl_idname = "bbp.add_straight_rail"
|
|
|
|
bl_label = "Straight Rail"
|
2024-01-06 23:51:11 +08:00
|
|
|
bl_options = {'REGISTER', 'UNDO'}
|
2025-01-11 21:36:11 +08:00
|
|
|
bl_translation_context = 'BBP_OT_add_straight_rail'
|
2024-01-06 23:51:11 +08:00
|
|
|
|
|
|
|
def execute(self, context):
|
2025-01-04 20:13:20 +08:00
|
|
|
UTIL_rail_creator.rail_creator_wrapper(
|
|
|
|
lambda bm: UTIL_rail_creator.create_straight_rail(
|
2024-01-07 17:33:21 +08:00
|
|
|
bm,
|
2024-01-08 15:08:20 +08:00
|
|
|
self.general_get_is_monorail(), c_DefaultRailRadius, c_DefaultRailSpan,
|
|
|
|
self.general_get_rail_length(), 0,
|
2024-01-07 17:33:21 +08:00
|
|
|
self.general_get_rail_start_cap(), self.general_get_rail_end_cap()
|
2024-05-13 13:39:42 +08:00
|
|
|
),
|
|
|
|
self.general_get_extra_transform()
|
2024-01-06 23:51:11 +08:00
|
|
|
)
|
|
|
|
return {'FINISHED'}
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
layout = self.layout
|
2024-01-08 15:08:20 +08:00
|
|
|
layout.label(text = 'Straight Rail')
|
|
|
|
self.draw_rail_section_input(layout)
|
|
|
|
self.draw_straight_rail_input(layout)
|
2024-01-07 17:33:21 +08:00
|
|
|
layout.separator()
|
2024-01-06 23:51:11 +08:00
|
|
|
self.draw_rail_cap_input(layout)
|
2024-05-13 13:39:42 +08:00
|
|
|
layout.separator()
|
|
|
|
self.draw_extra_transform_input(layout)
|
2024-01-08 15:08:20 +08:00
|
|
|
|
2024-05-13 13:39:42 +08:00
|
|
|
class BBP_OT_add_transition_rail(SharedExtraTransform, SharedRailCapInputProperty, SharedStraightRailInputProperty, bpy.types.Operator):
|
2024-01-09 17:52:30 +08:00
|
|
|
"""Add Transition Rail"""
|
|
|
|
bl_idname = "bbp.add_transition_rail"
|
|
|
|
bl_label = "Transition Rail"
|
|
|
|
bl_options = {'REGISTER', 'UNDO'}
|
2025-01-11 21:36:11 +08:00
|
|
|
bl_translation_context = 'BBP_OT_add_transition_rail'
|
2024-01-09 17:52:30 +08:00
|
|
|
|
|
|
|
def execute(self, context):
|
2025-01-04 20:13:20 +08:00
|
|
|
UTIL_rail_creator.rail_creator_wrapper(
|
|
|
|
lambda bm: UTIL_rail_creator.create_transition_rail(
|
2024-01-09 17:52:30 +08:00
|
|
|
bm,
|
|
|
|
c_DefaultRailRadius, c_DefaultRailSpan,
|
|
|
|
self.general_get_rail_length(),
|
|
|
|
self.general_get_rail_start_cap(), self.general_get_rail_end_cap()
|
2024-05-13 13:39:42 +08:00
|
|
|
),
|
|
|
|
self.general_get_extra_transform()
|
2024-01-09 17:52:30 +08:00
|
|
|
)
|
|
|
|
return {'FINISHED'}
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
layout = self.layout
|
|
|
|
layout.label(text = 'Transition Rail')
|
|
|
|
self.draw_straight_rail_input(layout)
|
|
|
|
layout.separator()
|
|
|
|
self.draw_rail_cap_input(layout)
|
2024-05-13 13:39:42 +08:00
|
|
|
layout.separator()
|
|
|
|
self.draw_extra_transform_input(layout)
|
2024-01-09 17:52:30 +08:00
|
|
|
|
2024-05-13 13:39:42 +08:00
|
|
|
class BBP_OT_add_side_rail(SharedExtraTransform, SharedRailCapInputProperty, SharedStraightRailInputProperty, bpy.types.Operator):
|
2024-01-08 15:08:20 +08:00
|
|
|
"""Add Side Rail"""
|
|
|
|
bl_idname = "bbp.add_side_rail"
|
|
|
|
bl_label = "Side Rail"
|
|
|
|
bl_options = {'REGISTER', 'UNDO'}
|
2025-01-11 21:36:11 +08:00
|
|
|
bl_translation_context = 'BBP_OT_add_side_rail'
|
2024-01-08 15:08:20 +08:00
|
|
|
|
|
|
|
side_rail_type: bpy.props.EnumProperty(
|
|
|
|
name = "Side Type",
|
|
|
|
description = "Side rail type",
|
|
|
|
items = [
|
|
|
|
('NORMAL', "Normal", "The normal side rail."),
|
|
|
|
('STONE', "Stone Specific", "The side rail which also allow stone ball passed."),
|
|
|
|
],
|
|
|
|
default = 'NORMAL',
|
2025-01-11 21:36:11 +08:00
|
|
|
translation_context = 'BBP_OT_add_side_rail/property'
|
2024-01-08 15:08:20 +08:00
|
|
|
) # type: ignore
|
|
|
|
|
|
|
|
def execute(self, context):
|
2025-01-04 20:13:20 +08:00
|
|
|
UTIL_rail_creator.rail_creator_wrapper(
|
|
|
|
lambda bm: UTIL_rail_creator.create_straight_rail(
|
2024-01-08 15:08:20 +08:00
|
|
|
bm,
|
|
|
|
False, c_DefaultRailRadius, c_DefaultRailSpan,
|
|
|
|
self.general_get_rail_length(),
|
|
|
|
c_NormalSideRailAngle if self.side_rail_type == 'NORMAL' else c_StoneSideRailAngle,
|
|
|
|
self.general_get_rail_start_cap(), self.general_get_rail_end_cap()
|
2024-05-13 13:39:42 +08:00
|
|
|
),
|
|
|
|
self.general_get_extra_transform()
|
2024-01-08 15:08:20 +08:00
|
|
|
)
|
|
|
|
return {'FINISHED'}
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
layout = self.layout
|
|
|
|
layout.label(text = 'Side Rail')
|
|
|
|
layout.prop(self, 'side_rail_type')
|
2024-01-07 17:33:21 +08:00
|
|
|
self.draw_straight_rail_input(layout)
|
2024-01-08 15:08:20 +08:00
|
|
|
layout.separator()
|
|
|
|
self.draw_rail_cap_input(layout)
|
2024-05-13 13:39:42 +08:00
|
|
|
layout.separator()
|
|
|
|
self.draw_extra_transform_input(layout)
|
2024-01-06 23:51:11 +08:00
|
|
|
|
2024-05-13 13:39:42 +08:00
|
|
|
class BBP_OT_add_arc_rail(SharedExtraTransform, SharedRailSectionInputProperty, SharedRailCapInputProperty, SharedScrewRailInputProperty, bpy.types.Operator):
|
2024-01-08 15:08:20 +08:00
|
|
|
"""Add Arc Rail"""
|
|
|
|
bl_idname = "bbp.add_arc_rail"
|
|
|
|
bl_label = "Arc Rail"
|
2024-01-06 23:51:11 +08:00
|
|
|
bl_options = {'REGISTER', 'UNDO'}
|
2025-01-11 21:36:11 +08:00
|
|
|
bl_translation_context = 'BBP_OT_add_arc_rail'
|
2024-01-06 23:51:11 +08:00
|
|
|
|
2024-01-08 15:08:20 +08:00
|
|
|
rail_screw_angle: bpy.props.FloatProperty(
|
|
|
|
name = "Angle",
|
|
|
|
description = "The angle of this arc rail rotated.",
|
|
|
|
default = math.radians(90),
|
|
|
|
min = 0, max = math.radians(360),
|
|
|
|
subtype = 'ANGLE',
|
2025-01-11 21:36:11 +08:00
|
|
|
translation_context = 'BBP_OT_add_arc_rail/property'
|
2024-01-08 15:08:20 +08:00
|
|
|
) # type: ignore
|
|
|
|
|
2024-01-06 23:51:11 +08:00
|
|
|
def execute(self, context):
|
2025-01-04 20:13:20 +08:00
|
|
|
UTIL_rail_creator.rail_creator_wrapper(
|
|
|
|
lambda bm: UTIL_rail_creator.create_screw_rail(
|
2024-01-07 17:33:21 +08:00
|
|
|
bm,
|
2024-01-08 15:08:20 +08:00
|
|
|
self.general_get_is_monorail(), c_DefaultRailRadius, c_DefaultRailSpan,
|
2024-01-07 17:33:21 +08:00
|
|
|
self.general_get_rail_start_cap(), self.general_get_rail_end_cap(),
|
2024-01-08 15:08:20 +08:00
|
|
|
math.degrees(self.rail_screw_angle), 0, 1, # blender passed value is in radians
|
2025-01-04 20:13:20 +08:00
|
|
|
self.general_get_rail_screw_steps(), self.general_get_rail_screw_radius(),
|
|
|
|
self.general_get_rail_screw_flip_x(), self.general_get_rail_screw_flip_y(), self.general_get_rail_screw_flip_z()
|
2024-05-13 13:39:42 +08:00
|
|
|
),
|
|
|
|
self.general_get_extra_transform()
|
2024-01-06 23:51:11 +08:00
|
|
|
)
|
|
|
|
return {'FINISHED'}
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
layout = self.layout
|
2024-01-08 15:08:20 +08:00
|
|
|
layout.label(text = 'Arc Rail')
|
|
|
|
self.draw_rail_section_input(layout)
|
|
|
|
self.draw_screw_rail_input(layout)
|
|
|
|
layout.prop(self, "rail_screw_angle")
|
2024-01-07 17:33:21 +08:00
|
|
|
layout.separator()
|
2025-01-04 20:13:20 +08:00
|
|
|
self.draw_screw_rail_flip_input(layout)
|
|
|
|
layout.separator()
|
2024-01-06 23:51:11 +08:00
|
|
|
self.draw_rail_cap_input(layout)
|
2024-05-13 13:39:42 +08:00
|
|
|
layout.separator()
|
|
|
|
self.draw_extra_transform_input(layout)
|
2024-01-08 15:08:20 +08:00
|
|
|
|
2024-05-13 13:39:42 +08:00
|
|
|
class BBP_OT_add_spiral_rail(SharedExtraTransform, SharedRailCapInputProperty, SharedScrewRailInputProperty, bpy.types.Operator):
|
2024-01-08 15:08:20 +08:00
|
|
|
"""Add Spiral Rail"""
|
|
|
|
bl_idname = "bbp.add_spiral_rail"
|
|
|
|
bl_label = "Spiral Rail"
|
|
|
|
bl_options = {'REGISTER', 'UNDO'}
|
2025-01-11 21:36:11 +08:00
|
|
|
bl_translation_context = 'BBP_OT_add_spiral_rail'
|
2024-01-08 15:08:20 +08:00
|
|
|
|
|
|
|
rail_screw_screw: bpy.props.FloatProperty(
|
|
|
|
name = "Screw",
|
|
|
|
description = "The increased height in each iteration. Minus height also is accepted.",
|
|
|
|
default = c_SpiralRailScrew,
|
2025-01-11 21:36:11 +08:00
|
|
|
unit = 'LENGTH',
|
|
|
|
translation_context = 'BBP_OT_add_spiral_rail/property'
|
2024-01-08 15:08:20 +08:00
|
|
|
) # type: ignore
|
|
|
|
|
|
|
|
rail_screw_iterations: bpy.props.IntProperty(
|
|
|
|
name = "Iterations",
|
|
|
|
description = "Indicate how many layers of this spiral rail should be generated.",
|
|
|
|
default = 1,
|
|
|
|
min = 1,
|
2025-01-11 21:36:11 +08:00
|
|
|
translation_context = 'BBP_OT_add_spiral_rail/property'
|
2024-01-08 15:08:20 +08:00
|
|
|
) # type: ignore
|
|
|
|
|
|
|
|
def execute(self, context):
|
2025-01-04 20:13:20 +08:00
|
|
|
UTIL_rail_creator.rail_creator_wrapper(
|
|
|
|
lambda bm: UTIL_rail_creator.create_screw_rail(
|
2024-01-08 15:08:20 +08:00
|
|
|
bm,
|
|
|
|
False, c_DefaultRailRadius, c_DefaultRailSpan,
|
|
|
|
self.general_get_rail_start_cap(), self.general_get_rail_end_cap(),
|
|
|
|
360, self.rail_screw_screw, self.rail_screw_iterations,
|
2025-01-04 20:13:20 +08:00
|
|
|
self.general_get_rail_screw_steps(), self.general_get_rail_screw_radius(),
|
|
|
|
self.general_get_rail_screw_flip_x(), self.general_get_rail_screw_flip_y(), self.general_get_rail_screw_flip_z()
|
2024-05-13 13:39:42 +08:00
|
|
|
),
|
|
|
|
self.general_get_extra_transform()
|
2024-01-08 15:08:20 +08:00
|
|
|
)
|
|
|
|
return {'FINISHED'}
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
layout = self.layout
|
|
|
|
layout.label(text = 'Spiral Rail')
|
|
|
|
self.draw_screw_rail_input(layout)
|
|
|
|
layout.prop(self, "rail_screw_screw")
|
|
|
|
layout.prop(self, "rail_screw_iterations")
|
|
|
|
layout.separator()
|
2025-01-04 20:13:20 +08:00
|
|
|
self.draw_screw_rail_flip_input(layout)
|
|
|
|
layout.separator()
|
2024-01-08 15:08:20 +08:00
|
|
|
self.draw_rail_cap_input(layout)
|
2024-05-13 13:39:42 +08:00
|
|
|
layout.separator()
|
|
|
|
self.draw_extra_transform_input(layout)
|
2024-01-08 15:08:20 +08:00
|
|
|
|
2024-05-13 13:39:42 +08:00
|
|
|
class BBP_OT_add_side_spiral_rail(SharedExtraTransform, SharedRailSectionInputProperty, SharedRailCapInputProperty, SharedScrewRailInputProperty, bpy.types.Operator):
|
2024-01-08 15:08:20 +08:00
|
|
|
"""Add Side Spiral Rail"""
|
|
|
|
bl_idname = "bbp.add_side_spiral_rail"
|
|
|
|
bl_label = "Side Spiral Rail"
|
|
|
|
bl_options = {'REGISTER', 'UNDO'}
|
2025-01-11 21:36:11 +08:00
|
|
|
bl_translation_context = 'BBP_OT_add_side_spiral_rail'
|
2024-01-08 15:08:20 +08:00
|
|
|
|
|
|
|
rail_screw_iterations: bpy.props.IntProperty(
|
|
|
|
name = "Iterations",
|
|
|
|
description = "Indicate how many layers of this spiral rail should be generated.",
|
|
|
|
default = 2,
|
|
|
|
# at least 2 ietrations can create 1 useful side spiral rail.
|
|
|
|
# becuase side spiral rail is edge shared.
|
|
|
|
min = 2,
|
2025-01-11 21:36:11 +08:00
|
|
|
translation_context = 'BBP_OT_add_side_spiral_rail/property'
|
2024-01-08 15:08:20 +08:00
|
|
|
) # type: ignore
|
|
|
|
|
|
|
|
def execute(self, context):
|
2025-01-04 20:13:20 +08:00
|
|
|
UTIL_rail_creator.rail_creator_wrapper(
|
|
|
|
lambda bm: UTIL_rail_creator.create_screw_rail(
|
2024-01-08 15:08:20 +08:00
|
|
|
bm,
|
|
|
|
True, c_DefaultRailRadius, c_DefaultRailSpan,
|
|
|
|
self.general_get_rail_start_cap(), self.general_get_rail_end_cap(),
|
|
|
|
360, c_SideSpiralRailScrew, self.rail_screw_iterations,
|
2025-01-04 20:13:20 +08:00
|
|
|
self.general_get_rail_screw_steps(), self.general_get_rail_screw_radius(),
|
|
|
|
self.general_get_rail_screw_flip_x(), self.general_get_rail_screw_flip_y(), self.general_get_rail_screw_flip_z()
|
2024-05-13 13:39:42 +08:00
|
|
|
),
|
|
|
|
self.general_get_extra_transform()
|
2024-01-08 15:08:20 +08:00
|
|
|
)
|
|
|
|
return {'FINISHED'}
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
layout = self.layout
|
|
|
|
layout.label(text = 'Spiral Rail')
|
|
|
|
self.draw_screw_rail_input(layout)
|
|
|
|
layout.prop(self, "rail_screw_iterations")
|
2024-01-07 17:33:21 +08:00
|
|
|
layout.separator()
|
2025-01-04 20:13:20 +08:00
|
|
|
self.draw_screw_rail_flip_input(layout)
|
|
|
|
layout.separator()
|
2024-01-08 15:08:20 +08:00
|
|
|
self.draw_rail_cap_input(layout)
|
2024-05-13 13:39:42 +08:00
|
|
|
layout.separator()
|
|
|
|
self.draw_extra_transform_input(layout)
|
2024-01-06 23:51:11 +08:00
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
2024-02-12 11:42:09 +08:00
|
|
|
def register() -> None:
|
2024-01-06 23:51:11 +08:00
|
|
|
bpy.utils.register_class(BBP_OT_add_rail_section)
|
|
|
|
bpy.utils.register_class(BBP_OT_add_transition_section)
|
2024-01-08 15:08:20 +08:00
|
|
|
|
2024-01-06 23:51:11 +08:00
|
|
|
bpy.utils.register_class(BBP_OT_add_straight_rail)
|
2024-01-09 17:52:30 +08:00
|
|
|
bpy.utils.register_class(BBP_OT_add_transition_rail)
|
2024-01-08 15:08:20 +08:00
|
|
|
bpy.utils.register_class(BBP_OT_add_side_rail)
|
|
|
|
|
|
|
|
bpy.utils.register_class(BBP_OT_add_arc_rail)
|
|
|
|
bpy.utils.register_class(BBP_OT_add_spiral_rail)
|
|
|
|
bpy.utils.register_class(BBP_OT_add_side_spiral_rail)
|
2024-01-06 23:51:11 +08:00
|
|
|
|
|
|
|
|
2024-02-12 11:42:09 +08:00
|
|
|
def unregister() -> None:
|
2024-01-08 15:08:20 +08:00
|
|
|
bpy.utils.unregister_class(BBP_OT_add_side_spiral_rail)
|
|
|
|
bpy.utils.unregister_class(BBP_OT_add_spiral_rail)
|
|
|
|
bpy.utils.unregister_class(BBP_OT_add_arc_rail)
|
|
|
|
|
|
|
|
bpy.utils.unregister_class(BBP_OT_add_side_rail)
|
2024-01-09 17:52:30 +08:00
|
|
|
bpy.utils.unregister_class(BBP_OT_add_transition_rail)
|
2024-01-06 23:51:11 +08:00
|
|
|
bpy.utils.unregister_class(BBP_OT_add_straight_rail)
|
2024-01-08 15:08:20 +08:00
|
|
|
|
2024-01-06 23:51:11 +08:00
|
|
|
bpy.utils.unregister_class(BBP_OT_add_transition_section)
|
|
|
|
bpy.utils.unregister_class(BBP_OT_add_rail_section)
|