diff --git a/DelvEdit/src/com/interrupt/dungeoneer/editor/EditorFrame.java b/DelvEdit/src/com/interrupt/dungeoneer/editor/EditorFrame.java index c2565f31..7b64f887 100644 --- a/DelvEdit/src/com/interrupt/dungeoneer/editor/EditorFrame.java +++ b/DelvEdit/src/com/interrupt/dungeoneer/editor/EditorFrame.java @@ -17,7 +17,6 @@ import com.badlogic.gdx.graphics.g3d.decals.Decal; import com.badlogic.gdx.graphics.g3d.decals.DecalBatch; import com.badlogic.gdx.graphics.glutils.FrameBuffer; -import com.badlogic.gdx.graphics.glutils.ShaderProgram; import com.badlogic.gdx.graphics.glutils.ShapeRenderer; import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType; import com.badlogic.gdx.math.*; @@ -51,11 +50,13 @@ import com.interrupt.dungeoneer.game.Level.Source; import com.interrupt.dungeoneer.generator.DungeonGenerator; import com.interrupt.dungeoneer.generator.GenInfo.Markers; -import com.interrupt.dungeoneer.gfx.*; +import com.interrupt.dungeoneer.gfx.GlRenderer; +import com.interrupt.dungeoneer.gfx.SpriteGroupStrategy; +import com.interrupt.dungeoneer.gfx.TextureAtlas; +import com.interrupt.dungeoneer.gfx.WorldChunk; import com.interrupt.dungeoneer.gfx.drawables.DrawableMesh; import com.interrupt.dungeoneer.gfx.drawables.DrawableSprite; import com.interrupt.dungeoneer.interfaces.Directional; -import com.interrupt.dungeoneer.partitioning.TriangleSpatialHash; import com.interrupt.dungeoneer.serializers.KryoSerializer; import com.interrupt.dungeoneer.tiles.ExitTile; import com.interrupt.dungeoneer.tiles.Tile; @@ -69,7 +70,6 @@ import javax.swing.*; import java.util.HashMap; -import java.util.Map.Entry; public class EditorFrame implements ApplicationListener { @@ -109,7 +109,6 @@ public enum MoveMode { NONE, DRAG, ROTATE } public boolean canDelete = true; - protected static TriangleSpatialHash triangleSpatialHash = new TriangleSpatialHash(1); protected static Array staticMeshCollisionTriangles = new Array(); protected Array spatialWorkerList = new Array(); @@ -209,8 +208,6 @@ public boolean isWestFloor() { } } - private JFrame window = null; - private GameInput input; public EditorInput editorInput; private InputMultiplexer inputMultiplexer; @@ -220,8 +217,6 @@ public boolean isWestFloor() { private boolean rightClickWasDown = false; - public TesselatorGroups tesselators; - public PerspectiveCamera camera = new PerspectiveCamera(); protected Pixmap wallPixmap; @@ -247,13 +242,11 @@ public boolean isWestFloor() { double rotya = 0; float rotYClamp = 1.571f; - double walkVel = 0.05; double walkSpeed = 0.15; double rotSpeed = 0.009; double maxRot = 0.8; - boolean readFloorMove, readCeilMove, readRotate; - private int readFloorMoveCount, readCeilMoveCount; + boolean readRotate; Mesh cubeMesh; Mesh gridMesh; @@ -303,6 +296,7 @@ protected Decal newObject () { private Player player = null; private boolean showLights = false; + private boolean lightsDirty = true; private Entity hoveredEntity = null; private Entity pickedEntity = null; @@ -334,11 +328,8 @@ protected Decal newObject () { Color selectedColor = new Color(1f, 0.5f, 0.5f, 1f); Vector3 intersection = new Vector3(); - Vector3 testPos = new Vector3(); Vector3 tempVector1 = new Vector3(); - Color tempColor = new Color(); - DrawableSprite unknownEntityMarker = new DrawableSprite(); Array controlPoints = new Array(); @@ -361,15 +352,12 @@ protected Decal newObject () { Vector3 rayOutVector = new Vector3(); - private boolean isOnWindows = System.getProperty("os.name").startsWith("Windows"); - public Editor editor; /** * @wbp.parser.entryPoint */ public EditorFrame(JFrame window, Editor editor) { - this.window = window; this.editor = editor; } @@ -378,8 +366,7 @@ public void init(){ Gdx.input.setInputProcessor( input ); renderer.init(); - - tesselators = new TesselatorGroups(); + renderer.enableLighting = showLights; cubeMesh = genCube(); spriteBatch = new DecalBatch(new SpriteGroupStrategy(camera, null, GlRenderer.worldShaderInfo, 1)); @@ -472,8 +459,6 @@ public void render() { rotY = -Game.instance.player.yrot; Audio.stopLoopingSounds(); - - tesselators.refresh(); } return; @@ -568,30 +553,13 @@ public void draw() { gl.glClearColor(0.2235f, 0.2235f, 0.2235f, 1); gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT | GL20.GL_STENCIL_BUFFER_BIT); - Tesselate(); - - tesselators.world.render(); - - GlRenderer.waterShaderInfo.setScrollSpeed(0f); - tesselators.water.render(); - - GlRenderer.waterShaderInfo.setScrollSpeed(0.03f); - tesselators.waterfall.render(); - - gl.glDepthFunc(GL20.GL_LEQUAL); - - GlRenderer.waterEdgeShaderInfo.setAttribute("u_noise_mod", 1f); - GlRenderer.waterEdgeShaderInfo.setAttribute("u_waveMod", 1f); - - Gdx.gl.glEnable(GL20.GL_POLYGON_OFFSET_FILL); - Gdx.gl.glPolygonOffset(-1f, -1f); - - tesselators.waterEdges.render(); - - GlRenderer.waterEdgeShaderInfo.setAttribute("u_noise_mod", 4f); - GlRenderer.waterEdgeShaderInfo.setAttribute("u_waveMod", 0f); + if(showLights && lightsDirty) { + lightsDirty = false; + level.updateLights(Source.EDITOR); + } - tesselators.waterfallEdges.render(); + renderer.Tesselate(level); + renderer.renderWorld(level); gl.glDisable(GL20.GL_CULL_FACE); @@ -639,46 +607,6 @@ public void draw() { Gdx.gl.glEnable(GL20.GL_ALPHA); Gdx.gl.glEnable(GL20.GL_CULL_FACE); - if(staticMeshBatch == null) { - staticMeshCollisionTriangles.clear(); - EditorCachePools.freeAllCaches(); - - // sort the mesh entities into buckets, determined by their texture - HashMap> meshesByTexture = new HashMap>(); - groupStaticMeshesByTexture(level.entities, meshesByTexture); - - // make a static mesh from each entity bucket - staticMeshBatch = new HashMap>(); - for(String key : meshesByTexture.keySet()) { - staticMeshBatch.put(key, mergeStaticMeshes(level, meshesByTexture.get(key))); - } - - // cleanup, don't need the mesh buckets anmyore - meshesByTexture.clear(); - - refreshTriangleSpatialHash(); - } - if(staticMeshBatch != null) { - for(Entry> meshBuckets : staticMeshBatch.entrySet()) { - Texture t = Art.cachedTextures.get(meshBuckets.getKey()); - if(t != null) GlRenderer.bindTexture(t); - if(meshBuckets.getValue() != null) { - GlRenderer.worldShaderInfo.setAttributes(camera.combined, - 0, - 1000, - 1000, - time, - Color.BLACK, - Color.BLACK); - - GlRenderer.worldShaderInfo.begin(); - for(Mesh m : meshBuckets.getValue()) { - m.render(GlRenderer.worldShaderInfo.shader, GL20.GL_TRIANGLES); - } - GlRenderer.worldShaderInfo.end(); - } - } - } renderer.renderDecals(); renderer.renderStencilPasses(); @@ -1550,29 +1478,8 @@ private void RenderEntitiesForPicking() { Gdx.gl.glCullFace(GL20.GL_BACK); Gdx.gl.glEnable(GL20.GL_CULL_FACE); - Tesselate(); - - // render world, keep depth buffer - tesselators.world.render(); - - GlRenderer.waterShaderInfo.setScrollSpeed(0f); - tesselators.water.render(); - - GlRenderer.waterShaderInfo.setScrollSpeed(0.03f); - tesselators.waterfall.render(); - - GlRenderer.waterEdgeShaderInfo.setAttribute("u_noise_mod", 1f); - GlRenderer.waterEdgeShaderInfo.setAttribute("u_waveMod", 1f); - - Gdx.gl.glEnable(GL20.GL_POLYGON_OFFSET_FILL); - Gdx.gl.glPolygonOffset(-1f, -1f); - - tesselators.waterEdges.render(); - - GlRenderer.waterEdgeShaderInfo.setAttribute("u_noise_mod", 4f); - GlRenderer.waterEdgeShaderInfo.setAttribute("u_waveMod", 0f); - - tesselators.waterfallEdges.render(); + renderer.Tesselate(level); + renderer.renderWorld(level); Gdx.gl.glDisable(GL20.GL_POLYGON_OFFSET_FILL); Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); @@ -1585,28 +1492,24 @@ private void RenderEntitiesForPicking() { } private void refreshTriangleSpatialHash() { - GlRenderer.triangleSpatialHash = triangleSpatialHash; - triangleSpatialHash.Flush(); - - // add the collision triangles to the spatial hash - for(int i = 0; i < staticMeshCollisionTriangles.size; i++) { - triangleSpatialHash.AddTriangle(staticMeshCollisionTriangles.get(i)); - } - - tesselators.world.addCollisionTriangles(triangleSpatialHash); - tesselators.water.addCollisionTriangles(triangleSpatialHash); - tesselators.waterfall.addCollisionTriangles(triangleSpatialHash); + GlRenderer.triangleSpatialHash.Flush(); } protected void refreshEntity(Entity theEntity) { if(theEntity instanceof Light && showLights) { - refreshLights(); + markWorldAsDirty((int)theEntity.x, (int)theEntity.y, (int)((Light)theEntity).range + 1); + ((Light)theEntity).clearCanSee(); + lightsDirty = true; } else if(theEntity instanceof ProjectedDecal) { ((ProjectedDecal)theEntity).refresh(); } else if(theEntity instanceof Model) { - if(!((Model)theEntity).isDynamic) staticMeshBatch = null; + Model m = (Model)theEntity; + if(!m.isDynamic) { + // Todo: Get range from the bounding box + markWorldAsDirty((int)theEntity.x, (int)theEntity.y, 5); + } } else if(theEntity instanceof Prefab) { Array contains = ((Prefab)theEntity).entities; @@ -2050,8 +1953,6 @@ public void tick() { // get picked entity Ray ray = camera.getPickRay(Gdx.input.getX(), Gdx.input.getY()); - float worldHitDistance = 10000000f; - // get plane intersection if(intpos != null) { if (!Gdx.input.isTouched()) { @@ -2063,10 +1964,9 @@ public void tick() { // try world intersection Intersector.intersectRayPlane(ray, p, intpos); - if (Collidor.intersectRayForwardFacingTriangles(camera.getPickRay(Gdx.input.getX(), Gdx.input.getY()), camera, triangleSpatialHash.getAllTriangles(), intpos, intersectNormal)) { + if (Collidor.intersectRayForwardFacingTriangles(camera.getPickRay(Gdx.input.getX(), Gdx.input.getY()), camera, GlRenderer.triangleSpatialHash.getAllTriangles(), intpos, intersectNormal)) { intersectTemp.set(intpos).sub(camera.position).nor(); intpos.add(intersectTemp.x * -0.05f, 0.0001f, intersectTemp.z * -0.05f); - worldHitDistance = intersectTemp.set(intpos).sub(camera.position).len(); } if(tileDragging) { @@ -2520,29 +2420,6 @@ public void setInputProcessor() { Gdx.input.setInputProcessor(inputMultiplexer); } - public Tesselator tesselator = new Tesselator(); - public void Tesselate() - { - if(!tesselators.world.needsTesselation()) return; - - if(renderer.chunks != null) - renderer.chunks.clear(); - - int width = level.width; - int height = level.height; - - int xOffset = 0; - int yOffset = 0; - - boolean makeFloors = true; - boolean makeCeilings = true; - boolean makeWalls = true; - - tesselator.Tesselate(level, renderer, null, xOffset, yOffset, width, height, tesselators, makeFloors, makeCeilings, makeWalls, showLights); - - refreshTriangleSpatialHash(); - } - public int GetNextPowerOf2(int v) { v--; v |= v >> 1; @@ -2641,7 +2518,7 @@ public Mesh genGrid (int height, int width) { indices[i++] = (short)(i - 1); } - Mesh mesh = new Mesh(true, vertices.length, indices.length, new VertexAttribute(Usage.Position, 3, "a_position"), new VertexAttribute(Usage.ColorUnpacked, 4, "a_color")); + Mesh mesh = new Mesh(false, vertices.length, indices.length, new VertexAttribute(Usage.Position, 3, "a_position"), new VertexAttribute(Usage.ColorUnpacked, 4, "a_color")); mesh.setVertices(vertices); mesh.setIndices(indices); @@ -2812,12 +2689,11 @@ public void addEntityMarker(Markers selectedItem) { for(int y = selY; y < selY + selHeight; y++) { EditorMarker eM = new EditorMarker(selectedItem, x, y); level.editorMarkers.add(eM); + markWorldAsDirty(x, y, 4); } } } - refreshLights(); - history.saveState(level); } @@ -2835,25 +2711,9 @@ public boolean selectionHasEntityMarker() { } public void addEntity(Entity e) { - if(selected) { - int x = selectionX; - int y = selectionY; - - String objCopy = Game.toJson(e); - - Entity copy = Game.fromJson(e.getClass(), objCopy); - copy.x = x + 0.5f; - copy.y = y + 0.5f; - - Tile at = level.getTileOrNull(x, y); - if(at != null) copy.z = at.floorHeight + 0.5f; - - level.entities.add(copy); - } - - history.saveState(level); - - refreshLights(); + level.entities.add(e); + e.init(level, Source.EDITOR); + markWorldAsDirty((int)e.x, (int)e.y, 4); } public void clearSelectedMarkers() { @@ -2872,14 +2732,16 @@ public void clearSelectedMarkers() { if(m.x == x && m.y == y) toDelete.add(m); } + if(toDelete.size > 0) { + markWorldAsDirty(x, y, 4); + } + for(EditorMarker m : toDelete) { level.editorMarkers.removeValue(m, true); } } } } - - refreshLights(); } public void refresh() { @@ -2891,8 +2753,31 @@ public void refresh() { refreshLights(); } + public void markWorldAsDirty(int xPos, int yPos, int radius) { + int startX = (xPos - radius) / 17; + int startY = (yPos - radius) / 17; + int endX = (xPos + radius) / 17; + int endY = (yPos + radius) / 17; + + for(int x = startX; x <= endX; x++) { + for(int y = startY; y <= endY; y++) { + WorldChunk chunk = renderer.GetWorldChunkAt(x * 17, y * 17); + + if(chunk == null) { + // No chunk here yet, so make one + chunk = new WorldChunk(renderer); + chunk.setOffset(x * 17, y * 17); + chunk.setSize(17, 17); + renderer.chunks.add(chunk); + } + + chunk.hasBuilt = false; + } + } + } + public void refreshLights() { - tesselators.refresh(); + level.isDirty = true; if(showLights) { level.cleanupLightCache(); @@ -2935,10 +2820,12 @@ public void setTile(Tile tocopy) { t.eastTex = t.westTex = t.northTex = t.southTex = null; t.bottomEastTex = t.bottomWestTex = t.bottomNorthTex = t.bottomSouthTex = null; + + markWorldAsDirty(x, y, 1); } } - // Paint directional tiles + // Paint directional tiless if(paintAdjacent.isChecked()) { if (selY - 1 >= 0) { for (int x = selX; x < selX + selWidth; x++) { @@ -3012,8 +2899,6 @@ public void setTile(Tile tocopy) { } } } - - refreshLights(); } public void paintTile(Tile tocopy) { @@ -3058,6 +2943,8 @@ public void paintTile(Tile tocopy) { t.bottomEastTexAtlas = t.bottomWestTexAtlas = t.bottomNorthTexAtlas = t.bottomSouthTexAtlas = null; t.init(Source.EDITOR); + + markWorldAsDirty(x, y, 1); } } @@ -3134,8 +3021,6 @@ public void paintTile(Tile tocopy) { } } } - - refreshLights(); } public void clearTiles() { @@ -3160,12 +3045,12 @@ public void clearTiles() { t.wallTexAtlas = pickedWallTextureAtlas; level.setTile(x, y, t); } + + markWorldAsDirty(x, y, 1); } } clearSelectedMarkers(); - - refreshLights(); } public void rotateFloorTex(int value) { @@ -3183,10 +3068,10 @@ public void rotateFloorTex(int value) { t.floorTexRot += value; t.floorTexRot %= 4; } + + markWorldAsDirty(x, y, 1); } } - - refreshLights(); } public Entity copyEntity(Entity entity) { @@ -3257,6 +3142,8 @@ public void paste() { Tile.copy(clipboard.tiles[x][y],t); level.setTile(x + selX, y + selY, t); } + + markWorldAsDirty(x + selX, y + selY, 1); } } @@ -3270,14 +3157,12 @@ public void paste() { copy.z += copyAt.getFloorHeight(0.5f, 0.5f); } - level.entities.add(copy); + addEntity(copy); } // save undo history history.saveState(level); } - - refreshLights(); } public void rotateAngle() { @@ -3296,10 +3181,10 @@ public void rotateAngle() { t.renderSolid = false; t.tileSpaceType = TileSpaceType.values()[(t.tileSpaceType.ordinal() + 1) % TileSpaceType.values().length]; } + + markWorldAsDirty(x, y, 1); } } - - refreshLights(); } public void rotateCeilTex(int value) { @@ -3317,10 +3202,10 @@ public void rotateCeilTex(int value) { t.ceilTexRot += value; t.ceilTexRot %= 4; } + + markWorldAsDirty(x, y, 1); } } - - refreshLights(); } public void moveFloor(int value) { @@ -3334,10 +3219,10 @@ public void moveFloor(int value) { Tile t = level.getTileOrNull(x,y); if(t != null) t.floorHeight += (value * 0.0625f); + + markWorldAsDirty(x, y, 1); } } - - refreshLights(); } public void moveCeiling(int value) { @@ -3351,10 +3236,10 @@ public void moveCeiling(int value) { Tile t = level.getTileOrNull(x,y); if(t != null) t.ceilHeight += (value * 0.0625f); + + markWorldAsDirty(x, y, 1); } } - - refreshLights(); } public void doFloorMoveUp() { @@ -3391,7 +3276,7 @@ public void doCeilMoveDown() { Vector3 t_pickerVector = new Vector3(); public void updatePickedSurface() { - if (Collidor.intersectRayForwardFacingTriangles(camera.getPickRay(Gdx.input.getX(), Gdx.input.getY()), camera, triangleSpatialHash.getAllTriangles(), t_pickerVector, intersectNormal)) { + if (Collidor.intersectRayForwardFacingTriangles(camera.getPickRay(Gdx.input.getX(), Gdx.input.getY()), camera, GlRenderer.triangleSpatialHash.getAllTriangles(), t_pickerVector, intersectNormal)) { t_pickerVector.add(intersectTemp.x * 0.0001f, intersectTemp.y * 0.0001f, intersectTemp.z * 0.0001f); pickedSurface.position.set(t_pickerVector); pickedSurface.isPicked = true; @@ -3624,7 +3509,7 @@ else if(pickedSurface.edge == TileEdges.South) { t.init(Source.EDITOR); history.saveState(level); - refreshLights(); + markWorldAsDirty((int)pickedSurface.position.x, (int)pickedSurface.position.y, 1); } } @@ -3858,159 +3743,6 @@ public TextureRegion[] loadAtlas(String texture, int spritesHorizontal, boolean return region; } - public Color GetLightmapAt(float posx, float posy, float posz) { - Color t = level.GetLightmapAt(posx, posz, posz); - - if(t == null) { - return Color.BLACK; - } - - return level.GetLightmapAt(posx, posy, posz); - } - - Array t_collisionTriangles = new Array(); - VertexAttributes t_staticMeshVertexAttributes = new VertexAttributes(new VertexAttribute(VertexAttributes.Usage.Position, 3, ShaderProgram.POSITION_ATTRIBUTE), - new VertexAttribute(VertexAttributes.Usage.ColorPacked, 4, ShaderProgram.COLOR_ATTRIBUTE), - new VertexAttribute(VertexAttributes.Usage.TextureCoordinates, 2, ShaderProgram.TEXCOORD_ATTRIBUTE + "0")); - - public Array mergeStaticMeshes(Level level, Array entities) { - short indexOffset = 0; - int vertexCount = 0; - - ShortArray indices = new ShortArray(500); - FloatArray vertices = new FloatArray(500); - - Array created = new Array(); - - for(Entity e : entities) { - if(e.drawable != null && e.drawable instanceof DrawableMesh) { - DrawableMesh drbl = (DrawableMesh)e.drawable; - - if(drbl.loadedMesh != null && drbl.isStaticMesh) { - - // may need to chunk up the meshes - if(drbl.loadedMesh.getNumIndices() + indexOffset >= 32000 && vertexCount > 0) { - - Mesh m = EditorCachePools.getStaticMesh(t_staticMeshVertexAttributes, vertexCount, indices.size, true); - - // pack the array - indices.shrink(); - vertices.shrink(); - - m.setIndices(indices.toArray()); - m.setVertices(vertices.toArray()); - - indices = new ShortArray(500); - vertices = new FloatArray(500); - - vertexCount = 0; - indexOffset = 0; - - created.add(m); - } - - VertexAttributes attributes = drbl.loadedMesh.getVertexAttributes(); - - int positionOffset = 0; - int uvOffset = 0; - int attSize = 0; - - for(int i = 0; i < attributes.size(); i++) { - VertexAttribute attrib = attributes.get(i); - - if(attrib.usage == VertexAttribute.Position().usage) { - positionOffset = attSize; - } - else if(attrib.usage == VertexAttribute.TexCoords(0).usage) { - uvOffset = attSize; - } - - attSize += attrib.numComponents; - } - - short[] ind = new short[drbl.loadedMesh.getNumIndices()]; - float[] verts = new float[drbl.loadedMesh.getNumVertices() * attSize]; - - if(ind.length > 0) - drbl.loadedMesh.getIndices(ind); - else { - ind = new short[drbl.loadedMesh.getNumVertices()]; - - for(int i = 0; i < drbl.loadedMesh.getNumVertices(); i++) { - ind[i] = (short)i; - } - } - - drbl.loadedMesh.getVertices(verts); - - Matrix4 matrix = new Matrix4().setToTranslation(e.x, e.z - 0.5f, e.y); - matrix.scale(drbl.scale, drbl.scale, drbl.scale); - matrix.mul(new Matrix4().setToRotation(Vector3.X, drbl.dir.y * -90f)); - - matrix.rotate(Vector3.Y, drbl.rotZ); - matrix.rotate(Vector3.X, drbl.rotX); - matrix.rotate(Vector3.Z, drbl.rotY); - - // translate the vertices by the model matrix - Matrix4.mulVec(matrix.val, verts, 0, drbl.loadedMesh.getNumVertices(), attSize); - - if(ind != null && verts != null) { - for(int i = 0; i < ind.length; i++) { - indices.add((short)(ind[i] + indexOffset)); - } - indexOffset += ind.length; - - for(int i = 0; i < drbl.loadedMesh.getNumVertices() * attSize; i+= attSize) { - - vertices.add(verts[i + positionOffset]); - vertices.add(verts[i + positionOffset + 1]); - vertices.add(verts[i + positionOffset + 2]); - - if (e.isSolid) { - t_collisionTriangles.add(EditorCachePools.getCollisionVector(verts[i + positionOffset], verts[i + positionOffset + 1], verts[i + positionOffset + 2])); - } - - float c = Color.WHITE.toFloatBits(); - if(!e.fullbrite && showLights) { - c = level.getLightColorAt(verts[i + positionOffset], verts[i + positionOffset + 2], verts[i + positionOffset + 1], null, new Color()).toFloatBits(); - } - - vertices.add(c); - vertices.add(verts[i + uvOffset]); - vertices.add(verts[i + uvOffset + 1]); - - vertexCount++; - } - } - } - } - } - - if(vertexCount == 0) return null; - - for (int i = 0; i < t_collisionTriangles.size; i += 3) { - Triangle triangle = EditorCachePools.getTriangle(); - triangle.v1.set(t_collisionTriangles.get(i + 2)); - triangle.v2.set(t_collisionTriangles.get(i + 1)); - triangle.v3.set(t_collisionTriangles.get(i)); - - staticMeshCollisionTriangles.add(triangle); - } - t_collisionTriangles.clear(); - - Mesh m = EditorCachePools.getStaticMesh(t_staticMeshVertexAttributes, vertexCount, indices.size, true); - - // pack the array - indices.shrink(); - vertices.shrink(); - - m.setIndices(indices.toArray()); - m.setVertices(vertices.toArray()); - - created.add(m); - return created; - } - public void doCarve() { if(pickedEntity != null) return; @@ -4074,13 +3806,15 @@ public void doPaint() { public void doDelete() { if(pickedEntity != null) { level.entities.removeValue(pickedEntity, true); + markWorldAsDirty((int)pickedEntity.x, (int)pickedEntity.y, 4); for(Entity selEntity : additionalSelected) { level.entities.removeValue(selEntity, true); + + markWorldAsDirty((int)selEntity.x, (int)selEntity.y, 4); } clearEntitySelection(); - refreshLights(); canDelete = false; } @@ -4088,6 +3822,8 @@ public void doDelete() { clearTiles(); } + refreshLights(); + // save undo history history.saveState(level); } @@ -4116,9 +3852,10 @@ public void flattenFloor() { t.floorHeight = matchFloorHeight; t.slopeNE = t.slopeNW = t.slopeSE = t.slopeSW = 0; } + + markWorldAsDirty(x, y, 1); } } - refreshLights(); } public void flattenCeiling() { @@ -4135,9 +3872,10 @@ public void flattenCeiling() { t.ceilHeight = matchCeilHeight; t.ceilSlopeNE = t.ceilSlopeNW = t.ceilSlopeSE = t.ceilSlopeSW = 0; } + + markWorldAsDirty(x, y, 1); } } - refreshLights(); } public void toggleSimulation() { @@ -4249,7 +3987,7 @@ public MoveMode getMoveMode() { } public Array GetCollisionTriangles() { - return triangleSpatialHash.getAllTriangles(); + return GlRenderer.triangleSpatialHash.getAllTriangles(); } public Array TriangleArrayToVectorList(Array triangles) { diff --git a/DelvEdit/src/com/interrupt/dungeoneer/editor/EditorRightClickEntitiesMenu.java b/DelvEdit/src/com/interrupt/dungeoneer/editor/EditorRightClickEntitiesMenu.java index 62a508e6..aabfa720 100644 --- a/DelvEdit/src/com/interrupt/dungeoneer/editor/EditorRightClickEntitiesMenu.java +++ b/DelvEdit/src/com/interrupt/dungeoneer/editor/EditorRightClickEntitiesMenu.java @@ -227,7 +227,8 @@ else if(surface.edge == TileEdges.South) { } } - editor.level.entities.add(entity); + editor.addEntity(entity); + editor.refreshLights(); editor.history.saveState(editor.level); } diff --git a/DelvEdit/src/com/interrupt/dungeoneer/editor/EditorRightClickMenu.java b/DelvEdit/src/com/interrupt/dungeoneer/editor/EditorRightClickMenu.java index 66283af4..815c3f5d 100644 --- a/DelvEdit/src/com/interrupt/dungeoneer/editor/EditorRightClickMenu.java +++ b/DelvEdit/src/com/interrupt/dungeoneer/editor/EditorRightClickMenu.java @@ -128,6 +128,8 @@ public void actionPerformed (ActionEvent event) { selected.y = selected.y - main.y; selected.z = selected.z - main.z; newGroup.entities.add(selected); + + editor.markWorldAsDirty((int)selected.x, (int)selected.y, 4); level.entities.removeValue(selected, true); } @@ -138,16 +140,18 @@ public void actionPerformed (ActionEvent event) { newGroup.entities.add(main); level.entities.removeValue(main, true); - level.entities.add(newGroup); + editor.addEntity(newGroup); } }); remove.addActionListener(new ActionListener() { public void actionPerformed (ActionEvent event) { level.entities.removeValue(main, true); + editor.markWorldAsDirty((int)main.x, (int)main.y, 4); for(Entity selected : additionalSelected) { level.entities.removeValue(selected, true); + editor.markWorldAsDirty((int)selected.x, (int)selected.y, 4); } editor.refreshLights(); diff --git a/Dungeoneer/src/com/interrupt/dungeoneer/gfx/GlRenderer.java b/Dungeoneer/src/com/interrupt/dungeoneer/gfx/GlRenderer.java index 840dba9a..700442cf 100644 --- a/Dungeoneer/src/com/interrupt/dungeoneer/gfx/GlRenderer.java +++ b/Dungeoneer/src/com/interrupt/dungeoneer/gfx/GlRenderer.java @@ -2527,6 +2527,23 @@ public void refreshChunksNear(float x, float y, float range) { } } + public WorldChunk GetWorldChunkAt(int x, int y) { + if(chunks == null) + return null; + + for(int i = 0; i < chunks.size; i++) { + WorldChunk c = chunks.get(i); + + if(x >= c.xOffset && x < c.xOffset + c.width) { + if(y >= c.yOffset && y < c.yOffset + c.height) { + return c; + } + } + } + + return null; + } + public void Tesselate(Level level) { if(level.isDirty) { @@ -2572,7 +2589,9 @@ public void Tesselate(Level level) for (int i = 0; i < chunks.size; i++) { WorldChunk c = chunks.get(i); if(c != null && !c.hasBuilt) { + triangleSpatialHash.dropWorldChunk(c); c.Tesselate(loadedLevel, this); + c.tesselators.world.addCollisionTriangles(triangleSpatialHash); } } } diff --git a/Dungeoneer/src/com/interrupt/dungeoneer/gfx/WorldChunk.java b/Dungeoneer/src/com/interrupt/dungeoneer/gfx/WorldChunk.java index 2413e41d..3774d8e2 100644 --- a/Dungeoneer/src/com/interrupt/dungeoneer/gfx/WorldChunk.java +++ b/Dungeoneer/src/com/interrupt/dungeoneer/gfx/WorldChunk.java @@ -10,9 +10,11 @@ import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.ArrayMap; import com.badlogic.gdx.utils.ObjectMap.Entry; +import com.badlogic.gdx.utils.Triangle; import com.interrupt.dungeoneer.Art; import com.interrupt.dungeoneer.GameManager; import com.interrupt.dungeoneer.entities.Entity; +import com.interrupt.dungeoneer.entities.Group; import com.interrupt.dungeoneer.game.Game; import com.interrupt.dungeoneer.game.Level; import com.interrupt.dungeoneer.game.OverworldChunk; @@ -127,6 +129,19 @@ public void freeStaticMeshes() { staticMeshBatch.clear(); } } + + public void AddEntityForEditor(Entity e, Level level) { + // Needed for static meshes in groups in the editor + if(e instanceof Group) { + e.init(level, Level.Source.EDITOR); + for(Entity g : ((Group) e).entities) { + AddEntityForEditor(g, level); + } + } else { + entities.add(e); + e.updateLight(level); + } + } public void Tesselate(Level level, GlRenderer renderer) { @@ -144,6 +159,15 @@ public void Tesselate(Level level, GlRenderer renderer) e.updateLight(level); } } + + // renderer hasn't sorted entities into static_entities yet + if(renderer.editorIsRendering) { + for(Entity e : level.entities) { + if(e.x >= xOffset && e.x < xOffset + width && e.y >= yOffset && e.y < yOffset + height) { + AddEntityForEditor(e, level); + } + } + } if(level instanceof OverworldLevel) { for(OverworldChunk chunk : ((OverworldLevel)level).chunks.values()) { @@ -244,4 +268,16 @@ public void renderStaticMeshBatch(ShaderInfo shader) { public void setOverworldChunk(OverworldChunk overworldChunk) { this.overworldChunk = overworldChunk; } + + public int getWorldX() { + return xOffset + (width / 2); + } + + public int getWorldY() { + return yOffset + (height / 2); + } + + public int getRadius() { + return width / 2; + } } diff --git a/Dungeoneer/src/com/interrupt/dungeoneer/partitioning/TriangleSpatialHash.java b/Dungeoneer/src/com/interrupt/dungeoneer/partitioning/TriangleSpatialHash.java index fc310d7c..2410cd41 100644 --- a/Dungeoneer/src/com/interrupt/dungeoneer/partitioning/TriangleSpatialHash.java +++ b/Dungeoneer/src/com/interrupt/dungeoneer/partitioning/TriangleSpatialHash.java @@ -3,12 +3,10 @@ import com.badlogic.gdx.math.Frustum; import com.badlogic.gdx.math.Vector3; import com.badlogic.gdx.math.collision.Ray; -import com.badlogic.gdx.utils.Array; -import com.badlogic.gdx.utils.IntArray; -import com.badlogic.gdx.utils.IntMap; -import com.badlogic.gdx.utils.Triangle; +import com.badlogic.gdx.utils.*; import com.interrupt.dungeoneer.GameManager; import com.interrupt.dungeoneer.game.CachePools; +import com.interrupt.dungeoneer.gfx.WorldChunk; import com.interrupt.dungeoneer.tiles.Tile; import com.interrupt.dungeoneer.tiles.Tile.TileSpaceType; @@ -133,6 +131,20 @@ public void AddTriangle(Triangle e) { key = getKey(e.v3.x, e.v3.z); PutTriangle(key, e); } + + public void dropWorldChunk(WorldChunk chunk) { + temp.clear(); + IntArray cells = getCellsNear(chunk.getWorldX(), chunk.getWorldY(), chunk.getRadius()); + + // drop triangles in these cells + for(int i = 0; i < cells.size; i++) { + int cell = cells.get(i); + Array inCell = hash.get(cell); + if(inCell != null) { + inCell.clear(); + } + } + } // Returns triangles found near an entity public Array getTrianglesAt(float x, float y, float colSize) {