diff --git a/frontend/farm_designer/__tests__/three_d_garden_map_test.tsx b/frontend/farm_designer/__tests__/three_d_garden_map_test.tsx index 5a5b0dc7f..0e95cadd6 100644 --- a/frontend/farm_designer/__tests__/three_d_garden_map_test.tsx +++ b/frontend/farm_designer/__tests__/three_d_garden_map_test.tsx @@ -1,9 +1,14 @@ import React from "react"; import { mount } from "enzyme"; import { ThreeDGardenMapProps, ThreeDGardenMap } from "../three_d_garden_map"; +import { fakeMapTransformProps } from "../../__test_support__/map_transform_props"; +import { fakeBotSize } from "../../__test_support__/fake_bot_data"; describe("", () => { const fakeProps = (): ThreeDGardenMapProps => ({ + mapTransformProps: fakeMapTransformProps(), + botSize: fakeBotSize(), + gridOffset: { x: 10, y: 10 }, }); it("renders", () => { diff --git a/frontend/farm_designer/index.tsx b/frontend/farm_designer/index.tsx index d43c37574..1fa5ae206 100755 --- a/frontend/farm_designer/index.tsx +++ b/frontend/farm_designer/index.tsx @@ -194,7 +194,10 @@ export class RawFarmDesigner {this.props.getConfigValue(BooleanSetting.three_d_garden) - ? + ? :
{ - props; - return ; + const config = clone(INITIAL); + const { gridSize } = props.mapTransformProps; + config.botSizeX = gridSize.x; + config.botSizeY = gridSize.y; + config.bedWidthOuter = gridSize.y + 160; + config.bedLengthOuter = gridSize.x + 160; + + return ; }; diff --git a/frontend/promo/__tests__/promo_test.tsx b/frontend/promo/__tests__/promo_test.tsx index 39728c29b..8b1bdd3f8 100644 --- a/frontend/promo/__tests__/promo_test.tsx +++ b/frontend/promo/__tests__/promo_test.tsx @@ -1,11 +1,11 @@ import React from "react"; -import { shallow } from "enzyme"; +import { mount } from "enzyme"; import { Promo } from "../promo"; describe("", () => { it("renders", () => { console.error = jest.fn(); - const wrapper = shallow(); + const wrapper = mount(); expect(wrapper.html()).toContain("three-d-garden"); }); }); diff --git a/frontend/promo/promo.tsx b/frontend/promo/promo.tsx index 71c89815d..70c179f57 100644 --- a/frontend/promo/promo.tsx +++ b/frontend/promo/promo.tsx @@ -1,5 +1,17 @@ import React from "react"; import { ThreeDGarden } from "../three_d_garden"; +import { + Config, INITIAL, modifyConfigsFromUrlParams, -export const Promo = () => - ; +} from "../three_d_garden/config"; + +export const Promo = () => { + const [config, setConfig] = React.useState(INITIAL); + + React.useEffect(() => { + setConfig(modifyConfigsFromUrlParams(config)); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); // intentionally empty dependency array + + return ; +}; diff --git a/frontend/three_d_garden/__tests__/bed_test.tsx b/frontend/three_d_garden/__tests__/bed_test.tsx new file mode 100644 index 000000000..24a178696 --- /dev/null +++ b/frontend/three_d_garden/__tests__/bed_test.tsx @@ -0,0 +1,27 @@ +import React from "react"; +import { mount } from "enzyme"; +import { INITIAL } from "../config"; +import { Bed, BedProps } from "../bed"; +import { clone } from "lodash"; + +describe("", () => { + const fakeProps = (): BedProps => ({ + config: clone(INITIAL), + }); + + it("renders bed", () => { + const p = fakeProps(); + p.config.extraLegsX = 0; + const wrapper = mount(); + expect(wrapper.html()).toContain("args=\"1500,50,50\""); + }); + + it("renders bed with extra legs", () => { + const p = fakeProps(); + p.config.extraLegsX = 2; + p.config.extraLegsY = 2; + p.config.legsFlush = false; + const wrapper = mount(); + expect(wrapper.html()).toContain("args=\"1500,50,50\""); + }); +}); diff --git a/frontend/three_d_garden/__tests__/components_test.tsx b/frontend/three_d_garden/__tests__/components_test.tsx new file mode 100644 index 000000000..8aba8c89d --- /dev/null +++ b/frontend/three_d_garden/__tests__/components_test.tsx @@ -0,0 +1,37 @@ +import React from "react"; +import { mount } from "enzyme"; +import { AmbientLight, Mesh, PointLight } from "../components"; +import { AmbientLightProps, MeshProps, PointLightProps } from "@react-three/fiber"; + +describe("", () => { + const fakeProps = (): AmbientLightProps => ({ + intensity: 0.5, + }); + + it("adds props", () => { + const wrapper = mount(); + expect(wrapper.props().intensity).toEqual(0.5); + }); +}); + +describe("", () => { + const fakeProps = (): PointLightProps => ({ + intensity: 0.5, + }); + + it("adds props", () => { + const wrapper = mount(); + expect(wrapper.props().intensity).toEqual(0.5); + }); +}); + +describe("", () => { + const fakeProps = (): MeshProps => ({ + name: "mesh", + }); + + it("adds props", () => { + const wrapper = mount(); + expect(wrapper.props().name).toEqual("mesh"); + }); +}); diff --git a/frontend/three_d_garden/__tests__/config_test.ts b/frontend/three_d_garden/__tests__/config_test.ts new file mode 100644 index 000000000..3ec339aaf --- /dev/null +++ b/frontend/three_d_garden/__tests__/config_test.ts @@ -0,0 +1,76 @@ +import { clone } from "lodash"; +import { INITIAL, modifyConfig, modifyConfigsFromUrlParams } from "../config"; + +describe("modifyConfig()", () => { + it("modifies config: lab", () => { + const initial = clone(INITIAL); + const result = modifyConfig(initial, { scene: "Lab" }); + expect(initial.lab).toEqual(false); + expect(result.lab).toEqual(true); + expect(initial.clouds).toEqual(true); + expect(result.clouds).toEqual(false); + expect(initial.bedType).toEqual("Standard"); + expect(result.bedType).toEqual("Mobile"); + }); + + it("modifies config: lab XL", () => { + const initial = clone(INITIAL); + const result = modifyConfig(initial, { + scene: "Lab", + sizePreset: "Genesis XL", + }); + expect(initial.bedType).toEqual("Standard"); + expect(result.bedType).toEqual("Standard"); + }); + + it("modifies config: Jr", () => { + const initial = clone(INITIAL); + const result = modifyConfig(initial, { sizePreset: "Jr" }); + expect(initial.x).toEqual(300); + expect(result.x).toEqual(100); + }); + + it("modifies config: bedType", () => { + const initial = clone(INITIAL); + initial.bedZOffset = 100; + initial.bedType = "Mobile"; + const result = modifyConfig(initial, { bedType: "Standard" }); + expect(result.bedZOffset).toEqual(0); + }); + + it("resets config", () => { + const initial = clone(INITIAL); + initial.bedLengthOuter = 1; + const result = modifyConfig(initial, { otherPreset: "Reset all" }); + expect(result.bedLengthOuter).toEqual(3000); + }); + + it("modifies config: preset", () => { + const initial = clone(INITIAL); + initial.bedHeight = 1; + const result = modifyConfig(initial, { otherPreset: "Initial" }); + expect(result.bedHeight).toEqual(300); + }); +}); + +describe("modifyConfigsFromUrlParams()", () => { + it("sets config scene", () => { + window.location.search = "?scene=Lab"; + const initial = clone(INITIAL); + initial.lab = false; + const result = modifyConfigsFromUrlParams(initial); + expect(result.lab).toEqual(true); + }); + + it("sets other config", () => { + window.location.search = "?kit=JR&x=1&ground=true"; + const initial = clone(INITIAL); + initial.sizePreset = "Genesis XL"; + initial.x = 100; + initial.ground = false; + const result = modifyConfigsFromUrlParams(initial); + expect(result.sizePreset).toEqual("Jr"); + expect(result.x).toEqual(1); + expect(result.ground).toEqual(true); + }); +}); diff --git a/frontend/three_d_garden/__tests__/index_test.tsx b/frontend/three_d_garden/__tests__/index_test.tsx index 5304f2c66..7e65291e1 100644 --- a/frontend/three_d_garden/__tests__/index_test.tsx +++ b/frontend/three_d_garden/__tests__/index_test.tsx @@ -19,9 +19,12 @@ import { } from ".."; import React from "react"; +import { INITIAL } from "../config"; +import { clone } from "lodash"; describe("", () => { const fakeProps = (): ThreeDGardenProps => ({ + config: clone(INITIAL), }); it("renders", () => { @@ -32,6 +35,7 @@ describe("", () => { describe("", () => { const fakeProps = (): ThreeDGardenModelProps => ({ + config: clone(INITIAL), }); it("renders model", () => { diff --git a/frontend/three_d_garden/bed.tsx b/frontend/three_d_garden/bed.tsx new file mode 100644 index 000000000..d9448783c --- /dev/null +++ b/frontend/three_d_garden/bed.tsx @@ -0,0 +1,161 @@ +import React from "react"; +import { Box, Extrude } from "@react-three/drei"; +import { DoubleSide, Path, Shape } from "three"; +import { range } from "lodash"; +import { Config } from "./config"; +import { Group, MeshPhongMaterial } from "./components"; + +const soil = ( + Type: typeof Path | typeof Shape, + botSize: Record<"x" | "y" | "z" | "thickness", number>, +): Path | Shape => { + const { x, y, thickness } = botSize; + + const hole = new Type(); + hole.moveTo(thickness, thickness); + hole.lineTo(thickness, y - thickness); + hole.lineTo(x - thickness, y - thickness); + hole.lineTo(x - thickness, thickness); + hole.lineTo(thickness, thickness); + return hole; +}; + +const bedStructure2D = ( + botSize: Record<"x" | "y" | "z" | "thickness", number>, +) => { + const { x, y } = botSize; + const shape = new Shape(); + + // outer edge + shape.moveTo(0, 0); + shape.lineTo(0, y); + shape.lineTo(x, y); + shape.lineTo(x, 0); + shape.lineTo(0, 0); + + // inner edge + shape.holes.push(soil(Path, botSize)); + + return shape; +}; + +export interface BedProps { + config: Config; +} + +export const Bed = (props: BedProps) => { + const { + bedWidthOuter, bedLengthOuter, botSizeZ, bedHeight, bedZOffset, + legSize, legsFlush, extraLegsX, extraLegsY, + soilHeight, ccSupportSize, + } = props.config; + const thickness = props.config.bedWallThickness; + const botSize = { x: bedLengthOuter, y: bedWidthOuter, z: botSizeZ, thickness }; + const bedStartZ = 0; + const legXPositions = [ + 0 + legSize / 2 + thickness, + ...(extraLegsX + ? range(0, bedLengthOuter, bedLengthOuter / (extraLegsX + 1)).slice(1) + : []), + bedLengthOuter - legSize / 2 - thickness, + ]; + const legYPositions = (index: number) => + [ + 0 + legSize / 2 + thickness, + ...(extraLegsY && (index == 0 || index == (legXPositions.length - 1)) + ? range(0, bedWidthOuter, bedWidthOuter / (extraLegsY + 1)).slice(1) + : []), + bedWidthOuter - legSize / 2 - thickness, + ]; + const casterHeight = legSize * 1.375; + + const Bed = ({ children }: { children: React.ReactElement }) => + + {children} + ; + + const Soil = ({ children }: { children: React.ReactElement }) => { + const soilDepth = bedHeight + (soilHeight - 50) - soilHeight; + return + {children} + ; + }; + + const bedColor = "#ad7039"; + return + + + + + + + + + + + + + {legXPositions.map((x, index) => + + {legYPositions(index).map(y => { + const legTopOffset = legsFlush ? bedHeight / 2 : bedHeight; + return + + + + ; + })} + )} + ; +}; diff --git a/frontend/three_d_garden/components.tsx b/frontend/three_d_garden/components.tsx index 18cc9e443..954c54e5a 100644 --- a/frontend/three_d_garden/components.tsx +++ b/frontend/three_d_garden/components.tsx @@ -3,6 +3,7 @@ import { AmbientLightProps, DirectionalLightProps, GroupProps, + MeshPhongMaterialProps, MeshProps, PointLightProps, } from "@react-three/fiber"; @@ -24,3 +25,6 @@ export const Mesh = (props: MeshProps) => export const PointLight = (props: PointLightProps) => ; + +export const MeshPhongMaterial = (props: MeshPhongMaterialProps) => + ; diff --git a/frontend/three_d_garden/config.ts b/frontend/three_d_garden/config.ts new file mode 100644 index 000000000..e809ad295 --- /dev/null +++ b/frontend/three_d_garden/config.ts @@ -0,0 +1,410 @@ +export interface Config { + sizePreset: string; + bedType: string; + otherPreset: string; + label: string; + botSizeX: number; + botSizeY: number; + botSizeZ: number; + bedWallThickness: number; + bedHeight: number; + ccSupportSize: number; + x: number; + y: number; + z: number; + beamLength: number; + columnLength: number; + zAxisLength: number; + bedXOffset: number; + bedYOffset: number; + bedZOffset: number; + zGantryOffset: number; + bedWidthOuter: number; + bedLengthOuter: number; + legSize: number; + legsFlush: boolean; + extraLegsX: number; + extraLegsY: number; + bedBrightness: number; + soilBrightness: number; + soilHeight: number; + plants: string; + labels: boolean; + labelsOnHover: boolean; + ground: boolean; + grid: boolean; + axes: boolean; + trail: boolean; + tracks: boolean; + clouds: boolean; + sunInclination: number; + sunAzimuth: number; + perspective: boolean; + bot: boolean; + laser: boolean; + tool: string; + cableCarriers: boolean; + viewCube: boolean; + stats: boolean; + config: boolean; + zoom: boolean; + pan: boolean; + bounds: boolean; + threeAxes: boolean; + xyDimensions: boolean; + zDimension: boolean; + promoInfo: boolean; + solar: boolean; + utilitiesPost: boolean; + packaging: boolean; + lab: boolean; + people: boolean; + scene: string; + lowDetail: boolean; +} + +export const INITIAL: Config = { + sizePreset: "Genesis", + bedType: "Standard", + otherPreset: "Initial", + label: "FarmBot Genesis v1.7", + botSizeX: 2720, + botSizeY: 1230, + botSizeZ: 500, + bedWallThickness: 40, + bedHeight: 300, + ccSupportSize: 50, + x: 300, + y: 700, + z: 200, + beamLength: 1500, + columnLength: 500, + zAxisLength: 1000, + bedXOffset: 140, + bedYOffset: 60, + bedZOffset: 0, + zGantryOffset: 140, + bedWidthOuter: 1360, + bedLengthOuter: 3000, + legSize: 100, + legsFlush: true, + extraLegsX: 1, + extraLegsY: 0, + bedBrightness: 8, + soilBrightness: 6, + soilHeight: 500, + plants: "Spring", + labels: false, + labelsOnHover: true, + ground: true, + grid: false, + axes: false, + trail: false, + tracks: true, + clouds: true, + sunInclination: 140, + sunAzimuth: 230, + perspective: true, + bot: true, + laser: false, + tool: "rotaryTool", + cableCarriers: true, + viewCube: false, + stats: false, + config: false, + zoom: false, + pan: false, + bounds: false, + threeAxes: false, + xyDimensions: false, + zDimension: false, + promoInfo: true, + solar: false, + utilitiesPost: true, + packaging: false, + lab: false, + people: false, + scene: "Outdoor", + lowDetail: false, +}; + +export const STRING_KEYS = [ + "sizePreset", "bedType", "otherPreset", "label", "plants", "tool", "scene", +]; + +export const NUMBER_KEYS = [ + "botSizeX", "botSizeY", "botSizeZ", "bedWallThickness", "bedHeight", + "ccSupportSize", "x", "y", "z", "beamLength", "columnLength", "zAxisLength", + "bedXOffset", "bedYOffset", "bedZOffset", "zGantryOffset", "bedWidthOuter", + "bedLengthOuter", "legSize", "extraLegsX", "extraLegsY", "bedBrightness", + "soilBrightness", "soilHeight", "sunInclination", "sunAzimuth", +]; + +export const BOOLEAN_KEYS = [ + "legsFlush", "labels", "labelsOnHover", "ground", "grid", "axes", "trail", + "tracks", "clouds", "perspective", "bot", "laser", "cableCarriers", + "viewCube", "stats", "config", "zoom", "pan", "bounds", "threeAxes", + "xyDimensions", "zDimension", "promoInfo", "solar", "utilitiesPost", + "packaging", "lab", "people", "lowDetail", +]; + +export const PRESETS: Record = { + "Jr": { + ...INITIAL, + sizePreset: "Jr", + bedType: "Standard", + label: "FarmBot Jr", + botSizeX: 620, + botSizeY: 220, + botSizeZ: 250, + beamLength: 550, + columnLength: 300, + zAxisLength: 750, + bedXOffset: 140, + bedYOffset: 80, + zGantryOffset: 140, + bedWidthOuter: 400, + bedLengthOuter: 900, + extraLegsX: 0, + extraLegsY: 0, + soilHeight: 280, + tracks: true, + }, + "Genesis": { + ...INITIAL, + sizePreset: "Genesis", + bedType: "Standard", + label: "FarmBot Genesis v1.7", + botSizeX: 2720, + botSizeY: 1230, + botSizeZ: 500, + beamLength: 1500, + columnLength: 500, + zAxisLength: 1000, + bedXOffset: 140, + bedYOffset: 60, + zGantryOffset: 140, + bedWidthOuter: 1360, + bedLengthOuter: 3000, + extraLegsX: 1, + extraLegsY: 0, + soilHeight: 500, + tracks: true, + }, + "Genesis XL": { + ...INITIAL, + sizePreset: "Genesis XL", + bedType: "Standard", + label: "FarmBot Genesis XL v1.7", + botSizeX: 5720, + botSizeY: 2730, + botSizeZ: 500, + beamLength: 3000, + columnLength: 500, + zAxisLength: 1000, + bedXOffset: 140, + bedYOffset: 60, + zGantryOffset: 140, + bedWidthOuter: 2860, + bedLengthOuter: 6000, + extraLegsX: 3, + extraLegsY: 1, + soilHeight: 500, + tracks: true, + }, + "Initial": INITIAL, + "Minimal": { + ...INITIAL, + bedWallThickness: 40, + bedHeight: 300, + x: 300, + y: 200, + z: 200, + ccSupportSize: 50, + legSize: 100, + legsFlush: false, + bedBrightness: 8, + soilBrightness: 6, + plants: "", + labels: false, + labelsOnHover: false, + ground: true, + grid: false, + axes: false, + trail: false, + clouds: false, + sunInclination: 90, + sunAzimuth: 0, + perspective: true, + bot: true, + laser: false, + tool: "", + cableCarriers: true, + viewCube: false, + stats: false, + config: false, + zoom: true, + pan: true, + bounds: false, + threeAxes: false, + xyDimensions: false, + zDimension: false, + promoInfo: false, + solar: false, + utilitiesPost: false, + packaging: false, + lab: false, + people: false, + scene: "Outdoor", + lowDetail: false, + }, + "Maximal": { + ...INITIAL, + bedWallThickness: 40, + bedHeight: 300, + x: 300, + y: 200, + z: 200, + ccSupportSize: 50, + legSize: 100, + legsFlush: true, + bedBrightness: 8, + soilBrightness: 6, + plants: "Spring", + labels: true, + labelsOnHover: false, + ground: true, + grid: true, + axes: true, + trail: true, + clouds: true, + sunInclination: 30, + sunAzimuth: 45, + perspective: true, + bot: true, + laser: true, + tool: "", + cableCarriers: true, + viewCube: true, + stats: true, + config: true, + zoom: true, + pan: true, + bounds: true, + threeAxes: true, + xyDimensions: true, + zDimension: true, + promoInfo: true, + solar: true, + utilitiesPost: true, + packaging: true, + lab: true, + people: true, + scene: "outdoor", + lowDetail: false, + }, +}; + +const SIZE_CONFIG_KEYS: (keyof Config)[] = [ + "sizePreset", "label", "bedType", + "botSizeX", "botSizeY", "botSizeZ", "beamLength", "columnLength", "zAxisLength", + "bedXOffset", "bedYOffset", "zGantryOffset", "bedWidthOuter", "bedLengthOuter", + "extraLegsX", "extraLegsY", "soilHeight", "tracks", +]; + +const OTHER_CONFIG_KEYS: (keyof Config)[] = [ + "bedWallThickness", "bedHeight", "x", "y", "z", + "ccSupportSize", "legSize", "legsFlush", + "bedBrightness", "soilBrightness", "plants", "labels", "ground", "grid", "axes", + "trail", "clouds", "sunInclination", "sunAzimuth", "perspective", "bot", "laser", + "tool", "cableCarriers", "viewCube", "stats", "config", "zoom", "bounds", + "threeAxes", "xyDimensions", "zDimension", "labelsOnHover", "promoInfo", "pan", + "solar", "utilitiesPost", "packaging", "lab", "people", "scene", "lowDetail", +]; + +export const modifyConfig = (config: Config, update: Partial) => { + const newConfig: Config = { ...config, ...update }; + if (update.sizePreset) { + const presetConfig = PRESETS[update.sizePreset]; + SIZE_CONFIG_KEYS.map(key => newConfig[key] = presetConfig[key] as never); + if (update.sizePreset == "Jr") { + newConfig.x = 100; + newConfig.y = 100; + newConfig.z = 50; + } + } + if (update.scene) { + newConfig.lab = update.scene == "Lab"; + newConfig.clouds = update.scene != "Lab"; + newConfig.people = update.scene == "Lab"; + newConfig.bedType = + (update.scene == "Lab" && newConfig.sizePreset != "Genesis XL") + ? "Mobile" + : "Standard"; + } + if (update.bedType || (newConfig.bedType != config.bedType)) { + newConfig.bedZOffset = newConfig.bedType == "Mobile" ? 500 : 0; + newConfig.legsFlush = newConfig.bedType != "Mobile"; + } + if (update.otherPreset) { + if (update.otherPreset == "Reset all") { + Object.keys(config).map(key => { + const configKey = key as keyof Config; + newConfig[configKey] = INITIAL[configKey] as never; + }); + } else { + const presetConfig = PRESETS[update.otherPreset]; + OTHER_CONFIG_KEYS.map(key => newConfig[key] = presetConfig[key] as never); + } + } + return newConfig; +}; + +export const KIT_LOOKUP: { [x: string]: string } = { + "genesis": "Genesis", + "genesis_xl": "Genesis XL", + "jr": "Jr", +}; + +export const modifyConfigsFromUrlParams = (config: Config) => { + let newConfig: Config = { ...config }; + const urlParams = new URLSearchParams(window.location.search); + const kit = urlParams.get("kit")?.toLowerCase(); + if (kit) { + const sizePreset = KIT_LOOKUP[kit]; + if (sizePreset && sizePreset != config.sizePreset) { + newConfig = modifyConfig(newConfig, { sizePreset }); + } + } + STRING_KEYS.map(key => { + const value = urlParams.get(key); + if (value) { + newConfig = modifyConfig(newConfig, { [key]: value }); + } + }); + NUMBER_KEYS.map(key => { + const value = urlParams.get(key); + if (value) { + newConfig = modifyConfig(newConfig, { [key]: parseInt(value) }); + } + }); + BOOLEAN_KEYS.map(key => { + const value = urlParams.get(key); + if (value) { + newConfig = modifyConfig(newConfig, { [key]: value == "true" }); + } + }); + return newConfig; +}; + +type SeasonProperties = { + sunIntensity: number; + sunColor: string; + cloudOpacity: number; +}; +export const seasonProperties: Record = { + Winter: { sunIntensity: 4 / 4, sunColor: "#A0C4FF", cloudOpacity: 0.85 }, + Spring: { sunIntensity: 7 / 4, sunColor: "#BDE0FE", cloudOpacity: 0.2 }, + Summer: { sunIntensity: 9 / 4, sunColor: "#FFFFFF", cloudOpacity: 0 }, + Fall: { sunIntensity: 5.5 / 4, sunColor: "#FFD6BC", cloudOpacity: 0.3 }, +}; diff --git a/frontend/three_d_garden/index.tsx b/frontend/three_d_garden/index.tsx index c05144943..9421354f5 100644 --- a/frontend/three_d_garden/index.tsx +++ b/frontend/three_d_garden/index.tsx @@ -1,25 +1,32 @@ -import { Circle, PerspectiveCamera, OrbitControls, Box } from "@react-three/drei"; +import { Circle, PerspectiveCamera, OrbitControls } from "@react-three/drei"; import { Canvas } from "@react-three/fiber"; import React from "react"; import { AmbientLight, DirectionalLight } from "./components"; +import { Config } from "./config"; +import { Bed } from "./bed"; export interface ThreeDGardenProps { + config: Config; } export const ThreeDGarden = (props: ThreeDGardenProps) => { - props; return
- +
; }; export interface ThreeDGardenModelProps { + config: Config; } export const ThreeDGardenModel = (props: ThreeDGardenModelProps) => { - props; + const mid = { + x: props.config.bedLengthOuter / 2, + y: props.config.bedWidthOuter / 2, + z: props.config.bedHeight, + }; return { rotation={[0, 0, 0]} up={[0, 0, 1]} /> @@ -36,12 +43,7 @@ export const ThreeDGardenModel = (props: ThreeDGardenModelProps) => { args={[30000, 16]} position={[0, 0, -10]}> - - - + ; };