Remove old library modification codes

This commit is contained in:
Ralty
2026-03-01 14:15:02 +07:00
parent 5a176e0ccc
commit 143cc447c8
23 changed files with 0 additions and 12629 deletions
@@ -1,864 +0,0 @@
package openfl.display;
#if !flash
import openfl.display._internal.Context3DGraphics;
import openfl.display.Bitmap;
import openfl.display.DisplayObject;
import openfl.display.Tilemap;
import openfl.events.EventDispatcher;
import openfl.events.RenderEvent;
import openfl.geom.ColorTransform;
import openfl.geom.Matrix;
import openfl.geom.Point;
import openfl.geom.Rectangle;
import openfl.text.TextField;
#if lime
import lime._internal.graphics.ImageCanvasUtil; // TODO
import lime.graphics.cairo.Cairo;
import lime.graphics.RenderContext;
import lime.graphics.RenderContextType;
#end
#if !openfl_debug
@:fileXml('tags="haxe,release"')
@:noDebug
#end
@:access(openfl.display._internal.Context3DGraphics)
@:access(lime.graphics.ImageBuffer)
@:access(openfl.display.Bitmap)
@:access(openfl.display.BitmapData)
@:access(openfl.display.DisplayObject)
@:access(openfl.display.Graphics)
@:access(openfl.display.Tilemap)
@:access(openfl.display3D.Context3D)
@:access(openfl.events.RenderEvent)
@:access(openfl.filters.BitmapFilter)
@:access(openfl.geom.ColorTransform)
@:access(openfl.geom.Rectangle)
@:access(openfl.geom.Transform)
@:access(openfl.text.TextField)
@:allow(openfl.display._internal)
@:allow(openfl.display)
@:allow(openfl.text)
class DisplayObjectRenderer extends EventDispatcher
{
@:noCompletion private var __allowSmoothing:Bool;
@:noCompletion private var __blendMode:BlendMode;
@:noCompletion private var __cleared:Bool;
@SuppressWarnings("checkstyle:Dynamic") @:noCompletion private var __context:#if lime RenderContext #else Dynamic #end;
@:noCompletion private var __overrideBlendMode:BlendMode;
@:noCompletion private var __pixelRatio:Float;
@:noCompletion private var __roundPixels:Bool;
@:noCompletion private var __stage:Stage;
@:noCompletion private var __tempColorTransform:ColorTransform;
@:noCompletion private var __transparent:Bool;
@SuppressWarnings("checkstyle:Dynamic") @:noCompletion private var __type:#if lime RenderContextType #else Dynamic #end;
@:noCompletion private var __worldAlpha:Float;
@:noCompletion private var __worldColorTransform:ColorTransform;
@:noCompletion private var __worldTransform:Matrix;
@:noCompletion private function new()
{
super();
__allowSmoothing = true;
__pixelRatio = 1;
__tempColorTransform = new ColorTransform();
__worldAlpha = 1;
}
@:noCompletion private function __clear():Void {}
@:noCompletion private function __getAlpha(value:Float):Float
{
return value * __worldAlpha;
}
@:noCompletion private function __getColorTransform(value:ColorTransform):ColorTransform
{
if (__worldColorTransform != null)
{
__tempColorTransform.__copyFrom(__worldColorTransform);
__tempColorTransform.__combine(value);
return __tempColorTransform;
}
else
{
return value;
}
}
@:noCompletion private function __popMask():Void {}
@:noCompletion private function __popMaskObject(object:DisplayObject, handleScrollRect:Bool = true):Void {}
@:noCompletion private function __popMaskRect():Void {}
@:noCompletion private function __pushMask(mask:DisplayObject):Void {}
@:noCompletion private function __pushMaskObject(object:DisplayObject, handleScrollRect:Bool = true):Void {}
@:noCompletion private function __pushMaskRect(rect:Rectangle, transform:Matrix):Void {}
@:noCompletion private function __render(object:IBitmapDrawable):Void {}
@:noCompletion private function __renderEvent(displayObject:DisplayObject):Void
{
var renderer = this;
#if lime
if (displayObject.__customRenderEvent != null && displayObject.__renderable)
{
displayObject.__customRenderEvent.allowSmoothing = renderer.__allowSmoothing;
displayObject.__customRenderEvent.objectMatrix.copyFrom(displayObject.__renderTransform);
displayObject.__customRenderEvent.objectColorTransform.__copyFrom(displayObject.__worldColorTransform);
displayObject.__customRenderEvent.renderer = renderer;
switch (renderer.__type)
{
case OPENGL:
if (!renderer.__cleared) renderer.__clear();
var renderer:OpenGLRenderer = cast renderer;
renderer.setShader(displayObject.__worldShader);
renderer.__context3D.__flushGL();
displayObject.__customRenderEvent.type = RenderEvent.RENDER_OPENGL;
case CAIRO:
displayObject.__customRenderEvent.type = RenderEvent.RENDER_CAIRO;
case DOM:
if (displayObject.stage != null && displayObject.__worldVisible)
{
displayObject.__customRenderEvent.type = RenderEvent.RENDER_DOM;
}
else
{
displayObject.__customRenderEvent.type = RenderEvent.CLEAR_DOM;
}
case CANVAS:
displayObject.__customRenderEvent.type = RenderEvent.RENDER_CANVAS;
default:
return;
}
renderer.__setBlendMode(displayObject.__worldBlendMode);
renderer.__pushMaskObject(displayObject);
displayObject.dispatchEvent(displayObject.__customRenderEvent);
renderer.__popMaskObject(displayObject);
if (renderer.__type == OPENGL)
{
var renderer:OpenGLRenderer = cast renderer;
renderer.setViewport();
}
}
#end
}
@:noCompletion private function __resize(width:Int, height:Int):Void {}
@:noCompletion private function __setBlendMode(value:BlendMode):Void {}
@:noCompletion private function __shouldCacheHardware(displayObject:DisplayObject, value:Null<Bool>):Null<Bool>
{
if (displayObject == null) return null;
switch (displayObject.__drawableType)
{
case SPRITE, STAGE:
if (value == true) return true;
value = __shouldCacheHardware_DisplayObject(displayObject, value);
if (value == true) return true;
if (displayObject.__children != null)
{
for (child in displayObject.__children)
{
value = __shouldCacheHardware_DisplayObject(child, value);
if (value == true) return true;
}
}
return value;
case TEXT_FIELD:
return value == true ? true : false;
case TILEMAP:
return true;
default:
return __shouldCacheHardware_DisplayObject(displayObject, value);
}
}
@:noCompletion private function __shouldCacheHardware_DisplayObject(displayObject:DisplayObject, value:Null<Bool>):Null<Bool>
{
if (value == true || displayObject.__filters != null) return true;
if (value == false || (displayObject.__graphics != null && !Context3DGraphics.isCompatible(displayObject.__graphics)))
{
return false;
}
return null;
}
@:noCompletion private function __updateCacheBitmap(displayObject:DisplayObject, force:Bool):Bool
{
if (displayObject == null) return false;
var renderer = this;
switch (displayObject.__drawableType)
{
case BITMAP:
var bitmap:Bitmap = cast displayObject;
// TODO: Handle filters without an intermediate draw
if (bitmap.__bitmapData == null
|| (bitmap.__filters == null #if lime && renderer.__type == OPENGL #end && bitmap.__cacheBitmap == null)) return false;
force = (bitmap.__bitmapData.image != null && bitmap.__bitmapData.image.version != bitmap.__imageVersion);
case TEXT_FIELD:
var textField:TextField = cast displayObject;
if (textField.__filters == null #if lime && renderer.__type == OPENGL #end && textField.__cacheBitmap == null
&& !textField.__domRender) return false;
if (force) textField.__renderDirty = true;
force = force || textField.__dirty;
case TILEMAP:
var tilemap:Tilemap = cast displayObject;
if (tilemap.__filters == null #if lime && renderer.__type == OPENGL #end && tilemap.__cacheBitmap == null) return false;
default:
}
#if lime
if (displayObject.__isCacheBitmapRender) return false;
#if openfl_disable_cacheasbitmap
return false;
#end
var colorTransform = ColorTransform.__pool.get();
colorTransform.__copyFrom(displayObject.__worldColorTransform);
if (renderer.__worldColorTransform != null) colorTransform.__combine(renderer.__worldColorTransform);
var updated = false;
// TODO: Do not force cacheAsBitmap on OpenGL once Scale-9 is properly supported in Context3DShape
if (displayObject.cacheAsBitmap
|| (renderer.__type != OPENGL && !colorTransform.__isDefault(true))
|| (renderer.__type == OPENGL && displayObject.scale9Grid != null))
{
var rect = null;
var needRender = (displayObject.__cacheBitmap == null
|| (displayObject.__renderDirty && (force || (displayObject.__children != null && displayObject.__children.length > 0)))
|| displayObject.opaqueBackground != displayObject.__cacheBitmapBackground);
var softwareDirty = needRender
|| (displayObject.__graphics != null && displayObject.__graphics.__softwareDirty)
|| !displayObject.__cacheBitmapColorTransform.__equals(colorTransform, true);
var hardwareDirty = needRender || (displayObject.__graphics != null && displayObject.__graphics.__hardwareDirty);
var renderType = renderer.__type;
if (softwareDirty || hardwareDirty)
{
#if !openfl_force_gl_cacheasbitmap
if (renderType == OPENGL)
{
if (#if !openfl_disable_gl_cacheasbitmap __shouldCacheHardware(displayObject, null) == false #else true #end)
{
#if (js && html5)
renderType = CANVAS;
#else
renderType = CAIRO;
#end
}
}
#end
if (softwareDirty && (renderType == CANVAS || renderType == CAIRO)) needRender = true;
if (hardwareDirty && renderType == OPENGL) needRender = true;
}
var updateTransform = (needRender || !displayObject.__cacheBitmap.__worldTransform.equals(displayObject.__worldTransform));
var hasFilters = #if !openfl_disable_filters displayObject.__filters != null #else false #end;
#if !openfl_enable_cacheasbitmap
if (renderer.__type == DOM && !hasFilters)
{
return false;
}
#end
if (hasFilters && !needRender)
{
for (filter in displayObject.__filters)
{
if (filter.__renderDirty)
{
needRender = true;
break;
}
}
}
if (displayObject.__cacheBitmapMatrix == null)
{
displayObject.__cacheBitmapMatrix = new Matrix();
}
var bitmapMatrix = (displayObject.__cacheAsBitmapMatrix != null ? displayObject.__cacheAsBitmapMatrix : displayObject.__renderTransform);
if (!needRender
&& (bitmapMatrix.a != displayObject.__cacheBitmapMatrix.a
|| bitmapMatrix.b != displayObject.__cacheBitmapMatrix.b
|| bitmapMatrix.c != displayObject.__cacheBitmapMatrix.c
|| bitmapMatrix.d != displayObject.__cacheBitmapMatrix.d))
{
needRender = true;
}
if (!needRender
&& renderer.__type != OPENGL
&& displayObject.__cacheBitmapData != null
&& displayObject.__cacheBitmapData.image != null
&& displayObject.__cacheBitmapData.image.version < displayObject.__cacheBitmapData.__textureVersion)
{
needRender = true;
}
// Ensure that cached bitmap is updated after changes to scrollRect
if (!needRender)
{
var current = displayObject;
while (current != null)
{
if (current.scrollRect != null)
{
// TODO: do we need to update transform if scroll rects haven't changed?
updateTransform = true;
break;
}
current = current.parent;
}
}
displayObject.__cacheBitmapMatrix.copyFrom(bitmapMatrix);
displayObject.__cacheBitmapMatrix.tx = 0;
displayObject.__cacheBitmapMatrix.ty = 0;
// TODO: Handle dimensions better if object has a scrollRect?
var bitmapWidth = 0, bitmapHeight = 0;
var filterWidth = 0, filterHeight = 0;
var offsetX = 0., offsetY = 0.;
#if (openfl_disable_hdpi || openfl_disable_hdpi_cacheasbitmap)
var pixelRatio = 1;
#else
var pixelRatio = __pixelRatio;
#end
if (updateTransform || needRender)
{
rect = Rectangle.__pool.get();
displayObject.__getFilterBounds(rect, displayObject.__cacheBitmapMatrix);
filterWidth = rect.width > 0 ? Math.floor(rect.width * pixelRatio) : 0;
filterHeight = rect.height > 0 ? Math.floor(rect.height * pixelRatio) : 0;
offsetX = rect.x > 0 ? Math.ceil(rect.x) : Math.floor(rect.x);
offsetY = rect.y > 0 ? Math.ceil(rect.y) : Math.floor(rect.y);
if (displayObject.__cacheBitmapData != null)
{
if (filterWidth > displayObject.__cacheBitmapData.width || filterHeight > displayObject.__cacheBitmapData.height)
{
bitmapWidth = Math.ceil(Math.max(filterWidth * 1.25, displayObject.__cacheBitmapData.width));
bitmapHeight = Math.ceil(Math.max(filterHeight * 1.25, displayObject.__cacheBitmapData.height));
needRender = true;
}
else
{
bitmapWidth = displayObject.__cacheBitmapData.width;
bitmapHeight = displayObject.__cacheBitmapData.height;
}
}
else
{
bitmapWidth = filterWidth;
bitmapHeight = filterHeight;
}
}
if (needRender)
{
updateTransform = true;
displayObject.__cacheBitmapBackground = displayObject.opaqueBackground;
if (filterWidth >= 0.5 && filterHeight >= 0.5)
{
var needsFill = (displayObject.opaqueBackground != null
&& (bitmapWidth != filterWidth || bitmapHeight != filterHeight));
var fillColor = displayObject.opaqueBackground != null ? (0xFF << 24) | displayObject.opaqueBackground : 0;
var bitmapColor = needsFill ? 0 : fillColor;
var allowFramebuffer = (renderer.__type == OPENGL);
if (displayObject.__cacheBitmapData == null
|| bitmapWidth > displayObject.__cacheBitmapData.width
|| bitmapHeight > displayObject.__cacheBitmapData.height)
{
displayObject.__cacheBitmapData = new BitmapData(bitmapWidth, bitmapHeight, true, bitmapColor);
if (displayObject.__cacheBitmap == null) displayObject.__cacheBitmap = new Bitmap();
displayObject.__cacheBitmap.__bitmapData = displayObject.__cacheBitmapData;
displayObject.__cacheBitmapRenderer = null;
}
else
{
displayObject.__cacheBitmapData.__fillRect(displayObject.__cacheBitmapData.rect, bitmapColor, allowFramebuffer);
}
if (needsFill)
{
rect.setTo(0, 0, filterWidth, filterHeight);
displayObject.__cacheBitmapData.__fillRect(rect, fillColor, allowFramebuffer);
}
}
else
{
ColorTransform.__pool.release(colorTransform);
displayObject.__cacheBitmap = null;
displayObject.__cacheBitmapData = null;
displayObject.__cacheBitmapData2 = null;
displayObject.__cacheBitmapData3 = null;
displayObject.__cacheBitmapRenderer = null;
if (displayObject.__drawableType == TEXT_FIELD)
{
var textField:TextField = cast displayObject;
if (textField.__cacheBitmap != null)
{
textField.__cacheBitmap.__renderTransform.tx -= textField.__offsetX * pixelRatio;
textField.__cacheBitmap.__renderTransform.ty -= textField.__offsetY * pixelRatio;
}
}
return true;
}
}
else
{
// Should we retain these longer?
displayObject.__cacheBitmapData = displayObject.__cacheBitmap.bitmapData;
displayObject.__cacheBitmapData2 = null;
displayObject.__cacheBitmapData3 = null;
}
if (updateTransform || needRender)
{
displayObject.__cacheBitmap.__worldTransform.copyFrom(displayObject.__worldTransform);
if (bitmapMatrix == displayObject.__renderTransform)
{
displayObject.__cacheBitmap.__renderTransform.identity();
displayObject.__cacheBitmap.__renderTransform.scale(1 / pixelRatio, 1 / pixelRatio);
displayObject.__cacheBitmap.__renderTransform.tx = displayObject.__renderTransform.tx + offsetX;
displayObject.__cacheBitmap.__renderTransform.ty = displayObject.__renderTransform.ty + offsetY;
}
else
{
displayObject.__cacheBitmap.__renderTransform.copyFrom(displayObject.__cacheBitmapMatrix);
displayObject.__cacheBitmap.__renderTransform.invert();
displayObject.__cacheBitmap.__renderTransform.concat(displayObject.__renderTransform);
displayObject.__cacheBitmap.__renderTransform.a *= 1 / pixelRatio;
displayObject.__cacheBitmap.__renderTransform.d *= 1 / pixelRatio;
displayObject.__cacheBitmap.__renderTransform.tx += offsetX;
displayObject.__cacheBitmap.__renderTransform.ty += offsetY;
}
}
displayObject.__cacheBitmap.smoothing = renderer.__allowSmoothing;
displayObject.__cacheBitmap.__renderable = displayObject.__renderable;
displayObject.__cacheBitmap.__worldAlpha = displayObject.__worldAlpha;
displayObject.__cacheBitmap.__worldBlendMode = displayObject.__worldBlendMode;
displayObject.__cacheBitmap.__worldShader = displayObject.__worldShader;
// displayObject.__cacheBitmap.__scrollRect = displayObject.__scrollRect;
// displayObject.__cacheBitmap.filters = displayObject.filters;
displayObject.__cacheBitmap.mask = displayObject.__mask;
if (needRender)
{
#if lime
if (displayObject.__cacheBitmapRenderer == null || renderType != displayObject.__cacheBitmapRenderer.__type)
{
if (renderType == OPENGL)
{
displayObject.__cacheBitmapRenderer = new OpenGLRenderer(cast(renderer, OpenGLRenderer).__context3D, displayObject.__cacheBitmapData);
}
else
{
if (displayObject.__cacheBitmapData.image == null)
{
var color = displayObject.opaqueBackground != null ? (0xFF << 24) | displayObject.opaqueBackground : 0;
displayObject.__cacheBitmapData = new BitmapData(bitmapWidth, bitmapHeight, true, color);
displayObject.__cacheBitmap.__bitmapData = displayObject.__cacheBitmapData;
}
#if (js && html5)
ImageCanvasUtil.convertToCanvas(displayObject.__cacheBitmapData.image);
displayObject.__cacheBitmapRenderer = new CanvasRenderer(displayObject.__cacheBitmapData.image.buffer.__srcContext);
#else
displayObject.__cacheBitmapRenderer = new CairoRenderer(new Cairo(displayObject.__cacheBitmapData.getSurface()));
#end
}
displayObject.__cacheBitmapRenderer.__worldTransform = new Matrix();
displayObject.__cacheBitmapRenderer.__worldColorTransform = new ColorTransform();
}
#else
return false;
#end
if (displayObject.__cacheBitmapColorTransform == null) displayObject.__cacheBitmapColorTransform = new ColorTransform();
displayObject.__cacheBitmapRenderer.__stage = displayObject.stage;
displayObject.__cacheBitmapRenderer.__allowSmoothing = renderer.__allowSmoothing;
displayObject.__cacheBitmapRenderer.__setBlendMode(NORMAL);
displayObject.__cacheBitmapRenderer.__worldAlpha = 1 / displayObject.__worldAlpha;
displayObject.__cacheBitmapRenderer.__worldTransform.copyFrom(displayObject.__renderTransform);
displayObject.__cacheBitmapRenderer.__worldTransform.invert();
displayObject.__cacheBitmapRenderer.__worldTransform.concat(displayObject.__cacheBitmapMatrix);
displayObject.__cacheBitmapRenderer.__worldTransform.tx -= offsetX;
displayObject.__cacheBitmapRenderer.__worldTransform.ty -= offsetY;
displayObject.__cacheBitmapRenderer.__worldTransform.scale(pixelRatio, pixelRatio);
displayObject.__cacheBitmapRenderer.__pixelRatio = pixelRatio;
displayObject.__cacheBitmapRenderer.__worldColorTransform.__copyFrom(colorTransform);
displayObject.__cacheBitmapRenderer.__worldColorTransform.__invert();
displayObject.__isCacheBitmapRender = true;
if (displayObject.__cacheBitmapRenderer.__type == OPENGL)
{
var parentRenderer:OpenGLRenderer = cast renderer;
var childRenderer:OpenGLRenderer = cast displayObject.__cacheBitmapRenderer;
var context = childRenderer.__context3D;
var cacheRTT = context.__state.renderToTexture;
var cacheRTTDepthStencil = context.__state.renderToTextureDepthStencil;
var cacheRTTAntiAlias = context.__state.renderToTextureAntiAlias;
var cacheRTTSurfaceSelector = context.__state.renderToTextureSurfaceSelector;
// var cacheFramebuffer = context.__contextState.__currentGLFramebuffer;
var cacheBlendMode = parentRenderer.__blendMode;
parentRenderer.__suspendClipAndMask();
childRenderer.__copyShader(parentRenderer);
// childRenderer.__copyState (parentRenderer);
displayObject.__cacheBitmapData.__setUVRect(context, 0, 0, filterWidth, filterHeight);
childRenderer.__setRenderTarget(displayObject.__cacheBitmapData);
if (displayObject.__cacheBitmapData.image != null)
displayObject.__cacheBitmapData.__textureVersion = displayObject.__cacheBitmapData.image.version
+ 1;
displayObject.__cacheBitmapData.__drawGL(displayObject, childRenderer);
if (hasFilters)
{
var needSecondBitmapData = true;
var needCopyOfOriginal = false;
for (filter in displayObject.__filters)
{
// if (filter.__needSecondBitmapData) {
// needSecondBitmapData = true;
// }
if (filter.__preserveObject)
{
needCopyOfOriginal = true;
}
}
var bitmap = displayObject.__cacheBitmapData;
var bitmap2 = null;
var bitmap3 = null;
// if (needSecondBitmapData) {
if (displayObject.__cacheBitmapData2 == null
|| bitmapWidth > displayObject.__cacheBitmapData2.width
|| bitmapHeight > displayObject.__cacheBitmapData2.height)
{
displayObject.__cacheBitmapData2 = new BitmapData(bitmapWidth, bitmapHeight, true, 0);
}
else
{
displayObject.__cacheBitmapData2.fillRect(displayObject.__cacheBitmapData2.rect, 0);
if (displayObject.__cacheBitmapData2.image != null)
{
displayObject.__cacheBitmapData2.__textureVersion = displayObject.__cacheBitmapData2.image.version + 1;
}
}
displayObject.__cacheBitmapData2.__setUVRect(context, 0, 0, filterWidth, filterHeight);
bitmap2 = displayObject.__cacheBitmapData2;
// } else {
// bitmap2 = bitmapData;
// }
if (needCopyOfOriginal)
{
if (displayObject.__cacheBitmapData3 == null
|| bitmapWidth > displayObject.__cacheBitmapData3.width
|| bitmapHeight > displayObject.__cacheBitmapData3.height)
{
displayObject.__cacheBitmapData3 = new BitmapData(bitmapWidth, bitmapHeight, true, 0);
}
else
{
displayObject.__cacheBitmapData3.fillRect(displayObject.__cacheBitmapData3.rect, 0);
if (displayObject.__cacheBitmapData3.image != null)
{
displayObject.__cacheBitmapData3.__textureVersion = displayObject.__cacheBitmapData3.image.version + 1;
}
}
displayObject.__cacheBitmapData3.__setUVRect(context, 0, 0, filterWidth, filterHeight);
bitmap3 = displayObject.__cacheBitmapData3;
}
childRenderer.__setBlendMode(NORMAL);
childRenderer.__worldAlpha = 1;
childRenderer.__worldTransform.identity();
childRenderer.__worldColorTransform.__identity();
// var sourceRect = bitmap.rect;
// if (__tempPoint == null) __tempPoint = new Point ();
// var destPoint = __tempPoint;
var shader, cacheBitmap;
for (filter in displayObject.__filters)
{
if (filter.__preserveObject)
{
childRenderer.__setRenderTarget(bitmap3);
childRenderer.__renderFilterPass(bitmap, childRenderer.__defaultDisplayShader, filter.__smooth);
}
for (i in 0...filter.__numShaderPasses)
{
shader = filter.__initShader(childRenderer, i, filter.__preserveObject ? bitmap3 : null);
childRenderer.__setBlendMode(filter.__shaderBlendMode);
childRenderer.__setRenderTarget(bitmap2);
childRenderer.__renderFilterPass(bitmap, shader, filter.__smooth);
cacheBitmap = bitmap;
bitmap = bitmap2;
bitmap2 = cacheBitmap;
}
filter.__renderDirty = false;
}
displayObject.__cacheBitmap.__bitmapData = bitmap;
}
parentRenderer.__blendMode = NORMAL;
parentRenderer.__setBlendMode(cacheBlendMode);
parentRenderer.__copyShader(childRenderer);
if (cacheRTT != null)
{
context.setRenderToTexture(cacheRTT, cacheRTTDepthStencil, cacheRTTAntiAlias, cacheRTTSurfaceSelector);
}
else
{
context.setRenderToBackBuffer();
}
// context.__bindGLFramebuffer (cacheFramebuffer);
// parentRenderer.__restoreState (childRenderer);
parentRenderer.__resumeClipAndMask(childRenderer);
parentRenderer.setViewport();
displayObject.__cacheBitmapColorTransform.__copyFrom(colorTransform);
}
else
{
#if (js && html5)
displayObject.__cacheBitmapData.__drawCanvas(displayObject, cast displayObject.__cacheBitmapRenderer);
#else
displayObject.__cacheBitmapData.__drawCairo(displayObject, cast displayObject.__cacheBitmapRenderer);
#end
if (hasFilters)
{
var needSecondBitmapData = false;
var needCopyOfOriginal = false;
for (filter in displayObject.__filters)
{
if (filter.__needSecondBitmapData)
{
needSecondBitmapData = true;
}
if (filter.__preserveObject)
{
needCopyOfOriginal = true;
}
}
var bitmap = displayObject.__cacheBitmapData;
var bitmap2 = null;
var bitmap3 = null;
if (needSecondBitmapData)
{
if (displayObject.__cacheBitmapData2 == null
|| displayObject.__cacheBitmapData2.image == null
|| bitmapWidth > displayObject.__cacheBitmapData2.width
|| bitmapHeight > displayObject.__cacheBitmapData2.height)
{
displayObject.__cacheBitmapData2 = new BitmapData(bitmapWidth, bitmapHeight, true, 0);
}
else
{
displayObject.__cacheBitmapData2.fillRect(displayObject.__cacheBitmapData2.rect, 0);
}
bitmap2 = displayObject.__cacheBitmapData2;
}
else
{
bitmap2 = bitmap;
}
if (needCopyOfOriginal)
{
if (displayObject.__cacheBitmapData3 == null
|| displayObject.__cacheBitmapData3.image == null
|| bitmapWidth > displayObject.__cacheBitmapData3.width
|| bitmapHeight > displayObject.__cacheBitmapData3.height)
{
displayObject.__cacheBitmapData3 = new BitmapData(bitmapWidth, bitmapHeight, true, 0);
}
else
{
displayObject.__cacheBitmapData3.fillRect(displayObject.__cacheBitmapData3.rect, 0);
}
bitmap3 = displayObject.__cacheBitmapData3;
}
if (displayObject.__tempPoint == null) displayObject.__tempPoint = new Point();
var destPoint = displayObject.__tempPoint;
var cacheBitmap, lastBitmap;
for (filter in displayObject.__filters)
{
if (filter.__preserveObject)
{
bitmap3.copyPixels(bitmap, bitmap.rect, destPoint);
}
lastBitmap = filter.__applyFilter(bitmap2, bitmap, bitmap.rect, destPoint);
if (filter.__preserveObject)
{
lastBitmap.draw(bitmap3, null,
displayObject.__objectTransform != null ? displayObject.__objectTransform.__colorTransform : null);
}
filter.__renderDirty = false;
if (needSecondBitmapData && lastBitmap == bitmap2)
{
cacheBitmap = bitmap;
bitmap = bitmap2;
bitmap2 = cacheBitmap;
}
}
if (displayObject.__cacheBitmapData != bitmap)
{
// TODO: Fix issue with swapping __cacheBitmap.__bitmapData
// __cacheBitmapData.copyPixels (bitmap, bitmap.rect, destPoint);
// Adding __cacheBitmapRenderer = null; makes this work
cacheBitmap = displayObject.__cacheBitmapData;
displayObject.__cacheBitmapData = bitmap;
displayObject.__cacheBitmapData2 = cacheBitmap;
displayObject.__cacheBitmap.__bitmapData = displayObject.__cacheBitmapData;
displayObject.__cacheBitmapRenderer = null;
}
displayObject.__cacheBitmap.__imageVersion = displayObject.__cacheBitmapData.__textureVersion;
}
displayObject.__cacheBitmapColorTransform.__copyFrom(colorTransform);
if (!displayObject.__cacheBitmapColorTransform.__isDefault(true))
{
displayObject.__cacheBitmapColorTransform.alphaMultiplier = 1;
displayObject.__cacheBitmapData.colorTransform(displayObject.__cacheBitmapData.rect, displayObject.__cacheBitmapColorTransform);
}
}
displayObject.__isCacheBitmapRender = false;
}
if (updateTransform || needRender)
{
Rectangle.__pool.release(rect);
}
updated = updateTransform;
}
else if (displayObject.__cacheBitmap != null)
{
if (renderer.__type == DOM)
{
var domRenderer:DOMRenderer = cast renderer;
domRenderer.__renderDrawableClear(displayObject.__cacheBitmap);
}
displayObject.__cacheBitmap = null;
displayObject.__cacheBitmapData = null;
displayObject.__cacheBitmapData2 = null;
displayObject.__cacheBitmapData3 = null;
displayObject.__cacheBitmapColorTransform = null;
displayObject.__cacheBitmapRenderer = null;
updated = true;
}
ColorTransform.__pool.release(colorTransform);
if (updated && displayObject.__drawableType == TEXT_FIELD)
{
var textField:TextField = cast displayObject;
if (textField.__cacheBitmap != null)
{
textField.__cacheBitmap.__renderTransform.tx -= textField.__offsetX;
textField.__cacheBitmap.__renderTransform.ty -= textField.__offsetY;
}
}
return updated;
#else
return false;
#end
}
}
#else
typedef DisplayObjectRenderer = Dynamic;
#end
-89
View File
@@ -1,89 +0,0 @@
package openfl.display;
import openfl.utils.ByteArray;
#if !openfl_debug
@:fileXml('tags="haxe,release"')
@:noDebug
#end
class GraphicsShader extends Shader
{
@:glVertexHeader("attribute float openfl_Alpha;
attribute vec4 openfl_ColorMultiplier;
attribute vec4 openfl_ColorOffset;
attribute vec4 openfl_Position;
attribute vec2 openfl_TextureCoord;
varying float openfl_Alphav;
varying vec4 openfl_ColorMultiplierv;
varying vec4 openfl_ColorOffsetv;
varying vec2 openfl_TextureCoordv;
uniform mat4 openfl_Matrix;
uniform bool openfl_HasColorTransform;
uniform vec2 openfl_TextureSize;")
@:glVertexBody("openfl_Alphav = openfl_Alpha;
openfl_TextureCoordv = openfl_TextureCoord;
if (openfl_HasColorTransform) {
openfl_ColorMultiplierv = openfl_ColorMultiplier;
openfl_ColorOffsetv = openfl_ColorOffset / 255.0;
}
gl_Position = openfl_Matrix * openfl_Position;")
@:glVertexSource("#pragma header
void main(void) {
#pragma body
}")
@:glFragmentHeader("varying float openfl_Alphav;
varying vec4 openfl_ColorMultiplierv;
varying vec4 openfl_ColorOffsetv;
varying vec2 openfl_TextureCoordv;
uniform bool openfl_HasColorTransform;
uniform vec2 openfl_TextureSize;
uniform sampler2D bitmap;")
@:glFragmentBody("vec4 color = texture2D (bitmap, openfl_TextureCoordv);
if (color.a == 0.0) {
gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
} else if (openfl_HasColorTransform) {
color = vec4(color.rgb / color.a, color.a);
mat4 colorMultiplier = mat4(0);
colorMultiplier[0][0] = openfl_ColorMultiplierv.x;
colorMultiplier[1][1] = openfl_ColorMultiplierv.y;
colorMultiplier[2][2] = openfl_ColorMultiplierv.z;
colorMultiplier[3][3] = 1.0; // openfl_ColorMultiplierv.w;
color = clamp(openfl_ColorOffsetv + (color * colorMultiplier), 0.0, 1.0);
if (color.a > 0.0) {
gl_FragColor = vec4(color.rgb * color.a * openfl_Alphav, color.a * openfl_Alphav);
} else {
gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
}
} else {
gl_FragColor = color * openfl_Alphav;
}")
#if emscripten
@:glFragmentSource("#pragma header
void main(void) {
#pragma body
gl_FragColor = gl_FragColor.bgra;
}")
#else
@:glFragmentSource("#pragma header
void main(void) {
#pragma body
}")
#end
public function new(code:ByteArray = null)
{
super(code);
}
}
File diff suppressed because it is too large Load Diff
@@ -1,95 +0,0 @@
package openfl.display3D.utils;
import flixel.util.FlxPool.IFlxPooled;
import flixel.util.FlxPool;
import lime.utils.UInt8Array;
class UInt8Buff implements IFlxPooled
{
static var _pools:Map<Int, FlxPool<UInt8Buff>> = [];
public static function getPool(length:Int) {
if(!_pools.exists(length)) {
_pools.set(length, new FlxPool<UInt8Buff>(UInt8Buff));
}
return _pools.get(length);
}
/**
* Recycle or create new FlxRect.
* Be sure to put() them back into the pool after you're done with them!
*/
public static inline function get(length:Int):UInt8Buff
{
var rect = getPool(length).get().set(length);
rect._inPool = false;
if(rect.buffer == null)
rect.buffer = new UInt8Array(length);
return rect;
}
/**
* Recycle or create a new FlxRect which will automatically be released
* to the pool when passed into a flixel function.
*/
public static inline function weak(length:Int):UInt8Buff
{
var rect = get(length);
rect._weak = true;
return rect;
}
var _weak:Bool = false;
var _inPool:Bool = false;
public var length(get, never):Int;
inline function get_length() {
return buffer.length;
}
public var buffer:UInt8Array;
@:keep
private function new(length:Int)
{
set(length);
}
/**
* Add this FlxRect to the recycling pool.
*/
public inline function put():Void
{
if (!_inPool)
{
_inPool = true;
_weak = false;
getPool(length).putUnsafe(this);
}
}
/**
* Add this FlxPoint to the recycling pool if it's a weak reference (allocated via weak()).
*/
public inline function putWeak():Void
{
if (_weak)
{
put();
}
}
/**
* Does nothing
*/
private inline function set(_length:Int):UInt8Buff
{
return this;
}
/**
* Necessary for IFlxDestroyable.
*/
public function destroy() {}
}
-705
View File
@@ -1,705 +0,0 @@
package openfl.media;
#if !flash
import haxe.Int64;
import openfl.events.Event;
import openfl.events.EventDispatcher;
import openfl.events.IOErrorEvent;
import openfl.net.URLRequest;
import openfl.utils.ByteArray;
import openfl.utils.Future;
#if lime
import openfl.utils._internal.UInt8Array;
import lime.media.AudioBuffer;
import lime.media.AudioSource;
#end
/**
The Sound class lets you work with sound in an application. The Sound class
lets you create a Sound object, load and play an external MP3 file into
that object, close the sound stream, and access data about the sound, such
as information about the number of bytes in the stream and ID3 metadata.
More detailed control of the sound is performed through the sound source
- the SoundChannel or Microphone object for the sound - and through the
properties in the SoundTransform class that control the output of the sound
to the computer's speakers.
In Flash Player 10 and later and AIR 1.5 and later, you can also use
this class to work with sound that is generated dynamically. In this case,
the Sound object uses the function you assign to a `sampleData`
event handler to poll for sound data. The sound is played as it is
retrieved from a ByteArray object that you populate with sound data. You
can use `Sound.extract()` to extract sound data from a Sound
object, after which you can manipulate it before writing it back to the
stream for playback.
To control sounds that are embedded in a SWF file, use the properties in
the SoundMixer class.
**Note**: The ActionScript 3.0 Sound API differs from ActionScript
2.0. In ActionScript 3.0, you cannot take sound objects and arrange them in
a hierarchy to control their properties.
When you use this class, consider the following security model:
* Loading and playing a sound is not allowed if the calling file is in
a network sandbox and the sound file to be loaded is local.
* By default, loading and playing a sound is not allowed if the calling
file is local and tries to load and play a remote sound. A user must grant
explicit permission to allow this type of access.
* Certain operations dealing with sound are restricted. The data in a
loaded sound cannot be accessed by a file in a different domain unless you
implement a cross-domain policy file. Sound-related APIs that fall under
this restriction are `Sound.id3`,
`SoundMixer.computeSpectrum()`,
`SoundMixer.bufferTime`, and the `SoundTransform`
class.
However, in Adobe AIR, content in the `application` security
sandbox(content installed with the AIR application) are not restricted by
these security limitations.
For more information related to security, see the Flash Player Developer
Center Topic: [Security](http://www.adobe.com/go/devnet_security_en).
@event complete Dispatched when data has loaded successfully.
@event id3 Dispatched by a Sound object when ID3 data is available
for an MP3 sound.
@event ioError Dispatched when an input/output error occurs that causes
a load operation to fail.
@event open Dispatched when a load operation starts.
@event progress Dispatched when data is received as a load operation
progresses.
@event sampleData Dispatched when the runtime requests new audio data.
**/
#if !openfl_debug
@:fileXml('tags="haxe,release"')
@:noDebug
#end
@:access(lime.media.AudioBuffer)
@:access(lime.utils.AssetLibrary)
@:access(openfl.media.SoundMixer)
@:access(openfl.media.SoundChannel.new)
@:autoBuild(openfl.utils._internal.AssetsMacro.embedSound())
class Sound extends EventDispatcher
{
/**
Returns the currently available number of bytes in this sound object. This
property is usually useful only for externally loaded files.
**/
public var bytesLoaded(default, null):Int;
/**
Returns the total number of bytes in this sound object.
**/
public var bytesTotal(default, null):Int;
/**
Provides access to the metadata that is part of an MP3 file.
MP3 sound files can contain ID3 tags, which provide metadata about the
file. If an MP3 sound that you load using the `Sound.load()` method
contains ID3 tags, you can query these properties. Only ID3 tags that
use the UTF-8 character set are supported.
Flash Player 9 and later and AIR support ID3 2.0 tags, specifically
2.3 and 2.4. The following tables list the standard ID3 2.0 tags and
the type of content the tags represent. The `Sound.id3` property
provides access to these tags through the format `my_sound.id3.COMM`,
`my_sound.id3.TIME`, and so on. The first table describes tags that
can be accessed either through the ID3 2.0 property name or the
ActionScript property name. The second table describes ID3 tags that
are supported but do not have predefined properties in ActionScript.
| ID3 2.0 tag | Corresponding Sound class property |
| --- | --- |
| COMM | Sound.id3.comment |
| TALB | Sound.id3.album |
| TCON | Sound.id3.genre |
| TIT2 | Sound.id3.songName |
| TPE1 | Sound.id3.artist |
| TRCK | Sound.id3.track |
| TYER | Sound.id3.year |
The following table describes ID3 tags that are supported but do not
have predefined properties in the Sound class. You access them by
calling `mySound.id3.TFLT`, `mySound.id3.TIME`, and so on. **NOTE:**
None of these tags are supported in Flash Lite 4.
| Property | Description |
| --- | --- |
| TFLT | File type |
| TIME | Time |
| TIT1 | Content group description |
| TIT2 | Title/song name/content description |
| TIT3 | Subtitle/description refinement |
| TKEY | Initial key |
| TLAN | Languages |
| TLEN | Length |
| TMED | Media type |
| TOAL | Original album/movie/show title |
| TOFN | Original filename |
| TOLY | Original lyricists/text writers |
| TOPE | Original artists/performers |
| TORY | Original release year |
| TOWN | File owner/licensee |
| TPE1 | Lead performers/soloists |
| TPE2 | Band/orchestra/accompaniment |
| TPE3 | Conductor/performer refinement |
| TPE4 | Interpreted, remixed, or otherwise modified by |
| TPOS | Part of a set |
| TPUB | Publisher |
| TRCK | Track number/position in set |
| TRDA | Recording dates |
| TRSN | Internet radio station name |
| TRSO | Internet radio station owner |
| TSIZ | Size |
| TSRC | ISRC (international standard recording code) |
| TSSE | Software/hardware and settings used for encoding |
| TYER | Year |
| WXXX | URL link frame |
When using this property, consider the Flash Player security model:
* The `id3` property of a Sound object is always permitted for SWF
files that are in the same security sandbox as the sound file. For
files in other sandboxes, there are security checks.
* When you load the sound, using the `load()` method of the Sound
class, you can specify a `context` parameter, which is a
SoundLoaderContext object. If you set the `checkPolicyFile` property
of the SoundLoaderContext object to `true`, Flash Player checks for a
URL policy file on the server from which the sound is loaded. If a
policy file exists and permits access from the domain of the loading
SWF file, then the file is allowed to access the `id3` property of the
Sound object; otherwise it is not.
However, in Adobe AIR, content in the `application` security sandbox
(content installed with the AIR application) are not restricted by
these security limitations.
For more information related to security, see the Flash Player
Developer Center Topic: <a
href="http://www.adobe.com/go/devnet_security_en"
scope="external">Security</a>.
**/
public var id3(get, never):ID3Info;
/**
Returns the buffering state of external MP3 files. If the value is
`true`, any playback is currently suspended while the object
waits for more data.
**/
public var isBuffering(default, null):Bool;
// @:noCompletion @:dox(hide) @:require(flash10_1) public var isURLInaccessible (default, null):Bool;
/**
The length of the current sound in milliseconds.
**/
public var length(get, never):Float;
/**
The URL from which this sound was loaded. This property is applicable only
to Sound objects that were loaded using the `Sound.load()`
method. For Sound objects that are associated with a sound asset from a
SWF file's library, the value of the `url` property is
`null`.
When you first call `Sound.load()`, the `url`
property initially has a value of `null`, because the final URL
is not yet known. The `url` property will have a non-null value
as soon as an `open` event is dispatched from the Sound
object.
The `url` property contains the final, absolute URL from
which a sound was loaded. The value of `url` is usually the
same as the value passed to the `stream` parameter of
`Sound.load()`. However, if you passed a relative URL to
`Sound.load()` the value of the `url` property
represents the absolute URL. Additionally, if the original URL request is
redirected by an HTTP server, the value of the `url` property
reflects the final URL from which the sound file was actually downloaded.
This reporting of an absolute, final URL is equivalent to the behavior of
`LoaderInfo.url`.
In some cases, the value of the `url` property is truncated;
see the `isURLInaccessible` property for details.
**/
public var url(default, null):String;
#if lime
@:noCompletion private var __buffer:AudioBuffer;
#end
#if openfljs
@:noCompletion private static function __init__()
{
untyped Object.defineProperties(Sound.prototype, {
"id3": {get: untyped #if haxe4 js.Syntax.code #else __js__ #end ("function () { return this.get_id3 (); }")},
"length": {get: untyped #if haxe4 js.Syntax.code #else __js__ #end ("function () { return this.get_length (); }")},
});
}
#end
/**
Creates a new Sound object. If you pass a valid URLRequest object to the
Sound constructor, the constructor automatically calls the
`load()` function for the Sound object. If you do not pass a
valid URLRequest object to the Sound constructor, you must call the
`load()` function for the Sound object yourself, or the stream
will not load.
Once `load()` is called on a Sound object, you can't later
load a different sound file into that Sound object. To load a different
sound file, create a new Sound object.
In Flash Player 10 and later and AIR 1.5 and later, instead of using
`load()`, you can use the `sampleData` event handler
to load sound dynamically into the Sound object.
@param stream The URL that points to an external MP3 file.
@param context An optional SoundLoader context object, which can define
the buffer time(the minimum number of milliseconds of MP3
data to hold in the Sound object's buffer) and can specify
whether the application should check for a cross-domain
policy file prior to loading the sound.
**/
public function new(stream:URLRequest = null, context:SoundLoaderContext = null)
{
super(this);
bytesLoaded = 0;
bytesTotal = 0;
isBuffering = false;
url = null;
if (stream != null)
{
load(stream, context);
}
}
/**
Closes the stream, causing any download of data to cease. No data may
be read from the stream after the `close()` method is called.
@throws IOError The stream could not be closed, or the stream was not
open.
**/
public function close():Void
{
#if lime
if (__buffer != null)
{
__buffer.dispose();
__buffer = null;
}
#end
}
#if false
/**
Extracts raw sound data from a Sound object.
This method is designed to be used when you are working with
dynamically generated audio, using a function you assign to the
`sampleData` event for a different Sound object. That is, you can use
this method to extract sound data from a Sound object. Then you can
write the data to the byte array that another Sound object is using to
stream dynamic audio.
The audio data is placed in the target byte array starting from the
current position of the byte array. The audio data is always exposed
as 44100 Hz Stereo. The sample type is a 32-bit floating-point value,
which can be converted to a Number using `ByteArray.readFloat()`.
@param target A ByteArray object in which the extracted sound samples
are placed.
@param length The number of sound samples to extract. A sample
contains both the left and right channels נthat is,
two 32-bit floating-point values.
@return The number of samples written to the ByteArray specified in
the `target` parameter.
**/
// @:noCompletion @:dox(hide) @:require(flash10) public function extract (target:ByteArray, length:Float, startPosition:Float = -1):Float;
#end
#if lime
/**
Creates a new Sound from an AudioBuffer immediately.
@param buffer An AudioBuffer instance
@returns A new Sound
**/
public static function fromAudioBuffer(buffer:AudioBuffer):Sound
{
var sound = new Sound();
sound.__buffer = buffer;
return sound;
}
#end
/**
Creates a new Sound from a file path synchronously. This means that the
Sound will be returned immediately (if supported).
HTML5 and Flash do not support creating Sound synchronously, so these targets
always return `null`.
In order to load files from a remote web address, use the `loadFromFile` method,
which supports asynchronous loading.
@param path A local file path containing a sound
@returns A new Sound if successful, or `null` if unsuccessful
**/
public static function fromFile(path:String):Sound
{
#if lime
return fromAudioBuffer(AudioBuffer.fromFile(path));
#else
return null;
#end
}
/**
Initiates loading of an external MP3 file from the specified URL. If you
provide a valid URLRequest object to the Sound constructor, the
constructor calls `Sound.load()` for you. You only need to call
`Sound.load()` yourself if you don't pass a valid URLRequest
object to the Sound constructor or you pass a `null` value.
Once `load()` is called on a Sound object, you can't later
load a different sound file into that Sound object. To load a different
sound file, create a new Sound object.
When using this method, consider the following security model:
* Calling `Sound.load()` is not allowed if the calling file
is in the local-with-file-system sandbox and the sound is in a network
sandbox.
* Access from the local-trusted or local-with-networking sandbox
requires permission from a website through a URL policy file.
* You cannot connect to commonly reserved ports. For a complete list
of blocked ports, see "Restricting Networking APIs" in the _ActionScript
3.0 Developer's Guide_.
* You can prevent a SWF file from using this method by setting the
`allowNetworking` parameter of the `object` and
`embed` tags in the HTML page that contains the SWF
content.
In Flash Player 10 and later, if you use a multipart Content-Type(for
example "multipart/form-data") that contains an upload(indicated by a
"filename" parameter in a "content-disposition" header within the POST
body), the POST operation is subject to the security rules applied to
uploads:
* The POST operation must be performed in response to a user-initiated
action, such as a mouse click or key press.
* If the POST operation is cross-domain(the POST target is not on the
same server as the SWF file that is sending the POST request), the target
server must provide a URL policy file that permits cross-domain
access.
Also, for any multipart Content-Type, the syntax must be valid
(according to the RFC2046 standards). If the syntax appears to be invalid,
the POST operation is subject to the security rules applied to
uploads.
In Adobe AIR, content in the `application` security sandbox
(content installed with the AIR application) are not restricted by these
security limitations.
For more information related to security, see the Flash Player
Developer Center Topic: [Security](http://www.adobe.com/go/devnet_security_en).
@param stream A URL that points to an external MP3 file.
@param context An optional SoundLoader context object, which can define
the buffer time(the minimum number of milliseconds of MP3
data to hold in the Sound object's buffer) and can specify
whether the application should check for a cross-domain
policy file prior to loading the sound.
@throws IOError A network error caused the load to fail.
@throws IOError The `digest` property of the
`stream` object is not `null`.
You should only set the `digest` property
of a URLRequest object when calling the
`URLLoader.load()` method when loading a
SWZ file(an Adobe platform component).
@throws SecurityError Local untrusted files may not communicate with the
Internet. You can work around this by reclassifying
this file as local-with-networking or trusted.
@throws SecurityError You cannot connect to commonly reserved ports. For a
complete list of blocked ports, see "Restricting
Networking APIs" in the _ActionScript 3.0
Developer's Guide_.
**/
public function load(stream:URLRequest, context:SoundLoaderContext = null):Void
{
url = stream.url;
#if lime
#if (js && html5)
var defaultLibrary = lime.utils.Assets.getLibrary("default");
if (defaultLibrary != null && defaultLibrary.cachedAudioBuffers.exists(url))
{
AudioBuffer_onURLLoad(defaultLibrary.cachedAudioBuffers.get(url));
}
else
{
AudioBuffer.loadFromFile(url).onComplete(AudioBuffer_onURLLoad).onError(function(_)
{
AudioBuffer_onURLLoad(null);
});
}
#else
AudioBuffer.loadFromFile(url).onComplete(AudioBuffer_onURLLoad).onError(function(_)
{
AudioBuffer_onURLLoad(null);
});
#end
#end
}
/**
Load MP3 sound data from a ByteArray object into a Sound object. The data will be read from the current
ByteArray position and will leave the ByteArray position at the end of the specified bytes length once
finished. If the MP3 sound data contains ID3 data ID3 events will be dispatched during this function call.
This function will throw an exception if the ByteArray object does not contain enough data.
@param bytes
@param bytesLength
**/
public function loadCompressedDataFromByteArray(bytes:ByteArray, bytesLength:Int):Void
{
if (bytes == null || bytesLength <= 0)
{
dispatchEvent(new IOErrorEvent(IOErrorEvent.IO_ERROR));
return;
}
if (bytes.position > 0 || bytes.length > bytesLength)
{
var copy = new ByteArray(bytesLength);
copy.writeBytes(bytes, bytes.position, bytesLength);
bytes = copy;
}
#if lime
__buffer = AudioBuffer.fromBytes(bytes);
if (__buffer == null)
{
dispatchEvent(new IOErrorEvent(IOErrorEvent.IO_ERROR));
}
else
{
dispatchEvent(new Event(Event.COMPLETE));
}
#else
dispatchEvent(new IOErrorEvent(IOErrorEvent.IO_ERROR));
#end
}
/**
Creates a new Sound from a file path or web address asynchronously. The file
load will occur in the background.
Progress, completion and error callbacks will be dispatched in the current
thread using callbacks attached to a returned Future object.
@param path A local file path or web address containing a sound
@returns A Future Sound
**/
public static function loadFromFile(path:String):Future<Sound>
{
#if lime
return AudioBuffer.loadFromFile(path).then(function(audioBuffer)
{
return Future.withValue(fromAudioBuffer(audioBuffer));
});
#else
return cast Future.withError("Cannot load audio file");
#end
}
/**
Creates a new Sound from a set of file paths or web addresses asynchronously.
The audio backend will choose the first compatible file format, and will load the file
it selects in the background.
Progress, completion and error callbacks will be dispatched in the current
thread using callbacks attached to a returned Future object.
@param paths A set of local file paths or web addresses containing sound
@returns A Future Sound
**/
public static function loadFromFiles(paths:Array<String>):Future<Sound>
{
#if lime
return AudioBuffer.loadFromFiles(paths).then(function(audioBuffer)
{
return Future.withValue(fromAudioBuffer(audioBuffer));
});
#else
return cast Future.withError("Cannot load audio files");
#end
}
/**
Load PCM 32-bit floating point sound data from a ByteArray object into a Sound object. The data will be read
from the current ByteArray position and will leave the ByteArray position at the end of the specified sample
length multiplied by either 1 channel or 2 channels if the stereo flag is set once finished.
Starting with Flash Player 11.8, the amount of audio data that can be passed to this function is limited. For
SWF versions >= 21, this function throws an exception if the amount of audio data passed into this function is
more than 1800 seconds. That is, samples / sampleRate should be less than or equal to 1800. For swf versions <
21, the runtime fails silently if the amount of audio data passed in is more than 12000 seconds. This is
provided only for backward compatibility.
This function throws an exception if the ByteArray object does not contain enough data.
@param bytes
@param samples
@param format
@param stereo
@param sampleRate
**/
public function loadPCMFromByteArray(bytes:ByteArray, samples:Int, format:String = "float", stereo:Bool = true, sampleRate:Float = 44100):Void
{
if (bytes == null)
{
dispatchEvent(new IOErrorEvent(IOErrorEvent.IO_ERROR));
return;
}
var bitsPerSample = (format == "float" ? 32 : 16); // "short"
var channels = (stereo ? 2 : 1);
var bytesLength = Std.int(samples * channels * (bitsPerSample / 8));
if (bytes.position > 0 || bytes.length > bytesLength)
{
var copy = new ByteArray(bytesLength);
copy.writeBytes(bytes, bytes.position, bytesLength);
bytes = copy;
}
#if lime
var audioBuffer = new AudioBuffer();
audioBuffer.bitsPerSample = bitsPerSample;
audioBuffer.channels = channels;
audioBuffer.data = new UInt8Array(bytes);
audioBuffer.sampleRate = Std.int(sampleRate);
__buffer = audioBuffer;
dispatchEvent(new Event(Event.COMPLETE));
#else
dispatchEvent(new IOErrorEvent(IOErrorEvent.IO_ERROR));
#end
}
/**
Generates a new SoundChannel object to play back the sound. This method
returns a SoundChannel object, which you access to stop the sound and to
monitor volume.(To control the volume, panning, and balance, access the
SoundTransform object assigned to the sound channel.)
@param startTime The initial position in milliseconds at which playback
should start.
@param loops Defines the number of times a sound loops back to the
`startTime` value before the sound channel
stops playback.
@param sndTransform The initial SoundTransform object assigned to the
sound channel.
@return A SoundChannel object, which you use to control the sound. This
method returns `null` if you have no sound card or if
you run out of available sound channels. The maximum number of
sound channels available at once is 32.
**/
public function play(startTime:Float = 0.0, loops:Int = 0, sndTransform:SoundTransform = null):SoundChannel
{
#if lime
if (__buffer == null || SoundMixer.__soundChannels.length >= SoundMixer.MAX_ACTIVE_CHANNELS)
{
return null;
}
if (sndTransform == null)
{
sndTransform = new SoundTransform();
}
else
{
sndTransform = sndTransform.clone();
}
var pan = SoundMixer.__soundTransform.pan + sndTransform.pan;
if (pan > 1) pan = 1;
else if (pan < -1) pan = -1;
var volume = SoundMixer.__soundTransform.volume * sndTransform.volume;
var source = new AudioSource(__buffer);
source.offset = Std.int(startTime);
if (loops > 1) source.loops = loops - 1;
source.gain = volume;
var position = source.position;
position.x = pan;
position.z = -1 * Math.sqrt(1 - Math.pow(pan, 2));
source.position = position;
return new SoundChannel(source, sndTransform);
#else
return null;
#end
}
// Get & Set Methods
@:noCompletion private function get_id3():ID3Info
{
return new ID3Info();
}
@:noCompletion private function get_length():Float
{
#if lime
if (__buffer != null)
{
#if (js && html5 && howlerjs)
return __buffer.src.duration() * 1000;
#else
if (__buffer.data != null) return (__buffer.data.length >> 0) / __buffer.channels / (__buffer.bitsPerSample >> 3) / __buffer.sampleRate * 1000;
else if (__buffer.__srcVorbisFile != null) {
var x = __buffer.__srcVorbisFile.pcmTotal();
return (x.high * 4294967296. + (x.low >> 0)) / __buffer.sampleRate * 1000;
}
#end
}
#end
return 0;
}
// Event Handlers
#if lime
@:noCompletion private function AudioBuffer_onURLLoad(buffer:AudioBuffer):Void
{
if (buffer == null)
{
dispatchEvent(new IOErrorEvent(IOErrorEvent.IO_ERROR));
}
else
{
__buffer = buffer;
dispatchEvent(new Event(Event.COMPLETE));
}
}
#end
}
#else
typedef Sound = flash.media.Sound;
#end
-400
View File
@@ -1,400 +0,0 @@
package openfl.media;
#if !flash
import haxe.Int64;
import openfl.events.Event;
import openfl.events.EventDispatcher;
#if lime
import lime.media.AudioSource;
import lime.media.openal.AL;
#end
/**
The SoundChannel class controls a sound in an application. Every sound is
assigned to a sound channel, and the application can have multiple sound
channels that are mixed together. The SoundChannel class contains a
`stop()` method, properties for monitoring the amplitude
(volume) of the channel, and a property for assigning a SoundTransform
object to the channel.
@event soundComplete Dispatched when a sound has finished playing.
@see [Playing sounds](https://books.openfl.org/openfl-developers-guide/working-with-sound/playing-sounds.html)
@see `openfl.media.Sound`
**/
#if !openfl_debug
@:fileXml('tags="haxe,release"')
@:noDebug
#end
#if lime_cffi
@:access(lime._internal.backend.native.NativeAudioSource)
@:access(lime.media.AudioSource)
#end
@:access(openfl.media.Sound)
@:access(openfl.media.SoundMixer)
@:final @:keep class SoundChannel extends EventDispatcher
{
/**
The current amplitude(volume) of the left channel, from 0(silent) to 1
(full amplitude).
**/
public var leftPeak(get, null):Float;
/**
The current amplitude(volume) of the right channel, from 0(silent) to 1
(full amplitude).
**/
public var rightPeak(get, null):Float;
/**
When the sound is playing, the `position` property indicates in
milliseconds the current point that is being played in the sound file.
When the sound is stopped or paused, the `position` property
indicates the last point that was played in the sound file.
A common use case is to save the value of the `position`
property when the sound is stopped. You can resume the sound later by
restarting it from that saved position.
If the sound is looped, `position` is reset to 0 at the
beginning of each loop.
**/
public var position(get, set):Float;
/**
The SoundTransform object assigned to the sound channel. A SoundTransform
object includes properties for setting volume, panning, left speaker
assignment, and right speaker assignment.
**/
public var soundTransform(get, set):SoundTransform;
/**
self explanatory
*/
public var loopTime(get, set):Float;
public var endTime(get, set):Null<Float>;
public var pitch(get, set):Float;
public var loops(get, set):Int;
@:noCompletion private var __sound:Sound;
@:noCompletion private var __isValid:Bool;
@:noCompletion private var __soundTransform:SoundTransform;
@:noCompletion private var __lastPeakTime:Float;
@:noCompletion private var __leftPeak:Float;
@:noCompletion private var __rightPeak:Float;
#if lime
@:noCompletion private var __source:AudioSource;
@:noCompletion private var __audioSource(get, set):AudioSource; // forward??? compatibility??
#end
#if openfljs
@:noCompletion private static function __init__()
{
untyped Object.defineProperties(SoundChannel.prototype, {
"position": {
get: untyped #if haxe4 js.Syntax.code #else __js__ #end ("function () { return this.get_position (); }"),
set: untyped #if haxe4 js.Syntax.code #else __js__ #end ("function (v) { return this.set_position (v); }")
},
"soundTransform": {
get: untyped #if haxe4 js.Syntax.code #else __js__ #end ("function () { return this.get_soundTransform (); }"),
set: untyped #if haxe4 js.Syntax.code #else __js__ #end ("function (v) { return this.set_soundTransform (v); }")
},
});
}
#end
@:noCompletion private function new(source:#if lime AudioSource #else Dynamic #end = null, soundTransform:SoundTransform = null):Void
{
super(this);
if (soundTransform != null) __soundTransform = soundTransform;
else __soundTransform = new SoundTransform();
__initAudioSource(source);
SoundMixer.__registerSoundChannel(this);
}
/**
Stops the sound playing in the channel.
**/
public function stop():Void
{
SoundMixer.__unregisterSoundChannel(this);
if (!__isValid) return;
#if lime
__source.stop();
#end
__dispose();
}
@:noCompletion private function __dispose():Void
{
if (!__isValid) return;
#if lime
__source.onComplete.remove(source_onComplete);
__source.dispose();
__source = null;
#end
__isValid = false;
}
@:noCompletion private function __updateTransform():Void
{
this.soundTransform = soundTransform;
}
@:noCompletion private function __updatePeaks(time:Float):Bool
{
if (Math.abs(time - __lastPeakTime) < 8) return false;
__lastPeakTime = time;
#if !macro
if (!__isValid) return false;
var buffer = __source.buffer;
var wordSize = buffer.bitsPerSample >> 3, byteSize = 1 << (buffer.bitsPerSample - 1);
var pos = Math.floor(time * buffer.sampleRate / 1000 * buffer.channels * wordSize);
var leftMin = 0, leftMax = 0, rightMin = 0, rightMax = 0, size = 0, buf;
#if lime_cffi
var backend = __source.__backend, i = 0;
if (backend.streamed) {
size = backend.bufferLengths[i = backend.bufferLengths.length - backend.requestBuffers];
buf = backend.bufferDatas[i].buffer;
pos -= Math.floor(backend.bufferTimes[i] * buffer.sampleRate * buffer.channels * wordSize);
while (pos > size) {
if (++i >= backend.bufferLengths.length) return false;
pos -= size;
buf = backend.bufferDatas[i].buffer;
size = backend.bufferLengths[i];
}
}
else
#end {
buf = buffer.data #if !js .buffer #end;
size = #if js buf.byteLength #else buf.length #end;
}
var s = Math.floor(Math.min(buffer.sampleRate / 80, 512)), c = 0, b;
pos -= pos % (buffer.channels * wordSize);
while (s > 0) {
b = funkin.backend.utils.AudioAnalyzer.getByte(buf, pos, wordSize);
if (c % 2 == 0) ((b > leftMax) ? (leftMax = b) : (if ((b = -b) > leftMin) (leftMin = b)));
else ((b > rightMax) ? (rightMax = b) : (if ((b = -b) > rightMin) (rightMin = b)));
if ((pos += wordSize) >= size) #if lime_cffi {
if (!backend.streamed || ++i >= backend.bufferLengths.length) break;
pos = 0;
buf = backend.bufferDatas[i].buffer;
size = backend.bufferLengths[i];
}
#else break; #end
if (++c > buffer.channels) {
c = 0;
s--;
}
}
if (buffer.channels == 1) __rightPeak = (__leftPeak = (leftMax + leftMin) / byteSize);
else {
__leftPeak = (leftMax + leftMin) / byteSize;
__rightPeak = (rightMax + rightMin) / byteSize;
}
#end
return true;
}
@:noCompletion private function __initAudioSource(source:#if lime AudioSource #else Dynamic #end):Void
{
#if lime
__source = source;
if (__source == null)
{
return;
}
__source.onComplete.add(source_onComplete);
__isValid = true;
__source.play();
#end
}
// Get & Set Methods
@:noCompletion private function get_position():Float
{
if (!__isValid) return 0;
#if lime
return __source.currentTime + __source.offset;
#else
return 0;
#end
}
@:noCompletion private function set_position(value:Float):Float
{
if (!__isValid) return 0;
#if lime
__source.currentTime = value - __source.offset;
#end
return value;
}
@:noCompletion private function get_soundTransform():SoundTransform
{
return __soundTransform.clone();
}
@:noCompletion private function set_soundTransform(value:SoundTransform):SoundTransform
{
if (value != null)
{
__soundTransform.pan = value.pan;
__soundTransform.volume = value.volume;
var pan = SoundMixer.__soundTransform.pan + __soundTransform.pan;
if (pan < -1) pan = -1;
if (pan > 1) pan = 1;
var volume = SoundMixer.__soundTransform.volume * __soundTransform.volume;
if (__isValid)
{
#if lime
// TODO: implement SoundTransform.leftToRight, etc. with Native setAngles?
__source.gain = volume;
__source.pan = pan;
return value;
#end
}
}
return value;
}
@:noCompletion private function get_pitch():Float
{
if (!__isValid) return 1;
#if lime
return __source.pitch;
#else
return 0;
#end
}
@:noCompletion private function set_pitch(value:Float):Float
{
if (!__isValid) return 1;
#if lime
return __source.pitch = value;
#else
return 0;
#end
}
@:noCompletion private function get_loopTime():Float
{
if (!__isValid) return -1;
#if lime
return __source.loopTime;
#else
return -1;
#end
}
@:noCompletion private function set_loopTime(value:Float):Float
{
if (!__isValid) return -1;
#if lime
return __source.loopTime = value;
#else
return -1;
#end
}
@:noCompletion private function get_endTime():Null<Float>
{
if (!__isValid) return null;
#if lime
return __source.length;
#else
return null;
#end
}
@:noCompletion private function set_endTime(value:Null<Float>):Null<Float>
{
if (!__isValid) return null;
#if lime
return __source.length = value;
#else
return null;
#end
}
@:noCompletion private function get_loops():Int
{
if (!__isValid) return 0;
#if lime
return __source.loops;
#else
return 0;
#end
}
@:noCompletion private function set_loops(value:Int):Int
{
if (!__isValid) return 0;
#if lime
return __source.loops = value;
#else
return 0;
#end
}
@:noCompletion private function get_leftPeak():Float
{
__updatePeaks(get_position());
return __leftPeak * (soundTransform == null ? 1 : soundTransform.volume);
}
@:noCompletion private function get_rightPeak():Float
{
__updatePeaks(get_position());
return __rightPeak * (soundTransform == null ? 1 : soundTransform.volume);
}
// Event Handlers
@:noCompletion private function source_onComplete():Void
{
SoundMixer.__unregisterSoundChannel(this);
__dispose();
dispatchEvent(new Event(Event.SOUND_COMPLETE));
}
@:noCompletion private function get___audioSource():AudioSource return __source;
@:noCompletion private function set___audioSource(source:AudioSource):AudioSource return __source = source;
}
#else
typedef SoundChannel = flash.media.SoundChannel;
#end