Skip to content
This repository has been archived by the owner on Aug 21, 2024. It is now read-only.

VariantComponent #8112

Merged
merged 2 commits into from
Jun 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions packages/client-core/i18n/en/editor.json
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,9 @@
"description": "Link to a room or a website.",
"lbl-url": "URL"
},
"lod": {
"variant": {
"name": "Variant",
"description": "Load different assets based on heuristics",
"device": "Device",
"device-mobile": "Mobile",
"device-desktop": "Desktop",
Expand All @@ -246,7 +248,8 @@
"heuristic-sceneScale": "Scene Scale",
"heuristic-manual": "Manual",
"heuristic-device": "Device",
"distance": "Distance",
"minDistance": "Minimum Distance",
"maxDistance": "Maximum Distance",
"src": "Source"
},
"map": {
Expand Down
56 changes: 3 additions & 53 deletions packages/editor/src/components/properties/ModelNodeEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,42 +26,30 @@ Ethereal Engine. All Rights Reserved.
import React, { useCallback } from 'react'
import { useTranslation } from 'react-i18next'

import {
DefaultModelTransformParameters,
ModelTransformParameters
} from '@etherealengine/engine/src/assets/classes/ModelTransform'
import { AnimationManager } from '@etherealengine/engine/src/avatar/AnimationManager'
import { LoopAnimationComponent } from '@etherealengine/engine/src/avatar/components/LoopAnimationComponent'
import {
addComponent,
getComponent,
getOptionalComponent,
hasComponent,
removeComponent,
setComponent,
useComponent
} from '@etherealengine/engine/src/ecs/functions/ComponentFunctions'
import { EquippableComponent } from '@etherealengine/engine/src/interaction/components/EquippableComponent'
import { CallbackComponent, getCallback } from '@etherealengine/engine/src/scene/components/CallbackComponent'
import { getCallback } from '@etherealengine/engine/src/scene/components/CallbackComponent'
import { getEntityErrors } from '@etherealengine/engine/src/scene/components/ErrorComponent'
import { ModelComponent } from '@etherealengine/engine/src/scene/components/ModelComponent'
import { addError, clearErrors } from '@etherealengine/engine/src/scene/functions/ErrorFunctions'
import { State, useState } from '@etherealengine/hyperflux'
import { useState } from '@etherealengine/hyperflux'

import ViewInArIcon from '@mui/icons-material/ViewInAr'

import exportGLTF from '../../functions/exportGLTF'
import { convertToScaffold, createLODsFromModel } from '../../functions/lodsFromModel'
import { LODsFromModelParameters } from '../../functions/lodsFromModel'
import BooleanInput from '../inputs/BooleanInput'
import { Button, PropertiesPanelButton } from '../inputs/Button'
import { PropertiesPanelButton } from '../inputs/Button'
import InputGroup from '../inputs/InputGroup'
import ModelInput from '../inputs/ModelInput'
import SelectInput from '../inputs/SelectInput'
import CollapsibleBlock from '../layout/CollapsibleBlock'
import PaginatedList from '../layout/PaginatedList'
import Well from '../layout/Well'
import GLTFTransformProperties from './GLTFTransformProperties'
import ModelTransformProperties from './ModelTransformProperties'
import NodeEditor from './NodeEditor'
import ScreenshareTargetNodeEditor from './ScreenshareTargetNodeEditor'
Expand Down Expand Up @@ -89,11 +77,6 @@ export const ModelNodeEditor: EditorComponentType = (props) => {

const loopAnimationComponent = getOptionalComponent(entity, LoopAnimationComponent)

const lodParms = useState<LODsFromModelParameters>(() => ({
serialize: false,
levels: []
}))

const onChangeEquippable = useCallback(() => {
if (isEquippable.value) {
removeComponent(props.entity, EquippableComponent)
Expand Down Expand Up @@ -156,12 +139,6 @@ export const ModelNodeEditor: EditorComponentType = (props) => {
getCallback(props.entity, 'xre.play')!()
}

const onAddLODLevel = useCallback(() => {
lodParms.levels[lodParms.levels.length].set({
...DefaultModelTransformParameters
})
}, [])

return (
<NodeEditor
name={t('editor:properties.model.title')}
Expand Down Expand Up @@ -208,33 +185,6 @@ export const ModelNodeEditor: EditorComponentType = (props) => {
</InputGroup>
<ScreenshareTargetNodeEditor entity={props.entity} multiEdit={props.multiEdit} />
<ShadowProperties entity={props.entity} />
<CollapsibleBlock label={t('editor:properties.model.lods.label')}>
<div className="bg-gradient-to-b from-blue-gray-400 to-cool-gray-800 rounded-lg shadow-lg">
<div className="px-4 py-2 border-b border-gray-300">
<h2 className="text-lg font-semibold text-gray-100">LODs</h2>
</div>
<InputGroup name="Serialize" label={t('editor:properties.model.lods.serialize')}>
<BooleanInput value={lodParms.value.serialize} onChange={lodParms.serialize.set} />
</InputGroup>
<InputGroup name="LOD Level Parameters" label={t('editor:properties.model.lods.lodLevelParameters')}>
<Button onClick={onAddLODLevel}>Add LOD Level</Button>
</InputGroup>
<PaginatedList
list={lodParms.levels}
element={(lodLevel: State<ModelTransformParameters>) => {
return <GLTFTransformProperties transformParms={lodLevel} onChange={lodLevel.set} />
}}
/>
<div className="p-4">
<Button onClick={convertToScaffold.bind({}, entity)}>Convert to Scaffold</Button>
</div>
<div className="p-4">
<Button onClick={createLODsFromModel.bind({}, entity, lodParms.value)}>
{t('editor:properties.model.lods.generate')}
</Button>
</div>
</div>
</CollapsibleBlock>
<ModelTransformProperties modelState={modelComponent} onChangeModel={(val) => modelComponent.src.set(val)} />
{!exporting.value && modelComponent.src.value && (
<Well>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,32 +27,26 @@ import React, { useCallback } from 'react'
import { useTranslation } from 'react-i18next'

import { Entity } from '@etherealengine/engine/src/ecs/classes/Entity'
import {
getComponent,
getMutableComponent,
useComponent
} from '@etherealengine/engine/src/ecs/functions/ComponentFunctions'
import { LODComponent, LODLevel } from '@etherealengine/engine/src/scene/components/LODComponent'
import { ModelComponent } from '@etherealengine/engine/src/scene/components/ModelComponent'
import { getComponent, useComponent } from '@etherealengine/engine/src/ecs/functions/ComponentFunctions'
import { NameComponent } from '@etherealengine/engine/src/scene/components/NameComponent'
import { VariantComponent, VariantLevel } from '@etherealengine/engine/src/scene/components/VariantComponent'
import { State } from '@etherealengine/hyperflux'

import DeblurIcon from '@mui/icons-material/Deblur'

import { serializeLOD } from '../../functions/lodsFromModel'
import { Button } from '../inputs/Button'
import InputGroup, { InputGroupContainer } from '../inputs/InputGroup'
import InputGroup from '../inputs/InputGroup'
import ModelInput from '../inputs/ModelInput'
import NumericInput from '../inputs/NumericInput'
import NumericInputGroup from '../inputs/NumericInputGroup'
import SelectInput from '../inputs/SelectInput'
import PaginatedList from '../layout/PaginatedList'
import NodeEditor from './NodeEditor'
import { EditorComponentType } from './Util'

export const LODProperties: EditorComponentType = ({ entity }: { entity: Entity }) => {
export const VariantNodeEditor: EditorComponentType = (props: { entity: Entity }) => {
const { t } = useTranslation()

const lodComponent = useComponent(entity, LODComponent)
const entity = props.entity
const variantComponent = useComponent(entity, VariantComponent)
const nameComponent = getComponent(entity, NameComponent)

const onChangeLevelProperty = useCallback(
Expand All @@ -64,90 +58,92 @@ export const LODProperties: EditorComponentType = ({ entity }: { entity: Entity
[entity]
)
return (
<div>
<h2 className="text-white text-2xl font-bold m-4">LODs</h2>
<NodeEditor
name={t('editor:properties.variant.name')}
description={t('editor:properties.variant.description')}
{...props}
>
<div className="bg-gray-800 rounded-lg p-4 m-4">
<h2 className="text-white text-xl font-bold mb-4">{nameComponent}</h2>
<InputGroup name="lodHeuristic" label={t('editor:properties.lod.heuristic')}>
<InputGroup name="lodHeuristic" label={t('editor:properties.variant.heuristic')}>
<SelectInput
value={lodComponent.lodHeuristic.value}
onChange={(val: typeof lodComponent.lodHeuristic.value) => lodComponent.lodHeuristic.set(val)}
value={variantComponent.heuristic.value}
onChange={(val: typeof variantComponent.heuristic.value) => variantComponent.heuristic.set(val)}
options={[
{ value: 'DISTANCE', label: t('editor:properties.lod.heuristic-distance') },
{ value: 'SCENE_SCALE', label: t('editor:properties.lod.heuristic-sceneScale') },
{ value: 'MANUAL', label: t('editor:properties.lod.heuristic-manual') },
{ value: 'DEVICE', label: t('editor:properties.lod.heuristic-device') }
{ value: 'DISTANCE', label: t('editor:properties.variant.heuristic-distance') },
{ value: 'SCENE_SCALE', label: t('editor:properties.variant.heuristic-sceneScale') },
{ value: 'MANUAL', label: t('editor:properties.variant.heuristic-manual') },
{ value: 'DEVICE', label: t('editor:properties.variant.heuristic-device') }
]}
/>
</InputGroup>
<Button
onClick={() =>
lodComponent.levels[lodComponent.levels.length].set({
distance: 0,
variantComponent.levels[variantComponent.levels.length].set({
src: '',
loaded: false,
metadata: {},
model: null
metadata: {}
})
}
>
Add LOD
Add Variant
</Button>
<PaginatedList
options={{ countPerPage: 1 }}
list={lodComponent.levels}
element={(level: State<LODLevel>) => {
options={{ countPerPage: 6 }}
list={variantComponent.levels}
element={(level: State<VariantLevel>) => {
return (
<div className="bg-gray-900 m-2">
<div style={{ margin: '2em' }}>
<InputGroup name="distance" label={t('editor:properties.lod.distance')}>
<NumericInput value={level.distance.value} onChange={onChangeLevelProperty(level, 'distance')} />
</InputGroup>
<InputGroup name="src" label={t('editor:properties.lod.src')}>
<InputGroup name="src" label={t('editor:properties.variant.src')}>
<ModelInput value={level.src.value} onChange={onChangeLevelProperty(level, 'src')} />
</InputGroup>
{lodComponent.lodHeuristic.value === 'DEVICE' && (
{variantComponent.heuristic.value === 'DEVICE' && (
<>
<InputGroup name="device" label={t('editor:properties.lod.device')}>
<InputGroup name="device" label={t('editor:properties.variant.device')}>
<SelectInput
value={level.metadata['device'].value}
onChange={onChangeLevelProperty(level.metadata, 'device')}
options={[
{ value: 'MOBILE', label: t('editor:properties.lod.device-mobile') },
{ value: 'DESKTOP', label: t('editor:properties.lod.device-desktop') }
{ value: 'MOBILE', label: t('editor:properties.variant.device-mobile') },
{ value: 'DESKTOP', label: t('editor:properties.variant.device-desktop') }
]}
/>
</InputGroup>
</>
)}
{variantComponent.heuristic.value === 'DISTANCE' && (
<>
<InputGroup name="minDistance" label={t('editor:properties.variant.minDistance')}>
<NumericInput
value={level.metadata['minDistance'].value}
onChange={onChangeLevelProperty(level.metadata, 'minDistance')}
/>
</InputGroup>
<InputGroup name="maxDistance" label={t('editor:properties.variant.maxDistance')}>
<NumericInput
value={level.metadata['maxDistance'].value}
onChange={onChangeLevelProperty(level.metadata, 'maxDistance')}
/>
</InputGroup>
</>
)}
</div>
<div className="flex justify-end">
<Button
onClick={() => {
const index = lodComponent.levels.indexOf(level)
lodComponent.levels.set(lodComponent.levels.value.filter((_, i) => i !== index))
const index = variantComponent.levels.indexOf(level)
variantComponent.levels.set(variantComponent.levels.value.filter((_, i) => i !== index))
}}
>
Remove
</Button>
</div>
<div className="flex justify-end">
<Button
onClick={() => {
const model = getComponent(lodComponent.target.value, ModelComponent)
serializeLOD(model.src, entity, level)
}}
>
Serialize
</Button>
</div>
</div>
)
}}
/>
</div>
</div>
</NodeEditor>
)
}

LODProperties.iconComponent = DeblurIcon
VariantNodeEditor.iconComponent = DeblurIcon
6 changes: 3 additions & 3 deletions packages/editor/src/functions/PrefabEditors.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ import { HemisphereLightComponent } from '@etherealengine/engine/src/scene/compo
import { ImageComponent } from '@etherealengine/engine/src/scene/components/ImageComponent'
import { InstancingComponent } from '@etherealengine/engine/src/scene/components/InstancingComponent'
import { InteriorComponent } from '@etherealengine/engine/src/scene/components/InteriorComponent'
import { LODComponent } from '@etherealengine/engine/src/scene/components/LODComponent'
import { MediaComponent } from '@etherealengine/engine/src/scene/components/MediaComponent'
import { MediaSettingsComponent } from '@etherealengine/engine/src/scene/components/MediaSettingsComponent'
import { ModelComponent } from '@etherealengine/engine/src/scene/components/ModelComponent'
Expand All @@ -60,6 +59,7 @@ import { SpawnPointComponent } from '@etherealengine/engine/src/scene/components
import { SplineComponent } from '@etherealengine/engine/src/scene/components/SplineComponent'
import { SpotLightComponent } from '@etherealengine/engine/src/scene/components/SpotLightComponent'
import { SystemComponent } from '@etherealengine/engine/src/scene/components/SystemComponent'
import { VariantComponent } from '@etherealengine/engine/src/scene/components/VariantComponent'
import { VideoComponent } from '@etherealengine/engine/src/scene/components/VideoComponent'
import { VolumetricComponent } from '@etherealengine/engine/src/scene/components/VolumetricComponent'
import { WaterComponent } from '@etherealengine/engine/src/scene/components/WaterComponent'
Expand All @@ -84,7 +84,6 @@ import HemisphereLightNodeEditor from '../components/properties/HemisphereLightN
import ImageNodeEditor from '../components/properties/ImageNodeEditor'
import InstancingNodeEditor from '../components/properties/InstancingNodeEditor'
import InteriorNodeEditor from '../components/properties/InteriorNodeEditor'
import { LODProperties } from '../components/properties/LODProperties'
import MediaNodeEditor from '../components/properties/MediaNodeEditor'
import { MediaSettingsEditor } from '../components/properties/MediaSettingsEditor'
import ModelNodeEditor from '../components/properties/ModelNodeEditor'
Expand All @@ -107,6 +106,7 @@ import SpotLightNodeEditor from '../components/properties/SpotLightNodeEditor'
import SystemNodeEditor from '../components/properties/SystemNodeEditor'
import TransformPropertyGroup from '../components/properties/TransformPropertyGroup'
import { EditorComponentType } from '../components/properties/Util'
import { VariantNodeEditor } from '../components/properties/VariantNodeEditor'
import VideoNodeEditor from '../components/properties/VideoNodeEditor'
import VolumetricNodeEditor from '../components/properties/VolumetricNodeEditor'
import WaterNodeEditor from '../components/properties/WaterNodeEditor'
Expand Down Expand Up @@ -150,7 +150,7 @@ EntityNodeEditor.set(EnvmapComponent, EnvMapEditor)
EntityNodeEditor.set(EnvMapBakeComponent, EnvMapBakeNodeEditor)
EntityNodeEditor.set(InstancingComponent, InstancingNodeEditor)
EntityNodeEditor.set(PersistentAnchorComponent, PersistentAnchorNodeEditor)
EntityNodeEditor.set(LODComponent, LODProperties)
EntityNodeEditor.set(VariantComponent, VariantNodeEditor)

export const prefabIcons = {
[LightPrefabs.ambientLight]: AmbientLightNodeEditor.iconComponent,
Expand Down
Loading