<commit_before>var Crafty = require('../core/core.js');

Crafty.extend({
    _drawLayerTemplates: {},
    _drawLayers: [],
    _addDrawLayerInstance: function (layer) {
        Crafty._drawLayers.push(layer);
        this._drawLayers.sort(function (a, b) { return a.options.z - b.options.z; });
    },

    _removeDrawLayerInstance: function (layer) {
        var i = this._drawLayers.indexOf(layer);
        if (i >= 0) {
            this._drawLayers.splice(i, 1);
        }
        this._drawLayers.sort(function (a, b) { return a.options.z - b.options.z; });
    },

    _registerLayerTemplate: function (type, layerTemplate) {
        this._drawLayerTemplates[type] = layerTemplate;
        var common = this._commonLayerProperties;

        // merge inits
        if (typeof layerTemplate.init === 'function') {
            var layerInit = layerTemplate.init;
            var commonInit = common.init;
            layerTemplate.init = function() {
                layerInit.call(this);
                commonInit.call(this);
            };
        }
        // merge removes
        if (typeof layerTemplate.remove === 'function') {
            var layerRemove = layerTemplate.remove;
            var commonRemove = common.remove;
            layerTemplate.remove = function() {
                layerRemove.call(this);
                commonRemove.call(this);
            };
        }
        // add common properties, don't overwrite existing ones
        for (var key in common) {
            if (layerTemplate[key]) continue;
            layerTemplate[key] = common[key];
        }
    },

    _commonLayerProperties: {
        // Layer options
        options: {
            xResponse: 1,
            yResponse: 1,
            scaleResponse: 1,
            z: 0
        },

        // A tracker for whether any elements in this layer need to listen to mouse/touch events
        _pointerEntities: 0,

        // Track dirty viewport state - render code should uncheck flag once finished handling it
        _dirtyViewport: false,

        // A cached version of the viewport rect
        _cachedViewportRect: null,

        // This init code will be run after any other specific layer init code
        init: function() {
            this._cachedViewportRect = {};

            // Handle viewport modifications
            this.uniqueBind("ViewportResize", this._resize);
            this.uniqueBind("InvalidateViewport", function () {
                this._dirtyViewport = true;
            });

            // Bind scene rendering (see drawing.js)
            this.uniqueBind("RenderScene", this._render);

            // Set pixelart to current status, and listen for changes
            this._setPixelart(Crafty._pixelartEnabled);
            this.uniqueBind("PixelartSet", this._setPixelart);

            Crafty._addDrawLayerInstance(this);
        },
        // This remove code will be run after any other specific layer remove code
        remove: function() {
            Crafty._removeDrawLayerInstance(this);
        },

        _resize: function() {
            // per default, do nothing
            // specific layer should overwrite this method
        },
        _setPixelart: function(enabled) {
            // per default, do nothing
            // specific layer should overwrite this method
        },
        _render: function() {
            // per default, render nothing
            // specific layer should overwrite this method
        },

        // Sort function for rendering in the correct order
        // Sort by globalZ
        _sort: function(a, b) {
            return a._globalZ - b._globalZ;
        },

        // Based on the camera options, find the Crafty coordinates
        // corresponding to the layer's position in the viewport
        _viewportRect: function (useCached) {
            var rect = this._cachedViewportRect;
            if (useCached) return rect;

            // total transform is viewport transform combined with this layer's transform
            var viewport = Crafty.viewport;
            var options = this.options;

            var scale = Math.pow(viewport._scale, options.scaleResponse);
            rect._scale = scale;
            rect._w = viewport._width / scale;
            rect._h = viewport._height / scale;
            
            // This particular transformation is designed such that,
            // if a combination pan/scale keeps the center of the screen fixed for a layer with x/y response of 1,
            // then it will also be fixed for layers with other values for x/y response
            // (note that the second term vanishes when either the response or scale are 1)
            rect._x = options.xResponse * (-viewport._x) - 
                0.5 * (options.xResponse - 1) * (1 - 1 / scale) * viewport._width;  
            rect._y = options.yResponse * (-viewport._y) - 
                0.5 * (options.yResponse - 1) * (1 - 1 / scale) * viewport._height; 

            return rect;
        },

        // transform a given rect to view space, depending on this layers' total transform
        _viewTransformRect: function(rect, outRect, useCached) {
            var view = this._viewportRect(useCached),
                scale = view._scale;

            outRect = outRect || {};
            outRect._x = Math.floor( rect._x * scale + Math.round(-view._x * scale) );
            outRect._y = Math.floor( rect._y * scale + Math.round(-view._y * scale) );
            outRect._w = Math.ceil( rect._w * scale );
            outRect._h = Math.ceil( rect._h * scale );

            return outRect;
        }
    },

    /**@
     * #Crafty.createLayer<commit_msg>Don't round coordinates of _viewTransformRect<commit_after>var Crafty = require('../core/core.js');

Crafty.extend({
    _drawLayerTemplates: {},
    _drawLayers: [],
    _addDrawLayerInstance: function (layer) {
        Crafty._drawLayers.push(layer);
        this._drawLayers.sort(function (a, b) { return a.options.z - b.options.z; });
    },

    _removeDrawLayerInstance: function (layer) {
        var i = this._drawLayers.indexOf(layer);
        if (i >= 0) {
            this._drawLayers.splice(i, 1);
        }
        this._drawLayers.sort(function (a, b) { return a.options.z - b.options.z; });
    },

    _registerLayerTemplate: function (type, layerTemplate) {
        this._drawLayerTemplates[type] = layerTemplate;
        var common = this._commonLayerProperties;

        // merge inits
        if (typeof layerTemplate.init === 'function') {
            var layerInit = layerTemplate.init;
            var commonInit = common.init;
            layerTemplate.init = function() {
                layerInit.call(this);
                commonInit.call(this);
            };
        }
        // merge removes
        if (typeof layerTemplate.remove === 'function') {
            var layerRemove = layerTemplate.remove;
            var commonRemove = common.remove;
            layerTemplate.remove = function() {
                layerRemove.call(this);
                commonRemove.call(this);
            };
        }
        // add common properties, don't overwrite existing ones
        for (var key in common) {
            if (layerTemplate[key]) continue;
            layerTemplate[key] = common[key];
        }
    },

    _commonLayerProperties: {
        // Layer options
        options: {
            xResponse: 1,
            yResponse: 1,
            scaleResponse: 1,
            z: 0
        },

        // A tracker for whether any elements in this layer need to listen to mouse/touch events
        _pointerEntities: 0,

        // Track dirty viewport state - render code should uncheck flag once finished handling it
        _dirtyViewport: false,

        // A cached version of the viewport rect
        _cachedViewportRect: null,

        // This init code will be run after any other specific layer init code
        init: function() {
            this._cachedViewportRect = {};

            // Handle viewport modifications
            this.uniqueBind("ViewportResize", this._resize);
            this.uniqueBind("InvalidateViewport", function () {
                this._dirtyViewport = true;
            });

            // Bind scene rendering (see drawing.js)
            this.uniqueBind("RenderScene", this._render);

            // Set pixelart to current status, and listen for changes
            this._setPixelart(Crafty._pixelartEnabled);
            this.uniqueBind("PixelartSet", this._setPixelart);

            Crafty._addDrawLayerInstance(this);
        },
        // This remove code will be run after any other specific layer remove code
        remove: function() {
            Crafty._removeDrawLayerInstance(this);
        },

        _resize: function() {
            // per default, do nothing
            // specific layer should overwrite this method
        },
        _setPixelart: function(enabled) {
            // per default, do nothing
            // specific layer should overwrite this method
        },
        _render: function() {
            // per default, render nothing
            // specific layer should overwrite this method
        },

        // Sort function for rendering in the correct order
        // Sort by globalZ
        _sort: function(a, b) {
            return a._globalZ - b._globalZ;
        },

        // Based on the camera options, find the Crafty coordinates
        // corresponding to the layer's position in the viewport
        _viewportRect: function (useCached) {
            var rect = this._cachedViewportRect;
            if (useCached) return rect;

            // total transform is viewport transform combined with this layer's transform
            var viewport = Crafty.viewport;
            var options = this.options;

            var scale = Math.pow(viewport._scale, options.scaleResponse);
            rect._scale = scale;
            rect._w = viewport._width / scale;
            rect._h = viewport._height / scale;
            
            // This particular transformation is designed such that,
            // if a combination pan/scale keeps the center of the screen fixed for a layer with x/y response of 1,
            // then it will also be fixed for layers with other values for x/y response
            // (note that the second term vanishes when either the response or scale are 1)
            rect._x = options.xResponse * (-viewport._x) - 
                0.5 * (options.xResponse - 1) * (1 - 1 / scale) * viewport._width;  
            rect._y = options.yResponse * (-viewport._y) - 
                0.5 * (options.yResponse - 1) * (1 - 1 / scale) * viewport._height; 

            return rect;
        },

        // transform a given rect to view space, depending on this layers' total transform
        _viewTransformRect: function(rect, outRect, useCached) {
            var view = this._viewportRect(useCached),
                scale = view._scale;

            outRect = outRect || {};
            outRect._x = rect._x * scale + Math.round(-view._x * scale);
            outRect._y = rect._y * scale + Math.round(-view._y * scale);
            outRect._w = rect._w * scale;
            outRect._h = rect._h * scale;

            return outRect;
        }
    },

    /**@
     * #Crafty.createLayer
{'fraction_non_alphanumeric': 0.0948885744605589, 'fraction_numerical': 0.0033604527767951893, 'mean_word_length': 1.76301001710237, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4296200', 'n_tokens_mistral': 2956, 'n_tokens_neox': 2830, 'n_words': 871}