らくがきノート

絵の練習や絵に関する備忘録を中心に、思ったことを気が向いたときに残していきます

clip studio paintに自動保存機能を擬似的に実装する

前置き

絵描きブログにしようと思って始めたはずが、絵を1枚すらあげず、今回もお絵かきツールの話です。

最近、クリスタ(clip studio paint)で絵を書いてる時にソフトが落ちたり、閉じるときの保存しますかのメッセージに対していいえを選択してしてやり直し…なんてことが続いてます

クリスタに自動保存機能があれば解決なんですが、そんな機能はないので、どうにかならないか簡単に調べみたところ、AHK(AutoHotKey)を用いた自動保存をすでに実装されてる方がいるみたいです。

ただ、自分が欲しい機能とは少し違ってたので自分で作ることにしました

やりたいこと

  • クリスタがアクティブな状態のときx秒間操作がなかったら自動で保存
  • クリスタのアクティブ状態に関わらずy秒経過すると自動で保存
  • 非アクティブの時に保存した場合は元々アクティブだったウインドウをアクティブな状態に保つ
  • 操作しているファイルの拡張子がclipの時だけ自動で保存(いい考えが浮かばず実装できず…)
  • 自動保存の一時停止が可能
  • 各機能のオン・オフやパラメータの設定が可能

自動保存ツール

AHK初心者で、とりあえずなんとなく動く程度のものですが、今回もスクリプトを公開しておきます。

exeの配布やAHKの詳しい使用方法は需要があるかわからないので、割愛します (AutoHotkeyA32.ahkスクリプトを記載し、同じフォルダ内にautosave.iniを作成すれば動作すると思います)

※ 以下のスクリプトの使用する際は自己責任でお願いします。何かあっても責任は持ちません。

ahkファイル

#SingleINstance IGNORE

; 起動時に自動保存開始
#Persistent
ReadIniFile()
SWitchAutoSaveState()
return

#InstallKeybdHook
#InstallMouseHook

; キー設定
vk1Dsc07B & s::SWitchAutoSaveState() ; 無変換キー + s:開始・停止切り替え
vk1Dsc07B & i::ShowState()           ; 無変換キー + s:開始・停止状態表示
vk1Dsc07B & escape::ExitApp          ; 無変換キー + esc:終了
vk1Dsc07B & r::ReadIniFile()         ; 無変換キー + r:iniファイル再読込
vk1Dsc07B & a::ShowReadIniInfo()     ; 無変換キー + a:設定状態表示

; Iniファイル読み込み
ReadIniFile()
{
    global
    IniRead,CHECK_INTERVAL,autosave.ini,INTERVAL,CHECK,60000
    IniRead,NO_ACT_INTERVAL,autosave.ini,INTERVAL,NO_ACTION,180000
    IniRead,FORCE_INTERVAL,autosave.ini,INTERVAL,FORCE,1800000

    IniRead,NO_ACT_SAVE_FL,autosave.ini,FLAG,NO_ACT_SAVE,1
    IniRead,FORCIBLY_SAVE_FL,autosave.ini,FLAG,FORCIBLY_SAVE,1
    IniRead,SHOW_TRAY_FL,autosave.ini,FLAG,SHOW_MESSAGE,1
    IniRead,SOUND_FL,autosave.ini,FLAG,BEEP,1

    IniRead,WINDOW_TEXT,autosave.ini,PAINT_TOOL,NAME,CLIP STUDIO PAINT

    auto_save_fl := false
}
; 設定状態表示
ShowReadIniInfo()
{
    global
    local noact = % NO_ACT_SAVE_FL ? "ON" : "OFF"
    local force = % FORCIBLY_SAVE_FL ? "ON" : "OFF"
    local msg = % SHOW_TRAY_FL ? "ON" : "OFF"
    local beep = % SOUND_FL ? "ON" : "OFF"
    msgbox,
    (
     監視間隔       :%CHECK_INTERVAL% ms
    自動保存間隔     :%NO_ACT_INTERVAL% ms
    強制自動保存間隔   :%FORCE_INTERVAL% ms
    自動保存       :%noact%
    強制保存       :%force%
    メッセージの表示    :%msg%
    保存時にビープ音を鳴らす :%beep%
    ペイントツール名    :%WINDOW_TEXT%
    )
}

