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

tm.define("shotgun.Button", {
    superClass: tm.display.CanvasElement,

    //描画スタイル設定
    DEFAULT_STYLE: {
        buttonColor: 'rgba(50, 150, 255, 0.8)',
        lineColor: 'rgba(200, 200, 200, 0.5)',
        lineWidth: 4,
        shadowColor: 'rgba(0, 0, 0, 0.5)',
        fontFamily: "azuki",
        fontSize: 50,
    },

    labelParam: {fontFamily: "azuki", align: "center", baseline:"middle", outlineWidth:3 },

    text: "",
    push: false,
    lock: false,

    //ボタン押下時の移動量
    downX: 0,
    downY: 10,

    init: function(width, height, text, style) {
        this.superInit();

        this.width = width || 200;
        this.height = height || 80;
        this.text = text || "";

        //セットアップ
        this.setup(style);

        //判定処理設定
        this.interactive = true;
        this.boundingType = "rect";
//        this.checkHierarchy = true;

        //イベントリスナ登録
        this.addEventListener("touchstart", function() {
            if (this.lock) return;

            this.push = true;
            this.button.x += this.downX;
            this.button.y += this.downY;
            var e = tm.event.Event("push");
            this.dispatchEvent(e);
        });
        this.addEventListener("touchmove", function(e) {
            if (this.lock) return;

            var pt = e.pointing;
            if (this.isHitPoint(pt.x, pt.y)) {
                if (!this.push) {
                    this.push = true;
                    this.button.x += this.downX;
                    this.button.y += this.downY;
                }
            } else {
                if (this.push) {
                    this.push = false;
                    this.button.x -= this.downX;
                    this.button.y -= this.downY;
                }
            }
        });
        this.addEventListener("touchend", function(e) {
            if (this.lock) return;

            var pt = e.pointing;
            if (this.isHitPoint(pt.x, pt.y)) {
                this.push = false;
                this.button.x -= this.downX;
                this.button.y -= this.downY;

                var e = tm.event.Event("pushed");
                this.dispatchEvent(e);
            }
        });
    },

    setup: function(style) {
        style = style || {};
        style.$safe(this.DEFAULT_STYLE)

        //登録済みの場合破棄する
        if (this.shadow) {
            this.shadow.remove();
            this.label.remove();
            this.button.remove();
        }

        var width = this.width, height = this.height;

        //ボタン影
        var shadowStyle = {
            fillStyle: style.shadowColor,
            strokeStyle: style.shadowColor,
            lineWidth: style.lineWidth
        };
        this.shadow = tm.display.RectangleShape(width, height, shadowStyle)
            .addChildTo(this)
            .setPosition(this.downX, this.downY);
        this.shadow.blendMode = "source-over";

        //ボタン本体
        var buttonStyle = {
            fillStyle: style.buttonColor,
            strokeStyle: style.lineColor,
            lineWidth: style.lineWidth
        };
        this.button = tm.display.RectangleShape(width, height, buttonStyle)
            .addChildTo(this);

        //ボタンラベル
        this.labelParam.fontFamily = style.fontFamily;
        this.label = tm.display.OutlineLabel(this.text, style.fontSize)
            .addChildTo(this.button)
            .setParam(this.labelParam);
    },
    setVisible: function(b) {
        this.shadow.visible = b;
        this.button.visible = b;
        this.label.visible = b;
        this.lock = !b;
        return this;
    },
    setLock: function(b) {
        this.lock = b;
        return this;
    },
});

tm.define("shotgun.RoundButton", {
    superClass: tm.display.CanvasElement,

    //描画スタイル設定
    DEFAULT_STYLE: {
        buttonColor: 'rgba(50, 150, 255, 0.8)',
        lineColor: 'rgba(200, 200, 200, 0.5)',
        lineWidth: 4,
        shadowColor: 'rgba(0, 0, 0, 0.5)',
        fontFamily: "azuki",
        fontSize: 50,
        radius: 16,
    },

    labelParam: {fontFamily: "azuki", align: "center", baseline:"middle", outlineWidth:3 },

    text: "",
    push: false,
    lock: false,

    //ボタン押下時の移動量
    downX: 0,
    downY: 10,

    init: function(width, height, text, style) {
        this.superInit();

        this.width = width || 200;
        this.height = height || 80;
        this.text = text || "";

        //セットアップ
        this.setup(style);

        //判定処理設定
        this.interactive = true;
        this.boundingType = "rect";
//        this.checkHierarchy = true;

        //イベントリスナ登録
        this.addEventListener("touchstart", function() {
            if (this.lock) return;

            this.push = true;
            this.button.x += this.downX;
            this.button.y += this.downY;
            var e = tm.event.Event("push");
            this.dispatchEvent(e);
        });
        this.addEventListener("touchmove", function(e) {
            if (this.lock) return;

            var pt = e.pointing;
            if (this.isHitPoint(pt.x, pt.y)) {
                if (!this.push) {
                    this.push = true;
                    this.button.x += this.downX;
                    this.button.y += this.downY;
                }
            } else {
                if (this.push) {
                    this.push = false;
                    this.button.x -= this.downX;
                    this.button.y -= this.downY;
                }
            }
        });
        this.addEventListener("touchend", function(e) {
            if (this.lock) return;

            var pt = e.pointing;
            if (this.isHitPoint(pt.x, pt.y)) {
                this.push = false;
                this.button.x -= this.downX;
                this.button.y -= this.downY;

                var e = tm.event.Event("pushed");
                this.dispatchEvent(e);
            }
        });
    },

    setup: function(style) {
        style = style || {};
        style.$safe(this.DEFAULT_STYLE)

        //登録済みの場合破棄する
        if (this.shadow) {
            this.shadow.remove();
            this.label.remove();
            this.button.remove();
        }

        var width = this.width, height = this.height;

        //ボタン影
        var shadowStyle = {
            fillStyle: style.shadowColor,
            strokeStyle: style.shadowColor,
            lineWidth: style.lineWidth,
            radius: style.radius,
        };
        this.shadow = tm.display.RoundRectangleShape(width, height, shadowStyle)
            .addChildTo(this)
            .setPosition(this.downX, this.downY);
        this.shadow.blendMode = "source-over";

        //ボタン本体
        var buttonStyle = {
            fillStyle: style.buttonColor,
            strokeStyle: style.lineColor,
            lineWidth: style.lineWidth,
            radius: style.radius,
        };
        this.button = tm.display.RoundRectangleShape(width, height, buttonStyle)
            .addChildTo(this);

        //ボタンラベル
        this.labelParam.fontFamily = style.fontFamily;
        this.label = tm.display.OutlineLabel(this.text, style.fontSize)
            .addChildTo(this.button)
            .setParam(this.labelParam);
    },
    setLock: function(b) {
        this.lock = b;
        return this;
    },
});

tm.define("shotgun.ToggleButton", {
    superClass: tm.app.Object2D,

    //描画スタイル設定
    DEFAULT_STYLE: {
        buttonColor: 'rgba(50, 150, 255, 0.8)',
        lineColor: 'rgba(200, 200, 200, 0.5)',
        lineWidth: 4,
        shadowColor: 'rgba(0, 0, 0, 0.5)',
        fontFamily: "azuki",
        fontSize: 50,
    },
    labelParam: {fontFamily: "azuki", align: "center", baseline:"middle", outlineWidth:3 },

    onText: "",
    offText: "",
    push: false,
    lock: false,
    _toggleON: false,

    //ボタン押下時の移動量
    downX: 0,
    downY: 10,

    init: function(width, height, onText, offText, style) {
        this.superInit();

        this.width = width || 200;
        this.height = height || 80;
        this.onText = onText || "";
        this.offText = offText || "";

        this.text = this.offText;

        //セットアップ
        this.setup(style);

        //判定処理設定
        this.interactive = true;
        this.boundingType = "rect";
//        this.checkHierarchy = true;

        //イベントリスナ登録
        this.addEventListener("touchstart", function() {
            if (this.lock) return;

            this.push = true;
            if (this._toggleON) {
                this.button.x += this.downX*0.5;
                this.button.y += this.downY*0.5;
            } else {
                this.button.x += this.downX*1.5;
                this.button.y += this.downY*1.5;
            }

            var e = tm.event.Event("push");
            this.dispatchEvent(e);
        });
        this.addEventListener("touchmove", function(e) {
            if (this.lock) return;

            var pt = e.pointing;
            if (this.isHitPoint(pt.x, pt.y)) {
                if (!this.push) {
                    this.push = true;
                    if (this._toggleON) {
                        this.button.x += this.downX*0.5;
                        this.button.y += this.downY*0.5;
                    } else {
                        this.button.x += this.downX*1.5;
                        this.button.y += this.downY*1.5;
                    }
                }
            } else {
                if (this.push) {
                    this.push = false;
                    if (this._toggleON) {
                        this.button.x -= this.downX*0.5;
                        this.button.y -= this.downY*0.5;
                    } else {
                        this.button.x -= this.downX*1.5;
                        this.button.y -= this.downY*1.5;
                    }
                }
            }
        });
        this.addEventListener("touchend", function(e) {
            if (this.lock) return;

            var pt = e.pointing;
            if (this.isHitPoint(pt.x, pt.y)) {
                this.push = false;
                this._toggleON = !this._toggleON;
                if (this._toggleON) {
                    this.text = this.onText;
                    this.button.x -= this.downX*0.5;
                    this.button.y -= this.downY*0.5;
                } else {
                    this.text = this.offText;
                    this.button.x -= this.downX*1.5;
                    this.button.y -= this.downY*1.5;
                }
                this.label.text = this.text;
                var e = tm.event.Event("pushed");
                this.dispatchEvent(e);
            }
        });
    },

    setup: function(style) {
        style = style || {};
        style.$safe(this.DEFAULT_STYLE)

        //登録済みの場合破棄する
        if (this.shadow) {
            this.shadow.remove();
            this.label.remove();
            this.button.remove();
        }

        var width = this.width, height = this.height;

        //ボタン影
        var shadowStyle = {
            fillStyle: style.shadowColor,
            strokeStyle: style.shadowColor,
            lineWidth: style.lineWidth
        };
        this.shadow = tm.display.RectangleShape(width, height, shadowStyle)
            .addChildTo(this)
            .setPosition(this.downX, this.downY);
        this.shadow.blendMode = "source-over";

        //ボタン本体
        var buttonStyle = {
            fillStyle: style.buttonColor,
            strokeStyle: style.lineColor,
            lineWidth: style.lineWidth
        };
        this.button = tm.display.RectangleShape(width, height, buttonStyle)
            .addChildTo(this);

        //ボタンラベル
        this.labelParam.fontFamily = style.fontFamily;
        this.label = tm.display.OutlineLabel(this.text, style.fontSize)
            .addChildTo(this.button)
            .setParam(this.labelParam);
    },
    setLock: function(b) {
        this.lock = b;
        return this;
    },
});

shotgun.ToggleButton.prototype.accessor("toggleON", {
    "set": function(b) {
        this._toggleON = b;

        if (this._toggleON) {
            this.button.x = this.downX;
            this.button.y = this.downY;
            this.text = this.onText;
        } else {
            this.button.x = 0;
            this.button.y = 0;
            this.text = this.offText;
        }
        this.label.text = this.text;
    },

    "get": function() {
        return this._toggleON;
    },
});

