Merge pull request #269 from codecombat/master

Merged progress into production
This commit is contained in:
Michael Schmatz 2014-01-21 19:17:36 -08:00
commit c21f304954
21 changed files with 532 additions and 165 deletions

View file

@ -8,6 +8,8 @@ CocoView = require 'views/kinds/CocoView'
preventBackspace = (event) ->
if event.keyCode is 8 and not elementAcceptsKeystrokes(event.srcElement or event.target)
event.preventDefault()
else if (key.ctrl or key.command) and not key.alt and event.keyCode in [219, 221] # prevent Ctrl/Cmd + [ / ]
event.preventDefault()
elementAcceptsKeystrokes = (el) ->
# http://stackoverflow.com/questions/1495219/how-can-i-prevent-the-backspace-key-from-navigating-back

View file

@ -152,7 +152,7 @@ class Angel
@ids[@lastID]
# https://github.com/codecombat/codecombat/issues/81 -- TODO: we need to wait for worker initialization first
infiniteLoopIntervalDuration: 15000 # check this often (must be more than the others added)
infiniteLoopIntervalDuration: 1500000 # check this often (must be more than the others added)
infiniteLoopTimeoutDuration: 1500 # wait this long when we check
abortTimeoutDuration: 500 # give in-process or dying workers this long to give up
constructor: (@god) ->

View file

@ -140,7 +140,7 @@ module.exports = class Mark extends CocoClass
worldZ = @sprite.thang.pos.z - @sprite.thang.depth / 2
@mark.alpha = 0.451 / Math.sqrt(worldZ / 2 + 1)
else
pos ?= @sprite.displayObject
pos ?= @sprite?.displayObject
@mark.x = pos.x
@mark.y = pos.y
if @name is 'highlight'

View file

@ -259,6 +259,6 @@ module.exports = class SpriteBoss extends CocoClass
target = thang?.target
targetPos = thang?.targetPos
targetPos = null if targetPos?.isZero?() # Null targetPos get serialized as (0, 0, 0)
@targetMark.toggle target or targetPos
@targetMark.setSprite if target then @sprites[target.id] else null
@targetMark.toggle @targetMark.sprite or targetPos
@targetMark.update if targetPos then @camera.worldToSurface targetPos else null

View file

