@itwin/core-backend
Version:
iTwin.js backend components
264 lines • 13 kB
JavaScript
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
* @module Elements
*/
import { Id64, JsonUtils } from "@itwin/core-bentley";
import { BisCodeSpec, Code, } from "@itwin/core-common";
import { DefinitionElement } from "./Element";
/* eslint-disable @typescript-eslint/naming-convention */
/** A PhysicalMaterial defines the matter that makes up physical elements.
* @note See [[RenderMaterialElement]] for the DefinitionElement used to define rendering characteristics.
* @public
*/
export class PhysicalMaterial extends DefinitionElement {
static get className() { return "PhysicalMaterial"; }
/** Create a Code for a PhysicalMaterial given a name that is meant to be unique within the scope of the specified DefinitionModel.
* @param iModel The IModelDb
* @param definitionModelId The Id of the DefinitionModel that will contain the PhysicalMaterial and provide the scope for its name.
* @param name The name (codeValue) of the PhysicalMaterial
*/
static createCode(iModel, definitionModelId, name) {
const codeSpec = iModel.codeSpecs.getByName(BisCodeSpec.physicalMaterial);
return new Code({ spec: codeSpec.id, scope: definitionModelId, value: name });
}
/** Create a PhysicalMaterial
* @param iModelDb The IModelDb
* @param definitionModelId The Id of the DefinitionModel that will contain the PhysicalMaterial and provide the scope for its name.
* @param name The name (codeValue) of the PhysicalMaterial
* @returns The newly constructed PhysicalMaterial
* @throws [[IModelError]] if there is a problem creating the PhysicalMaterial
*/
static create(iModelDb, definitionModelId, name) {
const elementProps = {
classFullName: this.classFullName,
model: definitionModelId,
code: this.createCode(iModelDb, definitionModelId, name),
};
return iModelDb.elements.createElement(elementProps);
}
}
/** Defines a rendering material.
* @note See [[PhysicalMaterial]] for the DefinitionElement used to define the matter that makes up physical elements.
* @public
*/
export class RenderMaterialElement extends DefinitionElement {
static get className() { return "RenderMaterial"; }
/** The name of a palette that can be used to categorize multiple materials. */
paletteName;
/** An optional description of the material. */
description;
constructor(props, iModel) {
super(props, iModel);
this.paletteName = props.paletteName;
this.description = props.description;
}
toJSON() {
const val = super.toJSON();
val.paletteName = this.paletteName;
val.description = this.description;
return val;
}
/**
* RenderMaterialElement custom HandledProps includes 'paletteName'.
* @inheritdoc
* @beta
*/
static _customHandledProps = [
{ propertyName: "paletteName", source: "Class" },
];
/**
* RenderMaterialElement deserializes 'paletteName'.
* @inheritdoc
* @beta
*/
static deserialize(props) {
const elProps = super.deserialize(props);
const instance = props.row;
elProps.paletteName = JsonUtils.asString(instance.paletteName);
return elProps;
}
/**
* RenderMaterialElement serializes 'paletteName'.
* @inheritdoc
* @beta
*/
static serialize(props, iModel) {
const inst = super.serialize(props, iModel);
inst.paletteName = props.paletteName;
return inst;
}
/** Create a Code for a RenderMaterial given a name that is meant to be unique within the scope of the specified DefinitionModel.
* @param iModel The IModelDb
* @param scopeModelId The Id of the DefinitionModel that contains the RenderMaterial and provides the scope for its name.
* @param name The RenderMaterial name
*/
static createCode(iModel, scopeModelId, name) {
const codeSpec = iModel.codeSpecs.getByName(BisCodeSpec.renderMaterial);
return 0 === name.length ? Code.createEmpty() : new Code({ spec: codeSpec.id, scope: scopeModelId, value: name });
}
/**
* Create a RenderMaterial with given parameters.
* @param iModelDb The iModel
* @param definitionModelId The [[DefinitionModel]]
* @param materialName The name/CodeValue of the RenderMaterial
* @param params Parameters object which describes how to construct the RenderMaterial
* @returns The newly constructed RenderMaterial element.
* @throws [[IModelError]] if unable to create the element.
*/
static create(iModelDb, definitionModelId, materialName, params) {
let maps;
const pbr_normal = params.normalMap?.scale;
if (params.patternMap || params.normalMap) {
function choose(obj, key) {
const pat = params.patternMap;
if (pat && undefined !== pat[key])
obj[key] = pat[key];
else if (params.normalMap && undefined !== params.normalMap[key])
obj[key] = params.normalMap[key];
}
const baseProps = {};
choose(baseProps, "pattern_angle");
choose(baseProps, "pattern_u_flip");
choose(baseProps, "pattern_flip");
choose(baseProps, "pattern_scale");
choose(baseProps, "pattern_offset");
choose(baseProps, "pattern_scalemode");
choose(baseProps, "pattern_mapping");
choose(baseProps, "pattern_weight");
choose(baseProps, "pattern_useconstantlod");
choose(baseProps, "pattern_constantlod_repetitions");
choose(baseProps, "pattern_constantlod_offset");
choose(baseProps, "pattern_constantlod_mindistanceclamp");
choose(baseProps, "pattern_constantlod_maxdistanceclamp");
maps = {};
if (params.patternMap)
maps.Pattern = { ...params.patternMap, ...baseProps };
if (params.normalMap) {
maps.Normal = {
...params.normalMap,
...baseProps,
};
delete maps.Normal.scale;
}
}
const renderMaterialProps = {
classFullName: this.classFullName,
code: this.createCode(iModelDb, definitionModelId, materialName),
paletteName: params.paletteName,
description: params.description,
jsonProperties: {
materialAssets: {
renderMaterial: {
HasBaseColor: params.color !== undefined,
color: params.color,
HasSpecularColor: params.specularColor !== undefined,
specular_color: params.specularColor,
HasFinish: params.finish !== undefined,
finish: params.finish,
HasTransmit: params.transmit !== undefined ? true : undefined,
transmit: params.transmit,
HasDiffuse: params.diffuse !== undefined,
diffuse: params.diffuse,
HasSpecular: params.specular !== undefined,
specular: params.specular,
HasReflect: params.reflect !== undefined,
reflect: params.reflect,
HasReflectColor: params.reflectColor !== undefined,
reflect_color: params.reflectColor,
Map: maps,
pbr_normal,
},
},
},
model: definitionModelId,
isPrivate: false,
};
return new RenderMaterialElement(renderMaterialProps, iModelDb);
}
/**
* Insert a new RenderMaterial into a model.
* @param iModelDb Insert into this iModel
* @param definitionModelId Insert the new Texture into this DefinitionModel
* @param materialName The name/CodeValue of the RenderMaterial
* @param params Parameters object which describes how to construct the RenderMaterial
* @returns The Id of the newly inserted RenderMaterial element.
* @throws [[IModelError]] if unable to insert the element.
*/
static insert(iModelDb, definitionModelId, materialName, params) {
const renderMaterial = this.create(iModelDb, definitionModelId, materialName, params);
return iModelDb.elements.insertElement(renderMaterial.toJSON());
}
/** @beta */
static onCloned(context, sourceProps, targetProps) {
super.onCloned(context, sourceProps, targetProps);
for (const mapName in sourceProps.jsonProperties?.materialAssets?.renderMaterial?.Map ?? {}) {
if (typeof mapName !== "string")
continue;
const sourceMap = sourceProps.jsonProperties.materialAssets.renderMaterial.Map[mapName];
// sourceMap could be null/undefined, keep it the same in targetProps
if (!sourceMap) {
targetProps.jsonProperties.materialAssets.renderMaterial.Map[mapName] = sourceMap;
continue;
}
if (!Id64.isValid(sourceMap.TextureId) || sourceMap.TextureId === undefined)
continue;
targetProps.jsonProperties.materialAssets.renderMaterial.Map[mapName].TextureId = context.findTargetElementId(sourceMap.TextureId ?? Id64.invalid);
}
}
}
/** @public */
(function (RenderMaterialElement) {
/** Parameters used to construct a [[RenderMaterial]].
* The persistent JSON representation - [RenderMaterialAssetProps]($common) - is quite verbose and unwieldy. This representation simplifies it somewhat.
* @see [[RenderMaterialElement.create]] and [[RenderMaterialElement.insert]] to create a [[RenderMaterial]] from parameters of this type.
* @deprecated in 3.6 - might be removed in next major version. Because it is not useful to use a `class` - just use [[RenderMaterialElementParams]] directly instead.
*/
class Params {
/** A required palette name that categorizes this RenderMaterial */
paletteName;
/** An optional description of this RenderMaterial */
description;
/** If defined, the color to use for surface fill or diffuse illumination, overriding the surface's own color. */
color;
/** The color to use for specular illumination. Default: black. */
specularColor;
/** The specular exponent describing the surface's shininess, in the range 0 through 128.
* Default: 0.
*/
finish;
/** A transparency to be applied to the surface, ranging from 0 (fully opaque) to 1 (fully transparent).
* If defined, then the material transparency overrides the transparency of whatever surface the material is applied to.
* If undefined, the material has no effect on surface transparency.
* Default: undefined.
*/
transmit;
/** The surface's diffuse reflectivity from 0.0 to 1.0. Default: 0.6. */
diffuse;
/** The surface's specular reflectivity from 0.0 to 1.0. Default: 0.0. */
specular;
/** Currently unused. */
reflect;
/** Currently unused. */
reflectColor;
/** Specifies a texture image to map onto the surface, replacing or mixing with the surface's own color and transparency.
* @note With the exception of `TextureId`, the [TextureMapProps]($common) of [[patternMap]] and [[normalMap]] are expected to be identical. If a property is defined in both
* [[patternMap]]] and [[normalMap]], the value in [[patternMap]] takes precedence.
*/
patternMap;
/** Specifies a [normal map](https://en.wikipedia.org/wiki/Normal_mapping) to apply to the surface to simulate more surface detail than is present in the
* surface's geometry.
* @note With the exception of `TextureId`, the [TextureMapProps]($common) of [[patternMap]] and [[normalMap]] are expected to be identical. If a property is defined in both
* [[patternMap]]] and [[normalMap]], the value in [[patternMap]] takes precedence.
*/
normalMap;
/** Construct a new RenderMaterial.Params object with the specified paletteName. Alter the public members on that object to specify settings. */
constructor(paletteName) {
this.paletteName = paletteName;
}
}
RenderMaterialElement.Params = Params;
})(RenderMaterialElement || (RenderMaterialElement = {}));
//# sourceMappingURL=Material.js.map