import type { BaseStyleProps, DisplayObjectConfig, Group } from '@antv/g';
import type { ProceduralGeometry as GGeometry, Material as GMaterial } from '@antv/g-plugin-3d';
import { Mesh } from '@antv/g-plugin-3d';
import type { IMaterial, Plugin } from '@antv/g-plugin-device-renderer';
import type { BaseNodeStyleProps, Prefix } from '@antv/g6';
import { BaseNode, omitStyleProps, subStyleProps } from '@antv/g6';
import { deepMix } from '@antv/util';
import { Material } from '../types';
import { createMaterial } from '../utils/material';
/**
* 3D 节点样式
*
* 3D node style props
*/
export interface BaseNode3DStyleProps extends BaseNodeStyleProps, Prefix<'material', IMaterial> {
geometry?: GGeometry;
material?: GMaterial;
texture?: string | TexImageSource;
materialType?: Material['type'];
}
/**
* 3D 节点基类
*
* 3D node base class
*/
export abstract class BaseNode3D extends BaseNode {
static defaultStyleProps: Partial = {
materialType: 'basic',
};
public type = 'node-3d';
protected get plugin() {
const renderer = this.context.canvas.getRenderer('main');
const plugin = renderer.getPlugin('device-renderer');
return plugin as unknown as Plugin;
}
protected get device() {
return this.plugin.getDevice();
}
constructor(options: DisplayObjectConfig) {
super(deepMix({}, { style: BaseNode3D.defaultStyleProps }, options));
}
public render(attributes: Required, container: Group) {
super.render(attributes, container);
}
protected getKeyStyle(attributes: Required): MeshStyleProps {
const style = omitStyleProps(super.getKeyStyle(attributes), 'material');
const geometry = this.getGeometry(attributes);
const material = this.getMaterial(attributes);
return { x: 0, y: 0, z: 0, ...style, geometry, material };
}
protected drawKeyShape(attributes: Required, container: Group = this) {
return this.upsert('key', Mesh, this.getKeyStyle(attributes), container);
}
protected abstract getGeometry(attributes: Required): GGeometry;
protected getMaterial(attributes: Required): GMaterial {
const { texture } = attributes;
const materialStyle = subStyleProps(attributes, 'material');
return createMaterial(this.plugin, materialStyle, texture);
}
}
export interface MeshStyleProps extends BaseStyleProps {
x?: number | string;
y?: number | string;
z?: number | string;
geometry: GGeometry;
material: GMaterial;
}