@ -4,12 +4,12 @@ module.exports = nativeDescription: "Português europeu", englishDescription: "P
saving: "A guardar..."
sending: "A enviar..."
cancel: "Cancelar"
# save: "Save"
# delay_1_sec: "1 second"
# delay_3_sec: "3 seconds"
# delay_5_sec: "5 seconds"
# manual: "Manual"
# fork: "Fork"
save: "Save"
delay_1_sec: "1 segundo"
delay_3_sec: "3 segundos"
delay_5_sec: "5 segundos"
manual: "Manual"
fork: "Fork"
play: "Jogar"
modal:
@ -31,28 +31,28 @@ module.exports = nativeDescription: "Português europeu", englishDescription: "P
about: "Sobre"
contact: "Contacto"
twitter_follow: "Seguir"
# employers: "Employers"
employers: "Patrões"
# versions:
# save_version_title: "Save New Version"
# new_major_version: "New Major Version"
# cla_prefix: "To save changes, first you must agree to our"
# cla_url: "CLA"
# cla_suffix: "."
# cla_agree: "I AGREE"
versions:
save_version_title: "Guardar Nova Versão"
new_major_version: "Nova Versão Principal"
cla_prefix: "Para guardar as alterações, precisas concordar com o nosso"
cla_url: "CLA"
cla_suffix: "."
cla_agree: "EU CONCORDO"
login:
sign_up: "Criar conta"
log_in: "Iniciar sessão"
log_out: "Terminar sessão"
log_out: "Sair"
recover: "recuperar conta"
recover:
recover_account_title: "recuperar conta"
# send_password: "Send Recovery Password"
recover_account_title: "Recuperar conta"
send_password: "Recuperar password"
signup:
# create_account_title: "Create Account to Save Progress"
create_account_title: "Cria uma conta para guardar o teu progresso."
description: "É grátis. Só precisamos de umas coisas e fica tudo pronto:"
email_announcements: "Receber anúncios por e-mail"
coppa: "13+ ou não-EUA "
@ -101,9 +101,9 @@ module.exports = nativeDescription: "Português europeu", englishDescription: "P
learn_more: "Sabe mais sobre ser um Diplomata"
subscribe_as_diplomat: "Subscrever como Diplomata"
# wizard_settings:
# title: "Wizard Settings"
# customize_avatar: "Customize Your Avatar"
wizard_settings:
title: "Definições do Wizard"
customize_avatar: "Altera o teu Avatar"
account_settings:
title: "Definições da Conta"
@ -122,7 +122,7 @@ module.exports = nativeDescription: "Português europeu", englishDescription: "P
new_password_verify: "Verificar"
email_subscriptions: "Subscrições de E-mail"
email_announcements: "Anúncios"
# email_notifications_description: "Get periodic notifications for your account."
email_notifications_description: "Recebe notificações periódicas sobre a tua conta."
email_announcements_description: "Recebe e-mails sobre as últimas novidades e desenvolvimentos no CodeCombat."
contributor_emails: "E-mails para Contribuintes"
contribute_prefix: "Estamos à procura de pessoas para se juntarem a nós! Visita a "
@ -136,11 +136,11 @@ module.exports = nativeDescription: "Português europeu", englishDescription: "P
account_profile:
edit_settings: "Editar Definições"
profile_for_prefix: "Perfil de "
# profile_for_suffix: ""
profile_for_suffix: ""
profile: "Perfil"
user_not_found: "Nenhum utilizador encontrado. Verifica o URL?"
gravatar_not_found_mine: "Não conseguimos encontrar o teu perfil associado com:"
# gravatar_not_found_email_suffix: "."
gravatar_not_found_email_suffix: "."
gravatar_signup_prefix: "Regista-te no "
gravatar_signup_suffix: " para começares!"
gravatar_not_found_other: "Infelizmente, não existe nenhum perfil associado ao endereço de e-mail desta pessoa."
@ -164,95 +164,95 @@ module.exports = nativeDescription: "Português europeu", englishDescription: "P
reload_title: "Recarregar todo o código?"
reload_really: "Tens a certeza que queres recarregar este nível de volta ao início?"
reload_confirm: "Recarregar tudo"
# victory_title_prefix: ""
victory_title_prefix: ""
victory_title_suffix: " Concluído"
# victory_sign_up: "Sign Up to Save Progress"
# victory_sign_up_poke: "Want to save your code? Create a free account!"
# victory_rate_the_level: "Rate the level: "
# victory_play_next_level: "Play Next Level"
# victory_go_home: "Go Home"
# victory_review: "Tell us more!"
# victory_hour_of_code_done: "Are You Done?"
# victory_hour_of_code_done_yes: "Yes, I'm finished with my Hour of Code!"
# multiplayer_title: "Multiplayer Settings"
# multiplayer_link_description: "Give this link to anyone to have them join you."
# multiplayer_hint_label: "Hint:"
# multiplayer_hint: " Click the link to select all, then press ⌘-C or Ctrl-C to copy the link."
# multiplayer_coming_soon: "More multiplayer features to come!"
# guide_title: "Guide"
# tome_minion_spells: "Your Minions' Spells"
# tome_read_only_spells: "Read-Only Spells"
# tome_other_units: "Other Units"
victory_sign_up: "Cria uma conta para guardar o teu progresso"
victory_sign_up_poke: "Queres guardar o teu código? Cria uma conta grátis!"
victory_rate_the_level: "Classifica este nível: "
victory_play_next_level: "Jogar próximo nível"
victory_go_home: "Ir para a Home"
victory_review: "Conta-nos mais!"
victory_hour_of_code_done: "É tudo?"
victory_hour_of_code_done_yes: "Sim, a minha Hora de Código chegou ao fim!"
multiplayer_title: "Definições de Multiplayer"
multiplayer_link_description: "Dá este link a alguém para se juntar a ti."
multiplayer_hint_label: "Dica:"
multiplayer_hint: " Carrega no link para seleccionar tudp, depois pressiona ⌘-C ou Ctrl-C para copiar o link."
multiplayer_coming_soon: "Mais funcionalidades de multiplayer hão de vir!"
guide_title: "Guia"
tome_minion_spells: "Feitiços dos teus Minions"
tome_read_only_spells: "Feitiços Read-Only"
tome_other_units: "Outras Unidades"
# tome_cast_button_castable: "Cast"
# tome_cast_button_casting: "Casting"
# tome_cast_button_cast: "Spell Cast"
tome_cast_button_cast: "Lançar Feitiço"
# tome_autocast_delay: "Autocast Delay"
# tome_select_spell: "Select a Spell"
# tome_select_a_thang: "Select Someone for "
# tome_available_spells: "Available Spells"
# hud_continue: "Continue (press shift-space)"
# spell_saved: "Spell Saved"
tome_select_spell: "Escolhe um Feitiço"
tome_select_a_thang: "Escolhe Alguém para "
tome_available_spells: "Feitiços disponíveis"
hud_continue: "Continuar (pressiona shift-space)"
spell_saved: "Feitiço Guardado"
# admin:
# av_title: "Admin Views"
# av_entities_sub_title: "Entities"
# av_entities_users_url: "Users"
# av_entities_active_instances_url: "Active Instances"
# av_other_sub_title: "Other"
# av_other_debug_base_url: "Base (for debugging base.jade)"
# u_title: "User List"
# lg_title: "Latest Games"
admin:
av_title: "Visualizações de Admin"
av_entities_sub_title: "Entidades"
av_entities_users_url: "utilizadores"
av_entities_active_instances_url: "Activar Instancias"
av_other_sub_title: "Outro"
av_other_debug_base_url: "Base (para fazer debug base.jade)"
u_title: "Lista de Utilizadores"
lg_title: "Últimos Jogos"
# editor:
# main_title: "CodeCombat Editors"
# main_description: "Build your own levels, campaigns, units and educational content. We provide all the tools you need!"
# article_title: "Article Editor"
# article_description: "Write articles that give players overviews of programming concepts which can be used across a variety of levels and campaigns."
# thang_title: "Thang Editor"
# thang_description: "Build units, defining their default logic, graphics and audio. Currently only supports importing Flash exported vector graphics."
# level_title: "Level Editor"
# level_description: "Includes the tools for scripting, uploading audio, and constructing custom logic to create all sorts of levels. Everything we use ourselves!"
# security_notice: "Many major features in these editors are not currently enabled by default. As we improve the security of these systems, they will be made generally available. If you'd like to use these features sooner, "
# contact_us: "contact us!"
# hipchat_prefix: "You can also find us in our"
# hipchat_url: "HipChat room."
# level_some_options: "Some Options?"
# level_tab_thangs: "Thangs"
# level_tab_scripts: "Scripts"
# level_tab_settings: "Settings"
# level_tab_components: "Components"
# level_tab_systems: "Systems"
# level_tab_thangs_title: "Current Thangs"
# level_tab_thangs_conditions: "Starting Conditions"
# level_tab_thangs_add: "Add Thangs"
# level_settings_title: "Settings"
# level_component_tab_title: "Current Components"
# level_component_btn_new: "Create New Component"
# level_systems_tab_title: "Current Systems"
# level_systems_btn_new: "Create New System"
# level_systems_btn_add: "Add System"
# level_components_title: "Back to All Thangs"
# level_components_type: "Type"
# level_component_edit_title: "Edit Component"
# level_system_edit_title: "Edit System"
# create_system_title: "Create New System"
# new_component_title: "Create New Component"
# new_component_field_system: "System"
editor:
main_title: "Editores para CodeCombat"
main_description: "Constrói os teus níveis, campanhas, unidades e conteúdo educacional. Nós fornecemos todas as ferramentas que precisas!"
article_title: "Editor de Artigos"
article_description: "Escreve artigos que dêem aos jogadores uma visão geral dos conceitos de programação que podem ser usados nos mais diversos níveis e campanhas."
thang_title: "Editor de Thang"
thang_description: "Constrói unidades, definindo a sua logica, visual e audio por defeito. De momento só é suportado 'importing Flash exported vector graphics'."
level_title: "Editor de níveis"
level_description: "Inclui ferramentas para a criação de scripts, upload de áudio, e construção de lógica personalizada para criar todos os tipos de níveis. Tudo o que nós usamos!"
security_notice: "Muitas das principais funcionalidades nestes editores não estão activas por defeito. À medida que a segurança destes sistemas é melhorada, eles serão disponibilizados. Se quiseres utilizar estas uncionalidades mais cedo, "
contact_us: "contacta-nos!"
hipchat_prefix: "Podes encontrar-nos no nosso"
hipchat_url: "canal HipChat."
level_some_options: "Algumas opções?"
level_tab_thangs: "Thangs"
level_tab_scripts: "Scripts"
level_tab_settings: "Configurações"
level_tab_components: "Componentes"
level_tab_systems: "Sistemas"
level_tab_thangs_title: "Thangs atuais"
level_tab_thangs_conditions: "Condições iniciais"
level_tab_thangs_add: "Adiciona Thangs"
level_settings_title: "Configurações"
level_component_tab_title: "Componentes atuais"
level_component_btn_new: "Cria um novo Componente"
level_systems_tab_title: "Sistemas atuais"
level_systems_btn_new: "Cria um novo Sistema"
level_systems_btn_add: "Adiciona um Sistema"
level_components_title: "Voltar para Todos os Thangs"
level_components_type: "Tipo"
level_component_edit_title: "Editar Componente"
level_system_edit_title: "Editar Sistema"
create_system_title: "Criar novo Sistema"
new_component_title: "Criar novo Componente"
new_component_field_system: "Sistema"
# article:
# edit_btn_preview: "Preview"
# edit_article_title: "Edit Article"
article:
edit_btn_preview: "Visualizar"
edit_article_title: "Editar Artigo"
general:
# and: "and"
and: "e"
or: "ou"
name: "Nome"
# body: "Body"
# version: "Version"
# commit_msg: "Commit Message"
# version_history_for: "Version History for: "
# results: "Results"
# description: "Description"
body: "Corpo"
version: "Versão"
commit_msg: "Mensagem de Commit"
version_history_for: "Histórico de versões por: "
results: "Resultados"
description: "Descrição"
email: "E-mail"
message: "Mensagem"
@ -424,18 +424,18 @@ module.exports = nativeDescription: "Português europeu", englishDescription: "P
# translating_diplomats: "Our Translating Diplomats:"
# helpful_ambassadors: "Our Helpful Ambassadors:"
# classes:
# archmage_title: "Archmage"
# archmage_title_description: "(Coder)"
# artisan_title: "Artisan"
# artisan_title_description: "(Level Builder)"
# adventurer_title: "Adventurer"
# adventurer_title_description: "(Level Playtester)"
# scribe_title: "Scribe"
# scribe_title_description: "(Article Editor)"
# diplomat_title: "Diplomat"
# diplomat_title_description: "(Translator)"
# ambassador_title: "Ambassador"
# ambassador_title_description: "(Support)"
# counselor_title: "Counselor"
# counselor_title_description: "(Expert/Teacher)"
classes:
archmage_title: "Archmage"
archmage_title_description: "(Coder)"
artisan_title: "Artisan"
artisan_title_description: "(Construtor de Níveis)"
adventurer_title: "Adventurer"
adventurer_title_description: "(Play-tester de Níveis)"
scribe_title: "Scribe"
scribe_title_description: "(Editor de Artigos)"
diplomat_title: "Diplomat"
diplomat_title_description: "(Tradutor)"
ambassador_title: "Ambassador"
ambassador_title_description: "(Suporte)"
counselor_title: "Counselor"
counselor_title_description: "(Expert/ Professor)"

