Super Kawaii Cute Cat Kaoani Blender에서 python api 사용하기(operator_simple.py 분석)

연구/Blender

Blender에서 python api 사용하기(operator_simple.py 분석)

치킨고양이짱아 2023. 3. 17. 16:08
728x90
728x90

Blender에서 기본적으로 제공하는 많은 기능들이 있지만, 그 기능들을 조합해서 실행하거나 나만의 기능을 만들고 싶을 때가 있다. 이때 "기능"이라고 하는 것을 Blender에서는 보통 operator라고 부른다.

Blender의 python templates의 operator_simple.py 코드를 분석해보고

operator를 어떤식으로 만들어야하는지 살펴보자.

import bpy


def main(context):
    for ob in context.scene.objects:
        print(ob)


class SimpleOperator(bpy.types.Operator):
    """Tooltip"""
    bl_idname = "object.simple_operator"
    bl_label = "Simple Object Operator"

    @classmethod
    def poll(cls, context):
        return context.active_object is not None

    def execute(self, context):
        main(context)
        return {'FINISHED'}


def menu_func(self, context):
    self.layout.operator(SimpleOperator.bl_idname, text=SimpleOperator.bl_label)


# Register and add to the "object" menu (required to also use F3 search "Simple Object Operator" for quick access).
def register():
    bpy.utils.register_class(SimpleOperator) 
    bpy.types.VIEW3D_MT_object.append(menu_func)


def unregister():
    bpy.utils.unregister_class(SimpleOperator)
    bpy.types.VIEW3D_MT_object.remove(menu_func)


if __name__ == "__main__":
    register()

    # test call
    bpy.ops.object.simple_operator()

 

1. operator 등록하기

일단, 하단쪽을 보면 register() 함수를 호출하고 있는데

register 함수 내부를 살펴보면,

bpy.utils.register_class(SimpleOperator)

이런 구문이 있다. bpy.utils.register_class는 사용자가 정의한 operator를 blender에 등록하는 것으로 인자로 사용자가 정의한 operator class의 이름을 넘겨주면 된다.

이렇게 만든 operator를 blender에 등록을 해줘야 사용이 가능하다.

 

2. bl_idname, bl_label

class SimpleOperator(bpy.types.Operator):
    """Tooltip"""
    bl_idname = "object.simple_operator"
    bl_label = "Simple Object Operator"

사용자 정의 operator를 만들 때는 꼭 bpy.types.Operator의 상속을 받아야한다.

bl_idname bl_label은 operator class끼리의 구분을 짓기 위해 사용하는 변수들이다.

bpy.types.Operator의 상속을 받는 Operator를 정의하면서 이값을 재설정해주지 않으면 새롭게 만든 operator의 bl_idname과 bl_label이 기본값을 가지기 때문에 꼭 재설정을 해주어야한다.

bl_label은 F3를 눌러 내가 만든 operator를 검색할 때 사용하는 문자열이다.

 

3. poll 함수

@classmethod
def poll(cls, context):
    return context.active_object is not None

poll 함수는 bpy.types.Operator에서 정의된 함수인데 여기서 오버라이딩을 하고 있다.

poll 함수는 조건을 따져서 operator를 실행할지 안할지 결정하는 역할을 한다.

True 또는 False 값을 return 한다. 만약 poll 함수에서 False가 return되면 operator의 실제 기능이 담겨있는 execute 함수는 실행하지 않고 operator를 종료하게 된다.

context는 현재의 상태를 담고 있는 변수라고 생각하면 된다. 그리고 context.active_object는 현재 상태에서 활성화된 object들을 나타낸다. 즉, SimpleOperator는 현재 활성화된 object가 있을때만 의도한 기능을 수행한다.

 

4. execute 함수

def execute(self, context):
    main(context)
    return {'FINISHED'}

execute 함수는 poll과 마찬가지로 bpy.types.Operator에서 정의된 함수인데 여기서 오버라이딩을 하고 있다.

execute 함수는 operator를 실행하면 수행할 작업들을 수행하고 operator를 종료하는 역할을 하는 함수이다.

g 키를 누르고 object를 움직일때처럼, 사용자의 입력을 처리하는 동안 operator를 종료하지 않고 유지해야하는 경우에는 execute 함수를 실행하지 않는다.

실행 즉시 결과를 도출하고 operator를 종료하는 경우에만 execute 함수를 실행한다.

위의 execute 함수에서는 main이라는 이름의 함수를 호출하고 있다.

def main(context):
    for ob in context.scene.objects:
        print(ob)

context.scene.objects는 현재의 장면에 포함된 모든 object를 의미한다.

 

5. Run script

위의 operator_simple.py 스크립트를 Run script 시키면 사용자가 정의한 operator를 test로 한번 실행하게 된다. 이는 f3 키를 눌러 사용자가 operator를 실행하는 것이 아니라 스크립트를 이용하여 바로 opeartor를 실행시키는 것이다!

if __name__ == "__main__":
    register()

    # test call
    bpy.ops.object.simple_operator()

SimpleOperator에서 정의해주었던 bl_idname으로 접근하여 operator를 호출한다.

bpy.ops.bl_idname() : 이런식으로 operator를 직접 호출할 수 있다. 이게 script에서 operator를 실행시키는 기본적인 방법이므로 꼭 암기해야 한다.

script를 실행시키게 되면 script가 실행되었다는 내용을 왼쪽 하단의 info 편집기에서 확인할 수 있다.

맨 아래쪽에 run_script라는 내용을 보면 스크립트가 잘 돌아갔음을 확인할 수 있다.

그리고 execute 함수 내부를 보면 main문을 호출하는데 그 main 문에서는 object들의 이름을 하나씩 출력하고 있다. 출력결과는 시스템 콘솔에서 확인할 수 있다.

 

6. Operator 만들어보기

위에서 배운 내용들을 바탕으로 object들의 위치를 x축으로 1만큼 옮기는 코드를 짜보았다.

import bpy


def main(context):
    for ob in context.scene.objects:
        ob.location.x += 1


class MyOperator(bpy.types.Operator):
    """Tooltip"""
    bl_idname = "object.my_operator"
    bl_label = "My Test Operator"

    @classmethod
    def poll(cls, context):
        return context.active_object is not None

    def execute(self, context):
        main(context)
        return {'FINISHED'}


def menu_func(self, context):
    self.layout.operator(SimpleOperator.bl_idname, text=SimpleOperator.bl_label)


def register():
    bpy.utils.register_class(MyOperator)
    bpy.types.VIEW3D_MT_object.append(menu_func)


def unregister():
    bpy.utils.unregister_class(MyOperator)
    bpy.types.VIEW3D_MT_object.remove(menu_func)


if __name__ == "__main__":
    register()

보통의 operator의 경우에는 실행할때 버튼이나 단축키를 사용하지만, 우리는 아직 그와 관련된 코드를 짜지 않았기 때문에 operator를 실행하기 위해서는 F3 단축키를 통해 operator를 직접 실행해야한다.

F3 단축키를 눌러 "My Test Operator"를 검색하고 실행시키면 scene에 포함된 모든 object들의 위치가 x축에 대해 1만큼 증가하게 된다.

 

 

 

728x90
728x90