Image Component

This commit is contained in:
Frank 2022-07-15 15:47:56 +02:00
parent 51da03f3c8
commit 877489c469
13 changed files with 263 additions and 36 deletions

View file

@ -1,7 +1,9 @@
package org.betterx.bclib.client.gui.modmenu;
import org.betterx.bclib.BCLib;
import org.betterx.ui.layout.components.*;
import org.betterx.ui.layout.values.DynamicSize;
import org.betterx.ui.layout.values.Size;
import org.betterx.ui.vanilla.LayoutScreen;
import net.minecraft.client.gui.screens.Screen;
@ -36,6 +38,13 @@ public class TestScreen extends LayoutScreen {
).centerHorizontal()
);
rows.addSpacer(16);
rows.add(new Image(
DynamicSize.fixed(24), DynamicSize.fixed(24),
BCLib.makeID("icon.png"),
new Size(512, 512)
).centerHorizontal()
);
rows.addSpacer(16);
rows.add(new Range<>(
DynamicSize.fill(), DynamicSize.fit(),
Component.literal("Integer"),
@ -72,7 +81,7 @@ public class TestScreen extends LayoutScreen {
}
));
rows.add(cb1);
rows.addSpacer(32);
rows.addSpacer(16);
rows.add(new Button(
DynamicSize.fit(), DynamicSize.fit(),
Component.literal("test"),

View file

@ -46,15 +46,15 @@ public abstract class AbstractStack<R extends ComponentRenderer, T extends Abstr
@Override
protected void renderInBounds(
PoseStack poseStack,
int x,
int y,
float a,
int mouseX,
int mouseY,
float deltaTicks,
Rectangle renderBounds,
Rectangle clipRect
) {
super.renderInBounds(poseStack, x, y, a, renderBounds, clipRect);
super.renderInBounds(poseStack, mouseX, mouseY, deltaTicks, renderBounds, clipRect);
for (Component<?> c : components) {
c.render(poseStack, x, y, a, renderBounds, clipRect);
c.render(poseStack, mouseX, mouseY, deltaTicks, renderBounds, clipRect);
}
}

View file

@ -19,13 +19,20 @@ public class AbstractVanillaComponentRenderer<C extends AbstractWidget, V extend
}
@Override
public void renderInBounds(PoseStack poseStack, int x, int y, float a, Rectangle bounds, Rectangle clipRect) {
public void renderInBounds(
PoseStack poseStack,
int mouseX,
int mouseY,
float deltaTicks,
Rectangle bounds,
Rectangle clipRect
) {
if (linkedComponent != null) {
if (linkedComponent.vanillaComponent != null) {
if (!linkedComponent.enabled) {
linkedComponent.vanillaComponent.setAlpha(linkedComponent.alpha / 2);
}
linkedComponent.vanillaComponent.render(poseStack, x, y, a);
linkedComponent.vanillaComponent.render(poseStack, mouseX, mouseY, deltaTicks);
if (!linkedComponent.enabled) {
linkedComponent.vanillaComponent.setAlpha(linkedComponent.alpha);
}

View file

@ -82,28 +82,35 @@ public abstract class Component<R extends ComponentRenderer> implements Componen
);
}
public void render(PoseStack poseStack, int x, int y, float a, Rectangle parentBounds, Rectangle clipRect) {
public void render(
PoseStack poseStack,
int mouseX,
int mouseY,
float deltaTicks,
Rectangle parentBounds,
Rectangle clipRect
) {
Rectangle r = relativeBounds.movedBy(parentBounds.left, parentBounds.top);
Rectangle clip = r.intersect(clipRect);
poseStack.pushPose();
poseStack.translate(relativeBounds.left, relativeBounds.top, 0);
if (r.overlaps(clip)) {
renderInBounds(poseStack, x - relativeBounds.left, y - relativeBounds.top, a, r, clip);
renderInBounds(poseStack, mouseX - relativeBounds.left, mouseY - relativeBounds.top, deltaTicks, r, clip);
}
poseStack.popPose();
}
protected void renderInBounds(
PoseStack poseStack,
int x,
int y,
float a,
int mouseX,
int mouseY,
float deltaTicks,
Rectangle renderBounds,
Rectangle clipRect
) {
if (renderer != null) {
setClippingRect(clipRect);
renderer.renderInBounds(poseStack, x, y, a, renderBounds, clipRect);
renderer.renderInBounds(poseStack, mouseX, mouseY, deltaTicks, renderBounds, clipRect);
setClippingRect(null);
}
}

View file

@ -0,0 +1,48 @@
package org.betterx.ui.layout.components;
import org.betterx.ui.layout.components.render.ComponentRenderer;
import org.betterx.ui.layout.values.DynamicSize;
import org.betterx.ui.layout.values.Rectangle;
import com.mojang.blaze3d.vertex.PoseStack;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
@Environment(EnvType.CLIENT)
public abstract class CustomRenderComponent<C extends CustomRenderComponent<C>> extends Component<CustomRenderComponent.CustomRenderRenderer<C>> {
public CustomRenderComponent(
DynamicSize width,
DynamicSize height
) {
super(width, height, new CustomRenderRenderer<>());
renderer.linkedComponent = (C) this;
}
protected abstract void customRender(
PoseStack stack,
int x,
int y,
float deltaTicks,
Rectangle bounds,
Rectangle clipRect
);
protected static class CustomRenderRenderer<C extends CustomRenderComponent<C>> implements ComponentRenderer {
C linkedComponent;
@Override
public void renderInBounds(
PoseStack stack,
int mouseX,
int mouseY,
float deltaTicks,
Rectangle bounds,
Rectangle clipRect
) {
if (linkedComponent != null) {
linkedComponent.customRender(stack, mouseX, mouseY, deltaTicks, bounds, clipRect);
}
}
}
}

View file

@ -0,0 +1,115 @@
package org.betterx.ui.layout.components;
import org.betterx.ui.layout.values.DynamicSize;
import org.betterx.ui.layout.values.Rectangle;
import org.betterx.ui.layout.values.Size;
import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.gui.GuiComponent;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.resources.ResourceLocation;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
@Environment(EnvType.CLIENT)
public class Image extends CustomRenderComponent {
protected Rectangle uvRect;
public final ResourceLocation location;
protected float alpha;
protected Size resourceSize;
public Image(DynamicSize width, DynamicSize height, ResourceLocation location) {
this(width, height, location, new Size(16, 16));
}
public Image(DynamicSize width, DynamicSize height, ResourceLocation location, Size resourceSize) {
super(width, height);
this.location = location;
this.uvRect = new Rectangle(0, 0, resourceSize.width(), resourceSize.height());
this.resourceSize = resourceSize;
this.alpha = 1f;
}
public Image setAlpha(float a) {
alpha = a;
return this;
}
public float getAlpha() {
return alpha;
}
public Image setUvRect(int left, int top, int width, int height) {
uvRect = new Rectangle(left, top, width, height);
return this;
}
public Rectangle getUvRect() {
return uvRect;
}
public Image setResourceSize(int width, int height) {
resourceSize = new Size(width, height);
return this;
}
public Size getResourceSize() {
return resourceSize;
}
@Override
public int getContentWidth() {
return resourceSize.width();
}
@Override
public int getContentHeight() {
return resourceSize.height();
}
@Override
protected void customRender(
PoseStack stack,
int mouseX,
int mouseY,
float deltaTicks,
Rectangle bounds,
Rectangle clipRect
) {
renderImage(stack, bounds, location, uvRect, resourceSize, alpha);
}
protected static void renderImage(
PoseStack stack,
Rectangle bounds,
ResourceLocation location,
Rectangle uvRect,
Size size,
float alpha
) {
RenderSystem.setShader(GameRenderer::getPositionTexShader);
RenderSystem.setShaderTexture(0, location);
RenderSystem.enableBlend();
RenderSystem.blendFunc(
GlStateManager.SourceFactor.SRC_ALPHA,
GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA
);
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, alpha);
GuiComponent.blit(
stack,
0, 0, bounds.width, bounds.height,
uvRect.left,
uvRect.top,
uvRect.width,
uvRect.height,
size.width(),
size.height()
);
}
}

View file

@ -94,9 +94,9 @@ public class Panel implements ComponentWithBounds, RelativeContainerEventHandler
}
@Override
public void render(PoseStack poseStack, int x, int y, float a) {
public void render(PoseStack poseStack, int mouseX, int mouseY, float deltaTicks) {
if (child != null) {
child.render(poseStack, x - bounds.left, y - bounds.top, a, bounds, bounds);
child.render(poseStack, mouseX - bounds.left, mouseY - bounds.top, deltaTicks, bounds, bounds);
}
}
// @Override

View file

@ -54,7 +54,14 @@ public class Text extends Component<Text.TextRenderer> {
}
@Override
public void renderInBounds(PoseStack stack, int x, int y, float a, Rectangle bounds, Rectangle clipRect) {
public void renderInBounds(
PoseStack stack,
int mouseX,
int mouseY,
float deltaTicks,
Rectangle bounds,
Rectangle clipRect
) {
if (linkedComponent != null) {
int left = bounds.width - getWidth(linkedComponent.text);
if (linkedComponent.hAlign == Alignment.MIN) left = 0;

View file

@ -3,6 +3,7 @@ package org.betterx.ui.layout.components;
import org.betterx.ui.layout.components.render.ComponentRenderer;
import org.betterx.ui.layout.components.render.NullRenderer;
import org.betterx.ui.layout.components.render.ScrollerRenderer;
import org.betterx.ui.layout.values.Alignment;
import org.betterx.ui.layout.values.DynamicSize;
import org.betterx.ui.layout.values.Rectangle;
import org.betterx.ui.vanilla.VanillaScrollerRenderer;
@ -59,7 +60,7 @@ public class VerticalScroll<R extends ComponentRenderer, RS extends ScrollerRend
protected int updateContainerWidth(int containerWidth) {
int myWidth = width.calculateOrFill(containerWidth);
if (child != null) {
child.width.calculateOrFill(myWidth - (scrollerRenderer.scrollerPadding() + scrollerRenderer.scrollerWidth()));
child.width.calculateOrFill(myWidth - scrollerWidth());
child.updateContainerWidth(child.width.calculatedSize());
}
return myWidth;
@ -75,9 +76,13 @@ public class VerticalScroll<R extends ComponentRenderer, RS extends ScrollerRend
return myHeight;
}
protected int scrollerWidth() {
return scrollerRenderer.scrollerWidth() + scrollerRenderer.scrollerPadding();
}
@Override
public int getContentWidth() {
return scrollerRenderer.scrollerWidth() + scrollerRenderer.scrollerPadding() + (child != null
return scrollerWidth() + (child != null
? child.getContentWidth()
: 0);
}
@ -91,8 +96,20 @@ public class VerticalScroll<R extends ComponentRenderer, RS extends ScrollerRend
void setRelativeBounds(int left, int top) {
super.setRelativeBounds(left, top);
if (child != null)
child.setRelativeBounds(0, 0);
if (child != null) {
int width = relativeBounds.width;
boolean willNeedScrollBar = child.height.calculatedSize() > relativeBounds.height;
if (willNeedScrollBar) width -= scrollerWidth();
int childTop = width - child.width.calculatedSize();
if (child.hAlign == Alignment.MIN) childTop = 0;
else if (child.hAlign == Alignment.CENTER) childTop /= 2;
int childLeft = relativeBounds.height - child.height.calculatedSize();
if (child.vAlign == Alignment.MIN) childLeft = 0;
else if (child.vAlign == Alignment.CENTER) childLeft /= 2;
child.setRelativeBounds(childLeft, childTop);
}
updateScrollViewMetrics();
}
@ -100,13 +117,13 @@ public class VerticalScroll<R extends ComponentRenderer, RS extends ScrollerRend
@Override
protected void renderInBounds(
PoseStack poseStack,
int x,
int y,
float a,
int mouseX,
int mouseY,
float deltaTicks,
Rectangle renderBounds,
Rectangle clipRect
) {
super.renderInBounds(poseStack, x, y, a, renderBounds, clipRect);
super.renderInBounds(poseStack, mouseX, mouseY, deltaTicks, renderBounds, clipRect);
if (showScrollBar()) {
if (child != null) {
@ -114,13 +131,8 @@ public class VerticalScroll<R extends ComponentRenderer, RS extends ScrollerRend
poseStack.translate(0, scrollerOffset(), 0);
setClippingRect(clipRect);
child.render(
poseStack, x, y, a,
renderBounds.movedBy(
0,
scrollerOffset(),
scrollerRenderer.scrollerWidth() + scrollerRenderer.scrollerPadding(),
0
),
poseStack, mouseX, mouseY, deltaTicks,
renderBounds.movedBy(0, scrollerOffset(), scrollerWidth(), 0),
clipRect
);
setClippingRect(null);
@ -129,7 +141,7 @@ public class VerticalScroll<R extends ComponentRenderer, RS extends ScrollerRend
scrollerRenderer.renderScrollBar(renderBounds, saveScrollerY(), scrollerHeight);
} else {
if (child != null) {
child.render(poseStack, x, y, a, renderBounds, clipRect);
child.render(poseStack, mouseX, mouseY, deltaTicks, renderBounds, clipRect);
}
}
}

View file

@ -9,5 +9,12 @@ import net.fabricmc.api.Environment;
@Environment(EnvType.CLIENT)
public interface ComponentRenderer {
void renderInBounds(PoseStack stack, int x, int y, float a, Rectangle bounds, Rectangle clipRect);
void renderInBounds(
PoseStack stack,
int mouseX,
int mouseY,
float deltaTicks,
Rectangle bounds,
Rectangle clipRect
);
}

View file

@ -10,7 +10,14 @@ import net.fabricmc.api.Environment;
@Environment(EnvType.CLIENT)
public class NullRenderer implements ComponentRenderer {
@Override
public void renderInBounds(PoseStack stack, int x, int y, float a, Rectangle bounds, Rectangle clipRect) {
public void renderInBounds(
PoseStack stack,
int mouseX,
int mouseY,
float deltaTicks,
Rectangle bounds,
Rectangle clipRect
) {
}
}

View file

@ -3,6 +3,10 @@ package org.betterx.ui.layout.components.render;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Font;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
@Environment(EnvType.CLIENT)
public interface TextProvider {
default Font getFont() {
return Minecraft.getInstance().font;

View file

@ -0,0 +1,4 @@
package org.betterx.ui.layout.values;
public record Size(int width, int height) {
}