public void LayoutElements(UIRenderContext rctx, float nsx0, float nsy0, float nsx1, float nsy1) { float expX = (nsx1 - nsx0) - m_data.width; float expY = (nsy1 - nsy0) - m_data.height; if (expX < 0) expX = 0; if (expY < 0) expY = 0; for (int i = 0; i < m_rtData.Length; i++) { outki.UIElement el = m_rtData[i].element; if (el == null) continue; UIElementLayout layout; float width = el.layout.width + el.expansion.width * expX; float height = el.layout.height + el.expansion.height * expY; layout.nsx0 = nsx0 + el.layout.x + el.expansion.x * expX; layout.nsy0 = nsy0 + el.layout.y + el.expansion.y * expY; layout.nsx1 = layout.nsx0 + width; layout.nsy1 = layout.nsy0 + height; layout.x0 = (float) Math.Floor(layout.nsx0 * rctx.LayoutScale + rctx.LayoutOffsetX); layout.y0 = (float) Math.Floor(layout.nsy0 * rctx.LayoutScale + rctx.LayoutOffsetY); layout.x1 = layout.x0 + (float) Math.Floor(0.5f + width * rctx.LayoutScale); layout.y1 = layout.y0 + (float) Math.Floor(0.5f + height * rctx.LayoutScale); m_rtData[i].renderer.OnLayout(rctx, ref layout); m_rtData[i].layout = layout; } }
public static UITiledFill CreateFill(UIRenderContext ctx, outki.Texture tex, outki.UIBitmapTilingSettings settings, float x0, float y0, float x1, float y1) { UITiledFill tf = new UITiledFill(); float tileW = settings.UseLayoutScale ? settings.TileWidth * ctx.LayoutScale : settings.TileWidth; float tileH = settings.UseLayoutScale ? settings.TileHeight * ctx.LayoutScale : settings.TileHeight; float numX = (x1 - x0) / tileW; float numY = (y1 - y0) / tileH; int cX = (int)Math.Ceiling(numX) + 1; int cY = (int)Math.Ceiling(numY) + 1; tf.m_xs = new float[cX]; tf.m_ys = new float[cY]; for (int i = 0; i < cX - 1; i++) tf.m_xs[i] = (int)(x0 + i * tileW); for (int i = 0; i < cY - 1; i++) tf.m_ys[i] = (int)(y0 + i * tileH); tf.m_xs[cX - 1] = x1; tf.m_ys[cY - 1] = y1; float lastU1 = (tf.m_xs[cX - 1] - tf.m_xs[cX - 2]) / tileW; float lastV1 = (tf.m_ys[cY - 1] - tf.m_ys[cY - 2]) / tileH; tf.m_tex_f = ctx.TextureManager.ResolveTexture(tex, ctx.LayoutScale, 0, 0, 1, 1); tf.m_tex_r = ctx.TextureManager.ResolveTexture(tex, ctx.LayoutScale, 0, 0, lastU1, 1); tf.m_tex_b = ctx.TextureManager.ResolveTexture(tex, ctx.LayoutScale, 0, 0, 1, lastV1); tf.m_tex_br = ctx.TextureManager.ResolveTexture(tex, ctx.LayoutScale, 0, 0, lastU1, lastV1); return tf; }
public override void OnLayout(UIRenderContext rctx, ref UIElementLayout elementLayout) { base.OnLayout(rctx, ref elementLayout); List<UIDialogManager.DialogInstance> dlgs = UIDialogManager.GetDialogs(); foreach (UIDialogManager.DialogInstance d in dlgs) { LayoutDialog(rctx, ref elementLayout, d); } }
public virtual void Render(UIRenderContext rctx, ref UIElementLayout layout) { DoLiveUpdate(rctx, ref layout); for (int i = 0; i < m_rtData.Length; i++) { if (m_rtData[i].element != null) { RenderSubElement(rctx, ref layout, m_rtData[i].element, m_rtData[i].renderer, ref m_rtData[i].layout); } } }
public void DoLiveUpdate(UIRenderContext rctx, ref UIElementLayout layout) { // Live update bool change = Putki.LiveUpdate.Update(ref m_data); for (int i = 0; i < m_rtData.Length; i++) change |= Putki.LiveUpdate.IsOld(m_rtData[i].element); // reload if changed. if (change) { Setup(m_data, m_handler); OnLayout(rctx, ref layout); } }
public override void Render(UIRenderContext rctx, ref UIElementLayout layout) { List<UIDialogManager.DialogInstance> dlgs = UIDialogManager.GetDialogs(); float fadeTarget = 0; if (dlgs.Count > 0) fadeTarget = 1; if (m_plateFade == -1) { m_plateFade = fadeTarget; } else { m_plateFade += rctx.FrameDelta * 5.0f * (fadeTarget - m_plateFade); if (fadeTarget == 1 && m_plateFade > 0.98f) m_plateFade = 1.0f; else if (fadeTarget == 0 && m_plateFade < 0.02f) m_plateFade = 0.0f; } outki.UIColor plate = new outki.UIColor(); plate.r = 0; plate.g = 0; plate.b = 0; plate.a = (byte)(128 * m_plateFade); UIRenderer.DrawSolidRect(layout.x0, layout.y0, layout.x1, layout.y1, plate); base.Render(rctx, ref layout); foreach (UIDialogManager.DialogInstance d in dlgs) { // Reinitialize if have no renderer, or handled by wrong widget.. if (d.Renderer == null || d.DialogContainerTag != (object)this) { d.DialogContainerTag = (object)this; d.Renderer = m_handler.CreateWidgetRenderer(d.Template); LayoutDialog(rctx, ref layout, d); } d.Renderer.Render(rctx, ref layout); } }
private void LayoutDialog(UIRenderContext rctx, ref UIElementLayout layout, UIDialogManager.DialogInstance dlg) { if (dlg.Renderer != null) dlg.Renderer.OnLayout(rctx, ref layout); }
public void Draw(float x0, float y0, float x1, float y1, float frameDelta, UIInputManager inputManager, EventHandler eventHandler) { bool mod = false; mod |= Putki.LiveUpdate.Update(ref m_screen); mod |= Putki.LiveUpdate.Update(ref m_screen.Root); if (mod) { CreateAndInit(); } // calculate the scale bool preserveLayoutAspect = m_screen.Config.PreserveLayoutAspect; bool useLayoutScaling = (m_screen.Config.ScaleMode == outki.UIScaleMode.ScaleMode_Prop_Layout); bool useMatrixScaling = (m_screen.Config.ScaleMode == outki.UIScaleMode.ScaleMode_Prop_Transform); UIElementLayout el = new UIElementLayout(); // Compute the actual screen pixels (first iteration), to figure out where on // the display this screen should be layouted. if (preserveLayoutAspect) { float cutW = m_screen.Root.width - m_screen.Config.CutL - m_screen.Config.CutR; float cutH = m_screen.Root.height - m_screen.Config.CutT - m_screen.Config.CutB; // when layouting here, float sWidth = (x1 - x0) / cutW; float sHeight = (y1 - y0) / cutH; // use the lowest size. float sScale = sWidth < sHeight ? sWidth : sHeight; float tgtWidth = (float)Math.Floor(m_screen.Root.width * sScale); float tgtHeight = (float)Math.Floor(m_screen.Root.height * sScale); el.x0 = (float)Math.Floor((x0 + x1 - tgtWidth) / 2); el.y0 = (float)Math.Floor((y0 + y1 - tgtHeight) / 2); el.x1 = el.x0 + tgtWidth; el.y1 = el.y0 + tgtHeight; } else { el.x0 = x0; el.y0 = y0; el.x1 = x1; el.y1 = y1; } // Compute the (uniform) scale factor to use for layout/matrix scaling. UIRenderContext rctx = new UIRenderContext(); rctx.InputManager = inputManager; rctx.TextureManager = m_textureManager; rctx.EventHandler = eventHandler; rctx.FrameDelta = frameDelta; if (rctx.EventHandler == null) rctx.EventHandler = new NullEventHandler(); if (useLayoutScaling || useMatrixScaling) { float sWidth = (el.x1 - el.x0) / m_screen.Root.width; float sHeight = (el.y1 - el.y0) / m_screen.Root.height; float sScale = sWidth < sHeight ? sWidth : sHeight; if (m_screen.Config.SnapScale) { for (int i=0;i<m_screen.ScalingForSnapping.Length;i++) { if (sScale > m_screen.ScalingForSnapping[i]) { sScale = m_screen.ScalingForSnapping[i]; break; } } } rctx.LayoutScale = sScale; rctx.LayoutOffsetX = -(float)Math.Floor(el.x0 * (rctx.LayoutScale - 1)); rctx.LayoutOffsetY = -(float)Math.Floor(el.y0 * (rctx.LayoutScale - 1)); } else { rctx.LayoutScale = 1; rctx.LayoutOffsetX = 0; rctx.LayoutOffsetY = 0; } // the non scaled, layout rect. el.nsx0 = el.x0; el.nsy0 = el.y0; el.nsx1 = el.x0 + (float) Math.Floor((el.x1 - el.x0) / rctx.LayoutScale); el.nsy1 = el.y0 + (float) Math.Floor((el.y1 - el.y0) / rctx.LayoutScale); m_rootRenderer.OnLayout(rctx, ref el); m_rootRenderer.Render(rctx, ref el); }
public void OnLayout(UIRenderContext rctx, float x0, float y0, float x1, float y1) { if (m_data is outki.UIBitmapFill) { outki.UIBitmapFill bf = m_data as outki.UIBitmapFill; if (bf.Tiling.EnableRepeatTiling) m_tiledFillRender = UITiledFill.CreateFill(rctx, bf.Texture, bf.Tiling, x0, y0, x1, y1); else m_tiledFillRender = null; } }
public void Draw(UIRenderContext ctx, float x0, float y0, float x1, float y1) { if (m_data == null) return; if (Putki.LiveUpdate.Update(ref m_data)) ResolveTextures(ctx); switch (m_data._rtti_type) { case outki.UISolidFill.TYPE: { outki.UISolidFill sf = m_data as outki.UISolidFill; UIRenderer.DrawSolidRect(x0, y0, x1, y1, sf.color); break; } case outki.UIGradientFill.TYPE: { outki.UIGradientFill gf = m_data as outki.UIGradientFill; UIRenderer.DrawGradientRect(x0, y0, x1, y1, gf.topleft, gf.topright, gf.bottomleft, gf.bottomright); break; } case outki.UIBitmapFill.TYPE: { if (m_tiledFillRender != null) { m_tiledFillRender.Draw(); } else { } break; } case outki.UISlice9Fill.TYPE: { outki.UISlice9Fill s9 = m_data as outki.UISlice9Fill; x0 -= (float) Math.Floor(s9.ExpandLeft * ctx.LayoutScale); y0 -= (float) Math.Floor(s9.ExpandTop * ctx.LayoutScale); x1 += (float) Math.Floor(s9.ExpandRight * ctx.LayoutScale); y1 += (float) Math.Floor(s9.ExpandBottom * ctx.LayoutScale); float[] xs = new float[4] { x0, x0 + s9.MarginLeft * ctx.LayoutScale, x1 - s9.MarignRight * ctx.LayoutScale, x1 }; float[] ys = new float[4] { y0, y0 + s9.MarginTop * ctx.LayoutScale, y1 - s9.MarginBottom * ctx.LayoutScale, y1 }; for (int y = 0; y < 3; y++) { if (ys[y + 1] <= ys[y]) continue; for (int x = 0; x < 3; x++) { if (xs[x + 1] <= xs[x]) continue; UIRenderer.DrawTexture(m_tex[3 * y + x], xs[x], ys[y], xs[x + 1], ys[y + 1]); } } } break; } }
public void ResolveTextures(UIRenderContext rctx) { if (m_data is outki.UISlice9Fill) { outki.UISlice9Fill s9 = (outki.UISlice9Fill) m_data; m_tex = new UIRenderer.Texture[9]; int p = 0; int[] us = new int[4] { 0, s9.MarginLeft, s9.texture.Width - s9.MarignRight, s9.texture.Width }; int[] vs = new int[4] { 0, s9.MarginTop, s9.texture.Height - s9.MarginBottom, s9.texture.Height }; for (int y = 0; y < 3; y++) { int v0 = vs[y]; int v1 = vs[y+1]; for (int x = 0; x < 3; x++) { int u0 = us[x]; int u1 = us[x+1]; m_tex[p++] = rctx.TextureManager.ResolveTexture(s9.texture, rctx.LayoutScale, u0, v0, u1, v1, true); } } } }
// This can be overriden for custom drawing. public virtual void RenderSubElement(UIRenderContext rctx, ref UIElementLayout myLayout, outki.UIElement element, UIElementRenderer renderer, ref UIElementLayout layout) { renderer.Render(rctx, ref layout); }
public virtual void OnLayout(UIRenderContext rctx, ref UIElementLayout elementLayout) { LayoutElements(rctx, elementLayout.nsx0, elementLayout.nsy0, elementLayout.nsx1, elementLayout.nsy1); }
public FormattedText FormatText(UIRenderContext ctx, string text, int pixelSize_, float wrapLength = 0.0f) { // Only during live editing. if (m_data == null || pixelSize_ < 1) return null; FormattedText fmt = new FormattedText(); fmt.glyphs = new FormattedGlyph[text.Count()]; fmt.lines = 1; float pixelSize = pixelSize_ * ctx.LayoutScale; outki.FontOutput f = null; double minDiff = 10000; foreach (outki.FontOutput fo in m_data.Outputs) { double diff = (float)Math.Abs(1 - (float)fo.PixelSize / (float)pixelSize); if (diff < minDiff) { minDiff = diff; f = fo; } } float scaling = (float)pixelSize / (float)f.PixelSize; if (f.OutputTexture != null) fmt.texture = ctx.TextureManager.ResolveTexture(f.OutputTexture, 1.0f, 0, 0, 1, 1); int pen = 0; fmt.x0 = 10000; fmt.x1 = -10000; fmt.y0 = 10000; fmt.y1 = -10000; fmt.facey0 = - scaling * f.BBoxMaxY / 64.0f; fmt.facey1 = - scaling * f.BBoxMinY / 64.0f; int penBreak = (int)(wrapLength * 64.0 / scaling); float yOffset = 0; for (int i = 0; i < text.Length; i++) { int gl = (int) text[i]; fmt.glyphs[i].u0 = 0; fmt.glyphs[i].v0 = 0; fmt.glyphs[i].u1 = 0; fmt.glyphs[i].v1 = 0; fmt.glyphs[i].wordbreak = (gl == ' '); fmt.glyphs[i].w = -666; if (pen > 0) { int left = text[i - 1]; int right = gl; for (int k=0;k<f.KerningCharL.Count();k++) if (f.KerningCharL[k] == left && f.KerningCharR[k] == right) { pen += (int)(m_spacingMultiplier * f.KerningOfs[k]); break; } } if (pen > penBreak && penBreak > 0) { // do word wrap. int k = i; while (k > 0) { if (fmt.glyphs[k].wordbreak) { // leave the wordbreak on that line and start next i = k; pen = 0; yOffset += fmt.facey1 - fmt.facey0; break; } k--; } // reset to a new line if (pen == 0) { // relayout from here. fmt.lines++; continue; } } bool gotit = false; foreach (outki.FontGlyphPixData fgl in f.PixGlyphs) { if (m_cache == null) break; if (fgl.glyph == gl) { string glyphId = "fnt-" + f.PixelSize + "-" + fgl.glyph; DynamicGlyphCache.Entry entry = m_cache.GetGlyph(glyphId, m_data, fgl); if (entry == null) break; fmt.glyphs[i].u0 = entry.rect._u0; fmt.glyphs[i].v0 = entry.rect._v0; fmt.glyphs[i].u1 = entry.rect._u1; fmt.glyphs[i].v1 = entry.rect._v1; fmt.glyphs[i].texture = entry.atlas.m_uitexture; float x = (scaling * ((pen + fgl.bearingX) >> 6)); float y = (scaling * ((0 + fgl.bearingY) >> 6)); float w = fgl.pixelWidth * scaling; float h = fgl.pixelHeight * scaling; fmt.glyphs[i].x = x; fmt.glyphs[i].y = y + yOffset; fmt.glyphs[i].w = w; fmt.glyphs[i].h = h; if (x < fmt.x0) fmt.x0 = x; if (x+w > fmt.x1) fmt.x1 = x+w; if (y < fmt.y0) fmt.y0 = y; if (y + h > fmt.y1) fmt.y1 = y + h; pen += (int)(m_spacingMultiplier * fgl.advance); gotit = true; break; } } if (gotit) { continue; } foreach (outki.FontGlyph fgl in f.Glyphs) { if (fgl.glyph == gl) { // rescale into possible uncropped texture float uo = fmt.texture.u0; float us = fmt.texture.u1 - fmt.texture.u0; float vo = fmt.texture.v0; float vs = fmt.texture.v1 - fmt.texture.v0; fmt.glyphs[i].u0 = fgl.u0; fmt.glyphs[i].v0 = fgl.v0; fmt.glyphs[i].u1 = fgl.u1; fmt.glyphs[i].v1 = fgl.v1; fmt.glyphs[i].u0 = fmt.glyphs[i].u0 * us + uo; fmt.glyphs[i].v0 = fmt.glyphs[i].v0 * vs + vo; fmt.glyphs[i].u1 = fmt.glyphs[i].u1 * us + uo; fmt.glyphs[i].v1 = fmt.glyphs[i].v1 * vs + vo; float x = (scaling * ((pen + fgl.bearingX) >> 6)); float y = (scaling * ((0 + fgl.bearingY) >> 6)); float w = fgl.pixelWidth * scaling; float h = fgl.pixelHeight * scaling; fmt.glyphs[i].x = x; fmt.glyphs[i].y = y + yOffset; fmt.glyphs[i].w = w; fmt.glyphs[i].h = h; fmt.glyphs[i].texture = fmt.texture; if (x < fmt.x0) fmt.x0 = x; if (x+w > fmt.x1) fmt.x1 = x+w; if (y < fmt.y0) fmt.y0 = y; if (y + h > fmt.y1) fmt.y1 = y + h; pen += (int)(m_spacingMultiplier * fgl.advance); break; } } } return fmt; }
public void Render(UIRenderContext ctx, float x0, float y0, FormattedText ft, UIRenderer.RColor color, int maxGlyphs = -1) { if (ft == null) return; UIRenderer.RColor restoreColor = UIRenderer.GetColor(); UIRenderer.MultiplyColor(color); if (maxGlyphs == -1 || maxGlyphs > ft.glyphs.Count()) maxGlyphs = ft.glyphs.Count(); for (int i = 0; i < maxGlyphs; i++) { if (ft.glyphs[i].w == -666) continue; float xp = x0 + ft.glyphs[i].x; float yp = y0 + ft.glyphs[i].y; UIRenderer.DrawTextureUV(ft.glyphs[i].texture, xp, yp, xp + ft.glyphs[i].w, yp + ft.glyphs[i].h, ft.glyphs[i].u0, ft.glyphs[i].v0, ft.glyphs[i].u1, ft.glyphs[i].v1); } UIRenderer.SetColor(restoreColor); }
public void Render(UIRenderContext ctx, float x0, float y0, FormattedText ft) { Render(ctx, x0, y0, ft, new UIRenderer.RColor(1,1,1,1)); }