diff --git a/core/src/mindustry/Vars.java b/core/src/mindustry/Vars.java index 24fcc3ad77..959b0bc390 100644 --- a/core/src/mindustry/Vars.java +++ b/core/src/mindustry/Vars.java @@ -5,7 +5,6 @@ import arc.*; import arc.assets.*; import arc.files.*; import arc.graphics.*; -import arc.graphics.g3d.*; import arc.scene.ui.layout.*; import arc.struct.*; import arc.util.*; @@ -165,7 +164,6 @@ public class Vars implements Loadable{ /** list of all locales that can be switched to */ public static Locale[] locales; - public static Camera3D cam3; public static FileTree tree = new FileTree(); public static Net net; public static ContentLoader content; @@ -264,10 +262,6 @@ public class Vars implements Loadable{ mods.load(); maps.load(); - - if(!headless){ - cam3 = new Camera3D(); - } } public static void loadLogger(){ diff --git a/core/src/mindustry/core/Renderer.java b/core/src/mindustry/core/Renderer.java index bfca715bce..4a7b6e64ae 100644 --- a/core/src/mindustry/core/Renderer.java +++ b/core/src/mindustry/core/Renderer.java @@ -13,6 +13,7 @@ import mindustry.content.*; import mindustry.game.EventType.*; import mindustry.gen.*; import mindustry.graphics.*; +import mindustry.graphics.g3d.*; import mindustry.ui.*; import static arc.Core.*; @@ -24,6 +25,7 @@ public class Renderer implements ApplicationListener{ public final OverlayRenderer overlays = new OverlayRenderer(); public final LightRenderer lights = new LightRenderer(); public final Pixelator pixelator = new Pixelator(); + public PlanetRenderer planets; public FrameBuffer effectBuffer = new FrameBuffer(); private Bloom bloom; @@ -47,6 +49,8 @@ public class Renderer implements ApplicationListener{ @Override public void init(){ + planets = new PlanetRenderer(); + if(settings.getBool("bloom")){ setupBloom(); } @@ -96,6 +100,7 @@ public class Renderer implements ApplicationListener{ minimap.dispose(); effectBuffer.dispose(); blocks.dispose(); + planets.dispose(); if(bloom != null){ bloom.dispose(); bloom = null; diff --git a/core/src/mindustry/graphics/Shaders.java b/core/src/mindustry/graphics/Shaders.java index 8e99d156a7..0e46e83d60 100644 --- a/core/src/mindustry/graphics/Shaders.java +++ b/core/src/mindustry/graphics/Shaders.java @@ -87,6 +87,8 @@ public class Shaders{ @Override public void apply(){ + camDir.set(renderer.planets.cam.direction).rotate(Vec3.Y, renderer.planets.planet.getRotation()); + setUniformf("u_lightdir", lightDir); setUniformf("u_ambientColor", ambientColor.r, ambientColor.g, ambientColor.b); setUniformf("u_camdir", camDir); diff --git a/core/src/mindustry/graphics/g3d/PlanetRenderer.java b/core/src/mindustry/graphics/g3d/PlanetRenderer.java new file mode 100644 index 0000000000..cd87079594 --- /dev/null +++ b/core/src/mindustry/graphics/g3d/PlanetRenderer.java @@ -0,0 +1,351 @@ +package mindustry.graphics.g3d; + +import arc.*; +import arc.graphics.*; +import arc.graphics.g2d.*; +import arc.graphics.g3d.*; +import arc.graphics.gl.*; +import arc.math.*; +import arc.math.geom.*; +import arc.struct.*; +import arc.util.ArcAnnotate.*; +import arc.util.*; +import mindustry.content.*; +import mindustry.game.Objectives.*; +import mindustry.game.*; +import mindustry.gen.*; +import mindustry.graphics.*; +import mindustry.graphics.g3d.PlanetGrid.*; +import mindustry.type.*; +import mindustry.type.Sector.*; +import mindustry.ui.*; + +public class PlanetRenderer implements Disposable{ + public static final float outlineRad = 1.17f, camLength = 4f; + public static final Color + outlineColor = Pal.accent.cpy().a(1f), + hoverColor = Pal.accent.cpy().a(0.5f), + borderColor = Pal.accent.cpy().a(0.3f), + shadowColor = new Color(0, 0, 0, 0.7f); + + private static final Array points = new Array<>(); + + /** Camera direction relative to the planet. Length is determined by zoom. */ + public final Vec3 camPos = new Vec3(); + /** The sun/main planet of the solar system from which everything is rendered. */ + public final Planet solarSystem = Planets.sun; + /** Planet being looked at. */ + public Planet planet = Planets.starter; + /** Camera used for rendering. */ + public Camera3D cam = new Camera3D(); + + public float zoom = 1f, selectAlpha = 1f; + public @Nullable Sector selected, hovered; + + private final Mesh[] outlines = new Mesh[10]; + private final VertexBatch3D batch = new VertexBatch3D(10000, false, true, 0); + private final PlaneBatch3D projector = new PlaneBatch3D(); + private final Mat3D mat = new Mat3D(); + private final FrameBuffer buffer = new FrameBuffer(2, 2, true); + + private final Bloom bloom = new Bloom(Core.graphics.getWidth()/4, Core.graphics.getHeight()/4, true, false){{ + setThreshold(0.8f); + blurPasses = 6; + }}; + private final Mesh atmosphere = MeshBuilder.buildHex(Color.white, 2, false, 1.5f); + + //seed: 8kmfuix03fw + private final CubemapMesh skybox = new CubemapMesh(new Cubemap("cubemaps/stars/")); + + public PlanetRenderer(){ + camPos.set(0, 0f, camLength); + projector.setScaling(1f / 150f); + cam.fov = 60f; + } + + /** Render the entire planet scene to the screen. */ + public void render(){ + Draw.flush(); + Gl.clear(Gl.depthBufferBit); + Gl.enable(Gl.depthTest); + Gl.depthMask(true); + + Gl.enable(Gl.cullFace); + Gl.cullFace(Gl.back); + + //lock to up vector so it doesn't get confusing + cam.up.set(Vec3.Y); + + cam.resize(Core.graphics.getWidth(), Core.graphics.getHeight()); + camPos.setLength(planet.radius * camLength + (zoom-1f) * planet.radius * 2); + cam.position.set(planet.position).add(camPos); + cam.lookAt(planet.position); + cam.update(); + + projector.proj(cam.combined); + batch.proj(cam.combined); + + beginBloom(); + + skybox.render(cam.combined); + + renderPlanet(solarSystem); + + endBloom(); + + Gl.enable(Gl.blend); + + //TODO perhaps draw this somewhere else + if(hovered != null){ + Draw.batch(projector, () -> { + setPlane(hovered); + Draw.color(Color.white, Pal.accent, Mathf.absin(5f, 1f)); + + TextureRegion icon = hovered.locked() ? Icon.lock.getRegion() : hovered.is(SectorAttribute.naval) ? Liquids.water.icon(Cicon.large) : null; + + if(icon != null){ + Draw.rect(icon, 0, 0); + } + + Draw.reset(); + }); + } + + Gl.disable(Gl.cullFace); + Gl.disable(Gl.depthTest); + + cam.update(); + } + + private void beginBloom(){ + bloom.resize(Core.graphics.getWidth() / 4, Core.graphics.getHeight() / 4); + bloom.capture(); + } + + private void endBloom(){ + bloom.render(); + } + + private void renderPlanet(Planet planet){ + //render planet at offsetted position in the world + planet.mesh.render(cam.combined, planet.getTransform(mat)); + + renderOrbit(planet); + + if(planet.isLandable() && planet == this.planet){ + renderSectors(planet); + } + + if(planet.parent != null && planet.hasAtmosphere && Core.settings.getBool("atmosphere")){ + Blending.additive.apply(); + + Shaders.atmosphere.camera = cam; + Shaders.atmosphere.planet = planet; + Shaders.atmosphere.bind(); + Shaders.atmosphere.apply(); + + atmosphere.render(Shaders.atmosphere, Gl.triangles); + + Blending.normal.apply(); + } + + for(Planet child : planet.children){ + renderPlanet(child); + } + } + + private void renderOrbit(Planet planet){ + if(planet.parent == null) return; + + Vec3 center = planet.parent.position; + float radius = planet.orbitRadius; + int points = (int)(radius * 50); + Angles.circleVectors(points, radius, (cx, cy) -> batch.vertex(Tmp.v32.set(center).add(cx, 0, cy), Pal.gray)); + batch.flush(Gl.lineLoop); + } + + private void renderSectors(Planet planet){ + //apply transformed position + batch.proj().mul(planet.getTransform(mat)); + + for(Sector sec : planet.sectors){ + + if(selectAlpha > 0.01f){ + if(sec.unlocked()){ + Color color = + sec.hasBase() ? Team.sharded.color : + sec.preset != null ? Team.derelict.color : + sec.hasEnemyBase() ? Team.crux.color : + null; + + if(color != null){ + drawSelection(sec, Tmp.c1.set(color).mul(0.8f).a(selectAlpha), 0.026f, -0.001f); + } + }else{ + draw(sec, Tmp.c1.set(shadowColor).mul(1, 1, 1, selectAlpha), -0.001f); + } + } + } + + if(hovered != null){ + draw(hovered, hoverColor, -0.001f); + drawBorders(hovered, borderColor); + } + + if(selected != null){ + drawSelection(selected); + drawBorders(selected, borderColor); + } + + batch.flush(Gl.triangles); + + //render arcs + if(selected != null && selected.preset != null){ + for(Objective o : selected.preset.requirements){ + if(o instanceof SectorObjective){ + SectorPreset preset = ((SectorObjective)o).preset; + drawArc(planet, selected.tile.v, preset.sector.tile.v); + } + } + } + + //render sector grid + Mesh mesh = outline(planet.grid.size); + Shader shader = Shaders.planetGrid; + Vec3 tile = planet.intersect(cam.getMouseRay(), outlineRad); + Shaders.planetGrid.mouse.lerp(tile == null ? Vec3.Zero : tile.sub(planet.position).rotate(Vec3.Y, planet.getRotation()), 0.2f); + + shader.bind(); + shader.setUniformMatrix4("u_proj", cam.combined.val); + shader.setUniformMatrix4("u_trans", planet.getTransform(mat).val); + shader.apply(); + mesh.render(shader, Gl.lines); + } + + private void drawArc(Planet planet, Vec3 a, Vec3 b){ + Vec3 avg = Tmp.v31.set(a).add(b).scl(0.5f); + avg.setLength(planet.radius*2f); + + points.clear(); + points.addAll(Tmp.v33.set(a).setLength(outlineRad), Tmp.v31, Tmp.v34.set(b).setLength(outlineRad)); + Tmp.bz3.set(points); + float points = 25; + + for(int i = 0; i < points + 1; i++){ + float f = i / points; + Tmp.c1.set(Pal.accent).lerp(Color.clear, (f+Time.globalTime()/80f)%1f); + batch.color(Tmp.c1); + batch.vertex(Tmp.bz3.valueAt(Tmp.v32, f)); + + } + batch.flush(Gl.lineStrip); + } + + private void drawBorders(Sector sector, Color base){ + Color color = Tmp.c1.set(base).a(base.a + 0.3f + Mathf.absin(Time.globalTime(), 5f, 0.3f)); + + float r1 = 1f; + float r2 = outlineRad + 0.001f; + + for(int i = 0; i < sector.tile.corners.length; i++){ + Corner c = sector.tile.corners[i], next = sector.tile.corners[(i+1) % sector.tile.corners.length]; + + Tmp.v31.set(c.v).setLength(r2); + Tmp.v32.set(next.v).setLength(r2); + Tmp.v33.set(c.v).setLength(r1); + + batch.tri2(Tmp.v31, Tmp.v32, Tmp.v33, color); + + Tmp.v31.set(next.v).setLength(r2); + Tmp.v32.set(next.v).setLength(r1); + Tmp.v33.set(c.v).setLength(r1); + + batch.tri2(Tmp.v31, Tmp.v32, Tmp.v33, color); + } + + if(batch.getNumVertices() >= batch.getMaxVertices() - 6 * 6){ + batch.flush(Gl.triangles); + } + } + + private void setPlane(Sector sector){ + float rotation = -planet.getRotation(); + float length = 0.01f; + + projector.setPlane( + //origin on sector position + Tmp.v33.set(sector.tile.v).setLength(outlineRad + length).rotate(Vec3.Y, rotation).add(planet.position), + //face up + sector.plane.project(Tmp.v32.set(sector.tile.v).add(Vec3.Y)).sub(sector.tile.v).rotate(Vec3.Y, rotation).nor(), + //right vector + Tmp.v31.set(Tmp.v32).rotate(Vec3.Y, -rotation).add(sector.tile.v).rotate(sector.tile.v, 90).sub(sector.tile.v).rotate(Vec3.Y, rotation).nor() + ); + } + + private void draw(Sector sector, Color color, float offset){ + float rr = outlineRad + offset; + for(int i = 0; i < sector.tile.corners.length; i++){ + Corner c = sector.tile.corners[i], next = sector.tile.corners[(i+1) % sector.tile.corners.length]; + batch.tri(Tmp.v31.set(c.v).setLength(rr), Tmp.v32.set(next.v).setLength(rr), Tmp.v33.set(sector.tile.v).setLength(rr), color); + } + } + + private void drawSelection(Sector sector){ + drawSelection(sector, Pal.accent, 0.04f, 0.001f); + } + + private void drawSelection(Sector sector, Color color, float stroke, float length){ + float arad = outlineRad + length; + + for(int i = 0; i < sector.tile.corners.length; i++){ + Corner next = sector.tile.corners[(i + 1) % sector.tile.corners.length]; + Corner curr = sector.tile.corners[i]; + + next.v.scl(arad); + curr.v.scl(arad); + sector.tile.v.scl(arad); + + Tmp.v31.set(curr.v).sub(sector.tile.v).setLength(curr.v.dst(sector.tile.v) - stroke).add(sector.tile.v); + Tmp.v32.set(next.v).sub(sector.tile.v).setLength(next.v.dst(sector.tile.v) - stroke).add(sector.tile.v); + + batch.tri(curr.v, next.v, Tmp.v31, color); + batch.tri(Tmp.v31, next.v, Tmp.v32, color); + + sector.tile.v.scl(1f / arad); + next.v.scl(1f / arad); + curr.v.scl(1f /arad); + } + } + + private Mesh outline(int size){ + if(outlines[size] == null){ + outlines[size] = MeshBuilder.buildHex(new HexMesher(){ + @Override + public float getHeight(Vec3 position){ + return 0; + } + + @Override + public Color getColor(Vec3 position){ + return outlineColor; + } + }, size, true, outlineRad, 0.2f); + } + return outlines[size]; + } + + @Override + public void dispose(){ + skybox.dispose(); + batch.dispose(); + projector.dispose(); + atmosphere.dispose(); + buffer.dispose(); + bloom.dispose(); + for(Mesh m : outlines){ + if(m != null){ + m.dispose(); + } + } + } +} diff --git a/core/src/mindustry/ui/dialogs/PlanetDialog.java b/core/src/mindustry/ui/dialogs/PlanetDialog.java index 621e3fcb93..dbc8666cbc 100644 --- a/core/src/mindustry/ui/dialogs/PlanetDialog.java +++ b/core/src/mindustry/ui/dialogs/PlanetDialog.java @@ -3,27 +3,18 @@ package mindustry.ui.dialogs; import arc.*; import arc.graphics.*; import arc.graphics.g2d.*; -import arc.graphics.g3d.*; import arc.graphics.gl.*; import arc.input.*; import arc.math.*; import arc.math.geom.*; import arc.scene.event.*; import arc.scene.ui.*; -import arc.scene.ui.TextButton.*; import arc.scene.ui.layout.*; -import arc.struct.*; import arc.util.*; -import arc.util.ArcAnnotate.*; -import mindustry.content.*; import mindustry.ctype.*; -import mindustry.game.EventType.*; -import mindustry.game.Objectives.*; -import mindustry.game.*; import mindustry.gen.*; import mindustry.graphics.*; import mindustry.graphics.g3d.*; -import mindustry.graphics.g3d.PlanetGrid.*; import mindustry.type.*; import mindustry.type.Sector.*; import mindustry.ui.*; @@ -31,61 +22,15 @@ import mindustry.ui.*; import static mindustry.Vars.*; public class PlanetDialog extends BaseDialog{ - private static final Color - outlineColor = Pal.accent.cpy().a(1f), - hoverColor = Pal.accent.cpy().a(0.5f), - borderColor = Pal.accent.cpy().a(0.3f), - shadowColor = new Color(0, 0, 0, 0.7f); - private static final float camLength = 4f; - private static final float outlineRad = 1.16f; - private static final Array points = new Array<>(); - - //the base planet that's being rendered - private final Planet solarSystem = Planets.sun; - - private final Mesh[] outlines = new Mesh[10]; - private final VertexBatch3D batch = new VertexBatch3D(10000, false, true, 0); - private final PlaneBatch3D projector = new PlaneBatch3D(); - private final Mat3D mat = new Mat3D(); - private final Vec3 camRelative = new Vec3(); - private final ResourcesDialog resources = new ResourcesDialog(); private final FrameBuffer buffer = new FrameBuffer(2, 2, true); + private final PlanetRenderer planets = renderer.planets; - private float zoom = 1f, smoothZoom = 1f, selectAlpha = 1f; - private Bloom bloom = new Bloom(Core.graphics.getWidth()/4, Core.graphics.getHeight()/4, true, false){{ - setThreshold(0.8f); - blurPasses = 6; - }}; - private Planet planet = Planets.starter; - private @Nullable Sector selected, hovered; + private float zoom = 1f; private Table stable; - private Mesh atmosphere = MeshBuilder.buildHex(Color.white, 2, false, 1.5f); - - //seed: 8kmfuix03fw - private CubemapMesh skybox = new CubemapMesh(new Cubemap("cubemaps/stars/")); public PlanetDialog(){ super("", Styles.fullDialog); - Events.on(DisposeEvent.class, () -> { - skybox.dispose(); - batch.dispose(); - projector.dispose(); - atmosphere.dispose(); - for(Mesh m : outlines){ - if(m != null){ - m.dispose(); - } - } - }); - - Events.on(ResizeEvent.class, e -> { - bloom.resize(Core.graphics.getWidth() / 4, Core.graphics.getHeight() / 4); - }); - - TextButtonStyle style = Styles.cleart; - float bmargin = 6f; - getCell(buttons).padBottom(-4); buttons.background(Styles.black).defaults().growX().height(64f).pad(0); @@ -95,54 +40,34 @@ public class PlanetDialog extends BaseDialog{ } }); - //TODO - //buttons.button("$back", Icon.left, style, this::hide).margin(bmargin); - //buttons.button("Research", Icon.tree, style, () -> ui.tech.show()).margin(bmargin); - //buttons.button("Database", Icon.book, style, () -> ui.database.show()).margin(bmargin); - //buttons.button("Resources", Icon.file, style, resources::show).margin(bmargin); - - cam3.fov = 60f; - - camRelative.set(0, 0f, camLength); - projector.setScaling(1f / 150f); - dragged((cx, cy) -> { - float upV = camRelative.angle(Vec3.Y); + Vec3 pos = planets.camPos; + + float upV = pos.angle(Vec3.Y); float xscale = 9f, yscale = 10f; float margin = 1; //scale X speed depending on polar coordinate float speed = 1f - Math.abs(upV - 90) / 90f; - camRelative.rotate(cam3.up, cx / xscale * speed); + pos.rotate(planets.cam.up, cx / xscale * speed); //prevent user from scrolling all the way up and glitching it out float amount = cy / yscale; amount = Mathf.clamp(upV + amount, margin, 180f - margin) - upV; - camRelative.rotate(Tmp.v31.set(cam3.up).rotate(cam3.direction, 90), amount); + pos.rotate(Tmp.v31.set(planets.cam.up).rotate(planets.cam.direction, 90), amount); }); scrolled(value -> { zoom = Mathf.clamp(zoom + value / 10f, 0.5f, 2f); }); - update(() -> { - if(planet.isLandable()){ - hovered = planet.getSector(cam3.getMouseRay(), outlineRad); - }else{ - hovered = selected = null; - } - - smoothZoom = Mathf.lerpDelta(smoothZoom, zoom, 0.4f); - selectAlpha = Mathf.lerpDelta(selectAlpha, Mathf.num(smoothZoom < 1.9f), 0.1f); - }); - addListener(new ElementGestureListener(){ @Override public void tap(InputEvent event, float x, float y, int count, KeyCode button){ - selected = hovered != null && hovered.locked() ? null : hovered; - if(selected != null){ + planets.selected = planets.hovered != null && planets.hovered.locked() ? null : planets.hovered; + if(planets.selected != null){ updateSelected(); } } @@ -162,12 +87,12 @@ public class PlanetDialog extends BaseDialog{ } public void show(Sector selected, int range){ - this.selected = null; - this.hovered = null; + planets.selected = null; + planets.hovered = null; //update view to sector - camRelative.set(Tmp.v33.set(selected.tile.v).rotate(Vec3.Y, -selected.planet.getRotation())); - zoom = smoothZoom = 1f; + planets.camPos.set(Tmp.v33.set(selected.tile.v).rotate(Vec3.Y, -selected.planet.getRotation())); + zoom = planets.zoom = 1f; show(); //TODO @@ -177,7 +102,7 @@ public class PlanetDialog extends BaseDialog{ cont.clear(); titleTable.remove(); - cont.rect((x, y, w, h) -> render()).grow(); + cont.rect((x, y, w, h) -> planets.render()).grow(); } @Override @@ -199,249 +124,59 @@ public class PlanetDialog extends BaseDialog{ } } - private void render(){ - Draw.flush(); - Gl.clear(Gl.depthBufferBit); - Gl.enable(Gl.depthTest); - Gl.depthMask(true); + @Override + public void act(float delta){ + super.act(delta); - Gl.enable(Gl.cullFace); - Gl.cullFace(Gl.back); - - //lock to up vector so it doesn't get confusing - cam3.up.set(Vec3.Y); - - cam3.resize(Core.graphics.getWidth(), Core.graphics.getHeight()); - camRelative.setLength(planet.radius * camLength + (smoothZoom-1f) * planet.radius * 2); - cam3.position.set(planet.position).add(camRelative); - cam3.lookAt(planet.position); - cam3.update(); - - //TODO hacky - Shaders.planet.camDir.set(cam3.direction).rotate(Vec3.Y, planet.getRotation()); - - projector.proj(cam3.combined); - batch.proj(cam3.combined); - - beginBloom(); - - skybox.render(cam3.combined); - - renderPlanet(solarSystem); - - endBloom(); - - Gl.enable(Gl.blend); - - if(hovered != null){ - Draw.batch(projector, () -> { - setPlane(hovered); - Draw.color(Color.white, Pal.accent, Mathf.absin(5f, 1f)); - - TextureRegion icon = hovered.locked() ? Icon.lock.getRegion() : hovered.is(SectorAttribute.naval) ? Liquids.water.icon(Cicon.large) : null; - - if(icon != null){ - Draw.rect(icon, 0, 0); - } - - Draw.reset(); - }); - } - - Gl.disable(Gl.cullFace); - Gl.disable(Gl.depthTest); - - if(selected != null){ + if(planets.selected != null){ addChild(stable); - Vec3 pos = cam3.project(Tmp.v31.set(selected.tile.v).setLength(outlineRad).rotate(Vec3.Y, -planet.getRotation()).add(planet.position)); + Vec3 pos = planets.cam.project(Tmp.v31.set(planets.selected.tile.v).setLength(PlanetRenderer.outlineRad).rotate(Vec3.Y, -planets.planet.getRotation()).add(planets.planet.position)); stable.setPosition(pos.x, pos.y, Align.center); stable.toFront(); }else{ stable.remove(); } - cam3.update(); - } - - private void beginBloom(){ - bloom.capture(); - } - - private void endBloom(){ - bloom.render(); - } - - private void renderPlanet(Planet planet){ - //render planet at offsetted position in the world - planet.mesh.render(cam3.combined, planet.getTransform(mat)); - - renderOrbit(planet); - - if(planet.isLandable() && planet == this.planet){ - renderSectors(planet); - } - - if(planet.parent != null && planet.hasAtmosphere && Core.settings.getBool("atmosphere")){ - Blending.additive.apply(); - - Shaders.atmosphere.camera = cam3; - Shaders.atmosphere.planet = planet; - Shaders.atmosphere.bind(); - Shaders.atmosphere.apply(); - - atmosphere.render(Shaders.atmosphere, Gl.triangles); - - Blending.normal.apply(); - } - - for(Planet child : planet.children){ - renderPlanet(child); - } - } - - private void renderOrbit(Planet planet){ - if(planet.parent == null) return; - - Vec3 center = planet.parent.position; - float radius = planet.orbitRadius; - int points = (int)(radius * 50); - Angles.circleVectors(points, radius, (cx, cy) -> batch.vertex(Tmp.v32.set(center).add(cx, 0, cy), Pal.gray)); - batch.flush(Gl.lineLoop); - } - - private void renderSectors(Planet planet){ - //apply transformed position - batch.proj().mul(planet.getTransform(mat)); - - for(Sector sec : planet.sectors){ - - if(selectAlpha > 0.01f){ - if(sec.unlocked()){ - Color color = - sec.hasBase() ? Team.sharded.color : - sec.preset != null ? Team.derelict.color : - sec.hasEnemyBase() ? Team.crux.color : - null; - - if(color != null){ - drawSelection(sec, Tmp.c1.set(color).mul(0.8f).a(selectAlpha), 0.026f, -0.001f); - } - }else{ - draw(sec, Tmp.c1.set(shadowColor).mul(1, 1, 1, selectAlpha), -0.001f); - } - } - } - - if(hovered != null){ - draw(hovered, hoverColor, -0.001f); - drawBorders(hovered, borderColor); - } - - if(selected != null){ - drawSelection(selected); - drawBorders(selected, borderColor); - } - - batch.flush(Gl.triangles); - - //render arcs - if(selected != null && selected.preset != null){ - for(Objective o : selected.preset.requirements){ - if(o instanceof SectorObjective){ - SectorPreset preset = ((SectorObjective)o).preset; - drawArc(planet, selected.tile.v, preset.sector.tile.v); - } - } - } - - //render sector grid - Mesh mesh = outline(planet.grid.size); - Shader shader = Shaders.planetGrid; - Vec3 tile = planet.intersect(cam3.getMouseRay(), outlineRad); - Shaders.planetGrid.mouse.lerp(tile == null ? Vec3.Zero : tile.sub(planet.position).rotate(Vec3.Y, planet.getRotation()), 0.2f); - - shader.bind(); - shader.setUniformMatrix4("u_proj", cam3.combined.val); - shader.setUniformMatrix4("u_trans", planet.getTransform(mat).val); - shader.apply(); - mesh.render(shader, Gl.lines); - } - - private void drawArc(Planet planet, Vec3 a, Vec3 b){ - Vec3 avg = Tmp.v31.set(a).add(b).scl(0.5f); - avg.setLength(planet.radius*2f); - - points.clear(); - points.addAll(Tmp.v33.set(a).setLength(outlineRad), Tmp.v31, Tmp.v34.set(b).setLength(outlineRad)); - Tmp.bz3.set(points); - float points = 25; - - for(int i = 0; i < points + 1; i++){ - float f = i / points; - Tmp.c1.set(Pal.accent).lerp(Color.clear, (f+Time.globalTime()/80f)%1f); - batch.color(Tmp.c1); - batch.vertex(Tmp.bz3.valueAt(Tmp.v32, f)); - - } - batch.flush(Gl.lineStrip); - } - - private void drawBorders(Sector sector, Color base){ - Color color = Tmp.c1.set(base).a(base.a + 0.3f + Mathf.absin(Time.globalTime(), 5f, 0.3f)); - - float r1 = 1f; - float r2 = outlineRad + 0.001f; - - for(int i = 0; i < sector.tile.corners.length; i++){ - Corner c = sector.tile.corners[i], next = sector.tile.corners[(i+1) % sector.tile.corners.length]; - - Tmp.v31.set(c.v).setLength(r2); - Tmp.v32.set(next.v).setLength(r2); - Tmp.v33.set(c.v).setLength(r1); - - batch.tri2(Tmp.v31, Tmp.v32, Tmp.v33, color); - - Tmp.v31.set(next.v).setLength(r2); - Tmp.v32.set(next.v).setLength(r1); - Tmp.v33.set(c.v).setLength(r1); - - batch.tri2(Tmp.v31, Tmp.v32, Tmp.v33, color); - } - - if(batch.getNumVertices() >= batch.getMaxVertices() - 6 * 6){ - batch.flush(Gl.triangles); - } + if(planets.planet.isLandable()){ + planets.hovered = planets.planet.getSector(planets.cam.getMouseRay(), PlanetRenderer.outlineRad); + }else{ + planets.hovered = planets.selected = null; + } + + planets.zoom = Mathf.lerpDelta(planets.zoom, zoom, 0.4f); + planets.selectAlpha = Mathf.lerpDelta(planets.selectAlpha, Mathf.num(planets.zoom < 1.9f), 0.1f); } + //TODO add strings to bundle after prototyping is done private void updateSelected(){ + Sector sector = planets.selected; + float x = stable.getX(Align.center), y = stable.getY(Align.center); stable.clear(); stable.background(Styles.black6); - //TODO add strings to bundle after prototyping is done - - stable.add("[accent]" + (selected.preset == null ? selected.id : selected.preset.localizedName)).row(); + stable.add("[accent]" + (sector.preset == null ? sector.id : sector.preset.localizedName)).row(); stable.image().color(Pal.accent).fillX().height(3f).pad(3f).row(); - stable.add(selected.save != null ? selected.save.getPlayTime() : "[lightgray]Unexplored").row(); + stable.add(sector.save != null ? sector.save.getPlayTime() : "[lightgray]Unexplored").row(); stable.add("Resources:").row(); stable.table(t -> { t.left(); int idx = 0; int max = 5; - for(UnlockableContent c : selected.data.resources){ + for(UnlockableContent c : sector.data.resources){ t.image(c.icon(Cicon.small)).padRight(3); if(++idx % max == 0) t.row(); } }).fillX().row(); //production - if(selected.hasBase() && selected.save.meta.hasProduction){ + if(sector.hasBase() && sector.save.meta.hasProduction){ stable.add("Production:").row(); stable.table(t -> { t.left(); - selected.save.meta.secinfo.exportRates().each(entry -> { + sector.save.meta.secinfo.exportRates().each(entry -> { int total = (int)(entry.value * turnDuration / 60f); if(total > 1){ t.image(entry.key.icon(Cicon.small)).padRight(3); @@ -453,7 +188,7 @@ public class PlanetDialog extends BaseDialog{ } //stored resources - if(selected.hasBase() && selected.save.meta.secinfo.coreItems.size > 0){ + if(sector.hasBase() && sector.save.meta.secinfo.coreItems.size > 0){ stable.add("Stored:").row(); stable.table(t -> { t.left(); @@ -461,7 +196,7 @@ public class PlanetDialog extends BaseDialog{ t.table(res -> { int i = 0; for(Item item : content.items()){ - int amount = selected.save.meta.secinfo.coreItems.get(item); + int amount = sector.save.meta.secinfo.coreItems.get(item); if(amount > 0){ res.image(item.icon(Cicon.small)).padRight(3); res.add(ui.formatAmount(amount)).color(Color.lightGray); @@ -477,107 +212,39 @@ public class PlanetDialog extends BaseDialog{ } //display how many turns this sector has been attacked - if(selected.getTurnsPassed() > 0 && selected.hasBase()){ + if(sector.getTurnsPassed() > 0 && sector.hasBase()){ stable.row(); - stable.add("[scarlet]" + Iconc.warning + " " + selected.getTurnsPassed() + "x attacks"); + stable.add("[scarlet]" + Iconc.warning + " " + sector.getTurnsPassed() + "x attacks"); } stable.row(); stable.button("Launch", Styles.transt, () -> { - if(selected != null){ - if(selected.is(SectorAttribute.naval)){ - ui.showInfo("You need a naval loadout to launch here."); - return; - } - control.playSector(selected); - hide(); + if(sector.is(SectorAttribute.naval)){ + ui.showInfo("You need a naval loadout to launch here."); + return; } + control.playSector(sector); + hide(); }).growX().padTop(2f).height(50f).minWidth(170f); stable.pack(); stable.setPosition(x, y, Align.center); stable.update(() -> { - if(selected != null){ + if(planets.selected != null){ //fade out UI when not facing selected sector - Tmp.v31.set(selected.tile.v).rotate(Vec3.Y, -planet.getRotation()).scl(-1f).nor(); - float dot = cam3.direction.dot(Tmp.v31); + Tmp.v31.set(planets.selected.tile.v).rotate(Vec3.Y, -planets.planet.getRotation()).scl(-1f).nor(); + float dot = planets.cam.direction.dot(Tmp.v31); stable.getColor().a = Math.max(dot, 0f)*2f; if(dot*2f <= -0.1f){ stable.remove(); - selected = null; + planets.selected = null; } } }); stable.act(0f); } - - private void setPlane(Sector sector){ - float rotation = -planet.getRotation(); - float length = 0.01f; - - projector.setPlane( - //origin on sector position - Tmp.v33.set(sector.tile.v).setLength(outlineRad + length).rotate(Vec3.Y, rotation).add(planet.position), - //face up - sector.plane.project(Tmp.v32.set(sector.tile.v).add(Vec3.Y)).sub(sector.tile.v).rotate(Vec3.Y, rotation).nor(), - //right vector - Tmp.v31.set(Tmp.v32).rotate(Vec3.Y, -rotation).add(sector.tile.v).rotate(sector.tile.v, 90).sub(sector.tile.v).rotate(Vec3.Y, rotation).nor() - ); - } - - private void draw(Sector sector, Color color, float offset){ - float rr = outlineRad + offset; - for(int i = 0; i < sector.tile.corners.length; i++){ - Corner c = sector.tile.corners[i], next = sector.tile.corners[(i+1) % sector.tile.corners.length]; - batch.tri(Tmp.v31.set(c.v).setLength(rr), Tmp.v32.set(next.v).setLength(rr), Tmp.v33.set(sector.tile.v).setLength(rr), color); - } - } - - private void drawSelection(Sector sector){ - drawSelection(sector, Pal.accent, 0.04f, 0.001f); - } - - private void drawSelection(Sector sector, Color color, float stroke, float length){ - float arad = outlineRad + length; - - for(int i = 0; i < sector.tile.corners.length; i++){ - Corner next = sector.tile.corners[(i + 1) % sector.tile.corners.length]; - Corner curr = sector.tile.corners[i]; - - next.v.scl(arad); - curr.v.scl(arad); - sector.tile.v.scl(arad); - - Tmp.v31.set(curr.v).sub(sector.tile.v).setLength(curr.v.dst(sector.tile.v) - stroke).add(sector.tile.v); - Tmp.v32.set(next.v).sub(sector.tile.v).setLength(next.v.dst(sector.tile.v) - stroke).add(sector.tile.v); - - batch.tri(curr.v, next.v, Tmp.v31, color); - batch.tri(Tmp.v31, next.v, Tmp.v32, color); - - sector.tile.v.scl(1f / arad); - next.v.scl(1f / arad); - curr.v.scl(1f /arad); - } - } - - private Mesh outline(int size){ - if(outlines[size] == null){ - outlines[size] = MeshBuilder.buildHex(new HexMesher(){ - @Override - public float getHeight(Vec3 position){ - return 0; - } - - @Override - public Color getColor(Vec3 position){ - return outlineColor; - } - }, size, true, outlineRad, 0.2f); - } - return outlines[size]; - } }