<commit_before>/*
 *  MainScene.js
 *  2014/06/19
 *  @auther minimo
 *  This Program is MIT license.
 *
 */

tm.define("shotgun.MainScene", {
    superClass: tm.app.Scene,

    //マルチタッチ補助クラス
    touches: null,
    touchID: -1,

    //タッチ情報
    startX: 0,
    startY: 0,
    moveX: 0,
    moveY: 0,
    beforeX: 0,
    beforeY: 0,

    //デッキ
    deck: null,

    shuffled: false,
    startTime: 0,

    //ゲーム内情報
    start: false,   //ゲームスタートフラグ
    score: 0,       //スコア
    life: 6,        //ライフ
    pick: true,     //カードピック可能フラグ
    count: 10,      //カード選択カウントダウン用

    //再生中BGM
    bgm: null,

    //経過時間
    time: 0,

    init: function() {
        this.superInit();
        this.background = "rgba(0, 0, 0, 0.0)";

        //バックグラウンド
        this.bg = tm.display.Sprite("greenback", SC_W*2, SC_H*2).addChildTo(this);

        //マルチタッチ初期化
        this.touches = tm.input.TouchesEx(this);

        //レイヤー準備
        this.lowerLayer = tm.app.Object2D().addChildTo(this);
        this.mainLayer = tm.app.Object2D().addChildTo(this);
        this.upperLayer = tm.app.Object2D().addChildTo(this);

        //スコア表示
        var that = this;
        var lb = this.scoreLabel = tm.display.OutlineLabel("SCORE:", 50).addChildTo(this);
        lb.setPosition(8, 64);
        lb.fontFamily = "'azuki'";
        lb.align     = "left";
        lb.baseline  = "middle";
        lb.outlineWidth = 1;
        lb.update = function() {
            this.text = "SCORE:"+that.score;
        }

        //ライフ表示
        var lb = this.lifeLabel = tm.display.OutlineLabel("LIFE:", 50).addChildTo(this);
        lb.setPosition(SC_W*0.7, 64);
        lb.fontFamily = "'azuki'";
        lb.align     = "left";
        lb.baseline  = "middle";
        lb.outlineWidth = 1;
        lb.update = function() {
            var life = that.life < 0 ? 0 : that.life;
            this.text = "LIFE:"+life;
        }

        //目隠し
        this.mask = tm.display.Sprite("blackback", SC_W*2, SC_H*2).addChildTo(this);
        this.mask.tweener.clear().fadeOut(100);

        //カードデッキ
        this.deck = shotgun.CardDeck().addChildTo(this.mainLayer);

        //BGM
        this.bgm = tm.asset.AssetManager.get("bgm").clone();
        this.bgm.loop = true;
        this.bgm.play();

        //スタートアップ
        var lb = this.scoreLabel = tm.display.OutlineLabel("READY", 100).addChildTo(this.upperLayer);
        lb.setPosition(SC_W/2, SC_H/2);
        lb.fontFamily = "'KS-Kohichi-FeltPen'";
        lb.align     = "center";
        lb.baseline  = "middle";
        lb.outlineWidth = 2;
        lb.tweener.clear().wait(500).fadeOut(500);
        lb.tweener.call(function(){
            that.deck.startup();
            that.deck.shuffle();
            that.start = true;
        });

        //カウントダウン表示
        var lb = this.countDown = tm.display.OutlineLabel("5", 300).addChildTo(this.upperLayer);
        lb.setPosition(SC_W/2, SC_H/2);
        lb.fontFamily = "'KS-Kohichi-FeltPen'";
        lb.align     = "center";
        lb.baseline  = "middle";
        lb.outlineWidth = 3;
        lb.beforeCount = 9;
        lb.alpha = 0.8;
        lb.update = function() {
            if (that.count < 6) {
                this.visible = true;
                this.text = ""+that.count;
            } else {
                this.visible = false;
            }
            if (this.beforeCount == that.count) {
                this.alpha -= 0.05;
                if (this.alpha < 0)this.alpha = 0;
            } else {
                this.alpha = 0.8;
            }
            this.beforeCount = that.count;
        }
    },

    update: function() {
        if (!this.start) return;

        if (this.time % 30 == 0) {
            this.count--;
            tm.asset.AssetManager.get("countdown").clone().play();
        }

        //手札が五枚揃った
        if (this.deck.numHand == 5 || this.count < 0) {
            this.deck.sortHand();
            this.deck.numHand = 0;
            var sc = this.deck.checkHand();
            this.dispHand(sc);
            if (sc == NOHAND) this.life--;
            if (sc == MISS) this.life -= 2;
            if (sc == ROYALSTRAIGHTFLASH) this.life++;

            //早上がりボーナス
            if (this.count > 5 && sc > 0) {
                sc = ~~(sc*1.5);
                var lb = tm.display.OutlineLabel("EXCELLENT!", 100).addChildTo(this);
                lb.setPosition(SC_W*0.5, SC_H*0.5);
                lb.fontFamily = "'KS-Kohichi-FeltPen'";
                lb.align     = "center";
                lb.baseline  = "middle";
                lb.outlineWidth = 3;
                lb.tweener.clear().wait(1000).call(function(){lb.remove();});
            }
            this.score += sc;
            if (this.score < 0) this.score = 0;

            //ゲームオーバー判定
            if (this.life < 0) {
                this.gameover();
            }
            this.count = 9;
        }

        this.time++;
    },

    //リスタート
    restart: function() {
        this.start = false;
        this.pick = true;
        this.score = 0;
        this.life = 6;
    },

    //ゲームオーバー
    gameover: function() {
        this.start = false;
        this.pick = false;
        var lb = this.title2 = tm.display.OutlineLabel("GAME OVER", 200).addChildTo(this.titleLayer);
        lb.setPosition(SC_W*0.6, SC_H*0.5-SC_H);
        lb.fontFamily = "'azuki'";
        lb.align     = "center";
        lb.baseline  = "middle";
        lb.outlineWidth = 3;
        lb.tweener.wait(500).move(SC_W*0.6, SC_H*0.35, 1500,"easeOutBounce");
    },

    //役名表示
    dispHand: function(hand) {
        var name;
        switch (hand) {
            case MISS:          name = "MISS!";break;
            case NOHAND:        name = "NO HAND";break;
            case ONEPAIR:       name = "ONE PAIR";break;
            case FLASH:         name = "FLASH";break;
            case TWOPAIR:       name = "TWO PAIR";break;
            case THREECARD:     name = "THREE CARD";break;
            case FULLHOUSE:     name = "FULL HOUSE";break;
            case STRAIGHT:      name = "STRAIGHT";break;
            case FOURCARD:      name = "FOURCARD";break;
            case STRAIGHTFLASH: name = "STRAIGHT FLASH";break;
            case ROYALSTRAIGHTFLASH: name = "ROYAL STRAIGHT FLASH!";break;
        }
        //役名表示
        var that = this;
        var lb = tm.display.OutlineLabel(name, 60).addChildTo(this);
        lb.setPosition(SC_W*0.5, SC_H*0.8);
        lb.fontFamily = "'KS-Kohichi-FeltPen'";
        lb.align     = "left";
        lb.baseline  = "middle";
        lb.outlineWidth = 3;
        lb.tweener.clear().wait(1000).call(function(){lb.remove(); that.deck.clearHand()});

        //効果音
        if (hand > 0) {
            tm.asset.AssetManager.get("hand").clone().play();
        } else {
            tm.asset.AssetManager.get("nohand").clone().play();
        }
    },

    //タッチorクリック開始処理
    ontouchesstart: function(e) {
        if (this.touchID > 0)return;
        this.touchID = e.ID;

        var sx = this.startX = e.pointing.x;
        var sy = this.startY = e.pointing.y;
        this.moveX = 0;
        this.moveY = 0;

        this.beforeX = sx;
        this.beforeY = sy;
    },

    //タッチorクリック移動処理
    ontouchesmove: function(e) {
        if (this.touchID != e.ID) return;

        var sx = e.pointing.x;
        var sy = e.pointing.y;
        var moveX = Math.abs(sx - this.beforeX);
        var moveY = Math.abs(sx - this.beforeY);

        if (!this.shuffled) {
            if (moveX > 300) {
                this.deck.shuffle(true);
                this.shuffled = true;
            }
        }

        if (this.time % 10 == 0) {
            this.beforeX = sx;
            this.beforeY = sy;
        }
    },

    //タッチorクリック終了処理
    ontouchesend: function(e) {
        if (this.touchID != e.ID) return;
        this.touchID = -1;

        var sx = e.pointing.x;
        var sy = e.pointing.y;

        if (this.pick && !this.shuffled) {
            var c = this.deck.pickCard(sx, sy);
            if (c) this.deck.addHand(c);
        }
        this.shuffled = false;
    },
});

<commit_msg>game leveling<commit_after>/*
 *  MainScene.js
 *  2014/06/19
 *  @auther minimo
 *  This Program is MIT license.
 *
 */

