File headers: use SPDX license identifiers
[blender-addons.git] / object_scatter / ui.py
blob5275260778ed02f49b4d657ef232d20517db993e
1 # SPDX-License-Identifier: GPL-2.0-or-later
3 import bpy
4 import math
6 from collections import namedtuple
8 from bpy.props import (
9 BoolProperty,
10 IntProperty,
11 FloatProperty,
12 PointerProperty
16 ScatterSettings = namedtuple("ScatterSettings",
17 ["seed", "density", "radius", "scale", "random_scale",
18 "rotation", "normal_offset", "use_normal_rotation"])
20 class ObjectScatterProperties(bpy.types.PropertyGroup):
21 seed: IntProperty(
22 name="Seed",
23 default=0,
24 description="Change it to get a different scatter pattern",
27 density: FloatProperty(
28 name="Density",
29 default=10,
30 min=0,
31 soft_max=50,
32 description="The amount of objects per unit on the line",
35 radius: FloatProperty(
36 name="Radius",
37 default=1,
38 min=0,
39 soft_max=5,
40 subtype='DISTANCE',
41 unit='LENGTH',
42 description="Maximum distance of the objects to the line",
45 scale: FloatProperty(
46 name="Scale",
47 default=0.3,
48 min=0.00001,
49 soft_max=1,
50 description="Size of the generated objects",
53 random_scale_percentage: FloatProperty(
54 name="Random Scale Percentage",
55 default=80,
56 min=0,
57 max=100,
58 subtype='PERCENTAGE',
59 precision=0,
60 description="Increase to get a larger range of sizes",
63 rotation: FloatProperty(
64 name="Rotation",
65 default=0.5,
66 min=0,
67 max=math.pi * 2,
68 soft_max=math.pi / 2,
69 subtype='ANGLE',
70 unit='ROTATION',
71 description="Maximum rotation of the generated objects",
74 normal_offset: FloatProperty(
75 name="Normal Offset",
76 default=0,
77 soft_min=-1.0,
78 soft_max=1.0,
79 description="Distance from the surface",
82 use_normal_rotation: BoolProperty(
83 name="Use Normal Rotation",
84 default=True,
85 description="Rotate the instances according to the surface normals",
88 def to_settings(self):
89 return ScatterSettings(
90 seed=self.seed,
91 density=self.density,
92 radius=self.radius,
93 scale=self.scale,
94 random_scale=self.random_scale_percentage / 100,
95 rotation=self.rotation,
96 normal_offset=self.normal_offset,
97 use_normal_rotation=self.use_normal_rotation,
101 class ObjectScatterPanel(bpy.types.Panel):
102 bl_idname = "OBJECT_PT_object_scatter"
103 bl_label = "Object Scatter"
104 bl_space_type = 'VIEW_3D'
105 bl_region_type = 'UI'
106 bl_category = "Tool"
108 def draw(self, context):
109 layout = self.layout
110 layout.use_property_split = True
111 scatter = context.scene.scatter_properties
113 layout.prop(scatter, "density", slider=True)
114 layout.prop(scatter, "radius", slider=True)
116 col = layout.column(align=True)
117 col.prop(scatter, "scale", slider=True)
118 col.prop(scatter, "random_scale_percentage", text="Randomness", slider=True)
120 layout.prop(scatter, "use_normal_rotation")
121 layout.prop(scatter, "rotation", slider=True)
122 layout.prop(scatter, "normal_offset", text="Offset", slider=True)
123 layout.prop(scatter, "seed")
125 def draw_menu(self, context):
126 layout = self.layout
127 layout.operator("object.scatter")
129 classes = (
130 ObjectScatterProperties,
131 ObjectScatterPanel,
134 def register():
135 for cls in classes:
136 bpy.utils.register_class(cls)
137 bpy.types.Scene.scatter_properties = PointerProperty(type=ObjectScatterProperties)
138 bpy.types.VIEW3D_MT_object.append(draw_menu)
140 def unregister():
141 for cls in classes:
142 bpy.utils.unregister_class(cls)
143 del bpy.types.Scene.scatter_properties
144 bpy.types.VIEW3D_MT_object.remove(draw_menu)