View file

@ -22,11 +22,41 @@
#thangs-treema
position: absolute
top: 40px
top: 80px
left: 0
right: 0
bottom: 0
overflow: scroll
&.hide-except-Unit
.treema-node
display: none
.treema-node.treema-Unit
display: block
&.hide-except-Doodad
.treema-node
display: none
.treema-node.treema-Doodad
display: block
&.hide-except-Floor
.treema-node
display: none
.treema-node.treema-Floor
display: block
&.hide-except-Wall
.treema-node
display: none
.treema-node.treema-Wall
display: block
&.hide-except-Misc
.treema-node
display: none
.treema-node.treema-Misc
display: block
.treema-children .treema-row *
cursor: pointer !important

View file

@ -30,11 +30,13 @@
color: white
#cast-button-view
display: none
.cast-button-group
position: absolute
// Bottom/right margins must appear to scroll to size of any paper gashes
top: 2%
right: 4%
top: 55px
left: 20px
z-index: 2
@include opacity(77)
.button-progress-overlay

View file

@ -32,10 +32,11 @@
.ace_editor
@include box-sizing(border-box)
margin-top: 40px
width: 100%
height: 90%
height: -webkit-calc(100% - 60px)
height: calc(100% - 60px)
height: 83%
height: -webkit-calc(100% - 60px - 40px)
height: calc(100% - 60px - 40px)
position: relative
background-color: transparent
line-height: 20px
@ -75,11 +76,10 @@
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2hpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYxIDY0LjE0MDk0OSwgMjAxMC8xMi8wNy0xMDo1NzowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDowMjgwMTE3NDA3MjA2ODExOEE2REU4Q0M1MTM1MkIxRiIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpBQjVEQUNDMzQ4RUIxMUUxOEVGRUUyNzFENDM3RDVFMCIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpBQjVEQUNDMjQ4RUIxMUUxOEVGRUUyNzFENDM3RDVFMCIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1LjEgTWFjaW50b3NoIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QTU1MjE3RDIzMTIwNjgxMThEQkI4NTlBMjQ1QTEwOTUiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MDI4MDExNzQwNzIwNjgxMThBNkRFOENDNTEzNTJCMUYiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7SazaGAAAAiElEQVR42mL8//8/AzUBEwOVweA3kAWboI2jCyhgDwBx4ZH9ey5Qy4UOQHweaHg/EAtQ08sFUIMDqBmGCkC8HmgoCCtQM1ICoK5toGYsg8KzHmjo+UGbDj8AcSMwORkSnQ7xgA3QtPmApISNBTyAGrSBGl6eAMSGxBhGyIVkZT3G0fKQYgAQYACL+C2ZM6PC7AAAAABJRU5ErkJggg==)
background-position: 0px center
//.user-code-problem
//.ace_scroller
// background-color: #470000
.ace_marker-layer
.ace_bracket
// Override faint gray
border-color: #0FF
border-color: #8FF
.ace_identifier
background-color: rgba(255, 128, 128, 0.15)