tm.define("shotgun.MainScene", {
    superClass: tm.app.Scene,

    //マルチタッチ補助クラス
    touches: null,
    touchID: -1,

    //タッチ情報
    startX: 0,
    startY: 0,
    moveX: 0,
    moveY: 0,
    beforeX: 0,
    beforeY: 0,

    //デッキ
    deck: null,

    shuffled: false,
    startTime: 0,

    //ゲーム内情報
    start: false,   //ゲームスタートフラグ
    score: 0,       //スコア
    life: 6,        //ライフ
    pick: true,     //カードピック可能フラグ
    count: 10,      //カード選択カウントダウン用
    level: 0,       //ゲームレベル

    //再生中BGM
    bgm: null,

    //経過時間
    time: 0,
    absTime: 0,

    init: function() {
        this.superInit();
        this.background = "rgba(0, 0, 0, 0.0)";

        //バックグラウンド
        this.bg = tm.display.Sprite("greenback", SC_W*2, SC_H*2).addChildTo(this);

        //マルチタッチ初期化
        this.touches = tm.input.TouchesEx(this);

        //レイヤー準備
        this.lowerLayer = tm.app.Object2D().addChildTo(this);
        this.mainLayer = tm.app.Object2D().addChildTo(this);
        this.upperLayer = tm.app.Object2D().addChildTo(this);

        //スコア表示
        var that = this;
        var lb = this.scoreLabel = tm.display.OutlineLabel("SCORE:", 50).addChildTo(this);
        lb.setPosition(8, 64);
        lb.fontFamily = "'azuki'";
        lb.align     = "left";
        lb.baseline  = "middle";
        lb.outlineWidth = 1;
        lb.update = function() {
            this.text = "SCORE:"+that.score;
        }

        //ライフ表示
        var lb = this.lifeLabel = tm.display.OutlineLabel("LIFE:", 50).addChildTo(this);
        lb.setPosition(SC_W*0.7, 64);
        lb.fontFamily = "'azuki'";
        lb.align     = "left";
        lb.baseline  = "middle";
        lb.outlineWidth = 1;
        lb.update = function() {
            var life = that.life < 0 ? 0 : that.life;
            this.text = "LIFE:"+life;
        }

        //目隠し
        this.mask = tm.display.Sprite("blackback", SC_W*2, SC_H*2).addChildTo(this);
        this.mask.tweener.clear().fadeOut(100);

        //カードデッキ
        this.deck = shotgun.CardDeck().addChildTo(this.mainLayer);

        //BGM
        this.bgm = tm.asset.AssetManager.get("bgm").clone();
        this.bgm.loop = true;
        this.bgm.play();

        //スタートアップ
        var lb = this.scoreLabel = tm.display.OutlineLabel("READY", 100).addChildTo(this.upperLayer);
        lb.setPosition(SC_W/2, SC_H/2);
        lb.fontFamily = "'KS-Kohichi-FeltPen'";
        lb.align     = "center";
        lb.baseline  = "middle";
        lb.outlineWidth = 2;
        lb.tweener.clear().wait(500).fadeOut(500);
        lb.tweener.call(function(){
            that.deck.startup();
            that.deck.shuffle();
            that.start = true;
        });

        //カウントダウン表示
        var lb = this.countDown = tm.display.OutlineLabel("5", 300).addChildTo(this.upperLayer);
        lb.setPosition(SC_W/2, SC_H/2);
        lb.fontFamily = "'KS-Kohichi-FeltPen'";
        lb.align     = "center";
        lb.baseline  = "middle";
        lb.outlineWidth = 3;
        lb.beforeCount = 9;
        lb.alpha = 0.8;
        lb.update = function() {
            if (that.count < 6) {
                this.visible = true;
                this.text = ""+that.count;
            } else {
                this.visible = false;
            }
            if (this.beforeCount == that.count) {
                this.alpha -= 0.05;
                if (this.alpha < 0)this.alpha = 0;
            } else {
                this.alpha = 0.8;
            }
            this.beforeCount = that.count;
        }
    },

    update: function() {
        if (!this.start) return;

        var level = Math.sqrt(this.absTime*0.0001)+1;
        var interval = 41-~~(level*10);
        if (interval < 20) interval = 20;
        if (this.time % interval == 0) {
            this.count--;
            tm.asset.AssetManager.get("countdown").clone().play();
        }

        //手札が五枚揃った
        if (this.deck.numHand == 5 || this.count < 0) {
            this.pick = false;
            this.deck.sortHand();
            this.deck.numHand = 0;
            var sc = this.deck.checkHand();
            this.dispHand(sc);
            if (sc == NOHAND) this.life--;
            if (sc == MISS) this.life -= 2;
            if (sc == ROYALSTRAIGHTFLASH) this.life++;

            //早上がりボーナス
            if (this.count > 5 && sc > 0) {
                sc = ~~(sc*1.5);
                var lb = tm.display.OutlineLabel("EXCELLENT!", 100).addChildTo(this);
                lb.setPosition(SC_W*0.5, SC_H*0.5);
                lb.fontFamily = "'KS-Kohichi-FeltPen'";
                lb.align     = "center";
                lb.baseline  = "middle";
                lb.outlineWidth = 3;
                lb.tweener.clear().wait(1000).call(function(){lb.remove();});
            }
            this.score += sc;
            if (this.score < 0) this.score = 0;

            //ゲームオーバー判定
            if (this.life < 0) {
                this.gameover();
            }
            this.count = 9;
            this.time = 0;
        }
        this.time++;
        this.absTime++;
    },

    //リスタート
    restart: function() {
        this.start = false;
        this.pick = true;
        this.score = 0;
        this.life = 6;
        this.time = 0;
        this.absTime = 0;
    },

    //ゲームオーバー
    gameover: function() {
        this.start = false;
        this.pick = false;
        var lb = this.title2 = tm.display.OutlineLabel("GAME OVER", 200).addChildTo(this.upperLayer);
        lb.setPosition(SC_W*0.6, SC_H*0.5-SC_H);
        lb.fontFamily = "'azuki'";
        lb.align     = "center";
        lb.baseline  = "middle";
        lb.outlineWidth = 3;
        lb.tweener.wait(500).move(SC_W*0.6, SC_H*0.35, 1500,"easeOutBounce");
    },

    //役名表示
    dispHand: function(hand) {
        var name;
        switch (hand) {
            case MISS:          name = "MISS!";break;
            case NOHAND:        name = "NO HAND";break;
            case ONEPAIR:       name = "ONE PAIR";break;
            case FLASH:         name = "FLASH";break;
            case TWOPAIR:       name = "TWO PAIR";break;
            case THREECARD:     name = "THREE CARD";break;
            case FULLHOUSE:     name = "FULL HOUSE";break;
            case STRAIGHT:      name = "STRAIGHT";break;
            case FOURCARD:      name = "FOURCARD";break;
            case STRAIGHTFLASH: name = "STRAIGHT FLASH";break;
            case ROYALSTRAIGHTFLASH: name = "ROYAL STRAIGHT FLASH!";break;
        }
        //役名表示
        var that = this;
        var lb = tm.display.OutlineLabel(name, 60).addChildTo(this);
        lb.setPosition(SC_W*0.5, SC_H*0.8);
        lb.fontFamily = "'KS-Kohichi-FeltPen'";
        lb.align     = "left";
        lb.baseline  = "middle";
        lb.outlineWidth = 3;
        lb.tweener.clear().wait(1000).call(function(){lb.remove(); that.deck.clearHand();that.pick = true;});

        //効果音
        if (hand > 0) {
            tm.asset.AssetManager.get("hand").clone().play();
        } else {
            tm.asset.AssetManager.get("nohand").clone().play();
        }
    },

    //タッチorクリック開始処理
    ontouchesstart: function(e) {
        if (this.touchID > 0)return;
        this.touchID = e.ID;

        var sx = this.startX = e.pointing.x;
        var sy = this.startY = e.pointing.y;
        this.moveX = 0;
        this.moveY = 0;

        this.beforeX = sx;
        this.beforeY = sy;
    },

    //タッチorクリック移動処理
    ontouchesmove: function(e) {
        if (this.touchID != e.ID) return;

        var sx = e.pointing.x;
        var sy = e.pointing.y;
        var moveX = Math.abs(sx - this.beforeX);
        var moveY = Math.abs(sx - this.beforeY);

        if (!this.shuffled) {
            if (moveX > 300) {
                this.deck.shuffle(true);
                this.shuffled = true;
            }
        }

        if (this.time % 10 == 0) {
            this.beforeX = sx;
            this.beforeY = sy;
        }
    },

    //タッチorクリック終了処理
    ontouchesend: function(e) {
        if (this.touchID != e.ID) return;
        this.touchID = -1;

        var sx = e.pointing.x;
        var sy = e.pointing.y;

        if (this.pick && !this.shuffled) {
            var c = this.deck.pickCard(sx, sy);
            if (c) this.deck.addHand(c);
        }
        this.shuffled = false;
    },
});

<|endoftext|>