tm.define("shotgun.SlideButton", {
    superClass: tm.app.Object2D,

    //描画スタイル設定
    DEFAULT_STYLE: {
        width: 160,
        height: 80,

        buttonWitdh: 80,
        buttonHeight: 80,

        //ボタン色
        buttonColor: 'rgba(255, 255, 255, 1.0)',
        buttonLine:  'rgba(200, 200, 200, 1.0)',
        lineWidth: 2,

        //ベース(on/off)色
        onColor: 'rgba(0, 255, 0, 1.0)',
        offColor: 'rgba(200, 200, 200, 1.0)',
    },

    style: null,

    _slideON: false,

    init: function(style) {
        this.superInit();

        this.style = style || {};
        this.style.$safe(this.DEFAULT_STYLE)

        this.width = style.width || 160;
        this.height = style.height || 80;

        this.text = this.offText;

        //セットアップ
        this.setup();

        //判定処理設定
        this.interactive = true;
        this.boundingType = "rect";
//        this.checkHierarchy = true;

        //イベントリスナ登録
        this.addEventListener("touchstart", function() {
            if (this._slideON) {
            } else {
            }
            var e = tm.event.Event("slide");
            this.dispatchEvent(e);
        });
    },

    setup: function() {
        //登録済みの場合破棄する
        if (this.shadow) {
            this.shadow.remove();
            this.label.remove();
            this.button.remove();
        }

        var style = this.style;
        var width = this.width, height = this.height;
        var buttonWidth = this.button, heightButton = this.heightButton;

        //ボタンベース
        var baseStyle = {fillStyle: style.offColor, strokeStyle: style.offColor, lineWidth:  style.lineWidth};
        this.button = tm.display.RectangleShape(width, height, buttonStyle)
            .addChildTo(this);

        //ボタン本体
        var buttonStyle = {fillStyle: style.buttonColor, strokeStyle: style.lineColor, lineWidth:  style.lineWidth};
        this.button = tm.display.RectangleShape(buttonWidth, buttonHeight, buttonStyle)
            .addChildTo(this);
    },
});

shotgun.SlideButton.prototype.accessor("slideON", {
    "set": function(b) {
        this._slideON = b;

        if (this._slideON) {
        } else {
        }
    },

    "get": function() {
        return this._slideON;
    },
});
<commit_msg>基底クラスをCanvasElementに変更<commit_after>/*
 *  Button.js
 *  2014/06/24
 *  @auther minimo
 *  This Program is MIT license.
 *
 */

tm.define("shotgun.Button", {
    superClass: tm.display.CanvasElement,

    //描画スタイル設定
    DEFAULT_STYLE: {
        buttonColor: 'rgba(50, 150, 255, 0.8)',
        lineColor: 'rgba(200, 200, 200, 0.5)',
        lineWidth: 4,
        shadowColor: 'rgba(0, 0, 0, 0.5)',
        fontFamily: "azuki",
        fontSize: 50,
    },

    labelParam: {fontFamily: "azuki", align: "center", baseline:"middle", outlineWidth:3 },

    text: "",
    push: false,
    lock: false,

    //ボタン押下時の移動量
    downX: 0,
    downY: 10,

    init: function(width, height, text, style) {
        this.superInit();

        this.width = width || 200;
        this.height = height || 80;
        this.text = text || "";

        //セットアップ
        this.setup(style);

        //判定処理設定
        this.interactive = true;
        this.boundingType = "rect";
//        this.checkHierarchy = true;

        //イベントリスナ登録
        this.addEventListener("touchstart", function() {
            if (this.lock) return;

            this.push = true;
            this.button.x += this.downX;
            this.button.y += this.downY;
            var e = tm.event.Event("push");
            this.dispatchEvent(e);
        });
        this.addEventListener("touchmove", function(e) {
            if (this.lock) return;

            var pt = e.pointing;
            if (this.isHitPoint(pt.x, pt.y)) {
                if (!this.push) {
                    this.push = true;
                    this.button.x += this.downX;
                    this.button.y += this.downY;
                }
            } else {
                if (this.push) {
                    this.push = false;
                    this.button.x -= this.downX;
                    this.button.y -= this.downY;
                }
            }
        });
        this.addEventListener("touchend", function(e) {
            if (this.lock) return;

            var pt = e.pointing;
            if (this.isHitPoint(pt.x, pt.y)) {
                this.push = false;
                this.button.x -= this.downX;
                this.button.y -= this.downY;

                var e = tm.event.Event("pushed");
                this.dispatchEvent(e);
            }
        });
    },

    setup: function(style) {
        style = style || {};
        style.$safe(this.DEFAULT_STYLE)

        //登録済みの場合破棄する
        if (this.shadow) {
            this.shadow.remove();
            this.label.remove();
            this.button.remove();
        }

        var width = this.width, height = this.height;

        //ボタン影
        var shadowStyle = {
            fillStyle: style.shadowColor,
            strokeStyle: style.shadowColor,
            lineWidth: style.lineWidth
        };
        this.shadow = tm.display.RectangleShape(width, height, shadowStyle)
            .addChildTo(this)
            .setPosition(this.downX, this.downY);
        this.shadow.blendMode = "source-over";

        //ボタン本体
        var buttonStyle = {
            fillStyle: style.buttonColor,
            strokeStyle: style.lineColor,
            lineWidth: style.lineWidth
        };
        this.button = tm.display.RectangleShape(width, height, buttonStyle)
            .addChildTo(this);

        //ボタンラベル
        this.labelParam.fontFamily = style.fontFamily;
        this.label = tm.display.OutlineLabel(this.text, style.fontSize)
            .addChildTo(this.button)
            .setParam(this.labelParam);
    },
    setVisible: function(b) {
        this.shadow.visible = b;
        this.button.visible = b;
        this.label.visible = b;
        this.lock = !b;
        return this;
    },
    setLock: function(b) {
        this.lock = b;
        return this;
    },
});

tm.define("shotgun.RoundButton", {
    superClass: tm.display.CanvasElement,

    //描画スタイル設定
    DEFAULT_STYLE: {
        buttonColor: 'rgba(50, 150, 255, 0.8)',
        lineColor: 'rgba(200, 200, 200, 0.5)',
        lineWidth: 4,
        shadowColor: 'rgba(0, 0, 0, 0.5)',
        fontFamily: "azuki",
        fontSize: 50,
        radius: 16,
    },

    labelParam: {fontFamily: "azuki", align: "center", baseline:"middle", outlineWidth:3 },

    text: "",
    push: false,
    lock: false,

    //ボタン押下時の移動量
    downX: 0,
    downY: 10,

    init: function(width, height, text, style) {
        this.superInit();

        this.width = width || 200;
        this.height = height || 80;
        this.text = text || "";

        //セットアップ
        this.setup(style);

        //判定処理設定
        this.interactive = true;
        this.boundingType = "rect";
//        this.checkHierarchy = true;

        //イベントリスナ登録
        this.addEventListener("touchstart", function() {
            if (this.lock) return;

            this.push = true;
            this.button.x += this.downX;
            this.button.y += this.downY;
            var e = tm.event.Event("push");
            this.dispatchEvent(e);
        });
        this.addEventListener("touchmove", function(e) {
            if (this.lock) return;

            var pt = e.pointing;
            if (this.isHitPoint(pt.x, pt.y)) {
                if (!this.push) {
                    this.push = true;
                    this.button.x += this.downX;
                    this.button.y += this.downY;
                }
            } else {
                if (this.push) {
                    this.push = false;
                    this.button.x -= this.downX;
                    this.button.y -= this.downY;
                }
            }
        });
        this.addEventListener("touchend", function(e) {
            if (this.lock) return;

            var pt = e.pointing;
            if (this.isHitPoint(pt.x, pt.y)) {
                this.push = false;
                this.button.x -= this.downX;
                this.button.y -= this.downY;

                var e = tm.event.Event("pushed");
                this.dispatchEvent(e);
            }
        });
    },

    setup: function(style) {
        style = style || {};
        style.$safe(this.DEFAULT_STYLE)

        //登録済みの場合破棄する
        if (this.shadow) {
            this.shadow.remove();
            this.label.remove();
            this.button.remove();
        }

        var width = this.width, height = this.height;

        //ボタン影
        var shadowStyle = {
            fillStyle: style.shadowColor,
            strokeStyle: style.shadowColor,
            lineWidth: style.lineWidth,
            radius: style.radius,
        };
        this.shadow = tm.display.RoundRectangleShape(width, height, shadowStyle)
            .addChildTo(this)
            .setPosition(this.downX, this.downY);
        this.shadow.blendMode = "source-over";

        //ボタン本体
        var buttonStyle = {
            fillStyle: style.buttonColor,
            strokeStyle: style.lineColor,
            lineWidth: style.lineWidth,
            radius: style.radius,
        };
        this.button = tm.display.RoundRectangleShape(width, height, buttonStyle)
            .addChildTo(this);

        //ボタンラベル
        this.labelParam.fontFamily = style.fontFamily;
        this.label = tm.display.OutlineLabel(this.text, style.fontSize)
            .addChildTo(this.button)
            .setParam(this.labelParam);
    },
    setLock: function(b) {
        this.lock = b;
        return this;
    },
});

tm.define("shotgun.ToggleButton", {
    superClass: tm.display.CanvasElement,

    //描画スタイル設定
    DEFAULT_STYLE: {
        buttonColor: 'rgba(50, 150, 255, 0.8)',
        lineColor: 'rgba(200, 200, 200, 0.5)',
        lineWidth: 4,
        shadowColor: 'rgba(0, 0, 0, 0.5)',
        fontFamily: "azuki",
        fontSize: 50,
    },
    labelParam: {fontFamily: "azuki", align: "center", baseline:"middle", outlineWidth:3 },

    onText: "",
    offText: "",
    push: false,
    lock: false,
    _toggleON: false,

    //ボタン押下時の移動量
    downX: 0,
    downY: 10,

    init: function(width, height, onText, offText, style) {
        this.superInit();

        this.width = width || 200;
        this.height = height || 80;
        this.onText = onText || "";
        this.offText = offText || "";

        this.text = this.offText;

        //セットアップ
        this.setup(style);

        //判定処理設定
        this.interactive = true;
        this.boundingType = "rect";
//        this.checkHierarchy = true;

        //イベントリスナ登録
        this.addEventListener("touchstart", function() {
            if (this.lock) return;

            this.push = true;
            if (this._toggleON) {
                this.button.x += this.downX*0.5;
                this.button.y += this.downY*0.5;
            } else {
                this.button.x += this.downX*1.5;
                this.button.y += this.downY*1.5;
            }

            var e = tm.event.Event("push");
            this.dispatchEvent(e);
        });
        this.addEventListener("touchmove", function(e) {
            if (this.lock) return;

            var pt = e.pointing;
            if (this.isHitPoint(pt.x, pt.y)) {
                if (!this.push) {
                    this.push = true;
                    if (this._toggleON) {
                        this.button.x += this.downX*0.5;
                        this.button.y += this.downY*0.5;
                    } else {
                        this.button.x += this.downX*1.5;
                        this.button.y += this.downY*1.5;
                    }
                }
            } else {
                if (this.push) {
                    this.push = false;
                    if (this._toggleON) {
                        this.button.x -= this.downX*0.5;
                        this.button.y -= this.downY*0.5;
                    } else {
                        this.button.x -= this.downX*1.5;
                        this.button.y -= this.downY*1.5;
                    }
                }
            }
        });
        this.addEventListener("touchend", function(e) {
            if (this.lock) return;

            var pt = e.pointing;
            if (this.isHitPoint(pt.x, pt.y)) {
                this.push = false;
                this._toggleON = !this._toggleON;
                if (this._toggleON) {
                    this.text = this.onText;
                    this.button.x -= this.downX*0.5;
                    this.button.y -= this.downY*0.5;
                } else {
                    this.text = this.offText;
                    this.button.x -= this.downX*1.5;
                    this.button.y -= this.downY*1.5;
                }
                this.label.text = this.text;
                var e = tm.event.Event("pushed");
                this.dispatchEvent(e);
            }
        });
    },

    setup: function(style) {
        style = style || {};
        style.$safe(this.DEFAULT_STYLE)

        //登録済みの場合破棄する
        if (this.shadow) {
            this.shadow.remove();
            this.label.remove();
            this.button.remove();
        }

        var width = this.width, height = this.height;

        //ボタン影
        var shadowStyle = {
            fillStyle: style.shadowColor,
            strokeStyle: style.shadowColor,
            lineWidth: style.lineWidth
        };
        this.shadow = tm.display.RectangleShape(width, height, shadowStyle)
            .addChildTo(this)
            .setPosition(this.downX, this.downY);
        this.shadow.blendMode = "source-over";

        //ボタン本体
        var buttonStyle = {
            fillStyle: style.buttonColor,
            strokeStyle: style.lineColor,
            lineWidth: style.lineWidth
        };
        this.button = tm.display.RectangleShape(width, height, buttonStyle)
            .addChildTo(this);

        //ボタンラベル
        this.labelParam.fontFamily = style.fontFamily;
        this.label = tm.display.OutlineLabel(this.text, style.fontSize)
            .addChildTo(this.button)
            .setParam(this.labelParam);
    },
    setLock: function(b) {
        this.lock = b;
        return this;
    },
});

