actually use the units the user sets (#727)
* actually use the units the user sets Signed-off-by: Jess Frazelle <github@jessfraz.com> * update kittycad lib Signed-off-by: Jess Frazelle <github@jessfraz.com> * next Signed-off-by: Jess Frazelle <github@jessfraz.com> * fix tests Signed-off-by: Jess Frazelle <github@jessfraz.com> * updates Signed-off-by: Jess Frazelle <github@jessfraz.com> * fix bug Signed-off-by: Jess Frazelle <github@jessfraz.com> * fix types Signed-off-by: Jess Frazelle <github@jessfraz.com> --------- Signed-off-by: Jess Frazelle <github@jessfraz.com>
This commit is contained in:
@ -10,7 +10,7 @@
|
|||||||
"@fortawesome/react-fontawesome": "^0.2.0",
|
"@fortawesome/react-fontawesome": "^0.2.0",
|
||||||
"@headlessui/react": "^1.7.13",
|
"@headlessui/react": "^1.7.13",
|
||||||
"@headlessui/tailwindcss": "^0.2.0",
|
"@headlessui/tailwindcss": "^0.2.0",
|
||||||
"@kittycad/lib": "^0.0.39",
|
"@kittycad/lib": "^0.0.40",
|
||||||
"@lezer/javascript": "^1.4.7",
|
"@lezer/javascript": "^1.4.7",
|
||||||
"@open-rpc/client-js": "^1.8.1",
|
"@open-rpc/client-js": "^1.8.1",
|
||||||
"@react-hook/resize-observer": "^1.2.6",
|
"@react-hook/resize-observer": "^1.2.6",
|
||||||
|
@ -6,8 +6,12 @@ import React from 'react'
|
|||||||
import { useFormik } from 'formik'
|
import { useFormik } from 'formik'
|
||||||
import { Models } from '@kittycad/lib'
|
import { Models } from '@kittycad/lib'
|
||||||
import { engineCommandManager } from '../lang/std/engineConnection'
|
import { engineCommandManager } from '../lang/std/engineConnection'
|
||||||
|
import { useGlobalStateContext } from 'hooks/useGlobalStateContext'
|
||||||
|
|
||||||
type OutputFormat = Models['OutputFormat_type']
|
type OutputFormat = Models['OutputFormat_type']
|
||||||
|
type OutputTypeKey = OutputFormat['type']
|
||||||
|
type ExtractStorageTypes<T> = T extends { storage: infer U } ? U : never
|
||||||
|
type StorageUnion = ExtractStorageTypes<OutputFormat>
|
||||||
|
|
||||||
interface ExportButtonProps extends React.PropsWithChildren {
|
interface ExportButtonProps extends React.PropsWithChildren {
|
||||||
className?: {
|
className?: {
|
||||||
@ -19,9 +23,18 @@ interface ExportButtonProps extends React.PropsWithChildren {
|
|||||||
|
|
||||||
export const ExportButton = ({ children, className }: ExportButtonProps) => {
|
export const ExportButton = ({ children, className }: ExportButtonProps) => {
|
||||||
const [modalIsOpen, setIsOpen] = React.useState(false)
|
const [modalIsOpen, setIsOpen] = React.useState(false)
|
||||||
|
const {
|
||||||
|
settings: {
|
||||||
|
state: {
|
||||||
|
context: { baseUnit },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} = useGlobalStateContext()
|
||||||
|
|
||||||
const defaultType = 'gltf'
|
const defaultType = 'gltf'
|
||||||
const [type, setType] = React.useState(defaultType)
|
const [type, setType] = React.useState<OutputTypeKey>(defaultType)
|
||||||
|
const defaultStorage = 'embedded'
|
||||||
|
const [storage, setStorage] = React.useState<StorageUnion>(defaultStorage)
|
||||||
|
|
||||||
function openModal() {
|
function openModal() {
|
||||||
setIsOpen(true)
|
setIsOpen(true)
|
||||||
@ -34,7 +47,7 @@ export const ExportButton = ({ children, className }: ExportButtonProps) => {
|
|||||||
// Default to gltf and embedded.
|
// Default to gltf and embedded.
|
||||||
const initialValues: OutputFormat = {
|
const initialValues: OutputFormat = {
|
||||||
type: defaultType,
|
type: defaultType,
|
||||||
storage: 'embedded',
|
storage: defaultStorage,
|
||||||
presentation: 'pretty',
|
presentation: 'pretty',
|
||||||
}
|
}
|
||||||
const formik = useFormik({
|
const formik = useFormik({
|
||||||
@ -62,6 +75,17 @@ export const ExportButton = ({ children, className }: ExportButtonProps) => {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (values.type === 'obj' || values.type === 'stl') {
|
||||||
|
values.units = baseUnit
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
values.type === 'ply' ||
|
||||||
|
values.type === 'stl' ||
|
||||||
|
values.type === 'gltf'
|
||||||
|
) {
|
||||||
|
// Set the storage type.
|
||||||
|
values.storage = storage
|
||||||
|
}
|
||||||
engineCommandManager.sendSceneCommand({
|
engineCommandManager.sendSceneCommand({
|
||||||
type: 'modeling_cmd_req',
|
type: 'modeling_cmd_req',
|
||||||
cmd: {
|
cmd: {
|
||||||
@ -71,6 +95,7 @@ export const ExportButton = ({ children, className }: ExportButtonProps) => {
|
|||||||
// in the scene to export. In that case, you'd pass the IDs thru here.
|
// in the scene to export. In that case, you'd pass the IDs thru here.
|
||||||
entity_ids: [],
|
entity_ids: [],
|
||||||
format: values,
|
format: values,
|
||||||
|
source_unit: baseUnit,
|
||||||
},
|
},
|
||||||
cmd_id: uuidv4(),
|
cmd_id: uuidv4(),
|
||||||
})
|
})
|
||||||
@ -105,7 +130,17 @@ export const ExportButton = ({ children, className }: ExportButtonProps) => {
|
|||||||
id="type"
|
id="type"
|
||||||
name="type"
|
name="type"
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setType(e.target.value)
|
setType(e.target.value as OutputTypeKey)
|
||||||
|
if (e.target.value === 'gltf') {
|
||||||
|
// Set default to embedded.
|
||||||
|
setStorage('embedded')
|
||||||
|
} else if (e.target.value === 'ply') {
|
||||||
|
// Set default to ascii.
|
||||||
|
setStorage('ascii')
|
||||||
|
} else if (e.target.value === 'stl') {
|
||||||
|
// Set default to ascii.
|
||||||
|
setStorage('ascii')
|
||||||
|
}
|
||||||
formik.handleChange(e)
|
formik.handleChange(e)
|
||||||
}}
|
}}
|
||||||
className="bg-chalkboard-20 dark:bg-chalkboard-90 w-full"
|
className="bg-chalkboard-20 dark:bg-chalkboard-90 w-full"
|
||||||
@ -123,10 +158,10 @@ export const ExportButton = ({ children, className }: ExportButtonProps) => {
|
|||||||
<select
|
<select
|
||||||
id="storage"
|
id="storage"
|
||||||
name="storage"
|
name="storage"
|
||||||
onChange={formik.handleChange}
|
onChange={(e) => {
|
||||||
value={
|
setStorage(e.target.value as StorageUnion)
|
||||||
'storage' in formik.values ? formik.values.storage : ''
|
formik.handleChange(e)
|
||||||
}
|
}}
|
||||||
className="bg-chalkboard-20 dark:bg-chalkboard-90 w-full"
|
className="bg-chalkboard-20 dark:bg-chalkboard-90 w-full"
|
||||||
>
|
>
|
||||||
{type === 'gltf' && (
|
{type === 'gltf' && (
|
||||||
|
@ -2,6 +2,8 @@ import { fireEvent, render, screen } from '@testing-library/react'
|
|||||||
import { BrowserRouter } from 'react-router-dom'
|
import { BrowserRouter } from 'react-router-dom'
|
||||||
import ProjectSidebarMenu from './ProjectSidebarMenu'
|
import ProjectSidebarMenu from './ProjectSidebarMenu'
|
||||||
import { ProjectWithEntryPointMetadata } from '../Router'
|
import { ProjectWithEntryPointMetadata } from '../Router'
|
||||||
|
import { GlobalStateProvider } from './GlobalStateProvider'
|
||||||
|
import CommandBarProvider from './CommandBar'
|
||||||
|
|
||||||
const now = new Date()
|
const now = new Date()
|
||||||
const projectWellFormed = {
|
const projectWellFormed = {
|
||||||
@ -38,7 +40,11 @@ describe('ProjectSidebarMenu tests', () => {
|
|||||||
test('Renders the project name', () => {
|
test('Renders the project name', () => {
|
||||||
render(
|
render(
|
||||||
<BrowserRouter>
|
<BrowserRouter>
|
||||||
|
<CommandBarProvider>
|
||||||
|
<GlobalStateProvider>
|
||||||
<ProjectSidebarMenu project={projectWellFormed} />
|
<ProjectSidebarMenu project={projectWellFormed} />
|
||||||
|
</GlobalStateProvider>
|
||||||
|
</CommandBarProvider>
|
||||||
</BrowserRouter>
|
</BrowserRouter>
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -55,7 +61,11 @@ describe('ProjectSidebarMenu tests', () => {
|
|||||||
test('Renders app name if given no project', () => {
|
test('Renders app name if given no project', () => {
|
||||||
render(
|
render(
|
||||||
<BrowserRouter>
|
<BrowserRouter>
|
||||||
|
<CommandBarProvider>
|
||||||
|
<GlobalStateProvider>
|
||||||
<ProjectSidebarMenu />
|
<ProjectSidebarMenu />
|
||||||
|
</GlobalStateProvider>
|
||||||
|
</CommandBarProvider>
|
||||||
</BrowserRouter>
|
</BrowserRouter>
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -69,7 +79,14 @@ describe('ProjectSidebarMenu tests', () => {
|
|||||||
test('Renders as a link if set to do so', () => {
|
test('Renders as a link if set to do so', () => {
|
||||||
render(
|
render(
|
||||||
<BrowserRouter>
|
<BrowserRouter>
|
||||||
<ProjectSidebarMenu project={projectWellFormed} renderAsLink={true} />
|
<CommandBarProvider>
|
||||||
|
<GlobalStateProvider>
|
||||||
|
<ProjectSidebarMenu
|
||||||
|
project={projectWellFormed}
|
||||||
|
renderAsLink={true}
|
||||||
|
/>
|
||||||
|
</GlobalStateProvider>
|
||||||
|
</CommandBarProvider>
|
||||||
</BrowserRouter>
|
</BrowserRouter>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ import { assign, createMachine } from 'xstate'
|
|||||||
import { CommandBarMeta } from '../lib/commands'
|
import { CommandBarMeta } from '../lib/commands'
|
||||||
import { Themes, getSystemTheme, setThemeClass } from '../lib/theme'
|
import { Themes, getSystemTheme, setThemeClass } from '../lib/theme'
|
||||||
import { CameraSystem, cameraSystems } from 'lib/cameraControls'
|
import { CameraSystem, cameraSystems } from 'lib/cameraControls'
|
||||||
|
import { Models } from '@kittycad/lib'
|
||||||
|
|
||||||
export const DEFAULT_PROJECT_NAME = 'project-$nnn'
|
export const DEFAULT_PROJECT_NAME = 'project-$nnn'
|
||||||
|
|
||||||
@ -11,11 +12,11 @@ export enum UnitSystem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const baseUnits = {
|
export const baseUnits = {
|
||||||
imperial: ['in', 'ft'],
|
imperial: ['in', 'ft', 'yd'],
|
||||||
metric: ['mm', 'cm', 'm'],
|
metric: ['mm', 'cm', 'm'],
|
||||||
} as const
|
} as const
|
||||||
|
|
||||||
export type BaseUnit = 'in' | 'ft' | 'mm' | 'cm' | 'm'
|
export type BaseUnit = Models['UnitLength_type']
|
||||||
|
|
||||||
export const baseUnitsUnion = Object.values(baseUnits).flatMap((v) => v)
|
export const baseUnitsUnion = Object.values(baseUnits).flatMap((v) => v)
|
||||||
|
|
||||||
|
@ -6,10 +6,10 @@
|
|||||||
serial-integration = { max-threads = 4 }
|
serial-integration = { max-threads = 4 }
|
||||||
|
|
||||||
[profile.default]
|
[profile.default]
|
||||||
slow-timeout = { period = "10s", terminate-after = 1 }
|
slow-timeout = { period = "60s", terminate-after = 1 }
|
||||||
|
|
||||||
[profile.ci]
|
[profile.ci]
|
||||||
slow-timeout = { period = "60s", terminate-after = 10 }
|
slow-timeout = { period = "120s", terminate-after = 10 }
|
||||||
|
|
||||||
[[profile.default.overrides]]
|
[[profile.default.overrides]]
|
||||||
filter = "test(serial_test_)"
|
filter = "test(serial_test_)"
|
||||||
|
4
src/wasm-lib/Cargo.lock
generated
4
src/wasm-lib/Cargo.lock
generated
@ -1412,9 +1412,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kittycad"
|
name = "kittycad"
|
||||||
version = "0.2.27"
|
version = "0.2.28"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c82a3e5373afc07fae47be6afbae0e5070bf765a730923f96ab532138e76ce9a"
|
checksum = "35b2f9302648dbb06fd7121687f9505fc3179eba84111a06d76b246e3158f5dc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 95 KiB After Width: | Height: | Size: 96 KiB |
@ -1530,10 +1530,10 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@juggle/resize-observer/-/resize-observer-3.4.0.tgz#08d6c5e20cf7e4cc02fd181c4b0c225cd31dbb60"
|
resolved "https://registry.yarnpkg.com/@juggle/resize-observer/-/resize-observer-3.4.0.tgz#08d6c5e20cf7e4cc02fd181c4b0c225cd31dbb60"
|
||||||
integrity sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==
|
integrity sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==
|
||||||
|
|
||||||
"@kittycad/lib@^0.0.39":
|
"@kittycad/lib@^0.0.40":
|
||||||
version "0.0.39"
|
version "0.0.40"
|
||||||
resolved "https://registry.yarnpkg.com/@kittycad/lib/-/lib-0.0.39.tgz#e548acf5ff7d45a1f1ec9ad2c61ddcfc30d159b7"
|
resolved "https://registry.yarnpkg.com/@kittycad/lib/-/lib-0.0.40.tgz#0ba00c642e76648fb7cb1337e799b9d24724312d"
|
||||||
integrity sha512-cB4wNjsKTMpJUn/kMK3qtkVAqB1csSglqThe+bj02nC1kWTB1XgYxksooc/Gzl1MoK1/n0OPQcbOb7Tojb836A==
|
integrity sha512-R8sQKLWe3lQC7l7cyY49oFgeiMvRh8+bCaaoLiIVYT+YiE9TaS+uwwF1+sR7MiX6YZp/YCBBPFGj4Ci0VHC9Bg==
|
||||||
dependencies:
|
dependencies:
|
||||||
node-fetch "3.3.2"
|
node-fetch "3.3.2"
|
||||||
openapi-types "^12.0.0"
|
openapi-types "^12.0.0"
|
||||||
|
Reference in New Issue
Block a user