<commit_before>pc.extend(pc.Application.prototype, function () {

    var lineVertexFormat = null;
    var lineBatches = [];
    var quadMesh = null;
    var cubeLocalPos = null;
    var cubeWorldPos = null;
    var linesGraphNode = new pc.GraphNode();

    var lineBatch = function () {
        // Sensible default value; buffers will be doubled and reallocated when it's not enough
        this.numLinesAllocated = 128;

        this.vb = null;
        this.vbRam = null;
        this.mesh = null;
        this.linesUsed = 0;
        this.material = null;
        this.meshInstance = null;
    };

    lineBatch.prototype = {
        init: function (device, linesToAdd) {
            // Allocate basic stuff once per batch
            if (!this.mesh) {
                this.mesh = new pc.Mesh();
                this.mesh.primitive[0].type = pc.PRIMITIVE_LINES;
                this.mesh.primitive[0].base = 0;
                this.mesh.primitive[0].indexed = false;

                this.material = new pc.BasicMaterial();
                this.material.vertexColors = true;
                this.material.blend = true;
                this.material.blendType = pc.BLEND_NORMAL;
                this.material.update();
            }

            // Increase buffer size, if it's not enough
            while((this.linesUsed + linesToAdd) > this.numLinesAllocated) {
                this.vb = null;
                this.numLinesAllocated *= 2;
            }

            // (Re)allocate line buffer
            if (!this.vb) {
                this.vb = new pc.VertexBuffer(device, lineVertexFormat, this.numLinesAllocated * 2, pc.BUFFER_DYNAMIC);
                this.mesh.vertexBuffer = this.vb;
                this.vbRam = new DataView(this.vb.lock());

                if (!this.meshInstance) {
                    linesGraphNode.worldTransform = pc.Mat4.IDENTITY;
                    linesGraphNode.dirtyWorld = linesGraphNode.dirtyNormal = false;
                    this.meshInstance = new pc.MeshInstance(linesGraphNode, this.mesh, this.material);
                }
            }
        },

        addLines: function(position, color) {
            // Append lines to buffer
            var multiColor = !!color.length;
            var offset = this.linesUsed * 2 * lineVertexFormat.size;
            var clr;
            for(var i=0; i<position.length; i++) {
                this.vbRam.setFloat32(offset, position[i].x, true); offset += 4;
                this.vbRam.setFloat32(offset, position[i].y, true); offset += 4;
                this.vbRam.setFloat32(offset, position[i].z, true); offset += 4;
                clr = multiColor? color[i] : color;
                this.vbRam.setUint8(offset, clr.r * 255); offset += 1;
                this.vbRam.setUint8(offset, clr.g * 255); offset += 1;
                this.vbRam.setUint8(offset, clr.b * 255); offset += 1;
                this.vbRam.setUint8(offset, clr.a * 255); offset += 1;
            }
            this.linesUsed += position.length / 2;
        },

        finalize: function(drawCalls) {
            // Update batch vertex buffer/issue drawcall if there are any lines
            if (this.linesUsed > 0) {
                this.vb.setData(this.vbRam.buffer);
                this.mesh.primitive[0].count = this.linesUsed * 2;
                drawCalls.push(this.meshInstance);
                this.linesUsed = 0;
            }
        }
    };

    function _addLines(batchId, position, color) {
        // Init global line drawing data once
        if (!lineVertexFormat) {
            lineVertexFormat = new pc.VertexFormat(this.graphicsDevice, [
                    { semantic: pc.SEMANTIC_POSITION, components: 3, type: pc.ELEMENTTYPE_FLOAT32 },
                    { semantic: pc.SEMANTIC_COLOR, components: 4, type: pc.ELEMENTTYPE_UINT8, normalize: true }
                ]);
            this.on('prerender', this._preRenderImmediate, this);
        }
        if (!lineBatches[batchId]) {
            // Init used batch once
            lineBatches[batchId] = new lineBatch();
            lineBatches[batchId].init(this.graphicsDevice, position.length / 2);
            if (batchId===pc.LINEBATCH_OVERLAY) {
                lineBatches[batchId].material.depthTest = false;
                lineBatches[batchId].meshInstance.layer = pc.LAYER_GIZMO;
            }
            else if (batchId===pc.LINEBATCH_GIZMO) {
                lineBatches[batchId].meshInstance.layer = pc.LAYER_GIZMO;
            }
        } else {
            // Possibly reallocate buffer if it's small
            lineBatches[batchId].init(this.graphicsDevice, position.length / 2);
        }
        // Append
        lineBatches[batchId].addLines(position, color);
    }

    /**
     * @function
     * @name pc.Application#renderLine
     * @description Draw a line in one color
     * @param {pc.Vec3} start The start of the line
     * @param {pc.Vec3} end The end of the line
     * @param {pc.Color} color The color of the line
     * @example
     * var start = new pc.Vec3(0,0,0);
     * var end = new pc.Vec3(1,0,0);
     * var color = new pc.Color(1,1,1);
     * app.renderLine(start, end, color);
     */
    /**
     * @function
     * @name pc.Application#renderLine^2
     * @description Draw a line which blends between two colors
     * @param {pc.Vec3} start The start of the line
     * @param {pc.Vec3} end The end of the line
     * @param {pc.Color} startColor The start color of the line
     * @param {pc.Color} endColor The end color of the line
     * @example
     * var start = new pc.Vec3(0,0,0);
     * var end = new pc.Vec3(1,0,0);
     * var startColor = new pc.Color(1,1,1);
     * var endColor = new pc.Color(1,0,0);
     * app.renderLine(start, end, startColor, endColor);
     */
    /**
     * @function
     * @name pc.Application#renderLine^3
     * @description Draw a line of one color with specified line type
     * @param {pc.Vec3} start The start of the line
     * @param {pc.Vec3} end The end of the line
     * @param {pc.Color} color The color of the line
     * @param {Number} lineType The type of rendering to use: pc.LINEBATCH_WORLD, pc.LINEBATCH_OVERLAY, pc.LINEBATCH_GIZMO. Default is pc.LINEBATCH_WORLD
     * @example
     * var start = new pc.Vec3(0,0,0);
     * var end = new pc.Vec3(1,0,0);
     * var color = new pc.Color(1,1,1);
     * app.renderLine(start, end, color, pc.LINEBATCH_OVERLAY);
     */
    /**
     * @function
     * @name pc.Application#renderLine^4
     * @description Draw a line which blends between two colors with specified line type
     * @param {pc.Vec3} start The start of the line
     * @param {pc.Vec3} end The end of the line
     * @param {pc.Color} startColor The start color of the line
     * @param {pc.Color} endColor The end color of the line
     * @param {Number} lineType The type of rendering to use: pc.LINEBATCH_WORLD, pc.LINEBATCH_OVERLAY, pc.LINEBATCH_GIZMO. Default is pc.LINEBATCH_WORLD
     * @example
     * var start = new pc.Vec3(0,0,0);
     * var end = new pc.Vec3(1,0,0);
     * var startColor = new pc.Color(1,1,1);
     * var endColor = new pc.Color(1,0,0);
     * app.renderLine(start, end, startColor, endColor, pc.LINEBATCH_OVERLAY);
     */
    function renderLine(start, end, color, arg3, arg4) {
        var endColor = color;
        var lineType = pc.LINEBATCH_WORLD;
        if (arg3) {
            if (typeof(arg3) === 'number') {
                lineType = arg3;
            } else {
                endColor = arg3;
                if (arg4) lineType = arg4;
            }
        }
        this._addLines(lineType, [start, end], [color, endColor]);
    }

    /**
     * @function
     * @name pc.Application#renderLines
     * @description Draw an array of lines.
     * @param {pc.Vec3[]} position An array of points to draw lines between
     * @param {pc.Color[]} color An array of colors to color the lines. This must be the same size as the position array
     * @param {Number} [lineType] The type of rendering to use: pc.LINEBATCH_WORLD, pc.LINEBATCH_OVERLAY, pc.LINEBATCH_GIZMO. Default is pc.LINEBATCH_WORLD
     * @example
     * var points = [new pc.Vec3(0,0,0), new pc.Vec3(1,0,0), new pc.Vec3(1,1,0), new pc.Vec3(1,1,1)];
     * var colors = [new pc.Color(1,0,0), new pc.Color(1,1,0), new pc.Color(0,1,1), new pc.Color(0,0,1)];
     * app.renderLines(points, colors);
    */
    function renderLines(position, color, lineType) {
        if (lineType===undefined) lineType = pc.LINEBATCH_WORLD;
        var multiColor = !!color.length;
        if (multiColor) {
            if (position.length !== color.length) {
                pc.log.error("renderLines: position/color arrays have different lengths");
                return;
            }
        }
        if (position.length % 2 !== 0) {
            pc.log.error("renderLines: array length is not divisible by 2");
            return;
        }
        this._addLines(lineType, position, color);
    }

    // Draw lines forming a transformed unit-sized cube at this frame
    // lineType is optional
    function renderWireCube(matrix, color, lineType) {
        if (lineType===undefined) lineType = pc.LINEBATCH_WORLD;
        var i;
        // Init cube data once
        if (!cubeLocalPos) {
            var x = 0.5;
            cubeLocalPos = [new pc.Vec3(-x, -x, -x), new pc.Vec3(-x, x, -x), new pc.Vec3(x, x, -x), new pc.Vec3(x, -x, -x),
                            new pc.Vec3(-x, -x, x), new pc.Vec3(-x, x, x), new pc.Vec3(x, x, x), new pc.Vec3(x, -x, x)];
            cubeWorldPos = [new pc.Vec3(), new pc.Vec3(), new pc.Vec3(), new pc.Vec3(),
                            new pc.Vec3(), new pc.Vec3(), new pc.Vec3(), new pc.Vec3()];
        }
        // Transform and append lines
        for(i=0; i<8; i++) {
            matrix.transformPoint(cubeLocalPos[i], cubeWorldPos[i]);
        }
        this.renderLines([cubeWorldPos[0],cubeWorldPos[1],
                     cubeWorldPos[1],cubeWorldPos[2],
                     cubeWorldPos[2],cubeWorldPos[3],
                     cubeWorldPos[3],cubeWorldPos[0],

                     cubeWorldPos[4],cubeWorldPos[5],
                     cubeWorldPos[5],cubeWorldPos[6],
                     cubeWorldPos[6],cubeWorldPos[7],
                     cubeWorldPos[7],cubeWorldPos[4],

                     cubeWorldPos[0],cubeWorldPos[4],
                     cubeWorldPos[1],cubeWorldPos[5],
                     cubeWorldPos[2],cubeWorldPos[6],
                     cubeWorldPos[3],cubeWorldPos[7]
                     ], color, lineType);
    }

    function _preRenderImmediate() {
        for(var i=0; i<3; i++) {
            if (lineBatches[i]) {
                lineBatches[i].finalize(this.scene.immediateDrawCalls);
            }
        }
    }

    // Draw meshInstance at this frame
    function renderMeshInstance(meshInstance) {
        this.scene.immediateDrawCalls.push(meshInstance);
    }

    // Draw mesh at this frame
    function renderMesh(mesh, material, matrix) {
        linesGraphNode.worldTransform = matrix;
        linesGraphNode.dirtyWorld = linesGraphNode.dirtyNormal = false;
        var instance = new pc.MeshInstance(linesGraphNode, mesh, material);
        this.scene.immediateDrawCalls.push(instance);
    }

    // Draw quad of size [-0.5, 0.5] at this frame
    // layer is optional
    function renderQuad(matrix, material, layer) {
        // Init quad data once
        if (!quadMesh) {
            var format = new pc.VertexFormat(this.graphicsDevice, [
                    { semantic: pc.SEMANTIC_POSITION, components: 3, type: pc.ELEMENTTYPE_FLOAT32 }
                ]);
            var quadVb = new pc.VertexBuffer(this.graphicsDevice, format, 4);
            var iterator = new pc.VertexIterator(quadVb);
            iterator.element[pc.SEMANTIC_POSITION].set(-0.5, -0.5, 0);
            iterator.next();
            iterator.element[pc.SEMANTIC_POSITION].set(0.5, -0.5, 0);
            iterator.next();
            iterator.element[pc.SEMANTIC_POSITION].set(-0.5, 0.5, 0);
            iterator.next();
            iterator.element[pc.SEMANTIC_POSITION].set(0.5, 0.5, 0);
            iterator.end();
            quadMesh = new pc.Mesh();
            quadMesh.vertexBuffer = quadVb;
            quadMesh.primitive[0].type = pc.PRIMITIVE_TRISTRIP;
            quadMesh.primitive[0].base = 0;
            quadMesh.primitive[0].count = 4;
            quadMesh.primitive[0].indexed = false;
        }
        // Issue quad drawcall
        linesGraphNode.worldTransform = matrix;
        linesGraphNode.dirtyWorld = linesGraphNode.dirtyNormal = false;
        var quad = new pc.MeshInstance(linesGraphNode, quadMesh, material);
        if (layer) quad.layer = layer;
        this.scene.immediateDrawCalls.push(quad);
    }

    return {
        renderMeshInstance: renderMeshInstance,
        renderMesh: renderMesh,
        renderLine: renderLine,
        renderLines: renderLines,
        renderQuad: renderQuad,
        renderWireCube: renderWireCube,
        _addLines: _addLines,
        _preRenderImmediate: _preRenderImmediate
    };
}());
<commit_msg>fix line rendering (#891)<commit_after>pc.extend(pc.Application.prototype, function () {

    var lineVertexFormat = null;
    var lineBatches = [];
    var quadMesh = null;
    var cubeLocalPos = null;
    var cubeWorldPos = null;
    var tempGraphNode = new pc.GraphNode();
    var identityGraphNode = new pc.GraphNode();

    var lineBatch = function () {
        // Sensible default value; buffers will be doubled and reallocated when it's not enough
        this.numLinesAllocated = 128;

        this.vb = null;
        this.vbRam = null;
        this.mesh = null;
        this.linesUsed = 0;
        this.material = null;
        this.meshInstance = null;
    };

    lineBatch.prototype = {
        init: function (device, linesToAdd) {
            // Allocate basic stuff once per batch
            if (!this.mesh) {
                this.mesh = new pc.Mesh();
                this.mesh.primitive[0].type = pc.PRIMITIVE_LINES;
                this.mesh.primitive[0].base = 0;
                this.mesh.primitive[0].indexed = false;

                this.material = new pc.BasicMaterial();
                this.material.vertexColors = true;
                this.material.blend = true;
                this.material.blendType = pc.BLEND_NORMAL;
                this.material.update();
            }

            // Increase buffer size, if it's not enough
            while((this.linesUsed + linesToAdd) > this.numLinesAllocated) {
                this.vb = null;
                this.numLinesAllocated *= 2;
            }

            // (Re)allocate line buffer
            if (!this.vb) {
                this.vb = new pc.VertexBuffer(device, lineVertexFormat, this.numLinesAllocated * 2, pc.BUFFER_DYNAMIC);
                this.mesh.vertexBuffer = this.vb;
                this.vbRam = new DataView(this.vb.lock());

                if (!this.meshInstance) {
                    identityGraphNode.worldTransform = pc.Mat4.IDENTITY;
                    identityGraphNode.dirtyWorld = identityGraphNode.dirtyNormal = false;
                    this.meshInstance = new pc.MeshInstance(identityGraphNode, this.mesh, this.material);
                }
            }
        },

        addLines: function(position, color) {
            // Append lines to buffer
            var multiColor = !!color.length;
            var offset = this.linesUsed * 2 * lineVertexFormat.size;
            var clr;
            for(var i=0; i<position.length; i++) {
                this.vbRam.setFloat32(offset, position[i].x, true); offset += 4;
                this.vbRam.setFloat32(offset, position[i].y, true); offset += 4;
                this.vbRam.setFloat32(offset, position[i].z, true); offset += 4;
                clr = multiColor? color[i] : color;
                this.vbRam.setUint8(offset, clr.r * 255); offset += 1;
                this.vbRam.setUint8(offset, clr.g * 255); offset += 1;
                this.vbRam.setUint8(offset, clr.b * 255); offset += 1;
                this.vbRam.setUint8(offset, clr.a * 255); offset += 1;
            }
            this.linesUsed += position.length / 2;
        },

        finalize: function(drawCalls) {
            // Update batch vertex buffer/issue drawcall if there are any lines
            if (this.linesUsed > 0) {
                this.vb.setData(this.vbRam.buffer);
                this.mesh.primitive[0].count = this.linesUsed * 2;
                drawCalls.push(this.meshInstance);
                this.linesUsed = 0;
            }
        }
    };

    function _addLines(batchId, position, color) {
        // Init global line drawing data once
        if (!lineVertexFormat) {
            lineVertexFormat = new pc.VertexFormat(this.graphicsDevice, [
                    { semantic: pc.SEMANTIC_POSITION, components: 3, type: pc.ELEMENTTYPE_FLOAT32 },
                    { semantic: pc.SEMANTIC_COLOR, components: 4, type: pc.ELEMENTTYPE_UINT8, normalize: true }
                ]);
            this.on('prerender', this._preRenderImmediate, this);
        }
        if (!lineBatches[batchId]) {
            // Init used batch once
            lineBatches[batchId] = new lineBatch();
            lineBatches[batchId].init(this.graphicsDevice, position.length / 2);
            if (batchId===pc.LINEBATCH_OVERLAY) {
                lineBatches[batchId].material.depthTest = false;
                lineBatches[batchId].meshInstance.layer = pc.LAYER_GIZMO;
            }
            else if (batchId===pc.LINEBATCH_GIZMO) {
                lineBatches[batchId].meshInstance.layer = pc.LAYER_GIZMO;
            }
        } else {
            // Possibly reallocate buffer if it's small
            lineBatches[batchId].init(this.graphicsDevice, position.length / 2);
        }
        // Append
        lineBatches[batchId].addLines(position, color);
    }

    /**
     * @function
     * @name pc.Application#renderLine
     * @description Draw a line in one color
     * @param {pc.Vec3} start The start of the line
     * @param {pc.Vec3} end The end of the line
     * @param {pc.Color} color The color of the line
     * @example
     * var start = new pc.Vec3(0,0,0);
     * var end = new pc.Vec3(1,0,0);
     * var color = new pc.Color(1,1,1);
     * app.renderLine(start, end, color);
     */
    /**
     * @function
     * @name pc.Application#renderLine^2
     * @description Draw a line which blends between two colors
     * @param {pc.Vec3} start The start of the line
     * @param {pc.Vec3} end The end of the line
     * @param {pc.Color} startColor The start color of the line
     * @param {pc.Color} endColor The end color of the line
     * @example
     * var start = new pc.Vec3(0,0,0);
     * var end = new pc.Vec3(1,0,0);
     * var startColor = new pc.Color(1,1,1);
     * var endColor = new pc.Color(1,0,0);
     * app.renderLine(start, end, startColor, endColor);
     */
    /**
     * @function
     * @name pc.Application#renderLine^3
     * @description Draw a line of one color with specified line type
     * @param {pc.Vec3} start The start of the line
     * @param {pc.Vec3} end The end of the line
     * @param {pc.Color} color The color of the line
     * @param {Number} lineType The type of rendering to use: pc.LINEBATCH_WORLD, pc.LINEBATCH_OVERLAY, pc.LINEBATCH_GIZMO. Default is pc.LINEBATCH_WORLD
     * @example
     * var start = new pc.Vec3(0,0,0);
     * var end = new pc.Vec3(1,0,0);
     * var color = new pc.Color(1,1,1);
     * app.renderLine(start, end, color, pc.LINEBATCH_OVERLAY);
     */
    /**
     * @function
     * @name pc.Application#renderLine^4
     * @description Draw a line which blends between two colors with specified line type
     * @param {pc.Vec3} start The start of the line
     * @param {pc.Vec3} end The end of the line
     * @param {pc.Color} startColor The start color of the line
     * @param {pc.Color} endColor The end color of the line
     * @param {Number} lineType The type of rendering to use: pc.LINEBATCH_WORLD, pc.LINEBATCH_OVERLAY, pc.LINEBATCH_GIZMO. Default is pc.LINEBATCH_WORLD
     * @example
     * var start = new pc.Vec3(0,0,0);
     * var end = new pc.Vec3(1,0,0);
     * var startColor = new pc.Color(1,1,1);
     * var endColor = new pc.Color(1,0,0);
     * app.renderLine(start, end, startColor, endColor, pc.LINEBATCH_OVERLAY);
     */
    function renderLine(start, end, color, arg3, arg4) {
        var endColor = color;
        var lineType = pc.LINEBATCH_WORLD;
        if (arg3) {
            if (typeof(arg3) === 'number') {
                lineType = arg3;
            } else {
                endColor = arg3;
                if (arg4) lineType = arg4;
            }
        }
        this._addLines(lineType, [start, end], [color, endColor]);
    }

    /**
     * @function
     * @name pc.Application#renderLines
     * @description Draw an array of lines.
     * @param {pc.Vec3[]} position An array of points to draw lines between
     * @param {pc.Color[]} color An array of colors to color the lines. This must be the same size as the position array
     * @param {Number} [lineType] The type of rendering to use: pc.LINEBATCH_WORLD, pc.LINEBATCH_OVERLAY, pc.LINEBATCH_GIZMO. Default is pc.LINEBATCH_WORLD
     * @example
     * var points = [new pc.Vec3(0,0,0), new pc.Vec3(1,0,0), new pc.Vec3(1,1,0), new pc.Vec3(1,1,1)];
     * var colors = [new pc.Color(1,0,0), new pc.Color(1,1,0), new pc.Color(0,1,1), new pc.Color(0,0,1)];
     * app.renderLines(points, colors);
    */
    function renderLines(position, color, lineType) {
        if (lineType===undefined) lineType = pc.LINEBATCH_WORLD;
        var multiColor = !!color.length;
        if (multiColor) {
            if (position.length !== color.length) {
                pc.log.error("renderLines: position/color arrays have different lengths");
                return;
            }
        }
        if (position.length % 2 !== 0) {
            pc.log.error("renderLines: array length is not divisible by 2");
            return;
        }
        this._addLines(lineType, position, color);
    }

    // Draw lines forming a transformed unit-sized cube at this frame
    // lineType is optional
    function renderWireCube(matrix, color, lineType) {
        if (lineType===undefined) lineType = pc.LINEBATCH_WORLD;
        var i;
        // Init cube data once
        if (!cubeLocalPos) {
            var x = 0.5;
            cubeLocalPos = [new pc.Vec3(-x, -x, -x), new pc.Vec3(-x, x, -x), new pc.Vec3(x, x, -x), new pc.Vec3(x, -x, -x),
                            new pc.Vec3(-x, -x, x), new pc.Vec3(-x, x, x), new pc.Vec3(x, x, x), new pc.Vec3(x, -x, x)];
            cubeWorldPos = [new pc.Vec3(), new pc.Vec3(), new pc.Vec3(), new pc.Vec3(),
                            new pc.Vec3(), new pc.Vec3(), new pc.Vec3(), new pc.Vec3()];
        }
        // Transform and append lines
        for(i=0; i<8; i++) {
            matrix.transformPoint(cubeLocalPos[i], cubeWorldPos[i]);
        }
        this.renderLines([cubeWorldPos[0],cubeWorldPos[1],
                     cubeWorldPos[1],cubeWorldPos[2],
                     cubeWorldPos[2],cubeWorldPos[3],
                     cubeWorldPos[3],cubeWorldPos[0],

                     cubeWorldPos[4],cubeWorldPos[5],
                     cubeWorldPos[5],cubeWorldPos[6],
                     cubeWorldPos[6],cubeWorldPos[7],
                     cubeWorldPos[7],cubeWorldPos[4],

                     cubeWorldPos[0],cubeWorldPos[4],
                     cubeWorldPos[1],cubeWorldPos[5],
                     cubeWorldPos[2],cubeWorldPos[6],
                     cubeWorldPos[3],cubeWorldPos[7]
                     ], color, lineType);
    }

    function _preRenderImmediate() {
        for(var i=0; i<3; i++) {
            if (lineBatches[i]) {
                lineBatches[i].finalize(this.scene.immediateDrawCalls);
            }
        }
    }

    // Draw meshInstance at this frame
    function renderMeshInstance(meshInstance) {
        this.scene.immediateDrawCalls.push(meshInstance);
    }

    // Draw mesh at this frame
    function renderMesh(mesh, material, matrix) {
        tempGraphNode.worldTransform = matrix;
        tempGraphNode.dirtyWorld = tempGraphNode.dirtyNormal = false;
        var instance = new pc.MeshInstance(tempGraphNode, mesh, material);
        this.scene.immediateDrawCalls.push(instance);
    }

    // Draw quad of size [-0.5, 0.5] at this frame
    // layer is optional
    function renderQuad(matrix, material, layer) {
        // Init quad data once
        if (!quadMesh) {
            var format = new pc.VertexFormat(this.graphicsDevice, [
                    { semantic: pc.SEMANTIC_POSITION, components: 3, type: pc.ELEMENTTYPE_FLOAT32 }
                ]);
            var quadVb = new pc.VertexBuffer(this.graphicsDevice, format, 4);
            var iterator = new pc.VertexIterator(quadVb);
            iterator.element[pc.SEMANTIC_POSITION].set(-0.5, -0.5, 0);
            iterator.next();
            iterator.element[pc.SEMANTIC_POSITION].set(0.5, -0.5, 0);
            iterator.next();
            iterator.element[pc.SEMANTIC_POSITION].set(-0.5, 0.5, 0);
            iterator.next();
            iterator.element[pc.SEMANTIC_POSITION].set(0.5, 0.5, 0);
            iterator.end();
            quadMesh = new pc.Mesh();
            quadMesh.vertexBuffer = quadVb;
            quadMesh.primitive[0].type = pc.PRIMITIVE_TRISTRIP;
            quadMesh.primitive[0].base = 0;
            quadMesh.primitive[0].count = 4;
            quadMesh.primitive[0].indexed = false;
        }
        // Issue quad drawcall
        tempGraphNode.worldTransform = matrix;
        tempGraphNode.dirtyWorld = tempGraphNode.dirtyNormal = false;
        var quad = new pc.MeshInstance(tempGraphNode, quadMesh, material);
        if (layer) quad.layer = layer;
        this.scene.immediateDrawCalls.push(quad);
    }

    return {
        renderMeshInstance: renderMeshInstance,
        renderMesh: renderMesh,
        renderLine: renderLine,
        renderLines: renderLines,
        renderQuad: renderQuad,
        renderWireCube: renderWireCube,
        _addLines: _addLines,
        _preRenderImmediate: _preRenderImmediate
    };
}());
<|endoftext|>


