- Blender Add-on -

Add-on集

ちょっとしたアドオンの作り方がわかってきたので、幾つか公開してみます。
日本語コメント部分は、UTF-8で保存しないとエラーになります。(このページはSJISなのでコピペの際は注意…)
リンク先のファイルは UTF-8のままです。

アドオンのお作法などは見よう見まねなので、そこのとこころはご容赦を…

メッシュ(その他データ)の名前をオブジェクトの名前に合わせる

Cube.001 やら Cylinder.002 など元の名前のまま残っているメッシュデータを、オブジェクトの名前に変更します。
メッシュ以外(ランプなど)にも対応したので、名前を DataRenamer に変更しました。
2つ以上のオブジェクトで共用されているメッシュデータの場合は、確認用ポップアップが出てくるので、そこで再度押すと実行されます。

DataRenamer.py

# Blender内部のデータ構造にアクセスするために必要
import bpy
import mathutils

# プラグインに関する情報
bl_info = {
    "name" : "DataRenamer",             # プラグイン名
    "author" : "Q@StudioPotpourri",     # 作者
    "version" : (0,4),                  # プラグインのバージョン
    "blender" : (2, 7, 7),              # プラグインが動作するBlenderのバージョン
    "location" : "Properties > Object > DataRenamer",   # Blender内部でのプラグインの位置づけ
    "description" : "Rename mesh",   # プラグインの説明
    "warning" : "",
    "wiki_url" : "",                    # プラグインの説明が存在するWikiページのURL
    "tracker_url" : "",                 # Blender Developer OrgのスレッドURL
    "category" : "Object"                   # プラグインのカテゴリ名
    }

class RenamerForce(bpy.types.Operator):
    """RenamerForce"""
    bl_idname = "object.renamerforce"
    bl_label = "RenameForce"
    bl_options = {'UNDO'}

    def execute(self, context):
        object = context.object
        name = object.name
        object.data.name = name
        
        return {'FINISHED'}

class Renamer(bpy.types.Operator):
    """Renamer"""

    bl_idname = "object.renamer"
    bl_label = "DataRenamer"
    bl_options = {'REGISTER','UNDO'}

    def invoke(self, context, event):
        object = context.object
        name = object.name

        if (object.name == object.data.name):
            return {'CANCELLED'}

        if (object.data.users == 1):
            return self.execute(context)
        else:
            return context.window_manager.invoke_props_popup(self, event)
        
        return {'CANCELLED'}

    def execute(self, context):
        object = context.object
        name = object.name;
        if (object.data.users == 1):
            object.data.name = name;
        
        return {'FINISHED'}

    def draw(self, context):
        layout = self.layout
        object = context.object
        data = context.object.data

        if (object.name == data.name):
            return

        col = layout.column()
        col.label(text="Data \"" + object.data.name + "\" has " + str(object.data.users) + " users.")
        col.operator("object.renamerforce", text="Rename it to \"" + object.name + "\" even so")

class OBJECT_PT_DataRenamer(bpy.types.Panel):
    bl_label = "DataRenamer"
    bl_space_type = "PROPERTIES"
    bl_region_type = "WINDOW"
    bl_context = "object"

    @classmethod
    def poll(cls, context):
        return (context.object.type == 'MESH' or context.object.type == 'LAMP' or context.object.type == 'CAMERA' or context.object.type == "CURVE")

    def draw(self, context):
        
        layout = self.layout
        object = context.object
        data = context.object.data
        
        l_row = layout.row();
        l_row.label(text=object.name, icon='OBJECT_DATA')
        if (object.type == 'MESH'):
            l_row.label(text=data.name, icon='MESH_DATA')
        if (object.type == 'CAMERA'):
            l_row.label(text=data.name, icon='CAMERA_DATA')
        if (object.type == 'CURVE'):
            l_row.label(text=data.name, icon='CURVE_DATA')
        if (object.type == 'LAMP'):
            if (data.type == 'POINT'):
                l_row.label(text=data.name, icon='LAMP_POINT')
            if (data.type == 'SUN'):
                l_row.label(text=data.name, icon='LAMP_SUN')
            if (data.type == 'SPOT'):
                l_row.label(text=data.name, icon='LAMP_SPOT')
            if (data.type == 'HEMI'):
                l_row.label(text=data.name, icon='LAMP_HEMI')
            if (data.type == 'AREA'):
                l_row.label(text=data.name, icon='LAMP_AREA')
            
        if (object.name == data.name and data.users == 1):
            l_row.label(text="users=" + str(data.users), icon='FILE_TICK')
        else:
            l_row.label(text="users=" + str(data.users), icon='DOT')
            if (object.name != data.name):
                layout.operator("object.renamer", text="Rename Single User Data")

