private void CollectTreeIdRecursive(TagTree sourceTree, float treeOffsetY, float offsetY, float viewHeight, List <string> drawTargetTreeIds) { var currentTreeOffsetY = treeOffsetY + sourceTree.offsetY; // Debug.Log("currentTreeOffsetY:" + currentTreeOffsetY + " offsetY:" + offsetY + " viewHeight:" + viewHeight); // top is in range or not. if (offsetY + viewHeight < currentTreeOffsetY) { // do nothing. return; } // bottom is in range or not. if (currentTreeOffsetY + sourceTree.viewHeight < offsetY) { // do nothing. return; } // this container is in range. drawTargetTreeIds.Add(sourceTree.id); var childlen = sourceTree.GetChildren(); for (var i = 0; i < childlen.Count; i++) { var child = childlen[i]; CollectTreeIdRecursive(child, currentTreeOffsetY, offsetY, viewHeight, drawTargetTreeIds); } }
private static void ResetRecursive(TagTree tree) { tree.hidden = tree.hiddenDefault; foreach (var child in tree.GetChildren()) { ResetRecursive(child); } }
public static void ShowLayoutRecursive(TagTree tree) { Debug.Log("tree:" + tree.tagValue + " treeType:" + tree.treeType + " offsetX:" + tree.offsetX + " offsetY:" + tree.offsetY + " width:" + tree.viewWidth + " height:" + tree.viewHeight); foreach (var child in tree.GetChildren()) { ShowLayoutRecursive(child); } }
private static void CollectTreeIdsRecursive(TagTree tree, List <string> treeIds) { if (tree.keyValueStore.ContainsKey(HTMLAttribute.ID)) { treeIds.Add(tree.keyValueStore[HTMLAttribute.ID] as string); } foreach (var child in tree.GetChildren()) { CollectTreeIdsRecursive(child, treeIds); } }
public static string ShowWholeContent(TagTree tree) { var builder = new StringBuilder(); builder.AppendLine(ShowContent(tree)); foreach (var child in tree.GetChildren()) { var childInf = " " + ShowWholeContent(child); builder.AppendLine(childInf); } return(builder.ToString()); }
private static void FindTreeByIdRecursively(TagTree tree, string id, List <TagTree> collectingTrees) { if (tree.keyValueStore.ContainsKey(HTMLAttribute.ID)) { var idCandidate = tree.keyValueStore[HTMLAttribute.ID] as string; if (idCandidate == id) { collectingTrees.Add(tree); } } foreach (var child in tree.GetChildren()) { FindTreeByIdRecursively(child, id, collectingTrees); } }
private static void CorrectRecursive(TagTree tree, List <string> usingIds) { var isUsing = !tree.hidden; if (isUsing) { usingIds.Add(tree.id); } var children = tree.GetChildren(); /* * 前方に元tree、後方に挿入treeがある場合があるので、 * childrenを逆にした配列を用意して畳み込みを行う。 */ var removeTargets = new List <TagTree>(); foreach (var reverted in children.AsEnumerable().Reverse()) { CorrectRecursive(reverted, usingIds); if (reverted is InsertedTree) { var insertedTree = reverted as InsertedTree; var baseTree = insertedTree.parentTree; // merge contents to base. baseTree.keyValueStore[HTMLAttribute._CONTENT] = baseTree.keyValueStore[HTMLAttribute._CONTENT] as string + insertedTree.keyValueStore[HTMLAttribute._CONTENT] as string; removeTargets.Add(insertedTree); } } foreach (var removeTarget in removeTargets) { tree.RemoveChild(removeTarget); } }
private void ExpandCustomTagToLayer(TagTree layerBaseTree) { var adoptedConstaints = resLoader.GetConstraints(layerBaseTree.tagValue); var children = layerBaseTree.GetChildren(); /* * これで、 * layer/child * -> * layer/box/child x N * になる。boxの数だけ増える。 */ foreach (var box in adoptedConstaints) { var boxName = box.boxName; var boxingChildren = children.Where(c => resLoader.GetLayerBoxName(layerBaseTree.tagValue, c.tagValue) == boxName).ToArray(); foreach (var boxingChild in boxingChildren) { var boxingChildChildren = boxingChild.GetChildren(); foreach (var boxingChildChild in boxingChildChildren) { if (!resLoader.IsDefaultTag(boxingChildChild.tagValue)) { switch (boxingChildChild.treeType) { case TreeType.Content_CRLF: case TreeType.Content_Text: { parseFailed((int)ParseErrors.CANNOT_CONTAIN_TEXT_IN_BOX_DIRECTLY, "tag:" + resLoader.GetTagFromValue(boxingChildChild.tagValue) + " could not contain text value directly. please wrap text content with some tag."); return; } } } } } if (boxingChildren.Any()) { var boxTag = resLoader.FindOrCreateTag(boxName); // 新規に中間box treeを作成する。 var newBoxTreeAttr = new AttributeKVs() { { HTMLAttribute._BOX, box.rect }, { HTMLAttribute._COLLISION, box.collisionGroupId } }; var boxTree = new TagTree(boxTag, newBoxTreeAttr, TreeType.CustomBox); // すでに入っているchildrenを取り除いて、boxを投入 layerBaseTree.ReplaceChildrenToBox(boxingChildren, boxTree); // boxTreeにchildを追加 boxTree.AddChildren(boxingChildren); // boxingChildがlayerな場合、parentがboxであるというマークをつける。 foreach (var child in boxingChildren) { switch (child.treeType) { case TreeType.CustomLayer: { child.keyValueStore[HTMLAttribute._LAYER_PARENT_TYPE] = "box"; break; } case TreeType.CustomBox: { child.keyValueStore[HTMLAttribute._LAYER_PARENT_TYPE] = "box"; break; } } } } } var errorTrees = layerBaseTree.GetChildren().Where(c => c.treeType != TreeType.CustomBox); if (errorTrees.Any()) { parseFailed((int)ParseErrors.NOT_RESERVED_TAG_IN_LAYER, "unexpected tag:" + string.Join(", ", errorTrees.Select(t => resLoader.GetTagFromValue(t.tagValue)).ToArray()) + " found at customLayer:" + resLoader.GetTagFromValue(layerBaseTree.tagValue) + ". please exclude not defined tags in this layer, or define it on this layer."); } }
// スクロールイベントから生成を行う ↓ // オブジェクトプールの再考(画面外に行ったオブジェクトのプール復帰、新しい要素のプールからの取得) // Layer系のオブジェクト、高さが0のツリー、hiddenを無視する(この辺は上記のチョイス時に削れると良さそう。) public IEnumerator Materialize(GameObject root, UUebViewCore core, TagTree tree, Vector2 viewRect, float yOffset, Action onLoaded) { var viewHeight = viewRect.y; { var rootRectTrans = root.GetComponent <RectTransform>(); this.core = core; // set anchor to left top. rootRectTrans.anchorMin = Vector2.up; rootRectTrans.anchorMax = Vector2.up; rootRectTrans.pivot = Vector2.up; rootRectTrans.sizeDelta = new Vector2(tree.viewWidth, tree.viewHeight); } // 描画範囲にあるツリーのidを集める。ここから一瞬でも外れたらskip。 var drawTreeIds = TraverseTree(tree, yOffset, viewHeight); // materialize root's children in parallel. var children = tree.GetChildren(); var cors = new List <IEnumerator>(); for (var i = 0; i < children.Count; i++) { var child = children[i]; var cor = MaterializeRecursive(child, root, drawTreeIds); cors.Add(cor); } // firstviewのmaterializeまでを並列で実行する while (true) { for (var i = 0; i < cors.Count; i++) { var cor = cors[i]; if (cor == null) { continue; } var cont = cor.MoveNext(); if (!cont) { cors[i] = null; } } var running = cors.Where(c => c != null).Any(); // wait all coroutine's end. if (!running) { break; } yield return(null); } onLoaded(); }
/** * 現状は全ての子について1f内で各1度は実行する、という処理になっている。 * n-m-o * \p-q * \r * * みたいな数のツリーがある場合、 * nのツリーを処理する段階で、毎フレームm,qが1度ずつ展開される。 * mの展開時にはoが毎フレーム1度ずつ展開される。 * pの展開時には、qとrが毎フレーム1度ずつ展開される。 * * なので、全てのツリーが1fに1度は初期化されるようになる。 */ private IEnumerator MaterializeRecursive(TagTree tree, GameObject parent, List <string> drawTargetTreeIds) { // Debug.LogError("materialize:" + tree.treeType + " tag:" + resLoader.GetTagFromValue(tree.tagValue)); if (tree.keyValueStore.ContainsKey(HTMLAttribute.LISTEN) && tree.keyValueStore.ContainsKey(HTMLAttribute.HIDDEN)) { core.AddListener(tree, tree.keyValueStore[HTMLAttribute.LISTEN] as string); } if (tree.hidden || tree.treeType == TreeType.Content_CRLF) { // cancel materialize of this tree. yield break; } // if (!drawTargetTreeIds.Contains(tree.id)) // { // yield break; // } var objCor = resLoader.LoadGameObjectFromPrefab(tree.id, tree.tagValue, tree.treeType); while (objCor.MoveNext()) { if (objCor.Current != null) { break; } yield return(null); } // set pos and size. var newGameObject = objCor.Current; var cached = false; if (newGameObject.transform.parent != null) { cached = true; } newGameObject.transform.SetParent(parent.transform, false); var rectTrans = newGameObject.GetComponent <RectTransform>(); rectTrans.anchoredPosition = TagTree.AnchoredPositionOf(tree); rectTrans.sizeDelta = TagTree.SizeDeltaOf(tree); // set parameters and events by container type. button, link. var src = string.Empty; if (tree.keyValueStore.ContainsKey(HTMLAttribute.SRC)) { src = tree.keyValueStore[HTMLAttribute.SRC] as string; } switch (tree.treeType) { case TreeType.Content_Img: case TreeType.CustomLayer: { if (tree.viewHeight == 0) { break; } // 画像コンテンツはキャッシュ済みの場合再度画像取得を行わない。 if (!cached) { // 画像指定がある場合のみ読み込む if (!string.IsNullOrEmpty(src)) { var imageLoadCor = resLoader.LoadImageAsync(src); // combine coroutine. var setImageCor = SetImageCor(newGameObject, imageLoadCor); resLoader.LoadParallel(setImageCor); } } break; } case TreeType.Content_Text: { // テキストコンテンツは毎回内容が変わる可能性があるため、キャッシュに関わらず更新する。 if (tree.keyValueStore.ContainsKey(HTMLAttribute._CONTENT)) { var text = tree.keyValueStore[HTMLAttribute._CONTENT] as string; if (!string.IsNullOrEmpty(text)) { pluggable.SetText(newGameObject, text, tree.keyValueStore.ContainsKey(HTMLAttribute._IS_SINGLE_LINE)); } } // 文字コンテンツのリンク化(hrefがついてるとリンクになる。実態はボタン。) if (tree.keyValueStore.ContainsKey(HTMLAttribute.HREF)) { var href = tree.keyValueStore[HTMLAttribute.HREF] as string; var linkId = string.Empty; if (tree.keyValueStore.ContainsKey(HTMLAttribute.ID)) { linkId = tree.keyValueStore[HTMLAttribute.ID] as string; } eventObjectCache[linkId] = new KeyValuePair <GameObject, string>(newGameObject, href); // add button component. AddButton(newGameObject, () => core.OnLinkTapped(newGameObject, href, linkId)); } break; } default: { // do nothing. break; } } // button attrに応じたボタン化 if (tree.keyValueStore.ContainsKey(HTMLAttribute.BUTTON)) { var isButton = tree.keyValueStore[HTMLAttribute.BUTTON] as string == "true"; if (isButton) { var buttonId = string.Empty; if (tree.keyValueStore.ContainsKey(HTMLAttribute.ID)) { buttonId = tree.keyValueStore[HTMLAttribute.ID] as string; } eventObjectCache[buttonId] = new KeyValuePair <GameObject, string>(newGameObject, src); // add button component. AddButton(newGameObject, () => core.OnImageTapped(newGameObject, src, buttonId)); } } var children = tree.GetChildren(); var enums = new List <IEnumerator>(); for (var i = 0; i < children.Count; i++) { var child = children[i]; var cor = MaterializeRecursive(child, newGameObject, drawTargetTreeIds); enums.Add(cor); } while (0 < enums.Count) { for (var i = 0; i < enums.Count; i++) { var continuation = enums[i].MoveNext(); if (!continuation || enums[i].Current != null) { // 終わったので除外する enums.RemoveAt(i); } } yield return(null); } }