読者です 読者をやめる 読者になる 読者になる

水深1mm

広く浅い個人的メモ。

非等幅フォントのBMFont出力を等幅に変換するスクリプト

nyahoon.com

ということらしい。のでコレをpythonで処理。

BMFontで出力した.fntファイルのパスを引数にして実行。
出力は同階層に.fnt.outで出力される。

# -*- coding: utf-8 -*-

import sys
import re

if __name__ == '__main__':
    font_file = sys.argv[1]
    print 'target_file : ', font_file

    font_data = open(font_file, mode='r')
    output_data = open(font_file + '.out', mode='w')

    fix_width = 66
    for data in font_data.readlines():
        if 'xoffset' in data and 'xadvance' in data:
            ofs, adv = re.findall('xoffset=(.?\d+).*xadvance=(.?\d+)', data)[0]

            if fix_width > int(adv):
                data = data.replace('xoffset=' + ofs, 'xoffset=' + str((int(fix_width) - int(adv)) / 2 + int(ofs)))
                data = data.replace('xadvance=' + adv, 'xadvance=' + str(fix_width))

        output_data.writelines(data)

    font_data.close()
    output_data.close()

出力されたものを

github.com

で使用し、Unityのカスタムフォントとして等幅表示されることを確認。

PySideとwatchdogを使用したフォルダ監視ツール

開発環境

  • python3.4(多分)
  • PySide・watchdogインストール済み

folder_killer

https://drive.google.com/file/d/0B4fmLEFqtND0X2ljRXJ1bkZyeEk/view?usp=docslist_api

  • 名前がfolder_killerだけどサンプルのため削除機能は現在無効にしている。
  • 普段とは違う環境からの投稿のため動作未検証。
# -*- coding: utf-8 -*-

from PySide.QtGui import QListWidgetItem

import os
import json
import sys
import time
import shutil
from PySide import QtGui, QtCore
from ui_MainWindow import *

from watchdog.observers import Observer
from watchdog.events import PatternMatchingEventHandler, FileSystemEvent, FileSystemEventHandler


_TARGET_DIR_NAMES = ['targetA', 'targetB', 'targetC', 'targetD']
# _TARGET_DIR_NAMES = None