View file

@ -0,0 +1,10 @@
@import "../../../bootstrap/mixins"
.spell-debug-view
position: absolute
z-index: 9001
max-width: 400px
padding: 10px
background: transparent url(/images/level/popover_background.png)
background-size: 100% 100%

View file

@ -0,0 +1,54 @@
@import "../../../bootstrap/mixins"
.spell-toolbar-view
position: absolute
z-index: 2
top: 2px
left: 5px
box-sizing: border-box
padding-left: 150px
height: 36px
width: 95%
width: -webkit-calc(95% - 5px)
width: calc(95% - 5px)
background-color: rgba(100, 45, 210, 0.05)
.spell-progress
position: relative
height: 100%
width: 50%
display: inline-block
.progress
position: absolute
left: 0px
top: 8px
bottom: 0px
width: 100%
cursor: pointer
overflow: visible
.bar
@include transition(width .0s linear)
position: relative
pointer-events: none
background-color: #67A4C8
width: 50%
.scrubber-handle
position: absolute
pointer-events: none
right: -16px
top: -7px
background: transparent url(/images/level/playback_thumb.png)
width: 32px
height: 32px
.btn-group
// I don't know, I can figure this out for real later
margin: -26px 0 0 18px
.metrics
display: inline-block
margin: -30px 0 0 10px
vertical-align: middle

View file

@ -1,5 +1,17 @@
.thangs-container.thangs-column
h3(data-i18n="editor.level_tab_thangs_title") Current Thangs
.btn-group(data-toggle="buttons-radio")#extant-thangs-filter
button.btn.btn-primary All
button.btn.btn-primary(value="Unit")
i.icon-user
button.btn.btn-primary(value="Wall")
i.icon-home
button.btn.btn-primary(value="Floor")
i.icon-globe
button.btn.btn-primary(value="Doodad")
i.icon-leaf
button.btn.btn-primary(value="Misc")
i.icon-question-sign
#thangs-treema(title="Double click to configure a thang")
.world-container.thangs-column

