import { Utils } from '../common/Utils';
/**
* @class StyleModifier
* The style modifier of object.
* @memberof THING
*/
class StyleModifier {
static dummyStyle;
/**
* The style modifier to clone or resume style when change its attributes.
*/
constructor(object) {
this._object = object;
this._resource = null;
this._needDisposeResource = false;
this._originalResource = null;
this._clippingPlanes = null;
StyleModifier.dummyStyle = StyleModifier.dummyStyle || Utils.createObject('Style');
}
// #region Private
_releaseStyle() {
if (!this._resource) {
return;
}
if (this._needDisposeResource) {
this._needDisposeResource = false;
let styleGroupPool = this._object.app.resourceManager.getStyleGroupPool();
styleGroupPool.releaseStyle(this._resource);
}
this._resource = null;
}
// #endregion
// #region Overrides
onBegin() {
let bodyNode = this._object.bodyNode;
let bodyResource = bodyNode.getStyle();
if (!this._resource) {
this._needDisposeResource = true;
this._resource = Utils.createObject('Style');
}
// Change to normal style without instanced drawing, due to any style attributes had changed
if (bodyResource != this._resource) {
this._originalResource = bodyResource;
this._resource.copy(bodyResource);
this._resource.enable('InstancedDrawing', false);
bodyNode.setStyle(this._resource);
}
}
onEnd() {
if (!this._originalResource) {
return;
}
let bodyNode = this._object.bodyNode;
bodyNode.setStyle(this._originalResource);
}
onChangeColor(key, value) {
let resource = this._resource;
switch (key) {
case 'outlineColor': resource.setOutlineColor(value); break;
default:
break;
}
}
onChangeValue(key, value) {
let resource = this._resource;
switch (key) {
case 'blendingType': resource.setBlendingType(value); break;
case 'sideType': resource.setSideType(value); break;
case 'transparent': resource.setTransparent(value); break;
// Boolean
case 'wireframe': resource.enable('Wireframe', value); break;
case 'depthTest': resource.enable('DepthTest', value); break;
case 'depthWrite': resource.enable('DepthWrite', value); break;
case 'envMapping': resource.enable('EnvMap', value); break;
// Object
case 'clippingPlanes':
if (value) {
this._clippingPlanes = value;
this._clippingPlanes.addStyleResource(resource);
}
else {
if (this._clippingPlanes) {
this._clippingPlanes.removeStyleResource(this._resource);
this._clippingPlanes = null;
}
}
break;
default:
break;
}
}
onChangeOpFunc(key, value) {
let resource = this._resource;
switch (key) {
case 'opacity': resource.setOpacityOp(value); break;
case 'color': resource.setColorOp(value); break;
case 'emissive': resource.setEmissiveOp(value); break;
case 'roughness': resource.setRoughnessOp(value); break;
case 'metalness': resource.setMetalnessOp(value); break;
default:
break;
}
}
onChangeImage(type, value) {
this._resource.setImage(type, value);
// Notify object image of style has changed
if (Utils.isFunction(this._object.onChangeImage)) {
this._object.onChangeImage();
}
}
onChangeUVMatrix(type, value) {
this._resource.setUVMatrix(type, value);
}
onChangeEdge(value) {
this._resource.setEdge(value);
}
onChangeEffect(value) {
let resource = this._resource;
resource.setEffect('glow', value.glow);
resource.setEffect('innerGlow', value.innerGlow);
resource.setEffect('lineBloom', value.lineBloom);
resource.setEffect('tailing', value.tailing);
resource.setEffect('radial', value.radial);
resource.setEffect('ghosting', value.ghosting);
}
onChangeAttribute(key, value) {
this._resource.setAttribute(key, value);
}
onChangeUniformValue(name, value) {
if (value && Utils.isFunction(value.toUniform)) {
// We must wait for the resource finish to loaded
if (Utils.isFunction(value.waitForComplete)) {
value.waitForComplete().then(() => {
// The style would be released after resource is ready
if (!this._resource) {
return;
}
let uniform = value.toUniform()['value'];
this._resource.setUniform(name, uniform);
});
}
else {
let uniform = value.toUniform()['value'];
this._resource.setUniform(name, uniform);
}
}
else {
this._resource.setUniform(name, value);
}
}
onChangeMacroValue(name, value) {
this._resource.defineMacro(name, value);
}
// #endregion
dispose() {
if (this._clippingPlanes) {
this._clippingPlanes.removeStyleResource(this._resource);
this._clippingPlanes = null;
}
if (this._originalResource) {
if (!this._originalResource.isDisposed()) {
let bodyNode = this._object.bodyNode;
let styleGroupPool = this._object.app.resourceManager.getStyleGroupPool();
// If we have this style in pool then let the pool to release it
if (styleGroupPool.hasStyle(this._originalResource)) {
// Because the original resource would be release later, so we set the dummy style to body node
bodyNode.setStyle(StyleModifier.dummyStyle);
styleGroupPool.releaseStyle(this._originalResource);
}
else {
bodyNode.setStyle(this._originalResource);
}
}
this._originalResource = null;
}
this._releaseStyle();
}
initResource(resource) {
this.dispose();
this._originalResource = resource;
let bodyNode = this._object.bodyNode;
bodyNode.setStyle(resource);
}
updateResource(resource) {
if (this._resource != resource) {
this._releaseStyle();
this._resource = resource;
}
let bodyNode = this._object.bodyNode;
bodyNode.setStyle(resource);
}
get object() {
return this._object;
}
get originalResource() {
return this._originalResource;
}
get resource() {
return this._resource;
}
/**
* Check class type.
* @type {Boolean}
* @private
*/
get isStyleModifier() {
return true;
}
}
export { StyleModifier }