shotgun.ToggleButton.prototype.accessor("toggleON", {
    "set": function(b) {
        this._toggleON = b;

        if (this._toggleON) {
            this.button.x = this.downX;
            this.button.y = this.downY;
            this.text = this.onText;
        } else {
            this.button.x = 0;
            this.button.y = 0;
            this.text = this.offText;
        }
        this.label.text = this.text;
    },

    "get": function() {
        return this._toggleON;
    },
});

tm.define("shotgun.SlideButton", {
    superClass: tm.display.CanvasElement,

    //描画スタイル設定
    DEFAULT_STYLE: {
        width: 160,
        height: 80,

        buttonWitdh: 80,
        buttonHeight: 80,

        //ボタン色
        buttonColor: 'rgba(255, 255, 255, 1.0)',
        buttonLine:  'rgba(200, 200, 200, 1.0)',
        lineWidth: 2,

        //ベース(on/off)色
        onColor: 'rgba(0, 255, 0, 1.0)',
        offColor: 'rgba(200, 200, 200, 1.0)',
    },

    style: null,

    _slideON: false,

    init: function(style) {
        this.superInit();

        this.style = style || {};
        this.style.$safe(this.DEFAULT_STYLE)

        this.width = style.width || 160;
        this.height = style.height || 80;

        this.text = this.offText;

        //セットアップ
        this.setup();

        //判定処理設定
        this.interactive = true;
        this.boundingType = "rect";
//        this.checkHierarchy = true;

        //イベントリスナ登録
        this.addEventListener("touchstart", function() {
            if (this._slideON) {
            } else {
            }
            var e = tm.event.Event("slide");
            this.dispatchEvent(e);
        });
    },

    setup: function() {
        //登録済みの場合破棄する
        if (this.shadow) {
            this.shadow.remove();
            this.label.remove();
            this.button.remove();
        }

        var style = this.style;
        var width = this.width, height = this.height;
        var buttonWidth = this.button, heightButton = this.heightButton;

        //ボタンベース
        var baseStyle = {fillStyle: style.offColor, strokeStyle: style.offColor, lineWidth:  style.lineWidth};
        this.button = tm.display.RectangleShape(width, height, buttonStyle)
            .addChildTo(this);

        //ボタン本体
        var buttonStyle = {fillStyle: style.buttonColor, strokeStyle: style.lineColor, lineWidth:  style.lineWidth};
        this.button = tm.display.RectangleShape(buttonWidth, buttonHeight, buttonStyle)
            .addChildTo(this);
    },
});

shotgun.SlideButton.prototype.accessor("slideON", {
    "set": function(b) {
        this._slideON = b;

        if (this._slideON) {
        } else {
        }
    },

    "get": function() {
        return this._slideON;
    },
});
<|endoftext|>


<commit_before>/**
 * Parse a whitespace separated list of floats, up to maxCount
 * The parser content is hold in a function
 */
function ParserContent (options) {
	/**
	 * options.maxCount
	 */
	var maxCount = options.maxCount
	var stack = []

	function save (data) {
		if (stack.push(data) >= maxCount) {
			self.emit_data(stack)
			stack = []
		}
	}

	atok
		// Parse a float, emit its value as a [data] event and continue with the rules
		.continue(0)
			.float(save)
		// Skip whitespaces and go back to the beginning when matched
		.continue( -atok.float_length )
			.whitespace()
		.continue()
}

// Build the float list parser
var Parser = require('..').createParser(ParserContent)
var p = new Parser({ maxCount: process.argv[2] || 5 })

p.on('debug', console.log)
p.atok.debug(true)
// p.on('data', console.log)
p.on('error', console.error)

console.log( p.atok.rules.length )
// The list should only parse maxCount items
p.end('1.1')
// p.write('1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 9.9 10.10 11.11 ')
<commit_msg>Fixed the float_list example<commit_after>/**
 * Parse a whitespace separated list of floats, up to maxCount
 * The parser content is hold in a function
 * NB. the parser function loses its context when used by createParser()
 */
function ParserContent (options) {
	/**
	 * options.maxCount
	 */
	var maxCount = options.maxCount
	var stack = []

	function save (data) {
		if (stack.push(data) >= maxCount) {
			self.emit_data(stack)
			stack = []
		}
	}

	function end () {
		self.emit_data(stack)
		stack = null
	}

	atok
		// Parse a float, emit its value as a [data] event and continue with the rules
		.float(save)
		// Skip whitespaces and go back to the beginning when matched
		// .continue(-1)
			.whitespace()

		// Emit the remaining data
		.on('end', end)
}

// Build the float list parser
var Parser = require('..').createParser(ParserContent)
var p = new Parser({ maxCount: process.argv[2] || 5 })

p.on('debug', console.log)
p.on('data', console.log)
p.on('error', console.error)
// p.debug(true)

// The list should only parse maxCount items
p.end('1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 9.9 10.10 11.11')
<|endoftext|>


<commit_before>/*
Copyright 2016 The Eyra Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

File author/s:
    Matthias Petursson <oldschool01123@gmail.com>
*/

(function () {
// service to handle recording, basically a wrapper around recorderjs

'use strict';

angular.module('daApp')
  .factory('recordingService', recordingService);

recordingService.$inject = ['$http', 'logger', 'utilityService'];

function recordingService($http, logger, utilityService) {
  var recHandler = {};
  var util = utilityService;

  recHandler.createWavFromBlob = createWavFromBlob; // exported for android audio recorder
  recHandler.getAudioContext = getAudioContext;
  recHandler.getStreamSource = getStreamSource;
  recHandler.init = init;
  recHandler.record = record;
  recHandler.setupCallbacks = setupCallbacks;
  recHandler.stop = stop;

  // local variable definitions for service
  var invalidTitle = util.getConstant('invalidTitle');

  // for some reason, putting this in an array, makes angular update this correctly
  recHandler.currentRecording = [{  "blob":new Blob(),
                                    "url":'',
                                    "title":invalidTitle}];

  var audio_context;
  var input;
  var recorder;

  return recHandler;

  //////////

  function init(initCompleteCallback) {
    recHandler.initCompleteCallback = initCompleteCallback;

    // kick it off
    try {
      // webkit shim
      window.AudioContext = window.AudioContext || window.webkitAudioContext;
      navigator.getUserMedia =  navigator.getUserMedia || navigator.webkitGetUserMedia ||
                                navigator.mozGetUserMedia || navigator.msGetUserMedia;
      window.URL = window.URL || window.webkitURL;

      audio_context = new AudioContext();
      logger.log('Audio context set up.');
      logger.log('navigator.getUserMedia ' + (navigator.getUserMedia ? 'available.' : 'not present!'));
    } catch (e) {
      alert('No web audio support in this browser!');
      logger.error(e);
    }

    navigator.getUserMedia({audio: true}, startUserMedia, function(e) {
      logger.error('No live audio input: ' + e);

      recHandler.initCompleteCallback(false);
    });
  }

  function getAudioContext() {
    return audio_context;
  }

  function getStreamSource() {
    return input;
  }

  function record() {
    logger.log('Recording...');
    recorder && recorder.record();
  }

  // setup callbacks for any controller which needs to use this service
  function setupCallbacks(recordingCompleteCallback) {
    recHandler.recordingCompleteCallback = recordingCompleteCallback;
  }

  function stop(valid) {
    recorder && recorder.stop();
    logger.log('Stopped recording.');

    if (valid) {
      // create WAV download link using audio data blob and display on website
      createWav();
    } else {
      logger.log('Token skipped, no recording made.');
    }

    recorder.clear();
  }

  //////////

  function createWav() {
    recorder && recorder.exportWAV(function(blob) {
      createWavFromBlob(recHandler, blob); // calls the recording complete callback
    });
  }

  function createWavFromBlob(handler, blob) {
    var url = (window.URL || window.webkitURL).createObjectURL(blob);
    // workaround for mobile playback, where it didn't work on chrome/android.
    // fetch blob at url using xhr, and use url generated from that blob.
    // see issue: https://code.google.com/p/chromium/issues/detail?id=227476
    // thanks, gbrlg
    $http.get(url, {'responseType':'blob'}).then(
      function success(response) {
        var reBlob = response.data;
        if (reBlob) {
          url = (window.URL || window.webkitURL).createObjectURL(reBlob);
        }
        finishCreateWav();
      },
      function error(response) {
        logger.error(response);
        finishCreateWav();
      }
    );

    // just added because of the async nature of $http
    function finishCreateWav() {
      handler.prevRecTitle = handler.currentRecording[0].title;
      // display recording on website
      handler.currentRecording[0] = { "blob":blob,
                                      "url":url,
                                      "title":(new Date().toISOString() + '.wav')};

      // notify main controller of completed recording
      handler.recordingCompleteCallback();
    }
  }

  function startUserMedia(stream) {
    input = audio_context.createMediaStreamSource(stream);
    // Fix for a firefox bug.
    // save a reference to the media stream source.
    // thanks, csch, http://stackoverflow.com/a/23486702/5272567
    window.source = input;
    logger.log('Media stream created.');
    // Uncomment if you want the audio to feedback directly
    //input.connect(audio_context.destination);
    //logger.log('Input connected to audio context destination.');

    recorder = new Recorder(input, { 'numChannels':1 });
    logger.log('Recorder initialised.');

    recHandler.initCompleteCallback(true);
  }
}
}());
<commit_msg>Make code robust to undefined recorder in style with rest of the file.<commit_after>/*
Copyright 2016 The Eyra Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

File author/s:
    Matthias Petursson <oldschool01123@gmail.com>
*/