View file

@ -1,4 +1,4 @@
button.btn.btn-mini.btn-inverse#play-button.playing(title="Alt-P: Toggle level play/pause")
button.btn.btn-mini.btn-inverse#play-button.playing(title="Ctrl/Cmd + P: Toggle level play/pause")
i.icon-play.icon-white.big
i.icon-pause.icon-white.big
i.icon-repeat.icon-white.big
@ -16,19 +16,19 @@ button.btn.btn-mini.btn-inverse#music-button(title="Toggle Music")
.scrubber-handle
.btn-group.dropup#playback-settings
button.btn.btn-mini.btn-inverse#zoom-in-button
button.btn.btn-mini.btn-inverse#zoom-in-button(title="Zoom In (or scroll down)")
i.icon-zoom-in.icon-white
button.btn.btn-mini.btn-inverse#zoom-out-button
button.btn.btn-mini.btn-inverse#zoom-out-button(title="Zoom Out (or scroll up)")
i.icon-zoom-out.icon-white
button.btn.btn-mini.btn-inverse.dropdown-toggle(data-toggle="dropdown")#settings-button
i.icon-cog.icon-white.big
ul.dropdown-menu
if me.get('name') == "Nick"
li(title="\\: Toggle debug display").selectable#debug-toggle
li(title="Ctrl/Cmd + \\: Toggle debug display").selectable#debug-toggle
i.icon-globe
| Debug Mode
i.icon-ok.hide
li(title="G: Toggle grid display").selectable#grid-toggle
li(title="Ctrl/Cmd + G: Toggle grid display").selectable#grid-toggle
i.icon-th
span(data-i18n="play_level.grid") Grid
i.icon-ok.hide

View file

@ -0,0 +1,2 @@
pre
code

View file

@ -0,0 +1,22 @@
.spell-progress
.progress
.bar
.scrubber-handle
.btn-group
button.btn.btn-mini.btn-inverse.banner.step-backward(title="Ctrl/Cmd + Alt + [: Step Backward")
i.icon-arrow-left.icon-white
button.btn.btn-mini.btn-inverse.banner.step-forward(title="Ctrl/Cmd + Alt + ]: Step Forward")
i.icon-arrow-right.icon-white
.metrics
code.statements-metric
span.metric.statement-index
| /
span.metric.statements-executed
span.metric.statements-executed-total
|
code.calls-metric
span.metric.call-index
| /
span.metric.calls-executed

View file

@ -43,10 +43,21 @@ module.exports = class ThangsTabView extends View
'sprite:mouse-up': 'onSpriteMouseUp'
'sprite:double-clicked': 'onSpriteDoubleClicked'
'surface:stage-mouse-down': 'onStageMouseDown'
events:
'click #extant-thangs-filter button': 'onFilterExtantThangs'
shortcuts:
'esc': -> @selectAddThang()
onFilterExtantThangs: (e) ->
button = $(e.target).closest('button')
button.button('toggle')
val = button.val()
@thangsTreema.$el.removeClass(@lastHideClass) if @lastHideClass
@thangsTreema.$el.addClass(@lastHideClass = "hide-except-#{val}") if val
constructor: (options) ->
super options
@world = options.world
@ -87,12 +98,20 @@ module.exports = class ThangsTabView extends View
return if @startsLoading
super()
$('.tab-content').click @selectAddThang
$('#thangs-list').bind 'mousewheel', @preventBodyScrollingInThangList
@$el.find('#extant-thangs-filter button:first').button('toggle')
# TODO: move these into the shortcuts list
key 'left', _.bind @moveAddThangSelection, @, -1
key 'right', _.bind @moveAddThangSelection, @, 1
key 'delete, del, backspace', @deleteSelectedExtantThang
key 'f', => Backbone.Mediator.publish('level-set-debug', debug: not @surface.debug)
key 'g', => Backbone.Mediator.publish('level-set-grid', grid: not @surface.gridShowing())
preventBodyScrollingInThangList: (e) ->
@scrollTop += (if e.deltaY < 0 then 1 else -1) * 30
e.preventDefault()
onLevelLoaded: (e) ->
@level = e.level
return if @startsLoading
@ -188,9 +207,12 @@ module.exports = class ThangsTabView extends View
else if @addThangSprite
# We clicked on the background when we had an add Thang selected, so add it
@addThang @addThangType, @addThangSprite.thang.pos
else
# We clicked on the background, so deselect anything selected
@thangsTreema.deselectAll()
# Commented out this bit so the extant thangs treema editor can select invisible thangs like arrows.
# Couldn't spot any bugs... But if there are any, better come up with a better solution.
# else
# # We clicked on the background, so deselect anything selected
# @thangsTreema.deselectAll()
selectAddThang: (e) =>
if e then target = $(e.target) else target = @$el.find('.add-thangs-palette') # pretend to click on background if no event
@ -370,6 +392,7 @@ class ThangNode extends TreemaObjectNode
valueClass: 'treema-thang'
collection: false
@thangNameMap: {}
@thangKindMap: {}
buildValueForDisplay: (valEl) ->
pos = _.find(@data.components, (c) -> c.config?.pos?)?.config.pos # TODO: hack
s = "#{@data.thangType}"
@ -377,6 +400,9 @@ class ThangNode extends TreemaObjectNode
unless name = ThangNode.thangNameMap[s]
thangType = _.find @settings.supermodel.getModels(ThangType), (m) -> m.get('original') is s
name = ThangNode.thangNameMap[s] = thangType.get 'name'
ThangNode.thangKindMap[s] = thangType.get 'kind'
kind = ThangNode.thangKindMap[s]
@$el.addClass "treema-#{kind}"
s = name
s += " - " + @data.id if @data.id isnt s
if pos

