スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

カテゴリ : スポンサー広告

KAGEXタグリファレンスなう

KAGEXリファレンスα6

ブログ書いてない分こっち書いてたんだよ!
ということでKAGEXタグリファレンス。
めっちゃ作りかけ。いつかできる。たまに見ると成長してるかも。
見事にめんどくさそーな所ばっか残ってるわろ。

完成したらワールド拡張なしでベターKAGとして使うには十分な環境できるんじゃないかな?
誤字脱字その他諸々はコメント欄まで。
スポンサーサイト

タグ : 吉里吉里 KAGEX

カテゴリ : KAGEX

UI定義CSV出力用フォトショスクリプト

ダウンロード

psdファイルからKAGEXのUILoader用のcsvファイルとpngファイルを吐き出します。
まともな説明もしてないし使い方もややっこしいのであまり意味はありません。
がなかなか整備も出来ないのでテキトーなサンプルと共にぶん投げておきます。

タグ : 吉里吉里 ツール KAGEX

カテゴリ : プラグイン配布

KAGEX講座(26) - メッセージ操作([eraftername])

前回 KAGEX講座(25) - 選択肢設定([selopt])
KAGEXにはテキスト入力を楽にするタグがあります。

ignoreCR
まずKAGにも存在するignoreCRについて説明します。
config.tjsのシナリオ解析モードの部分で設定できます。
以下引用
// ◆ シナリオ解析モード
// シナリオファイル中の改行に従わせたい場合に false を設定します。
// false を指定すると、KAG のシナリオ中の改行が、行末に \ または [p] を書か
// ない限りそのままメッセージレイヤ上での改行として扱われます。
// true を設定すると [r] タグを書かない限り改行されません。
// KAG2.x 互換にするには false を指定してください。
;global.ignoreCR = true;
デフォルトではtrueになっています。
falseにすると[r]タグを書かなくても改行されるようになります。
『クラムボンはわらつたよ。』[l]
『クラムボンはかぷかぷわらつたよ。』[l]
『クラムボンは跳てわらつたよ。』[l]
『クラムボンはかぷかぷわらつたよ。』
↓[r]タグを書かなくても改行されます。
ignorecr_1.png

