diff --git a/flixel/FlxCamera.hx b/flixel/FlxCamera.hx index acf179f8a4..99352d9214 100644 --- a/flixel/FlxCamera.hx +++ b/flixel/FlxCamera.hx @@ -11,6 +11,7 @@ import openfl.geom.Rectangle; import flixel.graphics.FlxGraphic; import flixel.graphics.frames.FlxFrame; import flixel.graphics.tile.FlxDrawBaseItem; +import flixel.graphics.tile.FlxDrawTriangleData; import flixel.graphics.tile.FlxDrawTrianglesItem; import flixel.math.FlxMath; import flixel.math.FlxMatrix; @@ -850,6 +851,100 @@ class FlxCamera extends FlxBasic } } + public function drawTriangleData(graphic:FlxGraphic, triangles:FlxDrawTriangleData, ?position:FlxPoint, ?blend:BlendMode, repeat = false, + smoothing = false, ?transform:ColorTransform, ?shader:FlxShader):Void + { + if (FlxG.renderBlit) + { + if (position == null) + position = renderPoint.set(); + + _bounds.set(0, 0, width, height); + + var verticesLength:Int = triangles.vertices.length; + var currentVertexPosition:Int = 0; + + var tempX:Float, tempY:Float; + var i:Int = 0; + var bounds = renderRect.set(); + drawVertices.splice(0, drawVertices.length); + + while (i < verticesLength) + { + tempX = position.x + triangles.vertices[i]; + tempY = position.y + triangles.vertices[i + 1]; + + drawVertices[currentVertexPosition++] = tempX; + drawVertices[currentVertexPosition++] = tempY; + + if (i == 0) + { + bounds.set(tempX, tempY, 0, 0); + } + else + { + FlxDrawTrianglesItem.inflateBounds(bounds, tempX, tempY); + } + + i += 2; + } + + position.putWeak(); + + if (!_bounds.overlaps(bounds)) + { + drawVertices.splice(drawVertices.length - verticesLength, verticesLength); + } + else + { + trianglesSprite.graphics.clear(); + trianglesSprite.graphics.beginBitmapFill(graphic.bitmap, null, repeat, smoothing); + trianglesSprite.graphics.drawTriangles(drawVertices, triangles.indices, triangles.uvs); + trianglesSprite.graphics.endFill(); + + // TODO: check this block of code for cases, when zoom < 1 (or initial zoom?)... + if (_useBlitMatrix) + _helperMatrix.copyFrom(_blitMatrix); + else + { + _helperMatrix.identity(); + _helperMatrix.translate(-viewMarginLeft, -viewMarginTop); + } + + buffer.draw(trianglesSprite, _helperMatrix); + #if FLX_DEBUG + if (FlxG.debugger.drawDebug) + { + var gfx:Graphics = FlxSpriteUtil.flashGfx; + gfx.clear(); + gfx.lineStyle(1, FlxColor.BLUE, 0.5); + gfx.drawTriangles(drawVertices, triangles.indices); + buffer.draw(FlxSpriteUtil.flashGfxSprite, _helperMatrix); + } + #end + // End of TODO... + } + + bounds.put(); + } + else + { + _bounds.set(0, 0, width, height); + var isColored:Bool = (triangles.colors != null && triangles.colors.length != 0); + + #if !flash + var hasColorOffsets:Bool = (transform != null && transform.hasRGBAOffsets()); + isColored = isColored || (transform != null && transform.hasRGBMultipliers()); + var drawItem:FlxDrawTrianglesItem = startTrianglesBatch(graphic, smoothing, isColored, blend, hasColorOffsets, shader); + drawItem.addTriangleData(triangles, position, _bounds, transform); + #else + var drawItem:FlxDrawTrianglesItem = startTrianglesBatch(graphic, smoothing, isColored, blend); + drawItem.addTriangleData(triangles, position, _bounds); + #end + } + } + + // @:deprecated("FlxCamera's drawTriangles is deprecated use drawTriangleData, instead") // TODO public function drawTriangles(graphic:FlxGraphic, vertices:DrawData, indices:DrawData, uvtData:DrawData, ?colors:DrawData, ?position:FlxPoint, ?blend:BlendMode, repeat:Bool = false, smoothing:Bool = false, ?transform:ColorTransform, ?shader:FlxShader):Void { @@ -935,10 +1030,10 @@ class FlxCamera extends FlxBasic var hasColorOffsets:Bool = (transform != null && transform.hasRGBAOffsets()); isColored = isColored || (transform != null && transform.hasRGBMultipliers()); var drawItem:FlxDrawTrianglesItem = startTrianglesBatch(graphic, smoothing, isColored, blend, hasColorOffsets, shader); - drawItem.addTriangles(vertices, indices, uvtData, colors, position, _bounds, transform); + drawItem.addTrianglesHelper(vertices, indices, uvtData, colors, position, _bounds, transform); #else var drawItem:FlxDrawTrianglesItem = startTrianglesBatch(graphic, smoothing, isColored, blend); - drawItem.addTriangles(vertices, indices, uvtData, colors, position, _bounds); + drawItem.addTrianglesHelper(vertices, indices, uvtData, colors, position, _bounds); #end } } diff --git a/flixel/FlxObject.hx b/flixel/FlxObject.hx index 9c18d0f35f..473fcd38b9 100644 --- a/flixel/FlxObject.hx +++ b/flixel/FlxObject.hx @@ -1150,6 +1150,18 @@ class FlxObject extends FlxBasic * @return Whether the object is on screen or not. */ public function isOnScreen(?camera:FlxCamera):Bool + { + return isColliderOnScreen(camera); + } + + /** + * Check and see if this object's hitbox is currently on screen. + * + * @param camera Specify which game camera you want. + * If `null`, it will just grab the first global camera. + * @return Whether the object is on screen or not. + */ + public function isColliderOnScreen(?camera:FlxCamera):Bool { if (camera == null) camera = FlxG.camera; @@ -1270,7 +1282,7 @@ class FlxObject extends FlxBasic */ public function drawDebugOnCamera(camera:FlxCamera):Void { - if (!camera.visible || !camera.exists || !isOnScreen(camera)) + if (!camera.visible || !camera.exists || !isColliderOnScreen(camera)) return; var rect = getBoundingBox(camera); diff --git a/flixel/FlxStrip.hx b/flixel/FlxStrip.hx index 8647e1642a..f89a9271e7 100644 --- a/flixel/FlxStrip.hx +++ b/flixel/FlxStrip.hx @@ -1,6 +1,13 @@ package flixel; -import flixel.graphics.tile.FlxDrawTrianglesItem.DrawData; +import flixel.graphics.tile.FlxDrawTriangleData; +import flixel.graphics.tile.FlxDrawTrianglesItem; +import flixel.math.FlxPoint; +import flixel.util.FlxColor; +import flixel.util.FlxDestroyUtil; +import openfl.Vector; +import openfl.display.Graphics; +import openfl.display.GraphicsPathCommand; /** * A very basic rendering component which uses `drawTriangles()`. @@ -15,39 +22,78 @@ import flixel.graphics.tile.FlxDrawTrianglesItem.DrawData; */ class FlxStrip extends FlxSprite { + /** + * List of triangles + */ + public var triangles:FlxDrawTriangleData; + /** * A `Vector` of floats where each pair of numbers is treated as a coordinate location (an x, y pair). */ - public var vertices:DrawData = new DrawData(); + // @:deprecated("FlxStrip's vertices is deprecated, use triangles.vertices, instead") // TODO + public var vertices(get, set):DrawData; + inline function get_vertices() return triangles.vertices; + inline function set_vertices(value:DrawData) return triangles.vertices = value; /** * A `Vector` of integers or indexes, where every three indexes define a triangle. */ - public var indices:DrawData = new DrawData(); + // @:deprecated("FlxStrip's indices is deprecated, use triangles.indices, instead") // TODO + public var indices(get, set):DrawData; + inline function get_indices() return triangles.indices; + inline function set_indices(value:DrawData) return triangles.indices = value; /** * A `Vector` of normalized coordinates used to apply texture mapping. */ - public var uvtData:DrawData = new DrawData(); + // @:deprecated("FlxStrip's uvtData is deprecated, use triangles.uvs, instead") // TODO + public var uvtData(get, set):DrawData; + inline function get_uvtData() return triangles.uvs; + inline function set_uvtData(value:DrawData) return triangles.uvs = value; - public var colors:DrawData = new DrawData(); + // @:deprecated("FlxStrip's color is deprecated, use triangles.colors, instead") // TODO + public var colors(get, set):DrawData; + inline function get_colors() return triangles.colors; + inline function set_colors(value:DrawData) return triangles.colors = value; - public var repeat:Bool = false; + // @:deprecated("FlxStrip's repeat is deprecated, use triangles.repeat, instead") // TODO + public var repeat(get, set):Bool; + inline function get_repeat() return triangles.repeat; + inline function set_repeat(value:Bool) return triangles.repeat = value; + + #if FLX_DEBUG + /** + * Overriding this will force a specific color to be used when debug drawing triangles + */ + public var debugTrianglesColor:FlxColor = FlxColor.BLUE; + + /** + * If true, draws the triangles of this strip, unless ignoreDrawDebug is true + */ + public var drawDebugTriangles:Bool = false; + + /** + * If true, draws the collision bounding box of this strip, unless ignoreDrawDebug is true + */ + public var drawDebugCollider:Bool = true; + #end + + public function new(x = 0.0, y = 0.0, ?graphic) + { + triangles = new FlxDrawTriangleData(); + super(x, y, graphic); + } override public function destroy():Void { - vertices = null; - indices = null; - uvtData = null; - colors = null; - + triangles = FlxDestroyUtil.destroy(triangles); super.destroy(); } // TODO: check this for cases when zoom is less than initial zoom... override public function draw():Void { - if (alpha == 0 || graphic == null || vertices == null) + if (alpha == 0 || graphic == null || triangles.vertices == null) return; for (camera in cameras) @@ -57,10 +103,64 @@ class FlxStrip extends FlxSprite getScreenPosition(_point, camera).subtractPoint(offset); #if !flash - camera.drawTriangles(graphic, vertices, indices, uvtData, colors, _point, blend, repeat, antialiasing, colorTransform, shader); + camera.drawTriangleData(graphic, triangles, _point, blend, repeat, antialiasing, colorTransform, shader); #else - camera.drawTriangles(graphic, vertices, indices, uvtData, colors, _point, blend, repeat, antialiasing); + camera.drawTriangleData(graphic, triangles, _point, blend, repeat, antialiasing); #end } + + #if FLX_DEBUG + if (FlxG.debugger.drawDebug) + drawDebug(); + #end + } + + #if FLX_DEBUG + override function drawDebugOnCamera(camera:FlxCamera) + { + final boundsOnScreen = isColliderOnScreen(camera); + final graphicOnScreen = isOnScreen(camera); + if (!camera.visible || !camera.exists || !(boundsOnScreen || graphicOnScreen)) + return; + + final gfx:Graphics = beginDrawDebug(camera); + if (boundsOnScreen && drawDebugCollider) + { + final rect = getBoundingBox(camera); + drawDebugBoundingBox(gfx, rect, allowCollisions, immovable); + } + + if (graphicOnScreen && drawDebugTriangles) + { + final pos = getScreenPosition(camera); + drawDebugTrianglesToBuffer(gfx, pos); + } + + endDrawDebug(camera); + } + + function drawDebugTrianglesToBuffer(gfx:Graphics, screenPos:FlxPoint) + { + gfx.lineStyle(1, debugTrianglesColor, 0.5); + // draw a path for each triangle + final numTriangles = Std.int(triangles.indices.length / 3); + final commands = new Vector(); + final data = new Vector(); + for (i in 0...numTriangles) + { + // add triangle vertices 0, 1, 2, 0 + commands.push(MOVE_TO); + commands.push(LINE_TO); + commands.push(LINE_TO); + commands.push(LINE_TO); + for (j in 0...4) + { + final index = triangles.indices[i * 3 + (j % 3)]; + data.push(screenPos.x + triangles.vertices[index * 2 + 0]); + data.push(screenPos.y + triangles.vertices[index * 2 + 1]); + } + } + gfx.drawPath(commands, data); } + #end } diff --git a/flixel/graphics/tile/FlxDrawTriangleData.hx b/flixel/graphics/tile/FlxDrawTriangleData.hx new file mode 100644 index 0000000000..6112cdb3f8 --- /dev/null +++ b/flixel/graphics/tile/FlxDrawTriangleData.hx @@ -0,0 +1,47 @@ +package flixel.graphics.tile; + +import flixel.graphics.tile.FlxDrawTrianglesItem; +import flixel.util.FlxDestroyUtil; + +class FlxDrawTriangleData implements IFlxDestroyable +{ + /** + * A `Vector` of floats where each pair of numbers is treated as a coordinate location (an x, y pair). + */ + public var vertices = new DrawData(); + + /** + * A `Vector` of integers or indexes, where every three indexes define a triangle. + */ + public var indices = new DrawData(); + + /** + * A `Vector` of normalized coordinates used to apply texture mapping. + */ + public var uvs = new DrawData(); + + public var colors = new DrawData(); + + /** + * Whether the image is tiled + */ + public var repeat:Bool = false; + + public function new () {} + + public function destroy() + { + vertices = null; + indices = null; + uvs = null; + colors = null; + } + + public function clear() + { + vertices = new DrawData(); + uvs = new DrawData(); + indices = new DrawData(); + colors = new DrawData(); + } +} \ No newline at end of file diff --git a/flixel/graphics/tile/FlxDrawTrianglesItem.hx b/flixel/graphics/tile/FlxDrawTrianglesItem.hx index 704d281ac5..17880a89a4 100644 --- a/flixel/graphics/tile/FlxDrawTrianglesItem.hx +++ b/flixel/graphics/tile/FlxDrawTrianglesItem.hx @@ -2,7 +2,7 @@ package flixel.graphics.tile; import flixel.FlxCamera; import flixel.graphics.frames.FlxFrame; -import flixel.graphics.tile.FlxDrawBaseItem.FlxDrawItemType; +import flixel.graphics.tile.FlxDrawBaseItem; import flixel.math.FlxMatrix; import flixel.math.FlxPoint; import flixel.math.FlxRect; @@ -88,14 +88,6 @@ class FlxDrawTrianglesItem extends FlxDrawBaseItem camera.canvas.graphics.drawTriangles(vertices, indices, uvtData, TriangleCulling.NONE, (colored) ? colors : null, blending); #end camera.canvas.graphics.endFill(); - #if FLX_DEBUG - if (FlxG.debugger.drawDebug) - { - var gfx:Graphics = camera.debugLayer.graphics; - gfx.lineStyle(1, FlxColor.BLUE, 0.5); - gfx.drawTriangles(vertices, indices, uvtData); - } - #end super.render(camera); } @@ -136,7 +128,141 @@ class FlxDrawTrianglesItem extends FlxDrawBaseItem #end } - public function addTriangles(vertices:DrawData, indices:DrawData, uvtData:DrawData, ?colors:DrawData, ?position:FlxPoint, + public function addTriangleData(triangles:FlxDrawTriangleData, ?position:FlxPoint, ?cameraBounds:FlxRect + #if !flash , ?transform:ColorTransform #end):Void + { + if (position == null) + position = point.set(); + + if (cameraBounds == null) + cameraBounds = rect.set(0, 0, FlxG.width, FlxG.height); + + var verticesLength:Int = triangles.vertices.length; + var prevVerticesLength:Int = this.vertices.length; + var numberOfVertices:Int = Std.int(verticesLength / 2); + var prevIndicesLength:Int = this.indices.length; + var prevUVTDataLength:Int = this.uvtData.length; + var prevColorsLength:Int = this.colors.length; + var prevNumberOfVertices:Int = this.numVertices; + + var tempX:Float, tempY:Float; + var i:Int = 0; + var currentVertexPosition:Int = prevVerticesLength; + + while (i < verticesLength) + { + tempX = position.x + triangles.vertices[i]; + tempY = position.y + triangles.vertices[i + 1]; + + this.vertices[currentVertexPosition++] = tempX; + this.vertices[currentVertexPosition++] = tempY; + + if (i == 0) + { + bounds.set(tempX, tempY, 0, 0); + } + else + { + inflateBounds(bounds, tempX, tempY); + } + + i += 2; + } + + if (!cameraBounds.overlaps(bounds)) + { + this.vertices.splice(this.vertices.length - verticesLength, verticesLength); + } + else + { + var uvtDataLength:Int = triangles.uvs.length; + for (i in 0...uvtDataLength) + { + this.uvtData[prevUVTDataLength + i] = triangles.uvs[i]; + } + + var indicesLength:Int = triangles.indices.length; + for (i in 0...indicesLength) + { + this.indices[prevIndicesLength + i] = triangles.indices[i] + prevNumberOfVertices; + } + + if (colored) + { + for (i in 0...numberOfVertices) + { + this.colors[prevColorsLength + i] = triangles.colors[i]; + } + + colorsPosition += numberOfVertices; + } + + verticesPosition += verticesLength; + indicesPosition += indicesLength; + } + + position.putWeak(); + cameraBounds.putWeak(); + + #if !flash + for (_ in 0...numTriangles) + { + alphas.push(transform != null ? transform.alphaMultiplier : 1.0); + alphas.push(transform != null ? transform.alphaMultiplier : 1.0); + alphas.push(transform != null ? transform.alphaMultiplier : 1.0); + } + + if (colored || hasColorOffsets) + { + if (colorMultipliers == null) + colorMultipliers = []; + + if (colorOffsets == null) + colorOffsets = []; + + for (_ in 0...(numTriangles * 3)) + { + if(transform != null) + { + colorMultipliers.push(transform.redMultiplier); + colorMultipliers.push(transform.greenMultiplier); + colorMultipliers.push(transform.blueMultiplier); + + colorOffsets.push(transform.redOffset); + colorOffsets.push(transform.greenOffset); + colorOffsets.push(transform.blueOffset); + colorOffsets.push(transform.alphaOffset); + } + else + { + colorMultipliers.push(1); + colorMultipliers.push(1); + colorMultipliers.push(1); + + colorOffsets.push(0); + colorOffsets.push(0); + colorOffsets.push(0); + colorOffsets.push(0); + } + + colorMultipliers.push(1); + } + } + #end + } + + // @:deprecated("FlxCamera's addTriangles is deprecated use addTriangleData, instead") // TODO + public inline function addTriangles(vertices:DrawData, indices:DrawData, uvtData:DrawData, ?colors:DrawData, ?position:FlxPoint, + ?cameraBounds:FlxRect #if !flash , ?transform:ColorTransform #end):Void + { + addTrianglesHelper(vertices, indices, uvtData, colors, position, cameraBounds #if !flash , transform #end); + } + + /** + * Used to avoid deprecation warnings from other deprecated methods + */ + @:allow(flixel.FlxCamera.drawTriangles) + function addTrianglesHelper(vertices:DrawData, indices:DrawData, uvtData:DrawData, ?colors:DrawData, ?position:FlxPoint, ?cameraBounds:FlxRect #if !flash , ?transform:ColorTransform #end):Void { if (position == null)