<commit_before>/*
 *  MainScene.js
 *  2015/09/08
 *  @auther minimo
 *  This Program is MIT license.
 */

phina.define("pbr.MainScene", {
    superClass: "phina.display.CanvasScene",

    _member: {
        score: 0,

        //現在ステージＩＤ
        stageId: 1,

        //再生中BGM
        bgm: null,

        //自機コントロール可能フラグ
        control: true,

        //ラベル用パラメータ
        labelParam: {
            fill: "white",
            stroke: "blue",
            strokeWidth: 2,

            fontFamily: "Orbitron",
            align: "center",
            baseline: "middle",
            fontSize: 32,
            fontWeight: ''
        },
        scorelabelParam: {
            fill: "white",
            stroke: "black",
            strokeWidth: 1,

            fontFamily: "UbuntuMono",
            align: "left",
            baseline: "middle",
            fontSize: 20,
            fontWeight: ''
        },
    },

    init: function(option) {
        this.superInit();
        this.$extend(this._member);

        option = (option || {}).$safe({stageId: 1});
        this.stageId = option.stageId;

        //バックグラウンド
        var param = {
            width:SC_W,
            height:SC_H,
            fill: 'black',
            stroke: false,
            backgroundColor: 'transparent',
        };
        this.bg = phina.display.RectangleShape(param)
            .addChildTo(this)
            .setPosition(SC_W*0.5, SC_H*0.5)

        //レイヤー準備
        this.base = phina.display.Layer().addChildTo(this).setPosition(SC_OFFSET_X, 0);
        this.layers = [];
        for (var i = 0; i < LAYER_SYSTEM+1; i++) {
            switch (i) {
                case LAYER_BULLET:
                    this.layers[i] = pbr.BulletLayer().addChildTo(this.base);
                    this.bulletLayer = this.layers[i];
                    break;
                case LAYER_SHOT:
                    this.layers[i] = pbr.ShotLayer().addChildTo(this.base);
                    this.shotLayer = this.layers[i];
                    break;
                default:
                    this.layers[i] = phina.display.Layer().addChildTo(this.base);
            }
            this.layers[i].parentScene = this;
        }

        //プレイヤー準備
        var player = this.player = pbr.Player()
            .addChildTo(this)
            .setPosition(SC_W*0.5, SC_H*0.5)
            .stageStartup();
        player.shotLayer = this.shotLayer;

//        this.pointer = pbr.PlayerPointer().addChildTo(this);
//        this.pointer.player = this.player;

        //弾幕設定クラス
        pbr.BulletConfig.setup(player, this.bulletLayer);

        //スコア表示
        var that = this;
        this.scoreLabel = phina.display.Label({text:"SCORE:"}.$safe(this.scorelabelParam))
            .addChildTo(this)
            .setPosition(8, 32);
        this.scoreLabel.update = function() {
            this.text = "SCORE "+that.score;
        }

        //ステージ初期化
        this.initStage();

        //目隠し
        this.mask = phina.display.RectangleShape(param)
            .addChildTo(this)
            .setPosition(SC_W*0.5, SC_H*0.5);
        this.mask.alpha = 0;
    },

    update: function(app) {
        //ステージ進行
        var event = this.stage.get(this.time);
        if (event) {
            if (typeof(event.value) === 'function') {
                event.value.call(this, app);
            } else {
                this.enterEnemyUnit(event.value);
            }
        }
        this.time++;
    },

    //ステージ初期化
    initStage: function() {
        if (this.ground) this.ground.remove();
        switch (this.stageId) {
            case 1:
                this.stage = pbr.Stage1(this, this.player);
                this.ground = pbr.Stage1Ground().setPosition(0, -400).addChildTo(this);
                break;
            case 2:
                this.stage = pbr.Stage1(this, this.player);
                this.ground = pbr.Stage1Ground().setPosition(0, -400).addChildTo(this);
                break;
            case 3:
                this.stage = pbr.Stage1(this, this.player);
                this.ground = pbr.Stage1Ground().setPosition(0, -400).addChildTo(this);
                break;
        }
        this.time = 0;
        this.timeVanish = 0;
        this.enemyCount = 0;
        this.enemyKill = 0;
        this.stageMiss = 0;

        //ステージ番号表示
        param = {text: "STAGE "+this.stageId, fill:"white", fontFamily: "Orbitron", align: "center", baseline: "middle", fontWeight: 800, outlineWidth: 2};
        var m1 = phina.display.Label(param, 50)
            .addChildTo(this)
            .setPosition(SC_W*0.5, SC_H*0.5)
        m1.alpha = 0;
        m1.tweener.wait(500).fadeIn(250).wait(1000).fadeOut(250).call(function(){this.remove()}.bind(m1));
    },

    //ステージ再スタート
    restartStage: function() {
    },

    //敵ユニット単位の投入
    enterEnemyUnit: function(name) {
        var unit = pbr.enemyUnit[name];
        if (unit === undefined)return;

        var len = unit.length;
        for (var i = 0; i < len; i++) {
            var e = unit[i];
            var en = pbr.Enemy(e.name,e.x, e.y, this.enemyID, e.param).addChildTo(this);
            if (en.data.type == ENEMY_BOSS) {
                this.bossGauge.setTarget(en);
                this.systemBase.tweener.clear().moveBy(0, 32, 1000);
            }
            this.enemyID++;
            this.enemyCount++;
        }
    },

    //敵単体の投入
    enterEnemy: function(name, x, y, param) {
        this.enemyID++;
        this.enemyCount++;
        return pbr.Enemy(name, x, y, this.enemyID-1, param).addChildTo(this);
    },

    //敵弾一括消去
    eraseBullet: function() {
    },

    //タッチorクリック開始処理
    onpointstart: function(e) {
    },

    //タッチorクリック移動処理
    onpointmove: function(e) {
    },

    //タッチorクリック終了処理
    onpointend: function(e) {
    },

    //addChildオーバーライド
    addChild: function(child) {
        if (child.layer === undefined) {
            return this.superClass.prototype.addChild.apply(this, arguments);
        }
        child.parentScene = this;
        return this.layers[child.layer].addChild(child);
    },
});
<commit_msg>add stage name<commit_after>/*
 *  MainScene.js
 *  2015/09/08
 *  @auther minimo
 *  This Program is MIT license.
 */

