All files / src/components/world TriggerView.tsx

0% Statements 0/38
0% Branches 0/12
0% Functions 0/10
0% Lines 0/38

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114                                                                                                                                                                                                                                   
import React, { memo, useCallback, useEffect } from "react";
import editorActions from "store/features/editor/editorActions";
import { triggerSelectors } from "store/features/entities/entitiesState";
import { MIDDLE_MOUSE, TILE_SIZE } from "consts";
import styled, { css } from "styled-components";
import { useAppDispatch, useAppSelector } from "store/hooks";
import renderTriggerContextMenu from "./renderTriggerContextMenu";
import { useContextMenu } from "ui/hooks/use-context-menu";
 
interface TriggerViewProps {
  id: string;
  sceneId: string;
  editable?: boolean;
}
 
interface WrapperProps {
  $selected?: boolean;
}
 
const Wrapper = styled.div<WrapperProps>`
  position: absolute;
  width: 8px;
  height: 8px;
  background-color: rgba(255, 120, 0, 0.5);
  outline: 1px solid rgba(255, 120, 0, 1);
  -webkit-transform: translate3d(0, 0, 0);
 
  ${(props) =>
    props.$selected
      ? css`
          background-color: rgba(255, 199, 40, 0.9);
        `
      : ""}
`;
 
const TriggerView = memo(({ id, sceneId, editable }: TriggerViewProps) => {
  const dispatch = useAppDispatch();
  const trigger = useAppSelector((state) =>
    triggerSelectors.selectById(state, id),
  );
  const selected = useAppSelector(
    (state) =>
      state.editor.type === "trigger" &&
      state.editor.scene === sceneId &&
      state.editor.entityId === id,
  );
  const isDragging = useAppSelector(
    (state) => selected && state.editor.dragging,
  );
 
  const onMouseUp = useCallback(() => {
    dispatch(editorActions.dragTriggerStop());
    window.removeEventListener("mouseup", onMouseUp);
  }, [dispatch]);
 
  const onMouseDown = useCallback(
    (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
      Iif (editable && e.nativeEvent.which !== MIDDLE_MOUSE) {
        dispatch(editorActions.dragTriggerStart({ sceneId, triggerId: id }));
        dispatch(editorActions.setTool({ tool: "select" }));
        window.addEventListener("mouseup", onMouseUp);
      }
    },
    [dispatch, editable, id, onMouseUp, sceneId],
  );
 
  useEffect(() => {
    Iif (isDragging) {
      window.addEventListener("mouseup", onMouseUp);
    }
    return () => {
      window.removeEventListener("mouseup", onMouseUp);
    };
  }, [onMouseUp, isDragging]);
 
  //#region Context Menu
 
  const getContextMenu = useCallback(() => {
    return renderTriggerContextMenu({
      dispatch,
      triggerId: id,
      sceneId,
    });
  }, [dispatch, id, sceneId]);
 
  const { onContextMenu, contextMenuElement } = useContextMenu({
    getMenu: getContextMenu,
  });
 
  //#endregion Context Menu
 
  Iif (!trigger) {
    return <></>;
  }
 
  return (
    <Wrapper
      $selected={selected}
      onMouseDown={onMouseDown}
      onContextMenu={onContextMenu}
      style={{
        left: trigger.x * TILE_SIZE,
        top: trigger.y * TILE_SIZE,
        width: Math.max(trigger.width, 1) * TILE_SIZE,
        height: Math.max(trigger.height, 1) * TILE_SIZE,
      }}
    >
      {contextMenuElement}
    </Wrapper>
  );
});
 
export default TriggerView;