import * as constants from "asciiflow/client/constants" ; import { isSpecial } from "asciiflow/client/constants" ; import { AbstractDrawFunction } from "asciiflow/client/draw/function" ; import { drawLine } from "asciiflow/client/draw/utils" ; import { Layer } from "asciiflow/client/layer" ; import { store } from "asciiflow/client/store" ; import { Vector } from "asciiflow/client/vector" ; interface IEnd { position : Vector ; clockwise : boolean ; startIsAlt : boolean ; midPointIsAlt ? : boolean ; endIsAlt : boolean ; } export class DrawMove extends AbstractDrawFunction { private startPosition : Vector ; private ends : IEnd [ ] = [ ] ; start ( position ) { this . startPosition = constants . TOUCH_ENABLED ? this . snapToNearest ( position ) : position ; this . ends = [ ] ; if ( ! constants . isSpecial ( store . currentCanvas . committed . get ( position ) ) ) { return ; } const ends = [ ] ; for ( const i of constants . DIRECTIONS ) { const midPoints = this . followLine ( this . startPosition , i ) ; for ( const midPoint of midPoints ) { const clockwise = i . x !== 0 ; const startIsAlt = constants . ALT_SPECIAL_VALUES . indexOf ( store . currentCanvas . committed . get ( position ) ) !== - 1 ; const midPointIsAlt = constants . ALT_SPECIAL_VALUES . indexOf ( store . currentCanvas . committed . get ( midPoint ) ) !== - 1 ; const midPointContext = store . currentCanvas . committed . context ( midPoint ) ; if ( midPointContext . sum ( ) === 1 ) { ends . push ( { position : midPoint , clockwise , startIsAlt , endIsAlt : midPointIsAlt , } ) ; continue ; } for ( const j of constants . DIRECTIONS ) { if ( i . add ( j ) . length ( ) === 0 || i . add ( j ) . length ( ) === 2 ) { continue ; } const secondEnds = this . followLine ( midPoint , j ) ; if ( secondEnds . length === 0 ) { continue ; } const secondEnd = secondEnds [ 0 ] ; const endIsAlt = constants . ALT_SPECIAL_VALUES . indexOf ( store . currentCanvas . committed . get ( secondEnd ) ) !== - 1 ; ends . push ( { position : secondEnd , clockwise , startIsAlt , midPointIsAlt , endIsAlt , } ) ; } } } this . ends = ends ; this . move ( this . startPosition ) ; } move ( position ) { const layer = new Layer ( ) ; for ( const end of this . ends ) { drawLine ( layer , this . startPosition , end . position , end . clockwise , "" ) ; } for ( const end of this . ends ) { drawLine ( layer , position , end . position , end . clockwise ) ; } for ( const end of this . ends ) { if ( end . startIsAlt ) { layer . set ( position , constants . ALT_SPECIAL_VALUE ) ; } if ( end . endIsAlt ) { layer . set ( end . position , constants . ALT_SPECIAL_VALUE ) ; } if ( end . midPointIsAlt ) { const midX = end . clockwise ? end . position . x : position . x ; const midY = end . clockwise ? position . y : end . position . y ; layer . set ( new Vector ( midX , midY ) , constants . ALT_SPECIAL_VALUE ) ; } } store . currentCanvas . setScratchLayer ( layer ) ; } end ( ) { store . currentCanvas . commitScratch ( ) ; } /**
     * Follows a line in a given direction from the startPosition.
     * Returns a list of positions that were line 'junctions'. This is a bit of a
     * loose definition, but basically means a point around which we resize things.
     */ followLine ( startPosition , direction ) { let endPosition = startPosition . clone ( ) ; const junctions = [ ] ; while ( true ) { const nextEnd = endPosition . add ( direction ) ; const nextEndValue = store . currentCanvas . committed . get ( nextEnd ) ; if ( ! isSpecial ( nextEndValue ) ) { if ( ! startPosition . equals ( endPosition ) ) { junctions . push ( endPosition ) ; } return junctions ; } endPosition = nextEnd ; const context = store . currentCanvas . committed . context ( endPosition ) ; if ( context . sum ( ) === 3 ) { junctions . push ( endPosition ) ; } if ( context . sum ( ) === 4 ) { junctions . push ( endPosition ) ; } } } /**
     * For a given position, finds the nearest cell that is of any interest to the
     * move tool, e.g. a corner or a line. Will look up to 1 cell in each direction
     * including diagonally.
     */ snapToNearest ( position ) { if ( isSpecial ( store . currentCanvas . committed . get ( position ) ) ) { return position ; } const allDirections = constants . DIRECTIONS . concat ( [ constants . DIR_LEFT . add ( constants . DIR_UP ) , constants . DIR_LEFT . add ( constants . DIR_DOWN ) , constants . DIR_RIGHT . add ( constants . DIR_UP ) , constants . DIR_RIGHT . add ( constants . DIR_DOWN ) , ] ) ; let bestDirection = null ; let bestContextSum = 0 ; for ( const direction of allDirections ) { const newPos = position . add ( direction ) ; const contextSum = store . currentCanvas . committed . context ( newPos ) . sum ( ) ; if ( isSpecial ( store . currentCanvas . committed . get ( newPos ) ) && contextSum > bestContextSum ) { bestDirection = direction ; bestContextSum = contextSum ; } } if ( bestDirection == null ) { return position ; } return position . add ( bestDirection ) ; } getCursor ( position ) { if ( isSpecial ( store . currentCanvas . committed . get ( position ) ) ) { return "move" ; } else { return "default" ; } } handleKey ( value ) { } }