phina.define("pbr.MainScene", {
    superClass: "phina.display.CanvasScene",

    _member: {
        score: 0,

        //現在ステージＩＤ
        stageId: 1,

        //再生中BGM
        bgm: null,

        //自機コントロール可能フラグ
        control: true,

        //ラベル用パラメータ
        labelParam: {
            fill: "white",
            stroke: "blue",
            strokeWidth: 2,

            fontFamily: "Orbitron",
            align: "center",
            baseline: "middle",
            fontSize: 32,
            fontWeight: ''
        },
        scorelabelParam: {
            fill: "white",
            stroke: "black",
            strokeWidth: 1,

            fontFamily: "UbuntuMono",
            align: "left",
            baseline: "middle",
            fontSize: 20,
            fontWeight: ''
        },

        stageName: {
            1: "Operation PLANET_BUSTER",
        },
    },

    init: function(option) {
        this.superInit();
        this.$extend(this._member);

        option = (option || {}).$safe({stageId: 1});
        this.stageId = option.stageId;

        //バックグラウンド
        var param = {
            width:SC_W,
            height:SC_H,
            fill: 'black',
            stroke: false,
            backgroundColor: 'transparent',
        };
        this.bg = phina.display.RectangleShape(param)
            .addChildTo(this)
            .setPosition(SC_W*0.5, SC_H*0.5)

        //レイヤー準備
        this.base = phina.display.Layer().addChildTo(this).setPosition(SC_OFFSET_X, 0);
        this.layers = [];
        for (var i = 0; i < LAYER_SYSTEM+1; i++) {
            switch (i) {
                case LAYER_BULLET:
                    this.layers[i] = pbr.BulletLayer().addChildTo(this.base);
                    this.bulletLayer = this.layers[i];
                    break;
                case LAYER_SHOT:
                    this.layers[i] = pbr.ShotLayer().addChildTo(this.base);
                    this.shotLayer = this.layers[i];
                    break;
                default:
                    this.layers[i] = phina.display.Layer().addChildTo(this.base);
            }
            this.layers[i].parentScene = this;
        }

        //プレイヤー準備
        var player = this.player = pbr.Player()
            .addChildTo(this)
            .setPosition(SC_W*0.5, SC_H*0.5)
            .stageStartup();
        player.shotLayer = this.shotLayer;

//        this.pointer = pbr.PlayerPointer().addChildTo(this);
//        this.pointer.player = this.player;

        //弾幕設定クラス
        pbr.BulletConfig.setup(player, this.bulletLayer);

        //スコア表示
        var that = this;
        this.scoreLabel = phina.display.Label({text:"SCORE:"}.$safe(this.scorelabelParam))
            .addChildTo(this)
            .setPosition(8, 32);
        this.scoreLabel.update = function() {
            this.text = "SCORE "+that.score;
        }

        //ステージ初期化
        this.initStage();

        //目隠し
        this.mask = phina.display.RectangleShape(param)
            .addChildTo(this)
            .setPosition(SC_W*0.5, SC_H*0.5);
        this.mask.alpha = 0;
    },

    update: function(app) {
        //ステージ進行
        var event = this.stage.get(this.time);
        if (event) {
            if (typeof(event.value) === 'function') {
                event.value.call(this, app);
            } else {
                this.enterEnemyUnit(event.value);
            }
        }
        this.time++;
    },

    //ステージ初期化
    initStage: function() {
        if (this.ground) this.ground.remove();
        switch (this.stageId) {
            case 1:
                this.stage = pbr.Stage1(this, this.player);
                this.ground = pbr.Stage1Ground().setPosition(0, -400).addChildTo(this);
                break;
            case 2:
                this.stage = pbr.Stage1(this, this.player);
                this.ground = pbr.Stage1Ground().setPosition(0, -400).addChildTo(this);
                break;
            case 3:
                this.stage = pbr.Stage1(this, this.player);
                this.ground = pbr.Stage1Ground().setPosition(0, -400).addChildTo(this);
                break;
        }
        this.time = 0;
        this.timeVanish = 0;
        this.enemyCount = 0;
        this.enemyKill = 0;
        this.stageMiss = 0;

        //ステージ番号表示
        param = {text: "STAGE "+this.stageId, fill:"white", fontFamily: "Orbitron", align: "center", baseline: "middle", fontWeight: 800, outlineWidth: 2};
        var m1 = phina.display.Label(param, 50)
            .addChildTo(this)
            .setPosition(SC_W*0.5, SC_H*0.5)
        m1.alpha = 0;
        m1.tweener.wait(500).fadeIn(250).wait(1000).fadeOut(250).call(function(){this.remove()}.bind(m1));
    },

    //ステージ再スタート
    restartStage: function() {
    },

    //敵ユニット単位の投入
    enterEnemyUnit: function(name) {
        var unit = pbr.enemyUnit[name];
        if (unit === undefined)return;

        var len = unit.length;
        for (var i = 0; i < len; i++) {
            var e = unit[i];
            var en = pbr.Enemy(e.name,e.x, e.y, this.enemyID, e.param).addChildTo(this);
            if (en.data.type == ENEMY_BOSS) {
                this.bossGauge.setTarget(en);
                this.systemBase.tweener.clear().moveBy(0, 32, 1000);
            }
            this.enemyID++;
            this.enemyCount++;
        }
    },

    //敵単体の投入
    enterEnemy: function(name, x, y, param) {
        this.enemyID++;
        this.enemyCount++;
        return pbr.Enemy(name, x, y, this.enemyID-1, param).addChildTo(this);
    },

    //敵弾一括消去
    eraseBullet: function() {
    },

    //タッチorクリック開始処理
    onpointstart: function(e) {
    },

    //タッチorクリック移動処理
    onpointmove: function(e) {
    },

    //タッチorクリック終了処理
    onpointend: function(e) {
    },

    //addChildオーバーライド
    addChild: function(child) {
        if (child.layer === undefined) {
            return this.superClass.prototype.addChild.apply(this, arguments);
        }
        child.parentScene = this;
        return this.layers[child.layer].addChild(child);
    },
});
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import { Animated, Text, TouchableOpacity, View } from 'react-native';