改行させたくない行では「¥」を入れます。
ただしコマンド行(@で始まるタグの行)はタグしかないことがわかっているので「¥」をつけなくても改行されません。
@font color=0xFF0000
『クラムボンはわらつたよ。』[l]
@font color=0x00FF00
『クラムボンはかぷかぷわらつたよ。』[l]
[font color=0xFF0000
『クラムボンは跳てわらつたよ。』[l]
[font color=0x00FF00
『クラムボンはかぷかぷわらつたよ。』
[font]タグのところの「¥」を忘れると改行が挟まってしまいます。

erafterpage
[erafterpage]タグを使うと[p]タグの後に自動で[er]タグを実行してくれるようにできます。
@erafterpage mode=true
『クラムボンはわらつたよ。』[p]
『クラムボンはかぷかぷわらつたよ。』[p]
『クラムボンは跳てわらつたよ。』[p]
『クラムボンはかぷかぷわらつたよ。』
[p]ごとにメッセージレイヤの文字が消去されます。
mode属性にtrueを指定すると有効、falseを指定すると無効にできます。

次回 KAGEX講座(27) - ラインモード([linemode])

続きを閉じる▲

タグ : 吉里吉里 KAGEX 講座

カテゴリ : KAGEX

吉里吉里/KAGEX アクション拡張 SKN_ActionEx

ダウンロード

KAGEXのアクション機能を拡張します。
といっても現在はboost機能とスキップ機能(TJS用)のみ。
キーを押している間だけアクションを加速。
スタッフロールが早送りできたりします。

タグ : 吉里吉里 プラグイン KAGEX

カテゴリ : プラグイン配布

選択肢まとめ - selopt, seladd, sellect, seldone

選択肢関係のタグまとめ。
もうちょっと文量まとまったら綺麗にリファレンスとしてまとめたいですがとりあえず。
まとめました→http://kagex.zouri.jp/

selopt (選択肢の属性)

属性必須?説明
leftnopixel 単位の数値選択肢領域の左端位置を指定します。
topnopixel 単位の数値選択肢領域の上端位置を指定します。
widthnopixel 単位の数値選択肢領域の幅を指定します。
heightnopixel 単位の数値選択肢領域の高さを指定します。
normalno画像ファイル名選択肢ボタンの画像として表示させる画像を分離ボタン形式で指定します。使用しない場合は "" を指定してください。
overno画像ファイル名選択肢ボタンの画像として表示させる画像を分離ボタン形式で指定します。使用しない場合は "" を指定してください。
onno画像ファイル名選択肢ボタンの画像として表示させる画像を分離ボタン形式で指定します。使用しない場合は "" を指定してください。
focusno画像ファイル名選択肢ボタンの画像として表示させる画像を分離ボタン形式で指定します。使用しない場合は "" を指定してください。
graphicno画像ファイル名選択肢ボタンの画像として表示させる画像を結合済みボタン形式で指定します。使用しない場合は "" を指定してください。
graphickeyno0xRRGGBB 形式 または パレットインデックス番号 または "adapt"結合済みボタン方式の場合の画像のカラーキーを指定します。分離ボタン形式では使用できません。
opacityno不透明度 ( 0 (全くの透明) ~ 255 (全くの不透明 ) )選択肢画像の不透明度を指定します。
selectcolorno0xRRGGBB 形式組み込みボタン形式の場合のボタンの文字の色を指定します。
selectbasecolorno0xRRGGBB 形式組み込みボタン形式の場合のボタンの色を指定します。
selectwidthnopixel 単位の数値組み込みボタン形式の場合のボタンの幅を指定します。
selectheightnopixel 単位の数値組み込みボタン形式の場合のボタンの高さを指定します。
fontfacenoフォント名文字のフォント名を指定します。 font タグの face 属性を参照してください。
sizenopixel 単位の数値文字サイズを pixel 単位で指定します。
colorno0xRRGGBB 形式選択肢の文字の色を指定します。組み込みボタン形式の場合は selectcolor 属性で指定してください。
selectedcolorno0xRRGGBB 形式選択済みの選択肢の文字の色を指定します。組み込みボタン形式の場合は無効です。
disabledcolorno0xRRGGBB 形式選択できない選択肢の文字の色を指定します。組み込みボタン形式の場合は無効です。
italicnotrue または false(デフォルト)文字を斜体にするかどうかを指定します。true を指定すると斜体になります。
boldnotrue または false(デフォルト)文字を太文字にするかを指定します。 true を指定すると太文字になります。
edgenotrue または false(デフォルト)文字を袋文字 ( 縁取り文字 ) にするかを指定します。true を指定すると袋文字になります。組み込みボタン形式の場合は無効です。
edgecolorno0xRRGGBB 形式文字の縁取りの色を指定します。
edgeemphasisno0以上の数値文字の縁取りの強調度を指定します。
edgeextentno0以上の数値文字の縁取りの太さを指定します。
shadownotrue または false(デフォルト)文字に影をつけるかを指定します。true を指定すると影がつきます。組み込みボタン形式の場合は無効です。
shadowcolorno0xRRGGBB 形式文字の影の色を指定します。
shadowoffsetxnopixel 単位の数値文字の影のX方向のずれの量を指定します。
shadowoffsetynopixel 単位の数値文字の影のY方向のずれの量を指定します。
shadowwidthno0以上の数値文字の影のぼかし具合を指定します。
overcolorno0xRRGGBB 形式マウスオーバー時の文字の色を指定します。組み込みボタン形式の場合は無効です。
overedgecolorno0xRRGGBB 形式マウスオーバー時の文字の縁取りの色を指定します。組み込みボタン形式の場合は無効です。
overshadowcolorno0xRRGGBB 形式マウスオーバー時の文字の影の色を指定します。組み込みボタン形式の場合は無効です。
oncolorno0xRRGGBB 形式マウスボタン押し下げ時の文字の色を指定します。組み込みボタン形式の場合は無効です。
onedgecolorno0xRRGGBB 形式マウスボタン押し下げ時の文字の縁取りの色を指定します。組み込みボタン形式の場合は無効です。
onshadowcolorno0xRRGGBB 形式マウスボタン押し下げ時の文字の影の色を指定します。組み込みボタン形式の場合は無効です。
focuscolorno0xRRGGBB 形式フォーカス時の文字の色を指定します。組み込みボタン形式の場合は無効です。
focusedgecolorno0xRRGGBB 形式フォーカス時の文字の縁取りの色を指定します。組み込みボタン形式の場合は無効です。
focusshadowcolorno0xRRGGBB 形式フォーカス時の文字の影の色を指定します。組み込みボタン形式の場合は無効です。
clickseno効果音ファイル名addbutton タグの clickse 属性のデフォルトの値を指定します。
enterseno効果音ファイル名addbutton タグの enterse 属性のデフォルトの値を指定します。
leaveseno効果音ファイル名addbutton タグの leavese 属性のデフォルトの値を指定します。
openseno効果音ファイル名選択肢を実行するときに再生する効果音を指定します。指定しなければ効果音は再生されません。
opensebufno効果音バッファ番号opense 属性で指定した効果音を鳴らす効果音バッファを指定します。
closeseno効果音ファイル名選択肢の実行終了時に再生する効果音を指定します。指定しなければ効果音は再生されません。※現ver.だとバグで再生されず。
closesebufno効果音バッファ番号closese 属性で指定した効果音を鳴らす効果音バッファを指定します。
msgoffnotrue または false(デフォルト)select タグの msgoff 属性のデフォルトの値を指定します。
msgonnotrue または false(デフォルト)select タグの msgon 属性のデフォルトの値を指定します。
fadetimeno時間(ms単位)選択肢を表示または隠すときのフェードにかける時間を指定します。デフォルトでは0です。
uistoragenoUI定義CSVファイル名UI定義ファイルを指定します。
uinameno文字列UI名を指定します。
select タグによる選択肢に対する様々な属性を指定します。
いずれの属性も、省略すれば設定は変更されません。
ボタンの各形式については button タグの説明を参照してください。分離ボタン形式、結合済みボタン形式、組み込みボタン形式の順に優先されます。


seladd (選択肢の登録)

属性必須?説明
storagenoシナリオファイル名ジャンプ先のシナリオファイルを指定します。省略すると現在のシナリオファイル内であると見なされます。
targetnoラベル名ジャンプ先のラベルを指定します。省略するとファイルの先頭から実行されます。
textno文字列選択肢上に表示される文字列を指定します。
evalnoTJS 式評価する TJS 式を指定します。この式の結果が false ならば選択肢は登録されません。
onceflagno変数名変数名を指定します。この変数が true ならば選択肢は登録されません。
この変数には選択されたときに true が代入されます。
この属性は eval 属性が指定されている場合は無視されます。
tagno文字列ボタン固有名タグを指定します。
この属性が指定された場合、選択されたときに sf.["select_"+tag] に true が代入されます。
clickseno効果音ファイル名選択肢ボタンがクリックされたときに再生する効果音を指定します。デフォルトの値は selopt タグの属性によります。再生しない場合は "" を指定してください。
clicksebufno効果音バッファ番号clickse 属性で指定した効果音を鳴らす効果音バッファを指定します。
enterseno効果音ファイル名選択肢ボタン内にマウスカーソルが入ってきたときに再生する効果音を指定します。デフォルトの値は selopt タグの属性によります。再生しない場合は "" を指定してください。
entersebufno効果音バッファ番号enterse 属性で指定した効果音を鳴らす効果音バッファを指定します。
leaveseno効果音ファイル名選択肢ボタン内からマウスカーソルが出ていった時に再生する効果音を指定します。デフォルトの値は selopt タグの属性によります。再生しない場合は "" を指定してください。
leavesebufno効果音バッファ番号leavese 属性で指定した効果音を鳴らす効果音バッファを指定します。
expnoTJS 式選択されたときに実行される TJS 式を指定します。
onenternoTJS 式選択肢ボタン内にマウスカーソルが入ってきたときに実行される TJS 式を指定します。
onleavenoTJS 式選択肢ボタン内からマウスカーソルが出ていった時に実行される TJS 式を指定します。
disablenotrue または falsetrue が指定された場合、選択肢が選択できないようになります。
省略すると false を指定したと見なされます。
選択肢を登録します。登録した選択肢は select タグで実行されます。


select (選択肢の実行)

属性必須?説明
storagenoシナリオファイル名seldone タグによるジャンプ先のシナリオファイルを指定します。省略すると seldone タグ実行時のシナリオファイル内であると見なされます。
targetnoラベル名seldone タグによるジャンプ先のラベルを指定します。省略するとファイルの先頭から実行されます。
msgoffnotrue または falsetrue が指定された場合、選択肢実行前に現在のメッセージレイヤを隠します。
デフォルトの値は selopt タグの属性によります。
msgonnotrue または falsetrue が指定された場合、選択肢実行前に現在のメッセージレイヤを表示します。
デフォルトの値は selopt タグの属性によります。
msgoff 属性が true の場合は無視されます。
seladd タグで登録された選択肢を表示し、選択肢が選択されるのを待ちます。
選択された選択肢に storage または target 属性でジャンプ先が指定されていた場合、指定先にジャンプします。指定されていない場合、ジャンプせずに次の行からシナリオファイルの実行を再開します。
選択肢が登録されていない場合、このタグは無視されます。


seldone (選択肢後の合流)

最後に実行された select タグの storage 属性と target 属性で指定されたジャンプ先へジャンプします。
ジャンプ先が指定されていない場合はシナリオファイルの進行を停止します。

続きを閉じる▲

タグ : 吉里吉里 KAGEX 講座

カテゴリ : KAGEX

KAGEXバグ修正まとめ

現バージョンのKAGEXで自分が見つけた限りのバグ。
とりあえず自分で直しておくことを推奨。
※明らかなバグ以外の修正も含んでます。一部バグじゃないかも。

3/28 MainWindow.tjsの修正追加
- 以下2012年 -
12/14 KAGEnvSe.tjsの修正追加
7/25 KAGEnvLevelLayer.tjsの修正追加
7/24 Initialize.tjs, Conductor.tjs, MainWindow.tjsの修正追加
5/10 KAGEnvImage.tjsの修正追加
3/5 AffineLayer.tjsの修正追加
- 以下2011年 -
12/24 TransLayer.tjsの修正追加
12//22 KAGEnvImage.tjsの修正追加
12/21 KAGEnvImage.tjsの修正追加
8/26 MainWindow.tjsの修正追加
8/21 GFX_Movie.tjsの修正追加
7/27 world.tjsの修正追加
6/28 KAGEnvImage.tjsの修正追加
5/25 kag3ex3に対応
4/22 MainWindow.tjsの修正追加
2/19 EditLayer.tjsの修正追加
2/11 MapSelectLayer.tjsの修正追加
2/3 ButtonLayer.tjsの修正追加
2/3 MessageLayer.tjsの修正追加
2/3 SliderLayer.tjsの修正追加
1/30 EditLayer.tjsの修正追加
1/30 GraphicLayer.tjsの修正追加
1/20 MainWindow.tjsの修正追加
1/16 UILoader.tjsの修正追加
1/13 SelectLayer.tjs再修正


world.tjsの308行目
                if (valueBase !== void && value.charAt(-1) == '%') {
 ↓修正
                if (valueBase !== void && value.charAt(value.length-1) == '%') {
「-1」の部分を「value.length-1」に。
314行目も全く同じです。
※kag3ex3で修正済みです。


SelectLayer.tjsの642行目
        playSE(closese, closesebuf) if (visible);
 ↓修正
//      playSE(closese, closesebuf) if (visible);
コメントアウトします。

SelectLayer.tjsの631行目
        window.insertTag("doneselect", elm !== void ? elm : %[]);
        if (setVisibleTime(false, fadeTime)) {
 ↓修正
        window.insertTag("doneselect", elm !== void ? elm : %[]);
        window.insertTag("se", %[storage:closese, buf:closesebuf]);
        if (setVisibleTime(false, fadeTime)) {
「window.insertTag("se", %[storage:closese, buf:closesebuf]);」をはさみます。


KAGEnvCharacter.tjsの619行目
            emotion.nowait = elm.nowait if elm.nowqait !== void;
 ↓修正
            emotion.nowait = elm.nowait if elm.nowait !== void;
「nowqait」→「nowait」
※kag3ex3で修正済みです。



KAGEnvCharacter.tjsの975行目
                    var operateMode = omPsNormal;
 ↓修正
                    var operateMode = omAuto;
「omPsNormal」を「omAuto」に。

UILoader.tjsの6行目
if (global.CSVParser === void) {
 ↓修正
if (typeof global.CSVParser === "undefined") {
「typeof」を追加。「void」→「"undefined"」
※kag3ex3で対応済み。



MainWindow.tjsの8544行目
            if (typeof target == "Object" && target instanceof "AffineLayer") {
                return waitLayerTransition(target, elm.canskip, +elm.wait);
            } else {
 ↓修正
            if (typeof target == "Object" && target instanceof "AffineLayer") {
                return waitLayerMotion(target, elm.canskip, +elm.wait);
            } else {
「waitLayerTransition」を「waitLayerMotion」に
※kag3ex3で削除



GraphicLayer.tjsの717行目
                    if (elm.width !== void || elm.height !== void) {
                        layer.setSize(elm.width !== void ? +elm.width : width,
                                      elm.height !== void ? +elm.height : height);
                    }
 ↓ 修正
                    if (elm.width !== void || elm.height !== void) {
                        setSize(elm.width !== void ? +elm.width : width,
                                      elm.height !== void ? +elm.height : height);
                    }
「layer.」を消去。


EditLayer.tjsの154行目
        if(Edit_vertical)
        {
            Edit_caretLayer.top = xpos;
            Edit_caretLayer.left = imageWidth - 3 - Edit_caretLayer.imageWidth;
            setAttentionPos(imageWidth - 3 , Edit_caretLayer.top);
        }
        else
        {
            Edit_caretLayer.top = 3;
            Edit_caretLayer.left = xpos;
            setAttentionPos(xpos, 3);
        }
 ↓ 修正
        if(Edit_vertical)
        {
            Edit_caretLayer.top = xpos + Edit_textOffsetY;
            Edit_caretLayer.left = imageWidth - 3 - Edit_caretLayer.imageWidth + Edit_textOffsetX;
            setAttentionPos(imageWidth - 3 , Edit_caretLayer.top);
        }
        else
        {
            Edit_caretLayer.top = 3 + Edit_textOffsetY;
            Edit_caretLayer.left = xpos + Edit_textOffsetX;
            setAttentionPos(xpos, 3);
        }
「 + Edit_textOffsetX」と「 + Edit_textOffsetY」をそれぞれ2箇所ずつ追加。


SliderLayer.tjsの132行目
                if (Slider_mouseOn) {
                    colorRect(0x_htabw, imw, tabh, clHighlight, 64);
                }
 ↓ 修正
                if (Slider_mouseOn) {
                    colorRect(0x_htabh, imw, tabh, clHighlight, 64);
                }
「x_htabw」→「x_htabh」


MessageLayer.tjsの3291行目
            object.position = +elm.position if elm.position !== void;
 ↓ 修正
            object.position = elm.position !== void ? +elm.position : 0;
「+elm.position if elm.position !== void」→「elm.position !== void ? +elm.position : 0」

MessageLayer.tjsの3044行目
            if (elm.trigger || elm.group) {
                object.loadButtons(elm.on, over, on, focus, elm.animcount, elm.animtime, true);
                object.groupName = elm.group;
            }
 ↓ 修正
            if (elm.trigger || elm.group != "") {
                object.loadButtons(on, over, on, focus, elm.animcount, elm.animtime, true);
                object.groupName = elm.group;
            }
「elm.group」→「elm.group != ""」
「elm.on」→「on」
3055行目も全く同じです。


ButtonLayer.tjsの240行目
        fillRect(00, imageWidth, imageHeight, 0);
↓ 修正
        fillRect(00, imageWidth, imageHeight, 0if !toggle;
「if !toggle」を追加。


MapSelectLayer.tjsの202行目
        buttonWidth  = elm.buttonwidth if elm.btnwidth !== void;
 ↓ 修正
        buttonWidth  = elm.buttonwidth if elm.buttonwidth !== void;
「elm.btnwidth」→「elm.buttonwidth」


EditLayer.tjsの209行目
        // クリックされた位置を割り出す
        x -= 3;
 ↓ 修正
        // クリックされた位置を割り出す
        x -= 3 + (Edit_vertical ? Edit_textOffsetY : Edit_textOffsetX);
「+ (Edit_vertical ? Edit_textOffsetY : Edit_textOffsetX)」を追加

EditLayer.tjsの593行目
                    // 背景を塗る
                    fillRect(xy, h, chw, highlightbg);
 ↓ 修正
                    // 背景を塗る
                    fillRect(x - h + Edit_textOffsetXy + Edit_textOffsetY, h, chw, highlightbg);
「x」→「x - h + Edit_textOffsetX」
「y」→「y + Edit_textOffsetY」

EditLayer.tjsの617行目
                    // 背景を塗る
                    fillRect(xy, chw, h, highlightbg);
 ↓ 修正
                    // 背景を塗る
                    fillRect(x + Edit_textOffsetXy + Edit_textOffsetY, chw, h, highlightbg);
「x」→「x + Edit_textOffsetX」
「y」→「y + Edit_textOffsetY」


MainWindow.tjsの1837行目
    function onMouseMove(x, y) {
        if (pseudoFullScreened && y == 0 && menuBarEnable && menuBarState) trackPseudoMenu();
        else if (trackTempMenuShowing) checkMenuBarHideTrackPseudoMenu();
        var hook = mouseMoveHook;
        if (hook.count > 0with (primaryLayer) callHook(hook, .cursorX, .cursorY);
        return super.onMouseMove(...);
    }
 ↓ 修正
    function onMouseMove(x, y) {
        if (pseudoFullScreened && y == 0 && menuBarEnable && menuBarState) trackPseudoMenu();
        else if (trackTempMenuShowing) checkMenuBarHideTrackPseudoMenu();
        if (isvalid this) {
            var hook = mouseMoveHook;
            if (hook.count > 0with (primaryLayer) callHook(hook, .cursorX, .cursorY);
        }
        return super.onMouseMove(...);
    }
「if (isvalid this) {」と「}」を追加。


KAGEnvImage.tjsの2533行目
        if (rgamma != void || ggamma != void || bgamma != void) {
            layer.adjustGamma(rgamma == void ? 1.0 : rgamma, 0255,
                              ggamma == void ? 1.0 : ggamma, 0255,
                              bgamma == void ? 1.0 : bgamma, 0255);
        }
 ↓ 修正
        if (rgamma !== void || ggamma !== void || bgamma !== void) {
            layer.adjustGamma(rgamma === void ? 1.0 : rgamma, 0255,
                              ggamma === void ? 1.0 : ggamma, 0255,
                              bgamma === void ? 1.0 : bgamma, 0255);
        }
3つの「!=」と「==」をそれぞれ「!==」と「===」に


world.tjsの580行目
    // 全アクション・トランジション終了時コールバック
    function onAllActionTransitionCompleted() {
        destroyTrigger.trigger();
    }
 ↓ 修正
    // 全アクション・トランジション終了時コールバック
    function onAllActionTransitionCompleted() {
        if(destroyTrigger isvalid) {
            destroyTrigger.trigger();
        }
    }
「if(destroyTrigger isvalid) {」と「}」を追加


GFX_Movie.tjsの52行目
        open(fn);
    }
 ↓ 修正
        open(fn);
        with (global.kag) {
            audioVolume = (.waveenable && .movieAudioEnable) ?
                (.wavevolume *  .movieAudioVolume) * 10 : 0;
        }

        play();
    }
「with (global.kag) { ~ }」を追加


MainWindow.tjsの10664行目
        // メッセージ窓だけ表から裏にコピー
        var messages = fore.messages;
 ↓ 修正
        // メッセージ窓だけ表から裏にコピー
        var messages = back.messages;
「fore」→「back」

KAGEnvImage.tjsの688行目
  function setRotate(param, elm) {
    rotateFrom = calcRelative(rotate, getFrom(param), 360);
    rotate     = calcRelative(rotate, getTo(param), 360);
    rotateTime = +elm.time;
    rotateAccel = +elm.accel;
    rotateNowait = elm.nowait;
  }
 ↓ 修正
  function setRotate(param, elm) {
    rotateFrom = calcRelative(rotate, getFrom(param), 360);
    rotate     = calcRelative(rotate, getTo(param), 360);
    rotateTime = elm.time;
    rotateAccel = elm.accel;
    rotateNowait = elm.nowait;
  }
「+elm.accel」の「+」を削除

KAGEnvImage.tjsの1408行目
    if (elm.slanty === voidslantx = 0;
 ↓ 修正
    if (elm.slanty === voidslanty = 0;
「slantx」→「slanty」

    if (doSlanty) {
      if (slantyFrom !== void) {
        layer.slanty = slantyFrom;
        slantyFrom = void;
      }
      if (slantxTime == 0) {
        layer.slanty = slanty;
      } else {
        layer.setSlantYTime(slanty, slantyTime, slantyAccel, slantyNowait);
      }
      doSlanty = false;
    }
 ↓ 修正
    if (doSlanty) {
      if (slantyFrom !== void) {
        layer.slanty = slantyFrom;
        slantyFrom = void;
      }
      if (slantyTime == 0) {
        layer.slanty = slanty;
      } else {
        layer.setSlantYTime(slanty, slantyTime, slantyAccel, slantyNowait);
      }
      doSlanty = false;
    }
「slantxTime」→「slantyTime」

TransLayer.tjsの215行目
  function stop() {
    done();
    layer.visible = false;
  }
 ↓ 修正
  function stop() {
    done();
    layer.visible = false;
    tlayer.visible = false;
  }
「tlayer.visible = false;」を追加。


AffineLayer.tjsの1795行目
  function setZoom(zx, zy=void) {
    //Debug.message("setZoom:" + zx + ":" + zy);
    if (zy == void) {
      zy = zx;
    }
    _zoomx = zx / 100.0;
    _zoomy = zy / 100.0;
    calcAffine();
  }
↓ 修正
  function setZoom(zx, zy=void) {
    //Debug.message("setZoom:" + zx + ":" + zy);
    if (zy === void) {
      zy = zx;
    }
    _zoomx = zx / 100.0;
    _zoomy = zy / 100.0;
    calcAffine();
  }
「zy == void」→「zy === void」


KAGEnvImage.tjsの378行目
          action.delay  = +elm.delay  if elm.time !== void;
↓ 修正
          action.delay  = +elm.delay  if elm.delay !== void;
「elm.time」→「elm.delay」


Initialize.tjsの437行目
var mp_dummy = %[], mp_target;
property mp {
  getter {
    var macroParams = mp_target ? mp_target.macroParams : void;
    return macroParams  ? /*dict*/macroParams : /*null or void*/mp_dummy;
  }
}
↓ 修正
//var mp_dummy = %[], mp_target;
//property mp {
//  getter {
//    var macroParams = mp_target ? mp_target.macroParams : void;
//    return macroParams  ? /*dict*/macroParams : /*null or void*/mp_dummy;
//  }
//}
全てコメントアウト

Conductor.tjsの202行目
    mp_target = this;
↓ 修正
    //mp_target = this;
コメントアウト

Conductor.tjsの420行目
    mp_target = void;
↓ 修正
    //mp_target = void;
コメントアウト。458行目も同じ

MainWindow.tjsの11277行目
  eval : function(elm)
  {
    // 式の評価
    Scripts.eval(elm.exp);
    return 0;
  } incontextof this,
↓ 修正
  eval : function(elm)
  {
    // 式の評価
    Scripts.eval(elm.exp,,,this);
    return 0;
  }/* incontextof this*/,
「Scripts.eval(elm.exp);」→「Scripts.eval(elm.exp,,,this);」
incontextof thisをコメントアウト

KAGEnvLevelLayer.tjsの145行目
    f.name  = name if initDisp;
↓ 修正
    f.name  = name/* if initDisp*/;
「if initDisp」をコメントアウト

KAGEnvSe.tjsの115行目
  var secommands = %[
  tagname : null
  taglist : null
  storage : setPlay incontextof this,
  play : setPlay incontextof this,
  stop : setStop incontextof this,
  fade : setFade incontextof this,
  loop : null,
  time : null,
  start : null,
  canskip : null,
  buf : null,
  filename : null,
  nosync : null,
  sync : null,
  wait : null,
  delayrun : null,
  ];
 ↓ 修正
  var secommands = %[
  tagname : null
  taglist : null
  storage : setPlay incontextof this,
  play : setPlay incontextof this,
  stop : setStop incontextof this,
  fade : setFade incontextof this,
  loop : null,
  time : null,
  start : null,
  canskip : null,
  buf : null,
  filename : null,
  nosync : null,
  sync : null,
  wait : null,
  delayrun : null,
  name : null,
  ];
「name : null,」を追加

MainWindow.tjsの3626行目
  function captureSnapshot(layer = snapshotLayer, w = scWidth, h = scHeight, hide = snapshotHideMessage) {
    with (layer) {
      .setImageSize(w, h);
      .face = dfAlpha;
      if (hide && !messageLayerHiding) setMessageLayerHiddenState(true);
      else hide = false;
      .piledCopy(00, fore.base, 00, w, h);
      if (hide) setMessageLayerHiddenState(false);
    }
  }
 ↓ 修正
  function captureSnapshot(layer = snapshotLayer, w = scWidth, h = scHeight, hide = snapshotHideMessage) {
    with (layer) {
      .setImageSize(w, h);
      .face = dfAlpha;
      if (hide && !messageLayerHiding) setMessageLayerHiddenState(true);
      else hide = false;
      setBaseLayerPos(00);
      .piledCopy(00, fore.base, 00, w, h);
      if (hide) setMessageLayerHiddenState(false);
    }
  }
「setBaseLayerPos(0, 0);」を追加

続きを閉じる▲

タグ : 吉里吉里 KAGEX

カテゴリ : KAGEX

KAGEXの文字描画について - layerExDraw.dll

KAGEXでは文字の描画方法が3種類存在します。
知らないと特定の場合に困ることになります。


1つ目は吉里吉里の機能を使った描画です。
KAGの文字描画は全てこれです。
※TJSで表現するとLayer.drawText()で描画させるやつです。
KAGEXでも基本的にはこちらが使われます。


2つ目はlayerExDraw.dllの機能を使った描画です。
「メッセージレイヤへの文字描画、名前レイヤへの文字描画、選択肢への文字描画のいずれかの場合」で、「横書き」かつ「縁取りあり」かつ「アンチエイリアスあり」の時にこちらが使用されます。

↓微妙に違う文字描画(上が吉里吉里による描画、下がlayerExDrawを使った描画、フォントはMS 明朝)
fontcmp.png
layerExDrawによる描画だと、縁取りと影を同時に描画できたり、取り消し線をひけるなど色々と便利な点もあるのですが、困る場合もあります。

それはレンダリング済みフォントが使えないということです。
↓文字化けしてしまいます
exdraw_prerend.png
簡単な解決方法としてはlayerExDraw.dllによる描画を使わないようにすればいいです。
pluginフォルダに入っているlayerExDraw.dllを削除してしまいましょう。
使っているという自覚がなければ他の箇所でも使われていないはずなので消してしまって問題ありません。
※layerExDraw.dllでインストールされていないフォントを使う方法もあるのですがここでは紹介しません。


3つ目はビットマップフォントを使った描画ですがデフォルトでは使われないので気にしなくて構いません。


ついでにTJS的な解説。
メッセージレイヤなどへの文字の描画はMessageLayer.tjsの2429行目あたりで定義されている「MessageLayerクラスのdrawTextToLayer関数」が使われます。
以下該当の関数をコピペ。
00:  function drawTextToLayer(lay, x, y, text, color) {
01:      var win = lay.window;
02:      if (typeof   win.bitmapFont == "Object" && win.bitmapFont) {
03:          var dt = win.bitmapFont.drawTextToLayer;
04:          // ビットマップフォント指定による強制描画
05:          dt(lay, x+shadowOffsetX, y+shadowOffsetY, text, shadowColor) if (shadow);
06:          dt(lay, x, y, text, color);
07:          return;
08:      }
09:      var dt = lay.drawText;
10:      if (!vertical && edge && antialiased && typeof lay.drawPathString != "undefined") {
11:          // layerExDraw拡張
12:          var tag = "__gdiplusfontapp";
13:          lay[tag] = new global.MessageLayer.GdiPlusFontApp() if (typeof lay[tag] == "undefined");
14:          lay[tag].drawText(this, lay, x, y, text, color);
15:      }
16:      else if(edge)   dt(x, y, text, color, 255, antialiased, edgeEmphasis, edgeColor, edgeExtent, 00);
17:      else if(shadow) dt(x, y, text, color, 255, antialiased, 255, shadowColor, shadowWidth, shadowOffsetX, shadowOffsetY);
18:      else            dt(x, y, text, color, 255, antialiased);
19:  }
第1引数layには文字を描画する対象となるレイヤオブジェクトがわたされます。
第2引数xは文字を描画するx座標、第3引数yがy座標です。
第4引数textは描画する文字列、第5引数colorは文字の色です。

1行目、レイヤの親ウィンドウはKAGEXのウィンドウのはずです。
2行目でウィンドウにbitmapFontが存在するか確かめていますが、自分で作らない限り存在することはありません。
※KAGEX側で勝手に作られることはありません。
なので3行目から7行目は無視されます。
8行目、レイヤのdrawText関数のショートカットを作成します。
以下dt()でレイヤのdrawText関数が使えるようになりました。
9行目、上の解説でも触れた「横書き」かつ「縁取りあり」かつ「アンチエイリアスあり」の条件をチェックしています。
verticalは縦書きの時にtrue,edgeは縁取りありの時にtrue,antialiasedはアンチエイリアスありの時にtrueになります。
※それぞれMessageLayerクラスのメンバ変数です。後述のedgeEmphasisなども同様。
最後の「typeof lay.drawPathString != "undefined"」ですが、drawPathStringとはlayerExDraw.dllを読み込んだときに定義される関数です。
「typeof lay.drawPathString != "undefined"のとき」つまり「drawPathStringが存在しているとき」にはlayerExDraw.dllが読み込まれていないと判断できます。
11行目から14行目でlayerExDrawによる描画を行っているのですが、面倒な部分なのでまた今度に回します。
16行目は10行目の条件が満たされないときに縁取りありで描画します。
edgeEmphasisが縁取りの濃さ、edgeColorが縁取りの色、edgeExtentが縁取りの厚さとなっています。
影を文字と同じ位置に描画することで縁取りのように見せかけています。
17行目は縁取りなし、影ありのときの描画です。
shadowColorは影色、shadowWidthが影の幅、shadowOffsetXが影の位置のxオフセット、shadowOffsetYが影の位置のyオフセットとなっています。
drawTextの機能をそのまま使っているだけです。
18行目は縁取りも影もなしでシンプルにdrawTextで文字を描画しています。
※余談ですがMessageLayer.tjsでは「縁取り」と「袋文字」が同じ意味で使われています。
※自分で読むときにはちょっと気をつけてください。

続きを閉じる▲

タグ : 吉里吉里 KAGEX TJS

カテゴリ : KAGEX

KAGEX講座(25) - 選択肢設定([selopt])

前回 KAGEX講座(24) - 選択肢表示([select], [seladd])
選択肢の設定を色々変えてみます。

選択肢の設定には[selopt]タグを使います。
このタグには様々な属性があります。
[selopt]の設定は設定を変えるまで何度選択肢を表示しても有効です。

ボタン設定
@道路
@selopt selectwidth=400 selectheight=80 selectbasecolor=0xFF0000 selectcolor=0x00FF00

*START
@cm
選択肢を表示します。[p][r]

@seladd text=選択肢1 target=*SELECTED
@seladd text=選択肢2 target=*SELECTED
@seladd text=選択肢3 target=*SELECTED
@select

*SELECTED
@cm
戻ります。[p][r]
@jump target=*START
selectwidthで選択肢ボタンの幅、selectheightで選択肢ボタンの高さ、selectcolorで選択肢の文字色、selectbasecolorで選択肢ボタンの色が設定できます。
selopt_1.png

領域設定
前回も言いましたが、KAGEXの選択肢はメッセージレイヤ上にではなく専用のレイヤ上に配置されます。
その専用のレイヤ(以下、領域レイヤ)の位置や大きさも設定できます。
領域レイヤは透明で見えませんが、デフォルトでは画面と同じ大きさになっています。
@道路
@selopt left=120 top=80 width=400 height=320 selectwidth=300 selectheight=50

*START
@cm
選択肢を表示します。[p][r]

@seladd text=選択肢1 target=*SELECTED
@seladd text=選択肢2 target=*SELECTED
@seladd text=選択肢3 target=*SELECTED
@select

*SELECTED
@cm
戻ります。[p][r]
@jump target=*START
leftで領域レイヤの左端、topで上端、widthで幅、heightで高さを設定します。
この画像ではわかりやすいように選択肢領域レイヤの範囲を緑色で塗っています。
selopt_2.png
領域レイヤは選択肢ボタンの表示する範囲になります。
選択肢ボタンはその数に合わせて領域レイヤの中で中央寄せされて配置されます。
選択肢ボタンの位置を1つずつ指定する必要はなく、選択肢を表示する範囲を指定するだけで勝手に配置してくれるわけです。

画像を使う
選択肢ボタンに画像を使うこともできます。
今回は↓の画像を「selopt_button.png」として使います。
「通常の状態」「ボタンが押された状態」「ボタンの上にマウスカーソルがある状態」が並んだボタン用の画像です。
selopt_button.png
@道路
@selopt graphic=selopt_button
*START
@cm
選択肢を表示します。[p][r]

@seladd text=選択肢1 target=*SELECTED
@seladd text=選択肢2 target=*SELECTED
@seladd text=選択肢3 target=*SELECTED
@select

*SELECTED
@cm
戻ります。[p][r]
@jump target=*START
画像ファイルをgraphic属性に指定します。
選択肢の文字は画像の中央に表示されます。
selopt_3.png

graphic属性以外の属性でも画像を指定できます。
↓の三枚をそれぞれ「selopt_button_normal」「selopt_button_on」「selopt_button_over」として使います。
先ほどのボタン画像を三枚に分割しただけです。
selopt_button_normal.png
selopt_button_on.png
selopt_button_over.png
@道路
@selopt normal=selopt_button_normal over=selopt_button_over on=selopt_button_on
*START
@cm
選択肢を表示します。[p][r]

@seladd text=選択肢1 target=*SELECTED
@seladd text=選択肢2 target=*SELECTED
@seladd text=選択肢3 target=*SELECTED
@select

*SELECTED
@cm
戻ります。[p][r]
@jump target=*START
normal属性に通常時の画像、over属性にマウスオーバー時の画像、on属性にボタンが押されたときの画像を指定します。
graphic属性とは異なり一枚ずつ別々に指定できるので便利です。
動作画面はgraphicの例と全く同じになります。

その他にも様々な属性があるのですが、それはまた別の場で紹介します。

次回 KAGEX講座(26) - メッセージ操作([eraftername])

続きを閉じる▲

タグ : 吉里吉里 KAGEX 講座

カテゴリ : KAGEX

TJS小ネタ - foreach

tjsの小ネタ。駄文。foreachの解説。

配列を順に処理するには↓のようにforで添え字をまわします。
var array = [0102030405060708090];

for (var i = 0; i < array.count; i++) {
    Debug.message(array[i]);
}
配列arrayの中身を順にDebug.message関数でコンソールに表示するだけのスクリプトです。
0, 10, 20, ..., 90まで表示されます。

ついでに逆順に処理する例
var array = [0102030405060708090];

for (var i = array.count-1; i >= 0; i--) {
    Debug.message(array[i]);
}
先ほどとは逆に90, 80, 70, ..., 0まで表示されます。


foreachの使い方(1)
辞書配列でもおなじように順に処理したい場合はどうするか。
KAGEXのUtils.tjsにそのためのの関数としてforeach関数が定義してあります。
以下該当部分をコピペ。
/**
 * 辞書の総なめ処理
 * @param dict 辞書
 * @param func 処理ファンクション func(name, value, dict);
 */

function foreach(dict, func, *) {
    if (dict) {
        var names = [];
        names.assign(dict);
        for (var i = 0; i < names.count; i += 2) {
            func(names[i], names[i+1], dict, *);
        }
    }
}
第1引数dictに処理したい辞書配列をわたします。
第2引数funcに辞書配列のそれぞれのペアを処理する関数をわたします。

とりあえず使ってみます。
/* スクリプト例(1) */

// 適当な辞書配列
var hoge = %[
    "first" => 1,
    "second" => 2,
    "third" => 3,
];

// 処理関数
function fuga(name, value, dict) {
    Debug.message("dict[" + name +"] の中身は「" + value + "」です。");
}

// foreachを使う
foreach(hoge, fuga);
これを実行すると以下のように表示されます。
dict[first] の中身は「1」です。
dict[second] の中身は「2」です。
dict[third] の中身は「3」です。
foreachの第2引数にわたした関数(ここではfuga関数)にはいくつか引数がわたされます。
第1引数(name)に添え字の名前が、第2引数(value)にはそれに対応する値がわたされます。
第3引数(dict)は使っていませんが、foreachの第1引数にわたした辞書配列がそのままわたされています。
第1引数と第2引数の内容が順に変わりながら、辞書配列のペアの数だけfuga関数が呼ばれます。
fuga("first"1, hoge);
fuga("second"2, hoge);
fuga("third"3, hoge);
というのを勝手にやってくれるのがforeach関数です。

foreachの使い方(2)
第3引数まではforeachの定義で決められていますが、第4引数以降には好きな引数をわたすことができます。
foreachの第3引数以降にわたしたものが、第4引数以降にそのままわたされます。

以下使ってみるスクリプト。
/* スクリプト例(2) */

// 適当な辞書配列
var hoge = %[
    "first" => 1,
    "second" => 2,
    "third" => 3,
];

// 処理関数
function fuga(name, value, dict, test1, test2) {
    Debug.message("dict[" + name +"] の中身は「" + value + "」です。");
    Debug.message("第4引数の値は:" + test1 + ", 第5引数の値は:" + test2);
    // ↑Debug.messageをもう1行追加
}

// foreachを使う
foreach(hoge, fuga, "test1にわたる値""test2にわたる値");
// ↑第3引数以降にも値をわたす
変更点は、
・関数fugaに引数test1とtest2を追加し、Debug.messageで表示するようにする。
・foreachの第3引数と第4引数に文字列をわたすようにする。
の2点のみです。

これを実行すると以下のように表示されます。
dict[first] の中身は「1」です。
第4引数の値は:test1にわたる値, 第5引数の値は:test2にわたる値
dict[second] の中身は「2」です。
第4引数の値は:test1にわたる値, 第5引数の値は:test2にわたる値
dict[third] の中身は「3」です。
第4引数の値は:test1にわたる値, 第5引数の値は:test2にわたる値

ここではforeachは以下のように処理関数fugaを呼び出しています。
fuga("first"1, hoge, "test1にわたる値""test2にわたる値");
fuga("second"2, hoge, "test1にわたる値""test2にわたる値");
fuga("third"3, hoge, "test1にわたる値""test2にわたる値");


実際にKAGEXで使われている部分を見るとhogeの部分は式中関数としてわたされていることが多いです。
見た目としては↓のようになります。
/* スクリプト例(3) */

// 適当な辞書配列
var hoge = %[
    "first" => 1,
    "second" => 2,
    "third" => 3,
];

// foreachを使う
foreach(hoge, function(name, value, dict) {
    Debug.message("dict[" + name +"] の中身は「" + value + "」です。");
});
実行結果はスクリプト例(1)とおなじになります。

使い方の説明は以上です。次はforeachのスクリプトを解説します。

foreachの仕組み
行番号を振って再掲。
0: function foreach(dict, func, *) {
1:     if (dict) {
2:         var names = [];
3:         names.assign(dict);
4:         for (var i = 0; i < names.count; i += 2) {
5:             func(names[i], names[i+1], dict, *);
6:         }
7:     }
8: }
0行目はただの関数宣言です。
1つ目の引数dictは処理したい辞書配列、2つ目の引数funcは処理関数でした。
3つ目の引数の*は見慣れないかもしれません。
リファレンス参照→http://devdoc.kikyou.info/tvp/docs/tjs2doc/contents/function.html#id214
4行目を見るとfuncの第4引数に*が指定されています。
ここではforeachの第3引数以降をfuncの第4引数以降にわたす機能を果たしています。

1行目はdictがvoidのときには何もしない、程度だと思います。

2行目はnamesに配列を生成しています。

3行目でその配列にわたされた辞書配列dictをコピーしています。
リファレンス参照→http://devdoc.kikyou.info/tvp/docs/tjs2doc/contents/array.html#id14
辞書配列を配列にコピーすると、「名前、値の順に交互に現れる配列」になります。
例えば引数にわたされたdictが
dict["first"] = 1;
dict["second"] = 2;
dict["third"] = 3;
だったとき、配列namesは
names[0] = "first";  // ←1つ目のペアの名前
names[1] = 1;        // ←1つ目のペアの値
names[2] = "second"// ←2つ目のペアの名前
names[3] = 2;        // ←2つ目のペアの値
names[4] = "third";  // ←3つ目のペアの名前
names[5] = 3;        // ←3つ目のペアの値
のようになります。
添え字が偶数の部分にペアの名前、奇数の部分にペアの値が入っている形です。

4,5,6行目のforループで実際にわたされた処理関数funcを呼び出します。
最初のループではi=0です。
このとき「func(names[0], names[1], dict, *);」として呼びだされます。
names[0]="first", names[1]=1だったので使い方の欄で説明したとおりに引数がわたされています。
次のループに入るときにはiに2を足すことで次のペアをわたしてfuncを呼び出します。
2周目のループでは「func(names[2], names[3], dict, *);」となるわけです。
これを最後のペアまで繰り返します。

続きを閉じる▲

タグ : 吉里吉里 KAGEX TJS

カテゴリ : TJS

KAGEX講座(24) - 選択肢表示([select], [seladd])

前回 KAGEX講座(23) - レイヤの拡大、縮小(zoom)
今回はKAGEXの機能を使って選択肢を表示してみます。

envinit.tjsは前回までとおなじです。
選択肢を表示するには[seladd]タグと[select]タグを使います。
@道路
@しおり show

*START
@cm
選択肢を表示します。[p][r]

@seladd text=選択肢1 storage=first.ks target=*sel1
@seladd text=選択肢2 storage=first.ks target=*sel2
@seladd text=選択肢3 storage=first.ks target=*sel3
@select

*sel1
@cm
選択肢1が選択されました[p][r]
@jump target=*START

*sel2
@cm
選択肢2が選択されました。[p][r]
@jump target=*START

*sel3
@cm
選択肢3が選択されました。[p][r]
@jump target=*START

↓実行画面
select_1.png

[seladd]タグでそれぞれの選択肢の内容を指定します。
各属性の意味は以下の通り
text選択肢に表示するテキスト
storage選択された時の飛び先ファイル名を指定します。
target選択されたときの飛び先ラベル名を指定します。
expこの選択肢が選択されたときに実行されるtjs式を指定します。
eval選択肢を表示する条件を指定します。
trueの時表示、falseの時非表示になります。
onceflag表示判定フラグを指定します。
指定した変数がfalseの時に表示、trueの時非表示になります。
この変数には選択されたときに自動的にtrueが代入されます。
※evalとonceflagを同時に指定することはできません。
※exp, eval, onceflagはこのサンプルでは未使用。

[select]タグを使うと[seladd]で指定された選択肢を表示できます。
[select]タグでは[s]タグと同じようにシナリオ進行が止まります。
このタグにもいくつか属性があります。
msgoff選択肢表示時にメッセージウィンドウを隠します。
msgon選択肢表示時にメッセージウィンドウを表示します。
storage[seldone]タグで合流する先のファイル名を指定します。
target[seldone]タグで合流する先のラベル名を指定します。
※[seldone]タグの説明はいつか気が向いたらするかもしれません。

KAGとは違い、選択肢は専用のレイヤ上に表示されます。
メッセージレイヤに配置されるボタンとは別物です。

ついでにサンプルもう一つ。
@道路
@しおり show

*START
@cm
選択肢を表示します。[p][r]

; ▼expを使ったサンプル。選択された選択肢名をf.selTextに代入します
@seladd text=選択肢1     target=*sel exp="f.selText='選択肢1'"
@seladd text=選択肢2     target=*sel exp="f.selText='選択肢2'"
; ▼選択肢3はonceflagを使ったサンプル。選択肢3は一度選択されると以後表示されません
@seladd text=選択肢3     target=*sel exp="f.selText='選択肢3'" onceflag=f.selFlag
@seladd text=フラグクリア target=*sel exp="f.selText='フラグクリア'"
; ▼msgoffを指定するとメッセージレイヤが隠されます
@select msgoff



*sel
@cm
; ▼msgoffで隠されたメッセージレイヤを[msgon]タグで表示
@msgon

[emb exp=f.selText]が選択されました。[p][r]

; ▼「フラグクリア」が選ばれたときにはf.selFlagにfalseを代入する
; ▼ こうすると選択肢3が再び表示されます
@if exp="f.selText == 'フラグクリア'"
    @eval exp="f.selFlag=false"
@endif

@jump target=*START
※[seladd]タグのstorage属性は同じファイル内なので省略しています。

細かい設定の仕方はまた次回。
次回 KAGEX講座(25) - 選択肢設定([selopt])

続きを閉じる▲

タグ : 吉里吉里 KAGEX 講座

カテゴリ : KAGEX

最新記事
カテゴリ

openclose

記事一覧
Twitter
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。