/// <summary>Destroys this renderman when it's no longer needed.</summary> public void Destroy() { if (FirstBatch != null) { // Pool: UIBatchPool.AddAll(FirstBatch, LastBatch); // Hide: UIBatchPool.HideAll(); } RootDocument.clear(); }
/// <summary>Sets up the current batch based on the isolation settings requested by a property.</summary> /// <param name="property">The displayable property which wants the batch.</param> /// <param name="fontTexture">The font texture to use with this batch.</param> public void SetupBatch(DisplayableProperty property, TextureAtlas graphics, TextureAtlas font) { if (property.Isolated) { if (property.GotBatchAlready) { // The property already got a batch on this layout - it doesn't need another. return; } // Isolated properties always get a new batch every time. CurrentBatch = UIBatchPool.Get(this); if (CurrentBatch == null) { CurrentBatch = new UIBatch(this); } property.GotBatchAlready = true; // And push it to the active stack: AddBatch(CurrentBatch); // Make sure it knows it's isolated: CurrentBatch.IsIsolated(property); } else { if (CurrentBatch != null && !CurrentBatch.Isolated) { // Re-use existing batch? if (font != null) { if (CurrentBatch.FontAtlas == null) { // Didn't have one assigned before. Assign now: CurrentBatch.SetFontAtlas(font); } else if (font != CurrentBatch.FontAtlas) { // Font atlas changed. Can't share. CurrentBatch = null; } } if (graphics != null) { if (CurrentBatch.GraphicsAtlas == null) { // Didn't have one assigned before. Assign now: CurrentBatch.SetGraphicsAtlas(graphics); } else if (graphics != CurrentBatch.GraphicsAtlas) { // Atlas changed. Can't share. CurrentBatch = null; } } if (CurrentBatch != null) { // Yep - reuse it. return; } } // Pull a batch from the pool and set it to currentbatch. May need to generate a new one. CurrentBatch = UIBatchPool.Get(this); if (CurrentBatch == null) { CurrentBatch = new UIBatch(this); } // And push it to the active stack: AddBatch(CurrentBatch); // Make sure it knows it's not isolated: CurrentBatch.NotIsolated(graphics, font); } // Finally, prepare it for layout: CurrentBatch.PrepareForLayout(); }
/// <summary>Sets up the current batch as a 'globally isolated' batch. This acts like a hybrid between isolated /// and shared.</summary> /// <param name="property">The displayable property which wants the batch.</param> /// <param name="fontTexture">The font texture to use with this batch.</param> public void SetupBatchGI(DisplayableProperty property, TextureAtlas graphics, TextureAtlas font) { if (!property.Isolated) { // Ordinary non-isolated batch: SetupBatch(property, graphics, font); return; } if (property.GotBatchAlready) { // Re-use existing batch? if (font != null) { if (CurrentBatch.FontAtlas == null) { // Didn't have one assigned before. Assign now: CurrentBatch.SetFontAtlas(font); } else if (font != CurrentBatch.FontAtlas) { // Font atlas changed. Can't share. CurrentBatch = null; } } if (graphics != null) { if (CurrentBatch.GraphicsAtlas == null) { // Didn't have one assigned before. Assign now: CurrentBatch.SetGraphicsAtlas(graphics); } else if (graphics != CurrentBatch.GraphicsAtlas) { // Atlas changed. Can't share. CurrentBatch = null; } } if (CurrentBatch != null) { // Yep - reuse it. return; } } // First timer or new one required - create: CurrentBatch = UIBatchPool.Get(this); if (CurrentBatch == null) { CurrentBatch = new UIBatch(this); } property.GotBatchAlready = true; // And push it to the active stack: AddBatch(CurrentBatch); // Use the global material, but set it as isolated // (note that we don't want to set CurrentBatch.IsolatedProperty as it may get unintentionally spammed): CurrentBatch.NotIsolated(graphics, font); CurrentBatch.Isolated = true; // Finally, prepare it for layout: CurrentBatch.PrepareForLayout(); }
/// <summary>Relocates all DOM elements by calculating their onscreen position. /// Each element may allocate sections of the 3D mesh (blocks) which are then flushed out /// into the unity mesh and onto the screen.</summary> public void Layout() { DoLayout = false; FullReflow = true; HighestUpdateMode = UpdateMode.None; Reset(); // Invalidate input pointers: // (So they figure out what elements are under the mouse/fingers) PowerUI.Input.PointersInvalid = true; // First, push all batches to the pool - inlined for speed: // Note that no isolated batches enter either the queue or the pool until their no longer isolated. if (FirstBatch != null) { LastBatch.BatchAfter = UIBatchPool.First; UIBatchPool.First = FirstBatch; } FirstBatch = LastBatch = null; // Note: Batches are Prepared For Layout as they are added. LayoutOccuring = true; // Position elements locally. // This sets their ParentOffset values and as a result finds their PixelWidth. IRenderableNode root = RootDocument.documentElement as IRenderableNode; if (root != null) { // Perform the initial reflow: RenderableData rd = root.RenderData; rd.UpdateCss(this); rd.Reflow(this); // Next up, position them globally: // This calculates OffsetLeft/Top and also fires the render event on the computed style object. rd.Render(this); } LayoutOccuring = false; // Tell each batch we're done laying them out: UIBatch currentBatch = FirstBatch; while (currentBatch != null) { currentBatch.CompletedLayout(); currentBatch = currentBatch.BatchAfter; } if (StylesToUpdate != null) { // Clear the isPainting flag. RenderableData style = StylesToUpdate; StylesToUpdate = null; while (style != null) { style.NextUpdateMode = UpdateMode.None; style = style.Next; } } // Hide all pool entries: UIBatchPool.HideAll(); FullReflow = false; }
/// <summary>Update causes all changes to be applied and layouts to occur.</summary> public void Update() { if (DoLayout && AllowLayout) { // Layout RootDocument. Layout(); } else if (StylesToUpdate != null) { // Local update - these events typically fire from changes to things like colour/z-index etc // as well as for reflows of "flow root" nodes. // It's done down here incase a full layout request is made (above). // If a full layout request was made, it would cover all of these anyway. UpdateMode modeToUse = HighestUpdateMode; HighestUpdateMode = UpdateMode.None; bool anyReflowMode = ((int)modeToUse > (int)UpdateMode.PaintAll); if (anyReflowMode) { // We'll be re-rendering. Reset(); // Invalidate input pointers: // (So they figure out what elements are under the mouse/fingers) PowerUI.Input.PointersInvalid = true; // First, push all batches to the pool - inlined for speed: // Note that no isolated batches enter either the queue or the pool until their no longer isolated. if (FirstBatch != null) { LastBatch.BatchAfter = UIBatchPool.First; UIBatchPool.First = FirstBatch; } FirstBatch = LastBatch = null; // Note: Batches are Prepared For Layout as they are added. LayoutOccuring = true; } Css.RenderableData style = StylesToUpdate; StylesToUpdate = null; while (style != null) { UpdateMode mode = style.NextUpdateMode; switch (mode) { case UpdateMode.PaintAll: // Don't bother if we're doing either kind of reflow: if (anyReflowMode) { continue; } // Repaint it: style.RepaintAll(this); break; case UpdateMode.Paint: // Repaint it: style.Repaint(this); // Must also repaint the nodes child text nodes too (as they share the same CS): NodeList kids = style.Node.childNodes_; if (kids != null) { // For each child node.. for (int i = 0; i < kids.length; i++) { // Get it as a text node: Node child = kids[i]; if (child is TextNode) { // Repaint it too: (child as IRenderableNode).RenderData.Repaint(this); } } } break; case UpdateMode.Reflow: // Flow root reflow request. // Must setup stacks and any other renderer settings here! // Perform the initial reflow now: style.UpdateCss(this); style.Reflow(this); break; case UpdateMode.Render: // Only call render: style.Render(this); break; /* * case UpdateMode.FastReflow: * * // Fast reflow request only requires a repaint. * * break; */ } // Clear its update mode: style.NextUpdateMode = UpdateMode.None; style = style.Next; } if (!anyReflowMode) { // Only a flush is required: UIBatch toFlush = FirstBatch; while (toFlush != null) { toFlush.Flush(); toFlush = toFlush.BatchAfter; } } else { // Position elements locally. // This sets their ParentOffset values and as a result finds their PixelWidth. IRenderableNode root = RootDocument.documentElement as IRenderableNode; if (root != null) { // Finally, position them globally: // This calculates OffsetLeft/Top and also fires the render event on the computed style object. root.RenderData.Render(this); } LayoutOccuring = false; // Tell each batch we're done laying them out: UIBatch currentBatch = FirstBatch; while (currentBatch != null) { currentBatch.CompletedLayout(); currentBatch = currentBatch.BatchAfter; } // Hide all pool entries: UIBatchPool.HideAll(); } } }