import Animation from 'lottie-react-native';
import { BlurView } from 'react-native-blur';

import loader from '../animation/loader.json';

import { FluidCard, FluidHeader, FluidButton } from '../components';
import { GetItem, SetItem } from '../persistence/db-helper';

import Icon from '../resources/icon';
import NewTrip from './new-trip';

import { height, width } from '../global';

class Ongoing extends Component {
  state = {
    onStartFade: new Animated.Value(0),
    newTripFade: new Animated.Value(0),
    loadingFade: new Animated.Value(0),
    displayNewTripView: false,
    displayLoadingBar: true,
    displayEditTrip: false,
    blur: false,
    id: '',
    results: {},
    disabled: true,
    visible: true,
  };

  constructor(props) {
    super(props);
  }

  componentWillMount() {
    this.fadeInit();
    this.setFlip();
  }

  componentDidMount() {
    GetItem('ID').then(id => this.setState({ id: id }));
  }

  fadeInit() {
    Animated.timing(this.state.onStartFade, {
      toValue: 1,
      duration: 2000,
    }).start(animation => {
      if (animation.finished) {
        this.setState({ disabled: false });
      }
    });
  }

  setFlip() {
    this.flipValue = new Animated.Value(0);
    this.flipValueListener = 0;

    this.flipValue.addListener(({ value }) => {
      this.flipValueListener = value;
    });

    this.frontInterpolate = this.flipValue.interpolate({
      inputRange: [0, 180],
      outputRange: ['0deg', '180deg'],
    });
    this.backInterpolate = this.flipValue.interpolate({
      inputRange: [0, 180],
      outputRange: ['180deg', '360deg'],
    });
  }

  flipCard() {
    if (this.flipValueListener >= 90) {
      Animated.spring(this.flipValue, {
        toValue: 0,
        friction: 8,
        tension: 10,
      }).start();
    } else {
      Animated.spring(this.flipValue, {
        toValue: 180,
        friction: 8,
        tension: 10,
      }).start();
    }
    // Need to make a state var holding isFlipped and Remove the reverse animation
  }

  fetchResults = async () => {
    let response = await fetch(
      'http://localhost:8000/v1/results?id=' + this.state.id,
    );

    return await response.json();
  };

  flipAndLoad = () => {
    this.fetchResults()
      .then(results => SetItem('RESULTS', JSON.stringify(results)))
      .catch(reason => console.log(reason.message));

    this.flipCard();

    let load = () => {
      Animated.timing(this.state.loadingFade, {
        toValue: 1,
        duration: 1000,
      }).start(() => this.loading.play());
    };

    if (this.state.displayLoadingBar) load();

    let asyncLoop = options => {
      let i = -1;

      let loop = () => {
        i++;
        if (i === options.length) {
          options.callback(this);
          return;
        }
        options.functionToLoop(loop, i);
      };
      loop();
    };

    asyncLoop({
      length: 10,
      functionToLoop: loop => {
        setTimeout(() => {
          GetItem('RESULTS')
            .then(results => {
              if (results !== null) {
                this.setState({ results: JSON.parse(results) });
              }
            })
            .catch(error => console.log('An error occurred: ' + error));
          loop();
        }, 1000);
      },
      callback: parent => {
        if (parent.state.results !== null)
          Animated.timing(this.state.loadingFade, {
            toValue: 0,
            duration: 1500,
          }).start(() =>
            this.setState({ displayLoadingBar: false, displayEditTrip: true }),
          );
      },
    });
  };

