This repository has been archived by the owner on Aug 21, 2024. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* added partial fix for darkened lightmaps on MeshBasicMaterials * added material overrides * Material Overrides: -added refresh button -added reverting to default material on delete * added 2 more materials * materials" * fixed refresh after adding to empty override list Co-authored-by: Gheric Speiginer <gheric.speiginer@gmail.com>
- Loading branch information
Showing
23 changed files
with
2,418 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
180 changes: 180 additions & 0 deletions
180
packages/editor/src/components/inputs/MaterialAssignment.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,180 @@ | ||
import React, { useState } from 'react' | ||
import { useTranslation } from 'react-i18next' | ||
import styled from 'styled-components' | ||
|
||
import { getComponent, removeComponent } from '@xrengine/engine/src/ecs/functions/ComponentFunctions' | ||
import { MaterialLibrary } from '@xrengine/engine/src/renderer/materials/MaterialLibrary' | ||
import { PatternTarget } from '@xrengine/engine/src/renderer/materials/MaterialParms' | ||
import { | ||
MaterialOverrideComponent, | ||
MaterialOverrideComponentType | ||
} from '@xrengine/engine/src/scene/components/MaterialOverrideComponent' | ||
import { refreshMaterials } from '@xrengine/engine/src/scene/functions/loaders/MaterialOverrideFunctions' | ||
|
||
import { Button } from './Button' | ||
import InputGroup, { InputGroupContent, InputGroupVerticalContainerWide, InputGroupVerticalContent } from './InputGroup' | ||
import SelectInput from './SelectInput' | ||
import StringInput, { ControlledStringInput } from './StringInput' | ||
|
||
const GroupContainer = (styled as any).label` | ||
background-color: $transparent; | ||
color: #9FA4B5; | ||
white-space: pre-wrap; | ||
padding: 0 8px 8px; | ||
` | ||
|
||
const ArrayInputGroupContent = (styled as any)(InputGroupContent)` | ||
margin: 4px 0px; | ||
display: -webkit-box; | ||
display: -webkit-flex; | ||
display: -ms-flexbox; | ||
display: flex; | ||
-webkit-flex-wrap: wrap; | ||
-ms-flex-wrap: wrap; | ||
flex-wrap: wrap; | ||
-webkit-flex-direction: row; | ||
-ms-flex-direction: row; | ||
flex-direction: row; | ||
}` | ||
/* | ||
& > label { | ||
max-width: 33.33333% !important; | ||
} | ||
& > input { | ||
max-width: 66.66666% !important; | ||
} | ||
& > div { | ||
max-width: 66.66666% !important; | ||
} | ||
`*/ | ||
|
||
export default function MaterialAssignment({ entity, node, modelComponent, values, onChange }) { | ||
let [count, setCount] = useState(values.length) | ||
|
||
let [materialIDs, setMaterialIDs] = useState<any[]>( | ||
Object.keys(MaterialLibrary).map((k) => { | ||
return { label: k, value: k } | ||
}) | ||
) | ||
const { t } = useTranslation() | ||
|
||
function onChangeSize(text, values, onChange) { | ||
const count = parseInt(text) | ||
let preCount = 0 | ||
if (!values) values = [] | ||
else preCount = values.length | ||
if (count == undefined || preCount == count) return | ||
if (preCount > count) values.splice(count) | ||
else | ||
for (let i = 0; i < count - preCount; i++) { | ||
values.push({ | ||
entity: -1, | ||
targetEntity: node.entity, | ||
materialID: '', | ||
patternTarget: PatternTarget.OBJ3D, | ||
pattern: '' | ||
}) | ||
} | ||
preCount = count | ||
onChange(values) | ||
} | ||
|
||
function onRemoveEntry(idx, values: any[], setCount, onChange) { | ||
return () => { | ||
const [removing] = values.splice(idx, 1) as MaterialOverrideComponentType[] | ||
removeComponent(removing.entity, MaterialOverrideComponent) | ||
setCount(values.length) | ||
onChange(values) | ||
} | ||
} | ||
|
||
function onAddEntry(values: any[], setCount, onChange) { | ||
return () => { | ||
setCount(values.length + 1) | ||
onChangeSize(`${values.length + 1}`, values, onChange) | ||
} | ||
} | ||
|
||
function onChangeAssignment(assignment, index, values, onChange) { | ||
values[index] = assignment | ||
onChange(values) | ||
} | ||
|
||
function onRefresh(onChange) { | ||
return async () => { | ||
await refreshMaterials(node.entity) | ||
onChange(modelComponent.materialOverrides) | ||
} | ||
} | ||
|
||
function MaterialAssignmentEntry(index) { | ||
const assignment = modelComponent.materialOverrides[index] | ||
function setAssignmentProperty(prop) { | ||
return (value) => { | ||
assignment[prop] = value | ||
onChangeAssignment(assignment, index, values, onChange) | ||
} | ||
} | ||
|
||
return ( | ||
<div> | ||
<span> | ||
<InputGroup name="Material ID" label={t('editor:properties.materialAssignment.lbl-materialID')}> | ||
<SelectInput | ||
key={`${entity}-${index}-materialID`} | ||
error={t('editor:properties.materialAssignment.error-materialID')} | ||
placeholder={t('editor:properties.materialAssignment.placeholder-materialID')} | ||
value={assignment.materialID} | ||
onChange={setAssignmentProperty('materialID')} | ||
options={materialIDs} | ||
/> | ||
</InputGroup> | ||
<InputGroup name="Pattern Target" label={t('editor:properties.materialAssignment.lbl-patternTarget')}> | ||
<SelectInput | ||
key={`${entity}-${index}-patternTarget`} | ||
value={assignment.patternTarget} | ||
onChange={setAssignmentProperty('patternTarget')} | ||
options={[ | ||
{ label: 'Object3D Name', value: PatternTarget.OBJ3D }, | ||
{ label: 'Mesh Name', value: PatternTarget.MESH }, | ||
{ label: 'Material Name', value: PatternTarget.MATERIAL } | ||
]} | ||
/> | ||
</InputGroup> | ||
<InputGroup name="Pattern" label={t('editor:properties.materialAssignment.lbl-pattern')}> | ||
<StringInput value={assignment.pattern} onChange={setAssignmentProperty('pattern')} /> | ||
</InputGroup> | ||
</span> | ||
<span> | ||
<Button onClick={onRemoveEntry(index, values, setCount, onChange)}>Delete</Button> | ||
</span> | ||
</div> | ||
) | ||
} | ||
|
||
return ( | ||
<GroupContainer> | ||
<InputGroupVerticalContainerWide> | ||
<InputGroupVerticalContent> | ||
<Button onClick={onRefresh(onChange)}> | ||
<p>Refresh</p> | ||
</Button> | ||
<ArrayInputGroupContent> | ||
<label> Count: </label> | ||
<ControlledStringInput value={count} onChange={(text) => onChangeSize(text, values, onChange)} /> | ||
<Button onClick={onAddEntry(values, setCount, onChange)}>+</Button> | ||
</ArrayInputGroupContent> | ||
{values && | ||
values.map((value, idx) => { | ||
return ( | ||
<ArrayInputGroupContent key={`${entity}-${idx}`} style={{ margin: '4px 2px' }}> | ||
<label>{idx + 1}: </label> | ||
{MaterialAssignmentEntry(idx)} | ||
</ArrayInputGroupContent> | ||
) | ||
})} | ||
</InputGroupVerticalContent> | ||
</InputGroupVerticalContainerWide> | ||
</GroupContainer> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import AliasVortex from './constants/AliasVortex.mat' | ||
import Caustics from './constants/Caustics.mat' | ||
import Circuits from './constants/Circuits.mat' | ||
import Cubes from './constants/Cubes.mat' | ||
import Fireball from './constants/Fireball.mat' | ||
import Galaxy from './constants/Galaxy.mat' | ||
import Generators from './constants/Generators.mat' | ||
import Noise_1 from './constants/Noise_1.mat' | ||
import ProteanClouds from './constants/ProteanClouds.mat' | ||
import VoronoiClouds from './constants/VoronoiClouds.mat' | ||
|
||
export const MaterialLibrary = { | ||
AliasVortex: AliasVortex, | ||
Caustics: Caustics, | ||
Circuits: Circuits, | ||
Cubes: Cubes, | ||
Fireball: Fireball, | ||
Galaxy: Galaxy, | ||
Generators: Generators, | ||
Noise_1: Noise_1, | ||
ProteanClouds: ProteanClouds, | ||
VoronoiClouds: VoronoiClouds | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
import { Material, Mesh, Object3D } from 'three' | ||
|
||
import { Entity } from '@xrengine/engine/src/ecs/classes/Entity' | ||
import { addComponent, getComponent, hasComponent } from '@xrengine/engine/src/ecs/functions/ComponentFunctions' | ||
import UpdateableObject3D from '@xrengine/engine/src/scene/classes/UpdateableObject3D' | ||
import { Object3DComponent } from '@xrengine/engine/src/scene/components/Object3DComponent' | ||
import { UpdatableComponent } from '@xrengine/engine/src/scene/components/UpdatableComponent' | ||
|
||
import { Engine } from '../../ecs/classes/Engine' | ||
import { MaterialOverrideComponentType } from '../../scene/components/MaterialOverrideComponent' | ||
import { MatRend } from '../../scene/systems/MaterialOverrideSystem' | ||
import { MaterialLibrary } from './MaterialLibrary' | ||
|
||
export type MaterialParms = { | ||
material: Material | ||
update: (delta: number) => void | ||
} | ||
|
||
export enum PatternTarget { | ||
OBJ3D, | ||
MESH, | ||
MATERIAL | ||
} | ||
|
||
function checkMatch(toCheck: string, assignment: MaterialOverrideComponentType): boolean { | ||
switch (typeof assignment.pattern) { | ||
case 'string': | ||
return toCheck.includes(assignment.pattern as string) | ||
case 'object': | ||
return (assignment.pattern as RegExp).test(toCheck) | ||
default: | ||
return false | ||
} | ||
} | ||
|
||
export async function assignMaterial(override: MaterialOverrideComponentType): Promise<[MatRend[], MaterialParms]> { | ||
const result: MatRend[] = [] | ||
//first retrieve material to build assignment | ||
const matParm: MaterialParms = await MaterialLibrary[override.materialID]() | ||
const target = getComponent(override.targetEntity, Object3DComponent)?.value | ||
if (!target) { | ||
console.error('Failed material override for override', override, ': target Object3D does not exist') | ||
} | ||
const root = getComponent(override.targetEntity, Object3DComponent).value as UpdateableObject3D | ||
root.traverse((obj3d) => { | ||
let isMatch = false | ||
switch (override.patternTarget) { | ||
case PatternTarget.OBJ3D: | ||
isMatch = checkMatch(obj3d.name, override) | ||
break | ||
case PatternTarget.MESH: | ||
if ((obj3d as Mesh)?.isMesh) { | ||
isMatch = checkMatch(obj3d.name, override) | ||
} | ||
break | ||
case PatternTarget.MATERIAL: | ||
let mesh = obj3d as Mesh | ||
if (mesh?.isMesh && mesh.material) { | ||
let mats = Array.isArray(mesh.material) ? mesh.material : [mesh.material] | ||
isMatch = mats.find((mat) => checkMatch(mat.name, override)) !== undefined | ||
} | ||
break | ||
} | ||
if (isMatch) { | ||
let mesh: Mesh | undefined | ||
switch (override.patternTarget) { | ||
case PatternTarget.OBJ3D: | ||
mesh = obj3d.children?.find((child: Mesh) => child.isMesh) as Mesh | undefined | ||
break | ||
case PatternTarget.MESH: | ||
mesh = obj3d as Mesh | ||
break | ||
case PatternTarget.MATERIAL: | ||
mesh = obj3d as Mesh | ||
break | ||
} | ||
if (!mesh) return | ||
result.push({ mesh: mesh, material: mesh.material }) | ||
mesh.material = matParm.material | ||
} | ||
}) | ||
return [result, matParm] | ||
} |
Oops, something went wrong.