View file

@ -24,7 +24,6 @@ module.exports = class CastButtonView extends View
context.castShortcutVerbose = @castShortcutVerbose
context
afterRender: ->
super()
# TODO: use a User setting instead of localStorage

View file

@ -64,7 +64,11 @@ module.exports = class Spell
functionParameters: @parameters
yieldConditionally: thang.plan?
requiresThis: thang.requiresThis
if @name is 'chooseAction' or not (me.team in @permissions.readwrite) or thang.id is 'Thoktar' # Gridmancer can't handle it
includeFlow: true
#callIndex: 0
#timelessVariables: ['i']
#statementIndex: 9001
if not (me.team in @permissions.readwrite)# or @name is 'chooseAction' or thang.id is 'Thoktar' # Gridmancer can't handle it
#console.log "Turning off includeFlow for", @spellKey
aetherOptions.includeFlow = false
aether = new Aether aetherOptions

View file

@ -0,0 +1,63 @@
View = require 'views/kinds/CocoView'
template = require 'templates/play/level/tome/spell_debug'
Range = ace.require("ace/range").Range
module.exports = class DebugView extends View
className: 'spell-debug-view'
template: template
subscriptions: {}
events: {}
constructor: (options) ->
super options
@ace = options.ace
@variableStates = {}
afterRender: ->
super()
@ace.on "mousemove", @onMouseMove
#@ace.on "click", onClick # same ACE API as mousemove
setVariableStates: (@variableStates) ->
@update()
onMouseMove: (e) =>
pos = e.getDocumentPosition()
column = pos.column
until column < 0
if token = e.editor.session.getTokenAt pos.row, column
break if token.type is 'identifier'
column = token.start - 1
else
--column
if token?.type is 'identifier' and token.value of @variableStates
@variable = token.value
@pos = {left: e.domEvent.offsetX + 50, top: e.domEvent.offsetY + 50}
@markerRange = new Range pos.row, token.start, pos.row, token.start + token.value.length
else
@variable = @markerRange = null
@update()
onMouseOut: (e) =>
@variable = @markerRange = null
@update()
update: ->
if @variable
value = @variableStates[@variable]
@$el.find("code").text "#{@variable}: #{value}"
@$el.show().css(@pos)
else
@$el.hide()
@updateMarker()
updateMarker: ->
if @marker
@ace.getSession().removeMarker @marker
@marker = null
if @markerRange
@marker = @ace.getSession().addMarker @markerRange, "ace_bracket", "text"
destroy: ->
super()
@ace?.removeEventListener "mousemove", @onMouseMove

View file

