CTRL (日本語)

CTRL - Control & Trigger Relays Library (制御&トリガー中継ライブラリ) - LÖVE 入力

基本的な使用方法に関しては簡単であり同時に強靭かつ広範囲の用途で先進的です。このライブラリではユーザ入力を処理するために必要な全ての機能を提供しており、ネイティブのフレームワークでは対応していない入力デバイスを処理するにも十分な技術で拡張することができます。

基本的な使用方法

使用を開始するには CTRL クラスのインスタンスを作成する必要があり(何らかの理由があり多数の CTRL のインスタンスが必要な場合は、それを作成することはできます)、イベントハンドラのコールバック関数を定義する必要があります。 CTRL により取り除かれた関連性のない入力イベントにおけるすべての情報、および残りの最も有用なステート(状態)の改善を除き、大部分は通常の LÖVE の入力コールバックと同様の方法で動作します。その後に一部の入力バインディングを作成する必要があります。そして最後に、 LÖVE 入力イベントを接続するための CTRL のインスタンスが必要となります。

コードの一例

local ctrl = require ( 'ctrl' ) ( )
function ctrl:inputpressed ( name, value ) print ( "pressed", name, value ) end
function ctrl:inputreleased ( name, value ) print ( "released", name, value ) end
function ctrl:inputmoved ( name, value ) print ( "moved", name, value ) end
ctrl:bind ( "fire", { "keyboard", "space" } )
ctrl:bind ( "fire", { "joystick", "default", "button", 1 } )
ctrl:bind ( "fire", { "mouse", "left" } )
ctrl:hookup ( )

有効な入力値の一覧

  • "keyboard"
    • すべて LÖVE の標準キーボード定数
  • "mouse"
    • "x", "y", "wheelx", "wheely", "left", "right", "middle"
    • 4, 5, 6, など。
  • "gamepad"
    • "default" またはジョイスティック用の任意の既存マッピングです
      • "axis"
        • "leftx", "rightx", "lefty", "righty", "triggerleft", "triggerright"
      • "button"
        • "a", "b", "x", "y", "back", "guide", "start", "leftstick", "rightstick", "leftshoulder", "rightshoulder"
      • "hat"
        • "up", "down", "left", "right"
  • "joystick"
    • "default" またはジョイスティック用の任意の既存デバイスマッピングです
      • "axis"
        • 1, 2, 3, など。
      • "button"
        • 1, 2, 3, など。
      • "hat"
        • 1, 2, 3, など。
          • "up", "down", "left", "right"

デフォルトではジョイスティックおよびゲームパッドのマップは "default" であり、これで大抵の場合は事足ります。

詳細

CTRL は基本的な機能性の上にたくさんの組み合わせることのできる機能を有しています。

入力の自動取得

入力設定画面で最も有用です。 grab 関数を使用することで利用者が Select (選択) の動作をするボタン押しても CTRL は自動的にバインド (接続、結線) 設定を行うことができ、そして全入力信号から望む入力だけを残して、それ以外をフィルタリング (除外、篩い分け) する設定を行うことができます。三種類の引数は全てオプション (必要に応じて選択) ですが、いずれかのコールバックまたは自動バインディング名称が存在するべきです (そうでなければ有効な動作は行われません)。

local bindname = "foo"
callback = function ( input )
	-- 利用者が  "escape" を押した場合は入力を取り消すか、またはバインドを行います。
	if input[ 1 ] == "keyboard" and input[ 2 ] == "escape" then ctrl:grab ( )
	else ctrl:bind ( bindname, input ) end
end
ctrl:grab ( callback )


-- 自動バインドに対しては次回の全入力を "foo" の動作として CTRL へ設定を行い、キーボードとゲームパッドからの入力のみできるようにします。
ctrl:grab ( "foo", { { "keyboard" }, { "gamepad", nil, "button" } } )

取得した入力バインディングを保存することは意味のあることです。それを CTRL で行うための機能として saveData および loadData 関数があります。ファイル名を渡してデータの読み込み・保存ができます。saveData に何も渡さない場合は、保存されたデータの文字列を返します。loadData の代わりに前述したデータの文字列を渡すことができます。

カスタムバインディング

最も重要な機能の一つはバインディングのカスタマイズ機能です。これは bind 関数の第三引数である bind のオプション引数 options へテーブルを渡すことで得られます。mapper テーブルが有するのはバインディングと結びついた生の値による再マッピング関数に関しての情報を有することができ、 filter テーブル は生の値からの最終実時間によるマッピング値に関して類似情報を有することができ、さらに events テーブルは、このバインディングで生成を行うイベントの一覧を有することができます。


Mapper (マッパー) テーブルは二種類の名称の値を有しています:

  • func: マッピングを行う関数
  • args (オプション): 関数へ渡すための追加の引数テーブル

