2020年に書いた記事「Blender 2.9, Python ビル、自動車、動画」を、blender 4.1.1で動作するように改訂しました。
なお途中の= KOI HONMACHI Map =の部分6行はJPEG画像(地図)を呼び出しているのでエラーが出る場合は消してください。
主な変更点は
(A)ビルの形状。cube使用。途中の2箇所 bpy.ops.mesh.primitive_cube_add(size=2 を (size = 1と変更すると元の狙った形状にできた。
原因不明。blender 2.9からblender 4.1へのどこかで仕様変更があったかも。
(B)自動車移動 CAR movement で、bpy.context.scene.frame_current = 1 を bpy.context.scene.frame_set(frame_num)に。frame_numには適度に数字をパラパラと入れて。ホロモン氏「MRが楽しい」 の記事を参考に。
(C)自動車移動 CAR movement の部分は変数を変えながら5行ごとにダラダラ書いていたのをきちんとfor文の繰り返しに変えました。最初からこう書けばよかった話。
title.bph55
#bph55, 車体、地図建物。階段, 看板2枚 2020.10.28---2024.5.17
import bpy
import bmesh
import math
from math import radians
from mathutils import Matrix
#========= DELETE ALL mesh, light, camera, みな削除する2行 =========
for item in bpy.data.objects:
bpy.data.objects.remove(item)
def hex_to_rgb( hex_value ): #=== hex color code to RGB
b = (hex_value & 0xFF) / 255.0
g = ((hex_value >> 8) & 0xFF) / 255.0
r = ((hex_value >> 16) & 0xFF) / 255.0
return r, g, b
def add_material(obj, material_name, h): #=== material to cube
material = bpy.data.materials.get(material_name)
if material is None:
material = bpy.data.materials.new(material_name)
material.use_nodes = True
principled_bsdf = material.node_tree.nodes['Principled BSDF']
if principled_bsdf is not None:
principled_bsdf.inputs[0].default_value = (*hex_to_rgb(h), 1)
obj.active_material = material
# =================== definition , create apartment #FThick=1.5 meter (3 meter per floor ) (modified for blender4.1)
xy_bump = 1.05 # building wide and narrow cube xy_bump ( 1 wide cube plus 1 narrow cube makes one floor)
def create_apartment(x_origin, y_origin, z_rot, NumOfStories, xScale, yScale, FThick, odd_color, even_color):
for i in range (0, 2*NumOfStories, 2):
bpy.ops.mesh.primitive_cube_add(size=1, enter_editmode=False, align='WORLD', location=(x_origin, y_origin, i * FThick), rotation=(0.0, 0.0, z_rot), scale=(xScale, yScale, FThick))
obj = bpy.context.object
# add_material( obj, "color01", odd_color )
add_material( obj, "", odd_color )
bpy.ops.mesh.primitive_cube_add(size=1, enter_editmode=False, align='WORLD', location=(x_origin, y_origin, FThick + i * FThick), rotation=(0.0, 0.0, z_rot), scale=(xScale*xy_bump, yScale*xy_bump, FThick))
obj = bpy.context.object
# add_material( obj, "color02", even_color )
add_material( obj, "", even_color )
# ======== create now z_rot:rotation, NumOfStories:floors,
# create_apartment(x_origin, y_origin, z_rot, NumOfStories, xScale, yScale, FThick, odd_color, even_color):
create_apartment(-21, -27, 1/180*3.14, 5, 15, 25, 1.5, 0x2F2F2F, 0xffe4b5) #ryowa #DARKSLATEGRAY#2F4F4F
create_apartment(-31, 4, -30/180*3.14, 15, 15, 18, 1.5, 0x2F2F2F, 0xffe4b5) #HBF #DARKSLATEGRAY#2F4F4F
create_apartment(-25, 20, -30/180*3.14, 8, 18, 15, 1.5, 0xffe4b5, 0x222222) #apt5 bldg
create_apartment(-23, 40, 0/180*3.14, 2, 15, 30, 1.2, 0xeeeeee, 0x6495ed) #boff #MAROON#800000 ,#DARKGRAY#A9A9A9 ##lightskyblue#87cefa #cornflowerblue#6495ed
create_apartment(-20, 68, 0/180*3.14, 4, 9, 9, 1.5, 0x2F2F2F, 0xffe4b5) #cosmos -20, 67, 10m 10m
create_apartment(14, 70, 0/180*3.14, 4, 22, 11, 1.5, 0x2F2F2F, 0xffe4b5) #seikei x14,y70, 22m 11m
create_apartment(-50, 53, 0/180*3.14, 10, 10, 10, 1.5, 0x2F2F2F, 0xffe4b5) #lumiere_k1 -49,53, scale 6,6
create_apartment(-60, 55, 0/180*3.14, 10, 12, 12, 1.5, 0x2F2F2F, 0xffe4b5) #lumiere_k2 -49,53, scale 6,6
# ====== create kanbans ... 2 planes
bpy.ops.mesh.primitive_plane_add(size=4, enter_editmode=False, align='WORLD', location=(-15, 48, 6.25), rotation=(3.14/2, 0, 3.14/2), scale=(1,1,1))
bpy.context.active_object.name = 'kanban_book'
bpy.ops.mesh.primitive_plane_add(size=4, enter_editmode=False, align='WORLD', location=(-15, 13, 3.5), rotation=(3.14/2, 0, 3.14*0.4), scale=(1,1,1))
bpy.ops.transform.resize(value=(1, 3, 0.7))
bpy.context.active_object.name = 'kanban_higa'
#==================== beginning of STAIRS . skew rectangle
pi = math.pi
# URL https://tamaki-py.hatenablog.com/entry/2019/06/03/223545
#'''オブジェクトモードから始めなければなりません. scene が empty(空)であるときスクリプトは動きません.'''
## オブジェクトモードに変更.
#bpy.ops.object.mode_set(mode='OBJECT')
## 全てのオブジェクトを選択.
#bpy.ops.object.select_all(action='SELECT')
## 選択された全てのオブジェクトを削除.
#bpy.ops.object.delete()
#'''立方体を作成し, 編集モードに切り替え.'''
# 立方体を配置.
#######(-49,60, 0)
# === stairs east face
bpy.ops.mesh.primitive_cube_add(size=1, location=(-51, 61, 0)) ##lumiere_koi_bldg stairs
bpy.ops.transform.resize(value=(0.1, 4, 1.4))
# 編集モードに切り替え.
bpy.ops.object.mode_set(mode='EDIT')
# 全てのメッシュを非選択状態にする.
bpy.ops.mesh.select_all(action='DESELECT')
'''面モードにし, 一つの面を回転させる.'''
# 面モードに設定.
bpy.ops.mesh.select_mode(type="FACE")
# bmesh オブジェクトのインスタンス化.
b_mesh = bmesh.from_edit_mesh(bpy.context.object.data)
b_mesh.faces.ensure_lookup_table()
b_mesh.faces[3].select = True # === face number (3) south face
bpy.ops.transform.translate(value=(0, 0, 3)) #=== move a face upward
bpy.ops.object.mode_set(mode='OBJECT')
for i in range(8):
bpy.ops.object.duplicate_move(OBJECT_OT_duplicate={"linked":False, "mode":'TRANSLATION'}, TRANSFORM_OT_translate={"value":(0, 0, 3), "orient_type":'GLOBAL', "orient_matrix":((1, 0, 0), (0, 1, 0), (0, 0, 1)), "orient_matrix_type":'GLOBAL', "constraint_axis":(False, False, False), })
# === lumiere_koi_bldg stairs west face
bpy.ops.mesh.primitive_cube_add(size=1, location=(-53, 61, 0)) ##lumiere_koi_bldg stairs
bpy.ops.transform.resize(value=(0.1, 4, 1.4))
# 編集モードに切り替え.
bpy.ops.object.mode_set(mode='EDIT')
# 全てのメッシュを非選択状態にする.
bpy.ops.mesh.select_all(action='DESELECT')
'''面モードにし, 一つの面を回転させる.'''
# 面モードに設定.
bpy.ops.mesh.select_mode(type="FACE")
# bmesh オブジェクトのインスタンス化.
b_mesh = bmesh.from_edit_mesh(bpy.context.object.data)
b_mesh.faces.ensure_lookup_table()
b_mesh.faces[1].select = True # === face number (3) south face
bpy.ops.transform.translate(value=(0, 0, 3)) #=== move a face upward
bpy.ops.object.mode_set(mode='OBJECT')
for i in range(8):
bpy.ops.object.duplicate_move(OBJECT_OT_duplicate={"linked":False, "mode":'TRANSLATION'}, TRANSFORM_OT_translate={"value":(0, 0, 3), "orient_type":'GLOBAL', "orient_matrix":((1, 0, 0), (0, 1, 0), (0, 0, 1)), "orient_matrix_type":'GLOBAL', "constraint_axis":(False, False, False), })
# === lumiere_koi_bldg stairs north rectrangle face
bpy.ops.mesh.primitive_cube_add(size=1, location=(-52, 63, 0)) ##lumiere_koi_bldg stairs
bpy.ops.transform.resize(value=(2,0.1,1.4)) #(0.1, 4, 1.4))
for i in range(8):
bpy.ops.object.duplicate_move(OBJECT_OT_duplicate={"linked":False, "mode":'TRANSLATION'}, TRANSFORM_OT_translate={"value":(0, 0, 3), "orient_type":'GLOBAL', "orient_matrix":((1, 0, 0), (0, 1, 0), (0, 0, 1)), "orient_matrix_type":'GLOBAL', "constraint_axis":(False, False, False), })
#============================ end of STAIRS
## === hodoukyo horizontal part
bpy.ops.mesh.primitive_cube_add(size=1, location=(-52, 67, 2.5))
bpy.ops.transform.resize(value=(2, 8, 1))
## === hodoukyo "v-shape" arch over the bridge
vlen = 12
vb_height =5 #apex height
ct_x = -52 # center x
ct_y = 67 # center y
for i in range(-vlen, (vlen +1) ): #( (-3, 3)と書けばマイナス側3個原点に1個、プラス側2個 合計6個)
x= i/2
y= i/2
z= vb_height - abs(i) / 8
bpy.ops.mesh.primitive_cube_add(size=0.3, location=(ct_x + x*0.3, ct_y + y*0.3, z))
bpy.ops.mesh.primitive_cube_add(size=0.3, location=(ct_x + x*0.3, ct_y -y*0.3, z))
bpy.ops.mesh.primitive_cube_add(size=0.3, location=(ct_x + x*0.3, ct_y + -vlen*0.3/2, 3.5))
bpy.ops.mesh.primitive_cube_add(size=0.3, location=(ct_x + x*0.3, ct_y + vlen*0.3/2, 3.5))
## === hodoukyo stairs part
bpy.ops.mesh.primitive_cube_add(size=1, location=(-49, 70, 1.3))
bpy.ops.transform.resize(value=(6, 2, 0.3))
# URL https://suzulang.com/blender-2-8-python-rotate/
# objに現在のアクティブなオブジェクトを指定する
obj = bpy.context.active_object
def rotate_object(rot_mat):
# decompose world_matrix's components, and from them assemble 4x4 matrices
orig_loc, orig_rot, orig_scale = obj.matrix_world.decompose()
#
orig_loc_mat = Matrix.Translation(orig_loc)
orig_rot_mat = orig_rot.to_matrix().to_4x4()
orig_scale_mat = (Matrix.Scale(orig_scale[0],4,(1,0,0)) @
Matrix.Scale(orig_scale[1],4,(0,1,0)) @
Matrix.Scale(orig_scale[2],4,(0,0,1)))
#
# assemble the new matrix
obj.matrix_world = orig_loc_mat @ rot_mat @ orig_rot_mat @ orig_scale_mat
# Matrix.Rotationで回転行列を作成
# Matrix.Rotation( ラジアンの回転角 , 4 , 回転軸 )
# 4 は4x4行列の意味
# 回転軸は(x,y,z)形式の他に 'X' や 'Y' や'Z' のように軸名を指定することもできる
rotate_object( Matrix.Rotation( radians(30), 4, (0,1,0) ) )
## === end of hodoukyo
# ===== road
bpy.ops.mesh.primitive_plane_add(size=2, enter_editmode=False, align='WORLD', location=(-7, 90, 0), scale=(1, 1, 1))
bpy.ops.transform.resize(value=(3, 200, 1))
bpy.ops.mesh.primitive_plane_add(size=2, enter_editmode=False, align='WORLD', location=(-0.6, 120, 0), scale=(1, 1, 1), rotation=(0.0, 0.0, -6/180*3.14))
bpy.ops.transform.resize(value=(100, 1, 1))
# Add a plane for ground ==================
bpy.ops.mesh.primitive_plane_add(size=400.0, align='WORLD', location=(0.0, 0.0, -0.5), rotation=(0.0, 0.0, 0.0) )
matp = bpy.data.materials.new('Plane')
matp.diffuse_color = (0.08, 0.08, 0.03, 0)
obj = bpy.context.view_layer.objects.active
obj.data.materials.append(matp)
# ================== world - surface - background (背景)
bpy.data.worlds["World"].node_tree.nodes["Background"].inputs[0].default_value = (0.01, 0.15, 0.25, 1)
bpy.data.worlds["World"].node_tree.nodes["Background"].inputs[1].default_value = 0.7
# ============== "light"
# create light datablock, set attributes
#light_data = bpy.data.lights.new(name="light_spot1", type='SPOT')
light_data = bpy.data.lights.new(name="light_spot1", type='SUN')
light_data.energy = 5
# create new object with our light datablock
light_object1 = bpy.data.objects.new(name="light_spot1", object_data=light_data)
# link light object
bpy.context.collection.objects.link(light_object1)
# make it active
bpy.context.view_layer.objects.active = light_object1
#change location
light_object1.location = (20, -10, 50)
light_object1.delta_rotation_euler = (1.3, 0, 0.3) #ゼロゼロゼロで真下を向く。
# update scene, if needed
dg = bpy.context.evaluated_depsgraph_get()
dg.update()
light_data = bpy.data.lights.new(name="light_spot2", type='SPOT')
light_data.energy = 20000
# create new object with our light datablock
light_object2 = bpy.data.objects.new(name="light_spot2", object_data=light_data)
# link light object
bpy.context.collection.objects.link(light_object2)
# make it active
bpy.context.view_layer.objects.active = light_object2
#change location
light_object2.location = (-20, 60, 40)
light_object2.delta_rotation_euler = (0.1, 0, 0.3) #ゼロゼロゼロで真下を向く。
# update scene, if needed
dg = bpy.context.evaluated_depsgraph_get()
dg.update()
light_data = bpy.data.lights.new(name="light_spot3", type='SPOT')
light_data.energy = 20000
# create new object with our light datablock
light_object3 = bpy.data.objects.new(name="light_spot3", object_data=light_data)
# link light object
bpy.context.collection.objects.link(light_object3)
# make it active
bpy.context.view_layer.objects.active = light_object3
#change location
light_object3.location = (-50, 60, 40)
light_object3.delta_rotation_euler = (0.1, 0, 0.3) #ゼロゼロゼロで真下を向く。
# update scene, if needed
dg = bpy.context.evaluated_depsgraph_get()
dg.update()
# ================
#======= KOI HONMACHI Map ======
bpy.ops.object.load_reference_image(filepath="/Users/nh7/Dropbox/blenderF/bpykmapR2.jpg")
bpy.context.active_object.name = 'plane_map1'
bpy.context.object.scale[0] = 106
bpy.context.object.scale[1] = 106
bpy.context.object.location[0] = -58.6
bpy.context.object.location[1] = 70.7
#======= KOI HONMACHI Map ======END
#======= car body manufacturing start
bpy.ops.mesh.primitive_cube_add(size=1, location=(0, 0, 0), scale=(1, 1, 1))
bpy.context.active_object.name = 'b_base'
bpy.ops.transform.resize(value=(1.5,3.4,0.9))
bpy.ops.mesh.primitive_plane_add(size=1, location=(0, -0.45, 0.4))
bpy.context.active_object.name = 'b_top'
bpy.ops.object.editmode_toggle()
bpy.ops.mesh.inset(thickness=0.1, depth=0.6)
bpy.ops.object.editmode_toggle()
bpy.ops.transform.resize(value=(1.5,2.5,1))
bpy.data.objects['b_base'].select_set(True)
bpy.data.objects['b_top'].select_set(True)
for x in bpy.context.selected_objects: # same COLOR on tires and body
objdd = x.data
mat = bpy.data.materials.new('Car_color')
#h = 0xdc143c ###0xdc143c= crimson
h = 0x800000 #ox800000=maroon
mat.diffuse_color = (*hex_to_rgb(h), 1) #====== COLOR
objdd.materials.append(mat)
bpy.data.objects['b_base'].select_set(False)
bpy.data.objects['b_top'].select_set(False)
bpy.ops.mesh.primitive_cylinder_add(vertices=16, radius=0.3 , depth=1.6, end_fill_type='NGON', location=(0,1.0,-0.3) )
bpy.context.active_object.name = 'tire_fr'
bpy.ops.transform.rotate(value=90/180*3.14, orient_axis='Y' )
bpy.ops.mesh.primitive_cylinder_add(vertices=16, radius=0.3 , depth=1.6, end_fill_type='NGON', location=(0,-1.2,-0.3) )
bpy.context.active_object.name = 'tire_rr'
bpy.ops.transform.rotate(value=90/180*3.14, orient_axis='Y' )
bpy.data.objects['tire_fr'].select_set(True)
bpy.data.objects['tire_rr'].select_set(True)
for x in bpy.context.selected_objects: # same COLOR on tires and body
objdd = x.data
mat = bpy.data.materials.new('Car_color')
h = 0x2f4f4f ###gray?????darkslategray
mat.diffuse_color = (*hex_to_rgb(h), 1) #====== COLOR
objdd.materials.append(mat)
bpy.data.objects['b_base'].select_set(True)
bpy.data.objects['b_top'].select_set(True)
bpy.data.objects['tire_fr'].select_set(True)
bpy.data.objects['tire_rr'].select_set(True)
bpy.ops.object.join()
bpy.context.active_object.name = 'joined_car1'
bpy.data.objects['joined_car1'].select_set(True)
#======= END of car body manufacturing
# ================ CAR movement with KEY FRAME (2024.5.17)
bpy.context.scene.frame_start = 1
bpy.context.scene.frame_end = 60
bpy.context.scene.frame_current = 10
#== moveloc_xyz_list[frameNumber, x, y, z, z_ax_rot]
moveloc_xyz_list = [[1, -8,-9,1,0], [10,-8,15,1,0], [20,-8,53,1,-2], [22,-10,59,1,-30],
[25,-14,60,1,-30], [40,-30,64,1,-30],[50,-45,65,1,0],[60,-65,65,1,0]]
bpy.data.objects['joined_car1'].select_set(True)
objects = bpy.data.objects
for i in range(len(moveloc_xyz_list)):
frame_num=moveloc_xyz_list[i][0]
xloc= moveloc_xyz_list[i][1]
yloc= moveloc_xyz_list[i][2]
zloc= moveloc_xyz_list[i][3]
z_ax_rot=moveloc_xyz_list[i][4]
bpy.context.scene.frame_set(frame_num) # set frame to frame_num
objects['joined_car1'].location = (xloc, yloc, zloc) # set location
bpy.ops.transform.rotate(value=z_ax_rot/180*3.14, orient_axis='Z' )
bpy.ops.anim.keyframe_insert_menu(type='Location') # KEY FRAME
bpy.ops.anim.keyframe_insert_menu(type='Rotation')
bpy.ops.transform.rotate(value=0, orient_axis='Z' )
#==== end of CAR movement (2024.5.17)
# ================ make a new CURVE for camera movement
# ==== nunoheya BEGIN
curvedata = bpy.data.curves.new("my curve", type='CURVE')
curvedata.dimensions = '3D'
polyline = curvedata.splines.new('BEZIER')
polyline.bezier_points.add(2) # 制御点数ー1個
polyline.bezier_points[0].co = -1,-61,18
polyline.bezier_points[0].handle_left = -1,-74,18
polyline.bezier_points[0].handle_right = -6,-45,18
polyline.bezier_points[1].co = 0,30,18
polyline.bezier_points[1].handle_left = -3,15,18
polyline.bezier_points[1].handle_right = 0,43,18
polyline.bezier_points[2].co = -18,62,20
polyline.bezier_points[2].handle_left = 0,58,20
polyline.bezier_points[2].handle_right = -30,62,20
obj = bpy.data.objects.new("my bezier", curvedata)
# 新しいCollectionを作成
newCol = bpy.data.collections.new('Collection 1')
# 現在のシーンにコレクションをリンク
bpy.context.scene.collection.children.link(newCol)
# コレクションにオブジェクトをリンク
newCol.objects.link(obj)
# ==== nunoheya END
# ================== = camera movement
#bpy.ops.curve.primitive_bezier_circle_add(enter_editmode=False, align='WORLD', location=(20, 20, 30))
bpy.ops.object.empty_add(type='CUBE', align='WORLD', location=(0,0,0))
bpy.ops.object.camera_add(enter_editmode=False, align='VIEW', location=(0,0,0), rotation=(0, 0, 0))
bpy.data.objects['Empty'].select_set(True)
bpy.data.objects['Camera'].select_set(True)
bpy.context.view_layer.objects.active = bpy.data.objects['Empty']
bpy.ops.object.parent_set(type='OBJECT')
bpy.data.objects['Camera'].select_set(False)
bpy.data.objects['Empty'].select_set(True)
bpy.ops.object.constraint_add(type='FOLLOW_PATH')
#bpy.context.object.constraints["Follow Path"].target = bpy.data.objects["BezierCircle"]
bpy.context.object.constraints["Follow Path"].target = bpy.data.objects["my bezier"]
bpy.context.object.constraints["Follow Path"].use_curve_follow = True
bpy.context.object.constraints["Follow Path"].use_fixed_location = True
bpy.data.objects['Empty'].select_set(False)
bpy.data.objects['Camera'].select_set(True)
bpy.ops.object.constraint_add(type='TRACK_TO')
#bpy.context.object.constraints["Track To"].target = bpy.data.objects["Cube.016"]
bpy.context.object.constraints["Track To"].target = bpy.data.objects["joined_car1"]
bpy.context.object.constraints["Track To"].up_axis = 'UP_Y'
bpy.context.object.constraints["Track To"].track_axis = 'TRACK_NEGATIVE_Z' #5m00sec
#Camera Keyframe #(Insert keyframe to object's Offset Factor Python API - stack exchange)
bpy.data.objects['Camera'].select_set(False)
bpy.data.objects['Empty'].select_set(True)
bpy.context.scene.frame_current = 1
bpy.context.object.constraints["Follow Path"].offset_factor = 0
ob = bpy.context.object
# ob.constraints['Follow Path']
# bpy.data.objects['Empty'].constraints["Follow Path"]
# [bpy.data.objects['Empty'].constraints["Follow Path"]]
con = ob.constraints.get("Follow Path")
con.offset_factor = 0.0
con.keyframe_insert("offset_factor", frame=1)
con.offset_factor = 0.25
con.keyframe_insert("offset_factor", frame=12)
con.offset_factor = 0.50
con.keyframe_insert("offset_factor", frame=18)
con.offset_factor = 0.70
con.keyframe_insert("offset_factor", frame=30)
con.offset_factor = 0.80
con.keyframe_insert("offset_factor", frame=50)
con.offset_factor = 0.99
con.keyframe_insert("offset_factor", frame=60)
# ==== END of camera movement
# ======== to EDIT mode, then OBJECT mode ===
#「# 編集モードへの移行」2.8向けに2行ほど改良。
# 編集モードへの移行
# 引数 arg_objectname:指定オブジェクト名
# 戻り値
def set_mode_edit(arg_objectname='Default'):
# 他のオブジェクトに操作を適用しないよう全てのオブジェクトを走査する
for ob in bpy.context.scene.objects:
# 非選択状態に設定する
#ob.select=False #blender2.7
ob.select_set(False)
# 指定オブジェクトを取得する
selectob = bpy.data.objects[arg_objectname]
# 変更オブジェクトをアクティブに変更する
#bpy.context.scene.objects.active = selectob #blender2.7
bpy.context.view_layer.objects.active = selectob
#
# 編集モードに移行する
bpy.ops.object.mode_set(mode='EDIT', toggle=False)
return
# 関数の実行例
set_mode_edit('my bezier')
# =====
#「# オブジェクトモードへの移行」2.8向けに2行ほど改良。
# オブジェクトモードへの移行
# 引数 arg_objectname:指定オブジェクト名
# 戻り値
def set_mode_object(arg_objectname='Default'):
# 他のオブジェクトに操作を適用しないよう全てのオブジェクトを走査する
for ob in bpy.context.scene.objects:
# 非選択状態に設定する
#ob.select=False
ob.select_set(False)
# 指定オブジェクトを取得する
selectob = bpy.data.objects[arg_objectname]
# 変更オブジェクトをアクティブに変更する
#bpy.context.scene.objects.active = selectob
bpy.context.view_layer.objects.active = selectob
# オブジェクトモードに移行する
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
return
# 関数の実行例
set_mode_object('my bezier')
# ======== to EDIT mode, then OBJECT mode === END