(function () {
// service to handle recording, basically a wrapper around recorderjs

'use strict';

angular.module('daApp')
  .factory('recordingService', recordingService);

recordingService.$inject = ['$http', 'logger', 'utilityService'];

function recordingService($http, logger, utilityService) {
  var recHandler = {};
  var util = utilityService;

  recHandler.createWavFromBlob = createWavFromBlob; // exported for android audio recorder
  recHandler.getAudioContext = getAudioContext;
  recHandler.getStreamSource = getStreamSource;
  recHandler.init = init;
  recHandler.record = record;
  recHandler.setupCallbacks = setupCallbacks;
  recHandler.stop = stop;

  // local variable definitions for service
  var invalidTitle = util.getConstant('invalidTitle');

  // for some reason, putting this in an array, makes angular update this correctly
  recHandler.currentRecording = [{  "blob":new Blob(),
                                    "url":'',
                                    "title":invalidTitle}];

  var audio_context;
  var input;
  var recorder;

  return recHandler;

  //////////

  function init(initCompleteCallback) {
    recHandler.initCompleteCallback = initCompleteCallback;

    // kick it off
    try {
      // webkit shim
      window.AudioContext = window.AudioContext || window.webkitAudioContext;
      navigator.getUserMedia =  navigator.getUserMedia || navigator.webkitGetUserMedia ||
                                navigator.mozGetUserMedia || navigator.msGetUserMedia;
      window.URL = window.URL || window.webkitURL;

      audio_context = new AudioContext();
      logger.log('Audio context set up.');
      logger.log('navigator.getUserMedia ' + (navigator.getUserMedia ? 'available.' : 'not present!'));
    } catch (e) {
      alert('No web audio support in this browser!');
      logger.error(e);
    }

    navigator.getUserMedia({audio: true}, startUserMedia, function(e) {
      logger.error('No live audio input: ' + e);

      recHandler.initCompleteCallback(false);
    });
  }

  function getAudioContext() {
    return audio_context;
  }

  function getStreamSource() {
    return input;
  }

  function record() {
    logger.log('Recording...');
    recorder && recorder.record();
  }

  // setup callbacks for any controller which needs to use this service
  function setupCallbacks(recordingCompleteCallback) {
    recHandler.recordingCompleteCallback = recordingCompleteCallback;
  }

  function stop(valid) {
    recorder && recorder.stop();
    logger.log('Stopped recording.');

    if (valid) {
      // create WAV download link using audio data blob and display on website
      createWav();
    } else {
      logger.log('Token skipped, no recording made.');
    }

    recorder && recorder.clear();
  }

  //////////

  function createWav() {
    recorder && recorder.exportWAV(function(blob) {
      createWavFromBlob(recHandler, blob); // calls the recording complete callback
    });
  }

  function createWavFromBlob(handler, blob) {
    var url = (window.URL || window.webkitURL).createObjectURL(blob);
    // workaround for mobile playback, where it didn't work on chrome/android.
    // fetch blob at url using xhr, and use url generated from that blob.
    // see issue: https://code.google.com/p/chromium/issues/detail?id=227476
    // thanks, gbrlg
    $http.get(url, {'responseType':'blob'}).then(
      function success(response) {
        var reBlob = response.data;
        if (reBlob) {
          url = (window.URL || window.webkitURL).createObjectURL(reBlob);
        }
        finishCreateWav();
      },
      function error(response) {
        logger.error(response);
        finishCreateWav();
      }
    );

    // just added because of the async nature of $http
    function finishCreateWav() {
      handler.prevRecTitle = handler.currentRecording[0].title;
      // display recording on website
      handler.currentRecording[0] = { "blob":blob,
                                      "url":url,
                                      "title":(new Date().toISOString() + '.wav')};

      // notify main controller of completed recording
      handler.recordingCompleteCallback();
    }
  }

  function startUserMedia(stream) {
    input = audio_context.createMediaStreamSource(stream);
    // Fix for a firefox bug.
    // save a reference to the media stream source.
    // thanks, csch, http://stackoverflow.com/a/23486702/5272567
    window.source = input;
    logger.log('Media stream created.');
    // Uncomment if you want the audio to feedback directly
    //input.connect(audio_context.destination);
    //logger.log('Input connected to audio context destination.');

    recorder = new Recorder(input, { 'numChannels':1 });
    logger.log('Recorder initialised.');

    recHandler.initCompleteCallback(true);
  }
}
}());
<|endoftext|>


