From 9804ed1e825cc00f835fcd0c4b621c8baa57b5a9 Mon Sep 17 00:00:00 2001 From: Martin Steiger Date: Thu, 29 Oct 2015 20:49:05 +0100 Subject: [PATCH] Add module-dependent overlays --- .../viewer/overlay/GraphNodeOverlay.java | 181 +++++++++++++ .../world/viewer/overlay/LakeOverlay.java | 63 +++++ .../viewer/overlay/PathfinderOverlay.java | 253 ++++++++++++++++++ .../viewer/overlay/RiverModelOverlay.java | 61 +++++ .../world/viewer/overlay/SiteOverlay.java | 75 ++++++ .../viewer/overlay/SpawningPointOverlay.java | 97 +++++++ 6 files changed, 730 insertions(+) create mode 100644 src/main/java/org/terasology/world/viewer/overlay/GraphNodeOverlay.java create mode 100644 src/main/java/org/terasology/world/viewer/overlay/LakeOverlay.java create mode 100644 src/main/java/org/terasology/world/viewer/overlay/PathfinderOverlay.java create mode 100644 src/main/java/org/terasology/world/viewer/overlay/RiverModelOverlay.java create mode 100644 src/main/java/org/terasology/world/viewer/overlay/SiteOverlay.java create mode 100644 src/main/java/org/terasology/world/viewer/overlay/SpawningPointOverlay.java diff --git a/src/main/java/org/terasology/world/viewer/overlay/GraphNodeOverlay.java b/src/main/java/org/terasology/world/viewer/overlay/GraphNodeOverlay.java new file mode 100644 index 0000000..23bc89c --- /dev/null +++ b/src/main/java/org/terasology/world/viewer/overlay/GraphNodeOverlay.java @@ -0,0 +1,181 @@ +/* + * Copyright 2015 MovingBlocks + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.terasology.world.viewer.overlay; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Shape; +import java.awt.geom.Area; +import java.awt.geom.Ellipse2D; +import java.awt.geom.Path2D; +import java.util.Iterator; +import java.util.function.Function; + +import org.terasology.math.geom.BaseVector2f; +import org.terasology.math.geom.ImmutableVector2f; +import org.terasology.math.geom.ImmutableVector2i; +import org.terasology.math.geom.Rect2i; +import org.terasology.math.geom.Vector2f; +import org.terasology.polyworld.graph.Corner; +import org.terasology.polyworld.graph.GraphFacet; +import org.terasology.polyworld.graph.Triangle; +import org.terasology.world.generation.Region; +import org.terasology.world.viewer.picker.CirclePickerClosest; + +/** + * Shows the triangle under the mouse cursor. + */ +public class GraphNodeOverlay extends AbstractOverlay implements WorldOverlay { + + private final Function regions; + + private Color fillColor = new Color(192, 32, 32, 128); + private Color frameColor = new Color(192, 32, 32, 192); + private BasicStroke stroke = new BasicStroke(0.2f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND); + + public enum Mode { + CORNER, + TRIANGLE, + REGION + } + + private Mode mode = Mode.CORNER; + + public GraphNodeOverlay(Function regionFunc) { + regions = regionFunc; + } + + @Override + public void render(Graphics2D g, Rect2i area, ImmutableVector2i cursor) { + if (cursor == null) { + return; + } + + Region r = regions.apply(cursor); + GraphFacet graphs = r.getFacet(GraphFacet.class); + g.setStroke(stroke); + if (graphs != null) { + Triangle t = graphs.getWorldTriangle(cursor.getX(), cursor.getY()); + Shape path = null; + + switch (mode) { + case CORNER: + Vector2f cursorf = new Vector2f(cursor.getX(), cursor.getY()); + CirclePickerClosest picker = new CirclePickerClosest<>(cursorf, c -> 3); + + picker.offer(t.getCorner1().getLocation(), t.getCorner1()); + picker.offer(t.getCorner2().getLocation(), t.getCorner2()); + + if (picker.getClosest() != null) { + Corner c = picker.getClosest(); + path = createCornerPath(c); + } else { + path = new Path2D.Float(); + } + break; + + case TRIANGLE: + path = createTrianglePath(t); + break; + + case REGION: + path = createRegionPath(t.getRegion()); + break; + } + + g.setColor(fillColor); + g.fill(path); + g.setColor(frameColor); + g.draw(path); + } + } + + public Mode getMode() { + return mode; + } + + public void setMode(Mode mode) { + this.mode = mode; + } + + private Shape createCornerPath(Corner c) { + Path2D path = new Path2D.Float(); + + float radCenter = 3; + float radAdj = 2; + + float cx = c.getLocation().getX(); + float cy = c.getLocation().getY(); + + for (Corner adj : c.getAdjacent()) { + float adx = adj.getLocation().getX(); + float ady = adj.getLocation().getY(); + path.moveTo(cx, cy); + path.lineTo(adx, ady); + } + + Area result = new Area(new BasicStroke(1f).createStrokedShape(path)); + result.add(new Area(new Ellipse2D.Float(cx - radCenter, cy - radCenter, radCenter * 2, radCenter * 2))); + + for (Corner adj : c.getAdjacent()) { + float adx = adj.getLocation().getX(); + float ady = adj.getLocation().getY(); + result.add(new Area(new Ellipse2D.Float(adx - radAdj, ady - radAdj, radAdj * 2, radAdj * 2))); + } + + return result; + } + + private Path2D createTrianglePath(Triangle t) { + BaseVector2f p0 = t.getRegion().getCenter(); + BaseVector2f p1 = t.getCorner1().getLocation(); + BaseVector2f p2 = t.getCorner2().getLocation(); + + Path2D path = new Path2D.Float(); + + path.moveTo(p0.getX(), p0.getY()); + path.lineTo(p1.getX(), p1.getY()); + path.lineTo(p2.getX(), p2.getY()); + path.closePath(); + + return path; + } + + private Path2D createRegionPath(org.terasology.polyworld.graph.Region region) { + + Path2D path = new Path2D.Float(); + + Iterator it = region.getCorners().iterator(); + + if (!it.hasNext()) { + return path; + } + + ImmutableVector2f p = it.next().getLocation(); + path.moveTo(p.getX(), p.getY()); + + while (it.hasNext()) { + p = it.next().getLocation(); + path.lineTo(p.getX(), p.getY()); + } + + path.closePath(); + return path; + } + +} diff --git a/src/main/java/org/terasology/world/viewer/overlay/LakeOverlay.java b/src/main/java/org/terasology/world/viewer/overlay/LakeOverlay.java new file mode 100644 index 0000000..bc6a398 --- /dev/null +++ b/src/main/java/org/terasology/world/viewer/overlay/LakeOverlay.java @@ -0,0 +1,63 @@ +/* + * Copyright 2015 MovingBlocks + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.terasology.world.viewer.overlay; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Polygon; +import java.util.function.Function; + +import org.terasology.cities.lakes.Lake; +import org.terasology.cities.lakes.LakeFacet; +import org.terasology.math.geom.ImmutableVector2i; +import org.terasology.math.geom.Rect2i; +import org.terasology.world.generation.Region; + +public class LakeOverlay extends AbstractOverlay implements WorldOverlay { + + private Function regions; + + public LakeOverlay(Function regionFunc) { + regions = regionFunc; + } + + @Override + public void render(Graphics2D g, Rect2i area, ImmutableVector2i cursor) { + if (cursor == null) { + return; + } + + Color fillColor = new Color(64, 64, 255, 128); + Color frameColor = new Color(64, 64, 255, 224); + + g.setStroke(new BasicStroke(1f, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_ROUND)); + Region r = regions.apply(cursor); + LakeFacet lakeFacet = r.getFacet(LakeFacet.class); + for (Lake lake : lakeFacet.getLakes()) { + if (lake.getContour().getPolygon().contains(cursor.getX(), cursor.getY())) { + Polygon poly = lake.getContour().getPolygon(); + g.translate(0.5, 0.5); + g.setColor(fillColor); + g.fill(poly); + g.setColor(frameColor); + g.draw(poly); + g.translate(-0.5, -0.5); + } + } + } +} diff --git a/src/main/java/org/terasology/world/viewer/overlay/PathfinderOverlay.java b/src/main/java/org/terasology/world/viewer/overlay/PathfinderOverlay.java new file mode 100644 index 0000000..4a10e13 --- /dev/null +++ b/src/main/java/org/terasology/world/viewer/overlay/PathfinderOverlay.java @@ -0,0 +1,253 @@ +/* + * Copyright 2015 MovingBlocks + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.terasology.world.viewer.overlay; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Shape; +import java.awt.geom.Area; +import java.awt.geom.Ellipse2D; +import java.awt.geom.Path2D; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.Optional; +import java.util.function.Function; + +import org.terasology.math.geom.BaseVector2f; +import org.terasology.math.geom.ImmutableVector2f; +import org.terasology.math.geom.ImmutableVector2i; +import org.terasology.math.geom.Rect2i; +import org.terasology.math.geom.Vector2f; +import org.terasology.pathfinding.GeneralPathFinder; +import org.terasology.pathfinding.GeneralPathFinder.Path; +import org.terasology.polyworld.graph.Corner; +import org.terasology.polyworld.graph.Edge; +import org.terasology.polyworld.graph.Graph; +import org.terasology.polyworld.graph.GraphFacet; +import org.terasology.polyworld.graph.Triangle; +import org.terasology.world.generation.Region; +import org.terasology.world.viewer.picker.CirclePickerClosest; + +/** + * Shows the triangle under the mouse cursor. + */ +public class PathfinderOverlay extends AbstractOverlay implements WorldOverlay { + + private final Function regions; + + private Color fillColor = new Color(192, 32, 32, 128); + private Color frameColor = new Color(192, 32, 32, 255); + private BasicStroke stroke = new BasicStroke(0.2f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND); + + public enum Mode { + CORNER, + TRIANGLE, + REGION, + PATH + } + + private Mode mode = Mode.PATH; + + public PathfinderOverlay(Function regionFunc) { + regions = regionFunc; + } + + @Override + public void render(Graphics2D g, Rect2i area, ImmutableVector2i cursor) { + if (cursor == null) { + return; + } + + Region r = regions.apply(cursor); + GraphFacet graphs = r.getFacet(GraphFacet.class); + g.setStroke(stroke); + Vector2f cursorf = new Vector2f(cursor.getX(), cursor.getY()); + + if (graphs != null) { + Triangle t = graphs.getWorldTriangle(cursor.getX(), cursor.getY()); + Shape path = null; + + switch (mode) { + case PATH: { + Graph gr = graphs.getWorld(cursor.getX(), cursor.getY()); + Corner other = gr.getCorners().get(gr.getCorners().size() / 2); + CirclePickerClosest picker = new CirclePickerClosest<>(cursorf, c -> 13); + + picker.offer(t.getCorner1().getLocation(), t.getCorner1()); + picker.offer(t.getCorner2().getLocation(), t.getCorner2()); + + if (picker.getClosest() != null) { + Corner c = picker.getClosest(); +Collection> edges = new ArrayList<>(); + for (Edge e : gr.getEdges()) { + edges.add(new GeneralPathFinder.DefaultEdge(e.getCorner0(), e.getCorner1(), +e.getCorner0().getLocation().distance(e.getCorner1().getLocation()) + )); + } + GeneralPathFinder dijkstra = new GeneralPathFinder<>(edges, false); + Optional> opt = dijkstra.computePath(c, other, 400, v -> +(double)v.getLocation().distance(other.getLocation()) + ); + if (opt.isPresent()) { + Path road = opt.get(); + + ImmutableVector2f p0 = road.getStart().getLocation(); + Path2D path2 = new Path2D.Float(); + path2.moveTo(p0.getX(), p0.getY()); + for (int i = 1; i < road.getSequence().size(); i++) { + ImmutableVector2f p1 = road.getSequence().get(i).getLocation(); + path2.lineTo(p1.getX(), p1.getY()); + } + g.setColor(Color.ORANGE); + g.setStroke(new BasicStroke(0f)); + + for (Corner c3 : gr.getCorners()) { + try { + road.getDistance(c3); // just test for the IllArgEx + ImmutableVector2f ol = c3.getLocation(); + g.fill(new Ellipse2D.Float(ol.getX()-2, ol.getY()-2, 4, 4)); + } catch (IllegalArgumentException e) { + // ignore silently + } + } + path = path2; + } + g.setColor(Color.GREEN); + g.drawOval((int)c.getLocation().getX()-400, (int)c.getLocation().getY()-400, 800, 800); + g.setStroke(new BasicStroke(3f)); + } + } +// ImmutableVector2f edgep1 = t.getCorner1().getLocation(); +// ImmutableVector2f edgep2 = t.getCorner2().getLocation(); +// LineSegment seg = new LineSegment(edgep1, edgep2); +// if (seg.distanceToPoint(cursorf) < 5) { +// g.setColor(Color.GREEN); +// g.setStroke(new BasicStroke(3f)); +// path = new Line2D.Float(edgep1.getX(), edgep1.getY(), edgep2.getX(), edgep2.getY()); +// } + + break; + + case CORNER: + CirclePickerClosest picker = new CirclePickerClosest<>(cursorf, c -> 3); + + picker.offer(t.getCorner1().getLocation(), t.getCorner1()); + picker.offer(t.getCorner2().getLocation(), t.getCorner2()); + + if (picker.getClosest() != null) { + Corner c = picker.getClosest(); + path = createCornerPath(c); + } else { + path = new Path2D.Float(); + } + break; + + case TRIANGLE: + path = createTrianglePath(t); + break; + + case REGION: + path = createRegionPath(t.getRegion()); + break; + } + + if (path != null) { +// g.setColor(fillColor); +// g.fill(path); + g.setColor(frameColor); + g.draw(path); + } + } + } + + public Mode getMode() { + return mode; + } + + public void setMode(Mode mode) { + this.mode = mode; + } + + private Shape createCornerPath(Corner c) { + Path2D path = new Path2D.Float(); + + float radCenter = 3; + float radAdj = 2; + + float cx = c.getLocation().getX(); + float cy = c.getLocation().getY(); + + for (Corner adj : c.getAdjacent()) { + float adx = adj.getLocation().getX(); + float ady = adj.getLocation().getY(); + path.moveTo(cx, cy); + path.lineTo(adx, ady); + } + + Area result = new Area(new BasicStroke(1f).createStrokedShape(path)); + result.add(new Area(new Ellipse2D.Float(cx - radCenter, cy - radCenter, radCenter * 2, radCenter * 2))); + + for (Corner adj : c.getAdjacent()) { + float adx = adj.getLocation().getX(); + float ady = adj.getLocation().getY(); + result.add(new Area(new Ellipse2D.Float(adx - radAdj, ady - radAdj, radAdj * 2, radAdj * 2))); + } + + return result; + } + + private Path2D createTrianglePath(Triangle t) { + BaseVector2f p0 = t.getRegion().getCenter(); + BaseVector2f p1 = t.getCorner1().getLocation(); + BaseVector2f p2 = t.getCorner2().getLocation(); + + Path2D path = new Path2D.Float(); + + path.moveTo(p0.getX(), p0.getY()); + path.lineTo(p1.getX(), p1.getY()); + path.lineTo(p2.getX(), p2.getY()); + path.closePath(); + + return path; + } + + private Path2D createRegionPath(org.terasology.polyworld.graph.Region region) { + + Path2D path = new Path2D.Float(); + + Iterator it = region.getCorners().iterator(); + + if (!it.hasNext()) { + return path; + } + + ImmutableVector2f p = it.next().getLocation(); + path.moveTo(p.getX(), p.getY()); + + while (it.hasNext()) { + p = it.next().getLocation(); + path.lineTo(p.getX(), p.getY()); + } + + path.closePath(); + return path; + } + +} + diff --git a/src/main/java/org/terasology/world/viewer/overlay/RiverModelOverlay.java b/src/main/java/org/terasology/world/viewer/overlay/RiverModelOverlay.java new file mode 100644 index 0000000..2cc4f98 --- /dev/null +++ b/src/main/java/org/terasology/world/viewer/overlay/RiverModelOverlay.java @@ -0,0 +1,61 @@ +/* + * Copyright 2015 MovingBlocks + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.terasology.world.viewer.overlay; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.geom.Line2D; +import java.util.function.Function; + +import org.terasology.math.geom.ImmutableVector2f; +import org.terasology.math.geom.ImmutableVector2i; +import org.terasology.math.geom.LineSegment; +import org.terasology.math.geom.Rect2i; +import org.terasology.math.geom.Vector2f; +import org.terasology.polyworld.graph.GraphFacet; +import org.terasology.polyworld.graph.Triangle; +import org.terasology.world.generation.Region; + +public class RiverModelOverlay extends AbstractOverlay implements WorldOverlay { + + private Function regions; + + public RiverModelOverlay(Function regionFunc) { + regions = regionFunc; + } + + @Override + public void render(Graphics2D g, Rect2i area, ImmutableVector2i cursor) { + if (cursor == null) { + return; + } + + Region r = regions.apply(cursor); + GraphFacet graphs = r.getFacet(GraphFacet.class); + if (graphs != null) { + Triangle t = graphs.getWorldTriangle(cursor.getX(), cursor.getY()); + ImmutableVector2f p0 = t.getCorner1().getLocation(); + ImmutableVector2f p1 = t.getCorner2().getLocation(); + if (LineSegment.distanceToPoint(p0, p1, new Vector2f(cursor.getX(), cursor.getY())) < 5) { + g.setStroke(new BasicStroke(3f)); + g.setColor(Color.RED); + g.draw(new Line2D.Float(p0.getX(), p0.getY(), p1.getX(), p1.getY())); + } + } + } +} diff --git a/src/main/java/org/terasology/world/viewer/overlay/SiteOverlay.java b/src/main/java/org/terasology/world/viewer/overlay/SiteOverlay.java new file mode 100644 index 0000000..34b6a56 --- /dev/null +++ b/src/main/java/org/terasology/world/viewer/overlay/SiteOverlay.java @@ -0,0 +1,75 @@ +/* + * Copyright 2015 MovingBlocks + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.terasology.world.viewer.overlay; + +import java.awt.Color; +import java.awt.Graphics2D; +import java.math.RoundingMode; +import java.util.function.Function; + +import org.terasology.cities.sites.Site; +import org.terasology.cities.sites.SiteFacet; +import org.terasology.math.geom.BaseVector2i; +import org.terasology.math.geom.ImmutableVector2i; +import org.terasology.math.geom.Rect2i; +import org.terasology.world.generation.Region; + +import com.google.common.math.IntMath; + +public class SiteOverlay extends AbstractOverlay implements WorldOverlay { + + private Function regions; + + public SiteOverlay(Function regionFunc) { + regions = regionFunc; + } + + @Override + public void render(Graphics2D g, Rect2i area, ImmutableVector2i cursor) { + if (cursor == null) { + return; + } + + g.setColor(Color.GRAY); + g.drawRect(128 * IntMath.divide(cursor.getX(), 128, RoundingMode.FLOOR), 128 * IntMath.divide(cursor.getY(), 128, RoundingMode.FLOOR), 128, 128); + + Color frameColor = new Color(128, 32, 32, 224); + + Region r = regions.apply(cursor); + SiteFacet facet = r.getFacet(SiteFacet.class); + + g.setColor(Color.BLACK); + Rect2i wr = facet.getWorldRegion(); + g.drawRect(wr.minX(), wr.minY(), wr.width(), wr.height()); + + Rect2i sr = facet.getCertainWorldRegion(); + g.drawRect(sr.minX(), sr.minY(), sr.width(), sr.height()); + + for (Site site : facet.getSettlements()) { + BaseVector2i pos = site.getPos(); + int rad = (int) site.getRadius(); +// if (pos.distance(cursor) < rad) { + g.setColor(frameColor); +// g.drawOval(pos.getX() - rad, pos.getY() - rad, rad * 2, rad * 2); + rad += 128; + g.drawOval(pos.getX() - rad, pos.getY() - rad, rad * 2, rad * 2); +// } + + + } + } +} diff --git a/src/main/java/org/terasology/world/viewer/overlay/SpawningPointOverlay.java b/src/main/java/org/terasology/world/viewer/overlay/SpawningPointOverlay.java new file mode 100644 index 0000000..c3b27d8 --- /dev/null +++ b/src/main/java/org/terasology/world/viewer/overlay/SpawningPointOverlay.java @@ -0,0 +1,97 @@ +/* + * Copyright 2015 MovingBlocks + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.terasology.world.viewer.overlay; + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.geom.Ellipse2D; + +import org.terasology.entitySystem.entity.EntityManager; +import org.terasology.entitySystem.entity.EntityRef; +import org.terasology.logic.location.LocationComponent; +import org.terasology.math.geom.BaseVector2i; +import org.terasology.math.geom.ImmutableVector2i; +import org.terasology.math.geom.Rect2i; +import org.terasology.math.geom.SpiralIterable; +import org.terasology.math.geom.Vector2i; +import org.terasology.math.geom.Vector3f; +import org.terasology.registry.CoreRegistry; +import org.terasology.world.generator.WorldGenerator; + +/** + * Shows the closest spawning point w.r.t. the mouse cursor. + */ +public class SpawningPointOverlay extends AbstractOverlay implements WorldOverlay { + + private final WorldGenerator worldGen; + private EntityRef player; + + public SpawningPointOverlay(WorldGenerator worldGen) { + this.worldGen = worldGen; + player = CoreRegistry.get(EntityManager.class).create(); + player.addComponent(new LocationComponent(new Vector3f(0, 0, 0))); + } + + @Override + public void render(Graphics2D g, Rect2i area, ImmutableVector2i cursor) { + if (cursor == null) { + return; + } + + LocationComponent location = player.getComponent(LocationComponent.class); + location.setWorldPosition(new Vector3f(cursor.getX(), location.getWorldPosition().getY(), cursor.getY())); + player.saveComponent(location); + + Vector3f pos = worldGen.getSpawnPosition(player); + + int searchRadius = 16; + + // try and find somewhere in this region a spot to land + Rect2i spawnArea = Rect2i.createFromMinAndSize(cursor.getX() - searchRadius, cursor.getY() - searchRadius, searchRadius * 2, searchRadius * 2); + + g.setColor(new Color(0x964B00)); + g.drawRect(spawnArea.minX(), spawnArea.minY(), spawnArea.width(), spawnArea.height()); + + int spiralRad = searchRadius / 2 - 1; + SpiralIterable spiral = SpiralIterable.clockwise(new Vector2i(cursor)).maxRadius(spiralRad).scale(2).build(); + g.setColor(Color.RED); + + Vector2i test2 = null; + for (BaseVector2i test : spiral) { + if (test2 != null) { + g.setColor(new Color(255, 0, 0, 128)); + g.drawLine(test2.getX(), test2.getY(), test.getX(), test.getY()); + } + g.setColor(Color.RED); + g.drawLine(test.getX(), test.getY(), test.getX(), test.getY()); + test2 = new Vector2i(test); + } + + float rad = 3; + g.create(); + g.setColor(Color.RED); + Ellipse2D.Float shape = new Ellipse2D.Float(pos.getX() - rad, pos.getZ() - rad, rad * 2, rad * 2); + g.fill(shape); + + + // draw outline +// g.setStroke(new BasicStroke(0.3f)); +// g.setColor(new Color(0x964B00)); // BROWN +// g.draw(shape); + } + +}