Skip to content

Commit f61dc8e

Browse files
committed
helpers for drawing entities
1 parent 4e5e7ea commit f61dc8e

File tree

4 files changed

+183
-4
lines changed

4 files changed

+183
-4
lines changed

src/main/java/com/cleanroommc/modularui/drawable/GuiDraw.java

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import com.cleanroommc.modularui.drawable.text.TextRenderer;
44
import com.cleanroommc.modularui.screen.RichTooltip;
55
import com.cleanroommc.modularui.screen.RichTooltipEvent;
6+
import com.cleanroommc.modularui.screen.viewport.GuiContext;
67
import com.cleanroommc.modularui.utils.Alignment;
78
import com.cleanroommc.modularui.utils.Color;
89
import com.cleanroommc.modularui.utils.NumberFormat;
@@ -15,8 +16,11 @@
1516
import net.minecraft.client.renderer.BufferBuilder;
1617
import net.minecraft.client.renderer.GlStateManager;
1718
import net.minecraft.client.renderer.RenderItem;
19+
import net.minecraft.client.renderer.entity.RenderManager;
1820
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
1921
import net.minecraft.client.renderer.texture.TextureMap;
22+
import net.minecraft.entity.Entity;
23+
import net.minecraft.entity.EntityLivingBase;
2024
import net.minecraft.item.ItemStack;
2125
import net.minecraft.util.ResourceLocation;
2226
import net.minecraftforge.client.event.RenderTooltipEvent;
@@ -29,6 +33,7 @@
2933
import org.jetbrains.annotations.Nullable;
3034

3135
import java.util.List;
36+
import java.util.function.Consumer;
3237

3338
public class GuiDraw {
3439

@@ -561,4 +566,89 @@ public static void drawTooltipBackground(ItemStack stack, List<String> lines, in
561566
// bottom accent border
562567
drawVerticalGradientRect(x - 3, y + height + 2, textWidth + 6, 1, borderColorEnd, borderColorEnd);
563568
}
569+
570+
/**
571+
* Draws an entity. Note that this does NOT do any necessary setup for rendering the entity. Please see
572+
* {@link #drawEntity(Entity, float, float, float, float, Consumer, Consumer)} for a full draw method.
573+
*
574+
* @param entity entity to draw.
575+
* @see #drawEntity(Entity, float, float, float, float, Consumer, Consumer)
576+
*/
577+
public static void drawEntityRaw(Entity entity) {
578+
RenderManager rendermanager = Minecraft.getMinecraft().getRenderManager();
579+
rendermanager.setPlayerViewY(180.0F);
580+
rendermanager.setRenderShadow(false);
581+
rendermanager.renderEntity(entity, 0.0D, 0.0D, 0.0D, 0.0F, 1.0F, false);
582+
rendermanager.setRenderShadow(true);
583+
}
584+
585+
/**
586+
* A simple method to a draw an entity in a GUI. Using the consumers is not always ideal to modify and restore entity state. In those
587+
* cases just copy and paste this method and put your code where the consumers would be called. The entity will be scaled so that it
588+
* fits right in the given size when untransformed (default). When transforming during pre draw, you may need to manually correct the
589+
* scale and offset.
590+
*
591+
* @param entity entity to draw
592+
* @param x x pos
593+
* @param y y pos
594+
* @param w the width of the area where the entity should be drawn
595+
* @param h the height of the area where the entity should be drawn
596+
* @param z the z layer ({@link GuiContext#getCurrentDrawingZ()} if drawn in a MUI)
597+
* @param preDraw a function to call before rendering. Transform or modify the entity here.
598+
* @param postDraw a function to call after rendering. Restore old entity state here if needed.
599+
* @param <T> type of the entity to render
600+
*/
601+
public static <T extends Entity> void drawEntity(T entity, float x, float y, float w, float h, float z, @Nullable Consumer<T> preDraw, @Nullable Consumer<T> postDraw) {
602+
GlStateManager.pushMatrix();
603+
Platform.setupDrawEntity(entity, x, y, w, h, z);
604+
if (preDraw != null) preDraw.accept(entity);
605+
drawEntityRaw(entity);
606+
if (postDraw != null) postDraw.accept(entity);
607+
Platform.endDrawEntity();
608+
GlStateManager.popMatrix();
609+
}
610+
611+
/**
612+
* Draws an entity which looks in the direction of the mouse like the player render in the player inventory does.
613+
* The code was copied from
614+
* {@link net.minecraft.client.gui.inventory.GuiInventory#drawEntityOnScreen(int, int, int, float, float, EntityLivingBase) GuiInventory.drawEntityOnScreen}.
615+
*
616+
* @param entity entity to draw
617+
* @param x x pos
618+
* @param y y pos
619+
* @param w the width of the area where the entity should be drawn
620+
* @param h the height of the area where the entity should be drawn
621+
* @param z the z layer ({@link GuiContext#getCurrentDrawingZ()} if drawn in a MUI)
622+
* @param mouseX current x pos of the mouse
623+
* @param mouseY current y pos of the mouse
624+
*/
625+
public static void drawEntityLookingAtMouse(EntityLivingBase entity, float x, float y, float w, float h, float z, int mouseX, int mouseY) {
626+
GlStateManager.pushMatrix();
627+
Platform.setupDrawEntity(entity, x, y, w, h, z);
628+
629+
// pre draw
630+
float f = entity.renderYawOffset;
631+
float f1 = entity.rotationYaw;
632+
float f2 = entity.rotationPitch;
633+
float f3 = entity.prevRotationYawHead;
634+
float f4 = entity.rotationYawHead;
635+
GlStateManager.rotate(-((float) Math.atan(mouseY / 40.0F)) * 20.0F, 1.0F, 0.0F, 0.0F);
636+
entity.renderYawOffset = (float) Math.atan(mouseX / 40.0F) * 20.0F;
637+
entity.rotationYaw = (float) Math.atan(mouseX / 40.0F) * 40.0F;
638+
entity.rotationPitch = -((float) Math.atan(mouseY / 40.0F)) * 20.0F;
639+
entity.rotationYawHead = entity.rotationYaw;
640+
entity.prevRotationYawHead = entity.rotationYaw;
641+
642+
drawEntityRaw(entity);
643+
644+
// post draw
645+
entity.renderYawOffset = f;
646+
entity.rotationYaw = f1;
647+
entity.rotationPitch = f2;
648+
entity.prevRotationYawHead = f3;
649+
entity.rotationYawHead = f4;
650+
651+
Platform.endDrawEntity();
652+
GlStateManager.popMatrix();
653+
}
564654
}

