mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-11-30 10:56:53 -05:00
Adding some options to the game menu options tab.
This commit is contained in:
parent
65658dec78
commit
4dcc5bd8ee
7 changed files with 243 additions and 24 deletions
|
@ -463,9 +463,11 @@
|
|||
inventory_caption: "Equip your hero"
|
||||
choose_hero_caption: "Choose hero, language"
|
||||
save_load_caption: "... and view history"
|
||||
options_caption: "Music and other settings"
|
||||
options_caption: "Configure settings"
|
||||
guide_caption: "Docs and tips"
|
||||
multiplayer_caption: "Play with friends!"
|
||||
autorun: "Autorun"
|
||||
autorun_description: "Control automatic code execution."
|
||||
|
||||
save_load:
|
||||
granularity_saved_games: "Saved"
|
||||
|
|
|
@ -1,5 +1,14 @@
|
|||
#game-menu-modal
|
||||
.modal-dialog
|
||||
margin-top: 0
|
||||
|
||||
.nav-tabs
|
||||
h2
|
||||
margin: 0
|
||||
|
||||
.tab-pane
|
||||
h3:first-child
|
||||
margin-top: 0
|
||||
|
||||
// http://stackoverflow.com/questions/18432577/stacked-tabs-in-bootstrap-3
|
||||
.tabs-left
|
||||
|
@ -25,7 +34,7 @@
|
|||
> a
|
||||
min-width: 74px
|
||||
margin-right: 0
|
||||
margin-bottom: 3px
|
||||
margin-bottom: 0
|
||||
|
||||
.tabs-left > .nav-tabs
|
||||
border-right: 1px solid #ddd
|
||||
|
|
|
@ -1,3 +1,67 @@
|
|||
@import "app/styles/bootstrap/variables"
|
||||
|
||||
#options-view
|
||||
h3
|
||||
text-decoration: underline
|
||||
.select-group
|
||||
display: block
|
||||
min-height: 20px
|
||||
margin-top: 10px
|
||||
margin-bottom: 10px
|
||||
padding-left: 20px
|
||||
vertical-align: middle
|
||||
|
||||
label
|
||||
font-weight: normal
|
||||
margin-right: 20px
|
||||
margin-bottom: 0
|
||||
|
||||
.form-group.radio-inline
|
||||
input
|
||||
margin-left: 0px
|
||||
margin-right: 5px
|
||||
|
||||
.radio-inline-parent-label
|
||||
padding-left: 0
|
||||
|
||||
#player-avatar-container
|
||||
position: relative
|
||||
margin: 0px 0px 15px 15px
|
||||
width: 230px
|
||||
max-height: 230px
|
||||
border-radius: 6px
|
||||
|
||||
img.profile-photo
|
||||
width: 100%
|
||||
|
||||
&.saving
|
||||
opacity: 0.5
|
||||
|
||||
.profile-caption
|
||||
background-color: rgba(0, 0, 0, 0.5)
|
||||
color: white
|
||||
border-bottom-right-radius: 6px
|
||||
border-bottom-left-radius: 6px
|
||||
position: absolute
|
||||
width: 100%
|
||||
bottom: 0px
|
||||
left: 0px
|
||||
text-align: center
|
||||
border: 0
|
||||
font-size: 18px
|
||||
|
||||
.editable-icon
|
||||
display: block
|
||||
position: absolute
|
||||
right: 5px
|
||||
top: 5px
|
||||
font-size: 20px
|
||||
color: $blue
|
||||
opacity: 0.5
|
||||
|
||||
&:hover
|
||||
cursor: pointer
|
||||
box-shadow: 0px 0px 2px 1px $blue
|
||||
|
||||
.editable-icon
|
||||
opacity: 1.0
|
||||
cursor: pointer
|
||||
|
||||
|
|
|
@ -1,15 +1,58 @@
|
|||
h3 Stuff to put in there maybe
|
||||
ul
|
||||
li Show/Hide Grid (may destroy the grid)
|
||||
li Show/Hide FPS (may keep admin-only)
|
||||
li Player Name
|
||||
li Player Avatar (currently just in settings, but it would be interesting to feature it in more places so that they’d actually start using it and increasing how much we can rely on it in social/multiplayer–and wherever it’s featured that’s not a tiny icon, we could let them change it)
|
||||
li Default programming language
|
||||
li Editor key bindings (default ACE, Emacs, Vim)
|
||||
li Live autocompletion
|
||||
li Show invisibles (visualize spaces/tabs)
|
||||
li Show indent guides (displays vertical lines to see indentation better)
|
||||
li Smart behaviors (autocompleting braces, brackets, and quotes)
|
||||
li Music on/off
|
||||
li Volume (assuming we’re also keeping volume next to play button in playback bar)
|
||||
li Autocast Delay
|
||||
#player-avatar-container(title="Click to change your avatar").pull-right
|
||||
if !me.get('photoURL')
|
||||
.editable-icon.glyphicon.glyphicon-pencil
|
||||
img.profile-photo(src=me.getPhotoURL(230))
|
||||
.form-group
|
||||
input#player-name.profile-caption(name="playerName", type="text", value=me.get('name') || 'Anoner')
|
||||
|
||||
.form
|
||||
h3(data-i18n="game_menu.general_options") General Options
|
||||
|
||||
.form-group.checkbox
|
||||
label(for="option-music")
|
||||
input#option-music(name="option-music", type="checkbox", checked=music)
|
||||
span(data-i18n="game_menu.music") Music
|
||||
span.help-block(data-i18n="game_menu.music_description") Turn background music on/off.
|
||||
|
||||
.form-group.select-group
|
||||
label.control-label(for="option-autorun-delay", data-i18n="game_menu.autorun") Autorun
|
||||
select#option-autorun-delay(name="autorunDelay")
|
||||
option(value=1000, selected=(autorunDelay === 1000), data-i18n="common.delay_1_sec") 1 second
|
||||
option(value=3000, selected=(autorunDelay === 3000), data-i18n="common.delay_3_sec") 3 seconds
|
||||
option(value=5000, selected=(autorunDelay === 5000), data-i18n="common.delay_5_sec") 5 seconds
|
||||
option(value=90019001, selected=(autorunDelay === 90019001), data-i18n="common.manual") Manual
|
||||
span.help-block(data-i18n="game_menu.autorun_description") Control automatic code execution.
|
||||
|
||||
h3(data-i18n="game_menu.editor_config_title") Editor Configuration
|
||||
|
||||
.form-group.select-group
|
||||
label.control-label(for="option-key-bindings", data-i18n="game_menu.editor_config_keybindings_label") Key Bindings
|
||||
select#option-key-bindings(name="keyBindings")
|
||||
option(value="default", selected=(aceConfig.keyBindings === "default"), data-i18n="game_menu.editor_config_keybindings_default") Default (Ace)
|
||||
option(value="vim", selected=(aceConfig.keyBindings === "vim")) Vim
|
||||
option(value="emacs", selected=(aceConfig.keyBindings === "emacs")) Emacs
|
||||
span.help-block(data-i18n="game_menu.editor_config_keybindings_description") Adds additional shortcuts known from the common editors.
|
||||
|
||||
.form-group.checkbox
|
||||
label(for="option-live-completion")
|
||||
input#option-live-completion(name="liveCompletion", type="checkbox", checked=aceConfig.liveCompletion)
|
||||
span(data-i18n="game_menu.editor_config_livecompletion_label") Live Autocompletion
|
||||
span.help-block(data-i18n="game_menu.editor_config_livecompletion_description") Displays autocomplete suggestions while typing.
|
||||
|
||||
.form-group.checkbox
|
||||
label(for="option-invisibles")
|
||||
input#option-invisibles(name="invisibles", type="checkbox", checked=aceConfig.invisibles)
|
||||
span(data-i18n="game_menu.editor_config_invisibles_label") Show Invisibles
|
||||
span.help-block(data-i18n="game_menu.editor_config_invisibles_description") Displays invisibles such as spaces or tabs.
|
||||
|
||||
.form-group.checkbox
|
||||
label(for="option-indent-guides")
|
||||
input#option-indent-guides(name="indentGuides", type="checkbox", checked=aceConfig.indentGuides)
|
||||
span(data-i18n="game_menu.editor_config_indentguides_label") Show Indent Guides
|
||||
span.help-block(data-i18n="game_menu.editor_config_indentguides_description") Displays vertical lines to see indentation better.
|
||||
|
||||
.form-group.checkbox
|
||||
label(for="option-behaviors")
|
||||
input#option-behaviors(name="behaviors", type="checkbox", checked=aceConfig.behaviors)
|
||||
span(data-i18n="game_menu.editor_config_behaviors_label") Smart Behaviors
|
||||
span.help-block(data-i18n="game_menu.editor_config_behaviors_description") Autocompletes brackets, braces, and quotes.
|
||||
|
|
|
@ -11,7 +11,7 @@ submenuViews = [
|
|||
|
||||
module.exports = class GameMenuModal extends ModalView
|
||||
template: template
|
||||
modalWidthPercent: 80
|
||||
modalWidthPercent: 95
|
||||
id: 'game-menu-modal'
|
||||
|
||||
events:
|
||||
|
@ -25,3 +25,7 @@ module.exports = class GameMenuModal extends ModalView
|
|||
super()
|
||||
@insertSubView new submenuView @options for submenuView in submenuViews
|
||||
@subviews.inventory_view.$el.addClass 'active'
|
||||
|
||||
onHidden: ->
|
||||
subview.onHidden?() for subviewKey, subview of @subviews
|
||||
me.patch()
|
||||
|
|
|
@ -2,15 +2,113 @@ CocoView = require 'views/kinds/CocoView'
|
|||
template = require 'templates/game-menu/options-view'
|
||||
{me} = require 'lib/auth'
|
||||
ThangType = require 'models/ThangType'
|
||||
User = require 'models/User'
|
||||
forms = require 'lib/forms'
|
||||
|
||||
module.exports = class OptionsView extends CocoView
|
||||
id: 'options-view'
|
||||
className: 'tab-pane'
|
||||
template: template
|
||||
aceConfig: {}
|
||||
defaultConfig:
|
||||
language: 'javascript'
|
||||
keyBindings: 'default'
|
||||
invisibles: false
|
||||
indentGuides: false
|
||||
behaviors: false
|
||||
liveCompletion: true
|
||||
|
||||
getRenderData: (context={}) ->
|
||||
context = super(context)
|
||||
context
|
||||
events:
|
||||
'change #option-music': 'updateMusic'
|
||||
'change #option-autorun-delay': 'updateAutorun'
|
||||
'change #option-key-bindings': 'updateInvisibles'
|
||||
'change #option-key-bindings': 'updateKeyBindings'
|
||||
'change #option-indent-guides': 'updateIndentGuides'
|
||||
'change #option-behaviors': 'updateBehaviors'
|
||||
'change #option-live-completion': 'updateLiveCompletion'
|
||||
'click .profile-photo': 'onEditProfilePhoto'
|
||||
'click .editable-icon': 'onEditProfilePhoto'
|
||||
'keyup #player-name': -> @trigger 'nameChanged'
|
||||
|
||||
constructor: (options) ->
|
||||
@uploadFilePath = "db/user/#{me.id}"
|
||||
@onNameChange = _.debounce(@checkNameExists, 500)
|
||||
@on 'nameChanged', @onNameChange
|
||||
@playerName = me.get 'name'
|
||||
super options
|
||||
|
||||
getRenderData: (c={}) ->
|
||||
c = super(c)
|
||||
@aceConfig = _.cloneDeep me.get('aceConfig') ? {}
|
||||
@aceConfig = _.defaults @aceConfig, @defaultConfig
|
||||
c.aceConfig = @aceConfig
|
||||
c.music = me.get('music')
|
||||
c.autorunDelay = me.get('autocastDelay') ? 5000
|
||||
c
|
||||
|
||||
afterRender: ->
|
||||
super()
|
||||
|
||||
onHidden: ->
|
||||
if @playerName and @playerName isnt me.get('name')
|
||||
me.set 'name', @playerName
|
||||
@aceConfig.invisibles = @$el.find('#option-invisibles').prop('checked')
|
||||
@aceConfig.keyBindings = @$el.find('#option-key-bindings').val()
|
||||
@aceConfig.indentGuides = @$el.find('#option-indent-guides').prop('checked')
|
||||
@aceConfig.behaviors = @$el.find('#option-behaviors').prop('checked')
|
||||
@aceConfig.liveCompletion = @$el.find('#option-live-completion').prop('checked')
|
||||
me.set 'aceConfig', @aceConfig
|
||||
Backbone.Mediator.publish 'tome:change-config'
|
||||
|
||||
updateMusic: ->
|
||||
me.set 'music', @$el.find('#option-music').prop('checked')
|
||||
|
||||
updateAutorun: ->
|
||||
me.set 'autocastDelay', parseInt(@$el.find('#option-autorun-delay').val())
|
||||
|
||||
updateInvisibles: ->
|
||||
@aceConfig.invisibles = @$el.find('#option-invisibles').prop('checked')
|
||||
|
||||
updateKeyBindings: ->
|
||||
@aceConfig.keyBindings = @$el.find('#option-key-bindings').val()
|
||||
|
||||
updateIndentGuides: ->
|
||||
@aceConfig.indentGuides = @$el.find('#option-indent-guides').prop('checked')
|
||||
|
||||
updateBehaviors: ->
|
||||
@aceConfig.behaviors = @$el.find('#option-behaviors').prop('checked')
|
||||
|
||||
updateLiveCompletion: ->
|
||||
@aceConfig.liveCompletion = @$el.find('#option-live-completion').prop('checked')
|
||||
|
||||
checkNameExists: =>
|
||||
forms.clearFormAlerts(@$el)
|
||||
name = $('#player-name').val()
|
||||
User.getUnconflictedName name, (newName) =>
|
||||
forms.clearFormAlerts(@$el)
|
||||
if name isnt newName
|
||||
forms.setErrorToProperty @$el, 'playerName', 'This name is already taken so you won\'t be able to keep it.', true
|
||||
else
|
||||
@playerName = newName
|
||||
|
||||
onEditProfilePhoto: (e) ->
|
||||
photoContainer = @$el.find('.profile-photo')
|
||||
onSaving = =>
|
||||
photoContainer.addClass('saving')
|
||||
onSaved = (uploadingPath) =>
|
||||
me.set('photoURL', uploadingPath)
|
||||
photoContainer.removeClass('saving').attr('src', me.getPhotoURL(photoContainer.width()))
|
||||
filepicker.pick {mimetypes: 'image/*'}, @onImageChosen(onSaving, onSaved)
|
||||
|
||||
formatImagePostData: (inkBlob) ->
|
||||
url: inkBlob.url, filename: inkBlob.filename, mimetype: inkBlob.mimetype, path: @uploadFilePath, force: true
|
||||
|
||||
onImageChosen: (onSaving, onSaved) ->
|
||||
(inkBlob) =>
|
||||
onSaving()
|
||||
uploadingPath = [@uploadFilePath, inkBlob.filename].join('/')
|
||||
$.ajax '/file', type: 'POST', data: @formatImagePostData(inkBlob), success: @onImageUploaded(onSaved, uploadingPath)
|
||||
|
||||
onImageUploaded: (onSaved, uploadingPath) ->
|
||||
(e) =>
|
||||
onSaved uploadingPath
|
||||
|
|
|
@ -3,7 +3,6 @@ request = require 'request'
|
|||
log = require 'winston'
|
||||
|
||||
DELIGHTED_EMAIL_DELAY = 1 * 86400 # in seconds
|
||||
DELIGHTED_EMAIL_DELAY = 10
|
||||
|
||||
module.exports.addDelightedUser = addDelightedUser = (user) ->
|
||||
return unless key = config.mail.delightedAPIKey
|
||||
|
|
Loading…
Reference in a new issue