  newTrip() {
    const frontAnimatedStyle = {
      transform: [{ rotateY: this.frontInterpolate }],
      backfaceVisibility: 'hidden',
    };
    const backAnimatedStyle = {
      transform: [{ rotateY: this.backInterpolate }],
      backfaceVisibility: 'hidden',
    };

    fadeInNewTrip = () => {
      Animated.timing(this.state.newTripFade, {
        toValue: 1,
        duration: 250,
      }).start();
    };

    fadeOutNewTrip = () => {
      Animated.timing(this.state.newTripFade, {
        toValue: 0,
        duration: 250,
      }).start(() => {
        this.setState({
          displayNewTripView: false,
          blur: false,
          newTripFade: new Animated.Value(0),
          visible: true,
        });
      });
    };

    loadingBar = () =>
      <Animated.View style={{ opacity: this.state.loadingFade }}>
        <Animation
          ref={animation => {
            this.loading = animation;
          }}
          style={{
            width: width * 0.8,
            height: width * 0.8,
          }}
          loop={true}
          speed={0.5}
          source={loader}
        />
      </Animated.View>;

    fadeInNewTrip();

    return (
      <Animated.View
        style={[styles.centerView, { opacity: this.state.newTripFade }]}>
        <FluidCard
          height={height * 0.7}
          style={[
            backAnimatedStyle,
            { borderWidth: 0, justifyContent: 'center' },
          ]}>
          <View style={{ flex: 0, borderWidth: 0 }}>
            {this.state.displayLoadingBar ? loadingBar() : null}
          </View>
          <View>
            {this.state.displayEditTrip ? this.editTrip() : null}
          </View>
        </FluidCard>
        <FluidCard
          height={height * 0.7}
          style={[
            { borderWidth: 0, position: 'absolute', justifyContent: 'center' },
            frontAnimatedStyle,
          ]}>
          <View style={{ borderWidth: 0 }}>
            <NewTrip />
            <View style={{ flex: 0, justifyContent: 'center', borderWidth: 0 }}>
              <FluidButton
                alignSelf="center"
                style={{ marginTop: height * 0.7 * 0.06 }}
                onPress={() => this.flipAndLoad()}>
                Next
              </FluidButton>
            </View>
          </View>
          <TouchableOpacity
            onPress={() => {
              fadeOutNewTrip();
            }}
            style={{
              position: 'absolute',
              top: 0,
              borderWidth: 0,
            }}>
            <Icon
              name="X"
              size={15}
              color="#2B2B2B"
              style={{
                borderWidth: 0,
                marginLeft: height * 0.7 * 0.04,
                marginTop: height * 0.7 * 0.04,
                marginBottom: height * 0.7 * 0.04,
              }}
            />
          </TouchableOpacity>
        </FluidCard>
      </Animated.View>
    );
  }

  editTrip() {
    return (
      <View>
        <Text>
          {JSON.stringify(this.state.results)}
        </Text>
      </View>
    );
  }

  render() {
    return (
      <View style={{ flex: 1 }}>
        <FluidHeader>Ongoing</FluidHeader>
        <Animated.View
          style={{
            alignItems: 'center',
            opacity: this.state.onStartFade,
          }}>
          {this.state.visible &&
            <TouchableOpacity
              disabled={this.state.disabled}
              onPress={() => {
                this.setState({ displayNewTripView: true, blur: true });
                this.setState({ visible: false });
              }}>
              <FluidCard
                height={height * 0.52}
                style={{
                  justifyContent: 'center',
                  alignItems: 'center',
                }}>
                <Text style={styles.textStyle}>Tap to add a new trip.</Text>
              </FluidCard>
            </TouchableOpacity>}
        </Animated.View>
        {this.state.blur
          ? <BlurView blurType="light" style={styles.absolute} />
          : null}
        {this.state.displayNewTripView ? this.newTrip() : null}
      </View>
    );
  }
}

const styles = {
  absolute: {
    position: 'absolute',
    top: 0,
    left: 0,
    bottom: 0,
    right: 0,
  },

  initCard: {
    alignItems: 'center',
  },

  centerView: {
    position: 'absolute',
    top: 0,
    bottom: 0,
    left: 0,
    right: 0,
    justifyContent: 'center',
    alignItems: 'center',
    flex: 1,
  },

  textStyle: {
    fontFamily: 'Rubik',
    fontSize: 18,
    fontWeight: '200',
    textAlign: 'center',
  },
};

export default Ongoing;
<commit_msg>increase fade duration<commit_after>import React, { Component } from 'react';
import { Animated, Text, TouchableOpacity, View } from 'react-native';

import Animation from 'lottie-react-native';
import { BlurView } from 'react-native-blur';

import loader from '../animation/loader.json';

import { FluidCard, FluidHeader, FluidButton } from '../components';
import { GetItem, SetItem } from '../persistence/db-helper';

import Icon from '../resources/icon';
import NewTrip from './new-trip';

import { height, width } from '../global';

class Ongoing extends Component {
  state = {
    onStartFade: new Animated.Value(0),
    newTripFade: new Animated.Value(0),
    loadingFade: new Animated.Value(0),
    displayNewTripView: false,
    displayLoadingBar: true,
    displayEditTrip: false,
    blur: false,
    id: '',
    results: {},
    disabled: true,
    visible: true,
  };

  constructor(props) {
    super(props);
  }

  componentWillMount() {
    this.fadeInit();
    this.setFlip();
  }

  componentDidMount() {
    GetItem('ID').then(id => this.setState({ id: id }));
  }

  fadeInit() {
    Animated.timing(this.state.onStartFade, {
      toValue: 1,
      duration: 2000,
    }).start(animation => {
      if (animation.finished) {
        this.setState({ disabled: false });
      }
    });
  }

  setFlip() {
    this.flipValue = new Animated.Value(0);
    this.flipValueListener = 0;

    this.flipValue.addListener(({ value }) => {
      this.flipValueListener = value;
    });

    this.frontInterpolate = this.flipValue.interpolate({
      inputRange: [0, 180],
      outputRange: ['0deg', '180deg'],
    });
    this.backInterpolate = this.flipValue.interpolate({
      inputRange: [0, 180],
      outputRange: ['180deg', '360deg'],
    });
  }

  flipCard() {
    if (this.flipValueListener >= 90) {
      Animated.spring(this.flipValue, {
        toValue: 0,
        friction: 8,
        tension: 10,
      }).start();
    } else {
      Animated.spring(this.flipValue, {
        toValue: 180,
        friction: 8,
        tension: 10,
      }).start();
    }
    // Need to make a state var holding isFlipped and Remove the reverse animation
  }

  fetchResults = async () => {
    let response = await fetch(
      'http://localhost:8000/v1/results?id=' + this.state.id,
    );

    return await response.json();
  };

  flipAndLoad = () => {
    this.fetchResults()
      .then(results => SetItem('RESULTS', JSON.stringify(results)))
      .catch(reason => console.log(reason.message));

    this.flipCard();

    let load = () => {
      Animated.timing(this.state.loadingFade, {
        toValue: 1,
        duration: 1000,
      }).start(() => this.loading.play());
    };

    if (this.state.displayLoadingBar) load();

    let asyncLoop = options => {
      let i = -1;

      let loop = () => {
        i++;
        if (i === options.length) {
          options.callback(this);
          return;
        }
        options.functionToLoop(loop, i);
      };
      loop();
    };

    asyncLoop({
      length: 10,
      functionToLoop: loop => {
        setTimeout(() => {
          GetItem('RESULTS')
            .then(results => {
              if (results !== null) {
                this.setState({ results: JSON.parse(results) });
              }
            })
            .catch(error => console.log('An error occurred: ' + error));
          loop();
        }, 1000);
      },
      callback: parent => {
        if (parent.state.results !== null)
          Animated.timing(this.state.loadingFade, {
            toValue: 0,
            duration: 2000,
          }).start(() =>
            this.setState({ displayLoadingBar: false, displayEditTrip: true }),
          );
      },
    });
  };

  newTrip() {
    const frontAnimatedStyle = {
      transform: [{ rotateY: this.frontInterpolate }],
      backfaceVisibility: 'hidden',
    };
    const backAnimatedStyle = {
      transform: [{ rotateY: this.backInterpolate }],
      backfaceVisibility: 'hidden',
    };

    fadeInNewTrip = () => {
      Animated.timing(this.state.newTripFade, {
        toValue: 1,
        duration: 250,
      }).start();
    };

    fadeOutNewTrip = () => {
      Animated.timing(this.state.newTripFade, {
        toValue: 0,
        duration: 250,
      }).start(() => {
        this.setState({
          displayNewTripView: false,
          blur: false,
          newTripFade: new Animated.Value(0),
          visible: true,
        });
      });
    };

    loadingBar = () =>
      <Animated.View style={{ opacity: this.state.loadingFade }}>
        <Animation
          ref={animation => {
            this.loading = animation;
          }}
          style={{
            width: width * 0.8,
            height: width * 0.8,
          }}
          loop={true}
          speed={0.5}
          source={loader}
        />
      </Animated.View>;

    fadeInNewTrip();

    return (
      <Animated.View
        style={[styles.centerView, { opacity: this.state.newTripFade }]}>
        <FluidCard
          height={height * 0.7}
          style={[
            backAnimatedStyle,
            { borderWidth: 0, justifyContent: 'center' },
          ]}>
          <View style={{ flex: 0, borderWidth: 0 }}>
            {this.state.displayLoadingBar ? loadingBar() : null}
          </View>
          <View>
            {this.state.displayEditTrip ? this.editTrip() : null}
          </View>
        </FluidCard>
        <FluidCard
          height={height * 0.7}
          style={[
            { borderWidth: 0, position: 'absolute', justifyContent: 'center' },
            frontAnimatedStyle,
          ]}>
          <View style={{ borderWidth: 0 }}>
            <NewTrip />
            <View style={{ flex: 0, justifyContent: 'center', borderWidth: 0 }}>
              <FluidButton
                alignSelf="center"
                style={{ marginTop: height * 0.7 * 0.06 }}
                onPress={() => this.flipAndLoad()}>
                Next
              </FluidButton>
            </View>
          </View>
          <TouchableOpacity
            onPress={() => {
              fadeOutNewTrip();
            }}
            style={{
              position: 'absolute',
              top: 0,
              borderWidth: 0,
            }}>
            <Icon
              name="X"
              size={15}
              color="#2B2B2B"
              style={{
                borderWidth: 0,
                marginLeft: height * 0.7 * 0.04,
                marginTop: height * 0.7 * 0.04,
                marginBottom: height * 0.7 * 0.04,
              }}
            />
          </TouchableOpacity>
        </FluidCard>
      </Animated.View>
    );
  }

