Blenderのテクスチャを他のソフトで作成している場合に
画像の更新のために手動で更新をするのも煩わしいので
データの更新を検出して再読み込みをさせるアドオンを作成しました
その使用法とPhotoshopの便利な機能「画像アセット」について解説したいと思います
Photoshopの「画像アセット」
Photoshopにはレイヤにつけた名前に従って自動的に画像を書き出す機能があります。
例えば グループレイヤに01.png 02.pngと名前をつけておくと
PSDの保存されている場所にPSDの名前に-assetsとついたフォルダが作られて
それぞれのグループを統合した画像で 01.png 02.png といった感じに出力されます
PSDのレイヤを編集するとその都度変更が自動出力されます
Web用の機能なので 3Dのテクスチャ用で出力できる種類はPNGのみですが
自動的に出力されるのは便利かと思います。
ファイルの名前の付け方によっては 画像を縮小したりもできます
Blenderの自動更新アドオン
さて、冒頭に話をした自動更新アドオンです。
Blenderに読み込んでいる画像ファイルの更新を検出して再読み込みします
他にも同様な機能なものはあるようですが、ミニマムな構成にしてみました。
長いデータなので
boothにダウンロード用ファイルを登録しました
bl_info = {
"name" : "AutoReloadImage",
"author" : "Yukimituki",
"description" : "",
"blender" : (2, 80, 0),
"version" : (0, 0, 1),
"location" : "",
"warning" : "",
"category" : "Image"
}
import bpy
import os
from bpy.types import (
PropertyGroup,
AddonPreferences,
)
class IMAGE_PT_AutoReload(bpy.types.Panel):
bl_idname = "autoreload.panel"
bl_label = "Reload Images"
bl_space_type = "IMAGE_EDITOR"
bl_region_type = "UI"
bl_category = "Image"
# 描画の定義
def draw(self, context):
layout = self.layout
row = layout.row()
row.prop(context.scene, "imageassets_autoreload_time")
row = layout.row()
row.prop(context.scene, "imageassets_autoreload_active")
row = layout.row()
row.operator("image.reloadbutton")
class ModalTimerOperator(bpy.types.Operator):
"""Operator which runs its self from a timer"""
bl_idname = "wm.modal_timer_operator"
bl_label = "Modal Timer Operator"
_timer = None
asset_dic = {}
def __init__(self):
asset_dic = self.asset_dic
self.asset_dic = set_asset_dic(asset_dic)
def modal(self, context, event):
#check ImageEditor panel value
if not context.scene.imageassets_autoreload_active:
context.window_manager.event_timer_remove(self._timer)
return {'FINISHED'}
if event.type == 'TIMER':
asset_dic = self.asset_dic
reload_assets(asset_dic)
self.asset_dic = set_asset_dic(asset_dic)
return {'PASS_THROUGH'}
def execute(self, context):
wm = context.window_manager
reload_cycle = context.scene.imageassets_autoreload_time
self._timer = wm.event_timer_add(reload_cycle, window=context.window)
wm.modal_handler_add(self)
self.asset_dic = set_asset_dic({})
return {'RUNNING_MODAL'}
def cancel(self, context):
wm = context.window_manager
wm.event_timer_remove(self._timer)
#手動リロード処理
class OBJECT_OT_reloadbutton(bpy.types.Operator):
bl_idname = "image.reloadbutton"
bl_label = "Manually update"
def execute(self, context):
for img in bpy.data.images:
#only single image file
if img.type != 'IMAGE': continue
img.reload()
set_asset_dic({})
return {'FINISHED'}
#自動リロード処理
def reload_assets(asset_dic):
for image_obj in asset_dic:
try:
#only single image file
if image_obj.type != 'IMAGE': continue
image_path = bpy.path.abspath(image_obj.filepath)
#チェック時にファイル保存が重なると一時的にファイルが認識できないため
if os.path.lexists(image_path) == False: continue
#更新時刻の取得 get modefied time
mod_time = os.stat(image_path).st_mtime_ns
if mod_time != asset_dic[image_obj]:
image_obj.reload()
asset_dic[image_obj] = mod_time
print("reload:%s" % image_obj.name )
except:pass
#ファイル内のイメージデータブロックの情報を記録
def set_asset_dic(asset_dic):
if len(bpy.data.images) == len(asset_dic): return(asset_dic)
for img in bpy.data.images:
if img.type != 'IMAGE':
image_path = bpy.path.abspath(img.filepath)
#get modefied time as nanosec(int)
asset_dic[img] = os.stat(image_path).st_mtime_ns
else:asset_dic[img] = 0
return(asset_dic)
def update_bool_func(self, context):
if context.scene.imageassets_autoreload_active:
bpy.ops.wm.modal_timer_operator()
classes = (
ModalTimerOperator,
IMAGE_PT_AutoReload,
OBJECT_OT_reloadbutton
)
#アドオンとして機能させるための情報の登録
def register():
#properties
Scene = bpy.types.Scene
props = bpy.props
Scene.imageassets_autoreload_active = props.BoolProperty(name="Auto Reload", description="", default=False, update = update_bool_func)
Scene.imageassets_autoreload_time = props.IntProperty(name="Reload Cycle",description="", default=10 )
#classes
for cls in classes:
bpy.utils.register_class(cls)
#アドオンを停止させた時に情報の削除
def unregister():
#properties
Scene = bpy.types.Scene
props = bpy.props
del Scene.imageassets_autoreload_active
del Scene.imageassets_autoreload_time
#classes
for cls in classes:
bpy.utils.unregister_class(cls)
if __name__ == "__main__":
register()
(Blender2.8用ですが5行目の "blender" : (2, 80, 0),の数字を(2,29,0)に書き換えることで2.79でも動作します )
アドオンとして読み込むと
画像エディッタやUVエディッタの画像タブに「Reload Images」の項目が出ます
Auto ReloadのチェックボックスをオンにするとReload Cycleの秒数毎にファイルをチェックしますManually updateのボタンで手動で更新することもできます。
先にPhotoshopの話をしましたが 画像ファイルの更新日時を検出する動作ですので
画像を作成するソフトは何でも構いません。
ゲームのモデル等 テクスチャを描く作業をしている人お役に立てれば幸いです。