diff --git a/Dungeoneer/assets/data/entities.dat b/Dungeoneer/assets/data/entities.dat index 33fc4e58..42ecfe79 100644 --- a/Dungeoneer/assets/data/entities.dat +++ b/Dungeoneer/assets/data/entities.dat @@ -1,5 +1,10 @@ { entities:{ + "Features": { + "NeoText": { + class: com.interrupt.dungeoneer.entities.NeoText + } + } "Areas": { "Spawn Blocker": { class:com.interrupt.dungeoneer.entities.areas.SpawnBlockerArea, diff --git a/Dungeoneer/src/com/interrupt/dungeoneer/entities/NeoText.java b/Dungeoneer/src/com/interrupt/dungeoneer/entities/NeoText.java new file mode 100644 index 00000000..39610e6e --- /dev/null +++ b/Dungeoneer/src/com/interrupt/dungeoneer/entities/NeoText.java @@ -0,0 +1,18 @@ +package com.interrupt.dungeoneer.entities; + +import com.badlogic.gdx.graphics.Color; +import com.interrupt.dungeoneer.annotations.EditorProperty; +import com.interrupt.dungeoneer.gfx.drawables.DrawableText; + +public class NeoText extends DirectionalEntity { + + @EditorProperty + public String text = "Test"; + + @EditorProperty + public Color textColor = Color.WHITE; + + public NeoText() { + this.drawable = new DrawableText(this.text); + } +} diff --git a/Dungeoneer/src/com/interrupt/dungeoneer/gfx/GlRenderer.java b/Dungeoneer/src/com/interrupt/dungeoneer/gfx/GlRenderer.java index 23acf309..77901cf9 100644 --- a/Dungeoneer/src/com/interrupt/dungeoneer/gfx/GlRenderer.java +++ b/Dungeoneer/src/com/interrupt/dungeoneer/gfx/GlRenderer.java @@ -36,10 +36,7 @@ import com.interrupt.dungeoneer.entities.triggers.TriggeredShop; import com.interrupt.dungeoneer.game.*; import com.interrupt.dungeoneer.gfx.decals.DDecal; -import com.interrupt.dungeoneer.gfx.drawables.DrawableBeam; -import com.interrupt.dungeoneer.gfx.drawables.DrawableMesh; -import com.interrupt.dungeoneer.gfx.drawables.DrawableProjectedDecal; -import com.interrupt.dungeoneer.gfx.drawables.DrawableSprite; +import com.interrupt.dungeoneer.gfx.drawables.*; import com.interrupt.dungeoneer.gfx.shaders.ShaderInfo; import com.interrupt.dungeoneer.gfx.shaders.WaterShaderInfo; import com.interrupt.dungeoneer.overlays.OverlayManager; @@ -130,6 +127,9 @@ public class GlRenderer { public SpriteBatch uiBatch; + public Array textToRender = new Array<>(); + public SpriteBatch textBatch; + protected ArrayMap opaqueSpriteBatches = new ArrayMap(); protected ArrayMap transparentSpriteBatches = new ArrayMap(); @@ -396,6 +396,8 @@ public void init() { uiBatch = new SpriteBatch(); uiBatch.setShader(uiShader); + textBatch = new SpriteBatch(); + postProcessBatch = new SpriteBatch(); postProcessBatch.disableBlending(); @@ -778,6 +780,69 @@ public void updateShaderAttributes() { } } + public void renderTextBatches() { + ShaderProgram activeProgram; + + if (renderingForPicking) { + activeProgram = ShaderManager.getShaderManager().getCompiledShader("picking").shader; + } else { + activeProgram = smoothLighting; + } + + textBatch.setShader(activeProgram); + + try { + int pvMatrixLoc = activeProgram.getUniformLocation("u_projectionViewMatrix"); + + for (int i = 0; i < textToRender.size; i++) { + DrawableText dT = textToRender.get(i); + + textBatch.begin(); + + Gdx.gl.glDepthMask(true); // SpriteBatch.begin() forces off depth writing, which we need for 3D space. + + Vector3 position = dT.parentPosition.cpy().add(dT.drawOffset); + + if (renderingForPicking) { + font.setColor(dT.pickingColor); + } else { + if (dT.editorState == Entity.EditorState.hovered) { + font.setColor(Color.SKY); + } else { + font.setColor(dT.worldColor.cpy().mul(dT.color)); // How to 'light' this correctly? + } + } + + GlyphLayout layout = font.draw(textBatch, dT.text, 0, 0); + + float scale = 0.025f * dT.scale; + Matrix4 pvmMatrix = camera.combined.cpy() // Calculate a new matrix to override the already-set uniform. + .translate(position.x, position.z, position.y) + .rotate(new Quaternion().setEulerAngles(dT.parentRotation.z, dT.parentRotation.y, dT.parentRotation.x)) + .scale(scale, scale, scale) + .translate( -layout.width / 2, 0, 0); // Center text on origin. + + activeProgram.setUniformMatrix(pvMatrixLoc, pvmMatrix); + + if (dT.editorState == Entity.EditorState.picked) { + textBatch.flush(); + + font.setColor(Color.CORAL); + font.draw(textBatch, dT.text, 0, 0); + + activeProgram.setUniformMatrix(pvMatrixLoc, pvmMatrix.translate(0, 0, -0.2f)); + } + + textBatch.end(); + } + + activeProgram.setUniformMatrix(pvMatrixLoc, camera.combined); // Reset the projection matrix. + + textToRender.clear(); + } + catch(Exception ex) { } + } + public void renderOpaqueSprites() { try { for (int i = 0; i < opaqueSpriteBatches.size; i++) { @@ -1057,6 +1122,7 @@ public void renderEntities(Level level) { } renderOpaqueSprites(); + renderTextBatches(); } public void renderEntitiesForPicking(Level level) { @@ -1094,6 +1160,7 @@ public void renderEntitiesForPicking(Level level) { } renderOpaqueSprites(); + renderTextBatches(); renderingForPicking = false; } @@ -1501,6 +1568,10 @@ else if(s.drawable instanceof DrawableSprite) else renderDrawableSprite(s.x, s.y, s.z, false, s, (DrawableSprite)s.drawable); } + + else if(s.drawable instanceof DrawableText) { + renderDrawableText(s.x, s.y, s.z, s, (DrawableText)s.drawable); + } else if(s.drawable instanceof DrawableBeam) { renderDrawableBeam(s.x, s.y, s.z, (DrawableBeam)s.drawable); } @@ -2237,7 +2308,6 @@ else if(drawable.billboard) { } else { Color lightmap = GetLightmapAt(x + drawable.drawOffset.x, z, y + drawable.drawOffset.y); - if(drawable.colorLastFrame != null) { drawable.colorLastFrame.lerp(lightmap.r, lightmap.g, lightmap.b, 1f, 4.5f * Gdx.graphics.getDeltaTime()); sd.setColor(drawable.colorLastFrame.r, drawable.colorLastFrame.g, drawable.colorLastFrame.b, drawable.color.a); @@ -2296,6 +2366,13 @@ else if(drawable.billboard) { usedDecals.add(sd); } + public void renderDrawableText(float x, float y, float z, Entity entity, DrawableText drawable) + { + drawable.worldColor.set(GetLightmapAt(x + drawable.drawOffset.x, z, y + drawable.drawOffset.y)); + drawable.pickingColor.set(entityPickColor); + textToRender.add(drawable); + } + Vector3 t_beam_axis = new Vector3(); Vector3 beam_tmp = new Vector3(); Vector3 t_beam_look = new Vector3(); diff --git a/Dungeoneer/src/com/interrupt/dungeoneer/gfx/drawables/DrawableText.java b/Dungeoneer/src/com/interrupt/dungeoneer/gfx/drawables/DrawableText.java new file mode 100644 index 00000000..0aa0deb8 --- /dev/null +++ b/Dungeoneer/src/com/interrupt/dungeoneer/gfx/drawables/DrawableText.java @@ -0,0 +1,37 @@ +package com.interrupt.dungeoneer.gfx.drawables; + +import com.badlogic.gdx.graphics.Color; +import com.badlogic.gdx.math.Vector3; +import com.interrupt.dungeoneer.entities.Entity; +import com.interrupt.dungeoneer.entities.NeoText; + +public class DrawableText extends Drawable { + + public String text = ""; + public Color worldColor = Color.WHITE; + public Vector3 parentPosition = new Vector3(); + public Vector3 parentRotation = new Vector3(); + public Entity.EditorState editorState = Entity.EditorState.hovered; + public Color pickingColor = Color.BLACK; + + public DrawableText() { + } + + public DrawableText(String text) { + this.text = text; + } + + public void update(Entity e) { + if (e instanceof NeoText) { + text = ((NeoText) e).text; + color.set(((NeoText) e).textColor); + } + + scale = e.scale; + + parentPosition.set(e.x, e.y, e.z); + parentRotation.set(e.getRotation()); + + editorState = e.editorState; + } +}