ドラッグ&ドロップ link

Ren'Py にはマウスで画面上を移動できるドラッグドロップ displayable があります。ドラッグの使用法としては次があります :

  • ウィンドウの位置合わせ、ウィンドウ位置を記憶できるようにする。

  • カードを画面上でドラッグする必要のあるカードゲーム ( 例えばソリティア )。

  • アイテムシステム。

  • ドラッグで並び順を変えるシステム。

ドラッグドロップ displayable は、上記やその他の場面においてドラッグドロップを実装できるようにします。ここに関係する2つのクラスがあります。 Drag クラスは、スクリーン上をドラッグできるもの、またはその上にドロップされたドラッグ可能なものを受け取れるもの、その両方が出来るもののいずれかを表します。 DragGroup クラスは Drag のグループを表します。ドラッグドロップを実行するためには、両方の Drag が同じドラッググループに属していなければなりません。

ドラッグドロップシステムは スクリーン言語 を通してか、または直接 displayable として使用できます。作成後に作成した Drag を参照する必要がないときは、スクリーン言語を使用すると良いでしょう。これはドラッグ可能オブジェクトが、ユーザーがスクリーン上に配置したウィンドウである場合などです。作成後も作成した Drag を参照する必要がある場合は、直接 Drag を作成し、それらを DragGroup に追加すると良いでしょう。

ドロップ link

Ren'Py にはドロップを実施する 2 つの方法があります。

  • mouse_drop が True なら、 drag はマウスカーソルの直下にあるドロップ可能なものにドロップします。

  • mouse_drop はデフォルトで False であり、そうならドロップはその drag ともっとも重なっているドロップ可能なものに行われます。

focus_mask が使用されるドラッグの開始時とは異なり、ドロップでは、透明ピクセルを含む、 ドラッグ可能なものとドロップ可能なものの矩形領域全体が考慮されます。drap と drop displayable はこれを考慮して一般的に矩形にして設計する必要があるでしょう。

Displayable link

class Drag(d=None, drag_name=None, draggable=True, droppable=True, drag_raise=True, dragging=None, dragged=None, dropped=None, drag_handle=(0.0, 0.0, 1.0, 1.0), drag_joined=..., clicked=None, hovered=None, unhovered=None, mouse_drop=False, **properties) link

それを囲んでいる領域上でドラッグ可能なオブジェクトを表わす displayable です。 Drag は他の Drag がドロップ可能な領域も表現できます。

その内側で Drag が移動可能なものを親と呼びます。一般的には親は Fixed()DragGroup であるはずです。

Drag は子を一つ持ちます。子の状態はドラッグドロップ処理の状態を反映します。 :

  • selected_hover ドラッグされている時。

  • selected_idle その上にドロップ可能な時。

  • hover - マウスをクリックすればドラッグ可能オブジェクトをドラッグできる時。

  • idle それ以外。

ドラッグで持てる部分はその子の内側の長方形です。ドラッグやクリックを実行するためにはマウスが Drag のその部分のピクセル上になければなりません。 focus_mask プロパティーが True なら、さらにそのピクセルが不透明でなければなりません。

新しく作成されたドラッグ可能なオブジェクトはデフォルトの DragGroup に追加されます。 ドラッグ可能オブジェクトは 一つの DragGroup にのみ所属できます。二つ目のグループに追加すると、最初のものからは削除されます。

Drag が最初にレンダリングされる時に、それが所属する DragGroup からその座標を決定できない場合その左上の座標が基本的なレイアウトアルゴリズムを使用して算出されます。いったん座標が算出されると、その Drag に保存された座標を優先し、レイアウトプロパティーは無視されます。

d

与えられると、この Drag の子になります。 None でなければ Drag はこれに優先して child スタイルを使用します。

drag_name

None を指定するかこのドラッグ可能オブジェクトの名前を指定します。これはドラッグ可能オブジェクトの name プロパティーとして利用できます。もし同じ名前の Drag がその DragGroup に所属しているまたはしていたならこの Drag の最初の座標はそのドラッグ可能オブジェクトから受け取ります。

draggable

True の場合、Drag はスクリーン上をマウスでドラッグできます。

droppable

True なら他の Drag がこの Drag 上にドロップ可能です。

drag_raise

True ならこの Drag がドラッグされたときにトップまで持ち上げられます。他の Drag と接続されていたら、すべての接続された Drag も持ち上げられます。

activated

Drag 上でマウスが押されたとき呼び出されるコールバック ( またはコールバックのリスト ) です。ドラッグされている Drag のリストを引数に呼び出されます。このコールバックの返り値は無視されます。

dragging

Drag がドラッグ中に呼び出されるコールバック ( またはコールバックのリスト ) です。それは1つの引数で呼び出され、ドラッグされている Drag のリストです。コールバックが None 以外の値を返すと、その値はインタラクションの結果として返されます。