src/main/java/com/cleanroommc/modularui/test/TestGuis.java

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,12 @@
1515
import com.cleanroommc.modularui.screen.CustomModularScreen;
1616
import com.cleanroommc.modularui.screen.ModularPanel;
1717
import com.cleanroommc.modularui.screen.RichTooltip;
18+
import com.cleanroommc.modularui.screen.viewport.GuiContext;
1819
import com.cleanroommc.modularui.screen.viewport.ModularGuiContext;
20+
import com.cleanroommc.modularui.theme.WidgetTheme;
1921
import com.cleanroommc.modularui.utils.*;
2022
import com.cleanroommc.modularui.utils.fakeworld.ArraySchema;
23+
import com.cleanroommc.modularui.utils.fakeworld.FakeEntity;
2124
import com.cleanroommc.modularui.utils.fakeworld.ISchema;
2225
import com.cleanroommc.modularui.value.StringValue;
2326
import com.cleanroommc.modularui.widget.DraggableWidget;
@@ -34,8 +37,11 @@
3437

3538
import com.cleanroommc.modularui.widgets.textfield.TextFieldWidget;
3639

40+
import net.minecraft.client.Minecraft;
3741
import net.minecraft.client.renderer.GlStateManager;
3842
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
43+
import net.minecraft.entity.Entity;
44+
import net.minecraft.entity.boss.EntityDragon;
3945
import net.minecraft.init.Blocks;
4046
import net.minecraft.init.Items;
4147
import net.minecraft.item.ItemStack;
@@ -54,7 +60,7 @@ public class TestGuis extends CustomModularScreen {
5460

5561
@Override
5662
public @NotNull ModularPanel buildUI(ModularGuiContext context) {
57-
return buildSearchTest(context);
63+
return buildSpriteAndEntityUI(context);
5864
}
5965

6066
public @NotNull ModularPanel buildAnimationUI(ModularGuiContext context) {
@@ -127,16 +133,19 @@ public class TestGuis extends CustomModularScreen {
127133
})));
128134
}
129135

130-
public @NotNull ModularPanel buildSpriteUI(ModularGuiContext context) {
136+
public @NotNull ModularPanel buildSpriteAndEntityUI(ModularGuiContext context) {
131137
TextureAtlasSprite sprite = SpriteHelper.getSpriteOfBlockState(GameObjectHelper.getBlockState("minecraft", "command_block"), EnumFacing.UP);
132138
// SpriteHelper.getSpriteOfItem(new ItemStack(Items.DIAMOND));
139+
Entity entity = FakeEntity.create(EntityDragon.class);
140+
float period = 3000f;
133141
return ModularPanel.defaultPanel("main")
134142
.size(150)
135143
.child(new TextWidget(IKey.str("Test String")).scale(0.6f).horizontalCenter().top(7))
136144
.child(new DraggableWidget<>()
137145
.background(new SpriteDrawable(sprite))
138146
.size(20)
139-
.center()
147+
.alignX(0.5f)
148+
.top(20)
140149
.tooltipBuilder(tooltip -> {
141150
tooltip.addLine(
142151
"Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. "
@@ -148,7 +157,19 @@ public class TestGuis extends CustomModularScreen {
148157
tooltip.alignment(Alignment.Center);
149158
tooltip.scale(0.5f);
150159
tooltip.pos(RichTooltip.Pos.NEXT_TO_MOUSE);
151-
}));
160+
}))
161+
.child(new IDrawable() {
162+
@Override
163+
public void draw(GuiContext context, int x, int y, int width, int height, WidgetTheme widgetTheme) {
164+
GuiDraw.drawEntity(entity, 0, 0, width, height, context.getCurrentDrawingZ(), e -> {
165+
float scale = 0.9f;
166+
GlStateManager.scale(scale, scale, scale);
167+
GlStateManager.translate(0, 7, 0);
168+
GlStateManager.rotate(35, 1, 0, 0);
169+
GlStateManager.rotate(360 * (Minecraft.getSystemTime() % period) / period, 0, 1, 0);
170+
}, null);
171+
}
172+
}.asWidget().alignX(0.5f).bottom(10).size(100, 75));
152173
}
153174

