diff options
| author | lonkaars <loek@pipeframe.xyz> | 2021-06-24 18:22:35 +0200 | 
|---|---|---|
| committer | lonkaars <loek@pipeframe.xyz> | 2021-06-24 18:22:35 +0200 | 
| commit | b7388bd7a4fb8602da9cdb525780c467a591e58e (patch) | |
| tree | 4200d330cd5b2dd44c4216899bcc640623dd8b57 | |
| parent | 32893a65bbf52ecfe390a37642bba505083957d8 (diff) | |
selection in global state
| -rw-r--r-- | pages/editor.tsx | 118 | 
1 files changed, 72 insertions, 46 deletions
| diff --git a/pages/editor.tsx b/pages/editor.tsx index e890d0b..5cdd40e 100644 --- a/pages/editor.tsx +++ b/pages/editor.tsx @@ -57,6 +57,16 @@ interface project {  		workingTimeline: anySlide[];  		tool: string;  	}; +	selection: { +		slides: anySlide[]; +		active: boolean; +		placed: boolean; +		hidden: boolean; +		type: { +			left: slideTypes | null; +			right: slideTypes | null; +		}; +	};  	update: {  		refreshLiveTimeline: () => void;  	}; @@ -71,6 +81,16 @@ var project = createState<project>({  		workingTimeline: [],  		tool: 'cursor',  	}, +	selection: { +		slides: [], +		active: false, +		placed: false, +		hidden: true, +		type: { +			left: null, +			right: null, +		}, +	},  	update: {  		refreshLiveTimeline: () => {  			player.timeline.slides = Array(...(project.timeline.workingTimeline.value)); @@ -242,11 +262,7 @@ function TimelineSelection(props: { selectionAreaRef: Ref<ReactNode>; }) {  	var workingTimeline = useHookstate(project).timeline.workingTimeline;  	var tool = useHookstate(project).timeline.tool; -	var [selectionActive, setSelectionActive] = useState(false); -	var [selectionPlaced, setSelectionPlaced] = useState(false); -	var [selectionHidden, setSelectionHidden] = useState(true); -	var [selectionLeftType, setSelectionLeftType] = useState(null); -	var [selectionRightType, setSelectionRightType] = useState(null); +	var selection = useHookstate(project).selection;  	var [selectionPos, selectionPosAPI] = useSpring(() => ({  		x1: 0, @@ -262,23 +278,22 @@ function TimelineSelection(props: { selectionAreaRef: Ref<ReactNode>; }) {  	}));  	var selectionRef = useRef(null); -	var [selection, setSelection] = useState<anySlide[]>([]);  	// drag on selection  	useDrag(({ movement: [x, _y], last }) => { -		if (!selectionPlaced) return; -		if (selection.length < 1) return; +		if (!project.selection.placed.value) return; +		if (project.selection.slides.value.length < 1) return;  		var frameOffset = Math.round(x / zoomToPx(project.timeline.zoom.value)); -		selection.forEach(slide => { -			var api = slideAPIs[slide.id]; -			switch (slide.type as slideTypes | 'loopBegin') { +		project.selection.slides.forEach(slide => { +			var api = slideAPIs[slide.value.id]; +			switch (slide.value.type as slideTypes | 'loopBegin') {  				case 'loopBegin': {  					if (!api) break; -					var loop = workingTimeline.value.find(s => s.id == slide.id) as loopSlide; +					var loop = workingTimeline.value.find(s => s.id == slide.value.id) as loopSlide;  					var begin = loop.beginFrame + frameOffset;  					api.start({ begin });  					if (last) { -						(project.timeline.workingTimeline.find(s => s.value.id == slide.id) as State<loopSlide>) +						(project.timeline.workingTimeline.find(s => s.value.id == slide.value.id) as State<loopSlide>)  							.beginFrame.set(begin);  						project.update.refreshLiveTimeline.value();  					} @@ -287,17 +302,17 @@ function TimelineSelection(props: { selectionAreaRef: Ref<ReactNode>; }) {  				}  				default: {  					if (!api) break; -					var frame = slide.frame + frameOffset; +					var frame = slide.value.frame + frameOffset;  					api.start({ frame });  					if (last) { -						workingTimeline.find(s => s.value.id == slide.id).frame.set(frame); +						workingTimeline.find(s => s.value.id == slide.value.id).frame.set(frame);  						project.update.refreshLiveTimeline.value();  					}  				}  			}  			if (last) return; -			var selectionFrame = selection[0].frame; +			var selectionFrame = project.selection.slides[0].frame.value;  			selectionPosAPI.start({ startingFrame: selectionFrame + frameOffset });  		});  	}, { domTarget: selectionRef, eventOptions: { passive: false } }); @@ -307,17 +322,16 @@ function TimelineSelection(props: { selectionAreaRef: Ref<ReactNode>; }) {  		var minDistance = 5; // minimal drag distance in pixels to register selection  		var distanceTraveled = Math.sqrt(ox ** 2 + oy ** 2); -		if (selectionHidden && distanceTraveled > minDistance) setSelectionHidden(false); -		if (selectionLeftType) setSelectionLeftType(null); -		if (selectionRightType) setSelectionRightType(null); -		if (selectionPlaced) setSelectionPlaced(false); +		if (project.selection.hidden.value && distanceTraveled > minDistance) project.selection.hidden.set(false); +		if (project.selection.type.left.value) project.selection.type.left.set(null); +		if (project.selection.type.right.value) project.selection.type.right.set(null); +		if (project.selection.placed.value) project.selection.placed.set(false);  		selectionPosAPI.start({  			center: 0,  			startOffset: 0,  			widthOffset: 0,  		}); -		selection = []; -		setSelection(selection); +		project.selection.slides.set([]);  		var timelineInner = document.querySelector('.timeline .timelineInner');  		var timelineRects = timelineInner.getBoundingClientRect(); @@ -338,11 +352,18 @@ function TimelineSelection(props: { selectionAreaRef: Ref<ReactNode>; }) {  		var frameWidth = Math.abs(sx) / zoom;  		var startingFrame = x1 / zoom; -		selectionPosAPI[first && selectionHidden ? 'set' : 'start']({ x1, y1, x2, y2, startingFrame, frameWidth }); -		if (!selectionActive) setSelectionActive(true); +		selectionPosAPI[first && project.selection.hidden ? 'set' : 'start']({ +			x1, +			y1, +			x2, +			y2, +			startingFrame, +			frameWidth, +		}); +		if (!project.selection.active.value) project.selection.active.set(true);  		if (last) { -			setSelectionActive(false); -			if (distanceTraveled <= minDistance) setSelectionHidden(true); +			project.selection.active.set(false); +			if (distanceTraveled <= minDistance) project.selection.hidden.set(true);  			else {  				var endingFrame = startingFrame + frameWidth;  				var expandedTimeline = new Array(...player.timeline.slides); @@ -360,12 +381,11 @@ function TimelineSelection(props: { selectionAreaRef: Ref<ReactNode>; }) {  				);  				if (keyframesInSelection.length < 1) { -					setSelectionHidden(true); +					project.selection.hidden.set(true);  					return;  				} -				selection = keyframesInSelection; -				setSelection(selection); +				project.selection.slides.set(keyframesInSelection);  				var left = keyframesInSelection[0];  				var right = keyframesInSelection[keyframesInSelection.length - 1]; @@ -393,9 +413,13 @@ function TimelineSelection(props: { selectionAreaRef: Ref<ReactNode>; }) {  						widthOffset,  					});  				}, 100); -				setSelectionLeftType(left.type); -				setSelectionRightType(right.type); -				setSelectionPlaced(true); +				project.selection.merge({ +					type: { +						left: left.type, +						right: right.type, +					}, +					placed: true, +				});  			}  		}  	}, { domTarget: props.selectionAreaRef, eventOptions: { passive: false } }); @@ -403,27 +427,29 @@ function TimelineSelection(props: { selectionAreaRef: Ref<ReactNode>; }) {  	useEffect(() => {  		var delkeys = ['del', 'backspace'];  		mousetrap.bind(delkeys, () => { -			if (!selectionPlaced) return; +			if (!project.selection.placed) return; -			selection.forEach(slide => { -				if (!slideTypes.includes(slide.type)) return; -				var index = workingTimeline.findIndex(s => s.value?.id == slide.id); +			project.selection.slides.forEach(slide => { +				if (!slideTypes.includes(slide.value.type)) return; +				var index = workingTimeline.findIndex(s => s.value?.id == slide.value.id);  				if (index == -1) return; -				var timeline = new Array(...workingTimeline.value); +				var timeline = new Array(...project.timeline.workingTimeline.value);  				timeline.splice(index, 1);  				workingTimeline.set(timeline);  			});  			project.update.refreshLiveTimeline.value(); -			setSelectionPlaced(false); -			setSelectionHidden(true); -			setSelection([]); +			project.selection.merge({ +				placed: false, +				hidden: true, +				slides: [], +			});  		});  		return () => {  			mousetrap.unbind(delkeys);  		}; -	}, [selectionPlaced, workingTimeline]); +	}, []);  	function CustomSelection(props: {  		x1: number; @@ -439,8 +465,8 @@ function TimelineSelection(props: { selectionAreaRef: Ref<ReactNode>; }) {  			width={props.x2 - props.x1 + 12}  			frameWidth={props.frameWidth}  			height={props.y2 - props.y1 + 12} -			left={selectionLeftType} -			right={selectionRightType} +			left={selection.type.left.get()} +			right={selection.type.right.get()}  			widthOffset={props.widthOffset}  		/>;  	} @@ -448,14 +474,14 @@ function TimelineSelection(props: { selectionAreaRef: Ref<ReactNode>; }) {  	return <animated.div  		id='selection' -		className={'posabs dispinbl ' + (selectionPlaced ? 'placed ' : '')} +		className={'posabs dispinbl ' + (selection.placed ? 'placed ' : '')}  		ref={selectionRef}  		style={{  			'--starting-frame': selectionPos.startingFrame,  			'--y': selectionPos.y1,  			'--start-offset': selectionPos.startOffset,  			'--center': selectionPos.center, -			pointerEvents: selectionPlaced ? 'all' : 'none', +			pointerEvents: selection.placed.get() ? 'all' : 'none',  		} as CSSProperties}  	>  		<AnimatedSelection @@ -465,7 +491,7 @@ function TimelineSelection(props: { selectionAreaRef: Ref<ReactNode>; }) {  			y2={selectionPos.y2}  			widthOffset={selectionPos.widthOffset}  			frameWidth={selectionPos.frameWidth} -			className={'' + (selectionActive ? 'active ' : '') + (selectionHidden ? 'hidden ' : '')} +			className={'' + (selection.active.get() ? 'active ' : '') + (selection.hidden.get() ? 'hidden ' : '')}  		/>  	</animated.div>;  } |