<commit_before>svgEditor.readLang({
	lang: "fr",
	dir : "ltr",
	common: {
		"ok": "OK",
		"cancel": "Annuler",
		"key_backspace": "Suppr.",
		"key_del": "Retour Arr.",
		"key_down": "Bas",
		"key_up": "Haut",
		"more_opts": "More Options",
		"url": "URL",
		"width": "Width",
		"height": "Height"
	},
	misc: {
		"powered_by": "Powered by"
	},
	ui: {
		"toggle_stroke_tools": "Montrer/Cacher plus d'outils de Contour",
		"palette_info": "Cliquer pour changer la couleur de remplissage, Shift-Clic pour changer la couleur de contour",
		"zoom_level": "Changer le niveau de zoom",
		"panel_drag": "Drag left/right to resize side panel"
	},
	properties: {
		"id": "Identifier l'élément",
		"fill_color": "Changer la couleur de remplissage",
		"stroke_color": "Changer la couleur du contour",
		"stroke_style": "Changer le style du contour",
		"stroke_width": "Changer la largeur du contour de 1, Shift-Click pour changer la largeur de 0.1",
		"pos_x": "Changer la position horizontale X",
		"pos_y": "Changer la position verticale Y",
		"linecap_butt": "Terminaison : Sur le nœud",
		"linecap_round": "Terminaison : Arrondie",
		"linecap_square": "Terminaison : Carrée",
		"linejoin_bevel": "Raccord : Biseauté",
		"linejoin_miter": "Raccord : Droit",
		"linejoin_round": "Raccord : Arrondi",
		"angle": "Changer l'angle de rotation",
		"blur": "Changer la valeur du flou gaussien",
		"opacity": "Changer l'opacité de l'élément sélectionné",
		"circle_cx": "Changer la position horizontale cx du cercle",
		"circle_cy": "Changer la position verticale cy du cercle",
		"circle_r": "Changer le rayon du cercle",
		"ellipse_cx": "Changer la position horizontale cx de l'ellipse",
		"ellipse_cy": "Changer la position verticale cy de l'ellipse",
		"ellipse_rx": "Changer le rayon horizontal x de l'ellipse",
		"ellipse_ry": "Changer le rayon vertical y de l'ellipse",
		"line_x1": "Changer la position horizontale x de début de la ligne",
		"line_x2": "Changer la position horizontale x de fin de la ligne",
		"line_y1": "Changer la position verticale y de début de la ligne",
		"line_y2": "Changer la position verticale y de fin de la ligne",
		"rect_height": "Changer la hauteur du rectangle",
		"rect_width": "Changer la largeur du rectangle",
		"corner_radius": "Changer le rayon des coins du rectangle",
		"image_width": "Changer la largeur de l'image",
		"image_height": "Changer la hauteur de l'image",
		"image_url": "Modifier l'URL",
		"node_x": "Changer la positon horizontale x du nœud",
		"node_y": "Changer la position verticale y du nœud",
		"seg_type": "Changer le type du Segment",
		"straight_segments": "Droit",
		"curve_segments": "Courbe",
		"text_contents": "Changer le contenu du texte",
		"font_family": "Changer la famille de police",
		"font_size": "Changer la taille de la police",
		"bold": "Texte en gras",
		"italic": "Texte en italique"
	},
	tools: {
		"main_menu": "Menu principal",
		"bkgnd_color_opac": "Changer la couleur d'arrière-plan / l'opacité",
		"connector_no_arrow": "Sans flèches",
		"fitToContent": "Ajuster au contenu",
		"fit_to_all": "Ajuster au contenu de tous les calques",
		"fit_to_canvas": "Ajuster au canevas",
		"fit_to_layer_content": "Ajuster au contenu du calque",
		"fit_to_sel": "Ajuster à la sélection",
		"align_relative_to": "Aligner par rapport à ...",
		"relativeTo": "Relativement à:",
		"Page": "Page",
		"largest_object": "Plus gros objet",
		"selected_objects": "Objets sélectionnés",
		"smallest_object": "Plus petit objet",
		"new_doc": "Nouvelle image",
		"open_doc": "Ouvrir une image",
		"export_png": "Exporter au format PNG",
		"save_doc": "Enregistrer l'image",
		"import_doc": "Importer un objet SVG",
		"align_to_page": "Aligner l'élément relativement à la Page",
		"align_bottom": "Aligner le bas des objets",
		"align_center": "Centrer verticalement",
		"align_left": "Aligner les côtés gauches",
		"align_middle": "Centrer horizontalement",
		"align_right": "Aligner les côtés droits",
		"align_top": "Aligner le haut des objets",
		"mode_select": "Outil de sélection",
		"mode_fhpath": "Crayon à main levée",
		"mode_line": "Tracer des lignes",
		"mode_connect": "Connecter deux objets",
		"mode_rect": "Rectangle Tool",
		"mode_square": "Square Tool",
		"mode_fhrect": "Rectangle main levée",
		"mode_ellipse": "Ellipse",
		"mode_circle": "Cercle",
		"mode_fhellipse": "Ellipse main levée",
		"mode_path": "Outil Chemin",
		"mode_shapelib": "Shape library",
		"mode_text": "Outil Texte",
		"mode_image": "Outil Image",
		"mode_zoom": "Zoom",
		"mode_eyedropper": "Outil Pipette",
		"no_embed": "NOTE: Cette image ne peut être incorporée en tant que données. Le contenu affiché sera celui de l'image située à cette adresse",
		"undo": "Annuler l'action",
		"redo": "Refaire l'action",
		"tool_source": "Modifier la source",
		"wireframe_mode": "Mode Fil de Fer",
		"toggle_grid": "Show/Hide Grid",
		"clone": "Clone Element(s)",
		"del": "Delete Element(s)",
		"group": "Grouper les éléments",
		"make_link": "Make (hyper)link",
		"set_link_url": "Set link URL (leave empty to remove)",
		"to_path": "Convertir en chemin",
		"reorient_path": "Réorienter le chemin",
		"ungroup": "Dégrouper les éléments",
		"docprops": "Propriétés du document",
		"imagelib": "Image Library",
		"move_bottom": "Déplacer vers le bas",
		"move_top": "Déplacer vers le haut",
		"node_clone": "Cloner le nœud",
		"node_delete": "Supprimer le nœud",
		"node_link": "Rendre les points de contrôle solidaires",
		"add_subpath": "Ajouter un sous-chemin",
		"openclose_path": "Ouvrir/Fermer sous-chemin",
		"source_save": "Appliquer Modifications",
		"cut": "Cut",
		"copy": "Copy",
		"paste": "Paste",
		"paste_in_place": "Paste in Place",
		"Retour Arr.": "Delete",
		"group": "Group",
		"move_front": "Bring to Front",
		"move_up": "Bring Forward",
		"move_down": "Send Backward",
		"move_back": "Send to Back"
	},
	layers: {
		"layer":"Calque",
		"layers": "Layers",
		"del": "Supprimer le calque",
		"move_down": "Descendre le calque",
		"new": "Nouveau calque",
		"rename": "Renommer le calque",
		"move_up": "Monter le calque",
		"dupe": "Duplicate Layer",
		"merge_down": "Merge Down",
		"merge_all": "Merge All",
		"move_elems_to": "Déplacer éléments vers:",
		"move_selected": "Déplacer les éléments sélectionnés vers un autre calque"
	},
	config: {
		"image_props": "Propriétés de l'Image",
		"doc_title": "Titre",
		"doc_dims": "Dimensions du canevas",
		"included_images": "Images incorporées",
		"image_opt_embed": "Incorporer les images en tant que données (fichiers locaux)",
		"image_opt_ref": "Utiliser la référence des images ",
		"editor_prefs": "Préférences de l'Éditeur",
		"icon_size": "Taille des icônes",
		"language": "Langue",
		"background": "Toile de fond de l'Éditeur",
		"editor_img_url": "Image URL",
		"editor_bg_note": "Note: La toile de fond n'est pas sauvegardée avec l'image.",
		"icon_large": "Grande",
		"icon_medium": "Moyenne",
		"icon_small": "Petite",
		"icon_xlarge": "Super-Grande",
		"select_predefined": "Sélectionner prédéfinis:",
		"units_and_rulers": "Units & Rulers",
		"show_rulers": "Show rulers",
		"base_unit": "Base Unit:",
		"grid": "Grid",
		"snapping_onoff": "Snapping on/off",
		"snapping_stepsize": "Snapping Step-Size:"
	},
	shape_cats: {
		"basic": "Basic",
		"object": "Objects",
		"symbol": "Symbols",
		"arrow": "Arrows",
		"flowchart": "Flowchart",
		"animal": "Animals",
		"game": "Cards & Chess",
		"dialog_balloon": "Dialog balloons",
		"electronics": "Electronics",
		"math": "Mathematical",
		"music": "Music",
		"misc": "Miscellaneous",
		"raphael_1": "raphaeljs.com set 1",
		"raphael_2": "raphaeljs.com set 2"
	},
	imagelib: {
		"select_lib": "Select an image library",
		"show_list": "Show library list",
		"import_single": "Import single",
		"import_multi": "Import multiple",
		"open": "Open as new document"
	},
	notification: {
		"invalidAttrValGiven":"Valeur fournie invalide",
		"noContentToFitTo":"Il n'y a pas de contenu auquel ajuster",
		"dupeLayerName":"Il existe déjà un calque de ce nom !",
		"enterUniqueLayerName":"Veuillez entrer un nom (unique) pour le calque",
		"enterNewLayerName":"Veuillez entrer le nouveau nom du calque",
		"layerHasThatName":"Le calque porte déjà ce nom",
		"QmoveElemsToLayer":"Déplacer les éléments sélectionnés vers le calque '%s' ?",
		"QwantToClear":"Voulez-vous effacer le dessin ?\nL'historique de vos actions sera également effacé !",
		"QwantToOpen":"Do you want to open a new file?\nThis will also erase your undo history!",
		"QerrorsRevertToSource":"Il y a des erreurs d'analyse syntaxique dans votre code-source SVG.\nRevenir au code-source SVG avant modifications ?",
		"QignoreSourceChanges":"Ignorer les modifications faites à la source SVG ?",
		"featNotSupported":"Fonction non supportée",
		"enterNewImgURL":"Entrer la nouvelle URL de l'image",
		"defsFailOnSave": "NOTE : À cause d'un bug de votre navigateur, cette image peut être affichée de façon incorrecte (dégradés ou éléments manquants). Cependant, une fois enregistrée, elle sera correcte.",
		"loadingImage":"Chargement de l'image, veuillez patienter...",
		"saveFromBrowser": "Selectionner \"Enregistrer sous...\" dans votre navigateur pour sauvegarder l'image en tant que fichier %s.",
		"noteTheseIssues": "Notez également les problèmes suivants : ",
		"unsavedChanges": "Il y a des changements non sauvegardés.",
		"enterNewLinkURL": "Enter the new hyperlink URL",
		"errorLoadingSVG": "Error: Unable to load SVG data",
		"URLloadFail": "Unable to load from URL",
		"retrieving": "Retrieving \"%s\"..."
	}
});<commit_msg>updated french translation. thanks kiruahxh<commit_after>svgEditor.readLang({
	lang: "fr",
	dir : "ltr",
	common: {
		"ok": "OK",
		"cancel": "Annuler",
		"key_backspace": "Suppr.",
		"key_del": "Retour Arr.",
		"key_down": "Bas",
		"key_up": "Haut",
		"more_opts": "Plus d'options",
		"url": "URL",
		"width": "Largeur",
		"height": "Hauteur"
	},
	misc: {
		"powered_by": "Powered by"
	},
	ui: {
		"toggle_stroke_tools": "Montrer/Cacher plus d'outils de Contour",
		"palette_info": "Cliquer pour changer la couleur de remplissage, Shift-Clic pour changer la couleur de contour",
		"zoom_level": "Changer le niveau de zoom",
		"panel_drag": "Tirer vers la gauche/droite pour redimentionner le panneau"
	},
	properties: {
		"id": "Identifier l'élément",
		"fill_color": "Changer la couleur de remplissage",
		"stroke_color": "Changer la couleur du contour",
		"stroke_style": "Changer le style du contour",
		"stroke_width": "Changer la largeur du contour de 1, Shift-Click pour changer la largeur de 0.1",
		"pos_x": "Changer la position horizontale X",
		"pos_y": "Changer la position verticale Y",
		"linecap_butt": "Terminaison : Sur le nœud",
		"linecap_round": "Terminaison : Arrondie",
		"linecap_square": "Terminaison : Carrée",
		"linejoin_bevel": "Raccord : Biseauté",
		"linejoin_miter": "Raccord : Droit",
		"linejoin_round": "Raccord : Arrondi",
		"angle": "Changer l'angle de rotation",
		"blur": "Changer la valeur du flou gaussien",
		"opacity": "Changer l'opacité de l'élément sélectionné",
		"circle_cx": "Changer la position horizontale cx du cercle",
		"circle_cy": "Changer la position verticale cy du cercle",
		"circle_r": "Changer le rayon du cercle",
		"ellipse_cx": "Changer la position horizontale cx de l'ellipse",
		"ellipse_cy": "Changer la position verticale cy de l'ellipse",
		"ellipse_rx": "Changer le rayon horizontal x de l'ellipse",
		"ellipse_ry": "Changer le rayon vertical y de l'ellipse",
		"line_x1": "Changer la position horizontale x de début de la ligne",
		"line_x2": "Changer la position horizontale x de fin de la ligne",
		"line_y1": "Changer la position verticale y de début de la ligne",
		"line_y2": "Changer la position verticale y de fin de la ligne",
		"rect_height": "Changer la hauteur du rectangle",
		"rect_width": "Changer la largeur du rectangle",
		"corner_radius": "Changer le rayon des coins du rectangle",
		"image_width": "Changer la largeur de l'image",
		"image_height": "Changer la hauteur de l'image",
		"image_url": "Modifier l'URL",
		"node_x": "Changer la positon horizontale x du nœud",
		"node_y": "Changer la position verticale y du nœud",
		"seg_type": "Changer le type du Segment",
		"straight_segments": "Droit",
		"curve_segments": "Courbe",
		"text_contents": "Changer le contenu du texte",
		"font_family": "Changer la famille de police",
		"font_size": "Changer la taille de la police",
		"bold": "Texte en gras",
		"italic": "Texte en italique"
	},
	tools: {
		"main_menu": "Menu principal",
		"bkgnd_color_opac": "Changer la couleur d'arrière-plan / l'opacité",
		"connector_no_arrow": "Sans flèches",
		"fitToContent": "Ajuster au contenu",
		"fit_to_all": "Ajuster au contenu de tous les calques",
		"fit_to_canvas": "Ajuster au canevas",
		"fit_to_layer_content": "Ajuster au contenu du calque",
		"fit_to_sel": "Ajuster à la sélection",
		"align_relative_to": "Aligner par rapport à ...",
		"relativeTo": "Relativement à:",
		"Page": "Page",
		"largest_object": "Plus gros objet",
		"selected_objects": "Objets sélectionnés",
		"smallest_object": "Plus petit objet",
		"new_doc": "Nouvelle image",
		"open_doc": "Ouvrir une image",
		"export_png": "Exporter au format PNG",
		"save_doc": "Enregistrer l'image",
		"import_doc": "Importer un objet SVG",
		"align_to_page": "Aligner l'élément relativement à la Page",
		"align_bottom": "Aligner le bas des objets",
		"align_center": "Centrer verticalement",
		"align_left": "Aligner les côtés gauches",
		"align_middle": "Centrer horizontalement",
		"align_right": "Aligner les côtés droits",
		"align_top": "Aligner le haut des objets",
		"mode_select": "Outil de sélection",
		"mode_fhpath": "Crayon à main levée",
		"mode_line": "Tracer des lignes",
		"mode_connect": "Connecter deux objets",
		"mode_rect": "Outil rectangle",
		"mode_square": "Outils carré",
		"mode_fhrect": "Rectangle main levée",
		"mode_ellipse": "Ellipse",
		"mode_circle": "Cercle",
		"mode_fhellipse": "Ellipse main levée",
		"mode_path": "Outil Chemin",
		"mode_shapelib": "Bibliothèque d'images",
		"mode_text": "Outil Texte",
		"mode_image": "Outil Image",
		"mode_zoom": "Zoom",
		"mode_eyedropper": "Outil Pipette",
		"no_embed": "NOTE: Cette image ne peut être incorporée en tant que données. Le contenu affiché sera celui de l'image située à cette adresse",
		"undo": "Annuler l'action",
		"redo": "Refaire l'action",
		"tool_source": "Modifier la source",
		"wireframe_mode": "Mode Fil de Fer",
		"toggle_grid": "Montrer/cacher la grille",
		"clone": "Cloner élement(s)",
		"del": "Supprimer élement(s)",
		"group": "Grouper les éléments",
		"make_link": "Créer (hyper)lien",
		"set_link_url": "Set link URL (leave empty to remove)",
		"to_path": "Convertir en chemin",
		"reorient_path": "Réorienter le chemin",
		"ungroup": "Dégrouper les éléments",
		"docprops": "Propriétés du document",
		"imagelib": "Bibliothèque d'images",
		"move_bottom": "Déplacer vers le bas",
		"move_top": "Déplacer vers le haut",
		"node_clone": "Cloner le nœud",
		"node_delete": "Supprimer le nœud",
		"node_link": "Rendre les points de contrôle solidaires",
		"add_subpath": "Ajouter un sous-chemin",
		"openclose_path": "Ouvrir/Fermer sous-chemin",
		"source_save": "Appliquer Modifications",
		"cut": "Couper",
		"copy": "Copier",
		"paste": "Coller",
		"paste_in_place": "Coller sur place",
		"Retour Arr.": "Supprimer",
		"move_front": "Placer au premier plan",
		"move_up": "Placer plus près",
		"move_down": "Placer au dernier plan",
		"move_back": "Placer plus au fond"
	},
	layers: {
		"layer":"Calque",
		"layers": "Calques",
		"del": "Supprimer le calque",
		"move_down": "Descendre le calque",
		"new": "Nouveau calque",
		"rename": "Renommer le calque",
		"move_up": "Monter le calque",
		"dupe": "Dupliquer calque",
		"merge_down": "Fusionner vers le bas",
		"merge_all": "Tout fusionner",
		"move_elems_to": "Déplacer éléments vers:",
		"move_selected": "Déplacer les éléments sélectionnés vers un autre calque"
	},
	config: {
		"image_props": "Propriétés de l'Image",
		"doc_title": "Titre",
		"doc_dims": "Dimensions du canevas",
		"included_images": "Images incorporées",
		"image_opt_embed": "Incorporer les images en tant que données (fichiers locaux)",
		"image_opt_ref": "Utiliser la référence des images ",
		"editor_prefs": "Préférences de l'Éditeur",
		"icon_size": "Taille des icônes",
		"language": "Langue",
		"background": "Toile de fond de l'Éditeur",
		"editor_img_url": "Image URL",
		"editor_bg_note": "Note: La toile de fond n'est pas sauvegardée avec l'image.",
		"icon_large": "Grande",
		"icon_medium": "Moyenne",
		"icon_small": "Petite",
		"icon_xlarge": "Super-Grande",
		"select_predefined": "Sélectionner prédéfinis:",
		"units_and_rulers": "Unités & Règles",
		"show_rulers": "Afficher les règles",
		"base_unit": "Unité de mesure:",
		"grid": "Grille",
		"snapping_onoff": "Snapping on/off",
		"snapping_stepsize": "Snapping Step-Size:"
	},
	shape_cats: {
		"basic": "Basique",
		"object": "Objets",
		"symbol": "Symboles",
		"arrow": "Flêches",
		"flowchart": "Diagramme de flux",
		"animal": "Animaux",
		"game": "Cartes & Echecs",
		"dialog_balloon": "Bulles de dialogue",
		"electronics": "Electronique",
		"math": "Mathématiques",
		"music": "Musique",
		"misc": "Divers",
		"raphael_1": "raphaeljs.com ensemble 1",
		"raphael_2": "raphaeljs.com ensemble 2"
	},
	imagelib: {
		"select_lib": "Select an image library",
		"show_list": "Show library list",
		"import_single": "Import single",
		"import_multi": "Import multiple",
		"open": "Open as new document"
	},
	notification: {
		"invalidAttrValGiven":"Valeur fournie invalide",
		"noContentToFitTo":"Il n'y a pas de contenu auquel ajuster",
		"dupeLayerName":"Il existe déjà un calque de ce nom !",
		"enterUniqueLayerName":"Veuillez entrer un nom (unique) pour le calque",
		"enterNewLayerName":"Veuillez entrer le nouveau nom du calque",
		"layerHasThatName":"Le calque porte déjà ce nom",
		"QmoveElemsToLayer":"Déplacer les éléments sélectionnés vers le calque '%s' ?",
		"QwantToClear":"Voulez-vous effacer le dessin ?\nL'historique de vos actions sera également effacé !",
		"QwantToOpen":"Do you want to open a new file?\nThis will also erase your undo history!",
		"QerrorsRevertToSource":"Il y a des erreurs d'analyse syntaxique dans votre code-source SVG.\nRevenir au code-source SVG avant modifications ?",
		"QignoreSourceChanges":"Ignorer les modifications faites à la source SVG ?",
		"featNotSupported":"Fonction non supportée",
		"enterNewImgURL":"Entrer la nouvelle URL de l'image",
		"defsFailOnSave": "NOTE : À cause d'un bug de votre navigateur, cette image peut être affichée de façon incorrecte (dégradés ou éléments manquants). Cependant, une fois enregistrée, elle sera correcte.",
		"loadingImage":"Chargement de l'image, veuillez patienter...",
		"saveFromBrowser": "Selectionner \"Enregistrer sous...\" dans votre navigateur pour sauvegarder l'image en tant que fichier %s.",
		"noteTheseIssues": "Notez également les problèmes suivants : ",
		"unsavedChanges": "Il y a des changements non sauvegardés.",
		"enterNewLinkURL": "Entrez la nouvel hyperlien URL",
		"errorLoadingSVG": "Erreur: Impossible de charger le document SVG",
		"URLloadFail": "Impossible de charger l'URL",
		"retrieving": "Récupère \"%s\"..."
	}
});
<|endoftext|>


