public LayerInfo(string layerName, BoxPos unboxedLayerSize, BoxConstraint[] boxes, string loadPath) { this.layerName = layerName; this.unboxedLayerSize = unboxedLayerSize; this.boxes = boxes; this.loadPath = loadPath; }
private static void ModifyLayerInstance(string viewName, GameObject currentLayerInstance, List <LayerInfoOnEditor> currentLayers, float parentWidth, float parentHeight) { // このインスタンスのポジションを0,0 leftTopAnchor、左上pivotにする。 // レイヤーのインスタンスは、インスタンス化時に必ず親のサイズにフィットするように変形される。 // ただし、親がboxではないlayerの場合、パーツ作成時の高さが使用される。 // アンカーは成立するため、相対的な配置をしつつ、レイアウトを綺麗に行うことができる。 var rectTrans = currentLayerInstance.GetComponent <RectTransform>(); var anchorWidth = (parentWidth * rectTrans.anchorMin.x) + (parentWidth * (1 - rectTrans.anchorMax.x)); var anchorHeight = (parentHeight * rectTrans.anchorMin.y) + (parentHeight * (1 - rectTrans.anchorMax.y)); var calculatedWidth = parentWidth - anchorWidth - rectTrans.offsetMin.x + rectTrans.offsetMax.x; var calculatedHeight = parentHeight - anchorHeight - rectTrans.offsetMin.y + rectTrans.offsetMax.y; var unboxedLayerSize = new BoxPos(rectTrans, calculatedHeight); rectTrans.anchoredPosition = new Vector2(0, 0); rectTrans.anchorMin = new Vector2(0, 1); rectTrans.anchorMax = new Vector2(0, 1); rectTrans.pivot = new Vector2(0, 1); var size = new Vector2(calculatedWidth, calculatedHeight); if (size.x <= 0 || size.y <= 0) { throw new Exception("layer size is negative. size:" + size); } var layerName = currentLayerInstance.name.ToLower(); var childrenConstraintDict = new Dictionary <string, BoxPos>(); var copiedChildList = new List <GameObject>(); /* * 元々のchildrenを別GameObjectとして分離 */ { foreach (Transform component in currentLayerInstance.transform) { var childGameObject = component.gameObject; // enableでなければスキップ if (!childGameObject.activeSelf) { continue; } var newChildGameObject = GameObject.Instantiate(childGameObject); newChildGameObject.name = childGameObject.name; copiedChildList.Add(newChildGameObject); } } using (new GameObjectDeleteUsing(copiedChildList.ToArray())) { /* * box情報を生成 */ { foreach (var boxObject in copiedChildList) { var boxRectTrans = boxObject.GetComponent <RectTransform>(); var boxName = layerName + "_" + boxObject.name; if (childrenConstraintDict.ContainsKey(boxName)) { throw new Exception("another box:" + boxName + " is already exist in layer:" + layerName + ". please set other name for each customTag on this layer."); } childrenConstraintDict[boxName] = new BoxPos(boxRectTrans, 0); } } /* * layer内のboxの削除(レイアウトの動的な伸張、変更を実行時に動的に行ないたいため、jsonにして吐き出す。実態がないほうがいい) */ { var list = new List <GameObject>(); for (var i = 0; i < currentLayerInstance.transform.childCount; i++) { list.Add(currentLayerInstance.transform.GetChild(i).gameObject); } // 取り出してから消す foreach (var childObj in list) { GameObject.DestroyImmediate(childObj); } } /* * このレイヤーのunboxed時のサイズと、内包しているboxの情報を追加 */ { var newChildConstraint = childrenConstraintDict .Select(kv => new BoxConstraint(kv.Key, kv.Value)) .ToArray(); var newLayer = new LayerInfo( layerName, unboxedLayerSize, newChildConstraint, "resources://" + ConstSettings.PREFIX_PATH_INFORMATION_RESOURCE + viewName + "/" + layerName.ToUpper() ); currentLayers.Add(new LayerInfoOnEditor(newLayer, size)); } /* * このprefabはlayer = レイアウトを行う前提の箱として使われる。 * レイヤー内には、box = 特定の名前の要素(prefabになる前の子供ゲームオブジェクト名のタグ要素)のみをレイアウトする。 * そのboxタグの中身にはなんでも入れることができる。 * * prefab名は大文字 になる。 */ { var prefabPath = "Assets/InformationResources/Resources/Views/" + viewName + "/" + layerName.ToUpper() + ".prefab"; var dirPath = Path.GetDirectoryName(prefabPath); FileController.CreateDirectoryRecursively(dirPath); PrefabUtility.CreatePrefab(prefabPath, currentLayerInstance); // layer自体の削除 GameObject.DestroyImmediate(currentLayerInstance); } /* * 取り出しておいたchildに対して再帰 */ foreach (var disposableChild in copiedChildList) { ModifyLayerInstance(viewName, disposableChild, currentLayers, calculatedWidth, calculatedHeight); } } }
/** * 画面幅、高さから、uGUIの計算を行って実際のレイアウト時のパラメータを算出する。 * パラメータとして渡って来るboxPosには、親のサイズに対してのレイアウト値が含まれた状態。 * */ public static Rect GetChildViewRectFromParentRectTrans(float parentWidth, float parentHeight, BoxPos pos, out float rightPadding, out float bottomPadding) { /* * 出せるものは次の要素。 * ・要素の起点位置(左上オフセット) * ・要素のサイズ * ・要素のパディング(右下オフセット) * * 基本的に、親のサイズに対して各数値が決まる。 * * まず左下のポイントが定まる。これは、anchorMinがどこを指すかに影響される。 * xが0の場合、offsetMinは左からの値になる。 * xが1の場合、offsetMinは右からの値になる。 * * アンカー座標系(右上に加算される系)において、 * * 左下のX位置 * anchorMinXという値が置けて、 * anchorMinX = width * anchorMin.x(0で左端、1で右端になる) * 左下のX位置は、(width * anchorMin.x) + offsetMin.x になる。 * * 左下のY位置 * anchorMinYという値が置けて、 * anchorMinY = height * anchorMin.y(0で下端、1で上端になる) * 左下のYの位置は、(height * anchorMin.y) + offsetMin.y になる。 * * 右上のX位置 * anchorMaxXという値が置けて、 * anchorMaxX = width * anchorMax.x(0で左端、1で右端になる) * 右上のX位置は、(width * anchorMax.x) + offsetMax.x になる。 * * 右上のY位置 * anchorMaxYという値が置けて、 * anchorMaxY = height * anchorMax.y(0で下端、1で上端になる) * 右上のYの位置は、(height * anchorMax.y) + offsetMax.y になる。 * * となる。 * * これらの値によって、anchorによって決められた描画位置とサイズが得られる。 * * y値は調整が必要で、下から上の変な系になっているため、実際のparentHeightから引く、という形になる。 * * また、heightは、下からの系なので、常にbottomY > topYとなるため、bottomY - topYとなる。 * * 各anchor値に対して、異常値(親の予算を無視した高い値)を指定できるため、 * 実際の親のサイズを使って導出する位置値にリミッターをかける。 */ var leftX = (parentWidth * pos.anchorMin.x) + pos.offsetMin.x; if (leftX < 0) { leftX = 0f; } var rightX = (parentWidth * pos.anchorMax.x) + pos.offsetMax.x; if (parentWidth < rightX) { rightX = parentWidth; } var bottomY = parentHeight - ((parentHeight * pos.anchorMin.y) + pos.offsetMin.y); if (parentHeight < bottomY) { bottomY = parentHeight; } var topY = parentHeight - ((parentHeight * pos.anchorMax.y) + pos.offsetMax.y); if (topY < 0) { topY = 0f; } var viewWidth = rightX - leftX; var viewHeight = bottomY - topY; /* * 右下の余白 * この値を実際に採用するかは、boxを並べる側で判断する。 */ rightPadding = parentWidth - (leftX + viewWidth); bottomPadding = parentHeight - (topY + viewHeight); // Debug.Log("leftX:" + leftX + " rightX:" + rightX + " topY:" + topY + " bottomY:" + bottomY + " width:" + viewWidth + " height:" + viewHeight + " rightPadding:" + rightPadding + " bottomPadding:" + bottomPadding); // Debug.LogWarning("parentHeight:" + parentHeight + " topY:" + topY + " viewHeight:" + viewHeight + " bottomPadding:" + bottomPadding); var resultRect = new Rect(leftX, topY, viewWidth, viewHeight); return(resultRect); }
public BoxConstraint(string boxName, BoxPos rect) { this.boxName = boxName.ToLower(); this.rect = rect; }