; 自動保存の開始・停止切り替え
SWitchAutoSaveState()
{
    global auto_save_fl
    if( auto_save_fl = true )
    {
        auto_save_fl := StopAutoSave()
        return
    }
    auto_save_fl := StartAutoSave()
}
; 自動保存の開始
StartAutoSave()
{
    global CHECK_INTERVAL
    SetTimer,LabelAutoSave,%CHECK_INTERVAL%
    ShowMessage( "オートセーブを開始します" )
    return true
}
; 自動保存の停止
StopAutoSave()
{
    SetTimer,LabelAutoSave,Off
    ShowMessage( "オートセーブを停止しました" )
    return false
}
; 自動保存の開始・停止時のメッセージ表示
ShowMessage(msg)
{
    global SHOW_TRAY_FL
    if( SHOW_TRAY_FL=false )
        return
    TrayTip,Info,%msg%,10,1
}
; 自動保存の実行状態表示
ShowState()
{
    global auto_save_fl
    TrayTip,Info,% auto_save_fl ? "オートセーブは実行中です" : "オートセーブは停止中です",10,1
}


; 保存処理
Save()
{
    global WINDOW_TEXT
    SetTitleMatchMode,2
    IfWinNotExist,%WINDOW_TEXT%
        return
    ForcibilySave()
    IfWinNotActive %WINDOW_TEXT%
        return
    NoActSave()
}

; 強制保存
ForcibilySave()
{
    global
    if( FORCIBLY_SAVE_FL=false )
        return
    if( AdvanceTime()<FORCE_INTERVAL)
        return
    WinGetClass,class,A
    ActivatePaintTool()
    SendSaveCommand()
    WinActivate,ahk_class %class%
}
; ペイントツールをアクティブにする
ActivatePaintTool()
{
    SetTitleMatchMode,2
    IfWinExist,%WINDOW_TEXT%
        WinActivate
}

; 操作がなかったときの保存
NoActSave()
{
    global
    if( NO_ACT_SAVE_FL=false )
        return
    if( A_TimeIdlePhysical > CHECK_INTERVAL+NO_ACT_INTERVAL )
        return
    if( A_TimeIdlePhysical>=NO_ACT_INTERVAL )
    {
        SendSaveCommand()
        return
    }
}
; 保存コマンド送信
SendSaveCommand()
{
    send,^s
    MakeBeep()
    AdvanceTime(true)
}
; ビープ音を鳴らす
MakeBeep()
{
    global SOUND_FL
    if( SOUND_FL = false)
        return
    SoundBeep
}

; 時間管理
; time_rest_fl = true で時間リセット
AdvanceTime( time_reset_fl=false)
{
    static t := 0
    if( time_reset_fl = true )
    {
        t := 0
        return %t%
    }
    global CHECK_INTERVAL
    t := % t + CHECK_INTERVAL
    return %t%
}
LabelAutoSave:
    Save()
return

autosave.ini

;===================================================================
; 時間間隔のパラメータ(単位:ミリ秒)
;   CHECK    :自動保存するかどうかを確認する間隔
;   NO_ACTION:ここで指定した時間以上操作していなかったとき自動保存する
;              (ペイントツールがアクティブ状態のときのみ実行される)
;   FORCE    :ここで指定した時間以上経過したとき、強制的に自動保存する
;              (ペイントツールが非アクティブな状態でも実行される)
;===================================================================
[INTERVAL]
CHECK     = 60000
NO_ACTION = 180000
FORCE     = 1800000

;===================================================================
; 機能のオン・オフのパラメータ
;   NO_ACT_SAVE   :指定時間操作がなかったとき自動で保存する
;                  (0:オフ 1:オン)
;   FORCIBLY_SAVE :指定時間経過すると強制的に自動で保存する
;                  (0:オフ 1:オン)
;   SHOW_MESSAGE  :自動保存機能の開始・停止時にメッセージを表示する
;                  (0:オフ 1:オン)
;   BEEP          :自動保存時にビープ音を鳴らす
;                  (0:オフ 1:オン)
;===================================================================
[FLAG]
NO_ACT_SAVE      = 1
FORCIBLY_SAVE    = 1
SHOW_MESSAGE     = 0
BEEP             = 1