@ -0,0 +1,94 @@
View = require 'views/kinds/CocoView'
template = require 'templates/play/level/tome/spell_toolbar'
module.exports = class SpellToolbarView extends View
className: 'spell-toolbar-view'
template: template
subscriptions:
'spell-step-backward': 'onStepBackward'
'spell-step-forward': 'onStepForward'
events:
'mousemove .progress': 'onProgressHover'
'mouseout .progress': 'onProgressMouseOut'
'click .step-backward': 'onStepBackward'
'click .step-forward': 'onStepForward'
constructor: (options) ->
super options
@ace = options.ace
afterRender: ->
super()
setStatementIndex: (statementIndex) ->
return unless total = @callState?.statementsExecuted
@statementIndex = Math.min(total - 1, Math.max(0, statementIndex))
@statementRatio = @statementIndex / (total - 1)
@statementTime = @callState.statements[@statementIndex].userInfo.time
@$el.find('.bar').css('width', 100 * @statementRatio + '%')
Backbone.Mediator.publish 'tome:spell-statement-index-updated', statementIndex: @statementIndex, ace: @ace
@$el.find('.step-backward').prop('disabled', @statementIndex is 0)
@$el.find('.step-forward').prop('disabled', @statementIndex is total - 1)
@updateMetrics()
updateMetrics: ->
statementsExecuted = @callState.statementsExecuted
$metrics = @$el.find('.metrics')
if @metrics.callsExecuted > 1
$metrics.find('.call-index').text @callIndex + 1
$metrics.find('.calls-executed').text @metrics.callsExecuted
$metrics.find('.calls-metric').show().attr('title', "Method call #{@callIndex + 1} of #{@metrics.callsExecuted} calls")
else
$metrics.find('.calls-metric').hide()
if @metrics.statementsExecuted
$metrics.find('.statement-index').text @statementIndex + 1
$metrics.find('.statements-executed').text statementsExecuted
if @metrics.statementsExecuted > statementsExecuted
$metrics.find('.statements-executed-total').text " (#{@metrics.statementsExecuted})"
titleSuffix = " (#{@metrics.statementsExecuted} statements total)"
else
$metrics.find('.statements-executed-total').text ""
titleSuffix = ""
$metrics.find('.statements-metric').show().attr('title', "Statement #{@statementIndex + 1} of #{statementsExecuted} this call#{titleSuffix}")
else
$metrics.find('.statements-metric').hide()
setStatementRatio: (ratio) ->
return unless total = @callState?.statementsExecuted
@setStatementIndex Math.floor ratio * total
onProgressHover: (e) ->
@setStatementRatio e.offsetX / @$el.find('.progress').width()
@updateTime()
@maintainIndexHover = true
onProgressMouseOut: (e) ->
@maintainIndexHover = false
onStepBackward: (e) -> @step -1
onStepForward: (e) -> @step 1
step: (delta) ->
lastTime = @statementTime
@setStatementIndex @statementIndex + delta
@updateTime() if @statementIndex isnt lastTime
updateTime: ->
@maintainIndexScrub = true
clearTimeout @maintainIndexScrubTimeout if @maintainIndexScrubTimeout
@maintainIndexScrubTimeout = _.delay (=> @maintainIndexScrub = false), 500
Backbone.Mediator.publish 'level-set-time', time: @statementTime, scrubDuration: 500
setCallState: (callState, statementIndex, @callIndex, @metrics) ->
return if callState is @callState and statementIndex is @statementIndex
return unless @callState = callState
if not @maintainIndexHover and not @maintainIndexScrub and statementIndex? and callState.statements[statementIndex].userInfo.time isnt @statementTime
@setStatementIndex statementIndex
else
@setStatementRatio @statementRatio
# Not sure yet whether it's better to maintain @statementIndex or @statementRatio
#else if @statementRatio is 1 or not @statementIndex?
# @setStatementRatio 1
#else
# @setStatementIndex @statementIndex

View file

