public void RenderItemstackTooltip(ItemSlot slot, double renderX, double renderY, float dt) { parentBounds.fixedX = renderX / RuntimeEnv.GUIScale; parentBounds.fixedY = renderY / RuntimeEnv.GUIScale; parentBounds.CalcWorldBounds(); renderedTooltipSlot.Itemstack = slot.Itemstack; stackInfo.SetSourceSlot(renderedTooltipSlot); bool newRightOverlap = capi.Input.MouseX + stackInfoBounds.OuterWidth > capi.Render.FrameWidth - 5; bool newBottomOverlap = capi.Input.MouseY + stackInfoBounds.OuterHeight > capi.Render.FrameHeight - 5; if (recalcAlignmentOffset || bottomOverlap != newBottomOverlap || newRightOverlap != rightOverlap) { stackInfoBounds.WithFixedAlignmentOffset( newRightOverlap ? -stackInfoBounds.OuterWidth / RuntimeEnv.GUIScale - tooltipOffsetX : 0, newBottomOverlap ? -stackInfoBounds.OuterHeight / RuntimeEnv.GUIScale - tooltipOffsetY : 0 ); stackInfoBounds.CalcWorldBounds(); stackInfoBounds.fixedOffsetY += Math.Max(0, -stackInfoBounds.renderY); stackInfoBounds.CalcWorldBounds(); bottomOverlap = newBottomOverlap; rightOverlap = newRightOverlap; recalcAlignmentOffset = false; } capi.Render.GlScissorFlag(false); stackInfo.RenderInteractiveElements(dt); capi.Render.GlScissorFlag(true); }
public override void RenderInteractiveElements(float deltaTime, double renderX, double renderY) { LineRectangled bounds = BoundsPerLine[0]; ElementBounds scibounds = ElementBounds.FixedSize((int)(bounds.Width / API.Config.RuntimeEnv.GUIScale), (int)(bounds.Height / API.Config.RuntimeEnv.GUIScale)); scibounds.ParentBounds = capi.Gui.WindowBounds; scibounds.CalcWorldBounds(); scibounds.absFixedX = renderX + bounds.X; scibounds.absFixedY = renderY + bounds.Y + offY; api.Render.PushScissor(scibounds, true); api.Render.RenderItemstackToGui( slot, renderX + bounds.X + bounds.Width * 0.5f + offX, renderY + bounds.Y + bounds.Height * 0.5f + offY, GuiElement.scaled(100), (float)size * 0.58f, ColorUtil.WhiteArgb, true, false, false); api.Render.PopScissor(); int relx = (int)(api.Input.MouseX - renderX); int rely = (int)(api.Input.MouseY - renderY); if (bounds.PointInside(relx, rely)) { RenderItemstackTooltip(slot, renderX + relx + offX, renderY + rely + offY, deltaTime); } }
public override void RenderTo(ICoreClientAPI capi, double x, double y) { float size = (float)GuiElement.scaled(25); float pad = (float)GuiElement.scaled(10); if (Texture == null) { Recompose(capi); } scissorBounds.fixedX = pad + x / RuntimeEnv.GUIScale - size / 2; scissorBounds.fixedY = y / RuntimeEnv.GUIScale - size / 2; scissorBounds.CalcWorldBounds(); if (scissorBounds.InnerWidth <= 0 || scissorBounds.InnerHeight <= 0) { return; } capi.Render.PushScissor(scissorBounds, true); capi.Render.RenderItemstackToGui(dummySlot, x + pad + size / 2, y + size / 2, 100, size, ColorUtil.WhiteArgb, true, false, false); capi.Render.PopScissor(); capi.Render.Render2DTexturePremultipliedAlpha( Texture.TextureId, (x + size + GuiElement.scaled(25)), y + size / 4 - 3, Texture.Width, Texture.Height, 50 ); }
/// <summary> /// Automatically adjusts the height of the element. /// </summary> public void Autoheight() { double totalHeight = 0; double pad = scaled(unscaledPadding); Bounds.CalcWorldBounds(); bool first = true; foreach (ConfigItem item in items) { double lineHeight = Math.Max( textUtil.GetMultilineTextHeight(Font, item.Key, Bounds.InnerWidth * leftWidthRel), textUtil.GetMultilineTextHeight(Font, item.Value, Bounds.InnerWidth * rightWidthRel) ); if (!first && item.Type == EnumItemType.Title) { lineHeight += scaled(20); } totalHeight += pad + lineHeight + pad; first = false; } innerBounds = Bounds.FlatCopy(); innerBounds.fixedHeight = totalHeight / RuntimeEnv.GUIScale; // Unscaled value! innerBounds.CalcWorldBounds(); }
public override void RenderInteractiveElements(float deltaTime, double renderX, double renderY) { LineRectangled bounds = BoundsPerLine[0]; ItemStack itemstack = Itemstacks[curItemIndex]; if ((secondsVisible -= deltaTime) <= 0) { secondsVisible = 1; curItemIndex = (curItemIndex + 1) % Itemstacks.Length; } slot.Itemstack = itemstack; ElementBounds scibounds = ElementBounds.FixedSize((int)(bounds.Width / RuntimeEnv.GUIScale), (int)(bounds.Height / RuntimeEnv.GUIScale)); scibounds.ParentBounds = capi.Gui.WindowBounds; scibounds.CalcWorldBounds(); scibounds.absFixedX = renderX + bounds.X; scibounds.absFixedY = renderY + bounds.Y; api.Render.PushScissor(scibounds); api.Render.RenderItemstackToGui(slot, renderX + bounds.X + bounds.Width * 0.5f, renderY + bounds.Y + bounds.Height * 0.5f, 100, (float)bounds.Width * 0.58f, ColorUtil.WhiteArgb, true, false, ShowStackSize); api.Render.PopScissor(); int relx = (int)(api.Input.MouseX - renderX); int rely = (int)(api.Input.MouseY - renderY); if (bounds.PointInside(relx, rely)) { RenderItemstackTooltip(slot, renderX + relx, renderY + rely, deltaTime); } }
public override void BeforeCalcBounds() { base.BeforeCalcBounds(); insideBounds = new ElementBounds().WithFixedPadding(unscaledCellSpacing).WithEmptyParent(); insideBounds.CalcWorldBounds(); CalcTotalHeight(); }
public override void ComposeElements(Context ctx, ImageSurface surface) { insideBounds = new ElementBounds().WithFixedPadding(unscaledCellSpacing).WithEmptyParent(); insideBounds.CalcWorldBounds(); Bounds.CalcWorldBounds(); ComposeList(); }
/// <summary> /// Called whenever the scrollbar or mouse wheel is used. /// </summary> /// <param name="value">The new value of the scrollbar.</param> protected void OnNewScrollbarvalue(float value) { ElementBounds bounds = SingleComposer.GetSlotGrid("slotgrid").Bounds; bounds.fixedY = 10 - GuiElementItemSlotGrid.unscaledSlotPadding - value; bounds.CalcWorldBounds(); }
public GuiElementHandbookList(ICoreClientAPI capi, ElementBounds bounds, API.Common.Action <int> onLeftClick, List <GuiHandbookPage> elements = null) : base(capi, bounds) { hoverOverlayTexture = new LoadedTexture(capi); insideBounds = new ElementBounds().WithFixedPadding(unscaledCellSpacing).WithEmptyParent(); insideBounds.CalcWorldBounds(); this.onLeftClick = onLeftClick; if (elements != null) { Elements = elements; } CalcTotalHeight(); }
void GenerateHighlight() { ImageSurface surfaceHighlight = new ImageSurface(Format.Argb32, (int)Bounds.OuterWidth, (int)Bounds.OuterHeight); Context ctxHighlight = genContext(surfaceHighlight); ctxHighlight.SetSourceRGBA(1, 1, 1, 0.1); ctxHighlight.Paint(); generateTexture(surfaceHighlight, ref highlightTexture); ctxHighlight.Dispose(); surfaceHighlight.Dispose(); highlightBounds = Bounds.FlatCopy().FixedGrow(6, 6); highlightBounds.CalcWorldBounds(); }
void Recompose() { descriptionElement.SetNewText(text, Font); RecalcBounds(); Bounds.CalcWorldBounds(); ElementBounds textBounds = Bounds.CopyOnlySize(); textBounds.CalcWorldBounds(); ImageSurface surface = new ImageSurface(Format.Argb32, (int)Math.Ceiling(hoverWidth), (int)Math.Ceiling(hoverHeight)); Context ctx = genContext(surface); ctx.SetSourceRGBA(0, 0, 0, 0); ctx.Paint(); if (Background?.FillColor != null) { ctx.SetSourceRGBA(Background.FillColor); RoundRectangle(ctx, 0, 0, hoverWidth, hoverHeight, Background.Radius); ctx.Fill(); } if (Background?.Shade == true) { ctx.SetSourceRGBA(GuiStyle.DialogLightBgColor[0] * 1.4, GuiStyle.DialogStrongBgColor[1] * 1.4, GuiStyle.DialogStrongBgColor[2] * 1.4, 1); RoundRectangle(ctx, 0, 0, hoverWidth, hoverHeight, Background.Radius); ctx.LineWidth = Background.BorderWidth * 1.75; ctx.Stroke(); surface.Blur(8.2); } if (Background?.BorderColor != null) { ctx.SetSourceRGBA(Background.BorderColor); RoundRectangle(ctx, 0, 0, hoverWidth, hoverHeight, Background.Radius); ctx.LineWidth = Background.BorderWidth; ctx.Stroke(); } generateTexture(surface, ref hoverTexture); ctx.Dispose(); surface.Dispose(); }
public override void ComposeElements(Context ctxStatic, ImageSurface surfaceStatic) { insideBounds = new ElementBounds().WithFixedPadding(unscaledCellSpacing).WithEmptyParent(); insideBounds.CalcWorldBounds(); CalcTotalHeight(); Bounds.CalcWorldBounds(); ImageSurface surface = new ImageSurface(Format.Argb32, (int)Bounds.InnerWidth, (int)GuiElement.scaled(unscaledCellHeight)); Context ctx = new Context(surface); ctx.SetSourceRGBA(1, 1, 1, 0.5); ctx.Paint(); generateTexture(surface, ref hoverOverlayTexture); ctx.Dispose(); surface.Dispose(); }
public override void ComposeTextElements(Context ctx, ImageSurface surface) { ctx.LineWidth = 1; // Vertical seperator line above the bounds ctx.NewPath(); ctx.MoveTo(Bounds.drawX + 1, Bounds.drawY); ctx.LineTo(Bounds.drawX + 1 + Bounds.InnerWidth, Bounds.drawY); ctx.ClosePath(); ctx.SetSourceRGBA(1, 1, 1, 0.7); ctx.Stroke(); ctx.NewPath(); ctx.MoveTo(Bounds.drawX + 1, Bounds.drawY + 1); ctx.LineTo(Bounds.drawX + 1 + Bounds.InnerWidth, Bounds.drawY + 1); ctx.ClosePath(); ctx.SetSourceRGBA(0, 0, 0, 0.7); ctx.Stroke(); ImageSurface surfaceHighlight = new ImageSurface(Format.Argb32, (int)Bounds.OuterWidth, (int)Bounds.OuterHeight); Context ctxHighlight = genContext(surfaceHighlight); ctxHighlight.SetSourceRGBA(0, 0, 0, 0); ctxHighlight.Paint(); ctxHighlight.SetSourceRGBA(1, 1, 1, 0.1); ctxHighlight.Paint(); generateTexture(surfaceHighlight, ref highlightTexture); ctxHighlight.Dispose(); surfaceHighlight.Dispose(); highlightBounds = Bounds.CopyOffsetedSibling().WithFixedPadding(0, 0).FixedGrow(2 * Bounds.absPaddingX, 2 * Bounds.absPaddingY); highlightBounds.CalcWorldBounds(); RecomposeText(); }
public virtual void ComposeFor(ElementBounds bounds, Context ctx, ImageSurface surface) { bounds.CalcWorldBounds(); ctx.Save(); Matrix m = ctx.Matrix; m.Translate(bounds.drawX, bounds.drawY); ctx.Matrix = m; for (int i = 0; i < Components.Length; i++) { Components[i].ComposeElements(ctx, surface); if (Debug) { ctx.LineWidth = 1f; if (Components[i] is ClearFloatTextComponent) { ctx.SetSourceRGBA(0, 0, 1, 0.5); } else { ctx.SetSourceRGBA(0, 0, 0, 0.5); } foreach (var val in Components[i].BoundsPerLine) { ctx.Rectangle(val.X, val.Y, val.Width, val.Height); ctx.Stroke(); } } } ctx.Restore(); }
public override void ComposeTextElements(Context ctx, ImageSurface surface) { EmbossRoundRectangleElement(ctx, Bounds, true, 2, 1); ctx.SetSourceRGBA(0, 0, 0, 0.3); ElementRoundRectangle(ctx, Bounds, false, 1); ctx.Fill(); ImageSurface surfaceHighlight = new ImageSurface(Format.Argb32, (int)Bounds.OuterWidth, (int)Bounds.OuterHeight); Context ctxHighlight = genContext(surfaceHighlight); ctxHighlight.SetSourceRGBA(1, 1, 1, 0.3); ctxHighlight.Paint(); generateTexture(surfaceHighlight, ref highlightTexture); ctxHighlight.Dispose(); surfaceHighlight.Dispose(); highlightBounds = Bounds.CopyOffsetedSibling().WithFixedPadding(0, 0).FixedGrow(2 * Bounds.absPaddingX, 2 * Bounds.absPaddingY); highlightBounds.CalcWorldBounds(); RecomposeText(); }
public override void RenderInteractiveElements(float deltaTime, double renderX, double renderY) { LineRectangled bounds = BoundsPerLine[0]; GridRecipeAndUnnamedIngredients recipeunin = GridRecipesAndUnIn[curItemIndex]; if ((secondsVisible -= deltaTime) <= 0) { secondsVisible = 1; curItemIndex = (curItemIndex + 1) % GridRecipesAndUnIn.Length; secondCounter++; } LoadedTexture extraTextTexture; if (extraTexts.TryGetValue(curItemIndex, out extraTextTexture)) { capi.Render.Render2DTexturePremultipliedAlpha(extraTextTexture.TextureId, (float)(renderX + bounds.X), (float)(renderY + bounds.Y + 3 * (size + 3)), extraTextTexture.Width, extraTextTexture.Height); } int mx = api.Input.MouseX; int my = api.Input.MouseY; double rx = 0, ry = 0; for (int x = 0; x < 3; x++) { for (int y = 0; y < 3; y++) { int index = recipeunin.Recipe.GetGridIndex(y, x, recipeunin.Recipe.resolvedIngredients, recipeunin.Recipe.Width); CraftingRecipeIngredient ingred = recipeunin.Recipe.GetElementInGrid(y, x, recipeunin.Recipe.resolvedIngredients, recipeunin.Recipe.Width); if (ingred == null) { continue; } rx = renderX + bounds.X + x * (size + GuiElement.scaled(3)); ry = renderY + bounds.Y + y * (size + GuiElement.scaled(3)); ItemStack[] unnamedWildcardStacklist = null; if (recipeunin.unnamedIngredients?.TryGetValue(index, out unnamedWildcardStacklist) == true) { dummyslot.Itemstack = unnamedWildcardStacklist[secondCounter % unnamedWildcardStacklist.Length]; dummyslot.Itemstack.StackSize = ingred.Quantity; } else { dummyslot.Itemstack = ingred.ResolvedItemstack.Clone(); } var scale = RuntimeEnv.GUIScale; ElementBounds scissorBounds = ElementBounds.Fixed(rx / scale, ry / scale, size / scale, size / scale).WithEmptyParent(); scissorBounds.CalcWorldBounds(); api.Render.PushScissor(scissorBounds, true); // 1.16.0: Fugly (but backwards compatible) hack: We temporarily store the ingredient code in an unused field of ItemSlot so that OnHandbookRecipeRender() has access to that number. Proper solution would be to alter the method signature to pass on this value. dummyslot.BackgroundIcon = index + ""; dummyslot.Itemstack.Collectible.OnHandbookRecipeRender(capi, recipeunin.Recipe, dummyslot, rx + size * 0.5f, ry + size * 0.5f, size); dummyslot.BackgroundIcon = null; api.Render.PopScissor(); // Super weird coordinates, no idea why double dx = mx - rx + 1; double dy = my - ry + 2; if (dx >= 0 && dx < size && dy >= 0 && dy < size) { RenderItemstackTooltip(dummyslot, rx + dx, ry + dy, deltaTime); } } } }
void Recompose() { if (curSlot?.Itemstack == null) { return; } readyToRender = false; string title = curSlot.GetStackName(); string desc = OnRequireInfoText(curSlot); desc.TrimEnd(); titleElement.SetNewText(title, titleFont); descriptionElement.SetNewText(desc, Font); RecalcBounds(title, desc); Bounds.CalcWorldBounds(); ElementBounds textBounds = Bounds.CopyOnlySize(); textBounds.CalcWorldBounds(); TyronThreadPool.QueueTask(() => { /*int i = 0; * while (i < 5 && titleElement.HalfComposed) System.Threading.Thread.Sleep(5);*/ ImageSurface surface = new ImageSurface(Format.Argb32, Bounds.OuterWidthInt, Bounds.OuterHeightInt); Context ctx = genContext(surface); ctx.SetSourceRGBA(0, 0, 0, 0); ctx.Paint(); ctx.SetSourceRGBA(backTint[0], backTint[1], backTint[2], backTint[3]); RoundRectangle(ctx, textBounds.bgDrawX, textBounds.bgDrawY, textBounds.OuterWidthInt, textBounds.OuterHeightInt, GuiStyle.DialogBGRadius); ctx.FillPreserve(); ctx.SetSourceRGBA(GuiStyle.DialogLightBgColor[0] * 1.4, GuiStyle.DialogStrongBgColor[1] * 1.4, GuiStyle.DialogStrongBgColor[2] * 1.4, 1); ctx.LineWidth = 3 * 1.75; ctx.StrokePreserve(); surface.Blur(8.2); ctx.SetSourceRGBA(backTint[0] / 2, backTint[1] / 2, backTint[2] / 2, backTint[3]); ctx.Stroke(); int w = (int)(scaled(ItemStackSize) + scaled(40)); int h = (int)(scaled(ItemStackSize) + scaled(40)); ImageSurface shSurface = new ImageSurface(Format.Argb32, w, h); Context shCtx = genContext(shSurface); shCtx.SetSourceRGBA(GuiStyle.DialogSlotBackColor); RoundRectangle(shCtx, 0, 0, w, h, 0); shCtx.FillPreserve(); shCtx.SetSourceRGBA(GuiStyle.DialogSlotFrontColor); shCtx.LineWidth = 5; shCtx.Stroke(); shSurface.Blur(7); shSurface.Blur(7); shSurface.Blur(7); EmbossRoundRectangleElement(shCtx, 0, 0, w, h, true); ctx.SetSourceSurface(shSurface, (int)(textBounds.drawX), (int)(textBounds.drawY + scaled(MarginTop))); ctx.Rectangle(textBounds.drawX, textBounds.drawY + scaled(MarginTop), w, h); ctx.Fill(); shCtx.Dispose(); shSurface.Dispose(); api.Event.EnqueueMainThreadTask(() => { //titleElement.genTexture(); //descriptionElement.genTexture(); titleElement.Compose(false); descriptionElement.Compose(false); generateTexture(surface, ref texture); ctx.Dispose(); surface.Dispose(); double offset = (int)(30 + ItemStackSize / 2); scissorBounds = ElementBounds.Fixed(4 + offset - ItemStackSize, 2 + offset + MarginTop - ItemStackSize, ItemStackSize + 38, ItemStackSize + 38).WithParent(Bounds); scissorBounds.CalcWorldBounds(); readyToRender = true; }, "genstackinfotexture"); }); }
private void ComposeDynamicElements() { // Released Button int btnWidth = (int)(scaled(20) * Scale); int btnHeight = (int)(Bounds.InnerHeight); ImageSurface surface = new ImageSurface(Format.Argb32, btnWidth, btnHeight); Context ctx = genContext(surface); ctx.SetSourceRGB(GuiStyle.DialogDefaultBgColor[0], GuiStyle.DialogDefaultBgColor[1], GuiStyle.DialogDefaultBgColor[2]); RoundRectangle(ctx, 0, 0, btnWidth, btnHeight, GuiStyle.ElementBGRadius); ctx.FillPreserve(); ctx.SetSourceRGBA(1, 1, 1, 0.1); ctx.Fill(); EmbossRoundRectangleElement(ctx, 0, 0, btnWidth, btnHeight, false, 2, 1); ctx.SetSourceRGBA(GuiStyle.DialogHighlightColor); RoundRectangle(ctx, 0, 0, btnWidth, btnHeight, 1); ctx.Fill(); ctx.NewPath(); ctx.LineTo(btnWidth - scaled(17) * Scale, scaled(10) * Scale); ctx.LineTo(btnWidth - scaled(3) * Scale, scaled(10) * Scale); ctx.LineTo(btnWidth - scaled(10) * Scale, scaled(20) * Scale); ctx.ClosePath(); ctx.SetSourceRGBA(1, 1, 1, 0.6); ctx.Fill(); generateTexture(surface, ref arrowDownButtonReleased); // Pressed Button ctx.Operator = Operator.Clear; ctx.SetSourceRGBA(0, 0, 0, 0); ctx.Paint(); ctx.Operator = Operator.Over; ctx.SetSourceRGB(GuiStyle.DialogDefaultBgColor[0], GuiStyle.DialogDefaultBgColor[1], GuiStyle.DialogDefaultBgColor[2]); RoundRectangle(ctx, 0, 0, btnWidth, btnHeight, GuiStyle.ElementBGRadius); ctx.FillPreserve(); ctx.SetSourceRGBA(0, 0, 0, 0.1); ctx.Fill(); EmbossRoundRectangleElement(ctx, 0, 0, btnWidth, btnHeight, true, 2, 1); ctx.SetSourceRGBA(GuiStyle.DialogHighlightColor); RoundRectangle(ctx, 0, 0, btnWidth, btnHeight, 1); ctx.Fill(); ctx.NewPath(); ctx.LineTo(btnWidth - scaled(17) * Scale, scaled(10) * Scale); ctx.LineTo(btnWidth - scaled(3) * Scale, scaled(10) * Scale); ctx.LineTo(btnWidth - scaled(10) * Scale, scaled(20) * Scale); ctx.ClosePath(); ctx.SetSourceRGBA(1, 1, 1, 0.4); ctx.Fill(); generateTexture(surface, ref arrowDownButtonPressed); surface.Dispose(); ctx.Dispose(); // Highlight overlay ImageSurface surfaceHighlight = new ImageSurface(Format.Argb32, (int)Bounds.OuterWidth - btnWidth, (int)Bounds.OuterHeight); Context ctxHighlight = genContext(surfaceHighlight); ctxHighlight.SetSourceRGBA(1, 1, 1, 0.3); ctxHighlight.Paint(); generateTexture(surfaceHighlight, ref highlightTexture); ctxHighlight.Dispose(); surfaceHighlight.Dispose(); highlightBounds = Bounds.CopyOffsetedSibling().WithFixedPadding(0, 0).FixedGrow(2 * Bounds.absPaddingX, 2 * Bounds.absPaddingY); highlightBounds.fixedWidth -= btnWidth; highlightBounds.CalcWorldBounds(); ComposeCurrentValue(); }
/// <summary> /// Composes the list of elements dynamically. /// </summary> public void ComposeDynamicElements() { Bounds.CalcWorldBounds(); if (multiSelect) { if (switches != null) { foreach (var val in switches) { val.Dispose(); } } switches = new GuiElementSwitch[Names.Length]; } for (int i = 0; i < richtTextElem.Length; i++) { richtTextElem[i].Dispose(); } richtTextElem = new GuiElementRichtext[Values.Length]; for (int i = 0; i < Values.Length; i++) { ElementBounds textBounds = ElementBounds.Fixed(0, 0, 700, 100).WithEmptyParent(); richtTextElem[i] = new GuiElementRichtext(api, new RichTextComponentBase[0], textBounds); } double scaleMul = Scale * RuntimeEnv.GUIScale; double lineHeight = unscaledLineHeight * scaleMul; // Expandable box with list of names expandedBoxWidth = Bounds.InnerWidth; expandedBoxHeight = Values.Length * lineHeight; double scrollbarWidth = 10; for (int i = 0; i < Values.Length; i++) { GuiElementRichtext elem = richtTextElem[i]; elem.SetNewTextWithoutRecompose(Names[i], Font); elem.BeforeCalcBounds(); expandedBoxWidth = Math.Max(expandedBoxWidth, elem.MaxLineWidth + scaled(scrollbarWidth + 5)); } expandedBoxWidth++; //expandedBoxWidth += 5 * scaleMul; ImageSurface surface = new ImageSurface(Format.Argb32, (int)expandedBoxWidth, (int)expandedBoxHeight); Context ctx = genContext(surface); visibleBounds = Bounds.FlatCopy(); visibleBounds.fixedHeight = Math.Min(MaxHeight, expandedBoxHeight / RuntimeEnv.GUIScale); visibleBounds.fixedWidth = expandedBoxWidth / RuntimeEnv.GUIScale; visibleBounds.fixedY += Bounds.InnerHeight / RuntimeEnv.GUIScale; visibleBounds.CalcWorldBounds(); Font.SetupContext(ctx); ctx.SetSourceRGBA(GuiStyle.DialogStrongBgColor); RoundRectangle(ctx, 0, 0, expandedBoxWidth, expandedBoxHeight, 1); ctx.FillPreserve(); ctx.SetSourceRGBA(0, 0, 0, 0.5); ctx.LineWidth = 2; ctx.Stroke(); double unscaledHeight = Font.GetFontExtents().Height / RuntimeEnv.GUIScale; double unscaledOffY = (unscaledLineHeight - unscaledHeight) / 2; double unscaledOffx = multiSelect ? unscaledHeight + 10 : 0; double scaledHeight = unscaledHeight * scaleMul; ctx.SetSourceRGBA(GuiStyle.DialogDefaultTextColor); ElementBounds switchParentBounds = Bounds.FlatCopy(); switchParentBounds.IsDrawingSurface = true; switchParentBounds.CalcWorldBounds(); for (int i = 0; i < Values.Length; i++) { int num = i; double y = ((int)unscaledOffY + i * unscaledLineHeight) * scaleMul; double x = unscaledOffx + 5 * scaleMul; double offy = (scaledHeight - Font.GetTextExtents(Names[i]).Height) / 2; if (multiSelect) { double pad = 2; ElementBounds switchBounds = new ElementBounds() { ParentBounds = switchParentBounds, fixedX = 4 * Scale, fixedY = (y + offy) / RuntimeEnv.GUIScale, fixedWidth = (unscaledHeight) * Scale, fixedHeight = (unscaledHeight) * Scale, fixedPaddingX = 0, fixedPaddingY = 0 }; switches[i] = new GuiElementSwitch(api, (on) => toggled(on, num), switchBounds, switchBounds.fixedHeight, pad); switches[i].ComposeElements(ctx, surface); ctx.SetSourceRGBA(GuiStyle.DialogDefaultTextColor); } GuiElementRichtext elem = richtTextElem[i]; elem.Bounds.fixedX = x; elem.Bounds.fixedY = (y + offy) / RuntimeEnv.GUIScale; elem.BeforeCalcBounds(); elem.Bounds.CalcWorldBounds(); elem.ComposeFor(elem.Bounds, ctx, surface); } generateTexture(surface, ref dropDownTexture); ctx.Dispose(); surface.Dispose(); // Scrollbar static stuff scrollbar.Bounds.WithFixedSize(scrollbarWidth, visibleBounds.fixedHeight - 3).WithFixedPosition(expandedBoxWidth / RuntimeEnv.GUIScale - 10, 0).WithFixedPadding(0, 2); scrollbar.Bounds.WithEmptyParent(); scrollbar.Bounds.CalcWorldBounds(); surface = new ImageSurface(Format.Argb32, (int)expandedBoxWidth, (int)scrollbar.Bounds.OuterHeight); ctx = genContext(surface); scrollbar.ComposeElements(ctx, surface); scrollbar.SetHeights((int)visibleBounds.InnerHeight / RuntimeEnv.GUIScale, (int)expandedBoxHeight / RuntimeEnv.GUIScale); generateTexture(surface, ref scrollbarTexture); ctx.Dispose(); surface.Dispose(); // Hover bar surface = new ImageSurface(Format.Argb32, (int)expandedBoxWidth, (int)(unscaledLineHeight * scaleMul)); ctx = genContext(surface); double[] col = GuiStyle.DialogHighlightColor; col[3] = 0.5; ctx.SetSourceRGBA(col); RoundRectangle(ctx, 0, 0, expandedBoxWidth, unscaledLineHeight * scaleMul, 0); ctx.Fill(); generateTexture(surface, ref hoverTexture); ctx.Dispose(); surface.Dispose(); }
/// <summary> /// Tells the composer to compose the gui. /// </summary> /// <param name="focusFirstElement">Whether or not to put the first element in focus.</param> public GuiComposer Compose(bool focusFirstElement = true) { if (Composed) { if (focusFirstElement && MaxTabIndex >= 0) { FocusElement(0); } return(this); } foreach (GuiElement element in staticElements.Values) { element.BeforeCalcBounds(); } bounds.Initialized = false; try { bounds.CalcWorldBounds(); } catch (Exception e) { Api.World.Logger.Error("Exception thrown when trying to calculate world bounds for gui composite " + dialogName + ": " + e); } bounds.IsDrawingSurface = true; // So here's yet another snippet of weird code. It *seems* as if most graphics cards really don't like // when you delete and reallocate textures often (maybe causes memory fragmentation and then spends extra time defragmenting? o.O) // So instead we allocate a larger space and re-use the previous texture, if we already have one that fits int wdt = (int)bounds.OuterWidth; int hgt = (int)bounds.OuterHeight; if (staticElementsTexture.TextureId != 0) { wdt = Math.Max(wdt, staticElementsTexture.Width); hgt = Math.Max(hgt, staticElementsTexture.Height); } ImageSurface surface = new ImageSurface(Format.Argb32, wdt, hgt); Context ctx = new Context(surface); ctx.SetSourceRGBA(0, 0, 0, 0); ctx.Paint(); ctx.Antialias = Antialias.Best; foreach (GuiElement element in staticElements.Values) { element.ComposeElements(ctx, surface); } interactiveElementsInDrawOrder.Clear(); foreach (GuiElement element in interactiveElements.Values) { int insertPos = 0; foreach (GuiElement addedElem in interactiveElementsInDrawOrder) { if (element.DrawOrder >= addedElem.DrawOrder) { insertPos++; } else { break; } } interactiveElementsInDrawOrder.Insert(insertPos, element); } if (!premultipliedAlpha) { surface.DemulAlpha(); } Api.Gui.LoadOrUpdateCairoTexture(surface, true, ref staticElementsTexture); ctx.Dispose(); surface.Dispose(); Composed = true; if (focusFirstElement && MaxTabIndex >= 0) { FocusElement(0); } return(this); }