;===================================================================
; ペイントツール
;   NAME : ペイントツール名
;         (ウィンドウアクティブ時に使用するので、タイトルに含まれる名前を設定する)
;===================================================================
[PAINT_TOOL]
NAME = CLIP STUDIO PAINT

左手デバイス(ロジクールG13)で任意のボタン押下時のみモードを切り替える

前置き

絵を描く際に左手デバイス(G13)を有効に使えてない気がしたので、設定を見直すことにしました。 ただ、指が届く範囲だとキーが足りず、手元を見ずに切替キーでモードを切り替えるのも難しいといった問題が出てきたのでいろいろと考えた結果スクリプトを使用することにしました。 f:id:yuki_taira:20170326152809p:plain:w500

やりたいこと

  • 「G22」キーが押された状態の間だけ切替キーの「M2」が押された状態にする
  • 「G21」キーが押された状態の間だけ切替キーの「M3」が押された状態にする
  • 「G21(G22)」を放すと切替キーの「M1」が押された状態にする

G13でスクリプトを使用する方法

  1. Gキーのカスタマイズを選択
  2. スクリプトを使用するプロファイルを右クリックし、スクリプトを選択 f:id:yuki_taira:20170326154814p:plain:w500
  3. 初期入力をすべて削除し、スクリプトを記入 f:id:yuki_taira:20170326155138p:plain:w500
  4. Ctrl+Sで保存し、ウインドウを閉じる

※ 以後このプロファイルでは「G21]「G22」を押すとモードが切り替わる

任意のキー押下時のみモードを切り替えるスクリプト

ネットを探してみましたが、やりたいことができるスクリプトが見つからなかったので公開しておきます。

※ 以下のスクリプトの使用する際は自己責任でお願いします。何かあっても責任は持ちません。

-- 切替キーの設定(G21,G22以外のキーで切り替える場合は変更)
SWITCH_MODE2_KEY = 22
SWITCH_MODE3_KEY = 21

MODE1 = 1
MODE2 = 2
MODE3 = 3

PRESSED_GKEY_CNT = 0
IS_SWITCH_KEY_PRESSED = false

function OnEvent( event, arg, family )
    if( family == "lhc" ) then
        PressGKeyCount( event )
        ResetMode()
        if( not IsModeSwitchingEvent( event ) ) then return end
        if( not IsModeSwitchingKeyPressed( arg ) ) then return end
        if( not IsModeSwitchableState() ) then return end
        SetMKeyState( GetMode( arg ), "lhc" )
        IS_SWITCH_KEY_PRESSED = true
    end
end

-- 押されているGキーのカウンター
function PressGKeyCount( event )
    cnt = event == "G_PRESSED" and 1 or 0
    cnt = event == "G_RELEASED" and -1 or cnt
    PRESSED_GKEY_CNT = PRESSED_GKEY_CNT + cnt
end

-- イベントがモード切替イベントかどうか
function IsModeSwitchingEvent( event )
    return event=="G_PRESSED"
end

-- 押されているキーがモード切替キーかどうか
function IsModeSwitchingKeyPressed( key )
    return key == SWITCH_MODE2_KEY or key == SWITCH_MODE3_KEY
end

-- 状態がモード切替可能状態かどうか
function IsModeSwitchableState()
    return PRESSED_GKEY_CNT == 1
end

-- 状態がモードリセット可能状態かどうか
function IsResetModeState()
    return PRESSED_GKEY_CNT == 0 and IS_SWITCH_KEY_PRESSED
end

-- 切替先のモードを取得
function GetMode( key )
    return key == SWITCH_MODE2_KEY and MODE2 or MODE3
end

-- デフォルトモード(M1)をセットしなおす
function ResetMode()
    if( not IsResetModeState() ) then return end
    SetMKeyState( MODE1, "lhc" )
    IS_SWITCH_KEY_PRESSED = false
end