<commit_before>import Sprite from './Sprite';
import direction from './../values/direction';
import Weapon from './../values/Weapon';
import config from '../../setup/config';
import Splatter from './Splatter';
import Flag from './Flag';

export default class Player extends Sprite {

    boot() {
        this.speed = 400;
        this.enableArcadePhysics();
        this.body.collideWorldBounds = true;
        this.direction = direction.RIGHT;
        this.weapon = new Weapon(this, this.game);
        this.number = 1;
        this.networkId = null;
        this.carryingFlag = false;
        this.flag = null;
        this.exp = 0;
        this.killStreak = 0;
    }

    isAlive() {
        return this.health > 0;
    }

    isDead() {
        return this.health === 0;
    }

    isVisible() {
        return this.visible && this.alpha === 1;
    }

    canShoot() {
        return this.isAlive() && this.isVisible();
    }

    collect(item) {
        item.kill();
    }

    shoot(overwriteDirection) {
        if (!this.canShoot()) {
            return;
        }

        this.weapon.shoot(overwriteDirection);
    }

    walkAnimation() {
        this.animations.play('walk');
    }

    stopShooting() {
        this.changeSpriteToNormal();

        if (this.isMoving()) {
            this.walkAnimation();
        }
    }

    changeSpriteToNormal() {
        this.loadTexture('player_'+this.team.name+'_'+this.playerSprite, 0, true);
    }

    updateName() {
        this.name.x = this.x;
        this.name.y = this.y - this.height * 1.2;
    }

    updateHealthbar() {
        this.healthbar.x = this.x - this.width / 2;
        this.healthbar.y = this.y - this.height * 1.5;
    }

    updateRank() {
        this.rankSprite.x = this.healthbar.x - this.rankSprite.width - 5;
        this.rankSprite.y = this.healthbar.y - (this.rankSprite.height / 3);
    }

    createRankSprite() {
        if(this.rankSprite) {
            this.rankSprite.kill();

            this.rankSprite = null;
        }

        const rank = this.rank();
        const rankSpriteKey = 'rank' + rank;
        this.rankSprite = this.game.add.sprite(0, 0, rankSpriteKey);
        this.rankSprite.scale.x = 0.1;
        this.rankSprite.scale.y = 0.1;

        this.updateRank();
    }

    checkNewPlayerSprite() {
      const rank = this.rank();
      if(rank >= 0 && rank < 7){
        this.playerSprite = "pistol";
      }else if(rank >= 7 && rank < 14){
        this.playerSprite = "flamer";
      }else if(rank >= 14 && rank < 21){
        this.playerSprite = "rifle";
      }else if(rank >= 21 && rank < 28){
        this.playerSprite = "laser";
      }else if(rank >= 28 && rank < 35){
        this.playerSprite = "plasma";
      }else if(rank >= 35 && rank < 42){
        this.playerSprite = "pistol2";
      }else if(rank >= 42 && rank < 49){
        this.playerSprite = "flamer2";
      }else if(rank >= 49 && rank < 56){
        this.playerSprite = "rifle2";
      }else if(rank >= 56 && rank < 63){
        this.playerSprite = "laser2";
      }else if(rank >= 63 && rank < 70){
        this.playerSprite = "plasma2";
      }

      this.loadTexture('player_'+this.team.name+'_'+this.playerSprite, 0, true);
    }

    getFlag(flag) {
        this.carryingFlag = true;
        this.flag = flag;
        this.addExp(4);
    }

    releaseFlag() {
        this.carryingFlag = false;
        this.flag.respawn();
        this.flag = null;
        this.addExp(10);
    }

    setDirection(newDirection) {
        this.direction = newDirection;

        switch (this.direction) {
            case direction.TOP:
                this.angle = -90;
                break;
            case direction.BOTTOM:
                this.angle = 90;
                break;
            case direction.LEFT:
                this.angle = 180;
                break;
            case direction.RIGHT:
                this.angle = 0;
                break;
        }
    }

    moveToDirection(newDirection, source = "user") {
        if (!this.visible) {
            this.body.velocity.y = 0;
            this.body.velocity.x = 0;
            return false;
        }

        this.updateName();
        this.updateHealthbar();
        this.updateRank();

        if (this.isFacingDirection(newDirection, true)) {
            return false;
        }

        eventSystem().emit('player.change_direction:before', {
            player: this,
            source: source
        });

        this.direction = newDirection;
        this.setDirection(newDirection);
        this.resetVelocity();

        switch (this.direction) {
            case direction.TOP:
                this.body.velocity.y -= this.speed;
                break;
            case direction.BOTTOM:
                this.body.velocity.y += this.speed;
                break;
            case direction.LEFT:
                this.body.velocity.x -= this.speed;
                break;
            case direction.RIGHT:
                this.body.velocity.x += this.speed;
                break;
        }

        this.walkAnimation();

        eventSystem().emit('player.change_direction:after', {
            player: this,
            source: source
        });

    }

    isFacingDirection(direction, isMoving) {

        if (direction !== this.direction) {
            return false;
        }

        if (isMoving !== this.isMoving()) {
            return false;
        }

        return true;
    }

    isMoving() {
        return this.body.velocity.x !== 0 || this.body.velocity.y !== 0;
    }

    stopMoving(newDirection = false, source = "user") {
        if(newDirection){
            this.direction = newDirection;
        }

        if (this.isFacingDirection(this.direction, false)) {
            return false;
        }

        eventSystem().emit('player.stop_moving:before', {
            player: this,
            source: source
        });

        this.resetVelocity();
        this.animations.stop();
        this.frame = 0;

        eventSystem().emit('player.stop_moving:after', {
            player: this,
            source: source
        });

        return true;
    }

    resetVelocity() {
        this.body.velocity.x = 0;
        this.body.velocity.y = 0;
    }

    damage(damage) {
        if (this.isDead() || !this.isVisible()) {
            return;
        }

        const newHealth = this.health - damage;

        this.setHealth(newHealth);
    }

    setHealth(health) {
        this.health = health;

        if (this.health > 0) {
            this.healthbar.scale.x = this.health / 100;
        } else {
            this.health = 0;
            this.dead();
        }
    }

    dead() {
        new Splatter(this.game, this.x, this.y, this.team.name + '_dead');
        this.visible = false;
        this.name.visible = false;
        this.healthbar.visible = false;
        this.rankSprite.visible = false;
        this.killStreak = 0;
        this.carryingFlag = false;
        this.flag.respawn();

        this.game.time.events.add(Phaser.Timer.SECOND * config.game.player.waitForRespawn, this.resetPlayer, this);

        eventSystem().emit('player_dead', {
           team: this.team.name
       });
    }

    resetPlayer() {
        this.reset(this.spawnPos.x, this.spawnPos.y);
        this.visible = true;
        this.name.visible = true;
        this.healthbar.visible = true;
        this.rankSprite.visible = true;
        this.health = 100;
        this.healthbar.scale.x = 1;
        this.updateName();
        this.updateHealthbar();
        this.updateRank();
        this.alpha = 0.2;
        this.game.time.events.add(Phaser.Timer.SECOND * config.game.player.invisible, this.endInvisible, this);
    }

    endInvisible() {
        this.alpha = 1;
    }

    setExp(exp) {
        const rankBefore = this.rank();
        this.exp = exp;
        const rankAfter = this.rank();
        const newRanks = rankAfter - rankBefore;

        if(newRanks > 0) {
            this.createRankSprite();
            this.checkNewPlayerSprite();
        }
    }

    addExp(amount) {
        this.setExp(this.exp + amount);

        eventSystem().emit('player.exp', {
            player: this,
            exp: this.exp
        });
    }

    rank() {
        for(let rank = 1; rank <= 75; rank++) {
            const maxExp = this.expFor(rank);

            if(this.exp < maxExp) {
                return rank;
            }
        }
    }

    expFor(rank) {
        return Math.round(10 + rank * rank * Math.log(rank));
    }

    killedPlayer() {
        this.killStreak++;

        const exp = this.expForKillStreak();

        this.addExp(exp);
    }

    expForKillStreak() {
        if(this.killStreak >= 5) {
            return 16;
        }

        switch(this.killStreak) {
            case 1: return 1;
            case 2: return 2;
            case 3: return 4;
            case 4: return 8;
            default: return 1;
        }
    }

}
<commit_msg>Just added todo<commit_after>import Sprite from './Sprite';
import direction from './../values/direction';
import Weapon from './../values/Weapon';
import config from '../../setup/config';
import Splatter from './Splatter';
import Flag from './Flag';

export default class Player extends Sprite {

    boot() {
        this.speed = 400;
        this.enableArcadePhysics();
        this.body.collideWorldBounds = true;
        this.direction = direction.RIGHT;
        this.weapon = new Weapon(this, this.game);
        this.number = 1;
        this.networkId = null;
        this.carryingFlag = false;
        this.flag = null;
        this.exp = 0;
        this.killStreak = 0;
    }

    isAlive() {
        return this.health > 0;
    }

