client/src/models/TxMondrianPoolScene.js
// Update the layout to accommodate a square of size squareWidth placed in the given slot
Update the layout to accommodate a square of size squareWidth placed in the given slot
Update the layout to accommodate a square of size squareWidth placed in the given slot
fillSlot (slot, squareWidth) {
    const square = {
      left: slot.x,
      right: slot.x + squareWidth,
      bottom: slot.y,
      top: slot.y + squareWidth
    }
    this.removeSlot(slot)
    for (let rowIndex = slot.y; rowIndex < square.top; rowIndex++) {
      const row = this.getRow({ y: rowIndex })
      if (row) {
        let collisions = []
        let maxExcess = 0
        for (let i = 0; i < row.slots.length; i++) {
          const testSlot = row.slots[i]
          if (!((testSlot.x + testSlot.r < square.left) || (testSlot.x >= square.right))) {
            collisions.push(testSlot)
            let excess = Math.max(0, (testSlot.x + testSlot.r) - (slot.x + slot.r))
            maxExcess = Math.max(maxExcess, excess)
          }
        }
        if (square.right < this.width && !row.map[square.right]) {
          this.addSlot({ x: square.right, y: rowIndex, r: (slot.r - squareWidth + maxExcess) })
        }
        for (let i = 0; i < collisions.length; i++) {
          collisions[i].r = slot.x - collisions[i].x
          if (collisions[i].r > 0) this.updateSlotSprite(collisions[i])
          else this.removeSlot(collisions[i])
        }
      } else {
        this.addRow()
        if (slot.x > 0) this.addSlot({ x: 0, y: rowIndex, r: slot.x })
        if (square.right < this.width) this.addSlot({ x: square.right, y: rowIndex, r: this.width - square.right})
      }
    }
    for (let rowIndex = Math.max(0, slot.y - squareWidth); rowIndex < slot.y; rowIndex++) {
      const row = this.getRow({ y: rowIndex })
      if (row) {
        for (let i = 0; i < row.slots.length; i++) {
          const testSlot = row.slots[i]
          if ((testSlot.x < slot.x + squareWidth) && (testSlot.x + testSlot.r > slot.x) && (testSlot.y + testSlot.r >= slot.y)) {
            const oldSlotWidth = testSlot.r
            testSlot.r = slot.y - testSlot.y
            if (testSlot.r > 0) this.updateSlotSprite(testSlot)
            else this.removeSlot(testSlot)
            let remaining = {
              x: testSlot.x + testSlot.r,
              y: testSlot.y,
              w: oldSlotWidth - testSlot.r,
              h: testSlot.r
            }
            while (remaining.w > 0 && remaining.h > 0) {
              if (remaining.w <= remaining.h) {
                this.addSlot({ x: remaining.x, y: remaining.y, r: remaining.w })
                remaining.y += remaining.w
                remaining.h -= remaining.w
              } else {
                this.addSlot({ x: remaining.x, y: remaining.y, r: remaining.h })
                remaining.x += remaining.h
                remaining.w -= remaining.h
              }
            }
          }
        }
      }
    }
    return { x: slot.x, y: slot.y, r: squareWidth }
  }
fillSlot ( slot , squareWidth ) { const square = { left : slot . x , right : slot . x + squareWidth , bottom : slot . y , top : slot . y + squareWidth } this . removeSlot ( slot ) for ( let rowIndex = slot . y ; rowIndex < square . top ; rowIndex ++ ) { const row = this . getRow ( { y : rowIndex } ) if ( row ) { let collisions = [ ] let maxExcess = 0 for ( let i = 0 ; i < row . slots . length ; i ++ ) { const testSlot = row . slots [ i ] if ( ! ( ( testSlot . x + testSlot . r < square . left ) || ( testSlot . x >= square . right ) ) ) { collisions . push ( testSlot ) let excess = Math . max ( 0 , ( testSlot . x + testSlot . r ) - ( slot . x + slot . r ) ) maxExcess = Math . max ( maxExcess , excess ) } } if ( square . right < this . width && ! row . map [ square . right ] ) { this . addSlot ( { x : square . right , y : rowIndex , r : ( slot . r - squareWidth + maxExcess ) } ) } for ( let i = 0 ; i < collisions . length ; i ++ ) { collisions [ i ] . r = slot . x - collisions [ i ] . x if ( collisions [ i ] . r > 0 ) this . updateSlotSprite ( collisions [ i ] ) else this . removeSlot ( collisions [ i ] ) } } else { this . addRow ( ) if ( slot . x > 0 ) this . addSlot ( { x : 0 , y : rowIndex , r : slot . x } ) if ( square . right < this . width ) this . addSlot ( { x : square . right , y : rowIndex , r : this . width - square . right } ) } } for ( let rowIndex = Math . max ( 0 , slot . y - squareWidth ) ; rowIndex < slot . y ; rowIndex ++ ) { const row = this . getRow ( { y : rowIndex } ) if ( row ) { for ( let i = 0 ; i < row . slots . length ; i ++ ) { const testSlot = row . slots [ i ] if ( ( testSlot . x < slot . x + squareWidth ) && ( testSlot . x + testSlot . r > slot . x ) && ( testSlot . y + testSlot . r >= slot . y ) ) { const oldSlotWidth = testSlot . r testSlot . r = slot . y - testSlot . y if ( testSlot . r > 0 ) this . updateSlotSprite ( testSlot ) else this . removeSlot ( testSlot ) let remaining = { x : testSlot . x + testSlot . r , y : testSlot . y , w : oldSlotWidth - testSlot . r , h : testSlot . r } while ( remaining . w > 0 && remaining . h > 0 ) { if ( remaining . w <= remaining . h ) { this . addSlot ( { x : remaining . x , y : remaining . y , r : remaining . w } ) remaining . y += remaining . w remaining . h -= remaining . w } else { this . addSlot ( { x : remaining . x , y : remaining . y , r : remaining . h } ) remaining . x += remaining . h remaining . w -= remaining . h } } } } } } return { x : slot . x , y : slot . y , r : squareWidth } }
Update the layout to accommodate a square of size squareWidth placed in the given slot
Update the layout to accommodate a square of size squareWidth placed in the given slot
// console.log(`filling slot at ${slot.x},${slot.y},${slot.r} with ${squareWidth}`) // Find and fix collisions for each affected row (from slot.y + 1 to slot.y + squareWidth - 1) // console.log(`Checking row ${rowIndex}`) // look for an overlapping slot // console.log(`Checking slot ${i} (x: ${testSlot.x}) in row ${rowIndex}`) // collision if this slot overlaps the new square // console.log('Collision!') // record how far this slot extends beyond the RHS of the filled slot (if at all) // console.log(`overruns by ${excess}`) // add a new slot on the RHS of the inserted square, unless one already exists or there's no space left there // console.log(`Adding RHS square at ${square.right},${rowIndex},${(slot.r - squareWidth + maxExcess)}`) // process collisions (remove or adjust) // console.log('processing collisions: ', collisions) // shrink the slot to the now available space, or remove if no space left // collision with implied slot in next uninitialised row // Find and fix collisions in region below the inserted square // console.log(`Checking row ${rowIndex}`) // look for all overlapping slots // console.log(`Checking slot ${i} (x: ${slot[i].x}) in row ${rowIndex}`) // collision if this slot overlaps the filled slot // console.log('Collision!') // shrink the slot to the now available space // now there's some uncovered space on the RHS of the old slot // console.log('remaining space: ', remaining) // tile with free-floating slots to make sure we don't lose that space // console.log('tiling free space')