Implementing more of new code editor design. Removed ThangList, EditorConfigModal, and a few other obsolete things.
BIN
app/assets/images/common/button-background-active-border.png
Normal file
After ![]() (image error) Size: 4.2 KiB |
BIN
app/assets/images/common/button-background-active.png
Normal file
After ![]() (image error) Size: 3.5 KiB |
BIN
app/assets/images/common/button-background-disabled-border.png
Normal file
After ![]() (image error) Size: 3.7 KiB |
BIN
app/assets/images/common/button-background-disabled.png
Normal file
After ![]() (image error) Size: 3.1 KiB |
BIN
app/assets/images/common/button-background-pressed-border.png
Normal file
After ![]() (image error) Size: 4.1 KiB |
BIN
app/assets/images/common/button-background-pressed.png
Normal file
After ![]() (image error) Size: 3.7 KiB |
BIN
app/assets/images/level/code_editor_background_border.png
Normal file
After ![]() (image error) Size: 34 KiB |
BIN
app/assets/images/level/code_editor_top_bar_hinge.png
Normal file
After ![]() (image error) Size: 1.7 KiB |
BIN
app/assets/images/level/code_editor_top_bar_wood_background.png
Normal file
After ![]() (image error) Size: 25 KiB |
BIN
app/assets/images/level/code_palette_wood_background.png
Normal file
After ![]() (image error) Size: 65 KiB |
BIN
app/assets/images/level/code_toolbar_background.png
Normal file
After ![]() (image error) Size: 7.6 KiB |
BIN
app/assets/images/level/code_toolbar_run_button_active.png
Normal file
After ![]() (image error) Size: 4.8 KiB |
After ![]() (image error) Size: 4.7 KiB |
BIN
app/assets/images/level/code_toolbar_run_button_zazz.png
Normal file
After ![]() (image error) Size: 5.3 KiB |
BIN
app/assets/images/level/code_toolbar_run_button_zazz_pressed.png
Normal file
After ![]() (image error) Size: 5.2 KiB |
BIN
app/assets/images/level/code_toolbar_submit_button_active.png
Normal file
After ![]() (image error) Size: 5.2 KiB |
After ![]() (image error) Size: 5.2 KiB |
BIN
app/assets/images/level/code_toolbar_submit_button_zazz.png
Normal file
After ![]() (image error) Size: 5.5 KiB |
After ![]() (image error) Size: 5.5 KiB |
BIN
app/assets/images/level/hud_hinge.png
Normal file
After ![]() (image error) Size: 2.1 KiB |
BIN
app/assets/images/level/thang_avatar_frame.png
Normal file
After ![]() (image error) Size: 4.7 KiB |
|
@ -198,6 +198,7 @@
|
|||
failing: "Failing"
|
||||
action_timeline: "Action Timeline"
|
||||
click_to_select: "Click on a unit to select it."
|
||||
reload: "Reload"
|
||||
reload_title: "Reload All Code?"
|
||||
reload_really: "Are you sure you want to reload this level back to the beginning?"
|
||||
reload_confirm: "Reload All"
|
||||
|
@ -447,7 +448,7 @@
|
|||
enter: "Enter"
|
||||
escape: "Escape"
|
||||
shift: "Shift"
|
||||
cast_spell: "Cast current spell."
|
||||
run_code: "Run current code."
|
||||
run_real_time: "Run in real time."
|
||||
continue_script: "Continue past current script."
|
||||
skip_scripts: "Skip past all skippable scripts."
|
||||
|
|
|
@ -85,9 +85,6 @@ module.exports =
|
|||
problems: {type: 'array'}
|
||||
isCast: {type: 'boolean'}
|
||||
|
||||
'tome:thang-list-entry-popover-shown': c.object {title: 'Thang List Entry Popover Shown', description: 'Published when we show the popover for a thang in the master list', required: ['entry']},
|
||||
entry: {type: 'object'}
|
||||
|
||||
'tome:spell-shown': c.object {title: 'Spell Shown', description: 'Published when we show a spell', required: ['thang', 'spell']},
|
||||
thang: {type: 'object'}
|
||||
spell: {type: 'object'}
|
||||
|
|
|
@ -312,9 +312,56 @@ kbd
|
|||
.arrow
|
||||
display: none
|
||||
|
||||
.btn.btn-illustrated
|
||||
background: 0
|
||||
border: 0
|
||||
border-radius: 0
|
||||
@include box-shadow(none)
|
||||
border-image: url(/images/common/button-background-active-border.png) 14 20 20 20 fill round
|
||||
border-width: 7px 10px 10px 10px
|
||||
padding: 0
|
||||
font-family: Open Sans Condensed
|
||||
text-transform: uppercase
|
||||
font-weight: bold
|
||||
color: rgb(248, 197, 146)
|
||||
|
||||
&:active
|
||||
border-image: url(/images/common/button-background-pressed-border.png) 14 16 16 20 fill round
|
||||
padding: 2px 0 0 2px
|
||||
border-width: 7px 8px 8px 10px
|
||||
|
||||
&.disabled, &:disabled
|
||||
border-image: url(/images/common/button-background-disabled-border.png) 14 20 20 20 fill round
|
||||
@include opacity(1)
|
||||
|
||||
> *
|
||||
@include opacity(0.5)
|
||||
|
||||
> *
|
||||
@include opacity(0.75)
|
||||
|
||||
&:hover > *
|
||||
@include opacity(1)
|
||||
|
||||
|
||||
html.no-borderimage
|
||||
.popover
|
||||
border: 0
|
||||
background: transparent url(/images/level/popover_background.png)
|
||||
background-size: 100% 100%
|
||||
padding: 10px 20px
|
||||
|
||||
.btn.btn-illustrated
|
||||
border: 0
|
||||
background-image: url(/images/common/button-background-active.png)
|
||||
background-size: 100% 100%
|
||||
padding: 7px 10px 10px 10px
|
||||
|
||||
&:active
|
||||
background-image: url(/images/common/button-background-pressed.png)
|
||||
padding: 9px 8px 8px 12px
|
||||
border: 0
|
||||
|
||||
&.disabled, &:disabled
|
||||
background-image: url(/images/common/button-background-disabled.png)
|
||||
|
||||
|
|
|
@ -97,6 +97,7 @@ $level-resize-transition-time: 0.5s
|
|||
top: 0px
|
||||
bottom: 0
|
||||
@include transition(width $level-resize-transition-time ease-in-out, right $level-resize-transition-time ease-in-out)
|
||||
overflow: hidden
|
||||
|
||||
// Level Docs
|
||||
.ui-effects-transfer
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
#level-editor-config-modal
|
||||
.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
|
|
@ -28,9 +28,9 @@
|
|||
|
||||
.avatar-frame
|
||||
position: absolute
|
||||
left: -13%
|
||||
top: -14%
|
||||
width: 132%
|
||||
left: -18%
|
||||
top: -19%
|
||||
width: 145%
|
||||
|
||||
.badge
|
||||
$radius: 8px
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
@include box-shadow(0px 0px 8px #333)
|
||||
color: white
|
||||
50%
|
||||
@include box-shadow(0px 0px 35px #87FFCE)
|
||||
color: #87FFFF
|
||||
@include box-shadow(0px 0px 35px #87CEFF)
|
||||
color: #87CEFF
|
||||
to
|
||||
@include box-shadow(0px 0px 8px #333)
|
||||
color: white
|
||||
|
@ -31,40 +31,113 @@
|
|||
width: 100%
|
||||
border-radius: 6px
|
||||
|
||||
.btn
|
||||
padding: 3px 10px
|
||||
height: 40px
|
||||
font-size: 22px
|
||||
background: transparent url(/images/level/code_toolbar_background.png)
|
||||
background-size: 100% 100%
|
||||
left: -15px
|
||||
right: 15px
|
||||
height: 94px
|
||||
margin-top: -8px
|
||||
padding: 20px 2.8%
|
||||
|
||||
.submit-button
|
||||
margin-left: 20px
|
||||
min-width: 150px
|
||||
.btn.btn-illustrated
|
||||
height: 46px
|
||||
font-size: 24px
|
||||
line-height: 24px
|
||||
width: 45%
|
||||
width: -webkit-calc(50% - 10px)
|
||||
width: calc(50% - 10px)
|
||||
border-image: url(/images/level/code_toolbar_run_button_active.png) 14 20 20 20 fill round
|
||||
border-width: 7px 10px 10px 10px
|
||||
|
||||
&:active
|
||||
border-image: url(/images/level/code_toolbar_run_button_active_pressed.png) 14 20 20 20 fill round
|
||||
padding: 2px 0 0 2px
|
||||
|
||||
&.submit-button
|
||||
margin-left: 10px
|
||||
border-image: url(/images/level/code_toolbar_submit_button_active.png) 14 20 20 20 fill round
|
||||
|
||||
&:active
|
||||
border-image: url(/images/level/code_toolbar_submit_button_active_pressed.png) 14 20 20 20 fill round
|
||||
|
||||
.cast-button
|
||||
margin-left: 10px
|
||||
min-width: 150px
|
||||
@include opacity(0.77)
|
||||
|
||||
&:hover, &.castable
|
||||
@include opacity(1)
|
||||
|
||||
.submit-button > *
|
||||
@include opacity(0.9)
|
||||
|
||||
&:hover
|
||||
@include opacity(1)
|
||||
|
||||
&:not(.winnable)
|
||||
|
||||
.cast-button.castable
|
||||
font-weight: bold
|
||||
-webkit-animation-name: castablePulse
|
||||
-webkit-animation-duration: 3s
|
||||
-webkit-animation-iteration-count: infinite
|
||||
.btn.btn-illustrated
|
||||
|
||||
.submit-button
|
||||
font-size: 16px
|
||||
&.cast-button.castable
|
||||
font-weight: bold
|
||||
@include animation(castablePulse 3s infinite)
|
||||
border-image: url(/images/level/code_toolbar_run_button_zazz.png) 14 20 20 20 fill round
|
||||
|
||||
&:active
|
||||
border-image: url(/images/level/code_toolbar_run_button_zazz_pressed.png) 14 20 20 20 fill round
|
||||
|
||||
&.submit-button
|
||||
font-size: 16px
|
||||
|
||||
&.winnable
|
||||
.submit-button
|
||||
font-weight: bold
|
||||
-webkit-animation-name: winnablePulse
|
||||
-webkit-animation-duration: 3s
|
||||
-webkit-animation-iteration-count: infinite
|
||||
|
||||
.cast-button
|
||||
font-size: 16px
|
||||
.btn.btn-illustrated
|
||||
&.submit-button
|
||||
font-weight: bold
|
||||
@include animation(winnablePulse 3s infinite)
|
||||
|
||||
border-image: url(/images/level/code_toolbar_submit_button_zazz.png) 14 20 20 20 fill round
|
||||
|
||||
&:active
|
||||
border-image: url(/images/level/code_toolbar_submit_button_zazz_pressed.png) 14 20 20 20 fill round
|
||||
|
||||
&.cast-button
|
||||
font-size: 16px
|
||||
|
||||
html.no-borderimage #cast-button-view
|
||||
.btn.btn-illustrated
|
||||
border: 0
|
||||
background-image: url(/images/level/code_toolbar_run_button_active.png)
|
||||
background-size: 100% 100%
|
||||
padding: 7px 10px 10px 10px
|
||||
|
||||
&:active
|
||||
background-image: url(/images/level/code_toolbar_run_button_active_pressed.png)
|
||||
padding: 9px 8px 8px 12px
|
||||
border: 0
|
||||
|
||||
&.submit-button
|
||||
background-image: url(/images/level/code_toolbar_submit_button_active_pressed.png)
|
||||
border: 0
|
||||
|
||||
&:active
|
||||
background-image: url(/images/level/code_toolbar_submit_button_active_pressed.png)
|
||||
border: 0
|
||||
|
||||
&:not(.winnable)
|
||||
.btn.btn-illustrated
|
||||
&.cast-button.castable
|
||||
border: 0
|
||||
background-image: url(/images/level/code_toolbar_run_button_zazz.png)
|
||||
|
||||
&:active
|
||||
background-image: url(/images/level/code_toolbar_run_button_zazz_pressed.png)
|
||||
|
||||
&.winnable
|
||||
.btn.btn-illustrated
|
||||
&.submit-button
|
||||
border: 0
|
||||
background-image: url(/images/level/code_toolbar_submit_button_zazz.png)
|
||||
|
||||
&:active
|
||||
border: 0
|
||||
background-image: url(/images/level/code_toolbar_submit_button_zazz_pressed.png)
|
||||
|
||||
|
|
|
@ -2,38 +2,37 @@
|
|||
@import "app/styles/bootstrap/variables"
|
||||
|
||||
@mixin editor-height($extraHeight)
|
||||
@include box-sizing(border-box)
|
||||
width: 98%
|
||||
height: 83%
|
||||
height: unquote("-webkit-calc(100% - 60px -")$extraHeight unquote(")")
|
||||
height: unquote("calc(100% - 60px -")$extraHeight unquote(")")
|
||||
height: unquote("-webkit-calc(100% - 100px -")$extraHeight unquote(")")
|
||||
height: unquote("calc(100% - 100px -")$extraHeight unquote(")")
|
||||
|
||||
#spell-view
|
||||
position: absolute
|
||||
left: 10px
|
||||
top: 140px
|
||||
//top: 48px
|
||||
right: 10px
|
||||
padding-bottom: 10px
|
||||
z-index: 1
|
||||
// Set z-index above palette
|
||||
margin-top: 10px
|
||||
padding-top: 20px
|
||||
padding-left: 30px
|
||||
padding-bottom: 95px
|
||||
display: none
|
||||
position: relative
|
||||
z-index: 1
|
||||
|
||||
&.shown
|
||||
display: block
|
||||
|
||||
.code-background
|
||||
position: absolute
|
||||
top: 0
|
||||
top: -68px
|
||||
left: 0px
|
||||
height: 100%
|
||||
width: 100%
|
||||
right: -10px
|
||||
|
||||
span.code-background
|
||||
border-width: 40px
|
||||
border-image: url(/images/level/code_editor_background.png) 40 fill round
|
||||
border-width: 124px 76px 64px 40px
|
||||
border-image: url(/images/level/code_editor_background_border.png) 124 76 64 40 fill round
|
||||
|
||||
img.code-background
|
||||
display: none
|
||||
width: 100%
|
||||
|
||||
.save-status
|
||||
display: none
|
||||
|
@ -44,7 +43,7 @@
|
|||
.firepad
|
||||
// When Firepad is active, it wraps .ace_editor in .firepad.
|
||||
@include editor-height(0px)
|
||||
width: 98%
|
||||
width: 94%
|
||||
|
||||
.ace_editor
|
||||
width: 100%
|
||||
|
@ -56,7 +55,7 @@
|
|||
.ace_editor
|
||||
// When Firepad isn't active, .ace_editor needs the width/height set itself.
|
||||
@include editor-height(0px)
|
||||
width: 98%
|
||||
width: 94%
|
||||
position: relative
|
||||
background-color: transparent
|
||||
line-height: 20px
|
||||
|
@ -70,14 +69,18 @@
|
|||
@include opacity(20)
|
||||
|
||||
.ace_gutter
|
||||
background-color: rgba(255, 255, 255, 0.25)
|
||||
background-color: transparent
|
||||
border-right: 1px solid rgb(195, 178, 156)
|
||||
//background-color: rgba(255, 255, 255, 0.25)
|
||||
width: 47px
|
||||
margin-left: 4px
|
||||
border-bottom: 1px dotted #2f261d
|
||||
|
||||
.ace_scroller
|
||||
background-color: transparent
|
||||
border-bottom: 1px dotted #2f261d
|
||||
//padding-left: 10px // Interrupts gutter and line highlighting
|
||||
|
||||
.ace_active-line, .ace_gutter-active-line
|
||||
background-color: rgba(255, 255, 255, 0.4)
|
||||
|
||||
.ace_content
|
||||
.executing, .executed, .problem-marker-info, .problem-marker-warning, .problem-marker-error
|
||||
|
@ -147,10 +150,10 @@
|
|||
.ace_searchbtn, .ace_replacebtn
|
||||
padding: 0px 4px
|
||||
|
||||
|
||||
html.no-borderimage
|
||||
#spell-view
|
||||
span.code-background
|
||||
display: none
|
||||
img.code-background
|
||||
display: block
|
||||
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
$height: 87px
|
||||
$paddingTop: 10px
|
||||
$paddingBottom: 25px
|
||||
$childMargin: 2px
|
||||
$childSize: $height - $paddingTop - $paddingBottom
|
||||
width: 100%
|
||||
height: $height
|
||||
|
@ -22,6 +21,7 @@
|
|||
position: relative
|
||||
background: transparent url(/images/level/code_editor_top_bar_wood_background.png)
|
||||
background-size: 100% 100%
|
||||
z-index: 2
|
||||
|
||||
.hinge
|
||||
position: absolute
|
||||
|
@ -30,7 +30,6 @@
|
|||
width: 24px
|
||||
height: 20px
|
||||
background-size: contain
|
||||
z-index: 100
|
||||
|
||||
.hinge-0
|
||||
left: 20%
|
||||
|
@ -45,15 +44,24 @@
|
|||
background: linear-gradient(to bottom, rgba(0,0,0,0.5) 0%,rgba(0,0,0,0.5) 100%), url(/images/level/code_editor_top_bar_wood_background.png)
|
||||
background-size: 100% 100%
|
||||
|
||||
.spell-list-button, .thang-avatar-view, .reload-code, .beautify-code, .fullscreen-code
|
||||
width: $childSize
|
||||
height: $childSize
|
||||
margin: 0 $childMargin
|
||||
.thang-avatar-view
|
||||
width: $childSize - 10px
|
||||
margin: 5px
|
||||
display: inline-block
|
||||
|
||||
.spell-list-button, .thang-avatar-view
|
||||
float: left
|
||||
|
||||
.btn.btn-small
|
||||
margin-top: 15px
|
||||
margin-right: 15px
|
||||
font-size: 18px
|
||||
|
||||
.glyphicon
|
||||
font-size: 16px
|
||||
|
||||
.btn.btn-small.spell-list-button
|
||||
float: left
|
||||
margin-top: 5px
|
||||
|
||||
.spell-tool-buttons
|
||||
position: absolute
|
||||
right: 0px
|
||||
|
@ -69,43 +77,32 @@
|
|||
.fullscreen-code
|
||||
float: right
|
||||
&:not(.maximized)
|
||||
.icon-resize-small
|
||||
.glyphicon-resize-small
|
||||
display: none
|
||||
&.maximized
|
||||
.icon-fullscreen
|
||||
.glyphicon-fullscreen
|
||||
display: none
|
||||
|
||||
.btn.btn-small
|
||||
background: transparent
|
||||
padding: 0
|
||||
|
||||
&:not(:hover)
|
||||
border-color: transparent
|
||||
@include box-shadow(none)
|
||||
|
||||
.icon-chevron-down, .icon-repeat, .icon-magnet, .icon-fullscreen, .icon-resize-small
|
||||
margin-top: 7px
|
||||
|
||||
.thang-avatar-wrapper
|
||||
border-width: 0
|
||||
|
||||
.method-label
|
||||
.method-name-area
|
||||
margin-left: 10px
|
||||
line-height: $childSize
|
||||
font-size: 1vw
|
||||
display: inline-block
|
||||
font-weight: bold
|
||||
color: white
|
||||
margin-top: 10px
|
||||
text-transform: uppercase
|
||||
display: inline-block
|
||||
font-family: Open Sans Condensed
|
||||
font-weight: bold
|
||||
|
||||
.method-signature
|
||||
margin-left: 10px
|
||||
line-height: $childSize
|
||||
font-size: 1vw
|
||||
display: inline-block
|
||||
font-weight: bold
|
||||
color: white
|
||||
text-transform: uppercase
|
||||
.method-label
|
||||
font-size: 12px
|
||||
color: rgb(243, 211, 59)
|
||||
margin-bottom: -5px
|
||||
|
||||
.method-signature
|
||||
color: white
|
||||
font-size: 18px
|
||||
padding: 0
|
||||
|
||||
.spell-list-entry-view:not(.spell-tab)
|
||||
cursor: pointer
|
||||
|
|
|
@ -3,55 +3,44 @@
|
|||
|
||||
#spell-palette-view
|
||||
position: absolute
|
||||
padding-bottom: 10px
|
||||
left: 10px
|
||||
right: 10px
|
||||
//height: 140px
|
||||
// Height relates to .tab-content height
|
||||
padding-top: 35px
|
||||
padding-left: 12px
|
||||
padding-right: 4px
|
||||
color: #333
|
||||
// Get crazy with the backgrounds so that we can lower the opacity on the editor background above it, making a gradient of the disabled background color on the top around where it's usually covered
|
||||
padding: 0 4px 10px 40px
|
||||
background-color: transparent
|
||||
background-size: 100% 100%
|
||||
z-index: 0
|
||||
z-index: 2
|
||||
//overflow-y: auto
|
||||
|
||||
.code-palette-background
|
||||
position: absolute
|
||||
left: 0
|
||||
top: 0
|
||||
width: 100%
|
||||
height: 100%
|
||||
z-index: -1
|
||||
|
||||
span.code-palette-background
|
||||
border-width: 25px
|
||||
border-image: url(/images/level/code_palette_background.png) 25 fill round
|
||||
|
||||
img.code-palette-background
|
||||
display: none
|
||||
.code-palette-background
|
||||
width: 100%
|
||||
position: absolute
|
||||
left: 0px
|
||||
z-index: -1
|
||||
|
||||
&.disabled
|
||||
@include opacity(0.80)
|
||||
|
||||
h4
|
||||
color: #333
|
||||
color: white
|
||||
font-size: 16px
|
||||
line-height: 16px
|
||||
margin: 0 4px
|
||||
margin: 25px 0 5px 2px
|
||||
font-weight: normal
|
||||
text-transform: uppercase
|
||||
|
||||
.nav > li > a
|
||||
padding: 2px 20px 0px 20px
|
||||
margin-bottom: 3px
|
||||
|
||||
ul.nav.nav-pills
|
||||
margin-top: 15px
|
||||
|
||||
h4
|
||||
margin-top: 2px
|
||||
li.active a
|
||||
background-color: transparent
|
||||
&.multiple-tabs li.active a
|
||||
background-color: lighten(rgb(230, 212, 146), 10%)
|
||||
background-color: darken(rgb(230, 212, 146), 30%)
|
||||
&.multiple-tabs li:not(.active) a
|
||||
cursor: pointer
|
||||
|
||||
|
@ -82,8 +71,9 @@
|
|||
@include flexbox()
|
||||
@include flex-wrap()
|
||||
@include flex-center()
|
||||
outline: 1px dashed #b86
|
||||
position: relative
|
||||
background-color: rgb(20, 13, 8)
|
||||
margin: 1px
|
||||
|
||||
img.item-image
|
||||
width: 38px
|
||||
|
@ -91,49 +81,11 @@
|
|||
position: absolute
|
||||
|
||||
&:not(:hover) img.item-image
|
||||
-webkit-filter: sepia(100%)
|
||||
filter: sepia(100%)
|
||||
-webkit-filter: contrast(50%) sepia(100%) saturate(500%) hue-rotate(7deg)
|
||||
filter: contrast(50%) sepia(100%) saturate(1000%) hue-rotate(7deg)
|
||||
|
||||
.spell-palette-entry-view
|
||||
margin-left: 38px
|
||||
width: 174px
|
||||
width: -webkit-calc(100% - 38px)
|
||||
width: calc(100% - 38px)
|
||||
|
||||
.code-language-logo
|
||||
position: absolute
|
||||
width: 16px
|
||||
height: 16px
|
||||
left: 16px
|
||||
top: 36px
|
||||
z-index: 10
|
||||
background-color: transparent
|
||||
background-repeat: no-repeat
|
||||
background-size: contain
|
||||
cursor: pointer
|
||||
|
||||
&.javascript
|
||||
background-image: url(/images/common/code_languages/javascript_icon.png)
|
||||
&.python
|
||||
background-image: url(/images/common/code_languages/python_icon.png)
|
||||
&.coffeescript
|
||||
background-image: url(/images/common/code_languages/coffeescript_icon.png)
|
||||
&.clojure
|
||||
background-image: url(/images/common/code_languages/clojure_icon.png)
|
||||
&.lua
|
||||
background-image: url(/images/common/code_languages/lua_icon.png)
|
||||
&.io
|
||||
background-image: url(/images/common/code_languages/io_icon.png)
|
||||
|
||||
&:hover
|
||||
outline: 1px outset #ccc
|
||||
|
||||
&:active
|
||||
outline: 1px inset #ccc
|
||||
|
||||
html.no-borderimage
|
||||
#spell-palette-view
|
||||
span.code-palette-background
|
||||
display: none
|
||||
img.code-palette-background
|
||||
display: block
|
||||
|
|
|
@ -25,20 +25,21 @@
|
|||
background-color: darken(#FFFFFF, 25%)
|
||||
|
||||
// Originally pulled these colors from the most relevant textmate-theme classes, but then fudged them a lot.
|
||||
&.function
|
||||
color: black
|
||||
&.object
|
||||
color: rgb(6, 150, 14)
|
||||
&.string
|
||||
color: rgb(3, 106, 7)
|
||||
&.number
|
||||
color: rgb(0, 0, 205)
|
||||
&.boolean
|
||||
color: rgb(88, 92, 246)
|
||||
&.snippet
|
||||
color: blue
|
||||
&.undefined
|
||||
color: rgb(197, 6, 11)
|
||||
//&.function
|
||||
// color: black
|
||||
//&.object
|
||||
// color: rgb(6, 150, 14)
|
||||
//&.string
|
||||
// color: rgb(3, 106, 7)
|
||||
//&.number
|
||||
// color: rgb(0, 0, 205)
|
||||
//&.boolean
|
||||
// color: rgb(88, 92, 246)
|
||||
//&.snippet
|
||||
// color: blue
|
||||
//&.undefined
|
||||
// color: rgb(197, 6, 11)
|
||||
color: rgb(243, 169, 49)
|
||||
|
||||
.spell-palette-popover.popover
|
||||
// Only those popovers which are our direct children (spell documentation)
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
@import "app/styles/mixins"
|
||||
@import "app/styles/bootstrap/variables"
|
||||
|
||||
#thang-list-view
|
||||
margin: 50px 15px 15px 15px
|
||||
overflow: auto
|
||||
height: 80%
|
||||
height: -webkit-calc(100% - 65px)
|
||||
height: calc(100% - 65px)
|
||||
|
||||
h3
|
||||
line-height: 25px
|
||||
margin: 0
|
||||
text-align: center
|
||||
letter-spacing: 0.1em
|
||||
|
||||
.thang-list-section
|
||||
margin: 5px
|
||||
padding: 5px
|
||||
background-color: rgba(200, 200, 200, 0.25)
|
||||
border-radius: 5px
|
||||
overflow: hidden
|
|
@ -1,38 +0,0 @@
|
|||
@import "app/styles/mixins"
|
||||
@import "app/styles/bootstrap/variables"
|
||||
|
||||
.thang-list-entry-view
|
||||
@include opacity(0.90)
|
||||
cursor: pointer
|
||||
float: left
|
||||
box-sizing: border-box
|
||||
width: 20%
|
||||
max-width: 100px
|
||||
position: relative
|
||||
|
||||
&.dead
|
||||
@include opacity(0.75)
|
||||
|
||||
&:after
|
||||
content: "×"
|
||||
font-size: 160px
|
||||
color: red
|
||||
@include opacity(0.75)
|
||||
position: absolute
|
||||
bottom: 0
|
||||
height: 100%
|
||||
width: 100%
|
||||
text-align: center
|
||||
line-height: 100px
|
||||
font-family: monospace
|
||||
|
||||
.thang-name
|
||||
text-decoration: line-through
|
||||
|
||||
&.disabled
|
||||
@include opacity(0.25)
|
||||
cursor: default
|
||||
|
||||
&:hover:not(.disabled)
|
||||
@include opacity(1)
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
@import "app/styles/mixins"
|
||||
@import "app/styles/bootstrap/variables"
|
||||
|
||||
.thang-list-entry-spells
|
||||
|
||||
.thang-list-entry-spell
|
||||
padding: 4px
|
||||
cursor: pointer
|
||||
|
||||
&:hover
|
||||
background-color: hsla(240, 40, 80, 0.25)
|
||||
|
||||
code
|
||||
background-color: transparent
|
||||
border: 0
|
||||
font-size: 1.1em
|
|
@ -1,55 +0,0 @@
|
|||
extends /templates/modal/modal_base
|
||||
|
||||
block modal-header-content
|
||||
h3(data-i18n="play_level.editor_config_title") Editor Configuration
|
||||
|
||||
block modal-body-content
|
||||
.form
|
||||
.form-group.select-group
|
||||
label.control-label(for="tome-session-language" data-i18n="play_level.editor_config_level_language_label") Language for This Level
|
||||
select#tome-session-language(name="language")
|
||||
for option in languages
|
||||
option(value=option.id selected=(sessionLanguage === option.id))= option.name
|
||||
span.help-block(data-i18n="play_level.editor_config_level_language_description") Define the programming language for this particular level.
|
||||
|
||||
.form-group.select-group
|
||||
label.control-label(for="tome-language" data-i18n="play_level.editor_config_default_language_label") Default Programming Language
|
||||
select#tome-language(name="language")
|
||||
for option in languages
|
||||
option(value=option.id selected=(language === option.id))= option.name
|
||||
span.help-block(data-i18n="play_level.editor_config_default_language_description") Define the programming language you want to code in when starting new levels.
|
||||
|
||||
.form-group.select-group
|
||||
label.control-label(for="tome-key-bindings" data-i18n="play_level.editor_config_keybindings_label") Key Bindings
|
||||
select#tome-key-bindings(name="keyBindings")
|
||||
option(value="default" selected=(keyBindings === "default") data-i18n="play_level.editor_config_keybindings_default") Default (Ace)
|
||||
option(value="vim" selected=(keyBindings === "vim")) Vim
|
||||
option(value="emacs" selected=(keyBindings === "emacs")) Emacs
|
||||
span.help-block(data-i18n="play_level.editor_config_keybindings_description") Adds additional shortcuts known from the common editors.
|
||||
|
||||
.form-group.checkbox
|
||||
label(for="tome-live-completion")
|
||||
input#tome-live-completion(name="liveCompletion", type="checkbox", checked=liveCompletion)
|
||||
span(data-i18n="play_level.editor_config_livecompletion_label") Live Autocompletion
|
||||
span.help-block(data-i18n="play_level.editor_config_livecompletion_description") Displays autocomplete suggestions while typing.
|
||||
|
||||
.form-group.checkbox
|
||||
label(for="tome-invisibles")
|
||||
input#tome-invisibles(name="invisibles", type="checkbox", checked=invisibles)
|
||||
span(data-i18n="play_level.editor_config_invisibles_label") Show Invisibles
|
||||
span.help-block(data-i18n="play_level.editor_config_invisibles_description") Displays invisibles such as spaces or tabs.
|
||||
|
||||
.form-group.checkbox
|
||||
label(for="tome-indent-guides")
|
||||
input#tome-indent-guides(name="indentGuides", type="checkbox", checked=indentGuides)
|
||||
span(data-i18n="play_level.editor_config_indentguides_label") Show Indent Guides
|
||||
span.help-block(data-i18n="play_level.editor_config_indentguides_description") Displays vertical lines to see indentation better.
|
||||
|
||||
.form-group.checkbox
|
||||
label(for="tome-behaviors")
|
||||
input#tome-behaviors(name="behaviors", type="checkbox", checked=behaviors)
|
||||
span(data-i18n="play_level.editor_config_behaviors_label") Smart Behaviors
|
||||
span.help-block(data-i18n="play_level.editor_config_behaviors_description") Autocompletes brackets, braces, and quotes.
|
||||
|
||||
block modal-footer-content
|
||||
a(href='#', data-dismiss="modal", aria-hidden="true", data-i18n="modal.close").btn.btn-primary Close
|
|
@ -19,7 +19,7 @@ block modal-body-content
|
|||
dl.dl-horizontal
|
||||
dt(title=shift + " " + enter)
|
||||
kbd ⇧ #{enter}
|
||||
dd(data-i18n="keyboard_shortcuts.cast_spell") Cast current spell.
|
||||
dd(data-i18n="keyboard_shortcuts.run_code") Run current code.
|
||||
dl.dl-horizontal
|
||||
dt(title=ctrlName + " " + shift + " " + enter)
|
||||
kbd #{ctrl} ⇧ #{enter}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
button.btn.btn-lg.btn-inverse.banner.cast-button(title=castVerbose, data-i18n="play_level.tome_run_button_ran") Ran
|
||||
button.btn.btn-lg.btn-illustrated.cast-button(title=castVerbose)
|
||||
span(data-i18n="play_level.tome_run_button_ran") Ran
|
||||
|
||||
if testSubmitText != null && testSubmitText.length > 0
|
||||
button.btn.btn-lg.btn-success.banner.submit-button(title=castRealTimeVerbose) #{testSubmitText}
|
||||
else
|
||||
button.btn.btn-lg.btn-success.banner.submit-button(title=castRealTimeVerbose, data-i18n="play_level.tome_submit_button") Submit
|
||||
button.btn.btn-lg.btn-illustrated.submit-button(title=castRealTimeVerbose)
|
||||
if testSubmitText != null && testSubmitText.length > 0
|
||||
span= testSubmitText
|
||||
else
|
||||
span(data-i18n="play_level.tome_submit_button") Submit
|
||||
|
|
|
@ -4,25 +4,27 @@
|
|||
.hinge.hinge-3
|
||||
|
||||
if includeSpellList
|
||||
.btn.btn-small.spell-list-button(data-i18n="[title]play_level.tome_see_all_methods", title="See all methods you can edit")
|
||||
i.icon-chevron-down
|
||||
.btn.btn-small.btn-illustrated.spell-list-button(data-i18n="[title]play_level.tome_see_all_methods", title="See all methods you can edit")
|
||||
.glyphicon.glyphicon-chevron-down
|
||||
|
||||
.thang-avatar-placeholder
|
||||
|
||||
.method-label(data-i18n="play_level.tome_current_method") Current Method
|
||||
.method-signature #{methodSignature}
|
||||
.method-name-area
|
||||
.method-label(data-i18n="play_level.tome_current_method") Current Method
|
||||
.method-signature #{methodSignature}
|
||||
|
||||
.spell-tool-buttons
|
||||
if levelType !== 'hero'
|
||||
.btn.btn-small.fullscreen-code(title=maximizeShortcutVerbose)
|
||||
i.icon-fullscreen
|
||||
i.icon-resize-small
|
||||
|
||||
.btn.btn-small.reload-code(data-i18n="[title]play_level.tome_reload_method", title="Reload original code for this method")
|
||||
i.icon-repeat
|
||||
.btn.btn-small.btn-illustrated.reload-code(data-i18n="[title]play_level.tome_reload_method", title="Reload original code for this method")
|
||||
.glyphicon.glyphicon-repeat
|
||||
span.spl(data-i18n="play_level.reload") Reload
|
||||
|
||||
if codeLanguage === 'javascript'
|
||||
.btn.btn-small.beautify-code(title=beautifyShortcutVerbose)
|
||||
i.icon-magnet
|
||||
if levelType !== 'hero' && levelType !== 'hero-ladder' && levelType !== 'hero-coop'
|
||||
.btn.btn-small.btn-illustrated.fullscreen-code(title=maximizeShortcutVerbose)
|
||||
.glyphicon.glyphicon-fullscreen
|
||||
.glyphicon.glyphicon-resize-small
|
||||
|
||||
if codeLanguage === 'javascript' && levelType !== 'hero' && levelType !== 'hero-ladder' && levelType !== 'hero-coop'
|
||||
.btn.btn-small.btn-illustrated.beautify-code(title=beautifyShortcutVerbose)
|
||||
.glyphicon.glyphicon-magnet
|
||||
|
||||
.clearfix
|
|
@ -1,8 +1,7 @@
|
|||
img(src="/images/level/code_palette_background.png").code-palette-background
|
||||
img(src="/images/level/code_palette_wood_background.png").code-palette-background
|
||||
span.code-palette-background
|
||||
if entryGroupSlugs
|
||||
// Non-hero; group by entry groups, or maybe nothing.
|
||||
.code-language-logo
|
||||
ul(class="nav nav-pills" + (tabbed ? ' multiple-tabs' : ''))
|
||||
each slug, group in entryGroupSlugs
|
||||
li(class=group == "this" || slug == "available-spells" ? "active" : "")
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
#readwrite-thangs.thang-list-section
|
||||
h3(data-i18n="play_level.tome_minion_spells") Your Minions' Spells
|
||||
.thang-list
|
||||
.clearfix
|
||||
|
||||
#read-thangs.thang-list-section
|
||||
h3(data-i18n="play_level.tome_read_only_spells") Read-Only Spells
|
||||
.thang-list
|
||||
.clearfix
|
||||
|
||||
#muggle-thangs.thang-list-section
|
||||
h3(data-i18n="play_level.tome_other_units") Other Units
|
||||
.thang-list
|
||||
.clearfix
|
|
@ -1,5 +0,0 @@
|
|||
h4.not-code(data-i18n="play_level.tome_select_spell") Select a Spell
|
||||
.thang-list-entry-spells
|
||||
for spell in spells
|
||||
div.thang-list-entry-spell
|
||||
code(data-spell-name=spell.name) #{spell.name}(#{parameters})
|
|
@ -2,8 +2,6 @@
|
|||
|
||||
#spell-list-view
|
||||
|
||||
#thang-list-view
|
||||
|
||||
#cast-button-view
|
||||
|
||||
#spell-view
|
||||
|
|
|
@ -2,9 +2,6 @@ CocoView = require 'views/kinds/CocoView'
|
|||
template = require 'templates/play/level/playback'
|
||||
{me} = require 'lib/auth'
|
||||
|
||||
EditorConfigModal = require './modal/EditorConfigModal'
|
||||
KeyboardShortcutsModal = require './modal/KeyboardShortcutsModal'
|
||||
|
||||
module.exports = class LevelPlaybackView extends CocoView
|
||||
id: 'playback-view'
|
||||
template: template
|
||||
|
|
|
@ -1,92 +0,0 @@
|
|||
ModalView = require 'views/kinds/ModalView'
|
||||
template = require 'templates/play/level/modal/editor_config'
|
||||
{me} = require 'lib/auth'
|
||||
|
||||
module.exports = class EditorConfigModal extends ModalView
|
||||
id: 'level-editor-config-modal'
|
||||
template: template
|
||||
aceConfig: {}
|
||||
|
||||
defaultConfig:
|
||||
language: 'python'
|
||||
keyBindings: 'default'
|
||||
invisibles: false
|
||||
indentGuides: false
|
||||
behaviors: false
|
||||
liveCompletion: true
|
||||
|
||||
events:
|
||||
'change #tome-invisibles': 'updateInvisibles'
|
||||
'change #tome-language': 'updateLanguage'
|
||||
'change #tome-key-bindings': 'updateKeyBindings'
|
||||
'change #tome-indent-guides': 'updateIndentGuides'
|
||||
'change #tome-behaviors': 'updateBehaviors'
|
||||
'change #tome-live-completion': 'updateLiveCompletion'
|
||||
|
||||
constructor: (options) ->
|
||||
super(options)
|
||||
@session = options.session
|
||||
|
||||
getRenderData: ->
|
||||
@aceConfig = _.cloneDeep me.get('aceConfig') ? {}
|
||||
@aceConfig = _.defaults @aceConfig, @defaultConfig
|
||||
c = super()
|
||||
c.languages = [
|
||||
{id: 'python', name: 'Python'}
|
||||
{id: 'javascript', name: 'JavaScript'}
|
||||
{id: 'coffeescript', name: 'CoffeeScript'}
|
||||
{id: 'clojure', name: 'Clojure (Experimental)'}
|
||||
{id: 'lua', name: 'Lua (Experimental)'}
|
||||
{id: 'io', name: 'Io (Experimental)'}
|
||||
]
|
||||
c.sessionLanguage = @session.get('codeLanguage') ? @aceConfig.language
|
||||
c.language = @aceConfig.language
|
||||
c.keyBindings = @aceConfig.keyBindings
|
||||
c.invisibles = @aceConfig.invisibles
|
||||
c.indentGuides = @aceConfig.indentGuides
|
||||
c.behaviors = @aceConfig.behaviors
|
||||
c.liveCompletion = @aceConfig.liveCompletion
|
||||
c
|
||||
|
||||
updateSessionLanguage: ->
|
||||
@session.set 'codeLanguage', @$el.find('#tome-session-language').val()
|
||||
|
||||
updateLanguage: ->
|
||||
@aceConfig.language = @$el.find('#tome-language').val()
|
||||
|
||||
updateInvisibles: ->
|
||||
@aceConfig.invisibles = @$el.find('#tome-invisibles').prop('checked')
|
||||
|
||||
updateKeyBindings: ->
|
||||
@aceConfig.keyBindings = @$el.find('#tome-key-bindings').val()
|
||||
|
||||
updateIndentGuides: ->
|
||||
@aceConfig.indentGuides = @$el.find('#tome-indent-guides').prop('checked')
|
||||
|
||||
updateBehaviors: ->
|
||||
@aceConfig.behaviors = @$el.find('#tome-behaviors').prop('checked')
|
||||
|
||||
updateLiveCompletion: ->
|
||||
@aceConfig.liveCompletion = @$el.find('#tome-live-completion').prop('checked')
|
||||
|
||||
afterRender: ->
|
||||
super()
|
||||
|
||||
onHidden: ->
|
||||
oldLanguage = @session.get('codeLanguage') ? @aceConfig.language
|
||||
newLanguage = @$el.find('#tome-session-language').val()
|
||||
@session.set 'codeLanguage', newLanguage
|
||||
@aceConfig.language = @$el.find('#tome-language').val()
|
||||
@aceConfig.invisibles = @$el.find('#tome-invisibles').prop('checked')
|
||||
@aceConfig.keyBindings = @$el.find('#tome-key-bindings').val()
|
||||
@aceConfig.indentGuides = @$el.find('#tome-indent-guides').prop('checked')
|
||||
@aceConfig.behaviors = @$el.find('#tome-behaviors').prop('checked')
|
||||
@aceConfig.liveCompletion = @$el.find('#tome-live-completion').prop('checked')
|
||||
me.set 'aceConfig', @aceConfig
|
||||
Backbone.Mediator.publish 'tome:change-config', {}
|
||||
Backbone.Mediator.publish 'tome:change-language', language: newLanguage unless newLanguage is oldLanguage
|
||||
@session.save() unless newLanguage is oldLanguage
|
||||
me.patch()
|
||||
|
||||
destroy: ->
|
||||
super()
|
|
@ -33,7 +33,7 @@ module.exports = class CastButtonView extends CocoView
|
|||
enter = $.i18n.t 'keyboard_shortcuts.enter'
|
||||
castShortcutVerbose = "#{shift}+#{enter}"
|
||||
castRealTimeShortcutVerbose = (if @isMac() then 'Cmd' else 'Ctrl') + '+' + castShortcutVerbose
|
||||
context.castVerbose = castShortcutVerbose + ': ' + $.i18n.t('keyboard_shortcuts.cast_spell')
|
||||
context.castVerbose = castShortcutVerbose + ': ' + $.i18n.t('keyboard_shortcuts.run_code')
|
||||
context.castRealTimeVerbose = castRealTimeShortcutVerbose + ': ' + $.i18n.t('keyboard_shortcuts.run_real_time')
|
||||
# A/B test submit button text
|
||||
context.testSubmitText = @testButtonsText.submit if @testGroup? and @testGroup isnt 0
|
||||
|
@ -105,7 +105,7 @@ module.exports = class CastButtonView extends CocoView
|
|||
, (castable) =>
|
||||
Backbone.Mediator.publish 'tome:spell-has-changed-significantly-calculation', hasChangedSignificantly: castable
|
||||
@castButton.toggleClass('castable', castable).toggleClass('casting', @casting)
|
||||
|
||||
|
||||
# A/B testing cast button text for en-US
|
||||
if $.i18n.lng() isnt 'en-US' or not @testGroup? or @testGroup is 0
|
||||
if @casting
|
||||
|
@ -160,5 +160,3 @@ module.exports = class CastButtonView extends CocoView
|
|||
Action: 'Loaded'
|
||||
levelID: @levelID
|
||||
castButtonText: @testButtonsText.run + ' ' + @testButtonsText.submit
|
||||
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@ module.exports = class SpellListEntryView extends CocoView
|
|||
context
|
||||
|
||||
createMethodSignature: ->
|
||||
return @spell.name if @options.level.get('type', true) in ['hero', 'hero-ladder', 'hero-coop']
|
||||
parameters = (@spell.parameters or []).slice()
|
||||
if @spell.language in ['python', 'lua']
|
||||
parameters.unshift 'self'
|
||||
|
|
|
@ -61,7 +61,7 @@ module.exports = class SpellListView extends CocoView
|
|||
theseThangs = _.keys(spell.thangs)
|
||||
changedThangs = not lastThangs or not _.isEqual theseThangs, lastThangs
|
||||
lastThangs = theseThangs
|
||||
newEntries.push entry = new SpellListEntryView spell: spell, showTopDivider: changedThangs, supermodel: @supermodel, includeSpellList: @spells.length > 1
|
||||
newEntries.push entry = new SpellListEntryView spell: spell, showTopDivider: changedThangs, supermodel: @supermodel, includeSpellList: @spells.length > 1, level: @options.level
|
||||
@entries.push entry
|
||||
for entry in newEntries
|
||||
@$el.append entry.el
|
||||
|
|
|
@ -5,7 +5,6 @@ filters = require 'lib/image_filter'
|
|||
SpellPaletteEntryView = require './SpellPaletteEntryView'
|
||||
LevelComponent = require 'models/LevelComponent'
|
||||
ThangType = require 'models/ThangType'
|
||||
EditorConfigModal = require '../modal/EditorConfigModal'
|
||||
|
||||
N_ROWS = 4
|
||||
|
||||
|
@ -20,9 +19,6 @@ module.exports = class SpellPaletteView extends CocoView
|
|||
'surface:frame-changed': 'onFrameChanged'
|
||||
'tome:change-language': 'onTomeChangedLanguage'
|
||||
|
||||
events:
|
||||
'click .code-language-logo': 'onEditEditorConfig'
|
||||
|
||||
constructor: (options) ->
|
||||
super options
|
||||
@thang = options.thang
|
||||
|
@ -54,7 +50,7 @@ module.exports = class SpellPaletteView extends CocoView
|
|||
@entryGroupElements = {}
|
||||
for group, entries of @entryGroups
|
||||
@entryGroupElements[group] = itemGroup = $('<div class="property-entry-item-group"></div>').appendTo @$el.find('.properties')
|
||||
itemGroup.append $('<img class="item-image"></img>').attr('src', entries[0].options.item.getPortraitURL()).css('top', Math.max(0, 19 * (entries.length - 2) / 2)) if entries[0].options.item?.getPortraitURL
|
||||
itemGroup.append $('<img class="item-image"></img>').attr('src', entries[0].options.item.getPortraitURL()).css('top', Math.max(0, 19 * (entries.length - 2) / 2) + 2) if entries[0].options.item?.getPortraitURL
|
||||
for entry in entries
|
||||
itemGroup.append entry.el
|
||||
entry.render() # Render after appending so that we can access parent container for popover
|
||||
|
@ -67,7 +63,6 @@ module.exports = class SpellPaletteView extends CocoView
|
|||
|
||||
updateCodeLanguage: (language) ->
|
||||
@options.language = language
|
||||
@$el.find('.code-language-logo').removeClass().addClass 'code-language-logo ' + language
|
||||
|
||||
updateMaxHeight: ->
|
||||
return unless @isHero
|
||||
|
@ -266,9 +261,6 @@ module.exports = class SpellPaletteView extends CocoView
|
|||
@createPalette()
|
||||
@render()
|
||||
|
||||
onEditEditorConfig: (e) ->
|
||||
@openModalView new EditorConfigModal session: @options.session
|
||||
|
||||
destroy: ->
|
||||
entry.destroy() for entry in @entries
|
||||
@toggleBackground = null
|
||||
|
|
|
@ -360,10 +360,10 @@ module.exports = class SpellView extends CocoView
|
|||
spellPaletteHeight = $('#spell-palette-view').outerHeight()
|
||||
maxHeight = tomeHeight - spellListTabEntryHeight - spellToolbarHeight - spellPaletteHeight
|
||||
linesAtMaxHeight = Math.floor(maxHeight / lineHeight)
|
||||
lines = Math.max 8, Math.min(screenLineCount + 4, linesAtMaxHeight)
|
||||
# 2 lines buffer is nice, but 4 leaves room to put problem alerts.
|
||||
lines = Math.max 8, Math.min(screenLineCount + 2, linesAtMaxHeight)
|
||||
# 2 lines buffer is nice
|
||||
@ace.setOptions minLines: lines, maxLines: lines
|
||||
$('#spell-palette-view').css('top', 38 + 45 + lineHeight * lines) # Move spell palette up, slightly underlapping us.
|
||||
$('#spell-palette-view').css('top', 175 + lineHeight * lines) # Move spell palette up, slightly overlapping us.
|
||||
|
||||
onManualCast: (e) ->
|
||||
cast = @$el.parent().length
|
||||
|
|
|
@ -1,178 +0,0 @@
|
|||
# TODO: be useful to add error indicator states to the spellsPopoverTemplate
|
||||
# TODO: reordering based on errors isn't working yet
|
||||
|
||||
CocoView = require 'views/kinds/CocoView'
|
||||
ThangAvatarView = require 'views/play/level/ThangAvatarView'
|
||||
template = require 'templates/play/level/tome/thang_list_entry'
|
||||
spellsPopoverTemplate = require 'templates/play/level/tome/thang_list_entry_spells'
|
||||
{me} = require 'lib/auth'
|
||||
|
||||
module.exports = class ThangListEntryView extends CocoView
|
||||
tagName: 'div' #'li'
|
||||
className: 'thang-list-entry-view'
|
||||
template: template
|
||||
controlsEnabled: true
|
||||
reasonsToBeDisabled: {}
|
||||
|
||||
subscriptions:
|
||||
'tome:problems-updated': 'onProblemsUpdated'
|
||||
'level:disable-controls': 'onDisableControls'
|
||||
'level:enable-controls': 'onEnableControls'
|
||||
'surface:frame-changed': 'onFrameChanged'
|
||||
'level:set-letterbox': 'onSetLetterbox'
|
||||
'tome:thang-list-entry-popover-shown': 'onThangListEntryPopoverShown'
|
||||
'surface:coordinates-shown': 'onSurfaceCoordinatesShown'
|
||||
|
||||
events:
|
||||
'click': 'onClick'
|
||||
'mouseenter': 'onMouseEnter'
|
||||
'mouseleave': 'onMouseLeave'
|
||||
|
||||
constructor: (options) ->
|
||||
super options
|
||||
@thang = options.thang
|
||||
@spells = options.spells
|
||||
@permission = options.permission
|
||||
@reasonsToBeDisabled = {}
|
||||
@sortSpells()
|
||||
|
||||
getRenderData: (context={}) ->
|
||||
context = super context
|
||||
context.thang = @thang
|
||||
context.spell = @spells
|
||||
context
|
||||
|
||||
afterRender: ->
|
||||
super()
|
||||
@avatar?.destroy()
|
||||
@avatar = new ThangAvatarView thang: @thang, includeName: true, supermodel: @supermodel
|
||||
@$el.append @avatar.el # Before rendering, so render can use parent for popover
|
||||
@avatar.render()
|
||||
@avatar.setSharedThangs @spells.length # A bit weird to call it sharedThangs; could refactor if we like this
|
||||
@$el.toggle Boolean(@thang.exists)
|
||||
@$el.popover(
|
||||
animation: false
|
||||
html: true
|
||||
placement: 'bottom'
|
||||
trigger: 'manual'
|
||||
content: @getSpellListHTML()
|
||||
container: @$el.parent().parent().parent()
|
||||
)
|
||||
|
||||
sortSpells: ->
|
||||
return if @sorted
|
||||
# Keep only spells for which we have permissions
|
||||
spells = _.filter @spells, (s) => @options.permission and me.team in s.permissions[@options.permission]
|
||||
@spells = _.sortBy spells, @sortScoreForSpell
|
||||
@sorted = true
|
||||
|
||||
sortScoreForSpell: (s) =>
|
||||
# Sort by errored-out spells first, then spells shared with fewest other Thangs
|
||||
# Lower comes first
|
||||
score = 0
|
||||
# My errors are highest priority
|
||||
score -= 9001900190019001 * (s.thangs[@thang.id].aether?.getAllProblems().length or 0)
|
||||
# Other shared Thangs errors are also high priority
|
||||
score -= _.reduce s.thangs, (spellThang, num) -> 900190019001 * (spellThang.aether?.getAllProblems().length or 0)
|
||||
# Read-only spells at the bottom
|
||||
score += 90019001 unless s.canWrite()
|
||||
# The more Thangs sharing a spell, the lower
|
||||
score += 9001 * _.size(s.thangs)
|
||||
score
|
||||
|
||||
select: ->
|
||||
@sortSpells()
|
||||
Backbone.Mediator.publish 'level:select-sprite', thangID: @thang.id, spellName: @spells[0]?.name
|
||||
|
||||
onClick: (e) ->
|
||||
return unless @controlsEnabled
|
||||
@select()
|
||||
|
||||
onMouseEnter: (e) ->
|
||||
return unless @controlsEnabled and @spells.length
|
||||
@clearTimeouts()
|
||||
@showSpellsTimeout = _.delay @showSpells, 100
|
||||
|
||||
onMouseLeave: (e) ->
|
||||
return unless @controlsEnabled and @spells.length
|
||||
@clearTimeouts()
|
||||
@hideSpellsTimeout = _.delay @hideSpells, 100
|
||||
|
||||
clearTimeouts: ->
|
||||
clearTimeout @showSpellsTimeout if @showSpellsTimeout
|
||||
clearTimeout @hideSpellsTimeout if @hideSpellsTimeout
|
||||
@showSpellsTimeout = @hideSpellsTimeout = null
|
||||
|
||||
onThangListEntryPopoverShown: (e) ->
|
||||
# I couldn't figure out how to get the mouseenter / mouseleave to always work, so this is a fallback
|
||||
# to hide our popover if another Thang's popover gets shown.
|
||||
return if e.entry is @
|
||||
@hideSpells()
|
||||
|
||||
onSurfaceCoordinatesShown: (e) ->
|
||||
# Definitely aren't hovering over this.
|
||||
@hideSpells()
|
||||
|
||||
showSpells: =>
|
||||
@clearTimeouts()
|
||||
@sortSpells()
|
||||
@$el.data('bs.popover').options.content = @getSpellListHTML()
|
||||
@$el.popover('setContent').popover('show')
|
||||
@$el.parent().parent().parent().i18n()
|
||||
@popover = @$el.parent().parent().parent().find('.popover')
|
||||
@popover.off 'mouseenter mouseleave'
|
||||
@popover.mouseenter (e) => @showSpells() if @controlsEnabled
|
||||
@popover.mouseleave (e) => @hideSpells()
|
||||
thangID = @thang.id
|
||||
@popover.find('code').click (e) ->
|
||||
Backbone.Mediator.publish 'level:select-sprite', thangID: thangID, spellName: $(@).data 'spell-name'
|
||||
Backbone.Mediator.publish 'tome:thang-list-entry-popover-shown', entry: @
|
||||
|
||||
hideSpells: =>
|
||||
@clearTimeouts()
|
||||
@$el.popover('hide')
|
||||
|
||||
getSpellListHTML: ->
|
||||
spellsPopoverTemplate {spells: @spells}
|
||||
|
||||
onProblemsUpdated: (e) ->
|
||||
return unless e.spell in @spells
|
||||
@sorted = false
|
||||
|
||||
onSetLetterbox: (e) ->
|
||||
if e.on then @reasonsToBeDisabled.letterbox = true else delete @reasonsToBeDisabled.letterbox
|
||||
@updateControls()
|
||||
|
||||
onDisableControls: (e) ->
|
||||
return if e.controls and not ('surface' in e.controls) # disable selection?
|
||||
@reasonsToBeDisabled.controls = true
|
||||
@updateControls()
|
||||
|
||||
onEnableControls: (e) ->
|
||||
delete @reasonsToBeDisabled.controls
|
||||
@updateControls()
|
||||
|
||||
updateControls: ->
|
||||
enabled = _.keys(@reasonsToBeDisabled).length is 0
|
||||
return if enabled is @controlsEnabled
|
||||
@controlsEnabled = enabled
|
||||
@$el.toggleClass('disabled', not enabled)
|
||||
|
||||
onFrameChanged: (e) ->
|
||||
# Optimize
|
||||
return unless currentThang = e.world.thangMap[@thang.id]
|
||||
exists = Boolean currentThang.exists
|
||||
if @thangDidExist isnt exists
|
||||
@$el.toggle exists
|
||||
@thangDidExist = exists
|
||||
dead = exists and currentThang.health <= 0
|
||||
if @thangWasDead isnt dead
|
||||
@$el.toggleClass 'dead', dead
|
||||
@thangWasDead = dead
|
||||
|
||||
destroy: ->
|
||||
@avatar?.destroy()
|
||||
@popover?.remove()
|
||||
@popover?.off 'mouseenter mouseleave'
|
||||
@popover?.find('code').off 'click'
|
||||
super()
|
|
@ -1,95 +0,0 @@
|
|||
# The ThangListView lives in the code area behind the SpellView, so that when you don't have a spell, you can select any Thang.
|
||||
# It just ha a bunch of ThangListEntryViews (which are mostly ThangAvatarViews) in a few sections.
|
||||
|
||||
CocoView = require 'views/kinds/CocoView'
|
||||
template = require 'templates/play/level/tome/thang_list'
|
||||
{me} = require 'lib/auth'
|
||||
ThangListEntryView = require './ThangListEntryView'
|
||||
|
||||
module.exports = class ThangListView extends CocoView
|
||||
className: 'thang-list-view'
|
||||
id: 'thang-list-view'
|
||||
template: template
|
||||
|
||||
constructor: (options) ->
|
||||
super options
|
||||
@spells = options.spells
|
||||
@thangs = _.filter options.thangs, 'isSelectable'
|
||||
@sortThangs()
|
||||
|
||||
sortThangs: ->
|
||||
@readwriteThangs = _.sortBy _.filter(@thangs, (thang) =>
|
||||
return true for spellKey, spell of @spells when thang.id of spell.thangs and spell.canWrite()
|
||||
false
|
||||
), @sortScoreForThang
|
||||
@readThangs = _.sortBy _.filter(@thangs, (thang) =>
|
||||
return true for spellKey, spell of @spells when thang.id of spell.thangs and spell.canRead() and not spell.canWrite()
|
||||
false
|
||||
), @sortScoreForThang
|
||||
@muggleThangs = _.sortBy _.without(@thangs, @readwriteThangs..., @readThangs...), @sortScoreForThang
|
||||
if @muggleThangs.length > 15
|
||||
@muggleThangs = [] # Don't render a zillion of these. Slow, too long, maybe not useful.
|
||||
|
||||
sortScoreForThang: (t) =>
|
||||
# Sort by my team, then most spells and fewest shared Thangs per spell,
|
||||
# then by thang.spriteName alpha, then by thang.id alpha.
|
||||
# Lower comes first
|
||||
score = 0
|
||||
# Thangs on my team are highest priority
|
||||
score -= 9001900190019001 if t.team is me.team
|
||||
# The more spells per Thang, the lower
|
||||
score -= 900190019001 for spellKey, spell of @spells when t.id of spell.thangs and spell.canRead()
|
||||
# The more Thangs per spell, the higher
|
||||
score += 90019001 for t2 of spell.thangs for spellKey, spell of @spells when t.id of spell.thangs
|
||||
alpha = (s) -> _.reduce [0 ... s.length], ((acc, i) -> acc + s.charCodeAt(i) / Math.pow(100, i)), 0
|
||||
# Alpha by spriteName
|
||||
score += 9001 * alpha t.spriteName
|
||||
# Alpha by id
|
||||
score += alpha t.id
|
||||
score
|
||||
|
||||
afterRender: ->
|
||||
super()
|
||||
@addThangListEntries()
|
||||
|
||||
addThangListEntries: ->
|
||||
@entries = []
|
||||
for [thangs, section, permission] in [
|
||||
[@readwriteThangs, '#readwrite-thangs', 'readwrite'] # Your Minions
|
||||
[@readThangs, '#read-thangs', 'read'] # Read-Only
|
||||
[@muggleThangs, '#muggle-thangs', null] # Non-Castable
|
||||
]
|
||||
section = @$el.find(section).toggle thangs.length > 0
|
||||
for thang in thangs
|
||||
spells = _.filter @spells, (s) -> thang.id of s.thangs
|
||||
entry = new ThangListEntryView thang: thang, spells: spells, permission: permission, supermodel: @supermodel
|
||||
section.find('.thang-list').append entry.el # Render after appending so that we can access parent container for popover
|
||||
entry.render()
|
||||
@entries.push entry
|
||||
|
||||
topSpellForThang: (thang) ->
|
||||
for entry in @entries when entry.thang.id is thang.id
|
||||
return entry.spells[0]
|
||||
null
|
||||
|
||||
selectPrimarySprite: ->
|
||||
@entries[0]?.select()
|
||||
|
||||
adjustThangs: (spells, thangs) ->
|
||||
# TODO: it would be nice to not have to do this any more, like if we migrate to the hero levels.
|
||||
# Recreating all the ThangListEntryViews and their ThangAvatarViews is pretty slow.
|
||||
# So they aren't even kept up-to-date during world streaming.
|
||||
# Updating the existing subviews? Would be kind of complicated to get all the new thangs and spells propagated.
|
||||
# I would do it, if I didn't think we were perhaps soon to not do the ThangList any more.
|
||||
# Will temporary reduce the number of muggle thangs we're willing to draw.
|
||||
@spells = @options.spells = spells
|
||||
for entry in @entries
|
||||
entry.$el.remove()
|
||||
entry.destroy()
|
||||
@thangs = @options.thangs = thangs
|
||||
@sortThangs()
|
||||
@addThangListEntries()
|
||||
|
||||
destroy: ->
|
||||
entry.destroy() for entry in @entries
|
||||
super()
|
|
@ -32,7 +32,6 @@ template = require 'templates/play/level/tome/tome'
|
|||
{me} = require 'lib/auth'
|
||||
Spell = require './Spell'
|
||||
SpellListView = require './SpellListView'
|
||||
ThangListView = require './ThangListView'
|
||||
SpellPaletteView = require './SpellPaletteView'
|
||||
CastButtonView = require './CastButtonView'
|
||||
|
||||
|
@ -62,8 +61,7 @@ module.exports = class TomeView extends CocoView
|
|||
#programmableThangs = _.filter @options.thangs, (t) -> t.isProgrammable and t.spriteName isnt 'Hero Placeholder'
|
||||
programmableThangs = _.filter @options.thangs, 'isProgrammable'
|
||||
@createSpells programmableThangs, programmableThangs[0]?.world # Do before spellList, thangList, and castButton
|
||||
@spellList = @insertSubView new SpellListView spells: @spells, supermodel: @supermodel
|
||||
@thangList = @insertSubView new ThangListView spells: @spells, thangs: @options.thangs, supermodel: @supermodel unless @options.level.get('type', true) is 'hero'
|
||||
@spellList = @insertSubView new SpellListView spells: @spells, supermodel: @supermodel, level: @options.level
|
||||
@castButton = @insertSubView new CastButtonView spells: @spells, levelID: @options.levelID
|
||||
@teamSpellMap = @generateTeamSpellMap(@spells)
|
||||
unless programmableThangs.length
|
||||
|
@ -77,7 +75,6 @@ module.exports = class TomeView extends CocoView
|
|||
thangs = _.filter e.world.thangs, 'inThangList'
|
||||
programmableThangs = _.filter thangs, 'isProgrammable'
|
||||
@createSpells programmableThangs, e.world
|
||||
@thangList?.adjustThangs @spells, thangs
|
||||
@spellList.adjustSpells @spells
|
||||
|
||||
onCommentMyCode: (e) ->
|
||||
|
@ -187,7 +184,6 @@ module.exports = class TomeView extends CocoView
|
|||
@spellPaletteView = null
|
||||
@$el.find('#spell-palette-view').hide()
|
||||
@castButton?.$el.hide()
|
||||
@thangList?.$el.show()
|
||||
|
||||
onSpriteSelected: (e) ->
|
||||
return if @spellView and @options.level.get('type', true) in ['hero', 'hero-ladder', 'hero-coop'] # Never deselect the hero in the Tome.
|
||||
|
@ -207,7 +203,6 @@ module.exports = class TomeView extends CocoView
|
|||
@$el.find('#' + @spellView.id).after(@spellView.el).remove()
|
||||
@$el.find('#' + @spellTabView.id).after(@spellTabView.el).remove()
|
||||
@castButton.attachTo @spellView
|
||||
@thangList?.$el.hide()
|
||||
Backbone.Mediator.publish 'tome:spell-shown', thang: thang, spell: spell
|
||||
@updateSpellPalette thang, spell
|
||||
@spellList.setThangAndSpell thang, spell
|
||||
|
@ -217,7 +212,7 @@ module.exports = class TomeView extends CocoView
|
|||
updateSpellPalette: (thang, spell) ->
|
||||
return unless thang and @spellPaletteView?.thang isnt thang and thang.programmableProperties or thang.apiProperties
|
||||
@spellPaletteView = @insertSubView new SpellPaletteView thang: thang, supermodel: @supermodel, programmable: spell?.canRead(), language: spell?.language ? @options.session.get('codeLanguage'), session: @options.session, level: @options.level
|
||||
@spellPaletteView.toggleControls {}, spell.view.controlsEnabled if spell # TODO: know when palette should have been disabled but didn't exist
|
||||
@spellPaletteView.toggleControls {}, spell.view.controlsEnabled if spell?.view # TODO: know when palette should have been disabled but didn't exist
|
||||
|
||||
spellFor: (thang, spellName) ->
|
||||
return null unless thang?.isProgrammable
|
||||
|
@ -225,9 +220,6 @@ module.exports = class TomeView extends CocoView
|
|||
selectedThangSpells = (@spells[spellKey] for spellKey in @thangSpells[thang.id])
|
||||
if spellName
|
||||
spell = _.find selectedThangSpells, {name: spellName}
|
||||
else if @thangList
|
||||
spell = @thangList.topSpellForThang thang
|
||||
#spell = selectedThangSpells[0] # TODO: remember last selected spell for this thang
|
||||
else
|
||||
spell = _.find selectedThangSpells, (spell) -> true # Just grab one
|
||||
spell
|
||||
|
@ -241,10 +233,8 @@ module.exports = class TomeView extends CocoView
|
|||
@cast()
|
||||
|
||||
onSelectPrimarySprite: (e) ->
|
||||
if @thangList
|
||||
@thangList.selectPrimarySprite()
|
||||
else
|
||||
Backbone.Mediator.publish 'level:select-sprite', thangID: 'Hero Placeholder'
|
||||
# TODO: this may not be correct
|
||||
Backbone.Mediator.publish 'level:select-sprite', thangID: 'Hero Placeholder'
|
||||
|
||||
destroy: ->
|
||||
spell.destroy() for spellKey, spell of @spells
|
||||
|
|