108 lines
4.2 KiB
Python
108 lines
4.2 KiB
Python
import bpy
|
|
import math
|
|
import webbrowser
|
|
from mathutils import Matrix
|
|
|
|
|
|
|
|
class MRTS_sinewave(bpy.types.Operator):
|
|
"""... Draw a sine wave in blender!!! .."""
|
|
bl_idname = "object.mrts_sinewave"
|
|
bl_label = ""
|
|
bl_options = {'REGISTER', 'UNDO'}
|
|
|
|
def visible_active_objmode_select(self, any_obj):
|
|
any_obj.hide_set(False)
|
|
bpy.context.view_layer.objects.active = any_obj
|
|
bpy.ops.object.mode_set(mode='OBJECT')
|
|
bpy.ops.object.select_all(action='DESELECT')
|
|
any_obj.select_set(True)
|
|
|
|
def get_perspective_view_distance(self, context, area):
|
|
view_distance = None
|
|
was_ortho = False
|
|
|
|
region_3d = area.spaces.active.region_3d
|
|
if region_3d.view_perspective == 'ORTHO':
|
|
was_ortho = True
|
|
region_3d.view_perspective = 'PERSP'
|
|
view_distance = region_3d.view_distance
|
|
if was_ortho:
|
|
region_3d.view_perspective = 'ORTHO'
|
|
|
|
return view_distance
|
|
|
|
def execute(self, context):
|
|
view_matrix = Matrix.Identity(4)
|
|
for area in bpy.context.screen.areas:
|
|
if area.type == 'VIEW_3D':
|
|
view_matrix = area.spaces.active.region_3d.view_matrix
|
|
view_distance = self.get_perspective_view_distance(context, area)
|
|
break
|
|
view_rotation_matrix = view_matrix.to_3x3().inverted()
|
|
|
|
# Parameters for the sine wave
|
|
amplitude = 100
|
|
frequency = 1
|
|
num_points = 100
|
|
phase = 0
|
|
scale = 2.0 # Scale the distance between points
|
|
shift_x = amplitude * scale / 2
|
|
|
|
sine_points = [(i * scale - shift_x, amplitude * math.sin(i * frequency * 2 * math.pi / (num_points-1) + phase), 0) for i in range(num_points)]
|
|
# Create a new Grease Pencil object if it doesn't exist
|
|
# gp_obj = None
|
|
for obj in bpy.context.scene.objects:
|
|
if obj.type == 'GPENCIL' and obj.name == "sine wave":
|
|
# gp_obj = obj
|
|
bpy.data.objects.remove(obj, do_unlink=True)
|
|
break
|
|
# if gp_obj is None:
|
|
# Create a new Grease Pencil data-block
|
|
|
|
#***************************************************************************************#
|
|
bpy.context.view_layer.active_layer_collection = bpy.context.view_layer.layer_collection
|
|
#***************************************************************************************#
|
|
|
|
gp_data = bpy.data.grease_pencils.new("GPencil")
|
|
gp_obj = bpy.data.objects.new("sine wave", gp_data)
|
|
bpy.context.collection.objects.link(gp_obj)
|
|
|
|
self.visible_active_objmode_select(gp_obj)
|
|
|
|
# Ensure we're in object mode with the correct object active
|
|
if bpy.context.active_object is not gp_obj:
|
|
bpy.context.view_layer.objects.active = gp_obj
|
|
gp_obj.select_set(True)
|
|
bpy.ops.object.mode_set(mode='OBJECT')
|
|
# Add a new Grease Pencil layer if it doesn't exist
|
|
if "SineWaveLayer" not in gp_obj.data.layers:
|
|
gp_layer = gp_obj.data.layers.new(name="SineWaveLayer", set_active=True)
|
|
else:
|
|
gp_layer = gp_obj.data.layers["SineWaveLayer"]
|
|
# Create a new frame in the Grease Pencil layer or use the current one
|
|
if not gp_layer.frames:
|
|
gp_frame = gp_layer.frames.new(bpy.context.scene.frame_current)
|
|
else:
|
|
gp_frame = gp_layer.active_frame
|
|
# Create a new stroke
|
|
if not gp_frame.strokes:
|
|
stroke = gp_frame.strokes.new()
|
|
stroke.display_mode = '3DSPACE'
|
|
stroke.points.add(count=len(sine_points))
|
|
for i, point in enumerate(sine_points):
|
|
stroke.points[i].co = point
|
|
if not gp_obj.data.materials:
|
|
mat = bpy.data.materials.new(name="GPencilMaterial")
|
|
mat.line_color = [1.0, 0.0, 0.0, 1.0]
|
|
gp_obj.data.materials.append(mat)
|
|
stroke.material_index = 0
|
|
|
|
gp_obj.rotation_mode = 'XYZ'
|
|
gp_obj.rotation_euler = view_rotation_matrix.to_euler()
|
|
scale_factor = view_distance / 300
|
|
gp_obj.scale = (scale_factor, scale_factor, scale_factor)
|
|
bpy.context.view_layer.update()
|
|
|
|
return {'FINISHED'}
|