You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

control.tsx 3.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. import state, { useSelector } from 'state'
  2. import styled from 'styles'
  3. import {
  4. ControlType,
  5. NumberCodeControl,
  6. TextCodeControl,
  7. VectorCodeControl,
  8. } from 'types'
  9. export default function Control({ id }: { id: string }): JSX.Element {
  10. const control = useSelector((s) => s.data.codeControls[id])
  11. if (!control) return null
  12. return (
  13. <>
  14. <label>{control.label}</label>
  15. {(() => {
  16. switch (control.type) {
  17. case ControlType.Number:
  18. return <NumberControl {...control} />
  19. case ControlType.Vector:
  20. return <VectorControl {...control} />
  21. case ControlType.Text:
  22. return <TextControl {...control} />
  23. }
  24. })()}
  25. </>
  26. )
  27. }
  28. function NumberControl({ id, min, max, step, value }: NumberCodeControl) {
  29. return (
  30. <Inputs>
  31. <input
  32. type="range"
  33. min={min}
  34. max={max}
  35. step={step}
  36. value={value}
  37. onChange={(e) =>
  38. state.send('CHANGED_CODE_CONTROL', {
  39. [id]: Number(e.currentTarget.value),
  40. })
  41. }
  42. />
  43. <input
  44. type="number"
  45. min={min}
  46. max={max}
  47. step={step}
  48. value={value}
  49. onChange={(e) =>
  50. state.send('CHANGED_CODE_CONTROL', {
  51. [id]: Number(e.currentTarget.value),
  52. })
  53. }
  54. />
  55. </Inputs>
  56. )
  57. }
  58. function VectorControl({
  59. id,
  60. value,
  61. min = -Infinity,
  62. max = Infinity,
  63. step = 0.01,
  64. isNormalized = false,
  65. }: VectorCodeControl) {
  66. return (
  67. <Inputs>
  68. <input
  69. type="range"
  70. min={isNormalized ? -1 : min}
  71. max={isNormalized ? 1 : max}
  72. step={step}
  73. value={value[0]}
  74. onChange={(e) =>
  75. state.send('CHANGED_CODE_CONTROL', {
  76. [id]: [Number(e.currentTarget.value), value[1]],
  77. })
  78. }
  79. />
  80. <input
  81. type="number"
  82. min={isNormalized ? -1 : min}
  83. max={isNormalized ? 1 : max}
  84. step={step}
  85. value={value[0]}
  86. onChange={(e) =>
  87. state.send('CHANGED_CODE_CONTROL', {
  88. [id]: [Number(e.currentTarget.value), value[1]],
  89. })
  90. }
  91. />
  92. <input
  93. type="range"
  94. min={isNormalized ? -1 : min}
  95. max={isNormalized ? 1 : max}
  96. step={step}
  97. value={value[1]}
  98. onChange={(e) =>
  99. state.send('CHANGED_CODE_CONTROL', {
  100. [id]: [value[0], Number(e.currentTarget.value)],
  101. })
  102. }
  103. />
  104. <input
  105. type="number"
  106. min={isNormalized ? -1 : min}
  107. max={isNormalized ? 1 : max}
  108. step={step}
  109. value={value[1]}
  110. onChange={(e) =>
  111. state.send('CHANGED_CODE_CONTROL', {
  112. [id]: [value[0], Number(e.currentTarget.value)],
  113. })
  114. }
  115. />
  116. </Inputs>
  117. )
  118. }
  119. function TextControl({ id, value }: TextCodeControl) {
  120. return (
  121. <Inputs>
  122. <input
  123. type="text"
  124. value={value}
  125. onChange={(e) =>
  126. state.send('CHANGED_CODE_CONTROL', {
  127. [id]: e.currentTarget.value,
  128. })
  129. }
  130. />
  131. </Inputs>
  132. )
  133. }
  134. const Inputs = styled('div', {
  135. display: 'flex',
  136. gap: '8px',
  137. height: '100%',
  138. '& input': {
  139. font: '$ui',
  140. width: '64px',
  141. fontSize: '$1',
  142. border: '1px solid $inputBorder',
  143. backgroundColor: '$input',
  144. color: '$text',
  145. height: '100%',
  146. padding: '0px 6px',
  147. },
  148. "& input[type='range']": {
  149. padding: 0,
  150. flexGrow: 2,
  151. },
  152. "& input[type='text']": {
  153. minWidth: 200,
  154. padding: 4,
  155. flexGrow: 2,
  156. },
  157. })