マッパー関数 (後述) は登録された文字列による名前の mapper 関数または関数値のいずれかです。呼び出し時に、 raw, last mapped, args, ... を渡します。第一引数は入力デバイスからの生の値です。第二引数は最後に呼び出されたときに出力された値です。第三引数は args であり、なにかのデータを有しているか、まったく存在しないオプションのテーブルです。最後の引数で vararg が渡されます。そられは全て有していますが、追加の生のイベント引数は一般的なイベントハンドラ関数へ渡されます。マウスイベントを除き標準的な LÖVE イベントは空となるため、 dx dy および isTouch はマウスのコールバックとなります。これを通じて多種多様な生の入力情報を渡すことでカスタムの生の入力イベントを定義することができます。

local fooMapper = function ( raw, last, args, ... )
	return raw * args.foo
end
ctrl:bind ( "foo", { "keyboard", "f" }, { mapper = { func = fooMapper, args = { foo = 1 } } } )


Filter (フィルター) テーブルは二種類の名称の値を有しています:

  • func: マッピングを行う関数
  • args (オプション): 関数へ渡すための追加の引数テーブル

マッパーと同様、フィルタ関数 (後述) は登録された文字列による名前の filter 関数または関数値のいずれかです。呼び出し時に、 dt, mapped または raw, last filtered, args を渡します。第一引数は update 関数からの dt です。第二引数は現在のマップ値 (マッパー未設定時は生の値) です。第三引数は最後に呼び出されたときに出力された値です。第四引数は args であり、なにかのデータを有しているか、まったく存在しないオプションのテーブルです。

local fooFilter = function ( dt, raw, last, args )
	return last + raw * dt
end
ctrl:bind ( "foo", { "keyboard", "f" }, { filter = { func = fooFilter } } )


イベントテーブルはイベントテーブルの一覧を有しています。 Filter (フィルター) テーブルは各三種類の名称の値を有しています:

  • trigger: 入力されたイベントを切り替えるかどうかを決定するための関数
  • handler: 入力されたイベントを処理するために呼び出されるコールバック関数
  • args (オプション): トリガー関数へ渡される追加の引数テーブル

トリガー関数 (後述) は登録された文字列による名前の trigger 関数または関数値のいずれかです。呼び出し時に、 current, previous, args を渡します。第一引数は現在の値です。第二引数は以前の値です。第三引数は args であり、なにかのデータを有しているか、まったく存在しないオプションのテーブルです。

ハンドラ関数は文字列による名前の既存イベントハンドラ関数 (単に正常であると定義されている) または関数値のいずれかです。呼び出し時に、 ctrl, name, value を渡します。第一引数はこのイベントを作動させた CTRL のインスタンスです。第二引数はこのイベントを作動させたバインド済みの動作名称です。第三引数は現在の値です。

local fooTrigger = function ( curr, last, args )
	return curr > last
end
local inputFooBar = function ( ctrl, name, value )
	print ( "foobar", name, value )
end
ctrl:bind ( "foo", { "keyboard", "f" }, { events = { foobar = { trigger = fooTrigger, handler = inputFooBar } } } )


マッパー、フィルタおよびトリガー関数は "登録済み" およびバインディングのコードから文字列名称により参照することができます。すぐに使用しないのであれば、ビットデータを一切消失することなく、データセーバーへ正確なバインディングを記憶することができます: 付加された関数のコードはファイルへ保存することはできませんが、文字列の名称は保存可能です。イベントハンドラのコールバックは明示的登録する必要はなく、 LÖVE の入力コールバックの定義と同様の方法で CTRL のインスタンスを定義します。バインディングのオプションを関数へ渡す代わりに、その方法 (訳注: インスタンスのことだと思います) を使う理由はマッパー、フィルタおよびトリガーと同じです。

ctrl:addMapperFunction ( "fooMapper", fooMapper )
ctrl:addFilterFunction ( "fooFilter", fooFilter )
ctrl:addTriggerFunction ( "fooTrigger", fooTrigger )
function ctrl:inputFooBar ( name, value )
	print ( "foobar", name, value )
end

CTRL はデフォルトで豊富なマッパー、フィルタ、トリガーを標準装備しています:

  • deadzone: アナログ入力範囲を 0 より小さい領域で固定します (args = { deadzone = 0.1 })
  • remap: 全部のアナログ入力範囲を異なる出力範囲へマッピングします (args = { rawmin = 0, rawmax = 1, mapmin = 0, mapmax = 1, min = 0, max = 1 })


  • smooth: 出力値を生の値に向かってスムーズに移動します (args = { speed = 1 })
  • ramp: 生の値により上下に出力値を動かします (args = { speed = 1, min = 0, max = 1 })


  • pressed: 値が 0.25 以下に下降するときに作動します
  • released: 値が 0.75 以上に上昇するときに作動します
  • moved: どのような量であっても値の変化が発生したときに作動します