dragged

Drag がドラッグされた時に呼び出されるコールバック ( またはコールバックのリスト ) です。それは二つの引数で呼び出されます。一つ目はドラッグされている Drag のリストです。二つ目はその上にドロップされている Drag か、ドロップが起きていないなら None です。コールバックが None ではなく値を返すとその値はインタラクションの結果として返されます。

dropped

Drag がドロップされた時に呼び出されるコールバック ( またはコールバックのリスト ) です。それは二つの引数で呼び出されます。一つ目はその上にドロップされている Drag 二つ目はドラッグされている Drag のリストです。コールバックが None 以外の値を返すと、その値はインタラクションの結果として返されます。

dragged と dropped のコールバックが同じイベントで起こされると、 dropped コールバックは dragged が None を返したときのみ呼び出されます。

clicked

Drag が移動なしでクリックされたときに、クリックされた Drag を引数に呼び出されるコールバックです。ドロップ可能オブジェクトもフォーカスを持て、クリックすることも可能です。 コールバックが None ではなく値を返したら、その値がインタラクションの結果として返されます。

alternate

Drag が(デスクトップの場合)右クリックされるか動かさないで長押し(モバイル)すると実行されるアクションです。このトリガーがモバイルプラットフォームで早すぎる場合は config.longpress_duration を大きくする必要があります。

hovered

Drag がフォーカスを所得すると実行するアクションです。

unhovered

Drag がフォーカスを失うと実行するアクションです。

tooltip

Drag がホバー状態で表示される tooltip です。

drag_handle

子内部のドラッグ有効範囲の位置を与える (x, y, width, height) のタプルです。このタプルには、 positions を含めます。

drag_joined

これは現在の Drag を引数として呼び出されます。ひとかたまりでドラッグしているドラッグ可能オブジェクトのタプル [ (drag, x, y) ] を返すことが期待されます。 x, y は Drag の互いに対するオフセットで、この drag に対するものではありません。 drag は組み合わされる Drag オブジェクトかそのような Drag の drag_name です。

drag_offscreen

drag が画面外へ動かせるかの条件を判定します。 drag_joined やサイズを変更出来る drag に使用すると、その drag が完全に画面外に出て画面に戻す方法がなくなる可能性があるため危険になり得ます。

これは次のうちどれか1つであるべきです。 :

False

画面外への drag の移動を禁止します(デフォルト)。

True

どの方向にも画面外へのドラッグを許可します。

"horizontal"

水平方向のみ画面外へのドラッグを許可します。

"vertical"

垂直方向のみ画面外へのドラッグを許可します。

(width, height)

width とheight は共に整数でなければなりません。 (width, height) のサイズ分が画面内にある限り、画面外へドラッグできます。例えば (100, 100) ならば、その displayable の他の部分が画面外にあっても、少なくとも 100x100 ピクセルの領域が画面内に残っていると保証します。これをドラッグされている displayable の幅と高さに設定すると、全く画面外へのドラッグを許可しないのと同じになります。

(min_x, max_x, min_y, max_y)

min_x, max_x, min_y, max_y はそれぞれ整数であり、 min_x が左端からのピクセル数、 max_x が右端からのピクセル数です。 min_y と max_y の上端と下端との関係も同じです。ドラッグはその端が指定した端にぶつかるまで動かせます。 (0, 0, 0, 0) は全く画面外へのドラッグを許可しないのと同じになります。

例えば (-100, 200, 0, 0) ならば drag は 100 ピクセル画面の端から左へドラッグでき、 200 ピクセル画面の端から右へドラッグできます。上下の画面外へのドラッグは許可しません。

これを使用して、 drag を画面内の境界に制限できます。 (200, -200, 200, -200) なら画面の端から 200 ピクセル内でのみドラッグを許可します。

これは drag の周りの追加の "境界" を想像しください。これは画面外に境界を置き、その中に drag を制限します。

callable

drag_offscreen には呼び出し可能オブジェクトも渡せます。引数は二つ必要となり、その drag のドラッグされた左上の座標を表す x と y 座標です。 drag の新しい (x, y) 座標となる (x, y) タプルを返さなければいけません。この呼び出し可能オブジェクトは drag の移動中頻繁に呼び出されます。例えば次の関数は drag を 300 ピクセル区切りにスナップします。

def drag_snap(x, y):

    if y < 300:
        y = 0
    elif y < 600:
        y = 300
    else:
        y = 600

    return 200, y
mouse_drop

True なら、 drag はカーソル下の最初のドロップ可能な物にドロップされます。デフォルトでは False で drag は重なりがもっとも大きい ドロップ可能なものにドロップされます。

drop_allowable

現在ドラッグしているもののこれへのドロップを許可するか決定するコールバックです。二つの引数で呼び出され、一つ目はドロップを受け取る Drag, 二つ目はドラッグされている Drag のリストです。

