Adjust animations, fix bugs, and tweak a few algos

* Adjust page change animations to slide the page closed and then
  open again.
* Add Railcraft to the standard set of mods
* Change every controller which uses an `ImageLoader` to only accept
  it from a parent controller (with the router creating the one
  shared instance).
* Fix several places where controllers need to refresh when the mod
  pack changes
* Fix a few places which should be using the `ImageLoader` but were
  not.
* Remove a number of animations which caused performance issues (esp.
  animating individual items in item group views).
* Fix a bug where changing the current version of a mod didn't cause
  the current crafting plan to be re-evaluated
* Simplify the name finder to allow regular expressions instead of
  the current algorithm
This commit is contained in:
Andrew Miner
2015-02-22 21:31:48 -08:00
parent 87d1868c81
commit 9f0d19d9e4
21 changed files with 128 additions and 102 deletions
+2
View File
@@ -6,6 +6,8 @@ All rights reserved.
*/
.view__item_page {
display: none;
& > div {
vertical-align: top;
display: inline-block;
+2
View File
@@ -6,6 +6,8 @@ All rights reserved.
*/
.view__mod_page {
display: none;
& > div {
vertical-align: top;
display: inline-block;
+1
View File
@@ -12,6 +12,7 @@ exports.DefaultMods = [
'buildcraft',
'enderio',
'industrial_craft_2',
'railcraft',
'thermal_expansion',
]
@@ -7,6 +7,7 @@ All rights reserved.
BaseController = require './base_controller'
{Duration} = require '../constants'
{Event} = require '../constants'
ImageLoader = require './image_loader'
########################################################################################################################
@@ -14,8 +15,8 @@ ImageLoader = require './image_loader'
module.exports = class CraftingGridController 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.imageLoader ?= new ImageLoader defaultUrl:'/images/unknown.png'
options.templateName = 'crafting_grid'
super options
@@ -23,6 +24,8 @@ module.exports = class CraftingGridController extends BaseController
@_modPack = options.modPack
@_slotCount = 9
@_modPack.on Event.change, => @tryRefresh()
# BaseController Methods #######################################################################
onDidRender: ->
@@ -22,10 +22,10 @@ Storage = require '../models/storage'
module.exports = class CraftingPageController 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.model ?= new CraftingPage modPack:options.modPack
options.imageLoader ?= new ImageLoader defaultUrl:'/images/unknown.png'
options.storage ?= new Storage storage:window.localStorage
options.templateName = 'crafting_page'
super options
@@ -7,6 +7,7 @@ All rights reserved.
BaseController = require './base_controller'
{Duration} = require '../constants'
{Event} = require '../constants'
ImageLoader = require './image_loader'
MinimalRecipeController = require './minimal_recipe_controller'
@@ -15,14 +16,14 @@ MinimalRecipeController = require './minimal_recipe_controller'
module.exports = class CraftingTableController extends BaseController
constructor: (options={})->
if not options.imageLoader? then throw new Error 'options.imageLoader is required'
if not options.model? then throw new Error 'options.model is required'
if not options.modPack? then throw new Error 'options.modPack is required'
options.imageLoader ?= new ImageLoader defaultUrl:'/images/unknown.png'
options.templateName = 'crafting_table'
super options
@_imageLoader = options.imageLoader
@_modPack = options.modPack
@imageLoader = options.imageLoader
@modPack = options.modPack
# Event Methods ################################################################################
@@ -42,7 +43,7 @@ module.exports = class CraftingTableController extends BaseController
# BaseController Overrides #####################################################################
onDidRender: ->
@recipeController = @addChild MinimalRecipeController, '.view__minimal_recipe', imageLoader:@_imageLoader, modPack:@_modPack
@recipeController = @addChild MinimalRecipeController, '.view__minimal_recipe', imageLoader:@imageLoader, modPack:@modPack
@$next = @$('.next')
@$prev = @$('.prev')
@@ -17,12 +17,12 @@ InventoryTableController = require './inventory_table_controller'
module.exports = class FullRecipeController 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.imageLoader ?= new ImageLoader defaultUrl:'/images/unknown.png'
options.templateName = 'full_recipe'
super options
@_imageLoader = options.imageLoader
@imageLoader = options.imageLoader
@modPack = options.modPack
# BaseController Overrides #####################################################################
@@ -30,17 +30,19 @@ module.exports = class FullRecipeController extends BaseController
onDidRender: ->
@gridController = @addChild CraftingGridController, '.view__crafting_grid',
modPack: @modPack
imageLoader: @_imageLoader
imageLoader: @imageLoader
@inputController = @addChild InventoryTableController, '.input .view__inventory_table',
editable: false
model: new Inventory
modPack: @modPack
editable: false
imageLoader: @imageLoader
model: new Inventory
modPack: @modPack
@outputController = @addChild InventoryTableController, '.output .view__inventory_table',
editable: false
model: new Inventory
modPack: @modPack
editable: false
imageLoader: @imageLoader
model: new Inventory
modPack: @modPack
@$tool = @$('.tool p')
super
@@ -19,12 +19,13 @@ module.exports = class InventoryController extends BaseController
@ONLY_DIGITS = /^[0-9]*$/
constructor: (options={})->
if not options.imageLoader? then throw new Error 'options.imageLoader is required'
if not options.model? then throw new Error 'options.model is required'
if not options.modPack? then throw new Error 'options.modPack is required'
@editable = options.editable ?= true
@icon = options.icon ?= '/images/chest_front.png'
@imageLoader = options.imageLoader ?= new ImageLoader defaultUrl:'/images/unknown.png'
@imageLoader = options.imageLoader
@modPack = options.modPack
@nameFinder = options.nameFinder ?= new NameFinder options.modPack
@onChange = options.onChange ?= -> # do nothing
@@ -168,6 +169,7 @@ module.exports = class InventoryController extends BaseController
minLength: 0
change: onChanged
close: onChanged
minLength: 3
select: onSelected
_refreshStacks: ->
@@ -185,7 +187,9 @@ module.exports = class InventoryController extends BaseController
modPack: @modPack
onRemove: if not @editable then null else (stack)=> @_removeStack(stack)
controller.render()
controller.$el.hide()
controller.$el.insertBefore $lastRow
controller.$el.slideDown duration:Duration.fast
@_stackControllers.push controller
else
controller.model = stack
@@ -20,11 +20,12 @@ module.exports = class InventoryTableController extends BaseController
@ONLY_DIGITS = /^[0-9]*$/
constructor: (options={})->
if not options.imageLoader? then throw new Error 'options.imageLoader is required'
if not options.model? then throw new Error 'options.model is required'
if not options.modPack? then throw new Error 'options.modPack is required'
@editable = options.editable ?= true
@imageLoader = options.imageLoader ?= new ImageLoader defaultUrl:'/images/unknown.png'
@imageLoader = options.imageLoader
@modPack = options.modPack
@nameFinder = options.nameFinder ?= new NameFinder options.modPack
@onChange = options.onChange ?= -> # do nothing
@@ -127,14 +128,13 @@ module.exports = class InventoryTableController extends BaseController
$lastRow = @$table.find 'tr:last-child'
@_stackControllers = []
@model.each (stack)=>
options =
controller = new StackController
editable: @editable
imageLoader: @imageLoader
model: stack
modPack: @modPack
onRemove: if not @editable then null else (stack)=> @_removeStack(stack)
controller = new StackController options
controller.render()
controller.$el.insertBefore $lastRow
@_stackControllers.push controller
@@ -12,12 +12,14 @@ BaseController = require './base_controller'
module.exports = class ItemController extends BaseController
constructor: (options={})->
if not options.imageLoader? then throw new Error 'options.imageLoader is required'
if not options.model? then throw new Error 'options.model is required'
if not options.modPack? then throw new Error 'options.modPack is required'
options.templateName = 'item'
super options
@_modPack = options.modPack
@_imageLoader = options.imageLoader
@_modPack = options.modPack
# BaseController Overrides #####################################################################
@@ -30,7 +32,7 @@ module.exports = class ItemController extends BaseController
refresh: ->
display = @_modPack.findItemDisplay @model.slug
@$icon.attr 'src', display.iconUrl
@_imageLoader.load display.iconUrl, @$icon
@$name.html display.itemName
@$nameLink.attr 'href', display.itemUrl
@@ -16,12 +16,14 @@ ItemController = require './item_controller'
module.exports = class ItemGroupController 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.title ?= ''
options.templateName = 'item_group'
super options
@_delayStep = 20
@_imageLoader = options.imageLoader
@_itemControllers = []
@_modPack = options.modPack
@_title = options.title
@@ -53,14 +55,12 @@ module.exports = class ItemGroupController extends BaseController
# Private Methods ##############################################################################
_createItemController: (item, delay)->
controller = new ItemController model:item, modPack:@_modPack
controller = new ItemController imageLoader:@_imageLoader, model:item, modPack:@_modPack
@_itemControllers.push controller
attachController = =>
controller.render()
controller.$el.hide()
@$items.append controller.$el
controller.$el.fadeIn duration:Duration.fast
_.delay attachController, delay
@@ -81,4 +81,4 @@ module.exports = class ItemGroupController extends BaseController
while @_itemControllers.length > controllerIndex
controller = @_itemControllers.pop()
controller.$el.fadeOut duration:Duration.normal, complete:-> @remove()
controller.$el.slideUp duration:Duration.normal, complete:-> @remove()
@@ -21,10 +21,10 @@ ItemPage = require '../models/item_page'
module.exports = class ItemPageController extends BaseController
constructor: (options={})->
if not options.modPack? then throw new Error 'options.modPack is required'
if not options.itemSlug? then throw new Error 'options.itemSlug is required'
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.imageLoader ?= new ImageLoader defaultUrl:'/images/unknown.png'
options.model ?= new ItemPage modPack:options.modPack
options.templateName ?= 'item_page'
@@ -34,23 +34,27 @@ module.exports = class ItemPageController extends BaseController
@_itemSlug = options.itemSlug
@_modPack = options.modPack
@_modPack.on Event.change, => @refresh()
@_modPack.on Event.change, => @tryRefresh()
# BaseController Overrides #####################################################################
onDidRender: ->
@_similarItemsController = @addChild ItemGroupController, '.similar .view__item_group', modPack:@_modPack
@_usedToMakeController = @addChild ItemGroupController, '.usedToMake .view__item_group', modPack:@_modPack
@_similarItemsController = @addChild ItemGroupController, '.similar .view__item_group',
imageLoader: @_imageLoader
modPack: @_modPack
@_usedToMakeController = @addChild ItemGroupController, '.usedToMake .view__item_group',
imageLoader: @_imageLoader
modPack: @_modPack
@$byline = @$('.byline')
@$bylineLink = @$('.byline a')
@$craftingPlanLink = @$('a.craftingPlan')
@$name = @$('h1.name')
@$recipeContainer = @$('.recipes .panel')
@$recipesSection = @$('.recipes')
@$similarContainer = @$('.similar')
@$titleImage = @$('.titleImage img')
@$usedToMakeContainer = @$('.usedToMake')
@$byline = @$('.byline')
@$bylineLink = @$('.byline a')
@$craftingPlanLink = @$('a.craftingPlan')
@$name = @$('h1.name')
@$recipeContainer = @$('.recipes .panel')
@$recipesSection = @$('.recipes')
@$similarSection = @$('.similar')
@$titleImage = @$('.titleImage img')
@$usedToMakeSection = @$('.usedToMake')
super
refresh: ->
@@ -60,13 +64,13 @@ module.exports = class ItemPageController extends BaseController
if @model.item?
display = @_modPack.findItemDisplay @model.item.slug
@$craftingPlanLink.attr href:display.craftingUrl
@$craftingPlanLink.fadeIn duration:Duration.normal
@$craftingPlanLink.fadeIn duration:Duration.fast
@_imageLoader.load display.iconUrl, @$titleImage
@$name.html display.itemName
@$el.slideDown duration:Duration.normal
else
@$craftingPlanLink.fadeOut duration:Duration.normal
@$titleImage.removeAttr 'src'
@$name.html ''
@$el.slideUp duration:Duration.normal
@_refreshByline()
@_refreshRecipes()
@@ -89,18 +93,18 @@ module.exports = class ItemPageController extends BaseController
if mod?.name?.length > 0
@$bylineLink.attr 'href', Url.mod modSlug:mod.slug
@$bylineLink.html mod.name
@$byline.fadeIn duration:Duration.normal
@$byline.fadeIn duration:Duration.fast
else
@$byline.fadeOut duration:Duration.normal
@$byline.fadeOut duration:Duration.fast
_refreshUsedToMake: ->
@_usedToMakeController.title = 'Used to Make'
@_usedToMakeController.model = @model.findComponentInItems()
if @_usedToMakeController.model?
@$usedToMakeContainer.fadeIn duration:Duration.normal
@$usedToMakeSection.slideDown duration:Duration.normal
else
@$usedToMakeContainer.fadeOut duration:Duration.normal
@$usedToMakeSection.slideUp duration:Duration.normal
_refreshRecipes: ->
@_recipeControllers ?= []
@@ -108,26 +112,24 @@ module.exports = class ItemPageController extends BaseController
recipes = @model.findRecipes()
if recipes?
@$recipesSection.fadeIn duration:Duration.normal
@$recipesSection.slideDown duration:Duration.normal
for recipe in @model.findRecipes()
controller = @_recipeControllers[index]
if not controller?
controller = new FullRecipeController modPack:@_modPack, model:recipe
controller = new FullRecipeController imageLoader:@_imageLoader, modPack:@_modPack, model:recipe
@_recipeControllers.push controller
controller.render()
controller.$el.hide()
@$recipeContainer.append controller.$el
controller.$el.fadeIn duration:Duration.normal
else
controller.model = recipe
index++
else
@$recipesSection.fadeOut duration:Duration.normal
@$recipesSection.slideUp duration:Duration.normal
while @_recipeControllers.length > index
controller = @_recipeControllers.pop()
controller.fadeOut duration:Duration.normal, complete:-> controller.$el.remove()
controller.$el.slideUp duration:Duration.normal, complete:-> controller.$el.remove()
_refreshSimilarItems: ->
group = @model.item?.group
@@ -138,9 +140,9 @@ module.exports = class ItemPageController extends BaseController
@_similarItemsController.model = null
if @_similarItemsController.model?
@$similarContainer.fadeIn duration:Duration.normal
@$similarSection.slideDown duration:Duration.normal
else
@$similarContainer.fadeOut duration:Duration.normal
@$similarSection.slideUp duration:Duration.normal
_resolveItemSlug: ->
@model.item = @_modPack.findItem @_itemSlug, includeDisabled:true
@@ -15,8 +15,8 @@ ImageLoader = require './image_loader'
module.exports = class MinimalRecipeController 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.imageLoader ?= new ImageLoader defaultUrl:'/images/unknown.png'
options.templateName = 'minimal_recipe'
super options
@@ -29,6 +29,7 @@ module.exports = class ModController extends BaseController
onVersionChanged: ->
@model.activeVersion = @$version.val()
@_plan.removeUncraftableItems()
@_plan.craft()
# BaseController Overrides #####################################################################
@@ -19,15 +19,18 @@ ItemGroupController = require './item_group_controller'
module.exports = class ModPageController 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.delayStep ?= 10
options.templateName = 'mod_page'
super options
@imageLoader = options.imageLoader
@modPack = options.modPack
@_delayStep = options.delayStep
@_effectiveModVersion = null
@_groupControllers = []
@_modPack = options.modPack
Object.defineProperties this,
effectiveModVersion: {get:@_getEffectiveModVersion}
@@ -59,10 +62,15 @@ module.exports = class ModPageController extends BaseController
refresh: ->
$('title').html if @model? then "#{@model.name} | #{Text.title}" else Text.title
@$name.html if @model? then @model.name else ''
@$byline.html if @model? then "by #{@model.author}" else ''
@$titleImage.attr 'src', (if @model? then Url.modLogoImage(modSlug:@model.slug) else '')
@$description.html if @model? then @model.description else ''
if @model?
@$name.html @model.name
@$byline.html "by #{@model.author}"
@$titleImage.attr 'src', Url.modLogoImage modSlug:@model.slug
@$description.html @model.description
@$el.slideDown duration:Duration.normal
else
@$el.slideUp duration:Duration.normal
@_refreshLink @$homePageLink, @model.homePageUrl
@_refreshLink @$documentationLink, @model.documentationUrl
@@ -98,7 +106,11 @@ module.exports = class ModPageController extends BaseController
items = modVersion.allItemsInGroup group
if not controller?
title = if group is Item.Group.Other then 'Items' else group
controller = new ItemGroupController model:items, modPack:@_modPack, title:title
controller = new ItemGroupController
imageLoader: @imageLoader
model: items
modPack: @modPack
title: title
controller.render()
@$groupContainer.append controller.$el
@_groupControllers[groupIndex] = controller
@@ -114,10 +126,10 @@ module.exports = class ModPageController extends BaseController
_refreshLink: ($link, url)->
if url?
$link.fadeIn duration:Duration.normal
$link.slideDown duration:Duration.normal
$link.attr 'href', url
else
$link.fadeOut duration:Duration.normal
$link.sludeUp duration:Duration.normal
_refreshVersions: ->
@$versionSelector.empty()
@@ -6,6 +6,7 @@ All rights reserved.
###
BaseController = require './base_controller'
{Event} = require '../constants'
ImageLoader = require './image_loader'
########################################################################################################################
@@ -13,10 +14,10 @@ ImageLoader = require './image_loader'
module.exports = class StackController extends BaseController
constructor: (options={})->
if not options.imageLoader? then throw new Error 'options.imageLoader is required'
if not options.model? then throw new Error 'options.model is required'
if not options.modPack? then throw new Error 'options.modPack is required'
options.imageLoader ?= new ImageLoader defaultUrl:'/images/unknown.png'
options.editable ?= false
options.onRemove ?= (stack)-> # do nothing
options.templateName = 'stack'
@@ -27,6 +28,8 @@ module.exports = class StackController extends BaseController
@onRemove = options.onRemove
@_imageLoader = options.imageLoader
@modPack.on Event.change, => @tryRefresh()
# Event Methods ################################################################################
onRemoveClicked: ->
+8 -6
View File
@@ -13,6 +13,7 @@ CraftingPageController = require './controllers/crafting_page_controller'
HeaderController = require './controllers/header_controller'
ItemPageController = require './controllers/item_page_controller'
ItemSlug = require './models/item_slug'
ImageLoader = require './controllers/image_loader'
Mod = require './models/mod'
ModPack = require './models/mod_pack'
ModPageController = require './controllers/mod_page_controller'
@@ -31,9 +32,10 @@ module.exports = class CraftingGuideRouter extends Backbone.Router
@_lastReported = null
super options
@modPack = new ModPack
@storage = new Storage storage:window.localStorage
@_defaultOptions = modPack:@modPack, storage:@storage
@imageLoader = new ImageLoader defaultUrl:'/images/unknown.png'
@modPack = new ModPack
@storage = new Storage storage:window.localStorage
@_defaultOptions = imageLoader:@imageLoader, modPack:@modPack, storage:@storage
@headerController = new HeaderController el:'.view__header'
@@ -124,11 +126,11 @@ module.exports = class CraftingGuideRouter extends Backbone.Router
controller.$el.addClass 'page'
$pageContent.replaceWith controller.$el
controller.$el.fadeIn showDuration, ->
controller.$el.slideDown showDuration, ->
controller.onDidShow()
if @_controller?
showDuration = Duration.long
@_controller.$el.fadeOut showDuration, show
showDuration = showDuration / 2
@_controller.$el.slideUp showDuration, show
else
show()
+6 -10
View File
@@ -59,7 +59,7 @@ module.exports = class CraftingPlan extends BaseModel
item = @modPack.findItem stack.itemSlug
@need.add item.slug, stack.quantity
@steps = (recipe:recipe for recipeSlug, recipe of @steps)
@steps = (step for recipeSlug, step of @steps)
@_resolveNeeds()
@_removeExtraSteps()
@@ -97,10 +97,6 @@ module.exports = class CraftingPlan extends BaseModel
# Private Methods ##############################################################################
_addStep: (recipe)->
logger.verbose -> "adding step for: #{recipe.slug}"
@steps[recipe.slug] = recipe
_chooseRecipe: (item)->
recipes = @modPack.findRecipes item.slug
return null unless recipes? and recipes.length > 0
@@ -143,7 +139,8 @@ module.exports = class CraftingPlan extends BaseModel
for inputStack in recipe.input
@_findSteps inputStack.itemSlug, parentSteps
@_addStep recipe
logger.verbose -> "adding step for: #{recipe.slug}"
@steps[recipe.slug] = recipe:recipe, itemSlug:item.slug
foundValidRecipe = true
break
catch error
@@ -159,8 +156,8 @@ module.exports = class CraftingPlan extends BaseModel
throw new Error 'invalid recipe path'
_hasStep: (itemSlug)->
for recipeSlug, recipe of @steps
return true if recipe.produces itemSlug
for recipeSlug, step of @steps
return true if step.recipe.produces itemSlug
return false
_qualifyItemSlug: (itemSlug)->
@@ -176,9 +173,8 @@ module.exports = class CraftingPlan extends BaseModel
for i in [@steps.length-1..0] by -1
step = @steps[i]
recipe = step.recipe
stepItemSlug = @_qualifyItemSlug step.recipe.itemSlug
step.multiplier = Math.ceil(@need.quantityOf(stepItemSlug) / recipe.output[0].quantity)
step.multiplier = Math.ceil(@need.quantityOf(step.itemSlug) / recipe.output[0].quantity)
if @includingTools
for stack in recipe.tools
-1
View File
@@ -40,7 +40,6 @@ module.exports = class ItemPage extends BaseModel
result = []
@item.modVersion.eachItemInGroup @item.group, (item)=>
return if item is @item
result.push item
return null unless result.length > 0
+4 -15
View File
@@ -43,35 +43,24 @@ module.exports = class NameFinder
# Private Methods ##############################################################################
_isMatch: (name, hint)->
nameWords = name.split ' '
hintWords = hint.split ' '
for hintWord in hintWords
while true
return false if nameWords.length is 0
nameWord = nameWords.shift()
break if nameWord.indexOf(hintWord) is 0
return true
_findNames: (nameHint=null)->
names = []
nameMap = {}
hintRegex = new RegExp(nameHint, 'i') if nameHint?
@modPack.eachMod (mod)=>
return unless mod.enabled or @includeDisabledMods
mod.eachName (name, itemSlug)=>
return if nameMap[name]
return if nameMap[name]?
item = mod.findItem itemSlug
if not @includeGatherable
return unless item? and item.isCraftable
scanName = "#{mod.name} : #{name}"
if nameHint?
return unless @_isMatch scanName.toLowerCase(), nameHint
if hintRegex?
return unless hintRegex.test scanName
nameMap[name] = name
names.push value:name, label:scanName, mod:mod
+10 -5
View File
@@ -50,16 +50,21 @@ module.exports = class Recipe extends BaseModel
if aValue isnt bValue
return if aValue > bValue then -1 else +1
aValue = a.getInputCount()
bValue = b.getInputCount()
if aValue isnt bValue
return if aValue < bValue then -1 else +1
aValue = a.getOutputCount()
bValue = b.getOutputCount()
if aValue isnt bValue
return if aValue > bValue then -1 else +1
aValue = a.tools.length
bValue = b.tools.length
if aValue isnt bValue
return if aValue < bValue then -1 else +1
aValue = a.getInputCount()
bValue = b.getInputCount()
if aValue isnt bValue
return if aValue < bValue then -1 else +1
return 0
# Public Methods ###############################################################################