    isDead() {
        return this.health === 0;
    }

    isVisible() {
        return this.visible && this.alpha === 1;
    }

    canShoot() {
        return this.isAlive() && this.isVisible();
    }

    collect(item) {
        item.kill();
    }

    shoot(overwriteDirection) {
        if (!this.canShoot()) {
            return;
        }

        this.weapon.shoot(overwriteDirection);
    }

    walkAnimation() {
        this.animations.play('walk');
    }

    stopShooting() {
        this.changeSpriteToNormal();

        if (this.isMoving()) {
            this.walkAnimation();
        }
    }

    changeSpriteToNormal() {
        this.loadTexture('player_'+this.team.name+'_'+this.playerSprite, 0, true);
    }

    updateName() {
        this.name.x = this.x;
        this.name.y = this.y - this.height * 1.2;
    }

    updateHealthbar() {
        this.healthbar.x = this.x - this.width / 2;
        this.healthbar.y = this.y - this.height * 1.5;
    }

    showCarryingFlag() {
        //TODO: Show Flag sign next to player
    }

    updateRank() {
        this.rankSprite.x = this.healthbar.x - this.rankSprite.width - 5;
        this.rankSprite.y = this.healthbar.y - (this.rankSprite.height / 3);
    }

    createRankSprite() {
        if(this.rankSprite) {
            this.rankSprite.kill();

            this.rankSprite = null;
        }

        const rank = this.rank();
        const rankSpriteKey = 'rank' + rank;
        this.rankSprite = this.game.add.sprite(0, 0, rankSpriteKey);
        this.rankSprite.scale.x = 0.1;
        this.rankSprite.scale.y = 0.1;

        this.updateRank();
    }

    checkNewPlayerSprite() {
      const rank = this.rank();
      if(rank >= 0 && rank < 7){
        this.playerSprite = "pistol";
      }else if(rank >= 7 && rank < 14){
        this.playerSprite = "flamer";
      }else if(rank >= 14 && rank < 21){
        this.playerSprite = "rifle";
      }else if(rank >= 21 && rank < 28){
        this.playerSprite = "laser";
      }else if(rank >= 28 && rank < 35){
        this.playerSprite = "plasma";
      }else if(rank >= 35 && rank < 42){
        this.playerSprite = "pistol2";
      }else if(rank >= 42 && rank < 49){
        this.playerSprite = "flamer2";
      }else if(rank >= 49 && rank < 56){
        this.playerSprite = "rifle2";
      }else if(rank >= 56 && rank < 63){
        this.playerSprite = "laser2";
      }else if(rank >= 63 && rank < 70){
        this.playerSprite = "plasma2";
      }

      this.loadTexture('player_'+this.team.name+'_'+this.playerSprite, 0, true);
    }

    getFlag(flag) {
        this.carryingFlag = true;
        this.flag = flag;
        this.addExp(4);
        this.showCarryingFlag();
    }

    releaseFlag() {
        this.carryingFlag = false;
        this.flag.respawn();
        this.flag = null;
        this.addExp(10);
    }

    setDirection(newDirection) {
        this.direction = newDirection;

        switch (this.direction) {
            case direction.TOP:
                this.angle = -90;
                break;
            case direction.BOTTOM:
                this.angle = 90;
                break;
            case direction.LEFT:
                this.angle = 180;
                break;
            case direction.RIGHT:
                this.angle = 0;
                break;
        }
    }

    moveToDirection(newDirection, source = "user") {
        if (!this.visible) {
            this.body.velocity.y = 0;
            this.body.velocity.x = 0;
            return false;
        }

        this.updateName();
        this.updateHealthbar();
        this.updateRank();

        if (this.isFacingDirection(newDirection, true)) {
            return false;
        }

        eventSystem().emit('player.change_direction:before', {
            player: this,
            source: source
        });

        this.direction = newDirection;
        this.setDirection(newDirection);
        this.resetVelocity();

        switch (this.direction) {
            case direction.TOP:
                this.body.velocity.y -= this.speed;
                break;
            case direction.BOTTOM:
                this.body.velocity.y += this.speed;
                break;
            case direction.LEFT:
                this.body.velocity.x -= this.speed;
                break;
            case direction.RIGHT:
                this.body.velocity.x += this.speed;
                break;
        }

        this.walkAnimation();

        eventSystem().emit('player.change_direction:after', {
            player: this,
            source: source
        });

    }

    isFacingDirection(direction, isMoving) {

        if (direction !== this.direction) {
            return false;
        }

        if (isMoving !== this.isMoving()) {
            return false;
        }

        return true;
    }

    isMoving() {
        return this.body.velocity.x !== 0 || this.body.velocity.y !== 0;
    }

    stopMoving(newDirection = false, source = "user") {
        if(newDirection){
            this.direction = newDirection;
        }

        if (this.isFacingDirection(this.direction, false)) {
            return false;
        }

        eventSystem().emit('player.stop_moving:before', {
            player: this,
            source: source
        });

        this.resetVelocity();
        this.animations.stop();
        this.frame = 0;

        eventSystem().emit('player.stop_moving:after', {
            player: this,
            source: source
        });

        return true;
    }

    resetVelocity() {
        this.body.velocity.x = 0;
        this.body.velocity.y = 0;
    }

    damage(damage) {
        if (this.isDead() || !this.isVisible()) {
            return;
        }

        const newHealth = this.health - damage;

        this.setHealth(newHealth);
    }

    setHealth(health) {
        this.health = health;

        if (this.health > 0) {
            this.healthbar.scale.x = this.health / 100;
        } else {
            this.health = 0;
            this.dead();
        }
    }

    dead() {
        new Splatter(this.game, this.x, this.y, this.team.name + '_dead');
        this.visible = false;
        this.name.visible = false;
        this.healthbar.visible = false;
        this.rankSprite.visible = false;
        this.killStreak = 0;
        this.carryingFlag = false;
        this.flag.respawn();

        this.game.time.events.add(Phaser.Timer.SECOND * config.game.player.waitForRespawn, this.resetPlayer, this);

        eventSystem().emit('player_dead', {
           team: this.team.name
       });
    }

    resetPlayer() {
        this.reset(this.spawnPos.x, this.spawnPos.y);
        this.visible = true;
        this.name.visible = true;
        this.healthbar.visible = true;
        this.rankSprite.visible = true;
        this.health = 100;
        this.healthbar.scale.x = 1;
        this.updateName();
        this.updateHealthbar();
        this.updateRank();
        this.alpha = 0.2;
        this.game.time.events.add(Phaser.Timer.SECOND * config.game.player.invisible, this.endInvisible, this);
    }

    endInvisible() {
        this.alpha = 1;
    }

    setExp(exp) {
        const rankBefore = this.rank();
        this.exp = exp;
        const rankAfter = this.rank();
        const newRanks = rankAfter - rankBefore;

        if(newRanks > 0) {
            this.createRankSprite();
            this.checkNewPlayerSprite();
        }
    }

    addExp(amount) {
        this.setExp(this.exp + amount);

        eventSystem().emit('player.exp', {
            player: this,
            exp: this.exp
        });
    }

    rank() {
        for(let rank = 1; rank <= 75; rank++) {
            const maxExp = this.expFor(rank);

            if(this.exp < maxExp) {
                return rank;
            }
        }
    }

    expFor(rank) {
        return Math.round(10 + rank * rank * Math.log(rank));
    }

    killedPlayer() {
        this.killStreak++;

        const exp = this.expForKillStreak();

        this.addExp(exp);
    }

    expForKillStreak() {
        if(this.killStreak >= 5) {
            return 16;
        }

        switch(this.killStreak) {
            case 1: return 1;
            case 2: return 2;
            case 3: return 4;
            case 4: return 8;
            default: return 1;
        }
    }

}
<|endoftext|>


<commit_before>/* global window document */
import React from 'react';
import Icon from '@economist/component-icon';
import reactCookie from 'react-cookie';
import LinkButton from '@economist/component-link-button';
import BarWrapper from '@economist/component-bar-wrapper';

const betaText = [
  (

      You're viewing a beta release of

        {" The Economist"}

      's new website

  ),
  (

      {' We would like to hear what you think'}

  ),
];

const googleForm = 'https://docs.google.com/forms/d/1ZCdwituoyhHAPKjCKvDvzRp66zwOv23GrCPH4rGINrE/viewform';

export default class BetaBar extends React.Component {
  static propTypes = {
    cookieName: React.PropTypes.string,
    cookieValue: React.PropTypes.string,
    closeCookieName: React.PropTypes.string,
    closeCookieValue: React.PropTypes.string,
    reactCookieInstance: React.PropTypes.shape({
      save: React.PropTypes.func,
    }),
    onFallback: React.PropTypes.func,
  }
  static defaultProps = {
    cookieName: 'ec_blogsab',
    cookieValue: 'b',
    closeCookieName: 'ec_rvmp_beta_close',
    closeCookieValue: 'x',
    reactCookieInstance: reactCookie,
  }
  constructor(...args) {
    super(...args);
    this.handleFallback = this.handleFallback.bind(this);
    this.handleDismiss = this.handleDismiss.bind(this);
    if (!this.state) {
      this.state = {};
    }
  }
  handleFallback(event) {
    if (typeof window === 'undefined' || typeof location === 'undefined') { return; }
    const { cookieName, cookieValue, reactCookieInstance } = this.props;

    if (cookieName && cookieValue && reactCookieInstance) {
      reactCookieInstance.save(cookieName, cookieValue, {
        maxAge: 30 * 24 * 60 * 60,
      });
      if (this.props.onFallback) {
        this.props.onFallback();
      }
    }

    if (event) {
      event.preventDefault();
    }
  }
  handleDismiss(event) {
    const { closeCookieName, closeCookieValue, reactCookieInstance } = this.props;

    if (closeCookieName && closeCookieValue && reactCookieInstance) {
      reactCookieInstance.save(closeCookieName, closeCookieValue)
    }

    this.setState({ wasDismissed: true });

    if (event) {
      event.preventDefault();
    }
  }
  componentWillMount() {
    if (typeof window === 'undefined') { return; }
    const { closeCookieName, closeCookieValue, reactCookieInstance } = this.props;
    if (closeCookieName && closeCookieValue && reactCookieInstance) {
      this.setState({
        wasDismissed: reactCookieInstance.load(this.props.closeCookieName) === this.props.closeCookieValue,
      });
    }
  }
  render() {
    if (this.state && this.state.wasDismissed) {
      return (

      );
    }
    const feedbackButton = (
      <LinkButton className="beta-bar--feedback" href={googleForm}>
        Leave feedback
      </LinkButton>
    );
    const fallbackButton = (

        Back to old version

    );
    return (
      <BarWrapper className="beta-bar" classNamePrefix="beta-bar" onClose={this.handleDismiss}>
        {betaText}

          {feedbackButton}
          {fallbackButton}

      </BarWrapper>
    );
  }
}
<commit_msg>fix: Remove unnecessary window.location check.<commit_after>/* global window document */
import React from 'react';
import Icon from '@economist/component-icon';
import reactCookie from 'react-cookie';
import LinkButton from '@economist/component-link-button';
import BarWrapper from '@economist/component-bar-wrapper';

const betaText = [
  (

      You're viewing a beta release of

        {" The Economist"}

      's new website

  ),
  (

      {' We would like to hear what you think'}

  ),
];

const googleForm = 'https://docs.google.com/forms/d/1ZCdwituoyhHAPKjCKvDvzRp66zwOv23GrCPH4rGINrE/viewform';