snapped

ドラッグがスナップを完了すると呼び出されるコールバック(またはコールバックのリスト)です。4つの引数で呼び出されます。1つ目はスナップアニメーションが処理された Drag です。2つ目と3つ目は Drag がスナップするよう設定された x と y 座標です。4つ目は真偽値で、 True ならスナップアニメーションは成功し、 False なら中断しました。例えば次の関数はスナップアニメーションが中断されると、その Drag の start_x と start_y 位置を意図したスナップ位置に設定します。

def snapped_callback(drag, x, y, completed):
    if not completed:
        drag.start_x = x
        drag.start_y = y

d を除いてパラメーターのすべてはその Drag オブジェクトでフィールドとして ( 同じ名前で ) 利用可能です。さらに Drag がレンダリングされた後は次のフィールドが利用可能になります。

x, y

ピクセルでのその親に対する Drag の位置

start_x, start_y

ピクセルでのその親に対するドラッグ開始時の Drag の位置

grab_x, grab_y

ピクセルでのその Drag に対する捕まれた x, y 位置です。

last_drop

離せば現在の Drag をドロップできる最後尾の Drag であり、妥当な Drag が現在なければ None になります。

snapping

この Drag がスナップアニメーションの途中なら True になります。

w, h

Drag の子のピクセルでの幅と高さです。

bottom() link

この displayable をその DragGroup の最下端にします。

set_child(d) link

この Drag の子を d に変更します。

snap(x, y, delay=0, warper=None) link

Drag の位置を変更します。 Drag が表示されていないと位置の変更は瞬間です。そうでなければ、位置の変更は delay 秒かけて任意のワーパーで行われ、ワーパーが指定されていなければ等速で移動します。

top() link

この displayable をその DragGroup のトップに持ち上げます。

class DragGroup(*children, **properties) link

Drag のグループを表します。ドラッグはその DragGroup 内部に制限されます。ドロップは同じ DragGroup に所属する Drag 間でのみ働きます。 Drag はそれが DragGroup の内側にあるときのみ持ち上げられます。

Fixed() と同様に DragGroup はレイアウトされます。

DragGroup のコンストラクターに渡されるすべての位置パラメーターはその DragGroup に追加される Drag であるべきです。

min_overlap

ドロップが受け入れられる最小のオーバーラップするピクセル数を表す整数です。

add(child) link

ドラッグされなければならない child をこの DragGroup に追加します。 child はこの DragGroup の他の全ての子の上に追加されます。

get_child_by_name(name) link

name の drag_name を持つ DragGroup の最初の子を返します。

remove(child) link

DragGroup から child を除去します。

link

以下の say スクリーンの例では、スクリーン上をドラッグしてユーザーがウィンドウの位置を選べます。

screen say(who, what):

    drag:
        drag_name "say"
        yalign 1.0
        drag_handle (0, 0, 1.0, 30)

        xalign 0.5

        window id "window":
            # Ensure that the window is smaller than the screen.
            xmaximum 600

            has vbox

            if who:
                text who id "who"

            text what id "what"

こちらはより複雑な例で、どのようにゲームプレイにドラッグを使用して影響を与えられるかを示します。どのようにキャラクターをドラッグしてある場所に移せるかを表わしています。

init python:

    def detective_dragged(drags, drop):

        if not drop:
            return

        store.detective = drags[0].drag_name
        store.city = drop.drag_name

        return True

screen send_detective_screen:

    # A map as background.
    add "europe.jpg"

    # A drag group ensures that the detectives and the cities can be
    # dragged to each other.
    draggroup:

        # Our detectives.
        drag:
            drag_name "Ivy"
            droppable False
            dragged detective_dragged
            xpos 100 ypos 100

            add "ivy.png"
        drag:
            drag_name "Zack"
            droppable False
            dragged detective_dragged
            xpos 150 ypos 100

            add "zack.png"

        # The cities they can go to.
        drag:
            drag_name "London"
            draggable False
            xpos 450 ypos 140

            add "london.png"

        drag:
            drag_name "Paris"
            draggable False
            xpos 500 ypos 280

            add "paris.png"

label send_detective:
    "We need to investigate! Who should we send, and where should they go?"

    call screen send_detective_screen

    "Okay, we'll send [detective] to [city]."

より複雑なシステムを正しく構築するためには、かなりのプログラミング技術が必要です。

as 節を使用して drag と変数を結び付け、その Drag のメソッドを呼び出すのに使用出来るようにします。

screen snap():

    drag:
        as carmen
        draggable True
        xpos 100 ypos 100
        frame:
            style "empty"
            background "carmen.png"
            xysize (100, 100)

            vbox:
                textbutton "London" action Function(carmen.snap, 450, 140, 1.0)
                textbutton "Paris" action Function(carmen.snap, 500, 280, 1.0)