Add basic support for displaying multiblock steps

This commit is contained in:
Andrew Miner
2015-11-22 22:33:15 -08:00
parent 8cdd130064
commit 7dbfd25ef3
12 changed files with 342 additions and 42 deletions
+17 -23
View File
@@ -107,30 +107,24 @@ module.exports = class BaseController extends backbone.View
# Property Methods #############################################################################
getModel: ->
return @_model
setModel: (newModel)->
return if @model is newModel
newModel = @onWillChangeModel @_model, newModel
@_model = newModel
@tryRefresh()
isRendered: ->
return @_rendered
getUser: ->
return @_user
setUser: (user)->
@_user = user
@tryRefresh()
Object.defineProperties @prototype,
model: {get:@prototype.getModel, set:@prototype.setModel}
rendered: {get:@prototype.isRendered }
user: {get:@prototype.getUser, set:@prototype.setUser}
model:
get: -> @_model
set: (newModel)->
return if @model is newModel
newModel = @onWillChangeModel @_model, newModel
@_model = newModel
@tryRefresh()
rendered:
get: -> @_rendered
user:
get: -> @_user
set: (newUser)->
@_user = newUser
@tryRefresh()
# Backbone.View Overrides ######################################################################
@@ -5,24 +5,25 @@ Copyright (c) 2015 by Redwood Labs
All rights reserved.
###
AdsenseController = require './adsense_controller'
EditableFile = require '../models/editable_file'
FullRecipeController = require './full_recipe_controller'
ImageLoader = require './image_loader'
Item = require '../models/item'
ItemGroupController = require './item_group_controller'
ItemPage = require '../models/item_page'
ItemSlug = require '../models/item_slug'
MarkdownSectionController = require './markdown_section_controller'
PageController = require './page_controller'
VideoController = require './video_controller'
_ = require 'underscore'
w = require 'when'
{Duration} = require '../constants'
{Event} = require '../constants'
{GitHub} = require '../constants'
{Text} = require '../constants'
{Url} = require '../constants'
_ = require 'underscore'
AdsenseController = require './adsense_controller'
{Duration} = require '../constants'
EditableFile = require '../models/editable_file'
{Event} = require '../constants'
FullRecipeController = require './full_recipe_controller'
{GitHub} = require '../constants'
ImageLoader = require './image_loader'
Item = require '../models/item'
ItemGroupController = require './item_group_controller'
ItemPage = require '../models/item_page'
ItemSlug = require '../models/item_slug'
MarkdownSectionController = require './markdown_section_controller'
MultiblockViewerController = require './multiblock_viewer_controller'
PageController = require './page_controller'
{Text} = require '../constants'
{Url} = require '../constants'
VideoController = require './video_controller'
w = require 'when'
########################################################################################################################
@@ -77,6 +78,7 @@ module.exports = class ItemPageController extends PageController
@adsenseController = @addChild AdsenseController, '.view__adsense', model:'sidebar_skyscraper'
options = imageLoader:@imageLoader, modPack:@modPack, show:false
@_multiblockController = @addChild MultiblockViewerController, '.view__multiblock_viewer', options
@_similarItemsController = @addChild ItemGroupController, '.view__item_group.similar', options
@_usedAsToolToMakeController = @addChild ItemGroupController, '.view__item_group.usedAsToolToMake', options
@_usedToMakeController = @addChild ItemGroupController, '.view__item_group.usedToMake', options
@@ -91,6 +93,7 @@ module.exports = class ItemPageController extends PageController
@$byline = @$('.byline')
@$bylineLink = @$('.byline a')
@$descriptionSection = @$('.description')
@$multiblockSection = @$('.multiblock.section')
@$name = @$('h1.name')
@$officialPageLink = @$('a.officialPage')
@$recipeContainer = @$('.recipes .panel')
@@ -127,6 +130,7 @@ module.exports = class ItemPageController extends PageController
@_refreshByline()
@_refreshDescription()
@_refreshMultiblock()
@_refreshRecipes()
@_refreshSimilarItems()
@_refreshUsedAsToolToMake()
@@ -217,6 +221,13 @@ module.exports = class ItemPageController extends PageController
@_descriptionController.model = @model.item.description
@_descriptionController.resetToDefaultState()
_refreshMultiblock: ->
if @model.item?.multiblock?
@_multiblockController.model = @model.item.multiblock
@show @$multiblockSection
else
@hide @$multiblockSection
_refreshRecipes: ->
@_recipeControllers ?= []
index = 0
@@ -0,0 +1,156 @@
###
Crafting Guide - multiblock_controller.coffee
Copyright (c) 2014-2015 by Redwood Labs
All rights reserved.
###
$ = require 'jquery'
_ = require '../underscore_mixins'
BaseController = require './base_controller'
########################################################################################################################
module.exports = class MultiblockController extends BaseController
@::IMAGE_SIZE = 48 # px
@::X_LAYER_H_SHIFT = -24 # px
@::Z_LAYER_H_SHIFT = +24 # px
@::X_LAYER_V_SHIFT = -12 # px
@::Y_LAYER_V_SHIFT = -30 # px
@::Z_LAYER_V_SHIFT = -12 # px
@::MAX_DROP_DELAY = 250 # ms
constructor: (options={})->
if not options.imageLoader? then throw new Error 'options.imageLoader is required'
if not options.modPack? then throw new Error 'options.modPack is required'
options.templateName = 'multiblock'
super options
@_currentLayer = 0
@_blockCache = null
@_imageLoader = options.imageLoader
@_modPack = options.modPack
# Public Methods ###############################################################################
goBackLayer: ->
@_currentLayer = Math.max 0, @_currentLayer - 1
@_refreshAllBlocks()
goNextLayer: ->
@_currentLayer = Math.min @model.height - 1, @_currentLayer + 1
@_refreshAllBlocks()
hasBackLayer: ->
return false unless @model?
return @_currentLayer > 0
hasNextLayer: ->
return false unless @model?
return @_currentLayer < @model.height - 1
# BaseController Overrides #####################################################################
onDidRender: ->
# do nothing
refresh: ->
@$el.css 'min-height':@_computeMinHeight(), 'min-width':@_computeMinWidth()
@_refreshBlockCache()
@_refreshAllBlocks()
# Private Methods ##############################################################################
_computePosition: (x, y, z, options={})->
if not @model? then return left:0, top:-@IMAGE_SIZE, 'z-index':0, opacity:0.0
options.hideUpperLayers ?= false
pxWidth = @$el.width()
pxHeight = @$el.height()
left = ((pxWidth - @IMAGE_SIZE) / 2) + (x * @X_LAYER_H_SHIFT) + (z * @Z_LAYER_H_SHIFT)
if options.hideUpperLayers and y > @_currentLayer
top = 0
opacity = 0.0
else
top = (pxHeight - @IMAGE_SIZE) + (x * @X_LAYER_V_SHIFT) + (z * @Z_LAYER_V_SHIFT) + (y * @Y_LAYER_V_SHIFT)
opacity = 1.0
zindex = (@model.width - x) + (@model.depth - z) + ((@model.width * @model.depth) * y)
return left:left, top:top, 'z-index':zindex, opacity:opacity
_computeMinHeight: ->
return 0 unless @model?
minHeight = Math.max(Math.abs(@model.width * @X_LAYER_V_SHIFT), Math.abs(@model.depth * @Z_LAYER_V_SHIFT))
minHeight += Math.abs(@model.height * @Y_LAYER_V_SHIFT)
minHeight += 2 * @IMAGE_SIZE
return minHeight
_computeMinWidth: ->
return 0 unless @model?
leftPosition = @_computePosition @model.width, 0, 0
rightPosition = @_computePosition 0, 0, @model.depth
return rightPosition.left - leftPosition.left
_randomDropDelay: ->
return Math.random() * @MAX_DROP_DELAY
_refreshBlockCache: ->
@_blockCache = null
return unless @model?
@_blockCache = width:@model.width, height:@model.height, depth:@model.depth
for x in [0...@model.width]
@_blockCache[x] ?= {}
for y in [0...@model.height]
@_blockCache[x][y] ?= {}
for z in [0...@model.depth]
@_blockCache[x][y][z] ?= null
for el in @$('.block')
$el = $(el)
@_blockCache[$el.data('x')][$el.data('y')][$el.data('z')] = $el
_refreshBlock: (x, y, z)->
return unless @model?
stack = @model.getStackAt x, y, z
$block = @_blockCache[x][y][z]
position = @_computePosition x, y, z, hideUpperLayers:true
move = false
if stack?
itemDisplay = @_modPack.findItemDisplay stack.itemSlug
if not $block?
$block = $("<img alt='#{itemDisplay.itemName}' class='block' />")
$block.css position, top:-@IMAGE_SIZE, opacity:0.0
@_imageLoader.load itemDisplay.iconUrl, $block
@_blockCache[x][y][z] = $block
@$el.append $block
move = true
else
$block.attr 'src', itemDisplay.iconUrl
move = true
else if $block?
$block.attr 'src', ''
move = true
if move then _.delay (-> $block.css position), @_randomDropDelay()
_refreshAllBlocks: ->
return unless @model?
for x in [0...@model.width]
for y in [0...@model.height]
for z in [0...@model.depth]
@_refreshBlock(x, y, z)
@@ -0,0 +1,68 @@
###
Crafting Guide - multiblock_viewer_controller.coffee
Copyright (c) 2014-2015 by Redwood Labs
All rights reserved.
###
_ = require '../underscore_mixins'
BaseController = require './base_controller'
MultiblockController = require './multiblock_controller'
########################################################################################################################
module.exports = class MultiblockViewerController extends BaseController
constructor: (options={})->
if not options.imageLoader? then throw new Error 'options.imageLoader is required'
if not options.modPack? then throw new Error 'options.modPack is required'
options.templateName = 'multiblock_viewer'
super options
@_imageLoader = options.imageLoader
@_modPack = options.modPack
# Event Methods ################################################################################
onBackClicked: ->
return if @backButton.hasClass 'disabled'
@multiblockController.goBackLayer()
@refresh()
onNextClicked: ->
return if @nextButton.hasClass 'disabled'
@multiblockController.goNextLayer()
@refresh()
# BaseController Overrides #####################################################################
onDidRender: ->
@multiblockController = @addChild MultiblockController, '.view__multiblock',
imageLoader: @_imageLoader
modPack: @_modPack
@backButton = @$('.button.back')
@nextButton = @$('.button.next')
super
refresh: ->
@multiblockController.model = @model
if @multiblockController.hasBackLayer()
@backButton.removeClass 'disabled'
else
@backButton.addClass 'disabled'
if @multiblockController.hasNextLayer()
@nextButton.removeClass 'disabled'
else
@nextButton.addClass 'disabled'
super
# Backbone.View Overrides ######################################################################
events: ->
_.extend super,
'click .button.back': 'onBackClicked'
'click .button.next': 'onNextClicked'