Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

state.ts 3.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. import { createSelectorHook, createState } from "@state-designer/react"
  2. import { clamp, screenToWorld } from "utils/utils"
  3. import * as vec from "utils/vec"
  4. import { Data } from "types"
  5. import { defaultDocument } from "./data"
  6. import * as Sessions from "./sessions"
  7. const initialData: Data = {
  8. camera: {
  9. point: [0, 0],
  10. zoom: 1,
  11. },
  12. brush: undefined,
  13. pointedId: null,
  14. selectedIds: [],
  15. currentPageId: "page0",
  16. document: defaultDocument,
  17. }
  18. const state = createState({
  19. data: initialData,
  20. on: {
  21. ZOOMED_CAMERA: {
  22. do: "zoomCamera",
  23. },
  24. PANNED_CAMERA: {
  25. do: "panCamera",
  26. },
  27. },
  28. initial: "selecting",
  29. states: {
  30. selecting: {
  31. on: {
  32. POINTED_CANVAS: { to: "brushSelecting" },
  33. POINTED_SHAPE: [
  34. "setPointedId",
  35. {
  36. if: "isPressingShiftKey",
  37. then: {
  38. if: "isPointedShapeSelected",
  39. do: "pullPointedIdFromSelectedIds",
  40. else: "pushPointedIdToSelectedIds",
  41. },
  42. else: ["clearSelectedIds", "pushPointedIdToSelectedIds"],
  43. },
  44. ],
  45. },
  46. },
  47. brushSelecting: {
  48. onEnter: [
  49. { unless: "isPressingShiftKey", do: "clearSelectedIds" },
  50. "startBrushSession",
  51. ],
  52. on: {
  53. MOVED_POINTER: "updateBrushSession",
  54. PANNED_CAMERA: "updateBrushSession",
  55. STOPPED_POINTING: { do: "completeSession", to: "selecting" },
  56. CANCELLED: { do: "cancelSession", to: "selecting" },
  57. },
  58. },
  59. },
  60. conditions: {
  61. isPointedShapeSelected(data) {
  62. return data.selectedIds.includes(data.pointedId)
  63. },
  64. isPressingShiftKey(data, payload: { shiftKey: boolean }) {
  65. return payload.shiftKey
  66. },
  67. },
  68. actions: {
  69. cancelSession(data) {
  70. session.cancel(data)
  71. session = undefined
  72. },
  73. completeSession(data) {
  74. session.complete(data)
  75. session = undefined
  76. },
  77. startBrushSession(data, payload: { point: number[] }) {
  78. session = new Sessions.BrushSession(
  79. data,
  80. screenToWorld(payload.point, data)
  81. )
  82. },
  83. updateBrushSession(data, payload: { point: number[] }) {
  84. session.update(data, screenToWorld(payload.point, data))
  85. },
  86. // Selection
  87. setPointedId(data, payload: { id: string }) {
  88. data.pointedId = payload.id
  89. },
  90. clearPointedId(data) {
  91. data.pointedId = undefined
  92. },
  93. clearSelectedIds(data) {
  94. data.selectedIds = []
  95. },
  96. pullPointedIdFromSelectedIds(data) {
  97. const { selectedIds, pointedId } = data
  98. selectedIds.splice(selectedIds.indexOf(pointedId, 1))
  99. },
  100. pushPointedIdToSelectedIds(data) {
  101. data.selectedIds.push(data.pointedId)
  102. },
  103. // Camera
  104. zoomCamera(data, payload: { delta: number; point: number[] }) {
  105. const { camera } = data
  106. const p0 = screenToWorld(payload.point, data)
  107. camera.zoom = clamp(
  108. camera.zoom - (payload.delta / 100) * camera.zoom,
  109. 0.5,
  110. 3
  111. )
  112. const p1 = screenToWorld(payload.point, data)
  113. camera.point = vec.add(camera.point, vec.sub(p1, p0))
  114. },
  115. panCamera(data, payload: { delta: number[]; point: number[] }) {
  116. const { camera } = data
  117. data.camera.point = vec.sub(
  118. camera.point,
  119. vec.div(payload.delta, camera.zoom)
  120. )
  121. },
  122. },
  123. values: {
  124. selectedIds(data) {
  125. return new Set(data.selectedIds)
  126. },
  127. },
  128. })
  129. let session: Sessions.BaseSession
  130. export default state
  131. export const useSelector = createSelectorHook(state)