@@ -7,6 +7,8 @@ import isEqual from "lodash/isEqual"
77import getActiveImage from "./get-active-image"
88import { saveToHistory } from "./history-handler.js"
99import colors from "../../colors"
10+ import fixTwisted from "./fix-twisted"
11+ import convertExpandingLineToPolygon from "./convert-expanding-line-to-polygon"
1012
1113const getRandomId = ( ) => Math . random ( ) . toString ( ) . split ( "." ) [ 1 ]
1214
@@ -199,6 +201,7 @@ export default (state: MainLayoutState, action: Action) => {
199201 const { x , y } = action
200202 if ( ! state . mode ) return state
201203 if ( ! activeImage ) return state
204+ const { mouseDownAt } = state
202205 switch ( state . mode . mode ) {
203206 case "MOVE_POLYGON_POINT ": {
204207 const { pointIndex , regionId } = state . mode
@@ -283,13 +286,65 @@ export default (state: MainLayoutState, action: Action) => {
283286 [ x , y ]
284287 )
285288 }
289+ case "DRAW_EXPANDING_LINE ": {
290+ const { regionId } = state . mode
291+ const [ expandingLine , regionIndex ] = getRegion ( regionId )
292+ if ( ! expandingLine ) return state
293+ const isMouseDown = Boolean ( state . mouseDownAt )
294+ if ( isMouseDown ) {
295+ // If the mouse is down, set width/angle
296+ const lastPoint = expandingLine . points . slice ( - 1 ) [ 0 ]
297+ const mouseDistFromLastPoint = Math . sqrt (
298+ ( lastPoint . x - x ) ** 2 + ( lastPoint . y - y ) ** 2
299+ )
300+ if ( mouseDistFromLastPoint < 0.002 && ! lastPoint . width ) return state
301+
302+ const newState = setIn (
303+ state ,
304+ [ ...pathToActiveImage , "regions" , regionIndex , "points" ] ,
305+ expandingLine . points . slice ( 0 , - 1 ) . concat ( [
306+ {
307+ ...lastPoint ,
308+ width : mouseDistFromLastPoint * 2 ,
309+ angle : Math . atan2 ( lastPoint . x - x , lastPoint . y - y ) ,
310+ } ,
311+ ] )
312+ )
313+ return newState
314+ } else {
315+ // If mouse is up, move the next candidate point
316+ return setIn (
317+ state ,
318+ [ ...pathToActiveImage , "regions" , regionIndex ] ,
319+ {
320+ ...expandingLine ,
321+ candidatePoint : { x, y } ,
322+ }
323+ )
324+ }
325+
326+ return state
327+ }
328+ case "SET_EXPANDING_LINE_WIDTH ": {
329+ const { regionId } = state . mode
330+ const [ expandingLine , regionIndex ] = getRegion ( regionId )
331+ if ( ! expandingLine ) return state
332+ const lastPoint = expandingLine . points . slice ( - 1 ) [ 0 ]
333+ const { mouseDownAt } = state
334+ return setIn (
335+ state ,
336+ [ ...pathToActiveImage , "regions" , regionIndex , "expandingWidth" ] ,
337+ Math . sqrt ( ( lastPoint . x - x ) ** 2 + ( lastPoint . y - y ) ** 2 )
338+ )
339+ }
286340 default :
287341 return state
288342 }
289343 }
290344 case "MOUSE_DOWN" : {
291345 if ( ! activeImage ) return state
292346 const { x , y } = action
347+ state = setIn ( state , [ "mouseDownAt" ] , { x, y } )
293348
294349 if ( state . allowedArea ) {
295350 // TODO clamp x/y instead of giving up
@@ -314,7 +369,49 @@ export default (state: MainLayoutState, action: Action) => {
314369 case "DRAW_EXPANDING_LINE ": {
315370 const [ expandingLine , regionIndex ] = getRegion ( state . mode . regionId )
316371 if ( ! expandingLine ) break
372+ const lastPoint = expandingLine . points . slice ( - 1 ) [ 0 ]
373+ if (
374+ expandingLine . points . length > 1 &&
375+ Math . sqrt ( ( lastPoint . x - x ) ** 2 + ( lastPoint . y - y ) ** 2 ) < 0.002
376+ ) {
377+ if ( ! lastPoint . width ) {
378+ return setIn ( state , [ "mode" ] , {
379+ mode : "SET_EXPANDING_LINE_WIDTH" ,
380+ regionId : state . mode . regionId ,
381+ } )
382+ } else {
383+ return state
384+ . setIn (
385+ [ ...pathToActiveImage , "regions" , regionIndex ] ,
386+ convertExpandingLineToPolygon ( expandingLine )
387+ )
388+ . setIn ( [ "mode" ] , null )
389+ }
390+ }
391+
392+ // Create new point
393+ return setIn (
394+ state ,
395+ [ ...pathToActiveImage , "regions" , regionIndex , "points" ] ,
396+ expandingLine . points . concat ( [ { x, y, angle : null , width : null } ] )
397+ )
398+ }
399+ case "SET_EXPANDING_LINE_WIDTH ": {
400+ const [ expandingLine , regionIndex ] = getRegion ( state . mode . regionId )
401+ if ( ! expandingLine ) break
402+ const { expandingWidth } = expandingLine
317403 return state
404+ . setIn (
405+ [ ...pathToActiveImage , "regions" , regionIndex ] ,
406+ convertExpandingLineToPolygon ( {
407+ ...expandingLine ,
408+ points : expandingLine . points . map ( ( p ) =>
409+ p . width ? p : { ...p , width : expandingWidth }
410+ ) ,
411+ expandingWidth : undefined ,
412+ } )
413+ )
414+ . setIn ( [ "mode" ] , null )
318415 }
319416 default :
320417 break
@@ -424,13 +521,15 @@ export default (state: MainLayoutState, action: Action) => {
424521 }
425522 case "MOUSE_UP ": {
426523 const { x , y } = action
524+ const { mouseDownAt = { x, y } } = state
427525 if ( ! state . mode ) return state
526+ state = setIn ( state , [ "mouseDownAt" ] , null )
428527 switch ( state . mode . mode ) {
429528 case "RESIZE_BOX" : {
430529 if ( state . mode . isNew ) {
431530 if (
432- Math . abs ( state . mode . original . x - x ) < 0.01 &&
433- Math . abs ( state . mode . original . y - y ) < 0.01
531+ Math . abs ( state . mode . original . x - x ) < 0.002 &&
532+ Math . abs ( state . mode . original . y - y ) < 0.002
434533 ) {
435534 return setIn (
436535 modifyRegion ( state . mode . regionId , null ) ,
@@ -450,6 +549,50 @@ export default (state: MainLayoutState, action: Action) => {
450549 case "MOVE_POLYGON_POINT" : {
451550 return { ...state , mode : null }
452551 }
552+ case "CREATE_POINT_LINE" : {
553+ return state
554+ }
555+ case "DRAW_EXPANDING_LINE" : {
556+ const [ expandingLine , regionIndex ] = getRegion ( state . mode . regionId )
557+ if ( ! expandingLine ) return state
558+ let newExpandingLine = expandingLine
559+ const lastPoint =
560+ expandingLine . points . length !== 0
561+ ? expandingLine . points . slice ( - 1 ) [ 0 ]
562+ : mouseDownAt
563+ let jointStart
564+ if ( expandingLine . points . length > 1 ) {
565+ jointStart = expandingLine . points . slice ( - 2 ) [ 0 ]
566+ } else {
567+ jointStart = lastPoint
568+ }
569+ const mouseDistFromLastPoint = Math . sqrt (
570+ ( lastPoint . x - x ) ** 2 + ( lastPoint . y - y ) ** 2
571+ )
572+ if ( mouseDistFromLastPoint > 0.002 ) {
573+ // The user is drawing has drawn the width for the last point
574+ const newPoints = [ ...expandingLine . points ]
575+ for ( let i = 0 ; i < newPoints . length - 1 ; i ++ ) {
576+ if ( newPoints [ i ] . width ) continue
577+ newPoints [ i ] = {
578+ ...newPoints [ i ] ,
579+ width : lastPoint . width ,
580+ }
581+ }
582+ newExpandingLine = setIn (
583+ expandingLine ,
584+ [ "points" ] ,
585+ fixTwisted ( newPoints )
586+ )
587+ } else {
588+ return state
589+ }
590+ return setIn (
591+ state ,
592+ [ ...pathToActiveImage , "regions" , regionIndex ] ,
593+ newExpandingLine
594+ )
595+ }
453596 default :
454597 return state
455598 }
@@ -538,10 +681,12 @@ export default (state: MainLayoutState, action: Action) => {
538681 }
539682 }
540683 case "SELECT_TOOL" : {
541- state = setIn ( state , [ "mode" ] , null )
542684 if ( action . selectedTool === "show-tags" ) {
543685 return setIn ( state , [ "showTags" ] , ! state . showTags )
686+ } else if ( action . selectedTool === "show-mask" ) {
687+ return setIn ( state , [ "showMask" ] , ! state . showMask )
544688 }
689+ state = setIn ( state , [ "mode" ] , null )
545690 return setIn ( state , [ "selectedTool" ] , action . selectedTool )
546691 }
547692 case "CANCEL" : {
0 commit comments