ゲームパッドのマッピング

CTRL 流の入力テーブルを受け入れる点を除き、LÖVE の gamepadMapping と同じ方法で機能しますので、 grab 関数を使用してゲームパッドのマッピングを設定することができます。

local joystick = love.joystick.getJoysticks[ 1 ]
local inputtype = "start"
local callback = function ( input )
	ctrl:setGamepadMapping ( joystick, inputtype, input )
end
-- ジョイスティックのボタンのみ対象として取得、フィルタ処理を開始します
ctrl:grab ( callback, { "joystick", nil, "button" } )

カスタム入力メソッド

これは仮想キーボードおよびモバイル機器で見かける仮想ジョイスティックといった純粋な仮想デバイスと同様にカスタム入力デバイスを使用できるようにします。これを行うには二種類の方法があります。一つ目の方法はカスタム入力デバイスのイベントを標準的なイベントへ流すことです。カスタムデバイスは表に出てこないため標準的なデバイスからは識別できません。二つ目の方法は新しい入力の種類を定義して手動で一般的な入力ハンドラ関数を呼び出すことです。

ctrl:addInputs ( { "virtualkeyboard", "A" }, { "w", "s", "a", "d" } )
ctrl:addInputs ( { "virtualkeyboard", "B" }, { "u", "j", "h", "k" } )

ctrl:bind ( "foo", { "virtualkeyboard", "A", "w" } )
ctrl:bind ( "bar", { "virtualkeyboard", "B", "u" } )
 . . .
function virtualkeyboard:pressed ( section, key )
	ctrl:handleUpdate ( { "virtualkeyboard", section, key }, 1 )
end
function virtualkeyboard:released ( section, key )
	ctrl:handleUpdate ( { "virtualkeyboard", section, key }, 0 )
end

デバイスマッピング

入力の種類が (キーボードやマウスのように) ユニークで繰り返し識別できないならば、その ID は実行時に生成する必要があります。それを行うための様々な方法はありますが、そのすべては一つたりとも全てを終わらせる銀の銃弾ではありません。これはデバイスの自動識別に関して CTRL が完全に止まってしまう理由であるため、代わりにデフォルトとして "default" のマッピングの行うために、自作の ID 生成関数を実装する必要があります。大抵の場合はデフォルトを使うだけで事足りますが、一部のシナリオとして、ローカル型のマルチプレイヤーゲームのように、同一デバイスであってもデバイスが類似していることがあるため識別を必要とします。よくある方法の人ととしてゲームパッドごとにインデックス番号を割り当て、番号によりゲームパッドを参照することです。もう一つの方法として必然的に GUID またはゲームパッドのリテラル名を取得して、それがユニークなものでなければ、区別をするために数字を付け加えることが必要です。一度 ID 生成を完了すると、 mapDevice 関数を使用して、この ID をジョイスティックに割り当てることができます:

local id = produceId ( joystick )
ctrl:mapDevice ( joystick, id )

リファレンスマニュアル

ctrl ( ), ctrl.new ( ) 入力ハンドラのインスタンスを新規作成して返します
ctrl:hookup ( )	デフォルトの LÖVE 入力コールバックに関して寄生対象の入力ハンドラを接続します
ctrl:bind ( name, input, [options] ) 入力の名称で指定された入力をバインドします
	* name - バインドを行う入力名称
	* input - バインドを行う CTRL の入力アドレス
	* options (オプション) - オプションのテーブルであり、以下のフィールドを有することができます:
		* mapper (オプション) - 生の値からなるマッパーのテーブルを記述します
			* func - マッパーのコールバック関数であり、マップ処理済みの値を返します
			* args (オプション) - コールバック関数の引数テーブル
		* filter (オプション) - フィルタの値を記述します
			* func - フィルタのコールバック関数であり、フィルタ処理済みの値を返します
			* args (オプション) - コールバック関数の引数テーブル
		* events (オプション) - イベントの一覧を記述したテーブルを有するテーブルです。各テーブルが有しているものは:
			* trigger	 - callback trigger function, returns true if event should be triggered
			* handler - callback handler function, called if event is triggered
			* args (optional) - callback trigger arguments table
ctrl:unbind ( [name], [input] )	unbinds specified inputs
	* name (optional) - input name to unbind
	* input (optional) - ctrl input address to unbind
	if called without arguments, unbinds everything
	if called without input address, unbinds everything bound to a specific name
	if called without name, unbinds everything bound to a specific address
	input address can be partial address, then it acts like a filter, unbinds everything that matches
