Surface
com.jsmacrosce.jsmacros.client.api.classes.render.components3d.Surface
A Draw2D panel rendered in the world. Its element coordinates are surface pixels measured from the top left, with y increasing downwards; surface size is in blocks, and getWidth() and getHeight() report pixel dimensions.
This is a 2D overlay living in three dimensions. It is a Draw2D in its own right, so everything a 2D overlay can hold, addText, addRect,addLine, addImage, addItem and the rest, works on it unchanged, and the same builders do too. The difference is where the result appears:
a surface is placed at a block position in the world, rotated to face a direction,
and drawn as a flat surface there rather than flat on the screen. The coordinates a script gives its elements are the surface's own pixels, measured from its top left with y growing downwards, and how big a pixel is in blocks is decided by the size and the subdivision count rather than by the element.
A surface is reached through Draw3D, either with addDraw2D for the quick form or through Draw3D.surfaceBuilder() for the full one. A surface on its own draws nothing; it is the 3D overlay holding it that has to be registered.
Three settings decide whether it can be seen. cull makes it depth tested, so terrain draws over it; leaving it off draws the surface over the world instead.renderBack decides whether the back is drawn at all, and with it off the surface disappears when the camera is behind it. And rotateToPlayer turns the surface to face the camera every frame, which overwrites whatever rotations were set.
Lighting is a fourth. By default everything on a surface is drawn at full brightness, ignoring the world. setWorldLight() samples the world instead,
once per frame at the surface's own position, and setLight(int, int) fixes a level. None of them model a cast shadow.
The size and the subdivision count work together rather than independently. The size is in blocks and the subdivision count says how many of those the smaller side is divided into, and one subdivision is the unit the elements are measured in. So a surface 1 block on a side with a subdivision count of 200 is 200 by 200 surface pixels, and the same surface at minSubdivisions of 1 is a single pixel. getWidth() and getHeight() report those subdivision counts, not the block size.
The two ways of making a surface do not start from the same place.
Draw3D.surfaceBuilder() leaves the count at 1, so a builder with nothing set on it gives a single pixel across its smaller side, while the short Draw3D.addDraw2D forms that take no subdivision count pass 200.
const draw = Hud.createDraw3D();
// a one block panel with room for a label, drawn over the world
const surface = draw.surfaceBuilder()
.pos(0.5, 64, 0.5)
.size(1, 1)
.minSubdivisions(200)
.cull(false)
.renderBack(true)
.buildAndAdd();
surface.addText("hello", 10, 10, Color.rgb(0xFF, 0xFF, 0xFF), true);
draw.register();Available in scripts as RenderElements.Surface.
Nested types
Constructors
new Surface
new Surface(Pos3D pos, Pos3D rotations, Pos2D sizes, int minSubdivisions, boolean renderBack, boolean cull)#1; initialization computes the pixel scale and clears/runs the inherited initialization behavior, but does not add this surface to a Draw3D overlay.Parameters:
pos: panel's top-left world position, in blocksrotations: rotations about x, y, and z, in degreessizes: physical width and height, in blocksminSubdivisions: subdivisions across the smaller side, clamped to at least1renderBack: whether to draw the surface when viewed from its back sidecull: whether depth testing against the world is enabled
Fields
boundEntity
null if unbound. While alive, the surface uses the entity's interpolated position plus boundOffset; if the entity is no longer alive, rendering uses pos instead.boundOffset
cull
pos
renderBack
rotateCenter
false; the builder defaults to true.rotateToPlayer
rotations
zIndexScale
0.001 blocks per z-index unit.Methods
bindToEntity
null unbinds it.Parameters:
boundEntity: the entity to bind the surface to
compareToSame
Parameters:
other: another surface to order this one against
otherdoesRotateToPlayer
true if the surface is configured to face the cameraequals
Parameters:
o: object to compare
true if o is this surface or has the same runtime class and equal position, rotations, and size; false for null or a different classgetBoundEntity
null if none is setgetBoundOffset
getHeight
getMinSubdivisions
1.getSizes
getWidth
getZIndex
0.0hashCode
hashCode(): int#init
isRotatingCenter
render
render(GuiGraphics drawContext, int mouseX, int mouseY, float delta): void#Parameters:
drawContext: graphics context, unusedmouseX: mouse x-coordinate, unusedmouseY: mouse y-coordinate, unuseddelta: frame delta, unused
setBoundOffset
Parameters:
boundOffset: offset from the entity's interpolated position
Parameters:
x: the x offset in blocksy: the y offset in blocksz: the z offset in blocks
setFullBrightLight
setLight
setMinSubdivisions
0 or below is raised to 1, so a surface can be made to have a single pixel but never none. The pixel scale is recomputed after the count is set.Parameters:
minSubdivisions: how many subdivisions the smaller side is divided into
setPos
pos.Parameters:
pos: position in world blocks
pos.Parameters:
pos: block position in the world
const draw = Hud.createDraw3D();
const surface = draw.surfaceBuilder().pos(0, 64, 0).buildAndAdd();
surface.setPos(10, 70, -4);
draw.register();Parameters:
x: the x coordinate of the surface's cornery: the y coordinate of the surface's cornerz: the z coordinate of the surface's corner
setRotateCenter
setRotateToPlayer
setRotations
Parameters:
x: the rotation about the x axis, in degreesy: the rotation about the y axis, in degreesz: the rotation about the z axis, in degrees
setSizes
Parameters:
x: the width of the surface, in blocksy: the height of the surface, in blocks