13
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

UnityのGUIで一覧表示

Last updated at Posted at 2014-03-21

Unityでテーブルレイアウトをやる場合はGUI.SelectionGridを使うのがいいかと思いますが、
1行を1つのアイテムに見せるような一覧表示をするのはちょっと難しそうです。

なので、ラベルを組み合わせてテーブルっぽく見せるスクリプトを作ってみました。

ListBox.js
class ListBox {
	static private var clickTimeDelta : float = 1.0;
	private var mouseDownTimeWindow : float;	

	var itemHeight:float = Screen.height / 12;
	var list:List.<System.Object>;
	var callback:Function;
	var top:float;
	var left:float; 
	var width:float; 
	var height:float;
	
	var scrollPosition: Vector2 = Vector2.zero;;
	var selectedInt : int = -1;
	var hoverInt:int = -1;
	
	var columns : String[];	
	var filteredColumns:String[];
	
	var labelTexture:Texture;
	var labelHoverTexture:Texture;
	var labelOnTexture:Texture;
	var labelStyle:GUIStyle;
	var labelStyleCenter:GUIStyle;
	var labelStyleRight:GUIStyle;

	private function refresh(){
		var first = list[0];
		var filteredColumnsArray = new Array();
		if(!first) {
			return;
		}
		var firstDict:Dictionary.<String, System.Object> = first as Dictionary.<String, System.Object>;
		if(firstDict) {
			var keys:Dictionary.KeyCollection.<String, System.Object> = firstDict.Keys;
			if(columns && columns.Length > 0) {
				for(var key in keys){
					for(var key2 in columns){
						if(key2 == key){
							filteredColumnsArray.Add(key);
						}
					}
				}
			} else {
				for(var key in keys){
					filteredColumnsArray.Add(key);
				}
			}
			filteredColumns = filteredColumnsArray.ToBuiltin(String);
		} 
		
		setItemWidth(this.width);
		if(filteredColumns && filteredColumns.Length > 0) {
			setItemWidth(Mathf.Round(this.width / filteredColumns.Length));
		}
	}
	
	private function Initialize(list:List.<System.Object>, callback:Function, top:float, left:float, width:float, height:float){
		labelTexture = Resources.Load("textures/list");
		labelOnTexture = Resources.Load("textures/list_on");
		labelHoverTexture = Resources.Load("textures/list_hover");
		labelStyle = new GUIStyle(GUI.skin.box);
		labelStyle.fontSize = Screen.height / 32;
		
		labelStyle.fixedHeight = itemHeight;
		labelStyle.alignment = TextAnchor.MiddleLeft;
		labelStyle.margin = RectOffset(0, 0, 0, 0);
		labelStyle.padding = RectOffset(16, 16, 0, 0);
		labelStyle.normal.background = labelTexture;

		labelStyleCenter = new GUIStyle(labelStyle);
   		labelStyleCenter.alignment = TextAnchor.MiddleCenter;
   			
   		labelStyleRight = new GUIStyle(labelStyle);
   		labelStyleRight.alignment = TextAnchor.MiddleRight;
   		mouseDownTimeWindow = -1;
   		
   		
		this.list = list;
		this.callback = callback;
		this.top = top;
		this.left = left; 
		this.width = width;
		this.height = height;
		refresh();
	}
	
	private function Initialize(list:List.<System.Object>, callback:Function, top:float, left:float){
		Initialize(list, callback, top, left, Screen.width - (left * 2), Screen.height - (top + itemHeight));
	}
	
	function ListBox(list:List.<System.Object>, callback:Function, top:float, left:float, width:float, height:float){
		Initialize(list, callback, top, left, width, height);
	}
	
	function ListBox(list:List.<System.Object>, callback:Function, top:float, left:float){
		Initialize(list, callback, top, left, Screen.width - (left * 2), Screen.height - (top + itemHeight));
	}
	
	function ListBox(list:List.<System.Object>, callback:Function){
		Initialize(list, callback, itemHeight, itemHeight);
	}
	
	function setItemHeight(_itemHeight:float){
		itemHeight = _itemHeight;
	}
	
	function setList(list:List.<System.Object>){
		this.list = list;
		refresh();
	}
	
	function setColumns(columns:String[]){
		this.columns = columns;
		refresh();
	}
	
	function setItemWidth(width:float) {
		labelStyle.fixedWidth = width;
		labelStyleCenter.fixedWidth = width;
		labelStyleRight.fixedWidth = width;
	}
	
