Skip to content

Commit 145cb64

Browse files
committed
Add support for culling
1 parent f62a70c commit 145cb64

12 files changed

Lines changed: 190 additions & 21 deletions

File tree

build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ plugins {
2121
}
2222

2323
group = "dev.dediamondpro"
24-
version = "1.3.1"
24+
version = "1.4.0"
2525

2626
dependencies {
2727
api(libs.commonmark)

elementa/src/main/kotlin/dev/dediamondpro/minemark/elementa/MineMarkComponent.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package dev.dediamondpro.minemark.elementa
1919

2020
import dev.dediamondpro.minemark.MineMarkCore
2121
import dev.dediamondpro.minemark.MineMarkCoreBuilder
22+
import dev.dediamondpro.minemark.data.ViewPort
2223
import dev.dediamondpro.minemark.elementa.elements.*
2324
import dev.dediamondpro.minemark.elementa.style.MarkdownStyle
2425
import dev.dediamondpro.minemark.elements.Elements
@@ -28,6 +29,7 @@ import gg.essential.elementa.UIComponent
2829
import gg.essential.elementa.dsl.constrain
2930
import gg.essential.elementa.dsl.pixels
3031
import gg.essential.universal.UMatrixStack
32+
import gg.essential.universal.UResolution
3133
import org.commonmark.ext.gfm.strikethrough.StrikethroughExtension
3234
import org.commonmark.ext.gfm.tables.TablesExtension
3335
import java.io.Reader
@@ -52,6 +54,13 @@ class MineMarkComponent(markdown: MineMarkElement<MarkdownStyle, UMatrixStack>)
5254
val parsedMarkdown: MineMarkElement<MarkdownStyle, UMatrixStack> = markdown.apply {
5355
addLayoutCallback(this@MineMarkComponent::layoutCallback)
5456
}
57+
private var viewPort: ViewPort =
58+
ViewPort(0f, 0f, UResolution.scaledWidth.toFloat(), UResolution.scaledHeight.toFloat())
59+
60+
override fun onWindowResize() {
61+
viewPort = ViewPort(0f, 0f, UResolution.scaledWidth.toFloat(), UResolution.scaledHeight.toFloat())
62+
super.onWindowResize()
63+
}
5564

5665
override fun afterInitialization() {
5766
super.afterInitialization()
@@ -89,6 +98,7 @@ class MineMarkComponent(markdown: MineMarkElement<MarkdownStyle, UMatrixStack>)
8998
this.getWidth(),
9099
mouse.first,
91100
mouse.second,
101+
viewPort,
92102
matrixStack
93103
)
94104
super.draw(matrixStack)

minecraft/src/main/java/dev/dediamondpro/minemark/minecraft/MineMarkDrawable.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,17 @@
1717

1818
package dev.dediamondpro.minemark.minecraft;
1919

20+
import com.mojang.blaze3d.platform.Window;
2021
import dev.dediamondpro.minemark.MineMarkCore;
2122
import dev.dediamondpro.minemark.MineMarkCoreBuilder;
23+
import dev.dediamondpro.minemark.data.ViewPort;
2224
import dev.dediamondpro.minemark.elements.Elements;
2325
import dev.dediamondpro.minemark.elements.MineMarkElement;
2426
import dev.dediamondpro.minemark.minecraft.elements.*;
2527
import dev.dediamondpro.minemark.minecraft.platform.MarkdownRenderer;
2628
import dev.dediamondpro.minemark.minecraft.style.MarkdownStyle;
2729
import dev.dediamondpro.minemark.utils.MouseButton;
30+
import net.minecraft.client.Minecraft;
2831
import net.minecraft.client.gui.GuiGraphics;
2932
import org.commonmark.ext.gfm.strikethrough.StrikethroughExtension;
3033
import org.commonmark.ext.gfm.tables.TablesExtension;
@@ -39,6 +42,7 @@ public class MineMarkDrawable implements AutoCloseable {
3942
.addExtension(TablesExtension.create())
4043
.build();
4144
private final MineMarkElement<MarkdownStyle, MarkdownRenderer> parsedMarkdown;
45+
private final Window window = Minecraft.getInstance().getWindow();
4246

4347
public MineMarkDrawable(MineMarkElement<MarkdownStyle, MarkdownRenderer> parsedMarkdown) {
4448
this.parsedMarkdown = parsedMarkdown;
@@ -69,7 +73,8 @@ public MineMarkDrawable(Reader markdown) throws IOException, SAXException {
6973
}
7074

7175
public void draw(float x, float y, float width, float mouseX, float mouseY, GuiGraphics drawContext) {
72-
parsedMarkdown.draw(x, y, width, mouseX, mouseY, new MarkdownRenderer(drawContext));
76+
ViewPort viewPort = new ViewPort(0, 0, window.getGuiScaledWidth(), window.getGuiScaledHeight());
77+
parsedMarkdown.draw(x, y, width, mouseX, mouseY, viewPort, new MarkdownRenderer(drawContext));
7378
}
7479

7580
public void beforeDraw(float x, float y, float width, float mouseX, float mouseY, GuiGraphics drawContext) {
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package dev.dediamondpro.minemark.data;
2+
3+
public class ViewPort {
4+
private final float x;
5+
private final float y;
6+
private final float width;
7+
private final float height;
8+
9+
/**
10+
* Create a new view port object
11+
*
12+
* @param x The top left x of the view port
13+
* @param y The top left y of the view port
14+
* @param width The width of the view port
15+
* @param height The height of the view port
16+
*/
17+
public ViewPort(float x, float y, float width, float height) {
18+
this.x = x;
19+
this.y = y;
20+
this.width = width;
21+
this.height = height;
22+
}
23+
24+
public float getLeftX() {
25+
return x;
26+
}
27+
28+
public float getTopY() {
29+
return y;
30+
}
31+
32+
public float getRightX() {
33+
return x + width;
34+
}
35+
36+
public float getBottomY() {
37+
return y + height;
38+
}
39+
40+
public float getWidth() {
41+
return width;
42+
}
43+
44+
public float getHeight() {
45+
return height;
46+
}
47+
48+
public boolean isInViewPort(float leftX, float topY, float rightX, float bottomY) {
49+
return !(leftX > getRightX() || rightX < getLeftX()
50+
|| topY > getBottomY() || bottomY < getTopY());
51+
}
52+
53+
public boolean isInViewPortVertical(float topY, float bottomY) {
54+
return !(topY > getBottomY() || bottomY < getTopY());
55+
}
56+
}

src/main/java/dev/dediamondpro/minemark/elements/BasicElement.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
import dev.dediamondpro.minemark.LayoutData;
2121
import dev.dediamondpro.minemark.LayoutStyle;
22+
import dev.dediamondpro.minemark.data.ViewPort;
2223
import dev.dediamondpro.minemark.style.Style;
2324
import org.jetbrains.annotations.NotNull;
2425
import org.jetbrains.annotations.Nullable;
@@ -32,7 +33,7 @@ public BasicElement(@NotNull S style, @NotNull LayoutStyle layoutStyle, @Nullabl
3233
}
3334

3435
@Override
35-
public void drawInternal(float xOffset, float yOffset, float mouseX, float mouseY, R renderData) {
36+
public void drawInternal(float xOffset, float yOffset, float mouseX, float mouseY, @Nullable ViewPort viewPort, R renderData) {
3637
drawElement(
3738
position.getX() + xOffset, position.getY() + yOffset,
3839
position.getWidth(), position.getHeight(),
@@ -52,6 +53,12 @@ public void generateLayout(LayoutData layoutData, R renderData) {
5253
position = layoutData.addElement(layoutStyle.get(LayoutStyle.ALIGNMENT), width, height);
5354
}
5455

56+
@Override
57+
public boolean shouldDraw(@NotNull ViewPort viewPort, float xOffset, float yOffset) {
58+
return viewPort.isInViewPort(position.getX() + xOffset, position.getY() + yOffset,
59+
position.getRightX() + xOffset, position.getBottomY() + yOffset);
60+
}
61+
5562
protected abstract void drawElement(float x, float y, float width, float height, float mouseX, float mouseY, R renderData);
5663

5764
protected abstract float getWidth(LayoutData layoutData, R renderData);

src/main/java/dev/dediamondpro/minemark/elements/ChildBasedElement.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,27 +19,38 @@
1919

2020
import dev.dediamondpro.minemark.LayoutData;
2121
import dev.dediamondpro.minemark.LayoutStyle;
22+
import dev.dediamondpro.minemark.data.ViewPort;
2223
import dev.dediamondpro.minemark.style.Style;
2324
import org.jetbrains.annotations.NotNull;
2425
import org.jetbrains.annotations.Nullable;
2526
import org.xml.sax.Attributes;
2627

2728
public abstract class ChildBasedElement<S extends Style, R> extends Element<S, R> {
29+
private float top = Float.NEGATIVE_INFINITY;
30+
private float bottom = Float.POSITIVE_INFINITY;
31+
2832
public ChildBasedElement(@NotNull S style, @NotNull LayoutStyle layoutStyle, @Nullable Element<S, R> parent, @NotNull String qName, @Nullable Attributes attributes) {
2933
super(style, layoutStyle, parent, qName, attributes);
3034
}
3135

3236
@Override
3337
public void generateLayout(LayoutData layoutData, R renderData) {
38+
top = layoutData.getCurrentLine().getY();
3439
float padding = getPadding(layoutData, renderData);
3540
layoutData.updateTopSpacing(padding);
3641
for (Element<S, R> child : children) {
3742
child.generateLayoutInternal(layoutData, renderData);
3843
}
3944
layoutData.updateBottomSpacing(padding);
45+
bottom = layoutData.getCurrentLine().getBottomY();
4046
}
4147

4248
protected float getPadding(LayoutData layoutData, R renderData) {
4349
return 0f;
4450
}
51+
52+
@Override
53+
public boolean shouldDraw(@NotNull ViewPort viewPort, float xOffset, float yOffset) {
54+
return viewPort.isInViewPortVertical(top + yOffset, bottom + yOffset);
55+
}
4556
}

src/main/java/dev/dediamondpro/minemark/elements/ChildMovingElement.java

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
import dev.dediamondpro.minemark.LayoutData;
2121
import dev.dediamondpro.minemark.LayoutStyle;
22+
import dev.dediamondpro.minemark.data.ViewPort;
2223
import dev.dediamondpro.minemark.style.Style;
2324
import dev.dediamondpro.minemark.utils.MouseButton;
2425
import org.jetbrains.annotations.ApiStatus;
@@ -35,6 +36,8 @@ public abstract class ChildMovingElement<S extends Style, R> extends Element<S,
3536
protected float totalHeight;
3637
protected float extraXOffset;
3738
protected float extraYOffset;
39+
float top = Float.NEGATIVE_INFINITY;
40+
float bottom = Float.POSITIVE_INFINITY;
3841

3942
public ChildMovingElement(@NotNull S style, @NotNull LayoutStyle layoutStyle, @Nullable Element<S, R> parent, @NotNull String qName, @Nullable Attributes attributes) {
4043
super(style, layoutStyle, parent, qName, attributes);
@@ -45,6 +48,7 @@ public void generateLayout(LayoutData layoutData, R renderData) {
4548
if (layoutData.isLineModified()) {
4649
layoutData.nextLine();
4750
}
51+
top = layoutData.getCurrentLine().getY();
4852

4953
float markerWidth = getMarkerWidth(layoutData, renderData);
5054
float outsidePadding = getOutsidePadding(layoutData, renderData);
@@ -82,6 +86,7 @@ public void generateLayout(LayoutData layoutData, R renderData) {
8286
totalHeight + insidePadding * 2
8387
);
8488
}
89+
bottom = layoutData.getCurrentLine().getBottomY();
8590
layoutData.nextLine();
8691

8792
extraXOffset = (markerType == MarkerType.BLOCK ? 0f : marker.getRightX()) + insidePadding;
@@ -96,15 +101,23 @@ protected void generateNewLayout(LayoutData layoutData, R renderData) {
96101

97102
@Override
98103
@ApiStatus.Internal
99-
public void drawInternal(float xOffset, float yOffset, float mouseX, float mouseY, R renderData) {
104+
public void drawInternal(float xOffset, float yOffset, float mouseX, float mouseY, @Nullable ViewPort viewPort, R renderData) {
100105
if (marker != null) {
101106
drawMarker(marker.getX() + xOffset, marker.getY() + yOffset, marker.getWidth(), marker.getHeight(), renderData);
102107
}
108+
109+
float newXOffset = xOffset + extraXOffset;
110+
float newYOffset = yOffset + extraYOffset;
111+
float newMouseX = mouseX - extraXOffset;
112+
float newMouseY = mouseY - extraYOffset;
103113
for (Element<S, R> child : children) {
104-
child.drawInternal(
105-
xOffset + extraXOffset, yOffset + extraYOffset,
106-
mouseX - extraXOffset, mouseY - extraYOffset, renderData
107-
);
114+
if (viewPort != null && child.shouldDraw(viewPort, newXOffset, newYOffset)) {
115+
child.drawInternal(
116+
newXOffset, newYOffset,
117+
newMouseX, newMouseY,
118+
viewPort, renderData
119+
);
120+
}
108121
}
109122
}
110123

@@ -151,4 +164,9 @@ protected enum MarkerType {
151164
FULL,
152165
BLOCK
153166
}
167+
168+
@Override
169+
public boolean shouldDraw(@NotNull ViewPort viewPort, float xOffset, float yOffset) {
170+
return viewPort.isInViewPortVertical(top + yOffset, bottom + yOffset);
171+
}
154172
}

src/main/java/dev/dediamondpro/minemark/elements/Element.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
import dev.dediamondpro.minemark.LayoutData;
2121
import dev.dediamondpro.minemark.LayoutStyle;
22+
import dev.dediamondpro.minemark.data.ViewPort;
2223
import dev.dediamondpro.minemark.elements.impl.TextElement;
2324
import dev.dediamondpro.minemark.elements.creators.ElementCreator;
2425
import dev.dediamondpro.minemark.style.Style;
@@ -71,9 +72,11 @@ public void complete() {
7172
* Internal method for drawing an element, should never be used directly.
7273
*/
7374
@ApiStatus.OverrideOnly
74-
public void drawInternal(float xOffset, float yOffset, float mouseX, float mouseY, R renderData){
75+
public void drawInternal(float xOffset, float yOffset, float mouseX, float mouseY, @Nullable ViewPort viewPort, R renderData) {
7576
for (Element<S, R> child : children) {
76-
child.drawInternal(xOffset, yOffset, mouseX, mouseY, renderData);
77+
if (viewPort == null || child.shouldDraw(viewPort, xOffset, yOffset)) {
78+
child.drawInternal(xOffset, yOffset, mouseX, mouseY, viewPort, renderData);
79+
}
7780
}
7881
}
7982

@@ -154,6 +157,14 @@ public String buildTree(int depth) {
154157
return builder.toString();
155158
}
156159

160+
/**
161+
* Function that decides if an element should be drawn or not given the current view port.
162+
* Used to cull elements that would be outside the viewport.
163+
*/
164+
public boolean shouldDraw(@NotNull ViewPort viewPort, float xOffset, float yOffset) {
165+
return true;
166+
}
167+
157168
public @Nullable Element<S, R> getParent() {
158169
return parent;
159170
}

src/main/java/dev/dediamondpro/minemark/elements/MineMarkElement.java

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,11 @@
1919

2020
import dev.dediamondpro.minemark.LayoutData;
2121
import dev.dediamondpro.minemark.LayoutStyle;
22+
import dev.dediamondpro.minemark.data.ViewPort;
2223
import dev.dediamondpro.minemark.style.Style;
2324
import dev.dediamondpro.minemark.utils.MouseButton;
2425
import org.jetbrains.annotations.ApiStatus;
26+
import org.jetbrains.annotations.Nullable;
2527
import org.xml.sax.Attributes;
2628

2729
import java.util.ArrayList;
@@ -45,16 +47,31 @@ public MineMarkElement(S style, LayoutStyle layoutStyle, Attributes attributes)
4547
* @param width The maximum width of the markdown element
4648
* @param mouseX The current X-Coordinate of the mouse
4749
* @param mouseY The current Y-Coordinate of the mouse
50+
* @param viewPort The currently visible content, content outside the viewport will not be rendered
4851
* @param renderData Data class passed to all subclassed to aid in rendering
4952
*/
50-
public void draw(float x, float y, float width, float mouseX, float mouseY, R renderData) {
53+
public void draw(float x, float y, float width, float mouseX, float mouseY, @Nullable ViewPort viewPort, R renderData) {
5154
if (width <= 0) {
5255
throw new IllegalArgumentException("Width cannot be zero or negative!");
5356
}
5457
if (width != lastWidth) {
5558
beforeDraw(x, y, width, mouseX, mouseY, renderData);
5659
}
57-
this.drawInternal(x, y, mouseX - x, mouseY - y, renderData);
60+
this.drawInternal(x, y, mouseX - x, mouseY - y, viewPort, renderData);
61+
}
62+
63+
/**
64+
* Draw the markdown layout
65+
*
66+
* @param x X-Coordinate of the top left corner
67+
* @param y Y-Coordinate of the top left corner
68+
* @param width The maximum width of the markdown element
69+
* @param mouseX The current X-Coordinate of the mouse
70+
* @param mouseY The current Y-Coordinate of the mouse
71+
* @param renderData Data class passed to all subclassed to aid in rendering
72+
*/
73+
public void draw(float x, float y, float width, float mouseX, float mouseY, R renderData) {
74+
this.draw(x, y, width, mouseX, mouseY, null, renderData);
5875
}
5976

6077

src/main/java/dev/dediamondpro/minemark/elements/impl/HeadingElement.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
import dev.dediamondpro.minemark.LayoutData;
2121
import dev.dediamondpro.minemark.LayoutStyle;
22+
import dev.dediamondpro.minemark.data.ViewPort;
2223
import dev.dediamondpro.minemark.elements.ChildBasedElement;
2324
import dev.dediamondpro.minemark.elements.Element;
2425
import dev.dediamondpro.minemark.elements.Inline;
@@ -45,8 +46,8 @@ public HeadingElement(@NotNull S style, @NotNull LayoutStyle layoutStyle, @Nulla
4546
}
4647

4748
@Override
48-
public void drawInternal(float xOffset, float yOffset, float mouseX, float mouseY, R renderData) {
49-
super.drawInternal(xOffset, yOffset, mouseX, mouseY, renderData);
49+
public void drawInternal(float xOffset, float yOffset, float mouseX, float mouseY, @Nullable ViewPort viewPort, R renderData) {
50+
super.drawInternal(xOffset, yOffset, mouseX, mouseY, viewPort, renderData);
5051
if (headingStyle.hasDivider()) {
5152
drawDivider(
5253
xOffset + dividerPosition.getX(), yOffset + dividerPosition.getY(),

0 commit comments

Comments
 (0)