def register():
    bpy.utils.register_module(__name__)

def unregister():
    bpy.utils.unregister_module(__name__)

if __name__ == "__main__":
    register()


ランダムに選択解除しながら Extrude を繰り返す

選択されている面をランダムに選択解除しながら Extrude を繰り返し、このような構造を作ります。
メッシュ分割された平面に適応すれば、このように簡易的な都市のような構造になります。
3D View の左側、メッシュツール内に登録されます。繰り返し回数や、一ステップごとの選択解除の確率を設定します。

Type: の選択肢は、上のような形状ではNormal方向へ伸ばすタイプ、下の街のような構造では Z directional を選びます。
(街のような構造の場合Normalでも見た目は一緒なのですが、ブロック境界のポリゴンに無駄が生じます)

RandomExtrude.py

# Blender内部のデータ構造にアクセスするために必要
import bpy
import mathutils
# Tool Self でプロパティ変更
from bpy.props import * 

# プラグインに関する情報
bl_info = {
    "name" : "Random Extrude",             # プラグイン名
    "author" : "Q@StudioPotpourri",                  # 作者
    "version" : (0,3),                  # プラグインのバージョン
    "blender" : (2, 7, 7),              # プラグインが動作するBlenderのバージョン
    "location" : "Mesh > Random Extrude",   # Blender内部でのプラグインの位置づけ
    "description" : "Repeat random deselect and extrude",   # プラグインの説明
    "warning" : "",
    "wiki_url" : "",                    # プラグインの説明が存在するWikiページのURL
    "tracker_url" : "",                 # Blender Developer OrgのスレッドURL
    "category" : "Mesh"                   # プラグインのカテゴリ名
    }

# メニュー
class CRandomExtrude(bpy.types.Operator):

    bl_idname = "mesh.random_extrude"      # ID名
    bl_label = "Random Extrude"            # メニューに表示される文字列
    bl_description = "Random Extrude"      # メニューに表示される説明文
    bl_options = {'REGISTER', 'UNDO'}

    # ツールシェルフへ表示させる値
    repeat = IntProperty(
        name = "Repeat",             
        description = "repeat ...",   
        default = 3,                    
        min = 0,                     
        max = 99)  

    deselectFirst = IntProperty(
        name = "First",    
        description = "Deselect Percent ...", 
        default = 0,
        subtype = 'PERCENTAGE',
        min = 0,                  
        max = 100)                    

    deselect = IntProperty(
        name = "",    
        description = "Deselect Percent ...", 
        default = 40,         
        subtype = 'PERCENTAGE',
        min = 0,                  
        max = 100) 

    seed = IntProperty(
        name = "Random seed",           
        description = "Random Seed ...",
        default = 3,
        min = 0)

    height = FloatProperty(
        name = "Step height",
        description = "lineSkip ...",
        default = 1,
        min = 0)

    Types = [("0", "Normal", "Normal"),
             ("1", "Z directional", "Z directional")]
    
    NormalTypes = EnumProperty(name="Type",
                               description ="Type",
                               items=Types)

    def draw(self, context):
        layout = self.layout;

        layout.prop(self, "repeat")
        layout.label("Deselect Percent:")
        row = layout.row()
        row.prop(self, "deselectFirst")
        row.prop(self, "deselect")

        layout.prop(self, "seed")
        layout.prop(self, "height")
        layout.prop(self, "NormalTypes")
        layout.prop(self, "normal")

    # 実際にプラグインが処理を実施する処理
    def execute(self, context):

        for num in range(0, self.repeat):
            deselect = self.deselect
            if num == 0:
                deselect = self.deselectFirst
            bpy.ops.mesh.select_random(percent=deselect, seed=self.seed, action='DESELECT')
            if int(self.NormalTypes) == 1:
                bpy.ops.mesh.extrude_region_move(TRANSFORM_OT_translate={"value":(0, 0, self.height)})
            else:
                bpy.ops.mesh.extrude_faces_move(TRANSFORM_OT_shrink_fatten={"value":-self.height})

        return {'FINISHED'}             # 成功した場合はFINISHEDを返す

# メニューを登録する関数
def menu_func(self, context):
    self.layout.label("Random Extrude:")
    self.layout.operator(CRandomExtrude.bl_idname)     # 登録したいクラスの「bl_idname」を指定

# プラグインをインストールしたときの処理
def register():
    bpy.utils.register_module(__name__)
    bpy.types.VIEW3D_PT_tools_meshedit.append(menu_func)

# プラグインをアンインストールしたときの処理
def unregister():
    bpy.utils.unregister_module(__name__)
    bpy.types.VIEW3D_PT_tools_meshedit.remove(menu_func)

# メイン関数
if __name__ == "__main__":
    register()

inserted by FC2 system