	function setItemTexture(texture:Texture) {
		labelStyle.normal.background = texture;
		labelStyleCenter.normal.background = texture;
		labelStyleRight.normal.background = texture;
	}
	
	function OnGUI() {
		if ( mouseDownTimeWindow > 0 ) {
			mouseDownTimeWindow -= Time.deltaTime;
			if(mouseDownTimeWindow < 0){
				mouseDownTimeWindow = 0;
			}
		}
		var selectStyle:GUIStyle = GUIStyle.none;
   		if(this.list){
   			var oldSelected:int = selectedInt;
   			var currentHeight:float = itemHeight * this.list.Count;
   			var mouseHover = false;
	   		scrollPosition = GUI.BeginScrollView (Rect (top, left, width, height), scrollPosition, Rect (0, 0, width, currentHeight));
				GUILayout.BeginVertical();
				var i:int=0;
				for (var item in this.list){
					if(i == oldSelected){
						setItemTexture(labelOnTexture);
					} else if(i == hoverInt){
						setItemTexture(labelHoverTexture);
					} else {
						setItemTexture(labelTexture);				
					}
					GUILayout.BeginHorizontal();
					var dict:Dictionary.<String, System.Object> = item as Dictionary.<String, System.Object>;
					if(dict){
						var j:int = 0;
						for(var column in filteredColumns) {
							var itemString = "";
							if(dict.ContainsKey(column)){
								itemString = dict[column];
							}
							
							if(j == 0) {
								GUILayout.Label(itemString, labelStyle);
							} else if(j == filteredColumns.Length - 1) {
								GUILayout.Label(itemString, labelStyleRight);
							} else {
								GUILayout.Label(itemString, labelStyleCenter);
							}
							j++;
						}
					} else {
						GUILayout.Label(item as String, labelStyle);
					}
					GUILayout.EndHorizontal();
					var rect:Rect = GUILayoutUtility.GetLastRect();
					var pos:Vector2 = Vector2(Input.mousePosition.x - left, (Screen.height - Input.mousePosition.y) - top);
					if (rect.Contains(pos)) {
						mouseHover = true;
						hoverInt = i;
						if(Input.GetMouseButton(0) || Input.GetMouseButtonUp(0)){
							selectedInt = i;
						} else {
							selectedInt = -1;
						}
					}
					i++;
				}	
				GUILayout.EndVertical();		
			GUI.EndScrollView ();

   			if (selectedInt >= 0) {
   				var mouseOut = ((selectedInt != oldSelected) && (oldSelected >= 0));
				if(mouseOut){
					mouseDownTimeWindow = 0;
					selectedInt = -1;
				} else if(Input.GetMouseButton(0) && mouseDownTimeWindow < 0) {
					mouseDownTimeWindow = clickTimeDelta;
				} else if(!Input.GetMouseButton(0) && (mouseDownTimeWindow > 0)) {
					if(callback){
						callback(list[selectedInt], selectedInt);
					}
					mouseDownTimeWindow = -1;
				} 
			}
			if(!Input.GetMouseButton(0) && mouseDownTimeWindow == 0) {
				mouseDownTimeWindow = -1;
			}
   		}
   	}
}

背景画像はこんな感じで
list.png textures/list
list_hover.png textures/list_hover
list_on.png textures/list_on

表示させる側のコードはこんな感じです

main.js
var listBox:ListBox;

function Start() {
	listBox = null;
}

function OnGUI(){
	if(!listBox){
		var stringList:List.<System.Object> = new List.<System.Object>();
	
		var item1 = new Dictionary.<String, System.Object>();
		item1['name'] = '布の服';
		item1['price'] = '80G';
		stringList.Add(item1);
		
		var item2 = new Dictionary.<String, System.Object>();
		item2['name'] = '旅人の服';
		item2['price'] = '100G';
		stringList.Add(item2);
		
		var item3 = new Dictionary.<String, System.Object>();
		item3['name'] = '銅の剣';
		item3['price'] = '120G';
		stringList.Add(item3);
		
		var item4 = new Dictionary.<String, System.Object>();
		item4['name'] = '銅の盾';
		item4['price'] = '70G';
		stringList.Add(item4);
		listBox = new ListBox(stringList, function(selected, index){
			Debug.Log("Selected '" + selected + "' at " + index);
		});
	}
	
	if (Event.current.type != EventType.keyDown) {
		listBox.OnGUI();
	}
}

実際の表示はこんな感じです。
ss.png

darktablesさんのJSONプラグイン
MiniJSON.csと併用することでJSONを一覧表示することもできます。

13
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?