154175

src/main/java/com/cleanroommc/modularui/utils/Platform.java

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
package com.cleanroommc.modularui.utils;
22

3+
import com.cleanroommc.modularui.screen.viewport.GuiContext;
4+
35
import net.minecraft.client.Minecraft;
46
import net.minecraft.client.entity.EntityPlayerSP;
57
import net.minecraft.client.renderer.BufferBuilder;
68
import net.minecraft.client.renderer.GlStateManager;
9+
import net.minecraft.client.renderer.OpenGlHelper;
710
import net.minecraft.client.renderer.RenderHelper;
811
import net.minecraft.client.renderer.Tessellator;
912
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
1013
import net.minecraft.client.settings.KeyBinding;
14+
import net.minecraft.entity.Entity;
1115
import net.minecraft.item.ItemStack;
1216
import net.minecraft.util.ResourceLocation;
1317
import net.minecraftforge.fml.relauncher.Side;
@@ -103,6 +107,46 @@ public static void setupDrawFont() {
103107
setupDrawTex();
104108
}
105109

110+
/**
111+
* Sets up the gl state for rendering an entity. The entity will be scaled so that it fits right in the given size when untransformed.
112+
*
113+
* @param entity entity to set up drawing for
114+
* @param x x pos
115+
* @param y y pos
116+
* @param w the width of the area where the entity should be drawn
117+
* @param h the height of the area where the entity should be drawn
118+
* @param z the z layer ({@link GuiContext#getCurrentDrawingZ()} if drawn in a MUI)
119+
*/
120+
public static void setupDrawEntity(Entity entity, float x, float y, float w, float h, float z) {
121+
float size;
122+
float scale;
123+
if (h / entity.height < w / entity.width) {
124+
size = entity.height;
125+
scale = h / size;
126+
} else {
127+
size = entity.width;
128+
scale = w / size;
129+
}
130+
GlStateManager.enableColorMaterial();
131+
GlStateManager.enableDepth();
132+
GlStateManager.translate(x + w / 2, y + h / 2, z + 50.0F);
133+
GlStateManager.scale(-scale, scale, scale);
134+
GlStateManager.translate(0, size / 2f, 0);
135+
GlStateManager.rotate(180.0F, 0.0F, 0.0F, 1.0F);
136+
GlStateManager.rotate(135.0F, 0.0F, 1.0F, 0.0F);
137+
RenderHelper.enableStandardItemLighting();
138+
GlStateManager.rotate(-135.0F, 0.0F, 1.0F, 0.0F);
139+
}
140+
141+
public static void endDrawEntity() {
142+
RenderHelper.disableStandardItemLighting();
143+
GlStateManager.disableRescaleNormal();
144+
GlStateManager.setActiveTexture(OpenGlHelper.lightmapTexUnit);
145+
GlStateManager.disableTexture2D();
146+
GlStateManager.setActiveTexture(OpenGlHelper.defaultTexUnit);
147+
GlStateManager.disableDepth();
148+
}
149+
106150
/**
107151
* <a href="https://i.sstatic.net/sfQdh.jpg">Reference</a>
108152
*/
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.cleanroommc.modularui.utils.fakeworld;
2+
3+
import net.minecraft.entity.Entity;
4+
import net.minecraft.world.World;
5+
import net.minecraftforge.fml.common.registry.EntityEntry;
6+
import net.minecraftforge.fml.common.registry.EntityRegistry;
7+
8+
/**
9+
* Utility class for creating entities for rendering in gui.
10+
*/
11+
public class FakeEntity {
12+
13+
private static final World entityWorld = new DummyWorld();
14+
15+
private FakeEntity() {}
16+
17+
public static <T extends Entity> T create(Class<T> entityClass) {
18+
return (T) create(EntityRegistry.getEntry(entityClass));
19+
}
20+
21+
public static Entity create(EntityEntry entry) {
22+
return entry.newInstance(entityWorld);
23+
}
24+
}

0 commit comments

Comments
 (0)