@ -4,6 +4,8 @@ template = require 'templates/play/level/tome/spell'
filters = require 'lib/image_filter'
Range = ace.require("ace/range").Range
Problem = require './problem'
SpellDebugView = require './spell_debug_view'
SpellToolbarView = require './spell_toolbar_view'
module.exports = class SpellView extends View
id: 'spell-view'
@ -25,9 +27,10 @@ module.exports = class SpellView extends View
'level:session-will-save': 'onSessionWillSave'
'modal-closed': 'focus'
'focus-editor': 'focus'
'tome:spell-statement-index-updated': 'onStatementIndexUpdated'
events:
'click .ace': -> console.log 'clicked ace', @
'mouseout': 'onMouseOut'
constructor: (options) ->
super options
@ -48,6 +51,7 @@ module.exports = class SpellView extends View
else
# needs to happen after the code generating this view is complete
setTimeout @onLoaded, 1
@createDebugView()
createACE: ->
# Test themes and settings here: http://ace.ajax.org/build/kitchen-sink.html
@ -86,24 +90,30 @@ module.exports = class SpellView extends View
name: 'end-all-scripts'
bindKey: {win: 'Escape', mac: 'Escape'}
exec: -> Backbone.Mediator.publish 'level:escape-pressed'
# TODO: These don't work on, for example, Danish keyboards. Figure out a more universal solution.
# @ace.commands.addCommand
# name: 'toggle-grid'
# bindKey: {win: 'Alt-G', mac: 'Alt-G'}
# exec: -> Backbone.Mediator.publish 'level-toggle-grid'
# @ace.commands.addCommand
# name: 'toggle-debug'
# bindKey: {win: 'Alt-\\', mac: 'Alt-\\'}
# exec: -> Backbone.Mediator.publish 'level-toggle-debug'
# @ace.commands.addCommand
# name: 'level-scrub-forward'
# bindKey: {win: 'Alt-]', mac: 'Alt-]'}
# exec: -> Backbone.Mediator.publish 'level-scrub-forward'
# @ace.commands.addCommand
# name: 'level-scrub-back'
# bindKey: {win: 'Alt-[', mac: 'Alt-['}
# exec: -> Backbone.Mediator.publish 'level-scrub-back'
@ace.commands.addCommand
name: 'toggle-grid'
bindKey: {win: 'Ctrl-G', mac: 'Command-G|Ctrl-G'}
exec: -> Backbone.Mediator.publish 'level-toggle-grid'
@ace.commands.addCommand
name: 'toggle-debug'
bindKey: {win: 'Ctrl-\\', mac: 'Command-\\|Ctrl-\\'}
exec: -> Backbone.Mediator.publish 'level-toggle-debug'
@ace.commands.addCommand
name: 'level-scrub-forward'
bindKey: {win: 'Ctrl-]', mac: 'Command-]|Ctrl-]'}
exec: -> Backbone.Mediator.publish 'level-scrub-forward'
@ace.commands.addCommand
name: 'level-scrub-back'
bindKey: {win: 'Ctrl-[', mac: 'Command-[|Ctrl-]'}
exec: -> Backbone.Mediator.publish 'level-scrub-back'
@ace.commands.addCommand
name: 'spell-step-forward'
bindKey: {win: 'Ctrl-Alt-]', mac: 'Command-Alt-]|Ctrl-Alt-]'}
exec: -> Backbone.Mediator.publish 'spell-step-forward'
@ace.commands.addCommand
name: 'spell-step-backward'
bindKey: {win: 'Ctrl-Alt-[', mac: 'Command-Alt-[|Ctrl-Alt-]'}
exec: -> Backbone.Mediator.publish 'spell-step-backward'
fillACE: ->
@ace.setValue @spell.source
@ -145,6 +155,17 @@ module.exports = class SpellView extends View
Backbone.Mediator.publish 'tome:spell-loaded', spell: @spell
@eventsSuppressed = false # Now that the initial change is in, we can start running any changed code
createDebugView: ->
@debugView = new SpellDebugView ace: @ace
@$el.append @debugView.render().$el.hide()
createToolbarView: ->
@toolbarView = new SpellToolbarView ace: @ace
@$el.prepend @toolbarView.render().$el
onMouseOut: (e) ->
@debugView.onMouseOut e
getSource: ->
@ace.getValue() # could also do @firepad.getText()
@ -368,22 +389,33 @@ module.exports = class SpellView extends View
@thang = e.selectedThang # update our thang to the current version
@highlightCurrentLine()
onStatementIndexUpdated: (e) ->
return unless e.ace is @ace
@highlightCurrentLine()
highlightCurrentLine: (flow) =>
# TODO: move this whole thing into SpellDebugView or somewhere?
flow ?= @spellThang?.castAether?.flow
return unless flow
executed = []
matched = false
for callState, callNumber in flow.states or []
states = flow.states ? []
currentCallIndex = null
for callState, callNumber in states
if not currentCallIndex? and callState.userInfo?.time > @thang.world.age
currentCallIndex = callNumber - 1
if matched
executed.pop()
break
executed.push []
for state, statementNumber in callState
for state, statementNumber in callState.statements
if state.userInfo?.time > @thang.world.age
matched = true
break
_.last(executed).push state
#state.executing = true if state.userInfo?.time is @thang.world.age # no work
currentCallIndex ?= callNumber - 1
#console.log "got call index", currentCallIndex, "for time", @thang.world.age, "out of", states.length
# TODO: don't redo the markers if they haven't actually changed
text = @aceDoc.getValue()
@ -397,11 +429,20 @@ module.exports = class SpellView extends View
markerRange.end.detach()
@aceSession.removeMarker markerRange.id
@markerRanges = []
@debugView.setVariableStates {}
@aceSession.removeGutterDecoration row, 'executing' for row in [0 ... @aceSession.getLength()]
$(@ace.container).find('.ace_gutter-cell.executing').removeClass('executing')
return unless executed.length
unless executed.length
@toolbarView?.$el.hide()
return
unless @toolbarView or (@spell.name is "plan" and @spellThang.castAether.metrics.statementsExecuted < 20)
@createToolbarView()
lastExecuted = _.last executed
@toolbarView?.$el.show()
statementIndex = Math.max 0, lastExecuted.length - 1
@toolbarView?.setCallState states[currentCallIndex], statementIndex, currentCallIndex, @spellThang.castAether.metrics
marked = {}
lastExecuted = lastExecuted[0 .. @toolbarView.statementIndex] if @toolbarView?.statementIndex?
for state, i in lastExecuted
#clazz = if state.executing then 'executing' else 'executed' # doesn't work
clazz = if i is lastExecuted.length - 1 then 'executing' else 'executed'
@ -410,6 +451,9 @@ module.exports = class SpellView extends View
continue if marked[key] > 2 # don't allow more than three of the same marker
marked[key] ?= 0
++marked[key]
else
@debugView.setVariableStates state.variables
#console.log "at", state.userInfo.time, "vars are now:", state.variables
[start, end] = [offsetToPos(state.range[0]), offsetToPos(state.range[1])]
markerRange = new Range(start.row, start.column, end.row, end.column)
markerRange.start = @aceDoc.createAnchor markerRange.start
@ -454,3 +498,4 @@ module.exports = class SpellView extends View
super()
@firepad?.dispose()
@ace.destroy()
@debugView.destroy()

View file

@ -114,6 +114,7 @@ module.exports = class TomeView extends View
@spellTabView?.$el.after('<div id="' + @spellTabView.id + '"></div>').detach()
@spellTabView = null
@removeSubView @spellPaletteView if @spellPaletteView
@castButton?.$el.hide()
@thangList?.$el.show()
onSpriteSelected: (e) ->
@ -137,6 +138,7 @@ module.exports = class TomeView extends View
@$el.find('#' + @spellTabView.id).after(@spellTabView.el).remove()
@spellView.setThang thang
@spellTabView.setThang thang
@castButton.$el.show()
@thangList.$el.hide()
@spellPaletteView = @insertSubView new SpellPaletteView thang: thang
@spellPaletteView.toggleControls {}, @spellView.controlsEnabled # TODO: know when palette should have been disabled but didn't exist