export default class BetaBar extends React.Component {
  static propTypes = {
    cookieName: React.PropTypes.string,
    cookieValue: React.PropTypes.string,
    closeCookieName: React.PropTypes.string,
    closeCookieValue: React.PropTypes.string,
    reactCookieInstance: React.PropTypes.shape({
      save: React.PropTypes.func,
    }),
    onFallback: React.PropTypes.func,
  }
  static defaultProps = {
    cookieName: 'ec_blogsab',
    cookieValue: 'b',
    closeCookieName: 'ec_rvmp_beta_close',
    closeCookieValue: 'x',
    reactCookieInstance: reactCookie,
  }
  constructor(...args) {
    super(...args);
    this.handleFallback = this.handleFallback.bind(this);
    this.handleDismiss = this.handleDismiss.bind(this);
    if (!this.state) {
      this.state = {};
    }
  }
  handleFallback(event) {
    if (typeof window === 'undefined') { return; }
    const { cookieName, cookieValue, reactCookieInstance } = this.props;

    if (cookieName && cookieValue && reactCookieInstance) {
      reactCookieInstance.save(cookieName, cookieValue, {
        maxAge: 30 * 24 * 60 * 60,
      });
      if (this.props.onFallback) {
        this.props.onFallback();
      }
    }

    if (event) {
      event.preventDefault();
    }
  }
  handleDismiss(event) {
    const { closeCookieName, closeCookieValue, reactCookieInstance } = this.props;

    if (closeCookieName && closeCookieValue && reactCookieInstance) {
      reactCookieInstance.save(closeCookieName, closeCookieValue)
    }

    this.setState({ wasDismissed: true });

    if (event) {
      event.preventDefault();
    }
  }
  componentWillMount() {
    if (typeof window === 'undefined') { return; }
    const { closeCookieName, closeCookieValue, reactCookieInstance } = this.props;
    if (closeCookieName && closeCookieValue && reactCookieInstance) {
      this.setState({
        wasDismissed: reactCookieInstance.load(this.props.closeCookieName) === this.props.closeCookieValue,
      });
    }
  }
  render() {
    if (this.state && this.state.wasDismissed) {
      return (

      );
    }
    const feedbackButton = (
      <LinkButton className="beta-bar--feedback" href={googleForm}>
        Leave feedback
      </LinkButton>
    );
    const fallbackButton = (

        Back to old version

    );
    return (
      <BarWrapper className="beta-bar" classNamePrefix="beta-bar" onClose={this.handleDismiss}>
        {betaText}

          {feedbackButton}
          {fallbackButton}

      </BarWrapper>
    );
  }
}
<|endoftext|>


<commit_before>import React from 'react';
import { connect } from 'react-redux';
import { compose } from 'ramda';
import { reduxForm } from 'redux-form';
import { withRouter } from 'react-router';
import PropTypes from 'prop-types';
import TextFieldForm from '../../../forms/textFieldForm';
import RadioForm from '../../../forms/radioForm';
import GridColumn from '../../../common/grid/gridColumn';
import { selectNormalizedCompletionReasons,
  selectCfeiStatus,
  selectCfeiWinnersStatus,
} from '../../../../store';
import { PROJECT_STATUSES, PROJECT_TYPES } from '../../../../helpers/constants';

const messages = {
  justification: 'Add justification for completing this CFEI',
  reason: 'Choose reason of completing this CFEI',
};

const mapCompletionReasons = (disableNoC, disablePar) => (item) => {
  if (item.value === 'NoC' && disableNoC) {
    return { disabled: true, ...item };
  } else if (item.value === 'Par' && disablePar) {
    return { disabled: true, ...item };
  }
  return item;
};

const CompleteCfeiForm = (props) => {
  const { handleSubmit, completionReasons } = props;
  return (
    <form onSubmit={handleSubmit}>
      <GridColumn>
        <RadioForm
          fieldName="completed_reason"
          label={messages.reason}
          values={completionReasons}
          column
        />
        <TextFieldForm
          fieldName="justification"
          label={messages.justification}
          placeholder="Enter comment..."
        />
      </GridColumn>

    </form >
  );
};

CompleteCfeiForm.propTypes = {
  handleSubmit: PropTypes.func.isRequired,
  completionReasons: PropTypes.array,
};

const formEditCfei = reduxForm({
  form: 'completeCfei',
})(CompleteCfeiForm);

const mapStateToProps = (state, { params: { id, type } }) => {
  const completionReasons = selectNormalizedCompletionReasons(state);
  const status = selectCfeiStatus(state, id);
  const reviewStarted = (status === PROJECT_STATUSES.OPE && type !== PROJECT_TYPES.DIRECT);
  const hasWinners = selectCfeiWinnersStatus(state, id);
  return {
    completionReasons: completionReasons.map(
      mapCompletionReasons(reviewStarted, !hasWinners)),
  };
};

export default compose(
  withRouter,
  connect(mapStateToProps),
)(formEditCfei);
<commit_msg>#1294 Finalize CFEI modal bug<commit_after>import React from 'react';
import { connect } from 'react-redux';
import { compose } from 'ramda';
import { reduxForm } from 'redux-form';
import { withRouter } from 'react-router';
import PropTypes from 'prop-types';
import TextFieldForm from '../../../forms/textFieldForm';
import RadioForm from '../../../forms/radioForm';
import GridColumn from '../../../common/grid/gridColumn';
import { selectNormalizedCompletionReasons,
  selectCfeiStatus,
  selectCfeiWinnersStatus,
} from '../../../../store';
import { PROJECT_STATUSES, PROJECT_TYPES } from '../../../../helpers/constants';

const messages = {
  justification: 'Add justification for completing this CFEI',
  reason: 'Choose reason of completing this CFEI',
};

const mapCompletionReasons = (disableNoC, disablePar) => (item) => {
  if (item.value === 'no_candidate' && disableNoC) {
    return { disabled: true, ...item };
  } else if (item.value === 'partners' && disablePar) {
    return { disabled: true, ...item };
  }
  return item;
};

const CompleteCfeiForm = (props) => {
  const { handleSubmit, completionReasons } = props;

  return (
    <form onSubmit={handleSubmit}>
      <GridColumn>
        <RadioForm
          fieldName="completed_reason"
          label={messages.reason}
          values={completionReasons}
          column
        />
        <TextFieldForm
          fieldName="justification"
          label={messages.justification}
          placeholder="Enter comment..."
        />
      </GridColumn>

    </form >
  );
};

CompleteCfeiForm.propTypes = {
  handleSubmit: PropTypes.func.isRequired,
  completionReasons: PropTypes.array,
};

const formEditCfei = reduxForm({
  form: 'completeCfei',
})(CompleteCfeiForm);

const mapStateToProps = (state, { params: { id, type } }) => {
  const completionReasons = selectNormalizedCompletionReasons(state);
  const status = selectCfeiStatus(state, id);
  const reviewStarted = (status === PROJECT_STATUSES.OPE && type !== PROJECT_TYPES.DIRECT);
  const hasWinners = selectCfeiWinnersStatus(state, id);
  console.log(completionReasons);
  return {
    completionReasons: completionReasons.map(
      mapCompletionReasons(reviewStarted, !hasWinners)),
  };
};

export default compose(
  withRouter,
  connect(mapStateToProps),
)(formEditCfei);
<|endoftext|>


<commit_before>var request = require('supertest')
  , assert = require('assert')

var server = require('../server')

describe('Post API', function(){
  it('GET /posts/:postId should return 404', function(done) {
    request(server)
      .get('/v1/posts/this-post-does-not-exist')
      .expect(404, done)
  })

  it('POST /posts should return 200', function(done) {
    request(server)
      .post('/v1/posts')
      .send({ body: 'Hello world' })
      .expect(200, done)
  })
})
<commit_msg>Changes test description that checks 404 post page.<commit_after>var request = require('supertest')
  , assert = require('assert')

var server = require('../server')

describe('Post API', function(){
  it('GET /posts/this-post-does-not-exist should return 404', function(done) {
    request(server)
      .get('/v1/posts/this-post-does-not-exist')
      .expect(404, done)
  })

  it('POST /posts should return 200', function(done) {
    request(server)
      .post('/v1/posts')
      .send({ body: 'Hello world' })
      .expect(200, done)
  })
})
<|endoftext|>


<commit_before>var
	Validator = require('./../../lib/Validator'),
	validator,
	options
;

exports.tests = {
	'should override the settings by editorconfig': function(test) {
		options = {
			trailingspaces: false,
			newlineMaximum: false,
			indentation: 'spaces',
			spaces: 2,
			newline: false,
			ignores: ['js-comments'],
			editorconfig: __dirname + '/../../.editorconfig'
		};

		// fake loading:
		validator = new Validator(options);
		validator._path = __dirname + '/editorconfig.js';
		validator._loadSettings();

		// newline:
		test.ok(validator._settings.newline !== options.newline);
		test.equal(validator._settings.newline, true);

		// indentation will be overwritten:
		test.ok(validator._settings.indentation !== options.indentation);
		test.equal(validator._settings.indentation, 'tabs');

		// spaces will be overwritten:
		test.ok(validator._settings.spaces !== options.spaces);
		test.equal(validator._settings.spaces, 'tab');

		// trailingspaces will be overwritten:
		test.ok(validator._settings.trailingspaces !== options.trailingspaces);
		test.equal(validator._settings.trailingspaces, true);

		// newlineMaximum will be unchanged:
		test.equal(validator._settings.newlineMaximum, options.newlineMaximum);

		test.done();
	},

	'should throw an exception if editorconfig has no valid path': function(test) {
		test.throws(function() {
			validator = new Validator({editorconfig: '.'});
			validator.validate(__filename);
		}, Error);

		test.throws(function() {
			validator = new Validator({editorconfig: __dirname});
			validator.validate(__filename);
		}, Error);

		test.throws(function() {
			validator = new Validator({editorconfig: __dirname + '/path/that/doesnt/existis/.editorconfig'});
			validator.validate(__filename);
		}, Error);

		test.done();
	}
};
<commit_msg>Make .editorconfig path relative so editorconfig module can find it<commit_after>var
	Validator = require('./../../lib/Validator'),
	validator,
	options
;

exports.tests = {
	'should override the settings by editorconfig': function(test) {
		options = {
			trailingspaces: false,
			newlineMaximum: false,
			indentation: 'spaces',
			spaces: 2,
			newline: false,
			ignores: ['js-comments'],
			editorconfig: '.editorconfig'
		};

		// fake loading:
		validator = new Validator(options);
		validator._path = __dirname + '/editorconfig.js';
		validator._loadSettings();

		// newline:
		test.ok(validator._settings.newline !== options.newline);
		test.equal(validator._settings.newline, true);

		// indentation will be overwritten:
		test.ok(validator._settings.indentation !== options.indentation);
		test.equal(validator._settings.indentation, 'tabs');

		// spaces will be overwritten:
		test.ok(validator._settings.spaces !== options.spaces);
		test.equal(validator._settings.spaces, 'tab');

		// trailingspaces will be overwritten:
		test.ok(validator._settings.trailingspaces !== options.trailingspaces);
		test.equal(validator._settings.trailingspaces, true);

		// newlineMaximum will be unchanged:
		test.equal(validator._settings.newlineMaximum, options.newlineMaximum);

		test.done();
	},

	'should throw an exception if editorconfig has no valid path': function(test) {
		test.throws(function() {
			validator = new Validator({editorconfig: '.'});
			validator.validate(__filename);
		}, Error);

		test.throws(function() {
			validator = new Validator({editorconfig: __dirname});
			validator.validate(__filename);
		}, Error);

		test.throws(function() {
			validator = new Validator({editorconfig: __dirname + '/path/that/doesnt/existis/.editorconfig'});
			validator.validate(__filename);
		}, Error);

		test.done();
	}
};
<|endoftext|>