<commit_before>$(function() {
    if (socket) {
        var username = $('body').attr('data-username');
        var key = $('body').attr('data-key');

        /* CHAT */
        var chat_topic = 'Global chat';
        var chat_names = {};
        var connected = false,
            reconnect = false;

        function connectChat() {
            if (connected)
                return;

            connected = true;

            if (reconnect !== true)
                socket.emit('chat_register', { nick: username, key: key });
            $chat.addClass('connected');

            // Keep them connected for another day
            createCookie("chat-connected", "true", 1);
        }

        function disconnectChat() {
            if (!connected)
                return;

            reconnect = true;
            connected = false;
            socket.emit('disconnect');
            $chat.removeClass('connected');

            $chat.removeClass('show');
            createCookie("chat", "closed");

            // Keep them connected for another day
            createCookie("chat-connected", "false", 1);

            // Remove old messages
            $chat.find('.chat-container ul li').remove();

            $chat.find('.chat-bar-title .topic').text('Global chat');
        }

        if (socket) {
            var connected = false;
            var unread = 0;
            var chat_main = $('#chat-main').length;

            if (!chat_main) {
                chat_bar = '
\

\
                                        \
                                        0\
                                        Global chat\

\

\

\
                                            Direct requests for answers will not be tollerated with in the chat (or anywhere else on the site). Do NOT give any personal details to ANY user!!

\
                                            Connect to IRC\

\

\

\

\
                                    <input type="text"/>\

';

                $('body').append(chat_bar);

                $chat = $('#chat-bar');

                // Is chat open
                result = new RegExp('(?:^|; )chat=([^;]*)').exec(document.cookie);
                if (result && result[1] == 'open') {
                    $chat.addClass('show');
                }
                result = new RegExp('(?:^|; )chat-connected=([^;]*)').exec(document.cookie);
                if (result && result[1] == 'true') {
                    connectChat();
                }

                $chat.find('.chat-connect').on('click', function(e) {
                    e.preventDefault();
                    connectChat();
                });
                $chat.find('.icon-off').on('click', function(e) {
                    e.preventDefault();
                    e.stopPropagation();
                    disconnectChat();
                });

            } else {
                $chat = $('#chat-main');

                connectChat();
            }$chat.find('.chat-bar-title .topic').text(chat_topic);

            $unread = $chat.find('.unread');
            $chat.find('.scroll').mCustomScrollbar();

            $chat.find('.chat-bar-title').on('click', function(e) {
                e.stopPropagation();

                if ($chat.hasClass('show')) {
                    $chat.removeClass('show');
                    createCookie("chat", "closed");
                } else {
                    $chat.addClass('show');
                    createCookie("chat", "open");
                    unread = 0;
                    $unread.text(0).addClass('hide');

                    counter_chat = unread;
                    favcounter.set(counter_notifications + counter_chat);
                }
            });

            // $chat.find('.chat-bar-title .icon-new-tab').on('click', function(e) {
            //     e.stopPropagation();
            //     $chat.removeClass('show');
            //     createCookie("chat", "closed");
            //     window.open('/chat.php', 'hackthis-chat', "height=400, width=600, scrollbars=no");
            // });

            $chat.find('input').keypress(function(event) {
                if (event.keyCode == 13 && connected) {
                    msg = $(this).val();
                    $(this).val('');

                    if (msg.length == 0)
                        return false;

                    if (msg.substring(0, 1) == "/" && msg.substring(0, 4) != "/me ") {
                        renderMsg({info: 'command'});
                        return false;
                    }

                    socket.emit('chat', { msg: msg });

                    if (msg.substring(0, 4) != "/me ")
                        renderMsg({nick: username, msg: msg});
                    else
                        renderMsg({info: 'action', nick: username, msg: msg.substring(4)});
                }
            });

            socket.on('chat', function (data) {
                if (data instanceof Array) {
                    for (var i = 0; i < data.length; i++) {
                        if (data[i].info == 'names')
                            renderMsg(data[i]);
                    }
                } else {
                    if (data.info === 'registered') {
                        // console.log(data);
                    } else if (data.info === 'topic') {
                        chat_topic = data.topic;
                        $chat.find('.chat-bar-title .topic').text(chat_topic);
                        // $chat.find('.chat-bar-title .topic').text(chat_topic + ' [' + Object.keys(chat_names).length + ' online]');
                    } else if (data.info === 'names') {
                        chat_names = data.names;
                        renderMsg(data);
                        $chat.find('.chat-bar-title .topic').text(chat_topic);
                        // $chat.find('.chat-bar-title .topic').text(chat_topic + ' [' + Object.keys(chat_names).length + ' online]');

                        if (chat_main) {
                            $.each(data.names, function(key, val) {
                                c = stringToColour(key);
                                span = $('', {style: 'color: '+c}).text(val + key);
                                data = $('
').text(data.msg).prepend(span);
                                $chat.find('.chat-names ul').append(data);
                            });
                        }

                    } else {
                        renderMsg(data);

                        if (!data.info) {
                            // Unread message
                            if (!$chat.hasClass('show')) {
                                unread++;
                                $unread.text(unread).removeClass('hide');

                                counter_chat = unread;
                                favcounter.set(counter_notifications + counter_chat);
                            }
                        }
                    }
                }
            });

            function renderMsg(data) {
                if (!connected)
                    return false;

                if (data.info) {
                    if (data.info == 'join')
                        data = $('
', {class: 'info'}).text('* '+data.nick+' has joined '+data.chan);
                    else if (data.info == 'names') {
                        var online = $('');
                        $.each(data.names, function(key, val) {
                            c = stringToColour(key);
                            span = $('', {style: 'color: '+c}).text(val+key);
                            online.append(span).append(' ');
                        });
                        data = $('
', {class: 'info'}).text('* Users online: ').append(online);
                    } else if (data.info == 'action') {
                        data = $('
', {class: 'info'}).text('* ' + data.nick + ' ' + data.msg);
                    } else if (data.info == 'command') {
                        data = $('
', {class: 'info'}).text('* This command is not yet supported');
                    } else {
                        data = $('
', {class: 'info'}).text('* '+data.nick+' has left');
                    }
                    $chat.find('.chat-container ul').append(data);
                } else {
                    // Get users colour
                    c = stringToColour(data.nick);

                    span = $('', {style: 'color: '+c}).text(data.nick + ' ');
                    data = $('
').text(data.msg).prepend(span);
                    $chat.find('.chat-container ul').append(data);
                }

                $chat.find('.scroll').mCustomScrollbar("scrollTo", "bottom");
            }

            var stringToColour = function(str) {
                for (var i = 0, hash = 0; i < str.length; hash = str.charCodeAt(i++) + ((hash << 5) - hash));
                for (var i = 0, colour = "#"; i < 3; colour += ("00" + ((hash >> i++ * 8) & 0xFF).toString(16)).slice(-2));
                return colour;
            }
        }
    }
});<commit_msg>Added history to chat bar<commit_after>$(function() {
    if (socket) {
        var username = $('body').attr('data-username');
        var key = $('body').attr('data-key');

        /* CHAT */
        var chat_topic = 'Global chat';
        var chat_names = {};
        var connected = false,
            reconnect = false;

        function connectChat() {
            if (connected)
                return;

            connected = true;

            if (reconnect !== true)
                socket.emit('chat_register', { nick: username, key: key });
            $chat.addClass('connected');

            // Keep them connected for another day
            createCookie("chat-connected", "true", 1);
        }

        function disconnectChat() {
            if (!connected)
                return;

            reconnect = true;
            connected = false;
            socket.emit('disconnect');
            $chat.removeClass('connected');

            $chat.removeClass('show');
            createCookie("chat", "closed");

            // Keep them connected for another day
            createCookie("chat-connected", "false", 1);

            // Remove old messages
            $chat.find('.chat-container ul li').remove();

            $chat.find('.chat-bar-title .topic').text('Global chat');
        }

        if (socket) {
            var connected = false;
            var unread = 0;
            var chat_main = $('#chat-main').length;

            if (!chat_main) {
                chat_bar = '
\

\
                                        \
                                        0\
                                        Global chat\

\

\

\
                                            Direct requests for answers will not be tollerated with in the chat (or anywhere else on the site). Do NOT give any personal details to ANY user!!

\
                                            Connect to IRC\

\

\

\

\
                                    <input type="text"/>\

';

                $('body').append(chat_bar);

                $chat = $('#chat-bar');

                // Is chat open
                result = new RegExp('(?:^|; )chat=([^;]*)').exec(document.cookie);
                if (result && result[1] == 'open') {
                    $chat.addClass('show');
                }
                result = new RegExp('(?:^|; )chat-connected=([^;]*)').exec(document.cookie);
                if (result && result[1] == 'true') {
                    connectChat();
                }

                $chat.find('.chat-connect').on('click', function(e) {
                    e.preventDefault();
                    connectChat();
                });
                $chat.find('.icon-off').on('click', function(e) {
                    e.preventDefault();
                    e.stopPropagation();
                    disconnectChat();
                });

            } else {
                $chat = $('#chat-main');

                connectChat();
            }$chat.find('.chat-bar-title .topic').text(chat_topic);

            $unread = $chat.find('.unread');
            $chat.find('.scroll').mCustomScrollbar();

            $chat.find('.chat-bar-title').on('click', function(e) {
                e.stopPropagation();

                if ($chat.hasClass('show')) {
                    $chat.removeClass('show');
                    createCookie("chat", "closed");
                } else {
                    $chat.addClass('show');
                    createCookie("chat", "open");
                    unread = 0;
                    $unread.text(0).addClass('hide');

                    counter_chat = unread;
                    favcounter.set(counter_notifications + counter_chat);
                }
            });

            // $chat.find('.chat-bar-title .icon-new-tab').on('click', function(e) {
            //     e.stopPropagation();
            //     $chat.removeClass('show');
            //     createCookie("chat", "closed");
            //     window.open('/chat.php', 'hackthis-chat', "height=400, width=600, scrollbars=no");
            // });

            $chat.find('input').keypress(function(event) {
                if (event.keyCode == 13 && connected) {
                    msg = $(this).val();
                    $(this).val('');

                    if (msg.length == 0)
                        return false;

                    if (msg.substring(0, 1) == "/" && msg.substring(0, 4) != "/me ") {
                        renderMsg({info: 'command'});
                        return false;
                    }

                    socket.emit('chat', { msg: msg });

                    if (msg.substring(0, 4) != "/me ")
                        renderMsg({nick: username, msg: msg});
                    else
                        renderMsg({info: 'action', nick: username, msg: msg.substring(4)});
                }
            });

            socket.on('chat', function (data) {
                if (data instanceof Array) {
                    for (var i = 0; i < data.length; i++) {
                        if (!data[i].info || data[i].info == 'names')
                            renderMsg(data[i]);
                    }
                } else {
                    if (data.info === 'registered') {
                        // console.log(data);
                    } else if (data.info === 'topic') {
                        chat_topic = data.topic;
                        $chat.find('.chat-bar-title .topic').text(chat_topic);
                        // $chat.find('.chat-bar-title .topic').text(chat_topic + ' [' + Object.keys(chat_names).length + ' online]');
                    } else if (data.info === 'names') {
                        chat_names = data.names;
                        renderMsg(data);
                        $chat.find('.chat-bar-title .topic').text(chat_topic);
                        // $chat.find('.chat-bar-title .topic').text(chat_topic + ' [' + Object.keys(chat_names).length + ' online]');

                        if (chat_main) {
                            $.each(data.names, function(key, val) {
                                c = stringToColour(key);
                                span = $('', {style: 'color: '+c}).text(val + key);
                                data = $('
').text(data.msg).prepend(span);
                                $chat.find('.chat-names ul').append(data);
                            });
                        }

                    } else {
                        renderMsg(data);

                        if (!data.info) {
                            // Unread message
                            if (!$chat.hasClass('show')) {
                                unread++;
                                $unread.text(unread).removeClass('hide');

                                counter_chat = unread;
                                favcounter.set(counter_notifications + counter_chat);
                            }
                        }
                    }
                }
            });

            function renderMsg(data) {
                if (!connected)
                    return false;

                if (data.info) {
                    if (data.info == 'join')
                        data = $('
', {class: 'info'}).text('* '+data.nick+' has joined '+data.chan);
                    else if (data.info == 'names') {
                        var online = $('');
                        $.each(data.names, function(key, val) {
                            c = stringToColour(key);
                            span = $('', {style: 'color: '+c}).text(val+key);
                            online.append(span).append(' ');
                        });
                        data = $('
', {class: 'info'}).text('* Users online: ').append(online);
                    } else if (data.info == 'action') {
                        data = $('
', {class: 'info'}).text('* ' + data.nick + ' ' + data.msg);
                    } else if (data.info == 'command') {
                        data = $('
', {class: 'info'}).text('* This command is not yet supported');
                    } else {
                        data = $('
', {class: 'info'}).text('* '+data.nick+' has left');
                    }
                    $chat.find('.chat-container ul').append(data);
                } else {
                    // Get users colour
                    c = stringToColour(data.nick);

                    span = $('', {style: 'color: '+c}).text(data.nick + ' ');
                    data = $('
').text(data.msg).prepend(span);
                    $chat.find('.chat-container ul').append(data);
                }

                $chat.find('.scroll').mCustomScrollbar("scrollTo", "bottom");
            }

            var stringToColour = function(str) {
                for (var i = 0, hash = 0; i < str.length; hash = str.charCodeAt(i++) + ((hash << 5) - hash));
                for (var i = 0, colour = "#"; i < 3; colour += ("00" + ((hash >> i++ * 8) & 0xFF).toString(16)).slice(-2));
                return colour;
            }
        }
    }
});<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2019 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

foam.CLASS({
  package: 'foam.u2.detail',
  name: 'SectionedDetailPropertyView',
  extends: 'foam.u2.View',

  documentation: `
    View for one property of a SectionedDetailView.
  `,

  css: `
    ^ m3 {
      font-size: 16px;
      font-weight: bold;
    }

    ^validation-container {
      margin-top: 4px;
      color: #d9170e;
    }

    ^helper-icon {
      width: 20px;
      height: 20px;
    }

    ^error-icon {
      width: 16px;
      height: 16px;
    }
    ^error .foam-u2-TextField {
      background-color: #fbedec;
      border: solid 1px #d9170e;
      font-size: 12px;
    }
    ^error .foam-u2-tag-TextArea {
      background-color: #fbedec;
      border: solid 1px #d9170e;
      font-size: 12px;
    }
    ^error .foam-u2-tag-Select {
      background-color: #fbedec;
      border: solid 1px #d9170e;
      font-size: 12px;
    }
    ^error .foam-u2-view-date-DateTimePicker .date-display-box {
      background-color: #fbedec;
      border: solid 1px #d9170e;
      font-size: 12px;
    }

    /*
      !IMPORTANT!
      For the following inputs below, we are planning
      encode these changes in the actual foam files
    */

    ^ .foam-u2-TextField {
      width: 100%;
      padding: 10px 8px;
      font-size: 14px;
    }

    ^ .foam-u2-view-date-DateTimePicker {
      cursor: pointer;
    }

    ^ .foam-u2-tag-Select {
      width: 100%;
      font-size: 14px;
      border: solid 1px #8e9090;
      border-radius: 3px;
      font-weight: 400;
      padding: 10px 8px;
      box-shadow: none;
      background: #ffffff url('images/dropdown-icon.svg') no-repeat 99% 50%;
      -webkit-appearance: none;
      cursor: pointer;
    }

    ^ .foam-u2-view-RichChoiceView {
      display: flex;
    }

    ^ .foam-u2-view-RichChoiceView-chevron {
      content: '▾';
      padding-left: 0px;
      font-size: 16px;
      color: #8D9090;
    }

    ^ .foam-u2-view-RichChoiceView-selection-view {
      padding: 2px 12px 0px 8px;
      width: 100%;
      border-radius: 3px;
      border: solid 1px #8e9090;
      background-color: #ffffff;
      box-sizing: border-box;
      -webkit-appearance: none;
      cursor: pointer;
      font-size: 14px;
    }

    ^ .foam-u2-view-RichChoiceView .search {
      padding: 8px 16px;
      font-size: 14px;
      border-bottom: 1px solid #f4f4f9;
    }

    ^ .foam-u2-detail-SectionedDetailPropertyView .property-filter {
      font-size: 14px;
      padding-left: 16px;
    }

    ^ .foam-u2-view-RichChoiceView .search input {
      border-bottom: none;
    }

    ^ .foam-u2-view-RichChoiceView .search img {
      top: 8px;
    }

    ^ .foam-u2-view-RichChoiceView-heading {
      border-bottom: 1px solid #f4f4f9;
      line-height: 24px;
      font-size: 14px;
      color: #333;
      font-weight: 900;
      padding: 6px 16px;
    }

    ^ .foam-u2-IntView {
      width: 100%;
      padding: 10px 8px;
      font-size: 14px;
    }

    ^ .foam-u2-view-RichChoiceView-container {
      z-index: 1000;
    }

    ^ .DefaultRowView-row {
      background: white;
      padding: 8px 16px;
      font-size: 12px;
      color: #424242;
    }

    ^ .DefaultRowView-row:hover {
      background: #f4f4f9;
      cursor: pointer;
    }

    ^ .foam-u2-CheckBox {
      -webkit-appearance: none;
      border-radius: 2px;
      border: solid 1px #8e9090;
      box-sizing: border-box;
      display: inline-block;
      fill: rgba(0, 0, 0, 0);

      vertical-align: middle;

      height: 16px;
      width: 16px;

      opacity: 1;

      transition: background-color 140ms, border-color 140ms;
    }

    ^ .foam-u2-CheckBox-label {
      margin-left: 12px;
      vertical-align: middle;
    }

    ^ .foam-u2-CheckBox:checked {
      background-color: #604aff;
      fill: white;
      border: solid 1px #604aff;
    }

    ^ .foam-u2-CheckBox:checked:after {
      content: url(data:image/svg+xml,%3Csvg%20viewBox%3D%220%200%2048%2048%22%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2215%22%20height%3D%2215%22%20version%3D%221.1%22%3E%0A%20%20%20%3Cpath%20fill%3D%22white%22%20stroke-width%3D%223%22%20d%3D%22M18%2032.34L9.66%2024l-2.83%202.83L18%2038l24-24-2.83-2.83z%22/%3E%0A%3C/svg%3E);
    }

    ^ input[type="radio" i] {
      -webkit-appearance: none;
      border-radius: 8px;
      background-color: #ffffff;
      border: solid 1px #8e9090;
      box-sizing: border-box;
      display: inline-block;
      fill: rgba(0, 0, 0, 0);

      vertical-align: middle;

      height: 16px;
      width: 16px;

      opacity: 1;

      transition: background-color 140ms, border-color 140ms;
    }

    ^ input[type="radio" i]:checked {
      background-color: #604aff;
    }

    ^ input[type="radio" i]:checked:after {
      content: url('images/active-radio.svg');
    }

    ^ .foam-u2-view-RadioView .foam-u2-view-RadioView:active {
      border: solid 1px #604aff !important;
    }

    ^ .foam-u2-view-RadioView .foam-u2-view-RadioView {
      padding: 16px 10px;
      border-radius: 4px;
      box-shadow: 0 1px 0 0 rgba(22, 29, 37, 0.05);
      border: solid 1px #8e9090;
      width: 330px;
    }

    ^ .foam-u2-view-RadioView label {
      margin-left: 12px;
    }
  `,

  requires: [
    'foam.u2.layout.Cols',
    'foam.u2.layout.Item',
    'foam.u2.layout.Rows'
  ],

  properties: [
    'prop',
  ],

  methods: [
    function initE() {
      var self = this;
      this.SUPER();
      this
        .show(this.prop.createVisibilityFor(this.data$)
          .map(m => m != foam.u2.Visibility.HIDDEN))
        .addClass(this.myClass())
        .start(self.Rows, { defaultChildStyle: { padding: '8px 0'} })
          .add(this.slot(function(data, prop) {

            var errorSlot = prop.validateObj ?
              data.slot(prop.validateObj) :
              foam.core.ConstantSlot.create({ value: null });

            return self.E()
              .start(self.Rows, { defaultChildStyle:  { 'line-height': '2' } })
                .start('m3').add(prop.label$).end()
                .start(self.Cols, { defaultChildStyle: {
                  'margin': '0 16px 0 0',
                  'justify-content': 'flex-start'
                }})
                  .start(self.Item)
                    .style({'flex-grow': 1})
                    .add(prop)
                    .enableClass(this.myClass('error'), errorSlot)
                  .end()
                  .callIf(prop.help, function() {
                    this.start({
                      class: 'foam.u2.tag.Image',
                      data: 'images/question-icon.svg'
                    })
                      .addClass(this.myClass('helper-icon'))
                      .attrs({ title: prop.help })
                    .end();
                  })
                .end()
                .start(self.Cols, { defaultChildStyle: {
                  'justify-content': 'flex-start',
                  'align-items': 'center',
                  'margin': '0 8px 0 0'
                }})
                  .addClass(this.myClass('validation-container'))
                  .show(errorSlot)
                  .start({
                    class: 'foam.u2.tag.Image',
                    data: 'images/inline-error-icon.svg'
                  })
                    .addClass(this.myClass('error-icon'))
                  .end()
                  .add(errorSlot.map((s) => {
                    return self.E().add(s);
                  }))
                .end()
              .end();
          }));
    }
  ]
});
<commit_msg>Added a fixme for the error validation<commit_after>/**
 * @license
 * Copyright 2019 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

foam.CLASS({
  package: 'foam.u2.detail',
  name: 'SectionedDetailPropertyView',
  extends: 'foam.u2.View',

  documentation: `
    View for one property of a SectionedDetailView.
  `,

  css: `
    ^ m3 {
      font-size: 16px;
      font-weight: bold;
    }

    ^validation-container {
      margin-top: 4px;
      color: #d9170e;
    }

    ^helper-icon {
      width: 20px;
      height: 20px;
    }

    ^error-icon {
      width: 16px;
      height: 16px;
    }

    // FIXME: the errors are coming out weird

    ^error .foam-u2-TextField {
      background-color: #fbedec;
      border: solid 1px #d9170e;
      font-size: 12px;
    }
    ^error .foam-u2-tag-TextArea {
      background-color: #fbedec;
      border: solid 1px #d9170e;
      font-size: 12px;
    }
    ^error .foam-u2-tag-Select {
      background-color: #fbedec;
      border: solid 1px #d9170e;
      font-size: 12px;
    }
    ^error .foam-u2-view-date-DateTimePicker .date-display-box {
      background-color: #fbedec;
      border: solid 1px #d9170e;
      font-size: 12px;
    }

    /*
      !IMPORTANT!
      For the following inputs below, we are planning
      encode these changes in the actual foam files
    */

    ^ .foam-u2-TextField {
      width: 100%;
      padding: 10px 8px;
      font-size: 14px;
    }

    ^ .foam-u2-view-date-DateTimePicker {
      cursor: pointer;
    }

    ^ .foam-u2-tag-Select {
      width: 100%;
      font-size: 14px;
      border: solid 1px #8e9090;
      border-radius: 3px;
      font-weight: 400;
      padding: 10px 8px;
      box-shadow: none;
      background: #ffffff url('images/dropdown-icon.svg') no-repeat 99% 50%;
      -webkit-appearance: none;
      cursor: pointer;
    }

    ^ .foam-u2-view-RichChoiceView {
      display: flex;
    }

    ^ .foam-u2-view-RichChoiceView-chevron {
      content: '▾';
      padding-left: 0px;
      font-size: 16px;
      color: #8D9090;
    }

    ^ .foam-u2-view-RichChoiceView-selection-view {
      padding: 2px 12px 0px 8px;
      width: 100%;
      border-radius: 3px;
      border: solid 1px #8e9090;
      background-color: #ffffff;
      box-sizing: border-box;
      -webkit-appearance: none;
      cursor: pointer;
      font-size: 14px;
    }

    ^ .foam-u2-view-RichChoiceView .search {
      padding: 8px 16px;
      font-size: 14px;
      border-bottom: 1px solid #f4f4f9;
    }

    ^ .foam-u2-detail-SectionedDetailPropertyView .property-filter {
      font-size: 14px;
      padding-left: 16px;
    }

    ^ .foam-u2-view-RichChoiceView .search input {
      border-bottom: none;
    }

    ^ .foam-u2-view-RichChoiceView .search img {
      top: 8px;
    }

    ^ .foam-u2-view-RichChoiceView-heading {
      border-bottom: 1px solid #f4f4f9;
      line-height: 24px;
      font-size: 14px;
      color: #333;
      font-weight: 900;
      padding: 6px 16px;
    }

    ^ .foam-u2-IntView {
      width: 100%;
      padding: 10px 8px;
      font-size: 14px;
    }

    ^ .foam-u2-view-RichChoiceView-container {
      z-index: 1000;
    }

    ^ .DefaultRowView-row {
      background: white;
      padding: 8px 16px;
      font-size: 12px;
      color: #424242;
    }

    ^ .DefaultRowView-row:hover {
      background: #f4f4f9;
      cursor: pointer;
    }

    ^ .foam-u2-CheckBox {
      -webkit-appearance: none;
      border-radius: 2px;
      border: solid 1px #8e9090;
      box-sizing: border-box;
      display: inline-block;
      fill: rgba(0, 0, 0, 0);

      vertical-align: middle;

      height: 16px;
      width: 16px;

      opacity: 1;

      transition: background-color 140ms, border-color 140ms;
    }

    ^ .foam-u2-CheckBox-label {
      margin-left: 12px;
      vertical-align: middle;
    }

    ^ .foam-u2-CheckBox:checked {
      background-color: #604aff;
      fill: white;
      border: solid 1px #604aff;
    }

    ^ .foam-u2-CheckBox:checked:after {
      content: url(data:image/svg+xml,%3Csvg%20viewBox%3D%220%200%2048%2048%22%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2215%22%20height%3D%2215%22%20version%3D%221.1%22%3E%0A%20%20%20%3Cpath%20fill%3D%22white%22%20stroke-width%3D%223%22%20d%3D%22M18%2032.34L9.66%2024l-2.83%202.83L18%2038l24-24-2.83-2.83z%22/%3E%0A%3C/svg%3E);
    }

    ^ input[type="radio" i] {
      -webkit-appearance: none;
      border-radius: 8px;
      background-color: #ffffff;
      border: solid 1px #8e9090;
      box-sizing: border-box;
      display: inline-block;
      fill: rgba(0, 0, 0, 0);

      vertical-align: middle;

      height: 16px;
      width: 16px;

      opacity: 1;

      transition: background-color 140ms, border-color 140ms;
    }

    ^ input[type="radio" i]:checked {
      background-color: #604aff;
    }

    ^ input[type="radio" i]:checked:after {
      content: url('images/active-radio.svg');
    }

    ^ .foam-u2-view-RadioView .foam-u2-view-RadioView:active {
      border: solid 1px #604aff !important;
    }

    ^ .foam-u2-view-RadioView .foam-u2-view-RadioView {
      padding: 16px 10px;
      border-radius: 4px;
      box-shadow: 0 1px 0 0 rgba(22, 29, 37, 0.05);
      border: solid 1px #8e9090;
      width: 330px;
    }

    ^ .foam-u2-view-RadioView label {
      margin-left: 12px;
    }
  `,

  requires: [
    'foam.u2.layout.Cols',
    'foam.u2.layout.Item',
    'foam.u2.layout.Rows'
  ],

  properties: [
    'prop',
  ],

  methods: [
    function initE() {
      var self = this;
      this.SUPER();
      this
        .show(this.prop.createVisibilityFor(this.data$)
          .map(m => m != foam.u2.Visibility.HIDDEN))
        .addClass(this.myClass())
        .start(self.Rows, { defaultChildStyle: { padding: '8px 0'} })
          .add(this.slot(function(data, prop) {

            var errorSlot = prop.validateObj ?
              data.slot(prop.validateObj) :
              foam.core.ConstantSlot.create({ value: null });

            return self.E()
              .start(self.Rows, { defaultChildStyle:  { 'line-height': '2' } })
                .start('m3').add(prop.label$).end()
                .start(self.Cols, { defaultChildStyle: {
                  'margin': '0 16px 0 0',
                  'justify-content': 'flex-start'
                }})
                  .start(self.Item)
                    .style({'flex-grow': 1})
                    .add(prop)
                    .enableClass(this.myClass('error'), errorSlot)
                  .end()
                  .callIf(prop.help, function() {
                    this.start({
                      class: 'foam.u2.tag.Image',
                      data: 'images/question-icon.svg'
                    })
                      .addClass(this.myClass('helper-icon'))
                      .attrs({ title: prop.help })
                    .end();
                  })
                .end()
                .start(self.Cols, { defaultChildStyle: {
                  'justify-content': 'flex-start',
                  'align-items': 'center',
                  'margin': '0 8px 0 0'
                }})
                  .addClass(this.myClass('validation-container'))
                  .show(errorSlot)
                  .start({
                    class: 'foam.u2.tag.Image',
                    data: 'images/inline-error-icon.svg'
                  })
                    .addClass(this.myClass('error-icon'))
                  .end()
                  .add(errorSlot.map((s) => {
                    return self.E().add(s);
                  }))
                .end()
              .end();
          }));
    }
  ]
});
<|endoftext|>


<commit_before>if (Meteor.isClient) {

	var haveILikedThis = function (postID) {
		var post = Posts.findOne({_id:postID});
		if (!post) {
			return false;
		}

		var likedBy = post.likedBy;
		var me = Meteor.userId();
		if(_.contains(likedBy, me))
			return true;
		return false;
	};

	Template.comment.events({
		'click a[target=_blank]': function(event) {
			event.preventDefault();
			window.open(event.target.href, '_blank');
		}
	});

	Template.commentList.helpers({
		comments: function() {
			return Comments.find({postId: this._id});
		}
	});

	Template.post.helpers({
		hasPicture: function (userId,ownedBy) {
			return getPicURLForUser(userId,ownedBy,false) !== '';
		},
		user_name: function (user) {
			return displayName(user);
		},
		shortMessage: function (message) {
			return shortLinkMessage(message);
		},
		getUrl: function(userId, ownedBy) {
			return getPicURLForUser(userId,ownedBy,false);
		}
	});

	Template.comment.helpers({
		user_name: function (user) {
			return displayName(user);
		}
	});

	Template.username.helpers({
		user_name: function (userId) {
			var userArray = Meteor.users.find(userId).fetch();
			if (userArray.length === 0) {
				return 'Error!!';
			}
			var user = userArray[0];
			if (user.profile && user.profile.name){
				return user.profile.name;
			}
			if (user.emails[0].address) {
				return user.emails[0].address;
			}
			return user;
		}
	});

	Template.commentSubmit.events({
		'submit form': function(e, template) {
			e.preventDefault();
			var body = document.getElementsByName('body')[0];
			var comment = {
				message: body.value,
				postId: template.data._id
			};
			createComment(comment);
			body.value = '';
		}
	});

	Template.like_button_individual.haveLiked = function (postID) {
		return haveILikedThis(postID);
	};

	Template.like_button_individual.events({
		'click .like_button_individual': function() {
			var postId = this._id;
			var userId = whoami();
			if (!haveILikedThis(postId)) {
				Meteor.call('like', postId, userId);
			} else{
				Meteor.call('unlike', postId, userId);
			}
		}
	});

	Template.removeCommentButton.myComment = function(commentId) {
		return Comments.find(commentId).fetch()[0].ownedBy === Meteor.userId();
	};
	Template.commentShort.ShortMessage = function (message) {
		return shortLinkMessage(message);
	};

	Template.removeComment.events({
		'click .remove': function(event, template) {
			removeComment(template.data);
		},
	});
}

getPostLikeCount = function (postId) {
	return Posts.findOne(postId).likedByCount;
};
<commit_msg>Just keep swimming...<commit_after>/* global getPicURLForUser */
/* global displayName */
/* global shortLinkMessage */
/* global createComment */
/* global whoami */
/* global removeComment */
/* global getPostLikeCount: true */

if (Meteor.isClient) {

	var haveILikedThis = function (postID) {
		var post = Posts.findOne({_id:postID});
		if (!post) {
			return false;
		}

		var likedBy = post.likedBy;
		var me = Meteor.userId();
		if(_.contains(likedBy, me))
			return true;
		return false;
	};

	Template.comment.events({
		'click a[target=_blank]': function(event) {
			event.preventDefault();
			window.open(event.target.href, '_blank');
		}
	});

	Template.commentList.helpers({
		comments: function() {
			return Comments.find({postId: this._id});
		}
	});

	Template.post.helpers({
		hasPicture: function (userId,ownedBy) {
			return getPicURLForUser(userId,ownedBy,false) !== '';
		},
		user_name: function (user) {
			return displayName(user);
		},
		shortMessage: function (message) {
			return shortLinkMessage(message);
		},
		getUrl: function(userId, ownedBy) {
			return getPicURLForUser(userId,ownedBy,false);
		}
	});

	Template.comment.helpers({
		user_name: function (user) {
			return displayName(user);
		}
	});

	Template.username.helpers({
		user_name: function (userId) {
			var userArray = Meteor.users.find(userId).fetch();
			if (userArray.length === 0) {
				return 'Error!!';
			}
			var user = userArray[0];
			if (user.profile && user.profile.name){
				return user.profile.name;
			}
			if (user.emails[0].address) {
				return user.emails[0].address;
			}
			return user;
		}
	});

	Template.commentSubmit.events({
		'submit form': function(e, template) {
			e.preventDefault();
			var body = document.getElementsByName('body')[0];
			var comment = {
				message: body.value,
				postId: template.data._id
			};
			createComment(comment);
			body.value = '';
		}
	});

	Template.like_button_individual.haveLiked = function (postID) {
		return haveILikedThis(postID);
	};

	Template.like_button_individual.events({
		'click .like_button_individual': function() {
			var postId = this._id;
			var userId = whoami();
			if (!haveILikedThis(postId)) {
				Meteor.call('like', postId, userId);
			} else{
				Meteor.call('unlike', postId, userId);
			}
		}
	});

	Template.removeCommentButton.myComment = function(commentId) {
		return Comments.find(commentId).fetch()[0].ownedBy === Meteor.userId();
	};
	Template.commentShort.ShortMessage = function (message) {
		return shortLinkMessage(message);
	};

	Template.removeComment.events({
		'click .remove': function(event, template) {
			removeComment(template.data);
		},
	});
}

getPostLikeCount = function (postId) {
	return Posts.findOne(postId).likedByCount;
};
<|endoftext|>


<commit_before>import { WS }                from 'Services';
import {
    createMarkerExpiry,
    createMarkerPurchaseTime,
    createMarkerSpotEntry,
    createMarkerSpotExit,
    createMarkerSpotMiddle,
    createMarkerStartTime,
} from './chart-marker-helpers';

export const createChartTickMarkers = (SmartChartStore, contract_info) => {
    const tick_marker_handler = tickMarker.getInstance(SmartChartStore, contract_info);

    if (contract_info.exit_tick_time) {
        tick_marker_handler.addSpotsFromHistory();
        tick_marker_handler.addLines();
    } else {
        // TODO: implement middle tick markers for ongoing contracts
        // tick_marker_handler.addMarkerSpotsFromStream();
    }
};

export const destroyChartTickMarkers = () => {
    tickMarker.destroyInstance();
};

const zip = (arr, ...arrs) => arr.map((val, idx) => arrs.reduce((a, curr) => [...a, curr[idx]], [val]));

const makeTickArr = (price_arr, times_arr) =>
    zip(price_arr, times_arr).reduce((acc, tick) => [...acc, { price: tick[0], time: tick[1] }], []);

const fnForEach = (fn) => ([...args]) => args.forEach(fn);

const tickMarker = (function () {
    let instance;

    const tickMarkerHandler = (SmartChartStore, { ...contract_info }) => {
        const ticks_history_req = {
            ticks_history: contract_info.underlying,
            start        : contract_info.entry_tick_time,
            end          : contract_info.exit_tick_time,
            count        : (contract_info.tick_count + 1), // add 1 to prevent for 1-tick contracts from returning 5000 ticks
        };
        const ticks_added_to_chart = [];

        const addMarkerFromContract = (markerConfigFn, tick, idx) => {
            const align_label = labelTopOrBottom(tick, idx);
            const marker_config = markerConfigFn(contract_info, idx, align_label);

            if (marker_config) SmartChartStore.createMarker(marker_config);
        };

        const labelTopOrBottom = (tick, idx) => {
            let align_label = 'top';
            if (tick && tick.price) {
                if (idx > 0 && ticks_added_to_chart.length > 1) {
                    const prev_tick = ticks_added_to_chart[idx - 1];

                    if (+tick.price < +prev_tick.price) align_label = 'bottom';
                    if (+tick.price === +prev_tick.price) align_label = prev_tick.align_label;
                }
                ticks_added_to_chart.push({ ...tick, align_label });
            }
            return align_label;
        };

        const addMarkerFromTick = (markerConfigFn, tick, idx) => {
            const align_label = labelTopOrBottom(tick, idx);
            const marker_config = markerConfigFn(tick, idx, align_label);

            if (marker_config) SmartChartStore.createMarker(marker_config);
        };

        const isContractTick = tick =>
            +tick.time >= +contract_info.entry_tick_time && +tick.time <= +contract_info.exit_tick_time;

        const isMiddleTick = tick =>
            +tick.time > contract_info.entry_tick_time && tick.time < contract_info.exit_tick_time;

        const isEntryTick = tick => +tick.time === +contract_info.entry_tick_time;

        const isExitTick = tick => +tick.time === +contract_info.exit_tick_time;

        const addTickToChart = (tick, idx) => {
            const is_entry  = idx === 0 && isEntryTick(tick);
            const is_exit   = isExitTick(tick);
            const is_middle = isMiddleTick(tick);

            if (is_entry) addMarkerFromContract(createMarkerSpotEntry, tick, idx);
            if (is_exit) addMarkerFromContract(createMarkerSpotExit, tick, idx);
            if (is_middle) addMarkerFromTick(createMarkerSpotMiddle, tick, idx);
        };

        const addTicks = ([ ...ticks_arr ]) => {
            const contract_ticks = ticks_arr
                .sort((a, b) => +a.time - +b.time)
                .filter(isContractTick);

            contract_ticks.forEach(addTickToChart);
        };

        const onTicksHistory = (data) => {
            const { prices, times } = data.history;
            const ticks = makeTickArr(prices, times);

            addTicks(ticks);
        };

        return {
            addSpotsFromHistory: () =>
                WS.sendRequest({ ...ticks_history_req }).then(onTicksHistory),
            addLines: () => {
                fnForEach(addMarkerFromContract)([createMarkerExpiry, createMarkerPurchaseTime, createMarkerStartTime]);
            },
            getContractId: () => contract_info.contract_id,
        };
    };

    return {
        getInstance: (SmartChartStore, contract_info) => {
            if (!instance || instance.getContractId() !== contract_info.contract_id) {
                instance = tickMarkerHandler(SmartChartStore, contract_info);
            }
            return instance;
        },
        destroyInstance: () => {
            // TODO: forget tick history stream for ongoing contracts here
            if (instance) instance = null;
        },
    };
})();
<commit_msg>Fix tick 1 label alignment<commit_after>import { WS }                from 'Services';
import {
    createMarkerExpiry,
    createMarkerPurchaseTime,
    createMarkerSpotEntry,
    createMarkerSpotExit,
    createMarkerSpotMiddle,
    createMarkerStartTime,
} from './chart-marker-helpers';

export const createChartTickMarkers = (SmartChartStore, contract_info) => {
    const tick_marker_handler = tickMarker.getInstance(SmartChartStore, contract_info);

    if (contract_info.exit_tick_time) {
        tick_marker_handler.addSpotsFromHistory();
        tick_marker_handler.addLines();
    } else {
        // TODO: implement middle tick markers for ongoing contracts
        // tick_marker_handler.addMarkerSpotsFromStream();
    }
};

export const destroyChartTickMarkers = () => {
    tickMarker.destroyInstance();
};

const zip = (arr, ...arrs) => arr.map((val, idx) => arrs.reduce((a, curr) => [...a, curr[idx]], [val]));

const makeTickArr = (price_arr, times_arr) =>
    zip(price_arr, times_arr).reduce((acc, tick) => [...acc, { price: tick[0], time: tick[1] }], []);

const fnForEach = (fn) => ([...args]) => args.forEach(fn);

const tickMarker = (function () {
    let instance;

    const tickMarkerHandler = (SmartChartStore, { ...contract_info }) => {
        const ticks_history_req = {
            ticks_history: contract_info.underlying,
            start        : contract_info.entry_tick_time,
            end          : contract_info.exit_tick_time,
            count        : (contract_info.tick_count + 1), // add 1 to prevent for 1-tick contracts from returning 5000 ticks
        };
        const ticks_added_to_chart = [];

        const addMarkerFromContract = (markerConfigFn, tick, idx) => {
            const align_label = labelTopOrBottom(tick, idx);
            const marker_config = markerConfigFn(contract_info, idx, align_label);

            if (marker_config) SmartChartStore.createMarker(marker_config);
        };

        const labelTopOrBottom = (tick, idx) => {
            let align_label = 'top';
            if (tick && tick.price) {
                if (idx > 0 && ticks_added_to_chart.length) {
                    const prev_tick = ticks_added_to_chart[idx - 1];

                    if (+tick.price < +prev_tick.price) align_label = 'bottom';
                    if (+tick.price === +prev_tick.price) align_label = prev_tick.align_label;
                }
                ticks_added_to_chart.push({ ...tick, align_label });
            }
            return align_label;
        };

        const addMarkerFromTick = (markerConfigFn, tick, idx) => {
            const align_label = labelTopOrBottom(tick, idx);
            const marker_config = markerConfigFn(tick, idx, align_label);

            if (marker_config) SmartChartStore.createMarker(marker_config);
        };

        const isContractTick = tick =>
            +tick.time >= +contract_info.entry_tick_time && +tick.time <= +contract_info.exit_tick_time;

        const isMiddleTick = tick =>
            +tick.time > contract_info.entry_tick_time && tick.time < contract_info.exit_tick_time;

        const isEntryTick = tick => +tick.time === +contract_info.entry_tick_time;

        const isExitTick = tick => +tick.time === +contract_info.exit_tick_time;

        const addTickToChart = (tick, idx) => {
            const is_entry  = idx === 0 && isEntryTick(tick);
            const is_exit   = isExitTick(tick);
            const is_middle = isMiddleTick(tick);

            if (is_entry) addMarkerFromContract(createMarkerSpotEntry, tick, idx);
            if (is_exit) addMarkerFromContract(createMarkerSpotExit, tick, idx);
            if (is_middle) addMarkerFromTick(createMarkerSpotMiddle, tick, idx);
        };

        const addTicks = ([ ...ticks_arr ]) => {
            const contract_ticks = ticks_arr
                .sort((a, b) => +a.time - +b.time)
                .filter(isContractTick);

            contract_ticks.forEach(addTickToChart);
        };

        const onTicksHistory = (data) => {
            const { prices, times } = data.history;
            const ticks = makeTickArr(prices, times);

            addTicks(ticks);
        };

        return {
            addSpotsFromHistory: () =>
                WS.sendRequest({ ...ticks_history_req }).then(onTicksHistory),
            addLines: () => {
                fnForEach(addMarkerFromContract)([createMarkerExpiry, createMarkerPurchaseTime, createMarkerStartTime]);
            },
            getContractId: () => contract_info.contract_id,
        };
    };

    return {
        getInstance: (SmartChartStore, contract_info) => {
            if (!instance || instance.getContractId() !== contract_info.contract_id) {
                instance = tickMarkerHandler(SmartChartStore, contract_info);
            }
            return instance;
        },
        destroyInstance: () => {
            // TODO: forget tick history stream for ongoing contracts here
            if (instance) instance = null;
        },
    };
})();
<|endoftext|>


<commit_before>define(['goo/loaders/handlers/ComponentHandler',
	'goo/entities/components/LightComponent',
	'goo/renderer/light/PointLight',
	'goo/renderer/light/SpotLight',
	'goo/renderer/light/DirectionalLight',
	'goo/math/Vector',
	'goo/util/rsvp',
	'goo/util/PromiseUtil',
	'goo/util/ObjectUtil'
],
/** @lends */
function(
	ComponentHandler,
	LightComponent,
	PointLight,
	SpotLight,
	DirectionalLight,
	Vector,
	RSVP,
	pu,
	_
) {
	'use strict';

	/**
	 * @class For handling loading of light components
	 * @constructor
	 * @param {World} world The goo world
	 * @param {function} getConfig The config loader function. See {@see DynamicLoader._loadRef}.
	 * @param {function} updateObject The handler function. See {@see DynamicLoader.update}.
	 * @extends ComponentHandler
	 * @private
	 */
	function LightComponentHandler() {
		ComponentHandler.apply(this, arguments);
		this._type = 'LightComponent';
	}

	LightComponentHandler.prototype = Object.create(ComponentHandler.prototype);
	LightComponentHandler.prototype.constructor = LightComponentHandler;
	ComponentHandler._registerClass('light', LightComponentHandler);

	/**
	 * Prepare component. Set defaults on config here.
	 * @param {object} config
	 * @private
	 */
	LightComponentHandler.prototype._prepare = function(config) {
		_.defaults(config, {
			direction: [0, 0, 0],
			color: [1, 1, 1],
			shadowCaster: false,
			lightCookie: null
		});
		if (config.type !== 'DirectionalLight') {
			config.range = (config.range !== undefined) ? config.range : 1000;
		}
		if (config.shadowCaster) {
			config.shadowSettings = config.shadowSettings || {};
			_.defaults(config.shadowSettings, {
				shadowType: 'Basic',
				near: 1,
				far: 1000,
				resolution: [512, 512],
				darkness: 0.5
			});
			var settings = config.shadowSettings;
			if (settings.projection === 'Parallel') {
				settings.size = (settings.size !== undefined) ? settings.size : 400;
			} else {
				settings.fov = (settings.fov !== undefined) ? settings.fov : 55;
			}
		}
	};

	/**
	 * Create light component object based on the config.
	 * @returns {LightComponent} the created component object
	 * @private
	 */
	LightComponentHandler.prototype._create = function() {
		return new LightComponent();
	};

	/**
	 * Update engine cameracomponent object based on the config.
	 * @param {Entity} entity The entity on which this component should be added.
	 * @param {object} config
	 * @param {object} options
	 * @returns {RSVP.Promise} promise that resolves with the component when loading is done.
	 */
	LightComponentHandler.prototype.update = function(entity, config, options) {
		var that = this;
		var Light = {
			SpotLight: SpotLight,
			DirectionalLight: DirectionalLight,
			PointLight: PointLight
		};

		return ComponentHandler.prototype.update.call(this, entity, config, options).then(function(component) {
			if (!component) { return; }
			var light = component.light;
			if(!light || Light[config.type] !== light.constructor) {
				light = new Light[config.type]();
				component.light = light;
			}
			for (var key in config) {
				var value = config[key];
				if (light.hasOwnProperty(key)) {
					if (key === 'shadowSettings') {
						for (var key in value) {
							var shadowVal = value[key];
							if (light.shadowSettings[key] instanceof Vector) {
								light.shadowSettings[key].set(shadowVal);
							} else {
								light.shadowSettings[key] = _.clone(shadowVal);
							}
						}
					}	else if (light[key] instanceof Vector) {
						light[key].set(value);
					} else {
						light[key] = _.clone(value);
					}
				}
			}

			if (config.type === 'PointLight') {
				light.shadowCaster = false;
			}

			if (config.lightCookie && config.type !== 'PointLight') {
				var textureObj = config.lightCookie;

				if (!textureObj || !textureObj.textureRef || textureObj.enabled === false) {
					light.lightCookie = null;
					return component;
				} else {
					return that._load(textureObj.textureRef, options).then(function (texture) {
						light.lightCookie = texture;
						return component;
					});
				}
			} else {
				light.lightCookie = null;
				return component;
			}
		});
	};

	return LightComponentHandler;
});
<commit_msg>Fixed https://trello.com/c/1aCX0n9t/1929-normal-if-shadows-are-turned-on-the-shader-will-break-on-ios8-make-a-nice-fallback-to-turn-off-shadows-where-they-aren-t-support<commit_after>define(['goo/loaders/handlers/ComponentHandler',
	'goo/entities/components/LightComponent',
	'goo/renderer/light/PointLight',
	'goo/renderer/light/SpotLight',
	'goo/renderer/light/DirectionalLight',
	'goo/math/Vector',
	'goo/util/rsvp',
	'goo/util/PromiseUtil',
	'goo/util/ObjectUtil'
],
/** @lends */
function(
	ComponentHandler,
	LightComponent,
	PointLight,
	SpotLight,
	DirectionalLight,
	Vector,
	RSVP,
	pu,
	_
) {
	'use strict';

	/**
	 * @class For handling loading of light components
	 * @constructor
	 * @param {World} world The goo world
	 * @param {function} getConfig The config loader function. See {@see DynamicLoader._loadRef}.
	 * @param {function} updateObject The handler function. See {@see DynamicLoader.update}.
	 * @extends ComponentHandler
	 * @private
	 */
	function LightComponentHandler() {
		ComponentHandler.apply(this, arguments);
		this._type = 'LightComponent';
	}

	LightComponentHandler.prototype = Object.create(ComponentHandler.prototype);
	LightComponentHandler.prototype.constructor = LightComponentHandler;
	ComponentHandler._registerClass('light', LightComponentHandler);

	//! AT: would be nice to have a FuncUtil.memoize()
	var cachedSupportsShadows;
	var supportsShadows = function () {
		if (cachedSupportsShadows === undefined) {
			var isIos = /(iPad|iPhone|iPod)/g.test(navigator.userAgent);
			cachedSupportsShadows = !isIos;
		}
		return cachedSupportsShadows;
	};

	/**
	 * Prepare component. Set defaults on config here.
	 * @param {object} config
	 * @private
	 */
	LightComponentHandler.prototype._prepare = function (config) {
		_.defaults(config, {
			direction: [0, 0, 0],
			color: [1, 1, 1],
			shadowCaster: false,
			lightCookie: null
		});

		if (config.type !== 'DirectionalLight') {
			config.range = (config.range !== undefined) ? config.range : 1000;
		}

		if (config.shadowCaster && supportsShadows(this.world.gooRunner.renderer)) {
			config.shadowSettings = config.shadowSettings || {};
			_.defaults(config.shadowSettings, {
				shadowType: 'Basic',
				near: 1,
				far: 1000,
				resolution: [512, 512],
				darkness: 0.5
			});

			var settings = config.shadowSettings;

			if (settings.projection === 'Parallel') {
				settings.size = (settings.size !== undefined) ? settings.size : 400;
			} else {
				settings.fov = (settings.fov !== undefined) ? settings.fov : 55;
			}
		}
	};

	/**
	 * Create light component object based on the config.
	 * @returns {LightComponent} the created component object
	 * @private
	 */
	LightComponentHandler.prototype._create = function() {
		return new LightComponent();
	};

	/**
	 * Update engine cameracomponent object based on the config.
	 * @param {Entity} entity The entity on which this component should be added.
	 * @param {object} config
	 * @param {object} options
	 * @returns {RSVP.Promise} promise that resolves with the component when loading is done.
	 */
	LightComponentHandler.prototype.update = function(entity, config, options) {
		var that = this;
		var Light = {
			SpotLight: SpotLight,
			DirectionalLight: DirectionalLight,
			PointLight: PointLight
		};

		return ComponentHandler.prototype.update.call(this, entity, config, options).then(function(component) {
			if (!component) { return; }
			var light = component.light;
			if(!light || Light[config.type] !== light.constructor) {
				light = new Light[config.type]();
				component.light = light;
			}

			for (var key in config) {
				var value = config[key];
				if (light.hasOwnProperty(key)) {
					if (key === 'shadowSettings') {
						for (var key in value) {
							var shadowVal = value[key];
							if (light.shadowSettings[key] instanceof Vector) {
								light.shadowSettings[key].set(shadowVal);
							} else {
								light.shadowSettings[key] = _.clone(shadowVal);
							}
						}
					}	else if (light[key] instanceof Vector) {
						light[key].set(value);
					} else {
						light[key] = _.clone(value);
					}
				}
			}

			if (config.type === 'PointLight' || !supportsShadows(that.world.gooRunner.renderer)) {
				light.shadowCaster = false;
			}

			if (config.lightCookie && config.type !== 'PointLight') {
				var textureObj = config.lightCookie;

				if (!textureObj || !textureObj.textureRef || textureObj.enabled === false) {
					light.lightCookie = null;
					return component;
				} else {
					return that._load(textureObj.textureRef, options).then(function (texture) {
						light.lightCookie = texture;
						return component;
					});
				}
			} else {
				light.lightCookie = null;
				return component;
			}
		});
	};

	return LightComponentHandler;
});
<|endoftext|>


<commit_before>(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        define(factory);
    } else if (typeof exports === 'object') {
        module.exports = factory();
    } else {
        root.httpinvoke = factory();
  }
}(this, function () {
    var trim = function(string) {
        return string.replace(/^\s+|\s+$/g,'');
    };
    var indexOf = function(array, item) {
        for(var i = 0; i < array.length; i += 1) {
            if(array[i] === item) {
                return i;
            }
        }
        return -1;
    };
    var createXHR = function() {
        try {
            createXHR = function() {
                return new XMLHttpRequest();
            };
            return createXHR();
        } catch(err) {
        }
        var candidates = ['Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.6.0', 'Msxml2.XMLHTTP.3.0', 'Msxml2.XMLHTTP'];
        var i = candidates.length - 1;
        while(i >= 0) {
            try {
                createXHR = function() {
                    return new ActiveXObject(candidates[i]);
                };
                return createXHR();
            } catch(err) {
            }
            i -= 1;
        }
        createXHR = function() {
            throw new Error('Cannot construct XMLHttpRequest');
        };
        return createXHR();
    };

    var parseHeader = function(header) {
        var colon = header.indexOf(':');
        return {
            name: header.slice(0, colon).toLowerCase(),
            value: trim(header.slice(colon + 1))
        };
    };

    // http://www.w3.org/TR/XMLHttpRequest/#the-setrequestheader()-method
    var forbiddenInputHeaders = ['accept-charset', 'accept-encoding', 'access-control-request-headers', 'access-control-request-method', 'connection', 'content-length', 'cookie', 'cookie2', 'date', 'dnt', 'expect', 'host', 'keep-alive', 'origin', 'referer', 'te', 'trailer', 'transfer-encoding', 'upgrade', 'user-agent', 'via'];
    var validateInputHeaders = function(headers) {
        for(var header in headers) {
            if(headers.hasOwnProperty(header)) {
                var headerl = header.toLowerCase();
                if(indexOf(forbiddenInputHeaders, headerl) >= 0) {
                    throw new Error('Input header ' + header + ' is forbidden to be set programmatically');
                }
                if(headerl.substr(0, 'proxy-'.length) === 'proxy-') {
                    throw new Error('Input header ' + header + ' (to be precise, all Proxy-*) is forbidden to be set programmatically');
                }
                if(headerl.substr(0, 'sec-'.length) === 'sec-') {
                    throw new Error('Input header ' + header + ' (to be precise, all Sec-*) is forbidden to be set programmatically');
                }
            }
        }
    };
    var fillOutputHeaders = function(xhr, outputHeaders) {
        var headers = xhr.getAllResponseHeaders().split(/\r?\n/);
        var i = headers.length - 1;
        var header;
        while(i >= 0) {
            header = trim(headers[i]);
            if(header.length > 0) {
                header = parseHeader(header);
                outputHeaders[header.name] = header.value;
            }
            i -= 1;
        }
    };

    var noop = function() {};
    var readyStates = ['UNSENT', 'OPENED', 'HEADERS_RECEIVED', 'LOADING', 'DONE'];
    return function(uri, method, options) {
        if(typeof method === 'undefined') {
            method = 'GET';
            options = {};
        } else if(typeof options === 'undefined') {
            if(typeof method === 'string') {
                options = {};
            } else {
                options = method;
                method = 'GET';
            }
        }
        var uploadProgressCb = options.uploading || noop;
        var downloadProgressCb = options.downloading || noop;
        var statusCb = options.gotStatus || noop;
        var cb = options.finished || noop;
        var deleteCallbacks = function() {
            uploadProgressCb = null;
            downloadProgressCb = null;
            statusCb = null;
            cb = null;
        };
        var input = options.input || null, inputLength = input === null ? 0 : input.length, inputHeaders = options.headers || {};
        try {
            validateInputHeaders(inputHeaders);
        } catch(err) {
            cb(err);
            deleteCallbacks();
            return;
        }
        var output, outputLength, outputHeaders = {};
        var xhr = createXHR();
        var i;

        if(typeof xhr.upload !== 'undefined') {
            xhr.upload.ontimeout = function(progressEvent) {
                if(cb) {
                    cb(new Error('upload timeout'));
                    deleteCallbacks();
                }
            };
            xhr.upload.onerror = function(progressEvent) {
                if(cb) {
                    cb(new Error('upload error'));
                    deleteCallbacks();
                }
            };
            xhr.upload.onprogress = function(progressEvent) {
                if(uploadProgressCb && progressEvent.lengthComputable) {
                    uploadProgressCb(0, progressEvent.loaded, inputLength);
                }
            };
        }

        if(typeof xhr.ontimeout !== 'undefined') {
            xhr.ontimeout = function(progressEvent) {
                if(cb) {
                    cb(new Error('download timeout'));
                    deleteCallbacks();
                }
            };
        }
        if(typeof xhr.onerror !== 'undefined') {
            xhr.onerror = function(progressEvent) {
                if(cb) {
                    cb(new Error('download error'));
                    deleteCallbacks();
                }
            };
        }
        if(typeof xhr.onprogress !== 'undefined') {
            xhr.onprogress = function(progressEvent) {
                if(downloadProgressCb && progressEvent.lengthComputable) {
                    downloadProgressCb(0, progressEvent.loaded, outputLength);
                }
            };
        }
        xhr.onreadystatechange = function() {
            if(!cb) {
                return;
            }
            var readyState = readyStates[xhr.readyState];
            if(readyState === 'HEADERS_RECEIVED') {
                fillOutputHeaders(xhr, outputHeaders);
                outputLength = Number(outputHeaders['content-length']);
                uploadProgressCb(0, inputLength, inputLength);
                uploadProgressCb = null;
                statusCb(xhr.status, outputHeaders);
                statusCb = null;
                downloadProgressCb(0, 0, outputLength);
            } else if(readyState === 'DONE') {
                if(xhr.status === 0) {
                    cb(new Error('"some type" of network error'));
                    deleteCallbacks();
                    return;
                }
                downloadProgressCb(0, outputLength, outputLength);
                downloadProgressCb = null;
                output = (typeof xhr.responseType === 'undefined' || xhr.responseType === '') ? 'text' : xhr.responseType;
                if(output === 'text') {
                    cb(null, xhr.responseText);
                } else {
                    cb(new Error('Unknown response body format ' + output));
                }
                deleteCallbacks();
            }
        };
        xhr.open(method, uri, true);
        for(var inputHeaderName in inputHeaders) {
            if(inputHeaders.hasOwnProperty(inputHeaderName)) {
                xhr.setRequestHeader(inputHeaderName, inputHeaders[inputHeaderName]);
            }
        }
        // Content-Length header is set automatically
        xhr.send(input);
        uploadProgressCb(0, 0, inputLength);
        if(typeof xhr.upload === 'undefined') {
            uploadProgressCb(0, inputLength, inputLength);
        }
        return function() {
            if(cb) {
                cb(new Error('abort'));
                deleteCallbacks();
                try {
                    xhr.abort();
                } catch(err){
                }
            }
        };
    };
}));
<commit_msg>-browser: fix browsers who do not yet have headers and status code at when readyState is HEADERS_RECEIVED<commit_after>(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        define(factory);
    } else if (typeof exports === 'object') {
        module.exports = factory();
    } else {
        root.httpinvoke = factory();
  }
}(this, function () {
    var trim = function(string) {
        return string.replace(/^\s+|\s+$/g,'');
    };
    var indexOf = function(array, item) {
        for(var i = 0; i < array.length; i += 1) {
            if(array[i] === item) {
                return i;
            }
        }
        return -1;
    };
    var createXHR = function() {
        try {
            createXHR = function() {
                return new XMLHttpRequest();
            };
            return createXHR();
        } catch(err) {
        }
        var candidates = ['Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.6.0', 'Msxml2.XMLHTTP.3.0', 'Msxml2.XMLHTTP'];
        var i = candidates.length - 1;
        while(i >= 0) {
            try {
                createXHR = function() {
                    return new ActiveXObject(candidates[i]);
                };
                return createXHR();
            } catch(err) {
            }
            i -= 1;
        }
        createXHR = function() {
            throw new Error('Cannot construct XMLHttpRequest');
        };
        return createXHR();
    };

    var parseHeader = function(header) {
        var colon = header.indexOf(':');
        return {
            name: header.slice(0, colon).toLowerCase(),
            value: trim(header.slice(colon + 1))
        };
    };

    // http://www.w3.org/TR/XMLHttpRequest/#the-setrequestheader()-method
    var forbiddenInputHeaders = ['accept-charset', 'accept-encoding', 'access-control-request-headers', 'access-control-request-method', 'connection', 'content-length', 'cookie', 'cookie2', 'date', 'dnt', 'expect', 'host', 'keep-alive', 'origin', 'referer', 'te', 'trailer', 'transfer-encoding', 'upgrade', 'user-agent', 'via'];
    var validateInputHeaders = function(headers) {
        for(var header in headers) {
            if(headers.hasOwnProperty(header)) {
                var headerl = header.toLowerCase();
                if(indexOf(forbiddenInputHeaders, headerl) >= 0) {
                    throw new Error('Input header ' + header + ' is forbidden to be set programmatically');
                }
                if(headerl.substr(0, 'proxy-'.length) === 'proxy-') {
                    throw new Error('Input header ' + header + ' (to be precise, all Proxy-*) is forbidden to be set programmatically');
                }
                if(headerl.substr(0, 'sec-'.length) === 'sec-') {
                    throw new Error('Input header ' + header + ' (to be precise, all Sec-*) is forbidden to be set programmatically');
                }
            }
        }
    };
    var fillOutputHeaders = function(xhr, outputHeaders) {
        var headers = xhr.getAllResponseHeaders().split(/\r?\n/);
        var i = headers.length - 1;
        var header;
        while(i >= 0) {
            header = trim(headers[i]);
            if(header.length > 0) {
                header = parseHeader(header);
                outputHeaders[header.name] = header.value;
            }
            i -= 1;
        }
    };

    var noop = function() {};
    var readyStates = ['UNSENT', 'OPENED', 'HEADERS_RECEIVED', 'LOADING', 'DONE'];
    return function(uri, method, options) {
        if(typeof method === 'undefined') {
            method = 'GET';
            options = {};
        } else if(typeof options === 'undefined') {
            if(typeof method === 'string') {
                options = {};
            } else {
                options = method;
                method = 'GET';
            }
        }
        var uploadProgressCb = options.uploading || noop;
        var downloadProgressCb = options.downloading || noop;
        var statusCb = options.gotStatus || noop;
        var cb = options.finished || noop;
        var deleteCallbacks = function() {
            uploadProgressCb = null;
            downloadProgressCb = null;
            statusCb = null;
            cb = null;
        };
        var input = options.input || null, inputLength = input === null ? 0 : input.length, inputHeaders = options.headers || {};
        try {
            validateInputHeaders(inputHeaders);
        } catch(err) {
            cb(err);
            deleteCallbacks();
            return;
        }
        var output, outputLength, outputHeaders = {};
        var xhr = createXHR();
        var i;

        if(typeof xhr.upload !== 'undefined') {
            xhr.upload.ontimeout = function(progressEvent) {
                if(cb) {
                    cb(new Error('upload timeout'));
                    deleteCallbacks();
                }
            };
            xhr.upload.onerror = function(progressEvent) {
                if(cb) {
                    cb(new Error('upload error'));
                    deleteCallbacks();
                }
            };
            xhr.upload.onprogress = function(progressEvent) {
                if(uploadProgressCb && progressEvent.lengthComputable) {
                    uploadProgressCb(0, progressEvent.loaded, inputLength);
                }
            };
        }

        if(typeof xhr.ontimeout !== 'undefined') {
            xhr.ontimeout = function(progressEvent) {
                if(cb) {
                    cb(new Error('download timeout'));
                    deleteCallbacks();
                }
            };
        }
        if(typeof xhr.onerror !== 'undefined') {
            xhr.onerror = function(progressEvent) {
                if(cb) {
                    cb(new Error('download error'));
                    deleteCallbacks();
                }
            };
        }
        if(typeof xhr.onprogress !== 'undefined') {
            xhr.onprogress = function(progressEvent) {
                if(downloadProgressCb && progressEvent.lengthComputable) {
                    downloadProgressCb(0, progressEvent.loaded, outputLength);
                }
            };
        }
        var onHeadersReceived = function() {
            if(statusCb === null) {
                return;
            }
            try {
                if(xhr.status === 'undefined') {
                    return;
                }
            } catch(_) {
                return;
            }
            fillOutputHeaders(xhr, outputHeaders);
            outputLength = Number(outputHeaders['content-length']);
            uploadProgressCb(0, inputLength, inputLength);
            uploadProgressCb = null;
            statusCb(xhr.status, outputHeaders);
            statusCb = null;
            downloadProgressCb(0, 0, outputLength);
        };
        xhr.onreadystatechange = function() {
            if(!cb) {
                return;
            }
            var readyState = readyStates[xhr.readyState];
            if(readyState === 'HEADERS_RECEIVED') {
                onHeadersReceived();
            } else if(readyState === 'DONE') {
                if(xhr.status === 0) {
                    cb(new Error('"some type" of network error'));
                    deleteCallbacks();
                    return;
                }
                onHeadersReceived();
                downloadProgressCb(0, outputLength, outputLength);
                downloadProgressCb = null;
                output = (typeof xhr.responseType === 'undefined' || xhr.responseType === '') ? 'text' : xhr.responseType;
                if(output === 'text') {
                    cb(null, xhr.responseText);
                } else {
                    cb(new Error('Unknown response body format ' + output));
                }
                deleteCallbacks();
            }
        };
        xhr.open(method, uri, true);
        for(var inputHeaderName in inputHeaders) {
            if(inputHeaders.hasOwnProperty(inputHeaderName)) {
                xhr.setRequestHeader(inputHeaderName, inputHeaders[inputHeaderName]);
            }
        }
        // Content-Length header is set automatically
        xhr.send(input);
        uploadProgressCb(0, 0, inputLength);
        if(typeof xhr.upload === 'undefined') {
            uploadProgressCb(0, inputLength, inputLength);
        }
        return function() {
            if(cb) {
                cb(new Error('abort'));
                deleteCallbacks();
                try {
                    xhr.abort();
                } catch(err){
                }
            }
        };
    };
}));
<|endoftext|>


<commit_before>import BABYLON from 'babylonjs';
import {EventSubscriptionContext} from '../../event-util';
import {Buttons} from '../input';
import testPower from './powers/testPower';
import testPower2 from './powers/testPower2';

export default class Hero {
  constructor(
    game, name, speed=15, airSpeed=5, jumpStrength=20,
    attackPower1=testPower, attackPower2=testPower2, attackPower3=testPower, attackPower4=testPower,
    defensePower1=testPower, defensePower2=testPower, defensePower3=testPower, defensePower4=testPower){
    this.game = game;
    this.scene = game.scene;
    this.name = name;

    // Create collision mask
    this.mask = this.initCapsule(2,4);
    this.mask.isVisible = false;

    // Add the mesh
    this.mesh = this.scene.meshes[2].clone(this.name); // 2 is the index of the player mesh
    this.mesh.isVisible = true;
    this.mesh.id = this.name;
    this.mesh.parent = this.mask;
    this.mesh.position.y = -3;
    // Add the player mesh to the shadowGenerator
    this.game.shadowGenerator.getShadowMap().renderList.push(this.mesh);
    // Add material for debug
    var material = new BABYLON.StandardMaterial("blue_material", this.scene);
    material.diffuseColor = BABYLON.Color3.Blue();
    this.mesh.material = material;

    // Create the physics body using mask TODO: Make the Impostor a capsule
    this.body = this.mask.setPhysicsState(BABYLON.PhysicsEngine.BoxImpostor, {mass:10, friction:0.02, restitution:0.5});

    this.updateMassProperties();

    this.initGroundCheck();

    // Movement variables
    this.onGround = false;
    this.jumpStrength = jumpStrength;
    this.speed = speed;
    this.airSpeed = airSpeed;
    this.moveBool = true;

    // Input
    this.Input = {
      AXIS_X : 0,
      AXIS_Y : 0,
      JUMP   : 0
    };

    // InitializeControls
    // TODO add more than just power
    this.attackPower1Pressed = false;
    this.attackPower2Pressed = false;
    this.attackPower3Pressed = false;
    this.attackPower4Pressed = false;

    this.jumpPressed = false;

    // InitializePowers
    this.attackPower1 = new attackPower1(game, this);
    this.attackPower2 = new attackPower2(game, this);
    this.attackPower3 = new attackPower3(game, this);
    this.attackPower4 = new attackPower4(game, this);

    this.defensePower1 = new defensePower1(game, this);
    this.defensePower2 = new defensePower2(game, this);
    this.defensePower3 = new defensePower3(game, this);
    this.defensePower4 = new defensePower4(game, this);

    // Add update loop to Babylon
    this.scene.registerBeforeRender(() => {
        this.update();
    });
  }

  initCapsule (width, height) {
    // Merges three spheres to create a capsule
    var m0 = BABYLON.Mesh.CreateSphere("m0", width, width, this.scene);
    var m1 = BABYLON.MeshBuilder.CreateCylinder("m1", {height: height, diameter: width, tessellation: 20},this.scene);
    var m2 = BABYLON.Mesh.CreateSphere("m2", width, width, this.scene);
    m0.position.y -= height * 0.5;
    m2.position.y += height * 0.5;
    m0.computeWorldMatrix(true);
	  m1.computeWorldMatrix(true);
	  m2.computeWorldMatrix(true);
    return BABYLON.Mesh.MergeMeshes([m0,m1,m2], true);
  }

  updateMassProperties() {
    this.body.linearDamping = .2;
    this.body.fixedRotation = true;
    this.body.updateMassProperties();
  }

  initGroundCheck() {
    // Create mesh for onGround collision check
    this.groundCheck = BABYLON.Mesh.CreateBox("mask", 2.5, this.scene);
    this.groundCheck.parent = this.mask;
    this.groundCheck.position.y = -3;
    this.groundCheck.scaling.y = 0.4;
  }

  checkGroundCheck() {
    // Check for ground
    if (this.groundCheck.intersectsMesh(this.game.ground, true)){
      this.mesh.material.diffuseColor = new BABYLON.Color3.Red();
      this.onGround = true;
    } else {
        this.onGround = false;
    }
  }

  update () {

    this.checkGroundCheck();

    if (this.moveBool) {
        this.move();
    }
    this.powers();
  }

  // use this to make xbox controller movement is smoove and doesn't go over the speed limit
  getScaleSpeed (movementVector, speed) {
      //console.log('movementvector strength:', movementVector.length());
      return speed * Math.min(1, movementVector.length());
  }

  move () {
    // Movement on ground
    // get normalized vector

    var movementVector = new BABYLON.Vector3(this.Input.AXIS_X,0,this.Input.AXIS_Y);
      //console.log('xbox move:', this.Input.AXIS_X, ', ', this.Input.AXIS_Y, ', scaleSpeed:', Math.min(1, movementVector.length()));
    var normalizedMovementVector = movementVector.clone().normalize();
    //console.log('scale speed:', this.getScaleSpeed(movementVector, this.speed));
    if (this.onGround) {
        movementVector = normalizedMovementVector.scale(this.getScaleSpeed(movementVector, this.speed));
    } else {
        movementVector = normalizedMovementVector.scale(this.getScaleSpeed(movementVector, this.airSpeed));
    }
    // movement
    // Player rotation
    this.mask.rotationQuaternion = BABYLON.Quaternion.RotationYawPitchRoll(Math.atan2(this.body.velocity.x, this.body.velocity.z), 0, 0);
    // Jump
    console.log('jump', this.jumpPressed);
    if (this.onGround && this.jumpPressed) {
        console.log("jump!");
        movementVector = movementVector.add(new BABYLON.Vector3(0,this.jumpStrength,0));
        this.mesh.material.diffuseColor = BABYLON.Color3.Blue();
    }
    // apply movement at the very end.
    console.log('ONGROUND:', this.onGround);
    this.mask.applyImpulse(movementVector, this.mask.position);
  }

  // Currently prioritizes the first power
  powers () {
    if (this.attackPower1Pressed) {
      this.useAttackPower1();
    } else if (this.attackPower2Pressed) {
      this.useAttackPower2();
    } else if (this.attackPower3Pressed) {
      this.useAttackPower3();
    } else if (this.attackPower4Pressed) {
      this.useAttackPower4();
    }
  }

  useAttackPower1 () {
      this.attackPower1Pressed = this.attackPower1.usePower();
  }

  useAttackPower2 () {
      this.attackPower2Pressed = this.attackPower2.usePower();
  }

  useAttackPower3 () {
      this.attackPower3Pressed = this.attackPower3.usePower();
  }

  useAttackPower4 () {
      this.attackPower4Pressed = this.attackPower4.usePower();
  }

  setPlayer(player) {
    (this._inputSubscriptions || {destroy: () => {}}).destroy();
    if (!player) {
      return;
    }
    this._inputSubscriptions = new EventSubscriptionContext(player.input)
      .on('end', () => this.setPlayer())
      .on('joychanged', joyVector => this.handleJoyChanged(joyVector))
      .on('buttondown', button => this.handleButtonDown(button))
      .on('buttonup', button => this.handleButtonUp(button))
    ;
  }

  handleJoyChanged(joyVector) {
    //console.log(joyVector);
    this.Input.AXIS_Y = joyVector.y;
    this.Input.AXIS_X = joyVector.x;
    //console.log(this.Input);
  }

  _handleButton(button, pressed) {
    switch (button) {
    case Buttons.A: this.attackPower1Pressed = pressed; break;
    case Buttons.B: this.attackPower2Pressed = pressed; break;
    case Buttons.X: this.attackPower3Pressed = pressed; break;
    case Buttons.Y: this.attackPower4Pressed = pressed; break;
    case Buttons.RB: // TODO: controllers do not yet know how to produce this.
      this.jumpPressed = pressed;
      break;
    }
  }

  handleButtonDown(button) {
    this._handleButton(button, true);
  }

  handleButtonUp(button) {
    this._handleButton(button, false);
  }
}
<commit_msg>Fixed my bad input code<commit_after>import BABYLON from 'babylonjs';
import {EventSubscriptionContext} from '../../event-util';
import {Buttons} from '../input';
import testPower from './powers/testPower';
import testPower2 from './powers/testPower2';

export default class Hero {
  constructor(
    game, name, speed=15, airSpeed=5, jumpStrength=20,
    attackPower1=testPower, attackPower2=testPower2, attackPower3=testPower, attackPower4=testPower,
    defensePower1=testPower, defensePower2=testPower, defensePower3=testPower, defensePower4=testPower){
    this.game = game;
    this.scene = game.scene;
    this.name = name;

    // Create collision mask
    this.mask = this.initCapsule(2,4);
    this.mask.isVisible = false;

    // Add the mesh
    this.mesh = this.scene.meshes[2].clone(this.name); // 2 is the index of the player mesh
    this.mesh.isVisible = true;
    this.mesh.id = this.name;
    this.mesh.parent = this.mask;
    this.mesh.position.y = -3;
    // Add the player mesh to the shadowGenerator
    this.game.shadowGenerator.getShadowMap().renderList.push(this.mesh);
    // Add material for debug
    var material = new BABYLON.StandardMaterial("blue_material", this.scene);
    material.diffuseColor = BABYLON.Color3.Blue();
    this.mesh.material = material;

    // Create the physics body using mask TODO: Make the Impostor a capsule
    this.body = this.mask.setPhysicsState(BABYLON.PhysicsEngine.BoxImpostor, {mass:10, friction:0.02, restitution:0.5});

    this.updateMassProperties();

    this.initGroundCheck();

    // Movement variables
    this.onGround = false;
    this.jumpStrength = jumpStrength;
    this.speed = speed;
    this.airSpeed = airSpeed;
    this.moveBool = true;

    // Input
    this.Input = {
      AXIS_X : 0,
      AXIS_Y : 0,
      JUMP : false,
      ATTACK1: false,
      ATTACK2: false,
      ATTACK3: false,
      ATTACK4: false,
    };

    // InitializeControls
    // TODO add more than just power
    this.attackPower1Pressed = false;
    this.attackPower2Pressed = false;
    this.attackPower3Pressed = false;
    this.attackPower4Pressed = false;

    this.jumpPressed = false;

    // InitializePowers
    this.attackPower1 = new attackPower1(game, this);
    this.attackPower2 = new attackPower2(game, this);
    this.attackPower3 = new attackPower3(game, this);
    this.attackPower4 = new attackPower4(game, this);

    this.defensePower1 = new defensePower1(game, this);
    this.defensePower2 = new defensePower2(game, this);
    this.defensePower3 = new defensePower3(game, this);
    this.defensePower4 = new defensePower4(game, this);

    // Add update loop to Babylon
    this.scene.registerBeforeRender(() => {
        this.update();
    });
  }

  initCapsule (width, height) {
    // Merges three spheres to create a capsule
    var m0 = BABYLON.Mesh.CreateSphere("m0", width, width, this.scene);
    var m1 = BABYLON.MeshBuilder.CreateCylinder("m1", {height: height, diameter: width, tessellation: 20},this.scene);
    var m2 = BABYLON.Mesh.CreateSphere("m2", width, width, this.scene);
    m0.position.y -= height * 0.5;
    m2.position.y += height * 0.5;
    m0.computeWorldMatrix(true);
	  m1.computeWorldMatrix(true);
	  m2.computeWorldMatrix(true);
    return BABYLON.Mesh.MergeMeshes([m0,m1,m2], true);
  }

  updateMassProperties() {
    this.body.linearDamping = .2;
    this.body.fixedRotation = true;
    this.body.updateMassProperties();
  }

  initGroundCheck() {
    // Create mesh for onGround collision check
    this.groundCheck = BABYLON.Mesh.CreateBox("mask", 2.5, this.scene);
    this.groundCheck.parent = this.mask;
    this.groundCheck.position.y = -3;
    this.groundCheck.scaling.y = 0.4;
  }

  checkGroundCheck() {
    // Check for ground
    if (this.groundCheck.intersectsMesh(this.game.ground, true)){
      this.mesh.material.diffuseColor = new BABYLON.Color3.Red();
      this.onGround = true;
    } else {
        this.onGround = false;
    }
  }

  update () {

    this.checkGroundCheck();

    if (this.moveBool) {
        this.move();
    }
    this.powers();
  }

  // use this to make xbox controller movement is smoove and doesn't go over the speed limit
  getScaleSpeed (movementVector, speed) {
      //console.log('movementvector strength:', movementVector.length());
      return speed * Math.min(1, movementVector.length());
  }

  move () {
    // Movement on ground
    // get normalized vector

    var movementVector = new BABYLON.Vector3(this.Input.AXIS_X,0,this.Input.AXIS_Y);
      //console.log('xbox move:', this.Input.AXIS_X, ', ', this.Input.AXIS_Y, ', scaleSpeed:', Math.min(1, movementVector.length()));
    var normalizedMovementVector = movementVector.clone().normalize();
    //console.log('scale speed:', this.getScaleSpeed(movementVector, this.speed));
    if (this.onGround) {
        movementVector = normalizedMovementVector.scale(this.getScaleSpeed(movementVector, this.speed));
    } else {
        movementVector = normalizedMovementVector.scale(this.getScaleSpeed(movementVector, this.airSpeed));
    }
    // movement
    // Player rotation
    this.mask.rotationQuaternion = BABYLON.Quaternion.RotationYawPitchRoll(Math.atan2(this.body.velocity.x, this.body.velocity.z), 0, 0);
    // Jump
    console.log('jump', this.jumpPressed);
    if (this.onGround && this.jumpPressed) {
        console.log("jump!");
        movementVector = movementVector.add(new BABYLON.Vector3(0,this.jumpStrength,0));
        this.mesh.material.diffuseColor = BABYLON.Color3.Blue();
    }
    // apply movement at the very end.
    console.log('ONGROUND:', this.onGround);
    this.mask.applyImpulse(movementVector, this.mask.position);
  }

  // Currently prioritizes the first power
  powers () {
    if (this.Input.ATTACK1) {
      this.useAttackPower1();
    } else if (this.Input.ATTACK2) {
      this.useAttackPower2();
    } else if (this.Input.ATTACK3) {
      this.useAttackPower3();
    } else if (this.Input.ATTACK4) {
      this.useAttackPower4();
    }
  }

  useAttackPower1 () {
      this.attackPower1.usePower();
  }

  useAttackPower2 () {
      this.attackPower2.usePower();
  }

  useAttackPower3 () {
      this.attackPower3.usePower();
  }

  useAttackPower4 () {
      this.attackPower4.usePower();
  }

  setPlayer(player) {
    (this._inputSubscriptions || {destroy: () => {}}).destroy();
    if (!player) {
      return;
    }
    this._inputSubscriptions = new EventSubscriptionContext(player.input)
      .on('end', () => this.setPlayer())
      .on('joychanged', joyVector => this.handleJoyChanged(joyVector))
      .on('buttondown', button => this.handleButtonDown(button))
      .on('buttonup', button => this.handleButtonUp(button))
    ;
  }

  handleJoyChanged(joyVector) {
    //console.log(joyVector);
    this.Input.AXIS_Y = joyVector.y;
    this.Input.AXIS_X = joyVector.x;
    //console.log(this.Input);
  }

  _handleButton(button, pressed) {
    switch (button) {
    case Buttons.A: this.Input.ATTACK1 = pressed; break;
    case Buttons.B: this.Input.ATTACK2 = pressed; break;
    case Buttons.X: this.Input.ATTACK3 = pressed; break;
    case Buttons.Y: this.Input.ATTACK4 = pressed; break;
    case Buttons.RB: // TODO: controllers do not yet know how to produce this.
      this.jumpPressed = pressed;
      break;
    }
  }

  handleButtonDown(button) {
    this._handleButton(button, true);
  }

  handleButtonUp(button) {
    this._handleButton(button, false);
  }
}
<|endoftext|>


<commit_before><commit_msg>updates demo bundle<commit_after><|endoftext|>


<commit_before><commit_msg>Update demo<commit_after><|endoftext|>