class MainWindow(QtGui.QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()

        self.__ui = Ui_MainWindow()
        self.__ui.setupUi(self)

        self.show()

        self.__ui.select_watch_btn.clicked.connect(self.__on_clicked)
        self.__ui.watch_path.textChanged.connect(self.__on_path_changed)

        self.__observer = Observer()
        pass

    def __on_clicked(self):
        # print('on_btn_clicked')

        path = QtGui.QFileDialog.getExistingDirectory(self, 'Open Directory', os.path.expanduser('~') + '/Desktop')
        if path:
            self.__ui.watch_path.setText(path)
        pass

    def __on_path_changed(self, text):
        # print('on_path_changed : ', text)

        if os.path.exists(text):
            #  起動中のスレッドを停止してから新たにObserver作成
            if self.__observer.is_alive():
                self.__observer.stop()
                self.__observer.join()

            print('Watch Path Changed: ', text)
            self.__observer = Observer()
            self.__observer.schedule(Killer(_TARGET_DIR_NAMES), text, True)
            self.__observer.start()
        pass

    def closeEvent(self, *args, **kwargs):
        if self.__observer.is_alive():
            self.__observer.stop()
            self.__observer.join()
        pass


class Killer(FileSystemEventHandler):
    def __init__(self, targets):
        self.__targets = targets

    def on_created(self, event):
        """
        @type event: FileSystemEvent
        """

        if os.path.basename(event.src_path) in self.__targets and event.is_directory:
            print('CreatedFolder : ', event.src_path)

            # 削除
            # print('Delete : ', event.src_path)
            # shutil.rmtree(event.src_path)
        pass

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    mainWin = MainWindow()
    sys.exit(app.exec_())

UI上で設定又は変更したパスが存在する場所であった場合にobserverのパスのみ変更したかったが、パスだけの変更が(パッと見)出来なかったので、observerそのものを作成しなおしている。

上記スクリプトでは設定したパスの直下に

_TARGET_DIR_NAMES = ['targetA', 'targetB', 'targetC', 'targetD']

で指定したディレクトリが作成された時になんやかんやしていた。

気が向いたらUIキャプチャ追加予定。

テキストファイルのリアルタイム表示

tailコマンドとかだとなんか違った。

必要環境

  • python2.7
  • watchdogインストール済み

watchdogが使えれば3.xでも大丈夫かも。

rtcat.bat & clcat.bat

https://drive.google.com/file/d/0B4fmLEFqtND0WmVGWWZqWHdYYW8/view?usp=sharing

準備

rtcat.batにあるclcat.batのパスを正しいパスに変更する。
後はrtcat.batをdoskey等で登録する。

使用方法

rtcat [*.監視対象ファイルの拡張子] [監視対象ファイル]

拡張子の指定は無くしたいがバッチ処理内で文字の分割が面倒くさいので省略。

Maya2015のサンプルShapeプラグインが表示されない

ShapeNodeのプラグインを作ろうと思ってサンプルのプラグインをビルドして使ってみたら表示されない。

なんでだと思って色々いじってたらビューポート2.0だと表示されない模様。

ShapeNodeとして作ろうとするとかなり面倒くさそうだったことと上記の問題により
普通のNodeとして作ってMELでつなげる感じにした。ひとまずこれで大丈夫そう。

Maya PySide まとめ

準備
  • 公式サイトからpython2.7インストール
  • C:\Python27とC:\Python27\Scriptsを環境変数のPathに追加
  • コマンドラインからPySideインストール

    pip install PySide

ファイル

(12/12追記)MayaQWidgetBaseMixin追加 https://drive.google.com/file/d/0B4fmLEFqtND0SnlEWDhTNkZrTWM/view?usp=sharing

UiSampleScript
│ UiData.py
│ UiSample.py
│ __init__.py
├─.idea
└─ui
  ui2py.py
  UiData.ui

※ .ideaフォルダはPyCharmのプロジェクトファイル

  • __init__.py
    • パッケージとして読み込むために必要
  • UiSample.py
  • UiData.py
    • UiData.uiをpythonに変換したもの
  • ui/UiData.ui
    • QtDesignerで作成したUI情報
  • ui/ui2py.py.ui
    • uiファイルをpyファイルに変換するスクリプト
    • uiファイルをこのファイルにドロップすると一階層上にpy出力
実行方法
  • Mayaのスクリプトパスが通っているフォルダ(Document/maya/scriptsとか)に
    UiSampleScriptフォルダごとコピー

  • Mayaを起動しスクリプトエディタ(Python)で以下を入力して実行

from UiSampleScript import UiSample
UiSample.MainWindow().show()
プログラムについて

Maya2014と2015で若干違うので注意する

パッと見た感じではMayaQWidgetBaseMixinで2014と同じことをやっているようだったので
たぶん2014の方法で2015も大丈夫(未検証)

(12/12追記)MayaQWidgetBaseMixinをimportだけして使ってなかった。

# -*- coding: utf-8 -*-

import os
import sys
from PySide import QtCore, QtGui
from UiData import Ui_UiSample_MainWindow

# Maya2015 ver
from maya.app.general.mayaMixin import MayaQWidgetBaseMixin


# Maya2014 ver
# def get_maya_window():
#     from maya.OpenMayaUI as omui
#     from shiboken import wrapInstance
#     return wrapInstance(long(omui.MQtUtil.mainWindow()), QtGui.QWidget)


class MainWindow(MayaQWidgetBaseMixin, QtGui.QMainWindow):
    def __init__(self, parent=None):
        # Maya2015 ver
        super(MainWindow, self).__init__(parent)
        self.__ui = Ui_UiSample_MainWindow()
        self.__ui.setupUi(self)

        # Maya2014 ver
        # super(MainWindow, self).__init__(get_maya_window())
        # self.__ui = Ui_UiSample_MainWindow()
        # self.__ui.setupUi(self)

        self.__ui.pushButton_1.clicked.connect(self._on_clicked_btn_1)
        self.__ui.pushButton_2.clicked.connect(self._on_clicked_btn_2)
        self.__ui.pushButton_3.clicked.connect(self._on_clicked_btn_3)
        pass

    def _on_clicked_btn_1(self):
        print 'pushed PushButton_1'
        pass

    def _on_clicked_btn_2(self):
        print 'pushed PushButton_2'
        pass

    def _on_clicked_btn_3(self):
        print 'pushed PushButton_3'
        pass

if __name__ == '__main__':
    ui = MainWindow().show()
Signal/Slotについて

https://wiki.qt.io/Signals_and_Slots_in_PySide_Japanese

self.__ui.pushButton_1.clicked.connect(self._on_clicked_btn_1)
self.__ui.pushButton_2.clicked.connect(self._on_clicked_btn_2)
self.__ui.pushButton_3.clicked.connect(self._on_clicked_btn_3)

ボタンをクリックしたときの処理を設定している

GUIの作成方法
  • QtDesignerを起動する

C:\Program Files\Autodesk\Maya2015\bin\designer.exe

使い方

f:id:bonbonbe:20150419180936p:plain

作成が終わったら保存したデータをui2py.pyにドロップしてpythonに変換する

UNITE Tokyo 2015 まとめ

先週のUNITEまとめ(適当)

整理終了

公式の公開資料 japan.unity3d.com

RealTimeGIはとても参考になった。 Unity5まだ触ってないけど。

驚いたのはUnityちゃんに本名があったこと。

基調講演

Republic(ゲーム)のプロジェクト本日より公開したので よければチェックしてね

Unity新機能
  • StateMachineBehaviour あるStaeに入った時に自分で記述した処理を実行できる サブステート的な使い方ができる

  • AoudioMixer 音量の調節などを簡単にできる SoundAが鳴っているときはSoundBの音量を下げるというようなことができる(ダキング) 複数のSoundの音量をいくつかあらかじめ設定しておきそれを動的に切り替えることがきる(SnapShot)

  • webGL対応したよ

  • IL2CPPで早くなったよ

  • Unity5.1でVRの機能追加するよ PLayerSettingでVRの設定をすると普通のシーン(VikingDemo)でもVRになるよ

  • VRコンテンツをやるんだったら今からやらないと間に合わない

  • CoudBuild ビルド時間の節約

      - これまで15万時間節約
    

    どこでも絶えずビルド環境が使える 配信が楽やで

  • UnityAds iosのアプリTop10のうち4つがUnityAds 日本のサポートはGREEとCyberAgent CrossyRoadもこれを使用している

続きを読む

実行した複数のMELコマンドをひとまとめにして一発でUndo

undoInfoのopenChunkとcloseChunkのフラグを使う。

cmds.undoInfo(openChunk=True)
# ひとまとめにする処理
"""
move ~
rotate ~
move ~  ...とか
"""
cmds.undoInfo(closeChunk=True)

以下のような形も可

def _on_mouse_pressed(self):
    # ひとまとめにする処理開始
    cmds.undoInfo(openChunk=True)
    
def _on_mouse_released(self):
    # ひとまとめにする処理終了
    cmds.undoInfo(closeChunk=True)

def _on_mouse_moved(self):
    # ひとまとめになる処理
    pass