mirror of
https://github.com/ninjamuffin99/Funkin.git
synced 2024-08-20 07:25:59 +00:00
added GrabbableCamera
This commit is contained in:
parent
9fc3a46b48
commit
ab7ba485cb
43
source/funkin/graphics/framebuffer/BitmapDataTools.hx
Normal file
43
source/funkin/graphics/framebuffer/BitmapDataTools.hx
Normal file
|
@ -0,0 +1,43 @@
|
|||
package funkin.graphics.framebuffer;
|
||||
|
||||
import flixel.FlxG;
|
||||
import openfl.display.Bitmap;
|
||||
import openfl.display.BitmapData;
|
||||
import openfl.display.Sprite;
|
||||
import openfl.filters.BitmapFilter;
|
||||
|
||||
/**
|
||||
* Provides cool stuff for `BitmapData`s that have a hardware texture internally.
|
||||
*/
|
||||
class BitmapDataTools
|
||||
{
|
||||
/**
|
||||
* Applies a bitmap filter to a bitmap immediately. The bitmap filter may refer
|
||||
* the bitmap itself as a shader input.
|
||||
* @param bitmap the bitmap data
|
||||
* @param filter the bitmap filter
|
||||
*/
|
||||
public static function applyFilter(bitmap:BitmapData, filter:BitmapFilter):Void
|
||||
{
|
||||
if (bitmap.readable)
|
||||
{
|
||||
FlxG.log.error('do not use `BitmapDataTools` for non-GPU bitmaps!');
|
||||
}
|
||||
// man, allow me to use anon structuers for local vars!
|
||||
static var cache:{sprite:Sprite, bitmap:Bitmap} = null;
|
||||
if (cache == null)
|
||||
{
|
||||
final sprite = new Sprite();
|
||||
final bitmap = new Bitmap();
|
||||
sprite.addChild(bitmap);
|
||||
cache =
|
||||
{
|
||||
sprite: sprite,
|
||||
bitmap: bitmap
|
||||
}
|
||||
}
|
||||
cache.bitmap.bitmapData = bitmap;
|
||||
cache.sprite.filters = [filter];
|
||||
bitmap.draw(cache.sprite);
|
||||
}
|
||||
}
|
42
source/funkin/graphics/framebuffer/FixedBitmapData.hx
Normal file
42
source/funkin/graphics/framebuffer/FixedBitmapData.hx
Normal file
|
@ -0,0 +1,42 @@
|
|||
package funkin.graphics.framebuffer;
|
||||
|
||||
import openfl.display.BitmapData;
|
||||
import openfl.display.DisplayObject;
|
||||
import openfl.display.DisplayObjectContainer;
|
||||
import openfl.display.IBitmapDrawable;
|
||||
import openfl.display.OpenGLRenderer;
|
||||
import openfl.display3D.textures.TextureBase;
|
||||
|
||||
/**
|
||||
* `BitmapData` is kinda broken so I fixed it.
|
||||
*/
|
||||
@:access(openfl.display3D.textures.TextureBase)
|
||||
@:access(openfl.display.OpenGLRenderer)
|
||||
class FixedBitmapData extends BitmapData
|
||||
{
|
||||
override function __drawGL(source:IBitmapDrawable, renderer:OpenGLRenderer):Void
|
||||
{
|
||||
if (Std.isOfType(source, DisplayObject))
|
||||
{
|
||||
final object:DisplayObjectContainer = cast source;
|
||||
renderer.__stage = object.stage;
|
||||
}
|
||||
super.__drawGL(source, renderer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Never use `BitmapData.fromTexture`, always use this.
|
||||
* @param texture the texture
|
||||
* @return the bitmap data
|
||||
*/
|
||||
public static function fromTexture(texture:TextureBase):FixedBitmapData
|
||||
{
|
||||
if (texture == null) return null;
|
||||
final bitmapData = new FixedBitmapData(texture.__width, texture.__height, true, 0);
|
||||
bitmapData.readable = false;
|
||||
bitmapData.__texture = texture;
|
||||
bitmapData.__textureContext = texture.__textureContext;
|
||||
bitmapData.image = null;
|
||||
return bitmapData;
|
||||
}
|
||||
}
|
|
@ -1,12 +1,12 @@
|
|||
package funkin.graphics.framebuffer;
|
||||
|
||||
import openfl.geom.Rectangle;
|
||||
import openfl.geom.Matrix;
|
||||
import openfl.display.BitmapData;
|
||||
import flixel.util.FlxColor;
|
||||
import flixel.FlxCamera;
|
||||
import flixel.util.FlxColor;
|
||||
import openfl.Lib;
|
||||
import openfl.display.BitmapData;
|
||||
import openfl.display3D.textures.TextureBase;
|
||||
import openfl.geom.Matrix;
|
||||
import openfl.geom.Rectangle;
|
||||
|
||||
/**
|
||||
* A single frame buffer. Used by `FrameBufferManager`.
|
||||
|
@ -27,7 +27,6 @@ class FrameBuffer
|
|||
camera = new FlxCamera();
|
||||
camera.antialiasing = false;
|
||||
camera.bgColor = FlxColor.TRANSPARENT;
|
||||
camera.flashSprite.cacheAsBitmap = true;
|
||||
@:privateAccess camera.flashSprite.stage = Lib.current.stage;
|
||||
}
|
||||
|
||||
|
@ -41,7 +40,7 @@ class FrameBuffer
|
|||
{
|
||||
dispose();
|
||||
texture = Lib.current.stage.context3D.createTexture(width, height, BGRA, true);
|
||||
bitmap = BitmapData.fromTexture(texture);
|
||||
bitmap = FixedBitmapData.fromTexture(texture);
|
||||
camera.bgColor = bgColor;
|
||||
}
|
||||
|
||||
|
@ -108,7 +107,7 @@ class FrameBuffer
|
|||
bitmap.dispose();
|
||||
bitmap = null;
|
||||
}
|
||||
spriteCopies.clear();
|
||||
spriteCopies.resize(0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
package funkin.graphics.framebuffer;
|
||||
|
||||
import flixel.FlxCamera;
|
||||
import flixel.FlxG;
|
||||
import flixel.FlxSprite;
|
||||
import flixel.util.FlxColor;
|
||||
import openfl.display.BitmapData;
|
||||
import flixel.FlxSprite;
|
||||
import flixel.FlxCamera;
|
||||
|
||||
/**
|
||||
* Manages frame buffers and gives access to each frame buffer.
|
||||
|
@ -56,7 +57,7 @@ class FrameBufferManager
|
|||
}
|
||||
|
||||
/**
|
||||
* Call this before everything is drawn.
|
||||
* Call this before drawing anything.
|
||||
*/
|
||||
public function lock():Void
|
||||
{
|
||||
|
|
161
source/funkin/graphics/framebuffer/GrabbableCamera.hx
Normal file
161
source/funkin/graphics/framebuffer/GrabbableCamera.hx
Normal file
|
@ -0,0 +1,161 @@
|
|||
package funkin.graphics.framebuffer;
|
||||
|
||||
import flixel.FlxCamera;
|
||||
import flixel.FlxG;
|
||||
import flixel.graphics.FlxGraphic;
|
||||
import flixel.graphics.frames.FlxFrame;
|
||||
import flixel.math.FlxMatrix;
|
||||
import flixel.math.FlxRect;
|
||||
import flixel.system.FlxAssets.FlxShader;
|
||||
import openfl.Lib;
|
||||
import openfl.display.BitmapData;
|
||||
import openfl.display3D.textures.TextureBase;
|
||||
|
||||
/**
|
||||
* A camera, but grabbable.
|
||||
*/
|
||||
@:access(openfl.display.DisplayObject)
|
||||
@:access(openfl.display.BitmapData)
|
||||
@:access(openfl.display3D.Context3D)
|
||||
@:access(openfl.display3D.textures.TextureBase)
|
||||
@:access(flixel.graphics.FlxGraphic)
|
||||
@:access(flixel.graphics.frames.FlxFrame)
|
||||
class GrabbableCamera extends FlxCamera
|
||||
{
|
||||
final grabbed:Array<BitmapData> = [];
|
||||
final texturePool:Array<TextureBase> = [];
|
||||
final defaultShader:FlxShader = new FlxShader();
|
||||
|
||||
final bgTexture:TextureBase;
|
||||
final bgBitmap:BitmapData;
|
||||
final bgFrame:FlxFrame;
|
||||
|
||||
public function new(x:Int = 0, y:Int = 0, width:Int = 0, height:Int = 0, zoom:Float = 0)
|
||||
{
|
||||
super(x, y, width, height, zoom);
|
||||
bgTexture = pickTexture(width, height);
|
||||
bgBitmap = FixedBitmapData.fromTexture(bgTexture);
|
||||
bgFrame = new FlxFrame(new FlxGraphic('', null));
|
||||
bgFrame.parent.bitmap = bgBitmap;
|
||||
bgFrame.frame = new FlxRect();
|
||||
}
|
||||
|
||||
/**
|
||||
* Grabs the camera screen and returns it as a `BitmapData`. The returned bitmap
|
||||
* will not be referred by the camera, so changing it will not affect the scene.
|
||||
* @param applyFilters if this is `true`, the camera's filters will be applied to the grabbed bitmap
|
||||
* @return the grabbed bitmap data
|
||||
*/
|
||||
public function grabScreen(applyFilters:Bool):BitmapData
|
||||
{
|
||||
final texture = pickTexture(width, height);
|
||||
final bitmap = FixedBitmapData.fromTexture(texture);
|
||||
squashTo(bitmap, applyFilters);
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
function squashTo(bitmap:BitmapData, applyFilters:Bool):Void
|
||||
{
|
||||
static final matrix = new FlxMatrix();
|
||||
|
||||
// resize the background bitmap if needed
|
||||
if (bgTexture.__width != width || bgTexture.__height != height)
|
||||
{
|
||||
resizeTexture(bgTexture, width, height);
|
||||
bgBitmap.__resize(width, height);
|
||||
bgFrame.parent.bitmap = bgBitmap;
|
||||
}
|
||||
|
||||
// grab the bitmap
|
||||
render();
|
||||
bitmap.fillRect(bitmap.rect, 0);
|
||||
matrix.setTo(1, 0, 0, 1, flashSprite.x, flashSprite.y);
|
||||
if (applyFilters)
|
||||
{
|
||||
bitmap.draw(flashSprite, matrix);
|
||||
}
|
||||
else
|
||||
{
|
||||
final tmp = flashSprite.filters;
|
||||
flashSprite.filters = null;
|
||||
bitmap.draw(flashSprite, matrix);
|
||||
flashSprite.filters = tmp;
|
||||
}
|
||||
|
||||
// also copy to the background bitmap
|
||||
bgBitmap.fillRect(bgBitmap.rect, 0);
|
||||
bgBitmap.draw(bitmap);
|
||||
|
||||
// clear graphics data
|
||||
super.clearDrawStack();
|
||||
canvas.graphics.clear();
|
||||
|
||||
// render the background bitmap
|
||||
bgFrame.frame.set(0, 0, width, height);
|
||||
matrix.setTo(viewWidth / width, 0, 0, viewHeight / height, viewMarginLeft, viewMarginTop);
|
||||
drawPixels(bgFrame, matrix);
|
||||
}
|
||||
|
||||
function resizeTexture(texture:TextureBase, width:Int, height:Int):Void
|
||||
{
|
||||
texture.__width = width;
|
||||
texture.__height = height;
|
||||
final context = texture.__context;
|
||||
final gl = context.gl;
|
||||
context.__bindGLTexture2D(texture.__textureID);
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, texture.__internalFormat, width, height, 0, texture.__format, gl.UNSIGNED_BYTE, null);
|
||||
context.__bindGLTexture2D(null);
|
||||
}
|
||||
|
||||
override function destroy():Void
|
||||
{
|
||||
super.destroy();
|
||||
disposeTextures();
|
||||
}
|
||||
|
||||
override function clearDrawStack():Void
|
||||
{
|
||||
super.clearDrawStack();
|
||||
// also clear grabbed bitmaps
|
||||
for (bitmap in grabbed)
|
||||
{
|
||||
texturePool.push(@:privateAccess bitmap.__texture);
|
||||
bitmap.dispose();
|
||||
}
|
||||
grabbed.clear();
|
||||
}
|
||||
|
||||
function pickTexture(width:Int, height:Int):TextureBase
|
||||
{
|
||||
// zero-sized textures will be problematic
|
||||
width = width < 1 ? 1 : width;
|
||||
height = height < 1 ? 1 : height;
|
||||
if (texturePool.length > 0)
|
||||
{
|
||||
final res = texturePool.pop();
|
||||
if (res.__width != width || res.__height != height)
|
||||
{
|
||||
resizeTexture(res, width, height);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
return Lib.current.stage.context3D.createTexture(width, height, BGRA, true);
|
||||
}
|
||||
|
||||
function disposeTextures():Void
|
||||
{
|
||||
trace('disposing textures');
|
||||
for (bitmap in grabbed)
|
||||
{
|
||||
bitmap.dispose();
|
||||
}
|
||||
grabbed.clear();
|
||||
for (texture in texturePool)
|
||||
{
|
||||
texture.dispose();
|
||||
}
|
||||
texturePool.resize(0);
|
||||
bgTexture.dispose();
|
||||
bgBitmap.dispose();
|
||||
}
|
||||
}
|
|
@ -61,21 +61,12 @@ class RuntimeRainShader extends RuntimePostEffectShader
|
|||
return puddleY = value;
|
||||
}
|
||||
|
||||
public var groundMap(default, set):BitmapData;
|
||||
public var blurredScreen(default, set):BitmapData;
|
||||
|
||||
function set_groundMap(value:BitmapData):BitmapData
|
||||
function set_blurredScreen(value:BitmapData):BitmapData
|
||||
{
|
||||
this.setBitmapData('uGroundMap', value);
|
||||
// this.setFloat2('uPuddleTextureSize', value.width, value.height);
|
||||
return groundMap = value;
|
||||
}
|
||||
|
||||
public var lightMap(default, set):BitmapData;
|
||||
|
||||
function set_lightMap(value:BitmapData):BitmapData
|
||||
{
|
||||
this.setBitmapData('uLightMap', value);
|
||||
return lightMap = value;
|
||||
this.setBitmapData('uBlurredScreen', value);
|
||||
return blurredScreen = value;
|
||||
}
|
||||
|
||||
public var mask(default, set):BitmapData;
|
||||
|
|
|
@ -411,7 +411,7 @@ class PlayState extends MusicBeatSubState
|
|||
/**
|
||||
* The camera which contains, and controls visibility of, the stage and characters.
|
||||
*/
|
||||
public var camGame:FlxCamera;
|
||||
public var camGame:SwagCamera;
|
||||
|
||||
/**
|
||||
* The camera which contains, and controls visibility of, a video cutscene.
|
||||
|
|
|
@ -3,6 +3,7 @@ package funkin.play.stage;
|
|||
import funkin.graphics.framebuffer.FrameBufferManager;
|
||||
import flixel.util.FlxColor;
|
||||
import funkin.graphics.framebuffer.SpriteCopy;
|
||||
import funkin.graphics.framebuffer.GrabbableCamera;
|
||||
import flixel.FlxCamera;
|
||||
import flixel.FlxSprite;
|
||||
import flixel.group.FlxSpriteGroup;
|
||||
|
@ -78,7 +79,7 @@ class Stage extends FlxSpriteGroup implements IPlayStateScriptedClass
|
|||
{
|
||||
if (frameBufferMan != null) frameBufferMan.dispose();
|
||||
frameBufferMan = new FrameBufferManager(FlxG.camera);
|
||||
onFrameBufferCreate();
|
||||
setupFrameBuffers();
|
||||
|
||||
buildStage();
|
||||
this.refresh();
|
||||
|
@ -696,7 +697,10 @@ class Stage extends FlxSpriteGroup implements IPlayStateScriptedClass
|
|||
debugIconGroup = null;
|
||||
}
|
||||
|
||||
frameBufferMan.dispose();
|
||||
if (frameBufferMan != null)
|
||||
{
|
||||
frameBufferMan.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -751,16 +755,50 @@ class Stage extends FlxSpriteGroup implements IPlayStateScriptedClass
|
|||
|
||||
override function draw():Void
|
||||
{
|
||||
frameBufferMan.lock();
|
||||
if (frameBufferMan != null)
|
||||
{
|
||||
frameBufferMan.lock();
|
||||
}
|
||||
super.draw();
|
||||
frameBufferMan.unlock();
|
||||
if (frameBufferMan != null)
|
||||
{
|
||||
frameBufferMan.unlock();
|
||||
}
|
||||
frameBuffersUpdated();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the frame buffer manager is ready.
|
||||
* Create frame buffers inside this method.
|
||||
*/
|
||||
public function onFrameBufferCreate():Void {}
|
||||
function setupFrameBuffers():Void {}
|
||||
|
||||
/**
|
||||
* Called when all the frame buffers are updated. If you need any
|
||||
* frame buffers before `grabScreen()`, make sure you
|
||||
* grab the screen inside this method since it immediately uses the
|
||||
* frame buffers.
|
||||
*/
|
||||
function frameBuffersUpdated():Void {}
|
||||
|
||||
/**
|
||||
* Grabs the current screen and returns it as a bitmap data. You can sefely modify it.
|
||||
* @param applyFilters if this is `true`, the filters set to the camera will be applied to the resulting bitmap
|
||||
* @return the grabbed screen
|
||||
*/
|
||||
function grabScreen(applyFilters:Bool):BitmapData
|
||||
{
|
||||
if (Std.isOfType(FlxG.camera, GrabbableCamera))
|
||||
{
|
||||
final cam:GrabbableCamera = cast FlxG.camera;
|
||||
return cam.grabScreen(applyFilters);
|
||||
}
|
||||
else
|
||||
{
|
||||
FlxG.log.error('cannot grab the screen: the main camera is not grabbable');
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public function onScriptEvent(event:ScriptEvent) {}
|
||||
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
package funkin.ui;
|
||||
|
||||
import funkin.graphics.framebuffer.GrabbableCamera;
|
||||
import flixel.FlxCamera;
|
||||
import flixel.FlxSprite;
|
||||
import flixel.math.FlxPoint;
|
||||
import funkin.util.MathUtil;
|
||||
|
||||
class SwagCamera extends FlxCamera
|
||||
class SwagCamera extends GrabbableCamera
|
||||
{
|
||||
/**
|
||||
* properly follow framerate
|
||||
|
|
Loading…
Reference in a new issue