All Downloads are FREE. Search and download functionalities are using the official Maven repository.

scaffold.libs_as.starling.rendering.BatchProcessor.as Maven / Gradle / Ivy

// =================================================================================================
//
//	Starling Framework
//	Copyright 2011-2015 Gamua. All Rights Reserved.
//
//	This program is free software. You can redistribute and/or modify it
//	in accordance with the terms of the accompanying license agreement.
//
// =================================================================================================

package starling.rendering
{
    import flash.geom.Matrix;

    import starling.display.Mesh;
    import starling.display.MeshBatch;
    import starling.utils.MathUtil;
    import starling.utils.MeshSubset;

    /** This class manages a list of mesh batches of different types;
     *  it acts as a "meta" MeshBatch that initiates all rendering.
     */
    internal class BatchProcessor
    {
        private var _batches:Vector.;
        private var _batchPool:BatchPool;
        private var _currentBatch:MeshBatch;
        private var _currentStyleType:Class;
        private var _onBatchComplete:Function;
        private var _cacheToken:BatchToken;

        // helper objects
        private static var sMeshSubset:MeshSubset = new MeshSubset();

        /** Creates a new batch processor. */
        public function BatchProcessor()
        {
            _batches = new [];
            _batchPool = new BatchPool();
            _cacheToken = new BatchToken();
        }

        /** Disposes all batches (including those in the reusable pool). */
        public function dispose():void
        {
            for each (var batch:MeshBatch in _batches)
                batch.dispose();

            _batches.length = 0;
            _batchPool.purge();
            _currentBatch = null;
        }

        /** Adds a mesh to the current batch, or to a new one if the current one does not support
         *  it. Whenever the batch changes, onBatchComplete is called for the previous
         *  one.
         *
         *  @param mesh       the mesh to add to the current (or new) batch.
         *  @param state      the render state from which to take the current settings for alpha,
         *                    modelview matrix, and blend mode.
         *  @param subset     the subset of the mesh you want to add, or null for
         *                    the complete mesh.
         *  @param ignoreTransformations   when enabled, the mesh's vertices will be added
         *                    without transforming them in any way (no matter the value of the
         *                    state's modelviewMatrix).
         */
        public function addMesh(mesh:Mesh, state:RenderState, subset:MeshSubset=null,
                                ignoreTransformations:Boolean=false):void
        {
            if (subset == null)
            {
                subset = sMeshSubset;
                subset.vertexID = subset.indexID = 0;
                subset.numVertices = mesh.numVertices;
                subset.numIndices  = mesh.numIndices;
            }
            else
            {
                if (subset.numVertices < 0) subset.numVertices = mesh.numVertices - subset.vertexID;
                if (subset.numIndices  < 0) subset.numIndices  = mesh.numIndices  - subset.indexID;
            }

            if (subset.numVertices > 0)
            {
                if (_currentBatch == null || !_currentBatch.canAddMesh(mesh, subset.numVertices))
                {
                    finishBatch();

                    _currentStyleType = mesh.style.type;
                    _currentBatch = _batchPool.get(_currentStyleType);
                    _currentBatch.blendMode = state ? state.blendMode : mesh.blendMode;
                    _cacheToken.setTo(_batches.length);
                    _batches[_batches.length] = _currentBatch;
                }

                var matrix:Matrix = state ? state.modelviewMatrix : null;
                var alpha:Number  = state ? state.alpha : 1.0;

                _currentBatch.addMesh(mesh, matrix, alpha, subset, ignoreTransformations);
                _cacheToken.vertexID += subset.numVertices;
                _cacheToken.indexID  += subset.numIndices;
            }
        }

        /** Finishes the current batch, i.e. call the 'onComplete' callback on the batch and
         *  prepares initialization of a new one. */
        public function finishBatch():void
        {
            var meshBatch:MeshBatch = _currentBatch;

            if (meshBatch)
            {
                _currentBatch = null;
                _currentStyleType = null;

                if (_onBatchComplete != null)
                    _onBatchComplete(meshBatch);
            }
        }

        /** Clears all batches and adds them to a pool so they can be reused later. */
        public function clear():void
        {
            var numBatches:int = _batches.length;

            for (var i:int=0; i _cacheToken.batchID)
                throw new RangeError("Token outside available range");

            for (var i:int = _cacheToken.batchID; i > token.batchID; --i)
                _batchPool.put(_batches.pop());

            if (_batches.length > token.batchID)
            {
                var batch:MeshBatch = _batches[token.batchID];
                batch.numIndices  = MathUtil.min(batch.numIndices,  token.indexID);
                batch.numVertices = MathUtil.min(batch.numVertices, token.vertexID);
            }

            _currentBatch = null;
            _cacheToken.copyFrom(token);
        }

        /** Sets all properties of the given token so that it describes the current position
         *  within this instance. */
        public function fillToken(token:BatchToken):BatchToken
        {
            token.batchID  = _cacheToken.batchID;
            token.vertexID = _cacheToken.vertexID;
            token.indexID  = _cacheToken.indexID;
            return token;
        }

        /** The number of batches currently stored in the BatchProcessor. */
        public function get numBatches():int { return _batches.length; }

        /** This callback is executed whenever a batch is finished and replaced by a new one.
         *  The finished MeshBatch is passed to the callback. Typically, this callback is used
         *  to actually render it. */
        public function get onBatchComplete():Function { return _onBatchComplete; }
        public function set onBatchComplete(value:Function):void { _onBatchComplete = value; }
    }
}

import flash.utils.Dictionary;

import starling.display.MeshBatch;

class BatchPool
{
    private var _batchLists:Dictionary;

    public function BatchPool()
    {
        _batchLists = new Dictionary();
    }

    public function purge():void
    {
        for each (var batchList:Vector. in _batchLists)
        {
            for (var i:int=0; i = _batchLists[styleType];
        if (batchList == null)
        {
            batchList = new [];
            _batchLists[styleType] = batchList;
        }

        if (batchList.length > 0) return batchList.pop();
        else
        {
            var batch:MeshBatch = new MeshBatch();
            batch.batchable = false;
            return batch;
        }
    }

    public function put(meshBatch:MeshBatch):void
    {
        var styleType:Class = meshBatch.style.type;
        var batchList:Vector. = _batchLists[styleType];
        if (batchList == null)
        {
            batchList = new [];
            _batchLists[styleType] = batchList;
        }

        meshBatch.clear();
        batchList[batchList.length] = meshBatch;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy