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); } } }
private static void ModifyContentInstance(string viewName, GameObject currentContentInstance, List <ContentInfo> currentContents) { var contentName = currentContentInstance.name.ToLower(); // set default rect. var rectTrans = currentContentInstance.GetComponent <RectTransform>(); rectTrans.anchoredPosition = new Vector2(0, 0); rectTrans.anchorMin = new Vector2(0, 1); rectTrans.anchorMax = new Vector2(0, 1); // 画像か文字を含んでいるコンテンツで、コードも可。でもボタンの実行に関しては画像に対してボタンが勝手にセットされる。ボタンをつけたらエラー。 // 文字のリンク化も勝手に行われる。というかあれもボタンだっけ。 // ボタンコンポーネントが付いていたら外す。 if (currentContentInstance.GetComponent <Button>() != null) { throw new Exception("do not attach Button component directory. Button component will be attached automatically."); } var components = currentContentInstance.GetComponents <Component>(); var type = TreeType.Content_Img; if (components.Length < 3) { type = TreeType.Content_Img; } else { // foreach (var s in components) { // Debug.LogError("s:" + s.GetType().Name); // } // rectTrans, canvasRenderer 以外を採用する。 var currentFirstComponent = components[2]; switch (currentFirstComponent.GetType().Name) { case "Image": { type = TreeType.Content_Img; break; } case "Text": { type = TreeType.Container; // not Content_Text. break; } default: { throw new Exception("unsupported second component on content. found component type:" + currentFirstComponent); } } } // 名前を登録する currentContents.Add(new ContentInfo(contentName, type, "resources://" + ConstSettings.PREFIX_PATH_INFORMATION_RESOURCE + viewName + "/" + contentName.ToUpper())); // このコンポーネントをprefab化する { var prefabPath = "Assets/InformationResources/Resources/Views/" + viewName + "/" + contentName.ToUpper() + ".prefab"; var dirPath = Path.GetDirectoryName(prefabPath); FileController.CreateDirectoryRecursively(dirPath); PrefabUtility.CreatePrefab(prefabPath, currentContentInstance); // 自体の削除 GameObject.DestroyImmediate(currentContentInstance); } }