Merge pull request 'Optmi renderer model & renderer shape parameter' (#38) from dev-mrkbear into master
Reviewed-on: http://git.mrkbear.com/MrKBear/living-together/pulls/38
This commit is contained in:
commit
27d4b07b41
@ -1,7 +1,7 @@
|
|||||||
import { ReactNode, createElement } from "react";
|
import { ReactNode, createElement } from "react";
|
||||||
import { Emitter } from "@Model/Emitter";
|
import { Emitter } from "@Model/Emitter";
|
||||||
import { Localization } from "@Component/Localization/Localization";
|
import { Localization } from "@Component/Localization/Localization";
|
||||||
import { IAnyObject } from "@Model/Renderer";
|
import { IAnyObject } from "@Model/Model";
|
||||||
|
|
||||||
enum ResizeDragDirection {
|
enum ResizeDragDirection {
|
||||||
top = 1,
|
top = 1,
|
||||||
|
@ -44,6 +44,11 @@ class BasicGroup extends DisplayObject<GroupShader> {
|
|||||||
*/
|
*/
|
||||||
public color = [1, 1, 1];
|
public color = [1, 1, 1];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 形状
|
||||||
|
*/
|
||||||
|
public shape: number = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 绘制立方体
|
* 绘制立方体
|
||||||
*/
|
*/
|
||||||
@ -66,6 +71,9 @@ class BasicGroup extends DisplayObject<GroupShader> {
|
|||||||
// 半径传递
|
// 半径传递
|
||||||
this.shader.radius(this.size);
|
this.shader.radius(this.size);
|
||||||
|
|
||||||
|
// 形状传递
|
||||||
|
this.shader.shape(this.shape);
|
||||||
|
|
||||||
// 指定颜色
|
// 指定颜色
|
||||||
this.shader.color(this.color);
|
this.shader.color(this.color);
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { AbstractRenderer, IRendererParam, IAnyObject } from "@Model/Renderer";
|
import { AbstractRenderer, IRendererParam } from "@Model/Renderer";
|
||||||
import { EventType } from "@Model/Emitter";
|
import { EventType } from "@Model/Emitter";
|
||||||
import { GLCanvas, GLCanvasOption } from "./GLCanvas";
|
import { GLCanvas, GLCanvasOption } from "./GLCanvas";
|
||||||
import { GLContext } from "./GLContext";
|
import { GLContext } from "./GLContext";
|
||||||
@ -16,19 +16,13 @@ type IRendererParams = IRendererOwnParams & GLCanvasOption;
|
|||||||
|
|
||||||
abstract class BasicRenderer<
|
abstract class BasicRenderer<
|
||||||
P extends IRendererParam = {},
|
P extends IRendererParam = {},
|
||||||
M extends IAnyObject = {},
|
|
||||||
E extends Record<EventType, any> = {}
|
E extends Record<EventType, any> = {}
|
||||||
> extends AbstractRenderer<P, M & IRendererParams, E & {loop: number}> {
|
> extends AbstractRenderer<P, E & {loop: number}> {
|
||||||
|
|
||||||
public get dom() {
|
public get dom() {
|
||||||
return this.canvas.dom
|
return this.canvas.dom
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 渲染器参数
|
|
||||||
*/
|
|
||||||
public param: Partial<M & IRendererParams> = {};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 使用的画布
|
* 使用的画布
|
||||||
*/
|
*/
|
||||||
@ -44,19 +38,16 @@ abstract class BasicRenderer<
|
|||||||
*/
|
*/
|
||||||
protected clock: Clock;
|
protected clock: Clock;
|
||||||
|
|
||||||
public constructor(param: Partial<M & IRendererParams> = {}) {
|
public constructor() {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
// 初始化参数
|
|
||||||
this.param = {
|
|
||||||
autoResize: param.autoResize ?? true,
|
|
||||||
mouseEvent: param.autoResize ?? true,
|
|
||||||
eventLog: param.eventLog ?? false,
|
|
||||||
className: param.className ?? ""
|
|
||||||
} as M & IRendererParams;
|
|
||||||
|
|
||||||
// 实例化画布对象
|
// 实例化画布对象
|
||||||
this.canvas = new GLCanvas(param.canvas, this.param);
|
this.canvas = new GLCanvas(undefined, {
|
||||||
|
autoResize: true,
|
||||||
|
mouseEvent: true,
|
||||||
|
eventLog: false,
|
||||||
|
className: "canvas"
|
||||||
|
});
|
||||||
|
|
||||||
// 实例化摄像机
|
// 实例化摄像机
|
||||||
this.camera = new Camera(this.canvas);
|
this.camera = new Camera(this.canvas);
|
||||||
|
@ -1,27 +1,49 @@
|
|||||||
import { ObjectID, ObjectData, ICommonParam } from "@Model/Renderer";
|
import { ObjectData } from "@Model/Renderer";
|
||||||
|
import { ObjectID } from "@Model/Model";
|
||||||
|
import { IParameterValue, getDefaultValue } from "@Model/Parameter";
|
||||||
import { BasicRenderer } from "./BasicRenderer";
|
import { BasicRenderer } from "./BasicRenderer";
|
||||||
import { BasicsShader } from "./BasicShader";
|
import { BasicsShader } from "./BasicShader";
|
||||||
import { Axis } from "./Axis";
|
import { Axis } from "./Axis";
|
||||||
import { BasicCube } from "./BasicCube";
|
import { BasicCube } from "./BasicCube";
|
||||||
import { GroupShader } from "./GroupShader";
|
import { GroupShader } from "./GroupShader";
|
||||||
import { BasicGroup } from "./BasicGroup";
|
import { BasicGroup } from "./BasicGroup";
|
||||||
import DisplayObject from "./DisplayObject";
|
import { DisplayObject } from "./DisplayObject";
|
||||||
|
|
||||||
interface IClassicRendererParams {
|
|
||||||
point: {
|
|
||||||
size: number;
|
|
||||||
}
|
|
||||||
cube: {
|
|
||||||
radius: number[];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum MouseMod {
|
enum MouseMod {
|
||||||
Drag = 1,
|
Drag = 1,
|
||||||
click = 2
|
click = 2
|
||||||
}
|
}
|
||||||
|
|
||||||
class ClassicRenderer extends BasicRenderer<{}, IClassicRendererParams> {
|
type IClassicRendererParameter = {
|
||||||
|
renderer: {};
|
||||||
|
points: {
|
||||||
|
color: "color",
|
||||||
|
size: "number",
|
||||||
|
shape: "option"
|
||||||
|
};
|
||||||
|
cube: {
|
||||||
|
color: "color"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
class ClassicRenderer extends BasicRenderer<IClassicRendererParameter> {
|
||||||
|
|
||||||
|
public override rendererParameterOption = {};
|
||||||
|
public override pointsParameterOption = {
|
||||||
|
color: { type: "color", name: "", defaultValue: [0, 0, 0] },
|
||||||
|
size: { type: "number", name: "Common.Attr.Key.Size", defaultValue: 60, numberStep: 10, numberMin: 0 },
|
||||||
|
shape: { type: "option", name: "Common.Render.Attr.Key.Display.Shape", defaultValue: "0", allOption: [
|
||||||
|
{ key: "0", name: "Common.Render.Attr.Key.Display.Shape.Square" },
|
||||||
|
{ key: "1", name: "Common.Render.Attr.Key.Display.Shape.Hollow.Square" },
|
||||||
|
{ key: "2", name: "Common.Render.Attr.Key.Display.Shape.Hollow.Plus" },
|
||||||
|
{ key: "3", name: "Common.Render.Attr.Key.Display.Shape.Hollow.Reduce" },
|
||||||
|
{ key: "4", name: "Common.Render.Attr.Key.Display.Shape.Hollow.Cross" },
|
||||||
|
{ key: "5", name: "Common.Render.Attr.Key.Display.Shape.Hollow.Checkerboard" }
|
||||||
|
]}
|
||||||
|
};
|
||||||
|
public override cubeParameterOption = {
|
||||||
|
color: { type: "color", name: "", defaultValue: [0, 0, 0] },
|
||||||
|
};
|
||||||
|
|
||||||
private basicShader: BasicsShader = undefined as any;
|
private basicShader: BasicsShader = undefined as any;
|
||||||
private axisObject: Axis = undefined as any;
|
private axisObject: Axis = undefined as any;
|
||||||
@ -52,6 +74,8 @@ class ClassicRenderer extends BasicRenderer<{}, IClassicRendererParams> {
|
|||||||
|
|
||||||
public onLoad(): this {
|
public onLoad(): this {
|
||||||
|
|
||||||
|
this.rendererParameter = getDefaultValue(this.rendererParameterOption);
|
||||||
|
|
||||||
// 自动调节分辨率
|
// 自动调节分辨率
|
||||||
this.autoResize();
|
this.autoResize();
|
||||||
|
|
||||||
@ -187,7 +211,7 @@ class ClassicRenderer extends BasicRenderer<{}, IClassicRendererParams> {
|
|||||||
|
|
||||||
points(
|
points(
|
||||||
id: ObjectID, position?: ObjectData,
|
id: ObjectID, position?: ObjectData,
|
||||||
param?: Readonly<Partial<ICommonParam & IClassicRendererParams["point"]>>
|
param?: Readonly<IParameterValue<IClassicRendererParameter["points"]>>
|
||||||
): this {
|
): this {
|
||||||
let object = this.objectPool.get(id);
|
let object = this.objectPool.get(id);
|
||||||
let group: BasicGroup;
|
let group: BasicGroup;
|
||||||
@ -229,14 +253,19 @@ class ClassicRenderer extends BasicRenderer<{}, IClassicRendererParams> {
|
|||||||
if (param.size) {
|
if (param.size) {
|
||||||
group.size = param.size;
|
group.size = param.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 半径数据
|
||||||
|
if (param.shape) {
|
||||||
|
group.shape = parseInt(param.shape);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
cube(
|
cube(
|
||||||
id: ObjectID, position?: ObjectData,
|
id: ObjectID, position?: ObjectData, radius?: ObjectData,
|
||||||
param?: Readonly<Partial<ICommonParam & IClassicRendererParams["cube"]>>
|
param?: Readonly<IParameterValue<IClassicRendererParameter["cube"]>>
|
||||||
): this {
|
): this {
|
||||||
let object = this.objectPool.get(id);
|
let object = this.objectPool.get(id);
|
||||||
let cube: BasicCube;
|
let cube: BasicCube;
|
||||||
@ -250,6 +279,13 @@ class ClassicRenderer extends BasicRenderer<{}, IClassicRendererParams> {
|
|||||||
cube.position[1] = position[1] ?? cube.position[1];
|
cube.position[1] = position[1] ?? cube.position[1];
|
||||||
cube.position[2] = position[2] ?? cube.position[2];
|
cube.position[2] = position[2] ?? cube.position[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (radius) {
|
||||||
|
cube.r[0] = radius[0] ?? cube.r[0];
|
||||||
|
cube.r[1] = radius[1] ?? cube.r[1];
|
||||||
|
cube.r[2] = radius[2] ?? cube.r[2];
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
throw new Error("Renderer: Use duplicate ObjectID when drawing different types of objects");
|
throw new Error("Renderer: Use duplicate ObjectID when drawing different types of objects");
|
||||||
}
|
}
|
||||||
@ -263,6 +299,12 @@ class ClassicRenderer extends BasicRenderer<{}, IClassicRendererParams> {
|
|||||||
cube.position[2] = position[2] ?? cube.position[2];
|
cube.position[2] = position[2] ?? cube.position[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (radius) {
|
||||||
|
cube.r[0] = radius[0] ?? cube.r[0];
|
||||||
|
cube.r[1] = radius[1] ?? cube.r[1];
|
||||||
|
cube.r[2] = radius[2] ?? cube.r[2];
|
||||||
|
}
|
||||||
|
|
||||||
this.objectPool.set(id, cube);
|
this.objectPool.set(id, cube);
|
||||||
console.log(`Renderer: Create new cube object with id ${id}`);
|
console.log(`Renderer: Create new cube object with id ${id}`);
|
||||||
}
|
}
|
||||||
@ -271,21 +313,11 @@ class ClassicRenderer extends BasicRenderer<{}, IClassicRendererParams> {
|
|||||||
cube.isDraw = true;
|
cube.isDraw = true;
|
||||||
|
|
||||||
// 参数传递
|
// 参数传递
|
||||||
if (param) {
|
if (param && param.color) {
|
||||||
|
|
||||||
// 颜色数据
|
cube.color[0] = param.color[0] ?? cube.color[0];
|
||||||
if (param.color) {
|
cube.color[1] = param.color[1] ?? cube.color[1];
|
||||||
cube.color[0] = param.color[0] ?? cube.color[0]
|
cube.color[2] = param.color[2] ?? cube.color[2];
|
||||||
cube.color[1] = param.color[1] ?? cube.color[1]
|
|
||||||
cube.color[2] = param.color[2] ?? cube.color[2]
|
|
||||||
}
|
|
||||||
|
|
||||||
// 半径数据
|
|
||||||
if (param.radius) {
|
|
||||||
cube.r[0] = param.radius[0] ?? cube.r[0];
|
|
||||||
cube.r[1] = param.radius[1] ?? cube.r[1];
|
|
||||||
cube.r[2] = param.radius[2] ?? cube.r[2];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
|
@ -10,6 +10,7 @@ interface IGroupShaderAttribute {
|
|||||||
|
|
||||||
interface IGroupShaderUniform {
|
interface IGroupShaderUniform {
|
||||||
uRadius: number,
|
uRadius: number,
|
||||||
|
uShape: number,
|
||||||
uMvp: ObjectData,
|
uMvp: ObjectData,
|
||||||
uColor: ObjectData,
|
uColor: ObjectData,
|
||||||
uFogColor: ObjectData,
|
uFogColor: ObjectData,
|
||||||
@ -50,10 +51,42 @@ class GroupShader extends GLShader<IGroupShaderAttribute, IGroupShaderUniform>{
|
|||||||
|
|
||||||
uniform vec3 uColor;
|
uniform vec3 uColor;
|
||||||
uniform vec3 uFogColor;
|
uniform vec3 uFogColor;
|
||||||
|
uniform int uShape;
|
||||||
|
|
||||||
varying float vFogPower;
|
varying float vFogPower;
|
||||||
|
|
||||||
void main(){
|
void main(){
|
||||||
|
|
||||||
|
float dist = distance(gl_PointCoord, vec2(0.5, 0.5));
|
||||||
|
vec2 normalPos = (gl_PointCoord - vec2(0.5, 0.5)) * 2.;
|
||||||
|
|
||||||
|
if ( uShape == 1 && abs(normalPos.x) < .6 && abs(normalPos.y) < .6) {
|
||||||
|
discard;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( uShape == 2 && abs(normalPos.x) > .3 && abs(normalPos.y) > .3) {
|
||||||
|
discard;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( uShape == 3 && abs(normalPos.y) > .3) {
|
||||||
|
discard;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( uShape == 4 &&
|
||||||
|
(abs(normalPos.x) < .4 || abs(normalPos.y) < .4) &&
|
||||||
|
(abs(normalPos.x) > .4 || abs(normalPos.y) > .4)
|
||||||
|
) {
|
||||||
|
discard;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( uShape == 5 &&
|
||||||
|
(abs(normalPos.x) < .75 && abs(normalPos.y) < .75) &&
|
||||||
|
(abs(normalPos.x) < .28 || abs(normalPos.y) < .28) &&
|
||||||
|
(abs(normalPos.x) > .28 || abs(normalPos.y) > .28)
|
||||||
|
) {
|
||||||
|
discard;
|
||||||
|
}
|
||||||
|
|
||||||
gl_FragColor = vec4(mix(uColor, uFogColor, vFogPower), 1.);
|
gl_FragColor = vec4(mix(uColor, uFogColor, vFogPower), 1.);
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@ -111,4 +144,13 @@ class GroupShader extends GLShader<IGroupShaderAttribute, IGroupShaderUniform>{
|
|||||||
this.uniformLocate("uFogDensity"), rgb
|
this.uniformLocate("uFogDensity"), rgb
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 形状
|
||||||
|
*/
|
||||||
|
public shape(shape: number) {
|
||||||
|
this.gl.uniform1i(
|
||||||
|
this.uniformLocate("uShape"), shape
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,7 +1,7 @@
|
|||||||
import { Component, ReactNode } from "react";
|
import { Component, ReactNode } from "react";
|
||||||
import { Icon } from "@fluentui/react";
|
import { Icon } from "@fluentui/react";
|
||||||
import { AllI18nKeys } from "@Component/Localization/Localization";
|
import { AllI18nKeys } from "@Component/Localization/Localization";
|
||||||
import { ObjectID } from "@Model/Renderer";
|
import { ObjectID } from "@Model/Model";
|
||||||
import { TextField, ITextFieldProps } from "@Input/TextField/TextField";
|
import { TextField, ITextFieldProps } from "@Input/TextField/TextField";
|
||||||
import "./AttrInput.scss";
|
import "./AttrInput.scss";
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { Component, Fragment, ReactNode } from "react";
|
import { Component, Fragment, ReactNode } from "react";
|
||||||
import { useSettingWithEvent, IMixinSettingProps, Language } from "@Context/Setting";
|
import { useSettingWithEvent, IMixinSettingProps, Language } from "@Context/Setting";
|
||||||
import { AttrInput } from "@Input/AttrInput/AttrInput";
|
import { AttrInput } from "@Input/AttrInput/AttrInput";
|
||||||
import { ObjectID } from "@Model/Renderer";
|
import { ObjectID } from "@Model/Model";
|
||||||
import { TogglesInput } from "@Input/TogglesInput/TogglesInput";
|
import { TogglesInput } from "@Input/TogglesInput/TogglesInput";
|
||||||
import { ObjectPicker } from "@Input/ObjectPicker/ObjectPicker";
|
import { ObjectPicker } from "@Input/ObjectPicker/ObjectPicker";
|
||||||
import { AllI18nKeys, I18N } from "@Component/Localization/Localization";
|
import { AllI18nKeys, I18N } from "@Component/Localization/Localization";
|
||||||
@ -10,7 +10,7 @@ import { ColorInput } from "@Input/ColorInput/ColorInput";
|
|||||||
import { ComboInput, IDisplayItem } from "@Input/ComboInput/ComboInput";
|
import { ComboInput, IDisplayItem } from "@Input/ComboInput/ComboInput";
|
||||||
import {
|
import {
|
||||||
IParameter, IParameterOption, IParameterOptionItem,
|
IParameter, IParameterOption, IParameterOptionItem,
|
||||||
IParameterValue, IParamValue, isObjectType, isVectorType
|
IParameterValue, IParamValue, isObjectType
|
||||||
} from "@Model/Parameter";
|
} from "@Model/Parameter";
|
||||||
import "./Parameter.scss";
|
import "./Parameter.scss";
|
||||||
|
|
||||||
@ -20,6 +20,7 @@ interface IParameterProps<P extends IParameter = {}> {
|
|||||||
key: ObjectID;
|
key: ObjectID;
|
||||||
change: <K extends keyof P>(key: K, val: IParamValue<P[K]>) => any;
|
change: <K extends keyof P>(key: K, val: IParamValue<P[K]>) => any;
|
||||||
i18n?: (key: string, language: Language) => string;
|
i18n?: (key: string, language: Language) => string;
|
||||||
|
renderKey?: Array<keyof P>;
|
||||||
title?: AllI18nKeys;
|
title?: AllI18nKeys;
|
||||||
titleOption?: Record<string, string>;
|
titleOption?: Record<string, string>;
|
||||||
isFirst?: boolean;
|
isFirst?: boolean;
|
||||||
@ -249,12 +250,18 @@ class Parameter<P extends IParameter> extends Component<IParameterProps<P> & IMi
|
|||||||
}
|
}
|
||||||
|
|
||||||
public render(): ReactNode {
|
public render(): ReactNode {
|
||||||
const allOptionKeys: Array<keyof P> = Object.getOwnPropertyNames(this.props.option);
|
|
||||||
|
let allOptionKeys: Array<keyof P>;
|
||||||
|
if (this.props.renderKey) {
|
||||||
|
allOptionKeys = this.props.renderKey;
|
||||||
|
} else {
|
||||||
|
allOptionKeys = Object.getOwnPropertyNames(this.props.option);
|
||||||
|
}
|
||||||
|
|
||||||
return <>
|
return <>
|
||||||
|
|
||||||
{
|
{
|
||||||
allOptionKeys.length <= 0 && this.props.title ?
|
allOptionKeys.length > 0 && this.props.title ?
|
||||||
<Message
|
<Message
|
||||||
isTitle
|
isTitle
|
||||||
first={this.props.isFirst}
|
first={this.props.isFirst}
|
||||||
|
@ -76,6 +76,7 @@ const EN_US = {
|
|||||||
"Common.Attr.Title.Individual.Generation": "Individual generation",
|
"Common.Attr.Title.Individual.Generation": "Individual generation",
|
||||||
"Common.Attr.Title.Behaviors": "Behaviors list",
|
"Common.Attr.Title.Behaviors": "Behaviors list",
|
||||||
"Common.Attr.Title.Individual.kill": "Individual kill",
|
"Common.Attr.Title.Individual.kill": "Individual kill",
|
||||||
|
"Common.Attr.Title.Render.Parameter": "Render parameters",
|
||||||
"Common.Attr.Key.Display.Name": "Display name",
|
"Common.Attr.Key.Display.Name": "Display name",
|
||||||
"Common.Attr.Key.Position.X": "Position X",
|
"Common.Attr.Key.Position.X": "Position X",
|
||||||
"Common.Attr.Key.Position.Y": "Position Y",
|
"Common.Attr.Key.Position.Y": "Position Y",
|
||||||
@ -106,6 +107,13 @@ const EN_US = {
|
|||||||
"Common.Attr.Key.Generation.Error.Invalid.Label": "The specified label has expired",
|
"Common.Attr.Key.Generation.Error.Invalid.Label": "The specified label has expired",
|
||||||
"Common.Attr.Key.Kill.Random": "Random kill",
|
"Common.Attr.Key.Kill.Random": "Random kill",
|
||||||
"Common.Attr.Key.Kill.Count": "Kill count",
|
"Common.Attr.Key.Kill.Count": "Kill count",
|
||||||
|
"Common.Render.Attr.Key.Display.Shape": "Display Shape",
|
||||||
|
"Common.Render.Attr.Key.Display.Shape.Square": "Square",
|
||||||
|
"Common.Render.Attr.Key.Display.Shape.Hollow.Square": "Hollow square",
|
||||||
|
"Common.Render.Attr.Key.Display.Shape.Hollow.Plus": "Plus",
|
||||||
|
"Common.Render.Attr.Key.Display.Shape.Hollow.Reduce": "Reduce",
|
||||||
|
"Common.Render.Attr.Key.Display.Shape.Hollow.Cross": "Cross",
|
||||||
|
"Common.Render.Attr.Key.Display.Shape.Hollow.Checkerboard": "Checkerboard",
|
||||||
"Panel.Info.Range.Details.Attr.Error.Not.Range": "Object is not a Range",
|
"Panel.Info.Range.Details.Attr.Error.Not.Range": "Object is not a Range",
|
||||||
"Panel.Info.Range.Details.Attr.Error.Unspecified": "Unspecified range object",
|
"Panel.Info.Range.Details.Attr.Error.Unspecified": "Unspecified range object",
|
||||||
"Panel.Info.Group.Details.Attr.Error.Not.Group": "Object is not a Group",
|
"Panel.Info.Group.Details.Attr.Error.Not.Group": "Object is not a Group",
|
||||||
|
@ -76,6 +76,7 @@ const ZH_CN = {
|
|||||||
"Common.Attr.Title.Individual.Generation": "生成个体",
|
"Common.Attr.Title.Individual.Generation": "生成个体",
|
||||||
"Common.Attr.Title.Behaviors": "行为列表",
|
"Common.Attr.Title.Behaviors": "行为列表",
|
||||||
"Common.Attr.Title.Individual.kill": "消除个体",
|
"Common.Attr.Title.Individual.kill": "消除个体",
|
||||||
|
"Common.Attr.Title.Render.Parameter": "渲染参数",
|
||||||
"Common.Attr.Key.Display.Name": "显示名称",
|
"Common.Attr.Key.Display.Name": "显示名称",
|
||||||
"Common.Attr.Key.Position.X": "X 坐标",
|
"Common.Attr.Key.Position.X": "X 坐标",
|
||||||
"Common.Attr.Key.Position.Y": "Y 坐标",
|
"Common.Attr.Key.Position.Y": "Y 坐标",
|
||||||
@ -106,6 +107,13 @@ const ZH_CN = {
|
|||||||
"Common.Attr.Key.Generation.Error.Invalid.Label": "指定的标签已失效",
|
"Common.Attr.Key.Generation.Error.Invalid.Label": "指定的标签已失效",
|
||||||
"Common.Attr.Key.Kill.Random": "随机消除",
|
"Common.Attr.Key.Kill.Random": "随机消除",
|
||||||
"Common.Attr.Key.Kill.Count": "消除数量",
|
"Common.Attr.Key.Kill.Count": "消除数量",
|
||||||
|
"Common.Render.Attr.Key.Display.Shape": "显示形状",
|
||||||
|
"Common.Render.Attr.Key.Display.Shape.Square": "方形",
|
||||||
|
"Common.Render.Attr.Key.Display.Shape.Hollow.Square": "空心方形",
|
||||||
|
"Common.Render.Attr.Key.Display.Shape.Hollow.Plus": "加号",
|
||||||
|
"Common.Render.Attr.Key.Display.Shape.Hollow.Reduce": "减号",
|
||||||
|
"Common.Render.Attr.Key.Display.Shape.Hollow.Cross": "叉号",
|
||||||
|
"Common.Render.Attr.Key.Display.Shape.Hollow.Checkerboard": "棋盘",
|
||||||
"Panel.Info.Range.Details.Attr.Error.Not.Range": "对象不是一个范围",
|
"Panel.Info.Range.Details.Attr.Error.Not.Range": "对象不是一个范围",
|
||||||
"Panel.Info.Range.Details.Attr.Error.Unspecified": "未指定范围对象",
|
"Panel.Info.Range.Details.Attr.Error.Unspecified": "未指定范围对象",
|
||||||
"Panel.Info.Group.Details.Attr.Error.Not.Group": "对象不是一个群",
|
"Panel.Info.Group.Details.Attr.Error.Not.Group": "对象不是一个群",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { LabelObject } from "@Model/Label"
|
import { LabelObject } from "@Model/Label"
|
||||||
import type { Model } from "@Model/Model";
|
import type { IAnyObject, Model } from "@Model/Model";
|
||||||
import type { ObjectID } from "@Model/Renderer";
|
import type { ObjectID } from "@Model/Model";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 可控对象
|
* 可控对象
|
||||||
@ -37,6 +37,11 @@ class CtrlObject extends LabelObject {
|
|||||||
*/
|
*/
|
||||||
protected model: Model;
|
protected model: Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 渲染数据
|
||||||
|
*/
|
||||||
|
public renderParameter: IAnyObject = {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构造器
|
* 构造器
|
||||||
*/
|
*/
|
||||||
|
@ -3,6 +3,8 @@ import { CtrlObject } from "@Model/CtrlObject";
|
|||||||
import type { Behavior } from "@Model/Behavior";
|
import type { Behavior } from "@Model/Behavior";
|
||||||
import { Label } from "@Model/Label";
|
import { Label } from "@Model/Label";
|
||||||
import { Range } from "@Model/Range";
|
import { Range } from "@Model/Range";
|
||||||
|
import { Model, ObjectID } from "@Model/Model";
|
||||||
|
import { getDefaultValue } from "@Model/Parameter";
|
||||||
|
|
||||||
enum GenMod {
|
enum GenMod {
|
||||||
Point = "p",
|
Point = "p",
|
||||||
@ -381,10 +383,14 @@ class Group extends CtrlObject {
|
|||||||
return dataBuffer;
|
return dataBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public constructor(model: Model, id: ObjectID) {
|
||||||
* 绘制大小
|
|
||||||
*/
|
super(model, id);
|
||||||
public size: number = 60;
|
|
||||||
|
if (model.renderer) {
|
||||||
|
this.renderParameter = getDefaultValue(model.renderer.pointsParameterOption);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Group;
|
export default Group;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import type { Group } from "@Model/Group";
|
import type { Group } from "@Model/Group";
|
||||||
import { ObjectID } from "@Model/Renderer";
|
import { ObjectID } from "@Model/Model";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 群中的个体类型
|
* 群中的个体类型
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import type { Model } from "@Model/Model";
|
import type { Model, ObjectID } from "@Model/Model";
|
||||||
import { ObjectID } from "@Model/Renderer";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 数据标签
|
* 数据标签
|
||||||
|
@ -5,9 +5,19 @@ import { IParamValue } from "@Model/Parameter";
|
|||||||
import { Individual } from "@Model/Individual";
|
import { Individual } from "@Model/Individual";
|
||||||
import { CtrlObject } from "@Model/CtrlObject";
|
import { CtrlObject } from "@Model/CtrlObject";
|
||||||
import { Emitter, EventType, EventMixin } from "@Model/Emitter";
|
import { Emitter, EventType, EventMixin } from "@Model/Emitter";
|
||||||
import { ObjectID, AbstractRenderer } from "@Model/Renderer";
|
import { AbstractRenderer } from "@Model/Renderer";
|
||||||
import { Behavior, IAnyBehavior, IAnyBehaviorRecorder } from "@Model/Behavior";
|
import { Behavior, IAnyBehavior, IAnyBehaviorRecorder } from "@Model/Behavior";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 对象标识符
|
||||||
|
*/
|
||||||
|
type ObjectID = string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 任意类型对象
|
||||||
|
*/
|
||||||
|
type IAnyObject = Record<string, any>;
|
||||||
|
|
||||||
type ModelEvent = {
|
type ModelEvent = {
|
||||||
labelChange: Label[];
|
labelChange: Label[];
|
||||||
objectChange: CtrlObject[];
|
objectChange: CtrlObject[];
|
||||||
@ -352,17 +362,12 @@ class Model extends Emitter<ModelEvent> {
|
|||||||
// 渲染
|
// 渲染
|
||||||
for (let i = 0; i < this.objectPool.length; i++) {
|
for (let i = 0; i < this.objectPool.length; i++) {
|
||||||
let object = this.objectPool[i];
|
let object = this.objectPool[i];
|
||||||
|
object.renderParameter.color = object.color;
|
||||||
if (object.display && object instanceof Group) {
|
if (object.display && object instanceof Group) {
|
||||||
this.renderer.points(object.id, object.exportPositionData(), {
|
this.renderer.points(object.id, object.exportPositionData(), object.renderParameter);
|
||||||
color: object.color,
|
|
||||||
size: object.size
|
|
||||||
} as any);
|
|
||||||
}
|
}
|
||||||
if (object.display && object instanceof Range) {
|
if (object.display && object instanceof Range) {
|
||||||
this.renderer.cube(object.id, object.position, {
|
this.renderer.cube(object.id, object.position, object.radius, object.renderParameter);
|
||||||
color: object.color,
|
|
||||||
radius: object.radius
|
|
||||||
} as any);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -376,5 +381,6 @@ export {
|
|||||||
EventMixin,
|
EventMixin,
|
||||||
Model,
|
Model,
|
||||||
CtrlObject,
|
CtrlObject,
|
||||||
ObjectID
|
ObjectID,
|
||||||
|
IAnyObject
|
||||||
}
|
}
|
@ -1,4 +1,6 @@
|
|||||||
import { CtrlObject } from "@Model/CtrlObject";
|
import { CtrlObject } from "@Model/CtrlObject";
|
||||||
|
import { Model, ObjectID } from "@Model/Model";
|
||||||
|
import { getDefaultValue } from "@Model/Parameter";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 范围
|
* 范围
|
||||||
@ -15,6 +17,15 @@ class Range extends CtrlObject {
|
|||||||
*/
|
*/
|
||||||
public radius: number[] = [1, 1, 1];
|
public radius: number[] = [1, 1, 1];
|
||||||
|
|
||||||
|
public constructor(model: Model, id: ObjectID) {
|
||||||
|
|
||||||
|
super(model, id);
|
||||||
|
|
||||||
|
if (model.renderer) {
|
||||||
|
this.renderParameter = getDefaultValue(model.renderer.cubeParameterOption);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Range;
|
export default Range;
|
||||||
|
@ -1,24 +1,31 @@
|
|||||||
import { Emitter, EventType } from "@Model/Emitter";
|
import { Emitter, EventType } from "@Model/Emitter";
|
||||||
|
import { IAnyObject, ObjectID } from "@Model/Model";
|
||||||
|
import { IParameter, IParameterOption, IParameterValue } from "@Model/Parameter";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 任意类型对象
|
* 默认类型
|
||||||
*/
|
*/
|
||||||
type IAnyObject = Record<string, any>;
|
type IDefaultType<T, D> = T extends undefined ? D : T;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 渲染器参数
|
* 渲染器参数
|
||||||
*/
|
*/
|
||||||
interface IRendererParam {
|
interface IRendererParam {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 渲染器参数
|
||||||
|
*/
|
||||||
|
renderer?: IParameter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 绘制点需要的参数
|
* 绘制点需要的参数
|
||||||
*/
|
*/
|
||||||
points?: IAnyObject
|
points?: IParameter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 绘制立方体需要的参数
|
* 绘制立方体需要的参数
|
||||||
*/
|
*/
|
||||||
cube?: IAnyObject
|
cube?: IParameter;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -32,22 +39,15 @@ interface ICommonParam {
|
|||||||
color?: ObjectData;
|
color?: ObjectData;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 对象标识符
|
|
||||||
*/
|
|
||||||
type ObjectID = string;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 接收的数据类型
|
* 接收的数据类型
|
||||||
*/
|
*/
|
||||||
type ObjectData = Array<number> | Float32Array;
|
type ObjectData = Array<number> | Float32Array;
|
||||||
|
|
||||||
interface IRendererConstructor<
|
interface IRendererConstructor {
|
||||||
M extends IAnyObject = {}
|
new (): AbstractRenderer<IRendererParam, AbstractRendererEvent>
|
||||||
> {
|
|
||||||
new (canvas: HTMLCanvasElement, param?: M): AbstractRenderer<
|
|
||||||
IRendererParam, IAnyObject, AbstractRendererEvent
|
|
||||||
>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type AbstractRendererEvent = {
|
type AbstractRendererEvent = {
|
||||||
@ -63,7 +63,6 @@ type AbstractRendererEvent = {
|
|||||||
*/
|
*/
|
||||||
abstract class AbstractRenderer<
|
abstract class AbstractRenderer<
|
||||||
P extends IRendererParam = {},
|
P extends IRendererParam = {},
|
||||||
M extends IAnyObject = {},
|
|
||||||
E extends AbstractRendererEvent = {loop: number}
|
E extends AbstractRendererEvent = {loop: number}
|
||||||
> extends Emitter<E> {
|
> extends Emitter<E> {
|
||||||
|
|
||||||
@ -72,28 +71,17 @@ abstract class AbstractRenderer<
|
|||||||
/**
|
/**
|
||||||
* 渲染器参数
|
* 渲染器参数
|
||||||
*/
|
*/
|
||||||
abstract param: Partial<M>;
|
public rendererParameterOption: IParameterOption<IDefaultType<P["renderer"], {}>> = {} as any;
|
||||||
|
public pointsParameterOption: IParameterOption<IDefaultType<P["points"], {}>> = {} as any;
|
||||||
|
public cubeParameterOption: IParameterOption<IDefaultType<P["cube"], {}>> = {} as any;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 类型断言
|
* 渲染器参数
|
||||||
*/
|
*/
|
||||||
get isRenderer() {
|
public rendererParameter: IParameterValue<IDefaultType<P["renderer"], {}>> = {} as any;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 断言对象是否是渲染器
|
* @function clean
|
||||||
*/
|
|
||||||
public static isRenderer(render: any): render is AbstractRenderer {
|
|
||||||
if (render instanceof Object) {
|
|
||||||
return !!(render as AbstractRenderer).isRenderer;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @function start
|
|
||||||
* 开始一次数据更新 \
|
* 开始一次数据更新 \
|
||||||
* 此函数将清除固定对象的绘制状态 \
|
* 此函数将清除固定对象的绘制状态 \
|
||||||
* 在每次数据更新前调用 \
|
* 在每次数据更新前调用 \
|
||||||
@ -110,7 +98,9 @@ abstract class AbstractRenderer<
|
|||||||
* @param id 使用的标识符
|
* @param id 使用的标识符
|
||||||
* @param position 做标集合
|
* @param position 做标集合
|
||||||
*/
|
*/
|
||||||
abstract points(id: ObjectID, position?: ObjectData, param?: Readonly<P["points"] & ICommonParam>): this;
|
abstract points(id: ObjectID, position?: ObjectData, param?:
|
||||||
|
Readonly<IParameterValue<IDefaultType<P["points"], {}>>>
|
||||||
|
): this;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @function cube 绘制立方体
|
* @function cube 绘制立方体
|
||||||
@ -120,12 +110,13 @@ abstract class AbstractRenderer<
|
|||||||
*
|
*
|
||||||
* 注意: 这里的半径指的是立方体重心与立方体任意一面几何中心的距离
|
* 注意: 这里的半径指的是立方体重心与立方体任意一面几何中心的距离
|
||||||
*/
|
*/
|
||||||
abstract cube(id: ObjectID, position?: ObjectData, param?: Readonly<P["cube"] & ICommonParam>): this;
|
abstract cube(id: ObjectID, position?: ObjectData, radius?: ObjectData, param?:
|
||||||
|
Readonly<IParameterValue<IDefaultType<P["cube"], {}>>>
|
||||||
|
): this;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default AbstractRenderer;
|
export default AbstractRenderer;
|
||||||
export {
|
export {
|
||||||
AbstractRenderer, ObjectID, IAnyObject,
|
AbstractRenderer, ICommonParam, IRendererParam,
|
||||||
ICommonParam, IRendererParam,
|
|
||||||
ObjectData, IRendererConstructor
|
ObjectData, IRendererConstructor
|
||||||
};
|
};
|
@ -21,7 +21,7 @@ class Laboratory extends Component {
|
|||||||
throw new Error("Laboratory: 重复引用 canvas 节点");
|
throw new Error("Laboratory: 重复引用 canvas 节点");
|
||||||
}
|
}
|
||||||
|
|
||||||
const renderer = new ClassicRenderer({ className: "canvas" }).onLoad();
|
const renderer = new ClassicRenderer().onLoad();
|
||||||
this.canvasContRef.current.appendChild(renderer.canvas.dom);
|
this.canvasContRef.current.appendChild(renderer.canvas.dom);
|
||||||
|
|
||||||
let model = new Model().bindRenderer(renderer);
|
let model = new Model().bindRenderer(renderer);
|
||||||
@ -39,22 +39,24 @@ class Laboratory extends Component {
|
|||||||
|
|
||||||
// 测试渲染器
|
// 测试渲染器
|
||||||
if (false) {
|
if (false) {
|
||||||
renderer.points("0");
|
// renderer.points("0");
|
||||||
renderer.points("1", new Array(100 * 3).fill(0).map(() => (Math.random() - .5) * 2));
|
// renderer.points("1", new Array(100 * 3).fill(0).map(() => (Math.random() - .5) * 2));
|
||||||
renderer.points("2", new Array(100 * 3).fill(0).map(() => (Math.random() - .5) * 2), {
|
// renderer.points("2", new Array(100 * 3).fill(0).map(() => (Math.random() - .5) * 2), {
|
||||||
size: 100,
|
// size: 100,
|
||||||
color: [1, 0, 1]
|
// color: [1, 0, 1]
|
||||||
});
|
// });
|
||||||
renderer.points("3", new Array(100 * 3).fill(0).map(() => (Math.random() - .5) * 2), {
|
// renderer.points("3", new Array(100 * 3).fill(0).map(() => (Math.random() - .5) * 2), {
|
||||||
size: 80,
|
// size: 80,
|
||||||
color: [0, 1, 1]
|
// color: [0, 1, 1]
|
||||||
});
|
// });
|
||||||
renderer.points("2");
|
// renderer.points("2");
|
||||||
renderer.cube("4");
|
// renderer.cube("4");
|
||||||
renderer.cube("5", new Array(3).fill(0).map(() => (Math.random() - .5) * 2), {
|
// renderer.cube("5",
|
||||||
radius: new Array(3).fill(0).map(() => Math.random() * 1.2),
|
// new Array(3).fill(0).map(() => (Math.random() - .5) * 2),
|
||||||
color: [1, 1, 0]
|
// new Array(3).fill(0).map(() => Math.random() * 1.2), {
|
||||||
})
|
// color: [1, 1, 0]
|
||||||
|
// }
|
||||||
|
// )
|
||||||
}
|
}
|
||||||
|
|
||||||
(window as any).renderer = renderer;
|
(window as any).renderer = renderer;
|
||||||
|
@ -35,9 +35,9 @@ class SimulatorWeb extends Component {
|
|||||||
(window as any).setting = (this.setting as any);
|
(window as any).setting = (this.setting as any);
|
||||||
|
|
||||||
// TODO: 这里要读取存档
|
// TODO: 这里要读取存档
|
||||||
|
const classicRender = new ClassicRenderer().onLoad();
|
||||||
this.status = new Status();
|
this.status = new Status();
|
||||||
this.status.renderer = new ClassicRenderer({ className: "canvas" }).onLoad();
|
this.status.bindRenderer(classicRender);
|
||||||
this.status.bindRenderer(this.status.renderer);
|
|
||||||
this.status.setting = this.setting;
|
this.status.setting = this.setting;
|
||||||
|
|
||||||
// 测试代码
|
// 测试代码
|
||||||
|
@ -4,7 +4,7 @@ import { useStatusWithEvent, IMixinStatusProps } from "@Context/Status";
|
|||||||
import { useSetting, IMixinSettingProps } from "@Context/Setting";
|
import { useSetting, IMixinSettingProps } from "@Context/Setting";
|
||||||
import { ComboInput, IDisplayItem } from "@Input/ComboInput/ComboInput";
|
import { ComboInput, IDisplayItem } from "@Input/ComboInput/ComboInput";
|
||||||
import { Message } from "@Input/Message/Message";
|
import { Message } from "@Input/Message/Message";
|
||||||
import { ObjectID } from "@Model/Renderer";
|
import { ObjectID } from "@Model/Model";
|
||||||
import { ColorInput } from "@Input/ColorInput/ColorInput";
|
import { ColorInput } from "@Input/ColorInput/ColorInput";
|
||||||
import { TogglesInput } from "@Input/TogglesInput/TogglesInput";
|
import { TogglesInput } from "@Input/TogglesInput/TogglesInput";
|
||||||
import { LabelPicker } from "@Input/LabelPicker/LabelPicker";
|
import { LabelPicker } from "@Input/LabelPicker/LabelPicker";
|
||||||
@ -13,6 +13,7 @@ import { AllI18nKeys } from "@Component/Localization/Localization";
|
|||||||
import { ObjectPicker } from "@Input/ObjectPicker/ObjectPicker";
|
import { ObjectPicker } from "@Input/ObjectPicker/ObjectPicker";
|
||||||
import { ConfirmPopup } from "@Component/ConfirmPopup/ConfirmPopup";
|
import { ConfirmPopup } from "@Component/ConfirmPopup/ConfirmPopup";
|
||||||
import { BehaviorPicker } from "@Input/BehaviorPicker/BehaviorPicker";
|
import { BehaviorPicker } from "@Input/BehaviorPicker/BehaviorPicker";
|
||||||
|
import { Parameter } from "@Input/Parameter/Parameter";
|
||||||
import "./GroupDetails.scss";
|
import "./GroupDetails.scss";
|
||||||
|
|
||||||
interface IGroupDetailsProps {}
|
interface IGroupDetailsProps {}
|
||||||
@ -54,14 +55,6 @@ class GroupDetails extends Component<IGroupDetailsProps & IMixinStatusProps & IM
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<AttrInput
|
|
||||||
id={group.id} isNumber={true} step={10} keyI18n="Common.Attr.Key.Size"
|
|
||||||
value={group.size} min={0}
|
|
||||||
valueChange={(val) => {
|
|
||||||
this.props.status?.changeGroupAttrib(group.id, "size", (val as any) / 1);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<LabelPicker
|
<LabelPicker
|
||||||
keyI18n="Common.Attr.Key.Label"
|
keyI18n="Common.Attr.Key.Label"
|
||||||
labels={group.allLabels()}
|
labels={group.allLabels()}
|
||||||
@ -115,6 +108,23 @@ class GroupDetails extends Component<IGroupDetailsProps & IMixinStatusProps & IM
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<Parameter
|
||||||
|
key={group.id}
|
||||||
|
option={this.props.status?.renderer.pointsParameterOption ?? {}}
|
||||||
|
title={"Common.Attr.Title.Render.Parameter"}
|
||||||
|
value={group.renderParameter}
|
||||||
|
renderKey={
|
||||||
|
Object.getOwnPropertyNames(this.props.status?.renderer.pointsParameterOption ?? {})
|
||||||
|
.filter((key) => key !== "color")
|
||||||
|
}
|
||||||
|
change={(key, value) => {
|
||||||
|
group.renderParameter[key as any] = value;
|
||||||
|
this.props.status?.changeGroupAttrib(
|
||||||
|
group.id, "renderParameter", group.renderParameter
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
<Message i18nKey="Common.Attr.Title.Behaviors" isTitle/>
|
<Message i18nKey="Common.Attr.Title.Behaviors" isTitle/>
|
||||||
|
|
||||||
<BehaviorPicker
|
<BehaviorPicker
|
||||||
|
@ -2,7 +2,7 @@ import { Component, ReactNode } from "react";
|
|||||||
import { BackgroundLevel, FontLevel, Theme } from "@Component/Theme/Theme";
|
import { BackgroundLevel, FontLevel, Theme } from "@Component/Theme/Theme";
|
||||||
import { useStatus, IMixinStatusProps } from "@Context/Status";
|
import { useStatus, IMixinStatusProps } from "@Context/Status";
|
||||||
import { ConfirmPopup } from "@Component/ConfirmPopup/ConfirmPopup";
|
import { ConfirmPopup } from "@Component/ConfirmPopup/ConfirmPopup";
|
||||||
import { ObjectID } from "@Model/Renderer";
|
import { ObjectID } from "@Model/Model";
|
||||||
import { Icon } from "@fluentui/react";
|
import { Icon } from "@fluentui/react";
|
||||||
import "./ObjectList.scss";
|
import "./ObjectList.scss";
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ import { useStatusWithEvent, IMixinStatusProps } from "@Context/Status";
|
|||||||
import { useSetting, IMixinSettingProps } from "@Context/Setting";
|
import { useSetting, IMixinSettingProps } from "@Context/Setting";
|
||||||
import { Localization } from "@Component/Localization/Localization";
|
import { Localization } from "@Component/Localization/Localization";
|
||||||
import { DetailsList } from "@Component/DetailsList/DetailsList";
|
import { DetailsList } from "@Component/DetailsList/DetailsList";
|
||||||
import { ObjectID } from "@Model/Renderer";
|
import { ObjectID } from "@Model/Model";
|
||||||
import { Icon } from "@fluentui/react";
|
import { Icon } from "@fluentui/react";
|
||||||
import "./ObjectList.scss";
|
import "./ObjectList.scss";
|
||||||
|
|
||||||
|
@ -3,11 +3,12 @@ import { useStatusWithEvent, IMixinStatusProps } from "@Context/Status";
|
|||||||
import { AttrInput } from "@Input/AttrInput/AttrInput";
|
import { AttrInput } from "@Input/AttrInput/AttrInput";
|
||||||
import { Message } from "@Input/Message/Message";
|
import { Message } from "@Input/Message/Message";
|
||||||
import { Range } from "@Model/Range";
|
import { Range } from "@Model/Range";
|
||||||
import { ObjectID } from "@Model/Renderer";
|
import { ObjectID } from "@Model/Model";
|
||||||
import { ColorInput } from "@Input/ColorInput/ColorInput";
|
import { ColorInput } from "@Input/ColorInput/ColorInput";
|
||||||
import { TogglesInput } from "@Input/TogglesInput/TogglesInput";
|
import { TogglesInput } from "@Input/TogglesInput/TogglesInput";
|
||||||
import { LabelPicker } from "@Input/LabelPicker/LabelPicker";
|
import { LabelPicker } from "@Input/LabelPicker/LabelPicker";
|
||||||
import { ConfirmPopup } from "@Component/ConfirmPopup/ConfirmPopup";
|
import { ConfirmPopup } from "@Component/ConfirmPopup/ConfirmPopup";
|
||||||
|
import { Parameter } from "@Input/Parameter/Parameter";
|
||||||
import "./RangeDetails.scss";
|
import "./RangeDetails.scss";
|
||||||
|
|
||||||
@useStatusWithEvent("rangeAttrChange", "focusObjectChange", "rangeLabelChange")
|
@useStatusWithEvent("rangeAttrChange", "focusObjectChange", "rangeLabelChange")
|
||||||
@ -72,6 +73,23 @@ class RangeDetails extends Component<IMixinStatusProps> {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<Parameter
|
||||||
|
key={range.id}
|
||||||
|
option={this.props.status?.renderer.cubeParameterOption ?? {}}
|
||||||
|
title={"Common.Attr.Title.Render.Parameter"}
|
||||||
|
value={range.renderParameter}
|
||||||
|
renderKey={
|
||||||
|
Object.getOwnPropertyNames(this.props.status?.renderer.cubeParameterOption ?? {})
|
||||||
|
.filter((key) => key !== "color")
|
||||||
|
}
|
||||||
|
change={(key, value) => {
|
||||||
|
range.renderParameter[key as any] = value;
|
||||||
|
this.props.status?.changeRangeAttrib(
|
||||||
|
range.id, "renderParameter", range.renderParameter
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
<Message i18nKey="Common.Attr.Title.Spatial" isTitle/>
|
<Message i18nKey="Common.Attr.Title.Spatial" isTitle/>
|
||||||
|
|
||||||
<AttrInput
|
<AttrInput
|
||||||
|
Loading…
Reference in New Issue
Block a user