ctrl:grab ( [callback], [autobind], [filters] )	starts tracking input devices for any activity, grabs the first one that changes
	* callback (optional) - function that will be called when activity is detected
		shall return true if it should ignore current input and track the next one
		called with the following arguments:
			* input - CTRL の入力アドレステーブル
			* name - the autobind argument unmodified
	* autobind (optional) - string input name to which it would automatically bind anything it finds
	* filters (optional) - list of ctrl input addresses that it will match against during tracking
ctrl:getBindings ( [name], [input] ) finds and returns list of all input addresses bound to a specified input name
	* name (optional) - name to look bindings for
	* input (optional) - ctrl input path to look in
	if name is not passed, finds all bindings
	input can be partial path, then it acts as a filter
	list entries have the following format:
		* name - 入力の文字列名
		* input - CTRL の入力アドレステーブル
		* options - 入力オプションのテーブル (マッパー、フィルタ、イベント)
ctrl:isUp ( name ) returns true if value of an input is under 0.25
	* name - input name to look for
ctrl:isDown ( name ) returns true if value of an input is above 0.75
	* name - input name to look for
ctrl:getValue ( name ) returns value of an input
	* name - input name to look for
ctrl:resetValues ( ) resets all values to 0
	focusing out and in a window combined with some ways of input handling can cause input glitches,
	resetting all values solves that problem
ctrl:mapDevice ( device, value ) maps userdata or table device to a string, number or boolean value
	* device - the input device userdata, table or any other value by which it's referenced
	* value - string, number or boolean value by which its input would be addressed
	should be used with joysticks and gamepads and other devices without persistent ID
ctrl:getMapping ( device ) returns previously mapped value for this device, defaults to "default"
	* device - the input device to look for
ctrl:setGamepadMapping ( joy, control, input ) mirros love.joystick.setGamepadMapping, but provides seamless integraiton with the library
	* joy - löve Joystick object to map
	* control - löve Gamepad control (button, hat, axis)
	* input - ctrl joystick input path table
ctrl:getGamepadMapping ( joy, control ) mirros love.joystick.getGamepadMapping, but provides seamless integraiton with the library
	* joy - löve Joystick object to get mapping from
	* control - löve Gamepad control (button, hat, axis)
	returns ctrl joystick input address table for selected Gamepad control
ctrl:addInputs ( input, new ) adds new values to the valid inputs list
	* input - ctrl input path to add to
	* new - list of additional valid inputs, can contain a metatable
ctrl:handleUpdate ( input, raw, ... ) processes input event and dispatches callbacks
	* input - CTRL の入力アドレステーブル
	* raw - 生の値
	* vararg - 生のマッパー関数へ渡される任意の追加値
ctrl:addTriggerFunction ( name, func ) adds new trigger function to the list
	* name - string name of new event trigger function
	* func - callback function, shall return true if event should be triggered
		called with the following arguments:
			* 現在の値
			* 以前の値
			* 関数の引数テーブル
ctrl:addFilterFunction ( name, func ) adds new filter function to the list
	* name - string name of new value filter function
	* func - callback function, shall return filtered value
		called with the following arguments:
			* 最終呼び出しからの経過時間
			* 生の入力値
			* 以前にフィルタ処理された値
			* 関数の引数テーブル
ctrl:addMapperFunction ( name, func ) adds new raw value mapper function to the list
	* name - string name of new raw value mapper function
	* func - callback function, shall return mapped raw value
		called with the following arguments:
			* 生の値
			* 以前にマップ処理された値
			* 関数の引数テーブル
			* vararg passed into input event handler function
ctrl:saveData ( [filename] ) saves all internal data to a file, returns data string if file is not provided
	* filename (optional) - filename to store data in
ctrl:loadData ( filename ) ファイルまたは文字列からデータを読み込みます
	* filename - データ読み込み先のファイル名、またはデータ文字列
ctrl:handleUpdate ( dt )
ctrl:handleKeypressed ( key, code, repeated )
ctrl:handleKeyreleased ( key, code, repeated )
ctrl:handleMousepressed ( x, y, button, touch )
ctrl:handleMousereleased ( x, y, button, touch )
ctrl:handleMousemoved ( x, y, dx, dy, touch )
ctrl:handleWheelmoved ( x, y )
ctrl:handleGamepadaxis ( joy, axis, value )
ctrl:handleGamepadpressed ( joy, button )
ctrl:handleGamepadreleased ( joy, button )
ctrl:handleJoystickaxis ( joy, axis, value )
ctrl:handleJoystickhat ( joy, hat, dir )
ctrl:handleJoystickpressed ( joy, button )
ctrl:handleJoystickreleased ( joy, button )
ctrl:handleJoystickadded ( joy )
ctrl:handleJoystickremoved ( joy )
	LÖVE input event handlers. To be called manually as appropriate if CTRL instance is not "hooked" up.

リンク

そのほかの言語