  editTrip() {
    return (
      <View>
        <Text>
          {JSON.stringify(this.state.results)}
        </Text>
      </View>
    );
  }

  render() {
    return (
      <View style={{ flex: 1 }}>
        <FluidHeader>Ongoing</FluidHeader>
        <Animated.View
          style={{
            alignItems: 'center',
            opacity: this.state.onStartFade,
          }}>
          {this.state.visible &&
            <TouchableOpacity
              disabled={this.state.disabled}
              onPress={() => {
                this.setState({ displayNewTripView: true, blur: true });
                this.setState({ visible: false });
              }}>
              <FluidCard
                height={height * 0.52}
                style={{
                  justifyContent: 'center',
                  alignItems: 'center',
                }}>
                <Text style={styles.textStyle}>Tap to add a new trip.</Text>
              </FluidCard>
            </TouchableOpacity>}
        </Animated.View>
        {this.state.blur
          ? <BlurView blurType="light" style={styles.absolute} />
          : null}
        {this.state.displayNewTripView ? this.newTrip() : null}
      </View>
    );
  }
}

const styles = {
  absolute: {
    position: 'absolute',
    top: 0,
    left: 0,
    bottom: 0,
    right: 0,
  },

  initCard: {
    alignItems: 'center',
  },

  centerView: {
    position: 'absolute',
    top: 0,
    bottom: 0,
    left: 0,
    right: 0,
    justifyContent: 'center',
    alignItems: 'center',
    flex: 1,
  },

  textStyle: {
    fontFamily: 'Rubik',
    fontSize: 18,
    fontWeight: '200',
    textAlign: 'center',
  },
};

export default Ongoing;
<|endoftext|>


<commit_before>/* Secure Creatives
  Provides support for rendering creatives into cross domain iframes such as SafeFrame to prevent
   access to a publisher page from creative payloads.
 */

import events from './events';
import { fireNativeTrackers, getAssetMessage } from './native';
import { EVENTS } from './constants';
import { isSlotMatchingAdUnitCode, logWarn, replaceAuctionPrice } from './utils';
import { auctionManager } from './auctionManager';
import find from 'core-js/library/fn/array/find';
import { isRendererRequired, executeRenderer } from './Renderer';

const BID_WON = EVENTS.BID_WON;

export function listenMessagesFromCreative() {
  addEventListener('message', receiveMessage, false);
}

function receiveMessage(ev) {
  var key = ev.message ? 'message' : 'data';
  var data = {};
  try {
    data = JSON.parse(ev[key]);
  } catch (e) {
    return;
  }

  if (data && data.adId) {
    const adObject = find(auctionManager.getBidsReceived(), function (bid) {
      return bid.adId === data.adId;
    });

    if (data.message === 'Prebid Request') {
      _sendAdToCreative(adObject, data.adServerDomain, ev.source);

      // save winning bids
      auctionManager.addWinningBid(adObject);

      events.emit(BID_WON, adObject);
    }

    // handle this script from native template in an ad server
    // window.parent.postMessage(JSON.stringify({
    //   message: 'Prebid Native',
    //   adId: '%%PATTERN:hb_adid%%'
    // }), '*');
    if (data.message === 'Prebid Native') {
      if (data.action === 'assetRequest') {
        const message = getAssetMessage(data, adObject);
        ev.source.postMessage(JSON.stringify(message), ev.origin);
        return;
      }

      const trackerType = fireNativeTrackers(data, adObject);
      if (trackerType === 'click') { return; }

      auctionManager.addWinningBid(adObject);
      events.emit(BID_WON, adObject);
    }
  }
}

export function _sendAdToCreative(adObject, remoteDomain, source) {
  const { adId, ad, adUrl, width, height, renderer, cpm } = adObject;
  // rendering for outstream safeframe
  if (isRendererRequired(renderer)) {
    executeRenderer(renderer, adObject);
  } else if (adId) {
    resizeRemoteCreative(adObject);
    source.postMessage(JSON.stringify({
      message: 'Prebid Response',
      ad: replaceAuctionPrice(ad, cpm),
      adUrl: replaceAuctionPrice(adUrl, cpm),
      adId,
      width,
      height
    }), remoteDomain);
  }
}

function resizeRemoteCreative({ adUnitCode, width, height }) {
  // resize both container div + iframe
  ['div:last-child', 'div:last-child iframe'].forEach(elmType => {
    let element = getElementByAdUnit(elmType);
    if (element) {
      let elementStyle = element.style;
      elementStyle.width = width + 'px';
      elementStyle.height = height + 'px';
    } else {
      logWarn(`Unable to locate matching page element for adUnitCode ${adUnitCode}.  Can't resize it to ad's dimensions.  Please review setup.`);
    }
  });

  function getElementByAdUnit(elmType) {
    let id = getElementIdBasedOnAdServer(adUnitCode);
    let parentDivEle = document.getElementById(id);
    return parentDivEle && parentDivEle.querySelector(elmType);
  }

  function getElementIdBasedOnAdServer(adUnitCode) {
    if (window.googletag) {
      return getDfpElementId(adUnitCode)
    } else if (window.apntag) {
      return getAstElementId(adUnitCode)
    } else {
      return adUnitCode;
    }
  }

  function getDfpElementId(adUnitCode) {
    return find(window.googletag.pubads().getSlots().filter(isSlotMatchingAdUnitCode(adUnitCode)), slot => slot).getSlotElementId()
  }

  function getAstElementId(adUnitCode) {
    let astTag = window.apntag.getTag(adUnitCode);
    return astTag && astTag.targetId;
  }
}
<commit_msg>add check to see if adObject is present (#4058)<commit_after>/* Secure Creatives
  Provides support for rendering creatives into cross domain iframes such as SafeFrame to prevent
   access to a publisher page from creative payloads.
 */

import events from './events';
import { fireNativeTrackers, getAssetMessage } from './native';
import { EVENTS } from './constants';
import { isSlotMatchingAdUnitCode, logWarn, replaceAuctionPrice } from './utils';
import { auctionManager } from './auctionManager';
import find from 'core-js/library/fn/array/find';
import { isRendererRequired, executeRenderer } from './Renderer';

const BID_WON = EVENTS.BID_WON;

export function listenMessagesFromCreative() {
  addEventListener('message', receiveMessage, false);
}

function receiveMessage(ev) {
  var key = ev.message ? 'message' : 'data';
  var data = {};
  try {
    data = JSON.parse(ev[key]);
  } catch (e) {
    return;
  }

  if (data && data.adId) {
    const adObject = find(auctionManager.getBidsReceived(), function (bid) {
      return bid.adId === data.adId;
    });

    if (adObject && data.message === 'Prebid Request') {
      _sendAdToCreative(adObject, data.adServerDomain, ev.source);

      // save winning bids
      auctionManager.addWinningBid(adObject);

      events.emit(BID_WON, adObject);
    }

    // handle this script from native template in an ad server
    // window.parent.postMessage(JSON.stringify({
    //   message: 'Prebid Native',
    //   adId: '%%PATTERN:hb_adid%%'
    // }), '*');
    if (adObject && data.message === 'Prebid Native') {
      if (data.action === 'assetRequest') {
        const message = getAssetMessage(data, adObject);
        ev.source.postMessage(JSON.stringify(message), ev.origin);
        return;
      }

      const trackerType = fireNativeTrackers(data, adObject);
      if (trackerType === 'click') { return; }

      auctionManager.addWinningBid(adObject);
      events.emit(BID_WON, adObject);
    }
  }
}

export function _sendAdToCreative(adObject, remoteDomain, source) {
  const { adId, ad, adUrl, width, height, renderer, cpm } = adObject;
  // rendering for outstream safeframe
  if (isRendererRequired(renderer)) {
    executeRenderer(renderer, adObject);
  } else if (adId) {
    resizeRemoteCreative(adObject);
    source.postMessage(JSON.stringify({
      message: 'Prebid Response',
      ad: replaceAuctionPrice(ad, cpm),
      adUrl: replaceAuctionPrice(adUrl, cpm),
      adId,
      width,
      height
    }), remoteDomain);
  }
}

function resizeRemoteCreative({ adUnitCode, width, height }) {
  // resize both container div + iframe
  ['div:last-child', 'div:last-child iframe'].forEach(elmType => {
    let element = getElementByAdUnit(elmType);
    if (element) {
      let elementStyle = element.style;
      elementStyle.width = width + 'px';
      elementStyle.height = height + 'px';
    } else {
      logWarn(`Unable to locate matching page element for adUnitCode ${adUnitCode}.  Can't resize it to ad's dimensions.  Please review setup.`);
    }
  });

  function getElementByAdUnit(elmType) {
    let id = getElementIdBasedOnAdServer(adUnitCode);
    let parentDivEle = document.getElementById(id);
    return parentDivEle && parentDivEle.querySelector(elmType);
  }

  function getElementIdBasedOnAdServer(adUnitCode) {
    if (window.googletag) {
      return getDfpElementId(adUnitCode)
    } else if (window.apntag) {
      return getAstElementId(adUnitCode)
    } else {
      return adUnitCode;
    }
  }

  function getDfpElementId(adUnitCode) {
    return find(window.googletag.pubads().getSlots().filter(isSlotMatchingAdUnitCode(adUnitCode)), slot => slot).getSlotElementId()
  }

  function getAstElementId(adUnitCode) {
    let astTag = window.apntag.getTag(adUnitCode);
    return astTag && astTag.targetId;
  }
}
<|endoftext|>